Skip to content

Commit 16fb217

Browse files
committed
Merge tag 'clk-imx-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux into clk-imx
Pull i.MX clk driver updates from Abel Vesa: - Add PM runtime support to i.MX8MP Audiomix - Add i.MX95 BLK CTL clock driver - Add DT schema for i.MX95 Display Master Block Control - Convert to platform remove callback returning void for i.MX8MP Audiomix * tag 'clk-imx-6.10' of git://git.kernel.org/pub/scm/linux/kernel/git/abelvesa/linux: clk: imx: imx8mp: Convert to platform remove callback returning void clk: imx: imx8mp: Switch to RUNTIME_PM_OPS() clk: imx: add i.MX95 BLK CTL clk driver dt-bindings: clock: support i.MX95 Display Master CSR module dt-bindings: clock: support i.MX95 BLK CTL module dt-bindings: clock: add i.MX95 clock header clk: imx: imx8mp: Add pm_runtime support for power saving
2 parents 4cece76 + f5072cf commit 16fb217

File tree

7 files changed

+728
-21
lines changed

7 files changed

+728
-21
lines changed
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/clock/nxp,imx95-blk-ctl.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: NXP i.MX95 Block Control
8+
9+
maintainers:
10+
- Peng Fan <peng.fan@nxp.com>
11+
12+
properties:
13+
compatible:
14+
items:
15+
- enum:
16+
- nxp,imx95-lvds-csr
17+
- nxp,imx95-display-csr
18+
- nxp,imx95-camera-csr
19+
- nxp,imx95-vpu-csr
20+
- const: syscon
21+
22+
reg:
23+
maxItems: 1
24+
25+
power-domains:
26+
maxItems: 1
27+
28+
clocks:
29+
maxItems: 1
30+
31+
'#clock-cells':
32+
const: 1
33+
description:
34+
The clock consumer should specify the desired clock by having the clock
35+
ID in its "clocks" phandle cell. See
36+
include/dt-bindings/clock/nxp,imx95-clock.h
37+
38+
required:
39+
- compatible
40+
- reg
41+
- '#clock-cells'
42+
- power-domains
43+
- clocks
44+
45+
additionalProperties: false
46+
47+
examples:
48+
- |
49+
syscon@4c410000 {
50+
compatible = "nxp,imx95-vpu-csr", "syscon";
51+
reg = <0x4c410000 0x10000>;
52+
#clock-cells = <1>;
53+
clocks = <&scmi_clk 114>;
54+
power-domains = <&scmi_devpd 21>;
55+
};
56+
...
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
2+
%YAML 1.2
3+
---
4+
$id: http://devicetree.org/schemas/clock/nxp,imx95-display-master-csr.yaml#
5+
$schema: http://devicetree.org/meta-schemas/core.yaml#
6+
7+
title: NXP i.MX95 Display Master Block Control
8+
9+
maintainers:
10+
- Peng Fan <peng.fan@nxp.com>
11+
12+
properties:
13+
compatible:
14+
items:
15+
- const: nxp,imx95-display-master-csr
16+
- const: syscon
17+
18+
reg:
19+
maxItems: 1
20+
21+
power-domains:
22+
maxItems: 1
23+
24+
clocks:
25+
maxItems: 1
26+
27+
'#clock-cells':
28+
const: 1
29+
description:
30+
The clock consumer should specify the desired clock by having the clock
31+
ID in its "clocks" phandle cell. See
32+
include/dt-bindings/clock/nxp,imx95-clock.h
33+
34+
mux-controller:
35+
type: object
36+
$ref: /schemas/mux/reg-mux.yaml
37+
38+
required:
39+
- compatible
40+
- reg
41+
- '#clock-cells'
42+
- mux-controller
43+
- power-domains
44+
- clocks
45+
46+
additionalProperties: false
47+
48+
examples:
49+
- |
50+
syscon@4c410000 {
51+
compatible = "nxp,imx95-display-master-csr", "syscon";
52+
reg = <0x4c410000 0x10000>;
53+
#clock-cells = <1>;
54+
clocks = <&scmi_clk 62>;
55+
power-domains = <&scmi_devpd 3>;
56+
57+
mux: mux-controller {
58+
compatible = "mmio-mux";
59+
#mux-control-cells = <1>;
60+
mux-reg-masks = <0x4 0x00000001>; /* Pixel_link_sel */
61+
idle-states = <0>;
62+
};
63+
};
64+
...

