Commit c1f74dbe authored by Stephen Boyd's avatar Stephen Boyd
Browse files

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()
Loading
Loading
Loading
Loading
+80 −0
Original line number Diff line number Diff line
@@ -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

/**
+24 −0
Original line number Diff line number Diff line
@@ -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;
+6 −2
Original line number Diff line number Diff line
@@ -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");
+4 −3
Original line number Diff line number Diff line
@@ -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] = {
+64 −1
Original line number Diff line number Diff line
@@ -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) {}