return;
 }
 
-/* Returns the DPLL rate */
+/**
+ * omap2_get_dpll_rate - returns the current DPLL CLKOUT rate
+ * @clk: struct clk * of a DPLL
+ *
+ * DPLLs can be locked or bypassed - basically, enabled or disabled.
+ * When locked, the DPLL output depends on the M and N values.  When
+ * bypassed, on OMAP2xxx, the output rate is either the 32KiHz clock
+ * or sys_clk.  Bypass rates on OMAP3 depend on the DPLL: DPLLs 1 and
+ * 2 are bypassed with dpll1_fclk and dpll2_fclk respectively
+ * (generated by DPLL3), while DPLL 3, 4, and 5 bypass rates are sys_clk.
+ * Returns the current DPLL CLKOUT rate (*not* CLKOUTX2) if the DPLL is
+ * locked, or the appropriate bypass rate if the DPLL is bypassed, or 0
+ * if the clock @clk is not a DPLL.
+ */
 u32 omap2_get_dpll_rate(struct clk *clk)
 {
        long long dpll_clk;
-       u32 dpll_mult, dpll_div, dpll;
+       u32 dpll_mult, dpll_div, v;
        struct dpll_data *dd;
 
        dd = clk->dpll_data;
-       /* REVISIT: What do we return on error? */
        if (!dd)
                return 0;
 
-       dpll = __raw_readl(dd->mult_div1_reg);
-       dpll_mult = dpll & dd->mult_mask;
+       /* Return bypass rate if DPLL is bypassed */
+       v = __raw_readl(dd->control_reg);
+       v &= dd->enable_mask;
+       v >>= __ffs(dd->enable_mask);
+
+       if (cpu_is_omap24xx()) {
+               if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
+                   v == OMAP2XXX_EN_DPLL_FRBYPASS)
+                       return dd->clk_bypass->rate;
+       } else if (cpu_is_omap34xx()) {
+               if (v == OMAP3XXX_EN_DPLL_LPBYPASS ||
+                   v == OMAP3XXX_EN_DPLL_FRBYPASS)
+                       return dd->clk_bypass->rate;
+       }
+
+       v = __raw_readl(dd->mult_div1_reg);
+       dpll_mult = v & dd->mult_mask;
        dpll_mult >>= __ffs(dd->mult_mask);
-       dpll_div = dpll & dd->div1_mask;
+       dpll_div = v & dd->div1_mask;
        dpll_div >>= __ffs(dd->div1_mask);
 
-       dpll_clk = (long long)clk->parent->rate * dpll_mult;
+       dpll_clk = (long long)dd->clk_ref->rate * dpll_mult;
        do_div(dpll_clk, dpll_div + 1);
 
        return dpll_clk;
        pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
                 "%ld\n", clk->name, target_rate);
 
-       scaled_rt_rp = target_rate / (clk->parent->rate / DPLL_SCALE_FACTOR);
+       scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
        scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
 
        dd->last_rounded_rate = 0;
                        break;
 
                r = _dpll_test_mult(&m, n, &new_rate, target_rate,
-                                   clk->parent->rate);
+                                   dd->clk_ref->rate);
 
                /* m can't be set low enough for this n - try with a larger n */
                if (r == DPLL_MULT_UNDERFLOW)
 
        dd->last_rounded_m = min_e_m;
        dd->last_rounded_n = min_e_n;
-       dd->last_rounded_rate = _dpll_compute_new_rate(clk->parent->rate,
+       dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
                                                       min_e_m,  min_e_n);
 
        pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
 
        CLK(NULL,       "omap_96m_alwon_fck", &omap_96m_alwon_fck, CK_343X),
        CLK(NULL,       "omap_96m_fck", &omap_96m_fck,  CK_343X),
        CLK(NULL,       "cm_96m_fck",   &cm_96m_fck,    CK_343X),
-       CLK(NULL,       "virt_omap_54m_fck", &virt_omap_54m_fck, CK_343X),
        CLK(NULL,       "omap_54m_fck", &omap_54m_fck,  CK_343X),
        CLK(NULL,       "omap_48m_fck", &omap_48m_fck,  CK_343X),
        CLK(NULL,       "omap_12m_fck", &omap_12m_fck,  CK_343X),
        CLK(NULL,       "emu_per_alwon_ck", &emu_per_alwon_ck, CK_343X),
        CLK(NULL,       "dpll5_ck",     &dpll5_ck,      CK_3430ES2),
        CLK(NULL,       "dpll5_m2_ck",  &dpll5_m2_ck,   CK_3430ES2),
