public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
@ 2003-03-12  0:25 Thayne Harbaugh
  2003-03-12 15:44 ` John Burch
  2003-03-12 16:27 ` Steve Wahl
  0 siblings, 2 replies; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-12  0:25 UTC (permalink / raw)
  To: linux-mtd

--=-bK4IZ7vhYqXn1yFR9yRW
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

For some reason I am confused: I get the feeling that what I'm trying to
understand is obvious - I just can't see the forest for the trees.  Will
someone help me understand?

cfi_cmdset_0002.c has several functions that use dq5 and dq6 for
monitoring the status of erase and write operations:

dq6 =3D CMD(1<<6);
dq5 =3D CMD(1<<5);

Apparently, from the code dq6 toggles during erase/read operations and
dq5 is low until the erase/read operation times out and then goes high
(somewhat like a watchdog bit).

My understanding,@least for the SST 49LF040 and PMC Pm49L004 is that
dq6 toggles during erase/write and dq7 is inverted until the erase/write
operation completes.  This causes me to expect to see the following code
rather than what is written above (not to mention that most everything
in do_write_one_word() should be adapted for dq7 invert):

dq7 =3D CMD(1<<7); /* invert */
dq6 =3D CMD(1<<6); /* toggle */

The differences give me the feeling that there really are two different
classes of cfi_cmdset_0002 - those devices that have a dq5 watchdog and
those devices that don't have the watchdog, but have a bit inverter on
dq7.

Am I not understanding what happens on bits 0-5 during an erase/write
operation?  The PMC and SST chips don't mention a thing about dq5
behavior.  If they don't have the dq5 watchdog timer then they will
behave in an undefined way (depending on the state of bit 5 in the
written word) with the current dq5 checking.  This explains the many
warnings I see with the SST and PMC chips in do_write_oneword(),

"Warning: DQ5 raised while program operation was in progress, however
operation completed OK"

Around here we refer to this as the "Dairy Queen 5" warning.

Obviosly, during an erase that completes prior to dq5 being read-back,
dq5 will be high and the current algorithm is erroneously correct.  This
can explain why I have not seen the same message in do_erase_oneblock().

Furthermore, the SST documentation on page 10 refers to "spurios
rejection" of good writes - differentiating between a write that
succeeds that appears to fail and a write that fails.  It says that a
write that appears to fail needs to be read back two more times
successfully to filter out spurious rejection.

Comments?  What should change to improve the operation completion
check?  Should cfi_cmdset_0002 be adapted to handle multiple types of
polling or should another command set be written?

--=20
Thayne Harbaugh
Linux Networx

--=-bK4IZ7vhYqXn1yFR9yRW
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+bn5rfsBPTKE6HMkRAs4BAJ9X+2ohh6yJj0pl/bhoePQkSDI+CQCfacc7
o6FfFw5wUv1dT06gFCcaGnY=
=+ZHx
-----END PGP SIGNATURE-----

--=-bK4IZ7vhYqXn1yFR9yRW--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12  0:25 DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning) Thayne Harbaugh
@ 2003-03-12 15:44 ` John Burch
  2003-03-12 16:35   ` Thayne Harbaugh
  2003-03-12 16:27 ` Steve Wahl
  1 sibling, 1 reply; 20+ messages in thread
From: John Burch @ 2003-03-12 15:44 UTC (permalink / raw)
  To: linux-mtd


> -----Original Message-----
> From: linux-mtd-admin at lists.infradead.org=20
> [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of=20
> Thayne Harbaugh
> Sent: Tuesday, March 11, 2003 7:25 PM
> To: linux-mtd at lists.infradead.org
> Subject: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
>=20
>=20
> For some reason I am confused: I get the feeling that what=20
> I'm trying to understand is obvious - I just can't see the=20
> forest for the trees.  Will someone help me understand?
>=20
> cfi_cmdset_0002.c has several functions that use dq5 and dq6=20
> for monitoring the status of erase and write operations:
>=20
> dq6 =3D CMD(1<<6);
> dq5 =3D CMD(1<<5);
>=20
> Apparently, from the code dq6 toggles during erase/read=20
> operations and dq5 is low until the erase/read operation=20
> times out and then goes high (somewhat like a watchdog bit).
>=20
> My understanding, at least for the SST 49LF040 and PMC=20
> Pm49L004 is that dq6 toggles during erase/write and dq7 is=20
> inverted until the erase/write operation completes.  This=20
> causes me to expect to see the following code rather than=20
> what is written above (not to mention that most everything in=20
> do_write_one_word() should be adapted for dq7 invert):
>=20
> dq7 =3D CMD(1<<7); /* invert */
> dq6 =3D CMD(1<<6); /* toggle */
>=20
> The differences give me the feeling that there really are two=20
> different classes of cfi_cmdset_0002 - those devices that=20
> have a dq5 watchdog and those devices that don't have the=20
> watchdog, but have a bit inverter on dq7.
>=20
> Am I not understanding what happens on bits 0-5 during an=20
> erase/write operation?  The PMC and SST chips don't mention a=20
> thing about dq5 behavior.  If they don't have the dq5=20
> watchdog timer then they will behave in an undefined way=20
> (depending on the state of bit 5 in the written word) with=20
> the current dq5 checking.  This explains the many warnings I=20
> see with the SST and PMC chips in do_write_oneword(),
>=20
> "Warning: DQ5 raised while program operation was in progress,=20
> however operation completed OK"
>=20
> Around here we refer to this as the "Dairy Queen 5" warning.
>=20
> Obviosly, during an erase that completes prior to dq5 being=20
> read-back, dq5 will be high and the current algorithm is=20
> erroneously correct.  This can explain why I have not seen=20
> the same message in do_erase_oneblock().
>=20
> Furthermore, the SST documentation on page 10 refers to=20
> "spurios rejection" of good writes - differentiating between=20
> a write that succeeds that appears to fail and a write that=20
> fails.  It says that a write that appears to fail needs to be=20
> read back two more times successfully to filter out spurious=20
> rejection.
>=20
> Comments?  What should change to improve the operation=20
> completion check?  Should cfi_cmdset_0002 be adapted to=20
> handle multiple types of polling or should another command=20
> set be written?

The attached app note from AMD explains things in detail relative
to AMD devices.  I'm not sure how it applies to PMC and SST
devices or not.  It seems as though DQ7 polling or DQ6 polling,
by themselves, give a simple pass/fail/busy result; while DQ7 or DQ6
polling in combination with DQ5 and DQ2 polling give pass/fail/
erase suspended/timeout/busy result.

John

>=20
> --=20
> Thayne Harbaugh
> Linux Networx
>=20

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12  0:25 DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning) Thayne Harbaugh
  2003-03-12 15:44 ` John Burch
