0001
0002
0003
0004
0005
0006
0007
0008
0009
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
0022
0023 #define SARL 0
0024 #define SARL_A370_SSCG_ENABLE BIT(10)
0025 #define SARL_A370_PCLK_FREQ_OPT 11
0026 #define SARL_A370_PCLK_FREQ_OPT_MASK 0xF
0027 #define SARL_A370_FAB_FREQ_OPT 15
0028 #define SARL_A370_FAB_FREQ_OPT_MASK 0x1F
0029 #define SARL_A370_TCLK_FREQ_OPT 20
0030 #define SARL_A370_TCLK_FREQ_OPT_MASK 0x1
0031
0032 enum { A370_CPU_TO_NBCLK, A370_CPU_TO_HCLK, A370_CPU_TO_DRAMCLK };
0033
0034 static const struct coreclk_ratio a370_coreclk_ratios[] __initconst = {
0035 { .id = A370_CPU_TO_NBCLK, .name = "nbclk" },
0036 { .id = A370_CPU_TO_HCLK, .name = "hclk" },
0037 { .id = A370_CPU_TO_DRAMCLK, .name = "dramclk" },
0038 };
0039
0040 static const u32 a370_tclk_freqs[] __initconst = {
0041 166000000,
0042 200000000,
0043 };
0044
0045 static u32 __init a370_get_tclk_freq(void __iomem *sar)
0046 {
0047 u8 tclk_freq_select = 0;
0048
0049 tclk_freq_select = ((readl(sar) >> SARL_A370_TCLK_FREQ_OPT) &
0050 SARL_A370_TCLK_FREQ_OPT_MASK);
0051 return a370_tclk_freqs[tclk_freq_select];
0052 }
0053
0054 static const u32 a370_cpu_freqs[] __initconst = {
0055 400000000,
0056 533000000,
0057 667000000,
0058 800000000,
0059 1000000000,
0060 1067000000,
0061 1200000000,
0062 };
0063
0064 static u32 __init a370_get_cpu_freq(void __iomem *sar)
0065 {
0066 u32 cpu_freq;
0067 u8 cpu_freq_select = 0;
0068
0069 cpu_freq_select = ((readl(sar) >> SARL_A370_PCLK_FREQ_OPT) &
0070 SARL_A370_PCLK_FREQ_OPT_MASK);
0071 if (cpu_freq_select >= ARRAY_SIZE(a370_cpu_freqs)) {
0072 pr_err("CPU freq select unsupported %d\n", cpu_freq_select);
0073 cpu_freq = 0;
0074 } else
0075 cpu_freq = a370_cpu_freqs[cpu_freq_select];
0076
0077 return cpu_freq;
0078 }
0079
0080 static const int a370_nbclk_ratios[32][2] __initconst = {
0081 {0, 1}, {1, 2}, {2, 2}, {2, 2},
0082 {1, 2}, {1, 2}, {1, 1}, {2, 3},
0083 {0, 1}, {1, 2}, {2, 4}, {0, 1},
0084 {1, 2}, {0, 1}, {0, 1}, {2, 2},
0085 {0, 1}, {0, 1}, {0, 1}, {1, 1},
0086 {2, 3}, {0, 1}, {0, 1}, {0, 1},
0087 {0, 1}, {0, 1}, {0, 1}, {1, 1},
0088 {0, 1}, {0, 1}, {0, 1}, {0, 1},
0089 };
0090
0091 static const int a370_hclk_ratios[32][2] __initconst = {
0092 {0, 1}, {1, 2}, {2, 6}, {2, 3},
0093 {1, 3}, {1, 4}, {1, 2}, {2, 6},
0094 {0, 1}, {1, 6}, {2, 10}, {0, 1},
0095 {1, 4}, {0, 1}, {0, 1}, {2, 5},
0096 {0, 1}, {0, 1}, {0, 1}, {1, 2},
0097 {2, 6}, {0, 1}, {0, 1}, {0, 1},
0098 {0, 1}, {0, 1}, {0, 1}, {1, 1},
0099 {0, 1}, {0, 1}, {0, 1}, {0, 1},
0100 };
0101
0102 static const int a370_dramclk_ratios[32][2] __initconst = {
0103 {0, 1}, {1, 2}, {2, 3}, {2, 3},
0104 {1, 3}, {1, 2}, {1, 2}, {2, 6},
0105 {0, 1}, {1, 3}, {2, 5}, {0, 1},
0106 {1, 4}, {0, 1}, {0, 1}, {2, 5},
0107 {0, 1}, {0, 1}, {0, 1}, {1, 1},
0108 {2, 3}, {0, 1}, {0, 1}, {0, 1},
0109 {0, 1}, {0, 1}, {0, 1}, {1, 1},
0110 {0, 1}, {0, 1}, {0, 1}, {0, 1},
0111 };
0112
0113 static void __init a370_get_clk_ratio(
0114 void __iomem *sar, int id, int *mult, int *div)
0115 {
0116 u32 opt = ((readl(sar) >> SARL_A370_FAB_FREQ_OPT) &
0117 SARL_A370_FAB_FREQ_OPT_MASK);
0118
0119 switch (id) {
0120 case A370_CPU_TO_NBCLK:
0121 *mult = a370_nbclk_ratios[opt][0];
0122 *div = a370_nbclk_ratios[opt][1];
0123 break;
0124 case A370_CPU_TO_HCLK:
0125 *mult = a370_hclk_ratios[opt][0];
0126 *div = a370_hclk_ratios[opt][1];
0127 break;
0128 case A370_CPU_TO_DRAMCLK:
0129 *mult = a370_dramclk_ratios[opt][0];
0130 *div = a370_dramclk_ratios[opt][1];
0131 break;
0132 }
0133 }
0134
0135 static bool a370_is_sscg_enabled(void __iomem *sar)
0136 {
0137 return !(readl(sar) & SARL_A370_SSCG_ENABLE);
0138 }
0139
0140 static const struct coreclk_soc_desc a370_coreclks = {
0141 .get_tclk_freq = a370_get_tclk_freq,
0142 .get_cpu_freq = a370_get_cpu_freq,
0143 .get_clk_ratio = a370_get_clk_ratio,
0144 .is_sscg_enabled = a370_is_sscg_enabled,
0145 .fix_sscg_deviation = kirkwood_fix_sscg_deviation,
0146 .ratios = a370_coreclk_ratios,
0147 .num_ratios = ARRAY_SIZE(a370_coreclk_ratios),
0148 };
0149
0150
0151
0152
0153
0154 static const struct clk_gating_soc_desc a370_gating_desc[] __initconst = {
0155 { "audio", NULL, 0, 0 },
0156 { "pex0_en", NULL, 1, 0 },
0157 { "pex1_en", NULL, 2, 0 },
0158 { "ge1", NULL, 3, 0 },
0159 { "ge0", NULL, 4, 0 },
0160 { "pex0", "pex0_en", 5, 0 },
0161 { "pex1", "pex1_en", 9, 0 },
0162 { "sata0", NULL, 15, 0 },
0163 { "sdio", NULL, 17, 0 },
0164 { "crypto", NULL, 23, CLK_IGNORE_UNUSED },
0165 { "tdm", NULL, 25, 0 },
0166 { "ddr", NULL, 28, CLK_IGNORE_UNUSED },
0167 { "sata1", NULL, 30, 0 },
0168 { }
0169 };
0170
0171 static void __init a370_clk_init(struct device_node *np)
0172 {
0173 struct device_node *cgnp =
0174 of_find_compatible_node(NULL, NULL, "marvell,armada-370-gating-clock");
0175
0176 mvebu_coreclk_setup(np, &a370_coreclks);
0177
0178 if (cgnp) {
0179 mvebu_clk_gating_setup(cgnp, a370_gating_desc);
0180 of_node_put(cgnp);
0181 }
0182 }
0183 CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init);
0184