i2c-pnx.c 19.3 KB
Newer Older
V
Vitaly Wool 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Provides I2C support for Philips PNX010x/PNX4008 boards.
 *
 * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
 *	    Vitaly Wool <vwool@ru.mvista.com>
 *
 * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
 * the terms of the GNU General Public License version 2. This program
 * is licensed "as is" without any warranty of any kind, whether express
 * or implied.
 */

#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/timer.h>
#include <linux/completion.h>
#include <linux/platform_device.h>
#include <linux/i2c-pnx.h>
22
#include <linux/io.h>
23 24
#include <linux/err.h>
#include <linux/clk.h>
25
#include <linux/slab.h>
26

27
#include <mach/hardware.h>
28
#include <mach/i2c.h>
V
Vitaly Wool 已提交
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53

#define I2C_PNX_TIMEOUT		10 /* msec */
#define I2C_PNX_SPEED_KHZ	100
#define I2C_PNX_REGION_SIZE	0x100

static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
{
	while (timeout > 0 &&
			(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
		mdelay(1);
		timeout--;
	}
	return (timeout <= 0);
}

static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
{
	while (timeout > 0 &&
			(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
		mdelay(1);
		timeout--;
	}
	return (timeout <= 0);
}

54
static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
55
{
56
	struct timer_list *timer = &alg_data->mif.timer;
57
	unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
V
Vitaly Wool 已提交
58

59 60 61
	if (expires <= 1)
		expires = 2;

V
Vitaly Wool 已提交
62 63
	del_timer_sync(timer);

64
	dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
V
Vitaly Wool 已提交
65 66 67
		jiffies, expires);

	timer->expires = jiffies + expires;
68
	timer->data = (unsigned long)&alg_data;
V
Vitaly Wool 已提交
69 70 71 72 73 74 75 76 77 78 79

	add_timer(timer);
}

/**
 * i2c_pnx_start - start a device
 * @slave_addr:		slave address
 * @adap:		pointer to adapter structure
 *
 * Generate a START signal in the desired mode.
 */
80 81
static int i2c_pnx_start(unsigned char slave_addr,
	struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
82
{
83
	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
V
Vitaly Wool 已提交
84 85 86 87
		slave_addr, alg_data->mif.mode);

	/* Check for 7 bit slave addresses only */
	if (slave_addr & ~0x7f) {
88 89 90
		dev_err(&alg_data->adapter.dev,
			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
			alg_data->adapter.name, slave_addr);
V
Vitaly Wool 已提交
91 92 93 94 95 96
		return -EINVAL;
	}

	/* First, make sure bus is idle */
	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
		/* Somebody else is monopolizing the bus */
97 98 99 100 101
		dev_err(&alg_data->adapter.dev,
			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
			alg_data->adapter.name, slave_addr,
			ioread32(I2C_REG_CTL(alg_data)),
			ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
102 103 104
		return -EBUSY;
	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
		/* Sorry, we lost the bus */
105 106 107
		dev_err(&alg_data->adapter.dev,
		        "%s: Arbitration failure. Slave addr = %02x\n",
			alg_data->adapter.name, slave_addr);
V
Vitaly Wool 已提交
108 109 110 111 112 113 114 115 116 117
		return -EIO;
	}

	/*
	 * OK, I2C is enabled and we have the bus.
	 * Clear the current TDI and AFI status flags.
	 */
	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
		  I2C_REG_STS(alg_data));

118
	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
V
Vitaly Wool 已提交
119 120 121 122 123 124
		(slave_addr << 1) | start_bit | alg_data->mif.mode);

	/* Write the slave address, START bit and R/W bit */
	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
		  I2C_REG_TX(alg_data));

125
	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
V
Vitaly Wool 已提交
126 127 128 129 130 131 132 133 134 135

	return 0;
}

/**
 * i2c_pnx_stop - stop a device
 * @adap:		pointer to I2C adapter structure
 *
 * Generate a STOP signal to terminate the master transaction.
 */