@ 2003-03-12 16:27 ` Steve Wahl
  2003-03-12 17:12   ` John Burch
  2003-03-17 15:40   ` Thayne Harbaugh
  1 sibling, 2 replies; 20+ messages in thread
From: Steve Wahl @ 2003-03-12 16:27 UTC (permalink / raw)
  To: linux-mtd

Thayne, 

I have a patch that I was given permission to check in, but never got
around to it, that covers a similar "DQ5 raised" problem.

I would wager you are running into the same problem I did, and that
your chips compatibly support DQ5, if not as a watchdog, at least by
holding it low while programming.

Can you look at my previous posts on this, try my patch (if you don't
have interleaved chips -- contact me if you do), and see if it works
for you?

http://lists.infradead.org/pipermail/linux-mtd/2003-January/006780.html

--> Steve


On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> For some reason I am confused: I get the feeling that what I'm trying to
> understand is obvious - I just can't see the forest for the trees.  Will
> someone help me understand?
> 
> cfi_cmdset_0002.c has several functions that use dq5 and dq6 for
> monitoring the status of erase and write operations:
> 
> dq6 = CMD(1<<6);
> dq5 = CMD(1<<5);
> 
> Apparently, from the code dq6 toggles during erase/read operations and
> dq5 is low until the erase/read operation times out and then goes high
> (somewhat like a watchdog bit).
> 
> My understanding, at least for the SST 49LF040 and PMC Pm49L004 is that
> dq6 toggles during erase/write and dq7 is inverted until the erase/write
> operation completes.  This causes me to expect to see the following code
> rather than what is written above (not to mention that most everything
> in do_write_one_word() should be adapted for dq7 invert):
> 
> dq7 = CMD(1<<7); /* invert */
> dq6 = CMD(1<<6); /* toggle */
> 
> The differences give me the feeling that there really are two different
> classes of cfi_cmdset_0002 - those devices that have a dq5 watchdog and
> those devices that don't have the watchdog, but have a bit inverter on
> dq7.
> 
> Am I not understanding what happens on bits 0-5 during an erase/write
> operation?  The PMC and SST chips don't mention a thing about dq5
> behavior.  If they don't have the dq5 watchdog timer then they will
> behave in an undefined way (depending on the state of bit 5 in the
> written word) with the current dq5 checking.  This explains the many
> warnings I see with the SST and PMC chips in do_write_oneword(),
> 
> "Warning: DQ5 raised while program operation was in progress, however
> operation completed OK"
> 
> Around here we refer to this as the "Dairy Queen 5" warning.
> 
> Obviosly, during an erase that completes prior to dq5 being read-back,
> dq5 will be high and the current algorithm is erroneously correct.  This
> can explain why I have not seen the same message in do_erase_oneblock().
> 
> Furthermore, the SST documentation on page 10 refers to "spurios
> rejection" of good writes - differentiating between a write that
> succeeds that appears to fail and a write that fails.  It says that a
> write that appears to fail needs to be read back two more times
> successfully to filter out spurious rejection.
> 
> Comments?  What should change to improve the operation completion
> check?  Should cfi_cmdset_0002 be adapted to handle multiple types of
> polling or should another command set be written?
> 
> -- 
> Thayne Harbaugh
> Linux Networx

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 15:44 ` John Burch
@ 2003-03-12 16:35   ` Thayne Harbaugh
  0 siblings, 0 replies; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-12 16:35 UTC (permalink / raw)
  To: linux-mtd

--=-SCiByEcspzKD8yaWvDLo
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Wed, 2003-03-12 at 08:44, John Burch wrote:
> > -----Original Message-----
> > From: linux-mtd-admin at lists.infradead.org=20
> > [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of=20
> > Thayne Harbaugh
> > Sent: Tuesday, March 11, 2003 7:25 PM
> > To: linux-mtd at lists.infradead.org
> > Subject: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
> >=20
> >=20

<snip>

>=20
> The attached app note

Attachment?

> from AMD explains things in detail relative
> to AMD devices.

<snip>

>=20
> John
>=20
> >=20
> > --=20
> > Thayne Harbaugh
> > Linux Networx
> >=20
>=20
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--=20
Thayne Harbaugh
Linux Networx

--=-SCiByEcspzKD8yaWvDLo
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+b2HWfsBPTKE6HMkRAhHHAJ9pblnTYxLLUr10W6LJtazo28wKmgCfRHFy
sqjeNuPDPxFm0yhfrss2E8o=
=aEVN
-----END PGP SIGNATURE-----

--=-SCiByEcspzKD8yaWvDLo--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 16:27 ` Steve Wahl
@ 2003-03-12 17:12   ` John Burch
  2003-03-12 21:43     ` Steve Wahl
  2003-03-17 15:40   ` Thayne Harbaugh
  1 sibling, 1 reply; 20+ messages in thread
From: John Burch @ 2003-03-12 17:12 UTC (permalink / raw)
  To: linux-mtd

This is a multi-part message in MIME format.

------=_NextPart_000_0028_01C2E890.9DBAE0C0
Content-Type: text/plain;
	charset="US-ASCII"
Content-Transfer-Encoding: quoted-printable

AMD's own method from code they provide is shown below...

By the way, AMD specifically mentions having to check DQ6/7 again
after DQ5=3D1 because of the possibility that DQ5=3D1 simultaneous with
toggling stopping.  The app note I referred to before (attached this
time)
describes this in some detail.  The status register (including DQ5)
won't reflect actual data until a reset command is issued, so I think
the concern about DQ5=3D1 because erased data (0xff) is read instead
of status is not valid.

John

>From AMD's cfiflash.c:

/*********************************************************************/
/* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms    */
/* described in the flash data book.  It can quickly ascertain the   */
/* operational status of the flash device, and return an             */
/* appropriate status code (defined in flash.h)                      */
/*********************************************************************/
=20
int flash_status(word far *fp)
{
	 unsigned char d, t;
	 int retry =3D 1;

again:

	 d =3D *fp;        /* read data */
	 t =3D d ^ *fp;    /* read it again and see what toggled */

	 if (t =3D=3D 0) {           /* no toggles, nothing's happening */
		return STATUS_READY;
	 }
	 else if (t =3D=3D 0x04) { /* erase-suspend */
		if (retry--) goto again;    /* may have been write
completion */
		return STATUS_ERSUSP;
	 }
	 else if (t & 0x40) {
		if (d & 0x20) {     /* timeout */
		  return STATUS_TIMEOUT;
		}
		else {
		  return STATUS_BUSY;
		}
	 }

	 if (retry--) goto again;    /* may have been write completion
*/

	 return STATUS_ERROR;
}



> -----Original Message-----
> From: linux-mtd-admin at lists.infradead.org=20
> [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of Steve Wahl
> Sent: Wednesday, March 12, 2003 11:28 AM
> To: Thayne Harbaugh
> Cc: linux-mtd at lists.infradead.org
> Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy=20
> Queen 5 warning)
>=20
>=20
> Thayne,=20
>=20
> I have a patch that I was given permission to check in, but=20
> never got around to it, that covers a similar "DQ5 raised" problem.
>=20
> I would wager you are running into the same problem I did,=20
> and that your chips compatibly support DQ5, if not as a=20
> watchdog, at least by holding it low while programming.
>=20
> Can you look at my previous posts on this, try my patch (if=20
> you don't have interleaved chips -- contact me if you do),=20
> and see if it works for you?
>=20
> http://lists.infradead.org/pipermail/linux-mtd/2003-January/00
> 6780.html
>=20
> --> Steve
>=20
>=20
> On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> > For some reason I am confused: I get the feeling that what=20
> I'm trying=20
> > to understand is obvious - I just can't see the forest for=20
> the trees. =20
> > Will someone help me understand?
> >=20
> > cfi_cmdset_0002.c has several functions that use dq5 and dq6 for=20
> > monitoring the status of erase and write operations:
> >=20
> > dq6 =3D CMD(1<<6);
> > dq5 =3D CMD(1<<5);
> >=20
> > Apparently, from the code dq6 toggles during erase/read=20
> operations and=20
> > dq5 is low until the erase/read operation times out and=20
> then goes high=20
> > (somewhat like a watchdog bit).
> >=20
> > My understanding, at least for the SST 49LF040 and PMC Pm49L004 is=20
> > that dq6 toggles during erase/write and dq7 is inverted until the=20
> > erase/write operation completes.  This causes me to expect=20
> to see the=20
> > following code rather than what is written above (not to=20
> mention that=20
> > most everything in do_write_one_word() should be adapted for dq7=20
> > invert):
> >=20
> > dq7 =3D CMD(1<<7); /* invert */
> > dq6 =3D CMD(1<<6); /* toggle */
> >=20
> > The differences give me the feeling that there really are two=20
> > different classes of cfi_cmdset_0002 - those devices that=20
> have a dq5=20
> > watchdog and those devices that don't have the watchdog, but have a=20
> > bit inverter on dq7.
> >=20
> > Am I not understanding what happens on bits 0-5 during an=20
> erase/write=20
> > operation?  The PMC and SST chips don't mention a thing about dq5=20
> > behavior.  If they don't have the dq5 watchdog timer then they will=20
> > behave in an undefined way (depending on the state of bit 5 in the=20
> > written word) with the current dq5 checking.  This explains=20
> the many=20
> > warnings I see with the SST and PMC chips in do_write_oneword(),
> >=20
> > "Warning: DQ5 raised while program operation was in=20
> progress, however=20
> > operation completed OK"
> >=20
> > Around here we refer to this as the "Dairy Queen 5" warning.
> >=20
> > Obviosly, during an erase that completes prior to dq5 being=20
> read-back,=20
> > dq5 will be high and the current algorithm is erroneously correct. =20
> > This can explain why I have not seen the same message in=20
> > do_erase_oneblock().
> >=20
> > Furthermore, the SST documentation on page 10 refers to "spurios=20
> > rejection" of good writes - differentiating between a write that=20
> > succeeds that appears to fail and a write that fails.  It=20
> says that a=20
> > write that appears to fail needs to be read back two more times=20
> > successfully to filter out spurious rejection.
> >=20
> > Comments?  What should change to improve the operation completion=20
> > check?  Should cfi_cmdset_0002 be adapted to handle=20
> multiple types of=20
> > polling or should another command set be written?
> >=20
> > --
> > Thayne Harbaugh
> > Linux Networx
>=20
>=20
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>=20

------=_NextPart_000_0028_01C2E890.9DBAE0C0
Content-Type: application/pdf;
	name="22152.pdf"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
	filename="22152.pdf"

JVBERi0xLjINJeLjz9MNCjQ0IDAgb2JqDTw8IA0vTGluZWFyaXplZCAxIA0vTyA0NiANL0ggWyA5
ODIgMzEwIF0gDS9MIDUyMTQ4IA0vRSAxMjk0NCANL04gMTAgDS9UIDUxMTUwIA0+PiANZW5kb2Jq
DSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg
ICB4cmVmDTQ0IDI5IA0wMDAwMDAwMDE2IDAwMDAwIG4NCjAwMDAwMDA5MjcgMDAwMDAgbg0KMDAw
MDAwMTI5MiAwMDAwMCBuDQowMDAwMDAxNDk5IDAwMDAwIG4NCjAwMDAwMDE2NDcgMDAwMDAgbg0K
MDAwMDAwMTczNCAwMDAwMCBuDQowMDAwMDAxODI2IDAwMDAwIG4NCjAwMDAwMDE4NDggMDAwMDAg
bg0KMDAwMDAwMzAzOCAwMDAwMCBuDQowMDAwMDAzMDYwIDAwMDAwIG4NCjAwMDAwMDQyNjUgMDAw
MDAgbg0KMDAwMDAwNDI4NyAwMDAwMCBuDQowMDAwMDA1NDI5IDAwMDAwIG4NCjAwMDAwMDU0NTEg
MDAwMDAgbg0KMDAwMDAwNjU1NyAwMDAwMCBuDQowMDAwMDA2NTc5IDAwMDAwIG4NCjAwMDAwMDc3
MzUgMDAwMDAgbg0KMDAwMDAwNzc1NyAwMDAwMCBuDQowMDAwMDA4OTMyIDAwMDAwIG4NCjAwMDAw
MTAxNTcgMDAwMDAgbg0KMDAwMDAxMDI2NyAwMDAwMCBuDQowMDAwMDEwMzcyIDAwMDAwIG4NCjAw
MDAwMTAzOTQgMDAwMDAgbg0KMDAwMDAxMTYxMiAwMDAwMCBuDQowMDAwMDExNjMzIDAwMDAwIG4N
CjAwMDAwMTI2MzggMDAwMDAgbg0KMDAwMDAxMjcxNSAwMDAwMCBuDQowMDAwMDAwOTgyIDAwMDAw
IG4NCjAwMDAwMDEyNzEgMDAwMDAgbg0KdHJhaWxlcg08PA0vU2l6ZSA3Mw0vSW5mbyA0MyAwIFIg
DS9Sb290IDQ1IDAgUiANL1ByZXYgNTExNDAgDS9JRFs8NDM3OGE5NjEyNjUxNGQ2Mjc0NGRhMGFh
ZTlkYjU4NzU+PDQzNzhhOTYxMjY1MTRkNjI3NDRkYTBhYWU5ZGI1ODc1Pl0NPj4Nc3RhcnR4cmVm
DTANJSVFT0YNICAgICANNDUgMCBvYmoNPDwgDS9UeXBlIC9DYXRhbG9nIA0vUGFnZXMgNDIgMCBS
IA0+PiANZW5kb2JqDTcxIDAgb2JqDTw8IC9TIDE2NSAvRmlsdGVyIC9GbGF0ZURlY29kZSAvTGVu
Z3RoIDcyIDAgUiA+PiANc3RyZWFtDQpIiWNgYGAGomsMrAwM7NYMfAwIwMfAAhRlYeDY4MLI4CDA
MO3Eoy37QwRUYmIEcxqymVQYGMra2pZOAyllklGt4ag597u7o/rsBztu67cfDJ3CD/zQdAayLJ1+
PPtkmL1jx9E99xkY0jIaWCMaGAQ7GhglGhiBlJBGA6OSS0eDcQejoFJHg2tEA6Y9QKDKwLCnB0hL
ArEcWESUgVvc8Y8iSwGzigPPAgbDFobDF5ilD/A0TWtM0WKQjGKQO2DBrhggf/WrG8Q/ALOLQEsN
ZW5kc3RyZWFtDWVuZG9iag03MiAwIG9iag0yMDQgDWVuZG9iag00NiAwIG9iag08PCANL1R5cGUg
L1BhZ2UgDS9QYXJlbnQgNDIgMCBSIA0vUmVzb3VyY2VzIDQ3IDAgUiANL0NvbnRlbnRzIFsgNTEg
MCBSIDUzIDAgUiA1NSAwIFIgNTcgMCBSIDU5IDAgUiA2MSAwIFIgNjYgMCBSIDY4IDAgUiBdIA0v
TWVkaWFCb3ggWyAwIDAgNjEyIDc5MiBdIA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3Rh
dGUgMCANPj4gDWVuZG9iag00NyAwIG9iag08PCANL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0gDS9G
b250IDw8IC9GMSA0OCAwIFIgL0YyIDQ5IDAgUiAvRjMgNjQgMCBSIC9GNCA2MyAwIFIgPj4gDS9F
eHRHU3RhdGUgPDwgL0dTMSA3MCAwIFIgL0dTMiA2OSAwIFIgPj4gDT4+IA1lbmRvYmoNNDggMCBv
YmoNPDwgDS9UeXBlIC9Gb250IA0vU3VidHlwZSAvVHlwZTEgDS9OYW1lIC9GMSANL0Jhc2VGb250
IC9IZWx2ZXRpY2EgDT4+IA1lbmRvYmoNNDkgMCBvYmoNPDwgDS9UeXBlIC9Gb250IA0vU3VidHlw
ZSAvVHlwZTEgDS9OYW1lIC9GMiANL0Jhc2VGb250IC9IZWx2ZXRpY2EtQm9sZCANPj4gDWVuZG9i
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
LO6QiIwGbpBAwC5OM67ssIjDnRS5gyDLDTnRIMcxKxIyjh0yq2xa5QXByGUZN6gwZoShaBoKGLSu
AvwiCi4oUBuFLjTgGySiIMNExvRlHrlRgR0gEAoBSGjnKfLw2DSsLjPLFiBxcFzfxmhrct3PqHQE
vsaSu+tCyeFAbB0hKOtY+zqjO8sdS+rCcOaFAhSnEkAyg9AUBjOLLrguVTzuhMZocGDfuCitZOzW
kBBQGtcOo5wiymPE2TXDbFw/HURPej8RVzLsOOyNrqQnEg3V+6oQCZEl6wleacx/cVi2Ojqa2dOa
51RPNrz5PNsUHbqjhoFLszhA4pMW7I5uS1qlowGijqjb2NxDhNS2i2k8AVVSDLvVqChlQNshRWQY
qPbrjBnXD9hi52PBRdGEBaj6vhlRimJSEFyZxkEdTCrb30ZYjiOUlL6acNupqXYljLlNKRyRlFoY
XajcIMG2Hz9PVYW0jDjW67IZXC5TnOIGMj1451fYI67jMWo8ELkj76ONALshA2uCC5Eujuc/0tce
58scpDD3uclatTvJmCLDwVJ85v7tBa4zETOjFGcNoXUzbLCUi4FOyVNlez7ZhzebZiNY4nZmLBRj
CS413+OpGjUI5EFGSMV36rVJstT9tbXehh3/ghB4eOY94+Q5Gk/mOz505AUIoqIEOKBNY1yEBoGj
XT2GQZhkFwcBAG1ThpIAyoEK4VBAG59JrVpAgU2DMgraiCA0fqqoHLaiVkCM+AoKL54AvrgIDWAw
MG1PxfnAts0DwFBXf/BU18F35mbgUaEGJtSCQNf1BAgUEwFPoAU+qErSIDG0cU/J+j9n8QvhC/6A
ENYBQ6aQDhOr9YEwLhbA5/YCoIwyhpDYhER4kw7g67SIEIohxUcUDaJDDoUl0hYnWJ0MIJECCE+Y
BRqTSGmjhG41cAoqg1VcbZtBuk+EBA1lbmRzdHJlYW0NZW5kb2JqDTYyIDAgb2JqDTw8IA0vVHlw
ZSAvRW5jb2RpbmcgDS9EaWZmZXJlbmNlcyBbIDM5IC9xdW90ZXNpbmdsZSA5NiAvZ3JhdmUgMTMw
IC9xdW90ZXNpbmdsYmFzZSAvZmxvcmluIC9xdW90ZWRibGJhc2UgDS9lbGxpcHNpcyAvZGFnZ2Vy
IC9kYWdnZXJkYmwgL2NpcmN1bWZsZXggL3BlcnRob3VzYW5kIC9TY2Fyb24gL2d1aWxzaW5nbGxl
ZnQgDS9PRSAxNDUgL3F1b3RlbGVmdCAvcXVvdGVyaWdodCAvcXVvdGVkYmxsZWZ0IC9xdW90ZWRi
bHJpZ2h0IC9idWxsZXQgDS9lbmRhc2ggL2VtZGFzaCAvdGlsZGUgL3RyYWRlbWFyayAvc2Nhcm9u
IC9ndWlsc2luZ2xyaWdodCAvb2UgL2RvdGxlc3NpIA0xNTkgL1lkaWVyZXNpcyAxNjQgL2N1cnJl
bmN5IDE2NiAvYnJva2VuYmFyIDE2OCAvZGllcmVzaXMgL2NvcHlyaWdodCANL29yZGZlbWluaW5l
IDE3MiAvbG9naWNhbG5vdCAxNzQgL3JlZ2lzdGVyZWQgL21hY3JvbiAvcmluZyAvcGx1c21pbnVz
IA0vdHdvc3VwZXJpb3IgL3RocmVlc3VwZXJpb3IgL2FjdXRlIC9tdSAxODMgL3BlcmlvZGNlbnRl
cmVkIC9jZWRpbGxhIA0vb25lc3VwZXJpb3IgL29yZG1hc2N1bGluZSAxODggL29uZXF1YXJ0ZXIg
L29uZWhhbGYgL3RocmVlcXVhcnRlcnMgDTE5MiAvQWdyYXZlIC9BYWN1dGUgL0FjaXJjdW1mbGV4
IC9BdGlsZGUgL0FkaWVyZXNpcyAvQXJpbmcgL0FFIC9DY2VkaWxsYSANL0VncmF2ZSAvRWFjdXRl
IC9FY2lyY3VtZmxleCAvRWRpZXJlc2lzIC9JZ3JhdmUgL0lhY3V0ZSAvSWNpcmN1bWZsZXggDS9J
ZGllcmVzaXMgL0V0aCAvTnRpbGRlIC9PZ3JhdmUgL09hY3V0ZSAvT2NpcmN1bWZsZXggL090aWxk
ZSAvT2RpZXJlc2lzIA0vbXVsdGlwbHkgL09zbGFzaCAvVWdyYXZlIC9VYWN1dGUgL1VjaXJjdW1m
bGV4IC9VZGllcmVzaXMgL1lhY3V0ZSANL1Rob3JuIC9nZXJtYW5kYmxzIC9hZ3JhdmUgL2FhY3V0
ZSAvYWNpcmN1bWZsZXggL2F0aWxkZSAvYWRpZXJlc2lzIA0vYXJpbmcgL2FlIC9jY2VkaWxsYSAv
ZWdyYXZlIC9lYWN1dGUgL2VjaXJjdW1mbGV4IC9lZGllcmVzaXMgL2lncmF2ZSANL2lhY3V0ZSAv
aWNpcmN1bWZsZXggL2lkaWVyZXNpcyAvZXRoIC9udGlsZGUgL29ncmF2ZSAvb2FjdXRlIC9vY2ly
Y3VtZmxleCANL290aWxkZSAvb2RpZXJlc2lzIC9kaXZpZGUgL29zbGFzaCAvdWdyYXZlIC91YWN1
dGUgL3VjaXJjdW1mbGV4IA0vdWRpZXJlc2lzIC95YWN1dGUgL3Rob3JuIC95ZGllcmVzaXMgXSAN
Pj4gDWVuZG9iag02MyAwIG9iag08PCANL1R5cGUgL0ZvbnQgDS9TdWJ0eXBlIC9UeXBlMSANL05h
bWUgL0Y0IA0vRW5jb2RpbmcgNjIgMCBSIA0vQmFzZUZvbnQgL0hlbHZldGljYS1Cb2xkIA0+PiAN
ZW5kb2JqDTY0IDAgb2JqDTw8IA0vVHlwZSAvRm9udCANL1N1YnR5cGUgL1R5cGUxIA0vTmFtZSAv
RjMgDS9FbmNvZGluZyA2MiAwIFIgDS9CYXNlRm9udCAvSGVsdmV0aWNhIA0+PiANZW5kb2JqDTY1
IDAgb2JqDTExNDIgDWVuZG9iag02NiAwIG9iag08PCAvRmlsdGVyIC9MWldEZWNvZGUgL0xlbmd0
aCA2NSAwIFIgPj4gDXN0cmVhbQ0KgANBQtGAuGA0HAgKh3gRbFBJNwpFoyGgoEBhMkSigoMhpiQ4
FB0jwtkBvjUViIxix0k0TiogOhok4oMogJ5wmZlORhmZ0jQokclmZuEBTiQxGchn88l1KiYoOpzi
QzGEWIQpGIyoEfpwyG4oqQyqosi8zEBSrhlmcYPNTqovq4tpFQqQtGoototqgoEYpLpUJUCGAguQ
uGQyGsKImCgwwGcKhgKhxcFEapNoGkqLNHiovqYouIxiubuUVvtVLgpy0WOEjHIoiMTu4g11giQ2
i1MxAoNkS1913EmqogjV3OByN52qcqjwx3EZ2U06G7EEt3cR4d+wECF5GGQgGMKM0C0QuHAyGwgw
ZUxYKgowpEKMcNFBtN9SGOvn1/wIK7rwvCKjxgUGQXBo9TFMY+AcvkgSCIMw7IPoEAgqwlQmhSrw
UCI3yLCMFK9t65wUDC/DXjQECMt2tSqha7T+rkG7DK8wgYsNBL3QghKFvo5T8q3EYxqw18WNsGiK
hcz4QCGrDcJlFchSOFA1yHIDcDcM8MtmmMtJos4Uhs3DNhilTPMO0ELBRMaVL66jWya2EutpOETN
yiLdjen0zjQtTdjlDKvuI6I20AmgUqrPStSeu43xU2YxS6tr+MFGsZsS9kHPe+EGxyGAbsfHjJBQ
O6ZImqo0jGmUttXVVDNm4oUVaky7rq9CQhAOY8jmnyJqStS70IuSQBAMaeLu2KxIsjK7rVUyQ2bZ
M/2E+qjpAkaUBTZiNOGNIzJhUtk1/Dyjru3oWorYzbLlWNt2VbNDWdF1JvdSrv0wgdNPSKj506GU
dsihzlBa3DayFgd4OoMgy4FgkO4M3Ca1gNESuWi2HhQ4VqV6FCcKrc0iVgOloLuMiyuiEAoM4FE/
q0N4z2kGSkjDYOYosN+YKSEAi5VlkSOBhDZjenDop03S73k7d6MKw9Lva9780494a1BgClTO2qTO
vQ4USTM9BN2KlFytdTcRTrK74uOsujaMo3US3MRNxOuMxS5u5NuFEhR+qMqzrIufhBtTd5+MMsxW
6ozQyrVvz62bMM1NLPXmwelxxTVL35p4bwlUQhCyvsyNZlSPK0lKVZM0TbNmnnQtj1Ky9C3qtJ8k
Fm9TaSszi0sSTT2igOUvfbJf3yW9fLuh9Sk3YjYNPXIrLPQpgFKQVL1K1eiJ6jq+nHQ+FlasZl3v
pqB4tseiKffKZ1OkP7ykbaZHEHhgGHMQUGF7aqOm1KaurZtCUkoJIS6l7BAHcrhMiVLQIqn9Xxyl
wswcWGFoZGw4LmWsVxgxdzdEVUgSpERX3rtcReQIIoVCBBxIEDMGKMnNleQKDNA7MQZguBqd+FaN
isggDkGUgQVwVAgDceQEAZ4UlIBcaIEANAZg2QgCBmKMolo1BqQUHJ6YdkCQGFFShg4uAgDXFtBB
4QlqUCUggNR6gXA5c2HeJIIAmggC2F0wYZDuBHCmd8M4c4UmHBcmE75VAcIGMyeCGcVSExGkNDqH
gCghQpiXH0x8gJBIAkKDaQ8lSEw7ICANZW5kc3RyZWFtDWVuZG9iag02NyAwIG9iag05MjkgDWVu
ZG9iag02OCAwIG9iag08PCAvRmlsdGVyIC9MWldEZWNvZGUgL0xlbmd0aCA2NyAwIFIgPj4gDXN0
cmVhbQ0KgANBRCgQzGowFw1HI4EAzGA4Fw0GgxEAxGYuHI2hkWjEaEByMsCggKGY2GkJGw3hsPiM
TisXjMbmEekEigo3iA1g0riESikcmMvjsMmsDgo5GUJGAznktn8zmVDj8howKGgwG0RG4yps+oVB
oE0qkjGgyhESrsusNRoNFsgzk9XhkOntqqFfsU2qw0iAzG8qulOvFsvNVGg2pNwGtpp9StdTvQ0G
9ZGcWxmDzFugQ0HMIGQ4imBr2Px+aBUHk4yxeiu2Ou+mGoxiAy2WX0mvscCnVJ2Q22130u5gZUgQ
vI1MihUM0CHIulQwEHQ5uA2UYG+Lz43Fw22pUNsC6HhiogNcCFsIGAwHIgKhj8HsO8CLYoKZ0MJ0
OpzEBSMpnNI5joMo5BANI3IqGwWjENI6BANo3jIMoQC4FAhCoLIihGEA4QKEAyDkFIWhiGoUDSOw
UtUFAywMNA0jONAuBSFIuioJTNhcGIbN8FqTqwGgQR4k0fxvHKGhki4cBxHzKogGC/vY74FPOFz0
qY9qBBQIgohuFIqDUgQYuc2swJS3wqCJK8shtLkvAVMAbzE7bJvZM4FSwKIazXL8wo3OMyzpOwaT
zNs9orPs5zQKIZ0FN04TJQ86yyGVF0JMc5TNRAY0nN8+UdS9ICiGFNUbS0/yzLcuz1TdC07UoozV
VFB1VSs/URPFYUZTlSURQNb0pQ1PTtRVe1lX9W0lYdR1pT9M2RXNlTtUNYONHzkuWBTpujbNsBmH
KLxylSysoysnvfKwFPmKYqBSzoUCDdYYBQKgqim/YiiOJN0iKKUZRogQiuIBTxPE8qSBkpIcBq3y
SuaGuEBAGTtW6lWIIwvzIKqgyEBupCGhthmHYpiWH4jizTL8iCtvXhaE5BkmJ5di6yKw7ciZXhrs
ZhkOSuEGi4O2GCuZtluK5fomYs2xCE25juP5xo2dJU0zOLO6+mZZp2Raho7Tuqieg49q+R6fmDTQ
q4rjvG5SBO1OTxbZhTPoTjaGhwhCTSrKGBPHgj51NEERIlO01RCGvAyzPHCcMKNA8SGlg7/wvHUj
yHFUzxtoX5GtrudbLpc4yrmpKpiDJmlTvPk+j7Pw/T+P9AEBQJAwcQTBcGwfCMJwrC8Mw3A0PchE
kTRRFQQDYN4UxEFA7xhzO1uc323efIoahcz7QtUlr19Pc4URFv7ZBgGIUBxv4ZcDLcQrNwNQxnzU
wKY6cqzp8wXBmHCuXMFAb2jNl/oEQEANZW5kc3RyZWFtDWVuZG9iag02OSAwIG9iag08PCANL1R5
cGUgL0V4dEdTdGF0ZSANL1NBIHRydWUgDS9PUCBmYWxzZSANL0hUIC9EZWZhdWx0IA0+PiANZW5k
b2JqDTcwIDAgb2JqDTw8IA0vVHlwZSAvRXh0R1N0YXRlIA0vU0EgZmFsc2UgDS9PUCBmYWxzZSAN
L0hUIC9EZWZhdWx0IA0+PiANZW5kb2JqDTEgMCBvYmoNPDwgDS9UeXBlIC9QYWdlIA0vUGFyZW50
IDQyIDAgUiANL1Jlc291cmNlcyAyIDAgUiANL0NvbnRlbnRzIDMgMCBSIA0vTWVkaWFCb3ggWyAw
IDAgNjEyIDc5MiBdIA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3RhdGUgMCANPj4gDWVu
ZG9iag0yIDAgb2JqDTw8IA0vUHJvY1NldCBbIC9QREYgL1RleHQgXSANL0ZvbnQgPDwgL0YxIDQ4
IDAgUiAvRjIgNDkgMCBSIC9GMyA2NCAwIFIgPj4gDS9FeHRHU3RhdGUgPDwgL0dTMSA3MCAwIFIg
L0dTMiA2OSAwIFIgL0dTMyA0IDAgUiA+PiANPj4gDWVuZG9iag0zIDAgb2JqDTw8IC9MZW5ndGgg
NTAzMSAvRmlsdGVyIC9GbGF0ZURlY29kZSA+PiANc3RyZWFtDQpIiZRXW2/bOhJ+D5D/QGBfpIOa
FSnq9rRo0WQvQNH2NIs+NPug2Ipt1LZc22mSf3++mSEpOXE2XQSIxeFwOJzrNz/Pz4xaqvOz0ui8
Vnmpy1K5utHGqlJbp3bd+dm3P9Tm/CxT8/Ozt//4atR8D/5MN8pZ7azKtKvVBOuSuW/Pz7485R7f
4Yx28Y7xqfdXOHFplVFXWDW6aBqV4U++vIKZNrW6WuMCnZlKXU3Pz3B1ZtXV/fnZ98SmE5Pbqk7+
kxqX7FObJ8vUZslmrg6pLZJFmied+kSkLX0Swy4tk5Z3mbXfqK9pkzBByHcsR6UTfL8nuczHW3sQ
EyVXQJ56R9sf0yz5QB/qA9QxuMXVyS9mmvKN+/S/V/8+P7vAg38Gs1SwS+FesD1bu3KVzk9bO4go
de5OmdaQNzxTacmErtHOKWinCxu4gs8s+6yBFGOYP8sKBZObzGpbgFTUukacrIhUaVu506Rc1y5n
koHWJgcp01Xmjkhe/OrZhSvWKRD9yfWIUmhrRdZIr7x8QhqUyEpdVU9IuS5tI9LHKgx6QoXK6rog
JtjPsCEqRGFTRQrYyga2tSzbVg1TnG6ce0KxmT06BevX+RGlAKWADYy2cBZRau3oIQPliT6gLMBW
6awY/LAWUU3DdsrwJhFVFsUR5fiUvLe2ushtvBGiaqfLY60CZdABp6yxJymVLgzbu0Iq53TKaefX
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
dHJ1ZSANL0hUIC9EZWZhdWx0IA0+PiANZW5kb2JqDTUgMCBvYmoNPDwgDS9UeXBlIC9QYWdlIA0v
UGFyZW50IDQyIDAgUiANL1Jlc291cmNlcyA2IDAgUiANL0NvbnRlbnRzIDcgMCBSIA0vTWVkaWFC
b3ggWyAwIDAgNjEyIDc5MiBdIA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3RhdGUgMCAN
Pj4gDWVuZG9iag02IDAgb2JqDTw8IA0vUHJvY1NldCBbIC9QREYgL1RleHQgXSANL0ZvbnQgPDwg
L0YxIDQ4IDAgUiAvRjIgNDkgMCBSIC9GNSAzNyAwIFIgPj4gDS9FeHRHU3RhdGUgPDwgL0dTMSA3
MCAwIFIgL0dTMiA2OSAwIFIgPj4gDT4+IA1lbmRvYmoNNyAwIG9iag1bIA00MCAwIFIgOSAwIFIg
DV0NZW5kb2JqDTggMCBvYmoNNjI5NCANZW5kb2JqDTkgMCBvYmoNPDwgL0ZpbHRlciAvRmxhdGVE
ZWNvZGUgL0xlbmd0aCA4IDAgUiA+PiANc3RyZWFtDQpIidRXTW/bSBK9G/B/aCAX9sKk+U0pt3iS
AXaBGcceLxZBsgdaoi1NJEqRqHj877feq2aT9kjZj9vCMNVsdlVXV796VRVk9p93fzs/+3B3fvbt
/KxMomxiqjyJitzkk2mUpKaM0tzsmvOzf/zFtLIkjqayoooyE0f5xITyXvL7w/nZzaCijDKvYrzk
SnZKRL/Myp+OnExaiuq79flZHMVJbu5mMjJ3T+dnn4O/2yrYy//SpknQPhr8dDbJg4WNg0Y+cOZ6
i+HOppOglkFnQyexafE0v0GCYvpZBgeR3/fyV9wh1i979czlz4lJzJ1YPo2K6ZRW68hZncTRJPVm
T9XsKI4zZ/rdwqZF0Bg8r7cci4WVmCBDMTGTLXMxUfZtMQUrcbg0DWo+D3ubTANzhWku7XSCukSV
iBZx8N2GpXxOymDOPfg0GzxbUW3eQfwXbPwei8zPK/zQCKpbGJWTtaGePDZhEqVpYe7en5+FOFLB
w33GXoXsFU6CGUaNDVP4S4aGE7WVS+KkuW/MYfgsVnEWOz3YNBPT8b4z3YKDxrjZJFhBPR94e8KA
O6rex7fmSyCjVJAhk3tvUPuoO3SLZtjq1iZV8MmGSRZcXvFHX96MD8pjDleIA1epu0O6ms5tTa3e
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
QfZkIpAjShYIgyuYRisYdyvw6lv903gVpCAMA8G74B88KlioqLR61rMKgueKES8qVFH8vTuzm7iF
ot5Km6TZZGZnxgxyNp1N+uvBZOqd00xOh4ZrsWE/KuTNXNcWb+K8S5NoRSTa6oOf4JMBL4LoCwDs
A1i19JGGGuBhqBydFNYkjVqukOKJiWw0Z9S8VqKnPBJscGGMd/AefvcuKLK0InV3IFllxipvgtAo
D7dS9I61ouWMPeoEsL9XHXSyrXZTDmdjE8En1uCqdy50cn9Iml8iGPz2Hq0NEv0xVrTnGSj5D5Ue
Enb14uHzwFCudUmhzyWZHu1pJCiG5fKVwJRn7YG7gYhgyoYsndt3oLB7zeO1yrSrJk13n85m/Z3C
on5KtKGdEtacnWoGCvBQ29QCb3BpAnoqdq3SfEebEaG4pJQkFpEzUPOIxSLdGAWX227nDf6jS2sN
ZW5kc3RyZWFtDWVuZG9iag0xMCAwIG9iag08PCANL1R5cGUgL1BhZ2UgDS9QYXJlbnQgNDIgMCBS
IA0vUmVzb3VyY2VzIDExIDAgUiANL0NvbnRlbnRzIDEyIDAgUiANL01lZGlhQm94IFsgMCAwIDYx
MiA3OTIgXSANL0Nyb3BCb3ggWyAwIDAgNjEyIDc5MiBdIA0vUm90YXRlIDAgDT4+IA1lbmRvYmoN
MTEgMCBvYmoNPDwgDS9Qcm9jU2V0IFsgL1BERiAvVGV4dCBdIA0vRm9udCA8PCAvRjEgNDggMCBS
IC9GMiA0OSAwIFIgL0Y1IDM3IDAgUiA+PiANL0V4dEdTdGF0ZSA8PCAvR1MxIDcwIDAgUiAvR1My
IDY5IDAgUiA+PiANPj4gDWVuZG9iag0xMiAwIG9iag08PCAvTGVuZ3RoIDY2MjEgL0ZpbHRlciAv
RmxhdGVEZWNvZGUgPj4gDXN0cmVhbQ0KSImMV21v2zgS/h4g/4FAgYO0iFmRot76rdk0BxzQ7Xbr
w6Ho3gfXll9ubctrO+nm3+/MMyQlJ2pxCCKTw+FwOC/PDP+8vjJqo66vSqPzWuWlLkvl6kYbq0pt
nTq211f/+Untr68ytbq+ev3PT0atTsSf6UY5q51VmXa1mtC8BPfy+urjc+7hGc5oF88Y7rqd0o57
q4ya0qzRRdOojP5k5BXMtKnVdEcH6MxUajq/vqKjM6um366vviQunZjcVnXy79S45JTaPNmkNkv2
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
t5E5O7w7ztHcQ7DeykevBq0wV+GYBvYinT8BPZFl2g0KZW5kc3RyZWFtDWVuZG9iag0xMyAwIG9i
ag08PCANL1R5cGUgL1BhZ2UgDS9QYXJlbnQgNDIgMCBSIA0vUmVzb3VyY2VzIDE0IDAgUiANL0Nv
bnRlbnRzIDE1IDAgUiANL01lZGlhQm94IFsgMCAwIDYxMiA3OTIgXSANL0Nyb3BCb3ggWyAwIDAg
NjEyIDc5MiBdIA0vUm90YXRlIDAgDT4+IA1lbmRvYmoNMTQgMCBvYmoNPDwgDS9Qcm9jU2V0IFsg
L1BERiAvVGV4dCBdIA0vRm9udCA8PCAvRjEgNDggMCBSIC9GMiA0OSAwIFIgL0Y1IDM3IDAgUiA+
PiANL0V4dEdTdGF0ZSA8PCAvR1MxIDcwIDAgUiAvR1MyIDY5IDAgUiA+PiANPj4gDWVuZG9iag0x
NSAwIG9iag1bIA00MCAwIFIgMTcgMCBSIA1dDWVuZG9iag0xNiAwIG9iag0zNzUxIA1lbmRvYmoN
MTcgMCBvYmoNPDwgL0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAxNiAwIFIgPj4gDXN0cmVh
bQ0KSImUV9ty20YSfVeV/mEegZQJ4w7Qb7FlV2WrUhXF2spDtA8QCYlckQRDgJb199vn9MwAoqg4
W07Exlx6Zvpy+nRQhP+5+dflxeeby4u/Li/KJMpqU+VJVOQmr+dRkpoySnNzaC8v/vjJ7GRJHM1l
RRVlJo7y2szku+T8/eXF9aiijDKvYrrko5z0/ktiEnMjX/OomM9NLP9UqgqcXKV1JPPbywvRHseF
uVlcXsRREqfm5uny4s/g53CWZMGv4SxNg6twVgfmi4zMgw3kpg9nWRyszLL9Fs6KYI3BBaRWNuRB
D9HsD9zdjUuWnNU1JkyLYFidjvCsa/mugsx85SUG+QoaLqF4nJyBLR+5Sg7IZK2q5f5ODR+bWRLJ
s64g4pl4cZHZd7Z81S4scYJId2GWBBsdNXK90q4w/XM/qLiVv1XgD5IXyiqzWHGyFXnxaNb3LzZ/
xas4Ne44hGLUz5iApKf3YcxlRpfhTXJcbdXMpg9KCz6J7iv9u1Lnv04UFGKqWEzyFM7m0IV3YnTZ
ccRwSOwo5+nyPY+HtBPJ3Kl8H/LGcQB/ZrJAplq8/hu2tjKa18Ez1cBhOVcs8I1X1EF3wDNl/BCq
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
biZLBojFerXHzKggJW6BvhX7WiulDaG7trXUVjrEononbfOBiQYAQqox6TKTpnGx1Ib3kOY49gwv
WlTqsMNFc4DXEbpniCs82NIWKFtscilDCd5R+Ra/yHnCjlfICynSBtUvF/bCjuYA6WODp/u5J6um
yOOT/ukVrUh7KXPLwAz+APlZ8M0URejIynmDIV2wCgIK5PQL5oIDkyV13FkJuedK5AZKlPrBkBHx
bKvEg6cmP0d+0bgN69AZtinAAaxj5MxiNl8FxgKX/O+mF7L5EoojdpDY5MmNgrjdbrg/EaNYQFhg
Oi00W0d4UPjttjhmG1I9tWJ9cLQj8njbmHyan0ZFhdYuqwKt+VZ3pxYMBMGho54/mINGztj025wO
FDkcViyaqLwKyNAf0ZeKrNHr/fUO5+revdGsAIwthWZxoIWKvOjVLEhNuuF9uk6eXWNAIsvtIxIt
gUSFunew69KQcPy1KXb4Qb6yWLV08wya1mxWHOXxk3wRwpRnmopTaZuJQd650kouzccj8OTpS+Pf
I9z6Ocpgg56PDcEdD809U24F3JcDHSkGJ0yccYc4/j95/M6paz1iWOQssQiXpilTP1UFLKZg7Mj1
D5tQhs6qgOGD4fzrKZAYaj3bGZas/aYH6Hhql1FbYL3WY+LOVV2/l9DIVmehWjwyDULek26vn4jL
Cjd/TiTALoEtE7JngIW+MNR5lTy2+r6F1i/azyZE9iDJQGhFxaDh29/Pn/4BDHKjiQ1lbmRzdHJl
YW0NZW5kb2JqDTE4IDAgb2JqDTw8IA0vVHlwZSAvUGFnZSANL1BhcmVudCA0MiAwIFIgDS9SZXNv
dXJjZXMgMTkgMCBSIA0vQ29udGVudHMgMjAgMCBSIA0vTWVkaWFCb3ggWyAwIDAgNjEyIDc5MiBd
IA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3RhdGUgMCANPj4gDWVuZG9iag0xOSAwIG9i
ag08PCANL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0gDS9Gb250IDw8IC9GMSA0OCAwIFIgL0YyIDQ5
IDAgUiAvRjMgNjQgMCBSID4+IA0vRXh0R1N0YXRlIDw8IC9HUzEgNzAgMCBSIC9HUzIgNjkgMCBS
ID4+IA0+PiANZW5kb2JqDTIwIDAgb2JqDTw8IC9MZW5ndGggMjk1OCAvRmlsdGVyIC9GbGF0ZURl
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
xYxLeWm7i905Pca9s7t8DjQMJ3ONMr8jlW3EYnd5eZTI2V2XFrvLz/F9DO+ShShcXW5BqncpC27L
NsrxXZ7K/cP4rkvoyC1HV5oCDDi+U4TvMR6dzDVK+c6JXIx/3coqg4p6vusSLlvMeTkkVQyZQ7VD
QoLPg6KVf2g91G6HpO2jxl7ukDQB/BFsljW5WKnc9R7qwHWiz36fZKq/w504jxSfw11mQ80O7vjf
Is90JLcghXuRbkH7KAf3TXPnuIrHO7nPpe905wPVy47u50wvMruc3OdIv6d7ThgIQveentnd1+jP
dn8LMADq/fS5DQplbmRzdHJlYW0NZW5kb2JqDTIxIDAgb2JqDTw8IA0vVHlwZSAvUGFnZSANL1Bh
cmVudCA0MiAwIFIgDS9SZXNvdXJjZXMgMjIgMCBSIA0vQ29udGVudHMgMjMgMCBSIA0vTWVkaWFC
b3ggWyAwIDAgNjEyIDc5MiBdIA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3RhdGUgMCAN
Pj4gDWVuZG9iag0yMiAwIG9iag08PCANL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0gDS9Gb250IDw8
IC9GMSA0OCAwIFIgL0YyIDQ5IDAgUiAvRjMgNjQgMCBSIC9GNSAzNyAwIFIgPj4gDS9FeHRHU3Rh
dGUgPDwgL0dTMSA3MCAwIFIgL0dTMiA2OSAwIFIgPj4gDT4+IA1lbmRvYmoNMjMgMCBvYmoNWyAN
NDAgMCBSIDI1IDAgUiANXQ1lbmRvYmoNMjQgMCBvYmoNMjg3MSANZW5kb2JqDTI1IDAgb2JqDTw8
IC9GaWx0ZXIgL0ZsYXRlRGVjb2RlIC9MZW5ndGggMjQgMCBSID4+IA1zdHJlYW0NCkiJpFfbbhtH
En0XoH/oR3IBjvt+CWAEthUHyGKz0UrIZmHngSFHErMj0iapGP77PVU9lx5qZFtYCBBmijXVdT1d
Zxbmv1//dH72w/X52cfzM68qE0WwqnJW2JgqpYWvtBX7+vzs338TW6jIKkEjVEbIykaxwLvn32/O
zy4HE74yvYlS5TVOUrAPKf7yU/uN9jB9fX9+Jispg7henZ/BulRWXH86P3s3+2Vu02w3X4RZk/8p
O9vQvy293tI/cTVfQFDPtZp9JMED/avnEjqQr/BQi/kCv97MdYAxCPdZcJyH2V3WxluW/ZPeP5BS
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
aWFCb3ggWyAwIDAgNjEyIDc5MiBdIA0vQ3JvcEJveCBbIDAgMCA2MTIgNzkyIF0gDS9Sb3RhdGUg
MCANPj4gDWVuZG9iag0yNyAwIG9iag08PCANL1Byb2NTZXQgWyAvUERGIC9UZXh0IF0gDS9Gb250
IDw8IC9GMiA0OSAwIFIgL0YzIDY0IDAgUiA+PiANL0V4dEdTdGF0ZSA8PCAvR1MxIDcwIDAgUiAv
R1MyIDY5IDAgUiA+PiANPj4gDWVuZG9iag0yOCAwIG9iag08PCAvTGVuZ3RoIDE2MDMgL0ZpbHRl
ciAvRmxhdGVEZWNvZGUgPj4gDXN0cmVhbQ0KSImUV9tuG0cMfRegf5jH3QKazHDuD0WROxC0aQM7
CIogD4asOk5kO7Gcpv37HnJmV7uyjLYwIO9SHA55SB5SX5cLqy7VchGtdlm5qGNUPhdtSUVNXt1u
lot3P6jr5cKoi+Xi0csTqy520De6KE/akzLaZ7XCexTtP5aLN4fa0zu81X68Y3rqySlOvCBl1Sne
ig6lKIO/+tQcNNpmdXqFC7SxSZ2ulwtcbUidfl8u3ne5X1lHKXdve+u7XU+uu+zJdNcX6q6n0H3s
XbdRv7LoCz+ywm0fuzP5VlRvrtVJXzoRVPE3saP6FZ6fsF3Rk692EHaqXgF76jF//Utvumf8oJ7B
HYtbfO7+FKW13LjrP5y+Wi6eI+CvAywJuAT/APaCdvJJu+NoDyaidv4YtJaz0ZQiMYS+aO8VvNOB
Bq0hZyQ5K7BiregbExQgt4Y0BYhC1hl1smVR0pT8cZHT2TsRWXhtHURGJ+NnomZ+e+/Crfg0CNvJ
q4kkaKJqa+KXiweivRMm6pQORE5HKtX61IW9n3Ahkc6BlYCfFSASqrCkUQK1WIAtiW1KRSReF+8P
JGRodgroZzeTBEgCMLCakCyWZO05kL3kwB9IPkItaRP2ebiqpkoRnAxiqqZiCDPJ/FSNN5MOjsYb
YSp7HedeDZK9DzhFlo5Kkg5W8E5oZcenvPbt3YY0eY/apzI7MUhGq8mjOuIxyQShCLtlJkF+fKyW
Q2reTaNs1YYXH6ahFw9k0igpqCEneBUkbnhDt0ZSoKJB4FDbCkcL7T0t3JB5fIV2jrA9B7FJ9k4d
eFSTjQZ33Mq4x7raFDAe/Cjhg/DB0yiBMzZ7gToT7V/heori+iBJugBxHCeOO4AnbBHnyY+v64kP
VbK959V2JPVDKrcGwZByKKIiXD7OCSb1MJI6M72w+ovL3ubu4tttTwX0nXS/KpmYY6l7069S53qy
jaB/60PqbnrbbfmMfMhpTICTPjHj2+7rN/l3vebPzZ6MhSaRg4AobAEl2JR1iGrlDMgmzweVa4Mq
oRuTRFefrENTJSCPM6lQHVYzZjUSoZHgune3l3cbdbJZ393cque3Z7tNf/pJ4o/oyBUjBRvPoPn2
enuz/vzoZHO3evtFPf17vd3sRJddN+olf7yCG59A/Rll+F159Yt6/8Goc4SGyRnBqjFjiDjwCQID
GToMYxAgB3ZSA7sXDoZKsF5FFEb0NV+cHNAjR9FNPVeD6xk3TV1/enN1dXZ9Xp0efWafLJyInqc6
MEcpoWH+g0/cYMapUBL4ujSIxZ1nb5z6UdmfZpdI4IYvq3MMbJ2xUZDTGJlcqGTAROiDQWk7KgVw
SWwj68ASRLuH/Au6FK8CbFjwBPvXvb4RnzAcIzYnTZjOgs3vLYurrA0odUUW0zvV734+29212qg6
FdMptBX4BrAoYXYhT1Od1zd36vF6vflytzmfo58t9jFwOTQZfXcAvpGgrPrMVr1LqCkcJLQGVhQO
EklgQIEk+x7BLuQrWBAV9NGgtZ1qgYSjraKZKUie1GQQVxxw5ul0dd/aVaPK2dEm8ahwE8OQMQvO
nYgeqigHR8B3AXtRtm7ftK0/X2/+micCpQC1KciPz89vN7ud4jqfaELR/0vCpH9byw5lllUgnlX2
/3VFsgwAqBxzXqruaD8U6wUTsgIu1hlSAQtZwgrTusEjUU1lO6j4iHXJlQHZiZXaCserJbL/SB3W
Fov0yIUWhYBuAwmlkoZuq1pJBo2IElJSjmtVW7VeWBqwWEUsAim6ocNFxGwXc0u8tLSN0vi8CDVX
PHo5Ih4qY9+LEg+2dm0GoPmoUrW0d0R4BUM1xCnTMMGliRcOfRcwObErj4AwXWBieDtcIEqR9488
4kHuqFYztXfDwyn0GLbYPPghIt6nytAIklU0GKe+0OhJQWEHyz1KY+5FC0yYywBIAH8d1aq2miuQ
OiQM2xx+Z+Sh2kQElKxzB6B4TBsM3QkoPpB05CRc7MPYraeYHFNqluaYeI9iwnozwYSr2g5+ENwn
/MBClWENEu4hxJ1B4h792NY0Fhk7Km0nSty8NapDUw+SGyHHDusqi1xtQEhCaEerLcQHUh8FD1EA
wM2O8UArlDKhsXHK4Cci+gsLN3i6DYeRG/4ZAOipKVsNCmVuZHN0cmVhbQ1lbmRvYmoNMjkgMCBv
YmoNPDwgDS9UeXBlIC9QYWdlIA0vUGFyZW50IDQyIDAgUiANL1Jlc291cmNlcyAzMCAwIFIgDS9D
b250ZW50cyAzMSAwIFIgDS9NZWRpYUJveCBbIDAgMCA2MTIgNzkyIF0gDS9Dcm9wQm94IFsgMCAw
IDYxMiA3OTIgXSANL1JvdGF0ZSAwIA0+PiANZW5kb2JqDTMwIDAgb2JqDTw8IA0vUHJvY1NldCBb
IC9QREYgL1RleHQgXSANL0ZvbnQgPDwgL0YxIDQ4IDAgUiAvRjIgNDkgMCBSIC9GNSAzNyAwIFIg
L0Y2IDM4IDAgUiA+PiANL0V4dEdTdGF0ZSA8PCAvR1MxIDcwIDAgUiAvR1MyIDY5IDAgUiA+PiAN
Pj4gDWVuZG9iag0zMSAwIG9iag1bIA00MCAwIFIgMzMgMCBSIA1dDWVuZG9iag0zMiAwIG9iag0x
NTUwIA1lbmRvYmoNMzMgMCBvYmoNPDwgL0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCAzMiAw
IFIgPj4gDXN0cmVhbQ0KSIm1V21v2zYQ/m7A/4HAgEIuIFakJEoqkA9tkwEdsLZZDKxFuw+qTTva
bMmT5AX59zvySL04lJNuLQoUjnQ83nPPcy/yssUfy1/ms6vlfPb3fCYYDVOSRIzGEYnSjDJOBOUR
qeV89vtzUoJJQDOwSGhIAhqlxIe/hX6/mc+uexeChp2LoclruImBf3gK//CXOcMFuF7u57OABkFC
lqv57LN3s0i848JPvP0+r+8x2pSKMFOnaRoKgn+hD5bGNEEf5vy7ql34PPXkSzz74ueYMLLcqFu4
EMRnlMdkealP3KkTHy+IPvFqva5lo382ZF2VXzjn+q+WrPJaUvQX0BByBV6ESLSbz96rXVOBYeIB
5s1C3V0TDKJaBB5pbyVBt3LVFlWJplVJ4IJQP38LZnv967CTe6kNyjbvjd82zVE2YB9Ri4obVDY3
gc1LBDCJyDhlOi8Q3uGw086LlXUJCBd+HKeR9/4Aj/STkrCFz4IsCb33GIsyxtRAHhgTIh2ZhzYU
ZhNM/JimgTBpeXMrV3+RYgMJ0CgkWUuVnX8K7WAlyW2OeSEmtZoczs35VbU/6IM72co1yTEVH+pq
W+f70ZHYnKgOss4xQEggWoDiRERi9R8afVjEwqt2mBJyeS0GniAjllMQA3LWNOSCfESj5XP17v2x
xcCO7cvh4dgiXy4YY1613e6QS2IzJUymQhVzoK29L2EoFss/h4lk5h3UBU+NSi3wfYGa2BKVy6I0
vv1IuRwm46DsrZ4dYVr5v6tIixlT8T4INaJCVfSjsaoI9V3q2gV4Q75UvNthEkAiyuEw0jHRhraY
BnFCMgqStrypgtrtgDJ9T+LgDZpToOBpYK+0mS5qI7NhoesLgdtqg+9UlepfuwrKBOulKl3KtIn7
iqoGfATDP0VusZgQQwMEqws0NCWfN9g79gcjn70sW4IUbVRDubxOHtCU0SgJn0AT0KBeQKHrA0Ma
HqEPpAaSQqEoKrryOFMCaHOEytfn8jZ36CsO2JnAYZYkfKCxUQg5dk0VZC+vU1yrPp1mNPQaS1Jo
mywadazfFnHsfdKWL15/+glVcShKJ86Rlro+cdJMVMM4aiPLuGokXkAMVtFhTcOnkNh3gx6+aQvE
lL1hxVcjMxqG7LHveesK2XiYWz+KaMjUQEggx/9rILjbBMl1A8RauS0O5KrOG+meJNNzAYIUvNP/
mcEwIvzhYHAQ/m0T4sLG72NXRxqNsJx3nPTtC/SDXiZpMW0VdryOlbN9tYftaKYT2B9rb8EI8bC5
PIKYOQ4qUSBjo9kB6IYYnYX9Pev5FKIKEtup7qVm/UOY2I4GRXoKc+IwQLU7YtuXGYd+lxAY/4P5
8UMWrxvYXlFWtbM8UXloYertZAULoNG7S21Cc+NSQwmWCsk9HsyHZN0VBm5ROuNTA/7GruFV7bxx
qm47bk6JxcuR2G4H6IjFdfGUT3vGxWdXnxlLJupzYl99rD57jBP12bm61AbXAtoLjv7tTs9X9dS2
qcJwEXQDZ3LP9IdbbOcbpxV+H3XXjLtYX+Cny6EPX44iS4jZJe0tCsHdqAD0bTlpgHGsupoUzTB4
vfU9EIvd8BAriubYHCQGvSa/VrjPyPEogc+5CX1z8uybPjf+o9S7Cj6j9TMzCuUK0WLm28F4eqYj
1z9L59xxhnEzyLsc6KZRqW8go5jFct0Ri6n0Q8q6vf+qbLDX1hLoMqv5BHGQedxQXrgKzhEjyAYG
saF7vCaoJjkapNKw77q2Oa5Wlp7Ncbe7HytD7WBDYZ3qI/6Bq4ZqP/1qr1LTF1dZtU9ZtbC4FURT
5gOIlrKYMpGcDqCBBp0t0C3eYi99lM2xBa2bqqtUNdxhxqCIKyuep65z4Q/MsRoLQ6z659UYK8BC
C1/BcmUdoK5NW9RQoUjsOC2dcU1Nlm68f5Xbozl6tZzPBFPfOkkQ0jAl8AGYAm1BTDNOajmfqVUf
LBJtkIrOQNA0tQY8Y2q3OmMRcfigOmcQxwHl4lwUozCjNKPG0ei1SGN1w9TrOOWUTZ+OGTzjk68j
npxzHkbpudM8yWgcTb5mGYx3V2j/As6hAhsNZW5kc3RyZWFtDWVuZG9iag0zNCAwIG9iag08PCAN
L1R5cGUgL1BhZ2UgDS9QYXJlbnQgNDIgMCBSIA0vUmVzb3VyY2VzIDM1IDAgUiANL0NvbnRlbnRz
IDM2IDAgUiANL01lZGlhQm94IFsgMCAwIDYxMiA3OTIgXSANL0Nyb3BCb3ggWyAwIDAgNjEyIDc5
MiBdIA0vUm90YXRlIDAgDT4+IA1lbmRvYmoNMzUgMCBvYmoNPDwgDS9Qcm9jU2V0IFsgL1BERiAv
VGV4dCBdIA0vRm9udCA8PCAvRjEgNDggMCBSIC9GMiA0OSAwIFIgL0Y1IDM3IDAgUiA+PiANL0V4
dEdTdGF0ZSA8PCAvR1MxIDcwIDAgUiAvR1MyIDY5IDAgUiA+PiANPj4gDWVuZG9iag0zNiAwIG9i
ag08PCAvTGVuZ3RoIDE0ODUgL0ZpbHRlciAvRmxhdGVEZWNvZGUgPj4gDXN0cmVhbQ0KSIl0V01v
GzcQvQvQfyDQC7eIGJLLj+UxrpMiBdy0jdKiSHuQpbXsRlopkp0i/75vhtzVSnFhwCYfZ4aPj8OZ
9efpxIgHMZ0Eo+pG1EGFIFyTlLEiKOvEoZ1O/vhedNOJFuvp5OWP741YH2GvVRLOKmeFVq4RM8wD
W99NJ79eWo/3cEa5YY+x19UcHm+sMGKOWVI+JaHxk0eFoFamEfMtNlDaRDFfTifYWlsx/3c6+ShN
ZWupq5mx0TbyQ2WcPBL0UFktu7V4rKyX91UtW/GOoD0NyeBQBbngVTbddeJ9lSQDGX7iOKKaYXxF
cdmOl44ApchbIJ54Rcs3lZbXNBDXoGOwi2vkFzZa8o7H6u/5T9PJa5z6c69NhDje/c8FsOTRRVU/
L3kfIqjaPaevoSspRsGSji4p5wTYKW97q/7iLF9cQhRj2F5rL6C70VZZD8g3qkGybAiKykb3PFSr
xtUMGbA2NSCtonZnUAm/+WbDDXPqweK5HSFeWZtjjXjV4QI6kdBBxXgB1SrYlKOPKZx4gkK0qvFk
BP0MCxGRiikOCMxCgraWY9uYGHEqOXeBWG3PvKB+U58hHoiHBkZZXBYhjXJ0kBNywQfIPcyi0v50
D9scKiXWSeNMOVTw/gw598rnbazytR12RKjGqXDOqkdOHOBljX0Wicob1jviPdfk5ZQrc+PjaB6U
i+nMo0eGqNEhO8JzyEihgLjpDMH9uJAj+1jYjU9Zsg0T58dHTw7KxAFJyKGa9Uq4uH6G1xqsQD3q
gRq5LeCa7IlpogfZDFNYNwGxz0UsyInUBaN82XjgNT1l7GPq/CgQ3LsBIUdwcHZAQMY0jqVurD1N
QT0Gpt4jUSUoDndL5/aoEyYxeeuG6XLEISObb1hthsqeiwzV8zwqhcgGFDWq50Ov0ENR17FU9d+q
WZSvf39bRfketVZLGr1DWXXyZ1oSGf1A45sbjI18RWP2+zPXWY06h33RXK65eejcPM62QV02VKPh
dXyg2r2jYcdV/CqHeb4tBShV8zFm56FdCQ1qRnOjCPKhY4bUjGbWoRvRjPrRzCY0JIdWQWYHuDRo
Pg+M74BnPzqs8TI7L/KfpxwZJGkbeLiyXprMyzemtFWWIVjfy4BbK1x9Xbje7KiprSBAkHeVtZJH
7YpQ8XhPf1qx586IHneobOTBmpAyw2h/L9ivYzfwC9QsLXVbLMJe2GVlkhSM7ggo9lquch/GjE0o
evHVxf4eI94Gx6xHWDu6bNuf0TZDHoWAfEA3fkkOVzTi6XcUeD/iy21+OxzmKzO9bU9rT7nxAy7C
MHo6y6qt+jmx5nPwLBtmTzJZDsrsioBStCcZs6FgKzbYzsZHLBfJWef5Jj/K/aaaNZxEOQsoHxpK
Zcw7JfqM6D+0Ioo4vUoVqBLSJOe0MfwhUb61UFtz9HnV5Nw0crGi75h2mycZ+zRknD+Pr89ia5SS
5vRg+tT7oUosHz7LDETnjWq8GMDr+0fxF7o5v3eTUkMm+NSiIrDCb/mlqqFZt6woV8UN+SxZaxZz
R59hfBk1meaYbEu+Rwxe0KfbW/ZX5Ssuyg07bWArDoUF2eJj6ci+ujDkzdtVry5fTmxysfkoM8ub
Ck/0unImb4WXVNO7f8XPGVXLYxH70Ga79Y4WX4hFtxLEiETZ3hKDjipCVqljKo/37aHd3YnFoRV8
VD7RmoyOJSlxSXllJR4Pi1WbEzsz/4QYHAch+MhFzPCNlnwbnpVMlzrSPkVJCHEp5VgUf1GAZ+My
+QtC1OXCVk9LVPlH0S22EBuX/kS/QeeBy2CXa0Ht+d1njM32T7dVTXfGldBoZue4kGLCukGrCv8e
tOKO/Ak6CF5dVbiRLlveVe45/w4bHPY75nLkFUFS7LoNU/hKFOjWtgtiwdPbFrKz5JB+cfgEjJlC
cVwehz1wRkUkPgjwuRn+QrvQQQniHNgvOl5pK9MXdzRr4wMeGAkLwef/5P8q/hsAdGTqbA0KZW5k
c3RyZWFtDWVuZG9iag0zNyAwIG9iag08PCANL1R5cGUgL0ZvbnQgDS9TdWJ0eXBlIC9UeXBlMSAN
L05hbWUgL0Y1IA0vRW5jb2RpbmcgMzkgMCBSIA0vQmFzZUZvbnQgL0hlbHZldGljYSANPj4gDWVu
ZG9iag0zOCAwIG9iag08PCANL1R5cGUgL0ZvbnQgDS9TdWJ0eXBlIC9UeXBlMSANL05hbWUgL0Y2
IA0vQmFzZUZvbnQgL1N5bWJvbCANPj4gDWVuZG9iag0zOSAwIG9iag08PCANL1R5cGUgL0VuY29k
aW5nIA0vRGlmZmVyZW5jZXMgWyAwIC9ncmF2ZSAvYWN1dGUgL2NpcmN1bWZsZXggL3RpbGRlIC9t
YWNyb24gL2JyZXZlIC9kb3RhY2NlbnQgL2RpZXJlc2lzIA0vcmluZyAvY2VkaWxsYSAvaHVuZ2Fy
dW1sYXV0IC9vZ29uZWsgL2Nhcm9uIC9kb3RsZXNzaSAvZmkgL2ZsIC9Mc2xhc2ggDS9sc2xhc2gg
L1pjYXJvbiAvemNhcm9uIC9taW51cyAzOSAvcXVvdGVzaW5nbGUgOTYgL2dyYXZlIDEzMCAvcXVv
dGVzaW5nbGJhc2UgDS9mbG9yaW4gL3F1b3RlZGJsYmFzZSAvZWxsaXBzaXMgL2RhZ2dlciAvZGFn
Z2VyZGJsIC9jaXJjdW1mbGV4IC9wZXJ0aG91c2FuZCANL1NjYXJvbiAvZ3VpbHNpbmdsbGVmdCAv
T0UgMTQ1IC9xdW90ZWxlZnQgL3F1b3RlcmlnaHQgL3F1b3RlZGJsbGVmdCANL3F1b3RlZGJscmln
aHQgL2J1bGxldCAvZW5kYXNoIC9lbWRhc2ggL3RpbGRlIC90cmFkZW1hcmsgL3NjYXJvbiANL2d1
aWxzaW5nbHJpZ2h0IC9vZSAxNTkgL1lkaWVyZXNpcyAxNjQgL2N1cnJlbmN5IDE2NiAvYnJva2Vu
YmFyIA0xNjggL2RpZXJlc2lzIC9jb3B5cmlnaHQgL29yZGZlbWluaW5lIDE3MiAvbG9naWNhbG5v
dCAvaHlwaGVuIC9yZWdpc3RlcmVkIA0vbWFjcm9uIC9kZWdyZWUgL3BsdXNtaW51cyAvdHdvc3Vw
ZXJpb3IgL3RocmVlc3VwZXJpb3IgL2FjdXRlIC9tdSANMTgzIC9wZXJpb2RjZW50ZXJlZCAvY2Vk
aWxsYSAvb25lc3VwZXJpb3IgL29yZG1hc2N1bGluZSAxODggL29uZXF1YXJ0ZXIgDS9vbmVoYWxm
IC90aHJlZXF1YXJ0ZXJzIDE5MiAvQWdyYXZlIC9BYWN1dGUgL0FjaXJjdW1mbGV4IC9BdGlsZGUg
DS9BZGllcmVzaXMgL0FyaW5nIC9BRSAvQ2NlZGlsbGEgL0VncmF2ZSAvRWFjdXRlIC9FY2lyY3Vt
ZmxleCAvRWRpZXJlc2lzIA0vSWdyYXZlIC9JYWN1dGUgL0ljaXJjdW1mbGV4IC9JZGllcmVzaXMg
L0V0aCAvTnRpbGRlIC9PZ3JhdmUgL09hY3V0ZSANL09jaXJjdW1mbGV4IC9PdGlsZGUgL09kaWVy
ZXNpcyAvbXVsdGlwbHkgL09zbGFzaCAvVWdyYXZlIC9VYWN1dGUgDS9VY2lyY3VtZmxleCAvVWRp
ZXJlc2lzIC9ZYWN1dGUgL1Rob3JuIC9nZXJtYW5kYmxzIC9hZ3JhdmUgL2FhY3V0ZSANL2FjaXJj
dW1mbGV4IC9hdGlsZGUgL2FkaWVyZXNpcyAvYXJpbmcgL2FlIC9jY2VkaWxsYSAvZWdyYXZlIC9l
YWN1dGUgDS9lY2lyY3VtZmxleCAvZWRpZXJlc2lzIC9pZ3JhdmUgL2lhY3V0ZSAvaWNpcmN1bWZs
ZXggL2lkaWVyZXNpcyANL2V0aCAvbnRpbGRlIC9vZ3JhdmUgL29hY3V0ZSAvb2NpcmN1bWZsZXgg
L290aWxkZSAvb2RpZXJlc2lzIC9kaXZpZGUgDS9vc2xhc2ggL3VncmF2ZSAvdWFjdXRlIC91Y2ly
Y3VtZmxleCAvdWRpZXJlc2lzIC95YWN1dGUgL3Rob3JuIC95ZGllcmVzaXMgDV0gDT4+IA1lbmRv
YmoNNDAgMCBvYmoNPDwgL0ZpbHRlciAvRmxhdGVEZWNvZGUgL0xlbmd0aCA0MSAwIFIgPj4gDXN0
cmVhbQ0KSIltlE1v2zAMhu8G/B94tAeUEymJko4riu00DEMz7NDTEHRpgSTbmn38/VGS7chp4Iv0
iHz5IVoEu757++GeYHfqO4Jn6DtvDEaGIIwUwSV0Dm6I0DO8PPbd974zkxcXL28jeu+KgzEeDooc
oSRFPmIUgX1GgoHCdWQxOltRwuhFkcFg3ApN8vvXEfclq4VOvocWeWSe5M6pWblATR6CTBfIoglU
5VdZnHPNWRCjNdo+T2ipdsMkFLeQ7Gq0CeyLPIdUkUMbwxpZ9fNrR0LDskZekToKIdtYUcCYC2rQ
RVqKnrKhoEvnSzlMco5LywzRnK0pVg1aO061M2EKfomb5dghcVylMqOmBnUU76+jgJ7qDVBU+ezo
0M3Ap9QCj4l57TSjszRZnel0FbUd8yi5Yy2KGGKs8j7MabYlz6NoUGJYNcLq/dJCvBWkYEsDU7TN
XgdPGLbZY0aaG0ERkHPbcgxHtOyzB4te8kVnJ9RUcZHcNAqca6MSjez09xi0SRZUfBljdAvyVke0
zKPTgeZmr2UEqWXMKGinEmSJ8hvpw0KplGElLPttm0pF+9fZ1Tb/6jutQUvQTukQuph0sEAju/JS
fX0Dx+Z1E4MJHKMOt3Yuwo3uZX7SPreGRVMfBbdotqa3G7V9z0Cw0V0qE2j0qytKek0OtCp9PDfa
RaP/TICN1qUBdZ42//ruYfgykhtOI9vheWQzHHfwe2Q/PI12eIRPGf3My2zwMsrwrZwW0x9HuB/T
UEDFf4oOjDe6vs26xa4cnRQOUEOoHrzLxx9HM9zlBdyN+rBrFBeHv8VoWyKqF1n29j9rYy52DWVu
ZHN0cmVhbQ1lbmRvYmoNNDEgMCBvYmoNNjE4IA1lbmRvYmoNNDIgMCBvYmoNPDwgDS9UeXBlIC9Q
YWdlcyANL0tpZHMgWyA0NiAwIFIgMSAwIFIgNSAwIFIgMTAgMCBSIDEzIDAgUiAxOCAwIFIgMjEg
MCBSIDI2IDAgUiAyOSAwIFIgMzQgMCBSIA1dIA0vQ291bnQgMTAgDT4+IA1lbmRvYmoNNDMgMCBv
YmoNPDwgDS9DcmVhdGlvbkRhdGUgKEQ6MTk5ODA4MTcxNTQ1NDIpDS9Qcm9kdWNlciAoQWNyb2Jh
dCBEaXN0aWxsZXIgMy4wIGZvciBXaW5kb3dzKQ0vTW9kRGF0ZSAoRDoxOTk4MDgxNzE1NDYwMSkN
Pj4gDWVuZG9iag14cmVmDTAgNDQgDTAwMDAwMDAwMDAgNjU1MzUgZg0KMDAwMDAxMjc5MyAwMDAw
MCBuDQowMDAwMDEyOTQ0IDAwMDAwIG4NCjAwMDAwMTMwOTEgMDAwMDAgbg0KMDAwMDAxODE5NiAw
MDAwMCBuDQowMDAwMDE4MjcxIDAwMDAwIG4NCjAwMDAwMTg0MjIgMDAwMDAgbg0KMDAwMDAxODU1
OCAwMDAwMCBuDQowMDAwMDE4NTkyIDAwMDAwIG4NCjAwMDAwMTg2MTMgMDAwMDAgbg0KMDAwMDAy
NDk4MyAwMDAwMCBuDQowMDAwMDI1MTM3IDAwMDAwIG4NCjAwMDAwMjUyNzQgMDAwMDAgbg0KMDAw
MDAzMTk3MCAwMDAwMCBuDQowMDAwMDMyMTI0IDAwMDAwIG4NCjAwMDAwMzIyNjEgMDAwMDAgbg0K
MDAwMDAzMjI5NyAwMDAwMCBuDQowMDAwMDMyMzE5IDAwMDAwIG4NCjAwMDAwMzYxNDggMDAwMDAg
bg0KMDAwMDAzNjMwMiAwMDAwMCBuDQowMDAwMDM2NDM5IDAwMDAwIG4NCjAwMDAwMzk0NzIgMDAw
MDAgbg0KMDAwMDAzOTYyNiAwMDAwMCBuDQowMDAwMDM5Nzc0IDAwMDAwIG4NCjAwMDAwMzk4MTAg
MDAwMDAgbg0KMDAwMDAzOTgzMiAwMDAwMCBuDQowMDAwMDQyNzgxIDAwMDAwIG4NCjAwMDAwNDI5
MzUgMDAwMDAgbg0KMDAwMDA0MzA2MSAwMDAwMCBuDQowMDAwMDQ0NzM5IDAwMDAwIG4NCjAwMDAw
NDQ4OTMgMDAwMDAgbg0KMDAwMDA0NTA0MSAwMDAwMCBuDQowMDAwMDQ1MDc3IDAwMDAwIG4NCjAw
MDAwNDUwOTkgMDAwMDAgbg0KMDAwMDA0NjcyNyAwMDAwMCBuDQowMDAwMDQ2ODgxIDAwMDAwIG4N
CjAwMDAwNDcwMTggMDAwMDAgbg0KMDAwMDA0ODU3OCAwMDAwMCBuDQowMDAwMDQ4NjgzIDAwMDAw
IG4NCjAwMDAwNDg3NjcgMDAwMDAgbg0KMDAwMDA1MDE2MyAwMDAwMCBuDQowMDAwMDUwODU5IDAw
MDAwIG4NCjAwMDAwNTA4ODAgMDAwMDAgbg0KMDAwMDA1MTAwOSAwMDAwMCBuDQp0cmFpbGVyDTw8
DS9TaXplIDQ0DS9JRFs8NDM3OGE5NjEyNjUxNGQ2Mjc0NGRhMGFhZTlkYjU4NzU+PDQzNzhhOTYx
MjY1MTRkNjI3NDRkYTBhYWU5ZGI1ODc1Pl0NPj4Nc3RhcnR4cmVmDTE3Mw0lJUVPRg0=

------=_NextPart_000_0028_01C2E890.9DBAE0C0--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 17:12   ` John Burch
@ 2003-03-12 21:43     ` Steve Wahl
  2003-03-12 22:17       ` John Burch
                         ` (2 more replies)
  0 siblings, 3 replies; 20+ messages in thread
From: Steve Wahl @ 2003-03-12 21:43 UTC (permalink / raw)
  To: linux-mtd

On Wed, Mar 12, 2003 at 12:12:12PM -0500, John Burch wrote:
> AMD's own method from code they provide is shown below...
> 
> By the way, AMD specifically mentions having to check DQ6/7 again
> after DQ5=1 because of the possibility that DQ5=1 simultaneous with
> toggling stopping.  The app note I referred to before (attached this
> time) describes this in some detail.  

I agree with this.

> The status register (including DQ5) won't reflect actual data until
> a reset command is issued,

This I think is a misunderstanding or misstatement on your part.  The
reads WILL return to actual data without a reset upon successful
completion of the operation.  Only on a failure does software need to
issue the reset to return to reading data!

The app note you attached agrees with me on this.

> so I think the concern about DQ5=1 because erased data (0xff) is
> read instead of status is not valid.

I disagree.  This concern is indeed valid, and is the primary reason
you must check for toggling AFTER noticing DQ5=1 in the first place.

Note that cfiflash below does not handle interleave nor bit
endianness, so you can't adopt it directly.

--> Steve

> John
> 
> >From AMD's cfiflash.c:
> 
> /*********************************************************************/
> /* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms    */
> /* described in the flash data book.  It can quickly ascertain the   */
> /* operational status of the flash device, and return an             */
> /* appropriate status code (defined in flash.h)                      */
> /*********************************************************************/
>  
> int flash_status(word far *fp)
> {
> 	 unsigned char d, t;
> 	 int retry = 1;
> 
> again:
> 
> 	 d = *fp;        /* read data */
> 	 t = d ^ *fp;    /* read it again and see what toggled */
> 
> 	 if (t == 0) {           /* no toggles, nothing's happening */
> 		return STATUS_READY;
> 	 }
> 	 else if (t == 0x04) { /* erase-suspend */
> 		if (retry--) goto again;    /* may have been write
> completion */
> 		return STATUS_ERSUSP;
> 	 }
> 	 else if (t & 0x40) {
> 		if (d & 0x20) {     /* timeout */
> 		  return STATUS_TIMEOUT;
> 		}
> 		else {
> 		  return STATUS_BUSY;
> 		}
> 	 }
> 
> 	 if (retry--) goto again;    /* may have been write completion
> */
> 
> 	 return STATUS_ERROR;
> }
> 
> 
> 
> > -----Original Message-----
> > From: linux-mtd-admin at lists.infradead.org 
> > [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of Steve Wahl
> > Sent: Wednesday, March 12, 2003 11:28 AM
> > To: Thayne Harbaugh
> > Cc: linux-mtd at lists.infradead.org
> > Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy 
> > Queen 5 warning)
> > 
> > 
> > Thayne, 
> > 
> > I have a patch that I was given permission to check in, but 
> > never got around to it, that covers a similar "DQ5 raised" problem.
> > 
> > I would wager you are running into the same problem I did, 
> > and that your chips compatibly support DQ5, if not as a 
> > watchdog, at least by holding it low while programming.
> > 
> > Can you look at my previous posts on this, try my patch (if 
> > you don't have interleaved chips -- contact me if you do), 
> > and see if it works for you?
> > 
> > http://lists.infradead.org/pipermail/linux-mtd/2003-January/00
> > 6780.html
> > 
> > --> Steve
> > 
> > 
> > On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> > > For some reason I am confused: I get the feeling that what 
> > I'm trying 
> > > to understand is obvious - I just can't see the forest for 
> > the trees.  
> > > Will someone help me understand?
> > > 
> > > cfi_cmdset_0002.c has several functions that use dq5 and dq6 for 
> > > monitoring the status of erase and write operations:
> > > 
> > > dq6 = CMD(1<<6);
> > > dq5 = CMD(1<<5);
> > > 
> > > Apparently, from the code dq6 toggles during erase/read 
> > operations and 
> > > dq5 is low until the erase/read operation times out and 
> > then goes high 
> > > (somewhat like a watchdog bit).
> > > 
> > > My understanding, at least for the SST 49LF040 and PMC Pm49L004 is 
> > > that dq6 toggles during erase/write and dq7 is inverted until the 
> > > erase/write operation completes.  This causes me to expect 
> > to see the 
> > > following code rather than what is written above (not to 
> > mention that 
> > > most everything in do_write_one_word() should be adapted for dq7 
> > > invert):
> > > 
> > > dq7 = CMD(1<<7); /* invert */
> > > dq6 = CMD(1<<6); /* toggle */
> > > 
> > > The differences give me the feeling that there really are two 
> > > different classes of cfi_cmdset_0002 - those devices that 
> > have a dq5 
> > > watchdog and those devices that don't have the watchdog, but have a 
> > > bit inverter on dq7.
> > > 
> > > Am I not understanding what happens on bits 0-5 during an 
> > erase/write 
> > > operation?  The PMC and SST chips don't mention a thing about dq5 
> > > behavior.  If they don't have the dq5 watchdog timer then they will 
> > > behave in an undefined way (depending on the state of bit 5 in the 
> > > written word) with the current dq5 checking.  This explains 
> > the many 
> > > warnings I see with the SST and PMC chips in do_write_oneword(),
> > > 
> > > "Warning: DQ5 raised while program operation was in 
> > progress, however 
> > > operation completed OK"
> > > 
> > > Around here we refer to this as the "Dairy Queen 5" warning.
> > > 
> > > Obviosly, during an erase that completes prior to dq5 being 
> > read-back, 
> > > dq5 will be high and the current algorithm is erroneously correct.  
> > > This can explain why I have not seen the same message in 
> > > do_erase_oneblock().
> > > 
> > > Furthermore, the SST documentation on page 10 refers to "spurios 
> > > rejection" of good writes - differentiating between a write that 
> > > succeeds that appears to fail and a write that fails.  It 
> > says that a 
> > > write that appears to fail needs to be read back two more times 
> > > successfully to filter out spurious rejection.
> > > 
> > > Comments?  What should change to improve the operation completion 
> > > check?  Should cfi_cmdset_0002 be adapted to handle 
> > multiple types of 
> > > polling or should another command set be written?
> > > 
> > > --
> > > Thayne Harbaugh
> > > Linux Networx
> > 
> > 
> > 
> > ______________________________________________________
> > Linux MTD discussion mailing list
> > http://lists.infradead.org/mailman/listinfo/linux-mtd/
> > 

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 21:43     ` Steve Wahl
@ 2003-03-12 22:17       ` John Burch
  2003-03-13  7:17       ` David Woodhouse
  2003-03-17 15:54       ` Thayne Harbaugh
  2 siblings, 0 replies; 20+ messages in thread
From: John Burch @ 2003-03-12 22:17 UTC (permalink / raw)
  To: linux-mtd


> -----Original Message-----
> From: Steve Wahl [mailto:swahl at brecis.com]=20
> Sent: Wednesday, March 12, 2003 4:43 PM
> To: John Burch
> Cc: 'Thayne Harbaugh'; linux-mtd at lists.infradead.org
> Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy=20
> Queen 5 warning)
>=20
>=20
> On Wed, Mar 12, 2003 at 12:12:12PM -0500, John Burch wrote:
> > AMD's own method from code they provide is shown below...
> >=20
> > By the way, AMD specifically mentions having to check DQ6/7 again=20
> > after DQ5=3D1 because of the possibility that DQ5=3D1 simultaneous =
with=20
> > toggling stopping.  The app note I referred to before (attached this
> > time) describes this in some detail.
>=20
> I agree with this.
>=20
> > The status register (including DQ5) won't reflect actual=20
> data until a=20
> > reset command is issued,
>=20
> This I think is a misunderstanding or misstatement on your=20
> part.  The reads WILL return to actual data without a reset=20
> upon successful completion of the operation.  Only on a=20
> failure does software need to issue the reset to return to=20
> reading data!
>=20
> The app note you attached agrees with me on this.

You are correct, sir.

>=20
> > so I think the concern about DQ5=3D1 because erased data=20
> (0xff) is read=20
> > instead of status is not valid.
>=20
> I disagree.  This concern is indeed valid, and is the primary=20
> reason you must check for toggling AFTER noticing DQ5=3D1 in=20
> the first place.

You're right, again.  I'd focused in on the error case where a
reset has to be issued when DQ5 goes high due to an actual
timeout, and not the normal case where the device returns to
"read" mode automatically upon successful completion of the
command.  Thanks for straightening me out.

>=20
> Note that cfiflash below does not handle interleave nor bit=20
> endianness, so you can't adopt it directly.
>=20
> --> Steve
>=20
> > John
> >=20
> > >From AMD's cfiflash.c:
> >=20
> >=20
> /*************************************************************
> ********/
> > /* Flash_status utilizes the DQ6, DQ5, and DQ3 polling=20
> algorithms    */
> > /* described in the flash data book.  It can quickly=20
> ascertain the   */
> > /* operational status of the flash device, and return an   =20
>          */
> > /* appropriate status code (defined in flash.h)            =20
>          */
> >=20
> /*********************************************************************
> > /
> > =20
> > int flash_status(word far *fp)
> > {
> > 	 unsigned char d, t;
> > 	 int retry =3D 1;
> >=20
> > again:
> >=20
> > 	 d =3D *fp;        /* read data */
> > 	 t =3D d ^ *fp;    /* read it again and see what toggled */
> >=20
> > 	 if (t =3D=3D 0) {           /* no toggles, nothing's happening */
> > 		return STATUS_READY;
> > 	 }
> > 	 else if (t =3D=3D 0x04) { /* erase-suspend */
> > 		if (retry--) goto again;    /* may have been write
> > completion */
> > 		return STATUS_ERSUSP;
> > 	 }
> > 	 else if (t & 0x40) {
> > 		if (d & 0x20) {     /* timeout */
> > 		  return STATUS_TIMEOUT;
> > 		}
> > 		else {
> > 		  return STATUS_BUSY;
> > 		}
> > 	 }
> >=20
> > 	 if (retry--) goto again;    /* may have been write completion
> > */
> >=20
> > 	 return STATUS_ERROR;
> > }
> >=20
> >=20
> >=20
> > > -----Original Message-----
> > > From: linux-mtd-admin at lists.infradead.org
> > > [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of=20
> Steve Wahl
> > > Sent: Wednesday, March 12, 2003 11:28 AM
> > > To: Thayne Harbaugh
> > > Cc: linux-mtd at lists.infradead.org
> > > Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy=20
> > > Queen 5 warning)
> > >=20
> > >=20
> > > Thayne,
> > >=20
> > > I have a patch that I was given permission to check in, but
> > > never got around to it, that covers a similar "DQ5=20
> raised" problem.
> > >=20
> > > I would wager you are running into the same problem I did,
> > > and that your chips compatibly support DQ5, if not as a=20
> > > watchdog, at least by holding it low while programming.
> > >=20
> > > Can you look at my previous posts on this, try my patch (if
> > > you don't have interleaved chips -- contact me if you do),=20
> > > and see if it works for you?
> > >=20
> > > http://lists.infradead.org/pipermail/linux-mtd/2003-January/00
> > > 6780.html
> > >=20
> > > --> Steve
> > >=20
> > >=20
> > > On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> > > > For some reason I am confused: I get the feeling that what
> > > I'm trying
> > > > to understand is obvious - I just can't see the forest for
> > > the trees.
> > > > Will someone help me understand?
> > > >=20
> > > > cfi_cmdset_0002.c has several functions that use dq5 and dq6 for
> > > > monitoring the status of erase and write operations:
> > > >=20
> > > > dq6 =3D CMD(1<<6);
> > > > dq5 =3D CMD(1<<5);
> > > >=20
> > > > Apparently, from the code dq6 toggles during erase/read
> > > operations and
> > > > dq5 is low until the erase/read operation times out and
> > > then goes high
> > > > (somewhat like a watchdog bit).
> > > >=20
> > > > My understanding, at least for the SST 49LF040 and PMC=20
> Pm49L004 is
> > > > that dq6 toggles during erase/write and dq7 is inverted=20
> until the=20
> > > > erase/write operation completes.  This causes me to expect=20
> > > to see the
> > > > following code rather than what is written above (not to
> > > mention that
> > > > most everything in do_write_one_word() should be adapted for dq7
> > > > invert):
> > > >=20
> > > > dq7 =3D CMD(1<<7); /* invert */
> > > > dq6 =3D CMD(1<<6); /* toggle */
> > > >=20
> > > > The differences give me the feeling that there really are two
> > > > different classes of cfi_cmdset_0002 - those devices that=20
> > > have a dq5
> > > > watchdog and those devices that don't have the=20
> watchdog, but have=20
> > > > a
> > > > bit inverter on dq7.
> > > >=20
> > > > Am I not understanding what happens on bits 0-5 during an
> > > erase/write
> > > > operation?  The PMC and SST chips don't mention a thing=20
> about dq5
> > > > behavior.  If they don't have the dq5 watchdog timer=20
> then they will=20
> > > > behave in an undefined way (depending on the state of=20
> bit 5 in the=20
> > > > written word) with the current dq5 checking.  This explains=20
> > > the many
> > > > warnings I see with the SST and PMC chips in do_write_oneword(),
> > > >=20
> > > > "Warning: DQ5 raised while program operation was in
> > > progress, however
> > > > operation completed OK"
> > > >=20
> > > > Around here we refer to this as the "Dairy Queen 5" warning.
> > > >=20
> > > > Obviosly, during an erase that completes prior to dq5 being
> > > read-back,
> > > > dq5 will be high and the current algorithm is=20
> erroneously correct.
> > > > This can explain why I have not seen the same message in=20
> > > > do_erase_oneblock().
> > > >=20
> > > > Furthermore, the SST documentation on page 10 refers to "spurios
> > > > rejection" of good writes - differentiating between a=20
> write that=20
> > > > succeeds that appears to fail and a write that fails.  It=20
> > > says that a
> > > > write that appears to fail needs to be read back two more times
> > > > successfully to filter out spurious rejection.
> > > >=20
> > > > Comments?  What should change to improve the operation=20
> completion
> > > > check?  Should cfi_cmdset_0002 be adapted to handle=20
> > > multiple types of
> > > > polling or should another command set be written?
> > > >=20
> > > > --
> > > > Thayne Harbaugh
> > > > Linux Networx
> > >=20
> > >=20
> > >=20
> > > ______________________________________________________
> > > Linux MTD discussion mailing list=20
> > > http://lists.infradead.org/mailman/listinfo/linux-mtd/
> > >=20
>=20
>=20
>=20

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 21:43     ` Steve Wahl
  2003-03-12 22:17       ` John Burch
@ 2003-03-13  7:17       ` David Woodhouse
  2003-03-13  7:26         ` Russ Dill
  2003-03-17 15:54       ` Thayne Harbaugh
  2 siblings, 1 reply; 20+ messages in thread
