diff options
Diffstat (limited to 'drivers/clk/mediatek')
-rw-r--r-- | drivers/clk/mediatek/Kconfig | 6 | ||||
-rw-r--r-- | drivers/clk/mediatek/Makefile | 1 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt2701-aud.c | 186 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt2701.c | 15 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt2712.c | 69 | ||||
-rw-r--r-- | drivers/clk/mediatek/clk-mt7622-aud.c | 15 |
6 files changed, 270 insertions, 22 deletions
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index 1f9ea0f21df1..92afe5989e97 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -54,6 +54,12 @@ config COMMON_CLK_MT2701_BDPSYS ---help--- This driver supports MediaTek MT2701 bdpsys clocks. +config COMMON_CLK_MT2701_AUDSYS + bool "Clock driver for Mediatek MT2701 audsys" + depends on COMMON_CLK_MT2701 + ---help--- + This driver supports Mediatek MT2701 audsys clocks. + config COMMON_CLK_MT2712 bool "Clock driver for MediaTek MT2712" depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile index 5160fdc4bbb8..b80eff2abb31 100644 --- a/drivers/clk/mediatek/Makefile +++ b/drivers/clk/mediatek/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o +obj-$(CONFIG_COMMON_CLK_MT2701_AUDSYS) += clk-mt2701-aud.o obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c new file mode 100644 index 000000000000..e66896a44fad --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-aud.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +#define GATE_AUDIO0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +#define GATE_AUDIO3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &audio3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs audio2_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +static const struct mtk_gate_regs audio3_cg_regs = { + .set_ofs = 0x634, + .clr_ofs = 0x634, + .sta_ofs = 0x634, +}; + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2), + GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20), + GATE_AUDIO0(CLK_AUD_SPDF, "audio_spdf", "audpll_sel", 21), + GATE_AUDIO0(CLK_AUD_SPDF2, "audio_spdf2", "audpll_sel", 22), + GATE_AUDIO0(CLK_AUD_APLL, "audio_apll", "audpll_sel", 23), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUD_I2SIN1, "audio_i2sin1", "aud_mux1_sel", 0), + GATE_AUDIO1(CLK_AUD_I2SIN2, "audio_i2sin2", "aud_mux1_sel", 1), + GATE_AUDIO1(CLK_AUD_I2SIN3, "audio_i2sin3", "aud_mux1_sel", 2), + GATE_AUDIO1(CLK_AUD_I2SIN4, "audio_i2sin4", "aud_mux1_sel", 3), + GATE_AUDIO1(CLK_AUD_I2SIN5, "audio_i2sin5", "aud_mux1_sel", 4), + GATE_AUDIO1(CLK_AUD_I2SIN6, "audio_i2sin6", "aud_mux1_sel", 5), + GATE_AUDIO1(CLK_AUD_I2SO1, "audio_i2so1", "aud_mux1_sel", 6), + GATE_AUDIO1(CLK_AUD_I2SO2, "audio_i2so2", "aud_mux1_sel", 7), + GATE_AUDIO1(CLK_AUD_I2SO3, "audio_i2so3", "aud_mux1_sel", 8), + GATE_AUDIO1(CLK_AUD_I2SO4, "audio_i2so4", "aud_mux1_sel", 9), + GATE_AUDIO1(CLK_AUD_I2SO5, "audio_i2so5", "aud_mux1_sel", 10), + GATE_AUDIO1(CLK_AUD_I2SO6, "audio_i2so6", "aud_mux1_sel", 11), + GATE_AUDIO1(CLK_AUD_ASRCI1, "audio_asrci1", "asm_h_sel", 12), + GATE_AUDIO1(CLK_AUD_ASRCI2, "audio_asrci2", "asm_h_sel", 13), + GATE_AUDIO1(CLK_AUD_ASRCO1, "audio_asrco1", "asm_h_sel", 14), + GATE_AUDIO1(CLK_AUD_ASRCO2, "audio_asrco2", "asm_h_sel", 15), + GATE_AUDIO1(CLK_AUD_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUD_A1SYS, "audio_a1sys", "aud_mux1_sel", 21), + GATE_AUDIO1(CLK_AUD_A2SYS, "audio_a2sys", "aud_mux2_sel", 22), + GATE_AUDIO1(CLK_AUD_AFE_CONN, "audio_afe_conn", "aud_mux1_sel", 23), + GATE_AUDIO1(CLK_AUD_AFE_MRGIF, "audio_afe_mrgif", "aud_mux1_sel", 25), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUD_MMIF_UL1, "audio_ul1", "aud_mux1_sel", 0), + GATE_AUDIO2(CLK_AUD_MMIF_UL2, "audio_ul2", "aud_mux1_sel", 1), + GATE_AUDIO2(CLK_AUD_MMIF_UL3, "audio_ul3", "aud_mux1_sel", 2), + GATE_AUDIO2(CLK_AUD_MMIF_UL4, "audio_ul4", "aud_mux1_sel", 3), + GATE_AUDIO2(CLK_AUD_MMIF_UL5, "audio_ul5", "aud_mux1_sel", 4), + GATE_AUDIO2(CLK_AUD_MMIF_UL6, "audio_ul6", "aud_mux1_sel", 5), + GATE_AUDIO2(CLK_AUD_MMIF_DL1, "audio_dl1", "aud_mux1_sel", 6), + GATE_AUDIO2(CLK_AUD_MMIF_DL2, "audio_dl2", "aud_mux1_sel", 7), + GATE_AUDIO2(CLK_AUD_MMIF_DL3, "audio_dl3", "aud_mux1_sel", 8), + GATE_AUDIO2(CLK_AUD_MMIF_DL4, "audio_dl4", "aud_mux1_sel", 9), + GATE_AUDIO2(CLK_AUD_MMIF_DL5, "audio_dl5", "aud_mux1_sel", 10), + GATE_AUDIO2(CLK_AUD_MMIF_DL6, "audio_dl6", "aud_mux1_sel", 11), + GATE_AUDIO2(CLK_AUD_MMIF_DLMCH, "audio_dlmch", "aud_mux1_sel", 12), + GATE_AUDIO2(CLK_AUD_MMIF_ARB1, "audio_arb1", "aud_mux1_sel", 13), + GATE_AUDIO2(CLK_AUD_MMIF_AWB1, "audio_awb", "aud_mux1_sel", 14), + GATE_AUDIO2(CLK_AUD_MMIF_AWB2, "audio_awb2", "aud_mux1_sel", 15), + GATE_AUDIO2(CLK_AUD_MMIF_DAI, "audio_dai", "aud_mux1_sel", 16), + /* AUDIO3 */ + GATE_AUDIO3(CLK_AUD_ASRCI3, "audio_asrci3", "asm_h_sel", 2), + GATE_AUDIO3(CLK_AUD_ASRCI4, "audio_asrci4", "asm_h_sel", 3), + GATE_AUDIO3(CLK_AUD_ASRCI5, "audio_asrci5", "asm_h_sel", 4), + GATE_AUDIO3(CLK_AUD_ASRCI6, "audio_asrci6", "asm_h_sel", 5), + GATE_AUDIO3(CLK_AUD_ASRCO3, "audio_asrco3", "asm_h_sel", 6), + GATE_AUDIO3(CLK_AUD_ASRCO4, "audio_asrco4", "asm_h_sel", 7), + GATE_AUDIO3(CLK_AUD_ASRCO5, "audio_asrco5", "asm_h_sel", 8), + GATE_AUDIO3(CLK_AUD_ASRCO6, "audio_asrco6", "asm_h_sel", 9), + GATE_AUDIO3(CLK_AUD_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), + GATE_AUDIO3(CLK_AUD_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), + GATE_AUDIO3(CLK_AUD_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), + GATE_AUDIO3(CLK_AUD_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), + GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), +}; + +static const struct of_device_id of_match_clk_mt2701_aud[] = { + { .compatible = "mediatek,mt2701-audsys", }, + {} +}; + +static int clk_mt2701_aud_probe(struct platform_device *pdev) +{ + struct clk_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + goto err_clk_provider; + } + + r = devm_of_platform_populate(&pdev->dev); + if (r) + goto err_plat_populate; + + return 0; + +err_plat_populate: + of_clk_del_provider(node); +err_clk_provider: + return r; +} + +static struct platform_driver clk_mt2701_aud_drv = { + .probe = clk_mt2701_aud_probe, + .driver = { + .name = "clk-mt2701-aud", + .of_match_table = of_match_clk_mt2701_aud, + }, +}; + +builtin_platform_driver(clk_mt2701_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c index 8e7f16fd87c9..deca7527f92f 100644 --- a/drivers/clk/mediatek/clk-mt2701.c +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -148,6 +148,7 @@ static const struct mtk_fixed_factor top_fixed_divs[] = { FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8), FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793), FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1), + FACTOR(CLK_TOP_AXISEL_D4, "axisel_d4", "axi_sel", 1, 4), }; static const char * const axi_parents[] = { @@ -857,13 +858,13 @@ static const struct mtk_gate peri_clks[] = { GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11), GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10), GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9), - GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8), - GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7), - GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6), - GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5), - GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4), - GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3), - GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2), + GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axisel_d4", 8), + GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axisel_d4", 7), + GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axisel_d4", 6), + GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axisel_d4", 5), + GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axisel_d4", 4), + GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axisel_d4", 3), + GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axisel_d4", 2), GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1), GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0), diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c index 498d13799388..991d4093726e 100644 --- a/drivers/clk/mediatek/clk-mt2712.c +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -221,6 +221,8 @@ static const struct mtk_fixed_factor top_divs[] = { 4), FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1, 4), + FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1_ck", 1, + 3), }; static const char * const axi_parents[] = { @@ -625,7 +627,7 @@ static const char * const ether_125m_parents[] = { static const char * const ether_50m_parents[] = { "clk26m", "etherpll_50m", - "univpll_d26", + "apll1_d3", "univpll3_d4" }; @@ -686,7 +688,7 @@ static const char * const i2c_parents[] = { static const char * const msdc0p_aes_parents[] = { "clk26m", - "msdcpll_ck", + "syspll_d2", "univpll_d3", "vcodecpll_ck" }; @@ -719,6 +721,17 @@ static const char * const aud_apll2_parents[] = { "clkaud_ext_i_2" }; +static const char * const apll1_ref_parents[] = { + "clkaud_ext_i_2", + "clkaud_ext_i_1", + "clki2si0_mck_i", + "clki2si1_mck_i", + "clki2si2_mck_i", + "clktdmin_mclk_i", + "clki2si2_mck_i", + "clktdmin_mclk_i" +}; + static const char * const audull_vtx_parents[] = { "d2a_ulclk_6p5m", "clkaud_ext_i_0" @@ -886,6 +899,10 @@ static struct mtk_composite top_muxes[] = { aud_apll2_parents, 0x134, 1, 1), MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel", audull_vtx_parents, 0x134, 31, 1), + MUX(CLK_TOP_APLL1_REF_SEL, "apll1_ref_sel", + apll1_ref_parents, 0x134, 4, 3), + MUX(CLK_TOP_APLL2_REF_SEL, "apll2_ref_sel", + apll1_ref_parents, 0x134, 7, 3), }; static const char * const mcu_mp0_parents[] = { @@ -932,36 +949,56 @@ static const struct mtk_clk_divider top_adj_divs[] = { DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8), }; -static const struct mtk_gate_regs top_cg_regs = { +static const struct mtk_gate_regs top0_cg_regs = { .set_ofs = 0x120, .clr_ofs = 0x120, .sta_ofs = 0x120, }; -#define GATE_TOP(_id, _name, _parent, _shift) { \ +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x424, + .clr_ofs = 0x424, + .sta_ofs = 0x424, +}; + +#define GATE_TOP0(_id, _name, _parent, _shift) { \ .id = _id, \ .name = _name, \ .parent_name = _parent, \ - .regs = &top_cg_regs, \ + .regs = &top0_cg_regs, \ .shift = _shift, \ .ops = &mtk_clk_gate_ops_no_setclr, \ } +#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_no_setclr_inv, \ + } + static const struct mtk_gate top_clks[] = { - GATE_TOP(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), - GATE_TOP(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), - GATE_TOP(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), - GATE_TOP(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), - GATE_TOP(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), - GATE_TOP(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), - GATE_TOP(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), - GATE_TOP(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), + /* TOP0 */ + GATE_TOP0(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), + /* TOP1 */ + GATE_TOP1(CLK_TOP_NFI2X_EN, "nfi2x_en", "nfi2x_sel", 0), + GATE_TOP1(CLK_TOP_NFIECC_EN, "nfiecc_en", "nfiecc_sel", 1), + GATE_TOP1(CLK_TOP_NFI1X_CK_EN, "nfi1x_ck_en", "nfi2x_sel", 2), }; static const struct mtk_gate_regs infra_cg_regs = { .set_ofs = 0x40, .clr_ofs = 0x44, - .sta_ofs = 0x40, + .sta_ofs = 0x48, }; #define GATE_INFRA(_id, _name, _parent, _shift) { \ @@ -1120,6 +1157,10 @@ static const struct mtk_gate peri_clks[] = { "msdc50_0_h_sel", 4), GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h", "msdc50_3_h_sel", 5), + GATE_PERI2(CLK_PERI_MSDC30_0_QTR_EN, "per_msdc30_0_q", + "axi_sel", 6), + GATE_PERI2(CLK_PERI_MSDC30_3_QTR_EN, "per_msdc30_3_q", + "mem_sel", 7), }; #define MT2712_PLL_FMAX (3000UL * MHZ) diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c index fad7d9fc53ba..4f3d47b41b3e 100644 --- a/drivers/clk/mediatek/clk-mt7622-aud.c +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -106,6 +106,7 @@ static const struct mtk_gate audio_clks[] = { GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), + GATE_AUDIO1(CLK_AUDIO_AFE_CONN, "audio_afe_conn", "a1sys_hp_sel", 23), /* AUDIO2 */ GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), @@ -149,11 +150,23 @@ static int clk_mt7622_audiosys_init(struct platform_device *pdev) clk_data); r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); - if (r) + if (r) { dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", pdev->name, r); + goto err_clk_provider; + } + + r = devm_of_platform_populate(&pdev->dev); + if (r) + goto err_plat_populate; + + return 0; + +err_plat_populate: + of_clk_del_provider(node); +err_clk_provider: return r; } |