Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux...
[pandora-kernel.git] / drivers / i2c / busses / i2c-pasemi.c
1 /*
2  * Copyright (C) 2006-2007 PA Semi, Inc
3  *
4  * SMBus host driver for PA Semi PWRficient
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 version 2 as
8  * published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18  */
19
20 #include <linux/module.h>
21 #include <linux/pci.h>
22 #include <linux/kernel.h>
23 #include <linux/stddef.h>
24 #include <linux/sched.h>
25 #include <linux/i2c.h>
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/io.h>
29
30 static struct pci_driver pasemi_smb_driver;
31
32 struct pasemi_smbus {
33         struct pci_dev          *dev;
34         struct i2c_adapter       adapter;
35         unsigned long            base;
36         int                      size;
37 };
38
39 /* Register offsets */
40 #define REG_MTXFIFO     0x00
41 #define REG_MRXFIFO     0x04
42 #define REG_SMSTA       0x14
43 #define REG_CTL         0x1c
44
45 /* Register defs */
46 #define MTXFIFO_READ    0x00000400
47 #define MTXFIFO_STOP    0x00000200
48 #define MTXFIFO_START   0x00000100
49 #define MTXFIFO_DATA_M  0x000000ff
50
51 #define MRXFIFO_EMPTY   0x00000100
52 #define MRXFIFO_DATA_M  0x000000ff
53
54 #define SMSTA_XEN       0x08000000
55 #define SMSTA_MTN       0x00200000
56
57 #define CTL_MRR         0x00000400
58 #define CTL_MTR         0x00000200
59 #define CTL_CLK_M       0x000000ff
60
61 #define CLK_100K_DIV    84
62 #define CLK_400K_DIV    21
63
64 static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val)
65 {
66         dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n",
67                 smbus->base + reg, val);
68         outl(val, smbus->base + reg);
69 }
70
71 static inline int reg_read(struct pasemi_smbus *smbus, int reg)
72 {
73         int ret;
74         ret = inl(smbus->base + reg);
75         dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n",
76                 smbus->base + reg, ret);
77         return ret;
78 }
79
80 #define TXFIFO_WR(smbus, reg)   reg_write((smbus), REG_MTXFIFO, (reg))
81 #define RXFIFO_RD(smbus)        reg_read((smbus), REG_MRXFIFO)
82
83 static void pasemi_smb_clear(struct pasemi_smbus *smbus)
84 {
85         unsigned int status;
86
87         status = reg_read(smbus, REG_SMSTA);
88         reg_write(smbus, REG_SMSTA, status);
89 }
90
91 static unsigned int pasemi_smb_waitready(struct pasemi_smbus *smbus)
92 {
93         int timeout = 10;
94         unsigned int status;
95
96         status = reg_read(smbus, REG_SMSTA);
97
98         while (!(status & SMSTA_XEN) && timeout--) {
99                 msleep(1);
100                 status = reg_read(smbus, REG_SMSTA);
101         }
102
103         /* Got NACK? */
104         if (status & SMSTA_MTN)
105                 return -ENXIO;
106
107         if (timeout < 0) {
108                 dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status);
109                 reg_write(smbus, REG_SMSTA, status);
110                 return -ETIME;
111         }
112
113         /* Clear XEN */
114         reg_write(smbus, REG_SMSTA, SMSTA_XEN);
115
116         return 0;
117 }
118
119 static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter,
120                                struct i2c_msg *msg, int stop)
121 {
122         struct pasemi_smbus *smbus = adapter->algo_data;
123         int read, i, err;
124         u32 rd;
125
126         read = msg->flags & I2C_M_RD ? 1 : 0;
127
128         TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read);
129
130         if (read) {
131                 TXFIFO_WR(smbus, msg->len | MTXFIFO_READ |
132                                  (stop ? MTXFIFO_STOP : 0));
133
134                 err = pasemi_smb_waitready(smbus);
135                 if (err)
136                         goto reset_out;
137
138                 for (i = 0; i < msg->len; i++) {
139                         rd = RXFIFO_RD(smbus);
140                         if (rd & MRXFIFO_EMPTY) {
141                                 err = -ENODATA;
142                                 goto reset_out;
143                         }
144                         msg->buf[i] = rd & MRXFIFO_DATA_M;
145                 }
146         } else {
147                 for (i = 0; i < msg->len - 1; i++)
148                         TXFIFO_WR(smbus, msg->buf[i]);
149
150                 TXFIFO_WR(smbus, msg->buf[msg->len-1] |
151                           (stop ? MTXFIFO_STOP : 0));
152         }
153
154         return 0;
155
156  reset_out:
157         reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
158                   (CLK_100K_DIV & CTL_CLK_M)));
159         return err;
160 }
161
162 static int pasemi_i2c_xfer(struct i2c_adapter *adapter,
163                            struct i2c_msg *msgs, int num)
164 {
165         struct pasemi_smbus *smbus = adapter->algo_data;
166         int ret, i;
167
168         pasemi_smb_clear(smbus);
169
170         ret = 0;
171
172         for (i = 0; i < num && !ret; i++)
173                 ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1)));
174
175         return ret ? ret : num;
176 }
177
178 static int pasemi_smb_xfer(struct i2c_adapter *adapter,
179                 u16 addr, unsigned short flags, char read_write, u8 command,
180                 int size, union i2c_smbus_data *data)
181 {
182         struct pasemi_smbus *smbus = adapter->algo_data;
183         unsigned int rd;
184         int read_flag, err;
185         int len = 0, i;
186
187         /* All our ops take 8-bit shifted addresses */
188         addr <<= 1;
189         read_flag = read_write == I2C_SMBUS_READ;
190
191         pasemi_smb_clear(smbus);
192
193         switch (size) {
194         case I2C_SMBUS_QUICK:
195                 TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START |
196                           MTXFIFO_STOP);
197                 break;
198         case I2C_SMBUS_BYTE:
199                 TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START);
200                 if (read_write)
201                         TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ);
202                 else
203                         TXFIFO_WR(smbus, MTXFIFO_STOP | command);
204                 break;
205         case I2C_SMBUS_BYTE_DATA:
206                 TXFIFO_WR(smbus, addr | MTXFIFO_START);
207                 TXFIFO_WR(smbus, command);
208                 if (read_write) {
209                         TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
210                         TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP);
211                 } else {
212                         TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte);
213                 }
214                 break;
215         case I2C_SMBUS_WORD_DATA:
216                 TXFIFO_WR(smbus, addr | MTXFIFO_START);
217                 TXFIFO_WR(smbus, command);
218                 if (read_write) {
219                         TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
220                         TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP);
221                 } else {
222                         TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
223                         TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8));
224                 }
225                 break;
226         case I2C_SMBUS_BLOCK_DATA:
227                 TXFIFO_WR(smbus, addr | MTXFIFO_START);
228                 TXFIFO_WR(smbus, command);
229                 if (read_write) {
230                         TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
231                         TXFIFO_WR(smbus, 1 | MTXFIFO_READ);
232                         rd = RXFIFO_RD(smbus);
233                         len = min_t(u8, (rd & MRXFIFO_DATA_M),
234                                     I2C_SMBUS_BLOCK_MAX);
235                         TXFIFO_WR(smbus, len | MTXFIFO_READ |
236                                          MTXFIFO_STOP);
237                 } else {
238                         len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX);
239                         TXFIFO_WR(smbus, len);
240                         for (i = 1; i < len; i++)
241                                 TXFIFO_WR(smbus, data->block[i]);
242                         TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP);
243                 }
244                 break;
245         case I2C_SMBUS_PROC_CALL:
246                 read_write = I2C_SMBUS_READ;
247                 TXFIFO_WR(smbus, addr | MTXFIFO_START);
248                 TXFIFO_WR(smbus, command);
249                 TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M);
250                 TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M);
251                 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START);
252                 TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ);
253                 break;
254         case I2C_SMBUS_BLOCK_PROC_CALL:
255                 len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1);
256                 read_write = I2C_SMBUS_READ;
257                 TXFIFO_WR(smbus, addr | MTXFIFO_START);
258                 TXFIFO_WR(smbus, command);
259                 TXFIFO_WR(smbus, len);
260                 for (i = 1; i <= len; i++)
261                         TXFIFO_WR(smbus, data->block[i]);
262                 TXFIFO_WR(smbus, addr | I2C_SMBUS_READ);
263                 TXFIFO_WR(smbus, MTXFIFO_READ | 1);
264                 rd = RXFIFO_RD(smbus);
265                 len = min_t(u8, (rd & MRXFIFO_DATA_M),
266                             I2C_SMBUS_BLOCK_MAX - len);
267                 TXFIFO_WR(smbus, len | MTXFIFO_READ | MTXFIFO_STOP);
268                 break;
269
270         default:
271                 dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
272                 return -EINVAL;
273         }
274
275         err = pasemi_smb_waitready(smbus);
276         if (err)
277                 goto reset_out;
278
279         if (read_write == I2C_SMBUS_WRITE)
280                 return 0;
281
282         switch (size) {
283         case I2C_SMBUS_BYTE:
284         case I2C_SMBUS_BYTE_DATA:
285                 rd = RXFIFO_RD(smbus);
286                 if (rd & MRXFIFO_EMPTY) {
287                         err = -ENODATA;
288                         goto reset_out;
289                 }
290                 data->byte = rd & MRXFIFO_DATA_M;
291                 break;
292         case I2C_SMBUS_WORD_DATA:
293         case I2C_SMBUS_PROC_CALL:
294                 rd = RXFIFO_RD(smbus);
295                 if (rd & MRXFIFO_EMPTY) {
296                         err = -ENODATA;
297                         goto reset_out;
298                 }
299                 data->word = rd & MRXFIFO_DATA_M;
300                 rd = RXFIFO_RD(smbus);
301                 if (rd & MRXFIFO_EMPTY) {
302                         err = -ENODATA;
303                         goto reset_out;
304                 }
305                 data->word |= (rd & MRXFIFO_DATA_M) << 8;
306                 break;
307         case I2C_SMBUS_BLOCK_DATA:
308         case I2C_SMBUS_BLOCK_PROC_CALL:
309                 data->block[0] = len;
310                 for (i = 1; i <= len; i ++) {
311                         rd = RXFIFO_RD(smbus);
312                         if (rd & MRXFIFO_EMPTY) {
313                                 err = -ENODATA;
314                                 goto reset_out;
315                         }
316                         data->block[i] = rd & MRXFIFO_DATA_M;
317                 }
318                 break;
319         }
320
321         return 0;
322
323  reset_out:
324         reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
325                   (CLK_100K_DIV & CTL_CLK_M)));
326         return err;
327 }
328
329 static u32 pasemi_smb_func(struct i2c_adapter *adapter)
330 {
331         return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
332                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
333                I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL |
334                I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C;
335 }
336
337 static const struct i2c_algorithm smbus_algorithm = {
338         .master_xfer    = pasemi_i2c_xfer,
339         .smbus_xfer     = pasemi_smb_xfer,
340         .functionality  = pasemi_smb_func,
341 };
342
343 static int __devinit pasemi_smb_probe(struct pci_dev *dev,
344                                       const struct pci_device_id *id)
345 {
346         struct pasemi_smbus *smbus;
347         int error;
348
349         if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO))
350                 return -ENODEV;
351
352         smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL);
353         if (!smbus)
354                 return -ENOMEM;
355
356         smbus->dev = dev;
357         smbus->base = pci_resource_start(dev, 0);
358         smbus->size = pci_resource_len(dev, 0);
359
360         if (!request_region(smbus->base, smbus->size,
361                             pasemi_smb_driver.name)) {
362                 error = -EBUSY;
363                 goto out_kfree;
364         }
365
366         smbus->adapter.owner = THIS_MODULE;
367         snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
368                  "PA Semi SMBus adapter at 0x%lx", smbus->base);
369         smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
370         smbus->adapter.algo = &smbus_algorithm;
371         smbus->adapter.algo_data = smbus;
372         smbus->adapter.nr = PCI_FUNC(dev->devfn);
373
374         /* set up the sysfs linkage to our parent device */
375         smbus->adapter.dev.parent = &dev->dev;
376
377         reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR |
378                   (CLK_100K_DIV & CTL_CLK_M)));
379
380         error = i2c_add_numbered_adapter(&smbus->adapter);
381         if (error)
382                 goto out_release_region;
383
384         pci_set_drvdata(dev, smbus);
385
386         return 0;
387
388  out_release_region:
389         release_region(smbus->base, smbus->size);
390  out_kfree:
391         kfree(smbus);
392         return error;
393 }
394
395 static void __devexit pasemi_smb_remove(struct pci_dev *dev)
396 {
397         struct pasemi_smbus *smbus = pci_get_drvdata(dev);
398
399         i2c_del_adapter(&smbus->adapter);
400         release_region(smbus->base, smbus->size);
401         kfree(smbus);
402 }
403
404 static const struct pci_device_id pasemi_smb_ids[] = {
405         { PCI_DEVICE(0x1959, 0xa003) },
406         { 0, }
407 };
408
409 MODULE_DEVICE_TABLE(pci, pasemi_smb_ids);
410
411 static struct pci_driver pasemi_smb_driver = {
412         .name           = "i2c-pasemi",
413         .id_table       = pasemi_smb_ids,
414         .probe          = pasemi_smb_probe,
415         .remove         = __devexit_p(pasemi_smb_remove),
416 };
417
418 static int __init pasemi_smb_init(void)
419 {
420         return pci_register_driver(&pasemi_smb_driver);
421 }
422
423 static void __exit pasemi_smb_exit(void)
424 {
425         pci_unregister_driver(&pasemi_smb_driver);
426 }
427
428 MODULE_LICENSE("GPL");
429 MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>");
430 MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver");
431
432 module_init(pasemi_smb_init);
433 module_exit(pasemi_smb_exit);