-       CLK(NULL,       "omap_120m_fck", &omap_120m_fck, CK_3430ES2),
        CLK(NULL,       "clkout2_src_ck", &clkout2_src_ck, CK_343X),
        CLK(NULL,       "sys_clkout2",  &sys_clkout2,   CK_343X),
        CLK(NULL,       "corex2_fck",   &corex2_fck,    CK_343X),
        unsigned long fint;
        u16 f = 0;
 
-       fint = clk->parent->rate / (n + 1);
+       fint = clk->dpll_data->clk_ref->rate / (n + 1);
 
        pr_debug("clock: fint is %lu\n", fint);
 
 }
 
 /*
- * omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
+ * _omap3_noncore_dpll_bypass - instruct a DPLL to bypass and wait for readiness
  * @clk: pointer to a DPLL struct clk
  *
  * Instructs a non-CORE DPLL to enter low-power bypass mode.  In
 static int omap3_noncore_dpll_enable(struct clk *clk)
 {
        int r;
+       struct dpll_data *dd;
 
        if (clk == &dpll3_ck)
                return -EINVAL;
 
-       if (clk->parent->rate == omap2_get_dpll_rate(clk))
+       dd = clk->dpll_data;
+       if (!dd)
+               return -EINVAL;
+
+       if (clk->rate == dd->clk_bypass->rate) {
+               WARN_ON(clk->parent != dd->clk_bypass);
                r = _omap3_noncore_dpll_bypass(clk);
-       else
+       } else {
+               WARN_ON(clk->parent != dd->clk_ref);
                r = _omap3_noncore_dpll_lock(clk);
+       }
+       /* FIXME: this is dubious - if clk->rate has changed, what about propagating? */
+       if (!r)
+               clk->rate = omap2_get_dpll_rate(clk);
 
        return r;
 }
  * @clk: struct clk * of DPLL to set
  * @rate: rounded target rate
  *
- * Program the DPLL with the rounded target rate.  Returns -EINVAL upon
- * error, or 0 upon success.
+ * Set the DPLL CLKOUT to the target rate.  If the DPLL can enter
+ * low-power bypass, and the target rate is the bypass source clock
+ * rate, then configure the DPLL for bypass.  Otherwise, round the
+ * target rate if it hasn't been done already, then program and lock
+ * the DPLL.  Returns -EINVAL upon error, or 0 upon success.
  */
 static int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate)
 {
+       struct clk *new_parent = NULL;
        u16 freqsel;
        struct dpll_data *dd;
+       int ret;
 
        if (!clk || !rate)
                return -EINVAL;
        if (rate == omap2_get_dpll_rate(clk))
                return 0;
 
-       if (dd->last_rounded_rate != rate)
-               omap2_dpll_round_rate(clk, rate);
+       /*
+        * Ensure both the bypass and ref clocks are enabled prior to
+        * doing anything; we need the bypass clock running to reprogram
+        * the DPLL.
+        */
+       omap2_clk_enable(dd->clk_bypass);
+       omap2_clk_enable(dd->clk_ref);
+
+       if (dd->clk_bypass->rate == rate &&
+           (clk->dpll_data->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
+               pr_debug("clock: %s: set rate: entering bypass.\n", clk->name);
 
-       if (dd->last_rounded_rate == 0)
-               return -EINVAL;
+               ret = _omap3_noncore_dpll_bypass(clk);
+               if (!ret)
+                       new_parent = dd->clk_bypass;
+       } else {
+               if (dd->last_rounded_rate != rate)
+                       omap2_dpll_round_rate(clk, rate);
+
+               if (dd->last_rounded_rate == 0)
+                       return -EINVAL;
+
+               freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
+               if (!freqsel)
+                       WARN_ON(1);
 
-       freqsel = _omap3_dpll_compute_freqsel(clk, dd->last_rounded_n);
-       if (!freqsel)
-               WARN_ON(1);
+               pr_debug("clock: %s: set rate: locking rate to %lu.\n",
+                        clk->name, rate);
 
-       omap3_noncore_dpll_program(clk, dd->last_rounded_m, dd->last_rounded_n,
-                                  freqsel);
+               ret = omap3_noncore_dpll_program(clk, dd->last_rounded_m,
+                                                dd->last_rounded_n, freqsel);
+               if (!ret)
+                       new_parent = dd->clk_ref;
+       }
+       if (!ret) {
+               /*
+                * Switch the parent clock in the heirarchy, and make sure
+                * that the new parent's usecount is correct.  Note: we
+                * enable the new parent before disabling the old to avoid
+                * any unnecessary hardware disable->enable transitions.
+                */
+               if (clk->usecount) {
+                       omap2_clk_enable(new_parent);
+                       omap2_clk_disable(clk->parent);
+               }
+               clk_reparent(clk, new_parent);
+               clk->rate = rate;
+       }
+       omap2_clk_disable(dd->clk_ref);
+       omap2_clk_disable(dd->clk_bypass);
 
        return 0;
 }
 
        dd = pclk->dpll_data;
 
-       WARN_ON(!dd->control_reg || !dd->enable_mask);
+       WARN_ON(!dd->enable_mask);
 
        v = __raw_readl(dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
-       if (v != DPLL_LOCKED)
+       if (v != OMAP3XXX_EN_DPLL_LOCKED)
                rate = clk->parent->rate;
        else
                rate = clk->parent->rate * 2;
 
  * DPLL5 supplies other peripheral clocks (USBHOST, USIM).
  */
 
+/* Forward declarations for DPLL bypass clocks */
+static struct clk dpll1_fck;
+static struct clk dpll2_fck;
+
 /* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
 #define DPLL_LOW_POWER_STOP            0x1
 #define DPLL_LOW_POWER_BYPASS          0x5
 
 /* CM CLOCKS */
 
-static const struct clksel_rate dpll_bypass_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
-       { .div = 0 }
-};
-
-static const struct clksel_rate dpll_locked_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
-       { .div = 0 }
-};
-
 static const struct clksel_rate div16_dpll_rates[] = {
        { .div = 1, .val = 1, .flags = RATE_IN_343X | DEFAULT_RATE },
        { .div = 2, .val = 2, .flags = RATE_IN_343X },
        .mult_div1_reg  = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKSEL1_PLL),
        .mult_mask      = OMAP3430_MPU_DPLL_MULT_MASK,
        .div1_mask      = OMAP3430_MPU_DPLL_DIV_MASK,
