@@ -49,7 +49,6 @@
/* DPLL Type and DCO Selection Flags */
#define DPLL_J_TYPE 0x1
-#define DPLL_NO_DCO_SEL 0x2
int omap2_clk_enable(struct clk *clk);
void omap2_clk_disable(struct clk *clk);
@@ -602,6 +602,8 @@ static struct dpll_data dpll4_dd_3630 __initdata = {
.autoidle_mask = OMAP3430_AUTO_PERIPH_DPLL_MASK,
.idlest_reg = OMAP_CM_REGADDR(PLL_MOD, CM_IDLEST),
.idlest_mask = OMAP3430_ST_PERIPH_CLK_MASK,
+ .dco_mask = OMAP3630_PERIPH_DPLL_DCO_SEL_MASK,
+ .sddiv_mask = OMAP3630_PERIPH_DPLL_SD_DIV_MASK,
.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
.min_divider = 1,
.max_divider = OMAP3_MAX_DPLL_DIV,
@@ -947,6 +947,7 @@ static struct dpll_data dpll_unipro_dd = {
.enable_mask = OMAP4430_DPLL_EN_MASK,
.autoidle_mask = OMAP4430_AUTO_DPLL_MODE_MASK,
.idlest_mask = OMAP4430_ST_DPLL_CLK_MASK,
+ .sddiv_mask = OMAP4430_DPLL_SD_DIV_MASK,
.max_multiplier = OMAP4430_MAX_DPLL_MULT,
.max_divider = OMAP4430_MAX_DPLL_DIV,
.min_divider = 1,
@@ -999,7 +1000,7 @@ static struct clk usb_hs_clk_div_ck = {
static struct dpll_data dpll_usb_dd = {
.mult_div1_reg = OMAP4430_CM_CLKSEL_DPLL_USB,
.clk_bypass = &usb_hs_clk_div_ck,
- .flags = DPLL_J_TYPE | DPLL_NO_DCO_SEL,
+ .flags = DPLL_J_TYPE,
.clk_ref = &sys_clkin_ck,
.control_reg = OMAP4430_CM_CLKMODE_DPLL_USB,
.modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
@@ -223,10 +223,9 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
}
/**
- * lookup_dco_sddiv - Set j-type DPLL4 compensation variables
+ * _lookup_dco - Lookup DCO used by j-type DPLL
* @clk: pointer to a DPLL struct clk
* @dco: digital control oscillator selector
- * @sd_div: target sigma-delta divider
* @m: DPLL multiplier to set
* @n: DPLL divider to set
*
@@ -235,11 +234,9 @@ static int _omap3_noncore_dpll_stop(struct clk *clk)
* XXX This code is not needed for 3430/AM35xx; can it be optimized
* out in non-multi-OMAP builds for those chips?
*/
-static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
- u8 n)
+static void _lookup_dco(struct clk *clk, u8 *dco, u16 m, u8 n)
{
- unsigned long fint, clkinp, sd; /* watch out for overflow */
- int mod1, mod2;
+ unsigned long fint, clkinp; /* watch out for overflow */
clkinp = clk->parent->rate;
fint = (clkinp / n) * m;
@@ -248,6 +245,27 @@ static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
*dco = 2;
else
*dco = 4;
+}
+
+/**
+ * _lookup_sddiv - Calculate sigma delta divider for j-type DPLL
+ * @clk: pointer to a DPLL struct clk
+ * @sd_div: target sigma-delta divider
+ * @m: DPLL multiplier to set
+ * @n: DPLL divider to set
+ *
+ * See 36xx TRM section 3.5.3.3.3.2 "Type B DPLL (Low-Jitter)"
+ *
+ * XXX This code is not needed for 3430/AM35xx; can it be optimized
+ * out in non-multi-OMAP builds for those chips?
+ */
+static void _lookup_sddiv(struct clk *clk, u8 *sd_div, u16 m, u8 n)
+{
+ unsigned long clkinp, sd; /* watch out for overflow */
+ int mod1, mod2;
+
+ clkinp = clk->parent->rate;
+
/*
* target sigma-delta to near 250MHz
* sd = ceil[(m/(n+1)) * (clkinp_MHz / 250)]
@@ -276,6 +294,7 @@ static void lookup_dco_sddiv(struct clk *clk, u8 *dco, u8 *sd_div, u16 m,
static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
{
struct dpll_data *dd = clk->dpll_data;
+ u8 dco, sd_div;
u32 v;
/* 3430 ES2 TRM: 4.7.6.9 DPLL Programming Sequence */
@@ -298,18 +317,16 @@ static int omap3_noncore_dpll_program(struct clk *clk, u16 m, u8 n, u16 freqsel)
v |= m << __ffs(dd->mult_mask);
v |= (n - 1) << __ffs(dd->div1_mask);
- /*
- * XXX This code is not needed for 3430/AM35XX; can it be optimized
- * out in non-multi-OMAP builds for those chips?
- */
- if ((dd->flags & DPLL_J_TYPE) && !(dd->flags & DPLL_NO_DCO_SEL)) {
- u8 dco, sd_div;
- lookup_dco_sddiv(clk, &dco, &sd_div, m, n);
- /* XXX This probably will need revision for OMAP4 */
- v &= ~(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK
- | OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
- v |= dco << __ffs(OMAP3630_PERIPH_DPLL_DCO_SEL_MASK);
- v |= sd_div << __ffs(OMAP3630_PERIPH_DPLL_SD_DIV_MASK);
+ /* Configure dco and sd_div for dplls that have these fields */
+ if (dd->dco_mask) {
+ _lookup_dco(clk, &dco, m, n);
+ v &= ~(dd->dco_mask);
+ v |= dco << __ffs(dd->dco_mask);
+ }
+ if (dd->sddiv_mask) {
+ _lookup_sddiv(clk, &sd_div, m, n);
+ v &= ~(dd->sddiv_mask);
+ v |= sd_div << __ffs(dd->sddiv_mask);
}
__raw_writel(v, dd->mult_div1_reg);
@@ -124,8 +124,7 @@ struct clksel {
*
* Possible values for @flags:
* DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs)
- * NO_DCO_SEL: don't program DCO (only for some J-type DPLLs)
-
+ *
* @freqsel_mask is only used on the OMAP34xx family and AM35xx.
*
* XXX Some DPLLs have multiple bypass inputs, so it's not technically
@@ -161,6 +160,8 @@ struct dpll_data {
u32 autoidle_mask;
u32 freqsel_mask;
u32 idlest_mask;
+ u32 dco_mask;
+ u32 sddiv_mask;
u8 auto_recal_bit;
u8 recal_en_bit;
u8 recal_st_bit;