136
static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
137 138 139 140
{
	/* Only 1 msec max timeout due to interrupt context */
	long timeout = 1000;

141
	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
142
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
143 144 145 146 147 148 149 150 151 152 153 154

	/* Write a STOP bit to TX FIFO */
	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));

	/* Wait until the STOP is seen. */
	while (timeout > 0 &&
	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
		/* may be called from interrupt context */
		udelay(1);
		timeout--;
	}

155
	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
156
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
157 158 159 160 161 162 163 164
}

/**
 * i2c_pnx_master_xmit - transmit data to slave
 * @adap:		pointer to I2C adapter structure
 *
 * Sends one byte of data to the slave
 */
165
static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
166 167 168
{
	u32 val;

169
	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
170
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
171 172 173 174 175

	if (alg_data->mif.len > 0) {
		/* We still have something to talk about... */
		val = *alg_data->mif.buf++;

176 177 178
		if (alg_data->mif.len == 1)
			val |= stop_bit;

V
Vitaly Wool 已提交
179 180 181
		alg_data->mif.len--;
		iowrite32(val, I2C_REG_TX(alg_data));

182 183
		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
			__func__, val, alg_data->mif.len + 1);
V
Vitaly Wool 已提交
184 185 186 187 188

		if (alg_data->mif.len == 0) {
			if (alg_data->last) {
				/* Wait until the STOP is seen. */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
189 190
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");
V
Vitaly Wool 已提交
191 192 193 194 195 196 197 198
			}
			/* Disable master interrupts */
			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
				  I2C_REG_CTL(alg_data));

			del_timer_sync(&alg_data->mif.timer);

199 200
			dev_dbg(&alg_data->adapter.dev,
				"%s(): Waking up xfer routine.\n",
201
				__func__);
V
Vitaly Wool 已提交
202 203 204 205 206

			complete(&alg_data->mif.complete);
		}
	} else if (alg_data->mif.len == 0) {
		/* zero-sized transfer */
207
		i2c_pnx_stop(alg_data);
V
Vitaly Wool 已提交
208 209 210 211 212 213 214 215

		/* Disable master interrupts. */
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
			  I2C_REG_CTL(alg_data));

		/* Stop timer. */
		del_timer_sync(&alg_data->mif.timer);
216 217 218
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Waking up xfer routine after zero-xfer.\n",
			__func__);
V
Vitaly Wool 已提交
219 220 221 222

		complete(&alg_data->mif.complete);
	}

223
	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
224
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
225 226 227 228 229 230 231 232 233 234

	return 0;
}

/**
 * i2c_pnx_master_rcv - receive data from slave
 * @adap:		pointer to I2C adapter structure
 *
 * Reads one byte data from the slave
 */
235
static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
236 237 238 239
{
	unsigned int val = 0;
	u32 ctl = 0;

240
	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
241
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
242 243 244 245 246

	/* Check, whether there is already data,
	 * or we didn't 'ask' for it yet.
	 */
	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
247 248 249
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Write dummy data to fill Rx-fifo...\n",
			__func__);
V
Vitaly Wool 已提交
250 251

		if (alg_data->mif.len == 1) {
252 253 254
			/* Last byte, do not acknowledge next rcv. */
			val |= stop_bit;

V
Vitaly Wool 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
			/*
			 * Enable interrupt RFDAIE (data in Rx fifo),
			 * and disable DRMIE (need data for Tx)
			 */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl |= mcntrl_rffie | mcntrl_daie;
			ctl &= ~mcntrl_drmie;
			iowrite32(ctl, I2C_REG_CTL(alg_data));
		}

		/*
		 * Now we'll 'ask' for data:
		 * For each byte we want to receive, we must
		 * write a (dummy) byte to the Tx-FIFO.
		 */
		iowrite32(val, I2C_REG_TX(alg_data));

		return 0;
	}

	/* Handle data. */
	if (alg_data->mif.len > 0) {
		val = ioread32(I2C_REG_RX(alg_data));
		*alg_data->mif.buf++ = (u8) (val & 0xff);
279 280
		dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
			__func__, val, alg_data->mif.len);
