diff mbox

[v9,03/27] clk: davinci: psc: allow for dev == NULL

Message ID 20180427001745.4116-4-david@lechnology.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

David Lechner April 27, 2018, 12:17 a.m. UTC
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>
---

v9 changes:
- new patch in v9


 drivers/clk/davinci/psc-dm355.c  |  2 +-
 drivers/clk/davinci/psc-dm365.c  |  2 +-
 drivers/clk/davinci/psc-dm644x.c |  2 +-
 drivers/clk/davinci/psc-dm646x.c |  2 +-
 drivers/clk/davinci/psc.c        | 70 ++++++++++++++++++++++++++++----
 include/linux/clk/davinci.h      |  5 +++
 6 files changed, 72 insertions(+), 11 deletions(-)

Comments

Sekhar Nori May 1, 2018, 2:02 p.m. UTC | #1
On Friday 27 April 2018 05:47 AM, David Lechner wrote:
> +static inline void *_devm_kzalloc(struct device *dev, size_t size, gfp_t flags)
> +{
> +	if (dev)
> +		return devm_kzalloc(dev, size, flags);
> +
> +	return kzalloc(size, flags);
> +}

I have the same question on the utility of this. A memory allocation
error so early on is not going to result in a bootable system anyway.
So, I wonder if its better to just BUG() in such cases. That will
actually help faster debug than returning an error back. I know the push
back on using BUG(), but clock drivers are special, and I think thats
why its seems to be used quite a bit already.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
David Lechner May 2, 2018, 1:49 a.m. UTC | #2
On 05/01/2018 09:02 AM, Sekhar Nori wrote:
> On Friday 27 April 2018 05:47 AM, David Lechner wrote:
>> +static inline void *_devm_kzalloc(struct device *dev, size_t size, gfp_t flags)
>> +{
>> +	if (dev)
>> +		return devm_kzalloc(dev, size, flags);
>> +
>> +	return kzalloc(size, flags);
>> +}
> 
> I have the same question on the utility of this. A memory allocation
> error so early on is not going to result in a bootable system anyway.
> So, I wonder if its better to just BUG() in such cases. That will
> actually help faster debug than returning an error back. I know the push
> back on using BUG(), but clock drivers are special, and I think thats
> why its seems to be used quite a bit already.
> 

Same reply here as well. On DA850/DA830, you might not get a console,
but you will "boot" even if one of the PSC devices fails though.

WARN() is probably just as good as BUG() in this case too.


--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sekhar Nori May 2, 2018, 3:08 p.m. UTC | #3
On Wednesday 02 May 2018 07:19 AM, David Lechner wrote:
> On 05/01/2018 09:02 AM, Sekhar Nori wrote:
>> On Friday 27 April 2018 05:47 AM, David Lechner wrote:
>>> +static inline void *_devm_kzalloc(struct device *dev, size_t size,
>>> gfp_t flags)
>>> +{
>>> +    if (dev)
>>> +        return devm_kzalloc(dev, size, flags);
>>> +
>>> +    return kzalloc(size, flags);
>>> +}
>>
>> I have the same question on the utility of this. A memory allocation
>> error so early on is not going to result in a bootable system anyway.
>> So, I wonder if its better to just BUG() in such cases. That will
>> actually help faster debug than returning an error back. I know the push
>> back on using BUG(), but clock drivers are special, and I think thats
>> why its seems to be used quite a bit already.
>>
> 
> Same reply here as well. On DA850/DA830, you might not get a console,
> but you will "boot" even if one of the PSC devices fails though.

Was not thinking of failure to boot due to clocks being disabled, but
the fact that you are not able to allocate a small amount of memory so
early in boot process. The chances of successful boot after memory
allocation failures like that are close to zero.

> WARN() is probably just as good as BUG() in this case too.

Okay, but with WARN() you would continue to proceed to try to boot which
is not going to be much fruitful (and might actually muddle the first
failure). But up to you on this.

Thanks,
Sekhar
--
To unsubscribe from this list: send the line "unsubscribe linux-clk" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/clk/davinci/psc-dm355.c b/drivers/clk/davinci/psc-dm355.c
index 6995ecea2677..001288dfdfb1 100644
--- a/drivers/clk/davinci/psc-dm355.c
+++ b/drivers/clk/davinci/psc-dm355.c
@@ -68,7 +68,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);
 }
diff --git a/drivers/clk/davinci/psc-dm365.c b/drivers/clk/davinci/psc-dm365.c
index 3ad915f37376..5b5b55b0b59a 100644
--- a/drivers/clk/davinci/psc-dm365.c
+++ b/drivers/clk/davinci/psc-dm365.c
@@ -73,7 +73,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);
 }
