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