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

clk: bcm: rpi: Run some clocks at the minimum rate allowed

The core clock and M2MC clocks are shared between some devices (Unicam
controllers and the HVS, and the HDMI controllers, respectively) that
will have various, varying, requirements depending on their current work
load.

Since those loads can require a fairly high clock rate in extreme
conditions (up to ~600MHz), we can end up running those clocks at their
maximum frequency even though we no longer require such a high rate.

Fortunately, those devices don't require an exact rate but a minimum
rate, and all the drivers are using clk_set_min_rate. Thus, we can just
rely on the fact that the clk_request minimum (which is the aggregated
minimum of all the clock users) is what we want at all times.

Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220225143534.405820-11-maxime@cerno.tech
Signed-off-by: Stephen Boyd <sboyd@kernel.org>

authored by

Maxime Ripard and committed by
Stephen Boyd
e9d6cea2 542acfec

+37
+37
drivers/clk/bcm/clk-raspberrypi.c
··· 77 77 bool export; 78 78 char *clkdev; 79 79 unsigned long min_rate; 80 + bool minimize; 80 81 }; 81 82 82 83 static struct raspberrypi_clk_variant ··· 88 87 }, 89 88 [RPI_FIRMWARE_CORE_CLK_ID] = { 90 89 .export = true, 90 + 91 + /* 92 + * The clock is shared between the HVS and the CSI 93 + * controllers, on the BCM2711 and will change depending 94 + * on the pixels composited on the HVS and the capture 95 + * resolution on Unicam. 96 + * 97 + * Since the rate can get quite large, and we need to 98 + * coordinate between both driver instances, let's 99 + * always use the minimum the drivers will let us. 100 + */ 101 + .minimize = true, 91 102 }, 92 103 [RPI_FIRMWARE_M2MC_CLK_ID] = { 93 104 .export = true, ··· 115 102 * in this situation. 116 103 */ 117 104 .min_rate = 120000000, 105 + 106 + /* 107 + * The clock is shared between the two HDMI controllers 108 + * on the BCM2711 and will change depending on the 109 + * resolution output on each. Since the rate can get 110 + * quite large, and we need to coordinate between both 111 + * driver instances, let's always use the minimum the 112 + * drivers will let us. 113 + */ 114 + .minimize = true, 118 115 }, 119 116 [RPI_FIRMWARE_V3D_CLK_ID] = { 120 117 .export = true, ··· 229 206 static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw, 230 207 struct clk_rate_request *req) 231 208 { 209 + struct raspberrypi_clk_data *data = 210 + container_of(hw, struct raspberrypi_clk_data, hw); 211 + struct raspberrypi_clk_variant *variant = data->variant; 212 + 232 213 /* 233 214 * The firmware will do the rounding but that isn't part of 234 215 * the interface with the firmware, so we just do our best 235 216 * here. 236 217 */ 218 + 237 219 req->rate = clamp(req->rate, req->min_rate, req->max_rate); 220 + 221 + /* 222 + * We want to aggressively reduce the clock rate here, so let's 223 + * just ignore the requested rate and return the bare minimum 224 + * rate we can get away with. 225 + */ 226 + if (variant->minimize && req->min_rate > 0) 227 + req->rate = req->min_rate; 228 + 238 229 return 0; 239 230 } 240 231