summaryrefslogtreecommitdiff
path: root/drivers/clk/bcm/clk-raspberrypi.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/bcm/clk-raspberrypi.c')
-rw-r--r--drivers/clk/bcm/clk-raspberrypi.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c
index c879f2e9a4a7..9d09621549b9 100644
--- a/drivers/clk/bcm/clk-raspberrypi.c
+++ b/drivers/clk/bcm/clk-raspberrypi.c
@@ -77,6 +77,7 @@ struct raspberrypi_clk_variant {
bool export;
char *clkdev;
unsigned long min_rate;
+ bool minimize;
};
static struct raspberrypi_clk_variant
@@ -87,6 +88,18 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NUM_CLK_ID] = {
},
[RPI_FIRMWARE_CORE_CLK_ID] = {
.export = true,
+
+ /*
+ * The clock is shared between the HVS and the CSI
+ * controllers, on the BCM2711 and will change depending
+ * on the pixels composited on the HVS and the capture
+ * resolution on Unicam.
+ *
+ * Since the rate can get quite large, and we need to
+ * coordinate between both driver instances, let's
+ * always use the minimum the drivers will let us.
+ */
+ .minimize = true,
},
[RPI_FIRMWARE_M2MC_CLK_ID] = {
.export = true,
@@ -102,6 +115,16 @@ raspberrypi_clk_variants[RPI_FIRMWARE_NUM_CLK_ID] = {
* in this situation.
*/
.min_rate = 120000000,
+
+ /*
+ * The clock is shared between the two HDMI controllers
+ * on the BCM2711 and will change depending on the
+ * resolution output on each. Since the rate can get
+ * quite large, and we need to coordinate between both
+ * driver instances, let's always use the minimum the
+ * drivers will let us.
+ */
+ .minimize = true,
},
[RPI_FIRMWARE_V3D_CLK_ID] = {
.export = true,
@@ -206,12 +229,26 @@ static int raspberrypi_fw_set_rate(struct clk_hw *hw, unsigned long rate,
static int raspberrypi_fw_dumb_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
+ struct raspberrypi_clk_data *data =
+ container_of(hw, struct raspberrypi_clk_data, hw);
+ struct raspberrypi_clk_variant *variant = data->variant;
+
/*
* The firmware will do the rounding but that isn't part of
* the interface with the firmware, so we just do our best
* here.
*/
+
req->rate = clamp(req->rate, req->min_rate, req->max_rate);
+
+ /*
+ * We want to aggressively reduce the clock rate here, so let's
+ * just ignore the requested rate and return the bare minimum
+ * rate we can get away with.
+ */
+ if (variant->minimize && req->min_rate > 0)
+ req->rate = req->min_rate;
+
return 0;
}