0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/kernel.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/io.h>
0016 #include <linux/of.h>
0017 #include "common.h"
0018 #include "dove-divider.h"
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 #define SAR_DOVE_CPU_FREQ 5
0066 #define SAR_DOVE_CPU_FREQ_MASK 0xf
0067 #define SAR_DOVE_L2_RATIO 9
0068 #define SAR_DOVE_L2_RATIO_MASK 0x7
0069 #define SAR_DOVE_DDR_RATIO 12
0070 #define SAR_DOVE_DDR_RATIO_MASK 0xf
0071 #define SAR_DOVE_TCLK_FREQ 23
0072 #define SAR_DOVE_TCLK_FREQ_MASK 0x3
0073
0074 enum { DOVE_CPU_TO_L2, DOVE_CPU_TO_DDR };
0075
0076 static const struct coreclk_ratio dove_coreclk_ratios[] __initconst = {
0077 { .id = DOVE_CPU_TO_L2, .name = "l2clk", },
0078 { .id = DOVE_CPU_TO_DDR, .name = "ddrclk", }
0079 };
0080
0081 static const u32 dove_tclk_freqs[] __initconst = {
0082 166666667,
0083 125000000,
0084 0, 0
0085 };
0086
0087 static u32 __init dove_get_tclk_freq(void __iomem *sar)
0088 {
0089 u32 opt = (readl(sar) >> SAR_DOVE_TCLK_FREQ) &
0090 SAR_DOVE_TCLK_FREQ_MASK;
0091 return dove_tclk_freqs[opt];
0092 }
0093
0094 static const u32 dove_cpu_freqs[] __initconst = {
0095 0, 0, 0, 0, 0,
0096 1000000000,
0097 933333333, 933333333,
0098 800000000, 800000000, 800000000,
0099 1066666667,
0100 666666667,
0101 533333333,
0102 400000000,
0103 333333333
0104 };
0105
0106 static u32 __init dove_get_cpu_freq(void __iomem *sar)
0107 {
0108 u32 opt = (readl(sar) >> SAR_DOVE_CPU_FREQ) &
0109 SAR_DOVE_CPU_FREQ_MASK;
0110 return dove_cpu_freqs[opt];
0111 }
0112
0113 static const int dove_cpu_l2_ratios[8][2] __initconst = {
0114 { 1, 1 }, { 0, 1 }, { 1, 2 }, { 0, 1 },
0115 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 }
0116 };
0117
0118 static const int dove_cpu_ddr_ratios[16][2] __initconst = {
0119 { 1, 1 }, { 0, 1 }, { 1, 2 }, { 2, 5 },
0120 { 1, 3 }, { 0, 1 }, { 1, 4 }, { 0, 1 },
0121 { 1, 5 }, { 0, 1 }, { 1, 6 }, { 0, 1 },
0122 { 1, 7 }, { 0, 1 }, { 1, 8 }, { 1, 10 }
0123 };
0124
0125 static void __init dove_get_clk_ratio(
0126 void __iomem *sar, int id, int *mult, int *div)
0127 {
0128 switch (id) {
0129 case DOVE_CPU_TO_L2:
0130 {
0131 u32 opt = (readl(sar) >> SAR_DOVE_L2_RATIO) &
0132 SAR_DOVE_L2_RATIO_MASK;
0133 *mult = dove_cpu_l2_ratios[opt][0];
0134 *div = dove_cpu_l2_ratios[opt][1];
0135 break;
0136 }
0137 case DOVE_CPU_TO_DDR:
0138 {
0139 u32 opt = (readl(sar) >> SAR_DOVE_DDR_RATIO) &
0140 SAR_DOVE_DDR_RATIO_MASK;
0141 *mult = dove_cpu_ddr_ratios[opt][0];
0142 *div = dove_cpu_ddr_ratios[opt][1];
0143 break;
0144 }
0145 }
0146 }
0147
0148 static const struct coreclk_soc_desc dove_coreclks = {
0149 .get_tclk_freq = dove_get_tclk_freq,
0150 .get_cpu_freq = dove_get_cpu_freq,
0151 .get_clk_ratio = dove_get_clk_ratio,
0152 .ratios = dove_coreclk_ratios,
0153 .num_ratios = ARRAY_SIZE(dove_coreclk_ratios),
0154 };
0155
0156
0157
0158
0159
0160 static const struct clk_gating_soc_desc dove_gating_desc[] __initconst = {
0161 { "usb0", NULL, 0, 0 },
0162 { "usb1", NULL, 1, 0 },
0163 { "ge", "gephy", 2, 0 },
0164 { "sata", NULL, 3, 0 },
0165 { "pex0", NULL, 4, 0 },
0166 { "pex1", NULL, 5, 0 },
0167 { "sdio0", NULL, 8, 0 },
0168 { "sdio1", NULL, 9, 0 },
0169 { "nand", NULL, 10, 0 },
0170 { "camera", NULL, 11, 0 },
0171 { "i2s0", NULL, 12, 0 },
0172 { "i2s1", NULL, 13, 0 },
0173 { "crypto", NULL, 15, 0 },
0174 { "ac97", NULL, 21, 0 },
0175 { "pdma", NULL, 22, 0 },
0176 { "xor0", NULL, 23, 0 },
0177 { "xor1", NULL, 24, 0 },
0178 { "gephy", NULL, 30, 0 },
0179 { }
0180 };
0181
0182 static void __init dove_clk_init(struct device_node *np)
0183 {
0184 struct device_node *cgnp =
0185 of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
0186 struct device_node *ddnp =
0187 of_find_compatible_node(NULL, NULL, "marvell,dove-divider-clock");
0188
0189 mvebu_coreclk_setup(np, &dove_coreclks);
0190
0191 if (ddnp) {
0192 dove_divider_clk_init(ddnp);
0193 of_node_put(ddnp);
0194 }
0195
0196 if (cgnp) {
0197 mvebu_clk_gating_setup(cgnp, dove_gating_desc);
0198 of_node_put(cgnp);
0199 }
0200 }
0201 CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init);