1215976Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett/** 41215976Sjmallett * @file 42215976Sjmallett * 43215976Sjmallett * Interface to power-throttle control, measurement, and debugging 44215976Sjmallett * facilities. 45215976Sjmallett * 46232812Sjmallett * <hr>$Revision: 70030 $<hr> 47215976Sjmallett * 48215976Sjmallett */ 49215976Sjmallett 50215976Sjmallett#include "cvmx.h" 51215976Sjmallett#include "cvmx-asm.h" 52232812Sjmallett#include "cvmx-coremask.h" 53215976Sjmallett#include "cvmx-power-throttle.h" 54215976Sjmallett 55215976Sjmallett 56232812Sjmallett#define CVMX_PTH_GET_MASK(len, pos) \ 57232812Sjmallett ((((uint64_t)1 << (len)) - 1) << (pos)) 58232812Sjmallett 59232812Sjmallett#define CVMX_PTH_AVAILABLE \ 60232812Sjmallett (cvmx_power_throttle_get_register(0) != (uint64_t)-1) 61232812Sjmallett 62215976Sjmallett/** 63232812Sjmallett * a field of the POWTHROTTLE register 64232812Sjmallett */ 65232812Sjmallettstatic struct cvmx_power_throttle_rfield_t { 66232812Sjmallett char name[16]; /* the field's name */ 67232812Sjmallett int32_t pos; /* position of the field's LSb */ 68232812Sjmallett int32_t len; /* the field's length */ 69232812Sjmallett int present; /* 1 for present */ 70232812Sjmallett} cvmx_power_throttle_rfield[] = { 71232812Sjmallett {"MAXPOW", 56, 8, 0}, 72232812Sjmallett {"POWER" , 48, 8, 0}, 73232812Sjmallett {"THROTT", 40, 8, 0}, 74232812Sjmallett {"Reserved", 28, 12, 0}, 75232812Sjmallett {"DISTAG", 27, 1, 0}, 76232812Sjmallett {"PERIOD", 24, 3, 0}, 77232812Sjmallett {"POWLIM", 16, 8, 0}, 78232812Sjmallett {"MAXTHR", 8, 8, 0}, 79232812Sjmallett {"MINTHR", 0, 8, 0}, 80232812Sjmallett {"HRMPOWADJ",32, 8, 0}, 81232812Sjmallett {"OVRRD", 28, 1, 0} 82232812Sjmallett}; 83232812Sjmallett 84232812Sjmallettstatic uint64_t cvmx_power_throttle_csr_addr(int ppid); 85232812Sjmallett 86232812Sjmallettstatic int cvmx_power_throttle_initialized; 87232812Sjmallett 88232812Sjmallett/** 89215976Sjmallett * @INTERNAL 90232812Sjmallett * Initialize cvmx_power_throttle_rfield[] based on model. 91232812Sjmallett */ 92232812Sjmallettstatic void cvmx_power_throttle_init(void) 93232812Sjmallett{ 94232812Sjmallett /* 95232812Sjmallett * Turn on the fields for a model 96232812Sjmallett */ 97232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 98232812Sjmallett { 99232812Sjmallett int i; 100232812Sjmallett struct cvmx_power_throttle_rfield_t *p; 101232812Sjmallett 102232812Sjmallett for (i = 0; i < CVMX_PTH_INDEX_MAX; i++) 103232812Sjmallett cvmx_power_throttle_rfield[i].present = 1; 104232812Sjmallett 105232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN63XX)) 106232812Sjmallett { 107232812Sjmallett /* 108232812Sjmallett * These fields do not come with o63 109232812Sjmallett */ 110232812Sjmallett p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_HRMPOWADJ]; 111232812Sjmallett p->present = 0; 112232812Sjmallett p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_OVRRD]; 113232812Sjmallett p->present = 0; 114232812Sjmallett } 115232812Sjmallett else 116232812Sjmallett { 117232812Sjmallett /* 118232812Sjmallett * The reserved field shrinks in models newer than o63 119232812Sjmallett */ 120232812Sjmallett p = &cvmx_power_throttle_rfield[CVMX_PTH_INDEX_RESERVED]; 121232812Sjmallett p->pos = 29; 122232812Sjmallett p->len = 3; 123232812Sjmallett } 124232812Sjmallett } 125232812Sjmallett} 126232812Sjmallett 127232812Sjmallettuint64_t cvmx_power_throttle_get_field(uint64_t r, 128232812Sjmallett cvmx_power_throttle_field_index_t i) 129232812Sjmallett{ 130232812Sjmallett uint64_t m; 131232812Sjmallett struct cvmx_power_throttle_rfield_t *p; 132232812Sjmallett 133232812Sjmallett assert(i < CVMX_PTH_INDEX_MAX); 134232812Sjmallett p = &cvmx_power_throttle_rfield[i]; 135232812Sjmallett if (!p->present) 136232812Sjmallett return (uint64_t) -1; 137232812Sjmallett m = CVMX_PTH_GET_MASK(p->len, p->pos); 138232812Sjmallett 139232812Sjmallett return((r & m) >> p->pos); 140232812Sjmallett} 141232812Sjmallett 142232812Sjmallett/** 143232812Sjmallett * @INTERNAL 144232812Sjmallett * Set the i'th field of power-throttle register r to v. 145232812Sjmallett */ 146232812Sjmallettstatic int cvmx_power_throttle_set_field(int i, uint64_t r, uint64_t v) 147232812Sjmallett{ 148232812Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 149232812Sjmallett { 150232812Sjmallett uint64_t m; 151232812Sjmallett struct cvmx_power_throttle_rfield_t *p; 152232812Sjmallett 153232812Sjmallett assert(i < CVMX_PTH_INDEX_MAX); 154232812Sjmallett 155232812Sjmallett p = &cvmx_power_throttle_rfield[i]; 156232812Sjmallett m = CVMX_PTH_GET_MASK(p->len, p->pos); 157232812Sjmallett 158232812Sjmallett return((~m & r) | ((v << p->pos) & m)); 159232812Sjmallett } 160232812Sjmallett return 0; 161232812Sjmallett} 162232812Sjmallett 163232812Sjmallett/** 164232812Sjmallett * @INTERNAL 165215976Sjmallett * Set the POWLIM field as percentage% of the MAXPOW field in r. 166215976Sjmallett */ 167232812Sjmallettstatic uint64_t cvmx_power_throttle_set_powlim(int ppid, 168232812Sjmallett uint8_t percentage) 169215976Sjmallett{ 170215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 171215976Sjmallett { 172232812Sjmallett uint64_t t, csr_addr, r; 173215976Sjmallett 174215976Sjmallett assert(percentage < 101); 175232812Sjmallett csr_addr = cvmx_power_throttle_csr_addr(ppid); 176232812Sjmallett r = cvmx_read_csr(csr_addr); 177232812Sjmallett 178232812Sjmallett t = cvmx_power_throttle_get_field(r, CVMX_PTH_INDEX_MAXPOW); 179232812Sjmallett if (!OCTEON_IS_MODEL(OCTEON_CN63XX)) 180232812Sjmallett { 181232812Sjmallett uint64_t s; 182232812Sjmallett 183232812Sjmallett s = cvmx_power_throttle_get_field(r, CVMX_PTH_INDEX_HRMPOWADJ); 184232812Sjmallett assert(t > s); 185232812Sjmallett t = t - s; 186232812Sjmallett } 187232812Sjmallett 188232812Sjmallett t = percentage * t / 100; 189215976Sjmallett r = cvmx_power_throttle_set_field(CVMX_PTH_INDEX_POWLIM, r, t); 190215976Sjmallett 191232812Sjmallett cvmx_write_csr(csr_addr, r); 192215976Sjmallett return r; 193215976Sjmallett } 194215976Sjmallett return 0; 195215976Sjmallett} 196215976Sjmallett 197215976Sjmallett/** 198215976Sjmallett * @INTERNAL 199215976Sjmallett * Given ppid, calculate its PowThrottle register's L2C_COP0_MAP CSR 200215976Sjmallett * address. (ppid == PTH_PPID_BCAST is for broadcasting) 201215976Sjmallett */ 202232812Sjmallettstatic uint64_t cvmx_power_throttle_csr_addr(int ppid) 203215976Sjmallett{ 204215976Sjmallett if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) 205215976Sjmallett { 206215976Sjmallett uint64_t csr_addr, reg_num, reg_reg, reg_sel; 207215976Sjmallett 208232812Sjmallett assert(ppid < CVMX_MAX_CORES); 209232812Sjmallett 210215976Sjmallett /* 211215976Sjmallett * register 11 selection 6 212215976Sjmallett */ 213215976Sjmallett reg_reg = 11; 214215976Sjmallett reg_sel = 6; 215215976Sjmallett reg_num = (ppid << 8) + (reg_reg << 3) + reg_sel; 216215976Sjmallett csr_addr = CVMX_L2C_COP0_MAPX(0) + ((reg_num) << 3); 217215976Sjmallett 218215976Sjmallett return csr_addr; 219215976Sjmallett } 220215976Sjmallett return 0; 221215976Sjmallett} 222215976Sjmallett 223215976Sjmallettint cvmx_power_throttle_self(uint8_t percentage) 224215976Sjmallett{ 225232812Sjmallett if (!CVMX_PTH_AVAILABLE) 226232812Sjmallett return -1; 227215976Sjmallett 228232812Sjmallett if (cvmx_power_throttle_set_powlim(cvmx_get_core_num(), 229232812Sjmallett percentage) == 0) 230232812Sjmallett return -1; 231215976Sjmallett 232215976Sjmallett return 0; 233215976Sjmallett} 234215976Sjmallett 235215976Sjmallettint cvmx_power_throttle(uint8_t percentage, uint64_t coremask) 236215976Sjmallett{ 237232812Sjmallett int ppid; 238232812Sjmallett int ret; 239232812Sjmallett 240232812Sjmallett if (!CVMX_PTH_AVAILABLE) 241232812Sjmallett return -1; 242232812Sjmallett 243232812Sjmallett ret = 0; 244232812Sjmallett for (ppid = 0; ppid < CVMX_MAX_CORES; ppid++) 245215976Sjmallett { 246232812Sjmallett if ((((uint64_t) 1) << ppid) & coremask) 247232812Sjmallett { 248232812Sjmallett if (cvmx_power_throttle_set_powlim(ppid, percentage) == 0) 249232812Sjmallett ret = -2; 250215976Sjmallett } 251215976Sjmallett } 252215976Sjmallett 253232812Sjmallett return ret; 254215976Sjmallett} 255232812Sjmallett 256232812Sjmallettint cvmx_power_throttle_bmp(uint8_t percentage, struct cvmx_coremask *pcm) 257232812Sjmallett{ 258232812Sjmallett int ppid; 259232812Sjmallett int ret; 260232812Sjmallett 261232812Sjmallett if (!CVMX_PTH_AVAILABLE) 262232812Sjmallett return -1; 263232812Sjmallett 264232812Sjmallett ret = 0; 265232812Sjmallett CVMX_COREMASK_FOR_EACH_CORE_BEGIN(pcm, ppid) 266232812Sjmallett { 267232812Sjmallett if (cvmx_power_throttle_set_powlim(ppid, percentage) == 0) 268232812Sjmallett ret = -2; 269232812Sjmallett } CVMX_COREMASK_FOR_EACH_CORE_END; 270232812Sjmallett 271232812Sjmallett return ret; 272232812Sjmallett} 273232812Sjmallett 274232812Sjmallettuint64_t cvmx_power_throttle_get_register(int ppid) 275232812Sjmallett{ 276232812Sjmallett uint64_t csr_addr; 277232812Sjmallett 278232812Sjmallett if (!cvmx_power_throttle_initialized) 279232812Sjmallett { 280232812Sjmallett cvmx_power_throttle_init(); 281232812Sjmallett cvmx_power_throttle_initialized = 1; 282232812Sjmallett } 283232812Sjmallett 284232812Sjmallett csr_addr = cvmx_power_throttle_csr_addr(ppid); 285232812Sjmallett 286232812Sjmallett if (csr_addr == 0) 287232812Sjmallett return -1; 288232812Sjmallett 289232812Sjmallett return cvmx_read_csr(csr_addr); 290232812Sjmallett} 291