diff --git a/drivers/clk/davinci/psc-dm644x.c b/drivers/clk/davinci/psc-dm644x.c
index c22367baa46f..74668931be48 100644
--- a/drivers/clk/davinci/psc-dm644x.c
+++ b/drivers/clk/davinci/psc-dm644x.c
@@ -63,7 +63,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);
 }
diff --git a/drivers/clk/davinci/psc-dm646x.c b/drivers/clk/davinci/psc-dm646x.c
index 468ef86ea40b..22473affa7cf 100644
--- a/drivers/clk/davinci/psc-dm646x.c
+++ b/drivers/clk/davinci/psc-dm646x.c
@@ -58,7 +58,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);
 }
diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
index ce170e600f09..1d4bcdd6bba0 100644
--- a/drivers/clk/davinci/psc.c
+++ b/drivers/clk/davinci/psc.c
@@ -63,7 +63,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
@@ -86,6 +86,50 @@  struct davinci_lpsc_clk {
 #define to_davinci_psc_data(x) container_of(x, struct davinci_psc_data, x)
 #define to_davinci_lpsc_clk(x) container_of(x, struct davinci_lpsc_clk, x)
 
+static inline void *_devm_kzalloc(struct device *dev, size_t size, gfp_t flags)
+{
+	if (dev)
+		return devm_kzalloc(dev, size, flags);
+
+	return kzalloc(size, flags);
+}
+
+static inline void *_devm_kcalloc(struct device *dev, size_t n, size_t size,
+				  gfp_t flags)
+{
+	if (dev)
+		return devm_kcalloc(dev, n, size, flags);
+
+	return kcalloc(n, size, flags);
+}
+
+static inline void *_devm_kmalloc_array(struct device *dev, size_t n,
+					size_t size, gfp_t flags)
+{
+	if (dev)
+		return devm_kmalloc_array(dev, n, size, flags);
+
+	return kmalloc_array(n, size, flags);
+}
+
+static inline int _devm_clk_hw_register(struct device *dev, struct clk_hw *hw)
+{
+	if (dev)
+		return devm_clk_hw_register(dev, hw);
+
+	return clk_hw_register(NULL, hw);
+}
+
+static inline struct regmap
+*_devm_regmap_init_mmio(struct device *dev, void __iomem *regs,
+			const struct regmap_config *config)
+{
+	if (dev)
+		return devm_regmap_init_mmio(dev, regs, config);
+
+	return regmap_init_mmio(NULL, regs, config);
+}
+
 /**
  * best_dev_name - get the "best" device name.
  * @dev: the device
@@ -221,6 +265,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 +283,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 = _devm_kzalloc(dev, sizeof(*lpsc), GFP_KERNEL);
 	if (!lpsc)
 		return ERR_PTR(-ENOMEM);
 
@@ -261,10 +306,14 @@  davinci_lpsc_clk_register(struct device *dev, const char *name,
 	lpsc->pd = pd;
 	lpsc->flags = flags;
 
-	ret = devm_clk_hw_register(dev, &lpsc->hw);
+	ret = _devm_clk_hw_register(dev, &lpsc->hw);
 	if (ret < 0)
 		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,11 +427,11 @@  __davinci_psc_register_clocks(struct device *dev,
 	struct regmap *regmap;
 	int i, ret;
 
-	psc = devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL);
+	psc = _devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL);
 	if (!psc)
 		return ERR_PTR(-ENOMEM);
 
-	clks = devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL);
+	clks = _devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL);
 	if (!clks)
 		return ERR_PTR(-ENOMEM);
 
@@ -396,14 +445,14 @@  __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);
+	pm_domains = _devm_kcalloc(dev, num_clks, sizeof(*pm_domains), GFP_KERNEL);
 	if (!pm_domains)
 		return ERR_PTR(-ENOMEM);
 
 	psc->pm_data.domains = pm_domains;
 	psc->pm_data.num_domains = num_clks;
 
-	regmap = devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
+	regmap = _devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
 	if (IS_ERR(regmap))
 		return ERR_CAST(regmap);
 
@@ -423,6 +472,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;
diff --git a/include/linux/clk/davinci.h b/include/linux/clk/davinci.h
index 1298cca509ac..b32dd3f53ecc 100644
--- a/include/linux/clk/davinci.h
+++ b/include/linux/clk/davinci.h
@@ -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___ */