Commit a1900f2efe2d75e0fe5b871421a2f2de2fa68b4e

Authored by Mike Turquette
Committed by Paul Walmsley
1 parent be73246058

ARM: OMAP4: clock: round_rate and recalc functions for DPLL_ABE

OMAP4 DPLL_ABE can enable a 4X multipler on top of the normal MN multipler
and divider. This is achieved by setting CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN
bit in CKGEN module of CM1. From the OMAP4 TRM:

Fdpll = Fref x 2 x (4 x M/(N+1)) in case REGM4XEN bit field is set (only
applicable to DPLL_ABE).

Add new round_rate() and recalc() functions for OMAP4, that check the
setting of REGM4XEN bit and handle this appropriately. The new functions
are a simple wrapper on top of the existing omap2_dpll_round_rate() and
omap2_dpll_get_rate() functions to handle the REGM4XEN bit.

The REGM4XEN bit is only implemented for the ABE DPLL on OMAP4 and so
only dpll_abe_ck uses omap4_dpll_regm4xen_round_rate() and
omap4_dpll_regm4xen_recalc() functions.

Signed-off-by: Mike Turquette <mturquette@ti.com>
Tested-by: Jon Hunter <jon-hunter@ti.com>
Signed-off-by: Jon Hunter <jon-hunter@ti.com>
[paul@pwsan.com: fixed attempt to return a negative from a fn returning
		 unsigned; pass along errors from omap2_dpll_round_rate();
		 added documentation; added Jon's S-o-b]
Signed-off-by: Paul Walmsley <paul@pwsan.com>

Showing 4 changed files with 80 additions and 2 deletions Side-by-side Diff

arch/arm/mach-omap2/clock.h
... ... @@ -66,6 +66,8 @@
66 66 int omap4_dpllmx_gatectrl_read(struct clk *clk);
67 67 void omap4_dpllmx_allow_gatectrl(struct clk *clk);
68 68 void omap4_dpllmx_deny_gatectrl(struct clk *clk);
  69 +long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate);
  70 +unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk);
69 71  
70 72 #ifdef CONFIG_OMAP_RESET_CLOCKS
71 73 void omap2_clk_disable_unused(struct clk *clk);
arch/arm/mach-omap2/clock44xx.h
... ... @@ -8,6 +8,13 @@
8 8 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
9 9 #define __ARCH_ARM_MACH_OMAP2_CLOCK44XX_H
10 10  
  11 +/*
  12 + * OMAP4430_REGM4XEN_MULT: If the CM_CLKMODE_DPLL_ABE.DPLL_REGM4XEN bit is
  13 + * set, then the DPLL's lock frequency is multiplied by 4 (OMAP4430 TRM
  14 + * vV Section 3.6.3.3.1 "DPLLs Output Clocks Parameters")
  15 + */
  16 +#define OMAP4430_REGM4XEN_MULT 4
  17 +
11 18 int omap4xxx_clk_init(void);
12 19  
13 20 #endif
arch/arm/mach-omap2/clock44xx_data.c
... ... @@ -270,8 +270,8 @@
270 270 .dpll_data = &dpll_abe_dd,
271 271 .init = &omap2_init_dpll_parent,
272 272 .ops = &clkops_omap3_noncore_dpll_ops,
273   - .recalc = &omap3_dpll_recalc,
274   - .round_rate = &omap2_dpll_round_rate,
  273 + .recalc = &omap4_dpll_regm4xen_recalc,
  274 + .round_rate = &omap4_dpll_regm4xen_round_rate,
275 275 .set_rate = &omap3_noncore_dpll_set_rate,
276 276 };
277 277  
arch/arm/mach-omap2/dpll44xx.c
... ... @@ -19,6 +19,7 @@
19 19 #include <plat/clock.h>
20 20  
21 21 #include "clock.h"
  22 +#include "clock44xx.h"
22 23 #include "cm-regbits-44xx.h"
23 24  
24 25 /* Supported only on OMAP4 */
... ... @@ -81,4 +82,73 @@
81 82 .allow_idle = omap4_dpllmx_allow_gatectrl,
82 83 .deny_idle = omap4_dpllmx_deny_gatectrl,
83 84 };
  85 +
  86 +/**
  87 + * omap4_dpll_regm4xen_recalc - compute DPLL rate, considering REGM4XEN bit
  88 + * @clk: struct clk * of the DPLL to compute the rate for
  89 + *
  90 + * Compute the output rate for the OMAP4 DPLL represented by @clk.
  91 + * Takes the REGM4XEN bit into consideration, which is needed for the
  92 + * OMAP4 ABE DPLL. Returns the DPLL's output rate (before M-dividers)
  93 + * upon success, or 0 upon error.
  94 + */
  95 +unsigned long omap4_dpll_regm4xen_recalc(struct clk *clk)
  96 +{
  97 + u32 v;
  98 + unsigned long rate;
  99 + struct dpll_data *dd;
  100 +
  101 + if (!clk || !clk->dpll_data)
  102 + return 0;
  103 +
  104 + dd = clk->dpll_data;
  105 +
  106 + rate = omap2_get_dpll_rate(clk);
  107 +
  108 + /* regm4xen adds a multiplier of 4 to DPLL calculations */
  109 + v = __raw_readl(dd->control_reg);
  110 + if (v & OMAP4430_DPLL_REGM4XEN_MASK)
  111 + rate *= OMAP4430_REGM4XEN_MULT;
  112 +
  113 + return rate;
  114 +}
  115 +
  116 +/**
  117 + * omap4_dpll_regm4xen_round_rate - round DPLL rate, considering REGM4XEN bit
  118 + * @clk: struct clk * of the DPLL to round a rate for
  119 + * @target_rate: the desired rate of the DPLL
  120 + *
  121 + * Compute the rate that would be programmed into the DPLL hardware
  122 + * for @clk if set_rate() were to be provided with the rate
  123 + * @target_rate. Takes the REGM4XEN bit into consideration, which is
  124 + * needed for the OMAP4 ABE DPLL. Returns the rounded rate (before
  125 + * M-dividers) upon success, -EINVAL if @clk is null or not a DPLL, or
  126 + * ~0 if an error occurred in omap2_dpll_round_rate().
  127 + */
  128 +long omap4_dpll_regm4xen_round_rate(struct clk *clk, unsigned long target_rate)
  129 +{
  130 + u32 v;
  131 + struct dpll_data *dd;
  132 + long r;
  133 +
  134 + if (!clk || !clk->dpll_data)
  135 + return -EINVAL;
  136 +
  137 + dd = clk->dpll_data;
  138 +
  139 + /* regm4xen adds a multiplier of 4 to DPLL calculations */
  140 + v = __raw_readl(dd->control_reg) & OMAP4430_DPLL_REGM4XEN_MASK;
  141 +
  142 + if (v)
  143 + target_rate = target_rate / OMAP4430_REGM4XEN_MULT;
  144 +
  145 + r = omap2_dpll_round_rate(clk, target_rate);
  146 + if (r == ~0)
  147 + return r;
  148 +
  149 + if (v)
  150 + clk->dpll_data->last_rounded_rate *= OMAP4430_REGM4XEN_MULT;
  151 +
  152 + return clk->dpll_data->last_rounded_rate;
  153 +}