|
@@ -1130,3 +1130,115 @@ static int s5pv210_epll_set_rate(struct clk *clk, unsigned long rate)
|
|
|
unsigned int epll_con, epll_con_k;
|
|
|
unsigned int i;
|
|
|
|
|
|
+ /* Return if nothing changed */
|
|
|
+ if (clk->rate == rate)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ epll_con = __raw_readl(S5P_EPLL_CON);
|
|
|
+ epll_con_k = __raw_readl(S5P_EPLL_CON1);
|
|
|
+
|
|
|
+ epll_con_k &= ~PLL46XX_KDIV_MASK;
|
|
|
+ epll_con &= ~(1 << 27 |
|
|
|
+ PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |
|
|
|
+ PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT |
|
|
|
+ PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
|
|
|
+ if (epll_div[i][0] == rate) {
|
|
|
+ epll_con_k |= epll_div[i][5] << 0;
|
|
|
+ epll_con |= (epll_div[i][1] << 27 |
|
|
|
+ epll_div[i][2] << PLL46XX_MDIV_SHIFT |
|
|
|
+ epll_div[i][3] << PLL46XX_PDIV_SHIFT |
|
|
|
+ epll_div[i][4] << PLL46XX_SDIV_SHIFT);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == ARRAY_SIZE(epll_div)) {
|
|
|
+ printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ __raw_writel(epll_con, S5P_EPLL_CON);
|
|
|
+ __raw_writel(epll_con_k, S5P_EPLL_CON1);
|
|
|
+
|
|
|
+ printk(KERN_WARNING "EPLL Rate changes from %lu to %lu\n",
|
|
|
+ clk->rate, rate);
|
|
|
+
|
|
|
+ clk->rate = rate;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct clk_ops s5pv210_epll_ops = {
|
|
|
+ .set_rate = s5pv210_epll_set_rate,
|
|
|
+ .get_rate = s5p_epll_get_rate,
|
|
|
+};
|
|
|
+
|
|
|
+static u32 vpll_div[][5] = {
|
|
|
+ { 54000000, 3, 53, 3, 0 },
|
|
|
+ { 108000000, 3, 53, 2, 0 },
|
|
|
+};
|
|
|
+
|
|
|
+static unsigned long s5pv210_vpll_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ return clk->rate;
|
|
|
+}
|
|
|
+
|
|
|
+static int s5pv210_vpll_set_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ unsigned int vpll_con;
|
|
|
+ unsigned int i;
|
|
|
+
|
|
|
+ /* Return if nothing changed */
|
|
|
+ if (clk->rate == rate)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ vpll_con = __raw_readl(S5P_VPLL_CON);
|
|
|
+ vpll_con &= ~(0x1 << 27 | \
|
|
|
+ PLL90XX_MDIV_MASK << PLL90XX_MDIV_SHIFT | \
|
|
|
+ PLL90XX_PDIV_MASK << PLL90XX_PDIV_SHIFT | \
|
|
|
+ PLL90XX_SDIV_MASK << PLL90XX_SDIV_SHIFT);
|
|
|
+
|
|
|
+ for (i = 0; i < ARRAY_SIZE(vpll_div); i++) {
|
|
|
+ if (vpll_div[i][0] == rate) {
|
|
|
+ vpll_con |= vpll_div[i][1] << PLL90XX_PDIV_SHIFT;
|
|
|
+ vpll_con |= vpll_div[i][2] << PLL90XX_MDIV_SHIFT;
|
|
|
+ vpll_con |= vpll_div[i][3] << PLL90XX_SDIV_SHIFT;
|
|
|
+ vpll_con |= vpll_div[i][4] << 27;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (i == ARRAY_SIZE(vpll_div)) {
|
|
|
+ printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
|
|
|
+ __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ __raw_writel(vpll_con, S5P_VPLL_CON);
|
|
|
+
|
|
|
+ /* Wait for VPLL lock */
|
|
|
+ while (!(__raw_readl(S5P_VPLL_CON) & (1 << PLL90XX_LOCKED_SHIFT)))
|
|
|
+ continue;
|
|
|
+
|
|
|
+ clk->rate = rate;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+static struct clk_ops s5pv210_vpll_ops = {
|
|
|
+ .get_rate = s5pv210_vpll_get_rate,
|
|
|
+ .set_rate = s5pv210_vpll_set_rate,
|
|
|
+};
|
|
|
+
|
|
|
+void __init_or_cpufreq s5pv210_setup_clocks(void)
|
|
|
+{
|
|
|
+ struct clk *xtal_clk;
|
|
|
+ unsigned long vpllsrc;
|
|
|
+ unsigned long armclk;
|
|
|
+ unsigned long hclk_msys;
|
|
|
+ unsigned long hclk_dsys;
|
|
|
+ unsigned long hclk_psys;
|
|
|
+ unsigned long pclk_msys;
|
|
|
+ unsigned long pclk_dsys;
|
|
|
+ unsigned long pclk_psys;
|