clk: shmobile: Add R-Car Gen2 ADSP clock support

Add the ADSP clock support to the R-Car generation 2 CPG driver.  This clock
gets derived from  PLL1.  The layout of the ADSPCKCR register is  similar to
those of the clocks supported by the 'clk-div6' driver but the divider encoding
is non-linear, so can't be supported by that driver...

Based on the original patch by Konstantin Kozhevnikov
<konstantin.kozhevnikov@cogentembedded.com>.

Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
This commit is contained in:
Sergei Shtylyov 2015-01-07 01:39:52 +03:00 коммит произвёл Geert Uytterhoeven
Родитель 90cf0e2b96
Коммит 1484276119
2 изменённых файлов: 51 добавлений и 2 удалений

Просмотреть файл

@ -18,7 +18,8 @@ Required Properties:
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", "z", and "rcan"
"pll0", "pll1", "pll3", "lb", "qspi", "sdh", "sd0", "sd1", "z", "rcan", and
"adsp"
Example
@ -32,5 +33,5 @@ Example
#clock-cells = <1>;
clock-output-names = "main", "pll0, "pll1", "pll3",
"lb", "qspi", "sdh", "sd0", "sd1", "z",
"rcan";
"rcan", "adsp";
};

Просмотреть файл

@ -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_ADSPCKCR 0x0000025c
#define CPG_RCANCKCR 0x00000270
/* -----------------------------------------------------------------------------
@ -199,6 +200,51 @@ static struct clk * __init cpg_rcan_clk_register(struct rcar_gen2_cpg *cpg,
return clk;
}
/* ADSP divisors */
static const struct clk_div_table cpg_adsp_div_table[] = {
{ 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 },
{ 5, 12 }, { 6, 16 }, { 7, 18 }, { 8, 24 },
{ 10, 36 }, { 11, 48 }, { 0, 0 },
};
static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg)
{
const char *parent_name = "pll1";
struct clk_divider *div;
struct clk_gate *gate;
struct clk *clk;
div = kzalloc(sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);
div->reg = cpg->reg + CPG_ADSPCKCR;
div->width = 4;
div->table = cpg_adsp_div_table;
div->lock = &cpg->lock;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate) {
kfree(div);
return ERR_PTR(-ENOMEM);
}
gate->reg = cpg->reg + CPG_ADSPCKCR;
gate->bit_idx = 8;
gate->flags = CLK_GATE_SET_TO_DISABLE;
gate->lock = &cpg->lock;
clk = clk_register_composite(NULL, "adsp", &parent_name, 1, NULL, NULL,
&div->hw, &clk_divider_ops,
&gate->hw, &clk_gate_ops, 0);
if (IS_ERR(clk)) {
kfree(gate);
kfree(div);
}
return clk;
}
/* -----------------------------------------------------------------------------
* CPG Clock Data
*/
@ -303,6 +349,8 @@ rcar_gen2_cpg_register_clock(struct device_node *np, struct rcar_gen2_cpg *cpg,
return cpg_z_clk_register(cpg);
} else if (!strcmp(name, "rcan")) {
return cpg_rcan_clk_register(cpg, np);
} else if (!strcmp(name, "adsp")) {
return cpg_adsp_clk_register(cpg);
} else {
return ERR_PTR(-EINVAL);
}