1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright(c) 2015-17 Intel Corporation
5 * skl-ssp-clk.c - ASoC skylake ssp clock driver
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>
15 #include "skl-ssp-clk.h"
16 #include "skl-topology.h"
18 #define to_skl_clk(_hw) container_of(_hw, struct skl_clk, hw)
20 struct skl_clk_parent
{
22 struct clk_lookup
*lookup
;
27 struct clk_lookup
*lookup
;
29 struct skl_clk_pdata
*pdata
;
34 struct skl_clk_parent parent
[SKL_MAX_CLK_SRC
];
35 struct skl_clk
*clk
[SKL_MAX_CLK_CNT
];
39 static int skl_get_clk_type(u32 index
)
42 case 0 ... (SKL_SCLK_OFS
- 1):
45 case SKL_SCLK_OFS
... (SKL_SCLKFS_OFS
- 1):
48 case SKL_SCLKFS_OFS
... (SKL_MAX_CLK_CNT
- 1):
56 static int skl_get_vbus_id(u32 index
, u8 clk_type
)
63 return index
- SKL_SCLK_OFS
;
66 return index
- SKL_SCLKFS_OFS
;
73 static void skl_fill_clk_ipc(struct skl_clk_rate_cfg_table
*rcfg
, u8 clk_type
)
75 struct nhlt_fmt_cfg
*fmt_cfg
;
76 union skl_clk_ctrl_ipc
*ipc
;
82 ipc
= &rcfg
->dma_ctl_ipc
;
83 if (clk_type
== SKL_SCLK_FS
) {
84 fmt_cfg
= (struct nhlt_fmt_cfg
*)rcfg
->config
;
85 wfmt
= &fmt_cfg
->fmt_ext
.fmt
;
87 /* Remove TLV Header size */
88 ipc
->sclk_fs
.hdr
.size
= sizeof(struct skl_dmactrl_sclkfs_cfg
) -
89 sizeof(struct skl_tlv_hdr
);
90 ipc
->sclk_fs
.sampling_frequency
= wfmt
->samples_per_sec
;
91 ipc
->sclk_fs
.bit_depth
= wfmt
->bits_per_sample
;
92 ipc
->sclk_fs
.valid_bit_depth
=
93 fmt_cfg
->fmt_ext
.sample
.valid_bits_per_sample
;
94 ipc
->sclk_fs
.number_of_channels
= wfmt
->channels
;
96 ipc
->mclk
.hdr
.type
= DMA_CLK_CONTROLS
;
97 /* Remove TLV Header size */
98 ipc
->mclk
.hdr
.size
= sizeof(struct skl_dmactrl_mclk_cfg
) -
99 sizeof(struct skl_tlv_hdr
);
103 /* Sends dma control IPC to turn the clock ON/OFF */
104 static int skl_send_clk_dma_control(struct skl
*skl
,
105 struct skl_clk_rate_cfg_table
*rcfg
,
106 u32 vbus_id
, u8 clk_type
,
109 struct nhlt_specific_cfg
*sp_cfg
;
110 u32 i2s_config_size
, node_id
= 0;
111 struct nhlt_fmt_cfg
*fmt_cfg
;
112 union skl_clk_ctrl_ipc
*ipc
;
113 void *i2s_config
= NULL
;
120 ipc
= &rcfg
->dma_ctl_ipc
;
121 fmt_cfg
= (struct nhlt_fmt_cfg
*)rcfg
->config
;
122 sp_cfg
= &fmt_cfg
->config
;
124 if (clk_type
== SKL_SCLK_FS
) {
125 ipc
->sclk_fs
.hdr
.type
=
126 enable
? DMA_TRANSMITION_START
: DMA_TRANSMITION_STOP
;
127 data
= (u8
*)&ipc
->sclk_fs
;
128 size
= sizeof(struct skl_dmactrl_sclkfs_cfg
);
130 /* 1 to enable mclk, 0 to enable sclk */
131 if (clk_type
== SKL_SCLK
)
136 ipc
->mclk
.keep_running
= enable
;
137 ipc
->mclk
.warm_up_over
= enable
;
138 ipc
->mclk
.clk_stop_over
= !enable
;
139 data
= (u8
*)&ipc
->mclk
;
140 size
= sizeof(struct skl_dmactrl_mclk_cfg
);
143 i2s_config_size
= sp_cfg
->size
+ size
;
144 i2s_config
= kzalloc(i2s_config_size
, GFP_KERNEL
);
149 memcpy(i2s_config
, sp_cfg
->caps
, sp_cfg
->size
);
151 /* copy additional dma controls information */
152 memcpy(i2s_config
+ sp_cfg
->size
, data
, size
);
154 node_id
= ((SKL_DMA_I2S_LINK_INPUT_CLASS
<< 8) | (vbus_id
<< 4));
155 ret
= skl_dsp_set_dma_control(skl
->skl_sst
, (u32
*)i2s_config
,
156 i2s_config_size
, node_id
);
162 static struct skl_clk_rate_cfg_table
*skl_get_rate_cfg(
163 struct skl_clk_rate_cfg_table
*rcfg
,
168 for (i
= 0; (i
< SKL_MAX_CLK_RATES
) && rcfg
[i
].rate
; i
++) {
169 if (rcfg
[i
].rate
== rate
)
176 static int skl_clk_change_status(struct skl_clk
*clkdev
,
179 struct skl_clk_rate_cfg_table
*rcfg
;
180 int vbus_id
, clk_type
;
182 clk_type
= skl_get_clk_type(clkdev
->id
);
186 vbus_id
= skl_get_vbus_id(clkdev
->id
, clk_type
);
190 rcfg
= skl_get_rate_cfg(clkdev
->pdata
->ssp_clks
[clkdev
->id
].rate_cfg
,
195 return skl_send_clk_dma_control(clkdev
->pdata
->pvt_data
, rcfg
,
196 vbus_id
, clk_type
, enable
);
199 static int skl_clk_prepare(struct clk_hw
*hw
)
201 struct skl_clk
*clkdev
= to_skl_clk(hw
);
203 return skl_clk_change_status(clkdev
, true);
206 static void skl_clk_unprepare(struct clk_hw
*hw
)
208 struct skl_clk
*clkdev
= to_skl_clk(hw
);
210 skl_clk_change_status(clkdev
, false);
213 static int skl_clk_set_rate(struct clk_hw
*hw
, unsigned long rate
,
214 unsigned long parent_rate
)
216 struct skl_clk
*clkdev
= to_skl_clk(hw
);
217 struct skl_clk_rate_cfg_table
*rcfg
;
223 rcfg
= skl_get_rate_cfg(clkdev
->pdata
->ssp_clks
[clkdev
->id
].rate_cfg
,
228 clk_type
= skl_get_clk_type(clkdev
->id
);
232 skl_fill_clk_ipc(rcfg
, clk_type
);
238 static unsigned long skl_clk_recalc_rate(struct clk_hw
*hw
,
239 unsigned long parent_rate
)
241 struct skl_clk
*clkdev
= to_skl_clk(hw
);
249 /* Not supported by clk driver. Implemented to satisfy clk fw */
250 long skl_clk_round_rate(struct clk_hw
*hw
, unsigned long rate
,
251 unsigned long *parent_rate
)
257 * prepare/unprepare are used instead of enable/disable as IPC will be sent
258 * in non-atomic context.
260 static const struct clk_ops skl_clk_ops
= {
261 .prepare
= skl_clk_prepare
,
262 .unprepare
= skl_clk_unprepare
,
263 .set_rate
= skl_clk_set_rate
,
264 .round_rate
= skl_clk_round_rate
,
265 .recalc_rate
= skl_clk_recalc_rate
,
268 static void unregister_parent_src_clk(struct skl_clk_parent
*pclk
,
272 clkdev_drop(pclk
[id
].lookup
);
273 clk_hw_unregister_fixed_rate(pclk
[id
].hw
);
277 static void unregister_src_clk(struct skl_clk_data
*dclk
)
279 u8 cnt
= dclk
->avail_clk_cnt
;
282 clkdev_drop(dclk
->clk
[cnt
]->lookup
);
285 static int skl_register_parent_clks(struct device
*dev
,
286 struct skl_clk_parent
*parent
,
287 struct skl_clk_parent_src
*pclk
)
291 for (i
= 0; i
< SKL_MAX_CLK_SRC
; i
++) {
293 /* Register Parent clock */
294 parent
[i
].hw
= clk_hw_register_fixed_rate(dev
, pclk
[i
].name
,
295 pclk
[i
].parent_name
, 0, pclk
[i
].rate
);
296 if (IS_ERR(parent
[i
].hw
)) {
297 ret
= PTR_ERR(parent
[i
].hw
);
301 parent
[i
].lookup
= clkdev_hw_create(parent
[i
].hw
, pclk
[i
].name
,
303 if (!parent
[i
].lookup
) {
304 clk_hw_unregister_fixed_rate(parent
[i
].hw
);
312 unregister_parent_src_clk(parent
, i
);
316 /* Assign fmt_config to clk_data */
317 static struct skl_clk
*register_skl_clk(struct device
*dev
,
318 struct skl_ssp_clk
*clk
,
319 struct skl_clk_pdata
*clk_pdata
, int id
)
321 struct clk_init_data init
;
322 struct skl_clk
*clkdev
;
325 clkdev
= devm_kzalloc(dev
, sizeof(*clkdev
), GFP_KERNEL
);
327 return ERR_PTR(-ENOMEM
);
329 init
.name
= clk
->name
;
330 init
.ops
= &skl_clk_ops
;
331 init
.flags
= CLK_SET_RATE_GATE
;
332 init
.parent_names
= &clk
->parent_name
;
333 init
.num_parents
= 1;
334 clkdev
->hw
.init
= &init
;
335 clkdev
->pdata
= clk_pdata
;
338 ret
= devm_clk_hw_register(dev
, &clkdev
->hw
);
340 clkdev
= ERR_PTR(ret
);
344 clkdev
->lookup
= clkdev_hw_create(&clkdev
->hw
, init
.name
, NULL
);
346 clkdev
= ERR_PTR(-ENOMEM
);
351 static int skl_clk_dev_probe(struct platform_device
*pdev
)
353 struct device
*dev
= &pdev
->dev
;
354 struct device
*parent_dev
= dev
->parent
;
355 struct skl_clk_parent_src
*parent_clks
;
356 struct skl_clk_pdata
*clk_pdata
;
357 struct skl_clk_data
*data
;
358 struct skl_ssp_clk
*clks
;
361 clk_pdata
= dev_get_platdata(&pdev
->dev
);
362 parent_clks
= clk_pdata
->parent_clks
;
363 clks
= clk_pdata
->ssp_clks
;
364 if (!parent_clks
|| !clks
)
367 data
= devm_kzalloc(dev
, sizeof(*data
), GFP_KERNEL
);
371 /* Register Parent clock */
372 ret
= skl_register_parent_clks(parent_dev
, data
->parent
, parent_clks
);
376 for (i
= 0; i
< clk_pdata
->num_clks
; i
++) {
378 * Only register valid clocks
379 * i.e. for which nhlt entry is present.
381 if (clks
[i
].rate_cfg
[0].rate
== 0)
384 data
->clk
[i
] = register_skl_clk(dev
, &clks
[i
], clk_pdata
, i
);
385 if (IS_ERR(data
->clk
[i
])) {
386 ret
= PTR_ERR(data
->clk
[i
]);
387 goto err_unreg_skl_clk
;
390 data
->avail_clk_cnt
++;
393 platform_set_drvdata(pdev
, data
);
398 unregister_src_clk(data
);
399 unregister_parent_src_clk(data
->parent
, SKL_MAX_CLK_SRC
);
404 static int skl_clk_dev_remove(struct platform_device
*pdev
)
406 struct skl_clk_data
*data
;
408 data
= platform_get_drvdata(pdev
);
409 unregister_src_clk(data
);
410 unregister_parent_src_clk(data
->parent
, SKL_MAX_CLK_SRC
);
415 static struct platform_driver skl_clk_driver
= {
417 .name
= "skl-ssp-clk",
419 .probe
= skl_clk_dev_probe
,
420 .remove
= skl_clk_dev_remove
,
423 module_platform_driver(skl_clk_driver
);
425 MODULE_DESCRIPTION("Skylake clock driver");
426 MODULE_AUTHOR("Jaikrishna Nemallapudi <jaikrishnax.nemallapudi@intel.com>");
427 MODULE_AUTHOR("Subhransu S. Prusty <subhransu.s.prusty@intel.com>");
428 MODULE_LICENSE("GPL v2");
429 MODULE_ALIAS("platform:skl-ssp-clk");