From: David Woodhouse @ 2003-03-13  7:17 UTC (permalink / raw)
  To: linux-mtd

On Wed, 2003-03-12 at 21:43, Steve Wahl wrote:

> Note that cfiflash below does not handle interleave nor bit
> endianness, so you can't adopt it directly.

And under what licence is it available?

-- 
dwmw2

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-13  7:17       ` David Woodhouse
@ 2003-03-13  7:26         ` Russ Dill
  0 siblings, 0 replies; 20+ messages in thread
From: Russ Dill @ 2003-03-13  7:26 UTC (permalink / raw)
  To: linux-mtd

On Thu, 2003-03-13 at 00:17, David Woodhouse wrote:
> On Wed, 2003-03-12 at 21:43, Steve Wahl wrote:
> 
> > Note that cfiflash below does not handle interleave nor bit
> > endianness, so you can't adopt it directly.
> 
> And under what licence is it available?

here is some GPL code written by someone who's never looked at the AMD
code (until the previous email)

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/blob/blob/src/blob/amd32.c?rev=1.6&content-type=text/vnd.viewcvs-markup

its a little complex because it handles two chips in an interleaved
configuration.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 16:27 ` Steve Wahl
  2003-03-12 17:12   ` John Burch
@ 2003-03-17 15:40   ` Thayne Harbaugh
  2003-03-17 18:38     ` Thayne Harbaugh
  1 sibling, 1 reply; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-17 15:40 UTC (permalink / raw)
  To: linux-mtd

