Merge branches 'clk-qcom', 'clk-mtk', 'clk-armada', 'clk-ingenic' and 'clk-meson' into clk-next

- Support qcom SM8150 RPMh clks
 - Set floor ops for qcom sd clks
 - Support qcom QCS404 WCSS clks
 - Support for Mediatek MT6779 SoCs
 - Add CPU clock support for Armada 7K/8K (specifically AP806 and AP807)

* clk-qcom:
  clk: qcom: rcg: Return failure for RCG update
  clk: qcom: fix QCS404 TuringCC regmap
  clk: qcom: clk-rpmh: Add support for SM8150
  dt-bindings: clock: Document SM8150 rpmh-clock compatible
  clk: qcom: clk-rpmh: Convert to parent data scheme
  dt-bindings: clock: Document the parent clocks
  clk: qcom: gcc: Use floor ops for SDCC clocks
  clk: qcom: gcc-qcs404: Use floor ops for sdcc clks
  clk: qcom: gcc-sdm845: Use floor ops for sdcc clks
  clk: qcom: define probe by index API as common API
  clk: qcom: Add WCSS gcc clock control for QCS404
  clk: qcom: msm8916: Don't build by default
  clk: qcom: gcc: Add global clock controller driver for SM8150
  dt-bindings: clock: Document gcc bindings for SM8150
  clk: qcom: clk-alpha-pll: Add support for Trion PLLs
  clk: qcom: clk-alpha-pll: Remove post_div_table checks
  clk: qcom: clk-alpha-pll: Remove unnecessary cast

* clk-mtk:
  clk: mediatek: Runtime PM support for MT8183 mcucfg clock provider
  clk: mediatek: Register clock gate with device
  clk: mediatek: add pericfg clocks for MT8183
  dt-bindings: clock: mediatek: add pericfg for MT8183
  clk: mediatek: Add MT6779 clock support
  clk: mediatek: Add dt-bindings for MT6779 clocks
  dt-bindings: mediatek: bindings for MT6779 clk
  clk: reset: Modify reset-controller driver

* clk-armada:
  clk: mvebu: ap80x: add AP807 clock support
  clk: mvebu: ap806: Prepare the introduction of AP807 clock support
  clk: mvebu: ap806: add AP-DCLK (hclk) to system controller driver
  clk: mvebu: ap806: be more explicit on what SaR is
  clk: mvebu: ap80x-cpu: add AP807 CPU clock support
  clk: mvebu: ap806-cpu: prepare mapping of AP807 CPU clock
  dt-bindings: ap806: Document AP807 clock compatible
  dt-bindings: ap80x: Document AP807 CPU clock compatible
  clk: mvebu: ap806: Fix clock name for the cluster
  clk: mvebu: add CPU clock driver for Armada 7K/8K
  clk: mvebu: add helper file for Armada AP and CP clocks
  dt-bindings: ap806: add the cluster clock node in the syscon file

* clk-ingenic:
  clk: ingenic: Use CLK_OF_DECLARE_DRIVER macro
  clk: ingenic/jz4740: Fix "pll half" divider not read/written properly

* clk-meson: (23 commits)
  clk: meson: g12a: add support for SM1 CPU 1, 2 & 3 clocks
  clk: meson: g12a: add support for SM1 DynamIQ Shared Unit clock
  clk: meson: g12a: add support for SM1 GP1 PLL
  dt-bindings: clk: meson: add sm1 periph clock controller bindings
  clk: meson: axg-audio: add g12a reset support
  dt-bindings: clock: meson: add resets to the audio clock controller
  clk: meson: g12a: expose CPUB clock ID for G12B
  clk: meson: g12a: add notifiers to handle cpu clock change
  clk: meson: add g12a cpu dynamic divider driver
  clk: core: introduce clk_hw_set_parent()
  clk: meson: remove clk input helper
  clk: meson: remove ee input bypass clocks
  clk: meson: clk-regmap: migrate to new parent description method
  clk: meson: meson8b: migrate to the new parent description method
  clk: meson: axg: migrate to the new parent description method
  clk: meson: gxbb: migrate to the new parent description method
  clk: meson: g12a: migrate to the new parent description method
  clk: meson: remove ao input bypass clocks
  clk: meson: axg-aoclk: migrate to the new parent description method
  clk: meson: gxbb-aoclk: migrate to the new parent description method
  ...
This commit is contained in:
Stephen Boyd
2019-09-19 15:30:59 -07:00
92 changed files with 11071 additions and 1725 deletions

View File

@@ -2489,6 +2489,12 @@ runtime_put:
return ret;
}
int clk_hw_set_parent(struct clk_hw *hw, struct clk_hw *parent)
{
return clk_core_set_parent_nolock(hw->core, parent->core);
}
EXPORT_SYMBOL_GPL(clk_hw_set_parent);
/**
* clk_set_parent - switch the parent of a mux clk
* @clk: the mux clk whose input we are switching

View File

@@ -257,4 +257,4 @@ static void __init jz4725b_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);

View File

@@ -53,6 +53,10 @@ static const u8 jz4740_cgu_cpccr_div_table[] = {
1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
};
static const u8 jz4740_cgu_pll_half_div_table[] = {
2, 1,
};
static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
/* External clocks */
@@ -86,7 +90,10 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
[JZ4740_CLK_PLL_HALF] = {
"pll half", CGU_CLK_DIV,
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 },
.div = {
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
jz4740_cgu_pll_half_div_table,
},
},
[JZ4740_CLK_CCLK] = {
@@ -241,4 +248,4 @@ static void __init jz4740_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);

View File

@@ -443,4 +443,4 @@ static void __init jz4770_cgu_init(struct device_node *np)
}
/* We only probe via devicetree, no need for a platform driver */
CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);

View File

@@ -725,4 +725,4 @@ static void __init jz4780_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);

View File

@@ -117,6 +117,62 @@ config COMMON_CLK_MT2712_VENCSYS
---help---
This driver supports MediaTek MT2712 vencsys clocks.
config COMMON_CLK_MT6779
bool "Clock driver for MediaTek MT6779"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
help
This driver supports MediaTek MT6779 basic clocks.
config COMMON_CLK_MT6779_MMSYS
bool "Clock driver for MediaTek MT6779 mmsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 mmsys clocks.
config COMMON_CLK_MT6779_IMGSYS
bool "Clock driver for MediaTek MT6779 imgsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 imgsys clocks.
config COMMON_CLK_MT6779_IPESYS
bool "Clock driver for MediaTek MT6779 ipesys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 ipesys clocks.
config COMMON_CLK_MT6779_CAMSYS
bool "Clock driver for MediaTek MT6779 camsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 camsys clocks.
config COMMON_CLK_MT6779_VDECSYS
bool "Clock driver for MediaTek MT6779 vdecsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 vdecsys clocks.
config COMMON_CLK_MT6779_VENCSYS
bool "Clock driver for MediaTek MT6779 vencsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 vencsys clocks.
config COMMON_CLK_MT6779_MFGCFG
bool "Clock driver for MediaTek MT6779 mfgcfg"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 mfgcfg clocks.
config COMMON_CLK_MT6779_AUDSYS
bool "Clock driver for Mediatek MT6779 audsys"
depends on COMMON_CLK_MT6779
help
This driver supports Mediatek MT6779 audsys clocks.
config COMMON_CLK_MT6797
bool "Clock driver for MediaTek MT6797"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST

View File

@@ -1,6 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
obj-$(CONFIG_COMMON_CLK_MT6779) += clk-mt6779.o
obj-$(CONFIG_COMMON_CLK_MT6779_MMSYS) += clk-mt6779-mm.o
obj-$(CONFIG_COMMON_CLK_MT6779_IMGSYS) += clk-mt6779-img.o
obj-$(CONFIG_COMMON_CLK_MT6779_IPESYS) += clk-mt6779-ipe.o
obj-$(CONFIG_COMMON_CLK_MT6779_CAMSYS) += clk-mt6779-cam.o
obj-$(CONFIG_COMMON_CLK_MT6779_VDECSYS) += clk-mt6779-vdec.o
obj-$(CONFIG_COMMON_CLK_MT6779_VENCSYS) += clk-mt6779-venc.o
obj-$(CONFIG_COMMON_CLK_MT6779_MFGCFG) += clk-mt6779-mfg.o
obj-$(CONFIG_COMMON_CLK_MT6779_AUDSYS) += clk-mt6779-aud.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o

View File

@@ -150,7 +150,8 @@ struct clk *mtk_clk_register_gate(
int sta_ofs,
u8 bit,
const struct clk_ops *ops,
unsigned long flags)
unsigned long flags,
struct device *dev)
{
struct mtk_clk_gate *cg;
struct clk *clk;
@@ -174,7 +175,7 @@ struct clk *mtk_clk_register_gate(
cg->hw.init = &init;
clk = clk_register(NULL, &cg->hw);
clk = clk_register(dev, &cg->hw);
if (IS_ERR(clk))
kfree(cg);

View File

@@ -40,7 +40,8 @@ struct clk *mtk_clk_register_gate(
int sta_ofs,
u8 bit,
const struct clk_ops *ops,
unsigned long flags);
unsigned long flags,
struct device *dev);
#define GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, \
_ops, _flags) { \

View File

@@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs audio0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs audio1_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x4,
.sta_ofs = 0x4,
};
#define GATE_AUDIO0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr)
#define GATE_AUDIO1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr)
static const struct mtk_gate audio_clks[] = {
/* AUDIO0 */
GATE_AUDIO0(CLK_AUD_AFE, "aud_afe", "audio_sel", 2),
GATE_AUDIO0(CLK_AUD_22M, "aud_22m", "aud_eng1_sel", 8),
GATE_AUDIO0(CLK_AUD_24M, "aud_24m", "aud_eng2_sel", 9),
GATE_AUDIO0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner",
"aud_eng2_sel", 18),
GATE_AUDIO0(CLK_AUD_APLL_TUNER, "aud_apll_tuner",
"aud_eng1_sel", 19),
GATE_AUDIO0(CLK_AUD_TDM, "aud_tdm", "aud_eng1_sel", 20),
GATE_AUDIO0(CLK_AUD_ADC, "aud_adc", "audio_sel", 24),
GATE_AUDIO0(CLK_AUD_DAC, "aud_dac", "audio_sel", 25),
GATE_AUDIO0(CLK_AUD_DAC_PREDIS, "aud_dac_predis",
"audio_sel", 26),
GATE_AUDIO0(CLK_AUD_TML, "aud_tml", "audio_sel", 27),
GATE_AUDIO0(CLK_AUD_NLE, "aud_nle", "audio_sel", 28),
/* AUDIO1 */
GATE_AUDIO1(CLK_AUD_I2S1_BCLK_SW, "aud_i2s1_bclk",
"audio_sel", 4),
GATE_AUDIO1(CLK_AUD_I2S2_BCLK_SW, "aud_i2s2_bclk",
"audio_sel", 5),
GATE_AUDIO1(CLK_AUD_I2S3_BCLK_SW, "aud_i2s3_bclk",
"audio_sel", 6),
GATE_AUDIO1(CLK_AUD_I2S4_BCLK_SW, "aud_i2s4_bclk",
"audio_sel", 7),
GATE_AUDIO1(CLK_AUD_I2S5_BCLK_SW, "aud_i2s5_bclk",
"audio_sel", 8),
GATE_AUDIO1(CLK_AUD_CONN_I2S_ASRC, "aud_conn_i2s",
"audio_sel", 12),
GATE_AUDIO1(CLK_AUD_GENERAL1_ASRC, "aud_general1",
"audio_sel", 13),
GATE_AUDIO1(CLK_AUD_GENERAL2_ASRC, "aud_general2",
"audio_sel", 14),
GATE_AUDIO1(CLK_AUD_DAC_HIRES, "aud_dac_hires",
"audio_h_sel", 15),
GATE_AUDIO1(CLK_AUD_ADC_HIRES, "aud_adc_hires",
"audio_h_sel", 16),
GATE_AUDIO1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml",
"audio_h_sel", 17),
GATE_AUDIO1(CLK_AUD_PDN_ADDA6_ADC, "aud_pdn_adda6_adc",
"audio_sel", 20),
GATE_AUDIO1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires",
"audio_h_sel",
21),
GATE_AUDIO1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "audio_sel",
28),
GATE_AUDIO1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis",
"audio_sel", 29),
GATE_AUDIO1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml",
"audio_sel", 30),
GATE_AUDIO1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires",
"audio_h_sel", 31),
};
static const struct of_device_id of_match_clk_mt6779_aud[] = {
{ .compatible = "mediatek,mt6779-audio", },
{}
};
static int clk_mt6779_aud_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK);
mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_aud_drv = {
.probe = clk_mt6779_aud_probe,
.driver = {
.name = "clk-mt6779-aud",
.of_match_table = of_match_clk_mt6779_aud,
},
};
builtin_platform_driver(clk_mt6779_aud_drv);

View File

@@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs cam_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_CAM(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate cam_clks[] = {
GATE_CAM(CLK_CAM_LARB10, "camsys_larb10", "cam_sel", 0),
GATE_CAM(CLK_CAM_DFP_VAD, "camsys_dfp_vad", "cam_sel", 1),
GATE_CAM(CLK_CAM_LARB11, "camsys_larb11", "cam_sel", 2),
GATE_CAM(CLK_CAM_LARB9, "camsys_larb9", "cam_sel", 3),
GATE_CAM(CLK_CAM_CAM, "camsys_cam", "cam_sel", 6),
GATE_CAM(CLK_CAM_CAMTG, "camsys_camtg", "cam_sel", 7),
GATE_CAM(CLK_CAM_SENINF, "camsys_seninf", "cam_sel", 8),
GATE_CAM(CLK_CAM_CAMSV0, "camsys_camsv0", "cam_sel", 9),
GATE_CAM(CLK_CAM_CAMSV1, "camsys_camsv1", "cam_sel", 10),
GATE_CAM(CLK_CAM_CAMSV2, "camsys_camsv2", "cam_sel", 11),
GATE_CAM(CLK_CAM_CAMSV3, "camsys_camsv3", "cam_sel", 12),
GATE_CAM(CLK_CAM_CCU, "camsys_ccu", "cam_sel", 13),
GATE_CAM(CLK_CAM_FAKE_ENG, "camsys_fake_eng", "cam_sel", 14),
};
static const struct of_device_id of_match_clk_mt6779_cam[] = {
{ .compatible = "mediatek,mt6779-camsys", },
{}
};
static int clk_mt6779_cam_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK);
mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_cam_drv = {
.probe = clk_mt6779_cam_probe,
.driver = {
.name = "clk-mt6779-cam",
.of_match_table = of_match_clk_mt6779_cam,
},
};
builtin_platform_driver(clk_mt6779_cam_drv);

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs img_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_IMG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate img_clks[] = {
GATE_IMG(CLK_IMG_LARB5, "imgsys_larb5", "img_sel", 0),
GATE_IMG(CLK_IMG_LARB6, "imgsys_larb6", "img_sel", 1),
GATE_IMG(CLK_IMG_DIP, "imgsys_dip", "img_sel", 2),
GATE_IMG(CLK_IMG_MFB, "imgsys_mfb", "img_sel", 6),
GATE_IMG(CLK_IMG_WPE_A, "imgsys_wpe_a", "img_sel", 7),
};
static const struct of_device_id of_match_clk_mt6779_img[] = {
{ .compatible = "mediatek,mt6779-imgsys", },
{}
};
static int clk_mt6779_img_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_img_drv = {
.probe = clk_mt6779_img_probe,
.driver = {
.name = "clk-mt6779-img",
.of_match_table = of_match_clk_mt6779_img,
},
};
builtin_platform_driver(clk_mt6779_img_drv);

