1*c087a94bSLad Prabhakar // SPDX-License-Identifier: GPL-2.0 2*c087a94bSLad Prabhakar // 3*c087a94bSLad Prabhakar // Helper routines for R-Car sound ADG. 4*c087a94bSLad Prabhakar // 5*c087a94bSLad Prabhakar // Copyright (C) 2013 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> 6*c087a94bSLad Prabhakar #include <linux/clk-provider.h> 7*c087a94bSLad Prabhakar #include <linux/clkdev.h> 8*c087a94bSLad Prabhakar #include "rsnd.h" 9*c087a94bSLad Prabhakar 10*c087a94bSLad Prabhakar #define CLKA 0 11*c087a94bSLad Prabhakar #define CLKB 1 12*c087a94bSLad Prabhakar #define CLKC 2 13*c087a94bSLad Prabhakar #define CLKI 3 14*c087a94bSLad Prabhakar #define CLKINMAX 4 15*c087a94bSLad Prabhakar 16*c087a94bSLad Prabhakar #define CLKOUT 0 17*c087a94bSLad Prabhakar #define CLKOUT1 1 18*c087a94bSLad Prabhakar #define CLKOUT2 2 19*c087a94bSLad Prabhakar #define CLKOUT3 3 20*c087a94bSLad Prabhakar #define CLKOUTMAX 4 21*c087a94bSLad Prabhakar 22*c087a94bSLad Prabhakar #define BRRx_MASK(x) (0x3FF & x) 23*c087a94bSLad Prabhakar 24*c087a94bSLad Prabhakar static struct rsnd_mod_ops adg_ops = { 25*c087a94bSLad Prabhakar .name = "adg", 26*c087a94bSLad Prabhakar }; 27*c087a94bSLad Prabhakar 28*c087a94bSLad Prabhakar #define ADG_HZ_441 0 29*c087a94bSLad Prabhakar #define ADG_HZ_48 1 30*c087a94bSLad Prabhakar #define ADG_HZ_SIZE 2 31*c087a94bSLad Prabhakar 32*c087a94bSLad Prabhakar struct rsnd_adg { 33*c087a94bSLad Prabhakar struct clk *clkin[CLKINMAX]; 34*c087a94bSLad Prabhakar struct clk *clkout[CLKOUTMAX]; 35*c087a94bSLad Prabhakar struct clk *null_clk; 36*c087a94bSLad Prabhakar struct clk_onecell_data onecell; 37*c087a94bSLad Prabhakar struct rsnd_mod mod; 38*c087a94bSLad Prabhakar int clkin_rate[CLKINMAX]; 39*c087a94bSLad Prabhakar int clkin_size; 40*c087a94bSLad Prabhakar int clkout_size; 41*c087a94bSLad Prabhakar u32 ckr; 42*c087a94bSLad Prabhakar u32 brga; 43*c087a94bSLad Prabhakar u32 brgb; 44*c087a94bSLad Prabhakar 45*c087a94bSLad Prabhakar int brg_rate[ADG_HZ_SIZE]; /* BRGA / BRGB */ 46*c087a94bSLad Prabhakar }; 47*c087a94bSLad Prabhakar 48*c087a94bSLad Prabhakar #define for_each_rsnd_clkin(pos, adg, i) \ 49*c087a94bSLad Prabhakar for (i = 0; \ 50*c087a94bSLad Prabhakar (i < adg->clkin_size) && \ 51*c087a94bSLad Prabhakar ((pos) = adg->clkin[i]); \ 52*c087a94bSLad Prabhakar i++) 53*c087a94bSLad Prabhakar #define for_each_rsnd_clkout(pos, adg, i) \ 54*c087a94bSLad Prabhakar for (i = 0; \ 55*c087a94bSLad Prabhakar (i < adg->clkout_size) && \ 56*c087a94bSLad Prabhakar ((pos) = adg->clkout[i]); \ 57*c087a94bSLad Prabhakar i++) 58*c087a94bSLad Prabhakar #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) 59*c087a94bSLad Prabhakar 60*c087a94bSLad Prabhakar static const char * const clkin_name_gen4[] = { 61*c087a94bSLad Prabhakar [CLKA] = "clkin", 62*c087a94bSLad Prabhakar }; 63*c087a94bSLad Prabhakar 64*c087a94bSLad Prabhakar static const char * const clkin_name_gen2[] = { 65*c087a94bSLad Prabhakar [CLKA] = "clk_a", 66*c087a94bSLad Prabhakar [CLKB] = "clk_b", 67*c087a94bSLad Prabhakar [CLKC] = "clk_c", 68*c087a94bSLad Prabhakar [CLKI] = "clk_i", 69*c087a94bSLad Prabhakar }; 70*c087a94bSLad Prabhakar 71*c087a94bSLad Prabhakar static const char * const clkout_name_gen2[] = { 72*c087a94bSLad Prabhakar [CLKOUT] = "audio_clkout", 73*c087a94bSLad Prabhakar [CLKOUT1] = "audio_clkout1", 74*c087a94bSLad Prabhakar [CLKOUT2] = "audio_clkout2", 75*c087a94bSLad Prabhakar [CLKOUT3] = "audio_clkout3", 76*c087a94bSLad Prabhakar }; 77*c087a94bSLad Prabhakar 78*c087a94bSLad Prabhakar static u32 rsnd_adg_calculate_brgx(unsigned long div) 79*c087a94bSLad Prabhakar { 80*c087a94bSLad Prabhakar int i; 81*c087a94bSLad Prabhakar 82*c087a94bSLad Prabhakar if (!div) 83*c087a94bSLad Prabhakar return 0; 84*c087a94bSLad Prabhakar 85*c087a94bSLad Prabhakar for (i = 3; i >= 0; i--) { 86*c087a94bSLad Prabhakar int ratio = 2 << (i * 2); 87*c087a94bSLad Prabhakar if (0 == (div % ratio)) 88*c087a94bSLad Prabhakar return (u32)((i << 8) | ((div / ratio) - 1)); 89*c087a94bSLad Prabhakar } 90*c087a94bSLad Prabhakar 91*c087a94bSLad Prabhakar return ~0; 92*c087a94bSLad Prabhakar } 93*c087a94bSLad Prabhakar 94*c087a94bSLad Prabhakar static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io) 95*c087a94bSLad Prabhakar { 96*c087a94bSLad Prabhakar struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); 97*c087a94bSLad Prabhakar int id = rsnd_mod_id(ssi_mod); 98*c087a94bSLad Prabhakar int ws = id; 99*c087a94bSLad Prabhakar 100*c087a94bSLad Prabhakar if (rsnd_ssi_is_pin_sharing(io)) { 101*c087a94bSLad Prabhakar switch (id) { 102*c087a94bSLad Prabhakar case 1: 103*c087a94bSLad Prabhakar case 2: 104*c087a94bSLad Prabhakar case 9: 105*c087a94bSLad Prabhakar ws = 0; 106*c087a94bSLad Prabhakar break; 107*c087a94bSLad Prabhakar case 4: 108*c087a94bSLad Prabhakar ws = 3; 109*c087a94bSLad Prabhakar break; 110*c087a94bSLad Prabhakar case 8: 111*c087a94bSLad Prabhakar ws = 7; 112*c087a94bSLad Prabhakar break; 113*c087a94bSLad Prabhakar } 114*c087a94bSLad Prabhakar } else { 115*c087a94bSLad Prabhakar /* 116*c087a94bSLad Prabhakar * SSI8 is not connected to ADG. 117*c087a94bSLad Prabhakar * Thus SSI9 is using ws = 8 118*c087a94bSLad Prabhakar */ 119*c087a94bSLad Prabhakar if (id == 9) 120*c087a94bSLad Prabhakar ws = 8; 121*c087a94bSLad Prabhakar } 122*c087a94bSLad Prabhakar 123*c087a94bSLad Prabhakar return (0x6 + ws) << 8; 124*c087a94bSLad Prabhakar } 125*c087a94bSLad Prabhakar 126*c087a94bSLad Prabhakar static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, 127*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 128*c087a94bSLad Prabhakar unsigned int target_rate, 129*c087a94bSLad Prabhakar unsigned int *target_val, 130*c087a94bSLad Prabhakar unsigned int *target_en) 131*c087a94bSLad Prabhakar { 132*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 133*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 134*c087a94bSLad Prabhakar int sel; 135*c087a94bSLad Prabhakar unsigned int val, en; 136*c087a94bSLad Prabhakar unsigned int min, diff; 137*c087a94bSLad Prabhakar unsigned int sel_rate[] = { 138*c087a94bSLad Prabhakar adg->clkin_rate[CLKA], /* 0000: CLKA */ 139*c087a94bSLad Prabhakar adg->clkin_rate[CLKB], /* 0001: CLKB */ 140*c087a94bSLad Prabhakar adg->clkin_rate[CLKC], /* 0010: CLKC */ 141*c087a94bSLad Prabhakar adg->brg_rate[ADG_HZ_441], /* 0011: BRGA */ 142*c087a94bSLad Prabhakar adg->brg_rate[ADG_HZ_48], /* 0100: BRGB */ 143*c087a94bSLad Prabhakar }; 144*c087a94bSLad Prabhakar 145*c087a94bSLad Prabhakar min = ~0; 146*c087a94bSLad Prabhakar val = 0; 147*c087a94bSLad Prabhakar en = 0; 148*c087a94bSLad Prabhakar for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { 149*c087a94bSLad Prabhakar int idx = 0; 150*c087a94bSLad Prabhakar int step = 2; 151*c087a94bSLad Prabhakar int div; 152*c087a94bSLad Prabhakar 153*c087a94bSLad Prabhakar if (!sel_rate[sel]) 154*c087a94bSLad Prabhakar continue; 155*c087a94bSLad Prabhakar 156*c087a94bSLad Prabhakar for (div = 2; div <= 98304; div += step) { 157*c087a94bSLad Prabhakar diff = abs(target_rate - sel_rate[sel] / div); 158*c087a94bSLad Prabhakar if (min > diff) { 159*c087a94bSLad Prabhakar val = (sel << 8) | idx; 160*c087a94bSLad Prabhakar min = diff; 161*c087a94bSLad Prabhakar en = 1 << (sel + 1); /* fixme */ 162*c087a94bSLad Prabhakar } 163*c087a94bSLad Prabhakar 164*c087a94bSLad Prabhakar /* 165*c087a94bSLad Prabhakar * step of 0_0000 / 0_0001 / 0_1101 166*c087a94bSLad Prabhakar * are out of order 167*c087a94bSLad Prabhakar */ 168*c087a94bSLad Prabhakar if ((idx > 2) && (idx % 2)) 169*c087a94bSLad Prabhakar step *= 2; 170*c087a94bSLad Prabhakar if (idx == 0x1c) { 171*c087a94bSLad Prabhakar div += step; 172*c087a94bSLad Prabhakar step *= 2; 173*c087a94bSLad Prabhakar } 174*c087a94bSLad Prabhakar idx++; 175*c087a94bSLad Prabhakar } 176*c087a94bSLad Prabhakar } 177*c087a94bSLad Prabhakar 178*c087a94bSLad Prabhakar if (min == ~0) { 179*c087a94bSLad Prabhakar dev_err(dev, "no Input clock\n"); 180*c087a94bSLad Prabhakar return; 181*c087a94bSLad Prabhakar } 182*c087a94bSLad Prabhakar 183*c087a94bSLad Prabhakar *target_val = val; 184*c087a94bSLad Prabhakar if (target_en) 185*c087a94bSLad Prabhakar *target_en = en; 186*c087a94bSLad Prabhakar } 187*c087a94bSLad Prabhakar 188*c087a94bSLad Prabhakar static void rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, 189*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 190*c087a94bSLad Prabhakar unsigned int in_rate, 191*c087a94bSLad Prabhakar unsigned int out_rate, 192*c087a94bSLad Prabhakar u32 *in, u32 *out, u32 *en) 193*c087a94bSLad Prabhakar { 194*c087a94bSLad Prabhakar struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); 195*c087a94bSLad Prabhakar unsigned int target_rate; 196*c087a94bSLad Prabhakar u32 *target_val; 197*c087a94bSLad Prabhakar u32 _in; 198*c087a94bSLad Prabhakar u32 _out; 199*c087a94bSLad Prabhakar u32 _en; 200*c087a94bSLad Prabhakar 201*c087a94bSLad Prabhakar /* default = SSI WS */ 202*c087a94bSLad Prabhakar _in = 203*c087a94bSLad Prabhakar _out = rsnd_adg_ssi_ws_timing_gen2(io); 204*c087a94bSLad Prabhakar 205*c087a94bSLad Prabhakar target_rate = 0; 206*c087a94bSLad Prabhakar target_val = NULL; 207*c087a94bSLad Prabhakar _en = 0; 208*c087a94bSLad Prabhakar if (runtime->rate != in_rate) { 209*c087a94bSLad Prabhakar target_rate = out_rate; 210*c087a94bSLad Prabhakar target_val = &_out; 211*c087a94bSLad Prabhakar } else if (runtime->rate != out_rate) { 212*c087a94bSLad Prabhakar target_rate = in_rate; 213*c087a94bSLad Prabhakar target_val = &_in; 214*c087a94bSLad Prabhakar } 215*c087a94bSLad Prabhakar 216*c087a94bSLad Prabhakar if (target_rate) 217*c087a94bSLad Prabhakar __rsnd_adg_get_timesel_ratio(priv, io, 218*c087a94bSLad Prabhakar target_rate, 219*c087a94bSLad Prabhakar target_val, &_en); 220*c087a94bSLad Prabhakar 221*c087a94bSLad Prabhakar if (in) 222*c087a94bSLad Prabhakar *in = _in; 223*c087a94bSLad Prabhakar if (out) 224*c087a94bSLad Prabhakar *out = _out; 225*c087a94bSLad Prabhakar if (en) 226*c087a94bSLad Prabhakar *en = _en; 227*c087a94bSLad Prabhakar } 228*c087a94bSLad Prabhakar 229*c087a94bSLad Prabhakar int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, 230*c087a94bSLad Prabhakar struct rsnd_dai_stream *io) 231*c087a94bSLad Prabhakar { 232*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(cmd_mod); 233*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 234*c087a94bSLad Prabhakar struct rsnd_mod *adg_mod = rsnd_mod_get(adg); 235*c087a94bSLad Prabhakar int id = rsnd_mod_id(cmd_mod); 236*c087a94bSLad Prabhakar int shift = (id % 2) ? 16 : 0; 237*c087a94bSLad Prabhakar u32 mask, val; 238*c087a94bSLad Prabhakar 239*c087a94bSLad Prabhakar rsnd_adg_get_timesel_ratio(priv, io, 240*c087a94bSLad Prabhakar rsnd_src_get_in_rate(priv, io), 241*c087a94bSLad Prabhakar rsnd_src_get_out_rate(priv, io), 242*c087a94bSLad Prabhakar NULL, &val, NULL); 243*c087a94bSLad Prabhakar 244*c087a94bSLad Prabhakar val = val << shift; 245*c087a94bSLad Prabhakar mask = 0x0f1f << shift; 246*c087a94bSLad Prabhakar 247*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, CMDOUT_TIMSEL, mask, val); 248*c087a94bSLad Prabhakar 249*c087a94bSLad Prabhakar return 0; 250*c087a94bSLad Prabhakar } 251*c087a94bSLad Prabhakar 252*c087a94bSLad Prabhakar int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod, 253*c087a94bSLad Prabhakar struct rsnd_dai_stream *io, 254*c087a94bSLad Prabhakar unsigned int in_rate, 255*c087a94bSLad Prabhakar unsigned int out_rate) 256*c087a94bSLad Prabhakar { 257*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(src_mod); 258*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 259*c087a94bSLad Prabhakar struct rsnd_mod *adg_mod = rsnd_mod_get(adg); 260*c087a94bSLad Prabhakar u32 in, out; 261*c087a94bSLad Prabhakar u32 mask, en; 262*c087a94bSLad Prabhakar int id = rsnd_mod_id(src_mod); 263*c087a94bSLad Prabhakar int shift = (id % 2) ? 16 : 0; 264*c087a94bSLad Prabhakar 265*c087a94bSLad Prabhakar rsnd_mod_make_sure(src_mod, RSND_MOD_SRC); 266*c087a94bSLad Prabhakar 267*c087a94bSLad Prabhakar rsnd_adg_get_timesel_ratio(priv, io, 268*c087a94bSLad Prabhakar in_rate, out_rate, 269*c087a94bSLad Prabhakar &in, &out, &en); 270*c087a94bSLad Prabhakar 271*c087a94bSLad Prabhakar in = in << shift; 272*c087a94bSLad Prabhakar out = out << shift; 273*c087a94bSLad Prabhakar mask = 0x0f1f << shift; 274*c087a94bSLad Prabhakar 275*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, SRCIN_TIMSEL(id / 2), mask, in); 276*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, SRCOUT_TIMSEL(id / 2), mask, out); 277*c087a94bSLad Prabhakar 278*c087a94bSLad Prabhakar if (en) 279*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, DIV_EN, en, en); 280*c087a94bSLad Prabhakar 281*c087a94bSLad Prabhakar return 0; 282*c087a94bSLad Prabhakar } 283*c087a94bSLad Prabhakar 284*c087a94bSLad Prabhakar static void rsnd_adg_set_ssi_clk(struct rsnd_mod *ssi_mod, u32 val) 285*c087a94bSLad Prabhakar { 286*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 287*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 288*c087a94bSLad Prabhakar struct rsnd_mod *adg_mod = rsnd_mod_get(adg); 289*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 290*c087a94bSLad Prabhakar int id = rsnd_mod_id(ssi_mod); 291*c087a94bSLad Prabhakar int shift = (id % 4) * 8; 292*c087a94bSLad Prabhakar u32 mask = 0xFF << shift; 293*c087a94bSLad Prabhakar 294*c087a94bSLad Prabhakar rsnd_mod_make_sure(ssi_mod, RSND_MOD_SSI); 295*c087a94bSLad Prabhakar 296*c087a94bSLad Prabhakar val = val << shift; 297*c087a94bSLad Prabhakar 298*c087a94bSLad Prabhakar /* 299*c087a94bSLad Prabhakar * SSI 8 is not connected to ADG. 300*c087a94bSLad Prabhakar * it works with SSI 7 301*c087a94bSLad Prabhakar */ 302*c087a94bSLad Prabhakar if (id == 8) 303*c087a94bSLad Prabhakar return; 304*c087a94bSLad Prabhakar 305*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, AUDIO_CLK_SEL(id / 4), mask, val); 306*c087a94bSLad Prabhakar 307*c087a94bSLad Prabhakar dev_dbg(dev, "AUDIO_CLK_SEL is 0x%x\n", val); 308*c087a94bSLad Prabhakar } 309*c087a94bSLad Prabhakar 310*c087a94bSLad Prabhakar int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate) 311*c087a94bSLad Prabhakar { 312*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 313*c087a94bSLad Prabhakar struct clk *clk; 314*c087a94bSLad Prabhakar int i; 315*c087a94bSLad Prabhakar int sel_table[] = { 316*c087a94bSLad Prabhakar [CLKA] = 0x1, 317*c087a94bSLad Prabhakar [CLKB] = 0x2, 318*c087a94bSLad Prabhakar [CLKC] = 0x3, 319*c087a94bSLad Prabhakar [CLKI] = 0x0, 320*c087a94bSLad Prabhakar }; 321*c087a94bSLad Prabhakar 322*c087a94bSLad Prabhakar /* 323*c087a94bSLad Prabhakar * find suitable clock from 324*c087a94bSLad Prabhakar * AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC/AUDIO_CLKI. 325*c087a94bSLad Prabhakar */ 326*c087a94bSLad Prabhakar for_each_rsnd_clkin(clk, adg, i) 327*c087a94bSLad Prabhakar if (rate == adg->clkin_rate[i]) 328*c087a94bSLad Prabhakar return sel_table[i]; 329*c087a94bSLad Prabhakar 330*c087a94bSLad Prabhakar /* 331*c087a94bSLad Prabhakar * find divided clock from BRGA/BRGB 332*c087a94bSLad Prabhakar */ 333*c087a94bSLad Prabhakar if (rate == adg->brg_rate[ADG_HZ_441]) 334*c087a94bSLad Prabhakar return 0x10; 335*c087a94bSLad Prabhakar 336*c087a94bSLad Prabhakar if (rate == adg->brg_rate[ADG_HZ_48]) 337*c087a94bSLad Prabhakar return 0x20; 338*c087a94bSLad Prabhakar 339*c087a94bSLad Prabhakar return -EIO; 340*c087a94bSLad Prabhakar } 341*c087a94bSLad Prabhakar 342*c087a94bSLad Prabhakar int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) 343*c087a94bSLad Prabhakar { 344*c087a94bSLad Prabhakar rsnd_adg_set_ssi_clk(ssi_mod, 0); 345*c087a94bSLad Prabhakar 346*c087a94bSLad Prabhakar return 0; 347*c087a94bSLad Prabhakar } 348*c087a94bSLad Prabhakar 349*c087a94bSLad Prabhakar int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) 350*c087a94bSLad Prabhakar { 351*c087a94bSLad Prabhakar struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod); 352*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 353*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 354*c087a94bSLad Prabhakar struct rsnd_mod *adg_mod = rsnd_mod_get(adg); 355*c087a94bSLad Prabhakar int data; 356*c087a94bSLad Prabhakar u32 ckr = 0; 357*c087a94bSLad Prabhakar 358*c087a94bSLad Prabhakar data = rsnd_adg_clk_query(priv, rate); 359*c087a94bSLad Prabhakar if (data < 0) 360*c087a94bSLad Prabhakar return data; 361*c087a94bSLad Prabhakar 362*c087a94bSLad Prabhakar rsnd_adg_set_ssi_clk(ssi_mod, data); 363*c087a94bSLad Prabhakar 364*c087a94bSLad Prabhakar if (0 == (rate % 8000)) 365*c087a94bSLad Prabhakar ckr = 0x80000000; /* BRGB output = 48kHz */ 366*c087a94bSLad Prabhakar 367*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr | ckr); 368*c087a94bSLad Prabhakar 369*c087a94bSLad Prabhakar dev_dbg(dev, "CLKOUT is based on BRG%c (= %dHz)\n", 370*c087a94bSLad Prabhakar (ckr) ? 'B' : 'A', 371*c087a94bSLad Prabhakar (ckr) ? adg->brg_rate[ADG_HZ_48] : 372*c087a94bSLad Prabhakar adg->brg_rate[ADG_HZ_441]); 373*c087a94bSLad Prabhakar 374*c087a94bSLad Prabhakar return 0; 375*c087a94bSLad Prabhakar } 376*c087a94bSLad Prabhakar 377*c087a94bSLad Prabhakar void rsnd_adg_clk_control(struct rsnd_priv *priv, int enable) 378*c087a94bSLad Prabhakar { 379*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 380*c087a94bSLad Prabhakar struct rsnd_mod *adg_mod = rsnd_mod_get(adg); 381*c087a94bSLad Prabhakar struct clk *clk; 382*c087a94bSLad Prabhakar int i; 383*c087a94bSLad Prabhakar 384*c087a94bSLad Prabhakar if (enable) { 385*c087a94bSLad Prabhakar rsnd_mod_bset(adg_mod, BRGCKR, 0x80770000, adg->ckr); 386*c087a94bSLad Prabhakar rsnd_mod_write(adg_mod, BRRA, adg->brga); 387*c087a94bSLad Prabhakar rsnd_mod_write(adg_mod, BRRB, adg->brgb); 388*c087a94bSLad Prabhakar } 389*c087a94bSLad Prabhakar 390*c087a94bSLad Prabhakar for_each_rsnd_clkin(clk, adg, i) { 391*c087a94bSLad Prabhakar if (enable) { 392*c087a94bSLad Prabhakar clk_prepare_enable(clk); 393*c087a94bSLad Prabhakar 394*c087a94bSLad Prabhakar /* 395*c087a94bSLad Prabhakar * We shouldn't use clk_get_rate() under 396*c087a94bSLad Prabhakar * atomic context. Let's keep it when 397*c087a94bSLad Prabhakar * rsnd_adg_clk_enable() was called 398*c087a94bSLad Prabhakar */ 399*c087a94bSLad Prabhakar adg->clkin_rate[i] = clk_get_rate(clk); 400*c087a94bSLad Prabhakar } else { 401*c087a94bSLad Prabhakar clk_disable_unprepare(clk); 402*c087a94bSLad Prabhakar } 403*c087a94bSLad Prabhakar } 404*c087a94bSLad Prabhakar } 405*c087a94bSLad Prabhakar 406*c087a94bSLad Prabhakar static struct clk *rsnd_adg_create_null_clk(struct rsnd_priv *priv, 407*c087a94bSLad Prabhakar const char * const name, 408*c087a94bSLad Prabhakar const char *parent) 409*c087a94bSLad Prabhakar { 410*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 411*c087a94bSLad Prabhakar struct clk *clk; 412*c087a94bSLad Prabhakar 413*c087a94bSLad Prabhakar clk = clk_register_fixed_rate(dev, name, parent, 0, 0); 414*c087a94bSLad Prabhakar if (IS_ERR_OR_NULL(clk)) { 415*c087a94bSLad Prabhakar dev_err(dev, "create null clk error\n"); 416*c087a94bSLad Prabhakar return ERR_CAST(clk); 417*c087a94bSLad Prabhakar } 418*c087a94bSLad Prabhakar 419*c087a94bSLad Prabhakar return clk; 420*c087a94bSLad Prabhakar } 421*c087a94bSLad Prabhakar 422*c087a94bSLad Prabhakar static struct clk *rsnd_adg_null_clk_get(struct rsnd_priv *priv) 423*c087a94bSLad Prabhakar { 424*c087a94bSLad Prabhakar struct rsnd_adg *adg = priv->adg; 425*c087a94bSLad Prabhakar 426*c087a94bSLad Prabhakar if (!adg->null_clk) { 427*c087a94bSLad Prabhakar static const char * const name = "rsnd_adg_null"; 428*c087a94bSLad Prabhakar 429*c087a94bSLad Prabhakar adg->null_clk = rsnd_adg_create_null_clk(priv, name, NULL); 430*c087a94bSLad Prabhakar } 431*c087a94bSLad Prabhakar 432*c087a94bSLad Prabhakar return adg->null_clk; 433*c087a94bSLad Prabhakar } 434*c087a94bSLad Prabhakar 435*c087a94bSLad Prabhakar static void rsnd_adg_null_clk_clean(struct rsnd_priv *priv) 436*c087a94bSLad Prabhakar { 437*c087a94bSLad Prabhakar struct rsnd_adg *adg = priv->adg; 438*c087a94bSLad Prabhakar 439*c087a94bSLad Prabhakar if (adg->null_clk) 440*c087a94bSLad Prabhakar clk_unregister_fixed_rate(adg->null_clk); 441*c087a94bSLad Prabhakar } 442*c087a94bSLad Prabhakar 443*c087a94bSLad Prabhakar static int rsnd_adg_get_clkin(struct rsnd_priv *priv) 444*c087a94bSLad Prabhakar { 445*c087a94bSLad Prabhakar struct rsnd_adg *adg = priv->adg; 446*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 447*c087a94bSLad Prabhakar struct clk *clk; 448*c087a94bSLad Prabhakar const char * const *clkin_name; 449*c087a94bSLad Prabhakar int clkin_size; 450*c087a94bSLad Prabhakar int i; 451*c087a94bSLad Prabhakar 452*c087a94bSLad Prabhakar clkin_name = clkin_name_gen2; 453*c087a94bSLad Prabhakar clkin_size = ARRAY_SIZE(clkin_name_gen2); 454*c087a94bSLad Prabhakar if (rsnd_is_gen4(priv)) { 455*c087a94bSLad Prabhakar clkin_name = clkin_name_gen4; 456*c087a94bSLad Prabhakar clkin_size = ARRAY_SIZE(clkin_name_gen4); 457*c087a94bSLad Prabhakar } 458*c087a94bSLad Prabhakar 459*c087a94bSLad Prabhakar for (i = 0; i < clkin_size; i++) { 460*c087a94bSLad Prabhakar clk = devm_clk_get(dev, clkin_name[i]); 461*c087a94bSLad Prabhakar 462*c087a94bSLad Prabhakar if (IS_ERR_OR_NULL(clk)) 463*c087a94bSLad Prabhakar clk = rsnd_adg_null_clk_get(priv); 464*c087a94bSLad Prabhakar if (IS_ERR_OR_NULL(clk)) 465*c087a94bSLad Prabhakar goto err; 466*c087a94bSLad Prabhakar 467*c087a94bSLad Prabhakar adg->clkin[i] = clk; 468*c087a94bSLad Prabhakar } 469*c087a94bSLad Prabhakar 470*c087a94bSLad Prabhakar adg->clkin_size = clkin_size; 471*c087a94bSLad Prabhakar 472*c087a94bSLad Prabhakar return 0; 473*c087a94bSLad Prabhakar 474*c087a94bSLad Prabhakar err: 475*c087a94bSLad Prabhakar dev_err(dev, "adg clock IN get failed\n"); 476*c087a94bSLad Prabhakar 477*c087a94bSLad Prabhakar rsnd_adg_null_clk_clean(priv); 478*c087a94bSLad Prabhakar 479*c087a94bSLad Prabhakar return -EIO; 480*c087a94bSLad Prabhakar } 481*c087a94bSLad Prabhakar 482*c087a94bSLad Prabhakar static void rsnd_adg_unregister_clkout(struct rsnd_priv *priv) 483*c087a94bSLad Prabhakar { 484*c087a94bSLad Prabhakar struct rsnd_adg *adg = priv->adg; 485*c087a94bSLad Prabhakar struct clk *clk; 486*c087a94bSLad Prabhakar int i; 487*c087a94bSLad Prabhakar 488*c087a94bSLad Prabhakar for_each_rsnd_clkout(clk, adg, i) 489*c087a94bSLad Prabhakar clk_unregister_fixed_rate(clk); 490*c087a94bSLad Prabhakar } 491*c087a94bSLad Prabhakar 492*c087a94bSLad Prabhakar static int rsnd_adg_get_clkout(struct rsnd_priv *priv) 493*c087a94bSLad Prabhakar { 494*c087a94bSLad Prabhakar struct rsnd_adg *adg = priv->adg; 495*c087a94bSLad Prabhakar struct clk *clk; 496*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 497*c087a94bSLad Prabhakar struct device_node *np = dev->of_node; 498*c087a94bSLad Prabhakar struct property *prop; 499*c087a94bSLad Prabhakar u32 ckr, brgx, brga, brgb; 500*c087a94bSLad Prabhakar u32 req_rate[ADG_HZ_SIZE] = {}; 501*c087a94bSLad Prabhakar uint32_t count = 0; 502*c087a94bSLad Prabhakar unsigned long req_Hz[ADG_HZ_SIZE]; 503*c087a94bSLad Prabhakar int clkout_size; 504*c087a94bSLad Prabhakar int i, req_size; 505*c087a94bSLad Prabhakar int approximate = 0; 506*c087a94bSLad Prabhakar const char *parent_clk_name = NULL; 507*c087a94bSLad Prabhakar const char * const *clkout_name; 508*c087a94bSLad Prabhakar int brg_table[] = { 509*c087a94bSLad Prabhakar [CLKA] = 0x0, 510*c087a94bSLad Prabhakar [CLKB] = 0x1, 511*c087a94bSLad Prabhakar [CLKC] = 0x4, 512*c087a94bSLad Prabhakar [CLKI] = 0x2, 513*c087a94bSLad Prabhakar }; 514*c087a94bSLad Prabhakar 515*c087a94bSLad Prabhakar ckr = 0; 516*c087a94bSLad Prabhakar brga = 0xff; /* default */ 517*c087a94bSLad Prabhakar brgb = 0xff; /* default */ 518*c087a94bSLad Prabhakar 519*c087a94bSLad Prabhakar /* 520*c087a94bSLad Prabhakar * ADG supports BRRA/BRRB output only 521*c087a94bSLad Prabhakar * this means all clkout0/1/2/3 will be same rate 522*c087a94bSLad Prabhakar */ 523*c087a94bSLad Prabhakar prop = of_find_property(np, "clock-frequency", NULL); 524*c087a94bSLad Prabhakar if (!prop) 525*c087a94bSLad Prabhakar goto rsnd_adg_get_clkout_end; 526*c087a94bSLad Prabhakar 527*c087a94bSLad Prabhakar req_size = prop->length / sizeof(u32); 528*c087a94bSLad Prabhakar if (req_size > ADG_HZ_SIZE) { 529*c087a94bSLad Prabhakar dev_err(dev, "too many clock-frequency\n"); 530*c087a94bSLad Prabhakar return -EINVAL; 531*c087a94bSLad Prabhakar } 532*c087a94bSLad Prabhakar 533*c087a94bSLad Prabhakar of_property_read_u32_array(np, "clock-frequency", req_rate, req_size); 534*c087a94bSLad Prabhakar req_Hz[ADG_HZ_48] = 0; 535*c087a94bSLad Prabhakar req_Hz[ADG_HZ_441] = 0; 536*c087a94bSLad Prabhakar for (i = 0; i < req_size; i++) { 537*c087a94bSLad Prabhakar if (0 == (req_rate[i] % 44100)) 538*c087a94bSLad Prabhakar req_Hz[ADG_HZ_441] = req_rate[i]; 539*c087a94bSLad Prabhakar if (0 == (req_rate[i] % 48000)) 540*c087a94bSLad Prabhakar req_Hz[ADG_HZ_48] = req_rate[i]; 541*c087a94bSLad Prabhakar } 542*c087a94bSLad Prabhakar 543*c087a94bSLad Prabhakar /* 544*c087a94bSLad Prabhakar * This driver is assuming that AUDIO_CLKA/AUDIO_CLKB/AUDIO_CLKC 545*c087a94bSLad Prabhakar * have 44.1kHz or 48kHz base clocks for now. 546*c087a94bSLad Prabhakar * 547*c087a94bSLad Prabhakar * SSI itself can divide parent clock by 1/1 - 1/16 548*c087a94bSLad Prabhakar * see 549*c087a94bSLad Prabhakar * rsnd_adg_ssi_clk_try_start() 550*c087a94bSLad Prabhakar * rsnd_ssi_master_clk_start() 551*c087a94bSLad Prabhakar */ 552*c087a94bSLad Prabhakar 553*c087a94bSLad Prabhakar /* 554*c087a94bSLad Prabhakar * [APPROXIMATE] 555*c087a94bSLad Prabhakar * 556*c087a94bSLad Prabhakar * clk_i (internal clock) can't create accurate rate, it will be approximate rate. 557*c087a94bSLad Prabhakar * 558*c087a94bSLad Prabhakar * <Note> 559*c087a94bSLad Prabhakar * 560*c087a94bSLad Prabhakar * clk_i needs x2 of required maximum rate. 561*c087a94bSLad Prabhakar * see 562*c087a94bSLad Prabhakar * - Minimum division of BRRA/BRRB 563*c087a94bSLad Prabhakar * - rsnd_ssi_clk_query() 564*c087a94bSLad Prabhakar * 565*c087a94bSLad Prabhakar * Sample Settings for TDM 8ch, 32bit width 566*c087a94bSLad Prabhakar * 567*c087a94bSLad Prabhakar * 8(ch) x 32(bit) x 44100(Hz) x 2<Note> = 22579200 568*c087a94bSLad Prabhakar * 8(ch) x 32(bit) x 48000(Hz) x 2<Note> = 24576000 569*c087a94bSLad Prabhakar * 570*c087a94bSLad Prabhakar * clock-frequency = <22579200 24576000>; 571*c087a94bSLad Prabhakar */ 572*c087a94bSLad Prabhakar for_each_rsnd_clkin(clk, adg, i) { 573*c087a94bSLad Prabhakar u32 rate, div; 574*c087a94bSLad Prabhakar 575*c087a94bSLad Prabhakar rate = clk_get_rate(clk); 576*c087a94bSLad Prabhakar 577*c087a94bSLad Prabhakar if (0 == rate) /* not used */ 578*c087a94bSLad Prabhakar continue; 579*c087a94bSLad Prabhakar 580*c087a94bSLad Prabhakar /* BRGA */ 581*c087a94bSLad Prabhakar 582*c087a94bSLad Prabhakar if (i == CLKI) 583*c087a94bSLad Prabhakar /* see [APPROXIMATE] */ 584*c087a94bSLad Prabhakar rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_441]) * req_Hz[ADG_HZ_441]; 585*c087a94bSLad Prabhakar if (!adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441] && (0 == rate % 44100)) { 586*c087a94bSLad Prabhakar div = rate / req_Hz[ADG_HZ_441]; 587*c087a94bSLad Prabhakar brgx = rsnd_adg_calculate_brgx(div); 588*c087a94bSLad Prabhakar if (BRRx_MASK(brgx) == brgx) { 589*c087a94bSLad Prabhakar brga = brgx; 590*c087a94bSLad Prabhakar adg->brg_rate[ADG_HZ_441] = rate / div; 591*c087a94bSLad Prabhakar ckr |= brg_table[i] << 20; 592*c087a94bSLad Prabhakar if (req_Hz[ADG_HZ_441]) 593*c087a94bSLad Prabhakar parent_clk_name = __clk_get_name(clk); 594*c087a94bSLad Prabhakar if (i == CLKI) 595*c087a94bSLad Prabhakar approximate = 1; 596*c087a94bSLad Prabhakar } 597*c087a94bSLad Prabhakar } 598*c087a94bSLad Prabhakar 599*c087a94bSLad Prabhakar /* BRGB */ 600*c087a94bSLad Prabhakar 601*c087a94bSLad Prabhakar if (i == CLKI) 602*c087a94bSLad Prabhakar /* see [APPROXIMATE] */ 603*c087a94bSLad Prabhakar rate = (clk_get_rate(clk) / req_Hz[ADG_HZ_48]) * req_Hz[ADG_HZ_48]; 604*c087a94bSLad Prabhakar if (!adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48] && (0 == rate % 48000)) { 605*c087a94bSLad Prabhakar div = rate / req_Hz[ADG_HZ_48]; 606*c087a94bSLad Prabhakar brgx = rsnd_adg_calculate_brgx(div); 607*c087a94bSLad Prabhakar if (BRRx_MASK(brgx) == brgx) { 608*c087a94bSLad Prabhakar brgb = brgx; 609*c087a94bSLad Prabhakar adg->brg_rate[ADG_HZ_48] = rate / div; 610*c087a94bSLad Prabhakar ckr |= brg_table[i] << 16; 611*c087a94bSLad Prabhakar if (req_Hz[ADG_HZ_48]) 612*c087a94bSLad Prabhakar parent_clk_name = __clk_get_name(clk); 613*c087a94bSLad Prabhakar if (i == CLKI) 614*c087a94bSLad Prabhakar approximate = 1; 615*c087a94bSLad Prabhakar } 616*c087a94bSLad Prabhakar } 617*c087a94bSLad Prabhakar } 618*c087a94bSLad Prabhakar 619*c087a94bSLad Prabhakar if (!(adg->brg_rate[ADG_HZ_48] && req_Hz[ADG_HZ_48]) && 620*c087a94bSLad Prabhakar !(adg->brg_rate[ADG_HZ_441] && req_Hz[ADG_HZ_441])) 621*c087a94bSLad Prabhakar goto rsnd_adg_get_clkout_end; 622*c087a94bSLad Prabhakar 623*c087a94bSLad Prabhakar if (approximate) 624*c087a94bSLad Prabhakar dev_info(dev, "It uses CLK_I as approximate rate"); 625*c087a94bSLad Prabhakar 626*c087a94bSLad Prabhakar clkout_name = clkout_name_gen2; 627*c087a94bSLad Prabhakar clkout_size = ARRAY_SIZE(clkout_name_gen2); 628*c087a94bSLad Prabhakar if (rsnd_is_gen4(priv)) 629*c087a94bSLad Prabhakar clkout_size = 1; /* reuse clkout_name_gen2[] */ 630*c087a94bSLad Prabhakar 631*c087a94bSLad Prabhakar /* 632*c087a94bSLad Prabhakar * ADG supports BRRA/BRRB output only. 633*c087a94bSLad Prabhakar * this means all clkout0/1/2/3 will be * same rate 634*c087a94bSLad Prabhakar */ 635*c087a94bSLad Prabhakar 636*c087a94bSLad Prabhakar of_property_read_u32(np, "#clock-cells", &count); 637*c087a94bSLad Prabhakar /* 638*c087a94bSLad Prabhakar * for clkout 639*c087a94bSLad Prabhakar */ 640*c087a94bSLad Prabhakar if (!count) { 641*c087a94bSLad Prabhakar clk = clk_register_fixed_rate(dev, clkout_name[CLKOUT], 642*c087a94bSLad Prabhakar parent_clk_name, 0, req_rate[0]); 643*c087a94bSLad Prabhakar if (IS_ERR_OR_NULL(clk)) 644*c087a94bSLad Prabhakar goto err; 645*c087a94bSLad Prabhakar 646*c087a94bSLad Prabhakar adg->clkout[CLKOUT] = clk; 647*c087a94bSLad Prabhakar adg->clkout_size = 1; 648*c087a94bSLad Prabhakar of_clk_add_provider(np, of_clk_src_simple_get, clk); 649*c087a94bSLad Prabhakar } 650*c087a94bSLad Prabhakar /* 651*c087a94bSLad Prabhakar * for clkout0/1/2/3 652*c087a94bSLad Prabhakar */ 653*c087a94bSLad Prabhakar else { 654*c087a94bSLad Prabhakar for (i = 0; i < clkout_size; i++) { 655*c087a94bSLad Prabhakar clk = clk_register_fixed_rate(dev, clkout_name[i], 656*c087a94bSLad Prabhakar parent_clk_name, 0, 657*c087a94bSLad Prabhakar req_rate[0]); 658*c087a94bSLad Prabhakar if (IS_ERR_OR_NULL(clk)) 659*c087a94bSLad Prabhakar goto err; 660*c087a94bSLad Prabhakar 661*c087a94bSLad Prabhakar adg->clkout[i] = clk; 662*c087a94bSLad Prabhakar } 663*c087a94bSLad Prabhakar adg->onecell.clks = adg->clkout; 664*c087a94bSLad Prabhakar adg->onecell.clk_num = clkout_size; 665*c087a94bSLad Prabhakar adg->clkout_size = clkout_size; 666*c087a94bSLad Prabhakar of_clk_add_provider(np, of_clk_src_onecell_get, 667*c087a94bSLad Prabhakar &adg->onecell); 668*c087a94bSLad Prabhakar } 669*c087a94bSLad Prabhakar 670*c087a94bSLad Prabhakar rsnd_adg_get_clkout_end: 671*c087a94bSLad Prabhakar adg->ckr = ckr; 672*c087a94bSLad Prabhakar adg->brga = brga; 673*c087a94bSLad Prabhakar adg->brgb = brgb; 674*c087a94bSLad Prabhakar 675*c087a94bSLad Prabhakar return 0; 676*c087a94bSLad Prabhakar 677*c087a94bSLad Prabhakar err: 678*c087a94bSLad Prabhakar dev_err(dev, "adg clock OUT get failed\n"); 679*c087a94bSLad Prabhakar 680*c087a94bSLad Prabhakar rsnd_adg_unregister_clkout(priv); 681*c087a94bSLad Prabhakar 682*c087a94bSLad Prabhakar return -EIO; 683*c087a94bSLad Prabhakar } 684*c087a94bSLad Prabhakar 685*c087a94bSLad Prabhakar #if defined(DEBUG) || defined(CONFIG_DEBUG_FS) 686*c087a94bSLad Prabhakar __printf(3, 4) 687*c087a94bSLad Prabhakar static void dbg_msg(struct device *dev, struct seq_file *m, 688*c087a94bSLad Prabhakar const char *fmt, ...) 689*c087a94bSLad Prabhakar { 690*c087a94bSLad Prabhakar char msg[128]; 691*c087a94bSLad Prabhakar va_list args; 692*c087a94bSLad Prabhakar 693*c087a94bSLad Prabhakar va_start(args, fmt); 694*c087a94bSLad Prabhakar vsnprintf(msg, sizeof(msg), fmt, args); 695*c087a94bSLad Prabhakar va_end(args); 696*c087a94bSLad Prabhakar 697*c087a94bSLad Prabhakar if (m) 698*c087a94bSLad Prabhakar seq_puts(m, msg); 699*c087a94bSLad Prabhakar else 700*c087a94bSLad Prabhakar dev_dbg(dev, "%s", msg); 701*c087a94bSLad Prabhakar } 702*c087a94bSLad Prabhakar 703*c087a94bSLad Prabhakar void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m) 704*c087a94bSLad Prabhakar { 705*c087a94bSLad Prabhakar struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 706*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 707*c087a94bSLad Prabhakar struct clk *clk; 708*c087a94bSLad Prabhakar int i; 709*c087a94bSLad Prabhakar 710*c087a94bSLad Prabhakar for_each_rsnd_clkin(clk, adg, i) 711*c087a94bSLad Prabhakar dbg_msg(dev, m, "%-18s : %pa : %ld\n", 712*c087a94bSLad Prabhakar __clk_get_name(clk), clk, clk_get_rate(clk)); 713*c087a94bSLad Prabhakar 714*c087a94bSLad Prabhakar dbg_msg(dev, m, "BRGCKR = 0x%08x, BRRA/BRRB = 0x%x/0x%x\n", 715*c087a94bSLad Prabhakar adg->ckr, adg->brga, adg->brgb); 716*c087a94bSLad Prabhakar dbg_msg(dev, m, "BRGA (for 44100 base) = %d\n", adg->brg_rate[ADG_HZ_441]); 717*c087a94bSLad Prabhakar dbg_msg(dev, m, "BRGB (for 48000 base) = %d\n", adg->brg_rate[ADG_HZ_48]); 718*c087a94bSLad Prabhakar 719*c087a94bSLad Prabhakar /* 720*c087a94bSLad Prabhakar * Actual CLKOUT will be exchanged in rsnd_adg_ssi_clk_try_start() 721*c087a94bSLad Prabhakar * by BRGCKR::BRGCKR_31 722*c087a94bSLad Prabhakar */ 723*c087a94bSLad Prabhakar for_each_rsnd_clkout(clk, adg, i) 724*c087a94bSLad Prabhakar dbg_msg(dev, m, "%-18s : %pa : %ld\n", 725*c087a94bSLad Prabhakar __clk_get_name(clk), clk, clk_get_rate(clk)); 726*c087a94bSLad Prabhakar } 727*c087a94bSLad Prabhakar #else 728*c087a94bSLad Prabhakar #define rsnd_adg_clk_dbg_info(priv, m) 729*c087a94bSLad Prabhakar #endif 730*c087a94bSLad Prabhakar 731*c087a94bSLad Prabhakar int rsnd_adg_probe(struct rsnd_priv *priv) 732*c087a94bSLad Prabhakar { 733*c087a94bSLad Prabhakar struct rsnd_adg *adg; 734*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 735*c087a94bSLad Prabhakar int ret; 736*c087a94bSLad Prabhakar 737*c087a94bSLad Prabhakar adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); 738*c087a94bSLad Prabhakar if (!adg) 739*c087a94bSLad Prabhakar return -ENOMEM; 740*c087a94bSLad Prabhakar 741*c087a94bSLad Prabhakar ret = rsnd_mod_init(priv, &adg->mod, &adg_ops, 742*c087a94bSLad Prabhakar NULL, 0, 0); 743*c087a94bSLad Prabhakar if (ret) 744*c087a94bSLad Prabhakar return ret; 745*c087a94bSLad Prabhakar 746*c087a94bSLad Prabhakar priv->adg = adg; 747*c087a94bSLad Prabhakar 748*c087a94bSLad Prabhakar ret = rsnd_adg_get_clkin(priv); 749*c087a94bSLad Prabhakar if (ret) 750*c087a94bSLad Prabhakar return ret; 751*c087a94bSLad Prabhakar 752*c087a94bSLad Prabhakar ret = rsnd_adg_get_clkout(priv); 753*c087a94bSLad Prabhakar if (ret) 754*c087a94bSLad Prabhakar return ret; 755*c087a94bSLad Prabhakar 756*c087a94bSLad Prabhakar rsnd_adg_clk_enable(priv); 757*c087a94bSLad Prabhakar rsnd_adg_clk_dbg_info(priv, NULL); 758*c087a94bSLad Prabhakar 759*c087a94bSLad Prabhakar return 0; 760*c087a94bSLad Prabhakar } 761*c087a94bSLad Prabhakar 762*c087a94bSLad Prabhakar void rsnd_adg_remove(struct rsnd_priv *priv) 763*c087a94bSLad Prabhakar { 764*c087a94bSLad Prabhakar struct device *dev = rsnd_priv_to_dev(priv); 765*c087a94bSLad Prabhakar struct device_node *np = dev->of_node; 766*c087a94bSLad Prabhakar 767*c087a94bSLad Prabhakar rsnd_adg_unregister_clkout(priv); 768*c087a94bSLad Prabhakar 769*c087a94bSLad Prabhakar of_clk_del_provider(np); 770*c087a94bSLad Prabhakar 771*c087a94bSLad Prabhakar rsnd_adg_clk_disable(priv); 772*c087a94bSLad Prabhakar 773*c087a94bSLad Prabhakar /* It should be called after rsnd_adg_clk_disable() */ 774*c087a94bSLad Prabhakar rsnd_adg_null_clk_clean(priv); 775*c087a94bSLad Prabhakar } 776