788 lines
17 KiB
C
Executable file
788 lines
17 KiB
C
Executable file
/*
|
||
* linux-3.10/drivers/video/sunxi/disp2/disp/disp_sys_intf.c
|
||
*
|
||
* Copyright (c) 2007-2017 Allwinnertech Co., Ltd.
|
||
*
|
||
* This software is licensed under the terms of the GNU General Public
|
||
* License version 2, as published by the Free Software Foundation, and
|
||
* may be copied, distributed, and modified under those terms.
|
||
*
|
||
* 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.
|
||
*
|
||
*/
|
||
|
||
#include "de/bsp_display.h"
|
||
#include "disp_sys_intf.h"
|
||
#include "asm/cacheflush.h"
|
||
#include <linux/clk/sunxi.h>
|
||
#include <linux/clk-private.h>
|
||
|
||
/* cache flush flags */
|
||
#define CACHE_FLUSH_I_CACHE_REGION 0
|
||
#define CACHE_FLUSH_D_CACHE_REGION 1
|
||
#define CACHE_FLUSH_CACHE_REGION 2
|
||
#define CACHE_CLEAN_D_CACHE_REGION 3
|
||
#define CACHE_CLEAN_FLUSH_D_CACHE_REGION 4
|
||
#define CACHE_CLEAN_FLUSH_CACHE_REGION 5
|
||
|
||
/*
|
||
*******************************************************************************
|
||
* OSAL_CacheRangeFlush
|
||
*
|
||
* Description:
|
||
* Cache flush
|
||
*
|
||
* Parameters:
|
||
* address : start address to be flush
|
||
* length : size
|
||
* flags : flush flags
|
||
*
|
||
* Return value:
|
||
* void
|
||
*
|
||
* note:
|
||
* void
|
||
*
|
||
*******************************************************************************
|
||
*/
|
||
void disp_sys_cache_flush(void*address, u32 length, u32 flags)
|
||
{
|
||
if (address == NULL || length == 0) {
|
||
return;
|
||
}
|
||
|
||
switch(flags) {
|
||
case CACHE_FLUSH_I_CACHE_REGION:
|
||
break;
|
||
|
||
case CACHE_FLUSH_D_CACHE_REGION:
|
||
break;
|
||
|
||
case CACHE_FLUSH_CACHE_REGION:
|
||
break;
|
||
|
||
case CACHE_CLEAN_D_CACHE_REGION:
|
||
break;
|
||
|
||
case CACHE_CLEAN_FLUSH_D_CACHE_REGION:
|
||
break;
|
||
|
||
case CACHE_CLEAN_FLUSH_CACHE_REGION:
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*
|
||
*******************************************************************************
|
||
* disp_sys_register_irq
|
||
*
|
||
* Description:
|
||
* irq register
|
||
*
|
||
* Parameters:
|
||
* irqno <20><>input. irq no
|
||
* flags <20><>input.
|
||
* Handler <20><>input. isr handler
|
||
* pArg <20><>input. para
|
||
* DataSize <20><>input. len of para
|
||
* prio <20><>input. priority
|
||
|
||
*
|
||
* Return value:
|
||
*
|
||
*
|
||
* note:
|
||
* typedef s32 (*ISRCallback)( void *pArg)<29><>
|
||
*
|
||
*******************************************************************************
|
||
*/
|
||
int disp_sys_register_irq(u32 IrqNo, u32 Flags, void* Handler,void *pArg,u32 DataSize,u32 Prio)
|
||
{
|
||
__inf("%s, irqNo=%d, Handler=0x%p, pArg=0x%p\n", __func__, IrqNo, Handler, pArg);
|
||
return request_irq(IrqNo, (irq_handler_t)Handler, IRQF_DISABLED, "dispaly", pArg);
|
||
}
|
||
|
||
/*
|
||
*******************************************************************************
|
||
* disp_sys_unregister_irq
|
||
*
|
||
* Description:
|
||
* irq unregister
|
||
*
|
||
* Parameters:
|
||
* irqno <09><>input. irq no
|
||
* handler <09><>input. isr handler
|
||
* Argment <09><>input. para
|
||
*
|
||
* Return value:
|
||
* void
|
||
*
|
||
* note:
|
||
* void
|
||
*
|
||
*******************************************************************************
|
||
*/
|
||
void disp_sys_unregister_irq(u32 IrqNo, void* Handler, void *pArg)
|
||
{
|
||
free_irq(IrqNo, pArg);
|
||
}
|
||
|
||
/*
|
||
*******************************************************************************
|
||
* disp_sys_enable_irq
|
||
*
|
||
* Description:
|
||
* enable irq
|
||
*
|
||
* Parameters:
|
||
* irqno <20><>input. irq no
|
||
*
|
||
* Return value:
|
||
* void
|
||
*
|
||
* note:
|
||
* void
|
||
*
|
||
*******************************************************************************
|
||
*/
|
||
void disp_sys_enable_irq(u32 IrqNo)
|
||
{
|
||
//enable_irq(IrqNo);
|
||
}
|
||
|
||
/*
|
||
*******************************************************************************
|
||
* disp_sys_disable_irq
|
||
*
|
||
* Description:
|
||
* disable irq
|
||
*
|
||
* Parameters:
|
||
* irqno <20><>input. irq no
|
||
*
|
||
* Return value:
|
||
* void
|
||
*
|
||
* note:
|
||
* void
|
||
*
|
||
*******************************************************************************
|
||
*/
|
||
void disp_sys_disable_irq(u32 IrqNo)
|
||
{
|
||
//disable_irq(IrqNo);
|
||
}
|
||
|
||
void * disp_sys_malloc(u32 Size)
|
||
{
|
||
return kmalloc(Size, GFP_KERNEL | __GFP_ZERO);
|
||
}
|
||
|
||
void disp_sys_free(void *Addr)
|
||
{
|
||
kfree(Addr);
|
||
}
|
||
|
||
|
||
/* type: 0:invalid, 1: int; 2:str, 3: gpio */
|
||
int disp_sys_script_get_item(char *main_name, char *sub_name, int value[], int type)
|
||
{
|
||
char compat[32];
|
||
u32 len = 0;
|
||
struct device_node *node;
|
||
int ret = 0;
|
||
struct gpio_config config;
|
||
|
||
len = sprintf(compat, "allwinner,sunxi-%s", main_name);
|
||
if (len > 32)
|
||
__wrn("size of mian_name is out of range\n");
|
||
|
||
node = of_find_compatible_node(NULL, NULL, compat);
|
||
if (!node) {
|
||
__wrn("of_find_compatible_node %s fail\n", compat);
|
||
return ret;
|
||
}
|
||
|
||
if (1 == type) {
|
||
if (of_property_read_u32_array(node, sub_name, value, 1))
|
||
__inf("of_property_read_u32_array %s.%s fail\n", main_name, sub_name);
|
||
else
|
||
ret = type;
|
||
} else if (2 == type) {
|
||
const char *str;
|
||
|
||
if (of_property_read_string(node, sub_name, &str))
|
||
__inf("of_property_read_string %s.%s fail\n", main_name, sub_name);
|
||
else {
|
||
ret = type;
|
||
memcpy((void*)value, str, strlen(str)+1);
|
||
}
|
||
} else if (3 == type) {
|
||
disp_gpio_set_t *gpio_info = (disp_gpio_set_t *)value;
|
||
int gpio;
|
||
|
||
gpio = of_get_named_gpio_flags(node, sub_name, 0, (enum of_gpio_flags *)&config);
|
||
if (!gpio_is_valid(gpio))
|
||
goto exit;
|
||
|
||
gpio_info->gpio = config.gpio;
|
||
gpio_info->mul_sel = config.mul_sel;
|
||
gpio_info->pull = config.pull;
|
||
gpio_info->drv_level = config.drv_level;
|
||
gpio_info->data = config.data;
|
||
memcpy(gpio_info->gpio_name, sub_name, strlen(sub_name)+1);
|
||
__inf("%s.%s gpio=%d,mul_sel=%d,data:%d\n",main_name, sub_name, gpio_info->gpio, gpio_info->mul_sel, gpio_info->data);
|
||
ret = type;
|
||
}
|
||
|
||
exit:
|
||
return ret;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_script_get_item);
|
||
|
||
int disp_sys_get_ic_ver(void)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
int disp_sys_gpio_request(disp_gpio_set_t *gpio_list, u32 group_count_max)
|
||
{
|
||
int ret = 0;
|
||
struct gpio_config pin_cfg;
|
||
char pin_name[32];
|
||
u32 config;
|
||
|
||
if (gpio_list == NULL) {
|
||
__wrn("%s: gpio list is null\n", __func__);
|
||
return 0;
|
||
}
|
||
|
||
pin_cfg.gpio = gpio_list->gpio;
|
||
pin_cfg.mul_sel = gpio_list->mul_sel;
|
||
pin_cfg.pull = gpio_list->pull;
|
||
pin_cfg.drv_level = gpio_list->drv_level;
|
||
pin_cfg.data = gpio_list->data;
|
||
ret = gpio_request(pin_cfg.gpio, NULL);
|
||
if (0 != ret) {
|
||
__wrn("%s failed, gpio_name=%s, gpio=%d, ret=%d\n", __func__, gpio_list->gpio_name, gpio_list->gpio, ret);
|
||
return 0;
|
||
} else {
|
||
__inf("%s, gpio_name=%s, gpio=%d, <%d,%d,%d,%d>ret=%d\n", __func__, gpio_list->gpio_name, gpio_list->gpio,\
|
||
gpio_list->mul_sel, gpio_list->pull, gpio_list->drv_level, gpio_list->data, ret);
|
||
}
|
||
ret = pin_cfg.gpio;
|
||
|
||
if (!IS_AXP_PIN(pin_cfg.gpio)) {
|
||
/* valid pin of sunxi-pinctrl,
|
||
* config pin attributes individually.
|
||
*/
|
||
sunxi_gpio_to_name(pin_cfg.gpio, pin_name);
|
||
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_FUNC, pin_cfg.mul_sel);
|
||
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
||
if (pin_cfg.pull != GPIO_PULL_DEFAULT) {
|
||
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_PUD, pin_cfg.pull);
|
||
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
||
}
|
||
if (pin_cfg.drv_level != GPIO_DRVLVL_DEFAULT) {
|
||
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DRV, pin_cfg.drv_level);
|
||
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
||
}
|
||
if (pin_cfg.data != GPIO_DATA_DEFAULT) {
|
||
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg.data);
|
||
pin_config_set(SUNXI_PINCTRL, pin_name, config);
|
||
}
|
||
} else if (IS_AXP_PIN(pin_cfg.gpio)) {
|
||
/* valid pin of axp-pinctrl,
|
||
* config pin attributes individually.
|
||
*/
|
||
sunxi_gpio_to_name(pin_cfg.gpio, pin_name);
|
||
if (pin_cfg.data != GPIO_DATA_DEFAULT) {
|
||
config = SUNXI_PINCFG_PACK(SUNXI_PINCFG_TYPE_DAT, pin_cfg.data);
|
||
pin_config_set(AXP_PINCTRL, pin_name, config);
|
||
}
|
||
} else {
|
||
pr_warn("invalid pin [%d] from sys-config\n", pin_cfg.gpio);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_gpio_request);
|
||
|
||
int disp_sys_gpio_request_simple(disp_gpio_set_t *gpio_list, u32 group_count_max)
|
||
{
|
||
#if 0
|
||
int ret = 0;
|
||
struct gpio_config pin_cfg;
|
||
|
||
if (gpio_list == NULL)
|
||
return 0;
|
||
|
||
pin_cfg.gpio = gpio_list->gpio;
|
||
pin_cfg.mul_sel = gpio_list->mul_sel;
|
||
pin_cfg.pull = gpio_list->pull;
|
||
pin_cfg.drv_level = gpio_list->drv_level;
|
||
pin_cfg.data = gpio_list->data;
|
||
ret = gpio_request(pin_cfg.gpio, NULL);
|
||
if (0 != ret) {
|
||
__wrn("%s failed, gpio_name=%s, gpio=%d, ret=%d\n", __func__, gpio_list->gpio_name, gpio_list->gpio, ret);
|
||
return ret;
|
||
} else {
|
||
__inf("%s, gpio_name=%s, gpio=%d, ret=%d\n", __func__, gpio_list->gpio_name, gpio_list->gpio, ret);
|
||
}
|
||
ret = pin_cfg.gpio;
|
||
|
||
return ret;
|
||
#endif
|
||
return 0;
|
||
}
|
||
int disp_sys_gpio_release(int p_handler, s32 if_release_to_default_status)
|
||
{
|
||
if (p_handler) {
|
||
gpio_free(p_handler);
|
||
} else {
|
||
__wrn("OSAL_GPIO_Release, hdl is NULL\n");
|
||
}
|
||
return 0;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_gpio_release);
|
||
|
||
/* direction: 0:input, 1:output */
|
||
int disp_sys_gpio_set_direction(u32 p_handler, u32 direction, const char *gpio_name)
|
||
{
|
||
int ret = -1;
|
||
|
||
if (p_handler) {
|
||
if (direction) {
|
||
s32 value;
|
||
|
||
value = __gpio_get_value(p_handler);
|
||
ret = gpio_direction_output(p_handler, value);
|
||
if (ret != 0) {
|
||
__wrn("gpio_direction_output fail!\n");
|
||
}
|
||
} else {
|
||
ret = gpio_direction_input(p_handler);
|
||
if (ret != 0) {
|
||
__wrn("gpio_direction_input fail!\n");
|
||
}
|
||
}
|
||
} else {
|
||
__wrn("OSAL_GPIO_DevSetONEPIN_IO_STATUS, hdl is NULL\n");
|
||
ret = -1;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_gpio_get_value(u32 p_handler, const char *gpio_name)
|
||
{
|
||
if (p_handler) {
|
||
return __gpio_get_value(p_handler);
|
||
}
|
||
__wrn("OSAL_GPIO_DevREAD_ONEPIN_DATA, hdl is NULL\n");
|
||
return -1;
|
||
}
|
||
|
||
int disp_sys_gpio_set_value(u32 p_handler, u32 value_to_gpio, const char *gpio_name)
|
||
{
|
||
if (p_handler) {
|
||
__gpio_set_value(p_handler, value_to_gpio);
|
||
} else {
|
||
__wrn("OSAL_GPIO_DevWRITE_ONEPIN_DATA, hdl is NULL\n");
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
int disp_sys_pin_set_state(char *dev_name, char *name)
|
||
{
|
||
char compat[32];
|
||
u32 len = 0;
|
||
struct device_node *node;
|
||
struct platform_device *pdev;
|
||
struct pinctrl *pctl;
|
||
struct pinctrl_state *state;
|
||
int ret = -1;
|
||
|
||
len = sprintf(compat, "allwinner,sunxi-%s", dev_name);
|
||
if (len > 32)
|
||
__wrn("size of mian_name is out of range\n");
|
||
|
||
node = of_find_compatible_node(NULL, NULL, compat);
|
||
if (!node) {
|
||
__wrn("of_find_compatible_node %s fail\n", compat);
|
||
goto exit;
|
||
}
|
||
|
||
pdev = of_find_device_by_node(node);
|
||
if (!node) {
|
||
__wrn("of_find_device_by_node for %s fail\n", compat);
|
||
goto exit;
|
||
}
|
||
|
||
pctl = pinctrl_get(&pdev->dev);
|
||
if (IS_ERR(pctl)) {
|
||
__wrn("pinctrl_get for %s fail\n", compat);
|
||
ret = PTR_ERR(pctl);
|
||
goto exit;
|
||
}
|
||
|
||
state = pinctrl_lookup_state(pctl, name);
|
||
if (IS_ERR(state)) {
|
||
__wrn("pinctrl_lookup_state for %s fail\n", compat);
|
||
ret = PTR_ERR(state);
|
||
goto exit;
|
||
}
|
||
|
||
ret = pinctrl_select_state(pctl, state);
|
||
if (ret < 0) {
|
||
__wrn("pinctrl_select_state(%s) for %s fail\n", name, compat);
|
||
goto exit;
|
||
}
|
||
ret = 0;
|
||
exit:
|
||
return ret;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_pin_set_state);
|
||
|
||
int disp_sys_power_enable(char *name)
|
||
{
|
||
int ret = 0;
|
||
#ifdef CONFIG_AW_AXP
|
||
struct regulator *regu= NULL;
|
||
regu= regulator_get(NULL, name);
|
||
if (IS_ERR(regu)) {
|
||
__wrn("some error happen, fail to get regulator %s\n", name);
|
||
goto exit;
|
||
}
|
||
|
||
//enalbe regulator
|
||
ret = regulator_enable(regu);
|
||
if (0 != ret) {
|
||
__wrn("some error happen, fail to enable regulator %s!\n", name);
|
||
goto exit1;
|
||
} else {
|
||
__inf("suceess to enable regulator %s!\n", name);
|
||
}
|
||
|
||
exit1:
|
||
//put regulater, when module exit
|
||
regulator_put(regu);
|
||
exit:
|
||
#endif
|
||
return ret;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_power_enable);
|
||
|
||
int disp_sys_power_disable(char *name)
|
||
{
|
||
int ret = 0;
|
||
#ifdef CONFIG_AW_AXP
|
||
struct regulator *regu= NULL;
|
||
|
||
regu= regulator_get(NULL, name);
|
||
if (IS_ERR(regu)) {
|
||
__wrn("some error happen, fail to get regulator %s\n", name);
|
||
goto exit;
|
||
}
|
||
|
||
//disalbe regulator
|
||
ret = regulator_disable(regu);
|
||
if (0 != ret) {
|
||
__wrn("some error happen, fail to disable regulator %s!\n", name);
|
||
goto exit1;
|
||
} else {
|
||
__inf("suceess to disable regulator %s!\n", name);
|
||
}
|
||
|
||
exit1:
|
||
//put regulater, when module exit
|
||
regulator_put(regu);
|
||
exit:
|
||
#endif
|
||
return ret;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_power_disable);
|
||
|
||
#if defined(CONFIG_PWM_SUNXI) || defined(CONFIG_PWM_SUNXI_NEW)
|
||
uintptr_t disp_sys_pwm_request(u32 pwm_id)
|
||
{
|
||
uintptr_t ret = 0;
|
||
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = pwm_request(pwm_id, "lcd");
|
||
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_request pwm %d fail!\n", pwm_id);
|
||
} else {
|
||
__inf("disp_sys_pwm_request pwm %d success!\n", pwm_id);
|
||
}
|
||
ret = (uintptr_t)pwm_dev;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_free(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = (struct pwm_device *)p_handler;
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_free, handle is NULL!\n");
|
||
ret = -1;
|
||
} else {
|
||
pwm_free(pwm_dev);
|
||
__inf("disp_sys_pwm_free pwm %d \n", pwm_dev->pwm);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_enable(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = (struct pwm_device *)p_handler;
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_Enable, handle is NULL!\n");
|
||
ret = -1;
|
||
} else {
|
||
ret = pwm_enable(pwm_dev);
|
||
__inf("disp_sys_pwm_Enable pwm %d \n", pwm_dev->pwm);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_disable(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = (struct pwm_device *)p_handler;
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_Disable, handle is NULL!\n");
|
||
ret = -1;
|
||
} else {
|
||
pwm_disable(pwm_dev);
|
||
__inf("disp_sys_pwm_Disable pwm %d \n", pwm_dev->pwm);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_config(uintptr_t p_handler, int duty_ns, int period_ns)
|
||
{
|
||
int ret = 0;
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = (struct pwm_device *)p_handler;
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_Config, handle is NULL!\n");
|
||
ret = -1;
|
||
} else {
|
||
ret = pwm_config(pwm_dev, duty_ns, period_ns);
|
||
__debug("disp_sys_pwm_Config pwm %d, <%d / %d> \n", pwm_dev->pwm, duty_ns, period_ns);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_set_polarity(uintptr_t p_handler, int polarity)
|
||
{
|
||
int ret = 0;
|
||
struct pwm_device *pwm_dev;
|
||
|
||
pwm_dev = (struct pwm_device *)p_handler;
|
||
if (NULL == pwm_dev || IS_ERR(pwm_dev)) {
|
||
__wrn("disp_sys_pwm_Set_Polarity, handle is NULL!\n");
|
||
ret = -1;
|
||
} else {
|
||
ret = pwm_set_polarity(pwm_dev, polarity);
|
||
__inf("disp_sys_pwm_Set_Polarity pwm %d, active %s\n", pwm_dev->pwm, (polarity==0)? "high":"low");
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
#else
|
||
uintptr_t disp_sys_pwm_request(u32 pwm_id)
|
||
{
|
||
uintptr_t ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_free(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_enable(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_disable(uintptr_t p_handler)
|
||
{
|
||
int ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_config(uintptr_t p_handler, int duty_ns, int period_ns)
|
||
{
|
||
int ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_pwm_set_polarity(uintptr_t p_handler, int polarity)
|
||
{
|
||
int ret = 0;
|
||
|
||
return ret;
|
||
}
|
||
|
||
#endif
|
||
|
||
int disp_sys_clk_set_rate(const char *id, unsigned long rate)
|
||
{
|
||
struct clk* hclk = NULL;
|
||
int ret = 0;
|
||
|
||
hclk = clk_get(NULL, id);
|
||
|
||
if (NULL == hclk || IS_ERR(hclk)) {
|
||
__wrn("Fail to get handle for clock %s.\n", id);
|
||
return -1;
|
||
}
|
||
|
||
if (rate == clk_get_rate(hclk)) {
|
||
__inf("Sys clk %s rate is alreay %ld, not need to set.\n", id, rate);
|
||
clk_put(hclk);
|
||
return 0;
|
||
}
|
||
|
||
ret = clk_set_rate(hclk, rate);
|
||
if (0 != ret)
|
||
__wrn("Fail to set rate[%ld] for clock %s.\n", rate, id);
|
||
else
|
||
__inf("Success to set rate[%ld] for clock %s.\n", rate, id);
|
||
|
||
clk_put(hclk);
|
||
|
||
return ret;
|
||
}
|
||
|
||
unsigned long disp_sys_clk_get_rate(const char *id)
|
||
{
|
||
struct clk* hclk = NULL;
|
||
unsigned long rate = 0;
|
||
|
||
hclk = clk_get(NULL, id);
|
||
|
||
if (NULL == hclk || IS_ERR(hclk)) {
|
||
__wrn("Fail to get handle for clock %s.\n", id);
|
||
return -1;
|
||
}
|
||
|
||
rate = clk_get_rate(hclk);
|
||
__inf("clock %s's rate is %ld\n", id, rate);
|
||
clk_put(hclk);
|
||
|
||
return rate;
|
||
}
|
||
EXPORT_SYMBOL(disp_sys_clk_set_rate);
|
||
int disp_sys_clk_set_parent(const char *id, const char *parent)
|
||
{
|
||
struct clk* hclk = NULL;
|
||
struct clk* hckl_parent = NULL;
|
||
int ret = 0;
|
||
|
||
hclk = clk_get(NULL, id);
|
||
|
||
if (NULL == hclk || IS_ERR(hclk)) {
|
||
__wrn("Fail to get handle for clock %s.\n", id);
|
||
return -1;
|
||
}
|
||
|
||
hckl_parent = clk_get(NULL, parent);
|
||
|
||
if (NULL == hckl_parent || IS_ERR(hckl_parent)) {
|
||
__wrn("Fail to get handle for clock %s.\n", parent);
|
||
clk_put(hclk);
|
||
return -1;
|
||
}
|
||
|
||
ret = clk_set_parent(hclk, hckl_parent);
|
||
if (0 != ret)
|
||
__wrn("Fail to set parent %s for clk %s\n", parent, id);
|
||
else
|
||
__inf("Success to set parent %s for clk %s\n", parent, id);
|
||
|
||
clk_put(hclk);
|
||
clk_put(hckl_parent);
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_clk_enable(const char *id)
|
||
{
|
||
struct clk* hclk = NULL;
|
||
int ret = 0;
|
||
|
||
hclk = clk_get(NULL, id);
|
||
|
||
if (NULL == hclk || IS_ERR(hclk)) {
|
||
__wrn("Fail to get handle for clock %s.\n", id);
|
||
return -1;
|
||
}
|
||
|
||
ret = clk_prepare_enable(hclk);
|
||
if (0 == ret)
|
||
__inf("Success enable clock %s.\n", id);
|
||
else
|
||
__wrn("Fail enable clock %s.\n", id);
|
||
clk_put(hclk);
|
||
|
||
return ret;
|
||
}
|
||
|
||
int disp_sys_clk_disable(const char *id)
|
||
{
|
||
struct clk* hclk = NULL;
|
||
int ret = 0;
|
||
|
||
hclk = clk_get(NULL, id);
|
||
|
||
if (NULL == hclk || IS_ERR(hclk)) {
|
||
__wrn("Fail to get handle for clock %s.\n", id);
|
||
return -1;
|
||
}
|
||
|
||
if (hclk->enable_count > 0)
|
||
clk_disable(hclk);
|
||
else
|
||
__wrn("clock %s is already disabled!!!\n", id);
|
||
clk_put(hclk);
|
||
|
||
return ret;
|
||
}
|
||
|
||
EXPORT_SYMBOL(disp_sys_clk_get_rate);
|
||
EXPORT_SYMBOL(disp_sys_clk_set_parent);
|
||
EXPORT_SYMBOL(disp_sys_clk_enable);
|
||
EXPORT_SYMBOL(disp_sys_clk_disable);
|