aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorIvo Sieben <meltedpianoman@gmail.com>2012-04-18 02:29:34 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-04-18 17:57:57 -0400
commitb4161f0bb5f815ca6d8108062b8e3b650c18fe39 (patch)
treed2a6fc73e380a351f9f2224c8443522f2d4ef9fc /drivers/misc
parent985087dbcb0265f46e8651fdc7e974f8a7184423 (diff)
Support M95040 SPI EEPROM
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>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/eeprom/at25.c19
1 files changed, 16 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 */