aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/i2c/chips/pcf857412
-rw-r--r--drivers/i2c/chips/pcf8574.c108
2 files changed, 51 insertions, 69 deletions
diff --git a/Documentation/i2c/chips/pcf8574 b/Documentation/i2c/chips/pcf8574
index 5c1ad1376b62..235815c075ff 100644
--- a/Documentation/i2c/chips/pcf8574
+++ b/Documentation/i2c/chips/pcf8574
@@ -4,13 +4,13 @@ Kernel driver pcf8574
4Supported chips: 4Supported chips:
5 * Philips PCF8574 5 * Philips PCF8574
6 Prefix: 'pcf8574' 6 Prefix: 'pcf8574'
7 Addresses scanned: I2C 0x20 - 0x27 7 Addresses scanned: none
8 Datasheet: Publicly available at the Philips Semiconductors website 8 Datasheet: Publicly available at the Philips Semiconductors website
9 http://www.semiconductors.philips.com/pip/PCF8574P.html 9 http://www.semiconductors.philips.com/pip/PCF8574P.html
10 10
11 * Philips PCF8574A 11 * Philips PCF8574A
12 Prefix: 'pcf8574a' 12 Prefix: 'pcf8574a'
13 Addresses scanned: I2C 0x38 - 0x3f 13 Addresses scanned: none
14 Datasheet: Publicly available at the Philips Semiconductors website 14 Datasheet: Publicly available at the Philips Semiconductors website
15 http://www.semiconductors.philips.com/pip/PCF8574P.html 15 http://www.semiconductors.philips.com/pip/PCF8574P.html
16 16
@@ -38,12 +38,10 @@ For more informations see the datasheet.
38Accessing PCF8574(A) via /sys interface 38Accessing PCF8574(A) via /sys interface
39------------------------------------- 39-------------------------------------
40 40
41! Be careful !
42The PCF8574(A) is plainly impossible to detect ! Stupid chip. 41The PCF8574(A) is plainly impossible to detect ! Stupid chip.
43So every chip with address in the interval [20..27] and [38..3f] are 42So, you have to pass the I2C bus and address of the installed PCF857A
44detected as PCF8574(A). If you have other chips in this address 43and PCF8574A devices explicitly to the driver at load time via the
45range, the workaround is to load this module after the one 44force=... parameter.
46for your others chips.
47 45
48On detection (i.e. insmod, modprobe et al.), directories are being 46On detection (i.e. insmod, modprobe et al.), directories are being
49created for each detected PCF8574(A): 47created for each detected PCF8574(A):
diff --git a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
index 1b3db2b3ada9..6ec309894c88 100644
--- a/drivers/i2c/chips/pcf8574.c
+++ b/drivers/i2c/chips/pcf8574.c
@@ -38,37 +38,19 @@
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/i2c.h> 39#include <linux/i2c.h>
40 40
41/* Addresses to scan */ 41/* Addresses to scan: none, device can't be detected */
42static const unsigned short normal_i2c[] = { 42static const unsigned short normal_i2c[] = { I2C_CLIENT_END };
43 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
44 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
45 I2C_CLIENT_END
46};
47 43
48/* Insmod parameters */ 44/* Insmod parameters */
49I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); 45I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a);
50 46
51/* Each client has this additional data */ 47/* Each client has this additional data */
52struct pcf8574_data { 48struct pcf8574_data {
53 struct i2c_client client;
54
55 int write; /* Remember last written value */ 49 int write; /* Remember last written value */
56}; 50};
57 51
58static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
59static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind);
60static int pcf8574_detach_client(struct i2c_client *client);
61static void pcf8574_init_client(struct i2c_client *client); 52static void pcf8574_init_client(struct i2c_client *client);
62 53
63/* This is the driver that will be inserted */
64static struct i2c_driver pcf8574_driver = {
65 .driver = {
66 .name = "pcf8574",
67 },
68 .attach_adapter = pcf8574_attach_adapter,
69 .detach_client = pcf8574_detach_client,
70};
71
72/* following are the sysfs callback functions */ 54/* following are the sysfs callback functions */
73static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) 55static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf)
74{ 56{
@@ -119,41 +101,22 @@ static const struct attribute_group pcf8574_attr_group = {
119 * Real code 101 * Real code
120 */ 102 */
121 103
122static int pcf8574_attach_adapter(struct i2c_adapter *adapter) 104/* Return 0 if detection is successful, -ENODEV otherwise */
123{ 105static int pcf8574_detect(struct i2c_client *client, int kind,
124 return i2c_probe(adapter, &addr_data, pcf8574_detect); 106 struct i2c_board_info *info)
125}
126
127/* This function is called by i2c_probe */
128static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
129{ 107{
130 struct i2c_client *client; 108 struct i2c_adapter *adapter = client->adapter;
131 struct pcf8574_data *data; 109 const char *client_name;
132 int err = 0;
133 const char *client_name = "";
134 110
135 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) 111 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
136 goto exit; 112 return -ENODEV;
137
138 /* OK. For now, we presume we have a valid client. We now create the
139 client structure, even though we cannot fill it completely yet. */
140 if (!(data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
141 err = -ENOMEM;
142 goto exit;
143 }
144
145 client = &data->client;
146 i2c_set_clientdata(client, data);
147 client->addr = address;
148 client->adapter = adapter;
149 client->driver = &pcf8574_driver;
150 113
151 /* Now, we would do the remaining detection. But the PCF8574 is plainly 114 /* Now, we would do the remaining detection. But the PCF8574 is plainly
152 impossible to detect! Stupid chip. */ 115 impossible to detect! Stupid chip. */
153 116
154 /* Determine the chip type */ 117 /* Determine the chip type */
155 if (kind <= 0) { 118 if (kind <= 0) {
156 if (address >= 0x38 && address <= 0x3f) 119 if (client->addr >= 0x38 && client->addr <= 0x3f)
157 kind = pcf8574a; 120 kind = pcf8574a;
158 else 121 else
159 kind = pcf8574; 122 kind = pcf8574;
@@ -163,40 +126,43 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
163 client_name = "pcf8574a"; 126 client_name = "pcf8574a";
164 else 127 else
165 client_name = "pcf8574"; 128 client_name = "pcf8574";
129 strlcpy(info->type, client_name, I2C_NAME_SIZE);
166 130
167 /* Fill in the remaining client fields and put it into the global list */ 131 return 0;
168 strlcpy(client->name, client_name, I2C_NAME_SIZE); 132}
133
134static int pcf8574_probe(struct i2c_client *client,
135 const struct i2c_device_id *id)
136{
137 struct pcf8574_data *data;
138 int err;
139
140 data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL);
141 if (!data) {
142 err = -ENOMEM;
143 goto exit;
144 }
145
146 i2c_set_clientdata(client, data);
169 147
170 /* Tell the I2C layer a new client has arrived */
171 if ((err = i2c_attach_client(client)))
172 goto exit_free;
173
174 /* Initialize the PCF8574 chip */ 148 /* Initialize the PCF8574 chip */
175 pcf8574_init_client(client); 149 pcf8574_init_client(client);
176 150
177 /* Register sysfs hooks */ 151 /* Register sysfs hooks */
178 err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); 152 err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group);
179 if (err) 153 if (err)
180 goto exit_detach; 154 goto exit_free;
181 return 0; 155 return 0;
182 156
183 exit_detach:
184 i2c_detach_client(client);
185 exit_free: 157 exit_free:
186 kfree(data); 158 kfree(data);
187 exit: 159 exit:
188 return err; 160 return err;
189} 161}
190 162
191static int pcf8574_detach_client(struct i2c_client *client) 163static int pcf8574_remove(struct i2c_client *client)
192{ 164{
193 int err;
194
195 sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); 165 sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
196
197 if ((err = i2c_detach_client(client)))
198 return err;
199
200 kfree(i2c_get_clientdata(client)); 166 kfree(i2c_get_clientdata(client));
201 return 0; 167 return 0;
202} 168}
@@ -208,6 +174,24 @@ static void pcf8574_init_client(struct i2c_client *client)
208 data->write = -EAGAIN; 174 data->write = -EAGAIN;
209} 175}
210 176
177static const struct i2c_device_id pcf8574_id[] = {
178 { "pcf8574", 0 },
179 { "pcf8574a", 0 },
180 { }
181};
182
183static struct i2c_driver pcf8574_driver = {
184 .driver = {
185 .name = "pcf8574",
186 },
187 .probe = pcf8574_probe,
188 .remove = pcf8574_remove,
189 .id_table = pcf8574_id,
190
191 .detect = pcf8574_detect,
192 .address_data = &addr_data,
193};
194
211static int __init pcf8574_init(void) 195static int __init pcf8574_init(void)
212{ 196{
213 return i2c_add_driver(&pcf8574_driver); 197 return i2c_add_driver(&pcf8574_driver);