--=-64s8WUTVLomH51lxT+h7
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Wed, 2003-03-12 at 09:27, Steve Wahl wrote:
> Thayne,=20
>=20
> I have a patch that I was given permission to check in, but never got
> around to it, that covers a similar "DQ5 raised" problem.

Speaking of never getting around to things - I'm finally replying to
your email.

> I would wager you are running into the same problem I did, and that
> your chips compatibly support DQ5, if not as a watchdog, at least by
> holding it low while programming.

I have sent email to PMC and the official response is that the _only_
bits that reflect erase/write operation status are I/O7 and I/O6
(effectively DQ7 and DQ6).  I/O7 is inverted data during the operation
and I/O6 toggles.  The PMC response was that AMD status bits aren't
supported.  In practice, however, DQ5 is low during erase/write
operations.  I am uneasy about using undocumented features.

> Can you look at my previous posts on this, try my patch (if you don't
> have interleaved chips -- contact me if you do),

No, I don't have interleaved chips.

> and see if it works
> for you?
>=20
> http://lists.infradead.org/pipermail/linux-mtd/2003-January/006780.html

I have looked through your patch and agree that it addresses a legal
state that currently triggers a warning and should not.  I do know,
however, that several manufactures recommend that the final status
should be checked an additional two times before a success is reported.

