1 // SPDX-License-Identifier: GPL-2.0-only 2 // Copyright(c) 2015-17 Intel Corporation 3 4 /* 5 * skl-ssp-clk.c - ASoC skylake ssp clock driver 6 */ 7 8 #include <linux/kernel.h> 9 #include <linux/module.h> 10 #include <linux/err.h> 11 #include <linux/platform_device.h> 12 #include <linux/clk-provider.h> 13 #include <linux/clkdev.h> 14 #include <sound/intel-nhlt.h> 15 #include "skl.h" 16 #include "skl-ssp-clk.h" 17 #include "skl-topology.h" 18 19 #define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw) 20 21 struct skl_clk_parent { 22 struct clk_hw *hw; 23 struct clk_lookup *lookup; 24 }; 25 26 struct skl_clk { 27 struct clk_hw hw; 28 struct clk_lookup *lookup; 29 unsigned long rate; 30 struct skl_clk_pdata *pdata; 31 u32 id; 32 }; 33 34 struct skl_clk_data { 35 struct skl_clk_parent parent[SKL_MAX_CLK_SRC]; 36 struct skl_clk *clk[SKL_MAX_CLK_CNT]; 37 u8 avail_clk_cnt; 38 }; 39 40 static int skl_get_clk_type(u32 index) 41 { 42 switch (index) { 43 case 0 ... (SKL_SCLK_OFS - 1): 44 return SKL_MCLK; 45 46 case SKL_SCLK_OFS ... (SKL_SCLKFS_OFS - 1): 47 return SKL_SCLK; 48 49 case SKL_SCLKFS_OFS ... (SKL_MAX_CLK_CNT - 1): 50 return SKL_SCLK_FS; 51 52 default: 53 return -EINVAL; 54 } 55 } 56 57 static int skl_get_vbus_id(u32 index, u8 clk_type) 58 { 59 switch (clk_type) { 60 case SKL_MCLK: 61 return index; 62 63 case SKL_SCLK: 64 return index - SKL_SCLK_OFS; 65 66 case SKL_SCLK_FS: 67 return index - SKL_SCLKFS_OFS; 68 69 default: 70 return -EINVAL; 71 } 72 } 73 74 static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type) 75 { 76 struct nhlt_fmt_cfg *fmt_cfg; 77 union skl_clk_ctrl_ipc *ipc; 78 struct wav_fmt *wfmt; 79 80 if (!rcfg) 81 return; 82 83 ipc = &rcfg->dma_ctl_ipc; 84 if (clk_type == SKL_SCLK_FS) { 85 fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config; 86 wfmt = &fmt_cfg->fmt_ext.fmt; 87 88 /* Remove TLV Header size */ 89 ipc->sclk_fs.hdr.size = sizeof(struct skl_dmactrl_sclkfs_cfg) - 90 sizeof(struct skl_tlv_hdr); 91 ipc->sclk_fs.sampling_frequency = wfmt->samples_per_sec; 92 ipc->sclk_fs.bit_depth = wfmt->bits_per_sample; 93 ipc->sclk_fs.valid_bit_depth = 94 fmt_cfg->fmt_ext.sample.valid_bits_per_sample; 95 ipc->sclk_fs.number_of_channels = wfmt->channels; 96 } else { 97 ipc->mclk.hdr.type = DMA_CLK_CONTROLS; 98 /* Remove TLV Header size */ 99 ipc->mclk.hdr.size = sizeof(struct skl_dmactrl_mclk_cfg) - 100 sizeof(struct skl_tlv_hdr); 101 } 102 } 103 104 /* Sends dma control IPC to turn the clock ON/OFF */ 105 static int skl_send_clk_dma_control(struct skl_dev *skl, 106 struct skl_clk_rate_cfg_table *rcfg, 107 u32 vbus_id, u8 clk_type, 108 bool enable) 109 { 110 struct nhlt_specific_cfg *sp_cfg; 111 u32 i2s_config_size, node_id = 0; 112 struct nhlt_fmt_cfg *fmt_cfg; 113 union skl_clk_ctrl_ipc *ipc; 114 void *i2s_config = NULL; 115 u8 *data, size; 116 int ret; 117 118 if (!rcfg) 119 return -EIO; 120 121 ipc = &rcfg->dma_ctl_ipc; 122 fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config; 123 sp_cfg = &fmt_cfg->config; 124 125 if (clk_type == SKL_SCLK_FS) { 126 ipc->sclk_fs.hdr.type = 127 enable ? DMA_TRANSMITION_START : DMA_TRANSMITION_STOP; 128 data = (u8 *)&ipc->sclk_fs; 129 size = sizeof(struct skl_dmactrl_sclkfs_cfg); 130 } else { 131 /* 1 to enable mclk, 0 to enable sclk */ 132 if (clk_type == SKL_SCLK) 133 ipc->mclk.mclk = 0; 134 else 135 ipc->mclk.mclk = 1; 136 137 ipc->mclk.keep_running = enable; 138 ipc->mclk.warm_up_over = enable; 139 ipc->mclk.clk_stop_over = !enable; 140 data = (u8 *)&ipc->mclk; 141 size = sizeof(struct skl_dmactrl_mclk_cfg); 142 } 143 144 i2s_config_size = sp_cfg->size + size; 145 i2s_config = kzalloc(i2s_config_size, GFP_KERNEL); 146 if (!i2s_config) 147 return -ENOMEM; 148 149 /* copy blob */ 150 memcpy(i2s_config, sp_cfg->caps, sp_cfg->size); 151 152 /* copy additional dma controls information */ 153 memcpy(i2s_config + sp_cfg->size, data, size); 154 155 node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4)); 156 ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config, 157 i2s_config_size, node_id); 158 kfree(i2s_config); 159 160 return ret; 161 } 162 163 static struct skl_clk_rate_cfg_table *skl_get_rate_cfg( 164 struct skl_clk_rate_cfg_table *rcfg, 165 unsigned long rate) 166 { 167 int i; 168 169 for (i = 0; (i < SKL_MAX_CLK_RATES) && rcfg[i].rate; i++) { 170 if (rcfg[i].rate == rate) 171 return &rcfg[i]; 172 } 173 174 return NULL; 175 } 176 177 static int skl_clk_change_status(struct skl_clk *clkdev, 178 bool enable) 179 { 180 struct skl_clk_rate_cfg_table *rcfg; 181 int vbus_id, clk_type; 182 183 clk_type = skl_get_clk_type(clkdev->id); 184 if (clk_type < 0) 185 return clk_type; 186 187 vbus_id = skl_get_vbus_id(clkdev->id, clk_type); 188 if (vbus_id < 0) 189 return vbus_id; 190 191 rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg, 192 clkdev->rate); 193 if (!rcfg) 194 return -EINVAL; 195 196 return skl_send_clk_dma_control(clkdev->pdata->pvt_data, rcfg, 197 vbus_id, clk_type, enable); 198 } 199 200 static int skl_clk_prepare(struct clk_hw *hw) 201 { 202 struct skl_clk *clkdev = to_skl_clk(hw); 203 204 return skl_clk_change_status(clkdev, true); 205 } 206 207 static void skl_clk_unprepare(struct clk_hw *hw) 208 { 209 struct skl_clk *clkdev = to_skl_clk(hw); 210 211 skl_clk_change_status(clkdev, false); 212 } 213 214 static int skl_clk_set_rate(struct clk_hw *hw, unsigned long rate, 215 unsigned long parent_rate) 216 { 217 struct skl_clk *clkdev = to_skl_clk(hw); 218 struct skl_clk_rate_cfg_table *rcfg; 219 int clk_type; 220 221 if (!rate) 222 return -EINVAL; 223 224 rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg, 225 rate); 226 if (!rcfg) 227 return -EINVAL; 228 229 clk_type = skl_get_clk_type(clkdev->id); 230 if (clk_type < 0) 231 return clk_type; 232 233 skl_fill_clk_ipc(rcfg, clk_type); 234 clkdev->rate = rate; 235 236 return 0; 237 } 238 239 static unsigned long skl_clk_recalc_rate(struct clk_hw *hw, 240 unsigned long parent_rate) 241 { 242 struct skl_clk *clkdev = to_skl_clk(hw); 243 244 if (clkdev->rate) 245 return clkdev->rate; 246 247 return 0; 248 } 249 250 /* Not supported by clk driver. Implemented to satisfy clk fw */ 251 static long skl_clk_round_rate(struct clk_hw *hw, unsigned long rate, 252 unsigned long *parent_rate) 253 { 254 return rate; 255 } 256 257 /* 258 * prepare/unprepare are used instead of enable/disable as IPC will be sent 259 * in non-atomic context. 260 */ 261 static const struct clk_ops skl_clk_ops = { 262 .prepare = skl_clk_prepare, 263 .unprepare = skl_clk_unprepare, 264 .set_rate = skl_clk_set_rate, 265 .round_rate = skl_clk_round_rate, 266 .recalc_rate = skl_clk_recalc_rate, 267 }; 268 269 static void unregister_parent_src_clk(struct skl_clk_parent *pclk, 270 unsigned int id) 271 { 272 while (id--) { 273 clkdev_drop(pclk[id].lookup); 274 clk_hw_unregister_fixed_rate(pclk[id].hw); 275 } 276 } 277 278 static void unregister_src_clk(struct skl_clk_data *dclk) 279 { 280 while (dclk->avail_clk_cnt--) 281 clkdev_drop(dclk->clk[dclk->avail_clk_cnt]->lookup); 282 } 283 284 static int skl_register_parent_clks(struct device *dev, 285 struct skl_clk_parent *parent, 286 struct skl_clk_parent_src *pclk) 287 { 288 int i, ret; 289 290 for (i = 0; i < SKL_MAX_CLK_SRC; i++) { 291 292 /* Register Parent clock */ 293 parent[i].hw = clk_hw_register_fixed_rate(dev, pclk[i].name, 294 pclk[i].parent_name, 0, pclk[i].rate); 295 if (IS_ERR(parent[i].hw)) { 296 ret = PTR_ERR(parent[i].hw); 297 goto err; 298 } 299 300 parent[i].lookup = clkdev_hw_create(parent[i].hw, pclk[i].name, 301 NULL); 302 if (!parent[i].lookup) { 303 clk_hw_unregister_fixed_rate(parent[i].hw); 304 ret = -ENOMEM; 305 goto err; 306 } 307 } 308 309 return 0; 310 err: 311 unregister_parent_src_clk(parent, i); 312 return ret; 313 } 314 315 /* Assign fmt_config to clk_data */ 316 static struct skl_clk *register_skl_clk(struct device *dev, 317 struct skl_ssp_clk *clk, 318 struct skl_clk_pdata *clk_pdata, int id) 319 { 320 struct clk_init_data init; 321 struct skl_clk *clkdev; 322 int ret; 323 324 clkdev = devm_kzalloc(dev, sizeof(*clkdev), GFP_KERNEL); 325 if (!clkdev) 326 return ERR_PTR(-ENOMEM); 327 328 init.name = clk->name; 329 init.ops = &skl_clk_ops; 330 init.flags = CLK_SET_RATE_GATE; 331 init.parent_names = &clk->parent_name; 332 init.num_parents = 1; 333 clkdev->hw.init = &init; 334 clkdev->pdata = clk_pdata; 335 336 clkdev->id = id; 337 ret = devm_clk_hw_register(dev, &clkdev->hw); 338 if (ret) { 339 clkdev = ERR_PTR(ret); 340 return clkdev; 341 } 342 343 clkdev->lookup = clkdev_hw_create(&clkdev->hw, init.name, NULL); 344 if (!clkdev->lookup) 345 clkdev = ERR_PTR(-ENOMEM); 346 347 return clkdev; 348 } 349 350 static int skl_clk_dev_probe(struct platform_device *pdev) 351 { 352 struct device *dev = &pdev->dev; 353 struct device *parent_dev = dev->parent; 354 struct skl_clk_parent_src *parent_clks; 355 struct skl_clk_pdata *clk_pdata; 356 struct skl_clk_data *data; 357 struct skl_ssp_clk *clks; 358 int ret, i; 359 360 clk_pdata = dev_get_platdata(&pdev->dev); 361 parent_clks = clk_pdata->parent_clks; 362 clks = clk_pdata->ssp_clks; 363 if (!parent_clks || !clks) 364 return -EIO; 365 366 data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); 367 if (!data) 368 return -ENOMEM; 369 370 /* Register Parent clock */ 371 ret = skl_register_parent_clks(parent_dev, data->parent, parent_clks); 372 if (ret < 0) 373 return ret; 374 375 for (i = 0; i < clk_pdata->num_clks; i++) { 376 /* 377 * Only register valid clocks 378 * i.e. for which nhlt entry is present. 379 */ 380 if (clks[i].rate_cfg[0].rate == 0) 381 continue; 382 383 data->clk[data->avail_clk_cnt] = register_skl_clk(dev, 384 &clks[i], clk_pdata, i); 385 386 if (IS_ERR(data->clk[data->avail_clk_cnt])) { 387 ret = PTR_ERR(data->clk[data->avail_clk_cnt]); 388 goto err_unreg_skl_clk; 389 } 390 391 data->avail_clk_cnt++; 392 } 393 394 platform_set_drvdata(pdev, data); 395 396 return 0; 397 398 err_unreg_skl_clk: 399 unregister_src_clk(data); 400 unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); 401 402 return ret; 403 } 404 405 static void skl_clk_dev_remove(struct platform_device *pdev) 406 { 407 struct skl_clk_data *data; 408 409 data = platform_get_drvdata(pdev); 410 unregister_src_clk(data); 411 unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC); 412 } 413 414 static struct platform_driver skl_clk_driver = { 415 .driver = { 416 .name = "skl-ssp-clk", 417 }, 418 .probe = skl_clk_dev_probe, 419 .remove_new = skl_clk_dev_remove, 420 }; 421 422 module_platform_driver(skl_clk_driver); 423 424 MODULE_DESCRIPTION("Skylake clock driver"); 425 MODULE_AUTHOR("Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>"); 426 MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>"); 427 MODULE_LICENSE("GPL v2"); 428 MODULE_ALIAS("platform:skl-ssp-clk"); 429
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.