summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/i2c-s3c2410.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 14:38:53 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 14:38:53 -0700
commit99bece775f988a4ee21ad3db9fd413caf1704ff6 (patch)
tree5975cdcd92301e54dfe1424ec5d008898b5c9331 /drivers/i2c/busses/i2c-s3c2410.c
parent736a2dd2571ac56b11ed95a7814d838d5311be04 (diff)
parentc39e8e4354ce4daf23336de5daa28a3b01f00aa6 (diff)
Merge branch 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux
Pull i2c changes from Wolfram Sang: - an arbitration driver. While the driver is quite simple, it caused discussion if we need additional arbitration on top of the one specified in the I2C standard. Conclusion is that I accept a few generic mechanisms, but not very specific ones. - the core lost the detach_adapter() call. It has no users anymore and was in the way for other cleanups. attach_adapter() is sadly still there since there are users waiting to be converted. - the core gained a bus recovery infrastructure. I2C defines a way to recover if the data line is stalled. This mechanism is now in the core and drivers can now pass some data to make use of it. - bigger driver cleanups for designware, s3c2410 - removing superfluous refcounting from drivers - removing Ben Dooks as second maintainer due to inactivity. Thanks for all your work so far, Ben! - bugfixes, feature additions, devicetree fixups, simplifications... * 'i2c/for-next' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux: (38 commits) i2c: xiic: must always write 16-bit words to TX_FIFO i2c: octeon: use HZ in timeout value i2c: octeon: Fix i2c fail problem when a process is terminated by a signal i2c: designware-pci: drop superfluous {get|put}_device i2c: designware-plat: drop superfluous {get|put}_device i2c: davinci: drop superfluous {get|put}_device MAINTAINERS: Ben Dooks is inactive regarding I2C i2c: mux: Add i2c-arb-gpio-challenge 'mux' driver i2c: at91: convert to dma_request_slave_channel_compat() i2c: mxs: do error checking and handling in PIO mode i2c: mxs: remove races in PIO code i2c-designware: switch to use runtime PM autosuspend i2c-designware: use usleep_range() in the busy-loop i2c-designware: enable/disable the controller properly i2c-designware: use dynamic adapter numbering on Lynxpoint i2c-designware-pci: use managed functions pcim_* and devm_* i2c-designware-pci: use dev_err() instead of printk() i2c-designware: move to managed functions (devm_*) i2c: remove CONFIG_HOTPLUG ifdefs i2c: s3c2410: Add SMBus emulation for block read ...
Diffstat (limited to 'drivers/i2c/busses/i2c-s3c2410.c')
-rw-r--r--drivers/i2c/busses/i2c-s3c2410.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c
index f6b880ba1932..6e8ee92ab553 100644
--- a/drivers/i2c/busses/i2c-s3c2410.c
+++ b/drivers/i2c/busses/i2c-s3c2410.c
@@ -42,9 +42,46 @@
#include <asm/irq.h>
-#include <plat/regs-iic.h>
#include <linux/platform_data/i2c-s3c2410.h>
+/* see s3c2410x user guide, v1.1, section 9 (p447) for more info */
+
+#define S3C2410_IICCON 0x00
+#define S3C2410_IICSTAT 0x04
+#define S3C2410_IICADD 0x08
+#define S3C2410_IICDS 0x0C
+#define S3C2440_IICLC 0x10
+
+#define S3C2410_IICCON_ACKEN (1 << 7)
+#define S3C2410_IICCON_TXDIV_16 (0 << 6)
+#define S3C2410_IICCON_TXDIV_512 (1 << 6)
+#define S3C2410_IICCON_IRQEN (1 << 5)
+#define S3C2410_IICCON_IRQPEND (1 << 4)
+#define S3C2410_IICCON_SCALE(x) ((x) & 0xf)
+#define S3C2410_IICCON_SCALEMASK (0xf)
+
+#define S3C2410_IICSTAT_MASTER_RX (2 << 6)
+#define S3C2410_IICSTAT_MASTER_TX (3 << 6)
+#define S3C2410_IICSTAT_SLAVE_RX (0 << 6)
+#define S3C2410_IICSTAT_SLAVE_TX (1 << 6)
+#define S3C2410_IICSTAT_MODEMASK (3 << 6)
+
+#define S3C2410_IICSTAT_START (1 << 5)
+#define S3C2410_IICSTAT_BUSBUSY (1 << 5)
+#define S3C2410_IICSTAT_TXRXEN (1 << 4)
+#define S3C2410_IICSTAT_ARBITR (1 << 3)
+#define S3C2410_IICSTAT_ASSLAVE (1 << 2)
+#define S3C2410_IICSTAT_ADDR0 (1 << 1)
+#define S3C2410_IICSTAT_LASTBIT (1 << 0)
+
+#define S3C2410_IICLC_SDA_DELAY0 (0 << 0)
+#define S3C2410_IICLC_SDA_DELAY5 (1 << 0)
+#define S3C2410_IICLC_SDA_DELAY10 (2 << 0)
+#define S3C2410_IICLC_SDA_DELAY15 (3 << 0)
+#define S3C2410_IICLC_SDA_DELAY_MASK (3 << 0)
+
+#define S3C2410_IICLC_FILTER_ON (1 << 2)
+
/* Treat S3C2410 as baseline hardware, anything else is supported via quirks */
#define QUIRK_S3C2440 (1 << 0)
#define QUIRK_HDMIPHY (1 << 1)
@@ -309,6 +346,12 @@ static inline int is_lastmsg(struct s3c24xx_i2c *i2c)
static inline int is_msglast(struct s3c24xx_i2c *i2c)
{
+ /* msg->len is always 1 for the first byte of smbus block read.
+ * Actual length will be read from slave. More bytes will be
+ * read according to the length then. */
+ if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
+ return 0;
+
return i2c->msg_ptr == i2c->msg->len-1;
}
@@ -448,6 +491,9 @@ static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat)
byte = readb(i2c->regs + S3C2410_IICDS);
i2c->msg->buf[i2c->msg_ptr++] = byte;
+ /* Add actual length to read for smbus block read */
+ if (i2c->msg->flags & I2C_M_RECV_LEN && i2c->msg->len == 1)
+ i2c->msg->len += byte;
prepare_read:
if (is_msglast(i2c)) {
/* last byte of buffer */