141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/*
241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Provides I2C support for Philips PNX010x/PNX4008 boards.
341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Authors: Dennis Kovalev <dkovalev@ru.mvista.com>
541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *	    Vitaly Wool <vwool@ru.mvista.com>
641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under
841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * the terms of the GNU General Public License version 2. This program
941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * is licensed "as is" without any warranty of any kind, whether express
1041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * or implied.
1141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
1241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
1341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/module.h>
1441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/interrupt.h>
1541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/ioport.h>
1641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/delay.h>
1741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/i2c.h>
1841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/timer.h>
1941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/completion.h>
2041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/platform_device.h>
2141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#include <linux/i2c-pnx.h>
22a7d73d8c686d919cc18dec63e5e194f0e5a7206eKevin Wells#include <linux/io.h>
230321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King#include <linux/err.h>
240321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King#include <linux/clk.h>
255a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
260321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
27a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h>
28a7d73d8c686d919cc18dec63e5e194f0e5a7206eKevin Wells#include <mach/i2c.h>
2941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#define I2C_PNX_TIMEOUT		10 /* msec */
3141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#define I2C_PNX_SPEED_KHZ	100
3241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool#define I2C_PNX_REGION_SIZE	0x100
3341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data)
3541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
3641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	while (timeout > 0 &&
3741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
3841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		mdelay(1);
3941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		timeout--;
4041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
4141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return (timeout <= 0);
4241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
4341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
4441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data)
4541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
4641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	while (timeout > 0 &&
4741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
4841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		mdelay(1);
4941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		timeout--;
5041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
5141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return (timeout <= 0);
5241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
5341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
5481d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data)
5541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
5681d6724a564fa5bd20b006eae0da4462d599bb92Russell King	struct timer_list *timer = &alg_data->mif.timer;
57eed18b5fa4d297c681b00144e8c6942dd35d39a7Russell King	unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT);
5841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
59b2f125bcf5eac41a6d74f75ac573b77753213b74Kevin Wells	if (expires <= 1)
60b2f125bcf5eac41a6d74f75ac573b77753213b74Kevin Wells		expires = 2;
61b2f125bcf5eac41a6d74f75ac573b77753213b74Kevin Wells
6241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	del_timer_sync(timer);
6341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
64eed18b5fa4d297c681b00144e8c6942dd35d39a7Russell King	dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n",
6541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		jiffies, expires);
6641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
6741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	timer->expires = jiffies + expires;
689ddabb055d73c63037878bb9346e52c7f2e07e96Wolfram Sang	timer->data = (unsigned long)alg_data;
6941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
7041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	add_timer(timer);
7141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
7241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
7341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/**
7441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * i2c_pnx_start - start a device
7541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @slave_addr:		slave address
7641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @adap:		pointer to adapter structure
7741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
7841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Generate a START signal in the desired mode.
7941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
8081d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic int i2c_pnx_start(unsigned char slave_addr,
8181d6724a564fa5bd20b006eae0da4462d599bb92Russell King	struct i2c_pnx_algo_data *alg_data)
8241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
8381d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__,
8441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		slave_addr, alg_data->mif.mode);
8541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
8641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Check for 7 bit slave addresses only */
8741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (slave_addr & ~0x7f) {
884be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_err(&alg_data->adapter.dev,
894be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s: Invalid slave address %x. Only 7-bit addresses are supported\n",
904be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			alg_data->adapter.name, slave_addr);
9141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		return -EINVAL;
9241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
9341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
9441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* First, make sure bus is idle */
9541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) {
9641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Somebody else is monopolizing the bus */
974be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_err(&alg_data->adapter.dev,
984be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n",
994be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			alg_data->adapter.name, slave_addr,
1004be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			ioread32(I2C_REG_CTL(alg_data)),
1014be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			ioread32(I2C_REG_STS(alg_data)));
10241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		return -EBUSY;
10341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) {
10441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Sorry, we lost the bus */
1054be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_err(&alg_data->adapter.dev,
1064be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		        "%s: Arbitration failure. Slave addr = %02x\n",
1074be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			alg_data->adapter.name, slave_addr);
10841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		return -EIO;
10941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
11041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
11141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/*
11241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * OK, I2C is enabled and we have the bus.
11341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * Clear the current TDI and AFI status flags.
11441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 */
11541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi,
11641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		  I2C_REG_STS(alg_data));
11741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
11881d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__,
11941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		(slave_addr << 1) | start_bit | alg_data->mif.mode);
12041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
12141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Write the slave address, START bit and R/W bit */
12241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode,
12341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		  I2C_REG_TX(alg_data));
12441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
12581d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__);
12641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
12741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return 0;
12841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
12941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
13041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/**
13141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * i2c_pnx_stop - stop a device
13241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @adap:		pointer to I2C adapter structure
13341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
13441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Generate a STOP signal to terminate the master transaction.
13541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
13681d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data)
13741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
13841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Only 1 msec max timeout due to interrupt context */
13941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	long timeout = 1000;
14041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
14181d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
14208882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
14341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
14441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Write a STOP bit to TX FIFO */
14541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data));
14641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
14741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Wait until the STOP is seen. */
14841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	while (timeout > 0 &&
14941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	       (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) {
15041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* may be called from interrupt context */
15141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		udelay(1);
15241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		timeout--;
15341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
15441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
15581d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
15608882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
15741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
15841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
15941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/**
16041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * i2c_pnx_master_xmit - transmit data to slave
16141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @adap:		pointer to I2C adapter structure
16241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
16341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Sends one byte of data to the slave
16441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
16581d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data)
16641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
16741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 val;
16841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
16981d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
17008882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
17141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
17241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (alg_data->mif.len > 0) {
17341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* We still have something to talk about... */
17441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		val = *alg_data->mif.buf++;
17541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
17628ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells		if (alg_data->mif.len == 1)
17728ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells			val |= stop_bit;
17828ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells
17941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.len--;
18041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(val, I2C_REG_TX(alg_data));
18141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
1824be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n",
1834be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			__func__, val, alg_data->mif.len + 1);
18441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
18541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (alg_data->mif.len == 0) {
18641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			if (alg_data->last) {
18741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				/* Wait until the STOP is seen. */
18841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
1894be53dbe74818a12cc737a89b5d0aec6095956e0Russell King					dev_err(&alg_data->adapter.dev,
1904be53dbe74818a12cc737a89b5d0aec6095956e0Russell King						"The bus is still active after timeout\n");
19141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			}
19241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			/* Disable master interrupts */
19341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
19441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
19541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				  I2C_REG_CTL(alg_data));
19641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
19741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			del_timer_sync(&alg_data->mif.timer);
19841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
1994be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			dev_dbg(&alg_data->adapter.dev,
2004be53dbe74818a12cc737a89b5d0aec6095956e0Russell King				"%s(): Waking up xfer routine.\n",
20108882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison				__func__);
20241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
20341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			complete(&alg_data->mif.complete);
20441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
20541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else if (alg_data->mif.len == 0) {
20641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* zero-sized transfer */
20781d6724a564fa5bd20b006eae0da4462d599bb92Russell King		i2c_pnx_stop(alg_data);
20841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
20941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Disable master interrupts. */
21041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ioread32(I2C_REG_CTL(alg_data)) &
21141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			~(mcntrl_afie | mcntrl_naie | mcntrl_drmie),
21241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			  I2C_REG_CTL(alg_data));
21341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
21441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Stop timer. */
21541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		del_timer_sync(&alg_data->mif.timer);
2164be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev,
2174be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s(): Waking up xfer routine after zero-xfer.\n",
2184be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			__func__);
21941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
22041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		complete(&alg_data->mif.complete);
22141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
22241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
22381d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
22408882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
22541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
22641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return 0;
22741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
22841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
22941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/**
23041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * i2c_pnx_master_rcv - receive data from slave
23141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @adap:		pointer to I2C adapter structure
23241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
23341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Reads one byte data from the slave
23441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
23581d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
23641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
23741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	unsigned int val = 0;
23841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 ctl = 0;
23941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
24081d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n",
24108882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
24241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
24341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Check, whether there is already data,
24441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * or we didn't 'ask' for it yet.
24541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 */
24641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
2474be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev,
2484be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s(): Write dummy data to fill Rx-fifo...\n",
2494be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			__func__);
25041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
25141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (alg_data->mif.len == 1) {
25228ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells			/* Last byte, do not acknowledge next rcv. */
25328ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells			val |= stop_bit;
25428ad3321a1ac732c7fe37d5be85f67fe40ef18a9Kevin Wells
25541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			/*
25641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			 * Enable interrupt RFDAIE (data in Rx fifo),
25741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			 * and disable DRMIE (need data for Tx)
25841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			 */
25941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			ctl = ioread32(I2C_REG_CTL(alg_data));
26041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			ctl |= mcntrl_rffie | mcntrl_daie;
26141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			ctl &= ~mcntrl_drmie;
26241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			iowrite32(ctl, I2C_REG_CTL(alg_data));
26341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
26441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
26541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/*
26641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * Now we'll 'ask' for data:
26741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * For each byte we want to receive, we must
26841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * write a (dummy) byte to the Tx-FIFO.
26941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 */
27041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(val, I2C_REG_TX(alg_data));
27141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
27241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		return 0;
27341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
27441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
27541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Handle data. */
27641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (alg_data->mif.len > 0) {
27741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		val = ioread32(I2C_REG_RX(alg_data));
27841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		*alg_data->mif.buf++ = (u8) (val & 0xff);
2794be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n",
2804be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			__func__, val, alg_data->mif.len);
28141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
28241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.len--;
28341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (alg_data->mif.len == 0) {
28441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			if (alg_data->last)
28541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				/* Wait until the STOP is seen. */
28641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				if (wait_timeout(I2C_PNX_TIMEOUT, alg_data))
2874be53dbe74818a12cc737a89b5d0aec6095956e0Russell King					dev_err(&alg_data->adapter.dev,
2884be53dbe74818a12cc737a89b5d0aec6095956e0Russell King						"The bus is still active after timeout\n");
28941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
29041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			/* Disable master interrupts */
29141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			ctl = ioread32(I2C_REG_CTL(alg_data));
29241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
29341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				 mcntrl_drmie | mcntrl_daie);
29441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			iowrite32(ctl, I2C_REG_CTL(alg_data));
29541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
29641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			/* Kill timer. */
29741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			del_timer_sync(&alg_data->mif.timer);
29841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			complete(&alg_data->mif.complete);
29941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
30041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
30141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
30281d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n",
30308882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
30441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
30541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return 0;
30641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
30741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3086c566fb7b3cda741dd6ed60c7d6aae0e17c9c8feVitaly Woolstatic irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id)
30941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
31081d6724a564fa5bd20b006eae0da4462d599bb92Russell King	struct i2c_pnx_algo_data *alg_data = dev_id;
31141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 stat, ctl;
31241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3134be53dbe74818a12cc737a89b5d0aec6095956e0Russell King	dev_dbg(&alg_data->adapter.dev,
3144be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		"%s(): mstat = %x mctrl = %x, mode = %d\n",
31508882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__,
31641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ioread32(I2C_REG_STS(alg_data)),
31741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ioread32(I2C_REG_CTL(alg_data)),
31841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.mode);
31941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	stat = ioread32(I2C_REG_STS(alg_data));
32041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
32141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* let's see what kind of event this is */
32241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (stat & mstatus_afi) {
32341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* We lost arbitration in the midst of a transfer */
32441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.ret = -EIO;
32541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
32641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Disable master interrupts. */
32741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ctl = ioread32(I2C_REG_CTL(alg_data));
32841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
32941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			 mcntrl_drmie);
33041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ctl, I2C_REG_CTL(alg_data));
33141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
33241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Stop timer, to prevent timeout. */
33341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		del_timer_sync(&alg_data->mif.timer);
33441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		complete(&alg_data->mif.complete);
33541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else if (stat & mstatus_nai) {
33641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Slave did not acknowledge, generate a STOP */
3374be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev,
3384be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s(): Slave did not acknowledge, generating a STOP.\n",
33908882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison			__func__);
34081d6724a564fa5bd20b006eae0da4462d599bb92Russell King		i2c_pnx_stop(alg_data);
34141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
34241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Disable master interrupts. */
34341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ctl = ioread32(I2C_REG_CTL(alg_data));
34441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie |
34541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			 mcntrl_drmie);
34641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ctl, I2C_REG_CTL(alg_data));
34741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
34841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Our return value. */
34941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.ret = -EIO;
35041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
35141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Stop timer, to prevent timeout. */
35241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		del_timer_sync(&alg_data->mif.timer);
35341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		complete(&alg_data->mif.complete);
35441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else {
35541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/*
35641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * Two options:
35741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * - Master Tx needs data.
35841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * - There is data in the Rx-fifo
35941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * The latter is only the case if we have requested for data,
36041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * via a dummy write. (See 'i2c_pnx_master_rcv'.)
36141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * We therefore check, as a sanity check, whether that interrupt
36241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * has been enabled.
36341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 */
36441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) {
36541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			if (alg_data->mif.mode == I2C_SMBUS_WRITE) {
36681d6724a564fa5bd20b006eae0da4462d599bb92Russell King				i2c_pnx_master_xmit(alg_data);
36741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			} else if (alg_data->mif.mode == I2C_SMBUS_READ) {
36881d6724a564fa5bd20b006eae0da4462d599bb92Russell King				i2c_pnx_master_rcv(alg_data);
36941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			}
37041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
37141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
37241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
37341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Clear TDI and AFI bits */
37441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	stat = ioread32(I2C_REG_STS(alg_data));
37541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data));
37641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3774be53dbe74818a12cc737a89b5d0aec6095956e0Russell King	dev_dbg(&alg_data->adapter.dev,
3784be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		"%s(): exiting, stat = %x ctrl = %x.\n",
37908882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		 __func__, ioread32(I2C_REG_STS(alg_data)),
38041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 ioread32(I2C_REG_CTL(alg_data)));
38141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
38241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return IRQ_HANDLED;
38341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
38441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
38541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic void i2c_pnx_timeout(unsigned long data)
38641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
38781d6724a564fa5bd20b006eae0da4462d599bb92Russell King	struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data;
38841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 ctl;
38941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
3904be53dbe74818a12cc737a89b5d0aec6095956e0Russell King	dev_err(&alg_data->adapter.dev,
3914be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		"Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n",
3924be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		ioread32(I2C_REG_STS(alg_data)),
3934be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		ioread32(I2C_REG_CTL(alg_data)));
39441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
39541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Reset master and disable interrupts */
39641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	ctl = ioread32(I2C_REG_CTL(alg_data));
39741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie);
39841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(ctl, I2C_REG_CTL(alg_data));
39941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
40041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	ctl |= mcntrl_reset;
40141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(ctl, I2C_REG_CTL(alg_data));
40241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	wait_reset(I2C_PNX_TIMEOUT, alg_data);
40341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	alg_data->mif.ret = -EIO;
40441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	complete(&alg_data->mif.complete);
40541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
40641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
40781d6724a564fa5bd20b006eae0da4462d599bb92Russell Kingstatic inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data)
40841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
40941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 stat;
41041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
41141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) {
41281d6724a564fa5bd20b006eae0da4462d599bb92Russell King		dev_err(&alg_data->adapter.dev,
41341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			"%s: Bus is still active after xfer. Reset it...\n",
4144be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			alg_data->adapter.name);
41541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
41641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			  I2C_REG_CTL(alg_data));
41741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		wait_reset(I2C_PNX_TIMEOUT, alg_data);
41841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) {
41941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* If there is data in the fifo's after transfer,
42041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 * flush fifo's by reset.
42141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		 */
42241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
42341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			  I2C_REG_CTL(alg_data));
42441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		wait_reset(I2C_PNX_TIMEOUT, alg_data);
42541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	} else if (stat & mstatus_nai) {
42641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset,
42741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			  I2C_REG_CTL(alg_data));
42841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		wait_reset(I2C_PNX_TIMEOUT, alg_data);
42941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
43041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
43141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
43241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/**
43341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * i2c_pnx_xfer - generic transfer entry point
43441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @adap:		pointer to I2C adapter structure
43541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @msgs:		array of messages
43641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * @num:		number of messages
43741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool *
43841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool * Initiates the transfer
43941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool */
44041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int
44141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wooli2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
44241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
44341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	struct i2c_msg *pmsg;
44441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	int rc = 0, completed = 0, i;
44541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	struct i2c_pnx_algo_data *alg_data = adap->algo_data;
44641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	u32 stat = ioread32(I2C_REG_STS(alg_data));
44741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
4484be53dbe74818a12cc737a89b5d0aec6095956e0Russell King	dev_dbg(&alg_data->adapter.dev,
4494be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		"%s(): entering: %d messages, stat = %04x.\n",
45008882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, num, ioread32(I2C_REG_STS(alg_data)));
45141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
45281d6724a564fa5bd20b006eae0da4462d599bb92Russell King	bus_reset_if_active(alg_data);
45341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
45441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Process transactions in a loop. */
45541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	for (i = 0; rc >= 0 && i < num; i++) {
45641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		u8 addr;
45741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
45841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		pmsg = &msgs[i];
45941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		addr = pmsg->addr;
46041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
46141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (pmsg->flags & I2C_M_TEN) {
46281d6724a564fa5bd20b006eae0da4462d599bb92Russell King			dev_err(&alg_data->adapter.dev,
46341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				"%s: 10 bits addr not supported!\n",
46481d6724a564fa5bd20b006eae0da4462d599bb92Russell King				alg_data->adapter.name);
46541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			rc = -EINVAL;
46641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			break;
46741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
46841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
46941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.buf = pmsg->buf;
47041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.len = pmsg->len;
47141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
47241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			I2C_SMBUS_READ : I2C_SMBUS_WRITE;
47341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->mif.ret = 0;
47441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		alg_data->last = (i == num - 1);
47541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
4764be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n",
4774be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			__func__, alg_data->mif.mode, alg_data->mif.len);
47841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
47981d6724a564fa5bd20b006eae0da4462d599bb92Russell King		i2c_pnx_arm_timer(alg_data);
48041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
48141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* initialize the completion var */
48241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		init_completion(&alg_data->mif.complete);
48341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
48441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Enable master interrupt */
48541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie |
48641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				mcntrl_naie | mcntrl_drmie,
48741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			  I2C_REG_CTL(alg_data));
48841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
48941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Put start-code and slave-address on the bus. */
49081d6724a564fa5bd20b006eae0da4462d599bb92Russell King		rc = i2c_pnx_start(addr, alg_data);
49141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (rc < 0)
49241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			break;
49341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
49441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Wait for completion */
49541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		wait_for_completion(&alg_data->mif.complete);
49641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
49741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if (!(rc = alg_data->mif.ret))
49841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			completed++;
4994be53dbe74818a12cc737a89b5d0aec6095956e0Russell King		dev_dbg(&alg_data->adapter.dev,
5004be53dbe74818a12cc737a89b5d0aec6095956e0Russell King			"%s(): Complete, return code = %d.\n",
50108882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison			__func__, rc);
50241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
50341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		/* Clear TDI and AFI bits in case they are set. */
50441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) {
50581d6724a564fa5bd20b006eae0da4462d599bb92Russell King			dev_dbg(&alg_data->adapter.dev,
50641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				"%s: TDI still set... clearing now.\n",
50781d6724a564fa5bd20b006eae0da4462d599bb92Russell King				alg_data->adapter.name);
50841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			iowrite32(stat, I2C_REG_STS(alg_data));
50941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
51041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) {
51181d6724a564fa5bd20b006eae0da4462d599bb92Russell King			dev_dbg(&alg_data->adapter.dev,
51241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				"%s: AFI still set... clearing now.\n",
51381d6724a564fa5bd20b006eae0da4462d599bb92Russell King				alg_data->adapter.name);
51441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool			iowrite32(stat, I2C_REG_STS(alg_data));
51541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		}
51641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
51741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
51881d6724a564fa5bd20b006eae0da4462d599bb92Russell King	bus_reset_if_active(alg_data);
51941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
52041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Cleanup to be sure... */
52141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	alg_data->mif.buf = NULL;
52241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	alg_data->mif.len = 0;
52341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
52481d6724a564fa5bd20b006eae0da4462d599bb92Russell King	dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
52508882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		__func__, ioread32(I2C_REG_STS(alg_data)));
52641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
52741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (completed != num)
52841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		return ((rc < 0) ? rc : -EREMOTEIO);
52941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
53041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return num;
53141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
53241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
53341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic u32 i2c_pnx_func(struct i2c_adapter *adapter)
53441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
53541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
53641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
53741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
53841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic struct i2c_algorithm pnx_algorithm = {
53941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.master_xfer = i2c_pnx_xfer,
54041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.functionality = i2c_pnx_func,
54141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool};
54241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
543a0dcf19f59d4f37150a6b7e115925d72aca15293Russell King#ifdef CONFIG_PM
54441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int i2c_pnx_controller_suspend(struct platform_device *pdev,
54541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool				      pm_message_t state)
54641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
5479d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
5480321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
5496c557cfee08751d22aed34840f389b846f0f4508Roland Stigge	clk_disable(alg_data->clk);
5500321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
5510321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	return 0;
55241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
55341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
55441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int i2c_pnx_controller_resume(struct platform_device *pdev)
55541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
5569d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
5570321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
558ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King	return clk_enable(alg_data->clk);
55941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
560a0dcf19f59d4f37150a6b7e115925d72aca15293Russell King#else
561a0dcf19f59d4f37150a6b7e115925d72aca15293Russell King#define i2c_pnx_controller_suspend	NULL
562a0dcf19f59d4f37150a6b7e115925d72aca15293Russell King#define i2c_pnx_controller_resume	NULL
563a0dcf19f59d4f37150a6b7e115925d72aca15293Russell King#endif
56441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
56541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int __devinit i2c_pnx_probe(struct platform_device *pdev)
56641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
56741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	unsigned long tmp;
56841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	int ret = 0;
56941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	struct i2c_pnx_algo_data *alg_data;
5706fff3da998ac3cc9ed8a84bf4f19911bd63c8c32Russell King	unsigned long freq;
57141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data;
57241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
5739d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	if (!i2c_pnx || !i2c_pnx->name) {
57441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		dev_err(&pdev->dev, "%s: no platform data supplied\n",
57508882d20932224d5c4500a855a2f4b1216e5f836Harvey Harrison		       __func__);
57641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ret = -EINVAL;
57741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		goto out;
57841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
57941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
58044c5d739181886cff8e3903dfa38cd704f3d9640Russell King	alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL);
58144c5d739181886cff8e3903dfa38cd704f3d9640Russell King	if (!alg_data) {
58244c5d739181886cff8e3903dfa38cd704f3d9640Russell King		ret = -ENOMEM;
58344c5d739181886cff8e3903dfa38cd704f3d9640Russell King		goto err_kzalloc;
58444c5d739181886cff8e3903dfa38cd704f3d9640Russell King	}
58544c5d739181886cff8e3903dfa38cd704f3d9640Russell King
5869d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	platform_set_drvdata(pdev, alg_data);
58741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
5889d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	strlcpy(alg_data->adapter.name, i2c_pnx->name,
5899d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King		sizeof(alg_data->adapter.name));
5909d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	alg_data->adapter.dev.parent = &pdev->dev;
5919d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	alg_data->adapter.algo = &pnx_algorithm;
5929d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	alg_data->adapter.algo_data = alg_data;
5939d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	alg_data->adapter.nr = pdev->id;
5949d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	alg_data->i2c_pnx = i2c_pnx;
5950321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
5960321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	alg_data->clk = clk_get(&pdev->dev, NULL);
5970321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	if (IS_ERR(alg_data->clk)) {
5980321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King		ret = PTR_ERR(alg_data->clk);
5990321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King		goto out_drvdata;
6000321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	}
6010321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King
60241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	init_timer(&alg_data->mif.timer);
60341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	alg_data->mif.timer.function = i2c_pnx_timeout;
60481d6724a564fa5bd20b006eae0da4462d599bb92Russell King	alg_data->mif.timer.data = (unsigned long)alg_data;
60541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
60641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Register I/O resource */
60744c5d739181886cff8e3903dfa38cd704f3d9640Russell King	if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE,
608449d2c759ddba46a89b698bdc64bfc2f7cc5bb66Julia Lawall				pdev->name)) {
60941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		dev_err(&pdev->dev,
61041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		       "I/O region 0x%08x for I2C already in use.\n",
61144c5d739181886cff8e3903dfa38cd704f3d9640Russell King		       i2c_pnx->base);
61241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ret = -ENODEV;
6130321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King		goto out_clkget;
61441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
61541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
61644c5d739181886cff8e3903dfa38cd704f3d9640Russell King	alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE);
61788d968b22fa26d5e3a8cab46fc7c3a21c89a91d3Russell King	if (!alg_data->ioaddr) {
61841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n");
61941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ret = -ENOMEM;
62041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		goto out_release;
62141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
62241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
623ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King	ret = clk_enable(alg_data->clk);
624ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King	if (ret)
625ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King		goto out_unmap;
62641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
6276fff3da998ac3cc9ed8a84bf4f19911bd63c8c32Russell King	freq = clk_get_rate(alg_data->clk);
6286fff3da998ac3cc9ed8a84bf4f19911bd63c8c32Russell King
62941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/*
63041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * Clock Divisor High This value is the number of system clocks
63141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * the serial clock (SCL) will be high.
63241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * For example, if the system clock period is 50 ns and the maximum
63341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * desired serial period is 10000 ns (100 kHz), then CLKHI would be
63441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value
63541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * programmed into CLKHI will vary from this slightly due to
63641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * variations in the output pad's rise and fall times as well as
63741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 * the deglitching filter length.
63841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	 */
63941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
6406fff3da998ac3cc9ed8a84bf4f19911bd63c8c32Russell King	tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2;
641be80dbaa3ed64337693be58fb2f3808e78911ba6Kevin Wells	if (tmp > 0x3FF)
642be80dbaa3ed64337693be58fb2f3808e78911ba6Kevin Wells		tmp = 0x3FF;
64341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(tmp, I2C_REG_CKH(alg_data));
64441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(tmp, I2C_REG_CKL(alg_data));
64541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
64641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data));
64741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) {
64841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		ret = -ENODEV;
649ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King		goto out_clock;
65041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
65141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	init_completion(&alg_data->mif.complete);
65241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
65344c5d739181886cff8e3903dfa38cd704f3d9640Russell King	ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt,
65481d6724a564fa5bd20b006eae0da4462d599bb92Russell King			0, pdev->name, alg_data);
65541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (ret)
65641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		goto out_clock;
65741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
65841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	/* Register this adapter with the I2C subsystem */
6599d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	ret = i2c_add_numbered_adapter(&alg_data->adapter);
66041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	if (ret < 0) {
66141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		dev_err(&pdev->dev, "I2C: Failed to add bus\n");
66241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		goto out_irq;
66341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	}
66441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
66541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n",
6669d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	       alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq);
66741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
66841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return 0;
66941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
67041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout_irq:
67181d6724a564fa5bd20b006eae0da4462d599bb92Russell King	free_irq(i2c_pnx->irq, alg_data);
67241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout_clock:
673ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King	clk_disable(alg_data->clk);
67441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout_unmap:
67588d968b22fa26d5e3a8cab46fc7c3a21c89a91d3Russell King	iounmap(alg_data->ioaddr);
67641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout_release:
67744c5d739181886cff8e3903dfa38cd704f3d9640Russell King	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
6780321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell Kingout_clkget:
6790321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	clk_put(alg_data->clk);
68041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout_drvdata:
68144c5d739181886cff8e3903dfa38cd704f3d9640Russell King	kfree(alg_data);
68244c5d739181886cff8e3903dfa38cd704f3d9640Russell Kingerr_kzalloc:
68341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	platform_set_drvdata(pdev, NULL);
68441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolout:
68541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return ret;
68641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
68741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
68841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int __devexit i2c_pnx_remove(struct platform_device *pdev)
68941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
6909d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev);
6919d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx;
69241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
69381d6724a564fa5bd20b006eae0da4462d599bb92Russell King	free_irq(i2c_pnx->irq, alg_data);
6949d7f73632c87ef1b6187eb539d1efd63c3cf0e36Russell King	i2c_del_adapter(&alg_data->adapter);
695ebdbbf2003ae2342147c87c2a6c6ed8984b9cedeRussell King	clk_disable(alg_data->clk);
69688d968b22fa26d5e3a8cab46fc7c3a21c89a91d3Russell King	iounmap(alg_data->ioaddr);
69744c5d739181886cff8e3903dfa38cd704f3d9640Russell King	release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE);
6980321cb83e1c3f3a4282bd620c6cec78c5b80b572Russell King	clk_put(alg_data->clk);
69944c5d739181886cff8e3903dfa38cd704f3d9640Russell King	kfree(alg_data);
70041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	platform_set_drvdata(pdev, NULL);
70141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
70241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return 0;
70341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
70441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
70541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic struct platform_driver i2c_pnx_driver = {
70641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.driver = {
70741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		.name = "pnx-i2c",
70841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool		.owner = THIS_MODULE,
70941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	},
71041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.probe = i2c_pnx_probe,
71141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.remove = __devexit_p(i2c_pnx_remove),
71241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.suspend = i2c_pnx_controller_suspend,
71341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	.resume = i2c_pnx_controller_resume,
71441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool};
71541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
71641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic int __init i2c_adap_pnx_init(void)
71741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
71841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	return platform_driver_register(&i2c_pnx_driver);
71941561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
72041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
72141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolstatic void __exit i2c_adap_pnx_exit(void)
72241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool{
72341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool	platform_driver_unregister(&i2c_pnx_driver);
72441561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool}
72541561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
72641561f28e76a47dc6de0a954da85d0b5c42874ebVitaly WoolMODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>");
72741561f28e76a47dc6de0a954da85d0b5c42874ebVitaly WoolMODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses");
72841561f28e76a47dc6de0a954da85d0b5c42874ebVitaly WoolMODULE_LICENSE("GPL");
729add8eda7f2be781af0224241e870715cf0cfd75aKay SieversMODULE_ALIAS("platform:pnx-i2c");
73041561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool
73141561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Wool/* We need to make sure I2C is initialized before USB */
73241561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolsubsys_initcall(i2c_adap_pnx_init);
73341561f28e76a47dc6de0a954da85d0b5c42874ebVitaly Woolmodule_exit(i2c_adap_pnx_exit);
734