aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-04-02 19:56:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-04-02 22:04:50 -0400
commit14dd1ff0f9e75dd4ae2f1ff8e48becb76d14f4ab (patch)
treea9e208f0c35c8e24ed0edb8a1bc5ca9a4dc9b585
parent7274ec8bd71e99018642f474528ea7de4bb3ae25 (diff)
memory_accessor: implement the new memory_accessor interfaces for SPI EEPROMs
- Define new setup() hook to export the accessor - Implement accessor methods Moves some error checking out of the sysfs interface code into the layer below it, which is now shared by both sysfs and memory access code. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com> Cc: Jean Delvare <khali@linux-fr.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/misc/eeprom/at25.c58
-rw-r--r--include/linux/spi/eeprom.h6
2 files changed, 50 insertions, 14 deletions
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 290dbe99647a..6bc0dac5c1e8 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -30,6 +30,7 @@
30 30
31struct at25_data { 31struct at25_data {
32 struct spi_device *spi; 32 struct spi_device *spi;
33 struct memory_accessor mem;
33 struct mutex lock; 34 struct mutex lock;
34 struct spi_eeprom chip; 35 struct spi_eeprom chip;
35 struct bin_attribute bin; 36 struct bin_attribute bin;
@@ -75,6 +76,13 @@ at25_ee_read(
75 struct spi_transfer t[2]; 76 struct spi_transfer t[2];
76 struct spi_message m; 77 struct spi_message m;
77 78
79 if (unlikely(offset >= at25->bin.size))
80 return 0;
81 if ((offset + count) > at25->bin.size)
82 count = at25->bin.size - offset;
83 if (unlikely(!count))
84 return count;
85
78 cp = command; 86 cp = command;
79 *cp++ = AT25_READ; 87 *cp++ = AT25_READ;
80 88
@@ -127,13 +135,6 @@ at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr,
127 dev = container_of(kobj, struct device, kobj); 135 dev = container_of(kobj, struct device, kobj);
128 at25 = dev_get_drvdata(dev); 136 at25 = dev_get_drvdata(dev);
129 137
130 if (unlikely(off >= at25->bin.size))
131 return 0;
132 if ((off + count) > at25->bin.size)
133 count = at25->bin.size - off;
134 if (unlikely(!count))
135 return count;
136
137 return at25_ee_read(at25, buf, off, count); 138 return at25_ee_read(at25, buf, off, count);
138} 139}
139 140
@@ -146,6 +147,13 @@ at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count)
146 unsigned buf_size; 147 unsigned buf_size;
147 u8 *bounce; 148 u8 *bounce;
148 149
150 if (unlikely(off >= at25->bin.size))
151 return -EFBIG;
152 if ((off + count) > at25->bin.size)
153 count = at25->bin.size - off;
154 if (unlikely(!count))
155 return count;
156
149 /* Temp buffer starts with command and address */ 157 /* Temp buffer starts with command and address */
150 buf_size = at25->chip.page_size; 158 buf_size = at25->chip.page_size;
151 if (buf_size > io_limit) 159 if (buf_size > io_limit)
@@ -253,18 +261,31 @@ at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr,
253 dev = container_of(kobj, struct device, kobj); 261 dev = container_of(kobj, struct device, kobj);
254 at25 = dev_get_drvdata(dev); 262 at25 = dev_get_drvdata(dev);
255 263
256 if (unlikely(off >= at25->bin.size))
257 return -EFBIG;
258 if ((off + count) > at25->bin.size)
259 count = at25->bin.size - off;
260 if (unlikely(!count))
261 return count;
262
263 return at25_ee_write(at25, buf, off, count); 264 return at25_ee_write(at25, buf, off, count);
264} 265}
265 266
266/*-------------------------------------------------------------------------*/ 267/*-------------------------------------------------------------------------*/
267 268
269/* Let in-kernel code access the eeprom data. */
270
271static ssize_t at25_mem_read(struct memory_accessor *mem, char *buf,
272 off_t offset, size_t count)
273{
274 struct at25_data *at25 = container_of(mem, struct at25_data, mem);
275
276 return at25_ee_read(at25, buf, offset, count);
277}
278
279static ssize_t at25_mem_write(struct memory_accessor *mem, char *buf,
280 off_t offset, size_t count)
281{
282 struct at25_data *at25 = container_of(mem, struct at25_data, mem);
283
284 return at25_ee_write(at25, buf, offset, count);
285}
286
287/*-------------------------------------------------------------------------*/
288
268static int at25_probe(struct spi_device *spi) 289static int at25_probe(struct spi_device *spi)
269{ 290{
270 struct at25_data *at25 = NULL; 291 struct at25_data *at25 = NULL;
@@ -317,6 +338,10 @@ static int at25_probe(struct spi_device *spi)
317 at25->addrlen = addrlen; 338 at25->addrlen = addrlen;
318 339
319 /* Export the EEPROM bytes through sysfs, since that's convenient. 340 /* Export the EEPROM bytes through sysfs, since that's convenient.
341 * And maybe to other kernel code; it might hold a board's Ethernet
342 * address, or board-specific calibration data generated on the
343 * manufacturing floor.
344 *
320 * Default to root-only access to the data; EEPROMs often hold data 345 * Default to root-only access to the data; EEPROMs often hold data
321 * that's sensitive for read and/or write, like ethernet addresses, 346 * that's sensitive for read and/or write, like ethernet addresses,
322 * security codes, board-specific manufacturing calibrations, etc. 347 * security codes, board-specific manufacturing calibrations, etc.
@@ -324,17 +349,22 @@ static int at25_probe(struct spi_device *spi)
324 at25->bin.attr.name = "eeprom"; 349 at25->bin.attr.name = "eeprom";
325 at25->bin.attr.mode = S_IRUSR; 350 at25->bin.attr.mode = S_IRUSR;
326 at25->bin.read = at25_bin_read; 351 at25->bin.read = at25_bin_read;
352 at25->mem.read = at25_mem_read;
327 353
328 at25->bin.size = at25->chip.byte_len; 354 at25->bin.size = at25->chip.byte_len;
329 if (!(chip->flags & EE_READONLY)) { 355 if (!(chip->flags & EE_READONLY)) {
330 at25->bin.write = at25_bin_write; 356 at25->bin.write = at25_bin_write;
331 at25->bin.attr.mode |= S_IWUSR; 357 at25->bin.attr.mode |= S_IWUSR;
358 at25->mem.write = at25_mem_write;
332 } 359 }
333 360
334 err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); 361 err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin);
335 if (err) 362 if (err)
336 goto fail; 363 goto fail;
337 364
365 if (chip->setup)
366 chip->setup(&at25->mem, chip->context);
367
338 dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n", 368 dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n",
339 (at25->bin.size < 1024) 369 (at25->bin.size < 1024)
340 ? at25->bin.size 370 ? at25->bin.size
diff --git a/include/linux/spi/eeprom.h b/include/linux/spi/eeprom.h
index 1085212c446e..306e7b1c69ed 100644
--- a/include/linux/spi/eeprom.h
+++ b/include/linux/spi/eeprom.h
@@ -1,6 +1,8 @@
1#ifndef __LINUX_SPI_EEPROM_H 1#ifndef __LINUX_SPI_EEPROM_H
2#define __LINUX_SPI_EEPROM_H 2#define __LINUX_SPI_EEPROM_H
3 3
4#include <linux/memory.h>
5
4/* 6/*
5 * Put one of these structures in platform_data for SPI EEPROMS handled 7 * Put one of these structures in platform_data for SPI EEPROMS handled
6 * by the "at25" driver. On SPI, most EEPROMS understand the same core 8 * by the "at25" driver. On SPI, most EEPROMS understand the same core
@@ -17,6 +19,10 @@ struct spi_eeprom {
17#define EE_ADDR2 0x0002 /* 16 bit addrs */ 19#define EE_ADDR2 0x0002 /* 16 bit addrs */
18#define EE_ADDR3 0x0004 /* 24 bit addrs */ 20#define EE_ADDR3 0x0004 /* 24 bit addrs */
19#define EE_READONLY 0x0008 /* disallow writes */ 21#define EE_READONLY 0x0008 /* disallow writes */
22
23 /* for exporting this chip's data to other kernel code */
24 void (*setup)(struct memory_accessor *mem, void *context);
25 void *context;
20}; 26};
21 27
22#endif /* __LINUX_SPI_EEPROM_H */ 28#endif /* __LINUX_SPI_EEPROM_H */