V
Vitaly Wool 已提交
281 282 283 284 285 286

		alg_data->mif.len--;
		if (alg_data->mif.len == 0) {
			if (alg_data->last)
				/* Wait until the STOP is seen. */
				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
287 288
					dev_err(&alg_data->adapter.dev,
						"The bus is still active after timeout\n");
V
Vitaly Wool 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301

			/* Disable master interrupts */
			ctl = ioread32(I2C_REG_CTL(alg_data));
			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
				 mcntrl_drmie | mcntrl_daie);
			iowrite32(ctl, I2C_REG_CTL(alg_data));

			/* Kill timer. */
			del_timer_sync(&alg_data->mif.timer);
			complete(&alg_data->mif.complete);
		}
	}

302
	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
303
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
304 305 306 307

	return 0;
}

308
static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
V
Vitaly Wool 已提交
309
{
310
	struct i2c_pnx_algo_data *alg_data = dev_id;
V
Vitaly Wool 已提交
311 312
	u32 stat, ctl;

313 314
	dev_dbg(&alg_data->adapter.dev,
		"%s(): mstat = %x mctrl = %x, mode = %d\n",
315
		__func__,
V
Vitaly Wool 已提交
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
		ioread32(I2C_REG_STS(alg_data)),
		ioread32(I2C_REG_CTL(alg_data)),
		alg_data->mif.mode);
	stat = ioread32(I2C_REG_STS(alg_data));

	/* let's see what kind of event this is */
	if (stat & mstatus_afi) {
		/* We lost arbitration in the midst of a transfer */
		alg_data->mif.ret = -EIO;

		/* Disable master interrupts. */
		ctl = ioread32(I2C_REG_CTL(alg_data));
		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
			 mcntrl_drmie);
		iowrite32(ctl, I2C_REG_CTL(alg_data));

		/* Stop timer, to prevent timeout. */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else if (stat & mstatus_nai) {
		/* Slave did not acknowledge, generate a STOP */
337 338
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Slave did not acknowledge, generating a STOP.\n",
339
			__func__);
340
		i2c_pnx_stop(alg_data);
V
Vitaly Wool 已提交
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365

		/* Disable master interrupts. */
		ctl = ioread32(I2C_REG_CTL(alg_data));
		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
			 mcntrl_drmie);
		iowrite32(ctl, I2C_REG_CTL(alg_data));

		/* Our return value. */
		alg_data->mif.ret = -EIO;

		/* Stop timer, to prevent timeout. */
		del_timer_sync(&alg_data->mif.timer);
		complete(&alg_data->mif.complete);
	} else {
		/*
		 * Two options:
		 * - Master Tx needs data.
		 * - There is data in the Rx-fifo
		 * The latter is only the case if we have requested for data,
		 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
		 * We therefore check, as a sanity check, whether that interrupt
		 * has been enabled.
		 */
		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
			if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
366
				i2c_pnx_master_xmit(alg_data);
V
Vitaly Wool 已提交
367
			} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
368
				i2c_pnx_master_rcv(alg_data);
V
Vitaly Wool 已提交
369 370 371 372 373 374 375 376
			}
		}
	}

	/* Clear TDI and AFI bits */
	stat = ioread32(I2C_REG_STS(alg_data));
	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));

377 378
	dev_dbg(&alg_data->adapter.dev,
		"%s(): exiting, stat = %x ctrl = %x.\n",
379
		 __func__, ioread32(I2C_REG_STS(alg_data)),
V
Vitaly Wool 已提交
380 381 382 383 384 385 386
		 ioread32(I2C_REG_CTL(alg_data)));

	return IRQ_HANDLED;
}

static void i2c_pnx_timeout(unsigned long data)
{
387
	struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
V
Vitaly Wool 已提交
388 389
	u32 ctl;

390 391 392 393
	dev_err(&alg_data->adapter.dev,
		"Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
		ioread32(I2C_REG_STS(alg_data)),
		ioread32(I2C_REG_CTL(alg_data)));
V
Vitaly Wool 已提交
394 395 396 397 398 399 400 401 402 403 404 405 406

	/* Reset master and disable interrupts */
	ctl = ioread32(I2C_REG_CTL(alg_data));
	ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
	iowrite32(ctl, I2C_REG_CTL(alg_data));

	ctl |= mcntrl_reset;
	iowrite32(ctl, I2C_REG_CTL(alg_data));
	wait_reset(I2C_PNX_TIMEOUT, alg_data);
	alg_data->mif.ret = -EIO;
	complete(&alg_data->mif.complete);
}

