1 /* 2 * Marvell Armada 375 SoC clocks 3 * 4 * Copyright (C) 2014 Marvell 5 * 6 * Gregory CLEMENT <gregory.clement@free-electrons.com> 7 * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 8 * Andrew Lunn <andrew@lunn.ch> 9 * 10 * This file is licensed under the terms of the GNU General Public 11 * License version 2. This program is licensed "as is" without any 12 * warranty of any kind, whether express or implied. 13 */ 14 15 #include <linux/kernel.h> 16 #include <linux/clk-provider.h> 17 #include <linux/io.h> 18 #include <linux/of.h> 19 #include "common.h" 20 21 /* 22 * Core Clocks 23 */ 24 25 /* 26 * For the Armada 375 SoCs, the CPU, DDR and L2 clocks frequencies are 27 * all modified at the same time, and not separately as for the Armada 28 * 370 or the Armada XP SoCs. 29 * 30 * SAR1[21:17] : CPU frequency DDR frequency L2 frequency 31 * 6 = 400 MHz 400 MHz 200 MHz 32 * 15 = 600 MHz 600 MHz 300 MHz 33 * 21 = 800 MHz 534 MHz 400 MHz 34 * 25 = 1000 MHz 500 MHz 500 MHz 35 * others reserved. 36 * 37 * SAR1[22] : TCLK frequency 38 * 0 = 166 MHz 39 * 1 = 200 MHz 40 */ 41 42 #define SAR1_A375_TCLK_FREQ_OPT 22 43 #define SAR1_A375_TCLK_FREQ_OPT_MASK 0x1 44 #define SAR1_A375_CPU_DDR_L2_FREQ_OPT 17 45 #define SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK 0x1F 46 47 static const u32 armada_375_tclk_frequencies[] __initconst = { 48 166000000, 49 200000000, 50 }; 51 52 static u32 __init armada_375_get_tclk_freq(void __iomem *sar) 53 { 54 u8 tclk_freq_select; 55 56 tclk_freq_select = ((readl(sar) >> SAR1_A375_TCLK_FREQ_OPT) & 57 SAR1_A375_TCLK_FREQ_OPT_MASK); 58 return armada_375_tclk_frequencies[tclk_freq_select]; 59 } 60 61 62 static const u32 armada_375_cpu_frequencies[] __initconst = { 63 0, 0, 0, 0, 0, 0, 64 400000000, 65 0, 0, 0, 0, 0, 0, 0, 0, 66 600000000, 67 0, 0, 0, 0, 0, 68 800000000, 69 0, 0, 0, 70 1000000000, 71 }; 72 73 static u32 __init armada_375_get_cpu_freq(void __iomem *sar) 74 { 75 u8 cpu_freq_select; 76 77 cpu_freq_select = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & 78 SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); 79 if (cpu_freq_select >= ARRAY_SIZE(armada_375_cpu_frequencies)) { 80 pr_err("Selected CPU frequency (%d) unsupported\n", 81 cpu_freq_select); 82 return 0; 83 } else 84 return armada_375_cpu_frequencies[cpu_freq_select]; 85 } 86 87 enum { A375_CPU_TO_DDR, A375_CPU_TO_L2 }; 88 89 static const struct coreclk_ratio armada_375_coreclk_ratios[] __initconst = { 90 { .id = A375_CPU_TO_L2, .name = "l2clk" }, 91 { .id = A375_CPU_TO_DDR, .name = "ddrclk" }, 92 }; 93 94 static const int armada_375_cpu_l2_ratios[32][2] __initconst = { 95 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 96 {0, 1}, {0, 1}, {1, 2}, {0, 1}, 97 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 98 {0, 1}, {0, 1}, {0, 1}, {1, 2}, 99 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 100 {0, 1}, {1, 2}, {0, 1}, {0, 1}, 101 {0, 1}, {1, 2}, {0, 1}, {0, 1}, 102 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 103 }; 104 105 static const int armada_375_cpu_ddr_ratios[32][2] __initconst = { 106 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 107 {0, 1}, {0, 1}, {1, 1}, {0, 1}, 108 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 109 {0, 1}, {0, 1}, {0, 1}, {2, 3}, 110 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 111 {0, 1}, {2, 3}, {0, 1}, {0, 1}, 112 {0, 1}, {1, 2}, {0, 1}, {0, 1}, 113 {0, 1}, {0, 1}, {0, 1}, {0, 1}, 114 }; 115 116 static void __init armada_375_get_clk_ratio( 117 void __iomem *sar, int id, int *mult, int *div) 118 { 119 u32 opt = ((readl(sar) >> SAR1_A375_CPU_DDR_L2_FREQ_OPT) & 120 SAR1_A375_CPU_DDR_L2_FREQ_OPT_MASK); 121 122 switch (id) { 123 case A375_CPU_TO_L2: 124 *mult = armada_375_cpu_l2_ratios[opt][0]; 125 *div = armada_375_cpu_l2_ratios[opt][1]; 126 break; 127 case A375_CPU_TO_DDR: 128 *mult = armada_375_cpu_ddr_ratios[opt][0]; 129 *div = armada_375_cpu_ddr_ratios[opt][1]; 130 break; 131 } 132 } 133 134 static const struct coreclk_soc_desc armada_375_coreclks = { 135 .get_tclk_freq = armada_375_get_tclk_freq, 136 .get_cpu_freq = armada_375_get_cpu_freq, 137 .get_clk_ratio = armada_375_get_clk_ratio, 138 .ratios = armada_375_coreclk_ratios, 139 .num_ratios = ARRAY_SIZE(armada_375_coreclk_ratios), 140 }; 141 142 static void __init armada_375_coreclk_init(struct device_node *np) 143 { 144 mvebu_coreclk_setup(np, &armada_375_coreclks); 145 } 146 CLK_OF_DECLARE(armada_375_core_clk, "marvell,armada-375-core-clock", 147 armada_375_coreclk_init); 148 149 /* 150 * Clock Gating Control 151 */ 152 static const struct clk_gating_soc_desc armada_375_gating_desc[] __initconst = { 153 { "mu", NULL, 2 }, 154 { "pp", NULL, 3 }, 155 { "ptp", NULL, 4 }, 156 { "pex0", NULL, 5 }, 157 { "pex1", NULL, 6 }, 158 { "audio", NULL, 8 }, 159 { "nd_clk", "nand", 11 }, 160 { "sata0_link", "sata0_core", 14 }, 161 { "sata0_core", NULL, 15 }, 162 { "usb3", NULL, 16 }, 163 { "sdio", NULL, 17 }, 164 { "usb", NULL, 18 }, 165 { "gop", NULL, 19 }, 166 { "sata1_link", "sata1_core", 20 }, 167 { "sata1_core", NULL, 21 }, 168 { "xor0", NULL, 22 }, 169 { "xor1", NULL, 23 }, 170 { "copro", NULL, 24 }, 171 { "tdm", NULL, 25 }, 172 { "crypto0_enc", NULL, 28 }, 173 { "crypto0_core", NULL, 29 }, 174 { "crypto1_enc", NULL, 30 }, 175 { "crypto1_core", NULL, 31 }, 176 { } 177 }; 178 179 static void __init armada_375_clk_gating_init(struct device_node *np) 180 { 181 mvebu_clk_gating_setup(np, armada_375_gating_desc); 182 } 183 CLK_OF_DECLARE(armada_375_clk_gating, "marvell,armada-375-gating-clock", 184 armada_375_clk_gating_init); 185