Skip to contentSkip to conversation

intel_mid_i2c: I2C driver support with IRQs

PATCH New Alan Cox 1 participant 6 messages Jun 17, 2010 1 message not in the archive

Subsystems (2)
lore
Share & tools
lore

Alan Cox

author
#0 lore raw

cover intel_mid_i2c: I2C driver support with IRQs

This series enables the I2C on the Intel MID platforms. I've kept it as a series of five patches to keep ownership and history. The first two add the x86 irq handling and the driver, the rest then polish it up.

Alan

---

Alan Cox (2):
intel_mid_i2c: minor cleanups
intel_mid_i2c: Do a bit of compaction and tidying

Alek Du (1):
gpio: implement x86 gpio_to_irq convert function

Wen Wang (2):
intel_mid_i2c: Minor changes after verification
intel_mid_i2c: I2C driver supporting Moorestown and Medfield platform

 arch/x86/include/asm/gpio.h   |    5 
 drivers/i2c/busses/Kconfig    |    9 
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-mrst.c |  902 +++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-mrst.h |  269 ++++++++++++
 5 files changed, 1182 insertions(+), 4 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-mrst.c
 create mode 100644 drivers/i2c/busses/i2c-mrst.h

A message that is not in the archive (sent off-list or not yet received): 20100617140352.17861.29664.stgit-bi+AKbBUZKY6gyzm1THtWbp2dZbC/[email protected]

author
#2 lore raw

PATCH 1/5 gpio: implement x86 gpio_to_irq convert function

From: Alek Du <[email protected]>

---

 arch/x86/include/asm/gpio.h |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)
arch/x86/include/asm/gpio.h +1 -4
index 49dbfdf..91d915a 100644
@@ -38,12 +38,9 @@ static inline int gpio_cansleep(unsigned int gpio)
 	return __gpio_cansleep(gpio);
 }
 
-/*
- * Not implemented, yet.
- */
 static inline int gpio_to_irq(unsigned int gpio)
 {
-	return -ENOSYS;
+	return __gpio_to_irq(gpio);
 }
 
 static inline int irq_to_gpio(unsigned int irq)
author
#3 lore raw

PATCH 2/5 intel_mid_i2c: I2C driver supporting Moorestown and Medfield platform

In reply to a message not in the archive

From: Wen Wang <[email protected]>

Initial release of the driver.

---

 drivers/i2c/busses/Kconfig    |    9 
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-mrst.c |  970 +++++++++++++++++++++++++++++++++++++++++
 drivers/i2c/busses/i2c-mrst.h |  274 ++++++++++++
 4 files changed, 1254 insertions(+), 0 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-mrst.c
 create mode 100644 drivers/i2c/busses/i2c-mrst.h
drivers/i2c/busses/Kconfig +9 -0
index bceafbf..f1a6eeb 100644
@@ -420,6 +420,15 @@ config I2C_IXP2000
 	  This driver is deprecated and will be dropped soon. Use i2c-gpio
 	  instead.
 
+config I2C_MRST
+	tristate "Intel Moorestown/Medfield Platform I2C controller"
+	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-mrst.
+
 config I2C_MPC
 	tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
 	depends on PPC32
drivers/i2c/busses/Makefile +1 -0
index 936880b..0b9aa00 100644
@@ -40,6 +40,7 @@ obj-$(CONFIG_I2C_IBM_IIC)	+= i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IMX)		+= i2c-imx.o
 obj-$(CONFIG_I2C_IOP3XX)	+= i2c-iop3xx.o
 obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
+obj-$(CONFIG_I2C_MRST)		+= i2c-mrst.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
drivers/i2c/busses/i2c-mrst.c new file +970 -0

970 lines not on this page · raw message

drivers/i2c/busses/i2c-mrst.h new file +274 -0

274 lines not on this page · raw message

author
#4 lore raw

PATCH 3/5 intel_mid_i2c: Do a bit of compaction and tidying

In reply to a message not in the archive

Squash down the switches into tables, and use the PCI ident field. We could perhaps take this further and put the platform and port numbr into this.

Check the speed (which is now 0/1/2) is valid and ignore otherwise.

---

 drivers/i2c/busses/i2c-mrst.c |  183 +++++++++++++----------------------------
 drivers/i2c/busses/i2c-mrst.h |    5 -
 2 files changed, 59 insertions(+), 129 deletions(-)
