aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ixp4xx/patches-2.6.23/014-eeprom_new_notifier.patch
blob: 4aa7a988bed26ce99254acdf7e276df8730cbe04 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
diff -uprN linux-2.6.23.orig/drivers/i2c/chips/eeprom.c linux-2.6.23/drivers/i2c/chips/eeprom.c
--- linux-2.6.23.orig/drivers/i2c/chips/eeprom.c	2007-10-09 15:31:38.000000000 -0500
+++ linux-2.6.23/drivers/i2c/chips/eeprom.c	2007-10-11 00:57:25.000000000 -0500
@@ -33,6 +33,8 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/mutex.h>
+#include <linux/notifier.h>
+#include <linux/eeprom.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x50, 0x51, 0x52, 0x53, 0x54,
@@ -41,26 +43,7 @@ static unsigned short normal_i2c[] = { 0
 /* Insmod parameters */
 I2C_CLIENT_INSMOD_1(eeprom);
 
-
-/* Size of EEPROM in bytes */
-#define EEPROM_SIZE		256
-
-/* possible types of eeprom devices */
-enum eeprom_nature {
-	UNKNOWN,
-	VAIO,
-};
-
-/* Each client has this additional data */
-struct eeprom_data {
-	struct i2c_client client;
-	struct mutex update_lock;
-	u8 valid;			/* bitfield, bit!=0 if slice is valid */
-	unsigned long last_updated[8];	/* In jiffies, 8 slices */
-	u8 data[EEPROM_SIZE];		/* Register values */
-	enum eeprom_nature nature;
-};
-
+ATOMIC_NOTIFIER_HEAD(eeprom_chain);
 
 static int eeprom_attach_adapter(struct i2c_adapter *adapter);
 static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind);
@@ -191,6 +174,7 @@ static int eeprom_detect(struct i2c_adap
 	data->valid = 0;
 	mutex_init(&data->update_lock);
 	data->nature = UNKNOWN;
+	data->attr = &eeprom_attr;
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
@@ -214,6 +198,9 @@ static int eeprom_detect(struct i2c_adap
 	if (err)
 		goto exit_detach;
 
+	/* call the notifier chain */
+	atomic_notifier_call_chain(&eeprom_chain, EEPROM_REGISTER, data);
+
 	return 0;
 
 exit_detach:
@@ -239,6 +226,41 @@ static int eeprom_detach_client(struct i
 	return 0;
 }
 
+/**
+ * register_eeprom_notifier - register a 'user' of EEPROM devices.
+ * @nb: pointer to notifier info structure
+ *
+ * Registers a callback function to be called upon detection
+ * of an EEPROM device.  Detection invokes the 'add' callback
+ * with the kobj of the mutex and a bin_attribute which allows
+ * read from the EEPROM.  The intention is that the notifier
+ * will be able to read system configuration from the notifier.
+ *
+ * Only EEPROMs detected *after* the addition of the notifier
+ * are notified.  I.e. EEPROMs already known to the system
+ * will not be notified - add the notifier from board level
+ * code!
+ */
+int register_eeprom_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_register(&eeprom_chain, nb);
+}
+
+/**
+ *	unregister_eeprom_notifier - unregister a 'user' of EEPROM devices.
+ *	@old: pointer to notifier info structure
+ *
+ *	Removes a callback function from the list of 'users' to be
+ *	notified upon detection of EEPROM devices.
+ */
+int unregister_eeprom_notifier(struct notifier_block *nb)
+{
+	return atomic_notifier_chain_unregister(&eeprom_chain, nb);
+}
+
+EXPORT_SYMBOL_GPL(register_eeprom_notifier);
+EXPORT_SYMBOL_GPL(unregister_eeprom_notifier);
+
 static int __init eeprom_init(void)
 {
 	return i2c_add_driver(&eeprom_driver);
diff -uprN linux-2.6.23.orig/include/linux/eeprom.h linux-2.6.23/include/linux/eeprom.h
--- linux-2.6.23.orig/include/linux/eeprom.h	1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.23/include/linux/eeprom.h	2007-10-11 00:57:25.000000000 -0500
@@ -0,0 +1,71 @@
+#ifndef _LINUX_EEPROM_H
+#define _LINUX_EEPROM_H
+/*
+ *  EEPROM notifier header
+ *
+ *  Copyright (C) 2006 John Bowler
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __KERNEL__
+#error This is a kernel header
+#endif
+
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
+
+/* Size of EEPROM in bytes */
+#define EEPROM_SIZE             256
+
+/* possible types of eeprom devices */
+enum eeprom_nature {
+	UNKNOWN,
+	VAIO,
+};
+
+/* Each client has this additional data */
+struct eeprom_data {
+	struct i2c_client client;
+	struct mutex update_lock;
+	u8 valid;			/* bitfield, bit!=0 if slice is valid */
+	unsigned long last_updated[8];	/* In jiffies, 8 slices */
+	u8 data[EEPROM_SIZE];		/* Register values */
+	enum eeprom_nature nature;
+	struct bin_attribute *attr;
+};
+
+/*
+ * This is very basic.
+ *
+ * If an EEPROM is detected on the I2C bus (this only works for
+ * I2C EEPROMs) the notifier chain  is called with
+ * both the I2C information and the kobject for the sysfs
+ * device which has been registers.  It is then possible to
+ * read from the device via the bin_attribute::read method
+ * to extract configuration information.
+ *
+ * Register the notifier in the board level code, there is no
+ * need to unregister it but you can if you want (it will save
+ * a little bit or kernel memory to do so).
+ */
+
+extern int register_eeprom_notifier(struct notifier_block *nb);
+extern int unregister_eeprom_notifier(struct notifier_block *nb);
+
+#endif /* _LINUX_EEPROM_H */
diff -uprN linux-2.6.23.orig/include/linux/notifier.h linux-2.6.23/include/linux/notifier.h
--- linux-2.6.23.orig/include/linux/notifier.h	2007-10-09 15:31:38.000000000 -0500
+++ linux-2.6.23/include/linux/notifier.h	2007-10-11 00:57:25.000000000 -0500
@@ -231,5 +231,8 @@ static inline int notifier_to_errno(int 
 #define PM_SUSPEND_PREPARE	0x0003 /* Going to suspend the system */
 #define PM_POST_SUSPEND		0x0004 /* Suspend finished */
 
+/* eeprom notifier chain */
+#define EEPROM_REGISTER		0x0001
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_NOTIFIER_H */