Commit 2f25528e authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Stephen Boyd
Browse files

clk: Add clk_bulk_get_optional() function



clk_bulk_get_optional() allows to get a group of clocks where one
or more is optional.  For a not available clock, e.g. not specifed
in the clock consumer node in DT, its respective struct clk pointer
will be NULL.  This allows for operating on a group of returned
clocks (struct clk_bulk_data array) with existing clk_bulk* APIs.

Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent a188339c
Loading
Loading
Loading
Loading
+20 −3
Original line number Original line Diff line number Diff line
@@ -75,8 +75,8 @@ void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
}
}
EXPORT_SYMBOL_GPL(clk_bulk_put);
EXPORT_SYMBOL_GPL(clk_bulk_put);


int __must_check clk_bulk_get(struct device *dev, int num_clks,
static int __clk_bulk_get(struct device *dev, int num_clks,
			      struct clk_bulk_data *clks)
			  struct clk_bulk_data *clks, bool optional)
{
{
	int ret;
	int ret;
	int i;
	int i;
@@ -88,10 +88,14 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks,
		clks[i].clk = clk_get(dev, clks[i].id);
		clks[i].clk = clk_get(dev, clks[i].id);
		if (IS_ERR(clks[i].clk)) {
		if (IS_ERR(clks[i].clk)) {
			ret = PTR_ERR(clks[i].clk);
			ret = PTR_ERR(clks[i].clk);
			clks[i].clk = NULL;

			if (ret == -ENOENT && optional)
				continue;

			if (ret != -EPROBE_DEFER)
			if (ret != -EPROBE_DEFER)
				dev_err(dev, "Failed to get clk '%s': %d\n",
				dev_err(dev, "Failed to get clk '%s': %d\n",
					clks[i].id, ret);
					clks[i].id, ret);
			clks[i].clk = NULL;
			goto err;
			goto err;
		}
		}
	}
	}
@@ -103,8 +107,21 @@ err:


	return ret;
	return ret;
}
}

int __must_check clk_bulk_get(struct device *dev, int num_clks,
			      struct clk_bulk_data *clks)
{
	return __clk_bulk_get(dev, num_clks, clks, false);
}
EXPORT_SYMBOL(clk_bulk_get);
EXPORT_SYMBOL(clk_bulk_get);


int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
				       struct clk_bulk_data *clks)
{
	return __clk_bulk_get(dev, num_clks, clks, true);
}
EXPORT_SYMBOL_GPL(clk_bulk_get_optional);

void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
{
{
	if (IS_ERR_OR_NULL(clks))
	if (IS_ERR_OR_NULL(clks))
+19 −0
Original line number Original line Diff line number Diff line
@@ -332,6 +332,19 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks,
 */
 */
int __must_check clk_bulk_get_all(struct device *dev,
int __must_check clk_bulk_get_all(struct device *dev,
				  struct clk_bulk_data **clks);
				  struct clk_bulk_data **clks);

/**
 * clk_bulk_get_optional - lookup and obtain a number of references to clock producer
 * @dev: device for clock "consumer"
 * @num_clks: the number of clk_bulk_data
 * @clks: the clk_bulk_data table of consumer
 *
 * Behaves the same as clk_bulk_get() except where there is no clock producer.
 * In this case, instead of returning -ENOENT, the function returns 0 and
 * NULL for a clk for which a clock producer could not be determined.
 */
int __must_check clk_bulk_get_optional(struct device *dev, int num_clks,
				       struct clk_bulk_data *clks);
/**
/**
 * devm_clk_bulk_get - managed get multiple clk consumers
 * devm_clk_bulk_get - managed get multiple clk consumers
 * @dev: device for clock "consumer"
 * @dev: device for clock "consumer"
@@ -718,6 +731,12 @@ static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
	return 0;
	return 0;
}
}


static inline int __must_check clk_bulk_get_optional(struct device *dev,
				int num_clks, struct clk_bulk_data *clks)
{
	return 0;
}

static inline int __must_check clk_bulk_get_all(struct device *dev,
static inline int __must_check clk_bulk_get_all(struct device *dev,
					 struct clk_bulk_data **clks)
					 struct clk_bulk_data **clks)
{
{