From 7348c1bed5da5654b9eefb79881910905d0a57a5 Mon Sep 17 00:00:00 2001
From: dkl <dkl@rock-chips.com>
Date: Sun, 20 Apr 2014 21:19:13 +0800
Subject: [PATCH] clk: rockchip: rk3288: adjust clock settings

1. add clkops_rate_3288_dclk_lcdc0/1
2. change gpll init_rate to 297M, and npll init_rate to 1250M
---
 arch/arm/boot/dts/rk3288-clocks.dtsi |   9 +-
 arch/arm/boot/dts/rk3288.dtsi        |   7 +-
 drivers/clk/rockchip/clk-ops.c       | 118 +++++++++++++++++++++++++++
 drivers/clk/rockchip/clk-pll.c       |   1 +
 include/dt-bindings/clock/rockchip.h |   2 +
 5 files changed, 132 insertions(+), 5 deletions(-)

diff --git a/arch/arm/boot/dts/rk3288-clocks.dtsi b/arch/arm/boot/dts/rk3288-clocks.dtsi
index 92d69a422742..f3e007fe34d3 100755
--- a/arch/arm/boot/dts/rk3288-clocks.dtsi
+++ b/arch/arm/boot/dts/rk3288-clocks.dtsi
@@ -662,6 +662,7 @@
 						clocks = <&clk_cpll>, <&clk_gpll>;
 						clock-output-names = "clk_spdif_pll";
 						#clock-cells = <0>;
+						#clock-init-cells = <1>;
 					};
 				};
 
@@ -1417,7 +1418,8 @@
 						rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
 						#clock-cells = <0>;
 						rockchip,clkops-idx =
-							<CLKOPS_RATE_MUX_EVENDIV>;
+							<CLKOPS_RATE_RK3288_DCLK_LCDC0>;
+						rockchip,flags = <CLK_SET_RATE_PARENT>;
 					};
 				};
 
@@ -1524,7 +1526,8 @@
 						rockchip,div-type = <CLK_DIVIDER_PLUS_ONE>;
 						#clock-cells = <0>;
 						rockchip,clkops-idx =
-							<CLKOPS_RATE_MUX_DIV>;
+							<CLKOPS_RATE_RK3288_DCLK_LCDC1>;
+						rockchip,flags = <CLK_SET_RATE_PARENT>;
 					};
 				};
 
@@ -1594,6 +1597,7 @@
 						#clock-cells = <0>;
 						rockchip,clkops-idx =
 							<CLKOPS_RATE_MUX_DIV>;
+						rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
 					};
 
 					/* reg[5]: reserved */
@@ -1616,6 +1620,7 @@
 						#clock-cells = <0>;
 						rockchip,clkops-idx =
 							<CLKOPS_RATE_MUX_DIV>;
+						rockchip,flags = <CLK_SET_RATE_NO_REPARENT>;
 					};
 
 					/* reg[13]: reserved */
diff --git a/arch/arm/boot/dts/rk3288.dtsi b/arch/arm/boot/dts/rk3288.dtsi
index b1e33458e2c2..3e0cb606d034 100755
--- a/arch/arm/boot/dts/rk3288.dtsi
+++ b/arch/arm/boot/dts/rk3288.dtsi
@@ -479,10 +479,11 @@
 		rockchip,clocks-init-parent =
 			<&clk_core &clk_apll>,	<&aclk_bus_src &clk_gpll>,
 			<&aclk_peri &clk_gpll>,	<&uart_pll_mux &clk_gpll>,
-			<&clk_i2s_pll &clk_cpll>, <&usbphy_480m &otgphy2_480m>;
+			<&clk_i2s_pll &clk_gpll>, <&clk_spdif_pll &clk_gpll>,
+			<&usbphy_480m &otgphy2_480m>;
 		rockchip,clocks-init-rate =
-			<&clk_core 792000000>,	<&clk_gpll 594000000>,
-			<&clk_cpll 384000000>,	<&clk_npll 500000000>,
+			<&clk_core 792000000>,	<&clk_gpll 297000000>,
+			/*<&clk_cpll 47000000>,*/	<&clk_npll 1250000000>,
 			<&aclk_bus_src 300000000>,	<&aclk_bus 300000000>,
 			<&hclk_bus 150000000>,	<&pclk_bus 75000000>,
 			<&clk_crypto 150000000>,	<&aclk_peri 300000000>,
diff --git a/drivers/clk/rockchip/clk-ops.c b/drivers/clk/rockchip/clk-ops.c
index f74ce889d960..4e7aef47321c 100644
--- a/drivers/clk/rockchip/clk-ops.c
+++ b/drivers/clk/rockchip/clk-ops.c
@@ -558,6 +558,122 @@ const struct clk_ops clkops_rate_3288_usb480m = {
 	.recalc_rate	= clk_3288_usb480m_recalc_rate,
 };
 