drivers/clk/imx/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,13 @@ config CLK_IMX93
114114
help
115115
Build the driver for i.MX93 CCM Clock Driver
116116

117+
config CLK_IMX95_BLK_CTL
118+
tristate "IMX95 Clock Driver for BLK CTL"
119+
depends on ARCH_MXC || COMPILE_TEST
120+
select MXC_CLK
121+
help
122+
Build the clock driver for i.MX95 BLK CTL
123+
117124
config CLK_IMXRT1050
118125
tristate "IMXRT1050 CCM Clock Driver"
119126
depends on SOC_IMXRT || COMPILE_TEST

drivers/clk/imx/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ obj-$(CONFIG_CLK_IMX8MP) += clk-imx8mp.o clk-imx8mp-audiomix.o
3131
obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
3232

3333
obj-$(CONFIG_CLK_IMX93) += clk-imx93.o
34+
obj-$(CONFIG_CLK_IMX95_BLK_CTL) += clk-imx95-blk-ctl.o
3435

3536
obj-$(CONFIG_MXC_CLK_SCU) += clk-imx-scu.o clk-imx-lpcg-scu.o clk-imx-acm.o
3637
clk-imx-scu-$(CONFIG_CLK_IMX8QXP) += clk-scu.o clk-imx8qxp.o \

drivers/clk/imx/clk-imx8mp-audiomix.c

Lines changed: 134 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,20 @@
77

88
#include <linux/clk-provider.h>
99
#include <linux/device.h>
10+
#include <linux/io.h>
1011
#include <linux/mod_devicetable.h>
1112
#include <linux/module.h>
1213
#include <linux/of.h>
1314
#include <linux/platform_device.h>
15+
#include <linux/pm_runtime.h>
1416

1517
#include <dt-bindings/clock/imx8mp-clock.h>
1618

1719
#include "clk.h"
1820

1921
#define CLKEN0 0x000
2022
#define CLKEN1 0x004
23+
#define EARC 0x200
2124
#define SAI1_MCLK_SEL 0x300
2225
#define SAI2_MCLK_SEL 0x304
2326
#define SAI3_MCLK_SEL 0x308
@@ -26,6 +29,11 @@
2629
#define SAI7_MCLK_SEL 0x314
2730
#define PDM_SEL 0x318
2831
#define SAI_PLL_GNRL_CTL 0x400
32+
#define SAI_PLL_FDIVL_CTL0 0x404
33+
#define SAI_PLL_FDIVL_CTL1 0x408
34+
#define SAI_PLL_SSCG_CTL 0x40C
35+
#define SAI_PLL_MNIT_CTL 0x410
36+
#define IPG_LP_CTRL 0x504
2937

3038
#define SAIn_MCLK1_PARENT(n) \
3139
static const struct clk_parent_data \
@@ -182,26 +190,82 @@ static struct clk_imx8mp_audiomix_sel sels[] = {
182190
CLK_SAIn(7)
183191
};
184192

