diff options
author | Li, Ning <ning.li@intel.com> | 2012-02-16 16:20:58 +0800 |
---|---|---|
committer | buildbot <buildbot@intel.com> | 2012-02-27 04:08:07 -0800 |
commit | 6c5fd8886c1224091ea5cff6175a0e921c12788e (patch) | |
tree | dd515cc744a5439c00c821a916db3ed4572ea115 /drivers/i2c | |
parent | 57dde0e9135c07d3ab09e52aed52b73e23c558f6 (diff) | |
download | kernel-mfld-blackbay-6c5fd8886c1224091ea5cff6175a0e921c12788e.tar.gz kernel-mfld-blackbay-6c5fd8886c1224091ea5cff6175a0e921c12788e.tar.bz2 kernel-mfld-blackbay-6c5fd8886c1224091ea5cff6175a0e921c12788e.zip |
dw-i2c: add CLV i2c hcnt/lcnt setting support
BZ: 22191
I2C HC/LC setting are different bettween PNW and CLV, to support
both platform, we add scl configuration function in controller
struct. With this patch, i2c hcnt/lcnt setting can be controlled
much easier.
Change-Id: Ic69b752ee28ee2f5498d1899016b947fa71154bc
Signed-off-by: Li, Ning <ning.li@intel.com>
Reviewed-on: http://android.intel.com:8080/35553
Reviewed-by: Zhang, Shijie <shijie.zhang@intel.com>
Reviewed-by: Yang, Bin <bin.yang@intel.com>
Reviewed-by: Yang, Fei <fei.yang@intel.com>
Reviewed-by: Kuppuswamy, Sathyanarayanan <sathyanarayanan.kuppuswamy@intel.com>
Reviewed-by: Du, Alek <alek.du@intel.com>
Tested-by: Wang, Zhifeng <zhifeng.wang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.c | 158 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-core.h | 111 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-designware-pcidrv.c | 37 |
3 files changed, 182 insertions, 124 deletions
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index 8758ce2614d..abbdc105e68 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c @@ -36,101 +36,6 @@ #include <linux/semaphore.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 - -#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)", @@ -303,35 +208,40 @@ int i2c_dw_init(struct dw_i2c_dev *dev) /* 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, - 227, /* tHD;STA = tHIGH = 22.7 us */ - 3, /* tf = 0.3 us */ - 0, /* 0: DW default, 1: Ideal */ - 23); /* offset = 23 */ - lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 227, /* tLOW = 22.7 us */ - 3, /* tf = 0.3 us */ - 28); /* offset = 28 */ - 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, - 52, /* tHD;STA = tHIGH = 5.2 us */ - 3, /* tf = 0.3 us */ - 0, /* 0: DW default, 1: Ideal */ - 11); /* offset = 11 */ - lcnt = i2c_dw_scl_lcnt(input_clock_khz, - 72, /* tLOW = 7.2 us */ - 3, /* tf = 0.3 us */ - 12); /* offset = 12 */ - 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); + if (dev->get_scl_cfg) + dev->get_scl_cfg(dev); + else { + /* set standard and fast speed deviders for high/low periods */ + + /* Standard-mode */ + hcnt = i2c_dw_scl_hcnt(input_clock_khz, + 227, /* tHD;STA = tHIGH = 22.7 us */ + 3, /* tf = 0.3 us */ + 0, /* 0: DW default, 1: Ideal */ + 23); /* offset = 23 */ + lcnt = i2c_dw_scl_lcnt(input_clock_khz, + 227, /* tLOW = 22.7 us */ + 3, /* tf = 0.3 us */ + 28); /* offset = 28 */ + 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, + 52, /* tHD;STA = tHIGH = 5.2 us */ + 3, /* tf = 0.3 us */ + 0, /* 0: DW default, 1: Ideal */ + 11); /* offset = 11 */ + lcnt = i2c_dw_scl_lcnt(input_clock_khz, + 72, /* tLOW = 7.2 us */ + 3, /* tf = 0.3 us */ + 12); /* offset = 12 */ + 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/2, DW_IC_TX_TL); diff --git a/drivers/i2c/busses/i2c-designware-core.h b/drivers/i2c/busses/i2c-designware-core.h index 119fad65ce4..7c7ae50cebe 100644 --- a/drivers/i2c/busses/i2c-designware-core.h +++ b/drivers/i2c/busses/i2c-designware-core.h @@ -26,6 +26,40 @@ * */ +/* + * 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_CON_MASTER 0x1 #define DW_IC_CON_SPEED_STD 0x2 @@ -34,6 +68,28 @@ #define DW_IC_CON_RESTART_EN 0x20 #define DW_IC_CON_SLAVE_DISABLE 0x40 +#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 */ @@ -42,6 +98,60 @@ #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) + +/* + * i2c scl hcnt/lcnt setting + */ +#define PNW_SS_SCLK_HCNT 0x1EC +#define PNW_SS_SCLK_LCNT 0x1F3 +#define PNW_FS_SCLK_HCNT 0x66 +#define PNW_FS_SCLK_LCNT 0x8B +#define PNW_HS_SCLK_HCNT 0x9 +#define PNW_HS_SCLK_LCNT 0x17 + +#define CLV_SS_SCLK_HCNT 0x1EC +#define CLV_SS_SCLK_LCNT 0x1F3 +#define CLV_FS_SCLK_HCNT 0x59 +#define CLV_FS_SCLK_LCNT 0x98 +#define CLV_HS_SCLK_HCNT 0x8 +#define CLV_HS_SCLK_LCNT 0x17 /** * struct dw_i2c_dev - private i2c-designware data @@ -76,6 +186,7 @@ struct dw_i2c_dev { struct semaphore lock; struct clk *clk; u32 (*get_clk_rate_khz) (struct dw_i2c_dev *dev); + int (*get_scl_cfg) (struct dw_i2c_dev *dev); struct dw_pci_controller *controller; int cmd_err; struct i2c_msg *msgs; diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c index 5440211e3cb..c20d4bc97cf 100644 --- a/drivers/i2c/busses/i2c-designware-pcidrv.c +++ b/drivers/i2c/busses/i2c-designware-pcidrv.c @@ -70,12 +70,36 @@ struct dw_pci_controller { u32 tx_fifo_depth; u32 rx_fifo_depth; u32 clk_khz; + int (*scl_cfg) (struct dw_i2c_dev *dev); + }; #define INTEL_MID_STD_CFG (DW_IC_CON_MASTER | \ DW_IC_CON_SLAVE_DISABLE | \ DW_IC_CON_RESTART_EN) +static int mfld_i2c_scl_cfg(struct dw_i2c_dev *dev) +{ + dw_writel(dev, PNW_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); + dw_writel(dev, PNW_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); + + dw_writel(dev, PNW_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); + dw_writel(dev, PNW_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); + + return 0; +} + +static int ctp_i2c_scl_cfg(struct dw_i2c_dev *dev) +{ + dw_writel(dev, CLV_SS_SCLK_HCNT, DW_IC_SS_SCL_HCNT); + dw_writel(dev, CLV_SS_SCLK_LCNT, DW_IC_SS_SCL_LCNT); + + dw_writel(dev, CLV_FS_SCLK_HCNT, DW_IC_FS_SCL_HCNT); + dw_writel(dev, CLV_FS_SCLK_LCNT, DW_IC_FS_SCL_LCNT); + + return 0; +} + static struct dw_pci_controller dw_pci_controllers[] = { [moorestown_0] = { .bus_num = 0, @@ -104,6 +128,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = mfld_i2c_scl_cfg, }, [medfield_1] = { .bus_num = 1, @@ -111,6 +136,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 20500, + .scl_cfg = mfld_i2c_scl_cfg, }, [medfield_2] = { .bus_num = 2, @@ -118,6 +144,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = mfld_i2c_scl_cfg, }, [medfield_3] = { .bus_num = 3, @@ -125,6 +152,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 20500, + .scl_cfg = mfld_i2c_scl_cfg, }, [medfield_4] = { .bus_num = 4, @@ -132,6 +160,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = mfld_i2c_scl_cfg, }, [medfield_5] = { .bus_num = 5, @@ -139,6 +168,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = mfld_i2c_scl_cfg, }, [cloverview_0] = { @@ -147,6 +177,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = ctp_i2c_scl_cfg, }, [cloverview_1] = { .bus_num = 1, @@ -154,6 +185,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = ctp_i2c_scl_cfg, }, [cloverview_2] = { .bus_num = 2, @@ -161,6 +193,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = ctp_i2c_scl_cfg, }, [cloverview_3] = { .bus_num = 3, @@ -168,6 +201,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 20500, + .scl_cfg = ctp_i2c_scl_cfg, }, [cloverview_4] = { .bus_num = 4, @@ -175,6 +209,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = ctp_i2c_scl_cfg, }, [cloverview_5] = { .bus_num = 5, @@ -182,6 +217,7 @@ static struct dw_pci_controller dw_pci_controllers[] = { .tx_fifo_depth = 32, .rx_fifo_depth = 32, .clk_khz = 17000, + .scl_cfg = ctp_i2c_scl_cfg, }, }; static struct i2c_algorithm i2c_dw_algo = { @@ -342,6 +378,7 @@ const struct pci_device_id *id) I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK; dev->master_cfg = controller->bus_cfg; + dev->get_scl_cfg = controller->scl_cfg; pci_set_drvdata(pdev, dev); |