Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Marvell MV98DX3236 SoC clocks
0004  *
0005  * Copyright (C) 2012 Marvell
0006  *
0007  * Gregory CLEMENT <gregory.clement@free-electrons.com>
0008  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
0009  * Andrew Lunn <andrew@lunn.ch>
0010  *
0011  */
0012 
0013 #include <linux/kernel.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/io.h>
0016 #include <linux/of.h>
0017 #include "common.h"
0018 
0019 
0020 /*
0021  * For 98DX4251 Sample At Reset the CPU, DDR and Main PLL clocks are all
0022  * defined at the same time
0023  *
0024  * SAR1[20:18]   : CPU frequency    DDR frequency   MPLL frequency
0025  *       0  =  400 MHz      400 MHz     800 MHz
0026  *       2  =  667 MHz      667 MHz     2000 MHz
0027  *       3  =  800 MHz      800 MHz     1600 MHz
0028  *       others reserved.
0029  *
0030  * For 98DX3236 Sample At Reset the CPU, DDR and Main PLL clocks are all
0031  * defined at the same time
0032  *
0033  * SAR1[20:18]   : CPU frequency    DDR frequency   MPLL frequency
0034  *       1  =  667 MHz      667 MHz     2000 MHz
0035  *       2  =  400 MHz      400 MHz     400 MHz
0036  *       3  =  800 MHz      800 MHz     800 MHz
0037  *       5  =  800 MHz      400 MHz     800 MHz
0038  *       others reserved.
0039  */
0040 
0041 #define SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT       18
0042 #define SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK  0x7
0043 
0044 static u32 __init mv98dx3236_get_tclk_freq(void __iomem *sar)
0045 {
0046     /* Tclk = 200MHz, no SaR dependency */
0047     return 200000000;
0048 }
0049 
0050 static const u32 mv98dx3236_cpu_frequencies[] __initconst = {
0051     0,
0052     667000000,
0053     400000000,
0054     800000000,
0055     0,
0056     800000000,
0057     0, 0,
0058 };
0059 
0060 static const u32 mv98dx4251_cpu_frequencies[] __initconst = {
0061     400000000,
0062     0,
0063     667000000,
0064     800000000,
0065     0, 0, 0, 0,
0066 };
0067 
0068 static u32 __init mv98dx3236_get_cpu_freq(void __iomem *sar)
0069 {
0070     u32 cpu_freq = 0;
0071     u8 cpu_freq_select = 0;
0072 
0073     cpu_freq_select = ((readl(sar) >> SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT) &
0074                SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK);
0075 
0076     if (of_machine_is_compatible("marvell,armadaxp-98dx4251"))
0077         cpu_freq = mv98dx4251_cpu_frequencies[cpu_freq_select];
0078     else if (of_machine_is_compatible("marvell,armadaxp-98dx3236"))
0079         cpu_freq = mv98dx3236_cpu_frequencies[cpu_freq_select];
0080 
0081     if (!cpu_freq)
0082         pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
0083 
0084     return cpu_freq;
0085 }
0086 
0087 enum {
0088     MV98DX3236_CPU_TO_DDR,
0089     MV98DX3236_CPU_TO_MPLL
0090 };
0091 
0092 static const struct coreclk_ratio mv98dx3236_core_ratios[] __initconst = {
0093     { .id = MV98DX3236_CPU_TO_DDR, .name = "ddrclk" },
0094     { .id = MV98DX3236_CPU_TO_MPLL, .name = "mpll" },
0095 };
0096 
0097 static const int __initconst mv98dx3236_cpu_mpll_ratios[8][2] = {
0098     {0, 1}, {3, 1}, {1, 1}, {1, 1},
0099     {0, 1}, {1, 1}, {0, 1}, {0, 1},
0100 };
0101 
0102 static const int __initconst mv98dx3236_cpu_ddr_ratios[8][2] = {
0103     {0, 1}, {1, 1}, {1, 1}, {1, 1},
0104     {0, 1}, {1, 2}, {0, 1}, {0, 1},
0105 };
0106 
0107 static const int __initconst mv98dx4251_cpu_mpll_ratios[8][2] = {
0108     {2, 1}, {0, 1}, {3, 1}, {2, 1},
0109     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0110 };
0111 
0112 static const int __initconst mv98dx4251_cpu_ddr_ratios[8][2] = {
0113     {1, 1}, {0, 1}, {1, 1}, {1, 1},
0114     {0, 1}, {0, 1}, {0, 1}, {0, 1},
0115 };
0116 
0117 static void __init mv98dx3236_get_clk_ratio(
0118     void __iomem *sar, int id, int *mult, int *div)
0119 {
0120     u32 opt = ((readl(sar) >> SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT) &
0121         SAR1_MV98DX3236_CPU_DDR_MPLL_FREQ_OPT_MASK);
0122 
0123     switch (id) {
0124     case MV98DX3236_CPU_TO_DDR:
0125         if (of_machine_is_compatible("marvell,armadaxp-98dx4251")) {
0126             *mult = mv98dx4251_cpu_ddr_ratios[opt][0];
0127             *div = mv98dx4251_cpu_ddr_ratios[opt][1];
0128         } else if (of_machine_is_compatible("marvell,armadaxp-98dx3236")) {
0129             *mult = mv98dx3236_cpu_ddr_ratios[opt][0];
0130             *div = mv98dx3236_cpu_ddr_ratios[opt][1];
0131         }
0132         break;
0133     case MV98DX3236_CPU_TO_MPLL:
0134         if (of_machine_is_compatible("marvell,armadaxp-98dx4251")) {
0135             *mult = mv98dx4251_cpu_mpll_ratios[opt][0];
0136             *div = mv98dx4251_cpu_mpll_ratios[opt][1];
0137         } else if (of_machine_is_compatible("marvell,armadaxp-98dx3236")) {
0138             *mult = mv98dx3236_cpu_mpll_ratios[opt][0];
0139             *div = mv98dx3236_cpu_mpll_ratios[opt][1];
0140         }
0141         break;
0142     }
0143 }
0144 
0145 static const struct coreclk_soc_desc mv98dx3236_core_clocks = {
0146     .get_tclk_freq = mv98dx3236_get_tclk_freq,
0147     .get_cpu_freq = mv98dx3236_get_cpu_freq,
0148     .get_clk_ratio = mv98dx3236_get_clk_ratio,
0149     .ratios = mv98dx3236_core_ratios,
0150     .num_ratios = ARRAY_SIZE(mv98dx3236_core_ratios),
0151 };
0152 
0153 
0154 /*
0155  * Clock Gating Control
0156  */
0157 
0158 static const struct clk_gating_soc_desc mv98dx3236_gating_desc[] __initconst = {
0159     { "ge1", NULL, 3, 0 },
0160     { "ge0", NULL, 4, 0 },
0161     { "pex00", NULL, 5, 0 },
0162     { "sdio", NULL, 17, 0 },
0163     { "usb0", NULL, 18, 0 },
0164     { "xor0", NULL, 22, 0 },
0165     { }
0166 };
0167 
0168 static void __init mv98dx3236_clk_init(struct device_node *np)
0169 {
0170     struct device_node *cgnp =
0171         of_find_compatible_node(NULL, NULL, "marvell,mv98dx3236-gating-clock");
0172 
0173     mvebu_coreclk_setup(np, &mv98dx3236_core_clocks);
0174 
0175     if (cgnp) {
0176         mvebu_clk_gating_setup(cgnp, mv98dx3236_gating_desc);
0177         of_node_put(cgnp);
0178     }
0179 }
0180 CLK_OF_DECLARE(mv98dx3236_clk, "marvell,mv98dx3236-core-clock", mv98dx3236_clk_init);