brintos

brintos / linux-shallow public Read only

0
0
Text · 12.9 KiB · fb06caa Raw
442 lines · c
1/* SPDX-License-Identifier: GPL-2.0-only */2/*3 * Copyright (c) 2013 Samsung Electronics Co., Ltd.4 * Copyright (c) 2013 Linaro Ltd.5 * Author: Thomas Abraham <thomas.ab@samsung.com>6 *7 * Common Clock Framework support for all Samsung platforms8*/9 10#ifndef __SAMSUNG_CLK_H11#define __SAMSUNG_CLK_H12 13#include <linux/clk-provider.h>14#include "clk-pll.h"15#include "clk-cpu.h"16 17/**18 * struct samsung_clk_provider - information about clock provider19 * @reg_base: virtual address for the register base20 * @dev: clock provider device needed for runtime PM21 * @lock: maintains exclusion between callbacks for a given clock-provider22 * @clk_data: holds clock related data like clk_hw* and number of clocks23 */24struct samsung_clk_provider {25	void __iomem *reg_base;26	struct device *dev;27	spinlock_t lock;28	/* clk_data must be the last entry due to variable length 'hws' array */29	struct clk_hw_onecell_data clk_data;30};31 32/**33 * struct samsung_clock_alias - information about mux clock34 * @id: platform specific id of the clock35 * @dev_name: name of the device to which this clock belongs36 * @alias: optional clock alias name to be assigned to this clock37 */38struct samsung_clock_alias {39	unsigned int		id;40	const char		*dev_name;41	const char		*alias;42};43 44#define ALIAS(_id, dname, a)	\45	{							\46		.id		= _id,				\47		.dev_name	= dname,			\48		.alias		= a,				\49	}50 51#define MHZ (1000 * 1000)52 53/**54 * struct samsung_fixed_rate_clock - information about fixed-rate clock55 * @id: platform specific id of the clock56 * @name: name of this fixed-rate clock57 * @parent_name: optional parent clock name58 * @flags: optional fixed-rate clock flags59 * @fixed_rate: fixed clock rate of this clock60 */61struct samsung_fixed_rate_clock {62	unsigned int		id;63	char			*name;64	const char		*parent_name;65	unsigned long		flags;66	unsigned long		fixed_rate;67};68 69#define FRATE(_id, cname, pname, f, frate)		\70	{						\71		.id		= _id,			\72		.name		= cname,		\73		.parent_name	= pname,		\74		.flags		= f,			\75		.fixed_rate	= frate,		\76	}77 78/**79 * struct samsung_fixed_factor_clock - information about fixed-factor clock80 * @id: platform specific id of the clock81 * @name: name of this fixed-factor clock82 * @parent_name: parent clock name83 * @mult: fixed multiplication factor84 * @div: fixed division factor85 * @flags: optional fixed-factor clock flags86 */87struct samsung_fixed_factor_clock {88	unsigned int		id;89	char			*name;90	const char		*parent_name;91	unsigned long		mult;92	unsigned long		div;93	unsigned long		flags;94};95 96#define FFACTOR(_id, cname, pname, m, d, f)		\97	{						\98		.id		= _id,			\99		.name		= cname,		\100		.parent_name	= pname,		\101		.mult		= m,			\102		.div		= d,			\103		.flags		= f,			\104	}105 106/**107 * struct samsung_mux_clock - information about mux clock108 * @id: platform specific id of the clock109 * @name: name of this mux clock110 * @parent_names: array of pointer to parent clock names111 * @num_parents: number of parents listed in @parent_names112 * @flags: optional flags for basic clock113 * @offset: offset of the register for configuring the mux114 * @shift: starting bit location of the mux control bit-field in @reg115 * @width: width of the mux control bit-field in @reg116 * @mux_flags: flags for mux-type clock117 */118struct samsung_mux_clock {119	unsigned int		id;120	const char		*name;121	const char		*const *parent_names;122	u8			num_parents;123	unsigned long		flags;124	unsigned long		offset;125	u8			shift;126	u8			width;127	u8			mux_flags;128};129 130#define __MUX(_id, cname, pnames, o, s, w, f, mf)		\131	{							\132		.id		= _id,				\133		.name		= cname,			\134		.parent_names	= pnames,			\135		.num_parents	= ARRAY_SIZE(pnames),		\136		.flags		= f,				\137		.offset		= o,				\138		.shift		= s,				\139		.width		= w,				\140		.mux_flags	= mf,				\141	}142 143#define MUX(_id, cname, pnames, o, s, w)			\144	__MUX(_id, cname, pnames, o, s, w, CLK_SET_RATE_NO_REPARENT, 0)145 146#define MUX_F(_id, cname, pnames, o, s, w, f, mf)		\147	__MUX(_id, cname, pnames, o, s, w, (f) | CLK_SET_RATE_NO_REPARENT, mf)148 149/* Used by MUX clocks where reparenting on clock rate change is allowed. */150#define nMUX(_id, cname, pnames, o, s, w)			\151	__MUX(_id, cname, pnames, o, s, w, 0, 0)152 153#define nMUX_F(_id, cname, pnames, o, s, w, f, mf)		\154	__MUX(_id, cname, pnames, o, s, w, f, mf)155 156/**157 * struct samsung_div_clock - information about div clock158 * @id: platform specific id of the clock159 * @name: name of this div clock160 * @parent_name: name of the parent clock161 * @flags: optional flags for basic clock162 * @offset: offset of the register for configuring the div163 * @shift: starting bit location of the div control bit-field in @reg164 * @width: width of the bitfield165 * @div_flags: flags for div-type clock166 * @table: array of divider/value pairs ending with a div set to 0167 */168struct samsung_div_clock {169	unsigned int		id;170	const char		*name;171	const char		*parent_name;172	unsigned long		flags;173	unsigned long		offset;174	u8			shift;175	u8			width;176	u8			div_flags;177	struct clk_div_table	*table;178};179 180#define __DIV(_id, cname, pname, o, s, w, f, df, t)	\181	{							\182		.id		= _id,				\183		.name		= cname,			\184		.parent_name	= pname,			\185		.flags		= f,				\186		.offset		= o,				\187		.shift		= s,				\188		.width		= w,				\189		.div_flags	= df,				\190		.table		= t,				\191	}192 193#define DIV(_id, cname, pname, o, s, w)				\194	__DIV(_id, cname, pname, o, s, w, 0, 0, NULL)195 196#define DIV_F(_id, cname, pname, o, s, w, f, df)		\197	__DIV(_id, cname, pname, o, s, w, f, df, NULL)198 199#define DIV_T(_id, cname, pname, o, s, w, t)			\200	__DIV(_id, cname, pname, o, s, w, 0, 0, t)201 202/**203 * struct samsung_gate_clock - information about gate clock204 * @id: platform specific id of the clock205 * @name: name of this gate clock206 * @parent_name: name of the parent clock207 * @flags: optional flags for basic clock208 * @offset: offset of the register for configuring the gate209 * @bit_idx: bit index of the gate control bit-field in @reg210 * @gate_flags: flags for gate-type clock211 */212struct samsung_gate_clock {213	unsigned int		id;214	const char		*name;215	const char		*parent_name;216	unsigned long		flags;217	unsigned long		offset;218	u8			bit_idx;219	u8			gate_flags;220};221 222#define __GATE(_id, cname, pname, o, b, f, gf)			\223	{							\224		.id		= _id,				\225		.name		= cname,			\226		.parent_name	= pname,			\227		.flags		= f,				\228		.offset		= o,				\229		.bit_idx	= b,				\230		.gate_flags	= gf,				\231	}232 233#define GATE(_id, cname, pname, o, b, f, gf)			\234	__GATE(_id, cname, pname, o, b, f, gf)235 236#define PNAME(x) static const char * const x[] __initconst237 238/**239 * struct samsung_clk_reg_dump - register dump of clock controller registers240 * @offset: clock register offset from the controller base address241 * @value: the value to be register at offset242 */243struct samsung_clk_reg_dump {244	u32	offset;245	u32	value;246};247 248/**249 * struct samsung_pll_clock - information about pll clock250 * @id: platform specific id of the clock251 * @name: name of this pll clock252 * @parent_name: name of the parent clock253 * @flags: optional flags for basic clock254 * @con_offset: offset of the register for configuring the PLL255 * @lock_offset: offset of the register for locking the PLL256 * @type: type of PLL to be registered257 * @rate_table: array of PLL settings for possible PLL rates258 */259struct samsung_pll_clock {260	unsigned int		id;261	const char		*name;262	const char		*parent_name;263	unsigned long		flags;264	int			con_offset;265	int			lock_offset;266	enum samsung_pll_type	type;267	const struct samsung_pll_rate_table *rate_table;268};269 270#define __PLL(_typ, _id, _name, _pname, _flags, _lock, _con, _rtable)	\271	{								\272		.id		= _id,					\273		.type		= _typ,					\274		.name		= _name,				\275		.parent_name	= _pname,				\276		.flags		= _flags,				\277		.con_offset	= _con,					\278		.lock_offset	= _lock,				\279		.rate_table	= _rtable,				\280	}281 282#define PLL(_typ, _id, _name, _pname, _lock, _con, _rtable)	\283	__PLL(_typ, _id, _name, _pname, CLK_GET_RATE_NOCACHE, _lock,	\284	      _con, _rtable)285 286struct samsung_cpu_clock {287	unsigned int	id;288	const char	*name;289	unsigned int	parent_id;290	unsigned int	alt_parent_id;291	unsigned long	flags;292	int		offset;293	enum exynos_cpuclk_layout reg_layout;294	const struct exynos_cpuclk_cfg_data *cfg;295};296 297#define CPU_CLK(_id, _name, _pid, _apid, _flags, _offset, _layout, _cfg) \298	{							\299		.id		  = _id,			\300		.name		  = _name,			\301		.parent_id	  = _pid,			\302		.alt_parent_id	  = _apid,			\303		.flags		  = _flags,			\304		.offset		  = _offset,			\305		.reg_layout	  = _layout,			\306		.cfg		  = _cfg,			\307	}308 309struct samsung_clock_reg_cache {310	struct list_head node;311	void __iomem *reg_base;312	struct samsung_clk_reg_dump *rdump;313	unsigned int rd_num;314	const struct samsung_clk_reg_dump *rsuspend;315	unsigned int rsuspend_num;316};317 318/**319 * struct samsung_cmu_info - all clocks information needed for CMU registration320 * @pll_clks: list of PLL clocks321 * @nr_pll_clks: count of clocks in @pll_clks322 * @mux_clks: list of mux clocks323 * @nr_mux_clks: count of clocks in @mux_clks324 * @div_clks: list of div clocks325 * @nr_div_clks: count of clocks in @div_clks326 * @gate_clks: list of gate clocks327 * @nr_gate_clks: count of clocks in @gate_clks328 * @fixed_clks: list of fixed clocks329 * @nr_fixed_clks: count clocks in @fixed_clks330 * @fixed_factor_clks: list of fixed factor clocks331 * @nr_fixed_factor_clks: count of clocks in @fixed_factor_clks332 * @nr_clk_ids: total number of clocks with IDs assigned333 * @cpu_clks: list of CPU clocks334 * @nr_cpu_clks: count of clocks in @cpu_clks335 * @clk_regs: list of clock registers336 * @nr_clk_regs: count of clock registers in @clk_regs337 * @suspend_regs: list of clock registers to set before suspend338 * @nr_suspend_regs: count of clock registers in @suspend_regs339 * @clk_name: name of the parent clock needed for CMU register access340 * @manual_plls: Enable manual control for PLL clocks341 */342struct samsung_cmu_info {343	const struct samsung_pll_clock *pll_clks;344	unsigned int nr_pll_clks;345	const struct samsung_mux_clock *mux_clks;346	unsigned int nr_mux_clks;347	const struct samsung_div_clock *div_clks;348	unsigned int nr_div_clks;349	const struct samsung_gate_clock *gate_clks;350	unsigned int nr_gate_clks;351	const struct samsung_fixed_rate_clock *fixed_clks;352	unsigned int nr_fixed_clks;353	const struct samsung_fixed_factor_clock *fixed_factor_clks;354	unsigned int nr_fixed_factor_clks;355	unsigned int nr_clk_ids;356	const struct samsung_cpu_clock *cpu_clks;357	unsigned int nr_cpu_clks;358 359	const unsigned long *clk_regs;360	unsigned int nr_clk_regs;361 362	const struct samsung_clk_reg_dump *suspend_regs;363	unsigned int nr_suspend_regs;364	const char *clk_name;365 366	/* ARM64 Exynos CMUs */367	bool manual_plls;368};369 370struct samsung_clk_provider *samsung_clk_init(struct device *dev,371			void __iomem *base, unsigned long nr_clks);372void samsung_clk_of_add_provider(struct device_node *np,373			struct samsung_clk_provider *ctx);374void samsung_clk_of_register_fixed_ext(375			struct samsung_clk_provider *ctx,376			struct samsung_fixed_rate_clock *fixed_rate_clk,377			unsigned int nr_fixed_rate_clk,378			const struct of_device_id *clk_matches);379 380void samsung_clk_add_lookup(struct samsung_clk_provider *ctx,381			struct clk_hw *clk_hw, unsigned int id);382 383void samsung_clk_register_alias(struct samsung_clk_provider *ctx,384			const struct samsung_clock_alias *list,385			unsigned int nr_clk);386void samsung_clk_register_fixed_rate(387			struct samsung_clk_provider *ctx,388			const struct samsung_fixed_rate_clock *clk_list,389			unsigned int nr_clk);390void samsung_clk_register_fixed_factor(391			struct samsung_clk_provider *ctx,392			const struct samsung_fixed_factor_clock *list,393			unsigned int nr_clk);394void samsung_clk_register_mux(struct samsung_clk_provider *ctx,395			const struct samsung_mux_clock *clk_list,396			unsigned int nr_clk);397void samsung_clk_register_div(struct samsung_clk_provider *ctx,398			const struct samsung_div_clock *clk_list,399			unsigned int nr_clk);400void samsung_clk_register_gate(struct samsung_clk_provider *ctx,401			const struct samsung_gate_clock *clk_list,402			unsigned int nr_clk);403void samsung_clk_register_pll(struct samsung_clk_provider *ctx,404			const struct samsung_pll_clock *pll_list,405			unsigned int nr_clk);406void samsung_clk_register_cpu(struct samsung_clk_provider *ctx,407		const struct samsung_cpu_clock *list, unsigned int nr_clk);408 409void samsung_cmu_register_clocks(struct samsung_clk_provider *ctx,410				 const struct samsung_cmu_info *cmu);411struct samsung_clk_provider *samsung_cmu_register_one(412			struct device_node *,413			const struct samsung_cmu_info *);414 415#ifdef CONFIG_PM_SLEEP416void samsung_clk_extended_sleep_init(void __iomem *reg_base,417			const unsigned long *rdump,418			unsigned long nr_rdump,419			const struct samsung_clk_reg_dump *rsuspend,420			unsigned long nr_rsuspend);421#else422static inline void samsung_clk_extended_sleep_init(void __iomem *reg_base,423			const unsigned long *rdump,424			unsigned long nr_rdump,425			const struct samsung_clk_reg_dump *rsuspend,426			unsigned long nr_rsuspend) {}427#endif428#define samsung_clk_sleep_init(reg_base, rdump, nr_rdump) \429	samsung_clk_extended_sleep_init(reg_base, rdump, nr_rdump, NULL, 0)430 431void samsung_clk_save(void __iomem *base,432			struct samsung_clk_reg_dump *rd,433			unsigned int num_regs);434void samsung_clk_restore(void __iomem *base,435			const struct samsung_clk_reg_dump *rd,436			unsigned int num_regs);437struct samsung_clk_reg_dump *samsung_clk_alloc_reg_dump(438			const unsigned long *rdump,439			unsigned long nr_rdump);440 441#endif /* __SAMSUNG_CLK_H */442