root/arch/arm/mach-omap2/vp.c

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

DEFINITIONS

This source file includes following definitions.
  1. _vp_set_init_voltage
  2. omap_vp_init
  3. omap_vp_update_errorgain
  4. omap_vp_forceupdate_scale
  5. omap_vp_enable
  6. omap_vp_disable

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <linux/kernel.h>
   3 #include <linux/init.h>
   4 
   5 #include "common.h"
   6 
   7 #include "voltage.h"
   8 #include "vp.h"
   9 #include "prm-regbits-34xx.h"
  10 #include "prm-regbits-44xx.h"
  11 #include "prm44xx.h"
  12 
  13 static u32 _vp_set_init_voltage(struct voltagedomain *voltdm, u32 volt)
  14 {
  15         struct omap_vp_instance *vp = voltdm->vp;
  16         u32 vpconfig;
  17         char vsel;
  18 
  19         vsel = voltdm->pmic->uv_to_vsel(volt);
  20 
  21         vpconfig = voltdm->read(vp->vpconfig);
  22         vpconfig &= ~(vp->common->vpconfig_initvoltage_mask |
  23                       vp->common->vpconfig_forceupdate |
  24                       vp->common->vpconfig_initvdd);
  25         vpconfig |= vsel << __ffs(vp->common->vpconfig_initvoltage_mask);
  26         voltdm->write(vpconfig, vp->vpconfig);
  27 
  28         /* Trigger initVDD value copy to voltage processor */
  29         voltdm->write((vpconfig | vp->common->vpconfig_initvdd),
  30                        vp->vpconfig);
  31 
  32         /* Clear initVDD copy trigger bit */
  33         voltdm->write(vpconfig, vp->vpconfig);
  34 
  35         return vpconfig;
  36 }
  37 
  38 /* Generic voltage init functions */
  39 void __init omap_vp_init(struct voltagedomain *voltdm)
  40 {
  41         struct omap_vp_instance *vp = voltdm->vp;
  42         u32 val, sys_clk_rate, timeout, waittime;
  43         u32 vddmin, vddmax, vstepmin, vstepmax;
  44 
  45         if (!voltdm->pmic || !voltdm->pmic->uv_to_vsel) {
  46                 pr_err("%s: No PMIC info for vdd_%s\n", __func__, voltdm->name);
  47                 return;
  48         }
  49 
  50         if (!voltdm->read || !voltdm->write) {
  51                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
  52                         __func__, voltdm->name);
  53                 return;
  54         }
  55 
  56         vp->enabled = false;
  57 
  58         /* Divide to avoid overflow */
  59         sys_clk_rate = voltdm->sys_clk.rate / 1000;
  60 
  61         timeout = (sys_clk_rate * voltdm->pmic->vp_timeout_us) / 1000;
  62         vddmin = max(voltdm->vp_param->vddmin, voltdm->pmic->vddmin);
  63         vddmax = min(voltdm->vp_param->vddmax, voltdm->pmic->vddmax);
  64         vddmin = voltdm->pmic->uv_to_vsel(vddmin);
  65         vddmax = voltdm->pmic->uv_to_vsel(vddmax);
  66 
  67         waittime = DIV_ROUND_UP(voltdm->pmic->step_size * sys_clk_rate,
  68                                 1000 * voltdm->pmic->slew_rate);
  69         vstepmin = voltdm->pmic->vp_vstepmin;
  70         vstepmax = voltdm->pmic->vp_vstepmax;
  71 
  72         /*
  73          * VP_CONFIG: error gain is not set here, it will be updated
  74          * on each scale, based on OPP.
  75          */
  76         val = (voltdm->pmic->vp_erroroffset <<
  77                __ffs(voltdm->vp->common->vpconfig_erroroffset_mask)) |
  78                 vp->common->vpconfig_timeouten;
  79         voltdm->write(val, vp->vpconfig);
  80 
  81         /* VSTEPMIN */
  82         val = (waittime << vp->common->vstepmin_smpswaittimemin_shift) |
  83                 (vstepmin <<  vp->common->vstepmin_stepmin_shift);
  84         voltdm->write(val, vp->vstepmin);
  85 
  86         /* VSTEPMAX */
  87         val = (vstepmax << vp->common->vstepmax_stepmax_shift) |
  88                 (waittime << vp->common->vstepmax_smpswaittimemax_shift);
  89         voltdm->write(val, vp->vstepmax);
  90 
  91         /* VLIMITTO */
  92         val = (vddmax << vp->common->vlimitto_vddmax_shift) |
  93                 (vddmin << vp->common->vlimitto_vddmin_shift) |
  94                 (timeout <<  vp->common->vlimitto_timeout_shift);
  95         voltdm->write(val, vp->vlimitto);
  96 }
  97 
  98 int omap_vp_update_errorgain(struct voltagedomain *voltdm,
  99                              unsigned long target_volt)
 100 {
 101         struct omap_volt_data *volt_data;
 102 
 103         if (!voltdm->vp)
 104                 return -EINVAL;
 105 
 106         /* Get volt_data corresponding to target_volt */
 107         volt_data = omap_voltage_get_voltdata(voltdm, target_volt);
 108         if (IS_ERR(volt_data))
 109                 return -EINVAL;
 110 
 111         /* Setting vp errorgain based on the voltage */
 112         voltdm->rmw(voltdm->vp->common->vpconfig_errorgain_mask,
 113                     volt_data->vp_errgain <<
 114                     __ffs(voltdm->vp->common->vpconfig_errorgain_mask),
 115                     voltdm->vp->vpconfig);
 116 
 117         return 0;
 118 }
 119 
 120 /* VP force update method of voltage scaling */
 121 int omap_vp_forceupdate_scale(struct voltagedomain *voltdm,
 122                               unsigned long target_volt)
 123 {
 124         struct omap_vp_instance *vp = voltdm->vp;
 125         u32 vpconfig;
 126         u8 target_vsel, current_vsel;
 127         int ret, timeout = 0;
 128 
 129         ret = omap_vc_pre_scale(voltdm, target_volt, &target_vsel, &current_vsel);
 130         if (ret)
 131                 return ret;
 132 
 133         /*
 134          * Clear all pending TransactionDone interrupt/status. Typical latency
 135          * is <3us
 136          */
 137         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
 138                 vp->common->ops->clear_txdone(vp->id);
 139                 if (!vp->common->ops->check_txdone(vp->id))
 140                         break;
 141                 udelay(1);
 142         }
 143         if (timeout >= VP_TRANXDONE_TIMEOUT) {
 144                 pr_warn("%s: vdd_%s TRANXDONE timeout exceeded. Voltage change aborted\n",
 145                         __func__, voltdm->name);
 146                 return -ETIMEDOUT;
 147         }
 148 
 149         vpconfig = _vp_set_init_voltage(voltdm, target_volt);
 150 
 151         /* Force update of voltage */
 152         voltdm->write(vpconfig | vp->common->vpconfig_forceupdate,
 153                       voltdm->vp->vpconfig);
 154 
 155         /*
 156          * Wait for TransactionDone. Typical latency is <200us.
 157          * Depends on SMPSWAITTIMEMIN/MAX and voltage change
 158          */
 159         timeout = 0;
 160         omap_test_timeout(vp->common->ops->check_txdone(vp->id),
 161                           VP_TRANXDONE_TIMEOUT, timeout);
 162         if (timeout >= VP_TRANXDONE_TIMEOUT)
 163                 pr_err("%s: vdd_%s TRANXDONE timeout exceeded. TRANXDONE never got set after the voltage update\n",
 164                        __func__, voltdm->name);
 165 
 166         omap_vc_post_scale(voltdm, target_volt, target_vsel, current_vsel);
 167 
 168         /*
 169          * Disable TransactionDone interrupt , clear all status, clear
 170          * control registers
 171          */
 172         timeout = 0;
 173         while (timeout++ < VP_TRANXDONE_TIMEOUT) {
 174                 vp->common->ops->clear_txdone(vp->id);
 175                 if (!vp->common->ops->check_txdone(vp->id))
 176                         break;
 177                 udelay(1);
 178         }
 179 
 180         if (timeout >= VP_TRANXDONE_TIMEOUT)
 181                 pr_warn("%s: vdd_%s TRANXDONE timeout exceeded while trying to clear the TRANXDONE status\n",
 182                         __func__, voltdm->name);
 183 
 184         /* Clear force bit */
 185         voltdm->write(vpconfig, vp->vpconfig);
 186 
 187         return 0;
 188 }
 189 
 190 /**
 191  * omap_vp_enable() - API to enable a particular VP
 192  * @voltdm:     pointer to the VDD whose VP is to be enabled.
 193  *
 194  * This API enables a particular voltage processor. Needed by the smartreflex
 195  * class drivers.
 196  */
 197 void omap_vp_enable(struct voltagedomain *voltdm)
 198 {
 199         struct omap_vp_instance *vp;
 200         u32 vpconfig, volt;
 201 
 202         if (!voltdm || IS_ERR(voltdm)) {
 203                 pr_warn("%s: VDD specified does not exist!\n", __func__);
 204                 return;
 205         }
 206 
 207         vp = voltdm->vp;
 208         if (!voltdm->read || !voltdm->write) {
 209                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
 210                         __func__, voltdm->name);
 211                 return;
 212         }
 213 
 214         /* If VP is already enabled, do nothing. Return */
 215         if (vp->enabled)
 216                 return;
 217 
 218         volt = voltdm_get_voltage(voltdm);
 219         if (!volt) {
 220                 pr_warn("%s: unable to find current voltage for %s\n",
 221                         __func__, voltdm->name);
 222                 return;
 223         }
 224 
 225         vpconfig = _vp_set_init_voltage(voltdm, volt);
 226 
 227         /* Enable VP */
 228         vpconfig |= vp->common->vpconfig_vpenable;
 229         voltdm->write(vpconfig, vp->vpconfig);
 230 
 231         vp->enabled = true;
 232 }
 233 
 234 /**
 235  * omap_vp_disable() - API to disable a particular VP
 236  * @voltdm:     pointer to the VDD whose VP is to be disabled.
 237  *
 238  * This API disables a particular voltage processor. Needed by the smartreflex
 239  * class drivers.
 240  */
 241 void omap_vp_disable(struct voltagedomain *voltdm)
 242 {
 243         struct omap_vp_instance *vp;
 244         u32 vpconfig;
 245         int timeout;
 246 
 247         if (!voltdm || IS_ERR(voltdm)) {
 248                 pr_warn("%s: VDD specified does not exist!\n", __func__);
 249                 return;
 250         }
 251 
 252         vp = voltdm->vp;
 253         if (!voltdm->read || !voltdm->write) {
 254                 pr_err("%s: No read/write API for accessing vdd_%s regs\n",
 255                         __func__, voltdm->name);
 256                 return;
 257         }
 258 
 259         /* If VP is already disabled, do nothing. Return */
 260         if (!vp->enabled) {
 261                 pr_warn("%s: Trying to disable VP for vdd_%s when it is already disabled\n",
 262                         __func__, voltdm->name);
 263                 return;
 264         }
 265 
 266         /* Disable VP */
 267         vpconfig = voltdm->read(vp->vpconfig);
 268         vpconfig &= ~vp->common->vpconfig_vpenable;
 269         voltdm->write(vpconfig, vp->vpconfig);
 270 
 271         /*
 272          * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
 273          */
 274         omap_test_timeout((voltdm->read(vp->vstatus)),
 275                           VP_IDLE_TIMEOUT, timeout);
 276 
 277         if (timeout >= VP_IDLE_TIMEOUT)
 278                 pr_warn("%s: vdd_%s idle timedout\n", __func__, voltdm->name);
 279 
 280         vp->enabled = false;
 281 
 282         return;
 283 }

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