> --> Steve
>=20
>=20
> On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> > For some reason I am confused: I get the feeling that what I'm trying t=
o
> > understand is obvious - I just can't see the forest for the trees.  Wil=
l
> > someone help me understand?
> >=20
> > cfi_cmdset_0002.c has several functions that use dq5 and dq6 for
> > monitoring the status of erase and write operations:
> >=20
> > dq6 =3D CMD(1<<6);
> > dq5 =3D CMD(1<<5);
> >=20
> > Apparently, from the code dq6 toggles during erase/read operations and
> > dq5 is low until the erase/read operation times out and then goes high
> > (somewhat like a watchdog bit).
> >=20
> > My understanding, at least for the SST 49LF040 and PMC Pm49L004 is that
> > dq6 toggles during erase/write and dq7 is inverted until the erase/writ=
e
> > operation completes.  This causes me to expect to see the following cod=
e
> > rather than what is written above (not to mention that most everything
> > in do_write_one_word() should be adapted for dq7 invert):
> >=20
> > dq7 =3D CMD(1<<7); /* invert */
> > dq6 =3D CMD(1<<6); /* toggle */
> >=20
> > The differences give me the feeling that there really are two different
> > classes of cfi_cmdset_0002 - those devices that have a dq5 watchdog and
> > those devices that don't have the watchdog, but have a bit inverter on
> > dq7.
> >=20
> > Am I not understanding what happens on bits 0-5 during an erase/write
> > operation?  The PMC and SST chips don't mention a thing about dq5
> > behavior.  If they don't have the dq5 watchdog timer then they will
> > behave in an undefined way (depending on the state of bit 5 in the
> > written word) with the current dq5 checking.  This explains the many
> > warnings I see with the SST and PMC chips in do_write_oneword(),
> >=20
> > "Warning: DQ5 raised while program operation was in progress, however
> > operation completed OK"
> >=20
> > Around here we refer to this as the "Dairy Queen 5" warning.
> >=20
> > Obviosly, during an erase that completes prior to dq5 being read-back,
> > dq5 will be high and the current algorithm is erroneously correct.  Thi=
s
> > can explain why I have not seen the same message in do_erase_oneblock()=
.
> >=20
> > Furthermore, the SST documentation on page 10 refers to "spurios
> > rejection" of good writes - differentiating between a write that
> > succeeds that appears to fail and a write that fails.  It says that a
> > write that appears to fail needs to be read back two more times
> > successfully to filter out spurious rejection.
> >=20
> > Comments?  What should change to improve the operation completion
> > check?  Should cfi_cmdset_0002 be adapted to handle multiple types of
> > polling or should another command set be written?
> >=20
> > --=20
> > Thayne Harbaugh
> > Linux Networx
>=20
>=20
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--=20
Thayne Harbaugh
Linux Networx

--=-64s8WUTVLomH51lxT+h7
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+dexufsBPTKE6HMkRAlp6AJ9GWe9I6x7WezK4AZrXLAwosBiwTwCfZQfj
ZOyJRWSWhmCLtdF4/kk084o=
=637Y
-----END PGP SIGNATURE-----

--=-64s8WUTVLomH51lxT+h7--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-12 21:43     ` Steve Wahl
  2003-03-12 22:17       ` John Burch
  2003-03-13  7:17       ` David Woodhouse
@ 2003-03-17 15:54       ` Thayne Harbaugh
  2003-03-17 16:09         ` John Burch
  2003-03-17 16:19         ` Steve Wahl
  2 siblings, 2 replies; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-17 15:54 UTC (permalink / raw)
  To: linux-mtd

--=-cETyYQUhDowe+f8spAYE
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Wed, 2003-03-12 at 14:43, Steve Wahl wrote:
> On Wed, Mar 12, 2003 at 12:12:12PM -0500, John Burch wrote:

<snip>

> > The status register (including DQ5) won't reflect actual data until
> > a reset command is issued,
>=20
> This I think is a misunderstanding or misstatement on your part.  The
> reads WILL return to actual data without a reset upon successful
> completion of the operation.  Only on a failure does software need to
> issue the reset to return to reading data!

Big question: how is it know if status bits are being read or the real
data that was written to an address?  I have read many data sheets and I
don't recall any of them discussing this concern.

