|
@@ -382,3 +382,127 @@ static u32 omap4_calc_volt_ramp(struct voltagedomain *voltdm, u32 voltage_diff)
|
|
|
cycles /= 4;
|
|
|
prescaler++;
|
|
|
}
|
|
|
+
|
|
|
+ /* check for overflow => invalid ramp time */
|
|
|
+ if (cycles > 63) {
|
|
|
+ pr_warn("%s: invalid setuptime for vdd_%s\n", __func__,
|
|
|
+ voltdm->name);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ cycles++;
|
|
|
+
|
|
|
+ return (prescaler << OMAP4430_RAMP_UP_PRESCAL_SHIFT) |
|
|
|
+ (cycles << OMAP4430_RAMP_UP_COUNT_SHIFT);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap4_usec_to_val_scrm - convert microsecond value to SCRM module bitfield
|
|
|
+ * @usec: microseconds
|
|
|
+ * @shift: number of bits to shift left
|
|
|
+ * @mask: bitfield mask
|
|
|
+ *
|
|
|
+ * Converts microsecond value to OMAP4 SCRM bitfield. Bitfield is
|
|
|
+ * shifted to requested position, and checked agains the mask value.
|
|
|
+ * If larger, forced to the max value of the field (i.e. the mask itself.)
|
|
|
+ * Returns the SCRM bitfield value.
|
|
|
+ */
|
|
|
+static u32 omap4_usec_to_val_scrm(u32 usec, int shift, u32 mask)
|
|
|
+{
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ val = omap_usec_to_32k(usec) << shift;
|
|
|
+
|
|
|
+ /* Check for overflow, if yes, force to max value */
|
|
|
+ if (val > mask)
|
|
|
+ val = mask;
|
|
|
+
|
|
|
+ return val;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * omap4_set_timings - set voltage ramp timings for a channel
|
|
|
+ * @voltdm: channel to configure
|
|
|
+ * @off_mode: whether off-mode values are used
|
|
|
+ *
|
|
|
+ * Calculates and sets the voltage ramp up / down values for a channel.
|
|
|
+ */
|
|
|
+static void omap4_set_timings(struct voltagedomain *voltdm, bool off_mode)
|
|
|
+{
|
|
|
+ u32 val;
|
|
|
+ u32 ramp;
|
|
|
+ int offset;
|
|
|
+ u32 tstart, tshut;
|
|
|
+
|
|
|
+ if (off_mode) {
|
|
|
+ ramp = omap4_calc_volt_ramp(voltdm,
|
|
|
+ voltdm->vc_param->on - voltdm->vc_param->off);
|
|
|
+ offset = voltdm->vfsm->voltsetup_off_reg;
|
|
|
+ } else {
|
|
|
+ ramp = omap4_calc_volt_ramp(voltdm,
|
|
|
+ voltdm->vc_param->on - voltdm->vc_param->ret);
|
|
|
+ offset = voltdm->vfsm->voltsetup_reg;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!ramp)
|
|
|
+ return;
|
|
|
+
|
|
|
+ val = voltdm->read(offset);
|
|
|
+
|
|
|
+ val |= ramp << OMAP4430_RAMP_DOWN_COUNT_SHIFT;
|
|
|
+
|
|
|
+ val |= ramp << OMAP4430_RAMP_UP_COUNT_SHIFT;
|
|
|
+
|
|
|
+ voltdm->write(val, offset);
|
|
|
+
|
|
|
+ omap_pm_get_oscillator(&tstart, &tshut);
|
|
|
+
|
|
|
+ val = omap4_usec_to_val_scrm(tstart, OMAP4_SETUPTIME_SHIFT,
|
|
|
+ OMAP4_SETUPTIME_MASK);
|
|
|
+ val |= omap4_usec_to_val_scrm(tshut, OMAP4_DOWNTIME_SHIFT,
|
|
|
+ OMAP4_DOWNTIME_MASK);
|
|
|
+
|
|
|
+ __raw_writel(val, OMAP4_SCRM_CLKSETUPTIME);
|
|
|
+}
|
|
|
+
|
|
|
+/* OMAP4 specific voltage init functions */
|
|
|
+static void __init omap4_vc_init_channel(struct voltagedomain *voltdm)
|
|
|
+{
|
|
|
+ omap4_set_timings(voltdm, true);
|
|
|
+ omap4_set_timings(voltdm, false);
|
|
|
+}
|
|
|
+
|
|
|
+struct i2c_init_data {
|
|
|
+ u8 loadbits;
|
|
|
+ u8 load;
|
|
|
+ u8 hsscll_38_4;
|
|
|
+ u8 hsscll_26;
|
|
|
+ u8 hsscll_19_2;
|
|
|
+ u8 hsscll_16_8;
|
|
|
+ u8 hsscll_12;
|
|
|
+};
|
|
|
+
|
|
|
+static const __initdata struct i2c_init_data omap4_i2c_timing_data[] = {
|
|
|
+ {
|
|
|
+ .load = 50,
|
|
|
+ .loadbits = 0x3,
|
|
|
+ .hsscll_38_4 = 13,
|
|
|
+ .hsscll_26 = 11,
|
|
|
+ .hsscll_19_2 = 9,
|
|
|
+ .hsscll_16_8 = 9,
|
|
|
+ .hsscll_12 = 8,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .load = 25,
|
|
|
+ .loadbits = 0x2,
|
|
|
+ .hsscll_38_4 = 13,
|
|
|
+ .hsscll_26 = 11,
|
|
|
+ .hsscll_19_2 = 9,
|
|
|
+ .hsscll_16_8 = 9,
|
|
|
+ .hsscll_12 = 8,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .load = 12,
|
|
|
+ .loadbits = 0x1,
|
|
|
+ .hsscll_38_4 = 11,
|
|
|
+ .hsscll_26 = 10,
|