clk: davinci: psc: allow for dev == NULL
On some davinci SoCs, we need to register the PSC clocks during early boot because they are needed for clocksource/clockevent. These changes allow for dev == NULL because in this case, we won't have a platform device for the clocks. Signed-off-by: David Lechner <david@lechnology.com> Reviewed-by: Sekhar Nori <nsekhar@ti.com> Signed-off-by: Michael Turquette <mturquette@baylibre.com> Link: lkml.kernel.org/r/20180525181150.17873-9-david@lechnology.com
This commit is contained in:
parent
17d8bacf19
commit
043eaa70ad
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/davinci.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/init.h>
|
||||
@ -68,7 +69,7 @@ static const struct davinci_lpsc_clk_info dm355_psc_info[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int dm355_psc_init(struct device *dev, void __iomem *base)
|
||||
int dm355_psc_init(struct device *dev, void __iomem *base)
|
||||
{
|
||||
return davinci_psc_register_clocks(dev, dm355_psc_info, 42, base);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/davinci.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/init.h>
|
||||
@ -86,7 +87,7 @@ static const struct davinci_lpsc_clk_info dm365_psc_info[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int dm365_psc_init(struct device *dev, void __iomem *base)
|
||||
int dm365_psc_init(struct device *dev, void __iomem *base)
|
||||
{
|
||||
return davinci_psc_register_clocks(dev, dm365_psc_info, 52, base);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/davinci.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/init.h>
|
||||
@ -63,7 +64,7 @@ static const struct davinci_lpsc_clk_info dm644x_psc_info[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int dm644x_psc_init(struct device *dev, void __iomem *base)
|
||||
int dm644x_psc_init(struct device *dev, void __iomem *base)
|
||||
{
|
||||
return davinci_psc_register_clocks(dev, dm644x_psc_info, 41, base);
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/davinci.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/init.h>
|
||||
@ -58,7 +59,7 @@ static const struct davinci_lpsc_clk_info dm646x_psc_info[] = {
|
||||
{ }
|
||||
};
|
||||
|
||||
static int dm646x_psc_init(struct device *dev, void __iomem *base)
|
||||
int dm646x_psc_init(struct device *dev, void __iomem *base)
|
||||
{
|
||||
return davinci_psc_register_clocks(dev, dm646x_psc_info, 46, base);
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk/davinci.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/of_address.h>
|
||||
@ -63,7 +64,7 @@ struct davinci_psc_data {
|
||||
|
||||
/**
|
||||
* struct davinci_lpsc_clk - LPSC clock structure
|
||||
* @dev: the device that provides this LPSC
|
||||
* @dev: the device that provides this LPSC or NULL
|
||||
* @hw: clk_hw for the LPSC
|
||||
* @pm_domain: power domain for the LPSC
|
||||
* @genpd_clk: clock reference owned by @pm_domain
|
||||
@ -221,6 +222,7 @@ static void davinci_psc_genpd_detach_dev(struct generic_pm_domain *pm_domain,
|
||||
|
||||
/**
|
||||
* davinci_lpsc_clk_register - register LPSC clock
|
||||
* @dev: the clocks's device or NULL
|
||||
* @name: name of this clock
|
||||
* @parent_name: name of clock's parent
|
||||
* @regmap: PSC MMIO region
|
||||
@ -238,7 +240,7 @@ davinci_lpsc_clk_register(struct device *dev, const char *name,
|
||||
int ret;
|
||||
bool is_on;
|
||||
|
||||
lpsc = devm_kzalloc(dev, sizeof(*lpsc), GFP_KERNEL);
|
||||
lpsc = kzalloc(sizeof(*lpsc), GFP_KERNEL);
|
||||
if (!lpsc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
@ -261,9 +263,15 @@ davinci_lpsc_clk_register(struct device *dev, const char *name,
|
||||
lpsc->pd = pd;
|
||||
lpsc->flags = flags;
|
||||
|
||||
ret = devm_clk_hw_register(dev, &lpsc->hw);
|
||||
if (ret < 0)
|
||||
ret = clk_hw_register(dev, &lpsc->hw);
|
||||
if (ret < 0) {
|
||||
kfree(lpsc);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/* for now, genpd is only registered when using device-tree */
|
||||
if (!dev || !dev->of_node)
|
||||
return lpsc;
|
||||
|
||||
/* genpd attach needs a way to look up this clock */
|
||||
ret = clk_hw_register_clkdev(&lpsc->hw, name, best_dev_name(dev));
|
||||
@ -378,13 +386,15 @@ __davinci_psc_register_clocks(struct device *dev,
|
||||
struct regmap *regmap;
|
||||
int i, ret;
|
||||
|
||||
psc = devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL);
|
||||
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
|
||||
if (!psc)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clks = devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
clks = kmalloc_array(num_clks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_psc;
|
||||
}
|
||||
|
||||
psc->clk_data.clks = clks;
|
||||
psc->clk_data.clk_num = num_clks;
|
||||
@ -396,16 +406,20 @@ __davinci_psc_register_clocks(struct device *dev,
|
||||
for (i = 0; i < num_clks; i++)
|
||||
clks[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
pm_domains = devm_kcalloc(dev, num_clks, sizeof(*pm_domains), GFP_KERNEL);
|
||||
if (!pm_domains)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
pm_domains = kcalloc(num_clks, sizeof(*pm_domains), GFP_KERNEL);
|
||||
if (!pm_domains) {
|
||||
ret = -ENOMEM;
|
||||
goto err_free_clks;
|
||||
}
|
||||
|
||||
psc->pm_data.domains = pm_domains;
|
||||
psc->pm_data.num_domains = num_clks;
|
||||
|
||||
regmap = devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
|
||||
if (IS_ERR(regmap))
|
||||
return ERR_CAST(regmap);
|
||||
regmap = regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
|
||||
if (IS_ERR(regmap)) {
|
||||
ret = PTR_ERR(regmap);
|
||||
goto err_free_pm_domains;
|
||||
}
|
||||
|
||||
for (; info->name; info++) {
|
||||
struct davinci_lpsc_clk *lpsc;
|
||||
@ -423,6 +437,13 @@ __davinci_psc_register_clocks(struct device *dev,
|
||||
pm_domains[info->md] = &lpsc->pm_domain;
|
||||
}
|
||||
|
||||
/*
|
||||
* for now, a reset controller is only registered when there is a device
|
||||
* to associate it with.
|
||||
*/
|
||||
if (!dev)
|
||||
return psc;
|
||||
|
||||
psc->rcdev.ops = &davinci_psc_reset_ops;
|
||||
psc->rcdev.owner = THIS_MODULE;
|
||||
psc->rcdev.dev = dev;
|
||||
@ -436,6 +457,15 @@ __davinci_psc_register_clocks(struct device *dev,
|
||||
dev_warn(dev, "Failed to register reset controller (%d)\n", ret);
|
||||
|
||||
return psc;
|
||||
|
||||
err_free_pm_domains:
|
||||
kfree(pm_domains);
|
||||
err_free_clks:
|
||||
kfree(clks);
|
||||
err_free_psc:
|
||||
kfree(psc);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
int davinci_psc_register_clocks(struct device *dev,
|
||||
|
@ -21,4 +21,9 @@ int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgch
|
||||
int dm644x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
|
||||
int dm646x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
|
||||
|
||||
int dm355_psc_init(struct device *dev, void __iomem *base);
|
||||
int dm365_psc_init(struct device *dev, void __iomem *base);
|
||||
int dm644x_psc_init(struct device *dev, void __iomem *base);
|
||||
int dm646x_psc_init(struct device *dev, void __iomem *base);
|
||||
|
||||
#endif /* __LINUX_CLK_DAVINCI_PLL_H___ */
|
||||
|
Loading…
Reference in New Issue
Block a user