提交 f5c7305d 编写于 作者: S Stephen Boyd

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
  ...
......@@ -18,17 +18,19 @@ Clocks:
-------
The Device Tree node representing the AP806 system controller provides
a number of clocks:
The Device Tree node representing the AP806/AP807 system controller
provides a number of clocks:
- 0: clock of CPU cluster 0
- 1: clock of CPU cluster 1
- 0: reference clock of CPU cluster 0
- 1: reference clock of CPU cluster 1
- 2: fixed PLL at 1200 Mhz
- 3: MSS clock, derived from the fixed PLL
Required properties:
- compatible: must be: "marvell,ap806-clock"
- compatible: must be one of:
* "marvell,ap806-clock"
* "marvell,ap807-clock"
- #clock-cells: must be set to 1
Pinctrl:
......@@ -143,3 +145,33 @@ ap_syscon1: system-controller@6f8000 {
#thermal-sensor-cells = <1>;
};
};
Cluster clocks:
---------------
Device Tree Clock bindings for cluster clock of Marvell
AP806/AP807. Each cluster contain up to 2 CPUs running at the same
frequency.
Required properties:
- compatible: must be one of:
* "marvell,ap806-cpu-clock"
* "marvell,ap807-cpu-clock"
- #clock-cells : should be set to 1.
- clocks : shall be the input parent clock(s) phandle for the clock
(one per cluster)
- reg: register range associated with the cluster clocks
ap_syscon1: system-controller@6f8000 {
compatible = "marvell,armada-ap806-syscon1", "syscon", "simple-mfd";
reg = <0x6f8000 0x1000>;
cpu_clk: clock-cpu@278 {
compatible = "marvell,ap806-cpu-clock";
clocks = <&ap_clk 0>, <&ap_clk 1>;
#clock-cells = <1>;
reg = <0x278 0xa30>;
};
};
......@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-apmixedsys"
- "mediatek,mt2712-apmixedsys", "syscon"
- "mediatek,mt6779-apmixedsys", "syscon"
- "mediatek,mt6797-apmixedsys"
- "mediatek,mt7622-apmixedsys"
- "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys"
......
......@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt6779-audio", "syscon"
- "mediatek,mt7622-audsys", "syscon"
- "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt8183-audiosys", "syscon"
......
......@@ -6,6 +6,7 @@ The MediaTek camsys controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt6779-camsys", "syscon"
- "mediatek,mt8183-camsys", "syscon"
- #clock-cells: Must be 1
......
......@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt2712-imgsys", "syscon"
- "mediatek,mt6779-imgsys", "syscon"
- "mediatek,mt6797-imgsys", "syscon"
- "mediatek,mt7623-imgsys", "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt8173-imgsys", "syscon"
......
......@@ -9,6 +9,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-infracfg", "syscon"
- "mediatek,mt2712-infracfg", "syscon"
- "mediatek,mt6779-infracfg_ao", "syscon"
- "mediatek,mt6797-infracfg", "syscon"
- "mediatek,mt7622-infracfg", "syscon"
- "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon"
......
Mediatek ipesys controller
============================
The Mediatek ipesys controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt6779-ipesys", "syscon"
- #clock-cells: Must be 1
The ipesys controller uses the common clk binding from
Documentation/devicetree/bindings/clock/clock-bindings.txt
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
Example:
ipesys: clock-controller@1b000000 {
compatible = "mediatek,mt6779-ipesys", "syscon";
reg = <0 0x1b000000 0 0x1000>;
#clock-cells = <1>;
};
......@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-mfgcfg", "syscon"
- "mediatek,mt6779-mfgcfg", "syscon"
- "mediatek,mt8183-mfgcfg", "syscon"
- #clock-cells: Must be 1
......
......@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt2712-mmsys", "syscon"
- "mediatek,mt6779-mmsys", "syscon"
- "mediatek,mt6797-mmsys", "syscon"
- "mediatek,mt7623-mmsys", "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt8173-mmsys", "syscon"
......
......@@ -14,6 +14,7 @@ Required Properties:
- "mediatek,mt7629-pericfg", "syscon"
- "mediatek,mt8135-pericfg", "syscon"
- "mediatek,mt8173-pericfg", "syscon"
- "mediatek,mt8183-pericfg", "syscon"
- #clock-cells: Must be 1
- #reset-cells: Must be 1
......
......@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-topckgen"
- "mediatek,mt2712-topckgen", "syscon"
- "mediatek,mt6779-topckgen", "syscon"
- "mediatek,mt6797-topckgen"
- "mediatek,mt7622-topckgen"
- "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen"
......
......@@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt2712-vdecsys", "syscon"
- "mediatek,mt6779-vdecsys", "syscon"
- "mediatek,mt6797-vdecsys", "syscon"
- "mediatek,mt7623-vdecsys", "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt8173-vdecsys", "syscon"
......
......@@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-vencsys", "syscon"
- "mediatek,mt6779-vencsys", "syscon"
- "mediatek,mt6797-vencsys", "syscon"
- "mediatek,mt8173-vencsys", "syscon"
- "mediatek,mt8183-vencsys", "syscon"
......
......@@ -22,6 +22,7 @@ Required Properties:
components.
- resets : phandle of the internal reset line
- #clock-cells : should be 1.
- #reset-cells : should be 1 on the g12a (and following) soc family
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
......
......@@ -11,6 +11,7 @@ Required Properties:
"amlogic,axg-clkc" for AXG SoC.
"amlogic,g12a-clkc" for G12A SoC.
"amlogic,g12b-clkc" for G12B SoC.
"amlogic,sm1-clkc" for SM1 SoC.
- clocks : list of clock phandle, one for each entry clock-names.
- clock-names : should contain the following:
* "xtal": the platform xtal
......
......@@ -23,6 +23,7 @@ Required properties :
"qcom,gcc-sdm630"
"qcom,gcc-sdm660"
"qcom,gcc-sdm845"
"qcom,gcc-sm8150"
- reg : shall contain base register location and length
- #clock-cells : shall contain 1
......@@ -38,6 +39,13 @@ Documentation/devicetree/bindings/thermal/qcom-tsens.txt
- protected-clocks : Protected clock specifier list as per common clock
binding.
For SM8150 only:
- clocks: a list of phandles and clock-specifier pairs,
one for each entry in clock-names.
- clock-names: "bi_tcxo" (required)
"sleep_clk" (optional)
"aud_ref_clock" (optional)
Example:
clock-controller@900000 {
compatible = "qcom,gcc-msm8960";
......@@ -71,3 +79,16 @@ Example of GCC with protected-clocks properties:
<GCC_LPASS_Q6_AXI_CLK>,
<GCC_LPASS_SWAY_CLK>;
};
Example of GCC with clocks
gcc: clock-controller@100000 {
compatible = "qcom,gcc-sm8150";
reg = <0x00100000 0x1f0000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
clock-names = "bi_tcxo",
"sleep_clk";
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
<&sleep_clk>;
};
......@@ -6,9 +6,14 @@ some Qualcomm Technologies Inc. SoCs. It accepts clock requests from
other hardware subsystems via RSC to control clocks.
Required properties :
- compatible : shall contain "qcom,sdm845-rpmh-clk"
- compatible : must be one of:
"qcom,sdm845-rpmh-clk"
"qcom,sm8150-rpmh-clk"
- #clock-cells : must contain 1
- clocks: a list of phandles and clock-specifier pairs,
one for each entry in clock-names.
- clock-names: Parent board clock: "xo".
Example :
......
......@@ -2489,6 +2489,12 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
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
......
......@@ -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);
......@@ -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);
......@@ -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);
......@@ -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);
......@@ -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
......
# 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
......
......@@ -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);
......
......@@ -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) { \
......
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
// 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);
此差异已折叠。
......@@ -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);
}
......
......@@ -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,
......
......@@ -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)
{
......
......@@ -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 */
......@@ -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);
}
# 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
......
......@@ -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
......
......@@ -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[] = {
......
此差异已折叠。
......@@ -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
......
......@@ -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);
......
// 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");
/* 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 */
// 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");
/* 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 */
......@@ -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 */
......@@ -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[] = {
......
此差异已折叠。
......@@ -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>
......
......@@ -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[] = {
......
此差异已折叠。
......@@ -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;
......
......@@ -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;
};
......
......@@ -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;
......
......@@ -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 {
......
此差异已折叠。
......@@ -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
......
......@@ -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
......
// 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);
// 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);
}
/* 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
......@@ -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
......
......@@ -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
......
此差异已折叠。
......@@ -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
......@@ -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)
......
此差异已折叠。
此差异已折叠。
......@@ -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
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册