193+
static const u16 audiomix_regs[] = {
194+
CLKEN0,
195+
CLKEN1,
196+
EARC,
197+
SAI1_MCLK_SEL,
198+
SAI2_MCLK_SEL,
199+
SAI3_MCLK_SEL,
200+
SAI5_MCLK_SEL,
201+
SAI6_MCLK_SEL,
202+
SAI7_MCLK_SEL,
203+
PDM_SEL,
204+
SAI_PLL_GNRL_CTL,
205+
SAI_PLL_FDIVL_CTL0,
206+
SAI_PLL_FDIVL_CTL1,
207+
SAI_PLL_SSCG_CTL,
208+
SAI_PLL_MNIT_CTL,
209+
IPG_LP_CTRL,
210+
};
211+
212+
struct clk_imx8mp_audiomix_priv {
213+
void __iomem *base;
214+
u32 regs_save[ARRAY_SIZE(audiomix_regs)];
215+
216+
/* Must be last */
217+
struct clk_hw_onecell_data clk_data;
218+
};
219+
220+
static void clk_imx8mp_audiomix_save_restore(struct device *dev, bool save)
221+
{
222+
struct clk_imx8mp_audiomix_priv *priv = dev_get_drvdata(dev);
223+
void __iomem *base = priv->base;
224+
int i;
225+
226+
if (save) {
227+
for (i = 0; i < ARRAY_SIZE(audiomix_regs); i++)
228+
priv->regs_save[i] = readl(base + audiomix_regs[i]);
229+
} else {
230+
for (i = 0; i < ARRAY_SIZE(audiomix_regs); i++)
231+
writel(priv->regs_save[i], base + audiomix_regs[i]);
232+
}
233+
}
234+
185235
static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
186236
{
187-
struct clk_hw_onecell_data *priv;
237+
struct clk_imx8mp_audiomix_priv *priv;
238+
struct clk_hw_onecell_data *clk_hw_data;
188239
struct device *dev = &pdev->dev;
189240
void __iomem *base;
190241
struct clk_hw *hw;
191-
int i;
242+
int i, ret;
192243

193244
priv = devm_kzalloc(dev,
194-
struct_size(priv, hws, IMX8MP_CLK_AUDIOMIX_END),
245+
struct_size(priv, clk_data.hws, IMX8MP_CLK_AUDIOMIX_END),
195246
GFP_KERNEL);
196247
if (!priv)
197248
return -ENOMEM;
198249

199-
priv->num = IMX8MP_CLK_AUDIOMIX_END;
250+
clk_hw_data = &priv->clk_data;
251+
clk_hw_data->num = IMX8MP_CLK_AUDIOMIX_END;
200252

201253
base = devm_platform_ioremap_resource(pdev, 0);
202254
if (IS_ERR(base))
203255
return PTR_ERR(base);
204256

257+
priv->base = base;
258+
dev_set_drvdata(dev, priv);
259+
260+
/*
261+
* pm_runtime_enable needs to be called before clk register.
262+
* That is to make core->rpm_enabled to be true for clock
263+
* usage.
264+
*/
265+
pm_runtime_get_noresume(dev);
266+
pm_runtime_set_active(dev);
267+
pm_runtime_enable(dev);
268+
205269
for (i = 0; i < ARRAY_SIZE(sels); i++) {
206270
if (sels[i].num_parents == 1) {
207271
hw = devm_clk_hw_register_gate_parent_data(dev,
@@ -216,10 +280,12 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
216280
0, NULL, NULL);
217281
}
218282

219-
if (IS_ERR(hw))
220-
return PTR_ERR(hw);
283+
if (IS_ERR(hw)) {
284+
ret = PTR_ERR(hw);
285+
goto err_clk_register;
286+
}
221287

222-
priv->hws[sels[i].clkid] = hw;
288+
clk_hw_data->hws[sels[i].clkid] = hw;
223289
}
224290

225291
/* SAI PLL */
@@ -228,39 +294,84 @@ static int clk_imx8mp_audiomix_probe(struct platform_device *pdev)
228294
ARRAY_SIZE(clk_imx8mp_audiomix_pll_parents),
229295
CLK_SET_RATE_NO_REPARENT, base + SAI_PLL_GNRL_CTL,
230296
0, 2, 0, NULL, NULL);
231-
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL] = hw;
297+
clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_REF_SEL] = hw;
232298

233299
hw = imx_dev_clk_hw_pll14xx(dev, "sai_pll", "sai_pll_ref_sel",
234300
base + 0x400, &imx_1443x_pll);
235-
if (IS_ERR(hw))
236-
return PTR_ERR(hw);
237-
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL] = hw;
301+
if (IS_ERR(hw)) {
302+
ret = PTR_ERR(hw);
303+
goto err_clk_register;
304+
}
305+
clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL] = hw;
238306