+#define RK3288_LIMIT_PLL_VIO0 (400*MHZ)
+
+static long clk_3288_dclk_lcdc0_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *best_parent_rate,
+		struct clk **best_parent_p)
+{
+	struct clk *gpll = clk_get(NULL, "clk_gpll");
+	struct clk *cpll = clk_get(NULL, "clk_cpll");
+	unsigned long best, div, prate;
+
+
+	if((rate <= (297*MHZ)) && ((297*MHZ)%rate == 0)) {
+		*best_parent_p = gpll;
+		best = rate;
+	} else {
+		*best_parent_p = cpll;
+		div = RK3288_LIMIT_PLL_VIO0/rate;
+		prate = div * rate;
+		*best_parent_rate = clk_round_rate(cpll, prate);
+		best = (*best_parent_rate)/div;	
+	}
+
+	return best;
+}
+
+static long clk_3288_dclk_lcdc0_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	return clk_3288_dclk_lcdc0_determine_rate(hw, rate, prate, NULL);
+}
+
+static int clk_3288_dclk_lcdc0_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk* aclk_vio0 = clk_get(NULL, "aclk_vio0");
+	struct clk* parent;
+
+	clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+	/* set aclk_vio */
+	if(parent_rate	== 297*MHZ)
+		parent = clk_get(NULL, "clk_gpll");
+	else
+		parent = clk_get(NULL, "clk_cpll");
+
+	clk_set_parent(aclk_vio0, parent);
+	clk_set_rate(aclk_vio0, __clk_get_rate(parent));
+
+	return 0;
+}
+
+const struct clk_ops clkops_rate_3288_dclk_lcdc0 = {
+	.determine_rate = clk_3288_dclk_lcdc0_determine_rate,
+	.set_rate	= clk_3288_dclk_lcdc0_set_rate,
+	.round_rate	= clk_3288_dclk_lcdc0_round_rate,
+	.recalc_rate	= clk_divider_recalc_rate,
+};
+
+#define RK3288_LIMIT_PLL_VIO1 (348*MHZ)
+
+static long clk_3288_dclk_lcdc1_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *best_parent_rate,
+		struct clk **best_parent_p)
+{
+	struct clk *gpll = clk_get(NULL, "clk_gpll");
+	struct clk *cpll = clk_get(NULL, "clk_cpll");
+	unsigned long best, div, prate;
+
+
+	if((rate <= (297*MHZ)) && ((297*MHZ)%rate == 0)) {
+		*best_parent_p = gpll;
+		best = rate;
+	} else {
+		*best_parent_p = cpll;
+		div = RK3288_LIMIT_PLL_VIO1/rate;
+		prate = div * rate;
+		*best_parent_rate = clk_round_rate(cpll, prate);
+		best = (*best_parent_rate)/div;	
+	}
+
+	return best;
+}
+
+static long clk_3288_dclk_lcdc1_round_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *prate)
+{
+	return clk_3288_dclk_lcdc1_determine_rate(hw, rate, prate, NULL);
+}
+
+static int clk_3288_dclk_lcdc1_set_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long parent_rate)
+{
+	struct clk* aclk_vio1 = clk_get(NULL, "aclk_vio1");
+	struct clk* parent;
+
+	clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+	/* set aclk_vio */
+	if(parent_rate	== 297*MHZ)
+		parent = clk_get(NULL, "clk_gpll");
+	else
+		parent = clk_get(NULL, "clk_cpll");
+
+	clk_set_parent(aclk_vio1, parent);
+	clk_set_rate(aclk_vio1, __clk_get_rate(parent));
+
+	return 0;
+}
+
+const struct clk_ops clkops_rate_3288_dclk_lcdc1 = {
+	.determine_rate = clk_3288_dclk_lcdc1_determine_rate,
+	.set_rate	= clk_3288_dclk_lcdc1_set_rate,
+	.round_rate	= clk_3288_dclk_lcdc1_round_rate,
+	.recalc_rate	= clk_divider_recalc_rate,
+};
+
 
 struct clk_ops_table rk_clkops_rate_table[] = {
 	{.index = CLKOPS_RATE_MUX_DIV,		.clk_ops = &clkops_rate_auto_parent},
@@ -570,6 +686,8 @@ struct clk_ops_table rk_clkops_rate_table[] = {
 	{.index = CLKOPS_RATE_DDR,		.clk_ops = &clkops_rate_ddr},
 	{.index = CLKOPS_RATE_RK3288_I2S,	.clk_ops = &clkops_rate_3288_i2s},
 	{.index = CLKOPS_RATE_RK3288_USB480M,	.clk_ops = &clkops_rate_3288_usb480m},
+	{.index = CLKOPS_RATE_RK3288_DCLK_LCDC0,.clk_ops = &clkops_rate_3288_dclk_lcdc0},
+	{.index = CLKOPS_RATE_RK3288_DCLK_LCDC1,.clk_ops = &clkops_rate_3288_dclk_lcdc1},
 	{.index = CLKOPS_RATE_I2S,		.clk_ops = NULL},
 	{.index = CLKOPS_RATE_CIFOUT,		.clk_ops = NULL},
 	{.index = CLKOPS_RATE_UART,		.clk_ops = NULL},
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c
index e3cd58124954..24f87c1f142c 100644
--- a/drivers/clk/rockchip/clk-pll.c
+++ b/drivers/clk/rockchip/clk-pll.c
@@ -6,6 +6,7 @@
 
 
 static const struct pll_clk_set pll_com_table[] = {
+	_RK3188_PLL_SET_CLKS(1250000,	12,	625,	1),
 	_RK3188_PLL_SET_CLKS(1200000,	1,	50,	1),
 	_RK3188_PLL_SET_CLKS(1188000,	2,	99,	1),
 	_RK3188_PLL_SET_CLKS(891000,	8,	594,	2),
diff --git a/include/dt-bindings/clock/rockchip.h b/include/dt-bindings/clock/rockchip.h
index 927a51d0a621..c216a0e9c109 100644
--- a/include/dt-bindings/clock/rockchip.h
+++ b/include/dt-bindings/clock/rockchip.h
@@ -54,6 +54,8 @@
 #define CLKOPS_RATE_DDR			13
 #define CLKOPS_RATE_RK3288_I2S		14
 #define CLKOPS_RATE_RK3288_USB480M	15
+#define CLKOPS_RATE_RK3288_DCLK_LCDC0	16
+#define CLKOPS_RATE_RK3288_DCLK_LCDC1	17
 #define CLKOPS_TABLE_END		(~0)
 
 /* pd id */
-- 
2.34.1