diff options
124 files changed, 7303 insertions, 554 deletions
diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt index bd7a0fa5801b..ea827e8763de 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt @@ -15,6 +15,7 @@ Required Properties: - "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys" - "mediatek,mt7629-apmixedsys" - "mediatek,mt8135-apmixedsys" + - "mediatek,mt8167-apmixedsys", "syscon" - "mediatek,mt8173-apmixedsys" - "mediatek,mt8183-apmixedsys", "syscon" - "mediatek,mt8516-apmixedsys" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt index 38309db115f5..b32d374193c7 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,audsys.txt @@ -11,6 +11,7 @@ Required Properties: - "mediatek,mt6779-audio", "syscon" - "mediatek,mt7622-audsys", "syscon" - "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon" + - "mediatek,mt8167-audiosys", "syscon" - "mediatek,mt8183-audiosys", "syscon" - "mediatek,mt8516-audsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt index 1e1f00718a7d..dce4c9241932 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt @@ -12,6 +12,7 @@ Required Properties: - "mediatek,mt6779-imgsys", "syscon" - "mediatek,mt6797-imgsys", "syscon" - "mediatek,mt7623-imgsys", "mediatek,mt2701-imgsys", "syscon" + - "mediatek,mt8167-imgsys", "syscon" - "mediatek,mt8173-imgsys", "syscon" - "mediatek,mt8183-imgsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt index 49a968be1a80..eb3523c7a7be 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt @@ -16,6 +16,7 @@ Required Properties: - "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon" - "mediatek,mt7629-infracfg", "syscon" - "mediatek,mt8135-infracfg", "syscon" + - "mediatek,mt8167-infracfg", "syscon" - "mediatek,mt8173-infracfg", "syscon" - "mediatek,mt8183-infracfg", "syscon" - "mediatek,mt8516-infracfg", "syscon" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt index ad5f9d2f6818..054424fb64b4 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,mfgcfg.txt @@ -8,6 +8,7 @@ Required Properties: - compatible: Should be one of: - "mediatek,mt2712-mfgcfg", "syscon" - "mediatek,mt6779-mfgcfg", "syscon" + - "mediatek,mt8167-mfgcfg", "syscon" - "mediatek,mt8183-mfgcfg", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt index 9b0394cbbdc9..5ce7578cf274 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt @@ -15,6 +15,7 @@ Required Properties: - "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen" - "mediatek,mt7629-topckgen" - "mediatek,mt8135-topckgen" + - "mediatek,mt8167-topckgen", "syscon" - "mediatek,mt8173-topckgen" - "mediatek,mt8183-topckgen", "syscon" - "mediatek,mt8516-topckgen" diff --git a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt index 7894558b7a1c..98195169176a 100644 --- a/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt +++ b/Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt @@ -11,6 +11,7 @@ Required Properties: - "mediatek,mt6779-vdecsys", "syscon" - "mediatek,mt6797-vdecsys", "syscon" - "mediatek,mt7623-vdecsys", "mediatek,mt2701-vdecsys", "syscon" + - "mediatek,mt8167-vdecsys", "syscon" - "mediatek,mt8173-vdecsys", "syscon" - "mediatek,mt8183-vdecsys", "syscon" - #clock-cells: Must be 1 diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml index 4d382128b711..3b45344ed758 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml @@ -36,6 +36,8 @@ properties: - allwinner,sun9i-a80-ccu - allwinner,sun50i-a64-ccu - allwinner,sun50i-a64-r-ccu + - allwinner,sun50i-a100-ccu + - allwinner,sun50i-a100-r-ccu - allwinner,sun50i-h5-ccu - allwinner,sun50i-h6-ccu - allwinner,sun50i-h6-r-ccu @@ -78,6 +80,7 @@ if: - allwinner,sun8i-a83t-r-ccu - allwinner,sun8i-h3-r-ccu - allwinner,sun50i-a64-r-ccu + - allwinner,sun50i-a100-r-ccu - allwinner,sun50i-h6-r-ccu then: @@ -94,7 +97,9 @@ else: if: properties: compatible: - const: allwinner,sun50i-h6-ccu + enum: + - allwinner,sun50i-a100-ccu + - allwinner,sun50i-h6-ccu then: properties: diff --git a/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml new file mode 100644 index 000000000000..0cdf53f41f84 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/qcom,dispcc-sm8x50.yaml @@ -0,0 +1,93 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/qcom,dispcc-sm8x50.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Display Clock & Reset Controller Binding for SM8150/SM8250 + +maintainers: + - Jonathan Marek <jonathan@marek.ca> + +description: | + Qualcomm display clock control module which supports the clocks, resets and + power domains on SM8150 and SM8250. + + See also: + dt-bindings/clock/qcom,dispcc-sm8150.h + dt-bindings/clock/qcom,dispcc-sm8250.h + +properties: + compatible: + enum: + - qcom,sm8150-dispcc + - qcom,sm8250-dispcc + + clocks: + items: + - description: Board XO source + - description: Byte clock from DSI PHY0 + - description: Pixel clock from DSI PHY0 + - description: Byte clock from DSI PHY1 + - description: Pixel clock from DSI PHY1 + - description: Link clock from DP PHY + - description: VCO DIV clock from DP PHY + + clock-names: + items: + - const: bi_tcxo + - const: dsi0_phy_pll_out_byteclk + - const: dsi0_phy_pll_out_dsiclk + - const: dsi1_phy_pll_out_byteclk + - const: dsi1_phy_pll_out_dsiclk + - const: dp_phy_pll_link_clk + - const: dp_phy_pll_vco_div_clk + + '#clock-cells': + const: 1 + + '#reset-cells': + const: 1 + + '#power-domain-cells': + const: 1 + + reg: + maxItems: 1 + +required: + - compatible + - reg + - clocks + - clock-names + - '#clock-cells' + - '#reset-cells' + - '#power-domain-cells' + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/qcom,rpmh.h> + clock-controller@af00000 { + compatible = "qcom,sm8250-dispcc"; + reg = <0x0af00000 0x10000>; + clocks = <&rpmhcc RPMH_CXO_CLK>, + <&dsi0_phy 0>, + <&dsi0_phy 1>, + <&dsi1_phy 0>, + <&dsi1_phy 1>, + <&dp_phy 0>, + <&dp_phy 1>; + clock-names = "bi_tcxo", + "dsi0_phy_pll_out_byteclk", + "dsi0_phy_pll_out_dsiclk", + "dsi1_phy_pll_out_byteclk", + "dsi1_phy_pll_out_dsiclk", + "dp_phy_pll_link_clk", + "dp_phy_pll_vco_div_clk"; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; +... diff --git a/Documentation/devicetree/bindings/clock/qcom,sc7180-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,sc7180-videocc.yaml deleted file mode 100644 index 2feea2b91aa9..000000000000 --- a/Documentation/devicetree/bindings/clock/qcom,sc7180-videocc.yaml +++ /dev/null @@ -1,65 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/clock/qcom,sc7180-videocc.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm Video Clock & Reset Controller Binding for SC7180 - -maintainers: - - Taniya Das <tdas@codeaurora.org> - -description: | - Qualcomm video clock control module which supports the clocks, resets and - power domains on SC7180. - - See also dt-bindings/clock/qcom,videocc-sc7180.h. - -properties: - compatible: - const: qcom,sc7180-videocc - - clocks: - items: - - description: Board XO source - - clock-names: - items: - - const: bi_tcxo - - '#clock-cells': - const: 1 - - '#reset-cells': - const: 1 - - '#power-domain-cells': - const: 1 - - reg: - maxItems: 1 - -required: - - compatible - - reg - - clocks - - clock-names - - '#clock-cells' - - '#reset-cells' - - '#power-domain-cells' - -additionalProperties: false - -examples: - - | - #include <dt-bindings/clock/qcom,rpmh.h> - clock-controller@ab00000 { - compatible = "qcom,sc7180-videocc"; - reg = <0x0ab00000 0x10000>; - clocks = <&rpmhcc RPMH_CXO_CLK>; - clock-names = "bi_tcxo"; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - }; -... diff --git a/Documentation/devicetree/bindings/clock/qcom,sdm845-videocc.yaml b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml index f7a0cf53d5f0..567202942b88 100644 --- a/Documentation/devicetree/bindings/clock/qcom,sdm845-videocc.yaml +++ b/Documentation/devicetree/bindings/clock/qcom,videocc.yaml @@ -1,23 +1,31 @@ # SPDX-License-Identifier: GPL-2.0-only %YAML 1.2 --- -$id: http://devicetree.org/schemas/clock/qcom,sdm845-videocc.yaml# +$id: http://devicetree.org/schemas/clock/qcom,videocc.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: Qualcomm Video Clock & Reset Controller Binding for SDM845 +title: Qualcomm Video Clock & Reset Controller Binding maintainers: - Taniya Das <tdas@codeaurora.org> description: | Qualcomm video clock control module which supports the clocks, resets and - power domains on SDM845. + power domains on SDM845/SC7180/SM8150/SM8250. - See also dt-bindings/clock/qcom,videocc-sdm845.h. + See also: + dt-bindings/clock/qcom,videocc-sc7180.h + dt-bindings/clock/qcom,videocc-sdm845.h + dt-bindings/clock/qcom,videocc-sm8150.h + dt-bindings/clock/qcom,videocc-sm8250.h properties: compatible: - const: qcom,sdm845-videocc + enum: + - qcom,sc7180-videocc + - qcom,sdm845-videocc + - qcom,sm8150-videocc + - qcom,sm8250-videocc clocks: items: diff --git a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml index e13aee8ab61a..9b414fbde6d7 100644 --- a/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,cpg-mssr.yaml @@ -47,6 +47,7 @@ properties: - renesas,r8a77980-cpg-mssr # R-Car V3H - renesas,r8a77990-cpg-mssr # R-Car E3 - renesas,r8a77995-cpg-mssr # R-Car D3 + - renesas,r8a779a0-cpg-mssr # R-Car V3U reg: maxItems: 1 diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 4026fac9fac3..c715d4681a0b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -49,7 +49,7 @@ source "drivers/clk/versatile/Kconfig" config CLK_HSDK bool "PLL Driver for HSDK platform" - depends on OF || COMPILE_TEST + depends on ARC_SOC_HSDK || COMPILE_TEST depends on HAS_IOMEM help This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs @@ -373,6 +373,7 @@ source "drivers/clk/meson/Kconfig" source "drivers/clk/mvebu/Kconfig" source "drivers/clk/qcom/Kconfig" source "drivers/clk/renesas/Kconfig" +source "drivers/clk/rockchip/Kconfig" source "drivers/clk/samsung/Kconfig" source "drivers/clk/sifive/Kconfig" source "drivers/clk/sprd/Kconfig" diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c index c88ee20bee31..cb4a406ed15d 100644 --- a/drivers/clk/at91/at91sam9g45.c +++ b/drivers/clk/at91/at91sam9g45.c @@ -46,13 +46,6 @@ static const struct { { .n = "pck1", .p = "prog1", .id = 9 }, }; -static const struct clk_pcr_layout at91sam9g45_pcr_layout = { - .offset = 0x10c, - .cmd = BIT(12), - .pid_mask = GENMASK(5, 0), - .div_mask = GENMASK(17, 16), -}; - struct pck { char *n; u8 id; diff --git a/drivers/clk/at91/clk-main.c b/drivers/clk/at91/clk-main.c index 5c83e899084f..cfae2f59df66 100644 --- a/drivers/clk/at91/clk-main.c +++ b/drivers/clk/at91/clk-main.c @@ -437,12 +437,17 @@ static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index) return -EINVAL; regmap_read(regmap, AT91_CKGR_MOR, &tmp); - tmp &= ~MOR_KEY_MASK; if (index && !(tmp & AT91_PMC_MOSCSEL)) - regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_MOSCSEL); + tmp = AT91_PMC_MOSCSEL; else if (!index && (tmp & AT91_PMC_MOSCSEL)) - regmap_write(regmap, AT91_CKGR_MOR, tmp & ~AT91_PMC_MOSCSEL); + tmp = 0; + else + return 0; + + regmap_update_bits(regmap, AT91_CKGR_MOR, + AT91_PMC_MOSCSEL | MOR_KEY_MASK, + tmp | AT91_PMC_KEY); while (!clk_sam9x5_main_ready(regmap)) cpu_relax(); diff --git a/drivers/clk/at91/clk-peripheral.c b/drivers/clk/at91/clk-peripheral.c index 7867eaf0447f..7a27ba8e0577 100644 --- a/drivers/clk/at91/clk-peripheral.c +++ b/drivers/clk/at91/clk-peripheral.c @@ -112,8 +112,8 @@ at91_clk_register_peripheral(struct regmap *regmap, const char *name, init.name = name; init.ops = &peripheral_ops; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); + init.parent_names = &parent_name; + init.num_parents = 1; init.flags = 0; periph->id = id; diff --git a/drivers/clk/at91/clk-sam9x60-pll.c b/drivers/clk/at91/clk-sam9x60-pll.c index b473298ef7e6..78f458a7b2ef 100644 --- a/drivers/clk/at91/clk-sam9x60-pll.c +++ b/drivers/clk/at91/clk-sam9x60-pll.c @@ -331,7 +331,7 @@ static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core, struct clk_hw *parent = clk_hw_get_parent(&core->hw); unsigned long tmp_rate, tmp_parent_rate, tmp_diff; long best_diff = -1, best_rate = -EINVAL; - u32 divid, best_div; + u32 divid; if (!rate) return 0; @@ -352,7 +352,6 @@ static long sam9x60_div_pll_compute_div(struct sam9x60_pll_core *core, *parent_rate = tmp_parent_rate; best_rate = tmp_rate; best_diff = tmp_diff; - best_div = divid; } if (!best_diff) diff --git a/drivers/clk/at91/sam9x60.c b/drivers/clk/at91/sam9x60.c index ab6318c0589e..3c4c95603595 100644 --- a/drivers/clk/at91/sam9x60.c +++ b/drivers/clk/at91/sam9x60.c @@ -279,7 +279,7 @@ static void __init sam9x60_pmc_setup(struct device_node *np) parent_names[3] = "masterck"; parent_names[4] = "pllack_divck"; parent_names[5] = "upllck_divck"; - for (i = 0; i < 8; i++) { + for (i = 0; i < 2; i++) { char name[6]; snprintf(name, sizeof(name), "prog%d", i); diff --git a/drivers/clk/baikal-t1/clk-ccu-pll.c b/drivers/clk/baikal-t1/clk-ccu-pll.c index 1eec8c0b8f50..2445d4b12baf 100644 --- a/drivers/clk/baikal-t1/clk-ccu-pll.c +++ b/drivers/clk/baikal-t1/clk-ccu-pll.c @@ -51,11 +51,13 @@ struct ccu_pll_info { }; /* - * Mark as critical all PLLs except Ethernet one. CPU and DDR PLLs are sources - * of CPU cores and DDR controller reference clocks, due to which they - * obviously shouldn't be ever gated. SATA and PCIe PLLs are the parents of - * APB-bus and DDR controller AXI-bus clocks. If they are gated the system will - * be unusable. + * Alas we have to mark all PLLs as critical. CPU and DDR PLLs are sources of + * CPU cores and DDR controller reference clocks, due to which they obviously + * shouldn't be ever gated. SATA and PCIe PLLs are the parents of APB-bus and + * DDR controller AXI-bus clocks. If they are gated the system will be + * unusable. Moreover disabling SATA and Ethernet PLLs causes automatic reset + * of the corresponding subsystems. So until we aren't ready to re-initialize + * all the devices consuming those PLLs, they will be marked as critical too. */ static const struct ccu_pll_info pll_info[] = { CCU_PLL_INFO(CCU_CPU_PLL, "cpu_pll", "ref_clk", CCU_CPU_PLL_BASE, @@ -67,7 +69,7 @@ static const struct ccu_pll_info pll_info[] = { CCU_PLL_INFO(CCU_PCIE_PLL, "pcie_pll", "ref_clk", CCU_PCIE_PLL_BASE, CLK_IS_CRITICAL), CCU_PLL_INFO(CCU_ETH_PLL, "eth_pll", "ref_clk", CCU_ETH_PLL_BASE, - CLK_SET_RATE_GATE) + CLK_IS_CRITICAL | CLK_SET_RATE_GATE) }; struct ccu_pll_data { diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 3439bc65bb4e..1ac803e14fa3 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -1338,8 +1338,10 @@ static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman, pll->hw.init = &init; ret = devm_clk_hw_register(cprman->dev, &pll->hw); - if (ret) + if (ret) { + kfree(pll); return NULL; + } return &pll->hw; } diff --git a/drivers/clk/bcm/clk-raspberrypi.c b/drivers/clk/bcm/clk-raspberrypi.c index 5cc82954e1ce..f89b9cfc4309 100644 --- a/drivers/clk/bcm/clk-raspberrypi.c +++ b/drivers/clk/bcm/clk-raspberrypi.c @@ -271,6 +271,7 @@ static int raspberrypi_discover_clocks(struct raspberrypi_clk *rpi, case RPI_FIRMWARE_CORE_CLK_ID: case RPI_FIRMWARE_M2MC_CLK_ID: case RPI_FIRMWARE_V3D_CLK_ID: + case RPI_FIRMWARE_PIXEL_BVB_CLK_ID: hw = raspberrypi_clk_register(rpi, clks->parent, clks->id); if (IS_ERR(hw)) diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index 96f351785b41..14d803e6af62 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -27,19 +27,23 @@ #define AXI_CLKGEN_V2_DRP_STATUS_BUSY BIT(16) +#define MMCM_REG_CLKOUT5_2 0x07 #define MMCM_REG_CLKOUT0_1 0x08 #define MMCM_REG_CLKOUT0_2 0x09 +#define MMCM_REG_CLKOUT6_2 0x13 #define MMCM_REG_CLK_FB1 0x14 #define MMCM_REG_CLK_FB2 0x15 #define MMCM_REG_CLK_DIV 0x16 #define MMCM_REG_LOCK1 0x18 #define MMCM_REG_LOCK2 0x19 #define MMCM_REG_LOCK3 0x1a +#define MMCM_REG_POWER 0x28 #define MMCM_REG_FILTER1 0x4e #define MMCM_REG_FILTER2 0x4f #define MMCM_CLKOUT_NOCOUNT BIT(6) +#define MMCM_CLK_DIV_DIVIDE BIT(11) #define MMCM_CLK_DIV_NOCOUNT BIT(12) struct axi_clkgen { @@ -107,6 +111,8 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, unsigned long d, d_min, d_max, _d_min, _d_max; unsigned long m, m_min, m_max; unsigned long f, dout, best_f, fvco; + unsigned long fract_shift = 0; + unsigned long fvco_min_fract, fvco_max_fract; fin /= 1000; fout /= 1000; @@ -119,42 +125,89 @@ static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1); d_max = min_t(unsigned long, fin / fpfd_min, 80); - m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1); - m_max = min_t(unsigned long, fvco_max * d_max / fin, 64); +again: + fvco_min_fract = fvco_min << fract_shift; + fvco_max_fract = fvco_max << fract_shift; + + m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min_fract, fin) * d_min, 1); + m_max = min_t(unsigned long, fvco_max_fract * d_max / fin, 64 << fract_shift); for (m = m_min; m <= m_max; m++) { - _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max)); - _d_max = min(d_max, fin * m / fvco_min); + _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max_fract)); + _d_max = min(d_max, fin * m / fvco_min_fract); for (d = _d_min; d <= _d_max; d++) { fvco = fin * m / d; dout = DIV_ROUND_CLOSEST(fvco, fout); - dout = clamp_t(unsigned long, dout, 1, 128); + dout = clamp_t(unsigned long, dout, 1, 128 << fract_shift); f = fvco / dout; if (abs(f - fout) < abs(best_f - fout)) { best_f = f; *best_d = d; - *best_m = m; - *best_dout = dout; + *best_m = m << (3 - fract_shift); + *best_dout = dout << (3 - fract_shift); if (best_f == fout) return; } } } + + /* Lets see if we find a better setting in fractional mode */ + if (fract_shift == 0) { + fract_shift = 3; + goto again; + } } -static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low, - unsigned int *high, unsigned int *edge, unsigned int *nocount) +struct axi_clkgen_div_params { + unsigned int low; + unsigned int high; + unsigned int edge; + unsigned int nocount; + unsigned int frac_en; + unsigned int frac; + unsigned int frac_wf_f; + unsigned int frac_wf_r; + unsigned int frac_phase; +}; + +static void axi_clkgen_calc_clk_params(unsigned int divider, + unsigned int frac_divider, struct axi_clkgen_div_params *params) { - if (divider == 1) - *nocount = 1; - else - *nocount = 0; - *high = divider / 2; - *edge = divider % 2; - *low = divider - *high; + memset(params, 0x0, sizeof(*params)); + + if (divider == 1) { + params->nocount = 1; + return; + } + + if (frac_divider == 0) { + params->high = divider / 2; + params->edge = divider % 2; + params->low = divider - params->high; + } else { + params->frac_en = 1; + params->frac = frac_divider; + + params->high = divider / 2; + params->edge = divider % 2; + params->low = params->high; + + if (params->edge == 0) { + params->high--; + params->frac_wf_r = 1; + } + + if (params->edge == 0 || frac_divider == 1) + params->low--; + if (((params->edge == 0) ^ (frac_divider == 1)) || + (divider == 2 && frac_divider == 1)) + params->frac_wf_f = 1; + + params->frac_phase = params->edge * 4 + frac_divider / 2; + } } static void axi_clkgen_write(struct axi_clkgen *axi_clkgen, @@ -246,15 +299,29 @@ static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) return container_of(clk_hw, struct axi_clkgen, clk_hw); } +static void axi_clkgen_set_div(struct axi_clkgen *axi_clkgen, + unsigned int reg1, unsigned int reg2, unsigned int reg3, + struct axi_clkgen_div_params *params) +{ + axi_clkgen_mmcm_write(axi_clkgen, reg1, + (params->high << 6) | params->low, 0xefff); + axi_clkgen_mmcm_write(axi_clkgen, reg2, + (params->frac << 12) | (params->frac_en << 11) | + (params->frac_wf_r << 10) | (params->edge << 7) | + (params->nocount << 6), 0x7fff); + if (reg3 != 0) { + axi_clkgen_mmcm_write(axi_clkgen, reg3, + (params->frac_phase << 11) | (params->frac_wf_f << 10), 0x3c00); + } +} + static int axi_clkgen_set_rate(struct clk_hw *clk_hw, unsigned long rate, unsigned long parent_rate) { struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); unsigned int d, m, dout; - unsigned int nocount; - unsigned int high; - unsigned int edge; - unsigned int low; + struct axi_clkgen_div_params params; + uint32_t power = 0; uint32_t filter; uint32_t lock; @@ -266,24 +333,26 @@ static int axi_clkgen_set_rate(struct clk_hw *clk_hw, if (d == 0 || dout == 0 || m == 0) return -EINVAL; + if ((dout & 0x7) != 0 || (m & 0x7) != 0) + power |= 0x9800; + + axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_POWER, power, 0x9800); + filter = axi_clkgen_lookup_filter(m - 1); lock = axi_clkgen_lookup_lock(m - 1); - axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); - axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_1, - (high << 6) | low, 0xefff); - axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLKOUT0_2, - (edge << 7) | (nocount << 6), 0x03ff); + axi_clkgen_calc_clk_params(dout >> 3, dout & 0x7, ¶ms); + axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLKOUT0_1, MMCM_REG_CLKOUT0_2, + MMCM_REG_CLKOUT5_2, ¶ms); - axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); + axi_clkgen_calc_clk_params(d, 0, ¶ms); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_DIV, - (edge << 13) | (nocount << 12) | (high << 6) | low, 0x3fff); + (params.edge << 13) | (params.nocount << 12) | + (params.high << 6) | params.low, 0x3fff); - axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); - axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB1, - (high << 6) | low, 0xefff); - axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_CLK_FB2, - (edge << 7) | (nocount << 6), 0x03ff); + axi_clkgen_calc_clk_params(m >> 3, m & 0x7, ¶ms); + axi_clkgen_set_div(axi_clkgen, MMCM_REG_CLK_FB1, MMCM_REG_CLK_FB2, + MMCM_REG_CLKOUT6_2, ¶ms); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK1, lock & 0x3ff, 0x3ff); axi_clkgen_mmcm_write(axi_clkgen, MMCM_REG_LOCK2, @@ -313,35 +382,51 @@ static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, return min_t(unsigned long long, tmp, LONG_MAX); } +static unsigned int axi_clkgen_get_div(struct axi_clkgen *axi_clkgen, + unsigned int reg1, unsigned int reg2) +{ + unsigned int val1, val2; + unsigned int div; + + axi_clkgen_mmcm_read(axi_clkgen, reg2, &val2); + if (val2 & MMCM_CLKOUT_NOCOUNT) + return 8; + + axi_clkgen_mmcm_read(axi_clkgen, reg1, &val1); + + div = (val1 & 0x3f) + ((val1 >> 6) & 0x3f); + div <<= 3; + + if (val2 & MMCM_CLK_DIV_DIVIDE) { + if ((val2 & BIT(7)) && (val2 & 0x7000) != 0x1000) + div += 8; + else + div += 16; + + div += (val2 >> 12) & 0x7; + } + + return div; +} + static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, unsigned long parent_rate) { struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); unsigned int d, m, dout; - unsigned int reg; unsigned long long tmp; + unsigned int val; - axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_2, ®); - if (reg & MMCM_CLKOUT_NOCOUNT) { - dout = 1; - } else { - axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLKOUT0_1, ®); - dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); - } + dout = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLKOUT0_1, + MMCM_REG_CLKOUT0_2); + m = axi_clkgen_get_div(axi_clkgen, MMCM_REG_CLK_FB1, + MMCM_REG_CLK_FB2); - axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, ®); - if (reg & MMCM_CLK_DIV_NOCOUNT) + axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_DIV, &val); + if (val & MMCM_CLK_DIV_NOCOUNT) d = 1; else - d = (reg & 0x3f) + ((reg >> 6) & 0x3f); - - axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB2, ®); - if (reg & MMCM_CLKOUT_NOCOUNT) { - m = 1; - } else { - axi_clkgen_mmcm_read(axi_clkgen, MMCM_REG_CLK_FB1, ®); - m = (reg & 0x3f) + ((reg >> 6) & 0x3f); - } + d = (val & 0x3f) + ((val >> 6) & 0x3f); if (d == 0 || dout == 0) return 0; diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 8b343e59dc61..910e6e74ae90 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -206,6 +206,7 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node) /** * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock + * @node: device node for the clock */ void __init of_fixed_factor_clk_setup(struct device_node *node) { diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c index 77499a27c8fb..45501637705c 100644 --- a/drivers/clk/clk-fixed-rate.c +++ b/drivers/clk/clk-fixed-rate.c @@ -168,6 +168,7 @@ static struct clk_hw *_of_fixed_clk_setup(struct device_node *node) /** * of_fixed_clk_setup() - Setup function for simple fixed rate clock + * @node: device node for the clock */ void __init of_fixed_clk_setup(struct device_node *node) { diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 5942e9874bc0..46101c6a20f2 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -31,7 +31,7 @@ #define CGA_PLL4 4 /* only on clockgen-1.0, which lacks CGB */ #define CGB_PLL1 4 #define CGB_PLL2 5 -#define MAX_PLL_DIV 16 +#define MAX_PLL_DIV 32 struct clockgen_pll_div { struct clk *clk; diff --git a/drivers/clk/clk-s2mps11.c b/drivers/clk/clk-s2mps11.c index 2ce370c804aa..aa21371f9104 100644 --- a/drivers/clk/clk-s2mps11.c +++ b/drivers/clk/clk-s2mps11.c @@ -267,18 +267,7 @@ static struct platform_driver s2mps11_clk_driver = { .remove = s2mps11_clk_remove, .id_table = s2mps11_clk_id, }; - -static int __init s2mps11_clk_init(void) -{ - return platform_driver_register(&s2mps11_clk_driver); -} -subsys_initcall(s2mps11_clk_init); - -static void __exit s2mps11_clk_cleanup(void) -{ - platform_driver_unregister(&s2mps11_clk_driver); -} -module_exit(s2mps11_clk_cleanup); +module_platform_driver(s2mps11_clk_driver); MODULE_DESCRIPTION("S2MPS11 Clock Driver"); MODULE_AUTHOR("Yadwinder Singh Brar <yadi.brar@samsung.com>"); diff --git a/drivers/clk/clk-si5341.c b/drivers/clk/clk-si5341.c index 3d7acab9d280..e0446e66fa64 100644 --- a/drivers/clk/clk-si5341.c +++ b/drivers/clk/clk-si5341.c @@ -883,11 +883,9 @@ static int si5341_output_set_parent(struct clk_hw *hw, u8 index) static u8 si5341_output_get_parent(struct clk_hw *hw) { struct clk_si5341_output *output = to_clk_si5341_output(hw); - int err; u32 val; - err = regmap_read(output->data->regmap, - SI5341_OUT_MUX_SEL(output), &val); + regmap_read(output->data->regmap, SI5341_OUT_MUX_SEL(output), &val); return val & 0x7; } diff --git a/drivers/clk/davinci/da8xx-cfgchip.c b/drivers/clk/davinci/da8xx-cfgchip.c index bdc52364b421..77d18276bfe8 100644 --- a/drivers/clk/davinci/da8xx-cfgchip.c +++ b/drivers/clk/davinci/da8xx-cfgchip.c @@ -571,6 +571,7 @@ static const struct clk_ops da8xx_usb1_clk48_ops = { /** * da8xx_cfgchip_register_usb1_clk48 - Register a new USB 1.1 PHY clock + * @dev: The device * @regmap: The CFGCHIP regmap */ static struct da8xx_usb1_clk48 * diff --git a/drivers/clk/ingenic/cgu.c b/drivers/clk/ingenic/cgu.c index d7981b670221..dac6edc670cc 100644 --- a/drivers/clk/ingenic/cgu.c +++ b/drivers/clk/ingenic/cgu.c @@ -12,15 +12,24 @@ #include <linux/clkdev.h> #include <linux/delay.h> #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/math64.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/slab.h> #include <linux/spinlock.h> +#include <linux/time.h> + #include "cgu.h" #define MHZ (1000 * 1000) +static inline const struct ingenic_cgu_clk_info * +to_clk_info(struct ingenic_clk *clk) +{ + return &clk->cgu->clock_info[clk->idx]; +} + /** * ingenic_cgu_gate_get() - get the value of clock gate register bit * @cgu: reference to the CGU whose registers should be read @@ -71,14 +80,13 @@ static unsigned long ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; const struct ingenic_cgu_pll_info *pll_info; unsigned m, n, od_enc, od; bool bypass; u32 ctl; - clk_info = &cgu->clock_info[ingenic_clk->idx]; BUG_ON(clk_info->type != CGU_CLK_PLL); pll_info = &clk_info->pll; @@ -144,18 +152,6 @@ ingenic_pll_calc(const struct ingenic_cgu_clk_info *clk_info, n * od); } -static inline const struct ingenic_cgu_clk_info *to_clk_info( - struct ingenic_clk *ingenic_clk) -{ - struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; - - clk_info = &cgu->clock_info[ingenic_clk->idx]; - BUG_ON(clk_info->type != CGU_CLK_PLL); - - return clk_info; -} - static long ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate, unsigned long *prate) @@ -166,6 +162,16 @@ ingenic_pll_round_rate(struct clk_hw *hw, unsigned long req_rate, return ingenic_pll_calc(clk_info, req_rate, *prate, NULL, NULL, NULL); } +static inline int ingenic_pll_check_stable(struct ingenic_cgu *cgu, + const struct ingenic_cgu_pll_info *pll_info) +{ + u32 ctl; + + return readl_poll_timeout(cgu->base + pll_info->reg, ctl, + ctl & BIT(pll_info->stable_bit), + 0, 100 * USEC_PER_MSEC); +} + static int ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate, unsigned long parent_rate) @@ -176,6 +182,7 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate, const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll; unsigned long rate, flags; unsigned int m, n, od; + int ret = 0; u32 ctl; rate = ingenic_pll_calc(clk_info, req_rate, parent_rate, @@ -197,9 +204,14 @@ ingenic_pll_set_rate(struct clk_hw *hw, unsigned long req_rate, ctl |= pll_info->od_encoding[od - 1] << pll_info->od_shift; writel(ctl, cgu->base + pll_info->reg); + + /* If the PLL is enabled, verify that it's stable */ + if (ctl & BIT(pll_info->enable_bit)) + ret = ingenic_pll_check_stable(cgu, pll_info); + spin_unlock_irqrestore(&cgu->lock, flags); - return 0; + return ret; } static int ingenic_pll_enable(struct clk_hw *hw) @@ -208,9 +220,8 @@ static int ingenic_pll_enable(struct clk_hw *hw) struct ingenic_cgu *cgu = ingenic_clk->cgu; const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); const struct ingenic_cgu_pll_info *pll_info = &clk_info->pll; - const unsigned int timeout = 100; unsigned long flags; - unsigned int i; + int ret; u32 ctl; spin_lock_irqsave(&cgu->lock, flags); @@ -226,20 +237,10 @@ static int ingenic_pll_enable(struct clk_hw *hw) writel(ctl, cgu->base + pll_info->reg); - /* wait for the PLL to stabilise */ - for (i = 0; i < timeout; i++) { - ctl = readl(cgu->base + pll_info->reg); - if (ctl & BIT(pll_info->stable_bit)) - break; - mdelay(1); - } - + ret = ingenic_pll_check_stable(cgu, pll_info); spin_unlock_irqrestore(&cgu->lock, flags); - if (i == timeout) - return -EBUSY; - - return 0; + return ret; } static void ingenic_pll_disable(struct clk_hw *hw) @@ -290,13 +291,11 @@ static const struct clk_ops ingenic_pll_ops = { static u8 ingenic_clk_get_parent(struct clk_hw *hw) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; u32 reg; u8 i, hw_idx, idx = 0; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_MUX) { reg = readl(cgu->base + clk_info->mux.reg); hw_idx = (reg >> clk_info->mux.shift) & @@ -318,14 +317,12 @@ static u8 ingenic_clk_get_parent(struct clk_hw *hw) static int ingenic_clk_set_parent(struct clk_hw *hw, u8 idx) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; unsigned long flags; u8 curr_idx, hw_idx, num_poss; u32 reg, mask; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_MUX) { /* * Convert the parent index to the hardware index by adding @@ -368,13 +365,11 @@ static unsigned long ingenic_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; unsigned long rate = parent_rate; u32 div_reg, div; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_DIV) { div_reg = readl(cgu->base + clk_info->div.reg); div = (div_reg >> clk_info->div.shift) & @@ -443,35 +438,41 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate, unsigned long *parent_rate) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); - struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); unsigned int div = 1; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_DIV) div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate); else if (clk_info->type & CGU_CLK_FIXDIV) div = clk_info->fixdiv.div; + else if (clk_hw_can_set_rate_parent(hw)) + *parent_rate = req_rate; return DIV_ROUND_UP(*parent_rate, div); } +static inline int ingenic_clk_check_stable(struct ingenic_cgu *cgu, + const struct ingenic_cgu_clk_info *clk_info) +{ + u32 reg; + + return readl_poll_timeout(cgu->base + clk_info->div.reg, reg, + !(reg & BIT(clk_info->div.busy_bit)), + 0, 100 * USEC_PER_MSEC); +} + static int ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, unsigned long parent_rate) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; - const unsigned timeout = 100; unsigned long rate, flags; - unsigned int hw_div, div, i; + unsigned int hw_div, div; u32 reg, mask; int ret = 0; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_DIV) { div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate); rate = DIV_ROUND_UP(parent_rate, div); @@ -504,16 +505,8 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, writel(reg, cgu->base + clk_info->div.reg); /* wait for the change to take effect */ - if (clk_info->div.busy_bit != -1) { - for (i = 0; i < timeout; i++) { - reg = readl(cgu->base + clk_info->div.reg); - if (!(reg & BIT(clk_info->div.busy_bit))) - break; - mdelay(1); - } - if (i == timeout) - ret = -EBUSY; - } + if (clk_info->div.busy_bit != -1) + ret = ingenic_clk_check_stable(cgu, clk_info); spin_unlock_irqrestore(&cgu->lock, flags); return ret; @@ -525,12 +518,10 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate, static int ingenic_clk_enable(struct clk_hw *hw) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; unsigned long flags; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_GATE) { /* ungate the clock */ spin_lock_irqsave(&cgu->lock, flags); @@ -547,12 +538,10 @@ static int ingenic_clk_enable(struct clk_hw *hw) static void ingenic_clk_disable(struct clk_hw *hw) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; unsigned long flags; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_GATE) { /* gate the clock */ spin_lock_irqsave(&cgu->lock, flags); @@ -564,12 +553,10 @@ static void ingenic_clk_disable(struct clk_hw *hw) static int ingenic_clk_is_enabled(struct clk_hw *hw) { struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw); + const struct ingenic_cgu_clk_info *clk_info = to_clk_info(ingenic_clk); struct ingenic_cgu *cgu = ingenic_clk->cgu; - const struct ingenic_cgu_clk_info *clk_info; int enabled = 1; - clk_info = &cgu->clock_info[ingenic_clk->idx]; - if (clk_info->type & CGU_CLK_GATE) enabled = !ingenic_cgu_gate_get(cgu, &clk_info->gate); @@ -644,6 +631,13 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) caps = clk_info->type; + if (caps & CGU_CLK_DIV) { + caps &= ~CGU_CLK_DIV; + } else if (!(caps & CGU_CLK_CUSTOM)) { + /* pass rate changes to the parent clock */ + clk_init.flags |= CLK_SET_RATE_PARENT; + } + if (caps & (CGU_CLK_MUX | CGU_CLK_CUSTOM)) { clk_init.num_parents = 0; @@ -683,7 +677,6 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) } } else if (caps & CGU_CLK_PLL) { clk_init.ops = &ingenic_pll_ops; - clk_init.flags |= CLK_SET_RATE_GATE; caps &= ~CGU_CLK_PLL; @@ -706,13 +699,6 @@ static int ingenic_register_clock(struct ingenic_cgu *cgu, unsigned idx) caps &= ~(CGU_CLK_MUX | CGU_CLK_MUX_GLITCHFREE); } - if (caps & CGU_CLK_DIV) { - caps &= ~CGU_CLK_DIV; - } else { - /* pass rate changes to the parent clock */ - clk_init.flags |= CLK_SET_RATE_PARENT; - } - if (caps) { pr_err("%s: unknown clock type 0x%x\n", __func__, caps); goto out; diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 2ad26cb927fd..aaf31abe1c8f 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -54,6 +54,8 @@ struct sci_clk_provider { * @provider: Master clock provider * @flags: Flags for the clock * @node: Link for handling clocks probed via DT + * @cached_req: Cached requested freq for determine rate calls + * @cached_res: Cached result freq for determine rate calls */ struct sci_clk { struct clk_hw hw; @@ -63,6 +65,8 @@ struct sci_clk { struct sci_clk_provider *provider; u8 flags; struct list_head node; + unsigned long cached_req; + unsigned long cached_res; }; #define to_sci_clk(_hw) container_of(_hw, struct sci_clk, hw) @@ -175,6 +179,11 @@ static int sci_clk_determine_rate(struct clk_hw *hw, int ret; u64 new_rate; + if (clk->cached_req && clk->cached_req == req->rate) { + req->rate = clk->cached_res; + return 0; + } + ret = clk->provider->ops->get_best_match_freq(clk->provider->sci, clk->dev_id, clk->clk_id, @@ -189,6 +198,9 @@ static int sci_clk_determine_rate(struct clk_hw *hw, return ret; } + clk->cached_req = req->rate; + clk->cached_res = new_rate; + req->rate = new_rate; return 0; @@ -209,7 +221,8 @@ static int sci_clk_set_rate(struct clk_hw *hw, unsigned long rate, struct sci_clk *clk = to_sci_clk(hw); return clk->provider->ops->set_freq(clk->provider->sci, clk->dev_id, - clk->clk_id, rate, rate, rate); + clk->clk_id, rate / 10 * 9, rate, + rate / 10 * 11); } /** @@ -249,6 +262,8 @@ static int sci_clk_set_parent(struct clk_hw *hw, u8 index) { struct sci_clk *clk = to_sci_clk(hw); + clk->cached_req = 0; + return clk->provider->ops->set_parent(clk->provider->sci, clk->dev_id, clk->clk_id, index + 1 + clk->clk_id); @@ -522,7 +537,7 @@ static int ti_sci_scan_clocks_from_dt(struct sci_clk_provider *provider) np = of_find_node_with_property(np, *clk_name); if (!np) { clk_name++; - break; + continue; } if (!of_device_is_available(np)) diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 89ceb2fbc7c4..ce8475098b31 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -352,6 +352,54 @@ config COMMON_CLK_MT8135 help This driver supports MediaTek MT8135 clocks. +config COMMON_CLK_MT8167 + bool "Clock driver for MediaTek MT8167" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 basic clocks. + +config COMMON_CLK_MT8167_AUDSYS + bool "Clock driver for MediaTek MT8167 audsys" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 audsys clocks. + +config COMMON_CLK_MT8167_IMGSYS + bool "Clock driver for MediaTek MT8167 imgsys" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 imgsys clocks. + +config COMMON_CLK_MT8167_MFGCFG + bool "Clock driver for MediaTek MT8167 mfgcfg" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 mfgcfg clocks. + +config COMMON_CLK_MT8167_MMSYS + bool "Clock driver for MediaTek MT8167 mmsys" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 mmsys clocks. + +config COMMON_CLK_MT8167_VDECSYS + bool "Clock driver for MediaTek MT8167 vdecsys" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 vdecsys clocks. + config COMMON_CLK_MT8173 bool "Clock driver for MediaTek MT8173" depends on ARCH_MEDIATEK || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 959b556d32ea..3b0c2be73824 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -47,6 +47,12 @@ obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o +obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o +obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o +obj-$(CONFIG_COMMON_CLK_MT8167_IMGSYS) += clk-mt8167-img.o +obj-$(CONFIG_COMMON_CLK_MT8167_MFGCFG) += clk-mt8167-mfgcfg.o +obj-$(CONFIG_COMMON_CLK_MT8167_MMSYS) += clk-mt8167-mm.o +obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c index db8db1b3b79d..d77ea5aff292 100644 --- a/drivers/clk/mediatek/clk-mt6765.c +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -909,7 +909,6 @@ static struct platform_driver clk_mt6765_drv = { .probe = clk_mt6765_probe, .driver = { .name = "clk-mt6765", - .owner = THIS_MODULE, .of_match_table = of_match_clk_mt6765, }, }; diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c index 9766cccf5844..6e0d3a166729 100644 --- a/drivers/clk/mediatek/clk-mt6779.c +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -919,6 +919,8 @@ static const struct mtk_gate infra_clks[] = { "pwm_sel", 19), GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm", "pwm_sel", 21), + GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0", + "uart_sel", 22), GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23), GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2", diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c index f35389a11af1..428eb24ffec5 100644 --- a/drivers/clk/mediatek/clk-mt6797.c +++ b/drivers/clk/mediatek/clk-mt6797.c @@ -582,7 +582,7 @@ CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg", static int mtk_infrasys_init(struct platform_device *pdev) { - int r, i; + int i; struct device_node *node = pdev->dev.of_node; if (!infra_clk_data) { @@ -599,11 +599,7 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), infra_clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); - if (r) - return r; - - return 0; + return of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data); } #define MT6797_PLL_FMAX (3000UL * MHZ) diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c index b73bdf152836..a0ee079670c7 100644 --- a/drivers/clk/mediatek/clk-mt7629.c +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -601,7 +601,6 @@ static int mtk_infrasys_init(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; struct clk_onecell_data *clk_data; - int r; clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); @@ -611,12 +610,8 @@ static int mtk_infrasys_init(struct platform_device *pdev) mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), clk_data); - r = of_clk_add_provider(node, of_clk_src_onecell_get, - clk_data); - if (r) - return r; - - return 0; + return of_clk_add_provider(node, of_clk_src_onecell_get, + clk_data); } static int mtk_pericfg_init(struct platform_device *pdev) diff --git a/drivers/clk/mediatek/clk-mt8167-aud.c b/drivers/clk/mediatek/clk-mt8167-aud.c new file mode 100644 index 000000000000..3f7bf6485792 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-aud.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.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/mt8167-clk.h> + +static const struct mtk_gate_regs aud_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_AUD(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &aud_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate aud_clks[] __initconst = { + GATE_AUD(CLK_AUD_AFE, "aud_afe", "clk26m_ck", 2), + GATE_AUD(CLK_AUD_I2S, "aud_i2s", "i2s_infra_bck", 6), + GATE_AUD(CLK_AUD_22M, "aud_22m", "rg_aud_engen1", 8), + GATE_AUD(CLK_AUD_24M, "aud_24m", "rg_aud_engen2", 9), + GATE_AUD(CLK_AUD_INTDIR, "aud_intdir", "rg_aud_spdif_in", 15), + GATE_AUD(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "rg_aud_engen2", 18), + GATE_AUD(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "rg_aud_engen1", 19), + GATE_AUD(CLK_AUD_HDMI, "aud_hdmi", "apll12_div4", 20), + GATE_AUD(CLK_AUD_SPDF, "aud_spdf", "apll12_div6", 21), + GATE_AUD(CLK_AUD_ADC, "aud_adc", "aud_afe", 24), + GATE_AUD(CLK_AUD_DAC, "aud_dac", "aud_afe", 25), + GATE_AUD(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "aud_afe", 26), + GATE_AUD(CLK_AUD_TML, "aud_tml", "aud_afe", 27), +}; + +static void __init mtk_audsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); + + mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_audsys, "mediatek,mt8167-audsys", mtk_audsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167-img.c b/drivers/clk/mediatek/clk-mt8167-img.c new file mode 100644 index 000000000000..3b4ec9eae432 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-img.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.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/mt8167-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &img_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate img_clks[] __initconst = { + GATE_IMG(CLK_IMG_LARB1_SMI, "img_larb1_smi", "smi_mm", 0), + GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "smi_mm", 5), + GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "smi_mm", 6), + GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "cam_mm", 7), + GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "smi_mm", 8), + GATE_IMG(CLK_IMG_VENC, "img_venc", "smi_mm", 9), +}; + +static void __init mtk_imgsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); + + mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8167-imgsys", mtk_imgsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c new file mode 100644 index 000000000000..90b871730f2d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.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/mt8167-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) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mfg_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mfg_clks[] __initconst = { + GATE_MFG(CLK_MFG_BAXI, "mfg_baxi", "ahb_infra_sel", 0), + GATE_MFG(CLK_MFG_BMEM, "mfg_bmem", "gfmux_emi1x_sel", 1), + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_mm", 2), + GATE_MFG(CLK_MFG_B26M, "mfg_b26m", "clk26m_ck", 3), +}; + +static void __init mtk_mfgcfg_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); + + mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_mfgcfg, "mediatek,mt8167-mfgcfg", mtk_mfgcfg_init); diff --git a/drivers/clk/mediatek/clk-mt8167-mm.c b/drivers/clk/mediatek/clk-mt8167-mm.c new file mode 100644 index 000000000000..963b129aade1 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-mm.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.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/mt8167-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_MM1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &mm1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "smi_mm", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "smi_mm", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "smi_mm", 2), + GATE_MM0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "smi_mm", 3), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "smi_mm", 4), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "smi_mm", 5), + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "smi_mm", 6), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "smi_mm", 7), + GATE_MM0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "smi_mm", 8), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "smi_mm", 9), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "smi_mm", 10), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "smi_mm", 11), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "smi_mm", 12), + GATE_MM0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "smi_mm", 13), + GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "smi_mm", 14), + GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "smi_mm", 15), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "smi_mm", 16), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "smi_mm", 17), + GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "smi_mm", 18), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "smi_mm", 19), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM_MM, "mm_disp_pwm_mm", "smi_mm", 0), + GATE_MM1(CLK_MM_DISP_PWM_26M, "mm_disp_pwm_26m", "smi_mm", 1), + GATE_MM1(CLK_MM_DSI_ENGINE, "mm_dsi_engine", "smi_mm", 2), + GATE_MM1(CLK_MM_DSI_DIGITAL, "mm_dsi_digital", "dsi0_lntc_dsick", 3), + GATE_MM1(CLK_MM_DPI0_ENGINE, "mm_dpi0_engine", "smi_mm", 4), + GATE_MM1(CLK_MM_DPI0_PXL, "mm_dpi0_pxl", "rg_fdpi0", 5), + GATE_MM1(CLK_MM_LVDS_PXL, "mm_lvds_pxl", "vpll_dpix", 14), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx_dig_cts", 15), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "smi_mm", 16), + GATE_MM1(CLK_MM_DPI1_PXL, "mm_dpi1_pxl", "rg_fdpi1", 17), + GATE_MM1(CLK_MM_HDMI_PXL, "mm_hdmi_pxl", "rg_fdpi1", 18), + GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll12_div6", 19), + GATE_MM1(CLK_MM_HDMI_ADSP_BCK, "mm_hdmi_adsp_b", "apll12_div4b", 20), + GATE_MM1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmtx_dig_cts", 21), +}; + +struct clk_mt8167_mm_driver_data { + const struct mtk_gate *gates_clk; + int gates_num; +}; + +static const struct clk_mt8167_mm_driver_data mt8167_mmsys_driver_data = { + .gates_clk = mm_clks, + .gates_num = ARRAY_SIZE(mm_clks), +}; + +static int clk_mt8167_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + const struct clk_mt8167_mm_driver_data *data; + struct clk_onecell_data *clk_data; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + data = &mt8167_mmsys_driver_data; + + ret = mtk_clk_register_gates(node, data->gates_clk, data->gates_num, + clk_data); + if (ret) + return ret; + + ret = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (ret) + return ret; + + return 0; +} + +static struct platform_driver clk_mt8173_mm_drv = { + .driver = { + .name = "clk-mt8167-mm", + }, + .probe = clk_mt8167_mm_probe, +}; + +builtin_platform_driver(clk_mt8173_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8167-vdec.c b/drivers/clk/mediatek/clk-mt8167-vdec.c new file mode 100644 index 000000000000..910b28355ec0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-vdec.c @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.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/mt8167-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_VDEC1_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate vdec_clks[] __initconst = { + /* VDEC0 */ + GATE_VDEC0_I(CLK_VDEC_CKEN, "vdec_cken", "rg_vdec", 0), + /* VDEC1 */ + GATE_VDEC1_I(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "smi_mm", 0), +}; + +static void __init mtk_vdecsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); + + mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8167-vdecsys", mtk_vdecsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c new file mode 100644 index 000000000000..e5ea10e31799 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167.c @@ -0,0 +1,1062 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static DEFINE_SPINLOCK(mt8167_clk_lock); + +static const struct mtk_fixed_clk fixed_clks[] __initconst = { + FIXED_CLK(CLK_TOP_CLK_NULL, "clk_null", NULL, 0), + FIXED_CLK(CLK_TOP_I2S_INFRA_BCK, "i2s_infra_bck", "clk_null", 26000000), + FIXED_CLK(CLK_TOP_MEMPLL, "mempll", "clk26m", 800000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC_DSICK, "dsi0_lntc_dsick", "clk26m", 75000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", "clk26m", 75000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx_dig_cts", "clk26m", 52500000), +}; + +static const struct mtk_fixed_factor top_divs[] __initconst = { + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D8, "mainpll_d8", "mainpll", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D16, "mainpll_d16", "mainpll", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D11, "mainpll_d11", "mainpll", 1, 11), + FACTOR(CLK_TOP_MAINPLL_D22, "mainpll_d22", "mainpll", 1, 22), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6), + FACTOR(CLK_TOP_MAINPLL_D12, "mainpll_d12", "mainpll", 1, 12), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D10, "mainpll_d10", "mainpll", 1, 10), + FACTOR(CLK_TOP_MAINPLL_D20, "mainpll_d20", "mainpll", 1, 20), + FACTOR(CLK_TOP_MAINPLL_D40, "mainpll_d40", "mainpll", 1, 40), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D14, "mainpll_d14", "mainpll", 1, 14), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D8, "univpll_d8", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D16, "univpll_d16", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL_D12, "univpll_d12", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL_D24, "univpll_d24", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D20, "univpll_d20", "univpll", 1, 20), + FACTOR(CLK_TOP_MMPLL380M, "mmpll380m", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_200M, "mmpll_200m", "mmpll", 1, 3), + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "rg_apll1_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "rg_apll1_d4_en", 1, 2), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "rg_apll2_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "rg_apll2_d4_en", 1, 2), + FACTOR(CLK_TOP_CLK26M, "clk26m_ck", "clk26m", 1, 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_MIPI_26M, "mipi_26m", "clk26m", 1, 1), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16), + FACTOR(CLK_TOP_AHB_INFRA_D2, "ahb_infra_d2", "ahb_infra_sel", 1, 2), + FACTOR(CLK_TOP_NFI1X, "nfi1x_ck", "nfi2x_pad_sel", 1, 2), + FACTOR(CLK_TOP_ETH_D2, "eth_d2_ck", "eth_sel", 1, 2), +}; + +static const char * const uart0_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const gfmux_emi1x_parents[] __initconst = { + "clk26m_ck", + "dmpll_ck" +}; + +static const char * const emi_ddrphy_parents[] __initconst = { + "gfmux_emi1x_sel", + "gfmux_emi1x_sel" +}; + +static const char * const ahb_infra_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d11", + "clk_null", + "mainpll_d12", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10" +}; + +static const char * const csw_mux_mfg_parents[] __initconst = { + "clk_null", + "clk_null", + "univpll_d3", + "univpll_d2", + "clk26m_ck", + "mainpll_d4", + "univpll_d24", + "mmpll380m" +}; + +static const char * const msdc0_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const camtg_mm_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "usb_phy48m_ck", + "clk_null", + "univpll_d6" +}; + +static const char * const pwm_mm_parents[] __initconst = { + "clk26m_ck", + "univpll_d12" +}; + +static const char * const uart1_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const msdc1_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const spm_52m_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const pmicspi_parents[] __initconst = { + "univpll_d20", + "usb_phy48m_ck", + "univpll_d16", + "clk26m_ck" +}; + +static const char * const qaxi_aud26m_parents[] __initconst = { + "clk26m_ck", + "ahb_infra_sel" +}; + +static const char * const aud_intbus_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d22", + "clk_null", + "mainpll_d11" +}; + +static const char * const nfi2x_pad_parents[] __initconst = { + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk26m_ck", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d12", + "mainpll_d8", + "clk_null", + "mainpll_d6", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d4", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10", + "mainpll_d7", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfi1x_pad_parents[] __initconst = { + "ahb_infra_sel", + "nfi1x_ck" +}; + +static const char * const mfg_mm_parents[] __initconst = { + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "csw_mux_mfg_sel", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d3", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d5", + "mainpll_d7", + "clk_null", + "mainpll_d14" +}; + +static const char * const ddrphycfg_parents[] __initconst = { + "clk26m_ck", + "mainpll_d16" +}; + +static const char * const smi_mm_parents[] __initconst = { + "clk26m_ck", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "univpll_d4", + "mainpll_d7", + "clk_null", + "mainpll_d14" +}; + +static const char * const usb_78m_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "univpll_d16", + "clk_null", + "mainpll_d20" +}; + +static const char * const scam_mm_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d14", + "clk_null", + "mainpll_d12" +}; + +static const char * const spinor_parents[] __initconst = { + "clk26m_d2", + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20", + "mainpll_d16", + "univpll_d12" +}; + +static const char * const msdc2_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const eth_parents[] __initconst = { + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20" +}; + +static const char * const vdec_mm_parents[] __initconst = { + "clk26m_ck", + "univpll_d4", + "mainpll_d4", + "univpll_d5", + "univpll_d6", + "mainpll_d6" +}; + +static const char * const dpi0_mm_parents[] __initconst = { + "clk26m_ck", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8" +}; + +static const char * const dpi1_mm_parents[] __initconst = { + "clk26m_ck", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const axi_mfg_in_parents[] __initconst = { + "clk26m_ck", + "mainpll_d11", + "univpll_d24", + "mmpll380m" +}; + +static const char * const slow_mfg_parents[] __initconst = { + "clk26m_ck", + "univpll_d12", + "univpll_d24" +}; + +static const char * const aud1_parents[] __initconst = { + "clk26m_ck", + "apll1_ck" +}; + +static const char * const aud2_parents[] __initconst = { + "clk26m_ck", + "apll2_ck" +}; + +static const char * const aud_engen1_parents[] __initconst = { + "clk26m_ck", + "rg_apll1_d2_en", + "rg_apll1_d4_en", + "rg_apll1_d8_en" +}; + +static const char * const aud_engen2_parents[] __initconst = { + "clk26m_ck", + "rg_apll2_d2_en", + "rg_apll2_d4_en", + "rg_apll2_d8_en" +}; + +static const char * const i2c_parents[] __initconst = { + "clk26m_ck", + "univpll_d20", + "univpll_d16", + "univpll_d12" +}; + +static const char * const aud_i2s0_m_parents[] __initconst = { + "rg_aud1", + "rg_aud2" +}; + +static const char * const pwm_parents[] __initconst = { + "clk26m_ck", + "univpll_d12" +}; + +static const char * const spi_parents[] __initconst = { + "clk26m_ck", + "univpll_d12", + "univpll_d8", + "univpll_d6" +}; + +static const char * const aud_spdifin_parents[] __initconst = { + "clk26m_ck", + "univpll_d2" +}; + +static const char * const uart2_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const bsi_parents[] __initconst = { + "clk26m_ck", + "mainpll_d10", + "mainpll_d12", + "mainpll_d20" +}; + +static const char * const dbg_atclk_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d5", + "clk_null", + "univpll_d5" +}; + +static const char * const csw_nfiecc_parents[] __initconst = { + "clk_null", + "mainpll_d7", + "mainpll_d6", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfiecc_parents[] __initconst = { + "clk_null", + "nfi2x_pad_sel", + "mainpll_d4", + "clk_null", + "csw_nfiecc_sel" +}; + +static struct mtk_composite top_muxes[] __initdata = { + /* CLK_MUX_SEL0 */ + MUX(CLK_TOP_UART0_SEL, "uart0_sel", uart0_parents, + 0x000, 0, 1), + MUX(CLK_TOP_GFMUX_EMI1X_SEL, "gfmux_emi1x_sel", gfmux_emi1x_parents, + 0x000, 1, 1), + MUX(CLK_TOP_EMI_DDRPHY_SEL, "emi_ddrphy_sel", emi_ddrphy_parents, + 0x000, 2, 1), + MUX(CLK_TOP_AHB_INFRA_SEL, "ahb_infra_sel", ahb_infra_parents, + 0x000, 4, 4), + MUX(CLK_TOP_CSW_MUX_MFG_SEL, "csw_mux_mfg_sel", csw_mux_mfg_parents, + 0x000, 8, 3), + MUX(CLK_TOP_MSDC0_SEL, "msdc0_sel", msdc0_parents, + 0x000, 11, 3), + MUX(CLK_TOP_CAMTG_MM_SEL, "camtg_mm_sel", camtg_mm_parents, + 0x000, 15, 3), + MUX(CLK_TOP_PWM_MM_SEL, "pwm_mm_sel", pwm_mm_parents, + 0x000, 18, 1), + MUX(CLK_TOP_UART1_SEL, "uart1_sel", uart1_parents, + 0x000, 19, 1), + MUX(CLK_TOP_MSDC1_SEL, "msdc1_sel", msdc1_parents, + 0x000, 20, 3), + MUX(CLK_TOP_SPM_52M_SEL, "spm_52m_sel", spm_52m_parents, + 0x000, 23, 1), + MUX(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x000, 24, 2), + MUX(CLK_TOP_QAXI_AUD26M_SEL, "qaxi_aud26m_sel", qaxi_aud26m_parents, + 0x000, 26, 1), + MUX(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x000, 27, 3), + /* CLK_MUX_SEL1 */ + MUX(CLK_TOP_NFI2X_PAD_SEL, "nfi2x_pad_sel", nfi2x_pad_parents, + 0x004, 0, 7), + MUX(CLK_TOP_NFI1X_PAD_SEL, "nfi1x_pad_sel", nfi1x_pad_parents, + 0x004, 7, 1), + MUX(CLK_TOP_MFG_MM_SEL, "mfg_mm_sel", mfg_mm_parents, + 0x004, 8, 6), + MUX(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x004, 15, 1), + MUX(CLK_TOP_SMI_MM_SEL, "smi_mm_sel", smi_mm_parents, + 0x004, 16, 4), + MUX(CLK_TOP_USB_78M_SEL, "usb_78m_sel", usb_78m_parents, + 0x004, 20, 3), + MUX(CLK_TOP_SCAM_MM_SEL, "scam_mm_sel", scam_mm_parents, + 0x004, 23, 3), + /* CLK_MUX_SEL8 */ + MUX(CLK_TOP_SPINOR_SEL, "spinor_sel", spinor_parents, + 0x040, 0, 3), + MUX(CLK_TOP_MSDC2_SEL, "msdc2_sel", msdc2_parents, + 0x040, 3, 3), + MUX(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 6, 3), + MUX(CLK_TOP_VDEC_MM_SEL, "vdec_mm_sel", vdec_mm_parents, + 0x040, 9, 3), + MUX(CLK_TOP_DPI0_MM_SEL, "dpi0_mm_sel", dpi0_mm_parents, + 0x040, 12, 3), + MUX(CLK_TOP_DPI1_MM_SEL, "dpi1_mm_sel", dpi1_mm_parents, + 0x040, 15, 3), + MUX(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, + 0x040, 18, 2), + MUX(CLK_TOP_SLOW_MFG_SEL, "slow_mfg_sel", slow_mfg_parents, + 0x040, 20, 2), + MUX(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x040, 22, 1), + MUX(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x040, 23, 1), + MUX(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", aud_engen1_parents, + 0x040, 24, 2), + MUX(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", aud_engen2_parents, + 0x040, 26, 2), + MUX(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, + 0x040, 28, 2), + /* CLK_SEL_9 */ + MUX(CLK_TOP_AUD_I2S0_M_SEL, "aud_i2s0_m_sel", aud_i2s0_m_parents, + 0x044, 12, 1), + MUX(CLK_TOP_AUD_I2S1_M_SEL, "aud_i2s1_m_sel", aud_i2s0_m_parents, + 0x044, 13, 1), + MUX(CLK_TOP_AUD_I2S2_M_SEL, "aud_i2s2_m_sel", aud_i2s0_m_parents, + 0x044, 14, 1), + MUX(CLK_TOP_AUD_I2S3_M_SEL, "aud_i2s3_m_sel", aud_i2s0_m_parents, + 0x044, 15, 1), + MUX(CLK_TOP_AUD_I2S4_M_SEL, "aud_i2s4_m_sel", aud_i2s0_m_parents, + 0x044, 16, 1), + MUX(CLK_TOP_AUD_I2S5_M_SEL, "aud_i2s5_m_sel", aud_i2s0_m_parents, + 0x044, 17, 1), + MUX(CLK_TOP_AUD_SPDIF_B_SEL, "aud_spdif_b_sel", aud_i2s0_m_parents, + 0x044, 18, 1), + /* CLK_MUX_SEL13 */ + MUX(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x07c, 0, 1), + MUX(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, + 0x07c, 1, 2), + MUX(CLK_TOP_AUD_SPDIFIN_SEL, "aud_spdifin_sel", aud_spdifin_parents, + 0x07c, 3, 1), + MUX(CLK_TOP_UART2_SEL, "uart2_sel", uart2_parents, + 0x07c, 4, 1), + MUX(CLK_TOP_BSI_SEL, "bsi_sel", bsi_parents, + 0x07c, 5, 2), + MUX(CLK_TOP_DBG_ATCLK_SEL, "dbg_atclk_sel", dbg_atclk_parents, + 0x07c, 7, 3), + MUX(CLK_TOP_CSW_NFIECC_SEL, "csw_nfiecc_sel", csw_nfiecc_parents, + 0x07c, 10, 3), + MUX(CLK_TOP_NFIECC_SEL, "nfiecc_sel", nfiecc_parents, + 0x07c, 13, 3), +}; + +static const char * const ifr_mux1_parents[] __initconst = { + "clk26m_ck", + "armpll", + "univpll", + "mainpll_d2" +}; + +static const char * const ifr_eth_25m_parents[] __initconst = { + "eth_d2_ck", + "rg_eth" +}; + +static const char * const ifr_i2c0_parents[] __initconst = { + "ahb_infra_d2", + "rg_i2c" +}; + +static const struct mtk_composite ifr_muxes[] __initconst = { + MUX(CLK_IFR_MUX1_SEL, "ifr_mux1_sel", ifr_mux1_parents, 0x000, + 2, 2), + MUX(CLK_IFR_ETH_25M_SEL, "ifr_eth_25m_sel", ifr_eth_25m_parents, 0x080, + 0, 1), + MUX(CLK_IFR_I2C0_SEL, "ifr_i2c0_sel", ifr_i2c0_parents, 0x080, + 1, 1), + MUX(CLK_IFR_I2C1_SEL, "ifr_i2c1_sel", ifr_i2c0_parents, 0x080, + 2, 1), + MUX(CLK_IFR_I2C2_SEL, "ifr_i2c2_sel", ifr_i2c0_parents, 0x080, + 3, 1), +}; + +#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ +} + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL12_CK_DIV0, "apll12_ck_div0", "aud_i2s0_m_sel", + 0x0048, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV1, "apll12_ck_div1", "aud_i2s1_m_sel", + 0x0048, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV2, "apll12_ck_div2", "aud_i2s2_m_sel", + 0x0048, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV3, "apll12_ck_div3", "aud_i2s3_m_sel", + 0x0048, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4, "apll12_ck_div4", "aud_i2s4_m_sel", + 0x004c, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4B, "apll12_ck_div4b", "apll12_div4", + 0x004c, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5, "apll12_ck_div5", "aud_i2s5_m_sel", + 0x004c, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5B, "apll12_ck_div5b", "apll12_div5", + 0x004c, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV6, "apll12_ck_div6", "aud_spdif_b_sel", + 0x0078, 0, 8), +}; + +#define DIV_ADJ_FLAG(_id, _name, _parent, _reg, _shift, _width, _flag) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ + .clk_divider_flags = _flag, \ +} + +static const struct mtk_clk_divider apmixed_adj_divs[] = { + DIV_ADJ_FLAG(CLK_APMIXED_HDMI_REF, "hdmi_ref", "tvdpll", + 0x1c4, 24, 3, CLK_DIVIDER_POWER_OF_TWO), +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x50, + .clr_ofs = 0x80, + .sta_ofs = 0x20, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x54, + .clr_ofs = 0x84, + .sta_ofs = 0x24, +}; + +static const struct mtk_gate_regs top2_cg_regs = { + .set_ofs = 0x6c, + .clr_ofs = 0x9c, + .sta_ofs = 0x3c, +}; + +static const struct mtk_gate_regs top3_cg_regs = { + .set_ofs = 0xa0, + .clr_ofs = 0xb0, + .sta_ofs = 0x70, +}; + +static const struct mtk_gate_regs top4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xb4, + .sta_ofs = 0x74, +}; + +static const struct mtk_gate_regs top5_cg_regs = { + .set_ofs = 0x44, + .clr_ofs = 0x44, + .sta_ofs = 0x44, +}; + +#define GATE_TOP0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP0_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP2_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP4_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top4_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP5(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top5_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate top_clks[] __initconst = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_PWM_MM, "pwm_mm", "pwm_mm_sel", 0), + GATE_TOP0(CLK_TOP_CAM_MM, "cam_mm", "camtg_mm_sel", 1), + GATE_TOP0(CLK_TOP_MFG_MM, "mfg_mm", "mfg_mm_sel", 2), + GATE_TOP0(CLK_TOP_SPM_52M, "spm_52m", "spm_52m_sel", 3), + GATE_TOP0_I(CLK_TOP_MIPI_26M_DBG, "mipi_26m_dbg", "mipi_26m", 4), + GATE_TOP0(CLK_TOP_SCAM_MM, "scam_mm", "scam_mm_sel", 5), + GATE_TOP0(CLK_TOP_SMI_MM, "smi_mm", "smi_mm_sel", 9), + /* TOP1 */ + GATE_TOP1(CLK_TOP_THEM, "them", "ahb_infra_sel", 1), + GATE_TOP1(CLK_TOP_APDMA, "apdma", "ahb_infra_sel", 2), + GATE_TOP1(CLK_TOP_I2C0, "i2c0", "ifr_i2c0_sel", 3), + GATE_TOP1(CLK_TOP_I2C1, "i2c1", "ifr_i2c1_sel", 4), + GATE_TOP1(CLK_TOP_AUXADC1, "auxadc1", "ahb_infra_sel", 5), + GATE_TOP1(CLK_TOP_NFI, "nfi", "nfi1x_pad_sel", 6), + GATE_TOP1(CLK_TOP_NFIECC, "nfiecc", "rg_nfiecc", 7), + GATE_TOP1(CLK_TOP_DEBUGSYS, "debugsys", "rg_dbg_atclk", 8), + GATE_TOP1(CLK_TOP_PWM, "pwm", "ahb_infra_sel", 9), + GATE_TOP1(CLK_TOP_UART0, "uart0", "uart0_sel", 10), + GATE_TOP1(CLK_TOP_UART1, "uart1", "uart1_sel", 11), + GATE_TOP1(CLK_TOP_BTIF, "btif", "ahb_infra_sel", 12), + GATE_TOP1(CLK_TOP_USB, "usb", "usb_78m", 13), + GATE_TOP1(CLK_TOP_FLASHIF_26M, "flashif_26m", "clk26m_ck", 14), + GATE_TOP1(CLK_TOP_AUXADC2, "auxadc2", "ahb_infra_sel", 15), + GATE_TOP1(CLK_TOP_I2C2, "i2c2", "ifr_i2c2_sel", 16), + GATE_TOP1(CLK_TOP_MSDC0, "msdc0", "msdc0_sel", 17), + GATE_TOP1(CLK_TOP_MSDC1, "msdc1", "msdc1_sel", 18), + GATE_TOP1(CLK_TOP_NFI2X, "nfi2x", "nfi2x_pad_sel", 19), + GATE_TOP1(CLK_TOP_PMICWRAP_AP, "pwrap_ap", "clk26m_ck", 20), + GATE_TOP1(CLK_TOP_SEJ, "sej", "ahb_infra_sel", 21), + GATE_TOP1(CLK_TOP_MEMSLP_DLYER, "memslp_dlyer", "clk26m_ck", 22), + GATE_TOP1(CLK_TOP_SPI, "spi", "spi_sel", 23), + GATE_TOP1(CLK_TOP_APXGPT, "apxgpt", "clk26m_ck", 24), + GATE_TOP1(CLK_TOP_AUDIO, "audio", "clk26m_ck", 25), + GATE_TOP1(CLK_TOP_PMICWRAP_MD, "pwrap_md", "clk26m_ck", 27), + GATE_TOP1(CLK_TOP_PMICWRAP_CONN, "pwrap_conn", "clk26m_ck", 28), + GATE_TOP1(CLK_TOP_PMICWRAP_26M, "pwrap_26m", "clk26m_ck", 29), + GATE_TOP1(CLK_TOP_AUX_ADC, "aux_adc", "clk26m_ck", 30), + GATE_TOP1(CLK_TOP_AUX_TP, "aux_tp", "clk26m_ck", 31), + /* TOP2 */ + GATE_TOP2(CLK_TOP_MSDC2, "msdc2", "ahb_infra_sel", 0), + GATE_TOP2(CLK_TOP_RBIST, "rbist", "univpll_d12", 1), + GATE_TOP2(CLK_TOP_NFI_BUS, "nfi_bus", "ahb_infra_sel", 2), + GATE_TOP2(CLK_TOP_GCE, "gce", "ahb_infra_sel", 4), + GATE_TOP2(CLK_TOP_TRNG, "trng", "ahb_infra_sel", 5), + GATE_TOP2(CLK_TOP_SEJ_13M, "sej_13m", "clk26m_ck", 6), + GATE_TOP2(CLK_TOP_AES, "aes", "ahb_infra_sel", 7), + GATE_TOP2(CLK_TOP_PWM_B, "pwm_b", "rg_pwm_infra", 8), + GATE_TOP2(CLK_TOP_PWM1_FB, "pwm1_fb", "rg_pwm_infra", 9), + GATE_TOP2(CLK_TOP_PWM2_FB, "pwm2_fb", "rg_pwm_infra", 10), + GATE_TOP2(CLK_TOP_PWM3_FB, "pwm3_fb", "rg_pwm_infra", 11), + GATE_TOP2(CLK_TOP_PWM4_FB, "pwm4_fb", "rg_pwm_infra", 12), + GATE_TOP2(CLK_TOP_PWM5_FB, "pwm5_fb", "rg_pwm_infra", 13), + GATE_TOP2(CLK_TOP_USB_1P, "usb_1p", "usb_78m", 14), + GATE_TOP2(CLK_TOP_FLASHIF_FREERUN, "flashif_freerun", "ahb_infra_sel", + 15), + GATE_TOP2(CLK_TOP_26M_HDMI_SIFM, "hdmi_sifm_26m", "clk26m_ck", 16), + GATE_TOP2(CLK_TOP_26M_CEC, "cec_26m", "clk26m_ck", 17), + GATE_TOP2(CLK_TOP_32K_CEC, "cec_32k", "clk32k", 18), + GATE_TOP2(CLK_TOP_66M_ETH, "eth_66m", "ahb_infra_d2", 19), + GATE_TOP2(CLK_TOP_133M_ETH, "eth_133m", "ahb_infra_sel", 20), + GATE_TOP2(CLK_TOP_FETH_25M, "feth_25m", "ifr_eth_25m_sel", 21), + GATE_TOP2(CLK_TOP_FETH_50M, "feth_50m", "rg_eth", 22), + GATE_TOP2(CLK_TOP_FLASHIF_AXI, "flashif_axi", "ahb_infra_sel", 23), + GATE_TOP2(CLK_TOP_USBIF, "usbif", "ahb_infra_sel", 24), + GATE_TOP2(CLK_TOP_UART2, "uart2", "rg_uart2", 25), + GATE_TOP2(CLK_TOP_BSI, "bsi", "ahb_infra_sel", 26), + GATE_TOP2(CLK_TOP_GCPU_B, "gcpu_b", "ahb_infra_sel", 27), + GATE_TOP2_I(CLK_TOP_MSDC0_INFRA, "msdc0_infra", "msdc0", 28), + GATE_TOP2_I(CLK_TOP_MSDC1_INFRA, "msdc1_infra", "msdc1", 29), + GATE_TOP2_I(CLK_TOP_MSDC2_INFRA, "msdc2_infra", "rg_msdc2", 30), + GATE_TOP2(CLK_TOP_USB_78M, "usb_78m", "usb_78m_sel", 31), + /* TOP3 */ + GATE_TOP3(CLK_TOP_RG_SPINOR, "rg_spinor", "spinor_sel", 0), + GATE_TOP3(CLK_TOP_RG_MSDC2, "rg_msdc2", "msdc2_sel", 1), + GATE_TOP3(CLK_TOP_RG_ETH, "rg_eth", "eth_sel", 2), + GATE_TOP3(CLK_TOP_RG_VDEC, "rg_vdec", "vdec_mm_sel", 3), + GATE_TOP3(CLK_TOP_RG_FDPI0, "rg_fdpi0", "dpi0_mm_sel", 4), + GATE_TOP3(CLK_TOP_RG_FDPI1, "rg_fdpi1", "dpi1_mm_sel", 5), + GATE_TOP3(CLK_TOP_RG_AXI_MFG, "rg_axi_mfg", "axi_mfg_in_sel", 6), + GATE_TOP3(CLK_TOP_RG_SLOW_MFG, "rg_slow_mfg", "slow_mfg_sel", 7), + GATE_TOP3(CLK_TOP_RG_AUD1, "rg_aud1", "aud1_sel", 8), + GATE_TOP3(CLK_TOP_RG_AUD2, "rg_aud2", "aud2_sel", 9), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN1, "rg_aud_engen1", "aud_engen1_sel", 10), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN2, "rg_aud_engen2", "aud_engen2_sel", 11), + GATE_TOP3(CLK_TOP_RG_I2C, "rg_i2c", "i2c_sel", 12), + GATE_TOP3(CLK_TOP_RG_PWM_INFRA, "rg_pwm_infra", "pwm_sel", 13), + GATE_TOP3(CLK_TOP_RG_AUD_SPDIF_IN, "rg_aud_spdif_in", "aud_spdifin_sel", + 14), + GATE_TOP3(CLK_TOP_RG_UART2, "rg_uart2", "uart2_sel", 15), + GATE_TOP3(CLK_TOP_RG_BSI, "rg_bsi", "bsi_sel", 16), + GATE_TOP3(CLK_TOP_RG_DBG_ATCLK, "rg_dbg_atclk", "dbg_atclk_sel", 17), + GATE_TOP3(CLK_TOP_RG_NFIECC, "rg_nfiecc", "nfiecc_sel", 18), + /* TOP4 */ + GATE_TOP4_I(CLK_TOP_RG_APLL1_D2_EN, "rg_apll1_d2_en", "apll1_d2", 8), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D4_EN, "rg_apll1_d4_en", "apll1_d4", 9), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D8_EN, "rg_apll1_d8_en", "apll1_d8", 10), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D2_EN, "rg_apll2_d2_en", "apll2_d2", 11), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D4_EN, "rg_apll2_d4_en", "apll2_d4", 12), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D8_EN, "rg_apll2_d8_en", "apll2_d8", 13), + /* TOP5 */ + GATE_TOP5(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll12_ck_div0", 0), + GATE_TOP5(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll12_ck_div1", 1), + GATE_TOP5(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll12_ck_div2", 2), + GATE_TOP5(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll12_ck_div3", 3), + GATE_TOP5(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll12_ck_div4", 4), + GATE_TOP5(CLK_TOP_APLL12_DIV4B, "apll12_div4b", "apll12_ck_div4b", 5), + GATE_TOP5(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll12_ck_div5", 6), + GATE_TOP5(CLK_TOP_APLL12_DIV5B, "apll12_div5b", "apll12_ck_div5b", 7), + GATE_TOP5(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll12_ck_div6", 8), +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(MT8167_CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), + clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8167_clk_lock, clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt8167_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8167-topckgen", mtk_topckgen_init); + +static void __init mtk_infracfg_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + + mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base, + &mt8167_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt8167-infracfg", mtk_infracfg_init); + +#define MT8167_PLL_FMAX (2500UL * MHZ) + +#define CON0_MT8167_RST_BAR BIT(27) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8167_RST_BAR, \ + .fmax = MT8167_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT8167_PLL_FMAX }, + { .div = 1, .freq = 1000000000 }, + { .div = 2, .freq = 604500000 }, + { .div = 3, .freq = 253500000 }, + { .div = 4, .freq = 126750000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0x00000001, 0, + 21, 0x0104, 24, 0, 0x0104, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0x00000001, + HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000001, + HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0x00000001, 0, + 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0x00000001, 0, + 31, 0x0180, 1, 0x0194, 0x0184, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0x00000001, 0, + 31, 0x01A0, 1, 0x01B4, 0x01A4, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x01C0, 0x01D0, 0x00000001, 0, + 21, 0x01C4, 24, 0, 0x01C4, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x01E0, 0x01F0, 0x00000001, 0, + 21, 0x01E4, 24, 0, 0x01E4, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + struct clk_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(MT8167_CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + mtk_clk_register_dividers(apmixed_adj_divs, ARRAY_SIZE(apmixed_adj_divs), + base, &mt8167_clk_lock, clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8167-apmixedsys", + mtk_apmixedsys_init); diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index dabeb435d067..034da203e8e0 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only +menu "Clock support for Amlogic platforms" + depends on ARCH_MESON || COMPILE_TEST + config COMMON_CLK_MESON_REGMAP tristate select REGMAP @@ -41,8 +44,9 @@ config COMMON_CLK_MESON_CPU_DYNDIV select COMMON_CLK_MESON_REGMAP config COMMON_CLK_MESON8B - bool - depends on ARCH_MESON + bool "Meson8 SoC Clock controller support" + depends on ARM + default y select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_MPLL select COMMON_CLK_MESON_PLL @@ -54,8 +58,9 @@ config COMMON_CLK_MESON8B want peripherals and CPU frequency scaling to work. config COMMON_CLK_GXBB - bool - depends on ARCH_MESON + bool "GXBB and GXL SoC clock controllers support" + depends on ARM64 + default y select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_VID_PLL_DIV @@ -69,8 +74,9 @@ config COMMON_CLK_GXBB Say Y if you want peripherals and CPU frequency scaling to work. config COMMON_CLK_AXG - bool - depends on ARCH_MESON + bool "AXG SoC clock controllers support" + depends on ARM64 + default y select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_MPLL @@ -84,7 +90,7 @@ config COMMON_CLK_AXG config COMMON_CLK_AXG_AUDIO tristate "Meson AXG Audio Clock Controller Driver" - depends on ARCH_MESON + depends on ARM64 select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_PHASE select COMMON_CLK_MESON_SCLK_DIV @@ -94,8 +100,9 @@ config COMMON_CLK_AXG_AUDIO aka axg, Say Y if you want audio subsystem to work. config COMMON_CLK_G12A - bool - depends on ARCH_MESON + bool "G12 and SM1 SoC clock controllers support" + depends on ARM64 + default y select COMMON_CLK_MESON_REGMAP select COMMON_CLK_MESON_DUALDIV select COMMON_CLK_MESON_MPLL @@ -107,3 +114,4 @@ config COMMON_CLK_G12A help Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2 devices, aka g12a. Say Y if you want peripherals to work. +endmenu diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c index 53715e36326c..7c8d02164443 100644 --- a/drivers/clk/meson/axg-audio.c +++ b/drivers/clk/meson/axg-audio.c @@ -147,6 +147,29 @@ }, \ } +#define AUD_SCLK_WS(_name, _reg, _width, _shift_ph, _shift_ws, _pname, \ + _iflags) { \ + .data = &(struct meson_sclk_ws_inv_data) { \ + .ph = { \ + .reg_off = (_reg), \ + .shift = (_shift_ph), \ + .width = (_width), \ + }, \ + .ws = { \ + .reg_off = (_reg), \ + .shift = (_shift_ws), \ + .width = (_width), \ + }, \ + }, \ + .hw.init = &(struct clk_init_data) { \ + .name = "aud_"#_name, \ + .ops = &meson_clk_phase_ops, \ + .parent_names = (const char *[]){ #_pname }, \ + .num_parents = 1, \ + .flags = (_iflags), \ + }, \ +} + /* Audio Master Clocks */ static const struct clk_parent_data mst_mux_parent_data[] = { { .fw_name = "mst_in0", }, @@ -254,6 +277,10 @@ static const struct clk_parent_data tdm_lrclk_parent_data[] = { AUD_PHASE(tdm##_name##_sclk, _reg, 1, 29, \ aud_tdm##_name##_sclk_post_en, \ CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT) +#define AUD_TDM_SCLK_WS(_name, _reg) \ + AUD_SCLK_WS(tdm##_name##_sclk, _reg, 1, 29, 28, \ + aud_tdm##_name##_sclk_post_en, \ + CLK_DUTY_CYCLE_PARENT | CLK_SET_RATE_PARENT) #define AUD_TDM_LRLCK(_name, _reg) \ AUD_MUX(tdm##_name##_lrclk, _reg, 0xf, 20, \ @@ -499,12 +526,6 @@ static struct clk_regmap tdmin_c_sclk = AUD_TDM_SCLK(in_c, AUDIO_CLK_TDMIN_C_CTRL); static struct clk_regmap tdmin_lb_sclk = AUD_TDM_SCLK(in_lb, AUDIO_CLK_TDMIN_LB_CTRL); -static struct clk_regmap tdmout_a_sclk = - AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL); -static struct clk_regmap tdmout_b_sclk = - AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL); -static struct clk_regmap tdmout_c_sclk = - AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL); static struct clk_regmap tdmin_a_lrclk = AUD_TDM_LRLCK(in_a, AUDIO_CLK_TDMIN_A_CTRL); @@ -521,6 +542,14 @@ static struct clk_regmap tdmout_b_lrclk = static struct clk_regmap tdmout_c_lrclk = AUD_TDM_LRLCK(out_c, AUDIO_CLK_TDMOUT_C_CTRL); +/* AXG Clocks */ +static struct clk_regmap axg_tdmout_a_sclk = + AUD_TDM_SCLK(out_a, AUDIO_CLK_TDMOUT_A_CTRL); +static struct clk_regmap axg_tdmout_b_sclk = + AUD_TDM_SCLK(out_b, AUDIO_CLK_TDMOUT_B_CTRL); +static struct clk_regmap axg_tdmout_c_sclk = + AUD_TDM_SCLK(out_c, AUDIO_CLK_TDMOUT_C_CTRL); + /* AXG/G12A Clocks */ static struct clk_hw axg_aud_top = { .init = &(struct clk_init_data) { @@ -591,7 +620,13 @@ static struct clk_regmap g12a_tdm_sclk_pad_1 = AUD_TDM_PAD_CTRL( static struct clk_regmap g12a_tdm_sclk_pad_2 = AUD_TDM_PAD_CTRL( sclk_pad_2, AUDIO_MST_PAD_CTRL1, 8, sclk_pad_ctrl_parent_data); -/* G12a/SM1 clocks */ +static struct clk_regmap g12a_tdmout_a_sclk = + AUD_TDM_SCLK_WS(out_a, AUDIO_CLK_TDMOUT_A_CTRL); +static struct clk_regmap g12a_tdmout_b_sclk = + AUD_TDM_SCLK_WS(out_b, AUDIO_CLK_TDMOUT_B_CTRL); +static struct clk_regmap g12a_tdmout_c_sclk = + AUD_TDM_SCLK_WS(out_c, AUDIO_CLK_TDMOUT_C_CTRL); + static struct clk_regmap toram = AUD_PCLK_GATE(toram, AUDIO_CLK_GATE_EN, 20); static struct clk_regmap spdifout_b = @@ -889,9 +924,9 @@ static struct clk_hw_onecell_data axg_audio_hw_onecell_data = { [AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw, [AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw, [AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw, - [AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw, - [AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw, - [AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw, + [AUD_CLKID_TDMOUT_A_SCLK] = &axg_tdmout_a_sclk.hw, + [AUD_CLKID_TDMOUT_B_SCLK] = &axg_tdmout_b_sclk.hw, + [AUD_CLKID_TDMOUT_C_SCLK] = &axg_tdmout_c_sclk.hw, [AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw, [AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw, [AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw, @@ -1026,9 +1061,9 @@ static struct clk_hw_onecell_data g12a_audio_hw_onecell_data = { [AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw, [AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw, [AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw, - [AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw, - [AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw, - [AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw, + [AUD_CLKID_TDMOUT_A_SCLK] = &g12a_tdmout_a_sclk.hw, + [AUD_CLKID_TDMOUT_B_SCLK] = &g12a_tdmout_b_sclk.hw, + [AUD_CLKID_TDMOUT_C_SCLK] = &g12a_tdmout_c_sclk.hw, [AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw, [AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw, [AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw, @@ -1170,9 +1205,9 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = { [AUD_CLKID_TDMIN_B_SCLK] = &tdmin_b_sclk.hw, [AUD_CLKID_TDMIN_C_SCLK] = &tdmin_c_sclk.hw, [AUD_CLKID_TDMIN_LB_SCLK] = &tdmin_lb_sclk.hw, - [AUD_CLKID_TDMOUT_A_SCLK] = &tdmout_a_sclk.hw, - [AUD_CLKID_TDMOUT_B_SCLK] = &tdmout_b_sclk.hw, - [AUD_CLKID_TDMOUT_C_SCLK] = &tdmout_c_sclk.hw, + [AUD_CLKID_TDMOUT_A_SCLK] = &g12a_tdmout_a_sclk.hw, + [AUD_CLKID_TDMOUT_B_SCLK] = &g12a_tdmout_b_sclk.hw, + [AUD_CLKID_TDMOUT_C_SCLK] = &g12a_tdmout_c_sclk.hw, [AUD_CLKID_TDMIN_A_LRCLK] = &tdmin_a_lrclk.hw, [AUD_CLKID_TDMIN_B_LRCLK] = &tdmin_b_lrclk.hw, [AUD_CLKID_TDMIN_C_LRCLK] = &tdmin_c_lrclk.hw, @@ -1209,12 +1244,7 @@ static struct clk_hw_onecell_data sm1_audio_hw_onecell_data = { }; -/* Convenience table to populate regmap in .probe() - * Note that this table is shared between both AXG and G12A, - * with spdifout_b clocks being exclusive to G12A. Since those - * clocks are not declared within the AXG onecell table, we do not - * feel the need to have separate AXG/G12A regmap tables. - */ +/* Convenience table to populate regmap in .probe(). */ static struct clk_regmap *const axg_clk_regmaps[] = { &ddr_arb, &pdm, @@ -1236,6 +1266,130 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &spdifout, &resample, &power_detect, + &mst_a_mclk_sel, + &mst_b_mclk_sel, + &mst_c_mclk_sel, + &mst_d_mclk_sel, + &mst_e_mclk_sel, + &mst_f_mclk_sel, + &mst_a_mclk_div, + &mst_b_mclk_div, + &mst_c_mclk_div, + &mst_d_mclk_div, + &mst_e_mclk_div, + &mst_f_mclk_div, + &mst_a_mclk, + &mst_b_mclk, + &mst_c_mclk, + &mst_d_mclk, + &mst_e_mclk, + &mst_f_mclk, + &spdifout_clk_sel, + &spdifout_clk_div, + &spdifout_clk, + &spdifin_clk_sel, + &spdifin_clk_div, + &spdifin_clk, + &pdm_dclk_sel, + &pdm_dclk_div, + &pdm_dclk, + &pdm_sysclk_sel, + &pdm_sysclk_div, + &pdm_sysclk, + &mst_a_sclk_pre_en, + &mst_b_sclk_pre_en, + &mst_c_sclk_pre_en, + &mst_d_sclk_pre_en, + &mst_e_sclk_pre_en, + &mst_f_sclk_pre_en, + &mst_a_sclk_div, + &mst_b_sclk_div, + &mst_c_sclk_div, + &mst_d_sclk_div, + &mst_e_sclk_div, + &mst_f_sclk_div, + &mst_a_sclk_post_en, + &mst_b_sclk_post_en, + &mst_c_sclk_post_en, + &mst_d_sclk_post_en, + &mst_e_sclk_post_en, + &mst_f_sclk_post_en, + &mst_a_sclk, + &mst_b_sclk, + &mst_c_sclk, + &mst_d_sclk, + &mst_e_sclk, + &mst_f_sclk, + &mst_a_lrclk_div, + &mst_b_lrclk_div, + &mst_c_lrclk_div, + &mst_d_lrclk_div, + &mst_e_lrclk_div, + &mst_f_lrclk_div, + &mst_a_lrclk, + &mst_b_lrclk, + &mst_c_lrclk, + &mst_d_lrclk, + &mst_e_lrclk, + &mst_f_lrclk, + &tdmin_a_sclk_sel, + &tdmin_b_sclk_sel, + &tdmin_c_sclk_sel, + &tdmin_lb_sclk_sel, + &tdmout_a_sclk_sel, + &tdmout_b_sclk_sel, + &tdmout_c_sclk_sel, + &tdmin_a_sclk_pre_en, + &tdmin_b_sclk_pre_en, + &tdmin_c_sclk_pre_en, + &tdmin_lb_sclk_pre_en, + &tdmout_a_sclk_pre_en, + &tdmout_b_sclk_pre_en, + &tdmout_c_sclk_pre_en, + &tdmin_a_sclk_post_en, + &tdmin_b_sclk_post_en, + &tdmin_c_sclk_post_en, + &tdmin_lb_sclk_post_en, + &tdmout_a_sclk_post_en, + &tdmout_b_sclk_post_en, + &tdmout_c_sclk_post_en, + &tdmin_a_sclk, + &tdmin_b_sclk, + &tdmin_c_sclk, + &tdmin_lb_sclk, + &axg_tdmout_a_sclk, + &axg_tdmout_b_sclk, + &axg_tdmout_c_sclk, + &tdmin_a_lrclk, + &tdmin_b_lrclk, + &tdmin_c_lrclk, + &tdmin_lb_lrclk, + &tdmout_a_lrclk, + &tdmout_b_lrclk, + &tdmout_c_lrclk, +}; + +static struct clk_regmap *const g12a_clk_regmaps[] = { + &ddr_arb, + &pdm, + &tdmin_a, + &tdmin_b, + &tdmin_c, + &tdmin_lb, + &tdmout_a, + &tdmout_b, + &tdmout_c, + &frddr_a, + &frddr_b, + &frddr_c, + &toddr_a, + &toddr_b, + &toddr_c, + &loopback, + &spdifin, + &spdifout, + &resample, + &power_detect, &spdifout_b, &mst_a_mclk_sel, &mst_b_mclk_sel, @@ -1328,9 +1482,9 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &tdmin_b_sclk, &tdmin_c_sclk, &tdmin_lb_sclk, - &tdmout_a_sclk, - &tdmout_b_sclk, - &tdmout_c_sclk, + &g12a_tdmout_a_sclk, + &g12a_tdmout_b_sclk, + &g12a_tdmout_c_sclk, &tdmin_a_lrclk, &tdmin_b_lrclk, &tdmin_c_lrclk, @@ -1465,9 +1619,9 @@ static struct clk_regmap *const sm1_clk_regmaps[] = { &tdmin_b_sclk, &tdmin_c_sclk, &tdmin_lb_sclk, - &tdmout_a_sclk, - &tdmout_b_sclk, - &tdmout_c_sclk, + &g12a_tdmout_a_sclk, + &g12a_tdmout_b_sclk, + &g12a_tdmout_c_sclk, &tdmin_a_lrclk, &tdmin_b_lrclk, &tdmin_c_lrclk, @@ -1713,8 +1867,8 @@ static const struct audioclk_data axg_audioclk_data = { }; static const struct audioclk_data g12a_audioclk_data = { - .regmap_clks = axg_clk_regmaps, - .regmap_clk_num = ARRAY_SIZE(axg_clk_regmaps), + .regmap_clks = g12a_clk_regmaps, + .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps), .hw_onecell_data = &g12a_audio_hw_onecell_data, .reset_offset = AUDIO_SW_RESET, .reset_num = 26, diff --git a/drivers/clk/meson/clk-phase.c b/drivers/clk/meson/clk-phase.c index fe22e171121a..a6763439f7d2 100644 --- a/drivers/clk/meson/clk-phase.c +++ b/drivers/clk/meson/clk-phase.c @@ -125,6 +125,62 @@ const struct clk_ops meson_clk_triphase_ops = { }; EXPORT_SYMBOL_GPL(meson_clk_triphase_ops); +/* + * This is a special clock for the audio controller. + * This drive a bit clock inverter for which the + * opposite value of the inverter bit needs to be manually + * set into another bit + */ +static inline struct meson_sclk_ws_inv_data * +meson_sclk_ws_inv_data(struct clk_regmap *clk) +{ + return (struct meson_sclk_ws_inv_data *)clk->data; +} + +static int meson_sclk_ws_inv_sync(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk); + unsigned int val; + + /* Get phase and sync the inverted value to ws */ + val = meson_parm_read(clk->map, &tph->ph); + meson_parm_write(clk->map, &tph->ws, val ? 0 : 1); + + return 0; +} + +static int meson_sclk_ws_inv_get_phase(struct clk_hw *hw) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk); + unsigned int val; + + val = meson_parm_read(clk->map, &tph->ph); + + return meson_clk_degrees_from_val(val, tph->ph.width); +} + +static int meson_sclk_ws_inv_set_phase(struct clk_hw *hw, int degrees) +{ + struct clk_regmap *clk = to_clk_regmap(hw); + struct meson_sclk_ws_inv_data *tph = meson_sclk_ws_inv_data(clk); + unsigned int val; + + val = meson_clk_degrees_to_val(degrees, tph->ph.width); + meson_parm_write(clk->map, &tph->ph, val); + meson_parm_write(clk->map, &tph->ws, val ? 0 : 1); + return 0; +} + +const struct clk_ops meson_sclk_ws_inv_ops = { + .init = meson_sclk_ws_inv_sync, + .get_phase = meson_sclk_ws_inv_get_phase, + .set_phase = meson_sclk_ws_inv_set_phase, +}; +EXPORT_SYMBOL_GPL(meson_sclk_ws_inv_ops); + + MODULE_DESCRIPTION("Amlogic phase driver"); MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/meson/clk-phase.h b/drivers/clk/meson/clk-phase.h index 5579f9ced142..b637b9b227bc 100644 --- a/drivers/clk/meson/clk-phase.h +++ b/drivers/clk/meson/clk-phase.h @@ -20,7 +20,13 @@ struct meson_clk_triphase_data { struct parm ph2; }; +struct meson_sclk_ws_inv_data { + struct parm ph; + struct parm ws; +}; + extern const struct clk_ops meson_clk_phase_ops; extern const struct clk_ops meson_clk_triphase_ops; +extern const struct clk_ops meson_sclk_ws_inv_ops; #endif /* __MESON_CLK_PHASE_H */ diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c index 9803d44bb157..b814d44917a5 100644 --- a/drivers/clk/meson/g12a.c +++ b/drivers/clk/meson/g12a.c @@ -298,6 +298,17 @@ static struct clk_regmap g12a_fclk_div2 = { &g12a_fclk_div2_div.hw }, .num_parents = 1, + /* + * Similar to fclk_div3, it seems that this clock is used by + * the resident firmware and is required by the platform to + * operate correctly. + * Until the following condition are met, we need this clock to + * be marked as critical: + * a) Mark the clock used by a firmware resource, if possible + * b) CCF has a clock hand-off mechanism to make the sure the + * clock stays on until the proper driver comes along + */ + .flags = CLK_IS_CRITICAL, }, }; diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c index bf8bea675d24..3a6d84cd6601 100644 --- a/drivers/clk/meson/meson-aoclk.c +++ b/drivers/clk/meson/meson-aoclk.c @@ -57,7 +57,7 @@ int meson_aoclkc_probe(struct platform_device *pdev) rstc->data = data; rstc->regmap = regmap; rstc->reset.ops = &meson_aoclk_reset_ops; - rstc->reset.nr_resets = data->num_reset, + rstc->reset.nr_resets = data->num_reset; rstc->reset.of_node = dev->of_node; ret = devm_reset_controller_register(dev, &rstc->reset); if (ret) { diff --git a/drivers/clk/mmp/clk-of-mmp2.c b/drivers/clk/mmp/clk-of-mmp2.c index 67208aea94c5..0839fb2049e9 100644 --- a/drivers/clk/mmp/clk-of-mmp2.c +++ b/drivers/clk/mmp/clk-of-mmp2.c @@ -347,9 +347,9 @@ static struct mmp_param_mux_clk mmp3_apmu_mux_clks[] = { }; static struct mmp_param_div_clk apmu_div_clks[] = { - {0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, 0, &disp0_lock}, + {0, "disp0_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 8, 4, CLK_DIVIDER_ONE_BASED, &disp0_lock}, {0, "disp0_sphy_div", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 15, 5, 0, &disp0_lock}, - {0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, 0, &disp1_lock}, + {0, "disp1_div", "disp1_mux", CLK_SET_RATE_PARENT, APMU_DISP1, 8, 4, CLK_DIVIDER_ONE_BASED, &disp1_lock}, {0, "ccic0_sphy_div", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 10, 5, 0, &ccic0_lock}, {0, "ccic1_sphy_div", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 10, 5, 0, &ccic1_lock}, }; diff --git a/drivers/clk/mmp/clk-of-pxa1928.c b/drivers/clk/mmp/clk-of-pxa1928.c index cede7b4ca3b9..998fc4207b0e 100644 --- a/drivers/clk/mmp/clk-of-pxa1928.c +++ b/drivers/clk/mmp/clk-of-pxa1928.c @@ -68,7 +68,6 @@ static struct mmp_clk_factor_tbl uart_factor_tbl[] = { static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit) { - struct clk *clk; struct mmp_clk_unit *unit = &pxa_unit->unit; mmp_register_fixed_rate_clks(unit, fixed_rate_clks, @@ -77,7 +76,7 @@ static void pxa1928_pll_init(struct pxa1928_clk_unit *pxa_unit) mmp_register_fixed_factor_clks(unit, fixed_factor_clks, ARRAY_SIZE(fixed_factor_clks)); - clk = mmp_clk_register_factor("uart_pll", "pll1_416", + mmp_clk_register_factor("uart_pll", "pll1_416", CLK_SET_RATE_PARENT, pxa_unit->mpmu_base + MPMU_UART_PLL, &uart_factor_masks, uart_factor_tbl, diff --git a/drivers/clk/mvebu/ap-cpu-clk.c b/drivers/clk/mvebu/ap-cpu-clk.c index 6b394302c76a..b4259b60dcfd 100644 --- a/drivers/clk/mvebu/ap-cpu-clk.c +++ b/drivers/clk/mvebu/ap-cpu-clk.c @@ -197,7 +197,7 @@ static int ap_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate, stable_bit = BIT(clk->pll_regs->ratio_state_offset + clk->cluster * - clk->pll_regs->ratio_state_cluster_offset), + 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, diff --git a/drivers/clk/pxa/clk-pxa.h b/drivers/clk/pxa/clk-pxa.h index f131d2834af4..5768e0f728ce 100644 --- a/drivers/clk/pxa/clk-pxa.h +++ b/drivers/clk/pxa/clk-pxa.h @@ -19,11 +19,11 @@ #define MUX_RO_RATE_RO_OPS(name, clk_name) \ static struct clk_hw name ## _mux_hw; \ static struct clk_hw name ## _rate_hw; \ - static struct clk_ops name ## _mux_ops = { \ + static const struct clk_ops name ## _mux_ops = { \ .get_parent = name ## _get_parent, \ .set_parent = dummy_clk_set_parent, \ }; \ - static struct clk_ops name ## _rate_ops = { \ + static const struct clk_ops name ## _rate_ops = { \ .recalc_rate = name ## _get_rate, \ }; \ static struct clk * __init clk_register_ ## name(void) \ @@ -38,7 +38,7 @@ #define RATE_RO_OPS(name, clk_name) \ static struct clk_hw name ## _rate_hw; \ - static const struct clk_ops name ## _rate_ops = { \ + static const struct clk_ops name ## _rate_ops = { \ .recalc_rate = name ## _get_rate, \ }; \ static struct clk * __init clk_register_ ## name(void) \ @@ -53,7 +53,7 @@ #define RATE_OPS(name, clk_name) \ static struct clk_hw name ## _rate_hw; \ - static struct clk_ops name ## _rate_ops = { \ + static const struct clk_ops name ## _rate_ops = { \ .recalc_rate = name ## _get_rate, \ .set_rate = name ## _set_rate, \ .determine_rate = name ## _determine_rate, \ diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig index 058327310c25..3a965bd326d5 100644 --- a/drivers/clk/qcom/Kconfig +++ b/drivers/clk/qcom/Kconfig @@ -413,6 +413,15 @@ 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_DISPCC_8250 + tristate "SM8150 and SM8250 Display Clock Controller" + depends on SM_GCC_8150 || SM_GCC_8250 + help + Support for the display clock controller on Qualcomm Technologies, Inc + SM8150 and SM8250 devices. + Say Y if you want to support display devices and functionality such as + splash screen. + config SM_GCC_8150 tristate "SM8150 Global Clock Controller" help @@ -444,6 +453,24 @@ config SM_GPUCC_8250 Say Y if you want to support graphics controller devices and functionality such as 3D graphics. +config SM_VIDEOCC_8150 + tristate "SM8150 Video Clock Controller" + select SDM_GCC_8150 + select QCOM_GDSC + help + Support for the video clock controller on SM8150 devices. + Say Y if you want to support video devices and functionality such as + video encode and decode. + +config SM_VIDEOCC_8250 + tristate "SM8250 Video Clock Controller" + select SDM_GCC_8250 + select QCOM_GDSC + help + Support for the video clock controller on SM8250 devices. + Say Y if you want to support video devices and functionality such as + video encode and decode. + config SPMI_PMIC_CLKDIV tristate "SPMI PMIC clkdiv Support" depends on SPMI || COMPILE_TEST diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile index 9677e769e7e9..11ae86febe87 100644 --- a/drivers/clk/qcom/Makefile +++ b/drivers/clk/qcom/Makefile @@ -64,10 +64,13 @@ 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_DISPCC_8250) += dispcc-sm8250.o obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o obj-$(CONFIG_SM_GCC_8250) += gcc-sm8250.o obj-$(CONFIG_SM_GPUCC_8150) += gpucc-sm8150.o obj-$(CONFIG_SM_GPUCC_8250) += gpucc-sm8250.o +obj-$(CONFIG_SM_VIDEOCC_8150) += videocc-sm8150.o +obj-$(CONFIG_SM_VIDEOCC_8250) += videocc-sm8250.o obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o obj-$(CONFIG_QCOM_HFPLL) += hfpll.o diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 26139ef005e4..564431130a76 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -609,7 +609,7 @@ static unsigned long alpha_huayra_pll_calc_rate(u64 prate, u32 l, u32 a) { /* - * a contains 16 bit alpha_val in two’s compliment number in the range + * a contains 16 bit alpha_val in two’s complement number in the range * of [-0.5, 0.5). */ if (a >= BIT(PLL_HUAYRA_ALPHA_WIDTH - 1)) @@ -641,7 +641,7 @@ alpha_huayra_pll_round_rate(unsigned long rate, unsigned long prate, quotient++; /* - * alpha_val should be in two’s compliment number in the range + * alpha_val should be in two’s complement number in the range * of [-0.5, 0.5) so if quotient >= 0.5 then increment the l value * since alpha value will be subtracted in this case. */ @@ -666,7 +666,7 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) regmap_read(pll->clkr.regmap, PLL_ALPHA_VAL(pll), &alpha); /* * Depending upon alpha_mode, it can be treated as M/N value or - * as a two’s compliment number. When alpha_mode=1, + * as a two’s complement number. When alpha_mode=1, * pll_alpha_val<15:8>=M and pll_apla_val<7:0>=N * * Fout=FIN*(L+(M/N)) @@ -674,12 +674,12 @@ alpha_pll_huayra_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) * M is a signed number (-128 to 127) and N is unsigned * (0 to 255). M/N has to be within +/-0.5. * - * When alpha_mode=0, it is a two’s compliment number in the + * When alpha_mode=0, it is a two’s complement number in the * range [-0.5, 0.5). * * Fout=FIN*(L+(alpha_val)/2^16) * - * where alpha_val is two’s compliment number. + * where alpha_val is two’s complement number. */ if (!(ctl & PLL_ALPHA_MODE)) return alpha_huayra_pll_calc_rate(rate, l, alpha); diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 357159fe85b5..59a5a0f261f3 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1182,14 +1182,21 @@ static int clk_rcg2_dp_set_rate_and_parent(struct clk_hw *hw, static int clk_rcg2_dp_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct clk_rate_request parent_req = *req; - int ret; + struct clk_rcg2 *rcg = to_clk_rcg2(hw); + unsigned long num, den; + u64 tmp; - ret = __clk_determine_rate(clk_hw_get_parent(hw), &parent_req); - if (ret) - return ret; + /* Parent rate is a fixed phy link rate */ + rational_best_approximation(req->best_parent_rate, req->rate, + GENMASK(rcg->mnd_width - 1, 0), + GENMASK(rcg->mnd_width - 1, 0), &den, &num); + + if (!num || !den) + return -EINVAL; - req->best_parent_rate = parent_req.rate; + tmp = req->best_parent_rate * num; + do_div(tmp, den); + req->rate = tmp; return 0; } diff --git a/drivers/clk/qcom/dispcc-sc7180.c b/drivers/clk/qcom/dispcc-sc7180.c index 0a5d395bce93..f487515701e3 100644 --- a/drivers/clk/qcom/dispcc-sc7180.c +++ b/drivers/clk/qcom/dispcc-sc7180.c @@ -202,7 +202,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_crypto_clk_src = { .name = "disp_cc_mdss_dp_crypto_clk_src", .parent_data = disp_cc_parent_data_1, .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_byte2_ops, }, }; @@ -216,7 +215,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { .name = "disp_cc_mdss_dp_link_clk_src", .parent_data = disp_cc_parent_data_1, .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_byte2_ops, }, }; @@ -230,7 +228,6 @@ static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = { .name = "disp_cc_mdss_dp_pixel_clk_src", .parent_data = disp_cc_parent_data_1, .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), - .flags = CLK_SET_RATE_PARENT, .ops = &clk_dp_ops, }, }; diff --git a/drivers/clk/qcom/dispcc-sm8250.c b/drivers/clk/qcom/dispcc-sm8250.c new file mode 100644 index 000000000000..07a98d3f882d --- /dev/null +++ b/drivers/clk/qcom/dispcc-sm8250.c @@ -0,0 +1,1107 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/reset-controller.h> + +#include <dt-bindings/clock/qcom,dispcc-sm8250.h> + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "gdsc.h" +#include "reset.h" + +enum { + P_BI_TCXO, + P_CHIP_SLEEP_CLK, + P_CORE_BI_PLL_TEST_SE, + P_DISP_CC_PLL0_OUT_MAIN, + P_DISP_CC_PLL1_OUT_EVEN, + P_DISP_CC_PLL1_OUT_MAIN, + P_DP_PHY_PLL_LINK_CLK, + P_DP_PHY_PLL_VCO_DIV_CLK, + P_DPTX1_PHY_PLL_LINK_CLK, + P_DPTX1_PHY_PLL_VCO_DIV_CLK, + P_DPTX2_PHY_PLL_LINK_CLK, + P_DPTX2_PHY_PLL_VCO_DIV_CLK, + P_DSI0_PHY_PLL_OUT_BYTECLK, + P_DSI0_PHY_PLL_OUT_DSICLK, + P_DSI1_PHY_PLL_OUT_BYTECLK, + P_DSI1_PHY_PLL_OUT_DSICLK, + P_EDP_PHY_PLL_LINK_CLK, + P_EDP_PHY_PLL_VCO_DIV_CLK, +}; + +static struct pll_vco vco_table[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct alpha_pll_config disp_cc_pll0_config = { + .l = 0x47, + .alpha = 0xE000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699C, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_init_data disp_cc_pll0_init = { + .name = "disp_cc_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, +}; + +static struct clk_alpha_pll disp_cc_pll0 = { + .offset = 0x0, + .vco_table = vco_table, + .num_vco = ARRAY_SIZE(vco_table), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &disp_cc_pll0_init +}; + +static struct alpha_pll_config disp_cc_pll1_config = { + .l = 0x1F, + .alpha = 0x4000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699C, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_init_data disp_cc_pll1_init = { + .name = "disp_cc_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, +}; + +static struct clk_alpha_pll disp_cc_pll1 = { + .offset = 0x1000, + .vco_table = vco_table, + .num_vco = ARRAY_SIZE(vco_table), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr.hw.init = &disp_cc_pll1_init +}; + +static const struct parent_map disp_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_DP_PHY_PLL_LINK_CLK, 1 }, + { P_DP_PHY_PLL_VCO_DIV_CLK, 2 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "dp_phy_pll_link_clk" }, + { .fw_name = "dp_phy_pll_vco_div_clk" }, +}; + +static const struct parent_map disp_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, +}; + +static const struct parent_map disp_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_DSI0_PHY_PLL_OUT_BYTECLK, 1 }, + { P_DSI1_PHY_PLL_OUT_BYTECLK, 2 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "dsi0_phy_pll_out_byteclk" }, + { .fw_name = "dsi1_phy_pll_out_byteclk" }, +}; + +static const struct parent_map disp_cc_parent_map_3[] = { + { P_BI_TCXO, 0 }, + { P_DISP_CC_PLL1_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_3[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &disp_cc_pll1.clkr.hw }, +}; + +static const struct parent_map disp_cc_parent_map_5[] = { + { P_BI_TCXO, 0 }, + { P_DISP_CC_PLL0_OUT_MAIN, 1 }, + { P_DISP_CC_PLL1_OUT_MAIN, 4 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_5[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &disp_cc_pll0.clkr.hw }, + { .hw = &disp_cc_pll1.clkr.hw }, +}; + +static const struct parent_map disp_cc_parent_map_6[] = { + { P_BI_TCXO, 0 }, + { P_DSI0_PHY_PLL_OUT_DSICLK, 1 }, + { P_DSI1_PHY_PLL_OUT_DSICLK, 2 }, +}; + +static const struct clk_parent_data disp_cc_parent_data_6[] = { + { .fw_name = "bi_tcxo" }, + { .fw_name = "dsi0_phy_pll_out_dsiclk" }, + { .fw_name = "dsi1_phy_pll_out_dsiclk" }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(37500000, P_DISP_CC_PLL1_OUT_MAIN, 16, 0, 0), + F(75000000, P_DISP_CC_PLL1_OUT_MAIN, 8, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = { + .cmd_rcgr = 0x22bc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_3, + .freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_ahb_clk_src", + .parent_data = disp_cc_parent_data_3, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_3), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_byte0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = { + .cmd_rcgr = 0x2110, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte0_clk_src", + .parent_data = disp_cc_parent_data_2, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_byte2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_byte1_clk_src = { + .cmd_rcgr = 0x212c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_2, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte1_clk_src", + .parent_data = disp_cc_parent_data_2, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_byte2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_aux1_clk_src = { + .cmd_rcgr = 0x2240, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_aux1_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_aux_clk_src = { + .cmd_rcgr = 0x21dc, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_aux_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_dp_link1_clk_src[] = { + F(162000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), + F(270000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), + F(540000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), + F(810000000, P_DP_PHY_PLL_LINK_CLK, 1, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_dp_link1_clk_src = { + .cmd_rcgr = 0x220c, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .freq_tbl = ftbl_disp_cc_mdss_dp_link1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link1_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_link_clk_src = { + .cmd_rcgr = 0x2178, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .freq_tbl = ftbl_disp_cc_mdss_dp_link1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_pixel1_clk_src = { + .cmd_rcgr = 0x21c4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel1_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .ops = &clk_dp_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_pixel2_clk_src = { + .cmd_rcgr = 0x21f4, + .mnd_width = 16, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel2_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .ops = &clk_dp_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_dp_pixel_clk_src = { + .cmd_rcgr = 0x21ac, + .mnd_width = 16, + .hid_width = 5, + .parent_map = disp_cc_parent_map_0, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel_clk_src", + .parent_data = disp_cc_parent_data_0, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_0), + .ops = &clk_dp_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = { + .cmd_rcgr = 0x2148, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_2, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_esc0_clk_src", + .parent_data = disp_cc_parent_data_2, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_esc1_clk_src = { + .cmd_rcgr = 0x2160, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_2, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_esc1_clk_src", + .parent_data = disp_cc_parent_data_2, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(85714286, P_DISP_CC_PLL1_OUT_MAIN, 7, 0, 0), + F(100000000, P_DISP_CC_PLL1_OUT_MAIN, 6, 0, 0), + F(150000000, P_DISP_CC_PLL1_OUT_MAIN, 4, 0, 0), + F(200000000, P_DISP_CC_PLL1_OUT_MAIN, 3, 0, 0), + F(300000000, P_DISP_CC_PLL1_OUT_MAIN, 2, 0, 0), + F(345000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(460000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = { + .cmd_rcgr = 0x20c8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_5, + .freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_mdp_clk_src", + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = { + .cmd_rcgr = 0x2098, + .mnd_width = 8, + .hid_width = 5, + .parent_map = disp_cc_parent_map_6, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_pclk0_clk_src", + .parent_data = disp_cc_parent_data_6, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_pixel_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_pclk1_clk_src = { + .cmd_rcgr = 0x20b0, + .mnd_width = 8, + .hid_width = 5, + .parent_map = disp_cc_parent_map_6, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_pclk1_clk_src", + .parent_data = disp_cc_parent_data_6, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_6), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_pixel_ops, + }, +}; + +static const struct freq_tbl ftbl_disp_cc_mdss_rot_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_DISP_CC_PLL1_OUT_MAIN, 3, 0, 0), + F(300000000, P_DISP_CC_PLL1_OUT_MAIN, 2, 0, 0), + F(345000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0), + F(460000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0), + { } +}; + +static struct clk_rcg2 disp_cc_mdss_rot_clk_src = { + .cmd_rcgr = 0x20e0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_5, + .freq_tbl = ftbl_disp_cc_mdss_rot_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_rot_clk_src", + .parent_data = disp_cc_parent_data_5, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_5), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = { + .cmd_rcgr = 0x20f8, + .mnd_width = 0, + .hid_width = 5, + .parent_map = disp_cc_parent_map_1, + .freq_tbl = ftbl_disp_cc_mdss_byte0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_vsync_clk_src", + .parent_data = disp_cc_parent_data_1, + .num_parents = ARRAY_SIZE(disp_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_ops, + }, +}; + +static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = { + .reg = 0x2128, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_byte0_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte0_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + + +static struct clk_regmap_div disp_cc_mdss_byte1_div_clk_src = { + .reg = 0x2144, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_byte1_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte1_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ops, + }, +}; + + +static struct clk_regmap_div disp_cc_mdss_dp_link1_div_clk_src = { + .reg = 0x2224, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dp_link1_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link1_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + }, +}; + + +static struct clk_regmap_div disp_cc_mdss_dp_link_div_clk_src = { + .reg = 0x2190, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "disp_cc_mdss_dp_link_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch disp_cc_mdss_ahb_clk = { + .halt_reg = 0x2080, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2080, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte0_clk = { + .halt_reg = 0x2028, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2028, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte0_intf_clk = { + .halt_reg = 0x202c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x202c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte0_intf_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte0_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte1_clk = { + .halt_reg = 0x2030, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2030, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_byte1_intf_clk = { + .halt_reg = 0x2034, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2034, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_byte1_intf_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_byte1_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_aux1_clk = { + .halt_reg = 0x2068, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2068, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_aux1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_aux1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_aux_clk = { + .halt_reg = 0x2054, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2054, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_aux_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_aux_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_link1_clk = { + .halt_reg = 0x205c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x205c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_link1_intf_clk = { + .halt_reg = 0x2060, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2060, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link1_intf_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link1_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_link_clk = { + .halt_reg = 0x2040, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2040, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_link_intf_clk = { + .halt_reg = 0x2044, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2044, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_link_intf_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_link_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_pixel1_clk = { + .halt_reg = 0x2050, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2050, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_pixel1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_pixel2_clk = { + .halt_reg = 0x2058, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2058, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_pixel2_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_dp_pixel_clk = { + .halt_reg = 0x204c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x204c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_dp_pixel_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_dp_pixel_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_esc0_clk = { + .halt_reg = 0x2038, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2038, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_esc0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_esc0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_esc1_clk = { + .halt_reg = 0x203c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x203c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_esc1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_esc1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_mdp_clk = { + .halt_reg = 0x200c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x200c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_mdp_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_mdp_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_mdp_lut_clk = { + .halt_reg = 0x201c, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x201c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_mdp_lut_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_mdp_clk_src.clkr.hw, + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = { + .halt_reg = 0x4004, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x4004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_non_gdsc_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_pclk0_clk = { + .halt_reg = 0x2004, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2004, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_pclk0_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_pclk0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_pclk1_clk = { + .halt_reg = 0x2008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_pclk1_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_pclk1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_rot_clk = { + .halt_reg = 0x2014, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2014, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_rot_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_rot_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_rscc_ahb_clk = { + .halt_reg = 0x400c, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x400c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_rscc_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_ahb_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_rscc_vsync_clk = { + .halt_reg = 0x4008, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x4008, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_rscc_vsync_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_vsync_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch disp_cc_mdss_vsync_clk = { + .halt_reg = 0x2024, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x2024, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "disp_cc_mdss_vsync_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &disp_cc_mdss_vsync_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc mdss_gdsc = { + .gdscr = 0x3000, + .pd = { + .name = "mdss_gdsc", + }, + .pwrsts = PWRSTS_OFF_ON, + .flags = HW_CTRL, +}; + +static struct clk_regmap *disp_cc_sm8250_clocks[] = { + [DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr, + [DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr, + [DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr, + [DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr, + [DISP_CC_MDSS_BYTE1_CLK] = &disp_cc_mdss_byte1_clk.clkr, + [DISP_CC_MDSS_BYTE1_CLK_SRC] = &disp_cc_mdss_byte1_clk_src.clkr, + [DISP_CC_MDSS_BYTE1_DIV_CLK_SRC] = &disp_cc_mdss_byte1_div_clk_src.clkr, + [DISP_CC_MDSS_BYTE1_INTF_CLK] = &disp_cc_mdss_byte1_intf_clk.clkr, + [DISP_CC_MDSS_DP_AUX1_CLK] = &disp_cc_mdss_dp_aux1_clk.clkr, + [DISP_CC_MDSS_DP_AUX1_CLK_SRC] = &disp_cc_mdss_dp_aux1_clk_src.clkr, + [DISP_CC_MDSS_DP_AUX_CLK] = &disp_cc_mdss_dp_aux_clk.clkr, + [DISP_CC_MDSS_DP_AUX_CLK_SRC] = &disp_cc_mdss_dp_aux_clk_src.clkr, + [DISP_CC_MDSS_DP_LINK1_CLK] = &disp_cc_mdss_dp_link1_clk.clkr, + [DISP_CC_MDSS_DP_LINK1_CLK_SRC] = &disp_cc_mdss_dp_link1_clk_src.clkr, + [DISP_CC_MDSS_DP_LINK1_DIV_CLK_SRC] = &disp_cc_mdss_dp_link1_div_clk_src.clkr, + [DISP_CC_MDSS_DP_LINK1_INTF_CLK] = &disp_cc_mdss_dp_link1_intf_clk.clkr, + [DISP_CC_MDSS_DP_LINK_CLK] = &disp_cc_mdss_dp_link_clk.clkr, + [DISP_CC_MDSS_DP_LINK_CLK_SRC] = &disp_cc_mdss_dp_link_clk_src.clkr, + [DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC] = &disp_cc_mdss_dp_link_div_clk_src.clkr, + [DISP_CC_MDSS_DP_LINK_INTF_CLK] = &disp_cc_mdss_dp_link_intf_clk.clkr, + [DISP_CC_MDSS_DP_PIXEL1_CLK] = &disp_cc_mdss_dp_pixel1_clk.clkr, + [DISP_CC_MDSS_DP_PIXEL1_CLK_SRC] = &disp_cc_mdss_dp_pixel1_clk_src.clkr, + [DISP_CC_MDSS_DP_PIXEL2_CLK] = &disp_cc_mdss_dp_pixel2_clk.clkr, + [DISP_CC_MDSS_DP_PIXEL2_CLK_SRC] = &disp_cc_mdss_dp_pixel2_clk_src.clkr, + [DISP_CC_MDSS_DP_PIXEL_CLK] = &disp_cc_mdss_dp_pixel_clk.clkr, + [DISP_CC_MDSS_DP_PIXEL_CLK_SRC] = &disp_cc_mdss_dp_pixel_clk_src.clkr, + [DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr, + [DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr, + [DISP_CC_MDSS_ESC1_CLK] = &disp_cc_mdss_esc1_clk.clkr, + [DISP_CC_MDSS_ESC1_CLK_SRC] = &disp_cc_mdss_esc1_clk_src.clkr, + [DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr, + [DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr, + [DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr, + [DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr, + [DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr, + [DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr, + [DISP_CC_MDSS_PCLK1_CLK] = &disp_cc_mdss_pclk1_clk.clkr, + [DISP_CC_MDSS_PCLK1_CLK_SRC] = &disp_cc_mdss_pclk1_clk_src.clkr, + [DISP_CC_MDSS_ROT_CLK] = &disp_cc_mdss_rot_clk.clkr, + [DISP_CC_MDSS_ROT_CLK_SRC] = &disp_cc_mdss_rot_clk_src.clkr, + [DISP_CC_MDSS_RSCC_AHB_CLK] = &disp_cc_mdss_rscc_ahb_clk.clkr, + [DISP_CC_MDSS_RSCC_VSYNC_CLK] = &disp_cc_mdss_rscc_vsync_clk.clkr, + [DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr, + [DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr, + [DISP_CC_PLL0] = &disp_cc_pll0.clkr, + [DISP_CC_PLL1] = &disp_cc_pll1.clkr, +}; + +static const struct qcom_reset_map disp_cc_sm8250_resets[] = { + [DISP_CC_MDSS_CORE_BCR] = { 0x2000 }, + [DISP_CC_MDSS_RSCC_BCR] = { 0x4000 }, +}; + +static struct gdsc *disp_cc_sm8250_gdscs[] = { + [MDSS_GDSC] = &mdss_gdsc, +}; + +static const struct regmap_config disp_cc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0x10000, + .fast_io = true, +}; + +static const struct qcom_cc_desc disp_cc_sm8250_desc = { + .config = &disp_cc_sm8250_regmap_config, + .clks = disp_cc_sm8250_clocks, + .num_clks = ARRAY_SIZE(disp_cc_sm8250_clocks), + .resets = disp_cc_sm8250_resets, + .num_resets = ARRAY_SIZE(disp_cc_sm8250_resets), + .gdscs = disp_cc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(disp_cc_sm8250_gdscs), +}; + +static const struct of_device_id disp_cc_sm8250_match_table[] = { + { .compatible = "qcom,sm8150-dispcc" }, + { .compatible = "qcom,sm8250-dispcc" }, + { } +}; +MODULE_DEVICE_TABLE(of, disp_cc_sm8250_match_table); + +static int disp_cc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &disp_cc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + /* note: trion == lucid, except for the prepare() op */ + BUILD_BUG_ON(CLK_ALPHA_PLL_TYPE_TRION != CLK_ALPHA_PLL_TYPE_LUCID); + if (of_device_is_compatible(pdev->dev.of_node, "qcom,sm8150-dispcc")) { + disp_cc_pll0_config.config_ctl_hi_val = 0x00002267; + disp_cc_pll0_config.config_ctl_hi1_val = 0x00000024; + disp_cc_pll0_config.user_ctl_hi1_val = 0x000000D0; + disp_cc_pll0_init.ops = &clk_alpha_pll_trion_ops; + disp_cc_pll1_config.config_ctl_hi_val = 0x00002267; + disp_cc_pll1_config.config_ctl_hi1_val = 0x00000024; + disp_cc_pll1_config.user_ctl_hi1_val = 0x000000D0; + disp_cc_pll1_init.ops = &clk_alpha_pll_trion_ops; + } + + clk_lucid_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config); + clk_lucid_pll_configure(&disp_cc_pll1, regmap, &disp_cc_pll1_config); + + /* Enable clock gating for MDP clocks */ + regmap_update_bits(regmap, 0x8000, 0x10, 0x10); + + /* DISP_CC_XO_CLK always-on */ + regmap_update_bits(regmap, 0x605c, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &disp_cc_sm8250_desc, regmap); +} + +static struct platform_driver disp_cc_sm8250_driver = { + .probe = disp_cc_sm8250_probe, + .driver = { + .name = "disp_cc-sm8250", + .of_match_table = disp_cc_sm8250_match_table, + }, +}; + +static int __init disp_cc_sm8250_init(void) +{ + return platform_driver_register(&disp_cc_sm8250_driver); +} +subsys_initcall(disp_cc_sm8250_init); + +static void __exit disp_cc_sm8250_exit(void) +{ + platform_driver_unregister(&disp_cc_sm8250_driver); +} +module_exit(disp_cc_sm8250_exit); + +MODULE_DESCRIPTION("QTI DISPCC SM8250 Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/qcom/gcc-ipq8074.c b/drivers/clk/qcom/gcc-ipq8074.c index ef2c9c4cf9ab..108fe27bee10 100644 --- a/drivers/clk/qcom/gcc-ipq8074.c +++ b/drivers/clk/qcom/gcc-ipq8074.c @@ -4322,7 +4322,7 @@ static const struct freq_tbl ftbl_pcie_rchng_clk_src[] = { { } }; -struct clk_rcg2 pcie0_rchng_clk_src = { +static struct clk_rcg2 pcie0_rchng_clk_src = { .cmd_rcgr = 0x75070, .freq_tbl = ftbl_pcie_rchng_clk_src, .hid_width = 5, diff --git a/drivers/clk/qcom/gcc-msm8939.c b/drivers/clk/qcom/gcc-msm8939.c index 778354f82b1e..39ebb443ae3d 100644 --- a/drivers/clk/qcom/gcc-msm8939.c +++ b/drivers/clk/qcom/gcc-msm8939.c @@ -595,24 +595,12 @@ static const struct clk_parent_data gcc_xo_gpll1_emclk_sleep_parent_data[] = { { .fw_name = "sleep_clk", .name = "sleep_clk" }, }; -static const struct parent_map gcc_xo_gpll6_gpll0_map[] = { - { P_XO, 0 }, - { P_GPLL6, 1 }, - { P_GPLL0, 2 }, -}; - static const struct clk_parent_data gcc_xo_gpll6_gpll0_parent_data[] = { { .fw_name = "xo" }, { .hw = &gpll6_vote.hw }, { .hw = &gpll0_vote.hw }, }; -static const struct parent_map gcc_xo_gpll6_gpll0a_map[] = { - { P_XO, 0 }, - { P_GPLL6, 1 }, - { P_GPLL0_AUX, 2 }, -}; - static const struct clk_parent_data gcc_xo_gpll6_gpll0a_parent_data[] = { { .fw_name = "xo" }, { .hw = &gpll6_vote.hw }, diff --git a/drivers/clk/qcom/gcc-msm8994.c b/drivers/clk/qcom/gcc-msm8994.c index b7fc8c7ba195..144d2ba7a9be 100644 --- a/drivers/clk/qcom/gcc-msm8994.c +++ b/drivers/clk/qcom/gcc-msm8994.c @@ -20,6 +20,7 @@ #include "clk-rcg.h" #include "clk-branch.h" #include "reset.h" +#include "gdsc.h" enum { P_XO, @@ -1772,6 +1773,32 @@ static struct clk_branch gcc_gp3_clk = { }, }; +static struct clk_branch gcc_lpass_q6_axi_clk = { + .halt_reg = 0x0280, + .clkr = { + .enable_reg = 0x0280, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_lpass_q6_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_mss_q6_bimc_axi_clk = { + .halt_reg = 0x0284, + .clkr = { + .enable_reg = 0x0284, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_mss_q6_bimc_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_pcie_0_aux_clk = { .halt_reg = 0x1ad4, .clkr = { @@ -1790,6 +1817,32 @@ static struct clk_branch gcc_pcie_0_aux_clk = { }, }; +static struct clk_branch gcc_pcie_0_cfg_ahb_clk = { + .halt_reg = 0x1ad0, + .clkr = { + .enable_reg = 0x1ad0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_0_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_0_mstr_axi_clk = { + .halt_reg = 0x1acc, + .clkr = { + .enable_reg = 0x1acc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_0_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_pcie_0_pipe_clk = { .halt_reg = 0x1ad8, .halt_check = BRANCH_HALT_DELAY, @@ -1809,6 +1862,20 @@ static struct clk_branch gcc_pcie_0_pipe_clk = { }, }; +static struct clk_branch gcc_pcie_0_slv_axi_clk = { + .halt_reg = 0x1ac8, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1ac8, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_0_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_pcie_1_aux_clk = { .halt_reg = 0x1b54, .clkr = { @@ -1827,6 +1894,32 @@ static struct clk_branch gcc_pcie_1_aux_clk = { }, }; +static struct clk_branch gcc_pcie_1_cfg_ahb_clk = { + .halt_reg = 0x1b54, + .clkr = { + .enable_reg = 0x1b54, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_1_cfg_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_pcie_1_mstr_axi_clk = { + .halt_reg = 0x1b50, + .clkr = { + .enable_reg = 0x1b50, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_1_mstr_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_pcie_1_pipe_clk = { .halt_reg = 0x1b58, .halt_check = BRANCH_HALT_DELAY, @@ -1846,6 +1939,19 @@ static struct clk_branch gcc_pcie_1_pipe_clk = { }, }; +static struct clk_branch gcc_pcie_1_slv_axi_clk = { + .halt_reg = 0x1b48, + .clkr = { + .enable_reg = 0x1b48, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pcie_1_slv_axi_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_pdm2_clk = { .halt_reg = 0x0ccc, .clkr = { @@ -1864,6 +1970,19 @@ static struct clk_branch gcc_pdm2_clk = { }, }; +static struct clk_branch gcc_pdm_ahb_clk = { + .halt_reg = 0x0cc4, + .clkr = { + .enable_reg = 0x0cc4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_pdm_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc1_apps_clk = { .halt_reg = 0x04c4, .clkr = { @@ -1899,6 +2018,23 @@ static struct clk_branch gcc_sdcc1_ahb_clk = { }, }; +static struct clk_branch gcc_sdcc2_ahb_clk = { + .halt_reg = 0x0508, + .clkr = { + .enable_reg = 0x0508, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_sdcc2_ahb_clk", + .parent_names = (const char *[]){ + "periph_noc_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc2_apps_clk = { .halt_reg = 0x0504, .clkr = { @@ -1917,6 +2053,23 @@ static struct clk_branch gcc_sdcc2_apps_clk = { }, }; +static struct clk_branch gcc_sdcc3_ahb_clk = { + .halt_reg = 0x0548, + .clkr = { + .enable_reg = 0x0548, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_sdcc3_ahb_clk", + .parent_names = (const char *[]){ + "periph_noc_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc3_apps_clk = { .halt_reg = 0x0544, .clkr = { @@ -1935,6 +2088,23 @@ static struct clk_branch gcc_sdcc3_apps_clk = { }, }; +static struct clk_branch gcc_sdcc4_ahb_clk = { + .halt_reg = 0x0588, + .clkr = { + .enable_reg = 0x0588, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_sdcc4_ahb_clk", + .parent_names = (const char *[]){ + "periph_noc_clk_src", + }, + .num_parents = 1, + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_sdcc4_apps_clk = { .halt_reg = 0x0584, .clkr = { @@ -1989,6 +2159,19 @@ static struct clk_branch gcc_sys_noc_usb3_axi_clk = { }, }; +static struct clk_branch gcc_tsif_ahb_clk = { + .halt_reg = 0x0d84, + .clkr = { + .enable_reg = 0x0d84, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_tsif_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_tsif_ref_clk = { .halt_reg = 0x0d88, .clkr = { @@ -2007,6 +2190,19 @@ static struct clk_branch gcc_tsif_ref_clk = { }, }; +static struct clk_branch gcc_ufs_ahb_clk = { + .halt_reg = 0x1d4c, + .clkr = { + .enable_reg = 0x1d4c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_ufs_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_ufs_axi_clk = { .halt_reg = 0x1d48, .clkr = { @@ -2043,6 +2239,34 @@ static struct clk_branch gcc_ufs_rx_cfg_clk = { }, }; +static struct clk_branch gcc_ufs_rx_symbol_0_clk = { + .halt_reg = 0x1d60, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1d60, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_ufs_rx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_rx_symbol_1_clk = { + .halt_reg = 0x1d64, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1d64, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_ufs_rx_symbol_1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_ufs_tx_cfg_clk = { .halt_reg = 0x1d50, .clkr = { @@ -2061,6 +2285,47 @@ static struct clk_branch gcc_ufs_tx_cfg_clk = { }, }; +static struct clk_branch gcc_ufs_tx_symbol_0_clk = { + .halt_reg = 0x1d58, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1d58, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_ufs_tx_symbol_0_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_ufs_tx_symbol_1_clk = { + .halt_reg = 0x1d5c, + .halt_check = BRANCH_HALT_DELAY, + .clkr = { + .enable_reg = 0x1d5c, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_ufs_tx_symbol_1_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch gcc_usb2_hs_phy_sleep_clk = { + .halt_reg = 0x04ac, + .clkr = { + .enable_reg = 0x04ac, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_usb2_hs_phy_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_usb30_master_clk = { .halt_reg = 0x03c8, .clkr = { @@ -2097,6 +2362,19 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = { }, }; +static struct clk_branch gcc_usb30_sleep_clk = { + .halt_reg = 0x03cc, + .clkr = { + .enable_reg = 0x03cc, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_usb30_sleep_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_usb3_phy_aux_clk = { .halt_reg = 0x1408, .clkr = { @@ -2115,6 +2393,19 @@ static struct clk_branch gcc_usb3_phy_aux_clk = { }, }; +static struct clk_branch gcc_usb_hs_ahb_clk = { + .halt_reg = 0x0488, + .clkr = { + .enable_reg = 0x0488, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_usb_hs_ahb_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + static struct clk_branch gcc_usb_hs_system_clk = { .halt_reg = 0x0484, .clkr = { @@ -2133,6 +2424,59 @@ static struct clk_branch gcc_usb_hs_system_clk = { }, }; +static struct clk_branch gcc_usb_phy_cfg_ahb2phy_clk = { + .halt_reg = 0x1a84, + .clkr = { + .enable_reg = 0x1a84, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data) + { + .name = "gcc_usb_phy_cfg_ahb2phy_clk", + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc pcie_gdsc = { + .gdscr = 0x1e18, + .pd = { + .name = "pcie", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_0_gdsc = { + .gdscr = 0x1ac4, + .pd = { + .name = "pcie_0", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc pcie_1_gdsc = { + .gdscr = 0x1b44, + .pd = { + .name = "pcie_1", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc usb30_gdsc = { + .gdscr = 0x3c4, + .pd = { + .name = "usb30", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc ufs_gdsc = { + .gdscr = 0x1d44, + .pd = { + .name = "ufs", + }, + .pwrsts = PWRSTS_OFF_ON, +}; + static struct clk_regmap *gcc_msm8994_clocks[] = { [GPLL0_EARLY] = &gpll0_early.clkr, [GPLL0] = &gpll0.clkr, @@ -2233,26 +2577,64 @@ static struct clk_regmap *gcc_msm8994_clocks[] = { [GCC_GP1_CLK] = &gcc_gp1_clk.clkr, [GCC_GP2_CLK] = &gcc_gp2_clk.clkr, [GCC_GP3_CLK] = &gcc_gp3_clk.clkr, + [GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.clkr, + [GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.clkr, [GCC_PCIE_0_AUX_CLK] = &gcc_pcie_0_aux_clk.clkr, + [GCC_PCIE_0_CFG_AHB_CLK] = &gcc_pcie_0_cfg_ahb_clk.clkr, + [GCC_PCIE_0_MSTR_AXI_CLK] = &gcc_pcie_0_mstr_axi_clk.clkr, [GCC_PCIE_0_PIPE_CLK] = &gcc_pcie_0_pipe_clk.clkr, + [GCC_PCIE_0_SLV_AXI_CLK] = &gcc_pcie_0_slv_axi_clk.clkr, [GCC_PCIE_1_AUX_CLK] = &gcc_pcie_1_aux_clk.clkr, + [GCC_PCIE_1_CFG_AHB_CLK] = &gcc_pcie_1_cfg_ahb_clk.clkr, + [GCC_PCIE_1_MSTR_AXI_CLK] = &gcc_pcie_1_mstr_axi_clk.clkr, [GCC_PCIE_1_PIPE_CLK] = &gcc_pcie_1_pipe_clk.clkr, + [GCC_PCIE_1_SLV_AXI_CLK] = &gcc_pcie_1_slv_axi_clk.clkr, [GCC_PDM2_CLK] = &gcc_pdm2_clk.clkr, + [GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.clkr, + [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, [GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.clkr, + [GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.clkr, [GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.clkr, + [GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.clkr, [GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.clkr, + [GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.clkr, [GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.clkr, - [GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.clkr, [GCC_SYS_NOC_UFS_AXI_CLK] = &gcc_sys_noc_ufs_axi_clk.clkr, [GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.clkr, + [GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.clkr, [GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.clkr, + [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, [GCC_UFS_AXI_CLK] = &gcc_ufs_axi_clk.clkr, [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, + [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, + [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, + [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, + [GCC_UFS_TX_SYMBOL_1_CLK] = &gcc_ufs_tx_symbol_1_clk.clkr, + [GCC_USB2_HS_PHY_SLEEP_CLK] = &gcc_usb2_hs_phy_sleep_clk.clkr, [GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.clkr, [GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.clkr, + [GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.clkr, [GCC_USB3_PHY_AUX_CLK] = &gcc_usb3_phy_aux_clk.clkr, + [GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.clkr, [GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.clkr, + [GCC_USB_PHY_CFG_AHB2PHY_CLK] = &gcc_usb_phy_cfg_ahb2phy_clk.clkr, +}; + +static struct gdsc *gcc_msm8994_gdscs[] = { + [PCIE_GDSC] = &pcie_gdsc, + [PCIE_0_GDSC] = &pcie_0_gdsc, + [PCIE_1_GDSC] = &pcie_1_gdsc, + [USB30_GDSC] = &usb30_gdsc, + [UFS_GDSC] = &ufs_gdsc, +}; + +static const struct qcom_reset_map gcc_msm8994_resets[] = { + [USB3_PHY_RESET] = { 0x1400 }, + [USB3PHY_PHY_RESET] = { 0x1404 }, + [PCIE_PHY_0_RESET] = { 0x1b18 }, + [PCIE_PHY_1_RESET] = { 0x1b98 }, + [QUSB2_PHY_RESET] = { 0x04b8 }, }; static const struct regmap_config gcc_msm8994_regmap_config = { @@ -2267,6 +2649,10 @@ static const struct qcom_cc_desc gcc_msm8994_desc = { .config = &gcc_msm8994_regmap_config, .clks = gcc_msm8994_clocks, .num_clks = ARRAY_SIZE(gcc_msm8994_clocks), + .resets = gcc_msm8994_resets, + .num_resets = ARRAY_SIZE(gcc_msm8994_resets), + .gdscs = gcc_msm8994_gdscs, + .num_gdscs = ARRAY_SIZE(gcc_msm8994_gdscs), }; static const struct of_device_id gcc_msm8994_match_table[] = { diff --git a/drivers/clk/qcom/gcc-sdm660.c b/drivers/clk/qcom/gcc-sdm660.c index f0b47b7d50ca..31258795e7b8 100644 --- a/drivers/clk/qcom/gcc-sdm660.c +++ b/drivers/clk/qcom/gcc-sdm660.c @@ -666,7 +666,7 @@ static struct clk_rcg2 hmss_rbcpr_clk_src = { .cmd_rcgr = 0x48044, .mnd_width = 0, .hid_width = 5, - .parent_map = gcc_parent_map_xo_gpll0_gpll0_early_div, + .parent_map = gcc_parent_map_xo_gpll0, .freq_tbl = ftbl_hmss_rbcpr_clk_src, .clkr.hw.init = &(struct clk_init_data){ .name = "hmss_rbcpr_clk_src", diff --git a/drivers/clk/qcom/gdsc.c b/drivers/clk/qcom/gdsc.c index bfc4ac02f9ea..af26e0695b86 100644 --- a/drivers/clk/qcom/gdsc.c +++ b/drivers/clk/qcom/gdsc.c @@ -358,6 +358,14 @@ static int gdsc_init(struct gdsc *sc) if ((sc->flags & VOTABLE) && on) gdsc_enable(&sc->pd); + /* + * Make sure the retain bit is set if the GDSC is already on, otherwise + * we end up turning off the GDSC and destroying all the register + * contents that we thought we were saving. + */ + if ((sc->flags & RETAIN_FF_ENABLE) && on) + gdsc_retain_ff_on(sc); + /* If ALWAYS_ON GDSCs are not ON, turn them ON */ if (sc->flags & ALWAYS_ON) { if (!on) diff --git a/drivers/clk/qcom/videocc-sm8150.c b/drivers/clk/qcom/videocc-sm8150.c new file mode 100644 index 000000000000..3087e2ec8fd4 --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8150.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,videocc-sm8150.h> + +#include "common.h" +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_CHIP_SLEEP_CLK, + P_CORE_BI_PLL_TEST_SE, + P_VIDEO_PLL0_OUT_EVEN, + P_VIDEO_PLL0_OUT_MAIN, + P_VIDEO_PLL0_OUT_ODD, +}; + +static struct pll_vco trion_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static struct alpha_pll_config video_pll0_config = { + .l = 0x14, + .alpha = 0xD555, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002267, + .config_ctl_hi1_val = 0x00000024, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x000000D0, +}; + +static struct clk_alpha_pll video_pll0 = { + .offset = 0x42c, + .vco_table = trion_vco, + .num_vco = ARRAY_SIZE(trion_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_TRION], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "video_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_trion_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_0[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_0[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &video_pll0.clkr.hw }, +}; + +static const struct freq_tbl ftbl_video_cc_iris_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(240000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(338000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(365000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(444000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + F(533000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_iris_clk_src = { + .cmd_rcgr = 0x7f0, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_0, + .freq_tbl = ftbl_video_cc_iris_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_iris_clk_src", + .parent_data = video_cc_parent_data_0, + .num_parents = ARRAY_SIZE(video_cc_parent_data_0), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_branch video_cc_iris_ahb_clk = { + .halt_reg = 0x8f4, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x8f4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_iris_ahb_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_iris_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs0_core_clk = { + .halt_reg = 0x890, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x890, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs0_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_iris_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_core_clk = { + .halt_reg = 0x8d0, + .halt_check = BRANCH_VOTED, + .clkr = { + .enable_reg = 0x8d0, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs1_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_iris_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvsc_core_clk = { + .halt_reg = 0x850, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0x850, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvsc_core_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_iris_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc venus_gdsc = { + .gdscr = 0x814, + .pd = { + .name = "venus_gdsc", + }, + .flags = 0, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc vcodec0_gdsc = { + .gdscr = 0x874, + .pd = { + .name = "vcodec0_gdsc", + }, + .flags = HW_CTRL, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc vcodec1_gdsc = { + .gdscr = 0x8b4, + .pd = { + .name = "vcodec1_gdsc", + }, + .flags = HW_CTRL, + .pwrsts = PWRSTS_OFF_ON, +}; +static struct clk_regmap *video_cc_sm8150_clocks[] = { + [VIDEO_CC_IRIS_AHB_CLK] = &video_cc_iris_ahb_clk.clkr, + [VIDEO_CC_IRIS_CLK_SRC] = &video_cc_iris_clk_src.clkr, + [VIDEO_CC_MVS0_CORE_CLK] = &video_cc_mvs0_core_clk.clkr, + [VIDEO_CC_MVS1_CORE_CLK] = &video_cc_mvs1_core_clk.clkr, + [VIDEO_CC_MVSC_CORE_CLK] = &video_cc_mvsc_core_clk.clkr, + [VIDEO_CC_PLL0] = &video_pll0.clkr, +}; + +static struct gdsc *video_cc_sm8150_gdscs[] = { + [VENUS_GDSC] = &venus_gdsc, + [VCODEC0_GDSC] = &vcodec0_gdsc, + [VCODEC1_GDSC] = &vcodec1_gdsc, +}; + +static const struct regmap_config video_cc_sm8150_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xb94, + .fast_io = true, +}; + +static const struct qcom_reset_map video_cc_sm8150_resets[] = { + [VIDEO_CC_MVSC_CORE_CLK_BCR] = { 0x850, 2 }, +}; + +static const struct qcom_cc_desc video_cc_sm8150_desc = { + .config = &video_cc_sm8150_regmap_config, + .clks = video_cc_sm8150_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8150_clocks), + .resets = video_cc_sm8150_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8150_resets), + .gdscs = video_cc_sm8150_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8150_gdscs), +}; + +static const struct of_device_id video_cc_sm8150_match_table[] = { + { .compatible = "qcom,sm8150-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8150_match_table); + +static int video_cc_sm8150_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &video_cc_sm8150_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_trion_pll_configure(&video_pll0, regmap, &video_pll0_config); + + /* Keep VIDEO_CC_XO_CLK ALWAYS-ON */ + regmap_update_bits(regmap, 0x984, 0x1, 0x1); + + return qcom_cc_really_probe(pdev, &video_cc_sm8150_desc, regmap); +} + +static struct platform_driver video_cc_sm8150_driver = { + .probe = video_cc_sm8150_probe, + .driver = { + .name = "video_cc-sm8150", + .of_match_table = video_cc_sm8150_match_table, + }, +}; + +static int __init video_cc_sm8150_init(void) +{ + return platform_driver_register(&video_cc_sm8150_driver); +} +subsys_initcall(video_cc_sm8150_init); + +static void __exit video_cc_sm8150_exit(void) +{ + platform_driver_unregister(&video_cc_sm8150_driver); +} +module_exit(video_cc_sm8150_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("QTI VIDEOCC SM8150 Driver"); diff --git a/drivers/clk/qcom/videocc-sm8250.c b/drivers/clk/qcom/videocc-sm8250.c new file mode 100644 index 000000000000..2797c61f5938 --- /dev/null +++ b/drivers/clk/qcom/videocc-sm8250.c @@ -0,0 +1,369 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/qcom,videocc-sm8250.h> + +#include "clk-alpha-pll.h" +#include "clk-branch.h" +#include "clk-rcg.h" +#include "clk-regmap.h" +#include "clk-regmap-divider.h" +#include "common.h" +#include "reset.h" +#include "gdsc.h" + +enum { + P_BI_TCXO, + P_CHIP_SLEEP_CLK, + P_CORE_BI_PLL_TEST_SE, + P_VIDEO_PLL0_OUT_MAIN, + P_VIDEO_PLL1_OUT_MAIN, +}; + +static struct pll_vco lucid_vco[] = { + { 249600000, 2000000000, 0 }, +}; + +static const struct alpha_pll_config video_pll0_config = { + .l = 0x25, + .alpha = 0x8000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699C, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll video_pll0 = { + .offset = 0x42c, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "video_pll0", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct alpha_pll_config video_pll1_config = { + .l = 0x2B, + .alpha = 0xC000, + .config_ctl_val = 0x20485699, + .config_ctl_hi_val = 0x00002261, + .config_ctl_hi1_val = 0x329A699C, + .user_ctl_val = 0x00000000, + .user_ctl_hi_val = 0x00000805, + .user_ctl_hi1_val = 0x00000000, +}; + +static struct clk_alpha_pll video_pll1 = { + .offset = 0x7d0, + .vco_table = lucid_vco, + .num_vco = ARRAY_SIZE(lucid_vco), + .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID], + .clkr = { + .hw.init = &(struct clk_init_data){ + .name = "video_pll1", + .parent_data = &(const struct clk_parent_data){ + .fw_name = "bi_tcxo", + }, + .num_parents = 1, + .ops = &clk_alpha_pll_lucid_ops, + }, + }, +}; + +static const struct parent_map video_cc_parent_map_1[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL0_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_1[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &video_pll0.clkr.hw }, +}; + +static const struct parent_map video_cc_parent_map_2[] = { + { P_BI_TCXO, 0 }, + { P_VIDEO_PLL1_OUT_MAIN, 1 }, +}; + +static const struct clk_parent_data video_cc_parent_data_2[] = { + { .fw_name = "bi_tcxo" }, + { .hw = &video_pll1.clkr.hw }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(720000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1014000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs0_clk_src = { + .cmd_rcgr = 0xb94, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_1, + .freq_tbl = ftbl_video_cc_mvs0_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs0_clk_src", + .parent_data = video_cc_parent_data_1, + .num_parents = ARRAY_SIZE(video_cc_parent_data_1), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = { + F(19200000, P_BI_TCXO, 1, 0, 0), + F(840000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0), + { } +}; + +static struct clk_rcg2 video_cc_mvs1_clk_src = { + .cmd_rcgr = 0xbb4, + .mnd_width = 0, + .hid_width = 5, + .parent_map = video_cc_parent_map_2, + .freq_tbl = ftbl_video_cc_mvs1_clk_src, + .clkr.hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs1_clk_src", + .parent_data = video_cc_parent_data_2, + .num_parents = ARRAY_SIZE(video_cc_parent_data_2), + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_rcg2_shared_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = { + .reg = 0xc54, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "video_cc_mvs0c_div2_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_mvs0_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = { + .reg = 0xcf4, + .shift = 0, + .width = 2, + .clkr.hw.init = &(struct clk_init_data) { + .name = "video_cc_mvs1c_div2_div_clk_src", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_mvs1_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_regmap_div_ro_ops, + }, +}; + +static struct clk_branch video_cc_mvs0c_clk = { + .halt_reg = 0xc34, + .halt_check = BRANCH_HALT, + .clkr = { + .enable_reg = 0xc34, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs0c_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_mvs0c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1_div2_clk = { + .halt_reg = 0xdf4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xdf4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs1_div2_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct clk_branch video_cc_mvs1c_clk = { + .halt_reg = 0xcd4, + .halt_check = BRANCH_HALT_VOTED, + .clkr = { + .enable_reg = 0xcd4, + .enable_mask = BIT(0), + .hw.init = &(struct clk_init_data){ + .name = "video_cc_mvs1c_clk", + .parent_data = &(const struct clk_parent_data){ + .hw = &video_cc_mvs1c_div2_div_clk_src.clkr.hw, + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + .ops = &clk_branch2_ops, + }, + }, +}; + +static struct gdsc mvs0c_gdsc = { + .gdscr = 0xbf8, + .pd = { + .name = "mvs0c_gdsc", + }, + .flags = 0, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs1c_gdsc = { + .gdscr = 0xc98, + .pd = { + .name = "mvs1c_gdsc", + }, + .flags = 0, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs0_gdsc = { + .gdscr = 0xd18, + .pd = { + .name = "mvs0_gdsc", + }, + .flags = HW_CTRL, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct gdsc mvs1_gdsc = { + .gdscr = 0xd98, + .pd = { + .name = "mvs1_gdsc", + }, + .flags = HW_CTRL, + .pwrsts = PWRSTS_OFF_ON, +}; + +static struct clk_regmap *video_cc_sm8250_clocks[] = { + [VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr, + [VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr, + [VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr, + [VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr, + [VIDEO_CC_MVS1_DIV2_CLK] = &video_cc_mvs1_div2_clk.clkr, + [VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr, + [VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr, + [VIDEO_CC_PLL0] = &video_pll0.clkr, + [VIDEO_CC_PLL1] = &video_pll1.clkr, +}; + +static const struct qcom_reset_map video_cc_sm8250_resets[] = { + [VIDEO_CC_CVP_INTERFACE_BCR] = { 0xe54 }, + [VIDEO_CC_CVP_MVS0_BCR] = { 0xd14 }, + [VIDEO_CC_MVS0C_CLK_ARES] = { 0xc34, 2 }, + [VIDEO_CC_CVP_MVS0C_BCR] = { 0xbf4 }, + [VIDEO_CC_CVP_MVS1_BCR] = { 0xd94 }, + [VIDEO_CC_MVS1C_CLK_ARES] = { 0xcd4, 2 }, + [VIDEO_CC_CVP_MVS1C_BCR] = { 0xc94 }, +}; + +static struct gdsc *video_cc_sm8250_gdscs[] = { + [MVS0C_GDSC] = &mvs0c_gdsc, + [MVS1C_GDSC] = &mvs1c_gdsc, + [MVS0_GDSC] = &mvs0_gdsc, + [MVS1_GDSC] = &mvs1_gdsc, +}; + +static const struct regmap_config video_cc_sm8250_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = 0xf4c, + .fast_io = true, +}; + +static const struct qcom_cc_desc video_cc_sm8250_desc = { + .config = &video_cc_sm8250_regmap_config, + .clks = video_cc_sm8250_clocks, + .num_clks = ARRAY_SIZE(video_cc_sm8250_clocks), + .resets = video_cc_sm8250_resets, + .num_resets = ARRAY_SIZE(video_cc_sm8250_resets), + .gdscs = video_cc_sm8250_gdscs, + .num_gdscs = ARRAY_SIZE(video_cc_sm8250_gdscs), +}; + +static const struct of_device_id video_cc_sm8250_match_table[] = { + { .compatible = "qcom,sm8250-videocc" }, + { } +}; +MODULE_DEVICE_TABLE(of, video_cc_sm8250_match_table); + +static int video_cc_sm8250_probe(struct platform_device *pdev) +{ + struct regmap *regmap; + + regmap = qcom_cc_map(pdev, &video_cc_sm8250_desc); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config); + clk_lucid_pll_configure(&video_pll1, regmap, &video_pll1_config); + + /* Keep VIDEO_CC_AHB_CLK and VIDEO_CC_XO_CLK ALWAYS-ON */ + regmap_update_bits(regmap, 0xe58, BIT(0), BIT(0)); + regmap_update_bits(regmap, 0xeec, BIT(0), BIT(0)); + + return qcom_cc_really_probe(pdev, &video_cc_sm8250_desc, regmap); +} + +static struct platform_driver video_cc_sm8250_driver = { + .probe = video_cc_sm8250_probe, + .driver = { + .name = "sm8250-videocc", + .of_match_table = video_cc_sm8250_match_table, + }, +}; + +static int __init video_cc_sm8250_init(void) +{ + return platform_driver_register(&video_cc_sm8250_driver); +} +subsys_initcall(video_cc_sm8250_init); + +static void __exit video_cc_sm8250_exit(void) +{ + platform_driver_unregister(&video_cc_sm8250_driver); +} +module_exit(video_cc_sm8250_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("QTI VIDEOCC SM8250 Driver"); diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 28e8730ce263..18915d668a30 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -30,6 +30,7 @@ config CLK_RENESAS select CLK_R8A77980 if ARCH_R8A77980 select CLK_R8A77990 if ARCH_R8A77990 select CLK_R8A77995 if ARCH_R8A77995 + select CLK_R8A779A0 if ARCH_R8A779A0 select CLK_R9A06G032 if ARCH_R9A06G032 select CLK_SH73A0 if ARCH_SH73A0 @@ -145,6 +146,10 @@ config CLK_R8A77995 bool "R-Car D3 clock support" if COMPILE_TEST select CLK_RCAR_GEN3_CPG +config CLK_R8A779A0 + bool "R-Car V3U clock support" if COMPILE_TEST + select CLK_RENESAS_CPG_MSSR + config CLK_R9A06G032 bool "Renesas R9A06G032 clock driver" help @@ -162,7 +167,7 @@ config CLK_RCAR_GEN2_CPG select CLK_RENESAS_CPG_MSSR config CLK_RCAR_GEN3_CPG - bool "R-Car Gen3 CPG clock support" if COMPILE_TEST + bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR config CLK_RCAR_USB2_CLOCK_SEL diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index c7c03ab9a6a3..c803912ef2ce 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_CLK_R8A77970) += r8a77970-cpg-mssr.o obj-$(CONFIG_CLK_R8A77980) += r8a77980-cpg-mssr.o obj-$(CONFIG_CLK_R8A77990) += r8a77990-cpg-mssr.o obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o +obj-$(CONFIG_CLK_R8A779A0) += r8a779a0-cpg-mssr.o obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o diff --git a/drivers/clk/renesas/r7s9210-cpg-mssr.c b/drivers/clk/renesas/r7s9210-cpg-mssr.c index 443bff08df4c..a85227c248f3 100644 --- a/drivers/clk/renesas/r7s9210-cpg-mssr.c +++ b/drivers/clk/renesas/r7s9210-cpg-mssr.c @@ -214,7 +214,7 @@ const struct cpg_mssr_info r7s9210_cpg_mssr_info __initconst = { .cpg_clk_register = rza2_cpg_clk_register, /* RZ/A2 has Standby Control Registers */ - .stbyctrl = true, + .reg_layout = CLK_REG_LAYOUT_RZ_A, }; static void __init r7s9210_cpg_mssr_early_init(struct device_node *np) diff --git a/drivers/clk/renesas/r8a7742-cpg-mssr.c b/drivers/clk/renesas/r8a7742-cpg-mssr.c index e919828668a4..e541489bd1cd 100644 --- a/drivers/clk/renesas/r8a7742-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7742-cpg-mssr.c @@ -97,7 +97,8 @@ static const struct mssr_mod_clk r8a7742_mod_clks[] __initconst = { DEF_MOD("tmu0", 125, R8A7742_CLK_CP), DEF_MOD("vsp1du1", 127, R8A7742_CLK_ZS), DEF_MOD("vsp1du0", 128, R8A7742_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7742_CLK_ZS), + DEF_MOD("vspr", 130, R8A7742_CLK_ZS), + DEF_MOD("vsps", 131, R8A7742_CLK_ZS), DEF_MOD("scifa2", 202, R8A7742_CLK_MP), DEF_MOD("scifa1", 203, R8A7742_CLK_MP), DEF_MOD("scifa0", 204, R8A7742_CLK_MP), diff --git a/drivers/clk/renesas/r8a7743-cpg-mssr.c b/drivers/clk/renesas/r8a7743-cpg-mssr.c index c01d9af2525a..0bba12a48d22 100644 --- a/drivers/clk/renesas/r8a7743-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7743-cpg-mssr.c @@ -92,7 +92,7 @@ static const struct mssr_mod_clk r8a7743_mod_clks[] __initconst = { DEF_MOD("tmu0", 125, R8A7743_CLK_CP), DEF_MOD("vsp1du1", 127, R8A7743_CLK_ZS), DEF_MOD("vsp1du0", 128, R8A7743_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7743_CLK_ZS), + DEF_MOD("vsps", 131, R8A7743_CLK_ZS), DEF_MOD("scifa2", 202, R8A7743_CLK_MP), DEF_MOD("scifa1", 203, R8A7743_CLK_MP), DEF_MOD("scifa0", 204, R8A7743_CLK_MP), diff --git a/drivers/clk/renesas/r8a7745-cpg-mssr.c b/drivers/clk/renesas/r8a7745-cpg-mssr.c index 493874e5ebee..dc4a64e8dfb5 100644 --- a/drivers/clk/renesas/r8a7745-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7745-cpg-mssr.c @@ -90,7 +90,7 @@ static const struct mssr_mod_clk r8a7745_mod_clks[] __initconst = { DEF_MOD("cmt0", 124, R8A7745_CLK_R), DEF_MOD("tmu0", 125, R8A7745_CLK_CP), DEF_MOD("vsp1du0", 128, R8A7745_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7745_CLK_ZS), + DEF_MOD("vsps", 131, R8A7745_CLK_ZS), DEF_MOD("scifa2", 202, R8A7745_CLK_MP), DEF_MOD("scifa1", 203, R8A7745_CLK_MP), DEF_MOD("scifa0", 204, R8A7745_CLK_MP), diff --git a/drivers/clk/renesas/r8a77470-cpg-mssr.c b/drivers/clk/renesas/r8a77470-cpg-mssr.c index d81ae65f0d18..f3d6e65011d7 100644 --- a/drivers/clk/renesas/r8a77470-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77470-cpg-mssr.c @@ -85,7 +85,7 @@ static const struct mssr_mod_clk r8a77470_mod_clks[] __initconst = { DEF_MOD("tmu2", 122, R8A77470_CLK_P), DEF_MOD("cmt0", 124, R8A77470_CLK_R), DEF_MOD("vsp1du0", 128, R8A77470_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A77470_CLK_ZS), + DEF_MOD("vsps", 131, R8A77470_CLK_ZS), DEF_MOD("msiof2", 205, R8A77470_CLK_MP), DEF_MOD("msiof1", 208, R8A77470_CLK_MP), DEF_MOD("sys-dmac1", 218, R8A77470_CLK_ZS), diff --git a/drivers/clk/renesas/r8a7790-cpg-mssr.c b/drivers/clk/renesas/r8a7790-cpg-mssr.c index c57cb93f8315..f7d233e0c142 100644 --- a/drivers/clk/renesas/r8a7790-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7790-cpg-mssr.c @@ -108,8 +108,8 @@ static const struct mssr_mod_clk r8a7790_mod_clks[] __initconst = { DEF_MOD("tmu0", 125, R8A7790_CLK_CP), DEF_MOD("vsp1du1", 127, R8A7790_CLK_ZS), DEF_MOD("vsp1du0", 128, R8A7790_CLK_ZS), - DEF_MOD("vsp1-rt", 130, R8A7790_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7790_CLK_ZS), + DEF_MOD("vspr", 130, R8A7790_CLK_ZS), + DEF_MOD("vsps", 131, R8A7790_CLK_ZS), DEF_MOD("scifa2", 202, R8A7790_CLK_MP), DEF_MOD("scifa1", 203, R8A7790_CLK_MP), DEF_MOD("scifa0", 204, R8A7790_CLK_MP), diff --git a/drivers/clk/renesas/r8a7791-cpg-mssr.c b/drivers/clk/renesas/r8a7791-cpg-mssr.c index 65702debcabb..a0de784868da 100644 --- a/drivers/clk/renesas/r8a7791-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7791-cpg-mssr.c @@ -102,7 +102,7 @@ static const struct mssr_mod_clk r8a7791_mod_clks[] __initconst = { DEF_MOD("tmu0", 125, R8A7791_CLK_CP), DEF_MOD("vsp1du1", 127, R8A7791_CLK_ZS), DEF_MOD("vsp1du0", 128, R8A7791_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7791_CLK_ZS), + DEF_MOD("vsps", 131, R8A7791_CLK_ZS), DEF_MOD("scifa2", 202, R8A7791_CLK_MP), DEF_MOD("scifa1", 203, R8A7791_CLK_MP), DEF_MOD("scifa0", 204, R8A7791_CLK_MP), diff --git a/drivers/clk/renesas/r8a7792-cpg-mssr.c b/drivers/clk/renesas/r8a7792-cpg-mssr.c index cf8b84a3a060..77af250876a5 100644 --- a/drivers/clk/renesas/r8a7792-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7792-cpg-mssr.c @@ -88,7 +88,7 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = { DEF_MOD("tmu0", 125, R8A7792_CLK_CP), DEF_MOD("vsp1du1", 127, R8A7792_CLK_ZS), DEF_MOD("vsp1du0", 128, R8A7792_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7792_CLK_ZS), + DEF_MOD("vsps", 131, R8A7792_CLK_ZS), DEF_MOD("msiof1", 208, R8A7792_CLK_MP), DEF_MOD("sys-dmac1", 218, R8A7792_CLK_ZS), DEF_MOD("sys-dmac0", 219, R8A7792_CLK_ZS), diff --git a/drivers/clk/renesas/r8a7794-cpg-mssr.c b/drivers/clk/renesas/r8a7794-cpg-mssr.c index c1948693c5c1..4d7fa26a72c9 100644 --- a/drivers/clk/renesas/r8a7794-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7794-cpg-mssr.c @@ -97,7 +97,7 @@ static const struct mssr_mod_clk r8a7794_mod_clks[] __initconst = { DEF_MOD("cmt0", 124, R8A7794_CLK_R), DEF_MOD("tmu0", 125, R8A7794_CLK_CP), DEF_MOD("vsp1du0", 128, R8A7794_CLK_ZS), - DEF_MOD("vsp1-sy", 131, R8A7794_CLK_ZS), + DEF_MOD("vsps", 131, R8A7794_CLK_ZS), DEF_MOD("scifa2", 202, R8A7794_CLK_MP), DEF_MOD("scifa1", 203, R8A7794_CLK_MP), DEF_MOD("scifa0", 204, R8A7794_CLK_MP), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c new file mode 100644 index 000000000000..17ebbac7ddfb --- /dev/null +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -0,0 +1,276 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * r8a779a0 Clock Pulse Generator / Module Standby and Software Reset + * + * Copyright (C) 2020 Renesas Electronics Corp. + * + * Based on r8a7795-cpg-mssr.c + * + * Copyright (C) 2015 Glider bvba + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include <linux/bug.h> +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/pm.h> +#include <linux/slab.h> +#include <linux/soc/renesas/rcar-rst.h> + +#include <dt-bindings/clock/r8a779a0-cpg-mssr.h> + +#include "renesas-cpg-mssr.h" +#include "rcar-gen3-cpg.h" + +enum rcar_r8a779a0_clk_types { + CLK_TYPE_R8A779A0_MAIN = CLK_TYPE_CUSTOM, + CLK_TYPE_R8A779A0_PLL1, + CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */ + CLK_TYPE_R8A779A0_PLL5, + CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */ + CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */ +}; + +struct rcar_r8a779a0_cpg_pll_config { + u8 extal_div; + u8 pll1_mult; + u8 pll1_div; + u8 pll5_mult; + u8 pll5_div; + u8 osc_prediv; +}; + +enum clk_ids { + /* Core Clock Outputs exported to DT */ + LAST_DT_CORE_CLK = R8A779A0_CLK_OSC, + + /* External Input Clocks */ + CLK_EXTAL, + CLK_EXTALR, + + /* Internal Core Clocks */ + CLK_MAIN, + CLK_PLL1, + CLK_PLL20, + CLK_PLL21, + CLK_PLL30, + CLK_PLL31, + CLK_PLL5, + CLK_PLL1_DIV2, + CLK_PLL20_DIV2, + CLK_PLL21_DIV2, + CLK_PLL30_DIV2, + CLK_PLL31_DIV2, + CLK_PLL5_DIV2, + CLK_PLL5_DIV4, + CLK_S1, + CLK_S2, + CLK_S3, + CLK_SDSRC, + CLK_RPCSRC, + CLK_OCO, + + /* Module Clocks */ + MOD_CLK_BASE +}; + +#define DEF_PLL(_name, _id, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \ + .offset = _offset) + +static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { + /* External Clock Inputs */ + DEF_INPUT("extal", CLK_EXTAL), + DEF_INPUT("extalr", CLK_EXTALR), + + /* Internal Core Clocks */ + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_R8A779A0_MAIN, CLK_EXTAL), + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_R8A779A0_PLL1, CLK_MAIN), + DEF_BASE(".pll5", CLK_PLL5, CLK_TYPE_R8A779A0_PLL5, CLK_MAIN), + DEF_PLL(".pll20", CLK_PLL20, 0x0834), + DEF_PLL(".pll21", CLK_PLL21, 0x0838), + DEF_PLL(".pll30", CLK_PLL30, 0x083c), + DEF_PLL(".pll31", CLK_PLL31, 0x0840), + + DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1), + DEF_FIXED(".pll20_div2", CLK_PLL20_DIV2, CLK_PLL20, 2, 1), + DEF_FIXED(".pll21_div2", CLK_PLL21_DIV2, CLK_PLL21, 2, 1), + DEF_FIXED(".pll30_div2", CLK_PLL30_DIV2, CLK_PLL30, 2, 1), + DEF_FIXED(".pll31_div2", CLK_PLL31_DIV2, CLK_PLL31, 2, 1), + DEF_FIXED(".pll5_div2", CLK_PLL5_DIV2, CLK_PLL5, 2, 1), + DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1), + DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1), + DEF_RATE(".oco", CLK_OCO, 32768), + + /* Core Clock Outputs */ + DEF_FIXED("zx", R8A779A0_CLK_ZX, CLK_PLL20_DIV2, 2, 1), + DEF_FIXED("s1d1", R8A779A0_CLK_S1D1, CLK_S1, 1, 1), + DEF_FIXED("s1d2", R8A779A0_CLK_S1D2, CLK_S1, 2, 1), + DEF_FIXED("s1d4", R8A779A0_CLK_S1D4, CLK_S1, 4, 1), + DEF_FIXED("s1d8", R8A779A0_CLK_S1D8, CLK_S1, 8, 1), + DEF_FIXED("s1d12", R8A779A0_CLK_S1D12, CLK_S1, 12, 1), + DEF_FIXED("s3d1", R8A779A0_CLK_S3D1, CLK_S3, 1, 1), + DEF_FIXED("s3d2", R8A779A0_CLK_S3D2, CLK_S3, 2, 1), + DEF_FIXED("s3d4", R8A779A0_CLK_S3D4, CLK_S3, 4, 1), + DEF_FIXED("zs", R8A779A0_CLK_ZS, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED("zt", R8A779A0_CLK_ZT, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("ztr", R8A779A0_CLK_ZTR, CLK_PLL1_DIV2, 2, 1), + DEF_FIXED("zr", R8A779A0_CLK_ZR, CLK_PLL1_DIV2, 1, 1), + DEF_FIXED("dsi", R8A779A0_CLK_DSI, CLK_PLL5_DIV4, 1, 1), + DEF_FIXED("cnndsp", R8A779A0_CLK_CNNDSP, CLK_PLL5_DIV4, 1, 1), + DEF_FIXED("vip", R8A779A0_CLK_VIP, CLK_PLL5, 5, 1), + DEF_FIXED("adgh", R8A779A0_CLK_ADGH, CLK_PLL5_DIV4, 1, 1), + DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1), + DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1), + DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1), + DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_MAIN, 2, 1), + + DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), + DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), + DEF_DIV6P1("csi0", R8A779A0_CLK_CSI0, CLK_PLL5_DIV4, 0x880), + + DEF_GEN3_OSC("osc", R8A779A0_CLK_OSC, CLK_EXTAL, 8), + DEF_GEN3_MDSEL("r", R8A779A0_CLK_R, 29, CLK_EXTALR, 1, CLK_OCO, 1), +}; + +static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), + DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), + DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), + DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), +}; + +static spinlock_t cpg_lock; + +static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata; +static unsigned int cpg_clk_extalr __initdata; +static u32 cpg_mode __initdata; + +struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, + const struct cpg_core_clk *core, const struct cpg_mssr_info *info, + struct clk **clks, void __iomem *base, + struct raw_notifier_head *notifiers) +{ + const struct clk *parent; + unsigned int mult = 1; + unsigned int div = 1; + u32 value; + + parent = clks[core->parent & 0xffff]; /* some types use high bits */ + if (IS_ERR(parent)) + return ERR_CAST(parent); + + switch (core->type) { + case CLK_TYPE_R8A779A0_MAIN: + div = cpg_pll_config->extal_div; + break; + + case CLK_TYPE_R8A779A0_PLL1: + mult = cpg_pll_config->pll1_mult; + div = cpg_pll_config->pll1_div; + break; + + case CLK_TYPE_R8A779A0_PLL2X_3X: + value = readl(base + core->offset); + mult = (((value >> 24) & 0x7f) + 1) * 2; + break; + + case CLK_TYPE_R8A779A0_PLL5: + mult = cpg_pll_config->pll5_mult; + div = cpg_pll_config->pll5_div; + break; + + case CLK_TYPE_R8A779A0_MDSEL: + /* + * Clock selectable between two parents and two fixed dividers + * using a mode pin + */ + if (cpg_mode & BIT(core->offset)) { + div = core->div & 0xffff; + } else { + parent = clks[core->parent >> 16]; + if (IS_ERR(parent)) + return ERR_CAST(parent); + div = core->div >> 16; + } + mult = 1; + break; + + case CLK_TYPE_R8A779A0_OSC: + /* + * Clock combining OSC EXTAL predivider and a fixed divider + */ + div = cpg_pll_config->osc_prediv * core->div; + break; + + default: + return ERR_PTR(-EINVAL); + } + + return clk_register_fixed_factor(NULL, core->name, + __clk_get_name(parent), 0, mult, div); +} + +/* + * CPG Clock Data + */ +/* + * MD EXTAL PLL1 PLL20 PLL30 PLL4 PLL5 OSC + * 14 13 (MHz) 21 31 + * -------------------------------------------------------- + * 0 0 16.66 x 1 x128 x216 x128 x144 x192 /16 + * 0 1 20 x 1 x106 x180 x106 x120 x160 /19 + * 1 0 Prohibited setting + * 1 1 33.33 / 2 x128 x216 x128 x144 x192 /32 + */ +#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 13) | \ + (((md) & BIT(13)) >> 13)) + +static const struct rcar_r8a779a0_cpg_pll_config cpg_pll_configs[4] = { + /* EXTAL div PLL1 mult/div PLL5 mult/div OSC prediv */ + { 1, 128, 1, 192, 1, 16, }, + { 1, 106, 1, 160, 1, 19, }, + { 0, 0, 0, 0, 0, 0, }, + { 2, 128, 1, 192, 1, 32, }, +}; + +static int __init r8a779a0_cpg_mssr_init(struct device *dev) +{ + int error; + + error = rcar_rst_read_mode_pins(&cpg_mode); + if (error) + return error; + + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; + cpg_clk_extalr = CLK_EXTALR; + spin_lock_init(&cpg_lock); + + return 0; +} + +const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = { + /* Core Clocks */ + .core_clks = r8a779a0_core_clks, + .num_core_clks = ARRAY_SIZE(r8a779a0_core_clks), + .last_dt_core_clk = LAST_DT_CORE_CLK, + .num_total_core_clks = MOD_CLK_BASE, + + /* Module Clocks */ + .mod_clks = r8a779a0_mod_clks, + .num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks), + .num_hw_mod_clks = 15 * 32, + + /* Callbacks */ + .init = r8a779a0_cpg_mssr_init, + .cpg_clk_register = rcar_r8a779a0_cpg_clk_register, + + .reg_layout = CLK_REG_LAYOUT_RCAR_V3U, +}; diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 5a306d28738c..94db88370337 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -57,8 +57,10 @@ static const u16 mstpsr[] = { 0x9A0, 0x9A4, 0x9A8, 0x9AC, }; -#define MSTPSR(i) mstpsr[i] - +static const u16 mstpsr_for_v3u[] = { + 0x2E00, 0x2E04, 0x2E08, 0x2E0C, 0x2E10, 0x2E14, 0x2E18, 0x2E1C, + 0x2E20, 0x2E24, 0x2E28, 0x2E2C, 0x2E30, 0x2E34, 0x2E38, +}; /* * System Module Stop Control Register offsets @@ -69,7 +71,10 @@ static const u16 smstpcr[] = { 0x990, 0x994, 0x998, 0x99C, }; -#define SMSTPCR(i) smstpcr[i] +static const u16 mstpcr_for_v3u[] = { + 0x2D00, 0x2D04, 0x2D08, 0x2D0C, 0x2D10, 0x2D14, 0x2D18, 0x2D1C, + 0x2D20, 0x2D24, 0x2D28, 0x2D2C, 0x2D30, 0x2D34, 0x2D38, +}; /* * Standby Control Register offsets (RZ/A) @@ -81,8 +86,6 @@ static const u16 stbcr[] = { 0x424, 0x428, 0x42C, }; -#define STBCR(i) stbcr[i] - /* * Software Reset Register offsets */ @@ -92,8 +95,10 @@ static const u16 srcr[] = { 0x920, 0x924, 0x928, 0x92C, }; -#define SRCR(i) srcr[i] - +static const u16 srcr_for_v3u[] = { + 0x2C00, 0x2C04, 0x2C08, 0x2C0C, 0x2C10, 0x2C14, 0x2C18, 0x2C1C, + 0x2C20, 0x2C24, 0x2C28, 0x2C2C, 0x2C30, 0x2C34, 0x2C38, +}; /* Realtime Module Stop Control Register offsets */ #define RMSTPCR(i) (smstpcr[i] - 0x20) @@ -102,8 +107,16 @@ static const u16 srcr[] = { #define MMSTPCR(i) (smstpcr[i] + 0x20) /* Software Reset Clearing Register offsets */ -#define SRSTCLR(i) (0x940 + (i) * 4) +static const u16 srstclr[] = { + 0x940, 0x944, 0x948, 0x94C, 0x950, 0x954, 0x958, 0x95C, + 0x960, 0x964, 0x968, 0x96C, +}; + +static const u16 srstclr_for_v3u[] = { + 0x2C80, 0x2C84, 0x2C88, 0x2C8C, 0x2C90, 0x2C94, 0x2C98, 0x2C9C, + 0x2CA0, 0x2CA4, 0x2CA8, 0x2CAC, 0x2CB0, 0x2CB4, 0x2CB8, +}; /** * Clock Pulse Generator / Module Standby and Software Reset Private Data @@ -111,13 +124,17 @@ static const u16 srcr[] = { * @rcdev: Optional reset controller entity * @dev: CPG/MSSR device * @base: CPG/MSSR register block base address + * @reg_layout: CPG/MSSR register layout * @rmw_lock: protects RMW register accesses * @np: Device node in DT for this CPG/MSSR module * @num_core_clks: Number of Core Clocks in clks[] * @num_mod_clks: Number of Module Clocks in clks[] * @last_dt_core_clk: ID of the last Core Clock exported to DT - * @stbyctrl: This device has Standby Control Registers * @notifiers: Notifier chain to save/restore clock state for system resume + * @status_regs: Pointer to status registers array + * @control_regs: Pointer to control registers array + * @reset_regs: Pointer to reset registers array + * @reset_clear_regs: Pointer to reset clearing registers array * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control * @smstpcr_saved[].val: Saved values of SMSTPCR[] * @clks: Array containing all Core and Module Clocks @@ -128,19 +145,23 @@ struct cpg_mssr_priv { #endif struct device *dev; void __iomem *base; + enum clk_reg_layout reg_layout; spinlock_t rmw_lock; struct device_node *np; unsigned int num_core_clks; unsigned int num_mod_clks; unsigned int last_dt_core_clk; - bool stbyctrl; struct raw_notifier_head notifiers; + const u16 *status_regs; + const u16 *control_regs; + const u16 *reset_regs; + const u16 *reset_clear_regs; struct { u32 mask; u32 val; - } smstpcr_saved[ARRAY_SIZE(smstpcr)]; + } smstpcr_saved[ARRAY_SIZE(mstpsr_for_v3u)]; struct clk *clks[]; }; @@ -177,40 +198,40 @@ static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable) enable ? "ON" : "OFF"); spin_lock_irqsave(&priv->rmw_lock, flags); - if (priv->stbyctrl) { - value = readb(priv->base + STBCR(reg)); + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { + value = readb(priv->base + priv->control_regs[reg]); if (enable) value &= ~bitmask; else value |= bitmask; - writeb(value, priv->base + STBCR(reg)); + writeb(value, priv->base + priv->control_regs[reg]); /* dummy read to ensure write has completed */ - readb(priv->base + STBCR(reg)); - barrier_data(priv->base + STBCR(reg)); + readb(priv->base + priv->control_regs[reg]); + barrier_data(priv->base + priv->control_regs[reg]); } else { - value = readl(priv->base + SMSTPCR(reg)); + value = readl(priv->base + priv->control_regs[reg]); if (enable) value &= ~bitmask; else value |= bitmask; - writel(value, priv->base + SMSTPCR(reg)); + writel(value, priv->base + priv->control_regs[reg]); } spin_unlock_irqrestore(&priv->rmw_lock, flags); - if (!enable || priv->stbyctrl) + if (!enable || priv->reg_layout == CLK_REG_LAYOUT_RZ_A) return 0; for (i = 1000; i > 0; --i) { - if (!(readl(priv->base + MSTPSR(reg)) & bitmask)) + if (!(readl(priv->base + priv->status_regs[reg]) & bitmask)) break; cpu_relax(); } if (!i) { dev_err(dev, "Failed to enable SMSTP %p[%d]\n", - priv->base + SMSTPCR(reg), bit); + priv->base + priv->control_regs[reg], bit); return -ETIMEDOUT; } @@ -233,10 +254,10 @@ static int cpg_mstp_clock_is_enabled(struct clk_hw *hw) struct cpg_mssr_priv *priv = clock->priv; u32 value; - if (priv->stbyctrl) - value = readb(priv->base + STBCR(clock->index / 32)); + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) + value = readb(priv->base + priv->control_regs[clock->index / 32]); else - value = readl(priv->base + MSTPSR(clock->index / 32)); + value = readl(priv->base + priv->status_regs[clock->index / 32]); return !(value & BIT(clock->index % 32)); } @@ -272,7 +293,7 @@ struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec, case CPG_MOD: type = "module"; - if (priv->stbyctrl) { + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { idx = MOD_CLK_PACK_10(clkidx); range_check = 7 - (clkidx % 10); } else { @@ -578,13 +599,13 @@ static int cpg_mssr_reset(struct reset_controller_dev *rcdev, dev_dbg(priv->dev, "reset %u%02u\n", reg, bit); /* Reset module */ - writel(bitmask, priv->base + SRCR(reg)); + writel(bitmask, priv->base + priv->reset_regs[reg]); /* Wait for at least one cycle of the RCLK clock (@ ca. 32 kHz) */ udelay(35); /* Release module from reset state */ - writel(bitmask, priv->base + SRSTCLR(reg)); + writel(bitmask, priv->base + priv->reset_clear_regs[reg]); return 0; } @@ -598,7 +619,7 @@ static int cpg_mssr_assert(struct reset_controller_dev *rcdev, unsigned long id) dev_dbg(priv->dev, "assert %u%02u\n", reg, bit); - writel(bitmask, priv->base + SRCR(reg)); + writel(bitmask, priv->base + priv->reset_regs[reg]); return 0; } @@ -612,7 +633,7 @@ static int cpg_mssr_deassert(struct reset_controller_dev *rcdev, dev_dbg(priv->dev, "deassert %u%02u\n", reg, bit); - writel(bitmask, priv->base + SRSTCLR(reg)); + writel(bitmask, priv->base + priv->reset_clear_regs[reg]); return 0; } @@ -624,7 +645,7 @@ static int cpg_mssr_status(struct reset_controller_dev *rcdev, unsigned int bit = id % 32; u32 bitmask = BIT(bit); - return !!(readl(priv->base + SRCR(reg)) & bitmask); + return !!(readl(priv->base + priv->reset_regs[reg]) & bitmask); } static const struct reset_control_ops cpg_mssr_reset_ops = { @@ -804,6 +825,12 @@ static const struct of_device_id cpg_mssr_match[] = { .data = &r8a77995_cpg_mssr_info, }, #endif +#ifdef CONFIG_CLK_R8A779A0 + { + .compatible = "renesas,r8a779a0-cpg-mssr", + .data = &r8a779a0_cpg_mssr_info, + }, +#endif { /* sentinel */ } }; @@ -825,9 +852,10 @@ static int cpg_mssr_suspend_noirq(struct device *dev) /* Save module registers with bits under our control */ for (reg = 0; reg < ARRAY_SIZE(priv->smstpcr_saved); reg++) { if (priv->smstpcr_saved[reg].mask) - priv->smstpcr_saved[reg].val = priv->stbyctrl ? - readb(priv->base + STBCR(reg)) : - readl(priv->base + SMSTPCR(reg)); + priv->smstpcr_saved[reg].val = + priv->reg_layout == CLK_REG_LAYOUT_RZ_A ? + readb(priv->base + priv->control_regs[reg]) : + readl(priv->base + priv->control_regs[reg]); } /* Save core clocks */ @@ -855,23 +883,23 @@ static int cpg_mssr_resume_noirq(struct device *dev) if (!mask) continue; - if (priv->stbyctrl) - oldval = readb(priv->base + STBCR(reg)); + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) + oldval = readb(priv->base + priv->control_regs[reg]); else - oldval = readl(priv->base + SMSTPCR(reg)); + oldval = readl(priv->base + priv->control_regs[reg]); newval = oldval & ~mask; newval |= priv->smstpcr_saved[reg].val & mask; if (newval == oldval) continue; - if (priv->stbyctrl) { - writeb(newval, priv->base + STBCR(reg)); + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { + writeb(newval, priv->base + priv->control_regs[reg]); /* dummy read to ensure write has completed */ - readb(priv->base + STBCR(reg)); - barrier_data(priv->base + STBCR(reg)); + readb(priv->base + priv->control_regs[reg]); + barrier_data(priv->base + priv->control_regs[reg]); continue; } else - writel(newval, priv->base + SMSTPCR(reg)); + writel(newval, priv->base + priv->control_regs[reg]); /* Wait until enabled clocks are really enabled */ mask &= ~priv->smstpcr_saved[reg].val; @@ -879,7 +907,7 @@ static int cpg_mssr_resume_noirq(struct device *dev) continue; for (i = 1000; i > 0; --i) { - oldval = readl(priv->base + MSTPSR(reg)); + oldval = readl(priv->base + priv->status_regs[reg]); if (!(oldval & mask)) break; cpu_relax(); @@ -887,8 +915,8 @@ static int cpg_mssr_resume_noirq(struct device *dev) if (!i) dev_warn(dev, "Failed to enable %s%u[0x%x]\n", - priv->stbyctrl ? "STB" : "SMSTP", reg, - oldval & mask); + priv->reg_layout == CLK_REG_LAYOUT_RZ_A ? + "STB" : "SMSTP", reg, oldval & mask); } return 0; @@ -937,7 +965,23 @@ static int __init cpg_mssr_common_init(struct device *dev, priv->num_mod_clks = info->num_hw_mod_clks; priv->last_dt_core_clk = info->last_dt_core_clk; RAW_INIT_NOTIFIER_HEAD(&priv->notifiers); - priv->stbyctrl = info->stbyctrl; + priv->reg_layout = info->reg_layout; + if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3) { + priv->status_regs = mstpsr; + priv->control_regs = smstpcr; + priv->reset_regs = srcr; + priv->reset_clear_regs = srstclr; + } else if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) { + priv->control_regs = stbcr; + } else if (priv->reg_layout == CLK_REG_LAYOUT_RCAR_V3U) { + priv->status_regs = mstpsr_for_v3u; + priv->control_regs = mstpcr_for_v3u; + priv->reset_regs = srcr_for_v3u; + priv->reset_clear_regs = srstclr_for_v3u; + } else { + error = -EINVAL; + goto out_err; + } for (i = 0; i < nclks; i++) priv->clks[i] = ERR_PTR(-ENOENT); @@ -1015,7 +1059,7 @@ static int __init cpg_mssr_probe(struct platform_device *pdev) return error; /* Reset Controller not supported for Standby Control SoCs */ - if (info->stbyctrl) + if (priv->reg_layout == CLK_REG_LAYOUT_RZ_A) return 0; error = cpg_mssr_reset_controller_register(priv); diff --git a/drivers/clk/renesas/renesas-cpg-mssr.h b/drivers/clk/renesas/renesas-cpg-mssr.h index 1cc569484250..6b2a0ade482e 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.h +++ b/drivers/clk/renesas/renesas-cpg-mssr.h @@ -85,6 +85,12 @@ struct mssr_mod_clk { struct device_node; +enum clk_reg_layout { + CLK_REG_LAYOUT_RCAR_GEN2_AND_GEN3 = 0, + CLK_REG_LAYOUT_RZ_A, + CLK_REG_LAYOUT_RCAR_V3U, +}; + /** * SoC-specific CPG/MSSR Description * @@ -105,6 +111,7 @@ struct device_node; * @crit_mod_clks: Array with Module Clock IDs of critical clocks that * should not be disabled without a knowledgeable driver * @num_crit_mod_clks: Number of entries in crit_mod_clks[] + * @reg_layout: CPG/MSSR register layout from enum clk_reg_layout * * @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power * Management, in addition to Module Clocks @@ -112,10 +119,6 @@ struct device_node; * * @init: Optional callback to perform SoC-specific initialization * @cpg_clk_register: Optional callback to handle special Core Clock types - * - * @stbyctrl: This device has Standby Control Registers which are 8-bits - * wide, no status registers (MSTPSR) and have different address - * offsets. */ struct cpg_mssr_info { @@ -130,7 +133,7 @@ struct cpg_mssr_info { unsigned int num_core_clks; unsigned int last_dt_core_clk; unsigned int num_total_core_clks; - bool stbyctrl; + enum clk_reg_layout reg_layout; /* Module Clocks */ const struct mssr_mod_clk *mod_clks; @@ -174,6 +177,7 @@ extern const struct cpg_mssr_info r8a77970_cpg_mssr_info; extern const struct cpg_mssr_info r8a77980_cpg_mssr_info; extern const struct cpg_mssr_info r8a77990_cpg_mssr_info; extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; +extern const struct cpg_mssr_info r8a779a0_cpg_mssr_info; void __init cpg_mssr_early_init(struct device_node *np, const struct cpg_mssr_info *info); diff --git a/drivers/clk/rockchip/Kconfig b/drivers/clk/rockchip/Kconfig new file mode 100644 index 000000000000..47cd6c5de837 --- /dev/null +++ b/drivers/clk/rockchip/Kconfig @@ -0,0 +1,78 @@ +# SPDX-License-Identifier: GPL-2.0 +# common clock support for ROCKCHIP SoC family. + +config COMMON_CLK_ROCKCHIP + bool "Rockchip clock controller common support" + depends on ARCH_ROCKCHIP + default ARCH_ROCKCHIP + help + Say y here to enable common clock controller for Rockchip platforms. + +if COMMON_CLK_ROCKCHIP +config CLK_PX30 + bool "Rockchip PX30 clock controller support" + default y + help + Build the driver for PX30 Clock Driver. + +config CLK_RV110X + bool "Rockchip RV110x clock controller support" + default y + help + Build the driver for RV110x Clock Driver. + +config CLK_RK3036 + bool "Rockchip RK3036 clock controller support" + default y + help + Build the driver for RK3036 Clock Driver. + +config CLK_RK312X + bool "Rockchip RK312x clock controller support" + default y + help + Build the driver for RK312x Clock Driver. + +config CLK_RK3188 + bool "Rockchip RK3188 clock controller support" + default y + help + Build the driver for RK3188 Clock Driver. + +config CLK_RK322X + bool "Rockchip RK322x clock controller support" + default y + help + Build the driver for RK322x Clock Driver. + +config CLK_RK3288 + bool "Rockchip RK3288 clock controller support" + depends on ARM + default y + help + Build the driver for RK3288 Clock Driver. + +config CLK_RK3308 + bool "Rockchip RK3308 clock controller support" + default y + help + Build the driver for RK3308 Clock Driver. + +config CLK_RK3328 + bool "Rockchip RK3328 clock controller support" + default y + help + Build the driver for RK3328 Clock Driver. + +config CLK_RK3368 + bool "Rockchip RK3368 clock controller support" + default y + help + Build the driver for RK3368 Clock Driver. + +config CLK_RK3399 + tristate "Rockchip RK3399 clock controller support" + default y + help + Build the driver for RK3399 Clock Driver. +endif diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 7c5b5813a87c..a99e4d9bbae1 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile @@ -3,24 +3,26 @@ # Rockchip Clock specific Makefile # -obj-y += clk.o -obj-y += clk-pll.o -obj-y += clk-cpu.o -obj-y += clk-half-divider.o -obj-y += clk-inverter.o -obj-y += clk-mmc-phase.o -obj-y += clk-muxgrf.o -obj-y += clk-ddr.o -obj-$(CONFIG_RESET_CONTROLLER) += softrst.o +obj-$(CONFIG_COMMON_CLK_ROCKCHIP) += clk-rockchip.o -obj-y += clk-px30.o -obj-y += clk-rv1108.o -obj-y += clk-rk3036.o -obj-y += clk-rk3128.o -obj-y += clk-rk3188.o -obj-y += clk-rk3228.o -obj-y += clk-rk3288.o -obj-y += clk-rk3308.o -obj-y += clk-rk3328.o -obj-y += clk-rk3368.o -obj-y += clk-rk3399.o +clk-rockchip-y += clk.o +clk-rockchip-y += clk-pll.o +clk-rockchip-y += clk-cpu.o +clk-rockchip-y += clk-half-divider.o +clk-rockchip-y += clk-inverter.o +clk-rockchip-y += clk-mmc-phase.o +clk-rockchip-y += clk-muxgrf.o +clk-rockchip-y += clk-ddr.o +clk-rockchip-$(CONFIG_RESET_CONTROLLER) += softrst.o + +obj-$(CONFIG_CLK_PX30) += clk-px30.o +obj-$(CONFIG_CLK_RV110X) += clk-rv1108.o +obj-$(CONFIG_CLK_RK3036) += clk-rk3036.o +obj-$(CONFIG_CLK_RK312X) += clk-rk3128.o +obj-$(CONFIG_CLK_RK3188) += clk-rk3188.o +obj-$(CONFIG_CLK_RK322X) += clk-rk3228.o +obj-$(CONFIG_CLK_RK3288) += clk-rk3288.o +obj-$(CONFIG_CLK_RK3308) += clk-rk3308.o +obj-$(CONFIG_CLK_RK3328) += clk-rk3328.o +obj-$(CONFIG_CLK_RK3368) += clk-rk3368.o +obj-$(CONFIG_CLK_RK3399) += clk-rk3399.o diff --git a/drivers/clk/rockchip/clk-ddr.c b/drivers/clk/rockchip/clk-ddr.c index 9273bce4d7b6..86718c54e56b 100644 --- a/drivers/clk/rockchip/clk-ddr.c +++ b/drivers/clk/rockchip/clk-ddr.c @@ -136,3 +136,4 @@ struct clk *rockchip_clk_register_ddrclk(const char *name, int flags, return clk; } +EXPORT_SYMBOL_GPL(rockchip_clk_register_ddrclk); diff --git a/drivers/clk/rockchip/clk-half-divider.c b/drivers/clk/rockchip/clk-half-divider.c index b333fc28c94b..ccd5c270c213 100644 --- a/drivers/clk/rockchip/clk-half-divider.c +++ b/drivers/clk/rockchip/clk-half-divider.c @@ -166,7 +166,7 @@ struct clk *rockchip_clk_register_halfdiv(const char *name, unsigned long flags, spinlock_t *lock) { - struct clk *clk; + struct clk_hw *hw = ERR_PTR(-ENOMEM); struct clk_mux *mux = NULL; struct clk_gate *gate = NULL; struct clk_divider *div = NULL; @@ -212,16 +212,18 @@ struct clk *rockchip_clk_register_halfdiv(const char *name, div_ops = &clk_half_divider_ops; } - clk = clk_register_composite(NULL, name, parent_names, num_parents, - mux ? &mux->hw : NULL, mux_ops, - div ? &div->hw : NULL, div_ops, - gate ? &gate->hw : NULL, gate_ops, - flags); + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux ? &mux->hw : NULL, mux_ops, + div ? &div->hw : NULL, div_ops, + gate ? &gate->hw : NULL, gate_ops, + flags); + if (IS_ERR(hw)) + goto err_div; - return clk; + return hw->clk; err_div: kfree(gate); err_gate: kfree(mux); - return ERR_PTR(-ENOMEM); + return ERR_CAST(hw); } diff --git a/drivers/clk/rockchip/clk-rk3308.c b/drivers/clk/rockchip/clk-rk3308.c index b0baf87a283e..5bf15f2a44b7 100644 --- a/drivers/clk/rockchip/clk-rk3308.c +++ b/drivers/clk/rockchip/clk-rk3308.c @@ -133,7 +133,6 @@ PNAME(mux_uart1_p) = { "clk_uart1_src", "dummy", "clk_uart1_frac" }; PNAME(mux_uart2_p) = { "clk_uart2_src", "dummy", "clk_uart2_frac" }; PNAME(mux_uart3_p) = { "clk_uart3_src", "dummy", "clk_uart3_frac" }; PNAME(mux_uart4_p) = { "clk_uart4_src", "dummy", "clk_uart4_frac" }; -PNAME(mux_timer_src_p) = { "xin24m", "clk_rtc32k" }; PNAME(mux_dclk_vop_p) = { "dclk_vop_src", "dclk_vop_frac", "xin24m" }; PNAME(mux_nandc_p) = { "clk_nandc_div", "clk_nandc_div50" }; PNAME(mux_sdmmc_p) = { "clk_sdmmc_div", "clk_sdmmc_div50" }; diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index ce1d2446f142..7df2f1e00347 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -5,9 +5,11 @@ */ #include <linux/clk-provider.h> +#include <linux/module.h> #include <linux/io.h> #include <linux/of.h> #include <linux/of_address.h> +#include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/regmap.h> #include <dt-bindings/clock/rk3399-cru.h> @@ -1600,3 +1602,57 @@ static void __init rk3399_pmu_clk_init(struct device_node *np) rockchip_clk_of_add_provider(np, ctx); } CLK_OF_DECLARE(rk3399_cru_pmu, "rockchip,rk3399-pmucru", rk3399_pmu_clk_init); + +struct clk_rk3399_inits { + void (*inits)(struct device_node *np); +}; + +static const struct clk_rk3399_inits clk_rk3399_pmucru_init = { + .inits = rk3399_pmu_clk_init, +}; + +static const struct clk_rk3399_inits clk_rk3399_cru_init = { + .inits = rk3399_clk_init, +}; + +static const struct of_device_id clk_rk3399_match_table[] = { + { + .compatible = "rockchip,rk3399-cru", + .data = &clk_rk3399_cru_init, + }, { + .compatible = "rockchip,rk3399-pmucru", + .data = &clk_rk3399_pmucru_init, + }, + { } +}; +MODULE_DEVICE_TABLE(of, clk_rk3399_match_table); + +static int __init clk_rk3399_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + const struct clk_rk3399_inits *init_data; + + match = of_match_device(clk_rk3399_match_table, &pdev->dev); + if (!match || !match->data) + return -EINVAL; + + init_data = match->data; + if (init_data->inits) + init_data->inits(np); + + return 0; +} + +static struct platform_driver clk_rk3399_driver = { + .driver = { + .name = "clk-rk3399", + .of_match_table = clk_rk3399_match_table, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver_probe(clk_rk3399_driver, clk_rk3399_probe); + +MODULE_DESCRIPTION("Rockchip RK3399 Clock Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:clk-rk3399"); diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 546e810c3560..b443169dd408 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -43,7 +43,7 @@ static struct clk *rockchip_clk_register_branch(const char *name, u8 gate_shift, u8 gate_flags, unsigned long flags, spinlock_t *lock) { - struct clk *clk; + struct clk_hw *hw; struct clk_mux *mux = NULL; struct clk_gate *gate = NULL; struct clk_divider *div = NULL; @@ -100,20 +100,18 @@ static struct clk *rockchip_clk_register_branch(const char *name, : &clk_divider_ops; } - clk = clk_register_composite(NULL, name, parent_names, num_parents, - mux ? &mux->hw : NULL, mux_ops, - div ? &div->hw : NULL, div_ops, - gate ? &gate->hw : NULL, gate_ops, - flags); - - if (IS_ERR(clk)) { - ret = PTR_ERR(clk); - goto err_composite; + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + mux ? &mux->hw : NULL, mux_ops, + div ? &div->hw : NULL, div_ops, + gate ? &gate->hw : NULL, gate_ops, + flags); + if (IS_ERR(hw)) { + kfree(div); + kfree(gate); + return ERR_CAST(hw); } - return clk; -err_composite: - kfree(div); + return hw->clk; err_div: kfree(gate); err_gate: @@ -214,8 +212,8 @@ static struct clk *rockchip_clk_register_frac_branch( unsigned long flags, struct rockchip_clk_branch *child, spinlock_t *lock) { + struct clk_hw *hw; struct rockchip_clk_frac *frac; - struct clk *clk; struct clk_gate *gate = NULL; struct clk_fractional_divider *div = NULL; const struct clk_ops *div_ops = NULL, *gate_ops = NULL; @@ -255,14 +253,14 @@ static struct clk *rockchip_clk_register_frac_branch( div->approximation = rockchip_fractional_approximation; div_ops = &clk_fractional_divider_ops; - clk = clk_register_composite(NULL, name, parent_names, num_parents, - NULL, NULL, - &div->hw, div_ops, - gate ? &gate->hw : NULL, gate_ops, - flags | CLK_SET_RATE_UNGATE); - if (IS_ERR(clk)) { + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + NULL, NULL, + &div->hw, div_ops, + gate ? &gate->hw : NULL, gate_ops, + flags | CLK_SET_RATE_UNGATE); + if (IS_ERR(hw)) { kfree(frac); - return clk; + return ERR_CAST(hw); } if (child) { @@ -292,7 +290,7 @@ static struct clk *rockchip_clk_register_frac_branch( mux_clk = clk_register(NULL, &frac_mux->hw); if (IS_ERR(mux_clk)) { kfree(frac); - return clk; + return mux_clk; } rockchip_clk_add_lookup(ctx, mux_clk, child->id); @@ -301,7 +299,7 @@ static struct clk *rockchip_clk_register_frac_branch( if (frac->mux_frac_idx >= 0) { pr_debug("%s: found fractional parent in mux at pos %d\n", __func__, frac->mux_frac_idx); - ret = clk_notifier_register(clk, &frac->clk_nb); + ret = clk_notifier_register(hw->clk, &frac->clk_nb); if (ret) pr_err("%s: failed to register clock notifier for %s\n", __func__, name); @@ -311,7 +309,7 @@ static struct clk *rockchip_clk_register_frac_branch( } } - return clk; + return hw->clk; } static struct clk *rockchip_clk_register_factor_branch(const char *name, @@ -320,7 +318,7 @@ static struct clk *rockchip_clk_register_factor_branch(const char *name, int gate_offset, u8 gate_shift, u8 gate_flags, unsigned long flags, spinlock_t *lock) { - struct clk *clk; + struct clk_hw *hw; struct clk_gate *gate = NULL; struct clk_fixed_factor *fix = NULL; @@ -349,20 +347,22 @@ static struct clk *rockchip_clk_register_factor_branch(const char *name, fix->mult = mult; fix->div = div; - clk = clk_register_composite(NULL, name, parent_names, num_parents, - NULL, NULL, - &fix->hw, &clk_fixed_factor_ops, - &gate->hw, &clk_gate_ops, flags); - if (IS_ERR(clk)) { + hw = clk_hw_register_composite(NULL, name, parent_names, num_parents, + NULL, NULL, + &fix->hw, &clk_fixed_factor_ops, + &gate->hw, &clk_gate_ops, flags); + if (IS_ERR(hw)) { kfree(fix); kfree(gate); + return ERR_CAST(hw); } - return clk; + return hw->clk; } -struct rockchip_clk_provider * __init rockchip_clk_init(struct device_node *np, - void __iomem *base, unsigned long nr_clks) +struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np, + void __iomem *base, + unsigned long nr_clks) { struct rockchip_clk_provider *ctx; struct clk **clk_table; @@ -394,14 +394,16 @@ err_free: kfree(ctx); return ERR_PTR(-ENOMEM); } +EXPORT_SYMBOL_GPL(rockchip_clk_init); -void __init rockchip_clk_of_add_provider(struct device_node *np, - struct rockchip_clk_provider *ctx) +void rockchip_clk_of_add_provider(struct device_node *np, + struct rockchip_clk_provider *ctx) { if (of_clk_add_provider(np, of_clk_src_onecell_get, &ctx->clk_data)) pr_err("%s: could not register clk provider\n", __func__); } +EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider); void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, struct clk *clk, unsigned int id) @@ -409,8 +411,9 @@ void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx, if (ctx->clk_data.clks && id) ctx->clk_data.clks[id] = clk; } +EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup); -void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, +void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, struct rockchip_pll_clock *list, unsigned int nr_pll, int grf_lock_offset) { @@ -433,11 +436,11 @@ void __init rockchip_clk_register_plls(struct rockchip_clk_provider *ctx, rockchip_clk_add_lookup(ctx, clk, list->id); } } +EXPORT_SYMBOL_GPL(rockchip_clk_register_plls); -void __init rockchip_clk_register_branches( - struct rockchip_clk_provider *ctx, - struct rockchip_clk_branch *list, - unsigned int nr_clk) +void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx, + struct rockchip_clk_branch *list, + unsigned int nr_clk) { struct clk *clk = NULL; unsigned int idx; @@ -566,14 +569,15 @@ void __init rockchip_clk_register_branches( rockchip_clk_add_lookup(ctx, clk, list->id); } } - -void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, - unsigned int lookup_id, - const char *name, const char *const *parent_names, - u8 num_parents, - const struct rockchip_cpuclk_reg_data *reg_data, - const struct rockchip_cpuclk_rate_table *rates, - int nrates) +EXPORT_SYMBOL_GPL(rockchip_clk_register_branches); + +void rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, + unsigned int lookup_id, + const char *name, const char *const *parent_names, + u8 num_parents, + const struct rockchip_cpuclk_reg_data *reg_data, + const struct rockchip_cpuclk_rate_table *rates, + int nrates) { struct clk *clk; @@ -588,9 +592,10 @@ void __init rockchip_clk_register_armclk(struct rockchip_clk_provider *ctx, rockchip_clk_add_lookup(ctx, clk, lookup_id); } +EXPORT_SYMBOL_GPL(rockchip_clk_register_armclk); -void __init rockchip_clk_protect_critical(const char *const clocks[], - int nclocks) +void rockchip_clk_protect_critical(const char *const clocks[], + int nclocks) { int i; @@ -602,6 +607,7 @@ void __init rockchip_clk_protect_critical(const char *const clocks[], clk_prepare_enable(clk); } } +EXPORT_SYMBOL_GPL(rockchip_clk_protect_critical); static void __iomem *rst_base; static unsigned int reg_restart; @@ -621,10 +627,10 @@ static struct notifier_block rockchip_restart_handler = { .priority = 128, }; -void __init +void rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, - unsigned int reg, - void (*cb)(void)) + unsigned int reg, + void (*cb)(void)) { int ret; @@ -636,3 +642,4 @@ rockchip_register_restart_notifier(struct rockchip_clk_provider *ctx, pr_err("%s: cannot register restart handler, %d\n", __func__, ret); } +EXPORT_SYMBOL_GPL(rockchip_register_restart_notifier); diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c index 5f1ff5e47c4f..5d07266745b8 100644 --- a/drivers/clk/rockchip/softrst.c +++ b/drivers/clk/rockchip/softrst.c @@ -77,9 +77,9 @@ static const struct reset_control_ops rockchip_softrst_ops = { .deassert = rockchip_softrst_deassert, }; -void __init rockchip_register_softrst(struct device_node *np, - unsigned int num_regs, - void __iomem *base, u8 flags) +void rockchip_register_softrst(struct device_node *np, + unsigned int num_regs, + void __iomem *base, u8 flags) { struct rockchip_softrst *softrst; int ret; @@ -107,3 +107,4 @@ void __init rockchip_register_softrst(struct device_node *np, kfree(softrst); } }; +EXPORT_SYMBOL_GPL(rockchip_register_softrst); diff --git a/drivers/clk/samsung/clk-cpu.c b/drivers/clk/samsung/clk-cpu.c index efc4fa61fbaf..00ef4d1b0888 100644 --- a/drivers/clk/samsung/clk-cpu.c +++ b/drivers/clk/samsung/clk-cpu.c @@ -401,26 +401,34 @@ static int exynos5433_cpuclk_notifier_cb(struct notifier_block *nb, /* helper function to register a CPU clock */ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, - unsigned int lookup_id, const char *name, const char *parent, - const char *alt_parent, unsigned long offset, - const struct exynos_cpuclk_cfg_data *cfg, + unsigned int lookup_id, const char *name, + const struct clk_hw *parent, const struct clk_hw *alt_parent, + unsigned long offset, const struct exynos_cpuclk_cfg_data *cfg, unsigned long num_cfgs, unsigned long flags) { struct exynos_cpuclk *cpuclk; struct clk_init_data init; - struct clk *parent_clk; + const char *parent_name; int ret = 0; + if (IS_ERR(parent) || IS_ERR(alt_parent)) { + pr_err("%s: invalid parent clock(s)\n", __func__); + return -EINVAL; + } + cpuclk = kzalloc(sizeof(*cpuclk), GFP_KERNEL); if (!cpuclk) return -ENOMEM; + parent_name = clk_hw_get_name(parent); + init.name = name; init.flags = CLK_SET_RATE_PARENT; - init.parent_names = &parent; + init.parent_names = &parent_name; init.num_parents = 1; init.ops = &exynos_cpuclk_clk_ops; + cpuclk->alt_parent = alt_parent; cpuclk->hw.init = &init; cpuclk->ctrl_base = ctx->reg_base + offset; cpuclk->lock = &ctx->lock; @@ -430,23 +438,8 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, else cpuclk->clk_nb.notifier_call = exynos_cpuclk_notifier_cb; - cpuclk->alt_parent = __clk_get_hw(__clk_lookup(alt_parent)); - if (!cpuclk->alt_parent) { - pr_err("%s: could not lookup alternate parent %s\n", - __func__, alt_parent); - ret = -EINVAL; - goto free_cpuclk; - } - - parent_clk = __clk_lookup(parent); - if (!parent_clk) { - pr_err("%s: could not lookup parent clock %s\n", - __func__, parent); - ret = -EINVAL; - goto free_cpuclk; - } - ret = clk_notifier_register(parent_clk, &cpuclk->clk_nb); + ret = clk_notifier_register(parent->clk, &cpuclk->clk_nb); if (ret) { pr_err("%s: failed to register clock notifier for %s\n", __func__, name); @@ -471,7 +464,7 @@ int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, free_cpuclk_data: kfree(cpuclk->cfg); unregister_clk_nb: - clk_notifier_unregister(parent_clk, &cpuclk->clk_nb); + clk_notifier_unregister(parent->clk, &cpuclk->clk_nb); free_cpuclk: kfree(cpuclk); return ret; diff --git a/drivers/clk/samsung/clk-cpu.h b/drivers/clk/samsung/clk-cpu.h index ad38cc27f3df..af74686db9ef 100644 --- a/drivers/clk/samsung/clk-cpu.h +++ b/drivers/clk/samsung/clk-cpu.h @@ -46,7 +46,7 @@ struct exynos_cpuclk_cfg_data { */ struct exynos_cpuclk { struct clk_hw hw; - struct clk_hw *alt_parent; + const struct clk_hw *alt_parent; void __iomem *ctrl_base; spinlock_t *lock; const struct exynos_cpuclk_cfg_data *cfg; @@ -62,9 +62,9 @@ struct exynos_cpuclk { #define CLK_CPU_HAS_E5433_REGS_LAYOUT (1 << 2) }; -extern int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, +int __init exynos_register_cpu_clock(struct samsung_clk_provider *ctx, unsigned int lookup_id, const char *name, - const char *parent, const char *alt_parent, + const struct clk_hw *parent, const struct clk_hw *alt_parent, unsigned long offset, const struct exynos_cpuclk_cfg_data *cfg, unsigned long num_cfgs, unsigned long flags); diff --git a/drivers/clk/samsung/clk-exynos3250.c b/drivers/clk/samsung/clk-exynos3250.c index 17897c7a84d4..17df7f9755aa 100644 --- a/drivers/clk/samsung/clk-exynos3250.c +++ b/drivers/clk/samsung/clk-exynos3250.c @@ -808,14 +808,16 @@ static const struct exynos_cpuclk_cfg_data e3250_armclk_d[] __initconst = { static void __init exynos3250_cmu_init(struct device_node *np) { struct samsung_clk_provider *ctx; + struct clk_hw **hws; ctx = samsung_cmu_register_one(np, &cmu_info); if (!ctx) return; + hws = ctx->clk_data.hws; exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p[0], mout_core_p[1], 0x14200, - e3250_armclk_d, ARRAY_SIZE(e3250_armclk_d), + hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL_USER_C], + 0x14200, e3250_armclk_d, ARRAY_SIZE(e3250_armclk_d), CLK_CPU_HAS_DIV1); exynos3_core_down_clock(ctx->reg_base); diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index 51564fc23c63..436fcd279951 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -1233,6 +1233,8 @@ static void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc soc) { struct samsung_clk_provider *ctx; + struct clk_hw **hws; + exynos4_soc = soc; reg_base = of_iomap(np, 0); @@ -1240,6 +1242,7 @@ static void __init exynos4_clk_init(struct device_node *np, panic("%s: failed to map registers\n", __func__); ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + hws = ctx->clk_data.hws; samsung_clk_of_register_fixed_ext(ctx, exynos4_fixed_rate_ext_clks, ARRAY_SIZE(exynos4_fixed_rate_ext_clks), @@ -1302,7 +1305,7 @@ static void __init exynos4_clk_init(struct device_node *np, exynos4210_fixed_factor_clks, ARRAY_SIZE(exynos4210_fixed_factor_clks)); exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4210[0], mout_core_p4210[1], 0x14200, + hws[CLK_MOUT_APLL], hws[CLK_SCLK_MPLL], 0x14200, e4210_armclk_d, ARRAY_SIZE(e4210_armclk_d), CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } else { @@ -1317,7 +1320,7 @@ static void __init exynos4_clk_init(struct device_node *np, ARRAY_SIZE(exynos4x12_fixed_factor_clks)); exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_core_p4x12[0], mout_core_p4x12[1], 0x14200, + hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL_USER_C], 0x14200, e4412_armclk_d, ARRAY_SIZE(e4412_armclk_d), CLK_CPU_NEEDS_DEBUG_ALT_DIV | CLK_CPU_HAS_DIV1); } diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c index 931c70a4da19..06588fab408a 100644 --- a/drivers/clk/samsung/clk-exynos5250.c +++ b/drivers/clk/samsung/clk-exynos5250.c @@ -253,14 +253,14 @@ static const struct samsung_mux_clock exynos5250_mux_clks[] __initconst = { /* * CMU_CPU */ - MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, CLK_SET_RATE_PARENT, 0), MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), /* * CMU_CORE */ - MUX(0, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1), + MUX(CLK_MOUT_MPLL, "mout_mpll", mout_mpll_p, SRC_CORE1, 8, 1), /* * CMU_TOP @@ -782,6 +782,7 @@ static void __init exynos5250_clk_init(struct device_node *np) { struct samsung_clk_provider *ctx; unsigned int tmp; + struct clk_hw **hws; if (np) { reg_base = of_iomap(np, 0); @@ -792,6 +793,7 @@ static void __init exynos5250_clk_init(struct device_node *np) } ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + hws = ctx->clk_data.hws; samsung_clk_of_register_fixed_ext(ctx, exynos5250_fixed_rate_ext_clks, ARRAY_SIZE(exynos5250_fixed_rate_ext_clks), @@ -821,7 +823,7 @@ static void __init exynos5250_clk_init(struct device_node *np) samsung_clk_register_gate(ctx, exynos5250_gate_clks, ARRAY_SIZE(exynos5250_gate_clks)); exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_cpu_p[0], mout_cpu_p[1], 0x200, + hws[CLK_MOUT_APLL], hws[CLK_MOUT_MPLL], 0x200, exynos5250_armclk_d, ARRAY_SIZE(exynos5250_armclk_d), CLK_CPU_HAS_DIV1); diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index fea33399a632..3ccd4eabd2a6 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -596,13 +596,14 @@ static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = { static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, SRC_TOP7, 4, 1), - MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2), - MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2), - - MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, + MUX(CLK_MOUT_MSPLL_KFC, "mout_mspll_kfc", mout_mspll_cpu_p, + SRC_TOP7, 8, 2), + MUX(CLK_MOUT_MSPLL_CPU, "mout_mspll_cpu", mout_mspll_cpu_p, + SRC_TOP7, 12, 2), + MUX_F(CLK_MOUT_APLL, "mout_apll", mout_apll_p, SRC_CPU, 0, 1, CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1), - MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1, + MUX_F(CLK_MOUT_KPLL, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1, CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0), MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1), @@ -712,8 +713,8 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { SRC_TOP12, 8, 1), MUX(0, "mout_sw_aclk266_g2d", mout_sw_aclk266_g2d_p, SRC_TOP12, 12, 1), - MUX_F(0, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, SRC_TOP12, 16, 1, - CLK_SET_RATE_PARENT, 0), + MUX_F(CLK_MOUT_SW_ACLK_G3D, "mout_sw_aclk_g3d", mout_sw_aclk_g3d_p, + SRC_TOP12, 16, 1, CLK_SET_RATE_PARENT, 0), MUX(0, "mout_sw_aclk300_jpeg", mout_sw_aclk300_jpeg_p, SRC_TOP12, 20, 1), MUX(CLK_MOUT_SW_ACLK300, "mout_sw_aclk300_disp1", @@ -1560,6 +1561,7 @@ static void __init exynos5x_clk_init(struct device_node *np, enum exynos5x_soc soc) { struct samsung_clk_provider *ctx; + struct clk_hw **hws; if (np) { reg_base = of_iomap(np, 0); @@ -1572,6 +1574,7 @@ static void __init exynos5x_clk_init(struct device_node *np, exynos5x_soc = soc; ctx = samsung_clk_init(np, reg_base, CLK_NR_CLKS); + hws = ctx->clk_data.hws; samsung_clk_of_register_fixed_ext(ctx, exynos5x_fixed_rate_ext_clks, ARRAY_SIZE(exynos5x_fixed_rate_ext_clks), @@ -1623,15 +1626,15 @@ static void __init exynos5x_clk_init(struct device_node *np, if (soc == EXYNOS5420) { exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_cpu_p[0], mout_cpu_p[1], 0x200, + hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200, exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0); } else { exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk", - mout_cpu_p[0], mout_cpu_p[1], 0x200, + hws[CLK_MOUT_APLL], hws[CLK_MOUT_MSPLL_CPU], 0x200, exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0); } exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk", - mout_kfc_p[0], mout_kfc_p[1], 0x28200, + hws[CLK_MOUT_KPLL], hws[CLK_MOUT_MSPLL_KFC], 0x28200, exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0); samsung_clk_extended_sleep_init(reg_base, @@ -1654,7 +1657,12 @@ static void __init exynos5x_clk_init(struct device_node *np, * that the internal busses get their clock regardless of the * main G3D clock enablement status. */ - clk_prepare_enable(__clk_lookup("mout_sw_aclk_g3d")); + clk_prepare_enable(hws[CLK_MOUT_SW_ACLK_G3D]->clk); + /* + * Keep top BPLL mux enabled permanently to ensure that DRAM operates + * properly. + */ + clk_prepare_enable(hws[CLK_MOUT_BPLL]->clk); samsung_clk_of_add_provider(np, ctx); } diff --git a/drivers/clk/samsung/clk-exynos5433.c b/drivers/clk/samsung/clk-exynos5433.c index 6f29ecd0442e..f203074d858b 100644 --- a/drivers/clk/samsung/clk-exynos5433.c +++ b/drivers/clk/samsung/clk-exynos5433.c @@ -3679,6 +3679,7 @@ static void __init exynos5433_cmu_apollo_init(struct device_node *np) { void __iomem *reg_base; struct samsung_clk_provider *ctx; + struct clk_hw **hws; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -3701,8 +3702,10 @@ static void __init exynos5433_cmu_apollo_init(struct device_node *np) samsung_clk_register_gate(ctx, apollo_gate_clks, ARRAY_SIZE(apollo_gate_clks)); + hws = ctx->clk_data.hws; + exynos_register_cpu_clock(ctx, CLK_SCLK_APOLLO, "apolloclk", - mout_apollo_p[0], mout_apollo_p[1], 0x200, + hws[CLK_MOUT_APOLLO_PLL], hws[CLK_MOUT_BUS_PLL_APOLLO_USER], 0x200, exynos5433_apolloclk_d, ARRAY_SIZE(exynos5433_apolloclk_d), CLK_CPU_HAS_E5433_REGS_LAYOUT); @@ -3933,6 +3936,7 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np) { void __iomem *reg_base; struct samsung_clk_provider *ctx; + struct clk_hw **hws; reg_base = of_iomap(np, 0); if (!reg_base) { @@ -3955,8 +3959,10 @@ static void __init exynos5433_cmu_atlas_init(struct device_node *np) samsung_clk_register_gate(ctx, atlas_gate_clks, ARRAY_SIZE(atlas_gate_clks)); + hws = ctx->clk_data.hws; + exynos_register_cpu_clock(ctx, CLK_SCLK_ATLAS, "atlasclk", - mout_atlas_p[0], mout_atlas_p[1], 0x200, + hws[CLK_MOUT_ATLAS_PLL], hws[CLK_MOUT_BUS_PLL_ATLAS_USER], 0x200, exynos5433_atlasclk_d, ARRAY_SIZE(exynos5433_atlasclk_d), CLK_CPU_HAS_E5433_REGS_LAYOUT); diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c index 45dcbc9e0302..d17b345f4d2d 100644 --- a/drivers/clk/sirf/clk-prima2.c +++ b/drivers/clk/sirf/clk-prima2.c @@ -134,7 +134,7 @@ static void __init prima2_clk_init(struct device_node *np) for (i = pll1; i < maxclk; i++) { prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); - BUG_ON(!prima2_clks[i]); + BUG_ON(IS_ERR(prima2_clks[i])); } clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); clk_register_clkdev(prima2_clks[io], NULL, "io"); diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c index 8fb12cbe0208..bb3e80928ebe 100644 --- a/drivers/clk/socfpga/clk-agilex.c +++ b/drivers/clk/socfpga/clk-agilex.c @@ -21,19 +21,6 @@ static const struct clk_parent_data pll_mux[] = { .name = "f2s-free-clk", }, }; -static const struct clk_parent_data cntr_mux[] = { - { .fw_name = "main_pll", - .name = "main_pll", }, - { .fw_name = "periph_pll", - .name = "periph_pll", }, - { .fw_name = "osc1", - .name = "osc1", }, - { .fw_name = "cb-intosc-hs-div2-clk", - .name = "cb-intosc-hs-div2-clk", }, - { .fw_name = "f2s-free-clk", - .name = "f2s-free-clk", }, -}; - static const struct clk_parent_data boot_mux[] = { { .fw_name = "osc1", .name = "osc1", }, diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index cdf333003c30..ce5f5847d5d3 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -17,6 +17,16 @@ config SUN50I_A64_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN50I_A100_CCU + bool "Support for the Allwinner A100 CCU" + default ARM64 && ARCH_SUNXI + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST + +config SUN50I_A100_R_CCU + bool "Support for the Allwinner A100 PRCM CCU" + default ARM64 && ARCH_SUNXI + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST + config SUN50I_H6_CCU bool "Support for the Allwinner H6 CCU" default ARM64 && ARCH_SUNXI diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 4c7bee883f2f..3eb5cff40eac 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -23,6 +23,8 @@ obj-y += ccu_mp.o # SoC support obj-$(CONFIG_SUNIV_F1C100S_CCU) += ccu-suniv-f1c100s.o obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o +obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o +obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c new file mode 100644 index 000000000000..a56142b90993 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_nm.h" + +#include "ccu-sun50i-a100-r.h" + +static const char * const cpus_r_apb2_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0" }; +static const struct ccu_mux_var_prediv cpus_r_apb2_predivs[] = { + { .index = 3, .shift = 0, .width = 5 }, +}; + +static struct ccu_div r_cpus_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 24, + .width = 2, + + .var_predivs = cpus_r_apb2_predivs, + .n_var_predivs = ARRAY_SIZE(cpus_r_apb2_predivs), + }, + + .common = { + .reg = 0x000, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("cpus", + cpus_r_apb2_parents, + &ccu_div_ops, + 0), + }, +}; + +static CLK_FIXED_FACTOR_HW(r_ahb_clk, "r-ahb", &r_cpus_clk.common.hw, 1, 1, 0); + +static struct ccu_div r_apb1_clk = { + .div = _SUNXI_CCU_DIV(0, 2), + + .common = { + .reg = 0x00c, + .hw.init = CLK_HW_INIT("r-apb1", + "r-ahb", + &ccu_div_ops, + 0), + }, +}; + +static struct ccu_div r_apb2_clk = { + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + + .mux = { + .shift = 24, + .width = 2, + + .var_predivs = cpus_r_apb2_predivs, + .n_var_predivs = ARRAY_SIZE(cpus_r_apb2_predivs), + }, + + .common = { + .reg = 0x010, + .features = CCU_FEATURE_VARIABLE_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("r-apb2", + cpus_r_apb2_parents, + &ccu_div_ops, + 0), + }, +}; + +static const struct clk_parent_data clk_parent_r_apb1[] = { + { .hw = &r_apb1_clk.common.hw }, +}; + +static const struct clk_parent_data clk_parent_r_apb2[] = { + { .hw = &r_apb2_clk.common.hw }, +}; + +static SUNXI_CCU_GATE_DATA(r_apb1_timer_clk, "r-apb1-timer", clk_parent_r_apb1, + 0x11c, BIT(0), 0); + +static SUNXI_CCU_GATE_DATA(r_apb1_twd_clk, "r-apb1-twd", clk_parent_r_apb1, + 0x12c, BIT(0), 0); + +static const char * const r_apb1_pwm_clk_parents[] = { "dcxo24M", "osc32k", + "iosc" }; +static SUNXI_CCU_MUX(r_apb1_pwm_clk, "r-apb1-pwm", r_apb1_pwm_clk_parents, + 0x130, 24, 2, 0); + +static SUNXI_CCU_GATE_DATA(r_apb1_bus_pwm_clk, "r-apb1-bus-pwm", + clk_parent_r_apb1, 0x13c, BIT(0), 0); + +static SUNXI_CCU_GATE_DATA(r_apb1_ppu_clk, "r-apb1-ppu", clk_parent_r_apb1, + 0x17c, BIT(0), 0); + +static SUNXI_CCU_GATE_DATA(r_apb2_uart_clk, "r-apb2-uart", clk_parent_r_apb2, + 0x18c, BIT(0), 0); + +static SUNXI_CCU_GATE_DATA(r_apb2_i2c0_clk, "r-apb2-i2c0", clk_parent_r_apb2, + 0x19c, BIT(0), 0); + +static SUNXI_CCU_GATE_DATA(r_apb2_i2c1_clk, "r-apb2-i2c1", clk_parent_r_apb2, + 0x19c, BIT(1), 0); + +static const char * const r_apb1_ir_rx_parents[] = { "osc32k", "dcxo24M" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(r_apb1_ir_rx_clk, "r-apb1-ir-rx", + r_apb1_ir_rx_parents, 0x1c0, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_DATA(r_apb1_bus_ir_rx_clk, "r-apb1-bus-ir-rx", + clk_parent_r_apb1, 0x1cc, BIT(0), 0); + +static SUNXI_CCU_GATE(r_ahb_bus_rtc_clk, "r-ahb-rtc", "r-ahb", + 0x20c, BIT(0), 0); + +static struct ccu_common *sun50i_a100_r_ccu_clks[] = { + &r_cpus_clk.common, + &r_apb1_clk.common, + &r_apb2_clk.common, + &r_apb1_timer_clk.common, + &r_apb1_twd_clk.common, + &r_apb1_pwm_clk.common, + &r_apb1_bus_pwm_clk.common, + &r_apb1_ppu_clk.common, + &r_apb2_uart_clk.common, + &r_apb2_i2c0_clk.common, + &r_apb2_i2c1_clk.common, + &r_apb1_ir_rx_clk.common, + &r_apb1_bus_ir_rx_clk.common, + &r_ahb_bus_rtc_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_a100_r_hw_clks = { + .hws = { + [CLK_R_CPUS] = &r_cpus_clk.common.hw, + [CLK_R_AHB] = &r_ahb_clk.hw, + [CLK_R_APB1] = &r_apb1_clk.common.hw, + [CLK_R_APB2] = &r_apb2_clk.common.hw, + [CLK_R_APB1_TIMER] = &r_apb1_timer_clk.common.hw, + [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw, + [CLK_R_APB1_PWM] = &r_apb1_pwm_clk.common.hw, + [CLK_R_APB1_BUS_PWM] = &r_apb1_bus_pwm_clk.common.hw, + [CLK_R_APB1_PPU] = &r_apb1_ppu_clk.common.hw, + [CLK_R_APB2_UART] = &r_apb2_uart_clk.common.hw, + [CLK_R_APB2_I2C0] = &r_apb2_i2c0_clk.common.hw, + [CLK_R_APB2_I2C1] = &r_apb2_i2c1_clk.common.hw, + [CLK_R_APB1_IR] = &r_apb1_ir_rx_clk.common.hw, + [CLK_R_APB1_BUS_IR] = &r_apb1_bus_ir_rx_clk.common.hw, + [CLK_R_AHB_BUS_RTC] = &r_ahb_bus_rtc_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_a100_r_ccu_resets[] = { + [RST_R_APB1_TIMER] = { 0x11c, BIT(16) }, + [RST_R_APB1_BUS_PWM] = { 0x13c, BIT(16) }, + [RST_R_APB1_PPU] = { 0x17c, BIT(16) }, + [RST_R_APB2_UART] = { 0x18c, BIT(16) }, + [RST_R_APB2_I2C0] = { 0x19c, BIT(16) }, + [RST_R_APB2_I2C1] = { 0x19c, BIT(17) }, + [RST_R_APB1_BUS_IR] = { 0x1cc, BIT(16) }, + [RST_R_AHB_BUS_RTC] = { 0x20c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun50i_a100_r_ccu_desc = { + .ccu_clks = sun50i_a100_r_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_a100_r_ccu_clks), + + .hw_clks = &sun50i_a100_r_hw_clks, + + .resets = sun50i_a100_r_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_a100_r_ccu_resets), +}; + +static int sun50i_a100_r_ccu_probe(struct platform_device *pdev) +{ + void __iomem *reg; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_r_ccu_desc); +} + +static const struct of_device_id sun50i_a100_r_ccu_ids[] = { + { .compatible = "allwinner,sun50i-a100-r-ccu" }, + { } +}; + +static struct platform_driver sun50i_a100_r_ccu_driver = { + .probe = sun50i_a100_r_ccu_probe, + .driver = { + .name = "sun50i-a100-r-ccu", + .of_match_table = sun50i_a100_r_ccu_ids, + }, +}; +module_platform_driver(sun50i_a100_r_ccu_driver); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h new file mode 100644 index 000000000000..3a8f187a51b7 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _CCU_SUN50I_A100_R_H +#define _CCU_SUN50I_A100_R_H + +#include <dt-bindings/clock/sun50i-a100-r-ccu.h> +#include <dt-bindings/reset/sun50i-a100-r-ccu.h> + +#define CLK_R_CPUS 0 +#define CLK_R_AHB 1 + +/* exported except APB1 for R_PIO */ + +#define CLK_R_APB2 3 + +#define CLK_NUMBER (CLK_R_AHB_BUS_RTC + 1) + +#endif /* _CCU_SUN50I_A100_R_H */ diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c new file mode 100644 index 000000000000..81b48c73d389 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c @@ -0,0 +1,1276 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" + +#include "ccu-sun50i-a100.h" + +#define SUN50I_A100_PLL_SDM_ENABLE BIT(24) +#define SUN50I_A100_PLL_OUTPUT_ENABLE BIT(27) +#define SUN50I_A100_PLL_LOCK BIT(28) +#define SUN50I_A100_PLL_LOCK_ENABLE BIT(29) +#define SUN50I_A100_PLL_ENABLE BIT(31) + +#define SUN50I_A100_PLL_PERIPH1_PATTERN0 0xd1303333 + +/* + * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However + * P should only be used for output frequencies lower than 288 MHz. + * + * For now we can just model it as a multiplier clock, and force P to /1. + * + * The M factor is present in the register's description, but not in the + * frequency formula, and it's documented as "M is only used for backdoor + * testing", so it's not modelled and then force to 0. + */ +#define SUN50I_A100_PLL_CPUX_REG 0x000 +static struct ccu_mult pll_cpux_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-cpux", "dcxo24M", + &ccu_mult_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ +#define SUN50I_A100_PLL_DDR0_REG 0x010 +static struct ccu_nkmp pll_ddr0_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x010, + .hw.init = CLK_HW_INIT("pll-ddr0", "dcxo24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE | + CLK_IS_CRITICAL), + }, +}; + +#define SUN50I_A100_PLL_PERIPH0_REG 0x020 +static struct ccu_nkmp pll_periph0_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x020, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0", "dcxo24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_A100_PLL_PERIPH1_REG 0x028 +static struct ccu_nkmp pll_periph1_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph1", "dcxo24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; +#define SUN50I_A100_PLL_PERIPH1_PATTERN0_REG 0x128 + +#define SUN50I_A100_PLL_GPU_REG 0x030 +static struct ccu_nkmp pll_gpu_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x030, + .hw.init = CLK_HW_INIT("pll-gpu", "dcxo24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * For Video PLLs, the output divider is described as "used for testing" + * in the user manual. So it's not modelled and forced to 0. + */ +#define SUN50I_A100_PLL_VIDEO0_REG 0x040 +static struct ccu_nm pll_video0_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .common = { + .reg = 0x040, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video0", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_A100_PLL_VIDEO1_REG 0x048 +static struct ccu_nm pll_video1_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .common = { + .reg = 0x048, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video1", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_A100_PLL_VIDEO2_REG 0x050 +static struct ccu_nm pll_video2_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .common = { + .reg = 0x050, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video2", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_A100_PLL_VE_REG 0x058 +static struct ccu_nkmp pll_ve_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x058, + .hw.init = CLK_HW_INIT("pll-ve", "dcxo24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * The COM PLL has m0 dividers in addition to the usual N, M + * factors. Since we only need 1 frequencies from this PLL: 45.1584 MHz, + * ignore it for now. + */ +#define SUN50I_A100_PLL_COM_REG 0x060 +static struct ccu_sdm_setting pll_com_sdm_table[] = { + { .rate = 451584000, .pattern = 0xc0014396, .m = 2, .n = 37 }, +}; + +static struct ccu_nm pll_com_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(0, 1), + .sdm = _SUNXI_CCU_SDM(pll_com_sdm_table, BIT(24), + 0x160, BIT(31)), + .common = { + .reg = 0x060, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, + .hw.init = CLK_HW_INIT("pll-com", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_A100_PLL_VIDEO3_REG 0x068 +static struct ccu_nm pll_video3_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .common = { + .reg = 0x068, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video3", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * The Audio PLL has m0, m1 dividers in addition to the usual N, M + * factors. Since we only need 4 frequencies from this PLL: 22.5792 MHz, + * 24.576 MHz, 90.3168MHz and 98.304MHz ignore them for now. + * Enforce the default for them, which is m0 = 1, m1 = 0. + */ +#define SUN50I_A100_PLL_AUDIO_REG 0x078 +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 45158400, .pattern = 0xc001bcd3, .m = 18, .n = 33 }, + { .rate = 49152000, .pattern = 0xc001eb85, .m = 20, .n = 40 }, + { .rate = 180633600, .pattern = 0xc001288d, .m = 3, .n = 22 }, + { .rate = 196608000, .pattern = 0xc001eb85, .m = 5, .n = 40 }, +}; + +static struct ccu_nm pll_audio_clk = { + .enable = SUN50I_A100_PLL_OUTPUT_ENABLE, + .lock = SUN50I_A100_PLL_LOCK, + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(16, 6), + .fixed_post_div = 2, + .sdm = _SUNXI_CCU_SDM(pll_audio_sdm_table, BIT(24), + 0x178, BIT(31)), + .common = { + .reg = 0x078, + .features = CCU_FEATURE_FIXED_POSTDIV | + CCU_FEATURE_SIGMA_DELTA_MOD, + .hw.init = CLK_HW_INIT("pll-audio", "dcxo24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const char * const cpux_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-cpux", + "pll-periph0" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0); +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0); + +static const char * const psi_ahb1_ahb2_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0", + "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", + psi_ahb1_ahb2_parents, 0x510, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); + +static const char * const ahb3_apb1_apb2_parents[] = { "dcxo24M", "osc32k", + "psi-ahb1-ahb2", + "pll-periph0", + "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); + +static const char * const mbus_parents[] = { "dcxo24M", "pll-ddr0", + "pll-periph0", + "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540, + 0, 3, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_IS_CRITICAL); + +static const char * const de_parents[] = { "pll-com", "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de0", de_parents, 0x600, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2", + 0x60c, BIT(0), 0); + +static const char * const g2d_parents[] = { "pll-com", "pll-periph0-2x", + "pll-video0-2x", "pll-video1-2x", + "pll-video2-2x"}; +static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", + g2d_parents, + 0x630, + 0, 4, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2", + 0x63c, BIT(0), 0); + +static const char * const gpu_parents[] = { "pll-gpu" }; +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_clk, "gpu", gpu_parents, 0x670, + 0, 2, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", + 0x67c, BIT(0), 0); + +static const char * const ce_parents[] = { "dcxo24M", "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2", + 0x68c, BIT(0), 0); + +static const char * const ve_parents[] = { "pll-ve" }; +static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, + 0, 3, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2", + 0x69c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2", + 0x70c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_msgbox_clk, "bus-msgbox", "psi-ahb1-ahb2", + 0x71c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_spinlock_clk, "bus-spinlock", "psi-ahb1-ahb2", + 0x72c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2", + 0x73c, BIT(0), 0); + +static SUNXI_CCU_GATE(avs_clk, "avs", "dcxo24M", 0x740, BIT(31), 0); + +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", + 0x78c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", + 0x79c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); + +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus", + 0x804, BIT(0), 0); +static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus", + 0x804, BIT(1), 0); +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus", + 0x804, BIT(2), 0); +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus", + 0x804, BIT(5), 0); +static SUNXI_CCU_GATE(mbus_csi_clk, "mbus-csi", "mbus", + 0x804, BIT(8), 0); +static SUNXI_CCU_GATE(mbus_isp_clk, "mbus-isp", "mbus", + 0x804, BIT(9), 0); +static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus", + 0x804, BIT(10), 0); + +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2", + 0x80c, BIT(0), CLK_IS_CRITICAL); + +static const char * const nand_spi_parents[] = { "dcxo24M", + "pll-periph0", + "pll-periph1", + "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0); + +static const char * const mmc_parents[] = { "dcxo24M", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + CLK_SET_RATE_NO_REPARENT); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + CLK_SET_RATE_NO_REPARENT); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + CLK_SET_RATE_NO_REPARENT); + +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0); + +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", nand_spi_parents, 0x948, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb3", 0x96c, BIT(2), 0); + +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970, + BIT(31) | BIT(30), 0); + +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb3", 0x97c, BIT(0), 0); + +static const char * const ir_parents[] = { "osc32k", "iosc", + "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_rx_clk, "ir-rx", ir_parents, 0x990, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ir_rx_clk, "bus-ir-rx", "ahb3", 0x99c, BIT(0), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_parents, 0x9c0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ir_tx_clk, "bus-ir-tx", "apb1", 0x9cc, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_gpadc_clk, "bus-gpadc", "apb1", 0x9ec, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0); + +static const char * const audio_parents[] = { "pll-audio", "pll-com-audio" }; +static struct ccu_div i2s0_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa10, + .hw.init = CLK_HW_INIT_PARENTS("i2s0", + audio_parents, + &ccu_div_ops, + CLK_SET_RATE_PARENT), + }, +}; + +static struct ccu_div i2s1_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa14, + .hw.init = CLK_HW_INIT_PARENTS("i2s1", + audio_parents, + &ccu_div_ops, + CLK_SET_RATE_PARENT), + }, +}; + +static struct ccu_div i2s2_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa18, + .hw.init = CLK_HW_INIT_PARENTS("i2s2", + audio_parents, + &ccu_div_ops, + CLK_SET_RATE_PARENT), + }, +}; + +static struct ccu_div i2s3_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa1c, + .hw.init = CLK_HW_INIT_PARENTS("i2s3", + audio_parents, + &ccu_div_ops, + CLK_SET_RATE_PARENT), + }, +}; + +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", 0xa20, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", 0xa20, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", 0xa20, BIT(2), 0); +static SUNXI_CCU_GATE(bus_i2s3_clk, "bus-i2s3", "apb1", 0xa20, BIT(3), 0); + +static struct ccu_div spdif_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa24, + .hw.init = CLK_HW_INIT_PARENTS("spdif", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0); + +static struct ccu_div dmic_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa40, + .hw.init = CLK_HW_INIT_PARENTS("dmic", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_dac_clk, "audio-codec-dac", + audio_parents, 0xa50, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_adc_clk, "audio-codec-adc", + audio_parents, 0xa54, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x", + audio_parents, 0xa58, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c, + BIT(0), 0); + +/* + * There are OHCI 12M clock source selection bits for 2 USB 2.0 ports. + * We will force them to 0 (12M divided from 48M). + */ +#define SUN50I_A100_USB0_CLK_REG 0xa70 +#define SUN50I_A100_USB1_CLK_REG 0xa74 + +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "dcxo24M", 0xa70, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "dcxo24M", 0xa74, BIT(29), 0); + +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0); + +static SUNXI_CCU_GATE(bus_lradc_clk, "bus-lradc", "ahb3", 0xa9c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_dpss_top0_clk, "bus-dpss-top0", "ahb3", + 0xabc, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_dpss_top1_clk, "bus-dpss-top1", "ahb3", + 0xacc, BIT(0), 0); + +static const char * const mipi_dsi_parents[] = { "dcxo24M", "pll-periph0-2x", + "pll-periph0" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", + mipi_dsi_parents, + 0xb24, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb3", + 0xb4c, BIT(0), 0); + +static const char * const tcon_lcd_parents[] = { "pll-video0-4x", + "pll-video1-4x", + "pll-video2-4x", + "pll-video3-4x", + "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_lcd_clk, "tcon-lcd0", + tcon_lcd_parents, 0xb60, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_tcon_lcd_clk, "bus-tcon-lcd0", "ahb3", + 0xb7c, BIT(0), 0); + +static const char * const ledc_parents[] = { "dcxo24M", + "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", + ledc_parents, 0xbf0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ledc_clk, "bus-ledc", "ahb3", 0xbfc, BIT(0), 0); + +static const char * const csi_top_parents[] = { "pll-periph0-2x", + "pll-video0-2x", + "pll-video1-2x", + "pll-video2-2x", + "pll-video3-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_top_clk, "csi-top", + csi_top_parents, 0xc04, + 0, 4, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const csi0_mclk_parents[] = { "dcxo24M", "pll-video2", + "pll-video3", "pll-video0", + "pll-video1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", + csi0_mclk_parents, 0xc08, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const csi1_mclk_parents[] = { "dcxo24M", "pll-video3", + "pll-video0", "pll-video1", + "pll-video2" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", + csi1_mclk_parents, 0xc0c, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_csi_clk, "bus-csi", "ahb3", 0xc1c, BIT(0), 0); + +static const char * const csi_isp_parents[] = { "pll-periph0-2x", + "pll-video0-2x", + "pll-video1-2x", + "pll-video2-2x", + "pll-video3-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_isp_clk, "csi-isp", + csi_isp_parents, 0xc20, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +/* Fixed factor clocks */ +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0); + +static CLK_FIXED_FACTOR_HW(pll_com_audio_clk, "pll-com-audio", + &pll_com_clk.common.hw, + 5, 1, CLK_SET_RATE_PARENT); + +static CLK_FIXED_FACTOR_HW(pll_periph0_2x_clk, "pll-periph0-2x", + &pll_periph0_clk.common.hw, + 1, 2, 0); + +static CLK_FIXED_FACTOR_HW(pll_periph1_2x_clk, "pll-periph1-2x", + &pll_periph1_clk.common.hw, + 1, 2, 0); + +static const struct clk_hw *pll_video0_parents[] = { + &pll_video0_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video0_4x_clk, "pll-video0-4x", + pll_video0_parents, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x", + pll_video0_parents, + 1, 2, CLK_SET_RATE_PARENT); + +static const struct clk_hw *pll_video1_parents[] = { + &pll_video1_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video1_4x_clk, "pll-video1-4x", + pll_video1_parents, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x", + pll_video1_parents, + 1, 2, CLK_SET_RATE_PARENT); + +static const struct clk_hw *pll_video2_parents[] = { + &pll_video2_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video2_4x_clk, "pll-video2-4x", + pll_video2_parents, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video2_2x_clk, "pll-video2-2x", + pll_video2_parents, + 1, 2, CLK_SET_RATE_PARENT); + +static const struct clk_hw *pll_video3_parents[] = { + &pll_video3_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video3_4x_clk, "pll-video3-4x", + pll_video3_parents, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video3_2x_clk, "pll-video3-2x", + pll_video3_parents, + 1, 2, CLK_SET_RATE_PARENT); + +static struct ccu_common *sun50i_a100_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_ddr0_clk.common, + &pll_periph0_clk.common, + &pll_periph1_clk.common, + &pll_gpu_clk.common, + &pll_video0_clk.common, + &pll_video1_clk.common, + &pll_video2_clk.common, + &pll_video3_clk.common, + &pll_ve_clk.common, + &pll_com_clk.common, + &pll_audio_clk.common, + &cpux_clk.common, + &axi_clk.common, + &cpux_apb_clk.common, + &psi_ahb1_ahb2_clk.common, + &ahb3_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &mbus_clk.common, + &de_clk.common, + &bus_de_clk.common, + &g2d_clk.common, + &bus_g2d_clk.common, + &gpu_clk.common, + &bus_gpu_clk.common, + &ce_clk.common, + &bus_ce_clk.common, + &ve_clk.common, + &bus_ve_clk.common, + &bus_dma_clk.common, + &bus_msgbox_clk.common, + &bus_spinlock_clk.common, + &bus_hstimer_clk.common, + &avs_clk.common, + &bus_dbg_clk.common, + &bus_psi_clk.common, + &bus_pwm_clk.common, + &bus_iommu_clk.common, + &mbus_dma_clk.common, + &mbus_ve_clk.common, + &mbus_ce_clk.common, + &mbus_nand_clk.common, + &mbus_csi_clk.common, + &mbus_isp_clk.common, + &mbus_g2d_clk.common, + &bus_dram_clk.common, + &nand0_clk.common, + &nand1_clk.common, + &bus_nand_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_i2c3_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &spi2_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &bus_spi2_clk.common, + &emac_25m_clk.common, + &bus_emac_clk.common, + &ir_rx_clk.common, + &bus_ir_rx_clk.common, + &ir_tx_clk.common, + &bus_ir_tx_clk.common, + &bus_gpadc_clk.common, + &bus_ths_clk.common, + &i2s0_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &i2s3_clk.common, + &bus_i2s0_clk.common, + &bus_i2s1_clk.common, + &bus_i2s2_clk.common, + &bus_i2s3_clk.common, + &spdif_clk.common, + &bus_spdif_clk.common, + &dmic_clk.common, + &bus_dmic_clk.common, + &audio_codec_dac_clk.common, + &audio_codec_adc_clk.common, + &audio_codec_4x_clk.common, + &bus_audio_codec_clk.common, + &usb_ohci0_clk.common, + &usb_phy0_clk.common, + &usb_ohci1_clk.common, + &usb_phy1_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_otg_clk.common, + &bus_lradc_clk.common, + &bus_dpss_top0_clk.common, + &bus_dpss_top1_clk.common, + &mipi_dsi_clk.common, + &bus_mipi_dsi_clk.common, + &tcon_lcd_clk.common, + &bus_tcon_lcd_clk.common, + &ledc_clk.common, + &bus_ledc_clk.common, + &csi_top_clk.common, + &csi0_mclk_clk.common, + &csi1_mclk_clk.common, + &bus_csi_clk.common, + &csi_isp_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_a100_hw_clks = { + .hws = { + [CLK_OSC12M] = &osc12M_clk.hw, + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, + [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw, + [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw, + [CLK_PLL_VIDEO2_2X] = &pll_video2_2x_clk.hw, + [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw, + [CLK_PLL_VIDEO3] = &pll_video3_clk.common.hw, + [CLK_PLL_VIDEO3_2X] = &pll_video3_2x_clk.hw, + [CLK_PLL_VIDEO3_4X] = &pll_video3_4x_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_COM] = &pll_com_clk.common.hw, + [CLK_PLL_COM_AUDIO] = &pll_com_audio_clk.hw, + [CLK_PLL_AUDIO] = &pll_audio_clk.common.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, + [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw, + [CLK_AHB3] = &ahb3_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_G2D] = &g2d_clk.common.hw, + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, + [CLK_GPU] = &gpu_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_MSGBOX] = &bus_msgbox_clk.common.hw, + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_BUS_PSI] = &bus_psi_clk.common.hw, + [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, + [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw, + [CLK_MBUS_CSI] = &mbus_csi_clk.common.hw, + [CLK_MBUS_ISP] = &mbus_isp_clk.common.hw, + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_NAND0] = &nand0_clk.common.hw, + [CLK_NAND1] = &nand1_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_SPI2] = &spi2_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, + [CLK_EMAC_25M] = &emac_25m_clk.common.hw, + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, + [CLK_IR_RX] = &ir_rx_clk.common.hw, + [CLK_BUS_IR_RX] = &bus_ir_rx_clk.common.hw, + [CLK_IR_TX] = &ir_tx_clk.common.hw, + [CLK_BUS_IR_TX] = &bus_ir_tx_clk.common.hw, + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_I2S3] = &i2s3_clk.common.hw, + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, + [CLK_BUS_I2S3] = &bus_i2s3_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_DMIC] = &dmic_clk.common.hw, + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, + [CLK_AUDIO_DAC] = &audio_codec_dac_clk.common.hw, + [CLK_AUDIO_ADC] = &audio_codec_adc_clk.common.hw, + [CLK_AUDIO_4X] = &audio_codec_4x_clk.common.hw, + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw, + [CLK_BUS_DPSS_TOP0] = &bus_dpss_top0_clk.common.hw, + [CLK_BUS_DPSS_TOP1] = &bus_dpss_top1_clk.common.hw, + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw, + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, + [CLK_TCON_LCD] = &tcon_lcd_clk.common.hw, + [CLK_BUS_TCON_LCD] = &bus_tcon_lcd_clk.common.hw, + [CLK_LEDC] = &ledc_clk.common.hw, + [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw, + [CLK_CSI_TOP] = &csi_top_clk.common.hw, + [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, + [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, + [CLK_BUS_CSI] = &bus_csi_clk.common.hw, + [CLK_CSI_ISP] = &csi_isp_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_a100_ccu_resets[] = { + [RST_MBUS] = { 0x540, BIT(30) }, + + [RST_BUS_DE] = { 0x60c, BIT(16) }, + [RST_BUS_G2D] = { 0x63c, BIT(16) }, + [RST_BUS_GPU] = { 0x67c, BIT(16) }, + [RST_BUS_CE] = { 0x68c, BIT(16) }, + [RST_BUS_VE] = { 0x69c, BIT(16) }, + [RST_BUS_DMA] = { 0x70c, BIT(16) }, + [RST_BUS_MSGBOX] = { 0x71c, BIT(16) }, + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) }, + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, + [RST_BUS_DBG] = { 0x78c, BIT(16) }, + [RST_BUS_PSI] = { 0x79c, BIT(16) }, + [RST_BUS_PWM] = { 0x7ac, BIT(16) }, + [RST_BUS_DRAM] = { 0x80c, BIT(16) }, + [RST_BUS_NAND] = { 0x82c, BIT(16) }, + [RST_BUS_MMC0] = { 0x84c, BIT(16) }, + [RST_BUS_MMC1] = { 0x84c, BIT(17) }, + [RST_BUS_MMC2] = { 0x84c, BIT(18) }, + [RST_BUS_UART0] = { 0x90c, BIT(16) }, + [RST_BUS_UART1] = { 0x90c, BIT(17) }, + [RST_BUS_UART2] = { 0x90c, BIT(18) }, + [RST_BUS_UART3] = { 0x90c, BIT(19) }, + [RST_BUS_UART4] = { 0x90c, BIT(20) }, + [RST_BUS_I2C0] = { 0x91c, BIT(16) }, + [RST_BUS_I2C1] = { 0x91c, BIT(17) }, + [RST_BUS_I2C2] = { 0x91c, BIT(18) }, + [RST_BUS_I2C3] = { 0x91c, BIT(19) }, + [RST_BUS_SPI0] = { 0x96c, BIT(16) }, + [RST_BUS_SPI1] = { 0x96c, BIT(17) }, + [RST_BUS_SPI2] = { 0x96c, BIT(18) }, + [RST_BUS_EMAC] = { 0x97c, BIT(16) }, + [RST_BUS_IR_RX] = { 0x99c, BIT(16) }, + [RST_BUS_IR_TX] = { 0x9cc, BIT(16) }, + [RST_BUS_GPADC] = { 0x9ec, BIT(16) }, + [RST_BUS_THS] = { 0x9fc, BIT(16) }, + [RST_BUS_I2S0] = { 0xa20, BIT(16) }, + [RST_BUS_I2S1] = { 0xa20, BIT(17) }, + [RST_BUS_I2S2] = { 0xa20, BIT(18) }, + [RST_BUS_I2S3] = { 0xa20, BIT(19) }, + [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, + [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) }, + + [RST_USB_PHY0] = { 0xa70, BIT(30) }, + [RST_USB_PHY1] = { 0xa74, BIT(30) }, + + [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, + [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, + [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, + [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, + [RST_BUS_OTG] = { 0xa8c, BIT(24) }, + + [RST_BUS_LRADC] = { 0xa9c, BIT(16) }, + [RST_BUS_DPSS_TOP0] = { 0xabc, BIT(16) }, + [RST_BUS_DPSS_TOP1] = { 0xacc, BIT(16) }, + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) }, + [RST_BUS_TCON_LCD] = { 0xb7c, BIT(16) }, + [RST_BUS_LVDS] = { 0xbac, BIT(16) }, + [RST_BUS_LEDC] = { 0xbfc, BIT(16) }, + [RST_BUS_CSI] = { 0xc1c, BIT(16) }, + [RST_BUS_CSI_ISP] = { 0xc2c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun50i_a100_ccu_desc = { + .ccu_clks = sun50i_a100_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_a100_ccu_clks), + + .hw_clks = &sun50i_a100_hw_clks, + + .resets = sun50i_a100_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_a100_ccu_resets), +}; + +static const u32 sun50i_a100_pll_regs[] = { + SUN50I_A100_PLL_CPUX_REG, + SUN50I_A100_PLL_DDR0_REG, + SUN50I_A100_PLL_PERIPH0_REG, + SUN50I_A100_PLL_PERIPH1_REG, + SUN50I_A100_PLL_GPU_REG, + SUN50I_A100_PLL_VIDEO0_REG, + SUN50I_A100_PLL_VIDEO1_REG, + SUN50I_A100_PLL_VIDEO2_REG, + SUN50I_A100_PLL_VIDEO3_REG, + SUN50I_A100_PLL_VE_REG, + SUN50I_A100_PLL_COM_REG, + SUN50I_A100_PLL_AUDIO_REG, +}; + +static const u32 sun50i_a100_pll_video_regs[] = { + SUN50I_A100_PLL_VIDEO0_REG, + SUN50I_A100_PLL_VIDEO1_REG, + SUN50I_A100_PLL_VIDEO2_REG, + SUN50I_A100_PLL_VIDEO3_REG, +}; + +static const u32 sun50i_a100_usb2_clk_regs[] = { + SUN50I_A100_USB0_CLK_REG, + SUN50I_A100_USB1_CLK_REG, +}; + +static struct ccu_pll_nb sun50i_a100_pll_cpu_nb = { + .common = &pll_cpux_clk.common, + /* copy from pll_cpux_clk */ + .enable = BIT(27), + .lock = BIT(28), +}; + +static struct ccu_mux_nb sun50i_a100_cpu_nb = { + .common = &cpux_clk.common, + .cm = &cpux_clk.mux, + .delay_us = 1, + .bypass_index = 4, /* index of pll periph0 */ +}; + +static int sun50i_a100_ccu_probe(struct platform_device *pdev) +{ + void __iomem *reg; + u32 val; + int i, ret; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + /* + * Enable lock and enable bits on all PLLs. + * + * Due to the current design, multiple PLLs share one power switch, + * so switching PLL is easy to cause stability problems. + * When initializing, we enable them by default. When disable, + * we only turn off the output of PLL. + */ + for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_regs); i++) { + val = readl(reg + sun50i_a100_pll_regs[i]); + val |= SUN50I_A100_PLL_LOCK_ENABLE | SUN50I_A100_PLL_ENABLE; + writel(val, reg + sun50i_a100_pll_regs[i]); + } + + /* + * In order to pass the EMI certification, the SDM function of + * the peripheral 1 bus is enabled, and the frequency is still + * calculated using the previous division factor. + */ + writel(SUN50I_A100_PLL_PERIPH1_PATTERN0, + reg + SUN50I_A100_PLL_PERIPH1_PATTERN0_REG); + + val = readl(reg + SUN50I_A100_PLL_PERIPH1_REG); + val |= SUN50I_A100_PLL_SDM_ENABLE; + writel(val, reg + SUN50I_A100_PLL_PERIPH1_REG); + + /* + * Force the output divider of video PLLs to 0. + * + * See the comment before pll-video0 definition for the reason. + */ + for (i = 0; i < ARRAY_SIZE(sun50i_a100_pll_video_regs); i++) { + val = readl(reg + sun50i_a100_pll_video_regs[i]); + val &= ~BIT(0); + writel(val, reg + sun50i_a100_pll_video_regs[i]); + } + + /* + * Enforce m1 = 0, m0 = 1 for Audio PLL + * + * See the comment before pll-audio definition for the reason. + */ + val = readl(reg + SUN50I_A100_PLL_AUDIO_REG); + val &= ~BIT(1); + val |= BIT(0); + writel(val, reg + SUN50I_A100_PLL_AUDIO_REG); + + /* + * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) + * + * This clock mux is still mysterious, and the code just enforces + * it to have a valid clock parent. + */ + for (i = 0; i < ARRAY_SIZE(sun50i_a100_usb2_clk_regs); i++) { + val = readl(reg + sun50i_a100_usb2_clk_regs[i]); + val &= ~GENMASK(25, 24); + writel(val, reg + sun50i_a100_usb2_clk_regs[i]); + } + + ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun50i_a100_ccu_desc); + if (ret) + return ret; + + /* Gate then ungate PLL CPU after any rate changes */ + ccu_pll_notifier_register(&sun50i_a100_pll_cpu_nb); + + /* Reparent CPU during PLL CPU rate changes */ + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, + &sun50i_a100_cpu_nb); + + return 0; +} + +static const struct of_device_id sun50i_a100_ccu_ids[] = { + { .compatible = "allwinner,sun50i-a100-ccu" }, + { } +}; + +static struct platform_driver sun50i_a100_ccu_driver = { + .probe = sun50i_a100_ccu_probe, + .driver = { + .name = "sun50i-a100-ccu", + .of_match_table = sun50i_a100_ccu_ids, + }, +}; +module_platform_driver(sun50i_a100_ccu_driver); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.h b/drivers/clk/sunxi-ng/ccu-sun50i-a100.h new file mode 100644 index 000000000000..21ce92bb1d5f --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _CCU_SUN50I_A100_H_ +#define _CCU_SUN50I_A100_H_ + +#include <dt-bindings/clock/sun50i-a100-ccu.h> +#include <dt-bindings/reset/sun50i-a100-ccu.h> + +#define CLK_OSC12M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_DDR0 2 + +/* PLL_PERIPH0 exported for PRCM */ + +#define CLK_PLL_PERIPH0_2X 4 +#define CLK_PLL_PERIPH1 5 +#define CLK_PLL_PERIPH1_2X 6 +#define CLK_PLL_GPU 7 +#define CLK_PLL_VIDEO0 8 +#define CLK_PLL_VIDEO0_2X 9 +#define CLK_PLL_VIDEO0_4X 10 +#define CLK_PLL_VIDEO1 11 +#define CLK_PLL_VIDEO1_2X 12 +#define CLK_PLL_VIDEO1_4X 13 +#define CLK_PLL_VIDEO2 14 +#define CLK_PLL_VIDEO2_2X 15 +#define CLK_PLL_VIDEO2_4X 16 +#define CLK_PLL_VIDEO3 17 +#define CLK_PLL_VIDEO3_2X 18 +#define CLK_PLL_VIDEO3_4X 19 +#define CLK_PLL_VE 20 +#define CLK_PLL_COM 21 +#define CLK_PLL_COM_AUDIO 22 +#define CLK_PLL_AUDIO 23 + +/* CPUX clock exported for DVFS */ + +#define CLK_AXI 25 +#define CLK_CPUX_APB 26 +#define CLK_PSI_AHB1_AHB2 27 +#define CLK_AHB3 28 + +/* APB1 clock exported for PIO */ + +#define CLK_APB2 30 + +/* All module clocks and bus gates are exported except DRAM */ + +#define CLK_BUS_DRAM 58 + +#define CLK_NUMBER (CLK_CSI_ISP + 1) + +#endif /* _CCU_SUN50I_A100_H_ */ diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c index 23bfe1d12f21..84153418453f 100644 --- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c +++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c @@ -45,18 +45,29 @@ static struct ccu_nkmp pll_cpu_clk = { * the base (2x, 4x and 8x), and one variable divider (the one true * pll audio). * - * We don't have any need for the variable divider for now, so we just - * hardcode it to match with the clock names + * With sigma-delta modulation for fractional-N on the audio PLL, + * we have to use specific dividers. This means the variable divider + * can no longer be used, as the audio codec requests the exact clock + * rates we support through this mechanism. So we now hard code the + * variable divider to 1. This means the clock rates will no longer + * match the clock names. */ #define SUN8I_R40_PLL_AUDIO_REG 0x008 -static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", - "osc24M", 0x008, - 8, 7, /* N */ - 0, 5, /* M */ - BIT(31), /* gate */ - BIT(28), /* lock */ - CLK_SET_RATE_UNGATE); +static struct ccu_sdm_setting pll_audio_sdm_table[] = { + { .rate = 22579200, .pattern = 0xc0010d84, .m = 8, .n = 7 }, + { .rate = 24576000, .pattern = 0xc000ac02, .m = 14, .n = 14 }, +}; + +static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", + "osc24M", 0x008, + 8, 7, /* N */ + 0, 5, /* M */ + pll_audio_sdm_table, BIT(24), + 0x284, BIT(31), + BIT(31), /* gate */ + BIT(28), /* lock */ + CLK_SET_RATE_UNGATE); static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0", "osc24M", 0x0010, @@ -952,10 +963,10 @@ static const struct clk_hw *clk_parent_pll_audio[] = { &pll_audio_base_clk.common.hw }; -/* We hardcode the divider to 4 for now */ +/* We hardcode the divider to 1 for now */ static CLK_FIXED_FACTOR_HWS(pll_audio_clk, "pll-audio", clk_parent_pll_audio, - 4, 1, CLK_SET_RATE_PARENT); + 1, 1, CLK_SET_RATE_PARENT); static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", clk_parent_pll_audio, 2, 1, CLK_SET_RATE_PARENT); @@ -1307,10 +1318,10 @@ static int sun8i_r40_ccu_probe(struct platform_device *pdev) if (IS_ERR(reg)) return PTR_ERR(reg); - /* Force the PLL-Audio-1x divider to 4 */ + /* Force the PLL-Audio-1x divider to 1 */ val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); val &= ~GENMASK(19, 16); - writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); + writel(val | (0 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); /* Force PLL-MIPI to MIPI mode */ val = readl(reg + SUN8I_R40_PLL_MIPI_REG); diff --git a/drivers/clk/tegra/clk-tegra210-emc.c b/drivers/clk/tegra/clk-tegra210-emc.c index 352a2c3fc374..971c919b2994 100644 --- a/drivers/clk/tegra/clk-tegra210-emc.c +++ b/drivers/clk/tegra/clk-tegra210-emc.c @@ -126,7 +126,7 @@ static int tegra210_clk_emc_set_rate(struct clk_hw *hw, unsigned long rate, unsigned int i; int err; - if (!provider || !provider->configs || provider->num_configs == 0) + if (!provider->configs || provider->num_configs == 0) return -EINVAL; for (i = 0; i < provider->num_configs; i++) { diff --git a/drivers/clk/ti/autoidle.c b/drivers/clk/ti/autoidle.c index 1cae226759dd..f6f8a409f148 100644 --- a/drivers/clk/ti/autoidle.c +++ b/drivers/clk/ti/autoidle.c @@ -82,7 +82,12 @@ static int _omap2_clk_allow_idle(struct clk_hw_omap *clk) */ int omap2_clk_deny_idle(struct clk *clk) { - struct clk_hw *hw = __clk_get_hw(clk); + struct clk_hw *hw; + + if (!clk) + return -EINVAL; + + hw = __clk_get_hw(clk); if (omap2_clk_is_hw_omap(hw)) { struct clk_hw_omap *c = to_clk_hw_omap(hw); @@ -101,7 +106,12 @@ int omap2_clk_deny_idle(struct clk *clk) */ int omap2_clk_allow_idle(struct clk *clk) { - struct clk_hw *hw = __clk_get_hw(clk); + struct clk_hw *hw; + + if (!clk) + return -EINVAL; + + hw = __clk_get_hw(clk); if (omap2_clk_is_hw_omap(hw)) { struct clk_hw_omap *c = to_clk_hw_omap(hw); diff --git a/drivers/clk/ti/clk-7xx.c b/drivers/clk/ti/clk-7xx.c index b4cf578a69e1..4e27f88062e7 100644 --- a/drivers/clk/ti/clk-7xx.c +++ b/drivers/clk/ti/clk-7xx.c @@ -637,6 +637,7 @@ static const struct omap_clkctrl_reg_data dra7_l4sec_clkctrl_regs[] __initconst { DRA7_L4SEC_DES_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" }, { DRA7_L4SEC_RNG_CLKCTRL, NULL, CLKF_HW_SUP | CLKF_SOC_NONSEC, "l4_root_clk_div" }, { DRA7_L4SEC_SHAM_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" }, + { DRA7_L4SEC_SHAM2_CLKCTRL, NULL, CLKF_HW_SUP, "l3_iclk_div" }, { 0 }, }; diff --git a/drivers/clk/ti/clockdomain.c b/drivers/clk/ti/clockdomain.c index ee56306f79d5..700b7f44f671 100644 --- a/drivers/clk/ti/clockdomain.c +++ b/drivers/clk/ti/clockdomain.c @@ -148,10 +148,12 @@ static void __init of_ti_clockdomain_setup(struct device_node *node) if (!omap2_clk_is_hw_omap(clk_hw)) { pr_warn("can't setup clkdm for basic clk %s\n", __clk_get_name(clk)); + clk_put(clk); continue; } to_clk_hw_omap(clk_hw)->clkdm_name = clkdm_name; omap2_init_clk_clkdm(clk_hw); + clk_put(clk); } } diff --git a/drivers/clk/uniphier/clk-uniphier-cpugear.c b/drivers/clk/uniphier/clk-uniphier-cpugear.c index 1a33a08abf2f..a2f01a4da127 100644 --- a/drivers/clk/uniphier/clk-uniphier-cpugear.c +++ b/drivers/clk/uniphier/clk-uniphier-cpugear.c @@ -90,7 +90,7 @@ struct clk_hw *uniphier_clk_register_cpugear(struct device *dev, init.ops = &uniphier_clk_cpugear_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = data->parent_names; - init.num_parents = data->num_parents, + init.num_parents = data->num_parents; gear->regmap = regmap; gear->regbase = data->regbase; diff --git a/drivers/clk/uniphier/clk-uniphier-mux.c b/drivers/clk/uniphier/clk-uniphier-mux.c index c0f4631601e2..462c84321b2d 100644 --- a/drivers/clk/uniphier/clk-uniphier-mux.c +++ b/drivers/clk/uniphier/clk-uniphier-mux.c @@ -70,7 +70,7 @@ struct clk_hw *uniphier_clk_register_mux(struct device *dev, init.ops = &uniphier_clk_mux_ops; init.flags = CLK_SET_RATE_PARENT; init.parent_names = data->parent_names; - init.num_parents = data->num_parents, + init.num_parents = data->num_parents; mux->regmap = regmap; mux->reg = data->reg; diff --git a/include/dt-bindings/clock/dra7.h b/include/dt-bindings/clock/dra7.h index 8cec5a1e1806..5ec4137231e3 100644 --- a/include/dt-bindings/clock/dra7.h +++ b/include/dt-bindings/clock/dra7.h @@ -332,6 +332,7 @@ #define DRA7_L4SEC_DES_CLKCTRL DRA7_L4SEC_CLKCTRL_INDEX(0x1b0) #define DRA7_L4SEC_RNG_CLKCTRL DRA7_L4SEC_CLKCTRL_INDEX(0x1c0) #define DRA7_L4SEC_SHAM_CLKCTRL DRA7_L4SEC_CLKCTRL_INDEX(0x1c8) +#define DRA7_L4SEC_SHAM2_CLKCTRL DRA7_L4SEC_CLKCTRL_INDEX(0x1f8) /* l4per2 clocks */ #define DRA7_L4PER2_CLKCTRL_OFFSET 0xc diff --git a/include/dt-bindings/clock/exynos5250.h b/include/dt-bindings/clock/exynos5250.h index bc8a3c53a54b..e259cc01f22f 100644 --- a/include/dt-bindings/clock/exynos5250.h +++ b/include/dt-bindings/clock/exynos5250.h @@ -172,8 +172,10 @@ #define CLK_MOUT_GPLL 1025 #define CLK_MOUT_ACLK200_DISP1_SUB 1026 #define CLK_MOUT_ACLK300_DISP1_SUB 1027 +#define CLK_MOUT_APLL 1028 +#define CLK_MOUT_MPLL 1029 /* must be greater than maximal clock id */ -#define CLK_NR_CLKS 1028 +#define CLK_NR_CLKS 1030 #endif /* _DT_BINDINGS_CLOCK_EXYNOS_5250_H */ diff --git a/include/dt-bindings/clock/exynos5420.h b/include/dt-bindings/clock/exynos5420.h index 02d5ac469a3d..9fffc6ceaadd 100644 --- a/include/dt-bindings/clock/exynos5420.h +++ b/include/dt-bindings/clock/exynos5420.h @@ -230,6 +230,12 @@ #define CLK_MOUT_USER_MAU_EPLL 659 #define CLK_MOUT_SCLK_SPLL 660 #define CLK_MOUT_MX_MSPLL_CCORE_PHY 661 +#define CLK_MOUT_SW_ACLK_G3D 662 +#define CLK_MOUT_APLL 663 +#define CLK_MOUT_MSPLL_CPU 664 +#define CLK_MOUT_KPLL 665 +#define CLK_MOUT_MSPLL_KFC 666 + /* divider clocks */ #define CLK_DOUT_PIXEL 768 diff --git a/include/dt-bindings/clock/mt8167-clk.h b/include/dt-bindings/clock/mt8167-clk.h new file mode 100644 index 000000000000..a96158edd817 --- /dev/null +++ b/include/dt-bindings/clock/mt8167-clk.h @@ -0,0 +1,131 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS. + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#ifndef _DT_BINDINGS_CLK_MT8167_H +#define _DT_BINDINGS_CLK_MT8167_H + +/* MT8167 is based on MT8516 */ +#include <dt-bindings/clock/mt8516-clk.h> + +/* APMIXEDSYS */ + +#define CLK_APMIXED_TVDPLL (CLK_APMIXED_NR_CLK + 0) +#define CLK_APMIXED_LVDSPLL (CLK_APMIXED_NR_CLK + 1) +#define CLK_APMIXED_HDMI_REF (CLK_APMIXED_NR_CLK + 2) +#define MT8167_CLK_APMIXED_NR_CLK (CLK_APMIXED_NR_CLK + 3) + +/* TOPCKGEN */ + +#define CLK_TOP_DSI0_LNTC_DSICK (CLK_TOP_NR_CLK + 0) +#define CLK_TOP_VPLL_DPIX (CLK_TOP_NR_CLK + 1) +#define CLK_TOP_LVDSTX_CLKDIG_CTS (CLK_TOP_NR_CLK + 2) +#define CLK_TOP_HDMTX_CLKDIG_CTS (CLK_TOP_NR_CLK + 3) +#define CLK_TOP_LVDSPLL (CLK_TOP_NR_CLK + 4) +#define CLK_TOP_LVDSPLL_D2 (CLK_TOP_NR_CLK + 5) +#define CLK_TOP_LVDSPLL_D4 (CLK_TOP_NR_CLK + 6) +#define CLK_TOP_LVDSPLL_D8 (CLK_TOP_NR_CLK + 7) +#define CLK_TOP_MIPI_26M (CLK_TOP_NR_CLK + 8) +#define CLK_TOP_TVDPLL (CLK_TOP_NR_CLK + 9) +#define CLK_TOP_TVDPLL_D2 (CLK_TOP_NR_CLK + 10) +#define CLK_TOP_TVDPLL_D4 (CLK_TOP_NR_CLK + 11) +#define CLK_TOP_TVDPLL_D8 (CLK_TOP_NR_CLK + 12) +#define CLK_TOP_TVDPLL_D16 (CLK_TOP_NR_CLK + 13) +#define CLK_TOP_PWM_MM (CLK_TOP_NR_CLK + 14) +#define CLK_TOP_CAM_MM (CLK_TOP_NR_CLK + 15) +#define CLK_TOP_MFG_MM (CLK_TOP_NR_CLK + 16) +#define CLK_TOP_SPM_52M (CLK_TOP_NR_CLK + 17) +#define CLK_TOP_MIPI_26M_DBG (CLK_TOP_NR_CLK + 18) +#define CLK_TOP_SCAM_MM (CLK_TOP_NR_CLK + 19) +#define CLK_TOP_SMI_MM (CLK_TOP_NR_CLK + 20) +#define CLK_TOP_26M_HDMI_SIFM (CLK_TOP_NR_CLK + 21) +#define CLK_TOP_26M_CEC (CLK_TOP_NR_CLK + 22) +#define CLK_TOP_32K_CEC (CLK_TOP_NR_CLK + 23) +#define CLK_TOP_GCPU_B (CLK_TOP_NR_CLK + 24) +#define CLK_TOP_RG_VDEC (CLK_TOP_NR_CLK + 25) +#define CLK_TOP_RG_FDPI0 (CLK_TOP_NR_CLK + 26) +#define CLK_TOP_RG_FDPI1 (CLK_TOP_NR_CLK + 27) +#define CLK_TOP_RG_AXI_MFG (CLK_TOP_NR_CLK + 28) +#define CLK_TOP_RG_SLOW_MFG (CLK_TOP_NR_CLK + 29) +#define CLK_TOP_GFMUX_EMI1X_SEL (CLK_TOP_NR_CLK + 30) +#define CLK_TOP_CSW_MUX_MFG_SEL (CLK_TOP_NR_CLK + 31) +#define CLK_TOP_CAMTG_MM_SEL (CLK_TOP_NR_CLK + 32) +#define CLK_TOP_PWM_MM_SEL (CLK_TOP_NR_CLK + 33) +#define CLK_TOP_SPM_52M_SEL (CLK_TOP_NR_CLK + 34) +#define CLK_TOP_MFG_MM_SEL (CLK_TOP_NR_CLK + 35) +#define CLK_TOP_SMI_MM_SEL (CLK_TOP_NR_CLK + 36) +#define CLK_TOP_SCAM_MM_SEL (CLK_TOP_NR_CLK + 37) +#define CLK_TOP_VDEC_MM_SEL (CLK_TOP_NR_CLK + 38) +#define CLK_TOP_DPI0_MM_SEL (CLK_TOP_NR_CLK + 39) +#define CLK_TOP_DPI1_MM_SEL (CLK_TOP_NR_CLK + 40) +#define CLK_TOP_AXI_MFG_IN_SEL (CLK_TOP_NR_CLK + 41) +#define CLK_TOP_SLOW_MFG_SEL (CLK_TOP_NR_CLK + 42) +#define MT8167_CLK_TOP_NR_CLK (CLK_TOP_NR_CLK + 43) + +/* MFGCFG */ + +#define CLK_MFG_BAXI 0 +#define CLK_MFG_BMEM 1 +#define CLK_MFG_BG3D 2 +#define CLK_MFG_B26M 3 +#define CLK_MFG_NR_CLK 4 + +/* MMSYS */ + +#define CLK_MM_SMI_COMMON 0 +#define CLK_MM_SMI_LARB0 1 +#define CLK_MM_CAM_MDP 2 +#define CLK_MM_MDP_RDMA 3 +#define CLK_MM_MDP_RSZ0 4 +#define CLK_MM_MDP_RSZ1 5 +#define CLK_MM_MDP_TDSHP 6 +#define CLK_MM_MDP_WDMA 7 +#define CLK_MM_MDP_WROT 8 +#define CLK_MM_FAKE_ENG 9 +#define CLK_MM_DISP_OVL0 10 +#define CLK_MM_DISP_RDMA0 11 +#define CLK_MM_DISP_RDMA1 12 +#define CLK_MM_DISP_WDMA 13 +#define CLK_MM_DISP_COLOR 14 +#define CLK_MM_DISP_CCORR 15 +#define CLK_MM_DISP_AAL 16 +#define CLK_MM_DISP_GAMMA 17 +#define CLK_MM_DISP_DITHER 18 +#define CLK_MM_DISP_UFOE 19 +#define CLK_MM_DISP_PWM_MM 20 +#define CLK_MM_DISP_PWM_26M 21 +#define CLK_MM_DSI_ENGINE 22 +#define CLK_MM_DSI_DIGITAL 23 +#define CLK_MM_DPI0_ENGINE 24 +#define CLK_MM_DPI0_PXL 25 +#define CLK_MM_LVDS_PXL 26 +#define CLK_MM_LVDS_CTS 27 +#define CLK_MM_DPI1_ENGINE 28 +#define CLK_MM_DPI1_PXL 29 +#define CLK_MM_HDMI_PXL 30 +#define CLK_MM_HDMI_SPDIF 31 +#define CLK_MM_HDMI_ADSP_BCK 32 +#define CLK_MM_HDMI_PLL 33 +#define CLK_MM_NR_CLK 34 + +/* IMGSYS */ + +#define CLK_IMG_LARB1_SMI 0 +#define CLK_IMG_CAM_SMI 1 +#define CLK_IMG_CAM_CAM 2 +#define CLK_IMG_SEN_TG 3 +#define CLK_IMG_SEN_CAM 4 +#define CLK_IMG_VENC 5 +#define CLK_IMG_NR_CLK 6 + +/* VDECSYS */ + +#define CLK_VDEC_CKEN 0 +#define CLK_VDEC_LARB1_CKEN 1 +#define CLK_VDEC_NR_CLK 2 + +#endif /* _DT_BINDINGS_CLK_MT8167_H */ diff --git a/include/dt-bindings/clock/qcom,dispcc-sm8150.h b/include/dt-bindings/clock/qcom,dispcc-sm8150.h new file mode 120000 index 000000000000..0312b4544acb --- /dev/null +++ b/include/dt-bindings/clock/qcom,dispcc-sm8150.h @@ -0,0 +1 @@ +qcom,dispcc-sm8250.h
\ No newline at end of file diff --git a/include/dt-bindings/clock/qcom,dispcc-sm8250.h b/include/dt-bindings/clock/qcom,dispcc-sm8250.h new file mode 100644 index 000000000000..fdaca6ad5c85 --- /dev/null +++ b/include/dt-bindings/clock/qcom,dispcc-sm8250.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_DISP_CC_SM8250_H +#define _DT_BINDINGS_CLK_QCOM_DISP_CC_SM8250_H + +/* DISP_CC clock registers */ +#define DISP_CC_MDSS_AHB_CLK 0 +#define DISP_CC_MDSS_AHB_CLK_SRC 1 +#define DISP_CC_MDSS_BYTE0_CLK 2 +#define DISP_CC_MDSS_BYTE0_CLK_SRC 3 +#define DISP_CC_MDSS_BYTE0_DIV_CLK_SRC 4 +#define DISP_CC_MDSS_BYTE0_INTF_CLK 5 +#define DISP_CC_MDSS_BYTE1_CLK 6 +#define DISP_CC_MDSS_BYTE1_CLK_SRC 7 +#define DISP_CC_MDSS_BYTE1_DIV_CLK_SRC 8 +#define DISP_CC_MDSS_BYTE1_INTF_CLK 9 +#define DISP_CC_MDSS_DP_AUX1_CLK 10 +#define DISP_CC_MDSS_DP_AUX1_CLK_SRC 11 +#define DISP_CC_MDSS_DP_AUX_CLK 12 +#define DISP_CC_MDSS_DP_AUX_CLK_SRC 13 +#define DISP_CC_MDSS_DP_LINK1_CLK 14 +#define DISP_CC_MDSS_DP_LINK1_CLK_SRC 15 +#define DISP_CC_MDSS_DP_LINK1_DIV_CLK_SRC 16 +#define DISP_CC_MDSS_DP_LINK1_INTF_CLK 17 +#define DISP_CC_MDSS_DP_LINK_CLK 18 +#define DISP_CC_MDSS_DP_LINK_CLK_SRC 19 +#define DISP_CC_MDSS_DP_LINK_DIV_CLK_SRC 20 +#define DISP_CC_MDSS_DP_LINK_INTF_CLK 21 +#define DISP_CC_MDSS_DP_PIXEL1_CLK 22 +#define DISP_CC_MDSS_DP_PIXEL1_CLK_SRC 23 +#define DISP_CC_MDSS_DP_PIXEL2_CLK 24 +#define DISP_CC_MDSS_DP_PIXEL2_CLK_SRC 25 +#define DISP_CC_MDSS_DP_PIXEL_CLK 26 +#define DISP_CC_MDSS_DP_PIXEL_CLK_SRC 27 +#define DISP_CC_MDSS_ESC0_CLK 28 +#define DISP_CC_MDSS_ESC0_CLK_SRC 29 +#define DISP_CC_MDSS_ESC1_CLK 30 +#define DISP_CC_MDSS_ESC1_CLK_SRC 31 +#define DISP_CC_MDSS_MDP_CLK 32 +#define DISP_CC_MDSS_MDP_CLK_SRC 33 +#define DISP_CC_MDSS_MDP_LUT_CLK 34 +#define DISP_CC_MDSS_NON_GDSC_AHB_CLK 35 +#define DISP_CC_MDSS_PCLK0_CLK 36 +#define DISP_CC_MDSS_PCLK0_CLK_SRC 37 +#define DISP_CC_MDSS_PCLK1_CLK 38 +#define DISP_CC_MDSS_PCLK1_CLK_SRC 39 +#define DISP_CC_MDSS_ROT_CLK 40 +#define DISP_CC_MDSS_ROT_CLK_SRC 41 +#define DISP_CC_MDSS_RSCC_AHB_CLK 42 +#define DISP_CC_MDSS_RSCC_VSYNC_CLK 43 +#define DISP_CC_MDSS_VSYNC_CLK 44 +#define DISP_CC_MDSS_VSYNC_CLK_SRC 45 +#define DISP_CC_PLL0 46 +#define DISP_CC_PLL1 47 + +/* DISP_CC Reset */ +#define DISP_CC_MDSS_CORE_BCR 0 +#define DISP_CC_MDSS_RSCC_BCR 1 + +/* DISP_CC GDSCR */ +#define MDSS_GDSC 0 + +#endif diff --git a/include/dt-bindings/clock/qcom,gcc-msm8994.h b/include/dt-bindings/clock/qcom,gcc-msm8994.h index 938969309e00..507b8d6effd2 100644 --- a/include/dt-bindings/clock/qcom,gcc-msm8994.h +++ b/include/dt-bindings/clock/qcom,gcc-msm8994.h @@ -126,5 +126,41 @@ #define GCC_USB3_PHY_AUX_CLK 116 #define GCC_USB_HS_SYSTEM_CLK 117 #define GCC_SDCC1_AHB_CLK 118 +#define GCC_LPASS_Q6_AXI_CLK 119 +#define GCC_MSS_Q6_BIMC_AXI_CLK 120 +#define GCC_PCIE_0_CFG_AHB_CLK 121 +#define GCC_PCIE_0_MSTR_AXI_CLK 122 +#define GCC_PCIE_0_SLV_AXI_CLK 123 +#define GCC_PCIE_1_CFG_AHB_CLK 124 +#define GCC_PCIE_1_MSTR_AXI_CLK 125 +#define GCC_PCIE_1_SLV_AXI_CLK 126 +#define GCC_PDM_AHB_CLK 127 +#define GCC_SDCC2_AHB_CLK 128 +#define GCC_SDCC3_AHB_CLK 129 +#define GCC_SDCC4_AHB_CLK 130 +#define GCC_TSIF_AHB_CLK 131 +#define GCC_UFS_AHB_CLK 132 +#define GCC_UFS_RX_SYMBOL_0_CLK 133 +#define GCC_UFS_RX_SYMBOL_1_CLK 134 +#define GCC_UFS_TX_SYMBOL_0_CLK 135 +#define GCC_UFS_TX_SYMBOL_1_CLK 136 +#define GCC_USB2_HS_PHY_SLEEP_CLK 137 +#define GCC_USB30_SLEEP_CLK 138 +#define GCC_USB_HS_AHB_CLK 139 +#define GCC_USB_PHY_CFG_AHB2PHY_CLK 140 + +/* GDSCs */ +#define PCIE_GDSC 0 +#define PCIE_0_GDSC 1 +#define PCIE_1_GDSC 2 +#define USB30_GDSC 3 +#define UFS_GDSC 4 + +/* Resets */ +#define USB3_PHY_RESET 0 +#define USB3PHY_PHY_RESET 1 +#define PCIE_PHY_0_RESET 2 +#define PCIE_PHY_1_RESET 3 +#define QUSB2_PHY_RESET 4 #endif diff --git a/include/dt-bindings/clock/qcom,videocc-sm8150.h b/include/dt-bindings/clock/qcom,videocc-sm8150.h new file mode 100644 index 000000000000..e24ee840cfdb --- /dev/null +++ b/include/dt-bindings/clock/qcom,videocc-sm8150.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8150_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8150_H + +/* VIDEO_CC clocks */ +#define VIDEO_CC_IRIS_AHB_CLK 0 +#define VIDEO_CC_IRIS_CLK_SRC 1 +#define VIDEO_CC_MVS0_CORE_CLK 2 +#define VIDEO_CC_MVS1_CORE_CLK 3 +#define VIDEO_CC_MVSC_CORE_CLK 4 +#define VIDEO_CC_PLL0 5 + +/* VIDEO_CC Resets */ +#define VIDEO_CC_MVSC_CORE_CLK_BCR 0 + +/* VIDEO_CC GDSCRs */ +#define VENUS_GDSC 0 +#define VCODEC0_GDSC 1 +#define VCODEC1_GDSC 2 + +#endif diff --git a/include/dt-bindings/clock/qcom,videocc-sm8250.h b/include/dt-bindings/clock/qcom,videocc-sm8250.h new file mode 100644 index 000000000000..2b2b3867af25 --- /dev/null +++ b/include/dt-bindings/clock/qcom,videocc-sm8250.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8250_H +#define _DT_BINDINGS_CLK_QCOM_VIDEO_CC_SM8250_H + +/* VIDEO_CC clocks */ +#define VIDEO_CC_MVS0_CLK_SRC 0 +#define VIDEO_CC_MVS0C_CLK 1 +#define VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC 2 +#define VIDEO_CC_MVS1_CLK_SRC 3 +#define VIDEO_CC_MVS1_DIV2_CLK 4 +#define VIDEO_CC_MVS1C_CLK 5 +#define VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC 6 +#define VIDEO_CC_PLL0 7 +#define VIDEO_CC_PLL1 8 + +/* VIDEO_CC resets */ +#define VIDEO_CC_CVP_INTERFACE_BCR 0 +#define VIDEO_CC_CVP_MVS0_BCR 1 +#define VIDEO_CC_MVS0C_CLK_ARES 2 +#define VIDEO_CC_CVP_MVS0C_BCR 3 +#define VIDEO_CC_CVP_MVS1_BCR 4 +#define VIDEO_CC_MVS1C_CLK_ARES 5 +#define VIDEO_CC_CVP_MVS1C_BCR 6 + +#define MVS0C_GDSC 0 +#define MVS1C_GDSC 1 +#define MVS0_GDSC 2 +#define MVS1_GDSC 3 + +#endif diff --git a/include/dt-bindings/clock/r8a779a0-cpg-mssr.h b/include/dt-bindings/clock/r8a779a0-cpg-mssr.h new file mode 100644 index 000000000000..f1d737ca7ca1 --- /dev/null +++ b/include/dt-bindings/clock/r8a779a0-cpg-mssr.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_CLOCK_R8A779A0_CPG_MSSR_H__ +#define __DT_BINDINGS_CLOCK_R8A779A0_CPG_MSSR_H__ + +#include <dt-bindings/clock/renesas-cpg-mssr.h> + +/* r8a779A0 CPG Core Clocks */ +#define R8A779A0_CLK_Z0 0 +#define R8A779A0_CLK_ZX 1 +#define R8A779A0_CLK_Z1 2 +#define R8A779A0_CLK_ZR 3 +#define R8A779A0_CLK_ZS 4 +#define R8A779A0_CLK_ZT 5 +#define R8A779A0_CLK_ZTR 6 +#define R8A779A0_CLK_S1D1 7 +#define R8A779A0_CLK_S1D2 8 +#define R8A779A0_CLK_S1D4 9 +#define R8A779A0_CLK_S1D8 10 +#define R8A779A0_CLK_S1D12 11 +#define R8A779A0_CLK_S3D1 12 +#define R8A779A0_CLK_S3D2 13 +#define R8A779A0_CLK_S3D4 14 +#define R8A779A0_CLK_LB 15 +#define R8A779A0_CLK_CP 16 +#define R8A779A0_CLK_CL 17 +#define R8A779A0_CLK_CL16MCK 18 +#define R8A779A0_CLK_ZB30 19 +#define R8A779A0_CLK_ZB30D2 20 +#define R8A779A0_CLK_ZB30D4 21 +#define R8A779A0_CLK_ZB31 22 +#define R8A779A0_CLK_ZB31D2 23 +#define R8A779A0_CLK_ZB31D4 24 +#define R8A779A0_CLK_SD0H 25 +#define R8A779A0_CLK_SD0 26 +#define R8A779A0_CLK_RPC 27 +#define R8A779A0_CLK_RPCD2 28 +#define R8A779A0_CLK_MSO 29 +#define R8A779A0_CLK_CANFD 30 +#define R8A779A0_CLK_CSI0 31 +#define R8A779A0_CLK_FRAY 32 +#define R8A779A0_CLK_DSI 33 +#define R8A779A0_CLK_VIP 34 +#define R8A779A0_CLK_ADGH 35 +#define R8A779A0_CLK_CNNDSP 36 +#define R8A779A0_CLK_ICU 37 +#define R8A779A0_CLK_ICUD2 38 +#define R8A779A0_CLK_VCBUS 39 +#define R8A779A0_CLK_CBFUSA 40 +#define R8A779A0_CLK_R 41 +#define R8A779A0_CLK_OSC 42 + +#endif /* __DT_BINDINGS_CLOCK_R8A779A0_CPG_MSSR_H__ */ diff --git a/include/dt-bindings/clock/sun50i-a100-ccu.h b/include/dt-bindings/clock/sun50i-a100-ccu.h new file mode 100644 index 000000000000..28dc36e1a232 --- /dev/null +++ b/include/dt-bindings/clock/sun50i-a100-ccu.h @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_A100_H_ +#define _DT_BINDINGS_CLK_SUN50I_A100_H_ + +#define CLK_PLL_PERIPH0 3 + +#define CLK_CPUX 24 + +#define CLK_APB1 29 + +#define CLK_MBUS 31 +#define CLK_DE 32 +#define CLK_BUS_DE 33 +#define CLK_G2D 34 +#define CLK_BUS_G2D 35 +#define CLK_GPU 36 +#define CLK_BUS_GPU 37 +#define CLK_CE 38 +#define CLK_BUS_CE 39 +#define CLK_VE 40 +#define CLK_BUS_VE 41 +#define CLK_BUS_DMA 42 +#define CLK_BUS_MSGBOX 43 +#define CLK_BUS_SPINLOCK 44 +#define CLK_BUS_HSTIMER 45 +#define CLK_AVS 46 +#define CLK_BUS_DBG 47 +#define CLK_BUS_PSI 48 +#define CLK_BUS_PWM 49 +#define CLK_BUS_IOMMU 50 +#define CLK_MBUS_DMA 51 +#define CLK_MBUS_VE 52 +#define CLK_MBUS_CE 53 +#define CLK_MBUS_NAND 54 +#define CLK_MBUS_CSI 55 +#define CLK_MBUS_ISP 56 +#define CLK_MBUS_G2D 57 + +#define CLK_NAND0 59 +#define CLK_NAND1 60 +#define CLK_BUS_NAND 61 +#define CLK_MMC0 62 +#define CLK_MMC1 63 +#define CLK_MMC2 64 +#define CLK_MMC3 65 +#define CLK_BUS_MMC0 66 +#define CLK_BUS_MMC1 67 +#define CLK_BUS_MMC2 68 +#define CLK_BUS_UART0 69 +#define CLK_BUS_UART1 70 +#define CLK_BUS_UART2 71 +#define CLK_BUS_UART3 72 +#define CLK_BUS_UART4 73 +#define CLK_BUS_I2C0 74 +#define CLK_BUS_I2C1 75 +#define CLK_BUS_I2C2 76 +#define CLK_BUS_I2C3 77 +#define CLK_SPI0 78 +#define CLK_SPI1 79 +#define CLK_SPI2 80 +#define CLK_BUS_SPI0 81 +#define CLK_BUS_SPI1 82 +#define CLK_BUS_SPI2 83 +#define CLK_EMAC_25M 84 +#define CLK_BUS_EMAC 85 +#define CLK_IR_RX 86 +#define CLK_BUS_IR_RX 87 +#define CLK_IR_TX 88 +#define CLK_BUS_IR_TX 89 +#define CLK_BUS_GPADC 90 +#define CLK_BUS_THS 91 +#define CLK_I2S0 92 +#define CLK_I2S1 93 +#define CLK_I2S2 94 +#define CLK_I2S3 95 +#define CLK_BUS_I2S0 96 +#define CLK_BUS_I2S1 97 +#define CLK_BUS_I2S2 98 +#define CLK_BUS_I2S3 99 +#define CLK_SPDIF 100 +#define CLK_BUS_SPDIF 101 +#define CLK_DMIC 102 +#define CLK_BUS_DMIC 103 +#define CLK_AUDIO_DAC 104 +#define CLK_AUDIO_ADC 105 +#define CLK_AUDIO_4X 106 +#define CLK_BUS_AUDIO_CODEC 107 +#define CLK_USB_OHCI0 108 +#define CLK_USB_PHY0 109 +#define CLK_USB_OHCI1 110 +#define CLK_USB_PHY1 111 +#define CLK_BUS_OHCI0 112 +#define CLK_BUS_OHCI1 113 +#define CLK_BUS_EHCI0 114 +#define CLK_BUS_EHCI1 115 +#define CLK_BUS_OTG 116 +#define CLK_BUS_LRADC 117 +#define CLK_BUS_DPSS_TOP0 118 +#define CLK_BUS_DPSS_TOP1 119 +#define CLK_MIPI_DSI 120 +#define CLK_BUS_MIPI_DSI 121 +#define CLK_TCON_LCD 122 +#define CLK_BUS_TCON_LCD 123 +#define CLK_LEDC 124 +#define CLK_BUS_LEDC 125 +#define CLK_CSI_TOP 126 +#define CLK_CSI0_MCLK 127 +#define CLK_CSI1_MCLK 128 +#define CLK_BUS_CSI 129 +#define CLK_CSI_ISP 130 + +#endif /* _DT_BINDINGS_CLK_SUN50I_A100_H_ */ diff --git a/include/dt-bindings/clock/sun50i-a100-r-ccu.h b/include/dt-bindings/clock/sun50i-a100-r-ccu.h new file mode 100644 index 000000000000..07312e7264fb --- /dev/null +++ b/include/dt-bindings/clock/sun50i-a100-r-ccu.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ +#define _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ + +#define CLK_R_APB1 2 + +#define CLK_R_APB1_TIMER 4 +#define CLK_R_APB1_TWD 5 +#define CLK_R_APB1_PWM 6 +#define CLK_R_APB1_BUS_PWM 7 +#define CLK_R_APB1_PPU 8 +#define CLK_R_APB2_UART 9 +#define CLK_R_APB2_I2C0 10 +#define CLK_R_APB2_I2C1 11 +#define CLK_R_APB1_IR 12 +#define CLK_R_APB1_BUS_IR 13 +#define CLK_R_AHB_BUS_RTC 14 + +#endif /* _DT_BINDINGS_CLK_SUN50I_A100_R_CCU_H_ */ diff --git a/include/dt-bindings/power/r8a779a0-sysc.h b/include/dt-bindings/power/r8a779a0-sysc.h new file mode 100644 index 000000000000..57929e459a67 --- /dev/null +++ b/include/dt-bindings/power/r8a779a0-sysc.h @@ -0,0 +1,59 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Renesas Electronics Corp. + */ +#ifndef __DT_BINDINGS_POWER_R8A779A0_SYSC_H__ +#define __DT_BINDINGS_POWER_R8A779A0_SYSC_H__ + +/* + * These power domain indices match the Power Domain Register Numbers (PDR) + */ + +#define R8A779A0_PD_A1E0D0C0 0 +#define R8A779A0_PD_A1E0D0C1 1 +#define R8A779A0_PD_A1E0D1C0 2 +#define R8A779A0_PD_A1E0D1C1 3 +#define R8A779A0_PD_A1E1D0C0 4 +#define R8A779A0_PD_A1E1D0C1 5 +#define R8A779A0_PD_A1E1D1C0 6 +#define R8A779A0_PD_A1E1D1C1 7 +#define R8A779A0_PD_A2E0D0 16 +#define R8A779A0_PD_A2E0D1 17 +#define R8A779A0_PD_A2E1D0 18 +#define R8A779A0_PD_A2E1D1 19 +#define R8A779A0_PD_A3E0 20 +#define R8A779A0_PD_A3E1 21 +#define R8A779A0_PD_3DG_A 24 +#define R8A779A0_PD_3DG_B 25 +#define R8A779A0_PD_A1CNN2 32 +#define R8A779A0_PD_A1DSP0 33 +#define R8A779A0_PD_A2IMP01 34 +#define R8A779A0_PD_A2DP0 35 +#define R8A779A0_PD_A2CV0 36 +#define R8A779A0_PD_A2CV1 37 +#define R8A779A0_PD_A2CV4 38 +#define R8A779A0_PD_A2CV6 39 +#define R8A779A0_PD_A2CN2 40 +#define R8A779A0_PD_A1CNN0 41 +#define R8A779A0_PD_A2CN0 42 +#define R8A779A0_PD_A3IR 43 +#define R8A779A0_PD_A1CNN1 44 +#define R8A779A0_PD_A1DSP1 45 +#define R8A779A0_PD_A2IMP23 46 +#define R8A779A0_PD_A2DP1 47 +#define R8A779A0_PD_A2CV2 48 +#define R8A779A0_PD_A2CV3 49 +#define R8A779A0_PD_A2CV5 50 +#define R8A779A0_PD_A2CV7 51 +#define R8A779A0_PD_A2CN1 52 +#define R8A779A0_PD_A3VIP0 56 +#define R8A779A0_PD_A3VIP1 57 +#define R8A779A0_PD_A3VIP2 58 +#define R8A779A0_PD_A3VIP3 59 +#define R8A779A0_PD_A3ISP01 60 +#define R8A779A0_PD_A3ISP23 61 + +/* Always-on power area */ +#define R8A779A0_PD_ALWAYS_ON 64 + +#endif /* __DT_BINDINGS_POWER_R8A779A0_SYSC_H__ */ diff --git a/include/dt-bindings/reset/sun50i-a100-ccu.h b/include/dt-bindings/reset/sun50i-a100-ccu.h new file mode 100644 index 000000000000..55c0ada99885 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-a100-ccu.h @@ -0,0 +1,68 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _DT_BINDINGS_RESET_SUN50I_A100_H_ +#define _DT_BINDINGS_RESET_SUN50I_A100_H_ + +#define RST_MBUS 0 +#define RST_BUS_DE 1 +#define RST_BUS_G2D 2 +#define RST_BUS_GPU 3 +#define RST_BUS_CE 4 +#define RST_BUS_VE 5 +#define RST_BUS_DMA 6 +#define RST_BUS_MSGBOX 7 +#define RST_BUS_SPINLOCK 8 +#define RST_BUS_HSTIMER 9 +#define RST_BUS_DBG 10 +#define RST_BUS_PSI 11 +#define RST_BUS_PWM 12 +#define RST_BUS_DRAM 13 +#define RST_BUS_NAND 14 +#define RST_BUS_MMC0 15 +#define RST_BUS_MMC1 16 +#define RST_BUS_MMC2 17 +#define RST_BUS_UART0 18 +#define RST_BUS_UART1 19 +#define RST_BUS_UART2 20 +#define RST_BUS_UART3 21 +#define RST_BUS_UART4 22 +#define RST_BUS_I2C0 23 +#define RST_BUS_I2C1 24 +#define RST_BUS_I2C2 25 +#define RST_BUS_I2C3 26 +#define RST_BUS_SPI0 27 +#define RST_BUS_SPI1 28 +#define RST_BUS_SPI2 29 +#define RST_BUS_EMAC 30 +#define RST_BUS_IR_RX 31 +#define RST_BUS_IR_TX 32 +#define RST_BUS_GPADC 33 +#define RST_BUS_THS 34 +#define RST_BUS_I2S0 35 +#define RST_BUS_I2S1 36 +#define RST_BUS_I2S2 37 +#define RST_BUS_I2S3 38 +#define RST_BUS_SPDIF 39 +#define RST_BUS_DMIC 40 +#define RST_BUS_AUDIO_CODEC 41 +#define RST_USB_PHY0 42 +#define RST_USB_PHY1 43 +#define RST_BUS_OHCI0 44 +#define RST_BUS_OHCI1 45 +#define RST_BUS_EHCI0 46 +#define RST_BUS_EHCI1 47 +#define RST_BUS_OTG 48 +#define RST_BUS_LRADC 49 +#define RST_BUS_DPSS_TOP0 50 +#define RST_BUS_DPSS_TOP1 51 +#define RST_BUS_MIPI_DSI 52 +#define RST_BUS_TCON_LCD 53 +#define RST_BUS_LVDS 54 +#define RST_BUS_LEDC 55 +#define RST_BUS_CSI 56 +#define RST_BUS_CSI_ISP 57 + +#endif /* _DT_BINDINGS_RESET_SUN50I_A100_H_ */ diff --git a/include/dt-bindings/reset/sun50i-a100-r-ccu.h b/include/dt-bindings/reset/sun50i-a100-r-ccu.h new file mode 100644 index 000000000000..737bf6f66626 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-a100-r-ccu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (c) 2020 Yangtao Li <frank@allwinnertech.com> + */ + +#ifndef _DT_BINDINGS_RST_SUN50I_A100_R_CCU_H_ +#define _DT_BINDINGS_RST_SUN50I_A100_R_CCU_H_ + +#define RST_R_APB1_TIMER 0 +#define RST_R_APB1_BUS_PWM 1 +#define RST_R_APB1_PPU 2 +#define RST_R_APB2_UART 3 +#define RST_R_APB2_I2C0 4 +#define RST_R_APB2_I2C1 5 +#define RST_R_APB1_BUS_IR 6 +#define RST_R_AHB_BUS_RTC 7 + +#endif /* _DT_BINDINGS_RST_SUN50I_A100_R_CCU_H_ */ |