/* sysTherm.c - Thermal Monitor and Geyserville III mechanism BSP routines */

/*
 * Copyright 2002-2007 Wind River Systems, Inc.
 *
 * The right to copy, distribute, modify or otherwise make use
 * of this software may be licensed only pursuant to the terms
 * of an applicable Wind River license agreement.
 */

/*
modification history
--------------------
01c,11sep07,scm  WIND00103507
01b,07apr07,scm  update for vxBus Apic drivers...
01a,02sep02,hdn  written
*/

/*
DESCRIPTION
This file contains routines to manipulate the Thermal Monitor, 
Clock Modulation and Geyserville III mechanism.  The Thermal Monitor 
is programmed to generate an interrupt to the processor when the 
thermal sensor is tripped.  Software Controlled Clock Modulation and
the Thermal Monitor are both enabled if the processor support them.
In this case, if the thermal status of the processor is hot, Clock 
Modulation through the Thermal Monitor takes precedence and the clock
is modulated at a 50% duty cycle, regardless of the setting of the
on-demand Clock Modulation duty cycle.  Either the Clock Modulation
or the Geyserville III technology is used to handle the performance
and power consumption state transition of the processor.  If the
processor has both capabilities, the Geyserville III is used.  The
Geyserville III support is determined by CPU feature information
returned by CPUID function 1.  Bit 7 returned in ECX denotes 
Geyserville III technology support.  Platforms supporting Geyserville
III (and the required IVMP IV VR technology) will set the GV3_EN bit
and the GV_SEL_LOCK bit in the IA32_MISC_ENABLE MSR during POST.

The initialization routine gv3LibInit() has six parameters.  The 
first parameter is how to manage the processor performance and power 
consumption state.  They are:
    - GV3_MAX_PERF (Maximum performance)
      the highest performance state is used all the time.
    - GV3_MAX_BATT (Maximum battery life)
      the lowest performance state is used all the time.
    - GV3_OPT_BATT (Optimized battery)
      the highest performance state is used if power source is AC.
      the lowest performance state is used if power source is Battery.
    - GV3_AUTO (Automatic)
      the performance state is adjusted to match the current processor
      utilization.
The next four parameters decide the state transition policy as follows.
The second and third one is X and Y, fourth and fifth one is N and M, 
respectively.
    - If CPU utilization is above X<95> % of state S for N<300> 
      millisecond, transition CPU to state S+1.
    - If CPU utilization is below Y<95> % of state S for M<1000> 
      millisecond, transition CPU to state S-1.
The last parameter is a function pointer to the routine that checks if
it is AC powered or Battery powered.  That routine returns TRUE if it 
is AC powered (default), FALSE otherwise.

SEE ALSO: src/arch/i86/gv3Lib.c
*/

#include <vxWorks.h>
#include <sysLib.h>
#include <tickLib.h>
#include <arch/i86/regsGv3.h>

#include <cpuPwrLib.h>

/* defines */

#ifndef LOAPIC_THERMAL
#define LOAPIC_THERMAL                  0x330   /* LVT (Thermal) */
#endif
                                                                                    
#ifndef LOAPIC_FIXED
#define LOAPIC_FIXED                    0x00000000 /* delivery mode: FIXED */
#endif

/* externals */

/* globals */

/* locals */

/* forward declarations */

/*******************************************************************************
*
* sysThermInit - Thermal Monitor initialization routine in the BSP
*
* This routine initializes the Thermal Monitor library.
*
* RETURN: OK, or ERROR if the processor is not capable of Thermal Monitor.
*/

STATUS sysThermInit (void)
    {
    UINT32 loApicBase;

    vxbDevMethodRun( DEVMETHOD_CALL(loApicIntrBaseGet),
                     (void *)&loApicBase );

    /* set up the Thermal Monitor interrupt handler */

    if (sysCpuId.featuresEdx & CPUID_ACPI)
	{
        *(int *)(loApicBase + LOAPIC_THERMAL) = LOAPIC_FIXED | 
					        INT_NUM_LOAPIC_THERMAL;
        cpuPwrThermIntConnect (INUM_TO_IVEC (INT_NUM_LOAPIC_THERMAL));

	}

    return (OK);
    }

