ARM: shmobile: r8a7778: use fixed ratio clock
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Fri, 12 Apr 2013 08:13:14 +0000 (01:13 -0700)
committerSimon Horman <horms+renesas@verge.net.au>
Fri, 7 Jun 2013 05:24:47 +0000 (14:24 +0900)
R-Car M1 has many clocks, and it is possible to
read/use clock ratio of these clocks from FRQMRx.
But, these ratio are fixed value and
these are decided by MD pin status.

This patch reads MD pin status,
and used fixed ratio clock for other clocks.
It was tesed on bock-w board.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
arch/arm/mach-shmobile/clock-r8a7778.c

index cd68552..5cc271e 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+/*
+ *     MD      MD      MD      MD       PLLA   PLLB    EXTAL   clki    clkz
+ *     19      18      12      11                      (HMz)   (MHz)   (MHz)
+ *----------------------------------------------------------------------------
+ *     1       0       0       0       x21     x21     38.00   800     800
+ *     1       0       0       1       x24     x24     33.33   800     800
+ *     1       0       1       0       x28     x28     28.50   800     800
+ *     1       0       1       1       x32     x32     25.00   800     800
+ *     1       1       0       1       x24     x21     33.33   800     700
+ *     1       1       1       0       x28     x21     28.50   800     600
+ *     1       1       1       1       x32     x24     25.00   800     600
+ */
+
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 #include <linux/clkdev.h>
+#include <mach/clock.h>
 #include <mach/common.h>
 
 #define MSTPCR0                IOMEM(0xffc80030)
@@ -37,6 +51,9 @@
 #define MSTPCR4                IOMEM(0xffc80050)
 #define MSTPCR5                IOMEM(0xffc80054)
 #define MSTPCR6                IOMEM(0xffc80058)
+#define MODEMR         0xFFCC0020
+
+#define MD(nr) BIT(nr)
 
 /* ioremap() through clock mapping mandatory to avoid
  * collision with ARM coherent DMA virtual memory range.
@@ -47,14 +64,42 @@ static struct clk_mapping cpg_mapping = {
        .len    = 0x80,
 };
 
-static struct clk clkp = {
-       .rate   = 62500000, /* FIXME: shortcut */
-       .flags  = CLK_ENABLE_ON_INIT,
+static struct clk extal_clk = {
+       /* .rate will be updated on r8a7778_clock_init() */
        .mapping = &cpg_mapping,
 };
 
