Skip to content

Commit 6722997

Browse files
mairacanalbebarino
authored andcommitted
clk: bcm: rpi: Manage clock rate in prepare/unprepare callbacks
On current firmware versions, RPI_FIRMWARE_SET_CLOCK_STATE doesn't actually power off the clock. To achieve meaningful power savings, the clock rate must be set to the minimum before disabling. This might be fixed in future firmware releases. Rather than pushing rate management to clock consumers, handle it directly in the clock framework's prepare/unprepare callbacks. In unprepare, set the rate to the minimum before disabling the clock. In prepare, for clocks marked with `maximize` (currently v3d), restore the rate to the maximum after enabling. Signed-off-by: Maíra Canal <mcanal@igalia.com> Reviewed-by: Maxime Ripard <mripard@kernel.org> Signed-off-by: Stephen Boyd <sboyd@kernel.org>
1 parent c369299 commit 6722997

1 file changed

Lines changed: 34 additions & 4 deletions

File tree

drivers/clk/bcm/clk-raspberrypi.c

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,16 +289,31 @@ static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
289289
static int raspberrypi_fw_prepare(struct clk_hw *hw)
290290
{
291291
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
292+
struct raspberrypi_clk_variant *variant = data->variant;
292293
struct raspberrypi_clk *rpi = data->rpi;
293294
u32 state = RPI_FIRMWARE_STATE_ENABLE_BIT;
294295
int ret;
295296

296297
ret = raspberrypi_clock_property(rpi->firmware, data,
297298
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
298-
if (ret)
299+
if (ret) {
299300
dev_err_ratelimited(rpi->dev,
300301
"Failed to set clock %s state to on: %d\n",
301302
clk_hw_get_name(hw), ret);
303+
return ret;
304+
}
305+
306+
/*
307+
* For clocks marked with 'maximize', restore the rate to the
308+
* maximum after enabling. This compensates for the rate being
309+
* set to minimum during unprepare (see raspberrypi_fw_unprepare).
310+
*/
311+
if (variant->maximize) {
312+
unsigned long min_rate, max_rate;
313+
314+
clk_hw_get_rate_range(hw, &min_rate, &max_rate);
315+
ret = raspberrypi_fw_set_rate(hw, max_rate, 0);
316+
}
302317

303318
return ret;
304319
}
@@ -307,9 +322,27 @@ static void raspberrypi_fw_unprepare(struct clk_hw *hw)
307322
{
308323
const struct raspberrypi_clk_data *data = clk_hw_to_data(hw);
309324
struct raspberrypi_clk *rpi = data->rpi;
325+
unsigned long min_rate, max_rate;
310326
u32 state = 0;
311327
int ret;
312328

329+
clk_hw_get_rate_range(hw, &min_rate, &max_rate);
330+
331+
/*
332+
* Setting the rate in unprepare is a deviation from the usual CCF
333+
* behavior, where unprepare only gates the clock. However, this is
334+
* needed, as RPI_FIRMWARE_SET_CLOCK_STATE doesn't actually power off
335+
* the clock on current firmware versions. Setting the rate to minimum
336+
* before disabling the clock is the only way to achieve meaningful
337+
* power savings.
338+
*
339+
* This is safe because no consumer should rely on the rate of an
340+
* unprepared clock. Any consumer must call clk_prepare() before use,
341+
* at which point the rate is either restored to maximum (for clocks
342+
* with the 'maximize' flag) or re-established by the consumer.
343+
*/
344+
raspberrypi_fw_set_rate(hw, min_rate, 0);
345+
313346
ret = raspberrypi_clock_property(rpi->firmware, data,
314347
RPI_FIRMWARE_SET_CLOCK_STATE, &state);
315348
if (ret)
@@ -387,9 +420,6 @@ static struct clk_hw *raspberrypi_clk_register(struct raspberrypi_clk *rpi,
387420
}
388421
}
389422

390-
if (variant->maximize)
391-
variant->min_rate = max_rate;
392-
393423
if (variant->min_rate) {
394424
unsigned long rate;
395425

0 commit comments

Comments
 (0)