diff options
| author | Stephen Boyd <sboyd@kernel.org> | 2026-08-13 17:42:25 -0700 |
|---|---|---|
| committer | Stephen Boyd <sboyd@kernel.org> | 2026-08-17 09:28:08 -0700 |
| commit | df822f2e36cf2c2864d166d90cf002df4d8689e5 (patch) | |
| tree | 7245d5de17dca83a30f98ff79a83879700abfbb7 /drivers | |
| parent | 804b10deb0e8872716416b38af0e4e60a038f0fd (diff) | |
| parent | cf561283254dd9f55805800237e6f82f08d91497 (diff) | |
Merge tag 'clk-misc-round-two-for-v7.3' of ssh://github.com/masneyb/linux into clk-pile
Pull clk patches from Brian Masney:
- New clock controller drivers for the Cix Sky1 audio subsystem (AUDSS),
UltraRISC DP1000, and MediaTek MT8173 MFG_TOP, along with their devicetree
bindings. Si549 support was added to the existing si544 driver.
- New clock and reset support for the Aspeed AST2700 PECI controller and Airoha
EN7523 PCIe PERSTOUT reset lines.
- The clk core gains devm_clk_bulk_get_enable() as the mandatory counterpart to
the existing optional variant, and exports
devm_clk_hw_register_composite_pdata() for modular drivers.
- Tegra gets a proper EMC clock implementation for Tegra114, 48MHz pll_p_out1
support needed for UEFI on Surface2, and the Xilinx clocking-wizard gains PLL
charge pump/lock parameter programming during dynamic reconfiguration.
- Bug fixes for a NULL pointer dereference from uninitialized clk_init_data in
the eswin driver, an IO remap leak in the MediaTek pllfh error path, inverted
gate control for MT8135 devapc_ck, a missing OF node put in tegra124-emc on
registration failure, a prepare reference leak in the palmas driver,
unregistered PLLs on MT6735 probe failure, a missing kasprintf NULL check in
pmc_atom, PCIe warm boot instability in the Airoha EN7523 driver, and a
clocking-wizard clock difference detection bug.
- Various cleanups across tegra, st, and mvebu providers to stop misusing the
consumer clock API, along with other minor fixes and improvements.
Signed-off-by: Brian Masney <bmasney@redhat.com>
* tag 'clk-misc-round-two-for-v7.3' of ssh://github.com/masneyb/linux: (45 commits)
clk: tegra: set up proper EMC clock implementation for Tegra114
clk: clocking-wizard: remove 20kHz restriction
clk: clocking-wizard: optimize clock search
clk: clocking-wizard: fix clock difference detection
clk: mediatek: mt8135: Fix inverted gate control for devapc_ck
clk: clocking-wizard: Program PLL CP/RES and lock parameters on reconfig
clk: tegra: support 48MHz clock for pll_p_out1
clk: aspeed: add AST2700 PECI clock
dt-bindings: clock: ast2700: add PECI clock
clk: mediatek: Add mt8173-mfgtop driver
dt-bindings: clock: mediatek: Add mt8173 mfgtop
clk: tegra: clean-up simple provider misuse of the consumer API
clk: st: clean-up simple provider misuse of the consumer API
clk: mvebu: clean-up simple provider misuse of the consumer API
clk: remove conditional return with no effect
clk: Add devm_clk_bulk_get_enable()
clk: en7523: add support for dedicated PCIe PERSTOUT reset
dt-bindings: clock: airoha: Add additional reset for PCIe PERSTOUT
arm64: dts: cix: sky1: add audss cru
reset: cix: add sky1 audss auxiliary reset driver
...
Diffstat (limited to 'drivers')
42 files changed, 2657 insertions, 146 deletions
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3d94c7611356..f9592fd9ec2b 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -155,12 +155,12 @@ config COMMON_CLK_SI514 generator. config COMMON_CLK_SI544 - tristate "Clock driver for SiLabs 544 devices" + tristate "Clock driver for SiLabs 544 and compatible devices" depends on I2C select REGMAP_I2C help - This driver supports the Silicon Labs 544 programmable clock - generator. + This driver supports the Silicon Labs 544/549 programmable clock + generators. config COMMON_CLK_SI570 tristate "Clock driver for SiLabs 570 and compatible devices" @@ -278,7 +278,7 @@ config COMMON_CLK_LAN966X tristate "Generic Clock Controller driver for LAN966X SoC" depends on HAS_IOMEM depends on OF - depends on SOC_LAN966 || ARCH_LAN969X || COMPILE_TEST + depends on SOC_LAN966 || ARCH_LAN969X || MCHP_LAN966X_PCI || COMPILE_TEST help This driver provides support for Generic Clock Controller(GCK) on LAN966X SoC. GCK generates and supplies clock to various peripherals @@ -509,6 +509,7 @@ source "drivers/clk/actions/Kconfig" source "drivers/clk/analogbits/Kconfig" source "drivers/clk/aspeed/Kconfig" source "drivers/clk/bcm/Kconfig" +source "drivers/clk/cix/Kconfig" source "drivers/clk/eswin/Kconfig" source "drivers/clk/hisilicon/Kconfig" source "drivers/clk/imgtec/Kconfig" @@ -541,6 +542,7 @@ source "drivers/clk/tenstorrent/Kconfig" source "drivers/clk/thead/Kconfig" source "drivers/clk/stm32/Kconfig" source "drivers/clk/ti/Kconfig" +source "drivers/clk/ultrarisc/Kconfig" source "drivers/clk/uniphier/Kconfig" source "drivers/clk/visconti/Kconfig" source "drivers/clk/x86/Kconfig" diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f9f669dff8a0..d61078cda465 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_ARCH_ARTPEC) += axis/ obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/ obj-y += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ +obj-y += cix/ obj-$(CONFIG_ARCH_DAVINCI) += davinci/ obj-$(CONFIG_COMMON_CLK_ESWIN) += eswin/ obj-$(CONFIG_COMMON_CLK_HISI) += hisilicon/ @@ -163,7 +164,7 @@ obj-y += spacemit/ obj-$(CONFIG_PLAT_SPEAR) += spear/ obj-y += sprd/ obj-$(CONFIG_ARCH_STI) += st/ -obj-$(CONFIG_ARCH_STM32) += stm32/ +obj-$(CONFIG_COMMON_CLK_STM32MP) += stm32/ obj-y += starfive/ obj-$(CONFIG_ARCH_SUNXI) += sunxi/ obj-y += sunxi-ng/ @@ -171,6 +172,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-y += tenstorrent/ obj-$(CONFIG_ARCH_THEAD) += thead/ obj-y += ti/ +obj-y += ultrarisc/ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/ obj-$(CONFIG_ARCH_U8500) += ux500/ obj-y += versatile/ diff --git a/drivers/clk/aspeed/clk-ast2700.c b/drivers/clk/aspeed/clk-ast2700.c index aa4dd7f24608..536600fcd024 100644 --- a/drivers/clk/aspeed/clk-ast2700.c +++ b/drivers/clk/aspeed/clk-ast2700.c @@ -272,6 +272,13 @@ static const unsigned int sdclk_parent_ids[] = { static const struct clk_hw *sdclk_parent_hws[ARRAY_SIZE(sdclk_parent_ids)]; +static const unsigned int peciclk_parent_ids[] = { + SCU1_CLKIN, + SCU1_CLK_HPLL_DIV4 +}; + +static const struct clk_hw *peciclk_parent_hws[ARRAY_SIZE(peciclk_parent_ids)]; + #define FIXED_CLK(_id, _name, _rate) \ { \ .id = _id, \ @@ -457,6 +464,7 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = { PLL_CLK(SCU1_CLK_HPLL, CLK_PLL, "soc1-hpll", SCU1_CLKIN, SCU1_HPLL_PARAM), PLL_CLK(SCU1_CLK_APLL, CLK_PLL, "soc1-apll", SCU1_CLKIN, SCU1_APLL_PARAM), PLL_CLK(SCU1_CLK_DPLL, CLK_PLL, "soc1-dpll", SCU1_CLKIN, SCU1_DPLL_PARAM), + FIXED_FACTOR_CLK(SCU1_CLK_HPLL_DIV4, "soc1-hpll_div4", SCU1_CLK_HPLL, 1, 4), FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV2, "soc1-apll_div2", SCU1_CLK_APLL, 1, 2), FIXED_FACTOR_CLK(SCU1_CLK_APLL_DIV4, "soc1-apll_div4", SCU1_CLK_APLL, 1, 4), FIXED_FACTOR_CLK(SCU1_CLK_CAN, "canclk", SCU1_CLK_APLL, 1, 10), @@ -480,6 +488,8 @@ static const struct ast2700_clk_info ast2700_scu1_clk_info[] __initconst = { uxclk_parent_hws, SCU1_CLK_SEL2, 0, 2), MUX_CLK(SCU1_CLK_HUXCLK, "huxclk", uxclk_parent_ids, ARRAY_SIZE(uxclk_parent_ids), uxclk_parent_hws, SCU1_CLK_SEL2, 3, 2), + MUX_CLK(SCU1_CLK_PECI, "peciclk", peciclk_parent_ids, ARRAY_SIZE(peciclk_parent_ids), + peciclk_parent_hws, SCU1_CLK_SEL2, 16, 1), DIVIDER_CLK(SCU1_CLK_SDCLK, "sdclk", SCU1_CLK_SDMUX, SCU1_CLK_SEL1, 14, 3, ast2700_clk_div_table), PLL_CLK(SCU1_CLK_UARTX, CLK_UART_PLL, "uartxclk", SCU1_CLK_UXCLK, SCU1_UXCLK_CTRL), diff --git a/drivers/clk/cix/Kconfig b/drivers/clk/cix/Kconfig new file mode 100644 index 000000000000..b057ef85fab6 --- /dev/null +++ b/drivers/clk/cix/Kconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: GPL-2.0 +# Audio subsystem clock support for Cixtech SoC family +menu "Cixtech Audio Subsystem Clock Driver" + +config CLK_SKY1_AUDSS + tristate "Cixtech Sky1 Audio Subsystem Clock Driver" + depends on ARCH_CIX || COMPILE_TEST + select AUXILIARY_BUS + select REGMAP_MMIO + select RESET_CONTROLLER + help + Support for the Audio Subsystem clock controller present on + Cixtech Sky1 SoC. This driver provides mux, divider and gate + clocks for DSP, I2S, HDA and related blocks in the audio + subsystem. Say M or Y here if you want to build this driver. +endmenu diff --git a/drivers/clk/cix/Makefile b/drivers/clk/cix/Makefile new file mode 100644 index 000000000000..bc612f1d08b2 --- /dev/null +++ b/drivers/clk/cix/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_CLK_SKY1_AUDSS) += clk-sky1-audss.o diff --git a/drivers/clk/cix/clk-sky1-audss.c b/drivers/clk/cix/clk-sky1-audss.c new file mode 100644 index 000000000000..e096b8121df3 --- /dev/null +++ b/drivers/clk/cix/clk-sky1-audss.c @@ -0,0 +1,1206 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Copyright 2026 Cix Technology Group Co., Ltd. + +#include <linux/auxiliary_bus.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/regmap.h> +#include <linux/reset.h> + +#include <dt-bindings/clock/cix,sky1-audss-cru.h> + +#define INFO_HIFI0 0x00 +#define INFO_CLK_GATE 0x10 +#define INFO_CLK_DIV 0x14 +#define INFO_CLK_MUX 0x18 +#define INFO_MCLK 0x70 + +#define SKY1_AUDSS_CLK_PARENTS_CNT 4 +#define SKY1_AUDSS_NUM_CLKS (CLK_MCLK4 + 1) + +static u32 sky1_reg_save[][2] = { + { INFO_HIFI0, 0 }, + { INFO_CLK_GATE, 0 }, + { INFO_CLK_DIV, 0 }, + { INFO_CLK_MUX, 0 }, + { INFO_MCLK, 0 }, +}; + +static const char * const sky1_audss_clk_names[SKY1_AUDSS_CLK_PARENTS_CNT] = { + "x8k", "x11k", "sys", "48m", +}; + +static const u32 sky1_clk_rate_default[SKY1_AUDSS_CLK_PARENTS_CNT] = { + 294912000, + 270950400, + 800000000, + 48000000, +}; + +static const char * const dsp_clk_parent[] = { + "audio_clk4" +}; + +static const char * const dsp_bclk_parent[] = { + "audio_clk4_div2" +}; + +static const char * const dsp_pbclk_parent[] = { + "audio_clk4_div4" +}; + +static const char * const sram_axi_parent[] = { + "audio_clk4_div2" +}; + +static const char * const hda_sys_parent[] = { + "audio_clk4_div2" +}; + +static const char * const hda_hda_parent[] = { + "audio_clk5" +}; + +static const char * const dmac_axi_parent[] = { + "audio_clk4_div2" +}; + +static const char * const wdg_apb_parent[] = { + "audio_clk5_div2" +}; + +static const char * const wdg_wdg_parent[] = { + "audio_clk5_div2" +}; + +static const char * const timer_apb_parent[] = { + "audio_clk4_div4" +}; + +static const char * const timer_timer_parent[] = { + "audio_clk5_div2" +}; + +static const char * const mailbox_apb_parent[] = { + "audio_clk4_div4" +}; + +static const char * const i2s_apb_parent[] = { + "audio_clk4_div4" +}; + +static const char * const i2s0_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s1_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s2_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s3_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s4_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s5_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s6_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s7_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s8_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const i2s9_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const char * const mclk_parents[] = { + "audio_clk0", "audio_clk2" +}; + +static const u32 i2s3_mux_table[] = { 0, 2 }; +static const u32 i2s4_mux_table[] = { 0, 2 }; + +/* + * audss composite clock definition + */ +struct muxdiv_cfg { + int offset; + u8 shift; + u8 width; + u8 flags; +}; + +struct gate_cfg { + int offset; + u8 shift; + u8 flags; +}; + +struct composite_clk_cfg { + u32 id; + const char * const name; + const char * const *parent_names; + int num_parents; + const u32 *mux_table; + struct muxdiv_cfg *mux_cfg; + struct muxdiv_cfg *div_cfg; + struct gate_cfg *gate_cfg; + unsigned long flags; +}; + +#define CFG(_id,\ + _name,\ + _parent_names,\ + _mux_table,\ + _mux_offset, _mux_shift, _mux_width, _mux_flags,\ + _div_offset, _div_shift, _div_width, _div_flags,\ + _gate_offset, _gate_shift, _gate_flags,\ + _flags)\ +{\ + .id = _id,\ + .name = _name,\ + .parent_names = _parent_names,\ + .num_parents = ARRAY_SIZE(_parent_names),\ + .mux_table = _mux_table,\ + .mux_cfg = &(struct muxdiv_cfg) { _mux_offset, _mux_shift, _mux_width, _mux_flags },\ + .div_cfg = &(struct muxdiv_cfg) { _div_offset, _div_shift, _div_width, _div_flags },\ + .gate_cfg = &(struct gate_cfg) { _gate_offset, _gate_shift, _gate_flags },\ + .flags = _flags,\ +} + +static const struct composite_clk_cfg sky1_audss_clks[] = { + /* dsp */ + CFG(CLK_DSP_CLK, + "audss_dsp_clk", + dsp_clk_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_HIFI0, 0, 0, + 0), + CFG(CLK_DSP_BCLK, + "audss_dsp_bclk", + dsp_bclk_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + -1, 0, 0, + 0), + CFG(CLK_DSP_PBCLK, + "audss_dsp_pbclk", + dsp_pbclk_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + -1, 0, 0, + 0), + /* sram */ + CFG(CLK_SRAM_AXI, + "audss_sram_axi", + sram_axi_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 16, 0, + 0), + /* hda */ + CFG(CLK_HDA_SYS, + "audss_hda_sys", + hda_sys_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 14, 0, + 0), + CFG(CLK_HDA_HDA, + "audss_hda_hda", + hda_hda_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 14, 0, + 0), + /* dmac */ + CFG(CLK_DMAC_AXI, + "audss_dmac_axi", + dmac_axi_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 15, 0, + 0), + /* wdg */ + CFG(CLK_WDG_APB, + "audss_wdg_apb", + wdg_apb_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 10, 0, + 0), + CFG(CLK_WDG_WDG, + "audss_wdg_wdg", + wdg_wdg_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 10, 0, + 0), + /* timer */ + CFG(CLK_TIMER_APB, + "audss_timer_apb", + timer_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 11, 0, + 0), + CFG(CLK_TIMER_TIMER, + "audss_timer_timer", + timer_timer_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 11, 0, + 0), + /* mailbox: mb0(ap->dsp), mb1(dsp->ap) */ + CFG(CLK_MB_0_APB, + "audss_mb_0_apb", + mailbox_apb_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 12, 0, + 0), + CFG(CLK_MB_1_APB, + "audss_mb_1_apb", + mailbox_apb_parent, + NULL, + -1, 0, 0, 0, + -1, 0, 0, 0, + INFO_CLK_GATE, 13, 0, + 0), + /* i2s */ + CFG(CLK_I2S0_APB, + "audss_i2s0_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 0, 0, + 0), + CFG(CLK_I2S1_APB, + "audss_i2s1_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 1, 0, + 0), + CFG(CLK_I2S2_APB, + "audss_i2s2_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 2, 0, + 0), + CFG(CLK_I2S3_APB, + "audss_i2s3_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 3, 0, + 0), + CFG(CLK_I2S4_APB, + "audss_i2s4_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 4, 0, + 0), + CFG(CLK_I2S5_APB, + "audss_i2s5_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 5, 0, + 0), + CFG(CLK_I2S6_APB, + "audss_i2s6_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 6, 0, + 0), + CFG(CLK_I2S7_APB, + "audss_i2s7_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 7, 0, + 0), + CFG(CLK_I2S8_APB, + "audss_i2s8_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 8, 0, + 0), + CFG(CLK_I2S9_APB, + "audss_i2s9_apb", + i2s_apb_parent, + NULL, + -1, 0, 0, 0, + INFO_CLK_DIV, 0, 2, 0, + INFO_CLK_GATE, 9, 0, + 0), + CFG(CLK_I2S0, + "audss_i2s0", + i2s0_parents, + NULL, + INFO_CLK_MUX, 0, 2, 0, + INFO_CLK_DIV, 2, 2, 0, + INFO_CLK_GATE, 0, 0, + 0), + CFG(CLK_I2S1, + "audss_i2s1", + i2s1_parents, + NULL, + INFO_CLK_MUX, 2, 2, 0, + INFO_CLK_DIV, 4, 2, 0, + INFO_CLK_GATE, 1, 0, + 0), + CFG(CLK_I2S2, + "audss_i2s2", + i2s2_parents, + NULL, + INFO_CLK_MUX, 4, 2, 0, + INFO_CLK_DIV, 6, 2, 0, + INFO_CLK_GATE, 2, 0, + 0), + CFG(CLK_I2S3, + "audss_i2s3", + i2s3_parents, + i2s3_mux_table, + INFO_CLK_MUX, 6, 2, 0, + INFO_CLK_DIV, 8, 2, 0, + INFO_CLK_GATE, 3, 0, + 0), + CFG(CLK_I2S4, + "audss_i2s4", + i2s4_parents, + i2s4_mux_table, + INFO_CLK_MUX, 8, 2, 0, + INFO_CLK_DIV, 10, 2, 0, + INFO_CLK_GATE, 4, 0, + 0), + CFG(CLK_I2S5, + "audss_i2s5", + i2s5_parents, + NULL, + INFO_CLK_MUX, 10, 2, 0, + INFO_CLK_DIV, 12, 2, 0, + INFO_CLK_GATE, 5, 0, + 0), + CFG(CLK_I2S6, + "audss_i2s6", + i2s6_parents, + NULL, + INFO_CLK_MUX, 12, 2, 0, + INFO_CLK_DIV, 14, 2, 0, + INFO_CLK_GATE, 6, 0, + 0), + CFG(CLK_I2S7, + "audss_i2s7", + i2s7_parents, + NULL, + INFO_CLK_MUX, 14, 2, 0, + INFO_CLK_DIV, 16, 2, 0, + INFO_CLK_GATE, 7, 0, + 0), + CFG(CLK_I2S8, + "audss_i2s8", + i2s8_parents, + NULL, + INFO_CLK_MUX, 16, 2, 0, + INFO_CLK_DIV, 18, 2, 0, + INFO_CLK_GATE, 8, 0, + 0), + CFG(CLK_I2S9, + "audss_i2s9", + i2s9_parents, + NULL, + INFO_CLK_MUX, 18, 2, 0, + INFO_CLK_DIV, 20, 2, 0, + INFO_CLK_GATE, 9, 0, + 0), + /* mclk */ + CFG(CLK_MCLK0, + "audss_mclk0", + mclk_parents, + NULL, + INFO_MCLK, 5, 1, 0, + -1, 0, 0, 0, + INFO_MCLK, 0, 0, + 0), + CFG(CLK_MCLK1, + "audss_mclk1", + mclk_parents, + NULL, + INFO_MCLK, 6, 1, 0, + -1, 0, 0, 0, + INFO_MCLK, 1, 0, + 0), + CFG(CLK_MCLK2, + "audss_mclk2", + mclk_parents, + NULL, + INFO_MCLK, 7, 1, 0, + -1, 0, 0, 0, + INFO_MCLK, 2, 0, + 0), + CFG(CLK_MCLK3, + "audss_mclk3", + mclk_parents, + NULL, + INFO_MCLK, 8, 1, 0, + -1, 0, 0, 0, + INFO_MCLK, 3, 0, + 0), + CFG(CLK_MCLK4, + "audss_mclk4", + mclk_parents, + NULL, + INFO_MCLK, 9, 1, 0, + -1, 0, 0, 0, + INFO_MCLK, 4, 0, + 0), +}; + +struct sky1_audss_clks_devtype_data { + u32 (*reg_save)[2]; + size_t reg_save_size; + const char * const *clk_names; + size_t clk_num; + const u32 *clk_rate_default; + const struct composite_clk_cfg *clk_cfg; + size_t clk_cfg_size; +}; + +static const struct regmap_config sky1_audss_regmap_config = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +struct sky1_audss_clks_priv { + struct device *dev; + struct regmap *regmap_cru; + struct reset_control *rst_noc; + struct clk *clks[SKY1_AUDSS_CLK_PARENTS_CNT]; + const struct sky1_audss_clks_devtype_data *devtype_data; + spinlock_t lock; + struct clk_hw_onecell_data *clk_data; +}; + +#if IS_ENABLED(CONFIG_RESET_SKY1_AUDSS) + +static int sky1_audss_reset_controller_register(struct device *dev) +{ + struct auxiliary_device *adev; + + if (!of_property_present(dev->of_node, "#reset-cells")) + return 0; + + adev = devm_auxiliary_device_create(dev, "reset", NULL); + if (!adev) + return -ENODEV; + + return 0; +} + +#else + +static int sky1_audss_reset_controller_register(struct device *dev) +{ + return 0; +} + +#endif + +/* + * clk_ops for audss clock mux/divider/gate + */ +struct sky1_clk_divider { + struct clk_divider div; + struct regmap *regmap; + int offset; +}; + +struct sky1_clk_gate { + struct clk_gate gate; + struct regmap *regmap; + int offset; +}; + +struct sky1_clk_mux { + struct clk_mux mux; + struct regmap *regmap; + int offset; +}; + +static inline struct sky1_clk_mux *to_sky1_clk_mux(struct clk_mux *mux) +{ + return container_of(mux, struct sky1_clk_mux, mux); +} + +static u8 sky1_audss_clk_mux_get_parent(struct clk_hw *hw) +{ + struct clk_mux *mux = to_clk_mux(hw); + struct sky1_clk_mux *sky1_mux = to_sky1_clk_mux(mux); + u32 val; + + regmap_read(sky1_mux->regmap, sky1_mux->offset, &val); + val = val >> mux->shift; + val &= mux->mask; + + return clk_mux_val_to_index(hw, mux->table, mux->flags, val); +} + +static int sky1_audss_clk_mux_set_parent(struct clk_hw *hw, u8 index) +{ + struct clk_mux *mux = to_clk_mux(hw); + u32 val = clk_mux_index_to_val(mux->table, mux->flags, index); + struct sky1_clk_mux *sky1_mux = to_sky1_clk_mux(mux); + unsigned long flags = 0; + u32 reg; + + if (mux->lock) + spin_lock_irqsave(mux->lock, flags); + else + __acquire(mux->lock); + + if (mux->flags & CLK_MUX_HIWORD_MASK) { + reg = mux->mask << (mux->shift + 16); + } else { + regmap_read(sky1_mux->regmap, sky1_mux->offset, ®); + reg &= ~(mux->mask << mux->shift); + } + val = val << mux->shift; + reg |= val; + regmap_write(sky1_mux->regmap, sky1_mux->offset, reg); + + if (mux->lock) + spin_unlock_irqrestore(mux->lock, flags); + else + __release(mux->lock); + + return 0; +} + +static int sky1_audss_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct clk_mux *mux = to_clk_mux(hw); + + return clk_mux_determine_rate_flags(hw, req, mux->flags); +} + +static const struct clk_ops sky1_audss_clk_mux_ops = { + .get_parent = sky1_audss_clk_mux_get_parent, + .set_parent = sky1_audss_clk_mux_set_parent, + .determine_rate = sky1_audss_clk_mux_determine_rate, +}; + +static inline struct sky1_clk_divider *to_sky1_clk_divider(struct clk_divider *div) +{ + return container_of(div, struct sky1_clk_divider, div); |
