1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Marvell Orion SoC clocks 4 * 5 * Copyright (C) 2014 Thomas Petazzoni 6 * 7 * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> 8 * 9 */ 10 11 #include <linux/kernel.h> 12 #include <linux/clk-provider.h> 13 #include <linux/io.h> 14 #include <linux/of.h> 15 #include "common.h" 16 17 static const struct coreclk_ratio orion_coreclk_ratios[] __initconst = { 18 { .id = 0, .name = "ddrclk", } 19 }; 20 21 /* 22 * Orion 5181 23 */ 24 25 #define SAR_MV88F5181_TCLK_FREQ 8 26 #define SAR_MV88F5181_TCLK_FREQ_MASK 0x3 27 28 static u32 __init mv88f5181_get_tclk_freq(void __iomem *sar) 29 { 30 u32 opt = (readl(sar) >> SAR_MV88F5181_TCLK_FREQ) & 31 SAR_MV88F5181_TCLK_FREQ_MASK; 32 if (opt == 0) 33 return 133333333; 34 else if (opt == 1) 35 return 150000000; 36 else if (opt == 2) 37 return 166666667; 38 else 39 return 0; 40 } 41 42 #define SAR_MV88F5181_CPU_FREQ 4 43 #define SAR_MV88F5181_CPU_FREQ_MASK 0xf 44 45 static u32 __init mv88f5181_get_cpu_freq(void __iomem *sar) 46 { 47 u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) & 48 SAR_MV88F5181_CPU_FREQ_MASK; 49 if (opt == 0) 50 return 333333333; 51 else if (opt == 1 || opt == 2) 52 return 400000000; 53 else if (opt == 3) 54 return 500000000; 55 else 56 return 0; 57 } 58 59 static void __init mv88f5181_get_clk_ratio(void __iomem *sar, int id, 60 int *mult, int *div) 61 { 62 u32 opt = (readl(sar) >> SAR_MV88F5181_CPU_FREQ) & 63 SAR_MV88F5181_CPU_FREQ_MASK; 64 if (opt == 0 || opt == 1) { 65 *mult = 1; 66 *div = 2; 67 } else if (opt == 2 || opt == 3) { 68 *mult = 1; 69 *div = 3; 70 } else { 71 *mult = 0; 72 *div = 1; 73 } 74 } 75 76 static const struct coreclk_soc_desc mv88f5181_coreclks = { 77 .get_tclk_freq = mv88f5181_get_tclk_freq, 78 .get_cpu_freq = mv88f5181_get_cpu_freq, 79 .get_clk_ratio = mv88f5181_get_clk_ratio, 80 .ratios = orion_coreclk_ratios, 81 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 82 }; 83 84 static void __init mv88f5181_clk_init(struct device_node *np) 85 { 86 return mvebu_coreclk_setup(np, &mv88f5181_coreclks); 87 } 88 89 CLK_OF_DECLARE(mv88f5181_clk, "marvell,mv88f5181-core-clock", mv88f5181_clk_init); 90 91 /* 92 * Orion 5182 93 */ 94 95 #define SAR_MV88F5182_TCLK_FREQ 8 96 #define SAR_MV88F5182_TCLK_FREQ_MASK 0x3 97 98 static u32 __init mv88f5182_get_tclk_freq(void __iomem *sar) 99 { 100 u32 opt = (readl(sar) >> SAR_MV88F5182_TCLK_FREQ) & 101 SAR_MV88F5182_TCLK_FREQ_MASK; 102 if (opt == 1) 103 return 150000000; 104 else if (opt == 2) 105 return 166666667; 106 else 107 return 0; 108 } 109 110 #define SAR_MV88F5182_CPU_FREQ 4 111 #define SAR_MV88F5182_CPU_FREQ_MASK 0xf 112 113 static u32 __init mv88f5182_get_cpu_freq(void __iomem *sar) 114 { 115 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) & 116 SAR_MV88F5182_CPU_FREQ_MASK; 117 if (opt == 0) 118 return 333333333; 119 else if (opt == 1 || opt == 2) 120 return 400000000; 121 else if (opt == 3) 122 return 500000000; 123 else 124 return 0; 125 } 126 127 static void __init mv88f5182_get_clk_ratio(void __iomem *sar, int id, 128 int *mult, int *div) 129 { 130 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) & 131 SAR_MV88F5182_CPU_FREQ_MASK; 132 if (opt == 0 || opt == 1) { 133 *mult = 1; 134 *div = 2; 135 } else if (opt == 2 || opt == 3) { 136 *mult = 1; 137 *div = 3; 138 } else { 139 *mult = 0; 140 *div = 1; 141 } 142 } 143 144 static const struct coreclk_soc_desc mv88f5182_coreclks = { 145 .get_tclk_freq = mv88f5182_get_tclk_freq, 146 .get_cpu_freq = mv88f5182_get_cpu_freq, 147 .get_clk_ratio = mv88f5182_get_clk_ratio, 148 .ratios = orion_coreclk_ratios, 149 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 150 }; 151 152 static void __init mv88f5182_clk_init(struct device_node *np) 153 { 154 return mvebu_coreclk_setup(np, &mv88f5182_coreclks); 155 } 156 157 CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init); 158 159 /* 160 * Orion 5281 161 */ 162 163 static u32 __init mv88f5281_get_tclk_freq(void __iomem *sar) 164 { 165 /* On 5281, tclk is always 166 Mhz */ 166 return 166666667; 167 } 168 169 #define SAR_MV88F5281_CPU_FREQ 4 170 #define SAR_MV88F5281_CPU_FREQ_MASK 0xf 171 172 static u32 __init mv88f5281_get_cpu_freq(void __iomem *sar) 173 { 174 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) & 175 SAR_MV88F5281_CPU_FREQ_MASK; 176 if (opt == 1 || opt == 2) 177 return 400000000; 178 else if (opt == 3) 179 return 500000000; 180 else 181 return 0; 182 } 183 184 static void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id, 185 int *mult, int *div) 186 { 187 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) & 188 SAR_MV88F5281_CPU_FREQ_MASK; 189 if (opt == 1) { 190 *mult = 1; 191 *div = 2; 192 } else if (opt == 2 || opt == 3) { 193 *mult = 1; 194 *div = 3; 195 } else { 196 *mult = 0; 197 *div = 1; 198 } 199 } 200 201 static const struct coreclk_soc_desc mv88f5281_coreclks = { 202 .get_tclk_freq = mv88f5281_get_tclk_freq, 203 .get_cpu_freq = mv88f5281_get_cpu_freq, 204 .get_clk_ratio = mv88f5281_get_clk_ratio, 205 .ratios = orion_coreclk_ratios, 206 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 207 }; 208 209 static void __init mv88f5281_clk_init(struct device_node *np) 210 { 211 return mvebu_coreclk_setup(np, &mv88f5281_coreclks); 212 } 213 214 CLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock", mv88f5281_clk_init); 215 216 /* 217 * Orion 6183 218 */ 219 220 #define SAR_MV88F6183_TCLK_FREQ 9 221 #define SAR_MV88F6183_TCLK_FREQ_MASK 0x1 222 223 static u32 __init mv88f6183_get_tclk_freq(void __iomem *sar) 224 { 225 u32 opt = (readl(sar) >> SAR_MV88F6183_TCLK_FREQ) & 226 SAR_MV88F6183_TCLK_FREQ_MASK; 227 if (opt == 0) 228 return 133333333; 229 else if (opt == 1) 230 return 166666667; 231 else 232 return 0; 233 } 234 235 #define SAR_MV88F6183_CPU_FREQ 1 236 #define SAR_MV88F6183_CPU_FREQ_MASK 0x3f 237 238 static u32 __init mv88f6183_get_cpu_freq(void __iomem *sar) 239 { 240 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) & 241 SAR_MV88F6183_CPU_FREQ_MASK; 242 if (opt == 9) 243 return 333333333; 244 else if (opt == 17) 245 return 400000000; 246 else 247 return 0; 248 } 249 250 static void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id, 251 int *mult, int *div) 252 { 253 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) & 254 SAR_MV88F6183_CPU_FREQ_MASK; 255 if (opt == 9 || opt == 17) { 256 *mult = 1; 257 *div = 2; 258 } else { 259 *mult = 0; 260 *div = 1; 261 } 262 } 263 264 static const struct coreclk_soc_desc mv88f6183_coreclks = { 265 .get_tclk_freq = mv88f6183_get_tclk_freq, 266 .get_cpu_freq = mv88f6183_get_cpu_freq, 267 .get_clk_ratio = mv88f6183_get_clk_ratio, 268 .ratios = orion_coreclk_ratios, 269 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 270 }; 271 272 273 static void __init mv88f6183_clk_init(struct device_node *np) 274 { 275 return mvebu_coreclk_setup(np, &mv88f6183_coreclks); 276 } 277 278 CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init); 279