aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/plat-omap/i2c.c39
-rw-r--r--drivers/i2c/busses/i2c-omap.c24
-rw-r--r--include/linux/i2c-omap.h9
3 files changed, 56 insertions, 16 deletions
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 624e26298faa..f044b5927508 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -26,9 +26,12 @@
26#include <linux/kernel.h> 26#include <linux/kernel.h>
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/i2c-omap.h>
30
29#include <mach/irqs.h> 31#include <mach/irqs.h>
30#include <plat/mux.h> 32#include <plat/mux.h>
31#include <plat/i2c.h> 33#include <plat/i2c.h>
34#include <plat/omap-pm.h>
32 35
33#define OMAP_I2C_SIZE 0x3f 36#define OMAP_I2C_SIZE 0x3f
34#define OMAP1_I2C_BASE 0xfffb3800 37#define OMAP1_I2C_BASE 0xfffb3800
@@ -70,14 +73,14 @@ static struct resource i2c_resources[][2] = {
70 }, \ 73 }, \
71 } 74 }
72 75
73static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; 76static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)];
74static struct platform_device omap_i2c_devices[] = { 77static struct platform_device omap_i2c_devices[] = {
75 I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), 78 I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
76#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 79#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
77 I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), 80 I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]),
78#endif 81#endif
79#if defined(CONFIG_ARCH_OMAP3) 82#if defined(CONFIG_ARCH_OMAP3)
80 I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), 83 I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]),
81#endif 84#endif
82}; 85};
83 86
@@ -100,10 +103,12 @@ static int __init omap_i2c_nr_ports(void)
100static int __init omap_i2c_add_bus(int bus_id) 103static int __init omap_i2c_add_bus(int bus_id)
101{ 104{
102 struct platform_device *pdev; 105 struct platform_device *pdev;
106 struct omap_i2c_bus_platform_data *pd;
103 struct resource *res; 107 struct resource *res;
104 resource_size_t base, irq; 108 resource_size_t base, irq;
105 109
106 pdev = &omap_i2c_devices[bus_id - 1]; 110 pdev = &omap_i2c_devices[bus_id - 1];
111 pd = pdev->dev.platform_data;
107 if (bus_id == 1) { 112 if (bus_id == 1) {
108 res = pdev->resource; 113 res = pdev->resource;
109 if (cpu_class_is_omap1()) { 114 if (cpu_class_is_omap1()) {
@@ -123,6 +128,15 @@ static int __init omap_i2c_add_bus(int bus_id)
123 if (cpu_class_is_omap2()) 128 if (cpu_class_is_omap2())
124 omap2_i2c_mux_pins(bus_id); 129 omap2_i2c_mux_pins(bus_id);
125 130
131 /*
132 * When waiting for completion of a i2c transfer, we need to
133 * set a wake up latency constraint for the MPU. This is to
134 * ensure quick enough wakeup from idle, when transfer
135 * completes.
136 */
137 if (cpu_is_omap34xx())
138 pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat;
139
126 return platform_device_register(pdev); 140 return platform_device_register(pdev);
127} 141}
128 142
@@ -146,8 +160,8 @@ static int __init omap_i2c_bus_setup(char *str)
146 get_options(str, 3, ints); 160 get_options(str, 3, ints);
147 if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) 161 if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
148 return 0; 162 return 0;
149 i2c_rate[ints[1] - 1] = ints[2]; 163 i2c_pdata[ints[1] - 1].clkrate = ints[2];
150 i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; 164 i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
151 165
152 return 1; 166 return 1;
153} 167}
@@ -161,9 +175,9 @@ static int __init omap_register_i2c_bus_cmdline(void)
161{ 175{
162 int i, err = 0; 176 int i, err = 0;
163 177
164 for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) 178 for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
165 if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { 179 if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
166 i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; 180 i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
167 err = omap_i2c_add_bus(i + 1); 181 err = omap_i2c_add_bus(i + 1);
168 if (err) 182 if (err)
169 goto out; 183 goto out;
@@ -197,9 +211,10 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
197 return err; 211 return err;
198 } 212 }
199 213
200 if (!i2c_rate[bus_id - 1]) 214 if (!i2c_pdata[bus_id - 1].clkrate)
201 i2c_rate[bus_id - 1] = clkrate; 215 i2c_pdata[bus_id - 1].clkrate = clkrate;
202 i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; 216
217 i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
203 218
204 return omap_i2c_add_bus(bus_id); 219 return omap_i2c_add_bus(bus_id);
205} 220}
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 46111ff18133..42c0b9108c7f 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -38,6 +38,7 @@
38#include <linux/clk.h> 38#include <linux/clk.h>
39#include <linux/io.h> 39#include <linux/io.h>
40#include <linux/slab.h> 40#include <linux/slab.h>
41#include <linux/i2c-omap.h>
41 42
42/* I2C controller revisions */ 43/* I2C controller revisions */
43#define OMAP_I2C_REV_2 0x20 44#define OMAP_I2C_REV_2 0x20
@@ -175,6 +176,9 @@ struct omap_i2c_dev {
175 struct clk *fclk; /* Functional clock */ 176 struct clk *fclk; /* Functional clock */
176 struct completion cmd_complete; 177 struct completion cmd_complete;
177 struct resource *ioarea; 178 struct resource *ioarea;
179 u32 latency; /* maximum mpu wkup latency */
180 void (*set_mpu_wkup_lat)(struct device *dev,
181 long latency);
178 u32 speed; /* Speed of bus in Khz */ 182 u32 speed; /* Speed of bus in Khz */
179 u16 cmd_err; 183 u16 cmd_err;
180 u8 *buf; 184 u8 *buf;
@@ -603,8 +607,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
603 * REVISIT: We should abort the transfer on signals, but the bus goes 607 * REVISIT: We should abort the transfer on signals, but the bus goes
604 * into arbitration and we're currently unable to recover from it. 608 * into arbitration and we're currently unable to recover from it.
605 */ 609 */
610 if (dev->set_mpu_wkup_lat != NULL)
611 dev->set_mpu_wkup_lat(dev->dev, dev->latency);
606 r = wait_for_completion_timeout(&dev->cmd_complete, 612 r = wait_for_completion_timeout(&dev->cmd_complete,
607 OMAP_I2C_TIMEOUT); 613 OMAP_I2C_TIMEOUT);
614 if (dev->set_mpu_wkup_lat != NULL)
615 dev->set_mpu_wkup_lat(dev->dev, -1);
608 dev->buf_len = 0; 616 dev->buf_len = 0;
609 if (r < 0) 617 if (r < 0)
610 return r; 618 return r;
@@ -927,6 +935,7 @@ omap_i2c_probe(struct platform_device *pdev)
927 struct omap_i2c_dev *dev; 935 struct omap_i2c_dev *dev;
928 struct i2c_adapter *adap; 936 struct i2c_adapter *adap;
929 struct resource *mem, *irq, *ioarea; 937 struct resource *mem, *irq, *ioarea;
938 struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data;
930 irq_handler_t isr; 939 irq_handler_t isr;
931 int r; 940 int r;
932 u32 speed = 0; 941 u32 speed = 0;
@@ -956,10 +965,13 @@ omap_i2c_probe(struct platform_device *pdev)
956 goto err_release_region; 965 goto err_release_region;
957 } 966 }
958 967
959 if (pdev->dev.platform_data != NULL) 968 if (pdata != NULL) {
960 speed = *(u32 *)pdev->dev.platform_data; 969 speed = pdata->clkrate;
961 else 970 dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat;
962 speed = 100; /* Defualt speed */ 971 } else {
972 speed = 100; /* Default speed */
973 dev->set_mpu_wkup_lat = NULL;
974 }
963 975
964 dev->speed = speed; 976 dev->speed = speed;
965 dev->idle = 1; 977 dev->idle = 1;
@@ -1011,6 +1023,10 @@ omap_i2c_probe(struct platform_device *pdev)
1011 dev->fifo_size = (dev->fifo_size / 2); 1023 dev->fifo_size = (dev->fifo_size / 2);
1012 dev->b_hw = 1; /* Enable hardware fixes */ 1024 dev->b_hw = 1; /* Enable hardware fixes */
1013 } 1025 }
1026 /* calculate wakeup latency constraint for MPU */
1027 if (dev->set_mpu_wkup_lat != NULL)
1028 dev->latency = (1000000 * dev->fifo_size) /
1029 (1000 * speed / 8);
1014 } 1030 }
1015 1031
1016 /* reset ASAP, clearing any IRQs */ 1032 /* reset ASAP, clearing any IRQs */
diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h
new file mode 100644
index 000000000000..78ebf507ce56
--- /dev/null
+++ b/include/linux/i2c-omap.h
@@ -0,0 +1,9 @@
1#ifndef __I2C_OMAP_H__
2#define __I2C_OMAP_H__
3
4struct omap_i2c_bus_platform_data {
5 u32 clkrate;
6 void (*set_mpu_wkup_lat)(struct device *dev, long set);
7};
8
9#endif