Skip to content

Commit ef38222

Browse files
committed
Merge tag 'samsung-clk-6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux into clk-samsung
Pull Samsung SoC clk drivers updates from Krzysztof Kozlowski: - Exynos850: Add CMU_G3D clock controller for the Mali GPU. This brings new PLLs and few cleanups/simplifications in core Exynos clock controller code, so they can be easier re-used in Exynos850 clock controller driver. New CMU_G3D clock controller needs Devicetree bindings header changes with clock indices which are pulled from Samsung SoC repository. - Extract Exynos5433 (ARM64) clock controller power management code to common driver parts, so later it can be re-used by other Exynos clock controller drivers. This only prepares for such re-usage, which is expected to come later for Exynos850. - Exynos850: make PMU_ALIVE_PCLK clock critical, because it is needed for core block - Power Management Unit. - Cleanup: remove() callback returns void. * tag 'samsung-clk-6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux: clk: samsung: exynos850: Make PMU_ALIVE_PCLK critical clk: samsung: Convert to platform remove callback returning void clk: samsung: exynos5433: Extract PM support to common ARM64 layer clk: samsung: Extract parent clock enabling to common function clk: samsung: Extract clocks registration to common function clk: samsung: exynos850: Add AUD and HSI main gate clocks clk: samsung: exynos850: Implement CMU_G3D domain clk: samsung: clk-pll: Implement pll0818x PLL type clk: samsung: Set dev in samsung_clk_init() clk: samsung: Don't pass reg_base to samsung_clk_register_pll() clk: samsung: Remove np argument from samsung_clk_init() dt-bindings: clock: exynos850: Add AUD and HSI main gate clocks dt-bindings: clock: exynos850: Add Exynos850 CMU_G3D
2 parents fe15c26 + babb3e6 commit ef38222

File tree

18 files changed

+475
-230
lines changed

18 files changed

+475
-230
lines changed

Documentation/devicetree/bindings/clock/samsung,exynos850-clock.yaml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ properties:
3737
- samsung,exynos850-cmu-cmgp
3838
- samsung,exynos850-cmu-core
3939
- samsung,exynos850-cmu-dpu
40+
- samsung,exynos850-cmu-g3d
4041
- samsung,exynos850-cmu-hsi
4142
- samsung,exynos850-cmu-is
4243
- samsung,exynos850-cmu-mfcmscl
@@ -169,6 +170,24 @@ allOf:
169170
- const: oscclk
170171
- const: dout_dpu
171172

173+
- if:
174+
properties:
175+
compatible:
176+
contains:
177+
const: samsung,exynos850-cmu-g3d
178+
179+
then:
180+
properties:
181+
clocks:
182+
items:
183+
- description: External reference clock (26 MHz)
184+
- description: G3D clock (from CMU_TOP)
185+
186+
clock-names:
187+
items:
188+
- const: oscclk
189+
- const: dout_g3d_switch
190+
172191
- if:
173192
properties:
174193
compatible:

drivers/clk/samsung/clk-exynos-arm64.c

Lines changed: 213 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
*/
1111
#include <linux/clk.h>
1212
#include <linux/of_address.h>
13+
#include <linux/of_device.h>
14+
#include <linux/pm_runtime.h>
15+
#include <linux/slab.h>
1316

1417
#include "clk-exynos-arm64.h"
1518

@@ -21,6 +24,19 @@
2124
#define GATE_OFF_START 0x2000
2225
#define GATE_OFF_END 0x2fff
2326

