intel_mid_i2c: I2C driver support with IRQs
Subsystems (2)
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]
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
@@ -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)
PATCH 2/5 intel_mid_i2c: I2C driver supporting Moorestown and Medfield platform
In reply to a message not in the archiveFrom: 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
@@ -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
@@ -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
PATCH 3/5 intel_mid_i2c: Do a bit of compaction and tidying
In reply to a message not in the archiveSquash 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
@@ -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
@@ -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
PATCH 4/5 intel_mid_i2c: minor cleanups
In reply to a message not in the archiveuint32t -> 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
@@ -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; }
PATCH 5/5 intel_mid_i2c: Minor changes after verification
In reply to a message not in the archiveFrom: 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
@@ -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) {