+       .clk_bypass     = &dpll1_fck,
+       .clk_ref        = &sys_ck,
        .freqsel_mask   = OMAP3430_MPU_DPLL_FREQSEL_MASK,
        .control_reg    = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_CLKEN_PLL),
        .enable_mask    = OMAP3430_EN_MPU_DPLL_MASK,
        .mult_div1_reg  = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKSEL1_PLL),
        .mult_mask      = OMAP3430_IVA2_DPLL_MULT_MASK,
        .div1_mask      = OMAP3430_IVA2_DPLL_DIV_MASK,
+       .clk_bypass     = &dpll2_fck,
+       .clk_ref        = &sys_ck,
        .freqsel_mask   = OMAP3430_IVA2_DPLL_FREQSEL_MASK,
        .control_reg    = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, OMAP3430_CM_CLKEN_PLL),
        .enable_mask    = OMAP3430_EN_IVA2_DPLL_MASK,
        .mult_div1_reg  = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL1),
        .mult_mask      = OMAP3430_CORE_DPLL_MULT_MASK,
        .div1_mask      = OMAP3430_CORE_DPLL_DIV_MASK,
+       .clk_bypass     = &sys_ck,
+       .clk_ref        = &sys_ck,
        .freqsel_mask   = OMAP3430_CORE_DPLL_FREQSEL_MASK,
        .control_reg    = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_mask    = OMAP3430_EN_CORE_DPLL_MASK,
        .recalc         = &omap2_clksel_recalc,
 };
 
