forked from luck/tmp_suning_uos_patched
clk: xgene: Add SoC and PMD PLL clocks with v2 hardware
Add X-Gene SoC and PMD PLL clocks support for v2 hardware. X-Gene SoC v2 and above use an slightly different SoC and PMD PLL hardware logic. Signed-off-by: Loc Ho <lho@apm.com> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
This commit is contained in:
parent
7b63c567b5
commit
47727beb26
|
@ -29,7 +29,9 @@
|
|||
#include <linux/of_address.h>
|
||||
|
||||
/* Register SCU_PCPPLL bit fields */
|
||||
#define N_DIV_RD(src) (((src) & 0x000001ff))
|
||||
#define N_DIV_RD(src) ((src) & 0x000001ff)
|
||||
#define SC_N_DIV_RD(src) ((src) & 0x0000007f)
|
||||
#define SC_OUTDIV2(src) (((src) & 0x00000100) >> 8)
|
||||
|
||||
/* Register SCU_SOCPLL bit fields */
|
||||
#define CLKR_RD(src) (((src) & 0x07000000)>>24)
|
||||
|
@ -63,6 +65,7 @@ struct xgene_clk_pll {
|
|||
spinlock_t *lock;
|
||||
u32 pll_offset;
|
||||
enum xgene_pll_type type;
|
||||
int version;
|
||||
};
|
||||
|
||||
#define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw)
|
||||
|
@ -92,27 +95,37 @@ static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
|
|||
|
||||
pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
|
||||
|
||||
if (pllclk->type == PLL_TYPE_PCP) {
|
||||
/*
|
||||
* PLL VCO = Reference clock * NF
|
||||
* PCP PLL = PLL_VCO / 2
|
||||
*/
|
||||
nout = 2;
|
||||
fvco = parent_rate * (N_DIV_RD(pll) + 4);
|
||||
if (pllclk->version <= 1) {
|
||||
if (pllclk->type == PLL_TYPE_PCP) {
|
||||
/*
|
||||
* PLL VCO = Reference clock * NF
|
||||
* PCP PLL = PLL_VCO / 2
|
||||
*/
|
||||
nout = 2;
|
||||
fvco = parent_rate * (N_DIV_RD(pll) + 4);
|
||||
} else {
|
||||
/*
|
||||
* Fref = Reference Clock / NREF;
|
||||
* Fvco = Fref * NFB;
|
||||
* Fout = Fvco / NOUT;
|
||||
*/
|
||||
nref = CLKR_RD(pll) + 1;
|
||||
nout = CLKOD_RD(pll) + 1;
|
||||
nfb = CLKF_RD(pll);
|
||||
fref = parent_rate / nref;
|
||||
fvco = fref * nfb;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Fref = Reference Clock / NREF;
|
||||
* Fvco = Fref * NFB;
|
||||
* Fout = Fvco / NOUT;
|
||||
* fvco = Reference clock * FBDIVC
|
||||
* PLL freq = fvco / NOUT
|
||||
*/
|
||||
nref = CLKR_RD(pll) + 1;
|
||||
nout = CLKOD_RD(pll) + 1;
|
||||
nfb = CLKF_RD(pll);
|
||||
fref = parent_rate / nref;
|
||||
fvco = fref * nfb;
|
||||
nout = SC_OUTDIV2(pll) ? 2 : 3;
|
||||
fvco = parent_rate * SC_N_DIV_RD(pll);
|
||||
}
|
||||
pr_debug("%s pll recalc rate %ld parent %ld\n", clk_hw_get_name(hw),
|
||||
fvco / nout, parent_rate);
|
||||
pr_debug("%s pll recalc rate %ld parent %ld version %d\n",
|
||||
clk_hw_get_name(hw), fvco / nout, parent_rate,
|
||||
pllclk->version);
|
||||
|
||||
return fvco / nout;
|
||||
}
|
||||
|
@ -125,7 +138,7 @@ static const struct clk_ops xgene_clk_pll_ops = {
|
|||
static struct clk *xgene_register_clk_pll(struct device *dev,
|
||||
const char *name, const char *parent_name,
|
||||
unsigned long flags, void __iomem *reg, u32 pll_offset,
|
||||
u32 type, spinlock_t *lock)
|
||||
u32 type, spinlock_t *lock, int version)
|
||||
{
|
||||
struct xgene_clk_pll *apmclk;
|
||||
struct clk *clk;
|
||||
|
@ -144,6 +157,7 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
|
|||
init.parent_names = parent_name ? &parent_name : NULL;
|
||||
init.num_parents = parent_name ? 1 : 0;
|
||||
|
||||
apmclk->version = version;
|
||||
apmclk->reg = reg;
|
||||
apmclk->lock = lock;
|
||||
apmclk->pll_offset = pll_offset;
|
||||
|
@ -160,26 +174,37 @@ static struct clk *xgene_register_clk_pll(struct device *dev,
|
|||
return clk;
|
||||
}
|
||||
|
||||
static int xgene_pllclk_version(struct device_node *np)
|
||||
{
|
||||
if (of_device_is_compatible(np, "apm,xgene-socpll-clock"))
|
||||
return 1;
|
||||
if (of_device_is_compatible(np, "apm,xgene-pcppll-clock"))
|
||||
return 1;
|
||||
return 2;
|
||||
}
|
||||
|
||||
static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type)
|
||||
{
|
||||
const char *clk_name = np->full_name;
|
||||
struct clk *clk;
|
||||
void __iomem *reg;
|
||||
const char *clk_name = np->full_name;
|
||||
struct clk *clk;
|
||||
void __iomem *reg;
|
||||
int version = xgene_pllclk_version(np);
|
||||
|
||||
reg = of_iomap(np, 0);
|
||||
if (reg == NULL) {
|
||||
pr_err("Unable to map CSR register for %s\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
clk = xgene_register_clk_pll(NULL,
|
||||
clk_name, of_clk_get_parent_name(np, 0),
|
||||
CLK_IS_ROOT, reg, 0, pll_type, &clk_lock);
|
||||
if (!IS_ERR(clk)) {
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
clk_register_clkdev(clk, clk_name, NULL);
|
||||
pr_debug("Add %s clock PLL\n", clk_name);
|
||||
}
|
||||
reg = of_iomap(np, 0);
|
||||
if (reg == NULL) {
|
||||
pr_err("Unable to map CSR register for %s\n", np->full_name);
|
||||
return;
|
||||
}
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
clk = xgene_register_clk_pll(NULL,
|
||||
clk_name, of_clk_get_parent_name(np, 0),
|
||||
CLK_IS_ROOT, reg, 0, pll_type, &clk_lock,
|
||||
version);
|
||||
if (!IS_ERR(clk)) {
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
clk_register_clkdev(clk, clk_name, NULL);
|
||||
pr_debug("Add %s clock PLL\n", clk_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void xgene_socpllclk_init(struct device_node *np)
|
||||
|
@ -460,7 +485,7 @@ static void __init xgene_devclk_init(struct device_node *np)
|
|||
rc = of_address_to_resource(np, i, &res);
|
||||
if (rc != 0) {
|
||||
if (i == 0) {
|
||||
pr_err("no DTS register for %s\n",
|
||||
pr_err("no DTS register for %s\n",
|
||||
np->full_name);
|
||||
return;
|
||||
}
|
||||
|
@ -518,4 +543,8 @@ static void __init xgene_devclk_init(struct device_node *np)
|
|||
|
||||
CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
|
||||
CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
|
||||
CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock",
|
||||
xgene_socpllclk_init);
|
||||
CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock",
|
||||
xgene_pcppllclk_init);
|
||||
CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);
|
||||
|
|
Loading…
Reference in New Issue
Block a user