407
static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
V
Vitaly Wool 已提交
408 409 410 411
{
	u32 stat;

	if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
412
		dev_err(&alg_data->adapter.dev,
V
Vitaly Wool 已提交
413
			"%s: Bus is still active after xfer. Reset it...\n",
414
			alg_data->adapter.name);
V
Vitaly Wool 已提交
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
			  I2C_REG_CTL(alg_data));
		wait_reset(I2C_PNX_TIMEOUT, alg_data);
	} else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
		/* If there is data in the fifo's after transfer,
		 * flush fifo's by reset.
		 */
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
			  I2C_REG_CTL(alg_data));
		wait_reset(I2C_PNX_TIMEOUT, alg_data);
	} else if (stat & mstatus_nai) {
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
			  I2C_REG_CTL(alg_data));
		wait_reset(I2C_PNX_TIMEOUT, alg_data);
	}
}

/**
 * i2c_pnx_xfer - generic transfer entry point
 * @adap:		pointer to I2C adapter structure
 * @msgs:		array of messages
 * @num:		number of messages
 *
 * Initiates the transfer
 */
static int
i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
{
	struct i2c_msg *pmsg;
	int rc = 0, completed = 0, i;
	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
	u32 stat = ioread32(I2C_REG_STS(alg_data));

448 449
	dev_dbg(&alg_data->adapter.dev,
		"%s(): entering: %d messages, stat = %04x.\n",
450
		__func__, num, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
451

452
	bus_reset_if_active(alg_data);
V
Vitaly Wool 已提交
453 454 455 456 457 458 459 460 461

	/* Process transactions in a loop. */
	for (i = 0; rc >= 0 && i < num; i++) {
		u8 addr;

		pmsg = &msgs[i];
		addr = pmsg->addr;

		if (pmsg->flags & I2C_M_TEN) {
462
			dev_err(&alg_data->adapter.dev,
V
Vitaly Wool 已提交
463
				"%s: 10 bits addr not supported!\n",
464
				alg_data->adapter.name);
V
Vitaly Wool 已提交
465 466 467 468 469 470 471 472 473 474 475
			rc = -EINVAL;
			break;
		}

		alg_data->mif.buf = pmsg->buf;
		alg_data->mif.len = pmsg->len;
		alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
			I2C_SMBUS_READ : I2C_SMBUS_WRITE;
		alg_data->mif.ret = 0;
		alg_data->last = (i == num - 1);

476 477
		dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
			__func__, alg_data->mif.mode, alg_data->mif.len);
V
Vitaly Wool 已提交
478

479
		i2c_pnx_arm_timer(alg_data);
V
Vitaly Wool 已提交
480 481 482 483 484 485 486 487 488 489

		/* initialize the completion var */
		init_completion(&alg_data->mif.complete);

		/* Enable master interrupt */
		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
				mcntrl_naie | mcntrl_drmie,
			  I2C_REG_CTL(alg_data));

		/* Put start-code and slave-address on the bus. */
490
		rc = i2c_pnx_start(addr, alg_data);
V
Vitaly Wool 已提交
491 492 493 494 495 496 497 498
		if (rc < 0)
			break;

		/* Wait for completion */
		wait_for_completion(&alg_data->mif.complete);

		if (!(rc = alg_data->mif.ret))
			completed++;
499 500
		dev_dbg(&alg_data->adapter.dev,
			"%s(): Complete, return code = %d.\n",
501
			__func__, rc);
V
Vitaly Wool 已提交
502 503 504

		/* Clear TDI and AFI bits in case they are set. */
		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
505
			dev_dbg(&alg_data->adapter.dev,
V
Vitaly Wool 已提交
506
				"%s: TDI still set... clearing now.\n",
507
				alg_data->adapter.name);
V
Vitaly Wool 已提交
508 509 510
			iowrite32(stat, I2C_REG_STS(alg_data));
		}
		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