27+
struct exynos_arm64_cmu_data {
28+
struct samsung_clk_reg_dump *clk_save;
29+
unsigned int nr_clk_save;
30+
const struct samsung_clk_reg_dump *clk_suspend;
31+
unsigned int nr_clk_suspend;
32+
33+
struct clk *clk;
34+
struct clk **pclks;
35+
int nr_pclks;
36+
37+
struct samsung_clk_provider *ctx;
38+
};
39+
2440
/**
2541
* exynos_arm64_init_clocks - Set clocks initial configuration
2642
* @np: CMU device tree node with "reg" property (CMU addr)
@@ -56,6 +72,83 @@ static void __init exynos_arm64_init_clocks(struct device_node *np,
5672
iounmap(reg_base);
5773
}
5874

75+
/**
76+
* exynos_arm64_enable_bus_clk - Enable parent clock of specified CMU
77+
*
78+
* @dev: Device object; may be NULL if this function is not being
79+
* called from platform driver probe function
80+
* @np: CMU device tree node
81+
* @cmu: CMU data
82+
*
83+
* Keep CMU parent clock running (needed for CMU registers access).
84+
*
85+
* Return: 0 on success or a negative error code on failure.
86+
*/
87+
static int __init exynos_arm64_enable_bus_clk(struct device *dev,
88+
struct device_node *np, const struct samsung_cmu_info *cmu)
89+
{
90+
struct clk *parent_clk;
91+
92+
if (!cmu->clk_name)
93+
return 0;
94+
95+
if (dev) {
96+
struct exynos_arm64_cmu_data *data;
97+
98+
parent_clk = clk_get(dev, cmu->clk_name);
99+
data = dev_get_drvdata(dev);
100+
if (data)
101+
data->clk = parent_clk;
102+
} else {
103+
parent_clk = of_clk_get_by_name(np, cmu->clk_name);
104+
}
105+
106+
if (IS_ERR(parent_clk))
107+
return PTR_ERR(parent_clk);
108+
109+
return clk_prepare_enable(parent_clk);
110+
}
111+
112+
static int __init exynos_arm64_cmu_prepare_pm(struct device *dev,
113+
const struct samsung_cmu_info *cmu)
114+
{
115+
struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
116+
int i;
117+
118+
data->clk_save = samsung_clk_alloc_reg_dump(cmu->clk_regs,
119+
cmu->nr_clk_regs);
120+
if (!data->clk_save)
121+
return -ENOMEM;
122+
123+
data->nr_clk_save = cmu->nr_clk_regs;
124+
data->clk_suspend = cmu->suspend_regs;
125+
data->nr_clk_suspend = cmu->nr_suspend_regs;
126+
data->nr_pclks = of_clk_get_parent_count(dev->of_node);
127+
if (!data->nr_pclks)
128+
return 0;
129+
130+
data->pclks = devm_kcalloc(dev, sizeof(struct clk *), data->nr_pclks,
131+
GFP_KERNEL);
132+
if (!data->pclks) {
133+
kfree(data->clk_save);
134+
return -ENOMEM;
135+
}
136+
137+
for (i = 0; i < data->nr_pclks; i++) {
138+
struct clk *clk = of_clk_get(dev->of_node, i);
139+
140+
if (IS_ERR(clk)) {
141+
kfree(data->clk_save);
142+
while (--i >= 0)
143+
clk_put(data->pclks[i]);
144+
return PTR_ERR(clk);
145+
}
146+
data->pclks[i] = clk;
147+
}
148+
149+
return 0;
150+
}
151+
59152
/**
60153
* exynos_arm64_register_cmu - Register specified Exynos CMU domain
61154
* @dev: Device object; may be NULL if this function is not being
@@ -72,23 +165,127 @@ static void __init exynos_arm64_init_clocks(struct device_node *np,
72165
void __init exynos_arm64_register_cmu(struct device *dev,
73166
struct device_node *np, const struct samsung_cmu_info *cmu)
74167
{
75-
/* Keep CMU parent clock running (needed for CMU registers access) */
76-
if (cmu->clk_name) {
77-
struct clk *parent_clk;
78-
79-
if (dev)
80-
parent_clk = clk_get(dev, cmu->clk_name);
81-
else
82-
parent_clk = of_clk_get_by_name(np, cmu->clk_name);
83-
84-
if (IS_ERR(parent_clk)) {
85-
pr_err("%s: could not find bus clock %s; err = %ld\n",
86-
__func__, cmu->clk_name, PTR_ERR(parent_clk));
87-
} else {
88-
clk_prepare_enable(parent_clk);
89-
}
90-
}
168+
int err;
169+
170+
/*
171+
* Try to boot even if the parent clock enablement fails, as it might be
172+
* already enabled by bootloader.
173+
*/
174+
err = exynos_arm64_enable_bus_clk(dev, np, cmu);
175+
if (err)
176+
pr_err("%s: could not enable bus clock %s; err = %d\n",
177+
__func__, cmu->clk_name, err);
91178