drivers/i2c/busses/i2c-mrst.c +59 -124
index 0b44ffd..9a8dfc8 100644
@@ -45,6 +45,20 @@
 #define mrst_i2c_read(reg)		__raw_readl(reg)
 #define mrst_i2c_write(reg, val)	__raw_writel((val), (reg))
 
+/* Use defines not enumerations so that we can do this with tables */
+
+#define MOOESTOWN	0
+#define	MEDFIELD	1
+
+#define NUM_PLATFORMS	2
+
+#define STANDARD	0
+#define FAST		1
+#define HIGH		2
+
+#define NUM_SPEEDS	3
+
+
 static int speed_mode[6] = {
 	STANDARD,
 	STANDARD,
@@ -120,6 +134,14 @@ static int mrst_i2c_disable(struct i2c_adapter *adap)
 static int mrst_i2c_hwinit(struct mrst_i2c_private *i2c)
 {
 	int err = 0;
+	static const u16 hcnt[NUM_PLATFORMS][NUM_SPEEDS] = {
+		{ 0x75,  0x15, 0x07 },
+		{ 0x1EC, 0x70, 0x06 }
+	};
+	static const u16 lcnt[NUM_PLATFORMS][NUM_SPEEDS] = {
+		{ 0x7C,  0x21, 0x0E },
+		{ 0x1F3, 0x81, 0x0F }
+	};
 
 	/* Disable i2c first */
 	mrst_i2c_disable(i2c->adap);
@@ -134,46 +156,13 @@ static int mrst_i2c_hwinit(struct mrst_i2c_private *i2c)
 	 * enable master FSM, disable slave FSM,
 	 * use target address when initiating transfer
 	 */
-	switch (i2c->speed) {
-	case STANDARD:
-		mrst_i2c_write(i2c->base + IC_CON,
-			       SLV_DIS | RESTART | STANDARD_MODE | MASTER_EN);
-
-		if (i2c->platform == MEDFIELD) {
-			mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x1EC);
-			mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x1F3);
-		} else if (i2c->platform == MOORESTOWN) {
-			mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT, 0x75);
-			mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT, 0x7c);
-		}
-		break;
-	case FAST:
-		mrst_i2c_write(i2c->base + IC_CON,
-			       SLV_DIS | RESTART | FAST_MODE | MASTER_EN);
-
-		if (i2c->platform == MEDFIELD) {
-			mrst_i2c_write(i2c->base + IC_FS_SCL_HCNT, 0x70);
-			mrst_i2c_write(i2c->base + IC_FS_SCL_LCNT, 0x81);
-		} else if (i2c->platform == MOORESTOWN) {
-			mrst_i2c_write(i2c->base + IC_FS_SCL_HCNT, 0x15);
-			mrst_i2c_write(i2c->base + IC_FS_SCL_LCNT, 0x21);
-		}
-		break;
-	case HIGH:
-		mrst_i2c_write(i2c->base + IC_CON,
-			       SLV_DIS | RESTART | HIGH_MODE | MASTER_EN);
-
-		if (i2c->platform == MEDFIELD) {
-			mrst_i2c_write(i2c->base + IC_HS_SCL_HCNT, 0x6);
-			mrst_i2c_write(i2c->base + IC_HS_SCL_LCNT, 0xF);
-		} else if (i2c->platform == MOORESTOWN) {
-			mrst_i2c_write(i2c->base + IC_HS_SCL_HCNT, 0x7);
-			mrst_i2c_write(i2c->base + IC_HS_SCL_LCNT, 0xE);
-		}
-		break;
-	default:
-		;
-	}
+
+	mrst_i2c_write(i2c->base + IC_CON,
+		(i2c->speed + 1) << 1 | SLV_DIS | RESTART | MASTER_EN);
+	mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT,
+		hcnt[i2c->platform][i2c->speed]);
+	mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT,
+		lcnt[i2c->platform][i2c->speed]);
 
 	/* Set tranmit & receive FIFO threshold to zero */
 	mrst_i2c_write(i2c->base + IC_RX_TL, 0x0);
@@ -416,6 +405,7 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 	int err;
 	uint32_t reg_val;
 	uint32_t bit_mask;
+	uint32_t mode;
 
 	/* Disable device first */
 	err = mrst_i2c_disable(adap);
@@ -425,34 +415,13 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 		return -ETIMEDOUT;
 	}
 
-	/* set the speed mode to standard */
+	mode = 1 + (i2c->speed << 1);
+	/* set the speed mode */
 	reg_val = mrst_i2c_read(i2c->base + IC_CON);
