diff options
| -rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 146 |
1 files changed, 114 insertions, 32 deletions
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 389ac6032a7b..46111ff18133 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
| @@ -45,29 +45,37 @@ | |||
| 45 | /* I2C controller revisions present on specific hardware */ | 45 | /* I2C controller revisions present on specific hardware */ |
| 46 | #define OMAP_I2C_REV_ON_2430 0x36 | 46 | #define OMAP_I2C_REV_ON_2430 0x36 |
| 47 | #define OMAP_I2C_REV_ON_3430 0x3C | 47 | #define OMAP_I2C_REV_ON_3430 0x3C |
| 48 | #define OMAP_I2C_REV_ON_4430 0x40 | ||
| 48 | 49 | ||
| 49 | /* timeout waiting for the controller to respond */ | 50 | /* timeout waiting for the controller to respond */ |
| 50 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) | 51 | #define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000)) |
| 51 | 52 | ||
| 52 | #define OMAP_I2C_REV_REG 0x00 | ||
| 53 | #define OMAP_I2C_IE_REG 0x01 | ||
| 54 | #define OMAP_I2C_STAT_REG 0x02 | ||
| 55 | #define OMAP_I2C_IV_REG 0x03 | ||
| 56 | /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ | 53 | /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */ |
| 57 | #define OMAP_I2C_WE_REG 0x03 | 54 | enum { |
| 58 | #define OMAP_I2C_SYSS_REG 0x04 | 55 | OMAP_I2C_REV_REG = 0, |
| 59 | #define OMAP_I2C_BUF_REG 0x05 | 56 | OMAP_I2C_IE_REG, |
| 60 | #define OMAP_I2C_CNT_REG 0x06 | 57 | OMAP_I2C_STAT_REG, |
| 61 | #define OMAP_I2C_DATA_REG 0x07 | 58 | OMAP_I2C_IV_REG, |
| 62 | #define OMAP_I2C_SYSC_REG 0x08 | 59 | OMAP_I2C_WE_REG, |
| 63 | #define OMAP_I2C_CON_REG 0x09 | 60 | OMAP_I2C_SYSS_REG, |
| 64 | #define OMAP_I2C_OA_REG 0x0a | 61 | OMAP_I2C_BUF_REG, |
| 65 | #define OMAP_I2C_SA_REG 0x0b | 62 | OMAP_I2C_CNT_REG, |
| 66 | #define OMAP_I2C_PSC_REG 0x0c | 63 | OMAP_I2C_DATA_REG, |
| 67 | #define OMAP_I2C_SCLL_REG 0x0d | 64 | OMAP_I2C_SYSC_REG, |
| 68 | #define OMAP_I2C_SCLH_REG 0x0e | 65 | OMAP_I2C_CON_REG, |
| 69 | #define OMAP_I2C_SYSTEST_REG 0x0f | 66 | OMAP_I2C_OA_REG, |
| 70 | #define OMAP_I2C_BUFSTAT_REG 0x10 | 67 | OMAP_I2C_SA_REG, |
| 68 | OMAP_I2C_PSC_REG, | ||
| 69 | OMAP_I2C_SCLL_REG, | ||
| 70 | OMAP_I2C_SCLH_REG, | ||
| 71 | OMAP_I2C_SYSTEST_REG, | ||
| 72 | OMAP_I2C_BUFSTAT_REG, | ||
| 73 | OMAP_I2C_REVNB_LO, | ||
| 74 | OMAP_I2C_REVNB_HI, | ||
| 75 | OMAP_I2C_IRQSTATUS_RAW, | ||
| 76 | OMAP_I2C_IRQENABLE_SET, | ||
| 77 | OMAP_I2C_IRQENABLE_CLR, | ||
| 78 | }; | ||
| 71 | 79 | ||
| 72 | /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ | 80 | /* I2C Interrupt Enable Register (OMAP_I2C_IE): */ |
| 73 | #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ | 81 | #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */ |
| @@ -170,6 +178,7 @@ struct omap_i2c_dev { | |||
| 170 | u32 speed; /* Speed of bus in Khz */ | 178 | u32 speed; /* Speed of bus in Khz */ |
| 171 | u16 cmd_err; | 179 | u16 cmd_err; |
| 172 | u8 *buf; | 180 | u8 *buf; |
| 181 | u8 *regs; | ||
| 173 | size_t buf_len; | 182 | size_t buf_len; |
| 174 | struct i2c_adapter adapter; | 183 | struct i2c_adapter adapter; |
| 175 | u8 fifo_size; /* use as flag and value | 184 | u8 fifo_size; /* use as flag and value |
| @@ -188,15 +197,64 @@ struct omap_i2c_dev { | |||
| 188 | u16 westate; | 197 | u16 westate; |
| 189 | }; | 198 | }; |
| 190 | 199 | ||
| 200 | const static u8 reg_map[] = { | ||
| 201 | [OMAP_I2C_REV_REG] = 0x00, | ||
| 202 | [OMAP_I2C_IE_REG] = 0x01, | ||
| 203 | [OMAP_I2C_STAT_REG] = 0x02, | ||
| 204 | [OMAP_I2C_IV_REG] = 0x03, | ||
| 205 | [OMAP_I2C_WE_REG] = 0x03, | ||
| 206 | [OMAP_I2C_SYSS_REG] = 0x04, | ||
| 207 | [OMAP_I2C_BUF_REG] = 0x05, | ||
| 208 | [OMAP_I2C_CNT_REG] = 0x06, | ||
| 209 | [OMAP_I2C_DATA_REG] = 0x07, | ||
| 210 | [OMAP_I2C_SYSC_REG] = 0x08, | ||
| 211 | [OMAP_I2C_CON_REG] = 0x09, | ||
| 212 | [OMAP_I2C_OA_REG] = 0x0a, | ||
| 213 | [OMAP_I2C_SA_REG] = 0x0b, | ||
| 214 | [OMAP_I2C_PSC_REG] = 0x0c, | ||
| 215 | [OMAP_I2C_SCLL_REG] = 0x0d, | ||
| 216 | [OMAP_I2C_SCLH_REG] = 0x0e, | ||
| 217 | [OMAP_I2C_SYSTEST_REG] = 0x0f, | ||
| 218 | [OMAP_I2C_BUFSTAT_REG] = 0x10, | ||
| 219 | }; | ||
| 220 | |||
| 221 | const static u8 omap4_reg_map[] = { | ||
| 222 | [OMAP_I2C_REV_REG] = 0x04, | ||
| 223 | [OMAP_I2C_IE_REG] = 0x2c, | ||
| 224 | [OMAP_I2C_STAT_REG] = 0x28, | ||
| 225 | [OMAP_I2C_IV_REG] = 0x34, | ||
| 226 | [OMAP_I2C_WE_REG] = 0x34, | ||
| 227 | [OMAP_I2C_SYSS_REG] = 0x90, | ||
| 228 | [OMAP_I2C_BUF_REG] = 0x94, | ||
| 229 | [OMAP_I2C_CNT_REG] = 0x98, | ||
| 230 | [OMAP_I2C_DATA_REG] = 0x9c, | ||
| 231 | [OMAP_I2C_SYSC_REG] = 0x20, | ||
| 232 | [OMAP_I2C_CON_REG] = 0xa4, | ||
| 233 | [OMAP_I2C_OA_REG] = 0xa8, | ||
| 234 | [OMAP_I2C_SA_REG] = 0xac, | ||
| 235 | [OMAP_I2C_PSC_REG] = 0xb0, | ||
| 236 | [OMAP_I2C_SCLL_REG] = 0xb4, | ||
| 237 | [OMAP_I2C_SCLH_REG] = 0xb8, | ||
| 238 | [OMAP_I2C_SYSTEST_REG] = 0xbC, | ||
| 239 | [OMAP_I2C_BUFSTAT_REG] = 0xc0, | ||
| 240 | [OMAP_I2C_REVNB_LO] = 0x00, | ||
| 241 | [OMAP_I2C_REVNB_HI] = 0x04, | ||
| 242 | [OMAP_I2C_IRQSTATUS_RAW] = 0x24, | ||
| 243 | [OMAP_I2C_IRQENABLE_SET] = 0x2c, | ||
| 244 | [OMAP_I2C_IRQENABLE_CLR] = 0x30, | ||
| 245 | }; | ||
| 246 | |||
| 191 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, | 247 | static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, |
| 192 | int reg, u16 val) | 248 | int reg, u16 val) |
| 193 | { | 249 | { |
| 194 | __raw_writew(val, i2c_dev->base + (reg << i2c_dev->reg_shift)); | 250 | __raw_writew(val, i2c_dev->base + |
| 251 | (i2c_dev->regs[reg] << i2c_dev->reg_shift)); | ||
| 195 | } | 252 | } |
| 196 | 253 | ||
| 197 | static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) | 254 | static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) |
| 198 | { | 255 | { |
| 199 | return __raw_readw(i2c_dev->base + (reg << i2c_dev->reg_shift)); | 256 | return __raw_readw(i2c_dev->base + |
| 257 | (i2c_dev->regs[reg] << i2c_dev->reg_shift)); | ||
| 200 | } | 258 | } |
| 201 | 259 | ||
| 202 | static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) | 260 | static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) |
| @@ -265,7 +323,11 @@ static void omap_i2c_idle(struct omap_i2c_dev *dev) | |||
| 265 | WARN_ON(dev->idle); | 323 | WARN_ON(dev->idle); |
| 266 | 324 | ||
| 267 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); | 325 | dev->iestate = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG); |
| 268 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); | 326 | if (dev->rev >= OMAP_I2C_REV_ON_4430) |
| 327 | omap_i2c_write_reg(dev, OMAP_I2C_IRQENABLE_CLR, 1); | ||
| 328 | else | ||
| 329 | omap_i2c_write_reg(dev, OMAP_I2C_IE_REG, 0); | ||
| 330 | |||
| 269 | if (dev->rev < OMAP_I2C_REV_2) { | 331 | if (dev->rev < OMAP_I2C_REV_2) { |
| 270 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ | 332 | iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */ |
| 271 | } else { | 333 | } else { |
| @@ -330,7 +392,9 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 330 | * REVISIT: Some wkup sources might not be needed. | 392 | * REVISIT: Some wkup sources might not be needed. |
| 331 | */ | 393 | */ |
| 332 | dev->westate = OMAP_I2C_WE_ALL; | 394 | dev->westate = OMAP_I2C_WE_ALL; |
| 333 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, dev->westate); | 395 | if (dev->rev < OMAP_I2C_REV_ON_4430) |
| 396 | omap_i2c_write_reg(dev, OMAP_I2C_WE_REG, | ||
| 397 | dev->westate); | ||
| 334 | } | 398 | } |
| 335 | } | 399 | } |
| 336 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); | 400 | omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0); |
| @@ -357,7 +421,7 @@ static int omap_i2c_init(struct omap_i2c_dev *dev) | |||
| 357 | psc = fclk_rate / 12000000; | 421 | psc = fclk_rate / 12000000; |
| 358 | } | 422 | } |
| 359 | 423 | ||
| 360 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | 424 | if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { |
| 361 | 425 | ||
| 362 | /* | 426 | /* |
| 363 | * HSI2C controller internal clk rate should be 19.2 Mhz for | 427 | * HSI2C controller internal clk rate should be 19.2 Mhz for |
| @@ -747,9 +811,12 @@ complete: | |||
| 747 | if (dev->buf_len) { | 811 | if (dev->buf_len) { |
| 748 | *dev->buf++ = w; | 812 | *dev->buf++ = w; |
| 749 | dev->buf_len--; | 813 | dev->buf_len--; |
| 750 | /* Data reg from 2430 is 8 bit wide */ | 814 | /* |
| 751 | if (!cpu_is_omap2430() && | 815 | * Data reg in 2430, omap3 and |
| 752 | !cpu_is_omap34xx()) { | 816 | * omap4 is 8 bit wide |
| 817 | */ | ||
| 818 | if (cpu_class_is_omap1() || | ||
| 819 | cpu_is_omap2420()) { | ||
| 753 | if (dev->buf_len) { | 820 | if (dev->buf_len) { |
| 754 | *dev->buf++ = w >> 8; | 821 | *dev->buf++ = w >> 8; |
| 755 | dev->buf_len--; | 822 | dev->buf_len--; |
| @@ -787,9 +854,12 @@ complete: | |||
| 787 | if (dev->buf_len) { | 854 | if (dev->buf_len) { |
| 788 | w = *dev->buf++; | 855 | w = *dev->buf++; |
| 789 | dev->buf_len--; | 856 | dev->buf_len--; |
| 790 | /* Data reg from 2430 is 8 bit wide */ | 857 | /* |
| 791 | if (!cpu_is_omap2430() && | 858 | * Data reg in 2430, omap3 and |
| 792 | !cpu_is_omap34xx()) { | 859 | * omap4 is 8 bit wide |
| 860 | */ | ||
| 861 | if (cpu_class_is_omap1() || | ||
| 862 | cpu_is_omap2420()) { | ||
| 793 | if (dev->buf_len) { | 863 | if (dev->buf_len) { |
| 794 | w |= *dev->buf++ << 8; | 864 | w |= *dev->buf++ << 8; |
| 795 | dev->buf_len--; | 865 | dev->buf_len--; |
| @@ -905,17 +975,24 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 905 | 975 | ||
| 906 | if (cpu_is_omap7xx()) | 976 | if (cpu_is_omap7xx()) |
| 907 | dev->reg_shift = 1; | 977 | dev->reg_shift = 1; |
| 978 | else if (cpu_is_omap44xx()) | ||
| 979 | dev->reg_shift = 0; | ||
| 908 | else | 980 | else |
| 909 | dev->reg_shift = 2; | 981 | dev->reg_shift = 2; |
| 910 | 982 | ||
| 911 | if ((r = omap_i2c_get_clocks(dev)) != 0) | 983 | if ((r = omap_i2c_get_clocks(dev)) != 0) |
| 912 | goto err_iounmap; | 984 | goto err_iounmap; |
| 913 | 985 | ||
| 986 | if (cpu_is_omap44xx()) | ||
| 987 | dev->regs = (u8 *) omap4_reg_map; | ||
| 988 | else | ||
| 989 | dev->regs = (u8 *) reg_map; | ||
| 990 | |||
| 914 | omap_i2c_unidle(dev); | 991 | omap_i2c_unidle(dev); |
| 915 | 992 | ||
| 916 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; | 993 | dev->rev = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff; |
| 917 | 994 | ||
| 918 | if (cpu_is_omap2430() || cpu_is_omap34xx()) { | 995 | if (!(cpu_class_is_omap1() || cpu_is_omap2420())) { |
| 919 | u16 s; | 996 | u16 s; |
| 920 | 997 | ||
| 921 | /* Set up the fifo size - Get total size */ | 998 | /* Set up the fifo size - Get total size */ |
| @@ -927,8 +1004,13 @@ omap_i2c_probe(struct platform_device *pdev) | |||
| 927 | * size. This is to ensure that we can handle the status on int | 1004 | * size. This is to ensure that we can handle the status on int |
| 928 | * call back latencies. | 1005 | * call back latencies. |
| 929 | */ | 1006 | */ |
| 930 | dev->fifo_size = (dev->fifo_size / 2); | 1007 | if (dev->rev >= OMAP_I2C_REV_ON_4430) { |
| 931 | dev->b_hw = 1; /* Enable hardware fixes */ | 1008 | dev->fifo_size = 0; |
| 1009 | dev->b_hw = 0; /* Disable hardware fixes */ | ||
| 1010 | } else { | ||
| 1011 | dev->fifo_size = (dev->fifo_size / 2); | ||
| 1012 | dev->b_hw = 1; /* Enable hardware fixes */ | ||
| 1013 | } | ||
| 932 | } | 1014 | } |
| 933 | 1015 | ||
| 934 | /* reset ASAP, clearing any IRQs */ | 1016 | /* reset ASAP, clearing any IRQs */ |
