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
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
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
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
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);