Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 // Copyright(c) 2015-17 Intel Corporation
0003 
0004 /*
0005  *  skl-ssp-clk.c - ASoC skylake ssp clock driver
0006  */
0007 
0008 #include <linux/kernel.h>
0009 #include <linux/module.h>
0010 #include <linux/err.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/clk-provider.h>
0013 #include <linux/clkdev.h>
0014 #include <sound/intel-nhlt.h>
0015 #include "skl.h"
0016 #include "skl-ssp-clk.h"
0017 #include "skl-topology.h"
0018 
0019 #define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw)
0020 
0021 struct skl_clk_parent {
0022     struct clk_hw *hw;
0023     struct clk_lookup *lookup;
0024 };
0025 
0026 struct skl_clk {
0027     struct clk_hw hw;
0028     struct clk_lookup *lookup;
0029     unsigned long rate;
0030     struct skl_clk_pdata *pdata;
0031     u32 id;
0032 };
0033 
0034 struct skl_clk_data {
0035     struct skl_clk_parent parent[SKL_MAX_CLK_SRC];
0036     struct skl_clk *clk[SKL_MAX_CLK_CNT];
0037     u8 avail_clk_cnt;
0038 };
0039 
0040 static int skl_get_clk_type(u32 index)
0041 {
0042     switch (index) {
0043     case 0 ... (SKL_SCLK_OFS - 1):
0044         return SKL_MCLK;
0045 
0046     case SKL_SCLK_OFS ... (SKL_SCLKFS_OFS - 1):
0047         return SKL_SCLK;
0048 
0049     case SKL_SCLKFS_OFS ... (SKL_MAX_CLK_CNT - 1):
0050         return SKL_SCLK_FS;
0051 
0052     default:
0053         return -EINVAL;
0054     }
0055 }
0056 
0057 static int skl_get_vbus_id(u32 index, u8 clk_type)
0058 {
0059     switch (clk_type) {
0060     case SKL_MCLK:
0061         return index;
0062 
0063     case SKL_SCLK:
0064         return index - SKL_SCLK_OFS;
0065 
0066     case SKL_SCLK_FS:
0067         return index - SKL_SCLKFS_OFS;
0068 
0069     default:
0070         return -EINVAL;
0071     }
0072 }
0073 
0074 static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table *rcfg, u8 clk_type)
0075 {
0076     struct nhlt_fmt_cfg *fmt_cfg;
0077     union skl_clk_ctrl_ipc *ipc;
0078     struct wav_fmt *wfmt;
0079 
0080     if (!rcfg)
0081         return;
0082 
0083     ipc = &rcfg->dma_ctl_ipc;
0084     if (clk_type == SKL_SCLK_FS) {
0085         fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config;
0086         wfmt = &fmt_cfg->fmt_ext.fmt;
0087 
0088         /* Remove TLV Header size */
0089         ipc->sclk_fs.hdr.size = sizeof(struct skl_dmactrl_sclkfs_cfg) -
0090                         sizeof(struct skl_tlv_hdr);
0091         ipc->sclk_fs.sampling_frequency = wfmt->samples_per_sec;
0092         ipc->sclk_fs.bit_depth = wfmt->bits_per_sample;
0093         ipc->sclk_fs.valid_bit_depth =
0094             fmt_cfg->fmt_ext.sample.valid_bits_per_sample;
0095         ipc->sclk_fs.number_of_channels = wfmt->channels;
0096     } else {
0097         ipc->mclk.hdr.type = DMA_CLK_CONTROLS;
0098         /* Remove TLV Header size */
0099         ipc->mclk.hdr.size = sizeof(struct skl_dmactrl_mclk_cfg) -
0100                         sizeof(struct skl_tlv_hdr);
0101     }
0102 }
0103 
0104 /* Sends dma control IPC to turn the clock ON/OFF */
0105 static int skl_send_clk_dma_control(struct skl_dev *skl,
0106                 struct skl_clk_rate_cfg_table *rcfg,
0107                 u32 vbus_id, u8 clk_type,
0108                 bool enable)
0109 {
0110     struct nhlt_specific_cfg *sp_cfg;
0111     u32 i2s_config_size, node_id = 0;
0112     struct nhlt_fmt_cfg *fmt_cfg;
0113     union skl_clk_ctrl_ipc *ipc;
0114     void *i2s_config = NULL;
0115     u8 *data, size;
0116     int ret;
0117 
0118     if (!rcfg)
0119         return -EIO;
0120 
0121     ipc = &rcfg->dma_ctl_ipc;
0122     fmt_cfg = (struct nhlt_fmt_cfg *)rcfg->config;
0123     sp_cfg = &fmt_cfg->config;
0124 
0125     if (clk_type == SKL_SCLK_FS) {
0126         ipc->sclk_fs.hdr.type =
0127             enable ? DMA_TRANSMITION_START : DMA_TRANSMITION_STOP;
0128         data = (u8 *)&ipc->sclk_fs;
0129         size = sizeof(struct skl_dmactrl_sclkfs_cfg);
0130     } else {
0131         /* 1 to enable mclk, 0 to enable sclk */
0132         if (clk_type == SKL_SCLK)
0133             ipc->mclk.mclk = 0;
0134         else
0135             ipc->mclk.mclk = 1;
0136 
0137         ipc->mclk.keep_running = enable;
0138         ipc->mclk.warm_up_over = enable;
0139         ipc->mclk.clk_stop_over = !enable;
0140         data = (u8 *)&ipc->mclk;
0141         size = sizeof(struct skl_dmactrl_mclk_cfg);
0142     }
0143 
0144     i2s_config_size = sp_cfg->size + size;
0145     i2s_config = kzalloc(i2s_config_size, GFP_KERNEL);
0146     if (!i2s_config)
0147         return -ENOMEM;
0148 
0149     /* copy blob */
0150     memcpy(i2s_config, sp_cfg->caps, sp_cfg->size);
0151 
0152     /* copy additional dma controls information */
0153     memcpy(i2s_config + sp_cfg->size, data, size);
0154 
0155     node_id = ((SKL_DMA_I2S_LINK_INPUT_CLASS << 8) | (vbus_id << 4));
0156     ret = skl_dsp_set_dma_control(skl, (u32 *)i2s_config,
0157                     i2s_config_size, node_id);
0158     kfree(i2s_config);
0159 
0160     return ret;
0161 }
0162 
0163 static struct skl_clk_rate_cfg_table *skl_get_rate_cfg(
0164         struct skl_clk_rate_cfg_table *rcfg,
0165                 unsigned long rate)
0166 {
0167     int i;
0168 
0169     for (i = 0; (i < SKL_MAX_CLK_RATES) && rcfg[i].rate; i++) {
0170         if (rcfg[i].rate == rate)
0171             return &rcfg[i];
0172     }
0173 
0174     return NULL;
0175 }
0176 
0177 static int skl_clk_change_status(struct skl_clk *clkdev,
0178                 bool enable)
0179 {
0180     struct skl_clk_rate_cfg_table *rcfg;
0181     int vbus_id, clk_type;
0182 
0183     clk_type = skl_get_clk_type(clkdev->id);
0184     if (clk_type < 0)
0185         return clk_type;
0186 
0187     vbus_id = skl_get_vbus_id(clkdev->id, clk_type);
0188     if (vbus_id < 0)
0189         return vbus_id;
0190 
0191     rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg,
0192                         clkdev->rate);
0193     if (!rcfg)
0194         return -EINVAL;
0195 
0196     return skl_send_clk_dma_control(clkdev->pdata->pvt_data, rcfg,
0197                     vbus_id, clk_type, enable);
0198 }
0199 
0200 static int skl_clk_prepare(struct clk_hw *hw)
0201 {
0202     struct skl_clk *clkdev = to_skl_clk(hw);
0203 
0204     return skl_clk_change_status(clkdev, true);
0205 }
0206 
0207 static void skl_clk_unprepare(struct clk_hw *hw)
0208 {
0209     struct skl_clk *clkdev = to_skl_clk(hw);
0210 
0211     skl_clk_change_status(clkdev, false);
0212 }
0213 
0214 static int skl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
0215                     unsigned long parent_rate)
0216 {
0217     struct skl_clk *clkdev = to_skl_clk(hw);
0218     struct skl_clk_rate_cfg_table *rcfg;
0219     int clk_type;
0220 
0221     if (!rate)
0222         return -EINVAL;
0223 
0224     rcfg = skl_get_rate_cfg(clkdev->pdata->ssp_clks[clkdev->id].rate_cfg,
0225                             rate);
0226     if (!rcfg)
0227         return -EINVAL;
0228 
0229     clk_type = skl_get_clk_type(clkdev->id);
0230     if (clk_type < 0)
0231         return clk_type;
0232 
0233     skl_fill_clk_ipc(rcfg, clk_type);
0234     clkdev->rate = rate;
0235 
0236     return 0;
0237 }
0238 
0239 static unsigned long skl_clk_recalc_rate(struct clk_hw *hw,
0240                 unsigned long parent_rate)
0241 {
0242     struct skl_clk *clkdev = to_skl_clk(hw);
0243 
0244     if (clkdev->rate)
0245         return clkdev->rate;
0246 
0247     return 0;
0248 }
0249 
0250 /* Not supported by clk driver. Implemented to satisfy clk fw */
0251 static long skl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
0252                    unsigned long *parent_rate)
0253 {
0254     return rate;
0255 }
0256 
0257 /*
0258  * prepare/unprepare are used instead of enable/disable as IPC will be sent
0259  * in non-atomic context.
0260  */
0261 static const struct clk_ops skl_clk_ops = {
0262     .prepare = skl_clk_prepare,
0263     .unprepare = skl_clk_unprepare,
0264     .set_rate = skl_clk_set_rate,
0265     .round_rate = skl_clk_round_rate,
0266     .recalc_rate = skl_clk_recalc_rate,
0267 };
0268 
0269 static void unregister_parent_src_clk(struct skl_clk_parent *pclk,
0270                     unsigned int id)
0271 {
0272     while (id--) {
0273         clkdev_drop(pclk[id].lookup);
0274         clk_hw_unregister_fixed_rate(pclk[id].hw);
0275     }
0276 }
0277 
0278 static void unregister_src_clk(struct skl_clk_data *dclk)
0279 {
0280     while (dclk->avail_clk_cnt--)
0281         clkdev_drop(dclk->clk[dclk->avail_clk_cnt]->lookup);
0282 }
0283 
0284 static int skl_register_parent_clks(struct device *dev,
0285             struct skl_clk_parent *parent,
0286             struct skl_clk_parent_src *pclk)
0287 {
0288     int i, ret;
0289 
0290     for (i = 0; i < SKL_MAX_CLK_SRC; i++) {
0291 
0292         /* Register Parent clock */
0293         parent[i].hw = clk_hw_register_fixed_rate(dev, pclk[i].name,
0294                 pclk[i].parent_name, 0, pclk[i].rate);
0295         if (IS_ERR(parent[i].hw)) {
0296             ret = PTR_ERR(parent[i].hw);
0297             goto err;
0298         }
0299 
0300         parent[i].lookup = clkdev_hw_create(parent[i].hw, pclk[i].name,
0301                                     NULL);
0302         if (!parent[i].lookup) {
0303             clk_hw_unregister_fixed_rate(parent[i].hw);
0304             ret = -ENOMEM;
0305             goto err;
0306         }
0307     }
0308 
0309     return 0;
0310 err:
0311     unregister_parent_src_clk(parent, i);
0312     return ret;
0313 }
0314 
0315 /* Assign fmt_config to clk_data */
0316 static struct skl_clk *register_skl_clk(struct device *dev,
0317             struct skl_ssp_clk *clk,
0318             struct skl_clk_pdata *clk_pdata, int id)
0319 {
0320     struct clk_init_data init;
0321     struct skl_clk *clkdev;
0322     int ret;
0323 
0324     clkdev = devm_kzalloc(dev, sizeof(*clkdev), GFP_KERNEL);
0325     if (!clkdev)
0326         return ERR_PTR(-ENOMEM);
0327 
0328     init.name = clk->name;
0329     init.ops = &skl_clk_ops;
0330     init.flags = CLK_SET_RATE_GATE;
0331     init.parent_names = &clk->parent_name;
0332     init.num_parents = 1;
0333     clkdev->hw.init = &init;
0334     clkdev->pdata = clk_pdata;
0335 
0336     clkdev->id = id;
0337     ret = devm_clk_hw_register(dev, &clkdev->hw);
0338     if (ret) {
0339         clkdev = ERR_PTR(ret);
0340         return clkdev;
0341     }
0342 
0343     clkdev->lookup = clkdev_hw_create(&clkdev->hw, init.name, NULL);
0344     if (!clkdev->lookup)
0345         clkdev = ERR_PTR(-ENOMEM);
0346 
0347     return clkdev;
0348 }
0349 
0350 static int skl_clk_dev_probe(struct platform_device *pdev)
0351 {
0352     struct device *dev = &pdev->dev;
0353     struct device *parent_dev = dev->parent;
0354     struct skl_clk_parent_src *parent_clks;
0355     struct skl_clk_pdata *clk_pdata;
0356     struct skl_clk_data *data;
0357     struct skl_ssp_clk *clks;
0358     int ret, i;
0359 
0360     clk_pdata = dev_get_platdata(&pdev->dev);
0361     parent_clks = clk_pdata->parent_clks;
0362     clks = clk_pdata->ssp_clks;
0363     if (!parent_clks || !clks)
0364         return -EIO;
0365 
0366     data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
0367     if (!data)
0368         return -ENOMEM;
0369 
0370     /* Register Parent clock */
0371     ret = skl_register_parent_clks(parent_dev, data->parent, parent_clks);
0372     if (ret < 0)
0373         return ret;
0374 
0375     for (i = 0; i < clk_pdata->num_clks; i++) {
0376         /*
0377          * Only register valid clocks
0378          * i.e. for which nhlt entry is present.
0379          */
0380         if (clks[i].rate_cfg[0].rate == 0)
0381             continue;
0382 
0383         data->clk[data->avail_clk_cnt] = register_skl_clk(dev,
0384                 &clks[i], clk_pdata, i);
0385 
0386         if (IS_ERR(data->clk[data->avail_clk_cnt])) {
0387             ret = PTR_ERR(data->clk[data->avail_clk_cnt]);
0388             goto err_unreg_skl_clk;
0389         }
0390 
0391         data->avail_clk_cnt++;
0392     }
0393 
0394     platform_set_drvdata(pdev, data);
0395 
0396     return 0;
0397 
0398 err_unreg_skl_clk:
0399     unregister_src_clk(data);
0400     unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC);
0401 
0402     return ret;
0403 }
0404 
0405 static int skl_clk_dev_remove(struct platform_device *pdev)
0406 {
0407     struct skl_clk_data *data;
0408 
0409     data = platform_get_drvdata(pdev);
0410     unregister_src_clk(data);
0411     unregister_parent_src_clk(data->parent, SKL_MAX_CLK_SRC);
0412 
0413     return 0;
0414 }
0415 
0416 static struct platform_driver skl_clk_driver = {
0417     .driver = {
0418         .name = "skl-ssp-clk",
0419     },
0420     .probe = skl_clk_dev_probe,
0421     .remove = skl_clk_dev_remove,
0422 };
0423 
0424 module_platform_driver(skl_clk_driver);
0425 
0426 MODULE_DESCRIPTION("Skylake clock driver");
0427 MODULE_AUTHOR("Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>");
0428 MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
0429 MODULE_LICENSE("GPL v2");
0430 MODULE_ALIAS("platform:skl-ssp-clk");