View File

@@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs ipe_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_IPE(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate ipe_clks[] = {
GATE_IPE(CLK_IPE_LARB7, "ipe_larb7", "ipe_sel", 0),
GATE_IPE(CLK_IPE_LARB8, "ipe_larb8", "ipe_sel", 1),
GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "ipe_sel", 2),
GATE_IPE(CLK_IPE_FD, "ipe_fd", "ipe_sel", 3),
GATE_IPE(CLK_IPE_FE, "ipe_fe", "ipe_sel", 4),
GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "ipe_sel", 5),
GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "ipe_sel", 6),
};
static const struct of_device_id of_match_clk_mt6779_ipe[] = {
{ .compatible = "mediatek,mt6779-ipesys", },
{}
};
static int clk_mt6779_ipe_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IPE_NR_CLK);
mtk_clk_register_gates(node, ipe_clks, ARRAY_SIZE(ipe_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_ipe_drv = {
.probe = clk_mt6779_ipe_probe,
.driver = {
.name = "clk-mt6779-ipe",
.of_match_table = of_match_clk_mt6779_ipe,
},
};
builtin_platform_driver(clk_mt6779_ipe_drv);

View File

@@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs mfg_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_MFG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate mfg_clks[] = {
GATE_MFG(CLK_MFGCFG_BG3D, "mfg_bg3d", "mfg_sel", 0),
};
static int clk_mt6779_mfg_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MFGCFG_NR_CLK);
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static const struct of_device_id of_match_clk_mt6779_mfg[] = {
{ .compatible = "mediatek,mt6779-mfgcfg", },
{}
};
static struct platform_driver clk_mt6779_mfg_drv = {
.probe = clk_mt6779_mfg_probe,
.driver = {
.name = "clk-mt6779-mfg",
.of_match_table = of_match_clk_mt6779_mfg,
},
};
builtin_platform_driver(clk_mt6779_mfg_drv);

View File

@@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs mm0_cg_regs = {
.set_ofs = 0x0104,
.clr_ofs = 0x0108,
.sta_ofs = 0x0100,
};
static const struct mtk_gate_regs mm1_cg_regs = {
.set_ofs = 0x0114,
.clr_ofs = 0x0118,
.sta_ofs = 0x0110,
};
#define GATE_MM0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
#define GATE_MM1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate mm_clks[] = {
/* MM0 */
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
GATE_MM0(CLK_MM_SMI_LARB1, "mm_smi_larb1", "mm_sel", 2),
GATE_MM0(CLK_MM_GALS_COMM0, "mm_gals_comm0", "mm_sel", 3),
GATE_MM0(CLK_MM_GALS_COMM1, "mm_gals_comm1", "mm_sel", 4),
GATE_MM0(CLK_MM_GALS_CCU2MM, "mm_gals_ccu2mm", "mm_sel", 5),
GATE_MM0(CLK_MM_GALS_IPU12MM, "mm_gals_ipu12mm", "mm_sel", 6),
GATE_MM0(CLK_MM_GALS_IMG2MM, "mm_gals_img2mm", "mm_sel", 7),
GATE_MM0(CLK_MM_GALS_CAM2MM, "mm_gals_cam2mm", "mm_sel", 8),
GATE_MM0(CLK_MM_GALS_IPU2MM, "mm_gals_ipu2mm", "mm_sel", 9),
GATE_MM0(CLK_MM_MDP_DL_TXCK, "mm_mdp_dl_txck", "mm_sel", 10),
GATE_MM0(CLK_MM_IPU_DL_TXCK, "mm_ipu_dl_txck", "mm_sel", 11),
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 12),
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 13),
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 14),
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 15),
GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 16),
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 17),
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 18),
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 19),
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 20),
GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 21),
GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 22),
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 23),
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 24),
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 25),
GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 26),
GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 27),
GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 28),
GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 29),
GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 30),
GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
/* MM1 */
GATE_MM1(CLK_MM_DSI0_MM_CK, "mm_dsi0_mmck", "mm_sel", 0),
GATE_MM1(CLK_MM_DSI0_IF_CK, "mm_dsi0_ifck", "mm_sel", 1),
GATE_MM1(CLK_MM_DPI_MM_CK, "mm_dpi_mmck", "mm_sel", 2),
GATE_MM1(CLK_MM_DPI_IF_CK, "mm_dpi_ifck", "dpi0_sel", 3),
GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 4),
GATE_MM1(CLK_MM_MDP_DL_RX_CK, "mm_mdp_dl_rxck", "mm_sel", 5),
GATE_MM1(CLK_MM_IPU_DL_RX_CK, "mm_ipu_dl_rxck", "mm_sel", 6),
GATE_MM1(CLK_MM_26M, "mm_26m", "f_f26m_ck", 7),
GATE_MM1(CLK_MM_MM_R2Y, "mm_mmsys_r2y", "mm_sel", 8),
GATE_MM1(CLK_MM_DISP_RSZ, "mm_disp_rsz", "mm_sel", 9),
GATE_MM1(CLK_MM_MDP_AAL, "mm_mdp_aal", "mm_sel", 10),
GATE_MM1(CLK_MM_MDP_HDR, "mm_mdp_hdr", "mm_sel", 11),
GATE_MM1(CLK_MM_DBI_MM_CK, "mm_dbi_mmck", "mm_sel", 12),
GATE_MM1(CLK_MM_DBI_IF_CK, "mm_dbi_ifck", "dpi0_sel", 13),
GATE_MM1(CLK_MM_DISP_POSTMASK0, "mm_disp_pm0", "mm_sel", 14),
GATE_MM1(CLK_MM_DISP_HRT_BW, "mm_disp_hrt_bw", "mm_sel", 15),
GATE_MM1(CLK_MM_DISP_OVL_FBDC, "mm_disp_ovl_fbdc", "mm_sel", 16),
};
static const struct of_device_id of_match_clk_mt6779_mm[] = {
{ .compatible = "mediatek,mt6779-mmsys", },
{}
};
static int clk_mt6779_mm_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_mm_drv = {
.probe = clk_mt6779_mm_probe,
.driver = {
.name = "clk-mt6779-mm",
.of_match_table = of_match_clk_mt6779_mm,
},
};
builtin_platform_driver(clk_mt6779_mm_drv);

View File

@@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs vdec0_cg_regs = {
.set_ofs = 0x0000,
.clr_ofs = 0x0004,
.sta_ofs = 0x0000,
};
static const struct mtk_gate_regs vdec1_cg_regs = {
.set_ofs = 0x0008,
.clr_ofs = 0x000c,
.sta_ofs = 0x0008,
};
#define GATE_VDEC0_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
#define GATE_VDEC1_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate vdec_clks[] = {
/* VDEC0 */
GATE_VDEC0_I(CLK_VDEC_VDEC, "vdec_cken", "vdec_sel", 0),
/* VDEC1 */
GATE_VDEC1_I(CLK_VDEC_LARB1, "vdec_larb1_cken", "vdec_sel", 0),
};
static const struct of_device_id of_match_clk_mt6779_vdec[] = {
{ .compatible = "mediatek,mt6779-vdecsys", },
{}
};
static int clk_mt6779_vdec_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VDEC_GCON_NR_CLK);
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_vdec_drv = {
.probe = clk_mt6779_vdec_probe,
.driver = {
.name = "clk-mt6779-vdec",
.of_match_table = of_match_clk_mt6779_vdec,
},
};
builtin_platform_driver(clk_mt6779_vdec_drv);

View File

@@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs venc_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_VENC_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate venc_clks[] = {
GATE_VENC_I(CLK_VENC_GCON_LARB, "venc_larb", "venc_sel", 0),
GATE_VENC_I(CLK_VENC_GCON_VENC, "venc_venc", "venc_sel", 4),
GATE_VENC_I(CLK_VENC_GCON_JPGENC, "venc_jpgenc", "venc_sel", 8),
GATE_VENC_I(CLK_VENC_GCON_GALS, "venc_gals", "venc_sel", 28),
};
static const struct of_device_id of_match_clk_mt6779_venc[] = {
{ .compatible = "mediatek,mt6779-vencsys", },
{}
};
static int clk_mt6779_venc_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VENC_GCON_NR_CLK);
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_venc_drv = {
.probe = clk_mt6779_venc_probe,
.driver = {
.name = "clk-mt6779-venc",
.of_match_table = of_match_clk_mt6779_venc,
},
};
builtin_platform_driver(clk_mt6779_venc_drv);

File diff suppressed because it is too large Load Diff

View File

@@ -5,6 +5,7 @@
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include "clk-mtk.h"
#include "clk-gate.h"
@@ -30,10 +31,12 @@ static int clk_mt8183_mfg_probe(struct platform_device *pdev)
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
pm_runtime_enable(&pdev->dev);
clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data);
mtk_clk_register_gates_with_dev(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data, &pdev->dev);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}

View File

@@ -17,6 +17,9 @@
#include <dt-bindings/clock/mt8183-clk.h>
/* Infra global controller reset set register */
#define INFRA_RST0_SET_OFFSET 0x120
static DEFINE_SPINLOCK(mt8183_clk_lock);
static const struct mtk_fixed_clk top_fixed_clks[] = {
@@ -999,6 +1002,20 @@ static const struct mtk_gate infra_clks[] = {
"msdc50_0_sel", 24),
};
static const struct mtk_gate_regs peri_cg_regs = {
.set_ofs = 0x20c,
.clr_ofs = 0x20c,
.sta_ofs = 0x20c,
};
#define GATE_PERI(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &peri_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr_inv)
static const struct mtk_gate peri_clks[] = {
GATE_PERI(CLK_PERI_AXI, "peri_axi", "axi_sel", 31),
};
static const struct mtk_gate_regs apmixed_cg_regs = {
.set_ofs = 0x20,
.clr_ofs = 0x20,
@@ -1185,12 +1202,36 @@ static int clk_mt8183_infra_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
dev_err(&pdev->dev,
"%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
mtk_register_reset_controller_set_clr(node, 4, INFRA_RST0_SET_OFFSET);
return r;
}
static int clk_mt8183_peri_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
@@ -1223,6 +1264,9 @@ static const struct of_device_id of_match_clk_mt8183[] = {
}, {
.compatible = "mediatek,mt8183-infracfg",
.data = clk_mt8183_infra_probe,
}, {
.compatible = "mediatek,mt8183-pericfg",
.data = clk_mt8183_peri_probe,
}, {
.compatible = "mediatek,mt8183-mcucfg",
.data = clk_mt8183_mcu_probe,

View File

@@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/clkdev.h>
#include <linux/mfd/syscon.h>
#include <linux/device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
@@ -93,9 +94,10 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
}
}
int mtk_clk_register_gates(struct device_node *node,
int mtk_clk_register_gates_with_dev(struct device_node *node,
const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data)
int num, struct clk_onecell_data *clk_data,
struct device *dev)
{
int i;
struct clk *clk;
@@ -122,7 +124,7 @@ int mtk_clk_register_gates(struct device_node *node,
gate->regs->set_ofs,
gate->regs->clr_ofs,
gate->regs->sta_ofs,
gate->shift, gate->ops, gate->flags);
gate->shift, gate->ops, gate->flags, dev);
if (IS_ERR(clk)) {
pr_err("Failed to register clk %s: %ld\n",
@@ -136,6 +138,14 @@ int mtk_clk_register_gates(struct device_node *node,
return 0;
}
int mtk_clk_register_gates(struct device_node *node,
const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data)
{
return mtk_clk_register_gates_with_dev(node,
clks, num, clk_data, NULL);
}
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
void __iomem *base, spinlock_t *lock)
{

View File

@@ -169,6 +169,11 @@ int mtk_clk_register_gates(struct device_node *node,
const struct mtk_gate *clks, int num,
struct clk_onecell_data *clk_data);
int mtk_clk_register_gates_with_dev(struct device_node *node,
const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data,
struct device *dev);
struct mtk_clk_divider {
int id;
const char *name;
@@ -240,4 +245,7 @@ struct clk *mtk_clk_register_ref2usb_tx(const char *name,
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs);
void mtk_register_reset_controller_set_clr(struct device_node *np,
unsigned int num_regs, int regofs);
#endif /* __DRV_CLK_MTK_H */

View File

@@ -19,6 +19,24 @@ struct mtk_reset {
struct reset_controller_dev rcdev;
};
static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
unsigned int reg = data->regofs + ((id / 32) << 4);
return regmap_write(data->regmap, reg, 1);
}
static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4;
return regmap_write(data->regmap, reg, 1);
}
static int mtk_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
@@ -49,14 +67,32 @@ static int mtk_reset(struct reset_controller_dev *rcdev,
return mtk_reset_deassert(rcdev, id);
}
static int mtk_reset_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
int ret;
ret = mtk_reset_assert_set_clr(rcdev, id);
if (ret)
return ret;
return mtk_reset_deassert_set_clr(rcdev, id);
}
static const struct reset_control_ops mtk_reset_ops = {
.assert = mtk_reset_assert,
.deassert = mtk_reset_deassert,
.reset = mtk_reset,
};
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs)
static const struct reset_control_ops mtk_reset_ops_set_clr = {
.assert = mtk_reset_assert_set_clr,
.deassert = mtk_reset_deassert_set_clr,
.reset = mtk_reset_set_clr,
};
static void mtk_register_reset_controller_common(struct device_node *np,
unsigned int num_regs, int regofs,
const struct reset_control_ops *reset_ops)
{
struct mtk_reset *data;
int ret;
@@ -77,7 +113,7 @@ void mtk_register_reset_controller(struct device_node *np,
data->regofs = regofs;
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = num_regs * 32;
data->rcdev.ops = &mtk_reset_ops;
data->rcdev.ops = reset_ops;
data->rcdev.of_node = np;
ret = reset_controller_register(&data->rcdev);
@@ -87,3 +123,17 @@ void mtk_register_reset_controller(struct device_node *np,
return;
}
}
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs)
{
mtk_register_reset_controller_common(np, num_regs, regofs,
&mtk_reset_ops);
}
void mtk_register_reset_controller_set_clr(struct device_node *np,
unsigned int num_regs, int regofs)
{
mtk_register_reset_controller_common(np, num_regs, regofs,
&mtk_reset_ops_set_clr);
}

View File

@@ -1,7 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
config COMMON_CLK_MESON_INPUT
tristate
config COMMON_CLK_MESON_REGMAP
tristate
select REGMAP
@@ -33,13 +30,15 @@ config COMMON_CLK_MESON_VID_PLL_DIV
config COMMON_CLK_MESON_AO_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_INPUT
select RESET_CONTROLLER
config COMMON_CLK_MESON_EE_CLKC
tristate
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_INPUT
config COMMON_CLK_MESON_CPU_DYNDIV
tristate
select COMMON_CLK_MESON_REGMAP
config COMMON_CLK_MESON8B
bool
@@ -86,7 +85,6 @@ config COMMON_CLK_AXG
config COMMON_CLK_AXG_AUDIO
tristate "Meson AXG Audio Clock Controller Driver"
depends on ARCH_MESON
select COMMON_CLK_MESON_INPUT
select COMMON_CLK_MESON_REGMAP
select COMMON_CLK_MESON_PHASE
select COMMON_CLK_MESON_SCLK_DIV
@@ -104,6 +102,7 @@ config COMMON_CLK_G12A
select COMMON_CLK_MESON_PLL
select COMMON_CLK_MESON_AO_CLKC
select COMMON_CLK_MESON_EE_CLKC
select COMMON_CLK_MESON_CPU_DYNDIV
select MFD_SYSCON
help
Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2