92179
exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs);
93180
samsung_cmu_register_one(np, cmu);
94181
}
182+
183+
/**
184+
* exynos_arm64_register_cmu_pm - Register Exynos CMU domain with PM support
185+
*
186+
* @pdev: Platform device object
187+
* @set_manual: If true, set gate clocks to manual mode
188+
*
189+
* It's a version of exynos_arm64_register_cmu() with PM support. Should be
190+
* called from probe function of platform driver.
191+
*
192+
* Return: 0 on success, or negative error code on error.
193+
*/
194+
int __init exynos_arm64_register_cmu_pm(struct platform_device *pdev,
195+
bool set_manual)
196+
{
197+
const struct samsung_cmu_info *cmu;
198+
struct device *dev = &pdev->dev;
199+
struct device_node *np = dev->of_node;
200+
struct exynos_arm64_cmu_data *data;
201+
void __iomem *reg_base;
202+
int ret;
203+
204+
cmu = of_device_get_match_data(dev);
205+
206+
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
207+
if (!data)
208+
return -ENOMEM;
209+
210+
platform_set_drvdata(pdev, data);
211+
212+
ret = exynos_arm64_cmu_prepare_pm(dev, cmu);
213+
if (ret)
214+
return ret;
215+
216+
/*
217+
* Try to boot even if the parent clock enablement fails, as it might be
218+
* already enabled by bootloader.
219+
*/
220+
ret = exynos_arm64_enable_bus_clk(dev, NULL, cmu);
221+
if (ret)
222+
dev_err(dev, "%s: could not enable bus clock %s; err = %d\n",
223+
__func__, cmu->clk_name, ret);
224+
225+
if (set_manual)
226+
exynos_arm64_init_clocks(np, cmu->clk_regs, cmu->nr_clk_regs);
227+
228+
reg_base = devm_platform_ioremap_resource(pdev, 0);
229+
if (IS_ERR(reg_base))
230+
return PTR_ERR(reg_base);
231+
232+
data->ctx = samsung_clk_init(dev, reg_base, cmu->nr_clk_ids);
233+
234+
/*
235+
* Enable runtime PM here to allow the clock core using runtime PM
236+
* for the registered clocks. Additionally, we increase the runtime
237+
* PM usage count before registering the clocks, to prevent the
238+
* clock core from runtime suspending the device.
239+
*/
240+
pm_runtime_get_noresume(dev);
241+
pm_runtime_set_active(dev);
242+
pm_runtime_enable(dev);
243+
244+
samsung_cmu_register_clocks(data->ctx, cmu);
245+
samsung_clk_of_add_provider(dev->of_node, data->ctx);
246+
pm_runtime_put_sync(dev);
247+
248+
return 0;
249+
}
250+
251+
int exynos_arm64_cmu_suspend(struct device *dev)
252+
{
253+
struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
254+
int i;
255+
256+
samsung_clk_save(data->ctx->reg_base, data->clk_save,
257+
data->nr_clk_save);
258+
259+
for (i = 0; i < data->nr_pclks; i++)
260+
clk_prepare_enable(data->pclks[i]);
261+
262+
/* For suspend some registers have to be set to certain values */
263+
samsung_clk_restore(data->ctx->reg_base, data->clk_suspend,
264+
data->nr_clk_suspend);
265+
266+
for (i = 0; i < data->nr_pclks; i++)
267+
clk_disable_unprepare(data->pclks[i]);
268+
269+
clk_disable_unprepare(data->clk);
270+
271+
return 0;
272+
}
273+
274+
int exynos_arm64_cmu_resume(struct device *dev)
275+
{
276+
struct exynos_arm64_cmu_data *data = dev_get_drvdata(dev);
277+
int i;
278+
279+
clk_prepare_enable(data->clk);
280+
281+
for (i = 0; i < data->nr_pclks; i++)
282+
clk_prepare_enable(data->pclks[i]);
283+
284+
samsung_clk_restore(data->ctx->reg_base, data->clk_save,
285+
data->nr_clk_save);
286+
287+
for (i = 0; i < data->nr_pclks; i++)
288+
clk_disable_unprepare(data->pclks[i]);
289+
290+
return 0;
291+
}

drivers/clk/samsung/clk-exynos-arm64.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,8 @@
1616

1717
void exynos_arm64_register_cmu(struct device *dev,
1818
struct device_node *np, const struct samsung_cmu_info *cmu);
19+
int exynos_arm64_register_cmu_pm(struct platform_device *pdev, bool set_manual);
20+
int exynos_arm64_cmu_suspend(struct device *dev);
21+
int exynos_arm64_cmu_resume(struct device *dev);
1922

