179 lines
5.0 KiB
C
179 lines
5.0 KiB
C
/*
|
|
* Copyright (C) 2017 Amlogic, Inc. 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 as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Description:
|
|
*/
|
|
|
|
#include <linux/reset.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include "tahoe_common.h"
|
|
|
|
u32 clock_a;
|
|
s32 clock_gate_count = 0;
|
|
|
|
|
|
void tahoe_hw_reset(void)
|
|
{
|
|
#if 0
|
|
if (IS_ERR(s_tahoe_rsts.core_rst) ||
|
|
IS_ERR(s_tahoe_rsts.a_rst) ||
|
|
IS_ERR(s_tahoe_rsts.apb_rst) ||
|
|
IS_ERR(s_tahoe_rsts.sys_rst)) {
|
|
return;
|
|
}
|
|
reset_control_reset(s_tahoe_rsts.core_rst);
|
|
reset_control_reset(s_tahoe_rsts.a_rst);
|
|
reset_control_reset(s_tahoe_rsts.apb_rst);
|
|
reset_control_reset(s_tahoe_rsts.sys_rst);
|
|
#endif
|
|
}
|
|
|
|
void tahoe_clk_put(struct device *dev, struct tahoe_clks *clks)
|
|
{
|
|
if (!(clks->sys_tahoe == NULL || IS_ERR(clks->sys_tahoe)))
|
|
devm_clk_put(dev, clks->sys_tahoe);
|
|
if (!(clks->tahoe_clk == NULL || IS_ERR(clks->tahoe_clk)))
|
|
devm_clk_put(dev, clks->tahoe_clk);
|
|
}
|
|
|
|
int tahoe_clk_get(struct device *dev, struct tahoe_clks *clks)
|
|
{
|
|
int ret;
|
|
|
|
clks->sys_tahoe = devm_clk_get(dev, "sys_tahoe");
|
|
|
|
if (IS_ERR(clks->sys_tahoe)) {
|
|
enc_pr(LOG_ERROR, "cannot get sys_tahoe clock\n");
|
|
clks->sys_tahoe = NULL;
|
|
//ret = -ENOENT;
|
|
//goto err;
|
|
}
|
|
/*
|
|
* "clk_tahoe" is used by the A9.
|
|
* For the same clock function, C5 uses "clk_tahoe_enc".
|
|
*/
|
|
clks->tahoe_clk = devm_clk_get(dev, "clk_tahoe");
|
|
|
|
if (IS_ERR(clks->tahoe_clk)) {
|
|
ret = PTR_ERR(clks->tahoe_clk);
|
|
|
|
if (ret != -ENOENT)
|
|
return ret;
|
|
|
|
clks->tahoe_clk = devm_clk_get(dev, "clk_tahoe_enc");
|
|
if (IS_ERR(clks->tahoe_clk)) {
|
|
ret = PTR_ERR(clks->tahoe_clk);
|
|
enc_pr(LOG_ERROR, "cannot get tahoe clock: %d\n", ret);
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int tahoe_rst_get(struct device *dev, struct tahoe_rsts *rsts)
|
|
{
|
|
//int ret = 0;
|
|
|
|
rsts->core_rst = devm_reset_control_get(dev, "tahoe_core_rst");
|
|
|
|
if (IS_ERR(rsts->core_rst)) {
|
|
enc_pr(LOG_ERROR, "cannot get core_rst\n");
|
|
rsts->core_rst = NULL;
|
|
//ret = -ENOENT;
|
|
//goto err;
|
|
}
|
|
|
|
rsts->a_rst = devm_reset_control_get(dev, "tahoe_a_rst");
|
|
|
|
if (IS_ERR(rsts->a_rst)) {
|
|
enc_pr(LOG_ERROR, "cannot get a_rst\n");
|
|
rsts->a_rst = NULL;
|
|
//ret = -ENOENT;
|
|
//goto err;
|
|
}
|
|
|
|
rsts->apb_rst = devm_reset_control_get(dev, "tahoe_apb_rst");
|
|
|
|
if (IS_ERR(rsts->apb_rst)) {
|
|
enc_pr(LOG_ERROR, "cannot get apb_rst\n");
|
|
rsts->apb_rst = NULL;
|
|
//ret = -ENOENT;
|
|
//goto err;
|
|
}
|
|
|
|
rsts->sys_rst = devm_reset_control_get(dev, "tahoe_sys_rst");
|
|
|
|
if (IS_ERR(rsts->sys_rst)) {
|
|
enc_pr(LOG_ERROR, "cannot get sys_rst\n");
|
|
rsts->sys_rst = NULL;
|
|
//ret = -ENOENT;
|
|
//goto err;
|
|
}
|
|
return 0;
|
|
//err:
|
|
//return ret;
|
|
}
|
|
|
|
void tahoe_clk_enable(struct tahoe_clks *clks,struct platform_device *tahoe_pdev)
|
|
{
|
|
if (clks->sys_tahoe != NULL) {
|
|
clk_prepare_enable(clks->sys_tahoe);
|
|
}
|
|
if (clock_a > 0) {
|
|
enc_pr(LOG_INFO, "tahoe: desired clock_a freq %u\n", clock_a);
|
|
clk_set_rate(clks->tahoe_clk, clock_a);
|
|
} else
|
|
clk_set_rate(clks->tahoe_clk, 666666666);
|
|
|
|
clk_prepare_enable(clks->tahoe_clk);
|
|
|
|
enc_pr(LOG_DEBUG, "tahoe: %ld\n", clk_get_rate(clks->tahoe_clk));
|
|
|
|
/* the power on*/
|
|
pm_runtime_get_sync(&tahoe_pdev->dev);
|
|
mdelay(5);
|
|
enc_pr(LOG_INFO, "tahoe power stauts after poweron: %d\n", pm_runtime_active(&tahoe_pdev->dev));
|
|
|
|
/* reset */
|
|
tahoe_hw_reset(); //__need_modify__
|
|
/* gate the clocks */
|
|
#ifdef TAHOE_SUPPORT_CLOCK_CONTROL
|
|
enc_pr(LOG_INFO, "tahoe_clk_enable, now gate off the clock\n");
|
|
clk_disable(clks->tahoe_clk);
|
|
#endif
|
|
}
|
|
|
|
void tahoe_clk_disable(struct tahoe_clks *clks, struct platform_device *tahoe_pdev)
|
|
{
|
|
#ifdef TAHOE_SUPPORT_CLOCK_CONTROL
|
|
if (clock_gate_count > 0)
|
|
#endif
|
|
{
|
|
enc_pr(LOG_INFO, "tahoe unclosed clock %d\n", clock_gate_count);
|
|
clk_disable(clks->tahoe_clk);
|
|
clock_gate_count = 0;
|
|
}
|
|
clk_unprepare(clks->tahoe_clk);
|
|
if (clks->sys_tahoe != NULL) {
|
|
clk_disable_unprepare(clks->sys_tahoe);
|
|
}
|
|
/* the power off */
|
|
pm_runtime_put_sync(&tahoe_pdev->dev);
|
|
mdelay(5);
|
|
enc_pr(LOG_INFO, "tahoe power stauts after poweroff: %d\n", pm_runtime_active(&tahoe_pdev->dev));
|
|
} |