summaryrefslogtreecommitdiffstats
path: root/target/linux/generic-2.6/patches-2.6.27/450-i2c_at24_add_kernel_interface_read_write.patch
blob: 36a3e69125858bf517890244944180dfef58c3ff (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
Subject: [PATCH 2/3] I2C: at24: add kernel interface for reading/writing EEPROM
Date: Monday 25 August 2008
From: Kevin Hilman <khilman@deeprootsystems.com>
To: davinci-linux-open-source@linux.davincidsp.com

This patch adds an interface by which other kernel code can read/write
detected EEPROM.

The platform code registers a 'setup' callback with the
at24_platform_data.  When the at24 driver detects an EEPROM, it fills
out the read and write functions of at24_iface and calls the setup
callback.  The platform code can then use the read/write functions in
the at24_iface struct for reading and writing the EEPROM.

Original idea, review and updates by David Brownell <david-b@pacbell.net>

Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
---
 drivers/i2c/chips/at24.c |   42 +++++++++++++++++++++++++++++++++++-------
 include/linux/i2c/at24.h |   10 ++++++++++
 2 files changed, 45 insertions(+), 7 deletions(-)

--- a/drivers/i2c/chips/at24.c
+++ b/drivers/i2c/chips/at24.c
@@ -53,6 +53,7 @@
 
 struct at24_data {
 	struct at24_platform_data chip;
+	struct at24_iface iface;
 	bool use_smbus;
 
 	/*
@@ -264,13 +265,6 @@ static ssize_t at24_bin_read(struct kobj
 
 
 /*
- * REVISIT: export at24_bin{read,write}() to let other kernel code use
- * eeprom data. For example, it might hold a board's Ethernet address, or
- * board-specific calibration data generated on the manufacturing floor.
- */
-
-
-/*
  * Note that if the hardware write-protect pin is pulled high, the whole
  * chip is normally write protected. But there are plenty of product
  * variants here, including OTP fuses and partial chip protect.
@@ -386,6 +380,30 @@ static ssize_t at24_bin_write(struct kob
 
 /*-------------------------------------------------------------------------*/
 
+/*
+ * This lets other kernel code access the eeprom data. For example, it
+ * might hold a board's Ethernet address, or board-specific calibration
+ * data generated on the manufacturing floor.
+ */
+
+static ssize_t at24_iface_read(struct at24_iface *iface, char *buf,
+			      off_t offset, size_t count)
+{
+	struct at24_data *at24 = container_of(iface, struct at24_data, iface);
+
+	return at24_eeprom_read(at24, buf, offset, count);
+}
+
+static ssize_t at24_iface_write(struct at24_iface *iface, char *buf,
+			       off_t offset, size_t count)
+{
+	struct at24_data *at24 = container_of(iface, struct at24_data, iface);
+
+	return at24_eeprom_write(at24, buf, offset, count);
+}
+
+/*-------------------------------------------------------------------------*/
+
 static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
 {
 	struct at24_platform_data chip;
@@ -413,6 +431,9 @@ static int at24_probe(struct i2c_client 
 		 * is recommended anyhow.
 		 */
 		chip.page_size = 1;
+
+		chip.setup = NULL;
+		chip.context = NULL;
 	}
 
 	if (!is_power_of_2(chip.byte_len))
@@ -449,6 +470,9 @@ static int at24_probe(struct i2c_client 
 		goto err_out;
 	}
 
+	at24->iface.read = at24_iface_read;
+	at24->iface.write = at24_iface_write;
+
 	mutex_init(&at24->lock);
 	at24->use_smbus = use_smbus;
 	at24->chip = chip;
@@ -521,6 +545,10 @@ static int at24_probe(struct i2c_client 
 		at24->write_max,
 		use_smbus ? ", use_smbus" : "");
 
+	/* export data to kernel code */
+	if (chip.setup)
+		chip.setup(&at24->iface, chip.context);
+
 	return 0;
 
 err_clients:
--- a/include/linux/i2c/at24.h
+++ b/include/linux/i2c/at24.h
@@ -15,6 +15,13 @@
  * is bigger than what the chip actually supports!
  */
 
+struct at24_iface {
+	ssize_t (*read)(struct at24_iface *, char *buf, off_t offset,
+			size_t count);
+	ssize_t (*write)(struct at24_iface *, char *buf, off_t offset,
+			 size_t count);
+};
+
 struct at24_platform_data {
 	u32		byte_len;		/* size (sum of all addr) */
 	u16		page_size;		/* for writes */
@@ -23,6 +30,9 @@ struct at24_platform_data {
 #define AT24_FLAG_READONLY	0x40	/* sysfs-entry will be read-only */
 #define AT24_FLAG_IRUGO		0x20	/* sysfs-entry will be world-readable */
 #define AT24_FLAG_TAKE8ADDR	0x10	/* take always 8 addresses (24c00) */
+
+	int             (*setup)(struct at24_iface *, void *context);
+	void		*context;
 };
 
 #endif /* _LINUX_AT24_H */