View File

@@ -2,9 +2,9 @@
# Amlogic clock drivers
obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o
obj-$(CONFIG_COMMON_CLK_MESON_CPU_DYNDIV) += clk-cpu-dyndiv.o
obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o
obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o
obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o

View File

@@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@@ -42,7 +40,9 @@ static struct clk_regmap axg_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "axg_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -64,7 +64,9 @@ static struct clk_regmap axg_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -77,7 +79,9 @@ static struct clk_regmap axg_aoclk_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@@ -124,7 +128,9 @@ static struct clk_regmap axg_aoclk_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "axg_ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_pre.hw
},
.num_parents = 1,
},
};
@@ -139,8 +145,10 @@ static struct clk_regmap axg_aoclk_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "axg_ao_32k_div",
"axg_ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_div.hw,
&axg_aoclk_32k_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -154,7 +162,9 @@ static struct clk_regmap axg_aoclk_32k = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_32k",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "axg_ao_32k_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_32k_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -170,8 +180,10 @@ static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "axg_ao_32k",
IN_PREFIX "ext_32k-0" },
.parent_data = (const struct clk_parent_data []) {
{ .hw = &axg_aoclk_32k.hw },
{ .fw_name = "ext_32k-0", },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -187,8 +199,10 @@ static struct clk_regmap axg_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"axg_ao_cts_rtc_oscin"},
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &axg_aoclk_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -203,8 +217,10 @@ static struct clk_regmap axg_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal",
"axg_ao_clk81" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &axg_aoclk_clk81.hw },
},
.num_parents = 2,
},
};
@@ -218,7 +234,9 @@ static struct clk_regmap axg_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "axg_ao_saradc_mux" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_saradc_mux.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -232,7 +250,9 @@ static struct clk_regmap axg_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "axg_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "axg_ao_saradc_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_aoclk_saradc_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -290,12 +310,6 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input axg_aoclk_inputs[] = {
{ .name = "xtal", .required = true },
{ .name = "mpeg-clk", .required = true },
{ .name = "ext-32k-0", .required = false },
};
static const struct meson_aoclk_data axg_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(axg_aoclk_reset),
@@ -303,9 +317,6 @@ static const struct meson_aoclk_data axg_aoclkc_data = {
.num_clks = ARRAY_SIZE(axg_aoclk_regmap),
.clks = axg_aoclk_regmap,
.hw_data = &axg_aoclk_onecell_data,
.inputs = axg_aoclk_inputs,
.num_inputs = ARRAY_SIZE(axg_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id axg_aoclkc_match_table[] = {

View File

@@ -12,10 +12,10 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "axg-audio.h"
#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-phase.h"
#include "sclk-div.h"
@@ -24,7 +24,7 @@
#define AUD_SLV_SCLK_COUNT 10
#define AUD_SLV_LRCLK_COUNT 10
#define AUD_GATE(_name, _reg, _bit, _pname, _iflags) \
#define AUD_GATE(_name, _reg, _bit, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@@ -33,13 +33,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pnames, _iflags) \
#define AUD_MUX(_name, _reg, _mask, _shift, _dflags, _pdata, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_mux_data){ \
.offset = (_reg), \
@@ -50,13 +50,13 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_mux_ops, \
.parent_names = (_pnames), \
.num_parents = ARRAY_SIZE(_pnames), \
.parent_data = _pdata, \
.num_parents = ARRAY_SIZE(_pdata), \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
}
#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _pname, _iflags) \
#define AUD_DIV(_name, _reg, _shift, _width, _dflags, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_div_data){ \
.offset = (_reg), \
@@ -67,15 +67,27 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data){ \
.name = "aud_"#_name, \
.ops = &clk_regmap_divider_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
}
#define AUD_PCLK_GATE(_name, _bit) \
AUD_GATE(_name, AUDIO_CLK_GATE_EN, _bit, "audio_pclk", 0)
struct clk_regmap aud_##_name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (AUDIO_CLK_GATE_EN), \
.bit_idx = (_bit), \
}, \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &clk_regmap_gate_ops, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "pclk", \
}, \
.num_parents = 1, \
}, \
}
/* Audio peripheral clocks */
static AUD_PCLK_GATE(ddr_arb, 0);
static AUD_PCLK_GATE(pdm, 1);
@@ -100,14 +112,20 @@ static AUD_PCLK_GATE(power_detect, 19);
static AUD_PCLK_GATE(spdifout_b, 21);
/* Audio Master Clocks */
static const char * const mst_mux_parent_names[] = {
"aud_mst_in0", "aud_mst_in1", "aud_mst_in2", "aud_mst_in3",
"aud_mst_in4", "aud_mst_in5", "aud_mst_in6", "aud_mst_in7",
static const struct clk_parent_data mst_mux_parent_data[] = {
{ .fw_name = "mst_in0", },
{ .fw_name = "mst_in1", },
{ .fw_name = "mst_in2", },
{ .fw_name = "mst_in3", },
{ .fw_name = "mst_in4", },
{ .fw_name = "mst_in5", },
{ .fw_name = "mst_in6", },
{ .fw_name = "mst_in7", },
};
#define AUD_MST_MUX(_name, _reg, _flag) \
AUD_MUX(_name##_sel, _reg, 0x7, 24, _flag, \
mst_mux_parent_names, CLK_SET_RATE_PARENT)
mst_mux_parent_data, 0)
#define AUD_MST_MCLK_MUX(_name, _reg) \
AUD_MST_MUX(_name, _reg, CLK_MUX_ROUND_CLOSEST)
@@ -129,7 +147,7 @@ static AUD_MST_MCLK_MUX(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_DIV(_name, _reg, _flag) \
AUD_DIV(_name##_div, _reg, 0, 16, _flag, \
"aud_"#_name"_sel", CLK_SET_RATE_PARENT) \
aud_##_name##_sel, CLK_SET_RATE_PARENT) \
#define AUD_MST_MCLK_DIV(_name, _reg) \
AUD_MST_DIV(_name, _reg, CLK_DIVIDER_ROUND_CLOSEST)
@@ -150,7 +168,7 @@ static AUD_MST_SYS_DIV(pdm_sysclk, AUDIO_CLK_PDMIN_CTRL1);
static AUD_MST_MCLK_DIV(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
#define AUD_MST_MCLK_GATE(_name, _reg) \
AUD_GATE(_name, _reg, 31, "aud_"#_name"_div", \
AUD_GATE(_name, _reg, 31, aud_##_name##_div, \
CLK_SET_RATE_PARENT)
static AUD_MST_MCLK_GATE(mst_a_mclk, AUDIO_MCLK_A_CTRL);
@@ -168,7 +186,7 @@ static AUD_MST_MCLK_GATE(spdifout_b_clk, AUDIO_CLK_SPDIFOUT_B_CTRL);
/* Sample Clocks */
#define AUD_MST_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(mst_##_name##_sclk_pre_en, _reg, 31, \
"aud_mst_"#_name"_mclk", 0)
aud_mst_##_name##_mclk, 0)
static AUD_MST_SCLK_PRE_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -178,7 +196,7 @@ static AUD_MST_SCLK_PRE_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_PRE_EN(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_SCLK_DIV(_name, _reg, _div_shift, _div_width, \
_hi_shift, _hi_width, _pname, _iflags) \
_hi_shift, _hi_width, _phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_sclk_div_data) { \
.div = { \
@@ -195,7 +213,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_sclk_div_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = (_iflags), \
}, \
@@ -203,7 +221,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_sclk_div, _reg, 20, 10, 0, 0, \
"aud_mst_"#_name"_sclk_pre_en", \
aud_mst_##_name##_sclk_pre_en, \
CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
@@ -214,8 +232,8 @@ static AUD_MST_SCLK_DIV(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_SCLK_POST_EN(_name, _reg) \
AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
"aud_mst_"#_name"_sclk_div", CLK_SET_RATE_PARENT)
AUD_GATE(mst_##_name##_sclk_post_en, _reg, 30, \
aud_mst_##_name##_sclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK_POST_EN(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -224,8 +242,8 @@ static AUD_MST_SCLK_POST_EN(d, AUDIO_MST_D_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(e, AUDIO_MST_E_SCLK_CTRL0);
static AUD_MST_SCLK_POST_EN(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
_pname, _iflags) \
#define AUD_TRIPHASE(_name, _reg, _width, _shift0, _shift1, _shift2, \
_phws, _iflags) \
struct clk_regmap aud_##_name = { \
.data = &(struct meson_clk_triphase_data) { \
.ph0 = { \
@@ -247,7 +265,7 @@ struct clk_regmap aud_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "aud_"#_name, \
.ops = &meson_clk_triphase_ops, \
.parent_names = (const char *[]) { _pname }, \
.parent_hws = (const struct clk_hw *[]) { &_phws.hw }, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | (_iflags), \
}, \
@@ -255,7 +273,7 @@ struct clk_regmap aud_##_name = { \
#define AUD_MST_SCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_sclk, _reg, 1, 0, 2, 4, \
"aud_mst_"#_name"_sclk_post_en", CLK_SET_RATE_PARENT)
aud_mst_##_name##_sclk_post_en, CLK_SET_RATE_PARENT)
static AUD_MST_SCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_SCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@@ -266,7 +284,7 @@ static AUD_MST_SCLK(f, AUDIO_MST_F_SCLK_CTRL1);
#define AUD_MST_LRCLK_DIV(_name, _reg) \
AUD_SCLK_DIV(mst_##_name##_lrclk_div, _reg, 0, 10, 10, 10, \
"aud_mst_"#_name"_sclk_post_en", 0) \
aud_mst_##_name##_sclk_post_en, 0) \
static AUD_MST_LRCLK_DIV(a, AUDIO_MST_A_SCLK_CTRL0);
static AUD_MST_LRCLK_DIV(b, AUDIO_MST_B_SCLK_CTRL0);
@@ -277,7 +295,7 @@ static AUD_MST_LRCLK_DIV(f, AUDIO_MST_F_SCLK_CTRL0);
#define AUD_MST_LRCLK(_name, _reg) \
AUD_TRIPHASE(mst_##_name##_lrclk, _reg, 1, 1, 3, 5, \
"aud_mst_"#_name"_lrclk_div", CLK_SET_RATE_PARENT)
aud_mst_##_name##_lrclk_div, CLK_SET_RATE_PARENT)
static AUD_MST_LRCLK(a, AUDIO_MST_A_SCLK_CTRL1);
static AUD_MST_LRCLK(b, AUDIO_MST_B_SCLK_CTRL1);
@@ -286,19 +304,29 @@ static AUD_MST_LRCLK(d, AUDIO_MST_D_SCLK_CTRL1);
static AUD_MST_LRCLK(e, AUDIO_MST_E_SCLK_CTRL1);
static AUD_MST_LRCLK(f, AUDIO_MST_F_SCLK_CTRL1);
static const char * const tdm_sclk_parent_names[] = {
"aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
"aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
"aud_slv_sclk0", "aud_slv_sclk1", "aud_slv_sclk2",
"aud_slv_sclk3", "aud_slv_sclk4", "aud_slv_sclk5",
"aud_slv_sclk6", "aud_slv_sclk7", "aud_slv_sclk8",
"aud_slv_sclk9"
static const struct clk_parent_data tdm_sclk_parent_data[] = {
{ .hw = &aud_mst_a_sclk.hw, },
{ .hw = &aud_mst_b_sclk.hw, },
{ .hw = &aud_mst_c_sclk.hw, },
{ .hw = &aud_mst_d_sclk.hw, },
{ .hw = &aud_mst_e_sclk.hw, },
{ .hw = &aud_mst_f_sclk.hw, },
{ .fw_name = "slv_sclk0", },
{ .fw_name = "slv_sclk1", },
{ .fw_name = "slv_sclk2", },
{ .fw_name = "slv_sclk3", },
{ .fw_name = "slv_sclk4", },
{ .fw_name = "slv_sclk5", },
{ .fw_name = "slv_sclk6", },
{ .fw_name = "slv_sclk7", },
{ .fw_name = "slv_sclk8", },
{ .fw_name = "slv_sclk9", },
};
#define AUD_TDM_SCLK_MUX(_name, _reg) \
AUD_MUX(tdm##_name##_sclk_sel, _reg, 0xf, 24, \
CLK_MUX_ROUND_CLOSEST, \
tdm_sclk_parent_names, 0)
tdm_sclk_parent_data, 0)
static AUD_TDM_SCLK_MUX(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_MUX(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -310,7 +338,7 @@ static AUD_TDM_SCLK_MUX(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_PRE_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_pre_en, _reg, 31, \
"aud_tdm"#_name"_sclk_sel", CLK_SET_RATE_PARENT)
aud_tdm##_name##_sclk_sel, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_PRE_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_PRE_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -322,7 +350,7 @@ static AUD_TDM_SCLK_PRE_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
#define AUD_TDM_SCLK_POST_EN(_name, _reg) \
AUD_GATE(tdm##_name##_sclk_post_en, _reg, 30, \
"aud_tdm"#_name"_sclk_pre_en", CLK_SET_RATE_PARENT)
aud_tdm##_name##_sclk_pre_en, CLK_SET_RATE_PARENT)
static AUD_TDM_SCLK_POST_EN(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_SCLK_POST_EN(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -344,8 +372,9 @@ static AUD_TDM_SCLK_POST_EN(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
.hw.init = &(struct clk_init_data) { \
.name = "aud_tdm"#_name"_sclk", \
.ops = &meson_clk_phase_ops, \
.parent_names = (const char *[]) \
{ "aud_tdm"#_name"_sclk_post_en" }, \
.parent_hws = (const struct clk_hw *[]) { \
&aud_tdm##_name##_sclk_post_en.hw \
}, \
.num_parents = 1, \
.flags = CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT, \
}, \
@@ -359,19 +388,29 @@ static AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL);
static AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL);
static AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
static const char * const tdm_lrclk_parent_names[] = {
"aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
"aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
"aud_slv_lrclk0", "aud_slv_lrclk1", "aud_slv_lrclk2",
"aud_slv_lrclk3", "aud_slv_lrclk4", "aud_slv_lrclk5",
"aud_slv_lrclk6", "aud_slv_lrclk7", "aud_slv_lrclk8",
"aud_slv_lrclk9"
static const struct clk_parent_data tdm_lrclk_parent_data[] = {
{ .hw = &aud_mst_a_lrclk.hw, },
{ .hw = &aud_mst_b_lrclk.hw, },
{ .hw = &aud_mst_c_lrclk.hw, },
{ .hw = &aud_mst_d_lrclk.hw, },
{ .hw = &aud_mst_e_lrclk.hw, },
{ .hw = &aud_mst_f_lrclk.hw, },
{ .fw_name = "slv_lrclk0", },
{ .fw_name = "slv_lrclk1", },
{ .fw_name = "slv_lrclk2", },
{ .fw_name = "slv_lrclk3", },
{ .fw_name = "slv_lrclk4", },
{ .fw_name = "slv_lrclk5", },
{ .fw_name = "slv_lrclk6", },
{ .fw_name = "slv_lrclk7", },
{ .fw_name = "slv_lrclk8", },
{ .fw_name = "slv_lrclk9", },
};
#define AUD_TDM_LRLCK(_name, _reg) \
AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
CLK_MUX_ROUND_CLOSEST, \
tdm_lrclk_parent_names, 0)
#define AUD_TDM_LRLCK(_name, _reg) \
AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \
CLK_MUX_ROUND_CLOSEST, \
tdm_lrclk_parent_data, 0)
static AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL);
static AUD_TDM_LRLCK(in_b, AUDIO_CLK_TDMIN_B_CTRL);
@@ -386,39 +425,51 @@ static AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL);
AUD_MUX(tdm_##_name, _reg, 0x7, _shift, 0, _parents, \
CLK_SET_RATE_NO_REPARENT)
static const char * const mclk_pad_ctrl_parent_names[] = {
"aud_mst_a_mclk", "aud_mst_b_mclk", "aud_mst_c_mclk",
"aud_mst_d_mclk", "aud_mst_e_mclk", "aud_mst_f_mclk",
static const struct clk_parent_data mclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_mclk.hw },
{ .hw = &aud_mst_b_mclk.hw },
{ .hw = &aud_mst_c_mclk.hw },
{ .hw = &aud_mst_d_mclk.hw },
{ .hw = &aud_mst_e_mclk.hw },
{ .hw = &aud_mst_f_mclk.hw },
};
static AUD_TDM_PAD_CTRL(mclk_pad_0, AUDIO_MST_PAD_CTRL0, 0,
mclk_pad_ctrl_parent_names);
mclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(mclk_pad_1, AUDIO_MST_PAD_CTRL0, 4,
mclk_pad_ctrl_parent_names);
mclk_pad_ctrl_parent_data);
static const char * const lrclk_pad_ctrl_parent_names[] = {
"aud_mst_a_lrclk", "aud_mst_b_lrclk", "aud_mst_c_lrclk",
"aud_mst_d_lrclk", "aud_mst_e_lrclk", "aud_mst_f_lrclk",
static const struct clk_parent_data lrclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_lrclk.hw },
{ .hw = &aud_mst_b_lrclk.hw },
{ .hw = &aud_mst_c_lrclk.hw },
{ .hw = &aud_mst_d_lrclk.hw },
{ .hw = &aud_mst_e_lrclk.hw },
{ .hw = &aud_mst_f_lrclk.hw },
};
static AUD_TDM_PAD_CTRL(lrclk_pad_0, AUDIO_MST_PAD_CTRL1, 16,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_1, AUDIO_MST_PAD_CTRL1, 20,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(lrclk_pad_2, AUDIO_MST_PAD_CTRL1, 24,
lrclk_pad_ctrl_parent_names);
lrclk_pad_ctrl_parent_data);
static const char * const sclk_pad_ctrl_parent_names[] = {
"aud_mst_a_sclk", "aud_mst_b_sclk", "aud_mst_c_sclk",
"aud_mst_d_sclk", "aud_mst_e_sclk", "aud_mst_f_sclk",
static const struct clk_parent_data sclk_pad_ctrl_parent_data[] = {
{ .hw = &aud_mst_a_sclk.hw },
{ .hw = &aud_mst_b_sclk.hw },
{ .hw = &aud_mst_c_sclk.hw },
{ .hw = &aud_mst_d_sclk.hw },
{ .hw = &aud_mst_e_sclk.hw },
{ .hw = &aud_mst_f_sclk.hw },
};
static AUD_TDM_PAD_CTRL(sclk_pad_0, AUDIO_MST_PAD_CTRL1, 0,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_1, AUDIO_MST_PAD_CTRL1, 4,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
static AUD_TDM_PAD_CTRL(sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8,
sclk_pad_ctrl_parent_names);
sclk_pad_ctrl_parent_data);
/*
* Array of all clocks provided by this provider
@@ -868,54 +919,84 @@ static int devm_clk_get_enable(struct device *dev, char *id)
return 0;
}
static int axg_register_clk_hw_input(struct device *dev,
const char *name)
struct axg_audio_reset_data {
struct reset_controller_dev rstc;
struct regmap *map;
unsigned int offset;
};
static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
unsigned long id,
unsigned int *reg,
unsigned int *bit)
{
char *clk_name;
struct clk_hw *hw;
int err = 0;
unsigned int stride = regmap_get_reg_stride(rst->map);
clk_name = kasprintf(GFP_KERNEL, "aud_%s", name);
if (!clk_name)
return -ENOMEM;
hw = meson_clk_hw_register_input(dev, name, clk_name, 0);
if (IS_ERR(hw)) {
/* It is ok if an input clock is missing */
if (PTR_ERR(hw) == -ENOENT) {
dev_dbg(dev, "%s not provided", name);
} else {
err = PTR_ERR(hw);
if (err != -EPROBE_DEFER)
dev_err(dev, "failed to get %s clock", name);
}
}
kfree(clk_name);
return err;
*reg = (id / (stride * BITS_PER_BYTE)) * stride;
*reg += rst->offset;
*bit = id % (stride * BITS_PER_BYTE);
}
static int axg_register_clk_hw_inputs(struct device *dev,
const char *basename,
unsigned int count)
static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
char *name;
int i, ret;
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int offset, bit;
for (i = 0; i < count; i++) {
name = kasprintf(GFP_KERNEL, "%s%d", basename, i);
if (!name)
return -ENOMEM;
axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
ret = axg_register_clk_hw_input(dev, name);
kfree(name);
if (ret)
return ret;
}
regmap_update_bits(rst->map, offset, BIT(bit),
assert ? BIT(bit) : 0);
return 0;
}
static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int val, offset, bit;
axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
regmap_read(rst->map, offset, &val);
return !!(val & BIT(bit));
}
static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, true);
}
static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, false);
}
static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
unsigned long id)
{
int ret;
ret = axg_audio_reset_assert(rcdev, id);
if (ret)
return ret;
return axg_audio_reset_deassert(rcdev, id);
}
static const struct reset_control_ops axg_audio_rstc_ops = {
.assert = axg_audio_reset_assert,
.deassert = axg_audio_reset_deassert,
.reset = axg_audio_reset_toggle,
.status = axg_audio_reset_status,
};
static const struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@@ -925,12 +1006,15 @@ static const struct regmap_config axg_audio_regmap_cfg = {
struct audioclk_data {
struct clk_hw_onecell_data *hw_onecell_data;
unsigned int reset_offset;
unsigned int reset_num;
};
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
struct axg_audio_reset_data *rst;
struct regmap *map;
struct resource *res;
void __iomem *regs;
@@ -963,29 +1047,6 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
return ret;
}
/* Register the peripheral input clock */
hw = meson_clk_hw_register_input(dev, "pclk", "audio_pclk", 0);
if (IS_ERR(hw))
return PTR_ERR(hw);
/* Register optional input master clocks */
ret = axg_register_clk_hw_inputs(dev, "mst_in",
AUD_MST_IN_COUNT);
if (ret)
return ret;
/* Register optional input slave sclks */
ret = axg_register_clk_hw_inputs(dev, "slv_sclk",
AUD_SLV_SCLK_COUNT);
if (ret)
return ret;
/* Register optional input slave lrclks */
ret = axg_register_clk_hw_inputs(dev, "slv_lrclk",
AUD_SLV_LRCLK_COUNT);
if (ret)
return ret;
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < ARRAY_SIZE(aud_clk_regmaps); i++)
aud_clk_regmaps[i]->map = map;
@@ -1005,8 +1066,27 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
}
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
data->hw_onecell_data);
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
data->hw_onecell_data);
if (ret)
return ret;
/* Stop here if there is no reset */
if (!data->reset_num)
return 0;
rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
rst->map = map;
rst->offset = data->reset_offset;
rst->rstc.nr_resets = data->reset_num;
rst->rstc.ops = &axg_audio_rstc_ops;
rst->rstc.of_node = dev->of_node;
rst->rstc.owner = THIS_MODULE;
return devm_reset_controller_register(dev, &rst->rstc);
}
static const struct audioclk_data axg_audioclk_data = {
@@ -1015,6 +1095,8 @@ static const struct audioclk_data axg_audioclk_data = {
static const struct audioclk_data g12a_audioclk_data = {
.hw_onecell_data = &g12a_audio_hw_onecell_data,
.reset_offset = AUDIO_SW_RESET,
.reset_num = 26,
};
static const struct of_device_id clkc_match_table[] = {

View File

@@ -22,6 +22,7 @@
#define AUDIO_MCLK_F_CTRL 0x018
#define AUDIO_MST_PAD_CTRL0 0x01c
#define AUDIO_MST_PAD_CTRL1 0x020
#define AUDIO_SW_RESET 0x024
#define AUDIO_MST_A_SCLK_CTRL0 0x040
#define AUDIO_MST_A_SCLK_CTRL1 0x044
#define AUDIO_MST_B_SCLK_CTRL0 0x048

View File

@@ -14,7 +14,6 @@
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-input.h"
#include "clk-regmap.h"
#include "clk-pll.h"
#include "clk-mpll.h"
@@ -59,7 +58,9 @@ static struct clk_regmap axg_fixed_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -74,7 +75,9 @@ static struct clk_regmap axg_fixed_pll = {
.hw.init = &(struct clk_init_data){
.name = "fixed_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll_dco.hw
},
.num_parents = 1,
/*
* This clock won't ever change at runtime so
@@ -114,7 +117,9 @@ static struct clk_regmap axg_sys_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -129,7 +134,9 @@ static struct clk_regmap axg_sys_pll = {
.hw.init = &(struct clk_init_data){
.name = "sys_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "sys_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sys_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -215,7 +222,9 @@ static struct clk_regmap axg_gp0_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -230,7 +239,9 @@ static struct clk_regmap axg_gp0_pll = {
.hw.init = &(struct clk_init_data){
.name = "gp0_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gp0_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gp0_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -284,7 +295,9 @@ static struct clk_regmap axg_hifi_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -299,7 +312,9 @@ static struct clk_regmap axg_hifi_pll = {
.hw.init = &(struct clk_init_data){
.name = "hifi_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "hifi_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_hifi_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -311,7 +326,7 @@ static struct clk_fixed_factor axg_fclk_div2_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -324,7 +339,9 @@ static struct clk_regmap axg_fclk_div2 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div2",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div2_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div2_div.hw
},
.num_parents = 1,
.flags = CLK_IS_CRITICAL,
},
@@ -336,7 +353,7 @@ static struct clk_fixed_factor axg_fclk_div3_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -349,7 +366,9 @@ static struct clk_regmap axg_fclk_div3 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div3",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div3_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div3_div.hw
},
.num_parents = 1,
/*
* FIXME:
@@ -372,7 +391,7 @@ static struct clk_fixed_factor axg_fclk_div4_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -385,7 +404,9 @@ static struct clk_regmap axg_fclk_div4 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div4",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div4_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div4_div.hw
},
.num_parents = 1,
},
};
@@ -396,7 +417,7 @@ static struct clk_fixed_factor axg_fclk_div5_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_fixed_pll.hw },
.num_parents = 1,
},
};
@@ -409,7 +430,9 @@ static struct clk_regmap axg_fclk_div5 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div5",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div5_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div5_div.hw
},
.num_parents = 1,
},
};
@@ -420,7 +443,9 @@ static struct clk_fixed_factor axg_fclk_div7_div = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7_div",
.ops = &clk_fixed_factor_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll.hw
},
.num_parents = 1,
},
};
@@ -433,7 +458,9 @@ static struct clk_regmap axg_fclk_div7 = {
.hw.init = &(struct clk_init_data){
.name = "fclk_div7",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "fclk_div7_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fclk_div7_div.hw
},
.num_parents = 1,
},
};
@@ -447,7 +474,9 @@ static struct clk_regmap axg_mpll_prediv = {
.hw.init = &(struct clk_init_data){
.name = "mpll_prediv",
.ops = &clk_regmap_divider_ro_ops,
.parent_names = (const char *[]){ "fixed_pll" },
.parent_hws = (const struct clk_hw *[]) {
&axg_fixed_pll.hw
},
.num_parents = 1,
},
};
@@ -480,7 +509,9 @@ static struct clk_regmap axg_mpll0_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll0_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@@ -493,7 +524,9 @@ static struct clk_regmap axg_mpll0 = {
.hw.init = &(struct clk_init_data){
.name = "mpll0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -527,7 +560,9 @@ static struct clk_regmap axg_mpll1_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll1_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@@ -540,7 +575,9 @@ static struct clk_regmap axg_mpll1 = {
.hw.init = &(struct clk_init_data){
.name = "mpll1",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll1_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll1_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -579,7 +616,9 @@ static struct clk_regmap axg_mpll2_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll2_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@@ -592,7 +631,9 @@ static struct clk_regmap axg_mpll2 = {
.hw.init = &(struct clk_init_data){
.name = "mpll2",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll2_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll2_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -626,7 +667,9 @@ static struct clk_regmap axg_mpll3_div = {
.hw.init = &(struct clk_init_data){
.name = "mpll3_div",
.ops = &meson_clk_mpll_ops,
.parent_names = (const char *[]){ "mpll_prediv" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll_prediv.hw
},
.num_parents = 1,
},
};
@@ -639,7 +682,9 @@ static struct clk_regmap axg_mpll3 = {
.hw.init = &(struct clk_init_data){
.name = "mpll3",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpll3_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpll3_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -702,7 +747,9 @@ static struct clk_regmap axg_pcie_pll_dco = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_dco",
.ops = &meson_clk_pll_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -717,7 +764,9 @@ static struct clk_regmap axg_pcie_pll_od = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll_od",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_dco" },
.parent_hws = (const struct clk_hw *[]) {
&axg_pcie_pll_dco.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -733,7 +782,9 @@ static struct clk_regmap axg_pcie_pll = {
.hw.init = &(struct clk_init_data){
.name = "pcie_pll",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "pcie_pll_od" },
.parent_hws = (const struct clk_hw *[]) {
&axg_pcie_pll_od.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -750,7 +801,7 @@ static struct clk_regmap axg_pcie_mux = {
.hw.init = &(struct clk_init_data){
.name = "pcie_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "pcie_pll" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_pll.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -767,7 +818,7 @@ static struct clk_regmap axg_pcie_ref = {
.hw.init = &(struct clk_init_data){
.name = "pcie_ref",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "pcie_mux" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_mux.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -781,7 +832,7 @@ static struct clk_regmap axg_pcie_cml_en0 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "pcie_ref" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
@@ -796,16 +847,21 @@ static struct clk_regmap axg_pcie_cml_en1 = {
.hw.init = &(struct clk_init_data) {
.name = "pcie_cml_en1",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "pcie_ref" },
.parent_hws = (const struct clk_hw *[]) { &axg_pcie_ref.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
static const char * const clk81_parent_names[] = {
IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
"fclk_div3", "fclk_div5"
static const struct clk_parent_data clk81_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_fclk_div7.hw },
{ .hw = &axg_mpll1.hw },
{ .hw = &axg_mpll2.hw },
{ .hw = &axg_fclk_div4.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
};
static struct clk_regmap axg_mpeg_clk_sel = {
@@ -818,8 +874,8 @@ static struct clk_regmap axg_mpeg_clk_sel = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = clk81_parent_names,
.num_parents = ARRAY_SIZE(clk81_parent_names),
.parent_data = clk81_parent_data,
.num_parents = ARRAY_SIZE(clk81_parent_data),
},
};
@@ -832,7 +888,9 @@ static struct clk_regmap axg_mpeg_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "mpeg_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "mpeg_clk_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpeg_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -846,15 +904,20 @@ static struct clk_regmap axg_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "clk81",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "mpeg_clk_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_mpeg_clk_div.hw
},
.num_parents = 1,
.flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
},
};
static const char * const axg_sd_emmc_clk0_parent_names[] = {
IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
static const struct clk_parent_data axg_sd_emmc_clk0_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_fclk_div2.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
{ .hw = &axg_fclk_div7.hw },
/*
* Following these parent clocks, we should also have had mpll2, mpll3
* and gp0_pll but these clocks are too precious to be used here. All
@@ -873,8 +936,8 @@ static struct clk_regmap axg_sd_emmc_b_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.parent_data = axg_sd_emmc_clk0_parent_data,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -889,7 +952,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_b_clk0_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_b_clk0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -903,7 +968,9 @@ static struct clk_regmap axg_sd_emmc_b_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_b_clk0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_b_clk0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -919,8 +986,8 @@ static struct clk_regmap axg_sd_emmc_c_clk0_sel = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = axg_sd_emmc_clk0_parent_names,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names),
.parent_data = axg_sd_emmc_clk0_parent_data,
.num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_data),
.flags = CLK_SET_RATE_PARENT,
},
};
@@ -935,7 +1002,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0_div = {
.hw.init = &(struct clk_init_data) {
.name = "sd_emmc_c_clk0_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_c_clk0_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -949,7 +1018,9 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
.hw.init = &(struct clk_init_data){
.name = "sd_emmc_c_clk0",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_sd_emmc_c_clk0_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -957,9 +1028,18 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
9, 10, 11, 13, 14, };
static const char * const gen_clk_parent_names[] = {
IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
"fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
static const struct clk_parent_data gen_clk_parent_data[] = {
{ .fw_name = "xtal", },
{ .hw = &axg_hifi_pll.hw },
{ .hw = &axg_mpll0.hw },
{ .hw = &axg_mpll1.hw },
{ .hw = &axg_mpll2.hw },
{ .hw = &axg_mpll3.hw },
{ .hw = &axg_fclk_div4.hw },
{ .hw = &axg_fclk_div3.hw },
{ .hw = &axg_fclk_div5.hw },
{ .hw = &axg_fclk_div7.hw },
{ .hw = &axg_gp0_pll.hw },
};
static struct clk_regmap axg_gen_clk_sel = {
@@ -978,8 +1058,8 @@ static struct clk_regmap axg_gen_clk_sel = {
* hifi_pll, mpll0, mpll1, mpll2, mpll3, fdiv4,
* fdiv3, fdiv5, [cts_msr_clk], fdiv7, gp0_pll
*/
.parent_names = gen_clk_parent_names,
.num_parents = ARRAY_SIZE(gen_clk_parent_names),
.parent_data = gen_clk_parent_data,
.num_parents = ARRAY_SIZE(gen_clk_parent_data),
},
};
@@ -992,7 +1072,9 @@ static struct clk_regmap axg_gen_clk_div = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "gen_clk_sel" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gen_clk_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -1006,12 +1088,17 @@ static struct clk_regmap axg_gen_clk = {
.hw.init = &(struct clk_init_data){
.name = "gen_clk",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "gen_clk_div" },
.parent_hws = (const struct clk_hw *[]) {
&axg_gen_clk_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
};
#define MESON_GATE(_name, _reg, _bit) \
MESON_PCLK(_name, _reg, _bit, &axg_clk81.hw)
/* Everything Else (EE) domain gates */
static MESON_GATE(axg_ddr, HHI_GCLK_MPEG0, 0);
static MESON_GATE(axg_audio_locker, HHI_GCLK_MPEG0, 2);

View File

@@ -0,0 +1,73 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#include <linux/clk-provider.h>
#include <linux/module.h>
#include "clk-regmap.h"
#include "clk-cpu-dyndiv.h"
static inline struct meson_clk_cpu_dyndiv_data *
meson_clk_cpu_dyndiv_data(struct clk_regmap *clk)
{
return (struct meson_clk_cpu_dyndiv_data *)clk->data;
}
static unsigned long meson_clk_cpu_dyndiv_recalc_rate(struct clk_hw *hw,
unsigned long prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
return divider_recalc_rate(hw, prate,
meson_parm_read(clk->map, &data->div),
NULL, 0, data->div.width);
}
static long meson_clk_cpu_dyndiv_round_rate(struct clk_hw *hw,
unsigned long rate,
unsigned long *prate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
return divider_round_rate(hw, rate, prate, NULL, data->div.width, 0);
}
static int meson_clk_cpu_dyndiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_regmap *clk = to_clk_regmap(hw);
struct meson_clk_cpu_dyndiv_data *data = meson_clk_cpu_dyndiv_data(clk);
unsigned int val;
int ret;
ret = divider_get_val(rate, parent_rate, NULL, data->div.width, 0);
if (ret < 0)
return ret;
val = (unsigned int)ret << data->div.shift;
/* Write the SYS_CPU_DYN_ENABLE bit before changing the divider */
meson_parm_write(clk->map, &data->dyn, 1);
/* Update the divider while removing the SYS_CPU_DYN_ENABLE bit */
return regmap_update_bits(clk->map, data->div.reg_off,
SETPMASK(data->div.width, data->div.shift) |
SETPMASK(data->dyn.width, data->dyn.shift),
val);
};
const struct clk_ops meson_clk_cpu_dyndiv_ops = {
.recalc_rate = meson_clk_cpu_dyndiv_recalc_rate,
.round_rate = meson_clk_cpu_dyndiv_round_rate,
.set_rate = meson_clk_cpu_dyndiv_set_rate,
};
EXPORT_SYMBOL_GPL(meson_clk_cpu_dyndiv_ops);
MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Neil Armstrong <narmstrong@baylibre.com>
*/
#ifndef __MESON_CLK_CPU_DYNDIV_H
#define __MESON_CLK_CPU_DYNDIV_H
#include <linux/clk-provider.h>
#include "parm.h"
struct meson_clk_cpu_dyndiv_data {
struct parm div;
struct parm dyn;
};
extern const struct clk_ops meson_clk_cpu_dyndiv_ops;
#endif /* __MESON_CLK_CPU_DYNDIV_H */

View File

@@ -1,49 +0,0 @@
// SPDX-License-Identifier: (GPL-2.0 OR MIT)
/*
* Copyright (c) 2018 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/device.h>
#include <linux/module.h>
#include "clk-input.h"
static const struct clk_ops meson_clk_no_ops = {};
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags)
{
struct clk *parent_clk = devm_clk_get(dev, of_name);
struct clk_init_data init;
const char *parent_name;
struct clk_hw *hw;
int ret;
if (IS_ERR(parent_clk))
return (struct clk_hw *)parent_clk;
hw = devm_kzalloc(dev, sizeof(*hw), GFP_KERNEL);
if (!hw)
return ERR_PTR(-ENOMEM);
parent_name = __clk_get_name(parent_clk);
init.name = clk_name;
init.ops = &meson_clk_no_ops;
init.flags = flags;
init.parent_names = &parent_name;
init.num_parents = 1;
hw->init = &init;
ret = devm_clk_hw_register(dev, hw);
return ret ? ERR_PTR(ret) : hw;
}
EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
MODULE_DESCRIPTION("Amlogic clock input helper");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL v2");

View File

@@ -1,19 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2019 BayLibre, SAS.
* Author: Jerome Brunet <jbrunet@baylibre.com>
*/
#ifndef __MESON_CLK_INPUT_H
#define __MESON_CLK_INPUT_H
#include <linux/clk-provider.h>
struct device;
struct clk_hw *meson_clk_hw_register_input(struct device *dev,
const char *of_name,
const char *clk_name,
unsigned long flags);
#endif /* __MESON_CLK_INPUT_H */

View File

@@ -111,7 +111,7 @@ clk_get_regmap_mux_data(struct clk_regmap *clk)
extern const struct clk_ops clk_regmap_mux_ops;
extern const struct clk_ops clk_regmap_mux_ro_ops;
#define __MESON_GATE(_name, _reg, _bit, _ops) \
#define __MESON_PCLK(_name, _reg, _bit, _ops, _pname) \
struct clk_regmap _name = { \
.data = &(struct clk_regmap_gate_data){ \
.offset = (_reg), \
@@ -120,15 +120,15 @@ struct clk_regmap _name = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name, \
.ops = _ops, \
.parent_names = (const char *[]){ "clk81" }, \
.parent_hws = (const struct clk_hw *[]) { _pname }, \
.num_parents = 1, \
.flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
}, \
}
#define MESON_GATE(_name, _reg, _bit) \
__MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops)
#define MESON_PCLK(_name, _reg, _bit, _pname) \
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ops, _pname)
#define MESON_GATE_RO(_name, _reg, _bit) \
__MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops)
#define MESON_PCLK_RO(_name, _reg, _bit, _pname) \
__MESON_PCLK(_name, _reg, _bit, &clk_regmap_gate_ro_ops, _pname)
#endif /* __CLK_REGMAP_H */

