diff options
author | David S. Miller <davem@davemloft.net> | 2009-01-26 20:43:16 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-26 20:43:16 -0500 |
commit | 3eacdf58c2c0b9507afedfc19108e98b992c31e4 (patch) | |
tree | d95e7e022ff6e6181edce43fe97cf2883b5a91ed /drivers/misc | |
parent | dd0a251c8e087bca05e8f9a3657078591ae6e12b (diff) | |
parent | 5376071069ec8a7e6a8112beab16fc24f5139475 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/Kconfig | 9 | ||||
-rw-r--r-- | drivers/misc/Makefile | 2 | ||||
-rw-r--r-- | drivers/misc/eeprom/Kconfig | 59 | ||||
-rw-r--r-- | drivers/misc/eeprom/Makefile | 4 | ||||
-rw-r--r-- | drivers/misc/eeprom/at24.c | 582 | ||||
-rw-r--r-- | drivers/misc/eeprom/at25.c | 389 | ||||
-rw-r--r-- | drivers/misc/eeprom/eeprom.c | 257 | ||||
-rw-r--r-- | drivers/misc/eeprom/eeprom_93cx6.c (renamed from drivers/misc/eeprom_93cx6.c) | 0 |
8 files changed, 1293 insertions, 9 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 419c378bd24b..56073199ceba 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig | |||
@@ -87,14 +87,6 @@ config PHANTOM | |||
87 | If you choose to build module, its name will be phantom. If unsure, | 87 | If you choose to build module, its name will be phantom. If unsure, |
88 | say N here. | 88 | say N here. |
89 | 89 | ||
90 | config EEPROM_93CX6 | ||
91 | tristate "EEPROM 93CX6 support" | ||
92 | ---help--- | ||
93 | This is a driver for the EEPROM chipsets 93c46 and 93c66. | ||
94 | The driver supports both read as well as write commands. | ||
95 | |||
96 | If unsure, say N. | ||
97 | |||
98 | config SGI_IOC4 | 90 | config SGI_IOC4 |
99 | tristate "SGI IOC4 Base IO support" | 91 | tristate "SGI IOC4 Base IO support" |
100 | depends on PCI | 92 | depends on PCI |
@@ -231,5 +223,6 @@ config DELL_LAPTOP | |||
231 | laptops. | 223 | laptops. |
232 | 224 | ||
233 | source "drivers/misc/c2port/Kconfig" | 225 | source "drivers/misc/c2port/Kconfig" |
226 | source "drivers/misc/eeprom/Kconfig" | ||
234 | 227 | ||
235 | endif # MISC_DEVICES | 228 | endif # MISC_DEVICES |
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index d5749a7bc777..bc1199830554 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile | |||
@@ -13,10 +13,10 @@ obj-$(CONFIG_TIFM_CORE) += tifm_core.o | |||
13 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o | 13 | obj-$(CONFIG_TIFM_7XX1) += tifm_7xx1.o |
14 | obj-$(CONFIG_PHANTOM) += phantom.o | 14 | obj-$(CONFIG_PHANTOM) += phantom.o |
15 | obj-$(CONFIG_SGI_IOC4) += ioc4.o | 15 | obj-$(CONFIG_SGI_IOC4) += ioc4.o |
16 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o | ||
17 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o | 16 | obj-$(CONFIG_ENCLOSURE_SERVICES) += enclosure.o |
18 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o | 17 | obj-$(CONFIG_KGDB_TESTS) += kgdbts.o |
19 | obj-$(CONFIG_SGI_XP) += sgi-xp/ | 18 | obj-$(CONFIG_SGI_XP) += sgi-xp/ |
20 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ | 19 | obj-$(CONFIG_SGI_GRU) += sgi-gru/ |
21 | obj-$(CONFIG_HP_ILO) += hpilo.o | 20 | obj-$(CONFIG_HP_ILO) += hpilo.o |
22 | obj-$(CONFIG_C2PORT) += c2port/ | 21 | obj-$(CONFIG_C2PORT) += c2port/ |
22 | obj-y += eeprom/ | ||
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig new file mode 100644 index 000000000000..c76df8cda5ef --- /dev/null +++ b/drivers/misc/eeprom/Kconfig | |||
@@ -0,0 +1,59 @@ | |||
1 | menu "EEPROM support" | ||
2 | |||
3 | config EEPROM_AT24 | ||
4 | tristate "I2C EEPROMs from most vendors" | ||
5 | depends on I2C && SYSFS && EXPERIMENTAL | ||
6 | help | ||
7 | Enable this driver to get read/write support to most I2C EEPROMs, | ||
8 | after you configure the driver to know about each EEPROM on | ||
9 | your target board. Use these generic chip names, instead of | ||
10 | vendor-specific ones like at24c64 or 24lc02: | ||
11 | |||
12 | 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08, | ||
13 | 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024 | ||
14 | |||
15 | Unless you like data loss puzzles, always be sure that any chip | ||
16 | you configure as a 24c32 (32 kbit) or larger is NOT really a | ||
17 | 24c16 (16 kbit) or smaller, and vice versa. Marking the chip | ||
18 | as read-only won't help recover from this. Also, if your chip | ||
19 | has any software write-protect mechanism you may want to review the | ||
20 | code to make sure this driver won't turn it on by accident. | ||
21 | |||
22 | If you use this with an SMBus adapter instead of an I2C adapter, | ||
23 | full functionality is not available. Only smaller devices are | ||
24 | supported (24c16 and below, max 4 kByte). | ||
25 | |||
26 | This driver can also be built as a module. If so, the module | ||
27 | will be called at24. | ||
28 | |||
29 | config EEPROM_AT25 | ||
30 | tristate "SPI EEPROMs from most vendors" | ||
31 | depends on SPI && SYSFS | ||
32 | help | ||
33 | Enable this driver to get read/write support to most SPI EEPROMs, | ||
34 | after you configure the board init code to know about each eeprom | ||
35 | on your target board. | ||
36 | |||
37 | This driver can also be built as a module. If so, the module | ||
38 | will be called at25. | ||
39 | |||
40 | config EEPROM_LEGACY | ||
41 | tristate "Old I2C EEPROM reader" | ||
42 | depends on I2C && SYSFS | ||
43 | help | ||
44 | If you say yes here you get read-only access to the EEPROM data | ||
45 | available on modern memory DIMMs and Sony Vaio laptops via I2C. Such | ||
46 | EEPROMs could theoretically be available on other devices as well. | ||
47 | |||
48 | This driver can also be built as a module. If so, the module | ||
49 | will be called eeprom. | ||
50 | |||
51 | config EEPROM_93CX6 | ||
52 | tristate "EEPROM 93CX6 support" | ||
53 | help | ||
54 | This is a driver for the EEPROM chipsets 93c46 and 93c66. | ||
55 | The driver supports both read as well as write commands. | ||
56 | |||
57 | If unsure, say N. | ||
58 | |||
59 | endmenu | ||
diff --git a/drivers/misc/eeprom/Makefile b/drivers/misc/eeprom/Makefile new file mode 100644 index 000000000000..539dd8f88128 --- /dev/null +++ b/drivers/misc/eeprom/Makefile | |||
@@ -0,0 +1,4 @@ | |||
1 | obj-$(CONFIG_EEPROM_AT24) += at24.o | ||
2 | obj-$(CONFIG_EEPROM_AT25) += at25.o | ||
3 | obj-$(CONFIG_EEPROM_LEGACY) += eeprom.o | ||
4 | obj-$(CONFIG_EEPROM_93CX6) += eeprom_93cx6.o | ||
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c new file mode 100644 index 000000000000..d4775528abc6 --- /dev/null +++ b/drivers/misc/eeprom/at24.c | |||
@@ -0,0 +1,582 @@ | |||
1 | /* | ||
2 | * at24.c - handle most I2C EEPROMs | ||
3 | * | ||
4 | * Copyright (C) 2005-2007 David Brownell | ||
5 | * Copyright (C) 2008 Wolfram Sang, Pengutronix | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License as published by | ||
9 | * the Free Software Foundation; either version 2 of the License, or | ||
10 | * (at your option) any later version. | ||
11 | */ | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/mutex.h> | ||
18 | #include <linux/sysfs.h> | ||
19 | #include <linux/mod_devicetable.h> | ||
20 | #include <linux/log2.h> | ||
21 | #include <linux/bitops.h> | ||
22 | #include <linux/jiffies.h> | ||
23 | #include <linux/i2c.h> | ||
24 | #include <linux/i2c/at24.h> | ||
25 | |||
26 | /* | ||
27 | * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. | ||
28 | * Differences between different vendor product lines (like Atmel AT24C or | ||
29 | * MicroChip 24LC, etc) won't much matter for typical read/write access. | ||
30 | * There are also I2C RAM chips, likewise interchangeable. One example | ||
31 | * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes). | ||
32 | * | ||
33 | * However, misconfiguration can lose data. "Set 16-bit memory address" | ||
34 | * to a part with 8-bit addressing will overwrite data. Writing with too | ||
35 | * big a page size also loses data. And it's not safe to assume that the | ||
36 | * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC | ||
37 | * uses 0x51, for just one example. | ||
38 | * | ||
39 | * Accordingly, explicit board-specific configuration data should be used | ||
40 | * in almost all cases. (One partial exception is an SMBus used to access | ||
41 | * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.) | ||
42 | * | ||
43 | * So this driver uses "new style" I2C driver binding, expecting to be | ||
44 | * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or | ||
45 | * similar kernel-resident tables; or, configuration data coming from | ||
46 | * a bootloader. | ||
47 | * | ||
48 | * Other than binding model, current differences from "eeprom" driver are | ||
49 | * that this one handles write access and isn't restricted to 24c02 devices. | ||
50 | * It also handles larger devices (32 kbit and up) with two-byte addresses, | ||
51 | * which won't work on pure SMBus systems. | ||
52 | */ | ||
53 | |||
54 | struct at24_data { | ||
55 | struct at24_platform_data chip; | ||
56 | bool use_smbus; | ||
57 | |||
58 | /* | ||
59 | * Lock protects against activities from other Linux tasks, | ||
60 | * but not from changes by other I2C masters. | ||
61 | */ | ||
62 | struct mutex lock; | ||
63 | struct bin_attribute bin; | ||
64 | |||
65 | u8 *writebuf; | ||
66 | unsigned write_max; | ||
67 | unsigned num_addresses; | ||
68 | |||
69 | /* | ||
70 | * Some chips tie up multiple I2C addresses; dummy devices reserve | ||
71 | * them for us, and we'll use them with SMBus calls. | ||
72 | */ | ||
73 | struct i2c_client *client[]; | ||
74 | }; | ||
75 | |||
76 | /* | ||
77 | * This parameter is to help this driver avoid blocking other drivers out | ||
78 | * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C | ||
79 | * clock, one 256 byte read takes about 1/43 second which is excessive; | ||
80 | * but the 1/170 second it takes at 400 kHz may be quite reasonable; and | ||
81 | * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible. | ||
82 | * | ||
83 | * This value is forced to be a power of two so that writes align on pages. | ||
84 | */ | ||
85 | static unsigned io_limit = 128; | ||
86 | module_param(io_limit, uint, 0); | ||
87 | MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)"); | ||
88 | |||
89 | /* | ||
90 | * Specs often allow 5 msec for a page write, sometimes 20 msec; | ||
91 | * it's important to recover from write timeouts. | ||
92 | */ | ||
93 | static unsigned write_timeout = 25; | ||
94 | module_param(write_timeout, uint, 0); | ||
95 | MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)"); | ||
96 | |||
97 | #define AT24_SIZE_BYTELEN 5 | ||
98 | #define AT24_SIZE_FLAGS 8 | ||
99 | |||
100 | #define AT24_BITMASK(x) (BIT(x) - 1) | ||
101 | |||
102 | /* create non-zero magic value for given eeprom parameters */ | ||
103 | #define AT24_DEVICE_MAGIC(_len, _flags) \ | ||
104 | ((1 << AT24_SIZE_FLAGS | (_flags)) \ | ||
105 | << AT24_SIZE_BYTELEN | ilog2(_len)) | ||
106 | |||
107 | static const struct i2c_device_id at24_ids[] = { | ||
108 | /* needs 8 addresses as A0-A2 are ignored */ | ||
109 | { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) }, | ||
110 | /* old variants can't be handled with this generic entry! */ | ||
111 | { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) }, | ||
112 | { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) }, | ||
113 | /* spd is a 24c02 in memory DIMMs */ | ||
114 | { "spd", AT24_DEVICE_MAGIC(2048 / 8, | ||
115 | AT24_FLAG_READONLY | AT24_FLAG_IRUGO) }, | ||
116 | { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) }, | ||
117 | /* 24rf08 quirk is handled at i2c-core */ | ||
118 | { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) }, | ||
119 | { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) }, | ||
120 | { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) }, | ||
121 | { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) }, | ||
122 | { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) }, | ||
123 | { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) }, | ||
124 | { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) }, | ||
125 | { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) }, | ||
126 | { "at24", 0 }, | ||
127 | { /* END OF LIST */ } | ||
128 | }; | ||
129 | MODULE_DEVICE_TABLE(i2c, at24_ids); | ||
130 | |||
131 | /*-------------------------------------------------------------------------*/ | ||
132 | |||
133 | /* | ||
134 | * This routine supports chips which consume multiple I2C addresses. It | ||
135 | * computes the addressing information to be used for a given r/w request. | ||
136 | * Assumes that sanity checks for offset happened at sysfs-layer. | ||
137 | */ | ||
138 | static struct i2c_client *at24_translate_offset(struct at24_data *at24, | ||
139 | unsigned *offset) | ||
140 | { | ||
141 | unsigned i; | ||
142 | |||
143 | if (at24->chip.flags & AT24_FLAG_ADDR16) { | ||
144 | i = *offset >> 16; | ||
145 | *offset &= 0xffff; | ||
146 | } else { | ||
147 | i = *offset >> 8; | ||
148 | *offset &= 0xff; | ||
149 | } | ||
150 | |||
151 | return at24->client[i]; | ||
152 | } | ||
153 | |||
154 | static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf, | ||
155 | unsigned offset, size_t count) | ||
156 | { | ||
157 | struct i2c_msg msg[2]; | ||
158 | u8 msgbuf[2]; | ||
159 | struct i2c_client *client; | ||
160 | int status, i; | ||
161 | |||
162 | memset(msg, 0, sizeof(msg)); | ||
163 | |||
164 | /* | ||
165 | * REVISIT some multi-address chips don't rollover page reads to | ||
166 | * the next slave address, so we may need to truncate the count. | ||
167 | * Those chips might need another quirk flag. | ||
168 | * | ||
169 | * If the real hardware used four adjacent 24c02 chips and that | ||
170 | * were misconfigured as one 24c08, that would be a similar effect: | ||
171 | * one "eeprom" file not four, but larger reads would fail when | ||
172 | * they crossed certain pages. | ||
173 | */ | ||
174 | |||
175 | /* | ||
176 | * Slave address and byte offset derive from the offset. Always | ||
177 | * set the byte address; on a multi-master board, another master | ||
178 | * may have changed the chip's "current" address pointer. | ||
179 | */ | ||
180 | client = at24_translate_offset(at24, &offset); | ||
181 | |||
182 | if (count > io_limit) | ||
183 | count = io_limit; | ||
184 | |||
185 | /* Smaller eeproms can work given some SMBus extension calls */ | ||
186 | if (at24->use_smbus) { | ||
187 | if (count > I2C_SMBUS_BLOCK_MAX) | ||
188 | count = I2C_SMBUS_BLOCK_MAX; | ||
189 | status = i2c_smbus_read_i2c_block_data(client, offset, | ||
190 | count, buf); | ||
191 | dev_dbg(&client->dev, "smbus read %zu@%d --> %d\n", | ||
192 | count, offset, status); | ||
193 | return (status < 0) ? -EIO : status; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * When we have a better choice than SMBus calls, use a combined | ||
198 | * I2C message. Write address; then read up to io_limit data bytes. | ||
199 | * Note that read page rollover helps us here (unlike writes). | ||
200 | * msgbuf is u8 and will cast to our needs. | ||
201 | */ | ||
202 | i = 0; | ||
203 | if (at24->chip.flags & AT24_FLAG_ADDR16) | ||
204 | msgbuf[i++] = offset >> 8; | ||
205 | msgbuf[i++] = offset; | ||
206 | |||
207 | msg[0].addr = client->addr; | ||
208 | msg[0].buf = msgbuf; | ||
209 | msg[0].len = i; | ||
210 | |||
211 | msg[1].addr = client->addr; | ||
212 | msg[1].flags = I2C_M_RD; | ||
213 | msg[1].buf = buf; | ||
214 | msg[1].len = count; | ||
215 | |||
216 | status = i2c_transfer(client->adapter, msg, 2); | ||
217 | dev_dbg(&client->dev, "i2c read %zu@%d --> %d\n", | ||
218 | count, offset, status); | ||
219 | |||
220 | if (status == 2) | ||
221 | return count; | ||
222 | else if (status >= 0) | ||
223 | return -EIO; | ||
224 | else | ||
225 | return status; | ||
226 | } | ||
227 | |||
228 | static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr, | ||
229 | char *buf, loff_t off, size_t count) | ||
230 | { | ||
231 | struct at24_data *at24; | ||
232 | ssize_t retval = 0; | ||
233 | |||
234 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
235 | |||
236 | if (unlikely(!count)) | ||
237 | return count; | ||
238 | |||
239 | /* | ||
240 | * Read data from chip, protecting against concurrent updates | ||
241 | * from this host, but not from other I2C masters. | ||
242 | */ | ||
243 | mutex_lock(&at24->lock); | ||
244 | |||
245 | while (count) { | ||
246 | ssize_t status; | ||
247 | |||
248 | status = at24_eeprom_read(at24, buf, off, count); | ||
249 | if (status <= 0) { | ||
250 | if (retval == 0) | ||
251 | retval = status; | ||
252 | break; | ||
253 | } | ||
254 | buf += status; | ||
255 | off += status; | ||
256 | count -= status; | ||
257 | retval += status; | ||
258 | } | ||
259 | |||
260 | mutex_unlock(&at24->lock); | ||
261 | |||
262 | return retval; | ||
263 | } | ||
264 | |||
265 | |||
266 | /* | ||
267 | * REVISIT: export at24_bin{read,write}() to let other kernel code use | ||
268 | * eeprom data. For example, it might hold a board's Ethernet address, or | ||
269 | * board-specific calibration data generated on the manufacturing floor. | ||
270 | */ | ||
271 | |||
272 | |||
273 | /* | ||
274 | * Note that if the hardware write-protect pin is pulled high, the whole | ||
275 | * chip is normally write protected. But there are plenty of product | ||
276 | * variants here, including OTP fuses and partial chip protect. | ||
277 | * | ||
278 | * We only use page mode writes; the alternative is sloooow. This routine | ||
279 | * writes at most one page. | ||
280 | */ | ||
281 | static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf, | ||
282 | unsigned offset, size_t count) | ||
283 | { | ||
284 | struct i2c_client *client; | ||
285 | struct i2c_msg msg; | ||
286 | ssize_t status; | ||
287 | unsigned long timeout, write_time; | ||
288 | unsigned next_page; | ||
289 | |||
290 | /* Get corresponding I2C address and adjust offset */ | ||
291 | client = at24_translate_offset(at24, &offset); | ||
292 | |||
293 | /* write_max is at most a page */ | ||
294 | if (count > at24->write_max) | ||
295 | count = at24->write_max; | ||
296 | |||
297 | /* Never roll over backwards, to the start of this page */ | ||
298 | next_page = roundup(offset + 1, at24->chip.page_size); | ||
299 | if (offset + count > next_page) | ||
300 | count = next_page - offset; | ||
301 | |||
302 | /* If we'll use I2C calls for I/O, set up the message */ | ||
303 | if (!at24->use_smbus) { | ||
304 | int i = 0; | ||
305 | |||
306 | msg.addr = client->addr; | ||
307 | msg.flags = 0; | ||
308 | |||
309 | /* msg.buf is u8 and casts will mask the values */ | ||
310 | msg.buf = at24->writebuf; | ||
311 | if (at24->chip.flags & AT24_FLAG_ADDR16) | ||
312 | msg.buf[i++] = offset >> 8; | ||
313 | |||
314 | msg.buf[i++] = offset; | ||
315 | memcpy(&msg.buf[i], buf, count); | ||
316 | msg.len = i + count; | ||
317 | } | ||
318 | |||
319 | /* | ||
320 | * Writes fail if the previous one didn't complete yet. We may | ||
321 | * loop a few times until this one succeeds, waiting at least | ||
322 | * long enough for one entire page write to work. | ||
323 | */ | ||
324 | timeout = jiffies + msecs_to_jiffies(write_timeout); | ||
325 | do { | ||
326 | write_time = jiffies; | ||
327 | if (at24->use_smbus) { | ||
328 | status = i2c_smbus_write_i2c_block_data(client, | ||
329 | offset, count, buf); | ||
330 | if (status == 0) | ||
331 | status = count; | ||
332 | } else { | ||
333 | status = i2c_transfer(client->adapter, &msg, 1); | ||
334 | if (status == 1) | ||
335 | status = count; | ||
336 | } | ||
337 | dev_dbg(&client->dev, "write %zu@%d --> %zd (%ld)\n", | ||
338 | count, offset, status, jiffies); | ||
339 | |||
340 | if (status == count) | ||
341 | return count; | ||
342 | |||
343 | /* REVISIT: at HZ=100, this is sloooow */ | ||
344 | msleep(1); | ||
345 | } while (time_before(write_time, timeout)); | ||
346 | |||
347 | return -ETIMEDOUT; | ||
348 | } | ||
349 | |||
350 | static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr, | ||
351 | char *buf, loff_t off, size_t count) | ||
352 | { | ||
353 | struct at24_data *at24; | ||
354 | ssize_t retval = 0; | ||
355 | |||
356 | at24 = dev_get_drvdata(container_of(kobj, struct device, kobj)); | ||
357 | |||
358 | if (unlikely(!count)) | ||
359 | return count; | ||
360 | |||
361 | /* | ||
362 | * Write data to chip, protecting against concurrent updates | ||
363 | * from this host, but not from other I2C masters. | ||
364 | */ | ||
365 | mutex_lock(&at24->lock); | ||
366 | |||
367 | while (count) { | ||
368 | ssize_t status; | ||
369 | |||
370 | status = at24_eeprom_write(at24, buf, off, count); | ||
371 | if (status <= 0) { | ||
372 | if (retval == 0) | ||
373 | retval = status; | ||
374 | break; | ||
375 | } | ||
376 | buf += status; | ||
377 | off += status; | ||
378 | count -= status; | ||
379 | retval += status; | ||
380 | } | ||
381 | |||
382 | mutex_unlock(&at24->lock); | ||
383 | |||
384 | return retval; | ||
385 | } | ||
386 | |||
387 | /*-------------------------------------------------------------------------*/ | ||
388 | |||
389 | static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) | ||
390 | { | ||
391 | struct at24_platform_data chip; | ||
392 | bool writable; | ||
393 | bool use_smbus = false; | ||
394 | struct at24_data *at24; | ||
395 | int err; | ||
396 | unsigned i, num_addresses; | ||
397 | kernel_ulong_t magic; | ||
398 | |||
399 | if (client->dev.platform_data) { | ||
400 | chip = *(struct at24_platform_data *)client->dev.platform_data; | ||
401 | } else { | ||
402 | if (!id->driver_data) { | ||
403 | err = -ENODEV; | ||
404 | goto err_out; | ||
405 | } | ||
406 | magic = id->driver_data; | ||
407 | chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN)); | ||
408 | magic >>= AT24_SIZE_BYTELEN; | ||
409 | chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS); | ||
410 | /* | ||
411 | * This is slow, but we can't know all eeproms, so we better | ||
412 | * play safe. Specifying custom eeprom-types via platform_data | ||
413 | * is recommended anyhow. | ||
414 | */ | ||
415 | chip.page_size = 1; | ||
416 | } | ||
417 | |||
418 | if (!is_power_of_2(chip.byte_len)) | ||
419 | dev_warn(&client->dev, | ||
420 | "byte_len looks suspicious (no power of 2)!\n"); | ||
421 | if (!is_power_of_2(chip.page_size)) | ||
422 | dev_warn(&client->dev, | ||
423 | "page_size looks suspicious (no power of 2)!\n"); | ||
424 | |||
425 | /* Use I2C operations unless we're stuck with SMBus extensions. */ | ||
426 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
427 | if (chip.flags & AT24_FLAG_ADDR16) { | ||
428 | err = -EPFNOSUPPORT; | ||
429 | goto err_out; | ||
430 | } | ||
431 | if (!i2c_check_functionality(client->adapter, | ||
432 | I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { | ||
433 | err = -EPFNOSUPPORT; | ||
434 | goto err_out; | ||
435 | } | ||
436 | use_smbus = true; | ||
437 | } | ||
438 | |||
439 | if (chip.flags & AT24_FLAG_TAKE8ADDR) | ||
440 | num_addresses = 8; | ||
441 | else | ||
442 | num_addresses = DIV_ROUND_UP(chip.byte_len, | ||
443 | (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256); | ||
444 | |||
445 | at24 = kzalloc(sizeof(struct at24_data) + | ||
446 | num_addresses * sizeof(struct i2c_client *), GFP_KERNEL); | ||
447 | if (!at24) { | ||
448 | err = -ENOMEM; | ||
449 | goto err_out; | ||
450 | } | ||
451 | |||
452 | mutex_init(&at24->lock); | ||
453 | at24->use_smbus = use_smbus; | ||
454 | at24->chip = chip; | ||
455 | at24->num_addresses = num_addresses; | ||
456 | |||
457 | /* | ||
458 | * Export the EEPROM bytes through sysfs, since that's convenient. | ||
459 | * By default, only root should see the data (maybe passwords etc) | ||
460 | */ | ||
461 | at24->bin.attr.name = "eeprom"; | ||
462 | at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; | ||
463 | at24->bin.read = at24_bin_read; | ||
464 | at24->bin.size = chip.byte_len; | ||
465 | |||
466 | writable = !(chip.flags & AT24_FLAG_READONLY); | ||
467 | if (writable) { | ||
468 | if (!use_smbus || i2c_check_functionality(client->adapter, | ||
469 | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) { | ||
470 | |||
471 | unsigned write_max = chip.page_size; | ||
472 | |||
473 | at24->bin.write = at24_bin_write; | ||
474 | at24->bin.attr.mode |= S_IWUSR; | ||
475 | |||
476 | if (write_max > io_limit) | ||
477 | write_max = io_limit; | ||
478 | if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX) | ||
479 | write_max = I2C_SMBUS_BLOCK_MAX; | ||
480 | at24->write_max = write_max; | ||
481 | |||
482 | /* buffer (data + address at the beginning) */ | ||
483 | at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL); | ||
484 | if (!at24->writebuf) { | ||
485 | err = -ENOMEM; | ||
486 | goto err_struct; | ||
487 | } | ||
488 | } else { | ||
489 | dev_warn(&client->dev, | ||
490 | "cannot write due to controller restrictions."); | ||
491 | } | ||
492 | } | ||
493 | |||
494 | at24->client[0] = client; | ||
495 | |||
496 | /* use dummy devices for multiple-address chips */ | ||
497 | for (i = 1; i < num_addresses; i++) { | ||
498 | at24->client[i] = i2c_new_dummy(client->adapter, | ||
499 | client->addr + i); | ||
500 | if (!at24->client[i]) { | ||
501 | dev_err(&client->dev, "address 0x%02x unavailable\n", | ||
502 | client->addr + i); | ||
503 | err = -EADDRINUSE; | ||
504 | goto err_clients; | ||
505 | } | ||
506 | } | ||
507 | |||
508 | err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin); | ||
509 | if (err) | ||
510 | goto err_clients; | ||
511 | |||
512 | i2c_set_clientdata(client, at24); | ||
513 | |||
514 | dev_info(&client->dev, "%zu byte %s EEPROM %s\n", | ||
515 | at24->bin.size, client->name, | ||
516 | writable ? "(writable)" : "(read-only)"); | ||
517 | dev_dbg(&client->dev, | ||
518 | "page_size %d, num_addresses %d, write_max %d%s\n", | ||
519 | chip.page_size, num_addresses, | ||
520 | at24->write_max, | ||
521 | use_smbus ? ", use_smbus" : ""); | ||
522 | |||
523 | return 0; | ||
524 | |||
525 | err_clients: | ||
526 | for (i = 1; i < num_addresses; i++) | ||
527 | if (at24->client[i]) | ||
528 | i2c_unregister_device(at24->client[i]); | ||
529 | |||
530 | kfree(at24->writebuf); | ||
531 | err_struct: | ||
532 | kfree(at24); | ||
533 | err_out: | ||
534 | dev_dbg(&client->dev, "probe error %d\n", err); | ||
535 | return err; | ||
536 | } | ||
537 | |||
538 | static int __devexit at24_remove(struct i2c_client *client) | ||
539 | { | ||
540 | struct at24_data *at24; | ||
541 | int i; | ||
542 | |||
543 | at24 = i2c_get_clientdata(client); | ||
544 | sysfs_remove_bin_file(&client->dev.kobj, &at24->bin); | ||
545 | |||
546 | for (i = 1; i < at24->num_addresses; i++) | ||
547 | i2c_unregister_device(at24->client[i]); | ||
548 | |||
549 | kfree(at24->writebuf); | ||
550 | kfree(at24); | ||
551 | i2c_set_clientdata(client, NULL); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | /*-------------------------------------------------------------------------*/ | ||
556 | |||
557 | static struct i2c_driver at24_driver = { | ||
558 | .driver = { | ||
559 | .name = "at24", | ||
560 | .owner = THIS_MODULE, | ||
561 | }, | ||
562 | .probe = at24_probe, | ||
563 | .remove = __devexit_p(at24_remove), | ||
564 | .id_table = at24_ids, | ||
565 | }; | ||
566 | |||
567 | static int __init at24_init(void) | ||
568 | { | ||
569 | io_limit = rounddown_pow_of_two(io_limit); | ||
570 | return i2c_add_driver(&at24_driver); | ||
571 | } | ||
572 | module_init(at24_init); | ||
573 | |||
574 | static void __exit at24_exit(void) | ||
575 | { | ||
576 | i2c_del_driver(&at24_driver); | ||
577 | } | ||
578 | module_exit(at24_exit); | ||
579 | |||
580 | MODULE_DESCRIPTION("Driver for most I2C EEPROMs"); | ||
581 | MODULE_AUTHOR("David Brownell and Wolfram Sang"); | ||
582 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c new file mode 100644 index 000000000000..290dbe99647a --- /dev/null +++ b/drivers/misc/eeprom/at25.c | |||
@@ -0,0 +1,389 @@ | |||
1 | /* | ||
2 | * at25.c -- support most SPI EEPROMs, such as Atmel AT25 models | ||
3 | * | ||
4 | * Copyright (C) 2006 David Brownell | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/device.h> | ||
18 | #include <linux/sched.h> | ||
19 | |||
20 | #include <linux/spi/spi.h> | ||
21 | #include <linux/spi/eeprom.h> | ||
22 | |||
23 | |||
24 | /* | ||
25 | * NOTE: this is an *EEPROM* driver. The vagaries of product naming | ||
26 | * mean that some AT25 products are EEPROMs, and others are FLASH. | ||
27 | * Handle FLASH chips with the drivers/mtd/devices/m25p80.c driver, | ||
28 | * not this one! | ||
29 | */ | ||
30 | |||
31 | struct at25_data { | ||
32 | struct spi_device *spi; | ||
33 | struct mutex lock; | ||
34 | struct spi_eeprom chip; | ||
35 | struct bin_attribute bin; | ||
36 | unsigned addrlen; | ||
37 | }; | ||
38 | |||
39 | #define AT25_WREN 0x06 /* latch the write enable */ | ||
40 | #define AT25_WRDI 0x04 /* reset the write enable */ | ||
41 | #define AT25_RDSR 0x05 /* read status register */ | ||
42 | #define AT25_WRSR 0x01 /* write status register */ | ||
43 | #define AT25_READ 0x03 /* read byte(s) */ | ||
44 | #define AT25_WRITE 0x02 /* write byte(s)/sector */ | ||
45 | |||
46 | #define AT25_SR_nRDY 0x01 /* nRDY = write-in-progress */ | ||
47 | #define AT25_SR_WEN 0x02 /* write enable (latched) */ | ||
48 | #define AT25_SR_BP0 0x04 /* BP for software writeprotect */ | ||
49 | #define AT25_SR_BP1 0x08 | ||
50 | #define AT25_SR_WPEN 0x80 /* writeprotect enable */ | ||
51 | |||
52 | |||
53 | #define EE_MAXADDRLEN 3 /* 24 bit addresses, up to 2 MBytes */ | ||
54 | |||
55 | /* Specs often allow 5 msec for a page write, sometimes 20 msec; | ||
56 | * it's important to recover from write timeouts. | ||
57 | */ | ||
58 | #define EE_TIMEOUT 25 | ||
59 | |||
60 | /*-------------------------------------------------------------------------*/ | ||
61 | |||
62 | #define io_limit PAGE_SIZE /* bytes */ | ||
63 | |||
64 | static ssize_t | ||
65 | at25_ee_read( | ||
66 | struct at25_data *at25, | ||
67 | char *buf, | ||
68 | unsigned offset, | ||
69 | size_t count | ||
70 | ) | ||
71 | { | ||
72 | u8 command[EE_MAXADDRLEN + 1]; | ||
73 | u8 *cp; | ||
74 | ssize_t status; | ||
75 | struct spi_transfer t[2]; | ||
76 | struct spi_message m; | ||
77 | |||
78 | cp = command; | ||
79 | *cp++ = AT25_READ; | ||
80 | |||
81 | /* 8/16/24-bit address is written MSB first */ | ||
82 | switch (at25->addrlen) { | ||
83 | default: /* case 3 */ | ||
84 | *cp++ = offset >> 16; | ||
85 | case 2: | ||
86 | *cp++ = offset >> 8; | ||
87 | case 1: | ||
88 | case 0: /* can't happen: for better codegen */ | ||
89 | *cp++ = offset >> 0; | ||
90 | } | ||
91 | |||
92 | spi_message_init(&m); | ||
93 | memset(t, 0, sizeof t); | ||
94 | |||
95 | t[0].tx_buf = command; | ||
96 | t[0].len = at25->addrlen + 1; | ||
97 | spi_message_add_tail(&t[0], &m); | ||
98 | |||
99 | t[1].rx_buf = buf; | ||
100 | t[1].len = count; | ||
101 | spi_message_add_tail(&t[1], &m); | ||
102 | |||
103 | mutex_lock(&at25->lock); | ||
104 | |||
105 | /* Read it all at once. | ||
106 | * | ||
107 | * REVISIT that's potentially a problem with large chips, if | ||
108 | * other devices on the bus need to be accessed regularly or | ||
109 | * this chip is clocked very slowly | ||
110 | */ | ||
111 | status = spi_sync(at25->spi, &m); | ||
112 | dev_dbg(&at25->spi->dev, | ||
113 | "read %Zd bytes at %d --> %d\n", | ||
114 | count, offset, (int) status); | ||
115 | |||
116 | mutex_unlock(&at25->lock); | ||
117 | return status ? status : count; | ||
118 | } | ||
119 | |||
120 | static ssize_t | ||
121 | at25_bin_read(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
122 | char *buf, loff_t off, size_t count) | ||
123 | { | ||
124 | struct device *dev; | ||
125 | struct at25_data *at25; | ||
126 | |||
127 | dev = container_of(kobj, struct device, kobj); | ||
128 | at25 = dev_get_drvdata(dev); | ||
129 | |||
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 | } | ||
139 | |||
140 | |||
141 | static ssize_t | ||
142 | at25_ee_write(struct at25_data *at25, char *buf, loff_t off, size_t count) | ||
143 | { | ||
144 | ssize_t status = 0; | ||
145 | unsigned written = 0; | ||
146 | unsigned buf_size; | ||
147 | u8 *bounce; | ||
148 | |||
149 | /* Temp buffer starts with command and address */ | ||
150 | buf_size = at25->chip.page_size; | ||
151 | if (buf_size > io_limit) | ||
152 | buf_size = io_limit; | ||
153 | bounce = kmalloc(buf_size + at25->addrlen + 1, GFP_KERNEL); | ||
154 | if (!bounce) | ||
155 | return -ENOMEM; | ||
156 | |||
157 | /* For write, rollover is within the page ... so we write at | ||
158 | * most one page, then manually roll over to the next page. | ||
159 | */ | ||
160 | bounce[0] = AT25_WRITE; | ||
161 | mutex_lock(&at25->lock); | ||
162 | do { | ||
163 | unsigned long timeout, retries; | ||
164 | unsigned segment; | ||
165 | unsigned offset = (unsigned) off; | ||
166 | u8 *cp = bounce + 1; | ||
167 | |||
168 | *cp = AT25_WREN; | ||
169 | status = spi_write(at25->spi, cp, 1); | ||
170 | if (status < 0) { | ||
171 | dev_dbg(&at25->spi->dev, "WREN --> %d\n", | ||
172 | (int) status); | ||
173 | break; | ||
174 | } | ||
175 | |||
176 | /* 8/16/24-bit address is written MSB first */ | ||
177 | switch (at25->addrlen) { | ||
178 | default: /* case 3 */ | ||
179 | *cp++ = offset >> 16; | ||
180 | case 2: | ||
181 | *cp++ = offset >> 8; | ||
182 | case 1: | ||
183 | case 0: /* can't happen: for better codegen */ | ||
184 | *cp++ = offset >> 0; | ||
185 | } | ||
186 | |||
187 | /* Write as much of a page as we can */ | ||
188 | segment = buf_size - (offset % buf_size); | ||
189 | if (segment > count) | ||
190 | segment = count; | ||
191 | memcpy(cp, buf, segment); | ||
192 | status = spi_write(at25->spi, bounce, | ||
193 | segment + at25->addrlen + 1); | ||
194 | dev_dbg(&at25->spi->dev, | ||
195 | "write %u bytes at %u --> %d\n", | ||
196 | segment, offset, (int) status); | ||
197 | if (status < 0) | ||
198 | break; | ||
199 | |||
200 | /* REVISIT this should detect (or prevent) failed writes | ||
201 | * to readonly sections of the EEPROM... | ||
202 | */ | ||
203 | |||
204 | /* Wait for non-busy status */ | ||
205 | timeout = jiffies + msecs_to_jiffies(EE_TIMEOUT); | ||
206 | retries = 0; | ||
207 | do { | ||
208 | int sr; | ||
209 | |||
210 | sr = spi_w8r8(at25->spi, AT25_RDSR); | ||
211 | if (sr < 0 || (sr & AT25_SR_nRDY)) { | ||
212 | dev_dbg(&at25->spi->dev, | ||
213 | "rdsr --> %d (%02x)\n", sr, sr); | ||
214 | /* at HZ=100, this is sloooow */ | ||
215 | msleep(1); | ||
216 | continue; | ||
217 | } | ||
218 | if (!(sr & AT25_SR_nRDY)) | ||
219 | break; | ||
220 | } while (retries++ < 3 || time_before_eq(jiffies, timeout)); | ||
221 | |||
222 | if (time_after(jiffies, timeout)) { | ||
223 | dev_err(&at25->spi->dev, | ||
224 | "write %d bytes offset %d, " | ||
225 | "timeout after %u msecs\n", | ||
226 | segment, offset, | ||
227 | jiffies_to_msecs(jiffies - | ||
228 | (timeout - EE_TIMEOUT))); | ||
229 | status = -ETIMEDOUT; | ||
230 | break; | ||
231 | } | ||
232 | |||
233 | off += segment; | ||
234 | buf += segment; | ||
235 | count -= segment; | ||
236 | written += segment; | ||
237 | |||
238 | } while (count > 0); | ||
239 | |||
240 | mutex_unlock(&at25->lock); | ||
241 | |||
242 | kfree(bounce); | ||
243 | return written ? written : status; | ||
244 | } | ||
245 | |||
246 | static ssize_t | ||
247 | at25_bin_write(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
248 | char *buf, loff_t off, size_t count) | ||
249 | { | ||
250 | struct device *dev; | ||
251 | struct at25_data *at25; | ||
252 | |||
253 | dev = container_of(kobj, struct device, kobj); | ||
254 | at25 = dev_get_drvdata(dev); | ||
255 | |||
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 | } | ||
265 | |||
266 | /*-------------------------------------------------------------------------*/ | ||
267 | |||
268 | static int at25_probe(struct spi_device *spi) | ||
269 | { | ||
270 | struct at25_data *at25 = NULL; | ||
271 | const struct spi_eeprom *chip; | ||
272 | int err; | ||
273 | int sr; | ||
274 | int addrlen; | ||
275 | |||
276 | /* Chip description */ | ||
277 | chip = spi->dev.platform_data; | ||
278 | if (!chip) { | ||
279 | dev_dbg(&spi->dev, "no chip description\n"); | ||
280 | err = -ENODEV; | ||
281 | goto fail; | ||
282 | } | ||
283 | |||
284 | /* For now we only support 8/16/24 bit addressing */ | ||
285 | if (chip->flags & EE_ADDR1) | ||
286 | addrlen = 1; | ||
287 | else if (chip->flags & EE_ADDR2) | ||
288 | addrlen = 2; | ||
289 | else if (chip->flags & EE_ADDR3) | ||
290 | addrlen = 3; | ||
291 | else { | ||
292 | dev_dbg(&spi->dev, "unsupported address type\n"); | ||
293 | err = -EINVAL; | ||
294 | goto fail; | ||
295 | } | ||
296 | |||
297 | /* Ping the chip ... the status register is pretty portable, | ||
298 | * unlike probing manufacturer IDs. We do expect that system | ||
299 | * firmware didn't write it in the past few milliseconds! | ||
300 | */ | ||
301 | sr = spi_w8r8(spi, AT25_RDSR); | ||
302 | if (sr < 0 || sr & AT25_SR_nRDY) { | ||
303 | dev_dbg(&spi->dev, "rdsr --> %d (%02x)\n", sr, sr); | ||
304 | err = -ENXIO; | ||
305 | goto fail; | ||
306 | } | ||
307 | |||
308 | if (!(at25 = kzalloc(sizeof *at25, GFP_KERNEL))) { | ||
309 | err = -ENOMEM; | ||
310 | goto fail; | ||
311 | } | ||
312 | |||
313 | mutex_init(&at25->lock); | ||
314 | at25->chip = *chip; | ||
315 | at25->spi = spi_dev_get(spi); | ||
316 | dev_set_drvdata(&spi->dev, at25); | ||
317 | at25->addrlen = addrlen; | ||
318 | |||
319 | /* Export the EEPROM bytes through sysfs, since that's convenient. | ||
320 | * Default to root-only access to the data; EEPROMs often hold data | ||
321 | * that's sensitive for read and/or write, like ethernet addresses, | ||
322 | * security codes, board-specific manufacturing calibrations, etc. | ||
323 | */ | ||
324 | at25->bin.attr.name = "eeprom"; | ||
325 | at25->bin.attr.mode = S_IRUSR; | ||
326 | at25->bin.read = at25_bin_read; | ||
327 | |||
328 | at25->bin.size = at25->chip.byte_len; | ||
329 | if (!(chip->flags & EE_READONLY)) { | ||
330 | at25->bin.write = at25_bin_write; | ||
331 | at25->bin.attr.mode |= S_IWUSR; | ||
332 | } | ||
333 | |||
334 | err = sysfs_create_bin_file(&spi->dev.kobj, &at25->bin); | ||
335 | if (err) | ||
336 | goto fail; | ||
337 | |||
338 | dev_info(&spi->dev, "%Zd %s %s eeprom%s, pagesize %u\n", | ||
339 | (at25->bin.size < 1024) | ||
340 | ? at25->bin.size | ||
341 | : (at25->bin.size / 1024), | ||
342 | (at25->bin.size < 1024) ? "Byte" : "KByte", | ||
343 | at25->chip.name, | ||
344 | (chip->flags & EE_READONLY) ? " (readonly)" : "", | ||
345 | at25->chip.page_size); | ||
346 | return 0; | ||
347 | fail: | ||
348 | dev_dbg(&spi->dev, "probe err %d\n", err); | ||
349 | kfree(at25); | ||
350 | return err; | ||
351 | } | ||
352 | |||
353 | static int __devexit at25_remove(struct spi_device *spi) | ||
354 | { | ||
355 | struct at25_data *at25; | ||
356 | |||
357 | at25 = dev_get_drvdata(&spi->dev); | ||
358 | sysfs_remove_bin_file(&spi->dev.kobj, &at25->bin); | ||
359 | kfree(at25); | ||
360 | return 0; | ||
361 | } | ||
362 | |||
363 | /*-------------------------------------------------------------------------*/ | ||
364 | |||
365 | static struct spi_driver at25_driver = { | ||
366 | .driver = { | ||
367 | .name = "at25", | ||
368 | .owner = THIS_MODULE, | ||
369 | }, | ||
370 | .probe = at25_probe, | ||
371 | .remove = __devexit_p(at25_remove), | ||
372 | }; | ||
373 | |||
374 | static int __init at25_init(void) | ||
375 | { | ||
376 | return spi_register_driver(&at25_driver); | ||
377 | } | ||
378 | module_init(at25_init); | ||
379 | |||
380 | static void __exit at25_exit(void) | ||
381 | { | ||
382 | spi_unregister_driver(&at25_driver); | ||
383 | } | ||
384 | module_exit(at25_exit); | ||
385 | |||
386 | MODULE_DESCRIPTION("Driver for most SPI EEPROMs"); | ||
387 | MODULE_AUTHOR("David Brownell"); | ||
388 | MODULE_LICENSE("GPL"); | ||
389 | |||
diff --git a/drivers/misc/eeprom/eeprom.c b/drivers/misc/eeprom/eeprom.c new file mode 100644 index 000000000000..2c27193aeaa0 --- /dev/null +++ b/drivers/misc/eeprom/eeprom.c | |||
@@ -0,0 +1,257 @@ | |||
1 | /* | ||
2 | Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and | ||
3 | Philip Edelbrock <phil@netroedge.com> | ||
4 | Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> | ||
5 | Copyright (C) 2003 IBM Corp. | ||
6 | Copyright (C) 2004 Jean Delvare <khali@linux-fr.org> | ||
7 | |||
8 | This program is free software; you can redistribute it and/or modify | ||
9 | it under the terms of the GNU General Public License as published by | ||
10 | the Free Software Foundation; either version 2 of the License, or | ||
11 | (at your option) any later version. | ||
12 | |||
13 | This program is distributed in the hope that it will be useful, | ||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | GNU General Public License for more details. | ||
17 | |||
18 | You should have received a copy of the GNU General Public License | ||
19 | along with this program; if not, write to the Free Software | ||
20 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/jiffies.h> | ||
28 | #include <linux/i2c.h> | ||
29 | #include <linux/mutex.h> | ||
30 | |||
31 | /* Addresses to scan */ | ||
32 | static const unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54, | ||
33 | 0x55, 0x56, 0x57, I2C_CLIENT_END }; | ||
34 | |||
35 | /* Insmod parameters */ | ||
36 | I2C_CLIENT_INSMOD_1(eeprom); | ||
37 | |||
38 | |||
39 | /* Size of EEPROM in bytes */ | ||
40 | #define EEPROM_SIZE 256 | ||
41 | |||
42 | /* possible types of eeprom devices */ | ||
43 | enum eeprom_nature { | ||
44 | UNKNOWN, | ||
45 | VAIO, | ||
46 | }; | ||
47 | |||
48 | /* Each client has this additional data */ | ||
49 | struct eeprom_data { | ||
50 | struct mutex update_lock; | ||
51 | u8 valid; /* bitfield, bit!=0 if slice is valid */ | ||
52 | unsigned long last_updated[8]; /* In jiffies, 8 slices */ | ||
53 | u8 data[EEPROM_SIZE]; /* Register values */ | ||
54 | enum eeprom_nature nature; | ||
55 | }; | ||
56 | |||
57 | |||
58 | static void eeprom_update_client(struct i2c_client *client, u8 slice) | ||
59 | { | ||
60 | struct eeprom_data *data = i2c_get_clientdata(client); | ||
61 | int i; | ||
62 | |||
63 | mutex_lock(&data->update_lock); | ||
64 | |||
65 | if (!(data->valid & (1 << slice)) || | ||
66 | time_after(jiffies, data->last_updated[slice] + 300 * HZ)) { | ||
67 | dev_dbg(&client->dev, "Starting eeprom update, slice %u\n", slice); | ||
68 | |||
69 | if (i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { | ||
70 | for (i = slice << 5; i < (slice + 1) << 5; i += 32) | ||
71 | if (i2c_smbus_read_i2c_block_data(client, i, | ||
72 | 32, data->data + i) | ||
73 | != 32) | ||
74 | goto exit; | ||
75 | } else { | ||
76 | for (i = slice << 5; i < (slice + 1) << 5; i += 2) { | ||
77 | int word = i2c_smbus_read_word_data(client, i); | ||
78 | if (word < 0) | ||
79 | goto exit; | ||
80 | data->data[i] = word & 0xff; | ||
81 | data->data[i + 1] = word >> 8; | ||
82 | } | ||
83 | } | ||
84 | data->last_updated[slice] = jiffies; | ||
85 | data->valid |= (1 << slice); | ||
86 | } | ||
87 | exit: | ||
88 | mutex_unlock(&data->update_lock); | ||
89 | } | ||
90 | |||
91 | static ssize_t eeprom_read(struct kobject *kobj, struct bin_attribute *bin_attr, | ||
92 | char *buf, loff_t off, size_t count) | ||
93 | { | ||
94 | struct i2c_client *client = to_i2c_client(container_of(kobj, struct device, kobj)); | ||
95 | struct eeprom_data *data = i2c_get_clientdata(client); | ||
96 | u8 slice; | ||
97 | |||
98 | if (off > EEPROM_SIZE) | ||
99 | return 0; | ||
100 | if (off + count > EEPROM_SIZE) | ||
101 | count = EEPROM_SIZE - off; | ||
102 | |||
103 | /* Only refresh slices which contain requested bytes */ | ||
104 | for (slice = off >> 5; slice <= (off + count - 1) >> 5; slice++) | ||
105 | eeprom_update_client(client, slice); | ||
106 | |||
107 | /* Hide Vaio private settings to regular users: | ||
108 | - BIOS passwords: bytes 0x00 to 0x0f | ||
109 | - UUID: bytes 0x10 to 0x1f | ||
110 | - Serial number: 0xc0 to 0xdf */ | ||
111 | if (data->nature == VAIO && !capable(CAP_SYS_ADMIN)) { | ||
112 | int i; | ||
113 | |||
114 | for (i = 0; i < count; i++) { | ||
115 | if ((off + i <= 0x1f) || | ||
116 | (off + i >= 0xc0 && off + i <= 0xdf)) | ||
117 | buf[i] = 0; | ||
118 | else | ||
119 | buf[i] = data->data[off + i]; | ||
120 | } | ||
121 | } else { | ||
122 | memcpy(buf, &data->data[off], count); | ||
123 | } | ||
124 | |||
125 | return count; | ||
126 | } | ||
127 | |||
128 | static struct bin_attribute eeprom_attr = { | ||
129 | .attr = { | ||
130 | .name = "eeprom", | ||
131 | .mode = S_IRUGO, | ||
132 | }, | ||
133 | .size = EEPROM_SIZE, | ||
134 | .read = eeprom_read, | ||
135 | }; | ||
136 | |||
137 | /* Return 0 if detection is successful, -ENODEV otherwise */ | ||
138 | static int eeprom_detect(struct i2c_client *client, int kind, | ||
139 | struct i2c_board_info *info) | ||
140 | { | ||
141 | struct i2c_adapter *adapter = client->adapter; | ||
142 | |||
143 | /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all | ||
144 | addresses 0x50-0x57, but we only care about 0x50. So decline | ||
145 | attaching to addresses >= 0x51 on DDC buses */ | ||
146 | if (!(adapter->class & I2C_CLASS_SPD) && client->addr >= 0x51) | ||
147 | return -ENODEV; | ||
148 | |||
149 | /* There are four ways we can read the EEPROM data: | ||
150 | (1) I2C block reads (faster, but unsupported by most adapters) | ||
151 | (2) Word reads (128% overhead) | ||
152 | (3) Consecutive byte reads (88% overhead, unsafe) | ||
153 | (4) Regular byte data reads (265% overhead) | ||
154 | The third and fourth methods are not implemented by this driver | ||
155 | because all known adapters support one of the first two. */ | ||
156 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA) | ||
157 | && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK)) | ||
158 | return -ENODEV; | ||
159 | |||
160 | strlcpy(info->type, "eeprom", I2C_NAME_SIZE); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static int eeprom_probe(struct i2c_client *client, | ||
166 | const struct i2c_device_id *id) | ||
167 | { | ||
168 | struct i2c_adapter *adapter = client->adapter; | ||
169 | struct eeprom_data *data; | ||
170 | int err; | ||
171 | |||
172 | if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) { | ||
173 | err = -ENOMEM; | ||
174 | goto exit; | ||
175 | } | ||
176 | |||
177 | memset(data->data, 0xff, EEPROM_SIZE); | ||
178 | i2c_set_clientdata(client, data); | ||
179 | mutex_init(&data->update_lock); | ||
180 | data->nature = UNKNOWN; | ||
181 | |||
182 | /* Detect the Vaio nature of EEPROMs. | ||
183 | We use the "PCG-" or "VGN-" prefix as the signature. */ | ||
184 | if (client->addr == 0x57 | ||
185 | && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) { | ||
186 | char name[4]; | ||
187 | |||
188 | name[0] = i2c_smbus_read_byte_data(client, 0x80); | ||
189 | name[1] = i2c_smbus_read_byte_data(client, 0x81); | ||
190 | name[2] = i2c_smbus_read_byte_data(client, 0x82); | ||
191 | name[3] = i2c_smbus_read_byte_data(client, 0x83); | ||
192 | |||
193 | if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) { | ||
194 | dev_info(&client->dev, "Vaio EEPROM detected, " | ||
195 | "enabling privacy protection\n"); | ||
196 | data->nature = VAIO; | ||
197 | } | ||
198 | } | ||
199 | |||
200 | /* create the sysfs eeprom file */ | ||
201 | err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr); | ||
202 | if (err) | ||
203 | goto exit_kfree; | ||
204 | |||
205 | return 0; | ||
206 | |||
207 | exit_kfree: | ||
208 | kfree(data); | ||
209 | exit: | ||
210 | return err; | ||
211 | } | ||
212 | |||
213 | static int eeprom_remove(struct i2c_client *client) | ||
214 | { | ||
215 | sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr); | ||
216 | kfree(i2c_get_clientdata(client)); | ||
217 | |||
218 | return 0; | ||
219 | } | ||
220 | |||
221 | static const struct i2c_device_id eeprom_id[] = { | ||
222 | { "eeprom", 0 }, | ||
223 | { } | ||
224 | }; | ||
225 | |||
226 | static struct i2c_driver eeprom_driver = { | ||
227 | .driver = { | ||
228 | .name = "eeprom", | ||
229 | }, | ||
230 | .probe = eeprom_probe, | ||
231 | .remove = eeprom_remove, | ||
232 | .id_table = eeprom_id, | ||
233 | |||
234 | .class = I2C_CLASS_DDC | I2C_CLASS_SPD, | ||
235 | .detect = eeprom_detect, | ||
236 | .address_data = &addr_data, | ||
237 | }; | ||
238 | |||
239 | static int __init eeprom_init(void) | ||
240 | { | ||
241 | return i2c_add_driver(&eeprom_driver); | ||
242 | } | ||
243 | |||
244 | static void __exit eeprom_exit(void) | ||
245 | { | ||
246 | i2c_del_driver(&eeprom_driver); | ||
247 | } | ||
248 | |||
249 | |||
250 | MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " | ||
251 | "Philip Edelbrock <phil@netroedge.com> and " | ||
252 | "Greg Kroah-Hartman <greg@kroah.com>"); | ||
253 | MODULE_DESCRIPTION("I2C EEPROM driver"); | ||
254 | MODULE_LICENSE("GPL"); | ||
255 | |||
256 | module_init(eeprom_init); | ||
257 | module_exit(eeprom_exit); | ||
diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c index 15b1780025c8..15b1780025c8 100644 --- a/drivers/misc/eeprom_93cx6.c +++ b/drivers/misc/eeprom/eeprom_93cx6.c | |||