mirror of
				https://github.com/smaeul/u-boot.git
				synced 2025-11-04 05:50:17 +00:00 
			
		
		
		
	Convert UTF-8 chars to ASCII in cases where make sense. No Copyright or names are converted. Signed-off-by: Michal Simek <michal.simek@amd.com> Reviewed-by: Tom Rini <trini@konsulko.com> Acked-by: Marek Behún <kabel@kernel.org>
		
			
				
	
	
		
			277 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			277 lines
		
	
	
		
			8.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0-or-later OR BSD-3-Clause */
 | 
						|
/*
 | 
						|
 * Copyright (C) STMicroelectronics 2022 - All Rights Reserved
 | 
						|
 * Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
 | 
						|
 */
 | 
						|
 | 
						|
struct stm32_clock_match_data;
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32_mux_cfg - multiplexer configuration
 | 
						|
 *
 | 
						|
 * @parent_names:	array of string names for all possible parents
 | 
						|
 * @num_parents:	number of possible parents
 | 
						|
 * @reg_off:		register controlling multiplexer
 | 
						|
 * @shift:		shift to multiplexer bit field
 | 
						|
 * @width:		width of the multiplexer bit field
 | 
						|
 * @mux_flags:		hardware-specific flags
 | 
						|
 * @table:		array of register values corresponding to the parent
 | 
						|
 *			index
 | 
						|
 */
 | 
						|
