diff options
-rw-r--r-- | arch/arm/plat-omap/i2c.c | 39 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-omap.c | 24 | ||||
-rw-r--r-- | include/linux/i2c-omap.h | 9 |
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 | ||
73 | static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; | 76 | static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; |
74 | static struct platform_device omap_i2c_devices[] = { | 77 | static 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) | |||
100 | static int __init omap_i2c_add_bus(int bus_id) | 103 | static 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 | |||
4 | struct omap_i2c_bus_platform_data { | ||
5 | u32 clkrate; | ||
6 | void (*set_mpu_wkup_lat)(struct device *dev, long set); | ||
7 | }; | ||
8 | |||
9 | #endif | ||