-static const struct clksel core_ck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
-       { .parent = &dpll3_m2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk core_ck = {
        .name           = "core_ck",
        .ops            = &clkops_null,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
-       .clksel         = core_ck_clksel,
-       .recalc         = &omap2_clksel_recalc,
-};
-
-static const struct clksel dpll3_m2x2_ck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
-       { .parent = &dpll3_x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
+       .parent         = &dpll3_m2_ck,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk dpll3_m2x2_ck = {
        .name           = "dpll3_m2x2_ck",
        .ops            = &clkops_null,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
-       .clksel         = dpll3_m2x2_ck_clksel,
+       .parent         = &dpll3_x2_ck,
        .clkdm_name     = "dpll3_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 /* The PWRDN bit is apparently only available on 3430ES2 and above */
        .recalc         = &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel emu_core_alwon_ck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
-       { .parent = &dpll3_m3x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk emu_core_alwon_ck = {
        .name           = "emu_core_alwon_ck",
        .ops            = &clkops_null,
        .parent         = &dpll3_m3x2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_CORE_CLK_MASK,
-       .clksel         = emu_core_alwon_ck_clksel,
        .clkdm_name     = "dpll3_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 /* DPLL4 */
        .mult_div1_reg  = OMAP_CM_REGADDR(PLL_MOD, CM_CLKSEL2),
        .mult_mask      = OMAP3430_PERIPH_DPLL_MULT_MASK,
        .div1_mask      = OMAP3430_PERIPH_DPLL_DIV_MASK,
+       .clk_bypass     = &sys_ck,
+       .clk_ref        = &sys_ck,
        .freqsel_mask   = OMAP3430_PERIPH_DPLL_FREQSEL_MASK,
        .control_reg    = OMAP_CM_REGADDR(PLL_MOD, CM_CLKEN),
        .enable_mask    = OMAP3430_EN_PERIPH_DPLL_MASK,
        .recalc         = &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel omap_96m_alwon_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
-       { .parent = &dpll4_m2x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 /*
  * DPLL4 generates DPLL4_M2X2_CLK which is then routed into the PRM as
  * PRM_96M_ALWON_(F)CLK.  Two clocks then emerge from the PRM:
        .name           = "omap_96m_alwon_fck",
        .ops            = &clkops_null,
        .parent         = &dpll4_m2x2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
-       .clksel         = omap_96m_alwon_fck_clksel,
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk cm_96m_fck = {
        .recalc         = &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel virt_omap_54m_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
-       { .parent = &dpll4_m3x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
-static struct clk virt_omap_54m_fck = {
-       .name           = "virt_omap_54m_fck",
-       .ops            = &clkops_null,
-       .parent         = &dpll4_m3x2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
-       .clksel         = virt_omap_54m_fck_clksel,
-       .recalc         = &omap2_clksel_recalc,
-};
-
 static const struct clksel_rate omap_54m_d4m3x2_rates[] = {
        { .div = 1, .val = 0, .flags = RATE_IN_343X | DEFAULT_RATE },
        { .div = 0 }
 };
 
 static const struct clksel omap_54m_clksel[] = {
-       { .parent = &virt_omap_54m_fck, .rates = omap_54m_d4m3x2_rates },
+       { .parent = &dpll4_m3x2_ck, .rates = omap_54m_d4m3x2_rates },
        { .parent = &sys_altclk,    .rates = omap_54m_alt_rates },
        { .parent = NULL }
 };
        .mult_div1_reg  = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKSEL4),
        .mult_mask      = OMAP3430ES2_PERIPH2_DPLL_MULT_MASK,
        .div1_mask      = OMAP3430ES2_PERIPH2_DPLL_DIV_MASK,
+       .clk_bypass     = &sys_ck,
+       .clk_ref        = &sys_ck,
        .freqsel_mask   = OMAP3430ES2_PERIPH2_DPLL_FREQSEL_MASK,
        .control_reg    = OMAP_CM_REGADDR(PLL_MOD, OMAP3430ES2_CM_CLKEN2),
        .enable_mask    = OMAP3430ES2_EN_PERIPH2_DPLL_MASK,
        .recalc         = &omap2_clksel_recalc,
 };
 
-static const struct clksel omap_120m_fck_clksel[] = {
-       { .parent = &sys_ck,      .rates = dpll_bypass_rates },
-       { .parent = &dpll5_m2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
-static struct clk omap_120m_fck = {
-       .name           = "omap_120m_fck",
-       .ops            = &clkops_null,
-       .parent         = &dpll5_m2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST2),
-       .clksel_mask    = OMAP3430ES2_ST_PERIPH2_CLK_MASK,
-       .clksel         = omap_120m_fck_clksel,
-       .recalc         = &omap2_clksel_recalc,
-};
-
 /* CM EXTERNAL CLOCK OUTPUTS */
 
 static const struct clksel_rate clkout2_src_core_rates[] = {
        .recalc         = &omap2_clksel_recalc,
 };
 
-/*
- * MPU clksel:
- * If DPLL1 is locked, mpu_ck derives from DPLL1; otherwise, mpu_ck
- * derives from the high-frequency bypass clock originating from DPLL3,
- * called 'dpll1_fck'
- */
-static const struct clksel mpu_clksel[] = {
-       { .parent = &dpll1_fck,     .rates = dpll_bypass_rates },
-       { .parent = &dpll1_x2m2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk mpu_ck = {
        .name           = "mpu_ck",
        .ops            = &clkops_null,
        .parent         = &dpll1_x2m2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(MPU_MOD, OMAP3430_CM_IDLEST_PLL),
-       .clksel_mask    = OMAP3430_ST_MPU_CLK_MASK,
-       .clksel         = mpu_clksel,
        .clkdm_name     = "mpu_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 /* arm_fck is divided by two when DPLL1 locked; otherwise, passthrough mpu_ck */
        .recalc         = &omap2_clksel_recalc,
 };
 
-/*
- * IVA2 clksel:
- * If DPLL2 is locked, iva2_ck derives from DPLL2; otherwise, iva2_ck
- * derives from the high-frequency bypass clock originating from DPLL3,
- * called 'dpll2_fck'
- */
-
-static const struct clksel iva2_clksel[] = {
-       { .parent = &dpll2_fck,   .rates = dpll_bypass_rates },
-       { .parent = &dpll2_m2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk iva2_ck = {
        .name           = "iva2_ck",
        .ops            = &clkops_omap2_dflt_wait,
        .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
-       .clksel_reg     = OMAP_CM_REGADDR(OMAP3430_IVA2_MOD,
-                                         OMAP3430_CM_IDLEST_PLL),
-       .clksel_mask    = OMAP3430_ST_IVA2_CLK_MASK,
-       .clksel         = iva2_clksel,
        .clkdm_name     = "iva2_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 /* Common interface clocks */
 static struct clk usbtll_fck = {
        .name           = "usbtll_fck",
        .ops            = &clkops_omap2_dflt,
-       .parent         = &omap_120m_fck,
+       .parent         = &dpll5_m2_ck,
        .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, OMAP3430ES2_CM_FCLKEN3),
        .enable_bit     = OMAP3430ES2_EN_USBTLL_SHIFT,
        .recalc         = &followparent_recalc,
 };
 
 /* DSS */
-static const struct clksel dss1_alwon_fck_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
-       { .parent = &dpll4_m4x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk dss1_alwon_fck = {
        .name           = "dss1_alwon_fck",
        .ops            = &clkops_omap2_dflt,
        .parent         = &dpll4_m4x2_ck,
-       .init           = &omap2_init_clksel_parent,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_DSS1_SHIFT,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
-       .clksel         = dss1_alwon_fck_clksel,
        .clkdm_name     = "dss_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk dss_tv_fck = {
 
 /* CAM */
 
-static const struct clksel cam_mclk_clksel[] = {
-       { .parent = &sys_ck,        .rates = dpll_bypass_rates },
-       { .parent = &dpll4_m5x2_ck, .rates = dpll_locked_rates },
-       { .parent = NULL }
-};
-
 static struct clk cam_mclk = {
        .name           = "cam_mclk",
        .ops            = &clkops_omap2_dflt_wait,
        .parent         = &dpll4_m5x2_ck,
-       .init           = &omap2_init_clksel_parent,
-       .clksel_reg     = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
-       .clksel_mask    = OMAP3430_ST_PERIPH_CLK_MASK,
-       .clksel         = cam_mclk_clksel,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430_EN_CAM_SHIFT,
        .clkdm_name     = "cam_clkdm",
-       .recalc         = &omap2_clksel_recalc,
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk cam_ick = {
 static struct clk usbhost_120m_fck = {
        .name           = "usbhost_120m_fck",
        .ops            = &clkops_omap2_dflt_wait,
-       .parent         = &omap_120m_fck,
+       .parent         = &dpll5_m2_ck,
        .init           = &omap2_init_clk_clkdm,
        .enable_reg     = OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_FCLKEN),
        .enable_bit     = OMAP3430ES2_EN_USBHOST2_SHIFT,
 
 static const struct clksel usim_clksel[] = {
        { .parent = &omap_96m_fck,      .rates = usim_96m_rates },
-       { .parent = &omap_120m_fck,     .rates = usim_120m_rates },
+       { .parent = &dpll5_m2_ck,       .rates = usim_120m_rates },
        { .parent = &sys_ck,            .rates = div2_rates },
        { .parent = NULL },
 };