-	switch (i2c->speed) {
-	case STANDARD:
-		if ((reg_val & 0x6) != STANDARD_MODE) {
-			dev_dbg(&adap->dev, "set standard mode\n");
-			mrst_i2c_write(i2c->base + IC_CON,
-				       (reg_val & (~0x6)) | STANDARD_MODE);
-		}
-		break;
-	case FAST:
-		if ((reg_val & 0x6) != FAST_MODE) {
-			dev_dbg(&adap->dev, "set fast mode\n");
-			mrst_i2c_write(i2c->base + IC_CON,
-				       (reg_val & (~0x6)) | FAST_MODE);
-		}
-		break;
-	case HIGH:
-		if ((reg_val & 0x6) != HIGH_MODE) {
-			dev_dbg(&adap->dev, "set high mode\n");
-			mrst_i2c_write(i2c->base + IC_CON,
-				       (reg_val & (~0x6)) | HIGH_MODE);
-		}
-		break;
-	default:
-		dev_dbg(&adap->dev, "set standard mode\n");
+	if ((reg_val & 0x06) != mode) {
+		dev_dbg(&adap->dev, "set mode %d\n", i2c->speed);
 		mrst_i2c_write(i2c->base + IC_CON,
-			       (reg_val & (~0x6)) | STANDARD_MODE);
+			       (reg_val & (~0x6)) | mode);
 	}
 
 	reg_val = mrst_i2c_read(i2c->base + IC_CON);
@@ -469,7 +438,7 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 			mrst_i2c_write(i2c->base + IC_CON, reg_val & (~(1<<4)));
 		}
 	}
-	/*enable restart conditions */
+	/* enable restart conditions */
 	reg_val = mrst_i2c_read(i2c->base + IC_CON);
 	if ((reg_val & (1<<5)) != 1<<5) {
 		dev_dbg(&adap->dev, "enable restart conditions\n");
@@ -714,15 +683,17 @@ err:
 }
 
 static struct pci_device_id mrst_i2c_ids[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0802)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0803)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0804)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0817)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0818)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0819)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082C)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082D)},
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x082E)},
+	/* 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, mrst_i2c_ids);
@@ -834,57 +805,21 @@ static int __devinit mrst_i2c_probe(struct pci_dev *dev,
 	pci_set_drvdata(dev, mrst);
 	i2c_set_adapdata(adap, mrst);
 
-	switch (id->device) {
-	case 0x0802:
-		dev_dbg(&dev->dev, KERN_INFO "I2C0\n");
-		adap->nr = busnum = 0;
-		mrst->platform = MOORESTOWN;
-		break;
-	case 0x0803:
-		dev_dbg(&dev->dev, KERN_INFO "I2C1\n");
-		adap->nr = busnum = 1;
+	adap->nr = busnum = id->driver_data;
+	if (dev->device <= 0x0804)
 		mrst->platform = MOORESTOWN;
-		break;
-	case 0x0804:
-		dev_dbg(&dev->dev, KERN_INFO "I2C2\n");
-		adap->nr = busnum = 2;
-		mrst->platform = MOORESTOWN;
-		break;
-	case 0x082C:
-		dev_dbg(&dev->dev, KERN_INFO "I2C0\n");
-		adap->nr = busnum = 0;
-		mrst->platform = MEDFIELD;
-		break;
-	case 0x082D:
-		dev_dbg(&dev->dev, KERN_INFO "I2C1\n");
-		adap->nr = busnum = 1;
-		mrst->platform = MEDFIELD;
-		break;
-	case 0x082E:
-		dev_dbg(&dev->dev, KERN_INFO "I2C2\n");
-		adap->nr = busnum = 2;
-		mrst->platform = MEDFIELD;
-		break;
-	case 0x0817:
-		dev_dbg(&dev->dev, KERN_INFO "I2C3\n");
-		adap->nr = busnum = 3;
-		mrst->platform = MEDFIELD;
-		break;
-	case 0x0818:
-		dev_dbg(&dev->dev, KERN_INFO "I2C4\n");
-		adap->nr = busnum = 4;
-		mrst->platform = MEDFIELD;
-		break;
-	case 0x0819:
-		dev_dbg(&dev->dev, KERN_INFO "I2C5\n");
-		adap->nr = busnum = 5;
+	else
 		mrst->platform = MEDFIELD;
-		break;
-	default:
-		;
+
+	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];
 	}
-	if (ctl_num > busnum)
-		mrst->speed = speed_mode[busnum];
 
 	/* Initialize i2c controller */
 	err = mrst_i2c_hwinit(mrst);
