brintos

brintos / linux-shallow public Read only

0
0
Text · 7.1 KiB · bcaf8ae Raw
336 lines · c
1/* SPDX-License-Identifier: GPL-2.0 */2/*3 * Copyright (C) 2020-2022 MaxLinear, Inc.4 * Copyright (C) 2020 Intel Corporation.5 * Zhu Yixin <yzhu@maxlinear.com>6 * Rahul Tanwar <rtanwar@maxlinear.com>7 */8 9#ifndef __CLK_CGU_H10#define __CLK_CGU_H11 12#include <linux/regmap.h>13 14struct lgm_clk_mux {15	struct clk_hw hw;16	struct regmap *membase;17	unsigned int reg;18	u8 shift;19	u8 width;20	unsigned long flags;21};22 23struct lgm_clk_divider {24	struct clk_hw hw;25	struct regmap *membase;26	unsigned int reg;27	u8 shift;28	u8 width;29	u8 shift_gate;30	u8 width_gate;31	unsigned long flags;32	const struct clk_div_table *table;33};34 35struct lgm_clk_ddiv {36	struct clk_hw hw;37	struct regmap *membase;38	unsigned int reg;39	u8 shift0;40	u8 width0;41	u8 shift1;42	u8 width1;43	u8 shift2;44	u8 width2;45	u8 shift_gate;46	u8 width_gate;47	unsigned int mult;48	unsigned int div;49	unsigned long flags;50};51 52struct lgm_clk_gate {53	struct clk_hw hw;54	struct regmap *membase;55	unsigned int reg;56	u8 shift;57	unsigned long flags;58};59 60enum lgm_clk_type {61	CLK_TYPE_FIXED,62	CLK_TYPE_MUX,63	CLK_TYPE_DIVIDER,64	CLK_TYPE_FIXED_FACTOR,65	CLK_TYPE_GATE,66	CLK_TYPE_NONE,67};68 69/**70 * struct lgm_clk_provider71 * @membase: IO mem base address for CGU.72 * @np: device node73 * @dev: device74 * @clk_data: array of hw clocks and clk number.75 */76struct lgm_clk_provider {77	struct regmap *membase;78	struct device_node *np;79	struct device *dev;80	struct clk_hw_onecell_data clk_data;81};82 83enum pll_type {84	TYPE_ROPLL,85	TYPE_LJPLL,86	TYPE_NONE,87};88 89struct lgm_clk_pll {90	struct clk_hw hw;91	struct regmap *membase;92	unsigned int reg;93	unsigned long flags;94	enum pll_type type;95};96 97/**98 * struct lgm_pll_clk_data99 * @id: platform specific id of the clock.100 * @name: name of this pll clock.101 * @parent_data: parent clock data.102 * @num_parents: number of parents.103 * @flags: optional flags for basic clock.104 * @type: platform type of pll.105 * @reg: offset of the register.106 */107struct lgm_pll_clk_data {108	unsigned int id;109	const char *name;110	const struct clk_parent_data *parent_data;111	u8 num_parents;112	unsigned long flags;113	enum pll_type type;114	int reg;115};116 117#define LGM_PLL(_id, _name, _pdata, _flags,		\118		_reg, _type)				\119	{						\120		.id = _id,				\121		.name = _name,				\122		.parent_data = _pdata,			\123		.num_parents = ARRAY_SIZE(_pdata),	\124		.flags = _flags,			\125		.reg = _reg,				\126		.type = _type,				\127	}128 129struct lgm_clk_ddiv_data {130	unsigned int id;131	const char *name;132	const struct clk_parent_data *parent_data;133	u8 flags;134	unsigned long div_flags;135	unsigned int reg;136	u8 shift0;137	u8 width0;138	u8 shift1;139	u8 width1;140	u8 shift_gate;141	u8 width_gate;142	u8 ex_shift;143	u8 ex_width;144};145 146#define LGM_DDIV(_id, _name, _pname, _flags, _reg,		\147		 _shft0, _wdth0, _shft1, _wdth1,		\148		 _shft_gate, _wdth_gate, _xshft, _df)		\149	{							\150		.id = _id,					\151		.name = _name,					\152		.parent_data = &(const struct clk_parent_data){	\153			.fw_name = _pname,			\154			.name = _pname,				\155		},						\156		.flags = _flags,				\157		.reg = _reg,					\158		.shift0 = _shft0,				\159		.width0 = _wdth0,				\160		.shift1 = _shft1,				\161		.width1 = _wdth1,				\162		.shift_gate = _shft_gate,			\163		.width_gate = _wdth_gate,			\164		.ex_shift = _xshft,				\165		.ex_width = 1,					\166		.div_flags = _df,				\167	}168 169struct lgm_clk_branch {170	unsigned int id;171	enum lgm_clk_type type;172	const char *name;173	const struct clk_parent_data *parent_data;174	u8 num_parents;175	unsigned long flags;176	unsigned int mux_off;177	u8 mux_shift;178	u8 mux_width;179	unsigned long mux_flags;180	unsigned int mux_val;181	unsigned int div_off;182	u8 div_shift;183	u8 div_width;184	u8 div_shift_gate;185	u8 div_width_gate;186	unsigned long div_flags;187	unsigned int div_val;188	const struct clk_div_table *div_table;189	unsigned int gate_off;190	u8 gate_shift;191	unsigned long gate_flags;192	unsigned int gate_val;193	unsigned int mult;194	unsigned int div;195};196 197/* clock flags definition */198#define CLOCK_FLAG_VAL_INIT	BIT(16)199#define MUX_CLK_SW		BIT(17)200#define GATE_CLK_HW		BIT(18)201#define DIV_CLK_NO_MASK		BIT(19)202 203#define LGM_MUX(_id, _name, _pdata, _f, _reg,		\204		_shift, _width, _cf, _v)		\205	{						\206		.id = _id,				\207		.type = CLK_TYPE_MUX,			\208		.name = _name,				\209		.parent_data = _pdata,			\210		.num_parents = ARRAY_SIZE(_pdata),	\211		.flags = _f,				\212		.mux_off = _reg,			\213		.mux_shift = _shift,			\214		.mux_width = _width,			\215		.mux_flags = _cf,			\216		.mux_val = _v,				\217	}218 219#define LGM_DIV(_id, _name, _pname, _f, _reg, _shift, _width,	\220		_shift_gate, _width_gate, _cf, _v, _dtable)	\221	{							\222		.id = _id,					\223		.type = CLK_TYPE_DIVIDER,			\224		.name = _name,					\225		.parent_data = &(const struct clk_parent_data){	\226			.fw_name = _pname,			\227			.name = _pname,				\228		},						\229		.num_parents = 1,				\230		.flags = _f,					\231		.div_off = _reg,				\232		.div_shift = _shift,				\233		.div_width = _width,				\234		.div_shift_gate = _shift_gate,			\235		.div_width_gate = _width_gate,			\236		.div_flags = _cf,				\237		.div_val = _v,					\238		.div_table = _dtable,				\239	}240 241#define LGM_GATE(_id, _name, _pname, _f, _reg,			\242		 _shift, _cf, _v)				\243	{							\244		.id = _id,					\245		.type = CLK_TYPE_GATE,				\246		.name = _name,					\247		.parent_data = &(const struct clk_parent_data){	\248			.fw_name = _pname,			\249			.name = _pname,				\250		},						\251		.num_parents = !_pname ? 0 : 1,			\252		.flags = _f,					\253		.gate_off = _reg,				\254		.gate_shift = _shift,				\255		.gate_flags = _cf,				\256		.gate_val = _v,					\257	}258 259#define LGM_FIXED(_id, _name, _pname, _f, _reg,			\260		  _shift, _width, _cf, _freq, _v)		\261	{							\262		.id = _id,					\263		.type = CLK_TYPE_FIXED,				\264		.name = _name,					\265		.parent_data = &(const struct clk_parent_data){	\266			.fw_name = _pname,			\267			.name = _pname,				\268		},						\269		.num_parents = !_pname ? 0 : 1,			\270		.flags = _f,					\271		.div_off = _reg,				\272		.div_shift = _shift,				\273		.div_width = _width,				\274		.div_flags = _cf,				\275		.div_val = _v,					\276		.mux_flags = _freq,				\277	}278 279#define LGM_FIXED_FACTOR(_id, _name, _pname, _f, _reg,		\280			 _shift, _width, _cf, _v, _m, _d)	\281	{							\282		.id = _id,					\283		.type = CLK_TYPE_FIXED_FACTOR,			\284		.name = _name,					\285		.parent_data = &(const struct clk_parent_data){	\286			.fw_name = _pname,			\287			.name = _pname,				\288		},						\289		.num_parents = 1,				\290		.flags = _f,					\291		.div_off = _reg,				\292		.div_shift = _shift,				\293		.div_width = _width,				\294		.div_flags = _cf,				\295		.div_val = _v,					\296		.mult = _m,					\297		.div = _d,					\298	}299 300static inline void lgm_set_clk_val(struct regmap *membase, u32 reg,301				   u8 shift, u8 width, u32 set_val)302{303	u32 mask = (GENMASK(width - 1, 0) << shift);304 305	regmap_update_bits(membase, reg, mask, set_val << shift);306}307 308static inline u32 lgm_get_clk_val(struct regmap *membase, u32 reg,309				  u8 shift, u8 width)310{311	u32 mask = (GENMASK(width - 1, 0) << shift);312	u32 val;313 314	if (regmap_read(membase, reg, &val)) {315		WARN_ONCE(1, "Failed to read clk reg: 0x%x\n", reg);316		return 0;317	}318 319	val = (val & mask) >> shift;320 321	return val;322}323 324 325 326int lgm_clk_register_branches(struct lgm_clk_provider *ctx,327			      const struct lgm_clk_branch *list,328			      unsigned int nr_clk);329int lgm_clk_register_plls(struct lgm_clk_provider *ctx,330			  const struct lgm_pll_clk_data *list,331			  unsigned int nr_clk);332int lgm_clk_register_ddiv(struct lgm_clk_provider *ctx,333			  const struct lgm_clk_ddiv_data *list,334			  unsigned int nr_clk);335#endif	/* __CLK_CGU_H */336