All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Heiko Stübner" <heiko@sntech.de>
To: Kukjin Kim <kgene.kim@samsung.com>
Cc: mturquette@linaro.org, linux-arm-kernel@lists.infradead.org,
	linux-samsung-soc@vger.kernel.org,
	Thomas Abraham <thomas.abraham@linaro.org>,
	Sylwester Nawrocki <sylvester.nawrocki@gmail.com>,
	t.figa@samsung.com
Subject: [PATCH 1/7] clk: samsung: add plls used in s3c2416 and s3c2443
Date: Tue, 12 Mar 2013 01:42:19 +0100	[thread overview]
Message-ID: <201303120142.19842.heiko@sntech.de> (raw)
In-Reply-To: <201303120141.31262.heiko@sntech.de>

This adds support for pll2126x, pll3000x, pll6552x and pll6553x.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/samsung/clk-pll.c |  376 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk-pll.h |    8 +
 2 files changed, 384 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 4b24511..b772f9e 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -400,6 +400,97 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name,
 }
 
 /*
+ * PLL2126x Clock Type
+ */
+
+#define PLL2126X_MDIV_MASK	(0xFF)
+#define PLL2126X_PDIV_MASK	(0x3)
+#define PLL2126X_SDIV_MASK	(0x3)
+#define PLL2126X_MDIV_SHIFT	(16)
+#define PLL2126X_PDIV_SHIFT	(8)
+#define PLL2126X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll2126x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll2126x(_hw) container_of(_hw, struct samsung_clk_pll2126x, hw)
+
+static unsigned long samsung_pll2126x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll2126x *pll = to_clk_pll2126x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL2126X_MDIV_SHIFT) & PLL2126X_MDIV_MASK;
+	pdiv = (pll_con >> PLL2126X_PDIV_SHIFT) & PLL2126X_PDIV_MASK;
+	sdiv = (pll_con >> PLL2126X_SDIV_SHIFT) & PLL2126X_SDIV_MASK;
+
+	fvco *= (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll2126x clock round rate operation */
+static long samsung_pll2126x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll2126x clock set rate */
+static int samsung_pll2126x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll2126x_clk_ops = {
+	.recalc_rate = samsung_pll2126x_recalc_rate,
+	.round_rate = samsung_pll2126x_round_rate,
+	.set_rate = samsung_pll2126x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll2126x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll2126x *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_pll2126x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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
  */
 
@@ -497,3 +588,288 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
 
 	return clk;
 }
+
+/*
+ * PLL3000x Clock Type
+ */
+
+#define PLL3000X_MDIV_MASK	(0xFF)
+#define PLL3000X_PDIV_MASK	(0x3)
+#define PLL3000X_SDIV_MASK	(0x3)
+#define PLL3000X_MDIV_SHIFT	(16)
+#define PLL3000X_PDIV_SHIFT	(8)
+#define PLL3000X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll3000x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll3000x(_hw) container_of(_hw, struct samsung_clk_pll3000x, hw)
+
+static unsigned long samsung_pll3000x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll3000x *pll = to_clk_pll3000x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL3000X_MDIV_SHIFT) & PLL3000X_MDIV_MASK;
+	pdiv = (pll_con >> PLL3000X_PDIV_SHIFT) & PLL3000X_PDIV_MASK;
+	sdiv = (pll_con >> PLL3000X_SDIV_SHIFT) & PLL3000X_SDIV_MASK;
+
+	fvco *= (2 * (mdiv + 8));
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll3000x clock round rate operation */
+static long samsung_pll3000x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll3000x clock set rate */
+static int samsung_pll3000x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll3000x_clk_ops = {
+	.recalc_rate = samsung_pll3000x_recalc_rate,
+	.round_rate = samsung_pll3000x_round_rate,
+	.set_rate = samsung_pll3000x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll3000x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll3000x *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_pll3000x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
+
+/*
+ * PLL6552x Clock Type
+ */
+
+#define PLL6552X_MDIV_MASK	(0x3FF)
+#define PLL6552X_PDIV_MASK	(0x3F)
+#define PLL6552X_SDIV_MASK	(0x7)
+#define PLL6552X_MDIV_SHIFT	(14)
+#define PLL6552X_PDIV_SHIFT	(5)
+#define PLL6552X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll6552x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll6552x(_hw) container_of(_hw, struct samsung_clk_pll6552x, hw)
+
+static unsigned long samsung_pll6552x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll6552x *pll = to_clk_pll6552x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL6552X_MDIV_SHIFT) & PLL6552X_MDIV_MASK;
+	pdiv = (pll_con >> PLL6552X_PDIV_SHIFT) & PLL6552X_PDIV_MASK;
+	sdiv = (pll_con >> PLL6552X_SDIV_SHIFT) & PLL6552X_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll6552x clock round rate operation */
+static long samsung_pll6552x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll6552x clock set rate */
+static int samsung_pll6552x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll6552x_clk_ops = {
+	.recalc_rate = samsung_pll6552x_recalc_rate,
+	.round_rate = samsung_pll6552x_round_rate,
+	.set_rate = samsung_pll6552x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll6552x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll6552x *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_pll6552x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
+
+/*
+ * PLL6553x Clock Type
+ */
+
+#define PLL6553X_MDIV_MASK	(0x7F)
+#define PLL6553X_PDIV_MASK	(0x1F)
+#define PLL6553X_SDIV_MASK	(0x3)
+#define PLL6553X_KDIV_MASK	(0xFFFF)
+#define PLL6553X_MDIV_SHIFT	(16)
+#define PLL6553X_PDIV_SHIFT	(8)
+#define PLL6553X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll6553x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll6553x(_hw) container_of(_hw, struct samsung_clk_pll6553x, hw)
+
+static unsigned long samsung_pll6553x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll6553x *pll = to_clk_pll6553x(hw);
+	u32 pll_con0, pll_con1, mdiv, pdiv, sdiv, kdiv;
+	u64 fvco = parent_rate;
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
+	mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+	kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+	/*
+	 * We need to multiple parent_rate by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	fvco *= (mdiv << 16) + kdiv;
+	do_div(fvco, (pdiv << sdiv));
+	fvco >>= 16;
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll6553x clock round rate operation */
+static long samsung_pll6553x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll6553x clock set rate */
+static int samsung_pll6553x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll6553x_clk_ops = {
+	.recalc_rate = samsung_pll6553x_recalc_rate,
+	.round_rate = samsung_pll6553x_round_rate,
+	.set_rate = samsung_pll6553x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll6553x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll6553x *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_pll6553x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index f33786e..465ee6f 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -34,8 +34,16 @@ 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 * __init samsung_clk_register_pll2126x(const char *name,
+			const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
 			const char *pname, const void __iomem *reg_base,
 			const unsigned long offset);
+extern struct clk * __init samsung_clk_register_pll3000x(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll6552x(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll6553x(const char *name,
+			const char *pname, const void __iomem *con_reg);
 
 #endif /* __SAMSUNG_CLK_PLL_H */
-- 
1.7.2.3

WARNING: multiple messages have this Message-ID (diff)
From: heiko@sntech.de (Heiko Stübner)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/7] clk: samsung: add plls used in s3c2416 and s3c2443
Date: Tue, 12 Mar 2013 01:42:19 +0100	[thread overview]
Message-ID: <201303120142.19842.heiko@sntech.de> (raw)
In-Reply-To: <201303120141.31262.heiko@sntech.de>

This adds support for pll2126x, pll3000x, pll6552x and pll6553x.

Signed-off-by: Heiko Stuebner <heiko@sntech.de>
---
 drivers/clk/samsung/clk-pll.c |  376 +++++++++++++++++++++++++++++++++++++++++
 drivers/clk/samsung/clk-pll.h |    8 +
 2 files changed, 384 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
index 4b24511..b772f9e 100644
--- a/drivers/clk/samsung/clk-pll.c
+++ b/drivers/clk/samsung/clk-pll.c
@@ -400,6 +400,97 @@ struct clk * __init samsung_clk_register_pll46xx(const char *name,
 }
 
 /*
+ * PLL2126x Clock Type
+ */
+
+#define PLL2126X_MDIV_MASK	(0xFF)
+#define PLL2126X_PDIV_MASK	(0x3)
+#define PLL2126X_SDIV_MASK	(0x3)
+#define PLL2126X_MDIV_SHIFT	(16)
+#define PLL2126X_PDIV_SHIFT	(8)
+#define PLL2126X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll2126x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll2126x(_hw) container_of(_hw, struct samsung_clk_pll2126x, hw)
+
+static unsigned long samsung_pll2126x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll2126x *pll = to_clk_pll2126x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL2126X_MDIV_SHIFT) & PLL2126X_MDIV_MASK;
+	pdiv = (pll_con >> PLL2126X_PDIV_SHIFT) & PLL2126X_PDIV_MASK;
+	sdiv = (pll_con >> PLL2126X_SDIV_SHIFT) & PLL2126X_SDIV_MASK;
+
+	fvco *= (mdiv + 8);
+	do_div(fvco, (pdiv + 2) << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll2126x clock round rate operation */
+static long samsung_pll2126x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll2126x clock set rate */
+static int samsung_pll2126x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll2126x_clk_ops = {
+	.recalc_rate = samsung_pll2126x_recalc_rate,
+	.round_rate = samsung_pll2126x_round_rate,
+	.set_rate = samsung_pll2126x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll2126x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll2126x *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_pll2126x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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
  */
 
@@ -497,3 +588,288 @@ struct clk * __init samsung_clk_register_pll2550x(const char *name,
 
 	return clk;
 }
+
+/*
+ * PLL3000x Clock Type
+ */
+
+#define PLL3000X_MDIV_MASK	(0xFF)
+#define PLL3000X_PDIV_MASK	(0x3)
+#define PLL3000X_SDIV_MASK	(0x3)
+#define PLL3000X_MDIV_SHIFT	(16)
+#define PLL3000X_PDIV_SHIFT	(8)
+#define PLL3000X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll3000x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll3000x(_hw) container_of(_hw, struct samsung_clk_pll3000x, hw)
+
+static unsigned long samsung_pll3000x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll3000x *pll = to_clk_pll3000x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL3000X_MDIV_SHIFT) & PLL3000X_MDIV_MASK;
+	pdiv = (pll_con >> PLL3000X_PDIV_SHIFT) & PLL3000X_PDIV_MASK;
+	sdiv = (pll_con >> PLL3000X_SDIV_SHIFT) & PLL3000X_SDIV_MASK;
+
+	fvco *= (2 * (mdiv + 8));
+	do_div(fvco, pdiv << sdiv);
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll3000x clock round rate operation */
+static long samsung_pll3000x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll3000x clock set rate */
+static int samsung_pll3000x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll3000x_clk_ops = {
+	.recalc_rate = samsung_pll3000x_recalc_rate,
+	.round_rate = samsung_pll3000x_round_rate,
+	.set_rate = samsung_pll3000x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll3000x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll3000x *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_pll3000x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
+
+/*
+ * PLL6552x Clock Type
+ */
+
+#define PLL6552X_MDIV_MASK	(0x3FF)
+#define PLL6552X_PDIV_MASK	(0x3F)
+#define PLL6552X_SDIV_MASK	(0x7)
+#define PLL6552X_MDIV_SHIFT	(14)
+#define PLL6552X_PDIV_SHIFT	(5)
+#define PLL6552X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll6552x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll6552x(_hw) container_of(_hw, struct samsung_clk_pll6552x, hw)
+
+static unsigned long samsung_pll6552x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll6552x *pll = to_clk_pll6552x(hw);
+	u32 pll_con, mdiv, pdiv, sdiv;
+	u64 fvco = parent_rate;
+
+	pll_con = __raw_readl(pll->con_reg);
+	mdiv = (pll_con >> PLL6552X_MDIV_SHIFT) & PLL6552X_MDIV_MASK;
+	pdiv = (pll_con >> PLL6552X_PDIV_SHIFT) & PLL6552X_PDIV_MASK;
+	sdiv = (pll_con >> PLL6552X_SDIV_SHIFT) & PLL6552X_SDIV_MASK;
+
+	fvco *= mdiv;
+	do_div(fvco, (pdiv << sdiv));
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll6552x clock round rate operation */
+static long samsung_pll6552x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll6552x clock set rate */
+static int samsung_pll6552x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll6552x_clk_ops = {
+	.recalc_rate = samsung_pll6552x_recalc_rate,
+	.round_rate = samsung_pll6552x_round_rate,
+	.set_rate = samsung_pll6552x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll6552x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll6552x *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_pll6552x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
+
+/*
+ * PLL6553x Clock Type
+ */
+
+#define PLL6553X_MDIV_MASK	(0x7F)
+#define PLL6553X_PDIV_MASK	(0x1F)
+#define PLL6553X_SDIV_MASK	(0x3)
+#define PLL6553X_KDIV_MASK	(0xFFFF)
+#define PLL6553X_MDIV_SHIFT	(16)
+#define PLL6553X_PDIV_SHIFT	(8)
+#define PLL6553X_SDIV_SHIFT	(0)
+
+struct samsung_clk_pll6553x {
+	struct clk_hw		hw;
+	const void __iomem	*con_reg;
+};
+
+#define to_clk_pll6553x(_hw) container_of(_hw, struct samsung_clk_pll6553x, hw)
+
+static unsigned long samsung_pll6553x_recalc_rate(struct clk_hw *hw,
+				unsigned long parent_rate)
+{
+	struct samsung_clk_pll6553x *pll = to_clk_pll6553x(hw);
+	u32 pll_con0, pll_con1, mdiv, pdiv, sdiv, kdiv;
+	u64 fvco = parent_rate;
+
+	pll_con0 = __raw_readl(pll->con_reg);
+	pll_con1 = __raw_readl(pll->con_reg + 4);
+	mdiv = (pll_con0 >> PLL6553X_MDIV_SHIFT) & PLL6553X_MDIV_MASK;
+	pdiv = (pll_con0 >> PLL6553X_PDIV_SHIFT) & PLL6553X_PDIV_MASK;
+	sdiv = (pll_con0 >> PLL6553X_SDIV_SHIFT) & PLL6553X_SDIV_MASK;
+	kdiv = pll_con1 & PLL6553X_KDIV_MASK;
+
+	/*
+	 * We need to multiple parent_rate by mdiv (the integer part) and kdiv
+	 * which is in 2^16ths, so shift mdiv up (does not overflow) and
+	 * add kdiv before multiplying. The use of tmp is to avoid any
+	 * overflows before shifting bac down into result when multipling
+	 * by the mdiv and kdiv pair.
+	 */
+
+	fvco *= (mdiv << 16) + kdiv;
+	do_div(fvco, (pdiv << sdiv));
+	fvco >>= 16;
+
+	return (unsigned long)fvco;
+}
+
+/* todo: implement pll6553x clock round rate operation */
+static long samsung_pll6553x_round_rate(struct clk_hw *hw,
+				unsigned long drate, unsigned long *prate)
+{
+	return -ENOTSUPP;
+}
+
+/* todo: implement pll6553x clock set rate */
+static int samsung_pll6553x_set_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long prate)
+{
+	return -ENOTSUPP;
+}
+
+static const struct clk_ops samsung_pll6553x_clk_ops = {
+	.recalc_rate = samsung_pll6553x_recalc_rate,
+	.round_rate = samsung_pll6553x_round_rate,
+	.set_rate = samsung_pll6553x_set_rate,
+};
+
+struct clk * __init samsung_clk_register_pll6553x(const char *name,
+			const char *pname, const void __iomem *con_reg)
+{
+	struct samsung_clk_pll6553x *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_pll6553x_clk_ops;
+	init.flags = CLK_GET_RATE_NOCACHE;
+	init.parent_names = &pname;
+	init.num_parents = 1;
+
+	pll->hw.init = &init;
+	pll->con_reg = con_reg;
+
+	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;
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
index f33786e..465ee6f 100644
--- a/drivers/clk/samsung/clk-pll.h
+++ b/drivers/clk/samsung/clk-pll.h
@@ -34,8 +34,16 @@ 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 * __init samsung_clk_register_pll2126x(const char *name,
+			const char *pname, const void __iomem *con_reg);
 extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
 			const char *pname, const void __iomem *reg_base,
 			const unsigned long offset);
+extern struct clk * __init samsung_clk_register_pll3000x(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll6552x(const char *name,
+			const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll6553x(const char *name,
+			const char *pname, const void __iomem *con_reg);
 
 #endif /* __SAMSUNG_CLK_PLL_H */
-- 
1.7.2.3

  reply	other threads:[~2013-03-12  0:42 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-12  0:41 [PATCH 0/7] ARM: S3C24XX: Convert S3C2416 to common clock framework Heiko Stübner
2013-03-12  0:41 ` Heiko Stübner
2013-03-12  0:42 ` Heiko Stübner [this message]
2013-03-12  0:42   ` [PATCH 1/7] clk: samsung: add plls used in s3c2416 and s3c2443 Heiko Stübner
2013-03-12 11:27   ` Russell King - ARM Linux
2013-03-12 11:27     ` Russell King - ARM Linux
2013-03-12 12:10   ` Sylwester Nawrocki
2013-03-12 12:10     ` Sylwester Nawrocki
2013-03-12 12:21     ` Heiko Stübner
2013-03-12 12:21       ` Heiko Stübner
2013-03-12 13:17       ` Sylwester Nawrocki
2013-03-12 13:17         ` Sylwester Nawrocki
2013-03-12  0:42 ` [PATCH 2/7] ARM: S3C24XX: add soc_is_s3c2416 and soc_is_s3c2443 Heiko Stübner
2013-03-12  0:42   ` Heiko Stübner
2013-03-12  0:43 ` [PATCH 3/7] ARM: S3C24XX: enable legacy clock code only when SAMSUNG_CLOCK selected Heiko Stübner
2013-03-12  0:43   ` Heiko Stübner
2013-03-12  0:43 ` [PATCH 4/7] clk: samsung: add clock-driver for s3c2416, s3c2443 and s3c2450 Heiko Stübner
2013-03-12  0:43   ` Heiko Stübner
2013-03-12  0:44 ` [PATCH 5/7] DO_NOT_APPLY: add clock driver for Samsung pwm clocks Heiko Stübner
2013-03-12  0:44   ` Heiko Stübner
2013-03-12  0:45 ` [PATCH 6/7] ARM: SAMSUNG: use clk_prepare_enable in samsung-time Heiko Stübner
2013-03-12  0:45   ` Heiko Stübner
2013-03-13 16:59   ` Pankaj Jangra
2013-03-13 16:59     ` Pankaj Jangra
2013-03-13 23:16     ` Heiko Stübner
2013-03-13 23:16       ` Heiko Stübner
2013-03-12  0:46 ` [PATCH 7/7] DO_NOT_APPLY: convert s3c2416 to use the common clock framework Heiko Stübner
2013-03-12  0:46   ` Heiko Stübner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201303120142.19842.heiko@sntech.de \
    --to=heiko@sntech.de \
    --cc=kgene.kim@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    --cc=mturquette@linaro.org \
    --cc=sylvester.nawrocki@gmail.com \
    --cc=t.figa@samsung.com \
    --cc=thomas.abraham@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.