511
			dev_dbg(&alg_data->adapter.dev,
V
Vitaly Wool 已提交
512
				"%s: AFI still set... clearing now.\n",
513
				alg_data->adapter.name);
V
Vitaly Wool 已提交
514 515 516 517
			iowrite32(stat, I2C_REG_STS(alg_data));
		}
	}

518
	bus_reset_if_active(alg_data);
V
Vitaly Wool 已提交
519 520 521 522 523

	/* Cleanup to be sure... */
	alg_data->mif.buf = NULL;
	alg_data->mif.len = 0;

524
	dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
525
		__func__, ioread32(I2C_REG_STS(alg_data)));
V
Vitaly Wool 已提交
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542

	if (completed != num)
		return ((rc < 0) ? rc : -EREMOTEIO);

	return num;
}

static u32 i2c_pnx_func(struct i2c_adapter *adapter)
{
	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
}

static struct i2c_algorithm pnx_algorithm = {
	.master_xfer = i2c_pnx_xfer,
	.functionality = i2c_pnx_func,
};

543
#ifdef CONFIG_PM
V
Vitaly Wool 已提交
544 545 546
static int i2c_pnx_controller_suspend(struct platform_device *pdev,
				      pm_message_t state)
{
547
	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
548

549 550
	/* FIXME: shouldn't this be clk_disable? */
	clk_enable(alg_data->clk);
551 552

	return 0;
V
Vitaly Wool 已提交
553 554 555 556
}

static int i2c_pnx_controller_resume(struct platform_device *pdev)
{
557
	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
558

559
	return clk_enable(alg_data->clk);
V
Vitaly Wool 已提交
560
}
561 562 563 564
#else
#define i2c_pnx_controller_suspend	NULL
#define i2c_pnx_controller_resume	NULL
#endif
V
Vitaly Wool 已提交
565 566 567 568 569 570

static int __devinit i2c_pnx_probe(struct platform_device *pdev)
{
	unsigned long tmp;
	int ret = 0;
	struct i2c_pnx_algo_data *alg_data;
571
	unsigned long freq;
V
Vitaly Wool 已提交
572 573
	struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;

574
	if (!i2c_pnx || !i2c_pnx->name) {
V
Vitaly Wool 已提交
575
		dev_err(&pdev->dev, "%s: no platform data supplied\n",
576
		       __func__);
V
Vitaly Wool 已提交
577 578 579 580
		ret = -EINVAL;
		goto out;
	}

581 582 583 584 585 586
	alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
	if (!alg_data) {
		ret = -ENOMEM;
		goto err_kzalloc;
	}

587
	platform_set_drvdata(pdev, alg_data);
V
Vitaly Wool 已提交
588

589 590 591 592 593 594 595
	strlcpy(alg_data->adapter.name, i2c_pnx->name,
		sizeof(alg_data->adapter.name));
	alg_data->adapter.dev.parent = &pdev->dev;
	alg_data->adapter.algo = &pnx_algorithm;
	alg_data->adapter.algo_data = alg_data;
	alg_data->adapter.nr = pdev->id;
	alg_data->i2c_pnx = i2c_pnx;
596 597 598 599 600 601 602

	alg_data->clk = clk_get(&pdev->dev, NULL);
	if (IS_ERR(alg_data->clk)) {
		ret = PTR_ERR(alg_data->clk);
		goto out_drvdata;
	}

V
Vitaly Wool 已提交
603 604
	init_timer(&alg_data->mif.timer);
	alg_data->mif.timer.function = i2c_pnx_timeout;
605
	alg_data->mif.timer.data = (unsigned long)alg_data;
V
Vitaly Wool 已提交
606 607

	/* Register I/O resource */
608
	if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
609
				pdev->name)) {
V
Vitaly Wool 已提交
610 611
		dev_err(&pdev->dev,
		       "I/O region 0x%08x for I2C already in use.\n",
612
		       i2c_pnx->base);
V
Vitaly Wool 已提交
613
		ret = -ENODEV;
614
		goto out_clkget;
V
Vitaly Wool 已提交
615 616
	}

