blob: 2ad7d22f7212448092d58f3923afd17391f02e9c [file] [log] [blame]
/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#ifndef _ARCH_ARM_MACH_MSM_MSM_DCVS_H
#define _ARCH_ARM_MACH_MSM_MSM_DCVS_H
#include <mach/msm_dcvs_scm.h>
#define CORE_NAME_MAX (32)
#define CORES_MAX (10)
#define CPU_OFFSET 1 /* used to notify TZ the core number */
#define GPU_OFFSET (CORES_MAX * 2/3) /* there will be more cpus than gpus,
* let the GPU be assigned fewer core
* elements and start later
*/
enum msm_core_idle_state {
MSM_DCVS_IDLE_ENTER,
MSM_DCVS_IDLE_EXIT,
};
enum msm_core_control_event {
MSM_DCVS_ENABLE_IDLE_PULSE,
MSM_DCVS_DISABLE_IDLE_PULSE,
MSM_DCVS_ENABLE_HIGH_LATENCY_MODES,
MSM_DCVS_DISABLE_HIGH_LATENCY_MODES,
};
struct msm_dcvs_sync_rule {
unsigned long cpu_khz;
unsigned long gpu_floor_khz;
};
struct msm_dcvs_platform_data {
struct msm_dcvs_sync_rule *sync_rules;
unsigned num_sync_rules;
unsigned long gpu_max_nom_khz;
};
struct msm_gov_platform_data {
struct msm_dcvs_core_info *info;
int latency;
};
/**
* msm_dcvs_register_cpu_freq
* @freq: the frequency value to register
* @voltage: the operating voltage (in mV) associated with the above frequency
*
* Register a cpu frequency and its operating voltage with dcvs.
*/
#ifdef CONFIG_MSM_DCVS
void msm_dcvs_register_cpu_freq(uint32_t freq, uint32_t voltage);
#else
static inline void msm_dcvs_register_cpu_freq(uint32_t freq, uint32_t voltage)
{}
#endif
/**
* msm_dcvs_idle
* @dcvs_core_id: The id returned by msm_dcvs_register_core
* @state: The enter/exit idle state the core is in
* @iowaited: iowait in us
* on iMSM_DCVS_IDLE_EXIT.
* @return:
* 0 on success,
* -ENOSYS,
* -EINVAL,
* SCM return values
*
* Send idle state notifications to the msm_dcvs driver
*/
int msm_dcvs_idle(int dcvs_core_id, enum msm_core_idle_state state,
uint32_t iowaited);
/**
* struct msm_dcvs_core_info
*
* Core specific information used by algorithm. Need to provide this
* before the sink driver can be registered.
*/
struct msm_dcvs_core_info {
int num_cores;
int *sensors;
int thermal_poll_ms;
struct msm_dcvs_freq_entry *freq_tbl;
struct msm_dcvs_core_param core_param;
struct msm_dcvs_algo_param algo_param;
struct msm_dcvs_energy_curve_coeffs energy_coeffs;
struct msm_dcvs_power_params power_param;
};
/**
* msm_dcvs_register_core
* @type: whether this is a CPU or a GPU
* @type_core_num: The number of the core for a type
* @info: The core specific algorithm parameters.
* @sensor: The thermal sensor number of the core in question
* @return :
* 0 on success,
* -ENOSYS,
* -ENOMEM
*
* Register the core with msm_dcvs driver. Done once at init before calling
* msm_dcvs_freq_sink_register
* Cores that need to run synchronously must share the same group id.
*/
extern int msm_dcvs_register_core(
enum msm_dcvs_core_type type,
int type_core_num,
struct msm_dcvs_core_info *info,
int (*set_frequency)(int type_core_num, unsigned int freq),
unsigned int (*get_frequency)(int type_core_num),
int (*idle_enable)(int type_core_num,
enum msm_core_control_event event),
int (*set_floor_frequency)(int type_core_num, unsigned int freq),
int sensor);
/**
* msm_dcvs_freq_sink_start
* @drv: The sink driver
* @return: Handle unique to the core.
*
* Register the clock driver code with the msm_dvs driver to get notified about
* frequency change requests.
*/
extern int msm_dcvs_freq_sink_start(int dcvs_core_id);
/**
* msm_dcvs_freq_sink_stop
* @drv: The sink driver
* @return:
* 0 on success,
* -EINVAL
*
* Unregister the sink driver for the core. This will cause the source driver
* for the core to stop sending idle pulses.
*/
extern int msm_dcvs_freq_sink_stop(int dcvs_core_id);
/**
* msm_dcvs_update_limits
* @drv: The sink driver
*
* Update the frequency known to dcvs when the limits are changed.
*/
extern void msm_dcvs_update_limits(int dcvs_core_id);
/**
* msm_dcvs_apply_gpu_floor
* @cpu_freq: CPU frequency to compare to GPU sync rules
*
* Apply a GPU floor frequency if the corresponding CPU frequency,
* or the number of CPUs online, requires it.
*/
extern void msm_dcvs_apply_gpu_floor(unsigned long cpu_freq);
/**
* msm_dcvs_update_algo_params
* @return:
* 0 on success, < 0 on error
*
* Updates the DCVS algorithm with parameters depending on the
* number of CPUs online.
*/
extern int msm_dcvs_update_algo_params(void);
#endif