Skip to content

Commit

Permalink
clk: x86: Add system specific quirk to mark clocks as critical
Browse files Browse the repository at this point in the history
Since commit 648e921 ("clk: x86: Stop marking clocks as
CLK_IS_CRITICAL"), the pmc_plt_clocks of the Bay Trail SoC are
unconditionally gated off. Unfortunately this will break systems where these
clocks are used for external purposes beyond the kernel's knowledge. Fix it
by implementing a system specific quirk to mark the necessary pmc_plt_clks as
critical.

Fixes: 648e921 ("clk: x86: Stop marking clocks as CLK_IS_CRITICAL")
Signed-off-by: David Müller <dave.mueller@gmx.ch>
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
  • Loading branch information
David Müller authored and Stephen Boyd committed Apr 10, 2019
1 parent 9f842ab commit 7c2e071
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 3 deletions.
14 changes: 11 additions & 3 deletions drivers/clk/x86/clk-pmc-atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ static const struct clk_ops plt_clk_ops = {
};

static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
void __iomem *base,
const struct pmc_clk_data *pmc_data,
const char **parent_names,
int num_parents)
{
Expand All @@ -184,9 +184,17 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id,
init.num_parents = num_parents;

pclk->hw.init = &init;
pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
pclk->reg = pmc_data->base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE;
spin_lock_init(&pclk->lock);

/*
* On some systems, the pmc_plt_clocks already enabled by the
* firmware are being marked as critical to avoid them being
* gated by the clock framework.
*/
if (pmc_data->critical && plt_clk_is_enabled(&pclk->hw))
init.flags |= CLK_IS_CRITICAL;

ret = devm_clk_hw_register(&pdev->dev, &pclk->hw);
if (ret) {
pclk = ERR_PTR(ret);
Expand Down Expand Up @@ -332,7 +340,7 @@ static int plt_clk_probe(struct platform_device *pdev)
return PTR_ERR(parent_names);

for (i = 0; i < PMC_CLK_NUM; i++) {
data->clks[i] = plt_clk_register(pdev, i, pmc_data->base,
data->clks[i] = plt_clk_register(pdev, i, pmc_data,
parent_names, data->nparents);
if (IS_ERR(data->clks[i])) {
err = PTR_ERR(data->clks[i]);
Expand Down
21 changes: 21 additions & 0 deletions drivers/platform/x86/pmc_atom.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/platform_data/x86/clk-pmc-atom.h>
Expand Down Expand Up @@ -391,18 +392,38 @@ static int pmc_dbgfs_register(struct pmc_dev *pmc)
}
#endif /* CONFIG_DEBUG_FS */

/*
* Some systems need one or more of their pmc_plt_clks to be
* marked as critical.
*/
static const struct dmi_system_id critclk_systems[] __initconst = {
{
.ident = "MPL CEC1x",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "MPL AG"),
DMI_MATCH(DMI_PRODUCT_NAME, "CEC10 Family"),
},
},
{ /*sentinel*/ }
};

static int pmc_setup_clks(struct pci_dev *pdev, void __iomem *pmc_regmap,
const struct pmc_data *pmc_data)
{
struct platform_device *clkdev;
struct pmc_clk_data *clk_data;
const struct dmi_system_id *d = dmi_first_match(critclk_systems);

clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
if (!clk_data)
return -ENOMEM;

clk_data->base = pmc_regmap; /* offset is added by client */
clk_data->clks = pmc_data->clks;
if (d) {
clk_data->critical = true;
pr_info("%s critclks quirk enabled\n", d->ident);
}

clkdev = platform_device_register_data(&pdev->dev, "clk-pmc-atom",
PLATFORM_DEVID_NONE,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/platform_data/x86/clk-pmc-atom.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@ struct pmc_clk {
*
* @base: PMC clock register base offset
* @clks: pointer to set of registered clocks, typically 0..5
* @critical: flag to indicate if firmware enabled pmc_plt_clks
* should be marked as critial or not
*/
struct pmc_clk_data {
void __iomem *base;
const struct pmc_clk *clks;
bool critical;
};

#endif /* __PLATFORM_DATA_X86_CLK_PMC_ATOM_H */

0 comments on commit 7c2e071

Please sign in to comment.