* [PATCH v13 0/6] add Amlogic A1 clock controller drivers @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. The audio clock controller is different from others, but the rest are very similar from a functional and regmap point of view. This patch series add support for Amlogic A1 PLL and Peripherals clock drivers. It blocks all A1 peripherals mainline support and a couple of patch series, which were already reviewed and acked, but weren't merged due to pending clock controller drivers series, e.g. https://lore.kernel.org/linux-amlogic/7hd09cw9oh.fsf@baylibre.com/ TODO: CPU and Audio clock controllers are not included in this patch series, it will be sent later. The following clks from these controllers are not supported for now: * Audio clks - vad, mclk_vad, mclk_d, resample_a, locker_in, mclk_b, pdmdclk, pdmsysclk, eqdrc, spdifin, mclk_a, audio2_toaudiotop, audio2_tovad, audio2_toddr_vad, audio2_tdmin_vad, audio2_pdm, audio2_ddr_arb, audio_audiolocker, audio_eqdrc, audio_resamplea, audio_spdifin, audio_toddrb, audio_toddra, audio_frddrb, audio_frddra, audio_tdmoutb, audio_tdmouta, audio_loopbacka, audio_tdminlb, audio_tdminb, audio_tdmina, audio_ddr_arb, mclk_c * CPU clks: cpu_fixed_source_sel0, cpu_fixed_source_div0, cpu_fixed_source_sel1, cpu_fixed_source_div1, cpu_clk Validation: * to double check all clk flags run below helper script: pushd /sys/kernel/debug/clk for f in *; do if [[ -f "$f/clk_flags" ]]; then flags="$(cat $f/clk_flags | awk '{$1=$1};1' | sed ':a;N;$!ba;s/\n/ | /g')" echo -e "$f: $flags" fi done popd * to trace current clks state use '/sys/kernel/debug/clk/clk_dump' node with jq post-processing: $ cat /sys/kernel/debug/clk/clk_dump | jq '.' > clk_dump.json * to debug clk rate propagation, compile kernel with the following definition: $ sed -i "s/undef CLOCK_ALLOW_WRITE_DEBUGFS/define CLOCK_ALLOW_WRITE_DEBUGFS/g" drivers/clk/clk.c after that, clk_rate debug node for each clock will be available for write operation Changes v13 since v12 at [13]: - make the clock object registration order from the roots to the leaves - rearrange the clkids following above rule Changes v12 since v11 at [12]: - split the DT bindings patchset into two patches: one for the PLL clock controller driver, and one for the peripherals clock controller driver - to satisfy the DT binding checker, use fake references to the peripherals clock controller in the PLL DT bindings schema, and then replace them with real references when the peripherals bindings become available. - remove the public/private clocks concept from both controllers, and instead use a linear clkid list with both exposed and internal objects, all of which are registered in the clock provider - combine all comments about RTC children with the flag 'CLK_SET_RATE_NO_REPARENT' into a single item with multiple references to it Changes v11 since v10 at [11]: - change include/dt-bindings license to proper value required for bindings files: 'GPL-2.0-only OR BSD-2-Clause' - pll and peripherals clocks are split into public and private parts; public clocks are available for external consumers through the DT layer, private clocks include internal muxes and dividers of composite clocks, they are placed inside clock controller driver without external access - make public clks CLKID bindings continuous - mark the following clock muxes as NO_REPARENT and add them to public clocks list: GEN_SEL, DSPA_A_SEL, DSPA_B_SEL, DSPB_A_SEL, DSP_B_B_SEL, PWM_A_SEL, PWM_B_SEL, PWM_C_SEL, PWM_D_SEL, PWM_E_SEL, PWM_F_SEL, CECA_32K_SEL, CECB_32K_SEL; each of them can be inherited from more accurate RTC clock and sometimes it's required to forbid reparenting in such situation; also GEN_SEL can be connected to external PAD and should not change parent automatically due to rate propagation. For such clocks user must setup parents on the DT side Changes v10 since v9 at [10]: - split general clk-pll changes into two different patchsets: optional rst usage and new power sequence - squash dt bindings patchsets to avoid chicken-or-the-egg problem during run dt binding check routines - add vendor prefix to PLL and Peripherals clkcs bindings filenames - clear managed hifi_pll fields from initial poke table - move DSPA_SEL, DSPB_SEL and SARADC_SEL to private clkid table, because it should not be opened for direct usage - pwm_a clk used for voltage regulation is not critical anymore, it must be included to the proper cpu voltage regulation setup (will be available in the next patch series) - as discussed with Jerome, dspX clks are simple clocks and it should be enabled/disabled/ignored/anything else from appropriate DSP driver, so remove CLK_IGNORE_UNUSED tags - provide more understandable comments and remove irrelevant (I hope so) - remove CONFIG_OF usage, because it's redundant - fix license issue, it's GPL-2.0+ only in the current version - some commit msgs rewording Changes v9 since v8 at [9]: - remove common a1-clkc driver for the first version of a1 clock controllers as Jerome suggested (it will be discussed after s4 and a1 clks landed, hope so) - replace inherited a1-pll clk_pll_ops with common ops and introduce custom A1 PLL logic under MESON_PARM_APPLICABLE() conditions - rename xtal depended clocks in PLL and Peripherals domains - remove 'a1_' prefix for all clocks, because they are already inside A1 driver, it's redundant - change udelay() to usleep_range() as preferred for small msec amount - purge all double quotes from the yaml schemas - use proper dt node names following kernel guidelines https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation - use devm_platform_ioremap_resource() instead of simple devm_ioremap_resource() - mark all dspX clocks as CLK_IGNORE_UNUSED, because we do not want to touch these clocks during CCF initialization due to possible workload execution on it started from bootloader; in this case bootloader already made all initialization stuff for dspX - also mark all dspX with NO_REPARENT tag, because from dspX clocks we want to select proper clk source from device tree Changes v8 since v7 at [8]: - introduced a1-clkc common driver for all A1 clock controllers - exported meson_clk_pll_wait_lock symbol - supported meson-a1-clkc common driver in the a1-pll and a1 clkc - inherited a1-pll from the base clk-pll driver, implemented own version of init/enable/disable/enabled routines; rate calculating logic is fully the same - aligned CLKID-related definitions with CLKID list from order perspective to remove holes and permutations - corrected Kconfig dependencies and types - provided correct MODULE_AUTHORs() - optimized and fixed up some clock relationships - removed unused register offset definitions - fixed up A1 PLL and Peripherals clkc dtb_check errors - fixed clk_summary kernel panic due to missing a1_pad_ctrl clk_regmap definition - included PLL and Peripherals clk controllers to the base a1 dts - The previous v7 version [8] had several logic and style problems, all of them are resolved in this version. Original Jian Hu v7 patches are not touched, and all additional fixes are implemented in separate patches. Patch "clk: meson: add support for A1 PLL clock ops" is removed, because a1-pll clk driver inherits all stuff from clk-pll base driver, just implements custom init/enable/disable/is_enabled callbacks. Changes v7 since v6 at [7]: - fix 'dt_binding_check' compiling error - add acked-by Changes v6 since v5 at [6]: - fix yaml file - add rst/current_en/l_detect parm detection - remove 'meson_eeclkc_data' in a1.c and a1-pll.c Changes v5 since v4 at [5]: - change yaml GPL - drop meson-eeclk.c patch, add probe function in each driver - add CLK_IS_CRITICAL for sys_clk clock, drop the flag for sys_a and sys_b - add new parm for pll, add protection for rst parm - drop flag for a1_fixed_pll - remove the same comment for fclk_div, add "refer to" - add critical flag for a1_sys_clk - remove rtc table - rename a1_dspa_en_dspa and a1_dspb_en_dspb - remove useless comment Changes v4 since v3 at [3]: - fix reparenting orphan failed, it depends on jerome's patch [4] - fix changelist in v3 about reparenting orphan - remove the dts patch Changes v3 since v2 at [2]: - add probe function for A1 - separate the clock driver into two patch - change some clock flags and ops - add support for a1 PLL ops - add A1 clock node - fix reparenting orphan clock failed, registering xtal_fixpll and xtal_hifipll after the provider registration, it is not a best way. Changes v2 since v1 at [1]: - place A1 config alphabetically - add actual reason for RO ops, CLK_IS_CRITICAL, CLK_IGNORE_UNUSED - separate the driver into two driver: peripheral and pll driver - delete CLK_IGNORE_UNUSED flag for pwm b/c/d/e/f clock, dsp clock - delete the change in Kconfig.platforms, address to Kevin alone - remove the useless comments - modify the meson pll driver to support A1 PLLs Links: [1] https://lkml.kernel.org/r/1569411888-98116-1-git-send-email-jian.hu@amlogic.com [2] https://lkml.kernel.org/r/1571382865-41978-1-git-send-email-jian.hu@amlogic.com [3] https://lkml.kernel.org/r/20191129144605.182774-1-jian.hu@amlogic.com [4] https://lkml.kernel.org/r/20191203080805.104628-1-jbrunet@baylibre.com [5] https://lkml.kernel.org/r/20191206074052.15557-1-jian.hu@amlogic.com [6] https://lkml.kernel.org/r/20191227094606.143637-1-jian.hu@amlogic.com [7] https://lkml.kernel.org/r/20200116080440.118679-1-jian.hu@amlogic.com [8] https://lore.kernel.org/linux-amlogic/20200120034937.128600-1-jian.hu@amlogic.com/ [9] https://lore.kernel.org/linux-amlogic/20221201225703.6507-1-ddrokosov@sberdevices.ru/ [10] https://lore.kernel.org/all/20230301183759.16163-1-ddrokosov@sberdevices.ru/ [11] https://lore.kernel.org/all/20230313201259.19998-1-ddrokosov@sberdevices.ru/ [12] https://lore.kernel.org/all/20230321193014.26349-1-ddrokosov@sberdevices.ru/ [13] https://lore.kernel.org/all/20230404155332.9571-1-ddrokosov@sberdevices.ru/ Dmitry Rokosov (6): clk: meson: make pll rst bit as optional clk: meson: introduce new pll power-on sequence for A1 SoC family dt-bindings: clock: meson: add A1 PLL clock controller bindings clk: meson: a1: add Amlogic A1 PLL clock controller driver dt-bindings: clock: meson: add A1 Peripherals clock controller bindings clk: meson: a1: add Amlogic A1 Peripherals clock controller driver .../bindings/clock/amlogic,a1-clkc.yaml | 73 + .../bindings/clock/amlogic,a1-pll-clkc.yaml | 59 + MAINTAINERS | 1 + drivers/clk/meson/Kconfig | 20 + drivers/clk/meson/Makefile | 2 + drivers/clk/meson/a1-pll.c | 356 +++ drivers/clk/meson/a1-pll.h | 47 + drivers/clk/meson/a1.c | 2273 +++++++++++++++++ drivers/clk/meson/a1.h | 114 + drivers/clk/meson/clk-pll.c | 47 +- drivers/clk/meson/clk-pll.h | 2 + include/dt-bindings/clock/amlogic,a1-clkc.h | 114 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 + 13 files changed, 3121 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h -- 2.36.0 ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 0/6] add Amlogic A1 clock controller drivers @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. The audio clock controller is different from others, but the rest are very similar from a functional and regmap point of view. This patch series add support for Amlogic A1 PLL and Peripherals clock drivers. It blocks all A1 peripherals mainline support and a couple of patch series, which were already reviewed and acked, but weren't merged due to pending clock controller drivers series, e.g. https://lore.kernel.org/linux-amlogic/7hd09cw9oh.fsf@baylibre.com/ TODO: CPU and Audio clock controllers are not included in this patch series, it will be sent later. The following clks from these controllers are not supported for now: * Audio clks - vad, mclk_vad, mclk_d, resample_a, locker_in, mclk_b, pdmdclk, pdmsysclk, eqdrc, spdifin, mclk_a, audio2_toaudiotop, audio2_tovad, audio2_toddr_vad, audio2_tdmin_vad, audio2_pdm, audio2_ddr_arb, audio_audiolocker, audio_eqdrc, audio_resamplea, audio_spdifin, audio_toddrb, audio_toddra, audio_frddrb, audio_frddra, audio_tdmoutb, audio_tdmouta, audio_loopbacka, audio_tdminlb, audio_tdminb, audio_tdmina, audio_ddr_arb, mclk_c * CPU clks: cpu_fixed_source_sel0, cpu_fixed_source_div0, cpu_fixed_source_sel1, cpu_fixed_source_div1, cpu_clk Validation: * to double check all clk flags run below helper script: pushd /sys/kernel/debug/clk for f in *; do if [[ -f "$f/clk_flags" ]]; then flags="$(cat $f/clk_flags | awk '{$1=$1};1' | sed ':a;N;$!ba;s/\n/ | /g')" echo -e "$f: $flags" fi done popd * to trace current clks state use '/sys/kernel/debug/clk/clk_dump' node with jq post-processing: $ cat /sys/kernel/debug/clk/clk_dump | jq '.' > clk_dump.json * to debug clk rate propagation, compile kernel with the following definition: $ sed -i "s/undef CLOCK_ALLOW_WRITE_DEBUGFS/define CLOCK_ALLOW_WRITE_DEBUGFS/g" drivers/clk/clk.c after that, clk_rate debug node for each clock will be available for write operation Changes v13 since v12 at [13]: - make the clock object registration order from the roots to the leaves - rearrange the clkids following above rule Changes v12 since v11 at [12]: - split the DT bindings patchset into two patches: one for the PLL clock controller driver, and one for the peripherals clock controller driver - to satisfy the DT binding checker, use fake references to the peripherals clock controller in the PLL DT bindings schema, and then replace them with real references when the peripherals bindings become available. - remove the public/private clocks concept from both controllers, and instead use a linear clkid list with both exposed and internal objects, all of which are registered in the clock provider - combine all comments about RTC children with the flag 'CLK_SET_RATE_NO_REPARENT' into a single item with multiple references to it Changes v11 since v10 at [11]: - change include/dt-bindings license to proper value required for bindings files: 'GPL-2.0-only OR BSD-2-Clause' - pll and peripherals clocks are split into public and private parts; public clocks are available for external consumers through the DT layer, private clocks include internal muxes and dividers of composite clocks, they are placed inside clock controller driver without external access - make public clks CLKID bindings continuous - mark the following clock muxes as NO_REPARENT and add them to public clocks list: GEN_SEL, DSPA_A_SEL, DSPA_B_SEL, DSPB_A_SEL, DSP_B_B_SEL, PWM_A_SEL, PWM_B_SEL, PWM_C_SEL, PWM_D_SEL, PWM_E_SEL, PWM_F_SEL, CECA_32K_SEL, CECB_32K_SEL; each of them can be inherited from more accurate RTC clock and sometimes it's required to forbid reparenting in such situation; also GEN_SEL can be connected to external PAD and should not change parent automatically due to rate propagation. For such clocks user must setup parents on the DT side Changes v10 since v9 at [10]: - split general clk-pll changes into two different patchsets: optional rst usage and new power sequence - squash dt bindings patchsets to avoid chicken-or-the-egg problem during run dt binding check routines - add vendor prefix to PLL and Peripherals clkcs bindings filenames - clear managed hifi_pll fields from initial poke table - move DSPA_SEL, DSPB_SEL and SARADC_SEL to private clkid table, because it should not be opened for direct usage - pwm_a clk used for voltage regulation is not critical anymore, it must be included to the proper cpu voltage regulation setup (will be available in the next patch series) - as discussed with Jerome, dspX clks are simple clocks and it should be enabled/disabled/ignored/anything else from appropriate DSP driver, so remove CLK_IGNORE_UNUSED tags - provide more understandable comments and remove irrelevant (I hope so) - remove CONFIG_OF usage, because it's redundant - fix license issue, it's GPL-2.0+ only in the current version - some commit msgs rewording Changes v9 since v8 at [9]: - remove common a1-clkc driver for the first version of a1 clock controllers as Jerome suggested (it will be discussed after s4 and a1 clks landed, hope so) - replace inherited a1-pll clk_pll_ops with common ops and introduce custom A1 PLL logic under MESON_PARM_APPLICABLE() conditions - rename xtal depended clocks in PLL and Peripherals domains - remove 'a1_' prefix for all clocks, because they are already inside A1 driver, it's redundant - change udelay() to usleep_range() as preferred for small msec amount - purge all double quotes from the yaml schemas - use proper dt node names following kernel guidelines https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation - use devm_platform_ioremap_resource() instead of simple devm_ioremap_resource() - mark all dspX clocks as CLK_IGNORE_UNUSED, because we do not want to touch these clocks during CCF initialization due to possible workload execution on it started from bootloader; in this case bootloader already made all initialization stuff for dspX - also mark all dspX with NO_REPARENT tag, because from dspX clocks we want to select proper clk source from device tree Changes v8 since v7 at [8]: - introduced a1-clkc common driver for all A1 clock controllers - exported meson_clk_pll_wait_lock symbol - supported meson-a1-clkc common driver in the a1-pll and a1 clkc - inherited a1-pll from the base clk-pll driver, implemented own version of init/enable/disable/enabled routines; rate calculating logic is fully the same - aligned CLKID-related definitions with CLKID list from order perspective to remove holes and permutations - corrected Kconfig dependencies and types - provided correct MODULE_AUTHORs() - optimized and fixed up some clock relationships - removed unused register offset definitions - fixed up A1 PLL and Peripherals clkc dtb_check errors - fixed clk_summary kernel panic due to missing a1_pad_ctrl clk_regmap definition - included PLL and Peripherals clk controllers to the base a1 dts - The previous v7 version [8] had several logic and style problems, all of them are resolved in this version. Original Jian Hu v7 patches are not touched, and all additional fixes are implemented in separate patches. Patch "clk: meson: add support for A1 PLL clock ops" is removed, because a1-pll clk driver inherits all stuff from clk-pll base driver, just implements custom init/enable/disable/is_enabled callbacks. Changes v7 since v6 at [7]: - fix 'dt_binding_check' compiling error - add acked-by Changes v6 since v5 at [6]: - fix yaml file - add rst/current_en/l_detect parm detection - remove 'meson_eeclkc_data' in a1.c and a1-pll.c Changes v5 since v4 at [5]: - change yaml GPL - drop meson-eeclk.c patch, add probe function in each driver - add CLK_IS_CRITICAL for sys_clk clock, drop the flag for sys_a and sys_b - add new parm for pll, add protection for rst parm - drop flag for a1_fixed_pll - remove the same comment for fclk_div, add "refer to" - add critical flag for a1_sys_clk - remove rtc table - rename a1_dspa_en_dspa and a1_dspb_en_dspb - remove useless comment Changes v4 since v3 at [3]: - fix reparenting orphan failed, it depends on jerome's patch [4] - fix changelist in v3 about reparenting orphan - remove the dts patch Changes v3 since v2 at [2]: - add probe function for A1 - separate the clock driver into two patch - change some clock flags and ops - add support for a1 PLL ops - add A1 clock node - fix reparenting orphan clock failed, registering xtal_fixpll and xtal_hifipll after the provider registration, it is not a best way. Changes v2 since v1 at [1]: - place A1 config alphabetically - add actual reason for RO ops, CLK_IS_CRITICAL, CLK_IGNORE_UNUSED - separate the driver into two driver: peripheral and pll driver - delete CLK_IGNORE_UNUSED flag for pwm b/c/d/e/f clock, dsp clock - delete the change in Kconfig.platforms, address to Kevin alone - remove the useless comments - modify the meson pll driver to support A1 PLLs Links: [1] https://lkml.kernel.org/r/1569411888-98116-1-git-send-email-jian.hu@amlogic.com [2] https://lkml.kernel.org/r/1571382865-41978-1-git-send-email-jian.hu@amlogic.com [3] https://lkml.kernel.org/r/20191129144605.182774-1-jian.hu@amlogic.com [4] https://lkml.kernel.org/r/20191203080805.104628-1-jbrunet@baylibre.com [5] https://lkml.kernel.org/r/20191206074052.15557-1-jian.hu@amlogic.com [6] https://lkml.kernel.org/r/20191227094606.143637-1-jian.hu@amlogic.com [7] https://lkml.kernel.org/r/20200116080440.118679-1-jian.hu@amlogic.com [8] https://lore.kernel.org/linux-amlogic/20200120034937.128600-1-jian.hu@amlogic.com/ [9] https://lore.kernel.org/linux-amlogic/20221201225703.6507-1-ddrokosov@sberdevices.ru/ [10] https://lore.kernel.org/all/20230301183759.16163-1-ddrokosov@sberdevices.ru/ [11] https://lore.kernel.org/all/20230313201259.19998-1-ddrokosov@sberdevices.ru/ [12] https://lore.kernel.org/all/20230321193014.26349-1-ddrokosov@sberdevices.ru/ [13] https://lore.kernel.org/all/20230404155332.9571-1-ddrokosov@sberdevices.ru/ Dmitry Rokosov (6): clk: meson: make pll rst bit as optional clk: meson: introduce new pll power-on sequence for A1 SoC family dt-bindings: clock: meson: add A1 PLL clock controller bindings clk: meson: a1: add Amlogic A1 PLL clock controller driver dt-bindings: clock: meson: add A1 Peripherals clock controller bindings clk: meson: a1: add Amlogic A1 Peripherals clock controller driver .../bindings/clock/amlogic,a1-clkc.yaml | 73 + .../bindings/clock/amlogic,a1-pll-clkc.yaml | 59 + MAINTAINERS | 1 + drivers/clk/meson/Kconfig | 20 + drivers/clk/meson/Makefile | 2 + drivers/clk/meson/a1-pll.c | 356 +++ drivers/clk/meson/a1-pll.h | 47 + drivers/clk/meson/a1.c | 2273 +++++++++++++++++ drivers/clk/meson/a1.h | 114 + drivers/clk/meson/clk-pll.c | 47 +- drivers/clk/meson/clk-pll.h | 2 + include/dt-bindings/clock/amlogic,a1-clkc.h | 114 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 + 13 files changed, 3121 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 0/6] add Amlogic A1 clock controller drivers @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. The audio clock controller is different from others, but the rest are very similar from a functional and regmap point of view. This patch series add support for Amlogic A1 PLL and Peripherals clock drivers. It blocks all A1 peripherals mainline support and a couple of patch series, which were already reviewed and acked, but weren't merged due to pending clock controller drivers series, e.g. https://lore.kernel.org/linux-amlogic/7hd09cw9oh.fsf@baylibre.com/ TODO: CPU and Audio clock controllers are not included in this patch series, it will be sent later. The following clks from these controllers are not supported for now: * Audio clks - vad, mclk_vad, mclk_d, resample_a, locker_in, mclk_b, pdmdclk, pdmsysclk, eqdrc, spdifin, mclk_a, audio2_toaudiotop, audio2_tovad, audio2_toddr_vad, audio2_tdmin_vad, audio2_pdm, audio2_ddr_arb, audio_audiolocker, audio_eqdrc, audio_resamplea, audio_spdifin, audio_toddrb, audio_toddra, audio_frddrb, audio_frddra, audio_tdmoutb, audio_tdmouta, audio_loopbacka, audio_tdminlb, audio_tdminb, audio_tdmina, audio_ddr_arb, mclk_c * CPU clks: cpu_fixed_source_sel0, cpu_fixed_source_div0, cpu_fixed_source_sel1, cpu_fixed_source_div1, cpu_clk Validation: * to double check all clk flags run below helper script: pushd /sys/kernel/debug/clk for f in *; do if [[ -f "$f/clk_flags" ]]; then flags="$(cat $f/clk_flags | awk '{$1=$1};1' | sed ':a;N;$!ba;s/\n/ | /g')" echo -e "$f: $flags" fi done popd * to trace current clks state use '/sys/kernel/debug/clk/clk_dump' node with jq post-processing: $ cat /sys/kernel/debug/clk/clk_dump | jq '.' > clk_dump.json * to debug clk rate propagation, compile kernel with the following definition: $ sed -i "s/undef CLOCK_ALLOW_WRITE_DEBUGFS/define CLOCK_ALLOW_WRITE_DEBUGFS/g" drivers/clk/clk.c after that, clk_rate debug node for each clock will be available for write operation Changes v13 since v12 at [13]: - make the clock object registration order from the roots to the leaves - rearrange the clkids following above rule Changes v12 since v11 at [12]: - split the DT bindings patchset into two patches: one for the PLL clock controller driver, and one for the peripherals clock controller driver - to satisfy the DT binding checker, use fake references to the peripherals clock controller in the PLL DT bindings schema, and then replace them with real references when the peripherals bindings become available. - remove the public/private clocks concept from both controllers, and instead use a linear clkid list with both exposed and internal objects, all of which are registered in the clock provider - combine all comments about RTC children with the flag 'CLK_SET_RATE_NO_REPARENT' into a single item with multiple references to it Changes v11 since v10 at [11]: - change include/dt-bindings license to proper value required for bindings files: 'GPL-2.0-only OR BSD-2-Clause' - pll and peripherals clocks are split into public and private parts; public clocks are available for external consumers through the DT layer, private clocks include internal muxes and dividers of composite clocks, they are placed inside clock controller driver without external access - make public clks CLKID bindings continuous - mark the following clock muxes as NO_REPARENT and add them to public clocks list: GEN_SEL, DSPA_A_SEL, DSPA_B_SEL, DSPB_A_SEL, DSP_B_B_SEL, PWM_A_SEL, PWM_B_SEL, PWM_C_SEL, PWM_D_SEL, PWM_E_SEL, PWM_F_SEL, CECA_32K_SEL, CECB_32K_SEL; each of them can be inherited from more accurate RTC clock and sometimes it's required to forbid reparenting in such situation; also GEN_SEL can be connected to external PAD and should not change parent automatically due to rate propagation. For such clocks user must setup parents on the DT side Changes v10 since v9 at [10]: - split general clk-pll changes into two different patchsets: optional rst usage and new power sequence - squash dt bindings patchsets to avoid chicken-or-the-egg problem during run dt binding check routines - add vendor prefix to PLL and Peripherals clkcs bindings filenames - clear managed hifi_pll fields from initial poke table - move DSPA_SEL, DSPB_SEL and SARADC_SEL to private clkid table, because it should not be opened for direct usage - pwm_a clk used for voltage regulation is not critical anymore, it must be included to the proper cpu voltage regulation setup (will be available in the next patch series) - as discussed with Jerome, dspX clks are simple clocks and it should be enabled/disabled/ignored/anything else from appropriate DSP driver, so remove CLK_IGNORE_UNUSED tags - provide more understandable comments and remove irrelevant (I hope so) - remove CONFIG_OF usage, because it's redundant - fix license issue, it's GPL-2.0+ only in the current version - some commit msgs rewording Changes v9 since v8 at [9]: - remove common a1-clkc driver for the first version of a1 clock controllers as Jerome suggested (it will be discussed after s4 and a1 clks landed, hope so) - replace inherited a1-pll clk_pll_ops with common ops and introduce custom A1 PLL logic under MESON_PARM_APPLICABLE() conditions - rename xtal depended clocks in PLL and Peripherals domains - remove 'a1_' prefix for all clocks, because they are already inside A1 driver, it's redundant - change udelay() to usleep_range() as preferred for small msec amount - purge all double quotes from the yaml schemas - use proper dt node names following kernel guidelines https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetree-basics.html#generic-names-recommendation - use devm_platform_ioremap_resource() instead of simple devm_ioremap_resource() - mark all dspX clocks as CLK_IGNORE_UNUSED, because we do not want to touch these clocks during CCF initialization due to possible workload execution on it started from bootloader; in this case bootloader already made all initialization stuff for dspX - also mark all dspX with NO_REPARENT tag, because from dspX clocks we want to select proper clk source from device tree Changes v8 since v7 at [8]: - introduced a1-clkc common driver for all A1 clock controllers - exported meson_clk_pll_wait_lock symbol - supported meson-a1-clkc common driver in the a1-pll and a1 clkc - inherited a1-pll from the base clk-pll driver, implemented own version of init/enable/disable/enabled routines; rate calculating logic is fully the same - aligned CLKID-related definitions with CLKID list from order perspective to remove holes and permutations - corrected Kconfig dependencies and types - provided correct MODULE_AUTHORs() - optimized and fixed up some clock relationships - removed unused register offset definitions - fixed up A1 PLL and Peripherals clkc dtb_check errors - fixed clk_summary kernel panic due to missing a1_pad_ctrl clk_regmap definition - included PLL and Peripherals clk controllers to the base a1 dts - The previous v7 version [8] had several logic and style problems, all of them are resolved in this version. Original Jian Hu v7 patches are not touched, and all additional fixes are implemented in separate patches. Patch "clk: meson: add support for A1 PLL clock ops" is removed, because a1-pll clk driver inherits all stuff from clk-pll base driver, just implements custom init/enable/disable/is_enabled callbacks. Changes v7 since v6 at [7]: - fix 'dt_binding_check' compiling error - add acked-by Changes v6 since v5 at [6]: - fix yaml file - add rst/current_en/l_detect parm detection - remove 'meson_eeclkc_data' in a1.c and a1-pll.c Changes v5 since v4 at [5]: - change yaml GPL - drop meson-eeclk.c patch, add probe function in each driver - add CLK_IS_CRITICAL for sys_clk clock, drop the flag for sys_a and sys_b - add new parm for pll, add protection for rst parm - drop flag for a1_fixed_pll - remove the same comment for fclk_div, add "refer to" - add critical flag for a1_sys_clk - remove rtc table - rename a1_dspa_en_dspa and a1_dspb_en_dspb - remove useless comment Changes v4 since v3 at [3]: - fix reparenting orphan failed, it depends on jerome's patch [4] - fix changelist in v3 about reparenting orphan - remove the dts patch Changes v3 since v2 at [2]: - add probe function for A1 - separate the clock driver into two patch - change some clock flags and ops - add support for a1 PLL ops - add A1 clock node - fix reparenting orphan clock failed, registering xtal_fixpll and xtal_hifipll after the provider registration, it is not a best way. Changes v2 since v1 at [1]: - place A1 config alphabetically - add actual reason for RO ops, CLK_IS_CRITICAL, CLK_IGNORE_UNUSED - separate the driver into two driver: peripheral and pll driver - delete CLK_IGNORE_UNUSED flag for pwm b/c/d/e/f clock, dsp clock - delete the change in Kconfig.platforms, address to Kevin alone - remove the useless comments - modify the meson pll driver to support A1 PLLs Links: [1] https://lkml.kernel.org/r/1569411888-98116-1-git-send-email-jian.hu@amlogic.com [2] https://lkml.kernel.org/r/1571382865-41978-1-git-send-email-jian.hu@amlogic.com [3] https://lkml.kernel.org/r/20191129144605.182774-1-jian.hu@amlogic.com [4] https://lkml.kernel.org/r/20191203080805.104628-1-jbrunet@baylibre.com [5] https://lkml.kernel.org/r/20191206074052.15557-1-jian.hu@amlogic.com [6] https://lkml.kernel.org/r/20191227094606.143637-1-jian.hu@amlogic.com [7] https://lkml.kernel.org/r/20200116080440.118679-1-jian.hu@amlogic.com [8] https://lore.kernel.org/linux-amlogic/20200120034937.128600-1-jian.hu@amlogic.com/ [9] https://lore.kernel.org/linux-amlogic/20221201225703.6507-1-ddrokosov@sberdevices.ru/ [10] https://lore.kernel.org/all/20230301183759.16163-1-ddrokosov@sberdevices.ru/ [11] https://lore.kernel.org/all/20230313201259.19998-1-ddrokosov@sberdevices.ru/ [12] https://lore.kernel.org/all/20230321193014.26349-1-ddrokosov@sberdevices.ru/ [13] https://lore.kernel.org/all/20230404155332.9571-1-ddrokosov@sberdevices.ru/ Dmitry Rokosov (6): clk: meson: make pll rst bit as optional clk: meson: introduce new pll power-on sequence for A1 SoC family dt-bindings: clock: meson: add A1 PLL clock controller bindings clk: meson: a1: add Amlogic A1 PLL clock controller driver dt-bindings: clock: meson: add A1 Peripherals clock controller bindings clk: meson: a1: add Amlogic A1 Peripherals clock controller driver .../bindings/clock/amlogic,a1-clkc.yaml | 73 + .../bindings/clock/amlogic,a1-pll-clkc.yaml | 59 + MAINTAINERS | 1 + drivers/clk/meson/Kconfig | 20 + drivers/clk/meson/Makefile | 2 + drivers/clk/meson/a1-pll.c | 356 +++ drivers/clk/meson/a1-pll.h | 47 + drivers/clk/meson/a1.c | 2273 +++++++++++++++++ drivers/clk/meson/a1.h | 114 + drivers/clk/meson/clk-pll.c | 47 +- drivers/clk/meson/clk-pll.h | 2 + include/dt-bindings/clock/amlogic,a1-clkc.h | 114 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 + 13 files changed, 3121 insertions(+), 7 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 1/6] clk: meson: make pll rst bit as optional 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Compared with the previous SoCs, self-adaption current module is newly added for A1, and there is no reset parameter except the fixed pll. Since we use clk-pll generic driver for A1 pll implementation, rst bit should be optional to support new behavior. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index afefeba6e458..314ca945a4d0 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); if (pll->init_count) { - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, pll->init_count); - meson_parm_write(clk->map, &pll->rst, 0); + + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); } return 0; @@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - if (meson_parm_read(clk->map, &pll->rst) || - !meson_parm_read(clk->map, &pll->en) || + if (MESON_PARM_APPLICABLE(&pll->rst) && + meson_parm_read(clk->map, &pll->rst)) + return 0; + + if (!meson_parm_read(clk->map, &pll->en) || !meson_parm_read(clk->map, &pll->l)) return 0; @@ -341,13 +348,15 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); /* Take the pll out reset */ - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -361,7 +370,8 @@ static void meson_clk_pll_disable(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); /* Put the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 1/6] clk: meson: make pll rst bit as optional @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Compared with the previous SoCs, self-adaption current module is newly added for A1, and there is no reset parameter except the fixed pll. Since we use clk-pll generic driver for A1 pll implementation, rst bit should be optional to support new behavior. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index afefeba6e458..314ca945a4d0 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); if (pll->init_count) { - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, pll->init_count); - meson_parm_write(clk->map, &pll->rst, 0); + + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); } return 0; @@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - if (meson_parm_read(clk->map, &pll->rst) || - !meson_parm_read(clk->map, &pll->en) || + if (MESON_PARM_APPLICABLE(&pll->rst) && + meson_parm_read(clk->map, &pll->rst)) + return 0; + + if (!meson_parm_read(clk->map, &pll->en) || !meson_parm_read(clk->map, &pll->l)) return 0; @@ -341,13 +348,15 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); /* Take the pll out reset */ - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -361,7 +370,8 @@ static void meson_clk_pll_disable(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); /* Put the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 1/6] clk: meson: make pll rst bit as optional @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Compared with the previous SoCs, self-adaption current module is newly added for A1, and there is no reset parameter except the fixed pll. Since we use clk-pll generic driver for A1 pll implementation, rst bit should be optional to support new behavior. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index afefeba6e458..314ca945a4d0 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -295,10 +295,14 @@ static int meson_clk_pll_init(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); if (pll->init_count) { - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); + regmap_multi_reg_write(clk->map, pll->init_regs, pll->init_count); - meson_parm_write(clk->map, &pll->rst, 0); + + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); } return 0; @@ -309,8 +313,11 @@ static int meson_clk_pll_is_enabled(struct clk_hw *hw) struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - if (meson_parm_read(clk->map, &pll->rst) || - !meson_parm_read(clk->map, &pll->en) || + if (MESON_PARM_APPLICABLE(&pll->rst) && + meson_parm_read(clk->map, &pll->rst)) + return 0; + + if (!meson_parm_read(clk->map, &pll->en) || !meson_parm_read(clk->map, &pll->l)) return 0; @@ -341,13 +348,15 @@ static int meson_clk_pll_enable(struct clk_hw *hw) return 0; /* Make sure the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Enable the pll */ meson_parm_write(clk->map, &pll->en, 1); /* Take the pll out reset */ - meson_parm_write(clk->map, &pll->rst, 0); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 0); if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -361,7 +370,8 @@ static void meson_clk_pll_disable(struct clk_hw *hw) struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); /* Put the pll is in reset */ - meson_parm_write(clk->map, &pll->rst, 1); + if (MESON_PARM_APPLICABLE(&pll->rst)) + meson_parm_write(clk->map, &pll->rst, 1); /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 2/6] clk: meson: introduce new pll power-on sequence for A1 SoC family 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Modern meson PLL IPs are a little bit different from early known PLLs. The main difference is located in the init/enable/disable sequences; the rate logic is the same. In A1 PLL, the PLL enable sequence is different, so add new optional pll reg bits and use the new power-on sequence to enable the PLL: 1. enable the pll, delay for 10us 2. enable the pll self-adaption current module, delay for 40us 3. enable the lock detect module Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 23 +++++++++++++++++++++++ drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 314ca945a4d0..56ec2210f1ad 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -358,6 +358,25 @@ static int meson_clk_pll_enable(struct clk_hw *hw) if (MESON_PARM_APPLICABLE(&pll->rst)) meson_parm_write(clk->map, &pll->rst, 0); + /* + * Compared with the previous SoCs, self-adaption current module + * is newly added for A1, keep the new power-on sequence to enable the + * PLL. The sequence is: + * 1. enable the pll, delay for 10us + * 2. enable the pll self-adaption current module, delay for 40us + * 3. enable the lock detect module + */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) { + usleep_range(10, 20); + meson_parm_write(clk->map, &pll->current_en, 1); + usleep_range(40, 50); + }; + + if (MESON_PARM_APPLICABLE(&pll->l_detect)) { + meson_parm_write(clk->map, &pll->l_detect, 1); + meson_parm_write(clk->map, &pll->l_detect, 0); + } + if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -375,6 +394,10 @@ static void meson_clk_pll_disable(struct clk_hw *hw) /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); + + /* Disable PLL internal self-adaption current module */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) + meson_parm_write(clk->map, &pll->current_en, 0); } static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 367efd0f6410..a2228c0fdce5 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -36,6 +36,8 @@ struct meson_clk_pll_data { struct parm frac; struct parm l; struct parm rst; + struct parm current_en; + struct parm l_detect; const struct reg_sequence *init_regs; unsigned int init_count; const struct pll_params_table *table; -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 2/6] clk: meson: introduce new pll power-on sequence for A1 SoC family @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Modern meson PLL IPs are a little bit different from early known PLLs. The main difference is located in the init/enable/disable sequences; the rate logic is the same. In A1 PLL, the PLL enable sequence is different, so add new optional pll reg bits and use the new power-on sequence to enable the PLL: 1. enable the pll, delay for 10us 2. enable the pll self-adaption current module, delay for 40us 3. enable the lock detect module Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 23 +++++++++++++++++++++++ drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 314ca945a4d0..56ec2210f1ad 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -358,6 +358,25 @@ static int meson_clk_pll_enable(struct clk_hw *hw) if (MESON_PARM_APPLICABLE(&pll->rst)) meson_parm_write(clk->map, &pll->rst, 0); + /* + * Compared with the previous SoCs, self-adaption current module + * is newly added for A1, keep the new power-on sequence to enable the + * PLL. The sequence is: + * 1. enable the pll, delay for 10us + * 2. enable the pll self-adaption current module, delay for 40us + * 3. enable the lock detect module + */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) { + usleep_range(10, 20); + meson_parm_write(clk->map, &pll->current_en, 1); + usleep_range(40, 50); + }; + + if (MESON_PARM_APPLICABLE(&pll->l_detect)) { + meson_parm_write(clk->map, &pll->l_detect, 1); + meson_parm_write(clk->map, &pll->l_detect, 0); + } + if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -375,6 +394,10 @@ static void meson_clk_pll_disable(struct clk_hw *hw) /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); + + /* Disable PLL internal self-adaption current module */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) + meson_parm_write(clk->map, &pll->current_en, 0); } static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 367efd0f6410..a2228c0fdce5 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -36,6 +36,8 @@ struct meson_clk_pll_data { struct parm frac; struct parm l; struct parm rst; + struct parm current_en; + struct parm l_detect; const struct reg_sequence *init_regs; unsigned int init_count; const struct pll_params_table *table; -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 2/6] clk: meson: introduce new pll power-on sequence for A1 SoC family @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Modern meson PLL IPs are a little bit different from early known PLLs. The main difference is located in the init/enable/disable sequences; the rate logic is the same. In A1 PLL, the PLL enable sequence is different, so add new optional pll reg bits and use the new power-on sequence to enable the PLL: 1. enable the pll, delay for 10us 2. enable the pll self-adaption current module, delay for 40us 3. enable the lock detect module Signed-off-by: Jian Hu <jian.hu@amlogic.com> Acked-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/clk-pll.c | 23 +++++++++++++++++++++++ drivers/clk/meson/clk-pll.h | 2 ++ 2 files changed, 25 insertions(+) diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index 314ca945a4d0..56ec2210f1ad 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -358,6 +358,25 @@ static int meson_clk_pll_enable(struct clk_hw *hw) if (MESON_PARM_APPLICABLE(&pll->rst)) meson_parm_write(clk->map, &pll->rst, 0); + /* + * Compared with the previous SoCs, self-adaption current module + * is newly added for A1, keep the new power-on sequence to enable the + * PLL. The sequence is: + * 1. enable the pll, delay for 10us + * 2. enable the pll self-adaption current module, delay for 40us + * 3. enable the lock detect module + */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) { + usleep_range(10, 20); + meson_parm_write(clk->map, &pll->current_en, 1); + usleep_range(40, 50); + }; + + if (MESON_PARM_APPLICABLE(&pll->l_detect)) { + meson_parm_write(clk->map, &pll->l_detect, 1); + meson_parm_write(clk->map, &pll->l_detect, 0); + } + if (meson_clk_pll_wait_lock(hw)) return -EIO; @@ -375,6 +394,10 @@ static void meson_clk_pll_disable(struct clk_hw *hw) /* Disable the pll */ meson_parm_write(clk->map, &pll->en, 0); + + /* Disable PLL internal self-adaption current module */ + if (MESON_PARM_APPLICABLE(&pll->current_en)) + meson_parm_write(clk->map, &pll->current_en, 0); } static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h index 367efd0f6410..a2228c0fdce5 100644 --- a/drivers/clk/meson/clk-pll.h +++ b/drivers/clk/meson/clk-pll.h @@ -36,6 +36,8 @@ struct meson_clk_pll_data { struct parm frac; struct parm l; struct parm rst; + struct parm current_en; + struct parm l_detect; const struct reg_sequence *init_regs; unsigned int init_count; const struct pll_params_table *table; -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL clock controller bindings. Also include new A1 clock controller dt bindings to MAINTAINERS. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ MAINTAINERS | 1 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ 3 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml new file mode 100644 index 000000000000..b3f46cf4b161 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials PLL Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-pll-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixpll_in + - description: input hifipll_in + + clock-names: + items: + - const: fixpll_in + - const: hifipll_in + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@7c80 { + compatible = "amlogic,a1-pll-clkc"; + reg = <0 0x7c80 0 0x18c>; + #clock-cells = <1>; + clocks = <&clkc_periphs_fixpll_in>, + <&clkc_periphs_hifipll_in>; + clock-names = "fixpll_in", "hifipll_in"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 39ff1a717625..8438bc9bd636 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1895,6 +1895,7 @@ L: linux-amlogic@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/clock/amlogic* F: drivers/clk/meson/ +F: include/dt-bindings/clock/a1* F: include/dt-bindings/clock/gxbb* F: include/dt-bindings/clock/meson* diff --git a/include/dt-bindings/clock/amlogic,a1-pll-clkc.h b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h new file mode 100644 index 000000000000..01fb8164ac29 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_CLKC_H +#define __A1_PLL_CLKC_H + +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2 6 +#define CLKID_FCLK_DIV3 7 +#define CLKID_FCLK_DIV5 8 +#define CLKID_FCLK_DIV7 9 +#define CLKID_HIFI_PLL 10 + +#endif /* __A1_PLL_CLKC_H */ -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL clock controller bindings. Also include new A1 clock controller dt bindings to MAINTAINERS. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ MAINTAINERS | 1 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ 3 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml new file mode 100644 index 000000000000..b3f46cf4b161 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials PLL Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-pll-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixpll_in + - description: input hifipll_in + + clock-names: + items: + - const: fixpll_in + - const: hifipll_in + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@7c80 { + compatible = "amlogic,a1-pll-clkc"; + reg = <0 0x7c80 0 0x18c>; + #clock-cells = <1>; + clocks = <&clkc_periphs_fixpll_in>, + <&clkc_periphs_hifipll_in>; + clock-names = "fixpll_in", "hifipll_in"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 39ff1a717625..8438bc9bd636 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1895,6 +1895,7 @@ L: linux-amlogic@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/clock/amlogic* F: drivers/clk/meson/ +F: include/dt-bindings/clock/a1* F: include/dt-bindings/clock/gxbb* F: include/dt-bindings/clock/meson* diff --git a/include/dt-bindings/clock/amlogic,a1-pll-clkc.h b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h new file mode 100644 index 000000000000..01fb8164ac29 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_CLKC_H +#define __A1_PLL_CLKC_H + +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2 6 +#define CLKID_FCLK_DIV3 7 +#define CLKID_FCLK_DIV5 8 +#define CLKID_FCLK_DIV7 9 +#define CLKID_HIFI_PLL 10 + +#endif /* __A1_PLL_CLKC_H */ -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL clock controller bindings. Also include new A1 clock controller dt bindings to MAINTAINERS. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ MAINTAINERS | 1 + .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ 3 files changed, 79 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml new file mode 100644 index 000000000000..b3f46cf4b161 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -0,0 +1,58 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-pll-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials PLL Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-pll-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixpll_in + - description: input hifipll_in + + clock-names: + items: + - const: fixpll_in + - const: hifipll_in + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@7c80 { + compatible = "amlogic,a1-pll-clkc"; + reg = <0 0x7c80 0 0x18c>; + #clock-cells = <1>; + clocks = <&clkc_periphs_fixpll_in>, + <&clkc_periphs_hifipll_in>; + clock-names = "fixpll_in", "hifipll_in"; + }; + }; diff --git a/MAINTAINERS b/MAINTAINERS index 39ff1a717625..8438bc9bd636 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1895,6 +1895,7 @@ L: linux-amlogic@lists.infradead.org S: Maintained F: Documentation/devicetree/bindings/clock/amlogic* F: drivers/clk/meson/ +F: include/dt-bindings/clock/a1* F: include/dt-bindings/clock/gxbb* F: include/dt-bindings/clock/meson* diff --git a/include/dt-bindings/clock/amlogic,a1-pll-clkc.h b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h new file mode 100644 index 000000000000..01fb8164ac29 --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-pll-clkc.h @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_CLKC_H +#define __A1_PLL_CLKC_H + +#define CLKID_FIXED_PLL 1 +#define CLKID_FCLK_DIV2 6 +#define CLKID_FCLK_DIV3 7 +#define CLKID_FCLK_DIV5 8 +#define CLKID_FCLK_DIV7 9 +#define CLKID_HIFI_PLL 10 + +#endif /* __A1_PLL_CLKC_H */ -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* Re: [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-12 13:46 ` Rob Herring -1 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: mturquette, jian.hu, khilman, krzysztof.kozlowski+dt, devicetree, jbrunet, linux-kernel, kernel, sboyd, linux-amlogic, linux-clk, robh+dt, linux-arm-kernel, rockosov, neil.armstrong, martin.blumenstingl On Wed, 05 Apr 2023 22:59:24 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL > clock controller bindings. > Also include new A1 clock controller dt bindings to MAINTAINERS. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ > MAINTAINERS | 1 + > .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ > 3 files changed, 79 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings @ 2023-04-12 13:46 ` Rob Herring 0 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: mturquette, jian.hu, khilman, krzysztof.kozlowski+dt, devicetree, jbrunet, linux-kernel, kernel, sboyd, linux-amlogic, linux-clk, robh+dt, linux-arm-kernel, rockosov, neil.armstrong, martin.blumenstingl On Wed, 05 Apr 2023 22:59:24 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL > clock controller bindings. > Also include new A1 clock controller dt bindings to MAINTAINERS. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ > MAINTAINERS | 1 + > .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ > 3 files changed, 79 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings @ 2023-04-12 13:46 ` Rob Herring 0 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: mturquette, jian.hu, khilman, krzysztof.kozlowski+dt, devicetree, jbrunet, linux-kernel, kernel, sboyd, linux-amlogic, linux-clk, robh+dt, linux-arm-kernel, rockosov, neil.armstrong, martin.blumenstingl On Wed, 05 Apr 2023 22:59:24 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 PLL clock driver, and A1 PLL > clock controller bindings. > Also include new A1 clock controller dt bindings to MAINTAINERS. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 58 +++++++++++++++++++ > MAINTAINERS | 1 + > .../dt-bindings/clock/amlogic,a1-pll-clkc.h | 20 +++++++ > 3 files changed, 79 insertions(+) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-pll-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce PLL clock controller for Amlogic A1 SoC family. The clock unit is an APB slave module that is designed for generating all of the internal and system clocks. The SoC uses an external 24MHz crystal; there are 4 internal PLLs: SYS_PLL/HIFI_PLL/USB_PLL/(FIXPLL), these PLLs generate 27 clock sources. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 ++ drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1-pll.c | 356 +++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1-pll.h | 47 +++++ 4 files changed, 414 insertions(+) create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index fc002c155bc3..f56da2a4b000 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -99,6 +99,16 @@ config COMMON_CLK_AXG_AUDIO Support for the audio clock controller on AmLogic A113D devices, aka axg, Say Y if you want audio subsystem to work. +config COMMON_CLK_A1_PLL + tristate "Meson A1 SoC PLL controller support" + depends on ARM64 + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_PLL + help + Support for the PLL clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 PLL clock controller + to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 6eca2a406ee3..2f17f475a48f 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o +obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c new file mode 100644 index 000000000000..f7ab11dcf2bc --- /dev/null +++ b/drivers/clk/meson/a1-pll.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1-pll.h" +#include "clk-regmap.h" + +static struct clk_regmap fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_FIXPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_FIXPLL_STS, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fixpll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixed_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixed_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static const struct pll_mult_range hifi_pll_mult_range = { + .min = 32, + .max = 64, +}; + +static const struct reg_sequence hifi_init_regs[] = { + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 }, + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 }, + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 }, + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 }, + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 }, +}; + +static struct clk_regmap hifi_pll = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_HIFIPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_HIFIPLL_STS, + .shift = 31, + .width = 1, + }, + .current_en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 26, + .width = 1, + }, + .l_detect = { + .reg_off = ANACTRL_HIFIPLL_CTRL2, + .shift = 6, + .width = 1, + }, + .range = &hifi_pll_mult_range, + .init_regs = hifi_init_regs, + .init_count = ARRAY_SIZE(hifi_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "hifipll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 21, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_div.hw + }, + .num_parents = 1, + /* + * This clock is used by DDR clock in BL2 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, + }, +}; + +static struct clk_fixed_factor fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div3_div.hw + }, + .num_parents = 1, + /* + * This clock is used by APB bus which is set in boot ROM code + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div5_div = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div5_div.hw + }, + .num_parents = 1, + /* + * This clock is used by AXI bus which setted in Romcode + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div7_div = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div7_div.hw + }, + .num_parents = 1, + }, +}; + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_pll_clks = { + .hws = { + [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw, + [CLKID_FIXED_PLL] = &fixed_pll.hw, + [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw, + [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw, + [CLKID_FCLK_DIV2] = &fclk_div2.hw, + [CLKID_FCLK_DIV3] = &fclk_div3.hw, + [CLKID_FCLK_DIV5] = &fclk_div5.hw, + [CLKID_FCLK_DIV7] = &fclk_div7.hw, + [CLKID_HIFI_PLL] = &hifi_pll.hw, + [NR_PLL_CLKS] = NULL, + }, + .num = NR_PLL_CLKS, +}; + +static struct clk_regmap *const a1_pll_regmaps[] = { + &fixed_pll_dco, + &fixed_pll, + &fclk_div2, + &fclk_div3, + &fclk_div5, + &fclk_div7, + &hifi_pll, +}; + +static struct regmap_config a1_pll_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_pll_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++) + a1_pll_regmaps[i]->map = map; + + /* Register clocks */ + for (clkid = 0; clkid < a1_pll_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_pll_clks); +} + +static const struct of_device_id a1_pll_clkc_match_table[] = { + { .compatible = "amlogic,a1-pll-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table); + +static struct platform_driver a1_pll_clkc_driver = { + .probe = meson_a1_pll_probe, + .driver = { + .name = "a1-pll-clkc", + .of_match_table = of_match_ptr(a1_pll_clkc_match_table), + }, +}; + +module_platform_driver(a1_pll_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h new file mode 100644 index 000000000000..69e5e31790f2 --- /dev/null +++ b/drivers/clk/meson/a1-pll.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 PLL Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_H +#define __A1_PLL_H + +#include "clk-pll.h" + +/* PLL register offset */ +#define ANACTRL_FIXPLL_CTRL0 0x0 +#define ANACTRL_FIXPLL_CTRL1 0x4 +#define ANACTRL_FIXPLL_STS 0x14 +#define ANACTRL_HIFIPLL_CTRL0 0xc0 +#define ANACTRL_HIFIPLL_CTRL1 0xc4 +#define ANACTRL_HIFIPLL_CTRL2 0xc8 +#define ANACTRL_HIFIPLL_CTRL3 0xcc +#define ANACTRL_HIFIPLL_CTRL4 0xd0 +#define ANACTRL_HIFIPLL_STS 0xd4 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_FIXED_PLL_DCO 0 +#define CLKID_FCLK_DIV2_DIV 2 +#define CLKID_FCLK_DIV3_DIV 3 +#define CLKID_FCLK_DIV5_DIV 4 +#define CLKID_FCLK_DIV7_DIV 5 +#define NR_PLL_CLKS 11 + +#endif /* __A1_PLL_H */ -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce PLL clock controller for Amlogic A1 SoC family. The clock unit is an APB slave module that is designed for generating all of the internal and system clocks. The SoC uses an external 24MHz crystal; there are 4 internal PLLs: SYS_PLL/HIFI_PLL/USB_PLL/(FIXPLL), these PLLs generate 27 clock sources. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 ++ drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1-pll.c | 356 +++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1-pll.h | 47 +++++ 4 files changed, 414 insertions(+) create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index fc002c155bc3..f56da2a4b000 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -99,6 +99,16 @@ config COMMON_CLK_AXG_AUDIO Support for the audio clock controller on AmLogic A113D devices, aka axg, Say Y if you want audio subsystem to work. +config COMMON_CLK_A1_PLL + tristate "Meson A1 SoC PLL controller support" + depends on ARM64 + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_PLL + help + Support for the PLL clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 PLL clock controller + to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 6eca2a406ee3..2f17f475a48f 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o +obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c new file mode 100644 index 000000000000..f7ab11dcf2bc --- /dev/null +++ b/drivers/clk/meson/a1-pll.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1-pll.h" +#include "clk-regmap.h" + +static struct clk_regmap fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_FIXPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_FIXPLL_STS, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fixpll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixed_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixed_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static const struct pll_mult_range hifi_pll_mult_range = { + .min = 32, + .max = 64, +}; + +static const struct reg_sequence hifi_init_regs[] = { + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 }, + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 }, + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 }, + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 }, + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 }, +}; + +static struct clk_regmap hifi_pll = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_HIFIPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_HIFIPLL_STS, + .shift = 31, + .width = 1, + }, + .current_en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 26, + .width = 1, + }, + .l_detect = { + .reg_off = ANACTRL_HIFIPLL_CTRL2, + .shift = 6, + .width = 1, + }, + .range = &hifi_pll_mult_range, + .init_regs = hifi_init_regs, + .init_count = ARRAY_SIZE(hifi_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "hifipll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 21, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_div.hw + }, + .num_parents = 1, + /* + * This clock is used by DDR clock in BL2 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, + }, +}; + +static struct clk_fixed_factor fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div3_div.hw + }, + .num_parents = 1, + /* + * This clock is used by APB bus which is set in boot ROM code + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div5_div = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div5_div.hw + }, + .num_parents = 1, + /* + * This clock is used by AXI bus which setted in Romcode + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div7_div = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div7_div.hw + }, + .num_parents = 1, + }, +}; + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_pll_clks = { + .hws = { + [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw, + [CLKID_FIXED_PLL] = &fixed_pll.hw, + [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw, + [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw, + [CLKID_FCLK_DIV2] = &fclk_div2.hw, + [CLKID_FCLK_DIV3] = &fclk_div3.hw, + [CLKID_FCLK_DIV5] = &fclk_div5.hw, + [CLKID_FCLK_DIV7] = &fclk_div7.hw, + [CLKID_HIFI_PLL] = &hifi_pll.hw, + [NR_PLL_CLKS] = NULL, + }, + .num = NR_PLL_CLKS, +}; + +static struct clk_regmap *const a1_pll_regmaps[] = { + &fixed_pll_dco, + &fixed_pll, + &fclk_div2, + &fclk_div3, + &fclk_div5, + &fclk_div7, + &hifi_pll, +}; + +static struct regmap_config a1_pll_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_pll_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++) + a1_pll_regmaps[i]->map = map; + + /* Register clocks */ + for (clkid = 0; clkid < a1_pll_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_pll_clks); +} + +static const struct of_device_id a1_pll_clkc_match_table[] = { + { .compatible = "amlogic,a1-pll-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table); + +static struct platform_driver a1_pll_clkc_driver = { + .probe = meson_a1_pll_probe, + .driver = { + .name = "a1-pll-clkc", + .of_match_table = of_match_ptr(a1_pll_clkc_match_table), + }, +}; + +module_platform_driver(a1_pll_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h new file mode 100644 index 000000000000..69e5e31790f2 --- /dev/null +++ b/drivers/clk/meson/a1-pll.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 PLL Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_H +#define __A1_PLL_H + +#include "clk-pll.h" + +/* PLL register offset */ +#define ANACTRL_FIXPLL_CTRL0 0x0 +#define ANACTRL_FIXPLL_CTRL1 0x4 +#define ANACTRL_FIXPLL_STS 0x14 +#define ANACTRL_HIFIPLL_CTRL0 0xc0 +#define ANACTRL_HIFIPLL_CTRL1 0xc4 +#define ANACTRL_HIFIPLL_CTRL2 0xc8 +#define ANACTRL_HIFIPLL_CTRL3 0xcc +#define ANACTRL_HIFIPLL_CTRL4 0xd0 +#define ANACTRL_HIFIPLL_STS 0xd4 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_FIXED_PLL_DCO 0 +#define CLKID_FCLK_DIV2_DIV 2 +#define CLKID_FCLK_DIV3_DIV 3 +#define CLKID_FCLK_DIV5_DIV 4 +#define CLKID_FCLK_DIV7_DIV 5 +#define NR_PLL_CLKS 11 + +#endif /* __A1_PLL_H */ -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce PLL clock controller for Amlogic A1 SoC family. The clock unit is an APB slave module that is designed for generating all of the internal and system clocks. The SoC uses an external 24MHz crystal; there are 4 internal PLLs: SYS_PLL/HIFI_PLL/USB_PLL/(FIXPLL), these PLLs generate 27 clock sources. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 ++ drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1-pll.c | 356 +++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1-pll.h | 47 +++++ 4 files changed, 414 insertions(+) create mode 100644 drivers/clk/meson/a1-pll.c create mode 100644 drivers/clk/meson/a1-pll.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index fc002c155bc3..f56da2a4b000 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -99,6 +99,16 @@ config COMMON_CLK_AXG_AUDIO Support for the audio clock controller on AmLogic A113D devices, aka axg, Say Y if you want audio subsystem to work. +config COMMON_CLK_A1_PLL + tristate "Meson A1 SoC PLL controller support" + depends on ARM64 + select COMMON_CLK_MESON_REGMAP + select COMMON_CLK_MESON_PLL + help + Support for the PLL clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 PLL clock controller + to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 6eca2a406ee3..2f17f475a48f 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o +obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c new file mode 100644 index 000000000000..f7ab11dcf2bc --- /dev/null +++ b/drivers/clk/meson/a1-pll.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1-pll.h" +#include "clk-regmap.h" + +static struct clk_regmap fixed_pll_dco = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_FIXPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_FIXPLL_STS, + .shift = 31, + .width = 1, + }, + .rst = { + .reg_off = ANACTRL_FIXPLL_CTRL0, + .shift = 29, + .width = 1, + }, + }, + .hw.init = &(struct clk_init_data){ + .name = "fixed_pll_dco", + .ops = &meson_clk_pll_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fixpll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixed_pll = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 20, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixed_pll", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll_dco.hw + }, + .num_parents = 1, + }, +}; + +static const struct pll_mult_range hifi_pll_mult_range = { + .min = 32, + .max = 64, +}; + +static const struct reg_sequence hifi_init_regs[] = { + { .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 }, + { .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 }, + { .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 }, + { .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 }, + { .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 }, +}; + +static struct clk_regmap hifi_pll = { + .data = &(struct meson_clk_pll_data){ + .en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 28, + .width = 1, + }, + .m = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 0, + .width = 8, + }, + .n = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 10, + .width = 5, + }, + .frac = { + .reg_off = ANACTRL_HIFIPLL_CTRL1, + .shift = 0, + .width = 19, + }, + .l = { + .reg_off = ANACTRL_HIFIPLL_STS, + .shift = 31, + .width = 1, + }, + .current_en = { + .reg_off = ANACTRL_HIFIPLL_CTRL0, + .shift = 26, + .width = 1, + }, + .l_detect = { + .reg_off = ANACTRL_HIFIPLL_CTRL2, + .shift = 6, + .width = 1, + }, + .range = &hifi_pll_mult_range, + .init_regs = hifi_init_regs, + .init_count = ARRAY_SIZE(hifi_init_regs), + }, + .hw.init = &(struct clk_init_data){ + .name = "hifi_pll", + .ops = &meson_clk_pll_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "hifipll_in", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor fclk_div2_div = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 21, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_div.hw + }, + .num_parents = 1, + /* + * This clock is used by DDR clock in BL2 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, + }, +}; + +static struct clk_fixed_factor fclk_div3_div = { + .mult = 1, + .div = 3, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div3 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 22, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div3", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div3_div.hw + }, + .num_parents = 1, + /* + * This clock is used by APB bus which is set in boot ROM code + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div5_div = { + .mult = 1, + .div = 5, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div5 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 23, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div5", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div5_div.hw + }, + .num_parents = 1, + /* + * This clock is used by AXI bus which setted in Romcode + * and is required by the platform to operate correctly. + */ + .flags = CLK_IS_CRITICAL, + }, +}; + +static struct clk_fixed_factor fclk_div7_div = { + .mult = 1, + .div = 7, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7_div", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &fixed_pll.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div7 = { + .data = &(struct clk_regmap_gate_data){ + .offset = ANACTRL_FIXPLL_CTRL0, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div7", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div7_div.hw + }, + .num_parents = 1, + }, +}; + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_pll_clks = { + .hws = { + [CLKID_FIXED_PLL_DCO] = &fixed_pll_dco.hw, + [CLKID_FIXED_PLL] = &fixed_pll.hw, + [CLKID_FCLK_DIV2_DIV] = &fclk_div2_div.hw, + [CLKID_FCLK_DIV3_DIV] = &fclk_div3_div.hw, + [CLKID_FCLK_DIV5_DIV] = &fclk_div5_div.hw, + [CLKID_FCLK_DIV7_DIV] = &fclk_div7_div.hw, + [CLKID_FCLK_DIV2] = &fclk_div2.hw, + [CLKID_FCLK_DIV3] = &fclk_div3.hw, + [CLKID_FCLK_DIV5] = &fclk_div5.hw, + [CLKID_FCLK_DIV7] = &fclk_div7.hw, + [CLKID_HIFI_PLL] = &hifi_pll.hw, + [NR_PLL_CLKS] = NULL, + }, + .num = NR_PLL_CLKS, +}; + +static struct clk_regmap *const a1_pll_regmaps[] = { + &fixed_pll_dco, + &fixed_pll, + &fclk_div2, + &fclk_div3, + &fclk_div5, + &fclk_div7, + &hifi_pll, +}; + +static struct regmap_config a1_pll_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_pll_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++) + a1_pll_regmaps[i]->map = map; + + /* Register clocks */ + for (clkid = 0; clkid < a1_pll_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_pll_clks); +} + +static const struct of_device_id a1_pll_clkc_match_table[] = { + { .compatible = "amlogic,a1-pll-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table); + +static struct platform_driver a1_pll_clkc_driver = { + .probe = meson_a1_pll_probe, + .driver = { + .name = "a1-pll-clkc", + .of_match_table = of_match_ptr(a1_pll_clkc_match_table), + }, +}; + +module_platform_driver(a1_pll_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1-pll.h b/drivers/clk/meson/a1-pll.h new file mode 100644 index 000000000000..69e5e31790f2 --- /dev/null +++ b/drivers/clk/meson/a1-pll.h @@ -0,0 +1,47 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 PLL Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_PLL_H +#define __A1_PLL_H + +#include "clk-pll.h" + +/* PLL register offset */ +#define ANACTRL_FIXPLL_CTRL0 0x0 +#define ANACTRL_FIXPLL_CTRL1 0x4 +#define ANACTRL_FIXPLL_STS 0x14 +#define ANACTRL_HIFIPLL_CTRL0 0xc0 +#define ANACTRL_HIFIPLL_CTRL1 0xc4 +#define ANACTRL_HIFIPLL_CTRL2 0xc8 +#define ANACTRL_HIFIPLL_CTRL3 0xcc +#define ANACTRL_HIFIPLL_CTRL4 0xd0 +#define ANACTRL_HIFIPLL_STS 0xd4 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-pll-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_FIXED_PLL_DCO 0 +#define CLKID_FCLK_DIV2_DIV 2 +#define CLKID_FCLK_DIV3_DIV 3 +#define CLKID_FCLK_DIV5_DIV 4 +#define CLKID_FCLK_DIV7_DIV 5 +#define NR_PLL_CLKS 11 + +#endif /* __A1_PLL_H */ -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-23 21:12 ` Martin Blumenstingl -1 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:12 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, currently Jerome is busy so I am trying to continue where he left off. I have followed the previous iterations a bit but may have missed some details. So apologies if I'm repeating some questions that Jerome previously asked. On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +config COMMON_CLK_A1_PLL > + tristate "Meson A1 SoC PLL controller support" Should this be "Amlogic A1 SoC PLL controller support"? My understanding is that the "meson" name was dropped for this generation of SoCs. [...] > +static const struct of_device_id a1_pll_clkc_match_table[] = { > + { .compatible = "amlogic,a1-pll-clkc", }, > + {}, nit-pick: please drop the comma after {} This empty entry is a sentinel, no other entries are supposed to come after this - so a trailing comma is not necessary. [...] > +/* PLL register offset */ > +#define ANACTRL_FIXPLL_CTRL0 0x0 > +#define ANACTRL_FIXPLL_CTRL1 0x4 > +#define ANACTRL_FIXPLL_STS 0x14 > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > +#define ANACTRL_HIFIPLL_STS 0xd4 Here I have a question that will potentially affect patch 3/6 ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). In the cover-letter you mentioned that quite a few clocks have been omitted. Any dt-bindings that we create need to be stable going forward. That means: the dt-bindings will always need to describe what the hardware is capable of, not what the driver implements. So my question is: do we have all needed inputs described in the dt-bindings (even though we're omitting quite a few registers here that will only be added/used in the future)? Older SoCs require (temporarily) using the XTAL clock for CPU clock tree changes. To make a long story short: I'm wondering if - at least - the XTAL clock input is missing. PS: I don't have an A1 datasheet nor a vendor kernel source (and even less a board for testing). So I can't verify any of this myself and I'm asking questions instead. Best regards, Martin ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-23 21:12 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:12 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, currently Jerome is busy so I am trying to continue where he left off. I have followed the previous iterations a bit but may have missed some details. So apologies if I'm repeating some questions that Jerome previously asked. On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +config COMMON_CLK_A1_PLL > + tristate "Meson A1 SoC PLL controller support" Should this be "Amlogic A1 SoC PLL controller support"? My understanding is that the "meson" name was dropped for this generation of SoCs. [...] > +static const struct of_device_id a1_pll_clkc_match_table[] = { > + { .compatible = "amlogic,a1-pll-clkc", }, > + {}, nit-pick: please drop the comma after {} This empty entry is a sentinel, no other entries are supposed to come after this - so a trailing comma is not necessary. [...] > +/* PLL register offset */ > +#define ANACTRL_FIXPLL_CTRL0 0x0 > +#define ANACTRL_FIXPLL_CTRL1 0x4 > +#define ANACTRL_FIXPLL_STS 0x14 > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > +#define ANACTRL_HIFIPLL_STS 0xd4 Here I have a question that will potentially affect patch 3/6 ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). In the cover-letter you mentioned that quite a few clocks have been omitted. Any dt-bindings that we create need to be stable going forward. That means: the dt-bindings will always need to describe what the hardware is capable of, not what the driver implements. So my question is: do we have all needed inputs described in the dt-bindings (even though we're omitting quite a few registers here that will only be added/used in the future)? Older SoCs require (temporarily) using the XTAL clock for CPU clock tree changes. To make a long story short: I'm wondering if - at least - the XTAL clock input is missing. PS: I don't have an A1 datasheet nor a vendor kernel source (and even less a board for testing). So I can't verify any of this myself and I'm asking questions instead. Best regards, Martin _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-23 21:12 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:12 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, currently Jerome is busy so I am trying to continue where he left off. I have followed the previous iterations a bit but may have missed some details. So apologies if I'm repeating some questions that Jerome previously asked. On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +config COMMON_CLK_A1_PLL > + tristate "Meson A1 SoC PLL controller support" Should this be "Amlogic A1 SoC PLL controller support"? My understanding is that the "meson" name was dropped for this generation of SoCs. [...] > +static const struct of_device_id a1_pll_clkc_match_table[] = { > + { .compatible = "amlogic,a1-pll-clkc", }, > + {}, nit-pick: please drop the comma after {} This empty entry is a sentinel, no other entries are supposed to come after this - so a trailing comma is not necessary. [...] > +/* PLL register offset */ > +#define ANACTRL_FIXPLL_CTRL0 0x0 > +#define ANACTRL_FIXPLL_CTRL1 0x4 > +#define ANACTRL_FIXPLL_STS 0x14 > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > +#define ANACTRL_HIFIPLL_STS 0xd4 Here I have a question that will potentially affect patch 3/6 ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). In the cover-letter you mentioned that quite a few clocks have been omitted. Any dt-bindings that we create need to be stable going forward. That means: the dt-bindings will always need to describe what the hardware is capable of, not what the driver implements. So my question is: do we have all needed inputs described in the dt-bindings (even though we're omitting quite a few registers here that will only be added/used in the future)? Older SoCs require (temporarily) using the XTAL clock for CPU clock tree changes. To make a long story short: I'm wondering if - at least - the XTAL clock input is missing. PS: I don't have an A1 datasheet nor a vendor kernel source (and even less a board for testing). So I can't verify any of this myself and I'm asking questions instead. Best regards, Martin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-04-23 21:12 ` Martin Blumenstingl (?) @ 2023-04-25 12:33 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:33 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, On Sun, Apr 23, 2023 at 11:12:27PM +0200, Martin Blumenstingl wrote: > Hello Dmitry, > > currently Jerome is busy so I am trying to continue where he left off. > I have followed the previous iterations a bit but may have missed some > details. So apologies if I'm repeating some questions that Jerome > previously asked. > Thank you very much for your effort! Please feel free to ask any questions you may have, without any hesitation. > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +config COMMON_CLK_A1_PLL > > + tristate "Meson A1 SoC PLL controller support" > Should this be "Amlogic A1 SoC PLL controller support"? > My understanding is that the "meson" name was dropped for this > generation of SoCs. > > [...] Yep, that's good point. Will change it in the next version. > > +static const struct of_device_id a1_pll_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-pll-clkc", }, > > + {}, > nit-pick: please drop the comma after {} > This empty entry is a sentinel, no other entries are supposed to come > after this - so a trailing comma is not necessary. > > [...] OK > > +/* PLL register offset */ > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > +#define ANACTRL_FIXPLL_STS 0x14 > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > +#define ANACTRL_HIFIPLL_STS 0xd4 > Here I have a question that will potentially affect patch 3/6 > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > In the cover-letter you mentioned that quite a few clocks have been omitted. > Any dt-bindings that we create need to be stable going forward. That > means: the dt-bindings will always need to describe what the hardware > is capable of, not what the driver implements. > So my question is: do we have all needed inputs described in the > dt-bindings (even though we're omitting quite a few registers here > that will only be added/used in the future)? > Older SoCs require (temporarily) using the XTAL clock for CPU clock > tree changes. To make a long story short: I'm wondering if - at least > - the XTAL clock input is missing. The Amlogic A1 clock engine comprises four clock controllers for peripherals, PLL, CPU, and audio. While the first two have been introduced in the current patch series, the last two will be sent in the next iteration. Presently, the PLL controller driver includes all the required bindings, and the peripherals controller driver has all bindings except for the CPU-related clock. However, I do not believe this to be a significant issue. The clock DT bindings are organized to simplify the process of introducing new bindings, whether public or private. For instance, we may add new bindings to include/dt-bindings at the end of the list and increase the overall number, without disrupting the DT bindings ABI (the old numbers will remain unchanged). > > PS: I don't have an A1 datasheet nor a vendor kernel source (and even > less a board for testing). So I can't verify any of this myself and > I'm asking questions instead. > -- Thank you, Dmitry ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-25 12:33 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:33 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, On Sun, Apr 23, 2023 at 11:12:27PM +0200, Martin Blumenstingl wrote: > Hello Dmitry, > > currently Jerome is busy so I am trying to continue where he left off. > I have followed the previous iterations a bit but may have missed some > details. So apologies if I'm repeating some questions that Jerome > previously asked. > Thank you very much for your effort! Please feel free to ask any questions you may have, without any hesitation. > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +config COMMON_CLK_A1_PLL > > + tristate "Meson A1 SoC PLL controller support" > Should this be "Amlogic A1 SoC PLL controller support"? > My understanding is that the "meson" name was dropped for this > generation of SoCs. > > [...] Yep, that's good point. Will change it in the next version. > > +static const struct of_device_id a1_pll_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-pll-clkc", }, > > + {}, > nit-pick: please drop the comma after {} > This empty entry is a sentinel, no other entries are supposed to come > after this - so a trailing comma is not necessary. > > [...] OK > > +/* PLL register offset */ > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > +#define ANACTRL_FIXPLL_STS 0x14 > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > +#define ANACTRL_HIFIPLL_STS 0xd4 > Here I have a question that will potentially affect patch 3/6 > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > In the cover-letter you mentioned that quite a few clocks have been omitted. > Any dt-bindings that we create need to be stable going forward. That > means: the dt-bindings will always need to describe what the hardware > is capable of, not what the driver implements. > So my question is: do we have all needed inputs described in the > dt-bindings (even though we're omitting quite a few registers here > that will only be added/used in the future)? > Older SoCs require (temporarily) using the XTAL clock for CPU clock > tree changes. To make a long story short: I'm wondering if - at least > - the XTAL clock input is missing. The Amlogic A1 clock engine comprises four clock controllers for peripherals, PLL, CPU, and audio. While the first two have been introduced in the current patch series, the last two will be sent in the next iteration. Presently, the PLL controller driver includes all the required bindings, and the peripherals controller driver has all bindings except for the CPU-related clock. However, I do not believe this to be a significant issue. The clock DT bindings are organized to simplify the process of introducing new bindings, whether public or private. For instance, we may add new bindings to include/dt-bindings at the end of the list and increase the overall number, without disrupting the DT bindings ABI (the old numbers will remain unchanged). > > PS: I don't have an A1 datasheet nor a vendor kernel source (and even > less a board for testing). So I can't verify any of this myself and > I'm asking questions instead. > -- Thank you, Dmitry _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-04-25 12:33 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:33 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, On Sun, Apr 23, 2023 at 11:12:27PM +0200, Martin Blumenstingl wrote: > Hello Dmitry, > > currently Jerome is busy so I am trying to continue where he left off. > I have followed the previous iterations a bit but may have missed some > details. So apologies if I'm repeating some questions that Jerome > previously asked. > Thank you very much for your effort! Please feel free to ask any questions you may have, without any hesitation. > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +config COMMON_CLK_A1_PLL > > + tristate "Meson A1 SoC PLL controller support" > Should this be "Amlogic A1 SoC PLL controller support"? > My understanding is that the "meson" name was dropped for this > generation of SoCs. > > [...] Yep, that's good point. Will change it in the next version. > > +static const struct of_device_id a1_pll_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-pll-clkc", }, > > + {}, > nit-pick: please drop the comma after {} > This empty entry is a sentinel, no other entries are supposed to come > after this - so a trailing comma is not necessary. > > [...] OK > > +/* PLL register offset */ > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > +#define ANACTRL_FIXPLL_STS 0x14 > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > +#define ANACTRL_HIFIPLL_STS 0xd4 > Here I have a question that will potentially affect patch 3/6 > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > In the cover-letter you mentioned that quite a few clocks have been omitted. > Any dt-bindings that we create need to be stable going forward. That > means: the dt-bindings will always need to describe what the hardware > is capable of, not what the driver implements. > So my question is: do we have all needed inputs described in the > dt-bindings (even though we're omitting quite a few registers here > that will only be added/used in the future)? > Older SoCs require (temporarily) using the XTAL clock for CPU clock > tree changes. To make a long story short: I'm wondering if - at least > - the XTAL clock input is missing. The Amlogic A1 clock engine comprises four clock controllers for peripherals, PLL, CPU, and audio. While the first two have been introduced in the current patch series, the last two will be sent in the next iteration. Presently, the PLL controller driver includes all the required bindings, and the peripherals controller driver has all bindings except for the CPU-related clock. However, I do not believe this to be a significant issue. The clock DT bindings are organized to simplify the process of introducing new bindings, whether public or private. For instance, we may add new bindings to include/dt-bindings at the end of the list and increase the overall number, without disrupting the DT bindings ABI (the old numbers will remain unchanged). > > PS: I don't have an A1 datasheet nor a vendor kernel source (and even > less a board for testing). So I can't verify any of this myself and > I'm asking questions instead. > -- Thank you, Dmitry _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-04-25 12:33 ` Dmitry Rokosov (?) @ 2023-05-01 18:39 ` Martin Blumenstingl -1 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-01 18:39 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, (I'm aware you already posted a v14 - but I'm still replying here to continue the discussion on one question I had to keep the context) On Tue, Apr 25, 2023 at 2:33 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > > > +/* PLL register offset */ > > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > > +#define ANACTRL_FIXPLL_STS 0x14 > > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > > +#define ANACTRL_HIFIPLL_STS 0xd4 > > Here I have a question that will potentially affect patch 3/6 > > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > > In the cover-letter you mentioned that quite a few clocks have been omitted. > > Any dt-bindings that we create need to be stable going forward. That > > means: the dt-bindings will always need to describe what the hardware > > is capable of, not what the driver implements. > > So my question is: do we have all needed inputs described in the > > dt-bindings (even though we're omitting quite a few registers here > > that will only be added/used in the future)? > > Older SoCs require (temporarily) using the XTAL clock for CPU clock > > tree changes. To make a long story short: I'm wondering if - at least > > - the XTAL clock input is missing. > > The Amlogic A1 clock engine comprises four clock controllers for > peripherals, PLL, CPU, and audio. While the first two have been > introduced in the current patch series, the last two will be sent in the > next iteration. I (think that I) understand this part. > Presently, the PLL controller driver includes all the required bindings, > and the peripherals controller driver has all bindings except for the > CPU-related clock. Let's stick to the PLL controller bindings for the next part. My understanding is that the PLL clock controller registers (ANACTRL_*) are managing the following clocks: - fixed_pll - sys_pll - hifi_pll - whatever "AUDDDS" is - and some miscellaneous registers like ANACTRL_POR_CNTL and ANACTRL_MISCTOP_CTRL0 I *think* you got the dt-bindings correct: Even though the driver part does not support the hifi_pll yet, this IP block seems to have a "hifipll_in" clock input. Since the dt-bindings describes the hardware it may describe (for example) clock inputs that are not used by the driver yet. If you agree with my statement from above I'll be able to make my original question more specific: Since we know that we have all the required inputs for fixed_pll, sys_pll and hifi_pll - do you know what AUDDDS is and whether it requires any specific clock inputs (other than "fixpll_in" and "hifipll_in")? > However, I do not believe this to be a significant issue. The clock DT > bindings are organized to simplify the process of introducing new bindings, > whether public or private. For instance, we may add new bindings to > include/dt-bindings at the end of the list and increase the overall number, > without disrupting the DT bindings ABI (the old numbers will remain > unchanged). Yep, this part is clear to me. I should have been more specific that I was asking about the inputs that are described in the .yaml file, not the clock IDs. Best regards, Martin ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-01 18:39 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-01 18:39 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, (I'm aware you already posted a v14 - but I'm still replying here to continue the discussion on one question I had to keep the context) On Tue, Apr 25, 2023 at 2:33 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > > > +/* PLL register offset */ > > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > > +#define ANACTRL_FIXPLL_STS 0x14 > > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > > +#define ANACTRL_HIFIPLL_STS 0xd4 > > Here I have a question that will potentially affect patch 3/6 > > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > > In the cover-letter you mentioned that quite a few clocks have been omitted. > > Any dt-bindings that we create need to be stable going forward. That > > means: the dt-bindings will always need to describe what the hardware > > is capable of, not what the driver implements. > > So my question is: do we have all needed inputs described in the > > dt-bindings (even though we're omitting quite a few registers here > > that will only be added/used in the future)? > > Older SoCs require (temporarily) using the XTAL clock for CPU clock > > tree changes. To make a long story short: I'm wondering if - at least > > - the XTAL clock input is missing. > > The Amlogic A1 clock engine comprises four clock controllers for > peripherals, PLL, CPU, and audio. While the first two have been > introduced in the current patch series, the last two will be sent in the > next iteration. I (think that I) understand this part. > Presently, the PLL controller driver includes all the required bindings, > and the peripherals controller driver has all bindings except for the > CPU-related clock. Let's stick to the PLL controller bindings for the next part. My understanding is that the PLL clock controller registers (ANACTRL_*) are managing the following clocks: - fixed_pll - sys_pll - hifi_pll - whatever "AUDDDS" is - and some miscellaneous registers like ANACTRL_POR_CNTL and ANACTRL_MISCTOP_CTRL0 I *think* you got the dt-bindings correct: Even though the driver part does not support the hifi_pll yet, this IP block seems to have a "hifipll_in" clock input. Since the dt-bindings describes the hardware it may describe (for example) clock inputs that are not used by the driver yet. If you agree with my statement from above I'll be able to make my original question more specific: Since we know that we have all the required inputs for fixed_pll, sys_pll and hifi_pll - do you know what AUDDDS is and whether it requires any specific clock inputs (other than "fixpll_in" and "hifipll_in")? > However, I do not believe this to be a significant issue. The clock DT > bindings are organized to simplify the process of introducing new bindings, > whether public or private. For instance, we may add new bindings to > include/dt-bindings at the end of the list and increase the overall number, > without disrupting the DT bindings ABI (the old numbers will remain > unchanged). Yep, this part is clear to me. I should have been more specific that I was asking about the inputs that are described in the .yaml file, not the clock IDs. Best regards, Martin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-01 18:39 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-01 18:39 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, (I'm aware you already posted a v14 - but I'm still replying here to continue the discussion on one question I had to keep the context) On Tue, Apr 25, 2023 at 2:33 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > > > +/* PLL register offset */ > > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > > +#define ANACTRL_FIXPLL_STS 0x14 > > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > > +#define ANACTRL_HIFIPLL_STS 0xd4 > > Here I have a question that will potentially affect patch 3/6 > > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > > In the cover-letter you mentioned that quite a few clocks have been omitted. > > Any dt-bindings that we create need to be stable going forward. That > > means: the dt-bindings will always need to describe what the hardware > > is capable of, not what the driver implements. > > So my question is: do we have all needed inputs described in the > > dt-bindings (even though we're omitting quite a few registers here > > that will only be added/used in the future)? > > Older SoCs require (temporarily) using the XTAL clock for CPU clock > > tree changes. To make a long story short: I'm wondering if - at least > > - the XTAL clock input is missing. > > The Amlogic A1 clock engine comprises four clock controllers for > peripherals, PLL, CPU, and audio. While the first two have been > introduced in the current patch series, the last two will be sent in the > next iteration. I (think that I) understand this part. > Presently, the PLL controller driver includes all the required bindings, > and the peripherals controller driver has all bindings except for the > CPU-related clock. Let's stick to the PLL controller bindings for the next part. My understanding is that the PLL clock controller registers (ANACTRL_*) are managing the following clocks: - fixed_pll - sys_pll - hifi_pll - whatever "AUDDDS" is - and some miscellaneous registers like ANACTRL_POR_CNTL and ANACTRL_MISCTOP_CTRL0 I *think* you got the dt-bindings correct: Even though the driver part does not support the hifi_pll yet, this IP block seems to have a "hifipll_in" clock input. Since the dt-bindings describes the hardware it may describe (for example) clock inputs that are not used by the driver yet. If you agree with my statement from above I'll be able to make my original question more specific: Since we know that we have all the required inputs for fixed_pll, sys_pll and hifi_pll - do you know what AUDDDS is and whether it requires any specific clock inputs (other than "fixpll_in" and "hifipll_in")? > However, I do not believe this to be a significant issue. The clock DT > bindings are organized to simplify the process of introducing new bindings, > whether public or private. For instance, we may add new bindings to > include/dt-bindings at the end of the list and increase the overall number, > without disrupting the DT bindings ABI (the old numbers will remain > unchanged). Yep, this part is clear to me. I should have been more specific that I was asking about the inputs that are described in the .yaml file, not the clock IDs. Best regards, Martin _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-05-01 18:39 ` Martin Blumenstingl @ 2023-05-11 13:26 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-05-11 13:26 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, I apologize for the delayed response as I was on vacation without email access. I hope this is not a problem. On Mon, May 01, 2023 at 08:39:20PM +0200, Martin Blumenstingl wrote: > Hello Dmitry, > > (I'm aware you already posted a v14 - but I'm still replying here to > continue the discussion on one question I had to keep the context) > Sure, please find, my thoughts below. > On Tue, Apr 25, 2023 at 2:33 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > > > +/* PLL register offset */ > > > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > > > +#define ANACTRL_FIXPLL_STS 0x14 > > > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > > > +#define ANACTRL_HIFIPLL_STS 0xd4 > > > Here I have a question that will potentially affect patch 3/6 > > > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > > > In the cover-letter you mentioned that quite a few clocks have been omitted. > > > Any dt-bindings that we create need to be stable going forward. That > > > means: the dt-bindings will always need to describe what the hardware > > > is capable of, not what the driver implements. > > > So my question is: do we have all needed inputs described in the > > > dt-bindings (even though we're omitting quite a few registers here > > > that will only be added/used in the future)? > > > Older SoCs require (temporarily) using the XTAL clock for CPU clock > > > tree changes. To make a long story short: I'm wondering if - at least > > > - the XTAL clock input is missing. > > > > The Amlogic A1 clock engine comprises four clock controllers for > > peripherals, PLL, CPU, and audio. While the first two have been > > introduced in the current patch series, the last two will be sent in the > > next iteration. > I (think that I) understand this part. > > > Presently, the PLL controller driver includes all the required bindings, > > and the peripherals controller driver has all bindings except for the > > CPU-related clock. > Let's stick to the PLL controller bindings for the next part. > My understanding is that the PLL clock controller registers > (ANACTRL_*) are managing the following clocks: > - fixed_pll > - sys_pll > - hifi_pll > - whatever "AUDDDS" is > - and some miscellaneous registers like ANACTRL_POR_CNTL and > ANACTRL_MISCTOP_CTRL0 > > I *think* you got the dt-bindings correct: > Even though the driver part does not support the hifi_pll yet, this IP > block seems to have a "hifipll_in" clock input. > Since the dt-bindings describes the hardware it may describe (for > example) clock inputs that are not used by the driver yet. > > If you agree with my statement from above I'll be able to make my > original question more specific: > Since we know that we have all the required inputs for fixed_pll, > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > requires any specific clock inputs (other than "fixpll_in" and > "hifipll_in")? > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very poor Amlogic datasheets and custom 4.19-based vendor drivers. The vendor driver has an AUDDDS clock in the PLL clock part, but it is not used anywhere. Unfortunately, as usual, the datasheet doesn't provide any information or explanation about what it is. However, the driver has a few lines of comments that indicate: /* * aud dds clock is not pll clock, not divider clock, * No clock model can describe it. * So we regard it as a gate, and the gate ops * should realize lonely. */ Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, but I do not see any relationship with other clocks (including the exported GENCLK). Jian did not include it in the first version of the PLL driver, and I have decided not to change it either. I also noticed a few lines of AUDDDS initialization sequences in the vendor driver, which may affect CPU clock objects (from my point of view). However, they are currently under development, and I will try to figure it out with Amlogic support. > > However, I do not believe this to be a significant issue. The clock DT > > bindings are organized to simplify the process of introducing new bindings, > > whether public or private. For instance, we may add new bindings to > > include/dt-bindings at the end of the list and increase the overall number, > > without disrupting the DT bindings ABI (the old numbers will remain > > unchanged). > Yep, this part is clear to me. I should have been more specific that I > was asking about the inputs that are described in the .yaml file, not > the clock IDs. Actually, AUDDDS has an xtal2dds parent clock, and if we need to have the AUDDDS clock in the PLL driver, we should add one more link between peripherals and PLL drivers. Let me know if you have any questions. -- Thank you, Dmitry _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-11 13:26 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-05-11 13:26 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, I apologize for the delayed response as I was on vacation without email access. I hope this is not a problem. On Mon, May 01, 2023 at 08:39:20PM +0200, Martin Blumenstingl wrote: > Hello Dmitry, > > (I'm aware you already posted a v14 - but I'm still replying here to > continue the discussion on one question I had to keep the context) > Sure, please find, my thoughts below. > On Tue, Apr 25, 2023 at 2:33 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > > > +/* PLL register offset */ > > > > +#define ANACTRL_FIXPLL_CTRL0 0x0 > > > > +#define ANACTRL_FIXPLL_CTRL1 0x4 > > > > +#define ANACTRL_FIXPLL_STS 0x14 > > > > +#define ANACTRL_HIFIPLL_CTRL0 0xc0 > > > > +#define ANACTRL_HIFIPLL_CTRL1 0xc4 > > > > +#define ANACTRL_HIFIPLL_CTRL2 0xc8 > > > > +#define ANACTRL_HIFIPLL_CTRL3 0xcc > > > > +#define ANACTRL_HIFIPLL_CTRL4 0xd0 > > > > +#define ANACTRL_HIFIPLL_STS 0xd4 > > > Here I have a question that will potentially affect patch 3/6 > > > ("dt-bindings: clock: meson: add A1 PLL clock controller bindings"). > > > In the cover-letter you mentioned that quite a few clocks have been omitted. > > > Any dt-bindings that we create need to be stable going forward. That > > > means: the dt-bindings will always need to describe what the hardware > > > is capable of, not what the driver implements. > > > So my question is: do we have all needed inputs described in the > > > dt-bindings (even though we're omitting quite a few registers here > > > that will only be added/used in the future)? > > > Older SoCs require (temporarily) using the XTAL clock for CPU clock > > > tree changes. To make a long story short: I'm wondering if - at least > > > - the XTAL clock input is missing. > > > > The Amlogic A1 clock engine comprises four clock controllers for > > peripherals, PLL, CPU, and audio. While the first two have been > > introduced in the current patch series, the last two will be sent in the > > next iteration. > I (think that I) understand this part. > > > Presently, the PLL controller driver includes all the required bindings, > > and the peripherals controller driver has all bindings except for the > > CPU-related clock. > Let's stick to the PLL controller bindings for the next part. > My understanding is that the PLL clock controller registers > (ANACTRL_*) are managing the following clocks: > - fixed_pll > - sys_pll > - hifi_pll > - whatever "AUDDDS" is > - and some miscellaneous registers like ANACTRL_POR_CNTL and > ANACTRL_MISCTOP_CTRL0 > > I *think* you got the dt-bindings correct: > Even though the driver part does not support the hifi_pll yet, this IP > block seems to have a "hifipll_in" clock input. > Since the dt-bindings describes the hardware it may describe (for > example) clock inputs that are not used by the driver yet. > > If you agree with my statement from above I'll be able to make my > original question more specific: > Since we know that we have all the required inputs for fixed_pll, > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > requires any specific clock inputs (other than "fixpll_in" and > "hifipll_in")? > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very poor Amlogic datasheets and custom 4.19-based vendor drivers. The vendor driver has an AUDDDS clock in the PLL clock part, but it is not used anywhere. Unfortunately, as usual, the datasheet doesn't provide any information or explanation about what it is. However, the driver has a few lines of comments that indicate: /* * aud dds clock is not pll clock, not divider clock, * No clock model can describe it. * So we regard it as a gate, and the gate ops * should realize lonely. */ Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, but I do not see any relationship with other clocks (including the exported GENCLK). Jian did not include it in the first version of the PLL driver, and I have decided not to change it either. I also noticed a few lines of AUDDDS initialization sequences in the vendor driver, which may affect CPU clock objects (from my point of view). However, they are currently under development, and I will try to figure it out with Amlogic support. > > However, I do not believe this to be a significant issue. The clock DT > > bindings are organized to simplify the process of introducing new bindings, > > whether public or private. For instance, we may add new bindings to > > include/dt-bindings at the end of the list and increase the overall number, > > without disrupting the DT bindings ABI (the old numbers will remain > > unchanged). > Yep, this part is clear to me. I should have been more specific that I > was asking about the inputs that are described in the .yaml file, not > the clock IDs. Actually, AUDDDS has an xtal2dds parent clock, and if we need to have the AUDDDS clock in the PLL driver, we should add one more link between peripherals and PLL drivers. Let me know if you have any questions. -- Thank you, Dmitry ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-05-11 13:26 ` Dmitry Rokosov @ 2023-05-14 20:53 ` Martin Blumenstingl -1 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-14 20:53 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hi Dmitry. On Thu, May 11, 2023 at 3:26 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > > If you agree with my statement from above I'll be able to make my > > original question more specific: > > Since we know that we have all the required inputs for fixed_pll, > > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > > requires any specific clock inputs (other than "fixpll_in" and > > "hifipll_in")? > > > > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very > poor Amlogic datasheets and custom 4.19-based vendor drivers. > The vendor driver has an AUDDDS clock in the PLL clock part, but it is not > used anywhere. Unfortunately, as usual, the datasheet doesn't provide any > information or explanation about what it is. However, the driver has a few > lines of comments that indicate: > > /* > * aud dds clock is not pll clock, not divider clock, > * No clock model can describe it. > * So we regard it as a gate, and the gate ops > * should realize lonely. > */ > > Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, > but I do not see any relationship with other clocks (including the exported > GENCLK). > Jian did not include it in the first version of the PLL driver, and I have > decided not to change it either. > > I also noticed a few lines of AUDDDS initialization sequences in the vendor > driver, which may affect CPU clock objects (from my point of view). > However, they are currently under development, and I will try to figure it > out with Amlogic support. > > > > However, I do not believe this to be a significant issue. The clock DT > > > bindings are organized to simplify the process of introducing new bindings, > > > whether public or private. For instance, we may add new bindings to > > > include/dt-bindings at the end of the list and increase the overall number, > > > without disrupting the DT bindings ABI (the old numbers will remain > > > unchanged). > > Yep, this part is clear to me. I should have been more specific that I > > was asking about the inputs that are described in the .yaml file, not > > the clock IDs. > > Actually, AUDDDS has an xtal2dds parent clock, and if we need to have > the AUDDDS clock in the PLL driver, we should add one more link between > peripherals and PLL drivers. > > Let me know if you have any questions. I have no questions - all I can say is that: - I like your approach of clarifying details of the AUDDDS clock with Amlogic - and I fully agree with your conclusion that (depending on what Amlogic says) we need one more link from the PLL driver to the AUDDDS clock Thank you for your persistence with this series, I'm sure it will pay off in the long run! Best regards, Martin ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-14 20:53 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-14 20:53 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hi Dmitry. On Thu, May 11, 2023 at 3:26 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > > If you agree with my statement from above I'll be able to make my > > original question more specific: > > Since we know that we have all the required inputs for fixed_pll, > > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > > requires any specific clock inputs (other than "fixpll_in" and > > "hifipll_in")? > > > > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very > poor Amlogic datasheets and custom 4.19-based vendor drivers. > The vendor driver has an AUDDDS clock in the PLL clock part, but it is not > used anywhere. Unfortunately, as usual, the datasheet doesn't provide any > information or explanation about what it is. However, the driver has a few > lines of comments that indicate: > > /* > * aud dds clock is not pll clock, not divider clock, > * No clock model can describe it. > * So we regard it as a gate, and the gate ops > * should realize lonely. > */ > > Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, > but I do not see any relationship with other clocks (including the exported > GENCLK). > Jian did not include it in the first version of the PLL driver, and I have > decided not to change it either. > > I also noticed a few lines of AUDDDS initialization sequences in the vendor > driver, which may affect CPU clock objects (from my point of view). > However, they are currently under development, and I will try to figure it > out with Amlogic support. > > > > However, I do not believe this to be a significant issue. The clock DT > > > bindings are organized to simplify the process of introducing new bindings, > > > whether public or private. For instance, we may add new bindings to > > > include/dt-bindings at the end of the list and increase the overall number, > > > without disrupting the DT bindings ABI (the old numbers will remain > > > unchanged). > > Yep, this part is clear to me. I should have been more specific that I > > was asking about the inputs that are described in the .yaml file, not > > the clock IDs. > > Actually, AUDDDS has an xtal2dds parent clock, and if we need to have > the AUDDDS clock in the PLL driver, we should add one more link between > peripherals and PLL drivers. > > Let me know if you have any questions. I have no questions - all I can say is that: - I like your approach of clarifying details of the AUDDDS clock with Amlogic - and I fully agree with your conclusion that (depending on what Amlogic says) we need one more link from the PLL driver to the AUDDDS clock Thank you for your persistence with this series, I'm sure it will pay off in the long run! Best regards, Martin _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-05-14 20:53 ` Martin Blumenstingl (?) @ 2023-05-29 13:49 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-05-29 13:49 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, As I promised before, I'm now back with the vendor's reply regarding AUDDDS. The information is still incomplete, but I have provided the available details below. Please take a look. On Sun, May 14, 2023 at 10:53:53PM +0200, Martin Blumenstingl wrote: > Hi Dmitry. > > On Thu, May 11, 2023 at 3:26 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > > If you agree with my statement from above I'll be able to make my > > > original question more specific: > > > Since we know that we have all the required inputs for fixed_pll, > > > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > > > requires any specific clock inputs (other than "fixpll_in" and > > > "hifipll_in")? > > > > > > > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very > > poor Amlogic datasheets and custom 4.19-based vendor drivers. > > The vendor driver has an AUDDDS clock in the PLL clock part, but it is not > > used anywhere. Unfortunately, as usual, the datasheet doesn't provide any > > information or explanation about what it is. However, the driver has a few > > lines of comments that indicate: > > > > /* > > * aud dds clock is not pll clock, not divider clock, > > * No clock model can describe it. > > * So we regard it as a gate, and the gate ops > > * should realize lonely. > > */ > > > > Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, > > but I do not see any relationship with other clocks (including the exported > > GENCLK). > > Jian did not include it in the first version of the PLL driver, and I have > > decided not to change it either. > > > > I also noticed a few lines of AUDDDS initialization sequences in the vendor > > driver, which may affect CPU clock objects (from my point of view). > > However, they are currently under development, and I will try to figure it > > out with Amlogic support. > > > > > > However, I do not believe this to be a significant issue. The clock DT > > > > bindings are organized to simplify the process of introducing new bindings, > > > > whether public or private. For instance, we may add new bindings to > > > > include/dt-bindings at the end of the list and increase the overall number, > > > > without disrupting the DT bindings ABI (the old numbers will remain > > > > unchanged). > > > Yep, this part is clear to me. I should have been more specific that I > > > was asking about the inputs that are described in the .yaml file, not > > > the clock IDs. > > > > Actually, AUDDDS has an xtal2dds parent clock, and if we need to have > > the AUDDDS clock in the PLL driver, we should add one more link between > > peripherals and PLL drivers. > > > > Let me know if you have any questions. > I have no questions - all I can say is that: > - I like your approach of clarifying details of the AUDDDS clock with Amlogic > - and I fully agree with your conclusion that (depending on what > Amlogic says) we need one more link from the PLL driver to the AUDDDS > clock > > Thank you for your persistence with this series, I'm sure it will pay > off in the long run! AUDDDS is a direct digital synthesizer used as a clock source. It is not used as default. You need to modify some clk registers in dts to enable it. Basically, it is used for audio. In A1 design, you can use AUD DDS as a clock source and it is not necessary. It is not used in the Amlogic default setting. According to the vendor, it is not necessary and is currently disabled by default. While we don't have much information about AUDDDS, the vendor suggests that it's not a commonly used clock object in A1 projects and it may be skipped if not needed. Based on all above information, I suppose we can skip it now. -- Thank you, Dmitry ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-29 13:49 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-05-29 13:49 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, As I promised before, I'm now back with the vendor's reply regarding AUDDDS. The information is still incomplete, but I have provided the available details below. Please take a look. On Sun, May 14, 2023 at 10:53:53PM +0200, Martin Blumenstingl wrote: > Hi Dmitry. > > On Thu, May 11, 2023 at 3:26 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > > If you agree with my statement from above I'll be able to make my > > > original question more specific: > > > Since we know that we have all the required inputs for fixed_pll, > > > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > > > requires any specific clock inputs (other than "fixpll_in" and > > > "hifipll_in")? > > > > > > > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very > > poor Amlogic datasheets and custom 4.19-based vendor drivers. > > The vendor driver has an AUDDDS clock in the PLL clock part, but it is not > > used anywhere. Unfortunately, as usual, the datasheet doesn't provide any > > information or explanation about what it is. However, the driver has a few > > lines of comments that indicate: > > > > /* > > * aud dds clock is not pll clock, not divider clock, > > * No clock model can describe it. > > * So we regard it as a gate, and the gate ops > > * should realize lonely. > > */ > > > > Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, > > but I do not see any relationship with other clocks (including the exported > > GENCLK). > > Jian did not include it in the first version of the PLL driver, and I have > > decided not to change it either. > > > > I also noticed a few lines of AUDDDS initialization sequences in the vendor > > driver, which may affect CPU clock objects (from my point of view). > > However, they are currently under development, and I will try to figure it > > out with Amlogic support. > > > > > > However, I do not believe this to be a significant issue. The clock DT > > > > bindings are organized to simplify the process of introducing new bindings, > > > > whether public or private. For instance, we may add new bindings to > > > > include/dt-bindings at the end of the list and increase the overall number, > > > > without disrupting the DT bindings ABI (the old numbers will remain > > > > unchanged). > > > Yep, this part is clear to me. I should have been more specific that I > > > was asking about the inputs that are described in the .yaml file, not > > > the clock IDs. > > > > Actually, AUDDDS has an xtal2dds parent clock, and if we need to have > > the AUDDDS clock in the PLL driver, we should add one more link between > > peripherals and PLL drivers. > > > > Let me know if you have any questions. > I have no questions - all I can say is that: > - I like your approach of clarifying details of the AUDDDS clock with Amlogic > - and I fully agree with your conclusion that (depending on what > Amlogic says) we need one more link from the PLL driver to the AUDDDS > clock > > Thank you for your persistence with this series, I'm sure it will pay > off in the long run! AUDDDS is a direct digital synthesizer used as a clock source. It is not used as default. You need to modify some clk registers in dts to enable it. Basically, it is used for audio. In A1 design, you can use AUD DDS as a clock source and it is not necessary. It is not used in the Amlogic default setting. According to the vendor, it is not necessary and is currently disabled by default. While we don't have much information about AUDDDS, the vendor suggests that it's not a commonly used clock object in A1 projects and it may be skipped if not needed. Based on all above information, I suppose we can skip it now. -- Thank you, Dmitry _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-29 13:49 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-05-29 13:49 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Martin, As I promised before, I'm now back with the vendor's reply regarding AUDDDS. The information is still incomplete, but I have provided the available details below. Please take a look. On Sun, May 14, 2023 at 10:53:53PM +0200, Martin Blumenstingl wrote: > Hi Dmitry. > > On Thu, May 11, 2023 at 3:26 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > > If you agree with my statement from above I'll be able to make my > > > original question more specific: > > > Since we know that we have all the required inputs for fixed_pll, > > > sys_pll and hifi_pll - do you know what AUDDDS is and whether it > > > requires any specific clock inputs (other than "fixpll_in" and > > > "hifipll_in")? > > > > > > > To be honest, I have prepared A1 peripherals and A1 PLL drivers based on very > > poor Amlogic datasheets and custom 4.19-based vendor drivers. > > The vendor driver has an AUDDDS clock in the PLL clock part, but it is not > > used anywhere. Unfortunately, as usual, the datasheet doesn't provide any > > information or explanation about what it is. However, the driver has a few > > lines of comments that indicate: > > > > /* > > * aud dds clock is not pll clock, not divider clock, > > * No clock model can describe it. > > * So we regard it as a gate, and the gate ops > > * should realize lonely. > > */ > > > > Additionally, the vendor driver states that AUDDDS has a 49Mhz clock, > > but I do not see any relationship with other clocks (including the exported > > GENCLK). > > Jian did not include it in the first version of the PLL driver, and I have > > decided not to change it either. > > > > I also noticed a few lines of AUDDDS initialization sequences in the vendor > > driver, which may affect CPU clock objects (from my point of view). > > However, they are currently under development, and I will try to figure it > > out with Amlogic support. > > > > > > However, I do not believe this to be a significant issue. The clock DT > > > > bindings are organized to simplify the process of introducing new bindings, > > > > whether public or private. For instance, we may add new bindings to > > > > include/dt-bindings at the end of the list and increase the overall number, > > > > without disrupting the DT bindings ABI (the old numbers will remain > > > > unchanged). > > > Yep, this part is clear to me. I should have been more specific that I > > > was asking about the inputs that are described in the .yaml file, not > > > the clock IDs. > > > > Actually, AUDDDS has an xtal2dds parent clock, and if we need to have > > the AUDDDS clock in the PLL driver, we should add one more link between > > peripherals and PLL drivers. > > > > Let me know if you have any questions. > I have no questions - all I can say is that: > - I like your approach of clarifying details of the AUDDDS clock with Amlogic > - and I fully agree with your conclusion that (depending on what > Amlogic says) we need one more link from the PLL driver to the AUDDDS > clock > > Thank you for your persistence with this series, I'm sure it will pay > off in the long run! AUDDDS is a direct digital synthesizer used as a clock source. It is not used as default. You need to modify some clk registers in dts to enable it. Basically, it is used for audio. In A1 design, you can use AUD DDS as a clock source and it is not necessary. It is not used in the Amlogic default setting. According to the vendor, it is not necessary and is currently disabled by default. While we don't have much information about AUDDDS, the vendor suggests that it's not a commonly used clock object in A1 projects and it may be skipped if not needed. Based on all above information, I suppose we can skip it now. -- Thank you, Dmitry _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver 2023-05-29 13:49 ` Dmitry Rokosov (?) @ 2023-05-29 20:23 ` Martin Blumenstingl -1 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-29 20:23 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, On Mon, May 29, 2023 at 3:49 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > > Hello Martin, > > As I promised before, I'm now back with the vendor's reply regarding > AUDDDS. The information is still incomplete, but I have provided the > available details below. Please take a look. Great, thank you for following up! [...] > AUDDDS is a direct digital synthesizer used as a clock source. It is > not used as default. You need to modify some clk registers in dts to > enable it. Basically, it is used for audio. > > In A1 design, you can use AUD DDS as a clock source and it is not > necessary. It is not used in the Amlogic default setting. > > According to the vendor, it is not necessary and is currently disabled > by default. While we don't have much information about AUDDDS, the > vendor suggests that it's not a commonly used clock object in A1 > projects and it may be skipped if not needed. My goal is to make the dt-bindings match the hardware implementation... > Based on all above information, I suppose we can skip it now. ...but in this case we simply don't have enough information (other than some register names and a high level description that it can be used as a clock) to do that. I still think we did the best we could for now, so I agree with you: let's skip it for now (and hope that retrofitting it later - if we ever need it - won't be a problem). Best regards, Martin ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-29 20:23 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-29 20:23 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, On Mon, May 29, 2023 at 3:49 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > > Hello Martin, > > As I promised before, I'm now back with the vendor's reply regarding > AUDDDS. The information is still incomplete, but I have provided the > available details below. Please take a look. Great, thank you for following up! [...] > AUDDDS is a direct digital synthesizer used as a clock source. It is > not used as default. You need to modify some clk registers in dts to > enable it. Basically, it is used for audio. > > In A1 design, you can use AUD DDS as a clock source and it is not > necessary. It is not used in the Amlogic default setting. > > According to the vendor, it is not necessary and is currently disabled > by default. While we don't have much information about AUDDDS, the > vendor suggests that it's not a commonly used clock object in A1 > projects and it may be skipped if not needed. My goal is to make the dt-bindings match the hardware implementation... > Based on all above information, I suppose we can skip it now. ...but in this case we simply don't have enough information (other than some register names and a high level description that it can be used as a clock) to do that. I still think we did the best we could for now, so I agree with you: let's skip it for now (and hope that retrofitting it later - if we ever need it - won't be a problem). Best regards, Martin _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver @ 2023-05-29 20:23 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-05-29 20:23 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel Hello Dmitry, On Mon, May 29, 2023 at 3:49 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > > Hello Martin, > > As I promised before, I'm now back with the vendor's reply regarding > AUDDDS. The information is still incomplete, but I have provided the > available details below. Please take a look. Great, thank you for following up! [...] > AUDDDS is a direct digital synthesizer used as a clock source. It is > not used as default. You need to modify some clk registers in dts to > enable it. Basically, it is used for audio. > > In A1 design, you can use AUD DDS as a clock source and it is not > necessary. It is not used in the Amlogic default setting. > > According to the vendor, it is not necessary and is currently disabled > by default. While we don't have much information about AUDDDS, the > vendor suggests that it's not a commonly used clock object in A1 > projects and it may be skipped if not needed. My goal is to make the dt-bindings match the hardware implementation... > Based on all above information, I suppose we can skip it now. ...but in this case we simply don't have enough information (other than some register names and a high level description that it can be used as a clock) to do that. I still think we did the best we could for now, so I agree with you: let's skip it for now (and hope that retrofitting it later - if we ever need it - won't be a problem). Best regards, Martin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 Peripherals clock driver, and A1 Peripherals clock controller bindings. A1 PLL clock controller has references to A1 Peripherals clock controller objects, so reflect them in the schema. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml new file mode 100644 index 000000000000..cb6d8f4eb959 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials Peripheral Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixed pll div2 + - description: input fixed pll div3 + - description: input fixed pll div5 + - description: input fixed pll div7 + - description: input hifi pll + - description: input oscillator (usually at 24MHz) + + clock-names: + items: + - const: fclk_div2 + - const: fclk_div3 + - const: fclk_div5 + - const: fclk_div7 + - const: hifi_pll + - const: xtal + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@800 { + compatible = "amlogic,a1-clkc"; + reg = <0 0x800 0 0x104>; + #clock-cells = <1>; + clocks = <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_DIV3>, + <&clkc_pll CLKID_FCLK_DIV5>, + <&clkc_pll CLKID_FCLK_DIV7>, + <&clkc_pll CLKID_HIFI_PLL>, + <&xtal>; + clock-names = "fclk_div2", "fclk_div3", + "fclk_div5", "fclk_div7", + "hifi_pll", "xtal"; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml index b3f46cf4b161..77a13b1f9d5a 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -43,6 +43,7 @@ additionalProperties: false examples: - | + #include <dt-bindings/clock/amlogic,a1-clkc.h> apb { #address-cells = <2>; #size-cells = <2>; @@ -51,8 +52,8 @@ examples: compatible = "amlogic,a1-pll-clkc"; reg = <0 0x7c80 0 0x18c>; #clock-cells = <1>; - clocks = <&clkc_periphs_fixpll_in>, - <&clkc_periphs_hifipll_in>; + clocks = <&clkc_periphs CLKID_FIXPLL_IN>, + <&clkc_periphs CLKID_HIFIPLL_IN>; clock-names = "fixpll_in", "hifipll_in"; }; }; diff --git a/include/dt-bindings/clock/amlogic,a1-clkc.h b/include/dt-bindings/clock/amlogic,a1-clkc.h new file mode 100644 index 000000000000..2c6221f2dc6b --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-clkc.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_CLKC_H +#define __A1_CLKC_H + +#define CLKID_FIXPLL_IN 1 +#define CLKID_USB_PHY_IN 2 +#define CLKID_USB_CTRL_IN 3 +#define CLKID_HIFIPLL_IN 4 +#define CLKID_SYSPLL_IN 5 +#define CLKID_DDS_IN 6 +#define CLKID_SYS 7 +#define CLKID_CLKTREE 8 +#define CLKID_RESET_CTRL 9 +#define CLKID_ANALOG_CTRL 10 +#define CLKID_PWR_CTRL 11 +#define CLKID_PAD_CTRL 12 +#define CLKID_SYS_CTRL 13 +#define CLKID_TEMP_SENSOR 14 +#define CLKID_AM2AXI_DIV 15 +#define CLKID_SPICC_B 16 +#define CLKID_SPICC_A 17 +#define CLKID_MSR 18 +#define CLKID_AUDIO 19 +#define CLKID_JTAG_CTRL 20 +#define CLKID_SARADC_EN 21 +#define CLKID_PWM_EF 22 +#define CLKID_PWM_CD 23 +#define CLKID_PWM_AB 24 +#define CLKID_CEC 25 +#define CLKID_I2C_S 26 +#define CLKID_IR_CTRL 27 +#define CLKID_I2C_M_D 28 +#define CLKID_I2C_M_C 29 +#define CLKID_I2C_M_B 30 +#define CLKID_I2C_M_A 31 +#define CLKID_ACODEC 32 +#define CLKID_OTP 33 +#define CLKID_SD_EMMC_A 34 +#define CLKID_USB_PHY 35 +#define CLKID_USB_CTRL 36 +#define CLKID_SYS_DSPB 37 +#define CLKID_SYS_DSPA 38 +#define CLKID_DMA 39 +#define CLKID_IRQ_CTRL 40 +#define CLKID_NIC 41 +#define CLKID_GIC 42 +#define CLKID_UART_C 43 +#define CLKID_UART_B 44 +#define CLKID_UART_A 45 +#define CLKID_SYS_PSRAM 46 +#define CLKID_RSA 47 +#define CLKID_CORESIGHT 48 +#define CLKID_AM2AXI_VAD 49 +#define CLKID_AUDIO_VAD 50 +#define CLKID_AXI_DMC 51 +#define CLKID_AXI_PSRAM 52 +#define CLKID_RAMB 53 +#define CLKID_RAMA 54 +#define CLKID_AXI_SPIFC 55 +#define CLKID_AXI_NIC 56 +#define CLKID_AXI_DMA 57 +#define CLKID_CPU_CTRL 58 +#define CLKID_ROM 59 +#define CLKID_PROC_I2C 60 +#define CLKID_DSPA_EN 63 +#define CLKID_DSPA_EN_NIC 64 +#define CLKID_DSPB_EN 65 +#define CLKID_DSPB_EN_NIC 66 +#define CLKID_RTC 67 +#define CLKID_CECA_32K 68 +#define CLKID_CECB_32K 69 +#define CLKID_24M 70 +#define CLKID_12M 71 +#define CLKID_FCLK_DIV2_DIVN 72 +#define CLKID_GEN 73 +#define CLKID_SARADC 75 +#define CLKID_PWM_A 76 +#define CLKID_PWM_B 77 +#define CLKID_PWM_C 78 +#define CLKID_PWM_D 79 +#define CLKID_PWM_E 80 +#define CLKID_PWM_F 81 +#define CLKID_SPICC 82 +#define CLKID_TS 83 +#define CLKID_SPIFC 84 +#define CLKID_USB_BUS 85 +#define CLKID_SD_EMMC 86 +#define CLKID_PSRAM 87 +#define CLKID_DMC 88 +#define CLKID_DSPA_A_SEL 95 +#define CLKID_DSPA_B_SEL 98 +#define CLKID_DSPB_A_SEL 101 +#define CLKID_DSPB_B_SEL 104 +#define CLKID_CECB_32K_SEL_PRE 113 +#define CLKID_CECB_32K_SEL 114 +#define CLKID_CECA_32K_SEL_PRE 117 +#define CLKID_CECA_32K_SEL 118 +#define CLKID_GEN_SEL 121 +#define CLKID_PWM_A_SEL 124 +#define CLKID_PWM_B_SEL 126 +#define CLKID_PWM_C_SEL 128 +#define CLKID_PWM_D_SEL 130 +#define CLKID_PWM_E_SEL 132 +#define CLKID_PWM_F_SEL 134 + +#endif /* __A1_CLKC_H */ -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 Peripherals clock driver, and A1 Peripherals clock controller bindings. A1 PLL clock controller has references to A1 Peripherals clock controller objects, so reflect them in the schema. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml new file mode 100644 index 000000000000..cb6d8f4eb959 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials Peripheral Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixed pll div2 + - description: input fixed pll div3 + - description: input fixed pll div5 + - description: input fixed pll div7 + - description: input hifi pll + - description: input oscillator (usually at 24MHz) + + clock-names: + items: + - const: fclk_div2 + - const: fclk_div3 + - const: fclk_div5 + - const: fclk_div7 + - const: hifi_pll + - const: xtal + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@800 { + compatible = "amlogic,a1-clkc"; + reg = <0 0x800 0 0x104>; + #clock-cells = <1>; + clocks = <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_DIV3>, + <&clkc_pll CLKID_FCLK_DIV5>, + <&clkc_pll CLKID_FCLK_DIV7>, + <&clkc_pll CLKID_HIFI_PLL>, + <&xtal>; + clock-names = "fclk_div2", "fclk_div3", + "fclk_div5", "fclk_div7", + "hifi_pll", "xtal"; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml index b3f46cf4b161..77a13b1f9d5a 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -43,6 +43,7 @@ additionalProperties: false examples: - | + #include <dt-bindings/clock/amlogic,a1-clkc.h> apb { #address-cells = <2>; #size-cells = <2>; @@ -51,8 +52,8 @@ examples: compatible = "amlogic,a1-pll-clkc"; reg = <0 0x7c80 0 0x18c>; #clock-cells = <1>; - clocks = <&clkc_periphs_fixpll_in>, - <&clkc_periphs_hifipll_in>; + clocks = <&clkc_periphs CLKID_FIXPLL_IN>, + <&clkc_periphs CLKID_HIFIPLL_IN>; clock-names = "fixpll_in", "hifipll_in"; }; }; diff --git a/include/dt-bindings/clock/amlogic,a1-clkc.h b/include/dt-bindings/clock/amlogic,a1-clkc.h new file mode 100644 index 000000000000..2c6221f2dc6b --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-clkc.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_CLKC_H +#define __A1_CLKC_H + +#define CLKID_FIXPLL_IN 1 +#define CLKID_USB_PHY_IN 2 +#define CLKID_USB_CTRL_IN 3 +#define CLKID_HIFIPLL_IN 4 +#define CLKID_SYSPLL_IN 5 +#define CLKID_DDS_IN 6 +#define CLKID_SYS 7 +#define CLKID_CLKTREE 8 +#define CLKID_RESET_CTRL 9 +#define CLKID_ANALOG_CTRL 10 +#define CLKID_PWR_CTRL 11 +#define CLKID_PAD_CTRL 12 +#define CLKID_SYS_CTRL 13 +#define CLKID_TEMP_SENSOR 14 +#define CLKID_AM2AXI_DIV 15 +#define CLKID_SPICC_B 16 +#define CLKID_SPICC_A 17 +#define CLKID_MSR 18 +#define CLKID_AUDIO 19 +#define CLKID_JTAG_CTRL 20 +#define CLKID_SARADC_EN 21 +#define CLKID_PWM_EF 22 +#define CLKID_PWM_CD 23 +#define CLKID_PWM_AB 24 +#define CLKID_CEC 25 +#define CLKID_I2C_S 26 +#define CLKID_IR_CTRL 27 +#define CLKID_I2C_M_D 28 +#define CLKID_I2C_M_C 29 +#define CLKID_I2C_M_B 30 +#define CLKID_I2C_M_A 31 +#define CLKID_ACODEC 32 +#define CLKID_OTP 33 +#define CLKID_SD_EMMC_A 34 +#define CLKID_USB_PHY 35 +#define CLKID_USB_CTRL 36 +#define CLKID_SYS_DSPB 37 +#define CLKID_SYS_DSPA 38 +#define CLKID_DMA 39 +#define CLKID_IRQ_CTRL 40 +#define CLKID_NIC 41 +#define CLKID_GIC 42 +#define CLKID_UART_C 43 +#define CLKID_UART_B 44 +#define CLKID_UART_A 45 +#define CLKID_SYS_PSRAM 46 +#define CLKID_RSA 47 +#define CLKID_CORESIGHT 48 +#define CLKID_AM2AXI_VAD 49 +#define CLKID_AUDIO_VAD 50 +#define CLKID_AXI_DMC 51 +#define CLKID_AXI_PSRAM 52 +#define CLKID_RAMB 53 +#define CLKID_RAMA 54 +#define CLKID_AXI_SPIFC 55 +#define CLKID_AXI_NIC 56 +#define CLKID_AXI_DMA 57 +#define CLKID_CPU_CTRL 58 +#define CLKID_ROM 59 +#define CLKID_PROC_I2C 60 +#define CLKID_DSPA_EN 63 +#define CLKID_DSPA_EN_NIC 64 +#define CLKID_DSPB_EN 65 +#define CLKID_DSPB_EN_NIC 66 +#define CLKID_RTC 67 +#define CLKID_CECA_32K 68 +#define CLKID_CECB_32K 69 +#define CLKID_24M 70 +#define CLKID_12M 71 +#define CLKID_FCLK_DIV2_DIVN 72 +#define CLKID_GEN 73 +#define CLKID_SARADC 75 +#define CLKID_PWM_A 76 +#define CLKID_PWM_B 77 +#define CLKID_PWM_C 78 +#define CLKID_PWM_D 79 +#define CLKID_PWM_E 80 +#define CLKID_PWM_F 81 +#define CLKID_SPICC 82 +#define CLKID_TS 83 +#define CLKID_SPIFC 84 +#define CLKID_USB_BUS 85 +#define CLKID_SD_EMMC 86 +#define CLKID_PSRAM 87 +#define CLKID_DMC 88 +#define CLKID_DSPA_A_SEL 95 +#define CLKID_DSPA_B_SEL 98 +#define CLKID_DSPB_A_SEL 101 +#define CLKID_DSPB_B_SEL 104 +#define CLKID_CECB_32K_SEL_PRE 113 +#define CLKID_CECB_32K_SEL 114 +#define CLKID_CECA_32K_SEL_PRE 117 +#define CLKID_CECA_32K_SEL 118 +#define CLKID_GEN_SEL 121 +#define CLKID_PWM_A_SEL 124 +#define CLKID_PWM_B_SEL 126 +#define CLKID_PWM_C_SEL 128 +#define CLKID_PWM_D_SEL 130 +#define CLKID_PWM_E_SEL 132 +#define CLKID_PWM_F_SEL 134 + +#endif /* __A1_CLKC_H */ -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Add the documentation for Amlogic A1 Peripherals clock driver, and A1 Peripherals clock controller bindings. A1 PLL clock controller has references to A1 Peripherals clock controller objects, so reflect them in the schema. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml new file mode 100644 index 000000000000..cb6d8f4eb959 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/amlogic,a1-clkc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Amlogic Meson A/C serials Peripheral Clock Control Unit + +maintainers: + - Neil Armstrong <neil.armstrong@linaro.org> + - Jerome Brunet <jbrunet@baylibre.com> + - Jian Hu <jian.hu@jian.hu.com> + - Dmitry Rokosov <ddrokosov@sberdevices.ru> + +properties: + compatible: + const: amlogic,a1-clkc + + '#clock-cells': + const: 1 + + reg: + maxItems: 1 + + clocks: + items: + - description: input fixed pll div2 + - description: input fixed pll div3 + - description: input fixed pll div5 + - description: input fixed pll div7 + - description: input hifi pll + - description: input oscillator (usually at 24MHz) + + clock-names: + items: + - const: fclk_div2 + - const: fclk_div3 + - const: fclk_div5 + - const: fclk_div7 + - const: hifi_pll + - const: xtal + +required: + - compatible + - '#clock-cells' + - reg + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/clock/amlogic,a1-pll-clkc.h> + apb { + #address-cells = <2>; + #size-cells = <2>; + + clock-controller@800 { + compatible = "amlogic,a1-clkc"; + reg = <0 0x800 0 0x104>; + #clock-cells = <1>; + clocks = <&clkc_pll CLKID_FCLK_DIV2>, + <&clkc_pll CLKID_FCLK_DIV3>, + <&clkc_pll CLKID_FCLK_DIV5>, + <&clkc_pll CLKID_FCLK_DIV7>, + <&clkc_pll CLKID_HIFI_PLL>, + <&xtal>; + clock-names = "fclk_div2", "fclk_div3", + "fclk_div5", "fclk_div7", + "hifi_pll", "xtal"; + }; + }; diff --git a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml index b3f46cf4b161..77a13b1f9d5a 100644 --- a/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml +++ b/Documentation/devicetree/bindings/clock/amlogic,a1-pll-clkc.yaml @@ -43,6 +43,7 @@ additionalProperties: false examples: - | + #include <dt-bindings/clock/amlogic,a1-clkc.h> apb { #address-cells = <2>; #size-cells = <2>; @@ -51,8 +52,8 @@ examples: compatible = "amlogic,a1-pll-clkc"; reg = <0 0x7c80 0 0x18c>; #clock-cells = <1>; - clocks = <&clkc_periphs_fixpll_in>, - <&clkc_periphs_hifipll_in>; + clocks = <&clkc_periphs CLKID_FIXPLL_IN>, + <&clkc_periphs CLKID_HIFIPLL_IN>; clock-names = "fixpll_in", "hifipll_in"; }; }; diff --git a/include/dt-bindings/clock/amlogic,a1-clkc.h b/include/dt-bindings/clock/amlogic,a1-clkc.h new file mode 100644 index 000000000000..2c6221f2dc6b --- /dev/null +++ b/include/dt-bindings/clock/amlogic,a1-clkc.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_CLKC_H +#define __A1_CLKC_H + +#define CLKID_FIXPLL_IN 1 +#define CLKID_USB_PHY_IN 2 +#define CLKID_USB_CTRL_IN 3 +#define CLKID_HIFIPLL_IN 4 +#define CLKID_SYSPLL_IN 5 +#define CLKID_DDS_IN 6 +#define CLKID_SYS 7 +#define CLKID_CLKTREE 8 +#define CLKID_RESET_CTRL 9 +#define CLKID_ANALOG_CTRL 10 +#define CLKID_PWR_CTRL 11 +#define CLKID_PAD_CTRL 12 +#define CLKID_SYS_CTRL 13 +#define CLKID_TEMP_SENSOR 14 +#define CLKID_AM2AXI_DIV 15 +#define CLKID_SPICC_B 16 +#define CLKID_SPICC_A 17 +#define CLKID_MSR 18 +#define CLKID_AUDIO 19 +#define CLKID_JTAG_CTRL 20 +#define CLKID_SARADC_EN 21 +#define CLKID_PWM_EF 22 +#define CLKID_PWM_CD 23 +#define CLKID_PWM_AB 24 +#define CLKID_CEC 25 +#define CLKID_I2C_S 26 +#define CLKID_IR_CTRL 27 +#define CLKID_I2C_M_D 28 +#define CLKID_I2C_M_C 29 +#define CLKID_I2C_M_B 30 +#define CLKID_I2C_M_A 31 +#define CLKID_ACODEC 32 +#define CLKID_OTP 33 +#define CLKID_SD_EMMC_A 34 +#define CLKID_USB_PHY 35 +#define CLKID_USB_CTRL 36 +#define CLKID_SYS_DSPB 37 +#define CLKID_SYS_DSPA 38 +#define CLKID_DMA 39 +#define CLKID_IRQ_CTRL 40 +#define CLKID_NIC 41 +#define CLKID_GIC 42 +#define CLKID_UART_C 43 +#define CLKID_UART_B 44 +#define CLKID_UART_A 45 +#define CLKID_SYS_PSRAM 46 +#define CLKID_RSA 47 +#define CLKID_CORESIGHT 48 +#define CLKID_AM2AXI_VAD 49 +#define CLKID_AUDIO_VAD 50 +#define CLKID_AXI_DMC 51 +#define CLKID_AXI_PSRAM 52 +#define CLKID_RAMB 53 +#define CLKID_RAMA 54 +#define CLKID_AXI_SPIFC 55 +#define CLKID_AXI_NIC 56 +#define CLKID_AXI_DMA 57 +#define CLKID_CPU_CTRL 58 +#define CLKID_ROM 59 +#define CLKID_PROC_I2C 60 +#define CLKID_DSPA_EN 63 +#define CLKID_DSPA_EN_NIC 64 +#define CLKID_DSPB_EN 65 +#define CLKID_DSPB_EN_NIC 66 +#define CLKID_RTC 67 +#define CLKID_CECA_32K 68 +#define CLKID_CECB_32K 69 +#define CLKID_24M 70 +#define CLKID_12M 71 +#define CLKID_FCLK_DIV2_DIVN 72 +#define CLKID_GEN 73 +#define CLKID_SARADC 75 +#define CLKID_PWM_A 76 +#define CLKID_PWM_B 77 +#define CLKID_PWM_C 78 +#define CLKID_PWM_D 79 +#define CLKID_PWM_E 80 +#define CLKID_PWM_F 81 +#define CLKID_SPICC 82 +#define CLKID_TS 83 +#define CLKID_SPIFC 84 +#define CLKID_USB_BUS 85 +#define CLKID_SD_EMMC 86 +#define CLKID_PSRAM 87 +#define CLKID_DMC 88 +#define CLKID_DSPA_A_SEL 95 +#define CLKID_DSPA_B_SEL 98 +#define CLKID_DSPB_A_SEL 101 +#define CLKID_DSPB_B_SEL 104 +#define CLKID_CECB_32K_SEL_PRE 113 +#define CLKID_CECB_32K_SEL 114 +#define CLKID_CECA_32K_SEL_PRE 117 +#define CLKID_CECA_32K_SEL 118 +#define CLKID_GEN_SEL 121 +#define CLKID_PWM_A_SEL 124 +#define CLKID_PWM_B_SEL 126 +#define CLKID_PWM_C_SEL 128 +#define CLKID_PWM_D_SEL 130 +#define CLKID_PWM_E_SEL 132 +#define CLKID_PWM_F_SEL 134 + +#endif /* __A1_CLKC_H */ -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* Re: [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-12 13:46 ` Rob Herring -1 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: devicetree, robh+dt, linux-clk, khilman, mturquette, kernel, martin.blumenstingl, linux-arm-kernel, krzysztof.kozlowski+dt, sboyd, rockosov, linux-amlogic, linux-kernel, jbrunet, jian.hu, neil.armstrong On Wed, 05 Apr 2023 22:59:26 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 Peripherals clock driver, > and A1 Peripherals clock controller bindings. > A1 PLL clock controller has references to A1 Peripherals clock > controller objects, so reflect them in the schema. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- > include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ > 3 files changed, 190 insertions(+), 2 deletions(-) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings @ 2023-04-12 13:46 ` Rob Herring 0 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: devicetree, robh+dt, linux-clk, khilman, mturquette, kernel, martin.blumenstingl, linux-arm-kernel, krzysztof.kozlowski+dt, sboyd, rockosov, linux-amlogic, linux-kernel, jbrunet, jian.hu, neil.armstrong On Wed, 05 Apr 2023 22:59:26 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 Peripherals clock driver, > and A1 Peripherals clock controller bindings. > A1 PLL clock controller has references to A1 Peripherals clock > controller objects, so reflect them in the schema. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- > include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ > 3 files changed, 190 insertions(+), 2 deletions(-) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings @ 2023-04-12 13:46 ` Rob Herring 0 siblings, 0 replies; 52+ messages in thread From: Rob Herring @ 2023-04-12 13:46 UTC (permalink / raw) To: Dmitry Rokosov Cc: devicetree, robh+dt, linux-clk, khilman, mturquette, kernel, martin.blumenstingl, linux-arm-kernel, krzysztof.kozlowski+dt, sboyd, rockosov, linux-amlogic, linux-kernel, jbrunet, jian.hu, neil.armstrong On Wed, 05 Apr 2023 22:59:26 +0300, Dmitry Rokosov wrote: > Add the documentation for Amlogic A1 Peripherals clock driver, > and A1 Peripherals clock controller bindings. > A1 PLL clock controller has references to A1 Peripherals clock > controller objects, so reflect them in the schema. > > Signed-off-by: Jian Hu <jian.hu@amlogic.com> > Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> > --- > .../bindings/clock/amlogic,a1-clkc.yaml | 73 +++++++++++ > .../bindings/clock/amlogic,a1-pll-clkc.yaml | 5 +- > include/dt-bindings/clock/amlogic,a1-clkc.h | 114 ++++++++++++++++++ > 3 files changed, 190 insertions(+), 2 deletions(-) > create mode 100644 Documentation/devicetree/bindings/clock/amlogic,a1-clkc.yaml > create mode 100644 include/dt-bindings/clock/amlogic,a1-clkc.h > Reviewed-by: Rob Herring <robh@kernel.org> _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-05 19:59 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce Peripherals clock controller for Amlogic A1 SoC family. A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. This patchset adds support for Amlogic A1 Peripherals clock driver and allows to generate clocks for all A1 SoC peripheral IPs. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1.c | 2273 ++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1.h | 114 ++ 4 files changed, 2398 insertions(+) create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index f56da2a4b000..970892b07043 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -109,6 +109,16 @@ config COMMON_CLK_A1_PLL device, A1 SoC Family. Say Y if you want A1 PLL clock controller to work. +config COMMON_CLK_A1 + tristate "Meson A1 SoC clock controller support" + depends on ARM64 + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_REGMAP + help + Support for the Peripherals clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 Peripherals clock + controller to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 2f17f475a48f..0e6f293c05d4 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o +obj-$(CONFIG_COMMON_CLK_A1) += a1.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c new file mode 100644 index 000000000000..26decdd64a8a --- /dev/null +++ b/drivers/clk/meson/a1.c @@ -0,0 +1,2273 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1.h" +#include "clk-dualdiv.h" +#include "clk-regmap.h" + +static struct clk_regmap xtal_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "xtal_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixpll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixpll_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_phy_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_phy_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_ctrl_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_ctrl_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap hifipll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifipll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap syspll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "syspll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap dds_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data) { + .name = "dds_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param clk_32k_div_table[] = { + { + .dual = 1, + .n1 = 733, + .m1 = 8, + .n2 = 732, + .m2 = 11, + }, + {} +}; + +static struct clk_regmap rtc_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_xtal = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_xtal", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = RTC_CTRL, + .mask = 0x3, + .shift = 0, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_xtal.hw, + &rtc_32k_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * All clocks that can be inherited from a more accurate RTC clock are marked + * with the CLK_SET_RATE_NO_REPARENT flag. This is because in certain + * situations, we may need to freeze their parent. The parent setup of these + * clocks should be located on the device tree side. + */ +struct clk_regmap rtc = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static u32 mux_table_sys[] = { 0, 1, 2, 3, 7 }; +static const struct clk_parent_data sys_parents[] = { + { .fw_name = "xtal" }, + { .fw_name = "fclk_div2" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div5" }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap sys_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys", + .ops = &clk_regmap_mux_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a.hw, + &sys_b.hw, + }, + .num_parents = 2, + /* + * This clock is used by APB bus which is set in boot ROM code + * 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_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 }; +static const struct clk_parent_data dsp_ab_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap dspa_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a.hw, + &dspa_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a.hw, + &dspb_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap clk_24m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "24m", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor clk_24m_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "24m_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap clk_12m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "12m", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn_pre = { + .data = &(struct clk_regmap_div_data){ + .offset = CLK12_24_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn_pre", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fclk_div2", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 12, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_divn_pre.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * the index 2 is sys_pll_div16, it will be implemented in the CPU clock driver, + * the index 4 is the clock measurement source, it's not supported yet + */ +static u32 gen_table[] = { 0, 1, 3, 5, 6, 7, 8 }; +static const struct clk_parent_data gen_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &rtc.hw }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap gen_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = GEN_CLK_CTRL, + .mask = 0xf, + .shift = 12, + .table = gen_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = gen_parent_data, + .num_parents = ARRAY_SIZE(gen_parent_data), + /* + * The GEN clock can be connected to an external pad, so it + * may be set up directly from the device tree. Additionally, + * the GEN clock can be inherited from a more accurate RTC + * clock, so in certain situations, it may be necessary + * to freeze its parent. + */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap gen_div = { + .data = &(struct clk_regmap_div_data){ + .offset = GEN_CLK_CTRL, + .shift = 0, + .width = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gen = { + .data = &(struct clk_regmap_gate_data){ + .offset = GEN_CLK_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "gen", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SAR_ADC_CLK_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &sys.hw, }, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap saradc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SAR_ADC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SAR_ADC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "saradc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_abcd_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_c_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_c", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_d_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_d", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_ef_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div5", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_e_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_e_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_e = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_e", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_f_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_f", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * spicc clk + * fdiv2 |\ |\ _____ + * ---------| |---DIV--| | | | spicc out + * ---------| | | |-----|GATE |--------- + * ..... |/ | / |_____| + * --------------------|/ + * 24M + */ +static const struct clk_parent_data spicc_spifc_parents[] = { + { .fw_name = "fclk_div2"}, + { .fw_name = "fclk_div3"}, + { .fw_name = "fclk_div5"}, + { .fw_name = "hifi_pll" }, +}; + +static struct clk_regmap spicc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spicc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPICC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spicc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPICC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ts_div = { + .data = &(struct clk_regmap_div_data){ + .offset = TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ts = { + .data = &(struct clk_regmap_gate_data){ + .offset = TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ts_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spifc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPIFC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spifc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPIFC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spifc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data usb_bus_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap usb_bus_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = USB_BUSCLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = usb_bus_parents, + .num_parents = ARRAY_SIZE(usb_bus_parents), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus_div = { + .data = &(struct clk_regmap_div_data){ + .offset = USB_BUSCLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus = { + .data = &(struct clk_regmap_gate_data){ + .offset = USB_BUSCLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_bus", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data sd_emmc_psram_dmc_parents[] = { + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, +}; + +static struct clk_regmap sd_emmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap sd_emmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SD_EMMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &sd_emmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SD_EMMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap psram_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PSRAM_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &psram_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram = { + .data = &(struct clk_regmap_gate_data){ + .offset = PSRAM_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "psram", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap dmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &dmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = DMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "dmc", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ceca_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECA_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_div.hw, + &ceca_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap ceca_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "cecb_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECB_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_div.hw, + &cecb_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap cecb_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &sys.hw) + +static MESON_GATE(clktree, SYS_CLK_EN0, 0); +static MESON_GATE(reset_ctrl, SYS_CLK_EN0, 1); +static MESON_GATE(analog_ctrl, SYS_CLK_EN0, 2); +static MESON_GATE(pwr_ctrl, SYS_CLK_EN0, 3); +static MESON_GATE(pad_ctrl, SYS_CLK_EN0, 4); +static MESON_GATE(sys_ctrl, SYS_CLK_EN0, 5); +static MESON_GATE(temp_sensor, SYS_CLK_EN0, 6); +static MESON_GATE(am2axi_dev, SYS_CLK_EN0, 7); +static MESON_GATE(spicc_b, SYS_CLK_EN0, 8); +static MESON_GATE(spicc_a, SYS_CLK_EN0, 9); +static MESON_GATE(msr, SYS_CLK_EN0, 10); +static MESON_GATE(audio, SYS_CLK_EN0, 11); +static MESON_GATE(jtag_ctrl, SYS_CLK_EN0, 12); +static MESON_GATE(saradc_en, SYS_CLK_EN0, 13); +static MESON_GATE(pwm_ef, SYS_CLK_EN0, 14); +static MESON_GATE(pwm_cd, SYS_CLK_EN0, 15); +static MESON_GATE(pwm_ab, SYS_CLK_EN0, 16); +static MESON_GATE(cec, SYS_CLK_EN0, 17); +static MESON_GATE(i2c_s, SYS_CLK_EN0, 18); +static MESON_GATE(ir_ctrl, SYS_CLK_EN0, 19); +static MESON_GATE(i2c_m_d, SYS_CLK_EN0, 20); +static MESON_GATE(i2c_m_c, SYS_CLK_EN0, 21); +static MESON_GATE(i2c_m_b, SYS_CLK_EN0, 22); +static MESON_GATE(i2c_m_a, SYS_CLK_EN0, 23); +static MESON_GATE(acodec, SYS_CLK_EN0, 24); +static MESON_GATE(otp, SYS_CLK_EN0, 25); +static MESON_GATE(sd_emmc_a, SYS_CLK_EN0, 26); +static MESON_GATE(usb_phy, SYS_CLK_EN0, 27); +static MESON_GATE(usb_ctrl, SYS_CLK_EN0, 28); +static MESON_GATE(sys_dspb, SYS_CLK_EN0, 29); +static MESON_GATE(sys_dspa, SYS_CLK_EN0, 30); +static MESON_GATE(dma, SYS_CLK_EN0, 31); +static MESON_GATE(irq_ctrl, SYS_CLK_EN1, 0); +static MESON_GATE(nic, SYS_CLK_EN1, 1); +static MESON_GATE(gic, SYS_CLK_EN1, 2); +static MESON_GATE(uart_c, SYS_CLK_EN1, 3); +static MESON_GATE(uart_b, SYS_CLK_EN1, 4); +static MESON_GATE(uart_a, SYS_CLK_EN1, 5); +static MESON_GATE(sys_psram, SYS_CLK_EN1, 6); +static MESON_GATE(rsa, SYS_CLK_EN1, 8); +static MESON_GATE(coresight, SYS_CLK_EN1, 9); +static MESON_GATE(am2axi_vad, AXI_CLK_EN, 0); +static MESON_GATE(audio_vad, AXI_CLK_EN, 1); +static MESON_GATE(axi_dmc, AXI_CLK_EN, 3); +static MESON_GATE(axi_psram, AXI_CLK_EN, 4); +static MESON_GATE(ramb, AXI_CLK_EN, 5); +static MESON_GATE(rama, AXI_CLK_EN, 6); +static MESON_GATE(axi_spifc, AXI_CLK_EN, 7); +static MESON_GATE(axi_nic, AXI_CLK_EN, 8); +static MESON_GATE(axi_dma, AXI_CLK_EN, 9); +static MESON_GATE(cpu_ctrl, AXI_CLK_EN, 10); +static MESON_GATE(rom, AXI_CLK_EN, 11); +static MESON_GATE(prod_i2c, AXI_CLK_EN, 12); + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_periphs_clks = { + .hws = { + [CLKID_XTAL_IN] = &xtal_in.hw, + [CLKID_FIXPLL_IN] = &fixpll_in.hw, + [CLKID_USB_PHY_IN] = &usb_phy_in.hw, + [CLKID_USB_CTRL_IN] = &usb_ctrl_in.hw, + [CLKID_HIFIPLL_IN] = &hifipll_in.hw, + [CLKID_SYSPLL_IN] = &syspll_in.hw, + [CLKID_DDS_IN] = &dds_in.hw, + [CLKID_SYS] = &sys.hw, + [CLKID_CLKTREE] = &clktree.hw, + [CLKID_RESET_CTRL] = &reset_ctrl.hw, + [CLKID_ANALOG_CTRL] = &analog_ctrl.hw, + [CLKID_PWR_CTRL] = &pwr_ctrl.hw, + [CLKID_PAD_CTRL] = &pad_ctrl.hw, + [CLKID_SYS_CTRL] = &sys_ctrl.hw, + [CLKID_TEMP_SENSOR] = &temp_sensor.hw, + [CLKID_AM2AXI_DIV] = &am2axi_dev.hw, + [CLKID_SPICC_B] = &spicc_b.hw, + [CLKID_SPICC_A] = &spicc_a.hw, + [CLKID_MSR] = &msr.hw, + [CLKID_AUDIO] = &audio.hw, + [CLKID_JTAG_CTRL] = &jtag_ctrl.hw, + [CLKID_SARADC_EN] = &saradc_en.hw, + [CLKID_PWM_EF] = &pwm_ef.hw, + [CLKID_PWM_CD] = &pwm_cd.hw, + [CLKID_PWM_AB] = &pwm_ab.hw, + [CLKID_CEC] = &cec.hw, + [CLKID_I2C_S] = &i2c_s.hw, + [CLKID_IR_CTRL] = &ir_ctrl.hw, + [CLKID_I2C_M_D] = &i2c_m_d.hw, + [CLKID_I2C_M_C] = &i2c_m_c.hw, + [CLKID_I2C_M_B] = &i2c_m_b.hw, + [CLKID_I2C_M_A] = &i2c_m_a.hw, + [CLKID_ACODEC] = &acodec.hw, + [CLKID_OTP] = &otp.hw, + [CLKID_SD_EMMC_A] = &sd_emmc_a.hw, + [CLKID_USB_PHY] = &usb_phy.hw, + [CLKID_USB_CTRL] = &usb_ctrl.hw, + [CLKID_SYS_DSPB] = &sys_dspb.hw, + [CLKID_SYS_DSPA] = &sys_dspa.hw, + [CLKID_DMA] = &dma.hw, + [CLKID_IRQ_CTRL] = &irq_ctrl.hw, + [CLKID_NIC] = &nic.hw, + [CLKID_GIC] = &gic.hw, + [CLKID_UART_C] = &uart_c.hw, + [CLKID_UART_B] = &uart_b.hw, + [CLKID_UART_A] = &uart_a.hw, + [CLKID_SYS_PSRAM] = &sys_psram.hw, + [CLKID_RSA] = &rsa.hw, + [CLKID_CORESIGHT] = &coresight.hw, + [CLKID_AM2AXI_VAD] = &am2axi_vad.hw, + [CLKID_AUDIO_VAD] = &audio_vad.hw, + [CLKID_AXI_DMC] = &axi_dmc.hw, + [CLKID_AXI_PSRAM] = &axi_psram.hw, + [CLKID_RAMB] = &ramb.hw, + [CLKID_RAMA] = &rama.hw, + [CLKID_AXI_SPIFC] = &axi_spifc.hw, + [CLKID_AXI_NIC] = &axi_nic.hw, + [CLKID_AXI_DMA] = &axi_dma.hw, + [CLKID_CPU_CTRL] = &cpu_ctrl.hw, + [CLKID_ROM] = &rom.hw, + [CLKID_PROC_I2C] = &prod_i2c.hw, + [CLKID_DSPA_SEL] = &dspa_sel.hw, + [CLKID_DSPB_SEL] = &dspb_sel.hw, + [CLKID_DSPA_EN] = &dspa_en.hw, + [CLKID_DSPA_EN_NIC] = &dspa_en_nic.hw, + [CLKID_DSPB_EN] = &dspb_en.hw, + [CLKID_DSPB_EN_NIC] = &dspb_en_nic.hw, + [CLKID_RTC] = &rtc.hw, + [CLKID_CECA_32K] = &ceca_32k_out.hw, + [CLKID_CECB_32K] = &cecb_32k_out.hw, + [CLKID_24M] = &clk_24m.hw, + [CLKID_12M] = &clk_12m.hw, + [CLKID_FCLK_DIV2_DIVN] = &fclk_div2_divn.hw, + [CLKID_GEN] = &gen.hw, + [CLKID_SARADC_SEL] = &saradc_sel.hw, + [CLKID_SARADC] = &saradc.hw, + [CLKID_PWM_A] = &pwm_a.hw, + [CLKID_PWM_B] = &pwm_b.hw, + [CLKID_PWM_C] = &pwm_c.hw, + [CLKID_PWM_D] = &pwm_d.hw, + [CLKID_PWM_E] = &pwm_e.hw, + [CLKID_PWM_F] = &pwm_f.hw, + [CLKID_SPICC] = &spicc.hw, + [CLKID_TS] = &ts.hw, + [CLKID_SPIFC] = &spifc.hw, + [CLKID_USB_BUS] = &usb_bus.hw, + [CLKID_SD_EMMC] = &sd_emmc.hw, + [CLKID_PSRAM] = &psram.hw, + [CLKID_DMC] = &dmc.hw, + [CLKID_SYS_A_SEL] = &sys_a_sel.hw, + [CLKID_SYS_A_DIV] = &sys_a_div.hw, + [CLKID_SYS_A] = &sys_a.hw, + [CLKID_SYS_B_SEL] = &sys_b_sel.hw, + [CLKID_SYS_B_DIV] = &sys_b_div.hw, + [CLKID_SYS_B] = &sys_b.hw, + [CLKID_DSPA_A_SEL] = &dspa_a_sel.hw, + [CLKID_DSPA_A_DIV] = &dspa_a_div.hw, + [CLKID_DSPA_A] = &dspa_a.hw, + [CLKID_DSPA_B_SEL] = &dspa_b_sel.hw, + [CLKID_DSPA_B_DIV] = &dspa_b_div.hw, + [CLKID_DSPA_B] = &dspa_b.hw, + [CLKID_DSPB_A_SEL] = &dspb_a_sel.hw, + [CLKID_DSPB_A_DIV] = &dspb_a_div.hw, + [CLKID_DSPB_A] = &dspb_a.hw, + [CLKID_DSPB_B_SEL] = &dspb_b_sel.hw, + [CLKID_DSPB_B_DIV] = &dspb_b_div.hw, + [CLKID_DSPB_B] = &dspb_b.hw, + [CLKID_RTC_32K_IN] = &rtc_32k_in.hw, + [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw, + [CLKID_RTC_32K_XTAL] = &rtc_32k_xtal.hw, + [CLKID_RTC_32K_SEL] = &rtc_32k_sel.hw, + [CLKID_CECB_32K_IN] = &cecb_32k_in.hw, + [CLKID_CECB_32K_DIV] = &cecb_32k_div.hw, + [CLKID_CECB_32K_SEL_PRE] = &cecb_32k_sel_pre.hw, + [CLKID_CECB_32K_SEL] = &cecb_32k_sel.hw, + [CLKID_CECA_32K_IN] = &ceca_32k_in.hw, + [CLKID_CECA_32K_DIV] = &ceca_32k_div.hw, + [CLKID_CECA_32K_SEL_PRE] = &ceca_32k_sel_pre.hw, + [CLKID_CECA_32K_SEL] = &ceca_32k_sel.hw, + [CLKID_DIV2_PRE] = &fclk_div2_divn_pre.hw, + [CLKID_24M_DIV2] = &clk_24m_div2.hw, + [CLKID_GEN_SEL] = &gen_sel.hw, + [CLKID_GEN_DIV] = &gen_div.hw, + [CLKID_SARADC_DIV] = &saradc_div.hw, + [CLKID_PWM_A_SEL] = &pwm_a_sel.hw, + [CLKID_PWM_A_DIV] = &pwm_a_div.hw, + [CLKID_PWM_B_SEL] = &pwm_b_sel.hw, + [CLKID_PWM_B_DIV] = &pwm_b_div.hw, + [CLKID_PWM_C_SEL] = &pwm_c_sel.hw, + [CLKID_PWM_C_DIV] = &pwm_c_div.hw, + [CLKID_PWM_D_SEL] = &pwm_d_sel.hw, + [CLKID_PWM_D_DIV] = &pwm_d_div.hw, + [CLKID_PWM_E_SEL] = &pwm_e_sel.hw, + [CLKID_PWM_E_DIV] = &pwm_e_div.hw, + [CLKID_PWM_F_SEL] = &pwm_f_sel.hw, + [CLKID_PWM_F_DIV] = &pwm_f_div.hw, + [CLKID_SPICC_SEL] = &spicc_sel.hw, + [CLKID_SPICC_DIV] = &spicc_div.hw, + [CLKID_SPICC_SEL2] = &spicc_sel2.hw, + [CLKID_TS_DIV] = &ts_div.hw, + [CLKID_SPIFC_SEL] = &spifc_sel.hw, + [CLKID_SPIFC_DIV] = &spifc_div.hw, + [CLKID_SPIFC_SEL2] = &spifc_sel2.hw, + [CLKID_USB_BUS_SEL] = &usb_bus_sel.hw, + [CLKID_USB_BUS_DIV] = &usb_bus_div.hw, + [CLKID_SD_EMMC_SEL] = &sd_emmc_sel.hw, + [CLKID_SD_EMMC_DIV] = &sd_emmc_div.hw, + [CLKID_SD_EMMC_SEL2] = &sd_emmc_sel2.hw, + [CLKID_PSRAM_SEL] = &psram_sel.hw, + [CLKID_PSRAM_DIV] = &psram_div.hw, + [CLKID_PSRAM_SEL2] = &psram_sel2.hw, + [CLKID_DMC_SEL] = &dmc_sel.hw, + [CLKID_DMC_DIV] = &dmc_div.hw, + [CLKID_DMC_SEL2] = &dmc_sel2.hw, + [NR_CLKS] = NULL, + }, + .num = NR_CLKS, +}; + +/* Convenience table to populate regmap in .probe */ +static struct clk_regmap *const a1_periphs_regmaps[] = { + &xtal_in, + &fixpll_in, + &usb_phy_in, + &usb_ctrl_in, + &hifipll_in, + &syspll_in, + &dds_in, + &sys, + &clktree, + &reset_ctrl, + &analog_ctrl, + &pwr_ctrl, + &pad_ctrl, + &sys_ctrl, + &temp_sensor, + &am2axi_dev, + &spicc_b, + &spicc_a, + &msr, + &audio, + &jtag_ctrl, + &saradc_en, + &pwm_ef, + &pwm_cd, + &pwm_ab, + &cec, + &i2c_s, + &ir_ctrl, + &i2c_m_d, + &i2c_m_c, + &i2c_m_b, + &i2c_m_a, + &acodec, + &otp, + &sd_emmc_a, + &usb_phy, + &usb_ctrl, + &sys_dspb, + &sys_dspa, + &dma, + &irq_ctrl, + &nic, + &gic, + &uart_c, + &uart_b, + &uart_a, + &sys_psram, + &rsa, + &coresight, + &am2axi_vad, + &audio_vad, + &axi_dmc, + &axi_psram, + &ramb, + &rama, + &axi_spifc, + &axi_nic, + &axi_dma, + &cpu_ctrl, + &rom, + &prod_i2c, + &dspa_sel, + &dspb_sel, + &dspa_en, + &dspa_en_nic, + &dspb_en, + &dspb_en_nic, + &rtc, + &ceca_32k_out, + &cecb_32k_out, + &clk_24m, + &clk_12m, + &fclk_div2_divn, + &gen, + &saradc_sel, + &saradc, + &pwm_a, + &pwm_b, + &pwm_c, + &pwm_d, + &pwm_e, + &pwm_f, + &spicc, + &ts, + &spifc, + &usb_bus, + &sd_emmc, + &psram, + &dmc, + &sys_a_sel, + &sys_a_div, + &sys_a, + &sys_b_sel, + &sys_b_div, + &sys_b, + &dspa_a_sel, + &dspa_a_div, + &dspa_a, + &dspa_b_sel, + &dspa_b_div, + &dspa_b, + &dspb_a_sel, + &dspb_a_div, + &dspb_a, + &dspb_b_sel, + &dspb_b_div, + &dspb_b, + &rtc_32k_in, + &rtc_32k_div, + &rtc_32k_xtal, + &rtc_32k_sel, + &cecb_32k_in, + &cecb_32k_div, + &cecb_32k_sel_pre, + &cecb_32k_sel, + &ceca_32k_in, + &ceca_32k_div, + &ceca_32k_sel_pre, + &ceca_32k_sel, + &fclk_div2_divn_pre, + &gen_sel, + &gen_div, + &saradc_div, + &pwm_a_sel, + &pwm_a_div, + &pwm_b_sel, + &pwm_b_div, + &pwm_c_sel, + &pwm_c_div, + &pwm_d_sel, + &pwm_d_div, + &pwm_e_sel, + &pwm_e_div, + &pwm_f_sel, + &pwm_f_div, + &spicc_sel, + &spicc_div, + &spicc_sel2, + &ts_div, + &spifc_sel, + &spifc_div, + &spifc_sel2, + &usb_bus_sel, + &usb_bus_div, + &sd_emmc_sel, + &sd_emmc_div, + &sd_emmc_sel2, + &psram_sel, + &psram_div, + &psram_sel2, + &dmc_sel, + &dmc_div, + &dmc_sel2, +}; + +static struct regmap_config a1_periphs_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_periphs_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_periphs_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_periphs_regmaps); i++) + a1_periphs_regmaps[i]->map = map; + + for (clkid = 0; clkid < a1_periphs_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_periphs_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_periphs_clks); +} + +static const struct of_device_id a1_periphs_clkc_match_table[] = { + { .compatible = "amlogic,a1-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); + +static struct platform_driver a1_periphs_clkc_driver = { + .probe = meson_a1_periphs_probe, + .driver = { + .name = "a1-clkc", + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), + }, +}; + +module_platform_driver(a1_periphs_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1.h b/drivers/clk/meson/a1.h new file mode 100644 index 000000000000..ae25a88be6d6 --- /dev/null +++ b/drivers/clk/meson/a1.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 Peripheral Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_H +#define __A1_H + +/* peripheral clock controller register offset */ +#define SYS_OSCIN_CTRL 0x0 +#define RTC_BY_OSCIN_CTRL0 0x4 +#define RTC_BY_OSCIN_CTRL1 0x8 +#define RTC_CTRL 0xc +#define SYS_CLK_CTRL0 0x10 +#define SYS_CLK_EN0 0x1c +#define SYS_CLK_EN1 0x20 +#define AXI_CLK_EN 0x24 +#define DSPA_CLK_EN 0x28 +#define DSPB_CLK_EN 0x2c +#define DSPA_CLK_CTRL0 0x30 +#define DSPB_CLK_CTRL0 0x34 +#define CLK12_24_CTRL 0x38 +#define GEN_CLK_CTRL 0x3c +#define SAR_ADC_CLK_CTRL 0xc0 +#define PWM_CLK_AB_CTRL 0xc4 +#define PWM_CLK_CD_CTRL 0xc8 +#define PWM_CLK_EF_CTRL 0xcc +#define SPICC_CLK_CTRL 0xd0 +#define TS_CLK_CTRL 0xd4 +#define SPIFC_CLK_CTRL 0xd8 +#define USB_BUSCLK_CTRL 0xdc +#define SD_EMMC_CLK_CTRL 0xe0 +#define CECA_CLK_CTRL0 0xe4 +#define CECA_CLK_CTRL1 0xe8 +#define CECB_CLK_CTRL0 0xec +#define CECB_CLK_CTRL1 0xf0 +#define PSRAM_CLK_CTRL 0xf4 +#define DMC_CLK_CTRL 0xf8 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_XTAL_IN 0 +#define CLKID_DSPA_SEL 61 +#define CLKID_DSPB_SEL 62 +#define CLKID_SARADC_SEL 74 +#define CLKID_SYS_A_SEL 89 +#define CLKID_SYS_A_DIV 90 +#define CLKID_SYS_A 91 +#define CLKID_SYS_B_SEL 92 +#define CLKID_SYS_B_DIV 93 +#define CLKID_SYS_B 94 +#define CLKID_DSPA_A_DIV 96 +#define CLKID_DSPA_A 97 +#define CLKID_DSPA_B_DIV 99 +#define CLKID_DSPA_B 100 +#define CLKID_DSPB_A_DIV 102 +#define CLKID_DSPB_A 103 +#define CLKID_DSPB_B_DIV 105 +#define CLKID_DSPB_B 106 +#define CLKID_RTC_32K_IN 107 +#define CLKID_RTC_32K_DIV 108 +#define CLKID_RTC_32K_XTAL 109 +#define CLKID_RTC_32K_SEL 110 +#define CLKID_CECB_32K_IN 111 +#define CLKID_CECB_32K_DIV 112 +#define CLKID_CECA_32K_IN 115 +#define CLKID_CECA_32K_DIV 116 +#define CLKID_DIV2_PRE 119 +#define CLKID_24M_DIV2 120 +#define CLKID_GEN_DIV 122 +#define CLKID_SARADC_DIV 123 +#define CLKID_PWM_A_DIV 125 +#define CLKID_PWM_B_DIV 127 +#define CLKID_PWM_C_DIV 129 +#define CLKID_PWM_D_DIV 131 +#define CLKID_PWM_E_DIV 133 +#define CLKID_PWM_F_DIV 135 +#define CLKID_SPICC_SEL 136 +#define CLKID_SPICC_DIV 137 +#define CLKID_SPICC_SEL2 138 +#define CLKID_TS_DIV 139 +#define CLKID_SPIFC_SEL 140 +#define CLKID_SPIFC_DIV 141 +#define CLKID_SPIFC_SEL2 142 +#define CLKID_USB_BUS_SEL 143 +#define CLKID_USB_BUS_DIV 144 +#define CLKID_SD_EMMC_SEL 145 +#define CLKID_SD_EMMC_DIV 146 +#define CLKID_SD_EMMC_SEL2 147 +#define CLKID_PSRAM_SEL 148 +#define CLKID_PSRAM_DIV 149 +#define CLKID_PSRAM_SEL2 150 +#define CLKID_DMC_SEL 151 +#define CLKID_DMC_DIV 152 +#define CLKID_DMC_SEL2 153 +#define NR_CLKS 154 + +#endif /* __A1_H */ -- 2.36.0 ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce Peripherals clock controller for Amlogic A1 SoC family. A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. This patchset adds support for Amlogic A1 Peripherals clock driver and allows to generate clocks for all A1 SoC peripheral IPs. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1.c | 2273 ++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1.h | 114 ++ 4 files changed, 2398 insertions(+) create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index f56da2a4b000..970892b07043 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -109,6 +109,16 @@ config COMMON_CLK_A1_PLL device, A1 SoC Family. Say Y if you want A1 PLL clock controller to work. +config COMMON_CLK_A1 + tristate "Meson A1 SoC clock controller support" + depends on ARM64 + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_REGMAP + help + Support for the Peripherals clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 Peripherals clock + controller to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 2f17f475a48f..0e6f293c05d4 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o +obj-$(CONFIG_COMMON_CLK_A1) += a1.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c new file mode 100644 index 000000000000..26decdd64a8a --- /dev/null +++ b/drivers/clk/meson/a1.c @@ -0,0 +1,2273 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1.h" +#include "clk-dualdiv.h" +#include "clk-regmap.h" + +static struct clk_regmap xtal_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "xtal_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixpll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixpll_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_phy_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_phy_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_ctrl_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_ctrl_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap hifipll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifipll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap syspll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "syspll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap dds_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data) { + .name = "dds_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param clk_32k_div_table[] = { + { + .dual = 1, + .n1 = 733, + .m1 = 8, + .n2 = 732, + .m2 = 11, + }, + {} +}; + +static struct clk_regmap rtc_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_xtal = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_xtal", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = RTC_CTRL, + .mask = 0x3, + .shift = 0, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_xtal.hw, + &rtc_32k_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * All clocks that can be inherited from a more accurate RTC clock are marked + * with the CLK_SET_RATE_NO_REPARENT flag. This is because in certain + * situations, we may need to freeze their parent. The parent setup of these + * clocks should be located on the device tree side. + */ +struct clk_regmap rtc = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static u32 mux_table_sys[] = { 0, 1, 2, 3, 7 }; +static const struct clk_parent_data sys_parents[] = { + { .fw_name = "xtal" }, + { .fw_name = "fclk_div2" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div5" }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap sys_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys", + .ops = &clk_regmap_mux_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a.hw, + &sys_b.hw, + }, + .num_parents = 2, + /* + * This clock is used by APB bus which is set in boot ROM code + * 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_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 }; +static const struct clk_parent_data dsp_ab_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap dspa_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a.hw, + &dspa_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a.hw, + &dspb_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap clk_24m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "24m", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor clk_24m_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "24m_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap clk_12m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "12m", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn_pre = { + .data = &(struct clk_regmap_div_data){ + .offset = CLK12_24_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn_pre", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fclk_div2", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 12, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_divn_pre.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * the index 2 is sys_pll_div16, it will be implemented in the CPU clock driver, + * the index 4 is the clock measurement source, it's not supported yet + */ +static u32 gen_table[] = { 0, 1, 3, 5, 6, 7, 8 }; +static const struct clk_parent_data gen_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &rtc.hw }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap gen_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = GEN_CLK_CTRL, + .mask = 0xf, + .shift = 12, + .table = gen_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = gen_parent_data, + .num_parents = ARRAY_SIZE(gen_parent_data), + /* + * The GEN clock can be connected to an external pad, so it + * may be set up directly from the device tree. Additionally, + * the GEN clock can be inherited from a more accurate RTC + * clock, so in certain situations, it may be necessary + * to freeze its parent. + */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap gen_div = { + .data = &(struct clk_regmap_div_data){ + .offset = GEN_CLK_CTRL, + .shift = 0, + .width = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gen = { + .data = &(struct clk_regmap_gate_data){ + .offset = GEN_CLK_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "gen", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SAR_ADC_CLK_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &sys.hw, }, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap saradc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SAR_ADC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SAR_ADC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "saradc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_abcd_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_c_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_c", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_d_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_d", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_ef_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div5", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_e_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_e_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_e = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_e", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_f_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_f", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * spicc clk + * fdiv2 |\ |\ _____ + * ---------| |---DIV--| | | | spicc out + * ---------| | | |-----|GATE |--------- + * ..... |/ | / |_____| + * --------------------|/ + * 24M + */ +static const struct clk_parent_data spicc_spifc_parents[] = { + { .fw_name = "fclk_div2"}, + { .fw_name = "fclk_div3"}, + { .fw_name = "fclk_div5"}, + { .fw_name = "hifi_pll" }, +}; + +static struct clk_regmap spicc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spicc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPICC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spicc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPICC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ts_div = { + .data = &(struct clk_regmap_div_data){ + .offset = TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ts = { + .data = &(struct clk_regmap_gate_data){ + .offset = TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ts_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spifc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPIFC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spifc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPIFC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spifc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data usb_bus_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap usb_bus_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = USB_BUSCLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = usb_bus_parents, + .num_parents = ARRAY_SIZE(usb_bus_parents), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus_div = { + .data = &(struct clk_regmap_div_data){ + .offset = USB_BUSCLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus = { + .data = &(struct clk_regmap_gate_data){ + .offset = USB_BUSCLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_bus", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data sd_emmc_psram_dmc_parents[] = { + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, +}; + +static struct clk_regmap sd_emmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap sd_emmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SD_EMMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &sd_emmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SD_EMMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap psram_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PSRAM_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &psram_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram = { + .data = &(struct clk_regmap_gate_data){ + .offset = PSRAM_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "psram", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap dmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &dmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = DMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "dmc", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ceca_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECA_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_div.hw, + &ceca_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap ceca_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "cecb_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECB_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_div.hw, + &cecb_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap cecb_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &sys.hw) + +static MESON_GATE(clktree, SYS_CLK_EN0, 0); +static MESON_GATE(reset_ctrl, SYS_CLK_EN0, 1); +static MESON_GATE(analog_ctrl, SYS_CLK_EN0, 2); +static MESON_GATE(pwr_ctrl, SYS_CLK_EN0, 3); +static MESON_GATE(pad_ctrl, SYS_CLK_EN0, 4); +static MESON_GATE(sys_ctrl, SYS_CLK_EN0, 5); +static MESON_GATE(temp_sensor, SYS_CLK_EN0, 6); +static MESON_GATE(am2axi_dev, SYS_CLK_EN0, 7); +static MESON_GATE(spicc_b, SYS_CLK_EN0, 8); +static MESON_GATE(spicc_a, SYS_CLK_EN0, 9); +static MESON_GATE(msr, SYS_CLK_EN0, 10); +static MESON_GATE(audio, SYS_CLK_EN0, 11); +static MESON_GATE(jtag_ctrl, SYS_CLK_EN0, 12); +static MESON_GATE(saradc_en, SYS_CLK_EN0, 13); +static MESON_GATE(pwm_ef, SYS_CLK_EN0, 14); +static MESON_GATE(pwm_cd, SYS_CLK_EN0, 15); +static MESON_GATE(pwm_ab, SYS_CLK_EN0, 16); +static MESON_GATE(cec, SYS_CLK_EN0, 17); +static MESON_GATE(i2c_s, SYS_CLK_EN0, 18); +static MESON_GATE(ir_ctrl, SYS_CLK_EN0, 19); +static MESON_GATE(i2c_m_d, SYS_CLK_EN0, 20); +static MESON_GATE(i2c_m_c, SYS_CLK_EN0, 21); +static MESON_GATE(i2c_m_b, SYS_CLK_EN0, 22); +static MESON_GATE(i2c_m_a, SYS_CLK_EN0, 23); +static MESON_GATE(acodec, SYS_CLK_EN0, 24); +static MESON_GATE(otp, SYS_CLK_EN0, 25); +static MESON_GATE(sd_emmc_a, SYS_CLK_EN0, 26); +static MESON_GATE(usb_phy, SYS_CLK_EN0, 27); +static MESON_GATE(usb_ctrl, SYS_CLK_EN0, 28); +static MESON_GATE(sys_dspb, SYS_CLK_EN0, 29); +static MESON_GATE(sys_dspa, SYS_CLK_EN0, 30); +static MESON_GATE(dma, SYS_CLK_EN0, 31); +static MESON_GATE(irq_ctrl, SYS_CLK_EN1, 0); +static MESON_GATE(nic, SYS_CLK_EN1, 1); +static MESON_GATE(gic, SYS_CLK_EN1, 2); +static MESON_GATE(uart_c, SYS_CLK_EN1, 3); +static MESON_GATE(uart_b, SYS_CLK_EN1, 4); +static MESON_GATE(uart_a, SYS_CLK_EN1, 5); +static MESON_GATE(sys_psram, SYS_CLK_EN1, 6); +static MESON_GATE(rsa, SYS_CLK_EN1, 8); +static MESON_GATE(coresight, SYS_CLK_EN1, 9); +static MESON_GATE(am2axi_vad, AXI_CLK_EN, 0); +static MESON_GATE(audio_vad, AXI_CLK_EN, 1); +static MESON_GATE(axi_dmc, AXI_CLK_EN, 3); +static MESON_GATE(axi_psram, AXI_CLK_EN, 4); +static MESON_GATE(ramb, AXI_CLK_EN, 5); +static MESON_GATE(rama, AXI_CLK_EN, 6); +static MESON_GATE(axi_spifc, AXI_CLK_EN, 7); +static MESON_GATE(axi_nic, AXI_CLK_EN, 8); +static MESON_GATE(axi_dma, AXI_CLK_EN, 9); +static MESON_GATE(cpu_ctrl, AXI_CLK_EN, 10); +static MESON_GATE(rom, AXI_CLK_EN, 11); +static MESON_GATE(prod_i2c, AXI_CLK_EN, 12); + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_periphs_clks = { + .hws = { + [CLKID_XTAL_IN] = &xtal_in.hw, + [CLKID_FIXPLL_IN] = &fixpll_in.hw, + [CLKID_USB_PHY_IN] = &usb_phy_in.hw, + [CLKID_USB_CTRL_IN] = &usb_ctrl_in.hw, + [CLKID_HIFIPLL_IN] = &hifipll_in.hw, + [CLKID_SYSPLL_IN] = &syspll_in.hw, + [CLKID_DDS_IN] = &dds_in.hw, + [CLKID_SYS] = &sys.hw, + [CLKID_CLKTREE] = &clktree.hw, + [CLKID_RESET_CTRL] = &reset_ctrl.hw, + [CLKID_ANALOG_CTRL] = &analog_ctrl.hw, + [CLKID_PWR_CTRL] = &pwr_ctrl.hw, + [CLKID_PAD_CTRL] = &pad_ctrl.hw, + [CLKID_SYS_CTRL] = &sys_ctrl.hw, + [CLKID_TEMP_SENSOR] = &temp_sensor.hw, + [CLKID_AM2AXI_DIV] = &am2axi_dev.hw, + [CLKID_SPICC_B] = &spicc_b.hw, + [CLKID_SPICC_A] = &spicc_a.hw, + [CLKID_MSR] = &msr.hw, + [CLKID_AUDIO] = &audio.hw, + [CLKID_JTAG_CTRL] = &jtag_ctrl.hw, + [CLKID_SARADC_EN] = &saradc_en.hw, + [CLKID_PWM_EF] = &pwm_ef.hw, + [CLKID_PWM_CD] = &pwm_cd.hw, + [CLKID_PWM_AB] = &pwm_ab.hw, + [CLKID_CEC] = &cec.hw, + [CLKID_I2C_S] = &i2c_s.hw, + [CLKID_IR_CTRL] = &ir_ctrl.hw, + [CLKID_I2C_M_D] = &i2c_m_d.hw, + [CLKID_I2C_M_C] = &i2c_m_c.hw, + [CLKID_I2C_M_B] = &i2c_m_b.hw, + [CLKID_I2C_M_A] = &i2c_m_a.hw, + [CLKID_ACODEC] = &acodec.hw, + [CLKID_OTP] = &otp.hw, + [CLKID_SD_EMMC_A] = &sd_emmc_a.hw, + [CLKID_USB_PHY] = &usb_phy.hw, + [CLKID_USB_CTRL] = &usb_ctrl.hw, + [CLKID_SYS_DSPB] = &sys_dspb.hw, + [CLKID_SYS_DSPA] = &sys_dspa.hw, + [CLKID_DMA] = &dma.hw, + [CLKID_IRQ_CTRL] = &irq_ctrl.hw, + [CLKID_NIC] = &nic.hw, + [CLKID_GIC] = &gic.hw, + [CLKID_UART_C] = &uart_c.hw, + [CLKID_UART_B] = &uart_b.hw, + [CLKID_UART_A] = &uart_a.hw, + [CLKID_SYS_PSRAM] = &sys_psram.hw, + [CLKID_RSA] = &rsa.hw, + [CLKID_CORESIGHT] = &coresight.hw, + [CLKID_AM2AXI_VAD] = &am2axi_vad.hw, + [CLKID_AUDIO_VAD] = &audio_vad.hw, + [CLKID_AXI_DMC] = &axi_dmc.hw, + [CLKID_AXI_PSRAM] = &axi_psram.hw, + [CLKID_RAMB] = &ramb.hw, + [CLKID_RAMA] = &rama.hw, + [CLKID_AXI_SPIFC] = &axi_spifc.hw, + [CLKID_AXI_NIC] = &axi_nic.hw, + [CLKID_AXI_DMA] = &axi_dma.hw, + [CLKID_CPU_CTRL] = &cpu_ctrl.hw, + [CLKID_ROM] = &rom.hw, + [CLKID_PROC_I2C] = &prod_i2c.hw, + [CLKID_DSPA_SEL] = &dspa_sel.hw, + [CLKID_DSPB_SEL] = &dspb_sel.hw, + [CLKID_DSPA_EN] = &dspa_en.hw, + [CLKID_DSPA_EN_NIC] = &dspa_en_nic.hw, + [CLKID_DSPB_EN] = &dspb_en.hw, + [CLKID_DSPB_EN_NIC] = &dspb_en_nic.hw, + [CLKID_RTC] = &rtc.hw, + [CLKID_CECA_32K] = &ceca_32k_out.hw, + [CLKID_CECB_32K] = &cecb_32k_out.hw, + [CLKID_24M] = &clk_24m.hw, + [CLKID_12M] = &clk_12m.hw, + [CLKID_FCLK_DIV2_DIVN] = &fclk_div2_divn.hw, + [CLKID_GEN] = &gen.hw, + [CLKID_SARADC_SEL] = &saradc_sel.hw, + [CLKID_SARADC] = &saradc.hw, + [CLKID_PWM_A] = &pwm_a.hw, + [CLKID_PWM_B] = &pwm_b.hw, + [CLKID_PWM_C] = &pwm_c.hw, + [CLKID_PWM_D] = &pwm_d.hw, + [CLKID_PWM_E] = &pwm_e.hw, + [CLKID_PWM_F] = &pwm_f.hw, + [CLKID_SPICC] = &spicc.hw, + [CLKID_TS] = &ts.hw, + [CLKID_SPIFC] = &spifc.hw, + [CLKID_USB_BUS] = &usb_bus.hw, + [CLKID_SD_EMMC] = &sd_emmc.hw, + [CLKID_PSRAM] = &psram.hw, + [CLKID_DMC] = &dmc.hw, + [CLKID_SYS_A_SEL] = &sys_a_sel.hw, + [CLKID_SYS_A_DIV] = &sys_a_div.hw, + [CLKID_SYS_A] = &sys_a.hw, + [CLKID_SYS_B_SEL] = &sys_b_sel.hw, + [CLKID_SYS_B_DIV] = &sys_b_div.hw, + [CLKID_SYS_B] = &sys_b.hw, + [CLKID_DSPA_A_SEL] = &dspa_a_sel.hw, + [CLKID_DSPA_A_DIV] = &dspa_a_div.hw, + [CLKID_DSPA_A] = &dspa_a.hw, + [CLKID_DSPA_B_SEL] = &dspa_b_sel.hw, + [CLKID_DSPA_B_DIV] = &dspa_b_div.hw, + [CLKID_DSPA_B] = &dspa_b.hw, + [CLKID_DSPB_A_SEL] = &dspb_a_sel.hw, + [CLKID_DSPB_A_DIV] = &dspb_a_div.hw, + [CLKID_DSPB_A] = &dspb_a.hw, + [CLKID_DSPB_B_SEL] = &dspb_b_sel.hw, + [CLKID_DSPB_B_DIV] = &dspb_b_div.hw, + [CLKID_DSPB_B] = &dspb_b.hw, + [CLKID_RTC_32K_IN] = &rtc_32k_in.hw, + [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw, + [CLKID_RTC_32K_XTAL] = &rtc_32k_xtal.hw, + [CLKID_RTC_32K_SEL] = &rtc_32k_sel.hw, + [CLKID_CECB_32K_IN] = &cecb_32k_in.hw, + [CLKID_CECB_32K_DIV] = &cecb_32k_div.hw, + [CLKID_CECB_32K_SEL_PRE] = &cecb_32k_sel_pre.hw, + [CLKID_CECB_32K_SEL] = &cecb_32k_sel.hw, + [CLKID_CECA_32K_IN] = &ceca_32k_in.hw, + [CLKID_CECA_32K_DIV] = &ceca_32k_div.hw, + [CLKID_CECA_32K_SEL_PRE] = &ceca_32k_sel_pre.hw, + [CLKID_CECA_32K_SEL] = &ceca_32k_sel.hw, + [CLKID_DIV2_PRE] = &fclk_div2_divn_pre.hw, + [CLKID_24M_DIV2] = &clk_24m_div2.hw, + [CLKID_GEN_SEL] = &gen_sel.hw, + [CLKID_GEN_DIV] = &gen_div.hw, + [CLKID_SARADC_DIV] = &saradc_div.hw, + [CLKID_PWM_A_SEL] = &pwm_a_sel.hw, + [CLKID_PWM_A_DIV] = &pwm_a_div.hw, + [CLKID_PWM_B_SEL] = &pwm_b_sel.hw, + [CLKID_PWM_B_DIV] = &pwm_b_div.hw, + [CLKID_PWM_C_SEL] = &pwm_c_sel.hw, + [CLKID_PWM_C_DIV] = &pwm_c_div.hw, + [CLKID_PWM_D_SEL] = &pwm_d_sel.hw, + [CLKID_PWM_D_DIV] = &pwm_d_div.hw, + [CLKID_PWM_E_SEL] = &pwm_e_sel.hw, + [CLKID_PWM_E_DIV] = &pwm_e_div.hw, + [CLKID_PWM_F_SEL] = &pwm_f_sel.hw, + [CLKID_PWM_F_DIV] = &pwm_f_div.hw, + [CLKID_SPICC_SEL] = &spicc_sel.hw, + [CLKID_SPICC_DIV] = &spicc_div.hw, + [CLKID_SPICC_SEL2] = &spicc_sel2.hw, + [CLKID_TS_DIV] = &ts_div.hw, + [CLKID_SPIFC_SEL] = &spifc_sel.hw, + [CLKID_SPIFC_DIV] = &spifc_div.hw, + [CLKID_SPIFC_SEL2] = &spifc_sel2.hw, + [CLKID_USB_BUS_SEL] = &usb_bus_sel.hw, + [CLKID_USB_BUS_DIV] = &usb_bus_div.hw, + [CLKID_SD_EMMC_SEL] = &sd_emmc_sel.hw, + [CLKID_SD_EMMC_DIV] = &sd_emmc_div.hw, + [CLKID_SD_EMMC_SEL2] = &sd_emmc_sel2.hw, + [CLKID_PSRAM_SEL] = &psram_sel.hw, + [CLKID_PSRAM_DIV] = &psram_div.hw, + [CLKID_PSRAM_SEL2] = &psram_sel2.hw, + [CLKID_DMC_SEL] = &dmc_sel.hw, + [CLKID_DMC_DIV] = &dmc_div.hw, + [CLKID_DMC_SEL2] = &dmc_sel2.hw, + [NR_CLKS] = NULL, + }, + .num = NR_CLKS, +}; + +/* Convenience table to populate regmap in .probe */ +static struct clk_regmap *const a1_periphs_regmaps[] = { + &xtal_in, + &fixpll_in, + &usb_phy_in, + &usb_ctrl_in, + &hifipll_in, + &syspll_in, + &dds_in, + &sys, + &clktree, + &reset_ctrl, + &analog_ctrl, + &pwr_ctrl, + &pad_ctrl, + &sys_ctrl, + &temp_sensor, + &am2axi_dev, + &spicc_b, + &spicc_a, + &msr, + &audio, + &jtag_ctrl, + &saradc_en, + &pwm_ef, + &pwm_cd, + &pwm_ab, + &cec, + &i2c_s, + &ir_ctrl, + &i2c_m_d, + &i2c_m_c, + &i2c_m_b, + &i2c_m_a, + &acodec, + &otp, + &sd_emmc_a, + &usb_phy, + &usb_ctrl, + &sys_dspb, + &sys_dspa, + &dma, + &irq_ctrl, + &nic, + &gic, + &uart_c, + &uart_b, + &uart_a, + &sys_psram, + &rsa, + &coresight, + &am2axi_vad, + &audio_vad, + &axi_dmc, + &axi_psram, + &ramb, + &rama, + &axi_spifc, + &axi_nic, + &axi_dma, + &cpu_ctrl, + &rom, + &prod_i2c, + &dspa_sel, + &dspb_sel, + &dspa_en, + &dspa_en_nic, + &dspb_en, + &dspb_en_nic, + &rtc, + &ceca_32k_out, + &cecb_32k_out, + &clk_24m, + &clk_12m, + &fclk_div2_divn, + &gen, + &saradc_sel, + &saradc, + &pwm_a, + &pwm_b, + &pwm_c, + &pwm_d, + &pwm_e, + &pwm_f, + &spicc, + &ts, + &spifc, + &usb_bus, + &sd_emmc, + &psram, + &dmc, + &sys_a_sel, + &sys_a_div, + &sys_a, + &sys_b_sel, + &sys_b_div, + &sys_b, + &dspa_a_sel, + &dspa_a_div, + &dspa_a, + &dspa_b_sel, + &dspa_b_div, + &dspa_b, + &dspb_a_sel, + &dspb_a_div, + &dspb_a, + &dspb_b_sel, + &dspb_b_div, + &dspb_b, + &rtc_32k_in, + &rtc_32k_div, + &rtc_32k_xtal, + &rtc_32k_sel, + &cecb_32k_in, + &cecb_32k_div, + &cecb_32k_sel_pre, + &cecb_32k_sel, + &ceca_32k_in, + &ceca_32k_div, + &ceca_32k_sel_pre, + &ceca_32k_sel, + &fclk_div2_divn_pre, + &gen_sel, + &gen_div, + &saradc_div, + &pwm_a_sel, + &pwm_a_div, + &pwm_b_sel, + &pwm_b_div, + &pwm_c_sel, + &pwm_c_div, + &pwm_d_sel, + &pwm_d_div, + &pwm_e_sel, + &pwm_e_div, + &pwm_f_sel, + &pwm_f_div, + &spicc_sel, + &spicc_div, + &spicc_sel2, + &ts_div, + &spifc_sel, + &spifc_div, + &spifc_sel2, + &usb_bus_sel, + &usb_bus_div, + &sd_emmc_sel, + &sd_emmc_div, + &sd_emmc_sel2, + &psram_sel, + &psram_div, + &psram_sel2, + &dmc_sel, + &dmc_div, + &dmc_sel2, +}; + +static struct regmap_config a1_periphs_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_periphs_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_periphs_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_periphs_regmaps); i++) + a1_periphs_regmaps[i]->map = map; + + for (clkid = 0; clkid < a1_periphs_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_periphs_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_periphs_clks); +} + +static const struct of_device_id a1_periphs_clkc_match_table[] = { + { .compatible = "amlogic,a1-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); + +static struct platform_driver a1_periphs_clkc_driver = { + .probe = meson_a1_periphs_probe, + .driver = { + .name = "a1-clkc", + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), + }, +}; + +module_platform_driver(a1_periphs_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1.h b/drivers/clk/meson/a1.h new file mode 100644 index 000000000000..ae25a88be6d6 --- /dev/null +++ b/drivers/clk/meson/a1.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 Peripheral Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_H +#define __A1_H + +/* peripheral clock controller register offset */ +#define SYS_OSCIN_CTRL 0x0 +#define RTC_BY_OSCIN_CTRL0 0x4 +#define RTC_BY_OSCIN_CTRL1 0x8 +#define RTC_CTRL 0xc +#define SYS_CLK_CTRL0 0x10 +#define SYS_CLK_EN0 0x1c +#define SYS_CLK_EN1 0x20 +#define AXI_CLK_EN 0x24 +#define DSPA_CLK_EN 0x28 +#define DSPB_CLK_EN 0x2c +#define DSPA_CLK_CTRL0 0x30 +#define DSPB_CLK_CTRL0 0x34 +#define CLK12_24_CTRL 0x38 +#define GEN_CLK_CTRL 0x3c +#define SAR_ADC_CLK_CTRL 0xc0 +#define PWM_CLK_AB_CTRL 0xc4 +#define PWM_CLK_CD_CTRL 0xc8 +#define PWM_CLK_EF_CTRL 0xcc +#define SPICC_CLK_CTRL 0xd0 +#define TS_CLK_CTRL 0xd4 +#define SPIFC_CLK_CTRL 0xd8 +#define USB_BUSCLK_CTRL 0xdc +#define SD_EMMC_CLK_CTRL 0xe0 +#define CECA_CLK_CTRL0 0xe4 +#define CECA_CLK_CTRL1 0xe8 +#define CECB_CLK_CTRL0 0xec +#define CECB_CLK_CTRL1 0xf0 +#define PSRAM_CLK_CTRL 0xf4 +#define DMC_CLK_CTRL 0xf8 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_XTAL_IN 0 +#define CLKID_DSPA_SEL 61 +#define CLKID_DSPB_SEL 62 +#define CLKID_SARADC_SEL 74 +#define CLKID_SYS_A_SEL 89 +#define CLKID_SYS_A_DIV 90 +#define CLKID_SYS_A 91 +#define CLKID_SYS_B_SEL 92 +#define CLKID_SYS_B_DIV 93 +#define CLKID_SYS_B 94 +#define CLKID_DSPA_A_DIV 96 +#define CLKID_DSPA_A 97 +#define CLKID_DSPA_B_DIV 99 +#define CLKID_DSPA_B 100 +#define CLKID_DSPB_A_DIV 102 +#define CLKID_DSPB_A 103 +#define CLKID_DSPB_B_DIV 105 +#define CLKID_DSPB_B 106 +#define CLKID_RTC_32K_IN 107 +#define CLKID_RTC_32K_DIV 108 +#define CLKID_RTC_32K_XTAL 109 +#define CLKID_RTC_32K_SEL 110 +#define CLKID_CECB_32K_IN 111 +#define CLKID_CECB_32K_DIV 112 +#define CLKID_CECA_32K_IN 115 +#define CLKID_CECA_32K_DIV 116 +#define CLKID_DIV2_PRE 119 +#define CLKID_24M_DIV2 120 +#define CLKID_GEN_DIV 122 +#define CLKID_SARADC_DIV 123 +#define CLKID_PWM_A_DIV 125 +#define CLKID_PWM_B_DIV 127 +#define CLKID_PWM_C_DIV 129 +#define CLKID_PWM_D_DIV 131 +#define CLKID_PWM_E_DIV 133 +#define CLKID_PWM_F_DIV 135 +#define CLKID_SPICC_SEL 136 +#define CLKID_SPICC_DIV 137 +#define CLKID_SPICC_SEL2 138 +#define CLKID_TS_DIV 139 +#define CLKID_SPIFC_SEL 140 +#define CLKID_SPIFC_DIV 141 +#define CLKID_SPIFC_SEL2 142 +#define CLKID_USB_BUS_SEL 143 +#define CLKID_USB_BUS_DIV 144 +#define CLKID_SD_EMMC_SEL 145 +#define CLKID_SD_EMMC_DIV 146 +#define CLKID_SD_EMMC_SEL2 147 +#define CLKID_PSRAM_SEL 148 +#define CLKID_PSRAM_DIV 149 +#define CLKID_PSRAM_SEL2 150 +#define CLKID_DMC_SEL 151 +#define CLKID_DMC_DIV 152 +#define CLKID_DMC_SEL2 153 +#define NR_CLKS 154 + +#endif /* __A1_H */ -- 2.36.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 52+ messages in thread
* [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-05 19:59 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-05 19:59 UTC (permalink / raw) To: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, martin.blumenstingl Cc: jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel, Dmitry Rokosov Introduce Peripherals clock controller for Amlogic A1 SoC family. A1 SoC has four clock controllers on the board: PLL, Peripherals, CPU, and Audio. This patchset adds support for Amlogic A1 Peripherals clock driver and allows to generate clocks for all A1 SoC peripheral IPs. Signed-off-by: Jian Hu <jian.hu@amlogic.com> Signed-off-by: Dmitry Rokosov <ddrokosov@sberdevices.ru> --- drivers/clk/meson/Kconfig | 10 + drivers/clk/meson/Makefile | 1 + drivers/clk/meson/a1.c | 2273 ++++++++++++++++++++++++++++++++++++ drivers/clk/meson/a1.h | 114 ++ 4 files changed, 2398 insertions(+) create mode 100644 drivers/clk/meson/a1.c create mode 100644 drivers/clk/meson/a1.h diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig index f56da2a4b000..970892b07043 100644 --- a/drivers/clk/meson/Kconfig +++ b/drivers/clk/meson/Kconfig @@ -109,6 +109,16 @@ config COMMON_CLK_A1_PLL device, A1 SoC Family. Say Y if you want A1 PLL clock controller to work. +config COMMON_CLK_A1 + tristate "Meson A1 SoC clock controller support" + depends on ARM64 + select COMMON_CLK_MESON_DUALDIV + select COMMON_CLK_MESON_REGMAP + help + Support for the Peripherals clock controller on Amlogic A113L based + device, A1 SoC Family. Say Y if you want A1 Peripherals clock + controller to work. + config COMMON_CLK_G12A tristate "G12 and SM1 SoC clock controllers support" depends on ARM64 diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile index 2f17f475a48f..0e6f293c05d4 100644 --- a/drivers/clk/meson/Makefile +++ b/drivers/clk/meson/Makefile @@ -17,6 +17,7 @@ obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o obj-$(CONFIG_COMMON_CLK_A1_PLL) += a1-pll.o +obj-$(CONFIG_COMMON_CLK_A1) += a1.o obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o meson8-ddr.o diff --git a/drivers/clk/meson/a1.c b/drivers/clk/meson/a1.c new file mode 100644 index 000000000000..26decdd64a8a --- /dev/null +++ b/drivers/clk/meson/a1.c @@ -0,0 +1,2273 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "a1.h" +#include "clk-dualdiv.h" +#include "clk-regmap.h" + +static struct clk_regmap xtal_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "xtal_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fixpll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "fixpll_in", + .ops = &clk_regmap_gate_ro_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_phy_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 2, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_phy_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap usb_ctrl_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 3, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_ctrl_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap hifipll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 4, + }, + .hw.init = &(struct clk_init_data) { + .name = "hifipll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap syspll_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 5, + }, + .hw.init = &(struct clk_init_data) { + .name = "syspll_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap dds_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_OSCIN_CTRL, + .bit_idx = 6, + }, + .hw.init = &(struct clk_init_data) { + .name = "dds_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static const struct meson_clk_dualdiv_param clk_32k_div_table[] = { + { + .dual = 1, + .n1 = 733, + .m1 = 8, + .n2 = 732, + .m2 = 11, + }, + {} +}; + +static struct clk_regmap rtc_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = RTC_BY_OSCIN_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = RTC_BY_OSCIN_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_xtal = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL1, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "rtc_32k_xtal", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap rtc_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = RTC_CTRL, + .mask = 0x3, + .shift = 0, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_xtal.hw, + &rtc_32k_div.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * All clocks that can be inherited from a more accurate RTC clock are marked + * with the CLK_SET_RATE_NO_REPARENT flag. This is because in certain + * situations, we may need to freeze their parent. The parent setup of these + * clocks should be located on the device tree side. + */ +struct clk_regmap rtc = { + .data = &(struct clk_regmap_gate_data){ + .offset = RTC_BY_OSCIN_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "rtc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &rtc_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static u32 mux_table_sys[] = { 0, 1, 2, 3, 7 }; +static const struct clk_parent_data sys_parents[] = { + { .fw_name = "xtal" }, + { .fw_name = "fclk_div2" }, + { .fw_name = "fclk_div3" }, + { .fw_name = "fclk_div5" }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap sys_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_sys, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_sel", + .ops = &clk_regmap_mux_ro_ops, + .parent_data = sys_parents, + .num_parents = ARRAY_SIZE(sys_parents), + }, +}; + +static struct clk_regmap sys_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SYS_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = SYS_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "sys_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sys = { + .data = &(struct clk_regmap_mux_data){ + .offset = SYS_CLK_CTRL0, + .mask = 0x1, + .shift = 31, + }, + .hw.init = &(struct clk_init_data){ + .name = "sys", + .ops = &clk_regmap_mux_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &sys_a.hw, + &sys_b.hw, + }, + .num_parents = 2, + /* + * This clock is used by APB bus which is set in boot ROM code + * 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_SET_RATE_PARENT | CLK_IS_CRITICAL, + }, +}; + +static u32 mux_table_dsp_ab[] = { 0, 1, 2, 3, 4, 7 }; +static const struct clk_parent_data dsp_ab_parent_data[] = { + { .fw_name = "xtal", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap dspa_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspa_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPA_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPA_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspa_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_a.hw, + &dspa_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspa_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPA_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspa_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspa_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 10, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 0, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 13, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x7, + .shift = 26, + .table = mux_table_dsp_ab, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = dsp_ab_parent_data, + .num_parents = ARRAY_SIZE(dsp_ab_parent_data), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap dspb_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DSPB_CLK_CTRL0, + .shift = 16, + .width = 10, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_CTRL0, + .bit_idx = 29, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DSPB_CLK_CTRL0, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dspb_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_a.hw, + &dspb_b.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 1, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dspb_en_nic = { + .data = &(struct clk_regmap_gate_data){ + .offset = DSPB_CLK_EN, + .bit_idx = 0, + }, + .hw.init = &(struct clk_init_data) { + .name = "dspb_en_nic", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &dspb_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap clk_24m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "24m", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_fixed_factor clk_24m_div2 = { + .mult = 1, + .div = 2, + .hw.init = &(struct clk_init_data){ + .name = "24m_div2", + .ops = &clk_fixed_factor_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap clk_12m = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 10, + }, + .hw.init = &(struct clk_init_data) { + .name = "12m", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &clk_24m_div2.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn_pre = { + .data = &(struct clk_regmap_div_data){ + .offset = CLK12_24_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn_pre", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "fclk_div2", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap fclk_div2_divn = { + .data = &(struct clk_regmap_gate_data){ + .offset = CLK12_24_CTRL, + .bit_idx = 12, + }, + .hw.init = &(struct clk_init_data){ + .name = "fclk_div2_divn", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &fclk_div2_divn_pre.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * the index 2 is sys_pll_div16, it will be implemented in the CPU clock driver, + * the index 4 is the clock measurement source, it's not supported yet + */ +static u32 gen_table[] = { 0, 1, 3, 5, 6, 7, 8 }; +static const struct clk_parent_data gen_parent_data[] = { + { .fw_name = "xtal", }, + { .hw = &rtc.hw }, + { .fw_name = "hifi_pll", }, + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "fclk_div7", }, +}; + +static struct clk_regmap gen_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = GEN_CLK_CTRL, + .mask = 0xf, + .shift = 12, + .table = gen_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = gen_parent_data, + .num_parents = ARRAY_SIZE(gen_parent_data), + /* + * The GEN clock can be connected to an external pad, so it + * may be set up directly from the device tree. Additionally, + * the GEN clock can be inherited from a more accurate RTC + * clock, so in certain situations, it may be necessary + * to freeze its parent. + */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap gen_div = { + .data = &(struct clk_regmap_div_data){ + .offset = GEN_CLK_CTRL, + .shift = 0, + .width = 11, + }, + .hw.init = &(struct clk_init_data){ + .name = "gen_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap gen = { + .data = &(struct clk_regmap_gate_data){ + .offset = GEN_CLK_CTRL, + .bit_idx = 11, + }, + .hw.init = &(struct clk_init_data) { + .name = "gen", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &gen_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SAR_ADC_CLK_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .fw_name = "xtal", }, + { .hw = &sys.hw, }, + }, + .num_parents = 2, + }, +}; + +static struct clk_regmap saradc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SAR_ADC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "saradc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap saradc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SAR_ADC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "saradc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &saradc_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_abcd_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_a_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_a_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_a_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_a = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_a", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_a_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_AB_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_b_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_AB_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_b_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_b = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_AB_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_b", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_b_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_c_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_c_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_c = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_c", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_c_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_CD_CTRL, + .mask = 0x1, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_abcd_parents, + .num_parents = ARRAY_SIZE(pwm_abcd_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_d_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_CD_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_d_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_d = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_CD_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_d", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_d_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data pwm_ef_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div5", }, + { .hw = &rtc.hw }, +}; + +static struct clk_regmap pwm_e_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_e_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_e_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_e = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_e", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_e_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PWM_CLK_EF_CTRL, + .mask = 0x3, + .shift = 25, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = pwm_ef_parents, + .num_parents = ARRAY_SIZE(pwm_ef_parents), + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap pwm_f_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PWM_CLK_EF_CTRL, + .shift = 16, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "pwm_f_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap pwm_f = { + .data = &(struct clk_regmap_gate_data){ + .offset = PWM_CLK_EF_CTRL, + .bit_idx = 24, + }, + .hw.init = &(struct clk_init_data) { + .name = "pwm_f", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &pwm_f_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +/* + * spicc clk + * fdiv2 |\ |\ _____ + * ---------| |---DIV--| | | | spicc out + * ---------| | | |-----|GATE |--------- + * ..... |/ | / |_____| + * --------------------|/ + * 24M + */ +static const struct clk_parent_data spicc_spifc_parents[] = { + { .fw_name = "fclk_div2"}, + { .fw_name = "fclk_div3"}, + { .fw_name = "fclk_div5"}, + { .fw_name = "hifi_pll" }, +}; + +static struct clk_regmap spicc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spicc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPICC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPICC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spicc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spicc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spicc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPICC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spicc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spicc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ts_div = { + .data = &(struct clk_regmap_div_data){ + .offset = TS_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "ts_div", + .ops = &clk_regmap_divider_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ts = { + .data = &(struct clk_regmap_gate_data){ + .offset = TS_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "ts", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ts_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = spicc_spifc_parents, + .num_parents = ARRAY_SIZE(spicc_spifc_parents), + }, +}; + +static struct clk_regmap spifc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SPIFC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SPIFC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "spifc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &spifc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap spifc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SPIFC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "spifc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &spifc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data usb_bus_parents[] = { + { .fw_name = "xtal", }, + { .hw = &sys.hw }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, +}; + +static struct clk_regmap usb_bus_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = USB_BUSCLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = usb_bus_parents, + .num_parents = ARRAY_SIZE(usb_bus_parents), + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus_div = { + .data = &(struct clk_regmap_div_data){ + .offset = USB_BUSCLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "usb_bus_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap usb_bus = { + .data = &(struct clk_regmap_gate_data){ + .offset = USB_BUSCLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "usb_bus", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &usb_bus_div.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static const struct clk_parent_data sd_emmc_psram_dmc_parents[] = { + { .fw_name = "fclk_div2", }, + { .fw_name = "fclk_div3", }, + { .fw_name = "fclk_div5", }, + { .fw_name = "hifi_pll", }, +}; + +static struct clk_regmap sd_emmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap sd_emmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = SD_EMMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = SD_EMMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "sd_emmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &sd_emmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap sd_emmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = SD_EMMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "sd_emmc", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &sd_emmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap psram_div = { + .data = &(struct clk_regmap_div_data){ + .offset = PSRAM_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = PSRAM_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "psram_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &psram_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap psram = { + .data = &(struct clk_regmap_gate_data){ + .offset = PSRAM_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "psram", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &psram_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x3, + .shift = 9, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel", + .ops = &clk_regmap_mux_ops, + .parent_data = sd_emmc_psram_dmc_parents, + .num_parents = ARRAY_SIZE(sd_emmc_psram_dmc_parents), + }, +}; + +static struct clk_regmap dmc_div = { + .data = &(struct clk_regmap_div_data){ + .offset = DMC_CLK_CTRL, + .shift = 0, + .width = 8, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_div", + .ops = &clk_regmap_divider_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc_sel2 = { + .data = &(struct clk_regmap_mux_data){ + .offset = DMC_CLK_CTRL, + .mask = 0x1, + .shift = 15, + }, + .hw.init = &(struct clk_init_data){ + .name = "dmc_sel2", + .ops = &clk_regmap_mux_ops, + .parent_data = (const struct clk_parent_data []) { + { .hw = &dmc_div.hw }, + { .fw_name = "xtal", }, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap dmc = { + .data = &(struct clk_regmap_gate_data){ + .offset = DMC_CLK_CTRL, + .bit_idx = 8, + }, + .hw.init = &(struct clk_init_data) { + .name = "dmc", + .ops = &clk_regmap_gate_ro_ops, + .parent_hws = (const struct clk_hw *[]) { + &dmc_sel2.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "ceca_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECA_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECA_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECA_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap ceca_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_div.hw, + &ceca_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap ceca_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECA_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap ceca_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECA_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "ceca_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &ceca_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_in = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 31, + }, + .hw.init = &(struct clk_init_data) { + .name = "cecb_32k_in", + .ops = &clk_regmap_gate_ops, + .parent_data = &(const struct clk_parent_data) { + .fw_name = "xtal", + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_div = { + .data = &(struct meson_clk_dualdiv_data){ + .n1 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 0, + .width = 12, + }, + .n2 = { + .reg_off = CECB_CLK_CTRL0, + .shift = 12, + .width = 12, + }, + .m1 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 0, + .width = 12, + }, + .m2 = { + .reg_off = CECB_CLK_CTRL1, + .shift = 12, + .width = 12, + }, + .dual = { + .reg_off = CECB_CLK_CTRL0, + .shift = 28, + .width = 1, + }, + .table = clk_32k_div_table, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_div", + .ops = &meson_clk_dualdiv_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_in.hw + }, + .num_parents = 1, + }, +}; + +static struct clk_regmap cecb_32k_sel_pre = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 24, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel_pre", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_div.hw, + &cecb_32k_in.hw, + }, + .num_parents = 2, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +static struct clk_regmap cecb_32k_sel = { + .data = &(struct clk_regmap_mux_data) { + .offset = CECB_CLK_CTRL1, + .mask = 0x1, + .shift = 31, + .flags = CLK_MUX_ROUND_CLOSEST, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_sel", + .ops = &clk_regmap_mux_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel_pre.hw, + &rtc.hw, + }, + .num_parents = 2, + /* For more information, please refer to rtc clock */ + .flags = CLK_SET_RATE_NO_REPARENT, + }, +}; + +static struct clk_regmap cecb_32k_out = { + .data = &(struct clk_regmap_gate_data){ + .offset = CECB_CLK_CTRL0, + .bit_idx = 30, + }, + .hw.init = &(struct clk_init_data){ + .name = "cecb_32k_out", + .ops = &clk_regmap_gate_ops, + .parent_hws = (const struct clk_hw *[]) { + &cecb_32k_sel.hw + }, + .num_parents = 1, + .flags = CLK_SET_RATE_PARENT, + }, +}; + +#define MESON_GATE(_name, _reg, _bit) \ + MESON_PCLK(_name, _reg, _bit, &sys.hw) + +static MESON_GATE(clktree, SYS_CLK_EN0, 0); +static MESON_GATE(reset_ctrl, SYS_CLK_EN0, 1); +static MESON_GATE(analog_ctrl, SYS_CLK_EN0, 2); +static MESON_GATE(pwr_ctrl, SYS_CLK_EN0, 3); +static MESON_GATE(pad_ctrl, SYS_CLK_EN0, 4); +static MESON_GATE(sys_ctrl, SYS_CLK_EN0, 5); +static MESON_GATE(temp_sensor, SYS_CLK_EN0, 6); +static MESON_GATE(am2axi_dev, SYS_CLK_EN0, 7); +static MESON_GATE(spicc_b, SYS_CLK_EN0, 8); +static MESON_GATE(spicc_a, SYS_CLK_EN0, 9); +static MESON_GATE(msr, SYS_CLK_EN0, 10); +static MESON_GATE(audio, SYS_CLK_EN0, 11); +static MESON_GATE(jtag_ctrl, SYS_CLK_EN0, 12); +static MESON_GATE(saradc_en, SYS_CLK_EN0, 13); +static MESON_GATE(pwm_ef, SYS_CLK_EN0, 14); +static MESON_GATE(pwm_cd, SYS_CLK_EN0, 15); +static MESON_GATE(pwm_ab, SYS_CLK_EN0, 16); +static MESON_GATE(cec, SYS_CLK_EN0, 17); +static MESON_GATE(i2c_s, SYS_CLK_EN0, 18); +static MESON_GATE(ir_ctrl, SYS_CLK_EN0, 19); +static MESON_GATE(i2c_m_d, SYS_CLK_EN0, 20); +static MESON_GATE(i2c_m_c, SYS_CLK_EN0, 21); +static MESON_GATE(i2c_m_b, SYS_CLK_EN0, 22); +static MESON_GATE(i2c_m_a, SYS_CLK_EN0, 23); +static MESON_GATE(acodec, SYS_CLK_EN0, 24); +static MESON_GATE(otp, SYS_CLK_EN0, 25); +static MESON_GATE(sd_emmc_a, SYS_CLK_EN0, 26); +static MESON_GATE(usb_phy, SYS_CLK_EN0, 27); +static MESON_GATE(usb_ctrl, SYS_CLK_EN0, 28); +static MESON_GATE(sys_dspb, SYS_CLK_EN0, 29); +static MESON_GATE(sys_dspa, SYS_CLK_EN0, 30); +static MESON_GATE(dma, SYS_CLK_EN0, 31); +static MESON_GATE(irq_ctrl, SYS_CLK_EN1, 0); +static MESON_GATE(nic, SYS_CLK_EN1, 1); +static MESON_GATE(gic, SYS_CLK_EN1, 2); +static MESON_GATE(uart_c, SYS_CLK_EN1, 3); +static MESON_GATE(uart_b, SYS_CLK_EN1, 4); +static MESON_GATE(uart_a, SYS_CLK_EN1, 5); +static MESON_GATE(sys_psram, SYS_CLK_EN1, 6); +static MESON_GATE(rsa, SYS_CLK_EN1, 8); +static MESON_GATE(coresight, SYS_CLK_EN1, 9); +static MESON_GATE(am2axi_vad, AXI_CLK_EN, 0); +static MESON_GATE(audio_vad, AXI_CLK_EN, 1); +static MESON_GATE(axi_dmc, AXI_CLK_EN, 3); +static MESON_GATE(axi_psram, AXI_CLK_EN, 4); +static MESON_GATE(ramb, AXI_CLK_EN, 5); +static MESON_GATE(rama, AXI_CLK_EN, 6); +static MESON_GATE(axi_spifc, AXI_CLK_EN, 7); +static MESON_GATE(axi_nic, AXI_CLK_EN, 8); +static MESON_GATE(axi_dma, AXI_CLK_EN, 9); +static MESON_GATE(cpu_ctrl, AXI_CLK_EN, 10); +static MESON_GATE(rom, AXI_CLK_EN, 11); +static MESON_GATE(prod_i2c, AXI_CLK_EN, 12); + +/* Array of all clocks registered by this provider */ +static struct clk_hw_onecell_data a1_periphs_clks = { + .hws = { + [CLKID_XTAL_IN] = &xtal_in.hw, + [CLKID_FIXPLL_IN] = &fixpll_in.hw, + [CLKID_USB_PHY_IN] = &usb_phy_in.hw, + [CLKID_USB_CTRL_IN] = &usb_ctrl_in.hw, + [CLKID_HIFIPLL_IN] = &hifipll_in.hw, + [CLKID_SYSPLL_IN] = &syspll_in.hw, + [CLKID_DDS_IN] = &dds_in.hw, + [CLKID_SYS] = &sys.hw, + [CLKID_CLKTREE] = &clktree.hw, + [CLKID_RESET_CTRL] = &reset_ctrl.hw, + [CLKID_ANALOG_CTRL] = &analog_ctrl.hw, + [CLKID_PWR_CTRL] = &pwr_ctrl.hw, + [CLKID_PAD_CTRL] = &pad_ctrl.hw, + [CLKID_SYS_CTRL] = &sys_ctrl.hw, + [CLKID_TEMP_SENSOR] = &temp_sensor.hw, + [CLKID_AM2AXI_DIV] = &am2axi_dev.hw, + [CLKID_SPICC_B] = &spicc_b.hw, + [CLKID_SPICC_A] = &spicc_a.hw, + [CLKID_MSR] = &msr.hw, + [CLKID_AUDIO] = &audio.hw, + [CLKID_JTAG_CTRL] = &jtag_ctrl.hw, + [CLKID_SARADC_EN] = &saradc_en.hw, + [CLKID_PWM_EF] = &pwm_ef.hw, + [CLKID_PWM_CD] = &pwm_cd.hw, + [CLKID_PWM_AB] = &pwm_ab.hw, + [CLKID_CEC] = &cec.hw, + [CLKID_I2C_S] = &i2c_s.hw, + [CLKID_IR_CTRL] = &ir_ctrl.hw, + [CLKID_I2C_M_D] = &i2c_m_d.hw, + [CLKID_I2C_M_C] = &i2c_m_c.hw, + [CLKID_I2C_M_B] = &i2c_m_b.hw, + [CLKID_I2C_M_A] = &i2c_m_a.hw, + [CLKID_ACODEC] = &acodec.hw, + [CLKID_OTP] = &otp.hw, + [CLKID_SD_EMMC_A] = &sd_emmc_a.hw, + [CLKID_USB_PHY] = &usb_phy.hw, + [CLKID_USB_CTRL] = &usb_ctrl.hw, + [CLKID_SYS_DSPB] = &sys_dspb.hw, + [CLKID_SYS_DSPA] = &sys_dspa.hw, + [CLKID_DMA] = &dma.hw, + [CLKID_IRQ_CTRL] = &irq_ctrl.hw, + [CLKID_NIC] = &nic.hw, + [CLKID_GIC] = &gic.hw, + [CLKID_UART_C] = &uart_c.hw, + [CLKID_UART_B] = &uart_b.hw, + [CLKID_UART_A] = &uart_a.hw, + [CLKID_SYS_PSRAM] = &sys_psram.hw, + [CLKID_RSA] = &rsa.hw, + [CLKID_CORESIGHT] = &coresight.hw, + [CLKID_AM2AXI_VAD] = &am2axi_vad.hw, + [CLKID_AUDIO_VAD] = &audio_vad.hw, + [CLKID_AXI_DMC] = &axi_dmc.hw, + [CLKID_AXI_PSRAM] = &axi_psram.hw, + [CLKID_RAMB] = &ramb.hw, + [CLKID_RAMA] = &rama.hw, + [CLKID_AXI_SPIFC] = &axi_spifc.hw, + [CLKID_AXI_NIC] = &axi_nic.hw, + [CLKID_AXI_DMA] = &axi_dma.hw, + [CLKID_CPU_CTRL] = &cpu_ctrl.hw, + [CLKID_ROM] = &rom.hw, + [CLKID_PROC_I2C] = &prod_i2c.hw, + [CLKID_DSPA_SEL] = &dspa_sel.hw, + [CLKID_DSPB_SEL] = &dspb_sel.hw, + [CLKID_DSPA_EN] = &dspa_en.hw, + [CLKID_DSPA_EN_NIC] = &dspa_en_nic.hw, + [CLKID_DSPB_EN] = &dspb_en.hw, + [CLKID_DSPB_EN_NIC] = &dspb_en_nic.hw, + [CLKID_RTC] = &rtc.hw, + [CLKID_CECA_32K] = &ceca_32k_out.hw, + [CLKID_CECB_32K] = &cecb_32k_out.hw, + [CLKID_24M] = &clk_24m.hw, + [CLKID_12M] = &clk_12m.hw, + [CLKID_FCLK_DIV2_DIVN] = &fclk_div2_divn.hw, + [CLKID_GEN] = &gen.hw, + [CLKID_SARADC_SEL] = &saradc_sel.hw, + [CLKID_SARADC] = &saradc.hw, + [CLKID_PWM_A] = &pwm_a.hw, + [CLKID_PWM_B] = &pwm_b.hw, + [CLKID_PWM_C] = &pwm_c.hw, + [CLKID_PWM_D] = &pwm_d.hw, + [CLKID_PWM_E] = &pwm_e.hw, + [CLKID_PWM_F] = &pwm_f.hw, + [CLKID_SPICC] = &spicc.hw, + [CLKID_TS] = &ts.hw, + [CLKID_SPIFC] = &spifc.hw, + [CLKID_USB_BUS] = &usb_bus.hw, + [CLKID_SD_EMMC] = &sd_emmc.hw, + [CLKID_PSRAM] = &psram.hw, + [CLKID_DMC] = &dmc.hw, + [CLKID_SYS_A_SEL] = &sys_a_sel.hw, + [CLKID_SYS_A_DIV] = &sys_a_div.hw, + [CLKID_SYS_A] = &sys_a.hw, + [CLKID_SYS_B_SEL] = &sys_b_sel.hw, + [CLKID_SYS_B_DIV] = &sys_b_div.hw, + [CLKID_SYS_B] = &sys_b.hw, + [CLKID_DSPA_A_SEL] = &dspa_a_sel.hw, + [CLKID_DSPA_A_DIV] = &dspa_a_div.hw, + [CLKID_DSPA_A] = &dspa_a.hw, + [CLKID_DSPA_B_SEL] = &dspa_b_sel.hw, + [CLKID_DSPA_B_DIV] = &dspa_b_div.hw, + [CLKID_DSPA_B] = &dspa_b.hw, + [CLKID_DSPB_A_SEL] = &dspb_a_sel.hw, + [CLKID_DSPB_A_DIV] = &dspb_a_div.hw, + [CLKID_DSPB_A] = &dspb_a.hw, + [CLKID_DSPB_B_SEL] = &dspb_b_sel.hw, + [CLKID_DSPB_B_DIV] = &dspb_b_div.hw, + [CLKID_DSPB_B] = &dspb_b.hw, + [CLKID_RTC_32K_IN] = &rtc_32k_in.hw, + [CLKID_RTC_32K_DIV] = &rtc_32k_div.hw, + [CLKID_RTC_32K_XTAL] = &rtc_32k_xtal.hw, + [CLKID_RTC_32K_SEL] = &rtc_32k_sel.hw, + [CLKID_CECB_32K_IN] = &cecb_32k_in.hw, + [CLKID_CECB_32K_DIV] = &cecb_32k_div.hw, + [CLKID_CECB_32K_SEL_PRE] = &cecb_32k_sel_pre.hw, + [CLKID_CECB_32K_SEL] = &cecb_32k_sel.hw, + [CLKID_CECA_32K_IN] = &ceca_32k_in.hw, + [CLKID_CECA_32K_DIV] = &ceca_32k_div.hw, + [CLKID_CECA_32K_SEL_PRE] = &ceca_32k_sel_pre.hw, + [CLKID_CECA_32K_SEL] = &ceca_32k_sel.hw, + [CLKID_DIV2_PRE] = &fclk_div2_divn_pre.hw, + [CLKID_24M_DIV2] = &clk_24m_div2.hw, + [CLKID_GEN_SEL] = &gen_sel.hw, + [CLKID_GEN_DIV] = &gen_div.hw, + [CLKID_SARADC_DIV] = &saradc_div.hw, + [CLKID_PWM_A_SEL] = &pwm_a_sel.hw, + [CLKID_PWM_A_DIV] = &pwm_a_div.hw, + [CLKID_PWM_B_SEL] = &pwm_b_sel.hw, + [CLKID_PWM_B_DIV] = &pwm_b_div.hw, + [CLKID_PWM_C_SEL] = &pwm_c_sel.hw, + [CLKID_PWM_C_DIV] = &pwm_c_div.hw, + [CLKID_PWM_D_SEL] = &pwm_d_sel.hw, + [CLKID_PWM_D_DIV] = &pwm_d_div.hw, + [CLKID_PWM_E_SEL] = &pwm_e_sel.hw, + [CLKID_PWM_E_DIV] = &pwm_e_div.hw, + [CLKID_PWM_F_SEL] = &pwm_f_sel.hw, + [CLKID_PWM_F_DIV] = &pwm_f_div.hw, + [CLKID_SPICC_SEL] = &spicc_sel.hw, + [CLKID_SPICC_DIV] = &spicc_div.hw, + [CLKID_SPICC_SEL2] = &spicc_sel2.hw, + [CLKID_TS_DIV] = &ts_div.hw, + [CLKID_SPIFC_SEL] = &spifc_sel.hw, + [CLKID_SPIFC_DIV] = &spifc_div.hw, + [CLKID_SPIFC_SEL2] = &spifc_sel2.hw, + [CLKID_USB_BUS_SEL] = &usb_bus_sel.hw, + [CLKID_USB_BUS_DIV] = &usb_bus_div.hw, + [CLKID_SD_EMMC_SEL] = &sd_emmc_sel.hw, + [CLKID_SD_EMMC_DIV] = &sd_emmc_div.hw, + [CLKID_SD_EMMC_SEL2] = &sd_emmc_sel2.hw, + [CLKID_PSRAM_SEL] = &psram_sel.hw, + [CLKID_PSRAM_DIV] = &psram_div.hw, + [CLKID_PSRAM_SEL2] = &psram_sel2.hw, + [CLKID_DMC_SEL] = &dmc_sel.hw, + [CLKID_DMC_DIV] = &dmc_div.hw, + [CLKID_DMC_SEL2] = &dmc_sel2.hw, + [NR_CLKS] = NULL, + }, + .num = NR_CLKS, +}; + +/* Convenience table to populate regmap in .probe */ +static struct clk_regmap *const a1_periphs_regmaps[] = { + &xtal_in, + &fixpll_in, + &usb_phy_in, + &usb_ctrl_in, + &hifipll_in, + &syspll_in, + &dds_in, + &sys, + &clktree, + &reset_ctrl, + &analog_ctrl, + &pwr_ctrl, + &pad_ctrl, + &sys_ctrl, + &temp_sensor, + &am2axi_dev, + &spicc_b, + &spicc_a, + &msr, + &audio, + &jtag_ctrl, + &saradc_en, + &pwm_ef, + &pwm_cd, + &pwm_ab, + &cec, + &i2c_s, + &ir_ctrl, + &i2c_m_d, + &i2c_m_c, + &i2c_m_b, + &i2c_m_a, + &acodec, + &otp, + &sd_emmc_a, + &usb_phy, + &usb_ctrl, + &sys_dspb, + &sys_dspa, + &dma, + &irq_ctrl, + &nic, + &gic, + &uart_c, + &uart_b, + &uart_a, + &sys_psram, + &rsa, + &coresight, + &am2axi_vad, + &audio_vad, + &axi_dmc, + &axi_psram, + &ramb, + &rama, + &axi_spifc, + &axi_nic, + &axi_dma, + &cpu_ctrl, + &rom, + &prod_i2c, + &dspa_sel, + &dspb_sel, + &dspa_en, + &dspa_en_nic, + &dspb_en, + &dspb_en_nic, + &rtc, + &ceca_32k_out, + &cecb_32k_out, + &clk_24m, + &clk_12m, + &fclk_div2_divn, + &gen, + &saradc_sel, + &saradc, + &pwm_a, + &pwm_b, + &pwm_c, + &pwm_d, + &pwm_e, + &pwm_f, + &spicc, + &ts, + &spifc, + &usb_bus, + &sd_emmc, + &psram, + &dmc, + &sys_a_sel, + &sys_a_div, + &sys_a, + &sys_b_sel, + &sys_b_div, + &sys_b, + &dspa_a_sel, + &dspa_a_div, + &dspa_a, + &dspa_b_sel, + &dspa_b_div, + &dspa_b, + &dspb_a_sel, + &dspb_a_div, + &dspb_a, + &dspb_b_sel, + &dspb_b_div, + &dspb_b, + &rtc_32k_in, + &rtc_32k_div, + &rtc_32k_xtal, + &rtc_32k_sel, + &cecb_32k_in, + &cecb_32k_div, + &cecb_32k_sel_pre, + &cecb_32k_sel, + &ceca_32k_in, + &ceca_32k_div, + &ceca_32k_sel_pre, + &ceca_32k_sel, + &fclk_div2_divn_pre, + &gen_sel, + &gen_div, + &saradc_div, + &pwm_a_sel, + &pwm_a_div, + &pwm_b_sel, + &pwm_b_div, + &pwm_c_sel, + &pwm_c_div, + &pwm_d_sel, + &pwm_d_div, + &pwm_e_sel, + &pwm_e_div, + &pwm_f_sel, + &pwm_f_div, + &spicc_sel, + &spicc_div, + &spicc_sel2, + &ts_div, + &spifc_sel, + &spifc_div, + &spifc_sel2, + &usb_bus_sel, + &usb_bus_div, + &sd_emmc_sel, + &sd_emmc_div, + &sd_emmc_sel2, + &psram_sel, + &psram_div, + &psram_sel2, + &dmc_sel, + &dmc_div, + &dmc_sel2, +}; + +static struct regmap_config a1_periphs_regmap_cfg = { + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, +}; + +static int meson_a1_periphs_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + void __iomem *base; + struct regmap *map; + int clkid, i, err; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "can't ioremap resource\n"); + + map = devm_regmap_init_mmio(dev, base, &a1_periphs_regmap_cfg); + if (IS_ERR(map)) + return dev_err_probe(dev, PTR_ERR(map), + "can't init regmap mmio region\n"); + + /* Populate regmap for the regmap backed clocks */ + for (i = 0; i < ARRAY_SIZE(a1_periphs_regmaps); i++) + a1_periphs_regmaps[i]->map = map; + + for (clkid = 0; clkid < a1_periphs_clks.num; clkid++) { + err = devm_clk_hw_register(dev, a1_periphs_clks.hws[clkid]); + if (err) + return dev_err_probe(dev, err, + "clock[%d] registration failed\n", + clkid); + } + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, + &a1_periphs_clks); +} + +static const struct of_device_id a1_periphs_clkc_match_table[] = { + { .compatible = "amlogic,a1-clkc", }, + {}, +}; +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); + +static struct platform_driver a1_periphs_clkc_driver = { + .probe = meson_a1_periphs_probe, + .driver = { + .name = "a1-clkc", + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), + }, +}; + +module_platform_driver(a1_periphs_clkc_driver); +MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>"); +MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/meson/a1.h b/drivers/clk/meson/a1.h new file mode 100644 index 000000000000..ae25a88be6d6 --- /dev/null +++ b/drivers/clk/meson/a1.h @@ -0,0 +1,114 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Amlogic Meson-A1 Peripheral Clock Controller internals + * + * Copyright (c) 2019 Amlogic, Inc. All rights reserved. + * Author: Jian Hu <jian.hu@amlogic.com> + * + * Copyright (c) 2023, SberDevices. All Rights Reserved. + * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru> + */ + +#ifndef __A1_H +#define __A1_H + +/* peripheral clock controller register offset */ +#define SYS_OSCIN_CTRL 0x0 +#define RTC_BY_OSCIN_CTRL0 0x4 +#define RTC_BY_OSCIN_CTRL1 0x8 +#define RTC_CTRL 0xc +#define SYS_CLK_CTRL0 0x10 +#define SYS_CLK_EN0 0x1c +#define SYS_CLK_EN1 0x20 +#define AXI_CLK_EN 0x24 +#define DSPA_CLK_EN 0x28 +#define DSPB_CLK_EN 0x2c +#define DSPA_CLK_CTRL0 0x30 +#define DSPB_CLK_CTRL0 0x34 +#define CLK12_24_CTRL 0x38 +#define GEN_CLK_CTRL 0x3c +#define SAR_ADC_CLK_CTRL 0xc0 +#define PWM_CLK_AB_CTRL 0xc4 +#define PWM_CLK_CD_CTRL 0xc8 +#define PWM_CLK_EF_CTRL 0xcc +#define SPICC_CLK_CTRL 0xd0 +#define TS_CLK_CTRL 0xd4 +#define SPIFC_CLK_CTRL 0xd8 +#define USB_BUSCLK_CTRL 0xdc +#define SD_EMMC_CLK_CTRL 0xe0 +#define CECA_CLK_CTRL0 0xe4 +#define CECA_CLK_CTRL1 0xe8 +#define CECB_CLK_CTRL0 0xec +#define CECB_CLK_CTRL1 0xf0 +#define PSRAM_CLK_CTRL 0xf4 +#define DMC_CLK_CTRL 0xf8 + +/* include the CLKIDs that have been made part of the DT binding */ +#include <dt-bindings/clock/amlogic,a1-clkc.h> + +/* + * CLKID index values for internal clocks + * + * These indices are entirely contrived and do not map onto the hardware. + * It has now been decided to expose everything by default in the DT header: + * include/dt-bindings/clock/a1-clkc.h. Only the clocks ids we don't want + * to expose, such as the internal muxes and dividers of composite clocks, + * will remain defined here. + */ +#define CLKID_XTAL_IN 0 +#define CLKID_DSPA_SEL 61 +#define CLKID_DSPB_SEL 62 +#define CLKID_SARADC_SEL 74 +#define CLKID_SYS_A_SEL 89 +#define CLKID_SYS_A_DIV 90 +#define CLKID_SYS_A 91 +#define CLKID_SYS_B_SEL 92 +#define CLKID_SYS_B_DIV 93 +#define CLKID_SYS_B 94 +#define CLKID_DSPA_A_DIV 96 +#define CLKID_DSPA_A 97 +#define CLKID_DSPA_B_DIV 99 +#define CLKID_DSPA_B 100 +#define CLKID_DSPB_A_DIV 102 +#define CLKID_DSPB_A 103 +#define CLKID_DSPB_B_DIV 105 +#define CLKID_DSPB_B 106 +#define CLKID_RTC_32K_IN 107 +#define CLKID_RTC_32K_DIV 108 +#define CLKID_RTC_32K_XTAL 109 +#define CLKID_RTC_32K_SEL 110 +#define CLKID_CECB_32K_IN 111 +#define CLKID_CECB_32K_DIV 112 +#define CLKID_CECA_32K_IN 115 +#define CLKID_CECA_32K_DIV 116 +#define CLKID_DIV2_PRE 119 +#define CLKID_24M_DIV2 120 +#define CLKID_GEN_DIV 122 +#define CLKID_SARADC_DIV 123 +#define CLKID_PWM_A_DIV 125 +#define CLKID_PWM_B_DIV 127 +#define CLKID_PWM_C_DIV 129 +#define CLKID_PWM_D_DIV 131 +#define CLKID_PWM_E_DIV 133 +#define CLKID_PWM_F_DIV 135 +#define CLKID_SPICC_SEL 136 +#define CLKID_SPICC_DIV 137 +#define CLKID_SPICC_SEL2 138 +#define CLKID_TS_DIV 139 +#define CLKID_SPIFC_SEL 140 +#define CLKID_SPIFC_DIV 141 +#define CLKID_SPIFC_SEL2 142 +#define CLKID_USB_BUS_SEL 143 +#define CLKID_USB_BUS_DIV 144 +#define CLKID_SD_EMMC_SEL 145 +#define CLKID_SD_EMMC_DIV 146 +#define CLKID_SD_EMMC_SEL2 147 +#define CLKID_PSRAM_SEL 148 +#define CLKID_PSRAM_DIV 149 +#define CLKID_PSRAM_SEL2 150 +#define CLKID_DMC_SEL 151 +#define CLKID_DMC_DIV 152 +#define CLKID_DMC_SEL2 153 +#define NR_CLKS 154 + +#endif /* __A1_H */ -- 2.36.0 _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply related [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver 2023-04-05 19:59 ` Dmitry Rokosov (?) @ 2023-04-23 21:30 ` Martin Blumenstingl -1 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:30 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > + { .compatible = "amlogic,a1-clkc", }, > + {}, nit-pick: please remove the comma after the sentinel > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > + > +static struct platform_driver a1_periphs_clkc_driver = { > + .probe = meson_a1_periphs_probe, > + .driver = { > + .name = "a1-clkc", > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), I wonder if we should drop of_match_ptr() here as no other meson clock driver uses it. Also there's commits like 00cb754ac622 ("clk: imx8mq: drop of_match_ptr from of_device_id table") which explicitly remove it from other drivers. Apart form these two this patch looks great to me. Best regards, Martin ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-23 21:30 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:30 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > + { .compatible = "amlogic,a1-clkc", }, > + {}, nit-pick: please remove the comma after the sentinel > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > + > +static struct platform_driver a1_periphs_clkc_driver = { > + .probe = meson_a1_periphs_probe, > + .driver = { > + .name = "a1-clkc", > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), I wonder if we should drop of_match_ptr() here as no other meson clock driver uses it. Also there's commits like 00cb754ac622 ("clk: imx8mq: drop of_match_ptr from of_device_id table") which explicitly remove it from other drivers. Apart form these two this patch looks great to me. Best regards, Martin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-23 21:30 ` Martin Blumenstingl 0 siblings, 0 replies; 52+ messages in thread From: Martin Blumenstingl @ 2023-04-23 21:30 UTC (permalink / raw) To: Dmitry Rokosov Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: [...] > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > + { .compatible = "amlogic,a1-clkc", }, > + {}, nit-pick: please remove the comma after the sentinel > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > + > +static struct platform_driver a1_periphs_clkc_driver = { > + .probe = meson_a1_periphs_probe, > + .driver = { > + .name = "a1-clkc", > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), I wonder if we should drop of_match_ptr() here as no other meson clock driver uses it. Also there's commits like 00cb754ac622 ("clk: imx8mq: drop of_match_ptr from of_device_id table") which explicitly remove it from other drivers. Apart form these two this patch looks great to me. Best regards, Martin _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver 2023-04-23 21:30 ` Martin Blumenstingl (?) @ 2023-04-25 12:05 ` Dmitry Rokosov -1 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:05 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Sun, Apr 23, 2023 at 11:30:38PM +0200, Martin Blumenstingl wrote: > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-clkc", }, > > + {}, > nit-pick: please remove the comma after the sentinel > Thank you for bringing up that point! There's no problem with removing it in the next version of the product. I'll prepare it. > > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > > + > > +static struct platform_driver a1_periphs_clkc_driver = { > > + .probe = meson_a1_periphs_probe, > > + .driver = { > > + .name = "a1-clkc", > > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), > I wonder if we should drop of_match_ptr() here as no other meson clock > driver uses it. > Also there's commits like 00cb754ac622 ("clk: imx8mq: drop > of_match_ptr from of_device_id table") which explicitly remove it from > other drivers. Exactly, all Meson clock drivers depend on the ARM64 config, which in turn selects CONFIG_OF by default. So of_match_ptr can be dropped. > > Apart form these two this patch looks great to me. > -- Thank you, Dmitry ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-25 12:05 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:05 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Sun, Apr 23, 2023 at 11:30:38PM +0200, Martin Blumenstingl wrote: > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-clkc", }, > > + {}, > nit-pick: please remove the comma after the sentinel > Thank you for bringing up that point! There's no problem with removing it in the next version of the product. I'll prepare it. > > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > > + > > +static struct platform_driver a1_periphs_clkc_driver = { > > + .probe = meson_a1_periphs_probe, > > + .driver = { > > + .name = "a1-clkc", > > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), > I wonder if we should drop of_match_ptr() here as no other meson clock > driver uses it. > Also there's commits like 00cb754ac622 ("clk: imx8mq: drop > of_match_ptr from of_device_id table") which explicitly remove it from > other drivers. Exactly, all Meson clock drivers depend on the ARM64 config, which in turn selects CONFIG_OF by default. So of_match_ptr can be dropped. > > Apart form these two this patch looks great to me. > -- Thank you, Dmitry _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 52+ messages in thread
* Re: [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver @ 2023-04-25 12:05 ` Dmitry Rokosov 0 siblings, 0 replies; 52+ messages in thread From: Dmitry Rokosov @ 2023-04-25 12:05 UTC (permalink / raw) To: Martin Blumenstingl Cc: neil.armstrong, jbrunet, mturquette, sboyd, robh+dt, krzysztof.kozlowski+dt, khilman, jian.hu, kernel, rockosov, linux-amlogic, linux-clk, devicetree, linux-kernel, linux-arm-kernel On Sun, Apr 23, 2023 at 11:30:38PM +0200, Martin Blumenstingl wrote: > On Wed, Apr 5, 2023 at 9:59 PM Dmitry Rokosov <ddrokosov@sberdevices.ru> wrote: > [...] > > +static const struct of_device_id a1_periphs_clkc_match_table[] = { > > + { .compatible = "amlogic,a1-clkc", }, > > + {}, > nit-pick: please remove the comma after the sentinel > Thank you for bringing up that point! There's no problem with removing it in the next version of the product. I'll prepare it. > > +MODULE_DEVICE_TABLE(of, a1_periphs_clkc_match_table); > > + > > +static struct platform_driver a1_periphs_clkc_driver = { > > + .probe = meson_a1_periphs_probe, > > + .driver = { > > + .name = "a1-clkc", > > + .of_match_table = of_match_ptr(a1_periphs_clkc_match_table), > I wonder if we should drop of_match_ptr() here as no other meson clock > driver uses it. > Also there's commits like 00cb754ac622 ("clk: imx8mq: drop > of_match_ptr from of_device_id table") which explicitly remove it from > other drivers. Exactly, all Meson clock drivers depend on the ARM64 config, which in turn selects CONFIG_OF by default. So of_match_ptr can be dropped. > > Apart form these two this patch looks great to me. > -- Thank you, Dmitry _______________________________________________ linux-amlogic mailing list linux-amlogic@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-amlogic ^ permalink raw reply [flat|nested] 52+ messages in thread
end of thread, other threads:[~2023-05-29 20:24 UTC | newest] Thread overview: 52+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2023-04-05 19:59 [PATCH v13 0/6] add Amlogic A1 clock controller drivers Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` [PATCH v13 1/6] clk: meson: make pll rst bit as optional Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` [PATCH v13 2/6] clk: meson: introduce new pll power-on sequence for A1 SoC family Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` [PATCH v13 3/6] dt-bindings: clock: meson: add A1 PLL clock controller bindings Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-12 13:46 ` Rob Herring 2023-04-12 13:46 ` Rob Herring 2023-04-12 13:46 ` Rob Herring 2023-04-05 19:59 ` [PATCH v13 4/6] clk: meson: a1: add Amlogic A1 PLL clock controller driver Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-23 21:12 ` Martin Blumenstingl 2023-04-23 21:12 ` Martin Blumenstingl 2023-04-23 21:12 ` Martin Blumenstingl 2023-04-25 12:33 ` Dmitry Rokosov 2023-04-25 12:33 ` Dmitry Rokosov 2023-04-25 12:33 ` Dmitry Rokosov 2023-05-01 18:39 ` Martin Blumenstingl 2023-05-01 18:39 ` Martin Blumenstingl 2023-05-01 18:39 ` Martin Blumenstingl 2023-05-11 13:26 ` Dmitry Rokosov 2023-05-11 13:26 ` Dmitry Rokosov 2023-05-14 20:53 ` Martin Blumenstingl 2023-05-14 20:53 ` Martin Blumenstingl 2023-05-29 13:49 ` Dmitry Rokosov 2023-05-29 13:49 ` Dmitry Rokosov 2023-05-29 13:49 ` Dmitry Rokosov 2023-05-29 20:23 ` Martin Blumenstingl 2023-05-29 20:23 ` Martin Blumenstingl 2023-05-29 20:23 ` Martin Blumenstingl 2023-04-05 19:59 ` [PATCH v13 5/6] dt-bindings: clock: meson: add A1 Peripherals clock controller bindings Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-12 13:46 ` Rob Herring 2023-04-12 13:46 ` Rob Herring 2023-04-12 13:46 ` Rob Herring 2023-04-05 19:59 ` [PATCH v13 6/6] clk: meson: a1: add Amlogic A1 Peripherals clock controller driver Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-05 19:59 ` Dmitry Rokosov 2023-04-23 21:30 ` Martin Blumenstingl 2023-04-23 21:30 ` Martin Blumenstingl 2023-04-23 21:30 ` Martin Blumenstingl 2023-04-25 12:05 ` Dmitry Rokosov 2023-04-25 12:05 ` Dmitry Rokosov 2023-04-25 12:05 ` Dmitry Rokosov
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.