View File

@@ -18,8 +18,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/*
* AO Configuration Clock registers offsets
* Register offsets from the data sheet must be multiplied by 4.
@@ -51,7 +49,9 @@ static struct clk_regmap g12a_aoclk_##_name = { \
.hw.init = &(struct clk_init_data) { \
.name = "g12a_ao_" #_name, \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -81,7 +81,9 @@ static struct clk_regmap g12a_aoclk_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -106,7 +108,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@@ -143,7 +147,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_pre.hw
},
.num_parents = 1,
},
};
@@ -158,8 +164,10 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div",
"g12a_ao_32k_by_oscin_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_div.hw,
&g12a_aoclk_32k_by_oscin_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -173,7 +181,9 @@ static struct clk_regmap g12a_aoclk_32k_by_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_32k_by_oscin",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_32k_by_oscin_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -189,7 +199,9 @@ static struct clk_regmap g12a_aoclk_cec_pre = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "cts_oscin" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cts_oscin.hw
},
.num_parents = 1,
},
};
@@ -226,7 +238,9 @@ static struct clk_regmap g12a_aoclk_cec_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_pre.hw
},
.num_parents = 1,
},
};
@@ -241,8 +255,10 @@ static struct clk_regmap g12a_aoclk_cec_sel = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_div",
"g12a_ao_cec_pre" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_div.hw,
&g12a_aoclk_cec_pre.hw,
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -256,7 +272,9 @@ static struct clk_regmap g12a_aoclk_cec = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cec",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_cec_sel" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_cec_sel.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -272,8 +290,10 @@ static struct clk_regmap g12a_aoclk_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "g12a_ao_32k_by_oscin",
IN_PREFIX "ext_32k-0" },
.parent_data = (const struct clk_parent_data []) {
{ .hw = &g12a_aoclk_32k_by_oscin.hw },
{ .fw_name = "ext-32k-0", },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -289,8 +309,10 @@ static struct clk_regmap g12a_aoclk_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"g12a_ao_cts_rtc_oscin"},
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &g12a_aoclk_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -305,8 +327,10 @@ static struct clk_regmap g12a_aoclk_saradc_mux = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_mux",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal",
"g12a_ao_clk81" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &g12a_aoclk_clk81.hw },
},
.num_parents = 2,
},
};
@@ -320,7 +344,9 @@ static struct clk_regmap g12a_aoclk_saradc_div = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_div",
.ops = &clk_regmap_divider_ops,
.parent_names = (const char *[]){ "g12a_ao_saradc_mux" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_saradc_mux.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -334,7 +360,9 @@ static struct clk_regmap g12a_aoclk_saradc_gate = {
.hw.init = &(struct clk_init_data){
.name = "g12a_ao_saradc_gate",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "g12a_ao_saradc_div" },
.parent_hws = (const struct clk_hw *[]) {
&g12a_aoclk_saradc_div.hw
},
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -417,12 +445,6 @@ static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input g12a_aoclk_inputs[] = {
{ .name = "xtal", .required = true },
{ .name = "mpeg-clk", .required = true },
{ .name = "ext-32k-0", .required = false },
};
static const struct meson_aoclk_data g12a_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(g12a_aoclk_reset),
@@ -430,9 +452,6 @@ static const struct meson_aoclk_data g12a_aoclkc_data = {
.num_clks = ARRAY_SIZE(g12a_aoclk_regmap),
.clks = g12a_aoclk_regmap,
.hw_data = &g12a_aoclk_onecell_data,
.inputs = g12a_aoclk_inputs,
.num_inputs = ARRAY_SIZE(g12a_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id g12a_aoclkc_match_table[] = {

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,14 @@
#define HHI_GP0_PLL_CNTL5 0x054
#define HHI_GP0_PLL_CNTL6 0x058
#define HHI_GP0_PLL_STS 0x05C
#define HHI_GP1_PLL_CNTL0 0x060
#define HHI_GP1_PLL_CNTL1 0x064
#define HHI_GP1_PLL_CNTL2 0x068
#define HHI_GP1_PLL_CNTL3 0x06C
#define HHI_GP1_PLL_CNTL4 0x070
#define HHI_GP1_PLL_CNTL5 0x074
#define HHI_GP1_PLL_CNTL6 0x078
#define HHI_GP1_PLL_STS 0x07C
#define HHI_PCIE_PLL_CNTL0 0x098
#define HHI_PCIE_PLL_CNTL1 0x09C
#define HHI_PCIE_PLL_CNTL2 0x0A0
@@ -72,6 +80,11 @@
#define HHI_SYS_CPUB_CLK_CNTL1 0x200
#define HHI_SYS_CPUB_CLK_CNTL 0x208
#define HHI_VPU_CLKB_CNTL 0x20C
#define HHI_SYS_CPU_CLK_CNTL2 0x210
#define HHI_SYS_CPU_CLK_CNTL3 0x214
#define HHI_SYS_CPU_CLK_CNTL4 0x218
#define HHI_SYS_CPU_CLK_CNTL5 0x21c
#define HHI_SYS_CPU_CLK_CNTL6 0x220
#define HHI_GEN_CLK_CNTL 0x228
#define HHI_VDIN_MEAS_CLK_CNTL 0x250
#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254
@@ -216,7 +229,6 @@
#define CLKID_CPUB_CLK_DYN1_DIV 221
#define CLKID_CPUB_CLK_DYN1 222
#define CLKID_CPUB_CLK_DYN 223
#define CLKID_CPUB_CLK 224
#define CLKID_CPUB_CLK_DIV16_EN 225
#define CLKID_CPUB_CLK_DIV16 226
#define CLKID_CPUB_CLK_DIV2 227
@@ -234,8 +246,17 @@
#define CLKID_CPUB_CLK_AXI 239
#define CLKID_CPUB_CLK_TRACE_SEL 240
#define CLKID_CPUB_CLK_TRACE 241
#define CLKID_GP1_PLL_DCO 242
#define CLKID_DSU_CLK_DYN0_SEL 244
#define CLKID_DSU_CLK_DYN0_DIV 245
#define CLKID_DSU_CLK_DYN0 246
#define CLKID_DSU_CLK_DYN1_SEL 247
#define CLKID_DSU_CLK_DYN1_DIV 248
#define CLKID_DSU_CLK_DYN1 249
#define CLKID_DSU_CLK_DYN 250
#define CLKID_DSU_CLK_FINAL 251
#define NR_CLKS 242
#define NR_CLKS 256
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/g12a-clkc.h>

View File

@@ -11,8 +11,6 @@
#include "clk-regmap.h"
#include "clk-dualdiv.h"
#define IN_PREFIX "ao-in-"
/* AO Configuration Clock registers offsets */
#define AO_RTI_PWR_CNTL_REG1 0x0c
#define AO_RTI_PWR_CNTL_REG0 0x10
@@ -31,7 +29,9 @@ static struct clk_regmap _name##_ao = { \
.hw.init = &(struct clk_init_data) { \
.name = #_name "_ao", \
.ops = &clk_regmap_gate_ops, \
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
.parent_data = &(const struct clk_parent_data) { \
.fw_name = "mpeg-clk", \
}, \
.num_parents = 1, \
.flags = CLK_IGNORE_UNUSED, \
}, \
@@ -52,7 +52,9 @@ static struct clk_regmap ao_cts_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_oscin",
.ops = &clk_regmap_gate_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "xtal" },
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
},
};
@@ -65,7 +67,7 @@ static struct clk_regmap ao_32k_pre = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_pre",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "ao_cts_oscin" },
.parent_hws = (const struct clk_hw *[]) { &ao_cts_oscin.hw },
.num_parents = 1,
},
};
@@ -112,7 +114,7 @@ static struct clk_regmap ao_32k_div = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_div",
.ops = &meson_clk_dualdiv_ops,
.parent_names = (const char *[]){ "ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) { &ao_32k_pre.hw },
.num_parents = 1,
},
};
@@ -127,8 +129,10 @@ static struct clk_regmap ao_32k_sel = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k_sel",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ "ao_32k_div",
"ao_32k_pre" },
.parent_hws = (const struct clk_hw *[]) {
&ao_32k_div.hw,
&ao_32k_pre.hw
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -142,7 +146,7 @@ static struct clk_regmap ao_32k = {
.hw.init = &(struct clk_init_data){
.name = "ao_32k",
.ops = &clk_regmap_gate_ops,
.parent_names = (const char *[]){ "ao_32k_sel" },
.parent_hws = (const struct clk_hw *[]) { &ao_32k_sel.hw },
.num_parents = 1,
.flags = CLK_SET_RATE_PARENT,
},
@@ -159,10 +163,12 @@ static struct clk_regmap ao_cts_rtc_oscin = {
.hw.init = &(struct clk_init_data){
.name = "ao_cts_rtc_oscin",
.ops = &clk_regmap_mux_ops,
.parent_names = (const char *[]){ IN_PREFIX "ext-32k-0",
IN_PREFIX "ext-32k-1",
IN_PREFIX "ext-32k-2",
"ao_32k" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "ext-32k-0", },
{ .fw_name = "ext-32k-1", },
{ .fw_name = "ext-32k-2", },
{ .hw = &ao_32k.hw },
},
.num_parents = 4,
.flags = CLK_SET_RATE_PARENT,
},
@@ -178,8 +184,10 @@ static struct clk_regmap ao_clk81 = {
.hw.init = &(struct clk_init_data){
.name = "ao_clk81",
.ops = &clk_regmap_mux_ro_ops,
.parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
"ao_cts_rtc_oscin" },
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "mpeg-clk", },
{ .hw = &ao_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -208,8 +216,10 @@ static struct clk_regmap ao_cts_cec = {
* Until CCF gets fixed, adding this fake parent that won't
* ever be registered should work around the problem
*/
.parent_names = (const char *[]){ "fixme",
"ao_cts_rtc_oscin" },
.parent_data = (const struct clk_parent_data []) {
{ .name = "fixme", .index = -1, },
{ .hw = &ao_cts_rtc_oscin.hw },
},
.num_parents = 2,
.flags = CLK_SET_RATE_PARENT,
},
@@ -261,14 +271,6 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
.num = NR_CLKS,
};
static const struct meson_aoclk_input gxbb_aoclk_inputs[] = {
{ .name = "xtal", .required = true, },
{ .name = "mpeg-clk", .required = true, },
{. name = "ext-32k-0", .required = false, },
{. name = "ext-32k-1", .required = false, },
{. name = "ext-32k-2", .required = false, },
};
static const struct meson_aoclk_data gxbb_aoclkc_data = {
.reset_reg = AO_RTI_GEN_CNTL_REG0,
.num_reset = ARRAY_SIZE(gxbb_aoclk_reset),
@@ -276,9 +278,6 @@ static const struct meson_aoclk_data gxbb_aoclkc_data = {
.num_clks = ARRAY_SIZE(gxbb_aoclk),
.clks = gxbb_aoclk,
.hw_data = &gxbb_aoclk_onecell_data,
.inputs = gxbb_aoclk_inputs,
.num_inputs = ARRAY_SIZE(gxbb_aoclk_inputs),
.input_prefix = IN_PREFIX,
};
static const struct of_device_id gxbb_aoclkc_match_table[] = {

File diff suppressed because it is too large Load Diff

View File

@@ -17,8 +17,6 @@
#include <linux/slab.h>
#include "meson-aoclk.h"
#include "clk-input.h"
static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev,
unsigned long id)
{
@@ -33,37 +31,6 @@ static const struct reset_control_ops meson_aoclk_reset_ops = {
.reset = meson_aoclk_do_reset,
};
static int meson_aoclkc_register_inputs(struct device *dev,
struct meson_aoclk_data *data)
{
struct clk_hw *hw;
char *str;
int i;
for (i = 0; i < data->num_inputs; i++) {
const struct meson_aoclk_input *in = &data->inputs[i];
str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix,
in->name);
if (!str)
return -ENOMEM;
hw = meson_clk_hw_register_input(dev, in->name, str, 0);
kfree(str);
if (IS_ERR(hw)) {
if (!in->required && PTR_ERR(hw) == -ENOENT)
continue;
else if (PTR_ERR(hw) != -EPROBE_DEFER)
dev_err(dev, "failed to register input %s\n",
in->name);
return PTR_ERR(hw);
}
}
return 0;
}
int meson_aoclkc_probe(struct platform_device *pdev)
{
struct meson_aoclk_reset_controller *rstc;
@@ -86,10 +53,6 @@ int meson_aoclkc_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
}
ret = meson_aoclkc_register_inputs(dev, data);
if (ret)
return ret;
/* Reset Controller */
rstc->data = data;
rstc->regmap = regmap;

View File

@@ -18,20 +18,12 @@
#include "clk-regmap.h"
struct meson_aoclk_input {
const char *name;
bool required;
};
struct meson_aoclk_data {
const unsigned int reset_reg;
const int num_reset;
const unsigned int *reset;
const int num_clks;
struct clk_regmap **clks;
const int num_inputs;
const struct meson_aoclk_input *inputs;
const char *input_prefix;
const struct clk_hw_onecell_data *hw_data;
};

View File

@@ -10,7 +10,6 @@
#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include "clk-input.h"
#include "clk-regmap.h"
#include "meson-eeclk.h"
@@ -18,7 +17,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
{
const struct meson_eeclkc_data *data;
struct device *dev = &pdev->dev;
struct clk_hw *input;
struct regmap *map;
int ret, i;
@@ -37,14 +35,6 @@ int meson_eeclkc_probe(struct platform_device *pdev)
if (data->init_count)
regmap_multi_reg_write(map, data->init_regs, data->init_count);
input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0);
if (IS_ERR(input)) {
ret = PTR_ERR(input);
if (ret != -EPROBE_DEFER)
dev_err(dev, "failed to get input clock");
return ret;
}
/* Populate regmap for the regmap backed clocks */
for (i = 0; i < data->regmap_clk_num; i++)
data->regmap_clks[i]->map = map;

View File

@@ -10,8 +10,6 @@
#include <linux/clk-provider.h>
#include "clk-regmap.h"
#define IN_PREFIX "ee-in-"
struct platform_device;
struct meson_eeclkc_data {

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,9 @@ config MVEBU_CLK_CPU
config MVEBU_CLK_COREDIV
bool
config ARMADA_AP_CP_HELPER
bool
config ARMADA_370_CLK
bool
select MVEBU_CLK_COMMON
@@ -35,9 +38,14 @@ config ARMADA_XP_CLK
config ARMADA_AP806_SYSCON
bool
select ARMADA_AP_CP_HELPER
config ARMADA_AP_CPU_CLK
bool
config ARMADA_CP110_SYSCON
bool
select ARMADA_AP_CP_HELPER
config DOVE_CLK
bool

View File

@@ -2,6 +2,7 @@
obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o
obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o
obj-$(CONFIG_ARMADA_AP_CP_HELPER) += armada_ap_cp_helper.o
obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o
obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-tbg.o
obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-periph.o
obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o mv98dx3236.o
obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o
obj-$(CONFIG_ARMADA_AP_CPU_CLK) += ap-cpu-clk.o
obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o
obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o
obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o

View File

@@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Marvell Armada AP CPU Clock Controller
*
* Copyright (C) 2018 Marvell
*
* Omri Itach <omrii@marvell.com>
* Gregory Clement <gregory.clement@bootlin.com>
*/
#define pr_fmt(fmt) "ap-cpu-clk: " fmt
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "armada_ap_cp_helper.h"
#define AP806_CPU_CLUSTER0 0
#define AP806_CPU_CLUSTER1 1
#define AP806_CPUS_PER_CLUSTER 2
#define APN806_CPU1_MASK 0x1
#define APN806_CLUSTER_NUM_OFFSET 8
#define APN806_CLUSTER_NUM_MASK BIT(APN806_CLUSTER_NUM_OFFSET)
#define APN806_MAX_DIVIDER 32
/**
* struct cpu_dfs_regs: CPU DFS register mapping
* @divider_reg: full integer ratio from PLL frequency to CPU clock frequency
* @force_reg: request to force new ratio regardless of relation to other clocks
* @ratio_reg: central request to switch ratios
*/
struct cpu_dfs_regs {
unsigned int divider_reg;
unsigned int force_reg;
unsigned int ratio_reg;
unsigned int ratio_state_reg;
unsigned int divider_mask;
unsigned int cluster_offset;
unsigned int force_mask;
int divider_offset;
int divider_ratio;
int ratio_offset;
int ratio_state_offset;
int ratio_state_cluster_offset;
};
/* AP806 CPU DFS register mapping*/
#define AP806_CA72MP2_0_PLL_CR_0_REG_OFFSET 0x278
#define AP806_CA72MP2_0_PLL_CR_1_REG_OFFSET 0x280
#define AP806_CA72MP2_0_PLL_CR_2_REG_OFFSET 0x284
#define AP806_CA72MP2_0_PLL_SR_REG_OFFSET 0xC94
#define AP806_CA72MP2_0_PLL_CR_CLUSTER_OFFSET 0x14
#define AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET 0
#define AP806_PLL_CR_CPU_CLK_DIV_RATIO 0
#define AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET)
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET 24
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK \
(0x1 << AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET)
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET 16
#define AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET 0
#define AP806_CA72MP2_0_PLL_RATIO_STATE 11
#define STATUS_POLL_PERIOD_US 1
#define STATUS_POLL_TIMEOUT_US 1000000
#define to_ap_cpu_clk(_hw) container_of(_hw, struct ap_cpu_clk, hw)
static const struct cpu_dfs_regs ap806_dfs_regs = {
.divider_reg = AP806_CA72MP2_0_PLL_CR_0_REG_OFFSET,
.force_reg = AP806_CA72MP2_0_PLL_CR_1_REG_OFFSET,
.ratio_reg = AP806_CA72MP2_0_PLL_CR_2_REG_OFFSET,
.ratio_state_reg = AP806_CA72MP2_0_PLL_SR_REG_OFFSET,
.divider_mask = AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK,
.cluster_offset = AP806_CA72MP2_0_PLL_CR_CLUSTER_OFFSET,
.force_mask = AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK,
.divider_offset = AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET,
.divider_ratio = AP806_PLL_CR_CPU_CLK_DIV_RATIO,
.ratio_offset = AP806_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET,
.ratio_state_offset = AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET,
.ratio_state_cluster_offset = AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET,
};
/* AP807 CPU DFS register mapping */
#define AP807_DEVICE_GENERAL_CONTROL_10_REG_OFFSET 0x278
#define AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET 0x27c
#define AP807_DEVICE_GENERAL_STATUS_6_REG_OFFSET 0xc98
#define AP807_CA72MP2_0_PLL_CR_CLUSTER_OFFSET 0x8
#define AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET 18
#define AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET)
#define AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET 12
#define AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET)
#define AP807_PLL_CR_CPU_CLK_DIV_RATIO 3
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET 0
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK \
(0x3 << AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET)
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET 6
#define AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_OFFSET 20
#define AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_CLUSTER_OFFSET 3
static const struct cpu_dfs_regs ap807_dfs_regs = {
.divider_reg = AP807_DEVICE_GENERAL_CONTROL_10_REG_OFFSET,
.force_reg = AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET,
.ratio_reg = AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET,
.ratio_state_reg = AP807_DEVICE_GENERAL_STATUS_6_REG_OFFSET,
.divider_mask = AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK,
.cluster_offset = AP807_CA72MP2_0_PLL_CR_CLUSTER_OFFSET,
.force_mask = AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK,
.divider_offset = AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET,
.divider_ratio = AP807_PLL_CR_CPU_CLK_DIV_RATIO,
.ratio_offset = AP807_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET,
.ratio_state_offset = AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_OFFSET,
.ratio_state_cluster_offset =
AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_CLUSTER_OFFSET
};
/*
* struct ap806_clk: CPU cluster clock controller instance
* @cluster: Cluster clock controller index
* @clk_name: Cluster clock controller name
* @dev : Cluster clock device
* @hw: HW specific structure of Cluster clock controller
* @pll_cr_base: CA72MP2 Register base (Device Sample at Reset register)
*/
struct ap_cpu_clk {
unsigned int cluster;
const char *clk_name;
struct device *dev;
struct clk_hw hw;
struct regmap *pll_cr_base;
const struct cpu_dfs_regs *pll_regs;
};
static unsigned long ap_cpu_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ap_cpu_clk *clk = to_ap_cpu_clk(hw);
unsigned int cpu_clkdiv_reg;
int cpu_clkdiv_ratio;
cpu_clkdiv_reg = clk->pll_regs->divider_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
regmap_read(clk->pll_cr_base, cpu_clkdiv_reg, &cpu_clkdiv_ratio);
cpu_clkdiv_ratio &= clk->pll_regs->divider_mask;
cpu_clkdiv_ratio >>= clk->pll_regs->divider_offset;
return parent_rate / cpu_clkdiv_ratio;
}
static int ap_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ap_cpu_clk *clk = to_ap_cpu_clk(hw);
int ret, reg, divider = parent_rate / rate;
unsigned int cpu_clkdiv_reg, cpu_force_reg, cpu_ratio_reg, stable_bit;
cpu_clkdiv_reg = clk->pll_regs->divider_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
cpu_force_reg = clk->pll_regs->force_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
cpu_ratio_reg = clk->pll_regs->ratio_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
regmap_read(clk->pll_cr_base, cpu_clkdiv_reg, &reg);
reg &= ~(clk->pll_regs->divider_mask);
reg |= (divider << clk->pll_regs->divider_offset);
/*
* AP807 CPU divider has two channels with ratio 1:3 and divider_ratio
* is 1. Otherwise, in the case of the AP806, divider_ratio is 0.
*/
if (clk->pll_regs->divider_ratio) {
reg &= ~(AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_MASK);
reg |= ((divider * clk->pll_regs->divider_ratio) <<
AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET);
}
regmap_write(clk->pll_cr_base, cpu_clkdiv_reg, reg);
regmap_update_bits(clk->pll_cr_base, cpu_force_reg,
clk->pll_regs->force_mask,
clk->pll_regs->force_mask);
regmap_update_bits(clk->pll_cr_base, cpu_ratio_reg,
BIT(clk->pll_regs->ratio_offset),
BIT(clk->pll_regs->ratio_offset));
stable_bit = BIT(clk->pll_regs->ratio_state_offset +
clk->cluster *
clk->pll_regs->ratio_state_cluster_offset),
ret = regmap_read_poll_timeout(clk->pll_cr_base,
clk->pll_regs->ratio_state_reg, reg,
reg & stable_bit, STATUS_POLL_PERIOD_US,
STATUS_POLL_TIMEOUT_US);
if (ret)
return ret;
regmap_update_bits(clk->pll_cr_base, cpu_ratio_reg,
BIT(clk->pll_regs->ratio_offset), 0);
return 0;
}
static long ap_cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
int divider = *parent_rate / rate;
divider = min(divider, APN806_MAX_DIVIDER);
return *parent_rate / divider;
}
static const struct clk_ops ap_cpu_clk_ops = {
.recalc_rate = ap_cpu_clk_recalc_rate,
.round_rate = ap_cpu_clk_round_rate,
.set_rate = ap_cpu_clk_set_rate,
};
static int ap_cpu_clock_probe(struct platform_device *pdev)
{
int ret, nclusters = 0, cluster_index = 0;
struct device *dev = &pdev->dev;
struct device_node *dn, *np = dev->of_node;
struct clk_hw_onecell_data *ap_cpu_data;
struct ap_cpu_clk *ap_cpu_clk;
struct regmap *regmap;
regmap = syscon_node_to_regmap(np->parent);
if (IS_ERR(regmap)) {
pr_err("cannot get pll_cr_base regmap\n");
return PTR_ERR(regmap);
}
/*
* AP806 has 4 cpus and DFS for AP806 is controlled per
* cluster (2 CPUs per cluster), cpu0 and cpu1 are fixed to
* cluster0 while cpu2 and cpu3 are fixed to cluster1 whether
* they are enabled or not. Since cpu0 is the boot cpu, then
* cluster0 must exist. If cpu2 or cpu3 is enabled, cluster1
* will exist and the cluster number is 2; otherwise the
* cluster number is 1.
*/
nclusters = 1;
for_each_of_cpu_node(dn) {
int cpu, err;
err = of_property_read_u32(dn, "reg", &cpu);
if (WARN_ON(err))
return err;
/* If cpu2 or cpu3 is enabled */
if (cpu & APN806_CLUSTER_NUM_MASK) {
nclusters = 2;
break;
}
}
/*
* DFS for AP806 is controlled per cluster (2 CPUs per cluster),
* so allocate structs per cluster
*/
ap_cpu_clk = devm_kcalloc(dev, nclusters, sizeof(*ap_cpu_clk),
GFP_KERNEL);
if (!ap_cpu_clk)
return -ENOMEM;
ap_cpu_data = devm_kzalloc(dev, sizeof(*ap_cpu_data) +
sizeof(struct clk_hw *) * nclusters,
GFP_KERNEL);
if (!ap_cpu_data)
return -ENOMEM;
for_each_of_cpu_node(dn) {
char *clk_name = "cpu-cluster-0";
struct clk_init_data init;
const char *parent_name;
struct clk *parent;
int cpu, err;
err = of_property_read_u32(dn, "reg", &cpu);
if (WARN_ON(err))
return err;
cluster_index = cpu & APN806_CLUSTER_NUM_MASK;
cluster_index >>= APN806_CLUSTER_NUM_OFFSET;
/* Initialize once for one cluster */
if (ap_cpu_data->hws[cluster_index])
continue;
parent = of_clk_get(np, cluster_index);
if (IS_ERR(parent)) {
dev_err(dev, "Could not get the clock parent\n");
return -EINVAL;
}
parent_name = __clk_get_name(parent);
clk_name[12] += cluster_index;
ap_cpu_clk[cluster_index].clk_name =
ap_cp_unique_name(dev, np->parent, clk_name);
ap_cpu_clk[cluster_index].cluster = cluster_index;
ap_cpu_clk[cluster_index].pll_cr_base = regmap;
ap_cpu_clk[cluster_index].hw.init = &init;
ap_cpu_clk[cluster_index].dev = dev;
ap_cpu_clk[cluster_index].pll_regs = of_device_get_match_data(&pdev->dev);
init.name = ap_cpu_clk[cluster_index].clk_name;
init.ops = &ap_cpu_clk_ops;
init.num_parents = 1;
init.parent_names = &parent_name;
ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw);
if (ret)
return ret;
ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw;
}
ap_cpu_data->num = cluster_index + 1;
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, ap_cpu_data);
if (ret)
dev_err(dev, "failed to register OF clock provider\n");
return ret;
}
static const struct of_device_id ap_cpu_clock_of_match[] = {
{
.compatible = "marvell,ap806-cpu-clock",
.data = &ap806_dfs_regs,
},
{
.compatible = "marvell,ap807-cpu-clock",
.data = &ap807_dfs_regs,
},
{ }
};
static struct platform_driver ap_cpu_clock_driver = {
.probe = ap_cpu_clock_probe,
.driver = {
.name = "marvell-ap-cpu-clock",
.of_match_table = ap_cpu_clock_of_match,
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(ap_cpu_clock_driver);

View File

@@ -10,18 +10,18 @@
#define pr_fmt(fmt) "ap806-system-controller: " fmt
#include "armada_ap_cp_helper.h"
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define AP806_SAR_REG 0x400
#define AP806_SAR_CLKFREQ_MODE_MASK 0x1f
#define AP806_CLK_NUM 5
#define AP806_CLK_NUM 6
static struct clk *ap806_clks[AP806_CLK_NUM];
@@ -30,22 +30,106 @@ static struct clk_onecell_data ap806_clk_data = {
.clk_num = AP806_CLK_NUM,
};
static char *ap806_unique_name(struct device *dev, struct device_node *np,
char *name)
static int ap806_get_sar_clocks(unsigned int freq_mode,
unsigned int *cpuclk_freq,
unsigned int *dclk_freq)
{
const __be32 *reg;
u64 addr;
switch (freq_mode) {
case 0x0:
*cpuclk_freq = 2000;
*dclk_freq = 600;
break;
case 0x1:
*cpuclk_freq = 2000;
*dclk_freq = 525;
break;
case 0x6:
*cpuclk_freq = 1800;
*dclk_freq = 600;
break;
case 0x7:
*cpuclk_freq = 1800;
*dclk_freq = 525;
break;
case 0x4:
*cpuclk_freq = 1600;
*dclk_freq = 400;
break;
case 0xB:
*cpuclk_freq = 1600;
*dclk_freq = 450;
break;
case 0xD:
*cpuclk_freq = 1600;
*dclk_freq = 525;
break;
case 0x1a:
*cpuclk_freq = 1400;
*dclk_freq = 400;
break;
case 0x14:
*cpuclk_freq = 1300;
*dclk_freq = 400;
break;
case 0x17:
*cpuclk_freq = 1300;
*dclk_freq = 325;
break;
case 0x19:
*cpuclk_freq = 1200;
*dclk_freq = 400;
break;
case 0x13:
*cpuclk_freq = 1000;
*dclk_freq = 325;
break;
case 0x1d:
*cpuclk_freq = 1000;
*dclk_freq = 400;
break;
case 0x1c:
*cpuclk_freq = 800;
*dclk_freq = 400;
break;
case 0x1b:
*cpuclk_freq = 600;
*dclk_freq = 400;
break;
default:
return -EINVAL;
}
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
return 0;
}
static int ap807_get_sar_clocks(unsigned int freq_mode,
unsigned int *cpuclk_freq,
unsigned int *dclk_freq)
{
switch (freq_mode) {
case 0x0:
*cpuclk_freq = 2000;
*dclk_freq = 1200;
break;
case 0x6:
*cpuclk_freq = 2200;
*dclk_freq = 1200;
break;
case 0xD:
*cpuclk_freq = 1600;
*dclk_freq = 1200;
break;
default:
return -EINVAL;
}
return 0;
}
static int ap806_syscon_common_probe(struct platform_device *pdev,
struct device_node *syscon_node)
{
unsigned int freq_mode, cpuclk_freq;
unsigned int freq_mode, cpuclk_freq, dclk_freq;
const char *name, *fixedclk_name;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
@@ -66,50 +150,29 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
switch (freq_mode) {
case 0x0:
case 0x1:
cpuclk_freq = 2000;
break;
case 0x6:
case 0x7:
cpuclk_freq = 1800;
break;
case 0x4:
case 0xB:
case 0xD:
cpuclk_freq = 1600;
break;
case 0x1a:
cpuclk_freq = 1400;
break;
case 0x14:
case 0x17:
cpuclk_freq = 1300;
break;
case 0x19:
cpuclk_freq = 1200;
break;
case 0x13:
case 0x1d:
cpuclk_freq = 1000;
break;
case 0x1c:
cpuclk_freq = 800;
break;
case 0x1b:
cpuclk_freq = 600;
break;
default:
dev_err(dev, "invalid SAR value\n");
if (of_device_is_compatible(pdev->dev.of_node,
"marvell,ap806-clock")) {
ret = ap806_get_sar_clocks(freq_mode, &cpuclk_freq, &dclk_freq);
} else if (of_device_is_compatible(pdev->dev.of_node,
"marvell,ap807-clock")) {
ret = ap807_get_sar_clocks(freq_mode, &cpuclk_freq, &dclk_freq);
} else {
dev_err(dev, "compatible not supported\n");
return -EINVAL;
}
if (ret) {
dev_err(dev, "invalid Sample at Reset value\n");
return ret;
}
/* Convert to hertz */
cpuclk_freq *= 1000 * 1000;
dclk_freq *= 1000 * 1000;
/* CPU clocks depend on the Sample At Reset configuration */
name = ap806_unique_name(dev, syscon_node, "cpu-cluster-0");
name = ap_cp_unique_name(dev, syscon_node, "pll-cluster-0");
ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL,
0, cpuclk_freq);
if (IS_ERR(ap806_clks[0])) {
@@ -117,7 +180,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
goto fail0;
}
name = ap806_unique_name(dev, syscon_node, "cpu-cluster-1");
name = ap_cp_unique_name(dev, syscon_node, "pll-cluster-1");
ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0,
cpuclk_freq);
if (IS_ERR(ap806_clks[1])) {
@@ -126,7 +189,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* Fixed clock is always 1200 Mhz */
fixedclk_name = ap806_unique_name(dev, syscon_node, "fixed");
fixedclk_name = ap_cp_unique_name(dev, syscon_node, "fixed");
ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL,
0, 1200 * 1000 * 1000);
if (IS_ERR(ap806_clks[2])) {
@@ -135,7 +198,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* MSS Clock is fixed clock divided by 6 */
name = ap806_unique_name(dev, syscon_node, "mss");
name = ap_cp_unique_name(dev, syscon_node, "mss");
ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name,
0, 1, 6);
if (IS_ERR(ap806_clks[3])) {
@@ -144,7 +207,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* SDIO(/eMMC) Clock is fixed clock divided by 3 */
name = ap806_unique_name(dev, syscon_node, "sdio");
name = ap_cp_unique_name(dev, syscon_node, "sdio");
ap806_clks[4] = clk_register_fixed_factor(NULL, name,
fixedclk_name,
0, 1, 3);
@@ -153,6 +216,14 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
goto fail4;
}
/* AP-DCLK(HCLK) Clock is DDR clock divided by 2 */
name = ap_cp_unique_name(dev, syscon_node, "ap-dclk");
ap806_clks[5] = clk_register_fixed_rate(dev, name, NULL, 0, dclk_freq);
if (IS_ERR(ap806_clks[5])) {
ret = PTR_ERR(ap806_clks[5]);
goto fail5;
}
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
if (ret)
goto fail_clk_add;
@@ -160,6 +231,8 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
return 0;
fail_clk_add:
clk_unregister_fixed_factor(ap806_clks[5]);
fail5:
clk_unregister_fixed_factor(ap806_clks[4]);
fail4:
clk_unregister_fixed_factor(ap806_clks[3]);
@@ -206,6 +279,7 @@ builtin_platform_driver(ap806_syscon_legacy_driver);
static const struct of_device_id ap806_clock_of_match[] = {
{ .compatible = "marvell,ap806-clock", },
{ .compatible = "marvell,ap807-clock", },
{ }
};

View File

@@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Marvell Armada AP and CP110 helper
*
* Copyright (C) 2018 Marvell
*
* Gregory Clement <gregory.clement@bootlin.com>
*
*/
#include "armada_ap_cp_helper.h"
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
char *ap_cp_unique_name(struct device *dev, struct device_node *np,
const char *name)
{
const __be32 *reg;
u64 addr;
/* Do not create a name if there is no clock */
if (!name)
return NULL;
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
}

View File

@@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ARMADA_AP_CP_HELPER_H
#define __ARMADA_AP_CP_HELPER_H
struct device;
struct device_node;
char *ap_cp_unique_name(struct device *dev, struct device_node *np,
const char *name);
#endif

View File

@@ -26,11 +26,11 @@
#define pr_fmt(fmt) "cp110-system-controller: " fmt
#include "armada_ap_cp_helper.h"
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -212,22 +212,6 @@ static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
return ERR_PTR(-EINVAL);
}
static char *cp110_unique_name(struct device *dev, struct device_node *np,
const char *name)
{
const __be32 *reg;
u64 addr;
/* Do not create a name if there is no clock */
if (!name)
return NULL;
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
}
static int cp110_syscon_common_probe(struct platform_device *pdev,
struct device_node *syscon_node)
{
@@ -261,7 +245,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clk_data->num = CP110_CLK_NUM;
/* Register the PLL0 which is the root of the hw tree */
pll0_name = cp110_unique_name(dev, syscon_node, "pll0");
pll0_name = ap_cp_unique_name(dev, syscon_node, "pll0");
hw = clk_hw_register_fixed_rate(NULL, pll0_name, NULL, 0,
1000 * 1000 * 1000);
if (IS_ERR(hw)) {
@@ -272,7 +256,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_PLL0] = hw;
/* PPv2 is PLL0/3 */
ppv2_name = cp110_unique_name(dev, syscon_node, "ppv2-core");
ppv2_name = ap_cp_unique_name(dev, syscon_node, "ppv2-core");
hw = clk_hw_register_fixed_factor(NULL, ppv2_name, pll0_name, 0, 1, 3);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
@@ -282,7 +266,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_PPV2] = hw;
/* X2CORE clock is PLL0/2 */
x2core_name = cp110_unique_name(dev, syscon_node, "x2core");
x2core_name = ap_cp_unique_name(dev, syscon_node, "x2core");
hw = clk_hw_register_fixed_factor(NULL, x2core_name, pll0_name,
0, 1, 2);
if (IS_ERR(hw)) {
@@ -293,7 +277,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_X2CORE] = hw;
/* Core clock is X2CORE/2 */
core_name = cp110_unique_name(dev, syscon_node, "core");
core_name = ap_cp_unique_name(dev, syscon_node, "core");
hw = clk_hw_register_fixed_factor(NULL, core_name, x2core_name,
0, 1, 2);
if (IS_ERR(hw)) {
@@ -303,7 +287,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_CORE] = hw;
/* NAND can be either PLL0/2.5 or core clock */
nand_name = cp110_unique_name(dev, syscon_node, "nand-core");
nand_name = ap_cp_unique_name(dev, syscon_node, "nand-core");
if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
hw = clk_hw_register_fixed_factor(NULL, nand_name,
pll0_name, 0, 2, 5);
@@ -318,7 +302,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_NAND] = hw;
/* SDIO clock is PLL0/2.5 */
sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
sdio_name = ap_cp_unique_name(dev, syscon_node, "sdio-core");
hw = clk_hw_register_fixed_factor(NULL, sdio_name,
pll0_name, 0, 2, 5);
if (IS_ERR(hw)) {
@@ -330,7 +314,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
/* create the unique name for all the gate clocks */
for (i = 0; i < ARRAY_SIZE(gate_base_names); i++)
gate_name[i] = cp110_unique_name(dev, syscon_node,
gate_name[i] = ap_cp_unique_name(dev, syscon_node,
gate_base_names[i]);
for (i = 0; i < ARRAY_SIZE(gate_base_names); i++) {

View File

@@ -21,7 +21,6 @@ if COMMON_CLK_QCOM
config QCOM_A53PLL
tristate "MSM8916 A53 PLL"
default ARCH_QCOM
help
Support for the A53 PLL on MSM8916 devices. It provides
the CPU with frequencies above 1GHz.
@@ -31,7 +30,6 @@ config QCOM_A53PLL
config QCOM_CLK_APCS_MSM8916
tristate "MSM8916 APCS Clock Controller"
depends on QCOM_APCS_IPC || COMPILE_TEST
default ARCH_QCOM
help
Support for the APCS Clock Controller on msm8916 devices. The
APCS is managing the mux and divider which feeds the CPUs.
@@ -292,6 +290,13 @@ config SDM_LPASSCC_845
Say Y if you want to use the LPASS branch clocks of the LPASS clock
controller to reset the LPASS subsystem.
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
help
Support for the global clock controller on SM8150 devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on SPMI || COMPILE_TEST

View File

@@ -50,6 +50,7 @@ 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_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
obj-$(CONFIG_QCOM_HFPLL) += hfpll.o

View File

@@ -32,6 +32,7 @@
# define PLL_LOCK_DET BIT(31)
#define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL])
#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL])
#define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL])
#define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U])
@@ -44,14 +45,17 @@
# define PLL_VCO_MASK 0x3
#define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U])
#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1])
#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL])
#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U])
#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1])
#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL])
#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])
#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])
#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL])
const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[CLK_ALPHA_PLL_TYPE_DEFAULT] = {
@@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[PLL_OFF_OPMODE] = 0x2c,
[PLL_OFF_FRAC] = 0x38,
},
[CLK_ALPHA_PLL_TYPE_TRION] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_CAL_L_VAL] = 0x08,
[PLL_OFF_USER_CTL] = 0x0c,
[PLL_OFF_USER_CTL_U] = 0x10,
[PLL_OFF_USER_CTL_U1] = 0x14,
[PLL_OFF_CONFIG_CTL] = 0x18,
[PLL_OFF_CONFIG_CTL_U] = 0x1c,
[PLL_OFF_CONFIG_CTL_U1] = 0x20,
[PLL_OFF_TEST_CTL] = 0x24,
[PLL_OFF_TEST_CTL_U] = 0x28,
[PLL_OFF_STATUS] = 0x30,
[PLL_OFF_OPMODE] = 0x38,
[PLL_OFF_ALPHA_VAL] = 0x40,
[PLL_OFF_CAL_VAL] = 0x44,
},
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
@@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
#define FABIA_PLL_OUT_MASK 0x7
#define FABIA_PLL_RATE_MARGIN 500
#define TRION_PLL_STANDBY 0x0
#define TRION_PLL_RUN 0x1
#define TRION_PLL_OUT_MASK 0x7
#define pll_alpha_width(p) \
((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
@@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
return alpha_huayra_pll_round_rate(rate, *prate, &l, &a);
}
static int trion_pll_is_enabled(struct clk_alpha_pll *pll,
struct regmap *regmap)
{
u32 mode_regval, opmode_regval;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval);
ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval);
if (ret)
return 0;
return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL));
}
static int clk_trion_pll_is_enabled(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
return trion_pll_is_enabled(pll, pll->clkr.regmap);
}
static int clk_trion_pll_enable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 val;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
/* If in FSM mode, just vote for it */
if (val & PLL_VOTE_FSM_ENA) {
ret = clk_enable_regmap(hw);
if (ret)
return ret;
return wait_for_pll_enable_active(pll);
}
/* Set operation mode to RUN */
regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN);
ret = wait_for_pll_enable_lock(pll);
if (ret)
return ret;
/* Enable the PLL outputs */
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),
TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK);
if (ret)
return ret;
/* Enable the global PLL outputs */
return regmap_update_bits(regmap, PLL_MODE(pll),
PLL_OUTCTRL, PLL_OUTCTRL);
}
static void clk_trion_pll_disable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 val;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return;
/* If in FSM mode, just unvote it */
if (val & PLL_VOTE_FSM_ENA) {
clk_disable_regmap(hw);
return;
}
/* Disable the global PLL output */
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
if (ret)
return;
/* Disable the PLL outputs */
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),
TRION_PLL_OUT_MASK, 0);
if (ret)
return;
/* Place the PLL mode in STANDBY */
regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY);
regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
}
static unsigned long
clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 l, frac;
u64 prate = parent_rate;
regmap_read(regmap, PLL_L_VAL(pll), &l);
regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH);
}
static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
unsigned long min_freq, max_freq;
u32 l;
u64 a;
rate = alpha_pll_round_rate(rate, *prate,
&l, &a, ALPHA_REG_16BIT_WIDTH);
if (!pll->vco_table || alpha_pll_find_vco(pll, rate))
return rate;
min_freq = pll->vco_table[0].min_freq;
max_freq = pll->vco_table[pll->num_vco - 1].max_freq;
return clamp(rate, min_freq, max_freq);
}
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
@@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = {
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
const struct clk_ops clk_trion_fixed_pll_ops = {
.enable = clk_trion_pll_enable,
.disable = clk_trion_pll_disable,
.is_enabled = clk_trion_pll_is_enabled,
.recalc_rate = clk_trion_pll_recalc_rate,
.round_rate = clk_trion_pll_round_rate,
};
EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops);
static unsigned long
clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
@@ -832,7 +989,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
int div;
/* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1;
return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
@@ -1036,11 +1193,6 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw,
u32 i, div = 1, val;
int ret;
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
if (ret)
return ret;
@@ -1058,16 +1210,71 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw,
return (parent_rate / div);
}
static unsigned long
clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 i, div = 1, val;
regmap_read(regmap, PLL_USER_CTL(pll), &val);
val >>= pll->post_div_shift;
val &= PLL_POST_DIV_MASK(pll);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].val == val) {
div = pll->post_div_table[i].div;
break;
}
}
return (parent_rate / div);
}
static long
clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
return divider_round_rate(hw, rate, prate, pll->post_div_table,
pll->width, CLK_DIVIDER_ROUND_CLOSEST);
};
static int
clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
struct regmap *regmap = pll->clkr.regmap;
int i, val = 0, div;
div = DIV_ROUND_UP_ULL(parent_rate, rate);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].div == div) {
val = pll->post_div_table[i].val;
break;
}
}
return regmap_update_bits(regmap, PLL_USER_CTL(pll),
PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
val << PLL_POST_DIV_SHIFT);
}
const struct clk_ops clk_trion_pll_postdiv_ops = {
.recalc_rate = clk_trion_pll_postdiv_recalc_rate,
.round_rate = clk_trion_pll_postdiv_round_rate,
.set_rate = clk_trion_pll_postdiv_set_rate,
};
EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops);
static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw,
unsigned long rate, unsigned long *prate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
return divider_round_rate(hw, rate, prate, pll->post_div_table,
pll->width, CLK_DIVIDER_ROUND_CLOSEST);
}
@@ -1089,12 +1296,7 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw,
if (val & PLL_VOTE_FSM_ENA)
return 0;
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
div = DIV_ROUND_UP_ULL(parent_rate, rate);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].div == div) {
val = pll->post_div_table[i].val;

View File

@@ -13,22 +13,27 @@ enum {
CLK_ALPHA_PLL_TYPE_HUAYRA,
CLK_ALPHA_PLL_TYPE_BRAMMO,
CLK_ALPHA_PLL_TYPE_FABIA,
CLK_ALPHA_PLL_TYPE_TRION,
CLK_ALPHA_PLL_TYPE_MAX,
};
enum {
PLL_OFF_L_VAL,
PLL_OFF_CAL_L_VAL,
PLL_OFF_ALPHA_VAL,
PLL_OFF_ALPHA_VAL_U,
PLL_OFF_USER_CTL,
PLL_OFF_USER_CTL_U,
PLL_OFF_USER_CTL_U1,
PLL_OFF_CONFIG_CTL,
PLL_OFF_CONFIG_CTL_U,
PLL_OFF_CONFIG_CTL_U1,
PLL_OFF_TEST_CTL,
PLL_OFF_TEST_CTL_U,
PLL_OFF_STATUS,
PLL_OFF_OPMODE,
PLL_OFF_FRAC,
PLL_OFF_CAL_VAL,
PLL_OFF_MAX_REGS
};
@@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
extern const struct clk_ops clk_trion_fixed_pll_ops;
extern const struct clk_ops clk_trion_pll_postdiv_ops;
#endif

View File

@@ -119,7 +119,7 @@ static int update_config(struct clk_rcg2 *rcg)
}
WARN(1, "%s: rcg didn't update its configuration.", name);
return 0;
return -EBUSY;
}
static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)

View File

@@ -95,7 +95,10 @@ static DEFINE_MUTEX(rpmh_clk_lock);
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpmh_ops, \
.name = #_name, \
.parent_names = (const char *[]){ "xo_board" }, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = "xo", \
.name = "xo_board", \
}, \
.num_parents = 1, \
}, \
}; \
@@ -110,7 +113,10 @@ static DEFINE_MUTEX(rpmh_clk_lock);
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpmh_ops, \
.name = #_name_active, \
.parent_names = (const char *[]){ "xo_board" }, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = "xo", \
.name = "xo_board", \
}, \
.num_parents = 1, \
}, \
}
@@ -368,6 +374,33 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
.num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
};
DEFINE_CLK_RPMH_ARC(sm8150, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk1, rf_clk1_ao, "rfclka1", 1);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk2, rf_clk2_ao, "rfclka2", 1);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
static struct clk_hw *sm8150_rpmh_clocks[] = {
[RPMH_CXO_CLK] = &sm8150_bi_tcxo.hw,
[RPMH_CXO_CLK_A] = &sm8150_bi_tcxo_ao.hw,
[RPMH_LN_BB_CLK2] = &sm8150_ln_bb_clk2.hw,
[RPMH_LN_BB_CLK2_A] = &sm8150_ln_bb_clk2_ao.hw,
[RPMH_LN_BB_CLK3] = &sm8150_ln_bb_clk3.hw,
[RPMH_LN_BB_CLK3_A] = &sm8150_ln_bb_clk3_ao.hw,
[RPMH_RF_CLK1] = &sm8150_rf_clk1.hw,
[RPMH_RF_CLK1_A] = &sm8150_rf_clk1_ao.hw,
[RPMH_RF_CLK2] = &sm8150_rf_clk2.hw,
[RPMH_RF_CLK2_A] = &sm8150_rf_clk2_ao.hw,
[RPMH_RF_CLK3] = &sm8150_rf_clk3.hw,
[RPMH_RF_CLK3_A] = &sm8150_rf_clk3_ao.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
.clks = sm8150_rpmh_clocks,
.num_clks = ARRAY_SIZE(sm8150_rpmh_clocks),
};
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@@ -447,6 +480,7 @@ static int clk_rpmh_probe(struct platform_device *pdev)
static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ }
};
MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);

View File

@@ -306,4 +306,24 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
}
EXPORT_SYMBOL_GPL(qcom_cc_probe);
int qcom_cc_probe_by_index(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 -ENOMEM;
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);
}
EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index);
MODULE_LICENSE("GPL v2");

View File

@@ -61,5 +61,7 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
extern int qcom_cc_probe_by_index(struct platform_device *pdev, int index,
const struct qcom_cc_desc *desc);
#endif

View File

@@ -1108,7 +1108,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@@ -1042,7 +1042,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_4,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@@ -1066,7 +1066,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_parent_names_1,
.num_parents = 3,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@@ -1057,7 +1057,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_parent_names_13,
.num_parents = 5,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@@ -1103,7 +1103,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_14,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@@ -2604,6 +2604,32 @@ static struct clk_branch gcc_usb_hs_system_clk = {
},
};
static struct clk_branch gcc_wdsp_q6ss_ahbs_clk = {
.halt_reg = 0x1e004,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1e004,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_wdsp_q6ss_ahbs_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_wdsp_q6ss_axim_clk = {
.halt_reg = 0x1e008,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1e008,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_wdsp_q6ss_axim_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_hw *gcc_qcs404_hws[] = {
&cxo.hw,
};
@@ -2749,6 +2775,9 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
[GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr,
[GCC_DCC_CLK] = &gcc_dcc_clk.clkr,
[GCC_DCC_XO_CLK] = &gcc_dcc_xo_clk.clkr,
[GCC_WCSS_Q6_AHB_CLK] = &gcc_wdsp_q6ss_ahbs_clk.clkr,
[GCC_WCSS_Q6_AXIM_CLK] = &gcc_wdsp_q6ss_axim_clk.clkr,
};
static const struct qcom_reset_map gcc_qcs404_resets[] = {
@@ -2774,6 +2803,7 @@ static const struct qcom_reset_map gcc_qcs404_resets[] = {
[GCC_PCIE_0_SLEEP_ARES] = { 0x3e040, 1 },
[GCC_PCIE_0_PIPE_ARES] = { 0x3e040, 0 },
[GCC_EMAC_BCR] = { 0x4e000 },
[GCC_WDSP_RESTART] = {0x19000},
};
static const struct regmap_config gcc_qcs404_regmap_config = {

View File

@@ -787,7 +787,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@@ -685,7 +685,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
.name = "gcc_sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_10,
.num_parents = 5,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@@ -709,7 +709,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
.name = "gcc_sdcc4_apps_clk_src",
.parent_names = gcc_parent_names_0,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

File diff suppressed because it is too large Load Diff

View File

@@ -112,25 +112,6 @@ static const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = {
.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;
@@ -139,14 +120,14 @@ static int lpass_cc_sdm845_probe(struct platform_device *pdev)
lpass_regmap_config.name = "cc";
desc = &lpass_cc_sdm845_desc;
ret = lpass_clocks_sdm845_probe(pdev, 0, desc);
ret = qcom_cc_probe_by_index(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);
return qcom_cc_probe_by_index(pdev, 1, desc);
}
static const struct of_device_id lpass_cc_sdm845_match_table[] = {

View File

@@ -96,7 +96,7 @@ static const struct regmap_config turingcc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x30000,
.max_register = 0x23004,
.fast_io = true,
};