blob: 421b33c2d73e6918a0a6a6977689631c767a19e5 [file] [log] [blame]
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: owen.chen <owen.chen@mediatek.com>
*/
/*
* @file mtk-clk-buf-ctl.c
* @brief Driver for clock buffer control
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "mtk_clkbuf_ctl.h"
#include "mtk_clkbuf_common.h"
#include "mtk_clkbuf_hw.h"
DEFINE_MUTEX(clk_buf_ctrl_lock);
static bool _clk_buf_check(void)
{
if (clk_buf_get_bringup_sta())
return false;
return clk_buf_get_init_sta();
}
int clk_buf_voter_ctrl_by_id(const uint8_t subsys_id, enum RC_CTRL_CMD rc_req)
{
return 0;
}
EXPORT_SYMBOL(clk_buf_voter_ctrl_by_id);
int clk_buf_set_xo_ctrl(u32 id, bool onoff)
{
if (_clk_buf_check())
return clk_buf_hw_ctrl(id, onoff);
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_set_xo_ctrl);
/* for spm driver use */
int is_clk_buf_under_flightmode(void)
{
if (_clk_buf_check())
return clk_buf_get_flight_mode();
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(is_clk_buf_under_flightmode);
/* for ccci driver to notify this */
int clk_buf_set_flight_mode(bool on)
{
if (_clk_buf_check())
return clk_buf_hw_set_flight_mode(on);
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_set_flight_mode);
int clk_buf_set_bblpm(bool on)
{
if (_clk_buf_check())
return clk_buf_ctrl_bblpm_sw(on);
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_set_bblpm);
int clk_buf_dump_log(void)
{
if (_clk_buf_check()) {
clk_buf_hw_dump_misc_log();
return 0;
}
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_dump_log);
int clk_buf_get_xo_en_sta(u32 id)
{
u32 stat = 0;
int ret = 0;
if (_clk_buf_check()) {
ret = clk_buf_hw_get_xo_en(id, &stat);
if (!ret)
return stat;
}
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_get_xo_en_sta);
int clk_buf_get_bblpm_enter_cond(u32 *bblpm_cond)
{
if (_clk_buf_check()) {
clk_buf_get_enter_bblpm_cond(bblpm_cond);
return 0;
}
return CLK_BUF_FAIL;
}
EXPORT_SYMBOL(clk_buf_get_bblpm_enter_cond);
static int mtk_clkbuf_probe(struct platform_device *pdev)
{
int ret = 0;
if (clkbuf_hw_is_ready() == CLK_BUF_NOT_READY)
return -EPROBE_DEFER;
clk_buf_get_bringup_node(pdev);
if (clk_buf_get_bringup_sta())
return 0;
ret = clk_buf_dts_init(pdev);
if (ret) {
pr_err("%s: failed due to chip DTS failed\n", __func__);
return ret;
}
ret = clk_buf_fs_init();
if (ret) {
pr_err("%s: failed due to file operation failed\n", __func__);
return ret;
}
if (clk_buf_get_init_sta())
return -EALREADY;
clk_buf_set_init_sta(true);
ret = clk_buf_xo_init();
if (ret) {
pr_err("%s: failed to init xo(%d)\n", __func__, ret);
return ret;
}
ret = clk_buf_bblpm_init();
if (ret) {
pr_err("%s: failed due bblpm init failed\n", __func__);
return ret;
}
return ret;
}
static const struct platform_device_id mtk_clkbuf_ids[] = {
{"mtk-clock-buffer", 0},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(platform, mtk_clkbuf_ids);
static const struct of_device_id mtk_clkbuf_of_match[] = {
{
.compatible = "mediatek,clock_buffer",
},
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, mtk_clkbuf_of_match);
static struct platform_driver mtk_clkbuf_driver = {
.driver = {
.name = "mtk-clock-buffer",
.of_match_table = of_match_ptr(mtk_clkbuf_of_match),
},
.probe = mtk_clkbuf_probe,
.id_table = mtk_clkbuf_ids,
};
module_platform_driver(mtk_clkbuf_driver);
MODULE_AUTHOR("Owen Chen <owen.chen@mediatek.com>");
MODULE_DESCRIPTION("SOC Driver for MediaTek Clock Buffer");
MODULE_LICENSE("GPL v2");