struct stm32_mux_cfg {
 | 
						|
	const char * const *parent_names;
 | 
						|
	u8 num_parents;
 | 
						|
	u32 reg_off;
 | 
						|
	u8 shift;
 | 
						|
	u8 width;
 | 
						|
	u8 mux_flags;
 | 
						|
	u32 *table;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32_gate_cfg - gating configuration
 | 
						|
 *
 | 
						|
 * @reg_off:	register controlling gate
 | 
						|
 * @bit_idx:	single bit controlling gate
 | 
						|
 * @gate_flags:	hardware-specific flags
 | 
						|
 * @set_clr:	0 : normal gate, 1 : has a register to clear the gate
 | 
						|
 */
 | 
						|
struct stm32_gate_cfg {
 | 
						|
	u32 reg_off;
 | 
						|
	u8 bit_idx;
 | 
						|
	u8 gate_flags;
 | 
						|
	u8 set_clr;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32_div_cfg - divider configuration
 | 
						|
 *
 | 
						|
 * @reg_off:	register containing the divider
 | 
						|
 * @shift:	shift to the divider bit field
 | 
						|
 * @width:	width of the divider bit field
 | 
						|
 * @table:	array of value/divider pairs, last entry should have div = 0
 | 
						|
 */
 | 
						|
struct stm32_div_cfg {
 | 
						|
	u32 reg_off;
 | 
						|
	u8 shift;
 | 
						|
	u8 width;
 | 
						|
	u8 div_flags;
 | 
						|
	const struct clk_div_table *table;
 | 
						|
};
 | 
						|
 | 
						|
#define NO_STM32_MUX	-1
 | 
						|
#define NO_STM32_DIV	-1
 | 
						|
#define NO_STM32_GATE	-1
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32_composite_cfg - composite configuration
 | 
						|
 *
 | 
						|
 * @mux:	index of a multiplexer
 | 
						|
 * @gate:	index of a gate
 | 
						|
 * @div:	index of a divider
 | 
						|
 */
 | 
						|
struct stm32_composite_cfg {
 | 
						|
	int mux;
 | 
						|
	int gate;
 | 
						|
	int div;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct clock_config - clock configuration
 | 
						|
 *
 | 
						|
 * @id:			binding id of the clock
 | 
						|
 * @name:		clock name
 | 
						|
 * @parent_name:	name of the clock parent
 | 
						|
 * @flags:		framework-specific flags
 | 
						|
 * @sec_id:		secure id (use to known if the clock is secured or not)
 | 
						|
 * @clock_cfg:		specific clock data configuration
 | 
						|
 * @setup:		specific call back to reister the clock (will use
 | 
						|
 *			clock_cfg data as input)
 | 
						|
 */
 | 
						|
struct clock_config {
 | 
						|
	unsigned long id;
 | 
						|
	const char *name;
 | 
						|
	const char *parent_name;
 | 
						|
	unsigned long flags;
 | 
						|
	int sec_id;
 | 
						|
	void *clock_cfg;
 | 
						|
 | 
						|
	struct clk *(*setup)(struct udevice *dev,
 | 
						|
			     const struct clock_config *cfg);
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct clk_stm32_clock_data - clock data
 | 
						|
 *
 | 
						|
 * @num_gates:		number of defined gates
 | 
						|
 * @gates:		array of gate configuration
 | 
						|
 * @muxes:		array of multiplexer configuration
 | 
						|
 * @dividers:		array of divider configuration
 | 
						|
 */
 | 
						|
struct clk_stm32_clock_data {
 | 
						|
	unsigned int num_gates;
 | 
						|
	const struct stm32_gate_cfg *gates;
 | 
						|
	const struct stm32_mux_cfg *muxes;
 | 
						|
	const struct stm32_div_cfg *dividers;
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32_clock_match_data - clock match data
 | 
						|
 *
 | 
						|
 * @num_gates:		number of clocks
 | 
						|
 * @tab_clocks:		array of clock configuration
 | 
						|
 * @clock_data:		definition of all gates / dividers / multiplexers
 | 
						|
 * @check_security:	call back to check if clock is secured or not
 | 
						|
 */
 | 
						|
struct stm32_clock_match_data {
 | 
						|
	unsigned int num_clocks;
 | 
						|
	const struct clock_config *tab_clocks;
 | 
						|
	const struct clk_stm32_clock_data *clock_data;
 | 
						|
	int (*check_security)(void __iomem *base,
 | 
						|
			      const struct clock_config *cfg);
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
 * struct stm32mp_rcc_priv - private struct for stm32mp clocks
 | 
						|
 *
 | 
						|
 * @base:	base register of RCC driver
 | 
						|
 * @gate_cpt:	array of refcounting for gate with more than one
 | 
						|
 *		clocks as input. See explanation of Peripheral clock enabling
 | 
						|
 *              below.
 | 
						|
 * @data:	data for gate / divider / multiplexer configuration
 | 
						|
 */
 | 
						|
struct stm32mp_rcc_priv {
 | 
						|
	void __iomem *base;
 | 
						|
	u8 *gate_cpt;
 | 
						|
	const struct clk_stm32_clock_data *data;
 | 
						|
};
 | 
						|
 | 
						|
int stm32_rcc_init(struct udevice *dev,
 | 
						|
		   const struct stm32_clock_match_data *data);
 | 
						|
 | 
						|
/**
 | 
						|
 * STM32 Gate
 | 
						|
 *
 | 
						|
 *               PCE (Peripheral Clock Enabling)                  Peripheral
 | 
						|
 *
 | 
						|
 *                ------------------------------                   ----------
 | 
						|
 *               |                              |                 |          |
 | 
						|
 *               |                              |                 |   PERx   |
 | 
						|
 * bus_ck        |                   -----      |                 |          |
 | 
						|
 * ------------->|------------------|     |     |  ckg_bus_perx   |          |
 | 
						|
 *               |                  | AND |-----|---------------->|          |
 | 
						|
 *               |       -----------|     |     |                 |          |
 | 
						|
 *               |      |            -----      |                 |          |
 | 
						|
 *               |      |                       |                 |          |
 | 
						|
 *               |    -----                     |                 |          |
 | 
						|
 * Perx_EN |-----|---| GCL |  Gating            |                 |          |
 | 
						|
 *               |    -----   Control           |                 |          |
 | 
						|
 *               |      |     Logic             |                 |          |
 | 
						|
 *               |      |                       |                 |          |
 | 
						|
 *               |      |            -----      |                 |          |
 | 
						|
 *               |       -----------|     |     |  ckg_ker_perx   |          |
 | 
						|
 * perx_ker_ck   |                  | AND |-----|---------------->|          |
 | 
						|
 * ------------->|------------------|     |     |                 |          |
 | 
						|
 *               |                   -----      |                 |          |
 | 
						|
 *               |                              |                 |          |
 | 
						|
 *               |                              |                 |          |
 | 
						|
 *                ------------------------------                   ----------
 | 
						|
 | 
						|
 * Each peripheral requires a bus interface clock, named ckg_bus_perx
 | 
						|
 * (for peripheral `x').
 | 
						|
 * Some peripherals (SAI, UART...) need also a dedicated clock for their
 | 
						|
 * communication interface, this clock is generally asynchronous with respect to
 | 
						|
 * the bus interface clock, and is named kernel clock (ckg_ker_perx).
 | 
						|
 | 
						|
 * Both clocks can be gated by one Perx_EN enable bit.
 | 
						|
 * Then we have to manage a refcounting on gate level to avoid gate if one
 | 
						|
 * the bus or the Kernel was enable.
 | 
						|
 *
 | 
						|
 * Example:
 | 
						|
 * 1) enable the bus clock
 | 
						|
 *	--> bus_clk ref_counting = 1, gate_ref_count = 1
 | 
						|
 * 2) enable the kernel clock
 | 
						|
 *	--> perx_ker_ck ref_counting = 1, gate_ref_count = 2
 | 
						|
 * 3) disable kernel clock
 | 
						|
 * 	---> perx_ker_ck ref_counting = 0, gate_ref_count = 1
 | 
						|
 * 	==> then i will not gate because gate_ref_count > 0
 | 
						|
 * 4) disable bus clock
 | 
						|
 *	--> bus_clk  ref_counting  = 0, gate_ref_count = 0
 | 
						|
 *	==> then i can gate (write in the register) because
 | 
						|
 *	    gate_ref_count = 0
 | 
						|
 */
 | 
						|
 | 
						|
struct clk_stm32_gate {
 | 
						|
	struct clk clk;
 | 
						|
	struct stm32mp_rcc_priv *priv;
 | 
						|
	int gate_id;
 | 
						|
};
 | 
						|
 | 
						|
#define to_clk_stm32_gate(_clk) container_of(_clk, struct clk_stm32_gate, clk)
 | 
						|
 | 
						|
struct clk *
 | 
						|
clk_stm32_gate_register(struct udevice *dev,
 | 
						|
			const struct clock_config *cfg);
 | 
						|
 | 
						|
struct clk *
 | 
						|
clk_stm32_register_composite(struct udevice *dev,
 | 
						|
			     const struct clock_config *cfg);
 | 
						|
 | 
						|
struct stm32_clk_gate_cfg {
 | 
						|
	int gate_id;
 | 
						|
};
 | 
						|
 | 
						|
#define STM32_GATE(_id, _name, _parent, _flags, _gate_id, _sec_id) \
 | 
						|
{ \
 | 
						|
	.id		= _id, \
 | 
						|
	.sec_id		= _sec_id, \
 | 
						|
	.name		= _name, \
 | 
						|
	.parent_name	= _parent, \
 | 
						|
	.flags		= _flags, \
 | 
						|
	.clock_cfg	= &(struct stm32_clk_gate_cfg) { \
 | 
						|
		.gate_id	= _gate_id, \
 | 
						|
	}, \
 | 
						|
	.setup		= clk_stm32_gate_register, \
 | 
						|
}
 | 
						|
 | 
						|
struct stm32_clk_composite_cfg {
 | 
						|
	int	gate_id;
 | 
						|
	int	mux_id;
 | 
						|
	int	div_id;
 | 
						|
};
 | 
						|
 | 
						|
#define STM32_COMPOSITE(_id, _name, _flags, _sec_id, \
 | 
						|
			_gate_id, _mux_id, _div_id) \
 | 
						|
{ \
 | 
						|
	.id		= _id, \
 | 
						|
	.name		= _name, \
 | 
						|
	.sec_id		= _sec_id, \
 | 
						|
	.flags		= _flags, \
 | 
						|
	.clock_cfg	= &(struct stm32_clk_composite_cfg) { \
 | 
						|
		.gate_id	= _gate_id, \
 | 
						|
		.mux_id		= _mux_id, \
 | 
						|
		.div_id		= _div_id, \
 | 
						|
	}, \
 | 
						|
	.setup		= clk_stm32_register_composite, \
 | 
						|
}
 | 
						|
 | 
						|
#define STM32_COMPOSITE_NOMUX(_id, _name, _parent, _flags, _sec_id, \
 | 
						|
			      _gate_id, _div_id) \
 | 
						|
{ \
 | 
						|
	.id		= _id, \
 | 
						|
	.name		= _name, \
 | 
						|
	.parent_name	= _parent, \
 | 
						|
	.sec_id		= _sec_id, \
 | 
						|
	.flags		= _flags, \
 | 
						|
	.clock_cfg	= &(struct stm32_clk_composite_cfg) { \
 | 
						|
		.gate_id	= _gate_id, \
 | 
						|
		.mux_id		= NO_STM32_MUX, \
 | 
						|
		.div_id		= _div_id, \
 | 
						|
	}, \
 | 
						|
	.setup		= clk_stm32_register_composite, \
 | 
						|
}
 | 
						|
 | 
						|
extern const struct clk_ops stm32_clk_ops;
 | 
						|
 | 
						|
ulong clk_stm32_get_rate_by_name(const char *name);
 |