1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * * Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 23 * This Software, including technical data, may be subject to U.S. export control 24 * laws, including the U.S. Export Administration Act and its associated 25 * regulations, and may be subject to export or import regulations in other 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38 ***********************license end**************************************/ 39 40/** 41 * @file 42 * 43 * Interface to power-throttle control, measurement, and debugging 44 * facilities. 45 * 46 * <hr>$Revision: 70030 $<hr> 47 * 48 */ 49 50#include "cvmx.h" 51#include "cvmx-asm.h" 52#include "cvmx-coremask.h" 53#include "cvmx-power-throttle.h" 54 55 56#define CVMX_PTH_GET_MASK(len, pos) \ 57 ((((uint64_t)1 << (len)) - 1) << (pos)) 58 59#define CVMX_PTH_AVAILABLE \ 60 (cvmx_power_throttle_get_register(0) != (uint64_t)-1) 61 62/** 63 * a field of the POWTHROTTLE register 64 */ 65static struct cvmx_power_throttle_rfield_t { 66 char name[16]; /* the field's name */ 67 int32_t pos; /* position of the field's LSb */ 68 int32_t len; /* the field's length */ 69 int present; /* 1 for present */ 70} cvmx_power_throttle_rfield[] = { 71 {"MAXPOW", 56, 8, 0}, 72 {"POWER" , 48, 8, 0}, 73 {"THROTT", 40, 8, 0}, 74 {"Reserved", 28, 12, 0}, 75 {"DISTAG", 27, 1, 0}, 76 {"PERIOD", 24, 3, 0}, 77 {"POWLIM", 16, 8, 0}, 78 {"MAXTHR", 8, 8, 0}, 79 {"MINTHR", 0, 8, 0}, 80 {"HRMPOWADJ",32, 8, 0}, 81 {"OVRRD", 28, 1, 0} 82}; 83 84static uint64_t cvmx_power_throttle_csr_addr(int ppid); 85 86static int cvmx_power_throttle_initialized; 87 88/** 89 * @INTERNAL 90 * Initialize cvmx_power_throttle_rfield[] based on model. 91 */ 92static void cvmx_power_throttle_init(void) 93{ 94 /* 95 * Turn on the fields for a model 96 */ 97 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 98 { 99 int i; 100 struct cvmx_power_throttle_rfield_t *p; 101 102 for (i = 0; i < CVMX_PTH_INDEX_MAX; i++) 103 cvmx_power_throttle_rfield[i].present = 1; 104 105 if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 106 { 107 /* 108 * These fields do not come with o63 109 */ 110 p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_HRMPOWADJ]; 111 p->present = 0; 112 p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_OVRRD]; 113 p->present = 0; 114 } 115 else 116 { 117 /* 118 * The reserved field shrinks in models newer than o63 119 */ 120 p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_RESERVED]; 121 p->pos = 29; 122 p->len = 3; 123 } 124 } 125} 126 127uint64_t cvmx_power_throttle_get_field(uint64_t r, 128 cvmx_power_throttle_field_index_t i) 129{ 130 uint64_t m; 131 struct cvmx_power_throttle_rfield_t *p; 132 133 assert(i < CVMX_PTH_INDEX_MAX); 134 p = &cvmx_power_throttle_rfield[i]; 135 if (!p->present) 136 return (uint64_t) -1; 137 m = CVMX_PTH_GET_MASK(p->len, p->pos); 138 139 return((r & m) >> p->pos); 140} 141 142/** 143 * @INTERNAL 144 * Set the i'th field of power-throttle register r to v. 145 */ 146static int cvmx_power_throttle_set_field(int i, uint64_t r, uint64_t v) 147{ 148 if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 149 { 150 uint64_t m; 151 struct cvmx_power_throttle_rfield_t *p; 152 153 assert(i < CVMX_PTH_INDEX_MAX); 154 155 p = &cvmx_power_throttle_rfield[i]; 156 m = CVMX_PTH_GET_MASK(p->len, p->pos); 157 158 return((~m & r) | ((v << p->pos) & m)); 159 } 160 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