|
@@ -512,3 +512,158 @@ static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
|
|
|
return parent / (div + 1);
|
|
|
}
|
|
|
|
|
|
+static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
|
|
|
+{
|
|
|
+ unsigned long parent = clk_get_rate(clk->parent);
|
|
|
+ u32 div;
|
|
|
+ u32 val;
|
|
|
+
|
|
|
+ if (rate < parent / (armclk_mask + 1))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ rate = clk_round_rate(clk, rate);
|
|
|
+ div = clk_get_rate(clk->parent) / rate;
|
|
|
+
|
|
|
+ val = __raw_readl(S3C_CLK_DIV0);
|
|
|
+ val &= ~armclk_mask;
|
|
|
+ val |= (div - 1);
|
|
|
+ __raw_writel(val, S3C_CLK_DIV0);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+static struct clk clk_arm = {
|
|
|
+ .name = "armclk",
|
|
|
+ .parent = &clk_mout_apll.clk,
|
|
|
+ .ops = &(struct clk_ops) {
|
|
|
+ .get_rate = s3c64xx_clk_arm_get_rate,
|
|
|
+ .set_rate = s3c64xx_clk_arm_set_rate,
|
|
|
+ .round_rate = s3c64xx_clk_arm_round_rate,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static unsigned long s3c64xx_clk_doutmpll_get_rate(struct clk *clk)
|
|
|
+{
|
|
|
+ unsigned long rate = clk_get_rate(clk->parent);
|
|
|
+
|
|
|
+ printk(KERN_DEBUG "%s: parent is %ld\n", __func__, rate);
|
|
|
+
|
|
|
+ if (__raw_readl(S3C_CLK_DIV0) & S3C6400_CLKDIV0_MPLL_MASK)
|
|
|
+ rate /= 2;
|
|
|
+
|
|
|
+ return rate;
|
|
|
+}
|
|
|
+
|
|
|
+static struct clk_ops clk_dout_ops = {
|
|
|
+ .get_rate = s3c64xx_clk_doutmpll_get_rate,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_dout_mpll = {
|
|
|
+ .name = "dout_mpll",
|
|
|
+ .parent = &clk_mout_mpll.clk,
|
|
|
+ .ops = &clk_dout_ops,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_spi_mmc_list[] = {
|
|
|
+ &clk_mout_epll.clk,
|
|
|
+ &clk_dout_mpll,
|
|
|
+ &clk_fin_epll,
|
|
|
+ &clk_27m,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_spi_mmc = {
|
|
|
+ .sources = clkset_spi_mmc_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_spi_mmc_list),
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_irda_list[] = {
|
|
|
+ &clk_mout_epll.clk,
|
|
|
+ &clk_dout_mpll,
|
|
|
+ NULL,
|
|
|
+ &clk_27m,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_irda = {
|
|
|
+ .sources = clkset_irda_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_irda_list),
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_uart_list[] = {
|
|
|
+ &clk_mout_epll.clk,
|
|
|
+ &clk_dout_mpll,
|
|
|
+ NULL,
|
|
|
+ NULL
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_uart = {
|
|
|
+ .sources = clkset_uart_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_uart_list),
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_uhost_list[] = {
|
|
|
+ &clk_48m,
|
|
|
+ &clk_mout_epll.clk,
|
|
|
+ &clk_dout_mpll,
|
|
|
+ &clk_fin_epll,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_uhost = {
|
|
|
+ .sources = clkset_uhost_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_uhost_list),
|
|
|
+};
|
|
|
+
|
|
|
+/* The peripheral clocks are all controlled via clocksource followed
|
|
|
+ * by an optional divider and gate stage. We currently roll this into
|
|
|
+ * one clock which hides the intermediate clock from the mux.
|
|
|
+ *
|
|
|
+ * Note, the JPEG clock can only be an even divider...
|
|
|
+ *
|
|
|
+ * The scaler and LCD clocks depend on the S3C64XX version, and also
|
|
|
+ * have a common parent divisor so are not included here.
|
|
|
+ */
|
|
|
+
|
|
|
+/* clocks that feed other parts of the clock source tree */
|
|
|
+
|
|
|
+static struct clk clk_iis_cd0 = {
|
|
|
+ .name = "iis_cdclk0",
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_iis_cd1 = {
|
|
|
+ .name = "iis_cdclk1",
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_iisv4_cd = {
|
|
|
+ .name = "iis_cdclk_v4",
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk clk_pcm_cd = {
|
|
|
+ .name = "pcm_cdclk",
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_audio0_list[] = {
|
|
|
+ [0] = &clk_mout_epll.clk,
|
|
|
+ [1] = &clk_dout_mpll,
|
|
|
+ [2] = &clk_fin_epll,
|
|
|
+ [3] = &clk_iis_cd0,
|
|
|
+ [4] = &clk_pcm_cd,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_audio0 = {
|
|
|
+ .sources = clkset_audio0_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_audio0_list),
|
|
|
+};
|
|
|
+
|
|
|
+static struct clk *clkset_audio1_list[] = {
|
|
|
+ [0] = &clk_mout_epll.clk,
|
|
|
+ [1] = &clk_dout_mpll,
|
|
|
+ [2] = &clk_fin_epll,
|
|
|
+ [3] = &clk_iis_cd1,
|
|
|
+ [4] = &clk_pcm_cd,
|
|
|
+};
|
|
|
+
|
|
|
+static struct clksrc_sources clkset_audio1 = {
|
|
|
+ .sources = clkset_audio1_list,
|
|
|
+ .nr_sources = ARRAY_SIZE(clkset_audio1_list),
|
|
|
+};
|
|
|
+
|