forked from luck/tmp_suning_uos_patched
Merge branch 'clk-qcom-sdm845-lpass' into clk-next
- Qualcomm SDM845 audio subsystem clks * clk-qcom-sdm845-lpass: clk: qcom: Add lpass clock controller driver for SDM845 dt-bindings: clock: Introduce QCOM LPASS clock bindings dt-bindings: clock: Update GCC bindings for protected-clocks
This commit is contained in:
commit
3315fe5faf
|
@ -35,6 +35,8 @@ be part of GCC and hence the TSENS properties can also be
|
|||
part of the GCC/clock-controller node.
|
||||
For more details on the TSENS properties please refer
|
||||
Documentation/devicetree/bindings/thermal/qcom-tsens.txt
|
||||
- protected-clocks : Protected clock specifier list as per common clock
|
||||
binding.
|
||||
|
||||
Example:
|
||||
clock-controller@900000 {
|
||||
|
@ -55,3 +57,17 @@ Example of GCC with TSENS properties:
|
|||
#reset-cells = <1>;
|
||||
#thermal-sensor-cells = <1>;
|
||||
};
|
||||
|
||||
Example of GCC with protected-clocks properties:
|
||||
clock-controller@100000 {
|
||||
compatible = "qcom,gcc-sdm845";
|
||||
reg = <0x100000 0x1f0000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
#power-domain-cells = <1>;
|
||||
protected-clocks = <GCC_QSPI_CORE_CLK>,
|
||||
<GCC_QSPI_CORE_CLK_SRC>,
|
||||
<GCC_QSPI_CNOC_PERIPH_AHB_CLK>,
|
||||
<GCC_LPASS_Q6_AXI_CLK>,
|
||||
<GCC_LPASS_SWAY_CLK>;
|
||||
};
|
||||
|
|
26
Documentation/devicetree/bindings/clock/qcom,lpasscc.txt
Normal file
26
Documentation/devicetree/bindings/clock/qcom,lpasscc.txt
Normal file
|
@ -0,0 +1,26 @@
|
|||
Qualcomm LPASS Clock Controller Binding
|
||||
-----------------------------------------------
|
||||
|
||||
Required properties :
|
||||
- compatible : shall contain "qcom,sdm845-lpasscc"
|
||||
- #clock-cells : from common clock binding, shall contain 1.
|
||||
- reg : shall contain base register address and size,
|
||||
in the order
|
||||
Index-0 maps to LPASS_CC register region
|
||||
Index-1 maps to LPASS_QDSP6SS register region
|
||||
|
||||
Optional properties :
|
||||
- reg-names : register names of LPASS domain
|
||||
"cc", "qdsp6ss".
|
||||
|
||||
Example:
|
||||
|
||||
The below node has to be defined in the cases where the LPASS peripheral loader
|
||||
would bring the subsystem out of reset.
|
||||
|
||||
lpasscc: clock-controller@17014000 {
|
||||
compatible = "qcom,sdm845-lpasscc";
|
||||
reg = <0x17014000 0x1f004>, <0x17300000 0x200>;
|
||||
reg-names = "cc", "qdsp6ss";
|
||||
#clock-cells = <1>;
|
||||
};
|
|
@ -276,6 +276,14 @@ config SDM_DISPCC_845
|
|||
Say Y if you want to support display devices and functionality such as
|
||||
splash screen.
|
||||
|
||||
config SDM_LPASSCC_845
|
||||
tristate "SDM845 Low Power Audio Subsystem (LPAAS) Clock Controller"
|
||||
select SDM_GCC_845
|
||||
help
|
||||
Support for the LPASS clock controller on SDM845 devices.
|
||||
Say Y if you want to use the LPASS branch clocks of the LPASS clock
|
||||
controller to reset the LPASS subsystem.
|
||||
|
||||
config SPMI_PMIC_CLKDIV
|
||||
tristate "SPMI PMIC clkdiv Support"
|
||||
depends on SPMI || COMPILE_TEST
|
||||
|
|
|
@ -47,6 +47,7 @@ obj-$(CONFIG_SDM_DISPCC_845) += dispcc-sdm845.o
|
|||
obj-$(CONFIG_SDM_GCC_660) += gcc-sdm660.o
|
||||
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
|
||||
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
|
||||
obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
|
||||
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
|
||||
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
|
||||
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
|
||||
|
|
|
@ -3153,6 +3153,37 @@ static struct clk_branch gcc_cpuss_gnoc_clk = {
|
|||
},
|
||||
};
|
||||
|
||||
/* TODO: Remove after DTS updated to protect these */
|
||||
#ifdef CONFIG_SDM_LPASSCC_845
|
||||
static struct clk_branch gcc_lpass_q6_axi_clk = {
|
||||
.halt_reg = 0x47000,
|
||||
.halt_check = BRANCH_HALT,
|
||||
.clkr = {
|
||||
.enable_reg = 0x47000,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_lpass_q6_axi_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch gcc_lpass_sway_clk = {
|
||||
.halt_reg = 0x47008,
|
||||
.halt_check = BRANCH_HALT,
|
||||
.clkr = {
|
||||
.enable_reg = 0x47008,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "gcc_lpass_sway_clk",
|
||||
.flags = CLK_IS_CRITICAL,
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct gdsc pcie_0_gdsc = {
|
||||
.gdscr = 0x6b004,
|
||||
.pd = {
|
||||
|
@ -3453,6 +3484,10 @@ static struct clk_regmap *gcc_sdm845_clocks[] = {
|
|||
[GCC_QSPI_CORE_CLK_SRC] = &gcc_qspi_core_clk_src.clkr,
|
||||
[GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr,
|
||||
[GCC_QSPI_CNOC_PERIPH_AHB_CLK] = &gcc_qspi_cnoc_periph_ahb_clk.clkr,
|
||||
#ifdef CONFIG_SDM_LPASSCC_845
|
||||
[GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.clkr,
|
||||
[GCC_LPASS_SWAY_CLK] = &gcc_lpass_sway_clk.clkr,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct qcom_reset_map gcc_sdm845_resets[] = {
|
||||
|
|
179
drivers/clk/qcom/lpasscc-sdm845.c
Normal file
179
drivers/clk/qcom/lpasscc-sdm845.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <dt-bindings/clock/qcom,lpass-sdm845.h>
|
||||
|
||||
#include "clk-regmap.h"
|
||||
#include "clk-branch.h"
|
||||
#include "common.h"
|
||||
|
||||
static struct clk_branch lpass_q6ss_ahbm_aon_clk = {
|
||||
.halt_reg = 0x12000,
|
||||
.halt_check = BRANCH_VOTED,
|
||||
.clkr = {
|
||||
.enable_reg = 0x12000,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_q6ss_ahbm_aon_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch lpass_q6ss_ahbs_aon_clk = {
|
||||
.halt_reg = 0x1f000,
|
||||
.halt_check = BRANCH_VOTED,
|
||||
.clkr = {
|
||||
.enable_reg = 0x1f000,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_q6ss_ahbs_aon_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch lpass_qdsp6ss_core_clk = {
|
||||
.halt_reg = 0x20,
|
||||
/* CLK_OFF would not toggle until LPASS is out of reset */
|
||||
.halt_check = BRANCH_HALT_SKIP,
|
||||
.clkr = {
|
||||
.enable_reg = 0x20,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_qdsp6ss_core_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch lpass_qdsp6ss_xo_clk = {
|
||||
.halt_reg = 0x38,
|
||||
/* CLK_OFF would not toggle until LPASS is out of reset */
|
||||
.halt_check = BRANCH_HALT_SKIP,
|
||||
.clkr = {
|
||||
.enable_reg = 0x38,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_qdsp6ss_xo_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct clk_branch lpass_qdsp6ss_sleep_clk = {
|
||||
.halt_reg = 0x3c,
|
||||
/* CLK_OFF would not toggle until LPASS is out of reset */
|
||||
.halt_check = BRANCH_HALT_SKIP,
|
||||
.clkr = {
|
||||
.enable_reg = 0x3c,
|
||||
.enable_mask = BIT(0),
|
||||
.hw.init = &(struct clk_init_data){
|
||||
.name = "lpass_qdsp6ss_sleep_clk",
|
||||
.ops = &clk_branch2_ops,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
static struct regmap_config lpass_regmap_config = {
|
||||
.reg_bits = 32,
|
||||
.reg_stride = 4,
|
||||
.val_bits = 32,
|
||||
.fast_io = true,
|
||||
};
|
||||
|
||||
static struct clk_regmap *lpass_cc_sdm845_clocks[] = {
|
||||
[LPASS_Q6SS_AHBM_AON_CLK] = &lpass_q6ss_ahbm_aon_clk.clkr,
|
||||
[LPASS_Q6SS_AHBS_AON_CLK] = &lpass_q6ss_ahbs_aon_clk.clkr,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc lpass_cc_sdm845_desc = {
|
||||
.config = &lpass_regmap_config,
|
||||
.clks = lpass_cc_sdm845_clocks,
|
||||
.num_clks = ARRAY_SIZE(lpass_cc_sdm845_clocks),
|
||||
};
|
||||
|
||||
static struct clk_regmap *lpass_qdsp6ss_sdm845_clocks[] = {
|
||||
[LPASS_QDSP6SS_XO_CLK] = &lpass_qdsp6ss_xo_clk.clkr,
|
||||
[LPASS_QDSP6SS_SLEEP_CLK] = &lpass_qdsp6ss_sleep_clk.clkr,
|
||||
[LPASS_QDSP6SS_CORE_CLK] = &lpass_qdsp6ss_core_clk.clkr,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = {
|
||||
.config = &lpass_regmap_config,
|
||||
.clks = lpass_qdsp6ss_sdm845_clocks,
|
||||
.num_clks = ARRAY_SIZE(lpass_qdsp6ss_sdm845_clocks),
|
||||
};
|
||||
|
||||
static int lpass_clocks_sdm845_probe(struct platform_device *pdev, int index,
|
||||
const struct qcom_cc_desc *desc)
|
||||
{
|
||||
struct regmap *regmap;
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
|
||||
base = devm_ioremap_resource(&pdev->dev, res);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
||||
regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config);
|
||||
if (IS_ERR(regmap))
|
||||
return PTR_ERR(regmap);
|
||||
|
||||
return qcom_cc_really_probe(pdev, desc, regmap);
|
||||
}
|
||||
|
||||
static int lpass_cc_sdm845_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct qcom_cc_desc *desc;
|
||||
int ret;
|
||||
|
||||
lpass_regmap_config.name = "cc";
|
||||
desc = &lpass_cc_sdm845_desc;
|
||||
|
||||
ret = lpass_clocks_sdm845_probe(pdev, 0, desc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
lpass_regmap_config.name = "qdsp6ss";
|
||||
desc = &lpass_qdsp6ss_sdm845_desc;
|
||||
|
||||
return lpass_clocks_sdm845_probe(pdev, 1, desc);
|
||||
}
|
||||
|
||||
static const struct of_device_id lpass_cc_sdm845_match_table[] = {
|
||||
{ .compatible = "qcom,sdm845-lpasscc" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, lpass_cc_sdm845_match_table);
|
||||
|
||||
static struct platform_driver lpass_cc_sdm845_driver = {
|
||||
.probe = lpass_cc_sdm845_probe,
|
||||
.driver = {
|
||||
.name = "sdm845-lpasscc",
|
||||
.of_match_table = lpass_cc_sdm845_match_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init lpass_cc_sdm845_init(void)
|
||||
{
|
||||
return platform_driver_register(&lpass_cc_sdm845_driver);
|
||||
}
|
||||
subsys_initcall(lpass_cc_sdm845_init);
|
||||
|
||||
static void __exit lpass_cc_sdm845_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&lpass_cc_sdm845_driver);
|
||||
}
|
||||
module_exit(lpass_cc_sdm845_exit);
|
||||
|
||||
MODULE_DESCRIPTION("QTI LPASS_CC SDM845 Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -197,6 +197,8 @@
|
|||
#define GCC_QSPI_CORE_CLK_SRC 187
|
||||
#define GCC_QSPI_CORE_CLK 188
|
||||
#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 189
|
||||
#define GCC_LPASS_Q6_AXI_CLK 190
|
||||
#define GCC_LPASS_SWAY_CLK 191
|
||||
|
||||
/* GCC Resets */
|
||||
#define GCC_MMSS_BCR 0
|
||||
|
|
15
include/dt-bindings/clock/qcom,lpass-sdm845.h
Normal file
15
include/dt-bindings/clock/qcom,lpass-sdm845.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2018, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DT_BINDINGS_CLK_SDM_LPASS_SDM845_H
|
||||
#define _DT_BINDINGS_CLK_SDM_LPASS_SDM845_H
|
||||
|
||||
#define LPASS_Q6SS_AHBM_AON_CLK 0
|
||||
#define LPASS_Q6SS_AHBS_AON_CLK 1
|
||||
#define LPASS_QDSP6SS_XO_CLK 2
|
||||
#define LPASS_QDSP6SS_SLEEP_CLK 3
|
||||
#define LPASS_QDSP6SS_CORE_CLK 4
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user