aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/eeprom/at25.c19
-rw-r--r--include/linux/spi/eeprom.h10
2 files changed, 26 insertions, 3 deletions
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 01ab3c9b4cf7..0842c2994ee2 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -50,6 +50,7 @@ struct at25_data {
50#define AT25_SR_BP1 0x08 50#define AT25_SR_BP1 0x08
51#define AT25_SR_WPEN 0x80 /* writeprotect enable */ 51#define AT25_SR_WPEN 0x80 /* writeprotect enable */
52 52
53#define AT25_INSTR_BIT3 0x08 /* Additional address bit in instr */
53 54
54#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ 55#define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */
55 56
@@ -75,6 +76,7 @@ at25_ee_read(
75 ssize_t status; 76 ssize_t status;
76 struct spi_transfer t[2]; 77 struct spi_transfer t[2];
77 struct spi_message m; 78 struct spi_message m;
79 u8 instr;
78 80
79 if (unlikely(offset >= at25->bin.size)) 81 if (unlikely(offset >= at25->bin.size))
80 return 0; 82 return 0;
@@ -84,7 +86,12 @@ at25_ee_read(
84 return count; 86 return count;
85 87
86 cp = command; 88 cp = command;
87 *cp++ = AT25_READ; 89
90 instr = AT25_READ;
91 if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
92 if (offset >= (1U << (at25->addrlen * 8)))
93 instr |= AT25_INSTR_BIT3;
94 *cp++ = instr;
88 95
89 /* 8/16/24-bit address is written MSB first */ 96 /* 8/16/24-bit address is written MSB first */
90 switch (at25->addrlen) { 97 switch (at25->addrlen) {
@@ -167,14 +174,14 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
167 /* For write, rollover is within the page ... so we write at 174 /* For write, rollover is within the page ... so we write at
168 * most one page, then manually roll over to the next page. 175 * most one page, then manually roll over to the next page.
169 */ 176 */
170 bounce[0] = AT25_WRITE;
171 mutex_lock(&at25->lock); 177 mutex_lock(&at25->lock);
172 do { 178 do {
173 unsigned long timeout, retries; 179 unsigned long timeout, retries;
174 unsigned segment; 180 unsigned segment;
175 unsigned offset = (unsigned) off; 181 unsigned offset = (unsigned) off;
176 u8 *cp = bounce + 1; 182 u8 *cp = bounce;
177 int sr; 183 int sr;
184 u8 instr;
178 185
179 *cp = AT25_WREN; 186 *cp = AT25_WREN;
180 status = spi_write(at25->spi, cp, 1); 187 status = spi_write(at25->spi, cp, 1);
@@ -184,6 +191,12 @@ at25_ee_write(struct at25_data *at25, const char *buf, loff_t off,
184 break; 191 break;
185 } 192 }
186 193
194 instr = AT25_WRITE;
195 if (at25->chip.flags & EE_INSTR_BIT3_IS_ADDR)
196 if (offset >= (1U << (at25->addrlen * 8)))
197 instr |= AT25_INSTR_BIT3;
198 *cp++ = instr;
199
187 /* 8/16/24-bit address is written MSB first */ 200 /* 8/16/24-bit address is written MSB first */
188 switch (at25->addrlen) { 201 switch (at25->addrlen) {
189 default: /* case 3 */ 202 default: /* case 3 */
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 306e7b1c69ed..403e007aef68 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -20,6 +20,16 @@ struct spi_eeprom {
20#define EE_ADDR3 0x0004 /* 24 bit addrs */ 20#define EE_ADDR3 0x0004 /* 24 bit addrs */
21#define EE_READONLY 0x0008 /* disallow writes */ 21#define EE_READONLY 0x0008 /* disallow writes */
22 22
23 /*
24 * Certain EEPROMS have a size that is larger than the number of address
25 * bytes would allow (e.g. like M95040 from ST that has 512 Byte size
26 * but uses only one address byte (A0 to A7) for addressing.) For
27 * the extra address bit (A8, A16 or A24) bit 3 of the instruction byte
28 * is used. This instruction bit is normally defined as don't care for
29 * other AT25 like chips.
30 */
31#define EE_INSTR_BIT3_IS_ADDR 0x0010
32
23 /* for exporting this chip's data to other kernel code */ 33 /* for exporting this chip's data to other kernel code */
24 void (*setup)(struct memory_accessor *mem, void *context); 34 void (*setup)(struct memory_accessor *mem, void *context);
25 void *context; 35 void *context;