Subversion Repositories shark

Rev

Rev 782 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

/*
 * Project: S.Ha.R.K.
 *
 * Coordinators:
 *   Giorgio Buttazzo    <giorgio@sssup.it>
 *   Paolo Gai           <pj@gandalf.sssup.it>
 *
 * Authors     :
 *   Mauro Marinoni      <mauro.marinoni@unipv.it>
 *
 *
 * ReTiS Lab (Scuola Superiore S.Anna - Pisa - Italy)
 *
 * http://www.sssup.it
 * http://retis.sssup.it
 * http://shark.sssup.it
 */


#include <kernel/func.h>
#include "../include/drivers/shark_cpu26.h"
#include <tracer.h>

//#define __CPU26_DEBUG__

/* CPU Initialization */
extern void early_cpu_init(void);
extern void identify_cpu_0(void);
extern void print_cpu_info_0(void);

/* AMD K6 PowerNow */
extern int  powernow_k6_init(void);
extern void powernow_k6_exit(void);
/* AMD K7 PowerNow */
extern int  powernow_init(void);
extern void powernow_exit(void);
/* AMD K8 PowerNow */
extern int  powernowk8_init(void);
extern void powernowk8_exit(void);
/* Cyrix MediaGX - NatSemi Geode */
extern int  cpufreq_gx_init(void);
extern void cpufreq_gx_exit(void);
/* Pentium4 clock modulation/speed scaling */
extern int  cpufreq_p4_init(void);
extern void cpufreq_p4_exit(void);
/* PentiumM/Centrino SpeedStep */
extern int  centrino_init(void);
extern void centrino_exit(void);
/* Pentium ICH SpeedStep */
extern int  speedstep_ich_init(void);
extern void speedstep_ich_exit(void);
/* Pentium SMI SpeedStep */
/*extern int  speedstep_smi_init(void);
extern void speedstep_smi_exit(void);*/


/* DVS function */
extern int cpufreq_target(unsigned int target_freq, unsigned int relation);
extern int cpufreq_get_cur_freq(void);
extern int cpufreq_get_min_freq(void);
extern int cpufreq_get_max_freq(void);
extern int cpufreq_get_latency(void);
extern int cpufreq_get_available_freqs(int *buf);
extern int cpufreq_show_available_freqs(char *buf);

static int      cpu_installed = FALSE;
static int      dvs_installed = DVS_NONE;
int             cpu26_freqs[DVS_MAX_NUM_FREQS];

/* DVS user function */

extern unsigned int clk_per_msec;

int  CPU26_set_frequency(unsigned int target_freq, unsigned int relation)
{

        int res;

        if (dvs_installed != DVS_NONE && dvs_installed != DVS_MEDIAGX_GEODE) {
                res = cpufreq_target(target_freq, relation);
                TRACER_LOGEVENT(FTrace_EVT_cycles_per_msec,0,clk_per_msec);
                return res;
        } else {
                return -1;
        }

}

extern void gx_force_values(unsigned char on_duration, unsigned char off_duration);

int CPU26_set_suspend_modulation(unsigned char on_duration, unsigned char off_duration) {

        if (dvs_installed == DVS_MEDIAGX_GEODE) {
                gx_force_values(on_duration, off_duration);
                return 0;
        }

        return -1;

}

inline int  CPU26_get_cur_frequency()
{
        return cpufreq_get_cur_freq();
}

inline int  CPU26_get_min_frequency()
{
        return cpufreq_get_min_freq();
}

inline int  CPU26_get_max_frequency()
{
        return cpufreq_get_max_freq();
}

inline int CPU26_get_frequencies(int *buf)
{
        return cpufreq_get_available_freqs (buf);
}

inline int CPU26_show_frequencies(char *buf)
{
        return cpufreq_show_available_freqs (buf);
}

inline int  CPU26_get_latency()
{
        return cpufreq_get_latency();
}

inline int  CPU26_DVS_status(void)
{
        return dvs_installed;
}      

int  CPU26_DVS_init(void)
{
        int ret = 0;

        if (cpu_installed == FALSE)
                return -1;

        if (dvs_installed != DVS_NONE)
                return 0;

        ret = powernow_k6_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check PowerNow! K6 - Returned: %d\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_POWERNOW_K6;
                return dvs_installed;
        }

        ret = powernow_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check PowerNow! K7 - Returned: %d\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_POWERNOW_K7;
                return dvs_installed;
        }

        ret = powernowk8_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check PowerNow! K8 - Returned: %d\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_POWERNOW_K8;
                return dvs_installed;
        }

        ret = cpufreq_gx_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check MediaGX/Geode (Returned: %d)\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_MEDIAGX_GEODE;
                return dvs_installed;
        }

        ret = cpufreq_p4_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check Pentium4 ClockModulation (Returned: %d)\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_P4_CLOCK_MOD;
                return dvs_installed;
        }

        ret = centrino_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check SpeedStep Centrino (Returned: %d)\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_SS_CENTRINO;
                return dvs_installed;
        }

        ret = speedstep_ich_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check SpeedStep ICH (Returned: %d)\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_SS_ICH;
                return dvs_installed;
        }

        /*ret = speedstep_smi_init();
#ifdef __CPU26_DEBUG__
        printk(KERN_DEBUG "Check SpeedStep SMI (Returned: %d)\n", ret);
#endif
        if (!ret) {
                dvs_installed = DVS_SS_SMI;
                return dvs_installed;
        }*/


        return -1;
}

int  CPU26_DVS_close(void)
{
        switch(dvs_installed) {
                case DVS_NONE:
                        return -1;
                case DVS_POWERNOW_K6:
                        powernow_k6_exit();
                        return 0;
                case DVS_POWERNOW_K7:
                        powernow_exit();
                        return 0;
                case DVS_POWERNOW_K8:
                        powernowk8_exit();
                        return 0;
                case DVS_MEDIAGX_GEODE:
                        cpufreq_gx_exit();
                        return 0;
                case DVS_P4_CLOCK_MOD:
                        cpufreq_p4_exit();
                        return 0;
                case DVS_SS_CENTRINO:
                        centrino_exit();
                        return 0;
                case DVS_SS_ICH:
                        speedstep_ich_exit();
                        return 0;
                /*case DVS_SS_SMI:
                        speedstep_smi_exit();
                        return 0;*/

        }

        dvs_installed = DVS_NONE;
        return 0;
}

/* Init the Linux CPU Layer */
inline int  CPU26_installed(void)
{
        return cpu_installed;
}

inline void CPU26_showinfo(void)
{
        print_cpu_info_0();
}

int  CPU26_init(void)
{
        int ret = 0;
       
        if (cpu_installed == TRUE) return 0;

        early_cpu_init();
       
        identify_cpu_0();

        printk(KERN_INFO);
        print_cpu_info_0();

        cpu_installed = TRUE;

        return ret;
}

inline int  CPU26_close(void)
{
        if (cpu_installed == TRUE) {
                return 0;
        } else
                return -1;
}