2023
#endif /* __CLK_EXYNOS_ARM64_H */

drivers/clk/samsung/clk-exynos-audss.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev)
268268
return ret;
269269
}
270270

271-
static int exynos_audss_clk_remove(struct platform_device *pdev)
271+
static void exynos_audss_clk_remove(struct platform_device *pdev)
272272
{
273273
of_clk_del_provider(pdev->dev.of_node);
274274

@@ -277,8 +277,6 @@ static int exynos_audss_clk_remove(struct platform_device *pdev)
277277

278278
if (!IS_ERR(epll))
279279
clk_disable_unprepare(epll);
280-
281-
return 0;
282280
}
283281

284282
static const struct dev_pm_ops exynos_audss_clk_pm_ops = {
@@ -295,7 +293,7 @@ static struct platform_driver exynos_audss_clk_driver = {
295293
.pm = &exynos_audss_clk_pm_ops,
296294
},
297295
.probe = exynos_audss_clk_probe,
298-
.remove = exynos_audss_clk_remove,
296+
.remove_new = exynos_audss_clk_remove,
299297
};
300298

301299
module_platform_driver(exynos_audss_clk_driver);

drivers/clk/samsung/clk-exynos-clkout.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,13 @@ static int exynos_clkout_probe(struct platform_device *pdev)
196196
return ret;
197197
}
198198

199-
static int exynos_clkout_remove(struct platform_device *pdev)
199+
static void exynos_clkout_remove(struct platform_device *pdev)
200200
{
201201
struct exynos_clkout *clkout = platform_get_drvdata(pdev);
202202

203203
of_clk_del_provider(clkout->np);
204204
clk_hw_unregister(clkout->data.hws[0]);
205205
iounmap(clkout->reg);
206-
207-
return 0;
208206
}
209207

210208
static int __maybe_unused exynos_clkout_suspend(struct device *dev)
@@ -235,7 +233,7 @@ static struct platform_driver exynos_clkout_driver = {
235233
.pm = &exynos_clkout_pm_ops,
236234
},
237235
.probe = exynos_clkout_probe,
238-
.remove = exynos_clkout_remove,
236+
.remove_new = exynos_clkout_remove,
239237
};
240238
module_platform_driver(exynos_clkout_driver);
241239

drivers/clk/samsung/clk-exynos4.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,7 +1251,7 @@ static void __init exynos4_clk_init(struct device_node *np,
12511251
if (!reg_base)
12521252
panic("%s: failed to map registers\n", __func__);
12531253

1254-
ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS);
1254+
ctx = samsung_clk_init(NULL, reg_base, CLK_NR_CLKS);
12551255
hws = ctx->clk_data.hws;
12561256

12571257
samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks,
@@ -1276,7 +1276,7 @@ static void __init exynos4_clk_init(struct device_node *np,
12761276
exynos4210_vpll_rates;
12771277

12781278
samsung_clk_register_pll(ctx, exynos4210_plls,
1279-
ARRAY_SIZE(exynos4210_plls), reg_base);
1279+
ARRAY_SIZE(exynos4210_plls));
12801280
} else {
12811281
if (clk_hw_get_rate(hws[CLK_FIN_PLL]) == 24000000) {
12821282
exynos4x12_plls[apll].rate_table =
@@ -1288,7 +1288,7 @@ static void __init exynos4_clk_init(struct device_node *np,
12881288
}
12891289

12901290
samsung_clk_register_pll(ctx, exynos4x12_plls,
1291-
ARRAY_SIZE(exynos4x12_plls), reg_base);
1291+
ARRAY_SIZE(exynos4x12_plls));
12921292
}
12931293

12941294
samsung_clk_register_fixed_rate(ctx, exynos4_fixed_rate_clks,

drivers/clk/samsung/clk-exynos4412-isp.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ static int __init exynos4x12_isp_clk_probe(struct platform_device *pdev)
121121
if (!exynos4x12_save_isp)
122122
return -ENOMEM;
123123

124-
ctx = samsung_clk_init(np, reg_base, CLK_NR_ISP_CLKS);
125-
ctx->dev = dev;
124+
ctx = samsung_clk_init(dev, reg_base, CLK_NR_ISP_CLKS);
126125

127126
platform_set_drvdata(pdev, ctx);
128127

0 commit comments

Comments
 (0)