Commit f38e66e0077659e5d2ca3858fdb26fc9b1765b9f

Authored by Santosh Shilimkar
Committed by Ben Dooks
1 parent f0ac131a21

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>

Showing 1 changed file with 114 additions and 32 deletions Side-by-side Diff

drivers/i2c/busses/i2c-omap.c
... ... @@ -45,29 +45,37 @@
45 45 /* I2C controller revisions present on specific hardware */
46 46 #define OMAP_I2C_REV_ON_2430 0x36
47 47 #define OMAP_I2C_REV_ON_3430 0x3C
  48 +#define OMAP_I2C_REV_ON_4430 0x40
48 49  
49 50 /* timeout waiting for the controller to respond */
50 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 53 /* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
57   -#define OMAP_I2C_WE_REG 0x03
58   -#define OMAP_I2C_SYSS_REG 0x04
59   -#define OMAP_I2C_BUF_REG 0x05
60   -#define OMAP_I2C_CNT_REG 0x06
61   -#define OMAP_I2C_DATA_REG 0x07
62   -#define OMAP_I2C_SYSC_REG 0x08
63   -#define OMAP_I2C_CON_REG 0x09
64   -#define OMAP_I2C_OA_REG 0x0a
65   -#define OMAP_I2C_SA_REG 0x0b
66   -#define OMAP_I2C_PSC_REG 0x0c
67   -#define OMAP_I2C_SCLL_REG 0x0d
68   -#define OMAP_I2C_SCLH_REG 0x0e
69   -#define OMAP_I2C_SYSTEST_REG 0x0f
70   -#define OMAP_I2C_BUFSTAT_REG 0x10
  54 +enum {
  55 + OMAP_I2C_REV_REG = 0,
  56 + OMAP_I2C_IE_REG,
  57 + OMAP_I2C_STAT_REG,
  58 + OMAP_I2C_IV_REG,
  59 + OMAP_I2C_WE_REG,
  60 + OMAP_I2C_SYSS_REG,
  61 + OMAP_I2C_BUF_REG,
  62 + OMAP_I2C_CNT_REG,
  63 + OMAP_I2C_DATA_REG,
  64 + OMAP_I2C_SYSC_REG,
  65 + OMAP_I2C_CON_REG,
  66 + OMAP_I2C_OA_REG,
  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 80 /* I2C Interrupt Enable Register (OMAP_I2C_IE): */
73 81 #define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
... ... @@ -170,6 +178,7 @@
170 178 u32 speed; /* Speed of bus in Khz */
171 179 u16 cmd_err;
172 180 u8 *buf;
  181 + u8 *regs;
173 182 size_t buf_len;
174 183 struct i2c_adapter adapter;
175 184 u8 fifo_size; /* use as flag and value
176 185  
177 186  
... ... @@ -188,15 +197,64 @@
188 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 247 static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
192 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 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 260 static int __init omap_i2c_get_clocks(struct omap_i2c_dev *dev)
... ... @@ -265,7 +323,11 @@
265 323 WARN_ON(dev->idle);
266 324  
267 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 331 if (dev->rev < OMAP_I2C_REV_2) {
270 332 iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG); /* Read clears */
271 333 } else {
... ... @@ -330,7 +392,9 @@
330 392 * REVISIT: Some wkup sources might not be needed.
331 393 */
332 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 400 omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
... ... @@ -357,7 +421,7 @@
357 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 427 * HSI2C controller internal clk rate should be 19.2 Mhz for
... ... @@ -747,9 +811,12 @@
747 811 if (dev->buf_len) {
748 812 *dev->buf++ = w;
749 813 dev->buf_len--;
750   - /* Data reg from 2430 is 8 bit wide */
751   - if (!cpu_is_omap2430() &&
752   - !cpu_is_omap34xx()) {
  814 + /*
  815 + * Data reg in 2430, omap3 and
  816 + * omap4 is 8 bit wide
  817 + */
  818 + if (cpu_class_is_omap1() ||
  819 + cpu_is_omap2420()) {
753 820 if (dev->buf_len) {
754 821 *dev->buf++ = w >> 8;
755 822 dev->buf_len--;
... ... @@ -787,9 +854,12 @@
787 854 if (dev->buf_len) {
788 855 w = *dev->buf++;
789 856 dev->buf_len--;
790   - /* Data reg from 2430 is 8 bit wide */
791   - if (!cpu_is_omap2430() &&
792   - !cpu_is_omap34xx()) {
  857 + /*
  858 + * Data reg in 2430, omap3 and
  859 + * omap4 is 8 bit wide
  860 + */
  861 + if (cpu_class_is_omap1() ||
  862 + cpu_is_omap2420()) {
793 863 if (dev->buf_len) {
794 864 w |= *dev->buf++ << 8;
795 865 dev->buf_len--;
796 866  
797 867  
... ... @@ -905,17 +975,24 @@
905 975  
906 976 if (cpu_is_omap7xx())
907 977 dev->reg_shift = 1;
  978 + else if (cpu_is_omap44xx())
  979 + dev->reg_shift = 0;
908 980 else
909 981 dev->reg_shift = 2;
910 982  
911 983 if ((r = omap_i2c_get_clocks(dev)) != 0)
912 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 991 omap_i2c_unidle(dev);
915 992  
916 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 996 u16 s;
920 997  
921 998 /* Set up the fifo size - Get total size */
... ... @@ -927,8 +1004,13 @@
927 1004 * size. This is to ensure that we can handle the status on int
928 1005 * call back latencies.
929 1006 */
930   - dev->fifo_size = (dev->fifo_size / 2);
931   - dev->b_hw = 1; /* Enable hardware fixes */
  1007 + if (dev->rev >= OMAP_I2C_REV_ON_4430) {
  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 1016 /* reset ASAP, clearing any IRQs */