cvmx-power-throttle.c revision 232812
1174380Sjhb/***********************license start*************** 2174380Sjhb * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3174380Sjhb * reserved. 4174380Sjhb * 5174380Sjhb * 6174380Sjhb * Redistribution and use in source and binary forms, with or without 7174380Sjhb * modification, are permitted provided that the following conditions are 8174380Sjhb * met: 9174380Sjhb * 10174380Sjhb * * Redistributions of source code must retain the above copyright 11174380Sjhb * notice, this list of conditions and the following disclaimer. 12174380Sjhb * 13174380Sjhb * * Redistributions in binary form must reproduce the above 14174380Sjhb * copyright notice, this list of conditions and the following 15174380Sjhb * disclaimer in the documentation and/or other materials provided 16174380Sjhb * with the distribution. 17174380Sjhb 18174380Sjhb * * Neither the name of Cavium Inc. nor the names of 19174380Sjhb * its contributors may be used to endorse or promote products 20174380Sjhb * derived from this software without specific prior written 21174380Sjhb * permission. 22174380Sjhb 23174380Sjhb * This Software, including technical data, may be subject to U.S. export control 24174380Sjhb * laws, including the U.S. Export Administration Act and its associated 25174380Sjhb * regulations, and may be subject to export or import regulations in other 26174380Sjhb * countries. 27174380Sjhb 28174380Sjhb * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29174380Sjhb * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30174380Sjhb * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31174380Sjhb * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32174380Sjhb * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33194910Sjhb * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34194910Sjhb * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35194910Sjhb * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36194910Sjhb * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37194910Sjhb * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38174380Sjhb ***********************license end**************************************/ 39174380Sjhb 40174380Sjhb/** 41174380Sjhb * @file 42174381Sjhb * 43174381Sjhb * Interface to power-throttle control, measurement, and debugging 44174381Sjhb * facilities. 45174381Sjhb * 46174381Sjhb * <hr>$Revision: 70030 $<hr> 47174381Sjhb * 48174381Sjhb */ 49174381Sjhb 50174381Sjhb#include "cvmx.h" 51174381Sjhb#include "cvmx-asm.h" 52174381Sjhb#include "cvmx-coremask.h" 53174381Sjhb#include "cvmx-power-throttle.h" 54174381Sjhb 55174381Sjhb 56174381Sjhb#define CVMX_PTH_GET_MASK(len, pos) \ 57174381Sjhb ((((uint64_t)1 << (len)) - 1) << (pos)) 58174381Sjhb 59174381Sjhb#define CVMX_PTH_AVAILABLE \ 60174381Sjhb (cvmx_power_throttle_get_register(0) != (uint64_t)-1) 61174381Sjhb 62174381Sjhb/** 63174381Sjhb * a field of the POWTHROTTLE register 64174381Sjhb */ 65174381Sjhbstatic struct cvmx_power_throttle_rfield_t { 66174381Sjhb char name[16]; /* the field's name */ 67174381Sjhb int32_t pos; /* position of the field's LSb */ 68174381Sjhb int32_t len; /* the field's length */ 69174381Sjhb int present; /* 1 for present */ 70174380Sjhb} cvmx_power_throttle_rfield[] = { 71174380Sjhb {"MAXPOW", 56, 8, 0}, 72174380Sjhb {"POWER" , 48, 8, 0}, 73194910Sjhb {"THROTT", 40, 8, 0}, 74194910Sjhb {"Reserved", 28, 12, 0}, 75194910Sjhb {"DISTAG", 27, 1, 0}, 76174380Sjhb {"PERIOD", 24, 3, 0}, 77174380Sjhb {"POWLIM", 16, 8, 0}, 78174380Sjhb {"MAXTHR", 8, 8, 0}, 79174380Sjhb {"MINTHR", 0, 8, 0}, 80174380Sjhb {"HRMPOWADJ",32, 8, 0}, 81174380Sjhb {"OVRRD", 28, 1, 0} 82174380Sjhb}; 83174380Sjhb 84174380Sjhbstatic uint64_t cvmx_power_throttle_csr_addr(int ppid); 85174380Sjhb 86174380Sjhbstatic int cvmx_power_throttle_initialized; 87174380Sjhb 88174380Sjhb/** 89174380Sjhb * @INTERNAL 90174380Sjhb * Initialize cvmx_power_throttle_rfield[] based on model. 91174380Sjhb */ 92174380Sjhbstatic void cvmx_power_throttle_init(void) 93174380Sjhb{ 94174380Sjhb /* 95174380Sjhb * Turn on the fields for a model 96174380Sjhb */ 97174380Sjhb if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 98194910Sjhb { 99194910Sjhb int i; 100194910Sjhb struct cvmx_power_throttle_rfield_t *p; 101194910Sjhb 102194910Sjhb for (i = 0; i < CVMX_PTH_INDEX_MAX; i++) 103194910Sjhb cvmx_power_throttle_rfield[i].present = 1; 104194910Sjhb 105194910Sjhb if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 106194910Sjhb { 107194910Sjhb /* 108194910Sjhb * These fields do not come with o63 109194910Sjhb */ 110194910Sjhb p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_HRMPOWADJ]; 111194910Sjhb p->present = 0; 112194910Sjhb p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_OVRRD]; 113194910Sjhb p->present = 0; 114194910Sjhb } 115194910Sjhb else 116194910Sjhb { 117194910Sjhb /* 118194910Sjhb * The reserved field shrinks in models newer than o63 119194910Sjhb */ 120194910Sjhb p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_RESERVED]; 121194910Sjhb p->pos = 29; 122194910Sjhb p->len = 3; 123194910Sjhb } 124194910Sjhb } 125194910Sjhb} 126194910Sjhb 127194910Sjhbuint64_t cvmx_power_throttle_get_field(uint64_t r, 128194910Sjhb cvmx_power_throttle_field_index_t i) 129194910Sjhb{ 130194910Sjhb uint64_t m; 131194910Sjhb struct cvmx_power_throttle_rfield_t *p; 132194910Sjhb 133194910Sjhb assert(i < CVMX_PTH_INDEX_MAX); 134194910Sjhb p = &cvmx_power_throttle_rfield[i]; 135194910Sjhb if (!p->present) 136194910Sjhb return (uint64_t) -1; 137194910Sjhb m = CVMX_PTH_GET_MASK(p->len, p->pos); 138194910Sjhb 139194910Sjhb return((r & m) >> p->pos); 140194910Sjhb} 141194910Sjhb 142194910Sjhb/** 143194910Sjhb * @INTERNAL 144194910Sjhb * Set the i'th field of power-throttle register r to v. 145194910Sjhb */ 146194910Sjhbstatic int cvmx_power_throttle_set_field(int i, uint64_t r, uint64_t v) 147194910Sjhb{ 148194910Sjhb if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 149194910Sjhb { 150205322Skib uint64_t m; 151205322Skib struct cvmx_power_throttle_rfield_t *p; 152205322Skib 153205322Skib assert(i < CVMX_PTH_INDEX_MAX); 154205322Skib 155194910Sjhb p = &cvmx_power_throttle_rfield[i]; 156194910Sjhb m = CVMX_PTH_GET_MASK(p->len, p->pos); 157205322Skib 158205322Skib return((~m & r) | ((v << p->pos) & m)); 159205322Skib } 160174380Sjhb return 0; 161} 162 163/** 164 * @INTERNAL 165 * Set the POWLIM field as percentage% of the MAXPOW field in r. 166 */ 167static uint64_t cvmx_power_throttle_set_powlim(int ppid, 168 uint8_t percentage) 169{ 170 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 171 { 172 uint64_t t, csr_addr, r; 173 174 assert(percentage < 101); 175 csr_addr = cvmx_power_throttle_csr_addr(ppid); 176 r = cvmx_read_csr(csr_addr); 177 178 t = cvmx_power_throttle_get_field(r, CVMX_PTH_INDEX_MAXPOW); 179 if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) 180 { 181 uint64_t s; 182 183 s = cvmx_power_throttle_get_field(r, CVMX_PTH_INDEX_HRMPOWADJ); 184 assert(t > s); 185 t = t - s; 186 } 187 188 t = percentage * t / 100; 189 r = cvmx_power_throttle_set_field(CVMX_PTH_INDEX_POWLIM, r, t); 190 191 cvmx_write_csr(csr_addr, r); 192 return r; 193 } 194 return 0; 195} 196 197/** 198 * @INTERNAL 199 * Given ppid, calculate its PowThrottle register's L2C_COP0_MAP CSR 200 * address. (ppid == PTH_PPID_BCAST is for broadcasting) 201 */ 202static uint64_t cvmx_power_throttle_csr_addr(int ppid) 203{ 204 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 205 { 206 uint64_t csr_addr, reg_num, reg_reg, reg_sel; 207 208 assert(ppid < CVMX_MAX_CORES); 209 210 /* 211 * register 11 selection 6 212 */ 213 reg_reg = 11; 214 reg_sel = 6; 215 reg_num = (ppid << 8) + (reg_reg << 3) + reg_sel; 216 csr_addr = CVMX_L2C_COP0_MAPX(0) + ((reg_num) << 3); 217 218 return csr_addr; 219 } 220 return 0; 221} 222 223int cvmx_power_throttle_self(uint8_t percentage) 224{ 225 if (!CVMX_PTH_AVAILABLE) 226 return -1; 227 228 if (cvmx_power_throttle_set_powlim(cvmx_get_core_num(), 229 percentage) == 0) 230 return -1; 231 232 return 0; 233} 234 235int cvmx_power_throttle(uint8_t percentage, uint64_t coremask) 236{ 237 int ppid; 238 int ret; 239 240 if (!CVMX_PTH_AVAILABLE) 241 return -1; 242 243 ret = 0; 244 for (ppid = 0; ppid < CVMX_MAX_CORES; ppid++) 245 { 246 if ((((uint64_t) 1) << ppid) & coremask) 247 { 248 if (cvmx_power_throttle_set_powlim(ppid, percentage) == 0) 249 ret = -2; 250 } 251 } 252 253 return ret; 254} 255 256int cvmx_power_throttle_bmp(uint8_t percentage, struct cvmx_coremask *pcm) 257{ 258 int ppid; 259 int ret; 260 261 if (!CVMX_PTH_AVAILABLE) 262 return -1; 263 264 ret = 0; 265 CVMX_COREMASK_FOR_EACH_CORE_BEGIN(pcm, ppid) 266 { 267 if (cvmx_power_throttle_set_powlim(ppid, percentage) == 0) 268 ret = -2; 269 } CVMX_COREMASK_FOR_EACH_CORE_END; 270 271 return ret; 272} 273 274uint64_t cvmx_power_throttle_get_register(int ppid) 275{ 276 uint64_t csr_addr; 277 278 if (!cvmx_power_throttle_initialized) 279 { 280 cvmx_power_throttle_init(); 281 cvmx_power_throttle_initialized = 1; 282 } 283 284 csr_addr = cvmx_power_throttle_csr_addr(ppid); 285 286 if (csr_addr == 0) 287 return -1; 288 289 return cvmx_read_csr(csr_addr); 290} 291