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