Message ID | 1370476651-6743-2-git-send-email-tomasz.figa@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Quoting Tomasz Figa (2013-06-05 16:57:25) > This patch adds support for PLL6552 and PLL6553 PLLs present on Samsung > S3C64xx SoCs. > > Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com> Acked-by: Mike Turquette <mturquette@linaro.org> or I can take it into clk-next. > --- > drivers/clk/samsung/clk-pll.c | 160 ++++++++++++++++++++++++++++++++++++++++++ > drivers/clk/samsung/clk-pll.h | 4 ++ > 2 files changed, 164 insertions(+) > > diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c > index 89135f6..cef0bb9 100644 > --- a/drivers/clk/samsung/clk-pll.c > +++ b/drivers/clk/samsung/clk-pll.c > @@ -336,6 +336,166 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, > } > > /* > + * PLL6552 Clock Type > + */ > + > +#define PLL6552_LOCK_REG 0x00 > +#define PLL6552_CON_REG 0x0c > + > +#define PLL6552_MDIV_MASK 0x3ff > +#define PLL6552_PDIV_MASK 0x3f > +#define PLL6552_SDIV_MASK 0x7 > +#define PLL6552_MDIV_SHIFT 16 > +#define PLL6552_PDIV_SHIFT 8 > +#define PLL6552_SDIV_SHIFT 0 > + > +struct samsung_clk_pll6552 { > + struct clk_hw hw; > + void __iomem *reg_base; > +}; > + > +#define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) > + > +static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, > + unsigned long parent_rate) > +{ > + struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); > + u32 mdiv, pdiv, sdiv, pll_con; > + u64 fvco = parent_rate; > + > + pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); > + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; > + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; > + sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; > + > + fvco *= mdiv; > + do_div(fvco, (pdiv << sdiv)); > + > + return (unsigned long)fvco; > +} > + > +static const struct clk_ops samsung_pll6552_clk_ops = { > + .recalc_rate = samsung_pll6552_recalc_rate, > +}; > + > +struct clk * __init samsung_clk_register_pll6552(const char *name, > + const char *pname, void __iomem *base) > +{ > + struct samsung_clk_pll6552 *pll; > + struct clk *clk; > + struct clk_init_data init; > + > + pll = kzalloc(sizeof(*pll), GFP_KERNEL); > + if (!pll) { > + pr_err("%s: could not allocate pll clk %s\n", __func__, name); > + return NULL; > + } > + > + init.name = name; > + init.ops = &samsung_pll6552_clk_ops; > + init.parent_names = &pname; > + init.num_parents = 1; > + > + pll->hw.init = &init; > + pll->reg_base = base; > + > + clk = clk_register(NULL, &pll->hw); > + if (IS_ERR(clk)) { > + pr_err("%s: failed to register pll clock %s\n", __func__, > + name); > + kfree(pll); > + } > + > + if (clk_register_clkdev(clk, name, NULL)) > + pr_err("%s: failed to register lookup for %s", __func__, name); > + > + return clk; > +} > + > +/* > + * PLL6553 Clock Type > + */ > + > +#define PLL6553_LOCK_REG 0x00 > +#define PLL6553_CON0_REG 0x0c > +#define PLL6553_CON1_REG 0x10 > + > +#define PLL6553_MDIV_MASK 0xff > +#define PLL6553_PDIV_MASK 0x3f > +#define PLL6553_SDIV_MASK 0x7 > +#define PLL6553_KDIV_MASK 0xffff > +#define PLL6553_MDIV_SHIFT 16 > +#define PLL6553_PDIV_SHIFT 8 > +#define PLL6553_SDIV_SHIFT 0 > +#define PLL6553_KDIV_SHIFT 0 > + > +struct samsung_clk_pll6553 { > + struct clk_hw hw; > + void __iomem *reg_base; > +}; > + > +#define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) > + > +static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, > + unsigned long parent_rate) > +{ > + struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); > + u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; > + u64 fvco = parent_rate; > + > + pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); > + pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); > + mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; > + pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; > + sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; > + kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK; > + > + fvco *= (mdiv << 16) + kdiv; > + do_div(fvco, (pdiv << sdiv)); > + fvco >>= 16; > + > + return (unsigned long)fvco; > +} > + > +static const struct clk_ops samsung_pll6553_clk_ops = { > + .recalc_rate = samsung_pll6553_recalc_rate, > +}; > + > +struct clk * __init samsung_clk_register_pll6553(const char *name, > + const char *pname, void __iomem *base) > +{ > + struct samsung_clk_pll6553 *pll; > + struct clk *clk; > + struct clk_init_data init; > + > + pll = kzalloc(sizeof(*pll), GFP_KERNEL); > + if (!pll) { > + pr_err("%s: could not allocate pll clk %s\n", __func__, name); > + return NULL; > + } > + > + init.name = name; > + init.ops = &samsung_pll6553_clk_ops; > + init.parent_names = &pname; > + init.num_parents = 1; > + > + pll->hw.init = &init; > + pll->reg_base = base; > + > + clk = clk_register(NULL, &pll->hw); > + if (IS_ERR(clk)) { > + pr_err("%s: failed to register pll clock %s\n", __func__, > + name); > + kfree(pll); > + } > + > + if (clk_register_clkdev(clk, name, NULL)) > + pr_err("%s: failed to register lookup for %s", __func__, name); > + > + return clk; > +} > + > +/* > * PLL2550x Clock Type > */ > > diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h > index f33786e..1d68a68 100644 > --- a/drivers/clk/samsung/clk-pll.h > +++ b/drivers/clk/samsung/clk-pll.h > @@ -34,6 +34,10 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, > extern struct clk * __init samsung_clk_register_pll46xx(const char *name, > const char *pname, const void __iomem *con_reg, > enum pll46xx_type type); > +extern struct clk *samsung_clk_register_pll6552(const char *name, > + const char *pname, void __iomem *base); > +extern struct clk *samsung_clk_register_pll6553(const char *name, > + const char *pname, void __iomem *base); > extern struct clk * __init samsung_clk_register_pll2550x(const char *name, > const char *pname, const void __iomem *reg_base, > const unsigned long offset); > -- > 1.8.2.1
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c index 89135f6..cef0bb9 100644 --- a/drivers/clk/samsung/clk-pll.c +++ b/drivers/clk/samsung/clk-pll.c @@ -336,6 +336,166 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name, } /* + * PLL6552 Clock Type + */ + +#define PLL6552_LOCK_REG 0x00 +#define PLL6552_CON_REG 0x0c + +#define PLL6552_MDIV_MASK 0x3ff +#define PLL6552_PDIV_MASK 0x3f +#define PLL6552_SDIV_MASK 0x7 +#define PLL6552_MDIV_SHIFT 16 +#define PLL6552_PDIV_SHIFT 8 +#define PLL6552_SDIV_SHIFT 0 + +struct samsung_clk_pll6552 { + struct clk_hw hw; + void __iomem *reg_base; +}; + +#define to_clk_pll6552(_hw) container_of(_hw, struct samsung_clk_pll6552, hw) + +static unsigned long samsung_pll6552_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll6552 *pll = to_clk_pll6552(hw); + u32 mdiv, pdiv, sdiv, pll_con; + u64 fvco = parent_rate; + + pll_con = __raw_readl(pll->reg_base + PLL6552_CON_REG); + mdiv = (pll_con >> PLL6552_MDIV_SHIFT) & PLL6552_MDIV_MASK; + pdiv = (pll_con >> PLL6552_PDIV_SHIFT) & PLL6552_PDIV_MASK; + sdiv = (pll_con >> PLL6552_SDIV_SHIFT) & PLL6552_SDIV_MASK; + + fvco *= mdiv; + do_div(fvco, (pdiv << sdiv)); + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll6552_clk_ops = { + .recalc_rate = samsung_pll6552_recalc_rate, +}; + +struct clk * __init samsung_clk_register_pll6552(const char *name, + const char *pname, void __iomem *base) +{ + struct samsung_clk_pll6552 *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) { + pr_err("%s: could not allocate pll clk %s\n", __func__, name); + return NULL; + } + + init.name = name; + init.ops = &samsung_pll6552_clk_ops; + init.parent_names = &pname; + init.num_parents = 1; + + pll->hw.init = &init; + pll->reg_base = base; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register pll clock %s\n", __func__, + name); + kfree(pll); + } + + if (clk_register_clkdev(clk, name, NULL)) + pr_err("%s: failed to register lookup for %s", __func__, name); + + return clk; +} + +/* + * PLL6553 Clock Type + */ + +#define PLL6553_LOCK_REG 0x00 +#define PLL6553_CON0_REG 0x0c +#define PLL6553_CON1_REG 0x10 + +#define PLL6553_MDIV_MASK 0xff +#define PLL6553_PDIV_MASK 0x3f +#define PLL6553_SDIV_MASK 0x7 +#define PLL6553_KDIV_MASK 0xffff +#define PLL6553_MDIV_SHIFT 16 +#define PLL6553_PDIV_SHIFT 8 +#define PLL6553_SDIV_SHIFT 0 +#define PLL6553_KDIV_SHIFT 0 + +struct samsung_clk_pll6553 { + struct clk_hw hw; + void __iomem *reg_base; +}; + +#define to_clk_pll6553(_hw) container_of(_hw, struct samsung_clk_pll6553, hw) + +static unsigned long samsung_pll6553_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct samsung_clk_pll6553 *pll = to_clk_pll6553(hw); + u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1; + u64 fvco = parent_rate; + + pll_con0 = __raw_readl(pll->reg_base + PLL6553_CON0_REG); + pll_con1 = __raw_readl(pll->reg_base + PLL6553_CON1_REG); + mdiv = (pll_con0 >> PLL6553_MDIV_SHIFT) & PLL6553_MDIV_MASK; + pdiv = (pll_con0 >> PLL6553_PDIV_SHIFT) & PLL6553_PDIV_MASK; + sdiv = (pll_con0 >> PLL6553_SDIV_SHIFT) & PLL6553_SDIV_MASK; + kdiv = (pll_con1 >> PLL6553_KDIV_SHIFT) & PLL6553_KDIV_MASK; + + fvco *= (mdiv << 16) + kdiv; + do_div(fvco, (pdiv << sdiv)); + fvco >>= 16; + + return (unsigned long)fvco; +} + +static const struct clk_ops samsung_pll6553_clk_ops = { + .recalc_rate = samsung_pll6553_recalc_rate, +}; + +struct clk * __init samsung_clk_register_pll6553(const char *name, + const char *pname, void __iomem *base) +{ + struct samsung_clk_pll6553 *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) { + pr_err("%s: could not allocate pll clk %s\n", __func__, name); + return NULL; + } + + init.name = name; + init.ops = &samsung_pll6553_clk_ops; + init.parent_names = &pname; + init.num_parents = 1; + + pll->hw.init = &init; + pll->reg_base = base; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: failed to register pll clock %s\n", __func__, + name); + kfree(pll); + } + + if (clk_register_clkdev(clk, name, NULL)) + pr_err("%s: failed to register lookup for %s", __func__, name); + + return clk; +} + +/* * PLL2550x Clock Type */ diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h index f33786e..1d68a68 100644 --- a/drivers/clk/samsung/clk-pll.h +++ b/drivers/clk/samsung/clk-pll.h @@ -34,6 +34,10 @@ extern struct clk * __init samsung_clk_register_pll45xx(const char *name, extern struct clk * __init samsung_clk_register_pll46xx(const char *name, const char *pname, const void __iomem *con_reg, enum pll46xx_type type); +extern struct clk *samsung_clk_register_pll6552(const char *name, + const char *pname, void __iomem *base); +extern struct clk *samsung_clk_register_pll6553(const char *name, + const char *pname, void __iomem *base); extern struct clk * __init samsung_clk_register_pll2550x(const char *name, const char *pname, const void __iomem *reg_base, const unsigned long offset);
This patch adds support for PLL6552 and PLL6553 PLLs present on Samsung S3C64xx SoCs. Signed-off-by: Tomasz Figa <tomasz.figa@gmail.com> --- drivers/clk/samsung/clk-pll.c | 160 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/samsung/clk-pll.h | 4 ++ 2 files changed, 164 insertions(+)