drm/etnaviv: implement cooling support for new GPU cores
authorLucas Stach <l.stach@pengutronix.de>
Tue, 11 Apr 2017 13:54:50 +0000 (15:54 +0200)
committerLucas Stach <l.stach@pengutronix.de>
Fri, 5 May 2017 15:14:51 +0000 (17:14 +0200)
GPU cores with the DYNAMIC_FREQUENCY_SCALING feature bit set expect the
platform to provide the clock scaling and ignore any requests to use the
internal FSCALE divider. Writes to this register still work, but don't
have any effect on the GPU clock frequency.

Save the initial core and shader clock frequency and ask the platform
to provide a slower clock when cooling is requested.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
drivers/gpu/drm/etnaviv/etnaviv_gpu.c
drivers/gpu/drm/etnaviv/etnaviv_gpu.h

index d4c7b443a757c24c8de78eadb38b89903149f244..ada45fdd0eaeead886cd7cac4068ad5f97c53add 100644 (file)
@@ -412,13 +412,19 @@ static void etnaviv_gpu_load_clock(struct etnaviv_gpu *gpu, u32 clock)
 
 static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu)
 {
-       unsigned int fscale = 1 << (6 - gpu->freq_scale);
-       u32 clock;
-
-       clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
-               VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
+       if (gpu->identity.minor_features2 &
+           chipMinorFeatures2_DYNAMIC_FREQUENCY_SCALING) {
+               clk_set_rate(gpu->clk_core,
+                            gpu->base_rate_core >> gpu->freq_scale);
+               clk_set_rate(gpu->clk_shader,
+                            gpu->base_rate_shader >> gpu->freq_scale);
+       } else {
+               unsigned int fscale = 1 << (6 - gpu->freq_scale);
+               u32 clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS |
+                           VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale);
 
-       etnaviv_gpu_load_clock(gpu, clock);
+               etnaviv_gpu_load_clock(gpu, clock);
+       }
 }
 
 static int etnaviv_hw_reset(struct etnaviv_gpu *gpu)
@@ -1742,11 +1748,13 @@ static int etnaviv_gpu_platform_probe(struct platform_device *pdev)
        DBG("clk_core: %p", gpu->clk_core);
        if (IS_ERR(gpu->clk_core))
                gpu->clk_core = NULL;
+       gpu->base_rate_core = clk_get_rate(gpu->clk_core);
 
        gpu->clk_shader = devm_clk_get(&pdev->dev, "shader");
        DBG("clk_shader: %p", gpu->clk_shader);
        if (IS_ERR(gpu->clk_shader))
                gpu->clk_shader = NULL;
+       gpu->base_rate_shader = clk_get_rate(gpu->clk_shader);
 
        /* TODO: figure out max mapped size */
        dev_set_drvdata(dev, gpu);
index 9227a97404473baa373d2ce2934dcf2cf497a7b7..689cb8f3680c97bcd62836bfd90885f134862650 100644 (file)
@@ -152,6 +152,8 @@ struct etnaviv_gpu {
        u32 hangcheck_dma_addr;
        struct work_struct recover_work;
        unsigned int freq_scale;
+       unsigned long base_rate_core;
+       unsigned long base_rate_shader;
 };
 
 static inline void gpu_write(struct etnaviv_gpu *gpu, u32 reg, u32 data)