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

Commit 293d2e97 authored by Georgi Djakov's avatar Georgi Djakov Committed by Stephen Boyd
Browse files

clk: qcom: Introduce parent_map tables



In the current parent mapping code, we can get duplicate or inconsistent
indexes, which leads to discrepancy between the number of elements in the
array and the number of parents. Until now, this was solved with some
reordering but this is not always possible.

This patch introduces index tables that are used to define the relations
between the PLL source and the hardware mux configuration value.
To accomplish this, here we do the following:
 - Define a parent_map struct to map the relations between PLL source index
 and register configuration value.
 - Add a qcom_find_src_index() function for finding the index of a clock
 matching the specific PLL configuration.
 - Update the {set,get}_parent RCG functions use the newly introduced
 parent_map struct.
 - Convert all existing drivers to the new parent_map tables.

Signed-off-by: default avatarGeorgi Djakov <georgi.djakov@linaro.org>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
parent fae507af
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ static u8 clk_rcg_get_parent(struct clk_hw *hw)
		goto err;
	ns = ns_to_src(&rcg->s, ns);
	for (i = 0; i < num_parents; i++)
		if (ns == rcg->s.parent_map[i])
		if (ns == rcg->s.parent_map[i].cfg)
			return i;

err:
@@ -90,7 +90,7 @@ static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
	ns = ns_to_src(s, ns);

	for (i = 0; i < num_parents; i++)
		if (ns == s->parent_map[i])
		if (ns == s->parent_map[i].cfg)
			return i;

err:
@@ -105,7 +105,7 @@ static int clk_rcg_set_parent(struct clk_hw *hw, u8 index)
	u32 ns;

	regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
	ns = src_to_ns(&rcg->s, rcg->s.parent_map[index], ns);
	ns = src_to_ns(&rcg->s, rcg->s.parent_map[index].cfg, ns);
	regmap_write(rcg->clkr.regmap, rcg->ns_reg, ns);

	return 0;
@@ -206,7 +206,7 @@ static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val)
static int configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
{
	u32 ns, md, reg;
	int bank, new_bank, ret;
	int bank, new_bank, ret, index;
	struct mn *mn;
	struct pre_div *p;
	struct src_sel *s;
@@ -276,7 +276,10 @@ static int configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
	}

	s = &rcg->s[new_bank];
	ns = src_to_ns(s, s->parent_map[f->src], ns);
	index = qcom_find_src_index(hw, s->parent_map, f->src);
	if (index < 0)
		return index;
	ns = src_to_ns(s, s->parent_map[index].cfg, ns);
	ret = regmap_write(rcg->clkr.regmap, ns_reg, ns);
	if (ret)
		return ret;
+12 −2
Original line number Diff line number Diff line
@@ -25,6 +25,16 @@ struct freq_tbl {
	u16 n;
};

/**
 * struct parent_map - map table for PLL source select configuration values
 * @src: source PLL
 * @cfg: configuration value
 */
struct parent_map {
	u8 src;
	u8 cfg;
};

/**
 * struct mn - M/N:D counter
 * @mnctr_en_bit: bit to enable mn counter
@@ -65,7 +75,7 @@ struct pre_div {
struct src_sel {
	u8		src_sel_shift;
#define SRC_SEL_MASK	0x7
	const u8	*parent_map;
	const struct parent_map	*parent_map;
};

/**
@@ -151,7 +161,7 @@ struct clk_rcg2 {
	u32			cmd_rcgr;
	u8			mnd_width;
	u8			hid_width;
	const u8		*parent_map;
	const struct parent_map	*parent_map;
	const struct freq_tbl	*freq_tbl;
	struct clk_regmap	clkr;
};
+9 −5
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw)
	cfg >>= CFG_SRC_SEL_SHIFT;

	for (i = 0; i < num_parents; i++)
		if (cfg == rcg->parent_map[i])
		if (cfg == rcg->parent_map[i].cfg)
			return i;

err:
@@ -114,10 +114,10 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
{
	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
	int ret;
	u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;

	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
				 CFG_SRC_SEL_MASK,
				 rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
				 CFG_SRC_SEL_MASK, cfg);
	if (ret)
		return ret;

@@ -222,7 +222,11 @@ static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
{
	u32 cfg, mask;
	int ret;
	struct clk_hw *hw = &rcg->clkr.hw;
	int ret, index = qcom_find_src_index(hw, rcg->parent_map, f->src);

	if (index < 0)
		return index;

	if (rcg->mnd_width && f->n) {
		mask = BIT(rcg->mnd_width) - 1;
@@ -245,7 +249,7 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
	mask = BIT(rcg->hid_width) - 1;
	mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
	cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
	cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
	cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
	if (rcg->mnd_width && f->n && (f->m != f->n))
		cfg |= CFG_MODE_DUAL_EDGE;
	ret = regmap_update_bits(rcg->clkr.regmap,
+12 −0
Original line number Diff line number Diff line
@@ -43,6 +43,18 @@ struct freq_tbl *qcom_find_freq(const struct freq_tbl *f, unsigned long rate)
}
EXPORT_SYMBOL_GPL(qcom_find_freq);

int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map, u8 src)
{
	int i, num_parents = __clk_get_num_parents(hw->clk);

	for (i = 0; i < num_parents; i++)
		if (src == map[i].src)
			return i;

	return -ENOENT;
}
EXPORT_SYMBOL_GPL(qcom_find_src_index);

struct regmap *
qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
{
+4 −0
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ struct clk_regmap;
struct qcom_reset_map;
struct regmap;
struct freq_tbl;
struct clk_hw;
struct parent_map;

struct qcom_cc_desc {
	const struct regmap_config *config;
@@ -30,6 +32,8 @@ struct qcom_cc_desc {

extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
					     unsigned long rate);
extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
			       u8 src);

extern struct regmap *qcom_cc_map(struct platform_device *pdev,
				  const struct qcom_cc_desc *desc);
Loading