aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/busses/i2c-powermac.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/i2c/busses/i2c-powermac.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/i2c/busses/i2c-powermac.c')
-rw-r--r--drivers/i2c/busses/i2c-powermac.c150
1 files changed, 85 insertions, 65 deletions
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 3c9d71f60187..b289ec99eeba 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -49,48 +49,38 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
49 int rc = 0; 49 int rc = 0;
50 int read = (read_write == I2C_SMBUS_READ); 50 int read = (read_write == I2C_SMBUS_READ);
51 int addrdir = (addr << 1) | read; 51 int addrdir = (addr << 1) | read;
52 int mode, subsize, len;
53 u32 subaddr;
54 u8 *buf;
52 u8 local[2]; 55 u8 local[2];
53 56
54 rc = pmac_i2c_open(bus, 0); 57 if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
55 if (rc) 58 mode = pmac_i2c_mode_std;
56 return rc; 59 subsize = 0;
60 subaddr = 0;
61 } else {
62 mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
63 subsize = 1;
64 subaddr = command;
65 }
57 66
58 switch (size) { 67 switch (size) {
59 case I2C_SMBUS_QUICK: 68 case I2C_SMBUS_QUICK:
60 rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); 69 buf = NULL;
61 if (rc) 70 len = 0;
62 goto bail;
63 rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
64 break; 71 break;
65 case I2C_SMBUS_BYTE: 72 case I2C_SMBUS_BYTE:
66 rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
67 if (rc)
68 goto bail;
69 rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
70 break;
71 case I2C_SMBUS_BYTE_DATA: 73 case I2C_SMBUS_BYTE_DATA:
72 rc = pmac_i2c_setmode(bus, read ? 74 buf = &data->byte;
73 pmac_i2c_mode_combined : 75 len = 1;
74 pmac_i2c_mode_stdsub);
75 if (rc)
76 goto bail;
77 rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
78 break; 76 break;
79 case I2C_SMBUS_WORD_DATA: 77 case I2C_SMBUS_WORD_DATA:
80 rc = pmac_i2c_setmode(bus, read ?
81 pmac_i2c_mode_combined :
82 pmac_i2c_mode_stdsub);
83 if (rc)
84 goto bail;
85 if (!read) { 78 if (!read) {
86 local[0] = data->word & 0xff; 79 local[0] = data->word & 0xff;
87 local[1] = (data->word >> 8) & 0xff; 80 local[1] = (data->word >> 8) & 0xff;
88 } 81 }
89 rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2); 82 buf = local;
90 if (rc == 0 && read) { 83 len = 2;
91 data->word = ((u16)local[1]) << 8;
92 data->word |= local[0];
93 }
94 break; 84 break;
95 85
96 /* Note that these are broken vs. the expected smbus API where 86 /* Note that these are broken vs. the expected smbus API where
@@ -105,28 +95,49 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
105 * a repeat start/addr phase (but not stop in between) 95 * a repeat start/addr phase (but not stop in between)
106 */ 96 */
107 case I2C_SMBUS_BLOCK_DATA: 97 case I2C_SMBUS_BLOCK_DATA:
108 rc = pmac_i2c_setmode(bus, read ? 98 buf = data->block;
109 pmac_i2c_mode_combined : 99 len = data->block[0] + 1;
110 pmac_i2c_mode_stdsub);
111 if (rc)
112 goto bail;
113 rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
114 data->block[0] + 1);
115
116 break; 100 break;
117 case I2C_SMBUS_I2C_BLOCK_DATA: 101 case I2C_SMBUS_I2C_BLOCK_DATA:
118 rc = pmac_i2c_setmode(bus, read ? 102 buf = &data->block[1];
119 pmac_i2c_mode_combined : 103 len = data->block[0];
120 pmac_i2c_mode_stdsub);
121 if (rc)
122 goto bail;
123 rc = pmac_i2c_xfer(bus, addrdir, 1, command,
124 &data->block[1], data->block[0]);
125 break; 104 break;
126 105
127 default: 106 default:
128 rc = -EINVAL; 107 return -EINVAL;
108 }
109
110 rc = pmac_i2c_open(bus, 0);
111 if (rc) {
112 dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
113 return rc;
114 }
115
116 rc = pmac_i2c_setmode(bus, mode);
117 if (rc) {
118 dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
119 mode, rc);
120 goto bail;
129 } 121 }
122
123 rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
124 if (rc) {
125 if (rc == -ENXIO)
126 dev_dbg(&adap->dev,
127 "I2C transfer at 0x%02x failed, size %d, "
128 "err %d\n", addrdir >> 1, size, rc);
129 else
130 dev_err(&adap->dev,
131 "I2C transfer at 0x%02x failed, size %d, "
132 "err %d\n", addrdir >> 1, size, rc);
133 goto bail;
134 }
135
136 if (size == I2C_SMBUS_WORD_DATA && read) {
137 data->word = ((u16)local[1]) << 8;
138 data->word |= local[0];
139 }
140
130 bail: 141 bail:
131 pmac_i2c_close(bus); 142 pmac_i2c_close(bus);
132 return rc; 143 return rc;
@@ -146,20 +157,39 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
146 int read; 157 int read;
147 int addrdir; 158 int addrdir;
148 159
160 if (num != 1) {
161 dev_err(&adap->dev,
162 "Multi-message I2C transactions not supported\n");
163 return -EOPNOTSUPP;
164 }
165
149 if (msgs->flags & I2C_M_TEN) 166 if (msgs->flags & I2C_M_TEN)
150 return -EINVAL; 167 return -EINVAL;
151 read = (msgs->flags & I2C_M_RD) != 0; 168 read = (msgs->flags & I2C_M_RD) != 0;
152 addrdir = (msgs->addr << 1) | read; 169 addrdir = (msgs->addr << 1) | read;
153 if (msgs->flags & I2C_M_REV_DIR_ADDR)
154 addrdir ^= 1;
155 170
156 rc = pmac_i2c_open(bus, 0); 171 rc = pmac_i2c_open(bus, 0);
157 if (rc) 172 if (rc) {
173 dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
158 return rc; 174 return rc;
175 }
159 rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); 176 rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
160 if (rc) 177 if (rc) {
178 dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
179 pmac_i2c_mode_std, rc);
161 goto bail; 180 goto bail;
181 }
162 rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); 182 rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
183 if (rc < 0) {
184 if (rc == -ENXIO)
185 dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
186 addrdir & 1 ? "read from" : "write to",
187 addrdir >> 1, rc);
188 else
189 dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
190 addrdir & 1 ? "read from" : "write to",
191 addrdir >> 1, rc);
192 }
163 bail: 193 bail:
164 pmac_i2c_close(bus); 194 pmac_i2c_close(bus);
165 return rc < 0 ? rc : 1; 195 return rc < 0 ? rc : 1;
@@ -183,19 +213,16 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
183static int __devexit i2c_powermac_remove(struct platform_device *dev) 213static int __devexit i2c_powermac_remove(struct platform_device *dev)
184{ 214{
185 struct i2c_adapter *adapter = platform_get_drvdata(dev); 215 struct i2c_adapter *adapter = platform_get_drvdata(dev);
186 struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter);
187 int rc; 216 int rc;
188 217
189 rc = i2c_del_adapter(adapter); 218 rc = i2c_del_adapter(adapter);
190 pmac_i2c_detach_adapter(bus, adapter);
191 i2c_set_adapdata(adapter, NULL);
192 /* We aren't that prepared to deal with this... */ 219 /* We aren't that prepared to deal with this... */
193 if (rc) 220 if (rc)
194 printk(KERN_WARNING 221 printk(KERN_WARNING
195 "i2c-powermac.c: Failed to remove bus %s !\n", 222 "i2c-powermac.c: Failed to remove bus %s !\n",
196 adapter->name); 223 adapter->name);
197 platform_set_drvdata(dev, NULL); 224 platform_set_drvdata(dev, NULL);
198 kfree(adapter); 225 memset(adapter, 0, sizeof(*adapter));
199 226
200 return 0; 227 return 0;
201} 228}
@@ -206,12 +233,12 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
206 struct pmac_i2c_bus *bus = dev->dev.platform_data; 233 struct pmac_i2c_bus *bus = dev->dev.platform_data;
207 struct device_node *parent = NULL; 234 struct device_node *parent = NULL;
208 struct i2c_adapter *adapter; 235 struct i2c_adapter *adapter;
209 char name[32];
210 const char *basename; 236 const char *basename;
211 int rc; 237 int rc;
212 238
213 if (bus == NULL) 239 if (bus == NULL)
214 return -EINVAL; 240 return -EINVAL;
241 adapter = pmac_i2c_get_adapter(bus);
215 242
216 /* Ok, now we need to make up a name for the interface that will 243 /* Ok, now we need to make up a name for the interface that will
217 * match what we used to do in the past, that is basically the 244 * match what we used to do in the past, that is basically the
@@ -237,29 +264,22 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
237 default: 264 default:
238 return -EINVAL; 265 return -EINVAL;
239 } 266 }
240 snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus)); 267 snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename,
268 pmac_i2c_get_channel(bus));
241 of_node_put(parent); 269 of_node_put(parent);
242 270
243 adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
244 if (adapter == NULL) {
245 printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
246 return -ENOMEM;
247 }
248 platform_set_drvdata(dev, adapter); 271 platform_set_drvdata(dev, adapter);
249 strcpy(adapter->name, name);
250 adapter->algo = &i2c_powermac_algorithm; 272 adapter->algo = &i2c_powermac_algorithm;
251 i2c_set_adapdata(adapter, bus); 273 i2c_set_adapdata(adapter, bus);
252 adapter->dev.parent = &dev->dev; 274 adapter->dev.parent = &dev->dev;
253 pmac_i2c_attach_adapter(bus, adapter);
254 rc = i2c_add_adapter(adapter); 275 rc = i2c_add_adapter(adapter);
255 if (rc) { 276 if (rc) {
256 printk(KERN_ERR "i2c-powermac: Adapter %s registration " 277 printk(KERN_ERR "i2c-powermac: Adapter %s registration "
257 "failed\n", name); 278 "failed\n", adapter->name);
258 i2c_set_adapdata(adapter, NULL); 279 memset(adapter, 0, sizeof(*adapter));
259 pmac_i2c_detach_adapter(bus, adapter);
260 } 280 }
261 281
262 printk(KERN_INFO "PowerMac i2c bus %s registered\n", name); 282 printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
263 283
264 if (!strncmp(basename, "uni-n", 5)) { 284 if (!strncmp(basename, "uni-n", 5)) {
265 struct device_node *np; 285 struct device_node *np;