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 5182 25 */ 26 27 #define SAR_MV88F5182_TCLK_FREQ 8 28 #define SAR_MV88F5182_TCLK_FREQ_MASK 0x3 29 30 static u32 __init mv88f5182_get_tclk_freq(void __iomem *sar) 31 { 32 u32 opt = (readl(sar) >> SAR_MV88F5182_TCLK_FREQ) & 33 SAR_MV88F5182_TCLK_FREQ_MASK; 34 if (opt == 1) 35 return 150000000; 36 else if (opt == 2) 37 return 166666667; 38 else 39 return 0; 40 } 41 42 #define SAR_MV88F5182_CPU_FREQ 4 43 #define SAR_MV88F5182_CPU_FREQ_MASK 0xf 44 45 static u32 __init mv88f5182_get_cpu_freq(void __iomem *sar) 46 { 47 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) & 48 SAR_MV88F5182_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 mv88f5182_get_clk_ratio(void __iomem *sar, int id, 60 int *mult, int *div) 61 { 62 u32 opt = (readl(sar) >> SAR_MV88F5182_CPU_FREQ) & 63 SAR_MV88F5182_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 mv88f5182_coreclks = { 77 .get_tclk_freq = mv88f5182_get_tclk_freq, 78 .get_cpu_freq = mv88f5182_get_cpu_freq, 79 .get_clk_ratio = mv88f5182_get_clk_ratio, 80 .ratios = orion_coreclk_ratios, 81 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 82 }; 83 84 static void __init mv88f5182_clk_init(struct device_node *np) 85 { 86 return mvebu_coreclk_setup(np, &mv88f5182_coreclks); 87 } 88 89 CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init); 90 91 /* 92 * Orion 5281 93 */ 94 95 static u32 __init mv88f5281_get_tclk_freq(void __iomem *sar) 96 { 97 /* On 5281, tclk is always 166 Mhz */ 98 return 166666667; 99 } 100 101 #define SAR_MV88F5281_CPU_FREQ 4 102 #define SAR_MV88F5281_CPU_FREQ_MASK 0xf 103 104 static u32 __init mv88f5281_get_cpu_freq(void __iomem *sar) 105 { 106 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) & 107 SAR_MV88F5281_CPU_FREQ_MASK; 108 if (opt == 1 || opt == 2) 109 return 400000000; 110 else if (opt == 3) 111 return 500000000; 112 else 113 return 0; 114 } 115 116 static void __init mv88f5281_get_clk_ratio(void __iomem *sar, int id, 117 int *mult, int *div) 118 { 119 u32 opt = (readl(sar) >> SAR_MV88F5281_CPU_FREQ) & 120 SAR_MV88F5281_CPU_FREQ_MASK; 121 if (opt == 1) { 122 *mult = 1; 123 *div = 2; 124 } else if (opt == 2 || opt == 3) { 125 *mult = 1; 126 *div = 3; 127 } else { 128 *mult = 0; 129 *div = 1; 130 } 131 } 132 133 static const struct coreclk_soc_desc mv88f5281_coreclks = { 134 .get_tclk_freq = mv88f5281_get_tclk_freq, 135 .get_cpu_freq = mv88f5281_get_cpu_freq, 136 .get_clk_ratio = mv88f5281_get_clk_ratio, 137 .ratios = orion_coreclk_ratios, 138 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 139 }; 140 141 static void __init mv88f5281_clk_init(struct device_node *np) 142 { 143 return mvebu_coreclk_setup(np, &mv88f5281_coreclks); 144 } 145 146 CLK_OF_DECLARE(mv88f5281_clk, "marvell,mv88f5281-core-clock", mv88f5281_clk_init); 147 148 /* 149 * Orion 6183 150 */ 151 152 #define SAR_MV88F6183_TCLK_FREQ 9 153 #define SAR_MV88F6183_TCLK_FREQ_MASK 0x1 154 155 static u32 __init mv88f6183_get_tclk_freq(void __iomem *sar) 156 { 157 u32 opt = (readl(sar) >> SAR_MV88F6183_TCLK_FREQ) & 158 SAR_MV88F6183_TCLK_FREQ_MASK; 159 if (opt == 0) 160 return 133333333; 161 else if (opt == 1) 162 return 166666667; 163 else 164 return 0; 165 } 166 167 #define SAR_MV88F6183_CPU_FREQ 1 168 #define SAR_MV88F6183_CPU_FREQ_MASK 0x3f 169 170 static u32 __init mv88f6183_get_cpu_freq(void __iomem *sar) 171 { 172 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) & 173 SAR_MV88F6183_CPU_FREQ_MASK; 174 if (opt == 9) 175 return 333333333; 176 else if (opt == 17) 177 return 400000000; 178 else 179 return 0; 180 } 181 182 static void __init mv88f6183_get_clk_ratio(void __iomem *sar, int id, 183 int *mult, int *div) 184 { 185 u32 opt = (readl(sar) >> SAR_MV88F6183_CPU_FREQ) & 186 SAR_MV88F6183_CPU_FREQ_MASK; 187 if (opt == 9 || opt == 17) { 188 *mult = 1; 189 *div = 2; 190 } else { 191 *mult = 0; 192 *div = 1; 193 } 194 } 195 196 static const struct coreclk_soc_desc mv88f6183_coreclks = { 197 .get_tclk_freq = mv88f6183_get_tclk_freq, 198 .get_cpu_freq = mv88f6183_get_cpu_freq, 199 .get_clk_ratio = mv88f6183_get_clk_ratio, 200 .ratios = orion_coreclk_ratios, 201 .num_ratios = ARRAY_SIZE(orion_coreclk_ratios), 202 }; 203 204 205 static void __init mv88f6183_clk_init(struct device_node *np) 206 { 207 return mvebu_coreclk_setup(np, &mv88f6183_coreclks); 208 } 209 210 CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init); 211