Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Maíra Canal and committed by
Stephen Boyd
67229973 c3692998

+34 -4
+34 -4
drivers/clk/bcm/clk-raspberrypi.c
··· 289 289 static int raspberrypi_fw_prepare(struct clk_hw *hw) 290 290 { 291 291 const struct raspberrypi_clk_data *data = clk_hw_to_data(hw); 292 + struct raspberrypi_clk_variant *variant = data->variant; 292 293 struct raspberrypi_clk *rpi = data->rpi; 293 294 u32 state = RPI_FIRMWARE_STATE_ENABLE_BIT; 294 295 int ret; 295 296 296 297 ret = raspberrypi_clock_property(rpi->firmware, data, 297 298 RPI_FIRMWARE_SET_CLOCK_STATE, &state); 298 - if (ret) 299 + if (ret) { 299 300 dev_err_ratelimited(rpi->dev, 300 301 "Failed to set clock %s state to on: %d\n", 301 302 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 + } 302 317 303 318 return ret; 304 319 } ··· 322 307 { 323 308 const struct raspberrypi_clk_data *data = clk_hw_to_data(hw); 324 309 struct raspberrypi_clk *rpi = data->rpi; 310 + unsigned long min_rate, max_rate; 325 311 u32 state = 0; 326 312 int ret; 313 + 314 + clk_hw_get_rate_range(hw, &min_rate, &max_rate); 315 + 316 + /* 317 + * Setting the rate in unprepare is a deviation from the usual CCF 318 + * behavior, where unprepare only gates the clock. However, this is 319 + * needed, as RPI_FIRMWARE_SET_CLOCK_STATE doesn't actually power off 320 + * the clock on current firmware versions. Setting the rate to minimum 321 + * before disabling the clock is the only way to achieve meaningful 322 + * power savings. 323 + * 324 + * This is safe because no consumer should rely on the rate of an 325 + * unprepared clock. Any consumer must call clk_prepare() before use, 326 + * at which point the rate is either restored to maximum (for clocks 327 + * with the 'maximize' flag) or re-established by the consumer. 328 + */ 329 + raspberrypi_fw_set_rate(hw, min_rate, 0); 327 330 328 331 ret = raspberrypi_clock_property(rpi->firmware, data, 329 332 RPI_FIRMWARE_SET_CLOCK_STATE, &state); ··· 419 386 return ERR_PTR(ret); 420 387 } 421 388 } 422 - 423 - if (variant->maximize) 424 - variant->min_rate = max_rate; 425 389 426 390 if (variant->min_rate) { 427 391 unsigned long rate;