diff options
Diffstat (limited to 'arch/arm/mach-omap2/i2c.c')
-rw-r--r-- | arch/arm/mach-omap2/i2c.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c index 79c478c4cb1..ace99944e96 100644 --- a/arch/arm/mach-omap2/i2c.c +++ b/arch/arm/mach-omap2/i2c.c | |||
@@ -21,9 +21,19 @@ | |||
21 | 21 | ||
22 | #include <plat/cpu.h> | 22 | #include <plat/cpu.h> |
23 | #include <plat/i2c.h> | 23 | #include <plat/i2c.h> |
24 | #include <plat/common.h> | ||
25 | #include <plat/omap_hwmod.h> | ||
24 | 26 | ||
25 | #include "mux.h" | 27 | #include "mux.h" |
26 | 28 | ||
29 | /* In register I2C_CON, Bit 15 is the I2C enable bit */ | ||
30 | #define I2C_EN BIT(15) | ||
31 | #define OMAP2_I2C_CON_OFFSET 0x24 | ||
32 | #define OMAP4_I2C_CON_OFFSET 0xA4 | ||
33 | |||
34 | /* Maximum microseconds to wait for OMAP module to softreset */ | ||
35 | #define MAX_MODULE_SOFTRESET_WAIT 10000 | ||
36 | |||
27 | void __init omap2_i2c_mux_pins(int bus_id) | 37 | void __init omap2_i2c_mux_pins(int bus_id) |
28 | { | 38 | { |
29 | char mux_name[sizeof("i2c2_scl.i2c2_scl")]; | 39 | char mux_name[sizeof("i2c2_scl.i2c2_scl")]; |
@@ -37,3 +47,61 @@ void __init omap2_i2c_mux_pins(int bus_id) | |||
37 | sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id); | 47 | sprintf(mux_name, "i2c%i_sda.i2c%i_sda", bus_id, bus_id); |
38 | omap_mux_init_signal(mux_name, OMAP_PIN_INPUT); | 48 | omap_mux_init_signal(mux_name, OMAP_PIN_INPUT); |
39 | } | 49 | } |
50 | |||
51 | /** | ||
52 | * omap_i2c_reset - reset the omap i2c module. | ||
53 | * @oh: struct omap_hwmod * | ||
54 | * | ||
55 | * The i2c moudle in omap2, omap3 had a special sequence to reset. The | ||
56 | * sequence is: | ||
57 | * - Disable the I2C. | ||
58 | * - Write to SOFTRESET bit. | ||
59 | * - Enable the I2C. | ||
60 | * - Poll on the RESETDONE bit. | ||
61 | * The sequence is implemented in below function. This is called for 2420, | ||
62 | * 2430 and omap3. | ||
63 | */ | ||
64 | int omap_i2c_reset(struct omap_hwmod *oh) | ||
65 | { | ||
66 | u32 v; | ||
67 | u16 i2c_con; | ||
68 | int c = 0; | ||
69 | |||
70 | if (oh->class->rev == OMAP_I2C_IP_VERSION_2) { | ||
71 | i2c_con = OMAP4_I2C_CON_OFFSET; | ||
72 | } else if (oh->class->rev == OMAP_I2C_IP_VERSION_1) { | ||
73 | i2c_con = OMAP2_I2C_CON_OFFSET; | ||
74 | } else { | ||
75 | WARN(1, "Cannot reset I2C block %s: unsupported revision\n", | ||
76 | oh->name); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | |||
80 | /* Disable I2C */ | ||
81 | v = omap_hwmod_read(oh, i2c_con); | ||
82 | v &= ~I2C_EN; | ||
83 | omap_hwmod_write(v, oh, i2c_con); | ||
84 | |||
85 | /* Write to the SOFTRESET bit */ | ||
86 | omap_hwmod_softreset(oh); | ||
87 | |||
88 | /* Enable I2C */ | ||
89 | v = omap_hwmod_read(oh, i2c_con); | ||
90 | v |= I2C_EN; | ||
91 | omap_hwmod_write(v, oh, i2c_con); | ||
92 | |||
93 | /* Poll on RESETDONE bit */ | ||
94 | omap_test_timeout((omap_hwmod_read(oh, | ||
95 | oh->class->sysc->syss_offs) | ||
96 | & SYSS_RESETDONE_MASK), | ||
97 | MAX_MODULE_SOFTRESET_WAIT, c); | ||
98 | |||
99 | if (c == MAX_MODULE_SOFTRESET_WAIT) | ||
100 | pr_warning("%s: %s: softreset failed (waited %d usec)\n", | ||
101 | __func__, oh->name, MAX_MODULE_SOFTRESET_WAIT); | ||
102 | else | ||
103 | pr_debug("%s: %s: softreset in %d usec\n", __func__, | ||
104 | oh->name, c); | ||
105 | |||
106 | return 0; | ||
107 | } | ||