drivers/i2c/busses/i2c-mrst.h +0 -5
index 441ff36..b0e4951 100644
@@ -42,11 +42,6 @@ struct mrst_i2c_private {
 	spinlock_t	slock;
 };
 
-/* Speed mode macros */
-#define STANDARD	100
-#define FAST		25
-#define	HIGH		3
-
 #define ACTIVE		0
 #define STANDBY		1
 
author
#5 lore raw

PATCH 4/5 intel_mid_i2c: minor cleanups

In reply to a message not in the archive

uint32t -> u32
bracketing of case statements
spacing and '!' usage

---

 drivers/i2c/busses/i2c-mrst.c |   54 +++++++++++++++++++----------------------
 1 files changed, 25 insertions(+), 29 deletions(-)
drivers/i2c/busses/i2c-mrst.c +25 -29
index 9a8dfc8..974c189 100644
@@ -240,50 +240,45 @@ static void mrst_i2c_abort(struct mrst_i2c_private *i2c)
 	 * the abort interrupt occured.
 	 */
 	switch (abort) {
-	case (ABRT_MASTER_DIS):
+	case ABRT_MASTER_DIS:
 		dev_err(&adap->dev,
-			"initiate Master operation with Master mode"
-			"disabled.\n");
+		"initiate Master operation with Master mode disabled.\n");
 
 		break;
-	case (ABRT_10B_RD_NORSTRT):
+	case ABRT_10B_RD_NORSTRT:
 		dev_err(&adap->dev,
-			"RESTART disabled and master sends READ cmd in 10-BIT"
-			"addressing.\n");
+	"RESTART disabled and master sends READ cmd in 10-BIT addressing.\n");
 		break;
-	case (ABRT_SBYTE_NORSTRT):
+	case ABRT_SBYTE_NORSTRT:
 		dev_err(&adap->dev,
-			"RESTART disabled and user is trying to send START"
-			"byte.\n");
+		"RESTART disabled and user is trying to send START byte.\n");
 		mrst_i2c_write(i2c->base + IC_TX_ABRT_SOURCE,
 			       !(ABRT_SBYTE_NORSTRT));
 		mrst_i2c_write(i2c->base + IC_CON, RESTART);
 		mrst_i2c_write(i2c->base + IC_TAR, !(IC_TAR_SPECIAL));
 		break;
-	case (ABRT_SBYTE_ACKDET):
+	case ABRT_SBYTE_ACKDET:
 		dev_err(&adap->dev,
 			"START byte was acknowledged.\n");
 		break;
-	case (ABRT_TXDATA_NOACK):
+	case ABRT_TXDATA_NOACK:
 		dev_err(&adap->dev,
 			"No acknowledge received from slave.\n");
 		break;
-	case (ABRT_10ADDR2_NOACK):
+	case ABRT_10ADDR2_NOACK:
 		dev_err(&adap->dev,
-			"The 2nd address byte of 10-bit address not"
-			"acknowledged.\n");
+	"The 2nd address byte of the 10-bit address not acknowledged.\n");
 		break;
-	case (ABRT_10ADDR1_NOACK):
+	case ABRT_10ADDR1_NOACK:
 		dev_dbg(&adap->dev,
-			"The 1st address byte of 10-bit address not"
-			"acknowledged.\n");
+		"The 1st address byte of 10-bit address not acknowledged.\n");
 		break;
-	case (ABRT_7B_ADDR_NOACK):
+	case ABRT_7B_ADDR_NOACK:
 		dev_err(&adap->dev,
 			"I2C slave device not acknowledge.\n");
 		break;
 	default:
-		;;
+		;
 	}
 
 	/* Clear TX_ABRT bit */
@@ -403,15 +398,15 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 	struct mrst_i2c_private *i2c =
 	    (struct mrst_i2c_private *)i2c_get_adapdata(adap);
 	int err;
-	uint32_t reg_val;
-	uint32_t bit_mask;
-	uint32_t mode;
+	u32 reg_val;
+	u32 bit_mask;
+	u32 mode;
 
 	/* Disable device first */
 	err = mrst_i2c_disable(adap);
 	if (err) {
 		dev_err(&adap->dev,
-			"Cannot disable i2c controller, timeout!\n");
+			"Cannot disable i2c controller, timeout\n");
 		return -ETIMEDOUT;
 	}
 
