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 19static 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 30static 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 45static 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 59static 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 76static 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 84static void __init mv88f5182_clk_init(struct device_node *np) 85{ 86 return mvebu_coreclk_setup(np, &mv88f5182_coreclks); 87} 88 89CLK_OF_DECLARE(mv88f5182_clk, "marvell,mv88f5182-core-clock", mv88f5182_clk_init); 90 91/* 92 * Orion 5281 93 */ 94 95static 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 104static 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 116static 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 133static 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 141static void __init mv88f5281_clk_init(struct device_node *np) 142{ 143 return mvebu_coreclk_setup(np, &mv88f5281_coreclks); 144} 145 146CLK_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 155static 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 170static 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 182static 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 196static 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 205static void __init mv88f6183_clk_init(struct device_node *np) 206{ 207 return mvebu_coreclk_setup(np, &mv88f6183_coreclks); 208} 209 210CLK_OF_DECLARE(mv88f6183_clk, "marvell,mv88f6183-core-clock", mv88f6183_clk_init); 211