aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
authorTony Lindgren <tony@atomide.com>2010-05-20 14:37:23 -0400
committerTony Lindgren <tony@atomide.com>2010-05-20 14:37:23 -0400
commitf6304f5804f228b6c2fea9e3dfac25c5b2db9b38 (patch)
tree362b9b6a3bd32b868e5917a32d448ac75c5854df /arch/arm/plat-omap
parent4fa73a1bf89ebea4eba8a9982b5f64d266d8b5e9 (diff)
parent6daa642d9b8ec762b3c5641cd5e5fa855a5405bf (diff)
Merge branch 'omap4-i2c-init' into omap-for-linus
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/i2c.c135
1 files changed, 98 insertions, 37 deletions
diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c
index 624e26298faa..eec2b4993c69 100644
--- a/arch/arm/plat-omap/i2c.c
+++ b/arch/arm/plat-omap/i2c.c
@@ -26,15 +26,19 @@
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
35#define OMAP2_I2C_BASE1 0x48070000 38#define OMAP2_I2C_BASE1 0x48070000
36#define OMAP2_I2C_BASE2 0x48072000 39#define OMAP2_I2C_BASE2 0x48072000
37#define OMAP2_I2C_BASE3 0x48060000 40#define OMAP2_I2C_BASE3 0x48060000
41#define OMAP4_I2C_BASE4 0x48350000
38 42
39static const char name[] = "i2c_omap"; 43static const char name[] = "i2c_omap";
40 44
@@ -51,11 +55,14 @@ static const char name[] = "i2c_omap";
51 55
52static struct resource i2c_resources[][2] = { 56static struct resource i2c_resources[][2] = {
53 { I2C_RESOURCE_BUILDER(0, 0) }, 57 { I2C_RESOURCE_BUILDER(0, 0) },
54#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 58#if defined(CONFIG_ARCH_OMAP2PLUS)
55 { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, INT_24XX_I2C2_IRQ) }, 59 { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, 0) },
60#endif
61#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
62 { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, 0) },
56#endif 63#endif
57#if defined(CONFIG_ARCH_OMAP3) 64#if defined(CONFIG_ARCH_OMAP4)
58 { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, INT_34XX_I2C3_IRQ) }, 65 { I2C_RESOURCE_BUILDER(OMAP4_I2C_BASE4, 0) },
59#endif 66#endif
60}; 67};
61 68
@@ -70,14 +77,17 @@ static struct resource i2c_resources[][2] = {
70 }, \ 77 }, \
71 } 78 }
72 79
73static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; 80static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)];
74static struct platform_device omap_i2c_devices[] = { 81static struct platform_device omap_i2c_devices[] = {
75 I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), 82 I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]),
76#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) 83#if defined(CONFIG_ARCH_OMAP2PLUS)
77 I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), 84 I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]),
85#endif
86#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
87 I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]),
78#endif 88#endif
79#if defined(CONFIG_ARCH_OMAP3) 89#if defined(CONFIG_ARCH_OMAP4)
80 I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), 90 I2C_DEV_BUILDER(4, i2c_resources[3], &i2c_pdata[3]),
81#endif 91#endif
82}; 92};
83 93
@@ -93,39 +103,89 @@ static int __init omap_i2c_nr_ports(void)
93 ports = 2; 103 ports = 2;
94 else if (cpu_is_omap34xx()) 104 else if (cpu_is_omap34xx())
95 ports = 3; 105 ports = 3;
106 else if (cpu_is_omap44xx())
107 ports = 4;
96 108
97 return ports; 109 return ports;
98} 110}
99 111
100static int __init omap_i2c_add_bus(int bus_id) 112/* Shared between omap2 and 3 */
113static resource_size_t omap2_i2c_irq[3] __initdata = {
114 INT_24XX_I2C1_IRQ,
115 INT_24XX_I2C2_IRQ,
116 INT_34XX_I2C3_IRQ,
117};
118
119static resource_size_t omap4_i2c_irq[4] __initdata = {
120 OMAP44XX_IRQ_I2C1,
121 OMAP44XX_IRQ_I2C2,
122 OMAP44XX_IRQ_I2C3,
123 OMAP44XX_IRQ_I2C4,
124};
125
126static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id)
101{ 127{
102 struct platform_device *pdev; 128 struct omap_i2c_bus_platform_data *pd;
103 struct resource *res; 129 struct resource *res;
104 resource_size_t base, irq;
105 130
106 pdev = &omap_i2c_devices[bus_id - 1]; 131 pd = pdev->dev.platform_data;
132 res = pdev->resource;
133 res[0].start = OMAP1_I2C_BASE;
134 res[0].end = res[0].start + OMAP_I2C_SIZE;
135 res[1].start = INT_I2C;
136 omap1_i2c_mux_pins(bus_id);
137
138 return platform_device_register(pdev);
139}
140
141static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id)
142{
143 struct resource *res;
144 resource_size_t *irq;
145
146 res = pdev->resource;
147
148 if (!cpu_is_omap44xx())
149 irq = omap2_i2c_irq;
150 else
151 irq = omap4_i2c_irq;
152
107 if (bus_id == 1) { 153 if (bus_id == 1) {
108 res = pdev->resource; 154 res[0].start = OMAP2_I2C_BASE1;
109 if (cpu_class_is_omap1()) { 155 res[0].end = res[0].start + OMAP_I2C_SIZE;
110 base = OMAP1_I2C_BASE;
111 irq = INT_I2C;
112 } else {
113 base = OMAP2_I2C_BASE1;
114 irq = INT_24XX_I2C1_IRQ;
115 }
116 res[0].start = base;
117 res[0].end = base + OMAP_I2C_SIZE;
118 res[1].start = irq;
119 } 156 }
120 157
121 if (cpu_class_is_omap1()) 158 res[1].start = irq[bus_id - 1];
122 omap1_i2c_mux_pins(bus_id); 159 omap2_i2c_mux_pins(bus_id);
123 if (cpu_class_is_omap2()) 160
124 omap2_i2c_mux_pins(bus_id); 161 /*
162 * When waiting for completion of a i2c transfer, we need to
163 * set a wake up latency constraint for the MPU. This is to
164 * ensure quick enough wakeup from idle, when transfer
165 * completes.
166 */
167 if (cpu_is_omap34xx()) {
168 struct omap_i2c_bus_platform_data *pd;
169
170 pd = pdev->dev.platform_data;
171 pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat;
172 }
125 173
126 return platform_device_register(pdev); 174 return platform_device_register(pdev);
127} 175}
128 176
177static int __init omap_i2c_add_bus(int bus_id)
178{
179 struct platform_device *pdev;
180
181 pdev = &omap_i2c_devices[bus_id - 1];
182
183 if (cpu_class_is_omap1())
184 return omap1_i2c_add_bus(pdev, bus_id);
185 else
186 return omap2_i2c_add_bus(pdev, bus_id);
187}
188
129/** 189/**
130 * omap_i2c_bus_setup - Process command line options for the I2C bus speed 190 * omap_i2c_bus_setup - Process command line options for the I2C bus speed
131 * @str: String of options 191 * @str: String of options
@@ -146,8 +206,8 @@ static int __init omap_i2c_bus_setup(char *str)
146 get_options(str, 3, ints); 206 get_options(str, 3, ints);
147 if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) 207 if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports)
148 return 0; 208 return 0;
149 i2c_rate[ints[1] - 1] = ints[2]; 209 i2c_pdata[ints[1] - 1].clkrate = ints[2];
150 i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; 210 i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP;
151 211
152 return 1; 212 return 1;
153} 213}
@@ -161,9 +221,9 @@ static int __init omap_register_i2c_bus_cmdline(void)
161{ 221{
162 int i, err = 0; 222 int i, err = 0;
163 223
164 for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) 224 for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++)
165 if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { 225 if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) {
166 i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; 226 i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
167 err = omap_i2c_add_bus(i + 1); 227 err = omap_i2c_add_bus(i + 1);
168 if (err) 228 if (err)
169 goto out; 229 goto out;
@@ -197,9 +257,10 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate,
197 return err; 257 return err;
198 } 258 }
199 259
200 if (!i2c_rate[bus_id - 1]) 260 if (!i2c_pdata[bus_id - 1].clkrate)
201 i2c_rate[bus_id - 1] = clkrate; 261 i2c_pdata[bus_id - 1].clkrate = clkrate;
202 i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; 262
263 i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP;
203 264
204 return omap_i2c_add_bus(bus_id); 265 return omap_i2c_add_bus(bus_id);
205} 266}