@@ -461,14 +456,15 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 	bit_mask = 1 << 11 | 1 << 10;
 
 	if ((reg_val & bit_mask) != 0x0) {
-		dev_dbg(&adap->dev, "WR: use target address when intiating"
-			"transfer, i2c_tx_target\n");
+		dev_dbg(&adap->dev,
+	 "WR: use target address when intiating transfer, i2c_tx_target\n");
 		mrst_i2c_write(i2c->base + IC_TAR, reg_val & ~bit_mask);
 	}
 
 	/* 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);
+	dev_dbg(&adap->dev,
+		"set target address to the I2C slave address, addr is %x\n",
+			pmsg->addr);
 	mrst_i2c_write(i2c->base + IC_TAR, pmsg->addr
 		       | (pmsg->flags & I2C_M_TEN ? IC_TAR_10BIT_ADDR : 0));
 
@@ -776,14 +772,14 @@ static int __devinit mrst_i2c_probe(struct pci_dev *dev,
 	/* Allocate the per-device data structure, mrst_i2c_private */
 	mrst = kzalloc(sizeof(struct mrst_i2c_private), GFP_KERNEL);
 	if (mrst == NULL) {
-		dev_err(&dev->dev, "Can't allocate interface!\n");
+		dev_err(&dev->dev, "Can't allocate interface\n");
 		err = -ENOMEM;
 		goto fail1;
 	}
 
 	adap = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
 	if (adap == NULL) {
-		dev_err(&dev->dev, "Can't allocate interface!\n");
+		dev_err(&dev->dev, "Can't allocate interface\n");
 		err = -ENOMEM;
 		goto fail2;
 	}
author
#6 lore raw

PATCH 5/5 intel_mid_i2c: Minor changes after verification

In reply to a message not in the archive

From: Wen Wang <[email protected]>

Added some minor changes/fixes after verification on the board.

---

 drivers/i2c/busses/i2c-mrst.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)
drivers/i2c/busses/i2c-mrst.c +5 -4
index 974c189..5da3ca5 100644
@@ -90,6 +90,7 @@ static int mrst_i2c_disable(struct i2c_adapter *adap)
 
 	int count = 0;
 	int ret1, ret2;
+	static const u16 delay[NUM_SPEEDS] = {100, 25, 3};
 
 	/* Set IC_ENABLE to 0 */
 	mrst_i2c_write(i2c->base + IC_ENABLE, 0);
@@ -98,7 +99,7 @@ static int mrst_i2c_disable(struct i2c_adapter *adap)
 	dev_dbg(&adap->dev, "mrst i2c disable\n");
 	while ((ret1 = mrst_i2c_read(i2c->base + IC_ENABLE_STATUS) & 0x1)
 		|| (ret2 = mrst_i2c_read(i2c->base + IC_STATUS) & 0x1)) {
-		udelay(i2c->speed);
+		udelay(delay[i2c->speed]);
 		mrst_i2c_write(i2c->base + IC_ENABLE, 0);
 		dev_dbg(&adap->dev, "i2c is busy, count is %d speed %d\n",
 			count, i2c->speed);
@@ -159,9 +160,9 @@ static int mrst_i2c_hwinit(struct mrst_i2c_private *i2c)
 
 	mrst_i2c_write(i2c->base + IC_CON,
 		(i2c->speed + 1) << 1 | SLV_DIS | RESTART | MASTER_EN);
-	mrst_i2c_write(i2c->base + IC_SS_SCL_HCNT,
+	mrst_i2c_write(i2c->base + (IC_SS_SCL_HCNT + (i2c->speed << 3)),
 		hcnt[i2c->platform][i2c->speed]);
-	mrst_i2c_write(i2c->base + IC_SS_SCL_LCNT,
+	mrst_i2c_write(i2c->base + (IC_SS_SCL_LCNT + (i2c->speed << 3)),
 		lcnt[i2c->platform][i2c->speed]);
 
 	/* Set tranmit & receive FIFO threshold to zero */
@@ -410,7 +411,7 @@ static int mrst_i2c_setup(struct i2c_adapter *adap,  struct i2c_msg *pmsg)
 		return -ETIMEDOUT;
 	}
 
-	mode = 1 + (i2c->speed << 1);
+	mode = (1 + i2c->speed) << 1;
 	/* set the speed mode */
 	reg_val = mrst_i2c_read(i2c->base + IC_CON);
 	if ((reg_val & 0x06) != mode) {