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.
|
part of the GCC/clock-controller node.
|
||||||
For more details on the TSENS properties please refer
|
For more details on the TSENS properties please refer
|
||||||
Documentation/devicetree/bindings/thermal/qcom-tsens.txt
|
Documentation/devicetree/bindings/thermal/qcom-tsens.txt
|
||||||
|
- protected-clocks : Protected clock specifier list as per common clock
|
||||||
|
binding.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
clock-controller@900000 {
|
clock-controller@900000 {
|
||||||
@ -55,3 +57,17 @@ Example of GCC with TSENS properties:
|
|||||||
#reset-cells = <1>;
|
#reset-cells = <1>;
|
||||||
#thermal-sensor-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
|
Say Y if you want to support display devices and functionality such as
|
||||||
splash screen.
|
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
|
config SPMI_PMIC_CLKDIV
|
||||||
tristate "SPMI PMIC clkdiv Support"
|
tristate "SPMI PMIC clkdiv Support"
|
||||||
depends on SPMI || COMPILE_TEST
|
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_660) += gcc-sdm660.o
|
||||||
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
|
obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
|
||||||
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-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_SDM_VIDEOCC_845) += videocc-sdm845.o
|
||||||
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
|
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
|
||||||
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.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 = {
|
static struct gdsc pcie_0_gdsc = {
|
||||||
.gdscr = 0x6b004,
|
.gdscr = 0x6b004,
|
||||||
.pd = {
|
.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_SRC] = &gcc_qspi_core_clk_src.clkr,
|
||||||
[GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr,
|
[GCC_QSPI_CORE_CLK] = &gcc_qspi_core_clk.clkr,
|
||||||
[GCC_QSPI_CNOC_PERIPH_AHB_CLK] = &gcc_qspi_cnoc_periph_ahb_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[] = {
|
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_SRC 187
|
||||||
#define GCC_QSPI_CORE_CLK 188
|
#define GCC_QSPI_CORE_CLK 188
|
||||||
#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 189
|
#define GCC_QSPI_CNOC_PERIPH_AHB_CLK 189
|
||||||
|
#define GCC_LPASS_Q6_AXI_CLK 190
|
||||||
|
#define GCC_LPASS_SWAY_CLK 191
|
||||||
|
|
||||||
/* GCC Resets */
|
/* GCC Resets */
|
||||||
#define GCC_MMSS_BCR 0
|
#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…
x
Reference in New Issue
Block a user