source: svn/newcon3bcm2_21bu/magnum/basemodules/chp/7552/bchp_avs.c @ 47

Last change on this file since 47 was 47, checked in by megakiss, 11 years ago

459Mhz로 OTC 주파수 변경

  • Property svn:executable set to *
File size: 73.2 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bchp_avs.c $
11 * $brcm_Revision: Hydra_Software_Devel/32 $
12 * $brcm_Date: 
13 *
14 * Module Description:
15 *   See Module Overview below.
16 *
17 * Revision History:
18 *
19 * $brcm_Log: /magnum/basemodules/chp/7425/bchp_avs.c $
20 *
21 * Hydra_Software_Devel/32   3/22/12 6:47p rjlewis
22 * SW7425-2218: Added support for Get Data extension function.  Added
23 * print to startup indicating AVS enabled in build.
24 *
25 * Hydra_Software_Devel/31   3/5/12 12:53p rjlewis
26 * SW7346-117: don't print trace message if in standby -- annoying.
27 * Restore working registers as part of restore process.
28 * Print a message on close to see when close is being called.
29 *
30 * Hydra_Software_Devel/30   3/5/12 12:08p rjlewis
31 * SW7346-117: Don't save/restore AVS registers if AVS not active (not
32 * enabled in CFE).
33 *
34 * Hydra_Software_Devel/29   3/2/12 6:26p rjlewis
35 * SW7435-43: support Ax parts that use second generation AVS.
36 * SW7552-219: fix support for Bx parts that use first generation AVS.
37 * SW7425-2218: added support for new extension test function.
38 *
39 * Hydra_Software_Devel/28   2/27/12 1:38p erickson
40 * SW7346-117: must call BDBG_OBJECT_DESTROY before freeing memory
41 *
42 * Hydra_Software_Devel/27   2/24/12 1:46p rjlewis
43 * SW7346-117: Added BDBG_OBJECT support (so I don't get a bad handle).
44 * If thresholds set in PI then indicate this on next start.
45 *
46 * Hydra_Software_Devel/26   2/23/12 11:35a rjlewis
47 * SW7346-117: AON registers different on 7358.
48 *
49 * Hydra_Software_Devel/25   2/17/12 6:15p rjlewis
50 * SW7346-117: Added support for S3 power management and ability to allow
51 * CFE AVS 0.5 to set thresholds.
52 * SW7425-2218: made test functions global to support test mode calls.
53 *
54 * Hydra_Software_Devel/24   2/6/12 1:38p rjlewis
55 * SW7425-2218: Added support for lock and unlock
56 *
57 * Hydra_Software_Devel/23   1/12/12 11:08a rjlewis
58 * SW7425-2146: can't use stdlib 'abs' function (generates warning when
59 * include file used and warning when no proto).
60 *
61 * Hydra_Software_Devel/22   1/11/12 5:43p rjlewis
62 * SW7425-2146: don't allow the voltage to exceed min/max (correct if it
63 * ever does).
64 * SW7425-2111: remember last dac written -- if it ever gets stepped on,
65 * put it back.
66 * Fix a bug in the lowest remote oscillator -- was not using the correct
67 * oscillator type for thresholds.
68 *
69 * Hydra_Software_Devel/21   1/9/12 4:23p rjlewis
70 * SW7552-187: don't use second generation process on 7552 Bx parts.
71 *
72 * Hydra_Software_Devel/20   12/16/11 3:26p rjlewis
73 * SW7346-117: Update the min values and add support for using MIN/MAX DAC
74 * values.
75 *
76 * Hydra_Software_Devel/19   10/26/11 3:22p rjlewis
77 * SW7346-527: fixed warning.
78 *
79 * Hydra_Software_Devel/18   10/7/11 11:07a rjlewis
80 * SW7346-117: removed CR in debug prints, changed err to wrn, added new
81 * wrn to say AVS enabled.
82 *
83 * Hydra_Software_Devel/17   9/15/11 11:03a rjlewis
84 * SW7346-117: make the oscillator counts automatic.
85 *
86 * Hydra_Software_Devel/16   9/12/11 5:20p rjlewis
87 * SW7346-117: Fixed seg fault due to chip revision not available until
88 * later.
89 *
90 * Hydra_Software_Devel/15   9/12/11 10:08a rjlewis
91 * SW7346-117: Updated to support B0 parts.
92 *
93 * Hydra_Software_Devel/14   9/2/11 9:51a rjlewis
94 * SW7346-117: handle the parts that didn't implement some oscillators.
95 *
96 * Hydra_Software_Devel/13   8/30/11 3:52p rjlewis
97 * SW7346-117: Enabled the constant voltage scheme for FF parts.
98 *
99 * Hydra_Software_Devel/12   8/30/11 2:31p rjlewis
100 * SW7346-117: decimal voltage debug printout needs to right justify the
101 * fractional part.
102 *
103 * Hydra_Software_Devel/11   8/29/11 3:20p rjlewis
104 * SW7346-117: temperature can go negative (can't use unsigned).
105 *
106 * Hydra_Software_Devel/10   8/26/11 5:44p rjlewis
107 * SW7346-117: fix warning and add new optional constant voltage routine
108 * for FF parts (disabled).
109 *
110 * Hydra_Software_Devel/9   8/26/11 12:10p rjlewis
111 * SW7346-117: resave PV value to threshold if not there (older CFE) and
112 * don't print interrupt value anymore.
113 *
114 * Hydra_Software_Devel/8   8/22/11 3:49p rjlewis
115 * SW7346-117: restore MIN/MAX_DAC registers BEFORE attempting to enable
116 * writing to DAC register.
117 *
118 * Hydra_Software_Devel/7   8/19/11 3:39p rjlewis
119 * SW7346-117: make sure we get the handles we require.  Number of remotes
120 * is not reflected correctly in RDB on 7358.
121 *
122 * Hydra_Software_Devel/6   8/16/11 3:35p rjlewis
123 * SW7346-117: updated the min/max supported voltage values.
124 *
125 * Hydra_Software_Devel/5   8/16/11 11:28a rjlewis
126 * SW7346-117: passing wrong parameter to Release resounce.
127 *
128 * Hydra_Software_Devel/4   8/15/11 1:37p rjlewis
129 * SW7346-117: Added support for power management.
130 *
131 * Hydra_Software_Devel/3   8/10/11 11:25a rjlewis
132 * SW7346-117: Can't use stdlib either. Use local version of abs.
133 *
134 * Hydra_Software_Devel/2   8/10/11 9:49a rjlewis
135 * SW7346-117: handle case where using wrong CFE.  Fix kernel mode compile
136 * error.
137 *
138 * Hydra_Software_Devel/1   8/4/11 7:23p rjlewis
139 * SW7346-117: Adding support for AVS hardware.
140 *
141 * 
142 ***************************************************************************/
143
144#if 0
145#include <stdio.h>
146#include <string.h>
147#include <stdint.h>
148#include <stdlib.h> /*for abs*/
149#endif
150
151#include "bstd.h"
152#include "bdbg.h"
153#include "bkni.h"
154#include "bchp.h"
155#include "bchp_priv.h"
156#ifdef BCHP_PWR_SUPPORT
157#include "bchp_pwr.h"
158#include "bchp_pwr_resources.h"
159#include "bchp_aon_ctrl.h"
160#endif
161
162BDBG_MODULE(BCHP_AVS);
163
164#include "bchp_avs.h"
165#include "bchp_avs_priv.h"
166
167/* TODO:
168** 1) If don't need LEAVE_ENABLE_SET then remove it and all referenced code.
169** 2) Add support for saving and checking registers on each "monitor" call (using AvsCheckSaveRegisters).
170** 3) Add more parameter checking (now that we're exporting more functions for testing).
171*/
172
173/* Compile time options: */
174/*#define LEAVE_ENABLE_SET*/ /* this is needed because delay required after enable is too long */
175
176/* There are two generations of AVS hardware that require different handling. */
177/* Statically decide which part uses which generation of AVS hardware. */
178/* Handle older parts or parts that have not updated to 2nd generation AVS hardware. */
179#if (((BCHP_CHIP==7231 || BCHP_CHIP==7344 || BCHP_CHIP==7346 || BCHP_CHIP==7422 || BCHP_CHIP==7425) && (BCHP_VER < BCHP_VER_B0)) \
180    || (BCHP_CHIP==7358 && BCHP_VER < BCHP_VER_B0)  /* we're at A2 -- they should use 2nd bump in Bx revs */ \
181    || (BCHP_CHIP==7552 && BCHP_VER <= BCHP_VER_B0) /* we're already at B0 revision using 1st bump */ \
182        )
183  #define AVS_GENERATION 1
184#else
185  #define AVS_GENERATION 2 /* all other parts default to 2nd generation */
186#endif
187
188/* The 7358 uses different design for AON registers (leave out until they decide how to use them) */
189#if (BCHP_CHIP!=7358)
190#define SAVE_TO_AON /* save the DAC_CODE and PVT_MON_CTRL registers to AON memory space as part of S3 shutdown */
191#endif
192
193/* We need to store four things across re-starts of the API:
194** 1) the original predicted voltage (also set by CFE)
195** 2) the fact that the thresolds were set by CFE
196** 3) the original DAC value set by CFE
197** 4) the final DAC value that was being used before the close
198**
199** We reserve the first two sets (four registers) of the central oscillator thresholds for storing information across restarts of the PI.
200** CFE uses the first lower threshold (threshold1_0) for storing the predicted voltage value.  This is used to identify FF parts.
201** FF parts requires a special initialization process so that we can still run the part at a lower voltage than if we used the default.
202** The second lower threshold (threshold1_1) is used by CFE to store a flag to indicate that it already initialized the threshold registers at startup.
203**
204** Because we always bump the starting DAC value by a margin on initialization we would be bumping the voltage on each subsequent
205** run allowing the voltage to "creep" up un-necessarily.  In order to correct for this, two central oscillator are reserved.
206** We use the first upper threshold (threshold2_0) for storing the original DAC value and restore it on each subsequent run.
207** If we closed properly we'll restart at the voltage value (DAC value) before the close.
208** We use the second upper threshold (threshold2_1) for storing the close DAC value and restore it on each subsequent run.
209** If we didn't close properly then we didn't get a chance to save the DAC so we'll revert to the DAC value set by CFE.
210**
211*/
212#define STARTING_OSCILLATOR 2 /* skip oscillator sets 0 and 1 when using central oscillator thresholds */
213
214/* This is where CFE stored the predicted voltage value on startup.
215** This is used to determine if the part is FF part (in whic case we process the voltage differently.
216** THIS MUST MATCH THE REGISTER AND VALUE FROM CFE (so if you change it then you'll need to change CFE too!).
217*/
218#define PREDICTED_VOLTAGE BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0
219
220/* This is where CFE set the flag that indicates that it set the thresholds already (and we don't need to do that here).
221** THIS MUST MATCH THE REGISTER AND VALUE FROM CFE (so if you change it then you'll need to change CFE too!).
222** The value MUST match or we'll re-do the setting of the thresholds.
223** That means backward compatibility with CFEs that don't have this update.
224*/
225#define THRESHOLDS_SET BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_1
226
227/* This is where we're going to save the starting DAC value for subsequent restarts */
228#define SAVED_DAC  BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0
229
230/* This is where we saved the closing DAC value when we (cleanly) shutdown */
231#define CLOSED_DAC BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_1
232
233/* We need to get some data from CFE and also provide some data to CFE.
234** We use some of the unused threshold registers to pass data (CFE->PI) and some AON registers to pass data back (PI->CFE).
235** This magic value is used to indicate that the data is valid and not some random junk written to a register.
236** This MUST match the value used by CFE -- do not change it!
237*/
238#define AVS_CFE_MAGIC 0x7735 /* ("sell" upside-down) this MUST match the value in CFE */
239#define AVS_AVS_MAGIC 0x5377 /* use this version to know WE set the thresholds */
240
241/*#include "bchp_avs_asb_registers.h"*/
242#include "bchp_avs_hw_mntr.h"
243#include "bchp_avs_pvt_mntr_config.h"
244#include "bchp_avs_ro_registers_0.h"
245#include "bchp_avs_ro_registers_1.h"
246#include "bchp_avs_rosc_threshold_1.h"
247#include "bchp_avs_rosc_threshold_2.h"
248
249#if (BCHP_CHIP == 7358)
250  #define MAX_REMOTE_OSCILLATORS 32 /* RDB shows 38 but really only 32 working */
251#endif
252
253/* Dynamically configure the number of central oscillators based on the shifts available */
254#ifndef MAX_CENTRAL_OSCILLATORS
255#if defined(BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_CEN_ROSC_1) /* defined if > 32 */
256  #if defined(BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_1_reserved0_SHIFT) /* defined if > 32 and < 64 */
257    #define MAX_CENTRAL_OSCILLATORS (32 + BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_1_reserved0_SHIFT)
258  #else
259    #define MAX_CENTRAL_OSCILLATORS 64 /* is exactly 64 */
260  #endif
261#elif defined(BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_0_reserved0_SHIFT) /* defined if < 32 */
262  #define MAX_CENTRAL_OSCILLATORS BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_0_reserved0_SHIFT
263#else
264  #define MAX_CENTRAL_OSCILLATORS 32 /* is exactly 32 */
265#endif
266#endif
267
268/* Dynamically configure the number of remote oscillators based on the shifts available */
269#ifndef MAX_REMOTE_OSCILLATORS
270#if defined(BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_RMT_ROSC_1) /* defined if > 32 */
271  #if defined(BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_RMT_ROSC_1_reserved0_SHIFT) /* defined if > 32 and < 64 */
272    #define MAX_REMOTE_OSCILLATORS (32 + BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_RMT_ROSC_1_reserved0_SHIFT)
273  #else
274    #define MAX_REMOTE_OSCILLATORS 64 /* is exactly 64 */
275  #endif
276#elif defined(BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_RMT_ROSC_0_reserved0_SHIFT) /* defined if < 32 */
277  #define MAX_REMOTE_OSCILLATORS BCHP_AVS_HW_MNTR_MEASUREMENTS_INIT_RMT_ROSC_0_reserved0_SHIFT
278#else
279  #define MAX_REMOTE_OSCILLATORS 32 /* is exactly 32 */
280#endif
281#endif
282
283/* Note: the above operations will not work if number of oscillators is greater than 64. Use same technique if that ever happens. */
284
285/* We're not allowed to use any of the standard library macros or functions due to build conflicts */
286#define AvsAbs(x) (((x)<0)?-(x):(x))
287
288/* In order to get rid of the floating points, do the math and print the parts */
289#define sign(f) ((f)<0)?'-':' ' /*space means positive*/
290#define mantissa(f) (AvsAbs((int)(f)/1000))
291#define fraction(f) (AvsAbs((int)((f) - (f)/1000*1000)))
292
293BDBG_OBJECT_ID(bchp_avs_t);
294
295/* This is the contect for this driver -- users use an opaque handle */
296struct BCHP_P_AvsContext {
297    BDBG_OBJECT(bchp_avs_t)    /* used to check if structure is valid */
298
299    BCHP_Handle hChip;     /* the handle for the chip open */
300        BREG_Handle hRegister; /* the register handle provided on open */
301
302        int dac_step_size; /* this is the maximum amount (+ or -) we'll change the DAC on each pass */
303
304        uint32_t last_dac;  /* keep track of the last value written to the DAC */
305        uint32_t last_temp; /* last data read from temperature register */
306        uint32_t last_voltage_1p1_0, last_voltage_1p1_1, last_voltage_0p99, last_voltage_2p75, last_voltage_3p63;
307
308        uint32_t V_0p99, V_1p1_0, V_1p1_1, V_2p75, V_3p63; /* last values read from voltage registers */
309
310        uint32_t original_dac; /* value of DAC set by CFE (or by our last run if run multiple times) */
311        uint32_t saved_predicted; /* value of predicted voltage saved by CFE */
312 
313        uint64_t central_exclude_mask; /* running exclude lists for this part */
314        uint64_t remote_exclude_mask;
315
316        bool ff_part; /* flag indicating that part requires special processing */
317        bool lock_enabled; /* flag to indicate AVS lock is enabled */
318        bool thresholdsSet; /* flag to indicate that the threshold values were set in CFE */
319
320        bool initialized; /* flag telling me that this structure has been properly initialized */
321        unsigned initialization_step; /* need to break down initialization into multiple steps */
322
323        bool standby; /* set to true to pause the AVS processing (low-power mode) */
324
325        bool doOnce; /* if printing the "beginning" status (debug) */
326
327        bool outOfBounds; /* temp -- so we only print this once */
328
329    /* These are the registers that need to be saved/restored when entering/exiting low power mode */
330    struct {
331        uint32_t dac, min_dac, max_dac;
332        uint32_t central_thresholds_min[MAX_CENTRAL_OSCILLATORS];
333        uint32_t central_thresholds_max[MAX_CENTRAL_OSCILLATORS];
334        uint32_t remote_hvt_min, remote_hvt_max;
335        uint32_t remote_svt_min, remote_svt_max;
336
337        uint32_t sw_controls;
338        uint32_t default_cent0;
339        uint32_t default_cent1;
340        uint32_t measurement;
341
342                bool valid;
343    } saved_registers;
344};
345
346/* This defines which of the voltages we're using for measurements (and to return) */
347#define last_voltage last_voltage_1p1_0
348
349/* forward references: */
350static void AvsInitialize(BCHP_P_AvsHandle handle);
351static void AvsUpdate(BCHP_P_AvsHandle handle);
352static void AvsSaveClosedDAC(BCHP_P_AvsHandle handle);
353static void AvsSaveRegisters(BCHP_P_AvsHandle handle);
354static void AvsRestoreRegisters(BCHP_P_AvsHandle handle, bool restore);
355/*static int AvsCheckSaveRegisters(BCHP_P_AvsHandle handle);*/
356
357/*\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\*/
358
359BERR_Code BCHP_P_AvsOpen (
360    BCHP_P_AvsHandle *phHandle,   /* [out] returns new handle on success */
361    BCHP_Handle       hChip)      /* [in] handle for chip data */
362{
363    BCHP_P_AvsHandle handle;
364        BERR_Code rc = BERR_SUCCESS; 
365
366        /* Make sure they gave me a place to return the handle and valid handles I'll need */
367        BDBG_ASSERT(phHandle);
368        BDBG_ASSERT(hChip);
369        BDBG_ASSERT(hChip->regHandle);
370
371    BDBG_ENTER(BCHP_AvsOpen);
372
373    /* If error ocurr user get a NULL *phHandle */
374    *phHandle = NULL;
375
376    /* Alloc the base chip context. */
377    handle = (BCHP_P_AvsHandle) (BKNI_Malloc(sizeof(struct BCHP_P_AvsContext)));
378    if (!handle)
379    {
380        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
381    }
382
383    /* Clear out the context and set defaults. */
384    BKNI_Memset((void*)handle, 0x0, sizeof(struct BCHP_P_AvsContext));
385    BDBG_OBJECT_SET(handle, bchp_avs_t);
386
387        /* Need register handle for accessing my registers. */
388        handle->hRegister = hChip->regHandle;
389    handle->hChip     = hChip;
390
391#ifdef BCHP_PWR_RESOURCE_AVS
392        rc = BCHP_PWR_AcquireResource(hChip, BCHP_PWR_RESOURCE_AVS);
393        if (rc != BERR_SUCCESS) {
394                BDBG_ERR(("Failed to acquire the AVS resource"));
395                BKNI_Free(handle);
396                return BERR_TRACE(BERR_UNKNOWN);
397        }
398#endif
399
400        /* This is the amount we'll change the value written to the DAC.
401        ** The step is programmable and, if optimizations are enabled, changes once we converge.
402        ** This ensures that we should converge or recover quickly (or more quickly) and then adjust more slowly after we converge.
403        ** With optimization enabled, the dac_step_size will change when required.
404        */
405#define DEFAULT_DAC_STEP_SIZE 1
406        handle->dac_step_size = DEFAULT_DAC_STEP_SIZE;
407
408        /* We're not initialized until we complete the initialization process */
409        handle->initialized = false;
410
411        *phHandle = handle; /*success -- return the handle*/
412
413        /* Always print something so we know that AVS is enabled in this build! */
414        /* The problem with this is that even if its included it doesn't mean that nexus has it enabled -- needs to be part of Monitor function */
415        /*BDBG_WRN(("AVS support included!"));*/
416
417        /* Handle older parts or parts that have not updated to 2nd generation AVS hardware. */
418        BDBG_MSG(("AVS_Open: Part uses generation %d of AVS", AVS_GENERATION));
419    BDBG_MSG(("AVS_Open: Number of oscillators: central=%d, remote=%d", MAX_CENTRAL_OSCILLATORS, MAX_REMOTE_OSCILLATORS));
420
421    BDBG_LEAVE(BCHP_AvsOpen);
422    return rc;
423}
424
425BERR_Code BCHP_P_AvsClose ( BCHP_P_AvsHandle hHandle )
426{
427    BDBG_ENTER(BCHP_AvsClose);
428    BDBG_OBJECT_ASSERT(hHandle, bchp_avs_t);
429
430        BDBG_MSG(("AVS Close called"));
431
432        AvsSaveClosedDAC(hHandle);
433#ifdef BCHP_PWR_RESOURCE_AVS
434        BCHP_PWR_ReleaseResource(hHandle->hChip, BCHP_PWR_RESOURCE_AVS);
435#endif
436    BDBG_OBJECT_DESTROY(hHandle, bchp_avs_t);
437        BKNI_Free(hHandle);
438
439    BDBG_LEAVE(BCHP_AvsClose);
440    return BERR_SUCCESS;
441}
442
443/* This gets called once a second to monitor the voltage and temperatures */
444BERR_Code BCHP_P_AvsMonitorPvt ( BCHP_P_AvsHandle hHandle )
445{
446    BDBG_ENTER(BCHP_Monitor_Pvt);
447    BDBG_OBJECT_ASSERT(hHandle, bchp_avs_t);
448
449        /*BDBG_MSG(("Entered AVS Processing routine (initialized=%s)", hHandle->initialized?"true":"false"));*/
450
451        /* If we have been placed in stand-by mode, we don't touch any registers */
452        /*if (hHandle->standby) return BERR_TRACE(BERR_UNKNOWN);*/
453        if (hHandle->standby) return BERR_UNKNOWN;
454
455        if (!hHandle->initialized) 
456        {
457                /* Prime everything until initialization completes */
458                AvsInitialize(hHandle);
459        }
460        else
461        {
462                /* Update on every other call */
463                AvsUpdate(hHandle);
464        }
465
466    BDBG_LEAVE(BCHP_Monitor_Pvt);
467    return BERR_SUCCESS;
468}
469
470BERR_Code BCHP_P_AvsStandbyMode(
471        BCHP_P_AvsHandle hHandle, /* [in] handle supplied from open */
472        bool activate)            /* [in] true to enter low power mode */
473{
474        BERR_Code rc = BERR_SUCCESS; 
475    BDBG_ENTER(BCHP_P_AvsLowPowerMode);
476    BDBG_OBJECT_ASSERT(hHandle, bchp_avs_t);
477
478        BDBG_MSG(("%s AVS standby-mode (AVS %s)", activate?"Entering":"Exiting", hHandle->initialized?"active":"inactive"));
479
480        /* If the AVS system was never initialized then nothing to do here */
481        if (!hHandle->initialized) return BERR_SUCCESS;
482
483        if (activate)
484        {
485                hHandle->standby = true; /* stop register accesses BEFORE we go to low power mode */
486                AvsSaveRegisters(hHandle);
487#ifdef BCHP_PWR_RESOURCE_AVS
488                rc = BCHP_PWR_ReleaseResource(hHandle->hChip, BCHP_PWR_RESOURCE_AVS);
489#endif
490        }
491        else
492        {
493#ifdef BCHP_PWR_RESOURCE_AVS
494                rc = BCHP_PWR_AcquireResource(hHandle->hChip, BCHP_PWR_RESOURCE_AVS);
495#endif
496                AvsRestoreRegisters(hHandle, true);
497                hHandle->standby = false;  /* re-enable register accesses AFTER we return from low power mode */
498        }
499
500    BDBG_LEAVE(BCHP_P_AvsLowPowerMode);
501    return rc;
502}
503
504/*\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\*/
505
506/* Background: There are two types of oscillators: central and remote.
507** The central ones are a block of different kinds with different threshold values.  These are packed close together in a
508** central area of the part.  The remote ones are a scattering of oscillators spread out on the part.  They are all the
509** same kind and the number may differ from chip to chip.  The central oscillators (because they are of different types)
510** will have a threshold setting for each one.  The remotes will all share the same set.
511** The object is to set some threshold values that can be used to tell if the voltage is too high or low.  When the voltage
512** is too low the oscillators will run slower and speed will drop below the lower threshold.  The voltage is raised to compensate.
513** When the voltage is too high the oscillators will run faster and speed will rise above upper threshold.  The voltage is lowered.
514** Note that monitoring temperature is not required because the effects of increased or decreased temperature will be reflected
515** in the oscillator speeds.
516*/
517
518typedef enum { Remote, Central } oscillator_t;
519
520/* Nice defines for debug prints */
521#define TorF(x) (((x)==true)?"true":"false")
522#define CentralOrRemote(x) (((x)==Remote)?"Remote":"Central")
523
524/* These are a bit mask of the oscillators to exclude from the processing */
525/* These were identified by the hardware team to be ineffectual representation of the speed of the processor */
526/* These are fixed across all instances so they don't need to be a part of the allocated data */
527static const uint64_t default_central_exclude_mask = ~((uint64_t)1<<44 | (uint64_t)1<<45); /* we are only using oscillators 44 & 45 */
528static const uint64_t default_remote_exclude_mask  = 0; /* we're using all the remotes */
529
530/*\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\*/
531
532/* Read the status of the specified central oscillator */
533uint32_t AvsReadCentralOscillator(BREG_Handle hRegister, unsigned oscillator)
534{
535        uint32_t cent;
536        cent = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_CEN_ROSC_STATUS_0 + (oscillator * 4)) & BCHP_AVS_RO_REGISTERS_0_CEN_ROSC_STATUS_0_data_MASK;
537        return cent;
538}
539
540/* Read the status of the specified remote oscillator */
541uint32_t AvsReadRemoteOscillator(BREG_Handle hRegister, unsigned oscillator)
542{
543        uint32_t rmt;
544        rmt = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_1_RMT_ROSC_STATUS_0 + (oscillator * 4)) & BCHP_AVS_RO_REGISTERS_1_RMT_ROSC_STATUS_0_data_MASK;
545        return rmt;
546}
547
548unsigned AvsGetNumberCentrals(void) { return MAX_CENTRAL_OSCILLATORS; }
549unsigned AvsGetNumberRemotes(void)  { return MAX_REMOTE_OSCILLATORS; }
550
551/* We have some parts that did not implement some oscillators.
552** These are identified by reading the status as zero.
553** Check all the oscillators (not already excluded) and add the ones we find.
554** This procedure could be done statically, but this does it dynamically.
555*/
556static void AvsUpdateExcludeLists(BCHP_P_AvsHandle handle)
557{
558        BREG_Handle hRegister = handle->hRegister;
559        uint32_t current;
560        unsigned i;
561
562        /* Start with the defaults and update as required */
563        handle->central_exclude_mask = default_central_exclude_mask;
564        handle->remote_exclude_mask  = default_remote_exclude_mask;
565
566        for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
567        {
568                if (((uint64_t)1<<i) & handle->central_exclude_mask) continue; /* skip items we're already excluding */
569
570                current = AvsReadCentralOscillator(hRegister, i);
571                if (!current)
572                        handle->central_exclude_mask |= (uint64_t)1<<i; /* add this oscillator to the exclude list */
573        }
574
575        for (i=0; i<MAX_REMOTE_OSCILLATORS; i++)
576        {
577                if (((uint64_t)1<<i) & handle->remote_exclude_mask) continue; /* skip items we're already excluding */
578
579                current = AvsReadRemoteOscillator(hRegister, i);
580                if (!current)
581                        handle->remote_exclude_mask |= (uint64_t)1<<i; /* add this oscillator to the exclude list */
582        }
583
584        if (handle->central_exclude_mask != default_central_exclude_mask)
585                BDBG_MSG(("Using corrected central exclude mask of: 0x%016llx", handle->central_exclude_mask));
586        if (handle->remote_exclude_mask != default_remote_exclude_mask)
587                BDBG_MSG(("Using corrected remote exclude mask of: 0x%016llx", handle->remote_exclude_mask));
588}
589
590/* This performs some pre-initialization cleanup from stuff passed from CFE */
591static void AvsCleanup(BCHP_P_AvsHandle handle)
592{
593        BREG_Handle hRegister = handle->hRegister;
594
595        /* A newer version of the CFE sets the MIN & MAX DAC values to prevent accidental DAC writes. */
596        /* This is identified by a MAX value that is different from the default. */
597        /* If the MAX is the default then this could be an old version of CFE. */
598        if (BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE) == 0x3FF) 
599        {
600            /* There is a CFE version out that only stores the predicted voltage in the MIN_DAC_CODE register.
601        ** Need to save this off BEFORE we step on it.
602        */
603        handle->saved_predicted = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE);
604
605        /* A version of CFE saves values to the MIN_DAC_CODE register; don't leave these set to non-valid numbers */
606        /* Note: you do NOT need to have the programming enable bit set in order to write these as it says in th4e RDB */
607        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE, 0);
608        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE, 0x3FF);
609
610        /*
611            ** WARNING: If you DON'T reset the registers above and attempt to either enable the PROGRAMMING_ENABLE
612            ** or write a DAC value that is lower/higher than the min/max, then the part will reset.
613        */
614        }
615}
616
617#if AVS_GENERATION==1
618  #define PVT_MON_CNTRL 0x001D0C03  /* see PVTMon manual for description of these bits */
619#else
620  #define PVT_MON_CNTRL 0x007D2683  /* definitions for this register changed in the second generation parts */
621#endif
622
623static void AvsInitializeRegisters(BCHP_P_AvsHandle handle)
624{
625        BREG_Handle hRegister = handle->hRegister;
626        uint32_t low_32, high_16;
627        uint64_t out;
628
629        /* Enable the DAC for writing */
630        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_PVT_MNTR_CTRL, PVT_MON_CNTRL);
631#ifdef LEAVE_ENABLE_SET
632        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 1); /* enable writing DAC */
633#endif
634
635        /* Set the interrupt flag when ANY (?) oscillator is BELOW the threshold value */
636        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_DIRECTION, 0);
637        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_DIRECTION, 0);
638
639#if 0
640        /* Tell the sequencer to skip items we're not using */
641        out = handle->central_exclude_mask;
642        low_32  = out & 0xFFFFFFFF;
643        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_0, low_32);
644#if (MAX_CENTRAL_OSCILLATORS > 32)
645        high_16 = (out >> 32);
646        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_1, high_16);
647#endif
648#else
649        /* If we tell the sequencer to skip these items then we won't get accurate data when trying to set the
650        ** thresholds based on the current values during the new setup process.  So its okay to tell the sequencer to
651        ** use all the oscillators, but we'll tell him to not use them for the threshold processing below.
652        */
653        low_32 = high_16 = 0;
654        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_0, low_32);
655        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_CEN_ROSC_1, high_16);
656#endif
657
658        /* And exclude the thresholds for items we're not using */
659        out = ~handle->central_exclude_mask; /* we enable the items we're NOT masking */
660        low_32  = out & 0xFFFFFFFF;
661        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_CEN_ROSC_THRESHOLD1_EN_0, low_32);
662        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_CEN_ROSC_THRESHOLD2_EN_0, low_32);
663#if (MAX_CENTRAL_OSCILLATORS > 32)
664        high_16 = (out >> 32);
665        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_CEN_ROSC_THRESHOLD1_EN_1, high_16);
666        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_CEN_ROSC_THRESHOLD2_EN_1, high_16);
667#endif
668/*BDBG_MSG(("Central: For mask of: %016llx; Using enable mask of: %016llx (high=%04x, low=%08x)", handle->central_exclude_mask, out, high_16, low_32));*/
669
670        /* Tell the sequencer to skip items we're not using */
671        out = handle->remote_exclude_mask;
672        low_32  = out & 0xFFFFFFFF;
673        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_RMT_ROSC_0, low_32);
674#if (MAX_REMOTE_OSCILLATORS > 32)
675        high_16 = (out >> 32);
676        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_MASK_RMT_ROSC_1, high_16);
677#endif
678
679        /* And exclude the thresholds for items we're not using */
680        out = ~handle->remote_exclude_mask; /* we enable the items we're NOT masking */
681        low_32  = out & 0xFFFFFFFF;
682        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_RMT_ROSC_THRESHOLD1_EN_0, low_32);
683        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_RMT_ROSC_THRESHOLD2_EN_0, low_32);
684#if (MAX_REMOTE_OSCILLATORS > 32)
685        high_16 = (out >> 32);
686        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_RMT_ROSC_THRESHOLD1_EN_1, high_16);
687        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_RMT_ROSC_THRESHOLD2_EN_1, high_16);
688#endif
689/*BDBG_MSG(("Remote: For mask of: %016llx; Using enable mask of: %016llx (high=%04x, low=%08x)", handle->remote_exclude_mask, out, high_16, low_32));*/
690}
691
692/* We set the voltage by controlling the DAC.  A larger DAC value means a lower voltage and vice versa. */
693void AvsSetDAC(BCHP_P_AvsHandle handle, uint32_t dac_code)
694{
695        BREG_Handle hRegister = handle->hRegister;
696
697        if (!dac_code) return; /* NEVER write 0 to DAC */
698        /* It would be nice if we had bounds here -- i.e. never go lower than xx or higher than yy */
699
700        /* Found a part that was forcing us to try to change the voltage past a point where changing the DAC yielded no change in the voltage.
701        ** That is, it lower the DAC, which was supposed to raise the voltage only the voltage didn't change.
702        ** When this happened, the DAC continued to go lower on each pass until the value wrapped.
703        ** Note that we don't need a cap for the max value as writing a large DAC will generate a low voltage and cause the board to reset.
704        ** Since I don't know where that value is, there is no way to test for this. Using arbitrary value could limit the ability to set a specific low voltage.
705        ** WARNING: don't print an error message or we'll continue to print on EVERY update.
706        */
707        if (dac_code < 10) {
708                if (!handle->outOfBounds) {
709                        BDBG_ERR(("DAC went lower than 10 -- this should not happen!"));
710                        handle->outOfBounds = true;
711                }
712                return; /* don't let the DAC ever go lower than this */
713        }
714        if (dac_code > 0x3FF) {
715                if (!handle->outOfBounds) {
716                        BDBG_ERR(("DAC went higher than 1024 -- this should not happen!"));
717                        handle->outOfBounds = true;
718                }
719                return; /* this is the maximum value allowed by the register -- if this is too high then we're out of control */
720        }
721        handle->outOfBounds = false; /* it is back in bounds so print again next time it goes out */
722
723#ifdef LEAVE_ENABLE_SET
724        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE, dac_code);
725#else
726 #if 0
727        /* There is a shadow copy of this register that gets loaded on the enable.
728        ** This version enables, sets, and then disables.
729        */
730        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 1); /* enable writing */
731        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE, dac_code);
732        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 0); /* disable writing */
733 #else
734        /* There is a shadow copy of this register that gets loaded on the enable.
735        ** If we enable first we could be loading something unintended.
736        */
737        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE, dac_code);
738        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 1); /* enable writing */
739        BKNI_Delay(10); /* delay just a bit before disable */
740        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 0); /* disable writing */
741 #endif
742#endif
743
744        /* We're supposed to wait awhile before reading any of the values provided by the PVTMON after changing the DAC.
745        ** But that's just not something we can can do here (sleep for 60 milliseconds that is).
746        ** Instead, we just make sure that we change the DAC as the last thing before exiting the poll loop.
747        ** The poll loop gets executed once a second so the values will have settled before we get called again.
748        ** Don't do this -> BKNI_Sleep(60);
749        */
750
751        /*BDBG_MSG(("Set DAC value of %x", dac_code));*/
752        handle->last_dac = dac_code; /* this is the last value we set the DAC to */
753}
754
755uint32_t AvsGetDAC(BCHP_P_AvsHandle handle)
756{
757        uint32_t dac_code;
758        dac_code = BREG_Read32(handle->hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE);
759        /*BDBG_MSG(("Got DAC value of %x", dac_code));*/
760        return dac_code;
761}
762
763/* These are fixed definitions provided by the developers for converting oscillator frequencies */
764#define DIVIDER_DEFINE 1000
765#define COUNTER_MAX    0x7FFF
766#define EDGE_COUNT     2
767
768/*
769** These functions are used when writing/reading the thresholds from supplied constants.
770** It puts the data into a format used by the hardware or into a format that is easier to read as a frequency.
771** The "toRegister" is needed when we used fixed constants for the thresholds (no longer used).
772** The "fromRegister" is needed when dumping the data in debug mode.
773*/
774
775#if 0
776/* We always convert the threshold values before writing the registers (turns KHz into correct format) */
777static uint32_t ConvertThresholdValue_toRegister(oscillator_t oscillator, unsigned long value)
778{
779        if (oscillator == Central)
780                return value * (COUNTER_MAX * EDGE_COUNT) / (2 * 108 * DIVIDER_DEFINE);
781        else
782                return value * (COUNTER_MAX * EDGE_COUNT) / (108 * DIVIDER_DEFINE);
783}
784/* We always convert the threshold values after reading the registers (turns KHz into correct format) */
785static unsigned long ConvertThresholdValue_fromRegister(oscillator_t oscillator, uint32_t reg)
786{
787        if (oscillator == Central)
788                return reg * (2 * 108 * DIVIDER_DEFINE) / (COUNTER_MAX * EDGE_COUNT);
789        else
790                return reg * (108 * DIVIDER_DEFINE) / (COUNTER_MAX * EDGE_COUNT);
791}
792#endif
793
794/* Return the threshold values for the specified central oscillator */
795void AvsReadCentralOscThresholds(BREG_Handle hRegister, unsigned oscillator, uint32_t *reg_min, uint32_t *reg_max)
796{
797        *reg_min = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (oscillator*4));
798        *reg_max = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (oscillator*4));
799}
800
801/* Return the threshold values for the specified remote oscillator */
802void AvsReadRemoteOscThresholds(BREG_Handle hRegister, unsigned oscillator, uint32_t *reg_min, uint32_t *reg_max)
803{
804        /* The even status values are for the GS thresholds and the odd are for the GH (not documented in the RDB!) */
805        /* This might need adjusting by the TPYE of the oscillator... */
806        if (oscillator & 1) {
807                *reg_min = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8H);
808                *reg_max = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8H);
809        } else {
810                *reg_min = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8S);
811                *reg_max = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8S);
812        }
813}
814
815/* This returns the current value from the register.  This needs converting before it reflects a temperature in centigrade units (see include file). */
816static uint32_t AvsGetTemperature(BCHP_P_AvsHandle handle)
817{
818        handle->last_temp = BREG_Read32(handle->hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUS);
819        handle->last_temp &= BCHP_AVS_RO_REGISTERS_0_PVT_TEMPERATURE_MNTR_STATUS_data_MASK;
820        return handle->last_temp;
821}
822
823#if 0
824static void printLastVoltages(BCHP_P_AvsHandle handle)
825{
826        BDBG_MSG(("voltage_1p1_0=%d, voltage_1p1_1=%d, voltage_0p99=%d, voltage_2p75=%d, voltage_3p63=%d (DAC=%d)",
827                handle->last_voltage_1p1_0, handle->last_voltage_1p1_1, handle->last_voltage_0p99, handle->last_voltage_2p75, handle->last_voltage_3p63,
828                handle->last_dac));
829}
830
831static uint32_t GetPVTmonitorData(BREG_Handle hRegister, unsigned control)
832{
833        uint32_t data;
834
835        /* Select the data to read, wait for it to settle, and Read the result */
836        BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_PVT_MNTR_CTRL, control);
837        data = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_PROCESS_MNTR_STATUS);
838        return (data & BCHP_AVS_RO_REGISTERS_0_PVT_PROCESS_MNTR_STATUS_data_MASK);
839}
840#endif
841
842/* This reads all of the voltage data provided by the PVT Monitor */
843static uint32_t AvsReadPvt(BCHP_P_AvsHandle handle)
844{
845        BREG_Handle hRegister = handle->hRegister;
846#ifdef USE_AVERAGE_VOLTAGE
847        unsigned i;
848        unsigned long temp;
849
850        /* There is a question as to whether we're getting the correct voltage value on a single read.
851        ** So instead of relying on a single read, read it a bunch of times and use an average.
852        */
853#define READ_VOLTAGE_THIS_MANY_TIMES 5
854        for (i=0; i<READ_VOLTAGE_THIS_MANY_TIMES; i++)
855                temp += BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_0_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_0_MNTR_STATUS_data_MASK;
856        temp /= READ_VOLTAGE_THIS_MANY_TIMES;
857#endif
858
859        /*Read voltages*/
860        handle->V_0p99  = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_0P99V_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_0P99V_MNTR_STATUS_data_MASK;
861#ifdef USE_AVERAGE_VOLTAGE
862        handle->V_1p1_0 = temp;
863#else
864        handle->V_1p1_0 = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_0_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_0_MNTR_STATUS_data_MASK;
865#endif
866        handle->V_1p1_1 = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_1_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_1P10V_1_MNTR_STATUS_data_MASK;
867        handle->V_2p75  = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_2p75V_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_2p75V_MNTR_STATUS_data_MASK;
868        handle->V_3p63  = BREG_Read32(hRegister, BCHP_AVS_RO_REGISTERS_0_PVT_3p63V_MNTR_STATUS) & BCHP_AVS_RO_REGISTERS_0_PVT_3p63V_MNTR_STATUS_data_MASK;
869
870#define bg_ref 990  /* make it 1000 bigger */
871
872        handle->last_voltage_0p99  = (bg_ref * handle->V_0p99 ) / 1024;
873        handle->last_voltage_1p1_0 = (bg_ref * handle->V_1p1_0 * 8) / (7*1024);
874        handle->last_voltage_1p1_1 = (bg_ref * handle->V_1p1_1 * 8) / (7*1024); 
875        handle->last_voltage_2p75  = (bg_ref * handle->V_2p75 * 3) / 1024;
876        handle->last_voltage_3p63  = (bg_ref * handle->V_3p63 * 4) / 1024;
877
878/*printLastVoltages();*/
879
880        return handle->last_voltage;
881}
882
883/* Reset the PVT Monitor Sequencer. 
884** Note: there needs to be a delay before reading all the values for them to become valid.
885** We do that by performing the reset after completing the convergence process, before we get called back in for a second pass.
886*/
887static void AvsResetSequencers(BREG_Handle hRegister)
888{
889        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_INIT, 1);
890        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SEQUENCER_INIT, 0);
891}
892
893#if 0
894static void AvsClearInterruptFlags(BREG_Handle hRegister)
895{
896        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_AVS_INTERRUPT_FLAGS_CLEAR, 0xF);
897        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_AVS_INTERRUPT_FLAGS_CLEAR, 0x0);
898}
899
900static unsigned AvsReadInterruptFlags(BREG_Handle hRegister)
901{
902        /*AvsClearInterruptFlags(hRegister);*/
903        /* Do I need a delay here? */
904        return (3 & BREG_Read32(hRegister, BCHP_AVS_HW_MNTR_AVS_INTERRUPT_FLAGS));
905}
906#endif
907
908/* Adjust the DAC (and therefore the voltage) by the specified step value */
909static bool AvsAdjustDacCode(BCHP_P_AvsHandle handle, int adjustment_step)
910{
911        uint32_t cur_val, new_val;
912        uint32_t voltage_1p1_0;
913        bool result = false;
914       
915        new_val = cur_val = AvsGetDAC(handle);
916
917        /*
918        ** We created a locking system to allow others to muck with registers without telling us.
919        ** Before they do anyting they are supposed to create the lock.
920        ** When the lock is enabled we won't fo anything to prevent them from doing what they want.
921        */
922
923        /* If lock is not enabled then okay to fix the DAC value */
924        if (!handle->lock_enabled)
925        {
926                /* HACK: Seeing this value come back incorrect sometimes (???) */
927                /* If we see this then something is wrong... (and we'll use the last [saved] value instead of the one we just read) */
928                if (handle->last_dac && handle->last_dac != cur_val) { 
929                        BDBG_ERR(("DAC current value (%d) not same as last (%d)", cur_val, handle->last_dac)); 
930                        cur_val = handle->last_dac; 
931                }
932        }
933
934/* These define the MIN and MAX values we'll let the voltage go to */
935#define VMIN_ABS 860   /*0.86V*/
936#define VMAX_ABS 1000  /*1.00V*/
937
938        voltage_1p1_0 = AvsReadPvt(handle);
939        /*BDBG_MSG(("Voltage = %d (min=%d, max=%d)", voltage_1p1_0, VMIN_ABS, VMAX_ABS));*/
940        /*BDBG_MSG(("DAC: current value (%d) last value (%d)", cur_val, handle->last_dac));*/
941
942        /* Make sure we never violate the voltage max and min values */
943        /* Note that the adjustment step can be negative to adjust the other way */
944        if ((VMIN_ABS <= voltage_1p1_0) && (voltage_1p1_0 <= VMAX_ABS)) 
945        {
946                new_val = cur_val + adjustment_step;
947                /*BDBG_MSG(("Setting new DAC value = %d (was %d, step=%d)", new_val, cur_val, adjustment_step));*/
948                result = true;
949        }
950        else
951        {
952                /* new algorithm says we shouldn't ALLOW the voltage to exceed its limits */
953                /* So we know we're outside the safe voltage range -- bring it back */
954                if (voltage_1p1_0 > VMAX_ABS)
955                        new_val = cur_val + AvsAbs(adjustment_step); /* increase DAC to lower voltage */
956                else
957                        new_val = cur_val - AvsAbs(adjustment_step); /* decrease DAC to increase voltage */
958
959                BDBG_MSG(("Voltage exceeding limit -- correcting (voltage=%d)", voltage_1p1_0));
960                /*BDBG_MSG(("Setting new DAC value = %d (was %d, step=%d)", new_val, cur_val, adjustment_step));*/
961                result = true;
962        }
963
964        if (new_val == 512) new_val += 1; /* apparently using 512 is bad */
965        if (new_val == cur_val) return result; /* optimization -- don't write register with same value */
966
967        AvsSetDAC(handle, new_val);
968        return result;
969}
970
971#if 0
972static void get_oscillator_values(BREG_Handle hRegister, oscillator_t oscillator, unsigned which_one, uint32_t *current, uint32_t *lower, uint32_t *upper)
973{
974        if (oscillator == Remote)
975        {
976                *current = AvsReadRemoteOscillator(hRegister, which_one);
977                AvsReadRemoteOscThresholds(hRegister, which_one, lower, upper);
978        }
979        else
980        {
981                *current = AvsReadCentralOscillator(hRegister, which_one);
982                AvsReadCentralOscThresholds(hRegister, which_one, lower, upper);
983        }
984}
985
986static void print_oscillator(char *what_kind, oscillator_t oscillator, unsigned which_one, uint32_t current, uint32_t lower, uint32_t upper)
987{
988#if 1
989        signed f_current = ConvertThresholdValue_fromRegister(oscillator, current);
990        signed f_lower   = ConvertThresholdValue_fromRegister(oscillator, lower);
991        signed f_upper   = ConvertThresholdValue_fromRegister(oscillator, upper);
992        BDBG_MSG(("%s %2d %08x %08x %08x (%c %c) c=%c%2d.%03d l=%c%2d.%03d u=%c%2d.%03d (ld=%c%2d.%03d, ud=%c%2d.%03d)",
993                what_kind, which_one, current, lower, upper, (current<=lower)?'L':'H', (current<=upper)?'L':'H',
994                sign(f_current), mantissa(f_current), fraction(f_current),
995                sign(f_lower), mantissa(f_lower), fraction(f_lower),
996                sign(f_upper), mantissa(f_upper), fraction(f_upper),
997                sign(f_current-f_lower), mantissa(f_current-f_lower), fraction(f_current-f_lower),
998                sign(f_current-f_upper), mantissa(f_current - f_upper), fraction(f_current - f_upper)));
999#else
1000        BDBG_MSG(("%s %2d %08x %08x %08x (%c %c)", what_kind, which_one, current, lower, upper, (current<=lower)?'L':'H', (current<=upper)?'L':'H'));
1001#endif
1002}
1003
1004static void get_and_print_oscillator(BCHP_P_AvsHandle handle, oscillator_t oscillator, unsigned which_one)
1005{
1006        uint32_t current;
1007        uint32_t lower, upper;
1008
1009        get_oscillator_values(handle->hRegister, oscillator, which_one, &current, &lower, &upper);
1010        print_oscillator(oscillator==Remote?"R:":"C:", oscillator, which_one, current, lower, upper);
1011} 
1012
1013static void printOscillators(BCHP_P_AvsHandle handle, char *text, bool include_excludes)
1014{
1015        unsigned i;
1016
1017        if (text) BDBG_MSG(("%s", text));
1018
1019        /* The number of central oscillators is set by the defaults or configuration file */
1020        for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
1021        {
1022                if (!include_excludes && (((uint64_t)1<<i) & handle->central_exclude_mask)) continue; /* skip items we're excluding */
1023                get_and_print_oscillator(handle, Central, i);
1024        }
1025
1026        /* The number of remote oscillators is fixed based on the part type (we dynamically set based on part) */
1027        for (i=0; i<MAX_REMOTE_OSCILLATORS; i++)
1028        {
1029                if (!include_excludes && (((uint64_t)1<<i) & handle->remote_exclude_mask)) continue; /* skip items we're excluding */
1030                get_and_print_oscillator(handle, Remote, i);
1031        }
1032}
1033#endif
1034
1035static void AvsSetNewThresholds_0(BCHP_P_AvsHandle handle)
1036{
1037        BREG_Handle hRegister = handle->hRegister;
1038        unsigned current_dac, closed_dac=0, saved_dac=0, thresholds=0, predicted;
1039
1040        current_dac = AvsGetDAC(handle);
1041
1042#if 1
1043        /* We reserve a threshold value for saving the DAC value set by us when we closed */
1044        closed_dac = BREG_Read32(hRegister, CLOSED_DAC);
1045        if (closed_dac)
1046        {
1047                /* use the original DAC value that CFE chose that we saved on the first run */
1048                AvsSetDAC(handle, closed_dac);
1049                BDBG_MSG(("Using saved DAC value of %d (0x%x) from close for starting DAC value", closed_dac, closed_dac));
1050                /* Don't use it again unless we close properly again */
1051                BREG_Write32(hRegister, CLOSED_DAC, 0);
1052        }
1053#endif
1054
1055#if 1
1056        /* We reserve a threshold value for saving the original DAC value set by CFE */
1057    if (!closed_dac)
1058    {
1059        saved_dac = BREG_Read32(hRegister, SAVED_DAC);
1060        if (saved_dac)
1061        {
1062                /* use the original DAC value that CFE chose that we saved on the first run */
1063                AvsSetDAC(handle, saved_dac);
1064                BDBG_MSG(("Using saved DAC value of %d (0x%x) for starting DAC value", saved_dac, saved_dac));
1065        }
1066        else
1067        {
1068                /* else this is our first run.  Save the CFE DAC value for future runs. */
1069                BREG_Write32(hRegister, SAVED_DAC, current_dac);
1070                BDBG_MSG(("Using CFE DAC value of %d (0x%x) for starting DAC value (saving)", current_dac, current_dac));
1071        }
1072    }
1073#endif
1074
1075        /* CFE stored the predicted voltage value (before applying margins, etc.) */
1076        /* If this one is set, ignore the one in the DAC_MIN register */
1077        predicted = BREG_Read32(hRegister, PREDICTED_VOLTAGE);
1078
1079        /* If it isn't in the one above then look in the secondary location  */
1080        if (!predicted) {
1081                predicted = handle->saved_predicted;
1082                BREG_Write32(hRegister, PREDICTED_VOLTAGE, predicted);
1083                BDBG_MSG(("Saving predicted voltage (%d) to save location", predicted));
1084        }
1085
1086        /* Either way, predicted is now the right one.  Dump and save a copy! */
1087        BDBG_MSG(("Predicted voltage (from CFE) = %d (%x)", predicted, predicted));
1088        handle->saved_predicted = predicted;
1089
1090/* A FF part is identified as having a predicted voltage lower the 0.730V */
1091#define FF_PART 730
1092
1093        /* We never want the voltage to go above a specific value for FF parts.
1094        ** Since CFE always uses the minimum voltage for a FF part this means we never need to change it.
1095        ** We can just not do ANY AVS processing for these parts (or use alternate method).
1096        ** If predicted is zero then this CFE never saved the predicted voltage value -- this is wrong CFE!
1097        */
1098        handle->ff_part = false;
1099        if (predicted && predicted < FF_PART) 
1100        {
1101                BDBG_MSG(("FF part identified -- using alternate AVS processing (predicted=%d)!", predicted));
1102                handle->ff_part = true;
1103        }
1104
1105#if 1
1106        /* Code to set threshold registers was copied to CFE in order to set the thresholds based on the status with
1107        ** the voltage set by CFE.  There is older code that doesn't do this so we have to "know" if CFE did this or not.
1108        ** CFE writes a magic flag in the following register if it did this operation.
1109        */
1110        handle->thresholdsSet = false;
1111        thresholds = BREG_Read32(hRegister, THRESHOLDS_SET);
1112        if (thresholds == AVS_CFE_MAGIC) 
1113        {
1114                BDBG_MSG(("Theshold values were set by CFE and will not be re-set here!"));
1115                handle->thresholdsSet = true;
1116        }
1117        if (thresholds == AVS_AVS_MAGIC) 
1118        {
1119                BDBG_MSG(("Theshold values were set by this PI and will not be re-set here!"));
1120                handle->thresholdsSet = true;
1121        }
1122#endif
1123}
1124
1125/* Save the current DAC value on a clean shutdown to restore on restart */
1126static void AvsSaveClosedDAC(BCHP_P_AvsHandle handle)
1127{
1128        BREG_Handle hRegister = handle->hRegister;
1129        unsigned current_dac;
1130
1131        current_dac = AvsGetDAC(handle);
1132
1133        BREG_Write32(hRegister, CLOSED_DAC, current_dac);
1134        BDBG_MSG(("Using current DAC value of %d (0x%x) for next starting DAC value (saving)", current_dac, current_dac));
1135}
1136
1137/*
1138** New Threshold Procedure (7/15/11):
1139** We're assuming that CFE has already started and has completed the open-loop processing resulting in a voltage value.
1140** This procedure uses that voltage value as a starting point for calculating new threshold values before beginning the convergence process.
1141**
1142** 1. For oscillators 44 and 45 of the central group (IROSCX2 oscillators) and the remote oscillators, find slowest oscillator for each vt
1143**    type and store its register value and its number.
1144** 2. Because the register values of remotes and central of the same IROSCX2 oscillator cell differ by a factor of 2 (extra divider on the
1145**    central oscillators), the min register value found in step 1 above is loaded into the corresponding threshold_1 registers depending
1146**    on whether the corresponding oscillator is in the central or the remote group.
1147** 3. Read the status registers of all the remaining central oscillators and store them as the lower threshold, on oscillator by oscillator basis.
1148** 4. Read the current dac code and decrement it by 16 codes.  This should result between 7 and 14mV, or an average of ~10mV.
1149**    The number 16 may still need to be refined based on actual test results.
1150** 5. Similar to step #1, for oscillators 44 and 45 and the remotes, find the slowest oscillator for each vt type and store its register value and its number.
1151** 6. Similar to step #2, load the register value in step 5 into the upper threshold (threshold_2), taking into account the factor of 2 mentioned above.
1152** 7. Read the status registers of all the remaining central oscillators and store them as the upper threshold, on oscillator by oscillator basis.
1153**
1154** Then, Run the standard convergence code that you should already have.
1155**
1156** The threshold procedure had to be broken into two steps because of the delay needed to get accurate readings for the voltages and oscillators.
1157** When we set a new voltage, by writing the DAC, there is a delay needed to allow the sequencer time to process all the new data (make another pass).
1158** This can be forced by resetting the sequencer (AvsResetSequencers) but this also requires a delay to allow the sequencer to process all the items.
1159** By splitting this process into two steps we'll process the first part in one call-back, and set the new voltage, and then process the rest in
1160** the second call-back (after a delay).
1161*/
1162static void AvsSetNewThresholds_1(BCHP_P_AvsHandle handle)
1163{
1164        BREG_Handle hRegister = handle->hRegister;
1165        unsigned i, current_dac, lowest_hvt, lowest_svt, temp;
1166        oscillator_t which_h_type, which_s_type; unsigned which_h, which_s;
1167        bool remotes;
1168
1169        /* 0) Use the current DAC value to choose the lower threshold value */
1170        current_dac = AvsGetDAC(handle);
1171
1172        /* 1) Find the lowest threshold for both the central and remote oscillators */
1173        lowest_hvt = AvsReadCentralOscillator(hRegister, 44);
1174        lowest_svt = AvsReadCentralOscillator(hRegister, 45);
1175        which_s_type = which_h_type = Central; which_h = 44; which_s = 45;
1176        remotes = false;
1177
1178    lowest_hvt *= 2; /* normalizing the central to the remotes because central are divided by 2 relative to remotes */
1179    lowest_svt *= 2;
1180
1181        for (i=0; i<MAX_REMOTE_OSCILLATORS; i++)
1182        {
1183                if (((uint64_t)1<<i) & handle->remote_exclude_mask) continue; /* skip items we're excluding */
1184                if (i&1) {
1185                        if ((temp = AvsReadRemoteOscillator(hRegister, i)) < lowest_hvt) { lowest_hvt = temp; remotes = true; which_h_type = Remote; which_h = i; }
1186                } else {
1187                        if ((temp = AvsReadRemoteOscillator(hRegister, i)) < lowest_svt) { lowest_svt = temp; remotes = true; which_s_type = Remote; which_s = i; }
1188                }
1189        }
1190
1191        {
1192                temp = AvsReadPvt(handle);
1193                BDBG_MSG(("Lower: For DAC = %d (0x%x) and voltage = %d (0x%x)", current_dac, current_dac, temp, temp));
1194                BDBG_MSG(("Lowest HVT = %s:%d = %d (0x%x)", CentralOrRemote(which_h_type), which_h, lowest_hvt, lowest_hvt));
1195                BDBG_MSG(("Lowest SVT = %s:%d = %d (0x%x)", CentralOrRemote(which_s_type), which_s, lowest_svt, lowest_svt));
1196        }
1197
1198        /* 2) Set the lower threshold with the smallest value found above. */
1199        BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (44*4)), lowest_hvt/2);
1200        BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (45*4)), lowest_svt/2);
1201        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8H, lowest_hvt);
1202        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8S, lowest_svt);
1203
1204#if 0 /* if we're not using these then don't write anything there */
1205        /* 3) Write the current status values to the lower threshold register */
1206        for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
1207        {
1208                if (i==44 || i==45) continue; /* already did these above */
1209                BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (i*4)), AvsReadCentralOscillator(hRegister, i));
1210        }
1211#endif
1212
1213        /* 4) Now, lower the DAC (raise the voltage) to choose the upper threshold value */
1214#define DAC_OFFSET 16
1215        current_dac -= DAC_OFFSET;
1216        AvsSetDAC(handle, current_dac);
1217}
1218
1219static void AvsSetNewThresholds_2(BCHP_P_AvsHandle handle)
1220{
1221        BREG_Handle hRegister = handle->hRegister;
1222        unsigned i, current_dac, lowest_hvt, lowest_svt, temp;
1223        oscillator_t which_h_type, which_s_type; unsigned which_h, which_s;
1224        bool remotes;
1225
1226        current_dac = AvsGetDAC(handle);
1227
1228        /* 5) Find the lowest threshold for both the central and remote oscillators at the new voltage */
1229        lowest_hvt = AvsReadCentralOscillator(hRegister, 44);
1230        lowest_svt = AvsReadCentralOscillator(hRegister, 45);
1231        which_s_type = which_h_type = Central; which_h = 44; which_s = 45;
1232        remotes = false;
1233
1234    lowest_hvt *= 2; /* normalizing the central to the remotes because central are divided by 2 relative to remotes */
1235    lowest_svt *= 2;
1236
1237        for (i=0; i<MAX_REMOTE_OSCILLATORS; i++)
1238        {
1239                if (((uint64_t)1<<i) & handle->remote_exclude_mask) continue; /* skip items we're excluding */
1240                if (i&1) {
1241                        if ((temp = AvsReadRemoteOscillator(hRegister, i)) < lowest_hvt) { lowest_hvt = temp; remotes = true; which_h_type = Remote; which_h = i; }
1242                } else {
1243                        if ((temp = AvsReadRemoteOscillator(hRegister, i)) < lowest_svt) { lowest_svt = temp; remotes = true; which_s_type = Remote; which_s = i; }
1244                }
1245        }
1246
1247        {
1248                temp = AvsReadPvt(handle);
1249                BDBG_MSG(("Upper: For DAC = %d (0x%x) and voltage = %d (0x%x)", current_dac, current_dac, temp, temp));
1250                BDBG_MSG(("Lowest HVT = %s:%d = %d (0x%x)", CentralOrRemote(which_h_type), which_h, lowest_hvt, lowest_hvt));
1251                BDBG_MSG(("Lowest SVT = %s:%d = %d (0x%x)", CentralOrRemote(which_s_type), which_s, lowest_svt, lowest_svt));
1252        }
1253
1254        /* 6) Set the upper threshold with the smallest value found above. */
1255        BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (44*4)), lowest_hvt/2);
1256        BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (45*4)), lowest_svt/2);
1257        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8H, lowest_hvt);
1258        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8S, lowest_svt);
1259
1260#if 0 /* if we're not using these then don't write anything there */
1261        /* 7) Write the current status values to the upper threshold register */
1262        for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
1263        {
1264                if (i==44 || i==45) continue; /* already did these above */
1265                BREG_Write32(hRegister, (BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (i*4)), AvsReadCentralOscillator(hRegister, i));
1266        }
1267#endif
1268
1269#if 1
1270        /* The thresholds have now been set so we don't need to re-do this on restart */
1271        BREG_Write32(hRegister, THRESHOLDS_SET, AVS_AVS_MAGIC);
1272#endif
1273}
1274
1275/* This is a special version for the FF parts.
1276** This is meant to maintain the voltage at specific value regardless of the temperature.
1277** For FF parts, this is run in place of the convergence algorithm.
1278*/
1279static void AvsConstantVoltageProcess(BCHP_P_AvsHandle handle)
1280{
1281        uint32_t dac, saved, voltage;
1282
1283        voltage = AvsReadPvt(handle);
1284        saved = dac = AvsGetDAC(handle);
1285
1286#define FF_Voltage_Norm 860 /* 0.860V */
1287#define ConstantMargin 4 /* millivolts */
1288#define DACchange 1 /* amount to change DAC on each pass */
1289
1290        if (voltage < (FF_Voltage_Norm - ConstantMargin)) dac -= DACchange; /* raise the voltage by lowering the DAC */
1291        if (voltage > (FF_Voltage_Norm + ConstantMargin)) dac += DACchange; /* lower the voltage by raising the DAC */
1292
1293        /* Only make changes when the value has changed */
1294        if (dac != saved) AvsSetDAC(handle, dac);
1295}
1296
1297/* This is the convergence algorithm.
1298** It checks the value of each oscillator against the threshold values.
1299** It moves the voltage by a fixed amount (on each call) until at least one of the oscillartors is inside the threshold boundaries.
1300** We can be unconverged by being outside the threshold ranges on all oscillators or by one or more oscillators being below the lower threshold.
1301** If all oscillators are above the upper threshold we lower the voltage (by raising the DAC).
1302** If even one oscillator is below the lower threshold we raise the voltage (by lowering the DAC).
1303** Return false if we failed to change the DAC due to voltage threshold violations (min/max).
1304*/
1305static bool AvsConvergeProcess(BCHP_P_AvsHandle handle)
1306{
1307        BREG_Handle hRegister = handle->hRegister;
1308        uint32_t current, lower=0, upper=0;
1309        bool increase=false, found_one=false, failed=false;
1310        unsigned i;
1311
1312        for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
1313        {
1314                if (((uint64_t)1<<i) & handle->central_exclude_mask) continue; /* skip items we're excluding */
1315
1316                current = AvsReadCentralOscillator(hRegister, i);
1317                AvsReadCentralOscThresholds(hRegister, i, &lower, &upper);
1318
1319                /*print_oscillator("CENTRAL:", Central, i, current, lower, upper);*/
1320
1321                        if (current < lower) {
1322                                increase = true;
1323                        } else if (current < upper) {
1324                                found_one = true;
1325                }
1326        }
1327
1328        for (i=0; i<MAX_REMOTE_OSCILLATORS; i++)
1329        {
1330                if (((uint64_t)1<<i) & handle->remote_exclude_mask) continue; /* skip items we're excluding */
1331
1332                current = AvsReadRemoteOscillator(hRegister, i);
1333                AvsReadRemoteOscThresholds(hRegister, i, &lower, &upper);
1334
1335                /*print_oscillator("REMOTE: ", Remote, i, current, lower, upper);*/
1336
1337                        if (current < lower) {
1338                                increase = true;
1339                        } else if (current < upper) {
1340                                found_one = true;
1341                }
1342        }
1343
1344        /*
1345        ** Note: this algorithm ensures that if we're below the lower threshold that we increase the voltage.
1346        ** If we don't find any oscillator below the upper threshold then we decrease the voltage.
1347        ** There is a swing to the values read so that sometimes we'll read a value under the lower threshold.
1348        ** We'll compensate for this by raising the voltage another step.  The swing should never be less than
1349        ** the threshold range or we'll end up vasilating between the two thresholds.
1350        ** You might think that its a good idea to increase the voltage by a larger amount then when lowering.
1351        ** This will bring us above the lower threshold quicker, but might allow us to increase past the upper
1352        ** threshold causing a vasilating situation.  Don't do this!
1353        */
1354
1355        if (increase) 
1356        {
1357                /*BDBG_MSG(("** DAC High (voltage too low) **"));*/
1358
1359                /* we raise the voltage by lowering the DAC */
1360                failed = AvsAdjustDacCode(handle, -(handle->dac_step_size*2));
1361        }
1362        else if (!found_one) 
1363        {
1364                /*BDBG_MSG(("** DAC low (voltage too high) **"));*/
1365
1366                /* we lower the voltage by raising the DAC */
1367                failed = AvsAdjustDacCode(handle, handle->dac_step_size);
1368        }
1369
1370        /*if (!handle->doOnce) printOscillators(handle, "Converged:", true);*/
1371        handle->doOnce = true;
1372        return failed;
1373}
1374
1375/*\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\*/
1376
1377static void AvsInitComplete(BCHP_P_AvsHandle handle)
1378{
1379        BDBG_MSG(("AVS initialized and processing started (AVS enabled)!"));
1380        handle->initialized = true;
1381}
1382
1383static void AvsInitialize(BCHP_P_AvsHandle handle)
1384{
1385        uint32_t current_dac;
1386
1387        /* This checks to make sure that CFE did what it was supposed to do (set the voltage as part of the open-loop process).
1388        ** If this wasn't done than we can't do anything more here -- trying to would be bad.
1389        ** The reason is that changing the voltage by too much here would change the rate at which we access memory.
1390        ** This has been tuned (shmoo) to provide the optimim access speed.  We could move outside the memory optimization window
1391        ** and cause memory access issues if we were to change the voltage too much.
1392        */
1393        current_dac = AvsGetDAC(handle);
1394
1395        if (!current_dac) {
1396                if (!handle->doOnce) {
1397                        BDBG_WRN(("Booted with CFE that doesn't include AVS support --- disabling AVS!"));
1398                        handle->doOnce = true;
1399                }
1400                return;
1401        }
1402
1403        /* Always print something so we know that AVS is enabled in this build! */
1404        /* This is here (instead of in the Open) so that we know that support is included in the application (and that its being called) */
1405        if (!handle->doOnce) {
1406                BDBG_WRN(("AVS support enabled!"));
1407                handle->doOnce = true;
1408        }
1409
1410        handle->original_dac = current_dac; /* this was the value when we first started (set from CFE?) */
1411
1412        /* Process the initialization in multiple steps, where each step ends in setting a new voltage.  This way each subsequent step (after the first)
1413        ** has an automatic delay that occured before our next call-back allowing the sequencer to make an additional pass and get new data.
1414        ** The third case is only necessary in order to allow everything to settle before (debug) printing the final register values.
1415        */
1416        BDBG_MSG(("Starting initialization step %d:", handle->initialization_step));
1417        switch (handle->initialization_step++) 
1418        {
1419                case 0:
1420                        /* Make sure this part has all the oscillators its supposed to */
1421                        AvsUpdateExcludeLists(handle);
1422
1423                        /* Perform some cleanup from CFE */
1424                        AvsCleanup(handle);
1425
1426                        /* Make sure the registers are prepared */
1427                        AvsInitializeRegisters(handle);
1428
1429                        /* Set the starting DAC from the saved value from first run (if any) */
1430                        AvsSetNewThresholds_0(handle);
1431
1432                        /* We don't do any further initialization for FF parts */
1433                        if (handle->ff_part) AvsInitComplete(handle);
1434
1435                        /* If the thresholds were already set in CFE then we don't need to set them here */
1436                        if (handle->thresholdsSet) AvsInitComplete(handle);
1437                        break;
1438
1439                case 1:
1440                        /* Set the new lower thresholds based on the current voltage */
1441                        AvsSetNewThresholds_1(handle);
1442                        break;
1443
1444                case 2:
1445                        /* Set the new upper thresholds based on the current voltage */
1446                        AvsSetNewThresholds_2(handle);
1447                        /*break; <-- don't need to break if NOT printing the new threshold values */
1448
1449                case 3:
1450                        /*printOscillators(handle, "New Thresholds Set:", true);*/
1451                        AvsInitComplete(handle);
1452                        break;
1453        }
1454
1455        /* We always reset the sequencer on the way out.  This will cause it to generate new values for the next pass.
1456        ** This assumes that we do this processing on a periodic basis AND that the period is enough to allow the sequencer
1457        ** to generate the new values before we get called back.
1458        */
1459        AvsResetSequencers(handle->hRegister);
1460        /*AvsClearInterruptFlags(handle->hRegister);*/
1461}
1462
1463static void AvsUpdate(BCHP_P_AvsHandle handle)
1464{
1465        /* Note: we read and print the values before we make any changes as the change can cause mis-reads on voltage values */
1466        AvsReadPvt(handle);
1467
1468        if (!handle->last_dac) handle->last_dac = AvsGetDAC(handle);
1469        handle->last_temp = AvsGetTemperature(handle);
1470
1471#if BDBG_DEBUG_BUILD
1472        {
1473                /* The formula is: centigrade = 418 - (.5556 * temp_reg) [multiplied everything by 1000 in order to get fractional part] */
1474                signed temperature = 418*1000 - (556 * handle->last_temp);
1475                BDBG_MSG(("Voltage = %d.%03dV (0x%x), DAC = %d (0x%x), Temp = [%c%d.%03dC] (0x%x)", 
1476                        mantissa(handle->last_voltage), fraction(handle->last_voltage), handle->last_voltage,
1477                        handle->last_dac, handle->last_dac,
1478                        sign(temperature), mantissa(temperature), fraction(temperature), handle->last_temp));
1479        }
1480#endif
1481
1482        /*
1483        ** Note: you'd think we could use the interrupt value to tell us whether all the oscillators are above the upper threshold
1484    ** or if one is below the lower, but in the current part the interrupt doesn't appear to work if using remote oscillators.
1485        ** So converge or check the voltage on every pass...
1486        */
1487
1488        if (handle->ff_part) 
1489                AvsConstantVoltageProcess(handle);
1490        else
1491                AvsConvergeProcess(handle);
1492
1493        /* When you reset the sequencer it takes a while for the values to be valid.
1494        ** If we reset on the way out of this routine we won't be called back until later when all the values are valid.
1495        */
1496        AvsResetSequencers(handle->hRegister);
1497}
1498
1499/* TODO: update this to use 'rmt' common utils code to do the save and restore for me */
1500
1501/* Save a copy of the registers we set.
1502** This can be used to ensure that none of our registers were stepped on by someother code.
1503** This can also be used to save a copy of the registers in memory prior to entering low-power mode.
1504*/
1505static void AvsSaveRegisters(BCHP_P_AvsHandle handle)
1506{
1507        BREG_Handle hRegister = handle->hRegister;
1508    unsigned int i;
1509
1510    handle->saved_registers.min_dac = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE);
1511    handle->saved_registers.max_dac = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE);
1512    handle->saved_registers.dac = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE);
1513        /* Note: we save them ALL (including the ones we reserved and the ones we're not using) */
1514    for (i=0; i<MAX_CENTRAL_OSCILLATORS; i++)
1515    {
1516        handle->saved_registers.central_thresholds_min[i] = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (i*4));
1517        handle->saved_registers.central_thresholds_max[i] = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (i*4));
1518    }
1519    handle->saved_registers.remote_hvt_min = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8H);
1520    handle->saved_registers.remote_hvt_max = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8H);
1521    handle->saved_registers.remote_svt_min = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8S);
1522    handle->saved_registers.remote_svt_max = BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8S);
1523
1524    handle->saved_registers.sw_controls   = BREG_Read32(hRegister, BCHP_AVS_HW_MNTR_SW_CONTROLS);
1525    handle->saved_registers.default_cent0 = BREG_Read32(hRegister, BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_0);
1526    handle->saved_registers.default_cent1 = BREG_Read32(hRegister, BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_1);
1527    handle->saved_registers.measurement   = BREG_Read32(hRegister, BCHP_AVS_HW_MNTR_ROSC_MEASUREMENT_TIME_CONTROL);
1528
1529        handle->saved_registers.valid = true; /* okay to use the saved set */
1530
1531#if defined(BCHP_PWR_SUPPORT) && defined(SAVE_TO_AON)
1532        /* We need to save the current DAC and PCT_MON_CTRL values so CFE can restore them as part of a warm boot */
1533        {
1534                uint32_t pvt_ctrl = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_PVT_MNTR_CTRL);
1535        uint32_t dac_code = BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE);
1536                dac_code &= 0xffff;
1537                dac_code |= (AVS_CFE_MAGIC<<16); /* tell CFE that these values are valid */
1538#define AON_DAC_CODE_REGISTER 83 /* these were negotiated with Linux and Power Management guys */
1539                BREG_Write32(hRegister, BCHP_AON_CTRL_SYSTEM_DATA_RAMi_ARRAY_BASE + (AON_DAC_CODE_REGISTER*4), dac_code);
1540#define AON_PVT_CTRL_REGISTER 84
1541                BREG_Write32(hRegister, BCHP_AON_CTRL_SYSTEM_DATA_RAMi_ARRAY_BASE + (AON_PVT_CTRL_REGISTER*4), pvt_ctrl);
1542#define AON_PV_SAVE_REGISTER 85
1543                BREG_Write32(hRegister, BCHP_AON_CTRL_SYSTEM_DATA_RAMi_ARRAY_BASE + (AON_PV_SAVE_REGISTER*4), handle->saved_predicted);
1544        }
1545#endif
1546}
1547
1548/* This is used to restore the saved set of registers.
1549** This is used to fix an issue where our registers were stepped on (restore=false).
1550** This is also used to restore the registers when exiting out of low-power mode (restore=true).
1551*/
1552static void AvsRestoreRegisters(BCHP_P_AvsHandle handle, bool restore)
1553{
1554        BREG_Handle hRegister = handle->hRegister;
1555    unsigned int i;
1556
1557        if (!handle->saved_registers.valid) {
1558                BDBG_ERR(("Attempt to restore saved AVS registers from invalid save set!"));
1559                return;
1560        }
1561
1562    if (restore) AvsInitializeRegisters(handle);
1563
1564#if 0
1565        /* This version enables and then sets the values to use */
1566    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 1); /* enable writing */
1567    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE, handle->saved_registers.min_dac);
1568    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE, handle->saved_registers.max_dac);
1569    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE, handle->saved_registers.dac);
1570#else
1571        /* This version sets the value (in shadow copies) which get loaded on the enable */
1572    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE, handle->saved_registers.min_dac);
1573    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE, handle->saved_registers.max_dac);
1574    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE, handle->saved_registers.dac);
1575    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 1); /* enable writing */
1576#endif
1577#ifndef LEAVE_ENABLE_SET
1578        BKNI_Delay(10);
1579    BREG_Write32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE_PROGRAMMING_ENABLE, 0); /* disable writing */
1580#endif
1581        /* Note: we saved them ALL so restore them all */
1582    for (i=0; i<MAX_CENTRAL_OSCILLATORS; i++)
1583    {
1584        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (i*4), handle->saved_registers.central_thresholds_min[i]);
1585        BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (i*4), handle->saved_registers.central_thresholds_max[i]);
1586    }
1587    BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8H, handle->saved_registers.remote_hvt_min);
1588    BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8H, handle->saved_registers.remote_hvt_max);
1589    BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8S, handle->saved_registers.remote_svt_min);
1590    BREG_Write32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8S, handle->saved_registers.remote_svt_max);
1591
1592        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_SW_CONTROLS, handle->saved_registers.sw_controls);
1593        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_0, handle->saved_registers.default_cent0);
1594        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_ENABLE_DEFAULT_CEN_ROSC_1, handle->saved_registers.default_cent1);
1595        BREG_Write32(hRegister, BCHP_AVS_HW_MNTR_ROSC_MEASUREMENT_TIME_CONTROL, handle->saved_registers.measurement);
1596
1597    BREG_Write32(hRegister, SAVED_DAC, handle->original_dac);
1598    BREG_Write32(hRegister, PREDICTED_VOLTAGE, handle->saved_predicted);
1599    BREG_Write32(hRegister, CLOSED_DAC, 0); /* make sure this is zero until we make it not zero */
1600
1601        handle->saved_registers.valid = false; /* technically its still okay to use but this will find a restore without a save */
1602}
1603
1604#if 0
1605/* Test all of my "important" registers to see if they got stepped on.
1606** We can do a save before leaving on each pass of the monitoring function and check on entry.
1607** IF there is a verify error, the restore can put the registers back to what they should be.
1608*/
1609static int AvsCheckSaveRegisters(BCHP_P_AvsHandle handle)
1610{
1611        BREG_Handle hRegister = handle->hRegister;
1612    unsigned int i, result=0;
1613
1614    if ((result |= handle->saved_registers.min_dac == BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MIN_DAC_CODE)))
1615                BDBG_ERR(("Check: MIN_DAC stepped on!"));
1616    if ((result |= handle->saved_registers.max_dac == BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_MAX_DAC_CODE)))
1617                BDBG_ERR(("Check: MAX_DAC stepped on!"));
1618    if ((result |= handle->saved_registers.dac == BREG_Read32(hRegister, BCHP_AVS_PVT_MNTR_CONFIG_DAC_CODE)))
1619                BDBG_ERR(("Check: DAC_CODE stepped on!"));
1620    for (i=STARTING_OSCILLATOR; i<MAX_CENTRAL_OSCILLATORS; i++)
1621    {
1622        if ((result |= handle->saved_registers.central_thresholds_min[i] == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_CEN_ROSC_0 + (i*4))))
1623                        BDBG_ERR(("Check: Central threshold MIN %d stepped on!", i));
1624        if ((result |= handle->saved_registers.central_thresholds_max[i] == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_CEN_ROSC_0 + (i*4))))
1625                        BDBG_ERR(("Check: Central threshold MAX %d stepped on!", i));
1626    }
1627    if ((result |= handle->saved_registers.remote_hvt_min == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8H)))
1628                BDBG_ERR(("Check: Remote threshold HVT min stepped on!"));
1629    if ((result |= handle->saved_registers.remote_hvt_max == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8H)))
1630                BDBG_ERR(("Check: Remote threshold HVT max stepped on!"));
1631    if ((result |= handle->saved_registers.remote_svt_min == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_1_THRESHOLD1_RMT_ROSC_G8S)))
1632                BDBG_ERR(("Check: Remote threshold SVT min stepped on!"));
1633    if ((result |= handle->saved_registers.remote_svt_max == BREG_Read32(hRegister, BCHP_AVS_ROSC_THRESHOLD_2_THRESHOLD2_RMT_ROSC_G8S)))
1634                BDBG_ERR(("Check: Remote threshold SVT max stepped on!"));
1635
1636        return result;
1637}
1638#endif
1639
1640/* The following are included for test purposes */
1641
1642BERR_Code AvsLock(BCHP_P_AvsHandle handle)
1643{
1644    BDBG_ENTER(BCHP_AvsLock);
1645        handle->lock_enabled = true;
1646    BDBG_LEAVE(BCHP_AvsLock);
1647    return BERR_SUCCESS;
1648}
1649
1650BERR_Code AvsUnlock(BCHP_P_AvsHandle handle)
1651{
1652    BDBG_ENTER(BCHP_AvsUnlock);
1653        handle->lock_enabled = false;
1654    BDBG_LEAVE(BCHP_AvsUnlock);
1655    return BERR_SUCCESS;
1656}
1657
1658void AvsGetTestData(BCHP_P_AvsHandle handle, AvsTestData *data)
1659{
1660        BDBG_ASSERT(handle);
1661        BDBG_ASSERT(data);
1662
1663        data->valid = false;
1664        if (!handle->initialized) return;
1665
1666        data->last_dac  = handle->last_dac;
1667        data->last_temp = handle->last_temp;
1668
1669        data->V_0p99  = handle->V_0p99; 
1670        data->V_1p1_0 = handle->V_1p1_0; 
1671        data->V_1p1_1 = handle->V_1p1_1; 
1672        data->V_2p75  = handle->V_2p75; 
1673        data->V_3p63  = handle->V_3p63; 
1674
1675        data->last_voltage_1p1_0 = handle->last_voltage_1p1_0; 
1676        data->last_voltage_1p1_1 = handle->last_voltage_1p1_1; 
1677        data->last_voltage_0p99  = handle->last_voltage_0p99; 
1678        data->last_voltage_2p75  = handle->last_voltage_2p75; 
1679        data->last_voltage_3p63  = handle->last_voltage_3p63;
1680
1681        data->valid = true;
1682}
1683
Note: See TracBrowser for help on using the repository browser.