+/*
+ * clock ratio of these clock will be updated
+ * on r8a7778_clock_init()
+ */
+SH_FIXED_RATIO_CLK_SET(plla_clk,       extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(pllb_clk,       extal_clk, 1, 1);
+SH_FIXED_RATIO_CLK_SET(i_clk,          plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(s_clk,          plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(s1_clk,         plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(s3_clk,         plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(s4_clk,         plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(b_clk,          plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(out_clk,                plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(p_clk,          plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(g_clk,          plla_clk,  1, 1);
+SH_FIXED_RATIO_CLK_SET(z_clk,          pllb_clk,  1, 1);
+
 static struct clk *main_clks[] = {
-       &clkp,
+       &extal_clk,
+       &plla_clk,
+       &pllb_clk,
+       &i_clk,
+       &s_clk,
+       &s1_clk,
+       &s3_clk,
+       &s4_clk,
+       &b_clk,
+       &out_clk,
+       &p_clk,
+       &g_clk,
+       &z_clk,
 };
 
 enum {
@@ -64,15 +109,15 @@ enum {
        MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
-       [MSTP114] = SH_CLK_MSTP32(&clkp, MSTPCR1, 14, 0), /* Ether */
-       [MSTP026] = SH_CLK_MSTP32(&clkp, MSTPCR0, 26, 0), /* SCIF0 */
-       [MSTP025] = SH_CLK_MSTP32(&clkp, MSTPCR0, 25, 0), /* SCIF1 */
-       [MSTP024] = SH_CLK_MSTP32(&clkp, MSTPCR0, 24, 0), /* SCIF2 */
-       [MSTP023] = SH_CLK_MSTP32(&clkp, MSTPCR0, 23, 0), /* SCIF3 */
-       [MSTP022] = SH_CLK_MSTP32(&clkp, MSTPCR0, 22, 0), /* SCIF4 */
-       [MSTP021] = SH_CLK_MSTP32(&clkp, MSTPCR0, 21, 0), /* SCIF5 */
-       [MSTP016] = SH_CLK_MSTP32(&clkp, MSTPCR0, 16, 0), /* TMU0 */
-       [MSTP015] = SH_CLK_MSTP32(&clkp, MSTPCR0, 15, 0), /* TMU1 */
+       [MSTP114] = SH_CLK_MSTP32(&p_clk, MSTPCR1, 14, 0), /* Ether */
+       [MSTP026] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 26, 0), /* SCIF0 */
+       [MSTP025] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 25, 0), /* SCIF1 */
+       [MSTP024] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 24, 0), /* SCIF2 */
+       [MSTP023] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 23, 0), /* SCIF3 */
+       [MSTP022] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 22, 0), /* SCIF4 */
+       [MSTP021] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 21, 0), /* SCIF5 */
+       [MSTP016] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 16, 0), /* TMU0 */
+       [MSTP015] = SH_CLK_MSTP32(&p_clk, MSTPCR0, 15, 0), /* TMU1 */
 };
 
 static struct clk_lookup lookups[] = {
@@ -90,8 +135,86 @@ static struct clk_lookup lookups[] = {
 
 void __init r8a7778_clock_init(void)
 {
+       void __iomem *modemr = ioremap_nocache(MODEMR, PAGE_SIZE);
+       u32 mode;
        int k, ret = 0;
 
+       BUG_ON(!modemr);
+       mode = ioread32(modemr);
+       iounmap(modemr);
+
+       switch (mode & (MD(19) | MD(18) | MD(12) | MD(11))) {
+       case MD(19):
+               extal_clk.rate = 38000000;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       21, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
+               break;
+       case MD(19) | MD(11):
+               extal_clk.rate = 33333333;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
+               break;
+       case MD(19) | MD(12):
+               extal_clk.rate = 28500000;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       28, 1);
+               break;
+       case MD(19) | MD(12) | MD(11):
+               extal_clk.rate = 25000000;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       32, 1);
+               break;
+       case MD(19) | MD(18) | MD(11):
+               extal_clk.rate = 33333333;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       24, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
+               break;
+       case MD(19) | MD(18) | MD(12):
+               extal_clk.rate = 28500000;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       28, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       21, 1);
+               break;
+       case MD(19) | MD(18) | MD(12) | MD(11):
+               extal_clk.rate = 25000000;
+               SH_CLK_SET_RATIO(&plla_clk_ratio,       32, 1);
+               SH_CLK_SET_RATIO(&pllb_clk_ratio,       24, 1);
+               break;
+       default:
+               BUG();
+       }
+
+       if (mode & MD(1)) {
+               SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
+               SH_CLK_SET_RATIO(&s_clk_ratio,  1, 3);
+               SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 6);
+               SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+               SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+               SH_CLK_SET_RATIO(&p_clk_ratio,  1, 12);
+               SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
+               if (mode & MD(2)) {
+                       SH_CLK_SET_RATIO(&b_clk_ratio,          1, 18);
+                       SH_CLK_SET_RATIO(&out_clk_ratio,        1, 18);
+               } else {
+                       SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
+                       SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
+               }
+       } else {
+               SH_CLK_SET_RATIO(&i_clk_ratio,  1, 1);
+               SH_CLK_SET_RATIO(&s_clk_ratio,  1, 4);
+               SH_CLK_SET_RATIO(&s1_clk_ratio, 1, 8);
+               SH_CLK_SET_RATIO(&s3_clk_ratio, 1, 4);
+               SH_CLK_SET_RATIO(&s4_clk_ratio, 1, 8);
+               SH_CLK_SET_RATIO(&p_clk_ratio,  1, 16);
+               SH_CLK_SET_RATIO(&g_clk_ratio,  1, 12);
+               if (mode & MD(2)) {
+                       SH_CLK_SET_RATIO(&b_clk_ratio,          1, 16);
+                       SH_CLK_SET_RATIO(&out_clk_ratio,        1, 16);
+               } else {
+                       SH_CLK_SET_RATIO(&b_clk_ratio,          1, 12);
+                       SH_CLK_SET_RATIO(&out_clk_ratio,        1, 12);
+               }
+       }
+
        for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
                ret = clk_register(main_clks[k]);