Merge branches 'clk-tegra' and 'clk-bulk-get-all' into clk-next
- Nvidia Tegra clk driver MBIST workaround fix - clk_bulk_get_all() API and friends to get all the clks for a device * clk-tegra: clk: tegra210: Include size.h for compilation ease clk: tegra: Fixes for MBIST work around clk: tegra: probe deferral error reporting * clk-bulk-get-all: clk: add managed version of clk_bulk_get_all clk: add new APIs to operate on all available clocks clk: bulk: add of_clk_bulk_get()
This commit is contained in:
commit
c1f74dbe59
@ -17,8 +17,65 @@
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
|
||||
struct clk_bulk_data *clks)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_clks; i++)
|
||||
clks[i].clk = NULL;
|
||||
|
||||
for (i = 0; i < num_clks; i++) {
|
||||
clks[i].clk = of_clk_get(np, i);
|
||||
if (IS_ERR(clks[i].clk)) {
|
||||
ret = PTR_ERR(clks[i].clk);
|
||||
pr_err("%pOF: Failed to get clk index: %d ret: %d\n",
|
||||
np, i, ret);
|
||||
clks[i].clk = NULL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
clk_bulk_put(i, clks);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __must_check of_clk_bulk_get_all(struct device_node *np,
|
||||
struct clk_bulk_data **clks)
|
||||
{
|
||||
struct clk_bulk_data *clk_bulk;
|
||||
int num_clks;
|
||||
int ret;
|
||||
|
||||
num_clks = of_clk_get_parent_count(np);
|
||||
if (!num_clks)
|
||||
return 0;
|
||||
|
||||
clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
|
||||
if (!clk_bulk)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = of_clk_bulk_get(np, num_clks, clk_bulk);
|
||||
if (ret) {
|
||||
kfree(clk_bulk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
*clks = clk_bulk;
|
||||
|
||||
return num_clks;
|
||||
}
|
||||
|
||||
void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
|
||||
{
|
||||
@ -59,6 +116,29 @@ err:
|
||||
}
|
||||
EXPORT_SYMBOL(clk_bulk_get);
|
||||
|
||||
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
|
||||
{
|
||||
if (IS_ERR_OR_NULL(clks))
|
||||
return;
|
||||
|
||||
clk_bulk_put(num_clks, clks);
|
||||
|
||||
kfree(clks);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_bulk_put_all);
|
||||
|
||||
int __must_check clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks)
|
||||
{
|
||||
struct device_node *np = dev_of_node(dev);
|
||||
|
||||
if (!np)
|
||||
return 0;
|
||||
|
||||
return of_clk_bulk_get_all(np, clks);
|
||||
}
|
||||
EXPORT_SYMBOL(clk_bulk_get_all);
|
||||
|
||||
#ifdef CONFIG_HAVE_CLK_PREPARE
|
||||
|
||||
/**
|
||||
|
@ -70,6 +70,30 @@ int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_bulk_get);
|
||||
|
||||
int __must_check devm_clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks)
|
||||
{
|
||||
struct clk_bulk_devres *devres;
|
||||
int ret;
|
||||
|
||||
devres = devres_alloc(devm_clk_bulk_release,
|
||||
sizeof(*devres), GFP_KERNEL);
|
||||
if (!devres)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = clk_bulk_get_all(dev, &devres->clks);
|
||||
if (ret > 0) {
|
||||
*clks = devres->clks;
|
||||
devres->num_clks = ret;
|
||||
devres_add(dev, devres);
|
||||
} else {
|
||||
devres_free(devres);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
|
||||
|
||||
static int devm_clk_match(struct device *dev, void *res, void *data)
|
||||
{
|
||||
struct clk **c = res;
|
||||
|
@ -1609,8 +1609,12 @@ int tegra_dfll_register(struct platform_device *pdev,
|
||||
|
||||
td->vdd_reg = devm_regulator_get(td->dev, "vdd-cpu");
|
||||
if (IS_ERR(td->vdd_reg)) {
|
||||
dev_err(td->dev, "couldn't get vdd_cpu regulator\n");
|
||||
return PTR_ERR(td->vdd_reg);
|
||||
ret = PTR_ERR(td->vdd_reg);
|
||||
if (ret != -EPROBE_DEFER)
|
||||
dev_err(td->dev, "couldn't get vdd_cpu regulator: %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
td->dvco_rst = devm_reset_control_get(td->dev, "dvco");
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <dt-bindings/clock/tegra210-car.h>
|
||||
#include <dt-bindings/reset/tegra210-car.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/sizes.h>
|
||||
#include <soc/tegra/pmc.h>
|
||||
|
||||
#include "clk.h"
|
||||
@ -2603,7 +2604,7 @@ static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = {
|
||||
[TEGRA_POWERGATE_MPE] = {
|
||||
.handle_lvl2_ovr = tegra210_generic_mbist_war,
|
||||
.lvl2_offset = LVL2_CLK_GATE_OVRE,
|
||||
.lvl2_mask = BIT(2),
|
||||
.lvl2_mask = BIT(29),
|
||||
},
|
||||
[TEGRA_POWERGATE_SOR] = {
|
||||
.handle_lvl2_ovr = tegra210_generic_mbist_war,
|
||||
@ -2654,14 +2655,14 @@ static struct tegra210_domain_mbist_war tegra210_pg_mbist_war[] = {
|
||||
.num_clks = ARRAY_SIZE(nvdec_slcg_clkids),
|
||||
.clk_init_data = nvdec_slcg_clkids,
|
||||
.handle_lvl2_ovr = tegra210_generic_mbist_war,
|
||||
.lvl2_offset = LVL2_CLK_GATE_OVRC,
|
||||
.lvl2_offset = LVL2_CLK_GATE_OVRE,
|
||||
.lvl2_mask = BIT(9) | BIT(31),
|
||||
},
|
||||
[TEGRA_POWERGATE_NVJPG] = {
|
||||
.num_clks = ARRAY_SIZE(nvjpg_slcg_clkids),
|
||||
.clk_init_data = nvjpg_slcg_clkids,
|
||||
.handle_lvl2_ovr = tegra210_generic_mbist_war,
|
||||
.lvl2_offset = LVL2_CLK_GATE_OVRC,
|
||||
.lvl2_offset = LVL2_CLK_GATE_OVRE,
|
||||
.lvl2_mask = BIT(9) | BIT(31),
|
||||
},
|
||||
[TEGRA_POWERGATE_AUD] = {
|
||||
|
@ -312,7 +312,26 @@ struct clk *clk_get(struct device *dev, const char *id);
|
||||
*/
|
||||
int __must_check clk_bulk_get(struct device *dev, int num_clks,
|
||||
struct clk_bulk_data *clks);
|
||||
|
||||
/**
|
||||
* clk_bulk_get_all - lookup and obtain all available references to clock
|
||||
* producer.
|
||||
* @dev: device for clock "consumer"
|
||||
* @clks: pointer to the clk_bulk_data table of consumer
|
||||
*
|
||||
* This helper function allows drivers to get all clk consumers in one
|
||||
* operation. If any of the clk cannot be acquired then any clks
|
||||
* that were obtained will be freed before returning to the caller.
|
||||
*
|
||||
* Returns a positive value for the number of clocks obtained while the
|
||||
* clock references are stored in the clk_bulk_data table in @clks field.
|
||||
* Returns 0 if there're none and a negative value if something failed.
|
||||
*
|
||||
* Drivers must assume that the clock source is not enabled.
|
||||
*
|
||||
* clk_bulk_get should not be called from within interrupt context.
|
||||
*/
|
||||
int __must_check clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks);
|
||||
/**
|
||||
* devm_clk_bulk_get - managed get multiple clk consumers
|
||||
* @dev: device for clock "consumer"
|
||||
@ -327,6 +346,22 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks,
|
||||
*/
|
||||
int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
|
||||
struct clk_bulk_data *clks);
|
||||
/**
|
||||
* devm_clk_bulk_get_all - managed get multiple clk consumers
|
||||
* @dev: device for clock "consumer"
|
||||
* @clks: pointer to the clk_bulk_data table of consumer
|
||||
*
|
||||
* Returns a positive value for the number of clocks obtained while the
|
||||
* clock references are stored in the clk_bulk_data table in @clks field.
|
||||
* Returns 0 if there're none and a negative value if something failed.
|
||||
*
|
||||
* This helper function allows drivers to get several clk
|
||||
* consumers in one operation with management, the clks will
|
||||
* automatically be freed when the device is unbound.
|
||||
*/
|
||||
|
||||
int __must_check devm_clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks);
|
||||
|
||||
/**
|
||||
* devm_clk_get - lookup and obtain a managed reference to a clock producer.
|
||||
@ -487,6 +522,19 @@ void clk_put(struct clk *clk);
|
||||
*/
|
||||
void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
|
||||
|
||||
/**
|
||||
* clk_bulk_put_all - "free" all the clock source
|
||||
* @num_clks: the number of clk_bulk_data
|
||||
* @clks: the clk_bulk_data table of consumer
|
||||
*
|
||||
* Note: drivers must ensure that all clk_bulk_enable calls made on this
|
||||
* clock source are balanced by clk_bulk_disable calls prior to calling
|
||||
* this function.
|
||||
*
|
||||
* clk_bulk_put_all should not be called from within interrupt context.
|
||||
*/
|
||||
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks);
|
||||
|
||||
/**
|
||||
* devm_clk_put - "free" a managed clock source
|
||||
* @dev: device used to acquire the clock
|
||||
@ -659,6 +707,12 @@ static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __must_check clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_clk_get(struct device *dev, const char *id)
|
||||
{
|
||||
return NULL;
|
||||
@ -670,6 +724,13 @@ static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clk
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int __must_check devm_clk_bulk_get_all(struct device *dev,
|
||||
struct clk_bulk_data **clks)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct clk *devm_get_clk_from_child(struct device *dev,
|
||||
struct device_node *np, const char *con_id)
|
||||
{
|
||||
@ -680,6 +741,8 @@ static inline void clk_put(struct clk *clk) {}
|
||||
|
||||
static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
|
||||
|
||||
static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
|
||||
|
||||
static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user