1 /* 2 * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms and conditions of the GNU General Public License, 6 * version 2, as published by the Free Software Foundation. 7 * 8 * This program is distributed in the hope it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 11 * more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include <linux/io.h> 18 #include <linux/clk-provider.h> 19 #include <linux/of.h> 20 #include <linux/of_address.h> 21 #include <linux/delay.h> 22 #include <linux/export.h> 23 #include <linux/clk/tegra.h> 24 25 #include "clk.h" 26 #include "clk-id.h" 27 28 #define AUDIO_SYNC_CLK_I2S0 0x4a0 29 #define AUDIO_SYNC_CLK_I2S1 0x4a4 30 #define AUDIO_SYNC_CLK_I2S2 0x4a8 31 #define AUDIO_SYNC_CLK_I2S3 0x4ac 32 #define AUDIO_SYNC_CLK_I2S4 0x4b0 33 #define AUDIO_SYNC_CLK_SPDIF 0x4b4 34 #define AUDIO_SYNC_CLK_DMIC1 0x560 35 #define AUDIO_SYNC_CLK_DMIC2 0x564 36 #define AUDIO_SYNC_CLK_DMIC3 0x6b8 37 38 #define AUDIO_SYNC_DOUBLER 0x49c 39 40 #define PLLA_OUT 0xb4 41 42 struct tegra_sync_source_initdata { 43 char *name; 44 unsigned long rate; 45 unsigned long max_rate; 46 int clk_id; 47 }; 48 49 #define SYNC(_name) \ 50 {\ 51 .name = #_name,\ 52 .rate = 24000000,\ 53 .max_rate = 24000000,\ 54 .clk_id = tegra_clk_ ## _name,\ 55 } 56 57 struct tegra_audio_clk_initdata { 58 char *gate_name; 59 char *mux_name; 60 u32 offset; 61 int gate_clk_id; 62 int mux_clk_id; 63 }; 64 65 #define AUDIO(_name, _offset) \ 66 {\ 67 .gate_name = #_name,\ 68 .mux_name = #_name"_mux",\ 69 .offset = _offset,\ 70 .gate_clk_id = tegra_clk_ ## _name,\ 71 .mux_clk_id = tegra_clk_ ## _name ## _mux,\ 72 } 73 74 struct tegra_audio2x_clk_initdata { 75 char *parent; 76 char *gate_name; 77 char *name_2x; 78 char *div_name; 79 int clk_id; 80 int clk_num; 81 u8 div_offset; 82 }; 83 84 #define AUDIO2X(_name, _num, _offset) \ 85 {\ 86 .parent = #_name,\ 87 .gate_name = #_name"_2x",\ 88 .name_2x = #_name"_doubler",\ 89 .div_name = #_name"_div",\ 90 .clk_id = tegra_clk_ ## _name ## _2x,\ 91 .clk_num = _num,\ 92 .div_offset = _offset,\ 93 } 94 95 static DEFINE_SPINLOCK(clk_doubler_lock); 96 97 static const char * const mux_audio_sync_clk[] = { "spdif_in_sync", 98 "i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", 99 "pll_a_out0", "vimclk_sync", 100 }; 101 102 static const char * const mux_dmic_sync_clk[] = { "unused", "i2s0_sync", 103 "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "pll_a_out0", 104 "vimclk_sync", 105 }; 106 107 static struct tegra_sync_source_initdata sync_source_clks[] __initdata = { 108 SYNC(spdif_in_sync), 109 SYNC(i2s0_sync), 110 SYNC(i2s1_sync), 111 SYNC(i2s2_sync), 112 SYNC(i2s3_sync), 113 SYNC(i2s4_sync), 114 SYNC(vimclk_sync), 115 }; 116 117 static struct tegra_audio_clk_initdata audio_clks[] = { 118 AUDIO(audio0, AUDIO_SYNC_CLK_I2S0), 119 AUDIO(audio1, AUDIO_SYNC_CLK_I2S1), 120 AUDIO(audio2, AUDIO_SYNC_CLK_I2S2), 121 AUDIO(audio3, AUDIO_SYNC_CLK_I2S3), 122 AUDIO(audio4, AUDIO_SYNC_CLK_I2S4), 123 AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF), 124 }; 125 126 static struct tegra_audio_clk_initdata dmic_clks[] = { 127 AUDIO(dmic1_sync_clk, AUDIO_SYNC_CLK_DMIC1), 128 AUDIO(dmic2_sync_clk, AUDIO_SYNC_CLK_DMIC2), 129 AUDIO(dmic3_sync_clk, AUDIO_SYNC_CLK_DMIC3), 130 }; 131 132 static struct tegra_audio2x_clk_initdata audio2x_clks[] = { 133 AUDIO2X(audio0, 113, 24), 134 AUDIO2X(audio1, 114, 25), 135 AUDIO2X(audio2, 115, 26), 136 AUDIO2X(audio3, 116, 27), 137 AUDIO2X(audio4, 117, 28), 138 AUDIO2X(spdif, 118, 29), 139 }; 140 141 static void __init tegra_audio_sync_clk_init(void __iomem *clk_base, 142 struct tegra_clk *tegra_clks, 143 struct tegra_audio_clk_initdata *sync, 144 int num_sync_clks, 145 const char * const *mux_names, 146 int num_mux_inputs) 147 { 148 struct clk *clk; 149 struct clk **dt_clk; 150 struct tegra_audio_clk_initdata *data; 151 int i; 152 153 for (i = 0, data = sync; i < num_sync_clks; i++, data++) { 154 dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks); 155 if (!dt_clk) 156 continue; 157 158 clk = clk_register_mux(NULL, data->mux_name, mux_names, 159 num_mux_inputs, 160 CLK_SET_RATE_NO_REPARENT, 161 clk_base + data->offset, 0, 3, 0, 162 NULL); 163 *dt_clk = clk; 164 165 dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks); 166 if (!dt_clk) 167 continue; 168 169 clk = clk_register_gate(NULL, data->gate_name, data->mux_name, 170 0, clk_base + data->offset, 4, 171 CLK_GATE_SET_TO_DISABLE, NULL); 172 *dt_clk = clk; 173 } 174 } 175 176 void __init tegra_audio_clk_init(void __iomem *clk_base, 177 void __iomem *pmc_base, struct tegra_clk *tegra_clks, 178 struct tegra_audio_clk_info *audio_info, 179 unsigned int num_plls) 180 { 181 struct clk *clk; 182 struct clk **dt_clk; 183 int i; 184 185 if (!audio_info || num_plls < 1) { 186 pr_err("No audio data passed to tegra_audio_clk_init\n"); 187 WARN_ON(1); 188 return; 189 } 190 191 for (i = 0; i < num_plls; i++) { 192 struct tegra_audio_clk_info *info = &audio_info[i]; 193 194 dt_clk = tegra_lookup_dt_id(info->clk_id, tegra_clks); 195 if (dt_clk) { 196 clk = tegra_clk_register_pll(info->name, info->parent, 197 clk_base, pmc_base, 0, info->pll_params, 198 NULL); 199 *dt_clk = clk; 200 } 201 } 202 203 /* PLLA_OUT0 */ 204 dt_clk = tegra_lookup_dt_id(tegra_clk_pll_a_out0, tegra_clks); 205 if (dt_clk) { 206 clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", 207 clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, 208 8, 8, 1, NULL); 209 clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", 210 clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | 211 CLK_SET_RATE_PARENT, 0, NULL); 212 *dt_clk = clk; 213 } 214 215 for (i = 0; i < ARRAY_SIZE(sync_source_clks); i++) { 216 struct tegra_sync_source_initdata *data; 217 218 data = &sync_source_clks[i]; 219 220 dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); 221 if (!dt_clk) 222 continue; 223 224 clk = tegra_clk_register_sync_source(data->name, 225 data->rate, data->max_rate); 226 *dt_clk = clk; 227 } 228 229 tegra_audio_sync_clk_init(clk_base, tegra_clks, audio_clks, 230 ARRAY_SIZE(audio_clks), mux_audio_sync_clk, 231 ARRAY_SIZE(mux_audio_sync_clk)); 232 233 /* make sure the DMIC sync clocks have a valid parent */ 234 for (i = 0; i < ARRAY_SIZE(dmic_clks); i++) 235 writel_relaxed(1, clk_base + dmic_clks[i].offset); 236 237 tegra_audio_sync_clk_init(clk_base, tegra_clks, dmic_clks, 238 ARRAY_SIZE(dmic_clks), mux_dmic_sync_clk, 239 ARRAY_SIZE(mux_dmic_sync_clk)); 240 241 for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) { 242 struct tegra_audio2x_clk_initdata *data; 243 244 data = &audio2x_clks[i]; 245 dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks); 246 if (!dt_clk) 247 continue; 248 249 clk = clk_register_fixed_factor(NULL, data->name_2x, 250 data->parent, CLK_SET_RATE_PARENT, 2, 1); 251 clk = tegra_clk_register_divider(data->div_name, 252 data->name_2x, clk_base + AUDIO_SYNC_DOUBLER, 253 0, 0, data->div_offset, 1, 0, 254 &clk_doubler_lock); 255 clk = tegra_clk_register_periph_gate(data->gate_name, 256 data->div_name, TEGRA_PERIPH_NO_RESET, 257 clk_base, CLK_SET_RATE_PARENT, data->clk_num, 258 periph_clk_enb_refcnt); 259 *dt_clk = clk; 260 } 261 } 262 263