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

Commit 29a30c26 authored by Heiko Stuebner's avatar Heiko Stuebner
Browse files

clk: rockchip: add a factor clock type



Add a clock type for fixed factor clocks. This allows us to define fixed
factor clocks where they appear in the clock hierarchy instead of in the
init function.

The additional factor_gate type, finally allows us to model some last
parts of the clock tree correctly.

Signed-off-by: default avatarHeiko Stuebner <heiko@sntech.de>
parent aebe3ad8
Loading
Loading
Loading
Loading
+55 −0
Original line number Original line Diff line number Diff line
@@ -265,6 +265,53 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
	return clk;
	return clk;
}
}


static struct clk *rockchip_clk_register_factor_branch(const char *name,
		const char *const *parent_names, u8 num_parents,
		void __iomem *base, unsigned int mult, unsigned int div,
		int gate_offset, u8 gate_shift, u8 gate_flags,
		unsigned long flags, spinlock_t *lock)
{
	struct clk *clk;
	struct clk_gate *gate = NULL;
	struct clk_fixed_factor *fix = NULL;

	/* without gate, register a simple factor clock */
	if (gate_offset == 0) {
		return clk_register_fixed_factor(NULL, name,
				parent_names[0], flags, mult,
				div);
	}

	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
	if (!gate)
		return ERR_PTR(-ENOMEM);

	gate->flags = gate_flags;
	gate->reg = base + gate_offset;
	gate->bit_idx = gate_shift;
	gate->lock = lock;

	fix = kzalloc(sizeof(*fix), GFP_KERNEL);
	if (!fix) {
		kfree(gate);
		return ERR_PTR(-ENOMEM);
	}

	fix->mult = mult;
	fix->div = div;

	clk = clk_register_composite(NULL, name, parent_names, num_parents,
				     NULL, NULL,
				     &fix->hw, &clk_fixed_factor_ops,
				     &gate->hw, &clk_gate_ops, flags);
	if (IS_ERR(clk)) {
		kfree(fix);
		kfree(gate);
	}

	return clk;
}

static DEFINE_SPINLOCK(clk_lock);
static DEFINE_SPINLOCK(clk_lock);
static struct clk **clk_table;
static struct clk **clk_table;
static void __iomem *reg_base;
static void __iomem *reg_base;
@@ -400,6 +447,14 @@ void __init rockchip_clk_register_branches(
				reg_base + list->muxdiv_offset,
				reg_base + list->muxdiv_offset,
				list->div_shift, list->div_flags, &clk_lock);
				list->div_shift, list->div_flags, &clk_lock);
			break;
			break;
		case branch_factor:
			clk = rockchip_clk_register_factor_branch(
				list->name, list->parent_names,
				list->num_parents, reg_base,
				list->div_shift, list->div_width,
				list->gate_offset, list->gate_shift,
				list->gate_flags, flags, &clk_lock);
			break;
		}
		}


		/* none of the cases above matched */
		/* none of the cases above matched */
+28 −0
Original line number Original line Diff line number Diff line
@@ -254,6 +254,7 @@ enum rockchip_clk_branch_type {
	branch_gate,
	branch_gate,
	branch_mmc,
	branch_mmc,
	branch_inverter,
	branch_inverter,
	branch_factor,
};
};


struct rockchip_clk_branch {
struct rockchip_clk_branch {
@@ -508,6 +509,33 @@ struct rockchip_clk_branch {
		.div_flags	= if,				\
		.div_flags	= if,				\
	}
	}


#define FACTOR(_id, cname, pname,  f, fm, fd)			\
	{							\
		.id		= _id,				\
		.branch_type	= branch_factor,		\
		.name		= cname,			\
		.parent_names	= (const char *[]){ pname },	\
		.num_parents	= 1,				\
		.flags		= f,				\
		.div_shift	= fm,				\
		.div_width	= fd,				\
	}

#define FACTOR_GATE(_id, cname, pname,  f, fm, fd, go, gb, gf)	\
	{							\
		.id		= _id,				\
		.branch_type	= branch_factor,		\
		.name		= cname,			\
		.parent_names	= (const char *[]){ pname },	\
		.num_parents	= 1,				\
		.flags		= f,				\
		.div_shift	= fm,				\
		.div_width	= fd,				\
		.gate_offset	= go,				\
		.gate_shift	= gb,				\
		.gate_flags	= gf,				\
	}

void rockchip_clk_init(struct device_node *np, void __iomem *base,
void rockchip_clk_init(struct device_node *np, void __iomem *base,
		       unsigned long nr_clks);
		       unsigned long nr_clks);
struct regmap *rockchip_clk_get_grf(void);
struct regmap *rockchip_clk_get_grf(void);