617
	alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
618
	if (!alg_data->ioaddr) {
V
Vitaly Wool 已提交
619 620 621 622 623
		dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
		ret = -ENOMEM;
		goto out_release;
	}

624 625 626
	ret = clk_enable(alg_data->clk);
	if (ret)
		goto out_unmap;
V
Vitaly Wool 已提交
627

628 629
	freq = clk_get_rate(alg_data->clk);

V
Vitaly Wool 已提交
630 631 632 633 634 635 636 637 638 639 640
	/*
	 * Clock Divisor High This value is the number of system clocks
	 * the serial clock (SCL) will be high.
	 * For example, if the system clock period is 50 ns and the maximum
	 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
	 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
	 * programmed into CLKHI will vary from this slightly due to
	 * variations in the output pad's rise and fall times as well as
	 * the deglitching filter length.
	 */

641
	tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
642 643
	if (tmp > 0x3FF)
		tmp = 0x3FF;
V
Vitaly Wool 已提交
644 645 646 647 648 649
	iowrite32(tmp, I2C_REG_CKH(alg_data));
	iowrite32(tmp, I2C_REG_CKL(alg_data));

	iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
	if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
		ret = -ENODEV;
650
		goto out_clock;
V
Vitaly Wool 已提交
651 652 653
	}
	init_completion(&alg_data->mif.complete);

654
	ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
655
			0, pdev->name, alg_data);
V
Vitaly Wool 已提交
656 657 658 659
	if (ret)
		goto out_clock;

	/* Register this adapter with the I2C subsystem */
660
	ret = i2c_add_numbered_adapter(&alg_data->adapter);
V
Vitaly Wool 已提交
661 662 663 664 665 666
	if (ret < 0) {
		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
		goto out_irq;
	}

	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
667
	       alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
V
Vitaly Wool 已提交
668 669 670 671

	return 0;

out_irq:
672
	free_irq(i2c_pnx->irq, alg_data);
V
Vitaly Wool 已提交
673
out_clock:
674
	clk_disable(alg_data->clk);
V
Vitaly Wool 已提交
675
out_unmap:
676
	iounmap(alg_data->ioaddr);
V
Vitaly Wool 已提交
677
out_release:
678
	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
679 680
out_clkget:
	clk_put(alg_data->clk);
V
Vitaly Wool 已提交
681
out_drvdata:
682 683
	kfree(alg_data);
err_kzalloc:
V
Vitaly Wool 已提交
684 685 686 687 688 689 690
	platform_set_drvdata(pdev, NULL);
out:
	return ret;
}

static int __devexit i2c_pnx_remove(struct platform_device *pdev)
{
691 692
	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
	struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
V
Vitaly Wool 已提交
693

694
	free_irq(i2c_pnx->irq, alg_data);
695
	i2c_del_adapter(&alg_data->adapter);
696
	clk_disable(alg_data->clk);
697
	iounmap(alg_data->ioaddr);
698
	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
699
	clk_put(alg_data->clk);
700
	kfree(alg_data);
V
Vitaly Wool 已提交
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
	platform_set_drvdata(pdev, NULL);

	return 0;
}

static struct platform_driver i2c_pnx_driver = {
	.driver = {
		.name = "pnx-i2c",
		.owner = THIS_MODULE,
	},
	.probe = i2c_pnx_probe,
	.remove = __devexit_p(i2c_pnx_remove),
	.suspend = i2c_pnx_controller_suspend,
	.resume = i2c_pnx_controller_resume,
};

static int __init i2c_adap_pnx_init(void)
{
	return platform_driver_register(&i2c_pnx_driver);
}

static void __exit i2c_adap_pnx_exit(void)
{
	platform_driver_unregister(&i2c_pnx_driver);
}

MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
MODULE_LICENSE("GPL");
730
MODULE_ALIAS("platform:pnx-i2c");
V
Vitaly Wool 已提交
731 732 733 734

/* We need to make sure I2C is initialized before USB */
subsys_initcall(i2c_adap_pnx_init);
module_exit(i2c_adap_pnx_exit);