[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-3.0 / pm-wip / voltdm / 0125-OMAP3-VC-make-I2C-config-programmable-with-PMIC-spec.patch
1 From 14fd863086d151e68a44c18a16726587ab9d6f8e Mon Sep 17 00:00:00 2001
2 From: Kevin Hilman <khilman@ti.com>
3 Date: Wed, 30 Mar 2011 16:36:30 -0700
4 Subject: [PATCH 125/149] OMAP3+: VC: make I2C config programmable with PMIC-specific settings
6 Remove hard-coded I2C configuration in favor of settings that can be
7 configured from PMIC-specific values. Currently only high-speed mode
8 and the master-code value are supported, since they were the only
9 fields currently used, but extending this is now trivial.
11 Thanks to Nishanth Menon <nm@ti.com> for reporting/fixing a sparse
12 problem and making omap_vc_i2c_init() static, as well as finding and
13 fixing a problem with the shift/mask of mcode.
15 Signed-off-by: Kevin Hilman <khilman@ti.com>
16 ---
17 arch/arm/mach-omap2/omap_twl.c | 4 +++
18 arch/arm/mach-omap2/vc.c | 51 +++++++++++++++++++++++++++++++-----
19 arch/arm/mach-omap2/vc.h | 7 +++++
20 arch/arm/mach-omap2/vc3xxx_data.c | 3 ++
21 arch/arm/mach-omap2/vc44xx_data.c | 3 ++
22 arch/arm/mach-omap2/voltage.h | 4 +++
23 6 files changed, 65 insertions(+), 7 deletions(-)
25 diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
26 index e467d45..6b247d1 100644
27 --- a/arch/arm/mach-omap2/omap_twl.c
28 +++ b/arch/arm/mach-omap2/omap_twl.c
29 @@ -159,6 +159,7 @@ static struct omap_voltdm_pmic omap3_mpu_pmic = {
30 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
31 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
32 .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
33 + .i2c_high_speed = true,
34 .vsel_to_uv = twl4030_vsel_to_uv,
35 .uv_to_vsel = twl4030_uv_to_vsel,
36 };
37 @@ -179,6 +180,7 @@ static struct omap_voltdm_pmic omap3_core_pmic = {
38 .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
39 .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
40 .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
41 + .i2c_high_speed = true,
42 .vsel_to_uv = twl4030_vsel_to_uv,
43 .uv_to_vsel = twl4030_uv_to_vsel,
44 };
45 @@ -199,6 +201,7 @@ static struct omap_voltdm_pmic omap4_mpu_pmic = {
46 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
47 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
48 .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG,
49 + .i2c_high_speed = true,
50 .vsel_to_uv = twl6030_vsel_to_uv,
51 .uv_to_vsel = twl6030_uv_to_vsel,
52 };
53 @@ -219,6 +222,7 @@ static struct omap_voltdm_pmic omap4_iva_pmic = {
54 .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US,
55 .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR,
56 .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG,
57 + .i2c_high_speed = true,
58 .vsel_to_uv = twl6030_vsel_to_uv,
59 .uv_to_vsel = twl6030_uv_to_vsel,
60 };
61 diff --git a/arch/arm/mach-omap2/vc.c b/arch/arm/mach-omap2/vc.c
62 index c431ca2..97a4c6c 100644
63 --- a/arch/arm/mach-omap2/vc.c
64 +++ b/arch/arm/mach-omap2/vc.c
65 @@ -199,13 +199,6 @@ static void __init omap3_vc_init_channel(struct voltagedomain *voltdm)
66 if (is_initialized)
67 return;
69 - /*
70 - * Generic VC parameters init
71 - * XXX This data should be abstracted out
72 - */
73 - voltdm->write(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK,
74 - OMAP3_PRM_VC_I2C_CFG_OFFSET);
75 -
76 omap3_vfsm_init(voltdm);
78 is_initialized = true;
79 @@ -228,6 +221,48 @@ static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
80 is_initialized = true;
81 }
83 +/**
84 + * omap_vc_i2c_init - initialize I2C interface to PMIC
85 + * @voltdm: voltage domain containing VC data
86 + *
87 + * Use PMIC supplied seetings for I2C high-speed mode and
88 + * master code (if set) and program the VC I2C configuration
89 + * register.
90 + *
91 + * The VC I2C configuration is common to all VC channels,
92 + * so this function only configures I2C for the first VC
93 + * channel registers. All other VC channels will use the
94 + * same configuration.
95 + */
96 +static void __init omap_vc_i2c_init(struct voltagedomain *voltdm)
97 +{
98 + struct omap_vc_channel *vc = voltdm->vc;
99 + static bool initialized;
100 + static bool i2c_high_speed;
101 + u8 mcode;
102 +
103 + if (initialized) {
104 + if (voltdm->pmic->i2c_high_speed != i2c_high_speed)
105 + pr_warn("%s: I2C config for all channels must match.",
106 + __func__);
107 + return;
108 + }
109 +
110 + i2c_high_speed = voltdm->pmic->i2c_high_speed;
111 + if (i2c_high_speed)
112 + voltdm->rmw(vc->common->i2c_cfg_hsen_mask,
113 + vc->common->i2c_cfg_hsen_mask,
114 + vc->common->i2c_cfg_reg);
115 +
116 + mcode = voltdm->pmic->i2c_mcode;
117 + if (mcode)
118 + voltdm->rmw(vc->common->i2c_mcode_mask,
119 + mcode << __ffs(vc->common->i2c_mcode_mask),
120 + vc->common->i2c_cfg_reg);
121 +
122 + initialized = true;
123 +}
124 +
125 void __init omap_vc_init_channel(struct voltagedomain *voltdm)
126 {
127 struct omap_vc_channel *vc = voltdm->vc;
128 @@ -296,6 +331,8 @@ void __init omap_vc_init_channel(struct voltagedomain *voltdm)
129 vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask),
130 voltdm->vfsm->voltsetup_reg);
132 + omap_vc_i2c_init(voltdm);
133 +
134 if (cpu_is_omap34xx())
135 omap3_vc_init_channel(voltdm);
136 else if (cpu_is_omap44xx())
137 diff --git a/arch/arm/mach-omap2/vc.h b/arch/arm/mach-omap2/vc.h
138 index 604f5b6..c577f28 100644
139 --- a/arch/arm/mach-omap2/vc.h
140 +++ b/arch/arm/mach-omap2/vc.h
141 @@ -35,6 +35,9 @@ struct voltagedomain;
142 * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
143 * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
144 * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
145 + * @i2c_cfg_reg: I2C configuration register offset
146 + * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register
147 + * @i2c_mcode_mask: MCODE field mask for I2C config register
148 *
149 * XXX One of cmd_on_mask and cmd_on_shift are not needed
150 * XXX VALID should probably be a shift, not a mask
151 @@ -54,6 +57,9 @@ struct omap_vc_common {
152 u8 cmd_ret_shift;
153 u8 cmd_off_shift;
154 u8 cfg_channel_reg;
155 + u8 i2c_cfg_reg;
156 + u8 i2c_cfg_hsen_mask;
157 + u8 i2c_mcode_mask;
158 };
160 /* omap_vc_channel.flags values */
161 @@ -75,6 +81,7 @@ struct omap_vc_channel {
162 u16 cmd_reg_addr;
163 u16 setup_time;
164 u8 cfg_channel;
165 + bool i2c_high_speed;
167 /* register access data */
168 const struct omap_vc_common *common;
169 diff --git a/arch/arm/mach-omap2/vc3xxx_data.c b/arch/arm/mach-omap2/vc3xxx_data.c
170 index f4449eb..95d7701 100644
171 --- a/arch/arm/mach-omap2/vc3xxx_data.c
172 +++ b/arch/arm/mach-omap2/vc3xxx_data.c
173 @@ -44,6 +44,9 @@ static struct omap_vc_common omap3_vc_common = {
174 .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT,
175 .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT,
176 .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET,
177 + .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK,
178 + .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET,
179 + .i2c_mcode_mask = OMAP3430_MCODE_MASK,
180 };
182 struct omap_vc_channel omap3_vc_mpu = {
183 diff --git a/arch/arm/mach-omap2/vc44xx_data.c b/arch/arm/mach-omap2/vc44xx_data.c
184 index 1610bde..148be18 100644
185 --- a/arch/arm/mach-omap2/vc44xx_data.c
186 +++ b/arch/arm/mach-omap2/vc44xx_data.c
187 @@ -45,6 +45,9 @@ static const struct omap_vc_common omap4_vc_common = {
188 .cmd_ret_shift = OMAP4430_RET_SHIFT,
189 .cmd_off_shift = OMAP4430_OFF_SHIFT,
190 .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET,
191 + .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET,
192 + .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK,
193 + .i2c_mcode_mask = OMAP4430_HSMCODE_MASK,
194 };
196 /* VC instance data for each controllable voltage line */
197 diff --git a/arch/arm/mach-omap2/voltage.h b/arch/arm/mach-omap2/voltage.h
198 index 72a0255..a0ae5c6 100644
199 --- a/arch/arm/mach-omap2/voltage.h
200 +++ b/arch/arm/mach-omap2/voltage.h
201 @@ -101,6 +101,8 @@ struct omap_volt_data {
202 * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
203 * @slew_rate: PMIC slew rate (in uv/us)
204 * @step_size: PMIC voltage step size (in uv)
205 + * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC
206 + * @i2c_mcode: master code value for I2C high-speed preamble transmission
207 * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV.
208 * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value.
209 */
210 @@ -121,6 +123,8 @@ struct omap_voltdm_pmic {
211 u8 vp_vddmin;
212 u8 vp_vddmax;
213 u8 vp_timeout_us;
214 + bool i2c_high_speed;
215 + u8 i2c_mcode;
216 unsigned long (*vsel_to_uv) (const u8 vsel);
217 u8 (*uv_to_vsel) (unsigned long uV);
218 };
219 --
220 1.6.6.1