blob: afc9c968deec9dd38c756068e3b38bfce80eab8a [file] [log] [blame]
Vitaly Wool41561f22006-12-10 21:21:29 +01001/*
2 * Provides I2C support for Philips PNX010x/PNX4008 boards.
3 *
4 * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
5 * Vitaly Wool <vwool@ru.mvista.com>
6 *
7 * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
8 * the terms of the GNU General Public License version 2. This program
9 * is licensed "as is" without any warranty of any kind, whether express
10 * or implied.
11 */
12
13#include <linux/module.h>
14#include <linux/interrupt.h>
15#include <linux/ioport.h>
16#include <linux/delay.h>
17#include <linux/i2c.h>
18#include <linux/timer.h>
19#include <linux/completion.h>
20#include <linux/platform_device.h>
21#include <linux/i2c-pnx.h>
Kevin Wellsa7d73d82009-11-12 00:25:52 +010022#include <linux/io.h>
Russell King0321cb82009-11-20 11:12:26 +000023#include <linux/err.h>
24#include <linux/clk.h>
25
Russell Kinga09e64f2008-08-05 16:14:15 +010026#include <mach/hardware.h>
Kevin Wellsa7d73d82009-11-12 00:25:52 +010027#include <mach/i2c.h>
Vitaly Wool41561f22006-12-10 21:21:29 +010028#include <asm/irq.h>
29#include <asm/uaccess.h>
30
31#define I2C_PNX_TIMEOUT 10 /* msec */
32#define I2C_PNX_SPEED_KHZ 100
33#define I2C_PNX_REGION_SIZE 0x100
Vitaly Wool41561f22006-12-10 21:21:29 +010034
35static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
36{
37 while (timeout > 0 &&
38 (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
39 mdelay(1);
40 timeout--;
41 }
42 return (timeout <= 0);
43}
44
45static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
46{
47 while (timeout > 0 &&
48 (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
49 mdelay(1);
50 timeout--;
51 }
52 return (timeout <= 0);
53}
54
Russell King81d67242009-11-21 12:40:00 +000055static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +010056{
Russell King81d67242009-11-21 12:40:00 +000057 struct timer_list *timer = &alg_data->mif.timer;
Vitaly Wool41561f22006-12-10 21:21:29 +010058 int expires = I2C_PNX_TIMEOUT / (1000 / HZ);
59
Kevin Wellsb2f125b2009-11-12 00:28:13 +010060 if (expires <= 1)
61 expires = 2;
62
Vitaly Wool41561f22006-12-10 21:21:29 +010063 del_timer_sync(timer);
64
Russell King81d67242009-11-21 12:40:00 +000065 dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %u jiffies.\n",
Vitaly Wool41561f22006-12-10 21:21:29 +010066 jiffies, expires);
67
68 timer->expires = jiffies + expires;
Russell King81d67242009-11-21 12:40:00 +000069 timer->data = (unsigned long)&alg_data;
Vitaly Wool41561f22006-12-10 21:21:29 +010070
71 add_timer(timer);
72}
73
74/**
75 * i2c_pnx_start - start a device
76 * @slave_addr: slave address
77 * @adap: pointer to adapter structure
78 *
79 * Generate a START signal in the desired mode.
80 */
Russell King81d67242009-11-21 12:40:00 +000081static int i2c_pnx_start(unsigned char slave_addr,
82 struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +010083{
Russell King81d67242009-11-21 12:40:00 +000084 dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +010085 slave_addr, alg_data->mif.mode);
86
87 /* Check for 7 bit slave addresses only */
88 if (slave_addr & ~0x7f) {
Russell King4be53db2009-11-21 12:46:31 +000089 dev_err(&alg_data->adapter.dev,
90 "%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
91 alg_data->adapter.name, slave_addr);
Vitaly Wool41561f22006-12-10 21:21:29 +010092 return -EINVAL;
93 }
94
95 /* First, make sure bus is idle */
96 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
97 /* Somebody else is monopolizing the bus */
Russell King4be53db2009-11-21 12:46:31 +000098 dev_err(&alg_data->adapter.dev,
99 "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
100 alg_data->adapter.name, slave_addr,
101 ioread32(I2C_REG_CTL(alg_data)),
102 ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100103 return -EBUSY;
104 } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
105 /* Sorry, we lost the bus */
Russell King4be53db2009-11-21 12:46:31 +0000106 dev_err(&alg_data->adapter.dev,
107 "%s: Arbitration failure. Slave addr = %02x\n",
108 alg_data->adapter.name, slave_addr);
Vitaly Wool41561f22006-12-10 21:21:29 +0100109 return -EIO;
110 }
111
112 /*
113 * OK, I2C is enabled and we have the bus.
114 * Clear the current TDI and AFI status flags.
115 */
116 iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
117 I2C_REG_STS(alg_data));
118
Russell King81d67242009-11-21 12:40:00 +0000119 dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +0100120 (slave_addr << 1) | start_bit | alg_data->mif.mode);
121
122 /* Write the slave address, START bit and R/W bit */
123 iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
124 I2C_REG_TX(alg_data));
125
Russell King81d67242009-11-21 12:40:00 +0000126 dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100127
128 return 0;
129}
130
131/**
132 * i2c_pnx_stop - stop a device
133 * @adap: pointer to I2C adapter structure
134 *
135 * Generate a STOP signal to terminate the master transaction.
136 */
Russell King81d67242009-11-21 12:40:00 +0000137static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100138{
Vitaly Wool41561f22006-12-10 21:21:29 +0100139 /* Only 1 msec max timeout due to interrupt context */
140 long timeout = 1000;
141
Russell King81d67242009-11-21 12:40:00 +0000142 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200143 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100144
145 /* Write a STOP bit to TX FIFO */
146 iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
147
148 /* Wait until the STOP is seen. */
149 while (timeout > 0 &&
150 (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
151 /* may be called from interrupt context */
152 udelay(1);
153 timeout--;
154 }
155
Russell King81d67242009-11-21 12:40:00 +0000156 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200157 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100158}
159
160/**
161 * i2c_pnx_master_xmit - transmit data to slave
162 * @adap: pointer to I2C adapter structure
163 *
164 * Sends one byte of data to the slave
165 */
Russell King81d67242009-11-21 12:40:00 +0000166static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100167{
Vitaly Wool41561f22006-12-10 21:21:29 +0100168 u32 val;
169
Russell King81d67242009-11-21 12:40:00 +0000170 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200171 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100172
173 if (alg_data->mif.len > 0) {
174 /* We still have something to talk about... */
175 val = *alg_data->mif.buf++;
176
177 if (alg_data->mif.len == 1) {
178 val |= stop_bit;
179 if (!alg_data->last)
180 val |= start_bit;
181 }
182
183 alg_data->mif.len--;
184 iowrite32(val, I2C_REG_TX(alg_data));
185
Russell King4be53db2009-11-21 12:46:31 +0000186 dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
187 __func__, val, alg_data->mif.len + 1);
Vitaly Wool41561f22006-12-10 21:21:29 +0100188
189 if (alg_data->mif.len == 0) {
190 if (alg_data->last) {
191 /* Wait until the STOP is seen. */
192 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
Russell King4be53db2009-11-21 12:46:31 +0000193 dev_err(&alg_data->adapter.dev,
194 "The bus is still active after timeout\n");
Vitaly Wool41561f22006-12-10 21:21:29 +0100195 }
196 /* Disable master interrupts */
197 iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
198 ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
199 I2C_REG_CTL(alg_data));
200
201 del_timer_sync(&alg_data->mif.timer);
202
Russell King4be53db2009-11-21 12:46:31 +0000203 dev_dbg(&alg_data->adapter.dev,
204 "%s(): Waking up xfer routine.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200205 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100206
207 complete(&alg_data->mif.complete);
208 }
209 } else if (alg_data->mif.len == 0) {
210 /* zero-sized transfer */
Russell King81d67242009-11-21 12:40:00 +0000211 i2c_pnx_stop(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100212
213 /* Disable master interrupts. */
214 iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
215 ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
216 I2C_REG_CTL(alg_data));
217
218 /* Stop timer. */
219 del_timer_sync(&alg_data->mif.timer);
Russell King4be53db2009-11-21 12:46:31 +0000220 dev_dbg(&alg_data->adapter.dev,
221 "%s(): Waking up xfer routine after zero-xfer.\n",
222 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100223
224 complete(&alg_data->mif.complete);
225 }
226
Russell King81d67242009-11-21 12:40:00 +0000227 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200228 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100229
230 return 0;
231}
232
233/**
234 * i2c_pnx_master_rcv - receive data from slave
235 * @adap: pointer to I2C adapter structure
236 *
237 * Reads one byte data from the slave
238 */
Russell King81d67242009-11-21 12:40:00 +0000239static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100240{
Vitaly Wool41561f22006-12-10 21:21:29 +0100241 unsigned int val = 0;
242 u32 ctl = 0;
243
Russell King81d67242009-11-21 12:40:00 +0000244 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200245 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100246
247 /* Check, whether there is already data,
248 * or we didn't 'ask' for it yet.
249 */
250 if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
Russell King4be53db2009-11-21 12:46:31 +0000251 dev_dbg(&alg_data->adapter.dev,
252 "%s(): Write dummy data to fill Rx-fifo...\n",
253 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100254
255 if (alg_data->mif.len == 1) {
256 /* Last byte, do not acknowledge next rcv. */
257 val |= stop_bit;
258 if (!alg_data->last)
259 val |= start_bit;
260
261 /*
262 * Enable interrupt RFDAIE (data in Rx fifo),
263 * and disable DRMIE (need data for Tx)
264 */
265 ctl = ioread32(I2C_REG_CTL(alg_data));
266 ctl |= mcntrl_rffie | mcntrl_daie;
267 ctl &= ~mcntrl_drmie;
268 iowrite32(ctl, I2C_REG_CTL(alg_data));
269 }
270
271 /*
272 * Now we'll 'ask' for data:
273 * For each byte we want to receive, we must
274 * write a (dummy) byte to the Tx-FIFO.
275 */
276 iowrite32(val, I2C_REG_TX(alg_data));
277
278 return 0;
279 }
280
281 /* Handle data. */
282 if (alg_data->mif.len > 0) {
283 val = ioread32(I2C_REG_RX(alg_data));
284 *alg_data->mif.buf++ = (u8) (val & 0xff);
Russell King4be53db2009-11-21 12:46:31 +0000285 dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
286 __func__, val, alg_data->mif.len);
Vitaly Wool41561f22006-12-10 21:21:29 +0100287
288 alg_data->mif.len--;
289 if (alg_data->mif.len == 0) {
290 if (alg_data->last)
291 /* Wait until the STOP is seen. */
292 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
Russell King4be53db2009-11-21 12:46:31 +0000293 dev_err(&alg_data->adapter.dev,
294 "The bus is still active after timeout\n");
Vitaly Wool41561f22006-12-10 21:21:29 +0100295
296 /* Disable master interrupts */
297 ctl = ioread32(I2C_REG_CTL(alg_data));
298 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
299 mcntrl_drmie | mcntrl_daie);
300 iowrite32(ctl, I2C_REG_CTL(alg_data));
301
302 /* Kill timer. */
303 del_timer_sync(&alg_data->mif.timer);
304 complete(&alg_data->mif.complete);
305 }
306 }
307
Russell King81d67242009-11-21 12:40:00 +0000308 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200309 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100310
311 return 0;
312}
313
Vitaly Wool6c566fb2007-01-04 13:07:03 +0100314static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
Vitaly Wool41561f22006-12-10 21:21:29 +0100315{
Russell King81d67242009-11-21 12:40:00 +0000316 struct i2c_pnx_algo_data *alg_data = dev_id;
Vitaly Wool41561f22006-12-10 21:21:29 +0100317 u32 stat, ctl;
Vitaly Wool41561f22006-12-10 21:21:29 +0100318
Russell King4be53db2009-11-21 12:46:31 +0000319 dev_dbg(&alg_data->adapter.dev,
320 "%s(): mstat = %x mctrl = %x, mode = %d\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200321 __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +0100322 ioread32(I2C_REG_STS(alg_data)),
323 ioread32(I2C_REG_CTL(alg_data)),
324 alg_data->mif.mode);
325 stat = ioread32(I2C_REG_STS(alg_data));
326
327 /* let's see what kind of event this is */
328 if (stat & mstatus_afi) {
329 /* We lost arbitration in the midst of a transfer */
330 alg_data->mif.ret = -EIO;
331
332 /* Disable master interrupts. */
333 ctl = ioread32(I2C_REG_CTL(alg_data));
334 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
335 mcntrl_drmie);
336 iowrite32(ctl, I2C_REG_CTL(alg_data));
337
338 /* Stop timer, to prevent timeout. */
339 del_timer_sync(&alg_data->mif.timer);
340 complete(&alg_data->mif.complete);
341 } else if (stat & mstatus_nai) {
342 /* Slave did not acknowledge, generate a STOP */
Russell King4be53db2009-11-21 12:46:31 +0000343 dev_dbg(&alg_data->adapter.dev,
344 "%s(): Slave did not acknowledge, generating a STOP.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200345 __func__);
Russell King81d67242009-11-21 12:40:00 +0000346 i2c_pnx_stop(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100347
348 /* Disable master interrupts. */
349 ctl = ioread32(I2C_REG_CTL(alg_data));
350 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
351 mcntrl_drmie);
352 iowrite32(ctl, I2C_REG_CTL(alg_data));
353
354 /* Our return value. */
355 alg_data->mif.ret = -EIO;
356
357 /* Stop timer, to prevent timeout. */
358 del_timer_sync(&alg_data->mif.timer);
359 complete(&alg_data->mif.complete);
360 } else {
361 /*
362 * Two options:
363 * - Master Tx needs data.
364 * - There is data in the Rx-fifo
365 * The latter is only the case if we have requested for data,
366 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
367 * We therefore check, as a sanity check, whether that interrupt
368 * has been enabled.
369 */
370 if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
371 if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
Russell King81d67242009-11-21 12:40:00 +0000372 i2c_pnx_master_xmit(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100373 } else if (alg_data->mif.mode == I2C_SMBUS_READ) {
Russell King81d67242009-11-21 12:40:00 +0000374 i2c_pnx_master_rcv(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100375 }
376 }
377 }
378
379 /* Clear TDI and AFI bits */
380 stat = ioread32(I2C_REG_STS(alg_data));
381 iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
382
Russell King4be53db2009-11-21 12:46:31 +0000383 dev_dbg(&alg_data->adapter.dev,
384 "%s(): exiting, stat = %x ctrl = %x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200385 __func__, ioread32(I2C_REG_STS(alg_data)),
Vitaly Wool41561f22006-12-10 21:21:29 +0100386 ioread32(I2C_REG_CTL(alg_data)));
387
388 return IRQ_HANDLED;
389}
390
391static void i2c_pnx_timeout(unsigned long data)
392{
Russell King81d67242009-11-21 12:40:00 +0000393 struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
Vitaly Wool41561f22006-12-10 21:21:29 +0100394 u32 ctl;
395
Russell King4be53db2009-11-21 12:46:31 +0000396 dev_err(&alg_data->adapter.dev,
397 "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
398 ioread32(I2C_REG_STS(alg_data)),
399 ioread32(I2C_REG_CTL(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100400
401 /* Reset master and disable interrupts */
402 ctl = ioread32(I2C_REG_CTL(alg_data));
403 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
404 iowrite32(ctl, I2C_REG_CTL(alg_data));
405
406 ctl |= mcntrl_reset;
407 iowrite32(ctl, I2C_REG_CTL(alg_data));
408 wait_reset(I2C_PNX_TIMEOUT, alg_data);
409 alg_data->mif.ret = -EIO;
410 complete(&alg_data->mif.complete);
411}
412
Russell King81d67242009-11-21 12:40:00 +0000413static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100414{
Vitaly Wool41561f22006-12-10 21:21:29 +0100415 u32 stat;
416
417 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
Russell King81d67242009-11-21 12:40:00 +0000418 dev_err(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100419 "%s: Bus is still active after xfer. Reset it...\n",
Russell King4be53db2009-11-21 12:46:31 +0000420 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100421 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
422 I2C_REG_CTL(alg_data));
423 wait_reset(I2C_PNX_TIMEOUT, alg_data);
424 } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
425 /* If there is data in the fifo's after transfer,
426 * flush fifo's by reset.
427 */
428 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
429 I2C_REG_CTL(alg_data));
430 wait_reset(I2C_PNX_TIMEOUT, alg_data);
431 } else if (stat & mstatus_nai) {
432 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
433 I2C_REG_CTL(alg_data));
434 wait_reset(I2C_PNX_TIMEOUT, alg_data);
435 }
436}
437
438/**
439 * i2c_pnx_xfer - generic transfer entry point
440 * @adap: pointer to I2C adapter structure
441 * @msgs: array of messages
442 * @num: number of messages
443 *
444 * Initiates the transfer
445 */
446static int
447i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
448{
449 struct i2c_msg *pmsg;
450 int rc = 0, completed = 0, i;
451 struct i2c_pnx_algo_data *alg_data = adap->algo_data;
452 u32 stat = ioread32(I2C_REG_STS(alg_data));
453
Russell King4be53db2009-11-21 12:46:31 +0000454 dev_dbg(&alg_data->adapter.dev,
455 "%s(): entering: %d messages, stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200456 __func__, num, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100457
Russell King81d67242009-11-21 12:40:00 +0000458 bus_reset_if_active(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100459
460 /* Process transactions in a loop. */
461 for (i = 0; rc >= 0 && i < num; i++) {
462 u8 addr;
463
464 pmsg = &msgs[i];
465 addr = pmsg->addr;
466
467 if (pmsg->flags & I2C_M_TEN) {
Russell King81d67242009-11-21 12:40:00 +0000468 dev_err(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100469 "%s: 10 bits addr not supported!\n",
Russell King81d67242009-11-21 12:40:00 +0000470 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100471 rc = -EINVAL;
472 break;
473 }
474
475 alg_data->mif.buf = pmsg->buf;
476 alg_data->mif.len = pmsg->len;
477 alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
478 I2C_SMBUS_READ : I2C_SMBUS_WRITE;
479 alg_data->mif.ret = 0;
480 alg_data->last = (i == num - 1);
481
Russell King4be53db2009-11-21 12:46:31 +0000482 dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
483 __func__, alg_data->mif.mode, alg_data->mif.len);
Vitaly Wool41561f22006-12-10 21:21:29 +0100484
Russell King81d67242009-11-21 12:40:00 +0000485 i2c_pnx_arm_timer(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100486
487 /* initialize the completion var */
488 init_completion(&alg_data->mif.complete);
489
490 /* Enable master interrupt */
491 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
492 mcntrl_naie | mcntrl_drmie,
493 I2C_REG_CTL(alg_data));
494
495 /* Put start-code and slave-address on the bus. */
Russell King81d67242009-11-21 12:40:00 +0000496 rc = i2c_pnx_start(addr, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100497 if (rc < 0)
498 break;
499
500 /* Wait for completion */
501 wait_for_completion(&alg_data->mif.complete);
502
503 if (!(rc = alg_data->mif.ret))
504 completed++;
Russell King4be53db2009-11-21 12:46:31 +0000505 dev_dbg(&alg_data->adapter.dev,
506 "%s(): Complete, return code = %d.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200507 __func__, rc);
Vitaly Wool41561f22006-12-10 21:21:29 +0100508
509 /* Clear TDI and AFI bits in case they are set. */
510 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
Russell King81d67242009-11-21 12:40:00 +0000511 dev_dbg(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100512 "%s: TDI still set... clearing now.\n",
Russell King81d67242009-11-21 12:40:00 +0000513 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100514 iowrite32(stat, I2C_REG_STS(alg_data));
515 }
516 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
Russell King81d67242009-11-21 12:40:00 +0000517 dev_dbg(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100518 "%s: AFI still set... clearing now.\n",
Russell King81d67242009-11-21 12:40:00 +0000519 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100520 iowrite32(stat, I2C_REG_STS(alg_data));
521 }
522 }
523
Russell King81d67242009-11-21 12:40:00 +0000524 bus_reset_if_active(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100525
526 /* Cleanup to be sure... */
527 alg_data->mif.buf = NULL;
528 alg_data->mif.len = 0;
529
Russell King81d67242009-11-21 12:40:00 +0000530 dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200531 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100532
533 if (completed != num)
534 return ((rc < 0) ? rc : -EREMOTEIO);
535
536 return num;
537}
538
539static u32 i2c_pnx_func(struct i2c_adapter *adapter)
540{
541 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
542}
543
544static struct i2c_algorithm pnx_algorithm = {
545 .master_xfer = i2c_pnx_xfer,
546 .functionality = i2c_pnx_func,
547};
548
Russell Kinga0dcf192009-11-20 10:50:34 +0000549#ifdef CONFIG_PM
Vitaly Wool41561f22006-12-10 21:21:29 +0100550static int i2c_pnx_controller_suspend(struct platform_device *pdev,
551 pm_message_t state)
552{
Russell King9d7f7362009-11-21 12:25:27 +0000553 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
Russell King0321cb82009-11-20 11:12:26 +0000554
Russell Kingebdbbf22009-11-20 11:44:46 +0000555 /* FIXME: shouldn't this be clk_disable? */
556 clk_enable(alg_data->clk);
Russell King0321cb82009-11-20 11:12:26 +0000557
558 return 0;
Vitaly Wool41561f22006-12-10 21:21:29 +0100559}
560
561static int i2c_pnx_controller_resume(struct platform_device *pdev)
562{
Russell King9d7f7362009-11-21 12:25:27 +0000563 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
Russell King0321cb82009-11-20 11:12:26 +0000564
Russell Kingebdbbf22009-11-20 11:44:46 +0000565 return clk_enable(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100566}
Russell Kinga0dcf192009-11-20 10:50:34 +0000567#else
568#define i2c_pnx_controller_suspend NULL
569#define i2c_pnx_controller_resume NULL
570#endif
Vitaly Wool41561f22006-12-10 21:21:29 +0100571
572static int __devinit i2c_pnx_probe(struct platform_device *pdev)
573{
574 unsigned long tmp;
575 int ret = 0;
576 struct i2c_pnx_algo_data *alg_data;
Russell King6fff3da2009-11-20 12:46:07 +0000577 unsigned long freq;
Vitaly Wool41561f22006-12-10 21:21:29 +0100578 struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
579
Russell King9d7f7362009-11-21 12:25:27 +0000580 if (!i2c_pnx || !i2c_pnx->name) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100581 dev_err(&pdev->dev, "%s: no platform data supplied\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200582 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100583 ret = -EINVAL;
584 goto out;
585 }
586
Russell King44c5d732009-11-21 12:10:54 +0000587 alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
588 if (!alg_data) {
589 ret = -ENOMEM;
590 goto err_kzalloc;
591 }
592
Russell King9d7f7362009-11-21 12:25:27 +0000593 platform_set_drvdata(pdev, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100594
Russell King9d7f7362009-11-21 12:25:27 +0000595 strlcpy(alg_data->adapter.name, i2c_pnx->name,
596 sizeof(alg_data->adapter.name));
597 alg_data->adapter.dev.parent = &pdev->dev;
598 alg_data->adapter.algo = &pnx_algorithm;
599 alg_data->adapter.algo_data = alg_data;
600 alg_data->adapter.nr = pdev->id;
601 alg_data->i2c_pnx = i2c_pnx;
Russell King0321cb82009-11-20 11:12:26 +0000602
603 alg_data->clk = clk_get(&pdev->dev, NULL);
604 if (IS_ERR(alg_data->clk)) {
605 ret = PTR_ERR(alg_data->clk);
606 goto out_drvdata;
607 }
608
Vitaly Wool41561f22006-12-10 21:21:29 +0100609 init_timer(&alg_data->mif.timer);
610 alg_data->mif.timer.function = i2c_pnx_timeout;
Russell King81d67242009-11-21 12:40:00 +0000611 alg_data->mif.timer.data = (unsigned long)alg_data;
Vitaly Wool41561f22006-12-10 21:21:29 +0100612
613 /* Register I/O resource */
Russell King44c5d732009-11-21 12:10:54 +0000614 if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
Julia Lawall449d2c72009-09-18 22:45:51 +0200615 pdev->name)) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100616 dev_err(&pdev->dev,
617 "I/O region 0x%08x for I2C already in use.\n",
Russell King44c5d732009-11-21 12:10:54 +0000618 i2c_pnx->base);
Vitaly Wool41561f22006-12-10 21:21:29 +0100619 ret = -ENODEV;
Russell King0321cb82009-11-20 11:12:26 +0000620 goto out_clkget;
Vitaly Wool41561f22006-12-10 21:21:29 +0100621 }
622
Russell King44c5d732009-11-21 12:10:54 +0000623 alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King88d968b2009-11-21 11:58:36 +0000624 if (!alg_data->ioaddr) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100625 dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
626 ret = -ENOMEM;
627 goto out_release;
628 }
629
Russell Kingebdbbf22009-11-20 11:44:46 +0000630 ret = clk_enable(alg_data->clk);
631 if (ret)
632 goto out_unmap;
Vitaly Wool41561f22006-12-10 21:21:29 +0100633
Russell King6fff3da2009-11-20 12:46:07 +0000634 freq = clk_get_rate(alg_data->clk);
635
Vitaly Wool41561f22006-12-10 21:21:29 +0100636 /*
637 * Clock Divisor High This value is the number of system clocks
638 * the serial clock (SCL) will be high.
639 * For example, if the system clock period is 50 ns and the maximum
640 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
641 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
642 * programmed into CLKHI will vary from this slightly due to
643 * variations in the output pad's rise and fall times as well as
644 * the deglitching filter length.
645 */
646
Russell King6fff3da2009-11-20 12:46:07 +0000647 tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
Vitaly Wool41561f22006-12-10 21:21:29 +0100648 iowrite32(tmp, I2C_REG_CKH(alg_data));
649 iowrite32(tmp, I2C_REG_CKL(alg_data));
650
651 iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
652 if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
653 ret = -ENODEV;
Russell Kingebdbbf22009-11-20 11:44:46 +0000654 goto out_clock;
Vitaly Wool41561f22006-12-10 21:21:29 +0100655 }
656 init_completion(&alg_data->mif.complete);
657
Russell King44c5d732009-11-21 12:10:54 +0000658 ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
Russell King81d67242009-11-21 12:40:00 +0000659 0, pdev->name, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100660 if (ret)
661 goto out_clock;
662
663 /* Register this adapter with the I2C subsystem */
Russell King9d7f7362009-11-21 12:25:27 +0000664 ret = i2c_add_numbered_adapter(&alg_data->adapter);
Vitaly Wool41561f22006-12-10 21:21:29 +0100665 if (ret < 0) {
666 dev_err(&pdev->dev, "I2C: Failed to add bus\n");
667 goto out_irq;
668 }
669
670 dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
Russell King9d7f7362009-11-21 12:25:27 +0000671 alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
Vitaly Wool41561f22006-12-10 21:21:29 +0100672
673 return 0;
674
675out_irq:
Russell King81d67242009-11-21 12:40:00 +0000676 free_irq(i2c_pnx->irq, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100677out_clock:
Russell Kingebdbbf22009-11-20 11:44:46 +0000678 clk_disable(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100679out_unmap:
Russell King88d968b2009-11-21 11:58:36 +0000680 iounmap(alg_data->ioaddr);
Vitaly Wool41561f22006-12-10 21:21:29 +0100681out_release:
Russell King44c5d732009-11-21 12:10:54 +0000682 release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King0321cb82009-11-20 11:12:26 +0000683out_clkget:
684 clk_put(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100685out_drvdata:
Russell King44c5d732009-11-21 12:10:54 +0000686 kfree(alg_data);
687err_kzalloc:
Vitaly Wool41561f22006-12-10 21:21:29 +0100688 platform_set_drvdata(pdev, NULL);
689out:
690 return ret;
691}
692
693static int __devexit i2c_pnx_remove(struct platform_device *pdev)
694{
Russell King9d7f7362009-11-21 12:25:27 +0000695 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
696 struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
Vitaly Wool41561f22006-12-10 21:21:29 +0100697
Russell King81d67242009-11-21 12:40:00 +0000698 free_irq(i2c_pnx->irq, alg_data);
Russell King9d7f7362009-11-21 12:25:27 +0000699 i2c_del_adapter(&alg_data->adapter);
Russell Kingebdbbf22009-11-20 11:44:46 +0000700 clk_disable(alg_data->clk);
Russell King88d968b2009-11-21 11:58:36 +0000701 iounmap(alg_data->ioaddr);
Russell King44c5d732009-11-21 12:10:54 +0000702 release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King0321cb82009-11-20 11:12:26 +0000703 clk_put(alg_data->clk);
Russell King44c5d732009-11-21 12:10:54 +0000704 kfree(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100705 platform_set_drvdata(pdev, NULL);
706
707 return 0;
708}
709
710static struct platform_driver i2c_pnx_driver = {
711 .driver = {
712 .name = "pnx-i2c",
713 .owner = THIS_MODULE,
714 },
715 .probe = i2c_pnx_probe,
716 .remove = __devexit_p(i2c_pnx_remove),
717 .suspend = i2c_pnx_controller_suspend,
718 .resume = i2c_pnx_controller_resume,
719};
720
721static int __init i2c_adap_pnx_init(void)
722{
723 return platform_driver_register(&i2c_pnx_driver);
724}
725
726static void __exit i2c_adap_pnx_exit(void)
727{
728 platform_driver_unregister(&i2c_pnx_driver);
729}
730
731MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
732MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
733MODULE_LICENSE("GPL");
Kay Sieversadd8eda2008-04-22 22:16:49 +0200734MODULE_ALIAS("platform:pnx-i2c");
Vitaly Wool41561f22006-12-10 21:21:29 +0100735
Vitaly Wool41561f22006-12-10 21:21:29 +0100736/* We need to make sure I2C is initialized before USB */
737subsys_initcall(i2c_adap_pnx_init);
Vitaly Wool41561f22006-12-10 21:21:29 +0100738module_exit(i2c_adap_pnx_exit);