239307
hw = devm_clk_hw_register_mux_parent_data_table(dev,
240308
"sai_pll_bypass", clk_imx8mp_audiomix_pll_bypass_sels,
241309
ARRAY_SIZE(clk_imx8mp_audiomix_pll_bypass_sels),
242310
CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
243311
base + SAI_PLL_GNRL_CTL, 16, 1, 0, NULL, NULL);
244-
if (IS_ERR(hw))
245-
return PTR_ERR(hw);
246-
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS] = hw;
312+
if (IS_ERR(hw)) {
313+
ret = PTR_ERR(hw);
314+
goto err_clk_register;
315+
}
316+
317+
clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_BYPASS] = hw;
247318

248319
hw = devm_clk_hw_register_gate(dev, "sai_pll_out", "sai_pll_bypass",
249320
0, base + SAI_PLL_GNRL_CTL, 13,
250321
0, NULL);
251-
if (IS_ERR(hw))
252-
return PTR_ERR(hw);
253-
priv->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT] = hw;
322+
if (IS_ERR(hw)) {
323+
ret = PTR_ERR(hw);
324+
goto err_clk_register;
325+
}
326+
clk_hw_data->hws[IMX8MP_CLK_AUDIOMIX_SAI_PLL_OUT] = hw;
254327

255328
hw = devm_clk_hw_register_fixed_factor(dev, "sai_pll_out_div2",
256329
"sai_pll_out", 0, 1, 2);
257-
if (IS_ERR(hw))
258-
return PTR_ERR(hw);
330+
if (IS_ERR(hw)) {
331+
ret = PTR_ERR(hw);
332+
goto err_clk_register;
333+
}
334+
335+
ret = devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
336+
clk_hw_data);
337+
if (ret)
338+
goto err_clk_register;
339+
340+
pm_runtime_put_sync(dev);
341+
return 0;
342+
343+
err_clk_register:
344+
pm_runtime_put_sync(dev);
345+
pm_runtime_disable(dev);
346+
return ret;
347+
}
348+
349+
static void clk_imx8mp_audiomix_remove(struct platform_device *pdev)
350+
{
351+
pm_runtime_disable(&pdev->dev);
352+
}
353+
354+
static int clk_imx8mp_audiomix_runtime_suspend(struct device *dev)
355+
{
356+
clk_imx8mp_audiomix_save_restore(dev, true);
259357

260-
return devm_of_clk_add_hw_provider(&pdev->dev, of_clk_hw_onecell_get,
261-
priv);
358+
return 0;
262359
}
263360

361+
static int clk_imx8mp_audiomix_runtime_resume(struct device *dev)
362+
{
363+
clk_imx8mp_audiomix_save_restore(dev, false);
364+
365+
return 0;
366+
}
367+
368+
static const struct dev_pm_ops clk_imx8mp_audiomix_pm_ops = {
369+
RUNTIME_PM_OPS(clk_imx8mp_audiomix_runtime_suspend,
370+
clk_imx8mp_audiomix_runtime_resume, NULL)
371+
SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
372+
pm_runtime_force_resume)
373+
};
374+
264375
static const struct of_device_id clk_imx8mp_audiomix_of_match[] = {
265376
{ .compatible = "fsl,imx8mp-audio-blk-ctrl" },
266377
{ /* sentinel */ }
@@ -269,9 +380,11 @@ MODULE_DEVICE_TABLE(of, clk_imx8mp_audiomix_of_match);
269380

270381
static struct platform_driver clk_imx8mp_audiomix_driver = {
271382
.probe = clk_imx8mp_audiomix_probe,
383+
.remove_new = clk_imx8mp_audiomix_remove,
272384
.driver = {
273385
.name = "imx8mp-audio-blk-ctrl",
274386
.of_match_table = clk_imx8mp_audiomix_of_match,
387+
.pm = pm_ptr(&clk_imx8mp_audiomix_pm_ops),
275388
},
276389
};
277390

0 commit comments

Comments
 (0)