forked from mirrors/linux
		
	clk: fix CLK_SET_RATE_GATE with clock rate protection
CLK_SET_RATE_GATE should prevent any operation which may result in a rate change or glitch while the clock is prepared/enabled. IOW, the following sequence is not allowed anymore with CLK_SET_RATE_GATE: * clk_get() * clk_prepare_enable() * clk_get_rate() * clk_set_rate() At the moment this is enforced on the leaf clock of the operation, not along the tree. This problematic because, if a PLL has the CLK_RATE_GATE, it won't be enforced if the clk_set_rate() is called on its child clocks. Using clock rate protection, we can now enforce CLK_SET_RATE_GATE along the clock tree Acked-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Quentin Schulz <quentin.schulz@free-electrons.com> Tested-by: Maxime Ripard <maxime.ripard@free-electrons.com> Signed-off-by: Jerome Brunet <jbrunet@baylibre.com> Signed-off-by: Michael Turquette <mturquette@baylibre.com> Link: lkml.kernel.org/r/20180619134051.16726-3-jbrunet@baylibre.com
This commit is contained in:
		
							parent
							
								
									ce397d215c
								
							
						
					
					
						commit
						9461f7b33d
					
				
					 1 changed files with 13 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -691,6 +691,9 @@ static void clk_core_unprepare(struct clk_core *core)
 | 
			
		|||
	    "Unpreparing critical %s\n", core->name))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (core->flags & CLK_SET_RATE_GATE)
 | 
			
		||||
		clk_core_rate_unprotect(core);
 | 
			
		||||
 | 
			
		||||
	if (--core->prepare_count > 0)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -765,6 +768,16 @@ static int clk_core_prepare(struct clk_core *core)
 | 
			
		|||
 | 
			
		||||
	core->prepare_count++;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * CLK_SET_RATE_GATE is a special case of clock protection
 | 
			
		||||
	 * Instead of a consumer claiming exclusive rate control, it is
 | 
			
		||||
	 * actually the provider which prevents any consumer from making any
 | 
			
		||||
	 * operation which could result in a rate change or rate glitch while
 | 
			
		||||
	 * the clock is prepared.
 | 
			
		||||
	 */
 | 
			
		||||
	if (core->flags & CLK_SET_RATE_GATE)
 | 
			
		||||
		clk_core_rate_protect(core);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
unprepare:
 | 
			
		||||
	clk_core_unprepare(core->parent);
 | 
			
		||||
| 
						 | 
				
			
			@ -1888,9 +1901,6 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
 | 
			
		|||
	if (clk_core_rate_is_protected(core))
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	if ((core->flags & CLK_SET_RATE_GATE) && core->prepare_count)
 | 
			
		||||
		return -EBUSY;
 | 
			
		||||
 | 
			
		||||
	/* calculate new rates and get the topmost changed clock */
 | 
			
		||||
	top = clk_calc_new_rates(core, req_rate);
 | 
			
		||||
	if (!top)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue