blob: 2b0bd0b042d6df7bd8513f20232619853c130939 [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
29#define I2C_PNX_TIMEOUT 10 /* msec */
30#define I2C_PNX_SPEED_KHZ 100
31#define I2C_PNX_REGION_SIZE 0x100
Vitaly Wool41561f22006-12-10 21:21:29 +010032
33static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
34{
35 while (timeout > 0 &&
36 (ioread32(I2C_REG_STS(data)) & mstatus_active)) {
37 mdelay(1);
38 timeout--;
39 }
40 return (timeout <= 0);
41}
42
43static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
44{
45 while (timeout > 0 &&
46 (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
47 mdelay(1);
48 timeout--;
49 }
50 return (timeout <= 0);
51}
52
Russell King81d67242009-11-21 12:40:00 +000053static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +010054{
Russell King81d67242009-11-21 12:40:00 +000055 struct timer_list *timer = &alg_data->mif.timer;
Russell Kingeed18b52009-11-21 12:58:13 +000056 unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
Vitaly Wool41561f22006-12-10 21:21:29 +010057
Kevin Wellsb2f125b2009-11-12 00:28:13 +010058 if (expires <= 1)
59 expires = 2;
60
Vitaly Wool41561f22006-12-10 21:21:29 +010061 del_timer_sync(timer);
62
Russell Kingeed18b52009-11-21 12:58:13 +000063 dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
Vitaly Wool41561f22006-12-10 21:21:29 +010064 jiffies, expires);
65
66 timer->expires = jiffies + expires;
Russell King81d67242009-11-21 12:40:00 +000067 timer->data = (unsigned long)&alg_data;
Vitaly Wool41561f22006-12-10 21:21:29 +010068
69 add_timer(timer);
70}
71
72/**
73 * i2c_pnx_start - start a device
74 * @slave_addr: slave address
75 * @adap: pointer to adapter structure
76 *
77 * Generate a START signal in the desired mode.
78 */
Russell King81d67242009-11-21 12:40:00 +000079static int i2c_pnx_start(unsigned char slave_addr,
80 struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +010081{
Russell King81d67242009-11-21 12:40:00 +000082 dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +010083 slave_addr, alg_data->mif.mode);
84
85 /* Check for 7 bit slave addresses only */
86 if (slave_addr & ~0x7f) {
Russell King4be53db2009-11-21 12:46:31 +000087 dev_err(&alg_data->adapter.dev,
88 "%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
89 alg_data->adapter.name, slave_addr);
Vitaly Wool41561f22006-12-10 21:21:29 +010090 return -EINVAL;
91 }
92
93 /* First, make sure bus is idle */
94 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
95 /* Somebody else is monopolizing the bus */
Russell King4be53db2009-11-21 12:46:31 +000096 dev_err(&alg_data->adapter.dev,
97 "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
98 alg_data->adapter.name, slave_addr,
99 ioread32(I2C_REG_CTL(alg_data)),
100 ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100101 return -EBUSY;
102 } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
103 /* Sorry, we lost the bus */
Russell King4be53db2009-11-21 12:46:31 +0000104 dev_err(&alg_data->adapter.dev,
105 "%s: Arbitration failure. Slave addr = %02x\n",
106 alg_data->adapter.name, slave_addr);
Vitaly Wool41561f22006-12-10 21:21:29 +0100107 return -EIO;
108 }
109
110 /*
111 * OK, I2C is enabled and we have the bus.
112 * Clear the current TDI and AFI status flags.
113 */
114 iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
115 I2C_REG_STS(alg_data));
116
Russell King81d67242009-11-21 12:40:00 +0000117 dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +0100118 (slave_addr << 1) | start_bit | alg_data->mif.mode);
119
120 /* Write the slave address, START bit and R/W bit */
121 iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
122 I2C_REG_TX(alg_data));
123
Russell King81d67242009-11-21 12:40:00 +0000124 dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100125
126 return 0;
127}
128
129/**
130 * i2c_pnx_stop - stop a device
131 * @adap: pointer to I2C adapter structure
132 *
133 * Generate a STOP signal to terminate the master transaction.
134 */
Russell King81d67242009-11-21 12:40:00 +0000135static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100136{
Vitaly Wool41561f22006-12-10 21:21:29 +0100137 /* Only 1 msec max timeout due to interrupt context */
138 long timeout = 1000;
139
Russell King81d67242009-11-21 12:40:00 +0000140 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200141 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100142
143 /* Write a STOP bit to TX FIFO */
144 iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
145
146 /* Wait until the STOP is seen. */
147 while (timeout > 0 &&
148 (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
149 /* may be called from interrupt context */
150 udelay(1);
151 timeout--;
152 }
153
Russell King81d67242009-11-21 12:40:00 +0000154 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200155 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100156}
157
158/**
159 * i2c_pnx_master_xmit - transmit data to slave
160 * @adap: pointer to I2C adapter structure
161 *
162 * Sends one byte of data to the slave
163 */
Russell King81d67242009-11-21 12:40:00 +0000164static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100165{
Vitaly Wool41561f22006-12-10 21:21:29 +0100166 u32 val;
167
Russell King81d67242009-11-21 12:40:00 +0000168 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200169 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100170
171 if (alg_data->mif.len > 0) {
172 /* We still have something to talk about... */
173 val = *alg_data->mif.buf++;
174
175 if (alg_data->mif.len == 1) {
176 val |= stop_bit;
177 if (!alg_data->last)
178 val |= start_bit;
179 }
180
181 alg_data->mif.len--;
182 iowrite32(val, I2C_REG_TX(alg_data));
183
Russell King4be53db2009-11-21 12:46:31 +0000184 dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
185 __func__, val, alg_data->mif.len + 1);
Vitaly Wool41561f22006-12-10 21:21:29 +0100186
187 if (alg_data->mif.len == 0) {
188 if (alg_data->last) {
189 /* Wait until the STOP is seen. */
190 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
Russell King4be53db2009-11-21 12:46:31 +0000191 dev_err(&alg_data->adapter.dev,
192 "The bus is still active after timeout\n");
Vitaly Wool41561f22006-12-10 21:21:29 +0100193 }
194 /* Disable master interrupts */
195 iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
196 ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
197 I2C_REG_CTL(alg_data));
198
199 del_timer_sync(&alg_data->mif.timer);
200
Russell King4be53db2009-11-21 12:46:31 +0000201 dev_dbg(&alg_data->adapter.dev,
202 "%s(): Waking up xfer routine.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200203 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100204
205 complete(&alg_data->mif.complete);
206 }
207 } else if (alg_data->mif.len == 0) {
208 /* zero-sized transfer */
Russell King81d67242009-11-21 12:40:00 +0000209 i2c_pnx_stop(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100210
211 /* Disable master interrupts. */
212 iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
213 ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
214 I2C_REG_CTL(alg_data));
215
216 /* Stop timer. */
217 del_timer_sync(&alg_data->mif.timer);
Russell King4be53db2009-11-21 12:46:31 +0000218 dev_dbg(&alg_data->adapter.dev,
219 "%s(): Waking up xfer routine after zero-xfer.\n",
220 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100221
222 complete(&alg_data->mif.complete);
223 }
224
Russell King81d67242009-11-21 12:40:00 +0000225 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200226 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100227
228 return 0;
229}
230
231/**
232 * i2c_pnx_master_rcv - receive data from slave
233 * @adap: pointer to I2C adapter structure
234 *
235 * Reads one byte data from the slave
236 */
Russell King81d67242009-11-21 12:40:00 +0000237static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100238{
Vitaly Wool41561f22006-12-10 21:21:29 +0100239 unsigned int val = 0;
240 u32 ctl = 0;
241
Russell King81d67242009-11-21 12:40:00 +0000242 dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200243 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100244
245 /* Check, whether there is already data,
246 * or we didn't 'ask' for it yet.
247 */
248 if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
Russell King4be53db2009-11-21 12:46:31 +0000249 dev_dbg(&alg_data->adapter.dev,
250 "%s(): Write dummy data to fill Rx-fifo...\n",
251 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100252
253 if (alg_data->mif.len == 1) {
254 /* Last byte, do not acknowledge next rcv. */
255 val |= stop_bit;
256 if (!alg_data->last)
257 val |= start_bit;
258
259 /*
260 * Enable interrupt RFDAIE (data in Rx fifo),
261 * and disable DRMIE (need data for Tx)
262 */
263 ctl = ioread32(I2C_REG_CTL(alg_data));
264 ctl |= mcntrl_rffie | mcntrl_daie;
265 ctl &= ~mcntrl_drmie;
266 iowrite32(ctl, I2C_REG_CTL(alg_data));
267 }
268
269 /*
270 * Now we'll 'ask' for data:
271 * For each byte we want to receive, we must
272 * write a (dummy) byte to the Tx-FIFO.
273 */
274 iowrite32(val, I2C_REG_TX(alg_data));
275
276 return 0;
277 }
278
279 /* Handle data. */
280 if (alg_data->mif.len > 0) {
281 val = ioread32(I2C_REG_RX(alg_data));
282 *alg_data->mif.buf++ = (u8) (val & 0xff);
Russell King4be53db2009-11-21 12:46:31 +0000283 dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
284 __func__, val, alg_data->mif.len);
Vitaly Wool41561f22006-12-10 21:21:29 +0100285
286 alg_data->mif.len--;
287 if (alg_data->mif.len == 0) {
288 if (alg_data->last)
289 /* Wait until the STOP is seen. */
290 if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
Russell King4be53db2009-11-21 12:46:31 +0000291 dev_err(&alg_data->adapter.dev,
292 "The bus is still active after timeout\n");
Vitaly Wool41561f22006-12-10 21:21:29 +0100293
294 /* Disable master interrupts */
295 ctl = ioread32(I2C_REG_CTL(alg_data));
296 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
297 mcntrl_drmie | mcntrl_daie);
298 iowrite32(ctl, I2C_REG_CTL(alg_data));
299
300 /* Kill timer. */
301 del_timer_sync(&alg_data->mif.timer);
302 complete(&alg_data->mif.complete);
303 }
304 }
305
Russell King81d67242009-11-21 12:40:00 +0000306 dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200307 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100308
309 return 0;
310}
311
Vitaly Wool6c566fb2007-01-04 13:07:03 +0100312static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
Vitaly Wool41561f22006-12-10 21:21:29 +0100313{
Russell King81d67242009-11-21 12:40:00 +0000314 struct i2c_pnx_algo_data *alg_data = dev_id;
Vitaly Wool41561f22006-12-10 21:21:29 +0100315 u32 stat, ctl;
Vitaly Wool41561f22006-12-10 21:21:29 +0100316
Russell King4be53db2009-11-21 12:46:31 +0000317 dev_dbg(&alg_data->adapter.dev,
318 "%s(): mstat = %x mctrl = %x, mode = %d\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200319 __func__,
Vitaly Wool41561f22006-12-10 21:21:29 +0100320 ioread32(I2C_REG_STS(alg_data)),
321 ioread32(I2C_REG_CTL(alg_data)),
322 alg_data->mif.mode);
323 stat = ioread32(I2C_REG_STS(alg_data));
324
325 /* let's see what kind of event this is */
326 if (stat & mstatus_afi) {
327 /* We lost arbitration in the midst of a transfer */
328 alg_data->mif.ret = -EIO;
329
330 /* Disable master interrupts. */
331 ctl = ioread32(I2C_REG_CTL(alg_data));
332 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
333 mcntrl_drmie);
334 iowrite32(ctl, I2C_REG_CTL(alg_data));
335
336 /* Stop timer, to prevent timeout. */
337 del_timer_sync(&alg_data->mif.timer);
338 complete(&alg_data->mif.complete);
339 } else if (stat & mstatus_nai) {
340 /* Slave did not acknowledge, generate a STOP */
Russell King4be53db2009-11-21 12:46:31 +0000341 dev_dbg(&alg_data->adapter.dev,
342 "%s(): Slave did not acknowledge, generating a STOP.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200343 __func__);
Russell King81d67242009-11-21 12:40:00 +0000344 i2c_pnx_stop(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100345
346 /* Disable master interrupts. */
347 ctl = ioread32(I2C_REG_CTL(alg_data));
348 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
349 mcntrl_drmie);
350 iowrite32(ctl, I2C_REG_CTL(alg_data));
351
352 /* Our return value. */
353 alg_data->mif.ret = -EIO;
354
355 /* Stop timer, to prevent timeout. */
356 del_timer_sync(&alg_data->mif.timer);
357 complete(&alg_data->mif.complete);
358 } else {
359 /*
360 * Two options:
361 * - Master Tx needs data.
362 * - There is data in the Rx-fifo
363 * The latter is only the case if we have requested for data,
364 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
365 * We therefore check, as a sanity check, whether that interrupt
366 * has been enabled.
367 */
368 if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
369 if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
Russell King81d67242009-11-21 12:40:00 +0000370 i2c_pnx_master_xmit(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100371 } else if (alg_data->mif.mode == I2C_SMBUS_READ) {
Russell King81d67242009-11-21 12:40:00 +0000372 i2c_pnx_master_rcv(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100373 }
374 }
375 }
376
377 /* Clear TDI and AFI bits */
378 stat = ioread32(I2C_REG_STS(alg_data));
379 iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
380
Russell King4be53db2009-11-21 12:46:31 +0000381 dev_dbg(&alg_data->adapter.dev,
382 "%s(): exiting, stat = %x ctrl = %x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200383 __func__, ioread32(I2C_REG_STS(alg_data)),
Vitaly Wool41561f22006-12-10 21:21:29 +0100384 ioread32(I2C_REG_CTL(alg_data)));
385
386 return IRQ_HANDLED;
387}
388
389static void i2c_pnx_timeout(unsigned long data)
390{
Russell King81d67242009-11-21 12:40:00 +0000391 struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
Vitaly Wool41561f22006-12-10 21:21:29 +0100392 u32 ctl;
393
Russell King4be53db2009-11-21 12:46:31 +0000394 dev_err(&alg_data->adapter.dev,
395 "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
396 ioread32(I2C_REG_STS(alg_data)),
397 ioread32(I2C_REG_CTL(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100398
399 /* Reset master and disable interrupts */
400 ctl = ioread32(I2C_REG_CTL(alg_data));
401 ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
402 iowrite32(ctl, I2C_REG_CTL(alg_data));
403
404 ctl |= mcntrl_reset;
405 iowrite32(ctl, I2C_REG_CTL(alg_data));
406 wait_reset(I2C_PNX_TIMEOUT, alg_data);
407 alg_data->mif.ret = -EIO;
408 complete(&alg_data->mif.complete);
409}
410
Russell King81d67242009-11-21 12:40:00 +0000411static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
Vitaly Wool41561f22006-12-10 21:21:29 +0100412{
Vitaly Wool41561f22006-12-10 21:21:29 +0100413 u32 stat;
414
415 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
Russell King81d67242009-11-21 12:40:00 +0000416 dev_err(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100417 "%s: Bus is still active after xfer. Reset it...\n",
Russell King4be53db2009-11-21 12:46:31 +0000418 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100419 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
420 I2C_REG_CTL(alg_data));
421 wait_reset(I2C_PNX_TIMEOUT, alg_data);
422 } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
423 /* If there is data in the fifo's after transfer,
424 * flush fifo's by reset.
425 */
426 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
427 I2C_REG_CTL(alg_data));
428 wait_reset(I2C_PNX_TIMEOUT, alg_data);
429 } else if (stat & mstatus_nai) {
430 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
431 I2C_REG_CTL(alg_data));
432 wait_reset(I2C_PNX_TIMEOUT, alg_data);
433 }
434}
435
436/**
437 * i2c_pnx_xfer - generic transfer entry point
438 * @adap: pointer to I2C adapter structure
439 * @msgs: array of messages
440 * @num: number of messages
441 *
442 * Initiates the transfer
443 */
444static int
445i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
446{
447 struct i2c_msg *pmsg;
448 int rc = 0, completed = 0, i;
449 struct i2c_pnx_algo_data *alg_data = adap->algo_data;
450 u32 stat = ioread32(I2C_REG_STS(alg_data));
451
Russell King4be53db2009-11-21 12:46:31 +0000452 dev_dbg(&alg_data->adapter.dev,
453 "%s(): entering: %d messages, stat = %04x.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200454 __func__, num, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100455
Russell King81d67242009-11-21 12:40:00 +0000456 bus_reset_if_active(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100457
458 /* Process transactions in a loop. */
459 for (i = 0; rc >= 0 && i < num; i++) {
460 u8 addr;
461
462 pmsg = &msgs[i];
463 addr = pmsg->addr;
464
465 if (pmsg->flags & I2C_M_TEN) {
Russell King81d67242009-11-21 12:40:00 +0000466 dev_err(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100467 "%s: 10 bits addr not supported!\n",
Russell King81d67242009-11-21 12:40:00 +0000468 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100469 rc = -EINVAL;
470 break;
471 }
472
473 alg_data->mif.buf = pmsg->buf;
474 alg_data->mif.len = pmsg->len;
475 alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
476 I2C_SMBUS_READ : I2C_SMBUS_WRITE;
477 alg_data->mif.ret = 0;
478 alg_data->last = (i == num - 1);
479
Russell King4be53db2009-11-21 12:46:31 +0000480 dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
481 __func__, alg_data->mif.mode, alg_data->mif.len);
Vitaly Wool41561f22006-12-10 21:21:29 +0100482
Russell King81d67242009-11-21 12:40:00 +0000483 i2c_pnx_arm_timer(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100484
485 /* initialize the completion var */
486 init_completion(&alg_data->mif.complete);
487
488 /* Enable master interrupt */
489 iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
490 mcntrl_naie | mcntrl_drmie,
491 I2C_REG_CTL(alg_data));
492
493 /* Put start-code and slave-address on the bus. */
Russell King81d67242009-11-21 12:40:00 +0000494 rc = i2c_pnx_start(addr, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100495 if (rc < 0)
496 break;
497
498 /* Wait for completion */
499 wait_for_completion(&alg_data->mif.complete);
500
501 if (!(rc = alg_data->mif.ret))
502 completed++;
Russell King4be53db2009-11-21 12:46:31 +0000503 dev_dbg(&alg_data->adapter.dev,
504 "%s(): Complete, return code = %d.\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200505 __func__, rc);
Vitaly Wool41561f22006-12-10 21:21:29 +0100506
507 /* Clear TDI and AFI bits in case they are set. */
508 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
Russell King81d67242009-11-21 12:40:00 +0000509 dev_dbg(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100510 "%s: TDI still set... clearing now.\n",
Russell King81d67242009-11-21 12:40:00 +0000511 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100512 iowrite32(stat, I2C_REG_STS(alg_data));
513 }
514 if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
Russell King81d67242009-11-21 12:40:00 +0000515 dev_dbg(&alg_data->adapter.dev,
Vitaly Wool41561f22006-12-10 21:21:29 +0100516 "%s: AFI still set... clearing now.\n",
Russell King81d67242009-11-21 12:40:00 +0000517 alg_data->adapter.name);
Vitaly Wool41561f22006-12-10 21:21:29 +0100518 iowrite32(stat, I2C_REG_STS(alg_data));
519 }
520 }
521
Russell King81d67242009-11-21 12:40:00 +0000522 bus_reset_if_active(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100523
524 /* Cleanup to be sure... */
525 alg_data->mif.buf = NULL;
526 alg_data->mif.len = 0;
527
Russell King81d67242009-11-21 12:40:00 +0000528 dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200529 __func__, ioread32(I2C_REG_STS(alg_data)));
Vitaly Wool41561f22006-12-10 21:21:29 +0100530
531 if (completed != num)
532 return ((rc < 0) ? rc : -EREMOTEIO);
533
534 return num;
535}
536
537static u32 i2c_pnx_func(struct i2c_adapter *adapter)
538{
539 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
540}
541
542static struct i2c_algorithm pnx_algorithm = {
543 .master_xfer = i2c_pnx_xfer,
544 .functionality = i2c_pnx_func,
545};
546
Russell Kinga0dcf192009-11-20 10:50:34 +0000547#ifdef CONFIG_PM
Vitaly Wool41561f22006-12-10 21:21:29 +0100548static int i2c_pnx_controller_suspend(struct platform_device *pdev,
549 pm_message_t state)
550{
Russell King9d7f7362009-11-21 12:25:27 +0000551 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
Russell King0321cb82009-11-20 11:12:26 +0000552
Russell Kingebdbbf22009-11-20 11:44:46 +0000553 /* FIXME: shouldn't this be clk_disable? */
554 clk_enable(alg_data->clk);
Russell King0321cb82009-11-20 11:12:26 +0000555
556 return 0;
Vitaly Wool41561f22006-12-10 21:21:29 +0100557}
558
559static int i2c_pnx_controller_resume(struct platform_device *pdev)
560{
Russell King9d7f7362009-11-21 12:25:27 +0000561 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
Russell King0321cb82009-11-20 11:12:26 +0000562
Russell Kingebdbbf22009-11-20 11:44:46 +0000563 return clk_enable(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100564}
Russell Kinga0dcf192009-11-20 10:50:34 +0000565#else
566#define i2c_pnx_controller_suspend NULL
567#define i2c_pnx_controller_resume NULL
568#endif
Vitaly Wool41561f22006-12-10 21:21:29 +0100569
570static int __devinit i2c_pnx_probe(struct platform_device *pdev)
571{
572 unsigned long tmp;
573 int ret = 0;
574 struct i2c_pnx_algo_data *alg_data;
Russell King6fff3da2009-11-20 12:46:07 +0000575 unsigned long freq;
Vitaly Wool41561f22006-12-10 21:21:29 +0100576 struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
577
Russell King9d7f7362009-11-21 12:25:27 +0000578 if (!i2c_pnx || !i2c_pnx->name) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100579 dev_err(&pdev->dev, "%s: no platform data supplied\n",
Harvey Harrison08882d22008-04-22 22:16:47 +0200580 __func__);
Vitaly Wool41561f22006-12-10 21:21:29 +0100581 ret = -EINVAL;
582 goto out;
583 }
584
Russell King44c5d732009-11-21 12:10:54 +0000585 alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
586 if (!alg_data) {
587 ret = -ENOMEM;
588 goto err_kzalloc;
589 }
590
Russell King9d7f7362009-11-21 12:25:27 +0000591 platform_set_drvdata(pdev, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100592
Russell King9d7f7362009-11-21 12:25:27 +0000593 strlcpy(alg_data->adapter.name, i2c_pnx->name,
594 sizeof(alg_data->adapter.name));
595 alg_data->adapter.dev.parent = &pdev->dev;
596 alg_data->adapter.algo = &pnx_algorithm;
597 alg_data->adapter.algo_data = alg_data;
598 alg_data->adapter.nr = pdev->id;
599 alg_data->i2c_pnx = i2c_pnx;
Russell King0321cb82009-11-20 11:12:26 +0000600
601 alg_data->clk = clk_get(&pdev->dev, NULL);
602 if (IS_ERR(alg_data->clk)) {
603 ret = PTR_ERR(alg_data->clk);
604 goto out_drvdata;
605 }
606
Vitaly Wool41561f22006-12-10 21:21:29 +0100607 init_timer(&alg_data->mif.timer);
608 alg_data->mif.timer.function = i2c_pnx_timeout;
Russell King81d67242009-11-21 12:40:00 +0000609 alg_data->mif.timer.data = (unsigned long)alg_data;
Vitaly Wool41561f22006-12-10 21:21:29 +0100610
611 /* Register I/O resource */
Russell King44c5d732009-11-21 12:10:54 +0000612 if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
Julia Lawall449d2c72009-09-18 22:45:51 +0200613 pdev->name)) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100614 dev_err(&pdev->dev,
615 "I/O region 0x%08x for I2C already in use.\n",
Russell King44c5d732009-11-21 12:10:54 +0000616 i2c_pnx->base);
Vitaly Wool41561f22006-12-10 21:21:29 +0100617 ret = -ENODEV;
Russell King0321cb82009-11-20 11:12:26 +0000618 goto out_clkget;
Vitaly Wool41561f22006-12-10 21:21:29 +0100619 }
620
Russell King44c5d732009-11-21 12:10:54 +0000621 alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King88d968b2009-11-21 11:58:36 +0000622 if (!alg_data->ioaddr) {
Vitaly Wool41561f22006-12-10 21:21:29 +0100623 dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
624 ret = -ENOMEM;
625 goto out_release;
626 }
627
Russell Kingebdbbf22009-11-20 11:44:46 +0000628 ret = clk_enable(alg_data->clk);
629 if (ret)
630 goto out_unmap;
Vitaly Wool41561f22006-12-10 21:21:29 +0100631
Russell King6fff3da2009-11-20 12:46:07 +0000632 freq = clk_get_rate(alg_data->clk);
633
Vitaly Wool41561f22006-12-10 21:21:29 +0100634 /*
635 * Clock Divisor High This value is the number of system clocks
636 * the serial clock (SCL) will be high.
637 * For example, if the system clock period is 50 ns and the maximum
638 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
639 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
640 * programmed into CLKHI will vary from this slightly due to
641 * variations in the output pad's rise and fall times as well as
642 * the deglitching filter length.
643 */
644
Russell King6fff3da2009-11-20 12:46:07 +0000645 tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
Vitaly Wool41561f22006-12-10 21:21:29 +0100646 iowrite32(tmp, I2C_REG_CKH(alg_data));
647 iowrite32(tmp, I2C_REG_CKL(alg_data));
648
649 iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
650 if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
651 ret = -ENODEV;
Russell Kingebdbbf22009-11-20 11:44:46 +0000652 goto out_clock;
Vitaly Wool41561f22006-12-10 21:21:29 +0100653 }
654 init_completion(&alg_data->mif.complete);
655
Russell King44c5d732009-11-21 12:10:54 +0000656 ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
Russell King81d67242009-11-21 12:40:00 +0000657 0, pdev->name, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100658 if (ret)
659 goto out_clock;
660
661 /* Register this adapter with the I2C subsystem */
Russell King9d7f7362009-11-21 12:25:27 +0000662 ret = i2c_add_numbered_adapter(&alg_data->adapter);
Vitaly Wool41561f22006-12-10 21:21:29 +0100663 if (ret < 0) {
664 dev_err(&pdev->dev, "I2C: Failed to add bus\n");
665 goto out_irq;
666 }
667
668 dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
Russell King9d7f7362009-11-21 12:25:27 +0000669 alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
Vitaly Wool41561f22006-12-10 21:21:29 +0100670
671 return 0;
672
673out_irq:
Russell King81d67242009-11-21 12:40:00 +0000674 free_irq(i2c_pnx->irq, alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100675out_clock:
Russell Kingebdbbf22009-11-20 11:44:46 +0000676 clk_disable(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100677out_unmap:
Russell King88d968b2009-11-21 11:58:36 +0000678 iounmap(alg_data->ioaddr);
Vitaly Wool41561f22006-12-10 21:21:29 +0100679out_release:
Russell King44c5d732009-11-21 12:10:54 +0000680 release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King0321cb82009-11-20 11:12:26 +0000681out_clkget:
682 clk_put(alg_data->clk);
Vitaly Wool41561f22006-12-10 21:21:29 +0100683out_drvdata:
Russell King44c5d732009-11-21 12:10:54 +0000684 kfree(alg_data);
685err_kzalloc:
Vitaly Wool41561f22006-12-10 21:21:29 +0100686 platform_set_drvdata(pdev, NULL);
687out:
688 return ret;
689}
690
691static int __devexit i2c_pnx_remove(struct platform_device *pdev)
692{
Russell King9d7f7362009-11-21 12:25:27 +0000693 struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
694 struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
Vitaly Wool41561f22006-12-10 21:21:29 +0100695
Russell King81d67242009-11-21 12:40:00 +0000696 free_irq(i2c_pnx->irq, alg_data);
Russell King9d7f7362009-11-21 12:25:27 +0000697 i2c_del_adapter(&alg_data->adapter);
Russell Kingebdbbf22009-11-20 11:44:46 +0000698 clk_disable(alg_data->clk);
Russell King88d968b2009-11-21 11:58:36 +0000699 iounmap(alg_data->ioaddr);
Russell King44c5d732009-11-21 12:10:54 +0000700 release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
Russell King0321cb82009-11-20 11:12:26 +0000701 clk_put(alg_data->clk);
Russell King44c5d732009-11-21 12:10:54 +0000702 kfree(alg_data);
Vitaly Wool41561f22006-12-10 21:21:29 +0100703 platform_set_drvdata(pdev, NULL);
704
705 return 0;
706}
707
708static struct platform_driver i2c_pnx_driver = {
709 .driver = {
710 .name = "pnx-i2c",
711 .owner = THIS_MODULE,
712 },
713 .probe = i2c_pnx_probe,
714 .remove = __devexit_p(i2c_pnx_remove),
715 .suspend = i2c_pnx_controller_suspend,
716 .resume = i2c_pnx_controller_resume,
717};
718
719static int __init i2c_adap_pnx_init(void)
720{
721 return platform_driver_register(&i2c_pnx_driver);
722}
723
724static void __exit i2c_adap_pnx_exit(void)
725{
726 platform_driver_unregister(&i2c_pnx_driver);
727}
728
729MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
730MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
731MODULE_LICENSE("GPL");
Kay Sieversadd8eda2008-04-22 22:16:49 +0200732MODULE_ALIAS("platform:pnx-i2c");
Vitaly Wool41561f22006-12-10 21:21:29 +0100733
Vitaly Wool41561f22006-12-10 21:21:29 +0100734/* We need to make sure I2C is initialized before USB */
735subsys_initcall(i2c_adap_pnx_init);
Vitaly Wool41561f22006-12-10 21:21:29 +0100736module_exit(i2c_adap_pnx_exit);