blob: 36c7c4b809f7f154ffef11a04343dae8e55e981e [file] [log] [blame]
/* Copyright (c) 2013-2014, 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.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/io.h>
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/iopoll.h>
#include <linux/regulator/consumer.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/clk/msm-clock-generic.h>
#include <soc/qcom/clock-local2.h>
#include <dt-bindings/clock/msm-clocks-8974.h>
#include "clock.h"
enum {
LPASS_BASE,
N_BASES,
};
static void __iomem *virt_bases[N_BASES];
#define LPASS_Q6SS_AHB_LFABIF_CBCR 0x22000
#define LPASS_Q6SS_XO_CBCR 0x26000
#define LPASS_Q6_AXI_CBCR 0x11C0
#define Q6SS_AHBM_CBCR 0x22004
#define AUDIO_WRAPPER_BR_CBCR 0x24000
#define LPASS_Q6SS_BCR 0x6000
static struct branch_clk q6ss_ahb_lfabif_clk = {
.cbcr_reg = LPASS_Q6SS_AHB_LFABIF_CBCR,
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
.dbg_name = "q6ss_ahb_lfabif_clk",
.ops = &clk_ops_branch,
CLK_INIT(q6ss_ahb_lfabif_clk.c),
},
};
static struct branch_clk q6ss_xo_clk = {
.cbcr_reg = LPASS_Q6SS_XO_CBCR,
.bcr_reg = LPASS_Q6SS_BCR,
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
.dbg_name = "q6ss_xo_clk",
.ops = &clk_ops_branch,
CLK_INIT(q6ss_xo_clk.c),
},
};
static struct branch_clk q6ss_ahbm_clk = {
.cbcr_reg = Q6SS_AHBM_CBCR,
.has_sibling = 1,
.base = &virt_bases[LPASS_BASE],
.c = {
.dbg_name = "q6ss_ahbm_clk",
.ops = &clk_ops_branch,
CLK_INIT(q6ss_ahbm_clk.c),
},
};
static struct clk_lookup msm_clocks_lpass_8974[] = {
CLK_LOOKUP_OF("core_clk", q6ss_xo_clk, "fe200000.qcom,lpass"),
CLK_LOOKUP_OF("iface_clk", q6ss_ahb_lfabif_clk, "fe200000.qcom,lpass"),
CLK_LOOKUP_OF("reg_clk", q6ss_ahbm_clk, "fe200000.qcom,lpass"),
};
static struct of_device_id msm_clock_lpasscc_match_table[] = {
{ .compatible = "qcom,lpasscc-8974" },
{}
};
static int msm_lpasscc_8974_probe(struct platform_device *pdev)
{
struct resource *res;
int ret;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base");
if (!res) {
dev_err(&pdev->dev, "Unable to retrieve register base.\n");
return -ENOMEM;
}
virt_bases[LPASS_BASE] = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
if (!virt_bases[LPASS_BASE])
return -ENOMEM;
ret = of_msm_clock_register(pdev->dev.of_node, msm_clocks_lpass_8974,
ARRAY_SIZE(msm_clocks_lpass_8974));
if (ret)
return ret;
dev_info(&pdev->dev, "Registered LPASS clocks.\n");
return 0;
}
static struct platform_driver msm_clock_lpasscc_driver = {
.probe = msm_lpasscc_8974_probe,
.driver = {
.name = "lpasscc",
.of_match_table = msm_clock_lpasscc_match_table,
.owner = THIS_MODULE,
},
};
int __init msm_lpasscc_8974_init(void)
{
return platform_driver_register(&msm_clock_lpasscc_driver);
}
arch_initcall(msm_lpasscc_8974_init);