Commit 6a136805 authored by Théo Lebrun's avatar Théo Lebrun Committed by Stephen Boyd
Browse files

clk: divider: Introduce CLK_DIVIDER_EVEN_INTEGERS flag



Add CLK_DIVIDER_EVEN_INTEGERS flag to support divisor of 2, 4, 6, etc.
The same divisor can be done using a table, which would be big and
wasteful for a clock dividor of width 8 (256 entries).

Require increasing flags size from u8 to u16 because
CLK_DIVIDER_EVEN_INTEGERS is the eighth flag. u16 is used inside struct
clk_divider; `unsigned long` is used for function arguments.

Signed-off-by: default avatarThéo Lebrun <theo.lebrun@bootlin.com>
Link: https://lore.kernel.org/r/20241007-mbly-clk-v5-3-e9d8994269cb@bootlin.com


Signed-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent bae7aff5
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
		return clk_div_mask(width);
	if (flags & CLK_DIVIDER_POWER_OF_TWO)
		return 1 << clk_div_mask(width);
	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
		return 2 * (clk_div_mask(width) + 1);
	if (table)
		return _get_table_maxdiv(table, width);
	return clk_div_mask(width) + 1;
@@ -97,6 +99,8 @@ static unsigned int _get_div(const struct clk_div_table *table,
		return 1 << val;
	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
		return val ? val : clk_div_mask(width) + 1;
	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
		return 2 * (val + 1);
	if (table)
		return _get_table_div(table, val);
	return val + 1;
@@ -122,6 +126,8 @@ static unsigned int _get_val(const struct clk_div_table *table,
		return __ffs(div);
	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
		return (div == clk_div_mask(width) + 1) ? 0 : div;
	if (flags & CLK_DIVIDER_EVEN_INTEGERS)
		return (div >> 1) - 1;
	if (table)
		return  _get_table_val(table, div);
	return div - 1;
@@ -538,7 +544,8 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
		struct device_node *np, const char *name,
		const char *parent_name, const struct clk_hw *parent_hw,
		const struct clk_parent_data *parent_data, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
		void __iomem *reg, u8 shift, u8 width,
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock)
{
	struct clk_divider *div;
@@ -610,8 +617,8 @@ EXPORT_SYMBOL_GPL(__clk_hw_register_divider);
struct clk *clk_register_divider_table(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width,
		u8 clk_divider_flags, const struct clk_div_table *table,
		spinlock_t *lock)
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock)
{
	struct clk_hw *hw;

@@ -664,7 +671,8 @@ struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
		struct device_node *np, const char *name,
		const char *parent_name, const struct clk_hw *parent_hw,
		const struct clk_parent_data *parent_data, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
		void __iomem *reg, u8 shift, u8 width,
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock)
{
	struct clk_hw **ptr, *hw;
+10 −5
Original line number Diff line number Diff line
@@ -689,13 +689,15 @@ struct clk_div_table {
 * CLK_DIVIDER_BIG_ENDIAN - By default little endian register accesses are used
 *	for the divider register.  Setting this flag makes the register accesses
 *	big endian.
 * CLK_DIVIDER_EVEN_INTEGERS - clock divisor is 2, 4, 6, 8, 10, etc.
 *	Formula is 2 * (value read from hardware + 1).
 */
struct clk_divider {
	struct clk_hw	hw;
	void __iomem	*reg;
	u8		shift;
	u8		width;
	u8		flags;
	u16		flags;
	const struct clk_div_table	*table;
	spinlock_t	*lock;
};
@@ -711,6 +713,7 @@ struct clk_divider {
#define CLK_DIVIDER_READ_ONLY		BIT(5)
#define CLK_DIVIDER_MAX_AT_ZERO		BIT(6)
#define CLK_DIVIDER_BIG_ENDIAN		BIT(7)
#define CLK_DIVIDER_EVEN_INTEGERS	BIT(8)

extern const struct clk_ops clk_divider_ops;
extern const struct clk_ops clk_divider_ro_ops;
@@ -740,19 +743,21 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev,
		struct device_node *np, const char *name,
		const char *parent_name, const struct clk_hw *parent_hw,
		const struct clk_parent_data *parent_data, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
		void __iomem *reg, u8 shift, u8 width,
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock);
struct clk_hw *__devm_clk_hw_register_divider(struct device *dev,
		struct device_node *np, const char *name,
		const char *parent_name, const struct clk_hw *parent_hw,
		const struct clk_parent_data *parent_data, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags,
		void __iomem *reg, u8 shift, u8 width,
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock);
struct clk *clk_register_divider_table(struct device *dev, const char *name,
		const char *parent_name, unsigned long flags,
		void __iomem *reg, u8 shift, u8 width,
		u8 clk_divider_flags, const struct clk_div_table *table,
		spinlock_t *lock);
		unsigned long clk_divider_flags,
		const struct clk_div_table *table, spinlock_t *lock);
/**
 * clk_register_divider - register a divider clock with the clock framework
 * @dev: device registering this clock