clk: shmobile: Add R-Car Gen2 RCAN clock support
Add the RCAN clock support to the R-Car generation 2 CPG driver. This clock gets derived from the USB_EXTAL clock, dividing it by 6. The layout of the RCANCKCR register is similar to those of the clocks supported by the 'clk-div6' driver but has no divider field, and so can't be supported by that driver... Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com> Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
parent
a2868160f4
commit
90cf0e2b96
|
@ -14,10 +14,11 @@ Required Properties:
|
|||
|
||||
- reg: Base address and length of the memory resource used by the CPG
|
||||
|
||||
- clocks: Reference to the parent clock
|
||||
- clocks: References to the parent clocks: first to the EXTAL clock, second
|
||||
to the USB_EXTAL clock
|
||||
- #clock-cells: Must be 1
|
||||
- clock-output-names: The names of the clocks. Supported clocks are "main",
|
||||
"pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1" and "z"
|
||||
"pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1", "z", and "rcan"
|
||||
|
||||
|
||||
Example
|
||||
|
@ -27,8 +28,9 @@ Example
|
|||
compatible = "renesas,r8a7790-cpg-clocks",
|
||||
"renesas,rcar-gen2-cpg-clocks";
|
||||
reg = <0 0xe6150000 0 0x1000>;
|
||||
clocks = <&extal_clk>;
|
||||
clocks = <&extal_clk &usb_extal_clk>;
|
||||
#clock-cells = <1>;
|
||||
clock-output-names = "main", "pll0, "pll1", "pll3",
|
||||
"lb", "qspi", "sdh", "sd0", "sd1", "z";
|
||||
"lb", "qspi", "sdh", "sd0", "sd1", "z",
|
||||
"rcan";
|
||||
};
|
||||
|
|
|
@ -33,6 +33,7 @@ struct rcar_gen2_cpg {
|
|||
#define CPG_FRQCRC 0x000000e0
|
||||
#define CPG_FRQCRC_ZFC_MASK (0x1f << 8)
|
||||
#define CPG_FRQCRC_ZFC_SHIFT 8
|
||||
#define CPG_RCANCKCR 0x00000270
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Z Clock
|
||||
|
@ -161,6 +162,43 @@ static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg)
|
|||
return clk;
|
||||
}
|
||||
|
||||
static struct clk * __init cpg_rcan_clk_register(struct rcar_gen2_cpg *cpg,
|
||||
struct device_node *np)
|
||||
{
|
||||
const char *parent_name = of_clk_get_parent_name(np, 1);
|
||||
struct clk_fixed_factor *fixed;
|
||||
struct clk_gate *gate;
|
||||
struct clk *clk;
|
||||
|
||||
fixed = kzalloc(sizeof(*fixed), GFP_KERNEL);
|
||||
if (!fixed)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
fixed->mult = 1;
|
||||
fixed->div = 6;
|
||||
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate) {
|
||||
kfree(fixed);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
gate->reg = cpg->reg + CPG_RCANCKCR;
|
||||
gate->bit_idx = 8;
|
||||
gate->flags = CLK_GATE_SET_TO_DISABLE;
|
||||
gate->lock = &cpg->lock;
|
||||
|
||||
clk = clk_register_composite(NULL, "rcan", &parent_name, 1, NULL, NULL,
|
||||
&fixed->hw, &clk_fixed_factor_ops,
|
||||
&gate->hw, &clk_gate_ops, 0);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(gate);
|
||||
kfree(fixed);
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* CPG Clock Data
|
||||
*/
|
||||
|
@ -263,6 +301,8 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
|
|||
shift = 0;
|
||||
} else if (!strcmp(name, "z")) {
|
||||
return cpg_z_clk_register(cpg);
|
||||
} else if (!strcmp(name, "rcan")) {
|
||||
return cpg_rcan_clk_register(cpg, np);
|
||||
} else {
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue