diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/i2c | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/i2c')
109 files changed, 0 insertions, 53597 deletions
diff --git a/ANDROID_3.4.5/drivers/i2c/Kconfig b/ANDROID_3.4.5/drivers/i2c/Kconfig deleted file mode 100644 index dd2ba673..00000000 --- a/ANDROID_3.4.5/drivers/i2c/Kconfig +++ /dev/null @@ -1,121 +0,0 @@ -# -# I2C subsystem configuration -# - -menuconfig I2C - tristate "I2C support" - depends on HAS_IOMEM - select RT_MUTEXES - ---help--- - I2C (pronounce: I-squared-C) is a slow serial bus protocol used in - many micro controller applications and developed by Philips. SMBus, - or System Management Bus is a subset of the I2C protocol. More - information is contained in the directory <file:Documentation/i2c/>, - especially in the file called "summary" there. - - Both I2C and SMBus are supported here. You will need this for - hardware sensors support, and also for Video For Linux support. - - If you want I2C support, you should say Y here and also to the - specific driver for your bus adapter(s) below. - - This I2C support can also be built as a module. If so, the module - will be called i2c-core. - -if I2C - -config I2C_BOARDINFO - boolean - default y - -config I2C_COMPAT - boolean "Enable compatibility bits for old user-space" - default y - help - Say Y here if you intend to run lm-sensors 3.1.1 or older, or any - other user-space package which expects i2c adapters to be class - devices. If you don't know, say Y. - -config I2C_CHARDEV - tristate "I2C device interface" - help - Say Y here to use i2c-* device files, usually found in the /dev - directory on your system. They make it possible to have user-space - programs use the I2C bus. Information on how to do this is - contained in the file <file:Documentation/i2c/dev-interface>. - - This support is also available as a module. If so, the module - will be called i2c-dev. - -config I2C_API - tristate "I2C API support" - help - Say Y here if you want to use i2c interface simply in other modules. - - This support is also available as a module. If so, the module - will be called i2c-api. - -config I2C_MUX - tristate "I2C bus multiplexing support" - depends on EXPERIMENTAL - help - Say Y here if you want the I2C core to support the ability to - handle multiplexed I2C bus topologies, by presenting each - multiplexed segment as a I2C adapter. - - This support is also available as a module. If so, the module - will be called i2c-mux. - -source drivers/i2c/muxes/Kconfig - -config I2C_HELPER_AUTO - bool "Autoselect pertinent helper modules" - default y - help - Some I2C bus drivers require so-called "I2C algorithm" modules - to work. These are basically software-only abstractions of generic - I2C interfaces. This option will autoselect them so that you don't - have to care. - - Unselect this only if you need to enable additional helper - modules, for example for use with external I2C bus drivers. - - In doubt, say Y. - -config I2C_SMBUS - tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO - help - Say Y here if you want support for SMBus extensions to the I2C - specification. At the moment, the only supported extension is - the SMBus alert protocol. - - This support is also available as a module. If so, the module - will be called i2c-smbus. - -source drivers/i2c/algos/Kconfig -source drivers/i2c/busses/Kconfig - -config I2C_DEBUG_CORE - bool "I2C Core debugging messages" - help - Say Y here if you want the I2C core to produce a bunch of debug - messages to the system log. Select this if you are having a - problem with I2C support and want to see more of what is going on. - -config I2C_DEBUG_ALGO - bool "I2C Algorithm debugging messages" - help - Say Y here if you want the I2C algorithm drivers to produce a bunch - of debug messages to the system log. Select this if you are having - a problem with I2C support and want to see more of what is going - on. - -config I2C_DEBUG_BUS - bool "I2C Bus debugging messages" - help - Say Y here if you want the I2C bus drivers to produce a bunch of - debug messages to the system log. Select this if you are having - a problem with I2C support and want to see more of what is going - on. - -endif # I2C diff --git a/ANDROID_3.4.5/drivers/i2c/Makefile b/ANDROID_3.4.5/drivers/i2c/Makefile deleted file mode 100644 index 38b383c4..00000000 --- a/ANDROID_3.4.5/drivers/i2c/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile for the i2c core. -# - -obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o -obj-$(CONFIG_I2C) += i2c-core.o -obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o -obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o -obj-$(CONFIG_I2C_MUX) += i2c-mux.o -obj-$(CONFIG_I2C_API) += i2c-api.o -obj-y += algos/ busses/ muxes/ - -ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG -CFLAGS_i2c-core.o := -Wno-deprecated-declarations diff --git a/ANDROID_3.4.5/drivers/i2c/algos/Kconfig b/ANDROID_3.4.5/drivers/i2c/algos/Kconfig deleted file mode 100644 index 39b0ade7..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/Kconfig +++ /dev/null @@ -1,25 +0,0 @@ -# -# I2C algorithm drivers configuration -# - -menu "I2C Algorithms" - visible if !I2C_HELPER_AUTO - -config I2C_ALGOBIT - tristate "I2C bit-banging interfaces" - -config I2C_ALGOPCF - tristate "I2C PCF 8584 interfaces" - -config I2C_ALGOPCA - tristate "I2C PCA 9564 interfaces" - -config I2C_ALGOWMT - tristate "WMT I2C Algorithm" - depends on ARCH_WMT && I2C - help - This supports the use of the WMT I2C interface found on WMT - processors. Say Y if you have one of these. You should also say Y - for the WMT I2C peripheral driver support below. - -endmenu diff --git a/ANDROID_3.4.5/drivers/i2c/algos/Makefile b/ANDROID_3.4.5/drivers/i2c/algos/Makefile deleted file mode 100644 index d26856d2..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the i2c algorithms -# - -obj-$(CONFIG_I2C_ALGOBIT) += i2c-algo-bit.o -obj-$(CONFIG_I2C_ALGOPCF) += i2c-algo-pcf.o -obj-$(CONFIG_I2C_ALGOPCA) += i2c-algo-pca.o - -ccflags-$(CONFIG_I2C_DEBUG_ALGO) := -DDEBUG -obj-$(CONFIG_I2C_WMT) += wmt-i2c-algo.o diff --git a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-bit.c b/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-bit.c deleted file mode 100644 index 7f0b8321..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-bit.c +++ /dev/null @@ -1,671 +0,0 @@ -/* ------------------------------------------------------------------------- - * i2c-algo-bit.c i2c driver algorithms for bit-shift adapters - * ------------------------------------------------------------------------- - * Copyright (C) 1995-2000 Simon G. Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA. - * ------------------------------------------------------------------------- */ - -/* With some changes from Frodo Looijaard <frodol@dds.nl>, Kyösti Mälkki - <kmalkki@cc.hut.fi> and Jean Delvare <khali@linux-fr.org> */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> - - -/* ----- global defines ----------------------------------------------- */ - -#ifdef DEBUG -#define bit_dbg(level, dev, format, args...) \ - do { \ - if (i2c_debug >= level) \ - dev_dbg(dev, format, ##args); \ - } while (0) -#else -#define bit_dbg(level, dev, format, args...) \ - do {} while (0) -#endif /* DEBUG */ - -/* ----- global variables --------------------------------------------- */ - -static int bit_test; /* see if the line-setting functions work */ -module_param(bit_test, int, S_IRUGO); -MODULE_PARM_DESC(bit_test, "lines testing - 0 off; 1 report; 2 fail if stuck"); - -#ifdef DEBUG -static int i2c_debug = 1; -module_param(i2c_debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2 verbose; 3 very verbose"); -#endif - -/* --- setting states on the bus with the right timing: --------------- */ - -#define setsda(adap, val) adap->setsda(adap->data, val) -#define setscl(adap, val) adap->setscl(adap->data, val) -#define getsda(adap) adap->getsda(adap->data) -#define getscl(adap) adap->getscl(adap->data) - -static inline void sdalo(struct i2c_algo_bit_data *adap) -{ - setsda(adap, 0); - udelay((adap->udelay + 1) / 2); -} - -static inline void sdahi(struct i2c_algo_bit_data *adap) -{ - setsda(adap, 1); - udelay((adap->udelay + 1) / 2); -} - -static inline void scllo(struct i2c_algo_bit_data *adap) -{ - setscl(adap, 0); - udelay(adap->udelay / 2); -} - -/* - * Raise scl line, and do checking for delays. This is necessary for slower - * devices. - */ -static int sclhi(struct i2c_algo_bit_data *adap) -{ - unsigned long start; - - setscl(adap, 1); - - /* Not all adapters have scl sense line... */ - if (!adap->getscl) - goto done; - - start = jiffies; - while (!getscl(adap)) { - /* This hw knows how to read the clock line, so we wait - * until it actually gets high. This is safer as some - * chips may hold it low ("clock stretching") while they - * are processing data internally. - */ - if (time_after(jiffies, start + adap->timeout)) { - /* Test one last time, as we may have been preempted - * between last check and timeout test. - */ - if (getscl(adap)) - break; - return -ETIMEDOUT; - } - cpu_relax(); - } -#ifdef DEBUG - if (jiffies != start && i2c_debug >= 3) - pr_debug("i2c-algo-bit: needed %ld jiffies for SCL to go " - "high\n", jiffies - start); -#endif - -done: - udelay(adap->udelay); - return 0; -} - - -/* --- other auxiliary functions -------------------------------------- */ -static void i2c_start(struct i2c_algo_bit_data *adap) -{ - /* assert: scl, sda are high */ - setsda(adap, 0); - udelay(adap->udelay); - scllo(adap); -} - -static void i2c_repstart(struct i2c_algo_bit_data *adap) -{ - /* assert: scl is low */ - sdahi(adap); - sclhi(adap); - setsda(adap, 0); - udelay(adap->udelay); - scllo(adap); -} - - -static void i2c_stop(struct i2c_algo_bit_data *adap) -{ - /* assert: scl is low */ - sdalo(adap); - sclhi(adap); - setsda(adap, 1); - udelay(adap->udelay); -} - - - -/* send a byte without start cond., look for arbitration, - check ackn. from slave */ -/* returns: - * 1 if the device acknowledged - * 0 if the device did not ack - * -ETIMEDOUT if an error occurred (while raising the scl line) - */ -static int i2c_outb(struct i2c_adapter *i2c_adap, unsigned char c) -{ - int i; - int sb; - int ack; - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - /* assert: scl is low */ - for (i = 7; i >= 0; i--) { - sb = (c >> i) & 1; - setsda(adap, sb); - udelay((adap->udelay + 1) / 2); - if (sclhi(adap) < 0) { /* timed out */ - bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " - "timeout at bit #%d\n", (int)c, i); - return -ETIMEDOUT; - } - /* FIXME do arbitration here: - * if (sb && !getsda(adap)) -> ouch! Get out of here. - * - * Report a unique code, so higher level code can retry - * the whole (combined) message and *NOT* issue STOP. - */ - scllo(adap); - } - sdahi(adap); - if (sclhi(adap) < 0) { /* timeout */ - bit_dbg(1, &i2c_adap->dev, "i2c_outb: 0x%02x, " - "timeout at ack\n", (int)c); - return -ETIMEDOUT; - } - - /* read ack: SDA should be pulled down by slave, or it may - * NAK (usually to report problems with the data we wrote). - */ - ack = !getsda(adap); /* ack: sda is pulled low -> success */ - bit_dbg(2, &i2c_adap->dev, "i2c_outb: 0x%02x %s\n", (int)c, - ack ? "A" : "NA"); - - scllo(adap); - return ack; - /* assert: scl is low (sda undef) */ -} - - -static int i2c_inb(struct i2c_adapter *i2c_adap) -{ - /* read byte via i2c port, without start/stop sequence */ - /* acknowledge is sent in i2c_read. */ - int i; - unsigned char indata = 0; - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - /* assert: scl is low */ - sdahi(adap); - for (i = 0; i < 8; i++) { - if (sclhi(adap) < 0) { /* timeout */ - bit_dbg(1, &i2c_adap->dev, "i2c_inb: timeout at bit " - "#%d\n", 7 - i); - return -ETIMEDOUT; - } - indata *= 2; - if (getsda(adap)) - indata |= 0x01; - setscl(adap, 0); - udelay(i == 7 ? adap->udelay / 2 : adap->udelay); - } - /* assert: scl is low */ - return indata; -} - -/* - * Sanity check for the adapter hardware - check the reaction of - * the bus lines only if it seems to be idle. - */ -static int test_bus(struct i2c_adapter *i2c_adap) -{ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - const char *name = i2c_adap->name; - int scl, sda, ret; - - if (adap->pre_xfer) { - ret = adap->pre_xfer(i2c_adap); - if (ret < 0) - return -ENODEV; - } - - if (adap->getscl == NULL) - pr_info("%s: Testing SDA only, SCL is not readable\n", name); - - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!scl || !sda) { - printk(KERN_WARNING - "%s: bus seems to be busy (scl=%d, sda=%d)\n", - name, scl, sda); - goto bailout; - } - - sdalo(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (sda) { - printk(KERN_WARNING "%s: SDA stuck high!\n", name); - goto bailout; - } - if (!scl) { - printk(KERN_WARNING "%s: SCL unexpected low " - "while pulling SDA low!\n", name); - goto bailout; - } - - sdahi(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!sda) { - printk(KERN_WARNING "%s: SDA stuck low!\n", name); - goto bailout; - } - if (!scl) { - printk(KERN_WARNING "%s: SCL unexpected low " - "while pulling SDA high!\n", name); - goto bailout; - } - - scllo(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 0 : getscl(adap); - if (scl) { - printk(KERN_WARNING "%s: SCL stuck high!\n", name); - goto bailout; - } - if (!sda) { - printk(KERN_WARNING "%s: SDA unexpected low " - "while pulling SCL low!\n", name); - goto bailout; - } - - sclhi(adap); - sda = getsda(adap); - scl = (adap->getscl == NULL) ? 1 : getscl(adap); - if (!scl) { - printk(KERN_WARNING "%s: SCL stuck low!\n", name); - goto bailout; - } - if (!sda) { - printk(KERN_WARNING "%s: SDA unexpected low " - "while pulling SCL high!\n", name); - goto bailout; - } - - if (adap->post_xfer) - adap->post_xfer(i2c_adap); - - pr_info("%s: Test OK\n", name); - return 0; -bailout: - sdahi(adap); - sclhi(adap); - - if (adap->post_xfer) - adap->post_xfer(i2c_adap); - - return -ENODEV; -} - -/* ----- Utility functions - */ - -/* try_address tries to contact a chip for a number of - * times before it gives up. - * return values: - * 1 chip answered - * 0 chip did not answer - * -x transmission error - */ -static int try_address(struct i2c_adapter *i2c_adap, - unsigned char addr, int retries) -{ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - int i, ret = 0; - - for (i = 0; i <= retries; i++) { - ret = i2c_outb(i2c_adap, addr); - if (ret == 1 || i == retries) - break; - bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); - i2c_stop(adap); - udelay(adap->udelay); - yield(); - bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); - i2c_start(adap); - } - if (i && ret) - bit_dbg(1, &i2c_adap->dev, "Used %d tries to %s client at " - "0x%02x: %s\n", i + 1, - addr & 1 ? "read from" : "write to", addr >> 1, - ret == 1 ? "success" : "failed, timeout?"); - return ret; -} - -static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) -{ - const unsigned char *temp = msg->buf; - int count = msg->len; - unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; - int retval; - int wrcount = 0; - - while (count > 0) { - retval = i2c_outb(i2c_adap, *temp); - - /* OK/ACK; or ignored NAK */ - if ((retval > 0) || (nak_ok && (retval == 0))) { - count--; - temp++; - wrcount++; - - /* A slave NAKing the master means the slave didn't like - * something about the data it saw. For example, maybe - * the SMBus PEC was wrong. - */ - } else if (retval == 0) { - dev_err(&i2c_adap->dev, "sendbytes: NAK bailout.\n"); - return -EIO; - - /* Timeout; or (someday) lost arbitration - * - * FIXME Lost ARB implies retrying the transaction from - * the first message, after the "winning" master issues - * its STOP. As a rule, upper layer code has no reason - * to know or care about this ... it is *NOT* an error. - */ - } else { - dev_err(&i2c_adap->dev, "sendbytes: error %d\n", - retval); - return retval; - } - } - return wrcount; -} - -static int acknak(struct i2c_adapter *i2c_adap, int is_ack) -{ - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - /* assert: sda is high */ - if (is_ack) /* send ack */ - setsda(adap, 0); - udelay((adap->udelay + 1) / 2); - if (sclhi(adap) < 0) { /* timeout */ - dev_err(&i2c_adap->dev, "readbytes: ack/nak timeout\n"); - return -ETIMEDOUT; - } - scllo(adap); - return 0; -} - -static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) -{ - int inval; - int rdcount = 0; /* counts bytes read */ - unsigned char *temp = msg->buf; - int count = msg->len; - const unsigned flags = msg->flags; - - while (count > 0) { - inval = i2c_inb(i2c_adap); - if (inval >= 0) { - *temp = inval; - rdcount++; - } else { /* read timed out */ - break; - } - - temp++; - count--; - - /* Some SMBus transactions require that we receive the - transaction length as the first read byte. */ - if (rdcount == 1 && (flags & I2C_M_RECV_LEN)) { - if (inval <= 0 || inval > I2C_SMBUS_BLOCK_MAX) { - if (!(flags & I2C_M_NO_RD_ACK)) - acknak(i2c_adap, 0); - dev_err(&i2c_adap->dev, "readbytes: invalid " - "block length (%d)\n", inval); - return -EPROTO; - } - /* The original count value accounts for the extra - bytes, that is, either 1 for a regular transaction, - or 2 for a PEC transaction. */ - count += inval; - msg->len += inval; - } - - bit_dbg(2, &i2c_adap->dev, "readbytes: 0x%02x %s\n", - inval, - (flags & I2C_M_NO_RD_ACK) - ? "(no ack/nak)" - : (count ? "A" : "NA")); - - if (!(flags & I2C_M_NO_RD_ACK)) { - inval = acknak(i2c_adap, count); - if (inval < 0) - return inval; - } - } - return rdcount; -} - -/* doAddress initiates the transfer by generating the start condition (in - * try_address) and transmits the address in the necessary format to handle - * reads, writes as well as 10bit-addresses. - * returns: - * 0 everything went okay, the chip ack'ed, or IGNORE_NAK flag was set - * -x an error occurred (like: -ENXIO if the device did not answer, or - * -ETIMEDOUT, for example if the lines are stuck...) - */ -static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) -{ - unsigned short flags = msg->flags; - unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK; - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - - unsigned char addr; - int ret, retries; - - retries = nak_ok ? 0 : i2c_adap->retries; - - if (flags & I2C_M_TEN) { - /* a ten bit address */ - addr = 0xf0 | ((msg->addr >> 7) & 0x06); - bit_dbg(2, &i2c_adap->dev, "addr0: %d\n", addr); - /* try extended address code...*/ - ret = try_address(i2c_adap, addr, retries); - if ((ret != 1) && !nak_ok) { - dev_err(&i2c_adap->dev, - "died at extended address code\n"); - return -ENXIO; - } - /* the remaining 8 bit address */ - ret = i2c_outb(i2c_adap, msg->addr & 0xff); - if ((ret != 1) && !nak_ok) { - /* the chip did not ack / xmission error occurred */ - dev_err(&i2c_adap->dev, "died at 2nd address code\n"); - return -ENXIO; - } - if (flags & I2C_M_RD) { - bit_dbg(3, &i2c_adap->dev, "emitting repeated " - "start condition\n"); - i2c_repstart(adap); - /* okay, now switch into reading mode */ - addr |= 0x01; - ret = try_address(i2c_adap, addr, retries); - if ((ret != 1) && !nak_ok) { - dev_err(&i2c_adap->dev, - "died at repeated address code\n"); - return -EIO; - } - } - } else { /* normal 7bit address */ - addr = msg->addr << 1; - if (flags & I2C_M_RD) - addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - ret = try_address(i2c_adap, addr, retries); - if ((ret != 1) && !nak_ok) - return -ENXIO; - } - - return 0; -} - -static int bit_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num) -{ - struct i2c_msg *pmsg; - struct i2c_algo_bit_data *adap = i2c_adap->algo_data; - int i, ret; - unsigned short nak_ok; - - if (adap->pre_xfer) { - ret = adap->pre_xfer(i2c_adap); - if (ret < 0) - return ret; - } - - bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); - i2c_start(adap); - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - nak_ok = pmsg->flags & I2C_M_IGNORE_NAK; - if (!(pmsg->flags & I2C_M_NOSTART)) { - if (i) { - bit_dbg(3, &i2c_adap->dev, "emitting " - "repeated start condition\n"); - i2c_repstart(adap); - } - ret = bit_doAddress(i2c_adap, pmsg); - if ((ret != 0) && !nak_ok) { - bit_dbg(1, &i2c_adap->dev, "NAK from " - "device addr 0x%02x msg #%d\n", - msgs[i].addr, i); - goto bailout; - } - } - if (pmsg->flags & I2C_M_RD) { - /* read bytes into buffer*/ - ret = readbytes(i2c_adap, pmsg); - if (ret >= 1) - bit_dbg(2, &i2c_adap->dev, "read %d byte%s\n", - ret, ret == 1 ? "" : "s"); - if (ret < pmsg->len) { - if (ret >= 0) - ret = -EIO; - goto bailout; - } - } else { - /* write bytes from buffer */ - ret = sendbytes(i2c_adap, pmsg); - if (ret >= 1) - bit_dbg(2, &i2c_adap->dev, "wrote %d byte%s\n", - ret, ret == 1 ? "" : "s"); - if (ret < pmsg->len) { - if (ret >= 0) - ret = -EIO; - goto bailout; - } - } - } - ret = i; - -bailout: - bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); - i2c_stop(adap); - - if (adap->post_xfer) - adap->post_xfer(i2c_adap); - return ret; -} - -static u32 bit_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_SMBUS_READ_BLOCK_DATA | - I2C_FUNC_SMBUS_BLOCK_PROC_CALL | - I2C_FUNC_10BIT_ADDR | I2C_FUNC_PROTOCOL_MANGLING; -} - - -/* -----exported algorithm data: ------------------------------------- */ - -const struct i2c_algorithm i2c_bit_algo = { - .master_xfer = bit_xfer, - .functionality = bit_func, -}; -EXPORT_SYMBOL(i2c_bit_algo); - -/* - * registering functions to load algorithms at runtime - */ -static int __i2c_bit_add_bus(struct i2c_adapter *adap, - int (*add_adapter)(struct i2c_adapter *)) -{ - struct i2c_algo_bit_data *bit_adap = adap->algo_data; - int ret; - - if (bit_test) { - ret = test_bus(adap); - if (bit_test >= 2 && ret < 0) - return -ENODEV; - } - - /* register new adapter to i2c module... */ - adap->algo = &i2c_bit_algo; - adap->retries = 3; - - ret = add_adapter(adap); - if (ret < 0) - return ret; - - /* Complain if SCL can't be read */ - if (bit_adap->getscl == NULL) { - dev_warn(&adap->dev, "Not I2C compliant: can't read SCL\n"); - dev_warn(&adap->dev, "Bus may be unreliable\n"); - } - return 0; -} - -int i2c_bit_add_bus(struct i2c_adapter *adap) -{ - return __i2c_bit_add_bus(adap, i2c_add_adapter); -} -EXPORT_SYMBOL(i2c_bit_add_bus); - -int i2c_bit_add_numbered_bus(struct i2c_adapter *adap) -{ - return __i2c_bit_add_bus(adap, i2c_add_numbered_adapter); -} -EXPORT_SYMBOL(i2c_bit_add_numbered_bus); - -MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); -MODULE_DESCRIPTION("I2C-Bus bit-banging algorithm"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pca.c b/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pca.c deleted file mode 100644 index 73133b10..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pca.c +++ /dev/null @@ -1,566 +0,0 @@ -/* - * i2c-algo-pca.c i2c driver algorithms for PCA9564 adapters - * Copyright (C) 2004 Arcom Control Systems - * Copyright (C) 2008 Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/delay.h> -#include <linux/jiffies.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-pca.h> - -#define DEB1(fmt, args...) do { if (i2c_debug >= 1) \ - printk(KERN_DEBUG fmt, ## args); } while (0) -#define DEB2(fmt, args...) do { if (i2c_debug >= 2) \ - printk(KERN_DEBUG fmt, ## args); } while (0) -#define DEB3(fmt, args...) do { if (i2c_debug >= 3) \ - printk(KERN_DEBUG fmt, ## args); } while (0) - -static int i2c_debug; - -#define pca_outw(adap, reg, val) adap->write_byte(adap->data, reg, val) -#define pca_inw(adap, reg) adap->read_byte(adap->data, reg) - -#define pca_status(adap) pca_inw(adap, I2C_PCA_STA) -#define pca_clock(adap) adap->i2c_clock -#define pca_set_con(adap, val) pca_outw(adap, I2C_PCA_CON, val) -#define pca_get_con(adap) pca_inw(adap, I2C_PCA_CON) -#define pca_wait(adap) adap->wait_for_completion(adap->data) -#define pca_reset(adap) adap->reset_chip(adap->data) - -static void pca9665_reset(void *pd) -{ - struct i2c_algo_pca_data *adap = pd; - pca_outw(adap, I2C_PCA_INDPTR, I2C_PCA_IPRESET); - pca_outw(adap, I2C_PCA_IND, 0xA5); - pca_outw(adap, I2C_PCA_IND, 0x5A); -} - -/* - * Generate a start condition on the i2c bus. - * - * returns after the start condition has occurred - */ -static int pca_start(struct i2c_algo_pca_data *adap) -{ - int sta = pca_get_con(adap); - DEB2("=== START\n"); - sta |= I2C_PCA_CON_STA; - sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); - pca_set_con(adap, sta); - return pca_wait(adap); -} - -/* - * Generate a repeated start condition on the i2c bus - * - * return after the repeated start condition has occurred - */ -static int pca_repeated_start(struct i2c_algo_pca_data *adap) -{ - int sta = pca_get_con(adap); - DEB2("=== REPEATED START\n"); - sta |= I2C_PCA_CON_STA; - sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_SI); - pca_set_con(adap, sta); - return pca_wait(adap); -} - -/* - * Generate a stop condition on the i2c bus - * - * returns after the stop condition has been generated - * - * STOPs do not generate an interrupt or set the SI flag, since the - * part returns the idle state (0xf8). Hence we don't need to - * pca_wait here. - */ -static void pca_stop(struct i2c_algo_pca_data *adap) -{ - int sta = pca_get_con(adap); - DEB2("=== STOP\n"); - sta |= I2C_PCA_CON_STO; - sta &= ~(I2C_PCA_CON_STA|I2C_PCA_CON_SI); - pca_set_con(adap, sta); -} - -/* - * Send the slave address and R/W bit - * - * returns after the address has been sent - */ -static int pca_address(struct i2c_algo_pca_data *adap, - struct i2c_msg *msg) -{ - int sta = pca_get_con(adap); - int addr; - - addr = ((0x7f & msg->addr) << 1); - if (msg->flags & I2C_M_RD) - addr |= 1; - DEB2("=== SLAVE ADDRESS %#04x+%c=%#04x\n", - msg->addr, msg->flags & I2C_M_RD ? 'R' : 'W', addr); - - pca_outw(adap, I2C_PCA_DAT, addr); - - sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); - pca_set_con(adap, sta); - - return pca_wait(adap); -} - -/* - * Transmit a byte. - * - * Returns after the byte has been transmitted - */ -static int pca_tx_byte(struct i2c_algo_pca_data *adap, - __u8 b) -{ - int sta = pca_get_con(adap); - DEB2("=== WRITE %#04x\n", b); - pca_outw(adap, I2C_PCA_DAT, b); - - sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI); - pca_set_con(adap, sta); - - return pca_wait(adap); -} - -/* - * Receive a byte - * - * returns immediately. - */ -static void pca_rx_byte(struct i2c_algo_pca_data *adap, - __u8 *b, int ack) -{ - *b = pca_inw(adap, I2C_PCA_DAT); - DEB2("=== READ %#04x %s\n", *b, ack ? "ACK" : "NACK"); -} - -/* - * Setup ACK or NACK for next received byte and wait for it to arrive. - * - * Returns after next byte has arrived. - */ -static int pca_rx_ack(struct i2c_algo_pca_data *adap, - int ack) -{ - int sta = pca_get_con(adap); - - sta &= ~(I2C_PCA_CON_STO|I2C_PCA_CON_STA|I2C_PCA_CON_SI|I2C_PCA_CON_AA); - - if (ack) - sta |= I2C_PCA_CON_AA; - - pca_set_con(adap, sta); - return pca_wait(adap); -} - -static int pca_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, - int num) -{ - struct i2c_algo_pca_data *adap = i2c_adap->algo_data; - struct i2c_msg *msg = NULL; - int curmsg; - int numbytes = 0; - int state; - int ret; - int completed = 1; - unsigned long timeout = jiffies + i2c_adap->timeout; - - while ((state = pca_status(adap)) != 0xf8) { - if (time_before(jiffies, timeout)) { - msleep(10); - } else { - dev_dbg(&i2c_adap->dev, "bus is not idle. status is " - "%#04x\n", state); - return -EBUSY; - } - } - - DEB1("{{{ XFER %d messages\n", num); - - if (i2c_debug >= 2) { - for (curmsg = 0; curmsg < num; curmsg++) { - int addr, i; - msg = &msgs[curmsg]; - - addr = (0x7f & msg->addr) ; - - if (msg->flags & I2C_M_RD) - printk(KERN_INFO " [%02d] RD %d bytes from %#02x [%#02x, ...]\n", - curmsg, msg->len, addr, (addr << 1) | 1); - else { - printk(KERN_INFO " [%02d] WR %d bytes to %#02x [%#02x%s", - curmsg, msg->len, addr, addr << 1, - msg->len == 0 ? "" : ", "); - for (i = 0; i < msg->len; i++) - printk("%#04x%s", msg->buf[i], i == msg->len - 1 ? "" : ", "); - printk("]\n"); - } - } - } - - curmsg = 0; - ret = -EIO; - while (curmsg < num) { - state = pca_status(adap); - - DEB3("STATE is 0x%02x\n", state); - msg = &msgs[curmsg]; - - switch (state) { - case 0xf8: /* On reset or stop the bus is idle */ - completed = pca_start(adap); - break; - - case 0x08: /* A START condition has been transmitted */ - case 0x10: /* A repeated start condition has been transmitted */ - completed = pca_address(adap, msg); - break; - - case 0x18: /* SLA+W has been transmitted; ACK has been received */ - case 0x28: /* Data byte in I2CDAT has been transmitted; ACK has been received */ - if (numbytes < msg->len) { - completed = pca_tx_byte(adap, - msg->buf[numbytes]); - numbytes++; - break; - } - curmsg++; numbytes = 0; - if (curmsg == num) - pca_stop(adap); - else - completed = pca_repeated_start(adap); - break; - - case 0x20: /* SLA+W has been transmitted; NOT ACK has been received */ - DEB2("NOT ACK received after SLA+W\n"); - pca_stop(adap); - ret = -ENXIO; - goto out; - - case 0x40: /* SLA+R has been transmitted; ACK has been received */ - completed = pca_rx_ack(adap, msg->len > 1); - break; - - case 0x50: /* Data bytes has been received; ACK has been returned */ - if (numbytes < msg->len) { - pca_rx_byte(adap, &msg->buf[numbytes], 1); - numbytes++; - completed = pca_rx_ack(adap, - numbytes < msg->len - 1); - break; - } - curmsg++; numbytes = 0; - if (curmsg == num) - pca_stop(adap); - else - completed = pca_repeated_start(adap); - break; - - case 0x48: /* SLA+R has been transmitted; NOT ACK has been received */ - DEB2("NOT ACK received after SLA+R\n"); - pca_stop(adap); - ret = -ENXIO; - goto out; - - case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */ - DEB2("NOT ACK received after data byte\n"); - pca_stop(adap); - goto out; - - case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */ - DEB2("Arbitration lost\n"); - /* - * The PCA9564 data sheet (2006-09-01) says "A - * START condition will be transmitted when the - * bus becomes free (STOP or SCL and SDA high)" - * when the STA bit is set (p. 11). - * - * In case this won't work, try pca_reset() - * instead. - */ - pca_start(adap); - goto out; - - case 0x58: /* Data byte has been received; NOT ACK has been returned */ - if (numbytes == msg->len - 1) { - pca_rx_byte(adap, &msg->buf[numbytes], 0); - curmsg++; numbytes = 0; - if (curmsg == num) - pca_stop(adap); - else - completed = pca_repeated_start(adap); - } else { - DEB2("NOT ACK sent after data byte received. " - "Not final byte. numbytes %d. len %d\n", - numbytes, msg->len); - pca_stop(adap); - goto out; - } - break; - case 0x70: /* Bus error - SDA stuck low */ - DEB2("BUS ERROR - SDA Stuck low\n"); - pca_reset(adap); - goto out; - case 0x90: /* Bus error - SCL stuck low */ - DEB2("BUS ERROR - SCL Stuck low\n"); - pca_reset(adap); - goto out; - case 0x00: /* Bus error during master or slave mode due to illegal START or STOP condition */ - DEB2("BUS ERROR - Illegal START or STOP\n"); - pca_reset(adap); - goto out; - default: - dev_err(&i2c_adap->dev, "unhandled SIO state 0x%02x\n", state); - break; - } - - if (!completed) - goto out; - } - - ret = curmsg; - out: - DEB1("}}} transferred %d/%d messages. " - "status is %#04x. control is %#04x\n", - curmsg, num, pca_status(adap), - pca_get_con(adap)); - return ret; -} - -static u32 pca_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm pca_algo = { - .master_xfer = pca_xfer, - .functionality = pca_func, -}; - -static unsigned int pca_probe_chip(struct i2c_adapter *adap) -{ - struct i2c_algo_pca_data *pca_data = adap->algo_data; - /* The trick here is to check if there is an indirect register - * available. If there is one, we will read the value we first - * wrote on I2C_PCA_IADR. Otherwise, we will read the last value - * we wrote on I2C_PCA_ADR - */ - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR); - pca_outw(pca_data, I2C_PCA_IND, 0xAA); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ITO); - pca_outw(pca_data, I2C_PCA_IND, 0x00); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IADR); - if (pca_inw(pca_data, I2C_PCA_IND) == 0xAA) { - printk(KERN_INFO "%s: PCA9665 detected.\n", adap->name); - return I2C_PCA_CHIP_9665; - } else { - printk(KERN_INFO "%s: PCA9564 detected.\n", adap->name); - return I2C_PCA_CHIP_9564; - } -} - -static int pca_init(struct i2c_adapter *adap) -{ - struct i2c_algo_pca_data *pca_data = adap->algo_data; - - adap->algo = &pca_algo; - - if (pca_probe_chip(adap) == I2C_PCA_CHIP_9564) { - static int freqs[] = {330, 288, 217, 146, 88, 59, 44, 36}; - int clock; - - if (pca_data->i2c_clock > 7) { - switch (pca_data->i2c_clock) { - case 330000: - pca_data->i2c_clock = I2C_PCA_CON_330kHz; - break; - case 288000: - pca_data->i2c_clock = I2C_PCA_CON_288kHz; - break; - case 217000: - pca_data->i2c_clock = I2C_PCA_CON_217kHz; - break; - case 146000: - pca_data->i2c_clock = I2C_PCA_CON_146kHz; - break; - case 88000: - pca_data->i2c_clock = I2C_PCA_CON_88kHz; - break; - case 59000: - pca_data->i2c_clock = I2C_PCA_CON_59kHz; - break; - case 44000: - pca_data->i2c_clock = I2C_PCA_CON_44kHz; - break; - case 36000: - pca_data->i2c_clock = I2C_PCA_CON_36kHz; - break; - default: - printk(KERN_WARNING - "%s: Invalid I2C clock speed selected." - " Using default 59kHz.\n", adap->name); - pca_data->i2c_clock = I2C_PCA_CON_59kHz; - } - } else { - printk(KERN_WARNING "%s: " - "Choosing the clock frequency based on " - "index is deprecated." - " Use the nominal frequency.\n", adap->name); - } - - pca_reset(pca_data); - - clock = pca_clock(pca_data); - printk(KERN_INFO "%s: Clock frequency is %dkHz\n", - adap->name, freqs[clock]); - - pca_set_con(pca_data, I2C_PCA_CON_ENSIO | clock); - } else { - int clock; - int mode; - int tlow, thi; - /* Values can be found on PCA9665 datasheet section 7.3.2.6 */ - int min_tlow, min_thi; - /* These values are the maximum raise and fall values allowed - * by the I2C operation mode (Standard, Fast or Fast+) - * They are used (added) below to calculate the clock dividers - * of PCA9665. Note that they are slightly different of the - * real maximum, to allow the change on mode exactly on the - * maximum clock rate for each mode - */ - int raise_fall_time; - - /* Ignore the reset function from the module, - * we can use the parallel bus reset - */ - pca_data->reset_chip = pca9665_reset; - - if (pca_data->i2c_clock > 1265800) { - printk(KERN_WARNING "%s: I2C clock speed too high." - " Using 1265.8kHz.\n", adap->name); - pca_data->i2c_clock = 1265800; - } - - if (pca_data->i2c_clock < 60300) { - printk(KERN_WARNING "%s: I2C clock speed too low." - " Using 60.3kHz.\n", adap->name); - pca_data->i2c_clock = 60300; - } - - /* To avoid integer overflow, use clock/100 for calculations */ - clock = pca_clock(pca_data) / 100; - - if (pca_data->i2c_clock > 10000) { - mode = I2C_PCA_MODE_TURBO; - min_tlow = 14; - min_thi = 5; - raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 4000) { - mode = I2C_PCA_MODE_FASTP; - min_tlow = 17; - min_thi = 9; - raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */ - } else if (pca_data->i2c_clock > 1000) { - mode = I2C_PCA_MODE_FAST; - min_tlow = 44; - min_thi = 20; - raise_fall_time = 58; /* Raise 29e-8s, Fall 29e-8s */ - } else { - mode = I2C_PCA_MODE_STD; - min_tlow = 157; - min_thi = 134; - raise_fall_time = 127; /* Raise 29e-8s, Fall 98e-8s */ - } - - /* The minimum clock that respects the thi/tlow = 134/157 is - * 64800 Hz. Below that, we have to fix the tlow to 255 and - * calculate the thi factor. - */ - if (clock < 648) { - tlow = 255; - thi = 1000000 - clock * raise_fall_time; - thi /= (I2C_PCA_OSC_PER * clock) - tlow; - } else { - tlow = (1000000 - clock * raise_fall_time) * min_tlow; - tlow /= I2C_PCA_OSC_PER * clock * (min_thi + min_tlow); - thi = tlow * min_thi / min_tlow; - } - - pca_reset(pca_data); - - printk(KERN_INFO - "%s: Clock frequency is %dHz\n", adap->name, clock * 100); - - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_IMODE); - pca_outw(pca_data, I2C_PCA_IND, mode); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLL); - pca_outw(pca_data, I2C_PCA_IND, tlow); - pca_outw(pca_data, I2C_PCA_INDPTR, I2C_PCA_ISCLH); - pca_outw(pca_data, I2C_PCA_IND, thi); - - pca_set_con(pca_data, I2C_PCA_CON_ENSIO); - } - udelay(500); /* 500 us for oscilator to stabilise */ - - return 0; -} - -/* - * registering functions to load algorithms at runtime - */ -int i2c_pca_add_bus(struct i2c_adapter *adap) -{ - int rval; - - rval = pca_init(adap); - if (rval) - return rval; - - return i2c_add_adapter(adap); -} -EXPORT_SYMBOL(i2c_pca_add_bus); - -int i2c_pca_add_numbered_bus(struct i2c_adapter *adap) -{ - int rval; - - rval = pca_init(adap); - if (rval) - return rval; - - return i2c_add_numbered_adapter(adap); -} -EXPORT_SYMBOL(i2c_pca_add_numbered_bus); - -MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>, " - "Wolfram Sang <w.sang@pengutronix.de>"); -MODULE_DESCRIPTION("I2C-Bus PCA9564/PCA9665 algorithm"); -MODULE_LICENSE("GPL"); - -module_param(i2c_debug, int, 0); diff --git a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.c b/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.c deleted file mode 100644 index 5c237952..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * i2c-algo-pcf.c i2c driver algorithms for PCF8584 adapters - * - * Copyright (C) 1995-1997 Simon G. Vogl - * 1998-2000 Hans Berglund - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA. - * - * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and - * Frodo Looijaard <frodol@dds.nl>, and also from Martin Bailey - * <mbailey@littlefeet-inc.com> - * - * Partially rewriten by Oleg I. Vdovikin <vdovikin@jscc.ru> to handle multiple - * messages, proper stop/repstart signaling during receive, added detect code - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-pcf.h> -#include "i2c-algo-pcf.h" - - -#define DEB2(x) if (i2c_debug >= 2) x -#define DEB3(x) if (i2c_debug >= 3) x /* print several statistical values */ -#define DEBPROTO(x) if (i2c_debug >= 9) x; - /* debug the protocol by showing transferred bits */ -#define DEF_TIMEOUT 16 - -/* - * module parameters: - */ -static int i2c_debug; - -/* setting states on the bus with the right timing: */ - -#define set_pcf(adap, ctl, val) adap->setpcf(adap->data, ctl, val) -#define get_pcf(adap, ctl) adap->getpcf(adap->data, ctl) -#define get_own(adap) adap->getown(adap->data) -#define get_clock(adap) adap->getclock(adap->data) -#define i2c_outb(adap, val) adap->setpcf(adap->data, 0, val) -#define i2c_inb(adap) adap->getpcf(adap->data, 0) - -/* other auxiliary functions */ - -static void i2c_start(struct i2c_algo_pcf_data *adap) -{ - DEBPROTO(printk(KERN_DEBUG "S ")); - set_pcf(adap, 1, I2C_PCF_START); -} - -static void i2c_repstart(struct i2c_algo_pcf_data *adap) -{ - DEBPROTO(printk(" Sr ")); - set_pcf(adap, 1, I2C_PCF_REPSTART); -} - -static void i2c_stop(struct i2c_algo_pcf_data *adap) -{ - DEBPROTO(printk("P\n")); - set_pcf(adap, 1, I2C_PCF_STOP); -} - -static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status) -{ - DEB2(printk(KERN_INFO - "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n", - *status)); - /* - * Cleanup from LAB -- reset and enable ESO. - * This resets the PCF8584; since we've lost the bus, no - * further attempts should be made by callers to clean up - * (no i2c_stop() etc.) - */ - set_pcf(adap, 1, I2C_PCF_PIN); - set_pcf(adap, 1, I2C_PCF_ESO); - /* - * We pause for a time period sufficient for any running - * I2C transaction to complete -- the arbitration logic won't - * work properly until the next START is seen. - * It is assumed the bus driver or client has set a proper value. - * - * REVISIT: should probably use msleep instead of mdelay if we - * know we can sleep. - */ - if (adap->lab_mdelay) - mdelay(adap->lab_mdelay); - - DEB2(printk(KERN_INFO - "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", - get_pcf(adap, 1))); -} - -static int wait_for_bb(struct i2c_algo_pcf_data *adap) -{ - - int timeout = DEF_TIMEOUT; - int status; - - status = get_pcf(adap, 1); - - while (!(status & I2C_PCF_BB) && --timeout) { - udelay(100); /* wait for 100 us */ - status = get_pcf(adap, 1); - } - - if (timeout == 0) { - printk(KERN_ERR "Timeout waiting for Bus Busy\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) -{ - - int timeout = DEF_TIMEOUT; - - *status = get_pcf(adap, 1); - - while ((*status & I2C_PCF_PIN) && --timeout) { - adap->waitforpin(adap->data); - *status = get_pcf(adap, 1); - } - if (*status & I2C_PCF_LAB) { - handle_lab(adap, status); - return -EINTR; - } - - if (timeout == 0) - return -ETIMEDOUT; - - return 0; -} - -/* - * This should perform the 'PCF8584 initialization sequence' as described - * in the Philips IC12 data book (1995, Aug 29). - * There should be a 30 clock cycle wait after reset, I assume this - * has been fulfilled. - * There should be a delay at the end equal to the longest I2C message - * to synchronize the BB-bit (in multimaster systems). How long is - * this? I assume 1 second is always long enough. - * - * vdovikin: added detect code for PCF8584 - */ -static int pcf_init_8584 (struct i2c_algo_pcf_data *adap) -{ - unsigned char temp; - - DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: PCF state 0x%02x\n", - get_pcf(adap, 1))); - - /* S1=0x80: S0 selected, serial interface off */ - set_pcf(adap, 1, I2C_PCF_PIN); - /* - * check to see S1 now used as R/W ctrl - - * PCF8584 does that when ESO is zero - */ - if (((temp = get_pcf(adap, 1)) & 0x7f) != (0)) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S0 (0x%02x).\n", temp)); - return -ENXIO; /* definitely not PCF8584 */ - } - - /* load own address in S0, effective address is (own << 1) */ - i2c_outb(adap, get_own(adap)); - /* check it's really written */ - if ((temp = i2c_inb(adap)) != get_own(adap)) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S0 (0x%02x).\n", temp)); - return -ENXIO; - } - - /* S1=0xA0, next byte in S2 */ - set_pcf(adap, 1, I2C_PCF_PIN | I2C_PCF_ES1); - /* check to see S2 now selected */ - if (((temp = get_pcf(adap, 1)) & 0x7f) != I2C_PCF_ES1) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S2 (0x%02x).\n", temp)); - return -ENXIO; - } - - /* load clock register S2 */ - i2c_outb(adap, get_clock(adap)); - /* check it's really written, the only 5 lowest bits does matter */ - if (((temp = i2c_inb(adap)) & 0x1f) != get_clock(adap)) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't set S2 (0x%02x).\n", temp)); - return -ENXIO; - } - - /* Enable serial interface, idle, S0 selected */ - set_pcf(adap, 1, I2C_PCF_IDLE); - - /* check to see PCF is really idled and we can access status register */ - if ((temp = get_pcf(adap, 1)) != (I2C_PCF_PIN | I2C_PCF_BB)) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: PCF detection failed -- can't select S1` (0x%02x).\n", temp)); - return -ENXIO; - } - - printk(KERN_DEBUG "i2c-algo-pcf.o: detected and initialized PCF8584.\n"); - - return 0; -} - -static int pcf_sendbytes(struct i2c_adapter *i2c_adap, const char *buf, - int count, int last) -{ - struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; - int wrcount, status, timeout; - - for (wrcount=0; wrcount<count; ++wrcount) { - DEB2(dev_dbg(&i2c_adap->dev, "i2c_write: writing %2.2X\n", - buf[wrcount] & 0xff)); - i2c_outb(adap, buf[wrcount]); - timeout = wait_for_pin(adap, &status); - if (timeout) { - if (timeout == -EINTR) - return -EINTR; /* arbitration lost */ - - i2c_stop(adap); - dev_err(&i2c_adap->dev, "i2c_write: error - timeout.\n"); - return -EREMOTEIO; /* got a better one ?? */ - } - if (status & I2C_PCF_LRB) { - i2c_stop(adap); - dev_err(&i2c_adap->dev, "i2c_write: error - no ack.\n"); - return -EREMOTEIO; /* got a better one ?? */ - } - } - if (last) - i2c_stop(adap); - else - i2c_repstart(adap); - - return wrcount; -} - -static int pcf_readbytes(struct i2c_adapter *i2c_adap, char *buf, - int count, int last) -{ - int i, status; - struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; - int wfp; - - /* increment number of bytes to read by one -- read dummy byte */ - for (i = 0; i <= count; i++) { - - if ((wfp = wait_for_pin(adap, &status))) { - if (wfp == -EINTR) - return -EINTR; /* arbitration lost */ - - i2c_stop(adap); - dev_err(&i2c_adap->dev, "pcf_readbytes timed out.\n"); - return -1; - } - - if ((status & I2C_PCF_LRB) && (i != count)) { - i2c_stop(adap); - dev_err(&i2c_adap->dev, "i2c_read: i2c_inb, No ack.\n"); - return -1; - } - - if (i == count - 1) { - set_pcf(adap, 1, I2C_PCF_ESO); - } else if (i == count) { - if (last) - i2c_stop(adap); - else - i2c_repstart(adap); - } - - if (i) - buf[i - 1] = i2c_inb(adap); - else - i2c_inb(adap); /* dummy read */ - } - - return i - 1; -} - - -static int pcf_doAddress(struct i2c_algo_pcf_data *adap, - struct i2c_msg *msg) -{ - unsigned short flags = msg->flags; - unsigned char addr; - - addr = msg->addr << 1; - if (flags & I2C_M_RD) - addr |= 1; - if (flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - i2c_outb(adap, addr); - - return 0; -} - -static int pcf_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, - int num) -{ - struct i2c_algo_pcf_data *adap = i2c_adap->algo_data; - struct i2c_msg *pmsg; - int i; - int ret=0, timeout, status; - - if (adap->xfer_begin) - adap->xfer_begin(adap->data); - - /* Check for bus busy */ - timeout = wait_for_bb(adap); - if (timeout) { - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: " - "Timeout waiting for BB in pcf_xfer\n");) - i = -EIO; - goto out; - } - - for (i = 0;ret >= 0 && i < num; i++) { - pmsg = &msgs[i]; - - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: Doing %s %d bytes to 0x%02x - %d of %d messages\n", - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num);) - - ret = pcf_doAddress(adap, pmsg); - - /* Send START */ - if (i == 0) - i2c_start(adap); - - /* Wait for PIN (pending interrupt NOT) */ - timeout = wait_for_pin(adap, &status); - if (timeout) { - if (timeout == -EINTR) { - /* arbitration lost */ - i = -EINTR; - goto out; - } - i2c_stop(adap); - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: Timeout waiting " - "for PIN(1) in pcf_xfer\n");) - i = -EREMOTEIO; - goto out; - } - - /* Check LRB (last rcvd bit - slave ack) */ - if (status & I2C_PCF_LRB) { - i2c_stop(adap); - DEB2(printk(KERN_ERR "i2c-algo-pcf.o: No LRB(1) in pcf_xfer\n");) - i = -EREMOTEIO; - goto out; - } - - DEB3(printk(KERN_DEBUG "i2c-algo-pcf.o: Msg %d, addr=0x%x, flags=0x%x, len=%d\n", - i, msgs[i].addr, msgs[i].flags, msgs[i].len);) - - if (pmsg->flags & I2C_M_RD) { - ret = pcf_readbytes(i2c_adap, pmsg->buf, pmsg->len, - (i + 1 == num)); - - if (ret != pmsg->len) { - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " - "only read %d bytes.\n",ret)); - } else { - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: read %d bytes.\n",ret)); - } - } else { - ret = pcf_sendbytes(i2c_adap, pmsg->buf, pmsg->len, - (i + 1 == num)); - - if (ret != pmsg->len) { - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: fail: " - "only wrote %d bytes.\n",ret)); - } else { - DEB2(printk(KERN_DEBUG "i2c-algo-pcf.o: wrote %d bytes.\n",ret)); - } - } - } - -out: - if (adap->xfer_end) - adap->xfer_end(adap->data); - return i; -} - -static u32 pcf_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_PROTOCOL_MANGLING; -} - -/* exported algorithm data: */ -static const struct i2c_algorithm pcf_algo = { - .master_xfer = pcf_xfer, - .functionality = pcf_func, -}; - -/* - * registering functions to load algorithms at runtime - */ -int i2c_pcf_add_bus(struct i2c_adapter *adap) -{ - struct i2c_algo_pcf_data *pcf_adap = adap->algo_data; - int rval; - - DEB2(dev_dbg(&adap->dev, "hw routines registered.\n")); - - /* register new adapter to i2c module... */ - adap->algo = &pcf_algo; - - if ((rval = pcf_init_8584(pcf_adap))) - return rval; - - rval = i2c_add_adapter(adap); - - return rval; -} -EXPORT_SYMBOL(i2c_pcf_add_bus); - -MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); -MODULE_DESCRIPTION("I2C-Bus PCF8584 algorithm"); -MODULE_LICENSE("GPL"); - -module_param(i2c_debug, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(i2c_debug, - "debug level - 0 off; 1 normal; 2,3 more verbose; 9 pcf-protocol"); diff --git a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.h b/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.h deleted file mode 100644 index 1ec703ee..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/i2c-algo-pcf.h +++ /dev/null @@ -1,77 +0,0 @@ -/* -------------------------------------------------------------------- */ -/* i2c-pcf8584.h: PCF 8584 global defines */ -/* -------------------------------------------------------------------- */ -/* Copyright (C) 1996 Simon G. Vogl - 1999 Hans Berglund - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA. */ -/* -------------------------------------------------------------------- */ - -/* With some changes from Frodo Looijaard <frodol@dds.nl> */ - -#ifndef I2C_PCF8584_H -#define I2C_PCF8584_H 1 - -/* ----- Control register bits ---------------------------------------- */ -#define I2C_PCF_PIN 0x80 -#define I2C_PCF_ESO 0x40 -#define I2C_PCF_ES1 0x20 -#define I2C_PCF_ES2 0x10 -#define I2C_PCF_ENI 0x08 -#define I2C_PCF_STA 0x04 -#define I2C_PCF_STO 0x02 -#define I2C_PCF_ACK 0x01 - -#define I2C_PCF_START (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK) -#define I2C_PCF_STOP (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_STO | I2C_PCF_ACK) -#define I2C_PCF_REPSTART ( I2C_PCF_ESO | I2C_PCF_STA | I2C_PCF_ACK) -#define I2C_PCF_IDLE (I2C_PCF_PIN | I2C_PCF_ESO | I2C_PCF_ACK) - -/* ----- Status register bits ----------------------------------------- */ -/*#define I2C_PCF_PIN 0x80 as above*/ - -#define I2C_PCF_INI 0x40 /* 1 if not initialized */ -#define I2C_PCF_STS 0x20 -#define I2C_PCF_BER 0x10 -#define I2C_PCF_AD0 0x08 -#define I2C_PCF_LRB 0x08 -#define I2C_PCF_AAS 0x04 -#define I2C_PCF_LAB 0x02 -#define I2C_PCF_BB 0x01 - -/* ----- Chip clock frequencies --------------------------------------- */ -#define I2C_PCF_CLK3 0x00 -#define I2C_PCF_CLK443 0x10 -#define I2C_PCF_CLK6 0x14 -#define I2C_PCF_CLK 0x18 -#define I2C_PCF_CLK12 0x1c - -/* ----- transmission frequencies ------------------------------------- */ -#define I2C_PCF_TRNS90 0x00 /* 90 kHz */ -#define I2C_PCF_TRNS45 0x01 /* 45 kHz */ -#define I2C_PCF_TRNS11 0x02 /* 11 kHz */ -#define I2C_PCF_TRNS15 0x03 /* 1.5 kHz */ - - -/* ----- Access to internal registers according to ES1,ES2 ------------ */ -/* they are mapped to the data port ( a0 = 0 ) */ -/* available when ESO == 0 : */ - -#define I2C_PCF_OWNADR 0 -#define I2C_PCF_INTREG I2C_PCF_ES2 -#define I2C_PCF_CLKREG I2C_PCF_ES1 - -#endif /* I2C_PCF8584_H */ diff --git a/ANDROID_3.4.5/drivers/i2c/algos/wmt-i2c-algo.c b/ANDROID_3.4.5/drivers/i2c/algos/wmt-i2c-algo.c deleted file mode 100755 index 3be850d2..00000000 --- a/ANDROID_3.4.5/drivers/i2c/algos/wmt-i2c-algo.c +++ /dev/null @@ -1,308 +0,0 @@ -/*++ - drivers/i2c/algos/wmt_i2c_algo.c - - Copyright (c) 2008 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ - -#define WMT_I2C_ALGO_C - -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ - -#include <mach/hardware.h> -#include <mach/wmt-i2c-bus.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else -#define DPRINTK printf - -#endif - -static struct i2c_adapter *wmt_i2c_adap[5]; - -/*!************************************************************************* -* wmt_i2c_valid_messages() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief verify the input message -* -* \retval 1 if success -*/ -static int wmt_i2c_valid_messages( - struct i2c_msg msgs[], /*!<; //[IN] transfer data */ - int num /*!<; //[IN] transfer data length */ -) -{ - int i; - if (num < 1 || num > MAX_MESSAGES) { - DPRINTK(KERN_INFO "Invalid number of messages (max=%d, num=%d)\n", MAX_MESSAGES, num); - return -EINVAL; - } - - /* check consistency of our messages */ - for (i = 0; i < num; i++) { - if (&msgs[i] == NULL) { - DPRINTK(KERN_INFO "Msgs is NULL\n"); - return -EINVAL; - } else { - if (msgs[i].buf == NULL) { - DPRINTK(KERN_INFO "Length is less than zero\n"); - return -EINVAL; - } - } - } - - return 1; -} -/*!************************************************************************* -* wmt_i2c_do_xfer() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief -* -* \retval 0 if success -*/ -static int wmt_i2c_do_xfer( - struct i2c_adapter *i2c_adap, /*!<; //[IN] a pointer point to struct inode */ - struct i2c_msg msgs[], /*!<; //[IN] transfer data */ - int num /*!<; //[IN] transfer data length */ -) -{ - int i; - struct i2c_algo_wmt_data *adap; - int ret = 0 ; - - adap = i2c_adap->algo_data; - - /*ret = adap->wait_bus_not_busy();*/ - for (i = 0 ; i < 10; ++i) - ; - if (ret < 0) - return ret ; - - ret = adap->send_request(msgs, num, 0, 0, 0); - - return ret; - -} - -/*!************************************************************************* -* wmt_i2c_xfer() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief Transfer (read/write) data to i2c bus, wmt_i2c_do_xfer will be called to transfer -* -* \retval 0 if success -*/ -static int wmt_i2c_xfer( - struct i2c_adapter *i2c_adap, /*!<; //[IN] a pointer point to struct inode */ - struct i2c_msg msgs[], /*!<; //[IN] transfer data */ - int num /*!<; //[IN] transfer data length */ -) -{ - int ret ; - int i ; - - ret = wmt_i2c_valid_messages(msgs, num); - if (ret < 0) - return ret ; - - for (i = i2c_adap->retries ; i >= 0; i--) { - - ret = wmt_i2c_do_xfer(i2c_adap, msgs, num); - if (ret > 0) - return ret ; - DPRINTK(KERN_INFO"Retrying transmission \n"); - udelay(100); - } - - DPRINTK(KERN_INFO"Retried %i times\n", i2c_adap->retries); - return ret; - -} -/*!************************************************************************* -* wmt_i2c_functionality() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief -* -* \retval smbus functionality -*/ -static u32 wmt_i2c_functionality( - struct i2c_adapter *adapter /*!<; //[IN] a pointer point to struct inode */ -) -{ - /* Emulate the SMBUS functions*/ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -/* - * send i2c_msg into fifo of i2c bus - * msg: transfer data content - * msg_num:number of transferring msg - * bus_id :used to indicate which bus do device want to access - */ -int wmt_i2c_transfer(struct i2c_msg* msgs, int msg_num, int bus_id, void (*callback)(void *data), void *data) -{ - struct i2c_algo_wmt_data *adap; - int ret = 0 ; - - adap = wmt_i2c_adap[bus_id]->algo_data; - ret = adap->send_request(msgs, msg_num, 1, callback, data); - return ret; -} - -#if 0 -/*!************************************************************************* -* wmt_i2c_control() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief To set i2c transfer mode -* -* \retval 0 if success -*/ -static int wmt_i2c_control( - struct i2c_adapter *i2c_adap, /*!<; //[IN] a pointer point to struct inode */ - unsigned int cmd, /*!<; //[IN] standard or fast mode */ - unsigned long arg /*!<; //Not in used, but can't delete */ -) -{ - int ret ; - struct i2c_algo_wmt_data *adap = i2c_adap->algo_data; - - ret = 0 ; - DPRINTK("wmt_i2c_control: cmd = 0x%8.8x \n", cmd); - - switch (cmd) { - case I2C_SET_STANDARD_MODE: - adap->set_mode(I2C_STANDARD_MODE); - break ; - case I2C_SET_FAST_MODE: - adap->set_mode(I2C_FAST_MODE); - break ; - default: - ret = -EINVAL; - break; - } - - return ret; -} -#endif - - -struct i2c_algorithm wmt_i2c_algorithm = { - .master_xfer = wmt_i2c_xfer, - .functionality = wmt_i2c_functionality, -}; -/*!************************************************************************* -* wmt_i2c_add_bus() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief -* -* \retval NULL -*/ -int wmt_i2c_add_bus(struct i2c_adapter *i2c_adap) -{ - printk(KERN_INFO"i2c: adding %s.\n", i2c_adap->name); - - i2c_adap->algo = &wmt_i2c_algorithm; - wmt_i2c_adap[i2c_adap->nr] = i2c_adap; - - /* register new adapter to i2c module... */ - /* - i2c_add_adapter(i2c_adap); - */ - i2c_add_numbered_adapter(i2c_adap); - - /* adap->reset();*/ - - return 0; -} -/*!************************************************************************* -* wmt_i2c_del_bus() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief -* -* \retval NULL -*/ -int wmt_i2c_del_bus(struct i2c_adapter *i2c_adap) -{ - int res; - res = i2c_del_adapter(i2c_adap); - if (res < 0) - return res; - - printk(KERN_INFO "i2c: removing %s.\n", i2c_adap->name); - - return 0; -} -/*!************************************************************************* -* wmt_i2c_algo_init() -* -* Private Function by Paul Kwong, 2007/1/12 -*/ -/*! -* \brief -* -* \retval NULL -*/ -static int __init wmt_i2c_algo_init(void) -{ - printk(KERN_INFO "i2c: wmt algorithm module loaded.\n"); - return 0; -} - -EXPORT_SYMBOL(wmt_i2c_add_bus); -EXPORT_SYMBOL(wmt_i2c_del_bus); - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C ALGO Driver"); -MODULE_LICENSE("GPL"); - -module_init(wmt_i2c_algo_init); - -#undef WMT_I2C_ALGO_C diff --git a/ANDROID_3.4.5/drivers/i2c/busses/Kconfig b/ANDROID_3.4.5/drivers/i2c/busses/Kconfig deleted file mode 100644 index 1bfed463..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/Kconfig +++ /dev/null @@ -1,931 +0,0 @@ -# -# Sensor device configuration -# - -menu "I2C Hardware Bus support" - -comment "PC SMBus host controller drivers" - depends on PCI - -config I2C_ALI1535 - tristate "ALI 1535" - depends on PCI - help - If you say yes to this option, support will be included for the SMB - Host controller on Acer Labs Inc. (ALI) M1535 South Bridges. The SMB - controller is part of the 7101 device, which is an ACPI-compliant - Power Management Unit (PMU). - - This driver can also be built as a module. If so, the module - will be called i2c-ali1535. - -config I2C_ALI1563 - tristate "ALI 1563" - depends on PCI && EXPERIMENTAL - help - If you say yes to this option, support will be included for the SMB - Host controller on Acer Labs Inc. (ALI) M1563 South Bridges. The SMB - controller is part of the 7101 device, which is an ACPI-compliant - Power Management Unit (PMU). - - This driver can also be built as a module. If so, the module - will be called i2c-ali1563. - -config I2C_ALI15X3 - tristate "ALI 15x3" - depends on PCI - help - If you say yes to this option, support will be included for the - Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces. - - This driver can also be built as a module. If so, the module - will be called i2c-ali15x3. - -config I2C_AMD756 - tristate "AMD 756/766/768/8111 and nVidia nForce" - depends on PCI - help - If you say yes to this option, support will be included for the AMD - 756/766/768 mainboard I2C interfaces. The driver also includes - support for the first (SMBus 1.0) I2C interface of the AMD 8111 and - the nVidia nForce I2C interface. - - This driver can also be built as a module. If so, the module - will be called i2c-amd756. - -config I2C_AMD756_S4882 - tristate "SMBus multiplexing on the Tyan S4882" - depends on I2C_AMD756 && X86 && EXPERIMENTAL - help - Enabling this option will add specific SMBus support for the Tyan - S4882 motherboard. On this 4-CPU board, the SMBus is multiplexed - over 8 different channels, where the various memory module EEPROMs - and temperature sensors live. Saying yes here will give you access - to these in addition to the trunk. - - This driver can also be built as a module. If so, the module - will be called i2c-amd756-s4882. - -config I2C_AMD8111 - tristate "AMD 8111" - depends on PCI - help - If you say yes to this option, support will be included for the - second (SMBus 2.0) AMD 8111 mainboard I2C interface. - - This driver can also be built as a module. If so, the module - will be called i2c-amd8111. - -config I2C_I801 - tristate "Intel 82801 (ICH/PCH)" - depends on PCI - select CHECK_SIGNATURE if X86 && DMI - help - If you say yes to this option, support will be included for the Intel - 801 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported: - 82801AA - 82801AB - 82801BA - 82801CA/CAM - 82801DB - 82801EB/ER (ICH5/ICH5R) - 6300ESB - ICH6 - ICH7 - ESB2 - ICH8 - ICH9 - EP80579 (Tolapai) - ICH10 - 5/3400 Series (PCH) - 6 Series (PCH) - Patsburg (PCH) - DH89xxCC (PCH) - Panther Point (PCH) - Lynx Point (PCH) - - This driver can also be built as a module. If so, the module - will be called i2c-i801. - -config I2C_ISCH - tristate "Intel SCH SMBus 1.0" - depends on PCI - select LPC_SCH - help - Say Y here if you want to use SMBus controller on the Intel SCH - based systems. - - This driver can also be built as a module. If so, the module - will be called i2c-isch. - -config I2C_PIIX4 - tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)" - depends on PCI - help - If you say yes to this option, support will be included for the Intel - PIIX4 family of mainboard I2C interfaces. Specifically, the following - versions of the chipset are supported (note that Serverworks is part - of Broadcom): - Intel PIIX4 - Intel 440MX - ATI IXP200 - ATI IXP300 - ATI IXP400 - ATI SB600 - ATI SB700 - ATI SB800 - AMD Hudson-2 - Serverworks OSB4 - Serverworks CSB5 - Serverworks CSB6 - Serverworks HT-1000 - Serverworks HT-1100 - SMSC Victory66 - - This driver can also be built as a module. If so, the module - will be called i2c-piix4. - -config I2C_NFORCE2 - tristate "Nvidia nForce2, nForce3 and nForce4" - depends on PCI - help - If you say yes to this option, support will be included for the Nvidia - nForce2, nForce3 and nForce4 families of mainboard I2C interfaces. - - This driver can also be built as a module. If so, the module - will be called i2c-nforce2. - -config I2C_NFORCE2_S4985 - tristate "SMBus multiplexing on the Tyan S4985" - depends on I2C_NFORCE2 && X86 && EXPERIMENTAL - help - Enabling this option will add specific SMBus support for the Tyan - S4985 motherboard. On this 4-CPU board, the SMBus is multiplexed - over 4 different channels, where the various memory module EEPROMs - live. Saying yes here will give you access to these in addition - to the trunk. - - This driver can also be built as a module. If so, the module - will be called i2c-nforce2-s4985. - -config I2C_SIS5595 - tristate "SiS 5595" - depends on PCI - help - If you say yes to this option, support will be included for the - SiS5595 SMBus (a subset of I2C) interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sis5595. - -config I2C_SIS630 - tristate "SiS 630/730" - depends on PCI - help - If you say yes to this option, support will be included for the - SiS630 and SiS730 SMBus (a subset of I2C) interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sis630. - -config I2C_SIS96X - tristate "SiS 96x" - depends on PCI - help - If you say yes to this option, support will be included for the SiS - 96x SMBus (a subset of I2C) interfaces. Specifically, the following - chipsets are supported: - 645/961 - 645DX/961 - 645DX/962 - 648/961 - 650/961 - 735 - 745 - - This driver can also be built as a module. If so, the module - will be called i2c-sis96x. - -config I2C_VIA - tristate "VIA VT82C586B" - depends on PCI && EXPERIMENTAL - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for the VIA - 82C586B I2C interface - - This driver can also be built as a module. If so, the module - will be called i2c-via. - -config I2C_VIAPRO - tristate "VIA VT82C596/82C686/82xx and CX700/VX8xx" - depends on PCI - help - If you say yes to this option, support will be included for the VIA - VT82C596 and later SMBus interface. Specifically, the following - chipsets are supported: - VT82C596A/B - VT82C686A/B - VT8231 - VT8233/A - VT8235 - VT8237R/A/S - VT8251 - CX700 - VX800/VX820 - VX855/VX875 - - This driver can also be built as a module. If so, the module - will be called i2c-viapro. - -if ACPI - -comment "ACPI drivers" - -config I2C_SCMI - tristate "SMBus Control Method Interface" - help - This driver supports the SMBus Control Method Interface. It needs the - BIOS to declare ACPI control methods as described in the SMBus Control - Method Interface specification. - - To compile this driver as a module, choose M here: - the module will be called i2c-scmi. - -endif # ACPI - -comment "Mac SMBus host controller drivers" - depends on PPC_CHRP || PPC_PMAC - -config I2C_HYDRA - tristate "CHRP Apple Hydra Mac I/O I2C interface" - depends on PCI && PPC_CHRP && EXPERIMENTAL - select I2C_ALGOBIT - help - This supports the use of the I2C interface in the Apple Hydra Mac - I/O chip on some CHRP machines (e.g. the LongTrail). Say Y if you - have such a machine. - - This support is also available as a module. If so, the module - will be called i2c-hydra. - -config I2C_POWERMAC - tristate "Powermac I2C interface" - depends on PPC_PMAC - default y - help - This exposes the various PowerMac i2c interfaces to the linux i2c - layer and to userland. It is used by various drivers on the PowerMac - platform, and should generally be enabled. - - This support is also available as a module. If so, the module - will be called i2c-powermac. - -comment "I2C system bus drivers (mostly embedded / system-on-chip)" - -config I2C_AT91 - tristate "Atmel AT91 I2C Two-Wire interface (TWI)" - depends on ARCH_AT91 && EXPERIMENTAL && BROKEN - help - This supports the use of the I2C interface on Atmel AT91 - processors. - - This driver is BROKEN because the controller which it uses - will easily trigger RX overrun and TX underrun errors. Using - low I2C clock rates may partially work around those issues - on some systems. Another serious problem is that there is no - documented way to issue repeated START conditions, as needed - to support combined I2C messages. Use the i2c-gpio driver - unless your system can cope with those limitations. - -config I2C_AU1550 - tristate "Au1550/Au1200/Au1300 SMBus interface" - depends on MIPS_ALCHEMY - help - If you say yes to this option, support will be included for the - Au1550/Au1200/Au1300 SMBus interface. - - This driver can also be built as a module. If so, the module - will be called i2c-au1550. - -config I2C_BLACKFIN_TWI - tristate "Blackfin TWI I2C support" - depends on BLACKFIN - depends on !BF561 && !BF531 && !BF532 && !BF533 - help - This is the I2C bus driver for Blackfin on-chip TWI interface. - - This driver can also be built as a module. If so, the module - will be called i2c-bfin-twi. - -config I2C_BLACKFIN_TWI_CLK_KHZ - int "Blackfin TWI I2C clock (kHz)" - depends on I2C_BLACKFIN_TWI - range 21 400 - default 50 - help - The unit of the TWI clock is kHz. - -config I2C_CPM - tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)" - depends on (CPM1 || CPM2) && OF_I2C - help - This supports the use of the I2C interface on Freescale - processors with CPM1 or CPM2. - - This driver can also be built as a module. If so, the module - will be called i2c-cpm. - -config I2C_DAVINCI - tristate "DaVinci I2C driver" - depends on ARCH_DAVINCI - help - Support for TI DaVinci I2C controller driver. - - This driver can also be built as a module. If so, the module - will be called i2c-davinci. - - Please note that this driver might be needed to bring up other - devices such as DaVinci NIC. - For details please see http://www.ti.com/davinci - -config I2C_DESIGNWARE_PLATFORM - tristate "Synopsys DesignWare Platfrom" - depends on HAVE_CLK - help - If you say yes to this option, support will be included for the - Synopsys DesignWare I2C adapter. Only master mode is supported. - - This driver can also be built as a module. If so, the module - will be called i2c-designware-platform. - -config I2C_DESIGNWARE_PCI - tristate "Synopsys DesignWare PCI" - depends on PCI - help - If you say yes to this option, support will be included for the - Synopsys DesignWare I2C adapter. Only master mode is supported. - - This driver can also be built as a module. If so, the module - will be called i2c-designware-pci. - -config I2C_EG20T - tristate "Intel EG20T PCH/LAPIS Semicon IOH(ML7213/ML7223/ML7831) I2C" - depends on PCI - help - This driver is for PCH(Platform controller Hub) I2C of EG20T which - is an IOH(Input/Output Hub) for x86 embedded processor. - This driver can access PCH I2C bus device. - - This driver also can be used for LAPIS Semiconductor IOH(Input/ - Output Hub), ML7213, ML7223 and ML7831. - ML7213 IOH is for IVI(In-Vehicle Infotainment) use, ML7223 IOH is - for MP(Media Phone) use and ML7831 IOH is for general purpose use. - ML7213/ML7223/ML7831 is companion chip for Intel Atom E6xx series. - ML7213/ML7223/ML7831 is completely compatible for Intel EG20T PCH. - -config I2C_GPIO - tristate "GPIO-based bitbanging I2C" - depends on GENERIC_GPIO - select I2C_ALGOBIT - help - This is a very simple bitbanging I2C driver utilizing the - arch-neutral GPIO API to control the SCL and SDA lines. - -config I2C_HIGHLANDER - tristate "Highlander FPGA SMBus interface" - depends on SH_HIGHLANDER - help - If you say yes to this option, support will be included for - the SMBus interface located in the FPGA on various Highlander - boards, particularly the R0P7780LC0011RL and R0P7785LC0011RL - FPGAs. This is wholly unrelated to the SoC I2C. - - This driver can also be built as a module. If so, the module - will be called i2c-highlander. - -config I2C_IBM_IIC - tristate "IBM PPC 4xx on-chip I2C interface" - depends on 4xx - help - Say Y here if you want to use IIC peripheral found on - embedded IBM PPC 4xx based systems. - - This driver can also be built as a module. If so, the module - will be called i2c-ibm_iic. - -config I2C_IMX - tristate "IMX I2C interface" - depends on ARCH_MXC - help - Say Y here if you want to use the IIC bus controller on - the Freescale i.MX/MXC processors. - - This driver can also be built as a module. If so, the module - will be called i2c-imx. - -config I2C_INTEL_MID - tristate "Intel Moorestown/Medfield Platform I2C controller" - depends on PCI - help - Say Y here if you have an Intel Moorestown/Medfield platform I2C - controller. - - This support is also available as a module. If so, the module - will be called i2c-intel-mid. - -config I2C_IOP3XX - tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface" - depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX - help - Say Y here if you want to use the IIC bus controller on - the Intel IOPx3xx I/O Processors or IXP4xx Network Processors. - - This driver can also be built as a module. If so, the module - will be called i2c-iop3xx. - -config I2C_IXP2000 - tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)" - depends on ARCH_IXP2000 - select I2C_ALGOBIT - help - Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based - system and are using GPIO lines for an I2C bus. - - This support is also available as a module. If so, the module - will be called i2c-ixp2000. - - This driver is deprecated and will be dropped soon. Use i2c-gpio - instead. - -config I2C_MPC - tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx" - depends on PPC - help - If you say yes to this option, support will be included for the - built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx, - MPC8240, MPC8245, MPC83xx, MPC85xx and MPC8641 family processors. - - This driver can also be built as a module. If so, the module - will be called i2c-mpc. - -config I2C_MV64XXX - tristate "Marvell mv64xxx I2C Controller" - depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL - help - If you say yes to this option, support will be included for the - built-in I2C interface on the Marvell 64xxx line of host bridges. - - This driver can also be built as a module. If so, the module - will be called i2c-mv64xxx. - -config I2C_MXS - tristate "Freescale i.MX28 I2C interface" - depends on SOC_IMX28 - help - Say Y here if you want to use the I2C bus controller on - the Freescale i.MX28 processors. - - This driver can also be built as a module. If so, the module - will be called i2c-mxs. - -config I2C_NOMADIK - tristate "ST-Ericsson Nomadik/Ux500 I2C Controller" - depends on PLAT_NOMADIK - help - If you say yes to this option, support will be included for the - I2C interface from ST-Ericsson's Nomadik and Ux500 architectures. - -config I2C_NUC900 - tristate "NUC900 I2C Driver" - depends on ARCH_W90X900 - help - Say Y here to include support for I2C controller in the - Winbond/Nuvoton NUC900 based System-on-Chip devices. - -config I2C_OCORES - tristate "OpenCores I2C Controller" - depends on EXPERIMENTAL - help - If you say yes to this option, support will be included for the - OpenCores I2C controller. For details see - http://www.opencores.org/projects.cgi/web/i2c/overview - - This driver can also be built as a module. If so, the module - will be called i2c-ocores. - -config I2C_OMAP - tristate "OMAP I2C adapter" - depends on ARCH_OMAP - default y if MACH_OMAP_H3 || MACH_OMAP_OSK - help - If you say yes to this option, support will be included for the - I2C interface on the Texas Instruments OMAP1/2 family of processors. - Like OMAP1510/1610/1710/5912 and OMAP242x. - For details see http://www.ti.com/omap. - -config I2C_PASEMI - tristate "PA Semi SMBus interface" - depends on PPC_PASEMI && PCI - help - Supports the PA Semi PWRficient on-chip SMBus interfaces. - -config I2C_PCA_PLATFORM - tristate "PCA9564/PCA9665 as platform device" - select I2C_ALGOPCA - default n - help - This driver supports a memory mapped Philips PCA9564/PCA9665 - parallel bus to I2C bus controller. - - This driver can also be built as a module. If so, the module - will be called i2c-pca-platform. - -config I2C_PMCMSP - tristate "PMC MSP I2C TWI Controller" - depends on PMC_MSP - help - This driver supports the PMC TWI controller on MSP devices. - - This driver can also be built as module. If so, the module - will be called i2c-pmcmsp. - -config I2C_PNX - tristate "I2C bus support for Philips PNX and NXP LPC targets" - depends on ARCH_PNX4008 || ARCH_LPC32XX - help - This driver supports the Philips IP3204 I2C IP block master and/or - slave controller - - This driver can also be built as a module. If so, the module - will be called i2c-pnx. - -config I2C_PUV3 - tristate "PKUnity v3 I2C bus support" - depends on UNICORE32 && ARCH_PUV3 - select I2C_ALGOBIT - help - This driver supports the I2C IP inside the PKUnity-v3 SoC. - This I2C bus controller is under AMBA/AXI bus. - - This driver can also be built as a module. If so, the module - will be called i2c-puv3. - -config I2C_PXA - tristate "Intel PXA2XX I2C adapter" - depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF) - help - If you have devices in the PXA I2C bus, say yes to this option. - This driver can also be built as a module. If so, the module - will be called i2c-pxa. - -config I2C_PXA_PCI - def_bool I2C_PXA && X86_32 && PCI && OF - -config I2C_PXA_SLAVE - bool "Intel PXA2XX I2C Slave comms support" - depends on I2C_PXA && !X86_32 - help - Support I2C slave mode communications on the PXA I2C bus. This - is necessary for systems where the PXA may be a target on the - I2C bus. - -config HAVE_S3C2410_I2C - bool - help - This will include I2C support for Samsung SoCs. If you want to - include I2C support for any machine, kindly select this in the - respective Kconfig file. - -config I2C_S3C2410 - tristate "S3C2410 I2C Driver" - depends on HAVE_S3C2410_I2C - help - Say Y here to include support for I2C controller in the - Samsung SoCs. - -config I2C_S6000 - tristate "S6000 I2C support" - depends on XTENSA_VARIANT_S6000 - help - This driver supports the on chip I2C device on the - S6000 xtensa processor family. - - To compile this driver as a module, choose M here. The module - will be called i2c-s6000. - -config I2C_SH7760 - tristate "Renesas SH7760 I2C Controller" - depends on CPU_SUBTYPE_SH7760 - help - This driver supports the 2 I2C interfaces on the Renesas SH7760. - - This driver can also be built as a module. If so, the module - will be called i2c-sh7760. - -config I2C_SH_MOBILE - tristate "SuperH Mobile I2C Controller" - depends on SUPERH || ARCH_SHMOBILE - help - If you say yes to this option, support will be included for the - built-in I2C interface on the Renesas SH-Mobile processor. - - This driver can also be built as a module. If so, the module - will be called i2c-sh_mobile. - -config I2C_SIMTEC - tristate "Simtec Generic I2C interface" - select I2C_ALGOBIT - help - If you say yes to this option, support will be included for - the Simtec Generic I2C interface. This driver is for the - simple I2C bus used on newer Simtec products for general - I2C, such as DDC on the Simtec BBD2016A. - - This driver can also be built as a module. If so, the module - will be called i2c-simtec. - -config I2C_SIRF - tristate "CSR SiRFprimaII I2C interface" - depends on ARCH_PRIMA2 - help - If you say yes to this option, support will be included for the - CSR SiRFprimaII I2C interface. - - This driver can also be built as a module. If so, the module - will be called i2c-sirf. - -config I2C_STU300 - tristate "ST Microelectronics DDC I2C interface" - depends on MACH_U300 - default y if MACH_U300 - help - If you say yes to this option, support will be included for the - I2C interface from ST Microelectronics simply called "DDC I2C" - supporting both I2C and DDC, used in e.g. the U300 series - mobile platforms. - - This driver can also be built as a module. If so, the module - will be called i2c-stu300. - -config I2C_TEGRA - tristate "NVIDIA Tegra internal I2C controller" - depends on ARCH_TEGRA - help - If you say yes to this option, support will be included for the - I2C controller embedded in NVIDIA Tegra SOCs - -config I2C_VERSATILE - tristate "ARM Versatile/Realview I2C bus support" - depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS - select I2C_ALGOBIT - help - Say yes if you want to support the I2C serial bus on ARMs Versatile - range of platforms. - - This driver can also be built as a module. If so, the module - will be called i2c-versatile. - -config I2C_OCTEON - tristate "Cavium OCTEON I2C bus support" - depends on CPU_CAVIUM_OCTEON - help - Say yes if you want to support the I2C serial bus on Cavium - OCTEON SOC. - - This driver can also be built as a module. If so, the module - will be called i2c-octeon. - -config I2C_XILINX - tristate "Xilinx I2C Controller" - depends on EXPERIMENTAL && HAS_IOMEM - help - If you say yes to this option, support will be included for the - Xilinx I2C controller. - - This driver can also be built as a module. If so, the module - will be called xilinx_i2c. - -config I2C_XLR - tristate "XLR I2C support" - depends on CPU_XLR - help - This driver enables support for the on-chip I2C interface of - the Netlogic XLR/XLS MIPS processors. - - This driver can also be built as a module. If so, the module - will be called i2c-xlr. - -comment "External I2C/SMBus adapter drivers" - -config I2C_DIOLAN_U2C - tristate "Diolan U2C-12 USB adapter" - depends on USB - help - If you say yes to this option, support will be included for Diolan - U2C-12, a USB to I2C interface. - - This driver can also be built as a module. If so, the module - will be called i2c-diolan-u2c. - -config I2C_PARPORT - tristate "Parallel port adapter" - depends on PARPORT - select I2C_ALGOBIT - select I2C_SMBUS - help - This supports parallel port I2C adapters such as the ones made by - Philips or Velleman, Analog Devices evaluation boards, and more. - Basically any adapter using the parallel port as an I2C bus with - no extra chipset is supported by this driver, or could be. - - This driver is a replacement for (and was inspired by) an older - driver named i2c-philips-par. The new driver supports more devices, - and makes it easier to add support for new devices. - - An adapter type parameter is now mandatory. Please read the file - Documentation/i2c/busses/i2c-parport for details. - - Another driver exists, named i2c-parport-light, which doesn't depend - on the parport driver. This is meant for embedded systems. Don't say - Y here if you intend to say Y or M there. - - This support is also available as a module. If so, the module - will be called i2c-parport. - -config I2C_PARPORT_LIGHT - tristate "Parallel port adapter (light)" - select I2C_ALGOBIT - select I2C_SMBUS - help - This supports parallel port I2C adapters such as the ones made by - Philips or Velleman, Analog Devices evaluation boards, and more. - Basically any adapter using the parallel port as an I2C bus with - no extra chipset is supported by this driver, or could be. - - This driver is a light version of i2c-parport. It doesn't depend - on the parport driver, and uses direct I/O access instead. This - might be preferred on embedded systems where wasting memory for - the clean but heavy parport handling is not an option. The - drawback is a reduced portability and the impossibility to - daisy-chain other parallel port devices. - - Don't say Y here if you said Y or M to i2c-parport. Saying M to - both is possible but both modules should not be loaded at the same - time. - - This support is also available as a module. If so, the module - will be called i2c-parport-light. - -config I2C_TAOS_EVM - tristate "TAOS evaluation module" - depends on EXPERIMENTAL - select SERIO - select SERIO_SERPORT - default n - help - This supports TAOS evaluation modules on serial port. In order to - use this driver, you will need the inputattach tool, which is part - of the input-utils package. - - If unsure, say N. - - This support is also available as a module. If so, the module - will be called i2c-taos-evm. - -config I2C_TINY_USB - tristate "Tiny-USB adapter" - depends on USB - help - If you say yes to this option, support will be included for the - i2c-tiny-usb, a simple do-it-yourself USB to I2C interface. See - http://www.harbaum.org/till/i2c_tiny_usb for hardware details. - - This driver can also be built as a module. If so, the module - will be called i2c-tiny-usb. - -comment "Other I2C/SMBus bus drivers" - -config I2C_ACORN - tristate "Acorn IOC/IOMD I2C bus support" - depends on ARCH_ACORN - default y - select I2C_ALGOBIT - help - Say yes if you want to support the I2C bus on Acorn platforms. - - If you don't know, say Y. - -config I2C_ELEKTOR - tristate "Elektor ISA card" - depends on ISA && HAS_IOPORT && BROKEN_ON_SMP - select I2C_ALGOPCF - help - This supports the PCF8584 ISA bus I2C adapter. Say Y if you own - such an adapter. - - This support is also available as a module. If so, the module - will be called i2c-elektor. - -config I2C_PCA_ISA - tristate "PCA9564/PCA9665 on an ISA bus" - depends on ISA - select I2C_ALGOPCA - default n - help - This driver supports ISA boards using the Philips PCA9564/PCA9665 - parallel bus to I2C bus controller. - - This driver can also be built as a module. If so, the module - will be called i2c-pca-isa. - - This device is almost undetectable and using this driver on a - system which doesn't have this device will result in long - delays when I2C/SMBus chip drivers are loaded (e.g. at boot - time). If unsure, say N. - -config I2C_SIBYTE - tristate "SiByte SMBus interface" - depends on SIBYTE_SB1xxx_SOC - help - Supports the SiByte SOC on-chip I2C interfaces (2 channels). - -config I2C_STUB - tristate "I2C/SMBus Test Stub" - depends on EXPERIMENTAL && m - default 'n' - help - This module may be useful to developers of SMBus client drivers, - especially for certain kinds of sensor chips. - - If you do build this module, be sure to read the notes and warnings - in <file:Documentation/i2c/i2c-stub>. - - If you don't know what to do here, definitely say N. - -config SCx200_I2C - tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)" - depends on SCx200_GPIO - select I2C_ALGOBIT - help - Enable the use of two GPIO pins of a SCx200 processor as an I2C bus. - - If you don't know what to do here, say N. - - This support is also available as a module. If so, the module - will be called scx200_i2c. - - This driver is deprecated and will be dropped soon. Use i2c-gpio - (or scx200_acb) instead. - -config SCx200_I2C_SCL - int "GPIO pin used for SCL" - depends on SCx200_I2C - default "12" - help - Enter the GPIO pin number used for the SCL signal. This value can - also be specified with a module parameter. - -config SCx200_I2C_SDA - int "GPIO pin used for SDA" - depends on SCx200_I2C - default "13" - help - Enter the GPIO pin number used for the SSA signal. This value can - also be specified with a module parameter. - -config SCx200_ACB - tristate "Geode ACCESS.bus support" - depends on X86_32 && PCI - help - Enable the use of the ACCESS.bus controllers on the Geode SCx200 and - SC1100 processors and the CS5535 and CS5536 Geode companion devices. - - If you don't know what to do here, say N. - - This support is also available as a module. If so, the module - will be called scx200_acb. - -config I2C_WMT - tristate "WonderMedia I2C Interface" - depends on ARCH_WMT && I2C && I2C_ALGOWMT - help - This supports the use of the WMT I2C interface found on the WMT - Say Y if you have one of these. You should also say Y for the WMT - I2C peripheral driver support below. - - To compile this driver as a module, say M here: the - modules will be called i2c-wmt and i2c-algo-wmt. -config I2C1_WMT - bool - depends on ARCH_WMT && I2C && I2C_ALGOWMT - default y -config I2C_SLAVE_WMT - bool "WonderMedia I2C-SLAVE Interface" - depends on ARCH_WMT && I2C_WMT - help - This supports the use of the WMT I2C SLAVE interface found on the WMT - Say Y if you have one of these. You should also say Y for the WMT - I2C peripheral driver support below. -endmenu diff --git a/ANDROID_3.4.5/drivers/i2c/busses/Makefile b/ANDROID_3.4.5/drivers/i2c/busses/Makefile deleted file mode 100644 index 20082f63..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/Makefile +++ /dev/null @@ -1,93 +0,0 @@ -# -# Makefile for the i2c bus drivers. -# - -# ACPI drivers -obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o - -# PC SMBus host controller drivers -obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o -obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o -obj-$(CONFIG_I2C_ALI15X3) += i2c-ali15x3.o -obj-$(CONFIG_I2C_AMD756) += i2c-amd756.o -obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o -obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o -obj-$(CONFIG_I2C_I801) += i2c-i801.o -obj-$(CONFIG_I2C_ISCH) += i2c-isch.o -obj-$(CONFIG_I2C_NFORCE2) += i2c-nforce2.o -obj-$(CONFIG_I2C_NFORCE2_S4985) += i2c-nforce2-s4985.o -obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o -obj-$(CONFIG_I2C_SIS5595) += i2c-sis5595.o -obj-$(CONFIG_I2C_SIS630) += i2c-sis630.o -obj-$(CONFIG_I2C_SIS96X) += i2c-sis96x.o -obj-$(CONFIG_I2C_VIA) += i2c-via.o -obj-$(CONFIG_I2C_VIAPRO) += i2c-viapro.o - -# Mac SMBus host controller drivers -obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o -obj-$(CONFIG_I2C_POWERMAC) += i2c-powermac.o - -# Embedded system I2C/SMBus host controller drivers -obj-$(CONFIG_I2C_AT91) += i2c-at91.o -obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o -obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o -obj-$(CONFIG_I2C_CPM) += i2c-cpm.o -obj-$(CONFIG_I2C_DAVINCI) += i2c-davinci.o -obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM) += i2c-designware-platform.o -i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o -obj-$(CONFIG_I2C_DESIGNWARE_PCI) += i2c-designware-pci.o -i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o -obj-$(CONFIG_I2C_EG20T) += i2c-eg20t.o -obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o -obj-$(CONFIG_I2C_HIGHLANDER) += i2c-highlander.o -obj-$(CONFIG_I2C_IBM_IIC) += i2c-ibm_iic.o -obj-$(CONFIG_I2C_IMX) += i2c-imx.o -obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o -obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o -obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o -obj-$(CONFIG_I2C_MPC) += i2c-mpc.o -obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o -obj-$(CONFIG_I2C_MXS) += i2c-mxs.o -obj-$(CONFIG_I2C_NOMADIK) += i2c-nomadik.o -obj-$(CONFIG_I2C_NUC900) += i2c-nuc900.o -obj-$(CONFIG_I2C_OCORES) += i2c-ocores.o -obj-$(CONFIG_I2C_OMAP) += i2c-omap.o -obj-$(CONFIG_I2C_PASEMI) += i2c-pasemi.o -obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o -obj-$(CONFIG_I2C_PMCMSP) += i2c-pmcmsp.o -obj-$(CONFIG_I2C_PNX) += i2c-pnx.o -obj-$(CONFIG_I2C_PUV3) += i2c-puv3.o -obj-$(CONFIG_I2C_PXA) += i2c-pxa.o -obj-$(CONFIG_I2C_PXA_PCI) += i2c-pxa-pci.o -obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o -obj-$(CONFIG_I2C_S6000) += i2c-s6000.o -obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o -obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o -obj-$(CONFIG_I2C_SIMTEC) += i2c-simtec.o -obj-$(CONFIG_I2C_SIRF) += i2c-sirf.o -obj-$(CONFIG_I2C_STU300) += i2c-stu300.o -obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o -obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o -obj-$(CONFIG_I2C_OCTEON) += i2c-octeon.o -obj-$(CONFIG_I2C_XILINX) += i2c-xiic.o -obj-$(CONFIG_I2C_XLR) += i2c-xlr.o - -# External I2C/SMBus adapter drivers -obj-$(CONFIG_I2C_DIOLAN_U2C) += i2c-diolan-u2c.o -obj-$(CONFIG_I2C_PARPORT) += i2c-parport.o -obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o -obj-$(CONFIG_I2C_TAOS_EVM) += i2c-taos-evm.o -obj-$(CONFIG_I2C_TINY_USB) += i2c-tiny-usb.o - -# Other I2C/SMBus bus drivers -obj-$(CONFIG_I2C_ACORN) += i2c-acorn.o -obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o -obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o -obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o -obj-$(CONFIG_I2C_STUB) += i2c-stub.o -obj-$(CONFIG_SCx200_ACB) += scx200_acb.o -obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o - -obj-$(CONFIG_I2C_WMT) += wmt-i2c-bus.o wmt-i2c-bus-1.o wmt-i2c-bus-2.o wmt-i2c-bus-3.o wmt-i2c-bus-4.o -obj-$(CONFIG_I2C_SLAVE_WMT) += wmt-i2c-slave-bus.o wmt-i2c-slave-bus-1.o -ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-acorn.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-acorn.c deleted file mode 100644 index ed9f48d5..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-acorn.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * linux/drivers/acorn/char/i2c.c - * - * Copyright (C) 2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * ARM IOC/IOMD i2c driver. - * - * On Acorn machines, the following i2c devices are on the bus: - * - PCF8583 real time clock & static RAM - */ -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/io.h> - -#include <mach/hardware.h> -#include <asm/hardware/ioc.h> - -#define FORCE_ONES 0xdc -#define SCL 0x02 -#define SDA 0x01 - -/* - * We must preserve all non-i2c output bits in IOC_CONTROL. - * Note also that we need to preserve the value of SCL and - * SDA outputs as well (which may be different from the - * values read back from IOC_CONTROL). - */ -static u_int force_ones; - -static void ioc_setscl(void *data, int state) -{ - u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); - u_int ones = force_ones; - - if (state) - ones |= SCL; - else - ones &= ~SCL; - - force_ones = ones; - - ioc_writeb(ioc_control | ones, IOC_CONTROL); -} - -static void ioc_setsda(void *data, int state) -{ - u_int ioc_control = ioc_readb(IOC_CONTROL) & ~(SCL | SDA); - u_int ones = force_ones; - - if (state) - ones |= SDA; - else - ones &= ~SDA; - - force_ones = ones; - - ioc_writeb(ioc_control | ones, IOC_CONTROL); -} - -static int ioc_getscl(void *data) -{ - return (ioc_readb(IOC_CONTROL) & SCL) != 0; -} - -static int ioc_getsda(void *data) -{ - return (ioc_readb(IOC_CONTROL) & SDA) != 0; -} - -static struct i2c_algo_bit_data ioc_data = { - .setsda = ioc_setsda, - .setscl = ioc_setscl, - .getsda = ioc_getsda, - .getscl = ioc_getscl, - .udelay = 80, - .timeout = HZ, -}; - -static struct i2c_adapter ioc_ops = { - .nr = 0, - .algo_data = &ioc_data, -}; - -static int __init i2c_ioc_init(void) -{ - force_ones = FORCE_ONES | SCL | SDA; - - return i2c_bit_add_numbered_bus(&ioc_ops); -} - -module_init(i2c_ioc_init); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1535.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1535.c deleted file mode 100644 index e66d248f..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1535.c +++ /dev/null @@ -1,552 +0,0 @@ -/* - * Copyright (c) 2000 Frodo Looijaard <frodol@dds.nl>, - * Philip Edelbrock <phil@netroedge.com>, - * Mark D. Studebaker <mdsxyz123@yahoo.com>, - * Dan Eaton <dan.eaton@rocketlogix.com> and - * Stephen Rousset <stephen.rousset@rocketlogix.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This is the driver for the SMB Host controller on - Acer Labs Inc. (ALI) M1535 South Bridge. - - The M1535 is a South bridge for portable systems. - It is very similar to the M15x3 South bridges also produced - by Acer Labs Inc. Some of the registers within the part - have moved and some have been redefined slightly. Additionally, - the sequencing of the SMBus transactions has been modified - to be more consistent with the sequencing recommended by - the manufacturer and observed through testing. These - changes are reflected in this driver and can be identified - by comparing this driver to the i2c-ali15x3 driver. - For an overview of these chips see http://www.acerlabs.com - - The SMB controller is part of the 7101 device, which is an - ACPI-compliant Power Management Unit (PMU). - - The whole 7101 device has to be enabled for the SMB to work. - You can't just enable the SMB alone. - The SMB and the ACPI have separate I/O spaces. - We make sure that the SMB is enabled. We leave the ACPI alone. - - This driver controls the SMB Host only. - - This driver does not use interrupts. -*/ - - -/* Note: we assume there can only be one ALI1535, with one SMBus interface */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> - - -/* ALI1535 SMBus address offsets */ -#define SMBHSTSTS (0 + ali1535_smba) -#define SMBHSTTYP (1 + ali1535_smba) -#define SMBHSTPORT (2 + ali1535_smba) -#define SMBHSTCMD (7 + ali1535_smba) -#define SMBHSTADD (3 + ali1535_smba) -#define SMBHSTDAT0 (4 + ali1535_smba) -#define SMBHSTDAT1 (5 + ali1535_smba) -#define SMBBLKDAT (6 + ali1535_smba) - -/* PCI Address Constants */ -#define SMBCOM 0x004 -#define SMBREV 0x008 -#define SMBCFG 0x0D1 -#define SMBBA 0x0E2 -#define SMBHSTCFG 0x0F0 -#define SMBCLK 0x0F2 - -/* Other settings */ -#define MAX_TIMEOUT 500 /* times 1/100 sec */ -#define ALI1535_SMB_IOSIZE 32 - -#define ALI1535_SMB_DEFAULTBASE 0x8040 - -/* ALI1535 address lock bits */ -#define ALI1535_LOCK 0x06 /* dwe */ - -/* ALI1535 command constants */ -#define ALI1535_QUICK 0x00 -#define ALI1535_BYTE 0x10 -#define ALI1535_BYTE_DATA 0x20 -#define ALI1535_WORD_DATA 0x30 -#define ALI1535_BLOCK_DATA 0x40 -#define ALI1535_I2C_READ 0x60 - -#define ALI1535_DEV10B_EN 0x80 /* Enable 10-bit addressing in */ - /* I2C read */ -#define ALI1535_T_OUT 0x08 /* Time-out Command (write) */ -#define ALI1535_A_HIGH_BIT9 0x08 /* Bit 9 of 10-bit address in */ - /* Alert-Response-Address */ - /* (read) */ -#define ALI1535_KILL 0x04 /* Kill Command (write) */ -#define ALI1535_A_HIGH_BIT8 0x04 /* Bit 8 of 10-bit address in */ - /* Alert-Response-Address */ - /* (read) */ - -#define ALI1535_D_HI_MASK 0x03 /* Mask for isolating bits 9-8 */ - /* of 10-bit address in I2C */ - /* Read Command */ - -/* ALI1535 status register bits */ -#define ALI1535_STS_IDLE 0x04 -#define ALI1535_STS_BUSY 0x08 /* host busy */ -#define ALI1535_STS_DONE 0x10 /* transaction complete */ -#define ALI1535_STS_DEV 0x20 /* device error */ -#define ALI1535_STS_BUSERR 0x40 /* bus error */ -#define ALI1535_STS_FAIL 0x80 /* failed bus transaction */ -#define ALI1535_STS_ERR 0xE0 /* all the bad error bits */ - -#define ALI1535_BLOCK_CLR 0x04 /* reset block data index */ - -/* ALI1535 device address register bits */ -#define ALI1535_RD_ADDR 0x01 /* Read/Write Bit in Device */ - /* Address field */ - /* -> Write = 0 */ - /* -> Read = 1 */ -#define ALI1535_SMBIO_EN 0x04 /* SMB I/O Space enable */ - -static struct pci_driver ali1535_driver; -static unsigned long ali1535_smba; -static unsigned short ali1535_offset; - -/* Detect whether a ALI1535 can be found, and initialize it, where necessary. - Note the differences between kernels with the old PCI BIOS interface and - newer kernels with the real PCI interface. In compat.h some things are - defined to make the transition easier. */ -static int __devinit ali1535_setup(struct pci_dev *dev) -{ - int retval; - unsigned char temp; - - /* Check the following things: - - SMB I/O address is initialized - - Device is enabled - - We can use the addresses - */ - - retval = pci_enable_device(dev); - if (retval) { - dev_err(&dev->dev, "ALI1535_smb can't enable device\n"); - goto exit; - } - - /* Determine the address of the SMBus area */ - pci_read_config_word(dev, SMBBA, &ali1535_offset); - dev_dbg(&dev->dev, "ALI1535_smb is at offset 0x%04x\n", ali1535_offset); - ali1535_offset &= (0xffff & ~(ALI1535_SMB_IOSIZE - 1)); - if (ali1535_offset == 0) { - dev_warn(&dev->dev, - "ALI1535_smb region uninitialized - upgrade BIOS?\n"); - retval = -ENODEV; - goto exit; - } - - if (pci_resource_flags(dev, 0) & IORESOURCE_IO) - ali1535_smba = pci_resource_start(dev, 0) + ali1535_offset; - else - ali1535_smba = ali1535_offset; - - retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE, - ali1535_driver.name); - if (retval) - goto exit; - - if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE, - ali1535_driver.name)) { - dev_err(&dev->dev, "ALI1535_smb region 0x%lx already in use!\n", - ali1535_smba); - retval = -EBUSY; - goto exit; - } - - /* check if whole device is enabled */ - pci_read_config_byte(dev, SMBCFG, &temp); - if ((temp & ALI1535_SMBIO_EN) == 0) { - dev_err(&dev->dev, "SMB device not enabled - upgrade BIOS?\n"); - retval = -ENODEV; - goto exit_free; - } - - /* Is SMB Host controller enabled? */ - pci_read_config_byte(dev, SMBHSTCFG, &temp); - if ((temp & 1) == 0) { - dev_err(&dev->dev, "SMBus controller not enabled - upgrade BIOS?\n"); - retval = -ENODEV; - goto exit_free; - } - - /* set SMB clock to 74KHz as recommended in data sheet */ - pci_write_config_byte(dev, SMBCLK, 0x20); - - /* - The interrupt routing for SMB is set up in register 0x77 in the - 1533 ISA Bridge device, NOT in the 7101 device. - Don't bother with finding the 1533 device and reading the register. - if ((....... & 0x0F) == 1) - dev_dbg(&dev->dev, "ALI1535 using Interrupt 9 for SMBus.\n"); - */ - pci_read_config_byte(dev, SMBREV, &temp); - dev_dbg(&dev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&dev->dev, "ALI1535_smba = 0x%lx\n", ali1535_smba); - - return 0; - -exit_free: - release_region(ali1535_smba, ALI1535_SMB_IOSIZE); -exit: - return retval; -} - -static int ali1535_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, TYP=%02x, " - "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - - /* get status */ - temp = inb_p(SMBHSTSTS); - - /* Make sure the SMBus host is ready to start transmitting */ - /* Check the busy bit first */ - if (temp & ALI1535_STS_BUSY) { - /* If the host controller is still busy, it may have timed out - * in the previous transaction, resulting in a "SMBus Timeout" - * printk. I've tried the following to reset a stuck busy bit. - * 1. Reset the controller with an KILL command. (this - * doesn't seem to clear the controller if an external - * device is hung) - * 2. Reset the controller and the other SMBus devices with a - * T_OUT command. (this clears the host busy bit if an - * external device is hung, but it comes back upon a new - * access to a device) - * 3. Disable and reenable the controller in SMBHSTCFG. Worst - * case, nothing seems to work except power reset. - */ - - /* Try resetting entire SMB bus, including other devices - This - * may not work either - it clears the BUSY bit but then the - * BUSY bit may come back on when you try and use the chip - * again. If that's the case you are stuck. - */ - dev_info(&adap->dev, - "Resetting entire SMB Bus to clear busy condition (%02x)\n", - temp); - outb_p(ALI1535_T_OUT, SMBHSTTYP); - temp = inb_p(SMBHSTSTS); - } - - /* now check the error bits and the busy bit */ - if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { - /* do a clear-on-write */ - outb_p(0xFF, SMBHSTSTS); - temp = inb_p(SMBHSTSTS); - if (temp & (ALI1535_STS_ERR | ALI1535_STS_BUSY)) { - /* This is probably going to be correctable only by a - * power reset as one of the bits now appears to be - * stuck */ - /* This may be a bus or device with electrical problems. */ - dev_err(&adap->dev, - "SMBus reset failed! (0x%02x) - controller or " - "device on bus is probably hung\n", temp); - return -EBUSY; - } - } else { - /* check and clear done bit */ - if (temp & ALI1535_STS_DONE) - outb_p(temp, SMBHSTSTS); - } - - /* start the transaction by writing anything to the start register */ - outb_p(0xFF, SMBHSTPORT); - - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - usleep_range(1000, 2000); - temp = inb_p(SMBHSTSTS); - } while (((temp & ALI1535_STS_BUSY) && !(temp & ALI1535_STS_IDLE)) - && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - result = -ETIMEDOUT; - dev_err(&adap->dev, "SMBus Timeout!\n"); - } - - if (temp & ALI1535_STS_FAIL) { - result = -EIO; - dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - } - - /* Unfortunately the ALI SMB controller maps "no response" and "bus - * collision" into a single bit. No response is the usual case so don't - * do a printk. This means that bus collisions go unreported. - */ - if (temp & ALI1535_STS_BUSERR) { - result = -ENXIO; - dev_dbg(&adap->dev, - "Error: no response or bus collision ADD=%02x\n", - inb_p(SMBHSTADD)); - } - - /* haven't ever seen this */ - if (temp & ALI1535_STS_DEV) { - result = -EIO; - dev_err(&adap->dev, "Error: device error\n"); - } - - /* check to see if the "command complete" indication is set */ - if (!(temp & ALI1535_STS_DONE)) { - result = -ETIMEDOUT; - dev_err(&adap->dev, "Error: command never completed\n"); - } - - dev_dbg(&adap->dev, "Transaction (post): STS=%02x, TYP=%02x, " - "CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMBHSTSTS), inb_p(SMBHSTTYP), inb_p(SMBHSTCMD), - inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - - /* take consequent actions for error conditions */ - if (!(temp & ALI1535_STS_DONE)) { - /* issue "kill" to reset host controller */ - outb_p(ALI1535_KILL, SMBHSTTYP); - outb_p(0xFF, SMBHSTSTS); - } else if (temp & ALI1535_STS_ERR) { - /* issue "timeout" to reset all devices on bus */ - outb_p(ALI1535_T_OUT, SMBHSTTYP); - outb_p(0xFF, SMBHSTSTS); - } - - return result; -} - -/* Return negative errno on error. */ -static s32 ali1535_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int i, len; - int temp; - int timeout; - s32 result = 0; - - /* make sure SMBus is idle */ - temp = inb_p(SMBHSTSTS); - for (timeout = 0; - (timeout < MAX_TIMEOUT) && !(temp & ALI1535_STS_IDLE); - timeout++) { - usleep_range(1000, 2000); - temp = inb_p(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT) - dev_warn(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); - - /* clear status register (clear-on-write) */ - outb_p(0xFF, SMBHSTSTS); - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI1535_QUICK; - outb_p(size, SMBHSTTYP); /* output command */ - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI1535_BYTE; - outb_p(size, SMBHSTTYP); /* output command */ - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI1535_BYTE_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI1535_WORD_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI1535_BLOCK_DATA; - outb_p(size, SMBHSTTYP); /* output command */ - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) { - len = 0; - data->block[0] = len; - } - if (len > 32) { - len = 32; - data->block[0] = len; - } - outb_p(len, SMBHSTDAT0); - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - result = -EOPNOTSUPP; - goto EXIT; - } - - result = ali1535_transaction(adap); - if (result) - goto EXIT; - - if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) { - result = 0; - goto EXIT; - } - - switch (size) { - case ALI1535_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI1535_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI1535_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case ALI1535_BLOCK_DATA: - len = inb_p(SMBHSTDAT0); - if (len > 32) - len = 32; - data->block[0] = len; - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTTYP) | ALI1535_BLOCK_CLR, SMBHSTTYP); - for (i = 1; i <= data->block[0]; i++) { - data->block[i] = inb_p(SMBBLKDAT); - dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", - len, i, data->block[i]); - } - break; - } -EXIT: - return result; -} - - -static u32 ali1535_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = ali1535_access, - .functionality = ali1535_func, -}; - -static struct i2c_adapter ali1535_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(ali1535_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, - { }, -}; - -MODULE_DEVICE_TABLE(pci, ali1535_ids); - -static int __devinit ali1535_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (ali1535_setup(dev)) { - dev_warn(&dev->dev, - "ALI1535 not detected, module not inserted.\n"); - return -ENODEV; - } - - /* set up the sysfs linkage to our parent device */ - ali1535_adapter.dev.parent = &dev->dev; - - snprintf(ali1535_adapter.name, sizeof(ali1535_adapter.name), - "SMBus ALI1535 adapter at %04x", ali1535_offset); - return i2c_add_adapter(&ali1535_adapter); -} - -static void __devexit ali1535_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&ali1535_adapter); - release_region(ali1535_smba, ALI1535_SMB_IOSIZE); -} - -static struct pci_driver ali1535_driver = { - .name = "ali1535_smbus", - .id_table = ali1535_ids, - .probe = ali1535_probe, - .remove = __devexit_p(ali1535_remove), -}; - -static int __init i2c_ali1535_init(void) -{ - return pci_register_driver(&ali1535_driver); -} - -static void __exit i2c_ali1535_exit(void) -{ - pci_unregister_driver(&ali1535_driver); -} - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, " - "Philip Edelbrock <phil@netroedge.com>, " - "Mark D. Studebaker <mdsxyz123@yahoo.com> " - "and Dan Eaton <dan.eaton@rocketlogix.com>"); -MODULE_DESCRIPTION("ALI1535 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ali1535_init); -module_exit(i2c_ali1535_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1563.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1563.c deleted file mode 100644 index 47ae0091..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali1563.c +++ /dev/null @@ -1,448 +0,0 @@ -/** - * i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge - * - * Copyright (C) 2004 Patrick Mochel - * 2005 Rudolf Marek <r.marek@assembler.cz> - * - * The 1563 southbridge is deceptively similar to the 1533, with a - * few notable exceptions. One of those happens to be the fact they - * upgraded the i2c core to be 2.0 compliant, and happens to be almost - * identical to the i2c controller found in the Intel 801 south - * bridges. - * - * This driver is based on a mix of the 15x3, 1535, and i801 drivers, - * with a little help from the ALi 1563 spec. - * - * This file is released under the GPLv2 - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/acpi.h> - -#define ALI1563_MAX_TIMEOUT 500 -#define ALI1563_SMBBA 0x80 -#define ALI1563_SMB_IOEN 1 -#define ALI1563_SMB_HOSTEN 2 -#define ALI1563_SMB_IOSIZE 16 - -#define SMB_HST_STS (ali1563_smba + 0) -#define SMB_HST_CNTL1 (ali1563_smba + 1) -#define SMB_HST_CNTL2 (ali1563_smba + 2) -#define SMB_HST_CMD (ali1563_smba + 3) -#define SMB_HST_ADD (ali1563_smba + 4) -#define SMB_HST_DAT0 (ali1563_smba + 5) -#define SMB_HST_DAT1 (ali1563_smba + 6) -#define SMB_BLK_DAT (ali1563_smba + 7) - -#define HST_STS_BUSY 0x01 -#define HST_STS_INTR 0x02 -#define HST_STS_DEVERR 0x04 -#define HST_STS_BUSERR 0x08 -#define HST_STS_FAIL 0x10 -#define HST_STS_DONE 0x80 -#define HST_STS_BAD 0x1c - - -#define HST_CNTL1_TIMEOUT 0x80 -#define HST_CNTL1_LAST 0x40 - -#define HST_CNTL2_KILL 0x04 -#define HST_CNTL2_START 0x40 -#define HST_CNTL2_QUICK 0x00 -#define HST_CNTL2_BYTE 0x01 -#define HST_CNTL2_BYTE_DATA 0x02 -#define HST_CNTL2_WORD_DATA 0x03 -#define HST_CNTL2_BLOCK 0x05 - - -#define HST_CNTL2_SIZEMASK 0x38 - -static struct pci_driver ali1563_pci_driver; -static unsigned short ali1563_smba; - -static int ali1563_transaction(struct i2c_adapter * a, int size) -{ - u32 data; - int timeout; - int status = -EIO; - - dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) { - dev_err(&a->dev, "ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) - return -EBUSY; - } - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); - - timeout = ALI1563_MAX_TIMEOUT; - do { - msleep(1); - } while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout); - - dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - if (timeout && !(data & HST_STS_BAD)) - return 0; - - if (!timeout) { - dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n"); - /* Issue 'kill' to host controller */ - outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2); - data = inb_p(SMB_HST_STS); - status = -ETIMEDOUT; - } - - /* device error - no response, ignore the autodetection case */ - if (data & HST_STS_DEVERR) { - if (size != HST_CNTL2_QUICK) - dev_err(&a->dev, "Device error!\n"); - status = -ENXIO; - } - /* bus collision */ - if (data & HST_STS_BUSERR) { - dev_err(&a->dev, "Bus collision!\n"); - /* Issue timeout, hoping it helps */ - outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1); - } - - if (data & HST_STS_FAIL) { - dev_err(&a->dev, "Cleaning fail after KILL!\n"); - outb_p(0x0,SMB_HST_CNTL2); - } - - return status; -} - -static int ali1563_block_start(struct i2c_adapter * a) -{ - u32 data; - int timeout; - int status = -EIO; - - dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) { - dev_warn(&a->dev,"ali1563: Trying to reset busy device\n"); - outb_p(data | HST_STS_BAD,SMB_HST_STS); - data = inb_p(SMB_HST_STS); - if (data & HST_STS_BAD) - return -EBUSY; - } - - /* Clear byte-ready bit */ - outb_p(data | HST_STS_DONE, SMB_HST_STS); - - /* Start transaction and wait for byte-ready bit to be set */ - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2); - - timeout = ALI1563_MAX_TIMEOUT; - do { - msleep(1); - } while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout); - - dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, " - "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n", - inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2), - inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0), - inb_p(SMB_HST_DAT1)); - - if (timeout && !(data & HST_STS_BAD)) - return 0; - - if (timeout == 0) - status = -ETIMEDOUT; - - if (data & HST_STS_DEVERR) - status = -ENXIO; - - dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n", - timeout ? "" : "Timeout ", - data & HST_STS_FAIL ? "Transaction Failed " : "", - data & HST_STS_BUSERR ? "No response or Bus Collision " : "", - data & HST_STS_DEVERR ? "Device Error " : "", - !(data & HST_STS_DONE) ? "Transaction Never Finished " : ""); - return status; -} - -static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw) -{ - int i, len; - int error = 0; - - /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); - - if (rw == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 1) - len = 1; - else if (len > 32) - len = 32; - outb_p(len,SMB_HST_DAT0); - outb_p(data->block[1],SMB_BLK_DAT); - } else - len = 32; - - outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2); - - for (i = 0; i < len; i++) { - if (rw == I2C_SMBUS_WRITE) { - outb_p(data->block[i + 1], SMB_BLK_DAT); - if ((error = ali1563_block_start(a))) - break; - } else { - if ((error = ali1563_block_start(a))) - break; - if (i == 0) { - len = inb_p(SMB_HST_DAT0); - if (len < 1) - len = 1; - else if (len > 32) - len = 32; - } - data->block[i+1] = inb_p(SMB_BLK_DAT); - } - } - /* Do we need this? */ - outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1); - return error; -} - -static s32 ali1563_access(struct i2c_adapter * a, u16 addr, - unsigned short flags, char rw, u8 cmd, - int size, union i2c_smbus_data * data) -{ - int error = 0; - int timeout; - u32 reg; - - for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) { - if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY)) - break; - } - if (!timeout) - dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg); - outb_p(0xff,SMB_HST_STS); - - /* Map the size to what the chip understands */ - switch (size) { - case I2C_SMBUS_QUICK: - size = HST_CNTL2_QUICK; - break; - case I2C_SMBUS_BYTE: - size = HST_CNTL2_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - size = HST_CNTL2_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - size = HST_CNTL2_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - size = HST_CNTL2_BLOCK; - break; - default: - dev_warn(&a->dev, "Unsupported transaction %d\n", size); - error = -EOPNOTSUPP; - goto Done; - } - - outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD); - outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2); - - /* Write the command register */ - - switch(size) { - case HST_CNTL2_BYTE: - if (rw== I2C_SMBUS_WRITE) - /* Beware it uses DAT0 register and not CMD! */ - outb_p(cmd, SMB_HST_DAT0); - break; - case HST_CNTL2_BYTE_DATA: - outb_p(cmd, SMB_HST_CMD); - if (rw == I2C_SMBUS_WRITE) - outb_p(data->byte, SMB_HST_DAT0); - break; - case HST_CNTL2_WORD_DATA: - outb_p(cmd, SMB_HST_CMD); - if (rw == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMB_HST_DAT0); - outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1); - } - break; - case HST_CNTL2_BLOCK: - outb_p(cmd, SMB_HST_CMD); - error = ali1563_block(a,data,rw); - goto Done; - } - - if ((error = ali1563_transaction(a, size))) - goto Done; - - if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK)) - goto Done; - - switch (size) { - case HST_CNTL2_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMB_HST_DAT0); - break; - case HST_CNTL2_BYTE_DATA: - data->byte = inb_p(SMB_HST_DAT0); - break; - case HST_CNTL2_WORD_DATA: - data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8); - break; - } -Done: - return error; -} - -static u32 ali1563_func(struct i2c_adapter * a) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - - -static int __devinit ali1563_setup(struct pci_dev * dev) -{ - u16 ctrl; - - pci_read_config_word(dev,ALI1563_SMBBA,&ctrl); - - /* SMB I/O Base in high 12 bits and must be aligned with the - * size of the I/O space. */ - ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1); - if (!ali1563_smba) { - dev_warn(&dev->dev,"ali1563_smba Uninitialized\n"); - goto Err; - } - - /* Check if device is enabled */ - if (!(ctrl & ALI1563_SMB_HOSTEN)) { - dev_warn(&dev->dev, "Host Controller not enabled\n"); - goto Err; - } - if (!(ctrl & ALI1563_SMB_IOEN)) { - dev_warn(&dev->dev, "I/O space not enabled, trying manually\n"); - pci_write_config_word(dev, ALI1563_SMBBA, - ctrl | ALI1563_SMB_IOEN); - pci_read_config_word(dev, ALI1563_SMBBA, &ctrl); - if (!(ctrl & ALI1563_SMB_IOEN)) { - dev_err(&dev->dev, "I/O space still not enabled, " - "giving up\n"); - goto Err; - } - } - - if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE, - ali1563_pci_driver.name)) - goto Err; - - if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE, - ali1563_pci_driver.name)) { - dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n", - ali1563_smba); - goto Err; - } - dev_info(&dev->dev, "Found ALi1563 SMBus at 0x%04x\n", ali1563_smba); - - return 0; -Err: - return -ENODEV; -} - -static void ali1563_shutdown(struct pci_dev *dev) -{ - release_region(ali1563_smba,ALI1563_SMB_IOSIZE); -} - -static const struct i2c_algorithm ali1563_algorithm = { - .smbus_xfer = ali1563_access, - .functionality = ali1563_func, -}; - -static struct i2c_adapter ali1563_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &ali1563_algorithm, -}; - -static int __devinit ali1563_probe(struct pci_dev * dev, - const struct pci_device_id * id_table) -{ - int error; - - if ((error = ali1563_setup(dev))) - goto exit; - ali1563_adapter.dev.parent = &dev->dev; - snprintf(ali1563_adapter.name, sizeof(ali1563_adapter.name), - "SMBus ALi 1563 Adapter @ %04x", ali1563_smba); - if ((error = i2c_add_adapter(&ali1563_adapter))) - goto exit_shutdown; - return 0; - -exit_shutdown: - ali1563_shutdown(dev); -exit: - dev_warn(&dev->dev, "ALi1563 SMBus probe failed (%d)\n", error); - return error; -} - -static void __devexit ali1563_remove(struct pci_dev * dev) -{ - i2c_del_adapter(&ali1563_adapter); - ali1563_shutdown(dev); -} - -static DEFINE_PCI_DEVICE_TABLE(ali1563_id_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1563) }, - {}, -}; - -MODULE_DEVICE_TABLE (pci, ali1563_id_table); - -static struct pci_driver ali1563_pci_driver = { - .name = "ali1563_smbus", - .id_table = ali1563_id_table, - .probe = ali1563_probe, - .remove = __devexit_p(ali1563_remove), -}; - -static int __init ali1563_init(void) -{ - return pci_register_driver(&ali1563_pci_driver); -} - -module_init(ali1563_init); - -static void __exit ali1563_exit(void) -{ - pci_unregister_driver(&ali1563_pci_driver); -} - -module_exit(ali1563_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali15x3.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali15x3.c deleted file mode 100644 index 087ea9ca..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ali15x3.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - Copyright (c) 1999 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> and - Mark D. Studebaker <mdsxyz123@yahoo.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This is the driver for the SMB Host controller on - Acer Labs Inc. (ALI) M1541 and M1543C South Bridges. - - The M1543C is a South bridge for desktop systems. - The M1533 is a South bridge for portable systems. - They are part of the following ALI chipsets: - "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge - with AGP and 100MHz CPU Front Side bus - "Aladdin V": Includes the M1541 Socket 7 North bridge - with AGP and 100MHz CPU Front Side bus - "Aladdin IV": Includes the M1541 Socket 7 North bridge - with host bus up to 83.3 MHz. - For an overview of these chips see http://www.acerlabs.com - - The M1533/M1543C devices appear as FOUR separate devices - on the PCI bus. An output of lspci will show something similar - to the following: - - 00:02.0 USB Controller: Acer Laboratories Inc. M5237 - 00:03.0 Bridge: Acer Laboratories Inc. M7101 - 00:07.0 ISA bridge: Acer Laboratories Inc. M1533 - 00:0f.0 IDE interface: Acer Laboratories Inc. M5229 - - The SMB controller is part of the 7101 device, which is an - ACPI-compliant Power Management Unit (PMU). - - The whole 7101 device has to be enabled for the SMB to work. - You can't just enable the SMB alone. - The SMB and the ACPI have separate I/O spaces. - We make sure that the SMB is enabled. We leave the ACPI alone. - - This driver controls the SMB Host only. - The SMB Slave controller on the M15X3 is not enabled. - - This driver does not use interrupts. -*/ - -/* Note: we assume there can only be one ALI15X3, with one SMBus interface */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> - -/* ALI15X3 SMBus address offsets */ -#define SMBHSTSTS (0 + ali15x3_smba) -#define SMBHSTCNT (1 + ali15x3_smba) -#define SMBHSTSTART (2 + ali15x3_smba) -#define SMBHSTCMD (7 + ali15x3_smba) -#define SMBHSTADD (3 + ali15x3_smba) -#define SMBHSTDAT0 (4 + ali15x3_smba) -#define SMBHSTDAT1 (5 + ali15x3_smba) -#define SMBBLKDAT (6 + ali15x3_smba) - -/* PCI Address Constants */ -#define SMBCOM 0x004 -#define SMBBA 0x014 -#define SMBATPC 0x05B /* used to unlock xxxBA registers */ -#define SMBHSTCFG 0x0E0 -#define SMBSLVC 0x0E1 -#define SMBCLK 0x0E2 -#define SMBREV 0x008 - -/* Other settings */ -#define MAX_TIMEOUT 200 /* times 1/100 sec */ -#define ALI15X3_SMB_IOSIZE 32 - -/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB. - We don't use these here. If the bases aren't set to some value we - tell user to upgrade BIOS and we fail. -*/ -#define ALI15X3_SMB_DEFAULTBASE 0xE800 - -/* ALI15X3 address lock bits */ -#define ALI15X3_LOCK 0x06 - -/* ALI15X3 command constants */ -#define ALI15X3_ABORT 0x02 -#define ALI15X3_T_OUT 0x04 -#define ALI15X3_QUICK 0x00 -#define ALI15X3_BYTE 0x10 -#define ALI15X3_BYTE_DATA 0x20 -#define ALI15X3_WORD_DATA 0x30 -#define ALI15X3_BLOCK_DATA 0x40 -#define ALI15X3_BLOCK_CLR 0x80 - -/* ALI15X3 status register bits */ -#define ALI15X3_STS_IDLE 0x04 -#define ALI15X3_STS_BUSY 0x08 -#define ALI15X3_STS_DONE 0x10 -#define ALI15X3_STS_DEV 0x20 /* device error */ -#define ALI15X3_STS_COLL 0x40 /* collision or no response */ -#define ALI15X3_STS_TERM 0x80 /* terminated by abort */ -#define ALI15X3_STS_ERR 0xE0 /* all the bad error bits */ - - -/* If force_addr is set to anything different from 0, we forcibly enable - the device at the given address. */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Initialize the base address of the i2c controller"); - -static struct pci_driver ali15x3_driver; -static unsigned short ali15x3_smba; - -static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev) -{ - u16 a; - unsigned char temp; - - /* Check the following things: - - SMB I/O address is initialized - - Device is enabled - - We can use the addresses - */ - - /* Unlock the register. - The data sheet says that the address registers are read-only - if the lock bits are 1, but in fact the address registers - are zero unless you clear the lock bits. - */ - pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp); - if (temp & ALI15X3_LOCK) { - temp &= ~ALI15X3_LOCK; - pci_write_config_byte(ALI15X3_dev, SMBATPC, temp); - } - - /* Determine the address of the SMBus area */ - pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba); - ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1)); - if (ali15x3_smba == 0 && force_addr == 0) { - dev_err(&ALI15X3_dev->dev, "ALI15X3_smb region uninitialized " - "- upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if(force_addr) - ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1); - - if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, - ali15x3_driver.name)) - return -EBUSY; - - if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, - ali15x3_driver.name)) { - dev_err(&ALI15X3_dev->dev, - "ALI15X3_smb region 0x%x already in use!\n", - ali15x3_smba); - return -ENODEV; - } - - if(force_addr) { - dev_info(&ALI15X3_dev->dev, "forcing ISA address 0x%04X\n", - ali15x3_smba); - if (PCIBIOS_SUCCESSFUL != pci_write_config_word(ALI15X3_dev, - SMBBA, - ali15x3_smba)) - goto error; - if (PCIBIOS_SUCCESSFUL != pci_read_config_word(ALI15X3_dev, - SMBBA, &a)) - goto error; - if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) { - /* make sure it works */ - dev_err(&ALI15X3_dev->dev, - "force address failed - not supported?\n"); - goto error; - } - } - /* check if whole device is enabled */ - pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp); - if ((temp & 1) == 0) { - dev_info(&ALI15X3_dev->dev, "enabling SMBus device\n"); - pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01); - } - - /* Is SMB Host controller enabled? */ - pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp); - if ((temp & 1) == 0) { - dev_info(&ALI15X3_dev->dev, "enabling SMBus controller\n"); - pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01); - } - - /* set SMB clock to 74KHz as recommended in data sheet */ - pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20); - - /* - The interrupt routing for SMB is set up in register 0x77 in the - 1533 ISA Bridge device, NOT in the 7101 device. - Don't bother with finding the 1533 device and reading the register. - if ((....... & 0x0F) == 1) - dev_dbg(&ALI15X3_dev->dev, "ALI15X3 using Interrupt 9 for SMBus.\n"); - */ - pci_read_config_byte(ALI15X3_dev, SMBREV, &temp); - dev_dbg(&ALI15X3_dev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&ALI15X3_dev->dev, "iALI15X3_smba = 0x%X\n", ali15x3_smba); - - return 0; -error: - release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); - return -ENODEV; -} - -/* Another internally used function */ -static int ali15x3_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&adap->dev, "Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - - /* get status */ - temp = inb_p(SMBHSTSTS); - - /* Make sure the SMBus host is ready to start transmitting */ - /* Check the busy bit first */ - if (temp & ALI15X3_STS_BUSY) { - /* - If the host controller is still busy, it may have timed out in the - previous transaction, resulting in a "SMBus Timeout" Dev. - I've tried the following to reset a stuck busy bit. - 1. Reset the controller with an ABORT command. - (this doesn't seem to clear the controller if an external - device is hung) - 2. Reset the controller and the other SMBus devices with a - T_OUT command. (this clears the host busy bit if an - external device is hung, but it comes back upon a new access - to a device) - 3. Disable and reenable the controller in SMBHSTCFG - Worst case, nothing seems to work except power reset. - */ - /* Abort - reset the host controller */ - /* - Try resetting entire SMB bus, including other devices - - This may not work either - it clears the BUSY bit but - then the BUSY bit may come back on when you try and use the chip again. - If that's the case you are stuck. - */ - dev_info(&adap->dev, "Resetting entire SMB Bus to " - "clear busy condition (%02x)\n", temp); - outb_p(ALI15X3_T_OUT, SMBHSTCNT); - temp = inb_p(SMBHSTSTS); - } - - /* now check the error bits and the busy bit */ - if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { - /* do a clear-on-write */ - outb_p(0xFF, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) & - (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) { - /* this is probably going to be correctable only by a power reset - as one of the bits now appears to be stuck */ - /* This may be a bus or device with electrical problems. */ - dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - " - "controller or device on bus is probably hung\n", - temp); - return -EBUSY; - } - } else { - /* check and clear done bit */ - if (temp & ALI15X3_STS_DONE) { - outb_p(temp, SMBHSTSTS); - } - } - - /* start the transaction by writing anything to the start register */ - outb_p(0xFF, SMBHSTSTART); - - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE))) - && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - result = -ETIMEDOUT; - dev_err(&adap->dev, "SMBus Timeout!\n"); - } - - if (temp & ALI15X3_STS_TERM) { - result = -EIO; - dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - } - - /* - Unfortunately the ALI SMB controller maps "no response" and "bus - collision" into a single bit. No response is the usual case so don't - do a printk. - This means that bus collisions go unreported. - */ - if (temp & ALI15X3_STS_COLL) { - result = -ENXIO; - dev_dbg(&adap->dev, - "Error: no response or bus collision ADD=%02x\n", - inb_p(SMBHSTADD)); - } - - /* haven't ever seen this */ - if (temp & ALI15X3_STS_DEV) { - result = -EIO; - dev_err(&adap->dev, "Error: device error\n"); - } - dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), - inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD), - inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1)); - return result; -} - -/* Return negative errno on error. */ -static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data * data) -{ - int i, len; - int temp; - int timeout; - - /* clear all the bits (clear-on-write) */ - outb_p(0xFF, SMBHSTSTS); - /* make sure SMBus is idle */ - temp = inb_p(SMBHSTSTS); - for (timeout = 0; - (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE); - timeout++) { - msleep(1); - temp = inb_p(SMBHSTSTS); - } - if (timeout >= MAX_TIMEOUT) { - dev_err(&adap->dev, "Idle wait Timeout! STS=0x%02x\n", temp); - } - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - size = ALI15X3_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = ALI15X3_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = ALI15X3_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = ALI15X3_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) { - len = 0; - data->block[0] = len; - } - if (len > 32) { - len = 32; - data->block[0] = len; - } - outb_p(len, SMBHSTDAT0); - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = ALI15X3_BLOCK_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - outb_p(size, SMBHSTCNT); /* output command */ - - temp = ali15x3_transaction(adap); - if (temp) - return temp; - - if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK)) - return 0; - - - switch (size) { - case ALI15X3_BYTE: /* Result put in SMBHSTDAT0 */ - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI15X3_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case ALI15X3_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case ALI15X3_BLOCK_DATA: - len = inb_p(SMBHSTDAT0); - if (len > 32) - len = 32; - data->block[0] = len; - /* Reset SMBBLKDAT */ - outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT); - for (i = 1; i <= data->block[0]; i++) { - data->block[i] = inb_p(SMBBLKDAT); - dev_dbg(&adap->dev, "Blk: len=%d, i=%d, data=%02x\n", - len, i, data->block[i]); - } - break; - } - return 0; -} - -static u32 ali15x3_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = ali15x3_access, - .functionality = ali15x3_func, -}; - -static struct i2c_adapter ali15x3_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(ali15x3_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, ali15x3_ids); - -static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (ali15x3_setup(dev)) { - dev_err(&dev->dev, - "ALI15X3 not detected, module not inserted.\n"); - return -ENODEV; - } - - /* set up the sysfs linkage to our parent device */ - ali15x3_adapter.dev.parent = &dev->dev; - - snprintf(ali15x3_adapter.name, sizeof(ali15x3_adapter.name), - "SMBus ALI15X3 adapter at %04x", ali15x3_smba); - return i2c_add_adapter(&ali15x3_adapter); -} - -static void __devexit ali15x3_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&ali15x3_adapter); - release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE); -} - -static struct pci_driver ali15x3_driver = { - .name = "ali15x3_smbus", - .id_table = ali15x3_ids, - .probe = ali15x3_probe, - .remove = __devexit_p(ali15x3_remove), -}; - -static int __init i2c_ali15x3_init(void) -{ - return pci_register_driver(&ali15x3_driver); -} - -static void __exit i2c_ali15x3_exit(void) -{ - pci_unregister_driver(&ali15x3_driver); -} - -MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl>, " - "Philip Edelbrock <phil@netroedge.com>, " - "and Mark D. Studebaker <mdsxyz123@yahoo.com>"); -MODULE_DESCRIPTION("ALI15X3 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_ali15x3_init); -module_exit(i2c_ali15x3_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756-s4882.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756-s4882.c deleted file mode 100644 index 378fcb5d..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756-s4882.c +++ /dev/null @@ -1,262 +0,0 @@ -/* - * i2c-amd756-s4882.c - i2c-amd756 extras for the Tyan S4882 motherboard - * - * Copyright (C) 2004, 2008 Jean Delvare <khali@linux-fr.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * We select the channels by sending commands to the Philips - * PCA9556 chip at I2C address 0x18. The main adapter is used for - * the non-multiplexed part of the bus, and 4 virtual adapters - * are defined for the multiplexed addresses: 0x50-0x53 (memory - * module EEPROM) located on channels 1-4, and 0x4c (LM63) - * located on multiplexed channels 0 and 5-7. We define one - * virtual adapter per CPU, which corresponds to two multiplexed - * channels: - * CPU0: virtual adapter 1, channels 1 and 0 - * CPU1: virtual adapter 2, channels 2 and 5 - * CPU2: virtual adapter 3, channels 3 and 6 - * CPU3: virtual adapter 4, channels 4 and 7 - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -extern struct i2c_adapter amd756_smbus; - -static struct i2c_adapter *s4882_adapter; -static struct i2c_algorithm *s4882_algo; - -/* Wrapper access functions for multiplexed SMBus */ -static DEFINE_MUTEX(amd756_lock); - -static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - int error; - - /* We exclude the multiplexed addresses */ - if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 - || addr == 0x18) - return -ENXIO; - - mutex_lock(&amd756_lock); - - error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - - mutex_unlock(&amd756_lock); - - return error; -} - -/* We remember the last used channels combination so as to only switch - channels when it is really needed. This greatly reduces the SMBus - overhead, but also assumes that nobody will be writing to the PCA9556 - in our back. */ -static u8 last_channels; - -static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data, - u8 channels) -{ - int error; - - /* We exclude the non-multiplexed addresses */ - if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) - return -ENXIO; - - mutex_lock(&amd756_lock); - - if (last_channels != channels) { - union i2c_smbus_data mplxdata; - mplxdata.byte = channels; - - error = amd756_smbus.algo->smbus_xfer(adap, 0x18, 0, - I2C_SMBUS_WRITE, 0x01, - I2C_SMBUS_BYTE_DATA, - &mplxdata); - if (error) - goto UNLOCK; - last_channels = channels; - } - error = amd756_smbus.algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - -UNLOCK: - mutex_unlock(&amd756_lock); - return error; -} - -static s32 amd756_access_virt1(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU0: channels 1 and 0 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x03); -} - -static s32 amd756_access_virt2(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU1: channels 2 and 5 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x24); -} - -static s32 amd756_access_virt3(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU2: channels 3 and 6 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x48); -} - -static s32 amd756_access_virt4(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data * data) -{ - /* CPU3: channels 4 and 7 enabled */ - return amd756_access_channel(adap, addr, flags, read_write, command, - size, data, 0x90); -} - -static int __init amd756_s4882_init(void) -{ - int i, error; - union i2c_smbus_data ioconfig; - - if (!amd756_smbus.dev.parent) - return -ENODEV; - - /* Configure the PCA9556 multiplexer */ - ioconfig.byte = 0x00; /* All I/O to output mode */ - error = i2c_smbus_xfer(&amd756_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, - I2C_SMBUS_BYTE_DATA, &ioconfig); - if (error) { - dev_err(&amd756_smbus.dev, "PCA9556 configuration failed\n"); - error = -EIO; - goto ERROR0; - } - - /* Unregister physical bus */ - error = i2c_del_adapter(&amd756_smbus); - if (error) { - dev_err(&amd756_smbus.dev, "Physical bus removal failed\n"); - goto ERROR0; - } - - printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4882\n"); - /* Define the 5 virtual adapters and algorithms structures */ - if (!(s4882_adapter = kzalloc(5 * sizeof(struct i2c_adapter), - GFP_KERNEL))) { - error = -ENOMEM; - goto ERROR1; - } - if (!(s4882_algo = kzalloc(5 * sizeof(struct i2c_algorithm), - GFP_KERNEL))) { - error = -ENOMEM; - goto ERROR2; - } - - /* Fill in the new structures */ - s4882_algo[0] = *(amd756_smbus.algo); - s4882_algo[0].smbus_xfer = amd756_access_virt0; - s4882_adapter[0] = amd756_smbus; - s4882_adapter[0].algo = s4882_algo; - s4882_adapter[0].dev.parent = amd756_smbus.dev.parent; - for (i = 1; i < 5; i++) { - s4882_algo[i] = *(amd756_smbus.algo); - s4882_adapter[i] = amd756_smbus; - snprintf(s4882_adapter[i].name, sizeof(s4882_adapter[i].name), - "SMBus 8111 adapter (CPU%d)", i-1); - s4882_adapter[i].algo = s4882_algo+i; - s4882_adapter[i].dev.parent = amd756_smbus.dev.parent; - } - s4882_algo[1].smbus_xfer = amd756_access_virt1; - s4882_algo[2].smbus_xfer = amd756_access_virt2; - s4882_algo[3].smbus_xfer = amd756_access_virt3; - s4882_algo[4].smbus_xfer = amd756_access_virt4; - - /* Register virtual adapters */ - for (i = 0; i < 5; i++) { - error = i2c_add_adapter(s4882_adapter+i); - if (error) { - printk(KERN_ERR "i2c-amd756-s4882: " - "Virtual adapter %d registration " - "failed, module not inserted\n", i); - for (i--; i >= 0; i--) - i2c_del_adapter(s4882_adapter+i); - goto ERROR3; - } - } - - return 0; - -ERROR3: - kfree(s4882_algo); - s4882_algo = NULL; -ERROR2: - kfree(s4882_adapter); - s4882_adapter = NULL; -ERROR1: - /* Restore physical bus */ - i2c_add_adapter(&amd756_smbus); -ERROR0: - return error; -} - -static void __exit amd756_s4882_exit(void) -{ - if (s4882_adapter) { - int i; - - for (i = 0; i < 5; i++) - i2c_del_adapter(s4882_adapter+i); - kfree(s4882_adapter); - s4882_adapter = NULL; - } - kfree(s4882_algo); - s4882_algo = NULL; - - /* Restore physical bus */ - if (i2c_add_adapter(&amd756_smbus)) - printk(KERN_ERR "i2c-amd756-s4882: " - "Physical bus restoration failed\n"); -} - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("S4882 SMBus multiplexing"); -MODULE_LICENSE("GPL"); - -module_init(amd756_s4882_init); -module_exit(amd756_s4882_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c deleted file mode 100644 index eb778bf1..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd756.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org> - - Shamelessly ripped from i2c-piix4.c: - - Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - 2002-04-08: Added nForce support. (Csaba Halasz) - 2002-10-03: Fixed nForce PnP I/O port. (Michael Steil) - 2002-12-28: Rewritten into something that resembles a Linux driver (hch) - 2003-11-29: Added back AMD8111 removed by the previous rewrite. - (Philip Pokorny) -*/ - -/* - Supports AMD756, AMD766, AMD768, AMD8111 and nVidia nForce - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> - -/* AMD756 SMBus address offsets */ -#define SMB_ADDR_OFFSET 0xE0 -#define SMB_IOSIZE 16 -#define SMB_GLOBAL_STATUS (0x0 + amd756_ioport) -#define SMB_GLOBAL_ENABLE (0x2 + amd756_ioport) -#define SMB_HOST_ADDRESS (0x4 + amd756_ioport) -#define SMB_HOST_DATA (0x6 + amd756_ioport) -#define SMB_HOST_COMMAND (0x8 + amd756_ioport) -#define SMB_HOST_BLOCK_DATA (0x9 + amd756_ioport) -#define SMB_HAS_DATA (0xA + amd756_ioport) -#define SMB_HAS_DEVICE_ADDRESS (0xC + amd756_ioport) -#define SMB_HAS_HOST_ADDRESS (0xE + amd756_ioport) -#define SMB_SNOOP_ADDRESS (0xF + amd756_ioport) - -/* PCI Address Constants */ - -/* address of I/O space */ -#define SMBBA 0x058 /* mh */ -#define SMBBANFORCE 0x014 - -/* general configuration */ -#define SMBGCFG 0x041 /* mh */ - -/* silicon revision code */ -#define SMBREV 0x008 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* AMD756 constants */ -#define AMD756_QUICK 0x00 -#define AMD756_BYTE 0x01 -#define AMD756_BYTE_DATA 0x02 -#define AMD756_WORD_DATA 0x03 -#define AMD756_PROCESS_CALL 0x04 -#define AMD756_BLOCK_DATA 0x05 - -static struct pci_driver amd756_driver; -static unsigned short amd756_ioport; - -/* - SMBUS event = I/O 28-29 bit 11 - see E0 for the status bits and enabled in E2 - -*/ -#define GS_ABRT_STS (1 << 0) -#define GS_COL_STS (1 << 1) -#define GS_PRERR_STS (1 << 2) -#define GS_HST_STS (1 << 3) -#define GS_HCYC_STS (1 << 4) -#define GS_TO_STS (1 << 5) -#define GS_SMB_STS (1 << 11) - -#define GS_CLEAR_STS (GS_ABRT_STS | GS_COL_STS | GS_PRERR_STS | \ - GS_HCYC_STS | GS_TO_STS ) - -#define GE_CYC_TYPE_MASK (7) -#define GE_HOST_STC (1 << 3) -#define GE_ABORT (1 << 5) - - -static int amd756_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&adap->dev, "Transaction (pre): GS=%04x, GE=%04x, ADD=%04x, " - "DAT=%04x\n", inw_p(SMB_GLOBAL_STATUS), - inw_p(SMB_GLOBAL_ENABLE), inw_p(SMB_HOST_ADDRESS), - inb_p(SMB_HOST_DATA)); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inw_p(SMB_GLOBAL_STATUS)) & (GS_HST_STS | GS_SMB_STS)) { - dev_dbg(&adap->dev, "SMBus busy (%04x). Waiting...\n", temp); - do { - msleep(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & (GS_HST_STS | GS_SMB_STS)) && - (timeout++ < MAX_TIMEOUT)); - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp); - goto abort; - } - timeout = 0; - } - - /* start the transaction by setting the start bit */ - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_HOST_STC, SMB_GLOBAL_ENABLE); - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = inw_p(SMB_GLOBAL_STATUS); - } while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "Completion timeout!\n"); - goto abort; - } - - if (temp & GS_PRERR_STS) { - result = -ENXIO; - dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n"); - } - - if (temp & GS_COL_STS) { - result = -EIO; - dev_warn(&adap->dev, "SMBus collision!\n"); - } - - if (temp & GS_TO_STS) { - result = -ETIMEDOUT; - dev_dbg(&adap->dev, "SMBus protocol timeout!\n"); - } - - if (temp & GS_HCYC_STS) - dev_dbg(&adap->dev, "SMBus protocol success!\n"); - - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - -#ifdef DEBUG - if (((temp = inw_p(SMB_GLOBAL_STATUS)) & GS_CLEAR_STS) != 0x00) { - dev_dbg(&adap->dev, - "Failed reset at end of transaction (%04x)\n", temp); - } -#endif - - dev_dbg(&adap->dev, - "Transaction (post): GS=%04x, GE=%04x, ADD=%04x, DAT=%04x\n", - inw_p(SMB_GLOBAL_STATUS), inw_p(SMB_GLOBAL_ENABLE), - inw_p(SMB_HOST_ADDRESS), inb_p(SMB_HOST_DATA)); - - return result; - - abort: - dev_warn(&adap->dev, "Sending abort\n"); - outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE); - msleep(100); - outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS); - return -EIO; -} - -/* Return negative errno on error. */ -static s32 amd756_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int i, len; - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - size = AMD756_QUICK; - break; - case I2C_SMBUS_BYTE: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMB_HOST_DATA); - size = AMD756_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->byte, SMB_HOST_DATA); - size = AMD756_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) - outw_p(data->word, SMB_HOST_DATA); /* TODO: endian???? */ - size = AMD756_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outw_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMB_HOST_ADDRESS); - outb_p(command, SMB_HOST_COMMAND); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - if (len > 32) - len = 32; - outw_p(len, SMB_HOST_DATA); - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], - SMB_HOST_BLOCK_DATA); - } - size = AMD756_BLOCK_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - /* How about enabling interrupts... */ - outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE); - - status = amd756_transaction(adap); - if (status) - return status; - - if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK)) - return 0; - - - switch (size) { - case AMD756_BYTE: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_BYTE_DATA: - data->byte = inw_p(SMB_HOST_DATA); - break; - case AMD756_WORD_DATA: - data->word = inw_p(SMB_HOST_DATA); /* TODO: endian???? */ - break; - case AMD756_BLOCK_DATA: - data->block[0] = inw_p(SMB_HOST_DATA) & 0x3f; - if(data->block[0] > 32) - data->block[0] = 32; - /* i = inw_p(SMBHSTCNT); Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMB_HOST_BLOCK_DATA); - break; - } - - return 0; -} - -static u32 amd756_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = amd756_access, - .functionality = amd756_func, -}; - -struct i2c_adapter amd756_smbus = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -enum chiptype { AMD756, AMD766, AMD768, NFORCE, AMD8111 }; -static const char* chipname[] = { - "AMD756", "AMD766", "AMD768", - "nVidia nForce", "AMD8111", -}; - -static DEFINE_PCI_DEVICE_TABLE(amd756_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_740B), - .driver_data = AMD756 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413), - .driver_data = AMD766 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_OPUS_7443), - .driver_data = AMD768 }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS), - .driver_data = AMD8111 }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_SMBUS), - .driver_data = NFORCE }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, amd756_ids); - -static int __devinit amd756_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int nforce = (id->driver_data == NFORCE); - int error; - u8 temp; - - if (amd756_ioport) { - dev_err(&pdev->dev, "Only one device supported " - "(you have a strange motherboard, btw)\n"); - return -ENODEV; - } - - if (nforce) { - if (PCI_FUNC(pdev->devfn) != 1) - return -ENODEV; - - pci_read_config_word(pdev, SMBBANFORCE, &amd756_ioport); - amd756_ioport &= 0xfffc; - } else { /* amd */ - if (PCI_FUNC(pdev->devfn) != 3) - return -ENODEV; - - pci_read_config_byte(pdev, SMBGCFG, &temp); - if ((temp & 128) == 0) { - dev_err(&pdev->dev, - "Error: SMBus controller I/O not enabled!\n"); - return -ENODEV; - } - - /* Determine the address of the SMBus areas */ - /* Technically it is a dword but... */ - pci_read_config_word(pdev, SMBBA, &amd756_ioport); - amd756_ioport &= 0xff00; - amd756_ioport += SMB_ADDR_OFFSET; - } - - error = acpi_check_region(amd756_ioport, SMB_IOSIZE, - amd756_driver.name); - if (error) - return -ENODEV; - - if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) { - dev_err(&pdev->dev, "SMB region 0x%x already in use!\n", - amd756_ioport); - return -ENODEV; - } - - pci_read_config_byte(pdev, SMBREV, &temp); - dev_dbg(&pdev->dev, "SMBREV = 0x%X\n", temp); - dev_dbg(&pdev->dev, "AMD756_smba = 0x%X\n", amd756_ioport); - - /* set up the sysfs linkage to our parent device */ - amd756_smbus.dev.parent = &pdev->dev; - - snprintf(amd756_smbus.name, sizeof(amd756_smbus.name), - "SMBus %s adapter at %04x", chipname[id->driver_data], - amd756_ioport); - - error = i2c_add_adapter(&amd756_smbus); - if (error) { - dev_err(&pdev->dev, - "Adapter registration failed, module not inserted\n"); - goto out_err; - } - - return 0; - - out_err: - release_region(amd756_ioport, SMB_IOSIZE); - return error; -} - -static void __devexit amd756_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&amd756_smbus); - release_region(amd756_ioport, SMB_IOSIZE); -} - -static struct pci_driver amd756_driver = { - .name = "amd756_smbus", - .id_table = amd756_ids, - .probe = amd756_probe, - .remove = __devexit_p(amd756_remove), -}; - -static int __init amd756_init(void) -{ - return pci_register_driver(&amd756_driver); -} - -static void __exit amd756_exit(void) -{ - pci_unregister_driver(&amd756_driver); -} - -MODULE_AUTHOR("Merlin Hughes <merlin@merlin.org>"); -MODULE_DESCRIPTION("AMD756/766/768/8111 and nVidia nForce SMBus driver"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(amd756_smbus); - -module_init(amd756_init) -module_exit(amd756_exit) diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd8111.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd8111.c deleted file mode 100644 index e5ac53b9..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-amd8111.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - * SMBus 2.0 driver for AMD-8111 IO-Hub. - * - * Copyright (c) 2002 Vojtech Pavlik - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2. - */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/acpi.h> -#include <linux/slab.h> -#include <linux/io.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Vojtech Pavlik <vojtech@suse.cz>"); -MODULE_DESCRIPTION("AMD8111 SMBus 2.0 driver"); - -struct amd_smbus { - struct pci_dev *dev; - struct i2c_adapter adapter; - int base; - int size; -}; - -static struct pci_driver amd8111_driver; - -/* - * AMD PCI control registers definitions. - */ - -#define AMD_PCI_MISC 0x48 - -#define AMD_PCI_MISC_SCI 0x04 /* deliver SCI */ -#define AMD_PCI_MISC_INT 0x02 /* deliver PCI IRQ */ -#define AMD_PCI_MISC_SPEEDUP 0x01 /* 16x clock speedup */ - -/* - * ACPI 2.0 chapter 13 PCI interface definitions. - */ - -#define AMD_EC_DATA 0x00 /* data register */ -#define AMD_EC_SC 0x04 /* status of controller */ -#define AMD_EC_CMD 0x04 /* command register */ -#define AMD_EC_ICR 0x08 /* interrupt control register */ - -#define AMD_EC_SC_SMI 0x04 /* smi event pending */ -#define AMD_EC_SC_SCI 0x02 /* sci event pending */ -#define AMD_EC_SC_BURST 0x01 /* burst mode enabled */ -#define AMD_EC_SC_CMD 0x08 /* byte in data reg is command */ -#define AMD_EC_SC_IBF 0x02 /* data ready for embedded controller */ -#define AMD_EC_SC_OBF 0x01 /* data ready for host */ - -#define AMD_EC_CMD_RD 0x80 /* read EC */ -#define AMD_EC_CMD_WR 0x81 /* write EC */ -#define AMD_EC_CMD_BE 0x82 /* enable burst mode */ -#define AMD_EC_CMD_BD 0x83 /* disable burst mode */ -#define AMD_EC_CMD_QR 0x84 /* query EC */ - -/* - * ACPI 2.0 chapter 13 access of registers of the EC - */ - -static int amd_ec_wait_write(struct amd_smbus *smbus) -{ - int timeout = 500; - - while ((inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_IBF) && --timeout) - udelay(1); - - if (!timeout) { - dev_warn(&smbus->dev->dev, - "Timeout while waiting for IBF to clear\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int amd_ec_wait_read(struct amd_smbus *smbus) -{ - int timeout = 500; - - while ((~inb(smbus->base + AMD_EC_SC) & AMD_EC_SC_OBF) && --timeout) - udelay(1); - - if (!timeout) { - dev_warn(&smbus->dev->dev, - "Timeout while waiting for OBF to set\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int amd_ec_read(struct amd_smbus *smbus, unsigned char address, - unsigned char *data) -{ - int status; - - status = amd_ec_wait_write(smbus); - if (status) - return status; - outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD); - - status = amd_ec_wait_write(smbus); - if (status) - return status; - outb(address, smbus->base + AMD_EC_DATA); - - status = amd_ec_wait_read(smbus); - if (status) - return status; - *data = inb(smbus->base + AMD_EC_DATA); - - return 0; -} - -static int amd_ec_write(struct amd_smbus *smbus, unsigned char address, - unsigned char data) -{ - int status; - - status = amd_ec_wait_write(smbus); - if (status) - return status; - outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD); - - status = amd_ec_wait_write(smbus); - if (status) - return status; - outb(address, smbus->base + AMD_EC_DATA); - - status = amd_ec_wait_write(smbus); - if (status) - return status; - outb(data, smbus->base + AMD_EC_DATA); - - return 0; -} - -/* - * ACPI 2.0 chapter 13 SMBus 2.0 EC register model - */ - -#define AMD_SMB_PRTCL 0x00 /* protocol, PEC */ -#define AMD_SMB_STS 0x01 /* status */ -#define AMD_SMB_ADDR 0x02 /* address */ -#define AMD_SMB_CMD 0x03 /* command */ -#define AMD_SMB_DATA 0x04 /* 32 data registers */ -#define AMD_SMB_BCNT 0x24 /* number of data bytes */ -#define AMD_SMB_ALRM_A 0x25 /* alarm address */ -#define AMD_SMB_ALRM_D 0x26 /* 2 bytes alarm data */ - -#define AMD_SMB_STS_DONE 0x80 -#define AMD_SMB_STS_ALRM 0x40 -#define AMD_SMB_STS_RES 0x20 -#define AMD_SMB_STS_STATUS 0x1f - -#define AMD_SMB_STATUS_OK 0x00 -#define AMD_SMB_STATUS_FAIL 0x07 -#define AMD_SMB_STATUS_DNAK 0x10 -#define AMD_SMB_STATUS_DERR 0x11 -#define AMD_SMB_STATUS_CMD_DENY 0x12 -#define AMD_SMB_STATUS_UNKNOWN 0x13 -#define AMD_SMB_STATUS_ACC_DENY 0x17 -#define AMD_SMB_STATUS_TIMEOUT 0x18 -#define AMD_SMB_STATUS_NOTSUP 0x19 -#define AMD_SMB_STATUS_BUSY 0x1A -#define AMD_SMB_STATUS_PEC 0x1F - -#define AMD_SMB_PRTCL_WRITE 0x00 -#define AMD_SMB_PRTCL_READ 0x01 -#define AMD_SMB_PRTCL_QUICK 0x02 -#define AMD_SMB_PRTCL_BYTE 0x04 -#define AMD_SMB_PRTCL_BYTE_DATA 0x06 -#define AMD_SMB_PRTCL_WORD_DATA 0x08 -#define AMD_SMB_PRTCL_BLOCK_DATA 0x0a -#define AMD_SMB_PRTCL_PROC_CALL 0x0c -#define AMD_SMB_PRTCL_BLOCK_PROC_CALL 0x0d -#define AMD_SMB_PRTCL_I2C_BLOCK_DATA 0x4a -#define AMD_SMB_PRTCL_PEC 0x80 - - -static s32 amd8111_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, u8 command, int size, - union i2c_smbus_data * data) -{ - struct amd_smbus *smbus = adap->algo_data; - unsigned char protocol, len, pec, temp[2]; - int i, status; - - protocol = (read_write == I2C_SMBUS_READ) ? AMD_SMB_PRTCL_READ - : AMD_SMB_PRTCL_WRITE; - pec = (flags & I2C_CLIENT_PEC) ? AMD_SMB_PRTCL_PEC : 0; - - switch (size) { - case I2C_SMBUS_QUICK: - protocol |= AMD_SMB_PRTCL_QUICK; - read_write = I2C_SMBUS_WRITE; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) { - status = amd_ec_write(smbus, AMD_SMB_CMD, - command); - if (status) - return status; - } - protocol |= AMD_SMB_PRTCL_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - if (read_write == I2C_SMBUS_WRITE) { - status = amd_ec_write(smbus, AMD_SMB_DATA, - data->byte); - if (status) - return status; - } - protocol |= AMD_SMB_PRTCL_BYTE_DATA; - break; - - case I2C_SMBUS_WORD_DATA: - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - if (read_write == I2C_SMBUS_WRITE) { - status = amd_ec_write(smbus, AMD_SMB_DATA, - data->word & 0xff); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_DATA + 1, - data->word >> 8); - if (status) - return status; - } - protocol |= AMD_SMB_PRTCL_WORD_DATA | pec; - break; - - case I2C_SMBUS_BLOCK_DATA: - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - if (read_write == I2C_SMBUS_WRITE) { - len = min_t(u8, data->block[0], - I2C_SMBUS_BLOCK_MAX); - status = amd_ec_write(smbus, AMD_SMB_BCNT, len); - if (status) - return status; - for (i = 0; i < len; i++) { - status = - amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); - if (status) - return status; - } - } - protocol |= AMD_SMB_PRTCL_BLOCK_DATA | pec; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = min_t(u8, data->block[0], - I2C_SMBUS_BLOCK_MAX); - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_BCNT, len); - if (status) - return status; - if (read_write == I2C_SMBUS_WRITE) - for (i = 0; i < len; i++) { - status = - amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); - if (status) - return status; - } - protocol |= AMD_SMB_PRTCL_I2C_BLOCK_DATA; - break; - - case I2C_SMBUS_PROC_CALL: - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_DATA, - data->word & 0xff); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_DATA + 1, - data->word >> 8); - if (status) - return status; - protocol = AMD_SMB_PRTCL_PROC_CALL | pec; - read_write = I2C_SMBUS_READ; - break; - - case I2C_SMBUS_BLOCK_PROC_CALL: - len = min_t(u8, data->block[0], - I2C_SMBUS_BLOCK_MAX - 1); - status = amd_ec_write(smbus, AMD_SMB_CMD, command); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_BCNT, len); - if (status) - return status; - for (i = 0; i < len; i++) { - status = amd_ec_write(smbus, AMD_SMB_DATA + i, - data->block[i + 1]); - if (status) - return status; - } - protocol = AMD_SMB_PRTCL_BLOCK_PROC_CALL | pec; - read_write = I2C_SMBUS_READ; - break; - - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - status = amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1); - if (status) - return status; - status = amd_ec_write(smbus, AMD_SMB_PRTCL, protocol); - if (status) - return status; - - status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - if (status) - return status; - - if (~temp[0] & AMD_SMB_STS_DONE) { - udelay(500); - status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - if (status) - return status; - } - - if (~temp[0] & AMD_SMB_STS_DONE) { - msleep(1); - status = amd_ec_read(smbus, AMD_SMB_STS, temp + 0); - if (status) - return status; - } - - if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS)) - return -EIO; - - if (read_write == I2C_SMBUS_WRITE) - return 0; - - switch (size) { - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - status = amd_ec_read(smbus, AMD_SMB_DATA, &data->byte); - if (status) - return status; - break; - - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - status = amd_ec_read(smbus, AMD_SMB_DATA, temp + 0); - if (status) - return status; - status = amd_ec_read(smbus, AMD_SMB_DATA + 1, temp + 1); - if (status) - return status; - data->word = (temp[1] << 8) | temp[0]; - break; - - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_BLOCK_PROC_CALL: - status = amd_ec_read(smbus, AMD_SMB_BCNT, &len); - if (status) - return status; - len = min_t(u8, len, I2C_SMBUS_BLOCK_MAX); - case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < len; i++) { - status = amd_ec_read(smbus, AMD_SMB_DATA + i, - data->block + i + 1); - if (status) - return status; - } - data->block[0] = len; - break; - } - - return 0; -} - - -static u32 amd8111_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA | - I2C_FUNC_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_PROC_CALL | - I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_PEC; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = amd8111_access, - .functionality = amd8111_func, -}; - - -static DEFINE_PCI_DEVICE_TABLE(amd8111_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_SMBUS2) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, amd8111_ids); - -static int __devinit amd8111_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - struct amd_smbus *smbus; - int error; - - if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) - return -ENODEV; - - smbus = kzalloc(sizeof(struct amd_smbus), GFP_KERNEL); - if (!smbus) - return -ENOMEM; - - smbus->dev = dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); - - error = acpi_check_resource_conflict(&dev->resource[0]); - if (error) { - error = -ENODEV; - goto out_kfree; - } - - if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) { - error = -EBUSY; - goto out_kfree; - } - - smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), - "SMBus2 AMD8111 adapter at %04x", smbus->base); - smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - - /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = &dev->dev; - - pci_write_config_dword(smbus->dev, AMD_PCI_MISC, 0); - error = i2c_add_adapter(&smbus->adapter); - if (error) - goto out_release_region; - - pci_set_drvdata(dev, smbus); - return 0; - - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void __devexit amd8111_remove(struct pci_dev *dev) -{ - struct amd_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(&smbus->adapter); - release_region(smbus->base, smbus->size); - kfree(smbus); -} - -static struct pci_driver amd8111_driver = { - .name = "amd8111_smbus2", - .id_table = amd8111_ids, - .probe = amd8111_probe, - .remove = __devexit_p(amd8111_remove), -}; - -static int __init i2c_amd8111_init(void) -{ - return pci_register_driver(&amd8111_driver); -} - -static void __exit i2c_amd8111_exit(void) -{ - pci_unregister_driver(&amd8111_driver); -} - -module_init(i2c_amd8111_init); -module_exit(i2c_amd8111_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-at91.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-at91.c deleted file mode 100644 index 1679deef..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-at91.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - i2c Support for Atmel's AT91 Two-Wire Interface (TWI) - - Copyright (C) 2004 Rick Bronson - Converted to 2.6 by Andrew Victor <andrew@sanpeople.com> - - Borrowed heavily from original work by: - Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. -*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/io.h> - -#include <mach/at91_twi.h> -#include <mach/board.h> -#include <mach/cpu.h> - -#define TWI_CLOCK 100000 /* Hz. max 400 Kbits/sec */ - - -static struct clk *twi_clk; -static void __iomem *twi_base; - -#define at91_twi_read(reg) __raw_readl(twi_base + (reg)) -#define at91_twi_write(reg, val) __raw_writel((val), twi_base + (reg)) - - -/* - * Initialize the TWI hardware registers. - */ -static void __devinit at91_twi_hwinit(void) -{ - unsigned long cdiv, ckdiv; - - at91_twi_write(AT91_TWI_IDR, 0xffffffff); /* Disable all interrupts */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_SWRST); /* Reset peripheral */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_MSEN); /* Set Master mode */ - - /* Calcuate clock dividers */ - cdiv = (clk_get_rate(twi_clk) / (2 * TWI_CLOCK)) - 3; - cdiv = cdiv + 1; /* round up */ - ckdiv = 0; - while (cdiv > 255) { - ckdiv++; - cdiv = cdiv >> 1; - } - - if (cpu_is_at91rm9200()) { /* AT91RM9200 Errata #22 */ - if (ckdiv > 5) { - printk(KERN_ERR "AT91 I2C: Invalid TWI_CLOCK value!\n"); - ckdiv = 5; - } - } - - at91_twi_write(AT91_TWI_CWGR, (ckdiv << 16) | (cdiv << 8) | cdiv); -} - -/* - * Poll the i2c status register until the specified bit is set. - * Returns 0 if timed out (100 msec). - */ -static short at91_poll_status(unsigned long bit) -{ - int loop_cntr = 10000; - - do { - udelay(10); - } while (!(at91_twi_read(AT91_TWI_SR) & bit) && (--loop_cntr > 0)); - - return (loop_cntr > 0); -} - -static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - /* Read data */ - while (length--) { - if (!length) /* need to send Stop before reading last byte */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - if (!at91_poll_status(AT91_TWI_RXRDY)) { - dev_dbg(&adap->dev, "RXRDY timeout\n"); - return -ETIMEDOUT; - } - *buf++ = (at91_twi_read(AT91_TWI_RHR) & 0xff); - } - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - /* Load first byte into transmitter */ - at91_twi_write(AT91_TWI_THR, *buf++); - - /* Send Start */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_START); - - do { - if (!at91_poll_status(AT91_TWI_TXRDY)) { - dev_dbg(&adap->dev, "TXRDY timeout\n"); - return -ETIMEDOUT; - } - - length--; /* byte was transmitted */ - - if (length > 0) /* more data to send? */ - at91_twi_write(AT91_TWI_THR, *buf++); - } while (length); - - /* Send Stop */ - at91_twi_write(AT91_TWI_CR, AT91_TWI_STOP); - - return 0; -} - -/* - * Generic i2c master transfer entrypoint. - * - * Note: We do not use Atmel's feature of storing the "internal device address". - * Instead the "internal device address" has to be written using a separate - * i2c message. - * http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-September/024411.html - */ -static int at91_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, int num) -{ - int i, ret; - - dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); - - for (i = 0; i < num; i++) { - dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, - pmsg->flags & I2C_M_RD ? "read" : "writ", - pmsg->len, pmsg->len > 1 ? "s" : "", - pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); - - at91_twi_write(AT91_TWI_MMR, (pmsg->addr << 16) - | ((pmsg->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); - - if (pmsg->len && pmsg->buf) { /* sanity check */ - if (pmsg->flags & I2C_M_RD) - ret = xfer_read(adap, pmsg->buf, pmsg->len); - else - ret = xfer_write(adap, pmsg->buf, pmsg->len); - - if (ret) - return ret; - - /* Wait until transfer is finished */ - if (!at91_poll_status(AT91_TWI_TXCOMP)) { - dev_dbg(&adap->dev, "TXCOMP timeout\n"); - return -ETIMEDOUT; - } - } - dev_dbg(&adap->dev, "transfer complete\n"); - pmsg++; /* next message */ - } - return i; -} - -/* - * Return list of supported functionality. - */ -static u32 at91_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm at91_algorithm = { - .master_xfer = at91_xfer, - .functionality = at91_func, -}; - -/* - * Main initialization routine. - */ -static int __devinit at91_i2c_probe(struct platform_device *pdev) -{ - struct i2c_adapter *adapter; - struct resource *res; - int rc; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; - - if (!request_mem_region(res->start, resource_size(res), "at91_i2c")) - return -EBUSY; - - twi_base = ioremap(res->start, resource_size(res)); - if (!twi_base) { - rc = -ENOMEM; - goto fail0; - } - - twi_clk = clk_get(NULL, "twi_clk"); - if (IS_ERR(twi_clk)) { - dev_err(&pdev->dev, "no clock defined\n"); - rc = -ENODEV; - goto fail1; - } - - adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (adapter == NULL) { - dev_err(&pdev->dev, "can't allocate inteface!\n"); - rc = -ENOMEM; - goto fail2; - } - snprintf(adapter->name, sizeof(adapter->name), "AT91"); - adapter->algo = &at91_algorithm; - adapter->class = I2C_CLASS_HWMON; - adapter->dev.parent = &pdev->dev; - /* adapter->id == 0 ... only one TWI controller for now */ - - platform_set_drvdata(pdev, adapter); - - clk_enable(twi_clk); /* enable peripheral clock */ - at91_twi_hwinit(); /* initialize TWI controller */ - - rc = i2c_add_numbered_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter %s registration failed\n", - adapter->name); - goto fail3; - } - - dev_info(&pdev->dev, "AT91 i2c bus driver.\n"); - return 0; - -fail3: - platform_set_drvdata(pdev, NULL); - kfree(adapter); - clk_disable(twi_clk); -fail2: - clk_put(twi_clk); -fail1: - iounmap(twi_base); -fail0: - release_mem_region(res->start, resource_size(res)); - - return rc; -} - -static int __devexit at91_i2c_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct resource *res; - int rc; - - rc = i2c_del_adapter(adapter); - platform_set_drvdata(pdev, NULL); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - iounmap(twi_base); - release_mem_region(res->start, resource_size(res)); - - clk_disable(twi_clk); /* disable peripheral clock */ - clk_put(twi_clk); - - return rc; -} - -#ifdef CONFIG_PM - -/* NOTE: could save a few mA by keeping clock off outside of at91_xfer... */ - -static int at91_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) -{ - clk_disable(twi_clk); - return 0; -} - -static int at91_i2c_resume(struct platform_device *pdev) -{ - return clk_enable(twi_clk); -} - -#else -#define at91_i2c_suspend NULL -#define at91_i2c_resume NULL -#endif - -static struct platform_driver at91_i2c_driver = { - .probe = at91_i2c_probe, - .remove = __devexit_p(at91_i2c_remove), - .suspend = at91_i2c_suspend, - .resume = at91_i2c_resume, - .driver = { - .name = "at91_i2c", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(at91_i2c_driver); - -MODULE_AUTHOR("Rick Bronson"); -MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:at91_i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-au1550.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-au1550.c deleted file mode 100644 index 582d616d..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-au1550.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * i2c-au1550.c: SMBus (i2c) adapter for Alchemy PSC interface - * Copyright (C) 2004 Embedded Edge, LLC <dan@embeddededge.com> - * - * 2.6 port by Matt Porter <mporter@kernel.crashing.org> - * - * The documentation describes this as an SMBus controller, but it doesn't - * understand any of the SMBus protocol in hardware. It's really an I2C - * controller that could emulate most of the SMBus in software. - * - * This is just a skeleton adapter to use with the Au1550 PSC - * algorithm. It was developed for the Pb1550, but will work with - * any Au1550 board that has a similar PSC configuration. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/delay.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/slab.h> - -#include <asm/mach-au1x00/au1000.h> -#include <asm/mach-au1x00/au1xxx_psc.h> - -#define PSC_SEL 0x00 -#define PSC_CTRL 0x04 -#define PSC_SMBCFG 0x08 -#define PSC_SMBMSK 0x0C -#define PSC_SMBPCR 0x10 -#define PSC_SMBSTAT 0x14 -#define PSC_SMBEVNT 0x18 -#define PSC_SMBTXRX 0x1C -#define PSC_SMBTMR 0x20 - -struct i2c_au1550_data { - void __iomem *psc_base; - int xfer_timeout; - struct i2c_adapter adap; - struct resource *ioarea; -}; - -static inline void WR(struct i2c_au1550_data *a, int r, unsigned long v) -{ - __raw_writel(v, a->psc_base + r); - wmb(); -} - -static inline unsigned long RD(struct i2c_au1550_data *a, int r) -{ - return __raw_readl(a->psc_base + r); -} - -static int wait_xfer_done(struct i2c_au1550_data *adap) -{ - int i; - - /* Wait for Tx Buffer Empty */ - for (i = 0; i < adap->xfer_timeout; i++) { - if (RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_TE) - return 0; - - udelay(1); - } - - return -ETIMEDOUT; -} - -static int wait_ack(struct i2c_au1550_data *adap) -{ - unsigned long stat; - - if (wait_xfer_done(adap)) - return -ETIMEDOUT; - - stat = RD(adap, PSC_SMBEVNT); - if ((stat & (PSC_SMBEVNT_DN | PSC_SMBEVNT_AN | PSC_SMBEVNT_AL)) != 0) - return -ETIMEDOUT; - - return 0; -} - -static int wait_master_done(struct i2c_au1550_data *adap) -{ - int i; - - /* Wait for Master Done. */ - for (i = 0; i < 2 * adap->xfer_timeout; i++) { - if ((RD(adap, PSC_SMBEVNT) & PSC_SMBEVNT_MD) != 0) - return 0; - udelay(1); - } - - return -ETIMEDOUT; -} - -static int -do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd, int q) -{ - unsigned long stat; - - /* Reset the FIFOs, clear events. */ - stat = RD(adap, PSC_SMBSTAT); - WR(adap, PSC_SMBEVNT, PSC_SMBEVNT_ALLCLR); - - if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) { - WR(adap, PSC_SMBPCR, PSC_SMBPCR_DC); - while ((RD(adap, PSC_SMBPCR) & PSC_SMBPCR_DC) != 0) - cpu_relax(); - udelay(50); - } - - /* Write out the i2c chip address and specify operation */ - addr <<= 1; - if (rd) - addr |= 1; - - /* zero-byte xfers stop immediately */ - if (q) - addr |= PSC_SMBTXRX_STP; - - /* Put byte into fifo, start up master. */ - WR(adap, PSC_SMBTXRX, addr); - WR(adap, PSC_SMBPCR, PSC_SMBPCR_MS); - if (wait_ack(adap)) - return -EIO; - return (q) ? wait_master_done(adap) : 0; -} - -static int wait_for_rx_byte(struct i2c_au1550_data *adap, unsigned char *out) -{ - int j; - - if (wait_xfer_done(adap)) - return -EIO; - - j = adap->xfer_timeout * 100; - do { - j--; - if (j <= 0) - return -EIO; - - if ((RD(adap, PSC_SMBSTAT) & PSC_SMBSTAT_RE) == 0) - j = 0; - else - udelay(1); - } while (j > 0); - - *out = RD(adap, PSC_SMBTXRX); - - return 0; -} - -static int i2c_read(struct i2c_au1550_data *adap, unsigned char *buf, - unsigned int len) -{ - int i; - - if (len == 0) - return 0; - - /* A read is performed by stuffing the transmit fifo with - * zero bytes for timing, waiting for bytes to appear in the - * receive fifo, then reading the bytes. - */ - i = 0; - while (i < (len - 1)) { - WR(adap, PSC_SMBTXRX, 0); - if (wait_for_rx_byte(adap, &buf[i])) - return -EIO; - - i++; - } - - /* The last byte has to indicate transfer done. */ - WR(adap, PSC_SMBTXRX, PSC_SMBTXRX_STP); - if (wait_master_done(adap)) - return -EIO; - - buf[i] = (unsigned char)(RD(adap, PSC_SMBTXRX) & 0xff); - return 0; -} - -static int i2c_write(struct i2c_au1550_data *adap, unsigned char *buf, - unsigned int len) -{ - int i; - unsigned long data; - - if (len == 0) - return 0; - - i = 0; - while (i < (len-1)) { - data = buf[i]; - WR(adap, PSC_SMBTXRX, data); - if (wait_ack(adap)) - return -EIO; - i++; - } - - /* The last byte has to indicate transfer done. */ - data = buf[i]; - data |= PSC_SMBTXRX_STP; - WR(adap, PSC_SMBTXRX, data); - if (wait_master_done(adap)) - return -EIO; - return 0; -} - -static int -au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) -{ - struct i2c_au1550_data *adap = i2c_adap->algo_data; - struct i2c_msg *p; - int i, err = 0; - - WR(adap, PSC_CTRL, PSC_CTRL_ENABLE); - - for (i = 0; !err && i < num; i++) { - p = &msgs[i]; - err = do_address(adap, p->addr, p->flags & I2C_M_RD, - (p->len == 0)); - if (err || !p->len) - continue; - if (p->flags & I2C_M_RD) - err = i2c_read(adap, p->buf, p->len); - else - err = i2c_write(adap, p->buf, p->len); - } - - /* Return the number of messages processed, or the error code. - */ - if (err == 0) - err = num; - - WR(adap, PSC_CTRL, PSC_CTRL_SUSPEND); - - return err; -} - -static u32 au1550_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm au1550_algo = { - .master_xfer = au1550_xfer, - .functionality = au1550_func, -}; - -static void i2c_au1550_setup(struct i2c_au1550_data *priv) -{ - unsigned long cfg; - - WR(priv, PSC_CTRL, PSC_CTRL_DISABLE); - WR(priv, PSC_SEL, PSC_SEL_PS_SMBUSMODE); - WR(priv, PSC_SMBCFG, 0); - WR(priv, PSC_CTRL, PSC_CTRL_ENABLE); - while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0) - cpu_relax(); - - cfg = PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 | PSC_SMBCFG_DD_DISABLE; - WR(priv, PSC_SMBCFG, cfg); - - /* Divide by 8 to get a 6.25 MHz clock. The later protocol - * timings are based on this clock. - */ - cfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8); - WR(priv, PSC_SMBCFG, cfg); - WR(priv, PSC_SMBMSK, PSC_SMBMSK_ALLMASK); - - /* Set the protocol timer values. See Table 71 in the - * Au1550 Data Book for standard timing values. - */ - WR(priv, PSC_SMBTMR, PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \ - PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \ - PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \ - PSC_SMBTMR_SET_CH(15)); - - cfg |= PSC_SMBCFG_DE_ENABLE; - WR(priv, PSC_SMBCFG, cfg); - while ((RD(priv, PSC_SMBSTAT) & PSC_SMBSTAT_SR) == 0) - cpu_relax(); - - WR(priv, PSC_CTRL, PSC_CTRL_SUSPEND); -} - -static void i2c_au1550_disable(struct i2c_au1550_data *priv) -{ - WR(priv, PSC_SMBCFG, 0); - WR(priv, PSC_CTRL, PSC_CTRL_DISABLE); -} - -/* - * registering functions to load algorithms at runtime - * Prior to calling us, the 50MHz clock frequency and routing - * must have been set up for the PSC indicated by the adapter. - */ -static int __devinit -i2c_au1550_probe(struct platform_device *pdev) -{ - struct i2c_au1550_data *priv; - struct resource *r; - int ret; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - ret = -ENODEV; - goto out; - } - - priv = kzalloc(sizeof(struct i2c_au1550_data), GFP_KERNEL); - if (!priv) { - ret = -ENOMEM; - goto out; - } - - priv->ioarea = request_mem_region(r->start, resource_size(r), - pdev->name); - if (!priv->ioarea) { - ret = -EBUSY; - goto out_mem; - } - - priv->psc_base = ioremap(r->start, resource_size(r)); - if (!priv->psc_base) { - ret = -EIO; - goto out_map; - } - priv->xfer_timeout = 200; - - priv->adap.nr = pdev->id; - priv->adap.algo = &au1550_algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &pdev->dev; - strlcpy(priv->adap.name, "Au1xxx PSC I2C", sizeof(priv->adap.name)); - - /* Now, set up the PSC for SMBus PIO mode. */ - i2c_au1550_setup(priv); - - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret == 0) { - platform_set_drvdata(pdev, priv); - return 0; - } - - i2c_au1550_disable(priv); - iounmap(priv->psc_base); -out_map: - release_resource(priv->ioarea); - kfree(priv->ioarea); -out_mem: - kfree(priv); -out: - return ret; -} - -static int __devexit i2c_au1550_remove(struct platform_device *pdev) -{ - struct i2c_au1550_data *priv = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&priv->adap); - i2c_au1550_disable(priv); - iounmap(priv->psc_base); - release_resource(priv->ioarea); - kfree(priv->ioarea); - kfree(priv); - return 0; -} - -#ifdef CONFIG_PM -static int i2c_au1550_suspend(struct device *dev) -{ - struct i2c_au1550_data *priv = dev_get_drvdata(dev); - - i2c_au1550_disable(priv); - - return 0; -} - -static int i2c_au1550_resume(struct device *dev) -{ - struct i2c_au1550_data *priv = dev_get_drvdata(dev); - - i2c_au1550_setup(priv); - - return 0; -} - -static const struct dev_pm_ops i2c_au1550_pmops = { - .suspend = i2c_au1550_suspend, - .resume = i2c_au1550_resume, -}; - -#define AU1XPSC_SMBUS_PMOPS (&i2c_au1550_pmops) - -#else -#define AU1XPSC_SMBUS_PMOPS NULL -#endif - -static struct platform_driver au1xpsc_smbus_driver = { - .driver = { - .name = "au1xpsc_smbus", - .owner = THIS_MODULE, - .pm = AU1XPSC_SMBUS_PMOPS, - }, - .probe = i2c_au1550_probe, - .remove = __devexit_p(i2c_au1550_remove), -}; - -module_platform_driver(au1xpsc_smbus_driver); - -MODULE_AUTHOR("Dan Malek, Embedded Edge, LLC."); -MODULE_DESCRIPTION("SMBus adapter Alchemy pb1550"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:au1xpsc_smbus"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-bfin-twi.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-bfin-twi.c deleted file mode 100644 index cdb59e5b..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-bfin-twi.c +++ /dev/null @@ -1,797 +0,0 @@ -/* - * Blackfin On-Chip Two Wire Interface Driver - * - * Copyright 2005-2007 Analog Devices Inc. - * - * Enter bugs at http://blackfin.uclinux.org/ - * - * Licensed under the GPL-2 or later. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/mm.h> -#include <linux/timer.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/delay.h> - -#include <asm/blackfin.h> -#include <asm/portmux.h> -#include <asm/irq.h> - -/* SMBus mode*/ -#define TWI_I2C_MODE_STANDARD 1 -#define TWI_I2C_MODE_STANDARDSUB 2 -#define TWI_I2C_MODE_COMBINED 3 -#define TWI_I2C_MODE_REPEAT 4 - -struct bfin_twi_iface { - int irq; - spinlock_t lock; - char read_write; - u8 command; - u8 *transPtr; - int readNum; - int writeNum; - int cur_mode; - int manual_stop; - int result; - struct i2c_adapter adap; - struct completion complete; - struct i2c_msg *pmsg; - int msg_num; - int cur_msg; - u16 saved_clkdiv; - u16 saved_control; - void __iomem *regs_base; -}; - - -#define DEFINE_TWI_REG(reg, off) \ -static inline u16 read_##reg(struct bfin_twi_iface *iface) \ - { return bfin_read16(iface->regs_base + (off)); } \ -static inline void write_##reg(struct bfin_twi_iface *iface, u16 v) \ - { bfin_write16(iface->regs_base + (off), v); } - -DEFINE_TWI_REG(CLKDIV, 0x00) -DEFINE_TWI_REG(CONTROL, 0x04) -DEFINE_TWI_REG(SLAVE_CTL, 0x08) -DEFINE_TWI_REG(SLAVE_STAT, 0x0C) -DEFINE_TWI_REG(SLAVE_ADDR, 0x10) -DEFINE_TWI_REG(MASTER_CTL, 0x14) -DEFINE_TWI_REG(MASTER_STAT, 0x18) -DEFINE_TWI_REG(MASTER_ADDR, 0x1C) -DEFINE_TWI_REG(INT_STAT, 0x20) -DEFINE_TWI_REG(INT_MASK, 0x24) -DEFINE_TWI_REG(FIFO_CTL, 0x28) -DEFINE_TWI_REG(FIFO_STAT, 0x2C) -DEFINE_TWI_REG(XMT_DATA8, 0x80) -DEFINE_TWI_REG(XMT_DATA16, 0x84) -DEFINE_TWI_REG(RCV_DATA8, 0x88) -DEFINE_TWI_REG(RCV_DATA16, 0x8C) - -static const u16 pin_req[2][3] = { - {P_TWI0_SCL, P_TWI0_SDA, 0}, - {P_TWI1_SCL, P_TWI1_SDA, 0}, -}; - -static void bfin_twi_handle_interrupt(struct bfin_twi_iface *iface, - unsigned short twi_int_status) -{ - unsigned short mast_stat = read_MASTER_STAT(iface); - - if (twi_int_status & XMTSERV) { - /* Transmit next data */ - if (iface->writeNum > 0) { - SSYNC(); - write_XMT_DATA8(iface, *(iface->transPtr++)); - iface->writeNum--; - } - /* start receive immediately after complete sending in - * combine mode. - */ - else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | MDIR | RSTART); - else if (iface->manual_stop) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | STOP); - else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | RSTART | MDIR); - else - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) | RSTART) & ~MDIR); - } - } - if (twi_int_status & RCVSERV) { - if (iface->readNum > 0) { - /* Receive next data */ - *(iface->transPtr) = read_RCV_DATA8(iface); - if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { - /* Change combine mode into sub mode after - * read first data. - */ - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - /* Get read number from first byte in block - * combine mode. - */ - if (iface->readNum == 1 && iface->manual_stop) - iface->readNum = *iface->transPtr + 1; - } - iface->transPtr++; - iface->readNum--; - } else if (iface->manual_stop) { - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | STOP); - } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg + 1 < iface->msg_num) { - if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | RSTART | MDIR); - else - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) | RSTART) & ~MDIR); - } - } - if (twi_int_status & MERR) { - write_INT_MASK(iface, 0); - write_MASTER_STAT(iface, 0x3e); - write_MASTER_CTL(iface, 0); - iface->result = -EIO; - - if (mast_stat & LOSTARB) - dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); - if (mast_stat & ANAK) - dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); - if (mast_stat & DNAK) - dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); - if (mast_stat & BUFRDERR) - dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); - if (mast_stat & BUFWRERR) - dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); - - /* Faulty slave devices, may drive SDA low after a transfer - * finishes. To release the bus this code generates up to 9 - * extra clocks until SDA is released. - */ - - if (read_MASTER_STAT(iface) & SDASEN) { - int cnt = 9; - do { - write_MASTER_CTL(iface, SCLOVR); - udelay(6); - write_MASTER_CTL(iface, 0); - udelay(6); - } while ((read_MASTER_STAT(iface) & SDASEN) && cnt--); - - write_MASTER_CTL(iface, SDAOVR | SCLOVR); - udelay(6); - write_MASTER_CTL(iface, SDAOVR); - udelay(6); - write_MASTER_CTL(iface, 0); - } - - /* If it is a quick transfer, only address without data, - * not an err, return 1. - */ - if (iface->cur_mode == TWI_I2C_MODE_STANDARD && - iface->transPtr == NULL && - (twi_int_status & MCOMP) && (mast_stat & DNAK)) - iface->result = 1; - - complete(&iface->complete); - return; - } - if (twi_int_status & MCOMP) { - if ((read_MASTER_CTL(iface) & MEN) == 0 && - (iface->cur_mode == TWI_I2C_MODE_REPEAT || - iface->cur_mode == TWI_I2C_MODE_COMBINED)) { - iface->result = -1; - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - } else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { - if (iface->readNum == 0) { - /* set the read number to 1 and ask for manual - * stop in block combine mode - */ - iface->readNum = 1; - iface->manual_stop = 1; - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) | (0xff << 6)); - } else { - /* set the readd number in other - * combine mode. - */ - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) & - (~(0xff << 6))) | - (iface->readNum << 6)); - } - /* remove restart bit and enable master receive */ - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~RSTART); - } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && - iface->cur_msg+1 < iface->msg_num) { - iface->cur_msg++; - iface->transPtr = iface->pmsg[iface->cur_msg].buf; - iface->writeNum = iface->readNum = - iface->pmsg[iface->cur_msg].len; - /* Set Transmit device address */ - write_MASTER_ADDR(iface, - iface->pmsg[iface->cur_msg].addr); - if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD) - iface->read_write = I2C_SMBUS_READ; - else { - iface->read_write = I2C_SMBUS_WRITE; - /* Transmit first data */ - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, - *(iface->transPtr++)); - iface->writeNum--; - } - } - - if (iface->pmsg[iface->cur_msg].len <= 255) - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) & - (~(0xff << 6))) | - (iface->pmsg[iface->cur_msg].len << 6)); - else { - write_MASTER_CTL(iface, - (read_MASTER_CTL(iface) | - (0xff << 6))); - iface->manual_stop = 1; - } - /* remove restart bit and enable master receive */ - write_MASTER_CTL(iface, - read_MASTER_CTL(iface) & ~RSTART); - } else { - iface->result = 1; - write_INT_MASK(iface, 0); - write_MASTER_CTL(iface, 0); - } - } - complete(&iface->complete); -} - -/* Interrupt handler */ -static irqreturn_t bfin_twi_interrupt_entry(int irq, void *dev_id) -{ - struct bfin_twi_iface *iface = dev_id; - unsigned long flags; - unsigned short twi_int_status; - - spin_lock_irqsave(&iface->lock, flags); - while (1) { - twi_int_status = read_INT_STAT(iface); - if (!twi_int_status) - break; - /* Clear interrupt status */ - write_INT_STAT(iface, twi_int_status); - bfin_twi_handle_interrupt(iface, twi_int_status); - SSYNC(); - } - spin_unlock_irqrestore(&iface->lock, flags); - return IRQ_HANDLED; -} - -/* - * One i2c master transfer - */ -static int bfin_twi_do_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct bfin_twi_iface *iface = adap->algo_data; - struct i2c_msg *pmsg; - int rc = 0; - - if (!(read_CONTROL(iface) & TWI_ENA)) - return -ENXIO; - - while (read_MASTER_STAT(iface) & BUSBUSY) - yield(); - - iface->pmsg = msgs; - iface->msg_num = num; - iface->cur_msg = 0; - - pmsg = &msgs[0]; - if (pmsg->flags & I2C_M_TEN) { - dev_err(&adap->dev, "10 bits addr not supported!\n"); - return -EINVAL; - } - - iface->cur_mode = TWI_I2C_MODE_REPEAT; - iface->manual_stop = 0; - iface->transPtr = pmsg->buf; - iface->writeNum = iface->readNum = pmsg->len; - iface->result = 0; - init_completion(&(iface->complete)); - /* Set Transmit device address */ - write_MASTER_ADDR(iface, pmsg->addr); - - /* FIFO Initiation. Data in FIFO should be - * discarded before start a new operation. - */ - write_FIFO_CTL(iface, 0x3); - SSYNC(); - write_FIFO_CTL(iface, 0); - SSYNC(); - - if (pmsg->flags & I2C_M_RD) - iface->read_write = I2C_SMBUS_READ; - else { - iface->read_write = I2C_SMBUS_WRITE; - /* Transmit first data */ - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, *(iface->transPtr++)); - iface->writeNum--; - SSYNC(); - } - } - - /* clear int stat */ - write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV); - - /* Interrupt mask . Enable XMT, RCV interrupt */ - write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - SSYNC(); - - if (pmsg->len <= 255) - write_MASTER_CTL(iface, pmsg->len << 6); - else { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } - - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); - SSYNC(); - - while (!iface->result) { - if (!wait_for_completion_timeout(&iface->complete, - adap->timeout)) { - iface->result = -1; - dev_err(&adap->dev, "master transfer timeout\n"); - } - } - - if (iface->result == 1) - rc = iface->cur_msg + 1; - else - rc = iface->result; - - return rc; -} - -/* - * Generic i2c master transfer entrypoint - */ -static int bfin_twi_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - return bfin_twi_do_master_xfer(adap, msgs, num); -} - -/* - * One I2C SMBus transfer - */ -int bfin_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - struct bfin_twi_iface *iface = adap->algo_data; - int rc = 0; - - if (!(read_CONTROL(iface) & TWI_ENA)) - return -ENXIO; - - while (read_MASTER_STAT(iface) & BUSBUSY) - yield(); - - iface->writeNum = 0; - iface->readNum = 0; - - /* Prepare datas & select mode */ - switch (size) { - case I2C_SMBUS_QUICK: - iface->transPtr = NULL; - iface->cur_mode = TWI_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE: - if (data == NULL) - iface->transPtr = NULL; - else { - if (read_write == I2C_SMBUS_READ) - iface->readNum = 1; - else - iface->writeNum = 1; - iface->transPtr = &data->byte; - } - iface->cur_mode = TWI_I2C_MODE_STANDARD; - break; - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 1; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = 1; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = &data->byte; - break; - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 2; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = 2; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = (u8 *)&data->word; - break; - case I2C_SMBUS_PROC_CALL: - iface->writeNum = 2; - iface->readNum = 2; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - iface->transPtr = (u8 *)&data->word; - break; - case I2C_SMBUS_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = 0; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = data->block[0] + 1; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = data->block; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - iface->readNum = data->block[0]; - iface->cur_mode = TWI_I2C_MODE_COMBINED; - } else { - iface->writeNum = data->block[0]; - iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; - } - iface->transPtr = (u8 *)&data->block[1]; - break; - default: - return -1; - } - - iface->result = 0; - iface->manual_stop = 0; - iface->read_write = read_write; - iface->command = command; - init_completion(&(iface->complete)); - - /* FIFO Initiation. Data in FIFO should be discarded before - * start a new operation. - */ - write_FIFO_CTL(iface, 0x3); - SSYNC(); - write_FIFO_CTL(iface, 0); - - /* clear int stat */ - write_INT_STAT(iface, MERR | MCOMP | XMTSERV | RCVSERV); - - /* Set Transmit device address */ - write_MASTER_ADDR(iface, addr); - SSYNC(); - - switch (iface->cur_mode) { - case TWI_I2C_MODE_STANDARDSUB: - write_XMT_DATA8(iface, iface->command); - write_INT_MASK(iface, MCOMP | MERR | - ((iface->read_write == I2C_SMBUS_READ) ? - RCVSERV : XMTSERV)); - SSYNC(); - - if (iface->writeNum + 1 <= 255) - write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); - else { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); - break; - case TWI_I2C_MODE_COMBINED: - write_XMT_DATA8(iface, iface->command); - write_INT_MASK(iface, MCOMP | MERR | RCVSERV | XMTSERV); - SSYNC(); - - if (iface->writeNum > 0) - write_MASTER_CTL(iface, (iface->writeNum + 1) << 6); - else - write_MASTER_CTL(iface, 0x1 << 6); - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ>100) ? FAST : 0)); - break; - default: - write_MASTER_CTL(iface, 0); - if (size != I2C_SMBUS_QUICK) { - /* Don't access xmit data register when this is a - * read operation. - */ - if (iface->read_write != I2C_SMBUS_READ) { - if (iface->writeNum > 0) { - write_XMT_DATA8(iface, - *(iface->transPtr++)); - if (iface->writeNum <= 255) - write_MASTER_CTL(iface, - iface->writeNum << 6); - else { - write_MASTER_CTL(iface, - 0xff << 6); - iface->manual_stop = 1; - } - iface->writeNum--; - } else { - write_XMT_DATA8(iface, iface->command); - write_MASTER_CTL(iface, 1 << 6); - } - } else { - if (iface->readNum > 0 && iface->readNum <= 255) - write_MASTER_CTL(iface, - iface->readNum << 6); - else if (iface->readNum > 255) { - write_MASTER_CTL(iface, 0xff << 6); - iface->manual_stop = 1; - } else - break; - } - } - write_INT_MASK(iface, MCOMP | MERR | - ((iface->read_write == I2C_SMBUS_READ) ? - RCVSERV : XMTSERV)); - SSYNC(); - - /* Master enable */ - write_MASTER_CTL(iface, read_MASTER_CTL(iface) | MEN | - ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | - ((CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ > 100) ? FAST : 0)); - break; - } - SSYNC(); - - while (!iface->result) { - if (!wait_for_completion_timeout(&iface->complete, - adap->timeout)) { - iface->result = -1; - dev_err(&adap->dev, "smbus transfer timeout\n"); - } - } - - rc = (iface->result >= 0) ? 0 : -1; - - return rc; -} - -/* - * Generic I2C SMBus transfer entrypoint - */ -int bfin_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - return bfin_twi_do_smbus_xfer(adap, addr, flags, - read_write, command, size, data); -} - -/* - * Return what the adapter supports - */ -static u32 bfin_twi_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK; -} - -static struct i2c_algorithm bfin_twi_algorithm = { - .master_xfer = bfin_twi_master_xfer, - .smbus_xfer = bfin_twi_smbus_xfer, - .functionality = bfin_twi_functionality, -}; - -static int i2c_bfin_twi_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct bfin_twi_iface *iface = platform_get_drvdata(pdev); - - iface->saved_clkdiv = read_CLKDIV(iface); - iface->saved_control = read_CONTROL(iface); - - free_irq(iface->irq, iface); - - /* Disable TWI */ - write_CONTROL(iface, iface->saved_control & ~TWI_ENA); - - return 0; -} - -static int i2c_bfin_twi_resume(struct platform_device *pdev) -{ - struct bfin_twi_iface *iface = platform_get_drvdata(pdev); - - int rc = request_irq(iface->irq, bfin_twi_interrupt_entry, - 0, pdev->name, iface); - if (rc) { - dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); - return -ENODEV; - } - - /* Resume TWI interface clock as specified */ - write_CLKDIV(iface, iface->saved_clkdiv); - - /* Resume TWI */ - write_CONTROL(iface, iface->saved_control); - - return 0; -} - -static int i2c_bfin_twi_probe(struct platform_device *pdev) -{ - struct bfin_twi_iface *iface; - struct i2c_adapter *p_adap; - struct resource *res; - int rc; - unsigned int clkhilow; - - iface = kzalloc(sizeof(struct bfin_twi_iface), GFP_KERNEL); - if (!iface) { - dev_err(&pdev->dev, "Cannot allocate memory\n"); - rc = -ENOMEM; - goto out_error_nomem; - } - - spin_lock_init(&(iface->lock)); - - /* Find and map our resources */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); - rc = -ENOENT; - goto out_error_get_res; - } - - iface->regs_base = ioremap(res->start, resource_size(res)); - if (iface->regs_base == NULL) { - dev_err(&pdev->dev, "Cannot map IO\n"); - rc = -ENXIO; - goto out_error_ioremap; - } - - iface->irq = platform_get_irq(pdev, 0); - if (iface->irq < 0) { - dev_err(&pdev->dev, "No IRQ specified\n"); - rc = -ENOENT; - goto out_error_no_irq; - } - - p_adap = &iface->adap; - p_adap->nr = pdev->id; - strlcpy(p_adap->name, pdev->name, sizeof(p_adap->name)); - p_adap->algo = &bfin_twi_algorithm; - p_adap->algo_data = iface; - p_adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - p_adap->dev.parent = &pdev->dev; - p_adap->timeout = 5 * HZ; - p_adap->retries = 3; - - rc = peripheral_request_list(pin_req[pdev->id], "i2c-bfin-twi"); - if (rc) { - dev_err(&pdev->dev, "Can't setup pin mux!\n"); - goto out_error_pin_mux; - } - - rc = request_irq(iface->irq, bfin_twi_interrupt_entry, - 0, pdev->name, iface); - if (rc) { - dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); - rc = -ENODEV; - goto out_error_req_irq; - } - - /* Set TWI internal clock as 10MHz */ - write_CONTROL(iface, ((get_sclk() / 1000 / 1000 + 5) / 10) & 0x7F); - - /* - * We will not end up with a CLKDIV=0 because no one will specify - * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250) - */ - clkhilow = ((10 * 1000 / CONFIG_I2C_BLACKFIN_TWI_CLK_KHZ) + 1) / 2; - - /* Set Twi interface clock as specified */ - write_CLKDIV(iface, (clkhilow << 8) | clkhilow); - - /* Enable TWI */ - write_CONTROL(iface, read_CONTROL(iface) | TWI_ENA); - SSYNC(); - - rc = i2c_add_numbered_adapter(p_adap); - if (rc < 0) { - dev_err(&pdev->dev, "Can't add i2c adapter!\n"); - goto out_error_add_adapter; - } - - platform_set_drvdata(pdev, iface); - - dev_info(&pdev->dev, "Blackfin BF5xx on-chip I2C TWI Contoller, " - "regs_base@%p\n", iface->regs_base); - - return 0; - -out_error_add_adapter: - free_irq(iface->irq, iface); -out_error_req_irq: -out_error_no_irq: - peripheral_free_list(pin_req[pdev->id]); -out_error_pin_mux: - iounmap(iface->regs_base); -out_error_ioremap: -out_error_get_res: - kfree(iface); -out_error_nomem: - return rc; -} - -static int i2c_bfin_twi_remove(struct platform_device *pdev) -{ - struct bfin_twi_iface *iface = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - - i2c_del_adapter(&(iface->adap)); - free_irq(iface->irq, iface); - peripheral_free_list(pin_req[pdev->id]); - iounmap(iface->regs_base); - kfree(iface); - - return 0; -} - -static struct platform_driver i2c_bfin_twi_driver = { - .probe = i2c_bfin_twi_probe, - .remove = i2c_bfin_twi_remove, - .suspend = i2c_bfin_twi_suspend, - .resume = i2c_bfin_twi_resume, - .driver = { - .name = "i2c-bfin-twi", - .owner = THIS_MODULE, - }, -}; - -static int __init i2c_bfin_twi_init(void) -{ - return platform_driver_register(&i2c_bfin_twi_driver); -} - -static void __exit i2c_bfin_twi_exit(void) -{ - platform_driver_unregister(&i2c_bfin_twi_driver); -} - -subsys_initcall(i2c_bfin_twi_init); -module_exit(i2c_bfin_twi_exit); - -MODULE_AUTHOR("Bryan Wu, Sonic Zhang"); -MODULE_DESCRIPTION("Blackfin BF5xx on-chip I2C TWI Contoller Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:i2c-bfin-twi"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-cpm.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-cpm.c deleted file mode 100644 index c1e1096b..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-cpm.c +++ /dev/null @@ -1,731 +0,0 @@ -/* - * Freescale CPM1/CPM2 I2C interface. - * Copyright (c) 1999 Dan Malek (dmalek@jlc.net). - * - * moved into proper i2c interface; - * Brad Parker (brad@heeltoe.com) - * - * Parts from dbox2_i2c.c (cvs.tuxbox.org) - * (C) 2000-2001 Felix Domke (tmbinc@gmx.net), Gillem (htoa@gmx.net) - * - * (C) 2007 Montavista Software, Inc. - * Vitaly Bordug <vitb@kernel.crashing.org> - * - * Converted to of_platform_device. Renamed to i2c-cpm.c. - * (C) 2007,2008 Jochen Friedrich <jochen@scram.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/errno.h> -#include <linux/stddef.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/dma-mapping.h> -#include <linux/of_device.h> -#include <linux/of_platform.h> -#include <linux/of_i2c.h> -#include <sysdev/fsl_soc.h> -#include <asm/cpm.h> - -/* Try to define this if you have an older CPU (earlier than rev D4) */ -/* However, better use a GPIO based bitbang driver in this case :/ */ -#undef I2C_CHIP_ERRATA - -#define CPM_MAX_READ 513 -#define CPM_MAXBD 4 - -#define I2C_EB (0x10) /* Big endian mode */ -#define I2C_EB_CPM2 (0x30) /* Big endian mode, memory snoop */ - -#define DPRAM_BASE ((u8 __iomem __force *)cpm_muram_addr(0)) - -/* I2C parameter RAM. */ -struct i2c_ram { - ushort rbase; /* Rx Buffer descriptor base address */ - ushort tbase; /* Tx Buffer descriptor base address */ - u_char rfcr; /* Rx function code */ - u_char tfcr; /* Tx function code */ - ushort mrblr; /* Max receive buffer length */ - uint rstate; /* Internal */ - uint rdp; /* Internal */ - ushort rbptr; /* Rx Buffer descriptor pointer */ - ushort rbc; /* Internal */ - uint rxtmp; /* Internal */ - uint tstate; /* Internal */ - uint tdp; /* Internal */ - ushort tbptr; /* Tx Buffer descriptor pointer */ - ushort tbc; /* Internal */ - uint txtmp; /* Internal */ - char res1[4]; /* Reserved */ - ushort rpbase; /* Relocation pointer */ - char res2[2]; /* Reserved */ -}; - -#define I2COM_START 0x80 -#define I2COM_MASTER 0x01 -#define I2CER_TXE 0x10 -#define I2CER_BUSY 0x04 -#define I2CER_TXB 0x02 -#define I2CER_RXB 0x01 -#define I2MOD_EN 0x01 - -/* I2C Registers */ -struct i2c_reg { - u8 i2mod; - u8 res1[3]; - u8 i2add; - u8 res2[3]; - u8 i2brg; - u8 res3[3]; - u8 i2com; - u8 res4[3]; - u8 i2cer; - u8 res5[3]; - u8 i2cmr; -}; - -struct cpm_i2c { - char *base; - struct platform_device *ofdev; - struct i2c_adapter adap; - uint dp_addr; - int version; /* CPM1=1, CPM2=2 */ - int irq; - int cp_command; - int freq; - struct i2c_reg __iomem *i2c_reg; - struct i2c_ram __iomem *i2c_ram; - u16 i2c_addr; - wait_queue_head_t i2c_wait; - cbd_t __iomem *tbase; - cbd_t __iomem *rbase; - u_char *txbuf[CPM_MAXBD]; - u_char *rxbuf[CPM_MAXBD]; - u32 txdma[CPM_MAXBD]; - u32 rxdma[CPM_MAXBD]; -}; - -static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id) -{ - struct cpm_i2c *cpm; - struct i2c_reg __iomem *i2c_reg; - struct i2c_adapter *adap = dev_id; - int i; - - cpm = i2c_get_adapdata(dev_id); - i2c_reg = cpm->i2c_reg; - - /* Clear interrupt. */ - i = in_8(&i2c_reg->i2cer); - out_8(&i2c_reg->i2cer, i); - - dev_dbg(&adap->dev, "Interrupt: %x\n", i); - - wake_up(&cpm->i2c_wait); - - return i ? IRQ_HANDLED : IRQ_NONE; -} - -static void cpm_reset_i2c_params(struct cpm_i2c *cpm) -{ - struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; - - /* Set up the I2C parameters in the parameter ram. */ - out_be16(&i2c_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE); - out_be16(&i2c_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE); - - if (cpm->version == 1) { - out_8(&i2c_ram->tfcr, I2C_EB); - out_8(&i2c_ram->rfcr, I2C_EB); - } else { - out_8(&i2c_ram->tfcr, I2C_EB_CPM2); - out_8(&i2c_ram->rfcr, I2C_EB_CPM2); - } - - out_be16(&i2c_ram->mrblr, CPM_MAX_READ); - - out_be32(&i2c_ram->rstate, 0); - out_be32(&i2c_ram->rdp, 0); - out_be16(&i2c_ram->rbptr, 0); - out_be16(&i2c_ram->rbc, 0); - out_be32(&i2c_ram->rxtmp, 0); - out_be32(&i2c_ram->tstate, 0); - out_be32(&i2c_ram->tdp, 0); - out_be16(&i2c_ram->tbptr, 0); - out_be16(&i2c_ram->tbc, 0); - out_be32(&i2c_ram->txtmp, 0); -} - -static void cpm_i2c_force_close(struct i2c_adapter *adap) -{ - struct cpm_i2c *cpm = i2c_get_adapdata(adap); - struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; - - dev_dbg(&adap->dev, "cpm_i2c_force_close()\n"); - - cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD); - - out_8(&i2c_reg->i2cmr, 0x00); /* Disable all interrupts */ - out_8(&i2c_reg->i2cer, 0xff); -} - -static void cpm_i2c_parse_message(struct i2c_adapter *adap, - struct i2c_msg *pmsg, int num, int tx, int rx) -{ - cbd_t __iomem *tbdf; - cbd_t __iomem *rbdf; - u_char addr; - u_char *tb; - u_char *rb; - struct cpm_i2c *cpm = i2c_get_adapdata(adap); - - tbdf = cpm->tbase + tx; - rbdf = cpm->rbase + rx; - - addr = pmsg->addr << 1; - if (pmsg->flags & I2C_M_RD) - addr |= 1; - - tb = cpm->txbuf[tx]; - rb = cpm->rxbuf[rx]; - - /* Align read buffer */ - rb = (u_char *) (((ulong) rb + 1) & ~1); - - tb[0] = addr; /* Device address byte w/rw flag */ - - out_be16(&tbdf->cbd_datlen, pmsg->len + 1); - out_be16(&tbdf->cbd_sc, 0); - - if (!(pmsg->flags & I2C_M_NOSTART)) - setbits16(&tbdf->cbd_sc, BD_I2C_START); - - if (tx + 1 == num) - setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP); - - if (pmsg->flags & I2C_M_RD) { - /* - * To read, we need an empty buffer of the proper length. - * All that is used is the first byte for address, the remainder - * is just used for timing (and doesn't really have to exist). - */ - - dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr); - - out_be16(&rbdf->cbd_datlen, 0); - out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT); - - if (rx + 1 == CPM_MAXBD) - setbits16(&rbdf->cbd_sc, BD_SC_WRAP); - - eieio(); - setbits16(&tbdf->cbd_sc, BD_SC_READY); - } else { - dev_dbg(&adap->dev, "cpm_i2c_write(abyte=0x%x)\n", addr); - - memcpy(tb+1, pmsg->buf, pmsg->len); - - eieio(); - setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT); - } -} - -static int cpm_i2c_check_message(struct i2c_adapter *adap, - struct i2c_msg *pmsg, int tx, int rx) -{ - cbd_t __iomem *tbdf; - cbd_t __iomem *rbdf; - u_char *tb; - u_char *rb; - struct cpm_i2c *cpm = i2c_get_adapdata(adap); - - tbdf = cpm->tbase + tx; - rbdf = cpm->rbase + rx; - - tb = cpm->txbuf[tx]; - rb = cpm->rxbuf[rx]; - - /* Align read buffer */ - rb = (u_char *) (((uint) rb + 1) & ~1); - - eieio(); - if (pmsg->flags & I2C_M_RD) { - dev_dbg(&adap->dev, "tx sc 0x%04x, rx sc 0x%04x\n", - in_be16(&tbdf->cbd_sc), in_be16(&rbdf->cbd_sc)); - - if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { - dev_dbg(&adap->dev, "I2C read; No ack\n"); - return -ENXIO; - } - if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) { - dev_err(&adap->dev, - "I2C read; complete but rbuf empty\n"); - return -EREMOTEIO; - } - if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) { - dev_err(&adap->dev, "I2C read; Overrun\n"); - return -EREMOTEIO; - } - memcpy(pmsg->buf, rb, pmsg->len); - } else { - dev_dbg(&adap->dev, "tx sc %d 0x%04x\n", tx, - in_be16(&tbdf->cbd_sc)); - - if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) { - dev_dbg(&adap->dev, "I2C write; No ack\n"); - return -ENXIO; - } - if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) { - dev_err(&adap->dev, "I2C write; Underrun\n"); - return -EIO; - } - if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) { - dev_err(&adap->dev, "I2C write; Collision\n"); - return -EIO; - } - } - return 0; -} - -static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct cpm_i2c *cpm = i2c_get_adapdata(adap); - struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg; - struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram; - struct i2c_msg *pmsg; - int ret, i; - int tptr; - int rptr; - cbd_t __iomem *tbdf; - cbd_t __iomem *rbdf; - - if (num > CPM_MAXBD) - return -EINVAL; - - /* Check if we have any oversized READ requests */ - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - if (pmsg->len >= CPM_MAX_READ) - return -EINVAL; - } - - /* Reset to use first buffer */ - out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase)); - out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase)); - - tbdf = cpm->tbase; - rbdf = cpm->rbase; - - tptr = 0; - rptr = 0; - - while (tptr < num) { - pmsg = &msgs[tptr]; - dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr); - - cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr); - if (pmsg->flags & I2C_M_RD) - rptr++; - tptr++; - } - /* Start transfer now */ - /* Enable RX/TX/Error interupts */ - out_8(&i2c_reg->i2cmr, I2CER_TXE | I2CER_TXB | I2CER_RXB); - out_8(&i2c_reg->i2cer, 0xff); /* Clear interrupt status */ - /* Chip bug, set enable here */ - setbits8(&i2c_reg->i2mod, I2MOD_EN); /* Enable */ - /* Begin transmission */ - setbits8(&i2c_reg->i2com, I2COM_START); - - tptr = 0; - rptr = 0; - - while (tptr < num) { - /* Check for outstanding messages */ - dev_dbg(&adap->dev, "test ready.\n"); - pmsg = &msgs[tptr]; - if (pmsg->flags & I2C_M_RD) - ret = wait_event_timeout(cpm->i2c_wait, - (in_be16(&tbdf[tptr].cbd_sc) & BD_SC_NAK) || - !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY), - 1 * HZ); - else - ret = wait_event_timeout(cpm->i2c_wait, - !(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY), - 1 * HZ); - if (ret == 0) { - ret = -EREMOTEIO; - dev_err(&adap->dev, "I2C transfer: timeout\n"); - goto out_err; - } - if (ret > 0) { - dev_dbg(&adap->dev, "ready.\n"); - ret = cpm_i2c_check_message(adap, pmsg, tptr, rptr); - tptr++; - if (pmsg->flags & I2C_M_RD) - rptr++; - if (ret) - goto out_err; - } - } -#ifdef I2C_CHIP_ERRATA - /* - * Chip errata, clear enable. This is not needed on rev D4 CPUs. - * Disabling I2C too early may cause too short stop condition - */ - udelay(4); - clrbits8(&i2c_reg->i2mod, I2MOD_EN); -#endif - return (num); - -out_err: - cpm_i2c_force_close(adap); -#ifdef I2C_CHIP_ERRATA - /* - * Chip errata, clear enable. This is not needed on rev D4 CPUs. - */ - clrbits8(&i2c_reg->i2mod, I2MOD_EN); -#endif - return ret; -} - -static u32 cpm_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -} - -/* -----exported algorithm data: ------------------------------------- */ - -static const struct i2c_algorithm cpm_i2c_algo = { - .master_xfer = cpm_i2c_xfer, - .functionality = cpm_i2c_func, -}; - -static const struct i2c_adapter cpm_ops = { - .owner = THIS_MODULE, - .name = "i2c-cpm", - .algo = &cpm_i2c_algo, -}; - -static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm) -{ - struct platform_device *ofdev = cpm->ofdev; - const u32 *data; - int len, ret, i; - void __iomem *i2c_base; - cbd_t __iomem *tbdf; - cbd_t __iomem *rbdf; - unsigned char brg; - - dev_dbg(&cpm->ofdev->dev, "cpm_i2c_setup()\n"); - - init_waitqueue_head(&cpm->i2c_wait); - - cpm->irq = of_irq_to_resource(ofdev->dev.of_node, 0, NULL); - if (!cpm->irq) - return -EINVAL; - - /* Install interrupt handler. */ - ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c", - &cpm->adap); - if (ret) - return ret; - - /* I2C parameter RAM */ - i2c_base = of_iomap(ofdev->dev.of_node, 1); - if (i2c_base == NULL) { - ret = -EINVAL; - goto out_irq; - } - - if (of_device_is_compatible(ofdev->dev.of_node, "fsl,cpm1-i2c")) { - - /* Check for and use a microcode relocation patch. */ - cpm->i2c_ram = i2c_base; - cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase); - - /* - * Maybe should use cpm_muram_alloc instead of hardcoding - * this in micropatch.c - */ - if (cpm->i2c_addr) { - cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr); - iounmap(i2c_base); - } - - cpm->version = 1; - - } else if (of_device_is_compatible(ofdev->dev.of_node, "fsl,cpm2-i2c")) { - cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64); - cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr); - out_be16(i2c_base, cpm->i2c_addr); - iounmap(i2c_base); - - cpm->version = 2; - - } else { - iounmap(i2c_base); - ret = -EINVAL; - goto out_irq; - } - - /* I2C control/status registers */ - cpm->i2c_reg = of_iomap(ofdev->dev.of_node, 0); - if (cpm->i2c_reg == NULL) { - ret = -EINVAL; - goto out_ram; - } - - data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len); - if (!data || len != 4) { - ret = -EINVAL; - goto out_reg; - } - cpm->cp_command = *data; - - data = of_get_property(ofdev->dev.of_node, "linux,i2c-class", &len); - if (data && len == 4) - cpm->adap.class = *data; - - data = of_get_property(ofdev->dev.of_node, "clock-frequency", &len); - if (data && len == 4) - cpm->freq = *data; - else - cpm->freq = 60000; /* use 60kHz i2c clock by default */ - - /* - * Allocate space for CPM_MAXBD transmit and receive buffer - * descriptors in the DP ram. - */ - cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8); - if (!cpm->dp_addr) { - ret = -ENOMEM; - goto out_reg; - } - - cpm->tbase = cpm_muram_addr(cpm->dp_addr); - cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD); - - /* Allocate TX and RX buffers */ - - tbdf = cpm->tbase; - rbdf = cpm->rbase; - - for (i = 0; i < CPM_MAXBD; i++) { - cpm->rxbuf[i] = dma_alloc_coherent(&cpm->ofdev->dev, - CPM_MAX_READ + 1, - &cpm->rxdma[i], GFP_KERNEL); - if (!cpm->rxbuf[i]) { - ret = -ENOMEM; - goto out_muram; - } - out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1)); - - cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL); - if (!cpm->txbuf[i]) { - ret = -ENOMEM; - goto out_muram; - } - out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]); - } - - /* Initialize Tx/Rx parameters. */ - - cpm_reset_i2c_params(cpm); - - dev_dbg(&cpm->ofdev->dev, "i2c_ram 0x%p, i2c_addr 0x%04x, freq %d\n", - cpm->i2c_ram, cpm->i2c_addr, cpm->freq); - dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n", - (u8 __iomem *)cpm->tbase - DPRAM_BASE, - (u8 __iomem *)cpm->rbase - DPRAM_BASE); - - cpm_command(cpm->cp_command, CPM_CR_INIT_TRX); - - /* - * Select an invalid address. Just make sure we don't use loopback mode - */ - out_8(&cpm->i2c_reg->i2add, 0x7f << 1); - - /* - * PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the - * i2c baud rate generator. This is divided by 2 x (DIV + 3) to get - * the actual i2c bus frequency. - */ - brg = get_brgfreq() / (32 * 2 * cpm->freq) - 3; - out_8(&cpm->i2c_reg->i2brg, brg); - - out_8(&cpm->i2c_reg->i2mod, 0x00); - out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); /* Master mode */ - - /* Disable interrupts. */ - out_8(&cpm->i2c_reg->i2cmr, 0); - out_8(&cpm->i2c_reg->i2cer, 0xff); - - return 0; - -out_muram: - for (i = 0; i < CPM_MAXBD; i++) { - if (cpm->rxbuf[i]) - dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, - cpm->rxbuf[i], cpm->rxdma[i]); - if (cpm->txbuf[i]) - dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, - cpm->txbuf[i], cpm->txdma[i]); - } - cpm_muram_free(cpm->dp_addr); -out_reg: - iounmap(cpm->i2c_reg); -out_ram: - if ((cpm->version == 1) && (!cpm->i2c_addr)) - iounmap(cpm->i2c_ram); - if (cpm->version == 2) - cpm_muram_free(cpm->i2c_addr); -out_irq: - free_irq(cpm->irq, &cpm->adap); - return ret; -} - -static void cpm_i2c_shutdown(struct cpm_i2c *cpm) -{ - int i; - - /* Shut down I2C. */ - clrbits8(&cpm->i2c_reg->i2mod, I2MOD_EN); - - /* Disable interrupts */ - out_8(&cpm->i2c_reg->i2cmr, 0); - out_8(&cpm->i2c_reg->i2cer, 0xff); - - free_irq(cpm->irq, &cpm->adap); - - /* Free all memory */ - for (i = 0; i < CPM_MAXBD; i++) { - dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, - cpm->rxbuf[i], cpm->rxdma[i]); - dma_free_coherent(&cpm->ofdev->dev, CPM_MAX_READ + 1, - cpm->txbuf[i], cpm->txdma[i]); - } - - cpm_muram_free(cpm->dp_addr); - iounmap(cpm->i2c_reg); - - if ((cpm->version == 1) && (!cpm->i2c_addr)) - iounmap(cpm->i2c_ram); - if (cpm->version == 2) - cpm_muram_free(cpm->i2c_addr); -} - -static int __devinit cpm_i2c_probe(struct platform_device *ofdev) -{ - int result, len; - struct cpm_i2c *cpm; - const u32 *data; - - cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL); - if (!cpm) - return -ENOMEM; - - cpm->ofdev = ofdev; - - dev_set_drvdata(&ofdev->dev, cpm); - - cpm->adap = cpm_ops; - i2c_set_adapdata(&cpm->adap, cpm); - cpm->adap.dev.parent = &ofdev->dev; - cpm->adap.dev.of_node = of_node_get(ofdev->dev.of_node); - - result = cpm_i2c_setup(cpm); - if (result) { - dev_err(&ofdev->dev, "Unable to init hardware\n"); - goto out_free; - } - - /* register new adapter to i2c module... */ - - data = of_get_property(ofdev->dev.of_node, "linux,i2c-index", &len); - cpm->adap.nr = (data && len == 4) ? be32_to_cpup(data) : -1; - result = i2c_add_numbered_adapter(&cpm->adap); - - if (result < 0) { - dev_err(&ofdev->dev, "Unable to register with I2C\n"); - goto out_shut; - } - - dev_dbg(&ofdev->dev, "hw routines for %s registered.\n", - cpm->adap.name); - - /* - * register OF I2C devices - */ - of_i2c_register_devices(&cpm->adap); - - return 0; -out_shut: - cpm_i2c_shutdown(cpm); -out_free: - dev_set_drvdata(&ofdev->dev, NULL); - kfree(cpm); - - return result; -} - -static int __devexit cpm_i2c_remove(struct platform_device *ofdev) -{ - struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev); - - i2c_del_adapter(&cpm->adap); - - cpm_i2c_shutdown(cpm); - - dev_set_drvdata(&ofdev->dev, NULL); - kfree(cpm); - - return 0; -} - -static const struct of_device_id cpm_i2c_match[] = { - { - .compatible = "fsl,cpm1-i2c", - }, - { - .compatible = "fsl,cpm2-i2c", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, cpm_i2c_match); - -static struct platform_driver cpm_i2c_driver = { - .probe = cpm_i2c_probe, - .remove = __devexit_p(cpm_i2c_remove), - .driver = { - .name = "fsl-i2c-cpm", - .owner = THIS_MODULE, - .of_match_table = cpm_i2c_match, - }, -}; - -module_platform_driver(cpm_i2c_driver); - -MODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>"); -MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-davinci.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-davinci.c deleted file mode 100644 index 79b4bcb3..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-davinci.c +++ /dev/null @@ -1,830 +0,0 @@ -/* - * TI DAVINCI I2C adapter driver. - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * - * Updated by Vinod & Sudhakar Feb 2005 - * - * ---------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/clk.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/cpufreq.h> -#include <linux/gpio.h> - -#include <mach/hardware.h> -#include <mach/i2c.h> - -/* ----- global defines ----------------------------------------------- */ - -#define DAVINCI_I2C_TIMEOUT (1*HZ) -#define DAVINCI_I2C_MAX_TRIES 2 -#define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ - DAVINCI_I2C_IMR_SCD | \ - DAVINCI_I2C_IMR_ARDY | \ - DAVINCI_I2C_IMR_NACK | \ - DAVINCI_I2C_IMR_AL) - -#define DAVINCI_I2C_OAR_REG 0x00 -#define DAVINCI_I2C_IMR_REG 0x04 -#define DAVINCI_I2C_STR_REG 0x08 -#define DAVINCI_I2C_CLKL_REG 0x0c -#define DAVINCI_I2C_CLKH_REG 0x10 -#define DAVINCI_I2C_CNT_REG 0x14 -#define DAVINCI_I2C_DRR_REG 0x18 -#define DAVINCI_I2C_SAR_REG 0x1c -#define DAVINCI_I2C_DXR_REG 0x20 -#define DAVINCI_I2C_MDR_REG 0x24 -#define DAVINCI_I2C_IVR_REG 0x28 -#define DAVINCI_I2C_EMDR_REG 0x2c -#define DAVINCI_I2C_PSC_REG 0x30 - -#define DAVINCI_I2C_IVR_AAS 0x07 -#define DAVINCI_I2C_IVR_SCD 0x06 -#define DAVINCI_I2C_IVR_XRDY 0x05 -#define DAVINCI_I2C_IVR_RDR 0x04 -#define DAVINCI_I2C_IVR_ARDY 0x03 -#define DAVINCI_I2C_IVR_NACK 0x02 -#define DAVINCI_I2C_IVR_AL 0x01 - -#define DAVINCI_I2C_STR_BB BIT(12) -#define DAVINCI_I2C_STR_RSFULL BIT(11) -#define DAVINCI_I2C_STR_SCD BIT(5) -#define DAVINCI_I2C_STR_ARDY BIT(2) -#define DAVINCI_I2C_STR_NACK BIT(1) -#define DAVINCI_I2C_STR_AL BIT(0) - -#define DAVINCI_I2C_MDR_NACK BIT(15) -#define DAVINCI_I2C_MDR_STT BIT(13) -#define DAVINCI_I2C_MDR_STP BIT(11) -#define DAVINCI_I2C_MDR_MST BIT(10) -#define DAVINCI_I2C_MDR_TRX BIT(9) -#define DAVINCI_I2C_MDR_XA BIT(8) -#define DAVINCI_I2C_MDR_RM BIT(7) -#define DAVINCI_I2C_MDR_IRS BIT(5) - -#define DAVINCI_I2C_IMR_AAS BIT(6) -#define DAVINCI_I2C_IMR_SCD BIT(5) -#define DAVINCI_I2C_IMR_XRDY BIT(4) -#define DAVINCI_I2C_IMR_RRDY BIT(3) -#define DAVINCI_I2C_IMR_ARDY BIT(2) -#define DAVINCI_I2C_IMR_NACK BIT(1) -#define DAVINCI_I2C_IMR_AL BIT(0) - -struct davinci_i2c_dev { - struct device *dev; - void __iomem *base; - struct completion cmd_complete; - struct clk *clk; - int cmd_err; - u8 *buf; - size_t buf_len; - int irq; - int stop; - u8 terminate; - struct i2c_adapter adapter; -#ifdef CONFIG_CPU_FREQ - struct completion xfr_complete; - struct notifier_block freq_transition; -#endif -}; - -/* default platform data to use if not supplied in the platform_device */ -static struct davinci_i2c_platform_data davinci_i2c_platform_data_default = { - .bus_freq = 100, - .bus_delay = 0, -}; - -static inline void davinci_i2c_write_reg(struct davinci_i2c_dev *i2c_dev, - int reg, u16 val) -{ - __raw_writew(val, i2c_dev->base + reg); -} - -static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) -{ - return __raw_readw(i2c_dev->base + reg); -} - -/* Generate a pulse on the i2c clock pin. */ -static void generic_i2c_clock_pulse(unsigned int scl_pin) -{ - u16 i; - - if (scl_pin) { - /* Send high and low on the SCL line */ - for (i = 0; i < 9; i++) { - gpio_set_value(scl_pin, 0); - udelay(20); - gpio_set_value(scl_pin, 1); - udelay(20); - } - } -} - -/* This routine does i2c bus recovery as specified in the - * i2c protocol Rev. 03 section 3.16 titled "Bus clear" - */ -static void i2c_recover_bus(struct davinci_i2c_dev *dev) -{ - u32 flag = 0; - struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; - - dev_err(dev->dev, "initiating i2c bus recovery\n"); - /* Send NACK to the slave */ - flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - flag |= DAVINCI_I2C_MDR_NACK; - /* write the data into mode register */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - if (pdata) - generic_i2c_clock_pulse(pdata->scl_pin); - /* Send STOP */ - flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - flag |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); -} - -static inline void davinci_i2c_reset_ctrl(struct davinci_i2c_dev *i2c_dev, - int val) -{ - u16 w; - - w = davinci_i2c_read_reg(i2c_dev, DAVINCI_I2C_MDR_REG); - if (!val) /* put I2C into reset */ - w &= ~DAVINCI_I2C_MDR_IRS; - else /* take I2C out of reset */ - w |= DAVINCI_I2C_MDR_IRS; - - davinci_i2c_write_reg(i2c_dev, DAVINCI_I2C_MDR_REG, w); -} - -static void i2c_davinci_calc_clk_dividers(struct davinci_i2c_dev *dev) -{ - struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; - u16 psc; - u32 clk; - u32 d; - u32 clkh; - u32 clkl; - u32 input_clock = clk_get_rate(dev->clk); - - /* NOTE: I2C Clock divider programming info - * As per I2C specs the following formulas provide prescaler - * and low/high divider values - * input clk --> PSC Div -----------> ICCL/H Div --> output clock - * module clk - * - * output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ] - * - * Thus, - * (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d; - * - * where if PSC == 0, d = 7, - * if PSC == 1, d = 6 - * if PSC > 1 , d = 5 - */ - - /* get minimum of 7 MHz clock, but max of 12 MHz */ - psc = (input_clock / 7000000) - 1; - if ((input_clock / (psc + 1)) > 12000000) - psc++; /* better to run under spec than over */ - d = (psc >= 2) ? 5 : 7 - psc; - - clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1); - clkh = clk >> 1; - clkl = clk - clkh; - - davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc); - davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh); - davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl); - - dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk); -} - -/* - * This function configures I2C and brings I2C out of reset. - * This function is called during I2C init function. This function - * also gets called if I2C encounters any errors. - */ -static int i2c_davinci_init(struct davinci_i2c_dev *dev) -{ - struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; - - if (!pdata) - pdata = &davinci_i2c_platform_data_default; - - /* put I2C into reset */ - davinci_i2c_reset_ctrl(dev, 0); - - /* compute clock dividers */ - i2c_davinci_calc_clk_dividers(dev); - - /* Respond at reserved "SMBus Host" slave address" (and zero); - * we seem to have no option to not respond... - */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_OAR_REG, 0x08); - - dev_dbg(dev->dev, "PSC = %d\n", - davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG)); - dev_dbg(dev->dev, "CLKL = %d\n", - davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG)); - dev_dbg(dev->dev, "CLKH = %d\n", - davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG)); - dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n", - pdata->bus_freq, pdata->bus_delay); - - /* Take the I2C module out of reset: */ - davinci_i2c_reset_ctrl(dev, 1); - - /* Enable interrupts */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, I2C_DAVINCI_INTR_ALL); - - return 0; -} - -/* - * Waiting for bus not busy - */ -static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, - char allow_sleep) -{ - unsigned long timeout; - static u16 to_cnt; - - timeout = jiffies + dev->adapter.timeout; - while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) - & DAVINCI_I2C_STR_BB) { - if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, - "timeout waiting for bus ready\n"); - to_cnt++; - return -ETIMEDOUT; - } else { - to_cnt = 0; - i2c_recover_bus(dev); - i2c_davinci_init(dev); - } - } - if (allow_sleep) - schedule_timeout(1); - } - - return 0; -} - -/* - * Low level master read/write transaction. This function is called - * from i2c_davinci_xfer. - */ -static int -i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) -{ - struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); - struct davinci_i2c_platform_data *pdata = dev->dev->platform_data; - u32 flag; - u16 w; - int r; - - if (!pdata) - pdata = &davinci_i2c_platform_data_default; - /* Introduce a delay, required for some boards (e.g Davinci EVM) */ - if (pdata->bus_delay) - udelay(pdata->bus_delay); - - /* set the slave address */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_SAR_REG, msg->addr); - - dev->buf = msg->buf; - dev->buf_len = msg->len; - dev->stop = stop; - - davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len); - - INIT_COMPLETION(dev->cmd_complete); - dev->cmd_err = 0; - - /* Take I2C out of reset and configure it as master */ - flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST; - - /* if the slave address is ten bit address, enable XA bit */ - if (msg->flags & I2C_M_TEN) - flag |= DAVINCI_I2C_MDR_XA; - if (!(msg->flags & I2C_M_RD)) - flag |= DAVINCI_I2C_MDR_TRX; - if (msg->len == 0) - flag |= DAVINCI_I2C_MDR_RM; - - /* Enable receive or transmit interrupts */ - w = davinci_i2c_read_reg(dev, DAVINCI_I2C_IMR_REG); - if (msg->flags & I2C_M_RD) - w |= DAVINCI_I2C_IMR_RRDY; - else - w |= DAVINCI_I2C_IMR_XRDY; - davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w); - - dev->terminate = 0; - - /* - * Write mode register first as needed for correct behaviour - * on OMAP-L138, but don't set STT yet to avoid a race with XRDY - * occurring before we have loaded DXR - */ - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - - /* - * First byte should be set here, not after interrupt, - * because transmit-data-ready interrupt can come before - * NACK-interrupt during sending of previous message and - * ICDXR may have wrong data - * It also saves us one interrupt, slightly faster - */ - if ((!(msg->flags & I2C_M_RD)) && dev->buf_len) { - davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, *dev->buf++); - dev->buf_len--; - } - - /* Set STT to begin transmit now DXR is loaded */ - flag |= DAVINCI_I2C_MDR_STT; - if (stop && msg->len != 0) - flag |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); - - r = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - dev->adapter.timeout); - if (r == 0) { - dev_err(dev->dev, "controller timed out\n"); - i2c_recover_bus(dev); - i2c_davinci_init(dev); - dev->buf_len = 0; - return -ETIMEDOUT; - } - if (dev->buf_len) { - /* This should be 0 if all bytes were transferred - * or dev->cmd_err denotes an error. - * A signal may have aborted the transfer. - */ - if (r >= 0) { - dev_err(dev->dev, "abnormal termination buf_len=%i\n", - dev->buf_len); - r = -EREMOTEIO; - } - dev->terminate = 1; - wmb(); - dev->buf_len = 0; - } - if (r < 0) - return r; - - /* no error */ - if (likely(!dev->cmd_err)) - return msg->len; - - /* We have an error */ - if (dev->cmd_err & DAVINCI_I2C_STR_AL) { - i2c_davinci_init(dev); - return -EIO; - } - - if (dev->cmd_err & DAVINCI_I2C_STR_NACK) { - if (msg->flags & I2C_M_IGNORE_NAK) - return msg->len; - if (stop) { - w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - w |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); - } - return -EREMOTEIO; - } - return -EIO; -} - -/* - * Prepare controller for a transaction and call i2c_davinci_xfer_msg - */ -static int -i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct davinci_i2c_dev *dev = i2c_get_adapdata(adap); - int i; - int ret; - - dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); - - ret = i2c_davinci_wait_bus_not_busy(dev, 1); - if (ret < 0) { - dev_warn(dev->dev, "timeout waiting for bus ready\n"); - return ret; - } - - for (i = 0; i < num; i++) { - ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1))); - dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num, - ret); - if (ret < 0) - return ret; - } - -#ifdef CONFIG_CPU_FREQ - complete(&dev->xfr_complete); -#endif - - return num; -} - -static u32 i2c_davinci_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static void terminate_read(struct davinci_i2c_dev *dev) -{ - u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - w |= DAVINCI_I2C_MDR_NACK; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); - - /* Throw away data */ - davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG); - if (!dev->terminate) - dev_err(dev->dev, "RDR IRQ while no data requested\n"); -} -static void terminate_write(struct davinci_i2c_dev *dev) -{ - u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); - w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w); - - if (!dev->terminate) - dev_dbg(dev->dev, "TDR IRQ while no data to send\n"); -} - -/* - * Interrupt service routine. This gets called whenever an I2C interrupt - * occurs. - */ -static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id) -{ - struct davinci_i2c_dev *dev = dev_id; - u32 stat; - int count = 0; - u16 w; - - while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) { - dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat); - if (count++ == 100) { - dev_warn(dev->dev, "Too much work in one IRQ\n"); - break; - } - - switch (stat) { - case DAVINCI_I2C_IVR_AL: - /* Arbitration lost, must retry */ - dev->cmd_err |= DAVINCI_I2C_STR_AL; - dev->buf_len = 0; - complete(&dev->cmd_complete); - break; - - case DAVINCI_I2C_IVR_NACK: - dev->cmd_err |= DAVINCI_I2C_STR_NACK; - dev->buf_len = 0; - complete(&dev->cmd_complete); - break; - - case DAVINCI_I2C_IVR_ARDY: - davinci_i2c_write_reg(dev, - DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_ARDY); - if (((dev->buf_len == 0) && (dev->stop != 0)) || - (dev->cmd_err & DAVINCI_I2C_STR_NACK)) { - w = davinci_i2c_read_reg(dev, - DAVINCI_I2C_MDR_REG); - w |= DAVINCI_I2C_MDR_STP; - davinci_i2c_write_reg(dev, - DAVINCI_I2C_MDR_REG, w); - } - complete(&dev->cmd_complete); - break; - - case DAVINCI_I2C_IVR_RDR: - if (dev->buf_len) { - *dev->buf++ = - davinci_i2c_read_reg(dev, - DAVINCI_I2C_DRR_REG); - dev->buf_len--; - if (dev->buf_len) - continue; - - davinci_i2c_write_reg(dev, - DAVINCI_I2C_STR_REG, - DAVINCI_I2C_IMR_RRDY); - } else { - /* signal can terminate transfer */ - terminate_read(dev); - } - break; - - case DAVINCI_I2C_IVR_XRDY: - if (dev->buf_len) { - davinci_i2c_write_reg(dev, DAVINCI_I2C_DXR_REG, - *dev->buf++); - dev->buf_len--; - if (dev->buf_len) - continue; - - w = davinci_i2c_read_reg(dev, - DAVINCI_I2C_IMR_REG); - w &= ~DAVINCI_I2C_IMR_XRDY; - davinci_i2c_write_reg(dev, - DAVINCI_I2C_IMR_REG, - w); - } else { - /* signal can terminate transfer */ - terminate_write(dev); - } - break; - - case DAVINCI_I2C_IVR_SCD: - davinci_i2c_write_reg(dev, - DAVINCI_I2C_STR_REG, DAVINCI_I2C_STR_SCD); - complete(&dev->cmd_complete); - break; - - case DAVINCI_I2C_IVR_AAS: - dev_dbg(dev->dev, "Address as slave interrupt\n"); - break; - - default: - dev_warn(dev->dev, "Unrecognized irq stat %d\n", stat); - break; - } - } - - return count ? IRQ_HANDLED : IRQ_NONE; -} - -#ifdef CONFIG_CPU_FREQ -static int i2c_davinci_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct davinci_i2c_dev *dev; - - dev = container_of(nb, struct davinci_i2c_dev, freq_transition); - if (val == CPUFREQ_PRECHANGE) { - wait_for_completion(&dev->xfr_complete); - davinci_i2c_reset_ctrl(dev, 0); - } else if (val == CPUFREQ_POSTCHANGE) { - i2c_davinci_calc_clk_dividers(dev); - davinci_i2c_reset_ctrl(dev, 1); - } - - return 0; -} - -static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) -{ - dev->freq_transition.notifier_call = i2c_davinci_cpufreq_transition; - - return cpufreq_register_notifier(&dev->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) -{ - cpufreq_unregister_notifier(&dev->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} -#else -static inline int i2c_davinci_cpufreq_register(struct davinci_i2c_dev *dev) -{ - return 0; -} - -static inline void i2c_davinci_cpufreq_deregister(struct davinci_i2c_dev *dev) -{ -} -#endif - -static struct i2c_algorithm i2c_davinci_algo = { - .master_xfer = i2c_davinci_xfer, - .functionality = i2c_davinci_func, -}; - -static int davinci_i2c_probe(struct platform_device *pdev) -{ - struct davinci_i2c_dev *dev; - struct i2c_adapter *adap; - struct resource *mem, *irq, *ioarea; - int r; - - /* NOTE: driver uses the static register mapping */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - dev_err(&pdev->dev, "no irq resource?\n"); - return -ENODEV; - } - - ioarea = request_mem_region(mem->start, resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } - - dev = kzalloc(sizeof(struct davinci_i2c_dev), GFP_KERNEL); - if (!dev) { - r = -ENOMEM; - goto err_release_region; - } - - init_completion(&dev->cmd_complete); -#ifdef CONFIG_CPU_FREQ - init_completion(&dev->xfr_complete); -#endif - dev->dev = get_device(&pdev->dev); - dev->irq = irq->start; - platform_set_drvdata(pdev, dev); - - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - r = -ENODEV; - goto err_free_mem; - } - clk_enable(dev->clk); - - dev->base = ioremap(mem->start, resource_size(mem)); - if (!dev->base) { - r = -EBUSY; - goto err_mem_ioremap; - } - - i2c_davinci_init(dev); - - r = request_irq(dev->irq, i2c_davinci_isr, 0, pdev->name, dev); - if (r) { - dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); - goto err_unuse_clocks; - } - - r = i2c_davinci_cpufreq_register(dev); - if (r) { - dev_err(&pdev->dev, "failed to register cpufreq\n"); - goto err_free_irq; - } - - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; - strlcpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name)); - adap->algo = &i2c_davinci_algo; - adap->dev.parent = &pdev->dev; - adap->timeout = DAVINCI_I2C_TIMEOUT; - - adap->nr = pdev->id; - r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(&pdev->dev, "failure adding adapter\n"); - goto err_free_irq; - } - - return 0; - -err_free_irq: - free_irq(dev->irq, dev); -err_unuse_clocks: - iounmap(dev->base); -err_mem_ioremap: - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; -err_free_mem: - platform_set_drvdata(pdev, NULL); - put_device(&pdev->dev); - kfree(dev); -err_release_region: - release_mem_region(mem->start, resource_size(mem)); - - return r; -} - -static int davinci_i2c_remove(struct platform_device *pdev) -{ - struct davinci_i2c_dev *dev = platform_get_drvdata(pdev); - struct resource *mem; - - i2c_davinci_cpufreq_deregister(dev); - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&dev->adapter); - put_device(&pdev->dev); - - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, 0); - free_irq(dev->irq, dev); - iounmap(dev->base); - kfree(dev); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - return 0; -} - -#ifdef CONFIG_PM -static int davinci_i2c_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - - /* put I2C into reset */ - davinci_i2c_reset_ctrl(i2c_dev, 0); - clk_disable(i2c_dev->clk); - - return 0; -} - -static int davinci_i2c_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct davinci_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - - clk_enable(i2c_dev->clk); - /* take I2C out of reset */ - davinci_i2c_reset_ctrl(i2c_dev, 1); - - return 0; -} - -static const struct dev_pm_ops davinci_i2c_pm = { - .suspend = davinci_i2c_suspend, - .resume = davinci_i2c_resume, -}; - -#define davinci_i2c_pm_ops (&davinci_i2c_pm) -#else -#define davinci_i2c_pm_ops NULL -#endif - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:i2c_davinci"); - -static struct platform_driver davinci_i2c_driver = { - .probe = davinci_i2c_probe, - .remove = davinci_i2c_remove, - .driver = { - .name = "i2c_davinci", - .owner = THIS_MODULE, - .pm = davinci_i2c_pm_ops, - }, -}; - -/* I2C may be needed to bring up other drivers */ -static int __init davinci_i2c_init_driver(void) -{ - return platform_driver_register(&davinci_i2c_driver); -} -subsys_initcall(davinci_i2c_init_driver); - -static void __exit davinci_i2c_exit_driver(void) -{ - platform_driver_unregister(&davinci_i2c_driver); -} -module_exit(davinci_i2c_exit_driver); - -MODULE_AUTHOR("Texas Instruments India"); -MODULE_DESCRIPTION("TI DaVinci I2C bus adapter"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.c deleted file mode 100644 index df879924..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Synopsys DesignWare I2C adapter driver (master only). - * - * Based on the TI DAVINCI I2C adapter driver. - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * - * ---------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ -#include <linux/clk.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/pm_runtime.h> -#include <linux/delay.h> -#include "i2c-designware-core.h" - -/* - * Registers offset - */ -#define DW_IC_CON 0x0 -#define DW_IC_TAR 0x4 -#define DW_IC_DATA_CMD 0x10 -#define DW_IC_SS_SCL_HCNT 0x14 -#define DW_IC_SS_SCL_LCNT 0x18 -#define DW_IC_FS_SCL_HCNT 0x1c -#define DW_IC_FS_SCL_LCNT 0x20 -#define DW_IC_INTR_STAT 0x2c -#define DW_IC_INTR_MASK 0x30 -#define DW_IC_RAW_INTR_STAT 0x34 -#define DW_IC_RX_TL 0x38 -#define DW_IC_TX_TL 0x3c -#define DW_IC_CLR_INTR 0x40 -#define DW_IC_CLR_RX_UNDER 0x44 -#define DW_IC_CLR_RX_OVER 0x48 -#define DW_IC_CLR_TX_OVER 0x4c -#define DW_IC_CLR_RD_REQ 0x50 -#define DW_IC_CLR_TX_ABRT 0x54 -#define DW_IC_CLR_RX_DONE 0x58 -#define DW_IC_CLR_ACTIVITY 0x5c -#define DW_IC_CLR_STOP_DET 0x60 -#define DW_IC_CLR_START_DET 0x64 -#define DW_IC_CLR_GEN_CALL 0x68 -#define DW_IC_ENABLE 0x6c -#define DW_IC_STATUS 0x70 -#define DW_IC_TXFLR 0x74 -#define DW_IC_RXFLR 0x78 -#define DW_IC_TX_ABRT_SOURCE 0x80 -#define DW_IC_COMP_PARAM_1 0xf4 -#define DW_IC_COMP_TYPE 0xfc -#define DW_IC_COMP_TYPE_VALUE 0x44570140 - -#define DW_IC_INTR_RX_UNDER 0x001 -#define DW_IC_INTR_RX_OVER 0x002 -#define DW_IC_INTR_RX_FULL 0x004 -#define DW_IC_INTR_TX_OVER 0x008 -#define DW_IC_INTR_TX_EMPTY 0x010 -#define DW_IC_INTR_RD_REQ 0x020 -#define DW_IC_INTR_TX_ABRT 0x040 -#define DW_IC_INTR_RX_DONE 0x080 -#define DW_IC_INTR_ACTIVITY 0x100 -#define DW_IC_INTR_STOP_DET 0x200 -#define DW_IC_INTR_START_DET 0x400 -#define DW_IC_INTR_GEN_CALL 0x800 - -#define DW_IC_INTR_DEFAULT_MASK (DW_IC_INTR_RX_FULL | \ - DW_IC_INTR_TX_EMPTY | \ - DW_IC_INTR_TX_ABRT | \ - DW_IC_INTR_STOP_DET) - -#define DW_IC_STATUS_ACTIVITY 0x1 - -#define DW_IC_ERR_TX_ABRT 0x1 - -/* - * status codes - */ -#define STATUS_IDLE 0x0 -#define STATUS_WRITE_IN_PROGRESS 0x1 -#define STATUS_READ_IN_PROGRESS 0x2 - -#define TIMEOUT 20 /* ms */ - -/* - * hardware abort codes from the DW_IC_TX_ABRT_SOURCE register - * - * only expected abort codes are listed here - * refer to the datasheet for the full list - */ -#define ABRT_7B_ADDR_NOACK 0 -#define ABRT_10ADDR1_NOACK 1 -#define ABRT_10ADDR2_NOACK 2 -#define ABRT_TXDATA_NOACK 3 -#define ABRT_GCALL_NOACK 4 -#define ABRT_GCALL_READ 5 -#define ABRT_SBYTE_ACKDET 7 -#define ABRT_SBYTE_NORSTRT 9 -#define ABRT_10B_RD_NORSTRT 10 -#define ABRT_MASTER_DIS 11 -#define ARB_LOST 12 - -#define DW_IC_TX_ABRT_7B_ADDR_NOACK (1UL << ABRT_7B_ADDR_NOACK) -#define DW_IC_TX_ABRT_10ADDR1_NOACK (1UL << ABRT_10ADDR1_NOACK) -#define DW_IC_TX_ABRT_10ADDR2_NOACK (1UL << ABRT_10ADDR2_NOACK) -#define DW_IC_TX_ABRT_TXDATA_NOACK (1UL << ABRT_TXDATA_NOACK) -#define DW_IC_TX_ABRT_GCALL_NOACK (1UL << ABRT_GCALL_NOACK) -#define DW_IC_TX_ABRT_GCALL_READ (1UL << ABRT_GCALL_READ) -#define DW_IC_TX_ABRT_SBYTE_ACKDET (1UL << ABRT_SBYTE_ACKDET) -#define DW_IC_TX_ABRT_SBYTE_NORSTRT (1UL << ABRT_SBYTE_NORSTRT) -#define DW_IC_TX_ABRT_10B_RD_NORSTRT (1UL << ABRT_10B_RD_NORSTRT) -#define DW_IC_TX_ABRT_MASTER_DIS (1UL << ABRT_MASTER_DIS) -#define DW_IC_TX_ARB_LOST (1UL << ARB_LOST) - -#define DW_IC_TX_ABRT_NOACK (DW_IC_TX_ABRT_7B_ADDR_NOACK | \ - DW_IC_TX_ABRT_10ADDR1_NOACK | \ - DW_IC_TX_ABRT_10ADDR2_NOACK | \ - DW_IC_TX_ABRT_TXDATA_NOACK | \ - DW_IC_TX_ABRT_GCALL_NOACK) - -static char *abort_sources[] = { - [ABRT_7B_ADDR_NOACK] = - "slave address not acknowledged (7bit mode)", - [ABRT_10ADDR1_NOACK] = - "first address byte not acknowledged (10bit mode)", - [ABRT_10ADDR2_NOACK] = - "second address byte not acknowledged (10bit mode)", - [ABRT_TXDATA_NOACK] = - "data not acknowledged", - [ABRT_GCALL_NOACK] = - "no acknowledgement for a general call", - [ABRT_GCALL_READ] = - "read after general call", - [ABRT_SBYTE_ACKDET] = - "start byte acknowledged", - [ABRT_SBYTE_NORSTRT] = - "trying to send start byte when restart is disabled", - [ABRT_10B_RD_NORSTRT] = - "trying to read when restart is disabled (10bit mode)", - [ABRT_MASTER_DIS] = - "trying to use disabled adapter", - [ARB_LOST] = - "lost arbitration", -}; - -u32 dw_readl(struct dw_i2c_dev *dev, int offset) -{ - u32 value = readl(dev->base + offset); - - if (dev->swab) - return swab32(value); - else - return value; -} - -void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset) -{ - if (dev->swab) - b = swab32(b); - - writel(b, dev->base + offset); -} - -static u32 -i2c_dw_scl_hcnt(u32 ic_clk, u32 tSYMBOL, u32 tf, int cond, int offset) -{ - /* - * DesignWare I2C core doesn't seem to have solid strategy to meet - * the tHD;STA timing spec. Configuring _HCNT based on tHIGH spec - * will result in violation of the tHD;STA spec. - */ - if (cond) - /* - * Conditional expression: - * - * IC_[FS]S_SCL_HCNT + (1+4+3) >= IC_CLK * tHIGH - * - * This is based on the DW manuals, and represents an ideal - * configuration. The resulting I2C bus speed will be - * faster than any of the others. - * - * If your hardware is free from tHD;STA issue, try this one. - */ - return (ic_clk * tSYMBOL + 5000) / 10000 - 8 + offset; - else - /* - * Conditional expression: - * - * IC_[FS]S_SCL_HCNT + 3 >= IC_CLK * (tHD;STA + tf) - * - * This is just experimental rule; the tHD;STA period turned - * out to be proportinal to (_HCNT + 3). With this setting, - * we could meet both tHIGH and tHD;STA timing specs. - * - * If unsure, you'd better to take this alternative. - * - * The reason why we need to take into account "tf" here, - * is the same as described in i2c_dw_scl_lcnt(). - */ - return (ic_clk * (tSYMBOL + tf) + 5000) / 10000 - 3 + offset; -} - -static u32 i2c_dw_scl_lcnt(u32 ic_clk, u32 tLOW, u32 tf, int offset) -{ - /* - * Conditional expression: - * - * IC_[FS]S_SCL_LCNT + 1 >= IC_CLK * (tLOW + tf) - * - * DW I2C core starts counting the SCL CNTs for the LOW period - * of the SCL clock (tLOW) as soon as it pulls the SCL line. - * In order to meet the tLOW timing spec, we need to take into - * account the fall time of SCL signal (tf). Default tf value - * should be 0.3 us, for safety. - */ - return ((ic_clk * (tLOW + tf) + 5000) / 10000) - 1 + offset; -} - -/** - * i2c_dw_init() - initialize the designware i2c master hardware - * @dev: device private data - * - * This functions configures and enables the I2C master. - * This function is called during I2C init function, and in case of timeout at - * run time. - */ -int i2c_dw_init(struct dw_i2c_dev *dev) -{ - u32 input_clock_khz; - u32 hcnt, lcnt; - u32 reg; - - input_clock_khz = dev->get_clk_rate_khz(dev); - - /* Configure register endianess access */ - reg = dw_readl(dev, DW_IC_COMP_TYPE); - if (reg == ___constant_swab32(DW_IC_COMP_TYPE_VALUE)) { - dev->swab = 1; - reg = DW_IC_COMP_TYPE_VALUE; - } - - if (reg != DW_IC_COMP_TYPE_VALUE) { - dev_err(dev->dev, "Unknown Synopsys component type: " - "0x%08x\n", reg); - return -ENODEV; - } - - /* Disable the adapter */ - dw_writel(dev, 0, DW_IC_ENABLE); - - /* set standard and fast speed deviders for high/low periods */ - - /* Standard-mode */ - hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 40, /* tHD;STA = tHIGH = 4.0 us */ - 3, /* tf = 0.3 us */ - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ - lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 47, /* tLOW = 4.7 us */ - 3, /* tf = 0.3 us */ - 0); /* No offset */ - dw_writel(dev, hcnt, DW_IC_SS_SCL_HCNT); - dw_writel(dev, lcnt, DW_IC_SS_SCL_LCNT); - dev_dbg(dev->dev, "Standard-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); - - /* Fast-mode */ - hcnt = i2c_dw_scl_hcnt(input_clock_khz, - 6, /* tHD;STA = tHIGH = 0.6 us */ - 3, /* tf = 0.3 us */ - 0, /* 0: DW default, 1: Ideal */ - 0); /* No offset */ - lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 13, /* tLOW = 1.3 us */ - 3, /* tf = 0.3 us */ - 0); /* No offset */ - dw_writel(dev, hcnt, DW_IC_FS_SCL_HCNT); - dw_writel(dev, lcnt, DW_IC_FS_SCL_LCNT); - dev_dbg(dev->dev, "Fast-mode HCNT:LCNT = %d:%d\n", hcnt, lcnt); - - /* Configure Tx/Rx FIFO threshold levels */ - dw_writel(dev, dev->tx_fifo_depth - 1, DW_IC_TX_TL); - dw_writel(dev, 0, DW_IC_RX_TL); - - /* configure the i2c master */ - dw_writel(dev, dev->master_cfg , DW_IC_CON); - return 0; -} - -/* - * Waiting for bus not busy - */ -static int i2c_dw_wait_bus_not_busy(struct dw_i2c_dev *dev) -{ - int timeout = TIMEOUT; - - while (dw_readl(dev, DW_IC_STATUS) & DW_IC_STATUS_ACTIVITY) { - if (timeout <= 0) { - dev_warn(dev->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; - } - timeout--; - mdelay(1); - } - - return 0; -} - -static void i2c_dw_xfer_init(struct dw_i2c_dev *dev) -{ - struct i2c_msg *msgs = dev->msgs; - u32 ic_con; - - /* Disable the adapter */ - dw_writel(dev, 0, DW_IC_ENABLE); - - /* set the slave (target) address */ - dw_writel(dev, msgs[dev->msg_write_idx].addr, DW_IC_TAR); - - /* if the slave address is ten bit address, enable 10BITADDR */ - ic_con = dw_readl(dev, DW_IC_CON); - if (msgs[dev->msg_write_idx].flags & I2C_M_TEN) - ic_con |= DW_IC_CON_10BITADDR_MASTER; - else - ic_con &= ~DW_IC_CON_10BITADDR_MASTER; - dw_writel(dev, ic_con, DW_IC_CON); - - /* Enable the adapter */ - dw_writel(dev, 1, DW_IC_ENABLE); - - /* Enable interrupts */ - dw_writel(dev, DW_IC_INTR_DEFAULT_MASK, DW_IC_INTR_MASK); -} - -/* - * Initiate (and continue) low level master read/write transaction. - * This function is only called from i2c_dw_isr, and pumping i2c_msg - * messages into the tx buffer. Even if the size of i2c_msg data is - * longer than the size of the tx buffer, it handles everything. - */ -void -i2c_dw_xfer_msg(struct dw_i2c_dev *dev) -{ - struct i2c_msg *msgs = dev->msgs; - u32 intr_mask; - int tx_limit, rx_limit; - u32 addr = msgs[dev->msg_write_idx].addr; - u32 buf_len = dev->tx_buf_len; - u8 *buf = dev->tx_buf; - - intr_mask = DW_IC_INTR_DEFAULT_MASK; - - for (; dev->msg_write_idx < dev->msgs_num; dev->msg_write_idx++) { - /* - * if target address has changed, we need to - * reprogram the target address in the i2c - * adapter when we are done with this transfer - */ - if (msgs[dev->msg_write_idx].addr != addr) { - dev_err(dev->dev, - "%s: invalid target address\n", __func__); - dev->msg_err = -EINVAL; - break; - } - - if (msgs[dev->msg_write_idx].len == 0) { - dev_err(dev->dev, - "%s: invalid message length\n", __func__); - dev->msg_err = -EINVAL; - break; - } - - if (!(dev->status & STATUS_WRITE_IN_PROGRESS)) { - /* new i2c_msg */ - buf = msgs[dev->msg_write_idx].buf; - buf_len = msgs[dev->msg_write_idx].len; - } - - tx_limit = dev->tx_fifo_depth - dw_readl(dev, DW_IC_TXFLR); - rx_limit = dev->rx_fifo_depth - dw_readl(dev, DW_IC_RXFLR); - - while (buf_len > 0 && tx_limit > 0 && rx_limit > 0) { - if (msgs[dev->msg_write_idx].flags & I2C_M_RD) { - dw_writel(dev, 0x100, DW_IC_DATA_CMD); - rx_limit--; - } else - dw_writel(dev, *buf++, DW_IC_DATA_CMD); - tx_limit--; buf_len--; - } - - dev->tx_buf = buf; - dev->tx_buf_len = buf_len; - - if (buf_len > 0) { - /* more bytes to be written */ - dev->status |= STATUS_WRITE_IN_PROGRESS; - break; - } else - dev->status &= ~STATUS_WRITE_IN_PROGRESS; - } - - /* - * If i2c_msg index search is completed, we don't need TX_EMPTY - * interrupt any more. - */ - if (dev->msg_write_idx == dev->msgs_num) - intr_mask &= ~DW_IC_INTR_TX_EMPTY; - - if (dev->msg_err) - intr_mask = 0; - - dw_writel(dev, intr_mask, DW_IC_INTR_MASK); -} - -static void -i2c_dw_read(struct dw_i2c_dev *dev) -{ - struct i2c_msg *msgs = dev->msgs; - int rx_valid; - - for (; dev->msg_read_idx < dev->msgs_num; dev->msg_read_idx++) { - u32 len; - u8 *buf; - - if (!(msgs[dev->msg_read_idx].flags & I2C_M_RD)) - continue; - - if (!(dev->status & STATUS_READ_IN_PROGRESS)) { - len = msgs[dev->msg_read_idx].len; - buf = msgs[dev->msg_read_idx].buf; - } else { - len = dev->rx_buf_len; - buf = dev->rx_buf; - } - - rx_valid = dw_readl(dev, DW_IC_RXFLR); - - for (; len > 0 && rx_valid > 0; len--, rx_valid--) - *buf++ = dw_readl(dev, DW_IC_DATA_CMD); - - if (len > 0) { - dev->status |= STATUS_READ_IN_PROGRESS; - dev->rx_buf_len = len; - dev->rx_buf = buf; - return; - } else - dev->status &= ~STATUS_READ_IN_PROGRESS; - } -} - -static int i2c_dw_handle_tx_abort(struct dw_i2c_dev *dev) -{ - unsigned long abort_source = dev->abort_source; - int i; - - if (abort_source & DW_IC_TX_ABRT_NOACK) { - for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) - dev_dbg(dev->dev, - "%s: %s\n", __func__, abort_sources[i]); - return -EREMOTEIO; - } - - for_each_set_bit(i, &abort_source, ARRAY_SIZE(abort_sources)) - dev_err(dev->dev, "%s: %s\n", __func__, abort_sources[i]); - - if (abort_source & DW_IC_TX_ARB_LOST) - return -EAGAIN; - else if (abort_source & DW_IC_TX_ABRT_GCALL_READ) - return -EINVAL; /* wrong msgs[] data */ - else - return -EIO; -} - -/* - * Prepare controller for a transaction and call i2c_dw_xfer_msg - */ -int -i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct dw_i2c_dev *dev = i2c_get_adapdata(adap); - int ret; - - dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num); - - mutex_lock(&dev->lock); - pm_runtime_get_sync(dev->dev); - - INIT_COMPLETION(dev->cmd_complete); - dev->msgs = msgs; - dev->msgs_num = num; - dev->cmd_err = 0; - dev->msg_write_idx = 0; - dev->msg_read_idx = 0; - dev->msg_err = 0; - dev->status = STATUS_IDLE; - dev->abort_source = 0; - - ret = i2c_dw_wait_bus_not_busy(dev); - if (ret < 0) - goto done; - - /* start the transfers */ - i2c_dw_xfer_init(dev); - - /* wait for tx to complete */ - ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, HZ); - if (ret == 0) { - dev_err(dev->dev, "controller timed out\n"); - i2c_dw_init(dev); - ret = -ETIMEDOUT; - goto done; - } else if (ret < 0) - goto done; - - if (dev->msg_err) { - ret = dev->msg_err; - goto done; - } - - /* no error */ - if (likely(!dev->cmd_err)) { - /* Disable the adapter */ - dw_writel(dev, 0, DW_IC_ENABLE); - ret = num; - goto done; - } - - /* We have an error */ - if (dev->cmd_err == DW_IC_ERR_TX_ABRT) { - ret = i2c_dw_handle_tx_abort(dev); - goto done; - } - ret = -EIO; - -done: - pm_runtime_put(dev->dev); - mutex_unlock(&dev->lock); - - return ret; -} - -u32 i2c_dw_func(struct i2c_adapter *adap) -{ - struct dw_i2c_dev *dev = i2c_get_adapdata(adap); - return dev->functionality; -} - -static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev) -{ - u32 stat; - - /* - * The IC_INTR_STAT register just indicates "enabled" interrupts. - * Ths unmasked raw version of interrupt status bits are available - * in the IC_RAW_INTR_STAT register. - * - * That is, - * stat = dw_readl(IC_INTR_STAT); - * equals to, - * stat = dw_readl(IC_RAW_INTR_STAT) & dw_readl(IC_INTR_MASK); - * - * The raw version might be useful for debugging purposes. - */ - stat = dw_readl(dev, DW_IC_INTR_STAT); - - /* - * Do not use the IC_CLR_INTR register to clear interrupts, or - * you'll miss some interrupts, triggered during the period from - * dw_readl(IC_INTR_STAT) to dw_readl(IC_CLR_INTR). - * - * Instead, use the separately-prepared IC_CLR_* registers. - */ - if (stat & DW_IC_INTR_RX_UNDER) - dw_readl(dev, DW_IC_CLR_RX_UNDER); - if (stat & DW_IC_INTR_RX_OVER) - dw_readl(dev, DW_IC_CLR_RX_OVER); - if (stat & DW_IC_INTR_TX_OVER) - dw_readl(dev, DW_IC_CLR_TX_OVER); - if (stat & DW_IC_INTR_RD_REQ) - dw_readl(dev, DW_IC_CLR_RD_REQ); - if (stat & DW_IC_INTR_TX_ABRT) { - /* - * The IC_TX_ABRT_SOURCE register is cleared whenever - * the IC_CLR_TX_ABRT is read. Preserve it beforehand. - */ - dev->abort_source = dw_readl(dev, DW_IC_TX_ABRT_SOURCE); - dw_readl(dev, DW_IC_CLR_TX_ABRT); - } - if (stat & DW_IC_INTR_RX_DONE) - dw_readl(dev, DW_IC_CLR_RX_DONE); - if (stat & DW_IC_INTR_ACTIVITY) - dw_readl(dev, DW_IC_CLR_ACTIVITY); - if (stat & DW_IC_INTR_STOP_DET) - dw_readl(dev, DW_IC_CLR_STOP_DET); - if (stat & DW_IC_INTR_START_DET) - dw_readl(dev, DW_IC_CLR_START_DET); - if (stat & DW_IC_INTR_GEN_CALL) - dw_readl(dev, DW_IC_CLR_GEN_CALL); - - return stat; -} - -/* - * Interrupt service routine. This gets called whenever an I2C interrupt - * occurs. - */ -irqreturn_t i2c_dw_isr(int this_irq, void *dev_id) -{ - struct dw_i2c_dev *dev = dev_id; - u32 stat, enabled; - - enabled = dw_readl(dev, DW_IC_ENABLE); - stat = dw_readl(dev, DW_IC_RAW_INTR_STAT); - dev_dbg(dev->dev, "%s: %s enabled= 0x%x stat=0x%x\n", __func__, - dev->adapter.name, enabled, stat); - if (!enabled || !(stat & ~DW_IC_INTR_ACTIVITY)) - return IRQ_NONE; - - stat = i2c_dw_read_clear_intrbits(dev); - - if (stat & DW_IC_INTR_TX_ABRT) { - dev->cmd_err |= DW_IC_ERR_TX_ABRT; - dev->status = STATUS_IDLE; - - /* - * Anytime TX_ABRT is set, the contents of the tx/rx - * buffers are flushed. Make sure to skip them. - */ - dw_writel(dev, 0, DW_IC_INTR_MASK); - goto tx_aborted; - } - - if (stat & DW_IC_INTR_RX_FULL) - i2c_dw_read(dev); - - if (stat & DW_IC_INTR_TX_EMPTY) - i2c_dw_xfer_msg(dev); - - /* - * No need to modify or disable the interrupt mask here. - * i2c_dw_xfer_msg() will take care of it according to - * the current transmit status. - */ - -tx_aborted: - if ((stat & (DW_IC_INTR_TX_ABRT | DW_IC_INTR_STOP_DET)) || dev->msg_err) - complete(&dev->cmd_complete); - - return IRQ_HANDLED; -} - -void i2c_dw_enable(struct dw_i2c_dev *dev) -{ - /* Enable the adapter */ - dw_writel(dev, 1, DW_IC_ENABLE); -} - -u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev) -{ - return dw_readl(dev, DW_IC_ENABLE); -} - -void i2c_dw_disable(struct dw_i2c_dev *dev) -{ - /* Disable controller */ - dw_writel(dev, 0, DW_IC_ENABLE); - - /* Disable all interupts */ - dw_writel(dev, 0, DW_IC_INTR_MASK); - dw_readl(dev, DW_IC_CLR_INTR); -} - -void i2c_dw_clear_int(struct dw_i2c_dev *dev) -{ - dw_readl(dev, DW_IC_CLR_INTR); -} - -void i2c_dw_disable_int(struct dw_i2c_dev *dev) -{ - dw_writel(dev, 0, DW_IC_INTR_MASK); -} - -u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) -{ - return dw_readl(dev, DW_IC_COMP_PARAM_1); -} diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.h b/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.h deleted file mode 100644 index 02d1a2dd..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-core.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Synopsys DesignWare I2C adapter driver (master only). - * - * Based on the TI DAVINCI I2C adapter driver. - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * - * ---------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ - - -#define DW_IC_CON_MASTER 0x1 -#define DW_IC_CON_SPEED_STD 0x2 -#define DW_IC_CON_SPEED_FAST 0x4 -#define DW_IC_CON_10BITADDR_MASTER 0x10 -#define DW_IC_CON_RESTART_EN 0x20 -#define DW_IC_CON_SLAVE_DISABLE 0x40 - - -/** - * struct dw_i2c_dev - private i2c-designware data - * @dev: driver model device node - * @base: IO registers pointer - * @cmd_complete: tx completion indicator - * @lock: protect this struct and IO registers - * @clk: input reference clock - * @cmd_err: run time hadware error code - * @msgs: points to an array of messages currently being transfered - * @msgs_num: the number of elements in msgs - * @msg_write_idx: the element index of the current tx message in the msgs - * array - * @tx_buf_len: the length of the current tx buffer - * @tx_buf: the current tx buffer - * @msg_read_idx: the element index of the current rx message in the msgs - * array - * @rx_buf_len: the length of the current rx buffer - * @rx_buf: the current rx buffer - * @msg_err: error status of the current transfer - * @status: i2c master status, one of STATUS_* - * @abort_source: copy of the TX_ABRT_SOURCE register - * @irq: interrupt number for the i2c master - * @adapter: i2c subsystem adapter node - * @tx_fifo_depth: depth of the hardware tx fifo - * @rx_fifo_depth: depth of the hardware rx fifo - */ -struct dw_i2c_dev { - struct device *dev; - void __iomem *base; - struct completion cmd_complete; - struct mutex lock; - struct clk *clk; - u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev); - struct dw_pci_controller *controller; - int cmd_err; - struct i2c_msg *msgs; - int msgs_num; - int msg_write_idx; - u32 tx_buf_len; - u8 *tx_buf; - int msg_read_idx; - u32 rx_buf_len; - u8 *rx_buf; - int msg_err; - unsigned int status; - u32 abort_source; - int irq; - int swab; - struct i2c_adapter adapter; - u32 functionality; - u32 master_cfg; - unsigned int tx_fifo_depth; - unsigned int rx_fifo_depth; -}; - -extern u32 dw_readl(struct dw_i2c_dev *dev, int offset); -extern void dw_writel(struct dw_i2c_dev *dev, u32 b, int offset); -extern int i2c_dw_init(struct dw_i2c_dev *dev); -extern int i2c_dw_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - int num); -extern u32 i2c_dw_func(struct i2c_adapter *adap); -extern irqreturn_t i2c_dw_isr(int this_irq, void *dev_id); -extern void i2c_dw_enable(struct dw_i2c_dev *dev); -extern u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev); -extern void i2c_dw_disable(struct dw_i2c_dev *dev); -extern void i2c_dw_clear_int(struct dw_i2c_dev *dev); -extern void i2c_dw_disable_int(struct dw_i2c_dev *dev); -extern u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-pcidrv.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-pcidrv.c deleted file mode 100644 index 00e8f213..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-pcidrv.c +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Synopsys DesignWare I2C adapter driver (master only). - * - * Based on the TI DAVINCI I2C adapter driver. - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * Copyright (C) 2011 Intel corporation. - * - * ---------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/pci.h> -#include <linux/pm_runtime.h> -#include "i2c-designware-core.h" - -#define DRIVER_NAME "i2c-designware-pci" - -enum dw_pci_ctl_id_t { - moorestown_0, - moorestown_1, - moorestown_2, - - medfield_0, - medfield_1, - medfield_2, - medfield_3, - medfield_4, - medfield_5, -}; - -struct dw_pci_controller { - u32 bus_num; - u32 bus_cfg; - u32 tx_fifo_depth; - u32 rx_fifo_depth; - u32 clk_khz; -}; - -#define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ - DW_IC_CON_SLAVE_DISABLE | \ - DW_IC_CON_RESTART_EN) - -static struct dw_pci_controller dw_pci_controllers[] = { - [moorestown_0] = { - .bus_num = 0, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [moorestown_1] = { - .bus_num = 1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [moorestown_2] = { - .bus_num = 2, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_0] = { - .bus_num = 0, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_1] = { - .bus_num = 1, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_2] = { - .bus_num = 2, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_3] = { - .bus_num = 3, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_STD, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_4] = { - .bus_num = 4, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, - [medfield_5] = { - .bus_num = 5, - .bus_cfg = INTEL_MID_STD_CFG | DW_IC_CON_SPEED_FAST, - .tx_fifo_depth = 32, - .rx_fifo_depth = 32, - .clk_khz = 25000, - }, -}; -static struct i2c_algorithm i2c_dw_algo = { - .master_xfer = i2c_dw_xfer, - .functionality = i2c_dw_func, -}; - -static int i2c_dw_pci_suspend(struct device *dev) -{ - struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); - struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); - int err; - - - i2c_dw_disable(i2c); - - err = pci_save_state(pdev); - if (err) { - dev_err(&pdev->dev, "pci_save_state failed\n"); - return err; - } - - err = pci_set_power_state(pdev, PCI_D3hot); - if (err) { - dev_err(&pdev->dev, "pci_set_power_state failed\n"); - return err; - } - - return 0; -} - -static int i2c_dw_pci_resume(struct device *dev) -{ - struct pci_dev *pdev = container_of(dev, struct pci_dev, dev); - struct dw_i2c_dev *i2c = pci_get_drvdata(pdev); - int err; - u32 enabled; - - enabled = i2c_dw_is_enabled(i2c); - if (enabled) - return 0; - - err = pci_set_power_state(pdev, PCI_D0); - if (err) { - dev_err(&pdev->dev, "pci_set_power_state() failed\n"); - return err; - } - - pci_restore_state(pdev); - - i2c_dw_init(i2c); - return 0; -} - -static int i2c_dw_pci_runtime_idle(struct device *dev) -{ - int err = pm_schedule_suspend(dev, 500); - dev_dbg(dev, "runtime_idle called\n"); - - if (err != 0) - return 0; - return -EBUSY; -} - -static const struct dev_pm_ops i2c_dw_pm_ops = { - .resume = i2c_dw_pci_resume, - .suspend = i2c_dw_pci_suspend, - SET_RUNTIME_PM_OPS(i2c_dw_pci_suspend, i2c_dw_pci_resume, - i2c_dw_pci_runtime_idle) -}; - -static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) -{ - return dev->controller->clk_khz; -} - -static int __devinit i2c_dw_pci_probe(struct pci_dev *pdev, -const struct pci_device_id *id) -{ - struct dw_i2c_dev *dev; - struct i2c_adapter *adap; - unsigned long start, len; - void __iomem *base; - int r; - struct dw_pci_controller *controller; - - if (id->driver_data >= ARRAY_SIZE(dw_pci_controllers)) { - printk(KERN_ERR "dw_i2c_pci_probe: invalid driver data %ld\n", - id->driver_data); - return -EINVAL; - } - - controller = &dw_pci_controllers[id->driver_data]; - - r = pci_enable_device(pdev); - if (r) { - dev_err(&pdev->dev, "Failed to enable I2C PCI device (%d)\n", - r); - goto exit; - } - - /* Determine the address of the I2C area */ - start = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!start || len == 0) { - dev_err(&pdev->dev, "base address not set\n"); - r = -ENODEV; - goto exit; - } - - r = pci_request_region(pdev, 0, DRIVER_NAME); - if (r) { - dev_err(&pdev->dev, "failed to request I2C region " - "0x%lx-0x%lx\n", start, - (unsigned long)pci_resource_end(pdev, 0)); - goto exit; - } - - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&pdev->dev, "I/O memory remapping failed\n"); - r = -ENOMEM; - goto err_release_region; - } - - - dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); - if (!dev) { - r = -ENOMEM; - goto err_release_region; - } - - init_completion(&dev->cmd_complete); - mutex_init(&dev->lock); - dev->clk = NULL; - dev->controller = controller; - dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; - dev->base = base; - dev->dev = get_device(&pdev->dev); - dev->functionality = - I2C_FUNC_I2C | - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK; - dev->master_cfg = controller->bus_cfg; - - pci_set_drvdata(pdev, dev); - - dev->tx_fifo_depth = controller->tx_fifo_depth; - dev->rx_fifo_depth = controller->rx_fifo_depth; - r = i2c_dw_init(dev); - if (r) - goto err_iounmap; - - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = 0; - adap->algo = &i2c_dw_algo; - adap->dev.parent = &pdev->dev; - adap->nr = controller->bus_num; - snprintf(adap->name, sizeof(adap->name), "i2c-designware-pci-%d", - adap->nr); - - r = request_irq(pdev->irq, i2c_dw_isr, IRQF_SHARED, adap->name, dev); - if (r) { - dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); - goto err_iounmap; - } - - i2c_dw_disable_int(dev); - i2c_dw_clear_int(dev); - r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(&pdev->dev, "failure adding adapter\n"); - goto err_free_irq; - } - - pm_runtime_put_noidle(&pdev->dev); - pm_runtime_allow(&pdev->dev); - - return 0; - -err_free_irq: - free_irq(pdev->irq, dev); -err_iounmap: - iounmap(dev->base); - pci_set_drvdata(pdev, NULL); - put_device(&pdev->dev); - kfree(dev); -err_release_region: - pci_release_region(pdev, 0); -exit: - return r; -} - -static void __devexit i2c_dw_pci_remove(struct pci_dev *pdev) -{ - struct dw_i2c_dev *dev = pci_get_drvdata(pdev); - - i2c_dw_disable(dev); - pm_runtime_forbid(&pdev->dev); - pm_runtime_get_noresume(&pdev->dev); - - pci_set_drvdata(pdev, NULL); - i2c_del_adapter(&dev->adapter); - put_device(&pdev->dev); - - free_irq(dev->irq, dev); - kfree(dev); - pci_release_region(pdev, 0); -} - -/* work with hotplug and coldplug */ -MODULE_ALIAS("i2c_designware-pci"); - -static DEFINE_PCI_DEVICE_TABLE(i2_designware_pci_ids) = { - /* Moorestown */ - { PCI_VDEVICE(INTEL, 0x0802), moorestown_0 }, - { PCI_VDEVICE(INTEL, 0x0803), moorestown_1 }, - { PCI_VDEVICE(INTEL, 0x0804), moorestown_2 }, - /* Medfield */ - { PCI_VDEVICE(INTEL, 0x0817), medfield_3,}, - { PCI_VDEVICE(INTEL, 0x0818), medfield_4 }, - { PCI_VDEVICE(INTEL, 0x0819), medfield_5 }, - { PCI_VDEVICE(INTEL, 0x082C), medfield_0 }, - { PCI_VDEVICE(INTEL, 0x082D), medfield_1 }, - { PCI_VDEVICE(INTEL, 0x082E), medfield_2 }, - { 0,} -}; -MODULE_DEVICE_TABLE(pci, i2_designware_pci_ids); - -static struct pci_driver dw_i2c_driver = { - .name = DRIVER_NAME, - .id_table = i2_designware_pci_ids, - .probe = i2c_dw_pci_probe, - .remove = __devexit_p(i2c_dw_pci_remove), - .driver = { - .pm = &i2c_dw_pm_ops, - }, -}; - -static int __init dw_i2c_init_driver(void) -{ - return pci_register_driver(&dw_i2c_driver); -} -module_init(dw_i2c_init_driver); - -static void __exit dw_i2c_exit_driver(void) -{ - pci_unregister_driver(&dw_i2c_driver); -} -module_exit(dw_i2c_exit_driver); - -MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); -MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-platdrv.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-platdrv.c deleted file mode 100644 index 4ba589ab..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-designware-platdrv.c +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Synopsys DesignWare I2C adapter driver (master only). - * - * Based on the TI DAVINCI I2C adapter driver. - * - * Copyright (C) 2006 Texas Instruments. - * Copyright (C) 2007 MontaVista Software Inc. - * Copyright (C) 2009 Provigent Ltd. - * - * ---------------------------------------------------------------------------- - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ---------------------------------------------------------------------------- - * - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/clk.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/of_i2c.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <linux/slab.h> -#include "i2c-designware-core.h" - -static struct i2c_algorithm i2c_dw_algo = { - .master_xfer = i2c_dw_xfer, - .functionality = i2c_dw_func, -}; -static u32 i2c_dw_get_clk_rate_khz(struct dw_i2c_dev *dev) -{ - return clk_get_rate(dev->clk)/1000; -} - -static int __devinit dw_i2c_probe(struct platform_device *pdev) -{ - struct dw_i2c_dev *dev; - struct i2c_adapter *adap; - struct resource *mem, *ioarea; - int irq, r; - - /* NOTE: driver uses the static register mapping */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no irq resource?\n"); - return irq; /* -ENXIO */ - } - - ioarea = request_mem_region(mem->start, resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } - - dev = kzalloc(sizeof(struct dw_i2c_dev), GFP_KERNEL); - if (!dev) { - r = -ENOMEM; - goto err_release_region; - } - - init_completion(&dev->cmd_complete); - mutex_init(&dev->lock); - dev->dev = get_device(&pdev->dev); - dev->irq = irq; - platform_set_drvdata(pdev, dev); - - dev->clk = clk_get(&pdev->dev, NULL); - dev->get_clk_rate_khz = i2c_dw_get_clk_rate_khz; - - if (IS_ERR(dev->clk)) { - r = -ENODEV; - goto err_free_mem; - } - clk_enable(dev->clk); - - dev->functionality = - I2C_FUNC_I2C | - I2C_FUNC_10BIT_ADDR | - I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK; - dev->master_cfg = DW_IC_CON_MASTER | DW_IC_CON_SLAVE_DISABLE | - DW_IC_CON_RESTART_EN | DW_IC_CON_SPEED_FAST; - - dev->base = ioremap(mem->start, resource_size(mem)); - if (dev->base == NULL) { - dev_err(&pdev->dev, "failure mapping io resources\n"); - r = -EBUSY; - goto err_unuse_clocks; - } - { - u32 param1 = i2c_dw_read_comp_param(dev); - - dev->tx_fifo_depth = ((param1 >> 16) & 0xff) + 1; - dev->rx_fifo_depth = ((param1 >> 8) & 0xff) + 1; - } - r = i2c_dw_init(dev); - if (r) - goto err_iounmap; - - i2c_dw_disable_int(dev); - r = request_irq(dev->irq, i2c_dw_isr, IRQF_DISABLED, pdev->name, dev); - if (r) { - dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq); - goto err_iounmap; - } - - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; - strlcpy(adap->name, "Synopsys DesignWare I2C adapter", - sizeof(adap->name)); - adap->algo = &i2c_dw_algo; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; - - adap->nr = pdev->id; - r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(&pdev->dev, "failure adding adapter\n"); - goto err_free_irq; - } - of_i2c_register_devices(adap); - - return 0; - -err_free_irq: - free_irq(dev->irq, dev); -err_iounmap: - iounmap(dev->base); -err_unuse_clocks: - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; -err_free_mem: - platform_set_drvdata(pdev, NULL); - put_device(&pdev->dev); - kfree(dev); -err_release_region: - release_mem_region(mem->start, resource_size(mem)); - - return r; -} - -static int __devexit dw_i2c_remove(struct platform_device *pdev) -{ - struct dw_i2c_dev *dev = platform_get_drvdata(pdev); - struct resource *mem; - - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&dev->adapter); - put_device(&pdev->dev); - - clk_disable(dev->clk); - clk_put(dev->clk); - dev->clk = NULL; - - i2c_dw_disable(dev); - free_irq(dev->irq, dev); - kfree(dev); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - return 0; -} - -#ifdef CONFIG_OF -static const struct of_device_id dw_i2c_of_match[] = { - { .compatible = "snps,designware-i2c", }, - {}, -}; -MODULE_DEVICE_TABLE(of, dw_i2c_of_match); -#endif - -/* work with hotplug and coldplug */ -MODULE_ALIAS("platform:i2c_designware"); - -static struct platform_driver dw_i2c_driver = { - .remove = __devexit_p(dw_i2c_remove), - .driver = { - .name = "i2c_designware", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(dw_i2c_of_match), - }, -}; - -static int __init dw_i2c_init_driver(void) -{ - return platform_driver_probe(&dw_i2c_driver, dw_i2c_probe); -} -subsys_initcall(dw_i2c_init_driver); - -static void __exit dw_i2c_exit_driver(void) -{ - platform_driver_unregister(&dw_i2c_driver); -} -module_exit(dw_i2c_exit_driver); - -MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>"); -MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-diolan-u2c.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-diolan-u2c.c deleted file mode 100644 index 7eb19a52..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-diolan-u2c.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * Driver for the Diolan u2c-12 USB-I2C adapter - * - * Copyright (c) 2010-2011 Ericsson AB - * - * Derived from: - * i2c-tiny-usb.c - * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/usb.h> -#include <linux/i2c.h> - -#define DRIVER_NAME "i2c-diolan-u2c" - -#define USB_VENDOR_ID_DIOLAN 0x0abf -#define USB_DEVICE_ID_DIOLAN_U2C 0x3370 - -#define DIOLAN_OUT_EP 0x02 -#define DIOLAN_IN_EP 0x84 - -/* commands via USB, must match command ids in the firmware */ -#define CMD_I2C_READ 0x01 -#define CMD_I2C_WRITE 0x02 -#define CMD_I2C_SCAN 0x03 /* Returns list of detected devices */ -#define CMD_I2C_RELEASE_SDA 0x04 -#define CMD_I2C_RELEASE_SCL 0x05 -#define CMD_I2C_DROP_SDA 0x06 -#define CMD_I2C_DROP_SCL 0x07 -#define CMD_I2C_READ_SDA 0x08 -#define CMD_I2C_READ_SCL 0x09 -#define CMD_GET_FW_VERSION 0x0a -#define CMD_GET_SERIAL 0x0b -#define CMD_I2C_START 0x0c -#define CMD_I2C_STOP 0x0d -#define CMD_I2C_REPEATED_START 0x0e -#define CMD_I2C_PUT_BYTE 0x0f -#define CMD_I2C_GET_BYTE 0x10 -#define CMD_I2C_PUT_ACK 0x11 -#define CMD_I2C_GET_ACK 0x12 -#define CMD_I2C_PUT_BYTE_ACK 0x13 -#define CMD_I2C_GET_BYTE_ACK 0x14 -#define CMD_I2C_SET_SPEED 0x1b -#define CMD_I2C_GET_SPEED 0x1c -#define CMD_I2C_SET_CLK_SYNC 0x24 -#define CMD_I2C_GET_CLK_SYNC 0x25 -#define CMD_I2C_SET_CLK_SYNC_TO 0x26 -#define CMD_I2C_GET_CLK_SYNC_TO 0x27 - -#define RESP_OK 0x00 -#define RESP_FAILED 0x01 -#define RESP_BAD_MEMADDR 0x04 -#define RESP_DATA_ERR 0x05 -#define RESP_NOT_IMPLEMENTED 0x06 -#define RESP_NACK 0x07 -#define RESP_TIMEOUT 0x09 - -#define U2C_I2C_SPEED_FAST 0 /* 400 kHz */ -#define U2C_I2C_SPEED_STD 1 /* 100 kHz */ -#define U2C_I2C_SPEED_2KHZ 242 /* 2 kHz, minimum speed */ -#define U2C_I2C_SPEED(f) ((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1) - -#define U2C_I2C_FREQ_FAST 400000 -#define U2C_I2C_FREQ_STD 100000 -#define U2C_I2C_FREQ(s) (1000000 / (2 * (s - 1) + 10)) - -#define DIOLAN_USB_TIMEOUT 100 /* in ms */ -#define DIOLAN_SYNC_TIMEOUT 20 /* in ms */ - -#define DIOLAN_OUTBUF_LEN 128 -#define DIOLAN_FLUSH_LEN (DIOLAN_OUTBUF_LEN - 4) -#define DIOLAN_INBUF_LEN 256 /* Maximum supported receive length */ - -/* Structure to hold all of our device specific stuff */ -struct i2c_diolan_u2c { - u8 obuffer[DIOLAN_OUTBUF_LEN]; /* output buffer */ - u8 ibuffer[DIOLAN_INBUF_LEN]; /* input buffer */ - struct usb_device *usb_dev; /* the usb device for this device */ - struct usb_interface *interface;/* the interface for this device */ - struct i2c_adapter adapter; /* i2c related things */ - int olen; /* Output buffer length */ - int ocount; /* Number of enqueued messages */ -}; - -static uint frequency = U2C_I2C_FREQ_STD; /* I2C clock frequency in Hz */ - -module_param(frequency, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz"); - -/* usb layer */ - -/* Send command to device, and get response. */ -static int diolan_usb_transfer(struct i2c_diolan_u2c *dev) -{ - int ret = 0; - int actual; - int i; - - if (!dev->olen || !dev->ocount) - return -EINVAL; - - ret = usb_bulk_msg(dev->usb_dev, - usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP), - dev->obuffer, dev->olen, &actual, - DIOLAN_USB_TIMEOUT); - if (!ret) { - for (i = 0; i < dev->ocount; i++) { - int tmpret; - - tmpret = usb_bulk_msg(dev->usb_dev, - usb_rcvbulkpipe(dev->usb_dev, - DIOLAN_IN_EP), - dev->ibuffer, - sizeof(dev->ibuffer), &actual, - DIOLAN_USB_TIMEOUT); - /* - * Stop command processing if a previous command - * returned an error. - * Note that we still need to retrieve all messages. - */ - if (ret < 0) - continue; - ret = tmpret; - if (ret == 0 && actual > 0) { - switch (dev->ibuffer[actual - 1]) { - case RESP_NACK: - /* - * Return ENXIO if NACK was received as - * response to the address phase, - * EIO otherwise - */ - ret = i == 1 ? -ENXIO : -EIO; - break; - case RESP_TIMEOUT: - ret = -ETIMEDOUT; - break; - case RESP_OK: - /* strip off return code */ - ret = actual - 1; - break; - default: - ret = -EIO; - break; - } - } - } - } - dev->olen = 0; - dev->ocount = 0; - return ret; -} - -static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush) -{ - if (flush || dev->olen >= DIOLAN_FLUSH_LEN) - return diolan_usb_transfer(dev); - return 0; -} - -/* Send command (no data) */ -static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush) -{ - dev->obuffer[dev->olen++] = command; - dev->ocount++; - return diolan_write_cmd(dev, flush); -} - -/* Send command with one byte of data */ -static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data, - bool flush) -{ - dev->obuffer[dev->olen++] = command; - dev->obuffer[dev->olen++] = data; - dev->ocount++; - return diolan_write_cmd(dev, flush); -} - -/* Send command with two bytes of data */ -static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1, - u8 d2, bool flush) -{ - dev->obuffer[dev->olen++] = command; - dev->obuffer[dev->olen++] = d1; - dev->obuffer[dev->olen++] = d2; - dev->ocount++; - return diolan_write_cmd(dev, flush); -} - -/* - * Flush input queue. - * If we don't do this at startup and the controller has queued up - * messages which were not retrieved, it will stop responding - * at some point. - */ -static void diolan_flush_input(struct i2c_diolan_u2c *dev) -{ - int i; - - for (i = 0; i < 10; i++) { - int actual = 0; - int ret; - - ret = usb_bulk_msg(dev->usb_dev, - usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP), - dev->ibuffer, sizeof(dev->ibuffer), &actual, - DIOLAN_USB_TIMEOUT); - if (ret < 0 || actual == 0) - break; - } - if (i == 10) - dev_err(&dev->interface->dev, "Failed to flush input buffer\n"); -} - -static int diolan_i2c_start(struct i2c_diolan_u2c *dev) -{ - return diolan_usb_cmd(dev, CMD_I2C_START, false); -} - -static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev) -{ - return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false); -} - -static int diolan_i2c_stop(struct i2c_diolan_u2c *dev) -{ - return diolan_usb_cmd(dev, CMD_I2C_STOP, true); -} - -static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack, - u8 *byte) -{ - int ret; - - ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true); - if (ret > 0) - *byte = dev->ibuffer[0]; - else if (ret == 0) - ret = -EIO; - - return ret; -} - -static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte) -{ - return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false); -} - -static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed) -{ - return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true); -} - -/* Enable or disable clock synchronization (stretching) */ -static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable) -{ - return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true); -} - -/* Set clock synchronization timeout in ms */ -static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms) -{ - int to_val = ms * 10; - - return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO, - to_val & 0xff, (to_val >> 8) & 0xff, true); -} - -static void diolan_fw_version(struct i2c_diolan_u2c *dev) -{ - int ret; - - ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true); - if (ret >= 2) - dev_info(&dev->interface->dev, - "Diolan U2C firmware version %u.%u\n", - (unsigned int)dev->ibuffer[0], - (unsigned int)dev->ibuffer[1]); -} - -static void diolan_get_serial(struct i2c_diolan_u2c *dev) -{ - int ret; - u32 serial; - - ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true); - if (ret >= 4) { - serial = le32_to_cpu(*(u32 *)dev->ibuffer); - dev_info(&dev->interface->dev, - "Diolan U2C serial number %u\n", serial); - } -} - -static int diolan_init(struct i2c_diolan_u2c *dev) -{ - int speed, ret; - - if (frequency >= 200000) { - speed = U2C_I2C_SPEED_FAST; - frequency = U2C_I2C_FREQ_FAST; - } else if (frequency >= 100000 || frequency == 0) { - speed = U2C_I2C_SPEED_STD; - frequency = U2C_I2C_FREQ_STD; - } else { - speed = U2C_I2C_SPEED(frequency); - if (speed > U2C_I2C_SPEED_2KHZ) - speed = U2C_I2C_SPEED_2KHZ; - frequency = U2C_I2C_FREQ(speed); - } - - dev_info(&dev->interface->dev, - "Diolan U2C at USB bus %03d address %03d speed %d Hz\n", - dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency); - - diolan_flush_input(dev); - diolan_fw_version(dev); - diolan_get_serial(dev); - - /* Set I2C speed */ - ret = diolan_set_speed(dev, speed); - if (ret < 0) - return ret; - - /* Configure I2C clock synchronization */ - ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST); - if (ret < 0) - return ret; - - if (speed != U2C_I2C_SPEED_FAST) - ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT); - - return ret; -} - -/* i2c layer */ - -static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, - int num) -{ - struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter); - struct i2c_msg *pmsg; - int i, j; - int ret, sret; - - ret = diolan_i2c_start(dev); - if (ret < 0) - return ret; - - for (i = 0; i < num; i++) { - pmsg = &msgs[i]; - if (i) { - ret = diolan_i2c_repeated_start(dev); - if (ret < 0) - goto abort; - } - if (pmsg->flags & I2C_M_RD) { - ret = - diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1); - if (ret < 0) - goto abort; - for (j = 0; j < pmsg->len; j++) { - u8 byte; - bool ack = j < pmsg->len - 1; - - /* - * Don't send NACK if this is the first byte - * of a SMBUS_BLOCK message. - */ - if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) - ack = true; - - ret = diolan_i2c_get_byte_ack(dev, ack, &byte); - if (ret < 0) - goto abort; - /* - * Adjust count if first received byte is length - */ - if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) { - if (byte == 0 - || byte > I2C_SMBUS_BLOCK_MAX) { - ret = -EPROTO; - goto abort; - } - pmsg->len += byte; - } - pmsg->buf[j] = byte; - } - } else { - ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1); - if (ret < 0) - goto abort; - for (j = 0; j < pmsg->len; j++) { - ret = diolan_i2c_put_byte_ack(dev, - pmsg->buf[j]); - if (ret < 0) - goto abort; - } - } - } -abort: - sret = diolan_i2c_stop(dev); - if (sret < 0 && ret >= 0) - ret = sret; - return ret; -} - -/* - * Return list of supported functionality. - */ -static u32 diolan_usb_func(struct i2c_adapter *a) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | - I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; -} - -static const struct i2c_algorithm diolan_usb_algorithm = { - .master_xfer = diolan_usb_xfer, - .functionality = diolan_usb_func, -}; - -/* device layer */ - -static const struct usb_device_id diolan_u2c_table[] = { - { USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, diolan_u2c_table); - -static void diolan_u2c_free(struct i2c_diolan_u2c *dev) -{ - usb_put_dev(dev->usb_dev); - kfree(dev); -} - -static int diolan_u2c_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct i2c_diolan_u2c *dev; - int ret; - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "no memory for device state\n"); - ret = -ENOMEM; - goto error; - } - - dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - /* setup i2c adapter description */ - dev->adapter.owner = THIS_MODULE; - dev->adapter.class = I2C_CLASS_HWMON; - dev->adapter.algo = &diolan_usb_algorithm; - i2c_set_adapdata(&dev->adapter, dev); - snprintf(dev->adapter.name, sizeof(dev->adapter.name), - DRIVER_NAME " at bus %03d device %03d", - dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - - dev->adapter.dev.parent = &dev->interface->dev; - - /* initialize diolan i2c interface */ - ret = diolan_init(dev); - if (ret < 0) { - dev_err(&interface->dev, "failed to initialize adapter\n"); - goto error_free; - } - - /* and finally attach to i2c layer */ - ret = i2c_add_adapter(&dev->adapter); - if (ret < 0) { - dev_err(&interface->dev, "failed to add I2C adapter\n"); - goto error_free; - } - - dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n"); - - return 0; - -error_free: - usb_set_intfdata(interface, NULL); - diolan_u2c_free(dev); -error: - return ret; -} - -static void diolan_u2c_disconnect(struct usb_interface *interface) -{ - struct i2c_diolan_u2c *dev = usb_get_intfdata(interface); - - i2c_del_adapter(&dev->adapter); - usb_set_intfdata(interface, NULL); - diolan_u2c_free(dev); - - dev_dbg(&interface->dev, "disconnected\n"); -} - -static struct usb_driver diolan_u2c_driver = { - .name = DRIVER_NAME, - .probe = diolan_u2c_probe, - .disconnect = diolan_u2c_disconnect, - .id_table = diolan_u2c_table, -}; - -module_usb_driver(diolan_u2c_driver); - -MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); -MODULE_DESCRIPTION(DRIVER_NAME " driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-eg20t.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-eg20t.c deleted file mode 100644 index c811289b..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-eg20t.c +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/fs.h> -#include <linux/io.h> -#include <linux/types.h> -#include <linux/interrupt.h> -#include <linux/jiffies.h> -#include <linux/pci.h> -#include <linux/mutex.h> -#include <linux/ktime.h> -#include <linux/slab.h> - -#define PCH_EVENT_SET 0 /* I2C Interrupt Event Set Status */ -#define PCH_EVENT_NONE 1 /* I2C Interrupt Event Clear Status */ -#define PCH_MAX_CLK 100000 /* Maximum Clock speed in MHz */ -#define PCH_BUFFER_MODE_ENABLE 0x0002 /* flag for Buffer mode enable */ -#define PCH_EEPROM_SW_RST_MODE_ENABLE 0x0008 /* EEPROM SW RST enable flag */ - -#define PCH_I2CSADR 0x00 /* I2C slave address register */ -#define PCH_I2CCTL 0x04 /* I2C control register */ -#define PCH_I2CSR 0x08 /* I2C status register */ -#define PCH_I2CDR 0x0C /* I2C data register */ -#define PCH_I2CMON 0x10 /* I2C bus monitor register */ -#define PCH_I2CBC 0x14 /* I2C bus transfer rate setup counter */ -#define PCH_I2CMOD 0x18 /* I2C mode register */ -#define PCH_I2CBUFSLV 0x1C /* I2C buffer mode slave address register */ -#define PCH_I2CBUFSUB 0x20 /* I2C buffer mode subaddress register */ -#define PCH_I2CBUFFOR 0x24 /* I2C buffer mode format register */ -#define PCH_I2CBUFCTL 0x28 /* I2C buffer mode control register */ -#define PCH_I2CBUFMSK 0x2C /* I2C buffer mode interrupt mask register */ -#define PCH_I2CBUFSTA 0x30 /* I2C buffer mode status register */ -#define PCH_I2CBUFLEV 0x34 /* I2C buffer mode level register */ -#define PCH_I2CESRFOR 0x38 /* EEPROM software reset mode format register */ -#define PCH_I2CESRCTL 0x3C /* EEPROM software reset mode ctrl register */ -#define PCH_I2CESRMSK 0x40 /* EEPROM software reset mode */ -#define PCH_I2CESRSTA 0x44 /* EEPROM software reset mode status register */ -#define PCH_I2CTMR 0x48 /* I2C timer register */ -#define PCH_I2CSRST 0xFC /* I2C reset register */ -#define PCH_I2CNF 0xF8 /* I2C noise filter register */ - -#define BUS_IDLE_TIMEOUT 20 -#define PCH_I2CCTL_I2CMEN 0x0080 -#define TEN_BIT_ADDR_DEFAULT 0xF000 -#define TEN_BIT_ADDR_MASK 0xF0 -#define PCH_START 0x0020 -#define PCH_RESTART 0x0004 -#define PCH_ESR_START 0x0001 -#define PCH_BUFF_START 0x1 -#define PCH_REPSTART 0x0004 -#define PCH_ACK 0x0008 -#define PCH_GETACK 0x0001 -#define CLR_REG 0x0 -#define I2C_RD 0x1 -#define I2CMCF_BIT 0x0080 -#define I2CMIF_BIT 0x0002 -#define I2CMAL_BIT 0x0010 -#define I2CBMFI_BIT 0x0001 -#define I2CBMAL_BIT 0x0002 -#define I2CBMNA_BIT 0x0004 -#define I2CBMTO_BIT 0x0008 -#define I2CBMIS_BIT 0x0010 -#define I2CESRFI_BIT 0X0001 -#define I2CESRTO_BIT 0x0002 -#define I2CESRFIIE_BIT 0x1 -#define I2CESRTOIE_BIT 0x2 -#define I2CBMDZ_BIT 0x0040 -#define I2CBMAG_BIT 0x0020 -#define I2CMBB_BIT 0x0020 -#define BUFFER_MODE_MASK (I2CBMFI_BIT | I2CBMAL_BIT | I2CBMNA_BIT | \ - I2CBMTO_BIT | I2CBMIS_BIT) -#define I2C_ADDR_MSK 0xFF -#define I2C_MSB_2B_MSK 0x300 -#define FAST_MODE_CLK 400 -#define FAST_MODE_EN 0x0001 -#define SUB_ADDR_LEN_MAX 4 -#define BUF_LEN_MAX 32 -#define PCH_BUFFER_MODE 0x1 -#define EEPROM_SW_RST_MODE 0x0002 -#define NORMAL_INTR_ENBL 0x0300 -#define EEPROM_RST_INTR_ENBL (I2CESRFIIE_BIT | I2CESRTOIE_BIT) -#define EEPROM_RST_INTR_DISBL 0x0 -#define BUFFER_MODE_INTR_ENBL 0x001F -#define BUFFER_MODE_INTR_DISBL 0x0 -#define NORMAL_MODE 0x0 -#define BUFFER_MODE 0x1 -#define EEPROM_SR_MODE 0x2 -#define I2C_TX_MODE 0x0010 -#define PCH_BUF_TX 0xFFF7 -#define PCH_BUF_RD 0x0008 -#define I2C_ERROR_MASK (I2CESRTO_EVENT | I2CBMIS_EVENT | I2CBMTO_EVENT | \ - I2CBMNA_EVENT | I2CBMAL_EVENT | I2CMAL_EVENT) -#define I2CMAL_EVENT 0x0001 -#define I2CMCF_EVENT 0x0002 -#define I2CBMFI_EVENT 0x0004 -#define I2CBMAL_EVENT 0x0008 -#define I2CBMNA_EVENT 0x0010 -#define I2CBMTO_EVENT 0x0020 -#define I2CBMIS_EVENT 0x0040 -#define I2CESRFI_EVENT 0x0080 -#define I2CESRTO_EVENT 0x0100 -#define PCI_DEVICE_ID_PCH_I2C 0x8817 - -#define pch_dbg(adap, fmt, arg...) \ - dev_dbg(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg) - -#define pch_err(adap, fmt, arg...) \ - dev_err(adap->pch_adapter.dev.parent, "%s :" fmt, __func__, ##arg) - -#define pch_pci_err(pdev, fmt, arg...) \ - dev_err(&pdev->dev, "%s :" fmt, __func__, ##arg) - -#define pch_pci_dbg(pdev, fmt, arg...) \ - dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg) - -/* -Set the number of I2C instance max -Intel EG20T PCH : 1ch -LAPIS Semiconductor ML7213 IOH : 2ch -LAPIS Semiconductor ML7831 IOH : 1ch -*/ -#define PCH_I2C_MAX_DEV 2 - -/** - * struct i2c_algo_pch_data - for I2C driver functionalities - * @pch_adapter: stores the reference to i2c_adapter structure - * @p_adapter_info: stores the reference to adapter_info structure - * @pch_base_address: specifies the remapped base address - * @pch_buff_mode_en: specifies if buffer mode is enabled - * @pch_event_flag: specifies occurrence of interrupt events - * @pch_i2c_xfer_in_progress: specifies whether the transfer is completed - */ -struct i2c_algo_pch_data { - struct i2c_adapter pch_adapter; - struct adapter_info *p_adapter_info; - void __iomem *pch_base_address; - int pch_buff_mode_en; - u32 pch_event_flag; - bool pch_i2c_xfer_in_progress; -}; - -/** - * struct adapter_info - This structure holds the adapter information for the - PCH i2c controller - * @pch_data: stores a list of i2c_algo_pch_data - * @pch_i2c_suspended: specifies whether the system is suspended or not - * perhaps with more lines and words. - * @ch_num: specifies the number of i2c instance - * - * pch_data has as many elements as maximum I2C channels - */ -struct adapter_info { - struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV]; - bool pch_i2c_suspended; - int ch_num; -}; - - -static int pch_i2c_speed = 100; /* I2C bus speed in Kbps */ -static int pch_clk = 50000; /* specifies I2C clock speed in KHz */ -static wait_queue_head_t pch_event; -static DEFINE_MUTEX(pch_mutex); - -/* Definition for ML7213 by LAPIS Semiconductor */ -#define PCI_VENDOR_ID_ROHM 0x10DB -#define PCI_DEVICE_ID_ML7213_I2C 0x802D -#define PCI_DEVICE_ID_ML7223_I2C 0x8010 -#define PCI_DEVICE_ID_ML7831_I2C 0x8817 - -static DEFINE_PCI_DEVICE_TABLE(pch_pcidev_id) = { - { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C), 1, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7223_I2C), 1, }, - { PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7831_I2C), 1, }, - {0,} -}; - -static irqreturn_t pch_i2c_handler(int irq, void *pData); - -static inline void pch_setbit(void __iomem *addr, u32 offset, u32 bitmask) -{ - u32 val; - val = ioread32(addr + offset); - val |= bitmask; - iowrite32(val, addr + offset); -} - -static inline void pch_clrbit(void __iomem *addr, u32 offset, u32 bitmask) -{ - u32 val; - val = ioread32(addr + offset); - val &= (~bitmask); - iowrite32(val, addr + offset); -} - -/** - * pch_i2c_init() - hardware initialization of I2C module - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_init(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - u32 pch_i2cbc; - u32 pch_i2ctmr; - u32 reg_value; - - /* reset I2C controller */ - iowrite32(0x01, p + PCH_I2CSRST); - msleep(20); - iowrite32(0x0, p + PCH_I2CSRST); - - /* Initialize I2C registers */ - iowrite32(0x21, p + PCH_I2CNF); - - pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN); - - if (pch_i2c_speed != 400) - pch_i2c_speed = 100; - - reg_value = PCH_I2CCTL_I2CMEN; - if (pch_i2c_speed == FAST_MODE_CLK) { - reg_value |= FAST_MODE_EN; - pch_dbg(adap, "Fast mode enabled\n"); - } - - if (pch_clk > PCH_MAX_CLK) - pch_clk = 62500; - - pch_i2cbc = (pch_clk + (pch_i2c_speed * 4)) / (pch_i2c_speed * 8); - /* Set transfer speed in I2CBC */ - iowrite32(pch_i2cbc, p + PCH_I2CBC); - - pch_i2ctmr = (pch_clk) / 8; - iowrite32(pch_i2ctmr, p + PCH_I2CTMR); - - reg_value |= NORMAL_INTR_ENBL; /* Enable interrupts in normal mode */ - iowrite32(reg_value, p + PCH_I2CCTL); - - pch_dbg(adap, - "I2CCTL=%x pch_i2cbc=%x pch_i2ctmr=%x Enable interrupts\n", - ioread32(p + PCH_I2CCTL), pch_i2cbc, pch_i2ctmr); - - init_waitqueue_head(&pch_event); -} - -static inline bool ktime_lt(const ktime_t cmp1, const ktime_t cmp2) -{ - return cmp1.tv64 < cmp2.tv64; -} - -/** - * pch_i2c_wait_for_bus_idle() - check the status of bus. - * @adap: Pointer to struct i2c_algo_pch_data. - * @timeout: waiting time counter (ms). - */ -static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap, - s32 timeout) -{ - void __iomem *p = adap->pch_base_address; - int schedule = 0; - unsigned long end = jiffies + msecs_to_jiffies(timeout); - - while (ioread32(p + PCH_I2CSR) & I2CMBB_BIT) { - if (time_after(jiffies, end)) { - pch_dbg(adap, "I2CSR = %x\n", ioread32(p + PCH_I2CSR)); - pch_err(adap, "%s: Timeout Error.return%d\n", - __func__, -ETIME); - pch_i2c_init(adap); - - return -ETIME; - } - - if (!schedule) - /* Retry after some usecs */ - udelay(5); - else - /* Wait a bit more without consuming CPU */ - usleep_range(20, 1000); - - schedule = 1; - } - - return 0; -} - -/** - * pch_i2c_start() - Generate I2C start condition in normal mode. - * @adap: Pointer to struct i2c_algo_pch_data. - * - * Generate I2C start condition in normal mode by setting I2CCTL.I2CMSTA to 1. - */ -static void pch_i2c_start(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_START); -} - -/** - * pch_i2c_wait_for_xfer_complete() - initiates a wait for the tx complete event - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static s32 pch_i2c_wait_for_xfer_complete(struct i2c_algo_pch_data *adap) -{ - long ret; - ret = wait_event_timeout(pch_event, - (adap->pch_event_flag != 0), msecs_to_jiffies(1000)); - - if (ret == 0) { - pch_err(adap, "timeout: %x\n", adap->pch_event_flag); - adap->pch_event_flag = 0; - return -ETIMEDOUT; - } - - if (adap->pch_event_flag & I2C_ERROR_MASK) { - pch_err(adap, "error bits set: %x\n", adap->pch_event_flag); - adap->pch_event_flag = 0; - return -EIO; - } - - adap->pch_event_flag = 0; - - return 0; -} - -/** - * pch_i2c_getack() - to confirm ACK/NACK - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static s32 pch_i2c_getack(struct i2c_algo_pch_data *adap) -{ - u32 reg_val; - void __iomem *p = adap->pch_base_address; - reg_val = ioread32(p + PCH_I2CSR) & PCH_GETACK; - - if (reg_val != 0) { - pch_err(adap, "return%d\n", -EPROTO); - return -EPROTO; - } - - return 0; -} - -/** - * pch_i2c_stop() - generate stop condition in normal mode. - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_stop(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - /* clear the start bit */ - pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_START); -} - -/** - * pch_i2c_repstart() - generate repeated start condition in normal mode - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_repstart(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_REPSTART); -} - -/** - * pch_i2c_writebytes() - write data to I2C bus in normal mode - * @i2c_adap: Pointer to the struct i2c_adapter. - * @last: specifies whether last message or not. - * In the case of compound mode it will be 1 for last message, - * otherwise 0. - * @first: specifies whether first message or not. - * 1 for first message otherwise 0. - */ -static s32 pch_i2c_writebytes(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, u32 last, u32 first) -{ - struct i2c_algo_pch_data *adap = i2c_adap->algo_data; - u8 *buf; - u32 length; - u32 addr; - u32 addr_2_msb; - u32 addr_8_lsb; - s32 wrcount; - s32 rtn; - void __iomem *p = adap->pch_base_address; - - length = msgs->len; - buf = msgs->buf; - addr = msgs->addr; - - /* enable master tx */ - pch_setbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); - - pch_dbg(adap, "I2CCTL = %x msgs->len = %d\n", ioread32(p + PCH_I2CCTL), - length); - - if (first) { - if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME) - return -ETIME; - } - - if (msgs->flags & I2C_M_TEN) { - addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7) & 0x06; - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); - if (first) - pch_i2c_start(adap); - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - addr_8_lsb = (addr & I2C_ADDR_MSK); - iowrite32(addr_8_lsb, p + PCH_I2CDR); - } else if (rtn == -EIO) { /* Arbitration Lost */ - pch_err(adap, "Lost Arbitration\n"); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMAL_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMIF_BIT); - pch_i2c_init(adap); - return -EAGAIN; - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - } else { - /* set 7 bit slave address and R/W bit as 0 */ - iowrite32(addr << 1, p + PCH_I2CDR); - if (first) - pch_i2c_start(adap); - } - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - } else if (rtn == -EIO) { /* Arbitration Lost */ - pch_err(adap, "Lost Arbitration\n"); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT); - pch_i2c_init(adap); - return -EAGAIN; - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - - for (wrcount = 0; wrcount < length; ++wrcount) { - /* write buffer value to I2C data register */ - iowrite32(buf[wrcount], p + PCH_I2CDR); - pch_dbg(adap, "writing %x to Data register\n", buf[wrcount]); - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMCF_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMIF_BIT); - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - } - - /* check if this is the last message */ - if (last) - pch_i2c_stop(adap); - else - pch_i2c_repstart(adap); - - pch_dbg(adap, "return=%d\n", wrcount); - - return wrcount; -} - -/** - * pch_i2c_sendack() - send ACK - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_sendack(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - pch_clrbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK); -} - -/** - * pch_i2c_sendnack() - send NACK - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_sendnack(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_ACK); -} - -/** - * pch_i2c_restart() - Generate I2C restart condition in normal mode. - * @adap: Pointer to struct i2c_algo_pch_data. - * - * Generate I2C restart condition in normal mode by setting I2CCTL.I2CRSTA. - */ -static void pch_i2c_restart(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - pch_dbg(adap, "I2CCTL = %x\n", ioread32(p + PCH_I2CCTL)); - pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_RESTART); -} - -/** - * pch_i2c_readbytes() - read data from I2C bus in normal mode. - * @i2c_adap: Pointer to the struct i2c_adapter. - * @msgs: Pointer to i2c_msg structure. - * @last: specifies whether last message or not. - * @first: specifies whether first message or not. - */ -static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, - u32 last, u32 first) -{ - struct i2c_algo_pch_data *adap = i2c_adap->algo_data; - - u8 *buf; - u32 count; - u32 length; - u32 addr; - u32 addr_2_msb; - u32 addr_8_lsb; - void __iomem *p = adap->pch_base_address; - s32 rtn; - - length = msgs->len; - buf = msgs->buf; - addr = msgs->addr; - - /* enable master reception */ - pch_clrbit(adap->pch_base_address, PCH_I2CCTL, I2C_TX_MODE); - - if (first) { - if (pch_i2c_wait_for_bus_idle(adap, BUS_IDLE_TIMEOUT) == -ETIME) - return -ETIME; - } - - if (msgs->flags & I2C_M_TEN) { - addr_2_msb = ((addr & I2C_MSB_2B_MSK) >> 7); - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, p + PCH_I2CDR); - if (first) - pch_i2c_start(adap); - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - addr_8_lsb = (addr & I2C_ADDR_MSK); - iowrite32(addr_8_lsb, p + PCH_I2CDR); - } else if (rtn == -EIO) { /* Arbitration Lost */ - pch_err(adap, "Lost Arbitration\n"); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMAL_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMIF_BIT); - pch_i2c_init(adap); - return -EAGAIN; - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - pch_i2c_restart(adap); - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - addr_2_msb |= I2C_RD; - iowrite32(addr_2_msb | TEN_BIT_ADDR_MASK, - p + PCH_I2CDR); - } else if (rtn == -EIO) { /* Arbitration Lost */ - pch_err(adap, "Lost Arbitration\n"); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMAL_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, - I2CMIF_BIT); - pch_i2c_init(adap); - return -EAGAIN; - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - } else { - /* 7 address bits + R/W bit */ - addr = (((addr) << 1) | (I2C_RD)); - iowrite32(addr, p + PCH_I2CDR); - } - - /* check if it is the first message */ - if (first) - pch_i2c_start(adap); - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave address" - "setting\n"); - return -EIO; - } - } else if (rtn == -EIO) { /* Arbitration Lost */ - pch_err(adap, "Lost Arbitration\n"); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMAL_BIT); - pch_clrbit(adap->pch_base_address, PCH_I2CSR, I2CMIF_BIT); - pch_i2c_init(adap); - return -EAGAIN; - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - - if (length == 0) { - pch_i2c_stop(adap); - ioread32(p + PCH_I2CDR); /* Dummy read needs */ - - count = length; - } else { - int read_index; - int loop; - pch_i2c_sendack(adap); - - /* Dummy read */ - for (loop = 1, read_index = 0; loop < length; loop++) { - buf[read_index] = ioread32(p + PCH_I2CDR); - - if (loop != 1) - read_index++; - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave" - "address setting\n"); - return -EIO; - } - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - - } /* end for */ - - pch_i2c_sendnack(adap); - - buf[read_index] = ioread32(p + PCH_I2CDR); /* Read final - 1 */ - - if (length != 1) - read_index++; - - rtn = pch_i2c_wait_for_xfer_complete(adap); - if (rtn == 0) { - if (pch_i2c_getack(adap)) { - pch_dbg(adap, "Receive NACK for slave" - "address setting\n"); - return -EIO; - } - } else { /* wait-event timeout */ - pch_i2c_stop(adap); - return -ETIME; - } - - if (last) - pch_i2c_stop(adap); - else - pch_i2c_repstart(adap); - - buf[read_index++] = ioread32(p + PCH_I2CDR); /* Read Final */ - count = read_index; - } - - return count; -} - -/** - * pch_i2c_cb() - Interrupt handler Call back function - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_cb(struct i2c_algo_pch_data *adap) -{ - u32 sts; - void __iomem *p = adap->pch_base_address; - - sts = ioread32(p + PCH_I2CSR); - sts &= (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT); - if (sts & I2CMAL_BIT) - adap->pch_event_flag |= I2CMAL_EVENT; - - if (sts & I2CMCF_BIT) - adap->pch_event_flag |= I2CMCF_EVENT; - - /* clear the applicable bits */ - pch_clrbit(adap->pch_base_address, PCH_I2CSR, sts); - - pch_dbg(adap, "PCH_I2CSR = %x\n", ioread32(p + PCH_I2CSR)); - - wake_up(&pch_event); -} - -/** - * pch_i2c_handler() - interrupt handler for the PCH I2C controller - * @irq: irq number. - * @pData: cookie passed back to the handler function. - */ -static irqreturn_t pch_i2c_handler(int irq, void *pData) -{ - u32 reg_val; - int flag; - int i; - struct adapter_info *adap_info = pData; - void __iomem *p; - u32 mode; - - for (i = 0, flag = 0; i < adap_info->ch_num; i++) { - p = adap_info->pch_data[i].pch_base_address; - mode = ioread32(p + PCH_I2CMOD); - mode &= BUFFER_MODE | EEPROM_SR_MODE; - if (mode != NORMAL_MODE) { - pch_err(adap_info->pch_data, - "I2C-%d mode(%d) is not supported\n", mode, i); - continue; - } - reg_val = ioread32(p + PCH_I2CSR); - if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) { - pch_i2c_cb(&adap_info->pch_data[i]); - flag = 1; - } - } - - return flag ? IRQ_HANDLED : IRQ_NONE; -} - -/** - * pch_i2c_xfer() - Reading adnd writing data through I2C bus - * @i2c_adap: Pointer to the struct i2c_adapter. - * @msgs: Pointer to i2c_msg structure. - * @num: number of messages. - */ -static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg *msgs, s32 num) -{ - struct i2c_msg *pmsg; - u32 i = 0; - u32 status; - s32 ret; - - struct i2c_algo_pch_data *adap = i2c_adap->algo_data; - - ret = mutex_lock_interruptible(&pch_mutex); - if (ret) - return -ERESTARTSYS; - - if (adap->p_adapter_info->pch_i2c_suspended) { - mutex_unlock(&pch_mutex); - return -EBUSY; - } - - pch_dbg(adap, "adap->p_adapter_info->pch_i2c_suspended is %d\n", - adap->p_adapter_info->pch_i2c_suspended); - /* transfer not completed */ - adap->pch_i2c_xfer_in_progress = true; - - for (i = 0; i < num && ret >= 0; i++) { - pmsg = &msgs[i]; - pmsg->flags |= adap->pch_buff_mode_en; - status = pmsg->flags; - pch_dbg(adap, - "After invoking I2C_MODE_SEL :flag= 0x%x\n", status); - - if ((status & (I2C_M_RD)) != false) { - ret = pch_i2c_readbytes(i2c_adap, pmsg, (i + 1 == num), - (i == 0)); - } else { - ret = pch_i2c_writebytes(i2c_adap, pmsg, (i + 1 == num), - (i == 0)); - } - } - - adap->pch_i2c_xfer_in_progress = false; /* transfer completed */ - - mutex_unlock(&pch_mutex); - - return (ret < 0) ? ret : num; -} - -/** - * pch_i2c_func() - return the functionality of the I2C driver - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static u32 pch_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; -} - -static struct i2c_algorithm pch_algorithm = { - .master_xfer = pch_i2c_xfer, - .functionality = pch_i2c_func -}; - -/** - * pch_i2c_disbl_int() - Disable PCH I2C interrupts - * @adap: Pointer to struct i2c_algo_pch_data. - */ -static void pch_i2c_disbl_int(struct i2c_algo_pch_data *adap) -{ - void __iomem *p = adap->pch_base_address; - - pch_clrbit(adap->pch_base_address, PCH_I2CCTL, NORMAL_INTR_ENBL); - - iowrite32(EEPROM_RST_INTR_DISBL, p + PCH_I2CESRMSK); - - iowrite32(BUFFER_MODE_INTR_DISBL, p + PCH_I2CBUFMSK); -} - -static int __devinit pch_i2c_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *base_addr; - int ret; - int i, j; - struct adapter_info *adap_info; - struct i2c_adapter *pch_adap; - - pch_pci_dbg(pdev, "Entered.\n"); - - adap_info = kzalloc((sizeof(struct adapter_info)), GFP_KERNEL); - if (adap_info == NULL) { - pch_pci_err(pdev, "Memory allocation FAILED\n"); - return -ENOMEM; - } - - ret = pci_enable_device(pdev); - if (ret) { - pch_pci_err(pdev, "pci_enable_device FAILED\n"); - goto err_pci_enable; - } - - ret = pci_request_regions(pdev, KBUILD_MODNAME); - if (ret) { - pch_pci_err(pdev, "pci_request_regions FAILED\n"); - goto err_pci_req; - } - - base_addr = pci_iomap(pdev, 1, 0); - - if (base_addr == NULL) { - pch_pci_err(pdev, "pci_iomap FAILED\n"); - ret = -ENOMEM; - goto err_pci_iomap; - } - - /* Set the number of I2C channel instance */ - adap_info->ch_num = id->driver_data; - - ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED, - KBUILD_MODNAME, adap_info); - if (ret) { - pch_pci_err(pdev, "request_irq FAILED\n"); - goto err_request_irq; - } - - for (i = 0; i < adap_info->ch_num; i++) { - pch_adap = &adap_info->pch_data[i].pch_adapter; - adap_info->pch_i2c_suspended = false; - - adap_info->pch_data[i].p_adapter_info = adap_info; - - pch_adap->owner = THIS_MODULE; - pch_adap->class = I2C_CLASS_HWMON; - strcpy(pch_adap->name, KBUILD_MODNAME); - pch_adap->algo = &pch_algorithm; - pch_adap->algo_data = &adap_info->pch_data[i]; - - /* base_addr + offset; */ - adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i; - - pch_adap->dev.parent = &pdev->dev; - - pch_i2c_init(&adap_info->pch_data[i]); - - pch_adap->nr = i; - ret = i2c_add_numbered_adapter(pch_adap); - if (ret) { - pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i); - goto err_add_adapter; - } - } - - pci_set_drvdata(pdev, adap_info); - pch_pci_dbg(pdev, "returns %d.\n", ret); - return 0; - -err_add_adapter: - for (j = 0; j < i; j++) - i2c_del_adapter(&adap_info->pch_data[j].pch_adapter); - free_irq(pdev->irq, adap_info); -err_request_irq: - pci_iounmap(pdev, base_addr); -err_pci_iomap: - pci_release_regions(pdev); -err_pci_req: - pci_disable_device(pdev); -err_pci_enable: - kfree(adap_info); - return ret; -} - -static void __devexit pch_i2c_remove(struct pci_dev *pdev) -{ - int i; - struct adapter_info *adap_info = pci_get_drvdata(pdev); - - free_irq(pdev->irq, adap_info); - - for (i = 0; i < adap_info->ch_num; i++) { - pch_i2c_disbl_int(&adap_info->pch_data[i]); - i2c_del_adapter(&adap_info->pch_data[i].pch_adapter); - } - - if (adap_info->pch_data[0].pch_base_address) - pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address); - - for (i = 0; i < adap_info->ch_num; i++) - adap_info->pch_data[i].pch_base_address = 0; - - pci_set_drvdata(pdev, NULL); - - pci_release_regions(pdev); - - pci_disable_device(pdev); - kfree(adap_info); -} - -#ifdef CONFIG_PM -static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state) -{ - int ret; - int i; - struct adapter_info *adap_info = pci_get_drvdata(pdev); - void __iomem *p = adap_info->pch_data[0].pch_base_address; - - adap_info->pch_i2c_suspended = true; - - for (i = 0; i < adap_info->ch_num; i++) { - while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) { - /* Wait until all channel transfers are completed */ - msleep(20); - } - } - - /* Disable the i2c interrupts */ - for (i = 0; i < adap_info->ch_num; i++) - pch_i2c_disbl_int(&adap_info->pch_data[i]); - - pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x " - "invoked function pch_i2c_disbl_int successfully\n", - ioread32(p + PCH_I2CSR), ioread32(p + PCH_I2CBUFSTA), - ioread32(p + PCH_I2CESRSTA)); - - ret = pci_save_state(pdev); - - if (ret) { - pch_pci_err(pdev, "pci_save_state\n"); - return ret; - } - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int pch_i2c_resume(struct pci_dev *pdev) -{ - int i; - struct adapter_info *adap_info = pci_get_drvdata(pdev); - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - if (pci_enable_device(pdev) < 0) { - pch_pci_err(pdev, "pch_i2c_resume:pci_enable_device FAILED\n"); - return -EIO; - } - - pci_enable_wake(pdev, PCI_D3hot, 0); - - for (i = 0; i < adap_info->ch_num; i++) - pch_i2c_init(&adap_info->pch_data[i]); - - adap_info->pch_i2c_suspended = false; - - return 0; -} -#else -#define pch_i2c_suspend NULL -#define pch_i2c_resume NULL -#endif - -static struct pci_driver pch_pcidriver = { - .name = KBUILD_MODNAME, - .id_table = pch_pcidev_id, - .probe = pch_i2c_probe, - .remove = __devexit_p(pch_i2c_remove), - .suspend = pch_i2c_suspend, - .resume = pch_i2c_resume -}; - -static int __init pch_pci_init(void) -{ - return pci_register_driver(&pch_pcidriver); -} -module_init(pch_pci_init); - -static void __exit pch_pci_exit(void) -{ - pci_unregister_driver(&pch_pcidriver); -} -module_exit(pch_pci_exit); - -MODULE_DESCRIPTION("Intel EG20T PCH/LAPIS Semico ML7213/ML7223/ML7831 IOH I2C"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Tomoya MORINAGA. <tomoya.rohm@gmail.com>"); -module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR)); -module_param(pch_clk, int, (S_IRUSR | S_IWUSR)); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-elektor.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-elektor.c deleted file mode 100644 index 37e2e82a..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-elektor.c +++ /dev/null @@ -1,347 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-elektor.c i2c-hw access for PCF8584 style isa bus adaptes */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-97 Simon G. Vogl - 1998-99 Hans Berglund - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even - Frodo Looijaard <frodol@dds.nl> */ - -/* Partially rewriten by Oleg I. Vdovikin for mmapped support of - for Alpha Processor Inc. UP-2000(+) boards */ - -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/pci.h> -#include <linux/wait.h> - -#include <linux/isa.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-pcf.h> -#include <linux/io.h> - -#include <asm/irq.h> - -#include "../algos/i2c-algo-pcf.h" - -#define DEFAULT_BASE 0x330 - -static int base; -static u8 __iomem *base_iomem; - -static int irq; -static int clock = 0x1c; -static int own = 0x55; -static int mmapped; - -/* vdovikin: removed static struct i2c_pcf_isa gpi; code - - this module in real supports only one device, due to missing arguments - in some functions, called from the algo-pcf module. Sometimes it's - need to be rewriten - but for now just remove this for simpler reading */ - -static wait_queue_head_t pcf_wait; -static int pcf_pending; -static spinlock_t lock; - -static struct i2c_adapter pcf_isa_ops; - -/* ----- local functions ---------------------------------------------- */ - -static void pcf_isa_setbyte(void *data, int ctl, int val) -{ - u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem; - - /* enable irq if any specified for serial operation */ - if (ctl && irq && (val & I2C_PCF_ESO)) { - val |= I2C_PCF_ENI; - } - - pr_debug("%s: Write %p 0x%02X\n", pcf_isa_ops.name, address, val); - iowrite8(val, address); -#ifdef __alpha__ - /* API UP2000 needs some hardware fudging to make the write stick */ - iowrite8(val, address); -#endif -} - -static int pcf_isa_getbyte(void *data, int ctl) -{ - u8 __iomem *address = ctl ? (base_iomem + 1) : base_iomem; - int val = ioread8(address); - - pr_debug("%s: Read %p 0x%02X\n", pcf_isa_ops.name, address, val); - return (val); -} - -static int pcf_isa_getown(void *data) -{ - return (own); -} - - -static int pcf_isa_getclock(void *data) -{ - return (clock); -} - -static void pcf_isa_waitforpin(void *data) -{ - DEFINE_WAIT(wait); - int timeout = 2; - unsigned long flags; - - if (irq > 0) { - spin_lock_irqsave(&lock, flags); - if (pcf_pending == 0) { - spin_unlock_irqrestore(&lock, flags); - prepare_to_wait(&pcf_wait, &wait, TASK_INTERRUPTIBLE); - if (schedule_timeout(timeout*HZ)) { - spin_lock_irqsave(&lock, flags); - if (pcf_pending == 1) { - pcf_pending = 0; - } - spin_unlock_irqrestore(&lock, flags); - } - finish_wait(&pcf_wait, &wait); - } else { - pcf_pending = 0; - spin_unlock_irqrestore(&lock, flags); - } - } else { - udelay(100); - } -} - - -static irqreturn_t pcf_isa_handler(int this_irq, void *dev_id) { - spin_lock(&lock); - pcf_pending = 1; - spin_unlock(&lock); - wake_up_interruptible(&pcf_wait); - return IRQ_HANDLED; -} - - -static int pcf_isa_init(void) -{ - spin_lock_init(&lock); - if (!mmapped) { - if (!request_region(base, 2, pcf_isa_ops.name)) { - printk(KERN_ERR "%s: requested I/O region (%#x:2) is " - "in use\n", pcf_isa_ops.name, base); - return -ENODEV; - } - base_iomem = ioport_map(base, 2); - if (!base_iomem) { - printk(KERN_ERR "%s: remap of I/O region %#x failed\n", - pcf_isa_ops.name, base); - release_region(base, 2); - return -ENODEV; - } - } else { - if (!request_mem_region(base, 2, pcf_isa_ops.name)) { - printk(KERN_ERR "%s: requested memory region (%#x:2) " - "is in use\n", pcf_isa_ops.name, base); - return -ENODEV; - } - base_iomem = ioremap(base, 2); - if (base_iomem == NULL) { - printk(KERN_ERR "%s: remap of memory region %#x " - "failed\n", pcf_isa_ops.name, base); - release_mem_region(base, 2); - return -ENODEV; - } - } - pr_debug("%s: registers %#x remapped to %p\n", pcf_isa_ops.name, base, - base_iomem); - - if (irq > 0) { - if (request_irq(irq, pcf_isa_handler, 0, pcf_isa_ops.name, - NULL) < 0) { - printk(KERN_ERR "%s: Request irq%d failed\n", - pcf_isa_ops.name, irq); - irq = 0; - } else - enable_irq(irq); - } - return 0; -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ -static struct i2c_algo_pcf_data pcf_isa_data = { - .setpcf = pcf_isa_setbyte, - .getpcf = pcf_isa_getbyte, - .getown = pcf_isa_getown, - .getclock = pcf_isa_getclock, - .waitforpin = pcf_isa_waitforpin, -}; - -static struct i2c_adapter pcf_isa_ops = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo_data = &pcf_isa_data, - .name = "i2c-elektor", -}; - -static int __devinit elektor_match(struct device *dev, unsigned int id) -{ -#ifdef __alpha__ - /* check to see we have memory mapped PCF8584 connected to the - Cypress cy82c693 PCI-ISA bridge as on UP2000 board */ - if (base == 0) { - struct pci_dev *cy693_dev; - - cy693_dev = pci_get_device(PCI_VENDOR_ID_CONTAQ, - PCI_DEVICE_ID_CONTAQ_82C693, NULL); - if (cy693_dev) { - unsigned char config; - /* yeap, we've found cypress, let's check config */ - if (!pci_read_config_byte(cy693_dev, 0x47, &config)) { - - dev_dbg(dev, "found cy82c693, config " - "register 0x47 = 0x%02x\n", config); - - /* UP2000 board has this register set to 0xe1, - but the most significant bit as seems can be - reset during the proper initialisation - sequence if guys from API decides to do that - (so, we can even enable Tsunami Pchip - window for the upper 1 Gb) */ - - /* so just check for ROMCS at 0xe0000, - ROMCS enabled for writes - and external XD Bus buffer in use. */ - if ((config & 0x7f) == 0x61) { - /* seems to be UP2000 like board */ - base = 0xe0000; - mmapped = 1; - /* UP2000 drives ISA with - 8.25 MHz (PCI/4) clock - (this can be read from cypress) */ - clock = I2C_PCF_CLK | I2C_PCF_TRNS90; - dev_info(dev, "found API UP2000 like " - "board, will probe PCF8584 " - "later\n"); - } - } - pci_dev_put(cy693_dev); - } - } -#endif - - /* sanity checks for mmapped I/O */ - if (mmapped && base < 0xc8000) { - dev_err(dev, "incorrect base address (%#x) specified " - "for mmapped I/O\n", base); - return 0; - } - - if (base == 0) { - base = DEFAULT_BASE; - } - return 1; -} - -static int __devinit elektor_probe(struct device *dev, unsigned int id) -{ - init_waitqueue_head(&pcf_wait); - if (pcf_isa_init()) - return -ENODEV; - pcf_isa_ops.dev.parent = dev; - if (i2c_pcf_add_bus(&pcf_isa_ops) < 0) - goto fail; - - dev_info(dev, "found device at %#x\n", base); - - return 0; - - fail: - if (irq > 0) { - disable_irq(irq); - free_irq(irq, NULL); - } - - if (!mmapped) { - ioport_unmap(base_iomem); - release_region(base, 2); - } else { - iounmap(base_iomem); - release_mem_region(base, 2); - } - return -ENODEV; -} - -static int __devexit elektor_remove(struct device *dev, unsigned int id) -{ - i2c_del_adapter(&pcf_isa_ops); - - if (irq > 0) { - disable_irq(irq); - free_irq(irq, NULL); - } - - if (!mmapped) { - ioport_unmap(base_iomem); - release_region(base, 2); - } else { - iounmap(base_iomem); - release_mem_region(base, 2); - } - - return 0; -} - -static struct isa_driver i2c_elektor_driver = { - .match = elektor_match, - .probe = elektor_probe, - .remove = __devexit_p(elektor_remove), - .driver = { - .owner = THIS_MODULE, - .name = "i2c-elektor", - }, -}; - -static int __init i2c_pcfisa_init(void) -{ - return isa_register_driver(&i2c_elektor_driver, 1); -} - -static void __exit i2c_pcfisa_exit(void) -{ - isa_unregister_driver(&i2c_elektor_driver); -} - -MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>"); -MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter"); -MODULE_LICENSE("GPL"); - -module_param(base, int, 0); -module_param(irq, int, 0); -module_param(clock, int, 0); -module_param(own, int, 0); -module_param(mmapped, int, 0); - -module_init(i2c_pcfisa_init); -module_exit(i2c_pcfisa_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-gpio.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-gpio.c deleted file mode 100644 index c0330a41..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-gpio.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Bitbanging I2C bus driver using the GPIO API - * - * Copyright (C) 2007 Atmel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/i2c-gpio.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/gpio.h> -#include <linux/of_gpio.h> -#include <linux/of_i2c.h> - -struct i2c_gpio_private_data { - struct i2c_adapter adap; - struct i2c_algo_bit_data bit_data; - struct i2c_gpio_platform_data pdata; -}; - -/* Toggle SDA by changing the direction of the pin */ -static void i2c_gpio_setsda_dir(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - if (state) - gpio_direction_input(pdata->sda_pin); - else - gpio_direction_output(pdata->sda_pin, 0); -} - -/* - * Toggle SDA by changing the output value of the pin. This is only - * valid for pins configured as open drain (i.e. setting the value - * high effectively turns off the output driver.) - */ -static void i2c_gpio_setsda_val(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - gpio_set_value(pdata->sda_pin, state); -} - -/* Toggle SCL by changing the direction of the pin. */ -static void i2c_gpio_setscl_dir(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - if (state) - gpio_direction_input(pdata->scl_pin); - else - gpio_direction_output(pdata->scl_pin, 0); -} - -/* - * Toggle SCL by changing the output value of the pin. This is used - * for pins that are configured as open drain and for output-only - * pins. The latter case will break the i2c protocol, but it will - * often work in practice. - */ -static void i2c_gpio_setscl_val(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - gpio_set_value(pdata->scl_pin, state); -} - -static int i2c_gpio_getsda(void *data) -{ - struct i2c_gpio_platform_data *pdata = data; - - return gpio_get_value(pdata->sda_pin); -} - -static int i2c_gpio_getscl(void *data) -{ - struct i2c_gpio_platform_data *pdata = data; - - return gpio_get_value(pdata->scl_pin); -} - -static int __devinit of_i2c_gpio_probe(struct device_node *np, - struct i2c_gpio_platform_data *pdata) -{ - u32 reg; - - if (of_gpio_count(np) < 2) - return -ENODEV; - - pdata->sda_pin = of_get_gpio(np, 0); - pdata->scl_pin = of_get_gpio(np, 1); - - if (!gpio_is_valid(pdata->sda_pin) || !gpio_is_valid(pdata->scl_pin)) { - pr_err("%s: invalid GPIO pins, sda=%d/scl=%d\n", - np->full_name, pdata->sda_pin, pdata->scl_pin); - return -ENODEV; - } - - of_property_read_u32(np, "i2c-gpio,delay-us", &pdata->udelay); - - if (!of_property_read_u32(np, "i2c-gpio,timeout-ms", ®)) - pdata->timeout = msecs_to_jiffies(reg); - - pdata->sda_is_open_drain = - of_property_read_bool(np, "i2c-gpio,sda-open-drain"); - pdata->scl_is_open_drain = - of_property_read_bool(np, "i2c-gpio,scl-open-drain"); - pdata->scl_is_output_only = - of_property_read_bool(np, "i2c-gpio,scl-output-only"); - - return 0; -} - -static int __devinit i2c_gpio_probe(struct platform_device *pdev) -{ - struct i2c_gpio_private_data *priv; - struct i2c_gpio_platform_data *pdata; - struct i2c_algo_bit_data *bit_data; - struct i2c_adapter *adap; - int ret; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - adap = &priv->adap; - bit_data = &priv->bit_data; - pdata = &priv->pdata; - - if (pdev->dev.of_node) { - ret = of_i2c_gpio_probe(pdev->dev.of_node, pdata); - if (ret) - return ret; - } else { - if (!pdev->dev.platform_data) - return -ENXIO; - memcpy(pdata, pdev->dev.platform_data, sizeof(*pdata)); - } - - ret = gpio_request(pdata->sda_pin, "sda"); - if (ret) - goto err_request_sda; - ret = gpio_request(pdata->scl_pin, "scl"); - if (ret) - goto err_request_scl; - - if (pdata->sda_is_open_drain) { - gpio_direction_output(pdata->sda_pin, 1); - bit_data->setsda = i2c_gpio_setsda_val; - } else { - gpio_direction_input(pdata->sda_pin); - bit_data->setsda = i2c_gpio_setsda_dir; - } - - if (pdata->scl_is_open_drain || pdata->scl_is_output_only) { - gpio_direction_output(pdata->scl_pin, 1); - bit_data->setscl = i2c_gpio_setscl_val; - } else { - gpio_direction_input(pdata->scl_pin); - bit_data->setscl = i2c_gpio_setscl_dir; - } - - if (!pdata->scl_is_output_only) - bit_data->getscl = i2c_gpio_getscl; - bit_data->getsda = i2c_gpio_getsda; - - if (pdata->udelay) - bit_data->udelay = pdata->udelay; - else if (pdata->scl_is_output_only) - bit_data->udelay = 50; /* 10 kHz */ - else - bit_data->udelay = 5; /* 100 kHz */ - - if (pdata->timeout) - bit_data->timeout = pdata->timeout; - else - bit_data->timeout = HZ / 10; /* 100 ms */ - - bit_data->data = pdata; - - adap->owner = THIS_MODULE; - snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id); - adap->algo_data = bit_data; - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; - - /* - * If "dev->id" is negative we consider it as zero. - * The reason to do so is to avoid sysfs names that only make - * sense when there are multiple adapters. - */ - adap->nr = (pdev->id != -1) ? pdev->id : 0; - ret = i2c_bit_add_numbered_bus(adap); - if (ret) - goto err_add_bus; - - of_i2c_register_devices(adap); - - platform_set_drvdata(pdev, priv); - - dev_info(&pdev->dev, "using pins %u (SDA) and %u (SCL%s)\n", - pdata->sda_pin, pdata->scl_pin, - pdata->scl_is_output_only - ? ", no clock stretching" : ""); - - return 0; - -err_add_bus: - gpio_free(pdata->scl_pin); -err_request_scl: - gpio_free(pdata->sda_pin); -err_request_sda: - return ret; -} - -static int __devexit i2c_gpio_remove(struct platform_device *pdev) -{ - struct i2c_gpio_private_data *priv; - struct i2c_gpio_platform_data *pdata; - struct i2c_adapter *adap; - - priv = platform_get_drvdata(pdev); - adap = &priv->adap; - pdata = &priv->pdata; - - i2c_del_adapter(adap); - gpio_free(pdata->scl_pin); - gpio_free(pdata->sda_pin); - - return 0; -} - -#if defined(CONFIG_OF) -static const struct of_device_id i2c_gpio_dt_ids[] = { - { .compatible = "i2c-gpio", }, - { /* sentinel */ } -}; - -MODULE_DEVICE_TABLE(of, i2c_gpio_dt_ids); -#endif - -static struct platform_driver i2c_gpio_driver = { - .driver = { - .name = "i2c-gpio", - .owner = THIS_MODULE, - .of_match_table = of_match_ptr(i2c_gpio_dt_ids), - }, - .probe = i2c_gpio_probe, - .remove = __devexit_p(i2c_gpio_remove), -}; - -static int __init i2c_gpio_init(void) -{ - int ret; - - ret = platform_driver_register(&i2c_gpio_driver); - if (ret) - printk(KERN_ERR "i2c-gpio: probe failed: %d\n", ret); - - return ret; -} -subsys_initcall(i2c_gpio_init); - -static void __exit i2c_gpio_exit(void) -{ - platform_driver_unregister(&i2c_gpio_driver); -} -module_exit(i2c_gpio_exit); - -MODULE_AUTHOR("Haavard Skinnemoen (Atmel)"); -MODULE_DESCRIPTION("Platform-independent bitbanging I2C driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:i2c-gpio"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-highlander.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-highlander.c deleted file mode 100644 index 19515df6..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-highlander.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Renesas Solutions Highlander FPGA I2C/SMBus support. - * - * Supported devices: R0P7780LC0011RL, R0P7785LC0011RL - * - * Copyright (C) 2008 Paul Mundt - * Copyright (C) 2008 Renesas Solutions Corp. - * Copyright (C) 2008 Atom Create Engineering Co., Ltd. - * - * This file is subject to the terms and conditions of the GNU General - * Public License version 2. See the file "COPYING" in the main directory - * of this archive for more details. - */ -#include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> -#include <linux/completion.h> -#include <linux/io.h> -#include <linux/delay.h> -#include <linux/slab.h> - -#define SMCR 0x00 -#define SMCR_START (1 << 0) -#define SMCR_IRIC (1 << 1) -#define SMCR_BBSY (1 << 2) -#define SMCR_ACKE (1 << 3) -#define SMCR_RST (1 << 4) -#define SMCR_IEIC (1 << 6) - -#define SMSMADR 0x02 - -#define SMMR 0x04 -#define SMMR_MODE0 (1 << 0) -#define SMMR_MODE1 (1 << 1) -#define SMMR_CAP (1 << 3) -#define SMMR_TMMD (1 << 4) -#define SMMR_SP (1 << 7) - -#define SMSADR 0x06 -#define SMTRDR 0x46 - -struct highlander_i2c_dev { - struct device *dev; - void __iomem *base; - struct i2c_adapter adapter; - struct completion cmd_complete; - unsigned long last_read_time; - int irq; - u8 *buf; - size_t buf_len; -}; - -static bool iic_force_poll, iic_force_normal; -static int iic_timeout = 1000, iic_read_delay; - -static inline void highlander_i2c_irq_enable(struct highlander_i2c_dev *dev) -{ - iowrite16(ioread16(dev->base + SMCR) | SMCR_IEIC, dev->base + SMCR); -} - -static inline void highlander_i2c_irq_disable(struct highlander_i2c_dev *dev) -{ - iowrite16(ioread16(dev->base + SMCR) & ~SMCR_IEIC, dev->base + SMCR); -} - -static inline void highlander_i2c_start(struct highlander_i2c_dev *dev) -{ - iowrite16(ioread16(dev->base + SMCR) | SMCR_START, dev->base + SMCR); -} - -static inline void highlander_i2c_done(struct highlander_i2c_dev *dev) -{ - iowrite16(ioread16(dev->base + SMCR) | SMCR_IRIC, dev->base + SMCR); -} - -static void highlander_i2c_setup(struct highlander_i2c_dev *dev) -{ - u16 smmr; - - smmr = ioread16(dev->base + SMMR); - smmr |= SMMR_TMMD; - - if (iic_force_normal) - smmr &= ~SMMR_SP; - else - smmr |= SMMR_SP; - - iowrite16(smmr, dev->base + SMMR); -} - -static void smbus_write_data(u8 *src, u16 *dst, int len) -{ - for (; len > 1; len -= 2) { - *dst++ = be16_to_cpup((__be16 *)src); - src += 2; - } - - if (len) - *dst = *src << 8; -} - -static void smbus_read_data(u16 *src, u8 *dst, int len) -{ - for (; len > 1; len -= 2) { - *(__be16 *)dst = cpu_to_be16p(src++); - dst += 2; - } - - if (len) - *dst = *src >> 8; -} - -static void highlander_i2c_command(struct highlander_i2c_dev *dev, - u8 command, int len) -{ - unsigned int i; - u16 cmd = (command << 8) | command; - - for (i = 0; i < len; i += 2) { - if (len - i == 1) - cmd = command << 8; - iowrite16(cmd, dev->base + SMSADR + i); - dev_dbg(dev->dev, "command data[%x] 0x%04x\n", i/2, cmd); - } -} - -static int highlander_i2c_wait_for_bbsy(struct highlander_i2c_dev *dev) -{ - unsigned long timeout; - - timeout = jiffies + msecs_to_jiffies(iic_timeout); - while (ioread16(dev->base + SMCR) & SMCR_BBSY) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; - } - - msleep(1); - } - - return 0; -} - -static int highlander_i2c_reset(struct highlander_i2c_dev *dev) -{ - iowrite16(ioread16(dev->base + SMCR) | SMCR_RST, dev->base + SMCR); - return highlander_i2c_wait_for_bbsy(dev); -} - -static int highlander_i2c_wait_for_ack(struct highlander_i2c_dev *dev) -{ - u16 tmp = ioread16(dev->base + SMCR); - - if ((tmp & (SMCR_IRIC | SMCR_ACKE)) == SMCR_ACKE) { - dev_warn(dev->dev, "ack abnormality\n"); - return highlander_i2c_reset(dev); - } - - return 0; -} - -static irqreturn_t highlander_i2c_irq(int irq, void *dev_id) -{ - struct highlander_i2c_dev *dev = dev_id; - - highlander_i2c_done(dev); - complete(&dev->cmd_complete); - - return IRQ_HANDLED; -} - -static void highlander_i2c_poll(struct highlander_i2c_dev *dev) -{ - unsigned long timeout; - u16 smcr; - - timeout = jiffies + msecs_to_jiffies(iic_timeout); - for (;;) { - smcr = ioread16(dev->base + SMCR); - - /* - * Don't bother checking ACKE here, this and the reset - * are handled in highlander_i2c_wait_xfer_done() when - * waiting for the ACK. - */ - - if (smcr & SMCR_IRIC) - return; - if (time_after(jiffies, timeout)) - break; - - cpu_relax(); - cond_resched(); - } - - dev_err(dev->dev, "polling timed out\n"); -} - -static inline int highlander_i2c_wait_xfer_done(struct highlander_i2c_dev *dev) -{ - if (dev->irq) - wait_for_completion_timeout(&dev->cmd_complete, - msecs_to_jiffies(iic_timeout)); - else - /* busy looping, the IRQ of champions */ - highlander_i2c_poll(dev); - - return highlander_i2c_wait_for_ack(dev); -} - -static int highlander_i2c_read(struct highlander_i2c_dev *dev) -{ - int i, cnt; - u16 data[16]; - - if (highlander_i2c_wait_for_bbsy(dev)) - return -EAGAIN; - - highlander_i2c_start(dev); - - if (highlander_i2c_wait_xfer_done(dev)) { - dev_err(dev->dev, "Arbitration loss\n"); - return -EAGAIN; - } - - /* - * The R0P7780LC0011RL FPGA needs a significant delay between - * data read cycles, otherwise the transceiver gets confused and - * garbage is returned when the read is subsequently aborted. - * - * It is not sufficient to wait for BBSY. - * - * While this generally only applies to the older SH7780-based - * Highlanders, the same issue can be observed on SH7785 ones, - * albeit less frequently. SH7780-based Highlanders may need - * this to be as high as 1000 ms. - */ - if (iic_read_delay && time_before(jiffies, dev->last_read_time + - msecs_to_jiffies(iic_read_delay))) - msleep(jiffies_to_msecs((dev->last_read_time + - msecs_to_jiffies(iic_read_delay)) - jiffies)); - - cnt = (dev->buf_len + 1) >> 1; - for (i = 0; i < cnt; i++) { - data[i] = ioread16(dev->base + SMTRDR + (i * sizeof(u16))); - dev_dbg(dev->dev, "read data[%x] 0x%04x\n", i, data[i]); - } - - smbus_read_data(data, dev->buf, dev->buf_len); - - dev->last_read_time = jiffies; - - return 0; -} - -static int highlander_i2c_write(struct highlander_i2c_dev *dev) -{ - int i, cnt; - u16 data[16]; - - smbus_write_data(dev->buf, data, dev->buf_len); - - cnt = (dev->buf_len + 1) >> 1; - for (i = 0; i < cnt; i++) { - iowrite16(data[i], dev->base + SMTRDR + (i * sizeof(u16))); - dev_dbg(dev->dev, "write data[%x] 0x%04x\n", i, data[i]); - } - - if (highlander_i2c_wait_for_bbsy(dev)) - return -EAGAIN; - - highlander_i2c_start(dev); - - return highlander_i2c_wait_xfer_done(dev); -} - -static int highlander_i2c_smbus_xfer(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - struct highlander_i2c_dev *dev = i2c_get_adapdata(adap); - u16 tmp; - - init_completion(&dev->cmd_complete); - - dev_dbg(dev->dev, "addr %04x, command %02x, read_write %d, size %d\n", - addr, command, read_write, size); - - /* - * Set up the buffer and transfer size - */ - switch (size) { - case I2C_SMBUS_BYTE_DATA: - dev->buf = &data->byte; - dev->buf_len = 1; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - dev->buf = &data->block[1]; - dev->buf_len = data->block[0]; - break; - default: - dev_err(dev->dev, "unsupported command %d\n", size); - return -EINVAL; - } - - /* - * Encode the mode setting - */ - tmp = ioread16(dev->base + SMMR); - tmp &= ~(SMMR_MODE0 | SMMR_MODE1); - - switch (dev->buf_len) { - case 1: - /* default */ - break; - case 8: - tmp |= SMMR_MODE0; - break; - case 16: - tmp |= SMMR_MODE1; - break; - case 32: - tmp |= (SMMR_MODE0 | SMMR_MODE1); - break; - default: - dev_err(dev->dev, "unsupported xfer size %d\n", dev->buf_len); - return -EINVAL; - } - - iowrite16(tmp, dev->base + SMMR); - - /* Ensure we're in a sane state */ - highlander_i2c_done(dev); - - /* Set slave address */ - iowrite16((addr << 1) | read_write, dev->base + SMSMADR); - - highlander_i2c_command(dev, command, dev->buf_len); - - if (read_write == I2C_SMBUS_READ) - return highlander_i2c_read(dev); - else - return highlander_i2c_write(dev); -} - -static u32 highlander_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; -} - -static const struct i2c_algorithm highlander_i2c_algo = { - .smbus_xfer = highlander_i2c_smbus_xfer, - .functionality = highlander_i2c_func, -}; - -static int __devinit highlander_i2c_probe(struct platform_device *pdev) -{ - struct highlander_i2c_dev *dev; - struct i2c_adapter *adap; - struct resource *res; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (unlikely(!res)) { - dev_err(&pdev->dev, "no mem resource\n"); - return -ENODEV; - } - - dev = kzalloc(sizeof(struct highlander_i2c_dev), GFP_KERNEL); - if (unlikely(!dev)) - return -ENOMEM; - - dev->base = ioremap_nocache(res->start, resource_size(res)); - if (unlikely(!dev->base)) { - ret = -ENXIO; - goto err; - } - - dev->dev = &pdev->dev; - platform_set_drvdata(pdev, dev); - - dev->irq = platform_get_irq(pdev, 0); - if (iic_force_poll) - dev->irq = 0; - - if (dev->irq) { - ret = request_irq(dev->irq, highlander_i2c_irq, 0, - pdev->name, dev); - if (unlikely(ret)) - goto err_unmap; - - highlander_i2c_irq_enable(dev); - } else { - dev_notice(&pdev->dev, "no IRQ, using polling mode\n"); - highlander_i2c_irq_disable(dev); - } - - dev->last_read_time = jiffies; /* initial read jiffies */ - - highlander_i2c_setup(dev); - - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; - strlcpy(adap->name, "HL FPGA I2C adapter", sizeof(adap->name)); - adap->algo = &highlander_i2c_algo; - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; - - /* - * Reset the adapter - */ - ret = highlander_i2c_reset(dev); - if (unlikely(ret)) { - dev_err(&pdev->dev, "controller didn't come up\n"); - goto err_free_irq; - } - - ret = i2c_add_numbered_adapter(adap); - if (unlikely(ret)) { - dev_err(&pdev->dev, "failure adding adapter\n"); - goto err_free_irq; - } - - return 0; - -err_free_irq: - if (dev->irq) - free_irq(dev->irq, dev); -err_unmap: - iounmap(dev->base); -err: - kfree(dev); - - platform_set_drvdata(pdev, NULL); - - return ret; -} - -static int __devexit highlander_i2c_remove(struct platform_device *pdev) -{ - struct highlander_i2c_dev *dev = platform_get_drvdata(pdev); - - i2c_del_adapter(&dev->adapter); - - if (dev->irq) - free_irq(dev->irq, dev); - - iounmap(dev->base); - kfree(dev); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver highlander_i2c_driver = { - .driver = { - .name = "i2c-highlander", - .owner = THIS_MODULE, - }, - - .probe = highlander_i2c_probe, - .remove = __devexit_p(highlander_i2c_remove), -}; - -module_platform_driver(highlander_i2c_driver); - -MODULE_AUTHOR("Paul Mundt"); -MODULE_DESCRIPTION("Renesas Highlander FPGA I2C/SMBus adapter"); -MODULE_LICENSE("GPL v2"); - -module_param(iic_force_poll, bool, 0); -module_param(iic_force_normal, bool, 0); -module_param(iic_timeout, int, 0); -module_param(iic_read_delay, int, 0); - -MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); -MODULE_PARM_DESC(iic_force_normal, - "Force normal mode (100 kHz), default is fast mode (400 kHz)"); -MODULE_PARM_DESC(iic_timeout, "Set timeout value in msecs (default 1000 ms)"); -MODULE_PARM_DESC(iic_read_delay, - "Delay between data read cycles (default 0 ms)"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-hydra.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-hydra.c deleted file mode 100644 index c527de17..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-hydra.c +++ /dev/null @@ -1,178 +0,0 @@ -/* - i2c Support for the Apple `Hydra' Mac I/O - - Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org> - - Based on i2c Support for Via Technologies 82C586B South Bridge - Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/types.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/init.h> -#include <linux/io.h> -#include <asm/hydra.h> - - -#define HYDRA_CPD_PD0 0x00000001 /* CachePD lines */ -#define HYDRA_CPD_PD1 0x00000002 -#define HYDRA_CPD_PD2 0x00000004 -#define HYDRA_CPD_PD3 0x00000008 - -#define HYDRA_SCLK HYDRA_CPD_PD0 -#define HYDRA_SDAT HYDRA_CPD_PD1 -#define HYDRA_SCLK_OE 0x00000010 -#define HYDRA_SDAT_OE 0x00000020 - -static inline void pdregw(void *data, u32 val) -{ - struct Hydra *hydra = (struct Hydra *)data; - writel(val, &hydra->CachePD); -} - -static inline u32 pdregr(void *data) -{ - struct Hydra *hydra = (struct Hydra *)data; - return readl(&hydra->CachePD); -} - -static void hydra_bit_setscl(void *data, int state) -{ - u32 val = pdregr(data); - if (state) - val &= ~HYDRA_SCLK_OE; - else { - val &= ~HYDRA_SCLK; - val |= HYDRA_SCLK_OE; - } - pdregw(data, val); -} - -static void hydra_bit_setsda(void *data, int state) -{ - u32 val = pdregr(data); - if (state) - val &= ~HYDRA_SDAT_OE; - else { - val &= ~HYDRA_SDAT; - val |= HYDRA_SDAT_OE; - } - pdregw(data, val); -} - -static int hydra_bit_getscl(void *data) -{ - return (pdregr(data) & HYDRA_SCLK) != 0; -} - -static int hydra_bit_getsda(void *data) -{ - return (pdregr(data) & HYDRA_SDAT) != 0; -} - -/* ------------------------------------------------------------------------ */ - -static struct i2c_algo_bit_data hydra_bit_data = { - .setsda = hydra_bit_setsda, - .setscl = hydra_bit_setscl, - .getsda = hydra_bit_getsda, - .getscl = hydra_bit_getscl, - .udelay = 5, - .timeout = HZ -}; - -static struct i2c_adapter hydra_adap = { - .owner = THIS_MODULE, - .name = "Hydra i2c", - .algo_data = &hydra_bit_data, -}; - -static DEFINE_PCI_DEVICE_TABLE(hydra_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_HYDRA) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, hydra_ids); - -static int __devinit hydra_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - unsigned long base = pci_resource_start(dev, 0); - int res; - - if (!request_mem_region(base+offsetof(struct Hydra, CachePD), 4, - hydra_adap.name)) - return -EBUSY; - - hydra_bit_data.data = pci_ioremap_bar(dev, 0); - if (hydra_bit_data.data == NULL) { - release_mem_region(base+offsetof(struct Hydra, CachePD), 4); - return -ENODEV; - } - - pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ - hydra_adap.dev.parent = &dev->dev; - res = i2c_bit_add_bus(&hydra_adap); - if (res < 0) { - iounmap(hydra_bit_data.data); - release_mem_region(base+offsetof(struct Hydra, CachePD), 4); - return res; - } - return 0; -} - -static void __devexit hydra_remove(struct pci_dev *dev) -{ - pdregw(hydra_bit_data.data, 0); /* clear SCLK_OE and SDAT_OE */ - i2c_del_adapter(&hydra_adap); - iounmap(hydra_bit_data.data); - release_mem_region(pci_resource_start(dev, 0)+ - offsetof(struct Hydra, CachePD), 4); -} - - -static struct pci_driver hydra_driver = { - .name = "hydra_smbus", - .id_table = hydra_ids, - .probe = hydra_probe, - .remove = __devexit_p(hydra_remove), -}; - -static int __init i2c_hydra_init(void) -{ - return pci_register_driver(&hydra_driver); -} - - -static void __exit i2c_hydra_exit(void) -{ - pci_unregister_driver(&hydra_driver); -} - - - -MODULE_AUTHOR("Geert Uytterhoeven <geert@linux-m68k.org>"); -MODULE_DESCRIPTION("i2c for Apple Hydra Mac I/O"); -MODULE_LICENSE("GPL"); - -module_init(i2c_hydra_init); -module_exit(i2c_hydra_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-i801.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-i801.c deleted file mode 100644 index ae2945a5..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-i801.c +++ /dev/null @@ -1,949 +0,0 @@ -/* - Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, - Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker - <mdsxyz123@yahoo.com> - Copyright (C) 2007 - 2012 Jean Delvare <khali@linux-fr.org> - Copyright (C) 2010 Intel Corporation, - David Woodhouse <dwmw2@infradead.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports the following Intel I/O Controller Hubs (ICH): - - I/O Block I2C - region SMBus Block proc. block - Chip name PCI ID size PEC buffer call read - ---------------------------------------------------------------------- - 82801AA (ICH) 0x2413 16 no no no no - 82801AB (ICH0) 0x2423 16 no no no no - 82801BA (ICH2) 0x2443 16 no no no no - 82801CA (ICH3) 0x2483 32 soft no no no - 82801DB (ICH4) 0x24c3 32 hard yes no no - 82801E (ICH5) 0x24d3 32 hard yes yes yes - 6300ESB 0x25a4 32 hard yes yes yes - 82801F (ICH6) 0x266a 32 hard yes yes yes - 6310ESB/6320ESB 0x269b 32 hard yes yes yes - 82801G (ICH7) 0x27da 32 hard yes yes yes - 82801H (ICH8) 0x283e 32 hard yes yes yes - 82801I (ICH9) 0x2930 32 hard yes yes yes - EP80579 (Tolapai) 0x5032 32 hard yes yes yes - ICH10 0x3a30 32 hard yes yes yes - ICH10 0x3a60 32 hard yes yes yes - 5/3400 Series (PCH) 0x3b30 32 hard yes yes yes - 6 Series (PCH) 0x1c22 32 hard yes yes yes - Patsburg (PCH) 0x1d22 32 hard yes yes yes - Patsburg (PCH) IDF 0x1d70 32 hard yes yes yes - Patsburg (PCH) IDF 0x1d71 32 hard yes yes yes - Patsburg (PCH) IDF 0x1d72 32 hard yes yes yes - DH89xxCC (PCH) 0x2330 32 hard yes yes yes - Panther Point (PCH) 0x1e22 32 hard yes yes yes - Lynx Point (PCH) 0x8c22 32 hard yes yes yes - - Features supported by this driver: - Software PEC no - Hardware PEC yes - Block buffer yes - Block process call transaction no - I2C block read transaction yes (doesn't use the block buffer) - Slave mode no - - See the file Documentation/i2c/busses/i2c-i801 for details. -*/ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/delay.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/acpi.h> -#include <linux/io.h> -#include <linux/dmi.h> -#include <linux/slab.h> - -/* I801 SMBus address offsets */ -#define SMBHSTSTS(p) (0 + (p)->smba) -#define SMBHSTCNT(p) (2 + (p)->smba) -#define SMBHSTCMD(p) (3 + (p)->smba) -#define SMBHSTADD(p) (4 + (p)->smba) -#define SMBHSTDAT0(p) (5 + (p)->smba) -#define SMBHSTDAT1(p) (6 + (p)->smba) -#define SMBBLKDAT(p) (7 + (p)->smba) -#define SMBPEC(p) (8 + (p)->smba) /* ICH3 and later */ -#define SMBAUXSTS(p) (12 + (p)->smba) /* ICH4 and later */ -#define SMBAUXCTL(p) (13 + (p)->smba) /* ICH4 and later */ - -/* PCI Address Constants */ -#define SMBBAR 4 -#define SMBHSTCFG 0x040 - -/* Host configuration bits for SMBHSTCFG */ -#define SMBHSTCFG_HST_EN 1 -#define SMBHSTCFG_SMB_SMI_EN 2 -#define SMBHSTCFG_I2C_EN 4 - -/* Auxiliary control register bits, ICH4+ only */ -#define SMBAUXCTL_CRC 1 -#define SMBAUXCTL_E32B 2 - -/* kill bit for SMBHSTCNT */ -#define SMBHSTCNT_KILL 2 - -/* Other settings */ -#define MAX_RETRIES 400 -#define ENABLE_INT9 0 /* set to 0x01 to enable - untested */ - -/* I801 command constants */ -#define I801_QUICK 0x00 -#define I801_BYTE 0x04 -#define I801_BYTE_DATA 0x08 -#define I801_WORD_DATA 0x0C -#define I801_PROC_CALL 0x10 /* unimplemented */ -#define I801_BLOCK_DATA 0x14 -#define I801_I2C_BLOCK_DATA 0x18 /* ICH5 and later */ -#define I801_BLOCK_LAST 0x34 -#define I801_I2C_BLOCK_LAST 0x38 /* ICH5 and later */ -#define I801_START 0x40 -#define I801_PEC_EN 0x80 /* ICH3 and later */ - -/* I801 Hosts Status register bits */ -#define SMBHSTSTS_BYTE_DONE 0x80 -#define SMBHSTSTS_INUSE_STS 0x40 -#define SMBHSTSTS_SMBALERT_STS 0x20 -#define SMBHSTSTS_FAILED 0x10 -#define SMBHSTSTS_BUS_ERR 0x08 -#define SMBHSTSTS_DEV_ERR 0x04 -#define SMBHSTSTS_INTR 0x02 -#define SMBHSTSTS_HOST_BUSY 0x01 - -#define STATUS_FLAGS (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \ - SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \ - SMBHSTSTS_INTR) - -/* Older devices have their ID defined in <linux/pci_ids.h> */ -#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 -/* Patsburg also has three 'Integrated Device Function' SMBus controllers */ -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0 0x1d70 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1 0x1d71 -#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2 0x1d72 -#define PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS 0x1e22 -#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS 0x2330 -#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS 0x3b30 -#define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS 0x8c22 - -struct i801_priv { - struct i2c_adapter adapter; - unsigned long smba; - unsigned char original_hstcfg; - struct pci_dev *pci_dev; - unsigned int features; -}; - -static struct pci_driver i801_driver; - -#define FEATURE_SMBUS_PEC (1 << 0) -#define FEATURE_BLOCK_BUFFER (1 << 1) -#define FEATURE_BLOCK_PROC (1 << 2) -#define FEATURE_I2C_BLOCK_READ (1 << 3) -/* Not really a feature, but it's convenient to handle it as such */ -#define FEATURE_IDF (1 << 15) - -static const char *i801_feature_names[] = { - "SMBus PEC", - "Block buffer", - "Block process call", - "I2C block read", -}; - -static unsigned int disable_features; -module_param(disable_features, uint, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(disable_features, "Disable selected driver features"); - -/* Make sure the SMBus host is ready to start transmitting. - Return 0 if it is, -EBUSY if it is not. */ -static int i801_check_pre(struct i801_priv *priv) -{ - int status; - - status = inb_p(SMBHSTSTS(priv)); - if (status & SMBHSTSTS_HOST_BUSY) { - dev_err(&priv->pci_dev->dev, "SMBus is busy, can't use it!\n"); - return -EBUSY; - } - - status &= STATUS_FLAGS; - if (status) { - dev_dbg(&priv->pci_dev->dev, "Clearing status flags (%02x)\n", - status); - outb_p(status, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) { - dev_err(&priv->pci_dev->dev, - "Failed clearing status flags (%02x)\n", - status); - return -EBUSY; - } - } - - return 0; -} - -/* Convert the status register to an error code, and clear it. */ -static int i801_check_post(struct i801_priv *priv, int status, int timeout) -{ - int result = 0; - - /* If the SMBus is still busy, we give up */ - if (timeout) { - dev_err(&priv->pci_dev->dev, "Transaction timeout\n"); - /* try to stop the current command */ - dev_dbg(&priv->pci_dev->dev, "Terminating the current operation\n"); - outb_p(inb_p(SMBHSTCNT(priv)) | SMBHSTCNT_KILL, - SMBHSTCNT(priv)); - usleep_range(1000, 2000); - outb_p(inb_p(SMBHSTCNT(priv)) & (~SMBHSTCNT_KILL), - SMBHSTCNT(priv)); - - /* Check if it worked */ - status = inb_p(SMBHSTSTS(priv)); - if ((status & SMBHSTSTS_HOST_BUSY) || - !(status & SMBHSTSTS_FAILED)) - dev_err(&priv->pci_dev->dev, - "Failed terminating the transaction\n"); - outb_p(STATUS_FLAGS, SMBHSTSTS(priv)); - return -ETIMEDOUT; - } - - if (status & SMBHSTSTS_FAILED) { - result = -EIO; - dev_err(&priv->pci_dev->dev, "Transaction failed\n"); - } - if (status & SMBHSTSTS_DEV_ERR) { - result = -ENXIO; - dev_dbg(&priv->pci_dev->dev, "No response\n"); - } - if (status & SMBHSTSTS_BUS_ERR) { - result = -EAGAIN; - dev_dbg(&priv->pci_dev->dev, "Lost arbitration\n"); - } - - if (result) { - /* Clear error flags */ - outb_p(status & STATUS_FLAGS, SMBHSTSTS(priv)); - status = inb_p(SMBHSTSTS(priv)) & STATUS_FLAGS; - if (status) { - dev_warn(&priv->pci_dev->dev, "Failed clearing status " - "flags at end of transaction (%02x)\n", - status); - } - } - - return result; -} - -static int i801_transaction(struct i801_priv *priv, int xact) -{ - int status; - int result; - int timeout = 0; - - result = i801_check_pre(priv); - if (result < 0) - return result; - - /* the current contents of SMBHSTCNT can be overwritten, since PEC, - * INTREN, SMBSCMD are passed in xact */ - outb_p(xact | I801_START, SMBHSTCNT(priv)); - - /* We will always wait for a fraction of a second! */ - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); - return 0; -} - -/* wait for INTR bit as advised by Intel */ -static void i801_wait_hwpec(struct i801_priv *priv) -{ - int timeout = 0; - int status; - - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((!(status & SMBHSTSTS_INTR)) - && (timeout++ < MAX_RETRIES)); - - if (timeout > MAX_RETRIES) - dev_dbg(&priv->pci_dev->dev, "PEC Timeout!\n"); - - outb_p(status, SMBHSTSTS(priv)); -} - -static int i801_block_transaction_by_block(struct i801_priv *priv, - union i2c_smbus_data *data, - char read_write, int hwpec) -{ - int i, len; - int status; - - inb_p(SMBHSTCNT(priv)); /* reset the data buffer index */ - - /* Use 32-byte buffer to process this transaction */ - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - outb_p(len, SMBHSTDAT0(priv)); - for (i = 0; i < len; i++) - outb_p(data->block[i+1], SMBBLKDAT(priv)); - } - - status = i801_transaction(priv, I801_BLOCK_DATA | ENABLE_INT9 | - I801_PEC_EN * hwpec); - if (status) - return status; - - if (read_write == I2C_SMBUS_READ) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - - data->block[0] = len; - for (i = 0; i < len; i++) - data->block[i + 1] = inb_p(SMBBLKDAT(priv)); - } - return 0; -} - -static int i801_block_transaction_byte_by_byte(struct i801_priv *priv, - union i2c_smbus_data *data, - char read_write, int command, - int hwpec) -{ - int i, len; - int smbcmd; - int status; - int result; - int timeout; - - result = i801_check_pre(priv); - if (result < 0) - return result; - - len = data->block[0]; - - if (read_write == I2C_SMBUS_WRITE) { - outb_p(len, SMBHSTDAT0(priv)); - outb_p(data->block[1], SMBBLKDAT(priv)); - } - - for (i = 1; i <= len; i++) { - if (i == len && read_write == I2C_SMBUS_READ) { - if (command == I2C_SMBUS_I2C_BLOCK_DATA) - smbcmd = I801_I2C_BLOCK_LAST; - else - smbcmd = I801_BLOCK_LAST; - } else { - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) - smbcmd = I801_I2C_BLOCK_DATA; - else - smbcmd = I801_BLOCK_DATA; - } - outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT(priv)); - - if (i == 1) - outb_p(inb(SMBHSTCNT(priv)) | I801_START, - SMBHSTCNT(priv)); - - /* We will always wait for a fraction of a second! */ - timeout = 0; - do { - usleep_range(250, 500); - status = inb_p(SMBHSTSTS(priv)); - } while ((!(status & SMBHSTSTS_BYTE_DONE)) - && (timeout++ < MAX_RETRIES)); - - result = i801_check_post(priv, status, timeout > MAX_RETRIES); - if (result < 0) - return result; - - if (i == 1 && read_write == I2C_SMBUS_READ - && command != I2C_SMBUS_I2C_BLOCK_DATA) { - len = inb_p(SMBHSTDAT0(priv)); - if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) { - dev_err(&priv->pci_dev->dev, - "Illegal SMBus block read size %d\n", - len); - /* Recover */ - while (inb_p(SMBHSTSTS(priv)) & - SMBHSTSTS_HOST_BUSY) - outb_p(SMBHSTSTS_BYTE_DONE, - SMBHSTSTS(priv)); - outb_p(SMBHSTSTS_INTR, SMBHSTSTS(priv)); - return -EPROTO; - } - data->block[0] = len; - } - - /* Retrieve/store value in SMBBLKDAT */ - if (read_write == I2C_SMBUS_READ) - data->block[i] = inb_p(SMBBLKDAT(priv)); - if (read_write == I2C_SMBUS_WRITE && i+1 <= len) - outb_p(data->block[i+1], SMBBLKDAT(priv)); - - /* signals SMBBLKDAT ready */ - outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS(priv)); - } - - return 0; -} - -static int i801_set_block_buffer_mode(struct i801_priv *priv) -{ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_E32B, SMBAUXCTL(priv)); - if ((inb_p(SMBAUXCTL(priv)) & SMBAUXCTL_E32B) == 0) - return -EIO; - return 0; -} - -/* Block transaction function */ -static int i801_block_transaction(struct i801_priv *priv, - union i2c_smbus_data *data, char read_write, - int command, int hwpec) -{ - int result = 0; - unsigned char hostc; - - if (command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (read_write == I2C_SMBUS_WRITE) { - /* set I2C_EN bit in configuration register */ - pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &hostc); - pci_write_config_byte(priv->pci_dev, SMBHSTCFG, - hostc | SMBHSTCFG_I2C_EN); - } else if (!(priv->features & FEATURE_I2C_BLOCK_READ)) { - dev_err(&priv->pci_dev->dev, - "I2C block read is unsupported!\n"); - return -EOPNOTSUPP; - } - } - - if (read_write == I2C_SMBUS_WRITE - || command == I2C_SMBUS_I2C_BLOCK_DATA) { - if (data->block[0] < 1) - data->block[0] = 1; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - } else { - data->block[0] = 32; /* max for SMBus block reads */ - } - - /* Experience has shown that the block buffer can only be used for - SMBus (not I2C) block transactions, even though the datasheet - doesn't mention this limitation. */ - if ((priv->features & FEATURE_BLOCK_BUFFER) - && command != I2C_SMBUS_I2C_BLOCK_DATA - && i801_set_block_buffer_mode(priv) == 0) - result = i801_block_transaction_by_block(priv, data, - read_write, hwpec); - else - result = i801_block_transaction_byte_by_byte(priv, data, - read_write, - command, hwpec); - - if (result == 0 && hwpec) - i801_wait_hwpec(priv); - - if (command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_WRITE) { - /* restore saved configuration register value */ - pci_write_config_byte(priv->pci_dev, SMBHSTCFG, hostc); - } - return result; -} - -/* Return negative errno on error. */ -static s32 i801_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int hwpec; - int block = 0; - int ret, xact = 0; - struct i801_priv *priv = i2c_get_adapdata(adap); - - hwpec = (priv->features & FEATURE_SMBUS_PEC) && (flags & I2C_CLIENT_PEC) - && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA; - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - xact = I801_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD(priv)); - xact = I801_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0(priv)); - xact = I801_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - outb_p(command, SMBHSTCMD(priv)); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0(priv)); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1(priv)); - } - xact = I801_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p(((addr & 0x7f) << 1) | (read_write & 0x01), - SMBHSTADD(priv)); - outb_p(command, SMBHSTCMD(priv)); - block = 1; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - /* NB: page 240 of ICH5 datasheet shows that the R/#W - * bit should be cleared here, even when reading */ - outb_p((addr & 0x7f) << 1, SMBHSTADD(priv)); - if (read_write == I2C_SMBUS_READ) { - /* NB: page 240 of ICH5 datasheet also shows - * that DATA1 is the cmd field when reading */ - outb_p(command, SMBHSTDAT1(priv)); - } else - outb_p(command, SMBHSTCMD(priv)); - block = 1; - break; - default: - dev_err(&priv->pci_dev->dev, "Unsupported transaction %d\n", - size); - return -EOPNOTSUPP; - } - - if (hwpec) /* enable/disable hardware PEC */ - outb_p(inb_p(SMBAUXCTL(priv)) | SMBAUXCTL_CRC, SMBAUXCTL(priv)); - else - outb_p(inb_p(SMBAUXCTL(priv)) & (~SMBAUXCTL_CRC), - SMBAUXCTL(priv)); - - if (block) - ret = i801_block_transaction(priv, data, read_write, size, - hwpec); - else - ret = i801_transaction(priv, xact | ENABLE_INT9); - - /* Some BIOSes don't like it when PEC is enabled at reboot or resume - time, so we forcibly disable it after every transaction. Turn off - E32B for the same reason. */ - if (hwpec || block) - outb_p(inb_p(SMBAUXCTL(priv)) & - ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); - - if (block) - return ret; - if (ret) - return ret; - if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK)) - return 0; - - switch (xact & 0x7f) { - case I801_BYTE: /* Result put in SMBHSTDAT0 */ - case I801_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0(priv)); - break; - case I801_WORD_DATA: - data->word = inb_p(SMBHSTDAT0(priv)) + - (inb_p(SMBHSTDAT1(priv)) << 8); - break; - } - return 0; -} - - -static u32 i801_func(struct i2c_adapter *adapter) -{ - struct i801_priv *priv = i2c_get_adapdata(adapter); - - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK | - ((priv->features & FEATURE_SMBUS_PEC) ? I2C_FUNC_SMBUS_PEC : 0) | - ((priv->features & FEATURE_I2C_BLOCK_READ) ? - I2C_FUNC_SMBUS_READ_I2C_BLOCK : 0); -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = i801_access, - .functionality = i801_func, -}; - -static DEFINE_PCI_DEVICE_TABLE(i801_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_2) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_4) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_16) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_17) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB2_17) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH8_5) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH9_6) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_EP80579_1) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, i801_ids); - -#if defined CONFIG_X86 && defined CONFIG_DMI -static unsigned char apanel_addr; - -/* Scan the system ROM for the signature "FJKEYINF" */ -static __init const void __iomem *bios_signature(const void __iomem *bios) -{ - ssize_t offset; - const unsigned char signature[] = "FJKEYINF"; - - for (offset = 0; offset < 0x10000; offset += 0x10) { - if (check_signature(bios + offset, signature, - sizeof(signature)-1)) - return bios + offset; - } - return NULL; -} - -static void __init input_apanel_init(void) -{ - void __iomem *bios; - const void __iomem *p; - - bios = ioremap(0xF0000, 0x10000); /* Can't fail */ - p = bios_signature(bios); - if (p) { - /* just use the first address */ - apanel_addr = readb(p + 8 + 3) >> 1; - } - iounmap(bios); -} - -struct dmi_onboard_device_info { - const char *name; - u8 type; - unsigned short i2c_addr; - const char *i2c_type; -}; - -static struct dmi_onboard_device_info __devinitdata dmi_devices[] = { - { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" }, - { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" }, - { "Hades", DMI_DEV_TYPE_OTHER, 0x73, "fschds" }, -}; - -static void __devinit dmi_check_onboard_device(u8 type, const char *name, - struct i2c_adapter *adap) -{ - int i; - struct i2c_board_info info; - - for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) { - /* & ~0x80, ignore enabled/disabled bit */ - if ((type & ~0x80) != dmi_devices[i].type) - continue; - if (strcasecmp(name, dmi_devices[i].name)) - continue; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = dmi_devices[i].i2c_addr; - strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE); - i2c_new_device(adap, &info); - break; - } -} - -/* We use our own function to check for onboard devices instead of - dmi_find_device() as some buggy BIOS's have the devices we are interested - in marked as disabled */ -static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm, - void *adap) -{ - int i, count; - - if (dm->type != 10) - return; - - count = (dm->length - sizeof(struct dmi_header)) / 2; - for (i = 0; i < count; i++) { - const u8 *d = (char *)(dm + 1) + (i * 2); - const char *name = ((char *) dm) + dm->length; - u8 type = d[0]; - u8 s = d[1]; - - if (!s) - continue; - s--; - while (s > 0 && name[0]) { - name += strlen(name) + 1; - s--; - } - if (name[0] == 0) /* Bogus string reference */ - continue; - - dmi_check_onboard_device(type, name, adap); - } -} - -/* Register optional slaves */ -static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) -{ - /* Only register slaves on main SMBus channel */ - if (priv->features & FEATURE_IDF) - return; - - if (apanel_addr) { - struct i2c_board_info info; - - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = apanel_addr; - strlcpy(info.type, "fujitsu_apanel", I2C_NAME_SIZE); - i2c_new_device(&priv->adapter, &info); - } - - if (dmi_name_in_vendors("FUJITSU")) - dmi_walk(dmi_check_onboard_devices, &priv->adapter); -} -#else -static void __init input_apanel_init(void) {} -static void __devinit i801_probe_optional_slaves(struct i801_priv *priv) {} -#endif /* CONFIG_X86 && CONFIG_DMI */ - -static int __devinit i801_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - unsigned char temp; - int err, i; - struct i801_priv *priv; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - i2c_set_adapdata(&priv->adapter, priv); - priv->adapter.owner = THIS_MODULE; - priv->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - priv->adapter.algo = &smbus_algorithm; - - priv->pci_dev = dev; - switch (dev->device) { - case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0: - case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1: - case PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2: - priv->features |= FEATURE_IDF; - /* fall through */ - default: - priv->features |= FEATURE_I2C_BLOCK_READ; - /* fall through */ - case PCI_DEVICE_ID_INTEL_82801DB_3: - priv->features |= FEATURE_SMBUS_PEC; - priv->features |= FEATURE_BLOCK_BUFFER; - /* fall through */ - case PCI_DEVICE_ID_INTEL_82801CA_3: - case PCI_DEVICE_ID_INTEL_82801BA_2: - case PCI_DEVICE_ID_INTEL_82801AB_3: - case PCI_DEVICE_ID_INTEL_82801AA_3: - break; - } - - /* Disable features on user request */ - for (i = 0; i < ARRAY_SIZE(i801_feature_names); i++) { - if (priv->features & disable_features & (1 << i)) - dev_notice(&dev->dev, "%s disabled by user\n", - i801_feature_names[i]); - } - priv->features &= ~disable_features; - - err = pci_enable_device(dev); - if (err) { - dev_err(&dev->dev, "Failed to enable SMBus PCI device (%d)\n", - err); - goto exit; - } - - /* Determine the address of the SMBus area */ - priv->smba = pci_resource_start(dev, SMBBAR); - if (!priv->smba) { - dev_err(&dev->dev, "SMBus base address uninitialized, " - "upgrade BIOS\n"); - err = -ENODEV; - goto exit; - } - - err = acpi_check_resource_conflict(&dev->resource[SMBBAR]); - if (err) { - err = -ENODEV; - goto exit; - } - - err = pci_request_region(dev, SMBBAR, i801_driver.name); - if (err) { - dev_err(&dev->dev, "Failed to request SMBus region " - "0x%lx-0x%Lx\n", priv->smba, - (unsigned long long)pci_resource_end(dev, SMBBAR)); - goto exit; - } - - pci_read_config_byte(priv->pci_dev, SMBHSTCFG, &temp); - priv->original_hstcfg = temp; - temp &= ~SMBHSTCFG_I2C_EN; /* SMBus timing */ - if (!(temp & SMBHSTCFG_HST_EN)) { - dev_info(&dev->dev, "Enabling SMBus device\n"); - temp |= SMBHSTCFG_HST_EN; - } - pci_write_config_byte(priv->pci_dev, SMBHSTCFG, temp); - - if (temp & SMBHSTCFG_SMB_SMI_EN) - dev_dbg(&dev->dev, "SMBus using interrupt SMI#\n"); - else - dev_dbg(&dev->dev, "SMBus using PCI Interrupt\n"); - - /* Clear special mode bits */ - if (priv->features & (FEATURE_SMBUS_PEC | FEATURE_BLOCK_BUFFER)) - outb_p(inb_p(SMBAUXCTL(priv)) & - ~(SMBAUXCTL_CRC | SMBAUXCTL_E32B), SMBAUXCTL(priv)); - - /* set up the sysfs linkage to our parent device */ - priv->adapter.dev.parent = &dev->dev; - - /* Retry up to 3 times on lost arbitration */ - priv->adapter.retries = 3; - - snprintf(priv->adapter.name, sizeof(priv->adapter.name), - "SMBus I801 adapter at %04lx", priv->smba); - err = i2c_add_adapter(&priv->adapter); - if (err) { - dev_err(&dev->dev, "Failed to add SMBus adapter\n"); - goto exit_release; - } - - i801_probe_optional_slaves(priv); - - pci_set_drvdata(dev, priv); - return 0; - -exit_release: - pci_release_region(dev, SMBBAR); -exit: - kfree(priv); - return err; -} - -static void __devexit i801_remove(struct pci_dev *dev) -{ - struct i801_priv *priv = pci_get_drvdata(dev); - - i2c_del_adapter(&priv->adapter); - pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); - pci_release_region(dev, SMBBAR); - pci_set_drvdata(dev, NULL); - kfree(priv); - /* - * do not call pci_disable_device(dev) since it can cause hard hangs on - * some systems during power-off (eg. Fujitsu-Siemens Lifebook E8010) - */ -} - -#ifdef CONFIG_PM -static int i801_suspend(struct pci_dev *dev, pm_message_t mesg) -{ - struct i801_priv *priv = pci_get_drvdata(dev); - - pci_save_state(dev); - pci_write_config_byte(dev, SMBHSTCFG, priv->original_hstcfg); - pci_set_power_state(dev, pci_choose_state(dev, mesg)); - return 0; -} - -static int i801_resume(struct pci_dev *dev) -{ - pci_set_power_state(dev, PCI_D0); - pci_restore_state(dev); - return pci_enable_device(dev); -} -#else -#define i801_suspend NULL -#define i801_resume NULL -#endif - -static struct pci_driver i801_driver = { - .name = "i801_smbus", - .id_table = i801_ids, - .probe = i801_probe, - .remove = __devexit_p(i801_remove), - .suspend = i801_suspend, - .resume = i801_resume, -}; - -static int __init i2c_i801_init(void) -{ - if (dmi_name_in_vendors("FUJITSU")) - input_apanel_init(); - return pci_register_driver(&i801_driver); -} - -static void __exit i2c_i801_exit(void) -{ - pci_unregister_driver(&i801_driver); -} - -MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>, " - "Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("I801 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_i801_init); -module_exit(i2c_i801_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.c deleted file mode 100644 index 806e225f..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.c +++ /dev/null @@ -1,818 +0,0 @@ -/* - * drivers/i2c/busses/i2c-ibm_iic.c - * - * Support for the IIC peripheral on IBM PPC 4xx - * - * Copyright (c) 2003, 2004 Zultys Technologies. - * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> - * - * Copyright (c) 2008 PIKA Technologies - * Sean MacLennan <smaclennan@pikatech.com> - * - * Based on original work by - * Ian DaSilva <idasilva@mvista.com> - * Armin Kuster <akuster@mvista.com> - * Matt Porter <mporter@mvista.com> - * - * Copyright 2000-2003 MontaVista Software Inc. - * - * Original driver version was highly leveraged from i2c-elektor.c - * - * Copyright 1995-97 Simon G. Vogl - * 1998-99 Hans Berglund - * - * With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> - * and even Frodo Looijaard <frodol@dds.nl> - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <asm/irq.h> -#include <linux/io.h> -#include <linux/i2c.h> -#include <linux/of_platform.h> -#include <linux/of_i2c.h> - -#include "i2c-ibm_iic.h" - -#define DRIVER_VERSION "2.2" - -MODULE_DESCRIPTION("IBM IIC driver v" DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -static bool iic_force_poll; -module_param(iic_force_poll, bool, 0); -MODULE_PARM_DESC(iic_force_poll, "Force polling mode"); - -static bool iic_force_fast; -module_param(iic_force_fast, bool, 0); -MODULE_PARM_DESC(iic_force_fast, "Force fast mode (400 kHz)"); - -#define DBG_LEVEL 0 - -#ifdef DBG -#undef DBG -#endif - -#ifdef DBG2 -#undef DBG2 -#endif - -#if DBG_LEVEL > 0 -# define DBG(f,x...) printk(KERN_DEBUG "ibm-iic" f, ##x) -#else -# define DBG(f,x...) ((void)0) -#endif -#if DBG_LEVEL > 1 -# define DBG2(f,x...) DBG(f, ##x) -#else -# define DBG2(f,x...) ((void)0) -#endif -#if DBG_LEVEL > 2 -static void dump_iic_regs(const char* header, struct ibm_iic_private* dev) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - printk(KERN_DEBUG "ibm-iic%d: %s\n", dev->idx, header); - printk(KERN_DEBUG - " cntl = 0x%02x, mdcntl = 0x%02x\n" - " sts = 0x%02x, extsts = 0x%02x\n" - " clkdiv = 0x%02x, xfrcnt = 0x%02x\n" - " xtcntlss = 0x%02x, directcntl = 0x%02x\n", - in_8(&iic->cntl), in_8(&iic->mdcntl), in_8(&iic->sts), - in_8(&iic->extsts), in_8(&iic->clkdiv), in_8(&iic->xfrcnt), - in_8(&iic->xtcntlss), in_8(&iic->directcntl)); -} -# define DUMP_REGS(h,dev) dump_iic_regs((h),(dev)) -#else -# define DUMP_REGS(h,dev) ((void)0) -#endif - -/* Bus timings (in ns) for bit-banging */ -static struct i2c_timings { - unsigned int hd_sta; - unsigned int su_sto; - unsigned int low; - unsigned int high; - unsigned int buf; -} timings [] = { -/* Standard mode (100 KHz) */ -{ - .hd_sta = 4000, - .su_sto = 4000, - .low = 4700, - .high = 4000, - .buf = 4700, -}, -/* Fast mode (400 KHz) */ -{ - .hd_sta = 600, - .su_sto = 600, - .low = 1300, - .high = 600, - .buf = 1300, -}}; - -/* Enable/disable interrupt generation */ -static inline void iic_interrupt_mode(struct ibm_iic_private* dev, int enable) -{ - out_8(&dev->vaddr->intmsk, enable ? INTRMSK_EIMTC : 0); -} - -/* - * Initialize IIC interface. - */ -static void iic_dev_init(struct ibm_iic_private* dev) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - - DBG("%d: init\n", dev->idx); - - /* Clear master address */ - out_8(&iic->lmadr, 0); - out_8(&iic->hmadr, 0); - - /* Clear slave address */ - out_8(&iic->lsadr, 0); - out_8(&iic->hsadr, 0); - - /* Clear status & extended status */ - out_8(&iic->sts, STS_SCMP | STS_IRQA); - out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | EXTSTS_LA - | EXTSTS_ICT | EXTSTS_XFRA); - - /* Set clock divider */ - out_8(&iic->clkdiv, dev->clckdiv); - - /* Clear transfer count */ - out_8(&iic->xfrcnt, 0); - - /* Clear extended control and status */ - out_8(&iic->xtcntlss, XTCNTLSS_SRC | XTCNTLSS_SRS | XTCNTLSS_SWC - | XTCNTLSS_SWS); - - /* Clear control register */ - out_8(&iic->cntl, 0); - - /* Enable interrupts if possible */ - iic_interrupt_mode(dev, dev->irq >= 0); - - /* Set mode control */ - out_8(&iic->mdcntl, MDCNTL_FMDB | MDCNTL_EINT | MDCNTL_EUBS - | (dev->fast_mode ? MDCNTL_FSM : 0)); - - DUMP_REGS("iic_init", dev); -} - -/* - * Reset IIC interface - */ -static void iic_dev_reset(struct ibm_iic_private* dev) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - int i; - u8 dc; - - DBG("%d: soft reset\n", dev->idx); - DUMP_REGS("reset", dev); - - /* Place chip in the reset state */ - out_8(&iic->xtcntlss, XTCNTLSS_SRST); - - /* Check if bus is free */ - dc = in_8(&iic->directcntl); - if (!DIRCTNL_FREE(dc)){ - DBG("%d: trying to regain bus control\n", dev->idx); - - /* Try to set bus free state */ - out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); - - /* Wait until we regain bus control */ - for (i = 0; i < 100; ++i){ - dc = in_8(&iic->directcntl); - if (DIRCTNL_FREE(dc)) - break; - - /* Toggle SCL line */ - dc ^= DIRCNTL_SCC; - out_8(&iic->directcntl, dc); - udelay(10); - dc ^= DIRCNTL_SCC; - out_8(&iic->directcntl, dc); - - /* be nice */ - cond_resched(); - } - } - - /* Remove reset */ - out_8(&iic->xtcntlss, 0); - - /* Reinitialize interface */ - iic_dev_init(dev); -} - -/* - * Do 0-length transaction using bit-banging through IIC_DIRECTCNTL register. - */ - -/* Wait for SCL and/or SDA to be high */ -static int iic_dc_wait(volatile struct iic_regs __iomem *iic, u8 mask) -{ - unsigned long x = jiffies + HZ / 28 + 2; - while ((in_8(&iic->directcntl) & mask) != mask){ - if (unlikely(time_after(jiffies, x))) - return -1; - cond_resched(); - } - return 0; -} - -static int iic_smbus_quick(struct ibm_iic_private* dev, const struct i2c_msg* p) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - const struct i2c_timings* t = &timings[dev->fast_mode ? 1 : 0]; - u8 mask, v, sda; - int i, res; - - /* Only 7-bit addresses are supported */ - if (unlikely(p->flags & I2C_M_TEN)){ - DBG("%d: smbus_quick - 10 bit addresses are not supported\n", - dev->idx); - return -EINVAL; - } - - DBG("%d: smbus_quick(0x%02x)\n", dev->idx, p->addr); - - /* Reset IIC interface */ - out_8(&iic->xtcntlss, XTCNTLSS_SRST); - - /* Wait for bus to become free */ - out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); - if (unlikely(iic_dc_wait(iic, DIRCNTL_MSDA | DIRCNTL_MSC))) - goto err; - ndelay(t->buf); - - /* START */ - out_8(&iic->directcntl, DIRCNTL_SCC); - sda = 0; - ndelay(t->hd_sta); - - /* Send address */ - v = (u8)((p->addr << 1) | ((p->flags & I2C_M_RD) ? 1 : 0)); - for (i = 0, mask = 0x80; i < 8; ++i, mask >>= 1){ - out_8(&iic->directcntl, sda); - ndelay(t->low / 2); - sda = (v & mask) ? DIRCNTL_SDAC : 0; - out_8(&iic->directcntl, sda); - ndelay(t->low / 2); - - out_8(&iic->directcntl, DIRCNTL_SCC | sda); - if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) - goto err; - ndelay(t->high); - } - - /* ACK */ - out_8(&iic->directcntl, sda); - ndelay(t->low / 2); - out_8(&iic->directcntl, DIRCNTL_SDAC); - ndelay(t->low / 2); - out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); - if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) - goto err; - res = (in_8(&iic->directcntl) & DIRCNTL_MSDA) ? -EREMOTEIO : 1; - ndelay(t->high); - - /* STOP */ - out_8(&iic->directcntl, 0); - ndelay(t->low); - out_8(&iic->directcntl, DIRCNTL_SCC); - if (unlikely(iic_dc_wait(iic, DIRCNTL_MSC))) - goto err; - ndelay(t->su_sto); - out_8(&iic->directcntl, DIRCNTL_SDAC | DIRCNTL_SCC); - - ndelay(t->buf); - - DBG("%d: smbus_quick -> %s\n", dev->idx, res ? "NACK" : "ACK"); -out: - /* Remove reset */ - out_8(&iic->xtcntlss, 0); - - /* Reinitialize interface */ - iic_dev_init(dev); - - return res; -err: - DBG("%d: smbus_quick - bus is stuck\n", dev->idx); - res = -EREMOTEIO; - goto out; -} - -/* - * IIC interrupt handler - */ -static irqreturn_t iic_handler(int irq, void *dev_id) -{ - struct ibm_iic_private* dev = (struct ibm_iic_private*)dev_id; - volatile struct iic_regs __iomem *iic = dev->vaddr; - - DBG2("%d: irq handler, STS = 0x%02x, EXTSTS = 0x%02x\n", - dev->idx, in_8(&iic->sts), in_8(&iic->extsts)); - - /* Acknowledge IRQ and wakeup iic_wait_for_tc */ - out_8(&iic->sts, STS_IRQA | STS_SCMP); - wake_up_interruptible(&dev->wq); - - return IRQ_HANDLED; -} - -/* - * Get master transfer result and clear errors if any. - * Returns the number of actually transferred bytes or error (<0) - */ -static int iic_xfer_result(struct ibm_iic_private* dev) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - - if (unlikely(in_8(&iic->sts) & STS_ERR)){ - DBG("%d: xfer error, EXTSTS = 0x%02x\n", dev->idx, - in_8(&iic->extsts)); - - /* Clear errors and possible pending IRQs */ - out_8(&iic->extsts, EXTSTS_IRQP | EXTSTS_IRQD | - EXTSTS_LA | EXTSTS_ICT | EXTSTS_XFRA); - - /* Flush master data buffer */ - out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); - - /* Is bus free? - * If error happened during combined xfer - * IIC interface is usually stuck in some strange - * state, the only way out - soft reset. - */ - if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ - DBG("%d: bus is stuck, resetting\n", dev->idx); - iic_dev_reset(dev); - } - return -EREMOTEIO; - } - else - return in_8(&iic->xfrcnt) & XFRCNT_MTC_MASK; -} - -/* - * Try to abort active transfer. - */ -static void iic_abort_xfer(struct ibm_iic_private* dev) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - unsigned long x; - - DBG("%d: iic_abort_xfer\n", dev->idx); - - out_8(&iic->cntl, CNTL_HMT); - - /* - * Wait for the abort command to complete. - * It's not worth to be optimized, just poll (timeout >= 1 tick) - */ - x = jiffies + 2; - while ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ - if (time_after(jiffies, x)){ - DBG("%d: abort timeout, resetting...\n", dev->idx); - iic_dev_reset(dev); - return; - } - schedule(); - } - - /* Just to clear errors */ - iic_xfer_result(dev); -} - -/* - * Wait for master transfer to complete. - * It puts current process to sleep until we get interrupt or timeout expires. - * Returns the number of transferred bytes or error (<0) - */ -static int iic_wait_for_tc(struct ibm_iic_private* dev){ - - volatile struct iic_regs __iomem *iic = dev->vaddr; - int ret = 0; - - if (dev->irq >= 0){ - /* Interrupt mode */ - ret = wait_event_interruptible_timeout(dev->wq, - !(in_8(&iic->sts) & STS_PT), dev->adap.timeout); - - if (unlikely(ret < 0)) - DBG("%d: wait interrupted\n", dev->idx); - else if (unlikely(in_8(&iic->sts) & STS_PT)){ - DBG("%d: wait timeout\n", dev->idx); - ret = -ETIMEDOUT; - } - } - else { - /* Polling mode */ - unsigned long x = jiffies + dev->adap.timeout; - - while (in_8(&iic->sts) & STS_PT){ - if (unlikely(time_after(jiffies, x))){ - DBG("%d: poll timeout\n", dev->idx); - ret = -ETIMEDOUT; - break; - } - - if (unlikely(signal_pending(current))){ - DBG("%d: poll interrupted\n", dev->idx); - ret = -ERESTARTSYS; - break; - } - schedule(); - } - } - - if (unlikely(ret < 0)) - iic_abort_xfer(dev); - else - ret = iic_xfer_result(dev); - - DBG2("%d: iic_wait_for_tc -> %d\n", dev->idx, ret); - - return ret; -} - -/* - * Low level master transfer routine - */ -static int iic_xfer_bytes(struct ibm_iic_private* dev, struct i2c_msg* pm, - int combined_xfer) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - char* buf = pm->buf; - int i, j, loops, ret = 0; - int len = pm->len; - - u8 cntl = (in_8(&iic->cntl) & CNTL_AMD) | CNTL_PT; - if (pm->flags & I2C_M_RD) - cntl |= CNTL_RW; - - loops = (len + 3) / 4; - for (i = 0; i < loops; ++i, len -= 4){ - int count = len > 4 ? 4 : len; - u8 cmd = cntl | ((count - 1) << CNTL_TCT_SHIFT); - - if (!(cntl & CNTL_RW)) - for (j = 0; j < count; ++j) - out_8((void __iomem *)&iic->mdbuf, *buf++); - - if (i < loops - 1) - cmd |= CNTL_CHT; - else if (combined_xfer) - cmd |= CNTL_RPST; - - DBG2("%d: xfer_bytes, %d, CNTL = 0x%02x\n", dev->idx, count, cmd); - - /* Start transfer */ - out_8(&iic->cntl, cmd); - - /* Wait for completion */ - ret = iic_wait_for_tc(dev); - - if (unlikely(ret < 0)) - break; - else if (unlikely(ret != count)){ - DBG("%d: xfer_bytes, requested %d, transferred %d\n", - dev->idx, count, ret); - - /* If it's not a last part of xfer, abort it */ - if (combined_xfer || (i < loops - 1)) - iic_abort_xfer(dev); - - ret = -EREMOTEIO; - break; - } - - if (cntl & CNTL_RW) - for (j = 0; j < count; ++j) - *buf++ = in_8((void __iomem *)&iic->mdbuf); - } - - return ret > 0 ? 0 : ret; -} - -/* - * Set target slave address for master transfer - */ -static inline void iic_address(struct ibm_iic_private* dev, struct i2c_msg* msg) -{ - volatile struct iic_regs __iomem *iic = dev->vaddr; - u16 addr = msg->addr; - - DBG2("%d: iic_address, 0x%03x (%d-bit)\n", dev->idx, - addr, msg->flags & I2C_M_TEN ? 10 : 7); - - if (msg->flags & I2C_M_TEN){ - out_8(&iic->cntl, CNTL_AMD); - out_8(&iic->lmadr, addr); - out_8(&iic->hmadr, 0xf0 | ((addr >> 7) & 0x06)); - } - else { - out_8(&iic->cntl, 0); - out_8(&iic->lmadr, addr << 1); - } -} - -static inline int iic_invalid_address(const struct i2c_msg* p) -{ - return (p->addr > 0x3ff) || (!(p->flags & I2C_M_TEN) && (p->addr > 0x7f)); -} - -static inline int iic_address_neq(const struct i2c_msg* p1, - const struct i2c_msg* p2) -{ - return (p1->addr != p2->addr) - || ((p1->flags & I2C_M_TEN) != (p2->flags & I2C_M_TEN)); -} - -/* - * Generic master transfer entrypoint. - * Returns the number of processed messages or error (<0) - */ -static int iic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct ibm_iic_private* dev = (struct ibm_iic_private*)(i2c_get_adapdata(adap)); - volatile struct iic_regs __iomem *iic = dev->vaddr; - int i, ret = 0; - - DBG2("%d: iic_xfer, %d msg(s)\n", dev->idx, num); - - if (!num) - return 0; - - /* Check the sanity of the passed messages. - * Uhh, generic i2c layer is more suitable place for such code... - */ - if (unlikely(iic_invalid_address(&msgs[0]))){ - DBG("%d: invalid address 0x%03x (%d-bit)\n", dev->idx, - msgs[0].addr, msgs[0].flags & I2C_M_TEN ? 10 : 7); - return -EINVAL; - } - for (i = 0; i < num; ++i){ - if (unlikely(msgs[i].len <= 0)){ - if (num == 1 && !msgs[0].len){ - /* Special case for I2C_SMBUS_QUICK emulation. - * IBM IIC doesn't support 0-length transactions - * so we have to emulate them using bit-banging. - */ - return iic_smbus_quick(dev, &msgs[0]); - } - DBG("%d: invalid len %d in msg[%d]\n", dev->idx, - msgs[i].len, i); - return -EINVAL; - } - if (unlikely(iic_address_neq(&msgs[0], &msgs[i]))){ - DBG("%d: invalid addr in msg[%d]\n", dev->idx, i); - return -EINVAL; - } - } - - /* Check bus state */ - if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){ - DBG("%d: iic_xfer, bus is not free\n", dev->idx); - - /* Usually it means something serious has happened. - * We *cannot* have unfinished previous transfer - * so it doesn't make any sense to try to stop it. - * Probably we were not able to recover from the - * previous error. - * The only *reasonable* thing I can think of here - * is soft reset. --ebs - */ - iic_dev_reset(dev); - - if ((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE){ - DBG("%d: iic_xfer, bus is still not free\n", dev->idx); - return -EREMOTEIO; - } - } - else { - /* Flush master data buffer (just in case) */ - out_8(&iic->mdcntl, in_8(&iic->mdcntl) | MDCNTL_FMDB); - } - - /* Load slave address */ - iic_address(dev, &msgs[0]); - - /* Do real transfer */ - for (i = 0; i < num && !ret; ++i) - ret = iic_xfer_bytes(dev, &msgs[i], i < num - 1); - - return ret < 0 ? ret : num; -} - -static u32 iic_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm iic_algo = { - .master_xfer = iic_xfer, - .functionality = iic_func -}; - -/* - * Calculates IICx_CLCKDIV value for a specific OPB clock frequency - */ -static inline u8 iic_clckdiv(unsigned int opb) -{ - /* Compatibility kludge, should go away after all cards - * are fixed to fill correct value for opbfreq. - * Previous driver version used hardcoded divider value 4, - * it corresponds to OPB frequency from the range (40, 50] MHz - */ - if (!opb){ - printk(KERN_WARNING "ibm-iic: using compatibility value for OPB freq," - " fix your board specific setup\n"); - opb = 50000000; - } - - /* Convert to MHz */ - opb /= 1000000; - - if (opb < 20 || opb > 150){ - printk(KERN_WARNING "ibm-iic: invalid OPB clock frequency %u MHz\n", - opb); - opb = opb < 20 ? 20 : 150; - } - return (u8)((opb + 9) / 10 - 1); -} - -static int __devinit iic_request_irq(struct platform_device *ofdev, - struct ibm_iic_private *dev) -{ - struct device_node *np = ofdev->dev.of_node; - int irq; - - if (iic_force_poll) - return 0; - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - dev_err(&ofdev->dev, "irq_of_parse_and_map failed\n"); - return 0; - } - - /* Disable interrupts until we finish initialization, assumes - * level-sensitive IRQ setup... - */ - iic_interrupt_mode(dev, 0); - if (request_irq(irq, iic_handler, 0, "IBM IIC", dev)) { - dev_err(&ofdev->dev, "request_irq %d failed\n", irq); - /* Fallback to the polling mode */ - return 0; - } - - return irq; -} - -/* - * Register single IIC interface - */ -static int __devinit iic_probe(struct platform_device *ofdev) -{ - struct device_node *np = ofdev->dev.of_node; - struct ibm_iic_private *dev; - struct i2c_adapter *adap; - const u32 *freq; - int ret; - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) { - dev_err(&ofdev->dev, "failed to allocate device data\n"); - return -ENOMEM; - } - - dev_set_drvdata(&ofdev->dev, dev); - - dev->vaddr = of_iomap(np, 0); - if (dev->vaddr == NULL) { - dev_err(&ofdev->dev, "failed to iomap device\n"); - ret = -ENXIO; - goto error_cleanup; - } - - init_waitqueue_head(&dev->wq); - - dev->irq = iic_request_irq(ofdev, dev); - if (!dev->irq) - dev_warn(&ofdev->dev, "using polling mode\n"); - - /* Board specific settings */ - if (iic_force_fast || of_get_property(np, "fast-mode", NULL)) - dev->fast_mode = 1; - - freq = of_get_property(np, "clock-frequency", NULL); - if (freq == NULL) { - freq = of_get_property(np->parent, "clock-frequency", NULL); - if (freq == NULL) { - dev_err(&ofdev->dev, "Unable to get bus frequency\n"); - ret = -EINVAL; - goto error_cleanup; - } - } - - dev->clckdiv = iic_clckdiv(*freq); - dev_dbg(&ofdev->dev, "clckdiv = %d\n", dev->clckdiv); - - /* Initialize IIC interface */ - iic_dev_init(dev); - - /* Register it with i2c layer */ - adap = &dev->adap; - adap->dev.parent = &ofdev->dev; - adap->dev.of_node = of_node_get(np); - strlcpy(adap->name, "IBM IIC", sizeof(adap->name)); - i2c_set_adapdata(adap, dev); - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->algo = &iic_algo; - adap->timeout = HZ; - - ret = i2c_add_adapter(adap); - if (ret < 0) { - dev_err(&ofdev->dev, "failed to register i2c adapter\n"); - goto error_cleanup; - } - - dev_info(&ofdev->dev, "using %s mode\n", - dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)"); - - /* Now register all the child nodes */ - of_i2c_register_devices(adap); - - return 0; - -error_cleanup: - if (dev->irq) { - iic_interrupt_mode(dev, 0); - free_irq(dev->irq, dev); - } - - if (dev->vaddr) - iounmap(dev->vaddr); - - dev_set_drvdata(&ofdev->dev, NULL); - kfree(dev); - return ret; -} - -/* - * Cleanup initialized IIC interface - */ -static int __devexit iic_remove(struct platform_device *ofdev) -{ - struct ibm_iic_private *dev = dev_get_drvdata(&ofdev->dev); - - dev_set_drvdata(&ofdev->dev, NULL); - - i2c_del_adapter(&dev->adap); - - if (dev->irq) { - iic_interrupt_mode(dev, 0); - free_irq(dev->irq, dev); - } - - iounmap(dev->vaddr); - kfree(dev); - - return 0; -} - -static const struct of_device_id ibm_iic_match[] = { - { .compatible = "ibm,iic", }, - {} -}; - -static struct platform_driver ibm_iic_driver = { - .driver = { - .name = "ibm-iic", - .owner = THIS_MODULE, - .of_match_table = ibm_iic_match, - }, - .probe = iic_probe, - .remove = __devexit_p(iic_remove), -}; - -module_platform_driver(ibm_iic_driver); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.h b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.h deleted file mode 100644 index fdaa4829..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ibm_iic.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * drivers/i2c/busses/i2c-ibm_iic.h - * - * Support for the IIC peripheral on IBM PPC 4xx - * - * Copyright (c) 2003 Zultys Technologies. - * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net> - * - * Based on original work by - * Ian DaSilva <idasilva@mvista.com> - * Armin Kuster <akuster@mvista.com> - * Matt Porter <mporter@mvista.com> - * - * Copyright 2000-2003 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - */ -#ifndef __I2C_IBM_IIC_H_ -#define __I2C_IBM_IIC_H_ - -#include <linux/i2c.h> - -struct iic_regs { - u16 mdbuf; - u16 sbbuf; - u8 lmadr; - u8 hmadr; - u8 cntl; - u8 mdcntl; - u8 sts; - u8 extsts; - u8 lsadr; - u8 hsadr; - u8 clkdiv; - u8 intmsk; - u8 xfrcnt; - u8 xtcntlss; - u8 directcntl; -}; - -struct ibm_iic_private { - struct i2c_adapter adap; - volatile struct iic_regs __iomem *vaddr; - wait_queue_head_t wq; - int idx; - int irq; - int fast_mode; - u8 clckdiv; -}; - -/* IICx_CNTL register */ -#define CNTL_HMT 0x80 -#define CNTL_AMD 0x40 -#define CNTL_TCT_MASK 0x30 -#define CNTL_TCT_SHIFT 4 -#define CNTL_RPST 0x08 -#define CNTL_CHT 0x04 -#define CNTL_RW 0x02 -#define CNTL_PT 0x01 - -/* IICx_MDCNTL register */ -#define MDCNTL_FSDB 0x80 -#define MDCNTL_FMDB 0x40 -#define MDCNTL_EGC 0x20 -#define MDCNTL_FSM 0x10 -#define MDCNTL_ESM 0x08 -#define MDCNTL_EINT 0x04 -#define MDCNTL_EUBS 0x02 -#define MDCNTL_HSCL 0x01 - -/* IICx_STS register */ -#define STS_SSS 0x80 -#define STS_SLPR 0x40 -#define STS_MDBS 0x20 -#define STS_MDBF 0x10 -#define STS_SCMP 0x08 -#define STS_ERR 0x04 -#define STS_IRQA 0x02 -#define STS_PT 0x01 - -/* IICx_EXTSTS register */ -#define EXTSTS_IRQP 0x80 -#define EXTSTS_BCS_MASK 0x70 -#define EXTSTS_BCS_FREE 0x40 -#define EXTSTS_IRQD 0x08 -#define EXTSTS_LA 0x04 -#define EXTSTS_ICT 0x02 -#define EXTSTS_XFRA 0x01 - -/* IICx_INTRMSK register */ -#define INTRMSK_EIRC 0x80 -#define INTRMSK_EIRS 0x40 -#define INTRMSK_EIWC 0x20 -#define INTRMSK_EIWS 0x10 -#define INTRMSK_EIHE 0x08 -#define INTRMSK_EIIC 0x04 -#define INTRMSK_EITA 0x02 -#define INTRMSK_EIMTC 0x01 - -/* IICx_XFRCNT register */ -#define XFRCNT_MTC_MASK 0x07 - -/* IICx_XTCNTLSS register */ -#define XTCNTLSS_SRC 0x80 -#define XTCNTLSS_SRS 0x40 -#define XTCNTLSS_SWC 0x20 -#define XTCNTLSS_SWS 0x10 -#define XTCNTLSS_SRST 0x01 - -/* IICx_DIRECTCNTL register */ -#define DIRCNTL_SDAC 0x08 -#define DIRCNTL_SCC 0x04 -#define DIRCNTL_MSDA 0x02 -#define DIRCNTL_MSC 0x01 - -/* Check if we really control the I2C bus and bus is free */ -#define DIRCTNL_FREE(v) (((v) & 0x0f) == 0x0f) - -#endif /* __I2C_IBM_IIC_H_ */ diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-imx.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-imx.c deleted file mode 100644 index dfb84b7e..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-imx.c +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright (C) 2002 Motorola GSG-China - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, - * USA. - * - * Author: - * Darius Augulis, Teltonika Inc. - * - * Desc.: - * Implementation of I2C Adapter/Algorithm Driver - * for I2C Bus integrated in Freescale i.MX/MXC processors - * - * Derived from Motorola GSG China I2C example driver - * - * Copyright (C) 2005 Torsten Koschorrek <koschorrek at synertronixx.de - * Copyright (C) 2005 Matthias Blaschke <blaschke at synertronixx.de - * Copyright (C) 2007 RightHand Technologies, Inc. - * Copyright (C) 2008 Darius Augulis <darius.augulis at teltonika.lt> - * - */ - -/** Includes ******************************************************************* -*******************************************************************************/ - -#include <linux/init.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/sched.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_i2c.h> - -#include <mach/irqs.h> -#include <mach/hardware.h> -#include <mach/i2c.h> - -/** Defines ******************************************************************** -*******************************************************************************/ - -/* This will be the driver name the kernel reports */ -#define DRIVER_NAME "imx-i2c" - -/* Default value */ -#define IMX_I2C_BIT_RATE 100000 /* 100kHz */ - -/* IMX I2C registers */ -#define IMX_I2C_IADR 0x00 /* i2c slave address */ -#define IMX_I2C_IFDR 0x04 /* i2c frequency divider */ -#define IMX_I2C_I2CR 0x08 /* i2c control */ -#define IMX_I2C_I2SR 0x0C /* i2c status */ -#define IMX_I2C_I2DR 0x10 /* i2c transfer data */ - -/* Bits of IMX I2C registers */ -#define I2SR_RXAK 0x01 -#define I2SR_IIF 0x02 -#define I2SR_SRW 0x04 -#define I2SR_IAL 0x10 -#define I2SR_IBB 0x20 -#define I2SR_IAAS 0x40 -#define I2SR_ICF 0x80 -#define I2CR_RSTA 0x04 -#define I2CR_TXAK 0x08 -#define I2CR_MTX 0x10 -#define I2CR_MSTA 0x20 -#define I2CR_IIEN 0x40 -#define I2CR_IEN 0x80 - -/** Variables ****************************************************************** -*******************************************************************************/ - -/* - * sorted list of clock divider, register value pairs - * taken from table 26-5, p.26-9, Freescale i.MX - * Integrated Portable System Processor Reference Manual - * Document Number: MC9328MXLRM, Rev. 5.1, 06/2007 - * - * Duplicated divider values removed from list - */ - -static u16 __initdata i2c_clk_div[50][2] = { - { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, - { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, - { 42, 0x03 }, { 44, 0x27 }, { 48, 0x28 }, { 52, 0x05 }, - { 56, 0x29 }, { 60, 0x06 }, { 64, 0x2A }, { 72, 0x2B }, - { 80, 0x2C }, { 88, 0x09 }, { 96, 0x2D }, { 104, 0x0A }, - { 112, 0x2E }, { 128, 0x2F }, { 144, 0x0C }, { 160, 0x30 }, - { 192, 0x31 }, { 224, 0x32 }, { 240, 0x0F }, { 256, 0x33 }, - { 288, 0x10 }, { 320, 0x34 }, { 384, 0x35 }, { 448, 0x36 }, - { 480, 0x13 }, { 512, 0x37 }, { 576, 0x14 }, { 640, 0x38 }, - { 768, 0x39 }, { 896, 0x3A }, { 960, 0x17 }, { 1024, 0x3B }, - { 1152, 0x18 }, { 1280, 0x3C }, { 1536, 0x3D }, { 1792, 0x3E }, - { 1920, 0x1B }, { 2048, 0x3F }, { 2304, 0x1C }, { 2560, 0x1D }, - { 3072, 0x1E }, { 3840, 0x1F } -}; - -struct imx_i2c_struct { - struct i2c_adapter adapter; - struct resource *res; - struct clk *clk; - void __iomem *base; - int irq; - wait_queue_head_t queue; - unsigned long i2csr; - unsigned int disable_delay; - int stopped; - unsigned int ifdr; /* IMX_I2C_IFDR */ -}; - -static const struct of_device_id i2c_imx_dt_ids[] = { - { .compatible = "fsl,imx1-i2c", }, - { /* sentinel */ } -}; - -/** Functions for IMX I2C adapter driver *************************************** -*******************************************************************************/ - -static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy) -{ - unsigned long orig_jiffies = jiffies; - unsigned int temp; - - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - - while (1) { - temp = readb(i2c_imx->base + IMX_I2C_I2SR); - if (for_busy && (temp & I2SR_IBB)) - break; - if (!for_busy && !(temp & I2SR_IBB)) - break; - if (time_after(jiffies, orig_jiffies + msecs_to_jiffies(500))) { - dev_dbg(&i2c_imx->adapter.dev, - "<%s> I2C bus is busy\n", __func__); - return -ETIMEDOUT; - } - schedule(); - } - - return 0; -} - -static int i2c_imx_trx_complete(struct imx_i2c_struct *i2c_imx) -{ - wait_event_timeout(i2c_imx->queue, i2c_imx->i2csr & I2SR_IIF, HZ / 10); - - if (unlikely(!(i2c_imx->i2csr & I2SR_IIF))) { - dev_dbg(&i2c_imx->adapter.dev, "<%s> Timeout\n", __func__); - return -ETIMEDOUT; - } - dev_dbg(&i2c_imx->adapter.dev, "<%s> TRX complete\n", __func__); - i2c_imx->i2csr = 0; - return 0; -} - -static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx) -{ - if (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_RXAK) { - dev_dbg(&i2c_imx->adapter.dev, "<%s> No ACK\n", __func__); - return -EIO; /* No ACK */ - } - - dev_dbg(&i2c_imx->adapter.dev, "<%s> ACK received\n", __func__); - return 0; -} - -static int i2c_imx_start(struct imx_i2c_struct *i2c_imx) -{ - unsigned int temp = 0; - int result; - - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - - clk_prepare_enable(i2c_imx->clk); - writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR); - /* Enable I2C controller */ - writeb(0, i2c_imx->base + IMX_I2C_I2SR); - writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR); - - /* Wait controller to be stable */ - udelay(50); - - /* Start I2C transaction */ - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp |= I2CR_MSTA; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); - if (result) - return result; - i2c_imx->stopped = 0; - - temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - return result; -} - -static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx) -{ - unsigned int temp = 0; - - if (!i2c_imx->stopped) { - /* Stop I2C transaction */ - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - } - if (cpu_is_mx1()) { - /* - * This delay caused by an i.MXL hardware bug. - * If no (or too short) delay, no "STOP" bit will be generated. - */ - udelay(i2c_imx->disable_delay); - } - - if (!i2c_imx->stopped) { - i2c_imx_bus_busy(i2c_imx, 0); - i2c_imx->stopped = 1; - } - - /* Disable I2C controller */ - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - clk_disable_unprepare(i2c_imx->clk); -} - -static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx, - unsigned int rate) -{ - unsigned int i2c_clk_rate; - unsigned int div; - int i; - - /* Divider value calculation */ - i2c_clk_rate = clk_get_rate(i2c_imx->clk); - div = (i2c_clk_rate + rate - 1) / rate; - if (div < i2c_clk_div[0][0]) - i = 0; - else if (div > i2c_clk_div[ARRAY_SIZE(i2c_clk_div) - 1][0]) - i = ARRAY_SIZE(i2c_clk_div) - 1; - else - for (i = 0; i2c_clk_div[i][0] < div; i++); - - /* Store divider value */ - i2c_imx->ifdr = i2c_clk_div[i][1]; - - /* - * There dummy delay is calculated. - * It should be about one I2C clock period long. - * This delay is used in I2C bus disable function - * to fix chip hardware bug. - */ - i2c_imx->disable_delay = (500000U * i2c_clk_div[i][0] - + (i2c_clk_rate / 2) - 1) / (i2c_clk_rate / 2); - - /* dev_dbg() can't be used, because adapter is not yet registered */ -#ifdef CONFIG_I2C_DEBUG_BUS - printk(KERN_DEBUG "I2C: <%s> I2C_CLK=%d, REQ DIV=%d\n", - __func__, i2c_clk_rate, div); - printk(KERN_DEBUG "I2C: <%s> IFDR[IC]=0x%x, REAL DIV=%d\n", - __func__, i2c_clk_div[i][1], i2c_clk_div[i][0]); -#endif -} - -static irqreturn_t i2c_imx_isr(int irq, void *dev_id) -{ - struct imx_i2c_struct *i2c_imx = dev_id; - unsigned int temp; - - temp = readb(i2c_imx->base + IMX_I2C_I2SR); - if (temp & I2SR_IIF) { - /* save status register */ - i2c_imx->i2csr = temp; - temp &= ~I2SR_IIF; - writeb(temp, i2c_imx->base + IMX_I2C_I2SR); - wake_up(&i2c_imx->queue); - return IRQ_HANDLED; - } - - return IRQ_NONE; -} - -static int i2c_imx_write(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) -{ - int i, result; - - dev_dbg(&i2c_imx->adapter.dev, "<%s> write slave address: addr=0x%x\n", - __func__, msgs->addr << 1); - - /* write slave address */ - writeb(msgs->addr << 1, i2c_imx->base + IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); - if (result) - return result; - result = i2c_imx_acked(i2c_imx); - if (result) - return result; - dev_dbg(&i2c_imx->adapter.dev, "<%s> write data\n", __func__); - - /* write data */ - for (i = 0; i < msgs->len; i++) { - dev_dbg(&i2c_imx->adapter.dev, - "<%s> write byte: B%d=0x%X\n", - __func__, i, msgs->buf[i]); - writeb(msgs->buf[i], i2c_imx->base + IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); - if (result) - return result; - result = i2c_imx_acked(i2c_imx); - if (result) - return result; - } - return 0; -} - -static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs) -{ - int i, result; - unsigned int temp; - - dev_dbg(&i2c_imx->adapter.dev, - "<%s> write slave address: addr=0x%x\n", - __func__, (msgs->addr << 1) | 0x01); - - /* write slave address */ - writeb((msgs->addr << 1) | 0x01, i2c_imx->base + IMX_I2C_I2DR); - result = i2c_imx_trx_complete(i2c_imx); - if (result) - return result; - result = i2c_imx_acked(i2c_imx); - if (result) - return result; - - dev_dbg(&i2c_imx->adapter.dev, "<%s> setup bus\n", __func__); - - /* setup bus to read data */ - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp &= ~I2CR_MTX; - if (msgs->len - 1) - temp &= ~I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - readb(i2c_imx->base + IMX_I2C_I2DR); /* dummy read */ - - dev_dbg(&i2c_imx->adapter.dev, "<%s> read data\n", __func__); - - /* read data */ - for (i = 0; i < msgs->len; i++) { - result = i2c_imx_trx_complete(i2c_imx); - if (result) - return result; - if (i == (msgs->len - 1)) { - /* It must generate STOP before read I2DR to prevent - controller from generating another clock cycle */ - dev_dbg(&i2c_imx->adapter.dev, - "<%s> clear MSTA\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp &= ~(I2CR_MSTA | I2CR_MTX); - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - i2c_imx_bus_busy(i2c_imx, 0); - i2c_imx->stopped = 1; - } else if (i == (msgs->len - 2)) { - dev_dbg(&i2c_imx->adapter.dev, - "<%s> set TXAK\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp |= I2CR_TXAK; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - } - msgs->buf[i] = readb(i2c_imx->base + IMX_I2C_I2DR); - dev_dbg(&i2c_imx->adapter.dev, - "<%s> read byte: B%d=0x%X\n", - __func__, i, msgs->buf[i]); - } - return 0; -} - -static int i2c_imx_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, int num) -{ - unsigned int i, temp; - int result; - struct imx_i2c_struct *i2c_imx = i2c_get_adapdata(adapter); - - dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__); - - /* Start I2C transfer */ - result = i2c_imx_start(i2c_imx); - if (result) - goto fail0; - - /* read/write data */ - for (i = 0; i < num; i++) { - if (i) { - dev_dbg(&i2c_imx->adapter.dev, - "<%s> repeated start\n", __func__); - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - temp |= I2CR_RSTA; - writeb(temp, i2c_imx->base + IMX_I2C_I2CR); - result = i2c_imx_bus_busy(i2c_imx, 1); - if (result) - goto fail0; - } - dev_dbg(&i2c_imx->adapter.dev, - "<%s> transfer message: %d\n", __func__, i); - /* write/read data */ -#ifdef CONFIG_I2C_DEBUG_BUS - temp = readb(i2c_imx->base + IMX_I2C_I2CR); - dev_dbg(&i2c_imx->adapter.dev, "<%s> CONTROL: IEN=%d, IIEN=%d, " - "MSTA=%d, MTX=%d, TXAK=%d, RSTA=%d\n", __func__, - (temp & I2CR_IEN ? 1 : 0), (temp & I2CR_IIEN ? 1 : 0), - (temp & I2CR_MSTA ? 1 : 0), (temp & I2CR_MTX ? 1 : 0), - (temp & I2CR_TXAK ? 1 : 0), (temp & I2CR_RSTA ? 1 : 0)); - temp = readb(i2c_imx->base + IMX_I2C_I2SR); - dev_dbg(&i2c_imx->adapter.dev, - "<%s> STATUS: ICF=%d, IAAS=%d, IBB=%d, " - "IAL=%d, SRW=%d, IIF=%d, RXAK=%d\n", __func__, - (temp & I2SR_ICF ? 1 : 0), (temp & I2SR_IAAS ? 1 : 0), - (temp & I2SR_IBB ? 1 : 0), (temp & I2SR_IAL ? 1 : 0), - (temp & I2SR_SRW ? 1 : 0), (temp & I2SR_IIF ? 1 : 0), - (temp & I2SR_RXAK ? 1 : 0)); -#endif - if (msgs[i].flags & I2C_M_RD) - result = i2c_imx_read(i2c_imx, &msgs[i]); - else - result = i2c_imx_write(i2c_imx, &msgs[i]); - if (result) - goto fail0; - } - -fail0: - /* Stop I2C transfer */ - i2c_imx_stop(i2c_imx); - - dev_dbg(&i2c_imx->adapter.dev, "<%s> exit with: %s: %d\n", __func__, - (result < 0) ? "error" : "success msg", - (result < 0) ? result : num); - return (result < 0) ? result : num; -} - -static u32 i2c_imx_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm i2c_imx_algo = { - .master_xfer = i2c_imx_xfer, - .functionality = i2c_imx_func, -}; - -static int __init i2c_imx_probe(struct platform_device *pdev) -{ - struct imx_i2c_struct *i2c_imx; - struct resource *res; - struct imxi2c_platform_data *pdata = pdev->dev.platform_data; - void __iomem *base; - resource_size_t res_size; - int irq, bitrate; - int ret; - - dev_dbg(&pdev->dev, "<%s>\n", __func__); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "can't get device resources\n"); - return -ENOENT; - } - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "can't get irq number\n"); - return -ENOENT; - } - - res_size = resource_size(res); - - if (!request_mem_region(res->start, res_size, DRIVER_NAME)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - return -EBUSY; - } - - base = ioremap(res->start, res_size); - if (!base) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -EIO; - goto fail1; - } - - i2c_imx = kzalloc(sizeof(struct imx_i2c_struct), GFP_KERNEL); - if (!i2c_imx) { - dev_err(&pdev->dev, "can't allocate interface\n"); - ret = -ENOMEM; - goto fail2; - } - - /* Setup i2c_imx driver structure */ - strcpy(i2c_imx->adapter.name, pdev->name); - i2c_imx->adapter.owner = THIS_MODULE; - i2c_imx->adapter.algo = &i2c_imx_algo; - i2c_imx->adapter.dev.parent = &pdev->dev; - i2c_imx->adapter.nr = pdev->id; - i2c_imx->adapter.dev.of_node = pdev->dev.of_node; - i2c_imx->irq = irq; - i2c_imx->base = base; - i2c_imx->res = res; - - /* Get I2C clock */ - i2c_imx->clk = clk_get(&pdev->dev, "i2c_clk"); - if (IS_ERR(i2c_imx->clk)) { - ret = PTR_ERR(i2c_imx->clk); - dev_err(&pdev->dev, "can't get I2C clock\n"); - goto fail3; - } - - /* Request IRQ */ - ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx); - if (ret) { - dev_err(&pdev->dev, "can't claim irq %d\n", i2c_imx->irq); - goto fail4; - } - - /* Init queue */ - init_waitqueue_head(&i2c_imx->queue); - - /* Set up adapter data */ - i2c_set_adapdata(&i2c_imx->adapter, i2c_imx); - - /* Set up clock divider */ - bitrate = IMX_I2C_BIT_RATE; - ret = of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &bitrate); - if (ret < 0 && pdata && pdata->bitrate) - bitrate = pdata->bitrate; - i2c_imx_set_clk(i2c_imx, bitrate); - - /* Set up chip registers to defaults */ - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); - - /* Add I2C adapter */ - ret = i2c_add_numbered_adapter(&i2c_imx->adapter); - if (ret < 0) { - dev_err(&pdev->dev, "registration failed\n"); - goto fail5; - } - - of_i2c_register_devices(&i2c_imx->adapter); - - /* Set up platform driver data */ - platform_set_drvdata(pdev, i2c_imx); - - dev_dbg(&i2c_imx->adapter.dev, "claimed irq %d\n", i2c_imx->irq); - dev_dbg(&i2c_imx->adapter.dev, "device resources from 0x%x to 0x%x\n", - i2c_imx->res->start, i2c_imx->res->end); - dev_dbg(&i2c_imx->adapter.dev, "allocated %d bytes at 0x%x \n", - res_size, i2c_imx->res->start); - dev_dbg(&i2c_imx->adapter.dev, "adapter name: \"%s\"\n", - i2c_imx->adapter.name); - dev_dbg(&i2c_imx->adapter.dev, "IMX I2C adapter registered\n"); - - return 0; /* Return OK */ - -fail5: - free_irq(i2c_imx->irq, i2c_imx); -fail4: - clk_put(i2c_imx->clk); -fail3: - kfree(i2c_imx); -fail2: - iounmap(base); -fail1: - release_mem_region(res->start, resource_size(res)); - return ret; /* Return error number */ -} - -static int __exit i2c_imx_remove(struct platform_device *pdev) -{ - struct imx_i2c_struct *i2c_imx = platform_get_drvdata(pdev); - - /* remove adapter */ - dev_dbg(&i2c_imx->adapter.dev, "adapter removed\n"); - i2c_del_adapter(&i2c_imx->adapter); - platform_set_drvdata(pdev, NULL); - - /* free interrupt */ - free_irq(i2c_imx->irq, i2c_imx); - - /* setup chip registers to defaults */ - writeb(0, i2c_imx->base + IMX_I2C_IADR); - writeb(0, i2c_imx->base + IMX_I2C_IFDR); - writeb(0, i2c_imx->base + IMX_I2C_I2CR); - writeb(0, i2c_imx->base + IMX_I2C_I2SR); - - clk_put(i2c_imx->clk); - - iounmap(i2c_imx->base); - release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res)); - kfree(i2c_imx); - return 0; -} - -static struct platform_driver i2c_imx_driver = { - .remove = __exit_p(i2c_imx_remove), - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - .of_match_table = i2c_imx_dt_ids, - } -}; - -static int __init i2c_adap_imx_init(void) -{ - return platform_driver_probe(&i2c_imx_driver, i2c_imx_probe); -} -subsys_initcall(i2c_adap_imx_init); - -static void __exit i2c_adap_imx_exit(void) -{ - platform_driver_unregister(&i2c_imx_driver); -} -module_exit(i2c_adap_imx_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Darius Augulis"); -MODULE_DESCRIPTION("I2C adapter driver for IMX I2C bus"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-intel-mid.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-intel-mid.c deleted file mode 100644 index 365bad5b..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-intel-mid.c +++ /dev/null @@ -1,1135 +0,0 @@ -/* - * Support for Moorestown/Medfield I2C chip - * - * Copyright (c) 2009 Intel Corporation. - * Copyright (c) 2009 Synopsys. Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, version - * 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT ANY - * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more - * details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/stat.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/pci.h> -#include <linux/interrupt.h> -#include <linux/pm_runtime.h> -#include <linux/io.h> - -#define DRIVER_NAME "i2c-intel-mid" -#define VERSION "Version 0.5ac2" -#define PLATFORM "Moorestown/Medfield" - -/* Tables use: 0 Moorestown, 1 Medfield */ -#define NUM_PLATFORMS 2 -enum platform_enum { - MOORESTOWN = 0, - MEDFIELD = 1, -}; - -enum mid_i2c_status { - STATUS_IDLE = 0, - STATUS_READ_START, - STATUS_READ_IN_PROGRESS, - STATUS_READ_SUCCESS, - STATUS_WRITE_START, - STATUS_WRITE_SUCCESS, - STATUS_XFER_ABORT, - STATUS_STANDBY -}; - -/** - * struct intel_mid_i2c_private - per device I²C context - * @adap: core i2c layer adapter information - * @dev: device reference for power management - * @base: register base - * @speed: speed mode for this port - * @complete: completion object for transaction wait - * @abort: reason for last abort - * @rx_buf: pointer into working receive buffer - * @rx_buf_len: receive buffer length - * @status: adapter state machine - * @msg: the message we are currently processing - * @platform: the MID device type we are part of - * @lock: transaction serialization - * - * We allocate one of these per device we discover, it holds the core - * i2c layer objects and the data we need to track privately. - */ -struct intel_mid_i2c_private { - struct i2c_adapter adap; - struct device *dev; - void __iomem *base; - int speed; - struct completion complete; - int abort; - u8 *rx_buf; - int rx_buf_len; - enum mid_i2c_status status; - struct i2c_msg *msg; - enum platform_enum platform; - struct mutex lock; -}; - -#define NUM_SPEEDS 3 - -#define ACTIVE 0 -#define STANDBY 1 - - -/* Control register */ -#define IC_CON 0x00 -#define SLV_DIS (1 << 6) /* Disable slave mode */ -#define RESTART (1 << 5) /* Send a Restart condition */ -#define ADDR_10BIT (1 << 4) /* 10-bit addressing */ -#define STANDARD_MODE (1 << 1) /* standard mode */ -#define FAST_MODE (2 << 1) /* fast mode */ -#define HIGH_MODE (3 << 1) /* high speed mode */ -#define MASTER_EN (1 << 0) /* Master mode */ - -/* Target address register */ -#define IC_TAR 0x04 -#define IC_TAR_10BIT_ADDR (1 << 12) /* 10-bit addressing */ -#define IC_TAR_SPECIAL (1 << 11) /* Perform special I2C cmd */ -#define IC_TAR_GC_OR_START (1 << 10) /* 0: Gerneral Call Address */ - /* 1: START BYTE */ -/* Slave Address Register */ -#define IC_SAR 0x08 /* Not used in Master mode */ - -/* High Speed Master Mode Code Address Register */ -#define IC_HS_MADDR 0x0c - -/* Rx/Tx Data Buffer and Command Register */ -#define IC_DATA_CMD 0x10 -#define IC_RD (1 << 8) /* 1: Read 0: Write */ - -/* Standard Speed Clock SCL High Count Register */ -#define IC_SS_SCL_HCNT 0x14 - -/* Standard Speed Clock SCL Low Count Register */ -#define IC_SS_SCL_LCNT 0x18 - -/* Fast Speed Clock SCL High Count Register */ -#define IC_FS_SCL_HCNT 0x1c - -/* Fast Spedd Clock SCL Low Count Register */ -#define IC_FS_SCL_LCNT 0x20 - -/* High Speed Clock SCL High Count Register */ -#define IC_HS_SCL_HCNT 0x24 - -/* High Speed Clock SCL Low Count Register */ -#define IC_HS_SCL_LCNT 0x28 - -/* Interrupt Status Register */ -#define IC_INTR_STAT 0x2c /* Read only */ -#define R_GEN_CALL (1 << 11) -#define R_START_DET (1 << 10) -#define R_STOP_DET (1 << 9) -#define R_ACTIVITY (1 << 8) -#define R_RX_DONE (1 << 7) -#define R_TX_ABRT (1 << 6) -#define R_RD_REQ (1 << 5) -#define R_TX_EMPTY (1 << 4) -#define R_TX_OVER (1 << 3) -#define R_RX_FULL (1 << 2) -#define R_RX_OVER (1 << 1) -#define R_RX_UNDER (1 << 0) - -/* Interrupt Mask Register */ -#define IC_INTR_MASK 0x30 /* Read and Write */ -#define M_GEN_CALL (1 << 11) -#define M_START_DET (1 << 10) -#define M_STOP_DET (1 << 9) -#define M_ACTIVITY (1 << 8) -#define M_RX_DONE (1 << 7) -#define M_TX_ABRT (1 << 6) -#define M_RD_REQ (1 << 5) -#define M_TX_EMPTY (1 << 4) -#define M_TX_OVER (1 << 3) -#define M_RX_FULL (1 << 2) -#define M_RX_OVER (1 << 1) -#define M_RX_UNDER (1 << 0) - -/* Raw Interrupt Status Register */ -#define IC_RAW_INTR_STAT 0x34 /* Read Only */ -#define GEN_CALL (1 << 11) /* General call */ -#define START_DET (1 << 10) /* (RE)START occurred */ -#define STOP_DET (1 << 9) /* STOP occurred */ -#define ACTIVITY (1 << 8) /* Bus busy */ -#define RX_DONE (1 << 7) /* Not used in Master mode */ -#define TX_ABRT (1 << 6) /* Transmit Abort */ -#define RD_REQ (1 << 5) /* Not used in Master mode */ -#define TX_EMPTY (1 << 4) /* TX FIFO <= threshold */ -#define TX_OVER (1 << 3) /* TX FIFO overflow */ -#define RX_FULL (1 << 2) /* RX FIFO >= threshold */ -#define RX_OVER (1 << 1) /* RX FIFO overflow */ -#define RX_UNDER (1 << 0) /* RX FIFO empty */ - -/* Receive FIFO Threshold Register */ -#define IC_RX_TL 0x38 - -/* Transmit FIFO Treshold Register */ -#define IC_TX_TL 0x3c - -/* Clear Combined and Individual Interrupt Register */ -#define IC_CLR_INTR 0x40 -#define CLR_INTR (1 << 0) - -/* Clear RX_UNDER Interrupt Register */ -#define IC_CLR_RX_UNDER 0x44 -#define CLR_RX_UNDER (1 << 0) - -/* Clear RX_OVER Interrupt Register */ -#define IC_CLR_RX_OVER 0x48 -#define CLR_RX_OVER (1 << 0) - -/* Clear TX_OVER Interrupt Register */ -#define IC_CLR_TX_OVER 0x4c -#define CLR_TX_OVER (1 << 0) - -#define IC_CLR_RD_REQ 0x50 - -/* Clear TX_ABRT Interrupt Register */ -#define IC_CLR_TX_ABRT 0x54 -#define CLR_TX_ABRT (1 << 0) -#define IC_CLR_RX_DONE 0x58 - -/* Clear ACTIVITY Interrupt Register */ -#define IC_CLR_ACTIVITY 0x5c -#define CLR_ACTIVITY (1 << 0) - -/* Clear STOP_DET Interrupt Register */ -#define IC_CLR_STOP_DET 0x60 -#define CLR_STOP_DET (1 << 0) - -/* Clear START_DET Interrupt Register */ -#define IC_CLR_START_DET 0x64 -#define CLR_START_DET (1 << 0) - -/* Clear GEN_CALL Interrupt Register */ -#define IC_CLR_GEN_CALL 0x68 -#define CLR_GEN_CALL (1 << 0) - -/* Enable Register */ -#define IC_ENABLE 0x6c -#define ENABLE (1 << 0) - -/* Status Register */ -#define IC_STATUS 0x70 /* Read Only */ -#define STAT_SLV_ACTIVITY (1 << 6) /* Slave not in idle */ -#define STAT_MST_ACTIVITY (1 << 5) /* Master not in idle */ -#define STAT_RFF (1 << 4) /* RX FIFO Full */ -#define STAT_RFNE (1 << 3) /* RX FIFO Not Empty */ -#define STAT_TFE (1 << 2) /* TX FIFO Empty */ -#define STAT_TFNF (1 << 1) /* TX FIFO Not Full */ -#define STAT_ACTIVITY (1 << 0) /* Activity Status */ - -/* Transmit FIFO Level Register */ -#define IC_TXFLR 0x74 /* Read Only */ -#define TXFLR (1 << 0) /* TX FIFO level */ - -/* Receive FIFO Level Register */ -#define IC_RXFLR 0x78 /* Read Only */ -#define RXFLR (1 << 0) /* RX FIFO level */ - -/* Transmit Abort Source Register */ -#define IC_TX_ABRT_SOURCE 0x80 -#define ABRT_SLVRD_INTX (1 << 15) -#define ABRT_SLV_ARBLOST (1 << 14) -#define ABRT_SLVFLUSH_TXFIFO (1 << 13) -#define ARB_LOST (1 << 12) -#define ABRT_MASTER_DIS (1 << 11) -#define ABRT_10B_RD_NORSTRT (1 << 10) -#define ABRT_SBYTE_NORSTRT (1 << 9) -#define ABRT_HS_NORSTRT (1 << 8) -#define ABRT_SBYTE_ACKDET (1 << 7) -#define ABRT_HS_ACKDET (1 << 6) -#define ABRT_GCALL_READ (1 << 5) -#define ABRT_GCALL_NOACK (1 << 4) -#define ABRT_TXDATA_NOACK (1 << 3) -#define ABRT_10ADDR2_NOACK (1 << 2) -#define ABRT_10ADDR1_NOACK (1 << 1) -#define ABRT_7B_ADDR_NOACK (1 << 0) - -/* Enable Status Register */ -#define IC_ENABLE_STATUS 0x9c -#define IC_EN (1 << 0) /* I2C in an enabled state */ - -/* Component Parameter Register 1*/ -#define IC_COMP_PARAM_1 0xf4 -#define APB_DATA_WIDTH (0x3 << 0) - -/* added by xiaolin --begin */ -#define SS_MIN_SCL_HIGH 4000 -#define SS_MIN_SCL_LOW 4700 -#define FS_MIN_SCL_HIGH 600 -#define FS_MIN_SCL_LOW 1300 -#define HS_MIN_SCL_HIGH_100PF 60 -#define HS_MIN_SCL_LOW_100PF 120 - -#define STANDARD 0 -#define FAST 1 -#define HIGH 2 - -#define NUM_SPEEDS 3 - -static int speed_mode[6] = { - FAST, - FAST, - FAST, - STANDARD, - FAST, - FAST -}; - -static int ctl_num = 6; -module_param_array(speed_mode, int, &ctl_num, S_IRUGO); -MODULE_PARM_DESC(speed_mode, "Set the speed of the i2c interface (0-2)"); - -/** - * intel_mid_i2c_disable - Disable I2C controller - * @adap: struct pointer to i2c_adapter - * - * Return Value: - * 0 success - * -EBUSY if device is busy - * -ETIMEDOUT if i2c cannot be disabled within the given time - * - * I2C bus state should be checked prior to disabling the hardware. If bus is - * not in idle state, an errno is returned. Write "0" to IC_ENABLE to disable - * I2C controller. - */ -static int intel_mid_i2c_disable(struct i2c_adapter *adap) -{ - struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); - int err = 0; - int count = 0; - int ret1, ret2; - static const u16 delay[NUM_SPEEDS] = {100, 25, 3}; - - /* Set IC_ENABLE to 0 */ - writel(0, i2c->base + IC_ENABLE); - - /* Check if device is busy */ - dev_dbg(&adap->dev, "mrst i2c disable\n"); - while ((ret1 = readl(i2c->base + IC_ENABLE_STATUS) & 0x1) - || (ret2 = readl(i2c->base + IC_STATUS) & 0x1)) { - udelay(delay[i2c->speed]); - writel(0, i2c->base + IC_ENABLE); - dev_dbg(&adap->dev, "i2c is busy, count is %d speed %d\n", - count, i2c->speed); - if (count++ > 10) { - err = -ETIMEDOUT; - break; - } - } - - /* Clear all interrupts */ - readl(i2c->base + IC_CLR_INTR); - readl(i2c->base + IC_CLR_STOP_DET); - readl(i2c->base + IC_CLR_START_DET); - readl(i2c->base + IC_CLR_ACTIVITY); - readl(i2c->base + IC_CLR_TX_ABRT); - readl(i2c->base + IC_CLR_RX_OVER); - readl(i2c->base + IC_CLR_RX_UNDER); - readl(i2c->base + IC_CLR_TX_OVER); - readl(i2c->base + IC_CLR_RX_DONE); - readl(i2c->base + IC_CLR_GEN_CALL); - - /* Disable all interupts */ - writel(0x0000, i2c->base + IC_INTR_MASK); - - return err; -} - -/** - * intel_mid_i2c_hwinit - Initialize the I2C hardware registers - * @dev: pci device struct pointer - * - * This function will be called in intel_mid_i2c_probe() before device - * registration. - * - * Return Values: - * 0 success - * -EBUSY i2c cannot be disabled - * -ETIMEDOUT i2c cannot be disabled - * -EFAULT If APB data width is not 32-bit wide - * - * I2C should be disabled prior to other register operation. If failed, an - * errno is returned. Mask and Clear all interrpts, this should be done at - * first. Set common registers which will not be modified during normal - * transfers, including: control register, FIFO threshold and clock freq. - * Check APB data width at last. - */ -static int intel_mid_i2c_hwinit(struct intel_mid_i2c_private *i2c) -{ - int err; - - static const u16 hcnt[NUM_PLATFORMS][NUM_SPEEDS] = { - { 0x75, 0x15, 0x07 }, - { 0x04c, 0x10, 0x06 } - }; - static const u16 lcnt[NUM_PLATFORMS][NUM_SPEEDS] = { - { 0x7C, 0x21, 0x0E }, - { 0x053, 0x19, 0x0F } - }; - - /* Disable i2c first */ - err = intel_mid_i2c_disable(&i2c->adap); - if (err) - return err; - - /* - * Setup clock frequency and speed mode - * Enable restart condition, - * enable master FSM, disable slave FSM, - * use target address when initiating transfer - */ - - writel((i2c->speed + 1) << 1 | SLV_DIS | RESTART | MASTER_EN, - i2c->base + IC_CON); - writel(hcnt[i2c->platform][i2c->speed], - i2c->base + (IC_SS_SCL_HCNT + (i2c->speed << 3))); - writel(lcnt[i2c->platform][i2c->speed], - i2c->base + (IC_SS_SCL_LCNT + (i2c->speed << 3))); - - /* Set tranmit & receive FIFO threshold to zero */ - writel(0x0, i2c->base + IC_RX_TL); - writel(0x0, i2c->base + IC_TX_TL); - - return 0; -} - -/** - * intel_mid_i2c_func - Return the supported three I2C operations. - * @adapter: i2c_adapter struct pointer - */ -static u32 intel_mid_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; -} - -/** - * intel_mid_i2c_address_neq - To check if the addresses for different i2c messages - * are equal. - * @p1: first i2c_msg - * @p2: second i2c_msg - * - * Return Values: - * 0 if addresses are equal - * 1 if not equal - * - * Within a single transfer, the I2C client may need to send its address more - * than once. So a check if the addresses match is needed. - */ -static inline bool intel_mid_i2c_address_neq(const struct i2c_msg *p1, - const struct i2c_msg *p2) -{ - if (p1->addr != p2->addr) - return 1; - if ((p1->flags ^ p2->flags) & I2C_M_TEN) - return 1; - return 0; -} - -/** - * intel_mid_i2c_abort - To handle transfer abortions and print error messages. - * @adap: i2c_adapter struct pointer - * - * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be - * distingushed. At present, no circumstances have been found out that - * multiple errors would be occurred simutaneously, so we simply use the - * register value directly. - * - * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need - * a few extra steps) - */ -static void intel_mid_i2c_abort(struct intel_mid_i2c_private *i2c) -{ - /* Read about source register */ - int abort = i2c->abort; - struct i2c_adapter *adap = &i2c->adap; - - /* Single transfer error check: - * According to databook, TX/RX FIFOs would be flushed when - * the abort interrupt occurred. - */ - if (abort & ABRT_MASTER_DIS) - dev_err(&adap->dev, - "initiate master operation with master mode disabled.\n"); - if (abort & ABRT_10B_RD_NORSTRT) - dev_err(&adap->dev, - "RESTART disabled and master sent READ cmd in 10-bit addressing.\n"); - - if (abort & ABRT_SBYTE_NORSTRT) { - dev_err(&adap->dev, - "RESTART disabled and user is trying to send START byte.\n"); - writel(~ABRT_SBYTE_NORSTRT, i2c->base + IC_TX_ABRT_SOURCE); - writel(RESTART, i2c->base + IC_CON); - writel(~IC_TAR_SPECIAL, i2c->base + IC_TAR); - } - - if (abort & ABRT_SBYTE_ACKDET) - dev_err(&adap->dev, - "START byte was not acknowledged.\n"); - if (abort & ABRT_TXDATA_NOACK) - dev_dbg(&adap->dev, - "No acknowledgement received from slave.\n"); - if (abort & ABRT_10ADDR2_NOACK) - dev_dbg(&adap->dev, - "The 2nd address byte of the 10-bit address was not acknowledged.\n"); - if (abort & ABRT_10ADDR1_NOACK) - dev_dbg(&adap->dev, - "The 1st address byte of 10-bit address was not acknowledged.\n"); - if (abort & ABRT_7B_ADDR_NOACK) - dev_dbg(&adap->dev, - "I2C slave device not acknowledged.\n"); - - /* Clear TX_ABRT bit */ - readl(i2c->base + IC_CLR_TX_ABRT); - i2c->status = STATUS_XFER_ABORT; -} - -/** - * xfer_read - Internal function to implement master read transfer. - * @adap: i2c_adapter struct pointer - * @buf: buffer in i2c_msg - * @length: number of bytes to be read - * - * Return Values: - * 0 if the read transfer succeeds - * -ETIMEDOUT if cannot read the "raw" interrupt register - * -EINVAL if a transfer abort occurred - * - * For every byte, a "READ" command will be loaded into IC_DATA_CMD prior to - * data transfer. The actual "read" operation will be performed if an RX_FULL - * interrupt occurred. - * - * Note there may be two interrupt signals captured, one should read - * IC_RAW_INTR_STAT to separate between errors and actual data. - */ -static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); - int i = length; - int err; - - if (length >= 256) { - dev_err(&adap->dev, - "I2C FIFO cannot support larger than 256 bytes\n"); - return -EMSGSIZE; - } - - INIT_COMPLETION(i2c->complete); - - readl(i2c->base + IC_CLR_INTR); - writel(0x0044, i2c->base + IC_INTR_MASK); - - i2c->status = STATUS_READ_START; - - while (i--) - writel(IC_RD, i2c->base + IC_DATA_CMD); - - i2c->status = STATUS_READ_START; - err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ); - if (!err) { - dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n"); - intel_mid_i2c_hwinit(i2c); - return -ETIMEDOUT; - } - if (i2c->status == STATUS_READ_SUCCESS) - return 0; - else - return -EIO; -} - -/** - * xfer_write - Internal function to implement master write transfer. - * @adap: i2c_adapter struct pointer - * @buf: buffer in i2c_msg - * @length: number of bytes to be read - * - * Return Values: - * 0 if the read transfer succeeds - * -ETIMEDOUT if we cannot read the "raw" interrupt register - * -EINVAL if a transfer abort occurred - * - * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to - * data transfer. The actual "write" operation will be performed when the - * RX_FULL interrupt signal occurs. - * - * Note there may be two interrupt signals captured, one should read - * IC_RAW_INTR_STAT to separate between errors and actual data. - */ -static int xfer_write(struct i2c_adapter *adap, - unsigned char *buf, int length) -{ - struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); - int i, err; - - if (length >= 256) { - dev_err(&adap->dev, - "I2C FIFO cannot support larger than 256 bytes\n"); - return -EMSGSIZE; - } - - INIT_COMPLETION(i2c->complete); - - readl(i2c->base + IC_CLR_INTR); - writel(0x0050, i2c->base + IC_INTR_MASK); - - i2c->status = STATUS_WRITE_START; - for (i = 0; i < length; i++) - writel((u16)(*(buf + i)), i2c->base + IC_DATA_CMD); - - i2c->status = STATUS_WRITE_START; - err = wait_for_completion_interruptible_timeout(&i2c->complete, HZ); - if (!err) { - dev_err(&adap->dev, "Timeout for ACK from I2C slave device\n"); - intel_mid_i2c_hwinit(i2c); - return -ETIMEDOUT; - } else { - if (i2c->status == STATUS_WRITE_SUCCESS) - return 0; - else - return -EIO; - } -} - -static int intel_mid_i2c_setup(struct i2c_adapter *adap, struct i2c_msg *pmsg) -{ - struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); - int err; - u32 reg; - u32 bit_mask; - u32 mode; - - /* Disable device first */ - err = intel_mid_i2c_disable(adap); - if (err) { - dev_err(&adap->dev, - "Cannot disable i2c controller, timeout\n"); - return err; - } - - mode = (1 + i2c->speed) << 1; - /* set the speed mode */ - reg = readl(i2c->base + IC_CON); - if ((reg & 0x06) != mode) { - dev_dbg(&adap->dev, "set mode %d\n", i2c->speed); - writel((reg & ~0x6) | mode, i2c->base + IC_CON); - } - - reg = readl(i2c->base + IC_CON); - /* use 7-bit addressing */ - if (pmsg->flags & I2C_M_TEN) { - if ((reg & ADDR_10BIT) != ADDR_10BIT) { - dev_dbg(&adap->dev, "set i2c 10 bit address mode\n"); - writel(reg | ADDR_10BIT, i2c->base + IC_CON); - } - } else { - if ((reg & ADDR_10BIT) != 0x0) { - dev_dbg(&adap->dev, "set i2c 7 bit address mode\n"); - writel(reg & ~ADDR_10BIT, i2c->base + IC_CON); - } - } - /* enable restart conditions */ - reg = readl(i2c->base + IC_CON); - if ((reg & RESTART) != RESTART) { - dev_dbg(&adap->dev, "enable restart conditions\n"); - writel(reg | RESTART, i2c->base + IC_CON); - } - - /* enable master FSM */ - reg = readl(i2c->base + IC_CON); - dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg); - writel(reg | MASTER_EN, i2c->base + IC_CON); - if ((reg & SLV_DIS) != SLV_DIS) { - dev_dbg(&adap->dev, "enable master FSM\n"); - writel(reg | SLV_DIS, i2c->base + IC_CON); - dev_dbg(&adap->dev, "ic_con reg is 0x%x\n", reg); - } - - /* use target address when initiating transfer */ - reg = readl(i2c->base + IC_TAR); - bit_mask = IC_TAR_SPECIAL | IC_TAR_GC_OR_START; - - if ((reg & bit_mask) != 0x0) { - dev_dbg(&adap->dev, - "WR: use target address when intiating transfer, i2c_tx_target\n"); - writel(reg & ~bit_mask, i2c->base + IC_TAR); - } - - /* set target address to the I2C slave address */ - dev_dbg(&adap->dev, - "set target address to the I2C slave address, addr is %x\n", - pmsg->addr); - writel(pmsg->addr | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0), - i2c->base + IC_TAR); - - /* Enable I2C controller */ - writel(ENABLE, i2c->base + IC_ENABLE); - - return 0; -} - -/** - * intel_mid_i2c_xfer - Main master transfer routine. - * @adap: i2c_adapter struct pointer - * @pmsg: i2c_msg struct pointer - * @num: number of i2c_msg - * - * Return Values: - * + number of messages transferred - * -ETIMEDOUT If cannot disable I2C controller or read IC_STATUS - * -EINVAL If the address in i2c_msg is invalid - * - * This function will be registered in i2c-core and exposed to external - * I2C clients. - * 1. Disable I2C controller - * 2. Unmask three interrupts: RX_FULL, TX_EMPTY, TX_ABRT - * 3. Check if address in i2c_msg is valid - * 4. Enable I2C controller - * 5. Perform real transfer (call xfer_read or xfer_write) - * 6. Wait until the current transfer is finished (check bus state) - * 7. Mask and clear all interrupts - */ -static int intel_mid_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *pmsg, - int num) -{ - struct intel_mid_i2c_private *i2c = i2c_get_adapdata(adap); - int i, err = 0; - - /* if number of messages equal 0*/ - if (num == 0) - return 0; - - pm_runtime_get(i2c->dev); - - mutex_lock(&i2c->lock); - dev_dbg(&adap->dev, "intel_mid_i2c_xfer, process %d msg(s)\n", num); - dev_dbg(&adap->dev, "slave address is %x\n", pmsg->addr); - - - if (i2c->status != STATUS_IDLE) { - dev_err(&adap->dev, "Adapter %d in transfer/standby\n", - adap->nr); - mutex_unlock(&i2c->lock); - pm_runtime_put(i2c->dev); - return -1; - } - - - for (i = 1; i < num; i++) { - /* Message address equal? */ - if (unlikely(intel_mid_i2c_address_neq(&pmsg[0], &pmsg[i]))) { - dev_err(&adap->dev, "Invalid address in msg[%d]\n", i); - mutex_unlock(&i2c->lock); - pm_runtime_put(i2c->dev); - return -EINVAL; - } - } - - if (intel_mid_i2c_setup(adap, pmsg)) { - mutex_unlock(&i2c->lock); - pm_runtime_put(i2c->dev); - return -EINVAL; - } - - for (i = 0; i < num; i++) { - i2c->msg = pmsg; - i2c->status = STATUS_IDLE; - /* Read or Write */ - if (pmsg->flags & I2C_M_RD) { - dev_dbg(&adap->dev, "I2C_M_RD\n"); - err = xfer_read(adap, pmsg->buf, pmsg->len); - } else { - dev_dbg(&adap->dev, "I2C_M_WR\n"); - err = xfer_write(adap, pmsg->buf, pmsg->len); - } - if (err < 0) - break; - dev_dbg(&adap->dev, "msg[%d] transfer complete\n", i); - pmsg++; /* next message */ - } - - /* Mask interrupts */ - writel(0x0000, i2c->base + IC_INTR_MASK); - /* Clear all interrupts */ - readl(i2c->base + IC_CLR_INTR); - - i2c->status = STATUS_IDLE; - mutex_unlock(&i2c->lock); - pm_runtime_put(i2c->dev); - - return err; -} - -static int intel_mid_i2c_runtime_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev); - struct i2c_adapter *adap = to_i2c_adapter(dev); - int err; - - if (i2c->status != STATUS_IDLE) - return -1; - - intel_mid_i2c_disable(adap); - - err = pci_save_state(pdev); - if (err) { - dev_err(dev, "pci_save_state failed\n"); - return err; - } - - err = pci_set_power_state(pdev, PCI_D3hot); - if (err) { - dev_err(dev, "pci_set_power_state failed\n"); - return err; - } - i2c->status = STATUS_STANDBY; - - return 0; -} - -static int intel_mid_i2c_runtime_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct intel_mid_i2c_private *i2c = pci_get_drvdata(pdev); - int err; - - if (i2c->status != STATUS_STANDBY) - return 0; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - err = pci_enable_device(pdev); - if (err) { - dev_err(dev, "pci_enable_device failed\n"); - return err; - } - - i2c->status = STATUS_IDLE; - - intel_mid_i2c_hwinit(i2c); - return err; -} - -static void i2c_isr_read(struct intel_mid_i2c_private *i2c) -{ - struct i2c_msg *msg = i2c->msg; - int rx_num; - u32 len; - u8 *buf; - - if (!(msg->flags & I2C_M_RD)) - return; - - if (i2c->status != STATUS_READ_IN_PROGRESS) { - len = msg->len; - buf = msg->buf; - } else { - len = i2c->rx_buf_len; - buf = i2c->rx_buf; - } - - rx_num = readl(i2c->base + IC_RXFLR); - - for (; len > 0 && rx_num > 0; len--, rx_num--) - *buf++ = readl(i2c->base + IC_DATA_CMD); - - if (len > 0) { - i2c->status = STATUS_READ_IN_PROGRESS; - i2c->rx_buf_len = len; - i2c->rx_buf = buf; - } else - i2c->status = STATUS_READ_SUCCESS; - - return; -} - -static irqreturn_t intel_mid_i2c_isr(int this_irq, void *dev) -{ - struct intel_mid_i2c_private *i2c = dev; - u32 stat = readl(i2c->base + IC_INTR_STAT); - - if (!stat) - return IRQ_NONE; - - dev_dbg(&i2c->adap.dev, "%s, stat = 0x%x\n", __func__, stat); - stat &= 0x54; - - if (i2c->status != STATUS_WRITE_START && - i2c->status != STATUS_READ_START && - i2c->status != STATUS_READ_IN_PROGRESS) - goto err; - - if (stat & TX_ABRT) - i2c->abort = readl(i2c->base + IC_TX_ABRT_SOURCE); - - readl(i2c->base + IC_CLR_INTR); - - if (stat & TX_ABRT) { - intel_mid_i2c_abort(i2c); - goto exit; - } - - if (stat & RX_FULL) { - i2c_isr_read(i2c); - goto exit; - } - - if (stat & TX_EMPTY) { - if (readl(i2c->base + IC_STATUS) & 0x4) - i2c->status = STATUS_WRITE_SUCCESS; - } - -exit: - if (i2c->status == STATUS_READ_SUCCESS || - i2c->status == STATUS_WRITE_SUCCESS || - i2c->status == STATUS_XFER_ABORT) { - /* Clear all interrupts */ - readl(i2c->base + IC_CLR_INTR); - /* Mask interrupts */ - writel(0, i2c->base + IC_INTR_MASK); - complete(&i2c->complete); - } -err: - return IRQ_HANDLED; -} - -static struct i2c_algorithm intel_mid_i2c_algorithm = { - .master_xfer = intel_mid_i2c_xfer, - .functionality = intel_mid_i2c_func, -}; - - -static const struct dev_pm_ops intel_mid_i2c_pm_ops = { - .runtime_suspend = intel_mid_i2c_runtime_suspend, - .runtime_resume = intel_mid_i2c_runtime_resume, -}; - -/** - * intel_mid_i2c_probe - I2C controller initialization routine - * @dev: pci device - * @id: device id - * - * Return Values: - * 0 success - * -ENODEV If cannot allocate pci resource - * -ENOMEM If the register base remapping failed, or - * if kzalloc failed - * - * Initialization steps: - * 1. Request for PCI resource - * 2. Remap the start address of PCI resource to register base - * 3. Request for device memory region - * 4. Fill in the struct members of intel_mid_i2c_private - * 5. Call intel_mid_i2c_hwinit() for hardware initialization - * 6. Register I2C adapter in i2c-core - */ -static int __devinit intel_mid_i2c_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - struct intel_mid_i2c_private *mrst; - unsigned long start, len; - int err, busnum; - void __iomem *base = NULL; - - dev_dbg(&dev->dev, "Get into probe function for I2C\n"); - err = pci_enable_device(dev); - if (err) { - dev_err(&dev->dev, "Failed to enable I2C PCI device (%d)\n", - err); - goto exit; - } - - /* Determine the address of the I2C area */ - start = pci_resource_start(dev, 0); - len = pci_resource_len(dev, 0); - if (!start || len == 0) { - dev_err(&dev->dev, "base address not set\n"); - err = -ENODEV; - goto exit; - } - dev_dbg(&dev->dev, "%s i2c resource start 0x%lx, len=%ld\n", - PLATFORM, start, len); - - err = pci_request_region(dev, 0, DRIVER_NAME); - if (err) { - dev_err(&dev->dev, "failed to request I2C region " - "0x%lx-0x%lx\n", start, - (unsigned long)pci_resource_end(dev, 0)); - goto exit; - } - - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&dev->dev, "I/O memory remapping failed\n"); - err = -ENOMEM; - goto fail0; - } - - /* Allocate the per-device data structure, intel_mid_i2c_private */ - mrst = kzalloc(sizeof(struct intel_mid_i2c_private), GFP_KERNEL); - if (mrst == NULL) { - dev_err(&dev->dev, "can't allocate interface\n"); - err = -ENOMEM; - goto fail1; - } - - /* Initialize struct members */ - snprintf(mrst->adap.name, sizeof(mrst->adap.name), - "Intel MID I2C at %lx", start); - mrst->adap.owner = THIS_MODULE; - mrst->adap.algo = &intel_mid_i2c_algorithm; - mrst->adap.dev.parent = &dev->dev; - mrst->dev = &dev->dev; - mrst->base = base; - mrst->speed = STANDARD; - mrst->abort = 0; - mrst->rx_buf_len = 0; - mrst->status = STATUS_IDLE; - - pci_set_drvdata(dev, mrst); - i2c_set_adapdata(&mrst->adap, mrst); - - mrst->adap.nr = busnum = id->driver_data; - if (dev->device <= 0x0804) - mrst->platform = MOORESTOWN; - else - mrst->platform = MEDFIELD; - - dev_dbg(&dev->dev, "I2C%d\n", busnum); - - if (ctl_num > busnum) { - if (speed_mode[busnum] < 0 || speed_mode[busnum] >= NUM_SPEEDS) - dev_warn(&dev->dev, "invalid speed %d ignored.\n", - speed_mode[busnum]); - else - mrst->speed = speed_mode[busnum]; - } - - /* Initialize i2c controller */ - err = intel_mid_i2c_hwinit(mrst); - if (err < 0) { - dev_err(&dev->dev, "I2C interface initialization failed\n"); - goto fail2; - } - - mutex_init(&mrst->lock); - init_completion(&mrst->complete); - - /* Clear all interrupts */ - readl(mrst->base + IC_CLR_INTR); - writel(0x0000, mrst->base + IC_INTR_MASK); - - err = request_irq(dev->irq, intel_mid_i2c_isr, IRQF_SHARED, - mrst->adap.name, mrst); - if (err) { - dev_err(&dev->dev, "Failed to request IRQ for I2C controller: " - "%s", mrst->adap.name); - goto fail2; - } - - /* Adapter registration */ - err = i2c_add_numbered_adapter(&mrst->adap); - if (err) { - dev_err(&dev->dev, "Adapter %s registration failed\n", - mrst->adap.name); - goto fail3; - } - - dev_dbg(&dev->dev, "%s I2C bus %d driver bind success.\n", - (mrst->platform == MOORESTOWN) ? "Moorestown" : "Medfield", - busnum); - - pm_runtime_enable(&dev->dev); - return 0; - -fail3: - free_irq(dev->irq, mrst); -fail2: - pci_set_drvdata(dev, NULL); - kfree(mrst); -fail1: - iounmap(base); -fail0: - pci_release_region(dev, 0); -exit: - return err; -} - -static void __devexit intel_mid_i2c_remove(struct pci_dev *dev) -{ - struct intel_mid_i2c_private *mrst = pci_get_drvdata(dev); - intel_mid_i2c_disable(&mrst->adap); - if (i2c_del_adapter(&mrst->adap)) - dev_err(&dev->dev, "Failed to delete i2c adapter"); - - free_irq(dev->irq, mrst); - pci_set_drvdata(dev, NULL); - iounmap(mrst->base); - kfree(mrst); - pci_release_region(dev, 0); -} - -static DEFINE_PCI_DEVICE_TABLE(intel_mid_i2c_ids) = { - /* Moorestown */ - { PCI_VDEVICE(INTEL, 0x0802), 0 }, - { PCI_VDEVICE(INTEL, 0x0803), 1 }, - { PCI_VDEVICE(INTEL, 0x0804), 2 }, - /* Medfield */ - { PCI_VDEVICE(INTEL, 0x0817), 3,}, - { PCI_VDEVICE(INTEL, 0x0818), 4 }, - { PCI_VDEVICE(INTEL, 0x0819), 5 }, - { PCI_VDEVICE(INTEL, 0x082C), 0 }, - { PCI_VDEVICE(INTEL, 0x082D), 1 }, - { PCI_VDEVICE(INTEL, 0x082E), 2 }, - { 0,} -}; -MODULE_DEVICE_TABLE(pci, intel_mid_i2c_ids); - -static struct pci_driver intel_mid_i2c_driver = { - .name = DRIVER_NAME, - .id_table = intel_mid_i2c_ids, - .probe = intel_mid_i2c_probe, - .remove = __devexit_p(intel_mid_i2c_remove), -}; - -static int __init intel_mid_i2c_init(void) -{ - return pci_register_driver(&intel_mid_i2c_driver); -} - -static void __exit intel_mid_i2c_exit(void) -{ - pci_unregister_driver(&intel_mid_i2c_driver); -} - -module_init(intel_mid_i2c_init); -module_exit(intel_mid_i2c_exit); - -MODULE_AUTHOR("Ba Zheng <zheng.ba@intel.com>"); -MODULE_DESCRIPTION("I2C driver for Moorestown Platform"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(VERSION); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.c deleted file mode 100644 index 93f147a9..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.c +++ /dev/null @@ -1,531 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-iop3xx.c i2c driver algorithms for Intel XScale IOP3xx & IXP46x */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd - * <Peter dot Milne at D hyphen TACQ dot com> - * - * With acknowledgements to i2c-algo-ibm_ocp.c by - * Ian DaSilva, MontaVista Software, Inc. idasilva@mvista.com - * - * And i2c-algo-pcf.c, which was created by Simon G. Vogl and Hans Berglund: - * - * Copyright (C) 1995-1997 Simon G. Vogl, 1998-2000 Hans Berglund - * - * And which acknowledged Kyösti Mälkki <kmalkki@cc.hut.fi>, - * Frodo Looijaard <frodol@dds.nl>, Martin Bailey<mbailey@littlefeet-inc.com> - * - * Major cleanup by Deepak Saxena <dsaxena@plexity.net>, 01/2005: - * - * - Use driver model to pass per-chip info instead of hardcoding and #ifdefs - * - Use ioremap/__raw_readl/__raw_writel instead of direct dereference - * - Make it work with IXP46x chips - * - Cleanup function names, coding style, etc - * - * - writing to slave address causes latchup on iop331. - * fix: driver refuses to address self. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, version 2. - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/io.h> - -#include "i2c-iop3xx.h" - -/* global unit counter */ -static int i2c_id; - -static inline unsigned char -iic_cook_addr(struct i2c_msg *msg) -{ - unsigned char addr; - - addr = (msg->addr << 1); - - if (msg->flags & I2C_M_RD) - addr |= 1; - - return addr; -} - -static void -iop3xx_i2c_reset(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - /* Follows devman 9.3 */ - __raw_writel(IOP3XX_ICR_UNIT_RESET, iop3xx_adap->ioaddr + CR_OFFSET); - __raw_writel(IOP3XX_ISR_CLEARBITS, iop3xx_adap->ioaddr + SR_OFFSET); - __raw_writel(0, iop3xx_adap->ioaddr + CR_OFFSET); -} - -static void -iop3xx_i2c_enable(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - u32 cr = IOP3XX_ICR_GCD | IOP3XX_ICR_SCLEN | IOP3XX_ICR_UE; - - /* - * Every time unit enable is asserted, GPOD needs to be cleared - * on IOP3XX to avoid data corruption on the bus. - */ -#if defined(CONFIG_ARCH_IOP32X) || defined(CONFIG_ARCH_IOP33X) - if (iop3xx_adap->id == 0) { - gpio_line_set(IOP3XX_GPIO_LINE(7), GPIO_LOW); - gpio_line_set(IOP3XX_GPIO_LINE(6), GPIO_LOW); - } else { - gpio_line_set(IOP3XX_GPIO_LINE(5), GPIO_LOW); - gpio_line_set(IOP3XX_GPIO_LINE(4), GPIO_LOW); - } -#endif - /* NB SR bits not same position as CR IE bits :-( */ - iop3xx_adap->SR_enabled = - IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD | - IOP3XX_ISR_RXFULL | IOP3XX_ISR_TXEMPTY; - - cr |= IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | - IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE; - - __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); -} - -static void -iop3xx_i2c_transaction_cleanup(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); - - cr &= ~(IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE | - IOP3XX_ICR_MSTOP | IOP3XX_ICR_SCLEN); - - __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); -} - -/* - * NB: the handler has to clear the source of the interrupt! - * Then it passes the SR flags of interest to BH via adap data - */ -static irqreturn_t -iop3xx_i2c_irq_handler(int this_irq, void *dev_id) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = dev_id; - u32 sr = __raw_readl(iop3xx_adap->ioaddr + SR_OFFSET); - - if ((sr &= iop3xx_adap->SR_enabled)) { - __raw_writel(sr, iop3xx_adap->ioaddr + SR_OFFSET); - iop3xx_adap->SR_received |= sr; - wake_up_interruptible(&iop3xx_adap->waitq); - } - return IRQ_HANDLED; -} - -/* check all error conditions, clear them , report most important */ -static int -iop3xx_i2c_error(u32 sr) -{ - int rc = 0; - - if ((sr & IOP3XX_ISR_BERRD)) { - if ( !rc ) rc = -I2C_ERR_BERR; - } - if ((sr & IOP3XX_ISR_ALD)) { - if ( !rc ) rc = -I2C_ERR_ALD; - } - return rc; -} - -static inline u32 -iop3xx_i2c_get_srstat(struct i2c_algo_iop3xx_data *iop3xx_adap) -{ - unsigned long flags; - u32 sr; - - spin_lock_irqsave(&iop3xx_adap->lock, flags); - sr = iop3xx_adap->SR_received; - iop3xx_adap->SR_received = 0; - spin_unlock_irqrestore(&iop3xx_adap->lock, flags); - - return sr; -} - -/* - * sleep until interrupted, then recover and analyse the SR - * saved by handler - */ -typedef int (* compare_func)(unsigned test, unsigned mask); -/* returns 1 on correct comparison */ - -static int -iop3xx_i2c_wait_event(struct i2c_algo_iop3xx_data *iop3xx_adap, - unsigned flags, unsigned* status, - compare_func compare) -{ - unsigned sr = 0; - int interrupted; - int done; - int rc = 0; - - do { - interrupted = wait_event_interruptible_timeout ( - iop3xx_adap->waitq, - (done = compare( sr = iop3xx_i2c_get_srstat(iop3xx_adap) ,flags )), - 1 * HZ; - ); - if ((rc = iop3xx_i2c_error(sr)) < 0) { - *status = sr; - return rc; - } else if (!interrupted) { - *status = sr; - return -ETIMEDOUT; - } - } while(!done); - - *status = sr; - - return 0; -} - -/* - * Concrete compare_funcs - */ -static int -all_bits_clear(unsigned test, unsigned mask) -{ - return (test & mask) == 0; -} - -static int -any_bits_set(unsigned test, unsigned mask) -{ - return (test & mask) != 0; -} - -static int -iop3xx_i2c_wait_tx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_i2c_wait_event( - iop3xx_adap, - IOP3XX_ISR_TXEMPTY | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, - status, any_bits_set); -} - -static int -iop3xx_i2c_wait_rx_done(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_i2c_wait_event( - iop3xx_adap, - IOP3XX_ISR_RXFULL | IOP3XX_ISR_ALD | IOP3XX_ISR_BERRD, - status, any_bits_set); -} - -static int -iop3xx_i2c_wait_idle(struct i2c_algo_iop3xx_data *iop3xx_adap, int *status) -{ - return iop3xx_i2c_wait_event( - iop3xx_adap, IOP3XX_ISR_UNITBUSY, status, all_bits_clear); -} - -static int -iop3xx_i2c_send_target_addr(struct i2c_algo_iop3xx_data *iop3xx_adap, - struct i2c_msg* msg) -{ - unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); - int status; - int rc; - - /* avoid writing to my slave address (hangs on 80331), - * forbidden in Intel developer manual - */ - if (msg->addr == MYSAR) { - return -EBUSY; - } - - __raw_writel(iic_cook_addr(msg), iop3xx_adap->ioaddr + DBR_OFFSET); - - cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); - cr |= IOP3XX_ICR_MSTART | IOP3XX_ICR_TBYTE; - - __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); - rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); - - return rc; -} - -static int -iop3xx_i2c_write_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char byte, - int stop) -{ - unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); - int status; - int rc = 0; - - __raw_writel(byte, iop3xx_adap->ioaddr + DBR_OFFSET); - cr &= ~IOP3XX_ICR_MSTART; - if (stop) { - cr |= IOP3XX_ICR_MSTOP; - } else { - cr &= ~IOP3XX_ICR_MSTOP; - } - cr |= IOP3XX_ICR_TBYTE; - __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); - rc = iop3xx_i2c_wait_tx_done(iop3xx_adap, &status); - - return rc; -} - -static int -iop3xx_i2c_read_byte(struct i2c_algo_iop3xx_data *iop3xx_adap, char* byte, - int stop) -{ - unsigned long cr = __raw_readl(iop3xx_adap->ioaddr + CR_OFFSET); - int status; - int rc = 0; - - cr &= ~IOP3XX_ICR_MSTART; - - if (stop) { - cr |= IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK; - } else { - cr &= ~(IOP3XX_ICR_MSTOP | IOP3XX_ICR_NACK); - } - cr |= IOP3XX_ICR_TBYTE; - __raw_writel(cr, iop3xx_adap->ioaddr + CR_OFFSET); - - rc = iop3xx_i2c_wait_rx_done(iop3xx_adap, &status); - - *byte = __raw_readl(iop3xx_adap->ioaddr + DBR_OFFSET); - - return rc; -} - -static int -iop3xx_i2c_writebytes(struct i2c_adapter *i2c_adap, const char *buf, int count) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int ii; - int rc = 0; - - for (ii = 0; rc == 0 && ii != count; ++ii) - rc = iop3xx_i2c_write_byte(iop3xx_adap, buf[ii], ii==count-1); - return rc; -} - -static int -iop3xx_i2c_readbytes(struct i2c_adapter *i2c_adap, char *buf, int count) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int ii; - int rc = 0; - - for (ii = 0; rc == 0 && ii != count; ++ii) - rc = iop3xx_i2c_read_byte(iop3xx_adap, &buf[ii], ii==count-1); - - return rc; -} - -/* - * Description: This function implements combined transactions. Combined - * transactions consist of combinations of reading and writing blocks of data. - * FROM THE SAME ADDRESS - * Each transfer (i.e. a read or a write) is separated by a repeated start - * condition. - */ -static int -iop3xx_i2c_handle_msg(struct i2c_adapter *i2c_adap, struct i2c_msg* pmsg) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int rc; - - rc = iop3xx_i2c_send_target_addr(iop3xx_adap, pmsg); - if (rc < 0) { - return rc; - } - - if ((pmsg->flags&I2C_M_RD)) { - return iop3xx_i2c_readbytes(i2c_adap, pmsg->buf, pmsg->len); - } else { - return iop3xx_i2c_writebytes(i2c_adap, pmsg->buf, pmsg->len); - } -} - -/* - * master_xfer() - main read/write entry - */ -static int -iop3xx_i2c_master_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, - int num) -{ - struct i2c_algo_iop3xx_data *iop3xx_adap = i2c_adap->algo_data; - int im = 0; - int ret = 0; - int status; - - iop3xx_i2c_wait_idle(iop3xx_adap, &status); - iop3xx_i2c_reset(iop3xx_adap); - iop3xx_i2c_enable(iop3xx_adap); - - for (im = 0; ret == 0 && im != num; im++) { - ret = iop3xx_i2c_handle_msg(i2c_adap, &msgs[im]); - } - - iop3xx_i2c_transaction_cleanup(iop3xx_adap); - - if(ret) - return ret; - - return im; -} - -static u32 -iop3xx_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm iop3xx_i2c_algo = { - .master_xfer = iop3xx_i2c_master_xfer, - .functionality = iop3xx_i2c_func, -}; - -static int -iop3xx_i2c_remove(struct platform_device *pdev) -{ - struct i2c_adapter *padapter = platform_get_drvdata(pdev); - struct i2c_algo_iop3xx_data *adapter_data = - (struct i2c_algo_iop3xx_data *)padapter->algo_data; - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - unsigned long cr = __raw_readl(adapter_data->ioaddr + CR_OFFSET); - - /* - * Disable the actual HW unit - */ - cr &= ~(IOP3XX_ICR_ALD_IE | IOP3XX_ICR_BERR_IE | - IOP3XX_ICR_RXFULL_IE | IOP3XX_ICR_TXEMPTY_IE); - __raw_writel(cr, adapter_data->ioaddr + CR_OFFSET); - - iounmap(adapter_data->ioaddr); - release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); - kfree(adapter_data); - kfree(padapter); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static int -iop3xx_i2c_probe(struct platform_device *pdev) -{ - struct resource *res; - int ret, irq; - struct i2c_adapter *new_adapter; - struct i2c_algo_iop3xx_data *adapter_data; - - new_adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (!new_adapter) { - ret = -ENOMEM; - goto out; - } - - adapter_data = kzalloc(sizeof(struct i2c_algo_iop3xx_data), GFP_KERNEL); - if (!adapter_data) { - ret = -ENOMEM; - goto free_adapter; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENODEV; - goto free_both; - } - - if (!request_mem_region(res->start, IOP3XX_I2C_IO_SIZE, pdev->name)) { - ret = -EBUSY; - goto free_both; - } - - /* set the adapter enumeration # */ - adapter_data->id = i2c_id++; - - adapter_data->ioaddr = ioremap(res->start, IOP3XX_I2C_IO_SIZE); - if (!adapter_data->ioaddr) { - ret = -ENOMEM; - goto release_region; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - ret = -ENXIO; - goto unmap; - } - ret = request_irq(irq, iop3xx_i2c_irq_handler, 0, - pdev->name, adapter_data); - - if (ret) { - ret = -EIO; - goto unmap; - } - - memcpy(new_adapter->name, pdev->name, strlen(pdev->name)); - new_adapter->owner = THIS_MODULE; - new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - new_adapter->dev.parent = &pdev->dev; - new_adapter->nr = pdev->id; - - /* - * Default values...should these come in from board code? - */ - new_adapter->timeout = HZ; - new_adapter->algo = &iop3xx_i2c_algo; - - init_waitqueue_head(&adapter_data->waitq); - spin_lock_init(&adapter_data->lock); - - iop3xx_i2c_reset(adapter_data); - iop3xx_i2c_enable(adapter_data); - - platform_set_drvdata(pdev, new_adapter); - new_adapter->algo_data = adapter_data; - - i2c_add_numbered_adapter(new_adapter); - - return 0; - -unmap: - iounmap(adapter_data->ioaddr); - -release_region: - release_mem_region(res->start, IOP3XX_I2C_IO_SIZE); - -free_both: - kfree(adapter_data); - -free_adapter: - kfree(new_adapter); - -out: - return ret; -} - - -static struct platform_driver iop3xx_i2c_driver = { - .probe = iop3xx_i2c_probe, - .remove = iop3xx_i2c_remove, - .driver = { - .owner = THIS_MODULE, - .name = "IOP3xx-I2C", - }, -}; - -module_platform_driver(iop3xx_i2c_driver); - -MODULE_AUTHOR("D-TACQ Solutions Ltd <www.d-tacq.com>"); -MODULE_DESCRIPTION("IOP3xx iic algorithm and driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:IOP3xx-I2C"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.h b/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.h deleted file mode 100644 index 097e2709..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-iop3xx.h +++ /dev/null @@ -1,107 +0,0 @@ -/* ------------------------------------------------------------------------- */ -/* i2c-iop3xx.h algorithm driver definitions private to i2c-iop3xx.c */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 2003 Peter Milne, D-TACQ Solutions Ltd - * <Peter dot Milne at D hyphen TACQ dot com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, version 2. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* ------------------------------------------------------------------------- */ - - -#ifndef I2C_IOP3XX_H -#define I2C_IOP3XX_H 1 - -/* - * iop321 hardware bit definitions - */ -#define IOP3XX_ICR_FAST_MODE 0x8000 /* 1=400kBps, 0=100kBps */ -#define IOP3XX_ICR_UNIT_RESET 0x4000 /* 1=RESET */ -#define IOP3XX_ICR_SAD_IE 0x2000 /* 1=Slave Detect Interrupt Enable */ -#define IOP3XX_ICR_ALD_IE 0x1000 /* 1=Arb Loss Detect Interrupt Enable */ -#define IOP3XX_ICR_SSD_IE 0x0800 /* 1=Slave STOP Detect Interrupt Enable */ -#define IOP3XX_ICR_BERR_IE 0x0400 /* 1=Bus Error Interrupt Enable */ -#define IOP3XX_ICR_RXFULL_IE 0x0200 /* 1=Receive Full Interrupt Enable */ -#define IOP3XX_ICR_TXEMPTY_IE 0x0100 /* 1=Transmit Empty Interrupt Enable */ -#define IOP3XX_ICR_GCD 0x0080 /* 1=General Call Disable */ -/* - * IOP3XX_ICR_GCD: 1 disables response as slave. "This bit must be set - * when sending a master mode general call message from the I2C unit" - */ -#define IOP3XX_ICR_UE 0x0040 /* 1=Unit Enable */ -/* - * "NOTE: To avoid I2C bus integrity problems, - * the user needs to ensure that the GPIO Output Data Register - - * GPOD bits associated with an I2C port are cleared prior to setting - * the enable bit for that I2C serial port. - * The user prepares to enable I2C port 0 and - * I2C port 1 by clearing GPOD bits 7:6 and GPOD bits 5:4, respectively. - */ -#define IOP3XX_ICR_SCLEN 0x0020 /* 1=SCL enable for master mode */ -#define IOP3XX_ICR_MABORT 0x0010 /* 1=Send a STOP with no data - * NB TBYTE must be clear */ -#define IOP3XX_ICR_TBYTE 0x0008 /* 1=Send/Receive a byte. i2c clears */ -#define IOP3XX_ICR_NACK 0x0004 /* 1=reply with NACK */ -#define IOP3XX_ICR_MSTOP 0x0002 /* 1=send a STOP after next data byte */ -#define IOP3XX_ICR_MSTART 0x0001 /* 1=initiate a START */ - - -#define IOP3XX_ISR_BERRD 0x0400 /* 1=BUS ERROR Detected */ -#define IOP3XX_ISR_SAD 0x0200 /* 1=Slave ADdress Detected */ -#define IOP3XX_ISR_GCAD 0x0100 /* 1=General Call Address Detected */ -#define IOP3XX_ISR_RXFULL 0x0080 /* 1=Receive Full */ -#define IOP3XX_ISR_TXEMPTY 0x0040 /* 1=Transmit Empty */ -#define IOP3XX_ISR_ALD 0x0020 /* 1=Arbitration Loss Detected */ -#define IOP3XX_ISR_SSD 0x0010 /* 1=Slave STOP Detected */ -#define IOP3XX_ISR_BBUSY 0x0008 /* 1=Bus BUSY */ -#define IOP3XX_ISR_UNITBUSY 0x0004 /* 1=Unit Busy */ -#define IOP3XX_ISR_NACK 0x0002 /* 1=Unit Rx or Tx a NACK */ -#define IOP3XX_ISR_RXREAD 0x0001 /* 1=READ 0=WRITE (R/W bit of slave addr */ - -#define IOP3XX_ISR_CLEARBITS 0x07f0 - -#define IOP3XX_ISAR_SAMASK 0x007f - -#define IOP3XX_IDBR_MASK 0x00ff - -#define IOP3XX_IBMR_SCL 0x0002 -#define IOP3XX_IBMR_SDA 0x0001 - -#define IOP3XX_GPOD_I2C0 0x00c0 /* clear these bits to enable ch0 */ -#define IOP3XX_GPOD_I2C1 0x0030 /* clear these bits to enable ch1 */ - -#define MYSAR 0 /* default slave address */ - -#define I2C_ERR 321 -#define I2C_ERR_BERR (I2C_ERR+0) -#define I2C_ERR_ALD (I2C_ERR+1) - - -#define CR_OFFSET 0 -#define SR_OFFSET 0x4 -#define SAR_OFFSET 0x8 -#define DBR_OFFSET 0xc -#define CCR_OFFSET 0x10 -#define BMR_OFFSET 0x14 - -#define IOP3XX_I2C_IO_SIZE 0x18 - -struct i2c_algo_iop3xx_data { - void __iomem *ioaddr; - wait_queue_head_t waitq; - spinlock_t lock; - u32 SR_enabled, SR_received; - int id; -}; - -#endif /* I2C_IOP3XX_H */ diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-isch.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-isch.c deleted file mode 100644 index f90a6057..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-isch.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus - - Based on i2c-piix4.c - Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - - Intel SCH support - Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports: - Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L) - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/io.h> -#include <linux/acpi.h> - -/* SCH SMBus address offsets */ -#define SMBHSTCNT (0 + sch_smba) -#define SMBHSTSTS (1 + sch_smba) -#define SMBHSTADD (4 + sch_smba) /* TSA */ -#define SMBHSTCMD (5 + sch_smba) -#define SMBHSTDAT0 (6 + sch_smba) -#define SMBHSTDAT1 (7 + sch_smba) -#define SMBBLKDAT (0x20 + sch_smba) - -/* Other settings */ -#define MAX_RETRIES 5000 - -/* I2C constants */ -#define SCH_QUICK 0x00 -#define SCH_BYTE 0x01 -#define SCH_BYTE_DATA 0x02 -#define SCH_WORD_DATA 0x03 -#define SCH_BLOCK_DATA 0x05 - -static unsigned short sch_smba; -static struct i2c_adapter sch_adapter; - -/* - * Start the i2c transaction -- the i2c_access will prepare the transaction - * and this function will execute it. - * return 0 for success and others for failure. - */ -static int sch_transaction(void) -{ - int temp; - int result = 0; - int retries = 0; - - dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), - inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), - inb(SMBHSTDAT1)); - - /* Make sure the SMBus host is ready to start transmitting */ - temp = inb(SMBHSTSTS) & 0x0f; - if (temp) { - /* Can not be busy since we checked it in sch_access */ - if (temp & 0x01) { - dev_dbg(&sch_adapter.dev, "Completion (%02x). " - "Clear...\n", temp); - } - if (temp & 0x06) { - dev_dbg(&sch_adapter.dev, "SMBus error (%02x). " - "Resetting...\n", temp); - } - outb(temp, SMBHSTSTS); - temp = inb(SMBHSTSTS) & 0x0f; - if (temp) { - dev_err(&sch_adapter.dev, - "SMBus is not ready: (%02x)\n", temp); - return -EAGAIN; - } - } - - /* start the transaction by setting bit 4 */ - outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT); - - do { - usleep_range(100, 200); - temp = inb(SMBHSTSTS) & 0x0f; - } while ((temp & 0x08) && (retries++ < MAX_RETRIES)); - - /* If the SMBus is still busy, we give up */ - if (retries > MAX_RETRIES) { - dev_err(&sch_adapter.dev, "SMBus Timeout!\n"); - result = -ETIMEDOUT; - } - if (temp & 0x04) { - result = -EIO; - dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be " - "locked until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } else if (temp & 0x02) { - result = -EIO; - dev_err(&sch_adapter.dev, "Error: no response!\n"); - } else if (temp & 0x01) { - dev_dbg(&sch_adapter.dev, "Post complete!\n"); - outb(temp, SMBHSTSTS); - temp = inb(SMBHSTSTS) & 0x07; - if (temp & 0x06) { - /* Completion clear failed */ - dev_dbg(&sch_adapter.dev, "Failed reset at end of " - "transaction (%02x), Bus error!\n", temp); - } - } else { - result = -ENXIO; - dev_dbg(&sch_adapter.dev, "No such address.\n"); - } - dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT), - inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0), - inb(SMBHSTDAT1)); - return result; -} - -/* - * This is the main access entry for i2c-sch access - * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write - * (0 for read and 1 for write), size is i2c transaction type and data is the - * union of transaction for data to be transferred or data read from bus. - * return 0 for success and others for failure. - */ -static s32 sch_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - int i, len, temp, rc; - - /* Make sure the SMBus host is not busy */ - temp = inb(SMBHSTSTS) & 0x0f; - if (temp & 0x08) { - dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp); - return -EAGAIN; - } - dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size, - (read_write)?"READ":"WRITE"); - switch (size) { - case I2C_SMBUS_QUICK: - outb((addr << 1) | read_write, SMBHSTADD); - size = SCH_QUICK; - break; - case I2C_SMBUS_BYTE: - outb((addr << 1) | read_write, SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb(command, SMBHSTCMD); - size = SCH_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb((addr << 1) | read_write, SMBHSTADD); - outb(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb(data->byte, SMBHSTDAT0); - size = SCH_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb((addr << 1) | read_write, SMBHSTADD); - outb(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb(data->word & 0xff, SMBHSTDAT0); - outb((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = SCH_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb((addr << 1) | read_write, SMBHSTADD); - outb(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EINVAL; - outb(len, SMBHSTDAT0); - for (i = 1; i <= len; i++) - outb(data->block[i], SMBBLKDAT+i-1); - } - size = SCH_BLOCK_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT); - outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT); - - rc = sch_transaction(); - if (rc) /* Error in transaction */ - return rc; - - if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK)) - return 0; - - switch (size) { - case SCH_BYTE: - case SCH_BYTE_DATA: - data->byte = inb(SMBHSTDAT0); - break; - case SCH_WORD_DATA: - data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8); - break; - case SCH_BLOCK_DATA: - data->block[0] = inb(SMBHSTDAT0); - if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb(SMBBLKDAT+i-1); - break; - } - return 0; -} - -static u32 sch_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = sch_access, - .functionality = sch_func, -}; - -static struct i2c_adapter sch_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static int __devinit smbus_sch_probe(struct platform_device *dev) -{ - struct resource *res; - int retval; - - res = platform_get_resource(dev, IORESOURCE_IO, 0); - if (!res) - return -EBUSY; - - if (!request_region(res->start, resource_size(res), dev->name)) { - dev_err(&dev->dev, "SMBus region 0x%x already in use!\n", - sch_smba); - return -EBUSY; - } - - sch_smba = res->start; - - dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba); - - /* set up the sysfs linkage to our parent device */ - sch_adapter.dev.parent = &dev->dev; - - snprintf(sch_adapter.name, sizeof(sch_adapter.name), - "SMBus SCH adapter at %04x", sch_smba); - - retval = i2c_add_adapter(&sch_adapter); - if (retval) { - dev_err(&dev->dev, "Couldn't register adapter!\n"); - release_region(res->start, resource_size(res)); - sch_smba = 0; - } - - return retval; -} - -static int __devexit smbus_sch_remove(struct platform_device *pdev) -{ - struct resource *res; - if (sch_smba) { - i2c_del_adapter(&sch_adapter); - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, resource_size(res)); - sch_smba = 0; - } - - return 0; -} - -static struct platform_driver smbus_sch_driver = { - .driver = { - .name = "isch_smbus", - .owner = THIS_MODULE, - }, - .probe = smbus_sch_probe, - .remove = __devexit_p(smbus_sch_remove), -}; - -module_platform_driver(smbus_sch_driver); - -MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>"); -MODULE_DESCRIPTION("Intel SCH SMBus driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:isch_smbus"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ixp2000.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ixp2000.c deleted file mode 100644 index 5d263f90..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ixp2000.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * drivers/i2c/busses/i2c-ixp2000.c - * - * I2C adapter for IXP2000 systems using GPIOs for I2C bus - * - * Author: Deepak Saxena <dsaxena@plexity.net> - * Based on IXDP2400 code by: Naeem M. Afzal <naeem.m.afzal@intel.com> - * Made generic by: Jeff Daly <jeffrey.daly@intel.com> - * - * Copyright (c) 2003-2004 MontaVista Software Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - * - * From Jeff Daly: - * - * I2C adapter driver for Intel IXDP2xxx platforms. This should work for any - * IXP2000 platform if it uses the HW GPIO in the same manner. Basically, - * SDA and SCL GPIOs have external pullups. Setting the respective GPIO to - * an input will make the signal a '1' via the pullup. Setting them to - * outputs will pull them down. - * - * The GPIOs are open drain signals and are used as configuration strap inputs - * during power-up so there's generally a buffer on the board that needs to be - * 'enabled' to drive the GPIOs. - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/slab.h> - -#include <mach/hardware.h> /* Pick up IXP2000-specific bits */ -#include <mach/gpio-ixp2000.h> - -static inline int ixp2000_scl_pin(void *data) -{ - return ((struct ixp2000_i2c_pins*)data)->scl_pin; -} - -static inline int ixp2000_sda_pin(void *data) -{ - return ((struct ixp2000_i2c_pins*)data)->sda_pin; -} - - -static void ixp2000_bit_setscl(void *data, int val) -{ - int i = 5000; - - if (val) { - gpio_line_config(ixp2000_scl_pin(data), GPIO_IN); - while(!gpio_line_get(ixp2000_scl_pin(data)) && i--); - } else { - gpio_line_config(ixp2000_scl_pin(data), GPIO_OUT); - } -} - -static void ixp2000_bit_setsda(void *data, int val) -{ - if (val) { - gpio_line_config(ixp2000_sda_pin(data), GPIO_IN); - } else { - gpio_line_config(ixp2000_sda_pin(data), GPIO_OUT); - } -} - -static int ixp2000_bit_getscl(void *data) -{ - return gpio_line_get(ixp2000_scl_pin(data)); -} - -static int ixp2000_bit_getsda(void *data) -{ - return gpio_line_get(ixp2000_sda_pin(data)); -} - -struct ixp2000_i2c_data { - struct ixp2000_i2c_pins *gpio_pins; - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo_data; -}; - -static int ixp2000_i2c_remove(struct platform_device *plat_dev) -{ - struct ixp2000_i2c_data *drv_data = platform_get_drvdata(plat_dev); - - platform_set_drvdata(plat_dev, NULL); - - i2c_del_adapter(&drv_data->adapter); - - kfree(drv_data); - - return 0; -} - -static int ixp2000_i2c_probe(struct platform_device *plat_dev) -{ - int err; - struct ixp2000_i2c_pins *gpio = plat_dev->dev.platform_data; - struct ixp2000_i2c_data *drv_data = - kzalloc(sizeof(struct ixp2000_i2c_data), GFP_KERNEL); - - if (!drv_data) - return -ENOMEM; - drv_data->gpio_pins = gpio; - - drv_data->algo_data.data = gpio; - drv_data->algo_data.setsda = ixp2000_bit_setsda; - drv_data->algo_data.setscl = ixp2000_bit_setscl; - drv_data->algo_data.getsda = ixp2000_bit_getsda; - drv_data->algo_data.getscl = ixp2000_bit_getscl; - drv_data->algo_data.udelay = 6; - drv_data->algo_data.timeout = HZ; - - strlcpy(drv_data->adapter.name, plat_dev->dev.driver->name, - sizeof(drv_data->adapter.name)); - drv_data->adapter.algo_data = &drv_data->algo_data, - - drv_data->adapter.dev.parent = &plat_dev->dev; - - gpio_line_config(gpio->sda_pin, GPIO_IN); - gpio_line_config(gpio->scl_pin, GPIO_IN); - gpio_line_set(gpio->scl_pin, 0); - gpio_line_set(gpio->sda_pin, 0); - - if ((err = i2c_bit_add_bus(&drv_data->adapter)) != 0) { - dev_err(&plat_dev->dev, "Could not install, error %d\n", err); - kfree(drv_data); - return err; - } - - platform_set_drvdata(plat_dev, drv_data); - - return 0; -} - -static struct platform_driver ixp2000_i2c_driver = { - .probe = ixp2000_i2c_probe, - .remove = ixp2000_i2c_remove, - .driver = { - .name = "IXP2000-I2C", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(ixp2000_i2c_driver); - -MODULE_AUTHOR ("Deepak Saxena <dsaxena@plexity.net>"); -MODULE_DESCRIPTION("IXP2000 GPIO-based I2C bus driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:IXP2000-I2C"); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mpc.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-mpc.c deleted file mode 100644 index 206caacd..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mpc.c +++ /dev/null @@ -1,758 +0,0 @@ -/* - * (C) Copyright 2003-2004 - * Humboldt Solutions Ltd, adrian@humboldt.co.uk. - - * This is a combined i2c adapter and algorithm driver for the - * MPC107/Tsi107 PowerPC northbridge and processors that include - * the same I2C unit (8240, 8245, 85xx). - * - * Release 0.8 - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/init.h> -#include <linux/of_platform.h> -#include <linux/of_i2c.h> -#include <linux/slab.h> - -#include <linux/io.h> -#include <linux/fsl_devices.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> - -#include <asm/mpc52xx.h> -#include <sysdev/fsl_soc.h> - -#define DRV_NAME "mpc-i2c" - -#define MPC_I2C_CLOCK_LEGACY 0 -#define MPC_I2C_CLOCK_PRESERVE (~0U) - -#define MPC_I2C_FDR 0x04 -#define MPC_I2C_CR 0x08 -#define MPC_I2C_SR 0x0c -#define MPC_I2C_DR 0x10 -#define MPC_I2C_DFSRR 0x14 - -#define CCR_MEN 0x80 -#define CCR_MIEN 0x40 -#define CCR_MSTA 0x20 -#define CCR_MTX 0x10 -#define CCR_TXAK 0x08 -#define CCR_RSTA 0x04 - -#define CSR_MCF 0x80 -#define CSR_MAAS 0x40 -#define CSR_MBB 0x20 -#define CSR_MAL 0x10 -#define CSR_SRW 0x04 -#define CSR_MIF 0x02 -#define CSR_RXAK 0x01 - -struct mpc_i2c { - struct device *dev; - void __iomem *base; - u32 interrupt; - wait_queue_head_t queue; - struct i2c_adapter adap; - int irq; - u32 real_clk; -}; - -struct mpc_i2c_divider { - u16 divider; - u16 fdr; /* including dfsrr */ -}; - -struct mpc_i2c_data { - void (*setup)(struct device_node *node, struct mpc_i2c *i2c, - u32 clock, u32 prescaler); - u32 prescaler; -}; - -static inline void writeccr(struct mpc_i2c *i2c, u32 x) -{ - writeb(x, i2c->base + MPC_I2C_CR); -} - -static irqreturn_t mpc_i2c_isr(int irq, void *dev_id) -{ - struct mpc_i2c *i2c = dev_id; - if (readb(i2c->base + MPC_I2C_SR) & CSR_MIF) { - /* Read again to allow register to stabilise */ - i2c->interrupt = readb(i2c->base + MPC_I2C_SR); - writeb(0, i2c->base + MPC_I2C_SR); - wake_up(&i2c->queue); - } - return IRQ_HANDLED; -} - -/* Sometimes 9th clock pulse isn't generated, and slave doesn't release - * the bus, because it wants to send ACK. - * Following sequence of enabling/disabling and sending start/stop generates - * the 9 pulses, so it's all OK. - */ -static void mpc_i2c_fixup(struct mpc_i2c *i2c) -{ - int k; - u32 delay_val = 1000000 / i2c->real_clk + 1; - - if (delay_val < 2) - delay_val = 2; - - for (k = 9; k; k--) { - writeccr(i2c, 0); - writeccr(i2c, CCR_MSTA | CCR_MTX | CCR_MEN); - udelay(delay_val); - writeccr(i2c, CCR_MEN); - udelay(delay_val << 1); - } -} - -static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing) -{ - unsigned long orig_jiffies = jiffies; - u32 x; - int result = 0; - - if (!i2c->irq) { - while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) { - schedule(); - if (time_after(jiffies, orig_jiffies + timeout)) { - dev_dbg(i2c->dev, "timeout\n"); - writeccr(i2c, 0); - result = -EIO; - break; - } - } - x = readb(i2c->base + MPC_I2C_SR); - writeb(0, i2c->base + MPC_I2C_SR); - } else { - /* Interrupt mode */ - result = wait_event_timeout(i2c->queue, - (i2c->interrupt & CSR_MIF), timeout); - - if (unlikely(!(i2c->interrupt & CSR_MIF))) { - dev_dbg(i2c->dev, "wait timeout\n"); - writeccr(i2c, 0); - result = -ETIMEDOUT; - } - - x = i2c->interrupt; - i2c->interrupt = 0; - } - - if (result < 0) - return result; - - if (!(x & CSR_MCF)) { - dev_dbg(i2c->dev, "unfinished\n"); - return -EIO; - } - - if (x & CSR_MAL) { - dev_dbg(i2c->dev, "MAL\n"); - return -EIO; - } - - if (writing && (x & CSR_RXAK)) { - dev_dbg(i2c->dev, "No RXAK\n"); - /* generate stop */ - writeccr(i2c, CCR_MEN); - return -EIO; - } - return 0; -} - -#if defined(CONFIG_PPC_MPC52xx) || defined(CONFIG_PPC_MPC512x) -static const struct mpc_i2c_divider mpc_i2c_dividers_52xx[] __devinitconst = { - {20, 0x20}, {22, 0x21}, {24, 0x22}, {26, 0x23}, - {28, 0x24}, {30, 0x01}, {32, 0x25}, {34, 0x02}, - {36, 0x26}, {40, 0x27}, {44, 0x04}, {48, 0x28}, - {52, 0x63}, {56, 0x29}, {60, 0x41}, {64, 0x2a}, - {68, 0x07}, {72, 0x2b}, {80, 0x2c}, {88, 0x09}, - {96, 0x2d}, {104, 0x0a}, {112, 0x2e}, {120, 0x81}, - {128, 0x2f}, {136, 0x47}, {144, 0x0c}, {160, 0x30}, - {176, 0x49}, {192, 0x31}, {208, 0x4a}, {224, 0x32}, - {240, 0x0f}, {256, 0x33}, {272, 0x87}, {288, 0x10}, - {320, 0x34}, {352, 0x89}, {384, 0x35}, {416, 0x8a}, - {448, 0x36}, {480, 0x13}, {512, 0x37}, {576, 0x14}, - {640, 0x38}, {768, 0x39}, {896, 0x3a}, {960, 0x17}, - {1024, 0x3b}, {1152, 0x18}, {1280, 0x3c}, {1536, 0x3d}, - {1792, 0x3e}, {1920, 0x1b}, {2048, 0x3f}, {2304, 0x1c}, - {2560, 0x1d}, {3072, 0x1e}, {3584, 0x7e}, {3840, 0x1f}, - {4096, 0x7f}, {4608, 0x5c}, {5120, 0x5d}, {6144, 0x5e}, - {7168, 0xbe}, {7680, 0x5f}, {8192, 0xbf}, {9216, 0x9c}, - {10240, 0x9d}, {12288, 0x9e}, {15360, 0x9f} -}; - -static int __devinit mpc_i2c_get_fdr_52xx(struct device_node *node, u32 clock, - int prescaler, u32 *real_clk) -{ - const struct mpc_i2c_divider *div = NULL; - unsigned int pvr = mfspr(SPRN_PVR); - u32 divider; - int i; - - if (clock == MPC_I2C_CLOCK_LEGACY) { - /* see below - default fdr = 0x3f -> div = 2048 */ - *real_clk = mpc5xxx_get_bus_frequency(node) / 2048; - return -EINVAL; - } - - /* Determine divider value */ - divider = mpc5xxx_get_bus_frequency(node) / clock; - - /* - * We want to choose an FDR/DFSR that generates an I2C bus speed that - * is equal to or lower than the requested speed. - */ - for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_52xx); i++) { - div = &mpc_i2c_dividers_52xx[i]; - /* Old MPC5200 rev A CPUs do not support the high bits */ - if (div->fdr & 0xc0 && pvr == 0x80822011) - continue; - if (div->divider >= divider) - break; - } - - *real_clk = mpc5xxx_get_bus_frequency(node) / div->divider; - return (int)div->fdr; -} - -static void __devinit mpc_i2c_setup_52xx(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ - int ret, fdr; - - if (clock == MPC_I2C_CLOCK_PRESERVE) { - dev_dbg(i2c->dev, "using fdr %d\n", - readb(i2c->base + MPC_I2C_FDR)); - return; - } - - ret = mpc_i2c_get_fdr_52xx(node, clock, prescaler, &i2c->real_clk); - fdr = (ret >= 0) ? ret : 0x3f; /* backward compatibility */ - - writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); - - if (ret >= 0) - dev_info(i2c->dev, "clock %u Hz (fdr=%d)\n", i2c->real_clk, - fdr); -} -#else /* !(CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x) */ -static void __devinit mpc_i2c_setup_52xx(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ -} -#endif /* CONFIG_PPC_MPC52xx || CONFIG_PPC_MPC512x */ - -#ifdef CONFIG_PPC_MPC512x -static void __devinit mpc_i2c_setup_512x(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ - struct device_node *node_ctrl; - void __iomem *ctrl; - const u32 *pval; - u32 idx; - - /* Enable I2C interrupts for mpc5121 */ - node_ctrl = of_find_compatible_node(NULL, NULL, - "fsl,mpc5121-i2c-ctrl"); - if (node_ctrl) { - ctrl = of_iomap(node_ctrl, 0); - if (ctrl) { - /* Interrupt enable bits for i2c-0/1/2: bit 24/26/28 */ - pval = of_get_property(node, "reg", NULL); - idx = (*pval & 0xff) / 0x20; - setbits32(ctrl, 1 << (24 + idx * 2)); - iounmap(ctrl); - } - of_node_put(node_ctrl); - } - - /* The clock setup for the 52xx works also fine for the 512x */ - mpc_i2c_setup_52xx(node, i2c, clock, prescaler); -} -#else /* CONFIG_PPC_MPC512x */ -static void __devinit mpc_i2c_setup_512x(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ -} -#endif /* CONFIG_PPC_MPC512x */ - -#ifdef CONFIG_FSL_SOC -static const struct mpc_i2c_divider mpc_i2c_dividers_8xxx[] __devinitconst = { - {160, 0x0120}, {192, 0x0121}, {224, 0x0122}, {256, 0x0123}, - {288, 0x0100}, {320, 0x0101}, {352, 0x0601}, {384, 0x0102}, - {416, 0x0602}, {448, 0x0126}, {480, 0x0103}, {512, 0x0127}, - {544, 0x0b03}, {576, 0x0104}, {608, 0x1603}, {640, 0x0105}, - {672, 0x2003}, {704, 0x0b05}, {736, 0x2b03}, {768, 0x0106}, - {800, 0x3603}, {832, 0x0b06}, {896, 0x012a}, {960, 0x0107}, - {1024, 0x012b}, {1088, 0x1607}, {1152, 0x0108}, {1216, 0x2b07}, - {1280, 0x0109}, {1408, 0x1609}, {1536, 0x010a}, {1664, 0x160a}, - {1792, 0x012e}, {1920, 0x010b}, {2048, 0x012f}, {2176, 0x2b0b}, - {2304, 0x010c}, {2560, 0x010d}, {2816, 0x2b0d}, {3072, 0x010e}, - {3328, 0x2b0e}, {3584, 0x0132}, {3840, 0x010f}, {4096, 0x0133}, - {4608, 0x0110}, {5120, 0x0111}, {6144, 0x0112}, {7168, 0x0136}, - {7680, 0x0113}, {8192, 0x0137}, {9216, 0x0114}, {10240, 0x0115}, - {12288, 0x0116}, {14336, 0x013a}, {15360, 0x0117}, {16384, 0x013b}, - {18432, 0x0118}, {20480, 0x0119}, {24576, 0x011a}, {28672, 0x013e}, - {30720, 0x011b}, {32768, 0x013f}, {36864, 0x011c}, {40960, 0x011d}, - {49152, 0x011e}, {61440, 0x011f} -}; - -static u32 __devinit mpc_i2c_get_sec_cfg_8xxx(void) -{ - struct device_node *node = NULL; - u32 __iomem *reg; - u32 val = 0; - - node = of_find_node_by_name(NULL, "global-utilities"); - if (node) { - const u32 *prop = of_get_property(node, "reg", NULL); - if (prop) { - /* - * Map and check POR Device Status Register 2 - * (PORDEVSR2) at 0xE0014 - */ - reg = ioremap(get_immrbase() + *prop + 0x14, 0x4); - if (!reg) - printk(KERN_ERR - "Error: couldn't map PORDEVSR2\n"); - else - val = in_be32(reg) & 0x00000080; /* sec-cfg */ - iounmap(reg); - } - } - if (node) - of_node_put(node); - - return val; -} - -static int __devinit mpc_i2c_get_fdr_8xxx(struct device_node *node, u32 clock, - u32 prescaler, u32 *real_clk) -{ - const struct mpc_i2c_divider *div = NULL; - u32 divider; - int i; - - if (clock == MPC_I2C_CLOCK_LEGACY) { - /* see below - default fdr = 0x1031 -> div = 16 * 3072 */ - *real_clk = fsl_get_sys_freq() / prescaler / (16 * 3072); - return -EINVAL; - } - - /* Determine proper divider value */ - if (of_device_is_compatible(node, "fsl,mpc8544-i2c")) - prescaler = mpc_i2c_get_sec_cfg_8xxx() ? 3 : 2; - if (!prescaler) - prescaler = 1; - - divider = fsl_get_sys_freq() / clock / prescaler; - - pr_debug("I2C: src_clock=%d clock=%d divider=%d\n", - fsl_get_sys_freq(), clock, divider); - - /* - * We want to choose an FDR/DFSR that generates an I2C bus speed that - * is equal to or lower than the requested speed. - */ - for (i = 0; i < ARRAY_SIZE(mpc_i2c_dividers_8xxx); i++) { - div = &mpc_i2c_dividers_8xxx[i]; - if (div->divider >= divider) - break; - } - - *real_clk = fsl_get_sys_freq() / prescaler / div->divider; - return div ? (int)div->fdr : -EINVAL; -} - -static void __devinit mpc_i2c_setup_8xxx(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ - int ret, fdr; - - if (clock == MPC_I2C_CLOCK_PRESERVE) { - dev_dbg(i2c->dev, "using dfsrr %d, fdr %d\n", - readb(i2c->base + MPC_I2C_DFSRR), - readb(i2c->base + MPC_I2C_FDR)); - return; - } - - ret = mpc_i2c_get_fdr_8xxx(node, clock, prescaler, &i2c->real_clk); - fdr = (ret >= 0) ? ret : 0x1031; /* backward compatibility */ - - writeb(fdr & 0xff, i2c->base + MPC_I2C_FDR); - writeb((fdr >> 8) & 0xff, i2c->base + MPC_I2C_DFSRR); - - if (ret >= 0) - dev_info(i2c->dev, "clock %d Hz (dfsrr=%d fdr=%d)\n", - i2c->real_clk, fdr >> 8, fdr & 0xff); -} - -#else /* !CONFIG_FSL_SOC */ -static void __devinit mpc_i2c_setup_8xxx(struct device_node *node, - struct mpc_i2c *i2c, - u32 clock, u32 prescaler) -{ -} -#endif /* CONFIG_FSL_SOC */ - -static void mpc_i2c_start(struct mpc_i2c *i2c) -{ - /* Clear arbitration */ - writeb(0, i2c->base + MPC_I2C_SR); - /* Start with MEN */ - writeccr(i2c, CCR_MEN); -} - -static void mpc_i2c_stop(struct mpc_i2c *i2c) -{ - writeccr(i2c, CCR_MEN); -} - -static int mpc_write(struct mpc_i2c *i2c, int target, - const u8 *data, int length, int restart) -{ - int i, result; - unsigned timeout = i2c->adap.timeout; - u32 flags = restart ? CCR_RSTA : 0; - - /* Start as master */ - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); - /* Write target byte */ - writeb((target << 1), i2c->base + MPC_I2C_DR); - - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; - - for (i = 0; i < length; i++) { - /* Write data byte */ - writeb(data[i], i2c->base + MPC_I2C_DR); - - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; - } - - return 0; -} - -static int mpc_read(struct mpc_i2c *i2c, int target, - u8 *data, int length, int restart, bool recv_len) -{ - unsigned timeout = i2c->adap.timeout; - int i, result; - u32 flags = restart ? CCR_RSTA : 0; - - /* Switch to read - restart */ - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags); - /* Write target address byte - this time with the read flag set */ - writeb((target << 1) | 1, i2c->base + MPC_I2C_DR); - - result = i2c_wait(i2c, timeout, 1); - if (result < 0) - return result; - - if (length) { - if (length == 1 && !recv_len) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK); - else - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA); - /* Dummy read */ - readb(i2c->base + MPC_I2C_DR); - } - - for (i = 0; i < length; i++) { - u8 byte; - - result = i2c_wait(i2c, timeout, 0); - if (result < 0) - return result; - - /* - * For block reads, we have to know the total length (1st byte) - * before we can determine if we are done. - */ - if (i || !recv_len) { - /* Generate txack on next to last byte */ - if (i == length - 2) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_TXAK); - /* Do not generate stop on last byte */ - if (i == length - 1) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_MTX); - } - - byte = readb(i2c->base + MPC_I2C_DR); - - /* - * Adjust length if first received byte is length. - * The length is 1 length byte plus actually data length - */ - if (i == 0 && recv_len) { - if (byte == 0 || byte > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - length += byte; - /* - * For block reads, generate txack here if data length - * is 1 byte (total length is 2 bytes). - */ - if (length == 2) - writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA - | CCR_TXAK); - } - data[i] = byte; - } - - return length; -} - -static int mpc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct i2c_msg *pmsg; - int i; - int ret = 0; - unsigned long orig_jiffies = jiffies; - struct mpc_i2c *i2c = i2c_get_adapdata(adap); - - mpc_i2c_start(i2c); - - /* Allow bus up to 1s to become not busy */ - while (readb(i2c->base + MPC_I2C_SR) & CSR_MBB) { - if (signal_pending(current)) { - dev_dbg(i2c->dev, "Interrupted\n"); - writeccr(i2c, 0); - return -EINTR; - } - if (time_after(jiffies, orig_jiffies + HZ)) { - u8 status = readb(i2c->base + MPC_I2C_SR); - - dev_dbg(i2c->dev, "timeout\n"); - if ((status & (CSR_MCF | CSR_MBB | CSR_RXAK)) != 0) { - writeb(status & ~CSR_MAL, - i2c->base + MPC_I2C_SR); - mpc_i2c_fixup(i2c); - } - return -EIO; - } - schedule(); - } - - for (i = 0; ret >= 0 && i < num; i++) { - pmsg = &msgs[i]; - dev_dbg(i2c->dev, - "Doing %s %d bytes to 0x%02x - %d of %d messages\n", - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num); - if (pmsg->flags & I2C_M_RD) { - bool recv_len = pmsg->flags & I2C_M_RECV_LEN; - - ret = mpc_read(i2c, pmsg->addr, pmsg->buf, pmsg->len, i, - recv_len); - if (recv_len && ret > 0) - pmsg->len = ret; - } else { - ret = - mpc_write(i2c, pmsg->addr, pmsg->buf, pmsg->len, i); - } - } - mpc_i2c_stop(i2c); - return (ret < 0) ? ret : num; -} - -static u32 mpc_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL - | I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL; -} - -static const struct i2c_algorithm mpc_algo = { - .master_xfer = mpc_xfer, - .functionality = mpc_functionality, -}; - -static struct i2c_adapter mpc_ops = { - .owner = THIS_MODULE, - .name = "MPC adapter", - .algo = &mpc_algo, - .timeout = HZ, -}; - -static const struct of_device_id mpc_i2c_of_match[]; -static int __devinit fsl_i2c_probe(struct platform_device *op) -{ - const struct of_device_id *match; - struct mpc_i2c *i2c; - const u32 *prop; - u32 clock = MPC_I2C_CLOCK_LEGACY; - int result = 0; - int plen; - - match = of_match_device(mpc_i2c_of_match, &op->dev); - if (!match) - return -EINVAL; - - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - i2c->dev = &op->dev; /* for debug and error output */ - - init_waitqueue_head(&i2c->queue); - - i2c->base = of_iomap(op->dev.of_node, 0); - if (!i2c->base) { - dev_err(i2c->dev, "failed to map controller\n"); - result = -ENOMEM; - goto fail_map; - } - - i2c->irq = irq_of_parse_and_map(op->dev.of_node, 0); - if (i2c->irq) { /* no i2c->irq implies polling */ - result = request_irq(i2c->irq, mpc_i2c_isr, - IRQF_SHARED, "i2c-mpc", i2c); - if (result < 0) { - dev_err(i2c->dev, "failed to attach interrupt\n"); - goto fail_request; - } - } - - if (of_get_property(op->dev.of_node, "fsl,preserve-clocking", NULL)) { - clock = MPC_I2C_CLOCK_PRESERVE; - } else { - prop = of_get_property(op->dev.of_node, "clock-frequency", - &plen); - if (prop && plen == sizeof(u32)) - clock = *prop; - } - - if (match->data) { - struct mpc_i2c_data *data = match->data; - data->setup(op->dev.of_node, i2c, clock, data->prescaler); - } else { - /* Backwards compatibility */ - if (of_get_property(op->dev.of_node, "dfsrr", NULL)) - mpc_i2c_setup_8xxx(op->dev.of_node, i2c, clock, 0); - } - - prop = of_get_property(op->dev.of_node, "fsl,timeout", &plen); - if (prop && plen == sizeof(u32)) { - mpc_ops.timeout = *prop * HZ / 1000000; - if (mpc_ops.timeout < 5) - mpc_ops.timeout = 5; - } - dev_info(i2c->dev, "timeout %u us\n", mpc_ops.timeout * 1000000 / HZ); - - dev_set_drvdata(&op->dev, i2c); - - i2c->adap = mpc_ops; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &op->dev; - i2c->adap.dev.of_node = of_node_get(op->dev.of_node); - - result = i2c_add_adapter(&i2c->adap); - if (result < 0) { - dev_err(i2c->dev, "failed to add adapter\n"); - goto fail_add; - } - of_i2c_register_devices(&i2c->adap); - - return result; - - fail_add: - dev_set_drvdata(&op->dev, NULL); - free_irq(i2c->irq, i2c); - fail_request: - irq_dispose_mapping(i2c->irq); - iounmap(i2c->base); - fail_map: - kfree(i2c); - return result; -}; - -static int __devexit fsl_i2c_remove(struct platform_device *op) -{ - struct mpc_i2c *i2c = dev_get_drvdata(&op->dev); - - i2c_del_adapter(&i2c->adap); - dev_set_drvdata(&op->dev, NULL); - - if (i2c->irq) - free_irq(i2c->irq, i2c); - - irq_dispose_mapping(i2c->irq); - iounmap(i2c->base); - kfree(i2c); - return 0; -}; - -static struct mpc_i2c_data mpc_i2c_data_512x __devinitdata = { - .setup = mpc_i2c_setup_512x, -}; - -static struct mpc_i2c_data mpc_i2c_data_52xx __devinitdata = { - .setup = mpc_i2c_setup_52xx, -}; - -static struct mpc_i2c_data mpc_i2c_data_8313 __devinitdata = { - .setup = mpc_i2c_setup_8xxx, -}; - -static struct mpc_i2c_data mpc_i2c_data_8543 __devinitdata = { - .setup = mpc_i2c_setup_8xxx, - .prescaler = 2, -}; - -static struct mpc_i2c_data mpc_i2c_data_8544 __devinitdata = { - .setup = mpc_i2c_setup_8xxx, - .prescaler = 3, -}; - -static const struct of_device_id mpc_i2c_of_match[] = { - {.compatible = "mpc5200-i2c", .data = &mpc_i2c_data_52xx, }, - {.compatible = "fsl,mpc5200b-i2c", .data = &mpc_i2c_data_52xx, }, - {.compatible = "fsl,mpc5200-i2c", .data = &mpc_i2c_data_52xx, }, - {.compatible = "fsl,mpc5121-i2c", .data = &mpc_i2c_data_512x, }, - {.compatible = "fsl,mpc8313-i2c", .data = &mpc_i2c_data_8313, }, - {.compatible = "fsl,mpc8543-i2c", .data = &mpc_i2c_data_8543, }, - {.compatible = "fsl,mpc8544-i2c", .data = &mpc_i2c_data_8544, }, - /* Backward compatibility */ - {.compatible = "fsl-i2c", }, - {}, -}; -MODULE_DEVICE_TABLE(of, mpc_i2c_of_match); - -/* Structure for a device driver */ -static struct platform_driver mpc_i2c_driver = { - .probe = fsl_i2c_probe, - .remove = __devexit_p(fsl_i2c_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRV_NAME, - .of_match_table = mpc_i2c_of_match, - }, -}; - -module_platform_driver(mpc_i2c_driver); - -MODULE_AUTHOR("Adrian Cox <adrian@humboldt.co.uk>"); -MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and " - "MPC824x/83xx/85xx/86xx/512x/52xx processors"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mv64xxx.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-mv64xxx.c deleted file mode 100644 index 4f44a330..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mv64xxx.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Driver for the i2c controller on the Marvell line of host bridges - * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family). - * - * Author: Mark A. Greer <mgreer@mvista.com> - * - * 2005 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/module.h> -#include <linux/spinlock.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/mv643xx_i2c.h> -#include <linux/platform_device.h> -#include <linux/io.h> - -/* Register defines */ -#define MV64XXX_I2C_REG_SLAVE_ADDR 0x00 -#define MV64XXX_I2C_REG_DATA 0x04 -#define MV64XXX_I2C_REG_CONTROL 0x08 -#define MV64XXX_I2C_REG_STATUS 0x0c -#define MV64XXX_I2C_REG_BAUD 0x0c -#define MV64XXX_I2C_REG_EXT_SLAVE_ADDR 0x10 -#define MV64XXX_I2C_REG_SOFT_RESET 0x1c - -#define MV64XXX_I2C_REG_CONTROL_ACK 0x00000004 -#define MV64XXX_I2C_REG_CONTROL_IFLG 0x00000008 -#define MV64XXX_I2C_REG_CONTROL_STOP 0x00000010 -#define MV64XXX_I2C_REG_CONTROL_START 0x00000020 -#define MV64XXX_I2C_REG_CONTROL_TWSIEN 0x00000040 -#define MV64XXX_I2C_REG_CONTROL_INTEN 0x00000080 - -/* Ctlr status values */ -#define MV64XXX_I2C_STATUS_BUS_ERR 0x00 -#define MV64XXX_I2C_STATUS_MAST_START 0x08 -#define MV64XXX_I2C_STATUS_MAST_REPEAT_START 0x10 -#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 -#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 -#define MV64XXX_I2C_STATUS_MAST_WR_ACK 0x28 -#define MV64XXX_I2C_STATUS_MAST_WR_NO_ACK 0x30 -#define MV64XXX_I2C_STATUS_MAST_LOST_ARB 0x38 -#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 -#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 -#define MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK 0x50 -#define MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 -#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 -#define MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 -#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 -#define MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 -#define MV64XXX_I2C_STATUS_NO_STATUS 0xf8 - -/* Driver states */ -enum { - MV64XXX_I2C_STATE_INVALID, - MV64XXX_I2C_STATE_IDLE, - MV64XXX_I2C_STATE_WAITING_FOR_START_COND, - MV64XXX_I2C_STATE_WAITING_FOR_RESTART, - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK, - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK, - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK, - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA, -}; - -/* Driver actions */ -enum { - MV64XXX_I2C_ACTION_INVALID, - MV64XXX_I2C_ACTION_CONTINUE, - MV64XXX_I2C_ACTION_SEND_START, - MV64XXX_I2C_ACTION_SEND_RESTART, - MV64XXX_I2C_ACTION_SEND_ADDR_1, - MV64XXX_I2C_ACTION_SEND_ADDR_2, - MV64XXX_I2C_ACTION_SEND_DATA, - MV64XXX_I2C_ACTION_RCV_DATA, - MV64XXX_I2C_ACTION_RCV_DATA_STOP, - MV64XXX_I2C_ACTION_SEND_STOP, -}; - -struct mv64xxx_i2c_data { - int irq; - u32 state; - u32 action; - u32 aborting; - u32 cntl_bits; - void __iomem *reg_base; - u32 reg_base_p; - u32 reg_size; - u32 addr1; - u32 addr2; - u32 bytes_left; - u32 byte_posn; - u32 send_stop; - u32 block; - int rc; - u32 freq_m; - u32 freq_n; - wait_queue_head_t waitq; - spinlock_t lock; - struct i2c_msg *msg; - struct i2c_adapter adapter; -}; - -/* - ***************************************************************************** - * - * Finite State Machine & Interrupt Routines - * - ***************************************************************************** - */ - -/* Reset hardware and initialize FSM */ -static void -mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) -{ - writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SOFT_RESET); - writel((((drv_data->freq_m & 0xf) << 3) | (drv_data->freq_n & 0x7)), - drv_data->reg_base + MV64XXX_I2C_REG_BAUD); - writel(0, drv_data->reg_base + MV64XXX_I2C_REG_SLAVE_ADDR); - writel(0, drv_data->reg_base + MV64XXX_I2C_REG_EXT_SLAVE_ADDR); - writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - drv_data->state = MV64XXX_I2C_STATE_IDLE; -} - -static void -mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) -{ - /* - * If state is idle, then this is likely the remnants of an old - * operation that driver has given up on or the user has killed. - * If so, issue the stop condition and go to idle. - */ - if (drv_data->state == MV64XXX_I2C_STATE_IDLE) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - return; - } - - /* The status from the ctlr [mostly] tells us what to do next */ - switch (status) { - /* Start condition interrupt */ - case MV64XXX_I2C_STATUS_MAST_START: /* 0x08 */ - case MV64XXX_I2C_STATUS_MAST_REPEAT_START: /* 0x10 */ - drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; - break; - - /* Performing a write */ - case MV64XXX_I2C_STATUS_MAST_WR_ADDR_ACK: /* 0x18 */ - if (drv_data->msg->flags & I2C_M_TEN) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; - break; - } - /* FALLTHRU */ - case MV64XXX_I2C_STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ - case MV64XXX_I2C_STATUS_MAST_WR_ACK: /* 0x28 */ - if ((drv_data->bytes_left == 0) - || (drv_data->aborting - && (drv_data->byte_posn != 0))) { - if (drv_data->send_stop) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; - } else { - drv_data->action = - MV64XXX_I2C_ACTION_SEND_RESTART; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_RESTART; - } - } else { - drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; - drv_data->bytes_left--; - } - break; - - /* Performing a read */ - case MV64XXX_I2C_STATUS_MAST_RD_ADDR_ACK: /* 40 */ - if (drv_data->msg->flags & I2C_M_TEN) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_2; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_2_ACK; - break; - } - /* FALLTHRU */ - case MV64XXX_I2C_STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ - if (drv_data->bytes_left == 0) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; - break; - } - /* FALLTHRU */ - case MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK: /* 0x50 */ - if (status != MV64XXX_I2C_STATUS_MAST_RD_DATA_ACK) - drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; - else { - drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA; - drv_data->bytes_left--; - } - drv_data->state = MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; - - if ((drv_data->bytes_left == 1) || drv_data->aborting) - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_ACK; - break; - - case MV64XXX_I2C_STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */ - drv_data->action = MV64XXX_I2C_ACTION_RCV_DATA_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; - break; - - case MV64XXX_I2C_STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */ - case MV64XXX_I2C_STATUS_MAST_WR_NO_ACK: /* 30 */ - case MV64XXX_I2C_STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */ - /* Doesn't seem to be a device at other end */ - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - drv_data->state = MV64XXX_I2C_STATE_IDLE; - drv_data->rc = -ENODEV; - break; - - default: - dev_err(&drv_data->adapter.dev, - "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " - "status: 0x%x, addr: 0x%x, flags: 0x%x\n", - drv_data->state, status, drv_data->msg->addr, - drv_data->msg->flags); - drv_data->action = MV64XXX_I2C_ACTION_SEND_STOP; - mv64xxx_i2c_hw_init(drv_data); - drv_data->rc = -EIO; - } -} - -static void -mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) -{ - switch(drv_data->action) { - case MV64XXX_I2C_ACTION_SEND_RESTART: - drv_data->cntl_bits |= MV64XXX_I2C_REG_CONTROL_START; - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - drv_data->block = 0; - wake_up_interruptible(&drv_data->waitq); - break; - - case MV64XXX_I2C_ACTION_CONTINUE: - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_SEND_START: - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_START, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_SEND_ADDR_1: - writel(drv_data->addr1, - drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_SEND_ADDR_2: - writel(drv_data->addr2, - drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_SEND_DATA: - writel(drv_data->msg->buf[drv_data->byte_posn++], - drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_RCV_DATA: - drv_data->msg->buf[drv_data->byte_posn++] = - readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); - writel(drv_data->cntl_bits, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - break; - - case MV64XXX_I2C_ACTION_RCV_DATA_STOP: - drv_data->msg->buf[drv_data->byte_posn++] = - readl(drv_data->reg_base + MV64XXX_I2C_REG_DATA); - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - drv_data->block = 0; - wake_up_interruptible(&drv_data->waitq); - break; - - case MV64XXX_I2C_ACTION_INVALID: - default: - dev_err(&drv_data->adapter.dev, - "mv64xxx_i2c_do_action: Invalid action: %d\n", - drv_data->action); - drv_data->rc = -EIO; - /* FALLTHRU */ - case MV64XXX_I2C_ACTION_SEND_STOP: - drv_data->cntl_bits &= ~MV64XXX_I2C_REG_CONTROL_INTEN; - writel(drv_data->cntl_bits | MV64XXX_I2C_REG_CONTROL_STOP, - drv_data->reg_base + MV64XXX_I2C_REG_CONTROL); - drv_data->block = 0; - wake_up_interruptible(&drv_data->waitq); - break; - } -} - -static irqreturn_t -mv64xxx_i2c_intr(int irq, void *dev_id) -{ - struct mv64xxx_i2c_data *drv_data = dev_id; - unsigned long flags; - u32 status; - irqreturn_t rc = IRQ_NONE; - - spin_lock_irqsave(&drv_data->lock, flags); - while (readl(drv_data->reg_base + MV64XXX_I2C_REG_CONTROL) & - MV64XXX_I2C_REG_CONTROL_IFLG) { - status = readl(drv_data->reg_base + MV64XXX_I2C_REG_STATUS); - mv64xxx_i2c_fsm(drv_data, status); - mv64xxx_i2c_do_action(drv_data); - rc = IRQ_HANDLED; - } - spin_unlock_irqrestore(&drv_data->lock, flags); - - return rc; -} - -/* - ***************************************************************************** - * - * I2C Msg Execution Routines - * - ***************************************************************************** - */ -static void -mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, - struct i2c_msg *msg) -{ - u32 dir = 0; - - drv_data->msg = msg; - drv_data->byte_posn = 0; - drv_data->bytes_left = msg->len; - drv_data->aborting = 0; - drv_data->rc = 0; - drv_data->cntl_bits = MV64XXX_I2C_REG_CONTROL_ACK | - MV64XXX_I2C_REG_CONTROL_INTEN | MV64XXX_I2C_REG_CONTROL_TWSIEN; - - if (msg->flags & I2C_M_RD) - dir = 1; - - if (msg->flags & I2C_M_TEN) { - drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; - drv_data->addr2 = (u32)msg->addr & 0xff; - } else { - drv_data->addr1 = ((u32)msg->addr & 0x7f) << 1 | dir; - drv_data->addr2 = 0; - } -} - -static void -mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) -{ - long time_left; - unsigned long flags; - char abort = 0; - - time_left = wait_event_interruptible_timeout(drv_data->waitq, - !drv_data->block, drv_data->adapter.timeout); - - spin_lock_irqsave(&drv_data->lock, flags); - if (!time_left) { /* Timed out */ - drv_data->rc = -ETIMEDOUT; - abort = 1; - } else if (time_left < 0) { /* Interrupted/Error */ - drv_data->rc = time_left; /* errno value */ - abort = 1; - } - - if (abort && drv_data->block) { - drv_data->aborting = 1; - spin_unlock_irqrestore(&drv_data->lock, flags); - - time_left = wait_event_timeout(drv_data->waitq, - !drv_data->block, drv_data->adapter.timeout); - - if ((time_left <= 0) && drv_data->block) { - drv_data->state = MV64XXX_I2C_STATE_IDLE; - dev_err(&drv_data->adapter.dev, - "mv64xxx: I2C bus locked, block: %d, " - "time_left: %d\n", drv_data->block, - (int)time_left); - mv64xxx_i2c_hw_init(drv_data); - } - } else - spin_unlock_irqrestore(&drv_data->lock, flags); -} - -static int -mv64xxx_i2c_execute_msg(struct mv64xxx_i2c_data *drv_data, struct i2c_msg *msg, - int is_first, int is_last) -{ - unsigned long flags; - - spin_lock_irqsave(&drv_data->lock, flags); - mv64xxx_i2c_prepare_for_io(drv_data, msg); - - if (unlikely(msg->flags & I2C_M_NOSTART)) { /* Skip start/addr phases */ - if (drv_data->msg->flags & I2C_M_RD) { - /* No action to do, wait for slave to send a byte */ - drv_data->action = MV64XXX_I2C_ACTION_CONTINUE; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_DATA; - } else { - drv_data->action = MV64XXX_I2C_ACTION_SEND_DATA; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_SLAVE_ACK; - drv_data->bytes_left--; - } - } else { - if (is_first) { - drv_data->action = MV64XXX_I2C_ACTION_SEND_START; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_START_COND; - } else { - drv_data->action = MV64XXX_I2C_ACTION_SEND_ADDR_1; - drv_data->state = - MV64XXX_I2C_STATE_WAITING_FOR_ADDR_1_ACK; - } - } - - drv_data->send_stop = is_last; - drv_data->block = 1; - mv64xxx_i2c_do_action(drv_data); - spin_unlock_irqrestore(&drv_data->lock, flags); - - mv64xxx_i2c_wait_for_completion(drv_data); - return drv_data->rc; -} - -/* - ***************************************************************************** - * - * I2C Core Support Routines (Interface to higher level I2C code) - * - ***************************************************************************** - */ -static u32 -mv64xxx_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL; -} - -static int -mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct mv64xxx_i2c_data *drv_data = i2c_get_adapdata(adap); - int i, rc; - - for (i = 0; i < num; i++) { - rc = mv64xxx_i2c_execute_msg(drv_data, &msgs[i], - i == 0, i + 1 == num); - if (rc < 0) - return rc; - } - - return num; -} - -static const struct i2c_algorithm mv64xxx_i2c_algo = { - .master_xfer = mv64xxx_i2c_xfer, - .functionality = mv64xxx_i2c_functionality, -}; - -/* - ***************************************************************************** - * - * Driver Interface & Early Init Routines - * - ***************************************************************************** - */ -static int __devinit -mv64xxx_i2c_map_regs(struct platform_device *pd, - struct mv64xxx_i2c_data *drv_data) -{ - int size; - struct resource *r = platform_get_resource(pd, IORESOURCE_MEM, 0); - - if (!r) - return -ENODEV; - - size = resource_size(r); - - if (!request_mem_region(r->start, size, drv_data->adapter.name)) - return -EBUSY; - - drv_data->reg_base = ioremap(r->start, size); - drv_data->reg_base_p = r->start; - drv_data->reg_size = size; - - return 0; -} - -static void -mv64xxx_i2c_unmap_regs(struct mv64xxx_i2c_data *drv_data) -{ - if (drv_data->reg_base) { - iounmap(drv_data->reg_base); - release_mem_region(drv_data->reg_base_p, drv_data->reg_size); - } - - drv_data->reg_base = NULL; - drv_data->reg_base_p = 0; -} - -static int __devinit -mv64xxx_i2c_probe(struct platform_device *pd) -{ - struct mv64xxx_i2c_data *drv_data; - struct mv64xxx_i2c_pdata *pdata = pd->dev.platform_data; - int rc; - - if ((pd->id != 0) || !pdata) - return -ENODEV; - - drv_data = kzalloc(sizeof(struct mv64xxx_i2c_data), GFP_KERNEL); - if (!drv_data) - return -ENOMEM; - - if (mv64xxx_i2c_map_regs(pd, drv_data)) { - rc = -ENODEV; - goto exit_kfree; - } - - strlcpy(drv_data->adapter.name, MV64XXX_I2C_CTLR_NAME " adapter", - sizeof(drv_data->adapter.name)); - - init_waitqueue_head(&drv_data->waitq); - spin_lock_init(&drv_data->lock); - - drv_data->freq_m = pdata->freq_m; - drv_data->freq_n = pdata->freq_n; - drv_data->irq = platform_get_irq(pd, 0); - if (drv_data->irq < 0) { - rc = -ENXIO; - goto exit_unmap_regs; - } - drv_data->adapter.dev.parent = &pd->dev; - drv_data->adapter.algo = &mv64xxx_i2c_algo; - drv_data->adapter.owner = THIS_MODULE; - drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout); - drv_data->adapter.nr = pd->id; - platform_set_drvdata(pd, drv_data); - i2c_set_adapdata(&drv_data->adapter, drv_data); - - mv64xxx_i2c_hw_init(drv_data); - - if (request_irq(drv_data->irq, mv64xxx_i2c_intr, 0, - MV64XXX_I2C_CTLR_NAME, drv_data)) { - dev_err(&drv_data->adapter.dev, - "mv64xxx: Can't register intr handler irq: %d\n", - drv_data->irq); - rc = -EINVAL; - goto exit_unmap_regs; - } else if ((rc = i2c_add_numbered_adapter(&drv_data->adapter)) != 0) { - dev_err(&drv_data->adapter.dev, - "mv64xxx: Can't add i2c adapter, rc: %d\n", -rc); - goto exit_free_irq; - } - - return 0; - - exit_free_irq: - free_irq(drv_data->irq, drv_data); - exit_unmap_regs: - mv64xxx_i2c_unmap_regs(drv_data); - exit_kfree: - kfree(drv_data); - return rc; -} - -static int __devexit -mv64xxx_i2c_remove(struct platform_device *dev) -{ - struct mv64xxx_i2c_data *drv_data = platform_get_drvdata(dev); - int rc; - - rc = i2c_del_adapter(&drv_data->adapter); - free_irq(drv_data->irq, drv_data); - mv64xxx_i2c_unmap_regs(drv_data); - kfree(drv_data); - - return rc; -} - -static struct platform_driver mv64xxx_i2c_driver = { - .probe = mv64xxx_i2c_probe, - .remove = __devexit_p(mv64xxx_i2c_remove), - .driver = { - .owner = THIS_MODULE, - .name = MV64XXX_I2C_CTLR_NAME, - }, -}; - -module_platform_driver(mv64xxx_i2c_driver); - -MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>"); -MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mxs.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-mxs.c deleted file mode 100644 index 76b8af44..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-mxs.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Freescale MXS I2C bus driver - * - * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K. - * - * based on a (non-working) driver which was: - * - * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved. - * - * TODO: add dma-support if platform-support for it is available - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - */ - -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/completion.h> -#include <linux/platform_device.h> -#include <linux/jiffies.h> -#include <linux/io.h> - -#include <mach/common.h> - -#define DRIVER_NAME "mxs-i2c" - -#define MXS_I2C_CTRL0 (0x00) -#define MXS_I2C_CTRL0_SET (0x04) - -#define MXS_I2C_CTRL0_SFTRST 0x80000000 -#define MXS_I2C_CTRL0_SEND_NAK_ON_LAST 0x02000000 -#define MXS_I2C_CTRL0_RETAIN_CLOCK 0x00200000 -#define MXS_I2C_CTRL0_POST_SEND_STOP 0x00100000 -#define MXS_I2C_CTRL0_PRE_SEND_START 0x00080000 -#define MXS_I2C_CTRL0_MASTER_MODE 0x00020000 -#define MXS_I2C_CTRL0_DIRECTION 0x00010000 -#define MXS_I2C_CTRL0_XFER_COUNT(v) ((v) & 0x0000FFFF) - -#define MXS_I2C_CTRL1 (0x40) -#define MXS_I2C_CTRL1_SET (0x44) -#define MXS_I2C_CTRL1_CLR (0x48) - -#define MXS_I2C_CTRL1_BUS_FREE_IRQ 0x80 -#define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ 0x40 -#define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ 0x20 -#define MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ 0x10 -#define MXS_I2C_CTRL1_EARLY_TERM_IRQ 0x08 -#define MXS_I2C_CTRL1_MASTER_LOSS_IRQ 0x04 -#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ 0x02 -#define MXS_I2C_CTRL1_SLAVE_IRQ 0x01 - -#define MXS_I2C_IRQ_MASK (MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | \ - MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ | \ - MXS_I2C_CTRL1_EARLY_TERM_IRQ | \ - MXS_I2C_CTRL1_MASTER_LOSS_IRQ | \ - MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \ - MXS_I2C_CTRL1_SLAVE_IRQ) - -#define MXS_I2C_QUEUECTRL (0x60) -#define MXS_I2C_QUEUECTRL_SET (0x64) -#define MXS_I2C_QUEUECTRL_CLR (0x68) - -#define MXS_I2C_QUEUECTRL_QUEUE_RUN 0x20 -#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE 0x04 - -#define MXS_I2C_QUEUESTAT (0x70) -#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY 0x00002000 -#define MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK 0x0000001F - -#define MXS_I2C_QUEUECMD (0x80) - -#define MXS_I2C_QUEUEDATA (0x90) - -#define MXS_I2C_DATA (0xa0) - - -#define MXS_CMD_I2C_SELECT (MXS_I2C_CTRL0_RETAIN_CLOCK | \ - MXS_I2C_CTRL0_PRE_SEND_START | \ - MXS_I2C_CTRL0_MASTER_MODE | \ - MXS_I2C_CTRL0_DIRECTION | \ - MXS_I2C_CTRL0_XFER_COUNT(1)) - -#define MXS_CMD_I2C_WRITE (MXS_I2C_CTRL0_PRE_SEND_START | \ - MXS_I2C_CTRL0_MASTER_MODE | \ - MXS_I2C_CTRL0_DIRECTION) - -#define MXS_CMD_I2C_READ (MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \ - MXS_I2C_CTRL0_MASTER_MODE) - -/** - * struct mxs_i2c_dev - per device, private MXS-I2C data - * - * @dev: driver model device node - * @regs: IO registers pointer - * @cmd_complete: completion object for transaction wait - * @cmd_err: error code for last transaction - * @adapter: i2c subsystem adapter node - */ -struct mxs_i2c_dev { - struct device *dev; - void __iomem *regs; - struct completion cmd_complete; - u32 cmd_err; - struct i2c_adapter adapter; -}; - -/* - * TODO: check if calls to here are really needed. If not, we could get rid of - * mxs_reset_block and the mach-dependency. Needs an I2C analyzer, probably. - */ -static void mxs_i2c_reset(struct mxs_i2c_dev *i2c) -{ - mxs_reset_block(i2c->regs); - writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET); - writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE, - i2c->regs + MXS_I2C_QUEUECTRL_SET); -} - -static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len, - int flags) -{ - u32 data; - - writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD); - - data = (addr << 1) | I2C_SMBUS_READ; - writel(data, i2c->regs + MXS_I2C_DATA); - - data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); -} - -static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c, - u8 addr, u8 *buf, int len, int flags) -{ - u32 data; - int i, shifts_left; - - data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags; - writel(data, i2c->regs + MXS_I2C_QUEUECMD); - - /* - * We have to copy the slave address (u8) and buffer (arbitrary number - * of u8) into the data register (u32). To achieve that, the u8 are put - * into the MSBs of 'data' which is then shifted for the next u8. When - * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32 - * looks like this: - * - * 3 2 1 0 - * 10987654|32109876|54321098|76543210 - * --------+--------+--------+-------- - * buffer+2|buffer+1|buffer+0|slave_addr - */ - - data = ((addr << 1) | I2C_SMBUS_WRITE) << 24; - - for (i = 0; i < len; i++) { - data >>= 8; - data |= buf[i] << 24; - if ((i & 3) == 2) - writel(data, i2c->regs + MXS_I2C_DATA); - } - - /* Write out the remaining bytes if any */ - shifts_left = 24 - (i & 3) * 8; - if (shifts_left) - writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA); -} - -/* - * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the - * rd_threshold to 1). Couldn't get this to work, though. - */ -static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c) -{ - unsigned long timeout = jiffies + msecs_to_jiffies(1000); - - while (readl(i2c->regs + MXS_I2C_QUEUESTAT) - & MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) { - if (time_after(jiffies, timeout)) - return -ETIMEDOUT; - cond_resched(); - } - - return 0; -} - -static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len) -{ - u32 data; - int i; - - for (i = 0; i < len; i++) { - if ((i & 3) == 0) { - if (mxs_i2c_wait_for_data(i2c)) - return -ETIMEDOUT; - data = readl(i2c->regs + MXS_I2C_QUEUEDATA); - } - buf[i] = data & 0xff; - data >>= 8; - } - - return 0; -} - -/* - * Low level master read/write transaction. - */ -static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, - int stop) -{ - struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap); - int ret; - int flags; - - dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", - msg->addr, msg->len, msg->flags, stop); - - if (msg->len == 0) - return -EINVAL; - - init_completion(&i2c->cmd_complete); - i2c->cmd_err = 0; - - flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0; - - if (msg->flags & I2C_M_RD) - mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags); - else - mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len, - flags); - - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_SET); - - ret = wait_for_completion_timeout(&i2c->cmd_complete, - msecs_to_jiffies(1000)); - if (ret == 0) - goto timeout; - - if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) { - ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len); - if (ret) - goto timeout; - } - - if (i2c->cmd_err == -ENXIO) - mxs_i2c_reset(i2c); - else - writel(MXS_I2C_QUEUECTRL_QUEUE_RUN, - i2c->regs + MXS_I2C_QUEUECTRL_CLR); - - dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err); - - return i2c->cmd_err; - -timeout: - dev_dbg(i2c->dev, "Timeout!\n"); - mxs_i2c_reset(i2c); - return -ETIMEDOUT; -} - -static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - int num) -{ - int i; - int err; - - for (i = 0; i < num; i++) { - err = mxs_i2c_xfer_msg(adap, &msgs[i], i == (num - 1)); - if (err) - return err; - } - - return num; -} - -static u32 mxs_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -} - -static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id) -{ - struct mxs_i2c_dev *i2c = dev_id; - u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK; - bool is_last_cmd; - - if (!stat) - return IRQ_NONE; - - if (stat & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ) - i2c->cmd_err = -ENXIO; - else if (stat & (MXS_I2C_CTRL1_EARLY_TERM_IRQ | - MXS_I2C_CTRL1_MASTER_LOSS_IRQ | - MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ)) - /* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */ - i2c->cmd_err = -EIO; - - is_last_cmd = (readl(i2c->regs + MXS_I2C_QUEUESTAT) & - MXS_I2C_QUEUESTAT_WRITE_QUEUE_CNT_MASK) == 0; - - if (is_last_cmd || i2c->cmd_err) - complete(&i2c->cmd_complete); - - writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR); - - return IRQ_HANDLED; -} - -static const struct i2c_algorithm mxs_i2c_algo = { - .master_xfer = mxs_i2c_xfer, - .functionality = mxs_i2c_func, -}; - -static int __devinit mxs_i2c_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct mxs_i2c_dev *i2c; - struct i2c_adapter *adap; - struct resource *res; - resource_size_t res_size; - int err, irq; - - i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENOENT; - - res_size = resource_size(res); - if (!devm_request_mem_region(dev, res->start, res_size, res->name)) - return -EBUSY; - - i2c->regs = devm_ioremap_nocache(dev, res->start, res_size); - if (!i2c->regs) - return -EBUSY; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c); - if (err) - return err; - - i2c->dev = dev; - platform_set_drvdata(pdev, i2c); - - /* Do reset to enforce correct startup after pinmuxing */ - mxs_i2c_reset(i2c); - - adap = &i2c->adapter; - strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name)); - adap->owner = THIS_MODULE; - adap->algo = &mxs_i2c_algo; - adap->dev.parent = dev; - adap->nr = pdev->id; - i2c_set_adapdata(adap, i2c); - err = i2c_add_numbered_adapter(adap); - if (err) { - dev_err(dev, "Failed to add adapter (%d)\n", err); - writel(MXS_I2C_CTRL0_SFTRST, - i2c->regs + MXS_I2C_CTRL0_SET); - return err; - } - - return 0; -} - -static int __devexit mxs_i2c_remove(struct platform_device *pdev) -{ - struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev); - int ret; - - ret = i2c_del_adapter(&i2c->adapter); - if (ret) - return -EBUSY; - - writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver mxs_i2c_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .remove = __devexit_p(mxs_i2c_remove), -}; - -static int __init mxs_i2c_init(void) -{ - return platform_driver_probe(&mxs_i2c_driver, mxs_i2c_probe); -} -subsys_initcall(mxs_i2c_init); - -static void __exit mxs_i2c_exit(void) -{ - platform_driver_unregister(&mxs_i2c_driver); -} -module_exit(mxs_i2c_exit); - -MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); -MODULE_DESCRIPTION("MXS I2C Bus Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2-s4985.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2-s4985.c deleted file mode 100644 index 29015eb9..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2-s4985.c +++ /dev/null @@ -1,257 +0,0 @@ -/* - * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard - * - * Copyright (C) 2008 Jean Delvare <khali@linux-fr.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* - * We select the channels by sending commands to the Philips - * PCA9556 chip at I2C address 0x18. The main adapter is used for - * the non-multiplexed part of the bus, and 4 virtual adapters - * are defined for the multiplexed addresses: 0x50-0x53 (memory - * module EEPROM) located on channels 1-4. We define one virtual - * adapter per CPU, which corresponds to one multiplexed channel: - * CPU0: virtual adapter 1, channel 1 - * CPU1: virtual adapter 2, channel 2 - * CPU2: virtual adapter 3, channel 3 - * CPU3: virtual adapter 4, channel 4 - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/mutex.h> - -extern struct i2c_adapter *nforce2_smbus; - -static struct i2c_adapter *s4985_adapter; -static struct i2c_algorithm *s4985_algo; - -/* Wrapper access functions for multiplexed SMBus */ -static DEFINE_MUTEX(nforce2_lock); - -static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - int error; - - /* We exclude the multiplexed addresses */ - if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30 - || addr == 0x18) - return -ENXIO; - - mutex_lock(&nforce2_lock); - error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - mutex_unlock(&nforce2_lock); - - return error; -} - -/* We remember the last used channels combination so as to only switch - channels when it is really needed. This greatly reduces the SMBus - overhead, but also assumes that nobody will be writing to the PCA9556 - in our back. */ -static u8 last_channels; - -static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data, - u8 channels) -{ - int error; - - /* We exclude the non-multiplexed addresses */ - if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30) - return -ENXIO; - - mutex_lock(&nforce2_lock); - if (last_channels != channels) { - union i2c_smbus_data mplxdata; - mplxdata.byte = channels; - - error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0, - I2C_SMBUS_WRITE, 0x01, - I2C_SMBUS_BYTE_DATA, - &mplxdata); - if (error) - goto UNLOCK; - last_channels = channels; - } - error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write, - command, size, data); - -UNLOCK: - mutex_unlock(&nforce2_lock); - return error; -} - -static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - /* CPU0: channel 1 enabled */ - return nforce2_access_channel(adap, addr, flags, read_write, command, - size, data, 0x02); -} - -static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - /* CPU1: channel 2 enabled */ - return nforce2_access_channel(adap, addr, flags, read_write, command, - size, data, 0x04); -} - -static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - /* CPU2: channel 3 enabled */ - return nforce2_access_channel(adap, addr, flags, read_write, command, - size, data, 0x08); -} - -static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, - union i2c_smbus_data *data) -{ - /* CPU3: channel 4 enabled */ - return nforce2_access_channel(adap, addr, flags, read_write, command, - size, data, 0x10); -} - -static int __init nforce2_s4985_init(void) -{ - int i, error; - union i2c_smbus_data ioconfig; - - if (!nforce2_smbus) - return -ENODEV; - - /* Configure the PCA9556 multiplexer */ - ioconfig.byte = 0x00; /* All I/O to output mode */ - error = i2c_smbus_xfer(nforce2_smbus, 0x18, 0, I2C_SMBUS_WRITE, 0x03, - I2C_SMBUS_BYTE_DATA, &ioconfig); - if (error) { - dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n"); - error = -EIO; - goto ERROR0; - } - - /* Unregister physical bus */ - error = i2c_del_adapter(nforce2_smbus); - if (error) { - dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n"); - goto ERROR0; - } - - printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n"); - /* Define the 5 virtual adapters and algorithms structures */ - s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL); - if (!s4985_adapter) { - error = -ENOMEM; - goto ERROR1; - } - s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL); - if (!s4985_algo) { - error = -ENOMEM; - goto ERROR2; - } - - /* Fill in the new structures */ - s4985_algo[0] = *(nforce2_smbus->algo); - s4985_algo[0].smbus_xfer = nforce2_access_virt0; - s4985_adapter[0] = *nforce2_smbus; - s4985_adapter[0].algo = s4985_algo; - s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent; - for (i = 1; i < 5; i++) { - s4985_algo[i] = *(nforce2_smbus->algo); - s4985_adapter[i] = *nforce2_smbus; - snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name), - "SMBus nForce2 adapter (CPU%d)", i - 1); - s4985_adapter[i].algo = s4985_algo + i; - s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent; - } - s4985_algo[1].smbus_xfer = nforce2_access_virt1; - s4985_algo[2].smbus_xfer = nforce2_access_virt2; - s4985_algo[3].smbus_xfer = nforce2_access_virt3; - s4985_algo[4].smbus_xfer = nforce2_access_virt4; - - /* Register virtual adapters */ - for (i = 0; i < 5; i++) { - error = i2c_add_adapter(s4985_adapter + i); - if (error) { - printk(KERN_ERR "i2c-nforce2-s4985: " - "Virtual adapter %d registration " - "failed, module not inserted\n", i); - for (i--; i >= 0; i--) - i2c_del_adapter(s4985_adapter + i); - goto ERROR3; - } - } - - return 0; - -ERROR3: - kfree(s4985_algo); - s4985_algo = NULL; -ERROR2: - kfree(s4985_adapter); - s4985_adapter = NULL; -ERROR1: - /* Restore physical bus */ - i2c_add_adapter(nforce2_smbus); -ERROR0: - return error; -} - -static void __exit nforce2_s4985_exit(void) -{ - if (s4985_adapter) { - int i; - - for (i = 0; i < 5; i++) - i2c_del_adapter(s4985_adapter+i); - kfree(s4985_adapter); - s4985_adapter = NULL; - } - kfree(s4985_algo); - s4985_algo = NULL; - - /* Restore physical bus */ - if (i2c_add_adapter(nforce2_smbus)) - printk(KERN_ERR "i2c-nforce2-s4985: " - "Physical bus restoration failed\n"); -} - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("S4985 SMBus multiplexing"); -MODULE_LICENSE("GPL"); - -module_init(nforce2_s4985_init); -module_exit(nforce2_s4985_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2.c deleted file mode 100644 index 43a96a12..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nforce2.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - SMBus driver for nVidia nForce2 MCP - - Added nForce3 Pro 150 Thomas Leibold <thomas@plx.com>, - Ported to 2.5 Patrick Dreker <patrick@dreker.de>, - Copyright (c) 2003 Hans-Frieder Vogt <hfvogt@arcor.de>, - Based on - SMBus 2.0 driver for AMD-8111 IO-Hub - Copyright (c) 2002 Vojtech Pavlik - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - SUPPORTED DEVICES PCI ID - nForce2 MCP 0064 - nForce2 Ultra 400 MCP 0084 - nForce3 Pro150 MCP 00D4 - nForce3 250Gb MCP 00E4 - nForce4 MCP 0052 - nForce4 MCP-04 0034 - nForce MCP51 0264 - nForce MCP55 0368 - nForce MCP61 03EB - nForce MCP65 0446 - nForce MCP67 0542 - nForce MCP73 07D8 - nForce MCP78S 0752 - nForce MCP79 0AA2 - - This driver supports the 2 SMBuses that are included in the MCP of the - nForce2/3/4/5xx chipsets. -*/ - -/* Note: we assume there can only be one nForce2, with two SMBus interfaces */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/dmi.h> -#include <linux/acpi.h> -#include <linux/slab.h> -#include <linux/io.h> - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Hans-Frieder Vogt <hfvogt@gmx.net>"); -MODULE_DESCRIPTION("nForce2/3/4/5xx SMBus driver"); - - -struct nforce2_smbus { - struct i2c_adapter adapter; - int base; - int size; - int blockops; - int can_abort; -}; - - -/* - * nVidia nForce2 SMBus control register definitions - * (Newer incarnations use standard BARs 4 and 5 instead) - */ -#define NFORCE_PCI_SMB1 0x50 -#define NFORCE_PCI_SMB2 0x54 - - -/* - * ACPI 2.0 chapter 13 SMBus 2.0 EC register model - */ -#define NVIDIA_SMB_PRTCL (smbus->base + 0x00) /* protocol, PEC */ -#define NVIDIA_SMB_STS (smbus->base + 0x01) /* status */ -#define NVIDIA_SMB_ADDR (smbus->base + 0x02) /* address */ -#define NVIDIA_SMB_CMD (smbus->base + 0x03) /* command */ -#define NVIDIA_SMB_DATA (smbus->base + 0x04) /* 32 data registers */ -#define NVIDIA_SMB_BCNT (smbus->base + 0x24) /* number of data - bytes */ -#define NVIDIA_SMB_STATUS_ABRT (smbus->base + 0x3c) /* register used to - check the status of - the abort command */ -#define NVIDIA_SMB_CTRL (smbus->base + 0x3e) /* control register */ - -#define NVIDIA_SMB_STATUS_ABRT_STS 0x01 /* Bit to notify that - abort succeeded */ -#define NVIDIA_SMB_CTRL_ABORT 0x20 -#define NVIDIA_SMB_STS_DONE 0x80 -#define NVIDIA_SMB_STS_ALRM 0x40 -#define NVIDIA_SMB_STS_RES 0x20 -#define NVIDIA_SMB_STS_STATUS 0x1f - -#define NVIDIA_SMB_PRTCL_WRITE 0x00 -#define NVIDIA_SMB_PRTCL_READ 0x01 -#define NVIDIA_SMB_PRTCL_QUICK 0x02 -#define NVIDIA_SMB_PRTCL_BYTE 0x04 -#define NVIDIA_SMB_PRTCL_BYTE_DATA 0x06 -#define NVIDIA_SMB_PRTCL_WORD_DATA 0x08 -#define NVIDIA_SMB_PRTCL_BLOCK_DATA 0x0a -#define NVIDIA_SMB_PRTCL_PEC 0x80 - -/* Misc definitions */ -#define MAX_TIMEOUT 100 - -/* We disable the second SMBus channel on these boards */ -static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = { - { - .ident = "DFI Lanparty NF4 Expert", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "DFI Corp,LTD"), - DMI_MATCH(DMI_BOARD_NAME, "LP UT NF4 Expert"), - }, - }, - { } -}; - -static struct pci_driver nforce2_driver; - -/* For multiplexing support, we need a global reference to the 1st - SMBus channel */ -#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE -struct i2c_adapter *nforce2_smbus; -EXPORT_SYMBOL_GPL(nforce2_smbus); - -static void nforce2_set_reference(struct i2c_adapter *adap) -{ - nforce2_smbus = adap; -} -#else -static inline void nforce2_set_reference(struct i2c_adapter *adap) { } -#endif - -static void nforce2_abort(struct i2c_adapter *adap) -{ - struct nforce2_smbus *smbus = adap->algo_data; - int timeout = 0; - unsigned char temp; - - dev_dbg(&adap->dev, "Aborting current transaction\n"); - - outb_p(NVIDIA_SMB_CTRL_ABORT, NVIDIA_SMB_CTRL); - do { - msleep(1); - temp = inb_p(NVIDIA_SMB_STATUS_ABRT); - } while (!(temp & NVIDIA_SMB_STATUS_ABRT_STS) && - (timeout++ < MAX_TIMEOUT)); - if (!(temp & NVIDIA_SMB_STATUS_ABRT_STS)) - dev_err(&adap->dev, "Can't reset the smbus\n"); - outb_p(NVIDIA_SMB_STATUS_ABRT_STS, NVIDIA_SMB_STATUS_ABRT); -} - -static int nforce2_check_status(struct i2c_adapter *adap) -{ - struct nforce2_smbus *smbus = adap->algo_data; - int timeout = 0; - unsigned char temp; - - do { - msleep(1); - temp = inb_p(NVIDIA_SMB_STS); - } while ((!temp) && (timeout++ < MAX_TIMEOUT)); - - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "SMBus Timeout!\n"); - if (smbus->can_abort) - nforce2_abort(adap); - return -ETIMEDOUT; - } - if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) { - dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp); - return -EIO; - } - return 0; -} - -/* Return negative errno on error */ -static s32 nforce2_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - struct nforce2_smbus *smbus = adap->algo_data; - unsigned char protocol, pec; - u8 len; - int i, status; - - protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ : - NVIDIA_SMB_PRTCL_WRITE; - pec = (flags & I2C_CLIENT_PEC) ? NVIDIA_SMB_PRTCL_PEC : 0; - - switch (size) { - - case I2C_SMBUS_QUICK: - protocol |= NVIDIA_SMB_PRTCL_QUICK; - read_write = I2C_SMBUS_WRITE; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, NVIDIA_SMB_CMD); - protocol |= NVIDIA_SMB_PRTCL_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, NVIDIA_SMB_DATA); - protocol |= NVIDIA_SMB_PRTCL_BYTE_DATA; - break; - - case I2C_SMBUS_WORD_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word, NVIDIA_SMB_DATA); - outb_p(data->word >> 8, NVIDIA_SMB_DATA+1); - } - protocol |= NVIDIA_SMB_PRTCL_WORD_DATA | pec; - break; - - case I2C_SMBUS_BLOCK_DATA: - outb_p(command, NVIDIA_SMB_CMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if ((len == 0) || (len > I2C_SMBUS_BLOCK_MAX)) { - dev_err(&adap->dev, - "Transaction failed " - "(requested block size: %d)\n", - len); - return -EINVAL; - } - outb_p(len, NVIDIA_SMB_BCNT); - for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++) - outb_p(data->block[i + 1], - NVIDIA_SMB_DATA+i); - } - protocol |= NVIDIA_SMB_PRTCL_BLOCK_DATA | pec; - break; - - default: - dev_err(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR); - outb_p(protocol, NVIDIA_SMB_PRTCL); - - status = nforce2_check_status(adap); - if (status) - return status; - - if (read_write == I2C_SMBUS_WRITE) - return 0; - - switch (size) { - - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - data->byte = inb_p(NVIDIA_SMB_DATA); - break; - - case I2C_SMBUS_WORD_DATA: - data->word = inb_p(NVIDIA_SMB_DATA) | (inb_p(NVIDIA_SMB_DATA+1) << 8); - break; - - case I2C_SMBUS_BLOCK_DATA: - len = inb_p(NVIDIA_SMB_BCNT); - if ((len <= 0) || (len > I2C_SMBUS_BLOCK_MAX)) { - dev_err(&adap->dev, "Transaction failed " - "(received block size: 0x%02x)\n", - len); - return -EPROTO; - } - for (i = 0; i < len; i++) - data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i); - data->block[0] = len; - break; - } - - return 0; -} - - -static u32 nforce2_func(struct i2c_adapter *adapter) -{ - /* other functionality might be possible, but is not tested */ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_PEC | - (((struct nforce2_smbus*)adapter->algo_data)->blockops ? - I2C_FUNC_SMBUS_BLOCK_DATA : 0); -} - -static struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = nforce2_access, - .functionality = nforce2_func, -}; - - -static DEFINE_PCI_DEVICE_TABLE(nforce2_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE2S_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE3S_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE4_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP78S_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP79_SMBUS) }, - { 0 } -}; - -MODULE_DEVICE_TABLE (pci, nforce2_ids); - - -static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar, - int alt_reg, struct nforce2_smbus *smbus, const char *name) -{ - int error; - - smbus->base = pci_resource_start(dev, bar); - if (smbus->base) { - smbus->size = pci_resource_len(dev, bar); - } else { - /* Older incarnations of the device used non-standard BARs */ - u16 iobase; - - if (pci_read_config_word(dev, alt_reg, &iobase) - != PCIBIOS_SUCCESSFUL) { - dev_err(&dev->dev, "Error reading PCI config for %s\n", - name); - return -EIO; - } - - smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK; - smbus->size = 64; - } - - error = acpi_check_region(smbus->base, smbus->size, - nforce2_driver.name); - if (error) - return error; - - if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) { - dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n", - smbus->base, smbus->base+smbus->size-1, name); - return -EBUSY; - } - smbus->adapter.owner = THIS_MODULE; - smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - smbus->adapter.dev.parent = &dev->dev; - snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), - "SMBus nForce2 adapter at %04x", smbus->base); - - error = i2c_add_adapter(&smbus->adapter); - if (error) { - dev_err(&smbus->adapter.dev, "Failed to register adapter.\n"); - release_region(smbus->base, smbus->size); - return error; - } - dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base); - return 0; -} - - -static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - struct nforce2_smbus *smbuses; - int res1, res2; - - /* we support 2 SMBus adapters */ - if (!(smbuses = kzalloc(2*sizeof(struct nforce2_smbus), GFP_KERNEL))) - return -ENOMEM; - pci_set_drvdata(dev, smbuses); - - switch(dev->device) { - case PCI_DEVICE_ID_NVIDIA_NFORCE2_SMBUS: - case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SMBUS: - case PCI_DEVICE_ID_NVIDIA_NFORCE_MCP55_SMBUS: - smbuses[0].blockops = 1; - smbuses[1].blockops = 1; - smbuses[0].can_abort = 1; - smbuses[1].can_abort = 1; - } - - /* SMBus adapter 1 */ - res1 = nforce2_probe_smb(dev, 4, NFORCE_PCI_SMB1, &smbuses[0], "SMB1"); - if (res1 < 0) - smbuses[0].base = 0; /* to have a check value */ - - /* SMBus adapter 2 */ - if (dmi_check_system(nforce2_dmi_blacklist2)) { - dev_err(&dev->dev, "Disabling SMB2 for safety reasons.\n"); - res2 = -EPERM; - smbuses[1].base = 0; - } else { - res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], - "SMB2"); - if (res2 < 0) - smbuses[1].base = 0; /* to have a check value */ - } - - if ((res1 < 0) && (res2 < 0)) { - /* we did not find even one of the SMBuses, so we give up */ - kfree(smbuses); - return -ENODEV; - } - - nforce2_set_reference(&smbuses[0].adapter); - return 0; -} - - -static void __devexit nforce2_remove(struct pci_dev *dev) -{ - struct nforce2_smbus *smbuses = pci_get_drvdata(dev); - - nforce2_set_reference(NULL); - if (smbuses[0].base) { - i2c_del_adapter(&smbuses[0].adapter); - release_region(smbuses[0].base, smbuses[0].size); - } - if (smbuses[1].base) { - i2c_del_adapter(&smbuses[1].adapter); - release_region(smbuses[1].base, smbuses[1].size); - } - kfree(smbuses); -} - -static struct pci_driver nforce2_driver = { - .name = "nForce2_smbus", - .id_table = nforce2_ids, - .probe = nforce2_probe, - .remove = __devexit_p(nforce2_remove), -}; - -static int __init nforce2_init(void) -{ - return pci_register_driver(&nforce2_driver); -} - -static void __exit nforce2_exit(void) -{ - pci_unregister_driver(&nforce2_driver); -} - -module_init(nforce2_init); -module_exit(nforce2_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nomadik.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-nomadik.c deleted file mode 100644 index 5267ab93..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nomadik.c +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * Copyright (C) 2009 ST-Ericsson SA - * Copyright (C) 2009 STMicroelectronics - * - * I2C master mode controller driver, used in Nomadik 8815 - * and Ux500 platforms. - * - * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com> - * Author: Sachin Verma <sachin.verma@st.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, as - * published by the Free Software Foundation. - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/regulator/consumer.h> -#include <linux/pm_runtime.h> - -#include <plat/i2c.h> - -#define DRIVER_NAME "nmk-i2c" - -/* I2C Controller register offsets */ -#define I2C_CR (0x000) -#define I2C_SCR (0x004) -#define I2C_HSMCR (0x008) -#define I2C_MCR (0x00C) -#define I2C_TFR (0x010) -#define I2C_SR (0x014) -#define I2C_RFR (0x018) -#define I2C_TFTR (0x01C) -#define I2C_RFTR (0x020) -#define I2C_DMAR (0x024) -#define I2C_BRCR (0x028) -#define I2C_IMSCR (0x02C) -#define I2C_RISR (0x030) -#define I2C_MISR (0x034) -#define I2C_ICR (0x038) - -/* Control registers */ -#define I2C_CR_PE (0x1 << 0) /* Peripheral Enable */ -#define I2C_CR_OM (0x3 << 1) /* Operating mode */ -#define I2C_CR_SAM (0x1 << 3) /* Slave addressing mode */ -#define I2C_CR_SM (0x3 << 4) /* Speed mode */ -#define I2C_CR_SGCM (0x1 << 6) /* Slave general call mode */ -#define I2C_CR_FTX (0x1 << 7) /* Flush Transmit */ -#define I2C_CR_FRX (0x1 << 8) /* Flush Receive */ -#define I2C_CR_DMA_TX_EN (0x1 << 9) /* DMA Tx enable */ -#define I2C_CR_DMA_RX_EN (0x1 << 10) /* DMA Rx Enable */ -#define I2C_CR_DMA_SLE (0x1 << 11) /* DMA sync. logic enable */ -#define I2C_CR_LM (0x1 << 12) /* Loopback mode */ -#define I2C_CR_FON (0x3 << 13) /* Filtering on */ -#define I2C_CR_FS (0x3 << 15) /* Force stop enable */ - -/* Master controller (MCR) register */ -#define I2C_MCR_OP (0x1 << 0) /* Operation */ -#define I2C_MCR_A7 (0x7f << 1) /* 7-bit address */ -#define I2C_MCR_EA10 (0x7 << 8) /* 10-bit Extended address */ -#define I2C_MCR_SB (0x1 << 11) /* Extended address */ -#define I2C_MCR_AM (0x3 << 12) /* Address type */ -#define I2C_MCR_STOP (0x1 << 14) /* Stop condition */ -#define I2C_MCR_LENGTH (0x7ff << 15) /* Transaction length */ - -/* Status register (SR) */ -#define I2C_SR_OP (0x3 << 0) /* Operation */ -#define I2C_SR_STATUS (0x3 << 2) /* controller status */ -#define I2C_SR_CAUSE (0x7 << 4) /* Abort cause */ -#define I2C_SR_TYPE (0x3 << 7) /* Receive type */ -#define I2C_SR_LENGTH (0x7ff << 9) /* Transfer length */ - -/* Interrupt mask set/clear (IMSCR) bits */ -#define I2C_IT_TXFE (0x1 << 0) -#define I2C_IT_TXFNE (0x1 << 1) -#define I2C_IT_TXFF (0x1 << 2) -#define I2C_IT_TXFOVR (0x1 << 3) -#define I2C_IT_RXFE (0x1 << 4) -#define I2C_IT_RXFNF (0x1 << 5) -#define I2C_IT_RXFF (0x1 << 6) -#define I2C_IT_RFSR (0x1 << 16) -#define I2C_IT_RFSE (0x1 << 17) -#define I2C_IT_WTSR (0x1 << 18) -#define I2C_IT_MTD (0x1 << 19) -#define I2C_IT_STD (0x1 << 20) -#define I2C_IT_MAL (0x1 << 24) -#define I2C_IT_BERR (0x1 << 25) -#define I2C_IT_MTDWS (0x1 << 28) - -#define GEN_MASK(val, mask, sb) (((val) << (sb)) & (mask)) - -/* some bits in ICR are reserved */ -#define I2C_CLEAR_ALL_INTS 0x131f007f - -/* first three msb bits are reserved */ -#define IRQ_MASK(mask) (mask & 0x1fffffff) - -/* maximum threshold value */ -#define MAX_I2C_FIFO_THRESHOLD 15 - -enum i2c_status { - I2C_NOP, - I2C_ON_GOING, - I2C_OK, - I2C_ABORT -}; - -/* operation */ -enum i2c_operation { - I2C_NO_OPERATION = 0xff, - I2C_WRITE = 0x00, - I2C_READ = 0x01 -}; - -/** - * struct i2c_nmk_client - client specific data - * @slave_adr: 7-bit slave address - * @count: no. bytes to be transferred - * @buffer: client data buffer - * @xfer_bytes: bytes transferred till now - * @operation: current I2C operation - */ -struct i2c_nmk_client { - unsigned short slave_adr; - unsigned long count; - unsigned char *buffer; - unsigned long xfer_bytes; - enum i2c_operation operation; -}; - -/** - * struct nmk_i2c_dev - private data structure of the controller. - * @pdev: parent platform device. - * @adap: corresponding I2C adapter. - * @irq: interrupt line for the controller. - * @virtbase: virtual io memory area. - * @clk: hardware i2c block clock. - * @cfg: machine provided controller configuration. - * @cli: holder of client specific data. - * @stop: stop condition. - * @xfer_complete: acknowledge completion for a I2C message. - * @result: controller propogated result. - * @regulator: pointer to i2c regulator. - * @busy: Busy doing transfer. - */ -struct nmk_i2c_dev { - struct platform_device *pdev; - struct i2c_adapter adap; - int irq; - void __iomem *virtbase; - struct clk *clk; - struct nmk_i2c_controller cfg; - struct i2c_nmk_client cli; - int stop; - struct completion xfer_complete; - int result; - struct regulator *regulator; - bool busy; -}; - -/* controller's abort causes */ -static const char *abort_causes[] = { - "no ack received after address transmission", - "no ack received during data phase", - "ack received after xmission of master code", - "master lost arbitration", - "slave restarts", - "slave reset", - "overflow, maxsize is 2047 bytes", -}; - -static inline void i2c_set_bit(void __iomem *reg, u32 mask) -{ - writel(readl(reg) | mask, reg); -} - -static inline void i2c_clr_bit(void __iomem *reg, u32 mask) -{ - writel(readl(reg) & ~mask, reg); -} - -/** - * flush_i2c_fifo() - This function flushes the I2C FIFO - * @dev: private data of I2C Driver - * - * This function flushes the I2C Tx and Rx FIFOs. It returns - * 0 on successful flushing of FIFO - */ -static int flush_i2c_fifo(struct nmk_i2c_dev *dev) -{ -#define LOOP_ATTEMPTS 10 - int i; - unsigned long timeout; - - /* - * flush the transmit and receive FIFO. The flushing - * operation takes several cycles before to be completed. - * On the completion, the I2C internal logic clears these - * bits, until then no one must access Tx, Rx FIFO and - * should poll on these bits waiting for the completion. - */ - writel((I2C_CR_FTX | I2C_CR_FRX), dev->virtbase + I2C_CR); - - for (i = 0; i < LOOP_ATTEMPTS; i++) { - timeout = jiffies + dev->adap.timeout; - - while (!time_after(jiffies, timeout)) { - if ((readl(dev->virtbase + I2C_CR) & - (I2C_CR_FTX | I2C_CR_FRX)) == 0) - return 0; - } - } - - dev_err(&dev->pdev->dev, - "flushing operation timed out giving up after %d attempts", - LOOP_ATTEMPTS); - - return -ETIMEDOUT; -} - -/** - * disable_all_interrupts() - Disable all interrupts of this I2c Bus - * @dev: private data of I2C Driver - */ -static void disable_all_interrupts(struct nmk_i2c_dev *dev) -{ - u32 mask = IRQ_MASK(0); - writel(mask, dev->virtbase + I2C_IMSCR); -} - -/** - * clear_all_interrupts() - Clear all interrupts of I2C Controller - * @dev: private data of I2C Driver - */ -static void clear_all_interrupts(struct nmk_i2c_dev *dev) -{ - u32 mask; - mask = IRQ_MASK(I2C_CLEAR_ALL_INTS); - writel(mask, dev->virtbase + I2C_ICR); -} - -/** - * init_hw() - initialize the I2C hardware - * @dev: private data of I2C Driver - */ -static int init_hw(struct nmk_i2c_dev *dev) -{ - int stat; - - stat = flush_i2c_fifo(dev); - if (stat) - goto exit; - - /* disable the controller */ - i2c_clr_bit(dev->virtbase + I2C_CR , I2C_CR_PE); - - disable_all_interrupts(dev); - - clear_all_interrupts(dev); - - dev->cli.operation = I2C_NO_OPERATION; - -exit: - return stat; -} - -/* enable peripheral, master mode operation */ -#define DEFAULT_I2C_REG_CR ((1 << 1) | I2C_CR_PE) - -/** - * load_i2c_mcr_reg() - load the MCR register - * @dev: private data of controller - */ -static u32 load_i2c_mcr_reg(struct nmk_i2c_dev *dev) -{ - u32 mcr = 0; - - /* 7-bit address transaction */ - mcr |= GEN_MASK(1, I2C_MCR_AM, 12); - mcr |= GEN_MASK(dev->cli.slave_adr, I2C_MCR_A7, 1); - - /* start byte procedure not applied */ - mcr |= GEN_MASK(0, I2C_MCR_SB, 11); - - /* check the operation, master read/write? */ - if (dev->cli.operation == I2C_WRITE) - mcr |= GEN_MASK(I2C_WRITE, I2C_MCR_OP, 0); - else - mcr |= GEN_MASK(I2C_READ, I2C_MCR_OP, 0); - - /* stop or repeated start? */ - if (dev->stop) - mcr |= GEN_MASK(1, I2C_MCR_STOP, 14); - else - mcr &= ~(GEN_MASK(1, I2C_MCR_STOP, 14)); - - mcr |= GEN_MASK(dev->cli.count, I2C_MCR_LENGTH, 15); - - return mcr; -} - -/** - * setup_i2c_controller() - setup the controller - * @dev: private data of controller - */ -static void setup_i2c_controller(struct nmk_i2c_dev *dev) -{ - u32 brcr1, brcr2; - u32 i2c_clk, div; - - writel(0x0, dev->virtbase + I2C_CR); - writel(0x0, dev->virtbase + I2C_HSMCR); - writel(0x0, dev->virtbase + I2C_TFTR); - writel(0x0, dev->virtbase + I2C_RFTR); - writel(0x0, dev->virtbase + I2C_DMAR); - - /* - * set the slsu: - * - * slsu defines the data setup time after SCL clock - * stretching in terms of i2c clk cycles. The - * needed setup time for the three modes are 250ns, - * 100ns, 10ns respectively thus leading to the values - * of 14, 6, 2 for a 48 MHz i2c clk. - */ - writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR); - - i2c_clk = clk_get_rate(dev->clk); - - /* fallback to std. mode if machine has not provided it */ - if (dev->cfg.clk_freq == 0) - dev->cfg.clk_freq = 100000; - - /* - * The spec says, in case of std. mode the divider is - * 2 whereas it is 3 for fast and fastplus mode of - * operation. TODO - high speed support. - */ - div = (dev->cfg.clk_freq > 100000) ? 3 : 2; - - /* - * generate the mask for baud rate counters. The controller - * has two baud rate counters. One is used for High speed - * operation, and the other is for std, fast mode, fast mode - * plus operation. Currently we do not supprt high speed mode - * so set brcr1 to 0. - */ - brcr1 = 0 << 16; - brcr2 = (i2c_clk/(dev->cfg.clk_freq * div)) & 0xffff; - - /* set the baud rate counter register */ - writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); - - /* - * set the speed mode. Currently we support - * only standard and fast mode of operation - * TODO - support for fast mode plus (up to 1Mb/s) - * and high speed (up to 3.4 Mb/s) - */ - if (dev->cfg.sm > I2C_FREQ_MODE_FAST) { - dev_err(&dev->pdev->dev, - "do not support this mode defaulting to std. mode\n"); - brcr2 = i2c_clk/(100000 * 2) & 0xffff; - writel((brcr1 | brcr2), dev->virtbase + I2C_BRCR); - writel(I2C_FREQ_MODE_STANDARD << 4, - dev->virtbase + I2C_CR); - } - writel(dev->cfg.sm << 4, dev->virtbase + I2C_CR); - - /* set the Tx and Rx FIFO threshold */ - writel(dev->cfg.tft, dev->virtbase + I2C_TFTR); - writel(dev->cfg.rft, dev->virtbase + I2C_RFTR); -} - -/** - * read_i2c() - Read from I2C client device - * @dev: private data of I2C Driver - * - * This function reads from i2c client device when controller is in - * master mode. There is a completion timeout. If there is no transfer - * before timeout error is returned. - */ -static int read_i2c(struct nmk_i2c_dev *dev) -{ - u32 status = 0; - u32 mcr; - u32 irq_mask = 0; - int timeout; - - mcr = load_i2c_mcr_reg(dev); - writel(mcr, dev->virtbase + I2C_MCR); - - /* load the current CR value */ - writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR, - dev->virtbase + I2C_CR); - - /* enable the controller */ - i2c_set_bit(dev->virtbase + I2C_CR, I2C_CR_PE); - - init_completion(&dev->xfer_complete); - - /* enable interrupts by setting the mask */ - irq_mask = (I2C_IT_RXFNF | I2C_IT_RXFF | - I2C_IT_MAL | I2C_IT_BERR); - - if (dev->stop) - irq_mask |= I2C_IT_MTD; - else - irq_mask |= I2C_IT_MTDWS; - - irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask); - - writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, - dev->virtbase + I2C_IMSCR); - - timeout = wait_for_completion_timeout( - &dev->xfer_complete, dev->adap.timeout); - - if (timeout < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_timeout " - "returned %d waiting for event\n", timeout); - status = timeout; - } - - if (timeout == 0) { - /* Controller timed out */ - dev_err(&dev->pdev->dev, "read from slave 0x%x timed out\n", - dev->cli.slave_adr); - status = -ETIMEDOUT; - } - return status; -} - -static void fill_tx_fifo(struct nmk_i2c_dev *dev, int no_bytes) -{ - int count; - - for (count = (no_bytes - 2); - (count > 0) && - (dev->cli.count != 0); - count--) { - /* write to the Tx FIFO */ - writeb(*dev->cli.buffer, - dev->virtbase + I2C_TFR); - dev->cli.buffer++; - dev->cli.count--; - dev->cli.xfer_bytes++; - } - -} - -/** - * write_i2c() - Write data to I2C client. - * @dev: private data of I2C Driver - * - * This function writes data to I2C client - */ -static int write_i2c(struct nmk_i2c_dev *dev) -{ - u32 status = 0; - u32 mcr; - u32 irq_mask = 0; - int timeout; - - mcr = load_i2c_mcr_reg(dev); - - writel(mcr, dev->virtbase + I2C_MCR); - - /* load the current CR value */ - writel(readl(dev->virtbase + I2C_CR) | DEFAULT_I2C_REG_CR, - dev->virtbase + I2C_CR); - - /* enable the controller */ - i2c_set_bit(dev->virtbase + I2C_CR , I2C_CR_PE); - - init_completion(&dev->xfer_complete); - - /* enable interrupts by settings the masks */ - irq_mask = (I2C_IT_TXFOVR | I2C_IT_MAL | I2C_IT_BERR); - - /* Fill the TX FIFO with transmit data */ - fill_tx_fifo(dev, MAX_I2C_FIFO_THRESHOLD); - - if (dev->cli.count != 0) - irq_mask |= I2C_IT_TXFNE; - - /* - * check if we want to transfer a single or multiple bytes, if so - * set the MTDWS bit (Master Transaction Done Without Stop) - * to start repeated start operation - */ - if (dev->stop) - irq_mask |= I2C_IT_MTD; - else - irq_mask |= I2C_IT_MTDWS; - - irq_mask = I2C_CLEAR_ALL_INTS & IRQ_MASK(irq_mask); - - writel(readl(dev->virtbase + I2C_IMSCR) | irq_mask, - dev->virtbase + I2C_IMSCR); - - timeout = wait_for_completion_timeout( - &dev->xfer_complete, dev->adap.timeout); - - if (timeout < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_timeout " - "returned %d waiting for event\n", timeout); - status = timeout; - } - - if (timeout == 0) { - /* Controller timed out */ - dev_err(&dev->pdev->dev, "write to slave 0x%x timed out\n", - dev->cli.slave_adr); - status = -ETIMEDOUT; - } - - return status; -} - -/** - * nmk_i2c_xfer_one() - transmit a single I2C message - * @dev: device with a message encoded into it - * @flags: message flags - */ -static int nmk_i2c_xfer_one(struct nmk_i2c_dev *dev, u16 flags) -{ - int status; - - if (flags & I2C_M_RD) { - /* read operation */ - dev->cli.operation = I2C_READ; - status = read_i2c(dev); - } else { - /* write operation */ - dev->cli.operation = I2C_WRITE; - status = write_i2c(dev); - } - - if (status || (dev->result)) { - u32 i2c_sr; - u32 cause; - - i2c_sr = readl(dev->virtbase + I2C_SR); - /* - * Check if the controller I2C operation status - * is set to ABORT(11b). - */ - if (((i2c_sr >> 2) & 0x3) == 0x3) { - /* get the abort cause */ - cause = (i2c_sr >> 4) & 0x7; - dev_err(&dev->pdev->dev, "%s\n", - cause >= ARRAY_SIZE(abort_causes) ? - "unknown reason" : - abort_causes[cause]); - } - - (void) init_hw(dev); - - status = status ? status : dev->result; - } - - return status; -} - -/** - * nmk_i2c_xfer() - I2C transfer function used by kernel framework - * @i2c_adap: Adapter pointer to the controller - * @msgs: Pointer to data to be written. - * @num_msgs: Number of messages to be executed - * - * This is the function called by the generic kernel i2c_transfer() - * or i2c_smbus...() API calls. Note that this code is protected by the - * semaphore set in the kernel i2c_transfer() function. - * - * NOTE: - * READ TRANSFER : We impose a restriction of the first message to be the - * index message for any read transaction. - * - a no index is coded as '0', - * - 2byte big endian index is coded as '3' - * !!! msg[0].buf holds the actual index. - * This is compatible with generic messages of smbus emulator - * that send a one byte index. - * eg. a I2C transation to read 2 bytes from index 0 - * idx = 0; - * msg[0].addr = client->addr; - * msg[0].flags = 0x0; - * msg[0].len = 1; - * msg[0].buf = &idx; - * - * msg[1].addr = client->addr; - * msg[1].flags = I2C_M_RD; - * msg[1].len = 2; - * msg[1].buf = rd_buff - * i2c_transfer(adap, msg, 2); - * - * WRITE TRANSFER : The I2C standard interface interprets all data as payload. - * If you want to emulate an SMBUS write transaction put the - * index as first byte(or first and second) in the payload. - * eg. a I2C transation to write 2 bytes from index 1 - * wr_buff[0] = 0x1; - * wr_buff[1] = 0x23; - * wr_buff[2] = 0x46; - * msg[0].flags = 0x0; - * msg[0].len = 3; - * msg[0].buf = wr_buff; - * i2c_transfer(adap, msg, 1); - * - * To read or write a block of data (multiple bytes) using SMBUS emulation - * please use the i2c_smbus_read_i2c_block_data() - * or i2c_smbus_write_i2c_block_data() API - */ -static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, - struct i2c_msg msgs[], int num_msgs) -{ - int status; - int i; - struct nmk_i2c_dev *dev = i2c_get_adapdata(i2c_adap); - int j; - - dev->busy = true; - - if (dev->regulator) - regulator_enable(dev->regulator); - pm_runtime_get_sync(&dev->pdev->dev); - - clk_enable(dev->clk); - - status = init_hw(dev); - if (status) - goto out; - - /* Attempt three times to send the message queue */ - for (j = 0; j < 3; j++) { - /* setup the i2c controller */ - setup_i2c_controller(dev); - - for (i = 0; i < num_msgs; i++) { - if (unlikely(msgs[i].flags & I2C_M_TEN)) { - dev_err(&dev->pdev->dev, - "10 bit addressing not supported\n"); - - status = -EINVAL; - goto out; - } - dev->cli.slave_adr = msgs[i].addr; - dev->cli.buffer = msgs[i].buf; - dev->cli.count = msgs[i].len; - dev->stop = (i < (num_msgs - 1)) ? 0 : 1; - dev->result = 0; - - status = nmk_i2c_xfer_one(dev, msgs[i].flags); - if (status != 0) - break; - } - if (status == 0) - break; - } - -out: - clk_disable(dev->clk); - pm_runtime_put_sync(&dev->pdev->dev); - if (dev->regulator) - regulator_disable(dev->regulator); - - dev->busy = false; - - /* return the no. messages processed */ - if (status) - return status; - else - return num_msgs; -} - -/** - * disable_interrupts() - disable the interrupts - * @dev: private data of controller - * @irq: interrupt number - */ -static int disable_interrupts(struct nmk_i2c_dev *dev, u32 irq) -{ - irq = IRQ_MASK(irq); - writel(readl(dev->virtbase + I2C_IMSCR) & ~(I2C_CLEAR_ALL_INTS & irq), - dev->virtbase + I2C_IMSCR); - return 0; -} - -/** - * i2c_irq_handler() - interrupt routine - * @irq: interrupt number - * @arg: data passed to the handler - * - * This is the interrupt handler for the i2c driver. Currently - * it handles the major interrupts like Rx & Tx FIFO management - * interrupts, master transaction interrupts, arbitration and - * bus error interrupts. The rest of the interrupts are treated as - * unhandled. - */ -static irqreturn_t i2c_irq_handler(int irq, void *arg) -{ - struct nmk_i2c_dev *dev = arg; - u32 tft, rft; - u32 count; - u32 misr; - u32 src = 0; - - /* load Tx FIFO and Rx FIFO threshold values */ - tft = readl(dev->virtbase + I2C_TFTR); - rft = readl(dev->virtbase + I2C_RFTR); - - /* read interrupt status register */ - misr = readl(dev->virtbase + I2C_MISR); - - src = __ffs(misr); - switch ((1 << src)) { - - /* Transmit FIFO nearly empty interrupt */ - case I2C_IT_TXFNE: - { - if (dev->cli.operation == I2C_READ) { - /* - * in read operation why do we care for writing? - * so disable the Transmit FIFO interrupt - */ - disable_interrupts(dev, I2C_IT_TXFNE); - } else { - fill_tx_fifo(dev, (MAX_I2C_FIFO_THRESHOLD - tft)); - /* - * if done, close the transfer by disabling the - * corresponding TXFNE interrupt - */ - if (dev->cli.count == 0) - disable_interrupts(dev, I2C_IT_TXFNE); - } - } - break; - - /* - * Rx FIFO nearly full interrupt. - * This is set when the numer of entries in Rx FIFO is - * greater or equal than the threshold value programmed - * in RFT - */ - case I2C_IT_RXFNF: - for (count = rft; count > 0; count--) { - /* Read the Rx FIFO */ - *dev->cli.buffer = readb(dev->virtbase + I2C_RFR); - dev->cli.buffer++; - } - dev->cli.count -= rft; - dev->cli.xfer_bytes += rft; - break; - - /* Rx FIFO full */ - case I2C_IT_RXFF: - for (count = MAX_I2C_FIFO_THRESHOLD; count > 0; count--) { - *dev->cli.buffer = readb(dev->virtbase + I2C_RFR); - dev->cli.buffer++; - } - dev->cli.count -= MAX_I2C_FIFO_THRESHOLD; - dev->cli.xfer_bytes += MAX_I2C_FIFO_THRESHOLD; - break; - - /* Master Transaction Done with/without stop */ - case I2C_IT_MTD: - case I2C_IT_MTDWS: - if (dev->cli.operation == I2C_READ) { - while (!(readl(dev->virtbase + I2C_RISR) - & I2C_IT_RXFE)) { - if (dev->cli.count == 0) - break; - *dev->cli.buffer = - readb(dev->virtbase + I2C_RFR); - dev->cli.buffer++; - dev->cli.count--; - dev->cli.xfer_bytes++; - } - } - - disable_all_interrupts(dev); - clear_all_interrupts(dev); - - if (dev->cli.count) { - dev->result = -EIO; - dev_err(&dev->pdev->dev, - "%lu bytes still remain to be xfered\n", - dev->cli.count); - (void) init_hw(dev); - } - complete(&dev->xfer_complete); - - break; - - /* Master Arbitration lost interrupt */ - case I2C_IT_MAL: - dev->result = -EIO; - (void) init_hw(dev); - - i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_MAL); - complete(&dev->xfer_complete); - - break; - - /* - * Bus Error interrupt. - * This happens when an unexpected start/stop condition occurs - * during the transaction. - */ - case I2C_IT_BERR: - dev->result = -EIO; - /* get the status */ - if (((readl(dev->virtbase + I2C_SR) >> 2) & 0x3) == I2C_ABORT) - (void) init_hw(dev); - - i2c_set_bit(dev->virtbase + I2C_ICR, I2C_IT_BERR); - complete(&dev->xfer_complete); - - break; - - /* - * Tx FIFO overrun interrupt. - * This is set when a write operation in Tx FIFO is performed and - * the Tx FIFO is full. - */ - case I2C_IT_TXFOVR: - dev->result = -EIO; - (void) init_hw(dev); - - dev_err(&dev->pdev->dev, "Tx Fifo Over run\n"); - complete(&dev->xfer_complete); - - break; - - /* unhandled interrupts by this driver - TODO*/ - case I2C_IT_TXFE: - case I2C_IT_TXFF: - case I2C_IT_RXFE: - case I2C_IT_RFSR: - case I2C_IT_RFSE: - case I2C_IT_WTSR: - case I2C_IT_STD: - dev_err(&dev->pdev->dev, "unhandled Interrupt\n"); - break; - default: - dev_err(&dev->pdev->dev, "spurious Interrupt..\n"); - break; - } - - return IRQ_HANDLED; -} - - -#ifdef CONFIG_PM -static int nmk_i2c_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); - - if (nmk_i2c->busy) - return -EBUSY; - - return 0; -} - -static int nmk_i2c_resume(struct device *dev) -{ - return 0; -} -#else -#define nmk_i2c_suspend NULL -#define nmk_i2c_resume NULL -#endif - -/* - * We use noirq so that we suspend late and resume before the wakeup interrupt - * to ensure that we do the !pm_runtime_suspended() check in resume before - * there has been a regular pm runtime resume (via pm_runtime_get_sync()). - */ -static const struct dev_pm_ops nmk_i2c_pm = { - .suspend_noirq = nmk_i2c_suspend, - .resume_noirq = nmk_i2c_resume, -}; - -static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm nmk_i2c_algo = { - .master_xfer = nmk_i2c_xfer, - .functionality = nmk_i2c_functionality -}; - -static int __devinit nmk_i2c_probe(struct platform_device *pdev) -{ - int ret = 0; - struct resource *res; - struct nmk_i2c_controller *pdata = - pdev->dev.platform_data; - struct nmk_i2c_dev *dev; - struct i2c_adapter *adap; - - dev = kzalloc(sizeof(struct nmk_i2c_dev), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "cannot allocate memory\n"); - ret = -ENOMEM; - goto err_no_mem; - } - dev->busy = false; - dev->pdev = pdev; - platform_set_drvdata(pdev, dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto err_no_resource; - } - - if (request_mem_region(res->start, resource_size(res), - DRIVER_NAME "I/O region") == NULL) { - ret = -EBUSY; - goto err_no_region; - } - - dev->virtbase = ioremap(res->start, resource_size(res)); - if (!dev->virtbase) { - ret = -ENOMEM; - goto err_no_ioremap; - } - - dev->irq = platform_get_irq(pdev, 0); - ret = request_irq(dev->irq, i2c_irq_handler, 0, - DRIVER_NAME, dev); - if (ret) { - dev_err(&pdev->dev, "cannot claim the irq %d\n", dev->irq); - goto err_irq; - } - - dev->regulator = regulator_get(&pdev->dev, "v-i2c"); - if (IS_ERR(dev->regulator)) { - dev_warn(&pdev->dev, "could not get i2c regulator\n"); - dev->regulator = NULL; - } - - pm_suspend_ignore_children(&pdev->dev, true); - pm_runtime_enable(&pdev->dev); - - dev->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(dev->clk)) { - dev_err(&pdev->dev, "could not get i2c clock\n"); - ret = PTR_ERR(dev->clk); - goto err_no_clk; - } - - adap = &dev->adap; - adap->dev.parent = &pdev->dev; - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adap->algo = &nmk_i2c_algo; - adap->timeout = pdata->timeout ? msecs_to_jiffies(pdata->timeout) : - msecs_to_jiffies(20000); - snprintf(adap->name, sizeof(adap->name), - "Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start); - - /* fetch the controller id */ - adap->nr = pdev->id; - - /* fetch the controller configuration from machine */ - dev->cfg.clk_freq = pdata->clk_freq; - dev->cfg.slsu = pdata->slsu; - dev->cfg.tft = pdata->tft; - dev->cfg.rft = pdata->rft; - dev->cfg.sm = pdata->sm; - - i2c_set_adapdata(adap, dev); - - dev_info(&pdev->dev, - "initialize %s on virtual base %p\n", - adap->name, dev->virtbase); - - ret = i2c_add_numbered_adapter(adap); - if (ret) { - dev_err(&pdev->dev, "failed to add adapter\n"); - goto err_add_adap; - } - - return 0; - - err_add_adap: - clk_put(dev->clk); - err_no_clk: - if (dev->regulator) - regulator_put(dev->regulator); - pm_runtime_disable(&pdev->dev); - free_irq(dev->irq, dev); - err_irq: - iounmap(dev->virtbase); - err_no_ioremap: - release_mem_region(res->start, resource_size(res)); - err_no_region: - platform_set_drvdata(pdev, NULL); - err_no_resource: - kfree(dev); - err_no_mem: - - return ret; -} - -static int __devexit nmk_i2c_remove(struct platform_device *pdev) -{ - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); - - i2c_del_adapter(&dev->adap); - flush_i2c_fifo(dev); - disable_all_interrupts(dev); - clear_all_interrupts(dev); - /* disable the controller */ - i2c_clr_bit(dev->virtbase + I2C_CR, I2C_CR_PE); - free_irq(dev->irq, dev); - iounmap(dev->virtbase); - if (res) - release_mem_region(res->start, resource_size(res)); - clk_put(dev->clk); - if (dev->regulator) - regulator_put(dev->regulator); - pm_runtime_disable(&pdev->dev); - platform_set_drvdata(pdev, NULL); - kfree(dev); - - return 0; -} - -static struct platform_driver nmk_i2c_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - .pm = &nmk_i2c_pm, - }, - .probe = nmk_i2c_probe, - .remove = __devexit_p(nmk_i2c_remove), -}; - -static int __init nmk_i2c_init(void) -{ - return platform_driver_register(&nmk_i2c_driver); -} - -static void __exit nmk_i2c_exit(void) -{ - platform_driver_unregister(&nmk_i2c_driver); -} - -subsys_initcall(nmk_i2c_init); -module_exit(nmk_i2c_exit); - -MODULE_AUTHOR("Sachin Verma, Srinidhi KASAGAR"); -MODULE_DESCRIPTION("Nomadik/Ux500 I2C driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nuc900.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-nuc900.c deleted file mode 100644 index 03b61577..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-nuc900.c +++ /dev/null @@ -1,708 +0,0 @@ -/* - * linux/drivers/i2c/busses/i2c-nuc900.c - * - * Copyright (c) 2010 Nuvoton technology corporation. - * - * This driver based on S3C2410 I2C driver of Ben Dooks <ben-Y5A6D6n0/KfQXOPxS62xeg@public.gmane.org>. - * Written by Wan ZongShun <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation;version 2 of the License. - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/slab.h> -#include <linux/io.h> - -#include <mach/mfp.h> -#include <mach/i2c.h> - -/* nuc900 i2c registers offset */ - -#define CSR 0x00 -#define DIVIDER 0x04 -#define CMDR 0x08 -#define SWR 0x0C -#define RXR 0x10 -#define TXR 0x14 - -/* nuc900 i2c CSR register bits */ - -#define IRQEN 0x003 -#define I2CBUSY 0x400 -#define I2CSTART 0x018 -#define IRQFLAG 0x004 -#define ARBIT_LOST 0x200 -#define SLAVE_ACK 0x800 - -/* nuc900 i2c CMDR register bits */ - -#define I2C_CMD_START 0x10 -#define I2C_CMD_STOP 0x08 -#define I2C_CMD_READ 0x04 -#define I2C_CMD_WRITE 0x02 -#define I2C_CMD_NACK 0x01 - -/* i2c controller state */ - -enum nuc900_i2c_state { - STATE_IDLE, - STATE_START, - STATE_READ, - STATE_WRITE, - STATE_STOP -}; - -/* i2c controller private data */ - -struct nuc900_i2c { - spinlock_t lock; - wait_queue_head_t wait; - - struct i2c_msg *msg; - unsigned int msg_num; - unsigned int msg_idx; - unsigned int msg_ptr; - unsigned int irq; - - enum nuc900_i2c_state state; - - void __iomem *regs; - struct clk *clk; - struct device *dev; - struct resource *ioarea; - struct i2c_adapter adap; -}; - -/* nuc900_i2c_master_complete - * - * complete the message and wake up the caller, using the given return code, - * or zero to mean ok. -*/ - -static inline void nuc900_i2c_master_complete(struct nuc900_i2c *i2c, int ret) -{ - dev_dbg(i2c->dev, "master_complete %d\n", ret); - - i2c->msg_ptr = 0; - i2c->msg = NULL; - i2c->msg_idx++; - i2c->msg_num = 0; - if (ret) - i2c->msg_idx = ret; - - wake_up(&i2c->wait); -} - -/* irq enable/disable functions */ - -static inline void nuc900_i2c_disable_irq(struct nuc900_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + CSR); - writel(tmp & ~IRQEN, i2c->regs + CSR); -} - -static inline void nuc900_i2c_enable_irq(struct nuc900_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + CSR); - writel(tmp | IRQEN, i2c->regs + CSR); -} - - -/* nuc900_i2c_message_start - * - * put the start of a message onto the bus -*/ - -static void nuc900_i2c_message_start(struct nuc900_i2c *i2c, - struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - - if (msg->flags & I2C_M_RD) - addr |= 0x1; - writel(addr & 0xff, i2c->regs + TXR); - writel(I2C_CMD_START | I2C_CMD_WRITE, i2c->regs + CMDR); -} - -static inline void nuc900_i2c_stop(struct nuc900_i2c *i2c, int ret) -{ - - dev_dbg(i2c->dev, "STOP\n"); - - /* stop the transfer */ - i2c->state = STATE_STOP; - writel(I2C_CMD_STOP, i2c->regs + CMDR); - - nuc900_i2c_master_complete(i2c, ret); - nuc900_i2c_disable_irq(i2c); -} - -/* helper functions to determine the current state in the set of - * messages we are sending -*/ - -/* is_lastmsg() - * - * returns TRUE if the current message is the last in the set -*/ - -static inline int is_lastmsg(struct nuc900_i2c *i2c) -{ - return i2c->msg_idx >= (i2c->msg_num - 1); -} - -/* is_msglast - * - * returns TRUE if we this is the last byte in the current message -*/ - -static inline int is_msglast(struct nuc900_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len-1; -} - -/* is_msgend - * - * returns TRUE if we reached the end of the current message -*/ - -static inline int is_msgend(struct nuc900_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -/* i2c_nuc900_irq_nextbyte - * - * process an interrupt and work out what to do - */ - -static void i2c_nuc900_irq_nextbyte(struct nuc900_i2c *i2c, - unsigned long iicstat) -{ - unsigned char byte; - - switch (i2c->state) { - - case STATE_IDLE: - dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); - break; - - case STATE_STOP: - dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); - nuc900_i2c_disable_irq(i2c); - break; - - case STATE_START: - /* last thing we did was send a start condition on the - * bus, or started a new i2c message - */ - - if (iicstat & SLAVE_ACK && - !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - /* ack was not received... */ - - dev_dbg(i2c->dev, "ack was not received\n"); - nuc900_i2c_stop(i2c, -ENXIO); - break; - } - - if (i2c->msg->flags & I2C_M_RD) - i2c->state = STATE_READ; - else - i2c->state = STATE_WRITE; - - /* terminate the transfer if there is nothing to do - * as this is used by the i2c probe to find devices. - */ - - if (is_lastmsg(i2c) && i2c->msg->len == 0) { - nuc900_i2c_stop(i2c, 0); - break; - } - - if (i2c->state == STATE_READ) - goto prepare_read; - - /* fall through to the write state, as we will need to - * send a byte as well - */ - - case STATE_WRITE: - /* we are writing data to the device... check for the - * end of the message, and if so, work out what to do - */ - - if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - if (iicstat & SLAVE_ACK) { - dev_dbg(i2c->dev, "WRITE: No Ack\n"); - - nuc900_i2c_stop(i2c, -ECONNREFUSED); - break; - } - } - -retry_write: - - if (!is_msgend(i2c)) { - byte = i2c->msg->buf[i2c->msg_ptr++]; - writeb(byte, i2c->regs + TXR); - writel(I2C_CMD_WRITE, i2c->regs + CMDR); - - } else if (!is_lastmsg(i2c)) { - /* we need to go to the next i2c message */ - - dev_dbg(i2c->dev, "WRITE: Next Message\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - /* check to see if we need to do another message */ - if (i2c->msg->flags & I2C_M_NOSTART) { - - if (i2c->msg->flags & I2C_M_RD) { - /* cannot do this, the controller - * forces us to send a new START - * when we change direction - */ - - nuc900_i2c_stop(i2c, -EINVAL); - } - - goto retry_write; - } else { - /* send the new start */ - nuc900_i2c_message_start(i2c, i2c->msg); - i2c->state = STATE_START; - } - - } else { - /* send stop */ - - nuc900_i2c_stop(i2c, 0); - } - break; - - case STATE_READ: - /* we have a byte of data in the data register, do - * something with it, and then work out wether we are - * going to do any more read/write - */ - - byte = readb(i2c->regs + RXR); - i2c->msg->buf[i2c->msg_ptr++] = byte; - -prepare_read: - if (is_msglast(i2c)) { - /* last byte of buffer */ - - if (is_lastmsg(i2c)) - writel(I2C_CMD_READ | I2C_CMD_NACK, - i2c->regs + CMDR); - - } else if (is_msgend(i2c)) { - /* ok, we've read the entire buffer, see if there - * is anything else we need to do - */ - - if (is_lastmsg(i2c)) { - /* last message, send stop and complete */ - dev_dbg(i2c->dev, "READ: Send Stop\n"); - - nuc900_i2c_stop(i2c, 0); - } else { - /* go to the next transfer */ - dev_dbg(i2c->dev, "READ: Next Transfer\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - writel(I2C_CMD_READ, i2c->regs + CMDR); - } - - } else { - writel(I2C_CMD_READ, i2c->regs + CMDR); - } - - break; - } -} - -/* nuc900_i2c_irq - * - * top level IRQ servicing routine -*/ - -static irqreturn_t nuc900_i2c_irq(int irqno, void *dev_id) -{ - struct nuc900_i2c *i2c = dev_id; - unsigned long status; - - status = readl(i2c->regs + CSR); - writel(status | IRQFLAG, i2c->regs + CSR); - - if (status & ARBIT_LOST) { - /* deal with arbitration loss */ - dev_err(i2c->dev, "deal with arbitration loss\n"); - goto out; - } - - if (i2c->state == STATE_IDLE) { - dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); - goto out; - } - - /* pretty much this leaves us with the fact that we've - * transmitted or received whatever byte we last sent - */ - - i2c_nuc900_irq_nextbyte(i2c, status); - - out: - return IRQ_HANDLED; -} - - -/* nuc900_i2c_set_master - * - * get the i2c bus for a master transaction -*/ - -static int nuc900_i2c_set_master(struct nuc900_i2c *i2c) -{ - int timeout = 400; - - while (timeout-- > 0) { - if (((readl(i2c->regs + SWR) & I2CSTART) == I2CSTART) && - ((readl(i2c->regs + CSR) & I2CBUSY) == 0)) { - return 0; - } - - msleep(1); - } - - return -ETIMEDOUT; -} - -/* nuc900_i2c_doxfer - * - * this starts an i2c transfer -*/ - -static int nuc900_i2c_doxfer(struct nuc900_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long iicstat, timeout; - int spins = 20; - int ret; - - ret = nuc900_i2c_set_master(i2c); - if (ret != 0) { - dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); - ret = -EAGAIN; - goto out; - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msgs; - i2c->msg_num = num; - i2c->msg_ptr = 0; - i2c->msg_idx = 0; - i2c->state = STATE_START; - - nuc900_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); - - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); - - ret = i2c->msg_idx; - - /* having these next two as dev_err() makes life very - * noisy when doing an i2cdetect - */ - - if (timeout == 0) - dev_dbg(i2c->dev, "timeout\n"); - else if (ret != num) - dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); - - /* ensure the stop has been through the bus */ - - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - iicstat = readl(i2c->regs + CSR); - } while ((iicstat & I2CBUSY) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + CSR); - } - - if (iicstat & I2CBUSY) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); - - out: - return ret; -} - -/* nuc900_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int nuc900_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct nuc900_i2c *i2c = (struct nuc900_i2c *)adap->algo_data; - int retry; - int ret; - - nuc900_i2c_enable_irq(i2c); - - for (retry = 0; retry < adap->retries; retry++) { - - ret = nuc900_i2c_doxfer(i2c, msgs, num); - - if (ret != -EAGAIN) - return ret; - - dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); - - udelay(100); - } - - return -EREMOTEIO; -} - -/* declare our i2c functionality */ -static u32 nuc900_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm nuc900_i2c_algorithm = { - .master_xfer = nuc900_i2c_xfer, - .functionality = nuc900_i2c_func, -}; - -/* nuc900_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - -static int __devinit nuc900_i2c_probe(struct platform_device *pdev) -{ - struct nuc900_i2c *i2c; - struct nuc900_platform_i2c *pdata; - struct resource *res; - int ret; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - - i2c = kzalloc(sizeof(struct nuc900_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - - strlcpy(i2c->adap.name, "nuc900-i2c0", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &nuc900_i2c_algorithm; - i2c->adap.retries = 2; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - - /* find the clock and enable it */ - - i2c->dev = &pdev->dev; - i2c->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = -ENOENT; - goto err_noclk; - } - - dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - - clk_enable(i2c->clk); - - /* map the registers */ - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_clk; - } - - i2c->ioarea = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (i2c->ioarea == NULL) { - dev_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_clk; - } - - i2c->regs = ioremap(res->start, resource_size(res)); - - if (i2c->regs == NULL) { - dev_err(&pdev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_ioarea; - } - - dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); - - /* setup info block for the i2c core */ - - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &pdev->dev; - - mfp_set_groupg(&pdev->dev, NULL); - - clk_get_rate(i2c->clk); - - ret = (i2c->clk.apbfreq)/(pdata->bus_freq * 5) - 1; - writel(ret & 0xffff, i2c->regs + DIVIDER); - - /* find the IRQ for this unit (note, this relies on the init call to - * ensure no current IRQs pending - */ - - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - goto err_iomap; - } - - ret = request_irq(i2c->irq, nuc900_i2c_irq, IRQF_SHARED, - dev_name(&pdev->dev), i2c); - - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_iomap; - } - - /* Note, previous versions of the driver used i2c_add_adapter() - * to add the bus at any number. We now pass the bus number via - * the platform data, so if unset it will now default to always - * being bus 0. - */ - - i2c->adap.nr = pdata->bus_num; - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); - goto err_irq; - } - - platform_set_drvdata(pdev, i2c); - - dev_info(&pdev->dev, "%s: NUC900 I2C adapter\n", - dev_name(&i2c->adap.dev)); - return 0; - - err_irq: - free_irq(i2c->irq, i2c); - - err_iomap: - iounmap(i2c->regs); - - err_ioarea: - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - - err_clk: - clk_disable(i2c->clk); - clk_put(i2c->clk); - - err_noclk: - kfree(i2c); - return ret; -} - -/* nuc900_i2c_remove - * - * called when device is removed from the bus -*/ - -static int __devexit nuc900_i2c_remove(struct platform_device *pdev) -{ - struct nuc900_i2c *i2c = platform_get_drvdata(pdev); - - i2c_del_adapter(&i2c->adap); - free_irq(i2c->irq, i2c); - - clk_disable(i2c->clk); - clk_put(i2c->clk); - - iounmap(i2c->regs); - - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - kfree(i2c); - - return 0; -} - -static struct platform_driver nuc900_i2c_driver = { - .probe = nuc900_i2c_probe, - .remove = __devexit_p(nuc900_i2c_remove), - .driver = { - .owner = THIS_MODULE, - .name = "nuc900-i2c0", - }, -}; - -static int __init i2c_adap_nuc900_init(void) -{ - return platform_driver_register(&nuc900_i2c_driver); -} - -static void __exit i2c_adap_nuc900_exit(void) -{ - platform_driver_unregister(&nuc900_i2c_driver); -} -subsys_initcall(i2c_adap_nuc900_init); -module_exit(i2c_adap_nuc900_exit); - -MODULE_DESCRIPTION("NUC900 I2C Bus driver"); -MODULE_AUTHOR("Wan ZongShun, <mcuos.com-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:nuc900-i2c0"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ocores.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-ocores.c deleted file mode 100644 index 18068dee..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-ocores.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * i2c-ocores.c: I2C bus driver for OpenCores I2C controller - * (http://www.opencores.org/projects.cgi/web/i2c/overview). - * - * Peter Korsgaard <jacmet@sunsite.dk> - * - * This file is licensed under the terms of the GNU General Public License - * version 2. This program is licensed "as is" without any warranty of any - * kind, whether express or implied. - */ - -/* - * Device tree configuration: - * - * Required properties: - * - compatible : "opencores,i2c-ocores" - * - reg : bus address start and address range size of device - * - interrupts : interrupt number - * - regstep : size of device registers in bytes - * - clock-frequency : frequency of bus clock in Hz - * - * Example: - * - * i2c0: ocores@a0000000 { - * compatible = "opencores,i2c-ocores"; - * reg = <0xa0000000 0x8>; - * interrupts = <10>; - * - * regstep = <1>; - * clock-frequency = <20000000>; - * - * -- Devices connected on this I2C bus get - * -- defined here; address- and size-cells - * -- apply to these child devices - * - * #address-cells = <1>; - * #size-cells = <0>; - * - * dummy@60 { - * compatible = "dummy"; - * reg = <60>; - * }; - * }; - * - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/i2c-ocores.h> -#include <linux/slab.h> -#include <linux/io.h> - -struct ocores_i2c { - void __iomem *base; - int regstep; - wait_queue_head_t wait; - struct i2c_adapter adap; - struct i2c_msg *msg; - int pos; - int nmsgs; - int state; /* see STATE_ */ - int clock_khz; -}; - -/* registers */ -#define OCI2C_PRELOW 0 -#define OCI2C_PREHIGH 1 -#define OCI2C_CONTROL 2 -#define OCI2C_DATA 3 -#define OCI2C_CMD 4 /* write only */ -#define OCI2C_STATUS 4 /* read only, same address as OCI2C_CMD */ - -#define OCI2C_CTRL_IEN 0x40 -#define OCI2C_CTRL_EN 0x80 - -#define OCI2C_CMD_START 0x91 -#define OCI2C_CMD_STOP 0x41 -#define OCI2C_CMD_READ 0x21 -#define OCI2C_CMD_WRITE 0x11 -#define OCI2C_CMD_READ_ACK 0x21 -#define OCI2C_CMD_READ_NACK 0x29 -#define OCI2C_CMD_IACK 0x01 - -#define OCI2C_STAT_IF 0x01 -#define OCI2C_STAT_TIP 0x02 -#define OCI2C_STAT_ARBLOST 0x20 -#define OCI2C_STAT_BUSY 0x40 -#define OCI2C_STAT_NACK 0x80 - -#define STATE_DONE 0 -#define STATE_START 1 -#define STATE_WRITE 2 -#define STATE_READ 3 -#define STATE_ERROR 4 - -static inline void oc_setreg(struct ocores_i2c *i2c, int reg, u8 value) -{ - iowrite8(value, i2c->base + reg * i2c->regstep); -} - -static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg) -{ - return ioread8(i2c->base + reg * i2c->regstep); -} - -static void ocores_process(struct ocores_i2c *i2c) -{ - struct i2c_msg *msg = i2c->msg; - u8 stat = oc_getreg(i2c, OCI2C_STATUS); - - if ((i2c->state == STATE_DONE) || (i2c->state == STATE_ERROR)) { - /* stop has been sent */ - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); - wake_up(&i2c->wait); - return; - } - - /* error? */ - if (stat & OCI2C_STAT_ARBLOST) { - i2c->state = STATE_ERROR; - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); - return; - } - - if ((i2c->state == STATE_START) || (i2c->state == STATE_WRITE)) { - i2c->state = - (msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE; - - if (stat & OCI2C_STAT_NACK) { - i2c->state = STATE_ERROR; - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); - return; - } - } else - msg->buf[i2c->pos++] = oc_getreg(i2c, OCI2C_DATA); - - /* end of msg? */ - if (i2c->pos == msg->len) { - i2c->nmsgs--; - i2c->msg++; - i2c->pos = 0; - msg = i2c->msg; - - if (i2c->nmsgs) { /* end? */ - /* send start? */ - if (!(msg->flags & I2C_M_NOSTART)) { - u8 addr = (msg->addr << 1); - - if (msg->flags & I2C_M_RD) - addr |= 1; - - i2c->state = STATE_START; - - oc_setreg(i2c, OCI2C_DATA, addr); - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); - return; - } else - i2c->state = (msg->flags & I2C_M_RD) - ? STATE_READ : STATE_WRITE; - } else { - i2c->state = STATE_DONE; - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP); - return; - } - } - - if (i2c->state == STATE_READ) { - oc_setreg(i2c, OCI2C_CMD, i2c->pos == (msg->len-1) ? - OCI2C_CMD_READ_NACK : OCI2C_CMD_READ_ACK); - } else { - oc_setreg(i2c, OCI2C_DATA, msg->buf[i2c->pos++]); - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_WRITE); - } -} - -static irqreturn_t ocores_isr(int irq, void *dev_id) -{ - struct ocores_i2c *i2c = dev_id; - - ocores_process(i2c); - - return IRQ_HANDLED; -} - -static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct ocores_i2c *i2c = i2c_get_adapdata(adap); - - i2c->msg = msgs; - i2c->pos = 0; - i2c->nmsgs = num; - i2c->state = STATE_START; - - oc_setreg(i2c, OCI2C_DATA, - (i2c->msg->addr << 1) | - ((i2c->msg->flags & I2C_M_RD) ? 1:0)); - - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_START); - - if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) - return (i2c->state == STATE_DONE) ? num : -EIO; - else - return -ETIMEDOUT; -} - -static void ocores_init(struct ocores_i2c *i2c) -{ - int prescale; - u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); - - /* make sure the device is disabled */ - oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); - - prescale = (i2c->clock_khz / (5*100)) - 1; - oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff); - oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8); - - /* Init the device */ - oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK); - oc_setreg(i2c, OCI2C_CONTROL, ctrl | OCI2C_CTRL_IEN | OCI2C_CTRL_EN); -} - - -static u32 ocores_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm ocores_algorithm = { - .master_xfer = ocores_xfer, - .functionality = ocores_func, -}; - -static struct i2c_adapter ocores_adapter = { - .owner = THIS_MODULE, - .name = "i2c-ocores", - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &ocores_algorithm, -}; - -#ifdef CONFIG_OF -static int ocores_i2c_of_probe(struct platform_device* pdev, - struct ocores_i2c* i2c) -{ - const __be32* val; - - val = of_get_property(pdev->dev.of_node, "regstep", NULL); - if (!val) { - dev_err(&pdev->dev, "Missing required parameter 'regstep'"); - return -ENODEV; - } - i2c->regstep = be32_to_cpup(val); - - val = of_get_property(pdev->dev.of_node, "clock-frequency", NULL); - if (!val) { - dev_err(&pdev->dev, - "Missing required parameter 'clock-frequency'"); - return -ENODEV; - } - i2c->clock_khz = be32_to_cpup(val) / 1000; - - return 0; -} -#else -#define ocores_i2c_of_probe(pdev,i2c) -ENODEV -#endif - -static int __devinit ocores_i2c_probe(struct platform_device *pdev) -{ - struct ocores_i2c *i2c; - struct ocores_i2c_platform_data *pdata; - struct resource *res, *res2; - int ret; - int i; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - res2 = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res2) - return -ENODEV; - - i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - if (!devm_request_mem_region(&pdev->dev, res->start, - resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Memory region busy\n"); - return -EBUSY; - } - - i2c->base = devm_ioremap_nocache(&pdev->dev, res->start, - resource_size(res)); - if (!i2c->base) { - dev_err(&pdev->dev, "Unable to map registers\n"); - return -EIO; - } - - pdata = pdev->dev.platform_data; - if (pdata) { - i2c->regstep = pdata->regstep; - i2c->clock_khz = pdata->clock_khz; - } else { - ret = ocores_i2c_of_probe(pdev, i2c); - if (ret) - return ret; - } - - ocores_init(i2c); - - init_waitqueue_head(&i2c->wait); - ret = devm_request_irq(&pdev->dev, res2->start, ocores_isr, 0, - pdev->name, i2c); - if (ret) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); - return ret; - } - - /* hook up driver to tree */ - platform_set_drvdata(pdev, i2c); - i2c->adap = ocores_adapter; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.dev.of_node = pdev->dev.of_node; - - /* add i2c adapter to i2c tree */ - ret = i2c_add_adapter(&i2c->adap); - if (ret) { - dev_err(&pdev->dev, "Failed to add adapter\n"); - return ret; - } - - /* add in known devices to the bus */ - if (pdata) { - for (i = 0; i < pdata->num_devices; i++) - i2c_new_device(&i2c->adap, pdata->devices + i); - } - - return 0; -} - -static int __devexit ocores_i2c_remove(struct platform_device* pdev) -{ - struct ocores_i2c *i2c = platform_get_drvdata(pdev); - - /* disable i2c logic */ - oc_setreg(i2c, OCI2C_CONTROL, oc_getreg(i2c, OCI2C_CONTROL) - & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); - - /* remove adapter & data */ - i2c_del_adapter(&i2c->adap); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -#ifdef CONFIG_PM -static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct ocores_i2c *i2c = platform_get_drvdata(pdev); - u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL); - - /* make sure the device is disabled */ - oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN)); - - return 0; -} - -static int ocores_i2c_resume(struct platform_device *pdev) -{ - struct ocores_i2c *i2c = platform_get_drvdata(pdev); - - ocores_init(i2c); - - return 0; -} -#else -#define ocores_i2c_suspend NULL -#define ocores_i2c_resume NULL -#endif - -static struct of_device_id ocores_i2c_match[] = { - { .compatible = "opencores,i2c-ocores", }, - {}, -}; -MODULE_DEVICE_TABLE(of, ocores_i2c_match); - -static struct platform_driver ocores_i2c_driver = { - .probe = ocores_i2c_probe, - .remove = __devexit_p(ocores_i2c_remove), - .suspend = ocores_i2c_suspend, - .resume = ocores_i2c_resume, - .driver = { - .owner = THIS_MODULE, - .name = "ocores-i2c", - .of_match_table = ocores_i2c_match, - }, -}; - -module_platform_driver(ocores_i2c_driver); - -MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); -MODULE_DESCRIPTION("OpenCores I2C bus driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ocores-i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-octeon.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-octeon.c deleted file mode 100644 index ee139a59..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-octeon.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * (C) Copyright 2009-2010 - * Nokia Siemens Networks, michael.lawnick.ext@nsn.com - * - * Portions Copyright (C) 2010 Cavium Networks, Inc. - * - * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/slab.h> -#include <linux/init.h> - -#include <linux/io.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/platform_device.h> - -#include <asm/octeon/octeon.h> - -#define DRV_NAME "i2c-octeon" - -/* The previous out-of-tree version was implicitly version 1.0. */ -#define DRV_VERSION "2.0" - -/* register offsets */ -#define SW_TWSI 0x00 -#define TWSI_INT 0x10 - -/* Controller command patterns */ -#define SW_TWSI_V 0x8000000000000000ull -#define SW_TWSI_EOP_TWSI_DATA 0x0C00000100000000ull -#define SW_TWSI_EOP_TWSI_CTL 0x0C00000200000000ull -#define SW_TWSI_EOP_TWSI_CLKCTL 0x0C00000300000000ull -#define SW_TWSI_EOP_TWSI_STAT 0x0C00000300000000ull -#define SW_TWSI_EOP_TWSI_RST 0x0C00000700000000ull -#define SW_TWSI_OP_TWSI_CLK 0x0800000000000000ull -#define SW_TWSI_R 0x0100000000000000ull - -/* Controller command and status bits */ -#define TWSI_CTL_CE 0x80 -#define TWSI_CTL_ENAB 0x40 -#define TWSI_CTL_STA 0x20 -#define TWSI_CTL_STP 0x10 -#define TWSI_CTL_IFLG 0x08 -#define TWSI_CTL_AAK 0x04 - -/* Some status values */ -#define STAT_START 0x08 -#define STAT_RSTART 0x10 -#define STAT_TXADDR_ACK 0x18 -#define STAT_TXDATA_ACK 0x28 -#define STAT_RXADDR_ACK 0x40 -#define STAT_RXDATA_ACK 0x50 -#define STAT_IDLE 0xF8 - -struct octeon_i2c { - wait_queue_head_t queue; - struct i2c_adapter adap; - int irq; - int twsi_freq; - int sys_freq; - resource_size_t twsi_phys; - void __iomem *twsi_base; - resource_size_t regsize; - struct device *dev; -}; - -/** - * octeon_i2c_write_sw - write an I2C core register. - * @i2c: The struct octeon_i2c. - * @eop_reg: Register selector. - * @data: Value to be written. - * - * The I2C core registers are accessed indirectly via the SW_TWSI CSR. - */ -static void octeon_i2c_write_sw(struct octeon_i2c *i2c, - u64 eop_reg, - u8 data) -{ - u64 tmp; - - __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); - } while ((tmp & SW_TWSI_V) != 0); -} - -/** - * octeon_i2c_read_sw - write an I2C core register. - * @i2c: The struct octeon_i2c. - * @eop_reg: Register selector. - * - * Returns the data. - * - * The I2C core registers are accessed indirectly via the SW_TWSI CSR. - */ -static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg) -{ - u64 tmp; - - __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI); - do { - tmp = __raw_readq(i2c->twsi_base + SW_TWSI); - } while ((tmp & SW_TWSI_V) != 0); - - return tmp & 0xFF; -} - -/** - * octeon_i2c_write_int - write the TWSI_INT register - * @i2c: The struct octeon_i2c. - * @data: Value to be written. - */ -static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data) -{ - u64 tmp; - - __raw_writeq(data, i2c->twsi_base + TWSI_INT); - tmp = __raw_readq(i2c->twsi_base + TWSI_INT); -} - -/** - * octeon_i2c_int_enable - enable the TS interrupt. - * @i2c: The struct octeon_i2c. - * - * The interrupt will be asserted when there is non-STAT_IDLE state in - * the SW_TWSI_EOP_TWSI_STAT register. - */ -static void octeon_i2c_int_enable(struct octeon_i2c *i2c) -{ - octeon_i2c_write_int(i2c, 0x40); -} - -/** - * octeon_i2c_int_disable - disable the TS interrupt. - * @i2c: The struct octeon_i2c. - */ -static void octeon_i2c_int_disable(struct octeon_i2c *i2c) -{ - octeon_i2c_write_int(i2c, 0); -} - -/** - * octeon_i2c_unblock - unblock the bus. - * @i2c: The struct octeon_i2c. - * - * If there was a reset while a device was driving 0 to bus, - * bus is blocked. We toggle it free manually by some clock - * cycles and send a stop. - */ -static void octeon_i2c_unblock(struct octeon_i2c *i2c) -{ - int i; - - dev_dbg(i2c->dev, "%s\n", __func__); - for (i = 0; i < 9; i++) { - octeon_i2c_write_int(i2c, 0x0); - udelay(5); - octeon_i2c_write_int(i2c, 0x200); - udelay(5); - } - octeon_i2c_write_int(i2c, 0x300); - udelay(5); - octeon_i2c_write_int(i2c, 0x100); - udelay(5); - octeon_i2c_write_int(i2c, 0x0); -} - -/** - * octeon_i2c_isr - the interrupt service routine. - * @int: The irq, unused. - * @dev_id: Our struct octeon_i2c. - */ -static irqreturn_t octeon_i2c_isr(int irq, void *dev_id) -{ - struct octeon_i2c *i2c = dev_id; - - octeon_i2c_int_disable(i2c); - wake_up_interruptible(&i2c->queue); - - return IRQ_HANDLED; -} - - -static int octeon_i2c_test_iflg(struct octeon_i2c *i2c) -{ - return (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_CTL) & TWSI_CTL_IFLG) != 0; -} - -/** - * octeon_i2c_wait - wait for the IFLG to be set. - * @i2c: The struct octeon_i2c. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_wait(struct octeon_i2c *i2c) -{ - int result; - - octeon_i2c_int_enable(i2c); - - result = wait_event_interruptible_timeout(i2c->queue, - octeon_i2c_test_iflg(i2c), - i2c->adap.timeout); - - octeon_i2c_int_disable(i2c); - - if (result < 0) { - dev_dbg(i2c->dev, "%s: wait interrupted\n", __func__); - return result; - } else if (result == 0) { - dev_dbg(i2c->dev, "%s: timeout\n", __func__); - return -ETIMEDOUT; - } - - return 0; -} - -/** - * octeon_i2c_start - send START to the bus. - * @i2c: The struct octeon_i2c. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_start(struct octeon_i2c *i2c) -{ - u8 data; - int result; - - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STA); - - result = octeon_i2c_wait(i2c); - if (result) { - if (octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT) == STAT_IDLE) { - /* - * Controller refused to send start flag May - * be a client is holding SDA low - let's try - * to free it. - */ - octeon_i2c_unblock(i2c); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STA); - - result = octeon_i2c_wait(i2c); - } - if (result) - return result; - } - - data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - if ((data != STAT_START) && (data != STAT_RSTART)) { - dev_err(i2c->dev, "%s: bad status (0x%x)\n", __func__, data); - return -EIO; - } - - return 0; -} - -/** - * octeon_i2c_stop - send STOP to the bus. - * @i2c: The struct octeon_i2c. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_stop(struct octeon_i2c *i2c) -{ - u8 data; - - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_STP); - - data = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - - if (data != STAT_IDLE) { - dev_err(i2c->dev, "%s: bad status(0x%x)\n", __func__, data); - return -EIO; - } - return 0; -} - -/** - * octeon_i2c_write - send data to the bus. - * @i2c: The struct octeon_i2c. - * @target: Target address. - * @data: Pointer to the data to be sent. - * @length: Length of the data. - * - * The address is sent over the bus, then the data. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_write(struct octeon_i2c *i2c, int target, - const u8 *data, int length) -{ - int i, result; - u8 tmp; - - result = octeon_i2c_start(i2c); - if (result) - return result; - - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, target << 1); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - for (i = 0; i < length; i++) { - tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - if ((tmp != STAT_TXADDR_ACK) && (tmp != STAT_TXDATA_ACK)) { - dev_err(i2c->dev, - "%s: bad status before write (0x%x)\n", - __func__, tmp); - return -EIO; - } - - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, data[i]); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - } - - return 0; -} - -/** - * octeon_i2c_read - receive data from the bus. - * @i2c: The struct octeon_i2c. - * @target: Target address. - * @data: Pointer to the location to store the datae . - * @length: Length of the data. - * - * The address is sent over the bus, then the data is read. - * - * Returns 0 on success, otherwise a negative errno. - */ -static int octeon_i2c_read(struct octeon_i2c *i2c, int target, - u8 *data, int length) -{ - int i, result; - u8 tmp; - - if (length < 1) - return -EINVAL; - - result = octeon_i2c_start(i2c); - if (result) - return result; - - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_DATA, (target<<1) | 1); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - for (i = 0; i < length; i++) { - tmp = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - if ((tmp != STAT_RXDATA_ACK) && (tmp != STAT_RXADDR_ACK)) { - dev_err(i2c->dev, - "%s: bad status before read (0x%x)\n", - __func__, tmp); - return -EIO; - } - - if (i+1 < length) - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB | TWSI_CTL_AAK); - else - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, - TWSI_CTL_ENAB); - - result = octeon_i2c_wait(i2c); - if (result) - return result; - - data[i] = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_DATA); - } - return 0; -} - -/** - * octeon_i2c_xfer - The driver's master_xfer function. - * @adap: Pointer to the i2c_adapter structure. - * @msgs: Pointer to the messages to be processed. - * @num: Length of the MSGS array. - * - * Returns the number of messages processed, or a negative errno on - * failure. - */ -static int octeon_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, - int num) -{ - struct i2c_msg *pmsg; - int i; - int ret = 0; - struct octeon_i2c *i2c = i2c_get_adapdata(adap); - - for (i = 0; ret == 0 && i < num; i++) { - pmsg = &msgs[i]; - dev_dbg(i2c->dev, - "Doing %s %d byte(s) to/from 0x%02x - %d of %d messages\n", - pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->len, pmsg->addr, i + 1, num); - if (pmsg->flags & I2C_M_RD) - ret = octeon_i2c_read(i2c, pmsg->addr, pmsg->buf, - pmsg->len); - else - ret = octeon_i2c_write(i2c, pmsg->addr, pmsg->buf, - pmsg->len); - } - octeon_i2c_stop(i2c); - - return (ret != 0) ? ret : num; -} - -static u32 octeon_i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm octeon_i2c_algo = { - .master_xfer = octeon_i2c_xfer, - .functionality = octeon_i2c_functionality, -}; - -static struct i2c_adapter octeon_i2c_ops = { - .owner = THIS_MODULE, - .name = "OCTEON adapter", - .algo = &octeon_i2c_algo, - .timeout = 2, -}; - -/** - * octeon_i2c_setclock - Calculate and set clock divisors. - */ -static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c) -{ - int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff; - int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; - - for (ndiv_idx = 0; ndiv_idx < 8 && delta_hz != 0; ndiv_idx++) { - /* - * An mdiv value of less than 2 seems to not work well - * with ds1337 RTCs, so we constrain it to larger - * values. - */ - for (mdiv_idx = 15; mdiv_idx >= 2 && delta_hz != 0; mdiv_idx--) { - /* - * For given ndiv and mdiv values check the - * two closest thp values. - */ - tclk = i2c->twsi_freq * (mdiv_idx + 1) * 10; - tclk *= (1 << ndiv_idx); - thp_base = (i2c->sys_freq / (tclk * 2)) - 1; - for (inc = 0; inc <= 1; inc++) { - thp_idx = thp_base + inc; - if (thp_idx < 5 || thp_idx > 0xff) - continue; - - foscl = i2c->sys_freq / (2 * (thp_idx + 1)); - foscl = foscl / (1 << ndiv_idx); - foscl = foscl / (mdiv_idx + 1) / 10; - diff = abs(foscl - i2c->twsi_freq); - if (diff < delta_hz) { - delta_hz = diff; - thp = thp_idx; - mdiv = mdiv_idx; - ndiv = ndiv_idx; - } - } - } - } - octeon_i2c_write_sw(i2c, SW_TWSI_OP_TWSI_CLK, thp); - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CLKCTL, (mdiv << 3) | ndiv); - - return 0; -} - -static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c) -{ - u8 status; - int tries; - - /* disable high level controller, enable bus access */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_CTL, TWSI_CTL_ENAB); - - /* reset controller */ - octeon_i2c_write_sw(i2c, SW_TWSI_EOP_TWSI_RST, 0); - - for (tries = 10; tries; tries--) { - udelay(1); - status = octeon_i2c_read_sw(i2c, SW_TWSI_EOP_TWSI_STAT); - if (status == STAT_IDLE) - return 0; - } - dev_err(i2c->dev, "%s: TWSI_RST failed! (0x%x)\n", __func__, status); - return -EIO; -} - -static int __devinit octeon_i2c_probe(struct platform_device *pdev) -{ - int irq, result = 0; - struct octeon_i2c *i2c; - struct octeon_i2c_data *i2c_data; - struct resource *res_mem; - - /* All adaptors have an irq. */ - irq = platform_get_irq(pdev, 0); - if (irq < 0) - return irq; - - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "kzalloc failed\n"); - result = -ENOMEM; - goto out; - } - i2c->dev = &pdev->dev; - i2c_data = pdev->dev.platform_data; - - res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - if (res_mem == NULL) { - dev_err(i2c->dev, "found no memory resource\n"); - result = -ENXIO; - goto fail_region; - } - - if (i2c_data == NULL) { - dev_err(i2c->dev, "no I2C frequency data\n"); - result = -ENXIO; - goto fail_region; - } - - i2c->twsi_phys = res_mem->start; - i2c->regsize = resource_size(res_mem); - i2c->twsi_freq = i2c_data->i2c_freq; - i2c->sys_freq = i2c_data->sys_freq; - - if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) { - dev_err(i2c->dev, "request_mem_region failed\n"); - goto fail_region; - } - i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize); - - init_waitqueue_head(&i2c->queue); - - i2c->irq = irq; - - result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); - if (result < 0) { - dev_err(i2c->dev, "failed to attach interrupt\n"); - goto fail_irq; - } - - result = octeon_i2c_initlowlevel(i2c); - if (result) { - dev_err(i2c->dev, "init low level failed\n"); - goto fail_add; - } - - result = octeon_i2c_setclock(i2c); - if (result) { - dev_err(i2c->dev, "clock init failed\n"); - goto fail_add; - } - - i2c->adap = octeon_i2c_ops; - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; - i2c_set_adapdata(&i2c->adap, i2c); - platform_set_drvdata(pdev, i2c); - - result = i2c_add_numbered_adapter(&i2c->adap); - if (result < 0) { - dev_err(i2c->dev, "failed to add adapter\n"); - goto fail_add; - } - - dev_info(i2c->dev, "version %s\n", DRV_VERSION); - - return result; - -fail_add: - platform_set_drvdata(pdev, NULL); - free_irq(i2c->irq, i2c); -fail_irq: - iounmap(i2c->twsi_base); - release_mem_region(i2c->twsi_phys, i2c->regsize); -fail_region: - kfree(i2c); -out: - return result; -}; - -static int __devexit octeon_i2c_remove(struct platform_device *pdev) -{ - struct octeon_i2c *i2c = platform_get_drvdata(pdev); - - i2c_del_adapter(&i2c->adap); - platform_set_drvdata(pdev, NULL); - free_irq(i2c->irq, i2c); - iounmap(i2c->twsi_base); - release_mem_region(i2c->twsi_phys, i2c->regsize); - kfree(i2c); - return 0; -}; - -static struct platform_driver octeon_i2c_driver = { - .probe = octeon_i2c_probe, - .remove = __devexit_p(octeon_i2c_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRV_NAME, - }, -}; - -module_platform_driver(octeon_i2c_driver); - -MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>"); -MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-omap.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-omap.c deleted file mode 100644 index 801df600..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-omap.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * TI OMAP I2C master mode driver - * - * Copyright (C) 2003 MontaVista Software, Inc. - * Copyright (C) 2005 Nokia Corporation - * Copyright (C) 2004 - 2007 Texas Instruments. - * - * Originally written by MontaVista Software, Inc. - * Additional contributions by: - * Tony Lindgren <tony@atomide.com> - * Imre Deak <imre.deak@nokia.com> - * Juha Yrjölä <juha.yrjola@solidboot.com> - * Syed Khasim <x0khasim@ti.com> - * Nishant Menon <nm@ti.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/completion.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/of.h> -#include <linux/of_i2c.h> -#include <linux/of_device.h> -#include <linux/slab.h> -#include <linux/i2c-omap.h> -#include <linux/pm_runtime.h> - -/* I2C controller revisions */ -#define OMAP_I2C_OMAP1_REV_2 0x20 - -/* I2C controller revisions present on specific hardware */ -#define OMAP_I2C_REV_ON_2430 0x36 -#define OMAP_I2C_REV_ON_3430 0x3C -#define OMAP_I2C_REV_ON_3530_4430 0x40 - -/* timeout waiting for the controller to respond */ -#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) - -/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ -enum { - OMAP_I2C_REV_REG = 0, - OMAP_I2C_IE_REG, - OMAP_I2C_STAT_REG, - OMAP_I2C_IV_REG, - OMAP_I2C_WE_REG, - OMAP_I2C_SYSS_REG, - OMAP_I2C_BUF_REG, - OMAP_I2C_CNT_REG, - OMAP_I2C_DATA_REG, - OMAP_I2C_SYSC_REG, - OMAP_I2C_CON_REG, - OMAP_I2C_OA_REG, - OMAP_I2C_SA_REG, - OMAP_I2C_PSC_REG, - OMAP_I2C_SCLL_REG, - OMAP_I2C_SCLH_REG, - OMAP_I2C_SYSTEST_REG, - OMAP_I2C_BUFSTAT_REG, - /* only on OMAP4430 */ - OMAP_I2C_IP_V2_REVNB_LO, - OMAP_I2C_IP_V2_REVNB_HI, - OMAP_I2C_IP_V2_IRQSTATUS_RAW, - OMAP_I2C_IP_V2_IRQENABLE_SET, - OMAP_I2C_IP_V2_IRQENABLE_CLR, -}; - -/* I2C Interrupt Enable Register (OMAP_I2C_IE): */ -#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ -#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */ -#define OMAP_I2C_IE_XRDY (1 << 4) /* TX data ready int enable */ -#define OMAP_I2C_IE_RRDY (1 << 3) /* RX data ready int enable */ -#define OMAP_I2C_IE_ARDY (1 << 2) /* Access ready int enable */ -#define OMAP_I2C_IE_NACK (1 << 1) /* No ack interrupt enable */ -#define OMAP_I2C_IE_AL (1 << 0) /* Arbitration lost int ena */ - -/* I2C Status Register (OMAP_I2C_STAT): */ -#define OMAP_I2C_STAT_XDR (1 << 14) /* TX Buffer draining */ -#define OMAP_I2C_STAT_RDR (1 << 13) /* RX Buffer draining */ -#define OMAP_I2C_STAT_BB (1 << 12) /* Bus busy */ -#define OMAP_I2C_STAT_ROVR (1 << 11) /* Receive overrun */ -#define OMAP_I2C_STAT_XUDF (1 << 10) /* Transmit underflow */ -#define OMAP_I2C_STAT_AAS (1 << 9) /* Address as slave */ -#define OMAP_I2C_STAT_AD0 (1 << 8) /* Address zero */ -#define OMAP_I2C_STAT_XRDY (1 << 4) /* Transmit data ready */ -#define OMAP_I2C_STAT_RRDY (1 << 3) /* Receive data ready */ -#define OMAP_I2C_STAT_ARDY (1 << 2) /* Register access ready */ -#define OMAP_I2C_STAT_NACK (1 << 1) /* No ack interrupt enable */ -#define OMAP_I2C_STAT_AL (1 << 0) /* Arbitration lost int ena */ - -/* I2C WE wakeup enable register */ -#define OMAP_I2C_WE_XDR_WE (1 << 14) /* TX drain wakup */ -#define OMAP_I2C_WE_RDR_WE (1 << 13) /* RX drain wakeup */ -#define OMAP_I2C_WE_AAS_WE (1 << 9) /* Address as slave wakeup*/ -#define OMAP_I2C_WE_BF_WE (1 << 8) /* Bus free wakeup */ -#define OMAP_I2C_WE_STC_WE (1 << 6) /* Start condition wakeup */ -#define OMAP_I2C_WE_GC_WE (1 << 5) /* General call wakeup */ -#define OMAP_I2C_WE_DRDY_WE (1 << 3) /* TX/RX data ready wakeup */ -#define OMAP_I2C_WE_ARDY_WE (1 << 2) /* Reg access ready wakeup */ -#define OMAP_I2C_WE_NACK_WE (1 << 1) /* No acknowledgment wakeup */ -#define OMAP_I2C_WE_AL_WE (1 << 0) /* Arbitration lost wakeup */ - -#define OMAP_I2C_WE_ALL (OMAP_I2C_WE_XDR_WE | OMAP_I2C_WE_RDR_WE | \ - OMAP_I2C_WE_AAS_WE | OMAP_I2C_WE_BF_WE | \ - OMAP_I2C_WE_STC_WE | OMAP_I2C_WE_GC_WE | \ - OMAP_I2C_WE_DRDY_WE | OMAP_I2C_WE_ARDY_WE | \ - OMAP_I2C_WE_NACK_WE | OMAP_I2C_WE_AL_WE) - -/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */ -#define OMAP_I2C_BUF_RDMA_EN (1 << 15) /* RX DMA channel enable */ -#define OMAP_I2C_BUF_RXFIF_CLR (1 << 14) /* RX FIFO Clear */ -#define OMAP_I2C_BUF_XDMA_EN (1 << 7) /* TX DMA channel enable */ -#define OMAP_I2C_BUF_TXFIF_CLR (1 << 6) /* TX FIFO Clear */ - -/* I2C Configuration Register (OMAP_I2C_CON): */ -#define OMAP_I2C_CON_EN (1 << 15) /* I2C module enable */ -#define OMAP_I2C_CON_BE (1 << 14) /* Big endian mode */ -#define OMAP_I2C_CON_OPMODE_HS (1 << 12) /* High Speed support */ -#define OMAP_I2C_CON_STB (1 << 11) /* Start byte mode (master) */ -#define OMAP_I2C_CON_MST (1 << 10) /* Master/slave mode */ -#define OMAP_I2C_CON_TRX (1 << 9) /* TX/RX mode (master only) */ -#define OMAP_I2C_CON_XA (1 << 8) /* Expand address */ -#define OMAP_I2C_CON_RM (1 << 2) /* Repeat mode (master only) */ -#define OMAP_I2C_CON_STP (1 << 1) /* Stop cond (master only) */ -#define OMAP_I2C_CON_STT (1 << 0) /* Start condition (master) */ - -/* I2C SCL time value when Master */ -#define OMAP_I2C_SCLL_HSSCLL 8 -#define OMAP_I2C_SCLH_HSSCLH 8 - -/* I2C System Test Register (OMAP_I2C_SYSTEST): */ -#ifdef DEBUG -#define OMAP_I2C_SYSTEST_ST_EN (1 << 15) /* System test enable */ -#define OMAP_I2C_SYSTEST_FREE (1 << 14) /* Free running mode */ -#define OMAP_I2C_SYSTEST_TMODE_MASK (3 << 12) /* Test mode select */ -#define OMAP_I2C_SYSTEST_TMODE_SHIFT (12) /* Test mode select */ -#define OMAP_I2C_SYSTEST_SCL_I (1 << 3) /* SCL line sense in */ -#define OMAP_I2C_SYSTEST_SCL_O (1 << 2) /* SCL line drive out */ -#define OMAP_I2C_SYSTEST_SDA_I (1 << 1) /* SDA line sense in */ -#define OMAP_I2C_SYSTEST_SDA_O (1 << 0) /* SDA line drive out */ -#endif - -/* OCP_SYSSTATUS bit definitions */ -#define SYSS_RESETDONE_MASK (1 << 0) - -/* OCP_SYSCONFIG bit definitions */ -#define SYSC_CLOCKACTIVITY_MASK (0x3 << 8) -#define SYSC_SIDLEMODE_MASK (0x3 << 3) -#define SYSC_ENAWAKEUP_MASK (1 << 2) -#define SYSC_SOFTRESET_MASK (1 << 1) -#define SYSC_AUTOIDLE_MASK (1 << 0) - -#define SYSC_IDLEMODE_SMART 0x2 -#define SYSC_CLOCKACTIVITY_FCLK 0x2 - -/* Errata definitions */ -#define I2C_OMAP_ERRATA_I207 (1 << 0) -#define I2C_OMAP3_1P153 (1 << 1) - -struct omap_i2c_dev { - struct device *dev; - void __iomem *base; /* virtual */ - int irq; - int reg_shift; /* bit shift for I2C register addresses */ - struct completion cmd_complete; - struct resource *ioarea; - u32 latency; /* maximum mpu wkup latency */ - void (*set_mpu_wkup_lat)(struct device *dev, - long latency); - u32 speed; /* Speed of bus in kHz */ - u32 dtrev; /* extra revision from DT */ - u32 flags; - u16 cmd_err; - u8 *buf; - u8 *regs; - size_t buf_len; - struct i2c_adapter adapter; - u8 fifo_size; /* use as flag and value - * fifo_size==0 implies no fifo - * if set, should be trsh+1 - */ - u8 rev; - unsigned b_hw:1; /* bad h/w fixes */ - u16 iestate; /* Saved interrupt register */ - u16 pscstate; - u16 scllstate; - u16 sclhstate; - u16 bufstate; - u16 syscstate; - u16 westate; - u16 errata; -}; - -static const u8 reg_map_ip_v1[] = { - [OMAP_I2C_REV_REG] = 0x00, - [OMAP_I2C_IE_REG] = 0x01, - [OMAP_I2C_STAT_REG] = 0x02, - [OMAP_I2C_IV_REG] = 0x03, - [OMAP_I2C_WE_REG] = 0x03, - [OMAP_I2C_SYSS_REG] = 0x04, - [OMAP_I2C_BUF_REG] = 0x05, - [OMAP_I2C_CNT_REG] = 0x06, - [OMAP_I2C_DATA_REG] = 0x07, - [OMAP_I2C_SYSC_REG] = 0x08, - [OMAP_I2C_CON_REG] = 0x09, - [OMAP_I2C_OA_REG] = 0x0a, - [OMAP_I2C_SA_REG] = 0x0b, - [OMAP_I2C_PSC_REG] = 0x0c, - [OMAP_I2C_SCLL_REG] = 0x0d, - [OMAP_I2C_SCLH_REG] = 0x0e, - [OMAP_I2C_SYSTEST_REG] = 0x0f, - [OMAP_I2C_BUFSTAT_REG] = 0x10, -}; - -static const u8 reg_map_ip_v2[] = { - [OMAP_I2C_REV_REG] = 0x04, - [OMAP_I2C_IE_REG] = 0x2c, - [OMAP_I2C_STAT_REG] = 0x28, - [OMAP_I2C_IV_REG] = 0x34, - [OMAP_I2C_WE_REG] = 0x34, - [OMAP_I2C_SYSS_REG] = 0x90, - [OMAP_I2C_BUF_REG] = 0x94, - [OMAP_I2C_CNT_REG] = 0x98, - [OMAP_I2C_DATA_REG] = 0x9c, - [OMAP_I2C_SYSC_REG] = 0x10, - [OMAP_I2C_CON_REG] = 0xa4, - [OMAP_I2C_OA_REG] = 0xa8, - [OMAP_I2C_SA_REG] = 0xac, - [OMAP_I2C_PSC_REG] = 0xb0, - [OMAP_I2C_SCLL_REG] = 0xb4, - [OMAP_I2C_SCLH_REG] = 0xb8, - [OMAP_I2C_SYSTEST_REG] = 0xbC, - [OMAP_I2C_BUFSTAT_REG] = 0xc0, - [OMAP_I2C_IP_V2_REVNB_LO] = 0x00, - [OMAP_I2C_IP_V2_REVNB_HI] = 0x04, - [OMAP_I2C_IP_V2_IRQSTATUS_RAW] = 0x24, - [OMAP_I2C_IP_V2_IRQENABLE_SET] = 0x2c, - [OMAP_I2C_IP_V2_IRQENABLE_CLR] = 0x30, -}; - -static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, - int reg, u16 val) -{ - __raw_writew(val, i2c_dev->base + - (i2c_dev->regs[reg] << i2c_dev->reg_shift)); -} - -static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) -{ - return __raw_readw(i2c_dev->base + - (i2c_dev->regs[reg] << i2c_dev->reg_shift)); -} - -static void omap_i2c_unidle(struct omap_i2c_dev *dev) -{ - if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, dev->pscstate); - omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, dev->scllstate); - omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, dev->sclhstate); - omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, dev->bufstate); - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, dev->syscstate); - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - } - - /* - * Don't write to this register if the IE state is 0 as it can - * cause deadlock. - */ - if (dev->iestate) - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); -} - -static void omap_i2c_idle(struct omap_i2c_dev *dev) -{ - u16 iv; - - dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - if (dev->dtrev == OMAP_I2C_IP_VERSION_2) - omap_i2c_write_reg(dev, OMAP_I2C_IP_V2_IRQENABLE_CLR, 1); - else - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); - - if (dev->rev < OMAP_I2C_OMAP1_REV_2) { - iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ - } else { - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, dev->iestate); - - /* Flush posted write */ - omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); - } -} - -static int omap_i2c_init(struct omap_i2c_dev *dev) -{ - u16 psc = 0, scll = 0, sclh = 0, buf = 0; - u16 fsscll = 0, fssclh = 0, hsscll = 0, hssclh = 0; - unsigned long fclk_rate = 12000000; - unsigned long timeout; - unsigned long internal_clk = 0; - struct clk *fclk; - - if (dev->rev >= OMAP_I2C_OMAP1_REV_2) { - /* Disable I2C controller before soft reset */ - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, - omap_i2c_read_reg(dev, OMAP_I2C_CON_REG) & - ~(OMAP_I2C_CON_EN)); - - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, SYSC_SOFTRESET_MASK); - /* For some reason we need to set the EN bit before the - * reset done bit gets set. */ - timeout = jiffies + OMAP_I2C_TIMEOUT; - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) & - SYSS_RESETDONE_MASK)) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, "timeout waiting " - "for controller reset\n"); - return -ETIMEDOUT; - } - msleep(1); - } - - /* SYSC register is cleared by the reset; rewrite it */ - if (dev->rev == OMAP_I2C_REV_ON_2430) { - - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, - SYSC_AUTOIDLE_MASK); - - } else if (dev->rev >= OMAP_I2C_REV_ON_3430) { - dev->syscstate = SYSC_AUTOIDLE_MASK; - dev->syscstate |= SYSC_ENAWAKEUP_MASK; - dev->syscstate |= (SYSC_IDLEMODE_SMART << - __ffs(SYSC_SIDLEMODE_MASK)); - dev->syscstate |= (SYSC_CLOCKACTIVITY_FCLK << - __ffs(SYSC_CLOCKACTIVITY_MASK)); - - omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, - dev->syscstate); - /* - * Enabling all wakup sources to stop I2C freezing on - * WFI instruction. - * REVISIT: Some wkup sources might not be needed. - */ - dev->westate = OMAP_I2C_WE_ALL; - omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, - dev->westate); - } - } - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - - if (dev->flags & OMAP_I2C_FLAG_ALWAYS_ARMXOR_CLK) { - /* - * The I2C functional clock is the armxor_ck, so there's - * no need to get "armxor_ck" separately. Now, if OMAP2420 - * always returns 12MHz for the functional clock, we can - * do this bit unconditionally. - */ - fclk = clk_get(dev->dev, "fck"); - fclk_rate = clk_get_rate(fclk); - clk_put(fclk); - - /* TRM for 5912 says the I2C clock must be prescaled to be - * between 7 - 12 MHz. The XOR input clock is typically - * 12, 13 or 19.2 MHz. So we should have code that produces: - * - * XOR MHz Divider Prescaler - * 12 1 0 - * 13 2 1 - * 19.2 2 1 - */ - if (fclk_rate > 12000000) - psc = fclk_rate / 12000000; - } - - if (!(dev->flags & OMAP_I2C_FLAG_SIMPLE_CLOCK)) { - - /* - * HSI2C controller internal clk rate should be 19.2 Mhz for - * HS and for all modes on 2430. On 34xx we can use lower rate - * to get longer filter period for better noise suppression. - * The filter is iclk (fclk for HS) period. - */ - if (dev->speed > 400 || - dev->flags & OMAP_I2C_FLAG_FORCE_19200_INT_CLK) - internal_clk = 19200; - else if (dev->speed > 100) - internal_clk = 9600; - else - internal_clk = 4000; - fclk = clk_get(dev->dev, "fck"); - fclk_rate = clk_get_rate(fclk) / 1000; - clk_put(fclk); - - /* Compute prescaler divisor */ - psc = fclk_rate / internal_clk; - psc = psc - 1; - - /* If configured for High Speed */ - if (dev->speed > 400) { - unsigned long scl; - - /* For first phase of HS mode */ - scl = internal_clk / 400; - fsscll = scl - (scl / 3) - 7; - fssclh = (scl / 3) - 5; - - /* For second phase of HS mode */ - scl = fclk_rate / dev->speed; - hsscll = scl - (scl / 3) - 7; - hssclh = (scl / 3) - 5; - } else if (dev->speed > 100) { - unsigned long scl; - - /* Fast mode */ - scl = internal_clk / dev->speed; - fsscll = scl - (scl / 3) - 7; - fssclh = (scl / 3) - 5; - } else { - /* Standard mode */ - fsscll = internal_clk / (dev->speed * 2) - 7; - fssclh = internal_clk / (dev->speed * 2) - 5; - } - scll = (hsscll << OMAP_I2C_SCLL_HSSCLL) | fsscll; - sclh = (hssclh << OMAP_I2C_SCLH_HSSCLH) | fssclh; - } else { - /* Program desired operating rate */ - fclk_rate /= (psc + 1) * 1000; - if (psc > 2) - psc = 2; - scll = fclk_rate / (dev->speed * 2) - 7 + psc; - sclh = fclk_rate / (dev->speed * 2) - 7 + psc; - } - - /* Setup clock prescaler to obtain approx 12MHz I2C module clock: */ - omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc); - - /* SCL low and high time values */ - omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG, scll); - omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG, sclh); - - if (dev->fifo_size) { - /* Note: setup required fifo size - 1. RTRSH and XTRSH */ - buf = (dev->fifo_size - 1) << 8 | OMAP_I2C_BUF_RXFIF_CLR | - (dev->fifo_size - 1) | OMAP_I2C_BUF_TXFIF_CLR; - omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, buf); - } - - /* Take the I2C module out of reset: */ - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN); - - dev->errata = 0; - - if (dev->flags & OMAP_I2C_FLAG_APPLY_ERRATA_I207) - dev->errata |= I2C_OMAP_ERRATA_I207; - - /* Enable interrupts */ - dev->iestate = (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY | - OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK | - OMAP_I2C_IE_AL) | ((dev->fifo_size) ? - (OMAP_I2C_IE_RDR | OMAP_I2C_IE_XDR) : 0); - omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, dev->iestate); - if (dev->flags & OMAP_I2C_FLAG_RESET_REGS_POSTIDLE) { - dev->pscstate = psc; - dev->scllstate = scll; - dev->sclhstate = sclh; - dev->bufstate = buf; - } - return 0; -} - -/* - * Waiting on Bus Busy - */ -static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev) -{ - unsigned long timeout; - - timeout = jiffies + OMAP_I2C_TIMEOUT; - while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, "timeout waiting for bus ready\n"); - return -ETIMEDOUT; - } - msleep(1); - } - - return 0; -} - -/* - * Low level master read/write transaction. - */ -static int omap_i2c_xfer_msg(struct i2c_adapter *adap, - struct i2c_msg *msg, int stop) -{ - struct omap_i2c_dev *dev = i2c_get_adapdata(adap); - int r; - u16 w; - - dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n", - msg->addr, msg->len, msg->flags, stop); - - if (msg->len == 0) - return -EINVAL; - - omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr); - - /* REVISIT: Could the STB bit of I2C_CON be used with probing? */ - dev->buf = msg->buf; - dev->buf_len = msg->len; - - omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len); - - /* Clear the FIFO Buffers */ - w = omap_i2c_read_reg(dev, OMAP_I2C_BUF_REG); - w |= OMAP_I2C_BUF_RXFIF_CLR | OMAP_I2C_BUF_TXFIF_CLR; - omap_i2c_write_reg(dev, OMAP_I2C_BUF_REG, w); - - init_completion(&dev->cmd_complete); - dev->cmd_err = 0; - - w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT; - - /* High speed configuration */ - if (dev->speed > 400) - w |= OMAP_I2C_CON_OPMODE_HS; - - if (msg->flags & I2C_M_TEN) - w |= OMAP_I2C_CON_XA; - if (!(msg->flags & I2C_M_RD)) - w |= OMAP_I2C_CON_TRX; - - if (!dev->b_hw && stop) - w |= OMAP_I2C_CON_STP; - - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); - - /* - * Don't write stt and stp together on some hardware. - */ - if (dev->b_hw && stop) { - unsigned long delay = jiffies + OMAP_I2C_TIMEOUT; - u16 con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); - while (con & OMAP_I2C_CON_STT) { - con = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); - - /* Let the user know if i2c is in a bad state */ - if (time_after(jiffies, delay)) { - dev_err(dev->dev, "controller timed out " - "waiting for start condition to finish\n"); - return -ETIMEDOUT; - } - cpu_relax(); - } - - w |= OMAP_I2C_CON_STP; - w &= ~OMAP_I2C_CON_STT; - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); - } - - /* - * REVISIT: We should abort the transfer on signals, but the bus goes - * into arbitration and we're currently unable to recover from it. - */ - r = wait_for_completion_timeout(&dev->cmd_complete, - OMAP_I2C_TIMEOUT); - dev->buf_len = 0; - if (r < 0) - return r; - if (r == 0) { - dev_err(dev->dev, "controller timed out\n"); - omap_i2c_init(dev); - return -ETIMEDOUT; - } - - if (likely(!dev->cmd_err)) - return 0; - - /* We have an error */ - if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR | - OMAP_I2C_STAT_XUDF)) { - omap_i2c_init(dev); - return -EIO; - } - - if (dev->cmd_err & OMAP_I2C_STAT_NACK) { - if (msg->flags & I2C_M_IGNORE_NAK) - return 0; - if (stop) { - w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG); - w |= OMAP_I2C_CON_STP; - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w); - } - return -EREMOTEIO; - } - return -EIO; -} - - -/* - * Prepare controller for a transaction and call omap_i2c_xfer_msg - * to do the work during IRQ processing. - */ -static int -omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct omap_i2c_dev *dev = i2c_get_adapdata(adap); - int i; - int r; - - pm_runtime_get_sync(dev->dev); - - r = omap_i2c_wait_for_bb(dev); - if (r < 0) - goto out; - - if (dev->set_mpu_wkup_lat != NULL) - dev->set_mpu_wkup_lat(dev->dev, dev->latency); - - for (i = 0; i < num; i++) { - r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1))); - if (r != 0) - break; - } - - if (dev->set_mpu_wkup_lat != NULL) - dev->set_mpu_wkup_lat(dev->dev, -1); - - if (r == 0) - r = num; - - omap_i2c_wait_for_bb(dev); -out: - pm_runtime_put(dev->dev); - return r; -} - -static u32 -omap_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -} - -static inline void -omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err) -{ - dev->cmd_err |= err; - complete(&dev->cmd_complete); -} - -static inline void -omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat) -{ - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat); -} - -static inline void i2c_omap_errata_i207(struct omap_i2c_dev *dev, u16 stat) -{ - /* - * I2C Errata(Errata Nos. OMAP2: 1.67, OMAP3: 1.8) - * Not applicable for OMAP4. - * Under certain rare conditions, RDR could be set again - * when the bus is busy, then ignore the interrupt and - * clear the interrupt. - */ - if (stat & OMAP_I2C_STAT_RDR) { - /* Step 1: If RDR is set, clear it */ - omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); - - /* Step 2: */ - if (!(omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) - & OMAP_I2C_STAT_BB)) { - - /* Step 3: */ - if (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) - & OMAP_I2C_STAT_RDR) { - omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); - dev_dbg(dev->dev, "RDR when bus is busy.\n"); - } - - } - } -} - -/* rev1 devices are apparently only on some 15xx */ -#ifdef CONFIG_ARCH_OMAP15XX - -static irqreturn_t -omap_i2c_omap1_isr(int this_irq, void *dev_id) -{ - struct omap_i2c_dev *dev = dev_id; - u16 iv, w; - - if (pm_runtime_suspended(dev->dev)) - return IRQ_NONE; - - iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); - switch (iv) { - case 0x00: /* None */ - break; - case 0x01: /* Arbitration lost */ - dev_err(dev->dev, "Arbitration lost\n"); - omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL); - break; - case 0x02: /* No acknowledgement */ - omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK); - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP); - break; - case 0x03: /* Register access ready */ - omap_i2c_complete_cmd(dev, 0); - break; - case 0x04: /* Receive data ready */ - if (dev->buf_len) { - w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); - *dev->buf++ = w; - dev->buf_len--; - if (dev->buf_len) { - *dev->buf++ = w >> 8; - dev->buf_len--; - } - } else - dev_err(dev->dev, "RRDY IRQ while no data requested\n"); - break; - case 0x05: /* Transmit data ready */ - if (dev->buf_len) { - w = *dev->buf++; - dev->buf_len--; - if (dev->buf_len) { - w |= *dev->buf++ << 8; - dev->buf_len--; - } - omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); - } else - dev_err(dev->dev, "XRDY IRQ while no data to send\n"); - break; - default: - return IRQ_NONE; - } - - return IRQ_HANDLED; -} -#else -#define omap_i2c_omap1_isr NULL -#endif - -/* - * OMAP3430 Errata 1.153: When an XRDY/XDR is hit, wait for XUDF before writing - * data to DATA_REG. Otherwise some data bytes can be lost while transferring - * them from the memory to the I2C interface. - */ -static int errata_omap3_1p153(struct omap_i2c_dev *dev, u16 *stat, int *err) -{ - unsigned long timeout = 10000; - - while (--timeout && !(*stat & OMAP_I2C_STAT_XUDF)) { - if (*stat & (OMAP_I2C_STAT_NACK | OMAP_I2C_STAT_AL)) { - omap_i2c_ack_stat(dev, *stat & (OMAP_I2C_STAT_XRDY | - OMAP_I2C_STAT_XDR)); - *err |= OMAP_I2C_STAT_XUDF; - return -ETIMEDOUT; - } - - cpu_relax(); - *stat = omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG); - } - - if (!timeout) { - dev_err(dev->dev, "timeout waiting on XUDF bit\n"); - return 0; - } - - return 0; -} - -static irqreturn_t -omap_i2c_isr(int this_irq, void *dev_id) -{ - struct omap_i2c_dev *dev = dev_id; - u16 bits; - u16 stat, w; - int err, count = 0; - - if (pm_runtime_suspended(dev->dev)) - return IRQ_NONE; - - bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); - while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) { - dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat); - if (count++ == 100) { - dev_warn(dev->dev, "Too much work in one IRQ\n"); - break; - } - - err = 0; -complete: - /* - * Ack the stat in one go, but [R/X]DR and [R/X]RDY should be - * acked after the data operation is complete. - * Ref: TRM SWPU114Q Figure 18-31 - */ - omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat & - ~(OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | - OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); - - if (stat & OMAP_I2C_STAT_NACK) - err |= OMAP_I2C_STAT_NACK; - - if (stat & OMAP_I2C_STAT_AL) { - dev_err(dev->dev, "Arbitration lost\n"); - err |= OMAP_I2C_STAT_AL; - } - /* - * ProDB0017052: Clear ARDY bit twice - */ - if (stat & (OMAP_I2C_STAT_ARDY | OMAP_I2C_STAT_NACK | - OMAP_I2C_STAT_AL)) { - omap_i2c_ack_stat(dev, stat & - (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR | - OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR | - OMAP_I2C_STAT_ARDY)); - omap_i2c_complete_cmd(dev, err); - return IRQ_HANDLED; - } - if (stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)) { - u8 num_bytes = 1; - - if (dev->errata & I2C_OMAP_ERRATA_I207) - i2c_omap_errata_i207(dev, stat); - - if (dev->fifo_size) { - if (stat & OMAP_I2C_STAT_RRDY) - num_bytes = dev->fifo_size; - else /* read RXSTAT on RDR interrupt */ - num_bytes = (omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG) - >> 8) & 0x3F; - } - while (num_bytes) { - num_bytes--; - w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG); - if (dev->buf_len) { - *dev->buf++ = w; - dev->buf_len--; - /* - * Data reg in 2430, omap3 and - * omap4 is 8 bit wide - */ - if (dev->flags & - OMAP_I2C_FLAG_16BIT_DATA_REG) { - if (dev->buf_len) { - *dev->buf++ = w >> 8; - dev->buf_len--; - } - } - } else { - if (stat & OMAP_I2C_STAT_RRDY) - dev_err(dev->dev, - "RRDY IRQ while no data" - " requested\n"); - if (stat & OMAP_I2C_STAT_RDR) - dev_err(dev->dev, - "RDR IRQ while no data" - " requested\n"); - break; - } - } - omap_i2c_ack_stat(dev, - stat & (OMAP_I2C_STAT_RRDY | OMAP_I2C_STAT_RDR)); - continue; - } - if (stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)) { - u8 num_bytes = 1; - if (dev->fifo_size) { - if (stat & OMAP_I2C_STAT_XRDY) - num_bytes = dev->fifo_size; - else /* read TXSTAT on XDR interrupt */ - num_bytes = omap_i2c_read_reg(dev, - OMAP_I2C_BUFSTAT_REG) - & 0x3F; - } - while (num_bytes) { - num_bytes--; - w = 0; - if (dev->buf_len) { - w = *dev->buf++; - dev->buf_len--; - /* - * Data reg in 2430, omap3 and - * omap4 is 8 bit wide - */ - if (dev->flags & - OMAP_I2C_FLAG_16BIT_DATA_REG) { - if (dev->buf_len) { - w |= *dev->buf++ << 8; - dev->buf_len--; - } - } - } else { - if (stat & OMAP_I2C_STAT_XRDY) - dev_err(dev->dev, - "XRDY IRQ while no " - "data to send\n"); - if (stat & OMAP_I2C_STAT_XDR) - dev_err(dev->dev, - "XDR IRQ while no " - "data to send\n"); - break; - } - - if ((dev->errata & I2C_OMAP3_1P153) && - errata_omap3_1p153(dev, &stat, &err)) - goto complete; - - omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w); - } - omap_i2c_ack_stat(dev, - stat & (OMAP_I2C_STAT_XRDY | OMAP_I2C_STAT_XDR)); - continue; - } - if (stat & OMAP_I2C_STAT_ROVR) { - dev_err(dev->dev, "Receive overrun\n"); - dev->cmd_err |= OMAP_I2C_STAT_ROVR; - } - if (stat & OMAP_I2C_STAT_XUDF) { - dev_err(dev->dev, "Transmit underflow\n"); - dev->cmd_err |= OMAP_I2C_STAT_XUDF; - } - } - - return count ? IRQ_HANDLED : IRQ_NONE; -} - -static const struct i2c_algorithm omap_i2c_algo = { - .master_xfer = omap_i2c_xfer, - .functionality = omap_i2c_func, -}; - -#ifdef CONFIG_OF -static struct omap_i2c_bus_platform_data omap3_pdata = { - .rev = OMAP_I2C_IP_VERSION_1, - .flags = OMAP_I2C_FLAG_APPLY_ERRATA_I207 | - OMAP_I2C_FLAG_RESET_REGS_POSTIDLE | - OMAP_I2C_FLAG_BUS_SHIFT_2, -}; - -static struct omap_i2c_bus_platform_data omap4_pdata = { - .rev = OMAP_I2C_IP_VERSION_2, -}; - -static const struct of_device_id omap_i2c_of_match[] = { - { - .compatible = "ti,omap4-i2c", - .data = &omap4_pdata, - }, - { - .compatible = "ti,omap3-i2c", - .data = &omap3_pdata, - }, - { }, -}; -MODULE_DEVICE_TABLE(of, omap_i2c_of_match); -#endif - -static int __devinit -omap_i2c_probe(struct platform_device *pdev) -{ - struct omap_i2c_dev *dev; - struct i2c_adapter *adap; - struct resource *mem, *irq, *ioarea; - struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; - struct device_node *node = pdev->dev.of_node; - const struct of_device_id *match; - irq_handler_t isr; - int r; - - /* NOTE: driver uses the static register mapping */ - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) { - dev_err(&pdev->dev, "no mem resource?\n"); - return -ENODEV; - } - irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!irq) { - dev_err(&pdev->dev, "no irq resource?\n"); - return -ENODEV; - } - - ioarea = request_mem_region(mem->start, resource_size(mem), - pdev->name); - if (!ioarea) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } - - dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL); - if (!dev) { - r = -ENOMEM; - goto err_release_region; - } - - match = of_match_device(of_match_ptr(omap_i2c_of_match), &pdev->dev); - if (match) { - u32 freq = 100000; /* default to 100000 Hz */ - - pdata = match->data; - dev->dtrev = pdata->rev; - dev->flags = pdata->flags; - - of_property_read_u32(node, "clock-frequency", &freq); - /* convert DT freq value in Hz into kHz for speed */ - dev->speed = freq / 1000; - } else if (pdata != NULL) { - dev->speed = pdata->clkrate; - dev->flags = pdata->flags; - dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; - dev->dtrev = pdata->rev; - } - - dev->dev = &pdev->dev; - dev->irq = irq->start; - dev->base = ioremap(mem->start, resource_size(mem)); - if (!dev->base) { - r = -ENOMEM; - goto err_free_mem; - } - - platform_set_drvdata(pdev, dev); - - dev->reg_shift = (dev->flags >> OMAP_I2C_FLAG_BUS_SHIFT__SHIFT) & 3; - - if (dev->dtrev == OMAP_I2C_IP_VERSION_2) - dev->regs = (u8 *)reg_map_ip_v2; - else - dev->regs = (u8 *)reg_map_ip_v1; - - pm_runtime_enable(dev->dev); - pm_runtime_get_sync(dev->dev); - - dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; - - if (dev->rev <= OMAP_I2C_REV_ON_3430) - dev->errata |= I2C_OMAP3_1P153; - - if (!(dev->flags & OMAP_I2C_FLAG_NO_FIFO)) { - u16 s; - - /* Set up the fifo size - Get total size */ - s = (omap_i2c_read_reg(dev, OMAP_I2C_BUFSTAT_REG) >> 14) & 0x3; - dev->fifo_size = 0x8 << s; - - /* - * Set up notification threshold as half the total available - * size. This is to ensure that we can handle the status on int - * call back latencies. - */ - - dev->fifo_size = (dev->fifo_size / 2); - - if (dev->rev >= OMAP_I2C_REV_ON_3530_4430) - dev->b_hw = 0; /* Disable hardware fixes */ - else - dev->b_hw = 1; /* Enable hardware fixes */ - - /* calculate wakeup latency constraint for MPU */ - if (dev->set_mpu_wkup_lat != NULL) - dev->latency = (1000000 * dev->fifo_size) / - (1000 * dev->speed / 8); - } - - /* reset ASAP, clearing any IRQs */ - omap_i2c_init(dev); - - isr = (dev->rev < OMAP_I2C_OMAP1_REV_2) ? omap_i2c_omap1_isr : - omap_i2c_isr; - r = request_irq(dev->irq, isr, 0, pdev->name, dev); - - if (r) { - dev_err(dev->dev, "failure requesting irq %i\n", dev->irq); - goto err_unuse_clocks; - } - - dev_info(dev->dev, "bus %d rev%d.%d.%d at %d kHz\n", pdev->id, - dev->dtrev, dev->rev >> 4, dev->rev & 0xf, dev->speed); - - pm_runtime_put(dev->dev); - - adap = &dev->adapter; - i2c_set_adapdata(adap, dev); - adap->owner = THIS_MODULE; - adap->class = I2C_CLASS_HWMON; - strlcpy(adap->name, "OMAP I2C adapter", sizeof(adap->name)); - adap->algo = &omap_i2c_algo; - adap->dev.parent = &pdev->dev; - adap->dev.of_node = pdev->dev.of_node; - - /* i2c device drivers may be active on return from add_adapter() */ - adap->nr = pdev->id; - r = i2c_add_numbered_adapter(adap); - if (r) { - dev_err(dev->dev, "failure adding adapter\n"); - goto err_free_irq; - } - - of_i2c_register_devices(adap); - - return 0; - -err_free_irq: - free_irq(dev->irq, dev); -err_unuse_clocks: - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - pm_runtime_put(dev->dev); - iounmap(dev->base); -err_free_mem: - platform_set_drvdata(pdev, NULL); - kfree(dev); -err_release_region: - release_mem_region(mem->start, resource_size(mem)); - - return r; -} - -static int -omap_i2c_remove(struct platform_device *pdev) -{ - struct omap_i2c_dev *dev = platform_get_drvdata(pdev); - struct resource *mem; - - platform_set_drvdata(pdev, NULL); - - free_irq(dev->irq, dev); - i2c_del_adapter(&dev->adapter); - omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); - iounmap(dev->base); - kfree(dev); - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - return 0; -} - -#ifdef CONFIG_PM_RUNTIME -static int omap_i2c_runtime_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); - - omap_i2c_idle(_dev); - - return 0; -} - -static int omap_i2c_runtime_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct omap_i2c_dev *_dev = platform_get_drvdata(pdev); - - omap_i2c_unidle(_dev); - - return 0; -} - -static struct dev_pm_ops omap_i2c_pm_ops = { - .runtime_suspend = omap_i2c_runtime_suspend, - .runtime_resume = omap_i2c_runtime_resume, -}; -#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops) -#else -#define OMAP_I2C_PM_OPS NULL -#endif - -static struct platform_driver omap_i2c_driver = { - .probe = omap_i2c_probe, - .remove = omap_i2c_remove, - .driver = { - .name = "omap_i2c", - .owner = THIS_MODULE, - .pm = OMAP_I2C_PM_OPS, - .of_match_table = of_match_ptr(omap_i2c_of_match), - }, -}; - -/* I2C may be needed to bring up other drivers */ -static int __init -omap_i2c_init_driver(void) -{ - return platform_driver_register(&omap_i2c_driver); -} -subsys_initcall(omap_i2c_init_driver); - -static void __exit omap_i2c_exit_driver(void) -{ - platform_driver_unregister(&omap_i2c_driver); -} -module_exit(omap_i2c_exit_driver); - -MODULE_AUTHOR("MontaVista Software, Inc. (and others)"); -MODULE_DESCRIPTION("TI OMAP I2C bus adapter"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:omap_i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport-light.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport-light.c deleted file mode 100644 index 4b95f7a6..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport-light.c +++ /dev/null @@ -1,281 +0,0 @@ -/* ------------------------------------------------------------------------ * - * i2c-parport-light.c I2C bus over parallel port * - * ------------------------------------------------------------------------ * - Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> - - Based on older i2c-velleman.c driver - Copyright (C) 1995-2000 Simon G. Vogl - With some changes from: - Frodo Looijaard <frodol@dds.nl> - Kyösti Mälkki <kmalkki@cc.hut.fi> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ------------------------------------------------------------------------ */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/i2c-smbus.h> -#include <linux/io.h> -#include "i2c-parport.h" - -#define DEFAULT_BASE 0x378 -#define DRVNAME "i2c-parport-light" - -static struct platform_device *pdev; - -static u16 base; -module_param(base, ushort, 0); -MODULE_PARM_DESC(base, "Base I/O address"); - -static int irq; -module_param(irq, int, 0); -MODULE_PARM_DESC(irq, "IRQ (optional)"); - -/* ----- Low-level parallel port access ----------------------------------- */ - -static inline void port_write(unsigned char p, unsigned char d) -{ - outb(d, base+p); -} - -static inline unsigned char port_read(unsigned char p) -{ - return inb(base+p); -} - -/* ----- Unified line operation functions --------------------------------- */ - -static inline void line_set(int state, const struct lineop *op) -{ - u8 oldval = port_read(op->port); - - /* Touch only the bit(s) needed */ - if ((op->inverted && !state) || (!op->inverted && state)) - port_write(op->port, oldval | op->val); - else - port_write(op->port, oldval & ~op->val); -} - -static inline int line_get(const struct lineop *op) -{ - u8 oldval = port_read(op->port); - - return ((op->inverted && (oldval & op->val) != op->val) - || (!op->inverted && (oldval & op->val) == op->val)); -} - -/* ----- I2C algorithm call-back functions and structures ----------------- */ - -static void parport_setscl(void *data, int state) -{ - line_set(state, &adapter_parm[type].setscl); -} - -static void parport_setsda(void *data, int state) -{ - line_set(state, &adapter_parm[type].setsda); -} - -static int parport_getscl(void *data) -{ - return line_get(&adapter_parm[type].getscl); -} - -static int parport_getsda(void *data) -{ - return line_get(&adapter_parm[type].getsda); -} - -/* Encapsulate the functions above in the correct structure - Note that getscl will be set to NULL by the attaching code for adapters - that cannot read SCL back */ -static struct i2c_algo_bit_data parport_algo_data = { - .setsda = parport_setsda, - .setscl = parport_setscl, - .getsda = parport_getsda, - .getscl = parport_getscl, - .udelay = 50, - .timeout = HZ, -}; - -/* ----- Driver registration ---------------------------------------------- */ - -static struct i2c_adapter parport_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON, - .algo_data = &parport_algo_data, - .name = "Parallel port adapter (light)", -}; - -/* SMBus alert support */ -static struct i2c_smbus_alert_setup alert_data = { - .alert_edge_triggered = 1, -}; -static struct i2c_client *ara; -static struct lineop parport_ctrl_irq = { - .val = (1 << 4), - .port = PORT_CTRL, -}; - -static int __devinit i2c_parport_probe(struct platform_device *pdev) -{ - int err; - - /* Reset hardware to a sane state (SCL and SDA high) */ - parport_setsda(NULL, 1); - parport_setscl(NULL, 1); - /* Other init if needed (power on...) */ - if (adapter_parm[type].init.val) { - line_set(1, &adapter_parm[type].init); - /* Give powered devices some time to settle */ - msleep(100); - } - - parport_adapter.dev.parent = &pdev->dev; - err = i2c_bit_add_bus(&parport_adapter); - if (err) { - dev_err(&pdev->dev, "Unable to register with I2C\n"); - return err; - } - - /* Setup SMBus alert if supported */ - if (adapter_parm[type].smbus_alert && irq) { - alert_data.irq = irq; - ara = i2c_setup_smbus_alert(&parport_adapter, &alert_data); - if (ara) - line_set(1, &parport_ctrl_irq); - else - dev_warn(&pdev->dev, "Failed to register ARA client\n"); - } - - return 0; -} - -static int __devexit i2c_parport_remove(struct platform_device *pdev) -{ - if (ara) { - line_set(0, &parport_ctrl_irq); - i2c_unregister_device(ara); - ara = NULL; - } - i2c_del_adapter(&parport_adapter); - - /* Un-init if needed (power off...) */ - if (adapter_parm[type].init.val) - line_set(0, &adapter_parm[type].init); - - return 0; -} - -static struct platform_driver i2c_parport_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = i2c_parport_probe, - .remove = __devexit_p(i2c_parport_remove), -}; - -static int __init i2c_parport_device_add(u16 address) -{ - int err; - - pdev = platform_device_alloc(DRVNAME, -1); - if (!pdev) { - err = -ENOMEM; - printk(KERN_ERR DRVNAME ": Device allocation failed\n"); - goto exit; - } - - err = platform_device_add(pdev); - if (err) { - printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n", - err); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(pdev); -exit: - return err; -} - -static int __init i2c_parport_init(void) -{ - int err; - - if (type < 0) { - printk(KERN_ERR DRVNAME ": adapter type unspecified\n"); - return -ENODEV; - } - - if (type >= ARRAY_SIZE(adapter_parm)) { - printk(KERN_ERR DRVNAME ": invalid type (%d)\n", type); - return -ENODEV; - } - - if (base == 0) { - pr_info(DRVNAME ": using default base 0x%x\n", DEFAULT_BASE); - base = DEFAULT_BASE; - } - - if (!request_region(base, 3, DRVNAME)) - return -EBUSY; - - if (irq != 0) - pr_info(DRVNAME ": using irq %d\n", irq); - - if (!adapter_parm[type].getscl.val) - parport_algo_data.getscl = NULL; - - /* Sets global pdev as a side effect */ - err = i2c_parport_device_add(base); - if (err) - goto exit_release; - - err = platform_driver_register(&i2c_parport_driver); - if (err) - goto exit_device; - - return 0; - -exit_device: - platform_device_unregister(pdev); -exit_release: - release_region(base, 3); - return err; -} - -static void __exit i2c_parport_exit(void) -{ - platform_driver_unregister(&i2c_parport_driver); - platform_device_unregister(pdev); - release_region(base, 3); -} - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("I2C bus over parallel port (light)"); -MODULE_LICENSE("GPL"); - -module_init(i2c_parport_init); -module_exit(i2c_parport_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.c deleted file mode 100644 index 24565687..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.c +++ /dev/null @@ -1,306 +0,0 @@ -/* ------------------------------------------------------------------------ * - * i2c-parport.c I2C bus over parallel port * - * ------------------------------------------------------------------------ * - Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org> - - Based on older i2c-philips-par.c driver - Copyright (C) 1995-2000 Simon G. Vogl - With some changes from: - Frodo Looijaard <frodol@dds.nl> - Kyösti Mälkki <kmalkki@cc.hut.fi> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ------------------------------------------------------------------------ */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/parport.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/i2c-smbus.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include "i2c-parport.h" - -/* ----- Device list ------------------------------------------------------ */ - -struct i2c_par { - struct pardevice *pdev; - struct i2c_adapter adapter; - struct i2c_algo_bit_data algo_data; - struct i2c_smbus_alert_setup alert_data; - struct i2c_client *ara; - struct list_head node; -}; - -static LIST_HEAD(adapter_list); -static DEFINE_MUTEX(adapter_list_lock); - -/* ----- Low-level parallel port access ----------------------------------- */ - -static void port_write_data(struct parport *p, unsigned char d) -{ - parport_write_data(p, d); -} - -static void port_write_control(struct parport *p, unsigned char d) -{ - parport_write_control(p, d); -} - -static unsigned char port_read_data(struct parport *p) -{ - return parport_read_data(p); -} - -static unsigned char port_read_status(struct parport *p) -{ - return parport_read_status(p); -} - -static unsigned char port_read_control(struct parport *p) -{ - return parport_read_control(p); -} - -static void (* const port_write[])(struct parport *, unsigned char) = { - port_write_data, - NULL, - port_write_control, -}; - -static unsigned char (* const port_read[])(struct parport *) = { - port_read_data, - port_read_status, - port_read_control, -}; - -/* ----- Unified line operation functions --------------------------------- */ - -static inline void line_set(struct parport *data, int state, - const struct lineop *op) -{ - u8 oldval = port_read[op->port](data); - - /* Touch only the bit(s) needed */ - if ((op->inverted && !state) || (!op->inverted && state)) - port_write[op->port](data, oldval | op->val); - else - port_write[op->port](data, oldval & ~op->val); -} - -static inline int line_get(struct parport *data, - const struct lineop *op) -{ - u8 oldval = port_read[op->port](data); - - return ((op->inverted && (oldval & op->val) != op->val) - || (!op->inverted && (oldval & op->val) == op->val)); -} - -/* ----- I2C algorithm call-back functions and structures ----------------- */ - -static void parport_setscl(void *data, int state) -{ - line_set((struct parport *) data, state, &adapter_parm[type].setscl); -} - -static void parport_setsda(void *data, int state) -{ - line_set((struct parport *) data, state, &adapter_parm[type].setsda); -} - -static int parport_getscl(void *data) -{ - return line_get((struct parport *) data, &adapter_parm[type].getscl); -} - -static int parport_getsda(void *data) -{ - return line_get((struct parport *) data, &adapter_parm[type].getsda); -} - -/* Encapsulate the functions above in the correct structure. - Note that this is only a template, from which the real structures are - copied. The attaching code will set getscl to NULL for adapters that - cannot read SCL back, and will also make the data field point to - the parallel port structure. */ -static const struct i2c_algo_bit_data parport_algo_data = { - .setsda = parport_setsda, - .setscl = parport_setscl, - .getsda = parport_getsda, - .getscl = parport_getscl, - .udelay = 10, /* ~50 kbps */ - .timeout = HZ, -}; - -/* ----- I2c and parallel port call-back functions and structures --------- */ - -void i2c_parport_irq(void *data) -{ - struct i2c_par *adapter = data; - struct i2c_client *ara = adapter->ara; - - if (ara) { - dev_dbg(&ara->dev, "SMBus alert received\n"); - i2c_handle_smbus_alert(ara); - } else - dev_dbg(&adapter->adapter.dev, - "SMBus alert received but no ARA client!\n"); -} - -static void i2c_parport_attach(struct parport *port) -{ - struct i2c_par *adapter; - - adapter = kzalloc(sizeof(struct i2c_par), GFP_KERNEL); - if (adapter == NULL) { - printk(KERN_ERR "i2c-parport: Failed to kzalloc\n"); - return; - } - - pr_debug("i2c-parport: attaching to %s\n", port->name); - parport_disable_irq(port); - adapter->pdev = parport_register_device(port, "i2c-parport", - NULL, NULL, i2c_parport_irq, PARPORT_FLAG_EXCL, adapter); - if (!adapter->pdev) { - printk(KERN_ERR "i2c-parport: Unable to register with parport\n"); - goto err_free; - } - - /* Fill the rest of the structure */ - adapter->adapter.owner = THIS_MODULE; - adapter->adapter.class = I2C_CLASS_HWMON; - strlcpy(adapter->adapter.name, "Parallel port adapter", - sizeof(adapter->adapter.name)); - adapter->algo_data = parport_algo_data; - /* Slow down if we can't sense SCL */ - if (!adapter_parm[type].getscl.val) { - adapter->algo_data.getscl = NULL; - adapter->algo_data.udelay = 50; /* ~10 kbps */ - } - adapter->algo_data.data = port; - adapter->adapter.algo_data = &adapter->algo_data; - adapter->adapter.dev.parent = port->physport->dev; - - if (parport_claim_or_block(adapter->pdev) < 0) { - printk(KERN_ERR "i2c-parport: Could not claim parallel port\n"); - goto err_unregister; - } - - /* Reset hardware to a sane state (SCL and SDA high) */ - parport_setsda(port, 1); - parport_setscl(port, 1); - /* Other init if needed (power on...) */ - if (adapter_parm[type].init.val) { - line_set(port, 1, &adapter_parm[type].init); - /* Give powered devices some time to settle */ - msleep(100); - } - - if (i2c_bit_add_bus(&adapter->adapter) < 0) { - printk(KERN_ERR "i2c-parport: Unable to register with I2C\n"); - goto err_unregister; - } - - /* Setup SMBus alert if supported */ - if (adapter_parm[type].smbus_alert) { - adapter->alert_data.alert_edge_triggered = 1; - adapter->ara = i2c_setup_smbus_alert(&adapter->adapter, - &adapter->alert_data); - if (adapter->ara) - parport_enable_irq(port); - else - printk(KERN_WARNING "i2c-parport: Failed to register " - "ARA client\n"); - } - - /* Add the new adapter to the list */ - mutex_lock(&adapter_list_lock); - list_add_tail(&adapter->node, &adapter_list); - mutex_unlock(&adapter_list_lock); - return; - - err_unregister: - parport_release(adapter->pdev); - parport_unregister_device(adapter->pdev); - err_free: - kfree(adapter); -} - -static void i2c_parport_detach(struct parport *port) -{ - struct i2c_par *adapter, *_n; - - /* Walk the list */ - mutex_lock(&adapter_list_lock); - list_for_each_entry_safe(adapter, _n, &adapter_list, node) { - if (adapter->pdev->port == port) { - if (adapter->ara) { - parport_disable_irq(port); - i2c_unregister_device(adapter->ara); - } - i2c_del_adapter(&adapter->adapter); - - /* Un-init if needed (power off...) */ - if (adapter_parm[type].init.val) - line_set(port, 0, &adapter_parm[type].init); - - parport_release(adapter->pdev); - parport_unregister_device(adapter->pdev); - list_del(&adapter->node); - kfree(adapter); - } - } - mutex_unlock(&adapter_list_lock); -} - -static struct parport_driver i2c_parport_driver = { - .name = "i2c-parport", - .attach = i2c_parport_attach, - .detach = i2c_parport_detach, -}; - -/* ----- Module loading, unloading and information ------------------------ */ - -static int __init i2c_parport_init(void) -{ - if (type < 0) { - printk(KERN_WARNING "i2c-parport: adapter type unspecified\n"); - return -ENODEV; - } - - if (type >= ARRAY_SIZE(adapter_parm)) { - printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type); - return -ENODEV; - } - - return parport_register_driver(&i2c_parport_driver); -} - -static void __exit i2c_parport_exit(void) -{ - parport_unregister_driver(&i2c_parport_driver); -} - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("I2C bus over parallel port"); -MODULE_LICENSE("GPL"); - -module_init(i2c_parport_init); -module_exit(i2c_parport_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.h b/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.h deleted file mode 100644 index 3fe65230..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-parport.h +++ /dev/null @@ -1,110 +0,0 @@ -/* ------------------------------------------------------------------------ * - * i2c-parport.h I2C bus over parallel port * - * ------------------------------------------------------------------------ * - Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * ------------------------------------------------------------------------ */ - -#define PORT_DATA 0 -#define PORT_STAT 1 -#define PORT_CTRL 2 - -struct lineop { - u8 val; - u8 port; - u8 inverted; -}; - -struct adapter_parm { - struct lineop setsda; - struct lineop setscl; - struct lineop getsda; - struct lineop getscl; - struct lineop init; - unsigned int smbus_alert:1; -}; - -static const struct adapter_parm adapter_parm[] = { - /* type 0: Philips adapter */ - { - .setsda = { 0x80, PORT_DATA, 1 }, - .setscl = { 0x08, PORT_CTRL, 0 }, - .getsda = { 0x80, PORT_STAT, 0 }, - .getscl = { 0x08, PORT_STAT, 0 }, - }, - /* type 1: home brew teletext adapter */ - { - .setsda = { 0x02, PORT_DATA, 0 }, - .setscl = { 0x01, PORT_DATA, 0 }, - .getsda = { 0x80, PORT_STAT, 1 }, - }, - /* type 2: Velleman K8000 adapter */ - { - .setsda = { 0x02, PORT_CTRL, 1 }, - .setscl = { 0x08, PORT_CTRL, 1 }, - .getsda = { 0x10, PORT_STAT, 0 }, - }, - /* type 3: ELV adapter */ - { - .setsda = { 0x02, PORT_DATA, 1 }, - .setscl = { 0x01, PORT_DATA, 1 }, - .getsda = { 0x40, PORT_STAT, 1 }, - .getscl = { 0x08, PORT_STAT, 1 }, - }, - /* type 4: ADM1032 evaluation board */ - { - .setsda = { 0x02, PORT_DATA, 1 }, - .setscl = { 0x01, PORT_DATA, 1 }, - .getsda = { 0x10, PORT_STAT, 1 }, - .init = { 0xf0, PORT_DATA, 0 }, - .smbus_alert = 1, - }, - /* type 5: ADM1025, ADM1030 and ADM1031 evaluation boards */ - { - .setsda = { 0x02, PORT_DATA, 1 }, - .setscl = { 0x01, PORT_DATA, 1 }, - .getsda = { 0x10, PORT_STAT, 1 }, - }, - /* type 6: Barco LPT->DVI (K5800236) adapter */ - { - .setsda = { 0x02, PORT_DATA, 1 }, - .setscl = { 0x01, PORT_DATA, 1 }, - .getsda = { 0x20, PORT_STAT, 0 }, - .getscl = { 0x40, PORT_STAT, 0 }, - .init = { 0xfc, PORT_DATA, 0 }, - }, - /* type 7: One For All JP1 parallel port adapter */ - { - .setsda = { 0x01, PORT_DATA, 0 }, - .setscl = { 0x02, PORT_DATA, 0 }, - .getsda = { 0x80, PORT_STAT, 1 }, - .init = { 0x04, PORT_DATA, 1 }, - }, -}; - -static int type = -1; -module_param(type, int, 0); -MODULE_PARM_DESC(type, - "Type of adapter:\n" - " 0 = Philips adapter\n" - " 1 = home brew teletext adapter\n" - " 2 = Velleman K8000 adapter\n" - " 3 = ELV adapter\n" - " 4 = ADM1032 evaluation board\n" - " 5 = ADM1025, ADM1030 and ADM1031 evaluation boards\n" - " 6 = Barco LPT->DVI (K5800236) adapter\n" - " 7 = One For All JP1 parallel port adapter\n" -); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pasemi.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pasemi.c deleted file mode 100644 index eaaea732..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pasemi.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2006-2007 PA Semi, Inc - * - * SMBus host driver for PA Semi PWRficient - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/sched.h> -#include <linux/i2c.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/io.h> - -static struct pci_driver pasemi_smb_driver; - -struct pasemi_smbus { - struct pci_dev *dev; - struct i2c_adapter adapter; - unsigned long base; - int size; -}; - -/* Register offsets */ -#define REG_MTXFIFO 0x00 -#define REG_MRXFIFO 0x04 -#define REG_SMSTA 0x14 -#define REG_CTL 0x1c - -/* Register defs */ -#define MTXFIFO_READ 0x00000400 -#define MTXFIFO_STOP 0x00000200 -#define MTXFIFO_START 0x00000100 -#define MTXFIFO_DATA_M 0x000000ff - -#define MRXFIFO_EMPTY 0x00000100 -#define MRXFIFO_DATA_M 0x000000ff - -#define SMSTA_XEN 0x08000000 -#define SMSTA_MTN 0x00200000 - -#define CTL_MRR 0x00000400 -#define CTL_MTR 0x00000200 -#define CTL_CLK_M 0x000000ff - -#define CLK_100K_DIV 84 -#define CLK_400K_DIV 21 - -static inline void reg_write(struct pasemi_smbus *smbus, int reg, int val) -{ - dev_dbg(&smbus->dev->dev, "smbus write reg %lx val %08x\n", - smbus->base + reg, val); - outl(val, smbus->base + reg); -} - -static inline int reg_read(struct pasemi_smbus *smbus, int reg) -{ - int ret; - ret = inl(smbus->base + reg); - dev_dbg(&smbus->dev->dev, "smbus read reg %lx val %08x\n", - smbus->base + reg, ret); - return ret; -} - -#define TXFIFO_WR(smbus, reg) reg_write((smbus), REG_MTXFIFO, (reg)) -#define RXFIFO_RD(smbus) reg_read((smbus), REG_MRXFIFO) - -static void pasemi_smb_clear(struct pasemi_smbus *smbus) -{ - unsigned int status; - - status = reg_read(smbus, REG_SMSTA); - reg_write(smbus, REG_SMSTA, status); -} - -static int pasemi_smb_waitready(struct pasemi_smbus *smbus) -{ - int timeout = 10; - unsigned int status; - - status = reg_read(smbus, REG_SMSTA); - - while (!(status & SMSTA_XEN) && timeout--) { - msleep(1); - status = reg_read(smbus, REG_SMSTA); - } - - /* Got NACK? */ - if (status & SMSTA_MTN) - return -ENXIO; - - if (timeout < 0) { - dev_warn(&smbus->dev->dev, "Timeout, status 0x%08x\n", status); - reg_write(smbus, REG_SMSTA, status); - return -ETIME; - } - - /* Clear XEN */ - reg_write(smbus, REG_SMSTA, SMSTA_XEN); - - return 0; -} - -static int pasemi_i2c_xfer_msg(struct i2c_adapter *adapter, - struct i2c_msg *msg, int stop) -{ - struct pasemi_smbus *smbus = adapter->algo_data; - int read, i, err; - u32 rd; - - read = msg->flags & I2C_M_RD ? 1 : 0; - - TXFIFO_WR(smbus, MTXFIFO_START | (msg->addr << 1) | read); - - if (read) { - TXFIFO_WR(smbus, msg->len | MTXFIFO_READ | - (stop ? MTXFIFO_STOP : 0)); - - err = pasemi_smb_waitready(smbus); - if (err) - goto reset_out; - - for (i = 0; i < msg->len; i++) { - rd = RXFIFO_RD(smbus); - if (rd & MRXFIFO_EMPTY) { - err = -ENODATA; - goto reset_out; - } - msg->buf[i] = rd & MRXFIFO_DATA_M; - } - } else { - for (i = 0; i < msg->len - 1; i++) - TXFIFO_WR(smbus, msg->buf[i]); - - TXFIFO_WR(smbus, msg->buf[msg->len-1] | - (stop ? MTXFIFO_STOP : 0)); - } - - return 0; - - reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); - return err; -} - -static int pasemi_i2c_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, int num) -{ - struct pasemi_smbus *smbus = adapter->algo_data; - int ret, i; - - pasemi_smb_clear(smbus); - - ret = 0; - - for (i = 0; i < num && !ret; i++) - ret = pasemi_i2c_xfer_msg(adapter, &msgs[i], (i == (num - 1))); - - return ret ? ret : num; -} - -static int pasemi_smb_xfer(struct i2c_adapter *adapter, - u16 addr, unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - struct pasemi_smbus *smbus = adapter->algo_data; - unsigned int rd; - int read_flag, err; - int len = 0, i; - - /* All our ops take 8-bit shifted addresses */ - addr <<= 1; - read_flag = read_write == I2C_SMBUS_READ; - - pasemi_smb_clear(smbus); - - switch (size) { - case I2C_SMBUS_QUICK: - TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START | - MTXFIFO_STOP); - break; - case I2C_SMBUS_BYTE: - TXFIFO_WR(smbus, addr | read_flag | MTXFIFO_START); - if (read_write) - TXFIFO_WR(smbus, 1 | MTXFIFO_STOP | MTXFIFO_READ); - else - TXFIFO_WR(smbus, MTXFIFO_STOP | command); - break; - case I2C_SMBUS_BYTE_DATA: - TXFIFO_WR(smbus, addr | MTXFIFO_START); - TXFIFO_WR(smbus, command); - if (read_write) { - TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START); - TXFIFO_WR(smbus, 1 | MTXFIFO_READ | MTXFIFO_STOP); - } else { - TXFIFO_WR(smbus, MTXFIFO_STOP | data->byte); - } - break; - case I2C_SMBUS_WORD_DATA: - TXFIFO_WR(smbus, addr | MTXFIFO_START); - TXFIFO_WR(smbus, command); - if (read_write) { - TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START); - TXFIFO_WR(smbus, 2 | MTXFIFO_READ | MTXFIFO_STOP); - } else { - TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M); - TXFIFO_WR(smbus, MTXFIFO_STOP | (data->word >> 8)); - } - break; - case I2C_SMBUS_BLOCK_DATA: - TXFIFO_WR(smbus, addr | MTXFIFO_START); - TXFIFO_WR(smbus, command); - if (read_write) { - TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START); - TXFIFO_WR(smbus, 1 | MTXFIFO_READ); - rd = RXFIFO_RD(smbus); - len = min_t(u8, (rd & MRXFIFO_DATA_M), - I2C_SMBUS_BLOCK_MAX); - TXFIFO_WR(smbus, len | MTXFIFO_READ | - MTXFIFO_STOP); - } else { - len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX); - TXFIFO_WR(smbus, len); - for (i = 1; i < len; i++) - TXFIFO_WR(smbus, data->block[i]); - TXFIFO_WR(smbus, data->block[len] | MTXFIFO_STOP); - } - break; - case I2C_SMBUS_PROC_CALL: - read_write = I2C_SMBUS_READ; - TXFIFO_WR(smbus, addr | MTXFIFO_START); - TXFIFO_WR(smbus, command); - TXFIFO_WR(smbus, data->word & MTXFIFO_DATA_M); - TXFIFO_WR(smbus, (data->word >> 8) & MTXFIFO_DATA_M); - TXFIFO_WR(smbus, addr | I2C_SMBUS_READ | MTXFIFO_START); - TXFIFO_WR(smbus, 2 | MTXFIFO_STOP | MTXFIFO_READ); - break; - case I2C_SMBUS_BLOCK_PROC_CALL: - len = min_t(u8, data->block[0], I2C_SMBUS_BLOCK_MAX - 1); - read_write = I2C_SMBUS_READ; - TXFIFO_WR(smbus, addr | MTXFIFO_START); - TXFIFO_WR(smbus, command); - TXFIFO_WR(smbus, len); - for (i = 1; i <= len; i++) - TXFIFO_WR(smbus, data->block[i]); - TXFIFO_WR(smbus, addr | I2C_SMBUS_READ); - TXFIFO_WR(smbus, MTXFIFO_READ | 1); - rd = RXFIFO_RD(smbus); - len = min_t(u8, (rd & MRXFIFO_DATA_M), - I2C_SMBUS_BLOCK_MAX - len); - TXFIFO_WR(smbus, len | MTXFIFO_READ | MTXFIFO_STOP); - break; - - default: - dev_warn(&adapter->dev, "Unsupported transaction %d\n", size); - return -EINVAL; - } - - err = pasemi_smb_waitready(smbus); - if (err) - goto reset_out; - - if (read_write == I2C_SMBUS_WRITE) - return 0; - - switch (size) { - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - rd = RXFIFO_RD(smbus); - if (rd & MRXFIFO_EMPTY) { - err = -ENODATA; - goto reset_out; - } - data->byte = rd & MRXFIFO_DATA_M; - break; - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - rd = RXFIFO_RD(smbus); - if (rd & MRXFIFO_EMPTY) { - err = -ENODATA; - goto reset_out; - } - data->word = rd & MRXFIFO_DATA_M; - rd = RXFIFO_RD(smbus); - if (rd & MRXFIFO_EMPTY) { - err = -ENODATA; - goto reset_out; - } - data->word |= (rd & MRXFIFO_DATA_M) << 8; - break; - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_BLOCK_PROC_CALL: - data->block[0] = len; - for (i = 1; i <= len; i ++) { - rd = RXFIFO_RD(smbus); - if (rd & MRXFIFO_EMPTY) { - err = -ENODATA; - goto reset_out; - } - data->block[i] = rd & MRXFIFO_DATA_M; - } - break; - } - - return 0; - - reset_out: - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); - return err; -} - -static u32 pasemi_smb_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_SMBUS_BLOCK_PROC_CALL | I2C_FUNC_I2C; -} - -static const struct i2c_algorithm smbus_algorithm = { - .master_xfer = pasemi_i2c_xfer, - .smbus_xfer = pasemi_smb_xfer, - .functionality = pasemi_smb_func, -}; - -static int __devinit pasemi_smb_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - struct pasemi_smbus *smbus; - int error; - - if (!(pci_resource_flags(dev, 0) & IORESOURCE_IO)) - return -ENODEV; - - smbus = kzalloc(sizeof(struct pasemi_smbus), GFP_KERNEL); - if (!smbus) - return -ENOMEM; - - smbus->dev = dev; - smbus->base = pci_resource_start(dev, 0); - smbus->size = pci_resource_len(dev, 0); - - if (!request_region(smbus->base, smbus->size, - pasemi_smb_driver.name)) { - error = -EBUSY; - goto out_kfree; - } - - smbus->adapter.owner = THIS_MODULE; - snprintf(smbus->adapter.name, sizeof(smbus->adapter.name), - "PA Semi SMBus adapter at 0x%lx", smbus->base); - smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus->adapter.algo = &smbus_algorithm; - smbus->adapter.algo_data = smbus; - smbus->adapter.nr = PCI_FUNC(dev->devfn); - - /* set up the sysfs linkage to our parent device */ - smbus->adapter.dev.parent = &dev->dev; - - reg_write(smbus, REG_CTL, (CTL_MTR | CTL_MRR | - (CLK_100K_DIV & CTL_CLK_M))); - - error = i2c_add_numbered_adapter(&smbus->adapter); - if (error) - goto out_release_region; - - pci_set_drvdata(dev, smbus); - - return 0; - - out_release_region: - release_region(smbus->base, smbus->size); - out_kfree: - kfree(smbus); - return error; -} - -static void __devexit pasemi_smb_remove(struct pci_dev *dev) -{ - struct pasemi_smbus *smbus = pci_get_drvdata(dev); - - i2c_del_adapter(&smbus->adapter); - release_region(smbus->base, smbus->size); - kfree(smbus); -} - -static DEFINE_PCI_DEVICE_TABLE(pasemi_smb_ids) = { - { PCI_DEVICE(0x1959, 0xa003) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, pasemi_smb_ids); - -static struct pci_driver pasemi_smb_driver = { - .name = "i2c-pasemi", - .id_table = pasemi_smb_ids, - .probe = pasemi_smb_probe, - .remove = __devexit_p(pasemi_smb_remove), -}; - -static int __init pasemi_smb_init(void) -{ - return pci_register_driver(&pasemi_smb_driver); -} - -static void __exit pasemi_smb_exit(void) -{ - pci_unregister_driver(&pasemi_smb_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR ("Olof Johansson <olof@lixom.net>"); -MODULE_DESCRIPTION("PA Semi PWRficient SMBus driver"); - -module_init(pasemi_smb_init); -module_exit(pasemi_smb_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-isa.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-isa.c deleted file mode 100644 index 29933f87..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-isa.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * i2c-pca-isa.c driver for PCA9564 on ISA boards - * Copyright (C) 2004 Arcom Control Systems - * Copyright (C) 2008 Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/ioport.h> -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/delay.h> -#include <linux/jiffies.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/isa.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-pca.h> -#include <linux/io.h> - -#include <asm/irq.h> - -#define DRIVER "i2c-pca-isa" -#define IO_SIZE 4 - -static unsigned long base; -static int irq = -1; - -/* Data sheet recommends 59kHz for 100kHz operation due to variation - * in the actual clock rate */ -static int clock = 59000; - -static struct i2c_adapter pca_isa_ops; -static wait_queue_head_t pca_wait; - -static void pca_isa_writebyte(void *pd, int reg, int val) -{ -#ifdef DEBUG_IO - static char *names[] = { "T/O", "DAT", "ADR", "CON" }; - printk(KERN_DEBUG "*** write %s at %#lx <= %#04x\n", names[reg], - base+reg, val); -#endif - outb(val, base+reg); -} - -static int pca_isa_readbyte(void *pd, int reg) -{ - int res = inb(base+reg); -#ifdef DEBUG_IO - { - static char *names[] = { "STA", "DAT", "ADR", "CON" }; - printk(KERN_DEBUG "*** read %s => %#04x\n", names[reg], res); - } -#endif - return res; -} - -static int pca_isa_waitforcompletion(void *pd) -{ - unsigned long timeout; - long ret; - - if (irq > -1) { - ret = wait_event_timeout(pca_wait, - pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI, pca_isa_ops.timeout); - } else { - /* Do polling */ - timeout = jiffies + pca_isa_ops.timeout; - do { - ret = time_before(jiffies, timeout); - if (pca_isa_readbyte(pd, I2C_PCA_CON) - & I2C_PCA_CON_SI) - break; - udelay(100); - } while (ret); - } - - return ret > 0; -} - -static void pca_isa_resetchip(void *pd) -{ - /* apparently only an external reset will do it. not a lot can be done */ - printk(KERN_WARNING DRIVER ": Haven't figured out how to do a reset yet\n"); -} - -static irqreturn_t pca_handler(int this_irq, void *dev_id) { - wake_up(&pca_wait); - return IRQ_HANDLED; -} - -static struct i2c_algo_pca_data pca_isa_data = { - /* .data intentionally left NULL, not needed with ISA */ - .write_byte = pca_isa_writebyte, - .read_byte = pca_isa_readbyte, - .wait_for_completion = pca_isa_waitforcompletion, - .reset_chip = pca_isa_resetchip, -}; - -static struct i2c_adapter pca_isa_ops = { - .owner = THIS_MODULE, - .algo_data = &pca_isa_data, - .name = "PCA9564/PCA9665 ISA Adapter", - .timeout = HZ, -}; - -static int __devinit pca_isa_match(struct device *dev, unsigned int id) -{ - int match = base != 0; - - if (match) { - if (irq <= -1) - dev_warn(dev, "Using polling mode (specify irq)\n"); - } else - dev_err(dev, "Please specify I/O base\n"); - - return match; -} - -static int __devinit pca_isa_probe(struct device *dev, unsigned int id) -{ - init_waitqueue_head(&pca_wait); - - dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq); - -#ifdef CONFIG_PPC - if (check_legacy_ioport(base)) { - dev_err(dev, "I/O address %#08lx is not available\n", base); - goto out; - } -#endif - - if (!request_region(base, IO_SIZE, "i2c-pca-isa")) { - dev_err(dev, "I/O address %#08lx is in use\n", base); - goto out; - } - - if (irq > -1) { - if (request_irq(irq, pca_handler, 0, "i2c-pca-isa", &pca_isa_ops) < 0) { - dev_err(dev, "Request irq%d failed\n", irq); - goto out_region; - } - } - - pca_isa_data.i2c_clock = clock; - if (i2c_pca_add_bus(&pca_isa_ops) < 0) { - dev_err(dev, "Failed to add i2c bus\n"); - goto out_irq; - } - - return 0; - - out_irq: - if (irq > -1) - free_irq(irq, &pca_isa_ops); - out_region: - release_region(base, IO_SIZE); - out: - return -ENODEV; -} - -static int __devexit pca_isa_remove(struct device *dev, unsigned int id) -{ - i2c_del_adapter(&pca_isa_ops); - - if (irq > -1) { - disable_irq(irq); - free_irq(irq, &pca_isa_ops); - } - release_region(base, IO_SIZE); - - return 0; -} - -static struct isa_driver pca_isa_driver = { - .match = pca_isa_match, - .probe = pca_isa_probe, - .remove = __devexit_p(pca_isa_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRIVER, - } -}; - -static int __init pca_isa_init(void) -{ - return isa_register_driver(&pca_isa_driver, 1); -} - -static void __exit pca_isa_exit(void) -{ - isa_unregister_driver(&pca_isa_driver); -} - -MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>"); -MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver"); -MODULE_LICENSE("GPL"); - -module_param(base, ulong, 0); -MODULE_PARM_DESC(base, "I/O base address"); - -module_param(irq, int, 0); -MODULE_PARM_DESC(irq, "IRQ"); -module_param(clock, int, 0); -MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t" - "For PCA9564: 330000,288000,217000,146000," - "88000,59000,44000,36000\n" - "\t\tFor PCA9665:\tStandard: 60300 - 100099\n" - "\t\t\t\tFast: 100100 - 400099\n" - "\t\t\t\tFast+: 400100 - 10000099\n" - "\t\t\t\tTurbo: Up to 1265800"); - -module_init(pca_isa_init); -module_exit(pca_isa_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-platform.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-platform.c deleted file mode 100644 index 2adbf1a8..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pca-platform.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * i2c_pca_platform.c - * - * Platform driver for the PCA9564 I2C controller. - * - * Copyright (C) 2008 Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/delay.h> -#include <linux/jiffies.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/i2c-algo-pca.h> -#include <linux/i2c-pca-platform.h> -#include <linux/gpio.h> -#include <linux/io.h> - -#include <asm/irq.h> - -struct i2c_pca_pf_data { - void __iomem *reg_base; - int irq; /* if 0, use polling */ - int gpio; - wait_queue_head_t wait; - struct i2c_adapter adap; - struct i2c_algo_pca_data algo_data; - unsigned long io_base; - unsigned long io_size; -}; - -/* Read/Write functions for different register alignments */ - -static int i2c_pca_pf_readbyte8(void *pd, int reg) -{ - struct i2c_pca_pf_data *i2c = pd; - return ioread8(i2c->reg_base + reg); -} - -static int i2c_pca_pf_readbyte16(void *pd, int reg) -{ - struct i2c_pca_pf_data *i2c = pd; - return ioread8(i2c->reg_base + reg * 2); -} - -static int i2c_pca_pf_readbyte32(void *pd, int reg) -{ - struct i2c_pca_pf_data *i2c = pd; - return ioread8(i2c->reg_base + reg * 4); -} - -static void i2c_pca_pf_writebyte8(void *pd, int reg, int val) -{ - struct i2c_pca_pf_data *i2c = pd; - iowrite8(val, i2c->reg_base + reg); -} - -static void i2c_pca_pf_writebyte16(void *pd, int reg, int val) -{ - struct i2c_pca_pf_data *i2c = pd; - iowrite8(val, i2c->reg_base + reg * 2); -} - -static void i2c_pca_pf_writebyte32(void *pd, int reg, int val) -{ - struct i2c_pca_pf_data *i2c = pd; - iowrite8(val, i2c->reg_base + reg * 4); -} - - -static int i2c_pca_pf_waitforcompletion(void *pd) -{ - struct i2c_pca_pf_data *i2c = pd; - unsigned long timeout; - long ret; - - if (i2c->irq) { - ret = wait_event_timeout(i2c->wait, - i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI, i2c->adap.timeout); - } else { - /* Do polling */ - timeout = jiffies + i2c->adap.timeout; - do { - ret = time_before(jiffies, timeout); - if (i2c->algo_data.read_byte(i2c, I2C_PCA_CON) - & I2C_PCA_CON_SI) - break; - udelay(100); - } while (ret); - } - - return ret > 0; -} - -static void i2c_pca_pf_dummyreset(void *pd) -{ - struct i2c_pca_pf_data *i2c = pd; - printk(KERN_WARNING "%s: No reset-pin found. Chip may get stuck!\n", - i2c->adap.name); -} - -static void i2c_pca_pf_resetchip(void *pd) -{ - struct i2c_pca_pf_data *i2c = pd; - - gpio_set_value(i2c->gpio, 0); - ndelay(100); - gpio_set_value(i2c->gpio, 1); -} - -static irqreturn_t i2c_pca_pf_handler(int this_irq, void *dev_id) -{ - struct i2c_pca_pf_data *i2c = dev_id; - - if ((i2c->algo_data.read_byte(i2c, I2C_PCA_CON) & I2C_PCA_CON_SI) == 0) - return IRQ_NONE; - - wake_up(&i2c->wait); - - return IRQ_HANDLED; -} - - -static int __devinit i2c_pca_pf_probe(struct platform_device *pdev) -{ - struct i2c_pca_pf_data *i2c; - struct resource *res; - struct i2c_pca9564_pf_platform_data *platform_data = - pdev->dev.platform_data; - int ret = 0; - int irq; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - /* If irq is 0, we do polling. */ - - if (res == NULL) { - ret = -ENODEV; - goto e_print; - } - - if (!request_mem_region(res->start, resource_size(res), res->name)) { - ret = -ENOMEM; - goto e_print; - } - - i2c = kzalloc(sizeof(struct i2c_pca_pf_data), GFP_KERNEL); - if (!i2c) { - ret = -ENOMEM; - goto e_alloc; - } - - init_waitqueue_head(&i2c->wait); - - i2c->reg_base = ioremap(res->start, resource_size(res)); - if (!i2c->reg_base) { - ret = -ENOMEM; - goto e_remap; - } - i2c->io_base = res->start; - i2c->io_size = resource_size(res); - i2c->irq = irq; - - i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; - i2c->adap.owner = THIS_MODULE; - snprintf(i2c->adap.name, sizeof(i2c->adap.name), - "PCA9564/PCA9665 at 0x%08lx", - (unsigned long) res->start); - i2c->adap.algo_data = &i2c->algo_data; - i2c->adap.dev.parent = &pdev->dev; - - if (platform_data) { - i2c->adap.timeout = platform_data->timeout; - i2c->algo_data.i2c_clock = platform_data->i2c_clock_speed; - i2c->gpio = platform_data->gpio; - } else { - i2c->adap.timeout = HZ; - i2c->algo_data.i2c_clock = 59000; - i2c->gpio = -1; - } - - i2c->algo_data.data = i2c; - i2c->algo_data.wait_for_completion = i2c_pca_pf_waitforcompletion; - i2c->algo_data.reset_chip = i2c_pca_pf_dummyreset; - - switch (res->flags & IORESOURCE_MEM_TYPE_MASK) { - case IORESOURCE_MEM_32BIT: - i2c->algo_data.write_byte = i2c_pca_pf_writebyte32; - i2c->algo_data.read_byte = i2c_pca_pf_readbyte32; - break; - case IORESOURCE_MEM_16BIT: - i2c->algo_data.write_byte = i2c_pca_pf_writebyte16; - i2c->algo_data.read_byte = i2c_pca_pf_readbyte16; - break; - case IORESOURCE_MEM_8BIT: - default: - i2c->algo_data.write_byte = i2c_pca_pf_writebyte8; - i2c->algo_data.read_byte = i2c_pca_pf_readbyte8; - break; - } - - /* Use gpio_is_valid() when in mainline */ - if (i2c->gpio > -1) { - ret = gpio_request(i2c->gpio, i2c->adap.name); - if (ret == 0) { - gpio_direction_output(i2c->gpio, 1); - i2c->algo_data.reset_chip = i2c_pca_pf_resetchip; - } else { - printk(KERN_WARNING "%s: Registering gpio failed!\n", - i2c->adap.name); - i2c->gpio = ret; - } - } - - if (irq) { - ret = request_irq(irq, i2c_pca_pf_handler, - IRQF_TRIGGER_FALLING, pdev->name, i2c); - if (ret) - goto e_reqirq; - } - - if (i2c_pca_add_numbered_bus(&i2c->adap) < 0) { - ret = -ENODEV; - goto e_adapt; - } - - platform_set_drvdata(pdev, i2c); - - printk(KERN_INFO "%s registered.\n", i2c->adap.name); - - return 0; - -e_adapt: - if (irq) - free_irq(irq, i2c); -e_reqirq: - if (i2c->gpio > -1) - gpio_free(i2c->gpio); - - iounmap(i2c->reg_base); -e_remap: - kfree(i2c); -e_alloc: - release_mem_region(res->start, resource_size(res)); -e_print: - printk(KERN_ERR "Registering PCA9564/PCA9665 FAILED! (%d)\n", ret); - return ret; -} - -static int __devexit i2c_pca_pf_remove(struct platform_device *pdev) -{ - struct i2c_pca_pf_data *i2c = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - - i2c_del_adapter(&i2c->adap); - - if (i2c->irq) - free_irq(i2c->irq, i2c); - - if (i2c->gpio > -1) - gpio_free(i2c->gpio); - - iounmap(i2c->reg_base); - release_mem_region(i2c->io_base, i2c->io_size); - kfree(i2c); - - return 0; -} - -static struct platform_driver i2c_pca_pf_driver = { - .probe = i2c_pca_pf_probe, - .remove = __devexit_p(i2c_pca_pf_remove), - .driver = { - .name = "i2c-pca-platform", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(i2c_pca_pf_driver); - -MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); -MODULE_DESCRIPTION("I2C-PCA9564/PCA9665 platform driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-piix4.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-piix4.c deleted file mode 100644 index c14d48dd..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-piix4.c +++ /dev/null @@ -1,563 +0,0 @@ -/* - Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports: - Intel PIIX4, 440MX - Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 - ATI IXP200, IXP300, IXP400, SB600, SB700, SB800 - AMD Hudson-2 - SMSC Victory66 - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include <linux/module.h> -#include <linux/moduleparam.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/dmi.h> -#include <linux/acpi.h> -#include <linux/io.h> - - -/* PIIX4 SMBus address offsets */ -#define SMBHSTSTS (0 + piix4_smba) -#define SMBHSLVSTS (1 + piix4_smba) -#define SMBHSTCNT (2 + piix4_smba) -#define SMBHSTCMD (3 + piix4_smba) -#define SMBHSTADD (4 + piix4_smba) -#define SMBHSTDAT0 (5 + piix4_smba) -#define SMBHSTDAT1 (6 + piix4_smba) -#define SMBBLKDAT (7 + piix4_smba) -#define SMBSLVCNT (8 + piix4_smba) -#define SMBSHDWCMD (9 + piix4_smba) -#define SMBSLVEVT (0xA + piix4_smba) -#define SMBSLVDAT (0xC + piix4_smba) - -/* count for request_region */ -#define SMBIOSIZE 8 - -/* PCI Address Constants */ -#define SMBBA 0x090 -#define SMBHSTCFG 0x0D2 -#define SMBSLVC 0x0D3 -#define SMBSHDW1 0x0D4 -#define SMBSHDW2 0x0D5 -#define SMBREV 0x0D6 - -/* Other settings */ -#define MAX_TIMEOUT 500 -#define ENABLE_INT9 0 - -/* PIIX4 constants */ -#define PIIX4_QUICK 0x00 -#define PIIX4_BYTE 0x04 -#define PIIX4_BYTE_DATA 0x08 -#define PIIX4_WORD_DATA 0x0C -#define PIIX4_BLOCK_DATA 0x14 - -/* insmod parameters */ - -/* If force is set to anything different from 0, we forcibly enable the - PIIX4. DANGEROUS! */ -static int force; -module_param (force, int, 0); -MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!"); - -/* If force_addr is set to anything different from 0, we forcibly enable - the PIIX4 at the given address. VERY DANGEROUS! */ -static int force_addr; -module_param (force_addr, int, 0); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the PIIX4 at the given address. " - "EXTREMELY DANGEROUS!"); - -static unsigned short piix4_smba; -static int srvrworks_csb5_delay; -static struct pci_driver piix4_driver; -static struct i2c_adapter piix4_adapter; - -static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = { - { - .ident = "Sapphire AM2RD790", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "SAPPHIRE Inc."), - DMI_MATCH(DMI_BOARD_NAME, "PC-AM2RD790"), - }, - }, - { - .ident = "DFI Lanparty UT 790FX", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "DFI Inc."), - DMI_MATCH(DMI_BOARD_NAME, "LP UT 790FX"), - }, - }, - { } -}; - -/* The IBM entry is in a separate table because we only check it - on Intel-based systems */ -static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = { - { - .ident = "IBM", - .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, - }, - { }, -}; - -static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) -{ - unsigned char temp; - - if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) && - (PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5)) - srvrworks_csb5_delay = 1; - - /* On some motherboards, it was reported that accessing the SMBus - caused severe hardware problems */ - if (dmi_check_system(piix4_dmi_blacklist)) { - dev_err(&PIIX4_dev->dev, - "Accessing the SMBus on this system is unsafe!\n"); - return -EPERM; - } - - /* Don't access SMBus on IBM systems which get corrupted eeproms */ - if (dmi_check_system(piix4_dmi_ibm) && - PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) { - dev_err(&PIIX4_dev->dev, "IBM system detected; this module " - "may corrupt your serial eeprom! Refusing to load " - "module!\n"); - return -EPERM; - } - - /* Determine the address of the SMBus areas */ - if (force_addr) { - piix4_smba = force_addr & 0xfff0; - force = 0; - } else { - pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba); - piix4_smba &= 0xfff0; - if(piix4_smba == 0) { - dev_err(&PIIX4_dev->dev, "SMBus base address " - "uninitialized - upgrade BIOS or use " - "force_addr=0xaddr\n"); - return -ENODEV; - } - } - - if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) - return -ENODEV; - - if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { - dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", - piix4_smba); - return -EBUSY; - } - - pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp); - - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the PIIX4 first. */ - if (force_addr) { - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba); - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01); - dev_info(&PIIX4_dev->dev, "WARNING: SMBus interface set to " - "new address %04x!\n", piix4_smba); - } else if ((temp & 1) == 0) { - if (force) { - /* This should never need to be done, but has been - * noted that many Dell machines have the SMBus - * interface on the PIIX4 disabled!? NOTE: This assumes - * I/O space and other allocations WERE done by the - * Bios! Don't complain if your hardware does weird - * things after enabling this. :') Check for Bios - * updates before resorting to this. - */ - pci_write_config_byte(PIIX4_dev, SMBHSTCFG, - temp | 1); - dev_printk(KERN_NOTICE, &PIIX4_dev->dev, - "WARNING: SMBus interface has been " - "FORCEFULLY ENABLED!\n"); - } else { - dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - return -ENODEV; - } - } - - if (((temp & 0x0E) == 8) || ((temp & 0x0E) == 2)) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt 9 for SMBus.\n"); - else if ((temp & 0x0E) == 0) - dev_dbg(&PIIX4_dev->dev, "Using Interrupt SMI# for SMBus.\n"); - else - dev_err(&PIIX4_dev->dev, "Illegal Interrupt configuration " - "(or code out of date)!\n"); - - pci_read_config_byte(PIIX4_dev, SMBREV, &temp); - dev_info(&PIIX4_dev->dev, - "SMBus Host Controller at 0x%x, revision %d\n", - piix4_smba, temp); - - return 0; -} - -static int __devinit piix4_setup_sb800(struct pci_dev *PIIX4_dev, - const struct pci_device_id *id) -{ - unsigned short smba_idx = 0xcd6; - u8 smba_en_lo, smba_en_hi, i2ccfg, i2ccfg_offset = 0x10, smb_en = 0x2c; - - /* SB800 and later SMBus does not support forcing address */ - if (force || force_addr) { - dev_err(&PIIX4_dev->dev, "SMBus does not support " - "forcing address!\n"); - return -EINVAL; - } - - /* Determine the address of the SMBus areas */ - if (!request_region(smba_idx, 2, "smba_idx")) { - dev_err(&PIIX4_dev->dev, "SMBus base address index region " - "0x%x already in use!\n", smba_idx); - return -EBUSY; - } - outb_p(smb_en, smba_idx); - smba_en_lo = inb_p(smba_idx + 1); - outb_p(smb_en + 1, smba_idx); - smba_en_hi = inb_p(smba_idx + 1); - release_region(smba_idx, 2); - - if ((smba_en_lo & 1) == 0) { - dev_err(&PIIX4_dev->dev, - "Host SMBus controller not enabled!\n"); - return -ENODEV; - } - - piix4_smba = ((smba_en_hi << 8) | smba_en_lo) & 0xffe0; - if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) - return -ENODEV; - - if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) { - dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n", - piix4_smba); - return -EBUSY; - } - - /* Request the SMBus I2C bus config region */ - if (!request_region(piix4_smba + i2ccfg_offset, 1, "i2ccfg")) { - dev_err(&PIIX4_dev->dev, "SMBus I2C bus config region " - "0x%x already in use!\n", piix4_smba + i2ccfg_offset); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - return -EBUSY; - } - i2ccfg = inb_p(piix4_smba + i2ccfg_offset); - release_region(piix4_smba + i2ccfg_offset, 1); - - if (i2ccfg & 1) - dev_dbg(&PIIX4_dev->dev, "Using IRQ for SMBus.\n"); - else - dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n"); - - dev_info(&PIIX4_dev->dev, - "SMBus Host Controller at 0x%x, revision %d\n", - piix4_smba, i2ccfg >> 4); - - return 0; -} - -static int piix4_transaction(void) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). " - "Resetting...\n", temp); - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp); - return -EBUSY; - } else { - dev_dbg(&piix4_adapter.dev, "Successful!\n"); - } - } - - /* start the transaction by setting bit 6 */ - outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT); - - /* We will always wait for a fraction of a second! (See PIIX4 docs errata) */ - if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */ - msleep(2); - else - msleep(1); - - while ((++timeout < MAX_TIMEOUT) && - ((temp = inb_p(SMBHSTSTS)) & 0x01)) - msleep(1); - - /* If the SMBus is still busy, we give up */ - if (timeout == MAX_TIMEOUT) { - dev_err(&piix4_adapter.dev, "SMBus Timeout!\n"); - result = -ETIMEDOUT; - } - - if (temp & 0x10) { - result = -EIO; - dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n"); - } - - if (temp & 0x08) { - result = -EIO; - dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be " - "locked until next hard reset. (sorry!)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - } - - if (temp & 0x04) { - result = -ENXIO; - dev_dbg(&piix4_adapter.dev, "Error: no response!\n"); - } - - if (inb_p(SMBHSTSTS) != 0x00) - outb_p(inb(SMBHSTSTS), SMBHSTSTS); - - if ((temp = inb_p(SMBHSTSTS)) != 0x00) { - dev_err(&piix4_adapter.dev, "Failed reset at end of " - "transaction (%02x)\n", temp); - } - dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, " - "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - return result; -} - -/* Return negative errno on error. */ -static s32 piix4_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int i, len; - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - outb_p((addr << 1) | read_write, - SMBHSTADD); - size = PIIX4_QUICK; - break; - case I2C_SMBUS_BYTE: - outb_p((addr << 1) | read_write, - SMBHSTADD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = PIIX4_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = PIIX4_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = PIIX4_WORD_DATA; - break; - case I2C_SMBUS_BLOCK_DATA: - outb_p((addr << 1) | read_write, - SMBHSTADD); - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EINVAL; - outb_p(len, SMBHSTDAT0); - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = PIIX4_BLOCK_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT); - - status = piix4_transaction(); - if (status) - return status; - - if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK)) - return 0; - - - switch (size) { - case PIIX4_BYTE: - case PIIX4_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case PIIX4_WORD_DATA: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case PIIX4_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - i = inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } - return 0; -} - -static u32 piix4_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = piix4_access, - .functionality = piix4_func, -}; - -static struct i2c_adapter piix4_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(piix4_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP200_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_OSB4) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB5) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_CSB6) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, - { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, - PCI_DEVICE_ID_SERVERWORKS_HT1100LD) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, piix4_ids); - -static int __devinit piix4_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - int retval; - - if ((dev->vendor == PCI_VENDOR_ID_ATI && - dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && - dev->revision >= 0x40) || - dev->vendor == PCI_VENDOR_ID_AMD) - /* base address location etc changed in SB800 */ - retval = piix4_setup_sb800(dev, id); - else - retval = piix4_setup(dev, id); - - if (retval) - return retval; - - /* set up the sysfs linkage to our parent device */ - piix4_adapter.dev.parent = &dev->dev; - - snprintf(piix4_adapter.name, sizeof(piix4_adapter.name), - "SMBus PIIX4 adapter at %04x", piix4_smba); - - if ((retval = i2c_add_adapter(&piix4_adapter))) { - dev_err(&dev->dev, "Couldn't register adapter!\n"); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - } - - return retval; -} - -static void __devexit piix4_remove(struct pci_dev *dev) -{ - if (piix4_smba) { - i2c_del_adapter(&piix4_adapter); - release_region(piix4_smba, SMBIOSIZE); - piix4_smba = 0; - } -} - -static struct pci_driver piix4_driver = { - .name = "piix4_smbus", - .id_table = piix4_ids, - .probe = piix4_probe, - .remove = __devexit_p(piix4_remove), -}; - -static int __init i2c_piix4_init(void) -{ - return pci_register_driver(&piix4_driver); -} - -static void __exit i2c_piix4_exit(void) -{ - pci_unregister_driver(&piix4_driver); -} - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " - "Philip Edelbrock <phil@netroedge.com>"); -MODULE_DESCRIPTION("PIIX4 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_piix4_init); -module_exit(i2c_piix4_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pmcmsp.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pmcmsp.c deleted file mode 100644 index 07b7447e..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pmcmsp.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * Specific bus support for PMC-TWI compliant implementation on MSP71xx. - * - * Copyright 2005-2007 PMC-Sierra, Inc. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/completion.h> -#include <linux/mutex.h> -#include <linux/delay.h> -#include <linux/io.h> - -#define DRV_NAME "pmcmsptwi" - -#define MSP_TWI_SF_CLK_REG_OFFSET 0x00 -#define MSP_TWI_HS_CLK_REG_OFFSET 0x04 -#define MSP_TWI_CFG_REG_OFFSET 0x08 -#define MSP_TWI_CMD_REG_OFFSET 0x0c -#define MSP_TWI_ADD_REG_OFFSET 0x10 -#define MSP_TWI_DAT_0_REG_OFFSET 0x14 -#define MSP_TWI_DAT_1_REG_OFFSET 0x18 -#define MSP_TWI_INT_STS_REG_OFFSET 0x1c -#define MSP_TWI_INT_MSK_REG_OFFSET 0x20 -#define MSP_TWI_BUSY_REG_OFFSET 0x24 - -#define MSP_TWI_INT_STS_DONE (1 << 0) -#define MSP_TWI_INT_STS_LOST_ARBITRATION (1 << 1) -#define MSP_TWI_INT_STS_NO_RESPONSE (1 << 2) -#define MSP_TWI_INT_STS_DATA_COLLISION (1 << 3) -#define MSP_TWI_INT_STS_BUSY (1 << 4) -#define MSP_TWI_INT_STS_ALL 0x1f - -#define MSP_MAX_BYTES_PER_RW 8 -#define MSP_MAX_POLL 5 -#define MSP_POLL_DELAY 10 -#define MSP_IRQ_TIMEOUT (MSP_MAX_POLL * MSP_POLL_DELAY) - -/* IO Operation macros */ -#define pmcmsptwi_readl __raw_readl -#define pmcmsptwi_writel __raw_writel - -/* TWI command type */ -enum pmcmsptwi_cmd_type { - MSP_TWI_CMD_WRITE = 0, /* Write only */ - MSP_TWI_CMD_READ = 1, /* Read only */ - MSP_TWI_CMD_WRITE_READ = 2, /* Write then Read */ -}; - -/* The possible results of the xferCmd */ -enum pmcmsptwi_xfer_result { - MSP_TWI_XFER_OK = 0, - MSP_TWI_XFER_TIMEOUT, - MSP_TWI_XFER_BUSY, - MSP_TWI_XFER_DATA_COLLISION, - MSP_TWI_XFER_NO_RESPONSE, - MSP_TWI_XFER_LOST_ARBITRATION, -}; - -/* Corresponds to a PMCTWI clock configuration register */ -struct pmcmsptwi_clock { - u8 filter; /* Bits 15:12, default = 0x03 */ - u16 clock; /* Bits 9:0, default = 0x001f */ -}; - -struct pmcmsptwi_clockcfg { - struct pmcmsptwi_clock standard; /* The standard/fast clock config */ - struct pmcmsptwi_clock highspeed; /* The highspeed clock config */ -}; - -/* Corresponds to the main TWI configuration register */ -struct pmcmsptwi_cfg { - u8 arbf; /* Bits 15:12, default=0x03 */ - u8 nak; /* Bits 11:8, default=0x03 */ - u8 add10; /* Bit 7, default=0x00 */ - u8 mst_code; /* Bits 6:4, default=0x00 */ - u8 arb; /* Bit 1, default=0x01 */ - u8 highspeed; /* Bit 0, default=0x00 */ -}; - -/* A single pmctwi command to issue */ -struct pmcmsptwi_cmd { - u16 addr; /* The slave address (7 or 10 bits) */ - enum pmcmsptwi_cmd_type type; /* The command type */ - u8 write_len; /* Number of bytes in the write buffer */ - u8 read_len; /* Number of bytes in the read buffer */ - u8 *write_data; /* Buffer of characters to send */ - u8 *read_data; /* Buffer to fill with incoming data */ -}; - -/* The private data */ -struct pmcmsptwi_data { - void __iomem *iobase; /* iomapped base for IO */ - int irq; /* IRQ to use (0 disables) */ - struct completion wait; /* Completion for xfer */ - struct mutex lock; /* Used for threadsafeness */ - enum pmcmsptwi_xfer_result last_result; /* result of last xfer */ -}; - -/* The default settings */ -static const struct pmcmsptwi_clockcfg pmcmsptwi_defclockcfg = { - .standard = { - .filter = 0x3, - .clock = 0x1f, - }, - .highspeed = { - .filter = 0x3, - .clock = 0x1f, - }, -}; - -static const struct pmcmsptwi_cfg pmcmsptwi_defcfg = { - .arbf = 0x03, - .nak = 0x03, - .add10 = 0x00, - .mst_code = 0x00, - .arb = 0x01, - .highspeed = 0x00, -}; - -static struct pmcmsptwi_data pmcmsptwi_data; - -static struct i2c_adapter pmcmsptwi_adapter; - -/* inline helper functions */ -static inline u32 pmcmsptwi_clock_to_reg( - const struct pmcmsptwi_clock *clock) -{ - return ((clock->filter & 0xf) << 12) | (clock->clock & 0x03ff); -} - -static inline void pmcmsptwi_reg_to_clock( - u32 reg, struct pmcmsptwi_clock *clock) -{ - clock->filter = (reg >> 12) & 0xf; - clock->clock = reg & 0x03ff; -} - -static inline u32 pmcmsptwi_cfg_to_reg(const struct pmcmsptwi_cfg *cfg) -{ - return ((cfg->arbf & 0xf) << 12) | - ((cfg->nak & 0xf) << 8) | - ((cfg->add10 & 0x1) << 7) | - ((cfg->mst_code & 0x7) << 4) | - ((cfg->arb & 0x1) << 1) | - (cfg->highspeed & 0x1); -} - -static inline void pmcmsptwi_reg_to_cfg(u32 reg, struct pmcmsptwi_cfg *cfg) -{ - cfg->arbf = (reg >> 12) & 0xf; - cfg->nak = (reg >> 8) & 0xf; - cfg->add10 = (reg >> 7) & 0x1; - cfg->mst_code = (reg >> 4) & 0x7; - cfg->arb = (reg >> 1) & 0x1; - cfg->highspeed = reg & 0x1; -} - -/* - * Sets the current clock configuration - */ -static void pmcmsptwi_set_clock_config(const struct pmcmsptwi_clockcfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->standard), - data->iobase + MSP_TWI_SF_CLK_REG_OFFSET); - pmcmsptwi_writel(pmcmsptwi_clock_to_reg(&cfg->highspeed), - data->iobase + MSP_TWI_HS_CLK_REG_OFFSET); - mutex_unlock(&data->lock); -} - -/* - * Gets the current TWI bus configuration - */ -static void pmcmsptwi_get_twi_config(struct pmcmsptwi_cfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_reg_to_cfg(pmcmsptwi_readl( - data->iobase + MSP_TWI_CFG_REG_OFFSET), cfg); - mutex_unlock(&data->lock); -} - -/* - * Sets the current TWI bus configuration - */ -static void pmcmsptwi_set_twi_config(const struct pmcmsptwi_cfg *cfg, - struct pmcmsptwi_data *data) -{ - mutex_lock(&data->lock); - pmcmsptwi_writel(pmcmsptwi_cfg_to_reg(cfg), - data->iobase + MSP_TWI_CFG_REG_OFFSET); - mutex_unlock(&data->lock); -} - -/* - * Parses the 'int_sts' register and returns a well-defined error code - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_get_result(u32 reg) -{ - if (reg & MSP_TWI_INT_STS_LOST_ARBITRATION) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Lost arbitration\n"); - return MSP_TWI_XFER_LOST_ARBITRATION; - } else if (reg & MSP_TWI_INT_STS_NO_RESPONSE) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: No response\n"); - return MSP_TWI_XFER_NO_RESPONSE; - } else if (reg & MSP_TWI_INT_STS_DATA_COLLISION) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Data collision\n"); - return MSP_TWI_XFER_DATA_COLLISION; - } else if (reg & MSP_TWI_INT_STS_BUSY) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: Bus busy\n"); - return MSP_TWI_XFER_BUSY; - } - - dev_dbg(&pmcmsptwi_adapter.dev, "Result: Operation succeeded\n"); - return MSP_TWI_XFER_OK; -} - -/* - * In interrupt mode, handle the interrupt. - * NOTE: Assumes data->lock is held. - */ -static irqreturn_t pmcmsptwi_interrupt(int irq, void *ptr) -{ - struct pmcmsptwi_data *data = ptr; - - u32 reason = pmcmsptwi_readl(data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - pmcmsptwi_writel(reason, data->iobase + MSP_TWI_INT_STS_REG_OFFSET); - - dev_dbg(&pmcmsptwi_adapter.dev, "Got interrupt 0x%08x\n", reason); - if (!(reason & MSP_TWI_INT_STS_DONE)) - return IRQ_NONE; - - data->last_result = pmcmsptwi_get_result(reason); - complete(&data->wait); - - return IRQ_HANDLED; -} - -/* - * Probe for and register the device and return 0 if there is one. - */ -static int __devinit pmcmsptwi_probe(struct platform_device *pldev) -{ - struct resource *res; - int rc = -ENODEV; - - /* get the static platform resources */ - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pldev->dev, "IOMEM resource not found\n"); - goto ret_err; - } - - /* reserve the memory region */ - if (!request_mem_region(res->start, resource_size(res), - pldev->name)) { - dev_err(&pldev->dev, - "Unable to get memory/io address region 0x%08x\n", - res->start); - rc = -EBUSY; - goto ret_err; - } - - /* remap the memory */ - pmcmsptwi_data.iobase = ioremap_nocache(res->start, - resource_size(res)); - if (!pmcmsptwi_data.iobase) { - dev_err(&pldev->dev, - "Unable to ioremap address 0x%08x\n", res->start); - rc = -EIO; - goto ret_unreserve; - } - - /* request the irq */ - pmcmsptwi_data.irq = platform_get_irq(pldev, 0); - if (pmcmsptwi_data.irq) { - rc = request_irq(pmcmsptwi_data.irq, &pmcmsptwi_interrupt, - IRQF_SHARED | IRQF_SAMPLE_RANDOM, - pldev->name, &pmcmsptwi_data); - if (rc == 0) { - /* - * Enable 'DONE' interrupt only. - * - * If you enable all interrupts, you will get one on - * error and another when the operation completes. - * This way you only have to handle one interrupt, - * but you can still check all result flags. - */ - pmcmsptwi_writel(MSP_TWI_INT_STS_DONE, - pmcmsptwi_data.iobase + - MSP_TWI_INT_MSK_REG_OFFSET); - } else { - dev_warn(&pldev->dev, - "Could not assign TWI IRQ handler " - "to irq %d (continuing with poll)\n", - pmcmsptwi_data.irq); - pmcmsptwi_data.irq = 0; - } - } - - init_completion(&pmcmsptwi_data.wait); - mutex_init(&pmcmsptwi_data.lock); - - pmcmsptwi_set_clock_config(&pmcmsptwi_defclockcfg, &pmcmsptwi_data); - pmcmsptwi_set_twi_config(&pmcmsptwi_defcfg, &pmcmsptwi_data); - - printk(KERN_INFO DRV_NAME ": Registering MSP71xx I2C adapter\n"); - - pmcmsptwi_adapter.dev.parent = &pldev->dev; - platform_set_drvdata(pldev, &pmcmsptwi_adapter); - i2c_set_adapdata(&pmcmsptwi_adapter, &pmcmsptwi_data); - - rc = i2c_add_adapter(&pmcmsptwi_adapter); - if (rc) { - dev_err(&pldev->dev, "Unable to register I2C adapter\n"); - goto ret_unmap; - } - - return 0; - -ret_unmap: - platform_set_drvdata(pldev, NULL); - if (pmcmsptwi_data.irq) { - pmcmsptwi_writel(0, - pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET); - free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data); - } - - iounmap(pmcmsptwi_data.iobase); - -ret_unreserve: - release_mem_region(res->start, resource_size(res)); - -ret_err: - return rc; -} - -/* - * Release the device and return 0 if there is one. - */ -static int __devexit pmcmsptwi_remove(struct platform_device *pldev) -{ - struct resource *res; - - i2c_del_adapter(&pmcmsptwi_adapter); - - platform_set_drvdata(pldev, NULL); - if (pmcmsptwi_data.irq) { - pmcmsptwi_writel(0, - pmcmsptwi_data.iobase + MSP_TWI_INT_MSK_REG_OFFSET); - free_irq(pmcmsptwi_data.irq, &pmcmsptwi_data); - } - - iounmap(pmcmsptwi_data.iobase); - - res = platform_get_resource(pldev, IORESOURCE_MEM, 0); - release_mem_region(res->start, resource_size(res)); - - return 0; -} - -/* - * Polls the 'busy' register until the command is complete. - * NOTE: Assumes data->lock is held. - */ -static void pmcmsptwi_poll_complete(struct pmcmsptwi_data *data) -{ - int i; - - for (i = 0; i < MSP_MAX_POLL; i++) { - u32 val = pmcmsptwi_readl(data->iobase + - MSP_TWI_BUSY_REG_OFFSET); - if (val == 0) { - u32 reason = pmcmsptwi_readl(data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - pmcmsptwi_writel(reason, data->iobase + - MSP_TWI_INT_STS_REG_OFFSET); - data->last_result = pmcmsptwi_get_result(reason); - return; - } - udelay(MSP_POLL_DELAY); - } - - dev_dbg(&pmcmsptwi_adapter.dev, "Result: Poll timeout\n"); - data->last_result = MSP_TWI_XFER_TIMEOUT; -} - -/* - * Do the transfer (low level): - * May use interrupt-driven or polling, depending on if an IRQ is - * presently registered. - * NOTE: Assumes data->lock is held. - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_do_xfer( - u32 reg, struct pmcmsptwi_data *data) -{ - dev_dbg(&pmcmsptwi_adapter.dev, "Writing cmd reg 0x%08x\n", reg); - pmcmsptwi_writel(reg, data->iobase + MSP_TWI_CMD_REG_OFFSET); - if (data->irq) { - unsigned long timeleft = wait_for_completion_timeout( - &data->wait, MSP_IRQ_TIMEOUT); - if (timeleft == 0) { - dev_dbg(&pmcmsptwi_adapter.dev, - "Result: IRQ timeout\n"); - complete(&data->wait); - data->last_result = MSP_TWI_XFER_TIMEOUT; - } - } else - pmcmsptwi_poll_complete(data); - - return data->last_result; -} - -/* - * Helper routine, converts 'pmctwi_cmd' struct to register format - */ -static inline u32 pmcmsptwi_cmd_to_reg(const struct pmcmsptwi_cmd *cmd) -{ - return ((cmd->type & 0x3) << 8) | - (((cmd->write_len - 1) & 0x7) << 4) | - ((cmd->read_len - 1) & 0x7); -} - -/* - * Do the transfer (high level) - */ -static enum pmcmsptwi_xfer_result pmcmsptwi_xfer_cmd( - struct pmcmsptwi_cmd *cmd, - struct pmcmsptwi_data *data) -{ - enum pmcmsptwi_xfer_result retval; - - if ((cmd->type == MSP_TWI_CMD_WRITE && cmd->write_len == 0) || - (cmd->type == MSP_TWI_CMD_READ && cmd->read_len == 0) || - (cmd->type == MSP_TWI_CMD_WRITE_READ && - (cmd->read_len == 0 || cmd->write_len == 0))) { - dev_err(&pmcmsptwi_adapter.dev, - "%s: Cannot transfer less than 1 byte\n", - __func__); - return -EINVAL; - } - - if (cmd->read_len > MSP_MAX_BYTES_PER_RW || - cmd->write_len > MSP_MAX_BYTES_PER_RW) { - dev_err(&pmcmsptwi_adapter.dev, - "%s: Cannot transfer more than %d bytes\n", - __func__, MSP_MAX_BYTES_PER_RW); - return -EINVAL; - } - - mutex_lock(&data->lock); - dev_dbg(&pmcmsptwi_adapter.dev, - "Setting address to 0x%04x\n", cmd->addr); - pmcmsptwi_writel(cmd->addr, data->iobase + MSP_TWI_ADD_REG_OFFSET); - - if (cmd->type == MSP_TWI_CMD_WRITE || - cmd->type == MSP_TWI_CMD_WRITE_READ) { - u64 tmp = be64_to_cpup((__be64 *)cmd->write_data); - tmp >>= (MSP_MAX_BYTES_PER_RW - cmd->write_len) * 8; - dev_dbg(&pmcmsptwi_adapter.dev, "Writing 0x%016llx\n", tmp); - pmcmsptwi_writel(tmp & 0x00000000ffffffffLL, - data->iobase + MSP_TWI_DAT_0_REG_OFFSET); - if (cmd->write_len > 4) - pmcmsptwi_writel(tmp >> 32, - data->iobase + MSP_TWI_DAT_1_REG_OFFSET); - } - - retval = pmcmsptwi_do_xfer(pmcmsptwi_cmd_to_reg(cmd), data); - if (retval != MSP_TWI_XFER_OK) - goto xfer_err; - - if (cmd->type == MSP_TWI_CMD_READ || - cmd->type == MSP_TWI_CMD_WRITE_READ) { - int i; - u64 rmsk = ~(0xffffffffffffffffLL << (cmd->read_len * 8)); - u64 tmp = (u64)pmcmsptwi_readl(data->iobase + - MSP_TWI_DAT_0_REG_OFFSET); - if (cmd->read_len > 4) - tmp |= (u64)pmcmsptwi_readl(data->iobase + - MSP_TWI_DAT_1_REG_OFFSET) << 32; - tmp &= rmsk; - dev_dbg(&pmcmsptwi_adapter.dev, "Read 0x%016llx\n", tmp); - - for (i = 0; i < cmd->read_len; i++) - cmd->read_data[i] = tmp >> i; - } - -xfer_err: - mutex_unlock(&data->lock); - - return retval; -} - -/* -- Algorithm functions -- */ - -/* - * Sends an i2c command out on the adapter - */ -static int pmcmsptwi_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msg, int num) -{ - struct pmcmsptwi_data *data = i2c_get_adapdata(adap); - struct pmcmsptwi_cmd cmd; - struct pmcmsptwi_cfg oldcfg, newcfg; - int ret; - - if (num > 2) { - dev_dbg(&adap->dev, "%d messages unsupported\n", num); - return -EINVAL; - } else if (num == 2) { - /* Check for a dual write-then-read command */ - struct i2c_msg *nextmsg = msg + 1; - if (!(msg->flags & I2C_M_RD) && - (nextmsg->flags & I2C_M_RD) && - msg->addr == nextmsg->addr) { - cmd.type = MSP_TWI_CMD_WRITE_READ; - cmd.write_len = msg->len; - cmd.write_data = msg->buf; - cmd.read_len = nextmsg->len; - cmd.read_data = nextmsg->buf; - } else { - dev_dbg(&adap->dev, - "Non write-read dual messages unsupported\n"); - return -EINVAL; - } - } else if (msg->flags & I2C_M_RD) { - cmd.type = MSP_TWI_CMD_READ; - cmd.read_len = msg->len; - cmd.read_data = msg->buf; - cmd.write_len = 0; - cmd.write_data = NULL; - } else { - cmd.type = MSP_TWI_CMD_WRITE; - cmd.read_len = 0; - cmd.read_data = NULL; - cmd.write_len = msg->len; - cmd.write_data = msg->buf; - } - - if (msg->len == 0) { - dev_err(&adap->dev, "Zero-byte messages unsupported\n"); - return -EINVAL; - } - - cmd.addr = msg->addr; - - if (msg->flags & I2C_M_TEN) { - pmcmsptwi_get_twi_config(&newcfg, data); - memcpy(&oldcfg, &newcfg, sizeof(oldcfg)); - - /* Set the special 10-bit address flag */ - newcfg.add10 = 1; - - pmcmsptwi_set_twi_config(&newcfg, data); - } - - /* Execute the command */ - ret = pmcmsptwi_xfer_cmd(&cmd, data); - - if (msg->flags & I2C_M_TEN) - pmcmsptwi_set_twi_config(&oldcfg, data); - - dev_dbg(&adap->dev, "I2C %s of %d bytes %s\n", - (msg->flags & I2C_M_RD) ? "read" : "write", msg->len, - (ret == MSP_TWI_XFER_OK) ? "succeeded" : "failed"); - - if (ret != MSP_TWI_XFER_OK) { - /* - * TODO: We could potentially loop and retry in the case - * of MSP_TWI_XFER_TIMEOUT. - */ - return -1; - } - - return 0; -} - -static u32 pmcmsptwi_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL; -} - -/* -- Initialization -- */ - -static struct i2c_algorithm pmcmsptwi_algo = { - .master_xfer = pmcmsptwi_master_xfer, - .functionality = pmcmsptwi_i2c_func, -}; - -static struct i2c_adapter pmcmsptwi_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &pmcmsptwi_algo, - .name = DRV_NAME, -}; - -static struct platform_driver pmcmsptwi_driver = { - .probe = pmcmsptwi_probe, - .remove = __devexit_p(pmcmsptwi_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(pmcmsptwi_driver); - -MODULE_DESCRIPTION("PMC MSP TWI/SMBus/I2C driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pnx.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pnx.c deleted file mode 100644 index eb8ad538..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pnx.c +++ /dev/null @@ -1,733 +0,0 @@ -/* - * Provides I2C support for Philips PNX010x/PNX4008 boards. - * - * Authors: Dennis Kovalev <dkovalev@ru.mvista.com> - * Vitaly Wool <vwool@ru.mvista.com> - * - * 2004-2006 (c) MontaVista Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include <linux/module.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/timer.h> -#include <linux/completion.h> -#include <linux/platform_device.h> -#include <linux/i2c-pnx.h> -#include <linux/io.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/slab.h> - -#include <mach/hardware.h> -#include <mach/i2c.h> - -#define I2C_PNX_TIMEOUT 10 /* msec */ -#define I2C_PNX_SPEED_KHZ 100 -#define I2C_PNX_REGION_SIZE 0x100 - -static inline int wait_timeout(long timeout, struct i2c_pnx_algo_data *data) -{ - while (timeout > 0 && - (ioread32(I2C_REG_STS(data)) & mstatus_active)) { - mdelay(1); - timeout--; - } - return (timeout <= 0); -} - -static inline int wait_reset(long timeout, struct i2c_pnx_algo_data *data) -{ - while (timeout > 0 && - (ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) { - mdelay(1); - timeout--; - } - return (timeout <= 0); -} - -static inline void i2c_pnx_arm_timer(struct i2c_pnx_algo_data *alg_data) -{ - struct timer_list *timer = &alg_data->mif.timer; - unsigned long expires = msecs_to_jiffies(I2C_PNX_TIMEOUT); - - if (expires <= 1) - expires = 2; - - del_timer_sync(timer); - - dev_dbg(&alg_data->adapter.dev, "Timer armed at %lu plus %lu jiffies.\n", - jiffies, expires); - - timer->expires = jiffies + expires; - timer->data = (unsigned long)alg_data; - - add_timer(timer); -} - -/** - * i2c_pnx_start - start a device - * @slave_addr: slave address - * @adap: pointer to adapter structure - * - * Generate a START signal in the desired mode. - */ -static int i2c_pnx_start(unsigned char slave_addr, - struct i2c_pnx_algo_data *alg_data) -{ - dev_dbg(&alg_data->adapter.dev, "%s(): addr 0x%x mode %d\n", __func__, - slave_addr, alg_data->mif.mode); - - /* Check for 7 bit slave addresses only */ - if (slave_addr & ~0x7f) { - dev_err(&alg_data->adapter.dev, - "%s: Invalid slave address %x. Only 7-bit addresses are supported\n", - alg_data->adapter.name, slave_addr); - return -EINVAL; - } - - /* First, make sure bus is idle */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) { - /* Somebody else is monopolizing the bus */ - dev_err(&alg_data->adapter.dev, - "%s: Bus busy. Slave addr = %02x, cntrl = %x, stat = %x\n", - alg_data->adapter.name, slave_addr, - ioread32(I2C_REG_CTL(alg_data)), - ioread32(I2C_REG_STS(alg_data))); - return -EBUSY; - } else if (ioread32(I2C_REG_STS(alg_data)) & mstatus_afi) { - /* Sorry, we lost the bus */ - dev_err(&alg_data->adapter.dev, - "%s: Arbitration failure. Slave addr = %02x\n", - alg_data->adapter.name, slave_addr); - return -EIO; - } - - /* - * OK, I2C is enabled and we have the bus. - * Clear the current TDI and AFI status flags. - */ - iowrite32(ioread32(I2C_REG_STS(alg_data)) | mstatus_tdi | mstatus_afi, - I2C_REG_STS(alg_data)); - - dev_dbg(&alg_data->adapter.dev, "%s(): sending %#x\n", __func__, - (slave_addr << 1) | start_bit | alg_data->mif.mode); - - /* Write the slave address, START bit and R/W bit */ - iowrite32((slave_addr << 1) | start_bit | alg_data->mif.mode, - I2C_REG_TX(alg_data)); - - dev_dbg(&alg_data->adapter.dev, "%s(): exit\n", __func__); - - return 0; -} - -/** - * i2c_pnx_stop - stop a device - * @adap: pointer to I2C adapter structure - * - * Generate a STOP signal to terminate the master transaction. - */ -static void i2c_pnx_stop(struct i2c_pnx_algo_data *alg_data) -{ - /* Only 1 msec max timeout due to interrupt context */ - long timeout = 1000; - - dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - /* Write a STOP bit to TX FIFO */ - iowrite32(0xff | stop_bit, I2C_REG_TX(alg_data)); - - /* Wait until the STOP is seen. */ - while (timeout > 0 && - (ioread32(I2C_REG_STS(alg_data)) & mstatus_active)) { - /* may be called from interrupt context */ - udelay(1); - timeout--; - } - - dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); -} - -/** - * i2c_pnx_master_xmit - transmit data to slave - * @adap: pointer to I2C adapter structure - * - * Sends one byte of data to the slave - */ -static int i2c_pnx_master_xmit(struct i2c_pnx_algo_data *alg_data) -{ - u32 val; - - dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - if (alg_data->mif.len > 0) { - /* We still have something to talk about... */ - val = *alg_data->mif.buf++; - - if (alg_data->mif.len == 1) - val |= stop_bit; - - alg_data->mif.len--; - iowrite32(val, I2C_REG_TX(alg_data)); - - dev_dbg(&alg_data->adapter.dev, "%s(): xmit %#x [%d]\n", - __func__, val, alg_data->mif.len + 1); - - if (alg_data->mif.len == 0) { - if (alg_data->last) { - /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&alg_data->adapter.dev, - "The bus is still active after timeout\n"); - } - /* Disable master interrupts */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) & - ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), - I2C_REG_CTL(alg_data)); - - del_timer_sync(&alg_data->mif.timer); - - dev_dbg(&alg_data->adapter.dev, - "%s(): Waking up xfer routine.\n", - __func__); - - complete(&alg_data->mif.complete); - } - } else if (alg_data->mif.len == 0) { - /* zero-sized transfer */ - i2c_pnx_stop(alg_data); - - /* Disable master interrupts. */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) & - ~(mcntrl_afie | mcntrl_naie | mcntrl_drmie), - I2C_REG_CTL(alg_data)); - - /* Stop timer. */ - del_timer_sync(&alg_data->mif.timer); - dev_dbg(&alg_data->adapter.dev, - "%s(): Waking up xfer routine after zero-xfer.\n", - __func__); - - complete(&alg_data->mif.complete); - } - - dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - return 0; -} - -/** - * i2c_pnx_master_rcv - receive data from slave - * @adap: pointer to I2C adapter structure - * - * Reads one byte data from the slave - */ -static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data) -{ - unsigned int val = 0; - u32 ctl = 0; - - dev_dbg(&alg_data->adapter.dev, "%s(): entering: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - /* Check, whether there is already data, - * or we didn't 'ask' for it yet. - */ - if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) { - dev_dbg(&alg_data->adapter.dev, - "%s(): Write dummy data to fill Rx-fifo...\n", - __func__); - - if (alg_data->mif.len == 1) { - /* Last byte, do not acknowledge next rcv. */ - val |= stop_bit; - - /* - * Enable interrupt RFDAIE (data in Rx fifo), - * and disable DRMIE (need data for Tx) - */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl |= mcntrl_rffie | mcntrl_daie; - ctl &= ~mcntrl_drmie; - iowrite32(ctl, I2C_REG_CTL(alg_data)); - } - - /* - * Now we'll 'ask' for data: - * For each byte we want to receive, we must - * write a (dummy) byte to the Tx-FIFO. - */ - iowrite32(val, I2C_REG_TX(alg_data)); - - return 0; - } - - /* Handle data. */ - if (alg_data->mif.len > 0) { - val = ioread32(I2C_REG_RX(alg_data)); - *alg_data->mif.buf++ = (u8) (val & 0xff); - dev_dbg(&alg_data->adapter.dev, "%s(): rcv 0x%x [%d]\n", - __func__, val, alg_data->mif.len); - - alg_data->mif.len--; - if (alg_data->mif.len == 0) { - if (alg_data->last) - /* Wait until the STOP is seen. */ - if (wait_timeout(I2C_PNX_TIMEOUT, alg_data)) - dev_err(&alg_data->adapter.dev, - "The bus is still active after timeout\n"); - - /* Disable master interrupts */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie | mcntrl_daie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Kill timer. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } - } - - dev_dbg(&alg_data->adapter.dev, "%s(): exiting: stat = %04x.\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - return 0; -} - -static irqreturn_t i2c_pnx_interrupt(int irq, void *dev_id) -{ - struct i2c_pnx_algo_data *alg_data = dev_id; - u32 stat, ctl; - - dev_dbg(&alg_data->adapter.dev, - "%s(): mstat = %x mctrl = %x, mode = %d\n", - __func__, - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data)), - alg_data->mif.mode); - stat = ioread32(I2C_REG_STS(alg_data)); - - /* let's see what kind of event this is */ - if (stat & mstatus_afi) { - /* We lost arbitration in the midst of a transfer */ - alg_data->mif.ret = -EIO; - - /* Disable master interrupts. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Stop timer, to prevent timeout. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } else if (stat & mstatus_nai) { - /* Slave did not acknowledge, generate a STOP */ - dev_dbg(&alg_data->adapter.dev, - "%s(): Slave did not acknowledge, generating a STOP.\n", - __func__); - i2c_pnx_stop(alg_data); - - /* Disable master interrupts. */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | - mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - /* Our return value. */ - alg_data->mif.ret = -EIO; - - /* Stop timer, to prevent timeout. */ - del_timer_sync(&alg_data->mif.timer); - complete(&alg_data->mif.complete); - } else { - /* - * Two options: - * - Master Tx needs data. - * - There is data in the Rx-fifo - * The latter is only the case if we have requested for data, - * via a dummy write. (See 'i2c_pnx_master_rcv'.) - * We therefore check, as a sanity check, whether that interrupt - * has been enabled. - */ - if ((stat & mstatus_drmi) || !(stat & mstatus_rfe)) { - if (alg_data->mif.mode == I2C_SMBUS_WRITE) { - i2c_pnx_master_xmit(alg_data); - } else if (alg_data->mif.mode == I2C_SMBUS_READ) { - i2c_pnx_master_rcv(alg_data); - } - } - } - - /* Clear TDI and AFI bits */ - stat = ioread32(I2C_REG_STS(alg_data)); - iowrite32(stat | mstatus_tdi | mstatus_afi, I2C_REG_STS(alg_data)); - - dev_dbg(&alg_data->adapter.dev, - "%s(): exiting, stat = %x ctrl = %x.\n", - __func__, ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); - - return IRQ_HANDLED; -} - -static void i2c_pnx_timeout(unsigned long data) -{ - struct i2c_pnx_algo_data *alg_data = (struct i2c_pnx_algo_data *)data; - u32 ctl; - - dev_err(&alg_data->adapter.dev, - "Master timed out. stat = %04x, cntrl = %04x. Resetting master...\n", - ioread32(I2C_REG_STS(alg_data)), - ioread32(I2C_REG_CTL(alg_data))); - - /* Reset master and disable interrupts */ - ctl = ioread32(I2C_REG_CTL(alg_data)); - ctl &= ~(mcntrl_afie | mcntrl_naie | mcntrl_rffie | mcntrl_drmie); - iowrite32(ctl, I2C_REG_CTL(alg_data)); - - ctl |= mcntrl_reset; - iowrite32(ctl, I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - alg_data->mif.ret = -EIO; - complete(&alg_data->mif.complete); -} - -static inline void bus_reset_if_active(struct i2c_pnx_algo_data *alg_data) -{ - u32 stat; - - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_active) { - dev_err(&alg_data->adapter.dev, - "%s: Bus is still active after xfer. Reset it...\n", - alg_data->adapter.name); - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } else if (!(stat & mstatus_rfe) || !(stat & mstatus_tfe)) { - /* If there is data in the fifo's after transfer, - * flush fifo's by reset. - */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } else if (stat & mstatus_nai) { - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_reset, - I2C_REG_CTL(alg_data)); - wait_reset(I2C_PNX_TIMEOUT, alg_data); - } -} - -/** - * i2c_pnx_xfer - generic transfer entry point - * @adap: pointer to I2C adapter structure - * @msgs: array of messages - * @num: number of messages - * - * Initiates the transfer - */ -static int -i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct i2c_msg *pmsg; - int rc = 0, completed = 0, i; - struct i2c_pnx_algo_data *alg_data = adap->algo_data; - u32 stat = ioread32(I2C_REG_STS(alg_data)); - - dev_dbg(&alg_data->adapter.dev, - "%s(): entering: %d messages, stat = %04x.\n", - __func__, num, ioread32(I2C_REG_STS(alg_data))); - - bus_reset_if_active(alg_data); - - /* Process transactions in a loop. */ - for (i = 0; rc >= 0 && i < num; i++) { - u8 addr; - - pmsg = &msgs[i]; - addr = pmsg->addr; - - if (pmsg->flags & I2C_M_TEN) { - dev_err(&alg_data->adapter.dev, - "%s: 10 bits addr not supported!\n", - alg_data->adapter.name); - rc = -EINVAL; - break; - } - - alg_data->mif.buf = pmsg->buf; - alg_data->mif.len = pmsg->len; - alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ? - I2C_SMBUS_READ : I2C_SMBUS_WRITE; - alg_data->mif.ret = 0; - alg_data->last = (i == num - 1); - - dev_dbg(&alg_data->adapter.dev, "%s(): mode %d, %d bytes\n", - __func__, alg_data->mif.mode, alg_data->mif.len); - - i2c_pnx_arm_timer(alg_data); - - /* initialize the completion var */ - init_completion(&alg_data->mif.complete); - - /* Enable master interrupt */ - iowrite32(ioread32(I2C_REG_CTL(alg_data)) | mcntrl_afie | - mcntrl_naie | mcntrl_drmie, - I2C_REG_CTL(alg_data)); - - /* Put start-code and slave-address on the bus. */ - rc = i2c_pnx_start(addr, alg_data); - if (rc < 0) - break; - - /* Wait for completion */ - wait_for_completion(&alg_data->mif.complete); - - if (!(rc = alg_data->mif.ret)) - completed++; - dev_dbg(&alg_data->adapter.dev, - "%s(): Complete, return code = %d.\n", - __func__, rc); - - /* Clear TDI and AFI bits in case they are set. */ - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_tdi) { - dev_dbg(&alg_data->adapter.dev, - "%s: TDI still set... clearing now.\n", - alg_data->adapter.name); - iowrite32(stat, I2C_REG_STS(alg_data)); - } - if ((stat = ioread32(I2C_REG_STS(alg_data))) & mstatus_afi) { - dev_dbg(&alg_data->adapter.dev, - "%s: AFI still set... clearing now.\n", - alg_data->adapter.name); - iowrite32(stat, I2C_REG_STS(alg_data)); - } - } - - bus_reset_if_active(alg_data); - - /* Cleanup to be sure... */ - alg_data->mif.buf = NULL; - alg_data->mif.len = 0; - - dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n", - __func__, ioread32(I2C_REG_STS(alg_data))); - - if (completed != num) - return ((rc < 0) ? rc : -EREMOTEIO); - - return num; -} - -static u32 i2c_pnx_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm pnx_algorithm = { - .master_xfer = i2c_pnx_xfer, - .functionality = i2c_pnx_func, -}; - -#ifdef CONFIG_PM -static int i2c_pnx_controller_suspend(struct platform_device *pdev, - pm_message_t state) -{ - struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - - clk_disable(alg_data->clk); - - return 0; -} - -static int i2c_pnx_controller_resume(struct platform_device *pdev) -{ - struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - - return clk_enable(alg_data->clk); -} -#else -#define i2c_pnx_controller_suspend NULL -#define i2c_pnx_controller_resume NULL -#endif - -static int __devinit i2c_pnx_probe(struct platform_device *pdev) -{ - unsigned long tmp; - int ret = 0; - struct i2c_pnx_algo_data *alg_data; - unsigned long freq; - struct i2c_pnx_data *i2c_pnx = pdev->dev.platform_data; - - if (!i2c_pnx || !i2c_pnx->name) { - dev_err(&pdev->dev, "%s: no platform data supplied\n", - __func__); - ret = -EINVAL; - goto out; - } - - alg_data = kzalloc(sizeof(*alg_data), GFP_KERNEL); - if (!alg_data) { - ret = -ENOMEM; - goto err_kzalloc; - } - - platform_set_drvdata(pdev, alg_data); - - strlcpy(alg_data->adapter.name, i2c_pnx->name, - sizeof(alg_data->adapter.name)); - alg_data->adapter.dev.parent = &pdev->dev; - alg_data->adapter.algo = &pnx_algorithm; - alg_data->adapter.algo_data = alg_data; - alg_data->adapter.nr = pdev->id; - alg_data->i2c_pnx = i2c_pnx; - - alg_data->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(alg_data->clk)) { - ret = PTR_ERR(alg_data->clk); - goto out_drvdata; - } - - init_timer(&alg_data->mif.timer); - alg_data->mif.timer.function = i2c_pnx_timeout; - alg_data->mif.timer.data = (unsigned long)alg_data; - - /* Register I/O resource */ - if (!request_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE, - pdev->name)) { - dev_err(&pdev->dev, - "I/O region 0x%08x for I2C already in use.\n", - i2c_pnx->base); - ret = -ENODEV; - goto out_clkget; - } - - alg_data->ioaddr = ioremap(i2c_pnx->base, I2C_PNX_REGION_SIZE); - if (!alg_data->ioaddr) { - dev_err(&pdev->dev, "Couldn't ioremap I2C I/O region\n"); - ret = -ENOMEM; - goto out_release; - } - - ret = clk_enable(alg_data->clk); - if (ret) - goto out_unmap; - - freq = clk_get_rate(alg_data->clk); - - /* - * Clock Divisor High This value is the number of system clocks - * the serial clock (SCL) will be high. - * For example, if the system clock period is 50 ns and the maximum - * desired serial period is 10000 ns (100 kHz), then CLKHI would be - * set to 0.5*(f_sys/f_i2c)-2=0.5*(20e6/100e3)-2=98. The actual value - * programmed into CLKHI will vary from this slightly due to - * variations in the output pad's rise and fall times as well as - * the deglitching filter length. - */ - - tmp = ((freq / 1000) / I2C_PNX_SPEED_KHZ) / 2 - 2; - if (tmp > 0x3FF) - tmp = 0x3FF; - iowrite32(tmp, I2C_REG_CKH(alg_data)); - iowrite32(tmp, I2C_REG_CKL(alg_data)); - - iowrite32(mcntrl_reset, I2C_REG_CTL(alg_data)); - if (wait_reset(I2C_PNX_TIMEOUT, alg_data)) { - ret = -ENODEV; - goto out_clock; - } - init_completion(&alg_data->mif.complete); - - ret = request_irq(i2c_pnx->irq, i2c_pnx_interrupt, - 0, pdev->name, alg_data); - if (ret) - goto out_clock; - - /* Register this adapter with the I2C subsystem */ - ret = i2c_add_numbered_adapter(&alg_data->adapter); - if (ret < 0) { - dev_err(&pdev->dev, "I2C: Failed to add bus\n"); - goto out_irq; - } - - dev_dbg(&pdev->dev, "%s: Master at %#8x, irq %d.\n", - alg_data->adapter.name, i2c_pnx->base, i2c_pnx->irq); - - return 0; - -out_irq: - free_irq(i2c_pnx->irq, alg_data); -out_clock: - clk_disable(alg_data->clk); -out_unmap: - iounmap(alg_data->ioaddr); -out_release: - release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); -out_clkget: - clk_put(alg_data->clk); -out_drvdata: - kfree(alg_data); -err_kzalloc: - platform_set_drvdata(pdev, NULL); -out: - return ret; -} - -static int __devexit i2c_pnx_remove(struct platform_device *pdev) -{ - struct i2c_pnx_algo_data *alg_data = platform_get_drvdata(pdev); - struct i2c_pnx_data *i2c_pnx = alg_data->i2c_pnx; - - free_irq(i2c_pnx->irq, alg_data); - i2c_del_adapter(&alg_data->adapter); - clk_disable(alg_data->clk); - iounmap(alg_data->ioaddr); - release_mem_region(i2c_pnx->base, I2C_PNX_REGION_SIZE); - clk_put(alg_data->clk); - kfree(alg_data); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver i2c_pnx_driver = { - .driver = { - .name = "pnx-i2c", - .owner = THIS_MODULE, - }, - .probe = i2c_pnx_probe, - .remove = __devexit_p(i2c_pnx_remove), - .suspend = i2c_pnx_controller_suspend, - .resume = i2c_pnx_controller_resume, -}; - -static int __init i2c_adap_pnx_init(void) -{ - return platform_driver_register(&i2c_pnx_driver); -} - -static void __exit i2c_adap_pnx_exit(void) -{ - platform_driver_unregister(&i2c_pnx_driver); -} - -MODULE_AUTHOR("Vitaly Wool, Dennis Kovalev <source@mvista.com>"); -MODULE_DESCRIPTION("I2C driver for Philips IP3204-based I2C busses"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pnx-i2c"); - -/* We need to make sure I2C is initialized before USB */ -subsys_initcall(i2c_adap_pnx_init); -module_exit(i2c_adap_pnx_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-powermac.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-powermac.c deleted file mode 100644 index 7b397c6f..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-powermac.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - i2c Support for Apple SMU Controller - - Copyright (c) 2005 Benjamin Herrenschmidt, IBM Corp. - <benh@kernel.crashing.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/types.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/device.h> -#include <linux/platform_device.h> -#include <asm/prom.h> -#include <asm/pmac_low_i2c.h> - -MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>"); -MODULE_DESCRIPTION("I2C driver for Apple PowerMac"); -MODULE_LICENSE("GPL"); - -/* - * SMBUS-type transfer entrypoint - */ -static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, - u16 addr, - unsigned short flags, - char read_write, - u8 command, - int size, - union i2c_smbus_data* data) -{ - struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); - int rc = 0; - int read = (read_write == I2C_SMBUS_READ); - int addrdir = (addr << 1) | read; - int mode, subsize, len; - u32 subaddr; - u8 *buf; - u8 local[2]; - - if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) { - mode = pmac_i2c_mode_std; - subsize = 0; - subaddr = 0; - } else { - mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub; - subsize = 1; - subaddr = command; - } - - switch (size) { - case I2C_SMBUS_QUICK: - buf = NULL; - len = 0; - break; - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - buf = &data->byte; - len = 1; - break; - case I2C_SMBUS_WORD_DATA: - if (!read) { - local[0] = data->word & 0xff; - local[1] = (data->word >> 8) & 0xff; - } - buf = local; - len = 2; - break; - - /* Note that these are broken vs. the expected smbus API where - * on reads, the length is actually returned from the function, - * but I think the current API makes no sense and I don't want - * any driver that I haven't verified for correctness to go - * anywhere near a pmac i2c bus anyway ... - * - * I'm also not completely sure what kind of phases to do between - * the actual command and the data (what I am _supposed_ to do that - * is). For now, I assume writes are a single stream and reads have - * a repeat start/addr phase (but not stop in between) - */ - case I2C_SMBUS_BLOCK_DATA: - buf = data->block; - len = data->block[0] + 1; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - buf = &data->block[1]; - len = data->block[0]; - break; - - default: - return -EINVAL; - } - - rc = pmac_i2c_open(bus, 0); - if (rc) { - dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); - return rc; - } - - rc = pmac_i2c_setmode(bus, mode); - if (rc) { - dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", - mode, rc); - goto bail; - } - - rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); - if (rc) { - if (rc == -ENXIO) - dev_dbg(&adap->dev, - "I2C transfer at 0x%02x failed, size %d, " - "err %d\n", addrdir >> 1, size, rc); - else - dev_err(&adap->dev, - "I2C transfer at 0x%02x failed, size %d, " - "err %d\n", addrdir >> 1, size, rc); - goto bail; - } - - if (size == I2C_SMBUS_WORD_DATA && read) { - data->word = ((u16)local[1]) << 8; - data->word |= local[0]; - } - - bail: - pmac_i2c_close(bus); - return rc; -} - -/* - * Generic i2c master transfer entrypoint. This driver only support single - * messages (for "lame i2c" transfers). Anything else should use the smbus - * entry point - */ -static int i2c_powermac_master_xfer( struct i2c_adapter *adap, - struct i2c_msg *msgs, - int num) -{ - struct pmac_i2c_bus *bus = i2c_get_adapdata(adap); - int rc = 0; - int read; - int addrdir; - - if (num != 1) { - dev_err(&adap->dev, - "Multi-message I2C transactions not supported\n"); - return -EOPNOTSUPP; - } - - if (msgs->flags & I2C_M_TEN) - return -EINVAL; - read = (msgs->flags & I2C_M_RD) != 0; - addrdir = (msgs->addr << 1) | read; - - rc = pmac_i2c_open(bus, 0); - if (rc) { - dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc); - return rc; - } - rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std); - if (rc) { - dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n", - pmac_i2c_mode_std, rc); - goto bail; - } - rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); - if (rc < 0) { - if (rc == -ENXIO) - dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n", - addrdir & 1 ? "read from" : "write to", - addrdir >> 1, rc); - else - dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", - addrdir & 1 ? "read from" : "write to", - addrdir >> 1, rc); - } - bail: - pmac_i2c_close(bus); - return rc < 0 ? rc : 1; -} - -static u32 i2c_powermac_func(struct i2c_adapter * adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_I2C; -} - -/* For now, we only handle smbus */ -static const struct i2c_algorithm i2c_powermac_algorithm = { - .smbus_xfer = i2c_powermac_smbus_xfer, - .master_xfer = i2c_powermac_master_xfer, - .functionality = i2c_powermac_func, -}; - - -static int __devexit i2c_powermac_remove(struct platform_device *dev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(dev); - int rc; - - rc = i2c_del_adapter(adapter); - /* We aren't that prepared to deal with this... */ - if (rc) - printk(KERN_WARNING - "i2c-powermac.c: Failed to remove bus %s !\n", - adapter->name); - platform_set_drvdata(dev, NULL); - memset(adapter, 0, sizeof(*adapter)); - - return 0; -} - - -static int __devinit i2c_powermac_probe(struct platform_device *dev) -{ - struct pmac_i2c_bus *bus = dev->dev.platform_data; - struct device_node *parent = NULL; - struct i2c_adapter *adapter; - const char *basename; - int rc; - - if (bus == NULL) - return -EINVAL; - adapter = pmac_i2c_get_adapter(bus); - - /* Ok, now we need to make up a name for the interface that will - * match what we used to do in the past, that is basically the - * controller's parent device node for keywest. PMU didn't have a - * naming convention and SMU has a different one - */ - switch(pmac_i2c_get_type(bus)) { - case pmac_i2c_bus_keywest: - parent = of_get_parent(pmac_i2c_get_controller(bus)); - if (parent == NULL) - return -EINVAL; - basename = parent->name; - break; - case pmac_i2c_bus_pmu: - basename = "pmu"; - break; - case pmac_i2c_bus_smu: - /* This is not what we used to do but I'm fixing drivers at - * the same time as this change - */ - basename = "smu"; - break; - default: - return -EINVAL; - } - snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename, - pmac_i2c_get_channel(bus)); - of_node_put(parent); - - platform_set_drvdata(dev, adapter); - adapter->algo = &i2c_powermac_algorithm; - i2c_set_adapdata(adapter, bus); - adapter->dev.parent = &dev->dev; - rc = i2c_add_adapter(adapter); - if (rc) { - printk(KERN_ERR "i2c-powermac: Adapter %s registration " - "failed\n", adapter->name); - memset(adapter, 0, sizeof(*adapter)); - } - - printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name); - - if (!strncmp(basename, "uni-n", 5)) { - struct device_node *np; - const u32 *prop; - struct i2c_board_info info; - - /* Instantiate I2C motion sensor if present */ - np = of_find_node_by_name(NULL, "accelerometer"); - if (np && of_device_is_compatible(np, "AAPL,accelerometer_1") && - (prop = of_get_property(np, "reg", NULL))) { - int i2c_bus; - const char *tmp_bus; - - /* look for bus either using "reg" or by path */ - tmp_bus = strstr(np->full_name, "/i2c-bus@"); - if (tmp_bus) - i2c_bus = *(tmp_bus + 9) - '0'; - else - i2c_bus = ((*prop) >> 8) & 0x0f; - - if (pmac_i2c_get_channel(bus) == i2c_bus) { - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = ((*prop) & 0xff) >> 1; - strlcpy(info.type, "ams", I2C_NAME_SIZE); - i2c_new_device(adapter, &info); - } - } - } - - return rc; -} - -static struct platform_driver i2c_powermac_driver = { - .probe = i2c_powermac_probe, - .remove = __devexit_p(i2c_powermac_remove), - .driver = { - .name = "i2c-powermac", - .bus = &platform_bus_type, - }, -}; - -module_platform_driver(i2c_powermac_driver); - -MODULE_ALIAS("platform:i2c-powermac"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-puv3.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-puv3.c deleted file mode 100644 index 93709fbe..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-puv3.c +++ /dev/null @@ -1,294 +0,0 @@ -/* - * I2C driver for PKUnity-v3 SoC - * Code specific to PKUnity SoC and UniCore ISA - * - * Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn> - * Copyright (C) 2001-2010 Guan Xuetao - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/types.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/clk.h> -#include <linux/platform_device.h> -#include <linux/io.h> -#include <mach/hardware.h> - -/* - * Poll the i2c status register until the specified bit is set. - * Returns 0 if timed out (100 msec). - */ -static short poll_status(unsigned long bit) -{ - int loop_cntr = 1000; - - if (bit & I2C_STATUS_TFNF) { - do { - udelay(10); - } while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0)); - } else { - /* RXRDY handler */ - do { - if (readl(I2C_TAR) == I2C_TAR_EEPROM) - msleep(20); - else - udelay(10); - } while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0)); - } - - return (loop_cntr > 0); -} - -static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - int i2c_reg = *buf; - - /* Read data */ - while (length--) { - if (!poll_status(I2C_STATUS_TFNF)) { - dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n"); - return -ETIMEDOUT; - } - - /* send addr */ - writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD); - - /* get ready to next write */ - i2c_reg++; - - /* send read CMD */ - writel(I2C_DATACMD_READ, I2C_DATACMD); - - /* wait until the Rx FIFO have available */ - if (!poll_status(I2C_STATUS_RFNE)) { - dev_dbg(&adap->dev, "RXRDY timeout\n"); - return -ETIMEDOUT; - } - - /* read the data to buf */ - *buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK); - buf++; - } - - return 0; -} - -static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length) -{ - int i2c_reg = *buf; - - /* Do nothing but storing the reg_num to a static variable */ - if (i2c_reg == -1) { - printk(KERN_WARNING "Error i2c reg\n"); - return -ETIMEDOUT; - } - - if (length == 1) - return 0; - - buf++; - length--; - while (length--) { - /* send addr */ - writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD); - - /* send write CMD */ - writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD); - - /* wait until the Rx FIFO have available */ - msleep(20); - - /* read the data to buf */ - i2c_reg++; - buf++; - } - - return 0; -} - -/* - * Generic i2c master transfer entrypoint. - * - */ -static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg, - int num) -{ - int i, ret; - unsigned char swap; - - /* Disable i2c */ - writel(I2C_ENABLE_DISABLE, I2C_ENABLE); - - /* Set the work mode and speed*/ - writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON); - - writel(pmsg->addr, I2C_TAR); - - /* Enable i2c */ - writel(I2C_ENABLE_ENABLE, I2C_ENABLE); - - dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num); - - for (i = 0; i < num; i++) { - dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i, - pmsg->flags & I2C_M_RD ? "read" : "writ", - pmsg->len, pmsg->len > 1 ? "s" : "", - pmsg->flags & I2C_M_RD ? "from" : "to", pmsg->addr); - - if (pmsg->len && pmsg->buf) { /* sanity check */ - if (pmsg->flags & I2C_M_RD) - ret = xfer_read(adap, pmsg->buf, pmsg->len); - else - ret = xfer_write(adap, pmsg->buf, pmsg->len); - - if (ret) - return ret; - - } - dev_dbg(&adap->dev, "transfer complete\n"); - pmsg++; /* next message */ - } - - /* XXX: fixup be16_to_cpu in bq27x00_battery.c */ - if (pmsg->addr == I2C_TAR_PWIC) { - swap = pmsg->buf[0]; - pmsg->buf[0] = pmsg->buf[1]; - pmsg->buf[1] = swap; - } - - return i; -} - -/* - * Return list of supported functionality. - */ -static u32 puv3_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm puv3_i2c_algorithm = { - .master_xfer = puv3_i2c_xfer, - .functionality = puv3_i2c_func, -}; - -/* - * Main initialization routine. - */ -static int __devinit puv3_i2c_probe(struct platform_device *pdev) -{ - struct i2c_adapter *adapter; - struct resource *mem; - int rc; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -ENODEV; - - if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c")) - return -EBUSY; - - adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL); - if (adapter == NULL) { - dev_err(&pdev->dev, "can't allocate inteface!\n"); - rc = -ENOMEM; - goto fail_nomem; - } - snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x", - mem->start); - adapter->algo = &puv3_i2c_algorithm; - adapter->class = I2C_CLASS_HWMON; - adapter->dev.parent = &pdev->dev; - - platform_set_drvdata(pdev, adapter); - - adapter->nr = pdev->id; - rc = i2c_add_numbered_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter '%s' registration failed\n", - adapter->name); - goto fail_add_adapter; - } - - dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n"); - return 0; - -fail_add_adapter: - platform_set_drvdata(pdev, NULL); - kfree(adapter); -fail_nomem: - release_mem_region(mem->start, resource_size(mem)); - - return rc; -} - -static int __devexit puv3_i2c_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct resource *mem; - int rc; - - rc = i2c_del_adapter(adapter); - if (rc) { - dev_err(&pdev->dev, "Adapter '%s' delete fail\n", - adapter->name); - return rc; - } - - put_device(&pdev->dev); - platform_set_drvdata(pdev, NULL); - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(mem->start, resource_size(mem)); - - return rc; -} - -#ifdef CONFIG_PM -static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state) -{ - int poll_count; - /* Disable the IIC */ - writel(I2C_ENABLE_DISABLE, I2C_ENABLE); - for (poll_count = 0; poll_count < 50; poll_count++) { - if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE) - udelay(25); - } - - return 0; -} - -static int puv3_i2c_resume(struct platform_device *dev) -{ - return 0 ; -} -#else -#define puv3_i2c_suspend NULL -#define puv3_i2c_resume NULL -#endif - -static struct platform_driver puv3_i2c_driver = { - .probe = puv3_i2c_probe, - .remove = __devexit_p(puv3_i2c_remove), - .suspend = puv3_i2c_suspend, - .resume = puv3_i2c_resume, - .driver = { - .name = "PKUnity-v3-I2C", - .owner = THIS_MODULE, - } -}; - -module_platform_driver(puv3_i2c_driver); - -MODULE_DESCRIPTION("PKUnity v3 I2C driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:puv3_i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa-pci.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa-pci.c deleted file mode 100644 index a0581798..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa-pci.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * The CE4100's I2C device is more or less the same one as found on PXA. - * It does not support slave mode, the register slightly moved. This PCI - * device provides three bars, every contains a single I2C controller. - */ -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/i2c/pxa-i2c.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_address.h> - -#define CE4100_PCI_I2C_DEVS 3 - -struct ce4100_devices { - struct platform_device *pdev[CE4100_PCI_I2C_DEVS]; -}; - -static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar) -{ - struct platform_device *pdev; - struct i2c_pxa_platform_data pdata; - struct resource res[2]; - struct device_node *child; - static int devnum; - int ret; - - memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data)); - memset(&res, 0, sizeof(res)); - - res[0].flags = IORESOURCE_MEM; - res[0].start = pci_resource_start(dev, bar); - res[0].end = pci_resource_end(dev, bar); - - res[1].flags = IORESOURCE_IRQ; - res[1].start = dev->irq; - res[1].end = dev->irq; - - for_each_child_of_node(dev->dev.of_node, child) { - const void *prop; - struct resource r; - int ret; - - ret = of_address_to_resource(child, 0, &r); - if (ret < 0) - continue; - if (r.start != res[0].start) - continue; - if (r.end != res[0].end) - continue; - if (r.flags != res[0].flags) - continue; - - prop = of_get_property(child, "fast-mode", NULL); - if (prop) - pdata.fast_mode = 1; - - break; - } - - if (!child) { - dev_err(&dev->dev, "failed to match a DT node for bar %d.\n", - bar); - ret = -EINVAL; - goto out; - } - - pdev = platform_device_alloc("ce4100-i2c", devnum); - if (!pdev) { - of_node_put(child); - ret = -ENOMEM; - goto out; - } - pdev->dev.parent = &dev->dev; - pdev->dev.of_node = child; - - ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res)); - if (ret) - goto err; - - ret = platform_device_add_data(pdev, &pdata, sizeof(pdata)); - if (ret) - goto err; - - ret = platform_device_add(pdev); - if (ret) - goto err; - devnum++; - return pdev; -err: - platform_device_put(pdev); -out: - return ERR_PTR(ret); -} - -static int __devinit ce4100_i2c_probe(struct pci_dev *dev, - const struct pci_device_id *ent) -{ - int ret; - int i; - struct ce4100_devices *sds; - - ret = pci_enable_device_mem(dev); - if (ret) - return ret; - - if (!dev->dev.of_node) { - dev_err(&dev->dev, "Missing device tree node.\n"); - return -EINVAL; - } - sds = kzalloc(sizeof(*sds), GFP_KERNEL); - if (!sds) { - ret = -ENOMEM; - goto err_mem; - } - - for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) { - sds->pdev[i] = add_i2c_device(dev, i); - if (IS_ERR(sds->pdev[i])) { - ret = PTR_ERR(sds->pdev[i]); - while (--i >= 0) - platform_device_unregister(sds->pdev[i]); - goto err_dev_add; - } - } - pci_set_drvdata(dev, sds); - return 0; - -err_dev_add: - pci_set_drvdata(dev, NULL); - kfree(sds); -err_mem: - pci_disable_device(dev); - return ret; -} - -static void __devexit ce4100_i2c_remove(struct pci_dev *dev) -{ - struct ce4100_devices *sds; - unsigned int i; - - sds = pci_get_drvdata(dev); - pci_set_drvdata(dev, NULL); - - for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) - platform_device_unregister(sds->pdev[i]); - - pci_disable_device(dev); - kfree(sds); -} - -static DEFINE_PCI_DEVICE_TABLE(ce4100_i2c_devices) = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)}, - { }, -}; -MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices); - -static struct pci_driver ce4100_i2c_driver = { - .name = "ce4100_i2c", - .id_table = ce4100_i2c_devices, - .probe = ce4100_i2c_probe, - .remove = __devexit_p(ce4100_i2c_remove), -}; - -static int __init ce4100_i2c_init(void) -{ - return pci_register_driver(&ce4100_i2c_driver); -} -module_init(ce4100_i2c_init); - -static void __exit ce4100_i2c_exit(void) -{ - pci_unregister_driver(&ce4100_i2c_driver); -} -module_exit(ce4100_i2c_exit); - -MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver"); -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa.c deleted file mode 100644 index f6733267..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-pxa.c +++ /dev/null @@ -1,1308 +0,0 @@ -/* - * i2c_adap_pxa.c - * - * I2C adapter for the PXA I2C bus access. - * - * Copyright (C) 2002 Intrinsyc Software Inc. - * Copyright (C) 2004-2005 Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * History: - * Apr 2002: Initial version [CS] - * Jun 2002: Properly separated algo/adap [FB] - * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] - * Jan 2003: added limited signal handling [Kai-Uwe Bloem] - * Sep 2004: Major rework to ensure efficient bus handling [RMK] - * Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood] - * Feb 2005: Rework slave mode handling [RMK] - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> -#include <linux/i2c-pxa.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/of_i2c.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/i2c/pxa-i2c.h> - -#include <asm/irq.h> - -#ifndef CONFIG_HAVE_CLK -#define clk_get(dev, id) NULL -#define clk_put(clk) do { } while (0) -#define clk_disable(clk) do { } while (0) -#define clk_enable(clk) do { } while (0) -#endif - -struct pxa_reg_layout { - u32 ibmr; - u32 idbr; - u32 icr; - u32 isr; - u32 isar; -}; - -enum pxa_i2c_types { - REGS_PXA2XX, - REGS_PXA3XX, - REGS_CE4100, -}; - -/* - * I2C registers definitions - */ -static struct pxa_reg_layout pxa_reg_layout[] = { - [REGS_PXA2XX] = { - .ibmr = 0x00, - .idbr = 0x08, - .icr = 0x10, - .isr = 0x18, - .isar = 0x20, - }, - [REGS_PXA3XX] = { - .ibmr = 0x00, - .idbr = 0x04, - .icr = 0x08, - .isr = 0x0c, - .isar = 0x10, - }, - [REGS_CE4100] = { - .ibmr = 0x14, - .idbr = 0x0c, - .icr = 0x00, - .isr = 0x04, - /* no isar register */ - }, -}; - -static const struct platform_device_id i2c_pxa_id_table[] = { - { "pxa2xx-i2c", REGS_PXA2XX }, - { "pxa3xx-pwri2c", REGS_PXA3XX }, - { "ce4100-i2c", REGS_CE4100 }, - { }, -}; -MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table); - -/* - * I2C bit definitions - */ - -#define ICR_START (1 << 0) /* start bit */ -#define ICR_STOP (1 << 1) /* stop bit */ -#define ICR_ACKNAK (1 << 2) /* send ACK(0) or NAK(1) */ -#define ICR_TB (1 << 3) /* transfer byte bit */ -#define ICR_MA (1 << 4) /* master abort */ -#define ICR_SCLE (1 << 5) /* master clock enable */ -#define ICR_IUE (1 << 6) /* unit enable */ -#define ICR_GCD (1 << 7) /* general call disable */ -#define ICR_ITEIE (1 << 8) /* enable tx interrupts */ -#define ICR_IRFIE (1 << 9) /* enable rx interrupts */ -#define ICR_BEIE (1 << 10) /* enable bus error ints */ -#define ICR_SSDIE (1 << 11) /* slave STOP detected int enable */ -#define ICR_ALDIE (1 << 12) /* enable arbitration interrupt */ -#define ICR_SADIE (1 << 13) /* slave address detected int enable */ -#define ICR_UR (1 << 14) /* unit reset */ -#define ICR_FM (1 << 15) /* fast mode */ - -#define ISR_RWM (1 << 0) /* read/write mode */ -#define ISR_ACKNAK (1 << 1) /* ack/nak status */ -#define ISR_UB (1 << 2) /* unit busy */ -#define ISR_IBB (1 << 3) /* bus busy */ -#define ISR_SSD (1 << 4) /* slave stop detected */ -#define ISR_ALD (1 << 5) /* arbitration loss detected */ -#define ISR_ITE (1 << 6) /* tx buffer empty */ -#define ISR_IRF (1 << 7) /* rx buffer full */ -#define ISR_GCAD (1 << 8) /* general call address detected */ -#define ISR_SAD (1 << 9) /* slave address detected */ -#define ISR_BED (1 << 10) /* bus error no ACK/NAK */ - -struct pxa_i2c { - spinlock_t lock; - wait_queue_head_t wait; - struct i2c_msg *msg; - unsigned int msg_num; - unsigned int msg_idx; - unsigned int msg_ptr; - unsigned int slave_addr; - - struct i2c_adapter adap; - struct clk *clk; -#ifdef CONFIG_I2C_PXA_SLAVE - struct i2c_slave_client *slave; -#endif - - unsigned int irqlogidx; - u32 isrlog[32]; - u32 icrlog[32]; - - void __iomem *reg_base; - void __iomem *reg_ibmr; - void __iomem *reg_idbr; - void __iomem *reg_icr; - void __iomem *reg_isr; - void __iomem *reg_isar; - - unsigned long iobase; - unsigned long iosize; - - int irq; - unsigned int use_pio :1; - unsigned int fast_mode :1; -}; - -#define _IBMR(i2c) ((i2c)->reg_ibmr) -#define _IDBR(i2c) ((i2c)->reg_idbr) -#define _ICR(i2c) ((i2c)->reg_icr) -#define _ISR(i2c) ((i2c)->reg_isr) -#define _ISAR(i2c) ((i2c)->reg_isar) - -/* - * I2C Slave mode address - */ -#define I2C_PXA_SLAVE_ADDR 0x1 - -#ifdef DEBUG - -struct bits { - u32 mask; - const char *set; - const char *unset; -}; -#define PXA_BIT(m, s, u) { .mask = m, .set = s, .unset = u } - -static inline void -decode_bits(const char *prefix, const struct bits *bits, int num, u32 val) -{ - printk("%s %08x: ", prefix, val); - while (num--) { - const char *str = val & bits->mask ? bits->set : bits->unset; - if (str) - printk("%s ", str); - bits++; - } -} - -static const struct bits isr_bits[] = { - PXA_BIT(ISR_RWM, "RX", "TX"), - PXA_BIT(ISR_ACKNAK, "NAK", "ACK"), - PXA_BIT(ISR_UB, "Bsy", "Rdy"), - PXA_BIT(ISR_IBB, "BusBsy", "BusRdy"), - PXA_BIT(ISR_SSD, "SlaveStop", NULL), - PXA_BIT(ISR_ALD, "ALD", NULL), - PXA_BIT(ISR_ITE, "TxEmpty", NULL), - PXA_BIT(ISR_IRF, "RxFull", NULL), - PXA_BIT(ISR_GCAD, "GenCall", NULL), - PXA_BIT(ISR_SAD, "SlaveAddr", NULL), - PXA_BIT(ISR_BED, "BusErr", NULL), -}; - -static void decode_ISR(unsigned int val) -{ - decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val); - printk("\n"); -} - -static const struct bits icr_bits[] = { - PXA_BIT(ICR_START, "START", NULL), - PXA_BIT(ICR_STOP, "STOP", NULL), - PXA_BIT(ICR_ACKNAK, "ACKNAK", NULL), - PXA_BIT(ICR_TB, "TB", NULL), - PXA_BIT(ICR_MA, "MA", NULL), - PXA_BIT(ICR_SCLE, "SCLE", "scle"), - PXA_BIT(ICR_IUE, "IUE", "iue"), - PXA_BIT(ICR_GCD, "GCD", NULL), - PXA_BIT(ICR_ITEIE, "ITEIE", NULL), - PXA_BIT(ICR_IRFIE, "IRFIE", NULL), - PXA_BIT(ICR_BEIE, "BEIE", NULL), - PXA_BIT(ICR_SSDIE, "SSDIE", NULL), - PXA_BIT(ICR_ALDIE, "ALDIE", NULL), - PXA_BIT(ICR_SADIE, "SADIE", NULL), - PXA_BIT(ICR_UR, "UR", "ur"), -}; - -#ifdef CONFIG_I2C_PXA_SLAVE -static void decode_ICR(unsigned int val) -{ - decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val); - printk("\n"); -} -#endif - -static unsigned int i2c_debug = DEBUG; - -static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) -{ - dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, - readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); -} - -#define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __func__) - -static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) -{ - unsigned int i; - printk(KERN_ERR "i2c: error: %s\n", why); - printk(KERN_ERR "i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", - i2c->msg_num, i2c->msg_idx, i2c->msg_ptr); - printk(KERN_ERR "i2c: ICR: %08x ISR: %08x\n", - readl(_ICR(i2c)), readl(_ISR(i2c))); - printk(KERN_DEBUG "i2c: log: "); - for (i = 0; i < i2c->irqlogidx; i++) - printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); - printk("\n"); -} - -#else /* ifdef DEBUG */ - -#define i2c_debug 0 - -#define show_state(i2c) do { } while (0) -#define decode_ISR(val) do { } while (0) -#define decode_ICR(val) do { } while (0) -#define i2c_pxa_scream_blue_murder(i2c, why) do { } while (0) - -#endif /* ifdef DEBUG / else */ - -static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); -static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id); - -static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) -{ - return !(readl(_ICR(i2c)) & ICR_SCLE); -} - -static void i2c_pxa_abort(struct pxa_i2c *i2c) -{ - int i = 250; - - if (i2c_pxa_is_slavemode(i2c)) { - dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); - return; - } - - while ((i > 0) && (readl(_IBMR(i2c)) & 0x1) == 0) { - unsigned long icr = readl(_ICR(i2c)); - - icr &= ~ICR_START; - icr |= ICR_ACKNAK | ICR_STOP | ICR_TB; - - writel(icr, _ICR(i2c)); - - show_state(i2c); - - mdelay(1); - i --; - } - - writel(readl(_ICR(i2c)) & ~(ICR_MA | ICR_START | ICR_STOP), - _ICR(i2c)); -} - -static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) -{ - int timeout = DEF_TIMEOUT; - - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { - if ((readl(_ISR(i2c)) & ISR_SAD) != 0) - timeout += 4; - - msleep(2); - show_state(i2c); - } - - if (timeout < 0) - show_state(i2c); - - return timeout < 0 ? I2C_RETRY : 0; -} - -static int i2c_pxa_wait_master(struct pxa_i2c *i2c) -{ - unsigned long timeout = jiffies + HZ*4; - - while (time_before(jiffies, timeout)) { - if (i2c_debug > 1) - dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", - __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); - - if (readl(_ISR(i2c)) & ISR_SAD) { - if (i2c_debug > 0) - dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__); - goto out; - } - - /* wait for unit and bus being not busy, and we also do a - * quick check of the i2c lines themselves to ensure they've - * gone high... - */ - if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) == 0 && readl(_IBMR(i2c)) == 3) { - if (i2c_debug > 0) - dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); - return 1; - } - - msleep(1); - } - - if (i2c_debug > 0) - dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); - out: - return 0; -} - -static int i2c_pxa_set_master(struct pxa_i2c *i2c) -{ - if (i2c_debug) - dev_dbg(&i2c->adap.dev, "setting to bus master\n"); - - if ((readl(_ISR(i2c)) & (ISR_UB | ISR_IBB)) != 0) { - dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__); - if (!i2c_pxa_wait_master(i2c)) { - dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__); - return I2C_RETRY; - } - } - - writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); - return 0; -} - -#ifdef CONFIG_I2C_PXA_SLAVE -static int i2c_pxa_wait_slave(struct pxa_i2c *i2c) -{ - unsigned long timeout = jiffies + HZ*1; - - /* wait for stop */ - - show_state(i2c); - - while (time_before(jiffies, timeout)) { - if (i2c_debug > 1) - dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", - __func__, (long)jiffies, readl(_ISR(i2c)), readl(_ICR(i2c)), readl(_IBMR(i2c))); - - if ((readl(_ISR(i2c)) & (ISR_UB|ISR_IBB)) == 0 || - (readl(_ISR(i2c)) & ISR_SAD) != 0 || - (readl(_ICR(i2c)) & ICR_SCLE) == 0) { - if (i2c_debug > 1) - dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); - return 1; - } - - msleep(1); - } - - if (i2c_debug > 0) - dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); - return 0; -} - -/* - * clear the hold on the bus, and take of anything else - * that has been configured - */ -static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode) -{ - show_state(i2c); - - if (errcode < 0) { - udelay(100); /* simple delay */ - } else { - /* we need to wait for the stop condition to end */ - - /* if we where in stop, then clear... */ - if (readl(_ICR(i2c)) & ICR_STOP) { - udelay(100); - writel(readl(_ICR(i2c)) & ~ICR_STOP, _ICR(i2c)); - } - - if (!i2c_pxa_wait_slave(i2c)) { - dev_err(&i2c->adap.dev, "%s: wait timedout\n", - __func__); - return; - } - } - - writel(readl(_ICR(i2c)) & ~(ICR_STOP|ICR_ACKNAK|ICR_MA), _ICR(i2c)); - writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); - - if (i2c_debug) { - dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", readl(_ICR(i2c)), readl(_ISR(i2c))); - decode_ICR(readl(_ICR(i2c))); - } -} -#else -#define i2c_pxa_set_slave(i2c, err) do { } while (0) -#endif - -static void i2c_pxa_reset(struct pxa_i2c *i2c) -{ - pr_debug("Resetting I2C Controller Unit\n"); - - /* abort any transfer currently under way */ - i2c_pxa_abort(i2c); - - /* reset according to 9.8 */ - writel(ICR_UR, _ICR(i2c)); - writel(I2C_ISR_INIT, _ISR(i2c)); - writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c)); - - if (i2c->reg_isar) - writel(i2c->slave_addr, _ISAR(i2c)); - - /* set control register values */ - writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); - -#ifdef CONFIG_I2C_PXA_SLAVE - dev_info(&i2c->adap.dev, "Enabling slave mode\n"); - writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c)); -#endif - - i2c_pxa_set_slave(i2c, 0); - - /* enable unit */ - writel(readl(_ICR(i2c)) | ICR_IUE, _ICR(i2c)); - udelay(100); -} - - -#ifdef CONFIG_I2C_PXA_SLAVE -/* - * PXA I2C Slave mode - */ - -static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) -{ - if (isr & ISR_BED) { - /* what should we do here? */ - } else { - int ret = 0; - - if (i2c->slave != NULL) - ret = i2c->slave->read(i2c->slave->data); - - writel(ret, _IDBR(i2c)); - writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); /* allow next byte */ - } -} - -static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) -{ - unsigned int byte = readl(_IDBR(i2c)); - - if (i2c->slave != NULL) - i2c->slave->write(i2c->slave->data, byte); - - writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); -} - -static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) -{ - int timeout; - - if (i2c_debug > 0) - dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n", - (isr & ISR_RWM) ? 'r' : 't'); - - if (i2c->slave != NULL) - i2c->slave->event(i2c->slave->data, - (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE); - - /* - * slave could interrupt in the middle of us generating a - * start condition... if this happens, we'd better back off - * and stop holding the poor thing up - */ - writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c)); - writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); - - timeout = 0x10000; - - while (1) { - if ((readl(_IBMR(i2c)) & 2) == 2) - break; - - timeout--; - - if (timeout <= 0) { - dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); - break; - } - } - - writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); -} - -static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) -{ - if (i2c_debug > 2) - dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n"); - - if (i2c->slave != NULL) - i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP); - - if (i2c_debug > 2) - dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n"); - - /* - * If we have a master-mode message waiting, - * kick it off now that the slave has completed. - */ - if (i2c->msg) - i2c_pxa_master_complete(i2c, I2C_RETRY); -} -#else -static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) -{ - if (isr & ISR_BED) { - /* what should we do here? */ - } else { - writel(0, _IDBR(i2c)); - writel(readl(_ICR(i2c)) | ICR_TB, _ICR(i2c)); - } -} - -static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) -{ - writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c)); -} - -static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) -{ - int timeout; - - /* - * slave could interrupt in the middle of us generating a - * start condition... if this happens, we'd better back off - * and stop holding the poor thing up - */ - writel(readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP), _ICR(i2c)); - writel(readl(_ICR(i2c)) | ICR_TB | ICR_ACKNAK, _ICR(i2c)); - - timeout = 0x10000; - - while (1) { - if ((readl(_IBMR(i2c)) & 2) == 2) - break; - - timeout--; - - if (timeout <= 0) { - dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); - break; - } - } - - writel(readl(_ICR(i2c)) & ~ICR_SCLE, _ICR(i2c)); -} - -static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) -{ - if (i2c->msg) - i2c_pxa_master_complete(i2c, I2C_RETRY); -} -#endif - -/* - * PXA I2C Master mode - */ - -static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - - if (msg->flags & I2C_M_RD) - addr |= 1; - - return addr; -} - -static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) -{ - u32 icr; - - /* - * Step 1: target slave address into IDBR - */ - writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); - - /* - * Step 2: initiate the write. - */ - icr = readl(_ICR(i2c)) & ~(ICR_STOP | ICR_ALDIE); - writel(icr | ICR_START | ICR_TB, _ICR(i2c)); -} - -static inline void i2c_pxa_stop_message(struct pxa_i2c *i2c) -{ - u32 icr; - - /* - * Clear the STOP and ACK flags - */ - icr = readl(_ICR(i2c)); - icr &= ~(ICR_STOP | ICR_ACKNAK); - writel(icr, _ICR(i2c)); -} - -static int i2c_pxa_pio_set_master(struct pxa_i2c *i2c) -{ - /* make timeout the same as for interrupt based functions */ - long timeout = 2 * DEF_TIMEOUT; - - /* - * Wait for the bus to become free. - */ - while (timeout-- && readl(_ISR(i2c)) & (ISR_IBB | ISR_UB)) { - udelay(1000); - show_state(i2c); - } - - if (timeout < 0) { - show_state(i2c); - dev_err(&i2c->adap.dev, - "i2c_pxa: timeout waiting for bus free\n"); - return I2C_RETRY; - } - - /* - * Set master mode. - */ - writel(readl(_ICR(i2c)) | ICR_SCLE, _ICR(i2c)); - - return 0; -} - -static int i2c_pxa_do_pio_xfer(struct pxa_i2c *i2c, - struct i2c_msg *msg, int num) -{ - unsigned long timeout = 500000; /* 5 seconds */ - int ret = 0; - - ret = i2c_pxa_pio_set_master(i2c); - if (ret) - goto out; - - i2c->msg = msg; - i2c->msg_num = num; - i2c->msg_idx = 0; - i2c->msg_ptr = 0; - i2c->irqlogidx = 0; - - i2c_pxa_start_message(i2c); - - while (i2c->msg_num > 0 && --timeout) { - i2c_pxa_handler(0, i2c); - udelay(10); - } - - i2c_pxa_stop_message(i2c); - - /* - * We place the return code in i2c->msg_idx. - */ - ret = i2c->msg_idx; - -out: - if (timeout == 0) - i2c_pxa_scream_blue_murder(i2c, "timeout"); - - return ret; -} - -/* - * We are protected by the adapter bus mutex. - */ -static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) -{ - long timeout; - int ret; - - /* - * Wait for the bus to become free. - */ - ret = i2c_pxa_wait_bus_not_busy(i2c); - if (ret) { - dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); - goto out; - } - - /* - * Set master mode. - */ - ret = i2c_pxa_set_master(i2c); - if (ret) { - dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret); - goto out; - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msg; - i2c->msg_num = num; - i2c->msg_idx = 0; - i2c->msg_ptr = 0; - i2c->irqlogidx = 0; - - i2c_pxa_start_message(i2c); - - spin_unlock_irq(&i2c->lock); - - /* - * The rest of the processing occurs in the interrupt handler. - */ - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); - i2c_pxa_stop_message(i2c); - - /* - * We place the return code in i2c->msg_idx. - */ - ret = i2c->msg_idx; - - if (!timeout && i2c->msg_num) { - i2c_pxa_scream_blue_murder(i2c, "timeout"); - ret = I2C_RETRY; - } - - out: - return ret; -} - -static int i2c_pxa_pio_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) -{ - struct pxa_i2c *i2c = adap->algo_data; - int ret, i; - - /* If the I2C controller is disabled we need to reset it - (probably due to a suspend/resume destroying state). We do - this here as we can then avoid worrying about resuming the - controller before its users. */ - if (!(readl(_ICR(i2c)) & ICR_IUE)) - i2c_pxa_reset(i2c); - - for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_pio_xfer(i2c, msgs, num); - if (ret != I2C_RETRY) - goto out; - - if (i2c_debug) - dev_dbg(&adap->dev, "Retrying transmission\n"); - udelay(100); - } - i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); - ret = -EREMOTEIO; - out: - i2c_pxa_set_slave(i2c, ret); - return ret; -} - -/* - * i2c_pxa_master_complete - complete the message and wake up. - */ -static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret) -{ - i2c->msg_ptr = 0; - i2c->msg = NULL; - i2c->msg_idx ++; - i2c->msg_num = 0; - if (ret) - i2c->msg_idx = ret; - if (!i2c->use_pio) - wake_up(&i2c->wait); -} - -static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) -{ - u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); - - again: - /* - * If ISR_ALD is set, we lost arbitration. - */ - if (isr & ISR_ALD) { - /* - * Do we need to do anything here? The PXA docs - * are vague about what happens. - */ - i2c_pxa_scream_blue_murder(i2c, "ALD set"); - - /* - * We ignore this error. We seem to see spurious ALDs - * for seemingly no reason. If we handle them as I think - * they should, we end up causing an I2C error, which - * is painful for some systems. - */ - return; /* ignore */ - } - - if (isr & ISR_BED) { - int ret = BUS_ERROR; - - /* - * I2C bus error - either the device NAK'd us, or - * something more serious happened. If we were NAK'd - * on the initial address phase, we can retry. - */ - if (isr & ISR_ACKNAK) { - if (i2c->msg_ptr == 0 && i2c->msg_idx == 0) - ret = I2C_RETRY; - else - ret = XFER_NAKED; - } - i2c_pxa_master_complete(i2c, ret); - } else if (isr & ISR_RWM) { - /* - * Read mode. We have just sent the address byte, and - * now we must initiate the transfer. - */ - if (i2c->msg_ptr == i2c->msg->len - 1 && - i2c->msg_idx == i2c->msg_num - 1) - icr |= ICR_STOP | ICR_ACKNAK; - - icr |= ICR_ALDIE | ICR_TB; - } else if (i2c->msg_ptr < i2c->msg->len) { - /* - * Write mode. Write the next data byte. - */ - writel(i2c->msg->buf[i2c->msg_ptr++], _IDBR(i2c)); - - icr |= ICR_ALDIE | ICR_TB; - - /* - * If this is the last byte of the last message, send - * a STOP. - */ - if (i2c->msg_ptr == i2c->msg->len && - i2c->msg_idx == i2c->msg_num - 1) - icr |= ICR_STOP; - } else if (i2c->msg_idx < i2c->msg_num - 1) { - /* - * Next segment of the message. - */ - i2c->msg_ptr = 0; - i2c->msg_idx ++; - i2c->msg++; - - /* - * If we aren't doing a repeated start and address, - * go back and try to send the next byte. Note that - * we do not support switching the R/W direction here. - */ - if (i2c->msg->flags & I2C_M_NOSTART) - goto again; - - /* - * Write the next address. - */ - writel(i2c_pxa_addr_byte(i2c->msg), _IDBR(i2c)); - - /* - * And trigger a repeated start, and send the byte. - */ - icr &= ~ICR_ALDIE; - icr |= ICR_START | ICR_TB; - } else { - if (i2c->msg->len == 0) { - /* - * Device probes have a message length of zero - * and need the bus to be reset before it can - * be used again. - */ - i2c_pxa_reset(i2c); - } - i2c_pxa_master_complete(i2c, 0); - } - - i2c->icrlog[i2c->irqlogidx-1] = icr; - - writel(icr, _ICR(i2c)); - show_state(i2c); -} - -static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr) -{ - u32 icr = readl(_ICR(i2c)) & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); - - /* - * Read the byte. - */ - i2c->msg->buf[i2c->msg_ptr++] = readl(_IDBR(i2c)); - - if (i2c->msg_ptr < i2c->msg->len) { - /* - * If this is the last byte of the last - * message, send a STOP. - */ - if (i2c->msg_ptr == i2c->msg->len - 1) - icr |= ICR_STOP | ICR_ACKNAK; - - icr |= ICR_ALDIE | ICR_TB; - } else { - i2c_pxa_master_complete(i2c, 0); - } - - i2c->icrlog[i2c->irqlogidx-1] = icr; - - writel(icr, _ICR(i2c)); -} - -#define VALID_INT_SOURCE (ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \ - ISR_SAD | ISR_BED) -static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id) -{ - struct pxa_i2c *i2c = dev_id; - u32 isr = readl(_ISR(i2c)); - - if (!(isr & VALID_INT_SOURCE)) - return IRQ_NONE; - - if (i2c_debug > 2 && 0) { - dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", - __func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c))); - decode_ISR(isr); - } - - if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog)) - i2c->isrlog[i2c->irqlogidx++] = isr; - - show_state(i2c); - - /* - * Always clear all pending IRQs. - */ - writel(isr & VALID_INT_SOURCE, _ISR(i2c)); - - if (isr & ISR_SAD) - i2c_pxa_slave_start(i2c, isr); - if (isr & ISR_SSD) - i2c_pxa_slave_stop(i2c); - - if (i2c_pxa_is_slavemode(i2c)) { - if (isr & ISR_ITE) - i2c_pxa_slave_txempty(i2c, isr); - if (isr & ISR_IRF) - i2c_pxa_slave_rxfull(i2c, isr); - } else if (i2c->msg) { - if (isr & ISR_ITE) - i2c_pxa_irq_txempty(i2c, isr); - if (isr & ISR_IRF) - i2c_pxa_irq_rxfull(i2c, isr); - } else { - i2c_pxa_scream_blue_murder(i2c, "spurious irq"); - } - - return IRQ_HANDLED; -} - - -static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) -{ - struct pxa_i2c *i2c = adap->algo_data; - int ret, i; - - for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_xfer(i2c, msgs, num); - if (ret != I2C_RETRY) - goto out; - - if (i2c_debug) - dev_dbg(&adap->dev, "Retrying transmission\n"); - udelay(100); - } - i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); - ret = -EREMOTEIO; - out: - i2c_pxa_set_slave(i2c, ret); - return ret; -} - -static u32 i2c_pxa_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm i2c_pxa_algorithm = { - .master_xfer = i2c_pxa_xfer, - .functionality = i2c_pxa_functionality, -}; - -static const struct i2c_algorithm i2c_pxa_pio_algorithm = { - .master_xfer = i2c_pxa_pio_xfer, - .functionality = i2c_pxa_functionality, -}; - -static struct of_device_id i2c_pxa_dt_ids[] = { - { .compatible = "mrvl,pxa-i2c", .data = (void *)REGS_PXA2XX }, - { .compatible = "mrvl,pwri2c", .data = (void *)REGS_PXA3XX }, - { .compatible = "mrvl,mmp-twsi", .data = (void *)REGS_PXA2XX }, - {} -}; -MODULE_DEVICE_TABLE(of, i2c_pxa_dt_ids); - -static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, - enum pxa_i2c_types *i2c_types) -{ - struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id = - of_match_device(i2c_pxa_dt_ids, &pdev->dev); - int ret; - - if (!of_id) - return 1; - ret = of_alias_get_id(np, "i2c"); - if (ret < 0) { - dev_err(&pdev->dev, "failed to get alias id, errno %d\n", ret); - return ret; - } - pdev->id = ret; - if (of_get_property(np, "mrvl,i2c-polling", NULL)) - i2c->use_pio = 1; - if (of_get_property(np, "mrvl,i2c-fast-mode", NULL)) - i2c->fast_mode = 1; - *i2c_types = (u32)(of_id->data); - return 0; -} - -static int i2c_pxa_probe_pdata(struct platform_device *pdev, - struct pxa_i2c *i2c, - enum pxa_i2c_types *i2c_types) -{ - struct i2c_pxa_platform_data *plat = pdev->dev.platform_data; - const struct platform_device_id *id = platform_get_device_id(pdev); - - *i2c_types = id->driver_data; - if (plat) { - i2c->use_pio = plat->use_pio; - i2c->fast_mode = plat->fast_mode; - } - return 0; -} - -static int i2c_pxa_probe(struct platform_device *dev) -{ - struct i2c_pxa_platform_data *plat = dev->dev.platform_data; - enum pxa_i2c_types i2c_type; - struct pxa_i2c *i2c; - struct resource *res = NULL; - int ret, irq; - - i2c = kzalloc(sizeof(struct pxa_i2c), GFP_KERNEL); - if (!i2c) { - ret = -ENOMEM; - goto emalloc; - } - - ret = i2c_pxa_probe_dt(dev, i2c, &i2c_type); - if (ret > 0) - ret = i2c_pxa_probe_pdata(dev, i2c, &i2c_type); - if (ret < 0) - goto eclk; - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - irq = platform_get_irq(dev, 0); - if (res == NULL || irq < 0) { - ret = -ENODEV; - goto eclk; - } - - if (!request_mem_region(res->start, resource_size(res), res->name)) { - ret = -ENOMEM; - goto eclk; - } - - i2c->adap.owner = THIS_MODULE; - i2c->adap.retries = 5; - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - - /* - * If "dev->id" is negative we consider it as zero. - * The reason to do so is to avoid sysfs names that only make - * sense when there are multiple adapters. - */ - i2c->adap.nr = dev->id; - snprintf(i2c->adap.name, sizeof(i2c->adap.name), "pxa_i2c-i2c.%u", - i2c->adap.nr); - - i2c->clk = clk_get(&dev->dev, NULL); - if (IS_ERR(i2c->clk)) { - ret = PTR_ERR(i2c->clk); - goto eclk; - } - - i2c->reg_base = ioremap(res->start, resource_size(res)); - if (!i2c->reg_base) { - ret = -EIO; - goto eremap; - } - - i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr; - i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr; - i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr; - i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr; - if (i2c_type != REGS_CE4100) - i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar; - - i2c->iobase = res->start; - i2c->iosize = resource_size(res); - - i2c->irq = irq; - - i2c->slave_addr = I2C_PXA_SLAVE_ADDR; - - if (plat) { -#ifdef CONFIG_I2C_PXA_SLAVE - i2c->slave_addr = plat->slave_addr; - i2c->slave = plat->slave; -#endif - i2c->adap.class = plat->class; - } - - clk_enable(i2c->clk); - - if (i2c->use_pio) { - i2c->adap.algo = &i2c_pxa_pio_algorithm; - } else { - i2c->adap.algo = &i2c_pxa_algorithm; - ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED, - i2c->adap.name, i2c); - if (ret) - goto ereqirq; - } - - i2c_pxa_reset(i2c); - - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &dev->dev; -#ifdef CONFIG_OF - i2c->adap.dev.of_node = dev->dev.of_node; -#endif - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - printk(KERN_INFO "I2C: Failed to add bus\n"); - goto eadapt; - } - of_i2c_register_devices(&i2c->adap); - - platform_set_drvdata(dev, i2c); - -#ifdef CONFIG_I2C_PXA_SLAVE - printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", - dev_name(&i2c->adap.dev), i2c->slave_addr); -#else - printk(KERN_INFO "I2C: %s: PXA I2C adapter\n", - dev_name(&i2c->adap.dev)); -#endif - return 0; - -eadapt: - if (!i2c->use_pio) - free_irq(irq, i2c); -ereqirq: - clk_disable(i2c->clk); - iounmap(i2c->reg_base); -eremap: - clk_put(i2c->clk); -eclk: - kfree(i2c); -emalloc: - release_mem_region(res->start, resource_size(res)); - return ret; -} - -static int __exit i2c_pxa_remove(struct platform_device *dev) -{ - struct pxa_i2c *i2c = platform_get_drvdata(dev); - - platform_set_drvdata(dev, NULL); - - i2c_del_adapter(&i2c->adap); - if (!i2c->use_pio) - free_irq(i2c->irq, i2c); - - clk_disable(i2c->clk); - clk_put(i2c->clk); - - iounmap(i2c->reg_base); - release_mem_region(i2c->iobase, i2c->iosize); - kfree(i2c); - - return 0; -} - -#ifdef CONFIG_PM -static int i2c_pxa_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pxa_i2c *i2c = platform_get_drvdata(pdev); - - clk_disable(i2c->clk); - - return 0; -} - -static int i2c_pxa_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pxa_i2c *i2c = platform_get_drvdata(pdev); - - clk_enable(i2c->clk); - i2c_pxa_reset(i2c); - - return 0; -} - -static const struct dev_pm_ops i2c_pxa_dev_pm_ops = { - .suspend_noirq = i2c_pxa_suspend_noirq, - .resume_noirq = i2c_pxa_resume_noirq, -}; - -#define I2C_PXA_DEV_PM_OPS (&i2c_pxa_dev_pm_ops) -#else -#define I2C_PXA_DEV_PM_OPS NULL -#endif - -static struct platform_driver i2c_pxa_driver = { - .probe = i2c_pxa_probe, - .remove = __exit_p(i2c_pxa_remove), - .driver = { - .name = "pxa2xx-i2c", - .owner = THIS_MODULE, - .pm = I2C_PXA_DEV_PM_OPS, - .of_match_table = i2c_pxa_dt_ids, - }, - .id_table = i2c_pxa_id_table, -}; - -static int __init i2c_adap_pxa_init(void) -{ - return platform_driver_register(&i2c_pxa_driver); -} - -static void __exit i2c_adap_pxa_exit(void) -{ - platform_driver_unregister(&i2c_pxa_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:pxa2xx-i2c"); - -subsys_initcall(i2c_adap_pxa_init); -module_exit(i2c_adap_pxa_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s3c2410.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-s3c2410.c deleted file mode 100644 index 737f7218..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s3c2410.c +++ /dev/null @@ -1,1161 +0,0 @@ -/* linux/drivers/i2c/busses/i2c-s3c2410.c - * - * Copyright (C) 2004,2005,2009 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * S3C2410 I2C Controller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/time.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/platform_device.h> -#include <linux/pm_runtime.h> -#include <linux/clk.h> -#include <linux/cpufreq.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/of_i2c.h> -#include <linux/of_gpio.h> - -#include <asm/irq.h> - -#include <plat/regs-iic.h> -#include <plat/iic.h> - -/* i2c controller state */ - -enum s3c24xx_i2c_state { - STATE_IDLE, - STATE_START, - STATE_READ, - STATE_WRITE, - STATE_STOP -}; - -enum s3c24xx_i2c_type { - TYPE_S3C2410, - TYPE_S3C2440, -}; - -struct s3c24xx_i2c { - spinlock_t lock; - wait_queue_head_t wait; - unsigned int suspended:1; - - struct i2c_msg *msg; - unsigned int msg_num; - unsigned int msg_idx; - unsigned int msg_ptr; - - unsigned int tx_setup; - unsigned int irq; - - enum s3c24xx_i2c_state state; - unsigned long clkrate; - - void __iomem *regs; - struct clk *clk; - struct device *dev; - struct resource *ioarea; - struct i2c_adapter adap; - - struct s3c2410_platform_i2c *pdata; - int gpios[2]; -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; -#endif -}; - -/* default platform data removed, dev should always carry data. */ - -/* s3c24xx_i2c_is2440() - * - * return true is this is an s3c2440 -*/ - -static inline int s3c24xx_i2c_is2440(struct s3c24xx_i2c *i2c) -{ - struct platform_device *pdev = to_platform_device(i2c->dev); - enum s3c24xx_i2c_type type; - -#ifdef CONFIG_OF - if (i2c->dev->of_node) - return of_device_is_compatible(i2c->dev->of_node, - "samsung,s3c2440-i2c"); -#endif - - type = platform_get_device_id(pdev)->driver_data; - return type == TYPE_S3C2440; -} - -/* s3c24xx_i2c_master_complete - * - * complete the message and wake up the caller, using the given return code, - * or zero to mean ok. -*/ - -static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) -{ - dev_dbg(i2c->dev, "master_complete %d\n", ret); - - i2c->msg_ptr = 0; - i2c->msg = NULL; - i2c->msg_idx++; - i2c->msg_num = 0; - if (ret) - i2c->msg_idx = ret; - - wake_up(&i2c->wait); -} - -static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + S3C2410_IICCON); - writel(tmp & ~S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); -} - -static inline void s3c24xx_i2c_enable_ack(struct s3c24xx_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + S3C2410_IICCON); - writel(tmp | S3C2410_IICCON_ACKEN, i2c->regs + S3C2410_IICCON); -} - -/* irq enable/disable functions */ - -static inline void s3c24xx_i2c_disable_irq(struct s3c24xx_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + S3C2410_IICCON); - writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); -} - -static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + S3C2410_IICCON); - writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); -} - - -/* s3c24xx_i2c_message_start - * - * put the start of a message onto the bus -*/ - -static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, - struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - unsigned long stat; - unsigned long iiccon; - - stat = 0; - stat |= S3C2410_IICSTAT_TXRXEN; - - if (msg->flags & I2C_M_RD) { - stat |= S3C2410_IICSTAT_MASTER_RX; - addr |= 1; - } else - stat |= S3C2410_IICSTAT_MASTER_TX; - - if (msg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - - /* todo - check for wether ack wanted or not */ - s3c24xx_i2c_enable_ack(i2c); - - iiccon = readl(i2c->regs + S3C2410_IICCON); - writel(stat, i2c->regs + S3C2410_IICSTAT); - - dev_dbg(i2c->dev, "START: %08lx to IICSTAT, %02x to DS\n", stat, addr); - writeb(addr, i2c->regs + S3C2410_IICDS); - - /* delay here to ensure the data byte has gotten onto the bus - * before the transaction is started */ - - ndelay(i2c->tx_setup); - - dev_dbg(i2c->dev, "iiccon, %08lx\n", iiccon); - writel(iiccon, i2c->regs + S3C2410_IICCON); - - stat |= S3C2410_IICSTAT_START; - writel(stat, i2c->regs + S3C2410_IICSTAT); -} - -static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) -{ - unsigned long iicstat = readl(i2c->regs + S3C2410_IICSTAT); - - dev_dbg(i2c->dev, "STOP\n"); - - /* stop the transfer */ - iicstat &= ~S3C2410_IICSTAT_START; - writel(iicstat, i2c->regs + S3C2410_IICSTAT); - - i2c->state = STATE_STOP; - - s3c24xx_i2c_master_complete(i2c, ret); - s3c24xx_i2c_disable_irq(i2c); -} - -/* helper functions to determine the current state in the set of - * messages we are sending */ - -/* is_lastmsg() - * - * returns TRUE if the current message is the last in the set -*/ - -static inline int is_lastmsg(struct s3c24xx_i2c *i2c) -{ - return i2c->msg_idx >= (i2c->msg_num - 1); -} - -/* is_msglast - * - * returns TRUE if we this is the last byte in the current message -*/ - -static inline int is_msglast(struct s3c24xx_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len-1; -} - -/* is_msgend - * - * returns TRUE if we reached the end of the current message -*/ - -static inline int is_msgend(struct s3c24xx_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -/* i2c_s3c_irq_nextbyte - * - * process an interrupt and work out what to do - */ - -static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat) -{ - unsigned long tmp; - unsigned char byte; - int ret = 0; - - switch (i2c->state) { - - case STATE_IDLE: - dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); - goto out; - - case STATE_STOP: - dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); - s3c24xx_i2c_disable_irq(i2c); - goto out_ack; - - case STATE_START: - /* last thing we did was send a start condition on the - * bus, or started a new i2c message - */ - - if (iicstat & S3C2410_IICSTAT_LASTBIT && - !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - /* ack was not received... */ - - dev_dbg(i2c->dev, "ack was not received\n"); - s3c24xx_i2c_stop(i2c, -ENXIO); - goto out_ack; - } - - if (i2c->msg->flags & I2C_M_RD) - i2c->state = STATE_READ; - else - i2c->state = STATE_WRITE; - - /* terminate the transfer if there is nothing to do - * as this is used by the i2c probe to find devices. */ - - if (is_lastmsg(i2c) && i2c->msg->len == 0) { - s3c24xx_i2c_stop(i2c, 0); - goto out_ack; - } - - if (i2c->state == STATE_READ) - goto prepare_read; - - /* fall through to the write state, as we will need to - * send a byte as well */ - - case STATE_WRITE: - /* we are writing data to the device... check for the - * end of the message, and if so, work out what to do - */ - - if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - if (iicstat & S3C2410_IICSTAT_LASTBIT) { - dev_dbg(i2c->dev, "WRITE: No Ack\n"); - - s3c24xx_i2c_stop(i2c, -ECONNREFUSED); - goto out_ack; - } - } - - retry_write: - - if (!is_msgend(i2c)) { - byte = i2c->msg->buf[i2c->msg_ptr++]; - writeb(byte, i2c->regs + S3C2410_IICDS); - - /* delay after writing the byte to allow the - * data setup time on the bus, as writing the - * data to the register causes the first bit - * to appear on SDA, and SCL will change as - * soon as the interrupt is acknowledged */ - - ndelay(i2c->tx_setup); - - } else if (!is_lastmsg(i2c)) { - /* we need to go to the next i2c message */ - - dev_dbg(i2c->dev, "WRITE: Next Message\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - /* check to see if we need to do another message */ - if (i2c->msg->flags & I2C_M_NOSTART) { - - if (i2c->msg->flags & I2C_M_RD) { - /* cannot do this, the controller - * forces us to send a new START - * when we change direction */ - - s3c24xx_i2c_stop(i2c, -EINVAL); - } - - goto retry_write; - } else { - /* send the new start */ - s3c24xx_i2c_message_start(i2c, i2c->msg); - i2c->state = STATE_START; - } - - } else { - /* send stop */ - - s3c24xx_i2c_stop(i2c, 0); - } - break; - - case STATE_READ: - /* we have a byte of data in the data register, do - * something with it, and then work out wether we are - * going to do any more read/write - */ - - byte = readb(i2c->regs + S3C2410_IICDS); - i2c->msg->buf[i2c->msg_ptr++] = byte; - - prepare_read: - if (is_msglast(i2c)) { - /* last byte of buffer */ - - if (is_lastmsg(i2c)) - s3c24xx_i2c_disable_ack(i2c); - - } else if (is_msgend(i2c)) { - /* ok, we've read the entire buffer, see if there - * is anything else we need to do */ - - if (is_lastmsg(i2c)) { - /* last message, send stop and complete */ - dev_dbg(i2c->dev, "READ: Send Stop\n"); - - s3c24xx_i2c_stop(i2c, 0); - } else { - /* go to the next transfer */ - dev_dbg(i2c->dev, "READ: Next Transfer\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - } - } - - break; - } - - /* acknowlegde the IRQ and get back on with the work */ - - out_ack: - tmp = readl(i2c->regs + S3C2410_IICCON); - tmp &= ~S3C2410_IICCON_IRQPEND; - writel(tmp, i2c->regs + S3C2410_IICCON); - out: - return ret; -} - -/* s3c24xx_i2c_irq - * - * top level IRQ servicing routine -*/ - -static irqreturn_t s3c24xx_i2c_irq(int irqno, void *dev_id) -{ - struct s3c24xx_i2c *i2c = dev_id; - unsigned long status; - unsigned long tmp; - - status = readl(i2c->regs + S3C2410_IICSTAT); - - if (status & S3C2410_IICSTAT_ARBITR) { - /* deal with arbitration loss */ - dev_err(i2c->dev, "deal with arbitration loss\n"); - } - - if (i2c->state == STATE_IDLE) { - dev_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); - - tmp = readl(i2c->regs + S3C2410_IICCON); - tmp &= ~S3C2410_IICCON_IRQPEND; - writel(tmp, i2c->regs + S3C2410_IICCON); - goto out; - } - - /* pretty much this leaves us with the fact that we've - * transmitted or received whatever byte we last sent */ - - i2c_s3c_irq_nextbyte(i2c, status); - - out: - return IRQ_HANDLED; -} - - -/* s3c24xx_i2c_set_master - * - * get the i2c bus for a master transaction -*/ - -static int s3c24xx_i2c_set_master(struct s3c24xx_i2c *i2c) -{ - unsigned long iicstat; - int timeout = 400; - - while (timeout-- > 0) { - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - - if (!(iicstat & S3C2410_IICSTAT_BUSBUSY)) - return 0; - - msleep(1); - } - - return -ETIMEDOUT; -} - -/* s3c24xx_i2c_doxfer - * - * this starts an i2c transfer -*/ - -static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long iicstat, timeout; - int spins = 20; - int ret; - - if (i2c->suspended) - return -EIO; - - ret = s3c24xx_i2c_set_master(i2c); - if (ret != 0) { - dev_err(i2c->dev, "cannot get bus (error %d)\n", ret); - ret = -EAGAIN; - goto out; - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msgs; - i2c->msg_num = num; - i2c->msg_ptr = 0; - i2c->msg_idx = 0; - i2c->state = STATE_START; - - s3c24xx_i2c_enable_irq(i2c); - s3c24xx_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); - - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); - - ret = i2c->msg_idx; - - /* having these next two as dev_err() makes life very - * noisy when doing an i2cdetect */ - - if (timeout == 0) - dev_dbg(i2c->dev, "timeout\n"); - else if (ret != num) - dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); - - /* ensure the stop has been through the bus */ - - dev_dbg(i2c->dev, "waiting for bus idle\n"); - - /* first, try busy waiting briefly */ - do { - cpu_relax(); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } while ((iicstat & S3C2410_IICSTAT_START) && --spins); - - /* if that timed out sleep */ - if (!spins) { - msleep(1); - iicstat = readl(i2c->regs + S3C2410_IICSTAT); - } - - if (iicstat & S3C2410_IICSTAT_START) - dev_warn(i2c->dev, "timeout waiting for bus idle\n"); - - out: - return ret; -} - -/* s3c24xx_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int s3c24xx_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct s3c24xx_i2c *i2c = (struct s3c24xx_i2c *)adap->algo_data; - int retry; - int ret; - - pm_runtime_get_sync(&adap->dev); - clk_enable(i2c->clk); - - for (retry = 0; retry < adap->retries; retry++) { - - ret = s3c24xx_i2c_doxfer(i2c, msgs, num); - - if (ret != -EAGAIN) { - clk_disable(i2c->clk); - pm_runtime_put_sync(&adap->dev); - return ret; - } - - dev_dbg(i2c->dev, "Retrying transmission (%d)\n", retry); - - udelay(100); - } - - clk_disable(i2c->clk); - pm_runtime_put_sync(&adap->dev); - return -EREMOTEIO; -} - -/* declare our i2c functionality */ -static u32 s3c24xx_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm s3c24xx_i2c_algorithm = { - .master_xfer = s3c24xx_i2c_xfer, - .functionality = s3c24xx_i2c_func, -}; - -/* s3c24xx_i2c_calcdivisor - * - * return the divisor settings for a given frequency -*/ - -static int s3c24xx_i2c_calcdivisor(unsigned long clkin, unsigned int wanted, - unsigned int *div1, unsigned int *divs) -{ - unsigned int calc_divs = clkin / wanted; - unsigned int calc_div1; - - if (calc_divs > (16*16)) - calc_div1 = 512; - else - calc_div1 = 16; - - calc_divs += calc_div1-1; - calc_divs /= calc_div1; - - if (calc_divs == 0) - calc_divs = 1; - if (calc_divs > 17) - calc_divs = 17; - - *divs = calc_divs; - *div1 = calc_div1; - - return clkin / (calc_divs * calc_div1); -} - -/* s3c24xx_i2c_clockrate - * - * work out a divisor for the user requested frequency setting, - * either by the requested frequency, or scanning the acceptable - * range of frequencies until something is found -*/ - -static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) -{ - struct s3c2410_platform_i2c *pdata = i2c->pdata; - unsigned long clkin = clk_get_rate(i2c->clk); - unsigned int divs, div1; - unsigned long target_frequency; - u32 iiccon; - int freq; - - i2c->clkrate = clkin; - clkin /= 1000; /* clkin now in KHz */ - - dev_dbg(i2c->dev, "pdata desired frequency %lu\n", pdata->frequency); - - target_frequency = pdata->frequency ? pdata->frequency : 100000; - - target_frequency /= 1000; /* Target frequency now in KHz */ - - freq = s3c24xx_i2c_calcdivisor(clkin, target_frequency, &div1, &divs); - - if (freq > target_frequency) { - dev_err(i2c->dev, - "Unable to achieve desired frequency %luKHz." \ - " Lowest achievable %dKHz\n", target_frequency, freq); - return -EINVAL; - } - - *got = freq; - - iiccon = readl(i2c->regs + S3C2410_IICCON); - iiccon &= ~(S3C2410_IICCON_SCALEMASK | S3C2410_IICCON_TXDIV_512); - iiccon |= (divs-1); - - if (div1 == 512) - iiccon |= S3C2410_IICCON_TXDIV_512; - - writel(iiccon, i2c->regs + S3C2410_IICCON); - - if (s3c24xx_i2c_is2440(i2c)) { - unsigned long sda_delay; - - if (pdata->sda_delay) { - sda_delay = clkin * pdata->sda_delay; - sda_delay = DIV_ROUND_UP(sda_delay, 1000000); - sda_delay = DIV_ROUND_UP(sda_delay, 5); - if (sda_delay > 3) - sda_delay = 3; - sda_delay |= S3C2410_IICLC_FILTER_ON; - } else - sda_delay = 0; - - dev_dbg(i2c->dev, "IICLC=%08lx\n", sda_delay); - writel(sda_delay, i2c->regs + S3C2440_IICLC); - } - - return 0; -} - -#ifdef CONFIG_CPU_FREQ - -#define freq_to_i2c(_n) container_of(_n, struct s3c24xx_i2c, freq_transition) - -static int s3c24xx_i2c_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct s3c24xx_i2c *i2c = freq_to_i2c(nb); - unsigned long flags; - unsigned int got; - int delta_f; - int ret; - - delta_f = clk_get_rate(i2c->clk) - i2c->clkrate; - - /* if we're post-change and the input clock has slowed down - * or at pre-change and the clock is about to speed up, then - * adjust our clock rate. <0 is slow, >0 speedup. - */ - - if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || - (val == CPUFREQ_PRECHANGE && delta_f > 0)) { - spin_lock_irqsave(&i2c->lock, flags); - ret = s3c24xx_i2c_clockrate(i2c, &got); - spin_unlock_irqrestore(&i2c->lock, flags); - - if (ret < 0) - dev_err(i2c->dev, "cannot find frequency\n"); - else - dev_info(i2c->dev, "setting freq %d\n", got); - } - - return 0; -} - -static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) -{ - i2c->freq_transition.notifier_call = s3c24xx_i2c_cpufreq_transition; - - return cpufreq_register_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) -{ - cpufreq_unregister_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -#else -static inline int s3c24xx_i2c_register_cpufreq(struct s3c24xx_i2c *i2c) -{ - return 0; -} - -static inline void s3c24xx_i2c_deregister_cpufreq(struct s3c24xx_i2c *i2c) -{ -} -#endif - -#ifdef CONFIG_OF -static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) -{ - int idx, gpio, ret; - - for (idx = 0; idx < 2; idx++) { - gpio = of_get_gpio(i2c->dev->of_node, idx); - if (!gpio_is_valid(gpio)) { - dev_err(i2c->dev, "invalid gpio[%d]: %d\n", idx, gpio); - goto free_gpio; - } - - ret = gpio_request(gpio, "i2c-bus"); - if (ret) { - dev_err(i2c->dev, "gpio [%d] request failed\n", gpio); - goto free_gpio; - } - } - return 0; - -free_gpio: - while (--idx >= 0) - gpio_free(i2c->gpios[idx]); - return -EINVAL; -} - -static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) -{ - unsigned int idx; - for (idx = 0; idx < 2; idx++) - gpio_free(i2c->gpios[idx]); -} -#else -static int s3c24xx_i2c_parse_dt_gpio(struct s3c24xx_i2c *i2c) -{ - return 0; -} - -static void s3c24xx_i2c_dt_gpio_free(struct s3c24xx_i2c *i2c) -{ -} -#endif - -/* s3c24xx_i2c_init - * - * initialise the controller, set the IO lines and frequency -*/ - -static int s3c24xx_i2c_init(struct s3c24xx_i2c *i2c) -{ - unsigned long iicon = S3C2410_IICCON_IRQEN | S3C2410_IICCON_ACKEN; - struct s3c2410_platform_i2c *pdata; - unsigned int freq; - - /* get the plafrom data */ - - pdata = i2c->pdata; - - /* inititalise the gpio */ - - if (pdata->cfg_gpio) - pdata->cfg_gpio(to_platform_device(i2c->dev)); - else - if (s3c24xx_i2c_parse_dt_gpio(i2c)) - return -EINVAL; - - /* write slave address */ - - writeb(pdata->slave_addr, i2c->regs + S3C2410_IICADD); - - dev_info(i2c->dev, "slave address 0x%02x\n", pdata->slave_addr); - - writel(iicon, i2c->regs + S3C2410_IICCON); - - /* we need to work out the divisors for the clock... */ - - if (s3c24xx_i2c_clockrate(i2c, &freq) != 0) { - writel(0, i2c->regs + S3C2410_IICCON); - dev_err(i2c->dev, "cannot meet bus frequency required\n"); - return -EINVAL; - } - - /* todo - check that the i2c lines aren't being dragged anywhere */ - - dev_info(i2c->dev, "bus frequency set to %d KHz\n", freq); - dev_dbg(i2c->dev, "S3C2410_IICCON=0x%02lx\n", iicon); - - return 0; -} - -#ifdef CONFIG_OF -/* s3c24xx_i2c_parse_dt - * - * Parse the device tree node and retreive the platform data. -*/ - -static void -s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) -{ - struct s3c2410_platform_i2c *pdata = i2c->pdata; - - if (!np) - return; - - pdata->bus_num = -1; /* i2c bus number is dynamically assigned */ - of_property_read_u32(np, "samsung,i2c-sda-delay", &pdata->sda_delay); - of_property_read_u32(np, "samsung,i2c-slave-addr", &pdata->slave_addr); - of_property_read_u32(np, "samsung,i2c-max-bus-freq", - (u32 *)&pdata->frequency); -} -#else -static void -s3c24xx_i2c_parse_dt(struct device_node *np, struct s3c24xx_i2c *i2c) -{ - return; -} -#endif - -/* s3c24xx_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - -static int s3c24xx_i2c_probe(struct platform_device *pdev) -{ - struct s3c24xx_i2c *i2c; - struct s3c2410_platform_i2c *pdata = NULL; - struct resource *res; - int ret; - - if (!pdev->dev.of_node) { - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - } - - i2c = devm_kzalloc(&pdev->dev, sizeof(struct s3c24xx_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - - i2c->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); - if (!i2c->pdata) { - ret = -ENOMEM; - goto err_noclk; - } - - if (pdata) - memcpy(i2c->pdata, pdata, sizeof(*pdata)); - else - s3c24xx_i2c_parse_dt(pdev->dev.of_node, i2c); - - strlcpy(i2c->adap.name, "s3c2410-i2c", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &s3c24xx_i2c_algorithm; - i2c->adap.retries = 2; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - i2c->tx_setup = 50; - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - - /* find the clock and enable it */ - - i2c->dev = &pdev->dev; - i2c->clk = clk_get(&pdev->dev, "i2c"); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = -ENOENT; - goto err_noclk; - } - - dev_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - - clk_enable(i2c->clk); - - /* map the registers */ - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_clk; - } - - i2c->ioarea = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (i2c->ioarea == NULL) { - dev_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_clk; - } - - i2c->regs = ioremap(res->start, resource_size(res)); - - if (i2c->regs == NULL) { - dev_err(&pdev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_ioarea; - } - - dev_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); - - /* setup info block for the i2c core */ - - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &pdev->dev; - - /* initialise the i2c controller */ - - ret = s3c24xx_i2c_init(i2c); - if (ret != 0) - goto err_iomap; - - /* find the IRQ for this unit (note, this relies on the init call to - * ensure no current IRQs pending - */ - - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - goto err_iomap; - } - - ret = request_irq(i2c->irq, s3c24xx_i2c_irq, 0, - dev_name(&pdev->dev), i2c); - - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_iomap; - } - - ret = s3c24xx_i2c_register_cpufreq(i2c); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); - goto err_irq; - } - - /* Note, previous versions of the driver used i2c_add_adapter() - * to add the bus at any number. We now pass the bus number via - * the platform data, so if unset it will now default to always - * being bus 0. - */ - - i2c->adap.nr = i2c->pdata->bus_num; - i2c->adap.dev.of_node = pdev->dev.of_node; - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add bus to i2c core\n"); - goto err_cpufreq; - } - - of_i2c_register_devices(&i2c->adap); - platform_set_drvdata(pdev, i2c); - - pm_runtime_enable(&pdev->dev); - pm_runtime_enable(&i2c->adap.dev); - - dev_info(&pdev->dev, "%s: S3C I2C adapter\n", dev_name(&i2c->adap.dev)); - clk_disable(i2c->clk); - return 0; - - err_cpufreq: - s3c24xx_i2c_deregister_cpufreq(i2c); - - err_irq: - free_irq(i2c->irq, i2c); - - err_iomap: - iounmap(i2c->regs); - - err_ioarea: - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - - err_clk: - clk_disable(i2c->clk); - clk_put(i2c->clk); - - err_noclk: - return ret; -} - -/* s3c24xx_i2c_remove - * - * called when device is removed from the bus -*/ - -static int s3c24xx_i2c_remove(struct platform_device *pdev) -{ - struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - - pm_runtime_disable(&i2c->adap.dev); - pm_runtime_disable(&pdev->dev); - - s3c24xx_i2c_deregister_cpufreq(i2c); - - i2c_del_adapter(&i2c->adap); - free_irq(i2c->irq, i2c); - - clk_disable(i2c->clk); - clk_put(i2c->clk); - - iounmap(i2c->regs); - - release_resource(i2c->ioarea); - s3c24xx_i2c_dt_gpio_free(i2c); - kfree(i2c->ioarea); - - return 0; -} - -#ifdef CONFIG_PM -static int s3c24xx_i2c_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 1; - - return 0; -} - -static int s3c24xx_i2c_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct s3c24xx_i2c *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 0; - clk_enable(i2c->clk); - s3c24xx_i2c_init(i2c); - clk_disable(i2c->clk); - - return 0; -} - -static const struct dev_pm_ops s3c24xx_i2c_dev_pm_ops = { - .suspend_noirq = s3c24xx_i2c_suspend_noirq, - .resume = s3c24xx_i2c_resume, -}; - -#define S3C24XX_DEV_PM_OPS (&s3c24xx_i2c_dev_pm_ops) -#else -#define S3C24XX_DEV_PM_OPS NULL -#endif - -/* device driver for platform bus bits */ - -static struct platform_device_id s3c24xx_driver_ids[] = { - { - .name = "s3c2410-i2c", - .driver_data = TYPE_S3C2410, - }, { - .name = "s3c2440-i2c", - .driver_data = TYPE_S3C2440, - }, { }, -}; -MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); - -#ifdef CONFIG_OF -static const struct of_device_id s3c24xx_i2c_match[] = { - { .compatible = "samsung,s3c2410-i2c" }, - { .compatible = "samsung,s3c2440-i2c" }, - {}, -}; -MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); -#else -#define s3c24xx_i2c_match NULL -#endif - -static struct platform_driver s3c24xx_i2c_driver = { - .probe = s3c24xx_i2c_probe, - .remove = s3c24xx_i2c_remove, - .id_table = s3c24xx_driver_ids, - .driver = { - .owner = THIS_MODULE, - .name = "s3c-i2c", - .pm = S3C24XX_DEV_PM_OPS, - .of_match_table = s3c24xx_i2c_match, - }, -}; - -static int __init i2c_adap_s3c_init(void) -{ - return platform_driver_register(&s3c24xx_i2c_driver); -} -subsys_initcall(i2c_adap_s3c_init); - -static void __exit i2c_adap_s3c_exit(void) -{ - platform_driver_unregister(&s3c24xx_i2c_driver); -} -module_exit(i2c_adap_s3c_exit); - -MODULE_DESCRIPTION("S3C24XX I2C Bus driver"); -MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.c deleted file mode 100644 index c64ba736..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * drivers/i2c/busses/i2c-s6000.c - * - * Description: Driver for S6000 Family I2C Interface - * Copyright (c) 2008 emlix GmbH - * Author: Oskar Schirmer <os@emlix.com> - * - * Partially based on i2c-bfin-twi.c driver by <sonic.zhang@analog.com> - * Copyright (c) 2005-2007 Analog Devices, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/i2c/s6000.h> -#include <linux/timer.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/interrupt.h> -#include <linux/platform_device.h> -#include <linux/io.h> - -#include "i2c-s6000.h" - -#define DRV_NAME "i2c-s6000" - -#define POLL_TIMEOUT (2 * HZ) - -struct s6i2c_if { - u8 __iomem *reg; /* memory mapped registers */ - int irq; - spinlock_t lock; - struct i2c_msg *msgs; /* messages currently handled */ - int msgs_num; /* nb of msgs to do */ - int msgs_push; /* nb of msgs read/written */ - int msgs_done; /* nb of msgs finally handled */ - unsigned push; /* nb of bytes read/written in msg */ - unsigned done; /* nb of bytes finally handled */ - int timeout_count; /* timeout retries left */ - struct timer_list timeout_timer; - struct i2c_adapter adap; - struct completion complete; - struct clk *clk; - struct resource *res; -}; - -static inline u16 i2c_rd16(struct s6i2c_if *iface, unsigned n) -{ - return readw(iface->reg + (n)); -} - -static inline void i2c_wr16(struct s6i2c_if *iface, unsigned n, u16 v) -{ - writew(v, iface->reg + (n)); -} - -static inline u32 i2c_rd32(struct s6i2c_if *iface, unsigned n) -{ - return readl(iface->reg + (n)); -} - -static inline void i2c_wr32(struct s6i2c_if *iface, unsigned n, u32 v) -{ - writel(v, iface->reg + (n)); -} - -static struct s6i2c_if s6i2c_if; - -static void s6i2c_handle_interrupt(struct s6i2c_if *iface) -{ - if (i2c_rd16(iface, S6_I2C_INTRSTAT) & (1 << S6_I2C_INTR_TXABRT)) { - i2c_rd16(iface, S6_I2C_CLRTXABRT); - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - complete(&iface->complete); - return; - } - if (iface->msgs_done >= iface->msgs_num) { - dev_err(&iface->adap.dev, "s6i2c: spurious I2C irq: %04x\n", - i2c_rd16(iface, S6_I2C_INTRSTAT)); - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - return; - } - while ((iface->msgs_push < iface->msgs_num) - && (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_TFNF))) { - struct i2c_msg *m = &iface->msgs[iface->msgs_push]; - if (!(m->flags & I2C_M_RD)) - i2c_wr16(iface, S6_I2C_DATACMD, m->buf[iface->push]); - else - i2c_wr16(iface, S6_I2C_DATACMD, - 1 << S6_I2C_DATACMD_READ); - if (++iface->push >= m->len) { - iface->push = 0; - iface->msgs_push += 1; - } - } - do { - struct i2c_msg *m = &iface->msgs[iface->msgs_done]; - if (!(m->flags & I2C_M_RD)) { - if (iface->msgs_done < iface->msgs_push) - iface->msgs_done += 1; - else - break; - } else if (i2c_rd16(iface, S6_I2C_STATUS) - & (1 << S6_I2C_STATUS_RFNE)) { - m->buf[iface->done] = i2c_rd16(iface, S6_I2C_DATACMD); - if (++iface->done >= m->len) { - iface->done = 0; - iface->msgs_done += 1; - } - } else{ - break; - } - } while (iface->msgs_done < iface->msgs_num); - if (iface->msgs_done >= iface->msgs_num) { - i2c_wr16(iface, S6_I2C_INTRMASK, 1 << S6_I2C_INTR_TXABRT); - complete(&iface->complete); - } else if (iface->msgs_push >= iface->msgs_num) { - i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) | - (1 << S6_I2C_INTR_RXFULL)); - } else { - i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXABRT) | - (1 << S6_I2C_INTR_TXEMPTY) | - (1 << S6_I2C_INTR_RXFULL)); - } -} - -static irqreturn_t s6i2c_interrupt_entry(int irq, void *dev_id) -{ - struct s6i2c_if *iface = dev_id; - if (!(i2c_rd16(iface, S6_I2C_STATUS) & ((1 << S6_I2C_INTR_RXUNDER) - | (1 << S6_I2C_INTR_RXOVER) - | (1 << S6_I2C_INTR_RXFULL) - | (1 << S6_I2C_INTR_TXOVER) - | (1 << S6_I2C_INTR_TXEMPTY) - | (1 << S6_I2C_INTR_RDREQ) - | (1 << S6_I2C_INTR_TXABRT) - | (1 << S6_I2C_INTR_RXDONE) - | (1 << S6_I2C_INTR_ACTIVITY) - | (1 << S6_I2C_INTR_STOPDET) - | (1 << S6_I2C_INTR_STARTDET) - | (1 << S6_I2C_INTR_GENCALL)))) - return IRQ_NONE; - - spin_lock(&iface->lock); - del_timer(&iface->timeout_timer); - s6i2c_handle_interrupt(iface); - spin_unlock(&iface->lock); - return IRQ_HANDLED; -} - -static void s6i2c_timeout(unsigned long data) -{ - struct s6i2c_if *iface = (struct s6i2c_if *)data; - unsigned long flags; - - spin_lock_irqsave(&iface->lock, flags); - s6i2c_handle_interrupt(iface); - if (--iface->timeout_count > 0) { - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - } else { - complete(&iface->complete); - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - } - spin_unlock_irqrestore(&iface->lock, flags); -} - -static int s6i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct s6i2c_if *iface = adap->algo_data; - int i; - if (num == 0) - return 0; - if (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY)) - yield(); - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - i2c_rd16(iface, S6_I2C_CLRINTR); - for (i = 0; i < num; i++) { - if (msgs[i].flags & I2C_M_TEN) { - dev_err(&adap->dev, - "s6i2c: 10 bits addr not supported\n"); - return -EINVAL; - } - if (msgs[i].len == 0) { - dev_err(&adap->dev, - "s6i2c: zero length message not supported\n"); - return -EINVAL; - } - if (msgs[i].addr != msgs[0].addr) { - dev_err(&adap->dev, - "s6i2c: multiple xfer cannot change target\n"); - return -EINVAL; - } - } - - iface->msgs = msgs; - iface->msgs_num = num; - iface->msgs_push = 0; - iface->msgs_done = 0; - iface->push = 0; - iface->done = 0; - iface->timeout_count = 10; - i2c_wr16(iface, S6_I2C_TAR, msgs[0].addr); - i2c_wr16(iface, S6_I2C_ENABLE, 1); - i2c_wr16(iface, S6_I2C_INTRMASK, (1 << S6_I2C_INTR_TXEMPTY) | - (1 << S6_I2C_INTR_TXABRT)); - - iface->timeout_timer.expires = jiffies + POLL_TIMEOUT; - add_timer(&iface->timeout_timer); - wait_for_completion(&iface->complete); - del_timer_sync(&iface->timeout_timer); - while (i2c_rd32(iface, S6_I2C_TXFLR) > 0) - schedule(); - while (i2c_rd16(iface, S6_I2C_STATUS) & (1 << S6_I2C_STATUS_ACTIVITY)) - schedule(); - - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - i2c_wr16(iface, S6_I2C_ENABLE, 0); - return iface->msgs_done; -} - -static u32 s6i2c_functionality(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm s6i2c_algorithm = { - .master_xfer = s6i2c_master_xfer, - .functionality = s6i2c_functionality, -}; - -static u16 __devinit nanoseconds_on_clk(struct s6i2c_if *iface, u32 ns) -{ - u32 dividend = ((clk_get_rate(iface->clk) / 1000) * ns) / 1000000; - if (dividend > 0xffff) - return 0xffff; - return dividend; -} - -static int __devinit s6i2c_probe(struct platform_device *dev) -{ - struct s6i2c_if *iface = &s6i2c_if; - struct i2c_adapter *p_adap; - const char *clock; - int bus_num, rc; - spin_lock_init(&iface->lock); - init_completion(&iface->complete); - iface->irq = platform_get_irq(dev, 0); - if (iface->irq < 0) { - rc = iface->irq; - goto err_out; - } - iface->res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!iface->res) { - rc = -ENXIO; - goto err_out; - } - iface->res = request_mem_region(iface->res->start, - resource_size(iface->res), - dev->dev.bus_id); - if (!iface->res) { - rc = -EBUSY; - goto err_out; - } - iface->reg = ioremap_nocache(iface->res->start, - resource_size(iface->res)); - if (!iface->reg) { - rc = -ENOMEM; - goto err_reg; - } - - clock = 0; - bus_num = -1; - if (dev->dev.platform_data) { - struct s6_i2c_platform_data *pdata = dev->dev.platform_data; - bus_num = pdata->bus_num; - clock = pdata->clock; - } - iface->clk = clk_get(&dev->dev, clock); - if (IS_ERR(iface->clk)) { - rc = PTR_ERR(iface->clk); - goto err_map; - } - rc = clk_enable(iface->clk); - if (rc < 0) - goto err_clk_put; - init_timer(&iface->timeout_timer); - iface->timeout_timer.function = s6i2c_timeout; - iface->timeout_timer.data = (unsigned long)iface; - - p_adap = &iface->adap; - strlcpy(p_adap->name, dev->name, sizeof(p_adap->name)); - p_adap->algo = &s6i2c_algorithm; - p_adap->algo_data = iface; - p_adap->nr = bus_num; - p_adap->class = 0; - p_adap->dev.parent = &dev->dev; - i2c_wr16(iface, S6_I2C_INTRMASK, 0); - rc = request_irq(iface->irq, s6i2c_interrupt_entry, - IRQF_SHARED, dev->name, iface); - if (rc) { - dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq); - goto err_clk_dis; - } - - i2c_wr16(iface, S6_I2C_ENABLE, 0); - udelay(1); - i2c_wr32(iface, S6_I2C_SRESET, 1 << S6_I2C_SRESET_IC_SRST); - i2c_wr16(iface, S6_I2C_CLRTXABRT, 1); - i2c_wr16(iface, S6_I2C_CON, - (1 << S6_I2C_CON_MASTER) | - (S6_I2C_CON_SPEED_NORMAL << S6_I2C_CON_SPEED) | - (0 << S6_I2C_CON_10BITSLAVE) | - (0 << S6_I2C_CON_10BITMASTER) | - (1 << S6_I2C_CON_RESTARTENA) | - (1 << S6_I2C_CON_SLAVEDISABLE)); - i2c_wr16(iface, S6_I2C_SSHCNT, nanoseconds_on_clk(iface, 4000)); - i2c_wr16(iface, S6_I2C_SSLCNT, nanoseconds_on_clk(iface, 4700)); - i2c_wr16(iface, S6_I2C_FSHCNT, nanoseconds_on_clk(iface, 600)); - i2c_wr16(iface, S6_I2C_FSLCNT, nanoseconds_on_clk(iface, 1300)); - i2c_wr16(iface, S6_I2C_RXTL, 0); - i2c_wr16(iface, S6_I2C_TXTL, 0); - - platform_set_drvdata(dev, iface); - rc = i2c_add_numbered_adapter(p_adap); - if (rc) - goto err_irq_free; - return 0; - -err_irq_free: - free_irq(iface->irq, iface); -err_clk_dis: - clk_disable(iface->clk); -err_clk_put: - clk_put(iface->clk); -err_map: - iounmap(iface->reg); -err_reg: - release_mem_region(iface->res->start, - resource_size(iface->res)); -err_out: - return rc; -} - -static int __devexit s6i2c_remove(struct platform_device *pdev) -{ - struct s6i2c_if *iface = platform_get_drvdata(pdev); - i2c_wr16(iface, S6_I2C_ENABLE, 0); - platform_set_drvdata(pdev, NULL); - i2c_del_adapter(&iface->adap); - free_irq(iface->irq, iface); - clk_disable(iface->clk); - clk_put(iface->clk); - iounmap(iface->reg); - release_mem_region(iface->res->start, - resource_size(iface->res)); - return 0; -} - -static struct platform_driver s6i2c_driver = { - .probe = s6i2c_probe, - .remove = __devexit_p(s6i2c_remove), - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init s6i2c_init(void) -{ - pr_info("I2C: S6000 I2C driver\n"); - return platform_driver_register(&s6i2c_driver); -} - -static void __exit s6i2c_exit(void) -{ - platform_driver_unregister(&s6i2c_driver); -} - -MODULE_DESCRIPTION("I2C-Bus adapter routines for S6000 I2C"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" DRV_NAME); - -subsys_initcall(s6i2c_init); -module_exit(s6i2c_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.h b/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.h deleted file mode 100644 index ff23b81d..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-s6000.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * drivers/i2c/busses/i2c-s6000.h - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2008 Emlix GmbH <info@emlix.com> - * Author: Oskar Schirmer <os@emlix.com> - */ - -#ifndef __DRIVERS_I2C_BUSSES_I2C_S6000_H -#define __DRIVERS_I2C_BUSSES_I2C_S6000_H - -#define S6_I2C_CON 0x000 -#define S6_I2C_CON_MASTER 0 -#define S6_I2C_CON_SPEED 1 -#define S6_I2C_CON_SPEED_NORMAL 1 -#define S6_I2C_CON_SPEED_FAST 2 -#define S6_I2C_CON_SPEED_MASK 3 -#define S6_I2C_CON_10BITSLAVE 3 -#define S6_I2C_CON_10BITMASTER 4 -#define S6_I2C_CON_RESTARTENA 5 -#define S6_I2C_CON_SLAVEDISABLE 6 -#define S6_I2C_TAR 0x004 -#define S6_I2C_TAR_GCORSTART 10 -#define S6_I2C_TAR_SPECIAL 11 -#define S6_I2C_SAR 0x008 -#define S6_I2C_HSMADDR 0x00C -#define S6_I2C_DATACMD 0x010 -#define S6_I2C_DATACMD_READ 8 -#define S6_I2C_SSHCNT 0x014 -#define S6_I2C_SSLCNT 0x018 -#define S6_I2C_FSHCNT 0x01C -#define S6_I2C_FSLCNT 0x020 -#define S6_I2C_INTRSTAT 0x02C -#define S6_I2C_INTRMASK 0x030 -#define S6_I2C_RAWINTR 0x034 -#define S6_I2C_INTR_RXUNDER 0 -#define S6_I2C_INTR_RXOVER 1 -#define S6_I2C_INTR_RXFULL 2 -#define S6_I2C_INTR_TXOVER 3 -#define S6_I2C_INTR_TXEMPTY 4 -#define S6_I2C_INTR_RDREQ 5 -#define S6_I2C_INTR_TXABRT 6 -#define S6_I2C_INTR_RXDONE 7 -#define S6_I2C_INTR_ACTIVITY 8 -#define S6_I2C_INTR_STOPDET 9 -#define S6_I2C_INTR_STARTDET 10 -#define S6_I2C_INTR_GENCALL 11 -#define S6_I2C_RXTL 0x038 -#define S6_I2C_TXTL 0x03C -#define S6_I2C_CLRINTR 0x040 -#define S6_I2C_CLRRXUNDER 0x044 -#define S6_I2C_CLRRXOVER 0x048 -#define S6_I2C_CLRTXOVER 0x04C -#define S6_I2C_CLRRDREQ 0x050 -#define S6_I2C_CLRTXABRT 0x054 -#define S6_I2C_CLRRXDONE 0x058 -#define S6_I2C_CLRACTIVITY 0x05C -#define S6_I2C_CLRSTOPDET 0x060 -#define S6_I2C_CLRSTARTDET 0x064 -#define S6_I2C_CLRGENCALL 0x068 -#define S6_I2C_ENABLE 0x06C -#define S6_I2C_STATUS 0x070 -#define S6_I2C_STATUS_ACTIVITY 0 -#define S6_I2C_STATUS_TFNF 1 -#define S6_I2C_STATUS_TFE 2 -#define S6_I2C_STATUS_RFNE 3 -#define S6_I2C_STATUS_RFF 4 -#define S6_I2C_TXFLR 0x074 -#define S6_I2C_RXFLR 0x078 -#define S6_I2C_SRESET 0x07C -#define S6_I2C_SRESET_IC_SRST 0 -#define S6_I2C_SRESET_IC_MASTER_SRST 1 -#define S6_I2C_SRESET_IC_SLAVE_SRST 2 -#define S6_I2C_TXABRTSOURCE 0x080 - -#endif diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-scmi.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-scmi.c deleted file mode 100644 index 388cbdc9..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-scmi.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * SMBus driver for ACPI SMBus CMI - * - * Copyright (C) 2009 Crane Cai <crane.cai@amd.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2. - */ - -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/acpi.h> - -#define ACPI_SMBUS_HC_CLASS "smbus" -#define ACPI_SMBUS_HC_DEVICE_NAME "cmi" - -ACPI_MODULE_NAME("smbus_cmi"); - -struct smbus_methods_t { - char *mt_info; - char *mt_sbr; - char *mt_sbw; -}; - -struct acpi_smbus_cmi { - acpi_handle handle; - struct i2c_adapter adapter; - u8 cap_info:1; - u8 cap_read:1; - u8 cap_write:1; - struct smbus_methods_t *methods; -}; - -static const struct smbus_methods_t smbus_methods = { - .mt_info = "_SBI", - .mt_sbr = "_SBR", - .mt_sbw = "_SBW", -}; - -/* Some IBM BIOSes omit the leading underscore */ -static const struct smbus_methods_t ibm_smbus_methods = { - .mt_info = "SBI_", - .mt_sbr = "SBR_", - .mt_sbw = "SBW_", -}; - -static const struct acpi_device_id acpi_smbus_cmi_ids[] = { - {"SMBUS01", (kernel_ulong_t)&smbus_methods}, - {ACPI_SMBUS_IBM_HID, (kernel_ulong_t)&ibm_smbus_methods}, - {"", 0} -}; -MODULE_DEVICE_TABLE(acpi, acpi_smbus_cmi_ids); - -#define ACPI_SMBUS_STATUS_OK 0x00 -#define ACPI_SMBUS_STATUS_FAIL 0x07 -#define ACPI_SMBUS_STATUS_DNAK 0x10 -#define ACPI_SMBUS_STATUS_DERR 0x11 -#define ACPI_SMBUS_STATUS_CMD_DENY 0x12 -#define ACPI_SMBUS_STATUS_UNKNOWN 0x13 -#define ACPI_SMBUS_STATUS_ACC_DENY 0x17 -#define ACPI_SMBUS_STATUS_TIMEOUT 0x18 -#define ACPI_SMBUS_STATUS_NOTSUP 0x19 -#define ACPI_SMBUS_STATUS_BUSY 0x1a -#define ACPI_SMBUS_STATUS_PEC 0x1f - -#define ACPI_SMBUS_PRTCL_WRITE 0x00 -#define ACPI_SMBUS_PRTCL_READ 0x01 -#define ACPI_SMBUS_PRTCL_QUICK 0x02 -#define ACPI_SMBUS_PRTCL_BYTE 0x04 -#define ACPI_SMBUS_PRTCL_BYTE_DATA 0x06 -#define ACPI_SMBUS_PRTCL_WORD_DATA 0x08 -#define ACPI_SMBUS_PRTCL_BLOCK_DATA 0x0a - - -static int -acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data *data) -{ - int result = 0; - struct acpi_smbus_cmi *smbus_cmi = adap->algo_data; - unsigned char protocol; - acpi_status status = 0; - struct acpi_object_list input; - union acpi_object mt_params[5]; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - union acpi_object *pkg; - char *method; - int len = 0; - - dev_dbg(&adap->dev, "access size: %d %s\n", size, - (read_write) ? "READ" : "WRITE"); - switch (size) { - case I2C_SMBUS_QUICK: - protocol = ACPI_SMBUS_PRTCL_QUICK; - command = 0; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 0; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = 0; - } - break; - - case I2C_SMBUS_BYTE: - protocol = ACPI_SMBUS_PRTCL_BYTE; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 0; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = 0; - } else { - command = 0; - } - break; - - case I2C_SMBUS_BYTE_DATA: - protocol = ACPI_SMBUS_PRTCL_BYTE_DATA; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 1; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = data->byte; - } - break; - - case I2C_SMBUS_WORD_DATA: - protocol = ACPI_SMBUS_PRTCL_WORD_DATA; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 2; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = data->word; - } - break; - - case I2C_SMBUS_BLOCK_DATA: - protocol = ACPI_SMBUS_PRTCL_BLOCK_DATA; - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EINVAL; - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = len; - mt_params[4].type = ACPI_TYPE_BUFFER; - mt_params[4].buffer.pointer = data->block + 1; - } - break; - - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - if (read_write == I2C_SMBUS_READ) { - protocol |= ACPI_SMBUS_PRTCL_READ; - method = smbus_cmi->methods->mt_sbr; - input.count = 3; - } else { - protocol |= ACPI_SMBUS_PRTCL_WRITE; - method = smbus_cmi->methods->mt_sbw; - input.count = 5; - } - - input.pointer = mt_params; - mt_params[0].type = ACPI_TYPE_INTEGER; - mt_params[0].integer.value = protocol; - mt_params[1].type = ACPI_TYPE_INTEGER; - mt_params[1].integer.value = addr; - mt_params[2].type = ACPI_TYPE_INTEGER; - mt_params[2].integer.value = command; - - status = acpi_evaluate_object(smbus_cmi->handle, method, &input, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Evaluating %s: %i", method, status)); - return -EIO; - } - - pkg = buffer.pointer; - if (pkg && pkg->type == ACPI_TYPE_PACKAGE) - obj = pkg->package.elements; - else { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - - result = obj->integer.value; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s return status: %i\n", - method, result)); - - switch (result) { - case ACPI_SMBUS_STATUS_OK: - result = 0; - break; - case ACPI_SMBUS_STATUS_BUSY: - result = -EBUSY; - goto out; - case ACPI_SMBUS_STATUS_TIMEOUT: - result = -ETIMEDOUT; - goto out; - case ACPI_SMBUS_STATUS_DNAK: - result = -ENXIO; - goto out; - default: - result = -EIO; - goto out; - } - - if (read_write == I2C_SMBUS_WRITE || size == I2C_SMBUS_QUICK) - goto out; - - obj = pkg->package.elements + 1; - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - - len = obj->integer.value; - obj = pkg->package.elements + 2; - switch (size) { - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - case I2C_SMBUS_WORD_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (len == 2) - data->word = obj->integer.value; - else - data->byte = obj->integer.value; - break; - case I2C_SMBUS_BLOCK_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - data->block[0] = len; - memcpy(data->block + 1, obj->buffer.pointer, len); - break; - } - -out: - kfree(buffer.pointer); - dev_dbg(&adap->dev, "Transaction status: %i\n", result); - return result; -} - -static u32 acpi_smbus_cmi_func(struct i2c_adapter *adapter) -{ - struct acpi_smbus_cmi *smbus_cmi = adapter->algo_data; - u32 ret; - - ret = smbus_cmi->cap_read | smbus_cmi->cap_write ? - I2C_FUNC_SMBUS_QUICK : 0; - - ret |= smbus_cmi->cap_read ? - (I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA | - I2C_FUNC_SMBUS_READ_BLOCK_DATA) : 0; - - ret |= smbus_cmi->cap_write ? - (I2C_FUNC_SMBUS_WRITE_BYTE | - I2C_FUNC_SMBUS_WRITE_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA | - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) : 0; - - return ret; -} - -static const struct i2c_algorithm acpi_smbus_cmi_algorithm = { - .smbus_xfer = acpi_smbus_cmi_access, - .functionality = acpi_smbus_cmi_func, -}; - - -static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, - const char *name) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - - if (!strcmp(name, smbus_cmi->methods->mt_info)) { - status = acpi_evaluate_object(smbus_cmi->handle, - smbus_cmi->methods->mt_info, - NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Evaluating %s: %i", - smbus_cmi->methods->mt_info, status)); - return -EIO; - } - - obj = buffer.pointer; - if (obj && obj->type == ACPI_TYPE_PACKAGE) - obj = obj->package.elements; - else { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - kfree(buffer.pointer); - return -EIO; - } - - if (obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - kfree(buffer.pointer); - return -EIO; - } else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMBus CMI Version %x" - "\n", (int)obj->integer.value)); - - kfree(buffer.pointer); - smbus_cmi->cap_info = 1; - } else if (!strcmp(name, smbus_cmi->methods->mt_sbr)) - smbus_cmi->cap_read = 1; - else if (!strcmp(name, smbus_cmi->methods->mt_sbw)) - smbus_cmi->cap_write = 1; - else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", - name)); - - return 0; -} - -static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level, - void *context, void **return_value) -{ - char node_name[5]; - struct acpi_buffer buffer = { sizeof(node_name), node_name }; - struct acpi_smbus_cmi *smbus_cmi = context; - acpi_status status; - - status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - - if (ACPI_SUCCESS(status)) - acpi_smbus_cmi_add_cap(smbus_cmi, node_name); - - return AE_OK; -} - -static int acpi_smbus_cmi_add(struct acpi_device *device) -{ - struct acpi_smbus_cmi *smbus_cmi; - const struct acpi_device_id *id; - - smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL); - if (!smbus_cmi) - return -ENOMEM; - - smbus_cmi->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_SMBUS_HC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_SMBUS_HC_CLASS); - device->driver_data = smbus_cmi; - smbus_cmi->cap_info = 0; - smbus_cmi->cap_read = 0; - smbus_cmi->cap_write = 0; - - for (id = acpi_smbus_cmi_ids; id->id[0]; id++) - if (!strcmp(id->id, acpi_device_hid(device))) - smbus_cmi->methods = - (struct smbus_methods_t *) id->driver_data; - - acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1, - acpi_smbus_cmi_query_methods, NULL, smbus_cmi, NULL); - - if (smbus_cmi->cap_info == 0) - goto err; - - snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name), - "SMBus CMI adapter %s", - acpi_device_name(device)); - smbus_cmi->adapter.owner = THIS_MODULE; - smbus_cmi->adapter.algo = &acpi_smbus_cmi_algorithm; - smbus_cmi->adapter.algo_data = smbus_cmi; - smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus_cmi->adapter.dev.parent = &device->dev; - - if (i2c_add_adapter(&smbus_cmi->adapter)) { - dev_err(&device->dev, "Couldn't register adapter!\n"); - goto err; - } - - return 0; - -err: - kfree(smbus_cmi); - device->driver_data = NULL; - return -EIO; -} - -static int acpi_smbus_cmi_remove(struct acpi_device *device, int type) -{ - struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device); - - i2c_del_adapter(&smbus_cmi->adapter); - kfree(smbus_cmi); - device->driver_data = NULL; - - return 0; -} - -static struct acpi_driver acpi_smbus_cmi_driver = { - .name = ACPI_SMBUS_HC_DEVICE_NAME, - .class = ACPI_SMBUS_HC_CLASS, - .ids = acpi_smbus_cmi_ids, - .ops = { - .add = acpi_smbus_cmi_add, - .remove = acpi_smbus_cmi_remove, - }, -}; - -static int __init acpi_smbus_cmi_init(void) -{ - return acpi_bus_register_driver(&acpi_smbus_cmi_driver); -} - -static void __exit acpi_smbus_cmi_exit(void) -{ - acpi_bus_unregister_driver(&acpi_smbus_cmi_driver); -} - -module_init(acpi_smbus_cmi_init); -module_exit(acpi_smbus_cmi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Crane Cai <crane.cai@amd.com>"); -MODULE_DESCRIPTION("ACPI SMBus CMI driver"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh7760.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh7760.c deleted file mode 100644 index c0c9dffb..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh7760.c +++ /dev/null @@ -1,567 +0,0 @@ -/* - * I2C bus driver for the SH7760 I2C Interfaces. - * - * (c) 2005-2008 MSC Vertriebsges.m.b.H, Manuel Lauss <mlau@msc-ge.com> - * - * licensed under the terms outlined in the file COPYING. - * - */ - -#include <linux/completion.h> -#include <linux/delay.h> -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/module.h> - -#include <asm/clock.h> -#include <asm/i2c-sh7760.h> - -/* register offsets */ -#define I2CSCR 0x0 /* slave ctrl */ -#define I2CMCR 0x4 /* master ctrl */ -#define I2CSSR 0x8 /* slave status */ -#define I2CMSR 0xC /* master status */ -#define I2CSIER 0x10 /* slave irq enable */ -#define I2CMIER 0x14 /* master irq enable */ -#define I2CCCR 0x18 /* clock dividers */ -#define I2CSAR 0x1c /* slave address */ -#define I2CMAR 0x20 /* master address */ -#define I2CRXTX 0x24 /* data port */ -#define I2CFCR 0x28 /* fifo control */ -#define I2CFSR 0x2C /* fifo status */ -#define I2CFIER 0x30 /* fifo irq enable */ -#define I2CRFDR 0x34 /* rx fifo count */ -#define I2CTFDR 0x38 /* tx fifo count */ - -#define REGSIZE 0x3C - -#define MCR_MDBS 0x80 /* non-fifo mode switch */ -#define MCR_FSCL 0x40 /* override SCL pin */ -#define MCR_FSDA 0x20 /* override SDA pin */ -#define MCR_OBPC 0x10 /* override pins */ -#define MCR_MIE 0x08 /* master if enable */ -#define MCR_TSBE 0x04 -#define MCR_FSB 0x02 /* force stop bit */ -#define MCR_ESG 0x01 /* en startbit gen. */ - -#define MSR_MNR 0x40 /* nack received */ -#define MSR_MAL 0x20 /* arbitration lost */ -#define MSR_MST 0x10 /* sent a stop */ -#define MSR_MDE 0x08 -#define MSR_MDT 0x04 -#define MSR_MDR 0x02 -#define MSR_MAT 0x01 /* slave addr xfer done */ - -#define MIE_MNRE 0x40 /* nack irq en */ -#define MIE_MALE 0x20 /* arblos irq en */ -#define MIE_MSTE 0x10 /* stop irq en */ -#define MIE_MDEE 0x08 -#define MIE_MDTE 0x04 -#define MIE_MDRE 0x02 -#define MIE_MATE 0x01 /* address sent irq en */ - -#define FCR_RFRST 0x02 /* reset rx fifo */ -#define FCR_TFRST 0x01 /* reset tx fifo */ - -#define FSR_TEND 0x04 /* last byte sent */ -#define FSR_RDF 0x02 /* rx fifo trigger */ -#define FSR_TDFE 0x01 /* tx fifo empty */ - -#define FIER_TEIE 0x04 /* tx fifo empty irq en */ -#define FIER_RXIE 0x02 /* rx fifo trig irq en */ -#define FIER_TXIE 0x01 /* tx fifo trig irq en */ - -#define FIFO_SIZE 16 - -struct cami2c { - void __iomem *iobase; - struct i2c_adapter adap; - - /* message processing */ - struct i2c_msg *msg; -#define IDF_SEND 1 -#define IDF_RECV 2 -#define IDF_STOP 4 - int flags; - -#define IDS_DONE 1 -#define IDS_ARBLOST 2 -#define IDS_NACK 4 - int status; - struct completion xfer_done; - - int irq; - struct resource *ioarea; -}; - -static inline void OUT32(struct cami2c *cam, int reg, unsigned long val) -{ - __raw_writel(val, (unsigned long)cam->iobase + reg); -} - -static inline unsigned long IN32(struct cami2c *cam, int reg) -{ - return __raw_readl((unsigned long)cam->iobase + reg); -} - -static irqreturn_t sh7760_i2c_irq(int irq, void *ptr) -{ - struct cami2c *id = ptr; - struct i2c_msg *msg = id->msg; - char *data = msg->buf; - unsigned long msr, fsr, fier, len; - - msr = IN32(id, I2CMSR); - fsr = IN32(id, I2CFSR); - - /* arbitration lost */ - if (msr & MSR_MAL) { - OUT32(id, I2CMCR, 0); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - id->status |= IDS_DONE | IDS_ARBLOST; - goto out; - } - - if (msr & MSR_MNR) { - /* NACK handling is very screwed up. After receiving a - * NAK IRQ one has to wait a bit before writing to any - * registers, or the ctl will lock up. After that delay - * do a normal i2c stop. Then wait at least 1 ms before - * attempting another transfer or ctl will stop working - */ - udelay(100); /* wait or risk ctl hang */ - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - OUT32(id, I2CFIER, 0); - OUT32(id, I2CMIER, MIE_MSTE); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - id->status |= IDS_NACK; - msr &= ~MSR_MAT; - fsr = 0; - /* In some cases the MST bit is also set. */ - } - - /* i2c-stop was sent */ - if (msr & MSR_MST) { - id->status |= IDS_DONE; - goto out; - } - - /* i2c slave addr was sent; set to "normal" operation */ - if (msr & MSR_MAT) - OUT32(id, I2CMCR, MCR_MIE); - - fier = IN32(id, I2CFIER); - - if (fsr & FSR_RDF) { - len = IN32(id, I2CRFDR); - if (msg->len <= len) { - if (id->flags & IDF_STOP) { - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - OUT32(id, I2CFIER, 0); - /* manual says: wait >= 0.5 SCL times */ - udelay(5); - /* next int should be MST */ - } else { - id->status |= IDS_DONE; - /* keep the RDF bit: ctrl holds SCL low - * until the setup for the next i2c_msg - * clears this bit. - */ - fsr &= ~FSR_RDF; - } - } - while (msg->len && len) { - *data++ = IN32(id, I2CRXTX); - msg->len--; - len--; - } - - if (msg->len) { - len = (msg->len >= FIFO_SIZE) ? FIFO_SIZE - 1 - : msg->len - 1; - - OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xf) << 4)); - } - - } else if (id->flags & IDF_SEND) { - if ((fsr & FSR_TEND) && (msg->len < 1)) { - if (id->flags & IDF_STOP) { - OUT32(id, I2CMCR, MCR_MIE | MCR_FSB); - } else { - id->status |= IDS_DONE; - /* keep the TEND bit: ctl holds SCL low - * until the setup for the next i2c_msg - * clears this bit. - */ - fsr &= ~FSR_TEND; - } - } - if (fsr & FSR_TDFE) { - while (msg->len && (IN32(id, I2CTFDR) < FIFO_SIZE)) { - OUT32(id, I2CRXTX, *data++); - msg->len--; - } - - if (msg->len < 1) { - fier &= ~FIER_TXIE; - OUT32(id, I2CFIER, fier); - } else { - len = (msg->len >= FIFO_SIZE) ? 2 : 0; - OUT32(id, I2CFCR, - FCR_RFRST | ((len & 3) << 2)); - } - } - } -out: - if (id->status & IDS_DONE) { - OUT32(id, I2CMIER, 0); - OUT32(id, I2CFIER, 0); - id->msg = NULL; - complete(&id->xfer_done); - } - /* clear status flags and ctrl resumes work */ - OUT32(id, I2CMSR, ~msr); - OUT32(id, I2CFSR, ~fsr); - OUT32(id, I2CSSR, 0); - - return IRQ_HANDLED; -} - - -/* prepare and start a master receive operation */ -static void sh7760_i2c_mrecv(struct cami2c *id) -{ - int len; - - id->flags |= IDF_RECV; - - /* set the slave addr reg; otherwise rcv wont work! */ - OUT32(id, I2CSAR, 0xfe); - OUT32(id, I2CMAR, (id->msg->addr << 1) | 1); - - /* adjust rx fifo trigger */ - if (id->msg->len >= FIFO_SIZE) - len = FIFO_SIZE - 1; /* trigger at fifo full */ - else - len = id->msg->len - 1; /* trigger before all received */ - - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFCR, FCR_TFRST | ((len & 0xF) << 4)); - - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMCR, MCR_MIE | MCR_ESG); - OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE); - OUT32(id, I2CFIER, FIER_RXIE); -} - -/* prepare and start a master send operation */ -static void sh7760_i2c_msend(struct cami2c *id) -{ - int len; - - id->flags |= IDF_SEND; - - /* set the slave addr reg; otherwise xmit wont work! */ - OUT32(id, I2CSAR, 0xfe); - OUT32(id, I2CMAR, (id->msg->addr << 1) | 0); - - /* adjust tx fifo trigger */ - if (id->msg->len >= FIFO_SIZE) - len = 2; /* trig: 2 bytes left in TX fifo */ - else - len = 0; /* trig: 8 bytes left in TX fifo */ - - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFCR, FCR_RFRST | ((len & 3) << 2)); - - while (id->msg->len && IN32(id, I2CTFDR) < FIFO_SIZE) { - OUT32(id, I2CRXTX, *(id->msg->buf)); - (id->msg->len)--; - (id->msg->buf)++; - } - - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMCR, MCR_MIE | MCR_ESG); - OUT32(id, I2CFSR, 0); - OUT32(id, I2CMIER, MIE_MNRE | MIE_MALE | MIE_MSTE | MIE_MATE); - OUT32(id, I2CFIER, FIER_TEIE | (id->msg->len ? FIER_TXIE : 0)); -} - -static inline int sh7760_i2c_busy_check(struct cami2c *id) -{ - return (IN32(id, I2CMCR) & MCR_FSDA); -} - -static int sh7760_i2c_master_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, - int num) -{ - struct cami2c *id = adap->algo_data; - int i, retr; - - if (sh7760_i2c_busy_check(id)) { - dev_err(&adap->dev, "sh7760-i2c%d: bus busy!\n", adap->nr); - return -EBUSY; - } - - i = 0; - while (i < num) { - retr = adap->retries; -retry: - id->flags = ((i == (num-1)) ? IDF_STOP : 0); - id->status = 0; - id->msg = msgs; - init_completion(&id->xfer_done); - - if (msgs->flags & I2C_M_RD) - sh7760_i2c_mrecv(id); - else - sh7760_i2c_msend(id); - - wait_for_completion(&id->xfer_done); - - if (id->status == 0) { - num = -EIO; - break; - } - - if (id->status & IDS_NACK) { - /* wait a bit or i2c module stops working */ - mdelay(1); - num = -EREMOTEIO; - break; - } - - if (id->status & IDS_ARBLOST) { - if (retr--) { - mdelay(2); - goto retry; - } - num = -EREMOTEIO; - break; - } - - msgs++; - i++; - } - - id->msg = NULL; - id->flags = 0; - id->status = 0; - - OUT32(id, I2CMCR, 0); - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMIER, 0); - OUT32(id, I2CFIER, 0); - - /* reset slave module registers too: master mode enables slave - * module for receive ops (ack, data). Without this reset, - * eternal bus activity might be reported after NACK / ARBLOST. - */ - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSAR, 0); - OUT32(id, I2CSSR, 0); - - return num; -} - -static u32 sh7760_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK); -} - -static const struct i2c_algorithm sh7760_i2c_algo = { - .master_xfer = sh7760_i2c_master_xfer, - .functionality = sh7760_i2c_func, -}; - -/* calculate CCR register setting for a desired scl clock. SCL clock is - * derived from I2C module clock (iclk) which in turn is derived from - * peripheral module clock (mclk, usually around 33MHz): - * iclk = mclk/(CDF + 1). iclk must be < 20MHz. - * scl = iclk/(SCGD*8 + 20). - */ -static int __devinit calc_CCR(unsigned long scl_hz) -{ - struct clk *mclk; - unsigned long mck, m1, dff, odff, iclk; - signed char cdf, cdfm; - int scgd, scgdm, scgds; - - mclk = clk_get(NULL, "peripheral_clk"); - if (IS_ERR(mclk)) { - return PTR_ERR(mclk); - } else { - mck = mclk->rate; - clk_put(mclk); - } - - odff = scl_hz; - scgdm = cdfm = m1 = 0; - for (cdf = 3; cdf >= 0; cdf--) { - iclk = mck / (1 + cdf); - if (iclk >= 20000000) - continue; - scgds = ((iclk / scl_hz) - 20) >> 3; - for (scgd = scgds; (scgd < 63) && scgd <= scgds + 1; scgd++) { - m1 = iclk / (20 + (scgd << 3)); - dff = abs(scl_hz - m1); - if (dff < odff) { - odff = dff; - cdfm = cdf; - scgdm = scgd; - } - } - } - /* fail if more than 25% off of requested SCL */ - if (odff > (scl_hz >> 2)) - return -EINVAL; - - /* create a CCR register value */ - return ((scgdm << 2) | cdfm); -} - -static int __devinit sh7760_i2c_probe(struct platform_device *pdev) -{ - struct sh7760_i2c_platdata *pd; - struct resource *res; - struct cami2c *id; - int ret; - - pd = pdev->dev.platform_data; - if (!pd) { - dev_err(&pdev->dev, "no platform_data!\n"); - ret = -ENODEV; - goto out0; - } - - id = kzalloc(sizeof(struct cami2c), GFP_KERNEL); - if (!id) { - dev_err(&pdev->dev, "no mem for private data\n"); - ret = -ENOMEM; - goto out0; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mmio resources\n"); - ret = -ENODEV; - goto out1; - } - - id->ioarea = request_mem_region(res->start, REGSIZE, pdev->name); - if (!id->ioarea) { - dev_err(&pdev->dev, "mmio already reserved\n"); - ret = -EBUSY; - goto out1; - } - - id->iobase = ioremap(res->start, REGSIZE); - if (!id->iobase) { - dev_err(&pdev->dev, "cannot ioremap\n"); - ret = -ENODEV; - goto out2; - } - - id->irq = platform_get_irq(pdev, 0); - - id->adap.nr = pdev->id; - id->adap.algo = &sh7760_i2c_algo; - id->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - id->adap.retries = 3; - id->adap.algo_data = id; - id->adap.dev.parent = &pdev->dev; - snprintf(id->adap.name, sizeof(id->adap.name), - "SH7760 I2C at %08lx", (unsigned long)res->start); - - OUT32(id, I2CMCR, 0); - OUT32(id, I2CMSR, 0); - OUT32(id, I2CMIER, 0); - OUT32(id, I2CMAR, 0); - OUT32(id, I2CSIER, 0); - OUT32(id, I2CSAR, 0); - OUT32(id, I2CSCR, 0); - OUT32(id, I2CSSR, 0); - OUT32(id, I2CFIER, 0); - OUT32(id, I2CFCR, FCR_RFRST | FCR_TFRST); - OUT32(id, I2CFSR, 0); - - ret = calc_CCR(pd->speed_khz * 1000); - if (ret < 0) { - dev_err(&pdev->dev, "invalid SCL clock: %dkHz\n", - pd->speed_khz); - goto out3; - } - OUT32(id, I2CCCR, ret); - - if (request_irq(id->irq, sh7760_i2c_irq, 0, - SH7760_I2C_DEVNAME, id)) { - dev_err(&pdev->dev, "cannot get irq %d\n", id->irq); - ret = -EBUSY; - goto out3; - } - - ret = i2c_add_numbered_adapter(&id->adap); - if (ret < 0) { - dev_err(&pdev->dev, "reg adap failed: %d\n", ret); - goto out4; - } - - platform_set_drvdata(pdev, id); - - dev_info(&pdev->dev, "%d kHz mmio %08x irq %d\n", - pd->speed_khz, res->start, id->irq); - - return 0; - -out4: - free_irq(id->irq, id); -out3: - iounmap(id->iobase); -out2: - release_resource(id->ioarea); - kfree(id->ioarea); -out1: - kfree(id); -out0: - return ret; -} - -static int __devexit sh7760_i2c_remove(struct platform_device *pdev) -{ - struct cami2c *id = platform_get_drvdata(pdev); - - i2c_del_adapter(&id->adap); - free_irq(id->irq, id); - iounmap(id->iobase); - release_resource(id->ioarea); - kfree(id->ioarea); - kfree(id); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver sh7760_i2c_drv = { - .driver = { - .name = SH7760_I2C_DEVNAME, - .owner = THIS_MODULE, - }, - .probe = sh7760_i2c_probe, - .remove = __devexit_p(sh7760_i2c_remove), -}; - -module_platform_driver(sh7760_i2c_drv); - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("SH7760 I2C bus driver"); -MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh_mobile.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh_mobile.c deleted file mode 100644 index 675c9692..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sh_mobile.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - * SuperH Mobile I2C Controller - * - * Copyright (C) 2008 Magnus Damm - * - * Portions of the code based on out-of-tree driver i2c-sh7343.c - * Copyright (c) 2006 Carlos Munoz <carlos@kenati.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/interrupt.h> -#include <linux/i2c.h> -#include <linux/err.h> -#include <linux/pm_runtime.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> -#include <linux/i2c/i2c-sh_mobile.h> - -/* Transmit operation: */ -/* */ -/* 0 byte transmit */ -/* BUS: S A8 ACK P */ -/* IRQ: DTE WAIT */ -/* ICIC: */ -/* ICCR: 0x94 0x90 */ -/* ICDR: A8 */ -/* */ -/* 1 byte transmit */ -/* BUS: S A8 ACK D8(1) ACK P */ -/* IRQ: DTE WAIT WAIT */ -/* ICIC: -DTE */ -/* ICCR: 0x94 0x90 */ -/* ICDR: A8 D8(1) */ -/* */ -/* 2 byte transmit */ -/* BUS: S A8 ACK D8(1) ACK D8(2) ACK P */ -/* IRQ: DTE WAIT WAIT WAIT */ -/* ICIC: -DTE */ -/* ICCR: 0x94 0x90 */ -/* ICDR: A8 D8(1) D8(2) */ -/* */ -/* 3 bytes or more, +---------+ gets repeated */ -/* */ -/* */ -/* Receive operation: */ -/* */ -/* 0 byte receive - not supported since slave may hold SDA low */ -/* */ -/* 1 byte receive [TX] | [RX] */ -/* BUS: S A8 ACK | D8(1) ACK P */ -/* IRQ: DTE WAIT | WAIT DTE */ -/* ICIC: -DTE | +DTE */ -/* ICCR: 0x94 0x81 | 0xc0 */ -/* ICDR: A8 | D8(1) */ -/* */ -/* 2 byte receive [TX]| [RX] */ -/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK P */ -/* IRQ: DTE WAIT | WAIT WAIT DTE */ -/* ICIC: -DTE | +DTE */ -/* ICCR: 0x94 0x81 | 0xc0 */ -/* ICDR: A8 | D8(1) D8(2) */ -/* */ -/* 3 byte receive [TX] | [RX] */ -/* BUS: S A8 ACK | D8(1) ACK D8(2) ACK D8(3) ACK P */ -/* IRQ: DTE WAIT | WAIT WAIT WAIT DTE */ -/* ICIC: -DTE | +DTE */ -/* ICCR: 0x94 0x81 | 0xc0 */ -/* ICDR: A8 | D8(1) D8(2) D8(3) */ -/* */ -/* 4 bytes or more, this part is repeated +---------+ */ -/* */ -/* */ -/* Interrupt order and BUSY flag */ -/* ___ _ */ -/* SDA ___\___XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXAAAAAAAAA___/ */ -/* SCL \_/1\_/2\_/3\_/4\_/5\_/6\_/7\_/8\___/9\_____/ */ -/* */ -/* S D7 D6 D5 D4 D3 D2 D1 D0 P */ -/* ___ */ -/* WAIT IRQ ________________________________/ \___________ */ -/* TACK IRQ ____________________________________/ \_______ */ -/* DTE IRQ __________________________________________/ \_ */ -/* AL IRQ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */ -/* _______________________________________________ */ -/* BUSY __/ \_ */ -/* */ - -enum sh_mobile_i2c_op { - OP_START = 0, - OP_TX_FIRST, - OP_TX, - OP_TX_STOP, - OP_TX_TO_RX, - OP_RX, - OP_RX_STOP, - OP_RX_STOP_DATA, -}; - -struct sh_mobile_i2c_data { - struct device *dev; - void __iomem *reg; - struct i2c_adapter adap; - unsigned long bus_speed; - struct clk *clk; - u_int8_t icic; - u_int8_t iccl; - u_int8_t icch; - u_int8_t flags; - - spinlock_t lock; - wait_queue_head_t wait; - struct i2c_msg *msg; - int pos; - int sr; -}; - -#define IIC_FLAG_HAS_ICIC67 (1 << 0) - -#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */ - -/* Register offsets */ -#define ICDR 0x00 -#define ICCR 0x04 -#define ICSR 0x08 -#define ICIC 0x0c -#define ICCL 0x10 -#define ICCH 0x14 - -/* Register bits */ -#define ICCR_ICE 0x80 -#define ICCR_RACK 0x40 -#define ICCR_TRS 0x10 -#define ICCR_BBSY 0x04 -#define ICCR_SCP 0x01 - -#define ICSR_SCLM 0x80 -#define ICSR_SDAM 0x40 -#define SW_DONE 0x20 -#define ICSR_BUSY 0x10 -#define ICSR_AL 0x08 -#define ICSR_TACK 0x04 -#define ICSR_WAIT 0x02 -#define ICSR_DTE 0x01 - -#define ICIC_ICCLB8 0x80 -#define ICIC_ICCHB8 0x40 -#define ICIC_ALE 0x08 -#define ICIC_TACKE 0x04 -#define ICIC_WAITE 0x02 -#define ICIC_DTEE 0x01 - -static void iic_wr(struct sh_mobile_i2c_data *pd, int offs, unsigned char data) -{ - if (offs == ICIC) - data |= pd->icic; - - iowrite8(data, pd->reg + offs); -} - -static unsigned char iic_rd(struct sh_mobile_i2c_data *pd, int offs) -{ - return ioread8(pd->reg + offs); -} - -static void iic_set_clr(struct sh_mobile_i2c_data *pd, int offs, - unsigned char set, unsigned char clr) -{ - iic_wr(pd, offs, (iic_rd(pd, offs) | set) & ~clr); -} - -static void activate_ch(struct sh_mobile_i2c_data *pd) -{ - unsigned long i2c_clk; - u_int32_t num; - u_int32_t denom; - u_int32_t tmp; - - /* Wake up device and enable clock */ - pm_runtime_get_sync(pd->dev); - clk_enable(pd->clk); - - /* Get clock rate after clock is enabled */ - i2c_clk = clk_get_rate(pd->clk); - - /* Calculate the value for iccl. From the data sheet: - * iccl = (p clock / transfer rate) * (L / (L + H)) - * where L and H are the SCL low/high ratio (5/4 in this case). - * We also round off the result. - */ - num = i2c_clk * 5; - denom = pd->bus_speed * 9; - tmp = num * 10 / denom; - if (tmp % 10 >= 5) - pd->iccl = (u_int8_t)((num/denom) + 1); - else - pd->iccl = (u_int8_t)(num/denom); - - /* one more bit of ICCL in ICIC */ - if (pd->flags & IIC_FLAG_HAS_ICIC67) { - if ((num/denom) > 0xff) - pd->icic |= ICIC_ICCLB8; - else - pd->icic &= ~ICIC_ICCLB8; - } - - /* Calculate the value for icch. From the data sheet: - icch = (p clock / transfer rate) * (H / (L + H)) */ - num = i2c_clk * 4; - tmp = num * 10 / denom; - if (tmp % 10 >= 5) - pd->icch = (u_int8_t)((num/denom) + 1); - else - pd->icch = (u_int8_t)(num/denom); - - /* one more bit of ICCH in ICIC */ - if (pd->flags & IIC_FLAG_HAS_ICIC67) { - if ((num/denom) > 0xff) - pd->icic |= ICIC_ICCHB8; - else - pd->icic &= ~ICIC_ICCHB8; - } - - /* Enable channel and configure rx ack */ - iic_set_clr(pd, ICCR, ICCR_ICE, 0); - - /* Mask all interrupts */ - iic_wr(pd, ICIC, 0); - - /* Set the clock */ - iic_wr(pd, ICCL, pd->iccl); - iic_wr(pd, ICCH, pd->icch); -} - -static void deactivate_ch(struct sh_mobile_i2c_data *pd) -{ - /* Clear/disable interrupts */ - iic_wr(pd, ICSR, 0); - iic_wr(pd, ICIC, 0); - - /* Disable channel */ - iic_set_clr(pd, ICCR, 0, ICCR_ICE); - - /* Disable clock and mark device as idle */ - clk_disable(pd->clk); - pm_runtime_put_sync(pd->dev); -} - -static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, - enum sh_mobile_i2c_op op, unsigned char data) -{ - unsigned char ret = 0; - unsigned long flags; - - dev_dbg(pd->dev, "op %d, data in 0x%02x\n", op, data); - - spin_lock_irqsave(&pd->lock, flags); - - switch (op) { - case OP_START: /* issue start and trigger DTE interrupt */ - iic_wr(pd, ICCR, 0x94); - break; - case OP_TX_FIRST: /* disable DTE interrupt and write data */ - iic_wr(pd, ICIC, ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - iic_wr(pd, ICDR, data); - break; - case OP_TX: /* write data */ - iic_wr(pd, ICDR, data); - break; - case OP_TX_STOP: /* write data and issue a stop afterwards */ - iic_wr(pd, ICDR, data); - iic_wr(pd, ICCR, 0x90); - break; - case OP_TX_TO_RX: /* select read mode */ - iic_wr(pd, ICCR, 0x81); - break; - case OP_RX: /* just read data */ - ret = iic_rd(pd, ICDR); - break; - case OP_RX_STOP: /* enable DTE interrupt, issue stop */ - iic_wr(pd, ICIC, - ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - iic_wr(pd, ICCR, 0xc0); - break; - case OP_RX_STOP_DATA: /* enable DTE interrupt, read data, issue stop */ - iic_wr(pd, ICIC, - ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - ret = iic_rd(pd, ICDR); - iic_wr(pd, ICCR, 0xc0); - break; - } - - spin_unlock_irqrestore(&pd->lock, flags); - - dev_dbg(pd->dev, "op %d, data out 0x%02x\n", op, ret); - return ret; -} - -static int sh_mobile_i2c_is_first_byte(struct sh_mobile_i2c_data *pd) -{ - if (pd->pos == -1) - return 1; - - return 0; -} - -static int sh_mobile_i2c_is_last_byte(struct sh_mobile_i2c_data *pd) -{ - if (pd->pos == (pd->msg->len - 1)) - return 1; - - return 0; -} - -static void sh_mobile_i2c_get_data(struct sh_mobile_i2c_data *pd, - unsigned char *buf) -{ - switch (pd->pos) { - case -1: - *buf = (pd->msg->addr & 0x7f) << 1; - *buf |= (pd->msg->flags & I2C_M_RD) ? 1 : 0; - break; - default: - *buf = pd->msg->buf[pd->pos]; - } -} - -static int sh_mobile_i2c_isr_tx(struct sh_mobile_i2c_data *pd) -{ - unsigned char data; - - if (pd->pos == pd->msg->len) - return 1; - - sh_mobile_i2c_get_data(pd, &data); - - if (sh_mobile_i2c_is_last_byte(pd)) - i2c_op(pd, OP_TX_STOP, data); - else if (sh_mobile_i2c_is_first_byte(pd)) - i2c_op(pd, OP_TX_FIRST, data); - else - i2c_op(pd, OP_TX, data); - - pd->pos++; - return 0; -} - -static int sh_mobile_i2c_isr_rx(struct sh_mobile_i2c_data *pd) -{ - unsigned char data; - int real_pos; - - do { - if (pd->pos <= -1) { - sh_mobile_i2c_get_data(pd, &data); - - if (sh_mobile_i2c_is_first_byte(pd)) - i2c_op(pd, OP_TX_FIRST, data); - else - i2c_op(pd, OP_TX, data); - break; - } - - if (pd->pos == 0) { - i2c_op(pd, OP_TX_TO_RX, 0); - break; - } - - real_pos = pd->pos - 2; - - if (pd->pos == pd->msg->len) { - if (real_pos < 0) { - i2c_op(pd, OP_RX_STOP, 0); - break; - } - data = i2c_op(pd, OP_RX_STOP_DATA, 0); - } else - data = i2c_op(pd, OP_RX, 0); - - if (real_pos >= 0) - pd->msg->buf[real_pos] = data; - } while (0); - - pd->pos++; - return pd->pos == (pd->msg->len + 2); -} - -static irqreturn_t sh_mobile_i2c_isr(int irq, void *dev_id) -{ - struct platform_device *dev = dev_id; - struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); - unsigned char sr; - int wakeup; - - sr = iic_rd(pd, ICSR); - pd->sr |= sr; /* remember state */ - - dev_dbg(pd->dev, "i2c_isr 0x%02x 0x%02x %s %d %d!\n", sr, pd->sr, - (pd->msg->flags & I2C_M_RD) ? "read" : "write", - pd->pos, pd->msg->len); - - if (sr & (ICSR_AL | ICSR_TACK)) { - /* don't interrupt transaction - continue to issue stop */ - iic_wr(pd, ICSR, sr & ~(ICSR_AL | ICSR_TACK)); - wakeup = 0; - } else if (pd->msg->flags & I2C_M_RD) - wakeup = sh_mobile_i2c_isr_rx(pd); - else - wakeup = sh_mobile_i2c_isr_tx(pd); - - if (sr & ICSR_WAIT) /* TODO: add delay here to support slow acks */ - iic_wr(pd, ICSR, sr & ~ICSR_WAIT); - - if (wakeup) { - pd->sr |= SW_DONE; - wake_up(&pd->wait); - } - - return IRQ_HANDLED; -} - -static int start_ch(struct sh_mobile_i2c_data *pd, struct i2c_msg *usr_msg) -{ - if (usr_msg->len == 0 && (usr_msg->flags & I2C_M_RD)) { - dev_err(pd->dev, "Unsupported zero length i2c read\n"); - return -EIO; - } - - /* Initialize channel registers */ - iic_set_clr(pd, ICCR, 0, ICCR_ICE); - - /* Enable channel and configure rx ack */ - iic_set_clr(pd, ICCR, ICCR_ICE, 0); - - /* Set the clock */ - iic_wr(pd, ICCL, pd->iccl); - iic_wr(pd, ICCH, pd->icch); - - pd->msg = usr_msg; - pd->pos = -1; - pd->sr = 0; - - /* Enable all interrupts to begin with */ - iic_wr(pd, ICIC, ICIC_DTEE | ICIC_WAITE | ICIC_ALE | ICIC_TACKE); - return 0; -} - -static int sh_mobile_i2c_xfer(struct i2c_adapter *adapter, - struct i2c_msg *msgs, - int num) -{ - struct sh_mobile_i2c_data *pd = i2c_get_adapdata(adapter); - struct i2c_msg *msg; - int err = 0; - u_int8_t val; - int i, k, retry_count; - - activate_ch(pd); - - /* Process all messages */ - for (i = 0; i < num; i++) { - msg = &msgs[i]; - - err = start_ch(pd, msg); - if (err) - break; - - i2c_op(pd, OP_START, 0); - - /* The interrupt handler takes care of the rest... */ - k = wait_event_timeout(pd->wait, - pd->sr & (ICSR_TACK | SW_DONE), - 5 * HZ); - if (!k) - dev_err(pd->dev, "Transfer request timed out\n"); - - retry_count = 1000; -again: - val = iic_rd(pd, ICSR); - - dev_dbg(pd->dev, "val 0x%02x pd->sr 0x%02x\n", val, pd->sr); - - /* the interrupt handler may wake us up before the - * transfer is finished, so poll the hardware - * until we're done. - */ - if (val & ICSR_BUSY) { - udelay(10); - if (retry_count--) - goto again; - - err = -EIO; - dev_err(pd->dev, "Polling timed out\n"); - break; - } - - /* handle missing acknowledge and arbitration lost */ - if ((val | pd->sr) & (ICSR_TACK | ICSR_AL)) { - err = -EIO; - break; - } - } - - deactivate_ch(pd); - - if (!err) - err = num; - return err; -} - -static u32 sh_mobile_i2c_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static struct i2c_algorithm sh_mobile_i2c_algorithm = { - .functionality = sh_mobile_i2c_func, - .master_xfer = sh_mobile_i2c_xfer, -}; - -static int sh_mobile_i2c_hook_irqs(struct platform_device *dev, int hook) -{ - struct resource *res; - int ret = -ENXIO; - int n, k = 0; - - while ((res = platform_get_resource(dev, IORESOURCE_IRQ, k))) { - for (n = res->start; hook && n <= res->end; n++) { - if (request_irq(n, sh_mobile_i2c_isr, 0, - dev_name(&dev->dev), dev)) { - for (n--; n >= res->start; n--) - free_irq(n, dev); - - goto rollback; - } - } - k++; - } - - if (hook) - return k > 0 ? 0 : -ENOENT; - - ret = 0; - - rollback: - k--; - - while (k >= 0) { - res = platform_get_resource(dev, IORESOURCE_IRQ, k); - for (n = res->start; n <= res->end; n++) - free_irq(n, dev); - - k--; - } - - return ret; -} - -static int sh_mobile_i2c_probe(struct platform_device *dev) -{ - struct i2c_sh_mobile_platform_data *pdata = dev->dev.platform_data; - struct sh_mobile_i2c_data *pd; - struct i2c_adapter *adap; - struct resource *res; - int size; - int ret; - - pd = kzalloc(sizeof(struct sh_mobile_i2c_data), GFP_KERNEL); - if (pd == NULL) { - dev_err(&dev->dev, "cannot allocate private data\n"); - return -ENOMEM; - } - - pd->clk = clk_get(&dev->dev, NULL); - if (IS_ERR(pd->clk)) { - dev_err(&dev->dev, "cannot get clock\n"); - ret = PTR_ERR(pd->clk); - goto err; - } - - ret = sh_mobile_i2c_hook_irqs(dev, 1); - if (ret) { - dev_err(&dev->dev, "cannot request IRQ\n"); - goto err_clk; - } - - pd->dev = &dev->dev; - platform_set_drvdata(dev, pd); - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&dev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_irq; - } - - size = resource_size(res); - - pd->reg = ioremap(res->start, size); - if (pd->reg == NULL) { - dev_err(&dev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_irq; - } - - /* Use platformd data bus speed or NORMAL_SPEED */ - pd->bus_speed = NORMAL_SPEED; - if (pdata && pdata->bus_speed) - pd->bus_speed = pdata->bus_speed; - - /* The IIC blocks on SH-Mobile ARM processors - * come with two new bits in ICIC. - */ - if (size > 0x17) - pd->flags |= IIC_FLAG_HAS_ICIC67; - - /* Enable Runtime PM for this device. - * - * Also tell the Runtime PM core to ignore children - * for this device since it is valid for us to suspend - * this I2C master driver even though the slave devices - * on the I2C bus may not be suspended. - * - * The state of the I2C hardware bus is unaffected by - * the Runtime PM state. - */ - pm_suspend_ignore_children(&dev->dev, true); - pm_runtime_enable(&dev->dev); - - /* setup the private data */ - adap = &pd->adap; - i2c_set_adapdata(adap, pd); - - adap->owner = THIS_MODULE; - adap->algo = &sh_mobile_i2c_algorithm; - adap->dev.parent = &dev->dev; - adap->retries = 5; - adap->nr = dev->id; - - strlcpy(adap->name, dev->name, sizeof(adap->name)); - - spin_lock_init(&pd->lock); - init_waitqueue_head(&pd->wait); - - ret = i2c_add_numbered_adapter(adap); - if (ret < 0) { - dev_err(&dev->dev, "cannot add numbered adapter\n"); - goto err_all; - } - - dev_info(&dev->dev, "I2C adapter %d with bus speed %lu Hz\n", - adap->nr, pd->bus_speed); - return 0; - - err_all: - iounmap(pd->reg); - err_irq: - sh_mobile_i2c_hook_irqs(dev, 0); - err_clk: - clk_put(pd->clk); - err: - kfree(pd); - return ret; -} - -static int sh_mobile_i2c_remove(struct platform_device *dev) -{ - struct sh_mobile_i2c_data *pd = platform_get_drvdata(dev); - - i2c_del_adapter(&pd->adap); - iounmap(pd->reg); - sh_mobile_i2c_hook_irqs(dev, 0); - clk_put(pd->clk); - pm_runtime_disable(&dev->dev); - kfree(pd); - return 0; -} - -static int sh_mobile_i2c_runtime_nop(struct device *dev) -{ - /* Runtime PM callback shared between ->runtime_suspend() - * and ->runtime_resume(). Simply returns success. - * - * This driver re-initializes all registers after - * pm_runtime_get_sync() anyway so there is no need - * to save and restore registers here. - */ - return 0; -} - -static const struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { - .runtime_suspend = sh_mobile_i2c_runtime_nop, - .runtime_resume = sh_mobile_i2c_runtime_nop, -}; - -static struct platform_driver sh_mobile_i2c_driver = { - .driver = { - .name = "i2c-sh_mobile", - .owner = THIS_MODULE, - .pm = &sh_mobile_i2c_dev_pm_ops, - }, - .probe = sh_mobile_i2c_probe, - .remove = sh_mobile_i2c_remove, -}; - -static int __init sh_mobile_i2c_adap_init(void) -{ - return platform_driver_register(&sh_mobile_i2c_driver); -} - -static void __exit sh_mobile_i2c_adap_exit(void) -{ - platform_driver_unregister(&sh_mobile_i2c_driver); -} - -subsys_initcall(sh_mobile_i2c_adap_init); -module_exit(sh_mobile_i2c_adap_exit); - -MODULE_DESCRIPTION("SuperH Mobile I2C Bus Controller driver"); -MODULE_AUTHOR("Magnus Damm"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:i2c-sh_mobile"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sibyte.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sibyte.c deleted file mode 100644 index 0fe505d7..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sibyte.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2004 Steven J. Hill - * Copyright (C) 2001,2002,2003 Broadcom Corporation - * Copyright (C) 1995-2000 Simon G. Vogl - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <asm/sibyte/sb1250_regs.h> -#include <asm/sibyte/sb1250_smbus.h> - - -struct i2c_algo_sibyte_data { - void *data; /* private data */ - int bus; /* which bus */ - void *reg_base; /* CSR base */ -}; - -/* ----- global defines ----------------------------------------------- */ -#define SMB_CSR(a,r) ((long)(a->reg_base + r)) - - -static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; - int data_bytes = 0; - int error; - - while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) - ; - - switch (size) { - case I2C_SMBUS_QUICK: - csr_out32((V_SMB_ADDR(addr) | - (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) | - V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START)); - break; - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_READ) { - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE), - SMB_CSR(adap, R_SMB_START)); - data_bytes = 1; - } else { - csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE), - SMB_CSR(adap, R_SMB_START)); - } - break; - case I2C_SMBUS_BYTE_DATA: - csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); - if (read_write == I2C_SMBUS_READ) { - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE), - SMB_CSR(adap, R_SMB_START)); - data_bytes = 1; - } else { - csr_out32(V_SMB_LB(data->byte), - SMB_CSR(adap, R_SMB_DATA)); - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE), - SMB_CSR(adap, R_SMB_START)); - } - break; - case I2C_SMBUS_WORD_DATA: - csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD)); - if (read_write == I2C_SMBUS_READ) { - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE), - SMB_CSR(adap, R_SMB_START)); - data_bytes = 2; - } else { - csr_out32(V_SMB_LB(data->word & 0xff), - SMB_CSR(adap, R_SMB_DATA)); - csr_out32(V_SMB_MB(data->word >> 8), - SMB_CSR(adap, R_SMB_DATA)); - csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE), - SMB_CSR(adap, R_SMB_START)); - } - break; - default: - return -EOPNOTSUPP; - } - - while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY) - ; - - error = csr_in32(SMB_CSR(adap, R_SMB_STATUS)); - if (error & M_SMB_ERROR) { - /* Clear error bit by writing a 1 */ - csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS)); - return (error & M_SMB_ERROR_TYPE) ? -EIO : -ENXIO; - } - - if (data_bytes == 1) - data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff; - if (data_bytes == 2) - data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff; - - return 0; -} - -static u32 bit_func(struct i2c_adapter *adap) -{ - return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA); -} - - -/* -----exported algorithm data: ------------------------------------- */ - -static const struct i2c_algorithm i2c_sibyte_algo = { - .smbus_xfer = smbus_xfer, - .functionality = bit_func, -}; - -/* - * registering functions to load algorithms at runtime - */ -static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed) -{ - struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data; - - /* Register new adapter to i2c module... */ - i2c_adap->algo = &i2c_sibyte_algo; - - /* Set the requested frequency. */ - csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ)); - csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL)); - - return i2c_add_numbered_adapter(i2c_adap); -} - - -static struct i2c_algo_sibyte_data sibyte_board_data[2] = { - { NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) }, - { NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) } -}; - -static struct i2c_adapter sibyte_board_adapter[2] = { - { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = NULL, - .algo_data = &sibyte_board_data[0], - .nr = 0, - .name = "SiByte SMBus 0", - }, - { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = NULL, - .algo_data = &sibyte_board_data[1], - .nr = 1, - .name = "SiByte SMBus 1", - }, -}; - -static int __init i2c_sibyte_init(void) -{ - pr_info("i2c-sibyte: i2c SMBus adapter module for SiByte board\n"); - if (i2c_sibyte_add_bus(&sibyte_board_adapter[0], K_SMB_FREQ_100KHZ) < 0) - return -ENODEV; - if (i2c_sibyte_add_bus(&sibyte_board_adapter[1], - K_SMB_FREQ_400KHZ) < 0) { - i2c_del_adapter(&sibyte_board_adapter[0]); - return -ENODEV; - } - return 0; -} - -static void __exit i2c_sibyte_exit(void) -{ - i2c_del_adapter(&sibyte_board_adapter[0]); - i2c_del_adapter(&sibyte_board_adapter[1]); -} - -module_init(i2c_sibyte_init); -module_exit(i2c_sibyte_exit); - -MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>"); -MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-simtec.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-simtec.c deleted file mode 100644 index 4fc87e7c..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-simtec.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright (C) 2005 Simtec Electronics - * Ben Dooks <ben@simtec.co.uk> - * - * Simtec Generic I2C Controller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/io.h> - -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> - -struct simtec_i2c_data { - struct resource *ioarea; - void __iomem *reg; - struct i2c_adapter adap; - struct i2c_algo_bit_data bit; -}; - -#define CMD_SET_SDA (1<<2) -#define CMD_SET_SCL (1<<3) - -#define STATE_SDA (1<<0) -#define STATE_SCL (1<<1) - -/* i2c bit-bus functions */ - -static void simtec_i2c_setsda(void *pw, int state) -{ - struct simtec_i2c_data *pd = pw; - writeb(CMD_SET_SDA | (state ? STATE_SDA : 0), pd->reg); -} - -static void simtec_i2c_setscl(void *pw, int state) -{ - struct simtec_i2c_data *pd = pw; - writeb(CMD_SET_SCL | (state ? STATE_SCL : 0), pd->reg); -} - -static int simtec_i2c_getsda(void *pw) -{ - struct simtec_i2c_data *pd = pw; - return readb(pd->reg) & STATE_SDA ? 1 : 0; -} - -static int simtec_i2c_getscl(void *pw) -{ - struct simtec_i2c_data *pd = pw; - return readb(pd->reg) & STATE_SCL ? 1 : 0; -} - -/* device registration */ - -static int simtec_i2c_probe(struct platform_device *dev) -{ - struct simtec_i2c_data *pd; - struct resource *res; - int size; - int ret; - - pd = kzalloc(sizeof(struct simtec_i2c_data), GFP_KERNEL); - if (pd == NULL) { - dev_err(&dev->dev, "cannot allocate private data\n"); - return -ENOMEM; - } - - platform_set_drvdata(dev, pd); - - res = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&dev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err; - } - - size = resource_size(res); - - pd->ioarea = request_mem_region(res->start, size, dev->name); - if (pd->ioarea == NULL) { - dev_err(&dev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err; - } - - pd->reg = ioremap(res->start, size); - if (pd->reg == NULL) { - dev_err(&dev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_res; - } - - /* setup the private data */ - - pd->adap.owner = THIS_MODULE; - pd->adap.algo_data = &pd->bit; - pd->adap.dev.parent = &dev->dev; - - strlcpy(pd->adap.name, "Simtec I2C", sizeof(pd->adap.name)); - - pd->bit.data = pd; - pd->bit.setsda = simtec_i2c_setsda; - pd->bit.setscl = simtec_i2c_setscl; - pd->bit.getsda = simtec_i2c_getsda; - pd->bit.getscl = simtec_i2c_getscl; - pd->bit.timeout = HZ; - pd->bit.udelay = 20; - - ret = i2c_bit_add_bus(&pd->adap); - if (ret) - goto err_all; - - return 0; - - err_all: - iounmap(pd->reg); - - err_res: - release_resource(pd->ioarea); - kfree(pd->ioarea); - - err: - kfree(pd); - return ret; -} - -static int simtec_i2c_remove(struct platform_device *dev) -{ - struct simtec_i2c_data *pd = platform_get_drvdata(dev); - - i2c_del_adapter(&pd->adap); - - iounmap(pd->reg); - release_resource(pd->ioarea); - kfree(pd->ioarea); - kfree(pd); - - return 0; -} - -/* device driver */ - -static struct platform_driver simtec_i2c_driver = { - .driver = { - .name = "simtec-i2c", - .owner = THIS_MODULE, - }, - .probe = simtec_i2c_probe, - .remove = simtec_i2c_remove, -}; - -module_platform_driver(simtec_i2c_driver); - -MODULE_DESCRIPTION("Simtec Generic I2C Bus driver"); -MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:simtec-i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sirf.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sirf.c deleted file mode 100644 index 5574a477..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sirf.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * I2C bus driver for CSR SiRFprimaII - * - * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company. - * - * Licensed under GPLv2 or later. - */ - -#include <linux/interrupt.h> -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/io.h> - -#define SIRFSOC_I2C_CLK_CTRL 0x00 -#define SIRFSOC_I2C_STATUS 0x0C -#define SIRFSOC_I2C_CTRL 0x10 -#define SIRFSOC_I2C_IO_CTRL 0x14 -#define SIRFSOC_I2C_SDA_DELAY 0x18 -#define SIRFSOC_I2C_CMD_START 0x1C -#define SIRFSOC_I2C_CMD_BUF 0x30 -#define SIRFSOC_I2C_DATA_BUF 0x80 - -#define SIRFSOC_I2C_CMD_BUF_MAX 16 -#define SIRFSOC_I2C_DATA_BUF_MAX 16 - -#define SIRFSOC_I2C_CMD(x) (SIRFSOC_I2C_CMD_BUF + (x)*0x04) -#define SIRFSOC_I2C_DATA_MASK(x) (0xFF<<(((x)&3)*8)) -#define SIRFSOC_I2C_DATA_SHIFT(x) (((x)&3)*8) - -#define SIRFSOC_I2C_DIV_MASK (0xFFFF) - -/* I2C status flags */ -#define SIRFSOC_I2C_STAT_BUSY BIT(0) -#define SIRFSOC_I2C_STAT_TIP BIT(1) -#define SIRFSOC_I2C_STAT_NACK BIT(2) -#define SIRFSOC_I2C_STAT_TR_INT BIT(4) -#define SIRFSOC_I2C_STAT_STOP BIT(6) -#define SIRFSOC_I2C_STAT_CMD_DONE BIT(8) -#define SIRFSOC_I2C_STAT_ERR BIT(9) -#define SIRFSOC_I2C_CMD_INDEX (0x1F<<16) - -/* I2C control flags */ -#define SIRFSOC_I2C_RESET BIT(0) -#define SIRFSOC_I2C_CORE_EN BIT(1) -#define SIRFSOC_I2C_MASTER_MODE BIT(2) -#define SIRFSOC_I2C_CMD_DONE_EN BIT(11) -#define SIRFSOC_I2C_ERR_INT_EN BIT(12) - -#define SIRFSOC_I2C_SDA_DELAY_MASK (0xFF) -#define SIRFSOC_I2C_SCLF_FILTER (3<<8) - -#define SIRFSOC_I2C_START_CMD BIT(0) - -#define SIRFSOC_I2C_CMD_RP(x) ((x)&0x7) -#define SIRFSOC_I2C_NACK BIT(3) -#define SIRFSOC_I2C_WRITE BIT(4) -#define SIRFSOC_I2C_READ BIT(5) -#define SIRFSOC_I2C_STOP BIT(6) -#define SIRFSOC_I2C_START BIT(7) - -#define SIRFSOC_I2C_DEFAULT_SPEED 100000 - -struct sirfsoc_i2c { - void __iomem *base; - struct clk *clk; - u32 cmd_ptr; /* Current position in CMD buffer */ - u8 *buf; /* Buffer passed by user */ - u32 msg_len; /* Message length */ - u32 finished_len; /* number of bytes read/written */ - u32 read_cmd_len; /* number of read cmd sent */ - int msg_read; /* 1 indicates a read message */ - int err_status; /* 1 indicates an error on bus */ - - u32 sda_delay; /* For suspend/resume */ - u32 clk_div; - int last; /* Last message in transfer, STOP cmd can be sent */ - - struct completion done; /* indicates completion of message transfer */ - struct i2c_adapter adapter; -}; - -static void i2c_sirfsoc_read_data(struct sirfsoc_i2c *siic) -{ - u32 data = 0; - int i; - - for (i = 0; i < siic->read_cmd_len; i++) { - if (!(i & 0x3)) - data = readl(siic->base + SIRFSOC_I2C_DATA_BUF + i); - siic->buf[siic->finished_len++] = - (u8)((data & SIRFSOC_I2C_DATA_MASK(i)) >> - SIRFSOC_I2C_DATA_SHIFT(i)); - } -} - -static void i2c_sirfsoc_queue_cmd(struct sirfsoc_i2c *siic) -{ - u32 regval; - int i = 0; - - if (siic->msg_read) { - while (((siic->finished_len + i) < siic->msg_len) - && (siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX)) { - regval = SIRFSOC_I2C_READ | SIRFSOC_I2C_CMD_RP(0); - if (((siic->finished_len + i) == - (siic->msg_len - 1)) && siic->last) - regval |= SIRFSOC_I2C_STOP | SIRFSOC_I2C_NACK; - writel(regval, - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - i++; - } - - siic->read_cmd_len = i; - } else { - while ((siic->cmd_ptr < SIRFSOC_I2C_CMD_BUF_MAX - 1) - && (siic->finished_len < siic->msg_len)) { - regval = SIRFSOC_I2C_WRITE | SIRFSOC_I2C_CMD_RP(0); - if ((siic->finished_len == (siic->msg_len - 1)) - && siic->last) - regval |= SIRFSOC_I2C_STOP; - writel(regval, - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - writel(siic->buf[siic->finished_len++], - siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - } - } - siic->cmd_ptr = 0; - - /* Trigger the transfer */ - writel(SIRFSOC_I2C_START_CMD, siic->base + SIRFSOC_I2C_CMD_START); -} - -static irqreturn_t i2c_sirfsoc_irq(int irq, void *dev_id) -{ - struct sirfsoc_i2c *siic = (struct sirfsoc_i2c *)dev_id; - u32 i2c_stat = readl(siic->base + SIRFSOC_I2C_STATUS); - - if (i2c_stat & SIRFSOC_I2C_STAT_ERR) { - /* Error conditions */ - siic->err_status = 1; - writel(SIRFSOC_I2C_STAT_ERR, siic->base + SIRFSOC_I2C_STATUS); - - if (i2c_stat & SIRFSOC_I2C_STAT_NACK) - dev_err(&siic->adapter.dev, "ACK not received\n"); - else - dev_err(&siic->adapter.dev, "I2C error\n"); - - complete(&siic->done); - } else if (i2c_stat & SIRFSOC_I2C_STAT_CMD_DONE) { - /* CMD buffer execution complete */ - if (siic->msg_read) - i2c_sirfsoc_read_data(siic); - if (siic->finished_len == siic->msg_len) - complete(&siic->done); - else /* Fill a new CMD buffer for left data */ - i2c_sirfsoc_queue_cmd(siic); - - writel(SIRFSOC_I2C_STAT_CMD_DONE, siic->base + SIRFSOC_I2C_STATUS); - } - - return IRQ_HANDLED; -} - -static void i2c_sirfsoc_set_address(struct sirfsoc_i2c *siic, - struct i2c_msg *msg) -{ - unsigned char addr; - u32 regval = SIRFSOC_I2C_START | SIRFSOC_I2C_CMD_RP(0) | SIRFSOC_I2C_WRITE; - - /* no data and last message -> add STOP */ - if (siic->last && (msg->len == 0)) - regval |= SIRFSOC_I2C_STOP; - - writel(regval, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); - - addr = msg->addr << 1; /* Generate address */ - if (msg->flags & I2C_M_RD) - addr |= 1; - - writel(addr, siic->base + SIRFSOC_I2C_CMD(siic->cmd_ptr++)); -} - -static int i2c_sirfsoc_xfer_msg(struct sirfsoc_i2c *siic, struct i2c_msg *msg) -{ - u32 regval = readl(siic->base + SIRFSOC_I2C_CTRL); - /* timeout waiting for the xfer to finish or fail */ - int timeout = msecs_to_jiffies((msg->len + 1) * 50); - int ret = 0; - - i2c_sirfsoc_set_address(siic, msg); - - writel(regval | SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN, - siic->base + SIRFSOC_I2C_CTRL); - i2c_sirfsoc_queue_cmd(siic); - - if (wait_for_completion_timeout(&siic->done, timeout) == 0) { - siic->err_status = 1; - dev_err(&siic->adapter.dev, "Transfer timeout\n"); - } - - writel(regval & ~(SIRFSOC_I2C_CMD_DONE_EN | SIRFSOC_I2C_ERR_INT_EN), - siic->base + SIRFSOC_I2C_CTRL); - writel(0, siic->base + SIRFSOC_I2C_CMD_START); - - if (siic->err_status) { - writel(readl(siic->base + SIRFSOC_I2C_CTRL) | SIRFSOC_I2C_RESET, - siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - - ret = -EIO; - } - - return ret; -} - -static u32 i2c_sirfsoc_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static int i2c_sirfsoc_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) -{ - struct sirfsoc_i2c *siic = adap->algo_data; - int i, ret; - - clk_enable(siic->clk); - - for (i = 0; i < num; i++) { - siic->buf = msgs[i].buf; - siic->msg_len = msgs[i].len; - siic->msg_read = !!(msgs[i].flags & I2C_M_RD); - siic->err_status = 0; - siic->cmd_ptr = 0; - siic->finished_len = 0; - siic->last = (i == (num - 1)); - - ret = i2c_sirfsoc_xfer_msg(siic, &msgs[i]); - if (ret) { - clk_disable(siic->clk); - return ret; - } - } - - clk_disable(siic->clk); - return num; -} - -/* I2C algorithms associated with this master controller driver */ -static const struct i2c_algorithm i2c_sirfsoc_algo = { - .master_xfer = i2c_sirfsoc_xfer, - .functionality = i2c_sirfsoc_func, -}; - -static int __devinit i2c_sirfsoc_probe(struct platform_device *pdev) -{ - struct sirfsoc_i2c *siic; - struct i2c_adapter *adap; - struct resource *mem_res; - struct clk *clk; - int bitrate; - int ctrl_speed; - int irq; - - int err; - u32 regval; - - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - err = PTR_ERR(clk); - dev_err(&pdev->dev, "Clock get failed\n"); - goto err_get_clk; - } - - err = clk_prepare(clk); - if (err) { - dev_err(&pdev->dev, "Clock prepare failed\n"); - goto err_clk_prep; - } - - err = clk_enable(clk); - if (err) { - dev_err(&pdev->dev, "Clock enable failed\n"); - goto err_clk_en; - } - - ctrl_speed = clk_get_rate(clk); - - siic = devm_kzalloc(&pdev->dev, sizeof(*siic), GFP_KERNEL); - if (!siic) { - dev_err(&pdev->dev, "Can't allocate driver data\n"); - err = -ENOMEM; - goto out; - } - adap = &siic->adapter; - adap->class = I2C_CLASS_HWMON; - - mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (mem_res == NULL) { - dev_err(&pdev->dev, "Unable to get MEM resource\n"); - err = -EINVAL; - goto out; - } - - siic->base = devm_request_and_ioremap(&pdev->dev, mem_res); - if (siic->base == NULL) { - dev_err(&pdev->dev, "IO remap failed!\n"); - err = -ENOMEM; - goto out; - } - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - err = irq; - goto out; - } - err = devm_request_irq(&pdev->dev, irq, i2c_sirfsoc_irq, 0, - dev_name(&pdev->dev), siic); - if (err) - goto out; - - adap->algo = &i2c_sirfsoc_algo; - adap->algo_data = siic; - - adap->dev.parent = &pdev->dev; - adap->nr = pdev->id; - - strlcpy(adap->name, "sirfsoc-i2c", sizeof(adap->name)); - - platform_set_drvdata(pdev, adap); - init_completion(&siic->done); - - /* Controller Initalisation */ - - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - while (readl(siic->base + SIRFSOC_I2C_CTRL) & SIRFSOC_I2C_RESET) - cpu_relax(); - writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, - siic->base + SIRFSOC_I2C_CTRL); - - siic->clk = clk; - - err = of_property_read_u32(pdev->dev.of_node, - "clock-frequency", &bitrate); - if (err < 0) - bitrate = SIRFSOC_I2C_DEFAULT_SPEED; - - if (bitrate < 100000) - regval = - (2 * ctrl_speed) / (2 * bitrate * 11); - else - regval = ctrl_speed / (bitrate * 5); - - writel(regval, siic->base + SIRFSOC_I2C_CLK_CTRL); - if (regval > 0xFF) - writel(0xFF, siic->base + SIRFSOC_I2C_SDA_DELAY); - else - writel(regval, siic->base + SIRFSOC_I2C_SDA_DELAY); - - err = i2c_add_numbered_adapter(adap); - if (err < 0) { - dev_err(&pdev->dev, "Can't add new i2c adapter\n"); - goto out; - } - - clk_disable(clk); - - dev_info(&pdev->dev, " I2C adapter ready to operate\n"); - - return 0; - -out: - clk_disable(clk); -err_clk_en: - clk_unprepare(clk); -err_clk_prep: - clk_put(clk); -err_get_clk: - return err; -} - -static int __devexit i2c_sirfsoc_remove(struct platform_device *pdev) -{ - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - i2c_del_adapter(adapter); - clk_unprepare(siic->clk); - clk_put(siic->clk); - return 0; -} - -#ifdef CONFIG_PM -static int i2c_sirfsoc_suspend(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - clk_enable(siic->clk); - siic->sda_delay = readl(siic->base + SIRFSOC_I2C_SDA_DELAY); - siic->clk_div = readl(siic->base + SIRFSOC_I2C_CLK_CTRL); - clk_disable(siic->clk); - return 0; -} - -static int i2c_sirfsoc_resume(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct i2c_adapter *adapter = platform_get_drvdata(pdev); - struct sirfsoc_i2c *siic = adapter->algo_data; - - clk_enable(siic->clk); - writel(SIRFSOC_I2C_RESET, siic->base + SIRFSOC_I2C_CTRL); - writel(SIRFSOC_I2C_CORE_EN | SIRFSOC_I2C_MASTER_MODE, - siic->base + SIRFSOC_I2C_CTRL); - writel(siic->clk_div, siic->base + SIRFSOC_I2C_CLK_CTRL); - writel(siic->sda_delay, siic->base + SIRFSOC_I2C_SDA_DELAY); - clk_disable(siic->clk); - return 0; -} - -static const struct dev_pm_ops i2c_sirfsoc_pm_ops = { - .suspend = i2c_sirfsoc_suspend, - .resume = i2c_sirfsoc_resume, -}; -#endif - -static const struct of_device_id sirfsoc_i2c_of_match[] __devinitconst = { - { .compatible = "sirf,prima2-i2c", }, - {}, -}; -MODULE_DEVICE_TABLE(of, sirfsoc_i2c_of_match); - -static struct platform_driver i2c_sirfsoc_driver = { - .driver = { - .name = "sirfsoc_i2c", - .owner = THIS_MODULE, -#ifdef CONFIG_PM - .pm = &i2c_sirfsoc_pm_ops, -#endif - .of_match_table = sirfsoc_i2c_of_match, - }, - .probe = i2c_sirfsoc_probe, - .remove = __devexit_p(i2c_sirfsoc_remove), -}; -module_platform_driver(i2c_sirfsoc_driver); - -MODULE_DESCRIPTION("SiRF SoC I2C master controller driver"); -MODULE_AUTHOR("Zhiwu Song <Zhiwu.Song@csr.com>, " - "Xiangzhen Ye <Xiangzhen.Ye@csr.com>"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis5595.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis5595.c deleted file mode 100644 index 87e5126d..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis5595.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and - Philip Edelbrock <phil@netroedge.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* Note: we assume there can only be one SIS5595 with one SMBus interface */ - -/* - Note: all have mfr. ID 0x1039. - SUPPORTED PCI ID - 5595 0008 - - Note: these chips contain a 0008 device which is incompatible with the - 5595. We recognize these by the presence of the listed - "blacklist" PCI ID and refuse to load. - - NOT SUPPORTED PCI ID BLACKLIST PCI ID - 540 0008 0540 - 550 0008 0550 - 5513 0008 5511 - 5581 0008 5597 - 5582 0008 5597 - 5597 0008 5597 - 5598 0008 5597/5598 - 630 0008 0630 - 645 0008 0645 - 646 0008 0646 - 648 0008 0648 - 650 0008 0650 - 651 0008 0651 - 730 0008 0730 - 735 0008 0735 - 745 0008 0745 - 746 0008 0746 -*/ - -/* TO DO: - * Add Block Transfers (ugly, but supported by the adapter) - * Add adapter resets - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/acpi.h> -#include <linux/io.h> - -static int blacklist[] = { - PCI_DEVICE_ID_SI_540, - PCI_DEVICE_ID_SI_550, - PCI_DEVICE_ID_SI_630, - PCI_DEVICE_ID_SI_645, - PCI_DEVICE_ID_SI_646, - PCI_DEVICE_ID_SI_648, - PCI_DEVICE_ID_SI_650, - PCI_DEVICE_ID_SI_651, - PCI_DEVICE_ID_SI_730, - PCI_DEVICE_ID_SI_735, - PCI_DEVICE_ID_SI_745, - PCI_DEVICE_ID_SI_746, - PCI_DEVICE_ID_SI_5511, /* 5513 chip has the 0008 device but that ID - shows up in other chips so we use the 5511 - ID for recognition */ - PCI_DEVICE_ID_SI_5597, - PCI_DEVICE_ID_SI_5598, - 0, /* terminates the list */ -}; - -/* Length of ISA address segment */ -#define SIS5595_EXTENT 8 -/* SIS5595 SMBus registers */ -#define SMB_STS_LO 0x00 -#define SMB_STS_HI 0x01 -#define SMB_CTL_LO 0x02 -#define SMB_CTL_HI 0x03 -#define SMB_ADDR 0x04 -#define SMB_CMD 0x05 -#define SMB_PCNT 0x06 -#define SMB_CNT 0x07 -#define SMB_BYTE 0x08 -#define SMB_DEV 0x10 -#define SMB_DB0 0x11 -#define SMB_DB1 0x12 -#define SMB_HAA 0x13 - -/* PCI Address Constants */ -#define SMB_INDEX 0x38 -#define SMB_DAT 0x39 -#define SIS5595_ENABLE_REG 0x40 -#define ACPI_BASE 0x90 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SIS5595 constants */ -#define SIS5595_QUICK 0x00 -#define SIS5595_BYTE 0x02 -#define SIS5595_BYTE_DATA 0x04 -#define SIS5595_WORD_DATA 0x06 -#define SIS5595_PROC_CALL 0x08 -#define SIS5595_BLOCK_DATA 0x0A - -/* insmod parameters */ - -/* If force_addr is set to anything different from 0, we forcibly enable - the device at the given address. */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller"); - -static struct pci_driver sis5595_driver; -static unsigned short sis5595_base; -static struct pci_dev *sis5595_pdev; - -static u8 sis5595_read(u8 reg) -{ - outb(reg, sis5595_base + SMB_INDEX); - return inb(sis5595_base + SMB_DAT); -} - -static void sis5595_write(u8 reg, u8 data) -{ - outb(reg, sis5595_base + SMB_INDEX); - outb(data, sis5595_base + SMB_DAT); -} - -static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev) -{ - u16 a; - u8 val; - int *i; - int retval; - - /* Look for imposters */ - for (i = blacklist; *i != 0; i++) { - struct pci_dev *dev; - dev = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); - if (dev) { - dev_err(&SIS5595_dev->dev, "Looked for SIS5595 but found unsupported device %.4x\n", *i); - pci_dev_put(dev); - return -ENODEV; - } - } - - /* Determine the address of the SMBus areas */ - pci_read_config_word(SIS5595_dev, ACPI_BASE, &sis5595_base); - if (sis5595_base == 0 && force_addr == 0) { - dev_err(&SIS5595_dev->dev, "ACPI base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if (force_addr) - sis5595_base = force_addr & ~(SIS5595_EXTENT - 1); - dev_dbg(&SIS5595_dev->dev, "ACPI Base address: %04x\n", sis5595_base); - - /* NB: We grab just the two SMBus registers here, but this may still - * interfere with ACPI :-( */ - retval = acpi_check_region(sis5595_base + SMB_INDEX, 2, - sis5595_driver.name); - if (retval) - return retval; - - if (!request_region(sis5595_base + SMB_INDEX, 2, - sis5595_driver.name)) { - dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n", - sis5595_base + SMB_INDEX, sis5595_base + SMB_INDEX + 1); - return -ENODEV; - } - - if (force_addr) { - dev_info(&SIS5595_dev->dev, "forcing ISA address 0x%04X\n", sis5595_base); - if (pci_write_config_word(SIS5595_dev, ACPI_BASE, sis5595_base) - != PCIBIOS_SUCCESSFUL) - goto error; - if (pci_read_config_word(SIS5595_dev, ACPI_BASE, &a) - != PCIBIOS_SUCCESSFUL) - goto error; - if ((a & ~(SIS5595_EXTENT - 1)) != sis5595_base) { - /* doesn't work for some chips! */ - dev_err(&SIS5595_dev->dev, "force address failed - not supported?\n"); - goto error; - } - } - - if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) - != PCIBIOS_SUCCESSFUL) - goto error; - if ((val & 0x80) == 0) { - dev_info(&SIS5595_dev->dev, "enabling ACPI\n"); - if (pci_write_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, val | 0x80) - != PCIBIOS_SUCCESSFUL) - goto error; - if (pci_read_config_byte(SIS5595_dev, SIS5595_ENABLE_REG, &val) - != PCIBIOS_SUCCESSFUL) - goto error; - if ((val & 0x80) == 0) { - /* doesn't work for some chips? */ - dev_err(&SIS5595_dev->dev, "ACPI enable failed - not supported?\n"); - goto error; - } - } - - /* Everything is happy */ - return 0; - -error: - release_region(sis5595_base + SMB_INDEX, 2); - return -ENODEV; -} - -static int sis5595_transaction(struct i2c_adapter *adap) -{ - int temp; - int result = 0; - int timeout = 0; - - /* Make sure the SMBus host is ready to start transmitting */ - temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); - if (temp != 0x00) { - dev_dbg(&adap->dev, "SMBus busy (%04x). Resetting...\n", temp); - sis5595_write(SMB_STS_LO, temp & 0xff); - sis5595_write(SMB_STS_HI, temp >> 8); - if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) { - dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); - return -EBUSY; - } else { - dev_dbg(&adap->dev, "Successful!\n"); - } - } - - /* start the transaction by setting bit 4 */ - sis5595_write(SMB_CTL_LO, sis5595_read(SMB_CTL_LO) | 0x10); - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = sis5595_read(SMB_STS_LO); - } while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "SMBus Timeout!\n"); - result = -ETIMEDOUT; - } - - if (temp & 0x10) { - dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - result = -ENXIO; - } - - if (temp & 0x20) { - dev_err(&adap->dev, "Bus collision! SMBus may be locked until " - "next hard reset (or not...)\n"); - /* Clock stops and slave is stuck in mid-transmission */ - result = -EIO; - } - - temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); - if (temp != 0x00) { - sis5595_write(SMB_STS_LO, temp & 0xff); - sis5595_write(SMB_STS_HI, temp >> 8); - } - - temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8); - if (temp != 0x00) - dev_dbg(&adap->dev, "Failed reset at end of transaction (%02x)\n", temp); - - return result; -} - -/* Return negative errno on error. */ -static s32 sis5595_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS5595_QUICK; - break; - case I2C_SMBUS_BYTE: - sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis5595_write(SMB_CMD, command); - size = SIS5595_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis5595_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis5595_write(SMB_BYTE, data->byte); - size = SIS5595_BYTE_DATA; - break; - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis5595_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis5595_write(SMB_BYTE, data->word & 0xff); - sis5595_write(SMB_BYTE + 1, - (data->word & 0xff00) >> 8); - } - size = (size == I2C_SMBUS_PROC_CALL) ? SIS5595_PROC_CALL : SIS5595_WORD_DATA; - break; - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - sis5595_write(SMB_CTL_LO, ((size & 0x0E))); - - status = sis5595_transaction(adap); - if (status) - return status; - - if ((size != SIS5595_PROC_CALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK))) - return 0; - - - switch (size) { - case SIS5595_BYTE: - case SIS5595_BYTE_DATA: - data->byte = sis5595_read(SMB_BYTE); - break; - case SIS5595_WORD_DATA: - case SIS5595_PROC_CALL: - data->word = sis5595_read(SMB_BYTE) + (sis5595_read(SMB_BYTE + 1) << 8); - break; - } - return 0; -} - -static u32 sis5595_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_PROC_CALL; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = sis5595_access, - .functionality = sis5595_func, -}; - -static struct i2c_adapter sis5595_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(sis5595_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, sis5595_ids); - -static int __devinit sis5595_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - int err; - - if (sis5595_setup(dev)) { - dev_err(&dev->dev, "SIS5595 not detected, module not inserted.\n"); - return -ENODEV; - } - - /* set up the sysfs linkage to our parent device */ - sis5595_adapter.dev.parent = &dev->dev; - - snprintf(sis5595_adapter.name, sizeof(sis5595_adapter.name), - "SMBus SIS5595 adapter at %04x", sis5595_base + SMB_INDEX); - err = i2c_add_adapter(&sis5595_adapter); - if (err) { - release_region(sis5595_base + SMB_INDEX, 2); - return err; - } - - /* Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - sis5595_pdev = pci_dev_get(dev); - return -ENODEV; -} - -static struct pci_driver sis5595_driver = { - .name = "sis5595_smbus", - .id_table = sis5595_ids, - .probe = sis5595_probe, -}; - -static int __init i2c_sis5595_init(void) -{ - return pci_register_driver(&sis5595_driver); -} - -static void __exit i2c_sis5595_exit(void) -{ - pci_unregister_driver(&sis5595_driver); - if (sis5595_pdev) { - i2c_del_adapter(&sis5595_adapter); - release_region(sis5595_base + SMB_INDEX, 2); - pci_dev_put(sis5595_pdev); - sis5595_pdev = NULL; - } -} - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>"); -MODULE_DESCRIPTION("SIS5595 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_sis5595_init); -module_exit(i2c_sis5595_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis630.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis630.c deleted file mode 100644 index 15cf78f6..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis630.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Changes: - 24.08.2002 - Fixed the typo in sis630_access (Thanks to Mark M. Hoffman) - Changed sis630_transaction.(Thanks to Mark M. Hoffman) - 18.09.2002 - Added SIS730 as supported. - 21.09.2002 - Added high_clock module option.If this option is set - used Host Master Clock 56KHz (default 14KHz).For now we save old Host - Master Clock and after transaction completed restore (otherwise - it's confuse BIOS and hung Machine). - 24.09.2002 - Fixed typo in sis630_access - Fixed logical error by restoring of Host Master Clock - 31.07.2003 - Added block data read/write support. -*/ - -/* - Status: beta - - Supports: - SIS 630 - SIS 730 - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/acpi.h> -#include <linux/io.h> - -/* SIS630 SMBus registers */ -#define SMB_STS 0x80 /* status */ -#define SMB_EN 0x81 /* status enable */ -#define SMB_CNT 0x82 -#define SMBHOST_CNT 0x83 -#define SMB_ADDR 0x84 -#define SMB_CMD 0x85 -#define SMB_PCOUNT 0x86 /* processed count */ -#define SMB_COUNT 0x87 -#define SMB_BYTE 0x88 /* ~0x8F data byte field */ -#define SMBDEV_ADDR 0x90 -#define SMB_DB0 0x91 -#define SMB_DB1 0x92 -#define SMB_SAA 0x93 - -/* register count for request_region */ -#define SIS630_SMB_IOREGION 20 - -/* PCI address constants */ -/* acpi base address register */ -#define SIS630_ACPI_BASE_REG 0x74 -/* bios control register */ -#define SIS630_BIOS_CTL_REG 0x40 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SIS630 constants */ -#define SIS630_QUICK 0x00 -#define SIS630_BYTE 0x01 -#define SIS630_BYTE_DATA 0x02 -#define SIS630_WORD_DATA 0x03 -#define SIS630_PCALL 0x04 -#define SIS630_BLOCK_DATA 0x05 - -static struct pci_driver sis630_driver; - -/* insmod parameters */ -static bool high_clock; -static bool force; -module_param(high_clock, bool, 0); -MODULE_PARM_DESC(high_clock, "Set Host Master Clock to 56KHz (default 14KHz)."); -module_param(force, bool, 0); -MODULE_PARM_DESC(force, "Forcibly enable the SIS630. DANGEROUS!"); - -/* acpi base address */ -static unsigned short acpi_base; - -/* supported chips */ -static int supported[] = { - PCI_DEVICE_ID_SI_630, - PCI_DEVICE_ID_SI_730, - 0 /* terminates the list */ -}; - -static inline u8 sis630_read(u8 reg) -{ - return inb(acpi_base + reg); -} - -static inline void sis630_write(u8 reg, u8 data) -{ - outb(data, acpi_base + reg); -} - -static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldclock) -{ - int temp; - - /* Make sure the SMBus host is ready to start transmitting. */ - if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { - dev_dbg(&adap->dev, "SMBus busy (%02x).Resetting...\n",temp); - /* kill smbus transaction */ - sis630_write(SMBHOST_CNT, 0x20); - - if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) { - dev_dbg(&adap->dev, "Failed! (%02x)\n", temp); - return -EBUSY; - } else { - dev_dbg(&adap->dev, "Successful!\n"); - } - } - - /* save old clock, so we can prevent machine for hung */ - *oldclock = sis630_read(SMB_CNT); - - dev_dbg(&adap->dev, "saved clock 0x%02x\n", *oldclock); - - /* disable timeout interrupt , set Host Master Clock to 56KHz if requested */ - if (high_clock) - sis630_write(SMB_CNT, 0x20); - else - sis630_write(SMB_CNT, (*oldclock & ~0x40)); - - /* clear all sticky bits */ - temp = sis630_read(SMB_STS); - sis630_write(SMB_STS, temp & 0x1e); - - /* start the transaction by setting bit 4 and size */ - sis630_write(SMBHOST_CNT,0x10 | (size & 0x07)); - - return 0; -} - -static int sis630_transaction_wait(struct i2c_adapter *adap, int size) -{ - int temp, result = 0, timeout = 0; - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = sis630_read(SMB_STS); - /* check if block transmitted */ - if (size == SIS630_BLOCK_DATA && (temp & 0x10)) - break; - } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&adap->dev, "SMBus Timeout!\n"); - result = -ETIMEDOUT; - } - - if (temp & 0x02) { - dev_dbg(&adap->dev, "Error: Failed bus transaction\n"); - result = -ENXIO; - } - - if (temp & 0x04) { - dev_err(&adap->dev, "Bus collision!\n"); - result = -EIO; - /* - TBD: Datasheet say: - the software should clear this bit and restart SMBUS operation. - Should we do it or user start request again? - */ - } - - return result; -} - -static void sis630_transaction_end(struct i2c_adapter *adap, u8 oldclock) -{ - int temp = 0; - - /* clear all status "sticky" bits */ - sis630_write(SMB_STS, temp); - - dev_dbg(&adap->dev, "SMB_CNT before clock restore 0x%02x\n", sis630_read(SMB_CNT)); - - /* - * restore old Host Master Clock if high_clock is set - * and oldclock was not 56KHz - */ - if (high_clock && !(oldclock & 0x20)) - sis630_write(SMB_CNT,(sis630_read(SMB_CNT) & ~0x20)); - - dev_dbg(&adap->dev, "SMB_CNT after clock restore 0x%02x\n", sis630_read(SMB_CNT)); -} - -static int sis630_transaction(struct i2c_adapter *adap, int size) -{ - int result = 0; - u8 oldclock = 0; - - result = sis630_transaction_start(adap, size, &oldclock); - if (!result) { - result = sis630_transaction_wait(adap, size); - sis630_transaction_end(adap, oldclock); - } - - return result; -} - -static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *data, int read_write) -{ - int i, len = 0, rc = 0; - u8 oldclock = 0; - - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len < 0) - len = 0; - else if (len > 32) - len = 32; - sis630_write(SMB_COUNT, len); - for (i=1; i <= len; i++) { - dev_dbg(&adap->dev, "set data 0x%02x\n", data->block[i]); - /* set data */ - sis630_write(SMB_BYTE+(i-1)%8, data->block[i]); - if (i==8 || (len<8 && i==len)) { - dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i); - /* first transaction */ - rc = sis630_transaction_start(adap, - SIS630_BLOCK_DATA, &oldclock); - if (rc) - return rc; - } - else if ((i-1)%8 == 7 || i==len) { - dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i); - if (i>8) { - dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i); - /* - If this is not first transaction, - we must clear sticky bit. - clear SMBARY_STS - */ - sis630_write(SMB_STS,0x10); - } - rc = sis630_transaction_wait(adap, - SIS630_BLOCK_DATA); - if (rc) { - dev_dbg(&adap->dev, "trans_wait failed\n"); - break; - } - } - } - } - else { - /* read request */ - data->block[0] = len = 0; - rc = sis630_transaction_start(adap, - SIS630_BLOCK_DATA, &oldclock); - if (rc) - return rc; - do { - rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA); - if (rc) { - dev_dbg(&adap->dev, "trans_wait failed\n"); - break; - } - /* if this first transaction then read byte count */ - if (len == 0) - data->block[0] = sis630_read(SMB_COUNT); - - /* just to be sure */ - if (data->block[0] > 32) - data->block[0] = 32; - - dev_dbg(&adap->dev, "block data read len=0x%x\n", data->block[0]); - - for (i=0; i < 8 && len < data->block[0]; i++,len++) { - dev_dbg(&adap->dev, "read i=%d len=%d\n", i, len); - data->block[len+1] = sis630_read(SMB_BYTE+i); - } - - dev_dbg(&adap->dev, "clear smbary_sts len=%d i=%d\n",len,i); - - /* clear SMBARY_STS */ - sis630_write(SMB_STS,0x10); - } while(len < data->block[0]); - } - - sis630_transaction_end(adap, oldclock); - - return rc; -} - -/* Return negative errno on error. */ -static s32 sis630_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data *data) -{ - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS630_QUICK; - break; - case I2C_SMBUS_BYTE: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis630_write(SMB_CMD, command); - size = SIS630_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis630_write(SMB_BYTE, data->byte); - size = SIS630_BYTE_DATA; - break; - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis630_write(SMB_BYTE, data->word & 0xff); - sis630_write(SMB_BYTE + 1,(data->word & 0xff00) >> 8); - } - size = (size == I2C_SMBUS_PROC_CALL ? SIS630_PCALL : SIS630_WORD_DATA); - break; - case I2C_SMBUS_BLOCK_DATA: - sis630_write(SMB_ADDR,((addr & 0x7f) << 1) | (read_write & 0x01)); - sis630_write(SMB_CMD, command); - size = SIS630_BLOCK_DATA; - return sis630_block_data(adap, data, read_write); - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", - size); - return -EOPNOTSUPP; - } - - status = sis630_transaction(adap, size); - if (status) - return status; - - if ((size != SIS630_PCALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) { - return 0; - } - - switch(size) { - case SIS630_BYTE: - case SIS630_BYTE_DATA: - data->byte = sis630_read(SMB_BYTE); - break; - case SIS630_PCALL: - case SIS630_WORD_DATA: - data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8); - break; - } - - return 0; -} - -static u32 sis630_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_PROC_CALL | - I2C_FUNC_SMBUS_BLOCK_DATA; -} - -static int __devinit sis630_setup(struct pci_dev *sis630_dev) -{ - unsigned char b; - struct pci_dev *dummy = NULL; - int retval, i; - - /* check for supported SiS devices */ - for (i=0; supported[i] > 0 ; i++) { - if ((dummy = pci_get_device(PCI_VENDOR_ID_SI, supported[i], dummy))) - break; /* found */ - } - - if (dummy) { - pci_dev_put(dummy); - } - else if (force) { - dev_err(&sis630_dev->dev, "WARNING: Can't detect SIS630 compatible device, but " - "loading because of force option enabled\n"); - } - else { - return -ENODEV; - } - - /* - Enable ACPI first , so we can accsess reg 74-75 - in acpi io space and read acpi base addr - */ - if (pci_read_config_byte(sis630_dev, SIS630_BIOS_CTL_REG,&b)) { - dev_err(&sis630_dev->dev, "Error: Can't read bios ctl reg\n"); - retval = -ENODEV; - goto exit; - } - /* if ACPI already enabled , do nothing */ - if (!(b & 0x80) && - pci_write_config_byte(sis630_dev, SIS630_BIOS_CTL_REG, b | 0x80)) { - dev_err(&sis630_dev->dev, "Error: Can't enable ACPI\n"); - retval = -ENODEV; - goto exit; - } - - /* Determine the ACPI base address */ - if (pci_read_config_word(sis630_dev,SIS630_ACPI_BASE_REG,&acpi_base)) { - dev_err(&sis630_dev->dev, "Error: Can't determine ACPI base address\n"); - retval = -ENODEV; - goto exit; - } - - dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base); - - retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, - sis630_driver.name); - if (retval) - goto exit; - - /* Everything is happy, let's grab the memory and set things up. */ - if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION, - sis630_driver.name)) { - dev_err(&sis630_dev->dev, "SMBus registers 0x%04x-0x%04x already " - "in use!\n", acpi_base + SMB_STS, acpi_base + SMB_SAA); - retval = -EBUSY; - goto exit; - } - - retval = 0; - -exit: - if (retval) - acpi_base = 0; - return retval; -} - - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = sis630_access, - .functionality = sis630_func, -}; - -static struct i2c_adapter sis630_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(sis630_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, sis630_ids); - -static int __devinit sis630_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - if (sis630_setup(dev)) { - dev_err(&dev->dev, "SIS630 comp. bus not detected, module not inserted.\n"); - return -ENODEV; - } - - /* set up the sysfs linkage to our parent device */ - sis630_adapter.dev.parent = &dev->dev; - - snprintf(sis630_adapter.name, sizeof(sis630_adapter.name), - "SMBus SIS630 adapter at %04x", acpi_base + SMB_STS); - - return i2c_add_adapter(&sis630_adapter); -} - -static void __devexit sis630_remove(struct pci_dev *dev) -{ - if (acpi_base) { - i2c_del_adapter(&sis630_adapter); - release_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION); - acpi_base = 0; - } -} - - -static struct pci_driver sis630_driver = { - .name = "sis630_smbus", - .id_table = sis630_ids, - .probe = sis630_probe, - .remove = __devexit_p(sis630_remove), -}; - -static int __init i2c_sis630_init(void) -{ - return pci_register_driver(&sis630_driver); -} - - -static void __exit i2c_sis630_exit(void) -{ - pci_unregister_driver(&sis630_driver); -} - - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Alexander Malysh <amalysh@web.de>"); -MODULE_DESCRIPTION("SIS630 SMBus driver"); - -module_init(i2c_sis630_init); -module_exit(i2c_sis630_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis96x.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis96x.c deleted file mode 100644 index cc5d1494..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-sis96x.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - This module must be considered BETA unless and until - the chipset manufacturer releases a datasheet. - The register definitions are based on the SiS630. - - This module relies on quirk_sis_96x_smbus (drivers/pci/quirks.c) - for just about every machine for which users have reported. - If this module isn't detecting your 96x south bridge, have a - look there. - - We assume there can only be one SiS96x with one SMBus interface. -*/ - -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/delay.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> - -/* base address register in PCI config space */ -#define SIS96x_BAR 0x04 - -/* SiS96x SMBus registers */ -#define SMB_STS 0x00 -#define SMB_EN 0x01 -#define SMB_CNT 0x02 -#define SMB_HOST_CNT 0x03 -#define SMB_ADDR 0x04 -#define SMB_CMD 0x05 -#define SMB_PCOUNT 0x06 -#define SMB_COUNT 0x07 -#define SMB_BYTE 0x08 -#define SMB_DEV_ADDR 0x10 -#define SMB_DB0 0x11 -#define SMB_DB1 0x12 -#define SMB_SAA 0x13 - -/* register count for request_region */ -#define SMB_IOSIZE 0x20 - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* SiS96x SMBus constants */ -#define SIS96x_QUICK 0x00 -#define SIS96x_BYTE 0x01 -#define SIS96x_BYTE_DATA 0x02 -#define SIS96x_WORD_DATA 0x03 -#define SIS96x_PROC_CALL 0x04 -#define SIS96x_BLOCK_DATA 0x05 - -static struct pci_driver sis96x_driver; -static struct i2c_adapter sis96x_adapter; -static u16 sis96x_smbus_base; - -static inline u8 sis96x_read(u8 reg) -{ - return inb(sis96x_smbus_base + reg) ; -} - -static inline void sis96x_write(u8 reg, u8 data) -{ - outb(data, sis96x_smbus_base + reg) ; -} - -/* Execute a SMBus transaction. - int size is from SIS96x_QUICK to SIS96x_BLOCK_DATA - */ -static int sis96x_transaction(int size) -{ - int temp; - int result = 0; - int timeout = 0; - - dev_dbg(&sis96x_adapter.dev, "SMBus transaction %d\n", size); - - /* Make sure the SMBus host is ready to start transmitting */ - if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { - - dev_dbg(&sis96x_adapter.dev, "SMBus busy (0x%02x). " - "Resetting...\n", temp); - - /* kill the transaction */ - sis96x_write(SMB_HOST_CNT, 0x20); - - /* check it again */ - if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) { - dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp); - return -EBUSY; - } else { - dev_dbg(&sis96x_adapter.dev, "Successful\n"); - } - } - - /* Turn off timeout interrupts, set fast host clock */ - sis96x_write(SMB_CNT, 0x20); - - /* clear all (sticky) status flags */ - temp = sis96x_read(SMB_STS); - sis96x_write(SMB_STS, temp & 0x1e); - - /* start the transaction by setting bit 4 and size bits */ - sis96x_write(SMB_HOST_CNT, 0x10 | (size & 0x07)); - - /* We will always wait for a fraction of a second! */ - do { - msleep(1); - temp = sis96x_read(SMB_STS); - } while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout > MAX_TIMEOUT) { - dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp); - result = -ETIMEDOUT; - } - - /* device error - probably missing ACK */ - if (temp & 0x02) { - dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n"); - result = -ENXIO; - } - - /* bus collision */ - if (temp & 0x04) { - dev_dbg(&sis96x_adapter.dev, "Bus collision!\n"); - result = -EIO; - } - - /* Finish up by resetting the bus */ - sis96x_write(SMB_STS, temp); - if ((temp = sis96x_read(SMB_STS))) { - dev_dbg(&sis96x_adapter.dev, "Failed reset at " - "end of transaction! (0x%02x)\n", temp); - } - - return result; -} - -/* Return negative errno on error. */ -static s32 sis96x_access(struct i2c_adapter * adap, u16 addr, - unsigned short flags, char read_write, - u8 command, int size, union i2c_smbus_data * data) -{ - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - size = SIS96x_QUICK; - break; - - case I2C_SMBUS_BYTE: - sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - if (read_write == I2C_SMBUS_WRITE) - sis96x_write(SMB_CMD, command); - size = SIS96x_BYTE; - break; - - case I2C_SMBUS_BYTE_DATA: - sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis96x_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) - sis96x_write(SMB_BYTE, data->byte); - size = SIS96x_BYTE_DATA; - break; - - case I2C_SMBUS_PROC_CALL: - case I2C_SMBUS_WORD_DATA: - sis96x_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01)); - sis96x_write(SMB_CMD, command); - if (read_write == I2C_SMBUS_WRITE) { - sis96x_write(SMB_BYTE, data->word & 0xff); - sis96x_write(SMB_BYTE + 1, (data->word & 0xff00) >> 8); - } - size = (size == I2C_SMBUS_PROC_CALL ? - SIS96x_PROC_CALL : SIS96x_WORD_DATA); - break; - - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - status = sis96x_transaction(size); - if (status) - return status; - - if ((size != SIS96x_PROC_CALL) && - ((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK))) - return 0; - - switch (size) { - case SIS96x_BYTE: - case SIS96x_BYTE_DATA: - data->byte = sis96x_read(SMB_BYTE); - break; - - case SIS96x_WORD_DATA: - case SIS96x_PROC_CALL: - data->word = sis96x_read(SMB_BYTE) + - (sis96x_read(SMB_BYTE + 1) << 8); - break; - } - return 0; -} - -static u32 sis96x_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_PROC_CALL; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = sis96x_access, - .functionality = sis96x_func, -}; - -static struct i2c_adapter sis96x_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static DEFINE_PCI_DEVICE_TABLE(sis96x_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, sis96x_ids); - -static int __devinit sis96x_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 ww = 0; - int retval; - - if (sis96x_smbus_base) { - dev_err(&dev->dev, "Only one device supported.\n"); - return -EBUSY; - } - - pci_read_config_word(dev, PCI_CLASS_DEVICE, &ww); - if (PCI_CLASS_SERIAL_SMBUS != ww) { - dev_err(&dev->dev, "Unsupported device class 0x%04x!\n", ww); - return -ENODEV; - } - - sis96x_smbus_base = pci_resource_start(dev, SIS96x_BAR); - if (!sis96x_smbus_base) { - dev_err(&dev->dev, "SiS96x SMBus base address " - "not initialized!\n"); - return -EINVAL; - } - dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n", - sis96x_smbus_base); - - retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]); - if (retval) - return -ENODEV; - - /* Everything is happy, let's grab the memory and set things up. */ - if (!request_region(sis96x_smbus_base, SMB_IOSIZE, - sis96x_driver.name)) { - dev_err(&dev->dev, "SMBus registers 0x%04x-0x%04x " - "already in use!\n", sis96x_smbus_base, - sis96x_smbus_base + SMB_IOSIZE - 1); - - sis96x_smbus_base = 0; - return -EINVAL; - } - - /* set up the sysfs linkage to our parent device */ - sis96x_adapter.dev.parent = &dev->dev; - - snprintf(sis96x_adapter.name, sizeof(sis96x_adapter.name), - "SiS96x SMBus adapter at 0x%04x", sis96x_smbus_base); - - if ((retval = i2c_add_adapter(&sis96x_adapter))) { - dev_err(&dev->dev, "Couldn't register adapter!\n"); - release_region(sis96x_smbus_base, SMB_IOSIZE); - sis96x_smbus_base = 0; - } - - return retval; -} - -static void __devexit sis96x_remove(struct pci_dev *dev) -{ - if (sis96x_smbus_base) { - i2c_del_adapter(&sis96x_adapter); - release_region(sis96x_smbus_base, SMB_IOSIZE); - sis96x_smbus_base = 0; - } -} - -static struct pci_driver sis96x_driver = { - .name = "sis96x_smbus", - .id_table = sis96x_ids, - .probe = sis96x_probe, - .remove = __devexit_p(sis96x_remove), -}; - -static int __init i2c_sis96x_init(void) -{ - return pci_register_driver(&sis96x_driver); -} - -static void __exit i2c_sis96x_exit(void) -{ - pci_unregister_driver(&sis96x_driver); -} - -MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); -MODULE_DESCRIPTION("SiS96x SMBus driver"); -MODULE_LICENSE("GPL"); - -/* Register initialization functions using helper macros */ -module_init(i2c_sis96x_init); -module_exit(i2c_sis96x_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-stu300.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-stu300.c deleted file mode 100644 index 4d44af18..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-stu300.c +++ /dev/null @@ -1,1057 +0,0 @@ -/* - * Copyright (C) 2007-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * ST DDC I2C master mode driver, used in e.g. U300 series platforms. - * Author: Linus Walleij <linus.walleij@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - */ -#include <linux/init.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/i2c.h> -#include <linux/spinlock.h> -#include <linux/completion.h> -#include <linux/err.h> -#include <linux/interrupt.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/slab.h> - -/* the name of this kernel module */ -#define NAME "stu300" - -/* CR (Control Register) 8bit (R/W) */ -#define I2C_CR (0x00000000) -#define I2C_CR_RESET_VALUE (0x00) -#define I2C_CR_RESET_UMASK (0x00) -#define I2C_CR_DDC1_ENABLE (0x80) -#define I2C_CR_TRANS_ENABLE (0x40) -#define I2C_CR_PERIPHERAL_ENABLE (0x20) -#define I2C_CR_DDC2B_ENABLE (0x10) -#define I2C_CR_START_ENABLE (0x08) -#define I2C_CR_ACK_ENABLE (0x04) -#define I2C_CR_STOP_ENABLE (0x02) -#define I2C_CR_INTERRUPT_ENABLE (0x01) -/* SR1 (Status Register 1) 8bit (R/-) */ -#define I2C_SR1 (0x00000004) -#define I2C_SR1_RESET_VALUE (0x00) -#define I2C_SR1_RESET_UMASK (0x00) -#define I2C_SR1_EVF_IND (0x80) -#define I2C_SR1_ADD10_IND (0x40) -#define I2C_SR1_TRA_IND (0x20) -#define I2C_SR1_BUSY_IND (0x10) -#define I2C_SR1_BTF_IND (0x08) -#define I2C_SR1_ADSL_IND (0x04) -#define I2C_SR1_MSL_IND (0x02) -#define I2C_SR1_SB_IND (0x01) -/* SR2 (Status Register 2) 8bit (R/-) */ -#define I2C_SR2 (0x00000008) -#define I2C_SR2_RESET_VALUE (0x00) -#define I2C_SR2_RESET_UMASK (0x40) -#define I2C_SR2_MASK (0xBF) -#define I2C_SR2_SCLFAL_IND (0x80) -#define I2C_SR2_ENDAD_IND (0x20) -#define I2C_SR2_AF_IND (0x10) -#define I2C_SR2_STOPF_IND (0x08) -#define I2C_SR2_ARLO_IND (0x04) -#define I2C_SR2_BERR_IND (0x02) -#define I2C_SR2_DDC2BF_IND (0x01) -/* CCR (Clock Control Register) 8bit (R/W) */ -#define I2C_CCR (0x0000000C) -#define I2C_CCR_RESET_VALUE (0x00) -#define I2C_CCR_RESET_UMASK (0x00) -#define I2C_CCR_MASK (0xFF) -#define I2C_CCR_FMSM (0x80) -#define I2C_CCR_CC_MASK (0x7F) -/* OAR1 (Own Address Register 1) 8bit (R/W) */ -#define I2C_OAR1 (0x00000010) -#define I2C_OAR1_RESET_VALUE (0x00) -#define I2C_OAR1_RESET_UMASK (0x00) -#define I2C_OAR1_ADD_MASK (0xFF) -/* OAR2 (Own Address Register 2) 8bit (R/W) */ -#define I2C_OAR2 (0x00000014) -#define I2C_OAR2_RESET_VALUE (0x40) -#define I2C_OAR2_RESET_UMASK (0x19) -#define I2C_OAR2_MASK (0xE6) -#define I2C_OAR2_FR_25_10MHZ (0x00) -#define I2C_OAR2_FR_10_1667MHZ (0x20) -#define I2C_OAR2_FR_1667_2667MHZ (0x40) -#define I2C_OAR2_FR_2667_40MHZ (0x60) -#define I2C_OAR2_FR_40_5333MHZ (0x80) -#define I2C_OAR2_FR_5333_66MHZ (0xA0) -#define I2C_OAR2_FR_66_80MHZ (0xC0) -#define I2C_OAR2_FR_80_100MHZ (0xE0) -#define I2C_OAR2_FR_MASK (0xE0) -#define I2C_OAR2_ADD_MASK (0x06) -/* DR (Data Register) 8bit (R/W) */ -#define I2C_DR (0x00000018) -#define I2C_DR_RESET_VALUE (0x00) -#define I2C_DR_RESET_UMASK (0xFF) -#define I2C_DR_D_MASK (0xFF) -/* ECCR (Extended Clock Control Register) 8bit (R/W) */ -#define I2C_ECCR (0x0000001C) -#define I2C_ECCR_RESET_VALUE (0x00) -#define I2C_ECCR_RESET_UMASK (0xE0) -#define I2C_ECCR_MASK (0x1F) -#define I2C_ECCR_CC_MASK (0x1F) - -/* - * These events are more or less responses to commands - * sent into the hardware, presumably reflecting the state - * of an internal state machine. - */ -enum stu300_event { - STU300_EVENT_NONE = 0, - STU300_EVENT_1, - STU300_EVENT_2, - STU300_EVENT_3, - STU300_EVENT_4, - STU300_EVENT_5, - STU300_EVENT_6, - STU300_EVENT_7, - STU300_EVENT_8, - STU300_EVENT_9 -}; - -enum stu300_error { - STU300_ERROR_NONE = 0, - STU300_ERROR_ACKNOWLEDGE_FAILURE, - STU300_ERROR_BUS_ERROR, - STU300_ERROR_ARBITRATION_LOST, - STU300_ERROR_UNKNOWN -}; - -/* timeout waiting for the controller to respond */ -#define STU300_TIMEOUT (msecs_to_jiffies(1000)) - -/* - * The number of address send athemps tried before giving up. - * If the first one failes it seems like 5 to 8 attempts are required. - */ -#define NUM_ADDR_RESEND_ATTEMPTS 12 - -/* I2C clock speed, in Hz 0-400kHz*/ -static unsigned int scl_frequency = 100000; -module_param(scl_frequency, uint, 0644); - -/** - * struct stu300_dev - the stu300 driver state holder - * @pdev: parent platform device - * @adapter: corresponding I2C adapter - * @phybase: location of I/O area in memory - * @physize: size of I/O area in memory - * @clk: hardware block clock - * @irq: assigned interrupt line - * @cmd_issue_lock: this locks the following cmd_ variables - * @cmd_complete: acknowledge completion for an I2C command - * @cmd_event: expected event coming in as a response to a command - * @cmd_err: error code as response to a command - * @speed: current bus speed in Hz - * @msg_index: index of current message - * @msg_len: length of current message - */ - -struct stu300_dev { - struct platform_device *pdev; - struct i2c_adapter adapter; - resource_size_t phybase; - resource_size_t physize; - void __iomem *virtbase; - struct clk *clk; - int irq; - spinlock_t cmd_issue_lock; - struct completion cmd_complete; - enum stu300_event cmd_event; - enum stu300_error cmd_err; - unsigned int speed; - int msg_index; - int msg_len; -}; - -/* Local forward function declarations */ -static int stu300_init_hw(struct stu300_dev *dev); - -/* - * The block needs writes in both MSW and LSW in order - * for all data lines to reach their destination. - */ -static inline void stu300_wr8(u32 value, void __iomem *address) -{ - writel((value << 16) | value, address); -} - -/* - * This merely masks off the duplicates which appear - * in bytes 1-3. You _MUST_ use 32-bit bus access on this - * device, else it will not work. - */ -static inline u32 stu300_r8(void __iomem *address) -{ - return readl(address) & 0x000000FFU; -} - -static void stu300_irq_enable(struct stu300_dev *dev) -{ - u32 val; - val = stu300_r8(dev->virtbase + I2C_CR); - val |= I2C_CR_INTERRUPT_ENABLE; - /* Twice paranoia (possible HW glitch) */ - stu300_wr8(val, dev->virtbase + I2C_CR); - stu300_wr8(val, dev->virtbase + I2C_CR); -} - -static void stu300_irq_disable(struct stu300_dev *dev) -{ - u32 val; - val = stu300_r8(dev->virtbase + I2C_CR); - val &= ~I2C_CR_INTERRUPT_ENABLE; - /* Twice paranoia (possible HW glitch) */ - stu300_wr8(val, dev->virtbase + I2C_CR); - stu300_wr8(val, dev->virtbase + I2C_CR); -} - - -/* - * Tells whether a certain event or events occurred in - * response to a command. The events represent states in - * the internal state machine of the hardware. The events - * are not very well described in the hardware - * documentation and can only be treated as abstract state - * machine states. - * - * @ret 0 = event has not occurred or unknown error, any - * other value means the correct event occurred or an error. - */ - -static int stu300_event_occurred(struct stu300_dev *dev, - enum stu300_event mr_event) { - u32 status1; - u32 status2; - - /* What event happened? */ - status1 = stu300_r8(dev->virtbase + I2C_SR1); - - if (!(status1 & I2C_SR1_EVF_IND)) - /* No event at all */ - return 0; - - status2 = stu300_r8(dev->virtbase + I2C_SR2); - - /* Block any multiple interrupts */ - stu300_irq_disable(dev); - - /* Check for errors first */ - if (status2 & I2C_SR2_AF_IND) { - dev->cmd_err = STU300_ERROR_ACKNOWLEDGE_FAILURE; - return 1; - } else if (status2 & I2C_SR2_BERR_IND) { - dev->cmd_err = STU300_ERROR_BUS_ERROR; - return 1; - } else if (status2 & I2C_SR2_ARLO_IND) { - dev->cmd_err = STU300_ERROR_ARBITRATION_LOST; - return 1; - } - - switch (mr_event) { - case STU300_EVENT_1: - if (status1 & I2C_SR1_ADSL_IND) - return 1; - break; - case STU300_EVENT_2: - case STU300_EVENT_3: - case STU300_EVENT_7: - case STU300_EVENT_8: - if (status1 & I2C_SR1_BTF_IND) { - return 1; - } - break; - case STU300_EVENT_4: - if (status2 & I2C_SR2_STOPF_IND) - return 1; - break; - case STU300_EVENT_5: - if (status1 & I2C_SR1_SB_IND) - /* Clear start bit */ - return 1; - break; - case STU300_EVENT_6: - if (status2 & I2C_SR2_ENDAD_IND) { - /* First check for any errors */ - return 1; - } - break; - case STU300_EVENT_9: - if (status1 & I2C_SR1_ADD10_IND) - return 1; - break; - default: - break; - } - /* If we get here, we're on thin ice. - * Here we are in a status where we have - * gotten a response that does not match - * what we requested. - */ - dev->cmd_err = STU300_ERROR_UNKNOWN; - dev_err(&dev->pdev->dev, - "Unhandled interrupt! %d sr1: 0x%x sr2: 0x%x\n", - mr_event, status1, status2); - return 0; -} - -static irqreturn_t stu300_irh(int irq, void *data) -{ - struct stu300_dev *dev = data; - int res; - - /* Just make sure that the block is clocked */ - clk_enable(dev->clk); - - /* See if this was what we were waiting for */ - spin_lock(&dev->cmd_issue_lock); - - res = stu300_event_occurred(dev, dev->cmd_event); - if (res || dev->cmd_err != STU300_ERROR_NONE) - complete(&dev->cmd_complete); - - spin_unlock(&dev->cmd_issue_lock); - - clk_disable(dev->clk); - - return IRQ_HANDLED; -} - -/* - * Sends a command and then waits for the bits masked by *flagmask* - * to go high or low by IRQ awaiting. - */ -static int stu300_start_and_await_event(struct stu300_dev *dev, - u8 cr_value, - enum stu300_event mr_event) -{ - int ret; - - if (unlikely(irqs_disabled())) { - /* TODO: implement polling for this case if need be. */ - WARN(1, "irqs are disabled, cannot poll for event\n"); - return -EIO; - } - - /* Lock command issue, fill in an event we wait for */ - spin_lock_irq(&dev->cmd_issue_lock); - init_completion(&dev->cmd_complete); - dev->cmd_err = STU300_ERROR_NONE; - dev->cmd_event = mr_event; - spin_unlock_irq(&dev->cmd_issue_lock); - - /* Turn on interrupt, send command and wait. */ - cr_value |= I2C_CR_INTERRUPT_ENABLE; - stu300_wr8(cr_value, dev->virtbase + I2C_CR); - ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - STU300_TIMEOUT); - if (ret < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout() " - "returned %d waiting for event %04x\n", ret, mr_event); - return ret; - } - - if (ret == 0) { - dev_err(&dev->pdev->dev, "controller timed out " - "waiting for event %d, reinit hardware\n", mr_event); - (void) stu300_init_hw(dev); - return -ETIMEDOUT; - } - - if (dev->cmd_err != STU300_ERROR_NONE) { - dev_err(&dev->pdev->dev, "controller (start) " - "error %d waiting for event %d, reinit hardware\n", - dev->cmd_err, mr_event); - (void) stu300_init_hw(dev); - return -EIO; - } - - return 0; -} - -/* - * This waits for a flag to be set, if it is not set on entry, an interrupt is - * configured to wait for the flag using a completion. - */ -static int stu300_await_event(struct stu300_dev *dev, - enum stu300_event mr_event) -{ - int ret; - - if (unlikely(irqs_disabled())) { - /* TODO: implement polling for this case if need be. */ - dev_err(&dev->pdev->dev, "irqs are disabled on this " - "system!\n"); - return -EIO; - } - - /* Is it already here? */ - spin_lock_irq(&dev->cmd_issue_lock); - dev->cmd_err = STU300_ERROR_NONE; - dev->cmd_event = mr_event; - - init_completion(&dev->cmd_complete); - - /* Turn on the I2C interrupt for current operation */ - stu300_irq_enable(dev); - - /* Unlock the command block and wait for the event to occur */ - spin_unlock_irq(&dev->cmd_issue_lock); - - ret = wait_for_completion_interruptible_timeout(&dev->cmd_complete, - STU300_TIMEOUT); - if (ret < 0) { - dev_err(&dev->pdev->dev, - "wait_for_completion_interruptible_timeout()" - "returned %d waiting for event %04x\n", ret, mr_event); - return ret; - } - - if (ret == 0) { - if (mr_event != STU300_EVENT_6) { - dev_err(&dev->pdev->dev, "controller " - "timed out waiting for event %d, reinit " - "hardware\n", mr_event); - (void) stu300_init_hw(dev); - } - return -ETIMEDOUT; - } - - if (dev->cmd_err != STU300_ERROR_NONE) { - if (mr_event != STU300_EVENT_6) { - dev_err(&dev->pdev->dev, "controller " - "error (await_event) %d waiting for event %d, " - "reinit hardware\n", dev->cmd_err, mr_event); - (void) stu300_init_hw(dev); - } - return -EIO; - } - - return 0; -} - -/* - * Waits for the busy bit to go low by repeated polling. - */ -#define BUSY_RELEASE_ATTEMPTS 10 -static int stu300_wait_while_busy(struct stu300_dev *dev) -{ - unsigned long timeout; - int i; - - for (i = 0; i < BUSY_RELEASE_ATTEMPTS; i++) { - timeout = jiffies + STU300_TIMEOUT; - - while (!time_after(jiffies, timeout)) { - /* Is not busy? */ - if ((stu300_r8(dev->virtbase + I2C_SR1) & - I2C_SR1_BUSY_IND) == 0) - return 0; - msleep(1); - } - - dev_err(&dev->pdev->dev, "transaction timed out " - "waiting for device to be free (not busy). " - "Attempt: %d\n", i+1); - - dev_err(&dev->pdev->dev, "base address = " - "0x%08x, reinit hardware\n", (u32) dev->virtbase); - - (void) stu300_init_hw(dev); - } - - dev_err(&dev->pdev->dev, "giving up after %d attempts " - "to reset the bus.\n", BUSY_RELEASE_ATTEMPTS); - - return -ETIMEDOUT; -} - -struct stu300_clkset { - unsigned long rate; - u32 setting; -}; - -static const struct stu300_clkset stu300_clktable[] = { - { 0, 0xFFU }, - { 2500000, I2C_OAR2_FR_25_10MHZ }, - { 10000000, I2C_OAR2_FR_10_1667MHZ }, - { 16670000, I2C_OAR2_FR_1667_2667MHZ }, - { 26670000, I2C_OAR2_FR_2667_40MHZ }, - { 40000000, I2C_OAR2_FR_40_5333MHZ }, - { 53330000, I2C_OAR2_FR_5333_66MHZ }, - { 66000000, I2C_OAR2_FR_66_80MHZ }, - { 80000000, I2C_OAR2_FR_80_100MHZ }, - { 100000000, 0xFFU }, -}; - - -static int stu300_set_clk(struct stu300_dev *dev, unsigned long clkrate) -{ - - u32 val; - int i = 0; - - /* Locate the appropriate clock setting */ - while (i < ARRAY_SIZE(stu300_clktable) - 1 && - stu300_clktable[i].rate < clkrate) - i++; - - if (stu300_clktable[i].setting == 0xFFU) { - dev_err(&dev->pdev->dev, "too %s clock rate requested " - "(%lu Hz).\n", i ? "high" : "low", clkrate); - return -EINVAL; - } - - stu300_wr8(stu300_clktable[i].setting, - dev->virtbase + I2C_OAR2); - - dev_dbg(&dev->pdev->dev, "Clock rate %lu Hz, I2C bus speed %d Hz " - "virtbase %p\n", clkrate, dev->speed, dev->virtbase); - - if (dev->speed > 100000) - /* Fast Mode I2C */ - val = ((clkrate/dev->speed) - 9)/3 + 1; - else - /* Standard Mode I2C */ - val = ((clkrate/dev->speed) - 7)/2 + 1; - - /* According to spec the divider must be > 2 */ - if (val < 0x002) { - dev_err(&dev->pdev->dev, "too low clock rate (%lu Hz).\n", - clkrate); - return -EINVAL; - } - - /* We have 12 bits clock divider only! */ - if (val & 0xFFFFF000U) { - dev_err(&dev->pdev->dev, "too high clock rate (%lu Hz).\n", - clkrate); - return -EINVAL; - } - - if (dev->speed > 100000) { - /* CC6..CC0 */ - stu300_wr8((val & I2C_CCR_CC_MASK) | I2C_CCR_FMSM, - dev->virtbase + I2C_CCR); - dev_dbg(&dev->pdev->dev, "set clock divider to 0x%08x, " - "Fast Mode I2C\n", val); - } else { - /* CC6..CC0 */ - stu300_wr8((val & I2C_CCR_CC_MASK), - dev->virtbase + I2C_CCR); - dev_dbg(&dev->pdev->dev, "set clock divider to " - "0x%08x, Standard Mode I2C\n", val); - } - - /* CC11..CC7 */ - stu300_wr8(((val >> 7) & 0x1F), - dev->virtbase + I2C_ECCR); - - return 0; -} - - -static int stu300_init_hw(struct stu300_dev *dev) -{ - u32 dummy; - unsigned long clkrate; - int ret; - - /* Disable controller */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - /* - * Set own address to some default value (0x00). - * We do not support slave mode anyway. - */ - stu300_wr8(0x00, dev->virtbase + I2C_OAR1); - /* - * The I2C controller only operates properly in 26 MHz but we - * program this driver as if we didn't know. This will also set the two - * high bits of the own address to zero as well. - * There is no known hardware issue with running in 13 MHz - * However, speeds over 200 kHz are not used. - */ - clkrate = clk_get_rate(dev->clk); - ret = stu300_set_clk(dev, clkrate); - - if (ret) - return ret; - /* - * Enable block, do it TWICE (hardware glitch) - * Setting bit 7 can enable DDC mode. (Not used currently.) - */ - stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, - dev->virtbase + I2C_CR); - stu300_wr8(I2C_CR_PERIPHERAL_ENABLE, - dev->virtbase + I2C_CR); - /* Make a dummy read of the status register SR1 & SR2 */ - dummy = stu300_r8(dev->virtbase + I2C_SR2); - dummy = stu300_r8(dev->virtbase + I2C_SR1); - - return 0; -} - - - -/* Send slave address. */ -static int stu300_send_address(struct stu300_dev *dev, - struct i2c_msg *msg, int resend) -{ - u32 val; - int ret; - - if (msg->flags & I2C_M_TEN) - /* This is probably how 10 bit addresses look */ - val = (0xf0 | (((u32) msg->addr & 0x300) >> 7)) & - I2C_DR_D_MASK; - else - val = ((msg->addr << 1) & I2C_DR_D_MASK); - - if (msg->flags & I2C_M_RD) { - /* This is the direction bit */ - val |= 0x01; - if (resend) - dev_dbg(&dev->pdev->dev, "read resend\n"); - } else if (resend) - dev_dbg(&dev->pdev->dev, "write resend\n"); - stu300_wr8(val, dev->virtbase + I2C_DR); - - /* For 10bit addressing, await 10bit request (EVENT 9) */ - if (msg->flags & I2C_M_TEN) { - ret = stu300_await_event(dev, STU300_EVENT_9); - /* - * The slave device wants a 10bit address, send the rest - * of the bits (the LSBits) - */ - val = msg->addr & I2C_DR_D_MASK; - /* This clears "event 9" */ - stu300_wr8(val, dev->virtbase + I2C_DR); - if (ret != 0) - return ret; - } - /* FIXME: Why no else here? two events for 10bit? - * Await event 6 (normal) or event 9 (10bit) - */ - - if (resend) - dev_dbg(&dev->pdev->dev, "await event 6\n"); - ret = stu300_await_event(dev, STU300_EVENT_6); - - /* - * Clear any pending EVENT 6 no matter what happened during - * await_event. - */ - val = stu300_r8(dev->virtbase + I2C_CR); - val |= I2C_CR_PERIPHERAL_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - - return ret; -} - -static int stu300_xfer_msg(struct i2c_adapter *adap, - struct i2c_msg *msg, int stop) -{ - u32 cr; - u32 val; - u32 i; - int ret; - int attempts = 0; - struct stu300_dev *dev = i2c_get_adapdata(adap); - - clk_enable(dev->clk); - - /* Remove this if (0) to trace each and every message. */ - if (0) { - dev_dbg(&dev->pdev->dev, "I2C message to: 0x%04x, len: %d, " - "flags: 0x%04x, stop: %d\n", - msg->addr, msg->len, msg->flags, stop); - } - - /* Zero-length messages are not supported by this hardware */ - if (msg->len == 0) { - ret = -EINVAL; - goto exit_disable; - } - - /* - * For some reason, sending the address sometimes fails when running - * on the 13 MHz clock. No interrupt arrives. This is a work around, - * which tries to restart and send the address up to 10 times before - * really giving up. Usually 5 to 8 attempts are enough. - */ - do { - if (attempts) - dev_dbg(&dev->pdev->dev, "wait while busy\n"); - /* Check that the bus is free, or wait until some timeout */ - ret = stu300_wait_while_busy(dev); - if (ret != 0) - goto exit_disable; - - if (attempts) - dev_dbg(&dev->pdev->dev, "re-int hw\n"); - /* - * According to ST, there is no problem if the clock is - * changed between 13 and 26 MHz during a transfer. - */ - ret = stu300_init_hw(dev); - if (ret) - goto exit_disable; - - /* Send a start condition */ - cr = I2C_CR_PERIPHERAL_ENABLE; - /* Setting the START bit puts the block in master mode */ - if (!(msg->flags & I2C_M_NOSTART)) - cr |= I2C_CR_START_ENABLE; - if ((msg->flags & I2C_M_RD) && (msg->len > 1)) - /* On read more than 1 byte, we need ack. */ - cr |= I2C_CR_ACK_ENABLE; - /* Check that it gets through */ - if (!(msg->flags & I2C_M_NOSTART)) { - if (attempts) - dev_dbg(&dev->pdev->dev, "send start event\n"); - ret = stu300_start_and_await_event(dev, cr, - STU300_EVENT_5); - } - - if (attempts) - dev_dbg(&dev->pdev->dev, "send address\n"); - - if (ret == 0) - /* Send address */ - ret = stu300_send_address(dev, msg, attempts != 0); - - if (ret != 0) { - attempts++; - dev_dbg(&dev->pdev->dev, "failed sending address, " - "retrying. Attempt: %d msg_index: %d/%d\n", - attempts, dev->msg_index, dev->msg_len); - } - - } while (ret != 0 && attempts < NUM_ADDR_RESEND_ATTEMPTS); - - if (attempts < NUM_ADDR_RESEND_ATTEMPTS && attempts > 0) { - dev_dbg(&dev->pdev->dev, "managed to get address " - "through after %d attempts\n", attempts); - } else if (attempts == NUM_ADDR_RESEND_ATTEMPTS) { - dev_dbg(&dev->pdev->dev, "I give up, tried %d times " - "to resend address.\n", - NUM_ADDR_RESEND_ATTEMPTS); - goto exit_disable; - } - - - if (msg->flags & I2C_M_RD) { - /* READ: we read the actual bytes one at a time */ - for (i = 0; i < msg->len; i++) { - if (i == msg->len-1) { - /* - * Disable ACK and set STOP condition before - * reading last byte - */ - val = I2C_CR_PERIPHERAL_ENABLE; - - if (stop) - val |= I2C_CR_STOP_ENABLE; - - stu300_wr8(val, - dev->virtbase + I2C_CR); - } - /* Wait for this byte... */ - ret = stu300_await_event(dev, STU300_EVENT_7); - if (ret != 0) - goto exit_disable; - /* This clears event 7 */ - msg->buf[i] = (u8) stu300_r8(dev->virtbase + I2C_DR); - } - } else { - /* WRITE: we send the actual bytes one at a time */ - for (i = 0; i < msg->len; i++) { - /* Write the byte */ - stu300_wr8(msg->buf[i], - dev->virtbase + I2C_DR); - /* Check status */ - ret = stu300_await_event(dev, STU300_EVENT_8); - /* Next write to DR will clear event 8 */ - if (ret != 0) { - dev_err(&dev->pdev->dev, "error awaiting " - "event 8 (%d)\n", ret); - goto exit_disable; - } - } - /* Check NAK */ - if (!(msg->flags & I2C_M_IGNORE_NAK)) { - if (stu300_r8(dev->virtbase + I2C_SR2) & - I2C_SR2_AF_IND) { - dev_err(&dev->pdev->dev, "I2C payload " - "send returned NAK!\n"); - ret = -EIO; - goto exit_disable; - } - } - if (stop) { - /* Send stop condition */ - val = I2C_CR_PERIPHERAL_ENABLE; - val |= I2C_CR_STOP_ENABLE; - stu300_wr8(val, dev->virtbase + I2C_CR); - } - } - - /* Check that the bus is free, or wait until some timeout occurs */ - ret = stu300_wait_while_busy(dev); - if (ret != 0) { - dev_err(&dev->pdev->dev, "timout waiting for transfer " - "to commence.\n"); - goto exit_disable; - } - - /* Dummy read status registers */ - val = stu300_r8(dev->virtbase + I2C_SR2); - val = stu300_r8(dev->virtbase + I2C_SR1); - ret = 0; - - exit_disable: - /* Disable controller */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - clk_disable(dev->clk); - return ret; -} - -static int stu300_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, - int num) -{ - int ret = -1; - int i; - - struct stu300_dev *dev = i2c_get_adapdata(adap); - dev->msg_len = num; - - for (i = 0; i < num; i++) { - /* - * Another driver appears to send stop for each message, - * here we only do that for the last message. Possibly some - * peripherals require this behaviour, then their drivers - * have to send single messages in order to get "stop" for - * each message. - */ - dev->msg_index = i; - - ret = stu300_xfer_msg(adap, &msgs[i], (i == (num - 1))); - - if (ret != 0) { - num = ret; - break; - } - } - - return num; -} - -static u32 stu300_func(struct i2c_adapter *adap) -{ - /* This is the simplest thing you can think of... */ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm stu300_algo = { - .master_xfer = stu300_xfer, - .functionality = stu300_func, -}; - -static int __init -stu300_probe(struct platform_device *pdev) -{ - struct stu300_dev *dev; - struct i2c_adapter *adap; - struct resource *res; - int bus_nr; - int ret = 0; - char clk_name[] = "I2C0"; - - dev = kzalloc(sizeof(struct stu300_dev), GFP_KERNEL); - if (!dev) { - dev_err(&pdev->dev, "could not allocate device struct\n"); - ret = -ENOMEM; - goto err_no_devmem; - } - - bus_nr = pdev->id; - clk_name[3] += (char)bus_nr; - dev->clk = clk_get(&pdev->dev, clk_name); - if (IS_ERR(dev->clk)) { - ret = PTR_ERR(dev->clk); - dev_err(&pdev->dev, "could not retrieve i2c bus clock\n"); - goto err_no_clk; - } - - dev->pdev = pdev; - platform_set_drvdata(pdev, dev); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto err_no_resource; - } - - dev->phybase = res->start; - dev->physize = resource_size(res); - - if (request_mem_region(dev->phybase, dev->physize, - NAME " I/O Area") == NULL) { - ret = -EBUSY; - goto err_no_ioregion; - } - - dev->virtbase = ioremap(dev->phybase, dev->physize); - dev_dbg(&pdev->dev, "initialize bus device I2C%d on virtual " - "base %p\n", bus_nr, dev->virtbase); - if (!dev->virtbase) { - ret = -ENOMEM; - goto err_no_ioremap; - } - - dev->irq = platform_get_irq(pdev, 0); - if (request_irq(dev->irq, stu300_irh, 0, - NAME, dev)) { - ret = -EIO; - goto err_no_irq; - } - - dev->speed = scl_frequency; - - clk_enable(dev->clk); - ret = stu300_init_hw(dev); - clk_disable(dev->clk); - - if (ret != 0) { - dev_err(&dev->pdev->dev, "error initializing hardware.\n"); - goto err_init_hw; - } - - /* IRQ event handling initialization */ - spin_lock_init(&dev->cmd_issue_lock); - dev->cmd_event = STU300_EVENT_NONE; - dev->cmd_err = STU300_ERROR_NONE; - - adap = &dev->adapter; - adap->owner = THIS_MODULE; - /* DDC class but actually often used for more generic I2C */ - adap->class = I2C_CLASS_DDC; - strlcpy(adap->name, "ST Microelectronics DDC I2C adapter", - sizeof(adap->name)); - adap->nr = bus_nr; - adap->algo = &stu300_algo; - adap->dev.parent = &pdev->dev; - i2c_set_adapdata(adap, dev); - - /* i2c device drivers may be active on return from add_adapter() */ - ret = i2c_add_numbered_adapter(adap); - if (ret) { - dev_err(&dev->pdev->dev, "failure adding ST Micro DDC " - "I2C adapter\n"); - goto err_add_adapter; - } - return 0; - - err_add_adapter: - err_init_hw: - free_irq(dev->irq, dev); - err_no_irq: - iounmap(dev->virtbase); - err_no_ioremap: - release_mem_region(dev->phybase, dev->physize); - err_no_ioregion: - platform_set_drvdata(pdev, NULL); - err_no_resource: - clk_put(dev->clk); - err_no_clk: - kfree(dev); - err_no_devmem: - dev_err(&pdev->dev, "failed to add " NAME " adapter: %d\n", - pdev->id); - return ret; -} - -#ifdef CONFIG_PM -static int stu300_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct stu300_dev *dev = platform_get_drvdata(pdev); - - /* Turn off everything */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - return 0; -} - -static int stu300_resume(struct platform_device *pdev) -{ - int ret = 0; - struct stu300_dev *dev = platform_get_drvdata(pdev); - - clk_enable(dev->clk); - ret = stu300_init_hw(dev); - clk_disable(dev->clk); - - if (ret != 0) - dev_err(&pdev->dev, "error re-initializing hardware.\n"); - return ret; -} -#else -#define stu300_suspend NULL -#define stu300_resume NULL -#endif - -static int __exit -stu300_remove(struct platform_device *pdev) -{ - struct stu300_dev *dev = platform_get_drvdata(pdev); - - i2c_del_adapter(&dev->adapter); - /* Turn off everything */ - stu300_wr8(0x00, dev->virtbase + I2C_CR); - free_irq(dev->irq, dev); - iounmap(dev->virtbase); - release_mem_region(dev->phybase, dev->physize); - clk_put(dev->clk); - platform_set_drvdata(pdev, NULL); - kfree(dev); - return 0; -} - -static struct platform_driver stu300_i2c_driver = { - .driver = { - .name = NAME, - .owner = THIS_MODULE, - }, - .remove = __exit_p(stu300_remove), - .suspend = stu300_suspend, - .resume = stu300_resume, - -}; - -static int __init stu300_init(void) -{ - return platform_driver_probe(&stu300_i2c_driver, stu300_probe); -} - -static void __exit stu300_exit(void) -{ - platform_driver_unregister(&stu300_i2c_driver); -} - -/* - * The systems using this bus often have very basic devices such - * as regulators on the I2C bus, so this needs to be loaded early. - * Therefore it is registered in the subsys_initcall(). - */ -subsys_initcall(stu300_init); -module_exit(stu300_exit); - -MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>"); -MODULE_DESCRIPTION("ST Micro DDC I2C adapter (" NAME ")"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:" NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-stub.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-stub.c deleted file mode 100644 index b1b34479..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-stub.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - i2c-stub.c - I2C/SMBus chip emulator - - Copyright (c) 2004 Mark M. Hoffman <mhoffman@lightlink.com> - Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#define DEBUG 1 - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/slab.h> -#include <linux/errno.h> -#include <linux/i2c.h> - -#define MAX_CHIPS 10 -#define STUB_FUNC (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | \ - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | \ - I2C_FUNC_SMBUS_I2C_BLOCK) - -static unsigned short chip_addr[MAX_CHIPS]; -module_param_array(chip_addr, ushort, NULL, S_IRUGO); -MODULE_PARM_DESC(chip_addr, - "Chip addresses (up to 10, between 0x03 and 0x77)"); - -static unsigned long functionality = STUB_FUNC; -module_param(functionality, ulong, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(functionality, "Override functionality bitfield"); - -struct stub_chip { - u8 pointer; - u16 words[256]; /* Byte operations use the LSB as per SMBus - specification */ -}; - -static struct stub_chip *stub_chips; - -/* Return negative errno on error. */ -static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, union i2c_smbus_data * data) -{ - s32 ret; - int i, len; - struct stub_chip *chip = NULL; - - /* Search for the right chip */ - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (addr == chip_addr[i]) { - chip = stub_chips + i; - break; - } - } - if (!chip) - return -ENODEV; - - switch (size) { - - case I2C_SMBUS_QUICK: - dev_dbg(&adap->dev, "smbus quick - addr 0x%02x\n", addr); - ret = 0; - break; - - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) { - chip->pointer = command; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "wrote 0x%02x.\n", - addr, command); - } else { - data->byte = chip->words[chip->pointer++] & 0xff; - dev_dbg(&adap->dev, "smbus byte - addr 0x%02x, " - "read 0x%02x.\n", - addr, data->byte); - } - - ret = 0; - break; - - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] &= 0xff00; - chip->words[command] |= data->byte; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "wrote 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } else { - data->byte = chip->words[command] & 0xff; - dev_dbg(&adap->dev, "smbus byte data - addr 0x%02x, " - "read 0x%02x at 0x%02x.\n", - addr, data->byte, command); - } - chip->pointer = command + 1; - - ret = 0; - break; - - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_WRITE) { - chip->words[command] = data->word; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "wrote 0x%04x at 0x%02x.\n", - addr, data->word, command); - } else { - data->word = chip->words[command]; - dev_dbg(&adap->dev, "smbus word data - addr 0x%02x, " - "read 0x%04x at 0x%02x.\n", - addr, data->word, command); - } - - ret = 0; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = data->block[0]; - if (read_write == I2C_SMBUS_WRITE) { - for (i = 0; i < len; i++) { - chip->words[command + i] &= 0xff00; - chip->words[command + i] |= data->block[1 + i]; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "wrote %d bytes at 0x%02x.\n", - addr, len, command); - } else { - for (i = 0; i < len; i++) { - data->block[1 + i] = - chip->words[command + i] & 0xff; - } - dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, " - "read %d bytes at 0x%02x.\n", - addr, len, command); - } - - ret = 0; - break; - - default: - dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n"); - ret = -EOPNOTSUPP; - break; - } /* switch (size) */ - - return ret; -} - -static u32 stub_func(struct i2c_adapter *adapter) -{ - return STUB_FUNC & functionality; -} - -static const struct i2c_algorithm smbus_algorithm = { - .functionality = stub_func, - .smbus_xfer = stub_xfer, -}; - -static struct i2c_adapter stub_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, - .name = "SMBus stub driver", -}; - -static int __init i2c_stub_init(void) -{ - int i, ret; - - if (!chip_addr[0]) { - printk(KERN_ERR "i2c-stub: Please specify a chip address\n"); - return -ENODEV; - } - - for (i = 0; i < MAX_CHIPS && chip_addr[i]; i++) { - if (chip_addr[i] < 0x03 || chip_addr[i] > 0x77) { - printk(KERN_ERR "i2c-stub: Invalid chip address " - "0x%02x\n", chip_addr[i]); - return -EINVAL; - } - - printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", - chip_addr[i]); - } - - /* Allocate memory for all chips at once */ - stub_chips = kzalloc(i * sizeof(struct stub_chip), GFP_KERNEL); - if (!stub_chips) { - printk(KERN_ERR "i2c-stub: Out of memory\n"); - return -ENOMEM; - } - - ret = i2c_add_adapter(&stub_adapter); - if (ret) - kfree(stub_chips); - return ret; -} - -static void __exit i2c_stub_exit(void) -{ - i2c_del_adapter(&stub_adapter); - kfree(stub_chips); -} - -MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>"); -MODULE_DESCRIPTION("I2C stub driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_stub_init); -module_exit(i2c_stub_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-taos-evm.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-taos-evm.c deleted file mode 100644 index 26c352a0..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-taos-evm.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * Driver for the TAOS evaluation modules - * These devices include an I2C master which can be controlled over the - * serial port. - * - * Copyright (C) 2007 Jean Delvare <khali@linux-fr.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <linux/delay.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/interrupt.h> -#include <linux/input.h> -#include <linux/serio.h> -#include <linux/init.h> -#include <linux/i2c.h> - -#define TAOS_BUFFER_SIZE 63 - -#define TAOS_STATE_INIT 0 -#define TAOS_STATE_IDLE 1 -#define TAOS_STATE_EOFF 2 -#define TAOS_STATE_RECV 3 - -#define TAOS_CMD_RESET 0x12 -#define TAOS_CMD_ECHO_ON '+' -#define TAOS_CMD_ECHO_OFF '-' - -static DECLARE_WAIT_QUEUE_HEAD(wq); - -struct taos_data { - struct i2c_adapter adapter; - struct i2c_client *client; - int state; - u8 addr; /* last used address */ - unsigned char buffer[TAOS_BUFFER_SIZE]; - unsigned int pos; /* position inside the buffer */ -}; - -/* TAOS TSL2550 EVM */ -static struct i2c_board_info tsl2550_info = { - I2C_BOARD_INFO("tsl2550", 0x39), -}; - -/* Instantiate i2c devices based on the adapter name */ -static struct i2c_client *taos_instantiate_device(struct i2c_adapter *adapter) -{ - if (!strncmp(adapter->name, "TAOS TSL2550 EVM", 16)) { - dev_info(&adapter->dev, "Instantiating device %s at 0x%02x\n", - tsl2550_info.type, tsl2550_info.addr); - return i2c_new_device(adapter, &tsl2550_info); - } - - return NULL; -} - -static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - struct serio *serio = adapter->algo_data; - struct taos_data *taos = serio_get_drvdata(serio); - char *p; - - /* Encode our transaction. "@" is for the device address, "$" for the - SMBus command and "#" for the data. */ - p = taos->buffer; - - /* The device remembers the last used address, no need to send it - again if it's the same */ - if (addr != taos->addr) - p += sprintf(p, "@%02X", addr); - - switch (size) { - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - sprintf(p, "$#%02X", command); - else - sprintf(p, "$"); - break; - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_WRITE) - sprintf(p, "$%02X#%02X", command, data->byte); - else - sprintf(p, "$%02X", command); - break; - default: - dev_warn(&adapter->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - /* Send the transaction to the TAOS EVM */ - dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer); - for (p = taos->buffer; *p; p++) - serio_write(serio, *p); - - taos->addr = addr; - - /* Start the transaction and read the answer */ - taos->pos = 0; - taos->state = TAOS_STATE_RECV; - serio_write(serio, read_write == I2C_SMBUS_WRITE ? '>' : '<'); - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(150)); - if (taos->state != TAOS_STATE_IDLE - || taos->pos != 5) { - dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n", - taos->pos); - return -EIO; - } - dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer); - - /* Interpret the returned string */ - p = taos->buffer + 1; - p[3] = '\0'; - if (!strcmp(p, "NAK")) - return -ENODEV; - - if (read_write == I2C_SMBUS_WRITE) { - if (!strcmp(p, "ACK")) - return 0; - } else { - if (p[0] == 'x') { - data->byte = simple_strtol(p + 1, NULL, 16); - return 0; - } - } - - return -EIO; -} - -static u32 taos_smbus_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_BYTE | I2C_FUNC_SMBUS_BYTE_DATA; -} - -static const struct i2c_algorithm taos_algorithm = { - .smbus_xfer = taos_smbus_xfer, - .functionality = taos_smbus_func, -}; - -static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data, - unsigned int flags) -{ - struct taos_data *taos = serio_get_drvdata(serio); - - switch (taos->state) { - case TAOS_STATE_INIT: - taos->buffer[taos->pos++] = data; - if (data == ':' - || taos->pos == TAOS_BUFFER_SIZE - 1) { - taos->buffer[taos->pos] = '\0'; - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - } - break; - case TAOS_STATE_EOFF: - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - break; - case TAOS_STATE_RECV: - taos->buffer[taos->pos++] = data; - if (data == ']') { - taos->buffer[taos->pos] = '\0'; - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); - } - break; - } - - return IRQ_HANDLED; -} - -/* Extract the adapter name from the buffer received after reset. - The buffer is modified and a pointer inside the buffer is returned. */ -static char *taos_adapter_name(char *buffer) -{ - char *start, *end; - - start = strstr(buffer, "TAOS "); - if (!start) - return NULL; - - end = strchr(start, '\r'); - if (!end) - return NULL; - *end = '\0'; - - return start; -} - -static int taos_connect(struct serio *serio, struct serio_driver *drv) -{ - struct taos_data *taos; - struct i2c_adapter *adapter; - char *name; - int err; - - taos = kzalloc(sizeof(struct taos_data), GFP_KERNEL); - if (!taos) { - err = -ENOMEM; - goto exit; - } - taos->state = TAOS_STATE_INIT; - serio_set_drvdata(serio, taos); - - err = serio_open(serio, drv); - if (err) - goto exit_kfree; - - adapter = &taos->adapter; - adapter->owner = THIS_MODULE; - adapter->algo = &taos_algorithm; - adapter->algo_data = serio; - adapter->dev.parent = &serio->dev; - - /* Reset the TAOS evaluation module to identify it */ - serio_write(serio, TAOS_CMD_RESET); - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(2000)); - - if (taos->state != TAOS_STATE_IDLE) { - err = -ENODEV; - dev_err(&serio->dev, "TAOS EVM reset failed (state=%d, " - "pos=%d)\n", taos->state, taos->pos); - goto exit_close; - } - - name = taos_adapter_name(taos->buffer); - if (!name) { - err = -ENODEV; - dev_err(&serio->dev, "TAOS EVM identification failed\n"); - goto exit_close; - } - strlcpy(adapter->name, name, sizeof(adapter->name)); - - /* Turn echo off for better performance */ - taos->state = TAOS_STATE_EOFF; - serio_write(serio, TAOS_CMD_ECHO_OFF); - - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(250)); - if (taos->state != TAOS_STATE_IDLE) { - err = -ENODEV; - dev_err(&serio->dev, "TAOS EVM echo off failed " - "(state=%d)\n", taos->state); - goto exit_close; - } - - err = i2c_add_adapter(adapter); - if (err) - goto exit_close; - dev_info(&serio->dev, "Connected to TAOS EVM\n"); - - taos->client = taos_instantiate_device(adapter); - return 0; - - exit_close: - serio_close(serio); - exit_kfree: - serio_set_drvdata(serio, NULL); - kfree(taos); - exit: - return err; -} - -static void taos_disconnect(struct serio *serio) -{ - struct taos_data *taos = serio_get_drvdata(serio); - - if (taos->client) - i2c_unregister_device(taos->client); - i2c_del_adapter(&taos->adapter); - serio_close(serio); - serio_set_drvdata(serio, NULL); - kfree(taos); - - dev_info(&serio->dev, "Disconnected from TAOS EVM\n"); -} - -static struct serio_device_id taos_serio_ids[] = { - { - .type = SERIO_RS232, - .proto = SERIO_TAOSEVM, - .id = SERIO_ANY, - .extra = SERIO_ANY, - }, - { 0 } -}; -MODULE_DEVICE_TABLE(serio, taos_serio_ids); - -static struct serio_driver taos_drv = { - .driver = { - .name = "taos-evm", - }, - .description = "TAOS evaluation module driver", - .id_table = taos_serio_ids, - .connect = taos_connect, - .disconnect = taos_disconnect, - .interrupt = taos_interrupt, -}; - -static int __init taos_init(void) -{ - return serio_register_driver(&taos_drv); -} - -static void __exit taos_exit(void) -{ - serio_unregister_driver(&taos_drv); -} - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("TAOS evaluation module driver"); -MODULE_LICENSE("GPL"); - -module_init(taos_init); -module_exit(taos_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-tegra.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-tegra.c deleted file mode 100644 index df19f3d5..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-tegra.c +++ /dev/null @@ -1,791 +0,0 @@ -/* - * drivers/i2c/busses/i2c-tegra.c - * - * Copyright (C) 2010 Google, Inc. - * Author: Colin Cross <ccross@android.com> - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/err.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/i2c-tegra.h> -#include <linux/of_i2c.h> -#include <linux/module.h> - -#include <asm/unaligned.h> - -#include <mach/clk.h> - -#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000)) -#define BYTES_PER_FIFO_WORD 4 - -#define I2C_CNFG 0x000 -#define I2C_CNFG_DEBOUNCE_CNT_SHIFT 12 -#define I2C_CNFG_PACKET_MODE_EN (1<<10) -#define I2C_CNFG_NEW_MASTER_FSM (1<<11) -#define I2C_STATUS 0x01C -#define I2C_SL_CNFG 0x020 -#define I2C_SL_CNFG_NACK (1<<1) -#define I2C_SL_CNFG_NEWSL (1<<2) -#define I2C_SL_ADDR1 0x02c -#define I2C_SL_ADDR2 0x030 -#define I2C_TX_FIFO 0x050 -#define I2C_RX_FIFO 0x054 -#define I2C_PACKET_TRANSFER_STATUS 0x058 -#define I2C_FIFO_CONTROL 0x05c -#define I2C_FIFO_CONTROL_TX_FLUSH (1<<1) -#define I2C_FIFO_CONTROL_RX_FLUSH (1<<0) -#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT 5 -#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT 2 -#define I2C_FIFO_STATUS 0x060 -#define I2C_FIFO_STATUS_TX_MASK 0xF0 -#define I2C_FIFO_STATUS_TX_SHIFT 4 -#define I2C_FIFO_STATUS_RX_MASK 0x0F -#define I2C_FIFO_STATUS_RX_SHIFT 0 -#define I2C_INT_MASK 0x064 -#define I2C_INT_STATUS 0x068 -#define I2C_INT_PACKET_XFER_COMPLETE (1<<7) -#define I2C_INT_ALL_PACKETS_XFER_COMPLETE (1<<6) -#define I2C_INT_TX_FIFO_OVERFLOW (1<<5) -#define I2C_INT_RX_FIFO_UNDERFLOW (1<<4) -#define I2C_INT_NO_ACK (1<<3) -#define I2C_INT_ARBITRATION_LOST (1<<2) -#define I2C_INT_TX_FIFO_DATA_REQ (1<<1) -#define I2C_INT_RX_FIFO_DATA_REQ (1<<0) -#define I2C_CLK_DIVISOR 0x06c - -#define DVC_CTRL_REG1 0x000 -#define DVC_CTRL_REG1_INTR_EN (1<<10) -#define DVC_CTRL_REG2 0x004 -#define DVC_CTRL_REG3 0x008 -#define DVC_CTRL_REG3_SW_PROG (1<<26) -#define DVC_CTRL_REG3_I2C_DONE_INTR_EN (1<<30) -#define DVC_STATUS 0x00c -#define DVC_STATUS_I2C_DONE_INTR (1<<30) - -#define I2C_ERR_NONE 0x00 -#define I2C_ERR_NO_ACK 0x01 -#define I2C_ERR_ARBITRATION_LOST 0x02 -#define I2C_ERR_UNKNOWN_INTERRUPT 0x04 - -#define PACKET_HEADER0_HEADER_SIZE_SHIFT 28 -#define PACKET_HEADER0_PACKET_ID_SHIFT 16 -#define PACKET_HEADER0_CONT_ID_SHIFT 12 -#define PACKET_HEADER0_PROTOCOL_I2C (1<<4) - -#define I2C_HEADER_HIGHSPEED_MODE (1<<22) -#define I2C_HEADER_CONT_ON_NAK (1<<21) -#define I2C_HEADER_SEND_START_BYTE (1<<20) -#define I2C_HEADER_READ (1<<19) -#define I2C_HEADER_10BIT_ADDR (1<<18) -#define I2C_HEADER_IE_ENABLE (1<<17) -#define I2C_HEADER_REPEAT_START (1<<16) -#define I2C_HEADER_MASTER_ADDR_SHIFT 12 -#define I2C_HEADER_SLAVE_ADDR_SHIFT 1 - -/** - * struct tegra_i2c_dev - per device i2c context - * @dev: device reference for power management - * @adapter: core i2c layer adapter information - * @clk: clock reference for i2c controller - * @i2c_clk: clock reference for i2c bus - * @iomem: memory resource for registers - * @base: ioremapped registers cookie - * @cont_id: i2c controller id, used for for packet header - * @irq: irq number of transfer complete interrupt - * @is_dvc: identifies the DVC i2c controller, has a different register layout - * @msg_complete: transfer completion notifier - * @msg_err: error code for completed message - * @msg_buf: pointer to current message data - * @msg_buf_remaining: size of unsent data in the message buffer - * @msg_read: identifies read transfers - * @bus_clk_rate: current i2c bus clock rate - * @is_suspended: prevents i2c controller accesses after suspend is called - */ -struct tegra_i2c_dev { - struct device *dev; - struct i2c_adapter adapter; - struct clk *clk; - struct clk *i2c_clk; - struct resource *iomem; - void __iomem *base; - int cont_id; - int irq; - bool irq_disabled; - int is_dvc; - struct completion msg_complete; - int msg_err; - u8 *msg_buf; - size_t msg_buf_remaining; - int msg_read; - unsigned long bus_clk_rate; - bool is_suspended; -}; - -static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) -{ - writel(val, i2c_dev->base + reg); -} - -static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) -{ - return readl(i2c_dev->base + reg); -} - -/* - * i2c_writel and i2c_readl will offset the register if necessary to talk - * to the I2C block inside the DVC block - */ -static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev, - unsigned long reg) -{ - if (i2c_dev->is_dvc) - reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40; - return reg; -} - -static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, - unsigned long reg) -{ - writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); -} - -static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) -{ - return readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg)); -} - -static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data, - unsigned long reg, int len) -{ - writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); -} - -static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data, - unsigned long reg, int len) -{ - readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len); -} - -static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) -{ - u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); - int_mask &= ~mask; - i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); -} - -static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) -{ - u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); - int_mask |= mask; - i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); -} - -static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) -{ - unsigned long timeout = jiffies + HZ; - u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL); - val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH; - i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); - - while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) & - (I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) { - if (time_after(jiffies, timeout)) { - dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n"); - return -ETIMEDOUT; - } - msleep(1); - } - return 0; -} - -static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev) -{ - u32 val; - int rx_fifo_avail; - u8 *buf = i2c_dev->msg_buf; - size_t buf_remaining = i2c_dev->msg_buf_remaining; - int words_to_transfer; - - val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); - rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >> - I2C_FIFO_STATUS_RX_SHIFT; - - /* Rounds down to not include partial word at the end of buf */ - words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; - if (words_to_transfer > rx_fifo_avail) - words_to_transfer = rx_fifo_avail; - - i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer); - - buf += words_to_transfer * BYTES_PER_FIFO_WORD; - buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; - rx_fifo_avail -= words_to_transfer; - - /* - * If there is a partial word at the end of buf, handle it manually to - * prevent overwriting past the end of buf - */ - if (rx_fifo_avail > 0 && buf_remaining > 0) { - BUG_ON(buf_remaining > 3); - val = i2c_readl(i2c_dev, I2C_RX_FIFO); - memcpy(buf, &val, buf_remaining); - buf_remaining = 0; - rx_fifo_avail--; - } - - BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0); - i2c_dev->msg_buf_remaining = buf_remaining; - i2c_dev->msg_buf = buf; - return 0; -} - -static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev) -{ - u32 val; - int tx_fifo_avail; - u8 *buf = i2c_dev->msg_buf; - size_t buf_remaining = i2c_dev->msg_buf_remaining; - int words_to_transfer; - - val = i2c_readl(i2c_dev, I2C_FIFO_STATUS); - tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >> - I2C_FIFO_STATUS_TX_SHIFT; - - /* Rounds down to not include partial word at the end of buf */ - words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD; - - /* It's very common to have < 4 bytes, so optimize that case. */ - if (words_to_transfer) { - if (words_to_transfer > tx_fifo_avail) - words_to_transfer = tx_fifo_avail; - - /* - * Update state before writing to FIFO. If this casues us - * to finish writing all bytes (AKA buf_remaining goes to 0) we - * have a potential for an interrupt (PACKET_XFER_COMPLETE is - * not maskable). We need to make sure that the isr sees - * buf_remaining as 0 and doesn't call us back re-entrantly. - */ - buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD; - tx_fifo_avail -= words_to_transfer; - i2c_dev->msg_buf_remaining = buf_remaining; - i2c_dev->msg_buf = buf + - words_to_transfer * BYTES_PER_FIFO_WORD; - barrier(); - - i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer); - - buf += words_to_transfer * BYTES_PER_FIFO_WORD; - } - - /* - * If there is a partial word at the end of buf, handle it manually to - * prevent reading past the end of buf, which could cross a page - * boundary and fault. - */ - if (tx_fifo_avail > 0 && buf_remaining > 0) { - BUG_ON(buf_remaining > 3); - memcpy(&val, buf, buf_remaining); - - /* Again update before writing to FIFO to make sure isr sees. */ - i2c_dev->msg_buf_remaining = 0; - i2c_dev->msg_buf = NULL; - barrier(); - - i2c_writel(i2c_dev, val, I2C_TX_FIFO); - } - - return 0; -} - -/* - * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller) - * block. This block is identical to the rest of the I2C blocks, except that - * it only supports master mode, it has registers moved around, and it needs - * some extra init to get it into I2C mode. The register moves are handled - * by i2c_readl and i2c_writel - */ -static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) -{ - u32 val = 0; - val = dvc_readl(i2c_dev, DVC_CTRL_REG3); - val |= DVC_CTRL_REG3_SW_PROG; - val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN; - dvc_writel(i2c_dev, val, DVC_CTRL_REG3); - - val = dvc_readl(i2c_dev, DVC_CTRL_REG1); - val |= DVC_CTRL_REG1_INTR_EN; - dvc_writel(i2c_dev, val, DVC_CTRL_REG1); -} - -static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) -{ - u32 val; - int err = 0; - - clk_enable(i2c_dev->clk); - - tegra_periph_reset_assert(i2c_dev->clk); - udelay(2); - tegra_periph_reset_deassert(i2c_dev->clk); - - if (i2c_dev->is_dvc) - tegra_dvc_init(i2c_dev); - - val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN | - (0x2 << I2C_CNFG_DEBOUNCE_CNT_SHIFT); - i2c_writel(i2c_dev, val, I2C_CNFG); - i2c_writel(i2c_dev, 0, I2C_INT_MASK); - clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8); - - if (!i2c_dev->is_dvc) { - u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); - sl_cfg |= I2C_SL_CNFG_NACK | I2C_SL_CNFG_NEWSL; - i2c_writel(i2c_dev, sl_cfg, I2C_SL_CNFG); - i2c_writel(i2c_dev, 0xfc, I2C_SL_ADDR1); - i2c_writel(i2c_dev, 0x00, I2C_SL_ADDR2); - - } - - val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT | - 0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT; - i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL); - - if (tegra_i2c_flush_fifos(i2c_dev)) - err = -ETIMEDOUT; - - clk_disable(i2c_dev->clk); - - if (i2c_dev->irq_disabled) { - i2c_dev->irq_disabled = 0; - enable_irq(i2c_dev->irq); - } - - return err; -} - -static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) -{ - u32 status; - const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; - struct tegra_i2c_dev *i2c_dev = dev_id; - - status = i2c_readl(i2c_dev, I2C_INT_STATUS); - - if (status == 0) { - dev_warn(i2c_dev->dev, "irq status 0 %08x %08x %08x\n", - i2c_readl(i2c_dev, I2C_PACKET_TRANSFER_STATUS), - i2c_readl(i2c_dev, I2C_STATUS), - i2c_readl(i2c_dev, I2C_CNFG)); - i2c_dev->msg_err |= I2C_ERR_UNKNOWN_INTERRUPT; - - if (!i2c_dev->irq_disabled) { - disable_irq_nosync(i2c_dev->irq); - i2c_dev->irq_disabled = 1; - } - goto err; - } - - if (unlikely(status & status_err)) { - if (status & I2C_INT_NO_ACK) - i2c_dev->msg_err |= I2C_ERR_NO_ACK; - if (status & I2C_INT_ARBITRATION_LOST) - i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST; - goto err; - } - - if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) { - if (i2c_dev->msg_buf_remaining) - tegra_i2c_empty_rx_fifo(i2c_dev); - else - BUG(); - } - - if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) { - if (i2c_dev->msg_buf_remaining) - tegra_i2c_fill_tx_fifo(i2c_dev); - else - tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ); - } - - i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) - dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); - - if (status & I2C_INT_PACKET_XFER_COMPLETE) { - BUG_ON(i2c_dev->msg_buf_remaining); - complete(&i2c_dev->msg_complete); - } - return IRQ_HANDLED; -err: - /* An error occurred, mask all interrupts */ - tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST | - I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ | - I2C_INT_RX_FIFO_DATA_REQ); - i2c_writel(i2c_dev, status, I2C_INT_STATUS); - if (i2c_dev->is_dvc) - dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); - - complete(&i2c_dev->msg_complete); - return IRQ_HANDLED; -} - -static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) -{ - u32 packet_header; - u32 int_mask; - int ret; - - tegra_i2c_flush_fifos(i2c_dev); - - if (msg->len == 0) - return -EINVAL; - - i2c_dev->msg_buf = msg->buf; - i2c_dev->msg_buf_remaining = msg->len; - i2c_dev->msg_err = I2C_ERR_NONE; - i2c_dev->msg_read = (msg->flags & I2C_M_RD); - INIT_COMPLETION(i2c_dev->msg_complete); - - packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) | - PACKET_HEADER0_PROTOCOL_I2C | - (i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) | - (1 << PACKET_HEADER0_PACKET_ID_SHIFT); - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); - - packet_header = msg->len - 1; - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); - - packet_header = msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT; - packet_header |= I2C_HEADER_IE_ENABLE; - if (!stop) - packet_header |= I2C_HEADER_REPEAT_START; - if (msg->flags & I2C_M_TEN) - packet_header |= I2C_HEADER_10BIT_ADDR; - if (msg->flags & I2C_M_IGNORE_NAK) - packet_header |= I2C_HEADER_CONT_ON_NAK; - if (msg->flags & I2C_M_RD) - packet_header |= I2C_HEADER_READ; - i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); - - if (!(msg->flags & I2C_M_RD)) - tegra_i2c_fill_tx_fifo(i2c_dev); - - int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; - if (msg->flags & I2C_M_RD) - int_mask |= I2C_INT_RX_FIFO_DATA_REQ; - else if (i2c_dev->msg_buf_remaining) - int_mask |= I2C_INT_TX_FIFO_DATA_REQ; - tegra_i2c_unmask_irq(i2c_dev, int_mask); - dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n", - i2c_readl(i2c_dev, I2C_INT_MASK)); - - ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT); - tegra_i2c_mask_irq(i2c_dev, int_mask); - - if (WARN_ON(ret == 0)) { - dev_err(i2c_dev->dev, "i2c transfer timed out\n"); - - tegra_i2c_init(i2c_dev); - return -ETIMEDOUT; - } - - dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n", - ret, completion_done(&i2c_dev->msg_complete), i2c_dev->msg_err); - - if (likely(i2c_dev->msg_err == I2C_ERR_NONE)) - return 0; - - /* - * NACK interrupt is generated before the I2C controller generates the - * STOP condition on the bus. So wait for 2 clock periods before resetting - * the controller so that STOP condition has been delivered properly. - */ - if (i2c_dev->msg_err == I2C_ERR_NO_ACK) - udelay(DIV_ROUND_UP(2 * 1000000, i2c_dev->bus_clk_rate)); - - tegra_i2c_init(i2c_dev); - if (i2c_dev->msg_err == I2C_ERR_NO_ACK) { - if (msg->flags & I2C_M_IGNORE_NAK) - return 0; - return -EREMOTEIO; - } - - return -EIO; -} - -static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], - int num) -{ - struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); - int i; - int ret = 0; - - if (i2c_dev->is_suspended) - return -EBUSY; - - clk_enable(i2c_dev->clk); - for (i = 0; i < num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop); - if (ret) - break; - } - clk_disable(i2c_dev->clk); - return ret ?: i; -} - -static u32 tegra_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm tegra_i2c_algo = { - .master_xfer = tegra_i2c_xfer, - .functionality = tegra_i2c_func, -}; - -static int __devinit tegra_i2c_probe(struct platform_device *pdev) -{ - struct tegra_i2c_dev *i2c_dev; - struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data; - struct resource *res; - struct resource *iomem; - struct clk *clk; - struct clk *i2c_clk; - const unsigned int *prop; - void __iomem *base; - int irq; - int ret = 0; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no mem resource\n"); - return -EINVAL; - } - iomem = request_mem_region(res->start, resource_size(res), pdev->name); - if (!iomem) { - dev_err(&pdev->dev, "I2C region already claimed\n"); - return -EBUSY; - } - - base = ioremap(iomem->start, resource_size(iomem)); - if (!base) { - dev_err(&pdev->dev, "Cannot ioremap I2C region\n"); - return -ENOMEM; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (!res) { - dev_err(&pdev->dev, "no irq resource\n"); - ret = -EINVAL; - goto err_iounmap; - } - irq = res->start; - - clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&pdev->dev, "missing controller clock"); - ret = PTR_ERR(clk); - goto err_release_region; - } - - i2c_clk = clk_get(&pdev->dev, "i2c"); - if (IS_ERR(i2c_clk)) { - dev_err(&pdev->dev, "missing bus clock"); - ret = PTR_ERR(i2c_clk); - goto err_clk_put; - } - - i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); - if (!i2c_dev) { - ret = -ENOMEM; - goto err_i2c_clk_put; - } - - i2c_dev->base = base; - i2c_dev->clk = clk; - i2c_dev->i2c_clk = i2c_clk; - i2c_dev->iomem = iomem; - i2c_dev->adapter.algo = &tegra_i2c_algo; - i2c_dev->irq = irq; - i2c_dev->cont_id = pdev->id; - i2c_dev->dev = &pdev->dev; - - i2c_dev->bus_clk_rate = 100000; /* default clock rate */ - if (pdata) { - i2c_dev->bus_clk_rate = pdata->bus_clk_rate; - - } else if (i2c_dev->dev->of_node) { /* if there is a device tree node ... */ - prop = of_get_property(i2c_dev->dev->of_node, - "clock-frequency", NULL); - if (prop) - i2c_dev->bus_clk_rate = be32_to_cpup(prop); - } - - if (pdev->dev.of_node) - i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node, - "nvidia,tegra20-i2c-dvc"); - else if (pdev->id == 3) - i2c_dev->is_dvc = 1; - init_completion(&i2c_dev->msg_complete); - - platform_set_drvdata(pdev, i2c_dev); - - ret = tegra_i2c_init(i2c_dev); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize i2c controller"); - goto err_free; - } - - ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev); - if (ret) { - dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq); - goto err_free; - } - - clk_enable(i2c_dev->i2c_clk); - - i2c_set_adapdata(&i2c_dev->adapter, i2c_dev); - i2c_dev->adapter.owner = THIS_MODULE; - i2c_dev->adapter.class = I2C_CLASS_HWMON; - strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter", - sizeof(i2c_dev->adapter.name)); - i2c_dev->adapter.algo = &tegra_i2c_algo; - i2c_dev->adapter.dev.parent = &pdev->dev; - i2c_dev->adapter.nr = pdev->id; - i2c_dev->adapter.dev.of_node = pdev->dev.of_node; - - ret = i2c_add_numbered_adapter(&i2c_dev->adapter); - if (ret) { - dev_err(&pdev->dev, "Failed to add I2C adapter\n"); - goto err_free_irq; - } - - of_i2c_register_devices(&i2c_dev->adapter); - - return 0; -err_free_irq: - free_irq(i2c_dev->irq, i2c_dev); -err_free: - kfree(i2c_dev); -err_i2c_clk_put: - clk_put(i2c_clk); -err_clk_put: - clk_put(clk); -err_release_region: - release_mem_region(iomem->start, resource_size(iomem)); -err_iounmap: - iounmap(base); - return ret; -} - -static int __devexit tegra_i2c_remove(struct platform_device *pdev) -{ - struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - i2c_del_adapter(&i2c_dev->adapter); - free_irq(i2c_dev->irq, i2c_dev); - clk_put(i2c_dev->i2c_clk); - clk_put(i2c_dev->clk); - release_mem_region(i2c_dev->iomem->start, - resource_size(i2c_dev->iomem)); - iounmap(i2c_dev->base); - kfree(i2c_dev); - return 0; -} - -#ifdef CONFIG_PM -static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - - i2c_lock_adapter(&i2c_dev->adapter); - i2c_dev->is_suspended = true; - i2c_unlock_adapter(&i2c_dev->adapter); - - return 0; -} - -static int tegra_i2c_resume(struct platform_device *pdev) -{ - struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); - int ret; - - i2c_lock_adapter(&i2c_dev->adapter); - - ret = tegra_i2c_init(i2c_dev); - - if (ret) { - i2c_unlock_adapter(&i2c_dev->adapter); - return ret; - } - - i2c_dev->is_suspended = false; - - i2c_unlock_adapter(&i2c_dev->adapter); - - return 0; -} -#endif - -#if defined(CONFIG_OF) -/* Match table for of_platform binding */ -static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { - { .compatible = "nvidia,tegra20-i2c", }, - { .compatible = "nvidia,tegra20-i2c-dvc", }, - {}, -}; -MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); -#else -#define tegra_i2c_of_match NULL -#endif - -static struct platform_driver tegra_i2c_driver = { - .probe = tegra_i2c_probe, - .remove = __devexit_p(tegra_i2c_remove), -#ifdef CONFIG_PM - .suspend = tegra_i2c_suspend, - .resume = tegra_i2c_resume, -#endif - .driver = { - .name = "tegra-i2c", - .owner = THIS_MODULE, - .of_match_table = tegra_i2c_of_match, - }, -}; - -static int __init tegra_i2c_init_driver(void) -{ - return platform_driver_register(&tegra_i2c_driver); -} - -static void __exit tegra_i2c_exit_driver(void) -{ - platform_driver_unregister(&tegra_i2c_driver); -} - -subsys_initcall(tegra_i2c_init_driver); -module_exit(tegra_i2c_exit_driver); - -MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver"); -MODULE_AUTHOR("Colin Cross"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-tiny-usb.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-tiny-usb.c deleted file mode 100644 index f07307ff..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-tiny-usb.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * driver for the i2c-tiny-usb adapter - 1.0 - * http://www.harbaum.org/till/i2c_tiny_usb - * - * Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2. - * - */ - -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/types.h> - -/* include interfaces to usb layer */ -#include <linux/usb.h> - -/* include interface to i2c layer */ -#include <linux/i2c.h> - -/* commands via USB, must match command ids in the firmware */ -#define CMD_ECHO 0 -#define CMD_GET_FUNC 1 -#define CMD_SET_DELAY 2 -#define CMD_GET_STATUS 3 - -#define CMD_I2C_IO 4 -#define CMD_I2C_IO_BEGIN (1<<0) -#define CMD_I2C_IO_END (1<<1) - -/* i2c bit delay, default is 10us -> 100kHz max - (in practice, due to additional delays in the i2c bitbanging - code this results in a i2c clock of about 50kHz) */ -static unsigned short delay = 10; -module_param(delay, ushort, 0); -MODULE_PARM_DESC(delay, "bit delay in microseconds " - "(default is 10us for 100kHz max)"); - -static int usb_read(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len); - -static int usb_write(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len); - -/* ----- begin of i2c layer ---------------------------------------------- */ - -#define STATUS_IDLE 0 -#define STATUS_ADDRESS_ACK 1 -#define STATUS_ADDRESS_NAK 2 - -static int usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) -{ - unsigned char status; - struct i2c_msg *pmsg; - int i; - - dev_dbg(&adapter->dev, "master xfer %d messages:\n", num); - - for (i = 0 ; i < num ; i++) { - int cmd = CMD_I2C_IO; - - if (i == 0) - cmd |= CMD_I2C_IO_BEGIN; - - if (i == num-1) - cmd |= CMD_I2C_IO_END; - - pmsg = &msgs[i]; - - dev_dbg(&adapter->dev, - " %d: %s (flags %d) %d bytes to 0x%02x\n", - i, pmsg->flags & I2C_M_RD ? "read" : "write", - pmsg->flags, pmsg->len, pmsg->addr); - - /* and directly send the message */ - if (pmsg->flags & I2C_M_RD) { - /* read data */ - if (usb_read(adapter, cmd, - pmsg->flags, pmsg->addr, - pmsg->buf, pmsg->len) != pmsg->len) { - dev_err(&adapter->dev, - "failure reading data\n"); - return -EREMOTEIO; - } - } else { - /* write data */ - if (usb_write(adapter, cmd, - pmsg->flags, pmsg->addr, - pmsg->buf, pmsg->len) != pmsg->len) { - dev_err(&adapter->dev, - "failure writing data\n"); - return -EREMOTEIO; - } - } - - /* read status */ - if (usb_read(adapter, CMD_GET_STATUS, 0, 0, &status, 1) != 1) { - dev_err(&adapter->dev, "failure reading status\n"); - return -EREMOTEIO; - } - - dev_dbg(&adapter->dev, " status = %d\n", status); - if (status == STATUS_ADDRESS_NAK) - return -EREMOTEIO; - } - - return i; -} - -static u32 usb_func(struct i2c_adapter *adapter) -{ - __le32 func; - - /* get functionality from adapter */ - if (usb_read(adapter, CMD_GET_FUNC, 0, 0, &func, sizeof(func)) != - sizeof(func)) { - dev_err(&adapter->dev, "failure reading functionality\n"); - return 0; - } - - return le32_to_cpu(func); -} - -/* This is the actual algorithm we define */ -static const struct i2c_algorithm usb_algorithm = { - .master_xfer = usb_xfer, - .functionality = usb_func, -}; - -/* ----- end of i2c layer ------------------------------------------------ */ - -/* ----- begin of usb layer ---------------------------------------------- */ - -/* - * Initially the usb i2c interface uses a vid/pid pair donated by - * Future Technology Devices International Ltd., later a pair was - * bought from EZPrototypes - */ -static const struct usb_device_id i2c_tiny_usb_table[] = { - { USB_DEVICE(0x0403, 0xc631) }, /* FTDI */ - { USB_DEVICE(0x1c40, 0x0534) }, /* EZPrototypes */ - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, i2c_tiny_usb_table); - -/* Structure to hold all of our device specific stuff */ -struct i2c_tiny_usb { - struct usb_device *usb_dev; /* the usb device for this device */ - struct usb_interface *interface; /* the interface for this device */ - struct i2c_adapter adapter; /* i2c related things */ -}; - -static int usb_read(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len) -{ - struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; - - /* do control transfer */ - return usb_control_msg(dev->usb_dev, usb_rcvctrlpipe(dev->usb_dev, 0), - cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | - USB_DIR_IN, value, index, data, len, 2000); -} - -static int usb_write(struct i2c_adapter *adapter, int cmd, - int value, int index, void *data, int len) -{ - struct i2c_tiny_usb *dev = (struct i2c_tiny_usb *)adapter->algo_data; - - /* do control transfer */ - return usb_control_msg(dev->usb_dev, usb_sndctrlpipe(dev->usb_dev, 0), - cmd, USB_TYPE_VENDOR | USB_RECIP_INTERFACE, - value, index, data, len, 2000); -} - -static void i2c_tiny_usb_free(struct i2c_tiny_usb *dev) -{ - usb_put_dev(dev->usb_dev); - kfree(dev); -} - -static int i2c_tiny_usb_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct i2c_tiny_usb *dev; - int retval = -ENOMEM; - u16 version; - - dev_dbg(&interface->dev, "probing usb device\n"); - - /* allocate memory for our device state and initialize it */ - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "Out of memory\n"); - goto error; - } - - dev->usb_dev = usb_get_dev(interface_to_usbdev(interface)); - dev->interface = interface; - - /* save our data pointer in this interface device */ - usb_set_intfdata(interface, dev); - - version = le16_to_cpu(dev->usb_dev->descriptor.bcdDevice); - dev_info(&interface->dev, - "version %x.%02x found at bus %03d address %03d\n", - version >> 8, version & 0xff, - dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - - /* setup i2c adapter description */ - dev->adapter.owner = THIS_MODULE; - dev->adapter.class = I2C_CLASS_HWMON; - dev->adapter.algo = &usb_algorithm; - dev->adapter.algo_data = dev; - snprintf(dev->adapter.name, sizeof(dev->adapter.name), - "i2c-tiny-usb at bus %03d device %03d", - dev->usb_dev->bus->busnum, dev->usb_dev->devnum); - - if (usb_write(&dev->adapter, CMD_SET_DELAY, delay, 0, NULL, 0) != 0) { - dev_err(&dev->adapter.dev, - "failure setting delay to %dus\n", delay); - retval = -EIO; - goto error; - } - - dev->adapter.dev.parent = &dev->interface->dev; - - /* and finally attach to i2c layer */ - i2c_add_adapter(&dev->adapter); - - /* inform user about successful attachment to i2c layer */ - dev_info(&dev->adapter.dev, "connected i2c-tiny-usb device\n"); - - return 0; - - error: - if (dev) - i2c_tiny_usb_free(dev); - - return retval; -} - -static void i2c_tiny_usb_disconnect(struct usb_interface *interface) -{ - struct i2c_tiny_usb *dev = usb_get_intfdata(interface); - - i2c_del_adapter(&dev->adapter); - usb_set_intfdata(interface, NULL); - i2c_tiny_usb_free(dev); - - dev_dbg(&interface->dev, "disconnected\n"); -} - -static struct usb_driver i2c_tiny_usb_driver = { - .name = "i2c-tiny-usb", - .probe = i2c_tiny_usb_probe, - .disconnect = i2c_tiny_usb_disconnect, - .id_table = i2c_tiny_usb_table, -}; - -module_usb_driver(i2c_tiny_usb_driver); - -/* ----- end of usb layer ------------------------------------------------ */ - -MODULE_AUTHOR("Till Harbaum <Till@Harbaum.org>"); -MODULE_DESCRIPTION("i2c-tiny-usb driver v1.0"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-versatile.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-versatile.c deleted file mode 100644 index f585aead..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-versatile.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * i2c-versatile.c - * - * Copyright (C) 2006 ARM Ltd. - * written by Russell King, Deep Blue Solutions Ltd. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/init.h> -#include <linux/platform_device.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/of_i2c.h> - -#define I2C_CONTROL 0x00 -#define I2C_CONTROLS 0x00 -#define I2C_CONTROLC 0x04 -#define SCL (1 << 0) -#define SDA (1 << 1) - -struct i2c_versatile { - struct i2c_adapter adap; - struct i2c_algo_bit_data algo; - void __iomem *base; -}; - -static void i2c_versatile_setsda(void *data, int state) -{ - struct i2c_versatile *i2c = data; - - writel(SDA, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC)); -} - -static void i2c_versatile_setscl(void *data, int state) -{ - struct i2c_versatile *i2c = data; - - writel(SCL, i2c->base + (state ? I2C_CONTROLS : I2C_CONTROLC)); -} - -static int i2c_versatile_getsda(void *data) -{ - struct i2c_versatile *i2c = data; - return !!(readl(i2c->base + I2C_CONTROL) & SDA); -} - -static int i2c_versatile_getscl(void *data) -{ - struct i2c_versatile *i2c = data; - return !!(readl(i2c->base + I2C_CONTROL) & SCL); -} - -static struct i2c_algo_bit_data i2c_versatile_algo = { - .setsda = i2c_versatile_setsda, - .setscl = i2c_versatile_setscl, - .getsda = i2c_versatile_getsda, - .getscl = i2c_versatile_getscl, - .udelay = 30, - .timeout = HZ, -}; - -static int i2c_versatile_probe(struct platform_device *dev) -{ - struct i2c_versatile *i2c; - struct resource *r; - int ret; - - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!r) { - ret = -EINVAL; - goto err_out; - } - - if (!request_mem_region(r->start, resource_size(r), "versatile-i2c")) { - ret = -EBUSY; - goto err_out; - } - - i2c = kzalloc(sizeof(struct i2c_versatile), GFP_KERNEL); - if (!i2c) { - ret = -ENOMEM; - goto err_release; - } - - i2c->base = ioremap(r->start, resource_size(r)); - if (!i2c->base) { - ret = -ENOMEM; - goto err_free; - } - - writel(SCL | SDA, i2c->base + I2C_CONTROLS); - - i2c->adap.owner = THIS_MODULE; - strlcpy(i2c->adap.name, "Versatile I2C adapter", sizeof(i2c->adap.name)); - i2c->adap.algo_data = &i2c->algo; - i2c->adap.dev.parent = &dev->dev; - i2c->adap.dev.of_node = dev->dev.of_node; - i2c->algo = i2c_versatile_algo; - i2c->algo.data = i2c; - - if (dev->id >= 0) { - /* static bus numbering */ - i2c->adap.nr = dev->id; - ret = i2c_bit_add_numbered_bus(&i2c->adap); - } else - /* dynamic bus numbering */ - ret = i2c_bit_add_bus(&i2c->adap); - if (ret >= 0) { - platform_set_drvdata(dev, i2c); - of_i2c_register_devices(&i2c->adap); - return 0; - } - - iounmap(i2c->base); - err_free: - kfree(i2c); - err_release: - release_mem_region(r->start, resource_size(r)); - err_out: - return ret; -} - -static int i2c_versatile_remove(struct platform_device *dev) -{ - struct i2c_versatile *i2c = platform_get_drvdata(dev); - - platform_set_drvdata(dev, NULL); - - i2c_del_adapter(&i2c->adap); - return 0; -} - -static const struct of_device_id i2c_versatile_match[] = { - { .compatible = "arm,versatile-i2c", }, - {}, -}; -MODULE_DEVICE_TABLE(of, i2c_versatile_match); - -static struct platform_driver i2c_versatile_driver = { - .probe = i2c_versatile_probe, - .remove = i2c_versatile_remove, - .driver = { - .name = "versatile-i2c", - .owner = THIS_MODULE, - .of_match_table = i2c_versatile_match, - }, -}; - -static int __init i2c_versatile_init(void) -{ - return platform_driver_register(&i2c_versatile_driver); -} - -static void __exit i2c_versatile_exit(void) -{ - platform_driver_unregister(&i2c_versatile_driver); -} - -subsys_initcall(i2c_versatile_init); -module_exit(i2c_versatile_exit); - -MODULE_DESCRIPTION("ARM Versatile I2C bus driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:versatile-i2c"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-via.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-via.c deleted file mode 100644 index 713d31ad..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-via.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - i2c Support for Via Technologies 82C586B South Bridge - - Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/pci.h> -#include <linux/ioport.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/io.h> - -/* Power management registers */ -#define PM_CFG_REVID 0x08 /* silicon revision code */ -#define PM_CFG_IOBASE0 0x20 -#define PM_CFG_IOBASE1 0x48 - -#define I2C_DIR (pm_io_base+0x40) -#define I2C_OUT (pm_io_base+0x42) -#define I2C_IN (pm_io_base+0x44) -#define I2C_SCL 0x02 /* clock bit in DIR/OUT/IN register */ -#define I2C_SDA 0x04 - -/* io-region reservation */ -#define IOSPACE 0x06 - -static struct pci_driver vt586b_driver; -static u16 pm_io_base; - -/* - It does not appear from the datasheet that the GPIO pins are - open drain. So a we set a low value by setting the direction to - output and a high value by setting the direction to input and - relying on the required I2C pullup. The data value is initialized - to 0 in via_init() and never changed. -*/ -static void bit_via_setscl(void *data, int state) -{ - outb(state ? inb(I2C_DIR) & ~I2C_SCL : inb(I2C_DIR) | I2C_SCL, I2C_DIR); -} - -static void bit_via_setsda(void *data, int state) -{ - outb(state ? inb(I2C_DIR) & ~I2C_SDA : inb(I2C_DIR) | I2C_SDA, I2C_DIR); -} - -static int bit_via_getscl(void *data) -{ - return (0 != (inb(I2C_IN) & I2C_SCL)); -} - -static int bit_via_getsda(void *data) -{ - return (0 != (inb(I2C_IN) & I2C_SDA)); -} - - -static struct i2c_algo_bit_data bit_data = { - .setsda = bit_via_setsda, - .setscl = bit_via_setscl, - .getsda = bit_via_getsda, - .getscl = bit_via_getscl, - .udelay = 5, - .timeout = HZ -}; - -static struct i2c_adapter vt586b_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .name = "VIA i2c", - .algo_data = &bit_data, -}; - - -static DEFINE_PCI_DEVICE_TABLE(vt586b_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3) }, - { 0, } -}; - -MODULE_DEVICE_TABLE (pci, vt586b_ids); - -static int __devinit vt586b_probe(struct pci_dev *dev, const struct pci_device_id *id) -{ - u16 base; - u8 rev; - int res; - - if (pm_io_base) { - dev_err(&dev->dev, "i2c-via: Will only support one host\n"); - return -ENODEV; - } - - pci_read_config_byte(dev, PM_CFG_REVID, &rev); - - switch (rev) { - case 0x00: - base = PM_CFG_IOBASE0; - break; - case 0x01: - case 0x10: - base = PM_CFG_IOBASE1; - break; - - default: - base = PM_CFG_IOBASE1; - /* later revision */ - } - - pci_read_config_word(dev, base, &pm_io_base); - pm_io_base &= (0xff << 8); - - if (!request_region(I2C_DIR, IOSPACE, vt586b_driver.name)) { - dev_err(&dev->dev, "IO 0x%x-0x%x already in use\n", I2C_DIR, I2C_DIR + IOSPACE); - return -ENODEV; - } - - outb(inb(I2C_DIR) & ~(I2C_SDA | I2C_SCL), I2C_DIR); - outb(inb(I2C_OUT) & ~(I2C_SDA | I2C_SCL), I2C_OUT); - - /* set up the sysfs linkage to our parent device */ - vt586b_adapter.dev.parent = &dev->dev; - - res = i2c_bit_add_bus(&vt586b_adapter); - if ( res < 0 ) { - release_region(I2C_DIR, IOSPACE); - pm_io_base = 0; - return res; - } - return 0; -} - -static void __devexit vt586b_remove(struct pci_dev *dev) -{ - i2c_del_adapter(&vt586b_adapter); - release_region(I2C_DIR, IOSPACE); - pm_io_base = 0; -} - - -static struct pci_driver vt586b_driver = { - .name = "vt586b_smbus", - .id_table = vt586b_ids, - .probe = vt586b_probe, - .remove = __devexit_p(vt586b_remove), -}; - -static int __init i2c_vt586b_init(void) -{ - return pci_register_driver(&vt586b_driver); -} - -static void __exit i2c_vt586b_exit(void) -{ - pci_unregister_driver(&vt586b_driver); -} - - -MODULE_AUTHOR("Kyösti Mälkki <kmalkki@cc.hut.fi>"); -MODULE_DESCRIPTION("i2c for Via vt82c586b southbridge"); -MODULE_LICENSE("GPL"); - -module_init(i2c_vt586b_init); -module_exit(i2c_vt586b_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-viapro.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-viapro.c deleted file mode 100644 index 333011c8..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-viapro.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl>, - Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>, - Mark D. Studebaker <mdsxyz123@yahoo.com> - Copyright (C) 2005 - 2008 Jean Delvare <khali@linux-fr.org> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -/* - Supports the following VIA south bridges: - - Chip name PCI ID REV I2C block - VT82C596A 0x3050 no - VT82C596B 0x3051 no - VT82C686A 0x3057 0x30 no - VT82C686B 0x3057 0x40 yes - VT8231 0x8235 no? - VT8233 0x3074 yes - VT8233A 0x3147 yes? - VT8235 0x3177 yes - VT8237R 0x3227 yes - VT8237A 0x3337 yes - VT8237S 0x3372 yes - VT8251 0x3287 yes - CX700 0x8324 yes - VX800/VX820 0x8353 yes - VX855/VX875 0x8409 yes - - Note: we assume there can only be one device, with one SMBus interface. -*/ - -#include <linux/module.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/kernel.h> -#include <linux/stddef.h> -#include <linux/ioport.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/acpi.h> -#include <linux/io.h> - -static struct pci_dev *vt596_pdev; - -#define SMBBA1 0x90 -#define SMBBA2 0x80 -#define SMBBA3 0xD0 - -/* SMBus address offsets */ -static unsigned short vt596_smba; -#define SMBHSTSTS (vt596_smba + 0) -#define SMBHSTCNT (vt596_smba + 2) -#define SMBHSTCMD (vt596_smba + 3) -#define SMBHSTADD (vt596_smba + 4) -#define SMBHSTDAT0 (vt596_smba + 5) -#define SMBHSTDAT1 (vt596_smba + 6) -#define SMBBLKDAT (vt596_smba + 7) - -/* PCI Address Constants */ - -/* SMBus data in configuration space can be found in two places, - We try to select the better one */ - -static unsigned short SMBHSTCFG = 0xD2; - -/* Other settings */ -#define MAX_TIMEOUT 500 - -/* VT82C596 constants */ -#define VT596_QUICK 0x00 -#define VT596_BYTE 0x04 -#define VT596_BYTE_DATA 0x08 -#define VT596_WORD_DATA 0x0C -#define VT596_PROC_CALL 0x10 -#define VT596_BLOCK_DATA 0x14 -#define VT596_I2C_BLOCK_DATA 0x34 - - -/* If force is set to anything different from 0, we forcibly enable the - VT596. DANGEROUS! */ -static bool force; -module_param(force, bool, 0); -MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!"); - -/* If force_addr is set to anything different from 0, we forcibly enable - the VT596 at the given address. VERY DANGEROUS! */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Forcibly enable the SMBus at the given address. " - "EXTREMELY DANGEROUS!"); - - -static struct pci_driver vt596_driver; -static struct i2c_adapter vt596_adapter; - -#define FEATURE_I2CBLOCK (1<<0) -static unsigned int vt596_features; - -#ifdef DEBUG -static void vt596_dump_regs(const char *msg, u8 size) -{ - dev_dbg(&vt596_adapter.dev, "%s: STS=%02x CNT=%02x CMD=%02x ADD=%02x " - "DAT=%02x,%02x\n", msg, inb_p(SMBHSTSTS), inb_p(SMBHSTCNT), - inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), - inb_p(SMBHSTDAT1)); - - if (size == VT596_BLOCK_DATA - || size == VT596_I2C_BLOCK_DATA) { - int i; - - dev_dbg(&vt596_adapter.dev, "BLK="); - for (i = 0; i < I2C_SMBUS_BLOCK_MAX / 2; i++) - printk("%02x,", inb_p(SMBBLKDAT)); - printk("\n"); - dev_dbg(&vt596_adapter.dev, " "); - for (; i < I2C_SMBUS_BLOCK_MAX - 1; i++) - printk("%02x,", inb_p(SMBBLKDAT)); - printk("%02x\n", inb_p(SMBBLKDAT)); - } -} -#else -static inline void vt596_dump_regs(const char *msg, u8 size) { } -#endif - -/* Return -1 on error, 0 on success */ -static int vt596_transaction(u8 size) -{ - int temp; - int result = 0; - int timeout = 0; - - vt596_dump_regs("Transaction (pre)", size); - - /* Make sure the SMBus host is ready to start transmitting */ - if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { - dev_dbg(&vt596_adapter.dev, "SMBus busy (0x%02x). " - "Resetting...\n", temp); - - outb_p(temp, SMBHSTSTS); - if ((temp = inb_p(SMBHSTSTS)) & 0x1F) { - dev_err(&vt596_adapter.dev, "SMBus reset failed! " - "(0x%02x)\n", temp); - return -EBUSY; - } - } - - /* Start the transaction by setting bit 6 */ - outb_p(0x40 | size, SMBHSTCNT); - - /* We will always wait for a fraction of a second */ - do { - msleep(1); - temp = inb_p(SMBHSTSTS); - } while ((temp & 0x01) && (++timeout < MAX_TIMEOUT)); - - /* If the SMBus is still busy, we give up */ - if (timeout == MAX_TIMEOUT) { - result = -ETIMEDOUT; - dev_err(&vt596_adapter.dev, "SMBus timeout!\n"); - } - - if (temp & 0x10) { - result = -EIO; - dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n", - size); - } - - if (temp & 0x08) { - result = -EIO; - dev_err(&vt596_adapter.dev, "SMBus collision!\n"); - } - - if (temp & 0x04) { - result = -ENXIO; - dev_dbg(&vt596_adapter.dev, "No response\n"); - } - - /* Resetting status register */ - if (temp & 0x1F) - outb_p(temp, SMBHSTSTS); - - vt596_dump_regs("Transaction (post)", size); - - return result; -} - -/* Return negative errno on error, 0 on success */ -static s32 vt596_access(struct i2c_adapter *adap, u16 addr, - unsigned short flags, char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - int i; - int status; - - switch (size) { - case I2C_SMBUS_QUICK: - size = VT596_QUICK; - break; - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_WRITE) - outb_p(command, SMBHSTCMD); - size = VT596_BYTE; - break; - case I2C_SMBUS_BYTE_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) - outb_p(data->byte, SMBHSTDAT0); - size = VT596_BYTE_DATA; - break; - case I2C_SMBUS_WORD_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - } - size = VT596_WORD_DATA; - break; - case I2C_SMBUS_PROC_CALL: - outb_p(command, SMBHSTCMD); - outb_p(data->word & 0xff, SMBHSTDAT0); - outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1); - size = VT596_PROC_CALL; - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - if (!(vt596_features & FEATURE_I2CBLOCK)) - goto exit_unsupported; - if (read_write == I2C_SMBUS_READ) - outb_p(data->block[0], SMBHSTDAT0); - /* Fall through */ - case I2C_SMBUS_BLOCK_DATA: - outb_p(command, SMBHSTCMD); - if (read_write == I2C_SMBUS_WRITE) { - u8 len = data->block[0]; - if (len > I2C_SMBUS_BLOCK_MAX) - len = I2C_SMBUS_BLOCK_MAX; - outb_p(len, SMBHSTDAT0); - inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= len; i++) - outb_p(data->block[i], SMBBLKDAT); - } - size = (size == I2C_SMBUS_I2C_BLOCK_DATA) ? - VT596_I2C_BLOCK_DATA : VT596_BLOCK_DATA; - break; - default: - goto exit_unsupported; - } - - outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD); - - status = vt596_transaction(size); - if (status) - return status; - - if (size == VT596_PROC_CALL) - read_write = I2C_SMBUS_READ; - - if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK)) - return 0; - - switch (size) { - case VT596_BYTE: - case VT596_BYTE_DATA: - data->byte = inb_p(SMBHSTDAT0); - break; - case VT596_WORD_DATA: - case VT596_PROC_CALL: - data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8); - break; - case VT596_I2C_BLOCK_DATA: - case VT596_BLOCK_DATA: - data->block[0] = inb_p(SMBHSTDAT0); - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) - data->block[0] = I2C_SMBUS_BLOCK_MAX; - inb_p(SMBHSTCNT); /* Reset SMBBLKDAT */ - for (i = 1; i <= data->block[0]; i++) - data->block[i] = inb_p(SMBBLKDAT); - break; - } - return 0; - -exit_unsupported: - dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n", - size); - return -EOPNOTSUPP; -} - -static u32 vt596_func(struct i2c_adapter *adapter) -{ - u32 func = I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_SMBUS_PROC_CALL | I2C_FUNC_SMBUS_BLOCK_DATA; - - if (vt596_features & FEATURE_I2CBLOCK) - func |= I2C_FUNC_SMBUS_I2C_BLOCK; - return func; -} - -static const struct i2c_algorithm smbus_algorithm = { - .smbus_xfer = vt596_access, - .functionality = vt596_func, -}; - -static struct i2c_adapter vt596_adapter = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &smbus_algorithm, -}; - -static int __devinit vt596_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned char temp; - int error; - - /* Determine the address of the SMBus areas */ - if (force_addr) { - vt596_smba = force_addr & 0xfff0; - force = 0; - goto found; - } - - if ((pci_read_config_word(pdev, id->driver_data, &vt596_smba)) || - !(vt596_smba & 0x0001)) { - /* try 2nd address and config reg. for 596 */ - if (id->device == PCI_DEVICE_ID_VIA_82C596_3 && - !pci_read_config_word(pdev, SMBBA2, &vt596_smba) && - (vt596_smba & 0x0001)) { - SMBHSTCFG = 0x84; - } else { - /* no matches at all */ - dev_err(&pdev->dev, "Cannot configure " - "SMBus I/O Base address\n"); - return -ENODEV; - } - } - - vt596_smba &= 0xfff0; - if (vt596_smba == 0) { - dev_err(&pdev->dev, "SMBus base address " - "uninitialized - upgrade BIOS or use " - "force_addr=0xaddr\n"); - return -ENODEV; - } - -found: - error = acpi_check_region(vt596_smba, 8, vt596_driver.name); - if (error) - return -ENODEV; - - if (!request_region(vt596_smba, 8, vt596_driver.name)) { - dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n", - vt596_smba); - return -ENODEV; - } - - pci_read_config_byte(pdev, SMBHSTCFG, &temp); - /* If force_addr is set, we program the new address here. Just to make - sure, we disable the VT596 first. */ - if (force_addr) { - pci_write_config_byte(pdev, SMBHSTCFG, temp & 0xfe); - pci_write_config_word(pdev, id->driver_data, vt596_smba); - pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); - dev_warn(&pdev->dev, "WARNING: SMBus interface set to new " - "address 0x%04x!\n", vt596_smba); - } else if (!(temp & 0x01)) { - if (force) { - /* NOTE: This assumes I/O space and other allocations - * WERE done by the Bios! Don't complain if your - * hardware does weird things after enabling this. - * :') Check for Bios updates before resorting to - * this. - */ - pci_write_config_byte(pdev, SMBHSTCFG, temp | 0x01); - dev_info(&pdev->dev, "Enabling SMBus device\n"); - } else { - dev_err(&pdev->dev, "SMBUS: Error: Host SMBus " - "controller not enabled! - upgrade BIOS or " - "use force=1\n"); - error = -ENODEV; - goto release_region; - } - } - - dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba); - - switch (pdev->device) { - case PCI_DEVICE_ID_VIA_CX700: - case PCI_DEVICE_ID_VIA_VX800: - case PCI_DEVICE_ID_VIA_VX855: - case PCI_DEVICE_ID_VIA_8251: - case PCI_DEVICE_ID_VIA_8237: - case PCI_DEVICE_ID_VIA_8237A: - case PCI_DEVICE_ID_VIA_8237S: - case PCI_DEVICE_ID_VIA_8235: - case PCI_DEVICE_ID_VIA_8233A: - case PCI_DEVICE_ID_VIA_8233_0: - vt596_features |= FEATURE_I2CBLOCK; - break; - case PCI_DEVICE_ID_VIA_82C686_4: - /* The VT82C686B (rev 0x40) does support I2C block - transactions, but the VT82C686A (rev 0x30) doesn't */ - if (pdev->revision >= 0x40) - vt596_features |= FEATURE_I2CBLOCK; - break; - } - - vt596_adapter.dev.parent = &pdev->dev; - snprintf(vt596_adapter.name, sizeof(vt596_adapter.name), - "SMBus Via Pro adapter at %04x", vt596_smba); - - vt596_pdev = pci_dev_get(pdev); - error = i2c_add_adapter(&vt596_adapter); - if (error) { - pci_dev_put(vt596_pdev); - vt596_pdev = NULL; - goto release_region; - } - - /* Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - return -ENODEV; - -release_region: - release_region(vt596_smba, 8); - return error; -} - -static DEFINE_PCI_DEVICE_TABLE(vt596_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596_3), - .driver_data = SMBBA1 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C596B_3), - .driver_data = SMBBA1 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4), - .driver_data = SMBBA1 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_0), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233A), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8235), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237S), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4), - .driver_data = SMBBA1 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_CX700), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX800), - .driver_data = SMBBA3 }, - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855), - .driver_data = SMBBA3 }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, vt596_ids); - -static struct pci_driver vt596_driver = { - .name = "vt596_smbus", - .id_table = vt596_ids, - .probe = vt596_probe, -}; - -static int __init i2c_vt596_init(void) -{ - return pci_register_driver(&vt596_driver); -} - - -static void __exit i2c_vt596_exit(void) -{ - pci_unregister_driver(&vt596_driver); - if (vt596_pdev != NULL) { - i2c_del_adapter(&vt596_adapter); - release_region(vt596_smba, 8); - pci_dev_put(vt596_pdev); - vt596_pdev = NULL; - } -} - -MODULE_AUTHOR("Kyosti Malkki <kmalkki@cc.hut.fi>, " - "Mark D. Studebaker <mdsxyz123@yahoo.com> and " - "Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("vt82c596 SMBus driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_vt596_init); -module_exit(i2c_vt596_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-xiic.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-xiic.c deleted file mode 100644 index 2bded764..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-xiic.c +++ /dev/null @@ -1,812 +0,0 @@ -/* - * i2c-xiic.c - * Copyright (c) 2002-2007 Xilinx Inc. - * Copyright (c) 2009-2010 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * This code was implemented by Mocean Laboratories AB when porting linux - * to the automotive development board Russellville. The copyright holder - * as seen in the header is Intel corporation. - * Mocean Laboratories forked off the GNU/Linux platform work into a - * separate company called Pelagicore AB, which committed the code to the - * kernel. - */ - -/* Supports: - * Xilinx IIC - */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/delay.h> -#include <linux/platform_device.h> -#include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/wait.h> -#include <linux/i2c-xiic.h> -#include <linux/io.h> -#include <linux/slab.h> - -#define DRIVER_NAME "xiic-i2c" - -enum xilinx_i2c_state { - STATE_DONE, - STATE_ERROR, - STATE_START -}; - -/** - * struct xiic_i2c - Internal representation of the XIIC I2C bus - * @base: Memory base of the HW registers - * @wait: Wait queue for callers - * @adap: Kernel adapter representation - * @tx_msg: Messages from above to be sent - * @lock: Mutual exclusion - * @tx_pos: Current pos in TX message - * @nmsgs: Number of messages in tx_msg - * @state: See STATE_ - * @rx_msg: Current RX message - * @rx_pos: Position within current RX message - */ -struct xiic_i2c { - void __iomem *base; - wait_queue_head_t wait; - struct i2c_adapter adap; - struct i2c_msg *tx_msg; - spinlock_t lock; - unsigned int tx_pos; - unsigned int nmsgs; - enum xilinx_i2c_state state; - struct i2c_msg *rx_msg; - int rx_pos; -}; - - -#define XIIC_MSB_OFFSET 0 -#define XIIC_REG_OFFSET (0x100+XIIC_MSB_OFFSET) - -/* - * Register offsets in bytes from RegisterBase. Three is added to the - * base offset to access LSB (IBM style) of the word - */ -#define XIIC_CR_REG_OFFSET (0x00+XIIC_REG_OFFSET) /* Control Register */ -#define XIIC_SR_REG_OFFSET (0x04+XIIC_REG_OFFSET) /* Status Register */ -#define XIIC_DTR_REG_OFFSET (0x08+XIIC_REG_OFFSET) /* Data Tx Register */ -#define XIIC_DRR_REG_OFFSET (0x0C+XIIC_REG_OFFSET) /* Data Rx Register */ -#define XIIC_ADR_REG_OFFSET (0x10+XIIC_REG_OFFSET) /* Address Register */ -#define XIIC_TFO_REG_OFFSET (0x14+XIIC_REG_OFFSET) /* Tx FIFO Occupancy */ -#define XIIC_RFO_REG_OFFSET (0x18+XIIC_REG_OFFSET) /* Rx FIFO Occupancy */ -#define XIIC_TBA_REG_OFFSET (0x1C+XIIC_REG_OFFSET) /* 10 Bit Address reg */ -#define XIIC_RFD_REG_OFFSET (0x20+XIIC_REG_OFFSET) /* Rx FIFO Depth reg */ -#define XIIC_GPO_REG_OFFSET (0x24+XIIC_REG_OFFSET) /* Output Register */ - -/* Control Register masks */ -#define XIIC_CR_ENABLE_DEVICE_MASK 0x01 /* Device enable = 1 */ -#define XIIC_CR_TX_FIFO_RESET_MASK 0x02 /* Transmit FIFO reset=1 */ -#define XIIC_CR_MSMS_MASK 0x04 /* Master starts Txing=1 */ -#define XIIC_CR_DIR_IS_TX_MASK 0x08 /* Dir of tx. Txing=1 */ -#define XIIC_CR_NO_ACK_MASK 0x10 /* Tx Ack. NO ack = 1 */ -#define XIIC_CR_REPEATED_START_MASK 0x20 /* Repeated start = 1 */ -#define XIIC_CR_GENERAL_CALL_MASK 0x40 /* Gen Call enabled = 1 */ - -/* Status Register masks */ -#define XIIC_SR_GEN_CALL_MASK 0x01 /* 1=a mstr issued a GC */ -#define XIIC_SR_ADDR_AS_SLAVE_MASK 0x02 /* 1=when addr as slave */ -#define XIIC_SR_BUS_BUSY_MASK 0x04 /* 1 = bus is busy */ -#define XIIC_SR_MSTR_RDING_SLAVE_MASK 0x08 /* 1=Dir: mstr <-- slave */ -#define XIIC_SR_TX_FIFO_FULL_MASK 0x10 /* 1 = Tx FIFO full */ -#define XIIC_SR_RX_FIFO_FULL_MASK 0x20 /* 1 = Rx FIFO full */ -#define XIIC_SR_RX_FIFO_EMPTY_MASK 0x40 /* 1 = Rx FIFO empty */ -#define XIIC_SR_TX_FIFO_EMPTY_MASK 0x80 /* 1 = Tx FIFO empty */ - -/* Interrupt Status Register masks Interrupt occurs when... */ -#define XIIC_INTR_ARB_LOST_MASK 0x01 /* 1 = arbitration lost */ -#define XIIC_INTR_TX_ERROR_MASK 0x02 /* 1=Tx error/msg complete */ -#define XIIC_INTR_TX_EMPTY_MASK 0x04 /* 1 = Tx FIFO/reg empty */ -#define XIIC_INTR_RX_FULL_MASK 0x08 /* 1=Rx FIFO/reg=OCY level */ -#define XIIC_INTR_BNB_MASK 0x10 /* 1 = Bus not busy */ -#define XIIC_INTR_AAS_MASK 0x20 /* 1 = when addr as slave */ -#define XIIC_INTR_NAAS_MASK 0x40 /* 1 = not addr as slave */ -#define XIIC_INTR_TX_HALF_MASK 0x80 /* 1 = TX FIFO half empty */ - -/* The following constants specify the depth of the FIFOs */ -#define IIC_RX_FIFO_DEPTH 16 /* Rx fifo capacity */ -#define IIC_TX_FIFO_DEPTH 16 /* Tx fifo capacity */ - -/* The following constants specify groups of interrupts that are typically - * enabled or disables at the same time - */ -#define XIIC_TX_INTERRUPTS \ -(XIIC_INTR_TX_ERROR_MASK | XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK) - -#define XIIC_TX_RX_INTERRUPTS (XIIC_INTR_RX_FULL_MASK | XIIC_TX_INTERRUPTS) - -/* The following constants are used with the following macros to specify the - * operation, a read or write operation. - */ -#define XIIC_READ_OPERATION 1 -#define XIIC_WRITE_OPERATION 0 - -/* - * Tx Fifo upper bit masks. - */ -#define XIIC_TX_DYN_START_MASK 0x0100 /* 1 = Set dynamic start */ -#define XIIC_TX_DYN_STOP_MASK 0x0200 /* 1 = Set dynamic stop */ - -/* - * The following constants define the register offsets for the Interrupt - * registers. There are some holes in the memory map for reserved addresses - * to allow other registers to be added and still match the memory map of the - * interrupt controller registers - */ -#define XIIC_DGIER_OFFSET 0x1C /* Device Global Interrupt Enable Register */ -#define XIIC_IISR_OFFSET 0x20 /* Interrupt Status Register */ -#define XIIC_IIER_OFFSET 0x28 /* Interrupt Enable Register */ -#define XIIC_RESETR_OFFSET 0x40 /* Reset Register */ - -#define XIIC_RESET_MASK 0xAUL - -/* - * The following constant is used for the device global interrupt enable - * register, to enable all interrupts for the device, this is the only bit - * in the register - */ -#define XIIC_GINTR_ENABLE_MASK 0x80000000UL - -#define xiic_tx_space(i2c) ((i2c)->tx_msg->len - (i2c)->tx_pos) -#define xiic_rx_space(i2c) ((i2c)->rx_msg->len - (i2c)->rx_pos) - -static void xiic_start_xfer(struct xiic_i2c *i2c); -static void __xiic_start_xfer(struct xiic_i2c *i2c); - -static inline void xiic_setreg8(struct xiic_i2c *i2c, int reg, u8 value) -{ - iowrite8(value, i2c->base + reg); -} - -static inline u8 xiic_getreg8(struct xiic_i2c *i2c, int reg) -{ - return ioread8(i2c->base + reg); -} - -static inline void xiic_setreg16(struct xiic_i2c *i2c, int reg, u16 value) -{ - iowrite16(value, i2c->base + reg); -} - -static inline void xiic_setreg32(struct xiic_i2c *i2c, int reg, int value) -{ - iowrite32(value, i2c->base + reg); -} - -static inline int xiic_getreg32(struct xiic_i2c *i2c, int reg) -{ - return ioread32(i2c->base + reg); -} - -static inline void xiic_irq_dis(struct xiic_i2c *i2c, u32 mask) -{ - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier & ~mask); -} - -static inline void xiic_irq_en(struct xiic_i2c *i2c, u32 mask) -{ - u32 ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - xiic_setreg32(i2c, XIIC_IIER_OFFSET, ier | mask); -} - -static inline void xiic_irq_clr(struct xiic_i2c *i2c, u32 mask) -{ - u32 isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - xiic_setreg32(i2c, XIIC_IISR_OFFSET, isr & mask); -} - -static inline void xiic_irq_clr_en(struct xiic_i2c *i2c, u32 mask) -{ - xiic_irq_clr(i2c, mask); - xiic_irq_en(i2c, mask); -} - -static void xiic_clear_rx_fifo(struct xiic_i2c *i2c) -{ - u8 sr; - for (sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); - !(sr & XIIC_SR_RX_FIFO_EMPTY_MASK); - sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)) - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); -} - -static void xiic_reinit(struct xiic_i2c *i2c) -{ - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); - - /* Set receive Fifo depth to maximum (zero based). */ - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, IIC_RX_FIFO_DEPTH - 1); - - /* Reset Tx Fifo. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_TX_FIFO_RESET_MASK); - - /* Enable IIC Device, remove Tx Fifo reset & disable general call. */ - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, XIIC_CR_ENABLE_DEVICE_MASK); - - /* make sure RX fifo is empty */ - xiic_clear_rx_fifo(i2c); - - /* Enable interrupts */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); - - xiic_irq_clr_en(i2c, XIIC_INTR_AAS_MASK | XIIC_INTR_ARB_LOST_MASK); -} - -static void xiic_deinit(struct xiic_i2c *i2c) -{ - u8 cr; - - xiic_setreg32(i2c, XIIC_RESETR_OFFSET, XIIC_RESET_MASK); - - /* Disable IIC Device. */ - cr = xiic_getreg8(i2c, XIIC_CR_REG_OFFSET); - xiic_setreg8(i2c, XIIC_CR_REG_OFFSET, cr & ~XIIC_CR_ENABLE_DEVICE_MASK); -} - -static void xiic_read_rx(struct xiic_i2c *i2c) -{ - u8 bytes_in_fifo; - int i; - - bytes_in_fifo = xiic_getreg8(i2c, XIIC_RFO_REG_OFFSET) + 1; - - dev_dbg(i2c->adap.dev.parent, "%s entry, bytes in fifo: %d, msg: %d" - ", SR: 0x%x, CR: 0x%x\n", - __func__, bytes_in_fifo, xiic_rx_space(i2c), - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); - - if (bytes_in_fifo > xiic_rx_space(i2c)) - bytes_in_fifo = xiic_rx_space(i2c); - - for (i = 0; i < bytes_in_fifo; i++) - i2c->rx_msg->buf[i2c->rx_pos++] = - xiic_getreg8(i2c, XIIC_DRR_REG_OFFSET); - - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, - (xiic_rx_space(i2c) > IIC_RX_FIFO_DEPTH) ? - IIC_RX_FIFO_DEPTH - 1 : xiic_rx_space(i2c) - 1); -} - -static int xiic_tx_fifo_space(struct xiic_i2c *i2c) -{ - /* return the actual space left in the FIFO */ - return IIC_TX_FIFO_DEPTH - xiic_getreg8(i2c, XIIC_TFO_REG_OFFSET) - 1; -} - -static void xiic_fill_tx_fifo(struct xiic_i2c *i2c) -{ - u8 fifo_space = xiic_tx_fifo_space(i2c); - int len = xiic_tx_space(i2c); - - len = (len > fifo_space) ? fifo_space : len; - - dev_dbg(i2c->adap.dev.parent, "%s entry, len: %d, fifo space: %d\n", - __func__, len, fifo_space); - - while (len--) { - u16 data = i2c->tx_msg->buf[i2c->tx_pos++]; - if ((xiic_tx_space(i2c) == 0) && (i2c->nmsgs == 1)) { - /* last message in transfer -> STOP */ - data |= XIIC_TX_DYN_STOP_MASK; - dev_dbg(i2c->adap.dev.parent, "%s TX STOP\n", __func__); - - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); - } else - xiic_setreg8(i2c, XIIC_DTR_REG_OFFSET, data); - } -} - -static void xiic_wakeup(struct xiic_i2c *i2c, int code) -{ - i2c->tx_msg = NULL; - i2c->rx_msg = NULL; - i2c->nmsgs = 0; - i2c->state = code; - wake_up(&i2c->wait); -} - -static void xiic_process(struct xiic_i2c *i2c) -{ - u32 pend, isr, ier; - u32 clr = 0; - - /* Get the interrupt Status from the IPIF. There is no clearing of - * interrupts in the IPIF. Interrupts must be cleared at the source. - * To find which interrupts are pending; AND interrupts pending with - * interrupts masked. - */ - isr = xiic_getreg32(i2c, XIIC_IISR_OFFSET); - ier = xiic_getreg32(i2c, XIIC_IIER_OFFSET); - pend = isr & ier; - - dev_dbg(i2c->adap.dev.parent, "%s entry, IER: 0x%x, ISR: 0x%x, " - "pend: 0x%x, SR: 0x%x, msg: %p, nmsgs: %d\n", - __func__, ier, isr, pend, xiic_getreg8(i2c, XIIC_SR_REG_OFFSET), - i2c->tx_msg, i2c->nmsgs); - - /* Do not processes a devices interrupts if the device has no - * interrupts pending - */ - if (!pend) - return; - - /* Service requesting interrupt */ - if ((pend & XIIC_INTR_ARB_LOST_MASK) || - ((pend & XIIC_INTR_TX_ERROR_MASK) && - !(pend & XIIC_INTR_RX_FULL_MASK))) { - /* bus arbritration lost, or... - * Transmit error _OR_ RX completed - * if this happens when RX_FULL is not set - * this is probably a TX error - */ - - dev_dbg(i2c->adap.dev.parent, "%s error\n", __func__); - - /* dynamic mode seem to suffer from problems if we just flushes - * fifos and the next message is a TX with len 0 (only addr) - * reset the IP instead of just flush fifos - */ - xiic_reinit(i2c); - - if (i2c->tx_msg) - xiic_wakeup(i2c, STATE_ERROR); - - } else if (pend & XIIC_INTR_RX_FULL_MASK) { - /* Receive register/FIFO is full */ - - clr = XIIC_INTR_RX_FULL_MASK; - if (!i2c->rx_msg) { - dev_dbg(i2c->adap.dev.parent, - "%s unexpexted RX IRQ\n", __func__); - xiic_clear_rx_fifo(i2c); - goto out; - } - - xiic_read_rx(i2c); - if (xiic_rx_space(i2c) == 0) { - /* this is the last part of the message */ - i2c->rx_msg = NULL; - - /* also clear TX error if there (RX complete) */ - clr |= (isr & XIIC_INTR_TX_ERROR_MASK); - - dev_dbg(i2c->adap.dev.parent, - "%s end of message, nmsgs: %d\n", - __func__, i2c->nmsgs); - - /* send next message if this wasn't the last, - * otherwise the transfer will be finialise when - * receiving the bus not busy interrupt - */ - if (i2c->nmsgs > 1) { - i2c->nmsgs--; - i2c->tx_msg++; - dev_dbg(i2c->adap.dev.parent, - "%s will start next...\n", __func__); - - __xiic_start_xfer(i2c); - } - } - } else if (pend & XIIC_INTR_BNB_MASK) { - /* IIC bus has transitioned to not busy */ - clr = XIIC_INTR_BNB_MASK; - - /* The bus is not busy, disable BusNotBusy interrupt */ - xiic_irq_dis(i2c, XIIC_INTR_BNB_MASK); - - if (!i2c->tx_msg) - goto out; - - if ((i2c->nmsgs == 1) && !i2c->rx_msg && - xiic_tx_space(i2c) == 0) - xiic_wakeup(i2c, STATE_DONE); - else - xiic_wakeup(i2c, STATE_ERROR); - - } else if (pend & (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK)) { - /* Transmit register/FIFO is empty or ½ empty */ - - clr = pend & - (XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_HALF_MASK); - - if (!i2c->tx_msg) { - dev_dbg(i2c->adap.dev.parent, - "%s unexpexted TX IRQ\n", __func__); - goto out; - } - - xiic_fill_tx_fifo(i2c); - - /* current message sent and there is space in the fifo */ - if (!xiic_tx_space(i2c) && xiic_tx_fifo_space(i2c) >= 2) { - dev_dbg(i2c->adap.dev.parent, - "%s end of message sent, nmsgs: %d\n", - __func__, i2c->nmsgs); - if (i2c->nmsgs > 1) { - i2c->nmsgs--; - i2c->tx_msg++; - __xiic_start_xfer(i2c); - } else { - xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); - - dev_dbg(i2c->adap.dev.parent, - "%s Got TX IRQ but no more to do...\n", - __func__); - } - } else if (!xiic_tx_space(i2c) && (i2c->nmsgs == 1)) - /* current frame is sent and is last, - * make sure to disable tx half - */ - xiic_irq_dis(i2c, XIIC_INTR_TX_HALF_MASK); - } else { - /* got IRQ which is not acked */ - dev_err(i2c->adap.dev.parent, "%s Got unexpected IRQ\n", - __func__); - clr = pend; - } -out: - dev_dbg(i2c->adap.dev.parent, "%s clr: 0x%x\n", __func__, clr); - - xiic_setreg32(i2c, XIIC_IISR_OFFSET, clr); -} - -static int xiic_bus_busy(struct xiic_i2c *i2c) -{ - u8 sr = xiic_getreg8(i2c, XIIC_SR_REG_OFFSET); - - return (sr & XIIC_SR_BUS_BUSY_MASK) ? -EBUSY : 0; -} - -static int xiic_busy(struct xiic_i2c *i2c) -{ - int tries = 3; - int err; - - if (i2c->tx_msg) - return -EBUSY; - - /* for instance if previous transfer was terminated due to TX error - * it might be that the bus is on it's way to become available - * give it at most 3 ms to wake - */ - err = xiic_bus_busy(i2c); - while (err && tries--) { - mdelay(1); - err = xiic_bus_busy(i2c); - } - - return err; -} - -static void xiic_start_recv(struct xiic_i2c *i2c) -{ - u8 rx_watermark; - struct i2c_msg *msg = i2c->rx_msg = i2c->tx_msg; - - /* Clear and enable Rx full interrupt. */ - xiic_irq_clr_en(i2c, XIIC_INTR_RX_FULL_MASK | XIIC_INTR_TX_ERROR_MASK); - - /* we want to get all but last byte, because the TX_ERROR IRQ is used - * to inidicate error ACK on the address, and negative ack on the last - * received byte, so to not mix them receive all but last. - * In the case where there is only one byte to receive - * we can check if ERROR and RX full is set at the same time - */ - rx_watermark = msg->len; - if (rx_watermark > IIC_RX_FIFO_DEPTH) - rx_watermark = IIC_RX_FIFO_DEPTH; - xiic_setreg8(i2c, XIIC_RFD_REG_OFFSET, rx_watermark - 1); - - if (!(msg->flags & I2C_M_NOSTART)) - /* write the address */ - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, - (msg->addr << 1) | XIIC_READ_OPERATION | - XIIC_TX_DYN_START_MASK); - - xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, - msg->len | ((i2c->nmsgs == 1) ? XIIC_TX_DYN_STOP_MASK : 0)); - if (i2c->nmsgs == 1) - /* very last, enable bus not busy as well */ - xiic_irq_clr_en(i2c, XIIC_INTR_BNB_MASK); - - /* the message is tx:ed */ - i2c->tx_pos = msg->len; -} - -static void xiic_start_send(struct xiic_i2c *i2c) -{ - struct i2c_msg *msg = i2c->tx_msg; - - xiic_irq_clr(i2c, XIIC_INTR_TX_ERROR_MASK); - - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, len: %d, " - "ISR: 0x%x, CR: 0x%x\n", - __func__, msg, msg->len, xiic_getreg32(i2c, XIIC_IISR_OFFSET), - xiic_getreg8(i2c, XIIC_CR_REG_OFFSET)); - - if (!(msg->flags & I2C_M_NOSTART)) { - /* write the address */ - u16 data = ((msg->addr << 1) & 0xfe) | XIIC_WRITE_OPERATION | - XIIC_TX_DYN_START_MASK; - if ((i2c->nmsgs == 1) && msg->len == 0) - /* no data and last message -> add STOP */ - data |= XIIC_TX_DYN_STOP_MASK; - - xiic_setreg16(i2c, XIIC_DTR_REG_OFFSET, data); - } - - xiic_fill_tx_fifo(i2c); - - /* Clear any pending Tx empty, Tx Error and then enable them. */ - xiic_irq_clr_en(i2c, XIIC_INTR_TX_EMPTY_MASK | XIIC_INTR_TX_ERROR_MASK | - XIIC_INTR_BNB_MASK); -} - -static irqreturn_t xiic_isr(int irq, void *dev_id) -{ - struct xiic_i2c *i2c = dev_id; - - spin_lock(&i2c->lock); - /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); - - dev_dbg(i2c->adap.dev.parent, "%s entry\n", __func__); - - xiic_process(i2c); - - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); - spin_unlock(&i2c->lock); - - return IRQ_HANDLED; -} - -static void __xiic_start_xfer(struct xiic_i2c *i2c) -{ - int first = 1; - int fifo_space = xiic_tx_fifo_space(i2c); - dev_dbg(i2c->adap.dev.parent, "%s entry, msg: %p, fifos space: %d\n", - __func__, i2c->tx_msg, fifo_space); - - if (!i2c->tx_msg) - return; - - i2c->rx_pos = 0; - i2c->tx_pos = 0; - i2c->state = STATE_START; - while ((fifo_space >= 2) && (first || (i2c->nmsgs > 1))) { - if (!first) { - i2c->nmsgs--; - i2c->tx_msg++; - i2c->tx_pos = 0; - } else - first = 0; - - if (i2c->tx_msg->flags & I2C_M_RD) { - /* we dont date putting several reads in the FIFO */ - xiic_start_recv(i2c); - return; - } else { - xiic_start_send(i2c); - if (xiic_tx_space(i2c) != 0) { - /* the message could not be completely sent */ - break; - } - } - - fifo_space = xiic_tx_fifo_space(i2c); - } - - /* there are more messages or the current one could not be completely - * put into the FIFO, also enable the half empty interrupt - */ - if (i2c->nmsgs > 1 || xiic_tx_space(i2c)) - xiic_irq_clr_en(i2c, XIIC_INTR_TX_HALF_MASK); - -} - -static void xiic_start_xfer(struct xiic_i2c *i2c) -{ - unsigned long flags; - - spin_lock_irqsave(&i2c->lock, flags); - xiic_reinit(i2c); - /* disable interrupts globally */ - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, 0); - spin_unlock_irqrestore(&i2c->lock, flags); - - __xiic_start_xfer(i2c); - xiic_setreg32(i2c, XIIC_DGIER_OFFSET, XIIC_GINTR_ENABLE_MASK); -} - -static int xiic_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - struct xiic_i2c *i2c = i2c_get_adapdata(adap); - int err; - - dev_dbg(adap->dev.parent, "%s entry SR: 0x%x\n", __func__, - xiic_getreg8(i2c, XIIC_SR_REG_OFFSET)); - - err = xiic_busy(i2c); - if (err) - return err; - - i2c->tx_msg = msgs; - i2c->nmsgs = num; - - xiic_start_xfer(i2c); - - if (wait_event_timeout(i2c->wait, (i2c->state == STATE_ERROR) || - (i2c->state == STATE_DONE), HZ)) - return (i2c->state == STATE_DONE) ? num : -EIO; - else { - i2c->tx_msg = NULL; - i2c->rx_msg = NULL; - i2c->nmsgs = 0; - return -ETIMEDOUT; - } -} - -static u32 xiic_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; -} - -static const struct i2c_algorithm xiic_algorithm = { - .master_xfer = xiic_xfer, - .functionality = xiic_func, -}; - -static struct i2c_adapter xiic_adapter = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo = &xiic_algorithm, -}; - - -static int __devinit xiic_i2c_probe(struct platform_device *pdev) -{ - struct xiic_i2c *i2c; - struct xiic_i2c_platform_data *pdata; - struct resource *res; - int ret, irq; - u8 i; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - goto resource_missing; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - goto resource_missing; - - pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data; - if (!pdata) - return -EINVAL; - - i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); - if (!i2c) - return -ENOMEM; - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "Memory region busy\n"); - ret = -EBUSY; - goto request_mem_failed; - } - - i2c->base = ioremap(res->start, resource_size(res)); - if (!i2c->base) { - dev_err(&pdev->dev, "Unable to map registers\n"); - ret = -EIO; - goto map_failed; - } - - /* hook up driver to tree */ - platform_set_drvdata(pdev, i2c); - i2c->adap = xiic_adapter; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - - xiic_reinit(i2c); - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - ret = request_irq(irq, xiic_isr, 0, pdev->name, i2c); - if (ret) { - dev_err(&pdev->dev, "Cannot claim IRQ\n"); - goto request_irq_failed; - } - - /* add i2c adapter to i2c tree */ - ret = i2c_add_adapter(&i2c->adap); - if (ret) { - dev_err(&pdev->dev, "Failed to add adapter\n"); - goto add_adapter_failed; - } - - /* add in known devices to the bus */ - for (i = 0; i < pdata->num_devices; i++) - i2c_new_device(&i2c->adap, pdata->devices + i); - - return 0; - -add_adapter_failed: - free_irq(irq, i2c); -request_irq_failed: - xiic_deinit(i2c); - iounmap(i2c->base); -map_failed: - release_mem_region(res->start, resource_size(res)); -request_mem_failed: - kfree(i2c); - - return ret; -resource_missing: - dev_err(&pdev->dev, "IRQ or Memory resource is missing\n"); - return -ENOENT; -} - -static int __devexit xiic_i2c_remove(struct platform_device* pdev) -{ - struct xiic_i2c *i2c = platform_get_drvdata(pdev); - struct resource *res; - - /* remove adapter & data */ - i2c_del_adapter(&i2c->adap); - - xiic_deinit(i2c); - - platform_set_drvdata(pdev, NULL); - - free_irq(platform_get_irq(pdev, 0), i2c); - - iounmap(i2c->base); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res) - release_mem_region(res->start, resource_size(res)); - - kfree(i2c); - - return 0; -} - -static struct platform_driver xiic_i2c_driver = { - .probe = xiic_i2c_probe, - .remove = __devexit_p(xiic_i2c_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - }, -}; - -module_platform_driver(xiic_i2c_driver); - -MODULE_AUTHOR("info@mocean-labs.com"); -MODULE_DESCRIPTION("Xilinx I2C bus driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:"DRIVER_NAME); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/i2c-xlr.c b/ANDROID_3.4.5/drivers/i2c/busses/i2c-xlr.c deleted file mode 100644 index 96d3fabd..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/i2c-xlr.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright 2011, Netlogic Microsystems Inc. - * Copyright 2004, Matt Porter <mporter@kernel.crashing.org> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/i2c.h> -#include <linux/io.h> -#include <linux/platform_device.h> - -/* XLR I2C REGISTERS */ -#define XLR_I2C_CFG 0x00 -#define XLR_I2C_CLKDIV 0x01 -#define XLR_I2C_DEVADDR 0x02 -#define XLR_I2C_ADDR 0x03 -#define XLR_I2C_DATAOUT 0x04 -#define XLR_I2C_DATAIN 0x05 -#define XLR_I2C_STATUS 0x06 -#define XLR_I2C_STARTXFR 0x07 -#define XLR_I2C_BYTECNT 0x08 -#define XLR_I2C_HDSTATIM 0x09 - -/* XLR I2C REGISTERS FLAGS */ -#define XLR_I2C_BUS_BUSY 0x01 -#define XLR_I2C_SDOEMPTY 0x02 -#define XLR_I2C_RXRDY 0x04 -#define XLR_I2C_ACK_ERR 0x08 -#define XLR_I2C_ARB_STARTERR 0x30 - -/* Register Values */ -#define XLR_I2C_CFG_ADDR 0xF8 -#define XLR_I2C_CFG_NOADDR 0xFA -#define XLR_I2C_STARTXFR_ND 0x02 /* No Data */ -#define XLR_I2C_STARTXFR_RD 0x01 /* Read */ -#define XLR_I2C_STARTXFR_WR 0x00 /* Write */ - -#define XLR_I2C_TIMEOUT 10 /* timeout per byte in msec */ - -/* - * On XLR/XLS, we need to use __raw_ IO to read the I2C registers - * because they are in the big-endian MMIO area on the SoC. - * - * The readl/writel implementation on XLR/XLS byteswaps, because - * those are for its little-endian PCI space (see arch/mips/Kconfig). - */ -static inline void xlr_i2c_wreg(u32 __iomem *base, unsigned int reg, u32 val) -{ - __raw_writel(val, base + reg); -} - -static inline u32 xlr_i2c_rdreg(u32 __iomem *base, unsigned int reg) -{ - return __raw_readl(base + reg); -} - -struct xlr_i2c_private { - struct i2c_adapter adap; - u32 __iomem *iobase; -}; - -static int xlr_i2c_tx(struct xlr_i2c_private *priv, u16 len, - u8 *buf, u16 addr) -{ - struct i2c_adapter *adap = &priv->adap; - unsigned long timeout, stoptime, checktime; - u32 i2c_status; - int pos, timedout; - u8 offset, byte; - - offset = buf[0]; - xlr_i2c_wreg(priv->iobase, XLR_I2C_ADDR, offset); - xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); - xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_ADDR); - xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len - 1); - - timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); - stoptime = jiffies + timeout; - timedout = 0; - pos = 1; -retry: - if (len == 1) { - xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, - XLR_I2C_STARTXFR_ND); - } else { - xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, buf[pos]); - xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, - XLR_I2C_STARTXFR_WR); - } - - while (!timedout) { - checktime = jiffies; - i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); - - if (i2c_status & XLR_I2C_SDOEMPTY) { - pos++; - /* need to do a empty dataout after the last byte */ - byte = (pos < len) ? buf[pos] : 0; - xlr_i2c_wreg(priv->iobase, XLR_I2C_DATAOUT, byte); - - /* reset timeout on successful xmit */ - stoptime = jiffies + timeout; - } - timedout = time_after(checktime, stoptime); - - if (i2c_status & XLR_I2C_ARB_STARTERR) { - if (timedout) - break; - goto retry; - } - - if (i2c_status & XLR_I2C_ACK_ERR) - return -EIO; - - if ((i2c_status & XLR_I2C_BUS_BUSY) == 0 && pos >= len) - return 0; - } - dev_err(&adap->dev, "I2C transmit timeout\n"); - return -ETIMEDOUT; -} - -static int xlr_i2c_rx(struct xlr_i2c_private *priv, u16 len, u8 *buf, u16 addr) -{ - struct i2c_adapter *adap = &priv->adap; - u32 i2c_status; - unsigned long timeout, stoptime, checktime; - int nbytes, timedout; - u8 byte; - - xlr_i2c_wreg(priv->iobase, XLR_I2C_CFG, XLR_I2C_CFG_NOADDR); - xlr_i2c_wreg(priv->iobase, XLR_I2C_BYTECNT, len); - xlr_i2c_wreg(priv->iobase, XLR_I2C_DEVADDR, addr); - - timeout = msecs_to_jiffies(XLR_I2C_TIMEOUT); - stoptime = jiffies + timeout; - timedout = 0; - nbytes = 0; -retry: - xlr_i2c_wreg(priv->iobase, XLR_I2C_STARTXFR, XLR_I2C_STARTXFR_RD); - - while (!timedout) { - checktime = jiffies; - i2c_status = xlr_i2c_rdreg(priv->iobase, XLR_I2C_STATUS); - if (i2c_status & XLR_I2C_RXRDY) { - if (nbytes > len) - return -EIO; /* should not happen */ - - /* we need to do a dummy datain when nbytes == len */ - byte = xlr_i2c_rdreg(priv->iobase, XLR_I2C_DATAIN); - if (nbytes < len) - buf[nbytes] = byte; - nbytes++; - - /* reset timeout on successful read */ - stoptime = jiffies + timeout; - } - - timedout = time_after(checktime, stoptime); - if (i2c_status & XLR_I2C_ARB_STARTERR) { - if (timedout) - break; - goto retry; - } - - if (i2c_status & XLR_I2C_ACK_ERR) - return -EIO; - - if ((i2c_status & XLR_I2C_BUS_BUSY) == 0) - return 0; - } - - dev_err(&adap->dev, "I2C receive timeout\n"); - return -ETIMEDOUT; -} - -static int xlr_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct i2c_msg *msg; - int i; - int ret = 0; - struct xlr_i2c_private *priv = i2c_get_adapdata(adap); - - for (i = 0; ret == 0 && i < num; i++) { - msg = &msgs[i]; - if (msg->flags & I2C_M_RD) - ret = xlr_i2c_rx(priv, msg->len, &msg->buf[0], - msg->addr); - else - ret = xlr_i2c_tx(priv, msg->len, &msg->buf[0], - msg->addr); - } - - return (ret != 0) ? ret : num; -} - -static u32 xlr_func(struct i2c_adapter *adap) -{ - /* Emulate SMBUS over I2C */ - return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_I2C; -} - -static struct i2c_algorithm xlr_i2c_algo = { - .master_xfer = xlr_i2c_xfer, - .functionality = xlr_func, -}; - -static int __devinit xlr_i2c_probe(struct platform_device *pdev) -{ - struct xlr_i2c_private *priv; - struct resource *res; - int ret; - - priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - priv->iobase = devm_request_and_ioremap(&pdev->dev, res); - if (!priv->iobase) { - dev_err(&pdev->dev, "devm_request_and_ioremap failed\n"); - return -EBUSY; - } - - priv->adap.dev.parent = &pdev->dev; - priv->adap.owner = THIS_MODULE; - priv->adap.algo_data = priv; - priv->adap.algo = &xlr_i2c_algo; - priv->adap.nr = pdev->id; - priv->adap.class = I2C_CLASS_HWMON; - snprintf(priv->adap.name, sizeof(priv->adap.name), "xlr-i2c"); - - i2c_set_adapdata(&priv->adap, priv); - ret = i2c_add_numbered_adapter(&priv->adap); - if (ret < 0) { - dev_err(&priv->adap.dev, "Failed to add i2c bus.\n"); - return ret; - } - - platform_set_drvdata(pdev, priv); - dev_info(&priv->adap.dev, "Added I2C Bus.\n"); - return 0; -} - -static int __devexit xlr_i2c_remove(struct platform_device *pdev) -{ - struct xlr_i2c_private *priv; - - priv = platform_get_drvdata(pdev); - i2c_del_adapter(&priv->adap); - platform_set_drvdata(pdev, NULL); - return 0; -} - -static struct platform_driver xlr_i2c_driver = { - .probe = xlr_i2c_probe, - .remove = __devexit_p(xlr_i2c_remove), - .driver = { - .name = "xlr-i2cbus", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(xlr_i2c_driver); - -MODULE_AUTHOR("Ganesan Ramalingam <ganesanr@netlogicmicro.com>"); -MODULE_DESCRIPTION("XLR/XLS SoC I2C Controller driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:xlr-i2cbus"); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/scx200_acb.c b/ANDROID_3.4.5/drivers/i2c/busses/scx200_acb.c deleted file mode 100644 index 2eacb778..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/scx200_acb.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> - - National Semiconductor SCx200 ACCESS.bus support - Also supports the AMD CS5535 and AMD CS5536 - - Based on i2c-keywest.c which is: - Copyright (c) 2001 Benjamin Herrenschmidt <benh@kernel.crashing.org> - Copyright (c) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/pci.h> -#include <linux/platform_device.h> -#include <linux/delay.h> -#include <linux/mutex.h> -#include <linux/slab.h> -#include <linux/io.h> - -#include <linux/scx200.h> - -#define NAME "scx200_acb" - -MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); -MODULE_DESCRIPTION("NatSemi SCx200 ACCESS.bus Driver"); -MODULE_ALIAS("platform:cs5535-smb"); -MODULE_LICENSE("GPL"); - -#define MAX_DEVICES 4 -static int base[MAX_DEVICES] = { 0x820, 0x840 }; -module_param_array(base, int, NULL, 0); -MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers"); - -#define POLL_TIMEOUT (HZ/5) - -enum scx200_acb_state { - state_idle, - state_address, - state_command, - state_repeat_start, - state_quick, - state_read, - state_write, -}; - -static const char *scx200_acb_state_name[] = { - "idle", - "address", - "command", - "repeat_start", - "quick", - "read", - "write", -}; - -/* Physical interface */ -struct scx200_acb_iface { - struct scx200_acb_iface *next; - struct i2c_adapter adapter; - unsigned base; - struct mutex mutex; - - /* State machine data */ - enum scx200_acb_state state; - int result; - u8 address_byte; - u8 command; - u8 *ptr; - char needs_reset; - unsigned len; -}; - -/* Register Definitions */ -#define ACBSDA (iface->base + 0) -#define ACBST (iface->base + 1) -#define ACBST_SDAST 0x40 /* SDA Status */ -#define ACBST_BER 0x20 -#define ACBST_NEGACK 0x10 /* Negative Acknowledge */ -#define ACBST_STASTR 0x08 /* Stall After Start */ -#define ACBST_MASTER 0x02 -#define ACBCST (iface->base + 2) -#define ACBCST_BB 0x02 -#define ACBCTL1 (iface->base + 3) -#define ACBCTL1_STASTRE 0x80 -#define ACBCTL1_NMINTE 0x40 -#define ACBCTL1_ACK 0x10 -#define ACBCTL1_STOP 0x02 -#define ACBCTL1_START 0x01 -#define ACBADDR (iface->base + 4) -#define ACBCTL2 (iface->base + 5) -#define ACBCTL2_ENABLE 0x01 - -/************************************************************************/ - -static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) -{ - const char *errmsg; - - dev_dbg(&iface->adapter.dev, "state %s, status = 0x%02x\n", - scx200_acb_state_name[iface->state], status); - - if (status & ACBST_BER) { - errmsg = "bus error"; - goto error; - } - if (!(status & ACBST_MASTER)) { - errmsg = "not master"; - goto error; - } - if (status & ACBST_NEGACK) { - dev_dbg(&iface->adapter.dev, "negative ack in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -ENXIO; - - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - outb(ACBST_STASTR | ACBST_NEGACK, ACBST); - - /* Reset the status register */ - outb(0, ACBST); - return; - } - - switch (iface->state) { - case state_idle: - dev_warn(&iface->adapter.dev, "interrupt in idle state\n"); - break; - - case state_address: - /* Do a pointer write first */ - outb(iface->address_byte & ~1, ACBSDA); - - iface->state = state_command; - break; - - case state_command: - outb(iface->command, ACBSDA); - - if (iface->address_byte & 1) - iface->state = state_repeat_start; - else - iface->state = state_write; - break; - - case state_repeat_start: - outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); - /* fallthrough */ - - case state_quick: - if (iface->address_byte & 1) { - if (iface->len == 1) - outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); - else - outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); - outb(iface->address_byte, ACBSDA); - - iface->state = state_read; - } else { - outb(iface->address_byte, ACBSDA); - - iface->state = state_write; - } - break; - - case state_read: - /* Set ACK if _next_ byte will be the last one */ - if (iface->len == 2) - outb(inb(ACBCTL1) | ACBCTL1_ACK, ACBCTL1); - else - outb(inb(ACBCTL1) & ~ACBCTL1_ACK, ACBCTL1); - - if (iface->len == 1) { - iface->result = 0; - iface->state = state_idle; - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - } - - *iface->ptr++ = inb(ACBSDA); - --iface->len; - - break; - - case state_write: - if (iface->len == 0) { - iface->result = 0; - iface->state = state_idle; - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - break; - } - - outb(*iface->ptr++, ACBSDA); - --iface->len; - - break; - } - - return; - - error: - dev_err(&iface->adapter.dev, - "%s in state %s (addr=0x%02x, len=%d, status=0x%02x)\n", errmsg, - scx200_acb_state_name[iface->state], iface->address_byte, - iface->len, status); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -static void scx200_acb_poll(struct scx200_acb_iface *iface) -{ - u8 status; - unsigned long timeout; - - timeout = jiffies + POLL_TIMEOUT; - while (1) { - status = inb(ACBST); - - /* Reset the status register to avoid the hang */ - outb(0, ACBST); - - if ((status & (ACBST_SDAST|ACBST_BER|ACBST_NEGACK)) != 0) { - scx200_acb_machine(iface, status); - return; - } - if (time_after(jiffies, timeout)) - break; - cpu_relax(); - cond_resched(); - } - - dev_err(&iface->adapter.dev, "timeout in state %s\n", - scx200_acb_state_name[iface->state]); - - iface->state = state_idle; - iface->result = -EIO; - iface->needs_reset = 1; -} - -static void scx200_acb_reset(struct scx200_acb_iface *iface) -{ - /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - /* Polling mode */ - outb(0, ACBCTL1); - /* Disable slave address */ - outb(0, ACBADDR); - /* Enable the ACCESS.bus device */ - outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); - /* Free STALL after START */ - outb(inb(ACBCTL1) & ~(ACBCTL1_STASTRE | ACBCTL1_NMINTE), ACBCTL1); - /* Send a STOP */ - outb(inb(ACBCTL1) | ACBCTL1_STOP, ACBCTL1); - /* Clear BER, NEGACK and STASTR bits */ - outb(ACBST_BER | ACBST_NEGACK | ACBST_STASTR, ACBST); - /* Clear BB bit */ - outb(inb(ACBCST) | ACBCST_BB, ACBCST); -} - -static s32 scx200_acb_smbus_xfer(struct i2c_adapter *adapter, - u16 address, unsigned short flags, - char rw, u8 command, int size, - union i2c_smbus_data *data) -{ - struct scx200_acb_iface *iface = i2c_get_adapdata(adapter); - int len; - u8 *buffer; - u16 cur_word; - int rc; - - switch (size) { - case I2C_SMBUS_QUICK: - len = 0; - buffer = NULL; - break; - - case I2C_SMBUS_BYTE: - len = 1; - buffer = rw ? &data->byte : &command; - break; - - case I2C_SMBUS_BYTE_DATA: - len = 1; - buffer = &data->byte; - break; - - case I2C_SMBUS_WORD_DATA: - len = 2; - cur_word = cpu_to_le16(data->word); - buffer = (u8 *)&cur_word; - break; - - case I2C_SMBUS_I2C_BLOCK_DATA: - len = data->block[0]; - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EINVAL; - buffer = &data->block[1]; - break; - - default: - return -EINVAL; - } - - dev_dbg(&adapter->dev, - "size=%d, address=0x%x, command=0x%x, len=%d, read=%d\n", - size, address, command, len, rw); - - if (!len && rw == I2C_SMBUS_READ) { - dev_dbg(&adapter->dev, "zero length read\n"); - return -EINVAL; - } - - mutex_lock(&iface->mutex); - - iface->address_byte = (address << 1) | rw; - iface->command = command; - iface->ptr = buffer; - iface->len = len; - iface->result = -EINVAL; - iface->needs_reset = 0; - - outb(inb(ACBCTL1) | ACBCTL1_START, ACBCTL1); - - if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) - iface->state = state_quick; - else - iface->state = state_address; - - while (iface->state != state_idle) - scx200_acb_poll(iface); - - if (iface->needs_reset) - scx200_acb_reset(iface); - - rc = iface->result; - - mutex_unlock(&iface->mutex); - - if (rc == 0 && size == I2C_SMBUS_WORD_DATA && rw == I2C_SMBUS_READ) - data->word = le16_to_cpu(cur_word); - -#ifdef DEBUG - dev_dbg(&adapter->dev, "transfer done, result: %d", rc); - if (buffer) { - int i; - printk(" data:"); - for (i = 0; i < len; ++i) - printk(" %02x", buffer[i]); - } - printk("\n"); -#endif - - return rc; -} - -static u32 scx200_acb_func(struct i2c_adapter *adapter) -{ - return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | - I2C_FUNC_SMBUS_I2C_BLOCK; -} - -/* For now, we only handle combined mode (smbus) */ -static const struct i2c_algorithm scx200_acb_algorithm = { - .smbus_xfer = scx200_acb_smbus_xfer, - .functionality = scx200_acb_func, -}; - -static struct scx200_acb_iface *scx200_acb_list; -static DEFINE_MUTEX(scx200_acb_list_mutex); - -static __devinit int scx200_acb_probe(struct scx200_acb_iface *iface) -{ - u8 val; - - /* Disable the ACCESS.bus device and Configure the SCL - frequency: 16 clock cycles */ - outb(0x70, ACBCTL2); - - if (inb(ACBCTL2) != 0x70) { - pr_debug(NAME ": ACBCTL2 readback failed\n"); - return -ENXIO; - } - - outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); - - val = inb(ACBCTL1); - if (val) { - pr_debug(NAME ": disabled, but ACBCTL1=0x%02x\n", - val); - return -ENXIO; - } - - outb(inb(ACBCTL2) | ACBCTL2_ENABLE, ACBCTL2); - - outb(inb(ACBCTL1) | ACBCTL1_NMINTE, ACBCTL1); - - val = inb(ACBCTL1); - if ((val & ACBCTL1_NMINTE) != ACBCTL1_NMINTE) { - pr_debug(NAME ": enabled, but NMINTE won't be set, " - "ACBCTL1=0x%02x\n", val); - return -ENXIO; - } - - return 0; -} - -static __devinit struct scx200_acb_iface *scx200_create_iface(const char *text, - struct device *dev, int index) -{ - struct scx200_acb_iface *iface; - struct i2c_adapter *adapter; - - iface = kzalloc(sizeof(*iface), GFP_KERNEL); - if (!iface) { - printk(KERN_ERR NAME ": can't allocate memory\n"); - return NULL; - } - - adapter = &iface->adapter; - i2c_set_adapdata(adapter, iface); - snprintf(adapter->name, sizeof(adapter->name), "%s ACB%d", text, index); - adapter->owner = THIS_MODULE; - adapter->algo = &scx200_acb_algorithm; - adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - adapter->dev.parent = dev; - - mutex_init(&iface->mutex); - - return iface; -} - -static int __devinit scx200_acb_create(struct scx200_acb_iface *iface) -{ - struct i2c_adapter *adapter; - int rc; - - adapter = &iface->adapter; - - rc = scx200_acb_probe(iface); - if (rc) { - printk(KERN_WARNING NAME ": probe failed\n"); - return rc; - } - - scx200_acb_reset(iface); - - if (i2c_add_adapter(adapter) < 0) { - printk(KERN_ERR NAME ": failed to register\n"); - return -ENODEV; - } - - if (!adapter->dev.parent) { - /* If there's no dev, we're tracking (ISA) ifaces manually */ - mutex_lock(&scx200_acb_list_mutex); - iface->next = scx200_acb_list; - scx200_acb_list = iface; - mutex_unlock(&scx200_acb_list_mutex); - } - - return 0; -} - -static struct scx200_acb_iface * __devinit scx200_create_dev(const char *text, - unsigned long base, int index, struct device *dev) -{ - struct scx200_acb_iface *iface; - int rc; - - iface = scx200_create_iface(text, dev, index); - - if (iface == NULL) - return NULL; - - if (!request_region(base, 8, iface->adapter.name)) { - printk(KERN_ERR NAME ": can't allocate io 0x%lx-0x%lx\n", - base, base + 8 - 1); - goto errout_free; - } - - iface->base = base; - rc = scx200_acb_create(iface); - - if (rc == 0) - return iface; - - release_region(base, 8); - errout_free: - kfree(iface); - return NULL; -} - -static int __devinit scx200_probe(struct platform_device *pdev) -{ - struct scx200_acb_iface *iface; - struct resource *res; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!res) { - dev_err(&pdev->dev, "can't fetch device resource info\n"); - return -ENODEV; - } - - iface = scx200_create_dev("CS5535", res->start, 0, &pdev->dev); - if (!iface) - return -EIO; - - dev_info(&pdev->dev, "SCx200 device '%s' registered\n", - iface->adapter.name); - platform_set_drvdata(pdev, iface); - - return 0; -} - -static void __devexit scx200_cleanup_iface(struct scx200_acb_iface *iface) -{ - i2c_del_adapter(&iface->adapter); - release_region(iface->base, 8); - kfree(iface); -} - -static int __devexit scx200_remove(struct platform_device *pdev) -{ - struct scx200_acb_iface *iface; - - iface = platform_get_drvdata(pdev); - platform_set_drvdata(pdev, NULL); - scx200_cleanup_iface(iface); - - return 0; -} - -static struct platform_driver scx200_pci_driver = { - .driver = { - .name = "cs5535-smb", - .owner = THIS_MODULE, - }, - .probe = scx200_probe, - .remove = __devexit_p(scx200_remove), -}; - -static DEFINE_PCI_DEVICE_TABLE(scx200_isa) = { - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SCx200_BRIDGE) }, - { PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_SC1100_BRIDGE) }, - { 0, } -}; - -static __init void scx200_scan_isa(void) -{ - int i; - - if (!pci_dev_present(scx200_isa)) - return; - - for (i = 0; i < MAX_DEVICES; ++i) { - if (base[i] == 0) - continue; - - /* XXX: should we care about failures? */ - scx200_create_dev("SCx200", base[i], i, NULL); - } -} - -static int __init scx200_acb_init(void) -{ - pr_debug(NAME ": NatSemi SCx200 ACCESS.bus Driver\n"); - - /* First scan for ISA-based devices */ - scx200_scan_isa(); /* XXX: should we care about errors? */ - - /* If at least one bus was created, init must succeed */ - if (scx200_acb_list) - return 0; - - /* No ISA devices; register the platform driver for PCI-based devices */ - return platform_driver_register(&scx200_pci_driver); -} - -static void __exit scx200_acb_cleanup(void) -{ - struct scx200_acb_iface *iface; - - platform_driver_unregister(&scx200_pci_driver); - - mutex_lock(&scx200_acb_list_mutex); - while ((iface = scx200_acb_list) != NULL) { - scx200_acb_list = iface->next; - mutex_unlock(&scx200_acb_list_mutex); - - scx200_cleanup_iface(iface); - - mutex_lock(&scx200_acb_list_mutex); - } - mutex_unlock(&scx200_acb_list_mutex); -} - -module_init(scx200_acb_init); -module_exit(scx200_acb_cleanup); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/scx200_i2c.c b/ANDROID_3.4.5/drivers/i2c/busses/scx200_i2c.c deleted file mode 100644 index 7ee0d502..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/scx200_i2c.c +++ /dev/null @@ -1,131 +0,0 @@ -/* linux/drivers/i2c/busses/scx200_i2c.c - - Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> - - National Semiconductor SCx200 I2C bus on GPIO pins - - Based on i2c-velleman.c Copyright (C) 1995-96, 2000 Simon G. Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -*/ - -#include <linux/module.h> -#include <linux/errno.h> -#include <linux/kernel.h> -#include <linux/init.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> -#include <linux/io.h> - -#include <linux/scx200_gpio.h> - -#define NAME "scx200_i2c" - -MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); -MODULE_DESCRIPTION("NatSemi SCx200 I2C Driver"); -MODULE_LICENSE("GPL"); - -static int scl = CONFIG_SCx200_I2C_SCL; -static int sda = CONFIG_SCx200_I2C_SDA; - -module_param(scl, int, 0); -MODULE_PARM_DESC(scl, "GPIO line for SCL"); -module_param(sda, int, 0); -MODULE_PARM_DESC(sda, "GPIO line for SDA"); - -static void scx200_i2c_setscl(void *data, int state) -{ - scx200_gpio_set(scl, state); -} - -static void scx200_i2c_setsda(void *data, int state) -{ - scx200_gpio_set(sda, state); -} - -static int scx200_i2c_getscl(void *data) -{ - return scx200_gpio_get(scl); -} - -static int scx200_i2c_getsda(void *data) -{ - return scx200_gpio_get(sda); -} - -/* ------------------------------------------------------------------------ - * Encapsulate the above functions in the correct operations structure. - * This is only done when more than one hardware adapter is supported. - */ - -static struct i2c_algo_bit_data scx200_i2c_data = { - .setsda = scx200_i2c_setsda, - .setscl = scx200_i2c_setscl, - .getsda = scx200_i2c_getsda, - .getscl = scx200_i2c_getscl, - .udelay = 10, - .timeout = HZ, -}; - -static struct i2c_adapter scx200_i2c_ops = { - .owner = THIS_MODULE, - .class = I2C_CLASS_HWMON | I2C_CLASS_SPD, - .algo_data = &scx200_i2c_data, - .name = "NatSemi SCx200 I2C", -}; - -static int scx200_i2c_init(void) -{ - pr_debug(NAME ": NatSemi SCx200 I2C Driver\n"); - - if (!scx200_gpio_present()) { - printk(KERN_ERR NAME ": no SCx200 gpio pins available\n"); - return -ENODEV; - } - - pr_debug(NAME ": SCL=GPIO%02u, SDA=GPIO%02u\n", scl, sda); - - if (scl == -1 || sda == -1 || scl == sda) { - printk(KERN_ERR NAME ": scl and sda must be specified\n"); - return -EINVAL; - } - - /* Configure GPIOs as open collector outputs */ - scx200_gpio_configure(scl, ~2, 5); - scx200_gpio_configure(sda, ~2, 5); - - if (i2c_bit_add_bus(&scx200_i2c_ops) < 0) { - printk(KERN_ERR NAME ": adapter %s registration failed\n", - scx200_i2c_ops.name); - return -ENODEV; - } - - return 0; -} - -static void scx200_i2c_cleanup(void) -{ - i2c_del_adapter(&scx200_i2c_ops); -} - -module_init(scx200_i2c_init); -module_exit(scx200_i2c_cleanup); - -/* - Local variables: - compile-command: "make -k -C ../.. SUBDIRS=drivers/i2c modules" - c-basic-offset: 8 - End: -*/ diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-1.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-1.c deleted file mode 100755 index 3fd0f5a3..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-1.c +++ /dev/null @@ -1,1294 +0,0 @@ -/*++ - drivers/i2c/busses/wmt_i2c_bus-1.c - - Copyright (c) 2013 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ -/* Include your headers here*/ -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <mach/wmt-i2c-bus.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <linux/syscore_ops.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else - #define DPRINTK printf - -#endif - - -#define MAX_BUS_READY_CNT 50 /* jiffy*/ -#define MAX_TX_TIMEOUT 500 /* ms*/ -#define MAX_RX_TIMEOUT 500 /* ms*/ -#define CTRL_GPIO GPIO_CTRL_GP17_I2C_BYTE_ADDR -#define PU_EN_GPIO PULL_EN_GP17_I2C_BYTE_ADDR -#define PU_CTRL_GPIO PULL_CTRL_GP17_I2C_BYTE_ADDR - -#define USE_UBOOT_PARA - -struct wmt_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int volatile isr_nack ; - int volatile isr_byte_end ; - int volatile isr_timeout ; - int volatile isr_int_pending ; -}; - -static int i2c_wmt_wait_bus_not_busy(void); -static int i2c_wmt_wait_bus_release(void); -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int speed_mode = 0; -unsigned int wmt_i2c1_speed_mode = 0; -static unsigned int is_master = 1;/*master:1, slave:0*/ -unsigned int wmt_i2c1_is_master = 1; -static unsigned int wmt_i2c1_power_state = 0;/*0:power on, 1:suspend, 2:shutdown*/ -EXPORT_SYMBOL(wmt_i2c1_is_master); - -/**/ -/* variable*/ -/*-------------------------------------------------*/ -static volatile struct wmt_i2c_s i2c ; - -DECLARE_WAIT_QUEUE_HEAD(i2c_wait); -/* -spinlock_t i2c_wmt_irqlock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_wmt_irqlock); -static struct list_head wmt_i2c_fifohead; -/* -static spinlock_t i2c_fifolock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_fifolock); -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); - -static void i2c_wmt_set_mode(enum i2c_mode_e mode /*!<; //[IN] mode */) -{ - if (is_master == 0) - return; - i2c.i2c_mode = mode ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - DPRINTK("I2C: set standard mode \n"); - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - DPRINTK("I2C: set fast mode \n"); - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - } -} - - -static int i2c_send_request( - struct i2c_msg *msg, - int msg_num, - int non_block, - void (*callback)(void *data), - void *data -) -{ - struct wmt_i2cbusfifo *i2c_fifo_head; - struct i2c_msg *pmsg = NULL; - int ret = 0; - int restart = 0; - int last = 0; - unsigned long flags; - int slave_addr = msg[0].addr; - - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (wmt_i2c1_power_state == 2) { - printk("I2C1 has been shutdown\n"); - return -EIO; - } - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - if (non_block == 0) - i2c.isr_int_pending = 0; - - i2c_fifo_head = kzalloc(sizeof(struct wmt_i2cbusfifo), GFP_ATOMIC); - if (!i2c_fifo_head) { - pr_err("%s: kzalloc fail\n", __func__); - return -ENOMEM; - } - INIT_LIST_HEAD(&i2c_fifo_head->busfifohead); - - pmsg = &msg[0]; - i2c_fifo_head->msg = pmsg; - i2c_fifo_head->msg_num = msg_num; - - if (list_empty(&wmt_i2c_fifohead)) { - if (i2c_wmt_wait_bus_release()) { - kfree(i2c_fifo_head); - printk("i2c1 bus has been pull down by slave\n"); - return -EIO; - } - } - - spin_lock_irqsave(&i2c_fifolock, flags); - if (list_empty(&wmt_i2c_fifohead)) { - i2c_wmt_wait_bus_not_busy(); - pmsg = &msg[0]; - i2c_fifo_head->xfer_length = 1; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - if (pmsg->flags & I2C_M_RD) { - i2c_fifo_head->xfer_length = 1; - ret = i2c_wmt_read_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } else { - i2c_fifo_head->xfer_length = 1; - if (pmsg->flags & I2C_M_NOSTART) - i2c_fifo_head->restart = 1; - else - i2c_fifo_head->restart = 0; - ret = i2c_wmt_write_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } - - } else { - i2c_fifo_head->xfer_length = 0; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - } - spin_unlock_irqrestore(&i2c_fifolock, flags); - if (non_block == 0) { - wait_event(i2c_wait, i2c.isr_int_pending); -#if 0 - if(wait_event_timeout(i2c_wait, i2c.isr_int_pending, HZ) == 0) { - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - if( fifo_head ){ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - fifo_head = NULL; - } - i2c.regs->cr_reg = 0 ; - i2c.regs->cr_reg |= I2C_CR_ENABLE ; - return -ETIMEDOUT; - } -#endif - ret = msg_num; - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - ret = -ETIMEDOUT ; - } - - } - - return ret; - - -} -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value; - int ret = 0; - - DPRINTK("[%s]:length = %d , slave_addr = %x\n", __func__, length , slave_addr); - - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - tcr_value = 0 ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - return ret; -} - -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int ret = 0 ; - - DPRINTK("[%s]length = %d , slave_addr = %x\n", __func__, length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - ret = 0 ; - return ret; - -} -static int i2c_wmt_read_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete read */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result = 0 ; - - if (is_master == 0) - return -ENXIO; - if (length <= 0) - return -1 ; - xfer_length = 0 ; - - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - ret = 0 ; - for (; ;) { - is_timeout = 0 ; - wait_event_result = wait_event_interruptible_timeout(i2c_wait, i2c.isr_int_pending , - (MAX_RX_TIMEOUT * HZ / 1000)) ; - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (rx) \n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (rx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err: write software timeout error (rx) \n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - buf[xfer_length] = (i2c.regs->cdr_reg >> 8) ; - ++xfer_length ; - DPRINTK("i2c_test: received BYTE_END\n\r"); - } - i2c.isr_int_pending = 0; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - if (length > xfer_length) { - if ((length - 1) == xfer_length) { /* next read is the last one*/ - i2c.regs->cr_reg |= (I2C_CR_TX_NEXT_NO_ACK | I2C_CR_CPU_RDY); - DPRINTK("i2c_test: set CPU_RDY & TX_ACK. next data is last.\r\n"); - } else { - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - DPRINTK("i2c_test: more data to read. only set CPU_RDY. \r\n"); - } - } else if (length == xfer_length) { /* end rx xfer*/ - if (last == 1) { /* stop case*/ - DPRINTK("i2c_test: read completed \r\n"); - break ; - } else { /* restart case*/ - /* ??? how to handle the restart after read ?*/ - DPRINTK("i2c_test: RX ReStart Case \r\n") ; - break ; - } - } else { - DPRINTK("i2c_err : read known error\n\r") ; - ret = -EIO ; - break ; - } - } - - DPRINTK("i2c_test: read sequence completed\n\r"); - return ret ; -} - -static int i2c_wmt_write_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete write */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result ; - - DPRINTK("length = %d , slave_addr = %x\n", length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - - ret = 0 ; - for (; ;) { - - is_timeout = 0 ; - /**/ - /* I2C: Wait for interrupt. if ( i2c.isr_int_pending == 1 ) ==> an interrupt exsits.*/ - /**/ - wait_event_result = wait_event_interruptible_timeout(i2c_wait, i2c.isr_int_pending , (MAX_TX_TIMEOUT * HZ / 1000)) ; - - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (tx)\n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (tx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (tx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (tx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err : write software timeout error (tx)\n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - DPRINTK("i2c: isr end byte (tx)\n\r") ; - ++xfer_length ; - } - i2c.isr_int_pending = 0 ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - - if ((i2c.regs->csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK) { - DPRINTK("i2c_err : write RCV NACK error\n\r") ; - ret = -EIO ; - break ; - } - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) { - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - break ; - } - if (length > xfer_length) { - i2c.regs->cdr_reg = (unsigned short) (buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - i2c.regs->cr_reg = (I2C_CR_CPU_RDY | I2C_CR_ENABLE) ; - DPRINTK("i2c_test: write register data \n\r") ; - } else if (length == xfer_length) { /* end tx xfer*/ - if (last == 1) { /* stop case*/ - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - DPRINTK("i2c_test: finish write \n\r") ; - break ; - } else { /* restart case*/ - /* handle the restart for first write then the next is read*/ - i2c.regs->cr_reg = (I2C_CR_ENABLE) ; - DPRINTK("i2c_test: tx restart Case \n\r") ; - break ; - } - } else { - DPRINTK("i2c_err : write unknown error\n\r") ; - ret = -EIO ; - break ; - } - } ; - - DPRINTK("i2c_test: write sequence completed\n\r"); - - return ret ; -} - -static int i2c_wmt_wait_bus_not_busy(void) -{ - int ret ; - int cnt ; - - ret = 0 ; - cnt = 0 ; - while (1) { - if ((REG16_VAL(I2C1_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) { - ret = 0; - break ; - } - cnt++ ; - - if (cnt > MAX_BUS_READY_CNT) { - ret = (-EBUSY) ; - printk("i2c_err : wait but not ready time-out\n\r") ; - cnt = 0; - break; - } - } - return ret ; -} - -static int i2c_wmt_wait_bus_release(void) -{ - int val, cnt = 0; - while(1) { - val = REG8_VAL(__GPIO_BASE + 0x0011); - if (0x0c == (val & 0x0c)) - return 0; - udelay(1); - cnt ++; - if (cnt > 5000) { - return -ETIMEDOUT; - } - } - } - -static void i2c_wmt_reset(void) -{ - unsigned short tmp ; - if (is_master == 0) - return; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C1_BASE_ADDR ; - i2c.irq_no = IRQ_I2C1 ; - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* hardware initial*/ - /**/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - else if (i2c.i2c_mode == I2C_FAST_MODE) - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - - DPRINTK("Resetting I2C Controller Unit\n"); - - return ; -} -static int wmt_i2c_transfer_msg(struct wmt_i2cbusfifo *fifo_head) -{ - int xfer_length = fifo_head->xfer_length; - int xfer_msgnum = fifo_head->xfer_msgnum; - struct i2c_msg *pmsg = &fifo_head->msg[xfer_msgnum]; - int restart = fifo_head->restart; - unsigned short tcr_value; - unsigned short slave_addr = pmsg->addr; - int length = pmsg->len; - int ret = 0; - - if (pmsg->flags & I2C_M_RD) { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } else { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(pmsg->buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - } - return ret; -} - -static irqreturn_t i2c_wmt_handler( - int this_irq, /*!<; //[IN] IRQ number */ - void *dev_id /*!<; //[IN] Pointer to device ID */ -) -{ - int wakeup ; - unsigned short isr_status ; - unsigned short tmp ; - unsigned long flags; - struct wmt_i2cbusfifo *fifo_head; - int xfer_length = 0; - int xfer_msgnum = 0; - struct i2c_msg *pmsg; - volatile unsigned short csr_reg; - - spin_lock_irqsave(&i2c_wmt_irqlock, flags); - isr_status = i2c.regs->isr_reg ; - csr_reg = i2c.regs->csr_reg; - wakeup = 0 ; - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - - if (isr_status & I2C_ISR_NACK_ADDR) { - DPRINTK("[%s]:i2c NACK\n", __func__); - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_NACK_ADDR_WRITE_CLEAR ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.isr_nack = 1 ; - wakeup = 1 ; - } - - if ((isr_status & I2C_ISR_BYTE_END && ((csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK))) { - /* - printk("data rcv nack\n"); - */ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_nack = 1 ; - wakeup = 1 ; - } else if (isr_status & I2C_ISR_BYTE_END) { - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_byte_end = 1 ; - xfer_length = fifo_head->xfer_length; - xfer_msgnum = fifo_head->xfer_msgnum; - pmsg = &fifo_head->msg[xfer_msgnum]; - - /*read case*/ - if (pmsg->flags & I2C_M_RD) { - pmsg->buf[xfer_length - 1] = (i2c.regs->cdr_reg >> 8) ; - /*the last data in current msg?*/ - if (xfer_length == pmsg->len - 1) { - /*last msg of the current request?*/ - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_TX_NEXT_NO_ACK); - } - /*spin_unlock(&i2c_fifolock);*/ - } else if (xfer_length == pmsg->len) {/*next msg*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else { /*data of this msg has been transfered*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*next request exist?*/ - if (list_empty(&wmt_i2c_fifohead)) {/*no more reqeust*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - } else { /*more request*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - fifo_head->xfer_length = 0; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - - /* - if (fifo_head->non_block == 0) { - printk("2 : non callback\n"); - wakeup = 1; - } else { - printk("2 :callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } - - } else { /*write case*/ - /*the last data in current msg?*/ - if (xfer_length == pmsg->len) { - /*last msg of the current request?*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - } - /*access next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else {/*this request finish*/ - /*spin_lock(&i2c_fifolock);*/ - /*next request exist?*/ - list_del(&fifo_head->busfifohead);/*del request*/ - if (list_empty(&wmt_i2c_fifohead)) { - /*kfree(fifo_head);*/ - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - - } else { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - /*next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /* - if (fifo_head->non_block == 0) { - printk("4:non callback\n"); - wakeup = 1; - } else { - printk("4:callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - i2c.regs->cdr_reg = (unsigned short) (pmsg->buf[fifo_head->xfer_length] & I2C_CDR_DATA_WRITE_MASK); - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_ENABLE); - } - } - } - - if (isr_status & I2C_ISR_SCL_TIME_OUT) { - printk("[%s]I2C1 SCL timeout\n", __func__); -#if 0 - i2c.regs->cr_reg |= BIT7;/*reset status*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR | I2C_ISR_BYTE_END_WRITE_CLEAR; - i2c.isr_timeout = 1 ; - wakeup = 1; -#endif - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR ; - } - - - if (wakeup) { - /*spin_lock_irqsave(&i2c_wmt_irqlock, flags);*/ - i2c.isr_int_pending = 1; - /*spin_unlock_irqrestore(&i2c_wmt_irqlock, flags);*/ - wake_up(&i2c_wait); - } else - DPRINTK("i2c_err : unknown I2C ISR Handle 0x%4.4X" , isr_status) ; - spin_unlock_irqrestore(&i2c_wmt_irqlock, flags); - return IRQ_HANDLED; -} - -static int i2c_wmt_resource_init(void) -{ - if (is_master == 0) - return 0; - if (request_irq(i2c.irq_no , &i2c_wmt_handler, IRQF_DISABLED, "i2c", 0) < 0) { - DPRINTK(KERN_INFO "I2C: Failed to register I2C irq %i\n", i2c.irq_no); - return -ENODEV; - } - return 0; -} - -static void i2c_wmt_resource_release(void) -{ - if (is_master == 0) - return; - free_irq(i2c.irq_no, 0); -} - -static struct i2c_algo_wmt_data i2c_wmt_data = { - write_msg: i2c_wmt_write_msg, - read_msg: i2c_wmt_read_msg, - send_request: i2c_send_request, - wait_bus_not_busy: i2c_wmt_wait_bus_not_busy, - reset: i2c_wmt_reset, - set_mode: i2c_wmt_set_mode, - udelay: I2C_ALGO_UDELAY, - timeout: I2C_ALGO_TIMEOUT, -}; - -static struct i2c_adapter i2c_wmt_ops = { - .owner = THIS_MODULE, - /* - .id = I2C_ALGO_WMT, - */ - .algo_data = &i2c_wmt_data, - .name = "wmt_i2c_adapter1", - .retries = I2C_ADAPTER_RETRIES, - .nr = 1, -}; - -#ifdef CONFIG_PM -static struct i2c_regs_s wmt_i2c_reg ; -static void i2c_shutdown(void) -{ - printk("i2c1 shutdown\n"); - wmt_i2c1_power_state = 2; - while (!list_empty(&wmt_i2c_fifohead)) - msleep(1); - while (1) {/*wait busy clear*/ - if ((REG16_VAL(I2C1_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) - break ; - msleep(1); - } - return; -} -static int i2c_suspend(void) -{ - printk("i2c1 suspend\n"); - wmt_i2c_reg.imr_reg = i2c.regs->imr_reg; - wmt_i2c_reg.tr_reg = i2c.regs->tr_reg; - wmt_i2c_reg.div_reg = i2c.regs->div_reg; - return 0; -} -static void i2c_resume(void) -{ - printk("i2c1 resume\n"); - GPIO_CTRL_GP17_I2C_BYTE_VAL &= ~(BIT2 | BIT3); - PULL_EN_GP17_I2C_BYTE_VAL |= (BIT2 | BIT3); - PULL_CTRL_GP17_I2C_BYTE_VAL |= (BIT2 | BIT3); - auto_pll_divisor(DEV_I2C1, CLK_ENABLE, 0, 0); - auto_pll_divisor(DEV_I2C1, SET_DIV, 2, 20);/*20M Hz*/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = wmt_i2c_reg.div_reg; - i2c.regs->imr_reg = wmt_i2c_reg.imr_reg; - i2c.regs->tr_reg = wmt_i2c_reg.tr_reg ; - i2c.regs->cr_reg = 0x001 ; -} -#else -#define i2c_suspend NULL -#define i2c_resume NULL -#define i2c_shutdown NULL -#endif -extern int wmt_i2c_add_bus(struct i2c_adapter *); -extern int wmt_i2c_del_bus(struct i2c_adapter *); - -#ifdef CONFIG_PM -static struct syscore_ops wmt_i2c_syscore_ops = -{ - .suspend = i2c_suspend, - .resume = i2c_resume, - .shutdown = i2c_shutdown, -}; -#endif - -static int __init i2c_adap_wmt_init(void) -{ - unsigned short tmp ; - char varname[] = "wmt.i2c.param"; -#ifdef CONFIG_I2C_SLAVE_WMT - char varname1[] = "wmt.bus.i2c.slave_port"; -#endif - unsigned char buf[80]; - int ret; - unsigned int port_num; - int idx = 0; - int varlen = 80; - unsigned int pllb_freq = 0; - unsigned int tr_val = 0; - -#ifdef CONFIG_I2C_SLAVE_WMT -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname1, buf, &varlen); -#else - ret = 1; -#endif - is_master = 1; - if (ret == 0) { - ret = sscanf(buf, "%x", &port_num); - while (ret) { - if (port_num != 1) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret; - ret = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; -#endif - wmt_i2c1_is_master = is_master; - if (is_master == 1) { -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname, buf, &varlen); -#else - ret = 1; -#endif - - if (ret == 0) { - ret = sscanf(buf, "%x:%x", &port_num, &speed_mode); - idx += 3; - while (ret) { - if (ret < 2) - speed_mode = 0; - else { - if (port_num != 1) - speed_mode = 0; - else - break; - } - ret = sscanf(buf + idx, ",%x:%x", &port_num, &speed_mode); - idx += 4; - } - } - if (speed_mode > 1) - speed_mode = 0; - wmt_i2c1_speed_mode = speed_mode; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C1_BASE_ADDR ; - i2c.irq_no = IRQ_I2C1 ; - printk("PORT 1 speed_mode = %d\n", speed_mode); - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else if (speed_mode == 1) - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - /**/ - /* hardware initial*/ - /**/ - auto_pll_divisor(DEV_I2C1, CLK_ENABLE, 0, 0); - pllb_freq = auto_pll_divisor(DEV_I2C1, SET_DIV, 2, 20);/*20M Hz*/ - if ((pllb_freq%(1000*2*100)) != 0) - tr_val = pllb_freq/(1000*2*100) + 1; - else - tr_val = pllb_freq/(1000*2*100); - *(volatile unsigned char *)CTRL_GPIO &= ~(BIT2 | BIT3); - *(volatile unsigned char *)PU_EN_GPIO |= (BIT2 | BIT3); - *(volatile unsigned char *)PU_CTRL_GPIO |= (BIT2 | BIT3); - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = 0xff00|tr_val; - else if (i2c.i2c_mode == I2C_FAST_MODE) { - tr_val /= 4; - i2c.regs->tr_reg = 0xff00|tr_val ; - } - } - - - if (i2c_wmt_resource_init() == 0) { - if (wmt_i2c_add_bus(&i2c_wmt_ops) < 0) { - i2c_wmt_resource_release(); - printk(KERN_INFO "i2c: Failed to add bus\n"); - return -ENODEV; - } - } else - return -ENODEV; - - INIT_LIST_HEAD(&wmt_i2c_fifohead); - -#ifdef CONFIG_PM - register_syscore_ops(&wmt_i2c_syscore_ops); -#endif - - wmt_i2c1_power_state = 0; - printk(KERN_INFO "i2c: successfully added bus\n"); - -#ifdef I2C_REG_TEST - printk("i2c.regs->cr_reg= 0x%08x\n\r", i2c.regs->cr_reg); - printk("i2c.regs->tcr_reg= 0x%08x\n\r", i2c.regs->tcr_reg); - printk("i2c.regs->csr_reg= 0x%08x\n\r", i2c.regs->csr_reg); - printk("i2c.regs->isr_reg= 0x%08x\n\r", i2c.regs->isr_reg); - printk("i2c.regs->imr_reg= 0x%08x\n\r", i2c.regs->imr_reg); - printk("i2c.regs->cdr_reg= 0x%08x\n\r", i2c.regs->cdr_reg); - printk("i2c.regs->tr_reg= 0x%08x\n\r", i2c.regs->tr_reg); - printk("i2c.regs->div_reg= 0x%08x\n\r", i2c.regs->div_reg); -#endif - - return 0; -} -subsys_initcall(i2c_adap_wmt_init); - -static void i2c_adap_wmt_exit(void) -{ - wmt_i2c_del_bus(&i2c_wmt_ops); - i2c_wmt_resource_release(); - - printk(KERN_INFO "i2c: successfully removed bus\n"); -} - - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C Adapter Driver"); -MODULE_LICENSE("GPL"); - -module_exit(i2c_adap_wmt_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-2.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-2.c deleted file mode 100755 index 64f5646c..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-2.c +++ /dev/null @@ -1,1253 +0,0 @@ -/*++ - drivers/i2c/busses/wmt-i2c-bus-2.c - - Copyright (c) 2013 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ -/* Include your headers here*/ -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <mach/wmt-i2c-bus.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <linux/syscore_ops.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else - #define DPRINTK printf - -#endif - - -#define MAX_BUS_READY_CNT 50 /* jiffy*/ -#define MAX_TX_TIMEOUT 500 /* ms*/ -#define MAX_RX_TIMEOUT 500 /* ms*/ -#define CTRL_GPIO GPIO_CTRL_GP17_I2C_BYTE_ADDR -#define PU_EN_GPIO PULL_EN_GP17_I2C_BYTE_ADDR -#define PU_CTRL_GPIO PULL_CTRL_GP17_I2C_BYTE_ADDR - -#define USE_UBOOT_PARA - -struct wmt_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int volatile isr_nack ; - int volatile isr_byte_end ; - int volatile isr_timeout ; - int volatile isr_int_pending ; -}; - -static int i2c_wmt_wait_bus_not_busy(void); -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int speed_mode = 1; -static unsigned int is_master = 1;/*master:1, slave:0*/ -unsigned int wmt_i2c2_is_master = 1; -unsigned int wmt_i2c2_speed_mode = 0; -static unsigned int wmt_i2c2_power_state = 0;/*0:power on, 1:suspend, 2:shutdown*/ -EXPORT_SYMBOL(wmt_i2c2_is_master); - -/**/ -/* variable*/ -/*-------------------------------------------------*/ -static volatile struct wmt_i2c_s i2c ; - -DECLARE_WAIT_QUEUE_HEAD(i2c2_wait); -/* -spinlock_t i2c2_wmt_irqlock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c2_wmt_irqlock); -static struct list_head wmt_i2c_fifohead; -/* -static spinlock_t i2c_fifolock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_fifolock); -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); - -static void i2c_wmt_set_mode(enum i2c_mode_e mode /*!<; //[IN] mode */) -{ - if (is_master == 0) - return; - i2c.i2c_mode = mode ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - DPRINTK("I2C: set standard mode \n"); - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - DPRINTK("I2C: set fast mode \n"); - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - } -} - - -static int i2c_send_request( - struct i2c_msg *msg, - int msg_num, - int non_block, - void (*callback)(void *data), - void *data -) -{ - struct wmt_i2cbusfifo *i2c_fifo_head; - struct i2c_msg *pmsg = NULL; - int ret = 0; - int restart = 0; - int last = 0; - unsigned long flags; - int slave_addr = msg[0].addr; - - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - if (wmt_i2c2_power_state == 2) { - printk("I2C2 has been shutdown\n"); - return -EIO; - } - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c_fifo_head = kzalloc(sizeof(struct wmt_i2cbusfifo), GFP_ATOMIC); - INIT_LIST_HEAD(&i2c_fifo_head->busfifohead); - - pmsg = &msg[0]; - i2c_fifo_head->msg = pmsg; - i2c_fifo_head->msg_num = msg_num; - - spin_lock_irqsave(&i2c_fifolock, flags); - if (list_empty(&wmt_i2c_fifohead)) { - i2c_wmt_wait_bus_not_busy(); - pmsg = &msg[0]; - i2c_fifo_head->xfer_length = 1; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - if (pmsg->flags & I2C_M_RD) { - i2c_fifo_head->xfer_length = 1; - ret = i2c_wmt_read_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } else { - i2c_fifo_head->xfer_length = 1; - if (pmsg->flags & I2C_M_NOSTART) - i2c_fifo_head->restart = 1; - else - i2c_fifo_head->restart = 0; - ret = i2c_wmt_write_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } - - } else { - i2c_fifo_head->xfer_length = 0; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - } - spin_unlock_irqrestore(&i2c_fifolock, flags); - if (non_block == 0) { - wait_event(i2c2_wait, i2c.isr_int_pending); - ret = msg_num; - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - ret = -ETIMEDOUT ; - } - - } - - return ret; - - -} -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value; - int ret = 0; - - DPRINTK("[%s]:length = %d , slave_addr = %x\n", __func__, length , slave_addr); - - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - tcr_value = 0 ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - return ret; -} - -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int ret = 0 ; - - DPRINTK("[%s]length = %d , slave_addr = %x\n", __func__, length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - ret = 0 ; - return ret; - -} -static int i2c_wmt_read_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete read */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result = 0 ; - - if (is_master == 0) - return -ENXIO; - if (length <= 0) - return -1 ; - xfer_length = 0 ; - - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - ret = 0 ; - for (; ;) { - is_timeout = 0 ; - wait_event_result = wait_event_interruptible_timeout(i2c2_wait, i2c.isr_int_pending , - (MAX_RX_TIMEOUT * HZ / 1000)) ; - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (rx) \n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (rx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err: write software timeout error (rx) \n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - buf[xfer_length] = (i2c.regs->cdr_reg >> 8) ; - ++xfer_length ; - DPRINTK("i2c_test: received BYTE_END\n\r"); - } - i2c.isr_int_pending = 0; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - if (length > xfer_length) { - if ((length - 1) == xfer_length) { /* next read is the last one*/ - i2c.regs->cr_reg |= (I2C_CR_TX_NEXT_NO_ACK | I2C_CR_CPU_RDY); - DPRINTK("i2c_test: set CPU_RDY & TX_ACK. next data is last.\r\n"); - } else { - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - DPRINTK("i2c_test: more data to read. only set CPU_RDY. \r\n"); - } - } else if (length == xfer_length) { /* end rx xfer*/ - if (last == 1) { /* stop case*/ - DPRINTK("i2c_test: read completed \r\n"); - break ; - } else { /* restart case*/ - /* ??? how to handle the restart after read ?*/ - DPRINTK("i2c_test: RX ReStart Case \r\n") ; - break ; - } - } else { - DPRINTK("i2c_err : read known error\n\r") ; - ret = -EIO ; - break ; - } - } - - DPRINTK("i2c_test: read sequence completed\n\r"); - return ret ; -} - -static int i2c_wmt_write_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete write */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result ; - - DPRINTK("length = %d , slave_addr = %x\n", length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - - ret = 0 ; - for (; ;) { - - is_timeout = 0 ; - /**/ - /* I2C: Wait for interrupt. if ( i2c.isr_int_pending == 1 ) ==> an interrupt exsits.*/ - /**/ - wait_event_result = wait_event_interruptible_timeout(i2c2_wait, i2c.isr_int_pending , (MAX_TX_TIMEOUT * HZ / 1000)) ; - - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (tx)\n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (tx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (tx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (tx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err : write software timeout error (tx)\n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - DPRINTK("i2c: isr end byte (tx)\n\r") ; - ++xfer_length ; - } - i2c.isr_int_pending = 0 ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - - if ((i2c.regs->csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK) { - DPRINTK("i2c_err : write RCV NACK error\n\r") ; - ret = -EIO ; - break ; - } - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) { - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - break ; - } - if (length > xfer_length) { - i2c.regs->cdr_reg = (unsigned short) (buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - i2c.regs->cr_reg = (I2C_CR_CPU_RDY | I2C_CR_ENABLE) ; - DPRINTK("i2c_test: write register data \n\r") ; - } else if (length == xfer_length) { /* end tx xfer*/ - if (last == 1) { /* stop case*/ - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - DPRINTK("i2c_test: finish write \n\r") ; - break ; - } else { /* restart case*/ - /* handle the restart for first write then the next is read*/ - i2c.regs->cr_reg = (I2C_CR_ENABLE) ; - DPRINTK("i2c_test: tx restart Case \n\r") ; - break ; - } - } else { - DPRINTK("i2c_err : write unknown error\n\r") ; - ret = -EIO ; - break ; - } - } ; - - DPRINTK("i2c_test: write sequence completed\n\r"); - - return ret ; -} - -static int i2c_wmt_wait_bus_not_busy(void) -{ - int ret ; - int cnt ; - - ret = 0 ; - cnt = 0 ; - while (1) { - if ((REG16_VAL(I2C2_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) { - ret = 0; - break ; - } - cnt++ ; - - if (cnt > MAX_BUS_READY_CNT) { - ret = (-EBUSY) ; - printk("i2c_err 2: wait but not ready time-out\n\r") ; - cnt = 0; - break; - } - } - return ret ; -} - -static void i2c_wmt_reset(void) -{ - unsigned short tmp ; - if (is_master == 0) - return; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C2_BASE_ADDR ; - i2c.irq_no = IRQ_I2C2 ; - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* hardware initial*/ - /**/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - else if (i2c.i2c_mode == I2C_FAST_MODE) - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - - DPRINTK("Resetting I2C Controller Unit\n"); - - return ; -} -static int wmt_i2c_transfer_msg(struct wmt_i2cbusfifo *fifo_head) -{ - int xfer_length = fifo_head->xfer_length; - int xfer_msgnum = fifo_head->xfer_msgnum; - struct i2c_msg *pmsg = &fifo_head->msg[xfer_msgnum]; - int restart = fifo_head->restart; - unsigned short tcr_value; - unsigned short slave_addr = pmsg->addr; - int length = pmsg->len; - int ret = 0; - - if (pmsg->flags & I2C_M_RD) { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } else { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(pmsg->buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - } - return ret; -} - -static irqreturn_t i2c_wmt_handler( - int this_irq, /*!<; //[IN] IRQ number */ - void *dev_id /*!<; //[IN] Pointer to device ID */ -) -{ - int wakeup ; - unsigned short isr_status ; - unsigned short tmp ; - unsigned long flags; - struct wmt_i2cbusfifo *fifo_head; - int xfer_length = 0; - int xfer_msgnum = 0; - struct i2c_msg *pmsg; - volatile unsigned short csr_reg; - - spin_lock_irqsave(&i2c2_wmt_irqlock, flags); - isr_status = i2c.regs->isr_reg ; - csr_reg = i2c.regs->csr_reg; - wakeup = 0 ; - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - - if (isr_status & I2C_ISR_NACK_ADDR) { - DPRINTK("[%s]:i2c NACK\n", __func__); - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_NACK_ADDR_WRITE_CLEAR ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.isr_nack = 1 ; - wakeup = 1 ; - } - - if ((isr_status & I2C_ISR_BYTE_END && ((csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK))) { - /* - printk("data rcv nack\n"); - */ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_nack = 1 ; - wakeup = 1 ; - } else if (isr_status & I2C_ISR_BYTE_END) { - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_byte_end = 1 ; - xfer_length = fifo_head->xfer_length; - xfer_msgnum = fifo_head->xfer_msgnum; - pmsg = &fifo_head->msg[xfer_msgnum]; - - /*read case*/ - if (pmsg->flags & I2C_M_RD) { - pmsg->buf[xfer_length - 1] = (i2c.regs->cdr_reg >> 8) ; - /*the last data in current msg?*/ - if (xfer_length == pmsg->len - 1) { - /*last msg of the current request?*/ - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_TX_NEXT_NO_ACK); - } - /*spin_unlock(&i2c_fifolock);*/ - } else if (xfer_length == pmsg->len) {/*next msg*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else { /*data of this msg has been transfered*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*next request exist?*/ - if (list_empty(&wmt_i2c_fifohead)) {/*no more reqeust*/ - /*kfree(fifo_head);*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - } else { /*more request*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - fifo_head->xfer_length = 0; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - - /* - if (fifo_head->non_block == 0) { - printk("2 : non callback\n"); - wakeup = 1; - } else { - printk("2 :callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } - - } else { /*write case*/ - /*the last data in current msg?*/ - if (xfer_length == pmsg->len) { - /*last msg of the current request?*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - } - /*access next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else {/*this request finish*/ - /*spin_lock(&i2c_fifolock);*/ - /*next request exist?*/ - list_del(&fifo_head->busfifohead);/*del request*/ - if (list_empty(&wmt_i2c_fifohead)) { - /*kfree(fifo_head);*/ - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - - } else { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - /*next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /* - if (fifo_head->non_block == 0) { - printk("4:non callback\n"); - wakeup = 1; - } else { - printk("4:callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - i2c.regs->cdr_reg = (unsigned short) (pmsg->buf[fifo_head->xfer_length] & I2C_CDR_DATA_WRITE_MASK); - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_ENABLE); - } - } - } - - if (isr_status & I2C_ISR_SCL_TIME_OUT) { - DPRINTK("[%s]SCL timeout\n", __func__); -#if 0 - i2c.regs->cr_reg |= BIT7;/*reset status*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR | I2C_ISR_BYTE_END_WRITE_CLEAR; - i2c.isr_timeout = 1 ; - wakeup = 1; -#endif - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR ; - } - - - if (wakeup) { - /*spin_lock_irqsave(&i2c_wmt_irqlock, flags);*/ - i2c.isr_int_pending = 1; - /*spin_unlock_irqrestore(&i2c_wmt_irqlock, flags);*/ - wake_up(&i2c2_wait); - } else - DPRINTK("i2c_err : unknown I2C ISR Handle 0x%4.4X" , isr_status) ; - spin_unlock_irqrestore(&i2c2_wmt_irqlock, flags); - return IRQ_HANDLED; -} - -static int i2c_wmt_resource_init(void) -{ - if (is_master == 0) - return 0; - if (request_irq(i2c.irq_no , &i2c_wmt_handler, IRQF_DISABLED, "i2c", 0) < 0) { - DPRINTK(KERN_INFO "I2C: Failed to register I2C irq %i\n", i2c.irq_no); - return -ENODEV; - } - return 0; -} - -static void i2c_wmt_resource_release(void) -{ - if (is_master == 0) - return; - free_irq(i2c.irq_no, 0); -} - -static struct i2c_algo_wmt_data i2c_wmt_data = { - write_msg: i2c_wmt_write_msg, - read_msg: i2c_wmt_read_msg, - send_request: i2c_send_request, - wait_bus_not_busy: i2c_wmt_wait_bus_not_busy, - reset: i2c_wmt_reset, - set_mode: i2c_wmt_set_mode, - udelay: I2C_ALGO_UDELAY, - timeout: I2C_ALGO_TIMEOUT, -}; - -static struct i2c_adapter i2c_wmt_ops = { - .owner = THIS_MODULE, - /* - .id = I2C_ALGO_WMT, - */ - .algo_data = &i2c_wmt_data, - .name = "wmt_i2c2_adapter", - .retries = I2C_ADAPTER_RETRIES, - .nr = 2, -}; - -#ifdef CONFIG_PM -static struct i2c_regs_s wmt_i2c_reg ; -static void i2c_shutdown(void) -{ - printk("i2c2 shutdown\n"); - wmt_i2c2_power_state = 2; - while (!list_empty(&wmt_i2c_fifohead)) - msleep(1); - while (1) {/*wait busy clear*/ - if ((REG16_VAL(I2C2_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) - break ; - msleep(1); - } - return; -} -static int i2c_suspend(void) -{ - printk("i2c2 suspend\n"); - wmt_i2c_reg.imr_reg = i2c.regs->imr_reg; - wmt_i2c_reg.tr_reg = i2c.regs->tr_reg; - wmt_i2c_reg.div_reg = i2c.regs->div_reg; - return 0; -} -static void i2c_resume(void) -{ - printk("i2c2 resume\n"); - GPIO_CTRL_GP17_I2C_BYTE_VAL &= ~(BIT4 | BIT5); - PULL_EN_GP17_I2C_BYTE_VAL |= (BIT4 | BIT5); - PULL_CTRL_GP17_I2C_BYTE_VAL |= (BIT4 | BIT5); - auto_pll_divisor(DEV_I2C2, CLK_ENABLE, 0, 0); - auto_pll_divisor(DEV_I2C2, SET_DIV, 2, 20);/*20M Hz*/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = wmt_i2c_reg.div_reg; - i2c.regs->imr_reg = wmt_i2c_reg.imr_reg; - i2c.regs->tr_reg = wmt_i2c_reg.tr_reg ; - i2c.regs->cr_reg = 0x001 ; -} -#else -#define i2c_suspend NULL -#define i2c_resume NULL -#define i2c_shutdown NULL -#endif -extern int wmt_i2c_add_bus(struct i2c_adapter *); -extern int wmt_i2c_del_bus(struct i2c_adapter *); - -#ifdef CONFIG_PM -static struct syscore_ops wmt_i2c_syscore_ops = { - .suspend = i2c_suspend, - .resume = i2c_resume, - .shutdown = i2c_shutdown, -}; -#endif - -static int __init i2c_adap_wmt_init(void) -{ - unsigned short tmp ; - char varname[] = "wmt.i2c.param"; -#ifdef CONFIG_I2C_SLAVE_WMT - char varname1[] = "wmt.bus.i2c.slave_port"; -#endif - unsigned char buf[80]; - int ret; - unsigned int port_num; - int idx = 0; - int varlen = 80; - unsigned int pllb_freq = 0; - unsigned int tr_val = 0; - -#ifdef CONFIG_I2C_SLAVE_WMT -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname1, buf, &varlen); -#else - ret = 1; -#endif - is_master = 1; - if (ret == 0) { - ret = sscanf(buf, "%x", &port_num); - while (ret) { - if (port_num != 0) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret; - ret = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; -#endif - wmt_i2c2_is_master = is_master; - if (is_master == 1) { -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname, buf, &varlen); -#else - ret = 1; -#endif - - if (ret == 0) { - ret = sscanf(buf, "%x:%x", &port_num, &speed_mode); - idx += 3; - while (ret) { - if (ret < 2) - speed_mode = 0; - else { - if (port_num != 2) - speed_mode = 0; - else - break; - } - ret = sscanf(buf + idx, ",%x:%x", &port_num, &speed_mode); - idx += 4; - } - } - if (speed_mode > 1) - speed_mode = 0; - wmt_i2c2_speed_mode = speed_mode; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C2_BASE_ADDR ; - i2c.irq_no = IRQ_I2C2 ; - - printk("PORT 2 speed_mode = %d\n", speed_mode); - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else if (speed_mode == 1) - i2c.i2c_mode = I2C_FAST_MODE ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - /**/ - /* hardware initial*/ - /**/ - auto_pll_divisor(DEV_I2C2, CLK_ENABLE, 0, 0); - pllb_freq = auto_pll_divisor(DEV_I2C2, SET_DIV, 2, 20);/*20M Hz*/ - if ((pllb_freq%(1000*2*100)) != 0) - tr_val = pllb_freq/(1000*2*100) + 1; - else - tr_val = pllb_freq/(1000*2*100); - *(volatile unsigned char *)CTRL_GPIO &= ~(BIT4 | BIT5); - *(volatile unsigned char *)PU_EN_GPIO |= (BIT4 | BIT5); - *(volatile unsigned char *)PU_CTRL_GPIO |= (BIT4 | BIT5); - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = 0xff00|tr_val; - else if (i2c.i2c_mode == I2C_FAST_MODE) { - tr_val /= 4; - i2c.regs->tr_reg = 0xff00|tr_val ; - } - } - - - if (i2c_wmt_resource_init() == 0) { - if (wmt_i2c_add_bus(&i2c_wmt_ops) < 0) { - i2c_wmt_resource_release(); - printk(KERN_INFO "i2c: Failed to add bus\n"); - return -ENODEV; - } - } else - return -ENODEV; - - INIT_LIST_HEAD(&wmt_i2c_fifohead); - -#ifdef CONFIG_PM - register_syscore_ops(&wmt_i2c_syscore_ops); -#endif - - printk(KERN_INFO "i2c: successfully added bus\n"); - -#ifdef I2C_REG_TEST - printk("i2c.regs->cr_reg= 0x%08x\n\r", i2c.regs->cr_reg); - printk("i2c.regs->tcr_reg= 0x%08x\n\r", i2c.regs->tcr_reg); - printk("i2c.regs->csr_reg= 0x%08x\n\r", i2c.regs->csr_reg); - printk("i2c.regs->isr_reg= 0x%08x\n\r", i2c.regs->isr_reg); - printk("i2c.regs->imr_reg= 0x%08x\n\r", i2c.regs->imr_reg); - printk("i2c.regs->cdr_reg= 0x%08x\n\r", i2c.regs->cdr_reg); - printk("i2c.regs->tr_reg= 0x%08x\n\r", i2c.regs->tr_reg); - printk("i2c.regs->div_reg= 0x%08x\n\r", i2c.regs->div_reg); -#endif - - return 0; -} -subsys_initcall(i2c_adap_wmt_init); - -static void i2c_adap_wmt_exit(void) -{ - wmt_i2c_del_bus(&i2c_wmt_ops); - i2c_wmt_resource_release(); - - printk(KERN_INFO "i2c: successfully removed bus\n"); -} - - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C Adapter Driver"); -MODULE_LICENSE("GPL"); - -module_exit(i2c_adap_wmt_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-3.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-3.c deleted file mode 100755 index b362a156..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-3.c +++ /dev/null @@ -1,1256 +0,0 @@ -/*++ - drivers/i2c/busses/wmt-i2c-bus-3.c - - Copyright (c) 2013 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ -/* Include your headers here*/ -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <mach/wmt-i2c-bus.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <linux/syscore_ops.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else - #define DPRINTK printf - -#endif - - -#define MAX_BUS_READY_CNT 50 /* jiffy*/ -#define MAX_TX_TIMEOUT 500 /* ms*/ -#define MAX_RX_TIMEOUT 500 /* ms*/ -#define CTRL_GPIO GPIO_CTRL_GP23_I2C3_BYTE_ADDR -#define PU_EN_GPIO PULL_EN_GP23_I2C3_BYTE_ADDR -#define PU_CTRL_GPIO PULL_CTRL_GP23_I2C3_BYTE_ADDR - -#define USE_UBOOT_PARA - -struct wmt_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int volatile isr_nack ; - int volatile isr_byte_end ; - int volatile isr_timeout ; - int volatile isr_int_pending ; -}; - -static int i2c_wmt_wait_bus_not_busy(void); -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int speed_mode = 1; -static unsigned int is_master = 1;/*master:1, slave:0*/ -unsigned int wmt_i2c3_is_master = 1; -unsigned int wmt_i2c3_speed_mode = 0; -static unsigned int wmt_i2c3_power_state = 0;/*0:power on, 1:suspend, 2:shutdown*/ -EXPORT_SYMBOL(wmt_i2c3_is_master); - -/**/ -/* variable*/ -/*-------------------------------------------------*/ -static volatile struct wmt_i2c_s i2c ; - -DECLARE_WAIT_QUEUE_HEAD(i2c3_wait); -/* -spinlock_t i2c3_wmt_irqlock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c3_wmt_irqlock); -static struct list_head wmt_i2c_fifohead; -/* -static spinlock_t i2c_fifolock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_fifolock); -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); - -static void i2c_wmt_set_mode(enum i2c_mode_e mode /*!<; //[IN] mode */) -{ - if (is_master == 0) - return; - i2c.i2c_mode = mode ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - DPRINTK("I2C: set standard mode \n"); - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - DPRINTK("I2C: set fast mode \n"); - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - } -} - - -static int i2c_send_request( - struct i2c_msg *msg, - int msg_num, - int non_block, - void (*callback)(void *data), - void *data -) -{ - struct wmt_i2cbusfifo *i2c_fifo_head; - struct i2c_msg *pmsg = NULL; - int ret = 0; - int restart = 0; - int last = 0; - unsigned long flags; - int slave_addr = msg[0].addr; - - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - if (wmt_i2c3_power_state == 2) { - printk("I2C3 has been shutdown\n"); - return -EIO; - } - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c_fifo_head = kzalloc(sizeof(struct wmt_i2cbusfifo), GFP_ATOMIC); - INIT_LIST_HEAD(&i2c_fifo_head->busfifohead); - - pmsg = &msg[0]; - i2c_fifo_head->msg = pmsg; - i2c_fifo_head->msg_num = msg_num; - - spin_lock_irqsave(&i2c_fifolock, flags); - if (list_empty(&wmt_i2c_fifohead)) { - i2c_wmt_wait_bus_not_busy(); - pmsg = &msg[0]; - i2c_fifo_head->xfer_length = 1; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - if (pmsg->flags & I2C_M_RD) { - i2c_fifo_head->xfer_length = 1; - ret = i2c_wmt_read_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } else { - i2c_fifo_head->xfer_length = 1; - if (pmsg->flags & I2C_M_NOSTART) - i2c_fifo_head->restart = 1; - else - i2c_fifo_head->restart = 0; - ret = i2c_wmt_write_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } - - } else { - i2c_fifo_head->xfer_length = 0; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - } - spin_unlock_irqrestore(&i2c_fifolock, flags); - if (non_block == 0) { - wait_event(i2c3_wait, i2c.isr_int_pending); - ret = msg_num; - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - ret = -ETIMEDOUT ; - } - - } - - return ret; - - -} -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value; - int ret = 0; - - DPRINTK("[%s]:length = %d , slave_addr = %x\n", __func__, length , slave_addr); - - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - tcr_value = 0 ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - return ret; -} - -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int ret = 0 ; - - DPRINTK("[%s]length = %d , slave_addr = %x\n", __func__, length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - ret = 0 ; - return ret; - -} -static int i2c_wmt_read_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete read */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result = 0 ; - - if (is_master == 0) - return -ENXIO; - if (length <= 0) - return -1 ; - xfer_length = 0 ; - - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - ret = 0 ; - for (; ;) { - is_timeout = 0 ; - wait_event_result = wait_event_interruptible_timeout(i2c3_wait, i2c.isr_int_pending , - (MAX_RX_TIMEOUT * HZ / 1000)) ; - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (rx) \n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (rx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err: write software timeout error (rx) \n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - buf[xfer_length] = (i2c.regs->cdr_reg >> 8) ; - ++xfer_length ; - DPRINTK("i2c_test: received BYTE_END\n\r"); - } - i2c.isr_int_pending = 0; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - if (length > xfer_length) { - if ((length - 1) == xfer_length) { /* next read is the last one*/ - i2c.regs->cr_reg |= (I2C_CR_TX_NEXT_NO_ACK | I2C_CR_CPU_RDY); - DPRINTK("i2c_test: set CPU_RDY & TX_ACK. next data is last.\r\n"); - } else { - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - DPRINTK("i2c_test: more data to read. only set CPU_RDY. \r\n"); - } - } else if (length == xfer_length) { /* end rx xfer*/ - if (last == 1) { /* stop case*/ - DPRINTK("i2c_test: read completed \r\n"); - break ; - } else { /* restart case*/ - /* ??? how to handle the restart after read ?*/ - DPRINTK("i2c_test: RX ReStart Case \r\n") ; - break ; - } - } else { - DPRINTK("i2c_err : read known error\n\r") ; - ret = -EIO ; - break ; - } - } - - DPRINTK("i2c_test: read sequence completed\n\r"); - return ret ; -} - -static int i2c_wmt_write_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete write */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result ; - - DPRINTK("length = %d , slave_addr = %x\n", length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - - ret = 0 ; - for (; ;) { - - is_timeout = 0 ; - /**/ - /* I2C: Wait for interrupt. if ( i2c.isr_int_pending == 1 ) ==> an interrupt exsits.*/ - /**/ - wait_event_result = wait_event_interruptible_timeout(i2c3_wait, i2c.isr_int_pending , (MAX_TX_TIMEOUT * HZ / 1000)) ; - - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (tx)\n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (tx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (tx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (tx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err : write software timeout error (tx)\n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - DPRINTK("i2c: isr end byte (tx)\n\r") ; - ++xfer_length ; - } - i2c.isr_int_pending = 0 ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - - if ((i2c.regs->csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK) { - DPRINTK("i2c_err : write RCV NACK error\n\r") ; - ret = -EIO ; - break ; - } - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) { - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - break ; - } - if (length > xfer_length) { - i2c.regs->cdr_reg = (unsigned short) (buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - i2c.regs->cr_reg = (I2C_CR_CPU_RDY | I2C_CR_ENABLE) ; - DPRINTK("i2c_test: write register data \n\r") ; - } else if (length == xfer_length) { /* end tx xfer*/ - if (last == 1) { /* stop case*/ - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - DPRINTK("i2c_test: finish write \n\r") ; - break ; - } else { /* restart case*/ - /* handle the restart for first write then the next is read*/ - i2c.regs->cr_reg = (I2C_CR_ENABLE) ; - DPRINTK("i2c_test: tx restart Case \n\r") ; - break ; - } - } else { - DPRINTK("i2c_err : write unknown error\n\r") ; - ret = -EIO ; - break ; - } - } ; - - DPRINTK("i2c_test: write sequence completed\n\r"); - - return ret ; -} - -static int i2c_wmt_wait_bus_not_busy(void) -{ - int ret ; - int cnt ; - - ret = 0 ; - cnt = 0 ; - while (1) { - if ((REG16_VAL(I2C3_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) { - ret = 0; - break ; - } - cnt++ ; - - if (cnt > MAX_BUS_READY_CNT) { - ret = (-EBUSY) ; - printk("i2c_err 3: wait but not ready time-out\n\r") ; - cnt = 0; - break; - } - } - return ret ; -} - -static void i2c_wmt_reset(void) -{ - unsigned short tmp ; - if (is_master == 0) - return; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C3_BASE_ADDR ; - i2c.irq_no = IRQ_I2C3 ; - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* hardware initial*/ - /**/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - else if (i2c.i2c_mode == I2C_FAST_MODE) - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - - DPRINTK("Resetting I2C Controller Unit\n"); - - return ; -} -static int wmt_i2c_transfer_msg(struct wmt_i2cbusfifo *fifo_head) -{ - int xfer_length = fifo_head->xfer_length; - int xfer_msgnum = fifo_head->xfer_msgnum; - struct i2c_msg *pmsg = &fifo_head->msg[xfer_msgnum]; - int restart = fifo_head->restart; - unsigned short tcr_value; - unsigned short slave_addr = pmsg->addr; - int length = pmsg->len; - int ret = 0; - - if (pmsg->flags & I2C_M_RD) { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } else { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(pmsg->buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - } - return ret; -} - -static irqreturn_t i2c_wmt_handler( - int this_irq, /*!<; //[IN] IRQ number */ - void *dev_id /*!<; //[IN] Pointer to device ID */ -) -{ - int wakeup ; - unsigned short isr_status ; - unsigned short tmp ; - unsigned long flags; - struct wmt_i2cbusfifo *fifo_head; - int xfer_length = 0; - int xfer_msgnum = 0; - struct i2c_msg *pmsg; - volatile unsigned short csr_reg; - - spin_lock_irqsave(&i2c3_wmt_irqlock, flags); - isr_status = i2c.regs->isr_reg ; - csr_reg = i2c.regs->csr_reg; - wakeup = 0 ; - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - - if (isr_status & I2C_ISR_NACK_ADDR) { - DPRINTK("[%s]:i2c NACK\n", __func__); - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_NACK_ADDR_WRITE_CLEAR ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.isr_nack = 1 ; - wakeup = 1 ; - } - - if ((isr_status & I2C_ISR_BYTE_END && ((csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK))) { - /* - printk("data rcv nack\n"); - */ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_nack = 1 ; - wakeup = 1 ; - } else if (isr_status & I2C_ISR_BYTE_END) { - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_byte_end = 1 ; - xfer_length = fifo_head->xfer_length; - xfer_msgnum = fifo_head->xfer_msgnum; - pmsg = &fifo_head->msg[xfer_msgnum]; - - /*read case*/ - if (pmsg->flags & I2C_M_RD) { - pmsg->buf[xfer_length - 1] = (i2c.regs->cdr_reg >> 8) ; - /*the last data in current msg?*/ - if (xfer_length == pmsg->len - 1) { - /*last msg of the current request?*/ - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_TX_NEXT_NO_ACK); - } - /*spin_unlock(&i2c_fifolock);*/ - } else if (xfer_length == pmsg->len) {/*next msg*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else { /*data of this msg has been transfered*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*next request exist?*/ - if (list_empty(&wmt_i2c_fifohead)) {/*no more reqeust*/ - /*kfree(fifo_head);*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - } else { /*more request*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - fifo_head->xfer_length = 0; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - - /* - if (fifo_head->non_block == 0) { - printk("2 : non callback\n"); - wakeup = 1; - } else { - printk("2 :callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } - - } else { /*write case*/ - /*the last data in current msg?*/ - if (xfer_length == pmsg->len) { - /*last msg of the current request?*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - } - /*access next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else {/*this request finish*/ - /*spin_lock(&i2c_fifolock);*/ - /*next request exist?*/ - list_del(&fifo_head->busfifohead);/*del request*/ - if (list_empty(&wmt_i2c_fifohead)) { - /*kfree(fifo_head);*/ - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - - } else { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - /*next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /* - if (fifo_head->non_block == 0) { - printk("4:non callback\n"); - wakeup = 1; - } else { - printk("4:callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - i2c.regs->cdr_reg = (unsigned short) (pmsg->buf[fifo_head->xfer_length] & I2C_CDR_DATA_WRITE_MASK); - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_ENABLE); - } - } - } - - if (isr_status & I2C_ISR_SCL_TIME_OUT) { - DPRINTK("[%s]SCL timeout\n", __func__); -#if 0 - i2c.regs->cr_reg |= BIT7;/*reset status*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR | I2C_ISR_BYTE_END_WRITE_CLEAR; - i2c.isr_timeout = 1 ; - wakeup = 1; -#endif - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR ; - } - - - if (wakeup) { - /*spin_lock_irqsave(&i2c_wmt_irqlock, flags);*/ - i2c.isr_int_pending = 1; - /*spin_unlock_irqrestore(&i2c_wmt_irqlock, flags);*/ - wake_up(&i2c3_wait); - } else - DPRINTK("i2c_err : unknown I2C ISR Handle 0x%4.4X" , isr_status) ; - spin_unlock_irqrestore(&i2c3_wmt_irqlock, flags); - return IRQ_HANDLED; -} - -static int i2c_wmt_resource_init(void) -{ - if (is_master == 0) - return 0; - if (request_irq(i2c.irq_no , &i2c_wmt_handler, IRQF_DISABLED, "i2c", 0) < 0) { - DPRINTK(KERN_INFO "I2C: Failed to register I2C irq %i\n", i2c.irq_no); - return -ENODEV; - } - return 0; -} - -static void i2c_wmt_resource_release(void) -{ - if (is_master == 0) - return; - free_irq(i2c.irq_no, 0); -} - -static struct i2c_algo_wmt_data i2c_wmt_data = { - write_msg: i2c_wmt_write_msg, - read_msg: i2c_wmt_read_msg, - send_request: i2c_send_request, - wait_bus_not_busy: i2c_wmt_wait_bus_not_busy, - reset: i2c_wmt_reset, - set_mode: i2c_wmt_set_mode, - udelay: I2C_ALGO_UDELAY, - timeout: I2C_ALGO_TIMEOUT, -}; - -static struct i2c_adapter i2c_wmt_ops = { - .owner = THIS_MODULE, - /* - .id = I2C_ALGO_WMT, - */ - .algo_data = &i2c_wmt_data, - .name = "wmt_i2c3_adapter", - .retries = I2C_ADAPTER_RETRIES, - .nr = 3, -}; - -#ifdef CONFIG_PM -static struct i2c_regs_s wmt_i2c_reg ; -static void i2c_shutdown(void) -{ - printk("i2c3 shutdown\n"); - wmt_i2c3_power_state = 2; - while (!list_empty(&wmt_i2c_fifohead)) - msleep(1); - while (1) {/*wait busy clear*/ - if ((REG16_VAL(I2C3_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) - break ; - msleep(1); - } - return; -} -static int i2c_suspend(void) -{ - printk("i2c3 suspend\n"); - wmt_i2c_reg.imr_reg = i2c.regs->imr_reg; - wmt_i2c_reg.tr_reg = i2c.regs->tr_reg; - wmt_i2c_reg.div_reg = i2c.regs->div_reg; - return 0; -} -static void i2c_resume(void) -{ - printk("i2c3 resume\n"); - GPIO_CTRL_GP23_I2C3_BYTE_VAL &= ~(BIT0 | BIT1); - PULL_EN_GP23_I2C3_BYTE_VAL |= (BIT0 | BIT1); - PULL_CTRL_GP23_I2C3_BYTE_VAL |= (BIT0 | BIT1); - PIN_SHARING_SEL_4BYTE_VAL &= ~BIT28; - auto_pll_divisor(DEV_I2C3, CLK_ENABLE, 0, 0); - auto_pll_divisor(DEV_I2C3, SET_DIV, 2, 20);/*20M Hz*/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = wmt_i2c_reg.div_reg; - i2c.regs->imr_reg = wmt_i2c_reg.imr_reg; - i2c.regs->tr_reg = wmt_i2c_reg.tr_reg ; - i2c.regs->cr_reg = 0x001 ; -} -#else -#define i2c_suspend NULL -#define i2c_resume NULL -#define i2c_shutdown NULL -#endif -extern int wmt_i2c_add_bus(struct i2c_adapter *); -extern int wmt_i2c_del_bus(struct i2c_adapter *); - -#ifdef CONFIG_PM -static struct syscore_ops wmt_i2c_syscore_ops = { - .suspend = i2c_suspend, - .resume = i2c_resume, - .shutdown = i2c_shutdown, -}; -#endif - -static int __init i2c_adap_wmt_init(void) -{ - unsigned short tmp ; - char varname[] = "wmt.i2c.param"; -#ifdef CONFIG_I2C_SLAVE_WMT - char varname1[] = "wmt.bus.i2c.slave_port"; -#endif - unsigned char buf[80]; - int ret; - unsigned int port_num; - int idx = 0; - int varlen = 80; - unsigned int pllb_freq = 0; - unsigned int tr_val = 0; - -#ifdef CONFIG_I2C_SLAVE_WMT -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname1, buf, &varlen); -#else - ret = 1; -#endif - is_master = 1; - if (ret == 0) { - ret = sscanf(buf, "%x", &port_num); - while (ret) { - if (port_num != 0) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret; - ret = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; -#endif - wmt_i2c3_is_master = is_master; - if (is_master == 1) { -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname, buf, &varlen); -#else - ret = 1; -#endif - - if (ret == 0) { - ret = sscanf(buf, "%x:%x", &port_num, &speed_mode); - idx += 3; - while (ret) { - if (ret < 2) - speed_mode = 0; - else { - if (port_num != 3) - speed_mode = 0; - else - break; - } - ret = sscanf(buf + idx, ",%x:%x", &port_num, &speed_mode); - idx += 4; - } - } - if (speed_mode > 1) - speed_mode = 0; - wmt_i2c3_speed_mode = speed_mode; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C3_BASE_ADDR ; - i2c.irq_no = IRQ_I2C3 ; - - printk("PORT 3 speed_mode = %d\n", speed_mode); - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else if (speed_mode == 1) - i2c.i2c_mode = I2C_FAST_MODE ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - /**/ - /* hardware initial*/ - /**/ - auto_pll_divisor(DEV_I2C3, CLK_ENABLE, 0, 0); - pllb_freq = auto_pll_divisor(DEV_I2C3, SET_DIV, 2, 20);/*20M Hz*/ - printk("pllb_freq = %d\n", pllb_freq); - if ((pllb_freq%(1000*2*100)) != 0) - tr_val = pllb_freq/(1000*2*100) + 1; - else - tr_val = pllb_freq/(1000*2*100); - *(volatile unsigned char *)CTRL_GPIO &= ~(BIT0 | BIT1); - *(volatile unsigned char *)PU_EN_GPIO |= (BIT0 | BIT1); - *(volatile unsigned char *)PU_CTRL_GPIO |= (BIT0 | BIT1); - PIN_SHARING_SEL_4BYTE_VAL &= ~BIT28; - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = 0xff00|tr_val; - else if (i2c.i2c_mode == I2C_FAST_MODE) { - tr_val /= 4; - i2c.regs->tr_reg = 0xff00|tr_val ; - } - } - - - if (i2c_wmt_resource_init() == 0) { - if (wmt_i2c_add_bus(&i2c_wmt_ops) < 0) { - i2c_wmt_resource_release(); - printk(KERN_INFO "i2c: Failed to add bus\n"); - return -ENODEV; - } - } else - return -ENODEV; - - INIT_LIST_HEAD(&wmt_i2c_fifohead); - -#ifdef CONFIG_PM - register_syscore_ops(&wmt_i2c_syscore_ops); -#endif - - printk(KERN_INFO "i2c: successfully added bus\n"); - -#ifdef I2C_REG_TEST - printk("i2c.regs->cr_reg= 0x%08x\n\r", i2c.regs->cr_reg); - printk("i2c.regs->tcr_reg= 0x%08x\n\r", i2c.regs->tcr_reg); - printk("i2c.regs->csr_reg= 0x%08x\n\r", i2c.regs->csr_reg); - printk("i2c.regs->isr_reg= 0x%08x\n\r", i2c.regs->isr_reg); - printk("i2c.regs->imr_reg= 0x%08x\n\r", i2c.regs->imr_reg); - printk("i2c.regs->cdr_reg= 0x%08x\n\r", i2c.regs->cdr_reg); - printk("i2c.regs->tr_reg= 0x%08x\n\r", i2c.regs->tr_reg); - printk("i2c.regs->div_reg= 0x%08x\n\r", i2c.regs->div_reg); -#endif - - return 0; -} -subsys_initcall(i2c_adap_wmt_init); - -static void i2c_adap_wmt_exit(void) -{ - wmt_i2c_del_bus(&i2c_wmt_ops); - i2c_wmt_resource_release(); - - printk(KERN_INFO "i2c: successfully removed bus\n"); -} - - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C Adapter Driver"); -MODULE_LICENSE("GPL"); - -module_exit(i2c_adap_wmt_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-4.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-4.c deleted file mode 100755 index 72e6531d..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus-4.c +++ /dev/null @@ -1,1274 +0,0 @@ -/*++ - drivers/i2c/busses/wmt_i2c_bus-4.c - - Copyright (c) 2013 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ -/* Include your headers here*/ -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <mach/wmt-i2c-bus.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <linux/syscore_ops.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else - #define DPRINTK printf - -#endif - - -#define MAX_BUS_READY_CNT 50 /* jiffy*/ -#define MAX_TX_TIMEOUT 500 /* ms*/ -#define MAX_RX_TIMEOUT 500 /* ms*/ - -#define USE_UBOOT_PARA - -struct wmt_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int volatile isr_nack ; - int volatile isr_byte_end ; - int volatile isr_timeout ; - int volatile isr_int_pending ; -}; - -static int i2c_wmt_wait_bus_not_busy(void); -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int speed_mode = 0; -unsigned int wmt_i2c4_speed_mode = 0; -static unsigned int is_master = 1;/*master:1, slave:0*/ -unsigned int wmt_i2c4_is_master = 1; -static unsigned int wmt_i2c4_power_state = 0;/*0:power on, 1:suspend, 2:shutdown*/ -EXPORT_SYMBOL(wmt_i2c4_is_master); - -/**/ -/* variable*/ -/*-------------------------------------------------*/ -static volatile struct wmt_i2c_s i2c ; - -DECLARE_WAIT_QUEUE_HEAD(i2c4_wait); -/* -spinlock_t i2c_wmt_irqlock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_wmt_irqlock); -static struct list_head wmt_i2c_fifohead; -/* -static spinlock_t i2c_fifolock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_fifolock); -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); - -static void i2c_gpio_init(void) -{ - GPIO_CTRL_GP10_I2S_BYTE_VAL &= ~BIT4; - GPIO_CTRL_GP11_I2S_BYTE_VAL &= ~BIT2; - - PULL_EN_GP10_I2S_BYTE_VAL |= BIT4; - PULL_EN_GP11_I2S_BYTE_VAL |= BIT2; - - PULL_CTRL_GP10_I2S_BYTE_VAL |= BIT4; - PULL_CTRL_GP11_I2S_BYTE_VAL |= BIT2; - - PIN_SHARING_SEL_4BYTE_VAL |= BIT21 | BIT22 | BIT13 | BIT14; -} - -static void i2c_wmt_set_mode(enum i2c_mode_e mode /*!<; //[IN] mode */) -{ - if (is_master == 0) - return; - i2c.i2c_mode = mode ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - DPRINTK("I2C: set standard mode \n"); - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - DPRINTK("I2C: set fast mode \n"); - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - } -} - - -static int i2c_send_request( - struct i2c_msg *msg, - int msg_num, - int non_block, - void (*callback)(void *data), - void *data -) -{ - struct wmt_i2cbusfifo *i2c_fifo_head; - struct i2c_msg *pmsg = NULL; - int ret = 0; - int restart = 0; - int last = 0; - unsigned long flags; - int slave_addr = msg[0].addr; - - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (wmt_i2c4_power_state == 2) { - printk("I2C4 has been shutdown\n"); - return -EIO; - } - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - if (non_block == 0) - i2c.isr_int_pending = 0; - - i2c_fifo_head = kzalloc(sizeof(struct wmt_i2cbusfifo), GFP_ATOMIC); - INIT_LIST_HEAD(&i2c_fifo_head->busfifohead); - - pmsg = &msg[0]; - i2c_fifo_head->msg = pmsg; - i2c_fifo_head->msg_num = msg_num; - - spin_lock_irqsave(&i2c_fifolock, flags); - if (list_empty(&wmt_i2c_fifohead)) { - i2c_wmt_wait_bus_not_busy(); - pmsg = &msg[0]; - i2c_fifo_head->xfer_length = 1; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - if (pmsg->flags & I2C_M_RD) { - i2c_fifo_head->xfer_length = 1; - ret = i2c_wmt_read_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } else { - i2c_fifo_head->xfer_length = 1; - if (pmsg->flags & I2C_M_NOSTART) - i2c_fifo_head->restart = 1; - else - i2c_fifo_head->restart = 0; - ret = i2c_wmt_write_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } - - } else { - i2c_fifo_head->xfer_length = 0; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - } - spin_unlock_irqrestore(&i2c_fifolock, flags); - if (non_block == 0) { - wait_event(i2c4_wait, i2c.isr_int_pending); - ret = msg_num; - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - ret = -ETIMEDOUT ; - } - - } - - return ret; - - -} -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value; - int ret = 0; - - DPRINTK("[%s]:length = %d , slave_addr = %x\n", __func__, length , slave_addr); - - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - tcr_value = 0 ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - return ret; -} - -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int ret = 0 ; - - DPRINTK("[%s]length = %d , slave_addr = %x\n", __func__, length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - ret = 0 ; - return ret; - -} -static int i2c_wmt_read_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete read */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result = 0 ; - - if (is_master == 0) - return -ENXIO; - if (length <= 0) - return -1 ; - xfer_length = 0 ; - - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - ret = 0 ; - for (; ;) { - is_timeout = 0 ; - wait_event_result = wait_event_interruptible_timeout(i2c4_wait, i2c.isr_int_pending , - (MAX_RX_TIMEOUT * HZ / 1000)) ; - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (rx) \n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (rx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err: write software timeout error (rx) \n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - buf[xfer_length] = (i2c.regs->cdr_reg >> 8) ; - ++xfer_length ; - DPRINTK("i2c_test: received BYTE_END\n\r"); - } - i2c.isr_int_pending = 0; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - if (length > xfer_length) { - if ((length - 1) == xfer_length) { /* next read is the last one*/ - i2c.regs->cr_reg |= (I2C_CR_TX_NEXT_NO_ACK | I2C_CR_CPU_RDY); - DPRINTK("i2c_test: set CPU_RDY & TX_ACK. next data is last.\r\n"); - } else { - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - DPRINTK("i2c_test: more data to read. only set CPU_RDY. \r\n"); - } - } else if (length == xfer_length) { /* end rx xfer*/ - if (last == 1) { /* stop case*/ - DPRINTK("i2c_test: read completed \r\n"); - break ; - } else { /* restart case*/ - /* ??? how to handle the restart after read ?*/ - DPRINTK("i2c_test: RX ReStart Case \r\n") ; - break ; - } - } else { - DPRINTK("i2c_err : read known error\n\r") ; - ret = -EIO ; - break ; - } - } - - DPRINTK("i2c_test: read sequence completed\n\r"); - return ret ; -} - -static int i2c_wmt_write_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete write */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result ; - - DPRINTK("length = %d , slave_addr = %x\n", length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - - ret = 0 ; - for (; ;) { - - is_timeout = 0 ; - /**/ - /* I2C: Wait for interrupt. if ( i2c.isr_int_pending == 1 ) ==> an interrupt exsits.*/ - /**/ - wait_event_result = wait_event_interruptible_timeout(i2c4_wait, i2c.isr_int_pending , (MAX_TX_TIMEOUT * HZ / 1000)) ; - - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (tx)\n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (tx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (tx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (tx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err : write software timeout error (tx)\n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - DPRINTK("i2c: isr end byte (tx)\n\r") ; - ++xfer_length ; - } - i2c.isr_int_pending = 0 ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - - if ((i2c.regs->csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK) { - DPRINTK("i2c_err : write RCV NACK error\n\r") ; - ret = -EIO ; - break ; - } - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) { - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - break ; - } - if (length > xfer_length) { - i2c.regs->cdr_reg = (unsigned short) (buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - i2c.regs->cr_reg = (I2C_CR_CPU_RDY | I2C_CR_ENABLE) ; - DPRINTK("i2c_test: write register data \n\r") ; - } else if (length == xfer_length) { /* end tx xfer*/ - if (last == 1) { /* stop case*/ - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - DPRINTK("i2c_test: finish write \n\r") ; - break ; - } else { /* restart case*/ - /* handle the restart for first write then the next is read*/ - i2c.regs->cr_reg = (I2C_CR_ENABLE) ; - DPRINTK("i2c_test: tx restart Case \n\r") ; - break ; - } - } else { - DPRINTK("i2c_err : write unknown error\n\r") ; - ret = -EIO ; - break ; - } - } ; - - DPRINTK("i2c_test: write sequence completed\n\r"); - - return ret ; -} - -static int i2c_wmt_wait_bus_not_busy(void) -{ - int ret ; - int cnt ; - - ret = 0 ; - cnt = 0 ; - while (1) { - if ((REG16_VAL(I2C4_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) { - ret = 0; - break ; - } - cnt++ ; - - if (cnt > MAX_BUS_READY_CNT) { - ret = (-EBUSY) ; - printk("i2c_err : wait but not ready time-out\n\r") ; - cnt = 0; - break; - } - } - return ret ; -} - -static void i2c_wmt_reset(void) -{ - unsigned short tmp ; - if (is_master == 0) - return; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C4_BASE_ADDR ; - i2c.irq_no = IRQ_I2C4 ; - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* hardware initial*/ - /**/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - else if (i2c.i2c_mode == I2C_FAST_MODE) - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - - DPRINTK("Resetting I2C Controller Unit\n"); - - return ; -} -static int wmt_i2c_transfer_msg(struct wmt_i2cbusfifo *fifo_head) -{ - int xfer_length = fifo_head->xfer_length; - int xfer_msgnum = fifo_head->xfer_msgnum; - struct i2c_msg *pmsg = &fifo_head->msg[xfer_msgnum]; - int restart = fifo_head->restart; - unsigned short tcr_value; - unsigned short slave_addr = pmsg->addr; - int length = pmsg->len; - int ret = 0; - - if (pmsg->flags & I2C_M_RD) { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } else { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(pmsg->buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - } - return ret; -} - -static irqreturn_t i2c_wmt_handler( - int this_irq, /*!<; //[IN] IRQ number */ - void *dev_id /*!<; //[IN] Pointer to device ID */ -) -{ - int wakeup ; - unsigned short isr_status ; - unsigned short tmp ; - unsigned long flags; - struct wmt_i2cbusfifo *fifo_head; - int xfer_length = 0; - int xfer_msgnum = 0; - struct i2c_msg *pmsg; - volatile unsigned short csr_reg; - - spin_lock_irqsave(&i2c_wmt_irqlock, flags); - isr_status = i2c.regs->isr_reg ; - csr_reg = i2c.regs->csr_reg; - wakeup = 0 ; - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - - if (isr_status & I2C_ISR_NACK_ADDR) { - DPRINTK("[%s]:i2c NACK\n", __func__); - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_NACK_ADDR_WRITE_CLEAR ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.isr_nack = 1 ; - wakeup = 1 ; - } - - if ((isr_status & I2C_ISR_BYTE_END && ((csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK))) { - /* - printk("data rcv nack\n"); - */ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_nack = 1 ; - wakeup = 1 ; - } else if (isr_status & I2C_ISR_BYTE_END) { - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_byte_end = 1 ; - xfer_length = fifo_head->xfer_length; - xfer_msgnum = fifo_head->xfer_msgnum; - pmsg = &fifo_head->msg[xfer_msgnum]; - - /*read case*/ - if (pmsg->flags & I2C_M_RD) { - pmsg->buf[xfer_length - 1] = (i2c.regs->cdr_reg >> 8) ; - /*the last data in current msg?*/ - if (xfer_length == pmsg->len - 1) { - /*last msg of the current request?*/ - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_TX_NEXT_NO_ACK); - } - /*spin_unlock(&i2c_fifolock);*/ - } else if (xfer_length == pmsg->len) {/*next msg*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else { /*data of this msg has been transfered*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*next request exist?*/ - if (list_empty(&wmt_i2c_fifohead)) {/*no more reqeust*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - } else { /*more request*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - fifo_head->xfer_length = 0; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - - /* - if (fifo_head->non_block == 0) { - printk("2 : non callback\n"); - wakeup = 1; - } else { - printk("2 :callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } - - } else { /*write case*/ - /*the last data in current msg?*/ - if (xfer_length == pmsg->len) { - /*last msg of the current request?*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - } - /*access next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else {/*this request finish*/ - /*spin_lock(&i2c_fifolock);*/ - /*next request exist?*/ - list_del(&fifo_head->busfifohead);/*del request*/ - if (list_empty(&wmt_i2c_fifohead)) { - /*kfree(fifo_head);*/ - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - - } else { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - /*next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /* - if (fifo_head->non_block == 0) { - printk("4:non callback\n"); - wakeup = 1; - } else { - printk("4:callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - i2c.regs->cdr_reg = (unsigned short) (pmsg->buf[fifo_head->xfer_length] & I2C_CDR_DATA_WRITE_MASK); - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_ENABLE); - } - } - } - - if (isr_status & I2C_ISR_SCL_TIME_OUT) { - DPRINTK("[%s]SCL timeout\n", __func__); -#if 0 - i2c.regs->cr_reg |= BIT7;/*reset status*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR | I2C_ISR_BYTE_END_WRITE_CLEAR; - i2c.isr_timeout = 1 ; - wakeup = 1; -#endif - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR ; - } - - - if (wakeup) { - /*spin_lock_irqsave(&i2c_wmt_irqlock, flags);*/ - i2c.isr_int_pending = 1; - /*spin_unlock_irqrestore(&i2c_wmt_irqlock, flags);*/ - wake_up(&i2c4_wait); - } else - DPRINTK("i2c_err : unknown I2C ISR Handle 0x%4.4X" , isr_status) ; - spin_unlock_irqrestore(&i2c_wmt_irqlock, flags); - return IRQ_HANDLED; -} - -static int i2c_wmt_resource_init(void) -{ - if (is_master == 0) - return 0; - if (request_irq(i2c.irq_no , &i2c_wmt_handler, IRQF_DISABLED, "i2c", 0) < 0) { - DPRINTK(KERN_INFO "I2C: Failed to register I2C irq %i\n", i2c.irq_no); - return -ENODEV; - } - return 0; -} - -static void i2c_wmt_resource_release(void) -{ - if (is_master == 0) - return; - free_irq(i2c.irq_no, 0); -} - -static struct i2c_algo_wmt_data i2c_wmt_data = { - write_msg: i2c_wmt_write_msg, - read_msg: i2c_wmt_read_msg, - send_request: i2c_send_request, - wait_bus_not_busy: i2c_wmt_wait_bus_not_busy, - reset: i2c_wmt_reset, - set_mode: i2c_wmt_set_mode, - udelay: I2C_ALGO_UDELAY, - timeout: I2C_ALGO_TIMEOUT, -}; - -static struct i2c_adapter i2c_wmt_ops = { - .owner = THIS_MODULE, - /* - .id = I2C_ALGO_WMT, - */ - .algo_data = &i2c_wmt_data, - .name = "wmt_i2c4_adapter", - .retries = I2C_ADAPTER_RETRIES, - .nr = 4, -}; - -#ifdef CONFIG_PM -static struct i2c_regs_s wmt_i2c_reg ; -static void i2c_shutdown(void) -{ - printk("i2c4 shutdown\n"); - wmt_i2c4_power_state = 2; - while (!list_empty(&wmt_i2c_fifohead)) - msleep(1); - while (1) {/*wait busy clear*/ - if ((REG16_VAL(I2C4_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) - break ; - msleep(1); - } - return; -} -static int i2c_suspend(void) -{ - printk("i2c4 suspend\n"); - wmt_i2c_reg.imr_reg = i2c.regs->imr_reg; - wmt_i2c_reg.tr_reg = i2c.regs->tr_reg; - wmt_i2c_reg.div_reg = i2c.regs->div_reg; - return 0; -} -static void i2c_resume(void) -{ - printk("i2c4 resume\n"); - /* - GPIO_CTRL_GP17_I2C_BYTE_VAL &= ~(BIT2 | BIT3); - PULL_EN_GP17_I2C_BYTE_VAL |= (BIT2 | BIT3); - PULL_CTRL_GP17_I2C_BYTE_VAL |= (BIT2 | BIT3); - */ - i2c_gpio_init(); - auto_pll_divisor(DEV_I2C4, CLK_ENABLE, 0, 0); - auto_pll_divisor(DEV_I2C4, SET_DIV, 2, 20);/*20M Hz*/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = wmt_i2c_reg.div_reg; - i2c.regs->imr_reg = wmt_i2c_reg.imr_reg; - i2c.regs->tr_reg = wmt_i2c_reg.tr_reg ; - i2c.regs->cr_reg = 0x001 ; -} -#else -#define i2c_suspend NULL -#define i2c_resume NULL -#define i2c_shutdown NULL -#endif -extern int wmt_i2c_add_bus(struct i2c_adapter *); -extern int wmt_i2c_del_bus(struct i2c_adapter *); - -#ifdef CONFIG_PM -static struct syscore_ops wmt_i2c_syscore_ops = -{ - .suspend = i2c_suspend, - .resume = i2c_resume, - .shutdown = i2c_shutdown, -}; -#endif - -static int __init i2c_adap_wmt_init(void) -{ - unsigned short tmp ; - char varname[] = "wmt.i2c.param"; -#ifdef CONFIG_I2C_SLAVE_WMT - char varname1[] = "wmt.bus.i2c.slave_port"; -#endif - unsigned char buf[80]; - int ret; - unsigned int port_num; - int idx = 0; - int varlen = 80; - /*since i2c4 is share pin, it turn on while uboot parameter define i2c4 mode*/ - int i2c_turn_on = 0; - unsigned int pllb_freq = 0; - unsigned int tr_val = 0; - -#ifdef CONFIG_I2C_SLAVE_WMT -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname1, buf, &varlen); -#else - ret = 1; -#endif - is_master = 1; - if (ret == 0) { - ret = sscanf(buf, "%x", &port_num); - while (ret) { - if (port_num != 4) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret; - ret = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; -#endif - wmt_i2c4_is_master = is_master; - if (is_master == 1) { -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname, buf, &varlen); -#else - ret = 1; -#endif - - if (ret == 0) { - ret = sscanf(buf, "%x:%x", &port_num, &speed_mode); - idx += 3; - while (ret) { - if (ret < 2) - speed_mode = 0; - else { - if (port_num != 4) - speed_mode = 0; - else { - i2c_turn_on = 1; - break; - } - } - ret = sscanf(buf + idx, ",%x:%x", &port_num, &speed_mode); - idx += 4; - } - } - if (i2c_turn_on == 0) { - printk("I2C4 turn off\n"); - return -EIO; - } - if (speed_mode > 1) - speed_mode = 0; - wmt_i2c4_speed_mode = speed_mode; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C4_BASE_ADDR ; - i2c.irq_no = IRQ_I2C4 ; - printk("PORT 4 speed_mode = %d\n", speed_mode); - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else if (speed_mode == 1) - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - /**/ - /* hardware initial*/ - /**/ - auto_pll_divisor(DEV_I2C4, CLK_ENABLE, 0, 0); - pllb_freq = auto_pll_divisor(DEV_I2C4, SET_DIV, 2, 20);/*20M Hz*/ - i2c_gpio_init(); - printk("pllb_freq = %d\n", pllb_freq); - if ((pllb_freq%(1000*2*100)) != 0) - tr_val = pllb_freq/(1000*2*100) + 1; - else - tr_val = pllb_freq/(1000*2*100); - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = 0xff00|tr_val; - else if (i2c.i2c_mode == I2C_FAST_MODE) { - tr_val /= 4; - i2c.regs->tr_reg = 0xff00|tr_val ; - } - } - - - if (i2c_wmt_resource_init() == 0) { - if (wmt_i2c_add_bus(&i2c_wmt_ops) < 0) { - i2c_wmt_resource_release(); - printk(KERN_INFO "i2c: Failed to add bus\n"); - return -ENODEV; - } - } else - return -ENODEV; - - INIT_LIST_HEAD(&wmt_i2c_fifohead); - -#ifdef CONFIG_PM - register_syscore_ops(&wmt_i2c_syscore_ops); -#endif - - wmt_i2c4_power_state = 0; - printk(KERN_INFO "i2c: successfully added bus\n"); - -#ifdef I2C_REG_TEST - printk("i2c.regs->cr_reg= 0x%08x\n\r", i2c.regs->cr_reg); - printk("i2c.regs->tcr_reg= 0x%08x\n\r", i2c.regs->tcr_reg); - printk("i2c.regs->csr_reg= 0x%08x\n\r", i2c.regs->csr_reg); - printk("i2c.regs->isr_reg= 0x%08x\n\r", i2c.regs->isr_reg); - printk("i2c.regs->imr_reg= 0x%08x\n\r", i2c.regs->imr_reg); - printk("i2c.regs->cdr_reg= 0x%08x\n\r", i2c.regs->cdr_reg); - printk("i2c.regs->tr_reg= 0x%08x\n\r", i2c.regs->tr_reg); - printk("i2c.regs->div_reg= 0x%08x\n\r", i2c.regs->div_reg); -#endif - - return 0; -} -subsys_initcall(i2c_adap_wmt_init); - -static void i2c_adap_wmt_exit(void) -{ - wmt_i2c_del_bus(&i2c_wmt_ops); - i2c_wmt_resource_release(); - - printk(KERN_INFO "i2c: successfully removed bus\n"); -} - - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C Adapter Driver"); -MODULE_LICENSE("GPL"); - -module_exit(i2c_adap_wmt_exit); - diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus.c deleted file mode 100755 index ecfda642..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-bus.c +++ /dev/null @@ -1,1254 +0,0 @@ -/*++ - drivers/i2c/busses/wmt-i2c-bus.c - - Copyright (c) 2013 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ -/* Include your headers here*/ -#include <linux/kernel.h> -#include <linux/module.h> - -#include <linux/i2c.h> -/* -#include <linux/i2c-id.h> -*/ -#include <linux/init.h> -#include <linux/time.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/errno.h> -#include <linux/interrupt.h> - -#include <mach/hardware.h> -#include <asm/irq.h> -#include <mach/irqs.h> -#include <mach/wmt-i2c-bus.h> -#include <linux/slab.h> -#include <linux/pm.h> -#include <linux/syscore_ops.h> - -#ifdef __KERNEL__ - -#ifdef DEBUG - #define DPRINTK printk -#else - #define DPRINTK(x...) -#endif - -#else - #define DPRINTK printf - -#endif - - -#define MAX_BUS_READY_CNT 50 /* jiffy*/ -#define MAX_TX_TIMEOUT 500 /* ms*/ -#define MAX_RX_TIMEOUT 500 /* ms*/ -#define CTRL_GPIO GPIO_CTRL_GP17_I2C_BYTE_ADDR -#define PU_EN_GPIO PULL_EN_GP17_I2C_BYTE_ADDR -#define PU_CTRL_GPIO PULL_CTRL_GP17_I2C_BYTE_ADDR - -#define USE_UBOOT_PARA - -struct wmt_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int volatile isr_nack ; - int volatile isr_byte_end ; - int volatile isr_timeout ; - int volatile isr_int_pending ; -}; - -static int i2c_wmt_wait_bus_not_busy(void); -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int speed_mode = 0; -static unsigned int is_master = 1;/*master:1, slave:0*/ -unsigned int wmt_i2c0_is_master = 1; -unsigned int wmt_i2c0_speed_mode = 0; -static unsigned int wmt_i2c0_power_state = 0;/*0:power on, 1:suspend, 2:shutdown*/ -EXPORT_SYMBOL(wmt_i2c0_is_master); - -/**/ -/* variable*/ -/*-------------------------------------------------*/ -static volatile struct wmt_i2c_s i2c ; - -DECLARE_WAIT_QUEUE_HEAD(i2c1_wait); -/* -spinlock_t i2c1_wmt_irqlock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c1_wmt_irqlock); -static struct list_head wmt_i2c_fifohead; -/* -static spinlock_t i2c_fifolock = SPIN_LOCK_UNLOCKED; -*/ -static DEFINE_SPINLOCK(i2c_fifolock); -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -); - -static void i2c_wmt_set_mode(enum i2c_mode_e mode /*!<; //[IN] mode */) -{ - if (is_master == 0) - return; - i2c.i2c_mode = mode ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - DPRINTK("I2C: set standard mode \n"); - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - DPRINTK("I2C: set fast mode \n"); - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - } -} - - -static int i2c_send_request( - struct i2c_msg *msg, - int msg_num, - int non_block, - void (*callback)(void *data), - void *data -) -{ - struct wmt_i2cbusfifo *i2c_fifo_head; - struct i2c_msg *pmsg = NULL; - int ret = 0; - int restart = 0; - int last = 0; - unsigned long flags; - int slave_addr = msg[0].addr; - - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - if (wmt_i2c0_power_state == 2) { - printk("I2C0 has been shutdown\n"); - return -EIO; - } - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c_fifo_head = kzalloc(sizeof(struct wmt_i2cbusfifo), GFP_ATOMIC); - INIT_LIST_HEAD(&i2c_fifo_head->busfifohead); - - pmsg = &msg[0]; - i2c_fifo_head->msg = pmsg; - i2c_fifo_head->msg_num = msg_num; - - spin_lock_irqsave(&i2c_fifolock, flags); - if (list_empty(&wmt_i2c_fifohead)) { - i2c_wmt_wait_bus_not_busy(); - pmsg = &msg[0]; - i2c_fifo_head->xfer_length = 1; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - if (pmsg->flags & I2C_M_RD) { - i2c_fifo_head->xfer_length = 1; - ret = i2c_wmt_read_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } else { - i2c_fifo_head->xfer_length = 1; - if (pmsg->flags & I2C_M_NOSTART) - i2c_fifo_head->restart = 1; - else - i2c_fifo_head->restart = 0; - ret = i2c_wmt_write_buf(pmsg->addr, pmsg->buf, pmsg->len, restart, last); - } - - } else { - i2c_fifo_head->xfer_length = 0; - i2c_fifo_head->xfer_msgnum = 0; - i2c_fifo_head->restart = 0; - i2c_fifo_head->non_block = non_block; - if (non_block == 1) { - i2c_fifo_head->callback = callback; - i2c_fifo_head->data = data; - } else { - i2c_fifo_head->callback = 0; - i2c_fifo_head->data = 0; - } - list_add_tail(&i2c_fifo_head->busfifohead, &wmt_i2c_fifohead); - } - spin_unlock_irqrestore(&i2c_fifolock, flags); - if (non_block == 0) { - wait_event(i2c1_wait, i2c.isr_int_pending); - ret = msg_num; - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - ret = -ETIMEDOUT ; - } - - } - - return ret; - - -} -static int i2c_wmt_read_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value; - int ret = 0; - - DPRINTK("[%s]:length = %d , slave_addr = %x\n", __func__, length , slave_addr); - - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (length <=0) - return -1; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - tcr_value = 0 ; - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - return ret; -} - -static int i2c_wmt_write_buf( - unsigned int slave_addr, - char *buf, - unsigned int length, - int restart, - int last -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int ret = 0 ; - - DPRINTK("[%s]length = %d , slave_addr = %x\n", __func__, length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - ret = 0 ; - return ret; - -} -static int i2c_wmt_read_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete read */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result = 0 ; - - if (is_master == 0) - return -ENXIO; - if (length <= 0) - return -1 ; - xfer_length = 0 ; - - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - ret = 0 ; - for (; ;) { - is_timeout = 0 ; - wait_event_result = wait_event_interruptible_timeout(i2c1_wait, i2c.isr_int_pending , - (MAX_RX_TIMEOUT * HZ / 1000)) ; - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (rx) \n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (rx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (rx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (rx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err: write software timeout error (rx) \n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - buf[xfer_length] = (i2c.regs->cdr_reg >> 8) ; - ++xfer_length ; - DPRINTK("i2c_test: received BYTE_END\n\r"); - } - i2c.isr_int_pending = 0; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - if (length > xfer_length) { - if ((length - 1) == xfer_length) { /* next read is the last one*/ - i2c.regs->cr_reg |= (I2C_CR_TX_NEXT_NO_ACK | I2C_CR_CPU_RDY); - DPRINTK("i2c_test: set CPU_RDY & TX_ACK. next data is last.\r\n"); - } else { - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - DPRINTK("i2c_test: more data to read. only set CPU_RDY. \r\n"); - } - } else if (length == xfer_length) { /* end rx xfer*/ - if (last == 1) { /* stop case*/ - DPRINTK("i2c_test: read completed \r\n"); - break ; - } else { /* restart case*/ - /* ??? how to handle the restart after read ?*/ - DPRINTK("i2c_test: RX ReStart Case \r\n") ; - break ; - } - } else { - DPRINTK("i2c_err : read known error\n\r") ; - ret = -EIO ; - break ; - } - } - - DPRINTK("i2c_test: read sequence completed\n\r"); - return ret ; -} - -static int i2c_wmt_write_msg( - unsigned int slave_addr, /*!<; //[IN] Salve address */ - char *buf, /*!<; //[OUT] Pointer to data */ - unsigned int length, /*!<; //Data length */ - int restart, /*!<; //Need to restart after a complete write */ - int last /*!<; //Last read */ -) -{ - unsigned short tcr_value ; - unsigned int xfer_length ; - int is_timeout ; - int ret = 0 ; - int wait_event_result ; - - DPRINTK("length = %d , slave_addr = %x\n", length , slave_addr); - if (slave_addr == WMT_I2C_API_I2C_ADDR) - return ret ; - - if (is_master == 0) - return -ENXIO; - - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length < 0) - return -1 ; - xfer_length = 0 ; /* for array index and also for checking counting*/ - if (restart == 0) - ret = i2c_wmt_wait_bus_not_busy() ; - if (ret < 0) - return ret ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - - ret = 0 ; - for (; ;) { - - is_timeout = 0 ; - /**/ - /* I2C: Wait for interrupt. if ( i2c.isr_int_pending == 1 ) ==> an interrupt exsits.*/ - /**/ - wait_event_result = wait_event_interruptible_timeout(i2c1_wait, i2c.isr_int_pending , (MAX_TX_TIMEOUT * HZ / 1000)) ; - - if (likely(wait_event_result > 0)) { - DPRINTK("I2C: wait interrupted (tx)\n"); - ret = 0 ; - } else if (likely(i2c.isr_int_pending == 0)) { - DPRINTK("I2C: wait timeout (tx) \n"); - is_timeout = 1 ; - ret = -ETIMEDOUT ; - } - - /**/ - /* fail case*/ - /**/ - if (i2c.isr_nack == 1) { - DPRINTK("i2c_err : write NACK error (tx) \n\r") ; - ret = -EIO ; - break ; - } - if (i2c.isr_timeout == 1) { - DPRINTK("i2c_err : write SCL timeout error (tx)\n\r") ; - msleep(10); - ret = -ETIMEDOUT ; - break ; - } - if (is_timeout == 1) { - DPRINTK("i2c_err : write software timeout error (tx)\n\r") ; - ret = -ETIMEDOUT ; - break ; - } - - /**/ - /* pass case*/ - /**/ - if (i2c.isr_byte_end == 1) { - DPRINTK("i2c: isr end byte (tx)\n\r") ; - ++xfer_length ; - } - i2c.isr_int_pending = 0 ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - - - if ((i2c.regs->csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK) { - DPRINTK("i2c_err : write RCV NACK error\n\r") ; - ret = -EIO ; - break ; - } - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) { - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - break ; - } - if (length > xfer_length) { - i2c.regs->cdr_reg = (unsigned short) (buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - i2c.regs->cr_reg = (I2C_CR_CPU_RDY | I2C_CR_ENABLE) ; - DPRINTK("i2c_test: write register data \n\r") ; - } else if (length == xfer_length) { /* end tx xfer*/ - if (last == 1) { /* stop case*/ - i2c.regs->cr_reg = (I2C_CR_TX_END|I2C_CR_CPU_RDY|I2C_CR_ENABLE) ; - DPRINTK("i2c_test: finish write \n\r") ; - break ; - } else { /* restart case*/ - /* handle the restart for first write then the next is read*/ - i2c.regs->cr_reg = (I2C_CR_ENABLE) ; - DPRINTK("i2c_test: tx restart Case \n\r") ; - break ; - } - } else { - DPRINTK("i2c_err : write unknown error\n\r") ; - ret = -EIO ; - break ; - } - } ; - - DPRINTK("i2c_test: write sequence completed\n\r"); - - return ret ; -} - -static int i2c_wmt_wait_bus_not_busy(void) -{ - int ret ; - int cnt ; - - ret = 0 ; - cnt = 0 ; - while (1) { - if ((REG16_VAL(I2C_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) { - ret = 0; - break ; - } - cnt++ ; - - if (cnt > MAX_BUS_READY_CNT) { - ret = (-EBUSY) ; - printk("i2c_err 0: wait but not ready time-out\n\r") ; - cnt = 0; - break; //add by rambo d10 always has it 2013-4-14 - } - } - return ret ; -} - -static void i2c_wmt_reset(void) -{ - unsigned short tmp ; - if (is_master == 0) - return; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C0_BASE_ADDR ; - i2c.irq_no = IRQ_I2C0 ; - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else - i2c.i2c_mode = I2C_FAST_MODE ; - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - - /**/ - /* hardware initial*/ - /**/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = I2C_TR_STD_VALUE ; /* 0x8041*/ - else if (i2c.i2c_mode == I2C_FAST_MODE) - i2c.regs->tr_reg = I2C_TR_FAST_VALUE ; /* 0x8011*/ - - DPRINTK("Resetting I2C Controller Unit\n"); - - return ; -} -static int wmt_i2c_transfer_msg(struct wmt_i2cbusfifo *fifo_head) -{ - int xfer_length = fifo_head->xfer_length; - int xfer_msgnum = fifo_head->xfer_msgnum; - struct i2c_msg *pmsg = &fifo_head->msg[xfer_msgnum]; - int restart = fifo_head->restart; - unsigned short tcr_value; - unsigned short slave_addr = pmsg->addr; - int length = pmsg->len; - int ret = 0; - - if (pmsg->flags & I2C_M_RD) { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg &= ~(I2C_CR_TX_NEXT_NO_ACK); /*clear NEXT_NO_ACK*/ - if (restart == 0) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) { - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - } else if (i2c.i2c_mode == I2C_FAST_MODE) { - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_READ |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - } - if (length == 1) - i2c.regs->cr_reg |= I2C_CR_TX_NEXT_NO_ACK; /*only 8-bit to read*/ - - i2c.regs->tcr_reg = tcr_value ; - - /*repeat start case*/ - if (restart == 1) - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } else { - if (restart == 0) - i2c_wmt_wait_bus_not_busy(); - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - /*i2c.isr_int_pending = 0;*/ - - /**/ - /* special case allow length:0, for i2c_smbus_xfer*/ - /**/ - if (length == 0) - i2c.regs->cdr_reg = 0 ; - else - i2c.regs->cdr_reg = (unsigned short)(pmsg->buf[xfer_length] & I2C_CDR_DATA_WRITE_MASK) ; - - if (restart == 0) { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); /*clear Tx end*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY); /*release SCL*/ - } - - /**/ - /* I2C: Set transfer mode [standard/fast]*/ - /**/ - tcr_value = 0 ; - if (i2c.i2c_mode == I2C_STANDARD_MODE) - tcr_value = (unsigned short)(I2C_TCR_STANDARD_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - else if (i2c.i2c_mode == I2C_FAST_MODE) - tcr_value = (unsigned short)(I2C_TCR_FAST_MODE|I2C_TCR_MASTER_WRITE |\ - (slave_addr & I2C_TCR_SLAVE_ADDR_MASK)) ; - - i2c.regs->tcr_reg = tcr_value ; - - if (restart == 1) - i2c.regs->cr_reg |= I2C_CR_CPU_RDY ; - } - return ret; -} - -static irqreturn_t i2c_wmt_handler( - int this_irq, /*!<; //[IN] IRQ number */ - void *dev_id /*!<; //[IN] Pointer to device ID */ -) -{ - int wakeup ; - unsigned short isr_status ; - unsigned short tmp ; - unsigned long flags; - struct wmt_i2cbusfifo *fifo_head; - int xfer_length = 0; - int xfer_msgnum = 0; - struct i2c_msg *pmsg; - volatile unsigned short csr_reg; - - spin_lock_irqsave(&i2c1_wmt_irqlock, flags); - isr_status = i2c.regs->isr_reg ; - csr_reg = i2c.regs->csr_reg; - wakeup = 0 ; - fifo_head = list_first_entry(&wmt_i2c_fifohead, struct wmt_i2cbusfifo, busfifohead); - - if (isr_status & I2C_ISR_NACK_ADDR) { - DPRINTK("[%s]:i2c NACK\n", __func__); - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_NACK_ADDR_WRITE_CLEAR ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.isr_nack = 1 ; - wakeup = 1 ; - } - - if ((isr_status & I2C_ISR_BYTE_END && ((csr_reg & I2C_CSR_RCV_ACK_MASK) == I2C_CSR_RCV_NOT_ACK))) { - /* - printk("data rcv nack\n"); - */ - list_del(&fifo_head->busfifohead);/*del request*/ - kfree(fifo_head); - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_nack = 1 ; - wakeup = 1 ; - } else if (isr_status & I2C_ISR_BYTE_END) { - i2c.regs->isr_reg = I2C_ISR_BYTE_END_WRITE_CLEAR ; - i2c.isr_byte_end = 1 ; - xfer_length = fifo_head->xfer_length; - xfer_msgnum = fifo_head->xfer_msgnum; - pmsg = &fifo_head->msg[xfer_msgnum]; - - /*read case*/ - if (pmsg->flags & I2C_M_RD) { - pmsg->buf[xfer_length - 1] = (i2c.regs->cdr_reg >> 8) ; - /*the last data in current msg?*/ - if (xfer_length == pmsg->len - 1) { - /*last msg of the current request?*/ - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - /* - ++fifo_head->xfer_msgnum; - */ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_TX_NEXT_NO_ACK); - } - /*spin_unlock(&i2c_fifolock);*/ - } else if (xfer_length == pmsg->len) {/*next msg*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else { /*data of this msg has been transfered*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*next request exist?*/ - if (list_empty(&wmt_i2c_fifohead)) {/*no more reqeust*/ - /*kfree(fifo_head);*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - } else { /*more request*/ - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - fifo_head->xfer_length = 0; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - - /* - if (fifo_head->non_block == 0) { - printk("2 : non callback\n"); - wakeup = 1; - } else { - printk("2 :callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= I2C_CR_CPU_RDY; - } - - } else { /*write case*/ - /*the last data in current msg?*/ - if (xfer_length == pmsg->len) { - /*last msg of the current request?*/ - if (xfer_msgnum < fifo_head->msg_num - 1) { - /*spin_lock(&i2c_fifolock);*/ - if (pmsg->flags & I2C_M_NOSTART) { - ++fifo_head->xfer_length; - fifo_head->restart = 1; - } else { - ++fifo_head->xfer_length; - fifo_head->restart = 0; - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - } - /*access next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - } else {/*this request finish*/ - /*spin_lock(&i2c_fifolock);*/ - /*next request exist?*/ - list_del(&fifo_head->busfifohead);/*del request*/ - if (list_empty(&wmt_i2c_fifohead)) { - /*kfree(fifo_head);*/ - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - - } else { - i2c.regs->cr_reg &= ~(I2C_CR_TX_END); - udelay(2); - i2c.regs->cr_reg |= (I2C_CR_TX_END); - if (fifo_head->non_block == 0) { - wakeup = 1; - } else { - fifo_head->callback(fifo_head->data); - } - kfree(fifo_head); - fifo_head = list_first_entry(&wmt_i2c_fifohead, - struct wmt_i2cbusfifo, busfifohead); - /* - if (fifo_head->non_block == 0) - wakeup = 1; - */ - - /*next msg*/ - fifo_head->xfer_length = 0; - ++fifo_head->xfer_msgnum; - wmt_i2c_transfer_msg(fifo_head); - ++fifo_head->xfer_length; - /* - if (fifo_head->non_block == 0) { - printk("4:non callback\n"); - wakeup = 1; - } else { - printk("4:callback\n"); - fifo_head->callback(fifo_head->data); - } - */ - } - /*spin_unlock(&i2c_fifolock);*/ - } - } else {/*next data*/ - i2c.regs->cdr_reg = (unsigned short) (pmsg->buf[fifo_head->xfer_length] & I2C_CDR_DATA_WRITE_MASK); - /*spin_lock(&i2c_fifolock);*/ - ++fifo_head->xfer_length; - /*spin_unlock(&i2c_fifolock);*/ - i2c.regs->cr_reg |= (I2C_CR_CPU_RDY | I2C_CR_ENABLE); - } - } - } - - if (isr_status & I2C_ISR_SCL_TIME_OUT) { - DPRINTK("[%s]SCL timeout\n", __func__); -#if 0 - i2c.regs->cr_reg |= BIT7;/*reset status*/ - /*spin_lock(&i2c_fifolock);*/ - list_del(&fifo_head->busfifohead);/*del request*/ - /*spin_unlock(&i2c_fifolock);*/ - xfer_length = 0; - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR | I2C_ISR_BYTE_END_WRITE_CLEAR; - i2c.isr_timeout = 1 ; - wakeup = 1; -#endif - i2c.regs->isr_reg = I2C_ISR_SCL_TIME_OUT_WRITE_CLEAR ; - } - - - if (wakeup) { - /*spin_lock_irqsave(&i2c_wmt_irqlock, flags);*/ - i2c.isr_int_pending = 1; - /*spin_unlock_irqrestore(&i2c_wmt_irqlock, flags);*/ - wake_up(&i2c1_wait); - } else - DPRINTK("i2c_err : unknown I2C ISR Handle 0x%4.4X" , isr_status) ; - spin_unlock_irqrestore(&i2c1_wmt_irqlock, flags); - return IRQ_HANDLED; -} - -static int i2c_wmt_resource_init(void) -{ - if (is_master == 0) - return 0; - if (request_irq(i2c.irq_no , &i2c_wmt_handler, IRQF_DISABLED, "i2c", 0) < 0) { - DPRINTK(KERN_INFO "I2C: Failed to register I2C irq %i\n", i2c.irq_no); - return -ENODEV; - } - return 0; -} - -static void i2c_wmt_resource_release(void) -{ - if (is_master == 0) - return; - free_irq(i2c.irq_no, 0); -} - -static struct i2c_algo_wmt_data i2c_wmt_data = { - write_msg: i2c_wmt_write_msg, - read_msg: i2c_wmt_read_msg, - send_request: i2c_send_request, - wait_bus_not_busy: i2c_wmt_wait_bus_not_busy, - reset: i2c_wmt_reset, - set_mode: i2c_wmt_set_mode, - udelay: I2C_ALGO_UDELAY, - timeout: I2C_ALGO_TIMEOUT, -}; - -static struct i2c_adapter i2c_wmt_ops = { - .owner = THIS_MODULE, - /* - .id = I2C_ALGO_WMT, - */ - .algo_data = &i2c_wmt_data, - .name = "wmt_i2c_adapter", - .retries = I2C_ADAPTER_RETRIES, - .nr = 0, -}; - -#ifdef CONFIG_PM -static struct i2c_regs_s wmt_i2c_reg ; -static void i2c_shutdown(void) -{ - printk("i2c0 shutdown\n"); - wmt_i2c0_power_state = 2; - while (!list_empty(&wmt_i2c_fifohead)) - msleep(1); - while (1) {/*wait busy clear*/ - if ((REG16_VAL(I2C_CSR_ADDR) & I2C_STATUS_MASK) == I2C_READY) - break ; - msleep(1); - } - return; -} -static int i2c_suspend(void) -{ - printk("i2c0 suspend\n"); - wmt_i2c_reg.imr_reg = i2c.regs->imr_reg; - wmt_i2c_reg.tr_reg = i2c.regs->tr_reg; - wmt_i2c_reg.div_reg = i2c.regs->div_reg; - return 0; -} -static void i2c_resume(void) -{ - printk("i2c0 resume\n"); - GPIO_CTRL_GP17_I2C_BYTE_VAL &= ~(BIT0 | BIT1); - PULL_EN_GP17_I2C_BYTE_VAL |= (BIT0 | BIT1); - PULL_CTRL_GP17_I2C_BYTE_VAL |= (BIT0 | BIT1); - auto_pll_divisor(DEV_I2C0, CLK_ENABLE, 0, 0); - auto_pll_divisor(DEV_I2C0, SET_DIV, 2, 20);/*20M Hz*/ - - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = wmt_i2c_reg.div_reg; - i2c.regs->imr_reg = wmt_i2c_reg.imr_reg; - i2c.regs->tr_reg = wmt_i2c_reg.tr_reg ; - i2c.regs->cr_reg = 0x001 ; -} -#else -#define i2c_suspend NULL -#define i2c_resume NULL -#define i2c_shutdown NULL -#endif -extern int wmt_i2c_add_bus(struct i2c_adapter *); -extern int wmt_i2c_del_bus(struct i2c_adapter *); - -#ifdef CONFIG_PM -static struct syscore_ops wmt_i2c_syscore_ops = -{ - .suspend = i2c_suspend, - .resume = i2c_resume, - .shutdown = i2c_shutdown, -}; -#endif - -static int __init i2c_adap_wmt_init(void) -{ - unsigned short tmp ; - char varname[] = "wmt.i2c.param"; -#ifdef CONFIG_I2C_SLAVE_WMT - char varname1[] = "wmt.bus.i2c.slave_port"; -#endif - unsigned char buf[80]; - int ret; - unsigned int port_num; - int idx = 0; - int varlen = 80; - unsigned int pllb_freq = 0; - unsigned int tr_val = 0; - -#ifdef CONFIG_I2C_SLAVE_WMT -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname1, buf, &varlen); -#else - ret = 1; -#endif - is_master = 1; - if (ret == 0) { - ret = sscanf(buf, "%x", &port_num); - while (ret) { - if (port_num != 0) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret; - ret = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; -#endif - wmt_i2c0_is_master = is_master; - if (is_master == 1) { -#ifdef USE_UBOOT_PARA - ret = wmt_getsyspara(varname, buf, &varlen); -#else - ret = 1; -#endif - - if (ret == 0) { - ret = sscanf(buf, "%x:%x", &port_num, &speed_mode); - idx += 3; - while (ret) { - if (ret < 2) - speed_mode = 0; - else { - if (port_num != 0) - speed_mode = 0; - else - break; - } - ret = sscanf(buf + idx, ",%x:%x", &port_num, &speed_mode); - idx += 4; - } - } - if (speed_mode > 1) - speed_mode = 0; - wmt_i2c0_speed_mode = speed_mode; - - /**/ - /* software initial*/ - /**/ - i2c.regs = (struct i2c_regs_s *)I2C0_BASE_ADDR ; - i2c.irq_no = IRQ_I2C0 ; - - printk("PORT 0 speed_mode = %d\n", speed_mode); - if (speed_mode == 0) - i2c.i2c_mode = I2C_STANDARD_MODE ; - else if (speed_mode == 1) - i2c.i2c_mode = I2C_FAST_MODE ; - - i2c.isr_nack = 0 ; - i2c.isr_byte_end = 0 ; - i2c.isr_timeout = 0 ; - i2c.isr_int_pending = 0; - /**/ - /* hardware initial*/ - /**/ - auto_pll_divisor(DEV_I2C0, CLK_ENABLE, 0, 0); - pllb_freq = auto_pll_divisor(DEV_I2C0, SET_DIV, 2, 20);/*20M Hz*/ - if ((pllb_freq%(1000*2*100)) != 0) - tr_val = pllb_freq/(1000*2*100) + 1; - else - tr_val = pllb_freq/(1000*2*100); - *(volatile unsigned char *)CTRL_GPIO &= ~(BIT0 | BIT1); - *(volatile unsigned char *)PU_EN_GPIO |= (BIT0 | BIT1); - *(volatile unsigned char *)PU_CTRL_GPIO |= (BIT0 | BIT1); - i2c.regs->cr_reg = 0 ; - i2c.regs->div_reg = APB_96M_I2C_DIV ; - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - i2c.regs->imr_reg = I2C_IMR_ALL_ENABLE ; /* 0x0007*/ - - i2c.regs->cr_reg = I2C_CR_ENABLE ; - tmp = i2c.regs->csr_reg ; /* read clear*/ - i2c.regs->isr_reg = I2C_ISR_ALL_WRITE_CLEAR ; /* 0x0007*/ - - if (i2c.i2c_mode == I2C_STANDARD_MODE) - i2c.regs->tr_reg = 0xff00|tr_val; - else if (i2c.i2c_mode == I2C_FAST_MODE) { - tr_val /= 4; - i2c.regs->tr_reg = 0xff00|tr_val ; - } - } - - - if (i2c_wmt_resource_init() == 0) { - if (wmt_i2c_add_bus(&i2c_wmt_ops) < 0) { - i2c_wmt_resource_release(); - printk(KERN_INFO "i2c: Failed to add bus\n"); - return -ENODEV; - } - } else - return -ENODEV; - - INIT_LIST_HEAD(&wmt_i2c_fifohead); - -#ifdef CONFIG_PM - printk("register i2c0 syscore ops\n"); - register_syscore_ops(&wmt_i2c_syscore_ops); -#endif - wmt_i2c0_power_state = 0; - printk(KERN_INFO "i2c: successfully added bus\n"); - -#ifdef I2C_REG_TEST - printk("i2c.regs->cr_reg= 0x%08x\n\r", i2c.regs->cr_reg); - printk("i2c.regs->tcr_reg= 0x%08x\n\r", i2c.regs->tcr_reg); - printk("i2c.regs->csr_reg= 0x%08x\n\r", i2c.regs->csr_reg); - printk("i2c.regs->isr_reg= 0x%08x\n\r", i2c.regs->isr_reg); - printk("i2c.regs->imr_reg= 0x%08x\n\r", i2c.regs->imr_reg); - printk("i2c.regs->cdr_reg= 0x%08x\n\r", i2c.regs->cdr_reg); - printk("i2c.regs->tr_reg= 0x%08x\n\r", i2c.regs->tr_reg); - printk("i2c.regs->div_reg= 0x%08x\n\r", i2c.regs->div_reg); -#endif - - return 0; -} -subsys_initcall(i2c_adap_wmt_init); - -static void i2c_adap_wmt_exit(void) -{ - wmt_i2c_del_bus(&i2c_wmt_ops); - i2c_wmt_resource_release(); - - printk(KERN_INFO "i2c: successfully removed bus\n"); -} - - -MODULE_AUTHOR("WonderMedia Technologies, Inc."); -MODULE_DESCRIPTION("WMT I2C Adapter Driver"); -MODULE_LICENSE("GPL"); - -module_exit(i2c_adap_wmt_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus-1.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus-1.c deleted file mode 100755 index 90b49ea8..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus-1.c +++ /dev/null @@ -1,661 +0,0 @@ -/*++ - drivers/i2c/busses/wmt-i2c-slave-bus-1.c - - Copyright (c) 2008 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. - - History: - 2010/03/15 First Version ---*/ - -#include <linux/config.h> -#define WMT_I2C1_SLAVE_C - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/errno.h> -#include <asm/uaccess.h> -#include <linux/kdev_t.h> -#include <linux/cdev.h> -#include <asm/semaphore.h> -#include <linux/proc_fs.h> - -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <mach/hardware.h> -#include "./wmt-i2c-slave-bus.h" -/*#define DEBUG*/ -#ifdef DEBUG -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - - -#define DEVICE_NAME "WMT_I2C_SLAVE-1" -#define PMC_ClOCK_ENABLE_LOWER 0xd8130250 -#define CTRL_GPIO21 0xD8110055 -#define PU_EN_GPIO21 0xD8110495 -#define PU_CTRL_GPIO21 0xD81104D5 - -#define DISABLE_I2C_SLAVE BIT15 - -struct i2c_slave_msg { - __u16 addr; /* slave address */ - __u16 flags; -#define I2C_M_RD 0x01 - __u16 len; /* data length */ - __u8 *buf; /* pointer to data */ -}; - -struct slave_i2c_dev_s { - /* module parameters */ - char *buf; - - /* char dev struct */ - struct cdev cdev; - struct class *class_slave_i2c; -}; - - -struct wmt_slave_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int isr_nack ; - int isr_byte_end ; - int isr_timeout ; - int isr_int_pending ; - struct compat_semaphore tx_sem; - struct compat_semaphore rx_sem; -}; - -static struct i2c_regs_s regs_backup; -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int is_master = 1;/*master:1, slave:0*/ - -static DEFINE_SPINLOCK(slave_i2c_lock); - -static int slave_i2c_dev_major = SLAVE_I2C_MAJOR; -static int slave_i2c_dev_minor = 1; -static int slave_i2c_dev_nr = 1; -static struct slave_i2c_dev_s slave_i2c_dev; - -static struct wmt_slave_i2c_s slave_i2c_port; - -static unsigned char slave_i2c_addr = 0x31; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *slave_i2c_proc; - -static int slave_i2c_reg_read(char *buf, char **start, off_t offset, int len) -{ - char *p = buf; - p += sprintf(p, "reg : value\n"); - p += sprintf(p, "cr : 0x%.4x\n", slave_i2c_port.regs->cr_reg); - p += sprintf(p, "tcr : 0x%.4x\n", slave_i2c_port.regs->tcr_reg); - p += sprintf(p, "csr : 0x%.4x\n", slave_i2c_port.regs->csr_reg); - p += sprintf(p, "isr : 0x%.4x\n", slave_i2c_port.regs->isr_reg); - p += sprintf(p, "imr : 0x%.4x\n", slave_i2c_port.regs->imr_reg); - p += sprintf(p, "cdr : 0x%.4x\n", slave_i2c_port.regs->cdr_reg); - p += sprintf(p, "tr : 0x%.4x\n", slave_i2c_port.regs->tr_reg); - p += sprintf(p, "scr : 0x%.4x\n", slave_i2c_port.regs->scr_reg); - p += sprintf(p, "cssr : 0x%.4x\n", slave_i2c_port.regs->cssr_reg); - p += sprintf(p, "simr : 0x%.4x\n", slave_i2c_port.regs->simr_reg); - p += sprintf(p, "sisr : 0x%.4x\n", slave_i2c_port.regs->sisr_reg); - p += sprintf(p, "csdr : 0x%.4x\n", slave_i2c_port.regs->csdr_reg); - p += sprintf(p, "str : 0x%.4x\n", slave_i2c_port.regs->str_reg); - return p - buf; -} - -static int slave_i2c_addr_read(char *buf, char **start, off_t offset, int len) -{ - char *p = buf; - p += sprintf(p, "i2c-slave address : 0x%.2x\n", slave_i2c_addr); - return p - buf; -} - -#endif - -static irqreturn_t slave_i2c_isr( - int irq, /*!<; // IRQ number */ - void *dev, /*!<; // Private paramater(i.e. pointer of spi port) */ - struct pt_regs *regs /*!<; // interrupt register */ -) -{ - unsigned short isr_status = slave_i2c_port.regs->sisr_reg; - unsigned short ssr_status = slave_i2c_port.regs->cssr_reg; - DPRINTK("slave_i2c isr sisr = %x\n", isr_status); - DPRINTK("slave_i2c isr cssr = %x\n", ssr_status); - if (isr_status & I2C_SISR_DAT_REQ) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_DAT_REQ_WRITE_CLEAR; - slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK; - compat_up(&slave_i2c_port.tx_sem); - } else if (isr_status & I2C_SISR_BYTE_END) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_BYTE_END_WRITE_CLEAR; - slave_i2c_port.isr_byte_end = 1; - slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK; - compat_up(&slave_i2c_port.rx_sem); - } else if (isr_status & I2C_SISR_SCL_TIME_OUT) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_SCL_TIME_OUT_WRITE_CLEAR; - slave_i2c_port.isr_timeout = 1 ; - } - return IRQ_HANDLED; -} - -static int wmt_slave_i2c_read_data(unsigned short addr , unsigned char *buf, int size, int flags) -{ - int ret = 0; - int xfer_len = 0; - int sleep_count = 1; - DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - while (xfer_len < size) { - compat_down_interruptible(&slave_i2c_port.rx_sem); - buf[xfer_len] = ((slave_i2c_port.regs->csdr_reg & I2C_SLAVE_READ_DATA_MASK) >> I2C_SLAVE_READ_DATA_SHIFT); - DPRINTK("data = %x\n", buf[xfer_len]); - xfer_len++; - } - ret = xfer_len; - while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) { - if (compat_sema_count(&slave_i2c_port.rx_sem) > 0) {/*receive data was longer than request*/ - ret = -1; - break; - } - msleep(sleep_count); - if (sleep_count < 16) - sleep_count *= 2; - } - DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - - return ret; -} - -static int wmt_slave_i2c_write_data(unsigned short addr, unsigned char *buf, int size, int flags) -{ - int ret = 0; - int xfer_len = 0; - int sleep_count = 1; - DPRINTK("tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - while (xfer_len < size) { - compat_down_interruptible(&slave_i2c_port.tx_sem); - slave_i2c_port.regs->csdr_reg = buf[xfer_len]; - DPRINTK("data = %x\n", buf[xfer_len]); - ++xfer_len; - } - ret = xfer_len; - while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) { - msleep(sleep_count); - if (sleep_count < 16) - sleep_count *= 2; - } - DPRINTK("2.tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - return ret; -} - -static int slave_i2c_do_xfer(unsigned short addr, unsigned char *buf, int size, int flags) -{ - int ret; - if (flags & I2C_M_RD) - ret = wmt_slave_i2c_read_data(addr , buf, size, flags); - else - ret = wmt_slave_i2c_write_data(addr , buf, size, flags); - return ret; -} - -int wmt_i2cslave_transfer1(struct i2c_slave_msg slave_msg) -{ - int flags = slave_msg.flags; - unsigned char *buf = slave_msg.buf; - unsigned short addr = slave_msg.addr; - int size = slave_msg.len; - int xfer_len; - if (is_master == 1) - return 0; - spin_lock(&slave_i2c_lock); - xfer_len = slave_i2c_do_xfer(addr, buf, size, flags); - spin_unlock(&slave_i2c_lock); - return xfer_len; -} -EXPORT_SYMBOL(wmt_i2cslave_transfer1); - -void wmt_i2cslave_setaddr1(struct i2c_slave_msg msg) -{ - if (is_master == 1) - return; - spin_lock(&slave_i2c_lock); - - slave_i2c_addr = msg.addr; - - if (msg.addr & DISABLE_I2C_SLAVE) - slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE; - else { - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->scr_reg = 0; - slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE); - slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR; - - if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else - slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE); - - slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE; - } - spin_unlock(&slave_i2c_lock); -} -EXPORT_SYMBOL(wmt_i2cslave_setaddr1); - -static ssize_t slave_i2c_read( - struct file *filp, - char __user *buf, - size_t count, - loff_t *f_pos -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg; - if (is_master == 1) - return ret; - slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL); - slave_msg.flags = 0; - slave_msg.flags |= I2C_M_RD; - slave_msg.len = count; - slave_msg.addr = slave_i2c_addr; - ret = wmt_i2cslave_transfer1(slave_msg); - if (copy_to_user(buf, slave_msg.buf, count)) { - kfree(slave_msg.buf); - return -EFAULT; - } - return ret; -} - -static ssize_t slave_i2c_write( - struct file *filp, - const char __user *buf, - size_t count, - loff_t *f_pos -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg; - if (is_master == 1) - return ret; - slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL); - slave_msg.flags = 0; - slave_msg.flags &= ~I2C_M_RD; - slave_msg.len = count; - slave_msg.addr = slave_i2c_addr; - if (copy_from_user(slave_msg.buf, buf, count)) { - kfree(slave_msg.buf); - return -EFAULT; - } - ret = wmt_i2cslave_transfer1(slave_msg); - return ret; /* return Write out data size*/ -} - -static int slave_i2c_open( - struct inode *inode, - struct file *filp -) -{ - struct slave_i2c_dev_s *dev; - char name[40]; - int minor_no; - - dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev); - filp->private_data = dev; - minor_no = iminor(inode); /* get */ - - /* Create user name*/ - memset(name, 0x0, 8); - sprintf(name, "slave-i2c%d", minor_no); - return 0; -} - -static int slave_i2c_release( - struct inode *inode, - struct file *filp -) -{ - struct slave_i2c_dev_s *dev; - int minor_no; - - dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev); - minor_no = iminor(inode); - - return 0; -} - -static int slave_i2c_ioctl( - struct inode *inode, - struct file *filp, - unsigned int cmd, - unsigned long arg -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg[1]; - unsigned char *data_ptr; - unsigned char __user *usr_ptr; - switch (cmd) { - case IOCTL_DO_TRANSFER: - if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg, - sizeof(struct i2c_slave_msg))) - return -EFAULT; - - data_ptr = (unsigned char *)kmalloc(slave_msg->len*sizeof(unsigned char), GFP_KERNEL); - usr_ptr = (unsigned char __user *)slave_msg->buf; - - if (copy_from_user(data_ptr, (unsigned char *)slave_msg->buf, - slave_msg->len*sizeof(unsigned char))) { - kfree(data_ptr); - return -EFAULT; - } - slave_msg->buf = data_ptr; - - ret = wmt_i2cslave_transfer1((struct i2c_slave_msg)*slave_msg); - - if (slave_msg->flags & I2C_M_RD) { - if (copy_to_user( - usr_ptr, - data_ptr, - slave_msg->len)) - ret = -EFAULT; - } - - kfree(data_ptr); - break; - case IOCTL_SET_ADDR: - if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg, - sizeof(struct i2c_slave_msg))) - return -EFAULT; - wmt_i2cslave_setaddr1((struct i2c_slave_msg) *slave_msg); - break; - case IOCTL_QUERY_DATA: - break; - case IOCTL_SET_SPEED_MODE: - break; - default: - break; - } - return ret; -} - -/*!************************************************************************* - driver file operations struct define -****************************************************************************/ -static struct file_operations i2c_slave_fops = { - .owner = THIS_MODULE, - .open = slave_i2c_open, - .read = slave_i2c_read, - .write = slave_i2c_write, - .ioctl = slave_i2c_ioctl, - .release = slave_i2c_release, -}; - -static int slave_i2c_probe( - struct device *dev -) -{ - int ret = 0; - dev_t dev_no; - struct cdev *cdev; - char name[40]; - char buf[80]; - unsigned int port_num; - int idx = 0; - char varname1[] = "wmt.bus.i2c.slave_port"; - int ret_val = 0; - int varlen = 80; - memset(name, 0, 40); - - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - - sprintf(name, "wmt_i2cslave%d",slave_i2c_dev_minor); - cdev = &slave_i2c_dev.cdev; - cdev_init(cdev, &i2c_slave_fops); - ret = cdev_add(cdev, dev_no, 8); - slave_i2c_dev.class_slave_i2c = class_create(THIS_MODULE, "wmt_i2cslave1"); - device_create(slave_i2c_dev.class_slave_i2c, NULL , - MKDEV(slave_i2c_dev_major,slave_i2c_dev_minor), - NULL, name); - if (ret) { - printk(KERN_ALERT "*E* register char dev \n"); - return ret; - } - -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *res; - - slave_i2c_proc = proc_mkdir("driver/wmt_i2cslave1", NULL); - /* - slave_i2c_proc->owner = THIS_MODULE; - */ - res = create_proc_entry("registers", 0, slave_i2c_proc); - if (res) { - res->read_proc = slave_i2c_reg_read; - } - - res = create_proc_entry("address", 0, slave_i2c_proc); - if (res) { - res->read_proc = slave_i2c_addr_read; - } -#endif - slave_i2c_port.regs = (struct i2c_regs_s *)I2C1_BASE_ADDR; - slave_i2c_port.irq_no = IRQ_I2C1; - slave_i2c_port.i2c_mode = I2C_STANDARD_MODE; - slave_i2c_port.isr_nack = 0; - slave_i2c_port.isr_byte_end = 0; - slave_i2c_port.isr_timeout = 0; - slave_i2c_port.isr_int_pending = 0; - compat_sema_init(&slave_i2c_port.tx_sem, 0); - compat_sema_init(&slave_i2c_port.rx_sem, 0); - ret_val = wmt_getsyspara(varname1, buf, &varlen); - is_master = 1; - if (ret_val == 0) { - ret_val = sscanf(buf, "%x", &port_num); - while (ret_val) { - if (port_num != 1) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret_val; - ret_val = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; - /**/ - /* hardware initial*/ - /**/ - if (is_master == 0) { - *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT0); - *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT2 | BIT3); - *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT2 | BIT3); - *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT2 | BIT3); - - /*set i2c slave register*/ - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->scr_reg = 0; - slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE); - slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR; - - if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else - slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE); - - slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE; - - slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE; - - if (request_irq(slave_i2c_port.irq_no , &slave_i2c_isr, IRQF_DISABLED, "i2c-slave", 0) < 0) { - DPRINTK(KERN_INFO "I2C-SLAVE: Failed to register I2C-SLAVE irq %i\n", slave_i2c_port.irq_no); - return -ENODEV; - } - } - - return ret; -} - -static int slave_i2c_remove( - struct device *dev /*!<; // please add parameters description her*/ -) -{ - struct cdev *cdev; - - cdev = &slave_i2c_dev.cdev; - cdev_del(cdev); - - return 0; -} /* End of spi_remove() */ - -static void slave_i2c_backup(void) -{ - regs_backup.cr_reg = slave_i2c_port.regs->cr_reg; - regs_backup.tcr_reg = slave_i2c_port.regs->tcr_reg; - regs_backup.scr_reg = slave_i2c_port.regs->scr_reg; - regs_backup.simr_reg = slave_i2c_port.regs->simr_reg; - regs_backup.str_reg = slave_i2c_port.regs->str_reg; - -} - -static void slave_i2c_restore(void) -{ - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->cr_reg = regs_backup.cr_reg; - slave_i2c_port.regs->tcr_reg = regs_backup.tcr_reg; - slave_i2c_port.regs->scr_reg = regs_backup.scr_reg; - slave_i2c_port.regs->simr_reg = regs_backup.simr_reg; - slave_i2c_port.regs->str_reg = regs_backup.str_reg; -} - -static int slave_i2c_suspend( - struct device *dev, /*!<; // please add parameters description her*/ - pm_message_t state /*!<; // please add parameters description her*/ -) -{ - if (is_master == 1) - return 0; - slave_i2c_backup(); - compat_sema_init(&slave_i2c_port.tx_sem, 0); - compat_sema_init(&slave_i2c_port.rx_sem, 0); - return 0; -} - - -static int slave_i2c_resume( - struct device *dev -) -{ - if (is_master == 1) - return 0; - *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT0); - *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT2 | BIT3); - *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT2 | BIT3); - *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT2 | BIT3); - slave_i2c_restore(); - return 0; -} - -/*!************************************************************************* - device driver struct define -****************************************************************************/ -static struct device_driver slave_i2c_driver = { - .name = "wmt_i2c_slave_1", /* This name should equal to platform device name.*/ - .bus = &platform_bus_type, - .probe = slave_i2c_probe, - .remove = slave_i2c_remove, - .suspend = slave_i2c_suspend, - .resume = slave_i2c_resume -}; - -static void slave_i2c_platform_release( - struct device *device -) -{ -} - -/*!************************************************************************* - platform device struct define -****************************************************************************/ - -static struct platform_device slave_i2c_device = { - .name = "wmt_i2c_slave_1", - .id = 1, - .dev = { .release = slave_i2c_platform_release, - }, - .num_resources = 0, - .resource = NULL, -}; - -static int slave_i2c_init(void) -{ - int ret; - dev_t dev_no; - char dev_name[40]; - memset(dev_name, 0, 40); - sprintf(dev_name, "wmt_i2c_slave%d", slave_i2c_device.id); - - if (slave_i2c_dev_major) { - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - ret = register_chrdev_region(dev_no, slave_i2c_dev_nr, dev_name); - } else { - ret = alloc_chrdev_region(&dev_no, slave_i2c_dev_minor, slave_i2c_dev_nr, dev_name); - slave_i2c_dev_major = MAJOR(dev_no); - } - - if (ret < 0) { - printk(KERN_ALERT "*E* can't get major %d\n", slave_i2c_dev_major); - return ret; - } - - platform_device_register(&slave_i2c_device); - ret = driver_register(&slave_i2c_driver); - - return ret; -} - -module_init(slave_i2c_init); - -static void slave_i2c_exit(void) -{ - dev_t dev_no; - - driver_unregister(&slave_i2c_driver); - platform_device_unregister(&slave_i2c_device); - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - unregister_chrdev_region(dev_no, slave_i2c_dev_nr); - - return; -} - -module_exit(slave_i2c_exit); - -MODULE_AUTHOR("WMT SW Team"); -MODULE_DESCRIPTION("WMT_slave_i2c device driver"); -MODULE_LICENSE("GPL"); -#undef WMT_I2C_SLAVE_C diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.c b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.c deleted file mode 100755 index 547e5ad0..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.c +++ /dev/null @@ -1,662 +0,0 @@ -/*++ - drivers/i2c/busses/wmt-i2c-slave-bus.c - - Copyright (c) 2008 WonderMedia Technologies, Inc. - - This program is free software: you can redistribute it and/or modify it under the - terms of the GNU General Public License as published by the Free Software Foundation, - either version 2 of the License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A - PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with - this program. If not, see <http://www.gnu.org/licenses/>. - - WonderMedia Technologies, Inc. - 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. - - History: - 2010/03/11 First Version ---*/ - -#include <linux/config.h> -#define WMT_I2C_SLAVE_C - -#include <linux/init.h> -#include <linux/module.h> -#include <linux/types.h> -#include <linux/fs.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/errno.h> -#include <asm/uaccess.h> -#include <linux/kdev_t.h> -#include <linux/cdev.h> -#include <asm/semaphore.h> -#include <linux/proc_fs.h> - -#include <linux/interrupt.h> -#include <linux/spinlock.h> -#include <linux/delay.h> -#include <linux/dma-mapping.h> -#include <mach/hardware.h> -#include "./wmt-i2c-slave-bus.h" -/*#define DEBUG*/ -#ifdef DEBUG - -#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args) -#else -#define DPRINTK(fmt, args...) -#endif - - -#define DEVICE_NAME "WMT_I2C_SLAVE-0" -#define PMC_ClOCK_ENABLE_LOWER 0xd8130250 -#define CTRL_GPIO21 0xD8110055 -#define PU_EN_GPIO21 0xD8110495 -#define PU_CTRL_GPIO21 0xD81104D5 - -#define DISABLE_I2C_SLAVE BIT15 - -struct i2c_slave_msg { - __u16 addr; /* slave address */ - __u16 flags; -#define I2C_M_RD 0x01 - __u16 len; /* data length */ - __u8 *buf; /* pointer to data */ -}; - -struct slave_i2c_dev_s { - /* module parameters */ - char *buf; - - /* char dev struct */ - struct cdev cdev; - struct class *class_slave_i2c; -}; - - -struct wmt_slave_i2c_s { - struct i2c_regs_s *regs; - int irq_no ; - enum i2c_mode_e i2c_mode ; - int isr_nack ; - int isr_byte_end ; - int isr_timeout ; - int isr_int_pending ; - struct compat_semaphore tx_sem; - struct compat_semaphore rx_sem; -}; - -static struct i2c_regs_s regs_backup; -extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen); -static unsigned int is_master = 1;/*master:1, slave:0*/ - -static DEFINE_SPINLOCK(slave_i2c_lock); - -static int slave_i2c_dev_major = SLAVE_I2C_MAJOR; -static int slave_i2c_dev_minor; -static int slave_i2c_dev_nr = 1; -static struct slave_i2c_dev_s slave_i2c_dev; - -static struct wmt_slave_i2c_s slave_i2c_port; - -static unsigned char slave_i2c_addr = 0x31; - -#ifdef CONFIG_PROC_FS -static struct proc_dir_entry *slave_i2c_proc; - -static int slave_i2c_reg_read(char *buf, char **start, off_t offset, int len) -{ - char *p = buf; - p += sprintf(p, "reg : value\n"); - p += sprintf(p, "cr : 0x%.4x\n", slave_i2c_port.regs->cr_reg); - p += sprintf(p, "tcr : 0x%.4x\n", slave_i2c_port.regs->tcr_reg); - p += sprintf(p, "csr : 0x%.4x\n", slave_i2c_port.regs->csr_reg); - p += sprintf(p, "isr : 0x%.4x\n", slave_i2c_port.regs->isr_reg); - p += sprintf(p, "imr : 0x%.4x\n", slave_i2c_port.regs->imr_reg); - p += sprintf(p, "cdr : 0x%.4x\n", slave_i2c_port.regs->cdr_reg); - p += sprintf(p, "tr : 0x%.4x\n", slave_i2c_port.regs->tr_reg); - p += sprintf(p, "scr : 0x%.4x\n", slave_i2c_port.regs->scr_reg); - p += sprintf(p, "cssr : 0x%.4x\n", slave_i2c_port.regs->cssr_reg); - p += sprintf(p, "simr : 0x%.4x\n", slave_i2c_port.regs->simr_reg); - p += sprintf(p, "sisr : 0x%.4x\n", slave_i2c_port.regs->sisr_reg); - p += sprintf(p, "csdr : 0x%.4x\n", slave_i2c_port.regs->csdr_reg); - p += sprintf(p, "str : 0x%.4x\n", slave_i2c_port.regs->str_reg); - return p - buf; -} - -static int slave_i2c_addr_read(char *buf, char **start, off_t offset, int len) -{ - char *p = buf; - p += sprintf(p, "i2c-slave address : 0x%.2x\n", slave_i2c_addr); - return p - buf; -} - -#endif - -static irqreturn_t slave_i2c_isr( - int irq, /*!<; // IRQ number */ - void *dev, /*!<; // Private paramater(i.e. pointer of spi port) */ - struct pt_regs *regs /*!<; // interrupt register */ -) -{ - unsigned short isr_status = slave_i2c_port.regs->sisr_reg; - unsigned short ssr_status = slave_i2c_port.regs->cssr_reg; - DPRINTK("slave_i2c isr sisr = %x\n", isr_status); - DPRINTK("slave_i2c isr cssr = %x\n", ssr_status); - if (isr_status & I2C_SISR_DAT_REQ) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_DAT_REQ_WRITE_CLEAR; - slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK; - compat_up(&slave_i2c_port.tx_sem); - } else if (isr_status & I2C_SISR_BYTE_END) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_BYTE_END_WRITE_CLEAR; - slave_i2c_port.isr_byte_end = 1; - slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK; - compat_up(&slave_i2c_port.rx_sem); - } else if (isr_status & I2C_SISR_SCL_TIME_OUT) { - slave_i2c_port.regs->sisr_reg |= I2C_SISR_SCL_TIME_OUT_WRITE_CLEAR; - slave_i2c_port.isr_timeout = 1 ; - } - return IRQ_HANDLED; -} - -static int wmt_slave_i2c_read_data(unsigned short addr , unsigned char *buf, int size, int flags) -{ - int ret = 0; - int xfer_len = 0; - int sleep_count = 1; - DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - while (xfer_len < size) { - compat_down_interruptible(&slave_i2c_port.rx_sem); - buf[xfer_len] = ((slave_i2c_port.regs->csdr_reg & I2C_SLAVE_READ_DATA_MASK) >> I2C_SLAVE_READ_DATA_SHIFT); - DPRINTK("data = %x\n", buf[xfer_len]); - xfer_len++; - } - ret = xfer_len; - while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) { - if (compat_sema_count(&slave_i2c_port.rx_sem) > 0) {/*receive data was longer than request*/ - ret = -1; - break; - } - msleep(sleep_count); - if (sleep_count < 16) - sleep_count *= 2; - } - DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - - return ret; -} - -static int wmt_slave_i2c_write_data(unsigned short addr, unsigned char *buf, int size, int flags) -{ - int ret = 0; - int xfer_len = 0; - int sleep_count = 1; - DPRINTK("tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - while (xfer_len < size) { - compat_down_interruptible(&slave_i2c_port.tx_sem); - slave_i2c_port.regs->csdr_reg = buf[xfer_len]; - DPRINTK("data = %x\n", buf[xfer_len]); - ++xfer_len; - } - ret = xfer_len; - while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) { - msleep(sleep_count); - if (sleep_count < 16) - sleep_count *= 2; - } - DPRINTK("2.tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg); - return ret; -} - -static int slave_i2c_do_xfer(unsigned short addr, unsigned char *buf, int size, int flags) -{ - int ret; - if (flags & I2C_M_RD) - ret = wmt_slave_i2c_read_data(addr , buf, size, flags); - else - ret = wmt_slave_i2c_write_data(addr , buf, size, flags); - return ret; -} - -int wmt_i2cslave_transfer0(struct i2c_slave_msg slave_msg) -{ - int flags = slave_msg.flags; - unsigned char *buf = slave_msg.buf; - unsigned short addr = slave_msg.addr; - int size = slave_msg.len; - int xfer_len; - if (is_master == 1) - return 0; - spin_lock(&slave_i2c_lock); - xfer_len = slave_i2c_do_xfer(addr, buf, size, flags); - spin_unlock(&slave_i2c_lock); - return xfer_len; -} -EXPORT_SYMBOL(wmt_i2cslave_transfer0); - -void wmt_i2cslave_setaddr0(struct i2c_slave_msg msg) -{ - if (is_master == 1) - return; - spin_lock(&slave_i2c_lock); - - slave_i2c_addr = msg.addr; - - if (msg.addr & DISABLE_I2C_SLAVE) - slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE; - else { - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->scr_reg = 0; - slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE); - slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR; - - if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else - slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE); - - slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE; - } - spin_unlock(&slave_i2c_lock); -} -EXPORT_SYMBOL(wmt_i2cslave_setaddr0); - -static ssize_t slave_i2c_read( - struct file *filp, - char __user *buf, - size_t count, - loff_t *f_pos -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg; - if (is_master == 1) - return ret; - slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL); - slave_msg.flags = 0; - slave_msg.flags |= I2C_M_RD; - slave_msg.len = count; - slave_msg.addr = slave_i2c_addr; - ret = wmt_i2cslave_transfer0(slave_msg); - if (copy_to_user(buf, slave_msg.buf, count)) { - kfree(slave_msg.buf); - return -EFAULT; - } - return ret; -} - -static ssize_t slave_i2c_write( - struct file *filp, - const char __user *buf, - size_t count, - loff_t *f_pos -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg; - if (is_master == 1) - return ret; - slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL); - slave_msg.flags = 0; - slave_msg.flags &= ~I2C_M_RD; - slave_msg.len = count; - slave_msg.addr = slave_i2c_addr; - if (copy_from_user(slave_msg.buf, buf, count)) { - kfree(slave_msg.buf); - return -EFAULT; - } - ret = wmt_i2cslave_transfer0(slave_msg); - return ret; /* return Write out data size*/ -} - -static int slave_i2c_open( - struct inode *inode, - struct file *filp -) -{ - struct slave_i2c_dev_s *dev; - char name[40]; - int minor_no; - - dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev); - filp->private_data = dev; - minor_no = iminor(inode); /* get */ - - /* Create user name*/ - memset(name, 0x0, 8); - sprintf(name, "slave-i2c%d", minor_no); - return 0; -} - -static int slave_i2c_release( - struct inode *inode, - struct file *filp -) -{ - struct slave_i2c_dev_s *dev; - int minor_no; - - dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev); - minor_no = iminor(inode); - - return 0; -} - -static int slave_i2c_ioctl( - struct inode *inode, - struct file *filp, - unsigned int cmd, - unsigned long arg -) -{ - int ret = 0; - struct i2c_slave_msg slave_msg[1]; - unsigned char *data_ptr; - unsigned char __user *usr_ptr; - switch (cmd) { - case IOCTL_DO_TRANSFER: - if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg, - sizeof(struct i2c_slave_msg))) - return -EFAULT; - - data_ptr = (unsigned char *)kmalloc(slave_msg->len*sizeof(unsigned char), GFP_KERNEL); - usr_ptr = (unsigned char __user *)slave_msg->buf; - - if (copy_from_user(data_ptr, (unsigned char *)slave_msg->buf, - slave_msg->len*sizeof(unsigned char))) { - kfree(data_ptr); - return -EFAULT; - } - slave_msg->buf = data_ptr; - - ret = wmt_i2cslave_transfer0((struct i2c_slave_msg)*slave_msg); - - if (slave_msg->flags & I2C_M_RD) { - if (copy_to_user( - usr_ptr, - data_ptr, - slave_msg->len)) - ret = -EFAULT; - } - - kfree(data_ptr); - break; - case IOCTL_SET_ADDR: - if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg, - sizeof(struct i2c_slave_msg))) - return -EFAULT; - wmt_i2cslave_setaddr0((struct i2c_slave_msg) *slave_msg); - break; - case IOCTL_QUERY_DATA: - break; - case IOCTL_SET_SPEED_MODE: - break; - default: - break; - } - return ret; -} - -/*!************************************************************************* - driver file operations struct define -****************************************************************************/ -static struct file_operations i2c_slave_fops = { - .owner = THIS_MODULE, - .open = slave_i2c_open, - .read = slave_i2c_read, - .write = slave_i2c_write, - .ioctl = slave_i2c_ioctl, - .release = slave_i2c_release, -}; - -static int slave_i2c_probe( - struct device *dev -) -{ - int ret = 0; - dev_t dev_no; - struct cdev *cdev; - char name[40]; - char buf[80]; - unsigned int port_num; - int idx = 0; - char varname1[] = "wmt.bus.i2c.slave_port"; - int ret_val = 0; - int varlen = 80; - memset(name, 0, 40); - - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - - sprintf(name, "wmt_i2cslave%d",slave_i2c_dev_minor); - cdev = &slave_i2c_dev.cdev; - cdev_init(cdev, &i2c_slave_fops); - ret = cdev_add(cdev, dev_no, 8); - slave_i2c_dev.class_slave_i2c = class_create(THIS_MODULE, "wmt_i2cslave"); - device_create(slave_i2c_dev.class_slave_i2c, NULL , - MKDEV(slave_i2c_dev_major,slave_i2c_dev_minor), - NULL, name); - if (ret) { - printk(KERN_ALERT "*E* register char dev \n"); - return ret; - } - -#ifdef CONFIG_PROC_FS - struct proc_dir_entry *res; - - slave_i2c_proc = proc_mkdir("driver/wmt_i2cslave0", NULL); - /* - slave_i2c_proc->owner = THIS_MODULE; - */ - res = create_proc_entry("registers", 0, slave_i2c_proc); - if (res) { - res->read_proc = slave_i2c_reg_read; - } - - res = create_proc_entry("address", 0, slave_i2c_proc); - if (res) { - res->read_proc = slave_i2c_addr_read; - } -#endif - slave_i2c_port.regs = (struct i2c_regs_s *)I2C0_BASE_ADDR; - slave_i2c_port.irq_no = IRQ_I2C0; - slave_i2c_port.i2c_mode = I2C_STANDARD_MODE; - slave_i2c_port.isr_nack = 0; - slave_i2c_port.isr_byte_end = 0; - slave_i2c_port.isr_timeout = 0; - slave_i2c_port.isr_int_pending = 0; - compat_sema_init(&slave_i2c_port.tx_sem, 0); - compat_sema_init(&slave_i2c_port.rx_sem, 0); - ret_val = wmt_getsyspara(varname1, buf, &varlen); - is_master = 1; - if (ret_val == 0) { - ret_val = sscanf(buf, "%x", &port_num); - while (ret_val) { - if (port_num != 0) - is_master = 1; - else { - is_master = 0; - break; - } - idx += ret_val; - ret_val = sscanf(buf + idx, ",%x", &port_num); - } - } else - is_master = 1; - /**/ - /* hardware initial*/ - /**/ - if (is_master == 0) { - *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT5); - *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT0 | BIT1); - *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT0 | BIT1); - *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT0 | BIT1); - - /*set i2c slave register*/ - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->scr_reg = 0; - slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE); - slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR; - - if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE) - slave_i2c_port.regs->scr_reg = slave_i2c_addr; - else - slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE); - - slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE; - - slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE; - - if (request_irq(slave_i2c_port.irq_no , &slave_i2c_isr, IRQF_DISABLED, "i2c-slave", 0) < 0) { - DPRINTK(KERN_INFO "I2C-SLAVE: Failed to register I2C-SLAVE irq %i\n", slave_i2c_port.irq_no); - return -ENODEV; - } - } - - return ret; -} - -static int slave_i2c_remove( - struct device *dev /*!<; // please add parameters description her*/ -) -{ - struct cdev *cdev; - - cdev = &slave_i2c_dev.cdev; - cdev_del(cdev); - - return 0; -} /* End of spi_remove() */ - -static void slave_i2c_backup(void) -{ - regs_backup.cr_reg = slave_i2c_port.regs->cr_reg; - regs_backup.tcr_reg = slave_i2c_port.regs->tcr_reg; - regs_backup.scr_reg = slave_i2c_port.regs->scr_reg; - regs_backup.simr_reg = slave_i2c_port.regs->simr_reg; - regs_backup.str_reg = slave_i2c_port.regs->str_reg; - -} - -static void slave_i2c_restore(void) -{ - slave_i2c_port.regs->cr_reg = 0; - slave_i2c_port.regs->cr_reg = regs_backup.cr_reg; - slave_i2c_port.regs->tcr_reg = regs_backup.tcr_reg; - slave_i2c_port.regs->scr_reg = regs_backup.scr_reg; - slave_i2c_port.regs->simr_reg = regs_backup.simr_reg; - slave_i2c_port.regs->str_reg = regs_backup.str_reg; -} - -static int slave_i2c_suspend( - struct device *dev, /*!<; // please add parameters description her*/ - pm_message_t state /*!<; // please add parameters description her*/ -) -{ - if (is_master == 1) - return 0; - slave_i2c_backup(); - compat_sema_init(&slave_i2c_port.tx_sem, 0); - compat_sema_init(&slave_i2c_port.rx_sem, 0); - return 0; -} - - -static int slave_i2c_resume( - struct device *dev -) -{ - if (is_master == 1) - return 0; - *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT5); - *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT0 | BIT1); - *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT0 | BIT1); - *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT0 | BIT1); - slave_i2c_restore(); - return 0; -} - -/*!************************************************************************* - device driver struct define -****************************************************************************/ -static struct device_driver slave_i2c_driver = { - .name = "wmt_i2c_slave_0", /* This name should equal to platform device name.*/ - .bus = &platform_bus_type, - .probe = slave_i2c_probe, - .remove = slave_i2c_remove, - .suspend = slave_i2c_suspend, - .resume = slave_i2c_resume -}; - -static void slave_i2c_platform_release( - struct device *device -) -{ -} - -/*!************************************************************************* - platform device struct define -****************************************************************************/ - -static struct platform_device slave_i2c_device = { - .name = "wmt_i2c_slave_0", - .id = 0, - .dev = { .release = slave_i2c_platform_release, - }, - .num_resources = 0, - .resource = NULL, -}; - -static int slave_i2c_init(void) -{ - int ret; - dev_t dev_no; - char dev_name[40]; - memset(dev_name, 0, 40); - sprintf(dev_name, "wmt_i2c_slave%d", slave_i2c_device.id); - - if (slave_i2c_dev_major) { - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - ret = register_chrdev_region(dev_no, slave_i2c_dev_nr, dev_name); - } else { - ret = alloc_chrdev_region(&dev_no, slave_i2c_dev_minor, slave_i2c_dev_nr, dev_name); - slave_i2c_dev_major = MAJOR(dev_no); - } - - if (ret < 0) { - printk(KERN_ALERT "*E* can't get major %d\n", slave_i2c_dev_major); - return ret; - } - - platform_device_register(&slave_i2c_device); - ret = driver_register(&slave_i2c_driver); - - return ret; -} - -module_init(slave_i2c_init); - -static void slave_i2c_exit(void) -{ - dev_t dev_no; - - driver_unregister(&slave_i2c_driver); - platform_device_unregister(&slave_i2c_device); - dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor); - unregister_chrdev_region(dev_no, slave_i2c_dev_nr); - - return; -} - -module_exit(slave_i2c_exit); - -MODULE_AUTHOR("WMT SW Team"); -MODULE_DESCRIPTION("WMT_slave_i2c device driver"); -MODULE_LICENSE("GPL"); -#undef WMT_I2C_SLAVE_C diff --git a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.h b/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.h deleted file mode 100755 index 485823db..00000000 --- a/ANDROID_3.4.5/drivers/i2c/busses/wmt-i2c-slave-bus.h +++ /dev/null @@ -1,24 +0,0 @@ -/*++ -Copyright (c) 2010 WonderMedia Technologies, Inc. - -This program is free software: you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation, either version 2 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. You -should have received a copy of the GNU General Public License along with this -program. If not, see http://www.gnu.org/licenses/>. - -WonderMedia Technologies, Inc. -10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C. ---*/ - -#define SLAVE_I2C_MAJOR 191 - -#define IOCTL_DO_TRANSFER 0xBF01 -#define IOCTL_SET_ADDR 0xBF02 -#define IOCTL_QUERY_DATA 0xBF03 -#define IOCTL_SET_SPEED_MODE 0xBF04 diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-api.c b/ANDROID_3.4.5/drivers/i2c/i2c-api.c deleted file mode 100755 index d01335bb..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-api.c +++ /dev/null @@ -1,216 +0,0 @@ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/errno.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/i2c.h> -#include <linux/slab.h> - -#define I2C_API_FAKE_ADDR 0x7f -#define I2C_MINORS 256 - -struct i2c_api { - struct list_head list; - struct i2c_client *client; -}; - -static LIST_HEAD(i2c_api_list); -static DEFINE_SPINLOCK(i2c_api_list_lock); - -static struct i2c_api *get_i2c_api(int bus_id) -{ - struct i2c_api *i2c_api; - - spin_lock(&i2c_api_list_lock); - list_for_each_entry(i2c_api, &i2c_api_list, list) { - if (i2c_api->client->adapter->nr == bus_id) - goto found; - } - i2c_api = NULL; - -found: - spin_unlock(&i2c_api_list_lock); - return i2c_api; -} - -static struct i2c_api *add_i2c_api(struct i2c_client *client) -{ - struct i2c_api *i2c_api; - - if (client->adapter->nr >= I2C_MINORS) { - printk(KERN_ERR "i2c_api: Out of device minors (%d)\n", - client->adapter->nr); - return NULL; - } - - i2c_api = kzalloc(sizeof(*i2c_api), GFP_KERNEL); - if (!i2c_api) - return NULL; - i2c_api->client = client; - - spin_lock(&i2c_api_list_lock); - list_add_tail(&i2c_api->list, &i2c_api_list); - spin_unlock(&i2c_api_list_lock); - return i2c_api; -} - -static void del_i2c_api(struct i2c_api *i2c_api) -{ - spin_lock(&i2c_api_list_lock); - list_del(&i2c_api->list); - spin_unlock(&i2c_api_list_lock); - kfree(i2c_api); -} - -static int i2c_api_do_xfer(int bus_id, char chip_addr, char sub_addr, int mode, - char *buf, unsigned int size) -{ -/** you could define more transfer mode here, implement it following. */ -#define I2C_API_XFER_MODE_SEND 0x0 /* standard send */ -#define I2C_API_XFER_MODE_RECV 0x1 /* standard receive */ -#define I2C_API_XFER_MODE_SEND_NO_SUBADDR 0x2 /* send without sub-address */ -#define I2C_API_XFER_MODE_RECV_NO_SUBADDR 0x3 /* receive without sub-address */ - - int ret = 0; - char *tmp; - struct i2c_api *i2c_api = get_i2c_api(bus_id); - - if (!i2c_api) - return -ENODEV; - - i2c_api->client->addr = chip_addr; - switch (mode) { - case I2C_API_XFER_MODE_SEND: - tmp = kmalloc(size + 1,GFP_KERNEL); - if (tmp == NULL) - return -ENOMEM; - tmp[0] = sub_addr; - memcpy(&tmp[1], buf, size); - ret = i2c_master_send(i2c_api->client, tmp, size + 1); - ret = (ret == size + 1) ? size : ret; - kfree(tmp); - break; - - case I2C_API_XFER_MODE_RECV: - ret = i2c_master_send(i2c_api->client, &sub_addr, 1); - if (ret < 0) - return ret; - ret = i2c_master_recv(i2c_api->client, buf, size); - break; - - case I2C_API_XFER_MODE_SEND_NO_SUBADDR: - ret = i2c_master_send(i2c_api->client, buf, size); - break; - - case I2C_API_XFER_MODE_RECV_NO_SUBADDR: - ret = i2c_master_recv(i2c_api->client, buf, size); - break; - - default: - return -EINVAL; - } - return ret; -} - -int i2c_api_do_send(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size) -{ - return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_SEND, buf, size); -} - -int i2c_api_do_recv(int bus_id, char chip_addr, char sub_addr, char *buf, unsigned int size) -{ - return i2c_api_do_xfer(bus_id, chip_addr, sub_addr, I2C_API_XFER_MODE_RECV, buf, size); -} - -int i2c_api_do_send_without_subaddr(int bus_id, char chip_addr, char *buf, unsigned int size) -{ - return i2c_api_do_xfer(bus_id, chip_addr, 0, I2C_API_XFER_MODE_SEND_NO_SUBADDR, buf, size); -} - -int i2c_api_do_recv_without_subaddr(int bus_id, char chip_addr, char *buf, unsigned int size) -{ - return i2c_api_do_xfer(bus_id, chip_addr, 0, I2C_API_XFER_MODE_RECV_NO_SUBADDR, buf, size); -} - -int i2c_api_attach(struct i2c_adapter *adap) -{ - struct i2c_board_info info; - struct i2c_client *client; - - memset(&info, 0, sizeof(struct i2c_board_info)); - strlcpy(info.type, "i2c_api", I2C_NAME_SIZE); - info.addr = I2C_API_FAKE_ADDR; - client = i2c_new_device(adap, &info); - if (client) - add_i2c_api(client); - printk(KERN_INFO "i2c_api_attach adap[%d]\n", adap->nr); - return 0; -} - -int i2c_api_detach(struct i2c_adapter *adap) -{ - struct i2c_api *i2c_api; - - i2c_api = get_i2c_api(adap->nr); - if (i2c_api) - del_i2c_api(i2c_api); - return 0; -} - -static const unsigned short normal_addr[] = { I2C_API_FAKE_ADDR, I2C_CLIENT_END }; -static const unsigned short ignore[] = { I2C_CLIENT_END }; -/*static struct i2c_client_address_data addr_data = -{ - .normal_i2c = normal_addr, - .probe = ignore, - .ignore = ignore, - .forces = NULL, -};*/ - -static const struct i2c_device_id id[] = { - {"I2C-API", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, id); - -static struct i2c_driver i2c_api_driver = { - .id_table = id, - .attach_adapter = i2c_api_attach, - .detach_adapter = i2c_api_detach, - .command = NULL, - .driver = { - .name = "I2C-API", - .owner = THIS_MODULE, - }, - //.address_data = &addr_data, -}; - -static int __init i2c_api_init(void) -{ - int ret = i2c_add_driver(&i2c_api_driver); - - if (ret) { - printk(KERN_ERR "[%s] Driver registration failed, module not inserted.\n", __func__); - return ret; - } - - return 0 ; -} - -static void __exit i2c_api_exit(void) -{ - i2c_del_driver(&i2c_api_driver); -} - -MODULE_AUTHOR("Loon, <Loonzhong@wondermedia.com.cn>"); -MODULE_DESCRIPTION("I2C i2c_api Driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_api_init); -module_exit(i2c_api_exit); - -EXPORT_SYMBOL_GPL(i2c_api_do_send); -EXPORT_SYMBOL_GPL(i2c_api_do_recv); -EXPORT_SYMBOL_GPL(i2c_api_do_send_without_subaddr); -EXPORT_SYMBOL_GPL(i2c_api_do_recv_without_subaddr); diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-boardinfo.c b/ANDROID_3.4.5/drivers/i2c/i2c-boardinfo.c deleted file mode 100644 index f24cc64e..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-boardinfo.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * i2c-boardinfo.c - collect pre-declarations of I2C devices - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA. - */ - -#include <linux/kernel.h> -#include <linux/i2c.h> -#include <linux/slab.h> -#include <linux/export.h> -#include <linux/rwsem.h> - -#include "i2c-core.h" - - -/* These symbols are exported ONLY FOR the i2c core. - * No other users will be supported. - */ -DECLARE_RWSEM(__i2c_board_lock); -EXPORT_SYMBOL_GPL(__i2c_board_lock); - -LIST_HEAD(__i2c_board_list); -EXPORT_SYMBOL_GPL(__i2c_board_list); - -int __i2c_first_dynamic_bus_num; -EXPORT_SYMBOL_GPL(__i2c_first_dynamic_bus_num); - - -/** - * i2c_register_board_info - statically declare I2C devices - * @busnum: identifies the bus to which these devices belong - * @info: vector of i2c device descriptors - * @len: how many descriptors in the vector; may be zero to reserve - * the specified bus number. - * - * Systems using the Linux I2C driver stack can declare tables of board info - * while they initialize. This should be done in board-specific init code - * near arch_initcall() time, or equivalent, before any I2C adapter driver is - * registered. For example, mainboard init code could define several devices, - * as could the init code for each daughtercard in a board stack. - * - * The I2C devices will be created later, after the adapter for the relevant - * bus has been registered. After that moment, standard driver model tools - * are used to bind "new style" I2C drivers to the devices. The bus number - * for any device declared using this routine is not available for dynamic - * allocation. - * - * The board info passed can safely be __initdata, but be careful of embedded - * pointers (for platform_data, functions, etc) since that won't be copied. - */ -int __init -i2c_register_board_info(int busnum, - struct i2c_board_info const *info, unsigned len) -{ - int status; - - down_write(&__i2c_board_lock); - - /* dynamic bus numbers will be assigned after the last static one */ - if (busnum >= __i2c_first_dynamic_bus_num) - __i2c_first_dynamic_bus_num = busnum + 1; - - for (status = 0; len; len--, info++) { - struct i2c_devinfo *devinfo; - - devinfo = kzalloc(sizeof(*devinfo), GFP_KERNEL); - if (!devinfo) { - pr_debug("i2c-core: can't register boardinfo!\n"); - status = -ENOMEM; - break; - } - - devinfo->busnum = busnum; - devinfo->board_info = *info; - list_add_tail(&devinfo->list, &__i2c_board_list); - } - - up_write(&__i2c_board_lock); - - return status; -} diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-core.c b/ANDROID_3.4.5/drivers/i2c/i2c-core.c deleted file mode 100644 index feb7dc35..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-core.c +++ /dev/null @@ -1,2136 +0,0 @@ -/* i2c-core.c - a device driver for the iic-bus interface */ -/* ------------------------------------------------------------------------- */ -/* Copyright (C) 1995-99 Simon G. Vogl - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA. */ -/* ------------------------------------------------------------------------- */ - -/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi>. - All SMBus-related things are written by Frodo Looijaard <frodol@dds.nl> - SMBus 2.0 support by Mark Studebaker <mdsxyz123@yahoo.com> and - Jean Delvare <khali@linux-fr.org> - Mux support by Rodolfo Giometti <giometti@enneenne.com> and - Michael Lawnick <michael.lawnick.ext@nsn.com> */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/init.h> -#include <linux/idr.h> -#include <linux/mutex.h> -#include <linux/of_device.h> -#include <linux/completion.h> -#include <linux/hardirq.h> -#include <linux/irqflags.h> -#include <linux/rwsem.h> -#include <linux/pm_runtime.h> -#include <asm/uaccess.h> - -#include "i2c-core.h" - - -/* core_lock protects i2c_adapter_idr, and guarantees - that device detection, deletion of detected devices, and attach_adapter - and detach_adapter calls are serialized */ -static DEFINE_MUTEX(core_lock); -static DEFINE_IDR(i2c_adapter_idr); - -static struct device_type i2c_client_type; -static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); - -/* ------------------------------------------------------------------------- */ - -static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, - const struct i2c_client *client) -{ - while (id->name[0]) { - if (strcmp(client->name, id->name) == 0) - return id; - id++; - } - return NULL; -} - -static int i2c_device_match(struct device *dev, struct device_driver *drv) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - - if (!client) - return 0; - - /* Attempt an OF style match */ - if (of_driver_match_device(dev, drv)) - return 1; - - driver = to_i2c_driver(drv); - /* match on an id table if there is one */ - if (driver->id_table) - return i2c_match_id(driver->id_table, client) != NULL; - - return 0; -} - -#ifdef CONFIG_HOTPLUG - -/* uevent helps with hotplug: modprobe -q $(MODALIAS) */ -static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) -{ - struct i2c_client *client = to_i2c_client(dev); - - if (add_uevent_var(env, "MODALIAS=%s%s", - I2C_MODULE_PREFIX, client->name)) - return -ENOMEM; - dev_dbg(dev, "uevent\n"); - return 0; -} - -#else -#define i2c_device_uevent NULL -#endif /* CONFIG_HOTPLUG */ - -static int i2c_device_probe(struct device *dev) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - int status; - - if (!client) - return 0; - - driver = to_i2c_driver(dev->driver); - if (!driver->probe || !driver->id_table) - return -ENODEV; - client->driver = driver; - if (!device_can_wakeup(&client->dev)) - device_init_wakeup(&client->dev, - client->flags & I2C_CLIENT_WAKE); - dev_dbg(dev, "probe\n"); - - status = driver->probe(client, i2c_match_id(driver->id_table, client)); - if (status) { - client->driver = NULL; - i2c_set_clientdata(client, NULL); - } - return status; -} - -static int i2c_device_remove(struct device *dev) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - int status; - - if (!client || !dev->driver) - return 0; - - driver = to_i2c_driver(dev->driver); - if (driver->remove) { - dev_dbg(dev, "remove\n"); - status = driver->remove(client); - } else { - dev->driver = NULL; - status = 0; - } - if (status == 0) { - client->driver = NULL; - i2c_set_clientdata(client, NULL); - } - return status; -} - -static void i2c_device_shutdown(struct device *dev) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - - if (!client || !dev->driver) - return; - driver = to_i2c_driver(dev->driver); - if (driver->shutdown) - driver->shutdown(client); -} - -#ifdef CONFIG_PM_SLEEP -static int i2c_legacy_suspend(struct device *dev, pm_message_t mesg) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - - if (!client || !dev->driver) - return 0; - driver = to_i2c_driver(dev->driver); - if (!driver->suspend) - return 0; - return driver->suspend(client, mesg); -} - -static int i2c_legacy_resume(struct device *dev) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - - if (!client || !dev->driver) - return 0; - driver = to_i2c_driver(dev->driver); - if (!driver->resume) - return 0; - return driver->resume(client); -} - -static int i2c_device_pm_suspend(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_suspend(dev); - else - return i2c_legacy_suspend(dev, PMSG_SUSPEND); -} - -static int i2c_device_pm_resume(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_resume(dev); - else - return i2c_legacy_resume(dev); -} - -static int i2c_device_pm_freeze(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_freeze(dev); - else - return i2c_legacy_suspend(dev, PMSG_FREEZE); -} - -static int i2c_device_pm_thaw(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_thaw(dev); - else - return i2c_legacy_resume(dev); -} - -static int i2c_device_pm_poweroff(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_poweroff(dev); - else - return i2c_legacy_suspend(dev, PMSG_HIBERNATE); -} - -static int i2c_device_pm_restore(struct device *dev) -{ - const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL; - - if (pm) - return pm_generic_restore(dev); - else - return i2c_legacy_resume(dev); -} -#else /* !CONFIG_PM_SLEEP */ -#define i2c_device_pm_suspend NULL -#define i2c_device_pm_resume NULL -#define i2c_device_pm_freeze NULL -#define i2c_device_pm_thaw NULL -#define i2c_device_pm_poweroff NULL -#define i2c_device_pm_restore NULL -#endif /* !CONFIG_PM_SLEEP */ - -static void i2c_client_dev_release(struct device *dev) -{ - kfree(to_i2c_client(dev)); -} - -static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? - to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); -} - -static ssize_t -show_modalias(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); -} - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); - -static struct attribute *i2c_dev_attrs[] = { - &dev_attr_name.attr, - /* modalias helps coldplug: modprobe $(cat .../modalias) */ - &dev_attr_modalias.attr, - NULL -}; - -static struct attribute_group i2c_dev_attr_group = { - .attrs = i2c_dev_attrs, -}; - -static const struct attribute_group *i2c_dev_attr_groups[] = { - &i2c_dev_attr_group, - NULL -}; - -static const struct dev_pm_ops i2c_device_pm_ops = { - .suspend = i2c_device_pm_suspend, - .resume = i2c_device_pm_resume, - .freeze = i2c_device_pm_freeze, - .thaw = i2c_device_pm_thaw, - .poweroff = i2c_device_pm_poweroff, - .restore = i2c_device_pm_restore, - SET_RUNTIME_PM_OPS( - pm_generic_runtime_suspend, - pm_generic_runtime_resume, - pm_generic_runtime_idle - ) -}; - -struct bus_type i2c_bus_type = { - .name = "i2c", - .match = i2c_device_match, - .probe = i2c_device_probe, - .remove = i2c_device_remove, - .shutdown = i2c_device_shutdown, - .pm = &i2c_device_pm_ops, -}; -EXPORT_SYMBOL_GPL(i2c_bus_type); - -static struct device_type i2c_client_type = { - .groups = i2c_dev_attr_groups, - .uevent = i2c_device_uevent, - .release = i2c_client_dev_release, -}; - - -/** - * i2c_verify_client - return parameter as i2c_client, or NULL - * @dev: device, probably from some driver model iterator - * - * When traversing the driver model tree, perhaps using driver model - * iterators like @device_for_each_child(), you can't assume very much - * about the nodes you find. Use this function to avoid oopses caused - * by wrongly treating some non-I2C device as an i2c_client. - */ -struct i2c_client *i2c_verify_client(struct device *dev) -{ - return (dev->type == &i2c_client_type) - ? to_i2c_client(dev) - : NULL; -} -EXPORT_SYMBOL(i2c_verify_client); - - -/* This is a permissive address validity check, I2C address map constraints - * are purposely not enforced, except for the general call address. */ -static int i2c_check_client_addr_validity(const struct i2c_client *client) -{ - if (client->flags & I2C_CLIENT_TEN) { - /* 10-bit address, all values are valid */ - if (client->addr > 0x3ff) - return -EINVAL; - } else { - /* 7-bit address, reject the general call address */ - if (client->addr == 0x00 || client->addr > 0x7f) - return -EINVAL; - } - return 0; -} - -/* And this is a strict address validity check, used when probing. If a - * device uses a reserved address, then it shouldn't be probed. 7-bit - * addressing is assumed, 10-bit address devices are rare and should be - * explicitly enumerated. */ -static int i2c_check_addr_validity(unsigned short addr) -{ - /* - * Reserved addresses per I2C specification: - * 0x00 General call address / START byte - * 0x01 CBUS address - * 0x02 Reserved for different bus format - * 0x03 Reserved for future purposes - * 0x04-0x07 Hs-mode master code - * 0x78-0x7b 10-bit slave addressing - * 0x7c-0x7f Reserved for future purposes - */ - if (addr < 0x08 || addr > 0x77) - return -EINVAL; - return 0; -} - -static int __i2c_check_addr_busy(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - int addr = *(int *)addrp; - - if (client && client->addr == addr) - return -EBUSY; - return 0; -} - -/* walk up mux tree */ -static int i2c_check_mux_parents(struct i2c_adapter *adapter, int addr) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - int result; - - result = device_for_each_child(&adapter->dev, &addr, - __i2c_check_addr_busy); - - if (!result && parent) - result = i2c_check_mux_parents(parent, addr); - - return result; -} - -/* recurse down mux tree */ -static int i2c_check_mux_children(struct device *dev, void *addrp) -{ - int result; - - if (dev->type == &i2c_adapter_type) - result = device_for_each_child(dev, addrp, - i2c_check_mux_children); - else - result = __i2c_check_addr_busy(dev, addrp); - - return result; -} - -static int i2c_check_addr_busy(struct i2c_adapter *adapter, int addr) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - int result = 0; - - if (parent) - result = i2c_check_mux_parents(parent, addr); - - if (!result) - result = device_for_each_child(&adapter->dev, &addr, - i2c_check_mux_children); - - return result; -} - -/** - * i2c_lock_adapter - Get exclusive access to an I2C bus segment - * @adapter: Target I2C bus segment - */ -void i2c_lock_adapter(struct i2c_adapter *adapter) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - i2c_lock_adapter(parent); - else - rt_mutex_lock(&adapter->bus_lock); -} -EXPORT_SYMBOL_GPL(i2c_lock_adapter); - -/** - * i2c_trylock_adapter - Try to get exclusive access to an I2C bus segment - * @adapter: Target I2C bus segment - */ -static int i2c_trylock_adapter(struct i2c_adapter *adapter) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - return i2c_trylock_adapter(parent); - else - return rt_mutex_trylock(&adapter->bus_lock); -} - -/** - * i2c_unlock_adapter - Release exclusive access to an I2C bus segment - * @adapter: Target I2C bus segment - */ -void i2c_unlock_adapter(struct i2c_adapter *adapter) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - - if (parent) - i2c_unlock_adapter(parent); - else - rt_mutex_unlock(&adapter->bus_lock); -} -EXPORT_SYMBOL_GPL(i2c_unlock_adapter); - -/** - * i2c_new_device - instantiate an i2c device - * @adap: the adapter managing the device - * @info: describes one I2C device; bus_num is ignored - * Context: can sleep - * - * Create an i2c device. Binding is handled through driver model - * probe()/remove() methods. A driver may be bound to this device when we - * return from this function, or any later moment (e.g. maybe hotplugging will - * load the driver module). This call is not appropriate for use by mainboard - * initialization logic, which usually runs during an arch_initcall() long - * before any i2c_adapter could exist. - * - * This returns the new i2c client, which may be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. - */ -struct i2c_client * -i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) -{ - struct i2c_client *client; - int status; - - client = kzalloc(sizeof *client, GFP_KERNEL); - if (!client) - return NULL; - - client->adapter = adap; - - client->dev.platform_data = info->platform_data; - - if (info->archdata) - client->dev.archdata = *info->archdata; - - client->flags = info->flags; - client->addr = info->addr; - client->irq = info->irq; - - strlcpy(client->name, info->type, sizeof(client->name)); - - /* Check for address validity */ - status = i2c_check_client_addr_validity(client); - if (status) { - dev_err(&adap->dev, "Invalid %d-bit I2C address 0x%02hx\n", - client->flags & I2C_CLIENT_TEN ? 10 : 7, client->addr); - goto out_err_silent; - } - - /* Check for address business */ - status = i2c_check_addr_busy(adap, client->addr); - if (status) - goto out_err; - - client->dev.parent = &client->adapter->dev; - client->dev.bus = &i2c_bus_type; - client->dev.type = &i2c_client_type; - client->dev.of_node = info->of_node; - - /* For 10-bit clients, add an arbitrary offset to avoid collisions */ - dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), - client->addr | ((client->flags & I2C_CLIENT_TEN) - ? 0xa000 : 0)); - status = device_register(&client->dev); - if (status) - goto out_err; - - dev_dbg(&adap->dev, "client [%s] registered with bus id %s\n", - client->name, dev_name(&client->dev)); - - return client; - -out_err: - dev_err(&adap->dev, "Failed to register i2c client %s at 0x%02x " - "(%d)\n", client->name, client->addr, status); -out_err_silent: - kfree(client); - return NULL; -} -EXPORT_SYMBOL_GPL(i2c_new_device); - - -/** - * i2c_unregister_device - reverse effect of i2c_new_device() - * @client: value returned from i2c_new_device() - * Context: can sleep - */ -void i2c_unregister_device(struct i2c_client *client) -{ - device_unregister(&client->dev); -} -EXPORT_SYMBOL_GPL(i2c_unregister_device); - - -static const struct i2c_device_id dummy_id[] = { - { "dummy", 0 }, - { }, -}; - -static int dummy_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return 0; -} - -static int dummy_remove(struct i2c_client *client) -{ - return 0; -} - -static struct i2c_driver dummy_driver = { - .driver.name = "dummy", - .probe = dummy_probe, - .remove = dummy_remove, - .id_table = dummy_id, -}; - -/** - * i2c_new_dummy - return a new i2c device bound to a dummy driver - * @adapter: the adapter managing the device - * @address: seven bit address to be used - * Context: can sleep - * - * This returns an I2C client bound to the "dummy" driver, intended for use - * with devices that consume multiple addresses. Examples of such chips - * include various EEPROMS (like 24c04 and 24c08 models). - * - * These dummy devices have two main uses. First, most I2C and SMBus calls - * except i2c_transfer() need a client handle; the dummy will be that handle. - * And second, this prevents the specified address from being bound to a - * different driver. - * - * This returns the new i2c client, which should be saved for later use with - * i2c_unregister_device(); or NULL to indicate an error. - */ -struct i2c_client *i2c_new_dummy(struct i2c_adapter *adapter, u16 address) -{ - struct i2c_board_info info = { - I2C_BOARD_INFO("dummy", address), - }; - - return i2c_new_device(adapter, &info); -} -EXPORT_SYMBOL_GPL(i2c_new_dummy); - -/* ------------------------------------------------------------------------- */ - -/* I2C bus adapters -- one roots each I2C or SMBUS segment */ - -static void i2c_adapter_dev_release(struct device *dev) -{ - struct i2c_adapter *adap = to_i2c_adapter(dev); - complete(&adap->dev_released); -} - -/* - * Let users instantiate I2C devices through sysfs. This can be used when - * platform initialization code doesn't contain the proper data for - * whatever reason. Also useful for drivers that do device detection and - * detection fails, either because the device uses an unexpected address, - * or this is a compatible device with different ID register values. - * - * Parameter checking may look overzealous, but we really don't want - * the user to provide incorrect parameters. - */ -static ssize_t -i2c_sysfs_new_device(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_adapter *adap = to_i2c_adapter(dev); - struct i2c_board_info info; - struct i2c_client *client; - char *blank, end; - int res; - - memset(&info, 0, sizeof(struct i2c_board_info)); - - blank = strchr(buf, ' '); - if (!blank) { - dev_err(dev, "%s: Missing parameters\n", "new_device"); - return -EINVAL; - } - if (blank - buf > I2C_NAME_SIZE - 1) { - dev_err(dev, "%s: Invalid device name\n", "new_device"); - return -EINVAL; - } - memcpy(info.type, buf, blank - buf); - - /* Parse remaining parameters, reject extra parameters */ - res = sscanf(++blank, "%hi%c", &info.addr, &end); - if (res < 1) { - dev_err(dev, "%s: Can't parse I2C address\n", "new_device"); - return -EINVAL; - } - if (res > 1 && end != '\n') { - dev_err(dev, "%s: Extra parameters\n", "new_device"); - return -EINVAL; - } - - client = i2c_new_device(adap, &info); - if (!client) - return -EINVAL; - - /* Keep track of the added device */ - mutex_lock(&adap->userspace_clients_lock); - list_add_tail(&client->detected, &adap->userspace_clients); - mutex_unlock(&adap->userspace_clients_lock); - dev_info(dev, "%s: Instantiated device %s at 0x%02hx\n", "new_device", - info.type, info.addr); - - return count; -} - -/* - * And of course let the users delete the devices they instantiated, if - * they got it wrong. This interface can only be used to delete devices - * instantiated by i2c_sysfs_new_device above. This guarantees that we - * don't delete devices to which some kernel code still has references. - * - * Parameter checking may look overzealous, but we really don't want - * the user to delete the wrong device. - */ -static ssize_t -i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_adapter *adap = to_i2c_adapter(dev); - struct i2c_client *client, *next; - unsigned short addr; - char end; - int res; - - /* Parse parameters, reject extra parameters */ - res = sscanf(buf, "%hi%c", &addr, &end); - if (res < 1) { - dev_err(dev, "%s: Can't parse I2C address\n", "delete_device"); - return -EINVAL; - } - if (res > 1 && end != '\n') { - dev_err(dev, "%s: Extra parameters\n", "delete_device"); - return -EINVAL; - } - - /* Make sure the device was added through sysfs */ - res = -ENOENT; - mutex_lock(&adap->userspace_clients_lock); - list_for_each_entry_safe(client, next, &adap->userspace_clients, - detected) { - if (client->addr == addr) { - dev_info(dev, "%s: Deleting device %s at 0x%02hx\n", - "delete_device", client->name, client->addr); - - list_del(&client->detected); - i2c_unregister_device(client); - res = count; - break; - } - } - mutex_unlock(&adap->userspace_clients_lock); - - if (res < 0) - dev_err(dev, "%s: Can't find device in list\n", - "delete_device"); - return res; -} - -static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); -static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device); - -static struct attribute *i2c_adapter_attrs[] = { - &dev_attr_name.attr, - &dev_attr_new_device.attr, - &dev_attr_delete_device.attr, - NULL -}; - -static struct attribute_group i2c_adapter_attr_group = { - .attrs = i2c_adapter_attrs, -}; - -static const struct attribute_group *i2c_adapter_attr_groups[] = { - &i2c_adapter_attr_group, - NULL -}; - -struct device_type i2c_adapter_type = { - .groups = i2c_adapter_attr_groups, - .release = i2c_adapter_dev_release, -}; -EXPORT_SYMBOL_GPL(i2c_adapter_type); - -#ifdef CONFIG_I2C_COMPAT -static struct class_compat *i2c_adapter_compat_class; -#endif - -static void i2c_scan_static_board_info(struct i2c_adapter *adapter) -{ - struct i2c_devinfo *devinfo; - - down_read(&__i2c_board_lock); - list_for_each_entry(devinfo, &__i2c_board_list, list) { - if (devinfo->busnum == adapter->nr - && !i2c_new_device(adapter, - &devinfo->board_info)) - dev_err(&adapter->dev, - "Can't create device at 0x%02x\n", - devinfo->board_info.addr); - } - up_read(&__i2c_board_lock); -} - -static int i2c_do_add_adapter(struct i2c_driver *driver, - struct i2c_adapter *adap) -{ - /* Detect supported devices on that bus, and instantiate them */ - i2c_detect(adap, driver); - - /* Let legacy drivers scan this bus for matching devices */ - if (driver->attach_adapter) { - dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n", - driver->driver.name); - dev_warn(&adap->dev, "Please use another way to instantiate " - "your i2c_client\n"); - /* We ignore the return code; if it fails, too bad */ - driver->attach_adapter(adap); - } - return 0; -} - -static int __process_new_adapter(struct device_driver *d, void *data) -{ - return i2c_do_add_adapter(to_i2c_driver(d), data); -} - -static int i2c_register_adapter(struct i2c_adapter *adap) -{ - int res = 0; - - /* Can't register until after driver model init */ - if (unlikely(WARN_ON(!i2c_bus_type.p))) { - res = -EAGAIN; - goto out_list; - } - - /* Sanity checks */ - if (unlikely(adap->name[0] == '\0')) { - pr_err("i2c-core: Attempt to register an adapter with " - "no name!\n"); - return -EINVAL; - } - if (unlikely(!adap->algo)) { - pr_err("i2c-core: Attempt to register adapter '%s' with " - "no algo!\n", adap->name); - return -EINVAL; - } - - rt_mutex_init(&adap->bus_lock); - mutex_init(&adap->userspace_clients_lock); - INIT_LIST_HEAD(&adap->userspace_clients); - - /* Set default timeout to 1 second if not already set */ - if (adap->timeout == 0) - adap->timeout = HZ; - - dev_set_name(&adap->dev, "i2c-%d", adap->nr); - adap->dev.bus = &i2c_bus_type; - adap->dev.type = &i2c_adapter_type; - res = device_register(&adap->dev); - if (res) - goto out_list; - - dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); - -#ifdef CONFIG_I2C_COMPAT - res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, - adap->dev.parent); - if (res) - dev_warn(&adap->dev, - "Failed to create compatibility class link\n"); -#endif - - /* create pre-declared device nodes */ - if (adap->nr < __i2c_first_dynamic_bus_num) - i2c_scan_static_board_info(adap); - - /* Notify drivers */ - mutex_lock(&core_lock); - bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); - mutex_unlock(&core_lock); - - return 0; - -out_list: - mutex_lock(&core_lock); - idr_remove(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - return res; -} - -/** - * i2c_add_adapter - declare i2c adapter, use dynamic bus number - * @adapter: the adapter to add - * Context: can sleep - * - * This routine is used to declare an I2C adapter when its bus number - * doesn't matter. Examples: for I2C adapters dynamically added by - * USB links or PCI plugin cards. - * - * When this returns zero, a new bus number was allocated and stored - * in adap->nr, and the specified adapter became available for clients. - * Otherwise, a negative errno value is returned. - */ -int i2c_add_adapter(struct i2c_adapter *adapter) -{ - int id, res = 0; - -retry: - if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) - return -ENOMEM; - - mutex_lock(&core_lock); - /* "above" here means "above or equal to", sigh */ - res = idr_get_new_above(&i2c_adapter_idr, adapter, - __i2c_first_dynamic_bus_num, &id); - mutex_unlock(&core_lock); - - if (res < 0) { - if (res == -EAGAIN) - goto retry; - return res; - } - - adapter->nr = id; - return i2c_register_adapter(adapter); -} -EXPORT_SYMBOL(i2c_add_adapter); - -/** - * i2c_add_numbered_adapter - declare i2c adapter, use static bus number - * @adap: the adapter to register (with adap->nr initialized) - * Context: can sleep - * - * This routine is used to declare an I2C adapter when its bus number - * matters. For example, use it for I2C adapters from system-on-chip CPUs, - * or otherwise built in to the system's mainboard, and where i2c_board_info - * is used to properly configure I2C devices. - * - * If the requested bus number is set to -1, then this function will behave - * identically to i2c_add_adapter, and will dynamically assign a bus number. - * - * If no devices have pre-been declared for this bus, then be sure to - * register the adapter before any dynamically allocated ones. Otherwise - * the required bus ID may not be available. - * - * When this returns zero, the specified adapter became available for - * clients using the bus number provided in adap->nr. Also, the table - * of I2C devices pre-declared using i2c_register_board_info() is scanned, - * and the appropriate driver model device nodes are created. Otherwise, a - * negative errno value is returned. - */ -int i2c_add_numbered_adapter(struct i2c_adapter *adap) -{ - int id; - int status; - - if (adap->nr == -1) /* -1 means dynamically assign bus id */ - return i2c_add_adapter(adap); - if (adap->nr & ~MAX_ID_MASK) - return -EINVAL; - -retry: - if (idr_pre_get(&i2c_adapter_idr, GFP_KERNEL) == 0) - return -ENOMEM; - - mutex_lock(&core_lock); - /* "above" here means "above or equal to", sigh; - * we need the "equal to" result to force the result - */ - status = idr_get_new_above(&i2c_adapter_idr, adap, adap->nr, &id); - if (status == 0 && id != adap->nr) { - status = -EBUSY; - idr_remove(&i2c_adapter_idr, id); - } - mutex_unlock(&core_lock); - if (status == -EAGAIN) - goto retry; - - if (status == 0) - status = i2c_register_adapter(adap); - return status; -} -EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter); - -static int i2c_do_del_adapter(struct i2c_driver *driver, - struct i2c_adapter *adapter) -{ - struct i2c_client *client, *_n; - int res; - - /* Remove the devices we created ourselves as the result of hardware - * probing (using a driver's detect method) */ - list_for_each_entry_safe(client, _n, &driver->clients, detected) { - if (client->adapter == adapter) { - dev_dbg(&adapter->dev, "Removing %s at 0x%x\n", - client->name, client->addr); - list_del(&client->detected); - i2c_unregister_device(client); - } - } - - if (!driver->detach_adapter) - return 0; - dev_warn(&adapter->dev, "%s: detach_adapter method is deprecated\n", - driver->driver.name); - res = driver->detach_adapter(adapter); - if (res) - dev_err(&adapter->dev, "detach_adapter failed (%d) " - "for driver [%s]\n", res, driver->driver.name); - return res; -} - -static int __unregister_client(struct device *dev, void *dummy) -{ - struct i2c_client *client = i2c_verify_client(dev); - if (client && strcmp(client->name, "dummy")) - i2c_unregister_device(client); - return 0; -} - -static int __unregister_dummy(struct device *dev, void *dummy) -{ - struct i2c_client *client = i2c_verify_client(dev); - if (client) - i2c_unregister_device(client); - return 0; -} - -static int __process_removed_adapter(struct device_driver *d, void *data) -{ - return i2c_do_del_adapter(to_i2c_driver(d), data); -} - -/** - * i2c_del_adapter - unregister I2C adapter - * @adap: the adapter being unregistered - * Context: can sleep - * - * This unregisters an I2C adapter which was previously registered - * by @i2c_add_adapter or @i2c_add_numbered_adapter. - */ -int i2c_del_adapter(struct i2c_adapter *adap) -{ - int res = 0; - struct i2c_adapter *found; - struct i2c_client *client, *next; - - /* First make sure that this adapter was ever added */ - mutex_lock(&core_lock); - found = idr_find(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - if (found != adap) { - pr_debug("i2c-core: attempting to delete unregistered " - "adapter [%s]\n", adap->name); - return -EINVAL; - } - - /* Tell drivers about this removal */ - mutex_lock(&core_lock); - res = bus_for_each_drv(&i2c_bus_type, NULL, adap, - __process_removed_adapter); - mutex_unlock(&core_lock); - if (res) - return res; - - /* Remove devices instantiated from sysfs */ - mutex_lock(&adap->userspace_clients_lock); - list_for_each_entry_safe(client, next, &adap->userspace_clients, - detected) { - dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name, - client->addr); - list_del(&client->detected); - i2c_unregister_device(client); - } - mutex_unlock(&adap->userspace_clients_lock); - - /* Detach any active clients. This can't fail, thus we do not - * check the returned value. This is a two-pass process, because - * we can't remove the dummy devices during the first pass: they - * could have been instantiated by real devices wishing to clean - * them up properly, so we give them a chance to do that first. */ - res = device_for_each_child(&adap->dev, NULL, __unregister_client); - res = device_for_each_child(&adap->dev, NULL, __unregister_dummy); - -#ifdef CONFIG_I2C_COMPAT - class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, - adap->dev.parent); -#endif - - /* device name is gone after device_unregister */ - dev_dbg(&adap->dev, "adapter [%s] unregistered\n", adap->name); - - /* clean up the sysfs representation */ - init_completion(&adap->dev_released); - device_unregister(&adap->dev); - - /* wait for sysfs to drop all references */ - wait_for_completion(&adap->dev_released); - - /* free bus id */ - mutex_lock(&core_lock); - idr_remove(&i2c_adapter_idr, adap->nr); - mutex_unlock(&core_lock); - - /* Clear the device structure in case this adapter is ever going to be - added again */ - memset(&adap->dev, 0, sizeof(adap->dev)); - - return 0; -} -EXPORT_SYMBOL(i2c_del_adapter); - - -/* ------------------------------------------------------------------------- */ - -int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *)) -{ - int res; - - mutex_lock(&core_lock); - res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn); - mutex_unlock(&core_lock); - - return res; -} -EXPORT_SYMBOL_GPL(i2c_for_each_dev); - -static int __process_new_driver(struct device *dev, void *data) -{ - if (dev->type != &i2c_adapter_type) - return 0; - return i2c_do_add_adapter(data, to_i2c_adapter(dev)); -} - -/* - * An i2c_driver is used with one or more i2c_client (device) nodes to access - * i2c slave chips, on a bus instance associated with some i2c_adapter. - */ - -int i2c_register_driver(struct module *owner, struct i2c_driver *driver) -{ - int res; - - /* Can't register until after driver model init */ - if (unlikely(WARN_ON(!i2c_bus_type.p))) - return -EAGAIN; - - /* add the driver to the list of i2c drivers in the driver core */ - driver->driver.owner = owner; - driver->driver.bus = &i2c_bus_type; - - /* When registration returns, the driver core - * will have called probe() for all matching-but-unbound devices. - */ - res = driver_register(&driver->driver); - if (res) - return res; - - /* Drivers should switch to dev_pm_ops instead. */ - if (driver->suspend) - pr_warn("i2c-core: driver [%s] using legacy suspend method\n", - driver->driver.name); - if (driver->resume) - pr_warn("i2c-core: driver [%s] using legacy resume method\n", - driver->driver.name); - - pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - - INIT_LIST_HEAD(&driver->clients); - /* Walk the adapters that are already present */ - i2c_for_each_dev(driver, __process_new_driver); - - return 0; -} -EXPORT_SYMBOL(i2c_register_driver); - -static int __process_removed_driver(struct device *dev, void *data) -{ - if (dev->type != &i2c_adapter_type) - return 0; - return i2c_do_del_adapter(data, to_i2c_adapter(dev)); -} - -/** - * i2c_del_driver - unregister I2C driver - * @driver: the driver being unregistered - * Context: can sleep - */ -void i2c_del_driver(struct i2c_driver *driver) -{ - i2c_for_each_dev(driver, __process_removed_driver); - - driver_unregister(&driver->driver); - pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); -} -EXPORT_SYMBOL(i2c_del_driver); - -/* ------------------------------------------------------------------------- */ - -/** - * i2c_use_client - increments the reference count of the i2c client structure - * @client: the client being referenced - * - * Each live reference to a client should be refcounted. The driver model does - * that automatically as part of driver binding, so that most drivers don't - * need to do this explicitly: they hold a reference until they're unbound - * from the device. - * - * A pointer to the client with the incremented reference counter is returned. - */ -struct i2c_client *i2c_use_client(struct i2c_client *client) -{ - if (client && get_device(&client->dev)) - return client; - return NULL; -} -EXPORT_SYMBOL(i2c_use_client); - -/** - * i2c_release_client - release a use of the i2c client structure - * @client: the client being no longer referenced - * - * Must be called when a user of a client is finished with it. - */ -void i2c_release_client(struct i2c_client *client) -{ - if (client) - put_device(&client->dev); -} -EXPORT_SYMBOL(i2c_release_client); - -struct i2c_cmd_arg { - unsigned cmd; - void *arg; -}; - -static int i2c_cmd(struct device *dev, void *_arg) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_cmd_arg *arg = _arg; - - if (client && client->driver && client->driver->command) - client->driver->command(client, arg->cmd, arg->arg); - return 0; -} - -void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg) -{ - struct i2c_cmd_arg cmd_arg; - - cmd_arg.cmd = cmd; - cmd_arg.arg = arg; - device_for_each_child(&adap->dev, &cmd_arg, i2c_cmd); -} -EXPORT_SYMBOL(i2c_clients_command); - -static int __init i2c_init(void) -{ - int retval; - - retval = bus_register(&i2c_bus_type); - if (retval) - return retval; -#ifdef CONFIG_I2C_COMPAT - i2c_adapter_compat_class = class_compat_register("i2c-adapter"); - if (!i2c_adapter_compat_class) { - retval = -ENOMEM; - goto bus_err; - } -#endif - retval = i2c_add_driver(&dummy_driver); - if (retval) - goto class_err; - return 0; - -class_err: -#ifdef CONFIG_I2C_COMPAT - class_compat_unregister(i2c_adapter_compat_class); -bus_err: -#endif - bus_unregister(&i2c_bus_type); - return retval; -} - -static void __exit i2c_exit(void) -{ - i2c_del_driver(&dummy_driver); -#ifdef CONFIG_I2C_COMPAT - class_compat_unregister(i2c_adapter_compat_class); -#endif - bus_unregister(&i2c_bus_type); -} - -/* We must initialize early, because some subsystems register i2c drivers - * in subsys_initcall() code, but are linked (and initialized) before i2c. - */ -postcore_initcall(i2c_init); -module_exit(i2c_exit); - -/* ---------------------------------------------------- - * the functional interface to the i2c busses. - * ---------------------------------------------------- - */ - -/** - * i2c_transfer - execute a single or combined I2C message - * @adap: Handle to I2C bus - * @msgs: One or more messages to execute before STOP is issued to - * terminate the operation; each message begins with a START. - * @num: Number of messages to be executed. - * - * Returns negative errno, else the number of messages executed. - * - * Note that there is no requirement that each message be sent to - * the same slave address, although that is the most common model. - */ -int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - unsigned long orig_jiffies; - int ret, try; - - /* REVISIT the fault reporting model here is weak: - * - * - When we get an error after receiving N bytes from a slave, - * there is no way to report "N". - * - * - When we get a NAK after transmitting N bytes to a slave, - * there is no way to report "N" ... or to let the master - * continue executing the rest of this combined message, if - * that's the appropriate response. - * - * - When for example "num" is two and we successfully complete - * the first message but get an error part way through the - * second, it's unclear whether that should be reported as - * one (discarding status on the second message) or errno - * (discarding status on the first one). - */ - - if (adap->algo->master_xfer) { -#ifdef DEBUG - for (ret = 0; ret < num; ret++) { - dev_dbg(&adap->dev, "master_xfer[%d] %c, addr=0x%02x, " - "len=%d%s\n", ret, (msgs[ret].flags & I2C_M_RD) - ? 'R' : 'W', msgs[ret].addr, msgs[ret].len, - (msgs[ret].flags & I2C_M_RECV_LEN) ? "+" : ""); - } -#endif - - if (in_atomic() || irqs_disabled()) { - ret = i2c_trylock_adapter(adap); - if (!ret) - /* I2C activity is ongoing. */ - return -EAGAIN; - } else { - i2c_lock_adapter(adap); - } - - /* Retry automatically on arbitration loss */ - orig_jiffies = jiffies; - for (ret = 0, try = 0; try <= adap->retries; try++) { - ret = adap->algo->master_xfer(adap, msgs, num); - if (ret != -EAGAIN) - break; - if (time_after(jiffies, orig_jiffies + adap->timeout)) - break; - } - i2c_unlock_adapter(adap); - - return ret; - } else { - dev_dbg(&adap->dev, "I2C level transfers not supported\n"); - return -EOPNOTSUPP; - } -} -EXPORT_SYMBOL(i2c_transfer); - -/** - * i2c_master_send - issue a single I2C message in master transmit mode - * @client: Handle to slave device - * @buf: Data that will be written to the slave - * @count: How many bytes to write, must be less than 64k since msg.len is u16 - * - * Returns negative errno, or else the number of bytes written. - */ -int i2c_master_send(const struct i2c_client *client, const char *buf, int count) -{ - int ret; - struct i2c_adapter *adap = client->adapter; - struct i2c_msg msg; - - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; - msg.len = count; - msg.buf = (char *)buf; - - ret = i2c_transfer(adap, &msg, 1); - - /* - * If everything went ok (i.e. 1 msg transmitted), return #bytes - * transmitted, else error code. - */ - return (ret == 1) ? count : ret; -} -EXPORT_SYMBOL(i2c_master_send); - -/** - * i2c_master_recv - issue a single I2C message in master receive mode - * @client: Handle to slave device - * @buf: Where to store data read from slave - * @count: How many bytes to read, must be less than 64k since msg.len is u16 - * - * Returns negative errno, or else the number of bytes read. - */ -int i2c_master_recv(const struct i2c_client *client, char *buf, int count) -{ - struct i2c_adapter *adap = client->adapter; - struct i2c_msg msg; - int ret; - - msg.addr = client->addr; - msg.flags = client->flags & I2C_M_TEN; - msg.flags |= I2C_M_RD; - msg.len = count; - msg.buf = buf; - - ret = i2c_transfer(adap, &msg, 1); - - /* - * If everything went ok (i.e. 1 msg received), return #bytes received, - * else error code. - */ - return (ret == 1) ? count : ret; -} -EXPORT_SYMBOL(i2c_master_recv); - -/* ---------------------------------------------------- - * the i2c address scanning function - * Will not work for 10-bit addresses! - * ---------------------------------------------------- - */ - -/* - * Legacy default probe function, mostly relevant for SMBus. The default - * probe method is a quick write, but it is known to corrupt the 24RF08 - * EEPROMs due to a state machine bug, and could also irreversibly - * write-protect some EEPROMs, so for address ranges 0x30-0x37 and 0x50-0x5f, - * we use a short byte read instead. Also, some bus drivers don't implement - * quick write, so we fallback to a byte read in that case too. - * On x86, there is another special case for FSC hardware monitoring chips, - * which want regular byte reads (address 0x73.) Fortunately, these are the - * only known chips using this I2C address on PC hardware. - * Returns 1 if probe succeeded, 0 if not. - */ -static int i2c_default_probe(struct i2c_adapter *adap, unsigned short addr) -{ - int err; - union i2c_smbus_data dummy; - -#ifdef CONFIG_X86 - if (addr == 0x73 && (adap->class & I2C_CLASS_HWMON) - && i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE_DATA)) - err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE_DATA, &dummy); - else -#endif - if (!((addr & ~0x07) == 0x30 || (addr & ~0x0f) == 0x50) - && i2c_check_functionality(adap, I2C_FUNC_SMBUS_QUICK)) - err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_WRITE, 0, - I2C_SMBUS_QUICK, NULL); - else if (i2c_check_functionality(adap, I2C_FUNC_SMBUS_READ_BYTE)) - err = i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE, &dummy); - else { - dev_warn(&adap->dev, "No suitable probing method supported\n"); - err = -EOPNOTSUPP; - } - - return err >= 0; -} - -static int i2c_detect_address(struct i2c_client *temp_client, - struct i2c_driver *driver) -{ - struct i2c_board_info info; - struct i2c_adapter *adapter = temp_client->adapter; - int addr = temp_client->addr; - int err; - - /* Make sure the address is valid */ - err = i2c_check_addr_validity(addr); - if (err) { - dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", - addr); - return err; - } - - /* Skip if already in use */ - if (i2c_check_addr_busy(adapter, addr)) - return 0; - - /* Make sure there is something at this address */ - if (!i2c_default_probe(adapter, addr)) - return 0; - - /* Finally call the custom detection function */ - memset(&info, 0, sizeof(struct i2c_board_info)); - info.addr = addr; - err = driver->detect(temp_client, &info); - if (err) { - /* -ENODEV is returned if the detection fails. We catch it - here as this isn't an error. */ - return err == -ENODEV ? 0 : err; - } - - /* Consistency check */ - if (info.type[0] == '\0') { - dev_err(&adapter->dev, "%s detection function provided " - "no name for 0x%x\n", driver->driver.name, - addr); - } else { - struct i2c_client *client; - - /* Detection succeeded, instantiate the device */ - dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", - info.type, info.addr); - client = i2c_new_device(adapter, &info); - if (client) - list_add_tail(&client->detected, &driver->clients); - else - dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", - info.type, info.addr); - } - return 0; -} - -static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) -{ - const unsigned short *address_list; - struct i2c_client *temp_client; - int i, err = 0; - int adap_id = i2c_adapter_id(adapter); - - address_list = driver->address_list; - if (!driver->detect || !address_list) - return 0; - - /* Stop here if the classes do not match */ - if (!(adapter->class & driver->class)) - return 0; - - /* Set up a temporary client to help detect callback */ - temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); - if (!temp_client) - return -ENOMEM; - temp_client->adapter = adapter; - - for (i = 0; address_list[i] != I2C_CLIENT_END; i += 1) { - dev_dbg(&adapter->dev, "found normal entry for adapter %d, " - "addr 0x%02x\n", adap_id, address_list[i]); - temp_client->addr = address_list[i]; - err = i2c_detect_address(temp_client, driver); - if (unlikely(err)) - break; - } - - kfree(temp_client); - return err; -} - -int i2c_probe_func_quick_read(struct i2c_adapter *adap, unsigned short addr) -{ - return i2c_smbus_xfer(adap, addr, 0, I2C_SMBUS_READ, 0, - I2C_SMBUS_QUICK, NULL) >= 0; -} -EXPORT_SYMBOL_GPL(i2c_probe_func_quick_read); - -struct i2c_client * -i2c_new_probed_device(struct i2c_adapter *adap, - struct i2c_board_info *info, - unsigned short const *addr_list, - int (*probe)(struct i2c_adapter *, unsigned short addr)) -{ - int i; - - if (!probe) - probe = i2c_default_probe; - - for (i = 0; addr_list[i] != I2C_CLIENT_END; i++) { - /* Check address validity */ - if (i2c_check_addr_validity(addr_list[i]) < 0) { - dev_warn(&adap->dev, "Invalid 7-bit address " - "0x%02x\n", addr_list[i]); - continue; - } - - /* Check address availability */ - if (i2c_check_addr_busy(adap, addr_list[i])) { - dev_dbg(&adap->dev, "Address 0x%02x already in " - "use, not probing\n", addr_list[i]); - continue; - } - - /* Test address responsiveness */ - if (probe(adap, addr_list[i])) - break; - } - - if (addr_list[i] == I2C_CLIENT_END) { - dev_dbg(&adap->dev, "Probing failed, no device found\n"); - return NULL; - } - - info->addr = addr_list[i]; - return i2c_new_device(adap, info); -} -EXPORT_SYMBOL_GPL(i2c_new_probed_device); - -struct i2c_adapter *i2c_get_adapter(int nr) -{ - struct i2c_adapter *adapter; - - mutex_lock(&core_lock); - adapter = idr_find(&i2c_adapter_idr, nr); - if (adapter && !try_module_get(adapter->owner)) - adapter = NULL; - - mutex_unlock(&core_lock); - return adapter; -} -EXPORT_SYMBOL(i2c_get_adapter); - -void i2c_put_adapter(struct i2c_adapter *adap) -{ - module_put(adap->owner); -} -EXPORT_SYMBOL(i2c_put_adapter); - -/* The SMBus parts */ - -#define POLY (0x1070U << 3) -static u8 crc8(u16 data) -{ - int i; - - for (i = 0; i < 8; i++) { - if (data & 0x8000) - data = data ^ POLY; - data = data << 1; - } - return (u8)(data >> 8); -} - -/* Incremental CRC8 over count bytes in the array pointed to by p */ -static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) -{ - int i; - - for (i = 0; i < count; i++) - crc = crc8((crc ^ p[i]) << 8); - return crc; -} - -/* Assume a 7-bit address, which is reasonable for SMBus */ -static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) -{ - /* The address will be sent first */ - u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); - pec = i2c_smbus_pec(pec, &addr, 1); - - /* The data buffer follows */ - return i2c_smbus_pec(pec, msg->buf, msg->len); -} - -/* Used for write only transactions */ -static inline void i2c_smbus_add_pec(struct i2c_msg *msg) -{ - msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg); - msg->len++; -} - -/* Return <0 on CRC error - If there was a write before this read (most cases) we need to take the - partial CRC from the write part into account. - Note that this function does modify the message (we need to decrease the - message length to hide the CRC byte from the caller). */ -static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) -{ - u8 rpec = msg->buf[--msg->len]; - cpec = i2c_smbus_msg_pec(cpec, msg); - - if (rpec != cpec) { - pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", - rpec, cpec); - return -EBADMSG; - } - return 0; -} - -/** - * i2c_smbus_read_byte - SMBus "receive byte" protocol - * @client: Handle to slave device - * - * This executes the SMBus "receive byte" protocol, returning negative errno - * else the byte received from the device. - */ -s32 i2c_smbus_read_byte(const struct i2c_client *client) -{ - union i2c_smbus_data data; - int status; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, 0, - I2C_SMBUS_BYTE, &data); - return (status < 0) ? status : data.byte; -} -EXPORT_SYMBOL(i2c_smbus_read_byte); - -/** - * i2c_smbus_write_byte - SMBus "send byte" protocol - * @client: Handle to slave device - * @value: Byte to be sent - * - * This executes the SMBus "send byte" protocol, returning negative errno - * else zero on success. - */ -s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value) -{ - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); -} -EXPORT_SYMBOL(i2c_smbus_write_byte); - -/** - * i2c_smbus_read_byte_data - SMBus "read byte" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * - * This executes the SMBus "read byte" protocol, returning negative errno - * else a data byte received from the device. - */ -s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) -{ - union i2c_smbus_data data; - int status; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BYTE_DATA, &data); - return (status < 0) ? status : data.byte; -} -EXPORT_SYMBOL(i2c_smbus_read_byte_data); - -/** - * i2c_smbus_write_byte_data - SMBus "write byte" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * @value: Byte being written - * - * This executes the SMBus "write byte" protocol, returning negative errno - * else zero on success. - */ -s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, - u8 value) -{ - union i2c_smbus_data data; - data.byte = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BYTE_DATA, &data); -} -EXPORT_SYMBOL(i2c_smbus_write_byte_data); - -/** - * i2c_smbus_read_word_data - SMBus "read word" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * - * This executes the SMBus "read word" protocol, returning negative errno - * else a 16-bit unsigned "word" received from the device. - */ -s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) -{ - union i2c_smbus_data data; - int status; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_WORD_DATA, &data); - return (status < 0) ? status : data.word; -} -EXPORT_SYMBOL(i2c_smbus_read_word_data); - -/** - * i2c_smbus_write_word_data - SMBus "write word" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * @value: 16-bit "word" being written - * - * This executes the SMBus "write word" protocol, returning negative errno - * else zero on success. - */ -s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, - u16 value) -{ - union i2c_smbus_data data; - data.word = value; - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_WORD_DATA, &data); -} -EXPORT_SYMBOL(i2c_smbus_write_word_data); - -/** - * i2c_smbus_process_call - SMBus "process call" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * @value: 16-bit "word" being written - * - * This executes the SMBus "process call" protocol, returning negative errno - * else a 16-bit unsigned "word" received from the device. - */ -s32 i2c_smbus_process_call(const struct i2c_client *client, u8 command, - u16 value) -{ - union i2c_smbus_data data; - int status; - data.word = value; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_PROC_CALL, &data); - return (status < 0) ? status : data.word; -} -EXPORT_SYMBOL(i2c_smbus_process_call); - -/** - * i2c_smbus_read_block_data - SMBus "block read" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * @values: Byte array into which data will be read; big enough to hold - * the data returned by the slave. SMBus allows at most 32 bytes. - * - * This executes the SMBus "block read" protocol, returning negative errno - * else the number of data bytes in the slave's response. - * - * Note that using this function requires that the client's adapter support - * the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality. Not all adapter drivers - * support this; its emulation through I2C messaging relies on a specific - * mechanism (I2C_M_RECV_LEN) which may not be implemented. - */ -s32 i2c_smbus_read_block_data(const struct i2c_client *client, u8 command, - u8 *values) -{ - union i2c_smbus_data data; - int status; - - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BLOCK_DATA, &data); - if (status) - return status; - - memcpy(values, &data.block[1], data.block[0]); - return data.block[0]; -} -EXPORT_SYMBOL(i2c_smbus_read_block_data); - -/** - * i2c_smbus_write_block_data - SMBus "block write" protocol - * @client: Handle to slave device - * @command: Byte interpreted by slave - * @length: Size of data block; SMBus allows at most 32 bytes - * @values: Byte array which will be written. - * - * This executes the SMBus "block write" protocol, returning negative errno - * else zero on success. - */ -s32 i2c_smbus_write_block_data(const struct i2c_client *client, u8 command, - u8 length, const u8 *values) -{ - union i2c_smbus_data data; - - if (length > I2C_SMBUS_BLOCK_MAX) - length = I2C_SMBUS_BLOCK_MAX; - data.block[0] = length; - memcpy(&data.block[1], values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_BLOCK_DATA, &data); -} -EXPORT_SYMBOL(i2c_smbus_write_block_data); - -/* Returns the number of read bytes */ -s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, - u8 length, u8 *values) -{ - union i2c_smbus_data data; - int status; - - if (length > I2C_SMBUS_BLOCK_MAX) - length = I2C_SMBUS_BLOCK_MAX; - data.block[0] = length; - status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); - if (status < 0) - return status; - - memcpy(values, &data.block[1], data.block[0]); - return data.block[0]; -} -EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); - -s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, - u8 length, const u8 *values) -{ - union i2c_smbus_data data; - - if (length > I2C_SMBUS_BLOCK_MAX) - length = I2C_SMBUS_BLOCK_MAX; - data.block[0] = length; - memcpy(data.block + 1, values, length); - return i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_WRITE, command, - I2C_SMBUS_I2C_BLOCK_DATA, &data); -} -EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); - -/* Simulate a SMBus command using the i2c protocol - No checking of parameters is done! */ -static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, - unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data *data) -{ - /* So we need to generate a series of msgs. In the case of writing, we - need to use only one message; when reading, we need two. We initialize - most things with sane defaults, to keep the code below somewhat - simpler. */ - unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; - unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; - int num = read_write == I2C_SMBUS_READ ? 2 : 1; - struct i2c_msg msg[2] = { { addr, flags, 1, msgbuf0 }, - { addr, flags | I2C_M_RD, 0, msgbuf1 } - }; - int i; - u8 partial_pec = 0; - int status; - - msgbuf0[0] = command; - switch (size) { - case I2C_SMBUS_QUICK: - msg[0].len = 0; - /* Special case: The read/write field is used as data */ - msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? - I2C_M_RD : 0); - num = 1; - break; - case I2C_SMBUS_BYTE: - if (read_write == I2C_SMBUS_READ) { - /* Special case: only a read! */ - msg[0].flags = I2C_M_RD | flags; - num = 1; - } - break; - case I2C_SMBUS_BYTE_DATA: - if (read_write == I2C_SMBUS_READ) - msg[1].len = 1; - else { - msg[0].len = 2; - msgbuf0[1] = data->byte; - } - break; - case I2C_SMBUS_WORD_DATA: - if (read_write == I2C_SMBUS_READ) - msg[1].len = 2; - else { - msg[0].len = 3; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = data->word >> 8; - } - break; - case I2C_SMBUS_PROC_CALL: - num = 2; /* Special case */ - read_write = I2C_SMBUS_READ; - msg[0].len = 3; - msg[1].len = 2; - msgbuf0[1] = data->word & 0xff; - msgbuf0[2] = data->word >> 8; - break; - case I2C_SMBUS_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - msg[1].flags |= I2C_M_RECV_LEN; - msg[1].len = 1; /* block length will be added by - the underlying bus driver */ - } else { - msg[0].len = data->block[0] + 2; - if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { - dev_err(&adapter->dev, - "Invalid block write size %d\n", - data->block[0]); - return -EINVAL; - } - for (i = 1; i < msg[0].len; i++) - msgbuf0[i] = data->block[i-1]; - } - break; - case I2C_SMBUS_BLOCK_PROC_CALL: - num = 2; /* Another special case */ - read_write = I2C_SMBUS_READ; - if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { - dev_err(&adapter->dev, - "Invalid block write size %d\n", - data->block[0]); - return -EINVAL; - } - msg[0].len = data->block[0] + 2; - for (i = 1; i < msg[0].len; i++) - msgbuf0[i] = data->block[i-1]; - msg[1].flags |= I2C_M_RECV_LEN; - msg[1].len = 1; /* block length will be added by - the underlying bus driver */ - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - if (read_write == I2C_SMBUS_READ) { - msg[1].len = data->block[0]; - } else { - msg[0].len = data->block[0] + 1; - if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { - dev_err(&adapter->dev, - "Invalid block write size %d\n", - data->block[0]); - return -EINVAL; - } - for (i = 1; i <= data->block[0]; i++) - msgbuf0[i] = data->block[i]; - } - break; - default: - dev_err(&adapter->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK - && size != I2C_SMBUS_I2C_BLOCK_DATA); - if (i) { - /* Compute PEC if first message is a write */ - if (!(msg[0].flags & I2C_M_RD)) { - if (num == 1) /* Write only */ - i2c_smbus_add_pec(&msg[0]); - else /* Write followed by read */ - partial_pec = i2c_smbus_msg_pec(0, &msg[0]); - } - /* Ask for PEC if last message is a read */ - if (msg[num-1].flags & I2C_M_RD) - msg[num-1].len++; - } - - status = i2c_transfer(adapter, msg, num); - if (status < 0) - return status; - - /* Check PEC if last message is a read */ - if (i && (msg[num-1].flags & I2C_M_RD)) { - status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); - if (status < 0) - return status; - } - - if (read_write == I2C_SMBUS_READ) - switch (size) { - case I2C_SMBUS_BYTE: - data->byte = msgbuf0[0]; - break; - case I2C_SMBUS_BYTE_DATA: - data->byte = msgbuf1[0]; - break; - case I2C_SMBUS_WORD_DATA: - case I2C_SMBUS_PROC_CALL: - data->word = msgbuf1[0] | (msgbuf1[1] << 8); - break; - case I2C_SMBUS_I2C_BLOCK_DATA: - for (i = 0; i < data->block[0]; i++) - data->block[i+1] = msgbuf1[i]; - break; - case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_BLOCK_PROC_CALL: - for (i = 0; i < msgbuf1[0] + 1; i++) - data->block[i] = msgbuf1[i]; - break; - } - return 0; -} - -/** - * i2c_smbus_xfer - execute SMBus protocol operations - * @adapter: Handle to I2C bus - * @addr: Address of SMBus slave on that bus - * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC) - * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE - * @command: Byte interpreted by slave, for protocols which use such bytes - * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL - * @data: Data to be read or written - * - * This executes an SMBus protocol operation, and returns a negative - * errno code else zero on success. - */ -s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, - char read_write, u8 command, int protocol, - union i2c_smbus_data *data) -{ - unsigned long orig_jiffies; - int try; - s32 res; - - flags &= I2C_M_TEN | I2C_CLIENT_PEC; - - if (adapter->algo->smbus_xfer) { - i2c_lock_adapter(adapter); - - /* Retry automatically on arbitration loss */ - orig_jiffies = jiffies; - for (res = 0, try = 0; try <= adapter->retries; try++) { - res = adapter->algo->smbus_xfer(adapter, addr, flags, - read_write, command, - protocol, data); - if (res != -EAGAIN) - break; - if (time_after(jiffies, - orig_jiffies + adapter->timeout)) - break; - } - i2c_unlock_adapter(adapter); - } else - res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, - command, protocol, data); - - return res; -} -EXPORT_SYMBOL(i2c_smbus_xfer); - -MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); -MODULE_DESCRIPTION("I2C-Bus main module"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-core.h b/ANDROID_3.4.5/drivers/i2c/i2c-core.h deleted file mode 100644 index 18a8fd21..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-core.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * i2c-core.h - interfaces internal to the I2C framework - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA. - */ - -#include <linux/rwsem.h> - -struct i2c_devinfo { - struct list_head list; - int busnum; - struct i2c_board_info board_info; -}; - -/* board_lock protects board_list and first_dynamic_bus_num. - * only i2c core components are allowed to use these symbols. - */ -extern struct rw_semaphore __i2c_board_lock; -extern struct list_head __i2c_board_list; -extern int __i2c_first_dynamic_bus_num; - diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-dev.c b/ANDROID_3.4.5/drivers/i2c/i2c-dev.c deleted file mode 100644 index 45048323..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-dev.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - i2c-dev.c - i2c-bus driver, char device interface - - Copyright (C) 1995-97 Simon G. Vogl - Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl> - Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com> - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - MA 02110-1301 USA. -*/ - -/* Note that this is a complete rewrite of Simon Vogl's i2c-dev module. - But I have used so much of his original code and ideas that it seems - only fair to recognize him as co-author -- Frodo */ - -/* The I2C_RDWR ioctl code is written by Kolja Waschk <waschk@telos.de> */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/notifier.h> -#include <linux/fs.h> -#include <linux/slab.h> -#include <linux/init.h> -#include <linux/list.h> -#include <linux/i2c.h> -#include <linux/i2c-dev.h> -#include <linux/jiffies.h> -#include <linux/uaccess.h> - -/* - * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a - * slave (i2c_client) with which messages will be exchanged. It's coupled - * with a character special file which is accessed by user mode drivers. - * - * The list of i2c_dev structures is parallel to the i2c_adapter lists - * maintained by the driver model, and is updated using bus notifications. - */ -struct i2c_dev { - struct list_head list; - struct i2c_adapter *adap; - struct device *dev; -}; - -#define I2C_MINORS 256 -static LIST_HEAD(i2c_dev_list); -static DEFINE_SPINLOCK(i2c_dev_list_lock); - -static struct i2c_dev *i2c_dev_get_by_minor(unsigned index) -{ - struct i2c_dev *i2c_dev; - - spin_lock(&i2c_dev_list_lock); - list_for_each_entry(i2c_dev, &i2c_dev_list, list) { - if (i2c_dev->adap->nr == index) - goto found; - } - i2c_dev = NULL; -found: - spin_unlock(&i2c_dev_list_lock); - return i2c_dev; -} - -static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap) -{ - struct i2c_dev *i2c_dev; - - if (adap->nr >= I2C_MINORS) { - printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n", - adap->nr); - return ERR_PTR(-ENODEV); - } - - i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL); - if (!i2c_dev) - return ERR_PTR(-ENOMEM); - i2c_dev->adap = adap; - - spin_lock(&i2c_dev_list_lock); - list_add_tail(&i2c_dev->list, &i2c_dev_list); - spin_unlock(&i2c_dev_list_lock); - return i2c_dev; -} - -static void return_i2c_dev(struct i2c_dev *i2c_dev) -{ - spin_lock(&i2c_dev_list_lock); - list_del(&i2c_dev->list); - spin_unlock(&i2c_dev_list_lock); - kfree(i2c_dev); -} - -static ssize_t show_adapter_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_dev *i2c_dev = i2c_dev_get_by_minor(MINOR(dev->devt)); - - if (!i2c_dev) - return -ENODEV; - return sprintf(buf, "%s\n", i2c_dev->adap->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_adapter_name, NULL); - -/* ------------------------------------------------------------------------- */ - -/* - * After opening an instance of this character special file, a file - * descriptor starts out associated only with an i2c_adapter (and bus). - * - * Using the I2C_RDWR ioctl(), you can then *immediately* issue i2c_msg - * traffic to any devices on the bus used by that adapter. That's because - * the i2c_msg vectors embed all the addressing information they need, and - * are submitted directly to an i2c_adapter. However, SMBus-only adapters - * don't support that interface. - * - * To use read()/write() system calls on that file descriptor, or to use - * SMBus interfaces (and work with SMBus-only hosts!), you must first issue - * an I2C_SLAVE (or I2C_SLAVE_FORCE) ioctl. That configures an anonymous - * (never registered) i2c_client so it holds the addressing information - * needed by those system calls and by this SMBus interface. - */ - -static ssize_t i2cdev_read(struct file *file, char __user *buf, size_t count, - loff_t *offset) -{ - char *tmp; - int ret; - - struct i2c_client *client = file->private_data; - - if (count > 8192) - count = 8192; - - tmp = kmalloc(count, GFP_KERNEL); - if (tmp == NULL) - return -ENOMEM; - - pr_debug("i2c-dev: i2c-%d reading %zu bytes.\n", - iminor(file->f_path.dentry->d_inode), count); - - ret = i2c_master_recv(client, tmp, count); - if (ret >= 0) - ret = copy_to_user(buf, tmp, count) ? -EFAULT : ret; - kfree(tmp); - return ret; -} - -static ssize_t i2cdev_write(struct file *file, const char __user *buf, - size_t count, loff_t *offset) -{ - int ret; - char *tmp; - struct i2c_client *client = file->private_data; - - if (count > 8192) - count = 8192; - - tmp = memdup_user(buf, count); - if (IS_ERR(tmp)) - return PTR_ERR(tmp); - - pr_debug("i2c-dev: i2c-%d writing %zu bytes.\n", - iminor(file->f_path.dentry->d_inode), count); - - ret = i2c_master_send(client, tmp, count); - kfree(tmp); - return ret; -} - -static int i2cdev_check(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - - if (!client || client->addr != *(unsigned int *)addrp) - return 0; - - return dev->driver ? -EBUSY : 0; -} - -/* walk up mux tree */ -static int i2cdev_check_mux_parents(struct i2c_adapter *adapter, int addr) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - int result; - - result = device_for_each_child(&adapter->dev, &addr, i2cdev_check); - if (!result && parent) - result = i2cdev_check_mux_parents(parent, addr); - - return result; -} - -/* recurse down mux tree */ -static int i2cdev_check_mux_children(struct device *dev, void *addrp) -{ - int result; - - if (dev->type == &i2c_adapter_type) - result = device_for_each_child(dev, addrp, - i2cdev_check_mux_children); - else - result = i2cdev_check(dev, addrp); - - return result; -} - -/* This address checking function differs from the one in i2c-core - in that it considers an address with a registered device, but no - driver bound to it, as NOT busy. */ -static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) -{ - struct i2c_adapter *parent = i2c_parent_is_i2c_adapter(adapter); - int result = 0; - - if (parent) - result = i2cdev_check_mux_parents(parent, addr); - - if (!result) - result = device_for_each_child(&adapter->dev, &addr, - i2cdev_check_mux_children); - - return result; -} - -static noinline int i2cdev_ioctl_rdrw(struct i2c_client *client, - unsigned long arg) -{ - struct i2c_rdwr_ioctl_data rdwr_arg; - struct i2c_msg *rdwr_pa; - u8 __user **data_ptrs; - int i, res; - - if (copy_from_user(&rdwr_arg, - (struct i2c_rdwr_ioctl_data __user *)arg, - sizeof(rdwr_arg))) - return -EFAULT; - - /* Put an arbitrary limit on the number of messages that can - * be sent at once */ - if (rdwr_arg.nmsgs > I2C_RDRW_IOCTL_MAX_MSGS) - return -EINVAL; - - rdwr_pa = memdup_user(rdwr_arg.msgs, - rdwr_arg.nmsgs * sizeof(struct i2c_msg)); - if (IS_ERR(rdwr_pa)) - return PTR_ERR(rdwr_pa); - - data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); - if (data_ptrs == NULL) { - kfree(rdwr_pa); - return -ENOMEM; - } - - res = 0; - for (i = 0; i < rdwr_arg.nmsgs; i++) { - /* Limit the size of the message to a sane amount; - * and don't let length change either. */ - if ((rdwr_pa[i].len > 8192) || - (rdwr_pa[i].flags & I2C_M_RECV_LEN)) { - res = -EINVAL; - break; - } - data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; - rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); - if (IS_ERR(rdwr_pa[i].buf)) { - res = PTR_ERR(rdwr_pa[i].buf); - break; - } - } - if (res < 0) { - int j; - for (j = 0; j < i; ++j) - kfree(rdwr_pa[j].buf); - kfree(data_ptrs); - kfree(rdwr_pa); - return res; - } - - res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); - while (i-- > 0) { - if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { - if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, - rdwr_pa[i].len)) - res = -EFAULT; - } - kfree(rdwr_pa[i].buf); - } - kfree(data_ptrs); - kfree(rdwr_pa); - return res; -} - -static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, - unsigned long arg) -{ - struct i2c_smbus_ioctl_data data_arg; - union i2c_smbus_data temp; - int datasize, res; - - if (copy_from_user(&data_arg, - (struct i2c_smbus_ioctl_data __user *) arg, - sizeof(struct i2c_smbus_ioctl_data))) - return -EFAULT; - if ((data_arg.size != I2C_SMBUS_BYTE) && - (data_arg.size != I2C_SMBUS_QUICK) && - (data_arg.size != I2C_SMBUS_BYTE_DATA) && - (data_arg.size != I2C_SMBUS_WORD_DATA) && - (data_arg.size != I2C_SMBUS_PROC_CALL) && - (data_arg.size != I2C_SMBUS_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && - (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && - (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { - dev_dbg(&client->adapter->dev, - "size out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.size); - return -EINVAL; - } - /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, - so the check is valid if size==I2C_SMBUS_QUICK too. */ - if ((data_arg.read_write != I2C_SMBUS_READ) && - (data_arg.read_write != I2C_SMBUS_WRITE)) { - dev_dbg(&client->adapter->dev, - "read_write out of range (%x) in ioctl I2C_SMBUS.\n", - data_arg.read_write); - return -EINVAL; - } - - /* Note that command values are always valid! */ - - if ((data_arg.size == I2C_SMBUS_QUICK) || - ((data_arg.size == I2C_SMBUS_BYTE) && - (data_arg.read_write == I2C_SMBUS_WRITE))) - /* These are special: we do not use data */ - return i2c_smbus_xfer(client->adapter, client->addr, - client->flags, data_arg.read_write, - data_arg.command, data_arg.size, NULL); - - if (data_arg.data == NULL) { - dev_dbg(&client->adapter->dev, - "data is NULL pointer in ioctl I2C_SMBUS.\n"); - return -EINVAL; - } - - if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || - (data_arg.size == I2C_SMBUS_BYTE)) - datasize = sizeof(data_arg.data->byte); - else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || - (data_arg.size == I2C_SMBUS_PROC_CALL)) - datasize = sizeof(data_arg.data->word); - else /* size == smbus block, i2c block, or block proc. call */ - datasize = sizeof(data_arg.data->block); - - if ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || - (data_arg.read_write == I2C_SMBUS_WRITE)) { - if (copy_from_user(&temp, data_arg.data, datasize)) - return -EFAULT; - } - if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { - /* Convert old I2C block commands to the new - convention. This preserves binary compatibility. */ - data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; - if (data_arg.read_write == I2C_SMBUS_READ) - temp.block[0] = I2C_SMBUS_BLOCK_MAX; - } - res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, - data_arg.read_write, data_arg.command, data_arg.size, &temp); - if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || - (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || - (data_arg.read_write == I2C_SMBUS_READ))) { - if (copy_to_user(data_arg.data, &temp, datasize)) - return -EFAULT; - } - return res; -} - -static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - struct i2c_client *client = file->private_data; - unsigned long funcs; - - dev_dbg(&client->adapter->dev, "ioctl, cmd=0x%02x, arg=0x%02lx\n", - cmd, arg); - - switch (cmd) { - case I2C_SLAVE: - case I2C_SLAVE_FORCE: - /* NOTE: devices set up to work with "new style" drivers - * can't use I2C_SLAVE, even when the device node is not - * bound to a driver. Only I2C_SLAVE_FORCE will work. - * - * Setting the PEC flag here won't affect kernel drivers, - * which will be using the i2c_client node registered with - * the driver model core. Likewise, when that client has - * the PEC flag already set, the i2c-dev driver won't see - * (or use) this setting. - */ - if ((arg > 0x3ff) || - (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f)) - return -EINVAL; - if (cmd == I2C_SLAVE && i2cdev_check_addr(client->adapter, arg)) - return -EBUSY; - /* REVISIT: address could become busy later */ - client->addr = arg; - return 0; - case I2C_TENBIT: - if (arg) - client->flags |= I2C_M_TEN; - else - client->flags &= ~I2C_M_TEN; - return 0; - case I2C_PEC: - if (arg) - client->flags |= I2C_CLIENT_PEC; - else - client->flags &= ~I2C_CLIENT_PEC; - return 0; - case I2C_FUNCS: - funcs = i2c_get_functionality(client->adapter); - return put_user(funcs, (unsigned long __user *)arg); - - case I2C_RDWR: - return i2cdev_ioctl_rdrw(client, arg); - - case I2C_SMBUS: - return i2cdev_ioctl_smbus(client, arg); - - case I2C_RETRIES: - client->adapter->retries = arg; - break; - case I2C_TIMEOUT: - /* For historical reasons, user-space sets the timeout - * value in units of 10 ms. - */ - client->adapter->timeout = msecs_to_jiffies(arg * 10); - break; - default: - /* NOTE: returning a fault code here could cause trouble - * in buggy userspace code. Some old kernel bugs returned - * zero in this case, and userspace code might accidentally - * have depended on that bug. - */ - return -ENOTTY; - } - return 0; -} - -static int i2cdev_open(struct inode *inode, struct file *file) -{ - unsigned int minor = iminor(inode); - struct i2c_client *client; - struct i2c_adapter *adap; - struct i2c_dev *i2c_dev; - - i2c_dev = i2c_dev_get_by_minor(minor); - if (!i2c_dev) - return -ENODEV; - - adap = i2c_get_adapter(i2c_dev->adap->nr); - if (!adap) - return -ENODEV; - - /* This creates an anonymous i2c_client, which may later be - * pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE. - * - * This client is ** NEVER REGISTERED ** with the driver model - * or I2C core code!! It just holds private copies of addressing - * information and maybe a PEC flag. - */ - client = kzalloc(sizeof(*client), GFP_KERNEL); - if (!client) { - i2c_put_adapter(adap); - return -ENOMEM; - } - snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr); - - client->adapter = adap; - file->private_data = client; - - return 0; -} - -static int i2cdev_release(struct inode *inode, struct file *file) -{ - struct i2c_client *client = file->private_data; - - i2c_put_adapter(client->adapter); - kfree(client); - file->private_data = NULL; - - return 0; -} - -static const struct file_operations i2cdev_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .read = i2cdev_read, - .write = i2cdev_write, - .unlocked_ioctl = i2cdev_ioctl, - .open = i2cdev_open, - .release = i2cdev_release, -}; - -/* ------------------------------------------------------------------------- */ - -static struct class *i2c_dev_class; - -static int i2cdev_attach_adapter(struct device *dev, void *dummy) -{ - struct i2c_adapter *adap; - struct i2c_dev *i2c_dev; - int res; - - if (dev->type != &i2c_adapter_type) - return 0; - adap = to_i2c_adapter(dev); - - i2c_dev = get_free_i2c_dev(adap); - if (IS_ERR(i2c_dev)) - return PTR_ERR(i2c_dev); - - /* register this i2c device with the driver core */ - i2c_dev->dev = device_create(i2c_dev_class, &adap->dev, - MKDEV(I2C_MAJOR, adap->nr), NULL, - "i2c-%d", adap->nr); - if (IS_ERR(i2c_dev->dev)) { - res = PTR_ERR(i2c_dev->dev); - goto error; - } - res = device_create_file(i2c_dev->dev, &dev_attr_name); - if (res) - goto error_destroy; - - pr_debug("i2c-dev: adapter [%s] registered as minor %d\n", - adap->name, adap->nr); - return 0; -error_destroy: - device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); -error: - return_i2c_dev(i2c_dev); - return res; -} - -static int i2cdev_detach_adapter(struct device *dev, void *dummy) -{ - struct i2c_adapter *adap; - struct i2c_dev *i2c_dev; - - if (dev->type != &i2c_adapter_type) - return 0; - adap = to_i2c_adapter(dev); - - i2c_dev = i2c_dev_get_by_minor(adap->nr); - if (!i2c_dev) /* attach_adapter must have failed */ - return 0; - - device_remove_file(i2c_dev->dev, &dev_attr_name); - return_i2c_dev(i2c_dev); - device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr)); - - pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name); - return 0; -} - -static int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action, - void *data) -{ - struct device *dev = data; - - switch (action) { - case BUS_NOTIFY_ADD_DEVICE: - return i2cdev_attach_adapter(dev, NULL); - case BUS_NOTIFY_DEL_DEVICE: - return i2cdev_detach_adapter(dev, NULL); - } - - return 0; -} - -static struct notifier_block i2cdev_notifier = { - .notifier_call = i2cdev_notifier_call, -}; - -/* ------------------------------------------------------------------------- */ - -/* - * module load/unload record keeping - */ - -static int __init i2c_dev_init(void) -{ - int res; - - printk(KERN_INFO "i2c /dev entries driver\n"); - - res = register_chrdev(I2C_MAJOR, "i2c", &i2cdev_fops); - if (res) - goto out; - - i2c_dev_class = class_create(THIS_MODULE, "i2c-dev"); - if (IS_ERR(i2c_dev_class)) { - res = PTR_ERR(i2c_dev_class); - goto out_unreg_chrdev; - } - - /* Keep track of adapters which will be added or removed later */ - res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier); - if (res) - goto out_unreg_class; - - /* Bind to already existing adapters right away */ - i2c_for_each_dev(NULL, i2cdev_attach_adapter); - - return 0; - -out_unreg_class: - class_destroy(i2c_dev_class); -out_unreg_chrdev: - unregister_chrdev(I2C_MAJOR, "i2c"); -out: - printk(KERN_ERR "%s: Driver Initialisation failed\n", __FILE__); - return res; -} - -static void __exit i2c_dev_exit(void) -{ - bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier); - i2c_for_each_dev(NULL, i2cdev_detach_adapter); - class_destroy(i2c_dev_class); - unregister_chrdev(I2C_MAJOR, "i2c"); -} - -MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and " - "Simon G. Vogl <simon@tk.uni-linz.ac.at>"); -MODULE_DESCRIPTION("I2C /dev entries driver"); -MODULE_LICENSE("GPL"); - -module_init(i2c_dev_init); -module_exit(i2c_dev_exit); diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-mux.c b/ANDROID_3.4.5/drivers/i2c/i2c-mux.c deleted file mode 100644 index d7a4833b..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-mux.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Multiplexed I2C bus driver. - * - * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> - * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> - * Copyright (c) 2009-2010 NSN GmbH & Co KG <michael.lawnick.ext@nsn.com> - * - * Simplifies access to complex multiplexed I2C bus topologies, by presenting - * each multiplexed bus segment as an additional I2C adapter. - * Supports multi-level mux'ing (mux behind a mux). - * - * Based on: - * i2c-virt.c from Kumar Gala <galak@kernel.crashing.org> - * i2c-virtual.c from Ken Harrenstien, Copyright (c) 2004 Google, Inc. - * i2c-virtual.c from Brian Kuschak <bkuschak@yahoo.com> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/i2c.h> -#include <linux/i2c-mux.h> - -/* multiplexer per channel data */ -struct i2c_mux_priv { - struct i2c_adapter adap; - struct i2c_algorithm algo; - - struct i2c_adapter *parent; - void *mux_dev; /* the mux chip/device */ - u32 chan_id; /* the channel id */ - - int (*select)(struct i2c_adapter *, void *mux_dev, u32 chan_id); - int (*deselect)(struct i2c_adapter *, void *mux_dev, u32 chan_id); -}; - -static int i2c_mux_master_xfer(struct i2c_adapter *adap, - struct i2c_msg msgs[], int num) -{ - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; - int ret; - - /* Switch to the right mux port and perform the transfer. */ - - ret = priv->select(parent, priv->mux_dev, priv->chan_id); - if (ret >= 0) - ret = parent->algo->master_xfer(parent, msgs, num); - if (priv->deselect) - priv->deselect(parent, priv->mux_dev, priv->chan_id); - - return ret; -} - -static int i2c_mux_smbus_xfer(struct i2c_adapter *adap, - u16 addr, unsigned short flags, - char read_write, u8 command, - int size, union i2c_smbus_data *data) -{ - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; - int ret; - - /* Select the right mux port and perform the transfer. */ - - ret = priv->select(parent, priv->mux_dev, priv->chan_id); - if (ret >= 0) - ret = parent->algo->smbus_xfer(parent, addr, flags, - read_write, command, size, data); - if (priv->deselect) - priv->deselect(parent, priv->mux_dev, priv->chan_id); - - return ret; -} - -/* Return the parent's functionality */ -static u32 i2c_mux_functionality(struct i2c_adapter *adap) -{ - struct i2c_mux_priv *priv = adap->algo_data; - struct i2c_adapter *parent = priv->parent; - - return parent->algo->functionality(parent); -} - -struct i2c_adapter *i2c_add_mux_adapter(struct i2c_adapter *parent, - void *mux_dev, u32 force_nr, u32 chan_id, - int (*select) (struct i2c_adapter *, - void *, u32), - int (*deselect) (struct i2c_adapter *, - void *, u32)) -{ - struct i2c_mux_priv *priv; - int ret; - - priv = kzalloc(sizeof(struct i2c_mux_priv), GFP_KERNEL); - if (!priv) - return NULL; - - /* Set up private adapter data */ - priv->parent = parent; - priv->mux_dev = mux_dev; - priv->chan_id = chan_id; - priv->select = select; - priv->deselect = deselect; - - /* Need to do algo dynamically because we don't know ahead - * of time what sort of physical adapter we'll be dealing with. - */ - if (parent->algo->master_xfer) - priv->algo.master_xfer = i2c_mux_master_xfer; - if (parent->algo->smbus_xfer) - priv->algo.smbus_xfer = i2c_mux_smbus_xfer; - priv->algo.functionality = i2c_mux_functionality; - - /* Now fill out new adapter structure */ - snprintf(priv->adap.name, sizeof(priv->adap.name), - "i2c-%d-mux (chan_id %d)", i2c_adapter_id(parent), chan_id); - priv->adap.owner = THIS_MODULE; - priv->adap.algo = &priv->algo; - priv->adap.algo_data = priv; - priv->adap.dev.parent = &parent->dev; - - if (force_nr) { - priv->adap.nr = force_nr; - ret = i2c_add_numbered_adapter(&priv->adap); - } else { - ret = i2c_add_adapter(&priv->adap); - } - if (ret < 0) { - dev_err(&parent->dev, - "failed to add mux-adapter (error=%d)\n", - ret); - kfree(priv); - return NULL; - } - - dev_info(&parent->dev, "Added multiplexed i2c bus %d\n", - i2c_adapter_id(&priv->adap)); - - return &priv->adap; -} -EXPORT_SYMBOL_GPL(i2c_add_mux_adapter); - -int i2c_del_mux_adapter(struct i2c_adapter *adap) -{ - struct i2c_mux_priv *priv = adap->algo_data; - int ret; - - ret = i2c_del_adapter(adap); - if (ret < 0) - return ret; - kfree(priv); - - return 0; -} -EXPORT_SYMBOL_GPL(i2c_del_mux_adapter); - -MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); -MODULE_DESCRIPTION("I2C driver for multiplexed I2C busses"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/i2c/i2c-smbus.c b/ANDROID_3.4.5/drivers/i2c/i2c-smbus.c deleted file mode 100644 index 9836d08f..00000000 --- a/ANDROID_3.4.5/drivers/i2c/i2c-smbus.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * i2c-smbus.c - SMBus extensions to the I2C protocol - * - * Copyright (C) 2008 David Brownell - * Copyright (C) 2010 Jean Delvare <khali@linux-fr.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, - * MA 02110-1301 USA. - */ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/device.h> -#include <linux/interrupt.h> -#include <linux/workqueue.h> -#include <linux/i2c.h> -#include <linux/i2c-smbus.h> -#include <linux/slab.h> - -struct i2c_smbus_alert { - unsigned int alert_edge_triggered:1; - int irq; - struct work_struct alert; - struct i2c_client *ara; /* Alert response address */ -}; - -struct alert_data { - unsigned short addr; - u8 flag:1; -}; - -/* If this is the alerting device, notify its driver */ -static int smbus_do_alert(struct device *dev, void *addrp) -{ - struct i2c_client *client = i2c_verify_client(dev); - struct alert_data *data = addrp; - - if (!client || client->addr != data->addr) - return 0; - if (client->flags & I2C_CLIENT_TEN) - return 0; - - /* - * Drivers should either disable alerts, or provide at least - * a minimal handler. Lock so client->driver won't change. - */ - device_lock(dev); - if (client->driver) { - if (client->driver->alert) - client->driver->alert(client, data->flag); - else - dev_warn(&client->dev, "no driver alert()!\n"); - } else - dev_dbg(&client->dev, "alert with no driver\n"); - device_unlock(dev); - - /* Stop iterating after we find the device */ - return -EBUSY; -} - -/* - * The alert IRQ handler needs to hand work off to a task which can issue - * SMBus calls, because those sleeping calls can't be made in IRQ context. - */ -static void smbus_alert(struct work_struct *work) -{ - struct i2c_smbus_alert *alert; - struct i2c_client *ara; - unsigned short prev_addr = 0; /* Not a valid address */ - - alert = container_of(work, struct i2c_smbus_alert, alert); - ara = alert->ara; - - for (;;) { - s32 status; - struct alert_data data; - - /* - * Devices with pending alerts reply in address order, low - * to high, because of slave transmit arbitration. After - * responding, an SMBus device stops asserting SMBALERT#. - * - * Note that SMBus 2.0 reserves 10-bit addresess for future - * use. We neither handle them, nor try to use PEC here. - */ - status = i2c_smbus_read_byte(ara); - if (status < 0) - break; - - data.flag = status & 1; - data.addr = status >> 1; - - if (data.addr == prev_addr) { - dev_warn(&ara->dev, "Duplicate SMBALERT# from dev " - "0x%02x, skipping\n", data.addr); - break; - } - dev_dbg(&ara->dev, "SMBALERT# from dev 0x%02x, flag %d\n", - data.addr, data.flag); - - /* Notify driver for the device which issued the alert */ - device_for_each_child(&ara->adapter->dev, &data, - smbus_do_alert); - prev_addr = data.addr; - } - - /* We handled all alerts; re-enable level-triggered IRQs */ - if (!alert->alert_edge_triggered) - enable_irq(alert->irq); -} - -static irqreturn_t smbalert_irq(int irq, void *d) -{ - struct i2c_smbus_alert *alert = d; - - /* Disable level-triggered IRQs until we handle them */ - if (!alert->alert_edge_triggered) - disable_irq_nosync(irq); - - schedule_work(&alert->alert); - return IRQ_HANDLED; -} - -/* Setup SMBALERT# infrastructure */ -static int smbalert_probe(struct i2c_client *ara, - const struct i2c_device_id *id) -{ - struct i2c_smbus_alert_setup *setup = ara->dev.platform_data; - struct i2c_smbus_alert *alert; - struct i2c_adapter *adapter = ara->adapter; - int res; - - alert = kzalloc(sizeof(struct i2c_smbus_alert), GFP_KERNEL); - if (!alert) - return -ENOMEM; - - alert->alert_edge_triggered = setup->alert_edge_triggered; - alert->irq = setup->irq; - INIT_WORK(&alert->alert, smbus_alert); - alert->ara = ara; - - if (setup->irq > 0) { - res = devm_request_irq(&ara->dev, setup->irq, smbalert_irq, - 0, "smbus_alert", alert); - if (res) { - kfree(alert); - return res; - } - } - - i2c_set_clientdata(ara, alert); - dev_info(&adapter->dev, "supports SMBALERT#, %s trigger\n", - setup->alert_edge_triggered ? "edge" : "level"); - - return 0; -} - -/* IRQ resource is managed so it is freed automatically */ -static int smbalert_remove(struct i2c_client *ara) -{ - struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); - - cancel_work_sync(&alert->alert); - - kfree(alert); - return 0; -} - -static const struct i2c_device_id smbalert_ids[] = { - { "smbus_alert", 0 }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, smbalert_ids); - -static struct i2c_driver smbalert_driver = { - .driver = { - .name = "smbus_alert", - }, - .probe = smbalert_probe, - .remove = smbalert_remove, - .id_table = smbalert_ids, -}; - -/** - * i2c_setup_smbus_alert - Setup SMBus alert support - * @adapter: the target adapter - * @setup: setup data for the SMBus alert handler - * Context: can sleep - * - * Setup handling of the SMBus alert protocol on a given I2C bus segment. - * - * Handling can be done either through our IRQ handler, or by the - * adapter (from its handler, periodic polling, or whatever). - * - * NOTE that if we manage the IRQ, we *MUST* know if it's level or - * edge triggered in order to hand it to the workqueue correctly. - * If triggering the alert seems to wedge the system, you probably - * should have said it's level triggered. - * - * This returns the ara client, which should be saved for later use with - * i2c_handle_smbus_alert() and ultimately i2c_unregister_device(); or NULL - * to indicate an error. - */ -struct i2c_client *i2c_setup_smbus_alert(struct i2c_adapter *adapter, - struct i2c_smbus_alert_setup *setup) -{ - struct i2c_board_info ara_board_info = { - I2C_BOARD_INFO("smbus_alert", 0x0c), - .platform_data = setup, - }; - - return i2c_new_device(adapter, &ara_board_info); -} -EXPORT_SYMBOL_GPL(i2c_setup_smbus_alert); - -/** - * i2c_handle_smbus_alert - Handle an SMBus alert - * @ara: the ARA client on the relevant adapter - * Context: can't sleep - * - * Helper function to be called from an I2C bus driver's interrupt - * handler. It will schedule the alert work, in turn calling the - * corresponding I2C device driver's alert function. - * - * It is assumed that ara is a valid i2c client previously returned by - * i2c_setup_smbus_alert(). - */ -int i2c_handle_smbus_alert(struct i2c_client *ara) -{ - struct i2c_smbus_alert *alert = i2c_get_clientdata(ara); - - return schedule_work(&alert->alert); -} -EXPORT_SYMBOL_GPL(i2c_handle_smbus_alert); - -static int __init i2c_smbus_init(void) -{ - return i2c_add_driver(&smbalert_driver); -} - -static void __exit i2c_smbus_exit(void) -{ - i2c_del_driver(&smbalert_driver); -} - -module_init(i2c_smbus_init); -module_exit(i2c_smbus_exit); - -MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>"); -MODULE_DESCRIPTION("SMBus protocol extensions support"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/i2c/muxes/Kconfig b/ANDROID_3.4.5/drivers/i2c/muxes/Kconfig deleted file mode 100644 index 90b7a016..00000000 --- a/ANDROID_3.4.5/drivers/i2c/muxes/Kconfig +++ /dev/null @@ -1,40 +0,0 @@ -# -# Multiplexer I2C chip drivers configuration -# - -menu "Multiplexer I2C Chip support" - depends on I2C_MUX - -config I2C_MUX_GPIO - tristate "GPIO-based I2C multiplexer" - depends on GENERIC_GPIO - help - If you say yes to this option, support will be included for a - GPIO based I2C multiplexer. This driver provides access to - I2C busses connected through a MUX, which is controlled - through GPIO pins. - - This driver can also be built as a module. If so, the module - will be called gpio-i2cmux. - -config I2C_MUX_PCA9541 - tristate "NXP PCA9541 I2C Master Selector" - depends on EXPERIMENTAL - help - If you say yes here you get support for the NXP PCA9541 - I2C Master Selector. - - This driver can also be built as a module. If so, the module - will be called pca9541. - -config I2C_MUX_PCA954x - tristate "Philips PCA954x I2C Mux/switches" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Philips PCA954x - I2C mux/switch devices. - - This driver can also be built as a module. If so, the module - will be called pca954x. - -endmenu diff --git a/ANDROID_3.4.5/drivers/i2c/muxes/Makefile b/ANDROID_3.4.5/drivers/i2c/muxes/Makefile deleted file mode 100644 index 4640436e..00000000 --- a/ANDROID_3.4.5/drivers/i2c/muxes/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for multiplexer I2C chip drivers. - -obj-$(CONFIG_I2C_MUX_GPIO) += gpio-i2cmux.o -obj-$(CONFIG_I2C_MUX_PCA9541) += pca9541.o -obj-$(CONFIG_I2C_MUX_PCA954x) += pca954x.o - -ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG diff --git a/ANDROID_3.4.5/drivers/i2c/muxes/gpio-i2cmux.c b/ANDROID_3.4.5/drivers/i2c/muxes/gpio-i2cmux.c deleted file mode 100644 index e5fa695e..00000000 --- a/ANDROID_3.4.5/drivers/i2c/muxes/gpio-i2cmux.c +++ /dev/null @@ -1,173 +0,0 @@ -/* - * I2C multiplexer using GPIO API - * - * Peter Korsgaard <peter.korsgaard@barco.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include <linux/i2c.h> -#include <linux/i2c-mux.h> -#include <linux/gpio-i2cmux.h> -#include <linux/platform_device.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/gpio.h> - -struct gpiomux { - struct i2c_adapter *parent; - struct i2c_adapter **adap; /* child busses */ - struct gpio_i2cmux_platform_data data; -}; - -static void gpiomux_set(const struct gpiomux *mux, unsigned val) -{ - int i; - - for (i = 0; i < mux->data.n_gpios; i++) - gpio_set_value(mux->data.gpios[i], val & (1 << i)); -} - -static int gpiomux_select(struct i2c_adapter *adap, void *data, u32 chan) -{ - struct gpiomux *mux = data; - - gpiomux_set(mux, mux->data.values[chan]); - - return 0; -} - -static int gpiomux_deselect(struct i2c_adapter *adap, void *data, u32 chan) -{ - struct gpiomux *mux = data; - - gpiomux_set(mux, mux->data.idle); - - return 0; -} - -static int __devinit gpiomux_probe(struct platform_device *pdev) -{ - struct gpiomux *mux; - struct gpio_i2cmux_platform_data *pdata; - struct i2c_adapter *parent; - int (*deselect) (struct i2c_adapter *, void *, u32); - unsigned initial_state; - int i, ret; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "Missing platform data\n"); - return -ENODEV; - } - - parent = i2c_get_adapter(pdata->parent); - if (!parent) { - dev_err(&pdev->dev, "Parent adapter (%d) not found\n", - pdata->parent); - return -ENODEV; - } - - mux = kzalloc(sizeof(*mux), GFP_KERNEL); - if (!mux) { - ret = -ENOMEM; - goto alloc_failed; - } - - mux->parent = parent; - mux->data = *pdata; - mux->adap = kzalloc(sizeof(struct i2c_adapter *) * pdata->n_values, - GFP_KERNEL); - if (!mux->adap) { - ret = -ENOMEM; - goto alloc_failed2; - } - - if (pdata->idle != GPIO_I2CMUX_NO_IDLE) { - initial_state = pdata->idle; - deselect = gpiomux_deselect; - } else { - initial_state = pdata->values[0]; - deselect = NULL; - } - - for (i = 0; i < pdata->n_gpios; i++) { - ret = gpio_request(pdata->gpios[i], "gpio-i2cmux"); - if (ret) - goto err_request_gpio; - gpio_direction_output(pdata->gpios[i], - initial_state & (1 << i)); - } - - for (i = 0; i < pdata->n_values; i++) { - u32 nr = pdata->base_nr ? (pdata->base_nr + i) : 0; - - mux->adap[i] = i2c_add_mux_adapter(parent, mux, nr, i, - gpiomux_select, deselect); - if (!mux->adap[i]) { - ret = -ENODEV; - dev_err(&pdev->dev, "Failed to add adapter %d\n", i); - goto add_adapter_failed; - } - } - - dev_info(&pdev->dev, "%d port mux on %s adapter\n", - pdata->n_values, parent->name); - - platform_set_drvdata(pdev, mux); - - return 0; - -add_adapter_failed: - for (; i > 0; i--) - i2c_del_mux_adapter(mux->adap[i - 1]); - i = pdata->n_gpios; -err_request_gpio: - for (; i > 0; i--) - gpio_free(pdata->gpios[i - 1]); - kfree(mux->adap); -alloc_failed2: - kfree(mux); -alloc_failed: - i2c_put_adapter(parent); - - return ret; -} - -static int __devexit gpiomux_remove(struct platform_device *pdev) -{ - struct gpiomux *mux = platform_get_drvdata(pdev); - int i; - - for (i = 0; i < mux->data.n_values; i++) - i2c_del_mux_adapter(mux->adap[i]); - - for (i = 0; i < mux->data.n_gpios; i++) - gpio_free(mux->data.gpios[i]); - - platform_set_drvdata(pdev, NULL); - i2c_put_adapter(mux->parent); - kfree(mux->adap); - kfree(mux); - - return 0; -} - -static struct platform_driver gpiomux_driver = { - .probe = gpiomux_probe, - .remove = __devexit_p(gpiomux_remove), - .driver = { - .owner = THIS_MODULE, - .name = "gpio-i2cmux", - }, -}; - -module_platform_driver(gpiomux_driver); - -MODULE_DESCRIPTION("GPIO-based I2C multiplexer driver"); -MODULE_AUTHOR("Peter Korsgaard <peter.korsgaard@barco.com>"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-i2cmux"); diff --git a/ANDROID_3.4.5/drivers/i2c/muxes/pca9541.c b/ANDROID_3.4.5/drivers/i2c/muxes/pca9541.c deleted file mode 100644 index e0df9b6c..00000000 --- a/ANDROID_3.4.5/drivers/i2c/muxes/pca9541.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * I2C multiplexer driver for PCA9541 bus master selector - * - * Copyright (c) 2010 Ericsson AB. - * - * Author: Guenter Roeck <guenter.roeck@ericsson.com> - * - * Derived from: - * pca954x.c - * - * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> - * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/jiffies.h> -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/i2c-mux.h> - -#include <linux/i2c/pca954x.h> - -/* - * The PCA9541 is a bus master selector. It supports two I2C masters connected - * to a single slave bus. - * - * Before each bus transaction, a master has to acquire bus ownership. After the - * transaction is complete, bus ownership has to be released. This fits well - * into the I2C multiplexer framework, which provides select and release - * functions for this purpose. For this reason, this driver is modeled as - * single-channel I2C bus multiplexer. - * - * This driver assumes that the two bus masters are controlled by two different - * hosts. If a single host controls both masters, platform code has to ensure - * that only one of the masters is instantiated at any given time. - */ - -#define PCA9541_CONTROL 0x01 -#define PCA9541_ISTAT 0x02 - -#define PCA9541_CTL_MYBUS (1 << 0) -#define PCA9541_CTL_NMYBUS (1 << 1) -#define PCA9541_CTL_BUSON (1 << 2) -#define PCA9541_CTL_NBUSON (1 << 3) -#define PCA9541_CTL_BUSINIT (1 << 4) -#define PCA9541_CTL_TESTON (1 << 6) -#define PCA9541_CTL_NTESTON (1 << 7) - -#define PCA9541_ISTAT_INTIN (1 << 0) -#define PCA9541_ISTAT_BUSINIT (1 << 1) -#define PCA9541_ISTAT_BUSOK (1 << 2) -#define PCA9541_ISTAT_BUSLOST (1 << 3) -#define PCA9541_ISTAT_MYTEST (1 << 6) -#define PCA9541_ISTAT_NMYTEST (1 << 7) - -#define BUSON (PCA9541_CTL_BUSON | PCA9541_CTL_NBUSON) -#define MYBUS (PCA9541_CTL_MYBUS | PCA9541_CTL_NMYBUS) -#define mybus(x) (!((x) & MYBUS) || ((x) & MYBUS) == MYBUS) -#define busoff(x) (!((x) & BUSON) || ((x) & BUSON) == BUSON) - -/* arbitration timeouts, in jiffies */ -#define ARB_TIMEOUT (HZ / 8) /* 125 ms until forcing bus ownership */ -#define ARB2_TIMEOUT (HZ / 4) /* 250 ms until acquisition failure */ - -/* arbitration retry delays, in us */ -#define SELECT_DELAY_SHORT 50 -#define SELECT_DELAY_LONG 1000 - -struct pca9541 { - struct i2c_adapter *mux_adap; - unsigned long select_timeout; - unsigned long arb_timeout; -}; - -static const struct i2c_device_id pca9541_id[] = { - {"pca9541", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, pca9541_id); - -/* - * Write to chip register. Don't use i2c_transfer()/i2c_smbus_xfer() - * as they will try to lock the adapter a second time. - */ -static int pca9541_reg_write(struct i2c_client *client, u8 command, u8 val) -{ - struct i2c_adapter *adap = client->adapter; - int ret; - - if (adap->algo->master_xfer) { - struct i2c_msg msg; - char buf[2]; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 2; - buf[0] = command; - buf[1] = val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - } else { - union i2c_smbus_data data; - - data.byte = val; - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_WRITE, - command, - I2C_SMBUS_BYTE_DATA, &data); - } - - return ret; -} - -/* - * Read from chip register. Don't use i2c_transfer()/i2c_smbus_xfer() - * as they will try to lock adapter a second time. - */ -static int pca9541_reg_read(struct i2c_client *client, u8 command) -{ - struct i2c_adapter *adap = client->adapter; - int ret; - u8 val; - - if (adap->algo->master_xfer) { - struct i2c_msg msg[2] = { - { - .addr = client->addr, - .flags = 0, - .len = 1, - .buf = &command - }, - { - .addr = client->addr, - .flags = I2C_M_RD, - .len = 1, - .buf = &val - } - }; - ret = adap->algo->master_xfer(adap, msg, 2); - if (ret == 2) - ret = val; - else if (ret >= 0) - ret = -EIO; - } else { - union i2c_smbus_data data; - - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_READ, - command, - I2C_SMBUS_BYTE_DATA, &data); - if (!ret) - ret = data.byte; - } - return ret; -} - -/* - * Arbitration management functions - */ - -/* Release bus. Also reset NTESTON and BUSINIT if it was set. */ -static void pca9541_release_bus(struct i2c_client *client) -{ - int reg; - - reg = pca9541_reg_read(client, PCA9541_CONTROL); - if (reg >= 0 && !busoff(reg) && mybus(reg)) - pca9541_reg_write(client, PCA9541_CONTROL, - (reg & PCA9541_CTL_NBUSON) >> 1); -} - -/* - * Arbitration is defined as a two-step process. A bus master can only activate - * the slave bus if it owns it; otherwise it has to request ownership first. - * This multi-step process ensures that access contention is resolved - * gracefully. - * - * Bus Ownership Other master Action - * state requested access - * ---------------------------------------------------- - * off - yes wait for arbitration timeout or - * for other master to drop request - * off no no take ownership - * off yes no turn on bus - * on yes - done - * on no - wait for arbitration timeout or - * for other master to release bus - * - * The main contention point occurs if the slave bus is off and both masters - * request ownership at the same time. In this case, one master will turn on - * the slave bus, believing that it owns it. The other master will request - * bus ownership. Result is that the bus is turned on, and master which did - * _not_ own the slave bus before ends up owning it. - */ - -/* Control commands per PCA9541 datasheet */ -static const u8 pca9541_control[16] = { - 4, 0, 1, 5, 4, 4, 5, 5, 0, 0, 1, 1, 0, 4, 5, 1 -}; - -/* - * Channel arbitration - * - * Return values: - * <0: error - * 0 : bus not acquired - * 1 : bus acquired - */ -static int pca9541_arbitrate(struct i2c_client *client) -{ - struct pca9541 *data = i2c_get_clientdata(client); - int reg; - - reg = pca9541_reg_read(client, PCA9541_CONTROL); - if (reg < 0) - return reg; - - if (busoff(reg)) { - int istat; - /* - * Bus is off. Request ownership or turn it on unless - * other master requested ownership. - */ - istat = pca9541_reg_read(client, PCA9541_ISTAT); - if (!(istat & PCA9541_ISTAT_NMYTEST) - || time_is_before_eq_jiffies(data->arb_timeout)) { - /* - * Other master did not request ownership, - * or arbitration timeout expired. Take the bus. - */ - pca9541_reg_write(client, - PCA9541_CONTROL, - pca9541_control[reg & 0x0f] - | PCA9541_CTL_NTESTON); - data->select_timeout = SELECT_DELAY_SHORT; - } else { - /* - * Other master requested ownership. - * Set extra long timeout to give it time to acquire it. - */ - data->select_timeout = SELECT_DELAY_LONG * 2; - } - } else if (mybus(reg)) { - /* - * Bus is on, and we own it. We are done with acquisition. - * Reset NTESTON and BUSINIT, then return success. - */ - if (reg & (PCA9541_CTL_NTESTON | PCA9541_CTL_BUSINIT)) - pca9541_reg_write(client, - PCA9541_CONTROL, - reg & ~(PCA9541_CTL_NTESTON - | PCA9541_CTL_BUSINIT)); - return 1; - } else { - /* - * Other master owns the bus. - * If arbitration timeout has expired, force ownership. - * Otherwise request it. - */ - data->select_timeout = SELECT_DELAY_LONG; - if (time_is_before_eq_jiffies(data->arb_timeout)) { - /* Time is up, take the bus and reset it. */ - pca9541_reg_write(client, - PCA9541_CONTROL, - pca9541_control[reg & 0x0f] - | PCA9541_CTL_BUSINIT - | PCA9541_CTL_NTESTON); - } else { - /* Request bus ownership if needed */ - if (!(reg & PCA9541_CTL_NTESTON)) - pca9541_reg_write(client, - PCA9541_CONTROL, - reg | PCA9541_CTL_NTESTON); - } - } - return 0; -} - -static int pca9541_select_chan(struct i2c_adapter *adap, void *client, u32 chan) -{ - struct pca9541 *data = i2c_get_clientdata(client); - int ret; - unsigned long timeout = jiffies + ARB2_TIMEOUT; - /* give up after this time */ - - data->arb_timeout = jiffies + ARB_TIMEOUT; - /* force bus ownership after this time */ - - do { - ret = pca9541_arbitrate(client); - if (ret) - return ret < 0 ? ret : 0; - - if (data->select_timeout == SELECT_DELAY_SHORT) - udelay(data->select_timeout); - else - msleep(data->select_timeout / 1000); - } while (time_is_after_eq_jiffies(timeout)); - - return -ETIMEDOUT; -} - -static int pca9541_release_chan(struct i2c_adapter *adap, - void *client, u32 chan) -{ - pca9541_release_bus(client); - return 0; -} - -/* - * I2C init/probing/exit functions - */ -static int pca9541_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adap = client->adapter; - struct pca954x_platform_data *pdata = client->dev.platform_data; - struct pca9541 *data; - int force; - int ret = -ENODEV; - - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE_DATA)) - goto err; - - data = kzalloc(sizeof(struct pca9541), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - i2c_set_clientdata(client, data); - - /* - * I2C accesses are unprotected here. - * We have to lock the adapter before releasing the bus. - */ - i2c_lock_adapter(adap); - pca9541_release_bus(client); - i2c_unlock_adapter(adap); - - /* Create mux adapter */ - - force = 0; - if (pdata) - force = pdata->modes[0].adap_id; - data->mux_adap = i2c_add_mux_adapter(adap, client, force, 0, - pca9541_select_chan, - pca9541_release_chan); - - if (data->mux_adap == NULL) { - dev_err(&client->dev, "failed to register master selector\n"); - goto exit_free; - } - - dev_info(&client->dev, "registered master selector for I2C %s\n", - client->name); - - return 0; - -exit_free: - kfree(data); -err: - return ret; -} - -static int pca9541_remove(struct i2c_client *client) -{ - struct pca9541 *data = i2c_get_clientdata(client); - - i2c_del_mux_adapter(data->mux_adap); - - kfree(data); - return 0; -} - -static struct i2c_driver pca9541_driver = { - .driver = { - .name = "pca9541", - .owner = THIS_MODULE, - }, - .probe = pca9541_probe, - .remove = pca9541_remove, - .id_table = pca9541_id, -}; - -module_i2c_driver(pca9541_driver); - -MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>"); -MODULE_DESCRIPTION("PCA9541 I2C master selector driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/i2c/muxes/pca954x.c b/ANDROID_3.4.5/drivers/i2c/muxes/pca954x.c deleted file mode 100644 index 0e37ef27..00000000 --- a/ANDROID_3.4.5/drivers/i2c/muxes/pca954x.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * I2C multiplexer - * - * Copyright (c) 2008-2009 Rodolfo Giometti <giometti@linux.it> - * Copyright (c) 2008-2009 Eurotech S.p.A. <info@eurotech.it> - * - * This module supports the PCA954x series of I2C multiplexer/switch chips - * made by Philips Semiconductors. - * This includes the: - * PCA9540, PCA9542, PCA9543, PCA9544, PCA9545, PCA9546, PCA9547 - * and PCA9548. - * - * These chips are all controlled via the I2C bus itself, and all have a - * single 8-bit register. The upstream "parent" bus fans out to two, - * four, or eight downstream busses or channels; which of these - * are selected is determined by the chip type and register contents. A - * mux can select only one sub-bus at a time; a switch can select any - * combination simultaneously. - * - * Based on: - * pca954x.c from Kumar Gala <galak@kernel.crashing.org> - * Copyright (C) 2006 - * - * Based on: - * pca954x.c from Ken Harrenstien - * Copyright (C) 2004 Google, Inc. (Ken Harrenstien) - * - * Based on: - * i2c-virtual_cb.c from Brian Kuschak <bkuschak@yahoo.com> - * and - * pca9540.c from Jean Delvare <khali@linux-fr.org>. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include <linux/module.h> -#include <linux/init.h> -#include <linux/slab.h> -#include <linux/device.h> -#include <linux/i2c.h> -#include <linux/i2c-mux.h> - -#include <linux/i2c/pca954x.h> - -#define PCA954X_MAX_NCHANS 8 - -enum pca_type { - pca_9540, - pca_9542, - pca_9543, - pca_9544, - pca_9545, - pca_9546, - pca_9547, - pca_9548, -}; - -struct pca954x { - enum pca_type type; - struct i2c_adapter *virt_adaps[PCA954X_MAX_NCHANS]; - - u8 last_chan; /* last register value */ -}; - -struct chip_desc { - u8 nchans; - u8 enable; /* used for muxes only */ - enum muxtype { - pca954x_ismux = 0, - pca954x_isswi - } muxtype; -}; - -/* Provide specs for the PCA954x types we know about */ -static const struct chip_desc chips[] = { - [pca_9540] = { - .nchans = 2, - .enable = 0x4, - .muxtype = pca954x_ismux, - }, - [pca_9543] = { - .nchans = 2, - .muxtype = pca954x_isswi, - }, - [pca_9544] = { - .nchans = 4, - .enable = 0x4, - .muxtype = pca954x_ismux, - }, - [pca_9545] = { - .nchans = 4, - .muxtype = pca954x_isswi, - }, - [pca_9547] = { - .nchans = 8, - .enable = 0x8, - .muxtype = pca954x_ismux, - }, - [pca_9548] = { - .nchans = 8, - .muxtype = pca954x_isswi, - }, -}; - -static const struct i2c_device_id pca954x_id[] = { - { "pca9540", pca_9540 }, - { "pca9542", pca_9540 }, - { "pca9543", pca_9543 }, - { "pca9544", pca_9544 }, - { "pca9545", pca_9545 }, - { "pca9546", pca_9545 }, - { "pca9547", pca_9547 }, - { "pca9548", pca_9548 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pca954x_id); - -/* Write to mux register. Don't use i2c_transfer()/i2c_smbus_xfer() - for this as they will try to lock adapter a second time */ -static int pca954x_reg_write(struct i2c_adapter *adap, - struct i2c_client *client, u8 val) -{ - int ret = -ENODEV; - - if (adap->algo->master_xfer) { - struct i2c_msg msg; - char buf[1]; - - msg.addr = client->addr; - msg.flags = 0; - msg.len = 1; - buf[0] = val; - msg.buf = buf; - ret = adap->algo->master_xfer(adap, &msg, 1); - } else { - union i2c_smbus_data data; - ret = adap->algo->smbus_xfer(adap, client->addr, - client->flags, - I2C_SMBUS_WRITE, - val, I2C_SMBUS_BYTE, &data); - } - - return ret; -} - -static int pca954x_select_chan(struct i2c_adapter *adap, - void *client, u32 chan) -{ - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - u8 regval; - int ret = 0; - - /* we make switches look like muxes, not sure how to be smarter */ - if (chip->muxtype == pca954x_ismux) - regval = chan | chip->enable; - else - regval = 1 << chan; - - /* Only select the channel if its different from the last channel */ - if (data->last_chan != regval) { - ret = pca954x_reg_write(adap, client, regval); - data->last_chan = regval; - } - - return ret; -} - -static int pca954x_deselect_mux(struct i2c_adapter *adap, - void *client, u32 chan) -{ - struct pca954x *data = i2c_get_clientdata(client); - - /* Deselect active channel */ - data->last_chan = 0; - return pca954x_reg_write(adap, client, data->last_chan); -} - -/* - * I2C init/probing/exit functions - */ -static int pca954x_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adap = to_i2c_adapter(client->dev.parent); - struct pca954x_platform_data *pdata = client->dev.platform_data; - int num, force; - struct pca954x *data; - int ret = -ENODEV; - - if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) - goto err; - - data = kzalloc(sizeof(struct pca954x), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto err; - } - - i2c_set_clientdata(client, data); - - /* Write the mux register at addr to verify - * that the mux is in fact present. This also - * initializes the mux to disconnected state. - */ - if (i2c_smbus_write_byte(client, 0) < 0) { - dev_warn(&client->dev, "probe failed\n"); - goto exit_free; - } - - data->type = id->driver_data; - data->last_chan = 0; /* force the first selection */ - - /* Now create an adapter for each channel */ - for (num = 0; num < chips[data->type].nchans; num++) { - force = 0; /* dynamic adap number */ - if (pdata) { - if (num < pdata->num_modes) - /* force static number */ - force = pdata->modes[num].adap_id; - else - /* discard unconfigured channels */ - break; - } - - data->virt_adaps[num] = - i2c_add_mux_adapter(adap, client, - force, num, pca954x_select_chan, - (pdata && pdata->modes[num].deselect_on_exit) - ? pca954x_deselect_mux : NULL); - - if (data->virt_adaps[num] == NULL) { - ret = -ENODEV; - dev_err(&client->dev, - "failed to register multiplexed adapter" - " %d as bus %d\n", num, force); - goto virt_reg_failed; - } - } - - dev_info(&client->dev, - "registered %d multiplexed busses for I2C %s %s\n", - num, chips[data->type].muxtype == pca954x_ismux - ? "mux" : "switch", client->name); - - return 0; - -virt_reg_failed: - for (num--; num >= 0; num--) - i2c_del_mux_adapter(data->virt_adaps[num]); -exit_free: - kfree(data); -err: - return ret; -} - -static int pca954x_remove(struct i2c_client *client) -{ - struct pca954x *data = i2c_get_clientdata(client); - const struct chip_desc *chip = &chips[data->type]; - int i, err; - - for (i = 0; i < chip->nchans; ++i) - if (data->virt_adaps[i]) { - err = i2c_del_mux_adapter(data->virt_adaps[i]); - if (err) - return err; - data->virt_adaps[i] = NULL; - } - - kfree(data); - return 0; -} - -static struct i2c_driver pca954x_driver = { - .driver = { - .name = "pca954x", - .owner = THIS_MODULE, - }, - .probe = pca954x_probe, - .remove = pca954x_remove, - .id_table = pca954x_id, -}; - -module_i2c_driver(pca954x_driver); - -MODULE_AUTHOR("Rodolfo Giometti <giometti@linux.it>"); -MODULE_DESCRIPTION("PCA954x I2C mux/switch driver"); -MODULE_LICENSE("GPL v2"); |