diff options
Diffstat (limited to 'drivers/i2c')
-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 */ |