> --> Steve
>=20
> > John
> >=20
> > >From AMD's cfiflash.c:
> >=20
> > /*********************************************************************/
> > /* Flash_status utilizes the DQ6, DQ5, and DQ3 polling algorithms    */
> > /* described in the flash data book.  It can quickly ascertain the   */
> > /* operational status of the flash device, and return an             */
> > /* appropriate status code (defined in flash.h)                      */
> > /*********************************************************************/
> > =20
> > int flash_status(word far *fp)
> > {
> > 	 unsigned char d, t;
> > 	 int retry =3D 1;
> >=20
> > again:
> >=20
> > 	 d =3D *fp;        /* read data */
> > 	 t =3D d ^ *fp;    /* read it again and see what toggled */
> >=20
> > 	 if (t =3D=3D 0) {           /* no toggles, nothing's happening */
> > 		return STATUS_READY;
> > 	 }
> > 	 else if (t =3D=3D 0x04) { /* erase-suspend */
> > 		if (retry--) goto again;    /* may have been write
> > completion */
> > 		return STATUS_ERSUSP;
> > 	 }
> > 	 else if (t & 0x40) {
> > 		if (d & 0x20) {     /* timeout */
> > 		  return STATUS_TIMEOUT;
> > 		}
> > 		else {
> > 		  return STATUS_BUSY;
> > 		}
> > 	 }
> >=20
> > 	 if (retry--) goto again;    /* may have been write completion
> > */
> >=20
> > 	 return STATUS_ERROR;
> > }
> >=20
> >=20
> >=20
> > > -----Original Message-----
> > > From: linux-mtd-admin at lists.infradead.org=20
> > > [mailto:linux-mtd-admin at lists.infradead.org] On Behalf Of Steve Wahl
> > > Sent: Wednesday, March 12, 2003 11:28 AM
> > > To: Thayne Harbaugh
> > > Cc: linux-mtd at lists.infradead.org
> > > Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy=20
> > > Queen 5 warning)
> > >=20
> > >=20
> > > Thayne,=20
> > >=20
> > > I have a patch that I was given permission to check in, but=20
> > > never got around to it, that covers a similar "DQ5 raised" problem.
> > >=20
> > > I would wager you are running into the same problem I did,=20
> > > and that your chips compatibly support DQ5, if not as a=20
> > > watchdog, at least by holding it low while programming.
> > >=20
> > > Can you look at my previous posts on this, try my patch (if=20
> > > you don't have interleaved chips -- contact me if you do),=20
> > > and see if it works for you?
> > >=20
> > > http://lists.infradead.org/pipermail/linux-mtd/2003-January/00
> > > 6780.html
> > >=20
> > > --> Steve
> > >=20
> > >=20
> > > On Tue, Mar 11, 2003 at 05:25:15PM -0700, Thayne Harbaugh wrote:
> > > > For some reason I am confused: I get the feeling that what=20
> > > I'm trying=20
> > > > to understand is obvious - I just can't see the forest for=20
> > > the trees. =20
> > > > Will someone help me understand?
> > > >=20
> > > > cfi_cmdset_0002.c has several functions that use dq5 and dq6 for=20
> > > > monitoring the status of erase and write operations:
> > > >=20
> > > > dq6 =3D CMD(1<<6);
> > > > dq5 =3D CMD(1<<5);
> > > >=20
> > > > Apparently, from the code dq6 toggles during erase/read=20
> > > operations and=20
> > > > dq5 is low until the erase/read operation times out and=20
> > > then goes high=20
> > > > (somewhat like a watchdog bit).
> > > >=20
> > > > My understanding, at least for the SST 49LF040 and PMC Pm49L004 is=20
> > > > that dq6 toggles during erase/write and dq7 is inverted until the=20
> > > > erase/write operation completes.  This causes me to expect=20
> > > to see the=20
> > > > following code rather than what is written above (not to=20
> > > mention that=20
> > > > most everything in do_write_one_word() should be adapted for dq7=20
> > > > invert):
> > > >=20
> > > > dq7 =3D CMD(1<<7); /* invert */
> > > > dq6 =3D CMD(1<<6); /* toggle */
> > > >=20
> > > > The differences give me the feeling that there really are two=20
> > > > different classes of cfi_cmdset_0002 - those devices that=20
> > > have a dq5=20
> > > > watchdog and those devices that don't have the watchdog, but have a=
=20
> > > > bit inverter on dq7.
> > > >=20
> > > > Am I not understanding what happens on bits 0-5 during an=20
> > > erase/write=20
> > > > operation?  The PMC and SST chips don't mention a thing about dq5=20
> > > > behavior.  If they don't have the dq5 watchdog timer then they will=
=20
> > > > behave in an undefined way (depending on the state of bit 5 in the=20
> > > > written word) with the current dq5 checking.  This explains=20
> > > the many=20
> > > > warnings I see with the SST and PMC chips in do_write_oneword(),
> > > >=20
> > > > "Warning: DQ5 raised while program operation was in=20
> > > progress, however=20
> > > > operation completed OK"
> > > >=20
> > > > Around here we refer to this as the "Dairy Queen 5" warning.
> > > >=20
> > > > Obviosly, during an erase that completes prior to dq5 being=20
> > > read-back,=20
> > > > dq5 will be high and the current algorithm is erroneously correct. =
=20
> > > > This can explain why I have not seen the same message in=20
> > > > do_erase_oneblock().
> > > >=20
> > > > Furthermore, the SST documentation on page 10 refers to "spurios=20
> > > > rejection" of good writes - differentiating between a write that=20
> > > > succeeds that appears to fail and a write that fails.  It=20
> > > says that a=20
> > > > write that appears to fail needs to be read back two more times=20
> > > > successfully to filter out spurious rejection.
> > > >=20
> > > > Comments?  What should change to improve the operation completion=20
> > > > check?  Should cfi_cmdset_0002 be adapted to handle=20
> > > multiple types of=20
> > > > polling or should another command set be written?
> > > >=20
> > > > --
> > > > Thayne Harbaugh
> > > > Linux Networx
> > >=20
> > >=20
> > >=20
> > > ______________________________________________________
> > > Linux MTD discussion mailing list
> > > http://lists.infradead.org/mailman/listinfo/linux-mtd/
> > >=20
>=20
>=20
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--=20
Thayne Harbaugh
Linux Networx

--=-cETyYQUhDowe+f8spAYE
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+de+tfsBPTKE6HMkRAjjgAJ9QETLlxInaPZtW4W/5BY3vz7dU8ACfTnFo
tZfaspvL/3AAR1ebfrQDwjU=
=pFkZ
-----END PGP SIGNATURE-----

--=-cETyYQUhDowe+f8spAYE--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 15:54       ` Thayne Harbaugh
@ 2003-03-17 16:09         ` John Burch
  2003-03-17 16:19         ` Steve Wahl
  1 sibling, 0 replies; 20+ messages in thread
From: John Burch @ 2003-03-17 16:09 UTC (permalink / raw)
  To: linux-mtd


> -----Original Message-----
> From: Thayne Harbaugh [mailto:tharbaugh at lnxi.com]=20
> Sent: Monday, March 17, 2003 10:54 AM
> To: Steve Wahl
> Cc: John Burch; linux-mtd at lists.infradead.org
> Subject: Re: DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy=20
> Queen 5 warning)
>=20
<snip>
>=20
>=20
> Big question: how is it know if status bits are being read or=20
> the real data that was written to an address?  I have read=20
> many data sheets and I don't recall any of them discussing=20
> this concern.

I believe that if DQ6 is not toggling, then you're reading
actual data.  If DQ6 is toggling and DQ5=3D0, then you're reading
Status and the device is still busy.  If DQ6 is toggling and DQ5=3D1,
You're still reading status and DQ6 must be checked again.
If toggling, operation timed out, you're still reading status, and
reset command must be issued. If not toggling, operation completed,
and you're reading data.  (At least this is how AMD describes it.)

John

<snip>

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 15:54       ` Thayne Harbaugh
  2003-03-17 16:09         ` John Burch
@ 2003-03-17 16:19         ` Steve Wahl
  2003-03-17 18:27           ` Thayne Harbaugh
  1 sibling, 1 reply; 20+ messages in thread
From: Steve Wahl @ 2003-03-17 16:19 UTC (permalink / raw)
  To: linux-mtd

On Mon, Mar 17, 2003 at 08:54:21AM -0700, Thayne Harbaugh wrote:
> On Wed, 2003-03-12 at 14:43, Steve Wahl wrote:
> > On Wed, Mar 12, 2003 at 12:12:12PM -0500, John Burch wrote:
> 
> <snip>
> 
> > > The status register (including DQ5) won't reflect actual data until
> > > a reset command is issued,
> > 
> > This I think is a misunderstanding or misstatement on your part.  The
> > reads WILL return to actual data without a reset upon successful
> > completion of the operation.  Only on a failure does software need to
> > issue the reset to return to reading data!
> 
> Big question: how is it know if status bits are being read or the real
> data that was written to an address?  I have read many data sheets and I
> don't recall any of them discussing this concern.

Easy, at least in theory.  If two consecutive reads are the same, then
the DQ6 isn't toggling any longer, therfore you are reading data.

Only if the two consecutive reads are different can you assume that
you read the status register -- and you can only assume the FIRST read
was a status register, because the second read could have been after
changing to data mode.

But, outside of easy theories, there's a couple of gotchas in there.

I've read at least one data sheet that suggested that the switch from
the status register to the data "register" happens asyncronously to
processor reads, so it is possible, though very unlikely, to get some
bits from the status register and some bits from the actual data
within a single read -- if the read happens at the exact instance that
the chip is switching from one mode to the other.

I have never seen any code that takes this into account -- sample
code, data sheet flow charts, etc.  I think this may, however, have
something to do with what you wrote: "I do know, however, that several
manufactures recommend that the final status should be checked an
additional two times before a success is reported."  I'd be interested
to see specific data sheets or application notes that do this.


--> Steve

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 16:19         ` Steve Wahl
@ 2003-03-17 18:27           ` Thayne Harbaugh
  2003-03-18 16:51             ` Steve Wahl
  0 siblings, 1 reply; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-17 18:27 UTC (permalink / raw)
  To: linux-mtd

--=-EvrZnUndJESZ8BzsyWWf
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Mon, 2003-03-17 at 09:19, Steve Wahl wrote:
> On Mon, Mar 17, 2003 at 08:54:21AM -0700, Thayne Harbaugh wrote:

<snip>

> > I do know, however, that several
> > manufactures recommend that the final status should be checked an
> > additional two times before a success is reported.


> I'd be interested
> to see specific data sheets or application notes that do this.

What I stated is not completely accurate.  Here is what SST states on
page 14 of _4_Mbit_LPC_Flash_SST49LF040_ in the Write Operation Status
Detection section:

The actual completion of the nonvolatile write is asynchronous with the
system; therefore, either a Data# Palling or Toggle Bit read may be
simultaneous with the completion of the Write cycle.  If this occurs,
the system may possibly get an erroneous result, i.e., valid data may
appear to conflict with either DQ7 or DQ6.  In order to prevent spurious
rejection, if an erroneous result occurs, the software routine should
include a loop to read the accessed location an additional two (2)
times.  If both reads are valid, then the device has completed the Write
cycle, otherwise the rejection is valid.



>=20
>=20
> --> Steve
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--=20
Thayne Harbaugh
Linux Networx

--=-EvrZnUndJESZ8BzsyWWf
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+dhOdfsBPTKE6HMkRAs74AJ9ehcvP2+OOFJETNselB5iIHK0fjwCdE2Z9
J0NvOYO2El7enuc/AoHNxA0=
=wDoQ
-----END PGP SIGNATURE-----

--=-EvrZnUndJESZ8BzsyWWf--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 15:40   ` Thayne Harbaugh
@ 2003-03-17 18:38     ` Thayne Harbaugh
  2003-03-19  0:23       ` Thayne Harbaugh
  0 siblings, 1 reply; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-17 18:38 UTC (permalink / raw)
  To: linux-mtd

--=-S5ixrRaefhmMdHKqH2Zj
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Mon, 2003-03-17 at 08:40, Thayne Harbaugh wrote:
> On Wed, 2003-03-12 at 09:27, Steve Wahl wrote:

<snip>

> > I would wager you are running into the same problem I did, and that
> > your chips compatibly support DQ5, if not as a watchdog, at least by
> > holding it low while programming.
>=20
> I have sent email to PMC and the official response is that the _only_
> bits that reflect erase/write operation status are I/O7 and I/O6
> (effectively DQ7 and DQ6).  I/O7 is inverted data during the operation
> and I/O6 toggles.  The PMC response was that AMD status bits aren't
> supported.  In practice, however, DQ5 is low during erase/write
> operations.  I am uneasy about using undocumented features.

I have been thinking about the above mentioned problem with DQ5.  I have
not seen DQ5 behavior documented in the SST49LF040 and Pm49FL00x
documentation and suspect that other chip documentation is similar. =20

Regardless of the current behavior of status bit 5 on these chips I
think the documentation should be followed.  This means that either the
cfi_cmdset_0002 driver needs to be adapted to work with the "simplified"
polling in _addition_ to the current polling of DQ5 (some switch is
added to poll correctly for a given device) or a new cfi_cmdset_xxxx is
written specifically for this simplified command set.

I'm not sure what would be a nice, clean way to switch polling
mechanisms, but I hesitate to duplicate code for a nearly identical
cfi_cmdset.

Thoughts?

--=20
Thayne Harbaugh
Linux Networx

--=-S5ixrRaefhmMdHKqH2Zj
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+dhYufsBPTKE6HMkRAipjAJ4iuyS+8gP8U0aVZGF6w6e8UpremgCeLWIv
U/MGKz16uCV6QGXIdA6tzfQ=
=SbBb
-----END PGP SIGNATURE-----

--=-S5ixrRaefhmMdHKqH2Zj--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 18:27           ` Thayne Harbaugh
@ 2003-03-18 16:51             ` Steve Wahl
  2003-03-18 17:22               ` Thayne Harbaugh
  0 siblings, 1 reply; 20+ messages in thread
From: Steve Wahl @ 2003-03-18 16:51 UTC (permalink / raw)
  To: linux-mtd

On Mon, Mar 17, 2003 at 11:27:41AM -0700, Thayne Harbaugh wrote:
> On Mon, 2003-03-17 at 09:19, Steve Wahl wrote:
> > On Mon, Mar 17, 2003 at 08:54:21AM -0700, Thayne Harbaugh wrote:
> 
> <snip>
> 
> > > I do know, however, that several
> > > manufactures recommend that the final status should be checked an
> > > additional two times before a success is reported.
> 
> 
> > I'd be interested
> > to see specific data sheets or application notes that do this.
> 
> What I stated is not completely accurate.  Here is what SST states on
> page 14 of _4_Mbit_LPC_Flash_SST49LF040_ in the Write Operation Status
> Detection section:
> 
> The actual completion of the nonvolatile write is asynchronous with the
> system; therefore, either a Data# Palling or Toggle Bit read may be
> simultaneous with the completion of the Write cycle.  If this occurs,
> the system may possibly get an erroneous result, i.e., valid data may
> appear to conflict with either DQ7 or DQ6.  In order to prevent spurious
> rejection, if an erroneous result occurs, the software routine should
> include a loop to read the accessed location an additional two (2)
> times.  If both reads are valid, then the device has completed the Write
> cycle, otherwise the rejection is valid.

Ahh.  If I read this correctly, if you are about to report an error
you should read two more times to make sure it's still there.

So your original wording should be "the final status should be checked
an additional two times before a *failure* is reported."  You could
legally / reasonably report success the instant you detect it.

Do you agree?

It is somewhat funny that if this was followed, I wouldn't have run
into the "DQ5 detected, but things seem OK" warning (can't remember
the original wording, sorry). 

--> Steve

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-18 16:51             ` Steve Wahl
@ 2003-03-18 17:22               ` Thayne Harbaugh
  0 siblings, 0 replies; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-18 17:22 UTC (permalink / raw)
  To: linux-mtd

--=-WR4q0zDjS2E9vaYtdMRV
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Tue, 2003-03-18 at 09:51, Steve Wahl wrote:
> On Mon, Mar 17, 2003 at 11:27:41AM -0700, Thayne Harbaugh wrote:
> > On Mon, 2003-03-17 at 09:19, Steve Wahl wrote:
> > > On Mon, Mar 17, 2003 at 08:54:21AM -0700, Thayne Harbaugh wrote:
> >=20
> > <snip>
> >=20
> > > > I do know, however, that several
> > > > manufactures recommend that the final status should be checked an
> > > > additional two times before a success is reported.
> >=20
> >=20
> > > I'd be interested
> > > to see specific data sheets or application notes that do this.
> >=20
> > What I stated is not completely accurate.  Here is what SST states on
> > page 14 of _4_Mbit_LPC_Flash_SST49LF040_ in the Write Operation Status
> > Detection section:
> >=20
> > The actual completion of the nonvolatile write is asynchronous with the
> > system; therefore, either a Data# Palling or Toggle Bit read may be
> > simultaneous with the completion of the Write cycle.  If this occurs,
> > the system may possibly get an erroneous result, i.e., valid data may
> > appear to conflict with either DQ7 or DQ6.  In order to prevent spuriou=
s
> > rejection, if an erroneous result occurs, the software routine should
> > include a loop to read the accessed location an additional two (2)
> > times.  If both reads are valid, then the device has completed the Writ=
e
> > cycle, otherwise the rejection is valid.
>=20
> Ahh.  If I read this correctly, if you are about to report an error
> you should read two more times to make sure it's still there.
>=20
> So your original wording should be "the final status should be checked
> an additional two times before a *failure* is reported."  You could
> legally / reasonably report success the instant you detect it.
>=20
> Do you agree?

Yes, that's exactly how I interpret it after re-reading it.  I have seen
this statement in more than one vendor's documentation.  This is also
the way I am writing my AMD simplified command set driver.

The part that I still scratch my head about is why it needs to read
correctly on _both_ reads.  Why is it not good enough to have success on
the last read?

> It is somewhat funny that if this was followed, I wouldn't have run
> into the "DQ5 detected, but things seem OK" warning (can't remember
> the original wording, sorry).=20

Yes, that would have eliminated the error.

>=20
> --> Steve
--=20
Thayne Harbaugh
Linux Networx

--=-WR4q0zDjS2E9vaYtdMRV
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+d1XpfsBPTKE6HMkRAuNKAJ9QKThjRWAbE7yrOqbSS9ojRPUA9wCfSvOl
uxoA+QJng3T5UgutVXIem2c=
=r7zg
-----END PGP SIGNATURE-----

--=-WR4q0zDjS2E9vaYtdMRV--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-17 18:38     ` Thayne Harbaugh
@ 2003-03-19  0:23       ` Thayne Harbaugh
  2003-03-19 15:56         ` Steve Wahl
  0 siblings, 1 reply; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-19  0:23 UTC (permalink / raw)
  To: linux-mtd

--=-RZKiLm5gawTslA20lq2l
Content-Type: multipart/mixed; boundary="=-YdlygX9g8mw3u7YELU6q"


--=-YdlygX9g8mw3u7YELU6q
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Mon, 2003-03-17 at 11:38, Thayne Harbaugh wrote:

> I have been thinking about the above mentioned problem with DQ5.  I have
> not seen DQ5 behavior documented in the SST49LF040 and Pm49FL00x
> documentation and suspect that other chip documentation is similar.

I wonder if this DQ5 for non suspend/resume chips is documented in
JESD21C.  Does anyone know or ever have an idea where to begin digging
through all the JEDEC meeting notes, etc.?

> Regardless of the current behavior of status bit 5 on these chips I
> think the documentation should be followed.

It's just plain dangerous to follow non-documented behavior.

>   This means that either the
> cfi_cmdset_0002 driver needs to be adapted to work with the "simplified"
> polling in _addition_ to the current polling of DQ5 (some switch is
> added to poll correctly for a given device) or a new cfi_cmdset_xxxx is
> written specifically for this simplified command set.
>=20
> I'm not sure what would be a nice, clean way to switch polling
> mechanisms, but I hesitate to duplicate code for a nearly identical
> cfi_cmdset.

I have worked up a patch that adds a new cfi_cmdset to the mix.  This is
for devices that support a subset or a simplified AMD command set
without the suspend/resume commands and extra query bits.

I feel it's good because I don't feel comfortable trusting the behavior
of DQ5 being low during erase/write operations for devices that don't
support DQ5 and have undocumented behavior for bits other than DQ7 and
DQ6.  It throws out suspend and resume functions and polls exclusively
on DQ7 and DQ6.

I have called this a simplified AMD commandset (ugly name - give me
something better) and have pulled cfi_cmdset_0005 out of the hat (I'm
not sure how the command set numbers are chosen).

Jedec devices listed in jedec_probe.c:jedec_table[] that don't support
suspend resume are marked as P_ID_AMD_SIMPLIFIED (new entry in cfi.h).

I'm not sure why gen_probe.c/check_cmd_set() uses the hex numbers in the
switch statement rather than the P_ID_* #define's from cfi.h - I used
the #define.

  It likely could be simplified even more - take out feeble support for
interleaved chips (which I don't have and can't test and I'm not even
sure that the chips that work this way support interleaving).

Sometimes I wish all of the command sets shared more code - other times
I'm glad they are split.

Should I commit it to CVS?  It works for me(TM).

> Thoughts?

Sorry to reply to myself - I talk back to myself as well.

I still think that the current cfi_cmdset_0002.c needs a fix similar to
what Steve Wahl proposed.  Has that settled and will it be committed?

--=20
Thayne Harbaugh
Linux Networx

--=-YdlygX9g8mw3u7YELU6q
Content-Disposition: attachment; filename=mtd-amd_simplified.patch
Content-Type: text/x-patch; name=mtd-amd_simplified.patch; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

diff -uNr mtd/drivers/mtd/chips/cfi_cmdset_0005.c mtd-amd_simplified/driver=
s/mtd/chips/cfi_cmdset_0005.c
--- mtd/drivers/mtd/chips/cfi_cmdset_0005.c	1969-12-31 17:00:00.000000000 -=
0700
+++ mtd-amd_simplified/drivers/mtd/chips/cfi_cmdset_0005.c	2003-03-18 16:51=
:05.000000000 -0700
@@ -0,0 +1,1027 @@
+/*
+ * Common Flash Interface support:
+ *   AMD Simplified command set (ID 0x0005)
+ *
+ * Copyright (C) 2000 Crossnet Co. <info@crossnet.co.jp>
+ * Copyright (C) 2003 Linux Networx - adapted to AMD simplified
+ *     command set by Thayne Harbaugh.  This is nearly the same
+ *     as cfi_cmdset_0002 except for the polling mechanism for
+ *     erase/write operations and the removal of extra
+ *     functionality: erase suspend and resume.  Ideally this and
+ *     cfi_cmdset_0002 should share as much as possible.
+ *
+ * Although this looks like it was written for interleaved chips,
+ *     it has never been tested.  Ise at your own risk and send
+ *     in the patches.
+ *
+ * This code is GPL
+ *
+ * $Id$
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <asm/io.h>
+#include <asm/byteorder.h>
+
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/cfi.h>
+
+
+static int cfi_amdsmpl_read (struct mtd_info *, loff_t, size_t, size_t *, =
u_char *);
+static int cfi_amdsmpl_write(struct mtd_info *, loff_t, size_t, size_t *, =
const u_char *);
+static int cfi_amdsmpl_erase_onesize(struct mtd_info *, struct erase_info =
*);
+static int cfi_amdsmpl_erase_varsize(struct mtd_info *, struct erase_info =
*);
+static void cfi_amdsmpl_sync (struct mtd_info *);
+static int cfi_amdsmpl_secsi_read (struct mtd_info *, loff_t, size_t, size=
_t *, u_char *);
+
+static void cfi_amdsmpl_destroy(struct mtd_info *);
+
+struct mtd_info *cfi_cmdset_0005(struct map_info *, int);
+static struct mtd_info *cfi_amdsmpl_setup (struct map_info *);
+
+
+static struct mtd_chip_driver cfi_amdsmpl_chipdrv =3D {
+	probe: NULL, /* Not usable directly */
+	destroy: cfi_amdsmpl_destroy,
+	name: "cfi_cmdset_0005",
+	module: THIS_MODULE
+};
+
+struct mtd_info *cfi_cmdset_0005(struct map_info *map, int primary)
+{
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	unsigned char bootloc;
+	int ofs_factor =3D cfi->interleave * cfi->device_type;
+	int i;
+	__u8 major, minor;
+	__u32 base =3D cfi->chips[0].start;
+
+	if (cfi->cfi_mode=3D=3DCFI_MODE_CFI){
+		__u16 adr =3D primary?cfi->cfiq->P_ADR:cfi->cfiq->A_ADR;
+
+		cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+	=09
+		major =3D cfi_read_query(map, base + (adr+3)*ofs_factor);
+		minor =3D cfi_read_query(map, base + (adr+4)*ofs_factor);
+	=09
+		printk(KERN_NOTICE " Amd/Fujitsu Extended Query Table v%c.%c at 0x%4.4X\=
n",
+		       major, minor, adr);
+				cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
+	=09
+		cfi_send_gen_cmd(0xaa, 0x555, base, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x55, 0x2aa, base, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x90, 0x555, base, map, cfi, cfi->device_type, NULL);
+		cfi->mfr =3D cfi_read_query(map, base);
+		cfi->id =3D cfi_read_query(map, base + ofs_factor);   =20
+
+		/* Wheee. Bring me the head of someone at AMD. */
+		cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
+		bootloc =3D cfi_read_query(map, base + (adr+15)*ofs_factor);
+		if (bootloc =3D=3D 3 && cfi->cfiq->NumEraseRegions > 1) {
+			printk(KERN_WARNING "%s: Swapping erase regions for broken CFI table.\n=
", map->name);
+		=09
+			for (i=3D0; i<cfi->cfiq->NumEraseRegions / 2; i++) {
+				int j =3D (cfi->cfiq->NumEraseRegions-1)-i;
+				__u32 swap;
+			=09
+				swap =3D cfi->cfiq->EraseRegionInfo[i];
+				cfi->cfiq->EraseRegionInfo[i] =3D cfi->cfiq->EraseRegionInfo[j];
+				cfi->cfiq->EraseRegionInfo[j] =3D swap;
+			}
+		}
+		switch (cfi->device_type) {
+		case CFI_DEVICETYPE_X8:
+			cfi->addr_unlock1 =3D 0x555;=20
+			cfi->addr_unlock2 =3D 0x2aa;=20
+			break;
+		case CFI_DEVICETYPE_X16:
+			cfi->addr_unlock1 =3D 0xaaa;
+			if (map->buswidth =3D=3D cfi->interleave) {
+				/* X16 chip(s) in X8 mode */
+				cfi->addr_unlock2 =3D 0x555;
+			} else {
+				cfi->addr_unlock2 =3D 0x554;
+			}
+			break;
+		case CFI_DEVICETYPE_X32:
+			cfi->addr_unlock1 =3D 0x1555;=20
+			cfi->addr_unlock2 =3D 0xaaa;=20
+			break;
+		default:
+			printk(KERN_NOTICE "Eep. Unknown cfi_cmdset_0005 device type %d\n", cfi=
->device_type);
+			return NULL;
+		}
+	} /* CFI mode */
+
+	for (i=3D0; i< cfi->numchips; i++) {
+		cfi->chips[i].word_write_time =3D 1<<cfi->cfiq->WordWriteTimeoutTyp;
+		cfi->chips[i].buffer_write_time =3D 1<<cfi->cfiq->BufWriteTimeoutTyp;
+		cfi->chips[i].erase_time =3D 1<<cfi->cfiq->BlockEraseTimeoutTyp;
+	}	=09
+=09
+	map->fldrv =3D &cfi_amdsmpl_chipdrv;
+
+	cfi_send_gen_cmd(0xf0, 0x55, base, map, cfi, cfi->device_type, NULL);
+	return cfi_amdsmpl_setup(map);
+}
+
+static struct mtd_info *cfi_amdsmpl_setup(struct map_info *map)
+{
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	struct mtd_info *mtd;
+	unsigned long devsize =3D (1<<cfi->cfiq->DevSize) * cfi->interleave;
+
+	mtd =3D kmalloc(sizeof(*mtd), GFP_KERNEL);
+	printk(KERN_NOTICE "number of %s chips: %d\n",=20
+		(cfi->cfi_mode =3D=3D CFI_MODE_CFI)?"CFI":"JEDEC",cfi->numchips);
+
+	if (!mtd) {
+	  printk(KERN_WARNING "Failed to allocate memory for MTD device\n");
+	  goto setup_err;
+	}
+
+	memset(mtd, 0, sizeof(*mtd));
+	mtd->priv =3D map;
+	mtd->type =3D MTD_NORFLASH;
+	/* Also select the correct geometry setup too */=20
+	mtd->size =3D devsize * cfi->numchips;
+=09
+	if (cfi->cfiq->NumEraseRegions =3D=3D 1) {
+		/* No need to muck about with multiple erase sizes */
+		mtd->erasesize =3D ((cfi->cfiq->EraseRegionInfo[0] >> 8) & ~0xff) * cfi-=
>interleave;
+	} else {
+		unsigned long offset =3D 0;
+		int i,j;
+
+		mtd->numeraseregions =3D cfi->cfiq->NumEraseRegions * cfi->numchips;
+		mtd->eraseregions =3D kmalloc(sizeof(struct mtd_erase_region_info) * mtd=
->numeraseregions, GFP_KERNEL);
+		if (!mtd->eraseregions) {=20
+			printk(KERN_WARNING "Failed to allocate memory for MTD erase region inf=
o\n");
+			goto setup_err;
+		}
+		=09
+		for (i=3D0; i<cfi->cfiq->NumEraseRegions; i++) {
+			unsigned long ernum, ersize;
+			ersize =3D ((cfi->cfiq->EraseRegionInfo[i] >> 8) & ~0xff) * cfi->interl=
eave;
+			ernum =3D (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1;
+		=09
+			if (mtd->erasesize < ersize) {
+				mtd->erasesize =3D ersize;
+			}
+			for (j=3D0; j<cfi->numchips; j++) {
+				mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].offset =3D (j*devs=
ize)+offset;
+				mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].erasesize =3D ersi=
ze;
+				mtd->eraseregions[(j*cfi->cfiq->NumEraseRegions)+i].numblocks =3D ernu=
m;
+			}
+			offset +=3D (ersize * ernum);
+		}
+		if (offset !=3D devsize) {
+			/* Argh */
+			printk(KERN_WARNING "Sum of regions (%lx) !=3D total size of set of int=
erleaved chips (%lx)\n", offset, devsize);
+			goto setup_err;
+		}
+#if 0
+		// debug
+		for (i=3D0; i<mtd->numeraseregions;i++){
+			printk("%d: offset=3D0x%x,size=3D0x%x,blocks=3D%d\n",
+			       i,mtd->eraseregions[i].offset,
+			       mtd->eraseregions[i].erasesize,
+			       mtd->eraseregions[i].numblocks);
+		}
+#endif
+	}
+
+	switch (CFIDEV_BUSWIDTH)
+	{
+	case 1:
+	case 2:
+	case 4:
+#if 1
+		if (mtd->numeraseregions > 1)
+			mtd->erase =3D cfi_amdsmpl_erase_varsize;
+		else
+#endif
+			mtd->erase =3D cfi_amdsmpl_erase_onesize;
+		mtd->read =3D cfi_amdsmpl_read;
+		mtd->write =3D cfi_amdsmpl_write;
+		break;
+
+	default:
+	        printk(KERN_WARNING "Unsupported buswidth\n");
+		goto setup_err;
+		break;
+	}
+	if (cfi->fast_prog) {
+		/* In cfi_amdsmpl_write() we frob the protection stuff
+		   without paying any attention to the state machine.
+		   This upsets in-progress erases. So we turn this flag
+		   off for now till the code gets fixed. */
+		printk(KERN_NOTICE "cfi_cmdset_0005: Disabling fast programming due to c=
ode brokenness.\n");
+		cfi->fast_prog =3D 0;
+	}
+
+
+        /* does this chip have a secsi area? */
+	if(cfi->mfr=3D=3D1){
+	=09
+		switch(cfi->id){
+		case 0x50:
+		case 0x53:
+		case 0x55:
+		case 0x56:
+		case 0x5C:
+		case 0x5F:
+			/* Yes */
+			mtd->read_user_prot_reg =3D cfi_amdsmpl_secsi_read;
+			mtd->read_fact_prot_reg =3D cfi_amdsmpl_secsi_read;
+		default:		      =20
+			;
+		}
+	}
+=09
+	=09
+	mtd->sync =3D cfi_amdsmpl_sync;
+	mtd->suspend =3D NULL;
+	mtd->resume =3D NULL;
+	mtd->flags =3D MTD_CAP_NORFLASH;
+	map->fldrv =3D &cfi_amdsmpl_chipdrv;
+	mtd->name =3D map->name;
+	MOD_INC_USE_COUNT;
+	return mtd;
+
+ setup_err:
+	if(mtd) {
+		if(mtd->eraseregions)
+			kfree(mtd->eraseregions);
+		kfree(mtd);
+	}
+	kfree(cfi->cmdset_priv);
+	kfree(cfi->cfiq);
+	return NULL;
+}
+
+static inline int do_read_onechip(struct map_info *map, struct flchip *chi=
p, loff_t adr, size_t len, u_char *buf)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long timeo =3D jiffies + HZ;
+
+ retry:
+	cfi_spin_lock(chip->mutex);
+
+	if (chip->state !=3D FL_READY){
+#if 0
+	        printk(KERN_DEBUG "Waiting for chip to read, status =3D %d\n", ch=
ip->state);
+#endif
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&chip->wq, &wait);
+               =20
+		cfi_spin_unlock(chip->mutex);
+
+		schedule();
+		remove_wait_queue(&chip->wq, &wait);
+#if 0
+		if(signal_pending(current))
+			return -EINTR;
+#endif
+		timeo =3D jiffies + HZ;
+
+		goto retry;
+	}=09
+
+	adr +=3D chip->start;
+
+	chip->state =3D FL_READY;
+
+	map->copy_from(map, buf, adr, len);
+
+	wake_up(&chip->wq);
+	cfi_spin_unlock(chip->mutex);
+
+	return 0;
+}
+
+static int cfi_amdsmpl_read (struct mtd_info *mtd, loff_t from, size_t len=
, size_t *retlen, u_char *buf)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	unsigned long ofs;
+	int chipnum;
+	int ret =3D 0;
+
+	/* ofs: offset within the first chip that the first read should start */
+
+	chipnum =3D (from >> cfi->chipshift);
+	ofs =3D from - (chipnum <<  cfi->chipshift);
+
+
+	*retlen =3D 0;
+
+	while (len) {
+		unsigned long thislen;
+
+		if (chipnum >=3D cfi->numchips)
+			break;
+
+		if ((len + ofs -1) >> cfi->chipshift)
+			thislen =3D (1<<cfi->chipshift) - ofs;
+		else
+			thislen =3D len;
+
+		ret =3D do_read_onechip(map, &cfi->chips[chipnum], ofs, thislen, buf);
+		if (ret)
+			break;
+
+		*retlen +=3D thislen;
+		len -=3D thislen;
+		buf +=3D thislen;
+
+		ofs =3D 0;
+		chipnum++;
+	}
+	return ret;
+}
+
+static inline int do_read_secsi_onechip(struct map_info *map, struct flchi=
p *chip, loff_t adr, size_t len, u_char *buf)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	unsigned long timeo =3D jiffies + HZ;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+
+ retry:
+	cfi_spin_lock(chip->mutex);
+
+	if (chip->state !=3D FL_READY){
+#if 0
+	        printk(KERN_DEBUG "Waiting for chip to read, status =3D %d\n", ch=
ip->state);
+#endif
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&chip->wq, &wait);
+               =20
+		cfi_spin_unlock(chip->mutex);
+
+		schedule();
+		remove_wait_queue(&chip->wq, &wait);
+#if 0
+		if(signal_pending(current))
+			return -EINTR;
+#endif
+		timeo =3D jiffies + HZ;
+
+		goto retry;
+	}=09
+
+	adr +=3D chip->start;
+
+	chip->state =3D FL_READY;
+=09
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+	cfi_send_gen_cmd(0x88, cfi->addr_unlock1, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+=09
+	map->copy_from(map, buf, adr, len);
+
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+	cfi_send_gen_cmd(0x90, cfi->addr_unlock1, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+	cfi_send_gen_cmd(0x00, cfi->addr_unlock1, chip->start, map, cfi, cfi->dev=
ice_type, NULL);
+=09
+	wake_up(&chip->wq);
+	cfi_spin_unlock(chip->mutex);
+
+	return 0;
+}
+
+static int cfi_amdsmpl_secsi_read (struct mtd_info *mtd, loff_t from, size=
_t len, size_t *retlen, u_char *buf)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	unsigned long ofs;
+	int chipnum;
+	int ret =3D 0;
+
+
+	/* ofs: offset within the first chip that the first read should start */
+
+	/* 8 secsi bytes per chip */
+	chipnum=3Dfrom>>3;
+	ofs=3Dfrom & 7;
+
+
+	*retlen =3D 0;
+
+	while (len) {
+		unsigned long thislen;
+
+		if (chipnum >=3D cfi->numchips)
+			break;
+
+		if ((len + ofs -1) >> 3)
+			thislen =3D (1<<3) - ofs;
+		else
+			thislen =3D len;
+
+		ret =3D do_read_secsi_onechip(map, &cfi->chips[chipnum], ofs, thislen, b=
uf);
+		if (ret)
+			break;
+
+		*retlen +=3D thislen;
+		len -=3D thislen;
+		buf +=3D thislen;
+
+		ofs =3D 0;
+		chipnum++;
+	}
+	return ret;
+}
+
+
+static inline int status_poll( struct map_info *map, struct flchip *chip, =
unsigned long adr, __u32 datum, unsigned long timeo )
+{
+	int ret =3D 0;
+	unsigned int dq6, dq7;=09
+	unsigned int oldstatus, status;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+
+	/*
+	 * Wait for the end of programing/erasure by using the toggle method.
+	 * As long as there is a programming procedure going on, bit 6 of the las=
t
+	 * written byte is toggling it's state with each consectuve read and
+	 * bit 7 is the complement of the data written.
+	 * The toggling stops as soon as the procedure is completed and bit
+	 * 7 represents true data.
+	 */
+
+	/*
+	 * Polling toggle bits instead of reading back many times
+	 * This ensures that write operation is really completed,
+	 */
+	dq6 =3D CMD(1<<6);     /* toggle until operation finishes */
+	dq7 =3D CMD(1<<7);     /* inverts data until operation finishes */
+
+	oldstatus =3D cfi_read(map, adr);
+	status =3D cfi_read(map, adr);
+	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.2x 0x%.2x\n", __func__, old=
status, status );
+
+	while( ( ( oldstatus ^ status ) & dq6 )
+	       && ( ( status ^ datum ) & dq7 )
+	       && ! time_after(jiffies, timeo) ) {
+
+		if (need_resched()) {
+			cfi_spin_unlock(chip->mutex);
+			yield();
+			cfi_spin_lock(chip->mutex);
+		} else=20
+			udelay(1);
+
+		oldstatus =3D cfi_read( map, adr );
+		status =3D cfi_read( map, adr );
+		DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.2x 0x%.2x\n", __func__, ol=
dstatus, status );
+	}
+
+	if ( time_after( jiffies, timeo ) ) {
+		/*
+		 * The operation did not complete in reasonable time - the
+		 * chip should be reset.
+		 */
+		printk(KERN_WARNING
+		       "MTD %s(): Internal flash device timeout occured\n",
+		       __func__ );
+	        cfi_write( map, CMD(0xF0), chip->start );
+		ret =3D -EIO;
+	} else {
+
+		status =3D cfi_read(map, adr);
+
+		if ( datum !=3D status ) {
+			/* must check two more times and succeed for both */
+			oldstatus =3D cfi_read(map, adr);
+			status =3D cfi_read(map, adr);
+			if ( datum !=3D oldstatus || datum !=3D status ) {
+				DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): 0x%.2x !=3D 0x%.2x\n", __func__, s=
tatus, datum );
+				ret =3D -EIO;
+			}
+		}
+	}
+
+	return ret;
+}
+
+
+static int do_write_oneword(struct map_info *map, struct flchip *chip, uns=
igned long adr, __u32 datum, int fast)
+{
+	unsigned long timeo =3D jiffies + HZ;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+    /* We use a 1ms + 1 jiffies generic timeout for writes (most devices h=
ave
+       a max write time of a few hundreds usec). However, we should use th=
e
+       maximum timeout value given by the chip at probe time instead.=20
+       Unfortunately, struct flchip does have a field for maximum timeout,=
=20
+       only for typical which can be far too short depending of the condit=
ions.
+       The ' + 1' is to avoid having a timeout of 0 jiffies if HZ is small=
er
+       than 1000. Using a static variable allows makes us save the costly
+       divide operation at each word write.*/=20
+    static unsigned long uWriteTimeout =3D ( HZ / 1000 ) + 1;
+	DECLARE_WAITQUEUE(wait, current);
+	int ret =3D 0;
+
+ retry:
+	cfi_spin_lock(chip->mutex);
+
+	if (chip->state !=3D FL_READY) {
+#if 0
+	        printk(KERN_DEBUG "Waiting for chip to write, status =3D %d\n", c=
hip->state);
+#endif
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&chip->wq, &wait);
+               =20
+		cfi_spin_unlock(chip->mutex);
+
+		schedule();
+		remove_wait_queue(&chip->wq, &wait);
+#if 0
+		printk(KERN_DEBUG "Wake up to write:\n");
+		if(signal_pending(current))
+			return -EINTR;
+#endif
+		timeo =3D jiffies + HZ;
+
+		goto retry;
+	}=09
+
+	chip->state =3D FL_WRITING;
+
+	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE (0x%.8lx)0x%.2x\n", __func__, a=
dr, datum );
+	adr +=3D chip->start;
+	ENABLE_VPP(map);
+	if (fast) { /* Unlock bypass */
+		cfi_send_gen_cmd(0xA0, 0, chip->start, map, cfi, cfi->device_type, NULL)=
;
+	}
+	else {
+	        cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, =
CFI_DEVICETYPE_X8, NULL);
+	        cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, =
CFI_DEVICETYPE_X8, NULL);
+	        cfi_send_gen_cmd(0xA0, cfi->addr_unlock1, chip->start, map, cfi, =
CFI_DEVICETYPE_X8, NULL);
+	}
+
+	cfi_write(map, datum, adr);
+
+	cfi_spin_unlock(chip->mutex);
+	cfi_udelay(chip->word_write_time);
+	cfi_spin_lock(chip->mutex);
+
+	/* See comment above for timeout value. */
+	ret =3D status_poll( map, chip, adr, datum, jiffies + uWriteTimeout );
+
+	DISABLE_VPP(map);
+	chip->state =3D FL_READY;
+	wake_up(&chip->wq);
+	cfi_spin_unlock(chip->mutex);
+
+	return ret;
+}
+
+
+static int cfi_amdsmpl_write (struct mtd_info *mtd, loff_t to , size_t len=
, size_t *retlen, const u_char *buf)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	int ret =3D 0;
+	int chipnum;
+	unsigned long ofs, chipstart;
+
+	*retlen =3D 0;
+	if (!len)
+		return 0;
+
+	chipnum =3D to >> cfi->chipshift;
+	ofs =3D to  - (chipnum << cfi->chipshift);
+	chipstart =3D cfi->chips[chipnum].start;
+
+	/* If it's not bus-aligned, do the first byte write */
+	if (ofs & (CFIDEV_BUSWIDTH-1)) {
+		unsigned long bus_ofs =3D ofs & ~(CFIDEV_BUSWIDTH-1);
+		int i =3D ofs - bus_ofs;
+		int n =3D 0;
+		u_char tmp_buf[8];
+		__u32 datum;
+
+		map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV=
_BUSWIDTH);
+		while (len && i < CFIDEV_BUSWIDTH)
+			tmp_buf[i++] =3D buf[n++], len--;
+
+		if (cfi_buswidth_is_2()) {
+			datum =3D *(__u16*)tmp_buf;
+		} else if (cfi_buswidth_is_4()) {
+			datum =3D *(__u32*)tmp_buf;
+		} else {
+			return -EINVAL;  /* should never happen, but be safe */
+		}
+
+		ret =3D do_write_oneword(map, &cfi->chips[chipnum],=20
+				bus_ofs, datum, 0);
+		if (ret)=20
+			return ret;
+	=09
+		ofs +=3D n;
+		buf +=3D n;
+		(*retlen) +=3D n;
+
+		if (ofs >> cfi->chipshift) {
+			chipnum ++;=20
+			ofs =3D 0;
+			if (chipnum =3D=3D cfi->numchips)
+				return 0;
+		}
+	}
+=09
+	if (cfi->fast_prog) {
+		/* Go into unlock bypass mode */
+		cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVIC=
ETYPE_X8, NULL);
+		cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEVIC=
ETYPE_X8, NULL);
+		cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEVIC=
ETYPE_X8, NULL);
+	}
+
+	/* We are now aligned, write as much as possible */
+	while(len >=3D CFIDEV_BUSWIDTH) {
+		__u32 datum;
+
+		if (cfi_buswidth_is_1()) {
+			datum =3D *(__u8*)buf;
+		} else if (cfi_buswidth_is_2()) {
+			datum =3D *(__u16*)buf;
+		} else if (cfi_buswidth_is_4()) {
+			datum =3D *(__u32*)buf;
+		} else {
+			return -EINVAL;
+		}
+		ret =3D do_write_oneword(map, &cfi->chips[chipnum],
+				       ofs, datum, cfi->fast_prog);
+		if (ret) {
+			if (cfi->fast_prog){
+				/* Get out of unlock bypass mode */
+				cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL)=
;
+				cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL)=
;
+			}
+			return ret;
+		}
+
+		ofs +=3D CFIDEV_BUSWIDTH;
+		buf +=3D CFIDEV_BUSWIDTH;
+		(*retlen) +=3D CFIDEV_BUSWIDTH;
+		len -=3D CFIDEV_BUSWIDTH;
+
+		if (ofs >> cfi->chipshift) {
+			if (cfi->fast_prog){
+				/* Get out of unlock bypass mode */
+				cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL)=
;
+				cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL)=
;
+			}
+
+			chipnum ++;=20
+			ofs =3D 0;
+			if (chipnum =3D=3D cfi->numchips)
+				return 0;
+			chipstart =3D cfi->chips[chipnum].start;
+			if (cfi->fast_prog){
+				/* Go into unlock bypass mode for next set of chips */
+				cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEV=
ICETYPE_X8, NULL);
+				cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chipstart, map, cfi, CFI_DEV=
ICETYPE_X8, NULL);
+				cfi_send_gen_cmd(0x20, cfi->addr_unlock1, chipstart, map, cfi, CFI_DEV=
ICETYPE_X8, NULL);
+			}
+		}
+	}
+
+	if (cfi->fast_prog){
+		/* Get out of unlock bypass mode */
+		cfi_send_gen_cmd(0x90, 0, chipstart, map, cfi, cfi->device_type, NULL);
+		cfi_send_gen_cmd(0x00, 0, chipstart, map, cfi, cfi->device_type, NULL);
+	}
+
+	/* Write the trailing bytes if any */
+	if (len & (CFIDEV_BUSWIDTH-1)) {
+		int i =3D 0, n =3D 0;
+		u_char tmp_buf[8];
+		__u32 datum;
+
+		map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUS=
WIDTH);
+		while (len--)
+			tmp_buf[i++] =3D buf[n++];
+
+		if (cfi_buswidth_is_2()) {
+			datum =3D *(__u16*)tmp_buf;
+		} else if (cfi_buswidth_is_4()) {
+			datum =3D *(__u32*)tmp_buf;
+		} else {
+			return -EINVAL;  /* should never happen, but be safe */
+		}
+
+		ret =3D do_write_oneword(map, &cfi->chips[chipnum],=20
+				ofs, datum, 0);
+		if (ret)=20
+			return ret;
+	=09
+		(*retlen) +=3D n;
+	}
+
+	return 0;
+}
+
+
+static inline int do_erase_oneblock(struct map_info *map, struct flchip *c=
hip, unsigned long adr)
+{
+	int ret =3D 0;
+	unsigned long timeo =3D jiffies + HZ;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	DECLARE_WAITQUEUE(wait, current);
+	__u32 ones =3D 0;
+
+ retry:
+	cfi_spin_lock(chip->mutex);
+
+	if (chip->state !=3D FL_READY){
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		add_wait_queue(&chip->wq, &wait);
+               =20
+		cfi_spin_unlock(chip->mutex);
+
+		schedule();
+		remove_wait_queue(&chip->wq, &wait);
+#if 0
+		if(signal_pending(current))
+			return -EINTR;
+#endif
+		timeo =3D jiffies + HZ;
+
+		goto retry;
+	}=09
+
+	chip->state =3D FL_ERASING;
+
+	DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n", __func__, adr );
+	adr +=3D chip->start;
+	ENABLE_VPP(map);
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVI=
CETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVI=
CETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVI=
CETYPE_X8, NULL);
+	cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVI=
CETYPE_X8, NULL);
+	cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVI=
CETYPE_X8, NULL);
+	cfi_write(map, CMD(0x30), adr);
+
+	switch( CFIDEV_BUSWIDTH ) {
+	case 1:
+		ones =3D (__u8)~0;
+		break;
+	case 2:
+		ones =3D (__u16)~0;
+		break;
+	case 4:
+		ones =3D (__u32)~0;
+		break;
+	}
+=09
+	ret =3D status_poll( map, chip, adr, ones, jiffies + (HZ*20) );
+
+	DISABLE_VPP(map);
+	chip->state =3D FL_READY;
+	wake_up(&chip->wq);
+	cfi_spin_unlock(chip->mutex);
+	return ret;
+}
+
+
+static int cfi_amdsmpl_erase_varsize(struct mtd_info *mtd, struct erase_in=
fo *instr)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	unsigned long adr, len;
+	int chipnum, ret =3D 0;
+	int i, first;
+	struct mtd_erase_region_info *regions =3D mtd->eraseregions;
+
+	if (instr->addr > mtd->size)
+		return -EINVAL;
+
+	if ((instr->len + instr->addr) > mtd->size)
+		return -EINVAL;
+
+	/* Check that both start and end of the requested erase are
+	 * aligned with the erasesize at the appropriate addresses.
+	 */
+
+	i =3D 0;
+
+	/* Skip all erase regions which are ended before the start of=20
+	   the requested erase. Actually, to save on the calculations,
+	   we skip to the first erase region which starts after the
+	   start of the requested erase, and then go back one.
+	*/
+=09
+	while (i < mtd->numeraseregions && instr->addr >=3D regions[i].offset)
+	       i++;
+	i--;
+
+	/* OK, now i is pointing at the erase region in which this=20
+	   erase request starts. Check the start of the requested
+	   erase range is aligned with the erase size which is in
+	   effect here.
+	*/
+
+	if (instr->addr & (regions[i].erasesize-1))
+		return -EINVAL;
+
+	/* Remember the erase region we start on */
+	first =3D i;
+
+	/* Next, check that the end of the requested erase is aligned
+	 * with the erase region at that address.
+	 */
+
+	while (i<mtd->numeraseregions && (instr->addr + instr->len) >=3D regions[=
i].offset)
+		i++;
+
+	/* As before, drop back one to point at the region in which
+	   the address actually falls
+	*/
+	i--;
+=09
+	if ((instr->addr + instr->len) & (regions[i].erasesize-1))
+		return -EINVAL;
+=09
+	chipnum =3D instr->addr >> cfi->chipshift;
+	adr =3D instr->addr - (chipnum << cfi->chipshift);
+	len =3D instr->len;
+
+	i=3Dfirst;
+
+	while(len) {
+		ret =3D do_erase_oneblock(map, &cfi->chips[chipnum], adr);
+
+		if (ret)
+			return ret;
+
+		adr +=3D regions[i].erasesize;
+		len -=3D regions[i].erasesize;
+
+		if (adr % (1<< cfi->chipshift) =3D=3D ((regions[i].offset + (regions[i].=
erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+			i++;
+
+		if (adr >> cfi->chipshift) {
+			adr =3D 0;
+			chipnum++;
+		=09
+			if (chipnum >=3D cfi->numchips)
+			break;
+		}
+	}
+
+	instr->state =3D MTD_ERASE_DONE;
+	if (instr->callback)
+		instr->callback(instr);
+=09
+	return 0;
+}
+
+
+static int cfi_amdsmpl_erase_onesize(struct mtd_info *mtd, struct erase_in=
fo *instr)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	unsigned long adr, len;
+	int chipnum, ret =3D 0;
+
+	if (instr->addr & (mtd->erasesize - 1))
+		return -EINVAL;
+
+	if (instr->len & (mtd->erasesize -1))
+		return -EINVAL;
+
+	if ((instr->len + instr->addr) > mtd->size)
+		return -EINVAL;
+
+	chipnum =3D instr->addr >> cfi->chipshift;
+	adr =3D instr->addr - (chipnum << cfi->chipshift);
+	len =3D instr->len;
+
+	while(len) {
+		ret =3D do_erase_oneblock(map, &cfi->chips[chipnum], adr);
+
+		if (ret)
+			return ret;
+
+		adr +=3D mtd->erasesize;
+		len -=3D mtd->erasesize;
+
+		if (adr >> cfi->chipshift) {
+			adr =3D 0;
+			chipnum++;
+		=09
+			if (chipnum >=3D cfi->numchips)
+			break;
+		}
+	}
+	=09
+	instr->state =3D MTD_ERASE_DONE;
+	if (instr->callback)
+		instr->callback(instr);
+=09
+	return 0;
+}
+
+
+static void cfi_amdsmpl_sync (struct mtd_info *mtd)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	int i;
+	struct flchip *chip;
+	int ret =3D 0;
+	DECLARE_WAITQUEUE(wait, current);
+
+	for (i=3D0; !ret && i<cfi->numchips; i++) {
+		chip =3D &cfi->chips[i];
+
+	retry:
+		cfi_spin_lock(chip->mutex);
+
+		switch(chip->state) {
+		case FL_READY:
+		case FL_STATUS:
+		case FL_CFI_QUERY:
+		case FL_JEDEC_QUERY:
+			chip->oldstate =3D chip->state;
+			chip->state =3D FL_SYNCING;
+			/* No need to wake_up() on this state change -=20
+			 * as the whole point is that nobody can do anything
+			 * with the chip now anyway.
+			 */
+		case FL_SYNCING:
+			cfi_spin_unlock(chip->mutex);
+			break;
+
+		default:
+			/* Not an idle state */
+			add_wait_queue(&chip->wq, &wait);
+		=09
+			cfi_spin_unlock(chip->mutex);
+
+			schedule();
+
+		        remove_wait_queue(&chip->wq, &wait);
+		=09
+			goto retry;
+		}
+	}
+
+	/* Unlock the chips again */
+
+	for (i--; i >=3D0; i--) {
+		chip =3D &cfi->chips[i];
+
+		cfi_spin_lock(chip->mutex);
+	=09
+		if (chip->state =3D=3D FL_SYNCING) {
+			chip->state =3D chip->oldstate;
+			wake_up(&chip->wq);
+		}
+		cfi_spin_unlock(chip->mutex);
+	}
+}
+
+
+static void cfi_amdsmpl_destroy(struct mtd_info *mtd)
+{
+	struct map_info *map =3D mtd->priv;
+	struct cfi_private *cfi =3D map->fldrv_priv;
+	kfree(cfi->cmdset_priv);
+	kfree(cfi->cfiq);
+	kfree(cfi);
+	kfree(mtd->eraseregions);
+}
+
+static char im_name[]=3D"cfi_cmdset_0005";
+
+int __init cfi_amdsmpl_init(void)
+{
+	inter_module_register(im_name, THIS_MODULE, &cfi_cmdset_0005);
+	return 0;
+}
+
+static void __exit cfi_amdsmpl_exit(void)
+{
+	inter_module_unregister(im_name);
+}
+
+module_init(cfi_amdsmpl_init);
+module_exit(cfi_amdsmpl_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Linux Networx - based on cfi_cmdset_0002.c by Crossnet Co. =
et al.");
+MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu simplified flash chips=
");
+
diff -uNr mtd/drivers/mtd/chips/Config.in mtd-amd_simplified/drivers/mtd/ch=
ips/Config.in
--- mtd/drivers/mtd/chips/Config.in	2002-09-03 07:30:43.000000000 -0600
+++ mtd-amd_simplified/drivers/mtd/chips/Config.in	2003-03-18 16:51:05.0000=
00000 -0700
@@ -44,6 +44,7 @@
 fi
 dep_tristate '  Support for Intel/Sharp flash chips' CONFIG_MTD_CFI_INTELE=
XT $CONFIG_MTD_GEN_PROBE
 dep_tristate '  Support for AMD/Fujitsu flash chips' CONFIG_MTD_CFI_AMDSTD=
 $CONFIG_MTD_GEN_PROBE
+dep_tristate '  Support for AMD Simplified flash chips' CONFIG_MTD_AMDSIMP=
LIFIED $CONFIG_MTD_GEN_PROBE
 dep_tristate '  Support for ST (Advanced Architecture) flash chips' CONFIG=
_MTD_CFI_STAA $CONFIG_MTD_GEN_PROBE
=20
 dep_tristate '  Support for RAM chips in bus mapping' CONFIG_MTD_RAM $CONF=
IG_MTD
diff -uNr mtd/drivers/mtd/chips/gen_probe.c mtd-amd_simplified/drivers/mtd/=
chips/gen_probe.c
--- mtd/drivers/mtd/chips/gen_probe.c	2003-01-31 06:35:07.000000000 -0700
+++ mtd-amd_simplified/drivers/mtd/chips/gen_probe.c	2003-03-18 16:51:05.00=
0000000 -0700
@@ -331,6 +331,10 @@
 	case 0x0002:
 		return cfi_cmdset_0002(map, primary);
 #endif
+#ifdef CONFIG_MTD_CFI_AMDSMPLFD
+	case P_ID_AMD_SIMPLIFIED:
+		return cfi_cmdset_0005(map, primary);
+#endif
 #ifdef CONFIG_MTD_CFI_STAA
         case 0x0020:
 		return cfi_cmdset_0020(map, primary);
diff -uNr mtd/drivers/mtd/chips/jedec_probe.c mtd-amd_simplified/drivers/mt=
d/chips/jedec_probe.c
--- mtd/drivers/mtd/chips/jedec_probe.c	2003-03-18 16:36:28.000000000 -0700
+++ mtd-amd_simplified/drivers/mtd/chips/jedec_probe.c	2003-03-18 16:51:05.=
000000000 -0700
@@ -746,7 +746,7 @@
 		name: "Atmel AT49BV512",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_64KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x10000,1)
 		}
@@ -756,7 +756,7 @@
 		name: "Atmel AT29LV512",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_64KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {
 			ERASEINFO(0x80,256),
@@ -934,7 +934,7 @@
 		name: "SST 39LF512",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_64KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,16),
 		}
@@ -944,7 +944,7 @@
 		name: "SST 39LF010",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_128KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,32),
 		}
@@ -954,7 +954,7 @@
 		name: "SST 39LF020",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_256KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,64),
 		}
@@ -964,7 +964,7 @@
 		name: "SST 39LF040",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_512KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,128),
 		}
@@ -974,7 +974,7 @@
 		name: "SST 39SF010A",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_128KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,32),
 		}
@@ -984,7 +984,7 @@
 		name: "SST 39SF020A",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_256KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,64),
 		}
@@ -994,7 +994,7 @@
 		name: "SST 49LF030A",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_512KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,96),
 		}
@@ -1004,7 +1004,7 @@
 		name: "SST 49LF040A",
 		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_512KiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,128),
 		}
@@ -1014,7 +1014,7 @@
 		name: "SST 49LF080A",
  		uaddr: MTD_UADDR_0x5555_0x2AAA,
 		DevSize: SIZE_1MiB,
-		CmdSet: P_ID_AMD_STD,
+		CmdSet: P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions: {ERASEINFO(0x01000,256),
 		}
@@ -1024,7 +1024,7 @@
 		name:            "PMC_Pm49FL002",
  		uaddr:           MTD_UADDR_0x5555_0x2AAA,
 		DevSize:         SIZE_256KiB,
-		CmdSet:          P_ID_AMD_STD,
+		CmdSet:          P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions:         {
 			ERASEINFO( 0x01000, 64 )
@@ -1035,7 +1035,7 @@
 		name:            "PMC_Pm49FL004",
  		uaddr:           MTD_UADDR_0x5555_0x2AAA,
 		DevSize:         SIZE_512KiB,
-		CmdSet:          P_ID_AMD_STD,
+		CmdSet:          P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions:         {
 			ERASEINFO( 0x01000, 128 )
@@ -1046,7 +1046,7 @@
 		name:            "PMC_Pm49FL008",
  		uaddr:           MTD_UADDR_0x5555_0x2AAA,
 		DevSize:         SIZE_1MiB,
-		CmdSet:          P_ID_AMD_STD,
+		CmdSet:          P_ID_AMD_SIMPLIFIED,
 		NumEraseRegions: 1,
 		regions:         {
 			ERASEINFO( 0x01000, 256 )
diff -uNr mtd/drivers/mtd/chips/Makefile mtd-amd_simplified/drivers/mtd/chi=
ps/Makefile
--- mtd/drivers/mtd/chips/Makefile	2003-02-13 14:07:31.000000000 -0700
+++ mtd-amd_simplified/drivers/mtd/chips/Makefile	2003-03-18 16:51:05.00000=
0000 -0700
@@ -22,6 +22,7 @@
 obj-$(CONFIG_MTD_AMDSTD)	+=3D amd_flash.o=20
 obj-$(CONFIG_MTD_CFI)		+=3D cfi_probe.o
 obj-$(CONFIG_MTD_CFI_STAA)	+=3D cfi_cmdset_0020.o
+obj-$(CONFIG_MTD_AMDSIMPLIFIED)	+=3D cfi_cmdset_0005.o
 obj-$(CONFIG_MTD_CFI_AMDSTD)	+=3D cfi_cmdset_0002.o
 obj-$(CONFIG_MTD_CFI_INTELEXT)	+=3D cfi_cmdset_0001.o
 obj-$(CONFIG_MTD_GEN_PROBE)	+=3D gen_probe.o
diff -uNr mtd/patches/Configure.help mtd-amd_simplified/patches/Configure.h=
elp
--- mtd/patches/Configure.help	2002-11-26 17:24:38.000000000 -0700
+++ mtd-amd_simplified/patches/Configure.help	2003-03-18 16:49:13.000000000=
 -0700
@@ -295,6 +295,20 @@
=20
   It also works on AMD compatible chips that do conform to CFI.
=20
+AMD simplified compatible flash chip support (non-CFI)
+CONFIG_MTD_AMDSIMPLIFIED
+  This option enables support for flash chips using a subset of
+  AMD commands.  These devices provide toggle and complement status
+  polling bits but do not have support for other status bits and the
+  more sophisticated functions, such as erase suspend, that those
+  chips support.
+
+  This driver is also available as a module ( =3D code which can be
+  inserted in and removed from the running kernel whenever you want).
+  If you want to compile it as a module, say M here and read
+  <file:Documentation/modules.txt>. The module will be called
+  amd_flash.o
+
 Support for RAM chips in bus mapping
 CONFIG_MTD_RAM
   This option enables basic support for RAM chips accessed through=20

--=-YdlygX9g8mw3u7YELU6q--

--=-RZKiLm5gawTslA20lq2l
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+d7iPfsBPTKE6HMkRAkwTAJ4vev0OXxtA+UDKkQEcq5sTJegPXQCeMDXw
/yRF12JriuOF4pSLMwLjhpw=
=cYZW
-----END PGP SIGNATURE-----

--=-RZKiLm5gawTslA20lq2l--

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-19  0:23       ` Thayne Harbaugh
@ 2003-03-19 15:56         ` Steve Wahl
  2003-03-19 19:38           ` Thayne Harbaugh
  0 siblings, 1 reply; 20+ messages in thread
From: Steve Wahl @ 2003-03-19 15:56 UTC (permalink / raw)
  To: linux-mtd

On Tue, Mar 18, 2003 at 05:23:43PM -0700, Thayne Harbaugh wrote:
>   It likely could be simplified even more - take out feeble support for
> interleaved chips (which I don't have and can't test and I'm not even
> sure that the chips that work this way support interleaving).

Interleaved operation is probably always supported, because the chips
don't "know" they're doing it.

Unless I'm completely mistaken, interleaving is simply having N chips
with a data bus width of W on a bus that's N * W wide.  For instance,
I once worked on a product with a processor that didn't do anything
smaller than a 32 bit bus, so the flash area of memory was populated
with 4 chips (each 8 bits wide).

For these, you generally issue the commands to all chips at one time,
in this case writing 32 bit words with the command bytes replicated in
each byte of the word.  Makes the polling a little complicated,
perhaps, because you have to watch for all chips to reach a finished
state before you continue.

Still thinking about the rest of what you wrote.  My initial thoughts
are this shouldn't really need a whole separate command set file.

--> Steve

^ permalink raw reply	[flat|nested] 20+ messages in thread

* DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning)
  2003-03-19 15:56         ` Steve Wahl
@ 2003-03-19 19:38           ` Thayne Harbaugh
  0 siblings, 0 replies; 20+ messages in thread
