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