summaryrefslogtreecommitdiffstats
path: root/drivers/i2c
diff options
context:
space:
mode:
authorMagnus Damm <damm@opensource.se>2010-03-11 11:06:02 +0100
committerPaul Mundt <lethal@linux-sh.org>2010-04-07 09:19:47 +0200
commit962b6032c889ed9a5f0bdb7052d9318067a75bda (patch)
treeb65470944ebdc16235225997d01d97d92d82f1c4 /drivers/i2c
parenti2c: i2c-sh_mobile register access code break out (diff)
downloadlinux-962b6032c889ed9a5f0bdb7052d9318067a75bda.tar.xz
linux-962b6032c889ed9a5f0bdb7052d9318067a75bda.zip
i2c: i2c-sh_mobile support for new ICIC bits
Add support for a new version of the IIC block found in the SH-Mobile ARM line of processors. Prototype patch written by Nishimoto-san. Tested on sh7377 and sh7372. Signed-off-by: NISHIMOTO Hiroki <nishimoto.hiroki@renesas.com> Signed-off-by: Magnus Damm <damm@opensource.se> Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'drivers/i2c')
-rw-r--r--drivers/i2c/busses/i2c-sh_mobile.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-sh_mobile.c b/drivers/i2c/busses/i2c-sh_mobile.c
index d2fabd9dbf80..598c49acaeb5 100644
--- a/drivers/i2c/busses/i2c-sh_mobile.c
+++ b/drivers/i2c/busses/i2c-sh_mobile.c
@@ -119,8 +119,10 @@ struct sh_mobile_i2c_data {
struct i2c_adapter adap;
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;
@@ -129,6 +131,8 @@ struct sh_mobile_i2c_data {
int sr;
};
+#define IIC_FLAG_HAS_ICIC67 (1 << 0)
+
#define NORMAL_SPEED 100000 /* FAST_SPEED 400000 */
/* Register offsets */
@@ -155,6 +159,8 @@ struct sh_mobile_i2c_data {
#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
@@ -162,6 +168,9 @@ struct sh_mobile_i2c_data {
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);
}
@@ -203,6 +212,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
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;
@@ -212,6 +229,14 @@ static void activate_ch(struct sh_mobile_i2c_data *pd)
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);
@@ -592,6 +617,12 @@ static int sh_mobile_i2c_probe(struct platform_device *dev)
goto err_irq;
}
+ /* 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