aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSantosh Shilimkar <santosh.shilimkar@ti.com>2010-05-11 14:35:04 -0400
committerBen Dooks <ben-linux@fluff.org>2010-05-19 19:18:59 -0400
commitf38e66e0077659e5d2ca3858fdb26fc9b1765b9f (patch)
treeec750fa25dc83de70b963ad6943b25a1df7315d0 /drivers
parentf0ac131a21ed13e8baaa9df6f0420f2c4b45e807 (diff)
omap: i2c: Add i2c support on omap4 platform
This patch is rebased version of earlier post to add I2C driver support to OMAP4 platform. On OMAP4, all I2C register address offsets are changed from OMAP1/2/3 I2C. In order to not have #ifdef's at various places in code, as well as to support multi-OMAP build, an array is created to hold the register addresses with it's offset. This patch was submitted, reviewed and acked on mailing list already. For more details refer below link http://www.mail-archive.com/linux-i2c@vger.kernel.org/msg02281.html This updated verion has a depedancy on "Add support for 16-bit registers" posted on linux-omap. Below is the patch-works link for the same http://patchwork.kernel.org/patch/72295/ Signed-off-by: Syed Rafiuddin <rafiuddin.syed@ti.com> Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Acked-by: Kevin Hilman <khilman@deeprootsystems.com> Reviewed-by: Paul Walmsley <paul@pwsan.com> Cc: Cory Maccarrone <darkstar6262@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Signed-off-by: Ben Dooks <ben-linux@fluff.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/i2c/busses/i2c-omap.c146
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 54enum {
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
200const 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
221const 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
191static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev, 247static 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
197static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg) 254static 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
202static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev) 260static 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 */