diff options
Diffstat (limited to 'arch/arm/mach-omap2/i2c.c')
-rw-r--r-- | arch/arm/mach-omap2/i2c.c | 93 |
1 files changed, 87 insertions, 6 deletions
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c index fc57e67b321f..b9074dde3b9c 100644 --- a/arch/arm/mach-omap2/i2c.c +++ b/arch/arm/mach-omap2/i2c.c | |||
@@ -19,21 +19,24 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <plat/i2c.h> | 22 | #include "soc.h" |
23 | #include "common.h" | 23 | #include "omap_hwmod.h" |
24 | #include <plat/omap_hwmod.h> | 24 | #include "omap_device.h" |
25 | #include "omap-pm.h" | ||
25 | 26 | ||
27 | #include "prm.h" | ||
28 | #include "common.h" | ||
26 | #include "mux.h" | 29 | #include "mux.h" |
30 | #include "i2c.h" | ||
27 | 31 | ||
28 | /* In register I2C_CON, Bit 15 is the I2C enable bit */ | 32 | /* In register I2C_CON, Bit 15 is the I2C enable bit */ |
29 | #define I2C_EN BIT(15) | 33 | #define I2C_EN BIT(15) |
30 | #define OMAP2_I2C_CON_OFFSET 0x24 | 34 | #define OMAP2_I2C_CON_OFFSET 0x24 |
31 | #define OMAP4_I2C_CON_OFFSET 0xA4 | 35 | #define OMAP4_I2C_CON_OFFSET 0xA4 |
32 | 36 | ||
33 | /* Maximum microseconds to wait for OMAP module to softreset */ | 37 | #define MAX_OMAP_I2C_HWMOD_NAME_LEN 16 |
34 | #define MAX_MODULE_SOFTRESET_WAIT 10000 | ||
35 | 38 | ||
36 | void __init omap2_i2c_mux_pins(int bus_id) | 39 | static void __init omap2_i2c_mux_pins(int bus_id) |
37 | { | 40 | { |
38 | char mux_name[sizeof("i2c2_scl.i2c2_scl")]; | 41 | char mux_name[sizeof("i2c2_scl.i2c2_scl")]; |
39 | 42 | ||
@@ -104,3 +107,81 @@ int omap_i2c_reset(struct omap_hwmod *oh) | |||
104 | 107 | ||
105 | return 0; | 108 | return 0; |
106 | } | 109 | } |
110 | |||
111 | static int __init omap_i2c_nr_ports(void) | ||
112 | { | ||
113 | int ports = 0; | ||
114 | |||
115 | if (cpu_is_omap24xx()) | ||
116 | ports = 2; | ||
117 | else if (cpu_is_omap34xx()) | ||
118 | ports = 3; | ||
119 | else if (cpu_is_omap44xx()) | ||
120 | ports = 4; | ||
121 | return ports; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * XXX This function is a temporary compatibility wrapper - only | ||
126 | * needed until the I2C driver can be converted to call | ||
127 | * omap_pm_set_max_dev_wakeup_lat() and handle a return code. | ||
128 | */ | ||
129 | static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) | ||
130 | { | ||
131 | omap_pm_set_max_mpu_wakeup_lat(dev, t); | ||
132 | } | ||
133 | |||
134 | static const char name[] = "omap_i2c"; | ||
135 | |||
136 | int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata, | ||
137 | int bus_id) | ||
138 | { | ||
139 | int l; | ||
140 | struct omap_hwmod *oh; | ||
141 | struct platform_device *pdev; | ||
142 | char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN]; | ||
143 | struct omap_i2c_bus_platform_data *pdata; | ||
144 | struct omap_i2c_dev_attr *dev_attr; | ||
145 | |||
146 | if (bus_id > omap_i2c_nr_ports()) | ||
147 | return -EINVAL; | ||
148 | |||
149 | omap2_i2c_mux_pins(bus_id); | ||
150 | |||
151 | l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id); | ||
152 | WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN, | ||
153 | "String buffer overflow in I2C%d device setup\n", bus_id); | ||
154 | oh = omap_hwmod_lookup(oh_name); | ||
155 | if (!oh) { | ||
156 | pr_err("Could not look up %s\n", oh_name); | ||
157 | return -EEXIST; | ||
158 | } | ||
159 | |||
160 | pdata = i2c_pdata; | ||
161 | /* | ||
162 | * pass the hwmod class's CPU-specific knowledge of I2C IP revision in | ||
163 | * use, and functionality implementation flags, up to the OMAP I2C | ||
164 | * driver via platform data | ||
165 | */ | ||
166 | pdata->rev = oh->class->rev; | ||
167 | |||
168 | dev_attr = (struct omap_i2c_dev_attr *)oh->dev_attr; | ||
169 | pdata->flags = dev_attr->flags; | ||
170 | |||
171 | /* | ||
172 | * When waiting for completion of a i2c transfer, we need to | ||
173 | * set a wake up latency constraint for the MPU. This is to | ||
174 | * ensure quick enough wakeup from idle, when transfer | ||
175 | * completes. | ||
176 | * Only omap3 has support for constraints | ||
177 | */ | ||
178 | if (cpu_is_omap34xx()) | ||
179 | pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; | ||
180 | pdev = omap_device_build(name, bus_id, oh, pdata, | ||
181 | sizeof(struct omap_i2c_bus_platform_data), | ||
182 | NULL, 0, 0); | ||
183 | WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name); | ||
184 | |||
185 | return PTR_RET(pdev); | ||
186 | } | ||
187 | |||