root/drivers/gpu/drm/msm/disp/dpu1/dpu_io_util.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. msm_dss_put_clk
  2. msm_dss_get_clk
  3. msm_dss_clk_set_rate
  4. msm_dss_enable_clk
  5. msm_dss_parse_clock

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /* Copyright (c) 2012-2015, 2017-2018, The Linux Foundation.
   3  * All rights reserved.
   4  */
   5 
   6 #include <linux/clk.h>
   7 #include <linux/clk/clk-conf.h>
   8 #include <linux/err.h>
   9 #include <linux/delay.h>
  10 #include <linux/of.h>
  11 
  12 #include <drm/drm_print.h>
  13 
  14 #include "dpu_io_util.h"
  15 
  16 void msm_dss_put_clk(struct dss_clk *clk_arry, int num_clk)
  17 {
  18         int i;
  19 
  20         for (i = num_clk - 1; i >= 0; i--) {
  21                 if (clk_arry[i].clk)
  22                         clk_put(clk_arry[i].clk);
  23                 clk_arry[i].clk = NULL;
  24         }
  25 }
  26 
  27 int msm_dss_get_clk(struct device *dev, struct dss_clk *clk_arry, int num_clk)
  28 {
  29         int i, rc = 0;
  30 
  31         for (i = 0; i < num_clk; i++) {
  32                 clk_arry[i].clk = clk_get(dev, clk_arry[i].clk_name);
  33                 rc = PTR_ERR_OR_ZERO(clk_arry[i].clk);
  34                 if (rc) {
  35                         DEV_ERR("%pS->%s: '%s' get failed. rc=%d\n",
  36                                 __builtin_return_address(0), __func__,
  37                                 clk_arry[i].clk_name, rc);
  38                         goto error;
  39                 }
  40         }
  41 
  42         return rc;
  43 
  44 error:
  45         for (i--; i >= 0; i--) {
  46                 if (clk_arry[i].clk)
  47                         clk_put(clk_arry[i].clk);
  48                 clk_arry[i].clk = NULL;
  49         }
  50 
  51         return rc;
  52 }
  53 
  54 int msm_dss_clk_set_rate(struct dss_clk *clk_arry, int num_clk)
  55 {
  56         int i, rc = 0;
  57 
  58         for (i = 0; i < num_clk; i++) {
  59                 if (clk_arry[i].clk) {
  60                         if (clk_arry[i].type != DSS_CLK_AHB) {
  61                                 DEV_DBG("%pS->%s: '%s' rate %ld\n",
  62                                         __builtin_return_address(0), __func__,
  63                                         clk_arry[i].clk_name,
  64                                         clk_arry[i].rate);
  65                                 rc = clk_set_rate(clk_arry[i].clk,
  66                                         clk_arry[i].rate);
  67                                 if (rc) {
  68                                         DEV_ERR("%pS->%s: %s failed. rc=%d\n",
  69                                                 __builtin_return_address(0),
  70                                                 __func__,
  71                                                 clk_arry[i].clk_name, rc);
  72                                         break;
  73                                 }
  74                         }
  75                 } else {
  76                         DEV_ERR("%pS->%s: '%s' is not available\n",
  77                                 __builtin_return_address(0), __func__,
  78                                 clk_arry[i].clk_name);
  79                         rc = -EPERM;
  80                         break;
  81                 }
  82         }
  83 
  84         return rc;
  85 }
  86 
  87 int msm_dss_enable_clk(struct dss_clk *clk_arry, int num_clk, int enable)
  88 {
  89         int i, rc = 0;
  90 
  91         if (enable) {
  92                 for (i = 0; i < num_clk; i++) {
  93                         DEV_DBG("%pS->%s: enable '%s'\n",
  94                                 __builtin_return_address(0), __func__,
  95                                 clk_arry[i].clk_name);
  96                         if (clk_arry[i].clk) {
  97                                 rc = clk_prepare_enable(clk_arry[i].clk);
  98                                 if (rc)
  99                                         DEV_ERR("%pS->%s: %s en fail. rc=%d\n",
 100                                                 __builtin_return_address(0),
 101                                                 __func__,
 102                                                 clk_arry[i].clk_name, rc);
 103                         } else {
 104                                 DEV_ERR("%pS->%s: '%s' is not available\n",
 105                                         __builtin_return_address(0), __func__,
 106                                         clk_arry[i].clk_name);
 107                                 rc = -EPERM;
 108                         }
 109 
 110                         if (rc && i) {
 111                                 msm_dss_enable_clk(&clk_arry[i - 1],
 112                                         i - 1, false);
 113                                 break;
 114                         }
 115                 }
 116         } else {
 117                 for (i = num_clk - 1; i >= 0; i--) {
 118                         DEV_DBG("%pS->%s: disable '%s'\n",
 119                                 __builtin_return_address(0), __func__,
 120                                 clk_arry[i].clk_name);
 121 
 122                         if (clk_arry[i].clk)
 123                                 clk_disable_unprepare(clk_arry[i].clk);
 124                         else
 125                                 DEV_ERR("%pS->%s: '%s' is not available\n",
 126                                         __builtin_return_address(0), __func__,
 127                                         clk_arry[i].clk_name);
 128                 }
 129         }
 130 
 131         return rc;
 132 }
 133 
 134 int msm_dss_parse_clock(struct platform_device *pdev,
 135                         struct dss_module_power *mp)
 136 {
 137         u32 i, rc = 0;
 138         const char *clock_name;
 139         int num_clk = 0;
 140 
 141         if (!pdev || !mp)
 142                 return -EINVAL;
 143 
 144         mp->num_clk = 0;
 145         num_clk = of_property_count_strings(pdev->dev.of_node, "clock-names");
 146         if (num_clk <= 0) {
 147                 pr_debug("clocks are not defined\n");
 148                 return 0;
 149         }
 150 
 151         mp->clk_config = devm_kcalloc(&pdev->dev,
 152                                       num_clk, sizeof(struct dss_clk),
 153                                       GFP_KERNEL);
 154         if (!mp->clk_config)
 155                 return -ENOMEM;
 156 
 157         for (i = 0; i < num_clk; i++) {
 158                 rc = of_property_read_string_index(pdev->dev.of_node,
 159                                                    "clock-names", i,
 160                                                    &clock_name);
 161                 if (rc) {
 162                         DRM_DEV_ERROR(&pdev->dev, "Failed to get clock name for %d\n",
 163                                 i);
 164                         break;
 165                 }
 166                 strlcpy(mp->clk_config[i].clk_name, clock_name,
 167                         sizeof(mp->clk_config[i].clk_name));
 168 
 169                 mp->clk_config[i].type = DSS_CLK_AHB;
 170         }
 171 
 172         rc = msm_dss_get_clk(&pdev->dev, mp->clk_config, num_clk);
 173         if (rc) {
 174                 DRM_DEV_ERROR(&pdev->dev, "Failed to get clock refs %d\n", rc);
 175                 goto err;
 176         }
 177 
 178         rc = of_clk_set_defaults(pdev->dev.of_node, false);
 179         if (rc) {
 180                 DRM_DEV_ERROR(&pdev->dev, "Failed to set clock defaults %d\n", rc);
 181                 goto err;
 182         }
 183 
 184         for (i = 0; i < num_clk; i++) {
 185                 u32 rate = clk_get_rate(mp->clk_config[i].clk);
 186                 if (!rate)
 187                         continue;
 188                 mp->clk_config[i].rate = rate;
 189                 mp->clk_config[i].type = DSS_CLK_PCLK;
 190         }
 191 
 192         mp->num_clk = num_clk;
 193         return 0;
 194 
 195 err:
 196         msm_dss_put_clk(mp->clk_config, num_clk);
 197         return rc;
 198 }

/* [<][>][^][v][top][bottom][index][help] */