]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.0/clk-x86-add-system-specific-quirk-to-mark-clocks-as-critical.patch
Linux 4.19.41
[thirdparty/kernel/stable-queue.git] / queue-5.0 / clk-x86-add-system-specific-quirk-to-mark-clocks-as-critical.patch
1 From 7c2e07130090ae001a97a6b65597830d6815e93e Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?David=20M=C3=BCller?= <dave.mueller@gmx.ch>
3 Date: Mon, 8 Apr 2019 15:33:54 +0200
4 Subject: clk: x86: Add system specific quirk to mark clocks as critical
5 MIME-Version: 1.0
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
8
9 From: David Müller <dave.mueller@gmx.ch>
10
11 commit 7c2e07130090ae001a97a6b65597830d6815e93e upstream.
12
13 Since commit 648e921888ad ("clk: x86: Stop marking clocks as
14 CLK_IS_CRITICAL"), the pmc_plt_clocks of the Bay Trail SoC are
15 unconditionally gated off. Unfortunately this will break systems where these
16 clocks are used for external purposes beyond the kernel's knowledge. Fix it
17 by implementing a system specific quirk to mark the necessary pmc_plt_clks as
18 critical.
19
20 Fixes: 648e921888ad ("clk: x86: Stop marking clocks as CLK_IS_CRITICAL")
21 Signed-off-by: David Müller <dave.mueller@gmx.ch>
22 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
23 Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
24 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
25 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
26
27 ---
28 drivers/clk/x86/clk-pmc-atom.c | 14 +++++++++++---
29 drivers/platform/x86/pmc_atom.c | 21 +++++++++++++++++++++
30 include/linux/platform_data/x86/clk-pmc-atom.h | 3 +++
31 3 files changed, 35 insertions(+), 3 deletions(-)
32
33 --- a/drivers/clk/x86/clk-pmc-atom.c
34 +++ b/drivers/clk/x86/clk-pmc-atom.c
35 @@ -165,7 +165,7 @@ static const struct clk_ops plt_clk_ops
36 };
37
38 static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
39 - void __iomem *base,
40 + const struct pmc_clk_data *pmc_data,
41 const char **parent_names,
42 int num_parents)
43 {
44 @@ -184,9 +184,17 @@ static struct clk_plt *plt_clk_register(
45 init.num_parents = num_parents;
46
47 pclk->hw.init = &init;
48 - pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
49 + pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
50 spin_lock_init(&pclk->lock);
51
52 + /*
53 + * On some systems, the pmc_plt_clocks already enabled by the
54 + * firmware are being marked as critical to avoid them being
55 + * gated by the clock framework.
56 + */
57 + if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw))
58 + init.flags |= CLK_IS_CRITICAL;
59 +
60 ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
61 if (ret) {
62 pclk = ERR_PTR(ret);
63 @@ -332,7 +340,7 @@ static int plt_clk_probe(struct platform
64 return PTR_ERR(parent_names);
65
66 for (i = 0; i < PMC_CLK_NUM; i++) {
67 - data->clks[i] = plt_clk_register(pdev, i, pmc_data->base,
68 + data->clks[i] = plt_clk_register(pdev, i, pmc_data,
69 parent_names, data->nparents);
70 if (IS_ERR(data->clks[i])) {
71 err = PTR_ERR(data->clks[i]);
72 --- a/drivers/platform/x86/pmc_atom.c
73 +++ b/drivers/platform/x86/pmc_atom.c
74 @@ -17,6 +17,7 @@
75
76 #include <linux/debugfs.h>
77 #include <linux/device.h>
78 +#include <linux/dmi.h>
79 #include <linux/init.h>
80 #include <linux/io.h>
81 #include <linux/platform_data/x86/clk-pmc-atom.h>
82 @@ -391,11 +392,27 @@ static int pmc_dbgfs_register(struct pmc
83 }
84 #endif /* CONFIG_DEBUG_FS */
85
86 +/*
87 + * Some systems need one or more of their pmc_plt_clks to be
88 + * marked as critical.
89 + */
90 +static const struct dmi_system_id critclk_systems[] __initconst = {
91 + {
92 + .ident = "MPL CEC1x",
93 + .matches = {
94 + DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"),
95 + DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"),
96 + },
97 + },
98 + { /*sentinel*/ }
99 +};
100 +
101 static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,
102 const struct pmc_data *pmc_data)
103 {
104 struct platform_device *clkdev;
105 struct pmc_clk_data *clk_data;
106 + const struct dmi_system_id *d = dmi_first_match(critclk_systems);
107
108 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
109 if (!clk_data)
110 @@ -403,6 +420,10 @@ static int pmc_setup_clks(struct pci_dev
111
112 clk_data->base = pmc_regmap; /* offset is added by client */
113 clk_data->clks = pmc_data->clks;
114 + if (d) {
115 + clk_data->critical = true;
116 + pr_info("%s critclks quirk enabled\n", d->ident);
117 + }
118
119 clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom",
120 PLATFORM_DEVID_NONE,
121 --- a/include/linux/platform_data/x86/clk-pmc-atom.h
122 +++ b/include/linux/platform_data/x86/clk-pmc-atom.h
123 @@ -35,10 +35,13 @@ struct pmc_clk {
124 *
125 * @base: PMC clock register base offset
126 * @clks: pointer to set of registered clocks, typically 0..5
127 + * @critical: flag to indicate if firmware enabled pmc_plt_clks
128 + * should be marked as critial or not
129 */
130 struct pmc_clk_data {
131 void __iomem *base;
132 const struct pmc_clk *clks;
133 + bool critical;
134 };
135
136 #endif /* __PLATFORM_DATA_X86_CLK_PMC_ATOM_H */