Commit f5395480f5088a86cc8594d29b5c2f07f6995c3d
1 parent
ce8ebe0dfb
Exists in
master
and in
4 other branches
OMAP3+: VC: make I2C config programmable with PMIC-specific settings
Remove hard-coded I2C configuration in favor of settings that can be configured from PMIC-specific values. Currently only high-speed mode and the master-code value are supported, since they were the only fields currently used, but extending this is now trivial. Thanks to Nishanth Menon <nm@ti.com> for reporting/fixing a sparse problem and making omap_vc_i2c_init() static, as well as finding and fixing a problem with the shift/mask of mcode. Signed-off-by: Kevin Hilman <khilman@ti.com>
Showing 6 changed files with 66 additions and 7 deletions Side-by-side Diff
arch/arm/mach-omap2/omap_twl.c
... | ... | @@ -159,6 +159,7 @@ |
159 | 159 | .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, |
160 | 160 | .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, |
161 | 161 | .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG, |
162 | + .i2c_high_speed = true, | |
162 | 163 | .vsel_to_uv = twl4030_vsel_to_uv, |
163 | 164 | .uv_to_vsel = twl4030_uv_to_vsel, |
164 | 165 | }; |
... | ... | @@ -179,6 +180,7 @@ |
179 | 180 | .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US, |
180 | 181 | .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR, |
181 | 182 | .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG, |
183 | + .i2c_high_speed = true, | |
182 | 184 | .vsel_to_uv = twl4030_vsel_to_uv, |
183 | 185 | .uv_to_vsel = twl4030_uv_to_vsel, |
184 | 186 | }; |
... | ... | @@ -199,6 +201,7 @@ |
199 | 201 | .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, |
200 | 202 | .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, |
201 | 203 | .volt_reg_addr = OMAP4_VDD_MPU_SR_VOLT_REG, |
204 | + .i2c_high_speed = true, | |
202 | 205 | .vsel_to_uv = twl6030_vsel_to_uv, |
203 | 206 | .uv_to_vsel = twl6030_uv_to_vsel, |
204 | 207 | }; |
... | ... | @@ -219,6 +222,7 @@ |
219 | 222 | .vp_timeout_us = OMAP4_VP_VLIMITTO_TIMEOUT_US, |
220 | 223 | .i2c_slave_addr = OMAP4_SRI2C_SLAVE_ADDR, |
221 | 224 | .volt_reg_addr = OMAP4_VDD_IVA_SR_VOLT_REG, |
225 | + .i2c_high_speed = true, | |
222 | 226 | .vsel_to_uv = twl6030_vsel_to_uv, |
223 | 227 | .uv_to_vsel = twl6030_uv_to_vsel, |
224 | 228 | }; |
arch/arm/mach-omap2/vc.c
... | ... | @@ -208,13 +208,6 @@ |
208 | 208 | if (is_initialized) |
209 | 209 | return; |
210 | 210 | |
211 | - /* | |
212 | - * Generic VC parameters init | |
213 | - * XXX This data should be abstracted out | |
214 | - */ | |
215 | - voltdm->write(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, | |
216 | - OMAP3_PRM_VC_I2C_CFG_OFFSET); | |
217 | - | |
218 | 211 | omap3_vfsm_init(voltdm); |
219 | 212 | |
220 | 213 | is_initialized = true; |
... | ... | @@ -237,6 +230,48 @@ |
237 | 230 | is_initialized = true; |
238 | 231 | } |
239 | 232 | |
233 | +/** | |
234 | + * omap_vc_i2c_init - initialize I2C interface to PMIC | |
235 | + * @voltdm: voltage domain containing VC data | |
236 | + * | |
237 | + * Use PMIC supplied seetings for I2C high-speed mode and | |
238 | + * master code (if set) and program the VC I2C configuration | |
239 | + * register. | |
240 | + * | |
241 | + * The VC I2C configuration is common to all VC channels, | |
242 | + * so this function only configures I2C for the first VC | |
243 | + * channel registers. All other VC channels will use the | |
244 | + * same configuration. | |
245 | + */ | |
246 | +static void __init omap_vc_i2c_init(struct voltagedomain *voltdm) | |
247 | +{ | |
248 | + struct omap_vc_channel *vc = voltdm->vc; | |
249 | + static bool initialized; | |
250 | + static bool i2c_high_speed; | |
251 | + u8 mcode; | |
252 | + | |
253 | + if (initialized) { | |
254 | + if (voltdm->pmic->i2c_high_speed != i2c_high_speed) | |
255 | + pr_warn("%s: I2C config for all channels must match.", | |
256 | + __func__); | |
257 | + return; | |
258 | + } | |
259 | + | |
260 | + i2c_high_speed = voltdm->pmic->i2c_high_speed; | |
261 | + if (i2c_high_speed) | |
262 | + voltdm->rmw(vc->common->i2c_cfg_hsen_mask, | |
263 | + vc->common->i2c_cfg_hsen_mask, | |
264 | + vc->common->i2c_cfg_reg); | |
265 | + | |
266 | + mcode = voltdm->pmic->i2c_mcode; | |
267 | + if (mcode) | |
268 | + voltdm->rmw(vc->common->i2c_mcode_mask, | |
269 | + mcode << __ffs(vc->common->i2c_mcode_mask), | |
270 | + vc->common->i2c_cfg_reg); | |
271 | + | |
272 | + initialized = true; | |
273 | +} | |
274 | + | |
240 | 275 | void __init omap_vc_init_channel(struct voltagedomain *voltdm) |
241 | 276 | { |
242 | 277 | struct omap_vc_channel *vc = voltdm->vc; |
... | ... | @@ -304,6 +339,8 @@ |
304 | 339 | voltdm->rmw(voltdm->vfsm->voltsetup_mask, |
305 | 340 | vc->setup_time << __ffs(voltdm->vfsm->voltsetup_mask), |
306 | 341 | voltdm->vfsm->voltsetup_reg); |
342 | + | |
343 | + omap_vc_i2c_init(voltdm); | |
307 | 344 | |
308 | 345 | if (cpu_is_omap34xx()) |
309 | 346 | omap3_vc_init_channel(voltdm); |
arch/arm/mach-omap2/vc.h
... | ... | @@ -37,6 +37,9 @@ |
37 | 37 | * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register |
38 | 38 | * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register |
39 | 39 | * @cfg_channel_reg: VC channel configuration register |
40 | + * @i2c_cfg_reg: I2C configuration register offset | |
41 | + * @i2c_cfg_hsen_mask: high-speed mode bit field mask in I2C config register | |
42 | + * @i2c_mcode_mask: MCODE field mask for I2C config register | |
40 | 43 | * |
41 | 44 | * XXX One of cmd_on_mask and cmd_on_shift are not needed |
42 | 45 | * XXX VALID should probably be a shift, not a mask |
... | ... | @@ -56,6 +59,9 @@ |
56 | 59 | u8 cmd_ret_shift; |
57 | 60 | u8 cmd_off_shift; |
58 | 61 | u8 cfg_channel_reg; |
62 | + u8 i2c_cfg_reg; | |
63 | + u8 i2c_cfg_hsen_mask; | |
64 | + u8 i2c_mcode_mask; | |
59 | 65 | }; |
60 | 66 | |
61 | 67 | /* omap_vc_channel.flags values */ |
... | ... | @@ -68,6 +74,7 @@ |
68 | 74 | * @cmd_reg_addr: command configuration register address |
69 | 75 | * @setup_time: setup time (in sys_clk cycles) of regulator for this channel |
70 | 76 | * @cfg_channel: current value of VC channel configuration register |
77 | + * @i2c_high_speed: whether or not to use I2C high-speed mode | |
71 | 78 | * |
72 | 79 | * @common: pointer to VC common data for this platform |
73 | 80 | * @smps_sa_mask: i2c slave address bitmask in the PRM_VC_SMPS_SA register |
... | ... | @@ -84,6 +91,7 @@ |
84 | 91 | u16 cmd_reg_addr; |
85 | 92 | u16 setup_time; |
86 | 93 | u8 cfg_channel; |
94 | + bool i2c_high_speed; | |
87 | 95 | |
88 | 96 | /* register access data */ |
89 | 97 | const struct omap_vc_common *common; |
arch/arm/mach-omap2/vc3xxx_data.c
... | ... | @@ -44,6 +44,9 @@ |
44 | 44 | .cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT, |
45 | 45 | .cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT, |
46 | 46 | .cfg_channel_reg = OMAP3_PRM_VC_CH_CONF_OFFSET, |
47 | + .i2c_cfg_hsen_mask = OMAP3430_HSEN_MASK, | |
48 | + .i2c_cfg_reg = OMAP3_PRM_VC_I2C_CFG_OFFSET, | |
49 | + .i2c_mcode_mask = OMAP3430_MCODE_MASK, | |
47 | 50 | }; |
48 | 51 | |
49 | 52 | struct omap_vc_channel omap3_vc_mpu = { |
arch/arm/mach-omap2/vc44xx_data.c
... | ... | @@ -45,6 +45,9 @@ |
45 | 45 | .cmd_ret_shift = OMAP4430_RET_SHIFT, |
46 | 46 | .cmd_off_shift = OMAP4430_OFF_SHIFT, |
47 | 47 | .cfg_channel_reg = OMAP4_PRM_VC_CFG_CHANNEL_OFFSET, |
48 | + .i2c_cfg_reg = OMAP4_PRM_VC_CFG_I2C_MODE_OFFSET, | |
49 | + .i2c_cfg_hsen_mask = OMAP4430_HSMODEEN_MASK, | |
50 | + .i2c_mcode_mask = OMAP4430_HSMCODE_MASK, | |
48 | 51 | }; |
49 | 52 | |
50 | 53 | /* VC instance data for each controllable voltage line */ |
arch/arm/mach-omap2/voltage.h
... | ... | @@ -103,6 +103,8 @@ |
103 | 103 | * @i2c_slave_addr: I2C slave address of PMIC |
104 | 104 | * @volt_reg_addr: voltage configuration register address |
105 | 105 | * @cmd_reg_addr: command (on, on-LP, ret, off) configuration register address |
106 | + * @i2c_high_speed: whether VC uses I2C high-speed mode to PMIC | |
107 | + * @i2c_mcode: master code value for I2C high-speed preamble transmission | |
106 | 108 | * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV. |
107 | 109 | * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value. |
108 | 110 | */ |
... | ... | @@ -123,6 +125,8 @@ |
123 | 125 | u8 vp_vddmin; |
124 | 126 | u8 vp_vddmax; |
125 | 127 | u8 vp_timeout_us; |
128 | + bool i2c_high_speed; | |
129 | + u8 i2c_mcode; | |
126 | 130 | unsigned long (*vsel_to_uv) (const u8 vsel); |
127 | 131 | u8 (*uv_to_vsel) (unsigned long uV); |
128 | 132 | }; |