Skip to content

Commit

Permalink
Support M95040 SPI EEPROM
Browse files Browse the repository at this point in the history
Updated the generic SPI EEPROM driver AT25 for support of an additional address
bit in the instruction byte. Certain EEPROMS have a size that is larger than the
number of address bytes would allow (e.g. like M95040 from ST that has 512 Byte
size but uses only one address byte (A0 to A7) for addressing.) For the extra
address bit (A8, A16 or A24) bit 3 of the instruction byte is used. This
instruction bit is normally defined as don't care for other AT25 like chips.

Reviewed-by: Wolfram Sang <w.sang@pengutronix.de>
Signed-off-by: Ivo Sieben <meltedpianoman@gmail.com>
Acked-by: Chris Wright <chrisw@sous-sol.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
Ivo Sieben authored and Greg Kroah-Hartman committed Apr 18, 2012
1 parent 985087d commit b4161f0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 3 deletions.
19 changes: 16 additions & 3 deletions drivers/misc/eeprom/at25.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ struct at25_data {
#define AT25_SR_BP1 0x08
#define AT25_SR_WPEN 0x80 /* writeprotect enable */

#define AT25_INSTR_BIT3 0x08 /* Additional address bit in instr */

#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */

Expand All @@ -75,6 +76,7 @@ at25_ee_read(
ssize_t status;
struct spi_transfer t[2];
struct spi_message m;
u8 instr;

if (unlikely(offset >= at25->bin.size))
return 0;
Expand All @@ -84,7 +86,12 @@ at25_ee_read(
return count;

cp = command;
*cp++ = AT25_READ;

instr = AT25_READ;
if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
if (offset >= (1U << (at25->addrlen * 8)))
instr |= AT25_INSTR_BIT3;
*cp++ = instr;

/* 8/16/24-bit address is written MSB first */
switch (at25->addrlen) {
Expand Down Expand Up @@ -167,14 +174,14 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
/* For write, rollover is within the page ... so we write at
* most one page, then manually roll over to the next page.
*/
bounce[0] = AT25_WRITE;
mutex_lock(&at25->lock);
do {
unsigned long timeout, retries;
unsigned segment;
unsigned offset = (unsigned) off;
u8 *cp = bounce + 1;
u8 *cp = bounce;
int sr;
u8 instr;

*cp = AT25_WREN;
status = spi_write(at25->spi, cp, 1);
Expand All @@ -184,6 +191,12 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
break;
}

instr = AT25_WRITE;
if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
if (offset >= (1U << (at25->addrlen * 8)))
instr |= AT25_INSTR_BIT3;
*cp++ = instr;

/* 8/16/24-bit address is written MSB first */
switch (at25->addrlen) {
default: /* case 3 */
Expand Down
10 changes: 10 additions & 0 deletions include/linux/spi/eeprom.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ struct spi_eeprom {
#define EE_ADDR3 0x0004 /* 24 bit addrs */
#define EE_READONLY 0x0008 /* disallow writes */

/*
* Certain EEPROMS have a size that is larger than the number of address
* bytes would allow (e.g. like M95040 from ST that has 512 Byte size
* but uses only one address byte (A0 to A7) for addressing.) For
* the extra address bit (A8, A16 or A24) bit 3 of the instruction byte
* is used. This instruction bit is normally defined as don't care for
* other AT25 like chips.
*/
#define EE_INSTR_BIT3_IS_ADDR 0x0010

/* for exporting this chip's data to other kernel code */
void (*setup)(struct memory_accessor *mem, void *context);
void *context;
Expand Down

0 comments on commit b4161f0

Please sign in to comment.