* drivers/devfreq/cpufreq.c
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
* Included Files
****************************************************************************/
#include <debug.h>
#include <nuttx/cpufreq.h>
#include <nuttx/devfreq.h>
#include <nuttx/kmalloc.h>
#include <nuttx/notifier.h>
#include <nuttx/sched.h>
* Private Types
****************************************************************************/
struct cpufreq_data_s
{
struct cpufreq_policy policy;
FAR struct devfreq_s *dev;
};
* Private Functions Prototypes
****************************************************************************/
static const uint32_t *get_table_converter(FAR struct devfreq_s *devfreq);
static int target_index_converter(FAR struct devfreq_s *devfreq,
size_t index);
static uint32_t get_frequency_converter(FAR struct devfreq_s *devfreq);
static int suspend_converter(FAR struct devfreq_s *devfreq);
static int resume_converter(FAR struct devfreq_s *devfreq);
* Private Data
****************************************************************************/
static struct cpufreq_data_s g_cpufreq_data;
static const struct devfreq_driver_s g_cpufreq_ops =
{
.get_table = get_table_converter,
.target_index = target_index_converter,
.get_frequency = get_frequency_converter,
.suspend = suspend_converter,
.resume = resume_converter,
};
* Private Functions
****************************************************************************/
static const uint32_t *get_table_converter(FAR struct devfreq_s *devfreq)
{
FAR struct cpufreq_data_s *data = devfreq->priv;
return data->policy.driver->get_table(&data->policy);
}
static int target_index_converter(FAR struct devfreq_s *devfreq,
size_t index)
{
FAR struct cpufreq_data_s *data = devfreq->priv;
return data->policy.driver->target_index(&data->policy, index);
}
static uint32_t get_frequency_converter(FAR struct devfreq_s *devfreq)
{
FAR struct cpufreq_data_s *data = devfreq->priv;
return data->policy.driver->get_frequency(&data->policy);
}
static int suspend_converter(FAR struct devfreq_s *devfreq)
{
FAR struct cpufreq_data_s *data = devfreq->priv;
return data->policy.driver->suspend(&data->policy);
}
static int resume_converter(FAR struct devfreq_s *devfreq)
{
FAR struct cpufreq_data_s *data = devfreq->priv;
return data->policy.driver->resume(&data->policy);
}
* Public Functions
****************************************************************************/
int cpufreq_init(FAR struct cpufreq_driver *driver)
{
FAR struct devfreq_governor_s *governor;
if (!driver || !driver->get_table || !driver->get_frequency ||
!driver->target_index)
{
return -EINVAL;
}
#if defined(CONFIG_CPUFREQ_DEFAULT_GOV_PERFORMANCE)
governor = devfreq_performance();
#elif defined(CONFIG_CPUFREQ_DEFAULT_GOV_POWERSAVE)
governor = devfreq_powersave();
#elif defined(CONFIG_CPUFREQ_DEFAULT_GOV_ONDEMAND)
governor = devfreq_ondemand();
#elif defined(CONFIG_CPUFREQ_DEFAULT_GOV_QLEARNING)
governor = devfreq_qlearning();
#endif
g_cpufreq_data.policy.driver = driver;
g_cpufreq_data.dev = devfreq_register(CONFIG_CPUFREQ_DEVICE_NAME, governor,
&g_cpufreq_ops,
&g_cpufreq_data);
if (g_cpufreq_data.dev == NULL)
{
return -ENOMEM;
}
return 0;
}
int cpufreq_uninit(void)
{
return devfreq_unregister(g_cpufreq_data.dev);
}
FAR struct cpufreq_policy *cpufreq_policy_get(void)
{
return &g_cpufreq_data.policy;
}
int cpufreq_suspend(FAR struct cpufreq_policy *policy)
{
return devfreq_suspend(g_cpufreq_data.dev);
}
int cpufreq_resume(FAR struct cpufreq_policy *policy)
{
return devfreq_resume(g_cpufreq_data.dev);
}
int cpufreq_register_notifier(FAR struct cpufreq_policy *policy,
FAR struct notifier_block *nb)
{
return devfreq_register_notifier(g_cpufreq_data.dev, nb);
}
int cpufreq_unregister_notifier(FAR struct cpufreq_policy *policy,
FAR struct notifier_block *nb)
{
return devfreq_unregister_notifier(g_cpufreq_data.dev, nb);
}
int cpufreq_get(FAR struct cpufreq_policy *policy)
{
return devfreq_get_frequency(g_cpufreq_data.dev);
}
FAR struct qos_request_s *cpufreq_qos_add_request(
FAR struct cpufreq_policy *policy,
unsigned int min, unsigned int max)
{
return devfreq_qos_add_request(g_cpufreq_data.dev, min, max);
}
int cpufreq_qos_update_request(FAR struct qos_request_s *qos,
unsigned int min, unsigned int max)
{
return devfreq_qos_update_request(g_cpufreq_data.dev, qos, min, max);
}
int cpufreq_qos_remove_request(FAR struct qos_request_s *qos)
{
return devfreq_qos_remove_request(g_cpufreq_data.dev, qos);
}