From: Thayne Harbaugh @ 2003-03-19 19:38 UTC (permalink / raw)
  To: linux-mtd

--=-kZtkePRDB816W7SZVvFx
Content-Type: text/plain
Content-Transfer-Encoding: quoted-printable

On Wed, 2003-03-19 at 08:56, Steve Wahl wrote:

> Still thinking about the rest of what you wrote.  My initial thoughts
> are this shouldn't really need a whole separate command set file.

Yeah, I don't like making a new driver either.  The concerns are knowing
_not_ to check DQ5 and other status bits as well as knowing that a
device does not support suspend/resume.  That could be described in
another field of the jedec_table[] - unless we can come up with a
_reliable_ way of probing that functionality.

I'm still thinking, too.  I just wanted a starting point - sometimes
it's hard to get going without some sample code.

> --> Steve
>=20
>=20
>=20
>=20
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
--=20
Thayne Harbaugh
Linux Networx

--=-kZtkePRDB816W7SZVvFx
Content-Type: application/pgp-signature; name=signature.asc
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org

iD8DBQA+eMc2fsBPTKE6HMkRAiw2AJsFNarjJ6p1730Lv8MaTSKiHbJcOwCggltp
MIcGi2FJjqSPg6efEAnLYjY=
=Wb2R
-----END PGP SIGNATURE-----

--=-kZtkePRDB816W7SZVvFx--

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2003-03-19 19:38 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-03-12  0:25 DQ5 & DQ6 in chips/cfi_cmdset_0002.c (Dairy Queen 5 warning) Thayne Harbaugh
2003-03-12 15:44 ` John Burch
2003-03-12 16:35   ` Thayne Harbaugh
2003-03-12 16:27 ` Steve Wahl
2003-03-12 17:12   ` John Burch
2003-03-12 21:43     ` Steve Wahl
2003-03-12 22:17       ` John Burch
2003-03-13  7:17       ` David Woodhouse
2003-03-13  7:26         ` Russ Dill
2003-03-17 15:54       ` Thayne Harbaugh
2003-03-17 16:09         ` John Burch
2003-03-17 16:19         ` Steve Wahl
2003-03-17 18:27           ` Thayne Harbaugh
2003-03-18 16:51             ` Steve Wahl
2003-03-18 17:22               ` Thayne Harbaugh
2003-03-17 15:40   ` Thayne Harbaugh
2003-03-17 18:38     ` Thayne Harbaugh
2003-03-19  0:23       ` Thayne Harbaugh
2003-03-19 15:56         ` Steve Wahl
2003-03-19 19:38           ` Thayne Harbaugh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox