diff mbox

[1/7] clk: samsung: pll: Add support for PLL6552 and PLL6553

Message ID 1370476651-6743-2-git-send-email-tomasz.figa@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tomasz Figa June 5, 2013, 11:57 p.m. UTC
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(+)

Comments

Mike Turquette June 12, 2013, 2:53 a.m. UTC | #1
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 mbox

Patch

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);