Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 043eaa70 authored by David Lechner's avatar David Lechner Committed by Michael Turquette
Browse files

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: default avatarDavid Lechner <david@lechnology.com>
Reviewed-by: default avatarSekhar Nori <nsekhar@ti.com>
Signed-off-by: default avatarMichael Turquette <mturquette@baylibre.com>
Link: lkml.kernel.org/r/20180525181150.17873-9-david@lechnology.com
parent 17d8bacf
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);
}
+2 −1
Original line number Diff line number Diff line
@@ -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);
}
+2 −1
Original line number Diff line number Diff line
@@ -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);
}
+2 −1
Original line number Diff line number Diff line
@@ -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);
}
+44 −14
Original line number Diff line number Diff line
@@ -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,
Loading