diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 18:49:45 +0000 |
commit | 2c3c1048746a4622d8c89a29670120dc8fab93c4 (patch) | |
tree | 848558de17fb3008cdf4d861b01ac7781903ce39 /drivers/clk/mediatek | |
parent | Initial commit. (diff) | |
download | linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.tar.xz linux-2c3c1048746a4622d8c89a29670120dc8fab93c4.zip |
Adding upstream version 6.1.76.upstream/6.1.76
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to '')
148 files changed, 31061 insertions, 0 deletions
diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig new file mode 100644 index 000000000..843cea0c7 --- /dev/null +++ b/drivers/clk/mediatek/Kconfig @@ -0,0 +1,712 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# MediaTek Clock Drivers +# +menu "Clock driver for MediaTek SoC" + depends on ARCH_MEDIATEK || COMPILE_TEST + +config COMMON_CLK_MEDIATEK + tristate + select RESET_CONTROLLER + help + MediaTek SoCs' clock support. + +config COMMON_CLK_MT2701 + bool "Clock driver for MediaTek MT2701" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM + help + This driver supports MediaTek MT2701 basic clocks. + +config COMMON_CLK_MT2701_MMSYS + bool "Clock driver for MediaTek MT2701 mmsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 mmsys clocks. + +config COMMON_CLK_MT2701_IMGSYS + bool "Clock driver for MediaTek MT2701 imgsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 imgsys clocks. + +config COMMON_CLK_MT2701_VDECSYS + bool "Clock driver for MediaTek MT2701 vdecsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 vdecsys clocks. + +config COMMON_CLK_MT2701_HIFSYS + bool "Clock driver for MediaTek MT2701 hifsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 hifsys clocks. + +config COMMON_CLK_MT2701_ETHSYS + bool "Clock driver for MediaTek MT2701 ethsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 ethsys clocks. + +config COMMON_CLK_MT2701_BDPSYS + bool "Clock driver for MediaTek MT2701 bdpsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 bdpsys clocks. + +config COMMON_CLK_MT2701_AUDSYS + bool "Clock driver for Mediatek MT2701 audsys" + depends on COMMON_CLK_MT2701 + help + This driver supports Mediatek MT2701 audsys clocks. + +config COMMON_CLK_MT2701_G3DSYS + bool "Clock driver for MediaTek MT2701 g3dsys" + depends on COMMON_CLK_MT2701 + help + This driver supports MediaTek MT2701 g3dsys clocks. + +config COMMON_CLK_MT2712 + bool "Clock driver for MediaTek MT2712" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT2712 basic clocks. + +config COMMON_CLK_MT2712_BDPSYS + bool "Clock driver for MediaTek MT2712 bdpsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 bdpsys clocks. + +config COMMON_CLK_MT2712_IMGSYS + bool "Clock driver for MediaTek MT2712 imgsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 imgsys clocks. + +config COMMON_CLK_MT2712_JPGDECSYS + bool "Clock driver for MediaTek MT2712 jpgdecsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 jpgdecsys clocks. + +config COMMON_CLK_MT2712_MFGCFG + bool "Clock driver for MediaTek MT2712 mfgcfg" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 mfgcfg clocks. + +config COMMON_CLK_MT2712_MMSYS + bool "Clock driver for MediaTek MT2712 mmsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 mmsys clocks. + +config COMMON_CLK_MT2712_VDECSYS + bool "Clock driver for MediaTek MT2712 vdecsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 vdecsys clocks. + +config COMMON_CLK_MT2712_VENCSYS + bool "Clock driver for MediaTek MT2712 vencsys" + depends on COMMON_CLK_MT2712 + help + This driver supports MediaTek MT2712 vencsys clocks. + +config COMMON_CLK_MT6765 + bool "Clock driver for MediaTek MT6765" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT6765 basic clocks. + +config COMMON_CLK_MT6765_AUDIOSYS + bool "Clock driver for MediaTek MT6765 audiosys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 audiosys clocks. + +config COMMON_CLK_MT6765_CAMSYS + bool "Clock driver for MediaTek MT6765 camsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 camsys clocks. + +config COMMON_CLK_MT6765_GCESYS + bool "Clock driver for MediaTek MT6765 gcesys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 gcesys clocks. + +config COMMON_CLK_MT6765_MMSYS + bool "Clock driver for MediaTek MT6765 mmsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mmsys clocks. + +config COMMON_CLK_MT6765_IMGSYS + bool "Clock driver for MediaTek MT6765 imgsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 imgsys clocks. + +config COMMON_CLK_MT6765_VCODECSYS + bool "Clock driver for MediaTek MT6765 vcodecsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 vcodecsys clocks. + +config COMMON_CLK_MT6765_MFGSYS + bool "Clock driver for MediaTek MT6765 mfgsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mfgsys clocks. + +config COMMON_CLK_MT6765_MIPI0ASYS + bool "Clock driver for MediaTek MT6765 mipi0asys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi0asys clocks. + +config COMMON_CLK_MT6765_MIPI0BSYS + bool "Clock driver for MediaTek MT6765 mipi0bsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi0bsys clocks. + +config COMMON_CLK_MT6765_MIPI1ASYS + bool "Clock driver for MediaTek MT6765 mipi1asys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi1asys clocks. + +config COMMON_CLK_MT6765_MIPI1BSYS + bool "Clock driver for MediaTek MT6765 mipi1bsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi1bsys clocks. + +config COMMON_CLK_MT6765_MIPI2ASYS + bool "Clock driver for MediaTek MT6765 mipi2asys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi2asys clocks. + +config COMMON_CLK_MT6765_MIPI2BSYS + bool "Clock driver for MediaTek MT6765 mipi2bsys" + depends on COMMON_CLK_MT6765 + help + This driver supports MediaTek MT6765 mipi2bsys clocks. + +config COMMON_CLK_MT6779 + tristate "Clock driver for MediaTek MT6779" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT6779 basic clocks. + +config COMMON_CLK_MT6779_MMSYS + tristate "Clock driver for MediaTek MT6779 mmsys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 mmsys clocks. + +config COMMON_CLK_MT6779_IMGSYS + tristate "Clock driver for MediaTek MT6779 imgsys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 imgsys clocks. + +config COMMON_CLK_MT6779_IPESYS + tristate "Clock driver for MediaTek MT6779 ipesys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 ipesys clocks. + +config COMMON_CLK_MT6779_CAMSYS + tristate "Clock driver for MediaTek MT6779 camsys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 camsys clocks. + +config COMMON_CLK_MT6779_VDECSYS + tristate "Clock driver for MediaTek MT6779 vdecsys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 vdecsys clocks. + +config COMMON_CLK_MT6779_VENCSYS + tristate "Clock driver for MediaTek MT6779 vencsys" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 vencsys clocks. + +config COMMON_CLK_MT6779_MFGCFG + tristate "Clock driver for MediaTek MT6779 mfgcfg" + depends on COMMON_CLK_MT6779 + help + This driver supports MediaTek MT6779 mfgcfg clocks. + +config COMMON_CLK_MT6779_AUDSYS + tristate "Clock driver for Mediatek MT6779 audsys" + depends on COMMON_CLK_MT6779 + help + This driver supports Mediatek MT6779 audsys clocks. + +config COMMON_CLK_MT6795 + tristate "Clock driver for MediaTek MT6795" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT6795 basic clocks and clocks + required for various peripherals found on MediaTek. + +config COMMON_CLK_MT6795_MFGCFG + tristate "Clock driver for MediaTek MT6795 mfgcfg" + depends on COMMON_CLK_MT6795 + default COMMON_CLK_MT6795 + help + This driver supports MediaTek MT6795 mfgcfg clocks. + +config COMMON_CLK_MT6795_MMSYS + tristate "Clock driver for MediaTek MT6795 mmsys" + depends on COMMON_CLK_MT6795 + default COMMON_CLK_MT6795 + help + This driver supports MediaTek MT6795 mmsys clocks. + +config COMMON_CLK_MT6795_VDECSYS + tristate "Clock driver for MediaTek MT6795 VDECSYS" + depends on COMMON_CLK_MT6795 + default COMMON_CLK_MT6795 + help + This driver supports MediaTek MT6795 vdecsys clocks. + +config COMMON_CLK_MT6795_VENCSYS + tristate "Clock driver for MediaTek MT6795 VENCSYS" + depends on COMMON_CLK_MT6795 + default COMMON_CLK_MT6795 + help + This driver supports MediaTek MT6795 vencsys clocks. + +config COMMON_CLK_MT6797 + bool "Clock driver for MediaTek MT6797" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT6797 basic clocks. + +config COMMON_CLK_MT6797_MMSYS + bool "Clock driver for MediaTek MT6797 mmsys" + depends on COMMON_CLK_MT6797 + help + This driver supports MediaTek MT6797 mmsys clocks. + +config COMMON_CLK_MT6797_IMGSYS + bool "Clock driver for MediaTek MT6797 imgsys" + depends on COMMON_CLK_MT6797 + help + This driver supports MediaTek MT6797 imgsys clocks. + +config COMMON_CLK_MT6797_VDECSYS + bool "Clock driver for MediaTek MT6797 vdecsys" + depends on COMMON_CLK_MT6797 + help + This driver supports MediaTek MT6797 vdecsys clocks. + +config COMMON_CLK_MT6797_VENCSYS + bool "Clock driver for MediaTek MT6797 vencsys" + depends on COMMON_CLK_MT6797 + help + This driver supports MediaTek MT6797 vencsys clocks. + +config COMMON_CLK_MT7622 + bool "Clock driver for MediaTek MT7622" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT7622 basic clocks and clocks + required for various periperals found on MediaTek. + +config COMMON_CLK_MT7622_ETHSYS + bool "Clock driver for MediaTek MT7622 ETHSYS" + depends on COMMON_CLK_MT7622 + help + This driver add support for clocks for Ethernet and SGMII + required on MediaTek MT7622 SoC. + +config COMMON_CLK_MT7622_HIFSYS + bool "Clock driver for MediaTek MT7622 HIFSYS" + depends on COMMON_CLK_MT7622 + help + This driver supports MediaTek MT7622 HIFSYS clocks providing + to PCI-E and USB. + +config COMMON_CLK_MT7622_AUDSYS + bool "Clock driver for MediaTek MT7622 AUDSYS" + depends on COMMON_CLK_MT7622 + help + This driver supports MediaTek MT7622 AUDSYS clocks providing + to audio consumers such as I2S and TDM. + +config COMMON_CLK_MT7629 + bool "Clock driver for MediaTek MT7629" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM + help + This driver supports MediaTek MT7629 basic clocks and clocks + required for various periperals found on MediaTek. + +config COMMON_CLK_MT7629_ETHSYS + bool "Clock driver for MediaTek MT7629 ETHSYS" + depends on COMMON_CLK_MT7629 + help + This driver add support for clocks for Ethernet and SGMII + required on MediaTek MT7629 SoC. + +config COMMON_CLK_MT7629_HIFSYS + bool "Clock driver for MediaTek MT7629 HIFSYS" + depends on COMMON_CLK_MT7629 + help + This driver supports MediaTek MT7629 HIFSYS clocks providing + to PCI-E and USB. + +config COMMON_CLK_MT7986 + bool "Clock driver for MediaTek MT7986" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT7986 basic clocks and clocks + required for various peripherals found on MediaTek. + +config COMMON_CLK_MT7986_ETHSYS + bool "Clock driver for MediaTek MT7986 ETHSYS" + depends on COMMON_CLK_MT7986 + default COMMON_CLK_MT7986 + help + This driver adds support for clocks for Ethernet and SGMII + required on MediaTek MT7986 SoC. + +config COMMON_CLK_MT8135 + bool "Clock driver for MediaTek MT8135" + depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM + help + This driver supports MediaTek MT8135 clocks. + +config COMMON_CLK_MT8167 + bool "Clock driver for MediaTek MT8167" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8167 basic clocks. + +config COMMON_CLK_MT8167_AUDSYS + bool "Clock driver for MediaTek MT8167 audsys" + depends on COMMON_CLK_MT8167 + default COMMON_CLK_MT8167 + help + This driver supports MediaTek MT8167 audsys clocks. + +config COMMON_CLK_MT8167_IMGSYS + bool "Clock driver for MediaTek MT8167 imgsys" + depends on COMMON_CLK_MT8167 + default COMMON_CLK_MT8167 + help + This driver supports MediaTek MT8167 imgsys clocks. + +config COMMON_CLK_MT8167_MFGCFG + bool "Clock driver for MediaTek MT8167 mfgcfg" + depends on COMMON_CLK_MT8167 + default COMMON_CLK_MT8167 + help + This driver supports MediaTek MT8167 mfgcfg clocks. + +config COMMON_CLK_MT8167_MMSYS + bool "Clock driver for MediaTek MT8167 mmsys" + depends on COMMON_CLK_MT8167 + default COMMON_CLK_MT8167 + help + This driver supports MediaTek MT8167 mmsys clocks. + +config COMMON_CLK_MT8167_VDECSYS + bool "Clock driver for MediaTek MT8167 vdecsys" + depends on COMMON_CLK_MT8167 + default COMMON_CLK_MT8167 + help + This driver supports MediaTek MT8167 vdecsys clocks. + +config COMMON_CLK_MT8173 + bool "Clock driver for MediaTek MT8173" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8173 clocks. + +config COMMON_CLK_MT8173_MMSYS + bool "Clock driver for MediaTek MT8173 mmsys" + depends on COMMON_CLK_MT8173 + default COMMON_CLK_MT8173 + help + This driver supports MediaTek MT8173 mmsys clocks. + +config COMMON_CLK_MT8183 + bool "Clock driver for MediaTek MT8183" + depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT8183 basic clocks. + +config COMMON_CLK_MT8183_AUDIOSYS + bool "Clock driver for MediaTek MT8183 audiosys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 audiosys clocks. + +config COMMON_CLK_MT8183_CAMSYS + bool "Clock driver for MediaTek MT8183 camsys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 camsys clocks. + +config COMMON_CLK_MT8183_IMGSYS + bool "Clock driver for MediaTek MT8183 imgsys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 imgsys clocks. + +config COMMON_CLK_MT8183_IPU_CORE0 + bool "Clock driver for MediaTek MT8183 ipu_core0" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 ipu_core0 clocks. + +config COMMON_CLK_MT8183_IPU_CORE1 + bool "Clock driver for MediaTek MT8183 ipu_core1" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 ipu_core1 clocks. + +config COMMON_CLK_MT8183_IPU_ADL + bool "Clock driver for MediaTek MT8183 ipu_adl" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 ipu_adl clocks. + +config COMMON_CLK_MT8183_IPU_CONN + bool "Clock driver for MediaTek MT8183 ipu_conn" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 ipu_conn clocks. + +config COMMON_CLK_MT8183_MFGCFG + bool "Clock driver for MediaTek MT8183 mfgcfg" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 mfgcfg clocks. + +config COMMON_CLK_MT8183_MMSYS + bool "Clock driver for MediaTek MT8183 mmsys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 mmsys clocks. + +config COMMON_CLK_MT8183_VDECSYS + bool "Clock driver for MediaTek MT8183 vdecsys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 vdecsys clocks. + +config COMMON_CLK_MT8183_VENCSYS + bool "Clock driver for MediaTek MT8183 vencsys" + depends on COMMON_CLK_MT8183 + default COMMON_CLK_MT8183 + help + This driver supports MediaTek MT8183 vencsys clocks. + +config COMMON_CLK_MT8186 + bool "Clock driver for MediaTek MT8186" + depends on ARM64 || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8186 clocks. + +config COMMON_CLK_MT8192 + bool "Clock driver for MediaTek MT8192" + depends on ARM64 || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARM64 + help + This driver supports MediaTek MT8192 basic clocks. + +config COMMON_CLK_MT8192_AUDSYS + bool "Clock driver for MediaTek MT8192 audsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 audsys clocks. + +config COMMON_CLK_MT8192_CAMSYS + bool "Clock driver for MediaTek MT8192 camsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 camsys and camsys_raw clocks. + +config COMMON_CLK_MT8192_IMGSYS + bool "Clock driver for MediaTek MT8192 imgsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 imgsys and imgsys2 clocks. + +config COMMON_CLK_MT8192_IMP_IIC_WRAP + bool "Clock driver for MediaTek MT8192 imp_iic_wrap" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 imp_iic_wrap clocks. + +config COMMON_CLK_MT8192_IPESYS + bool "Clock driver for MediaTek MT8192 ipesys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 ipesys clocks. + +config COMMON_CLK_MT8192_MDPSYS + bool "Clock driver for MediaTek MT8192 mdpsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 mdpsys clocks. + +config COMMON_CLK_MT8192_MFGCFG + bool "Clock driver for MediaTek MT8192 mfgcfg" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 mfgcfg clocks. + +config COMMON_CLK_MT8192_MMSYS + bool "Clock driver for MediaTek MT8192 mmsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 mmsys clocks. + +config COMMON_CLK_MT8192_MSDC + bool "Clock driver for MediaTek MT8192 msdc" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 msdc and msdc_top clocks. + +config COMMON_CLK_MT8192_SCP_ADSP + bool "Clock driver for MediaTek MT8192 scp_adsp" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 scp_adsp clocks. + +config COMMON_CLK_MT8192_VDECSYS + bool "Clock driver for MediaTek MT8192 vdecsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 vdecsys and vdecsys_soc clocks. + +config COMMON_CLK_MT8192_VENCSYS + bool "Clock driver for MediaTek MT8192 vencsys" + depends on COMMON_CLK_MT8192 + help + This driver supports MediaTek MT8192 vencsys clocks. + +config COMMON_CLK_MT8195 + bool "Clock driver for MediaTek MT8195" + depends on ARM64 || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8195 clocks. + +config COMMON_CLK_MT8365 + tristate "Clock driver for MediaTek MT8365" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK && ARM64 + help + This driver supports MediaTek MT8365 basic clocks. + +config COMMON_CLK_MT8365_APU + tristate "Clock driver for MediaTek MT8365 apu" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 apu clocks. + +config COMMON_CLK_MT8365_CAM + tristate "Clock driver for MediaTek MT8365 cam" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 cam clocks. + +config COMMON_CLK_MT8365_MFG + tristate "Clock driver for MediaTek MT8365 mfg" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 mfg clocks. + +config COMMON_CLK_MT8365_MMSYS + tristate "Clock driver for MediaTek MT8365 mmsys" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 mmsys clocks. + +config COMMON_CLK_MT8365_VDEC + tristate "Clock driver for MediaTek MT8365 vdec" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 vdec clocks. + +config COMMON_CLK_MT8365_VENC + tristate "Clock driver for MediaTek MT8365 venc" + depends on COMMON_CLK_MT8365 + default COMMON_CLK_MT8365 + help + This driver supports MediaTek MT8365 venc clocks. + +config COMMON_CLK_MT8516 + bool "Clock driver for MediaTek MT8516" + depends on ARCH_MEDIATEK || COMPILE_TEST + select COMMON_CLK_MEDIATEK + default ARCH_MEDIATEK + help + This driver supports MediaTek MT8516 clocks. + +config COMMON_CLK_MT8516_AUDSYS + bool "Clock driver for MediaTek MT8516 audsys" + depends on COMMON_CLK_MT8516 + help + This driver supports MediaTek MT8516 audsys clocks. + +endmenu diff --git a/drivers/clk/mediatek/Makefile b/drivers/clk/mediatek/Makefile new file mode 100644 index 000000000..ea3b73240 --- /dev/null +++ b/drivers/clk/mediatek/Makefile @@ -0,0 +1,114 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o + +obj-$(CONFIG_COMMON_CLK_MT6765) += clk-mt6765.o +obj-$(CONFIG_COMMON_CLK_MT6765_AUDIOSYS) += clk-mt6765-audio.o +obj-$(CONFIG_COMMON_CLK_MT6765_CAMSYS) += clk-mt6765-cam.o +obj-$(CONFIG_COMMON_CLK_MT6765_IMGSYS) += clk-mt6765-img.o +obj-$(CONFIG_COMMON_CLK_MT6765_MIPI0ASYS) += clk-mt6765-mipi0a.o +obj-$(CONFIG_COMMON_CLK_MT6765_MMSYS) += clk-mt6765-mm.o +obj-$(CONFIG_COMMON_CLK_MT6765_VCODECSYS) += clk-mt6765-vcodec.o +obj-$(CONFIG_COMMON_CLK_MT6779) += clk-mt6779.o +obj-$(CONFIG_COMMON_CLK_MT6779_MMSYS) += clk-mt6779-mm.o +obj-$(CONFIG_COMMON_CLK_MT6779_IMGSYS) += clk-mt6779-img.o +obj-$(CONFIG_COMMON_CLK_MT6779_IPESYS) += clk-mt6779-ipe.o +obj-$(CONFIG_COMMON_CLK_MT6779_CAMSYS) += clk-mt6779-cam.o +obj-$(CONFIG_COMMON_CLK_MT6779_VDECSYS) += clk-mt6779-vdec.o +obj-$(CONFIG_COMMON_CLK_MT6779_VENCSYS) += clk-mt6779-venc.o +obj-$(CONFIG_COMMON_CLK_MT6779_MFGCFG) += clk-mt6779-mfg.o +obj-$(CONFIG_COMMON_CLK_MT6779_AUDSYS) += clk-mt6779-aud.o +obj-$(CONFIG_COMMON_CLK_MT6795) += clk-mt6795-apmixedsys.o clk-mt6795-infracfg.o \ + clk-mt6795-pericfg.o clk-mt6795-topckgen.o +obj-$(CONFIG_COMMON_CLK_MT6795_MFGCFG) += clk-mt6795-mfg.o +obj-$(CONFIG_COMMON_CLK_MT6795_MMSYS) += clk-mt6795-mm.o +obj-$(CONFIG_COMMON_CLK_MT6795_VDECSYS) += clk-mt6795-vdecsys.o +obj-$(CONFIG_COMMON_CLK_MT6795_VENCSYS) += clk-mt6795-vencsys.o +obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o +obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o +obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o +obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o +obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o +obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o +obj-$(CONFIG_COMMON_CLK_MT2701_AUDSYS) += clk-mt2701-aud.o +obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o +obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o +obj-$(CONFIG_COMMON_CLK_MT2701_G3DSYS) += clk-mt2701-g3d.o +obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o +obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o +obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o +obj-$(CONFIG_COMMON_CLK_MT2701_VDECSYS) += clk-mt2701-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712) += clk-mt2712.o +obj-$(CONFIG_COMMON_CLK_MT2712_BDPSYS) += clk-mt2712-bdp.o +obj-$(CONFIG_COMMON_CLK_MT2712_IMGSYS) += clk-mt2712-img.o +obj-$(CONFIG_COMMON_CLK_MT2712_JPGDECSYS) += clk-mt2712-jpgdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_MFGCFG) += clk-mt2712-mfg.o +obj-$(CONFIG_COMMON_CLK_MT2712_MMSYS) += clk-mt2712-mm.o +obj-$(CONFIG_COMMON_CLK_MT2712_VDECSYS) += clk-mt2712-vdec.o +obj-$(CONFIG_COMMON_CLK_MT2712_VENCSYS) += clk-mt2712-venc.o +obj-$(CONFIG_COMMON_CLK_MT7622) += clk-mt7622.o +obj-$(CONFIG_COMMON_CLK_MT7622_ETHSYS) += clk-mt7622-eth.o +obj-$(CONFIG_COMMON_CLK_MT7622_HIFSYS) += clk-mt7622-hif.o +obj-$(CONFIG_COMMON_CLK_MT7622_AUDSYS) += clk-mt7622-aud.o +obj-$(CONFIG_COMMON_CLK_MT7629) += clk-mt7629.o +obj-$(CONFIG_COMMON_CLK_MT7629_ETHSYS) += clk-mt7629-eth.o +obj-$(CONFIG_COMMON_CLK_MT7629_HIFSYS) += clk-mt7629-hif.o +obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-apmixed.o +obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-topckgen.o +obj-$(CONFIG_COMMON_CLK_MT7986) += clk-mt7986-infracfg.o +obj-$(CONFIG_COMMON_CLK_MT7986_ETHSYS) += clk-mt7986-eth.o +obj-$(CONFIG_COMMON_CLK_MT8135) += clk-mt8135.o +obj-$(CONFIG_COMMON_CLK_MT8167) += clk-mt8167.o +obj-$(CONFIG_COMMON_CLK_MT8167_AUDSYS) += clk-mt8167-aud.o +obj-$(CONFIG_COMMON_CLK_MT8167_IMGSYS) += clk-mt8167-img.o +obj-$(CONFIG_COMMON_CLK_MT8167_MFGCFG) += clk-mt8167-mfgcfg.o +obj-$(CONFIG_COMMON_CLK_MT8167_MMSYS) += clk-mt8167-mm.o +obj-$(CONFIG_COMMON_CLK_MT8167_VDECSYS) += clk-mt8167-vdec.o +obj-$(CONFIG_COMMON_CLK_MT8173) += clk-mt8173.o +obj-$(CONFIG_COMMON_CLK_MT8173_MMSYS) += clk-mt8173-mm.o +obj-$(CONFIG_COMMON_CLK_MT8183) += clk-mt8183.o +obj-$(CONFIG_COMMON_CLK_MT8183_AUDIOSYS) += clk-mt8183-audio.o +obj-$(CONFIG_COMMON_CLK_MT8183_CAMSYS) += clk-mt8183-cam.o +obj-$(CONFIG_COMMON_CLK_MT8183_IMGSYS) += clk-mt8183-img.o +obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CORE0) += clk-mt8183-ipu0.o +obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CORE1) += clk-mt8183-ipu1.o +obj-$(CONFIG_COMMON_CLK_MT8183_IPU_ADL) += clk-mt8183-ipu_adl.o +obj-$(CONFIG_COMMON_CLK_MT8183_IPU_CONN) += clk-mt8183-ipu_conn.o +obj-$(CONFIG_COMMON_CLK_MT8183_MFGCFG) += clk-mt8183-mfgcfg.o +obj-$(CONFIG_COMMON_CLK_MT8183_MMSYS) += clk-mt8183-mm.o +obj-$(CONFIG_COMMON_CLK_MT8183_VDECSYS) += clk-mt8183-vdec.o +obj-$(CONFIG_COMMON_CLK_MT8183_VENCSYS) += clk-mt8183-venc.o +obj-$(CONFIG_COMMON_CLK_MT8186) += clk-mt8186-mcu.o clk-mt8186-topckgen.o clk-mt8186-infra_ao.o \ + clk-mt8186-apmixedsys.o clk-mt8186-imp_iic_wrap.o \ + clk-mt8186-mfg.o clk-mt8186-mm.o clk-mt8186-wpe.o \ + clk-mt8186-img.o clk-mt8186-vdec.o clk-mt8186-venc.o \ + clk-mt8186-cam.o clk-mt8186-mdp.o clk-mt8186-ipe.o +obj-$(CONFIG_COMMON_CLK_MT8192) += clk-mt8192.o +obj-$(CONFIG_COMMON_CLK_MT8192_AUDSYS) += clk-mt8192-aud.o +obj-$(CONFIG_COMMON_CLK_MT8192_CAMSYS) += clk-mt8192-cam.o +obj-$(CONFIG_COMMON_CLK_MT8192_IMGSYS) += clk-mt8192-img.o +obj-$(CONFIG_COMMON_CLK_MT8192_IMP_IIC_WRAP) += clk-mt8192-imp_iic_wrap.o +obj-$(CONFIG_COMMON_CLK_MT8192_IPESYS) += clk-mt8192-ipe.o +obj-$(CONFIG_COMMON_CLK_MT8192_MDPSYS) += clk-mt8192-mdp.o +obj-$(CONFIG_COMMON_CLK_MT8192_MFGCFG) += clk-mt8192-mfg.o +obj-$(CONFIG_COMMON_CLK_MT8192_MMSYS) += clk-mt8192-mm.o +obj-$(CONFIG_COMMON_CLK_MT8192_MSDC) += clk-mt8192-msdc.o +obj-$(CONFIG_COMMON_CLK_MT8192_SCP_ADSP) += clk-mt8192-scp_adsp.o +obj-$(CONFIG_COMMON_CLK_MT8192_VDECSYS) += clk-mt8192-vdec.o +obj-$(CONFIG_COMMON_CLK_MT8192_VENCSYS) += clk-mt8192-venc.o +obj-$(CONFIG_COMMON_CLK_MT8195) += clk-mt8195-apmixedsys.o clk-mt8195-topckgen.o \ + clk-mt8195-peri_ao.o clk-mt8195-infra_ao.o \ + clk-mt8195-cam.o clk-mt8195-ccu.o clk-mt8195-img.o \ + clk-mt8195-ipe.o clk-mt8195-mfg.o clk-mt8195-scp_adsp.o \ + clk-mt8195-vdec.o clk-mt8195-vdo0.o clk-mt8195-vdo1.o \ + clk-mt8195-venc.o clk-mt8195-vpp0.o clk-mt8195-vpp1.o \ + clk-mt8195-wpe.o clk-mt8195-imp_iic_wrap.o \ + clk-mt8195-apusys_pll.o +obj-$(CONFIG_COMMON_CLK_MT8365) += clk-mt8365.o +obj-$(CONFIG_COMMON_CLK_MT8365_APU) += clk-mt8365-apu.o +obj-$(CONFIG_COMMON_CLK_MT8365_CAM) += clk-mt8365-cam.o +obj-$(CONFIG_COMMON_CLK_MT8365_MFG) += clk-mt8365-mfg.o +obj-$(CONFIG_COMMON_CLK_MT8365_MMSYS) += clk-mt8365-mm.o +obj-$(CONFIG_COMMON_CLK_MT8365_VDEC) += clk-mt8365-vdec.o +obj-$(CONFIG_COMMON_CLK_MT8365_VENC) += clk-mt8365-venc.o +obj-$(CONFIG_COMMON_CLK_MT8516) += clk-mt8516.o +obj-$(CONFIG_COMMON_CLK_MT8516_AUDSYS) += clk-mt8516-aud.o diff --git a/drivers/clk/mediatek/clk-apmixed.c b/drivers/clk/mediatek/clk-apmixed.c new file mode 100644 index 000000000..60e34f124 --- /dev/null +++ b/drivers/clk/mediatek/clk-apmixed.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/delay.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/slab.h> + +#include "clk-mtk.h" + +#define REF2USB_TX_EN BIT(0) +#define REF2USB_TX_LPF_EN BIT(1) +#define REF2USB_TX_OUT_EN BIT(2) +#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \ + REF2USB_TX_OUT_EN) + +struct mtk_ref2usb_tx { + struct clk_hw hw; + void __iomem *base_addr; +}; + +static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_ref2usb_tx, hw); +} + +static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw) +{ + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); + + return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK; +} + +static int mtk_ref2usb_tx_prepare(struct clk_hw *hw) +{ + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); + u32 val; + + val = readl(tx->base_addr); + + val |= REF2USB_TX_EN; + writel(val, tx->base_addr); + udelay(100); + + val |= REF2USB_TX_LPF_EN; + writel(val, tx->base_addr); + + val |= REF2USB_TX_OUT_EN; + writel(val, tx->base_addr); + + return 0; +} + +static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw) +{ + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); + u32 val; + + val = readl(tx->base_addr); + val &= ~REF2USB_EN_MASK; + writel(val, tx->base_addr); +} + +static const struct clk_ops mtk_ref2usb_tx_ops = { + .is_prepared = mtk_ref2usb_tx_is_prepared, + .prepare = mtk_ref2usb_tx_prepare, + .unprepare = mtk_ref2usb_tx_unprepare, +}; + +struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name, + const char *parent_name, void __iomem *reg) +{ + struct mtk_ref2usb_tx *tx; + struct clk_init_data init = {}; + int ret; + + tx = kzalloc(sizeof(*tx), GFP_KERNEL); + if (!tx) + return ERR_PTR(-ENOMEM); + + tx->base_addr = reg; + tx->hw.init = &init; + + init.name = name; + init.ops = &mtk_ref2usb_tx_ops; + init.parent_names = &parent_name; + init.num_parents = 1; + + ret = clk_hw_register(NULL, &tx->hw); + + if (ret) { + kfree(tx); + return ERR_PTR(ret); + } + + return &tx->hw; +} +EXPORT_SYMBOL_GPL(mtk_clk_register_ref2usb_tx); + +void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw) +{ + struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw); + + clk_hw_unregister(hw); + kfree(tx); +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_ref2usb_tx); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-cpumux.c b/drivers/clk/mediatek/clk-cpumux.c new file mode 100644 index 000000000..25618eff6 --- /dev/null +++ b/drivers/clk/mediatek/clk-cpumux.c @@ -0,0 +1,172 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2015 Linaro Ltd. + * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> + */ + +#include <linux/clk-provider.h> +#include <linux/container_of.h> +#include <linux/err.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "clk-mtk.h" +#include "clk-cpumux.h" + +struct mtk_clk_cpumux { + struct clk_hw hw; + struct regmap *regmap; + u32 reg; + u32 mask; + u8 shift; +}; + +static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw) +{ + return container_of(_hw, struct mtk_clk_cpumux, hw); +} + +static u8 clk_cpumux_get_parent(struct clk_hw *hw) +{ + struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); + unsigned int val; + + regmap_read(mux->regmap, mux->reg, &val); + + val >>= mux->shift; + val &= mux->mask; + + return val; +} + +static int clk_cpumux_set_parent(struct clk_hw *hw, u8 index) +{ + struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); + u32 mask, val; + + val = index << mux->shift; + mask = mux->mask << mux->shift; + + return regmap_update_bits(mux->regmap, mux->reg, mask, val); +} + +static const struct clk_ops clk_cpumux_ops = { + .get_parent = clk_cpumux_get_parent, + .set_parent = clk_cpumux_set_parent, +}; + +static struct clk_hw * +mtk_clk_register_cpumux(const struct mtk_composite *mux, + struct regmap *regmap) +{ + struct mtk_clk_cpumux *cpumux; + int ret; + struct clk_init_data init; + + cpumux = kzalloc(sizeof(*cpumux), GFP_KERNEL); + if (!cpumux) + return ERR_PTR(-ENOMEM); + + init.name = mux->name; + init.ops = &clk_cpumux_ops; + init.parent_names = mux->parent_names; + init.num_parents = mux->num_parents; + init.flags = mux->flags; + + cpumux->reg = mux->mux_reg; + cpumux->shift = mux->mux_shift; + cpumux->mask = BIT(mux->mux_width) - 1; + cpumux->regmap = regmap; + cpumux->hw.init = &init; + + ret = clk_hw_register(NULL, &cpumux->hw); + if (ret) { + kfree(cpumux); + return ERR_PTR(ret); + } + + return &cpumux->hw; +} + +static void mtk_clk_unregister_cpumux(struct clk_hw *hw) +{ + struct mtk_clk_cpumux *cpumux; + if (!hw) + return; + + cpumux = to_mtk_clk_cpumux(hw); + + clk_hw_unregister(hw); + kfree(cpumux); +} + +int mtk_clk_register_cpumuxes(struct device_node *node, + const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + struct clk_hw *hw; + struct regmap *regmap; + + regmap = device_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + const struct mtk_composite *mux = &clks[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[mux->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, mux->id); + continue; + } + + hw = mtk_clk_register_cpumux(mux, regmap); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, + hw); + goto err; + } + + clk_data->hws[mux->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_composite *mux = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) + continue; + + mtk_clk_unregister_cpumux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_cpumuxes); + +void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + for (i = num; i > 0; i--) { + const struct mtk_composite *mux = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) + continue; + + mtk_clk_unregister_cpumux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_cpumuxes); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-cpumux.h b/drivers/clk/mediatek/clk-cpumux.h new file mode 100644 index 000000000..325adbef2 --- /dev/null +++ b/drivers/clk/mediatek/clk-cpumux.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2015 Linaro Ltd. + * Author: Pi-Cheng Chen <pi-cheng.chen@linaro.org> + */ + +#ifndef __DRV_CLK_CPUMUX_H +#define __DRV_CLK_CPUMUX_H + +struct clk_hw_onecell_data; +struct device_node; +struct mtk_composite; + +int mtk_clk_register_cpumuxes(struct device_node *node, + const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data); + +void mtk_clk_unregister_cpumuxes(const struct mtk_composite *clks, int num, + struct clk_hw_onecell_data *clk_data); + +#endif /* __DRV_CLK_CPUMUX_H */ diff --git a/drivers/clk/mediatek/clk-gate.c b/drivers/clk/mediatek/clk-gate.c new file mode 100644 index 000000000..0c867136e --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.c @@ -0,0 +1,294 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/printk.h> +#include <linux/regmap.h> +#include <linux/slab.h> +#include <linux/types.h> + +#include "clk-gate.h" + +struct mtk_clk_gate { + struct clk_hw hw; + struct regmap *regmap; + int set_ofs; + int clr_ofs; + int sta_ofs; + u8 bit; +}; + +static inline struct mtk_clk_gate *to_mtk_clk_gate(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_gate, hw); +} + +static u32 mtk_get_clockgating(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); + u32 val; + + regmap_read(cg->regmap, cg->sta_ofs, &val); + + return val & BIT(cg->bit); +} + +static int mtk_cg_bit_is_cleared(struct clk_hw *hw) +{ + return mtk_get_clockgating(hw) == 0; +} + +static int mtk_cg_bit_is_set(struct clk_hw *hw) +{ + return mtk_get_clockgating(hw) != 0; +} + +static void mtk_cg_set_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); + + regmap_write(cg->regmap, cg->set_ofs, BIT(cg->bit)); +} + +static void mtk_cg_clr_bit(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); + + regmap_write(cg->regmap, cg->clr_ofs, BIT(cg->bit)); +} + +static void mtk_cg_set_bit_no_setclr(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); + + regmap_set_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit)); +} + +static void mtk_cg_clr_bit_no_setclr(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg = to_mtk_clk_gate(hw); + + regmap_clear_bits(cg->regmap, cg->sta_ofs, BIT(cg->bit)); +} + +static int mtk_cg_enable(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); + + return 0; +} + +static void mtk_cg_disable(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); +} + +static int mtk_cg_enable_inv(struct clk_hw *hw) +{ + mtk_cg_set_bit(hw); + + return 0; +} + +static void mtk_cg_disable_inv(struct clk_hw *hw) +{ + mtk_cg_clr_bit(hw); +} + +static int mtk_cg_enable_no_setclr(struct clk_hw *hw) +{ + mtk_cg_clr_bit_no_setclr(hw); + + return 0; +} + +static void mtk_cg_disable_no_setclr(struct clk_hw *hw) +{ + mtk_cg_set_bit_no_setclr(hw); +} + +static int mtk_cg_enable_inv_no_setclr(struct clk_hw *hw) +{ + mtk_cg_set_bit_no_setclr(hw); + + return 0; +} + +static void mtk_cg_disable_inv_no_setclr(struct clk_hw *hw) +{ + mtk_cg_clr_bit_no_setclr(hw); +} + +const struct clk_ops mtk_clk_gate_ops_setclr = { + .is_enabled = mtk_cg_bit_is_cleared, + .enable = mtk_cg_enable, + .disable = mtk_cg_disable, +}; +EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr); + +const struct clk_ops mtk_clk_gate_ops_setclr_inv = { + .is_enabled = mtk_cg_bit_is_set, + .enable = mtk_cg_enable_inv, + .disable = mtk_cg_disable_inv, +}; +EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_setclr_inv); + +const struct clk_ops mtk_clk_gate_ops_no_setclr = { + .is_enabled = mtk_cg_bit_is_cleared, + .enable = mtk_cg_enable_no_setclr, + .disable = mtk_cg_disable_no_setclr, +}; +EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr); + +const struct clk_ops mtk_clk_gate_ops_no_setclr_inv = { + .is_enabled = mtk_cg_bit_is_set, + .enable = mtk_cg_enable_inv_no_setclr, + .disable = mtk_cg_disable_inv_no_setclr, +}; +EXPORT_SYMBOL_GPL(mtk_clk_gate_ops_no_setclr_inv); + +static struct clk_hw *mtk_clk_register_gate(const char *name, + const char *parent_name, + struct regmap *regmap, int set_ofs, + int clr_ofs, int sta_ofs, u8 bit, + const struct clk_ops *ops, + unsigned long flags, struct device *dev) +{ + struct mtk_clk_gate *cg; + int ret; + struct clk_init_data init = {}; + + cg = kzalloc(sizeof(*cg), GFP_KERNEL); + if (!cg) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = flags | CLK_SET_RATE_PARENT; + init.parent_names = parent_name ? &parent_name : NULL; + init.num_parents = parent_name ? 1 : 0; + init.ops = ops; + + cg->regmap = regmap; + cg->set_ofs = set_ofs; + cg->clr_ofs = clr_ofs; + cg->sta_ofs = sta_ofs; + cg->bit = bit; + + cg->hw.init = &init; + + ret = clk_hw_register(dev, &cg->hw); + if (ret) { + kfree(cg); + return ERR_PTR(ret); + } + + return &cg->hw; +} + +static void mtk_clk_unregister_gate(struct clk_hw *hw) +{ + struct mtk_clk_gate *cg; + if (!hw) + return; + + cg = to_mtk_clk_gate(hw); + + clk_hw_unregister(hw); + kfree(cg); +} + +int mtk_clk_register_gates_with_dev(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data, + struct device *dev) +{ + int i; + struct clk_hw *hw; + struct regmap *regmap; + + if (!clk_data) + return -ENOMEM; + + regmap = device_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + const struct mtk_gate *gate = &clks[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[gate->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, gate->id); + continue; + } + + hw = mtk_clk_register_gate(gate->name, gate->parent_name, + regmap, + gate->regs->set_ofs, + gate->regs->clr_ofs, + gate->regs->sta_ofs, + gate->shift, gate->ops, + gate->flags, dev); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", gate->name, + hw); + goto err; + } + + clk_data->hws[gate->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_gate *gate = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[gate->id])) + continue; + + mtk_clk_unregister_gate(clk_data->hws[gate->id]); + clk_data->hws[gate->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_gates_with_dev); + +int mtk_clk_register_gates(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + return mtk_clk_register_gates_with_dev(node, clks, num, clk_data, NULL); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_gates); + +void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_gate *gate = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[gate->id])) + continue; + + mtk_clk_unregister_gate(clk_data->hws[gate->id]); + clk_data->hws[gate->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_gates); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-gate.h b/drivers/clk/mediatek/clk-gate.h new file mode 100644 index 000000000..d9897ef53 --- /dev/null +++ b/drivers/clk/mediatek/clk-gate.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#ifndef __DRV_CLK_GATE_H +#define __DRV_CLK_GATE_H + +#include <linux/types.h> + +struct clk; +struct clk_hw_onecell_data; +struct clk_ops; +struct device; +struct device_node; + +extern const struct clk_ops mtk_clk_gate_ops_setclr; +extern const struct clk_ops mtk_clk_gate_ops_setclr_inv; +extern const struct clk_ops mtk_clk_gate_ops_no_setclr; +extern const struct clk_ops mtk_clk_gate_ops_no_setclr_inv; + +struct mtk_gate_regs { + u32 sta_ofs; + u32 clr_ofs; + u32 set_ofs; +}; + +struct mtk_gate { + int id; + const char *name; + const char *parent_name; + const struct mtk_gate_regs *regs; + int shift; + const struct clk_ops *ops; + unsigned long flags; +}; + +#define GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, \ + _ops, _flags) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = _regs, \ + .shift = _shift, \ + .ops = _ops, \ + .flags = _flags, \ + } + +#define GATE_MTK(_id, _name, _parent, _regs, _shift, _ops) \ + GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, _ops, 0) + +int mtk_clk_register_gates(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data); + +int mtk_clk_register_gates_with_dev(struct device_node *node, + const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data, + struct device *dev); + +void mtk_clk_unregister_gates(const struct mtk_gate *clks, int num, + struct clk_hw_onecell_data *clk_data); + +#endif /* __DRV_CLK_GATE_H */ diff --git a/drivers/clk/mediatek/clk-mt2701-aud.c b/drivers/clk/mediatek/clk-mt2701-aud.c new file mode 100644 index 000000000..4287bd3f5 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-aud.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +#define GATE_AUDIO0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio3_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs audio2_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +static const struct mtk_gate_regs audio3_cg_regs = { + .set_ofs = 0x634, + .clr_ofs = 0x634, + .sta_ofs = 0x634, +}; + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUD_AFE, "audio_afe", "aud_intbus_sel", 2), + GATE_AUDIO0(CLK_AUD_HDMI, "audio_hdmi", "audpll_sel", 20), + GATE_AUDIO0(CLK_AUD_SPDF, "audio_spdf", "audpll_sel", 21), + GATE_AUDIO0(CLK_AUD_SPDF2, "audio_spdf2", "audpll_sel", 22), + GATE_AUDIO0(CLK_AUD_APLL, "audio_apll", "audpll_sel", 23), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUD_I2SIN1, "audio_i2sin1", "aud_mux1_sel", 0), + GATE_AUDIO1(CLK_AUD_I2SIN2, "audio_i2sin2", "aud_mux1_sel", 1), + GATE_AUDIO1(CLK_AUD_I2SIN3, "audio_i2sin3", "aud_mux1_sel", 2), + GATE_AUDIO1(CLK_AUD_I2SIN4, "audio_i2sin4", "aud_mux1_sel", 3), + GATE_AUDIO1(CLK_AUD_I2SIN5, "audio_i2sin5", "aud_mux1_sel", 4), + GATE_AUDIO1(CLK_AUD_I2SIN6, "audio_i2sin6", "aud_mux1_sel", 5), + GATE_AUDIO1(CLK_AUD_I2SO1, "audio_i2so1", "aud_mux1_sel", 6), + GATE_AUDIO1(CLK_AUD_I2SO2, "audio_i2so2", "aud_mux1_sel", 7), + GATE_AUDIO1(CLK_AUD_I2SO3, "audio_i2so3", "aud_mux1_sel", 8), + GATE_AUDIO1(CLK_AUD_I2SO4, "audio_i2so4", "aud_mux1_sel", 9), + GATE_AUDIO1(CLK_AUD_I2SO5, "audio_i2so5", "aud_mux1_sel", 10), + GATE_AUDIO1(CLK_AUD_I2SO6, "audio_i2so6", "aud_mux1_sel", 11), + GATE_AUDIO1(CLK_AUD_ASRCI1, "audio_asrci1", "asm_h_sel", 12), + GATE_AUDIO1(CLK_AUD_ASRCI2, "audio_asrci2", "asm_h_sel", 13), + GATE_AUDIO1(CLK_AUD_ASRCO1, "audio_asrco1", "asm_h_sel", 14), + GATE_AUDIO1(CLK_AUD_ASRCO2, "audio_asrco2", "asm_h_sel", 15), + GATE_AUDIO1(CLK_AUD_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUD_A1SYS, "audio_a1sys", "aud_mux1_sel", 21), + GATE_AUDIO1(CLK_AUD_A2SYS, "audio_a2sys", "aud_mux2_sel", 22), + GATE_AUDIO1(CLK_AUD_AFE_CONN, "audio_afe_conn", "aud_mux1_sel", 23), + GATE_AUDIO1(CLK_AUD_AFE_MRGIF, "audio_afe_mrgif", "aud_mux1_sel", 25), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUD_MMIF_UL1, "audio_ul1", "aud_mux1_sel", 0), + GATE_AUDIO2(CLK_AUD_MMIF_UL2, "audio_ul2", "aud_mux1_sel", 1), + GATE_AUDIO2(CLK_AUD_MMIF_UL3, "audio_ul3", "aud_mux1_sel", 2), + GATE_AUDIO2(CLK_AUD_MMIF_UL4, "audio_ul4", "aud_mux1_sel", 3), + GATE_AUDIO2(CLK_AUD_MMIF_UL5, "audio_ul5", "aud_mux1_sel", 4), + GATE_AUDIO2(CLK_AUD_MMIF_UL6, "audio_ul6", "aud_mux1_sel", 5), + GATE_AUDIO2(CLK_AUD_MMIF_DL1, "audio_dl1", "aud_mux1_sel", 6), + GATE_AUDIO2(CLK_AUD_MMIF_DL2, "audio_dl2", "aud_mux1_sel", 7), + GATE_AUDIO2(CLK_AUD_MMIF_DL3, "audio_dl3", "aud_mux1_sel", 8), + GATE_AUDIO2(CLK_AUD_MMIF_DL4, "audio_dl4", "aud_mux1_sel", 9), + GATE_AUDIO2(CLK_AUD_MMIF_DL5, "audio_dl5", "aud_mux1_sel", 10), + GATE_AUDIO2(CLK_AUD_MMIF_DL6, "audio_dl6", "aud_mux1_sel", 11), + GATE_AUDIO2(CLK_AUD_MMIF_DLMCH, "audio_dlmch", "aud_mux1_sel", 12), + GATE_AUDIO2(CLK_AUD_MMIF_ARB1, "audio_arb1", "aud_mux1_sel", 13), + GATE_AUDIO2(CLK_AUD_MMIF_AWB1, "audio_awb", "aud_mux1_sel", 14), + GATE_AUDIO2(CLK_AUD_MMIF_AWB2, "audio_awb2", "aud_mux1_sel", 15), + GATE_AUDIO2(CLK_AUD_MMIF_DAI, "audio_dai", "aud_mux1_sel", 16), + /* AUDIO3 */ + GATE_AUDIO3(CLK_AUD_ASRCI3, "audio_asrci3", "asm_h_sel", 2), + GATE_AUDIO3(CLK_AUD_ASRCI4, "audio_asrci4", "asm_h_sel", 3), + GATE_AUDIO3(CLK_AUD_ASRCI5, "audio_asrci5", "asm_h_sel", 4), + GATE_AUDIO3(CLK_AUD_ASRCI6, "audio_asrci6", "asm_h_sel", 5), + GATE_AUDIO3(CLK_AUD_ASRCO3, "audio_asrco3", "asm_h_sel", 6), + GATE_AUDIO3(CLK_AUD_ASRCO4, "audio_asrco4", "asm_h_sel", 7), + GATE_AUDIO3(CLK_AUD_ASRCO5, "audio_asrco5", "asm_h_sel", 8), + GATE_AUDIO3(CLK_AUD_ASRCO6, "audio_asrco6", "asm_h_sel", 9), + GATE_AUDIO3(CLK_AUD_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), + GATE_AUDIO3(CLK_AUD_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), + GATE_AUDIO3(CLK_AUD_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), + GATE_AUDIO3(CLK_AUD_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), + GATE_AUDIO3(CLK_AUD_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), +}; + +static const struct of_device_id of_match_clk_mt2701_aud[] = { + { .compatible = "mediatek,mt2701-audsys", }, + {} +}; + +static int clk_mt2701_aud_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + goto err_clk_provider; + } + + r = devm_of_platform_populate(&pdev->dev); + if (r) + goto err_plat_populate; + + return 0; + +err_plat_populate: + of_clk_del_provider(node); +err_clk_provider: + return r; +} + +static struct platform_driver clk_mt2701_aud_drv = { + .probe = clk_mt2701_aud_probe, + .driver = { + .name = "clk-mt2701-aud", + .of_match_table = of_match_clk_mt2701_aud, + }, +}; + +builtin_platform_driver(clk_mt2701_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-bdp.c b/drivers/clk/mediatek/clk-mt2701-bdp.c new file mode 100644 index 000000000..b0f057207 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-bdp.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs bdp0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs bdp1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +#define GATE_BDP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &bdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_BDP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &bdp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate bdp_clks[] = { + GATE_BDP0(CLK_BDP_BRG_BA, "brg_baclk", "mm_sel", 0), + GATE_BDP0(CLK_BDP_BRG_DRAM, "brg_dram", "mm_sel", 1), + GATE_BDP0(CLK_BDP_LARB_DRAM, "larb_dram", "mm_sel", 2), + GATE_BDP0(CLK_BDP_WR_VDI_PXL, "wr_vdi_pxl", "hdmi_0_deep340m", 3), + GATE_BDP0(CLK_BDP_WR_VDI_DRAM, "wr_vdi_dram", "mm_sel", 4), + GATE_BDP0(CLK_BDP_WR_B, "wr_bclk", "mm_sel", 5), + GATE_BDP0(CLK_BDP_DGI_IN, "dgi_in", "dpi1_sel", 6), + GATE_BDP0(CLK_BDP_DGI_OUT, "dgi_out", "dpi1_sel", 7), + GATE_BDP0(CLK_BDP_FMT_MAST_27, "fmt_mast_27", "dpi1_sel", 8), + GATE_BDP0(CLK_BDP_FMT_B, "fmt_bclk", "mm_sel", 9), + GATE_BDP0(CLK_BDP_OSD_B, "osd_bclk", "mm_sel", 10), + GATE_BDP0(CLK_BDP_OSD_DRAM, "osd_dram", "mm_sel", 11), + GATE_BDP0(CLK_BDP_OSD_AGENT, "osd_agent", "osd_sel", 12), + GATE_BDP0(CLK_BDP_OSD_PXL, "osd_pxl", "dpi1_sel", 13), + GATE_BDP0(CLK_BDP_RLE_B, "rle_bclk", "mm_sel", 14), + GATE_BDP0(CLK_BDP_RLE_AGENT, "rle_agent", "mm_sel", 15), + GATE_BDP0(CLK_BDP_RLE_DRAM, "rle_dram", "mm_sel", 16), + GATE_BDP0(CLK_BDP_F27M, "f27m", "di_sel", 17), + GATE_BDP0(CLK_BDP_F27M_VDOUT, "f27m_vdout", "di_sel", 18), + GATE_BDP0(CLK_BDP_F27_74_74, "f27_74_74", "di_sel", 19), + GATE_BDP0(CLK_BDP_F2FS, "f2fs", "di_sel", 20), + GATE_BDP0(CLK_BDP_F2FS74_148, "f2fs74_148", "di_sel", 21), + GATE_BDP0(CLK_BDP_FB, "fbclk", "mm_sel", 22), + GATE_BDP0(CLK_BDP_VDO_DRAM, "vdo_dram", "mm_sel", 23), + GATE_BDP0(CLK_BDP_VDO_2FS, "vdo_2fs", "di_sel", 24), + GATE_BDP0(CLK_BDP_VDO_B, "vdo_bclk", "mm_sel", 25), + GATE_BDP0(CLK_BDP_WR_DI_PXL, "wr_di_pxl", "di_sel", 26), + GATE_BDP0(CLK_BDP_WR_DI_DRAM, "wr_di_dram", "mm_sel", 27), + GATE_BDP0(CLK_BDP_WR_DI_B, "wr_di_bclk", "mm_sel", 28), + GATE_BDP0(CLK_BDP_NR_PXL, "nr_pxl", "nr_sel", 29), + GATE_BDP0(CLK_BDP_NR_DRAM, "nr_dram", "mm_sel", 30), + GATE_BDP0(CLK_BDP_NR_B, "nr_bclk", "mm_sel", 31), + GATE_BDP1(CLK_BDP_RX_F, "rx_fclk", "hadds2_fbclk", 0), + GATE_BDP1(CLK_BDP_RX_X, "rx_xclk", "clk26m", 1), + GATE_BDP1(CLK_BDP_RXPDT, "rxpdtclk", "hdmi_0_pix340m", 2), + GATE_BDP1(CLK_BDP_RX_CSCL_N, "rx_cscl_n", "clk26m", 3), + GATE_BDP1(CLK_BDP_RX_CSCL, "rx_cscl", "clk26m", 4), + GATE_BDP1(CLK_BDP_RX_DDCSCL_N, "rx_ddcscl_n", "hdmi_scl_rx", 5), + GATE_BDP1(CLK_BDP_RX_DDCSCL, "rx_ddcscl", "hdmi_scl_rx", 6), + GATE_BDP1(CLK_BDP_RX_VCO, "rx_vcoclk", "hadds2pll_294m", 7), + GATE_BDP1(CLK_BDP_RX_DP, "rx_dpclk", "hdmi_0_pll340m", 8), + GATE_BDP1(CLK_BDP_RX_P, "rx_pclk", "hdmi_0_pll340m", 9), + GATE_BDP1(CLK_BDP_RX_M, "rx_mclk", "hadds2pll_294m", 10), + GATE_BDP1(CLK_BDP_RX_PLL, "rx_pllclk", "hdmi_0_pix340m", 11), + GATE_BDP1(CLK_BDP_BRG_RT_B, "brg_rt_bclk", "mm_sel", 12), + GATE_BDP1(CLK_BDP_BRG_RT_DRAM, "brg_rt_dram", "mm_sel", 13), + GATE_BDP1(CLK_BDP_LARBRT_DRAM, "larbrt_dram", "mm_sel", 14), + GATE_BDP1(CLK_BDP_TMDS_SYN, "tmds_syn", "hdmi_0_pll340m", 15), + GATE_BDP1(CLK_BDP_HDMI_MON, "hdmi_mon", "hdmi_0_pll340m", 16), +}; + +static const struct mtk_clk_desc bdp_desc = { + .clks = bdp_clks, + .num_clks = ARRAY_SIZE(bdp_clks), +}; + +static const struct of_device_id of_match_clk_mt2701_bdp[] = { + { + .compatible = "mediatek,mt2701-bdpsys", + .data = &bdp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2701_bdp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-bdp", + .of_match_table = of_match_clk_mt2701_bdp, + }, +}; + +builtin_platform_driver(clk_mt2701_bdp_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-eth.c b/drivers/clk/mediatek/clk-mt2701-eth.c new file mode 100644 index 000000000..601358748 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-eth.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs eth_cg_regs = { + .sta_ofs = 0x0030, +}; + +#define GATE_ETH(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate eth_clks[] = { + GATE_ETH(CLK_ETHSYS_HSDMA, "hsdma_clk", "ethif_sel", 5), + GATE_ETH(CLK_ETHSYS_ESW, "esw_clk", "ethpll_500m_ck", 6), + GATE_ETH(CLK_ETHSYS_GP2, "gp2_clk", "trgpll", 7), + GATE_ETH(CLK_ETHSYS_GP1, "gp1_clk", "ethpll_500m_ck", 8), + GATE_ETH(CLK_ETHSYS_PCM, "pcm_clk", "ethif_sel", 11), + GATE_ETH(CLK_ETHSYS_GDMA, "gdma_clk", "ethif_sel", 14), + GATE_ETH(CLK_ETHSYS_I2S, "i2s_clk", "ethif_sel", 17), + GATE_ETH(CLK_ETHSYS_CRYPTO, "crypto_clk", "ethif_sel", 29), +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static const struct of_device_id of_match_clk_mt2701_eth[] = { + { .compatible = "mediatek,mt2701-ethsys", }, + {} +}; + +static int clk_mt2701_eth_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_ETHSYS_NR); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static struct platform_driver clk_mt2701_eth_drv = { + .probe = clk_mt2701_eth_probe, + .driver = { + .name = "clk-mt2701-eth", + .of_match_table = of_match_clk_mt2701_eth, + }, +}; + +builtin_platform_driver(clk_mt2701_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-g3d.c b/drivers/clk/mediatek/clk-mt2701-g3d.c new file mode 100644 index 000000000..8d1fc8e33 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-g3d.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Sean Wang <sean.wang@mediatek.com> + * + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +#define GATE_G3D(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &g3d_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate_regs g3d_cg_regs = { + .sta_ofs = 0x0, + .set_ofs = 0x4, + .clr_ofs = 0x8, +}; + +static const struct mtk_gate g3d_clks[] = { + GATE_G3D(CLK_G3DSYS_CORE, "g3d_core", "mfg_sel", 0), +}; + +static u16 rst_ofs[] = { 0xc, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static int clk_mt2701_g3dsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_G3DSYS_NR); + + mtk_clk_register_gates(node, g3d_clks, ARRAY_SIZE(g3d_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static const struct of_device_id of_match_clk_mt2701_g3d[] = { + { + .compatible = "mediatek,mt2701-g3dsys", + .data = clk_mt2701_g3dsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt2701_g3d_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2701_g3d_drv = { + .probe = clk_mt2701_g3d_probe, + .driver = { + .name = "clk-mt2701-g3d", + .of_match_table = of_match_clk_mt2701_g3d, + }, +}; + +builtin_platform_driver(clk_mt2701_g3d_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-hif.c b/drivers/clk/mediatek/clk-mt2701-hif.c new file mode 100644 index 000000000..edeeb033a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-hif.c @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs hif_cg_regs = { + .sta_ofs = 0x0030, +}; + +#define GATE_HIF(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &hif_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate hif_clks[] = { + GATE_HIF(CLK_HIFSYS_USB0PHY, "usb0_phy_clk", "ethpll_500m_ck", 21), + GATE_HIF(CLK_HIFSYS_USB1PHY, "usb1_phy_clk", "ethpll_500m_ck", 22), + GATE_HIF(CLK_HIFSYS_PCIE0, "pcie0_clk", "ethpll_500m_ck", 24), + GATE_HIF(CLK_HIFSYS_PCIE1, "pcie1_clk", "ethpll_500m_ck", 25), + GATE_HIF(CLK_HIFSYS_PCIE2, "pcie2_clk", "ethpll_500m_ck", 26), +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static const struct of_device_id of_match_clk_mt2701_hif[] = { + { .compatible = "mediatek,mt2701-hifsys", }, + {} +}; + +static int clk_mt2701_hif_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_HIFSYS_NR); + + mtk_clk_register_gates(node, hif_clks, ARRAY_SIZE(hif_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + return r; + } + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return 0; +} + +static struct platform_driver clk_mt2701_hif_drv = { + .probe = clk_mt2701_hif_probe, + .driver = { + .name = "clk-mt2701-hif", + .of_match_table = of_match_clk_mt2701_hif, + }, +}; + +builtin_platform_driver(clk_mt2701_hif_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-img.c b/drivers/clk/mediatek/clk-mt2701-img.c new file mode 100644 index 000000000..eb172473f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-img.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_SMI_COMM, "img_smi_comm", "mm_sel", 0), + GATE_IMG(CLK_IMG_RESZ, "img_resz", "mm_sel", 1), + GATE_IMG(CLK_IMG_JPGDEC_SMI, "img_jpgdec_smi", "mm_sel", 5), + GATE_IMG(CLK_IMG_JPGDEC, "img_jpgdec", "mm_sel", 6), + GATE_IMG(CLK_IMG_VENC_LT, "img_venc_lt", "mm_sel", 8), + GATE_IMG(CLK_IMG_VENC, "img_venc", "mm_sel", 9), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt2701_img[] = { + { + .compatible = "mediatek,mt2701-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2701_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-img", + .of_match_table = of_match_clk_mt2701_img, + }, +}; + +builtin_platform_driver(clk_mt2701_img_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-mm.c b/drivers/clk/mediatek/clk-mt2701-mm.c new file mode 100644 index 000000000..eb069f3bc --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-mm.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs disp0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs disp1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +#define GATE_DISP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &disp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_DISP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &disp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + GATE_DISP0(CLK_MM_SMI_COMMON, "mm_smi_comm", "mm_sel", 0), + GATE_DISP0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_DISP0(CLK_MM_CMDQ, "mm_cmdq", "mm_sel", 2), + GATE_DISP0(CLK_MM_MUTEX, "mm_mutex", "mm_sel", 3), + GATE_DISP0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 4), + GATE_DISP0(CLK_MM_DISP_BLS, "mm_disp_bls", "mm_sel", 5), + GATE_DISP0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "mm_sel", 6), + GATE_DISP0(CLK_MM_DISP_RDMA, "mm_disp_rdma", "mm_sel", 7), + GATE_DISP0(CLK_MM_DISP_OVL, "mm_disp_ovl", "mm_sel", 8), + GATE_DISP0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9), + GATE_DISP0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "mm_sel", 10), + GATE_DISP0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_DISP0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 12), + GATE_DISP0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 13), + GATE_DISP0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "mm_sel", 14), + GATE_DISP0(CLK_MM_MDP_BLS_26M, "mm_mdp_bls_26m", "pwm_sel", 15), + GATE_DISP0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 16), + GATE_DISP0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 17), + GATE_DISP0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 18), + GATE_DISP0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_DISP0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 20), + GATE_DISP1(CLK_MM_DSI_ENGINE, "mm_dsi_eng", "mm_sel", 0), + GATE_DISP1(CLK_MM_DSI_DIG, "mm_dsi_dig", "dsi0_lntc_dsi", 1), + GATE_DISP1(CLK_MM_DPI_DIGL, "mm_dpi_digl", "dpi0_sel", 2), + GATE_DISP1(CLK_MM_DPI_ENGINE, "mm_dpi_eng", "mm_sel", 3), + GATE_DISP1(CLK_MM_DPI1_DIGL, "mm_dpi1_digl", "dpi1_sel", 4), + GATE_DISP1(CLK_MM_DPI1_ENGINE, "mm_dpi1_eng", "mm_sel", 5), + GATE_DISP1(CLK_MM_TVE_OUTPUT, "mm_tve_output", "tve_sel", 6), + GATE_DISP1(CLK_MM_TVE_INPUT, "mm_tve_input", "dpi0_sel", 7), + GATE_DISP1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi1_sel", 8), + GATE_DISP1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmi_sel", 9), + GATE_DISP1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll_sel", 10), + GATE_DISP1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll_sel", 11), + GATE_DISP1(CLK_MM_TVE_FMM, "mm_tve_fmm", "mm_sel", 14), +}; + +static int clk_mt2701_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2701_mm_drv = { + .probe = clk_mt2701_mm_probe, + .driver = { + .name = "clk-mt2701-mm", + }, +}; + +builtin_platform_driver(clk_mt2701_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt2701-vdec.c b/drivers/clk/mediatek/clk-mt2701-vdec.c new file mode 100644 index 000000000..0f07c5d73 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701-vdec.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + GATE_VDEC0(CLK_VDEC_CKGEN, "vdec_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_LARB, "vdec_larb_cken", "mm_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt2701_vdec[] = { + { + .compatible = "mediatek,mt2701-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2701_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2701-vdec", + .of_match_table = of_match_clk_mt2701_vdec, + }, +}; + +builtin_platform_driver(clk_mt2701_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2701.c b/drivers/clk/mediatek/clk-mt2701.c new file mode 100644 index 000000000..00d2e81bd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2701.c @@ -0,0 +1,1040 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: Shunli Wang <shunli.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt2701-clk.h> + +/* + * For some clocks, we don't care what their actual rates are. And these + * clocks may change their rate on different products or different scenarios. + * So we model these clocks' rate as 0, to denote it's not an actual rate. + */ +#define DUMMY_RATE 0 + +static DEFINE_SPINLOCK(mt2701_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_DPI, "dpi_ck", "clk26m", + 108 * MHZ), + FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", "clk26m", + 400 * MHZ), + FIXED_CLK(CLK_TOP_VENCPLL, "vencpll_ck", "clk26m", + 295750000), + FIXED_CLK(CLK_TOP_HDMI_0_PIX340M, "hdmi_0_pix340m", "clk26m", + 340 * MHZ), + FIXED_CLK(CLK_TOP_HDMI_0_DEEP340M, "hdmi_0_deep340m", "clk26m", + 340 * MHZ), + FIXED_CLK(CLK_TOP_HDMI_0_PLL340M, "hdmi_0_pll340m", "clk26m", + 340 * MHZ), + FIXED_CLK(CLK_TOP_HADDS2_FB, "hadds2_fbclk", "clk26m", + 27 * MHZ), + FIXED_CLK(CLK_TOP_WBG_DIG_416M, "wbg_dig_ck_416m", "clk26m", + 416 * MHZ), + FIXED_CLK(CLK_TOP_DSI0_LNTC_DSI, "dsi0_lntc_dsi", "clk26m", + 143 * MHZ), + FIXED_CLK(CLK_TOP_HDMI_SCL_RX, "hdmi_scl_rx", "clk26m", + 27 * MHZ), + FIXED_CLK(CLK_TOP_AUD_EXT1, "aud_ext1", "clk26m", + DUMMY_RATE), + FIXED_CLK(CLK_TOP_AUD_EXT2, "aud_ext2", "clk26m", + DUMMY_RATE), + FIXED_CLK(CLK_TOP_NFI1X_PAD, "nfi1x_pad", "clk26m", + DUMMY_RATE), +}; + +static const struct mtk_fixed_factor top_fixed_divs[] = { + FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4), + + FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll", 1, 52), + FACTOR(CLK_TOP_UNIVPLL_D108, "univpll_d108", "univpll", 1, 108), + FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8), + FACTOR(CLK_TOP_8BDAC, "8bdac_ck", "univpll_d2", 1, 1), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8), + FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll_d3", 1, 16), + FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8), + + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8), + + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + + FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "dmpll_ck", 1, 2), + FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "dmpll_ck", 1, 4), + FACTOR(CLK_TOP_DMPLL_X2, "dmpll_x2", "dmpll_ck", 1, 1), + + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), + + FACTOR(CLK_TOP_VDECPLL, "vdecpll_ck", "vdecpll", 1, 1), + FACTOR(CLK_TOP_TVD2PLL, "tvd2pll_ck", "tvd2pll", 1, 1), + FACTOR(CLK_TOP_TVD2PLL_D2, "tvd2pll_d2", "tvd2pll", 1, 2), + + FACTOR(CLK_TOP_MIPIPLL, "mipipll", "dpi_ck", 1, 1), + FACTOR(CLK_TOP_MIPIPLL_D2, "mipipll_d2", "dpi_ck", 1, 2), + FACTOR(CLK_TOP_MIPIPLL_D4, "mipipll_d4", "dpi_ck", 1, 4), + + FACTOR(CLK_TOP_HDMIPLL, "hdmipll_ck", "hdmitx_dig_cts", 1, 1), + FACTOR(CLK_TOP_HDMIPLL_D2, "hdmipll_d2", "hdmitx_dig_cts", 1, 2), + FACTOR(CLK_TOP_HDMIPLL_D3, "hdmipll_d3", "hdmitx_dig_cts", 1, 3), + + FACTOR(CLK_TOP_ARMPLL_1P3G, "armpll_1p3g_ck", "armpll", 1, 1), + + FACTOR(CLK_TOP_AUDPLL, "audpll", "audpll_sel", 1, 1), + FACTOR(CLK_TOP_AUDPLL_D4, "audpll_d4", "audpll_sel", 1, 4), + FACTOR(CLK_TOP_AUDPLL_D8, "audpll_d8", "audpll_sel", 1, 8), + FACTOR(CLK_TOP_AUDPLL_D16, "audpll_d16", "audpll_sel", 1, 16), + FACTOR(CLK_TOP_AUDPLL_D24, "audpll_d24", "audpll_sel", 1, 24), + + FACTOR(CLK_TOP_AUD1PLL_98M, "aud1pll_98m_ck", "aud1pll", 1, 3), + FACTOR(CLK_TOP_AUD2PLL_90M, "aud2pll_90m_ck", "aud2pll", 1, 3), + FACTOR(CLK_TOP_HADDS2PLL_98M, "hadds2pll_98m", "hadds2pll", 1, 3), + FACTOR(CLK_TOP_HADDS2PLL_294M, "hadds2pll_294m", "hadds2pll", 1, 1), + FACTOR(CLK_TOP_ETHPLL_500M, "ethpll_500m_ck", "ethpll", 1, 1), + FACTOR(CLK_TOP_CLK26M_D8, "clk26m_d8", "clk26m", 1, 8), + FACTOR(CLK_TOP_32K_INTERNAL, "32k_internal", "clk26m", 1, 793), + FACTOR(CLK_TOP_32K_EXTERNAL, "32k_external", "rtc32k", 1, 1), + FACTOR(CLK_TOP_AXISEL_D4, "axisel_d4", "axi_sel", 1, 4), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "mmpll_d2", + "dmpll_d2" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clk26m", + "syspll1_d8" +}; + +static const char * const mm_parents[] = { + "clk26m", + "vencpll_ck", + "syspll1_d2", + "syspll1_d4", + "univpll_d5", + "univpll1_d2", + "univpll2_d2", + "dmpll_ck" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4", +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vdecpll_ck", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "vencpll_ck", + "msdcpll_d2", + "mmpll_d2" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mmpll_ck", + "dmpll_x2_ck", + "msdcpll_ck", + "clk26m", + "syspll_d3", + "univpll_d3", + "univpll1_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d26", + "univpll2_d2", + "syspll3_d2", + "syspll3_d4", + "msdcpll_d2", + "mmpll_d2" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll3_d2", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8" +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const msdc30_parents[] = { + "clk26m", + "msdcpll_d2", + "syspll2_d2", + "syspll1_d4", + "univpll1_d4", + "univpll2_d4" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll3_d2", + "syspll4_d2", + "univpll3_d2", + "univpll2_d4" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll1_d8", + "syspll2_d4", + "syspll4_d2", + "syspll3_d4", + "syspll2_d8", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const scp_parents[] = { + "clk26m", + "syspll1_d8", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "mipipll", + "mipipll_d2", + "mipipll_d4", + "clk26m", + "tvdpll_ck", + "tvdpll_d2", + "tvdpll_d4" +}; + +static const char * const dpi1_parents[] = { + "clk26m", + "tvdpll_ck", + "tvdpll_d2", + "tvdpll_d4" +}; + +static const char * const tve_parents[] = { + "clk26m", + "mipipll", + "mipipll_d2", + "mipipll_d4", + "clk26m", + "tvdpll_ck", + "tvdpll_d2", + "tvdpll_d4" +}; + +static const char * const hdmi_parents[] = { + "clk26m", + "hdmipll_ck", + "hdmipll_d2", + "hdmipll_d3" +}; + +static const char * const apll_parents[] = { + "clk26m", + "audpll", + "audpll_d4", + "audpll_d8", + "audpll_d16", + "audpll_d24", + "clk26m", + "clk26m" +}; + +static const char * const rtc_parents[] = { + "32k_internal", + "32k_external", + "clk26m", + "univpll3_d8" +}; + +static const char * const nfi2x_parents[] = { + "clk26m", + "syspll2_d2", + "syspll_d7", + "univpll3_d2", + "syspll2_d4", + "univpll3_d4", + "syspll4_d4", + "clk26m" +}; + +static const char * const emmc_hclk_parents[] = { + "clk26m", + "syspll1_d2", + "syspll1_d4", + "syspll2_d2" +}; + +static const char * const flash_parents[] = { + "clk26m_d8", + "clk26m", + "syspll2_d8", + "syspll3_d4", + "univpll3_d4", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4" +}; + +static const char * const di_parents[] = { + "clk26m", + "tvd2pll_ck", + "tvd2pll_d2", + "clk26m" +}; + +static const char * const nr_osd_parents[] = { + "clk26m", + "vencpll_ck", + "syspll1_d2", + "syspll1_d4", + "univpll_d5", + "univpll1_d2", + "univpll2_d2", + "dmpll_ck" +}; + +static const char * const hdmirx_bist_parents[] = { + "clk26m", + "syspll_d3", + "clk26m", + "syspll1_d16", + "syspll4_d2", + "syspll1_d4", + "vencpll_ck", + "clk26m" +}; + +static const char * const intdir_parents[] = { + "clk26m", + "mmpll_ck", + "syspll_d2", + "univpll_d2" +}; + +static const char * const asm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const ms_card_parents[] = { + "clk26m", + "univpll3_d8", + "syspll4_d4" +}; + +static const char * const ethif_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll1_d2", + "dmpll_ck", + "dmpll_d2" +}; + +static const char * const hdmirx_parents[] = { + "clk26m", + "univpll_d52" +}; + +static const char * const cmsys_parents[] = { + "clk26m", + "syspll1_d2", + "univpll1_d2", + "univpll_d5", + "syspll_d5", + "syspll2_d2", + "syspll1_d4", + "syspll3_d2", + "syspll2_d4", + "syspll1_d8", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m" +}; + +static const char * const clk_8bdac_parents[] = { + "32k_internal", + "8bdac_ck", + "clk26m", + "clk26m" +}; + +static const char * const aud2dvd_parents[] = { + "a1sys_hp_ck", + "a2sys_hp_ck" +}; + +static const char * const padmclk_parents[] = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll_d108", + "univpll2_d8", + "univpll2_d16", + "univpll2_d32" +}; + +static const char * const aud_mux_parents[] = { + "clk26m", + "aud1pll_98m_ck", + "aud2pll_90m_ck", + "hadds2pll_98m", + "audio_ext1_ck", + "audio_ext2_ck" +}; + +static const char * const aud_src_parents[] = { + "aud_mux1_sel", + "aud_mux2_sel" +}; + +static const char * const cpu_parents[] = { + "clk26m", + "armpll", + "mainpll", + "mmpll" +}; + +static const struct mtk_composite cpu_muxes[] __initconst = { + MUX(CLK_INFRA_CPUSEL, "infra_cpu_sel", cpu_parents, 0x0000, 2, 2), +}; + +static const struct mtk_composite top_muxes[] = { + MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x0040, 0, 3, 7, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x0040, 8, 1, 15, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", + ddrphycfg_parents, 0x0040, 16, 1, 23, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, + 0x0040, 24, 3, 31), + + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x0050, 0, 2, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, + 0x0050, 8, 4, 15), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, + 0x0050, 16, 3, 23), + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, + 0x0050, 24, 3, 31), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + 0x0060, 0, 1, 7), + + MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi_parents, + 0x0060, 8, 3, 15), + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, + 0x0060, 16, 2, 23), + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, + 0x0060, 24, 3, 31), + + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, + 0x0070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, + 0x0070, 8, 3, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", msdc30_parents, + 0x0070, 16, 1, 23), + MUX_GATE(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x0070, 24, 3, 31), + + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x0080, 0, 4, 7), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, + 0x0080, 8, 2, 15), + MUX_GATE(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, + 0x0080, 16, 3, 23), + MUX_GATE_FLAGS_2(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, + 0x0080, 24, 2, 31, 0, CLK_MUX_ROUND_CLOSEST), + + MUX_GATE(CLK_TOP_TVE_SEL, "tve_sel", tve_parents, + 0x0090, 0, 3, 7), + MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, + 0x0090, 8, 2, 15), + MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, + 0x0090, 16, 3, 23), + + MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, + 0x00A0, 0, 2, 7, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, + 0x00A0, 8, 3, 15), + MUX_GATE(CLK_TOP_EMMC_HCLK_SEL, "emmc_hclk_sel", emmc_hclk_parents, + 0x00A0, 24, 2, 31), + + MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, + 0x00B0, 0, 3, 7), + MUX_GATE(CLK_TOP_DI_SEL, "di_sel", di_parents, + 0x00B0, 8, 2, 15), + MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", nr_osd_parents, + 0x00B0, 16, 3, 23), + MUX_GATE(CLK_TOP_OSD_SEL, "osd_sel", nr_osd_parents, + 0x00B0, 24, 3, 31), + + MUX_GATE(CLK_TOP_HDMIRX_BIST_SEL, "hdmirx_bist_sel", + hdmirx_bist_parents, 0x00C0, 0, 3, 7), + MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, + 0x00C0, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_I_SEL, "asm_i_sel", asm_parents, + 0x00C0, 16, 2, 23), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_parents, + 0x00C0, 24, 3, 31), + + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_parents, + 0x00D0, 0, 2, 7), + MUX_GATE(CLK_TOP_MS_CARD_SEL, "ms_card_sel", ms_card_parents, + 0x00D0, 16, 2, 23), + MUX_GATE(CLK_TOP_ETHIF_SEL, "ethif_sel", ethif_parents, + 0x00D0, 24, 3, 31), + + MUX_GATE(CLK_TOP_HDMIRX26_24_SEL, "hdmirx26_24_sel", hdmirx_parents, + 0x00E0, 0, 1, 7), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, + 0x00E0, 8, 3, 15), + MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", cmsys_parents, + 0x00E0, 16, 4, 23), + + MUX_GATE(CLK_TOP_SPI1_SEL, "spi2_sel", spi_parents, + 0x00E0, 24, 3, 31), + MUX_GATE(CLK_TOP_SPI2_SEL, "spi1_sel", spi_parents, + 0x00F0, 0, 3, 7), + MUX_GATE(CLK_TOP_8BDAC_SEL, "8bdac_sel", clk_8bdac_parents, + 0x00F0, 8, 2, 15), + MUX_GATE(CLK_TOP_AUD2DVD_SEL, "aud2dvd_sel", aud2dvd_parents, + 0x00F0, 16, 1, 23), + + MUX(CLK_TOP_PADMCLK_SEL, "padmclk_sel", padmclk_parents, + 0x0100, 0, 3), + + MUX(CLK_TOP_AUD_MUX1_SEL, "aud_mux1_sel", aud_mux_parents, + 0x012c, 0, 3), + MUX(CLK_TOP_AUD_MUX2_SEL, "aud_mux2_sel", aud_mux_parents, + 0x012c, 3, 3), + MUX(CLK_TOP_AUDPLL_MUX_SEL, "audpll_sel", aud_mux_parents, + 0x012c, 6, 3), + MUX_GATE(CLK_TOP_AUD_K1_SRC_SEL, "aud_k1_src_sel", aud_src_parents, + 0x012c, 15, 1, 23), + MUX_GATE(CLK_TOP_AUD_K2_SRC_SEL, "aud_k2_src_sel", aud_src_parents, + 0x012c, 16, 1, 24), + MUX_GATE(CLK_TOP_AUD_K3_SRC_SEL, "aud_k3_src_sel", aud_src_parents, + 0x012c, 17, 1, 25), + MUX_GATE(CLK_TOP_AUD_K4_SRC_SEL, "aud_k4_src_sel", aud_src_parents, + 0x012c, 18, 1, 26), + MUX_GATE(CLK_TOP_AUD_K5_SRC_SEL, "aud_k5_src_sel", aud_src_parents, + 0x012c, 19, 1, 27), + MUX_GATE(CLK_TOP_AUD_K6_SRC_SEL, "aud_k6_src_sel", aud_src_parents, + 0x012c, 20, 1, 28), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_AUD_EXTCK1_DIV, "audio_ext1_ck", "aud_ext1", + 0x0120, 0, 8), + DIV_ADJ(CLK_TOP_AUD_EXTCK2_DIV, "audio_ext2_ck", "aud_ext2", + 0x0120, 8, 8), + DIV_ADJ(CLK_TOP_AUD_MUX1_DIV, "aud_mux1_div", "aud_mux1_sel", + 0x0120, 16, 8), + DIV_ADJ(CLK_TOP_AUD_MUX2_DIV, "aud_mux2_div", "aud_mux2_sel", + 0x0120, 24, 8), + DIV_ADJ(CLK_TOP_AUD_K1_SRC_DIV, "aud_k1_src_div", "aud_k1_src_sel", + 0x0124, 0, 8), + DIV_ADJ(CLK_TOP_AUD_K2_SRC_DIV, "aud_k2_src_div", "aud_k2_src_sel", + 0x0124, 8, 8), + DIV_ADJ(CLK_TOP_AUD_K3_SRC_DIV, "aud_k3_src_div", "aud_k3_src_sel", + 0x0124, 16, 8), + DIV_ADJ(CLK_TOP_AUD_K4_SRC_DIV, "aud_k4_src_div", "aud_k4_src_sel", + 0x0124, 24, 8), + DIV_ADJ(CLK_TOP_AUD_K5_SRC_DIV, "aud_k5_src_div", "aud_k5_src_sel", + 0x0128, 0, 8), + DIV_ADJ(CLK_TOP_AUD_K6_SRC_DIV, "aud_k6_src_div", "aud_k6_src_sel", + 0x0128, 8, 8), +}; + +static const struct mtk_gate_regs top_aud_cg_regs = { + .sta_ofs = 0x012C, +}; + +#define GATE_TOP_AUD(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top_aud_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate top_clks[] = { + GATE_TOP_AUD(CLK_TOP_AUD_48K_TIMING, "a1sys_hp_ck", "aud_mux1_div", + 21), + GATE_TOP_AUD(CLK_TOP_AUD_44K_TIMING, "a2sys_hp_ck", "aud_mux2_div", + 22), + GATE_TOP_AUD(CLK_TOP_AUD_I2S1_MCLK, "aud_i2s1_mclk", "aud_k1_src_div", + 23), + GATE_TOP_AUD(CLK_TOP_AUD_I2S2_MCLK, "aud_i2s2_mclk", "aud_k2_src_div", + 24), + GATE_TOP_AUD(CLK_TOP_AUD_I2S3_MCLK, "aud_i2s3_mclk", "aud_k3_src_div", + 25), + GATE_TOP_AUD(CLK_TOP_AUD_I2S4_MCLK, "aud_i2s4_mclk", "aud_k4_src_div", + 26), + GATE_TOP_AUD(CLK_TOP_AUD_I2S5_MCLK, "aud_i2s5_mclk", "aud_k5_src_div", + 27), + GATE_TOP_AUD(CLK_TOP_AUD_I2S6_MCLK, "aud_i2s6_mclk", "aud_k6_src_div", + 28), +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), + base, &mt2701_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt2701_clk_lock, clk_data); + + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +#define GATE_ICG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + GATE_ICG(CLK_INFRA_DBG, "dbgclk", "axi_sel", 0), + GATE_ICG(CLK_INFRA_SMI, "smi_ck", "mm_sel", 1), + GATE_ICG(CLK_INFRA_QAXI_CM4, "cm4_ck", "axi_sel", 2), + GATE_ICG(CLK_INFRA_AUD_SPLIN_B, "audio_splin_bck", "hadds2pll_294m", 4), + GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "clk26m", 5), + GATE_ICG(CLK_INFRA_EFUSE, "efuse_ck", "clk26m", 6), + GATE_ICG(CLK_INFRA_L2C_SRAM, "l2c_sram_ck", "mm_sel", 7), + GATE_ICG(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8), + GATE_ICG(CLK_INFRA_CONNMCU, "connsys_bus", "wbg_dig_ck_416m", 12), + GATE_ICG(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 13), + GATE_ICG(CLK_INFRA_RAMBUFIF, "rambufif_ck", "mem_sel", 14), + GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "mem_sel", 15), + GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16), + GATE_ICG(CLK_INFRA_CEC, "cec_ck", "rtc_sel", 18), + GATE_ICG(CLK_INFRA_IRRX, "irrx_ck", "axi_sel", 19), + GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22), + GATE_ICG(CLK_INFRA_PMICWRAP, "pmicwrap_ck", "axi_sel", 23), + GATE_ICG(CLK_INFRA_DDCCI, "ddcci_ck", "axi_sel", 24), +}; + +static const struct mtk_fixed_factor infra_fixed_divs[] = { + FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2), +}; + +static u16 infrasys_rst_ofs[] = { 0x30, 0x34, }; +static u16 pericfg_rst_ofs[] = { 0x0, 0x4, }; + +static const struct mtk_clk_rst_desc clk_rst_desc[] = { + /* infrasys */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), + }, + /* pericfg */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), + }, +}; + +static struct clk_hw_onecell_data *infra_clk_data; + +static void __init mtk_infrasys_init_early(struct device_node *node) +{ + int r, i; + + if (!infra_clk_data) { + infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return; + + for (i = 0; i < CLK_INFRA_NR; i++) + infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); + } + + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + + mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), + infra_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt2701-infracfg", + mtk_infrasys_init_early); + +static int mtk_infrasys_init(struct platform_device *pdev) +{ + int r, i; + struct device_node *node = pdev->dev.of_node; + + if (!infra_clk_data) { + infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return -ENOMEM; + } else { + for (i = 0; i < CLK_INFRA_NR; i++) { + if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + infra_clk_data->hws[i] = ERR_PTR(-ENOENT); + } + } + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + infra_clk_data); + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); + if (r) + return r; + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); + + return 0; +} + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0x000c, + .clr_ofs = 0x0014, + .sta_ofs = 0x001c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate peri_clks[] = { + GATE_PERI0(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 31), + GATE_PERI0(CLK_PERI_ETH, "eth_ck", "clk26m", 30), + GATE_PERI0(CLK_PERI_SPI0, "spi0_ck", "spi0_sel", 29), + GATE_PERI0(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 28), + GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "clk26m", 27), + GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 26), + GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 25), + GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 24), + GATE_PERI0(CLK_PERI_BTIF, "bitif_ck", "axi_sel", 23), + GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 22), + GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 21), + GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 20), + GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 19), + GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 18), + GATE_PERI0(CLK_PERI_MSDC50_3, "msdc50_3_ck", "emmc_hclk_sel", 17), + GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_3_sel", 16), + GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_2_sel", 15), + GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 14), + GATE_PERI0(CLK_PERI_MSDC30_0, "msdc30_0_ck", "msdc30_0_sel", 13), + GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12), + GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11), + GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10), + GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9), + GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axisel_d4", 8), + GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axisel_d4", 7), + GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axisel_d4", 6), + GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axisel_d4", 5), + GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axisel_d4", 4), + GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axisel_d4", 3), + GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axisel_d4", 2), + GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1), + GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "nfi2x_sel", 0), + + GATE_PERI1(CLK_PERI_FCI, "fci_ck", "ms_card_sel", 11), + GATE_PERI1(CLK_PERI_SPI2, "spi2_ck", "spi2_sel", 10), + GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi1_sel", 9), + GATE_PERI1(CLK_PERI_HOST89_DVD, "host89_dvd_ck", "aud2dvd_sel", 8), + GATE_PERI1(CLK_PERI_HOST89_SPI, "host89_spi_ck", "spi0_sel", 7), + GATE_PERI1(CLK_PERI_HOST89_INT, "host89_int_ck", "axi_sel", 6), + GATE_PERI1(CLK_PERI_FLASH, "flash_ck", "nfi2x_sel", 5), + GATE_PERI1(CLK_PERI_NFI_PAD, "nfi_pad_ck", "nfi1x_pad", 4), + GATE_PERI1(CLK_PERI_NFI_ECC, "nfi_ecc_ck", "nfi1x_pad", 3), + GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "axi_sel", 2), + GATE_PERI1(CLK_PERI_USB_SLV, "usbslv_ck", "axi_sel", 1), + GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 0), +}; + +static const char * const uart_ck_sel_parents[] = { + "clk26m", + "uart_sel", +}; + +static const struct mtk_composite peri_muxs[] = { + MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, + 0x40c, 0, 1), + MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, + 0x40c, 1, 1), + MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, + 0x40c, 2, 1), + MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, + 0x40c, 3, 1), +}; + +static int mtk_pericfg_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + struct device_node *node = pdev->dev.of_node; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + mtk_clk_register_composites(peri_muxs, ARRAY_SIZE(peri_muxs), base, + &mt2701_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + return r; + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); + + return 0; +} + +#define MT8590_PLL_FMAX (2000 * MHZ) +#define CON0_MT8590_RST_BAR BIT(27) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ + _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8590_RST_BAR, \ + .fmax = MT8590_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + } + +static const struct mtk_pll_data apmixed_plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x200, 0x20c, 0x80000000, + PLL_AO, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x210, 0x21c, 0xf0000000, + HAVE_RST_BAR, 21, 0x210, 4, 0x0, 0x214, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x220, 0x22c, 0xf3000000, + HAVE_RST_BAR, 7, 0x220, 4, 0x0, 0x224, 14), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x230, 0x23c, 0, 0, + 21, 0x230, 4, 0x0, 0x234, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x240, 0x24c, 0x00000001, 0, + 21, 0x240, 4, 0x0, 0x244, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x250, 0x25c, 0x00000001, 0, + 21, 0x250, 4, 0x0, 0x254, 0), + PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x270, 0x27c, 0x00000001, 0, + 31, 0x270, 4, 0x0, 0x274, 0), + PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x280, 0x28c, 0x00000001, 0, + 31, 0x280, 4, 0x0, 0x284, 0), + PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x290, 0x29c, 0x00000001, 0, + 31, 0x290, 4, 0x0, 0x294, 0), + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x2a0, 0x2ac, 0x00000001, 0, + 31, 0x2a0, 4, 0x0, 0x2a4, 0), + PLL(CLK_APMIXED_HADDS2PLL, "hadds2pll", 0x2b0, 0x2bc, 0x00000001, 0, + 31, 0x2b0, 4, 0x0, 0x2b4, 0), + PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x2c0, 0x2cc, 0x00000001, 0, + 31, 0x2c0, 4, 0x0, 0x2c4, 0), + PLL(CLK_APMIXED_TVD2PLL, "tvd2pll", 0x2d0, 0x2dc, 0x00000001, 0, + 21, 0x2d0, 4, 0x0, 0x2d4, 0), +}; + +static const struct mtk_fixed_factor apmixed_fixed_divs[] = { + FACTOR(CLK_APMIXED_HDMI_REF, "hdmi_ref", "tvdpll", 1, 1), +}; + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, apmixed_plls, ARRAY_SIZE(apmixed_plls), + clk_data); + mtk_clk_register_factors(apmixed_fixed_divs, ARRAY_SIZE(apmixed_fixed_divs), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct of_device_id of_match_clk_mt2701[] = { + { + .compatible = "mediatek,mt2701-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt2701-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt2701-pericfg", + .data = mtk_pericfg_init, + }, { + .compatible = "mediatek,mt2701-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt2701_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2701_drv = { + .probe = clk_mt2701_probe, + .driver = { + .name = "clk-mt2701", + .of_match_table = of_match_clk_mt2701, + }, +}; + +static int __init clk_mt2701_init(void) +{ + return platform_driver_register(&clk_mt2701_drv); +} + +arch_initcall(clk_mt2701_init); diff --git a/drivers/clk/mediatek/clk-mt2712-bdp.c b/drivers/clk/mediatek/clk-mt2712-bdp.c new file mode 100644 index 000000000..5e668651d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-bdp.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs bdp_cg_regs = { + .set_ofs = 0x100, + .clr_ofs = 0x100, + .sta_ofs = 0x100, +}; + +#define GATE_BDP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &bdp_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate bdp_clks[] = { + GATE_BDP(CLK_BDP_BRIDGE_B, "bdp_bridge_b", "mm_sel", 0), + GATE_BDP(CLK_BDP_BRIDGE_DRAM, "bdp_bridge_d", "mm_sel", 1), + GATE_BDP(CLK_BDP_LARB_DRAM, "bdp_larb_d", "mm_sel", 2), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_PXL, "bdp_vdi_pxl", "tvd_sel", 3), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_DRAM, "bdp_vdi_d", "mm_sel", 4), + GATE_BDP(CLK_BDP_WR_CHANNEL_VDI_B, "bdp_vdi_b", "mm_sel", 5), + GATE_BDP(CLK_BDP_MT_B, "bdp_fmt_b", "mm_sel", 9), + GATE_BDP(CLK_BDP_DISPFMT_27M, "bdp_27m", "di_sel", 10), + GATE_BDP(CLK_BDP_DISPFMT_27M_VDOUT, "bdp_27m_vdout", "di_sel", 11), + GATE_BDP(CLK_BDP_DISPFMT_27_74_74, "bdp_27_74_74", "di_sel", 12), + GATE_BDP(CLK_BDP_DISPFMT_2FS, "bdp_2fs", "di_sel", 13), + GATE_BDP(CLK_BDP_DISPFMT_2FS_2FS74_148, "bdp_2fs74_148", "di_sel", 14), + GATE_BDP(CLK_BDP_DISPFMT_B, "bdp_b", "mm_sel", 15), + GATE_BDP(CLK_BDP_VDO_DRAM, "bdp_vdo_d", "mm_sel", 16), + GATE_BDP(CLK_BDP_VDO_2FS, "bdp_vdo_2fs", "di_sel", 17), + GATE_BDP(CLK_BDP_VDO_B, "bdp_vdo_b", "mm_sel", 18), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_PXL, "bdp_di_pxl", "di_sel", 19), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_DRAM, "bdp_di_d", "mm_sel", 20), + GATE_BDP(CLK_BDP_WR_CHANNEL_DI_B, "bdp_di_b", "mm_sel", 21), + GATE_BDP(CLK_BDP_NR_AGENT, "bdp_nr_agent", "nr_sel", 22), + GATE_BDP(CLK_BDP_NR_DRAM, "bdp_nr_d", "mm_sel", 23), + GATE_BDP(CLK_BDP_NR_B, "bdp_nr_b", "mm_sel", 24), + GATE_BDP(CLK_BDP_BRIDGE_RT_B, "bdp_bridge_rt_b", "mm_sel", 25), + GATE_BDP(CLK_BDP_BRIDGE_RT_DRAM, "bdp_bridge_rt_d", "mm_sel", 26), + GATE_BDP(CLK_BDP_LARB_RT_DRAM, "bdp_larb_rt_d", "mm_sel", 27), + GATE_BDP(CLK_BDP_TVD_TDC, "bdp_tvd_tdc", "mm_sel", 28), + GATE_BDP(CLK_BDP_TVD_54, "bdp_tvd_clk_54", "tvd_sel", 29), + GATE_BDP(CLK_BDP_TVD_CBUS, "bdp_tvd_cbus", "mm_sel", 30), +}; + +static const struct mtk_clk_desc bdp_desc = { + .clks = bdp_clks, + .num_clks = ARRAY_SIZE(bdp_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_bdp[] = { + { + .compatible = "mediatek,mt2712-bdpsys", + .data = &bdp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_bdp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-bdp", + .of_match_table = of_match_clk_mt2712_bdp, + }, +}; + +builtin_platform_driver(clk_mt2712_bdp_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-img.c b/drivers/clk/mediatek/clk-mt2712-img.c new file mode 100644 index 000000000..3ffa51384 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-img.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_SMI_LARB2, "img_smi_larb2", "mm_sel", 0), + GATE_IMG(CLK_IMG_SENINF_SCAM_EN, "img_scam_en", "csi0", 3), + GATE_IMG(CLK_IMG_SENINF_CAM_EN, "img_cam_en", "mm_sel", 8), + GATE_IMG(CLK_IMG_CAM_SV_EN, "img_cam_sv_en", "mm_sel", 9), + GATE_IMG(CLK_IMG_CAM_SV1_EN, "img_cam_sv1_en", "mm_sel", 10), + GATE_IMG(CLK_IMG_CAM_SV2_EN, "img_cam_sv2_en", "mm_sel", 11), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_img[] = { + { + .compatible = "mediatek,mt2712-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-img", + .of_match_table = of_match_clk_mt2712_img, + }, +}; + +builtin_platform_driver(clk_mt2712_img_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-jpgdec.c b/drivers/clk/mediatek/clk-mt2712-jpgdec.c new file mode 100644 index 000000000..8c768d5ce --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-jpgdec.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs jpgdec_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_JPGDEC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &jpgdec_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate jpgdec_clks[] = { + GATE_JPGDEC(CLK_JPGDEC_JPGDEC1, "jpgdec_jpgdec1", "jpgdec_sel", 0), + GATE_JPGDEC(CLK_JPGDEC_JPGDEC, "jpgdec_jpgdec", "jpgdec_sel", 4), +}; + +static const struct mtk_clk_desc jpgdec_desc = { + .clks = jpgdec_clks, + .num_clks = ARRAY_SIZE(jpgdec_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_jpgdec[] = { + { + .compatible = "mediatek,mt2712-jpgdecsys", + .data = &jpgdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_jpgdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-jpgdec", + .of_match_table = of_match_clk_mt2712_jpgdec, + }, +}; + +builtin_platform_driver(clk_mt2712_jpgdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mfg.c b/drivers/clk/mediatek/clk-mt2712-mfg.c new file mode 100644 index 000000000..8949315c2 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mfg.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_mfg[] = { + { + .compatible = "mediatek,mt2712-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-mfg", + .of_match_table = of_match_clk_mt2712_mfg, + }, +}; + +builtin_platform_driver(clk_mt2712_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-mm.c b/drivers/clk/mediatek/clk-mt2712-mm.c new file mode 100644 index 000000000..ad6daa8f2 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-mm.c @@ -0,0 +1,139 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs mm2_cg_regs = { + .set_ofs = 0x224, + .clr_ofs = 0x228, + .sta_ofs = 0x220, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM0_MM, "mm_pwm0_mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DISP_PWM0_26M, "mm_pwm0_26m", "pwm_sel", 1), + GATE_MM1(CLK_MM_DISP_PWM1_MM, "mm_pwm1_mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DISP_PWM1_26M, "mm_pwm1_26m", "pwm_sel", 3), + GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), + GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_lntc", 5), + GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), + GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_lntc", 7), + GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "vpll_dpix", 8), + GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), + GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "vpll3_dpix", 10), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11), + GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "vpll_dpix", 16), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx", 17), + GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18), + GATE_MM1(CLK_MM_SMI_COMMON1, "mm_smi_common1", "mm_sel", 21), + GATE_MM1(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 22), + GATE_MM1(CLK_MM_MDP_RDMA2, "mm_mdp_rdma2", "mm_sel", 23), + GATE_MM1(CLK_MM_MDP_TDSHP2, "mm_mdp_tdshp2", "mm_sel", 24), + GATE_MM1(CLK_MM_DISP_OVL2, "mm_disp_ovl2", "mm_sel", 25), + GATE_MM1(CLK_MM_DISP_WDMA2, "mm_disp_wdma2", "mm_sel", 26), + GATE_MM1(CLK_MM_DISP_COLOR2, "mm_disp_color2", "mm_sel", 27), + GATE_MM1(CLK_MM_DISP_AAL1, "mm_disp_aal1", "mm_sel", 28), + GATE_MM1(CLK_MM_DISP_OD1, "mm_disp_od1", "mm_sel", 29), + GATE_MM1(CLK_MM_LVDS1_PIXEL, "mm_lvds1_pixel", "vpll3_dpix", 30), + GATE_MM1(CLK_MM_LVDS1_CTS, "mm_lvds1_cts", "lvdstx3", 31), + /* MM2 */ + GATE_MM2(CLK_MM_SMI_LARB7, "mm_smi_larb7", "mm_sel", 0), + GATE_MM2(CLK_MM_MDP_RDMA3, "mm_mdp_rdma3", "mm_sel", 1), + GATE_MM2(CLK_MM_MDP_WROT2, "mm_mdp_wrot2", "mm_sel", 2), + GATE_MM2(CLK_MM_DSI2, "mm_dsi2", "mm_sel", 3), + GATE_MM2(CLK_MM_DSI2_DIGITAL, "mm_dsi2_digital", "dsi0_lntc", 4), + GATE_MM2(CLK_MM_DSI3, "mm_dsi3", "mm_sel", 5), + GATE_MM2(CLK_MM_DSI3_DIGITAL, "mm_dsi3_digital", "dsi1_lntc", 6), +}; + +static int clk_mt2712_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static struct platform_driver clk_mt2712_mm_drv = { + .probe = clk_mt2712_mm_probe, + .driver = { + .name = "clk-mt2712-mm", + }, +}; + +builtin_platform_driver(clk_mt2712_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-vdec.c b/drivers/clk/mediatek/clk-mt2712-vdec.c new file mode 100644 index 000000000..572290dd4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-vdec.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_IMGRZ_CKEN, "vdec_imgrz_cken", "vdec_sel", 1), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_vdec[] = { + { + .compatible = "mediatek,mt2712-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-vdec", + .of_match_table = of_match_clk_mt2712_vdec, + }, +}; + +builtin_platform_driver(clk_mt2712_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt2712-venc.c b/drivers/clk/mediatek/clk-mt2712-venc.c new file mode 100644 index 000000000..9588eb030 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712-venc.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_SMI_COMMON_CON, "venc_smi", "mm_sel", 0), + GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4), + GATE_VENC(CLK_VENC_SMI_LARB6, "venc_smi_larb6", "jpgdec_sel", 12), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt2712_venc[] = { + { + .compatible = "mediatek,mt2712-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt2712_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt2712-venc", + .of_match_table = of_match_clk_mt2712_venc, + }, +}; + +builtin_platform_driver(clk_mt2712_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt2712.c b/drivers/clk/mediatek/clk-mt2712.c new file mode 100644 index 000000000..d6c2cc183 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt2712.c @@ -0,0 +1,1462 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Weiyi Lu <weiyi.lu@mediatek.com> + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "clk-gate.h" +#include "clk-pll.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt2712-clk.h> + +static DEFINE_SPINLOCK(mt2712_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_VPLL3_DPIX, "vpll3_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", NULL, 200000000), + FIXED_CLK(CLK_TOP_LTEPLL_FS26M, "ltepll_fs26m", NULL, 26000000), + FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 350000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC, "dsi0_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_DSI1_LNTC, "dsi1_lntc", NULL, 143000000), + FIXED_CLK(CLK_TOP_LVDSTX3_CLKDIG_CTS, "lvdstx3", NULL, 140000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx", NULL, 140000000), + FIXED_CLK(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", NULL, 32768), + FIXED_CLK(CLK_TOP_CLKRTC_INT, "clkrtc_int", NULL, 32747), + FIXED_CLK(CLK_TOP_CSI0, "csi0", NULL, 26000000), + FIXED_CLK(CLK_TOP_CVBSPLL, "cvbspll", NULL, 108000000), +}; + +static const struct mtk_fixed_factor top_early_divs[] = { + FACTOR(CLK_TOP_SYS_26M, "sys_26m", "clk26m", 1, + 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "sys_26m", 1, + 2), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_ARMCA35PLL, "armca35pll_ck", "armca35pll", 1, + 1), + FACTOR(CLK_TOP_ARMCA35PLL_600M, "armca35pll_600m", "armca35pll_ck", 1, + 2), + FACTOR(CLK_TOP_ARMCA35PLL_400M, "armca35pll_400m", "armca35pll_ck", 1, + 3), + FACTOR(CLK_TOP_ARMCA72PLL, "armca72pll_ck", "armca72pll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, + 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, + 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, + 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, + 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "syspll_ck", 1, + 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, + 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "syspll_ck", 1, + 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, + 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "syspll_ck", 1, + 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, + 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll_ck", "univpll", 1, + 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_ck", 1, + 7), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_ck", 1, + 26), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univpll_ck", 1, + 52), + FACTOR(CLK_TOP_UNIVPLL_D104, "univpll_d104", "univpll_ck", 1, + 104), + FACTOR(CLK_TOP_UNIVPLL_D208, "univpll_d208", "univpll_ck", 1, + 208), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_ck", 1, + 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_ck", 1, + 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, + 8), + FACTOR(CLK_TOP_F_MP0_PLL1, "f_mp0_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_MP0_PLL2, "f_mp0_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL1, "f_big_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BIG_PLL2, "f_big_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL1, "f_bus_pll1_ck", "univpll_d2", 1, + 1), + FACTOR(CLK_TOP_F_BUS_PLL2, "f_bus_pll2_ck", "univpll1_d2", 1, + 1), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, + 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, + 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, + 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, + 8), + FACTOR(CLK_TOP_APLL1_D16, "apll1_d16", "apll1_ck", 1, + 16), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, + 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, + 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1, + 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1, + 8), + FACTOR(CLK_TOP_APLL2_D16, "apll2_d16", "apll2_ck", 1, + 16), + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll_ck", 1, + 8), + FACTOR(CLK_TOP_LVDSPLL2, "lvdspll2_ck", "lvdspll2", 1, + 1), + FACTOR(CLK_TOP_LVDSPLL2_D2, "lvdspll2_d2", "lvdspll2_ck", 1, + 2), + FACTOR(CLK_TOP_LVDSPLL2_D4, "lvdspll2_d4", "lvdspll2_ck", 1, + 4), + FACTOR(CLK_TOP_LVDSPLL2_D8, "lvdspll2_d8", "lvdspll2_ck", 1, + 8), + FACTOR(CLK_TOP_ETHERPLL_125M, "etherpll_125m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_ETHERPLL_50M, "etherpll_50m", "etherpll", 1, + 1), + FACTOR(CLK_TOP_CVBS, "cvbs", "cvbspll", 1, + 1), + FACTOR(CLK_TOP_CVBS_D2, "cvbs_d2", "cvbs", 1, + 2), + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, + 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, + 2), + FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, + 1), + FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll_ck", 1, + 2), + FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, + 1), + FACTOR(CLK_TOP_VCODECPLL_D2, "vcodecpll_d2", "vcodecpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, + 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, + 8), + FACTOR(CLK_TOP_TVDPLL_429M, "tvdpll_429m", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_429M_D2, "tvdpll_429m_d2", "tvdpll_429m", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_429M_D4, "tvdpll_429m_d4", "tvdpll_429m", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2_ck", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2_ck", 1, + 4), + FACTOR(CLK_TOP_D2A_ULCLK_6P5M, "d2a_ulclk_6p5m", "clk26m", 1, + 4), + FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1_ck", 1, + 3), + FACTOR(CLK_TOP_APLL2_D3, "apll2_d3", "apll2_ck", 1, + 3), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "msdcpll2_ck" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck" +}; + +static const char * const mm_parents[] = { + "clk26m", + "vencpll_ck", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vcodecpll_ck", + "tvdpll_429m", + "univpll_d3", + "vencpll_ck", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "syspll3_d2", + "tvdpll_ck" +}; + +static const char * const venc_parents[] = { + "clk26m", + "univpll1_d2", + "mmpll_d2", + "tvdpll_d2", + "syspll1_d2", + "univpll_d5", + "vcodecpll_d2", + "univpll2_d2", + "syspll3_d2" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d52", + "univpll_d208", + "univpll_d104", + "clk26m_d2", + "univpll_d26", + "univpll2_d8", + "syspll3_d4", + "syspll3_d2", + "univpll1_d4", + "univpll2_d2" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8" +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const usb30_parents[] = { + "clk26m", + "univpll3_d2", + "univpll3_d4", + "univpll2_d4" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "msdcpll_d4", + "vencpll_d2", + "univpll1_d2", + "msdcpll2_ck", + "msdcpll2_d2", + "msdcpll2_d4" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "univpll_d7", + "vencpll_d2" +}; + +static const char * const msdc30_3_parents[] = { + "clk26m", + "msdcpll2_ck", + "msdcpll2_d2", + "univpll2_d2", + "msdcpll2_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2", + "msdcpll_ck", + "msdcpll_d2", + "msdcpll_d4" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "syspll3_d2", + "syspll3_d4" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "syspll3_d4" +}; + +static const char * const dpilvds1_parents[] = { + "clk26m", + "lvdspll2_ck", + "lvdspll2_d2", + "lvdspll2_d4", + "lvdspll2_d8", + "clkfpc" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5" +}; + +static const char * const nr_parents[] = { + "clk26m", + "univpll1_d4", + "syspll2_d2", + "syspll1_d4", + "univpll1_d8", + "univpll3_d2", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const nfi2x_parents[] = { + "clk26m", + "syspll4_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll3_d2", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "syspll_d5", + "syspll1_d2" +}; + +static const char * const irda_parents[] = { + "clk26m", + "univpll2_d4", + "syspll2_d4", + "univpll2_d8" +}; + +static const char * const cci400_parents[] = { + "clk26m", + "vencpll_ck", + "armca35pll_600m", + "armca35pll_400m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "univpll_d3" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const mem_mfg_parents[] = { + "clk26m", + "mmpll_ck", + "univpll_d3" +}; + +static const char * const axi_mfg_parents[] = { + "clk26m", + "axi_sel", + "univpll_d5" +}; + +static const char * const scam_parents[] = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "syspll2_d4" +}; + +static const char * const nfiecc_parents[] = { + "clk26m", + "nfi2x_sel", + "syspll_d7", + "syspll2_d2", + "univpll2_d2", + "univpll_d5", + "syspll1_d2" +}; + +static const char * const pe2_mac_p0_parents[] = { + "clk26m", + "syspll1_d8", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "syspll3_d2" +}; + +static const char * const dpilvds_parents[] = { + "clk26m", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "clkfpc" +}; + +static const char * const hdcp_parents[] = { + "clk26m", + "syspll4_d2", + "syspll3_d4", + "univpll2_d4" +}; + +static const char * const hdcp_24m_parents[] = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll2_d8" +}; + +static const char * const rtc_parents[] = { + "clkrtc_int", + "clkrtc_ext", + "clk26m", + "univpll3_d8" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk26m_d2", + "syspll4_d4", + "univpll2_d8", + "univpll3_d4", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "etherpll_125m", + "syspll1_d4" +}; + +static const char * const apll_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8", + "apll1_d16", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8", + "apll2_d16", + "clk26m", + "clk26m" +}; + +static const char * const a1sys_hp_parents[] = { + "clk26m", + "apll1_ck", + "apll1_d2", + "apll1_d4", + "apll1_d8", + "apll1_d3" +}; + +static const char * const a2sys_hp_parents[] = { + "clk26m", + "apll2_ck", + "apll2_d2", + "apll2_d4", + "apll2_d8", + "apll2_d3" +}; + +static const char * const asm_l_parents[] = { + "clk26m", + "univpll2_d4", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const i2so1_parents[] = { + "clk26m", + "apll1_ck", + "apll2_ck" +}; + +static const char * const ether_125m_parents[] = { + "clk26m", + "etherpll_125m", + "univpll3_d2" +}; + +static const char * const ether_50m_parents[] = { + "clk26m", + "etherpll_50m", + "apll1_d3", + "univpll3_d4" +}; + +static const char * const jpgdec_parents[] = { + "clk26m", + "univpll_d3", + "tvdpll_429m", + "vencpll_ck", + "syspll_d3", + "vcodecpll_ck", + "univpll1_d2", + "armca35pll_400m", + "tvdpll_429m_d2", + "tvdpll_429m_d4" +}; + +static const char * const spislv_parents[] = { + "clk26m", + "univpll2_d4", + "univpll1_d4", + "univpll2_d2", + "univpll3_d2", + "univpll1_d8", + "univpll1_d2", + "univpll_d5" +}; + +static const char * const ether_parents[] = { + "clk26m", + "etherpll_50m", + "univpll_d26" +}; + +static const char * const di_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "vencpll_ck", + "vencpll_d2", + "cvbs", + "cvbs_d2" +}; + +static const char * const tvd_parents[] = { + "clk26m", + "cvbs_d2", + "univpll2_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll_d26", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const msdc0p_aes_parents[] = { + "clk26m", + "syspll_d2", + "univpll_d3", + "vcodecpll_ck" +}; + +static const char * const cmsys_parents[] = { + "clk26m", + "univpll_d3", + "syspll_d3", + "syspll1_d2", + "syspll2_d2" +}; + +static const char * const gcpu_parents[] = { + "clk26m", + "syspll_d3", + "syspll1_d2", + "univpll1_d2", + "univpll_d5", + "univpll3_d2", + "univpll_d3" +}; + +static const char * const aud_apll1_parents[] = { + "apll1", + "clkaud_ext_i_1" +}; + +static const char * const aud_apll2_parents[] = { + "apll2", + "clkaud_ext_i_2" +}; + +static const char * const apll1_ref_parents[] = { + "clkaud_ext_i_2", + "clkaud_ext_i_1", + "clki2si0_mck_i", + "clki2si1_mck_i", + "clki2si2_mck_i", + "clktdmin_mclk_i", + "clki2si2_mck_i", + "clktdmin_mclk_i" +}; + +static const char * const audull_vtx_parents[] = { + "d2a_ulclk_6p5m", + "clkaud_ext_i_0" +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x040, 0, 3, + 7, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, 8, 1, + 15, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", + mm_parents, 0x040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", + pwm_parents, 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", + vdec_parents, 0x050, 8, 4, 15), + MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", + venc_parents, 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", + mfg_parents, 0x050, 24, 4, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", + camtg_parents, 0x060, 0, 4, 7), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", + uart_parents, 0x060, 8, 1, 15), + MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", + spi_parents, 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", + usb20_parents, 0x060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", + usb30_parents, 0x070, 0, 2, 7), + MUX_GATE(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc50_0_h_sel", + msdc50_0_h_parents, 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x070, 16, 4, 23), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, 0x070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", + msdc30_1_parents, 0x080, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", + msdc30_3_parents, 0x080, 8, 4, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", + audio_parents, 0x080, 16, 2, 23), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, 0x080, 24, 3, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", + pmicspi_parents, 0x090, 0, 3, 7), + MUX_GATE(CLK_TOP_DPILVDS1_SEL, "dpilvds1_sel", + dpilvds1_parents, 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", + atb_parents, 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_NR_SEL, "nr_sel", + nr_parents, 0x090, 24, 3, 31), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_NFI2X_SEL, "nfi2x_sel", + nfi2x_parents, 0x0a0, 0, 4, 7), + MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", + irda_parents, 0x0a0, 8, 2, 15), + MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", + cci400_parents, 0x0a0, 16, 3, 23), + MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", + aud_1_parents, 0x0a0, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", + aud_2_parents, 0x0b0, 0, 2, 7), + MUX_GATE(CLK_TOP_MEM_MFG_IN_AS_SEL, "mem_mfg_sel", + mem_mfg_parents, 0x0b0, 8, 2, 15), + MUX_GATE(CLK_TOP_AXI_MFG_IN_AS_SEL, "axi_mfg_sel", + axi_mfg_parents, 0x0b0, 16, 2, 23), + MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", + scam_parents, 0x0b0, 24, 2, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_NFIECC_SEL, "nfiecc_sel", + nfiecc_parents, 0x0c0, 0, 3, 7), + MUX_GATE(CLK_TOP_PE2_MAC_P0_SEL, "pe2_mac_p0_sel", + pe2_mac_p0_parents, 0x0c0, 8, 3, 15), + MUX_GATE(CLK_TOP_PE2_MAC_P1_SEL, "pe2_mac_p1_sel", + pe2_mac_p0_parents, 0x0c0, 16, 3, 23), + MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", + dpilvds_parents, 0x0c0, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(CLK_TOP_MSDC50_3_HCLK_SEL, "msdc50_3_h_sel", + msdc50_0_h_parents, 0x0d0, 0, 3, 7), + MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", + hdcp_parents, 0x0d0, 8, 2, 15), + MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", + hdcp_24m_parents, 0x0d0, 16, 2, 23), + MUX_GATE_FLAGS(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x0d0, 24, 2, + 31, CLK_IS_CRITICAL), + /* CLK_CFG_10 */ + MUX_GATE(CLK_TOP_SPINOR_SEL, "spinor_sel", + spinor_parents, 0x500, 0, 4, 7), + MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", + apll_parents, 0x500, 8, 4, 15), + MUX_GATE(CLK_TOP_APLL2_SEL, "apll2_sel", + apll_parents, 0x500, 16, 4, 23), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", + a1sys_hp_parents, 0x500, 24, 3, 31), + /* CLK_CFG_11 */ + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", + a2sys_hp_parents, 0x510, 0, 3, 7), + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", + asm_l_parents, 0x510, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", + asm_l_parents, 0x510, 16, 2, 23), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", + asm_l_parents, 0x510, 24, 2, 31), + /* CLK_CFG_12 */ + MUX_GATE(CLK_TOP_I2SO1_SEL, "i2so1_sel", + i2so1_parents, 0x520, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SO2_SEL, "i2so2_sel", + i2so1_parents, 0x520, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SO3_SEL, "i2so3_sel", + i2so1_parents, 0x520, 16, 2, 23), + MUX_GATE(CLK_TOP_TDMO0_SEL, "tdmo0_sel", + i2so1_parents, 0x520, 24, 2, 31), + /* CLK_CFG_13 */ + MUX_GATE(CLK_TOP_TDMO1_SEL, "tdmo1_sel", + i2so1_parents, 0x530, 0, 2, 7), + MUX_GATE(CLK_TOP_I2SI1_SEL, "i2si1_sel", + i2so1_parents, 0x530, 8, 2, 15), + MUX_GATE(CLK_TOP_I2SI2_SEL, "i2si2_sel", + i2so1_parents, 0x530, 16, 2, 23), + MUX_GATE(CLK_TOP_I2SI3_SEL, "i2si3_sel", + i2so1_parents, 0x530, 24, 2, 31), + /* CLK_CFG_14 */ + MUX_GATE(CLK_TOP_ETHER_125M_SEL, "ether_125m_sel", + ether_125m_parents, 0x540, 0, 2, 7), + MUX_GATE(CLK_TOP_ETHER_50M_SEL, "ether_50m_sel", + ether_50m_parents, 0x540, 8, 2, 15), + MUX_GATE(CLK_TOP_JPGDEC_SEL, "jpgdec_sel", + jpgdec_parents, 0x540, 16, 4, 23), + MUX_GATE(CLK_TOP_SPISLV_SEL, "spislv_sel", + spislv_parents, 0x540, 24, 3, 31), + /* CLK_CFG_15 */ + MUX_GATE(CLK_TOP_ETHER_50M_RMII_SEL, "ether_sel", + ether_parents, 0x550, 0, 2, 7), + MUX_GATE(CLK_TOP_CAM2TG_SEL, "cam2tg_sel", + camtg_parents, 0x550, 8, 4, 15), + MUX_GATE(CLK_TOP_DI_SEL, "di_sel", + di_parents, 0x550, 16, 3, 23), + MUX_GATE(CLK_TOP_TVD_SEL, "tvd_sel", + tvd_parents, 0x550, 24, 2, 31), + /* CLK_CFG_16 */ + MUX_GATE(CLK_TOP_I2C_SEL, "i2c_sel", + i2c_parents, 0x560, 0, 3, 7), + MUX_GATE(CLK_TOP_PWM_INFRA_SEL, "pwm_infra_sel", + pwm_parents, 0x560, 8, 2, 15), + MUX_GATE(CLK_TOP_MSDC0P_AES_SEL, "msdc0p_aes_sel", + msdc0p_aes_parents, 0x560, 16, 2, 23), + MUX_GATE(CLK_TOP_CMSYS_SEL, "cmsys_sel", + cmsys_parents, 0x560, 24, 3, 31), + /* CLK_CFG_17 */ + MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", + gcpu_parents, 0x570, 0, 3, 7), + /* CLK_AUDDIV_4 */ + MUX(CLK_TOP_AUD_APLL1_SEL, "aud_apll1_sel", + aud_apll1_parents, 0x134, 0, 1), + MUX(CLK_TOP_AUD_APLL2_SEL, "aud_apll2_sel", + aud_apll2_parents, 0x134, 1, 1), + MUX(CLK_TOP_DA_AUDULL_VTX_6P5M_SEL, "audull_vtx_sel", + audull_vtx_parents, 0x134, 31, 1), + MUX(CLK_TOP_APLL1_REF_SEL, "apll1_ref_sel", + apll1_ref_parents, 0x134, 4, 3), + MUX(CLK_TOP_APLL2_REF_SEL, "apll2_ref_sel", + apll1_ref_parents, 0x134, 7, 3), +}; + +static const char * const mcu_mp0_parents[] = { + "clk26m", + "armca35pll_ck", + "f_mp0_pll1_ck", + "f_mp0_pll2_ck" +}; + +static const char * const mcu_mp2_parents[] = { + "clk26m", + "armca72pll_ck", + "f_big_pll1_ck", + "f_big_pll2_ck" +}; + +static const char * const mcu_bus_parents[] = { + "clk26m", + "cci400_sel", + "f_bus_pll1_ck", + "f_bus_pll2_ck" +}; + +static struct mtk_composite mcu_muxes[] = { + /* mp0_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, + 9, 2, -1, CLK_IS_CRITICAL), + /* mp2_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, + 9, 2, -1, CLK_IS_CRITICAL), + /* bus_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, + 9, 2, -1, CLK_IS_CRITICAL), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL_DIV0, "apll_div0", "i2so1_sel", 0x124, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV1, "apll_div1", "i2so2_sel", 0x124, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV2, "apll_div2", "i2so3_sel", 0x124, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV3, "apll_div3", "tdmo0_sel", 0x124, 24, 8), + DIV_ADJ(CLK_TOP_APLL_DIV4, "apll_div4", "tdmo1_sel", 0x128, 0, 8), + DIV_ADJ(CLK_TOP_APLL_DIV5, "apll_div5", "i2si1_sel", 0x128, 8, 8), + DIV_ADJ(CLK_TOP_APLL_DIV6, "apll_div6", "i2si2_sel", 0x128, 16, 8), + DIV_ADJ(CLK_TOP_APLL_DIV7, "apll_div7", "i2si3_sel", 0x128, 24, 8), +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x424, + .clr_ofs = 0x424, + .sta_ofs = 0x424, +}; + +#define GATE_TOP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_TOP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_APLL_DIV_PDN0, "apll_div_pdn0", "i2so1_sel", 0), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN1, "apll_div_pdn1", "i2so2_sel", 1), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN2, "apll_div_pdn2", "i2so3_sel", 2), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN3, "apll_div_pdn3", "tdmo0_sel", 3), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN4, "apll_div_pdn4", "tdmo1_sel", 4), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN5, "apll_div_pdn5", "i2si1_sel", 5), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN6, "apll_div_pdn6", "i2si2_sel", 6), + GATE_TOP0(CLK_TOP_APLL_DIV_PDN7, "apll_div_pdn7", "i2si3_sel", 7), + /* TOP1 */ + GATE_TOP1(CLK_TOP_NFI2X_EN, "nfi2x_en", "nfi2x_sel", 0), + GATE_TOP1(CLK_TOP_NFIECC_EN, "nfiecc_en", "nfiecc_sel", 1), + GATE_TOP1(CLK_TOP_NFI1X_CK_EN, "nfi1x_ck_en", "nfi2x_sel", 2), +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +#define GATE_INFRA(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_INFRA(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_INFRA(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), + GATE_INFRA(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "spi_sel", 24), + GATE_INFRA(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "spislv_sel", 25), + GATE_INFRA(CLK_INFRA_AO_UART5, "infra_ao_uart5", "axi_sel", 26), +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xc, + .clr_ofs = 0x14, + .sta_ofs = 0x1c, +}; + +static const struct mtk_gate_regs peri2_cg_regs = { + .set_ofs = 0x42c, + .clr_ofs = 0x42c, + .sta_ofs = 0x42c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_NFI, "per_nfi", + "axi_sel", 0), + GATE_PERI0(CLK_PERI_THERM, "per_therm", + "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM0, "per_pwm0", + "pwm_sel", 2), + GATE_PERI0(CLK_PERI_PWM1, "per_pwm1", + "pwm_sel", 3), + GATE_PERI0(CLK_PERI_PWM2, "per_pwm2", + "pwm_sel", 4), + GATE_PERI0(CLK_PERI_PWM3, "per_pwm3", + "pwm_sel", 5), + GATE_PERI0(CLK_PERI_PWM4, "per_pwm4", + "pwm_sel", 6), + GATE_PERI0(CLK_PERI_PWM5, "per_pwm5", + "pwm_sel", 7), + GATE_PERI0(CLK_PERI_PWM6, "per_pwm6", + "pwm_sel", 8), + GATE_PERI0(CLK_PERI_PWM7, "per_pwm7", + "pwm_sel", 9), + GATE_PERI0(CLK_PERI_PWM, "per_pwm", + "pwm_sel", 10), + GATE_PERI0(CLK_PERI_AP_DMA, "per_ap_dma", + "axi_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_0, "per_msdc30_0", + "msdc50_0_sel", 14), + GATE_PERI0(CLK_PERI_MSDC30_1, "per_msdc30_1", + "msdc30_1_sel", 15), + GATE_PERI0(CLK_PERI_MSDC30_2, "per_msdc30_2", + "msdc30_2_sel", 16), + GATE_PERI0(CLK_PERI_MSDC30_3, "per_msdc30_3", + "msdc30_3_sel", 17), + GATE_PERI0(CLK_PERI_UART0, "per_uart0", + "uart_sel", 20), + GATE_PERI0(CLK_PERI_UART1, "per_uart1", + "uart_sel", 21), + GATE_PERI0(CLK_PERI_UART2, "per_uart2", + "uart_sel", 22), + GATE_PERI0(CLK_PERI_UART3, "per_uart3", + "uart_sel", 23), + GATE_PERI0(CLK_PERI_I2C0, "per_i2c0", + "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C1, "per_i2c1", + "axi_sel", 25), + GATE_PERI0(CLK_PERI_I2C2, "per_i2c2", + "axi_sel", 26), + GATE_PERI0(CLK_PERI_I2C3, "per_i2c3", + "axi_sel", 27), + GATE_PERI0(CLK_PERI_I2C4, "per_i2c4", + "axi_sel", 28), + GATE_PERI0(CLK_PERI_AUXADC, "per_auxadc", + "ltepll_fs26m", 29), + GATE_PERI0(CLK_PERI_SPI0, "per_spi0", + "spi_sel", 30), + /* PERI1 */ + GATE_PERI1(CLK_PERI_SPI, "per_spi", + "spinor_sel", 1), + GATE_PERI1(CLK_PERI_I2C5, "per_i2c5", + "axi_sel", 3), + GATE_PERI1(CLK_PERI_SPI2, "per_spi2", + "spi_sel", 5), + GATE_PERI1(CLK_PERI_SPI3, "per_spi3", + "spi_sel", 6), + GATE_PERI1(CLK_PERI_SPI5, "per_spi5", + "spi_sel", 8), + GATE_PERI1(CLK_PERI_UART4, "per_uart4", + "uart_sel", 9), + GATE_PERI1(CLK_PERI_SFLASH, "per_sflash", + "uart_sel", 11), + GATE_PERI1(CLK_PERI_GMAC, "per_gmac", + "uart_sel", 12), + GATE_PERI1(CLK_PERI_PCIE0, "per_pcie0", + "uart_sel", 14), + GATE_PERI1(CLK_PERI_PCIE1, "per_pcie1", + "uart_sel", 15), + GATE_PERI1(CLK_PERI_GMAC_PCLK, "per_gmac_pclk", + "uart_sel", 16), + /* PERI2 */ + GATE_PERI2(CLK_PERI_MSDC50_0_EN, "per_msdc50_0_en", + "msdc50_0_sel", 0), + GATE_PERI2(CLK_PERI_MSDC30_1_EN, "per_msdc30_1_en", + "msdc30_1_sel", 1), + GATE_PERI2(CLK_PERI_MSDC30_2_EN, "per_msdc30_2_en", + "msdc30_2_sel", 2), + GATE_PERI2(CLK_PERI_MSDC30_3_EN, "per_msdc30_3_en", + "msdc30_3_sel", 3), + GATE_PERI2(CLK_PERI_MSDC50_0_HCLK_EN, "per_msdc50_0_h", + "msdc50_0_h_sel", 4), + GATE_PERI2(CLK_PERI_MSDC50_3_HCLK_EN, "per_msdc50_3_h", + "msdc50_3_h_sel", 5), + GATE_PERI2(CLK_PERI_MSDC30_0_QTR_EN, "per_msdc30_0_q", + "axi_sel", 6), + GATE_PERI2(CLK_PERI_MSDC30_3_QTR_EN, "per_msdc30_3_q", + "mem_sel", 7), +}; + +#define MT2712_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT2712_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT2712_RST_BAR, \ + .fmax = MT2712_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _pcwbits, _pd_reg, _pd_shift, _tuner_reg, \ + _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ + _pcw_shift, NULL) + +static const struct mtk_pll_div_table armca35pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1202500000 }, + { .div = 2, .freq = 500500000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table armca72pll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 994500000 }, + { .div = 2, .freq = 520000000 }, + { .div = 3, .freq = 315250000 }, + { .div = 4, .freq = 157625000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT2712_PLL_FMAX }, + { .div = 1, .freq = 1001000000 }, + { .div = 2, .freq = 601250000 }, + { .div = 3, .freq = 250250000 }, + { .div = 4, .freq = 125125000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0xf0000100, + HAVE_RST_BAR, 31, 0x0230, 4, 0, 0, 0, 0x0234, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0240, 0x024C, 0xfe000100, + HAVE_RST_BAR, 31, 0x0240, 4, 0, 0, 0, 0x0244, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x0320, 0x032C, 0xc0000100, + 0, 31, 0x0320, 4, 0, 0, 0, 0x0324, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x0280, 0x028C, 0x00000100, + 0, 31, 0x0280, 4, 0, 0, 0, 0x0284, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0330, 0x0340, 0x00000100, + 0, 31, 0x0330, 4, 0x0338, 0x0014, 0, 0x0334, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0350, 0x0360, 0x00000100, + 0, 31, 0x0350, 4, 0x0358, 0x0014, 1, 0x0354, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0370, 0x037c, 0x00000100, + 0, 31, 0x0370, 4, 0, 0, 0, 0x0374, 0), + PLL(CLK_APMIXED_LVDSPLL2, "lvdspll2", 0x0390, 0x039C, 0x00000100, + 0, 31, 0x0390, 4, 0, 0, 0, 0x0394, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0270, 0x027C, 0x00000100, + 0, 31, 0x0270, 4, 0, 0, 0, 0x0274, 0), + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x0410, 0x041C, 0x00000100, + 0, 31, 0x0410, 4, 0, 0, 0, 0x0414, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0290, 0x029C, 0xc0000100, + 0, 31, 0x0290, 4, 0, 0, 0, 0x0294, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0250, 0x0260, 0x00000100, + 0, 31, 0x0250, 4, 0, 0, 0, 0x0254, 0, + mmpll_div_table), + PLL_B(CLK_APMIXED_ARMCA35PLL, "armca35pll", 0x0100, 0x0110, 0xf0000100, + HAVE_RST_BAR, 31, 0x0100, 4, 0, 0, 0, 0x0104, 0, + armca35pll_div_table), + PLL_B(CLK_APMIXED_ARMCA72PLL, "armca72pll", 0x0210, 0x0220, 0x00000100, + 0, 31, 0x0210, 4, 0, 0, 0, 0x0214, 0, + armca72pll_div_table), + PLL(CLK_APMIXED_ETHERPLL, "etherpll", 0x0300, 0x030C, 0xc0000100, + 0, 31, 0x0300, 4, 0, 0, 0, 0x0304, 0), +}; + +static u16 infrasys_rst_ofs[] = { 0x30, 0x34, }; +static u16 pericfg_rst_ofs[] = { 0x0, 0x4, }; + +static const struct mtk_clk_rst_desc clk_rst_desc[] = { + /* infra */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), + }, + /* peri */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), + }, +}; + +static int clk_mt2712_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (r) + goto free_clk_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, "Cannot register clock provider: %d\n", r); + goto unregister_plls; + } + + return 0; + +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return r; +} + +static struct clk_hw_onecell_data *top_clk_data; + +static void clk_mt2712_top_init_early(struct device_node *node) +{ + int r, i; + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + for (i = 0; i < CLK_TOP_NR_CLK; i++) + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); + } + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} + +CLK_OF_DECLARE_DRIVER(mt2712_topckgen, "mediatek,mt2712-topckgen", + clk_mt2712_top_init_early); + +static int clk_mt2712_top_probe(struct platform_device *pdev) +{ + int r, i; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + if (!top_clk_data) { + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + } else { + for (i = 0; i < CLK_TOP_NR_CLK; i++) { + if (top_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + top_clk_data->hws[i] = ERR_PTR(-ENOENT); + } + } + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt2712_clk_lock, top_clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + top_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static int clk_mt2712_infra_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); + + return r; +} + +static int clk_mt2712_peri_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); + + return r; +} + +static int clk_mt2712_mcu_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + + mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + &mt2712_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r != 0) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt2712[] = { + { + .compatible = "mediatek,mt2712-apmixedsys", + .data = clk_mt2712_apmixed_probe, + }, { + .compatible = "mediatek,mt2712-topckgen", + .data = clk_mt2712_top_probe, + }, { + .compatible = "mediatek,mt2712-infracfg", + .data = clk_mt2712_infra_probe, + }, { + .compatible = "mediatek,mt2712-pericfg", + .data = clk_mt2712_peri_probe, + }, { + .compatible = "mediatek,mt2712-mcucfg", + .data = clk_mt2712_mcu_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt2712_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r != 0) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt2712_drv = { + .probe = clk_mt2712_probe, + .driver = { + .name = "clk-mt2712", + .of_match_table = of_match_clk_mt2712, + }, +}; + +static int __init clk_mt2712_init(void) +{ + return platform_driver_register(&clk_mt2712_drv); +} + +arch_initcall(clk_mt2712_init); diff --git a/drivers/clk/mediatek/clk-mt6765-audio.c b/drivers/clk/mediatek/clk-mt6765-audio.c new file mode 100644 index 000000000..5682e0302 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-audio.c @@ -0,0 +1,78 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x4, + .sta_ofs = 0x4, +}; + +#define GATE_AUDIO0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUDIO_AFE, "aud_afe", "audio_ck", 2), + GATE_AUDIO0(CLK_AUDIO_22M, "aud_22m", "aud_engen1_ck", 8), + GATE_AUDIO0(CLK_AUDIO_APLL_TUNER, "aud_apll_tuner", + "aud_engen1_ck", 19), + GATE_AUDIO0(CLK_AUDIO_ADC, "aud_adc", "audio_ck", 24), + GATE_AUDIO0(CLK_AUDIO_DAC, "aud_dac", "audio_ck", 25), + GATE_AUDIO0(CLK_AUDIO_DAC_PREDIS, "aud_dac_predis", + "audio_ck", 26), + GATE_AUDIO0(CLK_AUDIO_TML, "aud_tml", "audio_ck", 27), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUDIO_I2S1_BCLK, "aud_i2s1_bclk", + "audio_ck", 4), + GATE_AUDIO1(CLK_AUDIO_I2S2_BCLK, "aud_i2s2_bclk", + "audio_ck", 5), + GATE_AUDIO1(CLK_AUDIO_I2S3_BCLK, "aud_i2s3_bclk", + "audio_ck", 6), + GATE_AUDIO1(CLK_AUDIO_I2S4_BCLK, "aud_i2s4_bclk", + "audio_ck", 7), +}; + +static const struct mtk_clk_desc audio_desc = { + .clks = audio_clks, + .num_clks = ARRAY_SIZE(audio_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_audio[] = { + { + .compatible = "mediatek,mt6765-audsys", + .data = &audio_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_audio_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-audio", + .of_match_table = of_match_clk_mt6765_audio, + }, +}; + +builtin_platform_driver(clk_mt6765_audio_drv); diff --git a/drivers/clk/mediatek/clk-mt6765-cam.c b/drivers/clk/mediatek/clk-mt6765-cam.c new file mode 100644 index 000000000..6e7d192c1 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-cam.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB3, "cam_larb3", "mm_ck", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "mm_ck", 1), + GATE_CAM(CLK_CAM, "cam", "mm_ck", 6), + GATE_CAM(CLK_CAMTG, "camtg", "mm_ck", 7), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "mm_ck", 8), + GATE_CAM(CLK_CAMSV0, "camsv0", "mm_ck", 9), + GATE_CAM(CLK_CAMSV1, "camsv1", "mm_ck", 10), + GATE_CAM(CLK_CAMSV2, "camsv2", "mm_ck", 11), + GATE_CAM(CLK_CAM_CCU, "cam_ccu", "mm_ck", 12), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_cam[] = { + { + .compatible = "mediatek,mt6765-camsys", + .data = &cam_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-cam", + .of_match_table = of_match_clk_mt6765_cam, + }, +}; + +builtin_platform_driver(clk_mt6765_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt6765-img.c b/drivers/clk/mediatek/clk-mt6765-img.c new file mode 100644 index 000000000..cfbc90798 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-img.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_LARB2, "img_larb2", "mm_ck", 0), + GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_ck", 2), + GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_ck", 3), + GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_ck", 4), + GATE_IMG(CLK_IMG_RSC, "img_rsc", "mm_ck", 5), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_img[] = { + { + .compatible = "mediatek,mt6765-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-img", + .of_match_table = of_match_clk_mt6765_img, + }, +}; + +builtin_platform_driver(clk_mt6765_img_drv); diff --git a/drivers/clk/mediatek/clk-mt6765-mipi0a.c b/drivers/clk/mediatek/clk-mt6765-mipi0a.c new file mode 100644 index 000000000..f2b9dc808 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-mipi0a.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs mipi0a_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x80, + .sta_ofs = 0x80, +}; + +#define GATE_MIPI0A(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mipi0a_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate mipi0a_clks[] = { + GATE_MIPI0A(CLK_MIPI0A_CSR_CSI_EN_0A, + "mipi0a_csr_0a", "f_fseninf_ck", 1), +}; + +static const struct mtk_clk_desc mipi0a_desc = { + .clks = mipi0a_clks, + .num_clks = ARRAY_SIZE(mipi0a_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_mipi0a[] = { + { + .compatible = "mediatek,mt6765-mipi0a", + .data = &mipi0a_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_mipi0a_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-mipi0a", + .of_match_table = of_match_clk_mt6765_mipi0a, + }, +}; + +builtin_platform_driver(clk_mt6765_mipi0a_drv); diff --git a/drivers/clk/mediatek/clk-mt6765-mm.c b/drivers/clk/mediatek/clk-mt6765-mm.c new file mode 100644 index 000000000..a4570c9db --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-mm.c @@ -0,0 +1,81 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs mm_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +#define GATE_MM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM */ + GATE_MM(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_ck", 0), + GATE_MM(CLK_MM_MDP_CCORR0, "mm_mdp_ccorr0", "mm_ck", 1), + GATE_MM(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_ck", 2), + GATE_MM(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_ck", 3), + GATE_MM(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_ck", 4), + GATE_MM(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_ck", 5), + GATE_MM(CLK_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_ck", 6), + GATE_MM(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_ck", 7), + GATE_MM(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_ck", 8), + GATE_MM(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "mm_ck", 9), + GATE_MM(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_ck", 10), + GATE_MM(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_ck", 11), + GATE_MM(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_ck", 12), + GATE_MM(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_ck", 13), + GATE_MM(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_ck", 14), + GATE_MM(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_ck", 15), + GATE_MM(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_ck", 16), + GATE_MM(CLK_MM_DSI0, "mm_dsi0", "mm_ck", 17), + GATE_MM(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_ck", 18), + GATE_MM(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_ck", 19), + GATE_MM(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_ck", 20), + GATE_MM(CLK_MM_SMI_COMM0, "mm_smi_comm0", "mm_ck", 21), + GATE_MM(CLK_MM_SMI_COMM1, "mm_smi_comm1", "mm_ck", 22), + GATE_MM(CLK_MM_CAM_MDP, "mm_cam_mdp_ck", "mm_ck", 23), + GATE_MM(CLK_MM_SMI_IMG, "mm_smi_img_ck", "mm_ck", 24), + GATE_MM(CLK_MM_SMI_CAM, "mm_smi_cam_ck", "mm_ck", 25), + GATE_MM(CLK_MM_IMG_DL_RELAY, "mm_img_dl_relay", "mm_ck", 26), + GATE_MM(CLK_MM_IMG_DL_ASYNC_TOP, "mm_imgdl_async", "mm_ck", 27), + GATE_MM(CLK_MM_DIG_DSI, "mm_dig_dsi_ck", "mm_ck", 28), + GATE_MM(CLK_MM_F26M_HRTWT, "mm_hrtwt", "f_f26m_ck", 29), +}; + +static const struct mtk_clk_desc mm_desc = { + .clks = mm_clks, + .num_clks = ARRAY_SIZE(mm_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_mm[] = { + { + .compatible = "mediatek,mt6765-mmsys", + .data = &mm_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_mm_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-mm", + .of_match_table = of_match_clk_mt6765_mm, + }, +}; + +builtin_platform_driver(clk_mt6765_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt6765-vcodec.c b/drivers/clk/mediatek/clk-mt6765-vcodec.c new file mode 100644 index 000000000..75d72b9b4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765-vcodec.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_SET0_LARB, "venc_set0_larb", "mm_ck", 0), + GATE_VENC(CLK_VENC_SET1_VENC, "venc_set1_venc", "mm_ck", 4), + GATE_VENC(CLK_VENC_SET2_JPGENC, "jpgenc", "mm_ck", 8), + GATE_VENC(CLK_VENC_SET3_VDEC, "venc_set3_vdec", "mm_ck", 12), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt6765_vcodec[] = { + { + .compatible = "mediatek,mt6765-vcodecsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6765_vcodec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6765-vcodec", + .of_match_table = of_match_clk_mt6765_vcodec, + }, +}; + +builtin_platform_driver(clk_mt6765_vcodec_drv); diff --git a/drivers/clk/mediatek/clk-mt6765.c b/drivers/clk/mediatek/clk-mt6765.c new file mode 100644 index 000000000..2c6a52ff5 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6765.c @@ -0,0 +1,880 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt6765-clk.h> + +/*fmeter div select 4*/ +#define _DIV4_ 1 + +static DEFINE_SPINLOCK(mt6765_clk_lock); + +/* Total 12 subsys */ +static void __iomem *cksys_base; +static void __iomem *apmixed_base; + +/* CKSYS */ +#define CLK_SCP_CFG_0 (cksys_base + 0x200) +#define CLK_SCP_CFG_1 (cksys_base + 0x204) + +/* CG */ +#define AP_PLL_CON3 (apmixed_base + 0x0C) +#define PLLON_CON0 (apmixed_base + 0x44) +#define PLLON_CON1 (apmixed_base + 0x48) + +/* clk cfg update */ +#define CLK_CFG_0 0x40 +#define CLK_CFG_0_SET 0x44 +#define CLK_CFG_0_CLR 0x48 +#define CLK_CFG_1 0x50 +#define CLK_CFG_1_SET 0x54 +#define CLK_CFG_1_CLR 0x58 +#define CLK_CFG_2 0x60 +#define CLK_CFG_2_SET 0x64 +#define CLK_CFG_2_CLR 0x68 +#define CLK_CFG_3 0x70 +#define CLK_CFG_3_SET 0x74 +#define CLK_CFG_3_CLR 0x78 +#define CLK_CFG_4 0x80 +#define CLK_CFG_4_SET 0x84 +#define CLK_CFG_4_CLR 0x88 +#define CLK_CFG_5 0x90 +#define CLK_CFG_5_SET 0x94 +#define CLK_CFG_5_CLR 0x98 +#define CLK_CFG_6 0xa0 +#define CLK_CFG_6_SET 0xa4 +#define CLK_CFG_6_CLR 0xa8 +#define CLK_CFG_7 0xb0 +#define CLK_CFG_7_SET 0xb4 +#define CLK_CFG_7_CLR 0xb8 +#define CLK_CFG_8 0xc0 +#define CLK_CFG_8_SET 0xc4 +#define CLK_CFG_8_CLR 0xc8 +#define CLK_CFG_9 0xd0 +#define CLK_CFG_9_SET 0xd4 +#define CLK_CFG_9_CLR 0xd8 +#define CLK_CFG_10 0xe0 +#define CLK_CFG_10_SET 0xe4 +#define CLK_CFG_10_CLR 0xe8 +#define CLK_CFG_UPDATE 0x004 + +static const struct mtk_fixed_clk fixed_clks[] = { + FIXED_CLK(CLK_TOP_F_FRTC, "f_frtc_ck", "clk32k", 32768), + FIXED_CLK(CLK_TOP_CLK26M, "clk_26m_ck", "clk26m", 26000000), + FIXED_CLK(CLK_TOP_DMPLL, "dmpll_ck", NULL, 466000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_SYSPLL, "syspll_ck", "mainpll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_USB20_192M, "usb20_192m_ck", "univpll", 2, 13), + FACTOR(CLK_TOP_USB20_192M_D4, "usb20_192m_d4", "usb20_192m_ck", 1, 4), + FACTOR(CLK_TOP_USB20_192M_D8, "usb20_192m_d8", "usb20_192m_ck", 1, 8), + FACTOR(CLK_TOP_USB20_192M_D16, + "usb20_192m_d16", "usb20_192m_ck", 1, 16), + FACTOR(CLK_TOP_USB20_192M_D32, + "usb20_192m_d32", "usb20_192m_ck", 1, 32), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_d3", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_d3", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_d3", 1, 8), + FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll_d3", 1, 32), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll_ck", 1, 2), + FACTOR(CLK_TOP_MPLL, "mpll_ck", "mpll", 1, 1), + FACTOR(CLK_TOP_DA_MPLL_104M_DIV, "mpll_104m_div", "mpll_ck", 1, 2), + FACTOR(CLK_TOP_DA_MPLL_52M_DIV, "mpll_52m_div", "mpll_ck", 1, 4), + FACTOR(CLK_TOP_MFGPLL, "mfgpll_ck", "mfgpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, 8), + FACTOR(CLK_TOP_ULPOSC1, "ulposc1_ck", "ulposc1", 1, 1), + FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1_ck", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1_ck", 1, 4), + FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1_ck", 1, 8), + FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1_ck", 1, 16), + FACTOR(CLK_TOP_ULPOSC1_D32, "ulposc1_d32", "ulposc1_ck", 1, 32), + FACTOR(CLK_TOP_F_F26M, "f_f26m_ck", "clk_26m_ck", 1, 1), + FACTOR(CLK_TOP_AXI, "axi_ck", "axi_sel", 1, 1), + FACTOR(CLK_TOP_MM, "mm_ck", "mm_sel", 1, 1), + FACTOR(CLK_TOP_SCP, "scp_ck", "scp_sel", 1, 1), + FACTOR(CLK_TOP_MFG, "mfg_ck", "mfg_sel", 1, 1), + FACTOR(CLK_TOP_F_FUART, "f_fuart_ck", "uart_sel", 1, 1), + FACTOR(CLK_TOP_SPI, "spi_ck", "spi_sel", 1, 1), + FACTOR(CLK_TOP_MSDC50_0, "msdc50_0_ck", "msdc50_0_sel", 1, 1), + FACTOR(CLK_TOP_MSDC30_1, "msdc30_1_ck", "msdc30_1_sel", 1, 1), + FACTOR(CLK_TOP_AUDIO, "audio_ck", "audio_sel", 1, 1), + FACTOR(CLK_TOP_AUD_1, "aud_1_ck", "aud_1_sel", 1, 1), + FACTOR(CLK_TOP_AUD_ENGEN1, "aud_engen1_ck", "aud_engen1_sel", 1, 1), + FACTOR(CLK_TOP_F_FDISP_PWM, "f_fdisp_pwm_ck", "disp_pwm_sel", 1, 1), + FACTOR(CLK_TOP_SSPM, "sspm_ck", "sspm_sel", 1, 1), + FACTOR(CLK_TOP_DXCC, "dxcc_ck", "dxcc_sel", 1, 1), + FACTOR(CLK_TOP_I2C, "i2c_ck", "i2c_sel", 1, 1), + FACTOR(CLK_TOP_F_FPWM, "f_fpwm_ck", "pwm_sel", 1, 1), + FACTOR(CLK_TOP_F_FSENINF, "f_fseninf_ck", "seninf_sel", 1, 1), + FACTOR(CLK_TOP_AES_FDE, "aes_fde_ck", "aes_fde_sel", 1, 1), + FACTOR(CLK_TOP_F_BIST2FPC, "f_bist2fpc_ck", "univpll2_d2", 1, 1), + FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL0, "arm_div_pll0", "syspll_d2", 1, 1), + FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL1, "arm_div_pll1", "syspll_ck", 1, 1), + FACTOR(CLK_TOP_ARMPLL_DIVIDER_PLL2, "arm_div_pll2", "univpll_d2", 1, 1), + FACTOR(CLK_TOP_DA_USB20_48M_DIV, + "usb20_48m_div", "usb20_192m_d4", 1, 1), + FACTOR(CLK_TOP_DA_UNIV_48M_DIV, "univ_48m_div", "usb20_192m_d4", 1, 1), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll_d7", + "syspll1_d4", + "syspll3_d2" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck", + "apll1_ck" +}; + +static const char * const mm_parents[] = { + "clk26m", + "mmpll_ck", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll1_d2", + "mmpll_d2" +}; + +static const char * const scp_parents[] = { + "clk26m", + "syspll4_d2", + "univpll2_d2", + "syspll1_d2", + "univpll1_d2", + "syspll_d3", + "univpll_d3" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll_ck", + "syspll_d3", + "univpll_d3" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d4", + "syspll1_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "usb20_192m_d8", + "univpll2_d8", + "usb20_192m_d4", + "univpll2_d32", + "usb20_192m_d16", + "usb20_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll3_d2", + "syspll4_d2", + "syspll2_d4" +}; + +static const char * const msdc5hclk_parents[] = { + "clk26m", + "syspll1_d2", + "univpll1_d4", + "syspll2_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "syspll2_d2", + "syspll4_d2", + "univpll1_d2", + "syspll1_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "msdcpll_d2", + "univpll2_d2", + "syspll2_d2", + "syspll1_d4", + "univpll1_d4", + "usb20_192m_d4", + "syspll2_d4" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll2_d4", + "ulposc1_d2", + "ulposc1_d8" +}; + +static const char * const sspm_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d3" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "syspll1_d2", + "syspll1_d4", + "syspll1_d8" +}; + +static const char * const usb_top_parents[] = { + "clk26m", + "univpll3_d4" +}; + +static const char * const spm_parents[] = { + "clk26m", + "syspll1_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll3_d4", + "univpll3_d2", + "syspll1_d8", + "syspll2_d8" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll3_d4", + "syspll1_d8" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +static const char * const aes_fde_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll_d3", + "univpll2_d2", + "univpll1_d2", + "syspll1_d2" +}; + +static const char * const ulposc_parents[] = { + "clk26m", + "ulposc1_d4", + "ulposc1_d8", + "ulposc1_d16", + "ulposc1_d32" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +#define INVALID_UPDATE_REG 0xFFFFFFFF +#define INVALID_UPDATE_SHIFT -1 +#define INVALID_MUX_GATE -1 + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, + 0, 2, 7, CLK_CFG_UPDATE, 0, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, + 8, 2, 15, CLK_CFG_UPDATE, 1, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, CLK_CFG_0, + CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 3, 23, + CLK_CFG_UPDATE, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, CLK_CFG_0, + CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31, + CLK_CFG_UPDATE, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, CLK_CFG_1, + CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7, + CLK_CFG_UPDATE, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, CLK_CFG_1, + CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 2, 15, + CLK_CFG_UPDATE, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel", + camtg_parents, CLK_CFG_1, CLK_CFG_1_SET, + CLK_CFG_1_CLR, 16, 3, 23, CLK_CFG_UPDATE, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG1_SEL, "camtg1_sel", camtg_parents, + CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, + 24, 3, 31, CLK_CFG_UPDATE, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2_SEL, "camtg2_sel", + camtg_parents, CLK_CFG_2, CLK_CFG_2_SET, + CLK_CFG_2_CLR, 0, 3, 7, CLK_CFG_UPDATE, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3_SEL, "camtg3_sel", camtg_parents, + CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, + 8, 3, 15, CLK_CFG_UPDATE, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 1, 23, + CLK_CFG_UPDATE, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, CLK_CFG_2, + CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 2, 31, + CLK_CFG_UPDATE, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK_SEL, "msdc5hclk", + msdc5hclk_parents, CLK_CFG_3, CLK_CFG_3_SET, + CLK_CFG_3_CLR, 0, 2, 7, CLK_CFG_UPDATE, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, CLK_CFG_3, CLK_CFG_3_SET, + CLK_CFG_3_CLR, 8, 3, 15, CLK_CFG_UPDATE, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, CLK_CFG_3, CLK_CFG_3_SET, + CLK_CFG_3_CLR, 16, 3, 23, CLK_CFG_UPDATE, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, + 24, 2, 31, CLK_CFG_UPDATE, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, CLK_CFG_4, CLK_CFG_4_SET, + CLK_CFG_4_CLR, 0, 2, 7, CLK_CFG_UPDATE, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, + CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, + 8, 1, 15, CLK_CFG_UPDATE, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", + aud_engen1_parents, CLK_CFG_4, CLK_CFG_4_SET, + CLK_CFG_4_CLR, 16, 2, 23, CLK_CFG_UPDATE, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel", + disp_pwm_parents, CLK_CFG_4, CLK_CFG_4_SET, + CLK_CFG_4_CLR, 24, 2, 31, CLK_CFG_UPDATE, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSPM_SEL, "sspm_sel", sspm_parents, + CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7, + CLK_CFG_UPDATE, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents, + CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 2, 15, + CLK_CFG_UPDATE, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_SEL, "usb_top_sel", + usb_top_parents, CLK_CFG_5, CLK_CFG_5_SET, + CLK_CFG_5_CLR, 16, 1, 23, CLK_CFG_UPDATE, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, CLK_CFG_5, + CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31, + CLK_CFG_UPDATE, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, CLK_CFG_6, + CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 3, 7, CLK_CFG_UPDATE, + 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, CLK_CFG_6, + CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 2, 15, CLK_CFG_UPDATE, + 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel", seninf_parents, + CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 2, 23, + CLK_CFG_UPDATE, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_FDE_SEL, "aes_fde_sel", + aes_fde_parents, CLK_CFG_6, CLK_CFG_6_SET, + CLK_CFG_6_CLR, 24, 3, 31, CLK_CFG_UPDATE, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRAP_ULPOSC_SEL, "ulposc_sel", + ulposc_parents, CLK_CFG_7, CLK_CFG_7_SET, + CLK_CFG_7_CLR, 0, 3, 7, CLK_CFG_UPDATE, 28, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", camtm_parents, + CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 8, 2, 15, + CLK_CFG_UPDATE, 29), +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x104, + .sta_ofs = 0x104, +}; + +static const struct mtk_gate_regs top2_cg_regs = { + .set_ofs = 0x320, + .clr_ofs = 0x320, + .sta_ofs = 0x320, +}; + +#define GATE_TOP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_TOP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_TOP2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_MD_32K, "md_32k", "f_frtc_ck", 8), + GATE_TOP0(CLK_TOP_MD_26M, "md_26m", "f_f26m_ck", 9), + GATE_TOP0(CLK_TOP_MD2_32K, "md2_32k", "f_frtc_ck", 10), + GATE_TOP0(CLK_TOP_MD2_26M, "md2_26m", "f_f26m_ck", 11), + /* TOP1 */ + GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL0_EN, + "arm_div_pll0_en", "arm_div_pll0", 3), + GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL1_EN, + "arm_div_pll1_en", "arm_div_pll1", 4), + GATE_TOP1(CLK_TOP_ARMPLL_DIVIDER_PLL2_EN, + "arm_div_pll2_en", "arm_div_pll2", 5), + GATE_TOP1(CLK_TOP_FMEM_OCC_DRC_EN, "drc_en", "univpll2_d2", 6), + GATE_TOP1(CLK_TOP_USB20_48M_EN, "usb20_48m_en", "usb20_48m_div", 8), + GATE_TOP1(CLK_TOP_UNIVPLL_48M_EN, "univpll_48m_en", "univ_48m_div", 9), + GATE_TOP1(CLK_TOP_F_UFS_MP_SAP_CFG_EN, "ufs_sap", "f_f26m_ck", 12), + GATE_TOP1(CLK_TOP_F_BIST2FPC_EN, "bist2fpc", "f_bist2fpc_ck", 16), + /* TOP2 */ + GATE_TOP2(CLK_TOP_APLL12_DIV0, "apll12_div0", "aud_1_ck", 2), + GATE_TOP2(CLK_TOP_APLL12_DIV1, "apll12_div1", "aud_1_ck", 3), + GATE_TOP2(CLK_TOP_APLL12_DIV2, "apll12_div2", "aud_1_ck", 4), + GATE_TOP2(CLK_TOP_APLL12_DIV3, "apll12_div3", "aud_1_ck", 5), +}; + +static const struct mtk_gate_regs ifr2_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs ifr3_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs ifr4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs ifr5_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +#define GATE_IFR2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ifr2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_IFR3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ifr3_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_IFR4(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ifr4_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_IFR5(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ifr5_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ifr_clks[] = { + /* INFRA_TOPAXI */ + /* INFRA PERI */ + /* INFRA mode 0 */ + GATE_IFR2(CLK_IFR_ICUSB, "ifr_icusb", "axi_ck", 8), + GATE_IFR2(CLK_IFR_GCE, "ifr_gce", "axi_ck", 9), + GATE_IFR2(CLK_IFR_THERM, "ifr_therm", "axi_ck", 10), + GATE_IFR2(CLK_IFR_I2C_AP, "ifr_i2c_ap", "i2c_ck", 11), + GATE_IFR2(CLK_IFR_I2C_CCU, "ifr_i2c_ccu", "i2c_ck", 12), + GATE_IFR2(CLK_IFR_I2C_SSPM, "ifr_i2c_sspm", "i2c_ck", 13), + GATE_IFR2(CLK_IFR_I2C_RSV, "ifr_i2c_rsv", "i2c_ck", 14), + GATE_IFR2(CLK_IFR_PWM_HCLK, "ifr_pwm_hclk", "axi_ck", 15), + GATE_IFR2(CLK_IFR_PWM1, "ifr_pwm1", "f_fpwm_ck", 16), + GATE_IFR2(CLK_IFR_PWM2, "ifr_pwm2", "f_fpwm_ck", 17), + GATE_IFR2(CLK_IFR_PWM3, "ifr_pwm3", "f_fpwm_ck", 18), + GATE_IFR2(CLK_IFR_PWM4, "ifr_pwm4", "f_fpwm_ck", 19), + GATE_IFR2(CLK_IFR_PWM5, "ifr_pwm5", "f_fpwm_ck", 20), + GATE_IFR2(CLK_IFR_PWM, "ifr_pwm", "f_fpwm_ck", 21), + GATE_IFR2(CLK_IFR_UART0, "ifr_uart0", "f_fuart_ck", 22), + GATE_IFR2(CLK_IFR_UART1, "ifr_uart1", "f_fuart_ck", 23), + GATE_IFR2(CLK_IFR_GCE_26M, "ifr_gce_26m", "f_f26m_ck", 27), + GATE_IFR2(CLK_IFR_CQ_DMA_FPC, "ifr_dma", "axi_ck", 28), + GATE_IFR2(CLK_IFR_BTIF, "ifr_btif", "axi_ck", 31), + /* INFRA mode 1 */ + GATE_IFR3(CLK_IFR_SPI0, "ifr_spi0", "spi_ck", 1), + GATE_IFR3(CLK_IFR_MSDC0, "ifr_msdc0", "msdc5hclk", 2), + GATE_IFR3(CLK_IFR_MSDC1, "ifr_msdc1", "axi_ck", 4), + GATE_IFR3(CLK_IFR_TRNG, "ifr_trng", "axi_ck", 9), + GATE_IFR3(CLK_IFR_AUXADC, "ifr_auxadc", "f_f26m_ck", 10), + GATE_IFR3(CLK_IFR_CCIF1_AP, "ifr_ccif1_ap", "axi_ck", 12), + GATE_IFR3(CLK_IFR_CCIF1_MD, "ifr_ccif1_md", "axi_ck", 13), + GATE_IFR3(CLK_IFR_AUXADC_MD, "ifr_auxadc_md", "f_f26m_ck", 14), + GATE_IFR3(CLK_IFR_AP_DMA, "ifr_ap_dma", "axi_ck", 18), + GATE_IFR3(CLK_IFR_DEVICE_APC, "ifr_dapc", "axi_ck", 20), + GATE_IFR3(CLK_IFR_CCIF_AP, "ifr_ccif_ap", "axi_ck", 23), + GATE_IFR3(CLK_IFR_AUDIO, "ifr_audio", "axi_ck", 25), + GATE_IFR3(CLK_IFR_CCIF_MD, "ifr_ccif_md", "axi_ck", 26), + /* INFRA mode 2 */ + GATE_IFR4(CLK_IFR_RG_PWM_FBCLK6, "ifr_pwmfb", "f_f26m_ck", 0), + GATE_IFR4(CLK_IFR_DISP_PWM, "ifr_disp_pwm", "f_fdisp_pwm_ck", 2), + GATE_IFR4(CLK_IFR_CLDMA_BCLK, "ifr_cldmabclk", "axi_ck", 3), + GATE_IFR4(CLK_IFR_AUDIO_26M_BCLK, "ifr_audio26m", "f_f26m_ck", 4), + GATE_IFR4(CLK_IFR_SPI1, "ifr_spi1", "spi_ck", 6), + GATE_IFR4(CLK_IFR_I2C4, "ifr_i2c4", "i2c_ck", 7), + GATE_IFR4(CLK_IFR_SPI2, "ifr_spi2", "spi_ck", 9), + GATE_IFR4(CLK_IFR_SPI3, "ifr_spi3", "spi_ck", 10), + GATE_IFR4(CLK_IFR_I2C5, "ifr_i2c5", "i2c_ck", 18), + GATE_IFR4(CLK_IFR_I2C5_ARBITER, "ifr_i2c5a", "i2c_ck", 19), + GATE_IFR4(CLK_IFR_I2C5_IMM, "ifr_i2c5_imm", "i2c_ck", 20), + GATE_IFR4(CLK_IFR_I2C1_ARBITER, "ifr_i2c1a", "i2c_ck", 21), + GATE_IFR4(CLK_IFR_I2C1_IMM, "ifr_i2c1_imm", "i2c_ck", 22), + GATE_IFR4(CLK_IFR_I2C2_ARBITER, "ifr_i2c2a", "i2c_ck", 23), + GATE_IFR4(CLK_IFR_I2C2_IMM, "ifr_i2c2_imm", "i2c_ck", 24), + GATE_IFR4(CLK_IFR_SPI4, "ifr_spi4", "spi_ck", 25), + GATE_IFR4(CLK_IFR_SPI5, "ifr_spi5", "spi_ck", 26), + GATE_IFR4(CLK_IFR_CQ_DMA, "ifr_cq_dma", "axi_ck", 27), + GATE_IFR4(CLK_IFR_FAES_FDE, "ifr_faes_fde_ck", "aes_fde_ck", 29), + /* INFRA mode 3 */ + GATE_IFR5(CLK_IFR_MSDC0_SELF, "ifr_msdc0sf", "msdc50_0_ck", 0), + GATE_IFR5(CLK_IFR_MSDC1_SELF, "ifr_msdc1sf", "msdc50_0_ck", 1), + GATE_IFR5(CLK_IFR_I2C6, "ifr_i2c6", "i2c_ck", 6), + GATE_IFR5(CLK_IFR_AP_MSDC0, "ifr_ap_msdc0", "msdc50_0_ck", 7), + GATE_IFR5(CLK_IFR_MD_MSDC0, "ifr_md_msdc0", "msdc50_0_ck", 8), + GATE_IFR5(CLK_IFR_MSDC0_SRC, "ifr_msdc0_clk", "msdc50_0_ck", 9), + GATE_IFR5(CLK_IFR_MSDC1_SRC, "ifr_msdc1_clk", "msdc30_1_ck", 10), + GATE_IFR5(CLK_IFR_MCU_PM_BCLK, "ifr_mcu_pm_bclk", "axi_ck", 17), + GATE_IFR5(CLK_IFR_CCIF2_AP, "ifr_ccif2_ap", "axi_ck", 18), + GATE_IFR5(CLK_IFR_CCIF2_MD, "ifr_ccif2_md", "axi_ck", 19), + GATE_IFR5(CLK_IFR_CCIF3_AP, "ifr_ccif3_ap", "axi_ck", 20), + GATE_IFR5(CLK_IFR_CCIF3_MD, "ifr_ccif3_md", "axi_ck", 21), +}; + +/* additional CCF control for mipi26M race condition(disp/camera) */ +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &apmixed_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate apmixed_clks[] = { + /* AUDIO0 */ + GATE_APMIXED(CLK_APMIXED_SSUSB26M, "apmixed_ssusb26m", "f_f26m_ck", + 4), + GATE_APMIXED(CLK_APMIXED_APPLL26M, "apmixed_appll26m", "f_f26m_ck", + 5), + GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", "f_f26m_ck", + 6), + GATE_APMIXED(CLK_APMIXED_MDPLLGP26M, "apmixed_mdpll26m", "f_f26m_ck", + 7), + GATE_APMIXED(CLK_APMIXED_MMSYS_F26M, "apmixed_mmsys26m", "f_f26m_ck", + 8), + GATE_APMIXED(CLK_APMIXED_UFS26M, "apmixed_ufs26m", "f_f26m_ck", + 9), + GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", "f_f26m_ck", + 11), + GATE_APMIXED(CLK_APMIXED_MEMPLL26M, "apmixed_mempll26m", "f_f26m_ck", + 13), + GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m", + "f_f26m_ck", 14), + GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", "f_f26m_ck", + 16), +}; + +#define MT6765_PLL_FMAX (3800UL * MHZ) +#define MT6765_PLL_FMIN (1500UL * MHZ) + +#define CON0_MT6765_RST_BAR BIT(23) + +#define PLL_INFO_NULL (0xFF) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pcwibits, _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg,\ + _tuner_en_bit, _pcw_reg, _pcw_shift, _div_table) {\ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT6765_RST_BAR, \ + .fmax = MT6765_PLL_FMAX, \ + .fmin = MT6765_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = _pcwibits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pcwibits, _pd_reg, _pd_shift, _tuner_reg, \ + _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _pcwbits, _pcwibits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift, NULL) \ + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x021C, 0x0228, 0, + PLL_AO, 22, 8, 0x0220, 24, 0, 0, 0, 0x0220, 0), + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x020C, 0x0218, 0, + PLL_AO, 22, 8, 0x0210, 24, 0, 0, 0, 0x0210, 0), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x022C, 0x0238, 0, + PLL_AO, 22, 8, 0x0230, 24, 0, 0, 0, 0x0230, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x023C, 0x0248, 0, + (HAVE_RST_BAR | PLL_AO), 22, 8, 0x0240, 24, 0, 0, 0, 0x0240, + 0), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x024C, 0x0258, 0, + 0, 22, 8, 0x0250, 24, 0, 0, 0, 0x0250, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x025C, 0x0268, 0, + 0, 22, 8, 0x0260, 24, 0, 0, 0, 0x0260, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x026C, 0x0278, 0, + HAVE_RST_BAR, 22, 8, 0x0270, 24, 0, 0, 0, 0x0270, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x027C, 0x0288, 0, + 0, 22, 8, 0x0280, 24, 0, 0, 0, 0x0280, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x028C, 0x029C, 0, + 0, 32, 8, 0x0290, 24, 0x0040, 0x000C, 0, 0x0294, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x02A0, 0x02AC, 0, + PLL_AO, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0), +}; + +static int clk_mt6765_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + apmixed_base = base; + /* MPLL, CCIPLL, MAINPLL set HW mode, TDCLKSQ, CLKSQ1 */ + writel(readl(AP_PLL_CON3) & 0xFFFFFFE1, AP_PLL_CON3); + writel(readl(PLLON_CON0) & 0x01041041, PLLON_CON0); + writel(readl(PLLON_CON1) & 0x01041041, PLLON_CON1); + + return r; +} + +static int clk_mt6765_top_probe(struct platform_device *pdev) +{ + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct clk_hw_onecell_data *clk_data; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), + clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt6765_clk_lock, clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + cksys_base = base; + /* [4]:no need */ + writel(readl(CLK_SCP_CFG_0) | 0x3EF, CLK_SCP_CFG_0); + /*[1,2,3,8]: no need*/ + writel(readl(CLK_SCP_CFG_1) | 0x1, CLK_SCP_CFG_1); + + return r; +} + +static int clk_mt6765_ifr_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(base)) { + pr_err("%s(): ioremap failed\n", __func__); + return PTR_ERR(base); + } + + clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks), + clk_data); + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt6765[] = { + { + .compatible = "mediatek,mt6765-apmixedsys", + .data = clk_mt6765_apmixed_probe, + }, { + .compatible = "mediatek,mt6765-topckgen", + .data = clk_mt6765_top_probe, + }, { + .compatible = "mediatek,mt6765-infracfg", + .data = clk_mt6765_ifr_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt6765_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *d); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt6765_drv = { + .probe = clk_mt6765_probe, + .driver = { + .name = "clk-mt6765", + .of_match_table = of_match_clk_mt6765, + }, +}; + +static int __init clk_mt6765_init(void) +{ + return platform_driver_register(&clk_mt6765_drv); +} + +arch_initcall(clk_mt6765_init); diff --git a/drivers/clk/mediatek/clk-mt6779-aud.c b/drivers/clk/mediatek/clk-mt6779-aud.c new file mode 100644 index 000000000..6e473ae1f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-aud.c @@ -0,0 +1,116 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6779-clk.h> + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x4, + .sta_ofs = 0x4, +}; + +#define GATE_AUDIO0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) +#define GATE_AUDIO1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUD_AFE, "aud_afe", "audio_sel", 2), + GATE_AUDIO0(CLK_AUD_22M, "aud_22m", "aud_eng1_sel", 8), + GATE_AUDIO0(CLK_AUD_24M, "aud_24m", "aud_eng2_sel", 9), + GATE_AUDIO0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", + "aud_eng2_sel", 18), + GATE_AUDIO0(CLK_AUD_APLL_TUNER, "aud_apll_tuner", + "aud_eng1_sel", 19), + GATE_AUDIO0(CLK_AUD_TDM, "aud_tdm", "aud_eng1_sel", 20), + GATE_AUDIO0(CLK_AUD_ADC, "aud_adc", "audio_sel", 24), + GATE_AUDIO0(CLK_AUD_DAC, "aud_dac", "audio_sel", 25), + GATE_AUDIO0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", + "audio_sel", 26), + GATE_AUDIO0(CLK_AUD_TML, "aud_tml", "audio_sel", 27), + GATE_AUDIO0(CLK_AUD_NLE, "aud_nle", "audio_sel", 28), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUD_I2S1_BCLK_SW, "aud_i2s1_bclk", + "audio_sel", 4), + GATE_AUDIO1(CLK_AUD_I2S2_BCLK_SW, "aud_i2s2_bclk", + "audio_sel", 5), + GATE_AUDIO1(CLK_AUD_I2S3_BCLK_SW, "aud_i2s3_bclk", + "audio_sel", 6), + GATE_AUDIO1(CLK_AUD_I2S4_BCLK_SW, "aud_i2s4_bclk", + "audio_sel", 7), + GATE_AUDIO1(CLK_AUD_I2S5_BCLK_SW, "aud_i2s5_bclk", + "audio_sel", 8), + GATE_AUDIO1(CLK_AUD_CONN_I2S_ASRC, "aud_conn_i2s", + "audio_sel", 12), + GATE_AUDIO1(CLK_AUD_GENERAL1_ASRC, "aud_general1", + "audio_sel", 13), + GATE_AUDIO1(CLK_AUD_GENERAL2_ASRC, "aud_general2", + "audio_sel", 14), + GATE_AUDIO1(CLK_AUD_DAC_HIRES, "aud_dac_hires", + "audio_h_sel", 15), + GATE_AUDIO1(CLK_AUD_ADC_HIRES, "aud_adc_hires", + "audio_h_sel", 16), + GATE_AUDIO1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", + "audio_h_sel", 17), + GATE_AUDIO1(CLK_AUD_PDN_ADDA6_ADC, "aud_pdn_adda6_adc", + "audio_sel", 20), + GATE_AUDIO1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", + "audio_h_sel", + 21), + GATE_AUDIO1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "audio_sel", + 28), + GATE_AUDIO1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", + "audio_sel", 29), + GATE_AUDIO1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", + "audio_sel", 30), + GATE_AUDIO1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", + "audio_h_sel", 31), +}; + +static const struct mtk_clk_desc audio_desc = { + .clks = audio_clks, + .num_clks = ARRAY_SIZE(audio_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_aud[] = { + { + .compatible = "mediatek,mt6779-audio", + .data = &audio_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_aud_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-aud", + .of_match_table = of_match_clk_mt6779_aud, + }, +}; + +module_platform_driver(clk_mt6779_aud_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-cam.c b/drivers/clk/mediatek/clk-mt6779-cam.c new file mode 100644 index 000000000..7be3db90f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-cam.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6779-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB10, "camsys_larb10", "cam_sel", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "camsys_dfp_vad", "cam_sel", 1), + GATE_CAM(CLK_CAM_LARB11, "camsys_larb11", "cam_sel", 2), + GATE_CAM(CLK_CAM_LARB9, "camsys_larb9", "cam_sel", 3), + GATE_CAM(CLK_CAM_CAM, "camsys_cam", "cam_sel", 6), + GATE_CAM(CLK_CAM_CAMTG, "camsys_camtg", "cam_sel", 7), + GATE_CAM(CLK_CAM_SENINF, "camsys_seninf", "cam_sel", 8), + GATE_CAM(CLK_CAM_CAMSV0, "camsys_camsv0", "cam_sel", 9), + GATE_CAM(CLK_CAM_CAMSV1, "camsys_camsv1", "cam_sel", 10), + GATE_CAM(CLK_CAM_CAMSV2, "camsys_camsv2", "cam_sel", 11), + GATE_CAM(CLK_CAM_CAMSV3, "camsys_camsv3", "cam_sel", 12), + GATE_CAM(CLK_CAM_CCU, "camsys_ccu", "cam_sel", 13), + GATE_CAM(CLK_CAM_FAKE_ENG, "camsys_fake_eng", "cam_sel", 14), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_cam[] = { + { + .compatible = "mediatek,mt6779-camsys", + .data = &cam_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-cam", + .of_match_table = of_match_clk_mt6779_cam, + }, +}; + +module_platform_driver(clk_mt6779_cam_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-img.c b/drivers/clk/mediatek/clk-mt6779-img.c new file mode 100644 index 000000000..9bc51fc82 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-img.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6779-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_LARB5, "imgsys_larb5", "img_sel", 0), + GATE_IMG(CLK_IMG_LARB6, "imgsys_larb6", "img_sel", 1), + GATE_IMG(CLK_IMG_DIP, "imgsys_dip", "img_sel", 2), + GATE_IMG(CLK_IMG_MFB, "imgsys_mfb", "img_sel", 6), + GATE_IMG(CLK_IMG_WPE_A, "imgsys_wpe_a", "img_sel", 7), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_img[] = { + { + .compatible = "mediatek,mt6779-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-img", + .of_match_table = of_match_clk_mt6779_img, + }, +}; + +module_platform_driver(clk_mt6779_img_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-ipe.c b/drivers/clk/mediatek/clk-mt6779-ipe.c new file mode 100644 index 000000000..92e9d1ade --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-ipe.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6779-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs ipe_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_IPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipe_clks[] = { + GATE_IPE(CLK_IPE_LARB7, "ipe_larb7", "ipe_sel", 0), + GATE_IPE(CLK_IPE_LARB8, "ipe_larb8", "ipe_sel", 1), + GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "ipe_sel", 2), + GATE_IPE(CLK_IPE_FD, "ipe_fd", "ipe_sel", 3), + GATE_IPE(CLK_IPE_FE, "ipe_fe", "ipe_sel", 4), + GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "ipe_sel", 5), + GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "ipe_sel", 6), +}; + +static const struct mtk_clk_desc ipe_desc = { + .clks = ipe_clks, + .num_clks = ARRAY_SIZE(ipe_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_ipe[] = { + { + .compatible = "mediatek,mt6779-ipesys", + .data = &ipe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_ipe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-ipe", + .of_match_table = of_match_clk_mt6779_ipe, + }, +}; + +module_platform_driver(clk_mt6779_ipe_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-mfg.c b/drivers/clk/mediatek/clk-mt6779-mfg.c new file mode 100644 index 000000000..efc793a19 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-mfg.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6779-clk.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFGCFG_BG3D, "mfg_bg3d", "mfg_sel", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_mfg[] = { + { + .compatible = "mediatek,mt6779-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-mfg", + .of_match_table = of_match_clk_mt6779_mfg, + }, +}; + +module_platform_driver(clk_mt6779_mfg_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-mm.c b/drivers/clk/mediatek/clk-mt6779-mm.c new file mode 100644 index 000000000..eda8cbee3 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-mm.c @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6779-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_SMI_LARB1, "mm_smi_larb1", "mm_sel", 2), + GATE_MM0(CLK_MM_GALS_COMM0, "mm_gals_comm0", "mm_sel", 3), + GATE_MM0(CLK_MM_GALS_COMM1, "mm_gals_comm1", "mm_sel", 4), + GATE_MM0(CLK_MM_GALS_CCU2MM, "mm_gals_ccu2mm", "mm_sel", 5), + GATE_MM0(CLK_MM_GALS_IPU12MM, "mm_gals_ipu12mm", "mm_sel", 6), + GATE_MM0(CLK_MM_GALS_IMG2MM, "mm_gals_img2mm", "mm_sel", 7), + GATE_MM0(CLK_MM_GALS_CAM2MM, "mm_gals_cam2mm", "mm_sel", 8), + GATE_MM0(CLK_MM_GALS_IPU2MM, "mm_gals_ipu2mm", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_DL_TXCK, "mm_mdp_dl_txck", "mm_sel", 10), + GATE_MM0(CLK_MM_IPU_DL_TXCK, "mm_ipu_dl_txck", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 13), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 14), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 15), + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 16), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 17), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 18), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 29), + GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 30), + GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DSI0_MM_CK, "mm_dsi0_mmck", "mm_sel", 0), + GATE_MM1(CLK_MM_DSI0_IF_CK, "mm_dsi0_ifck", "mm_sel", 1), + GATE_MM1(CLK_MM_DPI_MM_CK, "mm_dpi_mmck", "mm_sel", 2), + GATE_MM1(CLK_MM_DPI_IF_CK, "mm_dpi_ifck", "dpi0_sel", 3), + GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 4), + GATE_MM1(CLK_MM_MDP_DL_RX_CK, "mm_mdp_dl_rxck", "mm_sel", 5), + GATE_MM1(CLK_MM_IPU_DL_RX_CK, "mm_ipu_dl_rxck", "mm_sel", 6), + GATE_MM1(CLK_MM_26M, "mm_26m", "f_f26m_ck", 7), + GATE_MM1(CLK_MM_MM_R2Y, "mm_mmsys_r2y", "mm_sel", 8), + GATE_MM1(CLK_MM_DISP_RSZ, "mm_disp_rsz", "mm_sel", 9), + GATE_MM1(CLK_MM_MDP_AAL, "mm_mdp_aal", "mm_sel", 10), + GATE_MM1(CLK_MM_MDP_HDR, "mm_mdp_hdr", "mm_sel", 11), + GATE_MM1(CLK_MM_DBI_MM_CK, "mm_dbi_mmck", "mm_sel", 12), + GATE_MM1(CLK_MM_DBI_IF_CK, "mm_dbi_ifck", "dpi0_sel", 13), + GATE_MM1(CLK_MM_DISP_POSTMASK0, "mm_disp_pm0", "mm_sel", 14), + GATE_MM1(CLK_MM_DISP_HRT_BW, "mm_disp_hrt_bw", "mm_sel", 15), + GATE_MM1(CLK_MM_DISP_OVL_FBDC, "mm_disp_ovl_fbdc", "mm_sel", 16), +}; + +static int clk_mt6779_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static struct platform_driver clk_mt6779_mm_drv = { + .probe = clk_mt6779_mm_probe, + .driver = { + .name = "clk-mt6779-mm", + }, +}; + +module_platform_driver(clk_mt6779_mm_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-vdec.c b/drivers/clk/mediatek/clk-mt6779-vdec.c new file mode 100644 index 000000000..3209a6518 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-vdec.c @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6779-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +#define GATE_VDEC0_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) +#define GATE_VDEC1_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0_I(CLK_VDEC_VDEC, "vdec_cken", "vdec_sel", 0), + /* VDEC1 */ + GATE_VDEC1_I(CLK_VDEC_LARB1, "vdec_larb1_cken", "vdec_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_vdec[] = { + { + .compatible = "mediatek,mt6779-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-vdec", + .of_match_table = of_match_clk_mt6779_vdec, + }, +}; + +module_platform_driver(clk_mt6779_vdec_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779-venc.c b/drivers/clk/mediatek/clk-mt6779-venc.c new file mode 100644 index 000000000..c25035c0f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779-venc.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6779-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_VENC_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC_I(CLK_VENC_GCON_LARB, "venc_larb", "venc_sel", 0), + GATE_VENC_I(CLK_VENC_GCON_VENC, "venc_venc", "venc_sel", 4), + GATE_VENC_I(CLK_VENC_GCON_JPGENC, "venc_jpgenc", "venc_sel", 8), + GATE_VENC_I(CLK_VENC_GCON_GALS, "venc_gals", "venc_sel", 28), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt6779_venc[] = { + { + .compatible = "mediatek,mt6779-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6779_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6779-venc", + .of_match_table = of_match_clk_mt6779_venc, + }, +}; + +module_platform_driver(clk_mt6779_venc_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6779.c b/drivers/clk/mediatek/clk-mt6779.c new file mode 100644 index 000000000..39dadc954 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6779.c @@ -0,0 +1,1323 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: Wendell Lin <wendell.lin@mediatek.com> + */ + +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt6779-clk.h> + +static DEFINE_SPINLOCK(mt6779_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_CLK26M, "f_f26m_ck", "clk26m", 26000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1, 2), + FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_MAINPLL_CK, "mainpll_ck", "mainpll", 1, 1), + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll_ck", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D2, "mainpll_d2_d2", "mainpll_d2", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D4, "mainpll_d2_d4", "mainpll_d2", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D2_D8, "mainpll_d2_d8", "mainpll_d2", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D2_D16, "mainpll_d2_d16", "mainpll_d2", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D3_D2, "mainpll_d3_d2", "mainpll_d3", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D3_D4, "mainpll_d3_d4", "mainpll_d3", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D3_D8, "mainpll_d3_d8", "mainpll_d3", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_CK, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D2_D8, "univpll_d2_d8", "univpll_d2", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3_D16, "univpll_d3_d16", "univpll_d3", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVP_192M_CK, "univpll_192m_ck", "univ2pll", 1, 13), + FACTOR(CLK_TOP_UNIVP_192M_D2, "univpll_192m_d2", "univpll_192m_ck", + 1, 2), + FACTOR(CLK_TOP_UNIVP_192M_D4, "univpll_192m_d4", "univpll_192m_ck", + 1, 4), + FACTOR(CLK_TOP_UNIVP_192M_D8, "univpll_192m_d8", "univpll_192m_ck", + 1, 8), + FACTOR(CLK_TOP_UNIVP_192M_D16, "univpll_192m_d16", "univpll_192m_ck", + 1, 16), + FACTOR(CLK_TOP_UNIVP_192M_D32, "univpll_192m_d32", "univpll_192m_ck", + 1, 32), + FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8), + FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8), + FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16), + FACTOR(CLK_TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, 2), + FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1, 4), + FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, 2), + FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1, 4), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6), + FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1), + FACTOR(CLK_TOP_ADSPPLL_CK, "adsppll_ck", "adsppll", 1, 1), + FACTOR(CLK_TOP_ADSPPLL_D4, "adsppll_d4", "adsppll", 1, 4), + FACTOR(CLK_TOP_ADSPPLL_D5, "adsppll_d5", "adsppll", 1, 5), + FACTOR(CLK_TOP_ADSPPLL_D6, "adsppll_d6", "adsppll", 1, 6), + FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8), + FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, 16), + FACTOR(CLK_TOP_AD_OSC_CK, "ad_osc_ck", "osc", 1, 1), + FACTOR(CLK_TOP_OSC_D2, "osc_d2", "osc", 1, 2), + FACTOR(CLK_TOP_OSC_D4, "osc_d4", "osc", 1, 4), + FACTOR(CLK_TOP_OSC_D8, "osc_d8", "osc", 1, 8), + FACTOR(CLK_TOP_OSC_D10, "osc_d10", "osc", 1, 10), + FACTOR(CLK_TOP_OSC_D16, "osc_d16", "osc", 1, 16), + FACTOR(CLK_TOP_AD_OSC2_CK, "ad_osc2_ck", "osc2", 1, 1), + FACTOR(CLK_TOP_OSC2_D2, "osc2_d2", "osc2", 1, 2), + FACTOR(CLK_TOP_OSC2_D3, "osc2_d3", "osc2", 1, 3), + FACTOR(CLK_TOP_TVDPLL_MAINPLL_D2_CK, "tvdpll_mainpll_d2_ck", + "tvdpll", 1, 1), + FACTOR(CLK_TOP_FMEM_466M_CK, "fmem_466m_ck", "fmem", 1, 1), +}; + +static const char * const axi_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d7", + "osc_d4" +}; + +static const char * const mm_parents[] = { + "clk26m", + "tvdpll_mainpll_d2_ck", + "mmpll_d7", + "mmpll_d5_d2", + "mainpll_d2_d2", + "mainpll_d3_d2" +}; + +static const char * const scp_parents[] = { + "clk26m", + "univpll_d2_d8", + "mainpll_d2_d4", + "mainpll_d3", + "univpll_d3", + "ad_osc2_ck", + "osc2_d2", + "osc2_d3" +}; + +static const char * const img_parents[] = { + "clk26m", + "mainpll_d2", + "mainpll_d2", + "univpll_d3", + "mainpll_d3", + "mmpll_d5_d2", + "tvdpll_mainpll_d2_ck", + "mainpll_d5" +}; + +static const char * const ipe_parents[] = { + "clk26m", + "mainpll_d2", + "mmpll_d7", + "univpll_d3", + "mainpll_d3", + "mmpll_d5_d2", + "mainpll_d2_d2", + "mainpll_d5" +}; + +static const char * const dpe_parents[] = { + "clk26m", + "mainpll_d2", + "mmpll_d7", + "univpll_d3", + "mainpll_d3", + "mmpll_d5_d2", + "mainpll_d2_d2", + "mainpll_d5" +}; + +static const char * const cam_parents[] = { + "clk26m", + "mainpll_d2", + "mmpll_d6", + "mainpll_d3", + "mmpll_d7", + "univpll_d3", + "mmpll_d5_d2", + "adsppll_d5", + "tvdpll_mainpll_d2_ck", + "univpll_d3_d2" +}; + +static const char * const ccu_parents[] = { + "clk26m", + "mainpll_d2", + "mmpll_d6", + "mainpll_d3", + "mmpll_d7", + "univpll_d3", + "mmpll_d5_d2", + "mainpll_d2_d2", + "adsppll_d5", + "univpll_d3_d2" +}; + +static const char * const dsp_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll_d7", + "mmpll_d6", + "adsppll_d5", + "tvdpll_ck", + "tvdpll_mainpll_d2_ck", + "univpll_d2", + "adsppll_d4" +}; + +static const char * const dsp1_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll_d7", + "mmpll_d6", + "adsppll_d5", + "tvdpll_ck", + "tvdpll_mainpll_d2_ck", + "univpll_d2", + "adsppll_d4" +}; + +static const char * const dsp2_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll_d7", + "mmpll_d6", + "adsppll_d5", + "tvdpll_ck", + "tvdpll_mainpll_d2_ck", + "univpll_d2", + "adsppll_d4" +}; + +static const char * const dsp3_parents[] = { + "clk26m", + "univpll_d3_d8", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll_d7", + "mmpll_d6", + "mainpll_d2", + "tvdpll_ck", + "tvdpll_mainpll_d2_ck", + "univpll_d2", + "adsppll_d4", + "mmpll_d4" +}; + +static const char * const ipu_if_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll_d7", + "mmpll_d6", + "adsppll_d5", + "tvdpll_ck", + "tvdpll_mainpll_d2_ck", + "univpll_d2", + "adsppll_d4" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll_ck", + "univpll_d3", + "mainpll_d5" +}; + +static const char * const f52m_mfg_parents[] = { + "clk26m", + "univpll_d3_d2", + "univpll_d3_d4", + "univpll_d3_d8" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const camtg2_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const camtg3_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const camtg4_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d3_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "mainpll_d5_d2", + "mainpll_d3_d4", + "msdcpll_d4" +}; + +static const char * const msdc50_hclk_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d3_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll_d2_d4", + "mainpll_d3_d2", + "univpll_d2_d2" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll_d3_d2", + "mainpll_d3_d2", + "mainpll_d7", + "msdcpll_d2" +}; + +static const char * const audio_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d7_d4", + "mainpll_d2_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d7_d2" +}; + +static const char * const fpwrap_ulposc_parents[] = { + "osc_d10", + "clk26m", + "osc_d4", + "osc_d8", + "osc_d16" +}; + +static const char * const atb_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d5" +}; + +static const char * const sspm_parents[] = { + "clk26m", + "univpll_d2_d4", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3" +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const scam_parents[] = { + "clk26m", + "mainpll_d5_d2" +}; + +static const char * const disppwm_parents[] = { + "clk26m", + "univpll_d3_d4", + "osc_d2", + "osc_d4", + "osc_d16" +}; + +static const char * const usb_top_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + +static const char * const ssusb_top_xhci_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + +static const char * const spm_parents[] = { + "clk26m", + "osc_d8", + "mainpll_d2_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "mainpll_d2_d8", + "univpll_d5_d2" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d7", + "univpll_d3_d2", + "univpll_d2_d2", + "mainpll_d3", + "mmpll_d4_d2", + "mmpll_d7", + "mmpll_d6" +}; + +static const char * const seninf1_parents[] = { + "clk26m", + "univpll_d7", + "univpll_d3_d2", + "univpll_d2_d2", + "mainpll_d3", + "mmpll_d4_d2", + "mmpll_d7", + "mmpll_d6" +}; + +static const char * const seninf2_parents[] = { + "clk26m", + "univpll_d7", + "univpll_d3_d2", + "univpll_d2_d2", + "mainpll_d3", + "mmpll_d4_d2", + "mmpll_d7", + "mmpll_d6" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d2_d4", + "mainpll_d2_d8" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const faes_ufsfde_parents[] = { + "clk26m", + "mainpll_d2", + "mainpll_d2_d2", + "mainpll_d3", + "mainpll_d2_d4", + "univpll_d3" +}; + +static const char * const fufs_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d2_d8", + "mainpll_d2_d16" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck" +}; + +static const char * const adsp_parents[] = { + "clk26m", + "mainpll_d3", + "univpll_d2_d4", + "univpll_d2", + "mmpll_d4", + "adsppll_d4", + "adsppll_d6" +}; + +static const char * const dpmaif_parents[] = { + "clk26m", + "univpll_d2_d4", + "mainpll_d3", + "mainpll_d2_d2", + "univpll_d2_d2", + "univpll_d3" +}; + +static const char * const venc_parents[] = { + "clk26m", + "mmpll_d7", + "mainpll_d3", + "univpll_d2_d2", + "mainpll_d2_d2", + "univpll_d3", + "mmpll_d6", + "mainpll_d5", + "mainpll_d3_d2", + "mmpll_d4_d2", + "univpll_d2_d4", + "mmpll_d5", + "univpll_192m_d2" + +}; + +static const char * const vdec_parents[] = { + "clk26m", + "univpll_d2_d4", + "mainpll_d3", + "univpll_d2_d2", + "mainpll_d2_d2", + "univpll_d3", + "univpll_d5", + "univpll_d5_d2", + "mainpll_d2", + "univpll_d2", + "univpll_192m_d2" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll_d7", + "univpll_d3_d2", + "univpll_d2_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll_d2_d8" +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "univpll_d7", + "apll1_ck", + "apll2_ck" +}; + +static const char * const camtg5_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +/* + * CRITICAL CLOCK: + * axi_sel is the main bus clock of whole SOC. + * spm_sel is the clock of the always-on co-processor. + * sspm_sel is the clock of the always-on co-processor. + */ +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "axi_sel", axi_parents, + 0x20, 0x24, 0x28, 0, 2, 7, + 0x004, 0, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MM, "mm_sel", mm_parents, + 0x20, 0x24, 0x28, 8, 3, 15, 0x004, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP, "scp_sel", scp_parents, + 0x20, 0x24, 0x28, 16, 3, 23, 0x004, 2), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG, "img_sel", img_parents, + 0x30, 0x34, 0x38, 0, 3, 7, 0x004, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE, "ipe_sel", ipe_parents, + 0x30, 0x34, 0x38, 8, 3, 15, 0x004, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPE, "dpe_sel", dpe_parents, + 0x30, 0x34, 0x38, 16, 3, 23, 0x004, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM, "cam_sel", cam_parents, + 0x30, 0x34, 0x38, 24, 4, 31, 0x004, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CCU, "ccu_sel", ccu_parents, + 0x40, 0x44, 0x48, 0, 4, 7, 0x004, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP, "dsp_sel", dsp_parents, + 0x40, 0x44, 0x48, 8, 4, 15, 0x004, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP1, "dsp1_sel", dsp1_parents, + 0x40, 0x44, 0x48, 16, 4, 23, 0x004, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP2, "dsp2_sel", dsp2_parents, + 0x40, 0x44, 0x48, 24, 4, 31, 0x004, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP3, "dsp3_sel", dsp3_parents, + 0x50, 0x54, 0x58, 0, 4, 7, 0x004, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPU_IF, "ipu_if_sel", ipu_if_parents, + 0x50, 0x54, 0x58, 8, 4, 15, 0x004, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG, "mfg_sel", mfg_parents, + 0x50, 0x54, 0x58, 16, 2, 23, 0x004, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_F52M_MFG, "f52m_mfg_sel", + f52m_mfg_parents, 0x50, 0x54, 0x58, + 24, 2, 31, 0x004, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "camtg_sel", camtg_parents, + 0x60, 0x64, 0x68, 0, 3, 7, 0x004, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2, "camtg2_sel", camtg2_parents, + 0x60, 0x64, 0x68, 8, 3, 15, 0x004, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3, "camtg3_sel", camtg3_parents, + 0x60, 0x64, 0x68, 16, 3, 23, 0x004, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4, "camtg4_sel", camtg4_parents, + 0x60, 0x64, 0x68, 24, 3, 31, 0x004, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART, "uart_sel", uart_parents, + 0x70, 0x74, 0x78, 0, 1, 7, 0x004, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "spi_sel", spi_parents, + 0x70, 0x74, 0x78, 8, 2, 15, 0x004, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "msdc50_hclk_sel", + msdc50_hclk_parents, 0x70, 0x74, 0x78, + 16, 2, 23, 0x004, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "msdc50_0_sel", + msdc50_0_parents, 0x70, 0x74, 0x78, + 24, 3, 31, 0x004, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "msdc30_1_sel", + msdc30_1_parents, 0x80, 0x84, 0x88, + 0, 3, 7, 0x004, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD, "audio_sel", audio_parents, + 0x80, 0x84, 0x88, 8, 2, 15, 0x004, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "aud_intbus_sel", + aud_intbus_parents, 0x80, 0x84, 0x88, + 16, 2, 23, 0x004, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_FPWRAP_ULPOSC, "fpwrap_ulposc_sel", + fpwrap_ulposc_parents, 0x80, 0x84, 0x88, + 24, 3, 31, 0x004, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB, "atb_sel", atb_parents, + 0x90, 0x94, 0x98, 0, 2, 7, 0x004, 28), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "sspm_sel", sspm_parents, + 0x90, 0x94, 0x98, 8, 3, 15, + 0x004, 29, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0, "dpi0_sel", dpi0_parents, + 0x90, 0x94, 0x98, 16, 3, 23, 0x004, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM, "scam_sel", scam_parents, + 0x90, 0x94, 0x98, 24, 1, 31, 0x004, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM, "disppwm_sel", + disppwm_parents, 0xa0, 0xa4, 0xa8, + 0, 3, 7, 0x008, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP, "usb_top_sel", + usb_top_parents, 0xa0, 0xa4, 0xa8, + 8, 2, 15, 0x008, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_TOP_XHCI, "ssusb_top_xhci_sel", + ssusb_top_xhci_parents, 0xa0, 0xa4, 0xa8, + 16, 2, 23, 0x008, 3), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "spm_sel", spm_parents, + 0xa0, 0xa4, 0xa8, 24, 2, 31, + 0x008, 4, CLK_IS_CRITICAL), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "i2c_sel", i2c_parents, + 0xb0, 0xb4, 0xb8, 0, 2, 7, 0x008, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF, "seninf_sel", seninf_parents, + 0xb0, 0xb4, 0xb8, 8, 2, 15, 0x008, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1, "seninf1_sel", + seninf1_parents, 0xb0, 0xb4, 0xb8, + 16, 2, 23, 0x008, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2, "seninf2_sel", + seninf2_parents, 0xb0, 0xb4, 0xb8, + 24, 2, 31, 0x008, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "dxcc_sel", dxcc_parents, + 0xc0, 0xc4, 0xc8, 0, 2, 7, 0x008, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENG1, "aud_eng1_sel", + aud_engen1_parents, 0xc0, 0xc4, 0xc8, + 8, 2, 15, 0x008, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENG2, "aud_eng2_sel", + aud_engen2_parents, 0xc0, 0xc4, 0xc8, + 16, 2, 23, 0x008, 11), + MUX_GATE_CLR_SET_UPD(CLK_TOP_FAES_UFSFDE, "faes_ufsfde_sel", + faes_ufsfde_parents, 0xc0, 0xc4, 0xc8, + 24, 3, 31, + 0x008, 12), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_FUFS, "fufs_sel", fufs_parents, + 0xd0, 0xd4, 0xd8, 0, 2, 7, 0x008, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1, "aud_1_sel", aud_1_parents, + 0xd0, 0xd4, 0xd8, 8, 1, 15, 0x008, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2, "aud_2_sel", aud_2_parents, + 0xd0, 0xd4, 0xd8, 16, 1, 23, 0x008, 15), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP, "adsp_sel", adsp_parents, + 0xd0, 0xd4, 0xd8, 24, 3, 31, 0x008, 16), + /* CLK_CFG_12 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF, "dpmaif_sel", dpmaif_parents, + 0xe0, 0xe4, 0xe8, 0, 3, 7, 0x008, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC, "venc_sel", venc_parents, + 0xe0, 0xe4, 0xe8, 8, 4, 15, 0x008, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC, "vdec_sel", vdec_parents, + 0xe0, 0xe4, 0xe8, 16, 4, 23, 0x008, 19), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM, "camtm_sel", camtm_parents, + 0xe0, 0xe4, 0xe8, 24, 2, 31, 0x004, 20), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "pwm_sel", pwm_parents, + 0xf0, 0xf4, 0xf8, 0, 1, 7, 0x008, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_H, "audio_h_sel", + audio_h_parents, 0xf0, 0xf4, 0xf8, + 8, 2, 15, 0x008, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5, "camtg5_sel", camtg5_parents, + 0xf0, 0xf4, 0xf8, 24, 3, 31, 0x008, 24), +}; + +static const char * const i2s0_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const i2s1_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const i2s2_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const i2s3_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const i2s4_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const i2s5_m_ck_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const struct mtk_composite top_aud_muxes[] = { + MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, + 0x320, 8, 1), + MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, + 0x320, 9, 1), + MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, + 0x320, 10, 1), + MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, + 0x320, 11, 1), + MUX(CLK_TOP_I2S4_M_SEL, "i2s4_m_ck_sel", i2s4_m_ck_parents, + 0x320, 12, 1), + MUX(CLK_TOP_I2S5_M_SEL, "i2s5_m_ck_sel", i2s5_m_ck_parents, + 0x328, 20, 1), +}; + +static struct mtk_composite top_aud_divs[] = { + DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "i2s0_m_ck_sel", + 0x320, 2, 0x324, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "i2s1_m_ck_sel", + 0x320, 3, 0x324, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "i2s2_m_ck_sel", + 0x320, 4, 0x324, 8, 16), + DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "i2s3_m_ck_sel", + 0x320, 5, 0x324, 8, 24), + DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "i2s4_m_ck_sel", + 0x320, 6, 0x328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIVB, "apll12_divb", "apll12_div4", + 0x320, 7, 0x328, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV5, "apll12_div5", "i2s5_m_ck_sel", + 0x328, 16, 0x328, 4, 28), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) +#define GATE_INFRA3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", + "axi_sel", 0), + GATE_INFRA0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", + "axi_sel", 1), + GATE_INFRA0(CLK_INFRA_PMIC_MD, "infra_pmic_md", + "axi_sel", 2), + GATE_INFRA0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", + "axi_sel", 3), + GATE_INFRA0(CLK_INFRA_SCPSYS, "infra_scp", + "axi_sel", 4), + GATE_INFRA0(CLK_INFRA_SEJ, "infra_sej", + "f_f26m_ck", 5), + GATE_INFRA0(CLK_INFRA_APXGPT, "infra_apxgpt", + "axi_sel", 6), + GATE_INFRA0(CLK_INFRA_ICUSB, "infra_icusb", + "axi_sel", 8), + GATE_INFRA0(CLK_INFRA_GCE, "infra_gce", + "axi_sel", 9), + GATE_INFRA0(CLK_INFRA_THERM, "infra_therm", + "axi_sel", 10), + GATE_INFRA0(CLK_INFRA_I2C0, "infra_i2c0", + "i2c_sel", 11), + GATE_INFRA0(CLK_INFRA_I2C1, "infra_i2c1", + "i2c_sel", 12), + GATE_INFRA0(CLK_INFRA_I2C2, "infra_i2c2", + "i2c_sel", 13), + GATE_INFRA0(CLK_INFRA_I2C3, "infra_i2c3", + "i2c_sel", 14), + GATE_INFRA0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", + "pwm_sel", 15), + GATE_INFRA0(CLK_INFRA_PWM1, "infra_pwm1", + "pwm_sel", 16), + GATE_INFRA0(CLK_INFRA_PWM2, "infra_pwm2", + "pwm_sel", 17), + GATE_INFRA0(CLK_INFRA_PWM3, "infra_pwm3", + "pwm_sel", 18), + GATE_INFRA0(CLK_INFRA_PWM4, "infra_pwm4", + "pwm_sel", 19), + GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm", + "pwm_sel", 21), + GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0", + "uart_sel", 22), + GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1", + "uart_sel", 23), + GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2", + "uart_sel", 24), + GATE_INFRA0(CLK_INFRA_UART3, "infra_uart3", + "uart_sel", 25), + GATE_INFRA0(CLK_INFRA_GCE_26M, "infra_gce_26m", + "axi_sel", 27), + GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, "infra_cqdma_fpc", + "axi_sel", 28), + GATE_INFRA0(CLK_INFRA_BTIF, "infra_btif", + "axi_sel", 31), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_SPI0, "infra_spi0", + "spi_sel", 1), + GATE_INFRA1(CLK_INFRA_MSDC0, "infra_msdc0", + "msdc50_hclk_sel", 2), + GATE_INFRA1(CLK_INFRA_MSDC1, "infra_msdc1", + "axi_sel", 4), + GATE_INFRA1(CLK_INFRA_MSDC2, "infra_msdc2", + "axi_sel", 5), + GATE_INFRA1(CLK_INFRA_MSDC0_SCK, "infra_msdc0_sck", + "msdc50_0_sel", 6), + GATE_INFRA1(CLK_INFRA_DVFSRC, "infra_dvfsrc", + "f_f26m_ck", 7), + GATE_INFRA1(CLK_INFRA_GCPU, "infra_gcpu", + "axi_sel", 8), + GATE_INFRA1(CLK_INFRA_TRNG, "infra_trng", + "axi_sel", 9), + GATE_INFRA1(CLK_INFRA_AUXADC, "infra_auxadc", + "f_f26m_ck", 10), + GATE_INFRA1(CLK_INFRA_CPUM, "infra_cpum", + "axi_sel", 11), + GATE_INFRA1(CLK_INFRA_CCIF1_AP, "infra_ccif1_ap", + "axi_sel", 12), + GATE_INFRA1(CLK_INFRA_CCIF1_MD, "infra_ccif1_md", + "axi_sel", 13), + GATE_INFRA1(CLK_INFRA_AUXADC_MD, "infra_auxadc_md", + "f_f26m_ck", 14), + GATE_INFRA1(CLK_INFRA_MSDC1_SCK, "infra_msdc1_sck", + "msdc30_1_sel", 16), + GATE_INFRA1(CLK_INFRA_MSDC2_SCK, "infra_msdc2_sck", + "msdc30_2_sel", 17), + GATE_INFRA1(CLK_INFRA_AP_DMA, "infra_apdma", + "axi_sel", 18), + GATE_INFRA1(CLK_INFRA_XIU, "infra_xiu", + "axi_sel", 19), + GATE_INFRA1(CLK_INFRA_DEVICE_APC, "infra_device_apc", + "axi_sel", 20), + GATE_INFRA1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", + "axi_sel", 23), + GATE_INFRA1(CLK_INFRA_DEBUGSYS, "infra_debugsys", + "axi_sel", 24), + GATE_INFRA1(CLK_INFRA_AUD, "infra_audio", + "axi_sel", 25), + GATE_INFRA1(CLK_INFRA_CCIF_MD, "infra_ccif_md", + "axi_sel", 26), + GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, "infra_dxcc_sec_core", + "dxcc_sel", 27), + GATE_INFRA1(CLK_INFRA_DXCC_AO, "infra_dxcc_ao", + "dxcc_sel", 28), + GATE_INFRA1(CLK_INFRA_DEVMPU_BCLK, "infra_devmpu_bclk", + "axi_sel", 30), + GATE_INFRA1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", + "f_f26m_ck", 31), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_IRTX, "infra_irtx", + "f_f26m_ck", 0), + GATE_INFRA2(CLK_INFRA_USB, "infra_usb", + "usb_top_sel", 1), + GATE_INFRA2(CLK_INFRA_DISP_PWM, "infra_disppwm", + "axi_sel", 2), + GATE_INFRA2(CLK_INFRA_AUD_26M_BCLK, + "infracfg_ao_audio_26m_bclk", "f_f26m_ck", 4), + GATE_INFRA2(CLK_INFRA_SPI1, "infra_spi1", + "spi_sel", 6), + GATE_INFRA2(CLK_INFRA_I2C4, "infra_i2c4", + "i2c_sel", 7), + GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_md_tmp_share", + "f_f26m_ck", 8), + GATE_INFRA2(CLK_INFRA_SPI2, "infra_spi2", + "spi_sel", 9), + GATE_INFRA2(CLK_INFRA_SPI3, "infra_spi3", + "spi_sel", 10), + GATE_INFRA2(CLK_INFRA_UNIPRO_SCK, "infra_unipro_sck", + "fufs_sel", 11), + GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", + "fufs_sel", 12), + GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", + "fufs_sel", 13), + GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", + "axi_sel", 14), + GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", + "axi_sel", 16), + GATE_INFRA2(CLK_INFRA_SSPM_BUS_HCLK, "infra_sspm_bus_hclk", + "axi_sel", 17), + GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", + "i2c_sel", 18), + GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", + "i2c_sel", 19), + GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", + "i2c_sel", 20), + GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, "infra_i2c1_arbiter", + "i2c_sel", 21), + GATE_INFRA2(CLK_INFRA_I2C1_IMM, "infra_i2c1_imm", + "i2c_sel", 22), + GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, "infra_i2c2_arbiter", + "i2c_sel", 23), + GATE_INFRA2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", + "i2c_sel", 24), + GATE_INFRA2(CLK_INFRA_SPI4, "infra_spi4", + "spi_sel", 25), + GATE_INFRA2(CLK_INFRA_SPI5, "infra_spi5", + "spi_sel", 26), + GATE_INFRA2(CLK_INFRA_CQ_DMA, "infra_cqdma", + "axi_sel", 27), + GATE_INFRA2(CLK_INFRA_UFS, "infra_ufs", + "fufs_sel", 28), + GATE_INFRA2(CLK_INFRA_AES_UFSFDE, "infra_aes_ufsfde", + "faes_ufsfde_sel", 29), + GATE_INFRA2(CLK_INFRA_UFS_TICK, "infra_ufs_tick", + "fufs_sel", 30), + GATE_INFRA2(CLK_INFRA_SSUSB_XHCI, "infra_ssusb_xhci", + "ssusb_top_xhci_sel", 31), + /* INFRA3 */ + GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", + "msdc50_0_sel", 0), + GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", + "msdc50_0_sel", 1), + GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", + "msdc50_0_sel", 2), + GATE_INFRA3(CLK_INFRA_SSPM_26M_SELF, "infra_sspm_26m_self", + "f_f26m_ck", 3), + GATE_INFRA3(CLK_INFRA_SSPM_32K_SELF, "infra_sspm_32k_self", + "f_f26m_ck", 4), + GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", + "axi_sel", 5), + GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", + "i2c_sel", 6), + GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", + "msdc50_hclk_sel", 7), + GATE_INFRA3(CLK_INFRA_MD_MSDC0, "infra_md_msdc0", + "msdc50_hclk_sel", 8), + GATE_INFRA3(CLK_INFRA_CCIF2_AP, "infra_ccif2_ap", + "axi_sel", 16), + GATE_INFRA3(CLK_INFRA_CCIF2_MD, "infra_ccif2_md", + "axi_sel", 17), + GATE_INFRA3(CLK_INFRA_CCIF3_AP, "infra_ccif3_ap", + "axi_sel", 18), + GATE_INFRA3(CLK_INFRA_CCIF3_MD, "infra_ccif3_md", + "axi_sel", 19), + GATE_INFRA3(CLK_INFRA_SEJ_F13M, "infra_sej_f13m", + "f_f26m_ck", 20), + GATE_INFRA3(CLK_INFRA_AES_BCLK, "infra_aes_bclk", + "axi_sel", 21), + GATE_INFRA3(CLK_INFRA_I2C7, "infra_i2c7", + "i2c_sel", 22), + GATE_INFRA3(CLK_INFRA_I2C8, "infra_i2c8", + "i2c_sel", 23), + GATE_INFRA3(CLK_INFRA_FBIST2FPC, "infra_fbist2fpc", + "msdc50_0_sel", 24), + GATE_INFRA3(CLK_INFRA_DPMAIF_CK, "infra_dpmaif", + "dpmaif_sel", 26), + GATE_INFRA3(CLK_INFRA_FADSP, "infra_fadsp", + "adsp_sel", 27), + GATE_INFRA3(CLK_INFRA_CCIF4_AP, "infra_ccif4_ap", + "axi_sel", 28), + GATE_INFRA3(CLK_INFRA_CCIF4_MD, "infra_ccif4_md", + "axi_sel", 29), + GATE_INFRA3(CLK_INFRA_SPI6, "infra_spi6", + "spi_sel", 30), + GATE_INFRA3(CLK_INFRA_SPI7, "infra_spi7", + "spi_sel", 31), +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x20, + .clr_ofs = 0x20, + .sta_ofs = 0x20, +}; + +#define GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &apmixed_cg_regs, \ + _shift, &mtk_clk_gate_ops_no_setclr_inv, _flags) + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, 0) + +/* + * CRITICAL CLOCK: + * apmixed_appll26m is the toppest clock gate of all PLLs. + */ +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_SSUSB26M, "apmixed_ssusb26m", + "f_f26m_ck", 4), + GATE_APMIXED_FLAGS(CLK_APMIXED_APPLL26M, "apmixed_appll26m", + "f_f26m_ck", 5, CLK_IS_CRITICAL), + GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", + "f_f26m_ck", 6), + GATE_APMIXED(CLK_APMIXED_MDPLLGP26M, "apmixed_mdpll26m", + "f_f26m_ck", 7), + GATE_APMIXED(CLK_APMIXED_MM_F26M, "apmixed_mmsys26m", + "f_f26m_ck", 8), + GATE_APMIXED(CLK_APMIXED_UFS26M, "apmixed_ufs26m", + "f_f26m_ck", 9), + GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", + "f_f26m_ck", 11), + GATE_APMIXED(CLK_APMIXED_MEMPLL26M, "apmixed_mempll26m", + "f_f26m_ck", 13), + GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m", + "f_f26m_ck", 14), + GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", + "f_f26m_ck", 16), + GATE_APMIXED(CLK_APMIXED_MIPID1_26M, "apmixed_mipid126m", + "f_f26m_ck", 17), +}; + +#define MT6779_PLL_FMAX (3800UL * MHZ) +#define MT6779_PLL_FMIN (1500UL * MHZ) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT6779_PLL_FMAX, \ + .fmin = MT6779_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = _pcwibits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg, NULL) + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0, + PLL_AO, 0, 22, 8, 0x0204, 24, 0, 0, 0, 0x0204, 0, 0), + PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0210, 0x021C, 0, + PLL_AO, 0, 22, 8, 0x0214, 24, 0, 0, 0, 0x0214, 0, 0), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x02A0, 0x02AC, 0, + PLL_AO, 0, 22, 8, 0x02A4, 24, 0, 0, 0, 0x02A4, 0, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0230, 0x023C, 0, + (HAVE_RST_BAR), BIT(24), 22, 8, 0x0234, 24, 0, 0, 0, + 0x0234, 0, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0240, 0x024C, 0, + (HAVE_RST_BAR), BIT(24), 22, 8, 0x0244, 24, + 0, 0, 0, 0x0244, 0, 0), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0250, 0x025C, 0, + 0, 0, 22, 8, 0x0254, 24, 0, 0, 0, 0x0254, 0, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0260, 0x026C, 0, + 0, 0, 22, 8, 0x0264, 24, 0, 0, 0, 0x0264, 0, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0, + 0, 0, 22, 8, 0x0274, 24, 0, 0, 0, 0x0274, 0, 0), + PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x02b0, 0x02bC, 0, + (HAVE_RST_BAR), BIT(23), 22, 8, 0x02b4, 24, + 0, 0, 0, 0x02b4, 0, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0280, 0x028C, 0, + (HAVE_RST_BAR), BIT(23), 22, 8, 0x0284, 24, + 0, 0, 0, 0x0284, 0, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x02C0, 0x02D0, 0, + 0, 0, 32, 8, 0x02C0, 1, 0, 0x14, 0, 0x02C4, 0, 0x2C0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x02D4, 0x02E4, 0, + 0, 0, 32, 8, 0x02D4, 1, 0, 0x14, 1, 0x02D8, 0, 0x02D4), +}; + +static int clk_mt6779_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int clk_mt6779_top_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), + node, &mt6779_clk_lock, clk_data); + + mtk_clk_register_composites(top_aud_muxes, ARRAY_SIZE(top_aud_muxes), + base, &mt6779_clk_lock, clk_data); + + mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), + base, &mt6779_clk_lock, clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int clk_mt6779_infra_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct of_device_id of_match_clk_mt6779[] = { + { + .compatible = "mediatek,mt6779-apmixed", + .data = clk_mt6779_apmixed_probe, + }, { + .compatible = "mediatek,mt6779-topckgen", + .data = clk_mt6779_top_probe, + }, { + .compatible = "mediatek,mt6779-infracfg_ao", + .data = clk_mt6779_infra_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt6779_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *pdev); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt6779_drv = { + .probe = clk_mt6779_probe, + .driver = { + .name = "clk-mt6779", + .of_match_table = of_match_clk_mt6779, + }, +}; + +static int __init clk_mt6779_init(void) +{ + return platform_driver_register(&clk_mt6779_drv); +} + +arch_initcall(clk_mt6779_init); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-apmixedsys.c b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c new file mode 100644 index 000000000..59761c72d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-apmixedsys.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-mtk.h" +#include "clk-pll.h" + +#define REG_REF2USB 0x8 +#define REG_AP_PLL_CON7 0x1c + #define MD1_MTCMOS_OFF BIT(0) + #define MD1_MEM_OFF BIT(1) + #define MD1_CLK_OFF BIT(4) + #define MD1_ISO_OFF BIT(8) + +#define MT6795_PLL_FMAX (3000UL * MHZ) +#define MT6795_CON0_EN BIT(0) +#define MT6795_CON0_RST_BAR BIT(24) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = MT6795_CON0_EN | _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = MT6795_CON0_RST_BAR, \ + .fmax = MT6795_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = NULL, \ + .pll_en_bit = 0, \ + } + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMCA53PLL, "armca53pll", 0x200, 0x20c, 0, PLL_AO, + 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000101, HAVE_RST_BAR, + 21, 0x220, 4, 0x0, 0x224, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000101, HAVE_RST_BAR, + 7, 0x230, 4, 0x0, 0x234, 14), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0, 0, 21, 0x244, 24, 0x0, 0x244, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0, 0, 21, 0x250, 4, 0x0, 0x254, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0, 0, 21, 0x260, 4, 0x0, 0x264, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0, 0, 21, 0x270, 4, 0x0, 0x274, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0, 0, 21, 0x280, 4, 0x0, 0x284, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0, 0, 21, 0x290, 4, 0x0, 0x294, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0, 0, 31, 0x2a0, 4, 0x2a8, 0x2a4, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0, 0, 31, 0x2b4, 4, 0x2bc, 0x2b8, 0), +}; + +static void clk_mt6795_apmixed_setup_md1(void __iomem *base) +{ + void __iomem *reg = base + REG_AP_PLL_CON7; + + /* Turn on MD1 internal clock */ + writel(readl(reg) & ~MD1_CLK_OFF, reg); + + /* Unlock MD1's MTCMOS power path */ + writel(readl(reg) & ~MD1_MTCMOS_OFF, reg); + + /* Turn on ISO */ + writel(readl(reg) & ~MD1_ISO_OFF, reg); + + /* Turn on memory */ + writel(readl(reg) & ~MD1_MEM_OFF, reg); +} + +static const struct of_device_id of_match_clk_mt6795_apmixed[] = { + { .compatible = "mediatek,mt6795-apmixedsys" }, + { /* sentinel */ } +}; + +static int clk_mt6795_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + void __iomem *base; + struct clk_hw *hw; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (ret) + goto free_clk_data; + + hw = mtk_clk_register_ref2usb_tx("ref2usb_tx", "clk26m", base + REG_REF2USB); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + dev_err(dev, "Failed to register ref2usb_tx: %d\n", ret); + goto unregister_plls; + } + clk_data->hws[CLK_APMIXED_REF2USB_TX] = hw; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) { + dev_err(dev, "Cannot register clock provider: %d\n", ret); + goto unregister_ref2usb; + } + + /* Setup MD1 to avoid random crashes */ + dev_dbg(dev, "Performing initial setup for MD1\n"); + clk_mt6795_apmixed_setup_md1(base); + + return 0; + +unregister_ref2usb: + mtk_clk_unregister_ref2usb_tx(clk_data->hws[CLK_APMIXED_REF2USB_TX]); +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static int clk_mt6795_apmixed_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_ref2usb_tx(clk_data->hws[CLK_APMIXED_REF2USB_TX]); + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt6795_apmixed_drv = { + .probe = clk_mt6795_apmixed_probe, + .remove = clk_mt6795_apmixed_remove, + .driver = { + .name = "clk-mt6795-apmixed", + .of_match_table = of_match_clk_mt6795_apmixed, + }, +}; +module_platform_driver(clk_mt6795_apmixed_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 apmixed clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-infracfg.c b/drivers/clk/mediatek/clk-mt6795-infracfg.c new file mode 100644 index 000000000..df7eed6e0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-infracfg.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <dt-bindings/reset/mediatek,mt6795-resets.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "reset.h" + +#define GATE_ICG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, \ + _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +static const char * const ca53_c0_parents[] = { + "clk26m", + "armca53pll", + "mainpll", + "univpll" +}; + +static const char * const ca53_c1_parents[] = { + "clk26m", + "armca53pll", + "mainpll", + "univpll" +}; + +static const struct mtk_composite cpu_muxes[] = { + MUX(CLK_INFRA_CA53_C0_SEL, "infra_ca53_c0_sel", ca53_c0_parents, 0x00, 0, 2), + MUX(CLK_INFRA_CA53_C1_SEL, "infra_ca53_c1_sel", ca53_c1_parents, 0x00, 2, 2), +}; + +static const struct mtk_gate infra_gates[] = { + GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1), + GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5), + GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7), + GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_ICG(CLK_INFRA_MD1MCU, "infra_md1mcu", "clk26m", 9), + GATE_ICG(CLK_INFRA_MD1BUS, "infra_md1bus", "axi_sel", 10), + GATE_ICG(CLK_INFRA_MD1DBB, "infra_dbb", "axi_sel", 11), + GATE_ICG(CLK_INFRA_DEVICE_APC, "infra_devapc", "clk26m", 12), + GATE_ICG(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 13), + GATE_ICG(CLK_INFRA_MD1LTE, "infra_md1lte", "axi_sel", 14), + GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "cpum_ck", 15), + GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), +}; + +static u16 infra_ao_rst_ofs[] = { 0x30, 0x34 }; + +static u16 infra_ao_idx_map[] = { + [MT6795_INFRA_RST0_SCPSYS_RST] = 0 * RST_NR_PER_BANK + 5, + [MT6795_INFRA_RST0_PMIC_WRAP_RST] = 0 * RST_NR_PER_BANK + 7, + [MT6795_INFRA_RST1_MIPI_DSI_RST] = 1 * RST_NR_PER_BANK + 4, + [MT6795_INFRA_RST1_MIPI_CSI_RST] = 1 * RST_NR_PER_BANK + 7, + [MT6795_INFRA_RST1_MM_IOMMU_RST] = 1 * RST_NR_PER_BANK + 15, +}; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_ao_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs), + .rst_idx_map = infra_ao_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map), +}; + +static const struct of_device_id of_match_clk_mt6795_infracfg[] = { + { .compatible = "mediatek,mt6795-infracfg" }, + { /* sentinel */ } +}; + +static int clk_mt6795_infracfg_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_gates(node, infra_gates, ARRAY_SIZE(infra_gates), clk_data); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); + if (ret) + goto unregister_gates; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_cpumuxes; + + return 0; + +unregister_cpumuxes: + mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); +unregister_gates: + mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static int clk_mt6795_infracfg_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_cpumuxes(cpu_muxes, ARRAY_SIZE(cpu_muxes), clk_data); + mtk_clk_unregister_gates(infra_gates, ARRAY_SIZE(infra_gates), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt6795_infracfg_drv = { + .driver = { + .name = "clk-mt6795-infracfg", + .of_match_table = of_match_clk_mt6795_infracfg, + }, + .probe = clk_mt6795_infracfg_probe, + .remove = clk_mt6795_infracfg_remove, +}; +module_platform_driver(clk_mt6795_infracfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 infracfg clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-mfg.c b/drivers/clk/mediatek/clk-mt6795-mfg.c new file mode 100644 index 000000000..ee7aab24e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-mfg.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BAXI, "mfg_baxi", "axi_mfg_in_sel", 0), + GATE_MFG(CLK_MFG_BMEM, "mfg_bmem", "mem_mfg_in_sel", 1), + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 2), + GATE_MFG(CLK_MFG_B26M, "mfg_b26m", "clk26m", 3), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt6795_mfg[] = { + { .compatible = "mediatek,mt6795-mfgcfg", .data = &mfg_desc }, + { /* sentinel */ } +}; + +static struct platform_driver clk_mt6795_mfg_drv = { + .driver = { + .name = "clk-mt6795-mfg", + .of_match_table = of_match_clk_mt6795_mfg, + }, + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, +}; +module_platform_driver(clk_mt6795_mfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 mfg clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-mm.c b/drivers/clk/mediatek/clk-mt6795-mm.c new file mode 100644 index 000000000..fd73f202f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-mm.c @@ -0,0 +1,132 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +static const struct mtk_gate mm_gates[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_CROP, "mm_mdp_crop", "mm_sel", 10), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "clk32k", 15), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_SPLIT1, "mm_disp_split1", "mm_sel", 29), + GATE_MM0(CLK_MM_DISP_MERGE, "mm_disp_merge", "mm_sel", 30), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), + + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM0MM, "mm_disp_pwm0mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DISP_PWM026M, "mm_disp_pwm026m", "pwm_sel", 1), + GATE_MM1(CLK_MM_DISP_PWM1MM, "mm_disp_pwm1mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DISP_PWM126M, "mm_disp_pwm126m", "pwm_sel", 3), + GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), + GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_dig", 5), + GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), + GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_dig", 7), + GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "dpi0_sel", 8), + GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), +}; + +static int clk_mt6795_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_gates(node, mm_gates, ARRAY_SIZE(mm_gates), clk_data); + if (ret) + goto free_clk_data; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return 0; + +unregister_gates: + mtk_clk_unregister_gates(mm_gates, ARRAY_SIZE(mm_gates), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static int clk_mt6795_mm_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(mm_gates, ARRAY_SIZE(mm_gates), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt6795_mm_drv = { + .driver = { + .name = "clk-mt6795-mm", + }, + .probe = clk_mt6795_mm_probe, + .remove = clk_mt6795_mm_remove, +}; +module_platform_driver(clk_mt6795_mm_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 MultiMedia clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-pericfg.c b/drivers/clk/mediatek/clk-mt6795-pericfg.c new file mode 100644 index 000000000..cb28d35da --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-pericfg.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <dt-bindings/reset/mediatek,mt6795-resets.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" +#include "reset.h" + +#define GATE_PERI(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri_cg_regs, \ + _shift, &mtk_clk_gate_ops_setclr) + +static DEFINE_SPINLOCK(mt6795_peri_clk_lock); + +static const struct mtk_gate_regs peri_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static const char * const uart_ck_sel_parents[] = { + "clk26m", + "uart_sel", +}; + +static const struct mtk_composite peri_clks[] = { + MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1), + MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1), + MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1), + MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), +}; + +static const struct mtk_gate peri_gates[] = { + GATE_PERI(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0), + GATE_PERI(CLK_PERI_THERM, "peri_therm", "axi_sel", 1), + GATE_PERI(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2), + GATE_PERI(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3), + GATE_PERI(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4), + GATE_PERI(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5), + GATE_PERI(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6), + GATE_PERI(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7), + GATE_PERI(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8), + GATE_PERI(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9), + GATE_PERI(CLK_PERI_USB0, "peri_usb0", "usb30_sel", 10), + GATE_PERI(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11), + GATE_PERI(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12), + GATE_PERI(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13), + GATE_PERI(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15), + GATE_PERI(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16), + GATE_PERI(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17), + GATE_PERI(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18), + GATE_PERI(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19), + GATE_PERI(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20), + GATE_PERI(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21), + GATE_PERI(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22), + GATE_PERI(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23), + GATE_PERI(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24), + GATE_PERI(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25), + GATE_PERI(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26), + GATE_PERI(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27), + GATE_PERI(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28), + GATE_PERI(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29), +}; + +static u16 peri_rst_ofs[] = { 0x0 }; + +static u16 peri_idx_map[] = { + [MT6795_PERI_NFI_SW_RST] = 14, + [MT6795_PERI_THERM_SW_RST] = 16, + [MT6795_PERI_MSDC1_SW_RST] = 20, +}; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = peri_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(peri_rst_ofs), + .rst_idx_map = peri_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(peri_idx_map), +}; + +static const struct of_device_id of_match_clk_mt6795_pericfg[] = { + { .compatible = "mediatek,mt6795-pericfg" }, + { /* sentinel */ } +}; + +static int clk_mt6795_pericfg_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates), clk_data); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base, + &mt6795_peri_clk_lock, clk_data); + if (ret) + goto unregister_gates; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_composites; + + return 0; + +unregister_composites: + mtk_clk_unregister_composites(peri_clks, ARRAY_SIZE(peri_clks), clk_data); +unregister_gates: + mtk_clk_unregister_gates(peri_gates, ARRAY_SIZE(peri_gates), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static int clk_mt6795_pericfg_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_composites(peri_clks, ARRAY_SIZE(peri_clks), clk_data); + mtk_clk_unregister_gates(peri_gates, ARRAY_SIZE(peri_gates), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt6795_pericfg_drv = { + .driver = { + .name = "clk-mt6795-pericfg", + .of_match_table = of_match_clk_mt6795_pericfg, + }, + .probe = clk_mt6795_pericfg_probe, + .remove = clk_mt6795_pericfg_remove, +}; +module_platform_driver(clk_mt6795_pericfg_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 pericfg clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-topckgen.c b/drivers/clk/mediatek/clk-mt6795-topckgen.c new file mode 100644 index 000000000..2948dd1ae --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-topckgen.c @@ -0,0 +1,610 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" + +/* + * For some clocks, we don't care what their actual rates are. And these + * clocks may change their rate on different products or different scenarios. + * So we model these clocks' rate as 0, to denote it's not an actual rate. + */ +#define DUMMY_RATE 0 + +#define TOP_MUX_GATE_NOSR(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) \ + MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _reg, \ + (_reg + 0x4), (_reg + 0x8), _shift, _width, \ + _gate, 0, -1, _flags) + +#define TOP_MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate, _flags) \ + TOP_MUX_GATE_NOSR(_id, _name, _parents, _reg, _shift, _width, \ + _gate, CLK_SET_RATE_PARENT | _flags) + +static DEFINE_SPINLOCK(mt6795_top_clk_lock); + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "dmpll_d4", + "dmpll_d8" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const axi_mfg_in_parents[] = { + "clk26m", + "axi_sel", + "dmpll_d2" +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_d26", + "univpll2_d2", + "syspll3_d2", + "syspll3_d4", + "univpll1_d4", + "dmpll_d8" +}; + +static const char * const cci400_parents[] = { + "clk26m", + "vencpll_ck", + "clk26m", + "clk26m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clk26m", + "syspll1_d8" +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "clk26m", + "clk26m", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const i2s0_m_ck_parents[] = { + "apll1_div1", + "apll2_div1" +}; + +static const char * const i2s1_m_ck_parents[] = { + "apll1_div2", + "apll2_div2" +}; + +static const char * const i2s2_m_ck_parents[] = { + "apll1_div3", + "apll2_div3" +}; + +static const char * const i2s3_m_ck_parents[] = { + "apll1_div4", + "apll2_div4" +}; + +static const char * const i2s3_b_ck_parents[] = { + "apll1_div5", + "apll2_div5" +}; + +static const char * const irda_parents[] = { + "clk26m", + "univpll2_d4", + "syspll2_d4", + "dmpll_d8", +}; + +static const char * const mem_mfg_in_parents[] = { + "clk26m", + "mmpll_ck", + "dmpll_ck" +}; + +static const char * const mem_parents[] = { + "clk26m", + "dmpll_ck" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mmpll_ck", + "dmpll_ck", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char * const mm_parents[] = { + "clk26m", + "vencpll_d2", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2" +}; + +static const char * const mjc_parents[] = { + "clk26m", + "univpll_d3", + "vcodecpll_ck", + "tvdpll_445p5m", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "syspll_d5", + "syspll1_d2", + "univpll_d5", + "univpll2_d2", + "dmpll_ck" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "msdcpll_d4", + "vencpll_d4", + "tvdpll_ck", + "univpll_d2", + "univpll1_d2", + "mmpll_ck" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4" +}; + +static const char * const msdc30_2_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2" +}; + +static const char * const msdc30_3_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "dmpll_d8", + "dmpll_d16" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const scam_parents[] = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "dmpll_d4" +}; + +static const char * const scp_parents[] = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll3_d2", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d4", + "univpll1_d8" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const usb30_parents[] = { + "clk26m", + "univpll3_d2", + "usb_syspll_125m", + "univpll2_d4" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const venc_parents[] = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const struct mtk_fixed_clk fixed_clks[] = { + FIXED_CLK(CLK_TOP_ADSYS_26M, "adsys_26m", "clk26m", 26 * MHZ), + FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk26m", DUMMY_RATE), + FIXED_CLK(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk26m", 125 * MHZ), + FIXED_CLK(CLK_TOP_DSI0_DIG, "dsi0_dig", "clk26m", DUMMY_RATE), + FIXED_CLK(CLK_TOP_DSI1_DIG, "dsi1_dig", "clk26m", DUMMY_RATE), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_ARMCA53PLL_754M, "armca53pll_754m", "clk26m", 1, 2), + FACTOR(CLK_TOP_ARMCA53PLL_502M, "armca53pll_502m", "clk26m", 1, 3), + + FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7), + + FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3), + + FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26), + + FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1), + FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793), + FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1), + + FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "clk26m", 1, 3), + + FACTOR(CLK_TOP_ARMCA53PLL_D2, "armca53pll_d2", "clk26m", 1, 1), + FACTOR(CLK_TOP_ARMCA53PLL_D3, "armca53pll_d3", "clk26m", 1, 1), + + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1), + FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2), + FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4), + FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8), + FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16), + + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1), + FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2), + FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4), + + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4), + + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16), + + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2), + + FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3), + FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4), + + FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1), + FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2), + FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4), +}; + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + TOP_MUX_GATE_NOSR(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x40, 0, 3, 7, CLK_IS_CRITICAL), + TOP_MUX_GATE_NOSR(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x40, 8, 1, 15, CLK_IS_CRITICAL), + TOP_MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x40, 16, 1, 23, CLK_IS_CRITICAL), + TOP_MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x40, 24, 3, 31, 0), + /* CLK_CFG_1 */ + TOP_MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x50, 0, 2, 7, 0), + TOP_MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x50, 8, 4, 15, 0), + TOP_MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x50, 16, 4, 23, 0), + TOP_MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x50, 24, 4, 31, 0), + /* CLK_CFG_2 */ + TOP_MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x60, 0, 3, 7, 0), + TOP_MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x60, 8, 1, 15, 0), + TOP_MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x60, 16, 3, 23, 0), + TOP_MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x60, 24, 2, 31, 0), + /* CLK_CFG_3 */ + TOP_MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x70, 0, 2, 7, 0), + TOP_MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, + 0x70, 8, 3, 15, 0), + TOP_MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x70, 16, 4, 23, 0), + TOP_MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x70, 24, 3, 31, 0), + /* CLK_CFG_4 */ + TOP_MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x80, 0, 3, 7, 0), + TOP_MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x80, 8, 3, 15, 0), + TOP_MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x80, 16, 2, 23, 0), + TOP_MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x80, 24, 3, 31, 0), + /* CLK_CFG_5 */ + TOP_MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x90, 0, 3, 5, 0), + TOP_MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x90, 8, 3, 15, 0), + TOP_MUX_GATE(CLK_TOP_MJC_SEL, "mjc_sel", mjc_parents, 0x90, 24, 4, 31, 0), + /* CLK_CFG_6 */ + /* + * The dpi0_sel clock should not propagate rate changes to its parent + * clock so the dpi driver can have full control over PLL and divider. + */ + TOP_MUX_GATE_NOSR(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0xa0, 0, 3, 7, 0), + TOP_MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0xa0, 8, 2, 15, 0), + TOP_MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, + 0xa0, 16, 3, 23, CLK_IS_CRITICAL), + TOP_MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0xa0, 24, 2, 31, 0), + /* CLK_CFG_7 */ + TOP_MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0xb0, 0, 2, 7, 0), + TOP_MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, + 0xb0, 8, 2, 15, 0), + TOP_MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, + 0xb0, 16, 2, 23, 0), + TOP_MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0xb0, 24, 2, 31, 0), +}; + +static struct mtk_composite top_aud_divs[] = { + MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1), + MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1), + MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1), + MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1), + MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1), + + DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24), + DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0), + DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8), + DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16), + DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24), + DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0), + + DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28), + DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0), + DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8), + DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16), + DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24), + DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4), +}; + + +static const struct of_device_id of_match_clk_mt6795_topckgen[] = { + { .compatible = "mediatek,mt6795-topckgen" }, + { /* sentinel */ } +}; + +static int clk_mt6795_topckgen_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + if (ret) + goto unregister_fixed_clks; + + ret = mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt6795_top_clk_lock, clk_data); + if (ret) + goto unregister_factors; + + ret = mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), base, + &mt6795_top_clk_lock, clk_data); + if (ret) + goto unregister_muxes; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_composites; + + return 0; + +unregister_composites: + mtk_clk_unregister_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_muxes, ARRAY_SIZE(top_muxes), clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + return ret; +} + +static int clk_mt6795_topckgen_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), clk_data); + mtk_clk_unregister_muxes(top_muxes, ARRAY_SIZE(top_muxes), clk_data); + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_unregister_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt6795_topckgen_drv = { + .driver = { + .name = "clk-mt6795-topckgen", + .of_match_table = of_match_clk_mt6795_topckgen, + }, + .probe = clk_mt6795_topckgen_probe, + .remove = clk_mt6795_topckgen_remove, +}; +module_platform_driver(clk_mt6795_topckgen_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 topckgen clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-vdecsys.c b/drivers/clk/mediatek/clk-mt6795-vdecsys.c new file mode 100644 index 000000000..d85d04e0d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-vdecsys.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" + +#define GATE_VDEC(_id, _name, _parent, _regs) \ + GATE_MTK(_id, _name, _parent, _regs, 0, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +static const struct mtk_gate vdec_clks[] = { + GATE_VDEC(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", &vdec0_cg_regs), + GATE_VDEC(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", &vdec1_cg_regs), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt6795_vdecsys[] = { + { .compatible = "mediatek,mt6795-vdecsys", .data = &vdec_desc }, + { /* sentinel */ } +}; + +static struct platform_driver clk_mt6795_vdecsys_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6795-vdecsys", + .of_match_table = of_match_clk_mt6795_vdecsys, + }, +}; +module_platform_driver(clk_mt6795_vdecsys_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 vdecsys clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6795-vencsys.c b/drivers/clk/mediatek/clk-mt6795-vencsys.c new file mode 100644 index 000000000..de40a982c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6795-vencsys.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Collabora Ltd. + * Author: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <dt-bindings/clock/mediatek,mt6795-clk.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_LARB, "venc_larb", "venc_sel", 0), + GATE_VENC(CLK_VENC_VENC, "venc_venc", "venc_sel", 4), + GATE_VENC(CLK_VENC_JPGENC, "venc_jpgenc", "venc_sel", 8), + GATE_VENC(CLK_VENC_JPGDEC, "venc_jpgdec", "venc_sel", 12), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt6795_vencsys[] = { + { .compatible = "mediatek,mt6795-vencsys", .data = &venc_desc }, + { /* sentinel */ } +}; + +static struct platform_driver clk_mt6795_vencsys_drv = { + .driver = { + .name = "clk-mt6795-vencsys", + .of_match_table = of_match_clk_mt6795_vencsys, + }, + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, +}; +module_platform_driver(clk_mt6795_vencsys_drv); + +MODULE_DESCRIPTION("MediaTek MT6795 vdecsys clocks driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c new file mode 100644 index 000000000..064413934 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6797-img.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* Copyright (c) 2017 MediaTek Inc. + * Author: Kevin Chen <kevin-cw.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6797-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_sel", 11), + GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_sel", 10), + GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_sel", 6), + GATE_IMG(CLK_IMG_LARB6, "img_larb6", "mm_sel", 0), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt6797_img[] = { + { + .compatible = "mediatek,mt6797-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6797_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6797-img", + .of_match_table = of_match_clk_mt6797_img, + }, +}; + +builtin_platform_driver(clk_mt6797_img_drv); diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c new file mode 100644 index 000000000..99a63f466 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6797-mm.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Kevin Chen <kevin-cw.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt6797-clk.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 2), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_COLOR, "mm_mdp_color", "mm_sel", 10), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 15), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 29), + GATE_MM0(CLK_MM_DISP_DSC, "mm_disp_dsc", "mm_sel", 30), + GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31), + GATE_MM1(CLK_MM_DSI0_MM_CLOCK, "mm_dsi0_mm_clock", "mm_sel", 0), + GATE_MM1(CLK_MM_DSI1_MM_CLOCK, "mm_dsi1_mm_clock", "mm_sel", 2), + GATE_MM1(CLK_MM_DPI_MM_CLOCK, "mm_dpi_mm_clock", "mm_sel", 4), + GATE_MM1(CLK_MM_DPI_INTERFACE_CLOCK, "mm_dpi_interface_clock", + "dpi0_sel", 5), + GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MM_CLOCK, "mm_larb4_axi_asif_mm_clock", + "mm_sel", 6), + GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK, "mm_larb4_axi_asif_mjc_clock", + "mjc_sel", 7), + GATE_MM1(CLK_MM_DISP_OVL0_MOUT_CLOCK, "mm_disp_ovl0_mout_clock", + "mm_sel", 8), + GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 9), + GATE_MM1(CLK_MM_DSI0_INTERFACE_CLOCK, "mm_dsi0_interface_clock", + "clk26m", 1), + GATE_MM1(CLK_MM_DSI1_INTERFACE_CLOCK, "mm_dsi1_interface_clock", + "clk26m", 3), +}; + +static int clk_mt6797_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt6797_mm_drv = { + .probe = clk_mt6797_mm_probe, + .driver = { + .name = "clk-mt6797-mm", + }, +}; + +builtin_platform_driver(clk_mt6797_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c new file mode 100644 index 000000000..8622ddd87 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6797-vdec.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Kevin-CW Chen <kevin-cw.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6797-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "vdec_sel", 8), + GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4), + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "mm_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt6797_vdec[] = { + { + .compatible = "mediatek,mt6797-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6797_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6797-vdec", + .of_match_table = of_match_clk_mt6797_vdec, + }, +}; + +builtin_platform_driver(clk_mt6797_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c new file mode 100644 index 000000000..928d611a4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6797-venc.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Kevin Chen <kevin-cw.chen@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt6797-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_0, "venc_0", "mm_sel", 0), + GATE_VENC(CLK_VENC_1, "venc_1", "venc_sel", 4), + GATE_VENC(CLK_VENC_2, "venc_2", "venc_sel", 8), + GATE_VENC(CLK_VENC_3, "venc_3", "venc_sel", 12), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt6797_venc[] = { + { + .compatible = "mediatek,mt6797-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt6797_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt6797-venc", + .of_match_table = of_match_clk_mt6797_venc, + }, +}; + +builtin_platform_driver(clk_mt6797_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c new file mode 100644 index 000000000..b362e99c8 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt6797.c @@ -0,0 +1,710 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016 MediaTek Inc. + * Author: Kevin Chen <kevin-cw.chen@mediatek.com> + */ + +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt6797-clk.h> + +/* + * For some clocks, we don't care what their actual rates are. And these + * clocks may change their rate on different products or different scenarios. + * So we model these clocks' rate as 0, to denote it's not an actual rate. + */ + +static DEFINE_SPINLOCK(mt6797_clk_lock); + +static const struct mtk_fixed_factor top_fixed_divs[] = { + FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3", "syspll_d3", 1, 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26), + FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck", "univpll", 1, 1), + FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck", "univpll", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8), + FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org", "ulposc", 1, 1), + FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck", "ulposc_ck_org", 1, 3), + FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2", "ulposc_ck", 1, 2), + FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3", "ulposc_ck", 1, 4), + FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4", "ulposc_ck", 1, 8), + FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8", "ulposc_ck", 1, 10), + FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10", "ulposc_ck_org", 1, 1), + FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1), + FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2", "mfgpll_ck", 1, 2), + FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck", "imgpll", 1, 1), + FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2", "imgpll_ck", 1, 2), + FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4", "imgpll_ck", 1, 4), + FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck", "codecpll", 1, 1), + FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2", "codecpll_ck", 1, 2), + FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck", "vdecpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16), + FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, 4), + FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll_ck", 1, 8), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll_d7", + "ulposc_axi_ck_mux", +}; + +static const char * const ulposc_axi_ck_mux_parents[] = { + "syspll1_d4", + "ulposc_axi_ck_mux_pre", +}; + +static const char * const ulposc_axi_ck_mux_pre_parents[] = { + "ulposc_d2", + "ulposc_d3", +}; + +static const char * const ddrphycfg_parents[] = { + "clk26m", + "syspll3_d2", + "syspll2_d4", + "syspll1_d8", +}; + +static const char * const mm_parents[] = { + "clk26m", + "imgpll_ck", + "univpll1_d2", + "syspll1_d2", +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll2_d4", + "ulposc_d2", + "ulposc_d3", + "ulposc_d8", + "ulposc_d10", + "ulposc_d4", +}; + +static const char * const vdec_parents[] = { + "clk26m", + "vdecpll_ck", + "imgpll_ck", + "syspll_d3", + "univpll_d5", + "clk26m", + "clk26m", +}; + +static const char * const venc_parents[] = { + "clk26m", + "codecpll_ck", + "syspll_d3", +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll_ck", + "syspll_d3", + "univpll_d3", +}; + +static const char * const camtg[] = { + "clk26m", + "univpll_d26", + "univpll2_d2", +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8", +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll3_d2", + "syspll2_d4", + "ulposc_spi_ck_mux", +}; + +static const char * const ulposc_spi_ck_mux_parents[] = { + "ulposc_d2", + "ulposc_d3", +}; + +static const char * const usb20_parents[] = { + "clk26m", + "univpll1_d8", + "syspll4_d2", +}; + +static const char * const msdc50_0_hclk_parents[] = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll", + "syspll_d3", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "msdcpll_d2", + "univpll1_d2", + "univpll_d3", +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll2_d2", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", +}; + +static const char * const msdc30_2_parents[] = { + "clk26m", + "univpll2_d8", + "syspll2_d8", + "syspll1_d8", + "msdcpll_d8", + "syspll3_d4", + "univpll_d26", +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16", +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2", +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "univpll_d26", + "syspll3_d4", + "syspll1_d8", + "ulposc_d4", + "ulposc_d8", + "syspll2_d8", +}; + +static const char * const scp_parents[] = { + "clk26m", + "syspll_d3", + "ulposc_ck", + "univpll_d5", +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d2", + "syspll_d5", +}; + +static const char * const mjc_parents[] = { + "clk26m", + "imgpll_ck", + "univpll_d5", + "syspll1_d2", +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16", + "clk26m", + "clk26m", +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck", +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck", +}; + +static const char * const ssusb_top_sys_parents[] = { + "clk26m", + "univpll3_d2", +}; + +static const char * const spm_parents[] = { + "clk26m", + "syspll1_d8", +}; + +static const char * const bsi_spi_parents[] = { + "clk26m", + "syspll_d3_d3", + "syspll1_d4", + "syspll_d7", +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "apll2_ck", + "apll1_ck", + "univpll_d7", +}; + +static const char * const mfg_52m_parents[] = { + "clk26m", + "univpll2_d8", + "univpll2_d4", + "univpll2_d4", +}; + +static const char * const anc_md32_parents[] = { + "clk26m", + "syspll1_d2", + "univpll_d5", +}; + +/* + * Clock mux ddrphycfg is needed by the DRAM controller. We mark it as + * critical as otherwise the system will hang after boot. + */ +static const struct mtk_composite top_muxes[] = { + MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre", + ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1), + MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux", + ulposc_axi_ck_mux_parents, 0x0040, 2, 1), + MUX(CLK_TOP_MUX_AXI, "axi_sel", axi_parents, + 0x0040, 0, 2), + MUX_FLAGS(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents, + 0x0040, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT), + MUX(CLK_TOP_MUX_MM, "mm_sel", mm_parents, + 0x0040, 24, 2), + MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, 0x0050, 8, 3, 15), + MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, 0x0050, 16, 2, 23), + MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, 0x0050, 24, 2, 31), + MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg, 0x0060, 0, 2, 7), + MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, 0x0060, 8, 1, 15), + MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x0060, 16, 2, 23), + MUX(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux", + ulposc_spi_ck_mux_parents, 0x0060, 18, 1), + MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents, + 0x0060, 24, 2, 31), + MUX(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel", + msdc50_0_hclk_parents, 0x0070, 8, 2), + MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", msdc50_0_parents, + 0x0070, 16, 4, 23), + MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", msdc30_1_parents, + 0x0070, 24, 3, 31), + MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", msdc30_2_parents, + 0x0080, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents, + 0x0080, 16, 2, 23), + MUX(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", aud_intbus_parents, + 0x0080, 24, 2), + MUX(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents, + 0x0090, 0, 3), + MUX(CLK_TOP_MUX_SCP, "scp_sel", scp_parents, + 0x0090, 8, 2), + MUX(CLK_TOP_MUX_ATB, "atb_sel", atb_parents, + 0x0090, 16, 2), + MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel", mjc_parents, 0x0090, 24, 2, 31), + MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel", dpi0_parents, 0x00A0, 0, 3, 7), + MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel", aud_1_parents, + 0x00A0, 16, 1, 23), + MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel", aud_2_parents, + 0x00A0, 24, 1, 31), + MUX(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel", + ssusb_top_sys_parents, 0x00B0, 8, 1), + MUX(CLK_TOP_MUX_SPM, "spm_sel", spm_parents, + 0x00C0, 0, 1), + MUX(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel", bsi_spi_parents, + 0x00C0, 8, 2), + MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel", audio_h_parents, + 0x00C0, 16, 2, 23), + MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel", anc_md32_parents, + 0x00C0, 24, 2, 31), + MUX(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel", mfg_52m_parents, + 0x0104, 1, 2), +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt6797_clk_lock, clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x0080, + .clr_ofs = 0x0084, + .sta_ofs = 0x0090, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x0088, + .clr_ofs = 0x008c, + .sta_ofs = 0x0094, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0x00a8, + .clr_ofs = 0x00ac, + .sta_ofs = 0x00b0, +}; + +#define GATE_ICG0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_ICG1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_ICG1_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flags) + +#define GATE_ICG2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_ICG2_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flags) + +/* + * Clock gates dramc and dramc_b are needed by the DRAM controller. + * We mark them as critical as otherwise the system will hang after boot. + */ +static const struct mtk_gate infra_clks[] = { + GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0), + GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1), + GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pmicspi_sel", 2), + GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pmicspi_sel", 3), + GATE_ICG0(CLK_INFRA_SCP, "infra_scp", "scp_sel", 4), + GATE_ICG0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5), + GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6), + GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m", "clk26m", 7), + GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb", "usb20_sel", 8), + GATE_ICG0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 9), + GATE_ICG0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10), + GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0", "axi_sel", 11), + GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1", "axi_sel", 12), + GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2", "axi_sel", 13), + GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3", "axi_sel", 14), + GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", "axi_sel", 15), + GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1", "axi_sel", 16), + GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2", "axi_sel", 17), + GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3", "axi_sel", 18), + GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4", "axi_sel", 19), + GATE_ICG0(CLK_INFRA_PWM, "infra_pwm", "axi_sel", 21), + GATE_ICG0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22), + GATE_ICG0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23), + GATE_ICG0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24), + GATE_ICG0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25), + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0", "axi_sel", 27), + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1", "axi_sel", 28), + GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2", "axi_sel", 29), + GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl", "clk26m", 30), + GATE_ICG0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31), + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3", "axi_sel", 0), + GATE_ICG1(CLK_INFRA_SPI, "infra_spi", "spi_sel", 1), + GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_sel", 2), + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4", "axi_sel", 3), + GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc30_1_sel", 4), + GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc30_2_sel", 5), + GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5", "axi_sel", 7), + GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8), + GATE_ICG1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9), + GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10), + GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11), + GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0", + "axi_sel", 12), + GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1", + "axi_sel", 13), + GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma", "axi_sel", 16), + GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "pwm_sel", 17), + GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma", "axi_sel", 18), + GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20), + GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "mm_sel", 22), + GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23), + GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25), + GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26), + GATE_ICG1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", + "clk26m", 31, CLK_IS_CRITICAL), + GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0), + GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1), + GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2), + GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "axi_sel", 3), + GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb", "axi_sel", 4), + GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm", "axi_sel", 5), + GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb", "axi_sel", 6), + GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7), + GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8), + GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10), + GATE_ICG2_FLAGS(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", + "clk26m", 11, CLK_IS_CRITICAL), + GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12), + GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13), + GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15), + GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0", "axi_sel", 16), + GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1", "axi_sel", 17), + GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus", "axi_sel", 18), + GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 19), + GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 20), + GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 21), + GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 22), + GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx", "spi_sel", 23), + GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys", + "ssusb_top_sys_sel", 24), + GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref", "clk26m", 9), + GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m", "clk26m", 26), + GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top", + "clk26m", 27), + GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share", + "axi_sel", 28), + GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc", "axi_sel", 29), + GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf", "axi_sel", 30), + GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf", "axi_sel", 31), + GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg", "mfg_52m_sel", 14), +}; + +static const struct mtk_fixed_factor infra_fixed_divs[] = { + FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2), +}; + +static struct clk_hw_onecell_data *infra_clk_data; + +static void mtk_infrasys_init_early(struct device_node *node) +{ + int r, i; + + if (!infra_clk_data) { + infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return; + + for (i = 0; i < CLK_INFRA_NR; i++) + infra_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); + } + + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} + +CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg", + mtk_infrasys_init_early); + +static int mtk_infrasys_init(struct platform_device *pdev) +{ + int i; + struct device_node *node = pdev->dev.of_node; + + if (!infra_clk_data) { + infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR); + if (!infra_clk_data) + return -ENOMEM; + } else { + for (i = 0; i < CLK_INFRA_NR; i++) { + if (infra_clk_data->hws[i] == ERR_PTR(-EPROBE_DEFER)) + infra_clk_data->hws[i] = ERR_PTR(-ENOENT); + } + } + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + infra_clk_data); + mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs), + infra_clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + infra_clk_data); +} + +#define MT6797_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT6797_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT6797_RST_BAR, \ + .fmax = MT6797_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ +} + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000100, PLL_AO, + 21, 0x220, 4, 0x0, 0x224, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000010, 0, 7, + 0x230, 4, 0x0, 0x234, 14), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000100, 0, 21, + 0x244, 24, 0x0, 0x244, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000120, 0, 21, + 0x250, 4, 0x0, 0x254, 0), + PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000120, 0, 21, + 0x260, 4, 0x0, 0x264, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000120, 0, 21, + 0x270, 4, 0x0, 0x274, 0), + PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000120, 0, 21, + 0x290, 4, 0x0, 0x294, 0), + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000120, 0, 21, + 0x2E4, 4, 0x0, 0x2E8, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000130, 0, 31, + 0x2A0, 4, 0x2A8, 0x2A4, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000130, 0, 31, + 0x2B4, 4, 0x2BC, 0x2B8, 0), +}; + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct of_device_id of_match_clk_mt6797[] = { + { + .compatible = "mediatek,mt6797-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt6797-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt6797-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt6797_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt6797_drv = { + .probe = clk_mt6797_probe, + .driver = { + .name = "clk-mt6797", + .of_match_table = of_match_clk_mt6797, + }, +}; + +static int __init clk_mt6797_init(void) +{ + return platform_driver_register(&clk_mt6797_drv); +} + +arch_initcall(clk_mt6797_init); diff --git a/drivers/clk/mediatek/clk-mt7622-aud.c b/drivers/clk/mediatek/clk-mt7622-aud.c new file mode 100644 index 000000000..b17731fa1 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-aud.c @@ -0,0 +1,176 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong <chen.zhong@mediatek.com> + * Sean Wang <sean.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7622-clk.h> + +#define GATE_AUDIO0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio3_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs audio2_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +static const struct mtk_gate_regs audio3_cg_regs = { + .set_ofs = 0x634, + .clr_ofs = 0x634, + .sta_ofs = 0x634, +}; + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUDIO_AFE, "audio_afe", "rtc", 2), + GATE_AUDIO0(CLK_AUDIO_HDMI, "audio_hdmi", "apll1_ck_sel", 20), + GATE_AUDIO0(CLK_AUDIO_SPDF, "audio_spdf", "apll1_ck_sel", 21), + GATE_AUDIO0(CLK_AUDIO_APLL, "audio_apll", "apll1_ck_sel", 23), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUDIO_I2SIN1, "audio_i2sin1", "a1sys_hp_sel", 0), + GATE_AUDIO1(CLK_AUDIO_I2SIN2, "audio_i2sin2", "a1sys_hp_sel", 1), + GATE_AUDIO1(CLK_AUDIO_I2SIN3, "audio_i2sin3", "a1sys_hp_sel", 2), + GATE_AUDIO1(CLK_AUDIO_I2SIN4, "audio_i2sin4", "a1sys_hp_sel", 3), + GATE_AUDIO1(CLK_AUDIO_I2SO1, "audio_i2so1", "a1sys_hp_sel", 6), + GATE_AUDIO1(CLK_AUDIO_I2SO2, "audio_i2so2", "a1sys_hp_sel", 7), + GATE_AUDIO1(CLK_AUDIO_I2SO3, "audio_i2so3", "a1sys_hp_sel", 8), + GATE_AUDIO1(CLK_AUDIO_I2SO4, "audio_i2so4", "a1sys_hp_sel", 9), + GATE_AUDIO1(CLK_AUDIO_ASRCI1, "audio_asrci1", "asm_h_sel", 12), + GATE_AUDIO1(CLK_AUDIO_ASRCI2, "audio_asrci2", "asm_h_sel", 13), + GATE_AUDIO1(CLK_AUDIO_ASRCO1, "audio_asrco1", "asm_h_sel", 14), + GATE_AUDIO1(CLK_AUDIO_ASRCO2, "audio_asrco2", "asm_h_sel", 15), + GATE_AUDIO1(CLK_AUDIO_INTDIR, "audio_intdir", "intdir_sel", 20), + GATE_AUDIO1(CLK_AUDIO_A1SYS, "audio_a1sys", "a1sys_hp_sel", 21), + GATE_AUDIO1(CLK_AUDIO_A2SYS, "audio_a2sys", "a2sys_hp_sel", 22), + GATE_AUDIO1(CLK_AUDIO_AFE_CONN, "audio_afe_conn", "a1sys_hp_sel", 23), + /* AUDIO2 */ + GATE_AUDIO2(CLK_AUDIO_UL1, "audio_ul1", "a1sys_hp_sel", 0), + GATE_AUDIO2(CLK_AUDIO_UL2, "audio_ul2", "a1sys_hp_sel", 1), + GATE_AUDIO2(CLK_AUDIO_UL3, "audio_ul3", "a1sys_hp_sel", 2), + GATE_AUDIO2(CLK_AUDIO_UL4, "audio_ul4", "a1sys_hp_sel", 3), + GATE_AUDIO2(CLK_AUDIO_UL5, "audio_ul5", "a1sys_hp_sel", 4), + GATE_AUDIO2(CLK_AUDIO_UL6, "audio_ul6", "a1sys_hp_sel", 5), + GATE_AUDIO2(CLK_AUDIO_DL1, "audio_dl1", "a1sys_hp_sel", 6), + GATE_AUDIO2(CLK_AUDIO_DL2, "audio_dl2", "a1sys_hp_sel", 7), + GATE_AUDIO2(CLK_AUDIO_DL3, "audio_dl3", "a1sys_hp_sel", 8), + GATE_AUDIO2(CLK_AUDIO_DL4, "audio_dl4", "a1sys_hp_sel", 9), + GATE_AUDIO2(CLK_AUDIO_DL5, "audio_dl5", "a1sys_hp_sel", 10), + GATE_AUDIO2(CLK_AUDIO_DL6, "audio_dl6", "a1sys_hp_sel", 11), + GATE_AUDIO2(CLK_AUDIO_DLMCH, "audio_dlmch", "a1sys_hp_sel", 12), + GATE_AUDIO2(CLK_AUDIO_ARB1, "audio_arb1", "a1sys_hp_sel", 13), + GATE_AUDIO2(CLK_AUDIO_AWB, "audio_awb", "a1sys_hp_sel", 14), + GATE_AUDIO2(CLK_AUDIO_AWB2, "audio_awb2", "a1sys_hp_sel", 15), + GATE_AUDIO2(CLK_AUDIO_DAI, "audio_dai", "a1sys_hp_sel", 16), + GATE_AUDIO2(CLK_AUDIO_MOD, "audio_mod", "a1sys_hp_sel", 17), + /* AUDIO3 */ + GATE_AUDIO3(CLK_AUDIO_ASRCI3, "audio_asrci3", "asm_h_sel", 2), + GATE_AUDIO3(CLK_AUDIO_ASRCI4, "audio_asrci4", "asm_h_sel", 3), + GATE_AUDIO3(CLK_AUDIO_ASRCO3, "audio_asrco3", "asm_h_sel", 6), + GATE_AUDIO3(CLK_AUDIO_ASRCO4, "audio_asrco4", "asm_h_sel", 7), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC1, "audio_mem_asrc1", "asm_h_sel", 10), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC2, "audio_mem_asrc2", "asm_h_sel", 11), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC3, "audio_mem_asrc3", "asm_h_sel", 12), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC4, "audio_mem_asrc4", "asm_h_sel", 13), + GATE_AUDIO3(CLK_AUDIO_MEM_ASRC5, "audio_mem_asrc5", "asm_h_sel", 14), +}; + +static int clk_mt7622_audiosys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + goto err_clk_provider; + } + + r = devm_of_platform_populate(&pdev->dev); + if (r) + goto err_plat_populate; + + return 0; + +err_plat_populate: + of_clk_del_provider(node); +err_clk_provider: + return r; +} + +static const struct of_device_id of_match_clk_mt7622_aud[] = { + { + .compatible = "mediatek,mt7622-audsys", + .data = clk_mt7622_audiosys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_aud_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_aud_drv = { + .probe = clk_mt7622_aud_probe, + .driver = { + .name = "clk-mt7622-aud", + .of_match_table = of_match_clk_mt7622_aud, + }, +}; + +builtin_platform_driver(clk_mt7622_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-eth.c b/drivers/clk/mediatek/clk-mt7622-eth.c new file mode 100644 index 000000000..a60190e83 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-eth.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong <chen.zhong@mediatek.com> + * Sean Wang <sean.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7622-clk.h> + +#define GATE_ETH(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate eth_clks[] = { + GATE_ETH(CLK_ETH_HSDMA_EN, "eth_hsdma_en", "eth_sel", 5), + GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8), + GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9), +}; + +static const struct mtk_gate_regs sgmii_cg_regs = { + .set_ofs = 0xE4, + .clr_ofs = 0xE4, + .sta_ofs = 0xE4, +}; + +#define GATE_SGMII(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &sgmii_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate sgmii_clks[] = { + GATE_SGMII(CLK_SGMII_TX250M_EN, "sgmii_tx250m_en", + "ssusb_tx250m", 2), + GATE_SGMII(CLK_SGMII_RX250M_EN, "sgmii_rx250m_en", + "ssusb_eq_rx250m", 3), + GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", + "ssusb_cdr_ref", 4), + GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", + "ssusb_cdr_fb", 5), +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static int clk_mt7622_ethsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static int clk_mt7622_sgmiisys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + + mtk_clk_register_gates(node, sgmii_clks, ARRAY_SIZE(sgmii_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_eth[] = { + { + .compatible = "mediatek,mt7622-ethsys", + .data = clk_mt7622_ethsys_init, + }, { + .compatible = "mediatek,mt7622-sgmiisys", + .data = clk_mt7622_sgmiisys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_eth_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_eth_drv = { + .probe = clk_mt7622_eth_probe, + .driver = { + .name = "clk-mt7622-eth", + .of_match_table = of_match_clk_mt7622_eth, + }, +}; + +builtin_platform_driver(clk_mt7622_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt7622-hif.c b/drivers/clk/mediatek/clk-mt7622-hif.c new file mode 100644 index 000000000..55baa6d06 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622-hif.c @@ -0,0 +1,157 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong <chen.zhong@mediatek.com> + * Sean Wang <sean.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7622-clk.h> + +#define GATE_PCIE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &pcie_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_SSUSB(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ssusb_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate_regs pcie_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate_regs ssusb_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate ssusb_clks[] = { + GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", + "to_u2_phy_1p", 0), + GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1), + GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5), + GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6), + GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "axi_sel", 7), + GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "hif_sel", 8), +}; + +static const struct mtk_gate pcie_clks[] = { + GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12), + GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13), + GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "axi_sel", 14), + GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "hif_sel", 15), + GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16), + GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17), + GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18), + GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19), + GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "axi_sel", 20), + GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "hif_sel", 21), + GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22), + GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23), + GATE_PCIE(CLK_SATA_AHB_EN, "sata_ahb_en", "axi_sel", 26), + GATE_PCIE(CLK_SATA_AXI_EN, "sata_axi_en", "hif_sel", 27), + GATE_PCIE(CLK_SATA_ASIC_EN, "sata_asic_en", "sata_asic", 28), + GATE_PCIE(CLK_SATA_RBC_EN, "sata_rbc_en", "sata_rbc", 29), + GATE_PCIE(CLK_SATA_PM_EN, "sata_pm_en", "univpll2_d4", 30), +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static int clk_mt7622_ssusbsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + + mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static int clk_mt7622_pciesys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + + mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static const struct of_device_id of_match_clk_mt7622_hif[] = { + { + .compatible = "mediatek,mt7622-pciesys", + .data = clk_mt7622_pciesys_init, + }, { + .compatible = "mediatek,mt7622-ssusbsys", + .data = clk_mt7622_ssusbsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_hif_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_hif_drv = { + .probe = clk_mt7622_hif_probe, + .driver = { + .name = "clk-mt7622-hif", + .of_match_table = of_match_clk_mt7622_hif, + }, +}; + +builtin_platform_driver(clk_mt7622_hif_drv); diff --git a/drivers/clk/mediatek/clk-mt7622.c b/drivers/clk/mediatek/clk-mt7622.c new file mode 100644 index 000000000..eebbb8790 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7622.c @@ -0,0 +1,749 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2017 MediaTek Inc. + * Author: Chen Zhong <chen.zhong@mediatek.com> + * Sean Wang <sean.wang@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt7622-clk.h> +#include <linux/clk.h> /* for consumer */ + +#define MT7622_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7622_RST_BAR BIT(27) + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table, _parent_name) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT7622_RST_BAR, \ + .fmax = MT7622_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,\ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL, "clkxtal") + +#define GATE_APMIXED_AO(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &apmixed_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv, CLK_IS_CRITICAL) + +#define GATE_INFRA(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_TOP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_TOP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI0_AO(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &peri0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static DEFINE_SPINLOCK(mt7622_clk_lock); + +static const char * const infra_mux1_parents[] = { + "clkxtal", + "armpll", + "main_core_en", + "armpll" +}; + +static const char * const axi_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7" +}; + +static const char * const mem_parents[] = { + "clkxtal", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clkxtal", + "syspll1_d8" +}; + +static const char * const eth_parents[] = { + "clkxtal", + "syspll1_d2", + "univpll1_d2", + "syspll1_d4", + "univpll_d5", + "clk_null", + "univpll_d7" +}; + +static const char * const pwm_parents[] = { + "clkxtal", + "univpll2_d4" +}; + +static const char * const f10m_ref_parents[] = { + "clkxtal", + "syspll4_d16" +}; + +static const char * const nfi_infra_parents[] = { + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "univpll2_d8", + "syspll1_d8", + "univpll1_d8", + "syspll4_d2", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4" +}; + +static const char * const flash_parents[] = { + "clkxtal", + "univpll_d80_d4", + "syspll2_d8", + "syspll3_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll2_d4" +}; + +static const char * const uart_parents[] = { + "clkxtal", + "univpll2_d8" +}; + +static const char * const spi0_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll2_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const spi1_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll4_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const msdc30_0_parents[] = { + "clkxtal", + "univpll2_d16", + "univ48m" +}; + +static const char * const a1sys_hp_parents[] = { + "clkxtal", + "aud1pll_ck", + "aud2pll_ck", + "clkxtal" +}; + +static const char * const intdir_parents[] = { + "clkxtal", + "syspll_d2", + "univpll_d2", + "sgmiipll_ck" +}; + +static const char * const aud_intbus_parents[] = { + "clkxtal", + "syspll1_d4", + "syspll4_d2", + "syspll3_d2" +}; + +static const char * const pmicspi_parents[] = { + "clkxtal", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "univpll2_d16" +}; + +static const char * const atb_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5" +}; + +static const char * const audio_parents[] = { + "clkxtal", + "syspll3_d4", + "syspll4_d4", + "univpll1_d16" +}; + +static const char * const usb20_parents[] = { + "clkxtal", + "univpll3_d4", + "syspll1_d8", + "clkxtal" +}; + +static const char * const aud1_parents[] = { + "clkxtal", + "aud1pll_ck" +}; + +static const char * const aud2_parents[] = { + "clkxtal", + "aud2pll_ck" +}; + +static const char * const asm_l_parents[] = { + "clkxtal", + "syspll_d5", + "univpll2_d2", + "univpll2_d4" +}; + +static const char * const apll1_ck_parents[] = { + "aud1_sel", + "aud2_sel" +}; + +static const char * const peribus_ck_parents[] = { + "syspll1_d8", + "syspll1_d4" +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x120, + .clr_ofs = 0x120, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x128, + .clr_ofs = 0x128, + .sta_ofs = 0x128, +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xC, + .clr_ofs = 0x14, + .sta_ofs = 0x1C, +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0, + PLL_AO, 21, 0x0204, 24, 0, 0x0204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0, + HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0, + HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0, + 0, 21, 0x0300, 1, 0, 0x0304, 0), + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0, + 0, 21, 0x0314, 1, 0, 0x0318, 0), + PLL(CLK_APMIXED_AUD1PLL, "aud1pll", 0x0324, 0x0330, 0, + 0, 31, 0x0324, 1, 0, 0x0328, 0), + PLL(CLK_APMIXED_AUD2PLL, "aud2pll", 0x0334, 0x0340, 0, + 0, 31, 0x0334, 1, 0, 0x0338, 0), + PLL(CLK_APMIXED_TRGPLL, "trgpll", 0x0344, 0x0354, 0, + 0, 21, 0x0344, 1, 0, 0x0348, 0), + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0, + 0, 21, 0x0358, 1, 0, 0x035C, 0), +}; + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED_AO(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5), +}; + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "axi_sel", 0), + GATE_INFRA(CLK_INFRA_TRNG, "trng_ck", "axi_sel", 2), + GATE_INFRA(CLK_INFRA_AUDIO_PD, "infra_audio_pd", "aud_intbus_sel", 5), + GATE_INFRA(CLK_INFRA_IRRX_PD, "infra_irrx_pd", "irrx_sel", 16), + GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "f10m_ref_sel", 18), + GATE_INFRA(CLK_INFRA_PMIC_PD, "infra_pmic_pd", "pmicspi_sel", 22), +}; + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", + 33333333), + FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", + 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4), + FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125), + FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1), + FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024), + FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1), + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), + FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL1_D16, "univpll1_d16", "univpll", 1, 32), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), + FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320), + FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25), + FACTOR(CLK_TOP_SGMIIPLL, "sgmiipll_ck", "sgmipll", 1, 1), + FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2), + FACTOR(CLK_TOP_AUD1PLL, "aud1pll_ck", "aud1pll", 1, 1), + FACTOR(CLK_TOP_AUD2PLL, "aud2pll_ck", "aud2pll", 1, 1), + FACTOR(CLK_TOP_AUD_I2S2_MCK, "aud_i2s2_mck", "i2s2_mck_sel", 1, 2), + FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "univpll2_d4", 1, 4), + FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "univpll1_d4", 1, 1), + FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1), +}; + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_APLL1_DIV_PD, "apll1_ck_div_pd", "apll1_ck_div", 0), + GATE_TOP0(CLK_TOP_APLL2_DIV_PD, "apll2_ck_div_pd", "apll2_ck_div", 1), + GATE_TOP0(CLK_TOP_I2S0_MCK_DIV_PD, "i2s0_mck_div_pd", "i2s0_mck_div", + 2), + GATE_TOP0(CLK_TOP_I2S1_MCK_DIV_PD, "i2s1_mck_div_pd", "i2s1_mck_div", + 3), + GATE_TOP0(CLK_TOP_I2S2_MCK_DIV_PD, "i2s2_mck_div_pd", "i2s2_mck_div", + 4), + GATE_TOP0(CLK_TOP_I2S3_MCK_DIV_PD, "i2s3_mck_div_pd", "i2s3_mck_div", + 5), + + /* TOP1 */ + GATE_TOP1(CLK_TOP_A1SYS_HP_DIV_PD, "a1sys_div_pd", "a1sys_div", 0), + GATE_TOP1(CLK_TOP_A2SYS_HP_DIV_PD, "a2sys_div_pd", "a2sys_div", 16), +}; + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL1_DIV, "apll1_ck_div", "apll1_ck_sel", + 0x120, 24, 3), + DIV_ADJ(CLK_TOP_APLL2_DIV, "apll2_ck_div", "apll2_ck_sel", + 0x120, 28, 3), + DIV_ADJ(CLK_TOP_I2S0_MCK_DIV, "i2s0_mck_div", "i2s0_mck_sel", + 0x124, 0, 7), + DIV_ADJ(CLK_TOP_I2S1_MCK_DIV, "i2s1_mck_div", "i2s1_mck_sel", + 0x124, 8, 7), + DIV_ADJ(CLK_TOP_I2S2_MCK_DIV, "i2s2_mck_div", "aud_i2s2_mck", + 0x124, 16, 7), + DIV_ADJ(CLK_TOP_I2S3_MCK_DIV, "i2s3_mck_div", "i2s3_mck_sel", + 0x124, 24, 7), + DIV_ADJ(CLK_TOP_A1SYS_HP_DIV, "a1sys_div", "a1sys_hp_sel", + 0x128, 8, 7), + DIV_ADJ(CLK_TOP_A2SYS_HP_DIV, "a2sys_div", "a2sys_hp_sel", + 0x128, 24, 7), +}; + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_THERM_PD, "peri_therm_pd", "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "clkxtal", 2), + GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "clkxtal", 3), + GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "clkxtal", 4), + GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "clkxtal", 5), + GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "clkxtal", 6), + GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "clkxtal", 7), + GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "clkxtal", 8), + GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "clkxtal", 9), + GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "axi_sel", 12), + GATE_PERI0(CLK_PERI_MSDC30_0_PD, "peri_msdc30_0", "msdc30_0_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI0_AO(CLK_PERI_UART0_PD, "peri_uart0_pd", "axi_sel", 17), + GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "axi_sel", 18), + GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "axi_sel", 19), + GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "axi_sel", 20), + GATE_PERI0(CLK_PERI_UART4_PD, "peri_uart4_pd", "axi_sel", 21), + GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "axi_sel", 22), + GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "axi_sel", 23), + GATE_PERI0(CLK_PERI_I2C1_PD, "peri_i2c1_pd", "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C2_PD, "peri_i2c2_pd", "axi_sel", 25), + GATE_PERI0(CLK_PERI_SPI1_PD, "peri_spi1_pd", "spi1_sel", 26), + GATE_PERI0(CLK_PERI_AUXADC_PD, "peri_auxadc_pd", "clkxtal", 27), + GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi0_sel", 28), + GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "nfi_infra_sel", 29), + GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "axi_sel", 30), + GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "axi_sel", 31), + + /* PERI1 */ + GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash_sel", 1), + GATE_PERI1(CLK_PERI_IRTX_PD, "peri_irtx_pd", "irtx_sel", 2), +}; + +static struct mtk_composite infra_muxes[] = { + MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, + 0x000, 2, 2), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x040, 0, 3, 7, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x040, 8, 1, 15, CLK_IS_CRITICAL), + MUX_GATE_FLAGS(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x040, 16, 1, 23, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 24, 3, 31), + + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, + 0x050, 8, 1, 15), + MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, + 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, + 0x050, 24, 3, 31), + + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + 0x060, 0, 1, 7), + MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, + 0x060, 8, 3, 15), + MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, + 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, + 0x060, 24, 3, 31), + + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, + 0x070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_0_parents, + 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_A1SYS_HP_SEL, "a1sys_hp_sel", a1sys_hp_parents, + 0x070, 16, 2, 23), + MUX_GATE(CLK_TOP_A2SYS_HP_SEL, "a2sys_hp_sel", a1sys_hp_parents, + 0x070, 24, 2, 31), + + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_INTDIR_SEL, "intdir_sel", intdir_parents, + 0x080, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x080, 8, 2, 15), + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x080, 16, 3, 23), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", ddrphycfg_parents, + 0x080, 24, 2, 31), + + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, + 0x090, 0, 2, 7), + MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", eth_parents, + 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + 0x090, 16, 2, 23), + MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, + 0x090, 24, 2, 31), + + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x0A0, 0, 1, 7), + MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x0A0, 8, 1, 15), + MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", f10m_ref_parents, + 0x0A0, 16, 1, 23), + MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", f10m_ref_parents, + 0x0A0, 24, 1, 31), + + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_ASM_L_SEL, "asm_l_sel", asm_l_parents, + 0x0B0, 0, 2, 7), + MUX_GATE(CLK_TOP_ASM_M_SEL, "asm_m_sel", asm_l_parents, + 0x0B0, 8, 2, 15), + MUX_GATE(CLK_TOP_ASM_H_SEL, "asm_h_sel", asm_l_parents, + 0x0B0, 16, 2, 23), + + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL1_SEL, "apll1_ck_sel", apll1_ck_parents, + 0x120, 6, 1), + MUX(CLK_TOP_APLL2_SEL, "apll2_ck_sel", apll1_ck_parents, + 0x120, 7, 1), + MUX(CLK_TOP_I2S0_MCK_SEL, "i2s0_mck_sel", apll1_ck_parents, + 0x120, 8, 1), + MUX(CLK_TOP_I2S1_MCK_SEL, "i2s1_mck_sel", apll1_ck_parents, + 0x120, 9, 1), + MUX(CLK_TOP_I2S2_MCK_SEL, "i2s2_mck_sel", apll1_ck_parents, + 0x120, 10, 1), + MUX(CLK_TOP_I2S3_MCK_SEL, "i2s3_mck_sel", apll1_ck_parents, + 0x120, 11, 1), +}; + +static struct mtk_composite peri_muxes[] = { + /* PERI_GLOBALCON_CKSEL */ + MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1), +}; + +static u16 infrasys_rst_ofs[] = { 0x30, }; +static u16 pericfg_rst_ofs[] = { 0x0, 0x4, }; + +static const struct mtk_clk_rst_desc clk_rst_desc[] = { + /* infrasys */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), + }, + /* pericfg */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), + }, +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt7622_clk_lock, clk_data); + + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int mtk_infrasys_init(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); + if (r) + return r; + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[0]); + + return 0; +} + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int mtk_pericfg_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7622_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + return r; + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc[1]); + + return 0; +} + +static const struct of_device_id of_match_clk_mt7622[] = { + { + .compatible = "mediatek,mt7622-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + .compatible = "mediatek,mt7622-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt7622-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt7622-pericfg", + .data = mtk_pericfg_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7622_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7622_drv = { + .probe = clk_mt7622_probe, + .driver = { + .name = "clk-mt7622", + .of_match_table = of_match_clk_mt7622, + }, +}; + +static int clk_mt7622_init(void) +{ + return platform_driver_register(&clk_mt7622_drv); +} + +arch_initcall(clk_mt7622_init); diff --git a/drivers/clk/mediatek/clk-mt7629-eth.c b/drivers/clk/mediatek/clk-mt7629-eth.c new file mode 100644 index 000000000..e1d2635c7 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7629-eth.c @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MediaTek Inc. + * Author: Wenzhen Yu <Wenzhen Yu@mediatek.com> + * Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7629-clk.h> + +#define GATE_ETH(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate eth_clks[] = { + GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "eth2pll", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "txclk_src_pre", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "txclk_src_pre", 8), + GATE_ETH(CLK_ETH_GP0_EN, "eth_gp0_en", "txclk_src_pre", 9), + GATE_ETH(CLK_ETH_ESW_EN, "eth_esw_en", "eth_500m", 16), +}; + +static const struct mtk_gate_regs sgmii_cg_regs = { + .set_ofs = 0xE4, + .clr_ofs = 0xE4, + .sta_ofs = 0xE4, +}; + +#define GATE_SGMII(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &sgmii_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate sgmii_clks[2][4] = { + { + GATE_SGMII(CLK_SGMII_TX_EN, "sgmii_tx_en", + "ssusb_tx250m", 2), + GATE_SGMII(CLK_SGMII_RX_EN, "sgmii_rx_en", + "ssusb_eq_rx250m", 3), + GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref", + "ssusb_cdr_ref", 4), + GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb", + "ssusb_cdr_fb", 5), + }, { + GATE_SGMII(CLK_SGMII_TX_EN, "sgmii_tx_en1", + "ssusb_tx250m", 2), + GATE_SGMII(CLK_SGMII_RX_EN, "sgmii_rx_en1", + "ssusb_eq_rx250m", 3), + GATE_SGMII(CLK_SGMII_CDR_REF, "sgmii_cdr_ref1", + "ssusb_cdr_ref", 4), + GATE_SGMII(CLK_SGMII_CDR_FB, "sgmii_cdr_fb1", + "ssusb_cdr_fb", 5), + } +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static int clk_mt7629_ethsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_ETH_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, eth_clks, CLK_ETH_NR_CLK, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static int clk_mt7629_sgmiisys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + static int id; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SGMII_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, sgmii_clks[id++], CLK_SGMII_NR_CLK, + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static const struct of_device_id of_match_clk_mt7629_eth[] = { + { + .compatible = "mediatek,mt7629-ethsys", + .data = clk_mt7629_ethsys_init, + }, { + .compatible = "mediatek,mt7629-sgmiisys", + .data = clk_mt7629_sgmiisys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7629_eth_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7629_eth_drv = { + .probe = clk_mt7629_eth_probe, + .driver = { + .name = "clk-mt7629-eth", + .of_match_table = of_match_clk_mt7629_eth, + }, +}; + +builtin_platform_driver(clk_mt7629_eth_drv); diff --git a/drivers/clk/mediatek/clk-mt7629-hif.c b/drivers/clk/mediatek/clk-mt7629-hif.c new file mode 100644 index 000000000..3628811a2 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7629-hif.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MediaTek Inc. + * Author: Wenzhen Yu <Wenzhen Yu@mediatek.com> + * Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7629-clk.h> + +#define GATE_PCIE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &pcie_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_SSUSB(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ssusb_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate_regs pcie_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate_regs ssusb_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +static const struct mtk_gate ssusb_clks[] = { + GATE_SSUSB(CLK_SSUSB_U2_PHY_1P_EN, "ssusb_u2_phy_1p", + "to_u2_phy_1p", 0), + GATE_SSUSB(CLK_SSUSB_U2_PHY_EN, "ssusb_u2_phy_en", "to_u2_phy", 1), + GATE_SSUSB(CLK_SSUSB_REF_EN, "ssusb_ref_en", "to_usb3_ref", 5), + GATE_SSUSB(CLK_SSUSB_SYS_EN, "ssusb_sys_en", "to_usb3_sys", 6), + GATE_SSUSB(CLK_SSUSB_MCU_EN, "ssusb_mcu_en", "to_usb3_mcu", 7), + GATE_SSUSB(CLK_SSUSB_DMA_EN, "ssusb_dma_en", "to_usb3_dma", 8), +}; + +static const struct mtk_gate pcie_clks[] = { + GATE_PCIE(CLK_PCIE_P1_AUX_EN, "pcie_p1_aux_en", "p1_1mhz", 12), + GATE_PCIE(CLK_PCIE_P1_OBFF_EN, "pcie_p1_obff_en", "free_run_4mhz", 13), + GATE_PCIE(CLK_PCIE_P1_AHB_EN, "pcie_p1_ahb_en", "from_top_ahb", 14), + GATE_PCIE(CLK_PCIE_P1_AXI_EN, "pcie_p1_axi_en", "from_top_axi", 15), + GATE_PCIE(CLK_PCIE_P1_MAC_EN, "pcie_p1_mac_en", "pcie1_mac_en", 16), + GATE_PCIE(CLK_PCIE_P1_PIPE_EN, "pcie_p1_pipe_en", "pcie1_pipe_en", 17), + GATE_PCIE(CLK_PCIE_P0_AUX_EN, "pcie_p0_aux_en", "p0_1mhz", 18), + GATE_PCIE(CLK_PCIE_P0_OBFF_EN, "pcie_p0_obff_en", "free_run_4mhz", 19), + GATE_PCIE(CLK_PCIE_P0_AHB_EN, "pcie_p0_ahb_en", "from_top_ahb", 20), + GATE_PCIE(CLK_PCIE_P0_AXI_EN, "pcie_p0_axi_en", "from_top_axi", 21), + GATE_PCIE(CLK_PCIE_P0_MAC_EN, "pcie_p0_mac_en", "pcie0_mac_en", 22), + GATE_PCIE(CLK_PCIE_P0_PIPE_EN, "pcie_p0_pipe_en", "pcie0_pipe_en", 23), +}; + +static u16 rst_ofs[] = { 0x34, }; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = rst_ofs, + .rst_bank_nr = ARRAY_SIZE(rst_ofs), +}; + +static int clk_mt7629_ssusbsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_SSUSB_NR_CLK); + + mtk_clk_register_gates(node, ssusb_clks, ARRAY_SIZE(ssusb_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static int clk_mt7629_pciesys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_PCIE_NR_CLK); + + mtk_clk_register_gates(node, pcie_clks, ARRAY_SIZE(pcie_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static const struct of_device_id of_match_clk_mt7629_hif[] = { + { + .compatible = "mediatek,mt7629-pciesys", + .data = clk_mt7629_pciesys_init, + }, { + .compatible = "mediatek,mt7629-ssusbsys", + .data = clk_mt7629_ssusbsys_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7629_hif_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7629_hif_drv = { + .probe = clk_mt7629_hif_probe, + .driver = { + .name = "clk-mt7629-hif", + .of_match_table = of_match_clk_mt7629_hif, + }, +}; + +builtin_platform_driver(clk_mt7629_hif_drv); diff --git a/drivers/clk/mediatek/clk-mt7629.c b/drivers/clk/mediatek/clk-mt7629.c new file mode 100644 index 000000000..01ee45fcd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7629.c @@ -0,0 +1,699 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2018 MediaTek Inc. + * Author: Wenzhen Yu <Wenzhen Yu@mediatek.com> + * Ryder Lee <ryder.lee@mediatek.com> + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt7629-clk.h> + +#define MT7629_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7629_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table, _parent_name) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT7629_RST_BAR, \ + .fmax = MT7629_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL, "clk20m") + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &apmixed_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_INFRA(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static DEFINE_SPINLOCK(mt7629_clk_lock); + +static const char * const axi_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7", + "dmpll_ck" +}; + +static const char * const mem_parents[] = { + "clkxtal", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] = { + "clkxtal", + "syspll1_d8" +}; + +static const char * const eth_parents[] = { + "clkxtal", + "syspll1_d2", + "univpll1_d2", + "syspll1_d4", + "univpll_d5", + "sgmiipll_d2", + "univpll_d7", + "dmpll_ck" +}; + +static const char * const pwm_parents[] = { + "clkxtal", + "univpll2_d4" +}; + +static const char * const f10m_ref_parents[] = { + "clkxtal", + "sgmiipll_d2" +}; + +static const char * const nfi_infra_parents[] = { + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "clkxtal", + "univpll2_d8", + "univpll3_d4", + "syspll1_d8", + "univpll1_d8", + "syspll4_d2", + "syspll2_d4", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4", + "syspll_d7" +}; + +static const char * const flash_parents[] = { + "clkxtal", + "univpll_d80_d4", + "syspll2_d8", + "syspll3_d4", + "univpll3_d4", + "univpll1_d8", + "syspll2_d4", + "univpll2_d4" +}; + +static const char * const uart_parents[] = { + "clkxtal", + "univpll2_d8" +}; + +static const char * const spi0_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll2_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const spi1_parents[] = { + "clkxtal", + "syspll3_d2", + "clkxtal", + "syspll4_d4", + "syspll4_d2", + "univpll2_d4", + "univpll1_d8", + "clkxtal" +}; + +static const char * const msdc30_0_parents[] = { + "clkxtal", + "univpll2_d16", + "univ48m" +}; + +static const char * const msdc30_1_parents[] = { + "clkxtal", + "univpll2_d16", + "univ48m", + "syspll2_d4", + "univpll2_d4", + "syspll_d7", + "syspll2_d2", + "univpll2_d2" +}; + +static const char * const ap2wbmcu_parents[] = { + "clkxtal", + "syspll1_d2", + "univ48m", + "syspll1_d8", + "univpll2_d4", + "syspll_d7", + "syspll2_d2", + "univpll2_d2" +}; + +static const char * const audio_parents[] = { + "clkxtal", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clkxtal", + "syspll1_d4", + "syspll4_d2", + "dmpll_d4" +}; + +static const char * const pmicspi_parents[] = { + "clkxtal", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "clkxtal", + "univpll2_d4", + "dmpll_d8" +}; + +static const char * const scp_parents[] = { + "clkxtal", + "syspll1_d8", + "univpll2_d2", + "univpll2_d4" +}; + +static const char * const atb_parents[] = { + "clkxtal", + "syspll1_d2", + "syspll_d5" +}; + +static const char * const hif_parents[] = { + "clkxtal", + "syspll1_d2", + "univpll1_d2", + "syspll1_d4", + "univpll_d5", + "clk_null", + "univpll_d7" +}; + +static const char * const sata_parents[] = { + "clkxtal", + "univpll2_d4" +}; + +static const char * const usb20_parents[] = { + "clkxtal", + "univpll3_d4", + "syspll1_d8" +}; + +static const char * const aud1_parents[] = { + "clkxtal" +}; + +static const char * const irrx_parents[] = { + "clkxtal", + "syspll4_d16" +}; + +static const char * const crypto_parents[] = { + "clkxtal", + "univpll_d3", + "univpll1_d2", + "syspll1_d2", + "univpll_d5", + "syspll_d5", + "univpll2_d2", + "syspll_d2" +}; + +static const char * const gpt10m_parents[] = { + "clkxtal", + "clkxtal_d4" +}; + +static const char * const peribus_ck_parents[] = { + "syspll1_d8", + "syspll1_d4" +}; + +static const char * const infra_mux1_parents[] = { + "clkxtal", + "armpll", + "main_core_en", + "armpll" +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x10, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0xC, + .clr_ofs = 0x14, + .sta_ofs = 0x1C, +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0, + 0, 21, 0x0204, 24, 0, 0x0204, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0210, 0x021C, 0, + HAVE_RST_BAR, 21, 0x0214, 24, 0, 0x0214, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0220, 0x022C, 0, + HAVE_RST_BAR, 7, 0x0224, 24, 0, 0x0224, 14), + PLL(CLK_APMIXED_ETH1PLL, "eth1pll", 0x0300, 0x0310, 0, + 0, 21, 0x0300, 1, 0, 0x0304, 0), + PLL(CLK_APMIXED_ETH2PLL, "eth2pll", 0x0314, 0x0320, 0, + 0, 21, 0x0314, 1, 0, 0x0318, 0), + PLL(CLK_APMIXED_SGMIPLL, "sgmipll", 0x0358, 0x0368, 0, + 0, 21, 0x0358, 1, 0, 0x035C, 0), +}; + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_MAIN_CORE_EN, "main_core_en", "mainpll", 5), +}; + +static const struct mtk_gate infra_clks[] = { + GATE_INFRA(CLK_INFRA_DBGCLK_PD, "infra_dbgclk_pd", "hd_faxi", 0), + GATE_INFRA(CLK_INFRA_TRNG_PD, "infra_trng_pd", "hd_faxi", 2), + GATE_INFRA(CLK_INFRA_DEVAPC_PD, "infra_devapc_pd", "hd_faxi", 4), + GATE_INFRA(CLK_INFRA_APXGPT_PD, "infra_apxgpt_pd", "infrao_10m", 18), + GATE_INFRA(CLK_INFRA_SEJ_PD, "infra_sej_pd", "infrao_10m", 19), +}; + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_TO_U2_PHY, "to_u2_phy", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_TO_U2_PHY_1P, "to_u2_phy_1p", "clkxtal", + 31250000), + FIXED_CLK(CLK_TOP_PCIE0_PIPE_EN, "pcie0_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_PCIE1_PIPE_EN, "pcie1_pipe_en", "clkxtal", + 125000000), + FIXED_CLK(CLK_TOP_SSUSB_TX250M, "ssusb_tx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_EQ_RX250M, "ssusb_eq_rx250m", "clkxtal", + 250000000), + FIXED_CLK(CLK_TOP_SSUSB_CDR_REF, "ssusb_cdr_ref", "clkxtal", + 33333333), + FIXED_CLK(CLK_TOP_SSUSB_CDR_FB, "ssusb_cdr_fb", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_ASIC, "sata_asic", "clkxtal", + 50000000), + FIXED_CLK(CLK_TOP_SATA_RBC, "sata_rbc", "clkxtal", + 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_TO_USB3_SYS, "to_usb3_sys", "eth1pll", 1, 4), + FACTOR(CLK_TOP_P1_1MHZ, "p1_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_4MHZ, "free_run_4mhz", "eth1pll", 1, 125), + FACTOR(CLK_TOP_P0_1MHZ, "p0_1mhz", "eth1pll", 1, 500), + FACTOR(CLK_TOP_ETH_500M, "eth_500m", "eth1pll", 1, 1), + FACTOR(CLK_TOP_TXCLK_SRC_PRE, "txclk_src_pre", "sgmiipll_d2", 1, 1), + FACTOR(CLK_TOP_RTC, "rtc", "clkxtal", 1, 1024), + FACTOR(CLK_TOP_PWM_QTR_26M, "pwm_qtr_26m", "clkxtal", 1, 1), + FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "cpum_tck", 1, 1), + FACTOR(CLK_TOP_TO_USB3_DA_TOP, "to_usb3_da_top", "clkxtal", 1, 1), + FACTOR(CLK_TOP_MEMPLL, "mempll", "clkxtal", 32, 1), + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "mempll", 1, 4), + FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "mempll", 1, 8), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll", 1, 32), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll", 1, 6), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), + FACTOR(CLK_TOP_SYSPLL4_D16, "syspll4_d16", "mainpll", 1, 112), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL2_D16, "univpll2_d16", "univpll", 1, 48), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), + FACTOR(CLK_TOP_UNIVPLL3_D16, "univpll3_d16", "univpll", 1, 80), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_D80_D4, "univpll_d80_d4", "univpll", 1, 320), + FACTOR(CLK_TOP_UNIV48M, "univ48m", "univpll", 1, 25), + FACTOR(CLK_TOP_SGMIIPLL_D2, "sgmiipll_d2", "sgmipll", 1, 2), + FACTOR(CLK_TOP_CLKXTAL_D4, "clkxtal_d4", "clkxtal", 1, 4), + FACTOR(CLK_TOP_HD_FAXI, "hd_faxi", "axi_sel", 1, 1), + FACTOR(CLK_TOP_FAXI, "faxi", "axi_sel", 1, 1), + FACTOR(CLK_TOP_F_FAUD_INTBUS, "f_faud_intbus", "aud_intbus_sel", 1, 1), + FACTOR(CLK_TOP_AP2WBHIF_HCLK, "ap2wbhif_hclk", "syspll1_d8", 1, 1), + FACTOR(CLK_TOP_10M_INFRAO, "infrao_10m", "gpt10m_sel", 1, 1), + FACTOR(CLK_TOP_MSDC30_1, "msdc30_1", "msdc30_1_sel", 1, 1), + FACTOR(CLK_TOP_SPI, "spi", "spi0_sel", 1, 1), + FACTOR(CLK_TOP_SF, "sf", "nfi_infra_sel", 1, 1), + FACTOR(CLK_TOP_FLASH, "flash", "flash_sel", 1, 1), + FACTOR(CLK_TOP_TO_USB3_REF, "to_usb3_ref", "sata_sel", 1, 4), + FACTOR(CLK_TOP_TO_USB3_MCU, "to_usb3_mcu", "axi_sel", 1, 1), + FACTOR(CLK_TOP_TO_USB3_DMA, "to_usb3_dma", "hif_sel", 1, 1), + FACTOR(CLK_TOP_FROM_TOP_AHB, "from_top_ahb", "axi_sel", 1, 1), + FACTOR(CLK_TOP_FROM_TOP_AXI, "from_top_axi", "hif_sel", 1, 1), + FACTOR(CLK_TOP_PCIE1_MAC_EN, "pcie1_mac_en", "sata_sel", 1, 1), + FACTOR(CLK_TOP_PCIE0_MAC_EN, "pcie0_mac_en", "sata_sel", 1, 1), +}; + +static const struct mtk_gate peri_clks[] = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_PWM1_PD, "peri_pwm1_pd", "pwm_qtr_26m", 2), + GATE_PERI0(CLK_PERI_PWM2_PD, "peri_pwm2_pd", "pwm_qtr_26m", 3), + GATE_PERI0(CLK_PERI_PWM3_PD, "peri_pwm3_pd", "pwm_qtr_26m", 4), + GATE_PERI0(CLK_PERI_PWM4_PD, "peri_pwm4_pd", "pwm_qtr_26m", 5), + GATE_PERI0(CLK_PERI_PWM5_PD, "peri_pwm5_pd", "pwm_qtr_26m", 6), + GATE_PERI0(CLK_PERI_PWM6_PD, "peri_pwm6_pd", "pwm_qtr_26m", 7), + GATE_PERI0(CLK_PERI_PWM7_PD, "peri_pwm7_pd", "pwm_qtr_26m", 8), + GATE_PERI0(CLK_PERI_PWM_PD, "peri_pwm_pd", "pwm_qtr_26m", 9), + GATE_PERI0(CLK_PERI_AP_DMA_PD, "peri_ap_dma_pd", "faxi", 12), + GATE_PERI0(CLK_PERI_MSDC30_1_PD, "peri_msdc30_1", "msdc30_1", 14), + GATE_PERI0(CLK_PERI_UART0_PD, "peri_uart0_pd", "faxi", 17), + GATE_PERI0(CLK_PERI_UART1_PD, "peri_uart1_pd", "faxi", 18), + GATE_PERI0(CLK_PERI_UART2_PD, "peri_uart2_pd", "faxi", 19), + GATE_PERI0(CLK_PERI_UART3_PD, "peri_uart3_pd", "faxi", 20), + GATE_PERI0(CLK_PERI_BTIF_PD, "peri_btif_pd", "faxi", 22), + GATE_PERI0(CLK_PERI_I2C0_PD, "peri_i2c0_pd", "faxi", 23), + GATE_PERI0(CLK_PERI_SPI0_PD, "peri_spi0_pd", "spi", 28), + GATE_PERI0(CLK_PERI_SNFI_PD, "peri_snfi_pd", "sf", 29), + GATE_PERI0(CLK_PERI_NFI_PD, "peri_nfi_pd", "faxi", 30), + GATE_PERI0(CLK_PERI_NFIECC_PD, "peri_nfiecc_pd", "faxi", 31), + /* PERI1 */ + GATE_PERI1(CLK_PERI_FLASH_PD, "peri_flash_pd", "flash", 1), +}; + +static struct mtk_composite infra_muxes[] = { + /* INFRA_TOPCKGEN_CKMUXSEL */ + MUX(CLK_INFRA_MUX1_SEL, "infra_mux1_sel", infra_mux1_parents, 0x000, + 2, 2), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x040, 0, 3, 7), + MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, + 0x040, 8, 1, 15), + MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x040, 16, 1, 23), + MUX_GATE(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 24, 3, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x050, 0, 2, 7), + MUX_GATE(CLK_TOP_F10M_REF_SEL, "f10m_ref_sel", f10m_ref_parents, + 0x050, 8, 1, 15), + MUX_GATE(CLK_TOP_NFI_INFRA_SEL, "nfi_infra_sel", nfi_infra_parents, + 0x050, 16, 4, 23), + MUX_GATE(CLK_TOP_FLASH_SEL, "flash_sel", flash_parents, + 0x050, 24, 3, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, + 0x060, 0, 1, 7), + MUX_GATE(CLK_TOP_SPI0_SEL, "spi0_sel", spi0_parents, + 0x060, 8, 3, 15), + MUX_GATE(CLK_TOP_SPI1_SEL, "spi1_sel", spi1_parents, + 0x060, 16, 3, 23), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", uart_parents, + 0x060, 24, 3, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_parents, + 0x070, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, + 0x070, 8, 3, 15), + MUX_GATE(CLK_TOP_AP2WBMCU_SEL, "ap2wbmcu_sel", ap2wbmcu_parents, + 0x070, 16, 3, 23), + MUX_GATE(CLK_TOP_AP2WBHIF_SEL, "ap2wbhif_sel", ap2wbmcu_parents, + 0x070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + 0x080, 0, 2, 7), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x080, 8, 2, 15), + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x080, 16, 3, 23), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, + 0x080, 24, 2, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, + 0x090, 0, 2, 7), + MUX_GATE(CLK_TOP_HIF_SEL, "hif_sel", hif_parents, + 0x090, 8, 3, 15), + MUX_GATE(CLK_TOP_SATA_SEL, "sata_sel", sata_parents, + 0x090, 16, 1, 23), + MUX_GATE(CLK_TOP_U2_SEL, "usb20_sel", usb20_parents, + 0x090, 24, 2, 31), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x0A0, 0, 1, 7), + MUX_GATE(CLK_TOP_AUD2_SEL, "aud2_sel", aud1_parents, + 0x0A0, 8, 1, 15), + MUX_GATE(CLK_TOP_IRRX_SEL, "irrx_sel", irrx_parents, + 0x0A0, 16, 1, 23), + MUX_GATE(CLK_TOP_IRTX_SEL, "irtx_sel", irrx_parents, + 0x0A0, 24, 1, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_SATA_MCU_SEL, "sata_mcu_sel", scp_parents, + 0x0B0, 0, 2, 7), + MUX_GATE(CLK_TOP_PCIE0_MCU_SEL, "pcie0_mcu_sel", scp_parents, + 0x0B0, 8, 2, 15), + MUX_GATE(CLK_TOP_PCIE1_MCU_SEL, "pcie1_mcu_sel", scp_parents, + 0x0B0, 16, 2, 23), + MUX_GATE(CLK_TOP_SSUSB_MCU_SEL, "ssusb_mcu_sel", scp_parents, + 0x0B0, 24, 2, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_CRYPTO_SEL, "crypto_sel", crypto_parents, + 0x0C0, 0, 3, 7), + MUX_GATE(CLK_TOP_SGMII_REF_1_SEL, "sgmii_ref_1_sel", f10m_ref_parents, + 0x0C0, 8, 1, 15), + MUX_GATE(CLK_TOP_10M_SEL, "gpt10m_sel", gpt10m_parents, + 0x0C0, 16, 1, 23), +}; + +static struct mtk_composite peri_muxes[] = { + /* PERI_GLOBALCON_CKSEL */ + MUX(CLK_PERIBUS_SEL, "peribus_ck_sel", peribus_ck_parents, 0x05C, 0, 1), +}; + +static int mtk_topckgen_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), + base, &mt7629_clk_lock, clk_data); + + clk_prepare_enable(clk_data->hws[CLK_TOP_AXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_MEM_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DDRPHYCFG_SEL]->clk); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int mtk_infrasys_init(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + mtk_clk_register_cpumuxes(node, infra_muxes, ARRAY_SIZE(infra_muxes), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + clk_data); +} + +static int mtk_pericfg_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + struct device_node *node = pdev->dev.of_node; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + mtk_clk_register_composites(peri_muxes, ARRAY_SIZE(peri_muxes), base, + &mt7629_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + return r; + + clk_prepare_enable(clk_data->hws[CLK_PERI_UART0_PD]->clk); + + return 0; +} + +static int mtk_apmixedsys_init(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), + clk_data); + + mtk_clk_register_gates(node, apmixed_clks, + ARRAY_SIZE(apmixed_clks), clk_data); + + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); + clk_prepare_enable(clk_data->hws[CLK_APMIXED_MAIN_CORE_EN]->clk); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + + +static const struct of_device_id of_match_clk_mt7629[] = { + { + .compatible = "mediatek,mt7629-apmixedsys", + .data = mtk_apmixedsys_init, + }, { + .compatible = "mediatek,mt7629-infracfg", + .data = mtk_infrasys_init, + }, { + .compatible = "mediatek,mt7629-topckgen", + .data = mtk_topckgen_init, + }, { + .compatible = "mediatek,mt7629-pericfg", + .data = mtk_pericfg_init, + }, { + /* sentinel */ + } +}; + +static int clk_mt7629_probe(struct platform_device *pdev) +{ + int (*clk_init)(struct platform_device *); + int r; + + clk_init = of_device_get_match_data(&pdev->dev); + if (!clk_init) + return -EINVAL; + + r = clk_init(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt7629_drv = { + .probe = clk_mt7629_probe, + .driver = { + .name = "clk-mt7629", + .of_match_table = of_match_clk_mt7629, + }, +}; + +static int clk_mt7629_init(void) +{ + return platform_driver_register(&clk_mt7629_drv); +} + +arch_initcall(clk_mt7629_init); diff --git a/drivers/clk/mediatek/clk-mt7986-apmixed.c b/drivers/clk/mediatek/clk-mt7986-apmixed.c new file mode 100644 index 000000000..62080ee4d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7986-apmixed.c @@ -0,0 +1,102 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih <sam.shih@mediatek.com> + * Author: Wenzhen Yu <wenzhen.yu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt7986-clk.h> +#include <linux/clk.h> + +#define MT7986_PLL_FMAX (2500UL * MHZ) +#define CON0_MT7986_RST_BAR BIT(27) + +#define PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + _div_table, _parent_name) \ + { \ + .id = _id, .name = _name, .reg = _reg, .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, .flags = _flags, \ + .rst_bar_mask = CON0_MT7986_RST_BAR, .fmax = MT7986_PLL_FMAX, \ + .pcwbits = _pcwbits, .pd_reg = _pd_reg, .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, .div_table = _div_table, \ + .parent_name = _parent_name, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, \ + _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) \ + PLL_xtal(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, NULL, \ + "clkxtal") + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0200, 0x020C, 0x0, 0, 32, + 0x0200, 4, 0, 0x0204, 0), + PLL(CLK_APMIXED_NET2PLL, "net2pll", 0x0210, 0x021C, 0x0, 0, 32, + 0x0210, 4, 0, 0x0214, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0220, 0x022C, 0x0, 0, 32, + 0x0220, 4, 0, 0x0224, 0), + PLL(CLK_APMIXED_SGMPLL, "sgmpll", 0x0230, 0x023c, 0x0, 0, 32, + 0x0230, 4, 0, 0x0234, 0), + PLL(CLK_APMIXED_WEDMCUPLL, "wedmcupll", 0x0240, 0x024c, 0x0, 0, + 32, 0x0240, 4, 0, 0x0244, 0), + PLL(CLK_APMIXED_NET1PLL, "net1pll", 0x0250, 0x025c, 0x0, 0, 32, + 0x0250, 4, 0, 0x0254, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x0260, 0x0270, 0x0, 0, 32, 0x0260, + 4, 0, 0x0264, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0278, 0x0288, 0x0, 0, 32, + 0x0278, 4, 0, 0x027c, 0), +}; + +static const struct of_device_id of_match_clk_mt7986_apmixed[] = { + { .compatible = "mediatek,mt7986-apmixedsys", }, + {} +}; + +static int clk_mt7986_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(plls)); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + clk_prepare_enable(clk_data->hws[CLK_APMIXED_ARMPLL]->clk); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_apmixed_data; + } + return r; + +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static struct platform_driver clk_mt7986_apmixed_drv = { + .probe = clk_mt7986_apmixed_probe, + .driver = { + .name = "clk-mt7986-apmixed", + .of_match_table = of_match_clk_mt7986_apmixed, + }, +}; +builtin_platform_driver(clk_mt7986_apmixed_drv); diff --git a/drivers/clk/mediatek/clk-mt7986-eth.c b/drivers/clk/mediatek/clk-mt7986-eth.c new file mode 100644 index 000000000..c21e1d672 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7986-eth.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih <sam.shih@mediatek.com> + * Author: Wenzhen Yu <wenzhen.yu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt7986-clk.h> + +static const struct mtk_gate_regs sgmii0_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &sgmii0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate sgmii0_clks[] __initconst = { + GATE_SGMII0(CLK_SGMII0_TX250M_EN, "sgmii0_tx250m_en", "top_xtal", 2), + GATE_SGMII0(CLK_SGMII0_RX250M_EN, "sgmii0_rx250m_en", "top_xtal", 3), + GATE_SGMII0(CLK_SGMII0_CDR_REF, "sgmii0_cdr_ref", "top_xtal", 4), + GATE_SGMII0(CLK_SGMII0_CDR_FB, "sgmii0_cdr_fb", "top_xtal", 5), +}; + +static const struct mtk_gate_regs sgmii1_cg_regs = { + .set_ofs = 0xe4, + .clr_ofs = 0xe4, + .sta_ofs = 0xe4, +}; + +#define GATE_SGMII1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &sgmii1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate sgmii1_clks[] __initconst = { + GATE_SGMII1(CLK_SGMII1_TX250M_EN, "sgmii1_tx250m_en", "top_xtal", 2), + GATE_SGMII1(CLK_SGMII1_RX250M_EN, "sgmii1_rx250m_en", "top_xtal", 3), + GATE_SGMII1(CLK_SGMII1_CDR_REF, "sgmii1_cdr_ref", "top_xtal", 4), + GATE_SGMII1(CLK_SGMII1_CDR_FB, "sgmii1_cdr_fb", "top_xtal", 5), +}; + +static const struct mtk_gate_regs eth_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x30, + .sta_ofs = 0x30, +}; + +#define GATE_ETH(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, ð_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate eth_clks[] __initconst = { + GATE_ETH(CLK_ETH_FE_EN, "eth_fe_en", "netsys_2x_sel", 6), + GATE_ETH(CLK_ETH_GP2_EN, "eth_gp2_en", "sgm_325m_sel", 7), + GATE_ETH(CLK_ETH_GP1_EN, "eth_gp1_en", "sgm_325m_sel", 8), + GATE_ETH(CLK_ETH_WOCPU1_EN, "eth_wocpu1_en", "netsys_mcu_sel", 14), + GATE_ETH(CLK_ETH_WOCPU0_EN, "eth_wocpu0_en", "netsys_mcu_sel", 15), +}; + +static void __init mtk_sgmiisys_0_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii0_clks)); + + mtk_clk_register_gates(node, sgmii0_clks, ARRAY_SIZE(sgmii0_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_sgmiisys_0, "mediatek,mt7986-sgmiisys_0", + mtk_sgmiisys_0_init); + +static void __init mtk_sgmiisys_1_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(sgmii1_clks)); + + mtk_clk_register_gates(node, sgmii1_clks, ARRAY_SIZE(sgmii1_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_sgmiisys_1, "mediatek,mt7986-sgmiisys_1", + mtk_sgmiisys_1_init); + +static void __init mtk_ethsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(ARRAY_SIZE(eth_clks)); + + mtk_clk_register_gates(node, eth_clks, ARRAY_SIZE(eth_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_ethsys, "mediatek,mt7986-ethsys", mtk_ethsys_init); diff --git a/drivers/clk/mediatek/clk-mt7986-infracfg.c b/drivers/clk/mediatek/clk-mt7986-infracfg.c new file mode 100644 index 000000000..74e68a719 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7986-infracfg.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih <sam.shih@mediatek.com> + * Author: Wenzhen Yu <wenzhen.yu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" + +#include <dt-bindings/clock/mt7986-clk.h> +#include <linux/clk.h> + +static DEFINE_SPINLOCK(mt7986_clk_lock); + +static const struct mtk_fixed_factor infra_divs[] = { + FACTOR(CLK_INFRA_SYSAXI_D2, "infra_sysaxi_d2", "sysaxi_sel", 1, 2), +}; + +static const char *const infra_uart_parent[] __initconst = { "csw_f26m_sel", + "uart_sel" }; + +static const char *const infra_spi_parents[] __initconst = { "i2c_sel", + "spi_sel" }; + +static const char *const infra_pwm_bsel_parents[] __initconst = { + "top_rtc_32p7k", "csw_f26m_sel", "infra_sysaxi_d2", "pwm_sel" +}; + +static const char *const infra_pcie_parents[] __initconst = { + "top_rtc_32p7k", "csw_f26m_sel", "top_xtal", "pextp_tl_ck_sel" +}; + +static const struct mtk_mux infra_muxes[] = { + /* MODULE_CLK_SEL_0 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART0_SEL, "infra_uart0_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 0, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART1_SEL, "infra_uart1_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 1, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_UART2_SEL, "infra_uart2_sel", + infra_uart_parent, 0x0018, 0x0010, 0x0014, 2, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI0_SEL, "infra_spi0_sel", + infra_spi_parents, 0x0018, 0x0010, 0x0014, 4, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_SPI1_SEL, "infra_spi1_sel", + infra_spi_parents, 0x0018, 0x0010, 0x0014, 5, 1, + -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM1_SEL, "infra_pwm1_sel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 9, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM2_SEL, "infra_pwm2_sel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 11, + 2, -1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PWM_BSEL, "infra_pwm_bsel", + infra_pwm_bsel_parents, 0x0018, 0x0010, 0x0014, 13, + 2, -1, -1, -1), + /* MODULE_CLK_SEL_1 */ + MUX_GATE_CLR_SET_UPD(CLK_INFRA_PCIE_SEL, "infra_pcie_sel", + infra_pcie_parents, 0x0028, 0x0020, 0x0024, 0, 2, + -1, -1, -1), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x40, + .clr_ofs = 0x44, + .sta_ofs = 0x48, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x50, + .clr_ofs = 0x54, + .sta_ofs = 0x58, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0x60, + .clr_ofs = 0x64, + .sta_ofs = 0x68, +}; + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_GPT_STA, "infra_gpt_sta", "infra_sysaxi_d2", 0), + GATE_INFRA0(CLK_INFRA_PWM_HCK, "infra_pwm_hck", "infra_sysaxi_d2", 1), + GATE_INFRA0(CLK_INFRA_PWM_STA, "infra_pwm_sta", "infra_pwm_bsel", 2), + GATE_INFRA0(CLK_INFRA_PWM1_CK, "infra_pwm1", "infra_pwm1_sel", 3), + GATE_INFRA0(CLK_INFRA_PWM2_CK, "infra_pwm2", "infra_pwm2_sel", 4), + GATE_INFRA0(CLK_INFRA_CQ_DMA_CK, "infra_cq_dma", "sysaxi_sel", 6), + GATE_INFRA0(CLK_INFRA_EIP97_CK, "infra_eip97", "eip_b_sel", 7), + GATE_INFRA0(CLK_INFRA_AUD_BUS_CK, "infra_aud_bus", "sysaxi_sel", 8), + GATE_INFRA0(CLK_INFRA_AUD_26M_CK, "infra_aud_26m", "csw_f26m_sel", 9), + GATE_INFRA0(CLK_INFRA_AUD_L_CK, "infra_aud_l", "aud_l_sel", 10), + GATE_INFRA0(CLK_INFRA_AUD_AUD_CK, "infra_aud_aud", "a1sys_sel", 11), + GATE_INFRA0(CLK_INFRA_AUD_EG2_CK, "infra_aud_eg2", "a_tuner_sel", 13), + GATE_INFRA0(CLK_INFRA_DRAMC_26M_CK, "infra_dramc_26m", "csw_f26m_sel", + 14), + GATE_INFRA0(CLK_INFRA_DBG_CK, "infra_dbg", "infra_sysaxi_d2", 15), + GATE_INFRA0(CLK_INFRA_AP_DMA_CK, "infra_ap_dma", "infra_sysaxi_d2", 16), + GATE_INFRA0(CLK_INFRA_SEJ_CK, "infra_sej", "infra_sysaxi_d2", 24), + GATE_INFRA0(CLK_INFRA_SEJ_13M_CK, "infra_sej_13m", "csw_f26m_sel", 25), + GATE_INFRA0(CLK_INFRA_TRNG_CK, "infra_trng", "sysaxi_sel", 26), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_THERM_CK, "infra_therm", "csw_f26m_sel", 0), + GATE_INFRA1(CLK_INFRA_I2C0_CK, "infra_i2c0", "i2c_sel", 1), + GATE_INFRA1(CLK_INFRA_UART0_CK, "infra_uart0", "infra_uart0_sel", 2), + GATE_INFRA1(CLK_INFRA_UART1_CK, "infra_uart1", "infra_uart1_sel", 3), + GATE_INFRA1(CLK_INFRA_UART2_CK, "infra_uart2", "infra_uart2_sel", 4), + GATE_INFRA1(CLK_INFRA_NFI1_CK, "infra_nfi1", "nfi1x_sel", 8), + GATE_INFRA1(CLK_INFRA_SPINFI1_CK, "infra_spinfi1", "spinfi_sel", 9), + GATE_INFRA1(CLK_INFRA_NFI_HCK_CK, "infra_nfi_hck", "infra_sysaxi_d2", + 10), + GATE_INFRA1(CLK_INFRA_SPI0_CK, "infra_spi0", "infra_spi0_sel", 11), + GATE_INFRA1(CLK_INFRA_SPI1_CK, "infra_spi1", "infra_spi1_sel", 12), + GATE_INFRA1(CLK_INFRA_SPI0_HCK_CK, "infra_spi0_hck", "infra_sysaxi_d2", + 13), + GATE_INFRA1(CLK_INFRA_SPI1_HCK_CK, "infra_spi1_hck", "infra_sysaxi_d2", + 14), + GATE_INFRA1(CLK_INFRA_FRTC_CK, "infra_frtc", "top_rtc_32k", 15), + GATE_INFRA1(CLK_INFRA_MSDC_CK, "infra_msdc", "emmc_416m_sel", 16), + GATE_INFRA1(CLK_INFRA_MSDC_HCK_CK, "infra_msdc_hck", "emmc_250m_sel", + 17), + GATE_INFRA1(CLK_INFRA_MSDC_133M_CK, "infra_msdc_133m", "sysaxi_sel", + 18), + GATE_INFRA1(CLK_INFRA_MSDC_66M_CK, "infra_msdc_66m", "infra_sysaxi_d2", + 19), + GATE_INFRA1(CLK_INFRA_ADC_26M_CK, "infra_adc_26m", "infra_adc_frc", 20), + GATE_INFRA1(CLK_INFRA_ADC_FRC_CK, "infra_adc_frc", "csw_f26m_sel", 21), + GATE_INFRA1(CLK_INFRA_FBIST2FPC_CK, "infra_fbist2fpc", "nfi1x_sel", 23), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_IUSB_133_CK, "infra_iusb_133", "sysaxi_sel", 0), + GATE_INFRA2(CLK_INFRA_IUSB_66M_CK, "infra_iusb_66m", "infra_sysaxi_d2", + 1), + GATE_INFRA2(CLK_INFRA_IUSB_SYS_CK, "infra_iusb_sys", "u2u3_sys_sel", 2), + GATE_INFRA2(CLK_INFRA_IUSB_CK, "infra_iusb", "u2u3_sel", 3), + GATE_INFRA2(CLK_INFRA_IPCIE_CK, "infra_ipcie", "pextp_tl_ck_sel", 12), + GATE_INFRA2(CLK_INFRA_IPCIE_PIPE_CK, "infra_ipcie_pipe", "top_xtal", + 13), + GATE_INFRA2(CLK_INFRA_IPCIER_CK, "infra_ipcier", "csw_f26m_sel", 14), + GATE_INFRA2(CLK_INFRA_IPCIEB_CK, "infra_ipcieb", "sysaxi_sel", 15), +}; + +static int clk_mt7986_infracfg_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(infra_divs) + ARRAY_SIZE(infra_muxes) + + ARRAY_SIZE(infra_clks); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); + mtk_clk_register_muxes(infra_muxes, ARRAY_SIZE(infra_muxes), node, + &mt7986_clk_lock, clk_data); + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_infracfg_data; + } + return r; + +free_infracfg_data: + mtk_free_clk_data(clk_data); + return r; + +} + +static const struct of_device_id of_match_clk_mt7986_infracfg[] = { + { .compatible = "mediatek,mt7986-infracfg", }, + {} +}; + +static struct platform_driver clk_mt7986_infracfg_drv = { + .probe = clk_mt7986_infracfg_probe, + .driver = { + .name = "clk-mt7986-infracfg", + .of_match_table = of_match_clk_mt7986_infracfg, + }, +}; +builtin_platform_driver(clk_mt7986_infracfg_drv); diff --git a/drivers/clk/mediatek/clk-mt7986-topckgen.c b/drivers/clk/mediatek/clk-mt7986-topckgen.c new file mode 100644 index 000000000..de5121cf2 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt7986-topckgen.c @@ -0,0 +1,342 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2021 MediaTek Inc. + * Author: Sam Shih <sam.shih@mediatek.com> + * Author: Wenzhen Yu <wenzhen.yu@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include "clk-mtk.h" +#include "clk-gate.h" +#include "clk-mux.h" + +#include <dt-bindings/clock/mt7986-clk.h> +#include <linux/clk.h> + +static DEFINE_SPINLOCK(mt7986_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_XTAL, "top_xtal", "clkxtal", 40000000), + FIXED_CLK(CLK_TOP_JTAG, "top_jtag", "clkxtal", 50000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + /* XTAL */ + FACTOR(CLK_TOP_XTAL_D2, "top_xtal_d2", "top_xtal", 1, 2), + FACTOR(CLK_TOP_RTC_32K, "top_rtc_32k", "top_xtal", 1, 1250), + FACTOR(CLK_TOP_RTC_32P7K, "top_rtc_32p7k", "top_xtal", 1, 1220), + /* MPLL */ + FACTOR(CLK_TOP_MPLL_D2, "top_mpll_d2", "mpll", 1, 2), + FACTOR(CLK_TOP_MPLL_D4, "top_mpll_d4", "mpll", 1, 4), + FACTOR(CLK_TOP_MPLL_D8, "top_mpll_d8", "mpll", 1, 8), + FACTOR(CLK_TOP_MPLL_D8_D2, "top_mpll_d8_d2", "mpll", 1, 16), + FACTOR(CLK_TOP_MPLL_D3_D2, "top_mpll_d3_d2", "mpll", 1, 6), + /* MMPLL */ + FACTOR(CLK_TOP_MMPLL_D2, "top_mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_D4, "top_mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D8, "top_mmpll_d8", "mmpll", 1, 8), + FACTOR(CLK_TOP_MMPLL_D8_D2, "top_mmpll_d8_d2", "mmpll", 1, 16), + FACTOR(CLK_TOP_MMPLL_D3_D8, "top_mmpll_d3_d8", "mmpll", 1, 24), + FACTOR(CLK_TOP_MMPLL_U2PHY, "top_mmpll_u2phy", "mmpll", 1, 30), + /* APLL2 */ + FACTOR(CLK_TOP_APLL2_D4, "top_apll2_d4", "apll2", 1, 4), + /* NET1PLL */ + FACTOR(CLK_TOP_NET1PLL_D4, "top_net1pll_d4", "net1pll", 1, 4), + FACTOR(CLK_TOP_NET1PLL_D5, "top_net1pll_d5", "net1pll", 1, 5), + FACTOR(CLK_TOP_NET1PLL_D5_D2, "top_net1pll_d5_d2", "net1pll", 1, 10), + FACTOR(CLK_TOP_NET1PLL_D5_D4, "top_net1pll_d5_d4", "net1pll", 1, 20), + FACTOR(CLK_TOP_NET1PLL_D8_D2, "top_net1pll_d8_d2", "net1pll", 1, 16), + FACTOR(CLK_TOP_NET1PLL_D8_D4, "top_net1pll_d8_d4", "net1pll", 1, 32), + /* NET2PLL */ + FACTOR(CLK_TOP_NET2PLL_D4, "top_net2pll_d4", "net2pll", 1, 4), + FACTOR(CLK_TOP_NET2PLL_D4_D2, "top_net2pll_d4_d2", "net2pll", 1, 8), + FACTOR(CLK_TOP_NET2PLL_D3_D2, "top_net2pll_d3_d2", "net2pll", 1, 2), + /* WEDMCUPLL */ + FACTOR(CLK_TOP_WEDMCUPLL_D5_D2, "top_wedmcupll_d5_d2", "wedmcupll", 1, + 10), +}; + +static const char *const nfi1x_parents[] __initconst = { "top_xtal", + "top_mmpll_d8", + "top_net1pll_d8_d2", + "top_net2pll_d3_d2", + "top_mpll_d4", + "top_mmpll_d8_d2", + "top_wedmcupll_d5_d2", + "top_mpll_d8" }; + +static const char *const spinfi_parents[] __initconst = { + "top_xtal_d2", "top_xtal", "top_net1pll_d5_d4", + "top_mpll_d4", "top_mmpll_d8_d2", "top_wedmcupll_d5_d2", + "top_mmpll_d3_d8", "top_mpll_d8" +}; + +static const char *const spi_parents[] __initconst = { + "top_xtal", "top_mpll_d2", "top_mmpll_d8", + "top_net1pll_d8_d2", "top_net2pll_d3_d2", "top_net1pll_d5_d4", + "top_mpll_d4", "top_wedmcupll_d5_d2" +}; + +static const char *const uart_parents[] __initconst = { "top_xtal", + "top_mpll_d8", + "top_mpll_d8_d2" }; + +static const char *const pwm_parents[] __initconst = { + "top_xtal", "top_net1pll_d8_d2", "top_net1pll_d5_d4", "top_mpll_d4" +}; + +static const char *const i2c_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4", "top_mpll_d4", "top_net1pll_d8_d4" +}; + +static const char *const pextp_tl_ck_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4", "top_net2pll_d4_d2", "top_rtc_32k" +}; + +static const char *const emmc_250m_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d2" +}; + +static const char *const emmc_416m_parents[] __initconst = { "top_xtal", + "mpll" }; + +static const char *const f_26m_adc_parents[] __initconst = { "top_xtal", + "top_mpll_d8_d2" }; + +static const char *const dramc_md32_parents[] __initconst = { "top_xtal", + "top_mpll_d2" }; + +static const char *const sysaxi_parents[] __initconst = { "top_xtal", + "top_net1pll_d8_d2", + "top_net2pll_d4" }; + +static const char *const sysapb_parents[] __initconst = { "top_xtal", + "top_mpll_d3_d2", + "top_net2pll_d4_d2" }; + +static const char *const arm_db_main_parents[] __initconst = { + "top_xtal", "top_net2pll_d3_d2" +}; + +static const char *const arm_db_jtsel_parents[] __initconst = { "top_jtag", + "top_xtal" }; + +static const char *const netsys_parents[] __initconst = { "top_xtal", + "top_mmpll_d4" }; + +static const char *const netsys_500m_parents[] __initconst = { + "top_xtal", "top_net1pll_d5" +}; + +static const char *const netsys_mcu_parents[] __initconst = { + "top_xtal", "wedmcupll", "top_mmpll_d2", "top_net1pll_d4", + "top_net1pll_d5" +}; + +static const char *const netsys_2x_parents[] __initconst = { + "top_xtal", "net2pll", "wedmcupll", "top_mmpll_d2" +}; + +static const char *const sgm_325m_parents[] __initconst = { "top_xtal", + "sgmpll" }; + +static const char *const sgm_reg_parents[] __initconst = { + "top_xtal", "top_net1pll_d8_d4" +}; + +static const char *const a1sys_parents[] __initconst = { "top_xtal", + "top_apll2_d4" }; + +static const char *const conn_mcusys_parents[] __initconst = { "top_xtal", + "top_mmpll_d2" }; + +static const char *const eip_b_parents[] __initconst = { "top_xtal", + "net2pll" }; + +static const char *const aud_l_parents[] __initconst = { "top_xtal", "apll2", + "top_mpll_d8_d2" }; + +static const char *const a_tuner_parents[] __initconst = { "top_xtal", + "top_apll2_d4", + "top_mpll_d8_d2" }; + +static const char *const u2u3_sys_parents[] __initconst = { + "top_xtal", "top_net1pll_d5_d4" +}; + +static const char *const da_u2_refsel_parents[] __initconst = { + "top_xtal", "top_mmpll_u2phy" +}; + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X_SEL, "nfi1x_sel", nfi1x_parents, + 0x000, 0x004, 0x008, 0, 3, 7, 0x1C0, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_SEL, "spinfi_sel", spinfi_parents, + 0x000, 0x004, 0x008, 8, 3, 15, 0x1C0, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x000, + 0x004, 0x008, 16, 3, 23, 0x1C0, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIM_MST_SEL, "spim_mst_sel", spi_parents, + 0x000, 0x004, 0x008, 24, 3, 31, 0x1C0, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x010, + 0x014, 0x018, 0, 2, 7, 0x1C0, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x010, + 0x014, 0x018, 8, 2, 15, 0x1C0, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x010, + 0x014, 0x018, 16, 2, 23, 0x1C0, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PEXTP_TL_SEL, "pextp_tl_ck_sel", + pextp_tl_ck_parents, 0x010, 0x014, 0x018, 24, 2, + 31, 0x1C0, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_250M_SEL, "emmc_250m_sel", + emmc_250m_parents, 0x020, 0x024, 0x028, 0, 1, 7, + 0x1C0, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EMMC_416M_SEL, "emmc_416m_sel", + emmc_416m_parents, 0x020, 0x024, 0x028, 8, 1, 15, + 0x1C0, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_F_26M_ADC_SEL, "f_26m_adc_sel", + f_26m_adc_parents, 0x020, 0x024, 0x028, 16, 1, 23, + 0x1C0, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_SEL, "dramc_sel", f_26m_adc_parents, + 0x020, 0x024, 0x028, 24, 1, 31, 0x1C0, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DRAMC_MD32_SEL, "dramc_md32_sel", + dramc_md32_parents, 0x030, 0x034, 0x038, 0, 1, 7, + 0x1C0, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAXI_SEL, "sysaxi_sel", sysaxi_parents, + 0x030, 0x034, 0x038, 8, 2, 15, 0x1C0, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SYSAPB_SEL, "sysapb_sel", sysapb_parents, + 0x030, 0x034, 0x038, 16, 2, 23, 0x1C0, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_MAIN_SEL, "arm_db_main_sel", + arm_db_main_parents, 0x030, 0x034, 0x038, 24, 1, + 31, 0x1C0, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ARM_DB_JTSEL, "arm_db_jtsel", + arm_db_jtsel_parents, 0x040, 0x044, 0x048, 0, 1, 7, + 0x1C0, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_SEL, "netsys_sel", netsys_parents, + 0x040, 0x044, 0x048, 8, 1, 15, 0x1C0, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_500M_SEL, "netsys_500m_sel", + netsys_500m_parents, 0x040, 0x044, 0x048, 16, 1, + 23, 0x1C0, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_MCU_SEL, "netsys_mcu_sel", + netsys_mcu_parents, 0x040, 0x044, 0x048, 24, 3, 31, + 0x1C0, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NETSYS_2X_SEL, "netsys_2x_sel", + netsys_2x_parents, 0x050, 0x054, 0x058, 0, 2, 7, + 0x1C0, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_325M_SEL, "sgm_325m_sel", + sgm_325m_parents, 0x050, 0x054, 0x058, 8, 1, 15, + 0x1C0, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SGM_REG_SEL, "sgm_reg_sel", + sgm_reg_parents, 0x050, 0x054, 0x058, 16, 1, 23, + 0x1C0, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_SEL, "a1sys_sel", a1sys_parents, + 0x050, 0x054, 0x058, 24, 1, 31, 0x1C0, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CONN_MCUSYS_SEL, "conn_mcusys_sel", + conn_mcusys_parents, 0x060, 0x064, 0x068, 0, 1, 7, + 0x1C0, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_EIP_B_SEL, "eip_b_sel", eip_b_parents, + 0x060, 0x064, 0x068, 8, 1, 15, 0x1C0, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PCIE_PHY_SEL, "pcie_phy_sel", + f_26m_adc_parents, 0x060, 0x064, 0x068, 16, 1, 23, + 0x1C0, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB3_PHY_SEL, "usb3_phy_sel", + f_26m_adc_parents, 0x060, 0x064, 0x068, 24, 1, 31, + 0x1C0, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_F26M_SEL, "csw_f26m_sel", + f_26m_adc_parents, 0x070, 0x074, 0x078, 0, 1, 7, + 0x1C0, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_L_SEL, "aud_l_sel", aud_l_parents, + 0x070, 0x074, 0x078, 8, 2, 15, 0x1C0, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A_TUNER_SEL, "a_tuner_sel", + a_tuner_parents, 0x070, 0x074, 0x078, 16, 2, 23, + 0x1C0, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SEL, "u2u3_sel", f_26m_adc_parents, + 0x070, 0x074, 0x078, 24, 1, 31, 0x1C4, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_SYS_SEL, "u2u3_sys_sel", + u2u3_sys_parents, 0x080, 0x084, 0x088, 0, 1, 7, + 0x1C4, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U2U3_XHCI_SEL, "u2u3_xhci_sel", + u2u3_sys_parents, 0x080, 0x084, 0x088, 8, 1, 15, + 0x1C4, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_REFSEL, "da_u2_refsel", + da_u2_refsel_parents, 0x080, 0x084, 0x088, 16, 1, + 23, 0x1C4, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DA_U2_CK_1P_SEL, "da_u2_ck_1p_sel", + da_u2_refsel_parents, 0x080, 0x084, 0x088, 24, 1, + 31, 0x1C4, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AP2CNN_HOST_SEL, "ap2cnn_host_sel", + sgm_reg_parents, 0x090, 0x094, 0x098, 0, 1, 7, + 0x1C4, 5), +}; + +static int clk_mt7986_topckgen_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + int nr = ARRAY_SIZE(top_fixed_clks) + ARRAY_SIZE(top_divs) + + ARRAY_SIZE(top_muxes); + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -ENOMEM; + } + + clk_data = mtk_alloc_clk_data(nr); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt7986_clk_lock, clk_data); + + clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAXI_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_SYSAPB_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_DRAMC_MD32_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_F26M_SEL]->clk); + clk_prepare_enable(clk_data->hws[CLK_TOP_SGM_REG_SEL]->clk); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) { + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + goto free_topckgen_data; + } + return r; + +free_topckgen_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt7986_topckgen[] = { + { .compatible = "mediatek,mt7986-topckgen", }, + {} +}; + +static struct platform_driver clk_mt7986_topckgen_drv = { + .probe = clk_mt7986_topckgen_probe, + .driver = { + .name = "clk-mt7986-topckgen", + .of_match_table = of_match_clk_mt7986_topckgen, + }, +}; +builtin_platform_driver(clk_mt7986_topckgen_drv); diff --git a/drivers/clk/mediatek/clk-mt8135.c b/drivers/clk/mediatek/clk-mt8135.c new file mode 100644 index 000000000..3ea06d2ec --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8135.c @@ -0,0 +1,640 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * Copyright (c) 2023 Collabora, Ltd. + * AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com> + */ + +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> +#include <dt-bindings/clock/mt8135-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +static DEFINE_SPINLOCK(mt8135_clk_lock); + +static const struct mtk_fixed_factor root_clk_alias[] __initconst = { + FACTOR(CLK_TOP_DSI0_LNTC_DSICLK, "dsi0_lntc_dsiclk", "clk_null", 1, 1), + FACTOR(CLK_TOP_HDMITX_CLKDIG_CTS, "hdmitx_clkdig_cts", "clk_null", 1, 1), + FACTOR(CLK_TOP_CLKPH_MCK, "clkph_mck", "clk_null", 1, 1), + FACTOR(CLK_TOP_CPUM_TCK_IN, "cpum_tck_in", "clk_null", 1, 1), +}; + +static const struct mtk_fixed_factor top_divs[] __initconst = { + FACTOR(CLK_TOP_MAINPLL_806M, "mainpll_806m", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_537P3M, "mainpll_537p3m", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_322P4M, "mainpll_322p4m", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_230P3M, "mainpll_230p3m", "mainpll", 1, 7), + + FACTOR(CLK_TOP_UNIVPLL_624M, "univpll_624m", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_416M, "univpll_416m", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_249P6M, "univpll_249p6m", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_178P3M, "univpll_178p3m", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_48M, "univpll_48m", "univpll", 1, 26), + + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_D3, "mmpll_d3", "mmpll", 1, 3), + FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll_d2", 1, 2), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll_d3", 1, 2), + + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll_806m", 1, 1), + FACTOR(CLK_TOP_SYSPLL_D4, "syspll_d4", "mainpll_806m", 1, 2), + FACTOR(CLK_TOP_SYSPLL_D6, "syspll_d6", "mainpll_806m", 1, 3), + FACTOR(CLK_TOP_SYSPLL_D8, "syspll_d8", "mainpll_806m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D10, "syspll_d10", "mainpll_806m", 1, 5), + FACTOR(CLK_TOP_SYSPLL_D12, "syspll_d12", "mainpll_806m", 1, 6), + FACTOR(CLK_TOP_SYSPLL_D16, "syspll_d16", "mainpll_806m", 1, 8), + FACTOR(CLK_TOP_SYSPLL_D24, "syspll_d24", "mainpll_806m", 1, 12), + + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll_537p3m", 1, 1), + + FACTOR(CLK_TOP_SYSPLL_D2P5, "syspll_d2p5", "mainpll_322p4m", 2, 1), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll_322p4m", 1, 1), + + FACTOR(CLK_TOP_SYSPLL_D3P5, "syspll_d3p5", "mainpll_230p3m", 2, 1), + + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_624m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_624m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D6, "univpll1_d6", "univpll_624m", 1, 6), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_624m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL1_D10, "univpll1_d10", "univpll_624m", 1, 10), + + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll_416m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll_416m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D6, "univpll2_d6", "univpll_416m", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll_416m", 1, 8), + + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll_416m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll_249p6m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll_178p3m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D10, "univpll_d10", "univpll_249p6m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll_48m", 1, 1), + + FACTOR(CLK_TOP_APLL, "apll_ck", "audpll", 1, 1), + FACTOR(CLK_TOP_APLL_D4, "apll_d4", "audpll", 1, 4), + FACTOR(CLK_TOP_APLL_D8, "apll_d8", "audpll", 1, 8), + FACTOR(CLK_TOP_APLL_D16, "apll_d16", "audpll", 1, 16), + FACTOR(CLK_TOP_APLL_D24, "apll_d24", "audpll", 1, 24), + + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + + FACTOR(CLK_TOP_LVDSTX_CLKDIG_CT, "lvdstx_clkdig_cts", "lvdspll", 1, 1), + FACTOR(CLK_TOP_VPLL_DPIX, "vpll_dpix_ck", "lvdspll", 1, 1), + + FACTOR(CLK_TOP_TVHDMI_H, "tvhdmi_h_ck", "tvdpll", 1, 1), + + FACTOR(CLK_TOP_HDMITX_CLKDIG_D2, "hdmitx_clkdig_d2", "hdmitx_clkdig_cts", 1, 2), + FACTOR(CLK_TOP_HDMITX_CLKDIG_D3, "hdmitx_clkdig_d3", "hdmitx_clkdig_cts", 1, 3), + + FACTOR(CLK_TOP_TVHDMI_D2, "tvhdmi_d2", "tvhdmi_h_ck", 1, 2), + FACTOR(CLK_TOP_TVHDMI_D4, "tvhdmi_d4", "tvhdmi_h_ck", 1, 4), + + FACTOR(CLK_TOP_MEMPLL_MCK_D4, "mempll_mck_d4", "clkph_mck", 1, 4), +}; + +static const char * const axi_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d4", + "syspll_d6", + "univpll_d5", + "univpll2_d2", + "syspll_d3p5" +}; + +static const char * const smi_parents[] __initconst = { + "clk26m", + "clkph_mck", + "syspll_d2p5", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d2", + "univpll1_d6", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", + "mmpll_d7", + "vdecpll", + "lvdspll" +}; + +static const char * const mfg_parents[] __initconst = { + "clk26m", + "univpll1_d4", + "syspll_d2", + "syspll_d2p5", + "syspll_d3", + "univpll_d5", + "univpll1_d2", + "mmpll_d2", + "mmpll_d3", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6", + "mmpll_d7" +}; + +static const char * const irda_parents[] __initconst = { + "clk26m", + "univpll2_d8", + "univpll1_d6" +}; + +static const char * const cam_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d3p5", + "syspll_d4", + "univpll_d5", + "univpll2_d2", + "univpll_d7", + "univpll1_d4" +}; + +static const char * const aud_intbus_parents[] __initconst = { + "clk26m", + "syspll_d6", + "univpll_d10" +}; + +static const char * const jpg_parents[] __initconst = { + "clk26m", + "syspll_d5", + "syspll_d4", + "syspll_d3", + "univpll_d7", + "univpll2_d2", + "univpll_d5" +}; + +static const char * const disp_parents[] __initconst = { + "clk26m", + "syspll_d3p5", + "syspll_d3", + "univpll2_d2", + "univpll_d5", + "univpll1_d2", + "lvdspll", + "vdecpll" +}; + +static const char * const msdc30_parents[] __initconst = { + "clk26m", + "syspll_d6", + "syspll_d5", + "univpll1_d4", + "univpll2_d4", + "msdcpll" +}; + +static const char * const usb20_parents[] __initconst = { + "clk26m", + "univpll2_d6", + "univpll1_d10" +}; + +static const char * const venc_parents[] __initconst = { + "clk26m", + "syspll_d3", + "syspll_d8", + "univpll_d5", + "univpll1_d6", + "mmpll_d4", + "mmpll_d5", + "mmpll_d6" +}; + +static const char * const spi_parents[] __initconst = { + "clk26m", + "syspll_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d6", + "univpll1_d8" +}; + +static const char * const uart_parents[] __initconst = { + "clk26m", + "univpll2_d8" +}; + +static const char * const mem_parents[] __initconst = { + "clk26m", + "clkph_mck" +}; + +static const char * const camtg_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll1_d6", + "syspll_d16", + "syspll_d8" +}; + +static const char * const audio_parents[] __initconst = { + "clk26m", + "syspll_d24" +}; + +static const char * const fix_parents[] __initconst = { + "rtc32k", + "clk26m", + "univpll_d5", + "univpll_d7", + "univpll1_d2", + "univpll1_d4", + "univpll1_d6", + "univpll1_d8" +}; + +static const char * const vdec_parents[] __initconst = { + "clk26m", + "vdecpll", + "clkph_mck", + "syspll_d2p5", + "syspll_d3", + "syspll_d3p5", + "syspll_d4", + "syspll_d5", + "syspll_d6", + "syspll_d8", + "univpll1_d2", + "univpll2_d2", + "univpll_d7", + "univpll_d10", + "univpll2_d4", + "lvdspll" +}; + +static const char * const ddrphycfg_parents[] __initconst = { + "clk26m", + "axi_sel", + "syspll_d12" +}; + +static const char * const dpilvds_parents[] __initconst = { + "clk26m", + "lvdspll", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8" +}; + +static const char * const pmicspi_parents[] __initconst = { + "clk26m", + "univpll2_d6", + "syspll_d8", + "syspll_d10", + "univpll1_d10", + "mempll_mck_d4", + "univpll_d26", + "syspll_d24" +}; + +static const char * const smi_mfg_as_parents[] __initconst = { + "clk26m", + "smi_sel", + "mfg_sel", + "mem_sel" +}; + +static const char * const gcpu_parents[] __initconst = { + "clk26m", + "syspll_d4", + "univpll_d7", + "syspll_d5", + "syspll_d6" +}; + +static const char * const dpi1_parents[] __initconst = { + "clk26m", + "tvhdmi_h_ck", + "tvhdmi_d2", + "tvhdmi_d4" +}; + +static const char * const cci_parents[] __initconst = { + "clk26m", + "mainpll_537p3m", + "univpll_d3", + "syspll_d2p5", + "syspll_d3", + "syspll_d5" +}; + +static const char * const apll_parents[] __initconst = { + "clk26m", + "apll_ck", + "apll_d4", + "apll_d8", + "apll_d16", + "apll_d24" +}; + +static const char * const hdmipll_parents[] __initconst = { + "clk26m", + "hdmitx_clkdig_cts", + "hdmitx_clkdig_d2", + "hdmitx_clkdig_d3" +}; + +static const struct mtk_composite top_muxes[] __initconst = { + /* CLK_CFG_0 */ + MUX_GATE(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x0140, 0, 3, INVALID_MUX_GATE_BIT), + MUX_GATE(CLK_TOP_SMI_SEL, "smi_sel", smi_parents, 0x0140, 8, 4, 15), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0140, 16, 4, 23), + MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x0140, 24, 2, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_CAM_SEL, "cam_sel", cam_parents, 0x0144, 0, 3, 7), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x0144, 8, 2, 15), + MUX_GATE(CLK_TOP_JPG_SEL, "jpg_sel", jpg_parents, 0x0144, 16, 3, 23), + MUX_GATE(CLK_TOP_DISP_SEL, "disp_sel", disp_parents, 0x0144, 24, 3, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_parents, 0x0148, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_parents, 0x0148, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_parents, 0x0148, 16, 3, 23), + MUX_GATE(CLK_TOP_MSDC30_4_SEL, "msdc30_4_sel", msdc30_parents, 0x0148, 24, 3, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x014c, 0, 2, 7), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0150, 8, 3, 15), + MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0150, 16, 3, 23), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0150, 24, 2, 31), + /* CLK_CFG_6 */ + MUX_GATE(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0158, 0, 2, 7), + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0158, 8, 3, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0158, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_FIX_SEL, "fix_sel", fix_parents, 0x015c, 0, 3, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x015c, 8, 4, 15), + MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x015c, 16, 2, 23), + MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x015c, 24, 3, 31), + /* CLK_CFG_8 */ + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0164, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_parents, 0x0164, 8, 3, 15), + MUX_GATE(CLK_TOP_SMI_MFG_AS_SEL, "smi_mfg_as_sel", smi_mfg_as_parents, + 0x0164, 16, 2, 23), + MUX_GATE(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0164, 24, 3, 31), + /* CLK_CFG_9 */ + MUX_GATE(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi1_parents, 0x0168, 0, 2, 7), + MUX_GATE_FLAGS(CLK_TOP_CCI_SEL, "cci_sel", cci_parents, 0x0168, 8, 3, 15, CLK_IS_CRITICAL), + MUX_GATE(CLK_TOP_APLL_SEL, "apll_sel", apll_parents, 0x0168, 16, 3, 23), + MUX_GATE(CLK_TOP_HDMIPLL_SEL, "hdmipll_sel", hdmipll_parents, 0x0168, 24, 2, 31), +}; + +static const struct mtk_gate_regs infra_cg_regs = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +#define GATE_ICG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_ICG_AO(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, CLK_IS_CRITICAL) + +static const struct mtk_gate infra_clks[] __initconst = { + GATE_ICG(CLK_INFRA_PMIC_WRAP, "pmic_wrap_ck", "axi_sel", 23), + GATE_ICG(CLK_INFRA_PMICSPI, "pmicspi_ck", "pmicspi_sel", 22), + GATE_ICG(CLK_INFRA_CCIF1_AP_CTRL, "ccif1_ap_ctrl", "axi_sel", 21), + GATE_ICG(CLK_INFRA_CCIF0_AP_CTRL, "ccif0_ap_ctrl", "axi_sel", 20), + GATE_ICG(CLK_INFRA_KP, "kp_ck", "axi_sel", 16), + GATE_ICG(CLK_INFRA_CPUM, "cpum_ck", "cpum_tck_in", 15), + GATE_ICG_AO(CLK_INFRA_M4U, "m4u_ck", "mem_sel", 8), + GATE_ICG(CLK_INFRA_MFGAXI, "mfgaxi_ck", "axi_sel", 7), + GATE_ICG(CLK_INFRA_DEVAPC, "devapc_ck", "axi_sel", 6), + GATE_ICG(CLK_INFRA_AUDIO, "audio_ck", "aud_intbus_sel", 5), + GATE_ICG(CLK_INFRA_MFG_BUS, "mfg_bus_ck", "axi_sel", 2), + GATE_ICG(CLK_INFRA_SMI, "smi_ck", "smi_sel", 1), + GATE_ICG(CLK_INFRA_DBGCLK, "dbgclk_ck", "axi_sel", 0), +}; + +static const struct mtk_gate_regs peri0_cg_regs = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static const struct mtk_gate_regs peri1_cg_regs = { + .set_ofs = 0x000c, + .clr_ofs = 0x0014, + .sta_ofs = 0x001c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_PERI1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate peri_gates[] __initconst = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_I2C5, "i2c5_ck", "axi_sel", 31), + GATE_PERI0(CLK_PERI_I2C4, "i2c4_ck", "axi_sel", 30), + GATE_PERI0(CLK_PERI_I2C3, "i2c3_ck", "axi_sel", 29), + GATE_PERI0(CLK_PERI_I2C2, "i2c2_ck", "axi_sel", 28), + GATE_PERI0(CLK_PERI_I2C1, "i2c1_ck", "axi_sel", 27), + GATE_PERI0(CLK_PERI_I2C0, "i2c0_ck", "axi_sel", 26), + GATE_PERI0(CLK_PERI_UART3, "uart3_ck", "axi_sel", 25), + GATE_PERI0(CLK_PERI_UART2, "uart2_ck", "axi_sel", 24), + GATE_PERI0(CLK_PERI_UART1, "uart1_ck", "axi_sel", 23), + GATE_PERI0(CLK_PERI_UART0, "uart0_ck", "axi_sel", 22), + GATE_PERI0(CLK_PERI_IRDA, "irda_ck", "irda_sel", 21), + GATE_PERI0(CLK_PERI_NLI, "nli_ck", "axi_sel", 20), + GATE_PERI0(CLK_PERI_MD_HIF, "md_hif_ck", "axi_sel", 19), + GATE_PERI0(CLK_PERI_AP_HIF, "ap_hif_ck", "axi_sel", 18), + GATE_PERI0(CLK_PERI_MSDC30_3, "msdc30_3_ck", "msdc30_4_sel", 17), + GATE_PERI0(CLK_PERI_MSDC30_2, "msdc30_2_ck", "msdc30_3_sel", 16), + GATE_PERI0(CLK_PERI_MSDC30_1, "msdc30_1_ck", "msdc30_2_sel", 15), + GATE_PERI0(CLK_PERI_MSDC20_2, "msdc20_2_ck", "msdc30_1_sel", 14), + GATE_PERI0(CLK_PERI_MSDC20_1, "msdc20_1_ck", "msdc30_0_sel", 13), + GATE_PERI0(CLK_PERI_AP_DMA, "ap_dma_ck", "axi_sel", 12), + GATE_PERI0(CLK_PERI_USB1, "usb1_ck", "usb20_sel", 11), + GATE_PERI0(CLK_PERI_USB0, "usb0_ck", "usb20_sel", 10), + GATE_PERI0(CLK_PERI_PWM, "pwm_ck", "axi_sel", 9), + GATE_PERI0(CLK_PERI_PWM7, "pwm7_ck", "axi_sel", 8), + GATE_PERI0(CLK_PERI_PWM6, "pwm6_ck", "axi_sel", 7), + GATE_PERI0(CLK_PERI_PWM5, "pwm5_ck", "axi_sel", 6), + GATE_PERI0(CLK_PERI_PWM4, "pwm4_ck", "axi_sel", 5), + GATE_PERI0(CLK_PERI_PWM3, "pwm3_ck", "axi_sel", 4), + GATE_PERI0(CLK_PERI_PWM2, "pwm2_ck", "axi_sel", 3), + GATE_PERI0(CLK_PERI_PWM1, "pwm1_ck", "axi_sel", 2), + GATE_PERI0(CLK_PERI_THERM, "therm_ck", "axi_sel", 1), + GATE_PERI0(CLK_PERI_NFI, "nfi_ck", "axi_sel", 0), + /* PERI1 */ + GATE_PERI1(CLK_PERI_USBSLV, "usbslv_ck", "axi_sel", 8), + GATE_PERI1(CLK_PERI_USB1_MCU, "usb1_mcu_ck", "axi_sel", 7), + GATE_PERI1(CLK_PERI_USB0_MCU, "usb0_mcu_ck", "axi_sel", 6), + GATE_PERI1(CLK_PERI_GCPU, "gcpu_ck", "gcpu_sel", 5), + GATE_PERI1(CLK_PERI_FHCTL, "fhctl_ck", "clk26m", 4), + GATE_PERI1(CLK_PERI_SPI1, "spi1_ck", "spi_sel", 3), + GATE_PERI1(CLK_PERI_AUXADC, "auxadc_ck", "clk26m", 2), + GATE_PERI1(CLK_PERI_PERI_PWRAP, "peri_pwrap_ck", "axi_sel", 1), + GATE_PERI1(CLK_PERI_I2C6, "i2c6_ck", "axi_sel", 0), +}; + +static const char * const uart_ck_sel_parents[] __initconst = { + "clk26m", + "uart_sel", +}; + +static const struct mtk_composite peri_clks[] __initconst = { + MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1), + MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1), + MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1), + MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), +}; + +static u16 infrasys_rst_ofs[] = { 0x30, 0x34, }; +static u16 pericfg_rst_ofs[] = { 0x0, 0x4, }; + +static const struct mtk_clk_rst_desc clk_rst_desc[] = { + /* infrasys */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), + }, + /* pericfg */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), + } +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8135_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8135-topckgen", mtk_topckgen_init); + +static void __init mtk_infrasys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, &clk_rst_desc[0]); +} +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8135-infracfg", mtk_infrasys_init); + +static void __init mtk_pericfg_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates), + clk_data); + mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base, + &mt8135_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, &clk_rst_desc[1]); +} +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8135-pericfg", mtk_pericfg_init); + +#define MT8135_PLL_FMAX (2000 * MHZ) +#define CON0_MT8135_RST_BAR BIT(27) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8135_RST_BAR, \ + .fmax = MT8135_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + } + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL1, "armpll1", 0x200, 0x218, 0x80000000, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_ARMPLL2, "armpll2", 0x2cc, 0x2e4, 0x80000000, 0, 21, 0x2d0, 24, 0x0, 0x2d0, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x21c, 0x234, 0xf0000000, HAVE_RST_BAR, 21, 0x21c, 6, 0x0, 0x220, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x238, 0x250, 0xf3000000, HAVE_RST_BAR, 7, 0x238, 6, 0x0, 0x238, 9), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x254, 0x26c, 0xf0000000, HAVE_RST_BAR, 21, 0x254, 6, 0x0, 0x258, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x278, 0x290, 0x80000000, 0, 21, 0x278, 6, 0x0, 0x27c, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x294, 0x2ac, 0x80000000, 0, 31, 0x294, 6, 0x0, 0x298, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2b0, 0x2c8, 0x80000000, 0, 21, 0x2b0, 6, 0x0, 0x2b4, 0), + PLL(CLK_APMIXED_AUDPLL, "audpll", 0x2e8, 0x300, 0x80000000, 0, 31, 0x2e8, 6, 0x2f8, 0x2ec, 0), + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x304, 0x31c, 0x80000000, 0, 21, 0x2b0, 6, 0x0, 0x308, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8135-apmixedsys", + mtk_apmixedsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167-aud.c b/drivers/clk/mediatek/clk-mt8167-aud.c new file mode 100644 index 000000000..b5ac196cd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-aud.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static const struct mtk_gate_regs aud_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_AUD(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + + +static const struct mtk_gate aud_clks[] __initconst = { + GATE_AUD(CLK_AUD_AFE, "aud_afe", "clk26m_ck", 2), + GATE_AUD(CLK_AUD_I2S, "aud_i2s", "i2s_infra_bck", 6), + GATE_AUD(CLK_AUD_22M, "aud_22m", "rg_aud_engen1", 8), + GATE_AUD(CLK_AUD_24M, "aud_24m", "rg_aud_engen2", 9), + GATE_AUD(CLK_AUD_INTDIR, "aud_intdir", "rg_aud_spdif_in", 15), + GATE_AUD(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "rg_aud_engen2", 18), + GATE_AUD(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "rg_aud_engen1", 19), + GATE_AUD(CLK_AUD_HDMI, "aud_hdmi", "apll12_div4", 20), + GATE_AUD(CLK_AUD_SPDF, "aud_spdf", "apll12_div6", 21), + GATE_AUD(CLK_AUD_ADC, "aud_adc", "aud_afe", 24), + GATE_AUD(CLK_AUD_DAC, "aud_dac", "aud_afe", 25), + GATE_AUD(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "aud_afe", 26), + GATE_AUD(CLK_AUD_TML, "aud_tml", "aud_afe", 27), +}; + +static void __init mtk_audsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); + + mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_audsys, "mediatek,mt8167-audsys", mtk_audsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167-img.c b/drivers/clk/mediatek/clk-mt8167-img.c new file mode 100644 index 000000000..4e7c0772b --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-img.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] __initconst = { + GATE_IMG(CLK_IMG_LARB1_SMI, "img_larb1_smi", "smi_mm", 0), + GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "smi_mm", 5), + GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "smi_mm", 6), + GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "cam_mm", 7), + GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "smi_mm", 8), + GATE_IMG(CLK_IMG_VENC, "img_venc", "smi_mm", 9), +}; + +static void __init mtk_imgsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); + + mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8167-imgsys", mtk_imgsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167-mfgcfg.c b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c new file mode 100644 index 000000000..192714498 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-mfgcfg.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] __initconst = { + GATE_MFG(CLK_MFG_BAXI, "mfg_baxi", "ahb_infra_sel", 0), + GATE_MFG(CLK_MFG_BMEM, "mfg_bmem", "gfmux_emi1x_sel", 1), + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_mm", 2), + GATE_MFG(CLK_MFG_B26M, "mfg_b26m", "clk26m_ck", 3), +}; + +static void __init mtk_mfgcfg_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK); + + mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_mfgcfg, "mediatek,mt8167-mfgcfg", mtk_mfgcfg_init); diff --git a/drivers/clk/mediatek/clk-mt8167-mm.c b/drivers/clk/mediatek/clk-mt8167-mm.c new file mode 100644 index 000000000..a94961b7b --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-mm.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "smi_mm", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "smi_mm", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "smi_mm", 2), + GATE_MM0(CLK_MM_MDP_RDMA, "mm_mdp_rdma", "smi_mm", 3), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "smi_mm", 4), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "smi_mm", 5), + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "smi_mm", 6), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "smi_mm", 7), + GATE_MM0(CLK_MM_MDP_WROT, "mm_mdp_wrot", "smi_mm", 8), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "smi_mm", 9), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "smi_mm", 10), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "smi_mm", 11), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "smi_mm", 12), + GATE_MM0(CLK_MM_DISP_WDMA, "mm_disp_wdma", "smi_mm", 13), + GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "smi_mm", 14), + GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "smi_mm", 15), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "smi_mm", 16), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "smi_mm", 17), + GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "smi_mm", 18), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "smi_mm", 19), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM_MM, "mm_disp_pwm_mm", "smi_mm", 0), + GATE_MM1(CLK_MM_DISP_PWM_26M, "mm_disp_pwm_26m", "smi_mm", 1), + GATE_MM1(CLK_MM_DSI_ENGINE, "mm_dsi_engine", "smi_mm", 2), + GATE_MM1(CLK_MM_DSI_DIGITAL, "mm_dsi_digital", "dsi0_lntc_dsick", 3), + GATE_MM1(CLK_MM_DPI0_ENGINE, "mm_dpi0_engine", "smi_mm", 4), + GATE_MM1(CLK_MM_DPI0_PXL, "mm_dpi0_pxl", "rg_fdpi0", 5), + GATE_MM1(CLK_MM_LVDS_PXL, "mm_lvds_pxl", "vpll_dpix", 14), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvdstx_dig_cts", 15), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "smi_mm", 16), + GATE_MM1(CLK_MM_DPI1_PXL, "mm_dpi1_pxl", "rg_fdpi1", 17), + GATE_MM1(CLK_MM_HDMI_PXL, "mm_hdmi_pxl", "rg_fdpi1", 18), + GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll12_div6", 19), + GATE_MM1(CLK_MM_HDMI_ADSP_BCK, "mm_hdmi_adsp_b", "apll12_div4b", 20), + GATE_MM1(CLK_MM_HDMI_PLL, "mm_hdmi_pll", "hdmtx_dig_cts", 21), +}; + +struct clk_mt8167_mm_driver_data { + const struct mtk_gate *gates_clk; + int gates_num; +}; + +static const struct clk_mt8167_mm_driver_data mt8167_mmsys_driver_data = { + .gates_clk = mm_clks, + .gates_num = ARRAY_SIZE(mm_clks), +}; + +static int clk_mt8167_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + const struct clk_mt8167_mm_driver_data *data; + struct clk_hw_onecell_data *clk_data; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + data = &mt8167_mmsys_driver_data; + + ret = mtk_clk_register_gates(node, data->gates_clk, data->gates_num, + clk_data); + if (ret) + return ret; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + return ret; + + return 0; +} + +static struct platform_driver clk_mt8173_mm_drv = { + .driver = { + .name = "clk-mt8167-mm", + }, + .probe = clk_mt8167_mm_probe, +}; + +builtin_platform_driver(clk_mt8173_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8167-vdec.c b/drivers/clk/mediatek/clk-mt8167-vdec.c new file mode 100644 index 000000000..38f0ba357 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167-vdec.c @@ -0,0 +1,61 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] __initconst = { + /* VDEC0 */ + GATE_VDEC0_I(CLK_VDEC_CKEN, "vdec_cken", "rg_vdec", 0), + /* VDEC1 */ + GATE_VDEC1_I(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "smi_mm", 0), +}; + +static void __init mtk_vdecsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); + + mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8167-vdecsys", mtk_vdecsys_init); diff --git a/drivers/clk/mediatek/clk-mt8167.c b/drivers/clk/mediatek/clk-mt8167.c new file mode 100644 index 000000000..f900ac4bf --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8167.c @@ -0,0 +1,1063 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 MediaTek Inc. + * Copyright (c) 2020 BayLibre, SAS + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8167-clk.h> + +static DEFINE_SPINLOCK(mt8167_clk_lock); + +static const struct mtk_fixed_clk fixed_clks[] __initconst = { + FIXED_CLK(CLK_TOP_CLK_NULL, "clk_null", NULL, 0), + FIXED_CLK(CLK_TOP_I2S_INFRA_BCK, "i2s_infra_bck", "clk_null", 26000000), + FIXED_CLK(CLK_TOP_MEMPLL, "mempll", "clk26m", 800000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC_DSICK, "dsi0_lntc_dsick", "clk26m", 75000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", "clk26m", 75000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx_dig_cts", "clk26m", 52500000), +}; + +static const struct mtk_fixed_factor top_divs[] __initconst = { + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D8, "mainpll_d8", "mainpll", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D16, "mainpll_d16", "mainpll", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D11, "mainpll_d11", "mainpll", 1, 11), + FACTOR(CLK_TOP_MAINPLL_D22, "mainpll_d22", "mainpll", 1, 22), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6), + FACTOR(CLK_TOP_MAINPLL_D12, "mainpll_d12", "mainpll", 1, 12), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D10, "mainpll_d10", "mainpll", 1, 10), + FACTOR(CLK_TOP_MAINPLL_D20, "mainpll_d20", "mainpll", 1, 20), + FACTOR(CLK_TOP_MAINPLL_D40, "mainpll_d40", "mainpll", 1, 40), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D14, "mainpll_d14", "mainpll", 1, 14), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D8, "univpll_d8", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D16, "univpll_d16", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL_D12, "univpll_d12", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL_D24, "univpll_d24", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D20, "univpll_d20", "univpll", 1, 20), + FACTOR(CLK_TOP_MMPLL380M, "mmpll380m", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_200M, "mmpll_200m", "mmpll", 1, 3), + FACTOR(CLK_TOP_LVDSPLL, "lvdspll_ck", "lvdspll", 1, 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "rg_apll1_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "rg_apll1_d4_en", 1, 2), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "rg_apll2_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "rg_apll2_d4_en", 1, 2), + FACTOR(CLK_TOP_CLK26M, "clk26m_ck", "clk26m", 1, 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_MIPI_26M, "mipi_26m", "clk26m", 1, 1), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16), + FACTOR(CLK_TOP_AHB_INFRA_D2, "ahb_infra_d2", "ahb_infra_sel", 1, 2), + FACTOR(CLK_TOP_NFI1X, "nfi1x_ck", "nfi2x_pad_sel", 1, 2), + FACTOR(CLK_TOP_ETH_D2, "eth_d2_ck", "eth_sel", 1, 2), +}; + +static const char * const uart0_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const gfmux_emi1x_parents[] __initconst = { + "clk26m_ck", + "dmpll_ck" +}; + +static const char * const emi_ddrphy_parents[] __initconst = { + "gfmux_emi1x_sel", + "gfmux_emi1x_sel" +}; + +static const char * const ahb_infra_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d11", + "clk_null", + "mainpll_d12", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10" +}; + +static const char * const csw_mux_mfg_parents[] __initconst = { + "clk_null", + "clk_null", + "univpll_d3", + "univpll_d2", + "clk26m_ck", + "mainpll_d4", + "univpll_d24", + "mmpll380m" +}; + +static const char * const msdc0_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const camtg_mm_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "usb_phy48m_ck", + "clk_null", + "univpll_d6" +}; + +static const char * const pwm_mm_parents[] __initconst = { + "clk26m_ck", + "univpll_d12" +}; + +static const char * const uart1_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const msdc1_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const spm_52m_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const pmicspi_parents[] __initconst = { + "univpll_d20", + "usb_phy48m_ck", + "univpll_d16", + "clk26m_ck" +}; + +static const char * const qaxi_aud26m_parents[] __initconst = { + "clk26m_ck", + "ahb_infra_sel" +}; + +static const char * const aud_intbus_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d22", + "clk_null", + "mainpll_d11" +}; + +static const char * const nfi2x_pad_parents[] __initconst = { + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk26m_ck", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d12", + "mainpll_d8", + "clk_null", + "mainpll_d6", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d4", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10", + "mainpll_d7", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfi1x_pad_parents[] __initconst = { + "ahb_infra_sel", + "nfi1x_ck" +}; + +static const char * const mfg_mm_parents[] __initconst = { + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "csw_mux_mfg_sel", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d3", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d5", + "mainpll_d7", + "clk_null", + "mainpll_d14" +}; + +static const char * const ddrphycfg_parents[] __initconst = { + "clk26m_ck", + "mainpll_d16" +}; + +static const char * const smi_mm_parents[] __initconst = { + "clk26m_ck", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "univpll_d4", + "mainpll_d7", + "clk_null", + "mainpll_d14" +}; + +static const char * const usb_78m_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "univpll_d16", + "clk_null", + "mainpll_d20" +}; + +static const char * const scam_mm_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d14", + "clk_null", + "mainpll_d12" +}; + +static const char * const spinor_parents[] __initconst = { + "clk26m_d2", + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20", + "mainpll_d16", + "univpll_d12" +}; + +static const char * const msdc2_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const eth_parents[] __initconst = { + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20" +}; + +static const char * const vdec_mm_parents[] __initconst = { + "clk26m_ck", + "univpll_d4", + "mainpll_d4", + "univpll_d5", + "univpll_d6", + "mainpll_d6" +}; + +static const char * const dpi0_mm_parents[] __initconst = { + "clk26m_ck", + "lvdspll_ck", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8" +}; + +static const char * const dpi1_mm_parents[] __initconst = { + "clk26m_ck", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const axi_mfg_in_parents[] __initconst = { + "clk26m_ck", + "mainpll_d11", + "univpll_d24", + "mmpll380m" +}; + +static const char * const slow_mfg_parents[] __initconst = { + "clk26m_ck", + "univpll_d12", + "univpll_d24" +}; + +static const char * const aud1_parents[] __initconst = { + "clk26m_ck", + "apll1_ck" +}; + +static const char * const aud2_parents[] __initconst = { + "clk26m_ck", + "apll2_ck" +}; + +static const char * const aud_engen1_parents[] __initconst = { + "clk26m_ck", + "rg_apll1_d2_en", + "rg_apll1_d4_en", + "rg_apll1_d8_en" +}; + +static const char * const aud_engen2_parents[] __initconst = { + "clk26m_ck", + "rg_apll2_d2_en", + "rg_apll2_d4_en", + "rg_apll2_d8_en" +}; + +static const char * const i2c_parents[] __initconst = { + "clk26m_ck", + "univpll_d20", + "univpll_d16", + "univpll_d12" +}; + +static const char * const aud_i2s0_m_parents[] __initconst = { + "rg_aud1", + "rg_aud2" +}; + +static const char * const pwm_parents[] __initconst = { + "clk26m_ck", + "univpll_d12" +}; + +static const char * const spi_parents[] __initconst = { + "clk26m_ck", + "univpll_d12", + "univpll_d8", + "univpll_d6" +}; + +static const char * const aud_spdifin_parents[] __initconst = { + "clk26m_ck", + "univpll_d2" +}; + +static const char * const uart2_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const bsi_parents[] __initconst = { + "clk26m_ck", + "mainpll_d10", + "mainpll_d12", + "mainpll_d20" +}; + +static const char * const dbg_atclk_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d5", + "clk_null", + "univpll_d5" +}; + +static const char * const csw_nfiecc_parents[] __initconst = { + "clk_null", + "mainpll_d7", + "mainpll_d6", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfiecc_parents[] __initconst = { + "clk_null", + "nfi2x_pad_sel", + "mainpll_d4", + "clk_null", + "csw_nfiecc_sel" +}; + +static struct mtk_composite top_muxes[] __initdata = { + /* CLK_MUX_SEL0 */ + MUX(CLK_TOP_UART0_SEL, "uart0_sel", uart0_parents, + 0x000, 0, 1), + MUX(CLK_TOP_GFMUX_EMI1X_SEL, "gfmux_emi1x_sel", gfmux_emi1x_parents, + 0x000, 1, 1), + MUX(CLK_TOP_EMI_DDRPHY_SEL, "emi_ddrphy_sel", emi_ddrphy_parents, + 0x000, 2, 1), + MUX(CLK_TOP_AHB_INFRA_SEL, "ahb_infra_sel", ahb_infra_parents, + 0x000, 4, 4), + MUX(CLK_TOP_CSW_MUX_MFG_SEL, "csw_mux_mfg_sel", csw_mux_mfg_parents, + 0x000, 8, 3), + MUX(CLK_TOP_MSDC0_SEL, "msdc0_sel", msdc0_parents, + 0x000, 11, 3), + MUX(CLK_TOP_CAMTG_MM_SEL, "camtg_mm_sel", camtg_mm_parents, + 0x000, 15, 3), + MUX(CLK_TOP_PWM_MM_SEL, "pwm_mm_sel", pwm_mm_parents, + 0x000, 18, 1), + MUX(CLK_TOP_UART1_SEL, "uart1_sel", uart1_parents, + 0x000, 19, 1), + MUX(CLK_TOP_MSDC1_SEL, "msdc1_sel", msdc1_parents, + 0x000, 20, 3), + MUX(CLK_TOP_SPM_52M_SEL, "spm_52m_sel", spm_52m_parents, + 0x000, 23, 1), + MUX(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x000, 24, 2), + MUX(CLK_TOP_QAXI_AUD26M_SEL, "qaxi_aud26m_sel", qaxi_aud26m_parents, + 0x000, 26, 1), + MUX(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x000, 27, 3), + /* CLK_MUX_SEL1 */ + MUX(CLK_TOP_NFI2X_PAD_SEL, "nfi2x_pad_sel", nfi2x_pad_parents, + 0x004, 0, 7), + MUX(CLK_TOP_NFI1X_PAD_SEL, "nfi1x_pad_sel", nfi1x_pad_parents, + 0x004, 7, 1), + MUX(CLK_TOP_MFG_MM_SEL, "mfg_mm_sel", mfg_mm_parents, + 0x004, 8, 6), + MUX(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, + 0x004, 15, 1), + MUX(CLK_TOP_SMI_MM_SEL, "smi_mm_sel", smi_mm_parents, + 0x004, 16, 4), + MUX(CLK_TOP_USB_78M_SEL, "usb_78m_sel", usb_78m_parents, + 0x004, 20, 3), + MUX(CLK_TOP_SCAM_MM_SEL, "scam_mm_sel", scam_mm_parents, + 0x004, 23, 3), + /* CLK_MUX_SEL8 */ + MUX(CLK_TOP_SPINOR_SEL, "spinor_sel", spinor_parents, + 0x040, 0, 3), + MUX(CLK_TOP_MSDC2_SEL, "msdc2_sel", msdc2_parents, + 0x040, 3, 3), + MUX(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 6, 3), + MUX(CLK_TOP_VDEC_MM_SEL, "vdec_mm_sel", vdec_mm_parents, + 0x040, 9, 3), + MUX(CLK_TOP_DPI0_MM_SEL, "dpi0_mm_sel", dpi0_mm_parents, + 0x040, 12, 3), + MUX(CLK_TOP_DPI1_MM_SEL, "dpi1_mm_sel", dpi1_mm_parents, + 0x040, 15, 3), + MUX(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, + 0x040, 18, 2), + MUX(CLK_TOP_SLOW_MFG_SEL, "slow_mfg_sel", slow_mfg_parents, + 0x040, 20, 2), + MUX(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x040, 22, 1), + MUX(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x040, 23, 1), + MUX(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", aud_engen1_parents, + 0x040, 24, 2), + MUX(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", aud_engen2_parents, + 0x040, 26, 2), + MUX(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, + 0x040, 28, 2), + /* CLK_SEL_9 */ + MUX(CLK_TOP_AUD_I2S0_M_SEL, "aud_i2s0_m_sel", aud_i2s0_m_parents, + 0x044, 12, 1), + MUX(CLK_TOP_AUD_I2S1_M_SEL, "aud_i2s1_m_sel", aud_i2s0_m_parents, + 0x044, 13, 1), + MUX(CLK_TOP_AUD_I2S2_M_SEL, "aud_i2s2_m_sel", aud_i2s0_m_parents, + 0x044, 14, 1), + MUX(CLK_TOP_AUD_I2S3_M_SEL, "aud_i2s3_m_sel", aud_i2s0_m_parents, + 0x044, 15, 1), + MUX(CLK_TOP_AUD_I2S4_M_SEL, "aud_i2s4_m_sel", aud_i2s0_m_parents, + 0x044, 16, 1), + MUX(CLK_TOP_AUD_I2S5_M_SEL, "aud_i2s5_m_sel", aud_i2s0_m_parents, + 0x044, 17, 1), + MUX(CLK_TOP_AUD_SPDIF_B_SEL, "aud_spdif_b_sel", aud_i2s0_m_parents, + 0x044, 18, 1), + /* CLK_MUX_SEL13 */ + MUX(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x07c, 0, 1), + MUX(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, + 0x07c, 1, 2), + MUX(CLK_TOP_AUD_SPDIFIN_SEL, "aud_spdifin_sel", aud_spdifin_parents, + 0x07c, 3, 1), + MUX(CLK_TOP_UART2_SEL, "uart2_sel", uart2_parents, + 0x07c, 4, 1), + MUX(CLK_TOP_BSI_SEL, "bsi_sel", bsi_parents, + 0x07c, 5, 2), + MUX(CLK_TOP_DBG_ATCLK_SEL, "dbg_atclk_sel", dbg_atclk_parents, + 0x07c, 7, 3), + MUX(CLK_TOP_CSW_NFIECC_SEL, "csw_nfiecc_sel", csw_nfiecc_parents, + 0x07c, 10, 3), + MUX(CLK_TOP_NFIECC_SEL, "nfiecc_sel", nfiecc_parents, + 0x07c, 13, 3), +}; + +static const char * const ifr_mux1_parents[] __initconst = { + "clk26m_ck", + "armpll", + "univpll", + "mainpll_d2" +}; + +static const char * const ifr_eth_25m_parents[] __initconst = { + "eth_d2_ck", + "rg_eth" +}; + +static const char * const ifr_i2c0_parents[] __initconst = { + "ahb_infra_d2", + "rg_i2c" +}; + +static const struct mtk_composite ifr_muxes[] __initconst = { + MUX(CLK_IFR_MUX1_SEL, "ifr_mux1_sel", ifr_mux1_parents, 0x000, + 2, 2), + MUX(CLK_IFR_ETH_25M_SEL, "ifr_eth_25m_sel", ifr_eth_25m_parents, 0x080, + 0, 1), + MUX(CLK_IFR_I2C0_SEL, "ifr_i2c0_sel", ifr_i2c0_parents, 0x080, + 1, 1), + MUX(CLK_IFR_I2C1_SEL, "ifr_i2c1_sel", ifr_i2c0_parents, 0x080, + 2, 1), + MUX(CLK_IFR_I2C2_SEL, "ifr_i2c2_sel", ifr_i2c0_parents, 0x080, + 3, 1), +}; + +#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ +} + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL12_CK_DIV0, "apll12_ck_div0", "aud_i2s0_m_sel", + 0x0048, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV1, "apll12_ck_div1", "aud_i2s1_m_sel", + 0x0048, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV2, "apll12_ck_div2", "aud_i2s2_m_sel", + 0x0048, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV3, "apll12_ck_div3", "aud_i2s3_m_sel", + 0x0048, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4, "apll12_ck_div4", "aud_i2s4_m_sel", + 0x004c, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4B, "apll12_ck_div4b", "apll12_div4", + 0x004c, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5, "apll12_ck_div5", "aud_i2s5_m_sel", + 0x004c, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5B, "apll12_ck_div5b", "apll12_div5", + 0x004c, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV6, "apll12_ck_div6", "aud_spdif_b_sel", + 0x0078, 0, 8), +}; + +#define DIV_ADJ_FLAG(_id, _name, _parent, _reg, _shift, _width, _flag) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ + .clk_divider_flags = _flag, \ +} + +static const struct mtk_clk_divider apmixed_adj_divs[] = { + DIV_ADJ_FLAG(CLK_APMIXED_HDMI_REF, "hdmi_ref", "tvdpll", + 0x1c4, 24, 3, CLK_DIVIDER_POWER_OF_TWO), +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x50, + .clr_ofs = 0x80, + .sta_ofs = 0x20, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x54, + .clr_ofs = 0x84, + .sta_ofs = 0x24, +}; + +static const struct mtk_gate_regs top2_cg_regs = { + .set_ofs = 0x6c, + .clr_ofs = 0x9c, + .sta_ofs = 0x3c, +}; + +static const struct mtk_gate_regs top3_cg_regs = { + .set_ofs = 0xa0, + .clr_ofs = 0xb0, + .sta_ofs = 0x70, +}; + +static const struct mtk_gate_regs top4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xb4, + .sta_ofs = 0x74, +}; + +static const struct mtk_gate_regs top5_cg_regs = { + .set_ofs = 0x44, + .clr_ofs = 0x44, + .sta_ofs = 0x44, +}; + +#define GATE_TOP0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP0_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP2_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_TOP4_I(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top4_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_TOP5(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &top5_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_no_setclr, \ + } + +static const struct mtk_gate top_clks[] __initconst = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_PWM_MM, "pwm_mm", "pwm_mm_sel", 0), + GATE_TOP0(CLK_TOP_CAM_MM, "cam_mm", "camtg_mm_sel", 1), + GATE_TOP0(CLK_TOP_MFG_MM, "mfg_mm", "mfg_mm_sel", 2), + GATE_TOP0(CLK_TOP_SPM_52M, "spm_52m", "spm_52m_sel", 3), + GATE_TOP0_I(CLK_TOP_MIPI_26M_DBG, "mipi_26m_dbg", "mipi_26m", 4), + GATE_TOP0(CLK_TOP_SCAM_MM, "scam_mm", "scam_mm_sel", 5), + GATE_TOP0(CLK_TOP_SMI_MM, "smi_mm", "smi_mm_sel", 9), + /* TOP1 */ + GATE_TOP1(CLK_TOP_THEM, "them", "ahb_infra_sel", 1), + GATE_TOP1(CLK_TOP_APDMA, "apdma", "ahb_infra_sel", 2), + GATE_TOP1(CLK_TOP_I2C0, "i2c0", "ifr_i2c0_sel", 3), + GATE_TOP1(CLK_TOP_I2C1, "i2c1", "ifr_i2c1_sel", 4), + GATE_TOP1(CLK_TOP_AUXADC1, "auxadc1", "ahb_infra_sel", 5), + GATE_TOP1(CLK_TOP_NFI, "nfi", "nfi1x_pad_sel", 6), + GATE_TOP1(CLK_TOP_NFIECC, "nfiecc", "rg_nfiecc", 7), + GATE_TOP1(CLK_TOP_DEBUGSYS, "debugsys", "rg_dbg_atclk", 8), + GATE_TOP1(CLK_TOP_PWM, "pwm", "ahb_infra_sel", 9), + GATE_TOP1(CLK_TOP_UART0, "uart0", "uart0_sel", 10), + GATE_TOP1(CLK_TOP_UART1, "uart1", "uart1_sel", 11), + GATE_TOP1(CLK_TOP_BTIF, "btif", "ahb_infra_sel", 12), + GATE_TOP1(CLK_TOP_USB, "usb", "usb_78m", 13), + GATE_TOP1(CLK_TOP_FLASHIF_26M, "flashif_26m", "clk26m_ck", 14), + GATE_TOP1(CLK_TOP_AUXADC2, "auxadc2", "ahb_infra_sel", 15), + GATE_TOP1(CLK_TOP_I2C2, "i2c2", "ifr_i2c2_sel", 16), + GATE_TOP1(CLK_TOP_MSDC0, "msdc0", "msdc0_sel", 17), + GATE_TOP1(CLK_TOP_MSDC1, "msdc1", "msdc1_sel", 18), + GATE_TOP1(CLK_TOP_NFI2X, "nfi2x", "nfi2x_pad_sel", 19), + GATE_TOP1(CLK_TOP_PMICWRAP_AP, "pwrap_ap", "clk26m_ck", 20), + GATE_TOP1(CLK_TOP_SEJ, "sej", "ahb_infra_sel", 21), + GATE_TOP1(CLK_TOP_MEMSLP_DLYER, "memslp_dlyer", "clk26m_ck", 22), + GATE_TOP1(CLK_TOP_SPI, "spi", "spi_sel", 23), + GATE_TOP1(CLK_TOP_APXGPT, "apxgpt", "clk26m_ck", 24), + GATE_TOP1(CLK_TOP_AUDIO, "audio", "clk26m_ck", 25), + GATE_TOP1(CLK_TOP_PMICWRAP_MD, "pwrap_md", "clk26m_ck", 27), + GATE_TOP1(CLK_TOP_PMICWRAP_CONN, "pwrap_conn", "clk26m_ck", 28), + GATE_TOP1(CLK_TOP_PMICWRAP_26M, "pwrap_26m", "clk26m_ck", 29), + GATE_TOP1(CLK_TOP_AUX_ADC, "aux_adc", "clk26m_ck", 30), + GATE_TOP1(CLK_TOP_AUX_TP, "aux_tp", "clk26m_ck", 31), + /* TOP2 */ + GATE_TOP2(CLK_TOP_MSDC2, "msdc2", "ahb_infra_sel", 0), + GATE_TOP2(CLK_TOP_RBIST, "rbist", "univpll_d12", 1), + GATE_TOP2(CLK_TOP_NFI_BUS, "nfi_bus", "ahb_infra_sel", 2), + GATE_TOP2(CLK_TOP_GCE, "gce", "ahb_infra_sel", 4), + GATE_TOP2(CLK_TOP_TRNG, "trng", "ahb_infra_sel", 5), + GATE_TOP2(CLK_TOP_SEJ_13M, "sej_13m", "clk26m_ck", 6), + GATE_TOP2(CLK_TOP_AES, "aes", "ahb_infra_sel", 7), + GATE_TOP2(CLK_TOP_PWM_B, "pwm_b", "rg_pwm_infra", 8), + GATE_TOP2(CLK_TOP_PWM1_FB, "pwm1_fb", "rg_pwm_infra", 9), + GATE_TOP2(CLK_TOP_PWM2_FB, "pwm2_fb", "rg_pwm_infra", 10), + GATE_TOP2(CLK_TOP_PWM3_FB, "pwm3_fb", "rg_pwm_infra", 11), + GATE_TOP2(CLK_TOP_PWM4_FB, "pwm4_fb", "rg_pwm_infra", 12), + GATE_TOP2(CLK_TOP_PWM5_FB, "pwm5_fb", "rg_pwm_infra", 13), + GATE_TOP2(CLK_TOP_USB_1P, "usb_1p", "usb_78m", 14), + GATE_TOP2(CLK_TOP_FLASHIF_FREERUN, "flashif_freerun", "ahb_infra_sel", + 15), + GATE_TOP2(CLK_TOP_26M_HDMI_SIFM, "hdmi_sifm_26m", "clk26m_ck", 16), + GATE_TOP2(CLK_TOP_26M_CEC, "cec_26m", "clk26m_ck", 17), + GATE_TOP2(CLK_TOP_32K_CEC, "cec_32k", "clk32k", 18), + GATE_TOP2(CLK_TOP_66M_ETH, "eth_66m", "ahb_infra_d2", 19), + GATE_TOP2(CLK_TOP_133M_ETH, "eth_133m", "ahb_infra_sel", 20), + GATE_TOP2(CLK_TOP_FETH_25M, "feth_25m", "ifr_eth_25m_sel", 21), + GATE_TOP2(CLK_TOP_FETH_50M, "feth_50m", "rg_eth", 22), + GATE_TOP2(CLK_TOP_FLASHIF_AXI, "flashif_axi", "ahb_infra_sel", 23), + GATE_TOP2(CLK_TOP_USBIF, "usbif", "ahb_infra_sel", 24), + GATE_TOP2(CLK_TOP_UART2, "uart2", "rg_uart2", 25), + GATE_TOP2(CLK_TOP_BSI, "bsi", "ahb_infra_sel", 26), + GATE_TOP2(CLK_TOP_GCPU_B, "gcpu_b", "ahb_infra_sel", 27), + GATE_TOP2_I(CLK_TOP_MSDC0_INFRA, "msdc0_infra", "msdc0", 28), + GATE_TOP2_I(CLK_TOP_MSDC1_INFRA, "msdc1_infra", "msdc1", 29), + GATE_TOP2_I(CLK_TOP_MSDC2_INFRA, "msdc2_infra", "rg_msdc2", 30), + GATE_TOP2(CLK_TOP_USB_78M, "usb_78m", "usb_78m_sel", 31), + /* TOP3 */ + GATE_TOP3(CLK_TOP_RG_SPINOR, "rg_spinor", "spinor_sel", 0), + GATE_TOP3(CLK_TOP_RG_MSDC2, "rg_msdc2", "msdc2_sel", 1), + GATE_TOP3(CLK_TOP_RG_ETH, "rg_eth", "eth_sel", 2), + GATE_TOP3(CLK_TOP_RG_VDEC, "rg_vdec", "vdec_mm_sel", 3), + GATE_TOP3(CLK_TOP_RG_FDPI0, "rg_fdpi0", "dpi0_mm_sel", 4), + GATE_TOP3(CLK_TOP_RG_FDPI1, "rg_fdpi1", "dpi1_mm_sel", 5), + GATE_TOP3(CLK_TOP_RG_AXI_MFG, "rg_axi_mfg", "axi_mfg_in_sel", 6), + GATE_TOP3(CLK_TOP_RG_SLOW_MFG, "rg_slow_mfg", "slow_mfg_sel", 7), + GATE_TOP3(CLK_TOP_RG_AUD1, "rg_aud1", "aud1_sel", 8), + GATE_TOP3(CLK_TOP_RG_AUD2, "rg_aud2", "aud2_sel", 9), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN1, "rg_aud_engen1", "aud_engen1_sel", 10), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN2, "rg_aud_engen2", "aud_engen2_sel", 11), + GATE_TOP3(CLK_TOP_RG_I2C, "rg_i2c", "i2c_sel", 12), + GATE_TOP3(CLK_TOP_RG_PWM_INFRA, "rg_pwm_infra", "pwm_sel", 13), + GATE_TOP3(CLK_TOP_RG_AUD_SPDIF_IN, "rg_aud_spdif_in", "aud_spdifin_sel", + 14), + GATE_TOP3(CLK_TOP_RG_UART2, "rg_uart2", "uart2_sel", 15), + GATE_TOP3(CLK_TOP_RG_BSI, "rg_bsi", "bsi_sel", 16), + GATE_TOP3(CLK_TOP_RG_DBG_ATCLK, "rg_dbg_atclk", "dbg_atclk_sel", 17), + GATE_TOP3(CLK_TOP_RG_NFIECC, "rg_nfiecc", "nfiecc_sel", 18), + /* TOP4 */ + GATE_TOP4_I(CLK_TOP_RG_APLL1_D2_EN, "rg_apll1_d2_en", "apll1_d2", 8), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D4_EN, "rg_apll1_d4_en", "apll1_d4", 9), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D8_EN, "rg_apll1_d8_en", "apll1_d8", 10), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D2_EN, "rg_apll2_d2_en", "apll2_d2", 11), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D4_EN, "rg_apll2_d4_en", "apll2_d4", 12), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D8_EN, "rg_apll2_d8_en", "apll2_d8", 13), + /* TOP5 */ + GATE_TOP5(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll12_ck_div0", 0), + GATE_TOP5(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll12_ck_div1", 1), + GATE_TOP5(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll12_ck_div2", 2), + GATE_TOP5(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll12_ck_div3", 3), + GATE_TOP5(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll12_ck_div4", 4), + GATE_TOP5(CLK_TOP_APLL12_DIV4B, "apll12_div4b", "apll12_ck_div4b", 5), + GATE_TOP5(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll12_ck_div5", 6), + GATE_TOP5(CLK_TOP_APLL12_DIV5B, "apll12_div5b", "apll12_ck_div5b", 7), + GATE_TOP5(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll12_ck_div6", 8), +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(MT8167_CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), + clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8167_clk_lock, clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt8167_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8167-topckgen", mtk_topckgen_init); + +static void __init mtk_infracfg_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + + mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base, + &mt8167_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt8167-infracfg", mtk_infracfg_init); + +#define MT8167_PLL_FMAX (2500UL * MHZ) + +#define CON0_MT8167_RST_BAR BIT(27) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8167_RST_BAR, \ + .fmax = MT8167_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT8167_PLL_FMAX }, + { .div = 1, .freq = 1000000000 }, + { .div = 2, .freq = 604500000 }, + { .div = 3, .freq = 253500000 }, + { .div = 4, .freq = 126750000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0, 0, + 21, 0x0104, 24, 0, 0x0104, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0, + HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000000, + HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0, 0, + 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0, 0, + 31, 0x0180, 1, 0x0194, 0x0184, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0, 0, + 31, 0x01A0, 1, 0x01B4, 0x01A4, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x01C0, 0x01D0, 0, 0, + 21, 0x01C4, 24, 0, 0x01C4, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x01E0, 0x01F0, 0, 0, + 21, 0x01E4, 24, 0, 0x01E4, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(MT8167_CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + mtk_clk_register_dividers(apmixed_adj_divs, ARRAY_SIZE(apmixed_adj_divs), + base, &mt8167_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8167-apmixedsys", + mtk_apmixedsys_init); diff --git a/drivers/clk/mediatek/clk-mt8173-mm.c b/drivers/clk/mediatek/clk-mt8173-mm.c new file mode 100644 index 000000000..5826eabdc --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8173-mm.c @@ -0,0 +1,134 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8173-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x0104, + .clr_ofs = 0x0108, + .sta_ofs = 0x0100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x0114, + .clr_ofs = 0x0118, + .sta_ofs = 0x0110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mt8173_mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6), + GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7), + GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8), + GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14), + GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 15), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16), + GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_SPLIT1, "mm_disp_split1", "mm_sel", 29), + GATE_MM0(CLK_MM_DISP_MERGE, "mm_disp_merge", "mm_sel", 30), + GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DISP_PWM0MM, "mm_disp_pwm0mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DISP_PWM026M, "mm_disp_pwm026m", "pwm_sel", 1), + GATE_MM1(CLK_MM_DISP_PWM1MM, "mm_disp_pwm1mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DISP_PWM126M, "mm_disp_pwm126m", "pwm_sel", 3), + GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4), + GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_dig", 5), + GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6), + GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_dig", 7), + GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "dpi0_sel", 8), + GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9), + GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "lvds_pxl", 10), + GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11), + GATE_MM1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi0_sel", 12), + GATE_MM1(CLK_MM_HDMI_PLLCK, "mm_hdmi_pllck", "hdmi_sel", 13), + GATE_MM1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll1", 14), + GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll2", 15), + GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "lvds_pxl", 16), + GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvds_cts", 17), + GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18), + GATE_MM1(CLK_MM_HDMI_HDCP, "mm_hdmi_hdcp", "hdcp_sel", 19), + GATE_MM1(CLK_MM_HDMI_HDCP24M, "mm_hdmi_hdcp24m", "hdcp_24m_sel", 20), +}; + +struct clk_mt8173_mm_driver_data { + const struct mtk_gate *gates_clk; + int gates_num; +}; + +static const struct clk_mt8173_mm_driver_data mt8173_mmsys_driver_data = { + .gates_clk = mt8173_mm_clks, + .gates_num = ARRAY_SIZE(mt8173_mm_clks), +}; + +static int clk_mt8173_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + const struct clk_mt8173_mm_driver_data *data; + struct clk_hw_onecell_data *clk_data; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + data = &mt8173_mmsys_driver_data; + + ret = mtk_clk_register_gates(node, data->gates_clk, data->gates_num, + clk_data); + if (ret) + return ret; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + return ret; + + return 0; +} + +static struct platform_driver clk_mt8173_mm_drv = { + .driver = { + .name = "clk-mt8173-mm", + }, + .probe = clk_mt8173_mm_probe, +}; + +builtin_platform_driver(clk_mt8173_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8173.c b/drivers/clk/mediatek/clk-mt8173.c new file mode 100644 index 000000000..b8529ee71 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8173.c @@ -0,0 +1,1125 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/clk.h> +#include <linux/of.h> +#include <linux/of_address.h> + +#include "clk-cpumux.h" +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8173-clk.h> + +/* + * For some clocks, we don't care what their actual rates are. And these + * clocks may change their rate on different products or different scenarios. + * So we model these clocks' rate as 0, to denote it's not an actual rate. + */ +#define DUMMY_RATE 0 + +static DEFINE_SPINLOCK(mt8173_clk_lock); + +static const struct mtk_fixed_clk fixed_clks[] __initconst = { + FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk26m", DUMMY_RATE), + FIXED_CLK(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk26m", 125 * MHZ), + FIXED_CLK(CLK_TOP_DSI0_DIG, "dsi0_dig", "clk26m", DUMMY_RATE), + FIXED_CLK(CLK_TOP_DSI1_DIG, "dsi1_dig", "clk26m", DUMMY_RATE), + FIXED_CLK(CLK_TOP_LVDS_PXL, "lvds_pxl", "lvdspll", DUMMY_RATE), + FIXED_CLK(CLK_TOP_LVDS_CTS, "lvds_cts", "lvdspll", DUMMY_RATE), +}; + +static const struct mtk_fixed_factor top_divs[] __initconst = { + FACTOR(CLK_TOP_ARMCA7PLL_754M, "armca7pll_754m", "armca7pll", 1, 2), + FACTOR(CLK_TOP_ARMCA7PLL_502M, "armca7pll_502m", "armca7pll", 1, 3), + + FACTOR(CLK_TOP_MAIN_H546M, "main_h546m", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAIN_H364M, "main_h364m", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAIN_H218P4M, "main_h218p4m", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAIN_H156M, "main_h156m", "mainpll", 1, 7), + + FACTOR(CLK_TOP_TVDPLL_445P5M, "tvdpll_445p5m", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_594M, "tvdpll_594m", "tvdpll", 1, 3), + + FACTOR(CLK_TOP_UNIV_624M, "univ_624m", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIV_416M, "univ_416m", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIV_249P6M, "univ_249p6m", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIV_178P3M, "univ_178p3m", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIV_48M, "univ_48m", "univpll", 1, 26), + + FACTOR(CLK_TOP_CLKRTC_EXT, "clkrtc_ext", "clk32k", 1, 1), + FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793), + FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1), + + FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2), + FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3), + + FACTOR(CLK_TOP_ARMCA7PLL_D2, "armca7pll_d2", "armca7pll_754m", 1, 1), + FACTOR(CLK_TOP_ARMCA7PLL_D3, "armca7pll_d3", "armca7pll_502m", 1, 1), + + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "clkph_mck_o", 1, 1), + FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2), + FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4), + FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8), + FACTOR(CLK_TOP_DMPLL_D16, "dmpll_d16", "clkph_mck_o", 1, 16), + + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_MSDCPLL2, "msdcpll2_ck", "msdcpll2", 1, 1), + FACTOR(CLK_TOP_MSDCPLL2_D2, "msdcpll2_d2", "msdcpll2", 1, 2), + FACTOR(CLK_TOP_MSDCPLL2_D4, "msdcpll2_d4", "msdcpll2", 1, 4), + + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "main_h546m", 1, 1), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "main_h546m", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "main_h546m", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "main_h546m", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "main_h546m", 1, 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "main_h364m", 1, 1), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "main_h364m", 1, 2), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "main_h364m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "main_h218p4m", 1, 1), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "main_h218p4m", 1, 2), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "main_h218p4m", 1, 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "main_h156m", 1, 1), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "main_h156m", 1, 2), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "main_h156m", 1, 4), + + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll_594m", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_594m", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_594m", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_594m", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_594m", 1, 16), + + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univ_624m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univ_624m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univ_624m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univ_624m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univ_416m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univ_416m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univ_416m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univ_416m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univ_249p6m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univ_249p6m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univ_249p6m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univ_249p6m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univ_178p3m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univ_48m", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_D52, "univpll_d52", "univ_48m", 1, 2), + + FACTOR(CLK_TOP_VCODECPLL, "vcodecpll_ck", "vcodecpll", 1, 3), + FACTOR(CLK_TOP_VCODECPLL_370P5, "vcodecpll_370p5", "vcodecpll", 1, 4), + + FACTOR(CLK_TOP_VENCPLL, "vencpll_ck", "vencpll", 1, 1), + FACTOR(CLK_TOP_VENCPLL_D2, "vencpll_d2", "vencpll", 1, 2), + FACTOR(CLK_TOP_VENCPLL_D4, "vencpll_d4", "vencpll", 1, 4), +}; + +static const char * const axi_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const mem_parents[] __initconst = { + "clk26m", + "dmpll_ck" +}; + +static const char * const ddrphycfg_parents[] __initconst = { + "clk26m", + "syspll1_d8" +}; + +static const char * const mm_parents[] __initconst = { + "clk26m", + "vencpll_d2", + "main_h364m", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2" +}; + +static const char * const pwm_parents[] __initconst = { + "clk26m", + "univpll2_d4", + "univpll3_d2", + "univpll1_d4" +}; + +static const char * const vdec_parents[] __initconst = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "mmpll_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const venc_parents[] __initconst = { + "clk26m", + "vcodecpll_ck", + "tvdpll_445p5m", + "univpll_d3", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "univpll2_d2", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const mfg_parents[] __initconst = { + "clk26m", + "mmpll_ck", + "dmpll_ck", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "clk26m", + "syspll_d3", + "syspll1_d2", + "syspll_d5", + "univpll_d3", + "univpll1_d2", + "univpll_d5", + "univpll2_d2" +}; + +static const char * const camtg_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll2_d2", + "syspll3_d2", + "syspll3_d4", + "univpll1_d4" +}; + +static const char * const uart_parents[] __initconst = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] __initconst = { + "clk26m", + "syspll3_d2", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d4", + "univpll1_d8" +}; + +static const char * const usb20_parents[] __initconst = { + "clk26m", + "univpll1_d8", + "univpll3_d4" +}; + +static const char * const usb30_parents[] __initconst = { + "clk26m", + "univpll3_d2", + "usb_syspll_125m", + "univpll2_d4" +}; + +static const char * const msdc50_0_h_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const msdc50_0_parents[] __initconst = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "msdcpll_d4", + "vencpll_d4", + "tvdpll_ck", + "univpll_d2", + "univpll1_d2", + "mmpll_ck", + "msdcpll2_ck", + "msdcpll2_d2", + "msdcpll2_d4" +}; + +static const char * const msdc30_1_parents[] __initconst = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4" +}; + +static const char * const msdc30_2_parents[] __initconst = { + "clk26m", + "univpll2_d2", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d2" +}; + +static const char * const msdc30_3_parents[] __initconst = { + "clk26m", + "msdcpll2_ck", + "msdcpll2_d2", + "univpll2_d2", + "msdcpll2_d4", + "msdcpll_d4", + "univpll1_d4", + "syspll2_d2", + "syspll_d7", + "univpll_d7", + "vencpll_d4", + "msdcpll_ck", + "msdcpll_d2", + "msdcpll_d4" +}; + +static const char * const audio_parents[] __initconst = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] __initconst = { + "clk26m", + "syspll1_d4", + "syspll4_d2", + "univpll3_d2", + "univpll2_d8", + "dmpll_d4", + "dmpll_d8" +}; + +static const char * const pmicspi_parents[] __initconst = { + "clk26m", + "syspll1_d8", + "syspll3_d4", + "syspll1_d16", + "univpll3_d4", + "univpll_d26", + "dmpll_d8", + "dmpll_d16" +}; + +static const char * const scp_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "syspll_d5", + "dmpll_d2", + "dmpll_d4" +}; + +static const char * const atb_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "univpll_d5", + "dmpll_d2" +}; + +static const char * const venc_lt_parents[] __initconst = { + "clk26m", + "univpll_d3", + "vcodecpll_ck", + "tvdpll_445p5m", + "vencpll_d2", + "syspll_d3", + "univpll1_d2", + "univpll2_d2", + "syspll1_d2", + "univpll_d5", + "vcodecpll_370p5", + "dmpll_ck" +}; + +static const char * const dpi0_parents[] __initconst = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "clk26m", + "clk26m", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const irda_parents[] __initconst = { + "clk26m", + "univpll2_d4", + "syspll2_d4" +}; + +static const char * const cci400_parents[] __initconst = { + "clk26m", + "vencpll_ck", + "armca7pll_754m", + "armca7pll_502m", + "univpll_d2", + "syspll_d2", + "msdcpll_ck", + "dmpll_ck" +}; + +static const char * const aud_1_parents[] __initconst = { + "clk26m", + "apll1_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const aud_2_parents[] __initconst = { + "clk26m", + "apll2_ck", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const mem_mfg_in_parents[] __initconst = { + "clk26m", + "mmpll_ck", + "dmpll_ck", + "clk26m" +}; + +static const char * const axi_mfg_in_parents[] __initconst = { + "clk26m", + "axi_sel", + "dmpll_d2" +}; + +static const char * const scam_parents[] __initconst = { + "clk26m", + "syspll3_d2", + "univpll2_d4", + "dmpll_d4" +}; + +static const char * const spinfi_ifr_parents[] __initconst = { + "clk26m", + "univpll2_d8", + "univpll3_d4", + "syspll4_d2", + "univpll2_d4", + "univpll3_d2", + "syspll1_d4", + "univpll1_d4" +}; + +static const char * const hdmi_parents[] __initconst = { + "clk26m", + "hdmitx_dig_cts", + "hdmitxpll_d2", + "hdmitxpll_d3" +}; + +static const char * const dpilvds_parents[] __initconst = { + "clk26m", + "lvdspll", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "fpc_ck" +}; + +static const char * const msdc50_2_h_parents[] __initconst = { + "clk26m", + "syspll1_d2", + "syspll2_d2", + "syspll4_d2", + "univpll_d5", + "univpll1_d4" +}; + +static const char * const hdcp_parents[] __initconst = { + "clk26m", + "syspll4_d2", + "syspll3_d4", + "univpll2_d4" +}; + +static const char * const hdcp_24m_parents[] __initconst = { + "clk26m", + "univpll_d26", + "univpll_d52", + "univpll2_d8" +}; + +static const char * const rtc_parents[] __initconst = { + "clkrtc_int", + "clkrtc_ext", + "clk26m", + "univpll3_d8" +}; + +static const char * const i2s0_m_ck_parents[] __initconst = { + "apll1_div1", + "apll2_div1" +}; + +static const char * const i2s1_m_ck_parents[] __initconst = { + "apll1_div2", + "apll2_div2" +}; + +static const char * const i2s2_m_ck_parents[] __initconst = { + "apll1_div3", + "apll2_div3" +}; + +static const char * const i2s3_m_ck_parents[] __initconst = { + "apll1_div4", + "apll2_div4" +}; + +static const char * const i2s3_b_ck_parents[] __initconst = { + "apll1_div5", + "apll2_div5" +}; + +static const char * const ca53_parents[] __initconst = { + "clk26m", + "armca7pll", + "mainpll", + "univpll" +}; + +static const char * const ca72_parents[] __initconst = { + "clk26m", + "armca15pll", + "mainpll", + "univpll" +}; + +static const struct mtk_composite cpu_muxes[] __initconst = { + MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2), + MUX(CLK_INFRA_CA72SEL, "infra_ca72_sel", ca72_parents, 0x0000, 2, 2), +}; + +static const struct mtk_composite top_muxes[] __initconst = { + /* CLK_CFG_0 */ + MUX(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, 0x0040, 0, 3), + MUX(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x0040, 8, 1), + MUX_GATE(CLK_TOP_DDRPHYCFG_SEL, "ddrphycfg_sel", ddrphycfg_parents, 0x0040, 16, 1, 23), + MUX_GATE(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x0040, 24, 4, 31), + /* CLK_CFG_1 */ + MUX_GATE(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0050, 0, 2, 7), + MUX_GATE(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_parents, 0x0050, 8, 4, 15), + MUX_GATE(CLK_TOP_VENC_SEL, "venc_sel", venc_parents, 0x0050, 16, 4, 23), + MUX_GATE(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x0050, 24, 4, 31), + /* CLK_CFG_2 */ + MUX_GATE(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, 0x0060, 0, 3, 7), + MUX_GATE(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x0060, 8, 1, 15), + MUX_GATE(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x0060, 16, 3, 23), + MUX_GATE(CLK_TOP_USB20_SEL, "usb20_sel", usb20_parents, 0x0060, 24, 2, 31), + /* CLK_CFG_3 */ + MUX_GATE(CLK_TOP_USB30_SEL, "usb30_sel", usb30_parents, 0x0070, 0, 2, 7), + MUX_GATE(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", msdc50_0_h_parents, 0x0070, 8, 3, 15), + MUX_GATE(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_parents, 0x0070, 16, 4, 23), + MUX_GATE(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_parents, 0x0070, 24, 3, 31), + /* CLK_CFG_4 */ + MUX_GATE(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_2_parents, 0x0080, 0, 3, 7), + MUX_GATE(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_parents, 0x0080, 8, 4, 15), + MUX_GATE(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, 0x0080, 16, 2, 23), + MUX_GATE(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, 0x0080, 24, 3, 31), + /* CLK_CFG_5 */ + MUX_GATE(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, 0x0090, 0, 3, 7 /* 7:5 */), + MUX_GATE(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x0090, 8, 3, 15), + MUX_GATE(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x0090, 16, 2, 23), + MUX_GATE(CLK_TOP_VENC_LT_SEL, "venclt_sel", venc_lt_parents, 0x0090, 24, 4, 31), + /* CLK_CFG_6 */ + /* + * The dpi0_sel clock should not propagate rate changes to its parent + * clock so the dpi driver can have full control over PLL and divider. + */ + MUX_GATE_FLAGS(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x00a0, 0, 3, 7, 0), + MUX_GATE(CLK_TOP_IRDA_SEL, "irda_sel", irda_parents, 0x00a0, 8, 2, 15), + MUX_GATE(CLK_TOP_CCI400_SEL, "cci400_sel", cci400_parents, 0x00a0, 16, 3, 23), + MUX_GATE(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, 0x00a0, 24, 2, 31), + /* CLK_CFG_7 */ + MUX_GATE(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, 0x00b0, 0, 2, 7), + MUX_GATE(CLK_TOP_MEM_MFG_IN_SEL, "mem_mfg_in_sel", mem_mfg_in_parents, 0x00b0, 8, 2, 15), + MUX_GATE(CLK_TOP_AXI_MFG_IN_SEL, "axi_mfg_in_sel", axi_mfg_in_parents, 0x00b0, 16, 2, 23), + MUX_GATE(CLK_TOP_SCAM_SEL, "scam_sel", scam_parents, 0x00b0, 24, 2, 31), + /* CLK_CFG_12 */ + MUX_GATE(CLK_TOP_SPINFI_IFR_SEL, "spinfi_ifr_sel", spinfi_ifr_parents, 0x00c0, 0, 3, 7), + MUX_GATE(CLK_TOP_HDMI_SEL, "hdmi_sel", hdmi_parents, 0x00c0, 8, 2, 15), + MUX_GATE(CLK_TOP_DPILVDS_SEL, "dpilvds_sel", dpilvds_parents, 0x00c0, 24, 3, 31), + /* CLK_CFG_13 */ + MUX_GATE(CLK_TOP_MSDC50_2_H_SEL, "msdc50_2_h_sel", msdc50_2_h_parents, 0x00d0, 0, 3, 7), + MUX_GATE(CLK_TOP_HDCP_SEL, "hdcp_sel", hdcp_parents, 0x00d0, 8, 2, 15), + MUX_GATE(CLK_TOP_HDCP_24M_SEL, "hdcp_24m_sel", hdcp_24m_parents, 0x00d0, 16, 2, 23), + MUX(CLK_TOP_RTC_SEL, "rtc_sel", rtc_parents, 0x00d0, 24, 2), + + DIV_GATE(CLK_TOP_APLL1_DIV0, "apll1_div0", "aud_1_sel", 0x12c, 8, 0x120, 4, 24), + DIV_GATE(CLK_TOP_APLL1_DIV1, "apll1_div1", "aud_1_sel", 0x12c, 9, 0x124, 8, 0), + DIV_GATE(CLK_TOP_APLL1_DIV2, "apll1_div2", "aud_1_sel", 0x12c, 10, 0x124, 8, 8), + DIV_GATE(CLK_TOP_APLL1_DIV3, "apll1_div3", "aud_1_sel", 0x12c, 11, 0x124, 8, 16), + DIV_GATE(CLK_TOP_APLL1_DIV4, "apll1_div4", "aud_1_sel", 0x12c, 12, 0x124, 8, 24), + DIV_GATE(CLK_TOP_APLL1_DIV5, "apll1_div5", "apll1_div4", 0x12c, 13, 0x12c, 4, 0), + + DIV_GATE(CLK_TOP_APLL2_DIV0, "apll2_div0", "aud_2_sel", 0x12c, 16, 0x120, 4, 28), + DIV_GATE(CLK_TOP_APLL2_DIV1, "apll2_div1", "aud_2_sel", 0x12c, 17, 0x128, 8, 0), + DIV_GATE(CLK_TOP_APLL2_DIV2, "apll2_div2", "aud_2_sel", 0x12c, 18, 0x128, 8, 8), + DIV_GATE(CLK_TOP_APLL2_DIV3, "apll2_div3", "aud_2_sel", 0x12c, 19, 0x128, 8, 16), + DIV_GATE(CLK_TOP_APLL2_DIV4, "apll2_div4", "aud_2_sel", 0x12c, 20, 0x128, 8, 24), + DIV_GATE(CLK_TOP_APLL2_DIV5, "apll2_div5", "apll2_div4", 0x12c, 21, 0x12c, 4, 4), + + MUX(CLK_TOP_I2S0_M_SEL, "i2s0_m_ck_sel", i2s0_m_ck_parents, 0x120, 4, 1), + MUX(CLK_TOP_I2S1_M_SEL, "i2s1_m_ck_sel", i2s1_m_ck_parents, 0x120, 5, 1), + MUX(CLK_TOP_I2S2_M_SEL, "i2s2_m_ck_sel", i2s2_m_ck_parents, 0x120, 6, 1), + MUX(CLK_TOP_I2S3_M_SEL, "i2s3_m_ck_sel", i2s3_m_ck_parents, 0x120, 7, 1), + MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1), +}; + +static const struct mtk_gate_regs infra_cg_regs __initconst = { + .set_ofs = 0x0040, + .clr_ofs = 0x0044, + .sta_ofs = 0x0048, +}; + +#define GATE_ICG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &infra_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate infra_clks[] __initconst = { + GATE_ICG(CLK_INFRA_DBGCLK, "infra_dbgclk", "axi_sel", 0), + GATE_ICG(CLK_INFRA_SMI, "infra_smi", "mm_sel", 1), + GATE_ICG(CLK_INFRA_AUDIO, "infra_audio", "aud_intbus_sel", 5), + GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6), + GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7), + GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8), + GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "cpum_ck", 15), + GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16), + GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18), + GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22), + GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23), +}; + +static const struct mtk_fixed_factor infra_divs[] __initconst = { + FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2), +}; + +static const struct mtk_gate_regs peri0_cg_regs __initconst = { + .set_ofs = 0x0008, + .clr_ofs = 0x0010, + .sta_ofs = 0x0018, +}; + +static const struct mtk_gate_regs peri1_cg_regs __initconst = { + .set_ofs = 0x000c, + .clr_ofs = 0x0014, + .sta_ofs = 0x001c, +}; + +#define GATE_PERI0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_PERI1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &peri1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate peri_gates[] __initconst = { + /* PERI0 */ + GATE_PERI0(CLK_PERI_NFI, "peri_nfi", "axi_sel", 0), + GATE_PERI0(CLK_PERI_THERM, "peri_therm", "axi_sel", 1), + GATE_PERI0(CLK_PERI_PWM1, "peri_pwm1", "axi_sel", 2), + GATE_PERI0(CLK_PERI_PWM2, "peri_pwm2", "axi_sel", 3), + GATE_PERI0(CLK_PERI_PWM3, "peri_pwm3", "axi_sel", 4), + GATE_PERI0(CLK_PERI_PWM4, "peri_pwm4", "axi_sel", 5), + GATE_PERI0(CLK_PERI_PWM5, "peri_pwm5", "axi_sel", 6), + GATE_PERI0(CLK_PERI_PWM6, "peri_pwm6", "axi_sel", 7), + GATE_PERI0(CLK_PERI_PWM7, "peri_pwm7", "axi_sel", 8), + GATE_PERI0(CLK_PERI_PWM, "peri_pwm", "axi_sel", 9), + GATE_PERI0(CLK_PERI_USB0, "peri_usb0", "usb20_sel", 10), + GATE_PERI0(CLK_PERI_USB1, "peri_usb1", "usb20_sel", 11), + GATE_PERI0(CLK_PERI_AP_DMA, "peri_ap_dma", "axi_sel", 12), + GATE_PERI0(CLK_PERI_MSDC30_0, "peri_msdc30_0", "msdc50_0_sel", 13), + GATE_PERI0(CLK_PERI_MSDC30_1, "peri_msdc30_1", "msdc30_1_sel", 14), + GATE_PERI0(CLK_PERI_MSDC30_2, "peri_msdc30_2", "msdc30_2_sel", 15), + GATE_PERI0(CLK_PERI_MSDC30_3, "peri_msdc30_3", "msdc30_3_sel", 16), + GATE_PERI0(CLK_PERI_NLI_ARB, "peri_nli_arb", "axi_sel", 17), + GATE_PERI0(CLK_PERI_IRDA, "peri_irda", "irda_sel", 18), + GATE_PERI0(CLK_PERI_UART0, "peri_uart0", "axi_sel", 19), + GATE_PERI0(CLK_PERI_UART1, "peri_uart1", "axi_sel", 20), + GATE_PERI0(CLK_PERI_UART2, "peri_uart2", "axi_sel", 21), + GATE_PERI0(CLK_PERI_UART3, "peri_uart3", "axi_sel", 22), + GATE_PERI0(CLK_PERI_I2C0, "peri_i2c0", "axi_sel", 23), + GATE_PERI0(CLK_PERI_I2C1, "peri_i2c1", "axi_sel", 24), + GATE_PERI0(CLK_PERI_I2C2, "peri_i2c2", "axi_sel", 25), + GATE_PERI0(CLK_PERI_I2C3, "peri_i2c3", "axi_sel", 26), + GATE_PERI0(CLK_PERI_I2C4, "peri_i2c4", "axi_sel", 27), + GATE_PERI0(CLK_PERI_AUXADC, "peri_auxadc", "clk26m", 28), + GATE_PERI0(CLK_PERI_SPI0, "peri_spi0", "spi_sel", 29), + GATE_PERI0(CLK_PERI_I2C5, "peri_i2c5", "axi_sel", 30), + GATE_PERI0(CLK_PERI_NFIECC, "peri_nfiecc", "axi_sel", 31), + /* PERI1 */ + GATE_PERI1(CLK_PERI_SPI, "peri_spi", "spi_sel", 0), + GATE_PERI1(CLK_PERI_IRRX, "peri_irrx", "spi_sel", 1), + GATE_PERI1(CLK_PERI_I2C6, "peri_i2c6", "axi_sel", 2), +}; + +static const char * const uart_ck_sel_parents[] __initconst = { + "clk26m", + "uart_sel", +}; + +static const struct mtk_composite peri_clks[] __initconst = { + MUX(CLK_PERI_UART0_SEL, "uart0_ck_sel", uart_ck_sel_parents, 0x40c, 0, 1), + MUX(CLK_PERI_UART1_SEL, "uart1_ck_sel", uart_ck_sel_parents, 0x40c, 1, 1), + MUX(CLK_PERI_UART2_SEL, "uart2_ck_sel", uart_ck_sel_parents, 0x40c, 2, 1), + MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1), +}; + +static const struct mtk_gate_regs cg_regs_4_8_0 __initconst = { + .set_ofs = 0x0004, + .clr_ofs = 0x0008, + .sta_ofs = 0x0000, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &cg_regs_4_8_0, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate img_clks[] __initconst = { + GATE_IMG(CLK_IMG_LARB2_SMI, "img_larb2_smi", "mm_sel", 0), + GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "mm_sel", 5), + GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "mm_sel", 6), + GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "camtg_sel", 7), + GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "mm_sel", 8), + GATE_IMG(CLK_IMG_CAM_SV, "img_cam_sv", "mm_sel", 9), + GATE_IMG(CLK_IMG_FD, "img_fd", "mm_sel", 11), +}; + +static const struct mtk_gate_regs vdec0_cg_regs __initconst = { + .set_ofs = 0x0000, + .clr_ofs = 0x0004, + .sta_ofs = 0x0000, +}; + +static const struct mtk_gate_regs vdec1_cg_regs __initconst = { + .set_ofs = 0x0008, + .clr_ofs = 0x000c, + .sta_ofs = 0x0008, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec0_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +#define GATE_VDEC1(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &vdec1_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate vdec_clks[] __initconst = { + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", 0), +}; + +#define GATE_VENC(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &cg_regs_4_8_0, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate venc_clks[] __initconst = { + GATE_VENC(CLK_VENC_CKE0, "venc_cke0", "mm_sel", 0), + GATE_VENC(CLK_VENC_CKE1, "venc_cke1", "venc_sel", 4), + GATE_VENC(CLK_VENC_CKE2, "venc_cke2", "venc_sel", 8), + GATE_VENC(CLK_VENC_CKE3, "venc_cke3", "venc_sel", 12), +}; + +#define GATE_VENCLT(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &cg_regs_4_8_0, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr_inv, \ + } + +static const struct mtk_gate venclt_clks[] __initconst = { + GATE_VENCLT(CLK_VENCLT_CKE0, "venclt_cke0", "mm_sel", 0), + GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4), +}; + +static u16 infrasys_rst_ofs[] = { 0x30, 0x34, }; +static u16 pericfg_rst_ofs[] = { 0x0, 0x4, }; + +static const struct mtk_clk_rst_desc clk_rst_desc[] = { + /* infrasys */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = infrasys_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infrasys_rst_ofs), + }, + /* pericfg */ + { + .version = MTK_RST_SIMPLE, + .rst_bank_ofs = pericfg_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(pericfg_rst_ofs), + } +}; + +static struct clk_hw_onecell_data *mt8173_top_clk_data __initdata; +static struct clk_hw_onecell_data *mt8173_pll_clk_data __initdata; + +static void __init mtk_clk_enable_critical(void) +{ + if (!mt8173_top_clk_data || !mt8173_pll_clk_data) + return; + + clk_prepare_enable(mt8173_pll_clk_data->hws[CLK_APMIXED_ARMCA15PLL]->clk); + clk_prepare_enable(mt8173_pll_clk_data->hws[CLK_APMIXED_ARMCA7PLL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_MEM_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_DDRPHYCFG_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_CCI400_SEL]->clk); + clk_prepare_enable(mt8173_top_clk_data->hws[CLK_TOP_RTC_SEL]->clk); +} + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8173_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_clk_enable_critical(); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8173-topckgen", mtk_topckgen_init); + +static void __init mtk_infrasys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data); + + mtk_clk_register_cpumuxes(node, cpu_muxes, ARRAY_SIZE(cpu_muxes), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, &clk_rst_desc[0]); +} +CLK_OF_DECLARE(mtk_infrasys, "mediatek,mt8173-infracfg", mtk_infrasys_init); + +static void __init mtk_pericfg_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_gates, ARRAY_SIZE(peri_gates), + clk_data); + mtk_clk_register_composites(peri_clks, ARRAY_SIZE(peri_clks), base, + &mt8173_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_register_reset_controller(node, &clk_rst_desc[1]); +} +CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init); + +struct mtk_clk_usb { + int id; + const char *name; + const char *parent; + u32 reg_ofs; +}; + +#define APMIXED_USB(_id, _name, _parent, _reg_ofs) { \ + .id = _id, \ + .name = _name, \ + .parent = _parent, \ + .reg_ofs = _reg_ofs, \ + } + +static const struct mtk_clk_usb apmixed_usb[] __initconst = { + APMIXED_USB(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8), +}; + +#define MT8173_PLL_FMAX (3000UL * MHZ) + +#define CON0_MT8173_RST_BAR BIT(24) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8173_RST_BAR, \ + .fmax = MT8173_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT8173_PLL_FMAX }, + { .div = 1, .freq = 1000000000 }, + { .div = 2, .freq = 702000000 }, + { .div = 3, .freq = 253500000 }, + { .div = 4, .freq = 126750000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMCA15PLL, "armca15pll", 0x200, 0x20c, 0, 0, 21, 0x204, 24, 0x0, 0x204, 0), + PLL(CLK_APMIXED_ARMCA7PLL, "armca7pll", 0x210, 0x21c, 0, 0, 21, 0x214, 24, 0x0, 0x214, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x220, 0x22c, 0xf0000100, HAVE_RST_BAR, 21, 0x220, 4, 0x0, 0x224, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x230, 0x23c, 0xfe000000, HAVE_RST_BAR, 7, 0x230, 4, 0x0, 0x234, 14), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x240, 0x24c, 0, 0, 21, 0x244, 24, 0x0, 0x244, 0, mmpll_div_table), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x250, 0x25c, 0, 0, 21, 0x250, 4, 0x0, 0x254, 0), + PLL(CLK_APMIXED_VENCPLL, "vencpll", 0x260, 0x26c, 0, 0, 21, 0x260, 4, 0x0, 0x264, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x270, 0x27c, 0, 0, 21, 0x270, 4, 0x0, 0x274, 0), + PLL(CLK_APMIXED_MPLL, "mpll", 0x280, 0x28c, 0, 0, 21, 0x280, 4, 0x0, 0x284, 0), + PLL(CLK_APMIXED_VCODECPLL, "vcodecpll", 0x290, 0x29c, 0, 0, 21, 0x290, 4, 0x0, 0x294, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x2a0, 0x2b0, 0, 0, 31, 0x2a0, 4, 0x2a4, 0x2a4, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x2b4, 0x2c4, 0, 0, 31, 0x2b4, 4, 0x2b8, 0x2b8, 0), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x2d0, 0x2dc, 0, 0, 21, 0x2d0, 4, 0x0, 0x2d4, 0), + PLL(CLK_APMIXED_MSDCPLL2, "msdcpll2", 0x2f0, 0x2fc, 0, 0, 21, 0x2f0, 4, 0x0, 0x2f4, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + struct clk_hw *hw; + int r, i; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) { + iounmap(base); + return; + } + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) { + const struct mtk_clk_usb *cku = &apmixed_usb[i]; + + hw = mtk_clk_register_ref2usb_tx(cku->name, cku->parent, base + cku->reg_ofs); + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %ld\n", cku->name, PTR_ERR(hw)); + continue; + } + + clk_data->hws[cku->id] = hw; + } + + hw = clk_hw_register_divider(NULL, "hdmi_ref", "tvdpll_594m", 0, + base + 0x40, 16, 3, CLK_DIVIDER_POWER_OF_TWO, + NULL); + clk_data->hws[CLK_APMIXED_HDMI_REF] = hw; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + + mtk_clk_enable_critical(); +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys", + mtk_apmixedsys_init); + +static void __init mtk_imgsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK); + + mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init); + +static void __init mtk_vdecsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK); + + mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init); + +static void __init mtk_vencsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK); + + mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init); + +static void __init mtk_vencltsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK); + + mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_vencltsys, "mediatek,mt8173-vencltsys", mtk_vencltsys_init); diff --git a/drivers/clk/mediatek/clk-mt8183-audio.c b/drivers/clk/mediatek/clk-mt8183-audio.c new file mode 100644 index 000000000..b2d7746ed --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-audio.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs audio0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs audio1_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x4, + .sta_ofs = 0x4, +}; + +#define GATE_AUDIO0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUDIO1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate audio_clks[] = { + /* AUDIO0 */ + GATE_AUDIO0(CLK_AUDIO_AFE, "aud_afe", "audio_sel", + 2), + GATE_AUDIO0(CLK_AUDIO_22M, "aud_22m", "aud_eng1_sel", + 8), + GATE_AUDIO0(CLK_AUDIO_24M, "aud_24m", "aud_eng2_sel", + 9), + GATE_AUDIO0(CLK_AUDIO_APLL2_TUNER, "aud_apll2_tuner", "aud_eng2_sel", + 18), + GATE_AUDIO0(CLK_AUDIO_APLL_TUNER, "aud_apll_tuner", "aud_eng1_sel", + 19), + GATE_AUDIO0(CLK_AUDIO_TDM, "aud_tdm", "apll12_divb", + 20), + GATE_AUDIO0(CLK_AUDIO_ADC, "aud_adc", "audio_sel", + 24), + GATE_AUDIO0(CLK_AUDIO_DAC, "aud_dac", "audio_sel", + 25), + GATE_AUDIO0(CLK_AUDIO_DAC_PREDIS, "aud_dac_predis", "audio_sel", + 26), + GATE_AUDIO0(CLK_AUDIO_TML, "aud_tml", "audio_sel", + 27), + /* AUDIO1 */ + GATE_AUDIO1(CLK_AUDIO_I2S1, "aud_i2s1", "audio_sel", + 4), + GATE_AUDIO1(CLK_AUDIO_I2S2, "aud_i2s2", "audio_sel", + 5), + GATE_AUDIO1(CLK_AUDIO_I2S3, "aud_i2s3", "audio_sel", + 6), + GATE_AUDIO1(CLK_AUDIO_I2S4, "aud_i2s4", "audio_sel", + 7), + GATE_AUDIO1(CLK_AUDIO_PDN_ADDA6_ADC, "aud_pdn_adda6_adc", "audio_sel", + 20), +}; + +static int clk_mt8183_audio_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + int r; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_AUDIO_NR_CLK); + + mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + return r; + + r = devm_of_platform_populate(&pdev->dev); + if (r) + of_clk_del_provider(node); + + return r; +} + +static const struct of_device_id of_match_clk_mt8183_audio[] = { + { .compatible = "mediatek,mt8183-audiosys", }, + {} +}; + +static struct platform_driver clk_mt8183_audio_drv = { + .probe = clk_mt8183_audio_probe, + .driver = { + .name = "clk-mt8183-audio", + .of_match_table = of_match_clk_mt8183_audio, + }, +}; + +builtin_platform_driver(clk_mt8183_audio_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-cam.c b/drivers/clk/mediatek/clk-mt8183-cam.c new file mode 100644 index 000000000..6907b1a6a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-cam.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB6, "cam_larb6", "cam_sel", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "cam_sel", 1), + GATE_CAM(CLK_CAM_LARB3, "cam_larb3", "cam_sel", 2), + GATE_CAM(CLK_CAM_CAM, "cam_cam", "cam_sel", 6), + GATE_CAM(CLK_CAM_CAMTG, "cam_camtg", "cam_sel", 7), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "cam_sel", 8), + GATE_CAM(CLK_CAM_CAMSV0, "cam_camsv0", "cam_sel", 9), + GATE_CAM(CLK_CAM_CAMSV1, "cam_camsv1", "cam_sel", 10), + GATE_CAM(CLK_CAM_CAMSV2, "cam_camsv2", "cam_sel", 11), + GATE_CAM(CLK_CAM_CCU, "cam_ccu", "cam_sel", 12), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_cam[] = { + { + .compatible = "mediatek,mt8183-camsys", + .data = &cam_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-cam", + .of_match_table = of_match_clk_mt8183_cam, + }, +}; + +builtin_platform_driver(clk_mt8183_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-img.c b/drivers/clk/mediatek/clk-mt8183-img.c new file mode 100644 index 000000000..8d884425d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-img.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_LARB5, "img_larb5", "img_sel", 0), + GATE_IMG(CLK_IMG_LARB2, "img_larb2", "img_sel", 1), + GATE_IMG(CLK_IMG_DIP, "img_dip", "img_sel", 2), + GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "img_sel", 3), + GATE_IMG(CLK_IMG_DPE, "img_dpe", "img_sel", 4), + GATE_IMG(CLK_IMG_RSC, "img_rsc", "img_sel", 5), + GATE_IMG(CLK_IMG_MFB, "img_mfb", "img_sel", 6), + GATE_IMG(CLK_IMG_WPE_A, "img_wpe_a", "img_sel", 7), + GATE_IMG(CLK_IMG_WPE_B, "img_wpe_b", "img_sel", 8), + GATE_IMG(CLK_IMG_OWE, "img_owe", "img_sel", 9), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_img[] = { + { + .compatible = "mediatek,mt8183-imgsys", + .data = &img_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-img", + .of_match_table = of_match_clk_mt8183_img, + }, +}; + +builtin_platform_driver(clk_mt8183_img_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-ipu0.c b/drivers/clk/mediatek/clk-mt8183-ipu0.c new file mode 100644 index 000000000..953a8a33d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-ipu0.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs ipu_core0_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IPU_CORE0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_core0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipu_core0_clks[] = { + GATE_IPU_CORE0(CLK_IPU_CORE0_JTAG, "ipu_core0_jtag", "dsp_sel", 0), + GATE_IPU_CORE0(CLK_IPU_CORE0_AXI, "ipu_core0_axi", "dsp_sel", 1), + GATE_IPU_CORE0(CLK_IPU_CORE0_IPU, "ipu_core0_ipu", "dsp_sel", 2), +}; + +static const struct mtk_clk_desc ipu_core0_desc = { + .clks = ipu_core0_clks, + .num_clks = ARRAY_SIZE(ipu_core0_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_ipu_core0[] = { + { + .compatible = "mediatek,mt8183-ipu_core0", + .data = &ipu_core0_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_ipu_core0_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-ipu_core0", + .of_match_table = of_match_clk_mt8183_ipu_core0, + }, +}; + +builtin_platform_driver(clk_mt8183_ipu_core0_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-ipu1.c b/drivers/clk/mediatek/clk-mt8183-ipu1.c new file mode 100644 index 000000000..221d12265 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-ipu1.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs ipu_core1_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IPU_CORE1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_core1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipu_core1_clks[] = { + GATE_IPU_CORE1(CLK_IPU_CORE1_JTAG, "ipu_core1_jtag", "dsp_sel", 0), + GATE_IPU_CORE1(CLK_IPU_CORE1_AXI, "ipu_core1_axi", "dsp_sel", 1), + GATE_IPU_CORE1(CLK_IPU_CORE1_IPU, "ipu_core1_ipu", "dsp_sel", 2), +}; + +static const struct mtk_clk_desc ipu_core1_desc = { + .clks = ipu_core1_clks, + .num_clks = ARRAY_SIZE(ipu_core1_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_ipu_core1[] = { + { + .compatible = "mediatek,mt8183-ipu_core1", + .data = &ipu_core1_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_ipu_core1_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-ipu_core1", + .of_match_table = of_match_clk_mt8183_ipu_core1, + }, +}; + +builtin_platform_driver(clk_mt8183_ipu_core1_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_adl.c b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c new file mode 100644 index 000000000..8c4fd96df --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-ipu_adl.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs ipu_adl_cg_regs = { + .set_ofs = 0x204, + .clr_ofs = 0x204, + .sta_ofs = 0x204, +}; + +#define GATE_IPU_ADL_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_adl_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate ipu_adl_clks[] = { + GATE_IPU_ADL_I(CLK_IPU_ADL_CABGEN, "ipu_adl_cabgen", "dsp_sel", 24), +}; + +static const struct mtk_clk_desc ipu_adl_desc = { + .clks = ipu_adl_clks, + .num_clks = ARRAY_SIZE(ipu_adl_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_ipu_adl[] = { + { + .compatible = "mediatek,mt8183-ipu_adl", + .data = &ipu_adl_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_ipu_adl_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-ipu_adl", + .of_match_table = of_match_clk_mt8183_ipu_adl, + }, +}; + +builtin_platform_driver(clk_mt8183_ipu_adl_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-ipu_conn.c b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c new file mode 100644 index 000000000..14a4c3ff8 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-ipu_conn.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs ipu_conn_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs ipu_conn_apb_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x10, + .sta_ofs = 0x10, +}; + +static const struct mtk_gate_regs ipu_conn_axi_cg_regs = { + .set_ofs = 0x18, + .clr_ofs = 0x18, + .sta_ofs = 0x18, +}; + +static const struct mtk_gate_regs ipu_conn_axi1_cg_regs = { + .set_ofs = 0x1c, + .clr_ofs = 0x1c, + .sta_ofs = 0x1c, +}; + +static const struct mtk_gate_regs ipu_conn_axi2_cg_regs = { + .set_ofs = 0x20, + .clr_ofs = 0x20, + .sta_ofs = 0x20, +}; + +#define GATE_IPU_CONN(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_conn_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_IPU_CONN_APB(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_conn_apb_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) + +#define GATE_IPU_CONN_AXI_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_conn_axi_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_IPU_CONN_AXI1_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_conn_axi1_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_IPU_CONN_AXI2_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipu_conn_axi2_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate ipu_conn_clks[] = { + GATE_IPU_CONN(CLK_IPU_CONN_IPU, + "ipu_conn_ipu", "dsp_sel", 0), + GATE_IPU_CONN(CLK_IPU_CONN_AHB, + "ipu_conn_ahb", "dsp_sel", 1), + GATE_IPU_CONN(CLK_IPU_CONN_AXI, + "ipu_conn_axi", "dsp_sel", 2), + GATE_IPU_CONN(CLK_IPU_CONN_ISP, + "ipu_conn_isp", "dsp_sel", 3), + GATE_IPU_CONN(CLK_IPU_CONN_CAM_ADL, + "ipu_conn_cam_adl", "dsp_sel", 4), + GATE_IPU_CONN(CLK_IPU_CONN_IMG_ADL, + "ipu_conn_img_adl", "dsp_sel", 5), + GATE_IPU_CONN_APB(CLK_IPU_CONN_DAP_RX, + "ipu_conn_dap_rx", "dsp1_sel", 0), + GATE_IPU_CONN_APB(CLK_IPU_CONN_APB2AXI, + "ipu_conn_apb2axi", "dsp1_sel", 3), + GATE_IPU_CONN_APB(CLK_IPU_CONN_APB2AHB, + "ipu_conn_apb2ahb", "dsp1_sel", 20), + GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU_CAB1TO2, + "ipu_conn_ipu_cab1to2", "dsp1_sel", 6), + GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU1_CAB1TO2, + "ipu_conn_ipu1_cab1to2", "dsp1_sel", 13), + GATE_IPU_CONN_AXI_I(CLK_IPU_CONN_IPU2_CAB1TO2, + "ipu_conn_ipu2_cab1to2", "dsp1_sel", 20), + GATE_IPU_CONN_AXI1_I(CLK_IPU_CONN_CAB3TO3, + "ipu_conn_cab3to3", "dsp1_sel", 0), + GATE_IPU_CONN_AXI2_I(CLK_IPU_CONN_CAB2TO1, + "ipu_conn_cab2to1", "dsp1_sel", 14), + GATE_IPU_CONN_AXI2_I(CLK_IPU_CONN_CAB3TO1_SLICE, + "ipu_conn_cab3to1_slice", "dsp1_sel", 17), +}; + +static const struct mtk_clk_desc ipu_conn_desc = { + .clks = ipu_conn_clks, + .num_clks = ARRAY_SIZE(ipu_conn_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_ipu_conn[] = { + { + .compatible = "mediatek,mt8183-ipu_conn", + .data = &ipu_conn_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_ipu_conn_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-ipu_conn", + .of_match_table = of_match_clk_mt8183_ipu_conn, + }, +}; + +builtin_platform_driver(clk_mt8183_ipu_conn_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-mfgcfg.c b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c new file mode 100644 index 000000000..730c9ae5e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-mfgcfg.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, CLK_SET_RATE_PARENT) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0) +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_mfg[] = { + { + .compatible = "mediatek,mt8183-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-mfg", + .of_match_table = of_match_clk_mt8183_mfg, + }, +}; + +builtin_platform_driver(clk_mt8183_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-mm.c b/drivers/clk/mediatek/clk-mt8183-mm.c new file mode 100644 index 000000000..11ecc6fb0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-mm.c @@ -0,0 +1,106 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0), + GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1), + GATE_MM0(CLK_MM_SMI_LARB1, "mm_smi_larb1", "mm_sel", 2), + GATE_MM0(CLK_MM_GALS_COMM0, "mm_gals_comm0", "mm_sel", 3), + GATE_MM0(CLK_MM_GALS_COMM1, "mm_gals_comm1", "mm_sel", 4), + GATE_MM0(CLK_MM_GALS_CCU2MM, "mm_gals_ccu2mm", "mm_sel", 5), + GATE_MM0(CLK_MM_GALS_IPU12MM, "mm_gals_ipu12mm", "mm_sel", 6), + GATE_MM0(CLK_MM_GALS_IMG2MM, "mm_gals_img2mm", "mm_sel", 7), + GATE_MM0(CLK_MM_GALS_CAM2MM, "mm_gals_cam2mm", "mm_sel", 8), + GATE_MM0(CLK_MM_GALS_IPU2MM, "mm_gals_ipu2mm", "mm_sel", 9), + GATE_MM0(CLK_MM_MDP_DL_TXCK, "mm_mdp_dl_txck", "mm_sel", 10), + GATE_MM0(CLK_MM_IPU_DL_TXCK, "mm_ipu_dl_txck", "mm_sel", 11), + GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 12), + GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 13), + GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 14), + GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 15), + GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 16), + GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 17), + GATE_MM0(CLK_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_sel", 18), + GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 19), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 20), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 21), + GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 22), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 23), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 24), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 25), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 26), + GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 27), + GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 28), + GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 29), + GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 30), + GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31), + /* MM1 */ + GATE_MM1(CLK_MM_DSI0_MM, "mm_dsi0_mm", "mm_sel", 0), + GATE_MM1(CLK_MM_DSI0_IF, "mm_dsi0_if", "mm_sel", 1), + GATE_MM1(CLK_MM_DPI_MM, "mm_dpi_mm", "mm_sel", 2), + GATE_MM1(CLK_MM_DPI_IF, "mm_dpi_if", "dpi0_sel", 3), + GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 4), + GATE_MM1(CLK_MM_MDP_DL_RX, "mm_mdp_dl_rx", "mm_sel", 5), + GATE_MM1(CLK_MM_IPU_DL_RX, "mm_ipu_dl_rx", "mm_sel", 6), + GATE_MM1(CLK_MM_26M, "mm_26m", "f_f26m_ck", 7), + GATE_MM1(CLK_MM_MMSYS_R2Y, "mm_mmsys_r2y", "mm_sel", 8), + GATE_MM1(CLK_MM_DISP_RSZ, "mm_disp_rsz", "mm_sel", 9), + GATE_MM1(CLK_MM_MDP_AAL, "mm_mdp_aal", "mm_sel", 10), + GATE_MM1(CLK_MM_MDP_CCORR, "mm_mdp_ccorr", "mm_sel", 11), + GATE_MM1(CLK_MM_DBI_MM, "mm_dbi_mm", "mm_sel", 12), + GATE_MM1(CLK_MM_DBI_IF, "mm_dbi_if", "dpi0_sel", 13), +}; + +static int clk_mt8183_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static struct platform_driver clk_mt8183_mm_drv = { + .probe = clk_mt8183_mm_probe, + .driver = { + .name = "clk-mt8183-mm", + }, +}; + +builtin_platform_driver(clk_mt8183_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-vdec.c b/drivers/clk/mediatek/clk-mt8183-vdec.c new file mode 100644 index 000000000..c294e50b9 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-vdec.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0_I(CLK_VDEC_VDEC, "vdec_vdec", "mm_sel", 0), + /* VDEC1 */ + GATE_VDEC1_I(CLK_VDEC_LARB1, "vdec_larb1", "mm_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_vdec[] = { + { + .compatible = "mediatek,mt8183-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-vdec", + .of_match_table = of_match_clk_mt8183_vdec, + }, +}; + +builtin_platform_driver(clk_mt8183_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt8183-venc.c b/drivers/clk/mediatek/clk-mt8183-venc.c new file mode 100644 index 000000000..0051c5d92 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183-venc.c @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC_I(CLK_VENC_LARB, "venc_larb", + "mm_sel", 0), + GATE_VENC_I(CLK_VENC_VENC, "venc_venc", + "mm_sel", 4), + GATE_VENC_I(CLK_VENC_JPGENC, "venc_jpgenc", + "mm_sel", 8), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt8183_venc[] = { + { + .compatible = "mediatek,mt8183-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8183_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8183-venc", + .of_match_table = of_match_clk_mt8183_venc, + }, +}; + +builtin_platform_driver(clk_mt8183_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt8183.c b/drivers/clk/mediatek/clk-mt8183.c new file mode 100644 index 000000000..1860a35a7 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8183.c @@ -0,0 +1,1369 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2018 MediaTek Inc. +// Author: Weiyi Lu <weiyi.lu@mediatek.com> + +#include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8183-clk.h> + +static DEFINE_SPINLOCK(mt8183_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_CLK26M, "f_f26m_ck", "clk26m", 26000000), + FIXED_CLK(CLK_TOP_ULPOSC, "osc", NULL, 250000), + FIXED_CLK(CLK_TOP_UNIVP_192M, "univpll_192m", "univpll", 192000000), +}; + +static const struct mtk_fixed_factor top_early_divs[] = { + FACTOR(CLK_TOP_CLK13M, "clk13m", "clk26m", 1, 2), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_F26M_CK_D2, "csw_f26m_ck_d2", "clk26m", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, + 1), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "syspll_ck", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_D2_D2, "syspll_d2_d2", "syspll_d2", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_D2_D4, "syspll_d2_d4", "syspll_d2", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D2_D8, "syspll_d2_d8", "syspll_d2", 1, + 8), + FACTOR(CLK_TOP_SYSPLL_D2_D16, "syspll_d2_d16", "syspll_d2", 1, + 16), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, + 3), + FACTOR(CLK_TOP_SYSPLL_D3_D2, "syspll_d3_d2", "syspll_d3", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_D3_D4, "syspll_d3_d4", "syspll_d3", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D3_D8, "syspll_d3_d8", "syspll_d3", 1, + 8), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, + 5), + FACTOR(CLK_TOP_SYSPLL_D5_D2, "syspll_d5_d2", "syspll_d5", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_D5_D4, "syspll_d5_d4", "syspll_d5", 1, + 4), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, + 7), + FACTOR(CLK_TOP_SYSPLL_D7_D2, "syspll_d7_d2", "syspll_d7", 1, + 2), + FACTOR(CLK_TOP_SYSPLL_D7_D4, "syspll_d7_d4", "syspll_d7", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, + 1), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll_ck", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL_D2_D8, "univpll_d2_d8", "univpll_d2", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, + 3), + FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, + 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, + 4), + FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, + 8), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, + 7), + FACTOR(CLK_TOP_UNIVP_192M_CK, "univ_192m_ck", "univpll_192m", 1, + 1), + FACTOR(CLK_TOP_UNIVP_192M_D2, "univ_192m_d2", "univ_192m_ck", 1, + 2), + FACTOR(CLK_TOP_UNIVP_192M_D4, "univ_192m_d4", "univ_192m_ck", 1, + 4), + FACTOR(CLK_TOP_UNIVP_192M_D8, "univ_192m_d8", "univ_192m_ck", 1, + 8), + FACTOR(CLK_TOP_UNIVP_192M_D16, "univ_192m_d16", "univ_192m_ck", 1, + 16), + FACTOR(CLK_TOP_UNIVP_192M_D32, "univ_192m_d32", "univ_192m_ck", 1, + 32), + FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, + 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, + 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, + 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, + 8), + FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, + 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, + 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, + 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, + 8), + FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, + 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, + 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, + 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, + 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, + 16), + FACTOR(CLK_TOP_MMPLL_CK, "mmpll_ck", "mmpll", 1, + 1), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, + 4), + FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, + 2), + FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1, + 4), + FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, + 5), + FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, + 2), + FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1, + 4), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, + 6), + FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, + 7), + FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, + 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, + 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, + 4), + FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, + 8), + FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, + 16), + FACTOR(CLK_TOP_AD_OSC_CK, "ad_osc_ck", "osc", 1, + 1), + FACTOR(CLK_TOP_OSC_D2, "osc_d2", "osc", 1, + 2), + FACTOR(CLK_TOP_OSC_D4, "osc_d4", "osc", 1, + 4), + FACTOR(CLK_TOP_OSC_D8, "osc_d8", "osc", 1, + 8), + FACTOR(CLK_TOP_OSC_D16, "osc_d16", "osc", 1, + 16), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, + 2), + FACTOR(CLK_TOP_UNIVPLL_D3_D16, "univpll_d3_d16", "univpll_d3", 1, + 16), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll_d2_d4", + "syspll_d7", + "osc_d4" +}; + +static const char * const mm_parents[] = { + "clk26m", + "mmpll_d7", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "syspll_d3_d2" +}; + +static const char * const img_parents[] = { + "clk26m", + "mmpll_d6", + "univpll_d3", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "univpll_d3_d2", + "syspll_d3_d2" +}; + +static const char * const cam_parents[] = { + "clk26m", + "syspll_d2", + "mmpll_d6", + "syspll_d3", + "mmpll_d7", + "univpll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "syspll_d3_d2", + "univpll_d3_d2" +}; + +static const char * const dsp_parents[] = { + "clk26m", + "mmpll_d6", + "mmpll_d7", + "univpll_d3", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "univpll_d3_d2", + "syspll_d3_d2" +}; + +static const char * const dsp1_parents[] = { + "clk26m", + "mmpll_d6", + "mmpll_d7", + "univpll_d3", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "univpll_d3_d2", + "syspll_d3_d2" +}; + +static const char * const dsp2_parents[] = { + "clk26m", + "mmpll_d6", + "mmpll_d7", + "univpll_d3", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "univpll_d3_d2", + "syspll_d3_d2" +}; + +static const char * const ipu_if_parents[] = { + "clk26m", + "mmpll_d6", + "mmpll_d7", + "univpll_d3", + "syspll_d3", + "univpll_d2_d2", + "syspll_d2_d2", + "univpll_d3_d2", + "syspll_d3_d2" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll_ck", + "univpll_d3", + "syspll_d3" +}; + +static const char * const f52m_mfg_parents[] = { + "clk26m", + "univpll_d3_d2", + "univpll_d3_d4", + "univpll_d3_d8" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univ_192m_d8", + "univpll_d3_d8", + "univ_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univ_192m_d16", + "univ_192m_d32" +}; + +static const char * const camtg2_parents[] = { + "clk26m", + "univ_192m_d8", + "univpll_d3_d8", + "univ_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univ_192m_d16", + "univ_192m_d32" +}; + +static const char * const camtg3_parents[] = { + "clk26m", + "univ_192m_d8", + "univpll_d3_d8", + "univ_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univ_192m_d16", + "univ_192m_d32" +}; + +static const char * const camtg4_parents[] = { + "clk26m", + "univ_192m_d8", + "univpll_d3_d8", + "univ_192m_d4", + "univpll_d3_d16", + "csw_f26m_ck_d2", + "univ_192m_d16", + "univ_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d3_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "syspll_d5_d2", + "syspll_d3_d4", + "msdcpll_d4" +}; + +static const char * const msdc50_hclk_parents[] = { + "clk26m", + "syspll_d2_d2", + "syspll_d3_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll_d2_d4", + "syspll_d3_d2", + "univpll_d2_d2" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "univpll_d3_d2", + "syspll_d3_d2", + "syspll_d7", + "msdcpll_d2" +}; + +static const char * const msdc30_2_parents[] = { + "clk26m", + "univpll_d3_d2", + "syspll_d3_d2", + "syspll_d7", + "msdcpll_d2" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll_d5_d4", + "syspll_d7_d4", + "syspll_d2_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll_d2_d4", + "syspll_d7_d2" +}; + +static const char * const pmicspi_parents[] = { + "clk26m", + "syspll_d2_d8", + "osc_d8" +}; + +static const char * const fpwrap_ulposc_parents[] = { + "clk26m", + "osc_d16", + "osc_d4", + "osc_d8" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll_d2_d2", + "syspll_d5" +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16", + "univpll_d5_d2", + "univpll_d3_d4", + "syspll_d3_d4", + "univpll_d3_d8" +}; + +static const char * const scam_parents[] = { + "clk26m", + "syspll_d5_d2" +}; + +static const char * const disppwm_parents[] = { + "clk26m", + "univpll_d3_d4", + "osc_d2", + "osc_d4", + "osc_d16" +}; + +static const char * const usb_top_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + + +static const char * const ssusb_top_xhci_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + +static const char * const spm_parents[] = { + "clk26m", + "syspll_d2_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "syspll_d2_d8", + "univpll_d5_d2" +}; + +static const char * const scp_parents[] = { + "clk26m", + "univpll_d2_d8", + "syspll_d5", + "syspll_d2_d2", + "univpll_d2_d2", + "syspll_d3", + "univpll_d3" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d2_d2", + "univpll_d3_d2", + "univpll_d2_d4" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "syspll_d2_d2", + "syspll_d2_d4", + "syspll_d2_d8" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const faes_ufsfde_parents[] = { + "clk26m", + "syspll_d2", + "syspll_d2_d2", + "syspll_d3", + "syspll_d2_d4", + "univpll_d3" +}; + +static const char * const fufs_parents[] = { + "clk26m", + "syspll_d2_d4", + "syspll_d2_d8", + "syspll_d2_d16" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck" +}; + +/* + * CRITICAL CLOCK: + * axi_sel is the main bus clock of whole SOC. + * spm_sel is the clock of the always-on co-processor. + */ +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_AXI, "axi_sel", + axi_parents, 0x40, + 0x44, 0x48, 0, 2, 7, 0x004, 0, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MM, "mm_sel", + mm_parents, 0x40, + 0x44, 0x48, 8, 3, 15, 0x004, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IMG, "img_sel", + img_parents, 0x40, + 0x44, 0x48, 16, 3, 23, 0x004, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAM, "cam_sel", + cam_parents, 0x40, + 0x44, 0x48, 24, 4, 31, 0x004, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP, "dsp_sel", + dsp_parents, 0x50, + 0x54, 0x58, 0, 4, 7, 0x004, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP1, "dsp1_sel", + dsp1_parents, 0x50, + 0x54, 0x58, 8, 4, 15, 0x004, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DSP2, "dsp2_sel", + dsp2_parents, 0x50, + 0x54, 0x58, 16, 4, 23, 0x004, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_IPU_IF, "ipu_if_sel", + ipu_if_parents, 0x50, + 0x54, 0x58, 24, 4, 31, 0x004, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MFG, "mfg_sel", + mfg_parents, 0x60, + 0x64, 0x68, 0, 2, 7, 0x004, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_F52M_MFG, "f52m_mfg_sel", + f52m_mfg_parents, 0x60, + 0x64, 0x68, 8, 2, 15, 0x004, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG, "camtg_sel", + camtg_parents, 0x60, + 0x64, 0x68, 16, 3, 23, 0x004, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG2, "camtg2_sel", + camtg2_parents, 0x60, + 0x64, 0x68, 24, 3, 31, 0x004, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG3, "camtg3_sel", + camtg3_parents, 0x70, + 0x74, 0x78, 0, 3, 7, 0x004, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_CAMTG4, "camtg4_sel", + camtg4_parents, 0x70, + 0x74, 0x78, 8, 3, 15, 0x004, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_UART, "uart_sel", + uart_parents, 0x70, + 0x74, 0x78, 16, 1, 23, 0x004, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SPI, "spi_sel", + spi_parents, 0x70, + 0x74, 0x78, 24, 2, 31, 0x004, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_hclk_sel", + msdc50_hclk_parents, 0x80, + 0x84, 0x88, 0, 2, 7, 0x004, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", + msdc50_0_parents, 0x80, + 0x84, 0x88, 8, 3, 15, 0x004, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", + msdc30_1_parents, 0x80, + 0x84, 0x88, 16, 3, 23, 0x004, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", + msdc30_2_parents, 0x80, + 0x84, 0x88, 24, 3, 31, 0x004, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUDIO, "audio_sel", + audio_parents, 0x90, + 0x94, 0x98, 0, 2, 7, 0x004, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", + aud_intbus_parents, 0x90, + 0x94, 0x98, 8, 2, 15, 0x004, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", + pmicspi_parents, 0x90, + 0x94, 0x98, 16, 2, 23, 0x004, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FPWRAP_ULPOSC, "fpwrap_ulposc_sel", + fpwrap_ulposc_parents, 0x90, + 0x94, 0x98, 24, 2, 31, 0x004, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_ATB, "atb_sel", + atb_parents, 0xa0, + 0xa4, 0xa8, 0, 2, 7, 0x004, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DPI0, "dpi0_sel", + dpi0_parents, 0xa0, + 0xa4, 0xa8, 16, 4, 23, 0x004, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCAM, "scam_sel", + scam_parents, 0xa0, + 0xa4, 0xa8, 24, 1, 31, 0x004, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DISP_PWM, "disppwm_sel", + disppwm_parents, 0xb0, + 0xb4, 0xb8, 0, 3, 7, 0x004, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_USB_TOP, "usb_top_sel", + usb_top_parents, 0xb0, + 0xb4, 0xb8, 8, 2, 15, 0x004, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SSUSB_TOP_XHCI, "ssusb_top_xhci_sel", + ssusb_top_xhci_parents, 0xb0, + 0xb4, 0xb8, 16, 2, 23, 0x004, 30), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MUX_SPM, "spm_sel", + spm_parents, 0xb0, + 0xb4, 0xb8, 24, 1, 31, 0x008, 0, CLK_IS_CRITICAL), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_I2C, "i2c_sel", + i2c_parents, 0xc0, + 0xc4, 0xc8, 0, 2, 7, 0x008, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SCP, "scp_sel", + scp_parents, 0xc0, + 0xc4, 0xc8, 8, 3, 15, 0x008, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_SENINF, "seninf_sel", + seninf_parents, 0xc0, + 0xc4, 0xc8, 16, 2, 23, 0x008, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_DXCC, "dxcc_sel", + dxcc_parents, 0xc0, + 0xc4, 0xc8, 24, 2, 31, 0x008, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_ENG1, "aud_eng1_sel", + aud_engen1_parents, 0xd0, + 0xd4, 0xd8, 0, 2, 7, 0x008, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_ENG2, "aud_eng2_sel", + aud_engen2_parents, 0xd0, + 0xd4, 0xd8, 8, 2, 15, 0x008, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FAES_UFSFDE, "faes_ufsfde_sel", + faes_ufsfde_parents, 0xd0, + 0xd4, 0xd8, 16, 3, 23, 0x008, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_FUFS, "fufs_sel", + fufs_parents, 0xd0, + 0xd4, 0xd8, 24, 2, 31, 0x008, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_1, "aud_1_sel", + aud_1_parents, 0xe0, + 0xe4, 0xe8, 0, 1, 7, 0x008, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MUX_AUD_2, "aud_2_sel", + aud_2_parents, 0xe0, + 0xe4, 0xe8, 8, 1, 15, 0x008, 10), +}; + +static const char * const apll_i2s0_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const apll_i2s1_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const apll_i2s2_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const apll_i2s3_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const apll_i2s4_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static const char * const apll_i2s5_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static struct mtk_composite top_aud_muxes[] = { + MUX(CLK_TOP_MUX_APLL_I2S0, "apll_i2s0_sel", apll_i2s0_parents, + 0x320, 8, 1), + MUX(CLK_TOP_MUX_APLL_I2S1, "apll_i2s1_sel", apll_i2s1_parents, + 0x320, 9, 1), + MUX(CLK_TOP_MUX_APLL_I2S2, "apll_i2s2_sel", apll_i2s2_parents, + 0x320, 10, 1), + MUX(CLK_TOP_MUX_APLL_I2S3, "apll_i2s3_sel", apll_i2s3_parents, + 0x320, 11, 1), + MUX(CLK_TOP_MUX_APLL_I2S4, "apll_i2s4_sel", apll_i2s4_parents, + 0x320, 12, 1), + MUX(CLK_TOP_MUX_APLL_I2S5, "apll_i2s5_sel", apll_i2s5_parents, + 0x328, 20, 1), +}; + +static const char * const mcu_mp0_parents[] = { + "clk26m", + "armpll_ll", + "armpll_div_pll1", + "armpll_div_pll2" +}; + +static const char * const mcu_mp2_parents[] = { + "clk26m", + "armpll_l", + "armpll_div_pll1", + "armpll_div_pll2" +}; + +static const char * const mcu_bus_parents[] = { + "clk26m", + "ccipll", + "armpll_div_pll1", + "armpll_div_pll2" +}; + +static struct mtk_composite mcu_muxes[] = { + /* mp0_pll_divider_cfg */ + MUX(CLK_MCU_MP0_SEL, "mcu_mp0_sel", mcu_mp0_parents, 0x7A0, 9, 2), + /* mp2_pll_divider_cfg */ + MUX(CLK_MCU_MP2_SEL, "mcu_mp2_sel", mcu_mp2_parents, 0x7A8, 9, 2), + /* bus_pll_divider_cfg */ + MUX(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, 9, 2), +}; + +static struct mtk_composite top_aud_divs[] = { + DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll_i2s0_sel", + 0x320, 2, 0x324, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll_i2s1_sel", + 0x320, 3, 0x324, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll_i2s2_sel", + 0x320, 4, 0x324, 8, 16), + DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll_i2s3_sel", + 0x320, 5, 0x324, 8, 24), + DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll_i2s4_sel", + 0x320, 6, 0x328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIVB, "apll12_divb", "apll12_div4", + 0x320, 7, 0x328, 8, 8), +}; + +static const struct mtk_gate_regs top_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x104, + .sta_ofs = 0x104, +}; + +#define GATE_TOP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate top_clks[] = { + /* TOP */ + GATE_TOP(CLK_TOP_ARMPLL_DIV_PLL1, "armpll_div_pll1", "mainpll", 4), + GATE_TOP(CLK_TOP_ARMPLL_DIV_PLL2, "armpll_div_pll2", "univpll", 5), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", + "axi_sel", 0), + GATE_INFRA0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", + "axi_sel", 1), + GATE_INFRA0(CLK_INFRA_PMIC_MD, "infra_pmic_md", + "axi_sel", 2), + GATE_INFRA0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", + "axi_sel", 3), + GATE_INFRA0(CLK_INFRA_SCPSYS, "infra_scp", + "scp_sel", 4), + GATE_INFRA0(CLK_INFRA_SEJ, "infra_sej", + "f_f26m_ck", 5), + GATE_INFRA0(CLK_INFRA_APXGPT, "infra_apxgpt", + "axi_sel", 6), + GATE_INFRA0(CLK_INFRA_ICUSB, "infra_icusb", + "axi_sel", 8), + GATE_INFRA0(CLK_INFRA_GCE, "infra_gce", + "axi_sel", 9), + GATE_INFRA0(CLK_INFRA_THERM, "infra_therm", + "axi_sel", 10), + GATE_INFRA0(CLK_INFRA_I2C0, "infra_i2c0", + "i2c_sel", 11), + GATE_INFRA0(CLK_INFRA_I2C1, "infra_i2c1", + "i2c_sel", 12), + GATE_INFRA0(CLK_INFRA_I2C2, "infra_i2c2", + "i2c_sel", 13), + GATE_INFRA0(CLK_INFRA_I2C3, "infra_i2c3", + "i2c_sel", 14), + GATE_INFRA0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", + "axi_sel", 15), + GATE_INFRA0(CLK_INFRA_PWM1, "infra_pwm1", + "i2c_sel", 16), + GATE_INFRA0(CLK_INFRA_PWM2, "infra_pwm2", + "i2c_sel", 17), + GATE_INFRA0(CLK_INFRA_PWM3, "infra_pwm3", + "i2c_sel", 18), + GATE_INFRA0(CLK_INFRA_PWM4, "infra_pwm4", + "i2c_sel", 19), + GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm", + "i2c_sel", 21), + GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0", + "uart_sel", 22), + GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1", + "uart_sel", 23), + GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2", + "uart_sel", 24), + GATE_INFRA0(CLK_INFRA_UART3, "infra_uart3", + "uart_sel", 25), + GATE_INFRA0(CLK_INFRA_GCE_26M, "infra_gce_26m", + "axi_sel", 27), + GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, "infra_cqdma_fpc", + "axi_sel", 28), + GATE_INFRA0(CLK_INFRA_BTIF, "infra_btif", + "axi_sel", 31), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_SPI0, "infra_spi0", + "spi_sel", 1), + GATE_INFRA1(CLK_INFRA_MSDC0, "infra_msdc0", + "msdc50_hclk_sel", 2), + GATE_INFRA1(CLK_INFRA_MSDC1, "infra_msdc1", + "axi_sel", 4), + GATE_INFRA1(CLK_INFRA_MSDC2, "infra_msdc2", + "axi_sel", 5), + GATE_INFRA1(CLK_INFRA_MSDC0_SCK, "infra_msdc0_sck", + "msdc50_0_sel", 6), + GATE_INFRA1(CLK_INFRA_DVFSRC, "infra_dvfsrc", + "f_f26m_ck", 7), + GATE_INFRA1(CLK_INFRA_GCPU, "infra_gcpu", + "axi_sel", 8), + GATE_INFRA1(CLK_INFRA_TRNG, "infra_trng", + "axi_sel", 9), + GATE_INFRA1(CLK_INFRA_AUXADC, "infra_auxadc", + "f_f26m_ck", 10), + GATE_INFRA1(CLK_INFRA_CPUM, "infra_cpum", + "axi_sel", 11), + GATE_INFRA1(CLK_INFRA_CCIF1_AP, "infra_ccif1_ap", + "axi_sel", 12), + GATE_INFRA1(CLK_INFRA_CCIF1_MD, "infra_ccif1_md", + "axi_sel", 13), + GATE_INFRA1(CLK_INFRA_AUXADC_MD, "infra_auxadc_md", + "f_f26m_ck", 14), + GATE_INFRA1(CLK_INFRA_MSDC1_SCK, "infra_msdc1_sck", + "msdc30_1_sel", 16), + GATE_INFRA1(CLK_INFRA_MSDC2_SCK, "infra_msdc2_sck", + "msdc30_2_sel", 17), + GATE_INFRA1(CLK_INFRA_AP_DMA, "infra_apdma", + "axi_sel", 18), + GATE_INFRA1(CLK_INFRA_XIU, "infra_xiu", + "axi_sel", 19), + GATE_INFRA1(CLK_INFRA_DEVICE_APC, "infra_device_apc", + "axi_sel", 20), + GATE_INFRA1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", + "axi_sel", 23), + GATE_INFRA1(CLK_INFRA_DEBUGSYS, "infra_debugsys", + "axi_sel", 24), + GATE_INFRA1(CLK_INFRA_AUDIO, "infra_audio", + "axi_sel", 25), + GATE_INFRA1(CLK_INFRA_CCIF_MD, "infra_ccif_md", + "axi_sel", 26), + GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, "infra_dxcc_sec_core", + "dxcc_sel", 27), + GATE_INFRA1(CLK_INFRA_DXCC_AO, "infra_dxcc_ao", + "dxcc_sel", 28), + GATE_INFRA1(CLK_INFRA_DEVMPU_BCLK, "infra_devmpu_bclk", + "axi_sel", 30), + GATE_INFRA1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", + "f_f26m_ck", 31), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_IRTX, "infra_irtx", + "f_f26m_ck", 0), + GATE_INFRA2(CLK_INFRA_USB, "infra_usb", + "usb_top_sel", 1), + GATE_INFRA2(CLK_INFRA_DISP_PWM, "infra_disppwm", + "axi_sel", 2), + GATE_INFRA2(CLK_INFRA_CLDMA_BCLK, "infra_cldma_bclk", + "axi_sel", 3), + GATE_INFRA2(CLK_INFRA_AUDIO_26M_BCLK, "infra_audio_26m_bclk", + "f_f26m_ck", 4), + GATE_INFRA2(CLK_INFRA_SPI1, "infra_spi1", + "spi_sel", 6), + GATE_INFRA2(CLK_INFRA_I2C4, "infra_i2c4", + "i2c_sel", 7), + GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_md_tmp_share", + "f_f26m_ck", 8), + GATE_INFRA2(CLK_INFRA_SPI2, "infra_spi2", + "spi_sel", 9), + GATE_INFRA2(CLK_INFRA_SPI3, "infra_spi3", + "spi_sel", 10), + GATE_INFRA2(CLK_INFRA_UNIPRO_SCK, "infra_unipro_sck", + "ssusb_top_xhci_sel", 11), + GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", + "fufs_sel", 12), + GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_BCLK, "infra_ufs_mp_sap_bck", + "fufs_sel", 13), + GATE_INFRA2(CLK_INFRA_MD32_BCLK, "infra_md32_bclk", + "axi_sel", 14), + GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", + "axi_sel", 16), + GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", + "i2c_sel", 18), + GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", + "i2c_sel", 19), + GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", + "i2c_sel", 20), + GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, "infra_i2c1_arbiter", + "i2c_sel", 21), + GATE_INFRA2(CLK_INFRA_I2C1_IMM, "infra_i2c1_imm", + "i2c_sel", 22), + GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, "infra_i2c2_arbiter", + "i2c_sel", 23), + GATE_INFRA2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", + "i2c_sel", 24), + GATE_INFRA2(CLK_INFRA_SPI4, "infra_spi4", + "spi_sel", 25), + GATE_INFRA2(CLK_INFRA_SPI5, "infra_spi5", + "spi_sel", 26), + GATE_INFRA2(CLK_INFRA_CQ_DMA, "infra_cqdma", + "axi_sel", 27), + GATE_INFRA2(CLK_INFRA_UFS, "infra_ufs", + "fufs_sel", 28), + GATE_INFRA2(CLK_INFRA_AES_UFSFDE, "infra_aes_ufsfde", + "faes_ufsfde_sel", 29), + GATE_INFRA2(CLK_INFRA_UFS_TICK, "infra_ufs_tick", + "fufs_sel", 30), + /* INFRA3 */ + GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", + "msdc50_0_sel", 0), + GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", + "msdc50_0_sel", 1), + GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", + "msdc50_0_sel", 2), + GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", + "axi_sel", 5), + GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", + "i2c_sel", 6), + GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", + "msdc50_hclk_sel", 7), + GATE_INFRA3(CLK_INFRA_MD_MSDC0, "infra_md_msdc0", + "msdc50_hclk_sel", 8), + GATE_INFRA3(CLK_INFRA_CCIF2_AP, "infra_ccif2_ap", + "axi_sel", 16), + GATE_INFRA3(CLK_INFRA_CCIF2_MD, "infra_ccif2_md", + "axi_sel", 17), + GATE_INFRA3(CLK_INFRA_CCIF3_AP, "infra_ccif3_ap", + "axi_sel", 18), + GATE_INFRA3(CLK_INFRA_CCIF3_MD, "infra_ccif3_md", + "axi_sel", 19), + GATE_INFRA3(CLK_INFRA_SEJ_F13M, "infra_sej_f13m", + "f_f26m_ck", 20), + GATE_INFRA3(CLK_INFRA_AES_BCLK, "infra_aes_bclk", + "axi_sel", 21), + GATE_INFRA3(CLK_INFRA_I2C7, "infra_i2c7", + "i2c_sel", 22), + GATE_INFRA3(CLK_INFRA_I2C8, "infra_i2c8", + "i2c_sel", 23), + GATE_INFRA3(CLK_INFRA_FBIST2FPC, "infra_fbist2fpc", + "msdc50_0_sel", 24), +}; + +static const struct mtk_gate_regs peri_cg_regs = { + .set_ofs = 0x20c, + .clr_ofs = 0x20c, + .sta_ofs = 0x20c, +}; + +#define GATE_PERI(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate peri_clks[] = { + GATE_PERI(CLK_PERI_AXI, "peri_axi", "axi_sel", 31), +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x20, + .clr_ofs = 0x20, + .sta_ofs = 0x20, +}; + +#define GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &apmixed_cg_regs, \ + _shift, &mtk_clk_gate_ops_no_setclr_inv, _flags) + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_APMIXED_FLAGS(_id, _name, _parent, _shift, 0) + +/* + * CRITICAL CLOCK: + * apmixed_appll26m is the toppest clock gate of all PLLs. + */ +static const struct mtk_gate apmixed_clks[] = { + /* AUDIO0 */ + GATE_APMIXED(CLK_APMIXED_SSUSB_26M, "apmixed_ssusb26m", + "f_f26m_ck", 4), + GATE_APMIXED_FLAGS(CLK_APMIXED_APPLL_26M, "apmixed_appll26m", + "f_f26m_ck", 5, CLK_IS_CRITICAL), + GATE_APMIXED(CLK_APMIXED_MIPIC0_26M, "apmixed_mipic026m", + "f_f26m_ck", 6), + GATE_APMIXED(CLK_APMIXED_MDPLLGP_26M, "apmixed_mdpll26m", + "f_f26m_ck", 7), + GATE_APMIXED(CLK_APMIXED_MMSYS_26M, "apmixed_mmsys26m", + "f_f26m_ck", 8), + GATE_APMIXED(CLK_APMIXED_UFS_26M, "apmixed_ufs26m", + "f_f26m_ck", 9), + GATE_APMIXED(CLK_APMIXED_MIPIC1_26M, "apmixed_mipic126m", + "f_f26m_ck", 11), + GATE_APMIXED(CLK_APMIXED_MEMPLL_26M, "apmixed_mempll26m", + "f_f26m_ck", 13), + GATE_APMIXED(CLK_APMIXED_CLKSQ_LVPLL_26M, "apmixed_lvpll26m", + "f_f26m_ck", 14), + GATE_APMIXED(CLK_APMIXED_MIPID0_26M, "apmixed_mipid026m", + "f_f26m_ck", 16), + GATE_APMIXED(CLK_APMIXED_MIPID1_26M, "apmixed_mipid126m", + "f_f26m_ck", 17), +}; + +#define MT8183_PLL_FMAX (3800UL * MHZ) +#define MT8183_PLL_FMIN (1500UL * MHZ) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8183_PLL_FMAX, \ + .fmin = MT8183_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = _pcwibits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pcwibits, _pd_reg, \ + _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, \ + _pcw_chg_reg, NULL) + +static const struct mtk_pll_div_table armpll_div_table[] = { + { .div = 0, .freq = MT8183_PLL_FMAX }, + { .div = 1, .freq = 1500 * MHZ }, + { .div = 2, .freq = 750 * MHZ }, + { .div = 3, .freq = 375 * MHZ }, + { .div = 4, .freq = 187500000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table mfgpll_div_table[] = { + { .div = 0, .freq = MT8183_PLL_FMAX }, + { .div = 1, .freq = 1600 * MHZ }, + { .div = 2, .freq = 800 * MHZ }, + { .div = 3, .freq = 400 * MHZ }, + { .div = 4, .freq = 200 * MHZ }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL_B(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0200, 0x020C, 0, + HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0204, 24, 0x0, 0x0, 0, + 0x0204, 0, 0, armpll_div_table), + PLL_B(CLK_APMIXED_ARMPLL_L, "armpll_l", 0x0210, 0x021C, 0, + HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0214, 24, 0x0, 0x0, 0, + 0x0214, 0, 0, armpll_div_table), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0290, 0x029C, 0, + HAVE_RST_BAR | PLL_AO, BIT(24), 22, 8, 0x0294, 24, 0x0, 0x0, 0, + 0x0294, 0, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0, + HAVE_RST_BAR, BIT(24), 22, 8, 0x0224, 24, 0x0, 0x0, 0, + 0x0224, 0, 0), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0230, 0x023C, 0, + HAVE_RST_BAR, BIT(24), 22, 8, 0x0234, 24, 0x0, 0x0, 0, + 0x0234, 0, 0), + PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0, + 0, 0, 22, 8, 0x0244, 24, 0x0, 0x0, 0, 0x0244, 0, 0, + mfgpll_div_table), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0, + 0, 0, 22, 8, 0x0254, 24, 0x0, 0x0, 0, 0x0254, 0, 0), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0260, 0x026C, 0, + 0, 0, 22, 8, 0x0264, 24, 0x0, 0x0, 0, 0x0264, 0, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0270, 0x027C, 0, + HAVE_RST_BAR, BIT(23), 22, 8, 0x0274, 24, 0x0, 0x0, 0, + 0x0274, 0, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0, + 0, 0, 32, 8, 0x02A0, 1, 0x02A8, 0x0014, 0, 0x02A4, 0, 0x02A0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x02b4, 0x02c4, 0, + 0, 0, 32, 8, 0x02B4, 1, 0x02BC, 0x0014, 1, 0x02B8, 0, 0x02B4), +}; + +static u16 infra_rst_ofs[] = { + INFRA_RST0_SET_OFFSET, + INFRA_RST1_SET_OFFSET, + INFRA_RST2_SET_OFFSET, + INFRA_RST3_SET_OFFSET, +}; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_rst_ofs), +}; + +static int clk_mt8183_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static struct clk_hw_onecell_data *top_clk_data; + +static void clk_mt8183_top_init_early(struct device_node *node) +{ + int i; + + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + for (i = 0; i < CLK_TOP_NR_CLK; i++) + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + + of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); +} + +CLK_OF_DECLARE_DRIVER(mt8183_topckgen, "mediatek,mt8183-topckgen", + clk_mt8183_top_init_early); + +/* Register mux notifier for MFG mux */ +static int clk_mt8183_reg_mfg_mux_notifier(struct device *dev, struct clk *clk) +{ + struct mtk_mux_nb *mfg_mux_nb; + int i; + + mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL); + if (!mfg_mux_nb) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(top_muxes); i++) + if (top_muxes[i].id == CLK_TOP_MUX_MFG) + break; + if (i == ARRAY_SIZE(top_muxes)) + return -EINVAL; + + mfg_mux_nb->ops = top_muxes[i].ops; + mfg_mux_nb->bypass_index = 0; /* Bypass to 26M crystal */ + + return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb); +} + +static int clk_mt8183_top_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct device_node *node = pdev->dev.of_node; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), + top_clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + + mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), + node, &mt8183_clk_lock, top_clk_data); + + mtk_clk_register_composites(top_aud_muxes, ARRAY_SIZE(top_aud_muxes), + base, &mt8183_clk_lock, top_clk_data); + + mtk_clk_register_composites(top_aud_divs, ARRAY_SIZE(top_aud_divs), + base, &mt8183_clk_lock, top_clk_data); + + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), + top_clk_data); + + ret = clk_mt8183_reg_mfg_mux_notifier(&pdev->dev, + top_clk_data->hws[CLK_TOP_MUX_MFG]->clk); + if (ret) + return ret; + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + top_clk_data); +} + +static int clk_mt8183_infra_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + + mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), + clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) { + dev_err(&pdev->dev, + "%s(): could not register clock provider: %d\n", + __func__, r); + return r; + } + + mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + + return r; +} + +static int clk_mt8183_peri_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + + mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), + clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static int clk_mt8183_mcu_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + + mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + &mt8183_clk_lock, clk_data); + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static const struct of_device_id of_match_clk_mt8183[] = { + { + .compatible = "mediatek,mt8183-apmixedsys", + .data = clk_mt8183_apmixed_probe, + }, { + .compatible = "mediatek,mt8183-topckgen", + .data = clk_mt8183_top_probe, + }, { + .compatible = "mediatek,mt8183-infracfg", + .data = clk_mt8183_infra_probe, + }, { + .compatible = "mediatek,mt8183-pericfg", + .data = clk_mt8183_peri_probe, + }, { + .compatible = "mediatek,mt8183-mcucfg", + .data = clk_mt8183_mcu_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt8183_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *pdev); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r) + dev_err(&pdev->dev, + "could not register clock provider: %s: %d\n", + pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt8183_drv = { + .probe = clk_mt8183_probe, + .driver = { + .name = "clk-mt8183", + .of_match_table = of_match_clk_mt8183, + }, +}; + +static int __init clk_mt8183_init(void) +{ + return platform_driver_register(&clk_mt8183_drv); +} + +arch_initcall(clk_mt8183_init); diff --git a/drivers/clk/mediatek/clk-mt8186-apmixedsys.c b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c new file mode 100644 index 000000000..e692a2a67 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-apmixedsys.c @@ -0,0 +1,133 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-mtk.h" +#include "clk-pll.h" + +#define MT8186_PLL_FMAX (3800UL * MHZ) +#define MT8186_PLL_FMIN (1500UL * MHZ) +#define MT8186_INTEGER_BITS (8) + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8186_PLL_FMAX, \ + .fmin = MT8186_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = MT8186_INTEGER_BITS, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = 0, \ + .pcw_chg_reg = 0, \ + .en_reg = 0, \ + .pll_en_bit = 0, \ + } + +static const struct mtk_pll_data plls[] = { + /* + * armpll_ll/armpll_bl/ccipll are main clock source of AP MCU, + * should not be closed in Linux world. + */ + PLL(CLK_APMIXED_ARMPLL_LL, "armpll_ll", 0x0204, 0x0210, 0, + PLL_AO, 0, 22, 0x0208, 24, 0, 0, 0, 0x0208), + PLL(CLK_APMIXED_ARMPLL_BL, "armpll_bl", 0x0214, 0x0220, 0, + PLL_AO, 0, 22, 0x0218, 24, 0, 0, 0, 0x0218), + PLL(CLK_APMIXED_CCIPLL, "ccipll", 0x0224, 0x0230, 0, + PLL_AO, 0, 22, 0x0228, 24, 0, 0, 0, 0x0228), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0244, 0x0250, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0248, 24, 0, 0, 0, 0x0248), + PLL(CLK_APMIXED_UNIV2PLL, "univ2pll", 0x0324, 0x0330, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0328, 24, 0, 0, 0, 0x0328), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x038C, 0x0398, 0, + 0, 0, 22, 0x0390, 24, 0, 0, 0, 0x0390), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0254, 0x0260, 0, + 0, 0, 22, 0x0258, 24, 0, 0, 0, 0x0258), + PLL(CLK_APMIXED_NNAPLL, "nnapll", 0x035C, 0x0368, 0, + 0, 0, 22, 0x0360, 24, 0, 0, 0, 0x0360), + PLL(CLK_APMIXED_NNA2PLL, "nna2pll", 0x036C, 0x0378, 0, + 0, 0, 22, 0x0370, 24, 0, 0, 0, 0x0370), + PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x0304, 0x0310, 0, + 0, 0, 22, 0x0308, 24, 0, 0, 0, 0x0308), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0314, 0x0320, 0, + 0, 0, 22, 0x0318, 24, 0, 0, 0, 0x0318), + PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0264, 0x0270, 0, + 0, 0, 22, 0x0268, 24, 0, 0, 0, 0x0268), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0334, 0x0344, 0, + 0, 0, 32, 0x0338, 24, 0x0040, 0x000C, 0, 0x033C), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0348, 0x0358, 0, + 0, 0, 32, 0x034C, 24, 0x0044, 0x000C, 5, 0x0350), +}; + +static const struct of_device_id of_match_clk_mt8186_apmixed[] = { + { .compatible = "mediatek,mt8186-apmixedsys", }, + {} +}; + +static int clk_mt8186_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (r) + goto free_apmixed_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_plls; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_apmixed_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_apmixed_drv = { + .probe = clk_mt8186_apmixed_probe, + .remove = clk_mt8186_apmixed_remove, + .driver = { + .name = "clk-mt8186-apmixed", + .of_match_table = of_match_clk_mt8186_apmixed, + }, +}; +builtin_platform_driver(clk_mt8186_apmixed_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-cam.c b/drivers/clk/mediatek/clk-mt8186-cam.c new file mode 100644 index 000000000..9ec345a2c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-cam.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB13, "cam_larb13", "top_cam", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "top_cam", 1), + GATE_CAM(CLK_CAM_LARB14, "cam_larb14", "top_cam", 2), + GATE_CAM(CLK_CAM, "cam", "top_cam", 6), + GATE_CAM(CLK_CAMTG, "camtg", "top_cam", 7), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "top_cam", 8), + GATE_CAM(CLK_CAMSV1, "camsv1", "top_cam", 10), + GATE_CAM(CLK_CAMSV2, "camsv2", "top_cam", 11), + GATE_CAM(CLK_CAMSV3, "camsv3", "top_cam", 12), + GATE_CAM(CLK_CAM_CCU0, "cam_ccu0", "top_cam", 13), + GATE_CAM(CLK_CAM_CCU1, "cam_ccu1", "top_cam", 14), + GATE_CAM(CLK_CAM_MRAW0, "cam_mraw0", "top_cam", 15), + GATE_CAM(CLK_CAM_FAKE_ENG, "cam_fake_eng", "top_cam", 17), + GATE_CAM(CLK_CAM_CCU_GALS, "cam_ccu_gals", "top_cam", 18), + GATE_CAM(CLK_CAM2MM_GALS, "cam2mm_gals", "top_cam", 19), +}; + +static const struct mtk_gate cam_rawa_clks[] = { + GATE_CAM(CLK_CAM_RAWA_LARBX_RAWA, "cam_rawa_larbx_rawa", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWA, "cam_rawa", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWA_CAMTG_RAWA, "cam_rawa_camtg_rawa", "top_cam", 2), +}; + +static const struct mtk_gate cam_rawb_clks[] = { + GATE_CAM(CLK_CAM_RAWB_LARBX_RAWB, "cam_rawb_larbx_rawb", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWB, "cam_rawb", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWB_CAMTG_RAWB, "cam_rawb_camtg_rawb", "top_cam", 2), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct mtk_clk_desc cam_rawa_desc = { + .clks = cam_rawa_clks, + .num_clks = ARRAY_SIZE(cam_rawa_clks), +}; + +static const struct mtk_clk_desc cam_rawb_desc = { + .clks = cam_rawb_clks, + .num_clks = ARRAY_SIZE(cam_rawb_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_cam[] = { + { + .compatible = "mediatek,mt8186-camsys", + .data = &cam_desc, + }, { + .compatible = "mediatek,mt8186-camsys_rawa", + .data = &cam_rawa_desc, + }, { + .compatible = "mediatek,mt8186-camsys_rawb", + .data = &cam_rawb_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-cam", + .of_match_table = of_match_clk_mt8186_cam, + }, +}; +builtin_platform_driver(clk_mt8186_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-img.c b/drivers/clk/mediatek/clk-mt8186-img.c new file mode 100644 index 000000000..08a625475 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-img.c @@ -0,0 +1,68 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img1_clks[] = { + GATE_IMG(CLK_IMG1_LARB9_IMG1, "img1_larb9_img1", "top_img1", 0), + GATE_IMG(CLK_IMG1_LARB10_IMG1, "img1_larb10_img1", "top_img1", 1), + GATE_IMG(CLK_IMG1_DIP, "img1_dip", "top_img1", 2), + GATE_IMG(CLK_IMG1_GALS_IMG1, "img1_gals_img1", "top_img1", 12), +}; + +static const struct mtk_gate img2_clks[] = { + GATE_IMG(CLK_IMG2_LARB9_IMG2, "img2_larb9_img2", "top_img1", 0), + GATE_IMG(CLK_IMG2_LARB10_IMG2, "img2_larb10_img2", "top_img1", 1), + GATE_IMG(CLK_IMG2_MFB, "img2_mfb", "top_img1", 6), + GATE_IMG(CLK_IMG2_WPE, "img2_wpe", "top_img1", 7), + GATE_IMG(CLK_IMG2_MSS, "img2_mss", "top_img1", 8), + GATE_IMG(CLK_IMG2_GALS_IMG2, "img2_gals_img2", "top_img1", 12), +}; + +static const struct mtk_clk_desc img1_desc = { + .clks = img1_clks, + .num_clks = ARRAY_SIZE(img1_clks), +}; + +static const struct mtk_clk_desc img2_desc = { + .clks = img2_clks, + .num_clks = ARRAY_SIZE(img2_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_img[] = { + { + .compatible = "mediatek,mt8186-imgsys1", + .data = &img1_desc, + }, { + .compatible = "mediatek,mt8186-imgsys2", + .data = &img2_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-img", + .of_match_table = of_match_clk_mt8186_img, + }, +}; +builtin_platform_driver(clk_mt8186_img_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c new file mode 100644 index 000000000..47f2e480a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-imp_iic_wrap.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs imp_iic_wrap_cg_regs = { + .set_ofs = 0xe08, + .clr_ofs = 0xe04, + .sta_ofs = 0xe00, +}; + +#define GATE_IMP_IIC_WRAP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &imp_iic_wrap_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate imp_iic_wrap_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C0, + "imp_iic_wrap_ap_clock_i2c0", "infra_ao_i2c_ap", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C1, + "imp_iic_wrap_ap_clock_i2c1", "infra_ao_i2c_ap", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C2, + "imp_iic_wrap_ap_clock_i2c2", "infra_ao_i2c_ap", 2), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C3, + "imp_iic_wrap_ap_clock_i2c3", "infra_ao_i2c_ap", 3), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C4, + "imp_iic_wrap_ap_clock_i2c4", "infra_ao_i2c_ap", 4), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C5, + "imp_iic_wrap_ap_clock_i2c5", "infra_ao_i2c_ap", 5), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C6, + "imp_iic_wrap_ap_clock_i2c6", "infra_ao_i2c_ap", 6), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C7, + "imp_iic_wrap_ap_clock_i2c7", "infra_ao_i2c_ap", 7), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C8, + "imp_iic_wrap_ap_clock_i2c8", "infra_ao_i2c_ap", 8), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_AP_CLOCK_I2C9, + "imp_iic_wrap_ap_clock_i2c9", "infra_ao_i2c_ap", 9), +}; + +static const struct mtk_clk_desc imp_iic_wrap_desc = { + .clks = imp_iic_wrap_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_imp_iic_wrap[] = { + { + .compatible = "mediatek,mt8186-imp_iic_wrap", + .data = &imp_iic_wrap_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_imp_iic_wrap_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-imp_iic_wrap", + .of_match_table = of_match_clk_mt8186_imp_iic_wrap, + }, +}; +builtin_platform_driver(clk_mt8186_imp_iic_wrap_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-infra_ao.c b/drivers/clk/mediatek/clk-mt8186-infra_ao.c new file mode 100644 index 000000000..df2a6bd1a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-infra_ao.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> +#include <dt-bindings/reset/mt8186-resets.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs infra_ao0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra_ao1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra_ao2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra_ao3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +#define GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO0(_id, _name, _parent, _shift) \ + GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO1(_id, _name, _parent, _shift) \ + GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO2(_id, _name, _parent, _shift) \ + GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, 0) + + #define GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO3(_id, _name, _parent, _shift) \ + GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, 0) + +static const struct mtk_gate infra_ao_clks[] = { + /* INFRA_AO0 */ + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_TMR, "infra_ao_pmic_tmr", "top_pwrap_ulposc", 0), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_AP, "infra_ao_pmic_ap", "top_pwrap_ulposc", 1), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_MD, "infra_ao_pmic_md", "top_pwrap_ulposc", 2), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_CONN, "infra_ao_pmic_conn", "top_pwrap_ulposc", 3), + /* infra_ao_scp_core are main clock in always-on co-processor. */ + GATE_INFRA_AO0_FLAGS(CLK_INFRA_AO_SCP_CORE, + "infra_ao_scp_core", "top_scp", 4, CLK_IS_CRITICAL), + /* infra_ao_sej is main clock for secure engine with JTAG support */ + GATE_INFRA_AO0_FLAGS(CLK_INFRA_AO_SEJ, + "infra_ao_sej", "top_axi", 5, CLK_IS_CRITICAL), + GATE_INFRA_AO0(CLK_INFRA_AO_APXGPT, "infra_ao_apxgpt", "top_axi", 6), + GATE_INFRA_AO0(CLK_INFRA_AO_ICUSB, "infra_ao_icusb", "top_axi", 8), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE, "infra_ao_gce", "top_axi", 9), + GATE_INFRA_AO0(CLK_INFRA_AO_THERM, "infra_ao_therm", "top_axi", 10), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_AP, "infra_ao_i2c_ap", "top_i2c", 11), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_CCU, "infra_ao_i2c_ccu", "top_i2c", 12), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_SSPM, "infra_ao_i2c_sspm", "top_i2c", 13), + GATE_INFRA_AO0(CLK_INFRA_AO_I2C_RSV, "infra_ao_i2c_rsv", "top_i2c", 14), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM_HCLK, "infra_ao_pwm_hclk", "top_axi", 15), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM1, "infra_ao_pwm1", "top_pwm", 16), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM2, "infra_ao_pwm2", "top_pwm", 17), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM3, "infra_ao_pwm3", "top_pwm", 18), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM4, "infra_ao_pwm4", "top_pwm", 19), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM5, "infra_ao_pwm5", "top_pwm", 20), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM, "infra_ao_pwm", "top_pwm", 21), + GATE_INFRA_AO0(CLK_INFRA_AO_UART0, "infra_ao_uart0", "top_uart", 22), + GATE_INFRA_AO0(CLK_INFRA_AO_UART1, "infra_ao_uart1", "top_uart", 23), + GATE_INFRA_AO0(CLK_INFRA_AO_UART2, "infra_ao_uart2", "top_uart", 24), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE_26M, "infra_ao_gce_26m", "clk26m", 27), + GATE_INFRA_AO0(CLK_INFRA_AO_CQ_DMA_FPC, "infra_ao_dma", "top_axi", 28), + GATE_INFRA_AO0(CLK_INFRA_AO_BTIF, "infra_ao_btif", "top_axi", 31), + /* INFRA_AO1 */ + GATE_INFRA_AO1(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "top_spi", 1), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC0, "infra_ao_msdc0", "top_msdc5hclk", 2), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDCFDE, "infra_ao_msdcfde", "top_aes_msdcfde", 3), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC1, "infra_ao_msdc1", "top_axi", 4), + /* infra_ao_dvfsrc is for internal DVFS usage, should not be handled by Linux */ + GATE_INFRA_AO1_FLAGS(CLK_INFRA_AO_DVFSRC, + "infra_ao_dvfsrc", "top_dvfsrc", 7, CLK_IS_CRITICAL), + GATE_INFRA_AO1(CLK_INFRA_AO_GCPU, "infra_ao_gcpu", "top_axi", 8), + GATE_INFRA_AO1(CLK_INFRA_AO_TRNG, "infra_ao_trng", "top_axi", 9), + GATE_INFRA_AO1(CLK_INFRA_AO_AUXADC, "infra_ao_auxadc", "clk26m", 10), + GATE_INFRA_AO1(CLK_INFRA_AO_CPUM, "infra_ao_cpum", "top_axi", 11), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF1_AP, "infra_ao_ccif1_ap", "top_axi", 12), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF1_MD, "infra_ao_ccif1_md", "top_axi", 13), + GATE_INFRA_AO1(CLK_INFRA_AO_AUXADC_MD, "infra_ao_auxadc_md", "clk26m", 14), + GATE_INFRA_AO1(CLK_INFRA_AO_AP_DMA, "infra_ao_ap_dma", "top_axi", 18), + GATE_INFRA_AO1(CLK_INFRA_AO_XIU, "infra_ao_xiu", "top_axi", 19), + /* infra_ao_device_apc is for device access permission control module */ + GATE_INFRA_AO1_FLAGS(CLK_INFRA_AO_DEVICE_APC, + "infra_ao_dapc", "top_axi", 20, CLK_IS_CRITICAL), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF_AP, "infra_ao_ccif_ap", "top_axi", 23), + GATE_INFRA_AO1(CLK_INFRA_AO_DEBUGTOP, "infra_ao_debugtop", "top_axi", 24), + GATE_INFRA_AO1(CLK_INFRA_AO_AUDIO, "infra_ao_audio", "top_axi", 25), + GATE_INFRA_AO1(CLK_INFRA_AO_CCIF_MD, "infra_ao_ccif_md", "top_axi", 26), + GATE_INFRA_AO1(CLK_INFRA_AO_DXCC_SEC_CORE, "infra_ao_secore", "top_dxcc", 27), + GATE_INFRA_AO1(CLK_INFRA_AO_DXCC_AO, "infra_ao_dxcc_ao", "top_dxcc", 28), + GATE_INFRA_AO1(CLK_INFRA_AO_IMP_IIC, "infra_ao_imp_iic", "top_axi", 29), + GATE_INFRA_AO1(CLK_INFRA_AO_DRAMC_F26M, "infra_ao_dramc26", "clk26m", 31), + /* INFRA_AO2 */ + GATE_INFRA_AO2(CLK_INFRA_AO_RG_PWM_FBCLK6, "infra_ao_pwm_fbclk6", "clk26m", 0), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_HCLK, "infra_ao_ssusb_hclk", "top_axi", 1), + GATE_INFRA_AO2(CLK_INFRA_AO_DISP_PWM, "infra_ao_disp_pwm", "top_disp_pwm", 2), + GATE_INFRA_AO2(CLK_INFRA_AO_CLDMA_BCLK, "infra_ao_cldmabclk", "top_axi", 3), + GATE_INFRA_AO2(CLK_INFRA_AO_AUDIO_26M_BCLK, "infra_ao_audio26m", "clk26m", 4), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_HCLK, "infra_ao_ssusb_p1_hclk", "top_axi", 5), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "top_spi", 6), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C4, "infra_ao_i2c4", "top_i2c", 7), + GATE_INFRA_AO2(CLK_INFRA_AO_MODEM_TEMP_SHARE, "infra_ao_mdtemp", "clk26m", 8), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI2, "infra_ao_spi2", "top_spi", 9), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI3, "infra_ao_spi3", "top_spi", 10), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_REF, "infra_ao_ssusb_ref", "clk26m", 11), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_XHCI, "infra_ao_ssusb_xhci", "top_ssusb_xhci", 12), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_REF, "infra_ao_ssusb_p1_ref", "clk26m", 13), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_XHCI, + "infra_ao_ssusb_p1_xhci", "top_ssusb_xhci_1p", 14), + /* infra_ao_sspm is main clock in co-processor, should not be closed in Linux. */ + GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_SSPM, "infra_ao_sspm", "top_sspm", 15, CLK_IS_CRITICAL), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_TOP_P1_SYS, + "infra_ao_ssusb_p1_sys", "top_ssusb_1p", 16), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5, "infra_ao_i2c5", "top_i2c", 18), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5_ARBITER, "infra_ao_i2c5a", "top_i2c", 19), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C5_IMM, "infra_ao_i2c5_imm", "top_i2c", 20), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C1_ARBITER, "infra_ao_i2c1a", "top_i2c", 21), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C1_IMM, "infra_ao_i2c1_imm", "top_i2c", 22), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C2_ARBITER, "infra_ao_i2c2a", "top_i2c", 23), + GATE_INFRA_AO2(CLK_INFRA_AO_I2C2_IMM, "infra_ao_i2c2_imm", "top_i2c", 24), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI4, "infra_ao_spi4", "top_spi", 25), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI5, "infra_ao_spi5", "top_spi", 26), + GATE_INFRA_AO2(CLK_INFRA_AO_CQ_DMA, "infra_ao_cq_dma", "top_axi", 27), + GATE_INFRA_AO2(CLK_INFRA_AO_BIST2FPC, "infra_ao_bist2fpc", "f_bist2fpc_ck", 28), + /* INFRA_AO3 */ + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC0_SELF, "infra_ao_msdc0sf", "top_msdc50_0", 0), + GATE_INFRA_AO3(CLK_INFRA_AO_SPINOR, "infra_ao_spinor", "top_spinor", 1), + /* + * infra_ao_sspm_26m/infra_ao_sspm_32k are main clocks in co-processor, + * should not be closed in Linux. + */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SSPM_26M_SELF, "infra_ao_sspm_26m", "clk26m", 3, + CLK_IS_CRITICAL), + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SSPM_32K_SELF, "infra_ao_sspm_32k", "clk32k", 4, + CLK_IS_CRITICAL), + GATE_INFRA_AO3(CLK_INFRA_AO_I2C6, "infra_ao_i2c6", "top_i2c", 6), + GATE_INFRA_AO3(CLK_INFRA_AO_AP_MSDC0, "infra_ao_ap_msdc0", "top_axi", 7), + GATE_INFRA_AO3(CLK_INFRA_AO_MD_MSDC0, "infra_ao_md_msdc0", "top_axi", 8), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC0_SRC, "infra_ao_msdc0_clk", "top_msdc50_0", 9), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC1_SRC, "infra_ao_msdc1_clk", "top_msdc30_1", 10), + /* infra_ao_sej_f13m is main clock for secure engine with JTAG support */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_SEJ_F13M, + "infra_ao_sej_f13m", "clk26m", 15, CLK_IS_CRITICAL), + /* infra_ao_aes_top0_bclk is for secure encryption */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_AES_TOP0_BCLK, + "infra_ao_aes_top0_bclk", "top_axi", 16, CLK_IS_CRITICAL), + GATE_INFRA_AO3(CLK_INFRA_AO_MCU_PM_BCLK, "infra_ao_mcu_pm_bclk", "top_axi", 17), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF2_AP, "infra_ao_ccif2_ap", "top_axi", 18), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF2_MD, "infra_ao_ccif2_md", "top_axi", 19), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF3_AP, "infra_ao_ccif3_ap", "top_axi", 20), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF3_MD, "infra_ao_ccif3_md", "top_axi", 21), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP_26M, "infra_ao_fadsp_26m", "clk26m", 22), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP_32K, "infra_ao_fadsp_32k", "clk32k", 23), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF4_AP, "infra_ao_ccif4_ap", "top_axi", 24), + GATE_INFRA_AO3(CLK_INFRA_AO_CCIF4_MD, "infra_ao_ccif4_md", "top_axi", 25), + GATE_INFRA_AO3(CLK_INFRA_AO_FADSP, "infra_ao_fadsp", "top_audiodsp", 27), + GATE_INFRA_AO3(CLK_INFRA_AO_FLASHIF_133M, "infra_ao_flashif_133m", "top_axi", 28), + GATE_INFRA_AO3(CLK_INFRA_AO_FLASHIF_66M, "infra_ao_flashif_66m", "top_axi", 29), +}; + +static u16 infra_ao_rst_ofs[] = { + INFRA_RST0_SET_OFFSET, + INFRA_RST1_SET_OFFSET, + INFRA_RST2_SET_OFFSET, + INFRA_RST3_SET_OFFSET, + INFRA_RST4_SET_OFFSET, +}; + +static u16 infra_ao_idx_map[] = { + [MT8186_INFRA_THERMAL_CTRL_RST] = 0 * RST_NR_PER_BANK + 0, + [MT8186_INFRA_PTP_CTRL_RST] = 1 * RST_NR_PER_BANK + 0, +}; + +static struct mtk_clk_rst_desc infra_ao_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_ao_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs), + .rst_idx_map = infra_ao_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map), +}; + +static const struct mtk_clk_desc infra_ao_desc = { + .clks = infra_ao_clks, + .num_clks = ARRAY_SIZE(infra_ao_clks), + .rst_desc = &infra_ao_rst_desc, +}; + +static const struct of_device_id of_match_clk_mt8186_infra_ao[] = { + { + .compatible = "mediatek,mt8186-infracfg_ao", + .data = &infra_ao_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_infra_ao_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-infra-ao", + .of_match_table = of_match_clk_mt8186_infra_ao, + }, +}; +builtin_platform_driver(clk_mt8186_infra_ao_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-ipe.c b/drivers/clk/mediatek/clk-mt8186-ipe.c new file mode 100644 index 000000000..8fca148ef --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-ipe.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs ipe_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipe_clks[] = { + GATE_IPE(CLK_IPE_LARB19, "ipe_larb19", "top_ipe", 0), + GATE_IPE(CLK_IPE_LARB20, "ipe_larb20", "top_ipe", 1), + GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "top_ipe", 2), + GATE_IPE(CLK_IPE_FD, "ipe_fd", "top_ipe", 3), + GATE_IPE(CLK_IPE_FE, "ipe_fe", "top_ipe", 4), + GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "top_ipe", 5), + GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "top_ipe", 6), + GATE_IPE(CLK_IPE_GALS_IPE, "ipe_gals_ipe", "top_img1", 8), +}; + +static const struct mtk_clk_desc ipe_desc = { + .clks = ipe_clks, + .num_clks = ARRAY_SIZE(ipe_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_ipe[] = { + { + .compatible = "mediatek,mt8186-ipesys", + .data = &ipe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_ipe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-ipe", + .of_match_table = of_match_clk_mt8186_ipe, + }, +}; +builtin_platform_driver(clk_mt8186_ipe_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mcu.c b/drivers/clk/mediatek/clk-mt8186-mcu.c new file mode 100644 index 000000000..dfc305c1f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mcu.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-mtk.h" + +static const char * const mcu_armpll_ll_parents[] = { + "clk26m", + "armpll_ll", + "mainpll", + "univpll_d2" +}; + +static const char * const mcu_armpll_bl_parents[] = { + "clk26m", + "armpll_bl", + "mainpll", + "univpll_d2" +}; + +static const char * const mcu_armpll_bus_parents[] = { + "clk26m", + "ccipll", + "mainpll", + "univpll_d2" +}; + +/* + * We only configure the CPU muxes when adjust CPU frequency in MediaTek CPUFreq Driver. + * Other fields like divider always keep the same value. (set once in bootloader) + */ +static struct mtk_composite mcu_muxes[] = { + /* CPU_PLLDIV_CFG0 */ + MUX(CLK_MCU_ARMPLL_LL_SEL, "mcu_armpll_ll_sel", mcu_armpll_ll_parents, 0x2A0, 9, 2), + /* CPU_PLLDIV_CFG1 */ + MUX(CLK_MCU_ARMPLL_BL_SEL, "mcu_armpll_bl_sel", mcu_armpll_bl_parents, 0x2A4, 9, 2), + /* BUS_PLLDIV_CFG */ + MUX(CLK_MCU_ARMPLL_BUS_SEL, "mcu_armpll_bus_sel", mcu_armpll_bus_parents, 0x2E0, 9, 2), +}; + +static const struct of_device_id of_match_clk_mt8186_mcu[] = { + { .compatible = "mediatek,mt8186-mcusys", }, + {} +}; + +static int clk_mt8186_mcu_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + if (!clk_data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + r = PTR_ERR(base); + goto free_mcu_data; + } + + r = mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), base, + NULL, clk_data); + if (r) + goto free_mcu_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_composite_muxes; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_composite_muxes: + mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data); +free_mcu_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_mcu_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_mcu_drv = { + .probe = clk_mt8186_mcu_probe, + .remove = clk_mt8186_mcu_remove, + .driver = { + .name = "clk-mt8186-mcu", + .of_match_table = of_match_clk_mt8186_mcu, + }, +}; +builtin_platform_driver(clk_mt8186_mcu_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mdp.c b/drivers/clk/mediatek/clk-mt8186-mdp.c new file mode 100644 index 000000000..05174088e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mdp.c @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mdp0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mdp2_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +#define GATE_MDP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MDP2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mdp_clks[] = { + /* MDP0 */ + GATE_MDP0(CLK_MDP_RDMA0, "mdp_rdma0", "top_mdp", 0), + GATE_MDP0(CLK_MDP_TDSHP0, "mdp_tdshp0", "top_mdp", 1), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC0, "mdp_img_dl_async0", "top_mdp", 2), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC1, "mdp_img_dl_async1", "top_mdp", 3), + GATE_MDP0(CLK_MDP_DISP_RDMA, "mdp_disp_rdma", "top_mdp", 4), + GATE_MDP0(CLK_MDP_HMS, "mdp_hms", "top_mdp", 5), + GATE_MDP0(CLK_MDP_SMI0, "mdp_smi0", "top_mdp", 6), + GATE_MDP0(CLK_MDP_APB_BUS, "mdp_apb_bus", "top_mdp", 7), + GATE_MDP0(CLK_MDP_WROT0, "mdp_wrot0", "top_mdp", 8), + GATE_MDP0(CLK_MDP_RSZ0, "mdp_rsz0", "top_mdp", 9), + GATE_MDP0(CLK_MDP_HDR0, "mdp_hdr0", "top_mdp", 10), + GATE_MDP0(CLK_MDP_MUTEX0, "mdp_mutex0", "top_mdp", 11), + GATE_MDP0(CLK_MDP_WROT1, "mdp_wrot1", "top_mdp", 12), + GATE_MDP0(CLK_MDP_RSZ1, "mdp_rsz1", "top_mdp", 13), + GATE_MDP0(CLK_MDP_FAKE_ENG0, "mdp_fake_eng0", "top_mdp", 14), + GATE_MDP0(CLK_MDP_AAL0, "mdp_aal0", "top_mdp", 15), + GATE_MDP0(CLK_MDP_DISP_WDMA, "mdp_disp_wdma", "top_mdp", 16), + GATE_MDP0(CLK_MDP_COLOR, "mdp_color", "top_mdp", 17), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC2, "mdp_img_dl_async2", "top_mdp", 18), + /* MDP2 */ + GATE_MDP2(CLK_MDP_IMG_DL_RELAY0_ASYNC0, "mdp_img_dl_rel0_as0", "top_mdp", 0), + GATE_MDP2(CLK_MDP_IMG_DL_RELAY1_ASYNC1, "mdp_img_dl_rel1_as1", "top_mdp", 8), + GATE_MDP2(CLK_MDP_IMG_DL_RELAY2_ASYNC2, "mdp_img_dl_rel2_as2", "top_mdp", 24), +}; + +static const struct mtk_clk_desc mdp_desc = { + .clks = mdp_clks, + .num_clks = ARRAY_SIZE(mdp_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_mdp[] = { + { + .compatible = "mediatek,mt8186-mdpsys", + .data = &mdp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_mdp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-mdp", + .of_match_table = of_match_clk_mt8186_mdp, + }, +}; +builtin_platform_driver(clk_mt8186_mdp_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mfg.c b/drivers/clk/mediatek/clk-mt8186-mfg.c new file mode 100644 index 000000000..f1f92216f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mfg.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "top_mfg", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_mfg[] = { + { + .compatible = "mediatek,mt8186-mfgsys", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-mfg", + .of_match_table = of_match_clk_mt8186_mfg, + }, +}; +builtin_platform_driver(clk_mt8186_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-mm.c b/drivers/clk/mediatek/clk-mt8186-mm.c new file mode 100644 index 000000000..1d33be407 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-mm.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x1a4, + .clr_ofs = 0x1a8, + .sta_ofs = 0x1a0, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_DISP_MUTEX0, "mm_disp_mutex0", "top_disp", 0), + GATE_MM0(CLK_MM_APB_MM_BUS, "mm_apb_mm_bus", "top_disp", 1), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "top_disp", 2), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "top_disp", 3), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "top_disp", 4), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "top_disp", 5), + GATE_MM0(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "top_disp", 7), + GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "top_disp", 8), + GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "top_disp", 9), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "top_disp", 10), + GATE_MM0(CLK_MM_SMI_INFRA, "mm_smi_infra", "top_disp", 11), + GATE_MM0(CLK_MM_DISP_DSC_WRAP0, "mm_disp_dsc_wrap0", "top_disp", 12), + GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "top_disp", 13), + GATE_MM0(CLK_MM_DISP_POSTMASK0, "mm_disp_postmask0", "top_disp", 14), + GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "top_disp", 16), + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "top_disp", 17), + GATE_MM0(CLK_MM_DSI0, "mm_dsi0", "top_disp", 19), + GATE_MM0(CLK_MM_DISP_FAKE_ENG0, "mm_disp_fake_eng0", "top_disp", 20), + GATE_MM0(CLK_MM_DISP_FAKE_ENG1, "mm_disp_fake_eng1", "top_disp", 21), + GATE_MM0(CLK_MM_SMI_GALS, "mm_smi_gals", "top_disp", 22), + GATE_MM0(CLK_MM_SMI_IOMMU, "mm_smi_iommu", "top_disp", 24), + GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "top_disp", 25), + GATE_MM0(CLK_MM_DISP_DPI, "mm_disp_dpi", "top_disp", 26), + /* MM1 */ + GATE_MM1(CLK_MM_DSI0_DSI_CK_DOMAIN, "mm_dsi0_dsi_domain", "top_disp", 0), + GATE_MM1(CLK_MM_DISP_26M, "mm_disp_26m_ck", "top_disp", 10), +}; + +static int clk_mt8186_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); + if (r) + goto free_mm_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(mm_clks, ARRAY_SIZE(mm_clks), clk_data); +free_mm_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_mm_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(mm_clks, ARRAY_SIZE(mm_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_mm_drv = { + .probe = clk_mt8186_mm_probe, + .remove = clk_mt8186_mm_remove, + .driver = { + .name = "clk-mt8186-mm", + }, +}; +builtin_platform_driver(clk_mt8186_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-topckgen.c b/drivers/clk/mediatek/clk-mt8186-topckgen.c new file mode 100644 index 000000000..d7f2c4663 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-topckgen.c @@ -0,0 +1,780 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-mtk.h" +#include "clk-mux.h" + +static DEFINE_SPINLOCK(mt8186_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_ULPOSC1, "ulposc1", NULL, 250000000), + FIXED_CLK(CLK_TOP_466M_FMEM, "hd_466m_fmem_ck", NULL, 466000000), + FIXED_CLK(CLK_TOP_MPLL, "mpll", NULL, 208000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D2, "mainpll_d2_d2", "mainpll_d2", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D2_D4, "mainpll_d2_d4", "mainpll_d2", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D2_D16, "mainpll_d2_d16", "mainpll_d2", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D3_D2, "mainpll_d3_d2", "mainpll_d3", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D3_D4, "mainpll_d3_d4", "mainpll_d3", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ2pll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D2, "univpll_d2_d2", "univpll_d2", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2_D4, "univpll_d2_d4", "univpll_d2", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D3_D2, "univpll_d3_d2", "univpll_d3", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D3_D4, "univpll_d3_d4", "univpll_d3", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D3_D8, "univpll_d3_d8", "univpll_d3", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3_D32, "univpll_d3_d32", "univpll_d3", 1, 32), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univ2pll", 1, 13), + FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16), + FACTOR(CLK_TOP_TVDPLL_D32, "tvdpll_d32", "tvdpll", 1, 32), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1", 1, 4), + FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1", 1, 8), + FACTOR(CLK_TOP_ULPOSC1_D10, "ulposc1_d10", "ulposc1", 1, 10), + FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1", 1, 16), + FACTOR(CLK_TOP_ULPOSC1_D32, "ulposc1_d32", "ulposc1", 1, 32), + FACTOR(CLK_TOP_ADSPPLL_D2, "adsppll_d2", "adsppll", 1, 2), + FACTOR(CLK_TOP_ADSPPLL_D4, "adsppll_d4", "adsppll", 1, 4), + FACTOR(CLK_TOP_ADSPPLL_D8, "adsppll_d8", "adsppll", 1, 8), + FACTOR(CLK_TOP_NNAPLL_D2, "nnapll_d2", "nnapll", 1, 2), + FACTOR(CLK_TOP_NNAPLL_D4, "nnapll_d4", "nnapll", 1, 4), + FACTOR(CLK_TOP_NNAPLL_D8, "nnapll_d8", "nnapll", 1, 8), + FACTOR(CLK_TOP_NNA2PLL_D2, "nna2pll_d2", "nna2pll", 1, 2), + FACTOR(CLK_TOP_NNA2PLL_D4, "nna2pll_d4", "nna2pll", 1, 4), + FACTOR(CLK_TOP_NNA2PLL_D8, "nna2pll_d8", "nna2pll", 1, 8), + FACTOR(CLK_TOP_F_BIST2FPC, "f_bist2fpc_ck", "univpll_d3_d2", 1, 1), +}; + +static const char * const axi_parents[] = { + "clk26m", + "mainpll_d7", + "mainpll_d2_d4", + "univpll_d7" +}; + +static const char * const scp_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d5", + "mainpll_d2_d2", + "mainpll_d3", + "univpll_d3" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll", + "mainpll_d3", + "mainpll_d5" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d3_d8", + "univpll_192m_d4", + "univpll_d3_d32", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d3_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d3_d4", + "mainpll_d5_d2", + "mainpll_d2_d4", + "mainpll_d7", + "mainpll_d3_d2", + "mainpll_d5" +}; + +static const char * const msdc5hclk_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d7", + "mainpll_d3_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll", + "univpll_d3", + "msdcpll_d2", + "mainpll_d7", + "mainpll_d3_d2", + "univpll_d2_d2" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "msdcpll_d2", + "univpll_d3_d2", + "mainpll_d3_d2", + "mainpll_d7" +}; + +static const char * const audio_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d7_d4", + "mainpll_d2_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "mainpll_d2_d4", + "mainpll_d7_d2" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll_d5_d2", + "univpll_d3_d4", + "ulposc1_d2", + "ulposc1_d8" +}; + +static const char * const sspm_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d3_d2", + "mainpll_d5", + "mainpll_d3" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "mainpll_d2_d2", + "mainpll_d2_d4" +}; + +static const char * const usb_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d5_d2" +}; + +static const char * const srck_parents[] = { + "clk32k", + "clk26m", + "ulposc1_d10" +}; + +static const char * const spm_parents[] = { + "clk32k", + "ulposc1_d10", + "clk26m", + "mainpll_d7_d2" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d3_d4", + "univpll_d5_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll_d3_d8", + "univpll_d3_d4", + "univpll_d2_d4" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d2_d4", + "univpll_d2_d2", + "univpll_d3_d2" +}; + +static const char * const aes_msdcfde_parents[] = { + "clk26m", + "univpll_d3", + "mainpll_d3", + "univpll_d2_d2", + "mainpll_d2_d2", + "mainpll_d2_d4" +}; + +static const char * const pwrap_ulposc_parents[] = { + "clk26m", + "univpll_d5_d4", + "ulposc1_d4", + "ulposc1_d8", + "ulposc1_d10", + "ulposc1_d16", + "ulposc1_d32" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll_d2_d4", + "univpll_d3_d2" +}; + +static const char * const venc_parents[] = { + "clk26m", + "mmpll", + "mainpll_d2_d2", + "mainpll_d2", + "univpll_d3", + "univpll_d2_d2", + "mainpll_d3", + "mmpll" +}; + +static const char * const isp_parents[] = { + "clk26m", + "mainpll_d2", + "mainpll_d2_d2", + "univpll_d3", + "mainpll_d3", + "mmpll", + "univpll_d5", + "univpll_d2_d2", + "mmpll_d2" +}; + +static const char * const dpmaif_parents[] = { + "clk26m", + "univpll_d2_d2", + "mainpll_d3", + "mainpll_d2_d2", + "univpll_d3_d2" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "mainpll_d3", + "mainpll_d2_d2", + "univpll_d5", + "mainpll_d2", + "univpll_d3", + "univpll_d2_d2" +}; + +static const char * const disp_parents[] = { + "clk26m", + "univpll_d3_d2", + "mainpll_d5", + "univpll_d5", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const mdp_parents[] = { + "clk26m", + "mainpll_d5", + "univpll_d5", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "univpll_d7", + "apll1", + "apll2" +}; + +static const char * const ufs_parents[] = { + "clk26m", + "mainpll_d7", + "univpll_d2_d4", + "mainpll_d2_d4" +}; + +static const char * const aes_fde_parents[] = { + "clk26m", + "univpll_d3", + "mainpll_d2_d2", + "univpll_d5" +}; + +static const char * const audiodsp_parents[] = { + "clk26m", + "ulposc1_d10", + "adsppll", + "adsppll_d2", + "adsppll_d4", + "adsppll_d8" +}; + +static const char * const dvfsrc_parents[] = { + "clk26m", + "ulposc1_d10", +}; + +static const char * const dsi_occ_parents[] = { + "clk26m", + "univpll_d3_d2", + "mpll", + "mainpll_d5" +}; + +static const char * const spmi_mst_parents[] = { + "clk26m", + "univpll_d5_d4", + "ulposc1_d4", + "ulposc1_d8", + "ulposc1_d10", + "ulposc1_d16", + "ulposc1_d32" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk13m", + "mainpll_d7_d4", + "univpll_d3_d8", + "univpll_d5_d4", + "mainpll_d7_d2" +}; + +static const char * const nna_parents[] = { + "clk26m", + "univpll_d3_d8", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll", + "mainpll_d2", + "univpll_d2", + "nnapll_d2", + "nnapll_d4", + "nnapll_d8", + "nnapll", + "nna2pll" +}; + +static const char * const nna2_parents[] = { + "clk26m", + "univpll_d3_d8", + "mainpll_d2_d4", + "univpll_d3_d2", + "mainpll_d2_d2", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mmpll", + "mainpll_d2", + "univpll_d2", + "nna2pll_d2", + "nna2pll_d4", + "nna2pll_d8", + "nnapll", + "nna2pll" +}; + +static const char * const ssusb_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d5_d2" +}; + +static const char * const wpe_parents[] = { + "clk26m", + "univpll_d3_d2", + "mainpll_d5", + "univpll_d5", + "univpll_d2_d2", + "mainpll_d3", + "univpll_d3", + "mainpll_d2", + "mmpll" +}; + +static const char * const dpi_parents[] = { + "clk26m", + "tvdpll", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16", + "tvdpll_d32" +}; + +static const char * const u3_occ_250m_parents[] = { + "clk26m", + "univpll_d5" +}; + +static const char * const u3_occ_500m_parents[] = { + "clk26m", + "nna2pll_d2" +}; + +static const char * const adsp_bus_parents[] = { + "clk26m", + "ulposc1_d2", + "mainpll_d5", + "mainpll_d2_d2", + "mainpll_d3", + "mainpll_d2", + "univpll_d3" +}; + +static const char * const apll_mck_parents[] = { + "top_aud_1", + "top_aud_2" +}; + +static const struct mtk_mux top_mtk_muxes[] = { + /* + * CLK_CFG_0 + * top_axi is bus clock, should not be closed by Linux. + * top_scp is main clock in always-on co-processor. + */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", axi_parents, + 0x0040, 0x0044, 0x0048, 0, 2, 7, 0x0004, 0, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", scp_parents, + 0x0040, 0x0044, 0x0048, 8, 3, 15, 0x0004, 1, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG, "top_mfg", + mfg_parents, 0x0040, 0x0044, 0x0048, 16, 2, 23, 0x0004, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "top_camtg", + camtg_parents, 0x0040, 0x0044, 0x0048, 24, 3, 31, 0x0004, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG1, "top_camtg1", + camtg_parents, 0x0050, 0x0054, 0x0058, 0, 3, 7, 0x0004, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2, "top_camtg2", + camtg_parents, 0x0050, 0x0054, 0x0058, 8, 3, 15, 0x0004, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3, "top_camtg3", + camtg_parents, 0x0050, 0x0054, 0x0058, 16, 3, 23, 0x0004, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4, "top_camtg4", + camtg_parents, 0x0050, 0x0054, 0x0058, 24, 3, 31, 0x0004, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5, "top_camtg5", + camtg_parents, 0x0060, 0x0064, 0x0068, 0, 3, 7, 0x0004, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG6, "top_camtg6", + camtg_parents, 0x0060, 0x0064, 0x0068, 8, 3, 15, 0x0004, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART, "top_uart", + uart_parents, 0x0060, 0x0064, 0x0068, 16, 1, 23, 0x0004, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi", + spi_parents, 0x0060, 0x0064, 0x0068, 24, 3, 31, 0x0004, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc5hclk", + msdc5hclk_parents, 0x0070, 0x0074, 0x0078, 0, 2, 7, 0x0004, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x0070, 0x0074, 0x0078, 8, 3, 15, 0x0004, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_1_parents, 0x0070, 0x0074, 0x0078, 16, 3, 23, 0x0004, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO, "top_audio", + audio_parents, 0x0070, 0x0074, 0x0078, 24, 2, 31, 0x0004, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus", + aud_intbus_parents, 0x0080, 0x0084, 0x0088, 0, 2, 7, 0x0004, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1, "top_aud_1", + aud_1_parents, 0x0080, 0x0084, 0x0088, 8, 1, 15, 0x0004, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2, "top_aud_2", + aud_2_parents, 0x0080, 0x0084, 0x0088, 16, 1, 23, 0x0004, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1, "top_aud_engen1", + aud_engen1_parents, 0x0080, 0x0084, 0x0088, 24, 2, 31, 0x0004, 19), + /* + * CLK_CFG_5 + * top_sspm is main clock in always-on co-processor, should not be closed + * in Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2, "top_aud_engen2", + aud_engen2_parents, 0x0090, 0x0094, 0x0098, 0, 2, 7, 0x0004, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM, "top_disp_pwm", + disp_pwm_parents, 0x0090, 0x0094, 0x0098, 8, 3, 15, 0x0004, 21), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SSPM, "top_sspm", sspm_parents, + 0x0090, 0x0094, 0x0098, 16, 3, 23, 0x0004, 22, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "top_dxcc", + dxcc_parents, 0x0090, 0x0094, 0x0098, 24, 2, 31, 0x0004, 23), + /* + * CLK_CFG_6 + * top_spm and top_srck are main clocks in always-on co-processor. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP, "top_usb", + usb_parents, 0x00a0, 0x00a4, 0x00a8, 0, 2, 7, 0x0004, 24), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", srck_parents, + 0x00a0, 0x00a4, 0x00a8, 8, 2, 15, 0x0004, 25, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", spm_parents, + 0x00a0, 0x00a4, 0x00a8, 16, 2, 23, 0x0004, 26, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "top_i2c", + i2c_parents, 0x00a0, 0x00a4, 0x00a8, 24, 2, 31, 0x0004, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm", + pwm_parents, 0x00b0, 0x00b4, 0x00b8, 0, 2, 7, 0x0004, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF, "top_seninf", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 8, 2, 15, 0x0004, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1, "top_seninf1", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 16, 2, 23, 0x0004, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2, "top_seninf2", + seninf_parents, 0x00b0, 0x00b4, 0x00b8, 24, 2, 31, 0x0008, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF3, "top_seninf3", + seninf_parents, 0x00c0, 0x00c4, 0x00c8, 0, 2, 7, 0x0008, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE, "top_aes_msdcfde", + aes_msdcfde_parents, 0x00c0, 0x00c4, 0x00c8, 8, 3, 15, 0x0008, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWRAP_ULPOSC, "top_pwrap_ulposc", + pwrap_ulposc_parents, 0x00c0, 0x00c4, 0x00c8, 16, 3, 23, 0x0008, 3), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM, "top_camtm", + camtm_parents, 0x00c0, 0x00c4, 0x00c8, 24, 2, 31, 0x0008, 4), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC, "top_venc", + venc_parents, 0x00d0, 0x00d4, 0x00d8, 0, 3, 7, 0x0008, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM, "top_cam", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 8, 4, 15, 0x0008, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1, "top_img1", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 16, 4, 23, 0x0008, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE, "top_ipe", + isp_parents, 0x00d0, 0x00d4, 0x00d8, 24, 4, 31, 0x0008, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF, "top_dpmaif", + dpmaif_parents, 0x00e0, 0x00e4, 0x00e8, 0, 3, 7, 0x0008, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC, "top_vdec", + vdec_parents, 0x00e0, 0x00e4, 0x00e8, 8, 3, 15, 0x0008, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP, "top_disp", + disp_parents, 0x00e0, 0x00e4, 0x00e8, 16, 4, 23, 0x0008, 11), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP, "top_mdp", + mdp_parents, 0x00e0, 0x00e4, 0x00e8, 24, 4, 31, 0x0008, 12), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H, "top_audio_h", + audio_h_parents, 0x00ec, 0x00f0, 0x00f4, 0, 2, 7, 0x0008, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS, "top_ufs", + ufs_parents, 0x00ec, 0x00f0, 0x00f4, 8, 2, 15, 0x0008, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_FDE, "top_aes_fde", + aes_fde_parents, 0x00ec, 0x00f0, 0x00f4, 16, 2, 23, 0x0008, 15), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIODSP, "top_audiodsp", + audiodsp_parents, 0x00ec, 0x00f0, 0x00f4, 24, 3, 31, 0x0008, 16), + /* + * CLK_CFG_12 + * dvfsrc is for internal DVFS usage, should not be closed in Linux. + */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", dvfsrc_parents, + 0x0100, 0x0104, 0x0108, 0, 1, 7, 0x0008, 17, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC, "top_dsi_occ", + dsi_occ_parents, 0x0100, 0x0104, 0x0108, 8, 2, 15, 0x0008, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST, "top_spmi_mst", + spmi_mst_parents, 0x0100, 0x0104, 0x0108, 16, 3, 23, 0x0008, 19), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINOR, "top_spinor", + spinor_parents, 0x0110, 0x0114, 0x0118, 0, 3, 6, 0x0008, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA, "top_nna", + nna_parents, 0x0110, 0x0114, 0x0118, 7, 4, 14, 0x0008, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA1, "top_nna1", + nna_parents, 0x0110, 0x0114, 0x0118, 15, 4, 22, 0x0008, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA2, "top_nna2", + nna2_parents, 0x0110, 0x0114, 0x0118, 23, 4, 30, 0x0008, 23), + /* CLK_CFG_14 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI, "top_ssusb_xhci", + ssusb_parents, 0x0120, 0x0124, 0x0128, 0, 2, 5, 0x0008, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_TOP_1P, "top_ssusb_1p", + ssusb_parents, 0x0120, 0x0124, 0x0128, 6, 2, 11, 0x0008, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_1P, "top_ssusb_xhci_1p", + ssusb_parents, 0x0120, 0x0124, 0x0128, 12, 2, 17, 0x0008, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_WPE, "top_wpe", + wpe_parents, 0x0120, 0x0124, 0x0128, 18, 4, 25, 0x0008, 27), + /* CLK_CFG_15 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI, "top_dpi", + dpi_parents, 0x0180, 0x0184, 0x0188, 0, 3, 6, 0x0008, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U3_OCC_250M, "top_u3_occ_250m", + u3_occ_250m_parents, 0x0180, 0x0184, 0x0188, 7, 1, 11, 0x0008, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_U3_OCC_500M, "top_u3_occ_500m", + u3_occ_500m_parents, 0x0180, 0x0184, 0x0188, 12, 1, 16, 0x0008, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP_BUS, "top_adsp_bus", + adsp_bus_parents, 0x0180, 0x0184, 0x0188, 17, 3, 23, 0x0008, 31), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL_I2S0_MCK_SEL, "apll_i2s0_mck_sel", apll_mck_parents, 0x0320, 16, 1), + MUX(CLK_TOP_APLL_I2S1_MCK_SEL, "apll_i2s1_mck_sel", apll_mck_parents, 0x0320, 17, 1), + MUX(CLK_TOP_APLL_I2S2_MCK_SEL, "apll_i2s2_mck_sel", apll_mck_parents, 0x0320, 18, 1), + MUX(CLK_TOP_APLL_I2S4_MCK_SEL, "apll_i2s4_mck_sel", apll_mck_parents, 0x0320, 19, 1), + MUX(CLK_TOP_APLL_TDMOUT_MCK_SEL, "apll_tdmout_mck_sel", apll_mck_parents, + 0x0320, 20, 1), +}; + +static const struct mtk_composite top_adj_divs[] = { + DIV_GATE(CLK_TOP_APLL12_CK_DIV0, "apll12_div0", "apll_i2s0_mck_sel", + 0x0320, 0, 0x0328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_CK_DIV1, "apll12_div1", "apll_i2s1_mck_sel", + 0x0320, 1, 0x0328, 8, 8), + DIV_GATE(CLK_TOP_APLL12_CK_DIV2, "apll12_div2", "apll_i2s2_mck_sel", + 0x0320, 2, 0x0328, 8, 16), + DIV_GATE(CLK_TOP_APLL12_CK_DIV4, "apll12_div4", "apll_i2s4_mck_sel", + 0x0320, 3, 0x0328, 8, 24), + DIV_GATE(CLK_TOP_APLL12_CK_DIV_TDMOUT_M, "apll12_div_tdmout_m", "apll_tdmout_mck_sel", + 0x0320, 4, 0x0334, 8, 0), +}; + +static const struct of_device_id of_match_clk_mt8186_topck[] = { + { .compatible = "mediatek,mt8186-topckgen", }, + {} +}; + +static int clk_mt8186_topck_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + r = PTR_ERR(base); + goto free_top_data; + } + + r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + clk_data); + if (r) + goto free_top_data; + + r = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + if (r) + goto unregister_fixed_clks; + + r = mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_factors; + + r = mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_muxes; + + r = mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt8186_clk_lock, clk_data); + if (r) + goto unregister_composite_muxes; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_composite_divs; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_composite_divs: + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), clk_data); +unregister_composite_muxes: + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); +free_top_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8186_topck_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), clk_data); + mtk_clk_unregister_composites(top_muxes, ARRAY_SIZE(top_muxes), clk_data); + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), clk_data); + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8186_topck_drv = { + .probe = clk_mt8186_topck_probe, + .remove = clk_mt8186_topck_remove, + .driver = { + .name = "clk-mt8186-topck", + .of_match_table = of_match_clk_mt8186_topck, + }, +}; +builtin_platform_driver(clk_mt8186_topck_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-vdec.c b/drivers/clk/mediatek/clk-mt8186-vdec.c new file mode 100644 index 000000000..5ad7e1ae0 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-vdec.c @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/module.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8186-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x190, + .clr_ofs = 0x190, + .sta_ofs = 0x190, +}; + +static const struct mtk_gate_regs vdec2_cg_regs = { + .set_ofs = 0x200, + .clr_ofs = 0x204, + .sta_ofs = 0x200, +}; + +static const struct mtk_gate_regs vdec3_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_VDEC2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec3_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "top_vdec", 0), + GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "top_vdec", 4), + GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "top_vdec", 8), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_MINI_MDP_CKEN_CFG_RG, "vdec_mini_mdp_cken_cfg_rg", "top_vdec", 0), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_LAT_CKEN, "vdec_lat_cken", "top_vdec", 0), + GATE_VDEC2(CLK_VDEC_LAT_ACTIVE, "vdec_lat_active", "top_vdec", 4), + GATE_VDEC2(CLK_VDEC_LAT_CKEN_ENG, "vdec_lat_cken_eng", "top_vdec", 8), + /* VDEC3 */ + GATE_VDEC3(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "top_vdec", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_vdec[] = { + { + .compatible = "mediatek,mt8186-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-vdec", + .of_match_table = of_match_clk_mt8186_vdec, + }, +}; +builtin_platform_driver(clk_mt8186_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-venc.c b/drivers/clk/mediatek/clk-mt8186-venc.c new file mode 100644 index 000000000..f5519f794 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-venc.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_CKE0_LARB, "venc_cke0_larb", "top_venc", 0), + GATE_VENC(CLK_VENC_CKE1_VENC, "venc_cke1_venc", "top_venc", 4), + GATE_VENC(CLK_VENC_CKE2_JPGENC, "venc_cke2_jpgenc", "top_venc", 8), + GATE_VENC(CLK_VENC_CKE5_GALS, "venc_cke5_gals", "top_venc", 28), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_venc[] = { + { + .compatible = "mediatek,mt8186-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-venc", + .of_match_table = of_match_clk_mt8186_venc, + }, +}; +builtin_platform_driver(clk_mt8186_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt8186-wpe.c b/drivers/clk/mediatek/clk-mt8186-wpe.c new file mode 100644 index 000000000..8db3e9178 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8186-wpe.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2022 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> +#include <dt-bindings/clock/mt8186-clk.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs wpe_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_WPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wpe_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate wpe_clks[] = { + GATE_WPE(CLK_WPE_CK_EN, "wpe", "top_wpe", 17), + GATE_WPE(CLK_WPE_SMI_LARB8_CK_EN, "wpe_smi_larb8", "top_wpe", 19), + GATE_WPE(CLK_WPE_SYS_EVENT_TX_CK_EN, "wpe_sys_event_tx", "top_wpe", 20), + GATE_WPE(CLK_WPE_SMI_LARB8_PCLK_EN, "wpe_smi_larb8_p_en", "top_wpe", 25), +}; + +static const struct mtk_clk_desc wpe_desc = { + .clks = wpe_clks, + .num_clks = ARRAY_SIZE(wpe_clks), +}; + +static const struct of_device_id of_match_clk_mt8186_wpe[] = { + { + .compatible = "mediatek,mt8186-wpesys", + .data = &wpe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8186_wpe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8186-wpe", + .of_match_table = of_match_clk_mt8186_wpe, + }, +}; +builtin_platform_driver(clk_mt8186_wpe_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-aud.c b/drivers/clk/mediatek/clk-mt8192-aud.c new file mode 100644 index 000000000..8c989bffd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-aud.c @@ -0,0 +1,118 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs aud0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs aud1_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x4, + .sta_ofs = 0x4, +}; + +static const struct mtk_gate_regs aud2_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +#define GATE_AUD0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUD1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +#define GATE_AUD2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud2_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate aud_clks[] = { + /* AUD0 */ + GATE_AUD0(CLK_AUD_AFE, "aud_afe", "audio_sel", 2), + GATE_AUD0(CLK_AUD_22M, "aud_22m", "aud_engen1_sel", 8), + GATE_AUD0(CLK_AUD_24M, "aud_24m", "aud_engen2_sel", 9), + GATE_AUD0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "aud_engen2_sel", 18), + GATE_AUD0(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "aud_engen1_sel", 19), + GATE_AUD0(CLK_AUD_TDM, "aud_tdm", "aud_1_sel", 20), + GATE_AUD0(CLK_AUD_ADC, "aud_adc", "audio_sel", 24), + GATE_AUD0(CLK_AUD_DAC, "aud_dac", "audio_sel", 25), + GATE_AUD0(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "audio_sel", 26), + GATE_AUD0(CLK_AUD_TML, "aud_tml", "audio_sel", 27), + GATE_AUD0(CLK_AUD_NLE, "aud_nle", "audio_sel", 28), + /* AUD1 */ + GATE_AUD1(CLK_AUD_I2S1_B, "aud_i2s1_b", "audio_sel", 4), + GATE_AUD1(CLK_AUD_I2S2_B, "aud_i2s2_b", "audio_sel", 5), + GATE_AUD1(CLK_AUD_I2S3_B, "aud_i2s3_b", "audio_sel", 6), + GATE_AUD1(CLK_AUD_I2S4_B, "aud_i2s4_b", "audio_sel", 7), + GATE_AUD1(CLK_AUD_CONNSYS_I2S_ASRC, "aud_connsys_i2s_asrc", "audio_sel", 12), + GATE_AUD1(CLK_AUD_GENERAL1_ASRC, "aud_general1_asrc", "audio_sel", 13), + GATE_AUD1(CLK_AUD_GENERAL2_ASRC, "aud_general2_asrc", "audio_sel", 14), + GATE_AUD1(CLK_AUD_DAC_HIRES, "aud_dac_hires", "audio_h_sel", 15), + GATE_AUD1(CLK_AUD_ADC_HIRES, "aud_adc_hires", "audio_h_sel", 16), + GATE_AUD1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml", "audio_h_sel", 17), + GATE_AUD1(CLK_AUD_ADDA6_ADC, "aud_adda6_adc", "audio_sel", 20), + GATE_AUD1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires", "audio_h_sel", 21), + GATE_AUD1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "audio_sel", 28), + GATE_AUD1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis", "audio_sel", 29), + GATE_AUD1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml", "audio_sel", 30), + GATE_AUD1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires", "audio_h_sel", 31), + /* AUD2 */ + GATE_AUD2(CLK_AUD_I2S5_B, "aud_i2s5_b", "audio_sel", 0), + GATE_AUD2(CLK_AUD_I2S6_B, "aud_i2s6_b", "audio_sel", 1), + GATE_AUD2(CLK_AUD_I2S7_B, "aud_i2s7_b", "audio_sel", 2), + GATE_AUD2(CLK_AUD_I2S8_B, "aud_i2s8_b", "audio_sel", 3), + GATE_AUD2(CLK_AUD_I2S9_B, "aud_i2s9_b", "audio_sel", 4), +}; + +static int clk_mt8192_aud_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); + if (r) + return r; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + return r; + + r = devm_of_platform_populate(&pdev->dev); + if (r) + of_clk_del_provider(node); + + return r; +} + +static const struct of_device_id of_match_clk_mt8192_aud[] = { + { .compatible = "mediatek,mt8192-audsys", }, + {} +}; + +static struct platform_driver clk_mt8192_aud_drv = { + .probe = clk_mt8192_aud_probe, + .driver = { + .name = "clk-mt8192-aud", + .of_match_table = of_match_clk_mt8192_aud, + }, +}; + +builtin_platform_driver(clk_mt8192_aud_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-cam.c b/drivers/clk/mediatek/clk-mt8192-cam.c new file mode 100644 index 000000000..90b57d46e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-cam.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB13, "cam_larb13", "cam_sel", 0), + GATE_CAM(CLK_CAM_DFP_VAD, "cam_dfp_vad", "cam_sel", 1), + GATE_CAM(CLK_CAM_LARB14, "cam_larb14", "cam_sel", 2), + GATE_CAM(CLK_CAM_CAM, "cam_cam", "cam_sel", 6), + GATE_CAM(CLK_CAM_CAMTG, "cam_camtg", "cam_sel", 7), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "cam_sel", 8), + GATE_CAM(CLK_CAM_CAMSV0, "cam_camsv0", "cam_sel", 9), + GATE_CAM(CLK_CAM_CAMSV1, "cam_camsv1", "cam_sel", 10), + GATE_CAM(CLK_CAM_CAMSV2, "cam_camsv2", "cam_sel", 11), + GATE_CAM(CLK_CAM_CAMSV3, "cam_camsv3", "cam_sel", 12), + GATE_CAM(CLK_CAM_CCU0, "cam_ccu0", "cam_sel", 13), + GATE_CAM(CLK_CAM_CCU1, "cam_ccu1", "cam_sel", 14), + GATE_CAM(CLK_CAM_MRAW0, "cam_mraw0", "cam_sel", 15), + GATE_CAM(CLK_CAM_FAKE_ENG, "cam_fake_eng", "cam_sel", 17), + GATE_CAM(CLK_CAM_CCU_GALS, "cam_ccu_gals", "cam_sel", 18), + GATE_CAM(CLK_CAM_CAM2MM_GALS, "cam2mm_gals", "cam_sel", 19), +}; + +static const struct mtk_gate cam_rawa_clks[] = { + GATE_CAM(CLK_CAM_RAWA_LARBX, "cam_rawa_larbx", "cam_sel", 0), + GATE_CAM(CLK_CAM_RAWA_CAM, "cam_rawa_cam", "cam_sel", 1), + GATE_CAM(CLK_CAM_RAWA_CAMTG, "cam_rawa_camtg", "cam_sel", 2), +}; + +static const struct mtk_gate cam_rawb_clks[] = { + GATE_CAM(CLK_CAM_RAWB_LARBX, "cam_rawb_larbx", "cam_sel", 0), + GATE_CAM(CLK_CAM_RAWB_CAM, "cam_rawb_cam", "cam_sel", 1), + GATE_CAM(CLK_CAM_RAWB_CAMTG, "cam_rawb_camtg", "cam_sel", 2), +}; + +static const struct mtk_gate cam_rawc_clks[] = { + GATE_CAM(CLK_CAM_RAWC_LARBX, "cam_rawc_larbx", "cam_sel", 0), + GATE_CAM(CLK_CAM_RAWC_CAM, "cam_rawc_cam", "cam_sel", 1), + GATE_CAM(CLK_CAM_RAWC_CAMTG, "cam_rawc_camtg", "cam_sel", 2), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct mtk_clk_desc cam_rawa_desc = { + .clks = cam_rawa_clks, + .num_clks = ARRAY_SIZE(cam_rawa_clks), +}; + +static const struct mtk_clk_desc cam_rawb_desc = { + .clks = cam_rawb_clks, + .num_clks = ARRAY_SIZE(cam_rawb_clks), +}; + +static const struct mtk_clk_desc cam_rawc_desc = { + .clks = cam_rawc_clks, + .num_clks = ARRAY_SIZE(cam_rawc_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_cam[] = { + { + .compatible = "mediatek,mt8192-camsys", + .data = &cam_desc, + }, { + .compatible = "mediatek,mt8192-camsys_rawa", + .data = &cam_rawa_desc, + }, { + .compatible = "mediatek,mt8192-camsys_rawb", + .data = &cam_rawb_desc, + }, { + .compatible = "mediatek,mt8192-camsys_rawc", + .data = &cam_rawc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-cam", + .of_match_table = of_match_clk_mt8192_cam, + }, +}; + +builtin_platform_driver(clk_mt8192_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-img.c b/drivers/clk/mediatek/clk-mt8192-img.c new file mode 100644 index 000000000..da82d65a7 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-img.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_LARB9, "img_larb9", "img1_sel", 0), + GATE_IMG(CLK_IMG_LARB10, "img_larb10", "img1_sel", 1), + GATE_IMG(CLK_IMG_DIP, "img_dip", "img1_sel", 2), + GATE_IMG(CLK_IMG_GALS, "img_gals", "img1_sel", 12), +}; + +static const struct mtk_gate img2_clks[] = { + GATE_IMG(CLK_IMG2_LARB11, "img2_larb11", "img1_sel", 0), + GATE_IMG(CLK_IMG2_LARB12, "img2_larb12", "img1_sel", 1), + GATE_IMG(CLK_IMG2_MFB, "img2_mfb", "img1_sel", 6), + GATE_IMG(CLK_IMG2_WPE, "img2_wpe", "img1_sel", 7), + GATE_IMG(CLK_IMG2_MSS, "img2_mss", "img1_sel", 8), + GATE_IMG(CLK_IMG2_GALS, "img2_gals", "img1_sel", 12), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct mtk_clk_desc img2_desc = { + .clks = img2_clks, + .num_clks = ARRAY_SIZE(img2_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_img[] = { + { + .compatible = "mediatek,mt8192-imgsys", + .data = &img_desc, + }, { + .compatible = "mediatek,mt8192-imgsys2", + .data = &img2_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-img", + .of_match_table = of_match_clk_mt8192_img, + }, +}; + +builtin_platform_driver(clk_mt8192_img_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c new file mode 100644 index 000000000..ff8e20bb4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-imp_iic_wrap.c @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs imp_iic_wrap_cg_regs = { + .set_ofs = 0xe08, + .clr_ofs = 0xe04, + .sta_ofs = 0xe00, +}; + +#define GATE_IMP_IIC_WRAP(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &imp_iic_wrap_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE) + +static const struct mtk_gate imp_iic_wrap_c_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C10, "imp_iic_wrap_c_i2c10", "infra_i2c0", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C11, "imp_iic_wrap_c_i2c11", "infra_i2c0", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C12, "imp_iic_wrap_c_i2c12", "infra_i2c0", 2), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_C_I2C13, "imp_iic_wrap_c_i2c13", "infra_i2c0", 3), +}; + +static const struct mtk_gate imp_iic_wrap_e_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_E_I2C3, "imp_iic_wrap_e_i2c3", "infra_i2c0", 0), +}; + +static const struct mtk_gate imp_iic_wrap_n_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_N_I2C0, "imp_iic_wrap_n_i2c0", "infra_i2c0", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_N_I2C6, "imp_iic_wrap_n_i2c6", "infra_i2c0", 1), +}; + +static const struct mtk_gate imp_iic_wrap_s_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C7, "imp_iic_wrap_s_i2c7", "infra_i2c0", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C8, "imp_iic_wrap_s_i2c8", "infra_i2c0", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C9, "imp_iic_wrap_s_i2c9", "infra_i2c0", 2), +}; + +static const struct mtk_gate imp_iic_wrap_w_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C5, "imp_iic_wrap_w_i2c5", "infra_i2c0", 0), +}; + +static const struct mtk_gate imp_iic_wrap_ws_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C1, "imp_iic_wrap_ws_i2c1", "infra_i2c0", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C2, "imp_iic_wrap_ws_i2c2", "infra_i2c0", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_WS_I2C4, "imp_iic_wrap_ws_i2c4", "infra_i2c0", 2), +}; + +static const struct mtk_clk_desc imp_iic_wrap_c_desc = { + .clks = imp_iic_wrap_c_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_c_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_e_desc = { + .clks = imp_iic_wrap_e_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_e_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_n_desc = { + .clks = imp_iic_wrap_n_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_n_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_s_desc = { + .clks = imp_iic_wrap_s_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_s_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_w_desc = { + .clks = imp_iic_wrap_w_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_w_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_ws_desc = { + .clks = imp_iic_wrap_ws_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_ws_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_imp_iic_wrap[] = { + { + .compatible = "mediatek,mt8192-imp_iic_wrap_c", + .data = &imp_iic_wrap_c_desc, + }, { + .compatible = "mediatek,mt8192-imp_iic_wrap_e", + .data = &imp_iic_wrap_e_desc, + }, { + .compatible = "mediatek,mt8192-imp_iic_wrap_n", + .data = &imp_iic_wrap_n_desc, + }, { + .compatible = "mediatek,mt8192-imp_iic_wrap_s", + .data = &imp_iic_wrap_s_desc, + }, { + .compatible = "mediatek,mt8192-imp_iic_wrap_w", + .data = &imp_iic_wrap_w_desc, + }, { + .compatible = "mediatek,mt8192-imp_iic_wrap_ws", + .data = &imp_iic_wrap_ws_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_imp_iic_wrap_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-imp_iic_wrap", + .of_match_table = of_match_clk_mt8192_imp_iic_wrap, + }, +}; + +builtin_platform_driver(clk_mt8192_imp_iic_wrap_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-ipe.c b/drivers/clk/mediatek/clk-mt8192-ipe.c new file mode 100644 index 000000000..0225abe41 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-ipe.c @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs ipe_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ipe_clks[] = { + GATE_IPE(CLK_IPE_LARB19, "ipe_larb19", "ipe_sel", 0), + GATE_IPE(CLK_IPE_LARB20, "ipe_larb20", "ipe_sel", 1), + GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "ipe_sel", 2), + GATE_IPE(CLK_IPE_FD, "ipe_fd", "ipe_sel", 3), + GATE_IPE(CLK_IPE_FE, "ipe_fe", "ipe_sel", 4), + GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "ipe_sel", 5), + GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "ipe_sel", 6), + GATE_IPE(CLK_IPE_GALS, "ipe_gals", "ipe_sel", 8), +}; + +static const struct mtk_clk_desc ipe_desc = { + .clks = ipe_clks, + .num_clks = ARRAY_SIZE(ipe_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_ipe[] = { + { + .compatible = "mediatek,mt8192-ipesys", + .data = &ipe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_ipe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-ipe", + .of_match_table = of_match_clk_mt8192_ipe, + }, +}; + +builtin_platform_driver(clk_mt8192_ipe_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-mdp.c b/drivers/clk/mediatek/clk-mt8192-mdp.c new file mode 100644 index 000000000..4675788d7 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-mdp.c @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs mdp0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mdp1_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +#define GATE_MDP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MDP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mdp1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mdp_clks[] = { + /* MDP0 */ + GATE_MDP0(CLK_MDP_RDMA0, "mdp_mdp_rdma0", "mdp_sel", 0), + GATE_MDP0(CLK_MDP_TDSHP0, "mdp_mdp_tdshp0", "mdp_sel", 1), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC0, "mdp_img_dl_async0", "mdp_sel", 2), + GATE_MDP0(CLK_MDP_IMG_DL_ASYNC1, "mdp_img_dl_async1", "mdp_sel", 3), + GATE_MDP0(CLK_MDP_RDMA1, "mdp_mdp_rdma1", "mdp_sel", 4), + GATE_MDP0(CLK_MDP_TDSHP1, "mdp_mdp_tdshp1", "mdp_sel", 5), + GATE_MDP0(CLK_MDP_SMI0, "mdp_smi0", "mdp_sel", 6), + GATE_MDP0(CLK_MDP_APB_BUS, "mdp_apb_bus", "mdp_sel", 7), + GATE_MDP0(CLK_MDP_WROT0, "mdp_mdp_wrot0", "mdp_sel", 8), + GATE_MDP0(CLK_MDP_RSZ0, "mdp_mdp_rsz0", "mdp_sel", 9), + GATE_MDP0(CLK_MDP_HDR0, "mdp_mdp_hdr0", "mdp_sel", 10), + GATE_MDP0(CLK_MDP_MUTEX0, "mdp_mdp_mutex0", "mdp_sel", 11), + GATE_MDP0(CLK_MDP_WROT1, "mdp_mdp_wrot1", "mdp_sel", 12), + GATE_MDP0(CLK_MDP_RSZ1, "mdp_mdp_rsz1", "mdp_sel", 13), + GATE_MDP0(CLK_MDP_HDR1, "mdp_mdp_hdr1", "mdp_sel", 14), + GATE_MDP0(CLK_MDP_FAKE_ENG0, "mdp_mdp_fake_eng0", "mdp_sel", 15), + GATE_MDP0(CLK_MDP_AAL0, "mdp_mdp_aal0", "mdp_sel", 16), + GATE_MDP0(CLK_MDP_AAL1, "mdp_mdp_aal1", "mdp_sel", 17), + GATE_MDP0(CLK_MDP_COLOR0, "mdp_mdp_color0", "mdp_sel", 18), + GATE_MDP0(CLK_MDP_COLOR1, "mdp_mdp_color1", "mdp_sel", 19), + /* MDP1 */ + GATE_MDP1(CLK_MDP_IMG_DL_RELAY0_ASYNC0, "mdp_img_dl_relay0_async0", "mdp_sel", 0), + GATE_MDP1(CLK_MDP_IMG_DL_RELAY1_ASYNC1, "mdp_img_dl_relay1_async1", "mdp_sel", 8), +}; + +static const struct mtk_clk_desc mdp_desc = { + .clks = mdp_clks, + .num_clks = ARRAY_SIZE(mdp_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_mdp[] = { + { + .compatible = "mediatek,mt8192-mdpsys", + .data = &mdp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_mdp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-mdp", + .of_match_table = of_match_clk_mt8192_mdp, + }, +}; + +builtin_platform_driver(clk_mt8192_mdp_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-mfg.c b/drivers/clk/mediatek/clk-mt8192-mfg.c new file mode 100644 index 000000000..ec5b44ffa --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-mfg.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, \ + _shift, &mtk_clk_gate_ops_setclr, \ + CLK_SET_RATE_PARENT) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_pll_sel", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_mfg[] = { + { + .compatible = "mediatek,mt8192-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-mfg", + .of_match_table = of_match_clk_mt8192_mfg, + }, +}; + +builtin_platform_driver(clk_mt8192_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-mm.c b/drivers/clk/mediatek/clk-mt8192-mm.c new file mode 100644 index 000000000..1be3ff4d4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-mm.c @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs mm2_cg_regs = { + .set_ofs = 0x1a4, + .clr_ofs = 0x1a8, + .sta_ofs = 0x1a0, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_MM2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_DISP_MUTEX0, "mm_disp_mutex0", "disp_sel", 0), + GATE_MM0(CLK_MM_DISP_CONFIG, "mm_disp_config", "disp_sel", 1), + GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "disp_sel", 2), + GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "disp_sel", 3), + GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "disp_sel", 4), + GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "disp_sel", 5), + GATE_MM0(CLK_MM_DISP_UFBC_WDMA0, "mm_disp_ufbc_wdma0", "disp_sel", 6), + GATE_MM0(CLK_MM_DISP_RSZ0, "mm_disp_rsz0", "disp_sel", 7), + GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "disp_sel", 8), + GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "disp_sel", 9), + GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "disp_sel", 10), + GATE_MM0(CLK_MM_SMI_INFRA, "mm_smi_infra", "disp_sel", 11), + GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "disp_sel", 12), + GATE_MM0(CLK_MM_DISP_POSTMASK0, "mm_disp_postmask0", "disp_sel", 13), + GATE_MM0(CLK_MM_DISP_DSC_WRAP0, "mm_disp_dsc_wrap0", "disp_sel", 14), + GATE_MM0(CLK_MM_DSI0, "mm_dsi0", "disp_sel", 15), + GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "disp_sel", 16), + GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "disp_sel", 17), + GATE_MM0(CLK_MM_DISP_FAKE_ENG0, "mm_disp_fake_eng0", "disp_sel", 18), + GATE_MM0(CLK_MM_DISP_FAKE_ENG1, "mm_disp_fake_eng1", "disp_sel", 19), + GATE_MM0(CLK_MM_MDP_TDSHP4, "mm_mdp_tdshp4", "disp_sel", 20), + GATE_MM0(CLK_MM_MDP_RSZ4, "mm_mdp_rsz4", "disp_sel", 21), + GATE_MM0(CLK_MM_MDP_AAL4, "mm_mdp_aal4", "disp_sel", 22), + GATE_MM0(CLK_MM_MDP_HDR4, "mm_mdp_hdr4", "disp_sel", 23), + GATE_MM0(CLK_MM_MDP_RDMA4, "mm_mdp_rdma4", "disp_sel", 24), + GATE_MM0(CLK_MM_MDP_COLOR4, "mm_mdp_color4", "disp_sel", 25), + GATE_MM0(CLK_MM_DISP_Y2R0, "mm_disp_y2r0", "disp_sel", 26), + GATE_MM0(CLK_MM_SMI_GALS, "mm_smi_gals", "disp_sel", 27), + GATE_MM0(CLK_MM_DISP_OVL2_2L, "mm_disp_ovl2_2l", "disp_sel", 28), + GATE_MM0(CLK_MM_DISP_RDMA4, "mm_disp_rdma4", "disp_sel", 29), + GATE_MM0(CLK_MM_DISP_DPI0, "mm_disp_dpi0", "disp_sel", 30), + /* MM1 */ + GATE_MM1(CLK_MM_SMI_IOMMU, "mm_smi_iommu", "disp_sel", 0), + /* MM2 */ + GATE_MM2(CLK_MM_DSI_DSI0, "mm_dsi_dsi0", "disp_sel", 0), + GATE_MM2(CLK_MM_DPI_DPI0, "mm_dpi_dpi0", "dpi_sel", 8), + GATE_MM2(CLK_MM_26MHZ, "mm_26mhz", "clk26m", 24), + GATE_MM2(CLK_MM_32KHZ, "mm_32khz", "clk32k", 25), +}; + +static int clk_mt8192_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks), clk_data); + if (r) + return r; + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); +} + +static struct platform_driver clk_mt8192_mm_drv = { + .probe = clk_mt8192_mm_probe, + .driver = { + .name = "clk-mt8192-mm", + }, +}; + +builtin_platform_driver(clk_mt8192_mm_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-msdc.c b/drivers/clk/mediatek/clk-mt8192-msdc.c new file mode 100644 index 000000000..a72e1b73f --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-msdc.c @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs msdc_top_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_MSDC_TOP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &msdc_top_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate msdc_top_clks[] = { + GATE_MSDC_TOP(CLK_MSDC_TOP_AES_0P, "msdc_top_aes_0p", "aes_msdcfde_sel", 0), + GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_0P, "msdc_top_src_0p", "infra_msdc0_src", 1), + GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_1P, "msdc_top_src_1p", "infra_msdc1_src", 2), + GATE_MSDC_TOP(CLK_MSDC_TOP_SRC_2P, "msdc_top_src_2p", "infra_msdc2_src", 3), + GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC0, "msdc_top_p_msdc0", "axi_sel", 4), + GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC1, "msdc_top_p_msdc1", "axi_sel", 5), + GATE_MSDC_TOP(CLK_MSDC_TOP_P_MSDC2, "msdc_top_p_msdc2", "axi_sel", 6), + GATE_MSDC_TOP(CLK_MSDC_TOP_P_CFG, "msdc_top_p_cfg", "axi_sel", 7), + GATE_MSDC_TOP(CLK_MSDC_TOP_AXI, "msdc_top_axi", "axi_sel", 8), + GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_0P, "msdc_top_h_mst_0p", "infra_msdc0", 9), + GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_1P, "msdc_top_h_mst_1p", "infra_msdc1", 10), + GATE_MSDC_TOP(CLK_MSDC_TOP_H_MST_2P, "msdc_top_h_mst_2p", "infra_msdc2", 11), + GATE_MSDC_TOP(CLK_MSDC_TOP_MEM_OFF_DLY_26M, "msdc_top_mem_off_dly_26m", "clk26m", 12), + GATE_MSDC_TOP(CLK_MSDC_TOP_32K, "msdc_top_32k", "clk32k", 13), + GATE_MSDC_TOP(CLK_MSDC_TOP_AHB2AXI_BRG_AXI, "msdc_top_ahb2axi_brg_axi", "axi_sel", 14), +}; + +static const struct mtk_clk_desc msdc_top_desc = { + .clks = msdc_top_clks, + .num_clks = ARRAY_SIZE(msdc_top_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_msdc[] = { + { + .compatible = "mediatek,mt8192-msdc_top", + .data = &msdc_top_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_msdc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-msdc", + .of_match_table = of_match_clk_mt8192_msdc, + }, +}; + +builtin_platform_driver(clk_mt8192_msdc_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-scp_adsp.c b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c new file mode 100644 index 000000000..18a867910 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-scp_adsp.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs scp_adsp_cg_regs = { + .set_ofs = 0x180, + .clr_ofs = 0x180, + .sta_ofs = 0x180, +}; + +#define GATE_SCP_ADSP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &scp_adsp_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate scp_adsp_clks[] = { + GATE_SCP_ADSP(CLK_SCP_ADSP_AUDIODSP, "scp_adsp_audiodsp", "adsp_sel", 0), +}; + +static const struct mtk_clk_desc scp_adsp_desc = { + .clks = scp_adsp_clks, + .num_clks = ARRAY_SIZE(scp_adsp_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_scp_adsp[] = { + { + .compatible = "mediatek,mt8192-scp_adsp", + .data = &scp_adsp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_scp_adsp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-scp_adsp", + .of_match_table = of_match_clk_mt8192_scp_adsp, + }, +}; + +builtin_platform_driver(clk_mt8192_scp_adsp_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-vdec.c b/drivers/clk/mediatek/clk-mt8192-vdec.c new file mode 100644 index 000000000..e149962db --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-vdec.c @@ -0,0 +1,95 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x200, + .clr_ofs = 0x204, + .sta_ofs = 0x200, +}; + +static const struct mtk_gate_regs vdec2_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_VDEC, "vdec_vdec", "vdec_sel", 0), + GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LAT, "vdec_lat", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_LAT_ACTIVE, "vdec_lat_active", "vdec_sel", 4), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_LARB1, "vdec_larb1", "vdec_sel", 0), +}; + +static const struct mtk_gate vdec_soc_clks[] = { + /* VDEC_SOC0 */ + GATE_VDEC0(CLK_VDEC_SOC_VDEC, "vdec_soc_vdec", "vdec_sel", 0), + GATE_VDEC0(CLK_VDEC_SOC_VDEC_ACTIVE, "vdec_soc_vdec_active", "vdec_sel", 4), + /* VDEC_SOC1 */ + GATE_VDEC1(CLK_VDEC_SOC_LAT, "vdec_soc_lat", "vdec_sel", 0), + GATE_VDEC1(CLK_VDEC_SOC_LAT_ACTIVE, "vdec_soc_lat_active", "vdec_sel", 4), + /* VDEC_SOC2 */ + GATE_VDEC2(CLK_VDEC_SOC_LARB1, "vdec_soc_larb1", "vdec_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct mtk_clk_desc vdec_soc_desc = { + .clks = vdec_soc_clks, + .num_clks = ARRAY_SIZE(vdec_soc_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_vdec[] = { + { + .compatible = "mediatek,mt8192-vdecsys", + .data = &vdec_desc, + }, { + .compatible = "mediatek,mt8192-vdecsys_soc", + .data = &vdec_soc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-vdec", + .of_match_table = of_match_clk_mt8192_vdec, + }, +}; + +builtin_platform_driver(clk_mt8192_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt8192-venc.c b/drivers/clk/mediatek/clk-mt8192-venc.c new file mode 100644 index 000000000..80b8bb170 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192-venc.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8192-clk.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_SET0_LARB, "venc_set0_larb", "venc_sel", 0), + GATE_VENC(CLK_VENC_SET1_VENC, "venc_set1_venc", "venc_sel", 4), + GATE_VENC(CLK_VENC_SET2_JPGENC, "venc_set2_jpgenc", "venc_sel", 8), + GATE_VENC(CLK_VENC_SET5_GALS, "venc_set5_gals", "venc_sel", 28), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt8192_venc[] = { + { + .compatible = "mediatek,mt8192-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8192_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8192-venc", + .of_match_table = of_match_clk_mt8192_venc, + }, +}; + +builtin_platform_driver(clk_mt8192_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt8192.c b/drivers/clk/mediatek/clk-mt8192.c new file mode 100644 index 000000000..d0f226931 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8192.c @@ -0,0 +1,1253 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8192-clk.h> +#include <dt-bindings/reset/mt8192-resets.h> + +static DEFINE_SPINLOCK(mt8192_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_ULPOSC, "ulposc", NULL, 260000000), +}; + +static const struct mtk_fixed_factor top_early_divs[] = { + FACTOR(CLK_TOP_CSW_F26M_D2, "csw_f26m_d2", "clk26m", 1, 2), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D4_D16, "mainpll_d4_d16", "mainpll_d4", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6), + FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1", 1, 8), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2", 1, 8), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, 2), + FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, 2), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6), + FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll_d6", 1, 2), + FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + FACTOR(CLK_TOP_MMPLL_D9, "mmpll_d9", "mmpll", 1, 9), + FACTOR(CLK_TOP_APUPLL, "apupll_ck", "apupll", 1, 2), + FACTOR(CLK_TOP_NPUPLL, "npupll_ck", "npupll", 1, 1), + FACTOR(CLK_TOP_TVDPLL, "tvdpll_ck", "tvdpll", 1, 1), + FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2), + FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4), + FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll", 1, 8), + FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll", 1, 16), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_OSC_D2, "osc_d2", "ulposc", 1, 2), + FACTOR(CLK_TOP_OSC_D4, "osc_d4", "ulposc", 1, 4), + FACTOR(CLK_TOP_OSC_D8, "osc_d8", "ulposc", 1, 8), + FACTOR(CLK_TOP_OSC_D10, "osc_d10", "ulposc", 1, 10), + FACTOR(CLK_TOP_OSC_D16, "osc_d16", "ulposc", 1, 16), + FACTOR(CLK_TOP_OSC_D20, "osc_d20", "ulposc", 1, 20), + FACTOR(CLK_TOP_ADSPPLL, "adsppll_ck", "adsppll", 1, 1), + FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13), + FACTOR(CLK_TOP_UNIVPLL_192M_D2, "univpll_192m_d2", "univpll_192m", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32), +}; + +static const char * const axi_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d7_d2", + "mainpll_d4_d2", + "mainpll_d5_d2", + "mainpll_d6_d2", + "osc_d4" +}; + +static const char * const spm_parents[] = { + "clk26m", + "osc_d10", + "mainpll_d7_d4", + "clk32k" +}; + +static const char * const scp_parents[] = { + "clk26m", + "univpll_d5", + "mainpll_d6_d2", + "mainpll_d6", + "univpll_d6", + "mainpll_d4_d2", + "mainpll_d5_d2", + "univpll_d4_d2" +}; + +static const char * const bus_aximem_parents[] = { + "clk26m", + "mainpll_d7_d2", + "mainpll_d4_d2", + "mainpll_d5_d2", + "mainpll_d6" +}; + +static const char * const disp_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d5_d2", + "univpll_d4_d2", + "mmpll_d7", + "univpll_d6", + "mainpll_d4", + "mmpll_d5_d2" +}; + +static const char * const mdp_parents[] = { + "clk26m", + "mainpll_d5_d2", + "mmpll_d6_d2", + "mainpll_d4_d2", + "mmpll_d4_d2", + "mainpll_d6", + "univpll_d6", + "mainpll_d4", + "tvdpll_ck", + "univpll_d4", + "mmpll_d5_d2" +}; + +static const char * const img_parents[] = { + "clk26m", + "univpll_d4", + "tvdpll_ck", + "mainpll_d4", + "univpll_d5", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "mmpll_d4_d2", + "mainpll_d4_d2", + "mmpll_d6_d2", + "mmpll_d5_d2" +}; + +static const char * const ipe_parents[] = { + "clk26m", + "mainpll_d4", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "univpll_d4_d2", + "mainpll_d4_d2", + "mmpll_d6_d2", + "mmpll_d5_d2" +}; + +static const char * const dpe_parents[] = { + "clk26m", + "mainpll_d4", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "univpll_d4_d2", + "univpll_d5_d2", + "mmpll_d6_d2" +}; + +static const char * const cam_parents[] = { + "clk26m", + "mainpll_d4", + "mmpll_d6", + "univpll_d4", + "univpll_d5", + "univpll_d6", + "mmpll_d7", + "univpll_d4_d2", + "mainpll_d4_d2", + "univpll_d6_d2" +}; + +static const char * const ccu_parents[] = { + "clk26m", + "mainpll_d4", + "mmpll_d6", + "mainpll_d6", + "mmpll_d7", + "univpll_d4_d2", + "mmpll_d6_d2", + "mmpll_d5_d2", + "univpll_d5", + "univpll_d6_d2" +}; + +static const char * const dsp7_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d6", + "mmpll_d6", + "univpll_d5", + "mmpll_d5", + "univpll_d4", + "mmpll_d4" +}; + +static const char * const mfg_ref_parents[] = { + "clk26m", + "clk26m", + "univpll_d6", + "mainpll_d5_d2" +}; + +static const char * const mfg_pll_parents[] = { + "mfg_ref_sel", + "mfgpll" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d6_d8", + "univpll_192m_d4", + "univpll_d6_d16", + "csw_f26m_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d6_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d6_d4", + "msdcpll_d4" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d6_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "msdcpll_d2", + "univpll_d4_d4", + "mainpll_d6_d2", + "univpll_d4_d2" +}; + +static const char * const msdc30_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d6_d2", + "mainpll_d7_d2", + "msdcpll_d2" +}; + +static const char * const audio_parents[] = { + "clk26m", + "mainpll_d5_d8", + "mainpll_d7_d8", + "mainpll_d4_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d7_d4" +}; + +static const char * const pwrap_ulposc_parents[] = { + "osc_d10", + "clk26m", + "osc_d4", + "osc_d8", + "osc_d16" +}; + +static const char * const atb_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d5_d2" +}; + +static const char * const dpi_parents[] = { + "clk26m", + "tvdpll_d2", + "tvdpll_d4", + "tvdpll_d8", + "tvdpll_d16" +}; + +static const char * const scam_parents[] = { + "clk26m", + "mainpll_d5_d4" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll_d6_d4", + "osc_d2", + "osc_d4", + "osc_d16" +}; + +static const char * const usb_top_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d6_d4", + "univpll_d5_d2" +}; + +static const char * const ssusb_xhci_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d6_d4", + "univpll_d5_d2" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "mainpll_d4_d8", + "univpll_d5_d4" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d4_d4", + "univpll_d6_d2", + "univpll_d4_d2", + "univpll_d7", + "univpll_d6", + "mmpll_d6", + "univpll_d5" +}; + +static const char * const tl_parents[] = { + "clk26m", + "univpll_192m_d2", + "mainpll_d6_d4" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d4_d4", + "mainpll_d4_d8" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const aes_ufsfde_parents[] = { + "clk26m", + "mainpll_d4", + "mainpll_d4_d2", + "mainpll_d6", + "mainpll_d4_d4", + "univpll_d4_d2", + "univpll_d6" +}; + +static const char * const ufs_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d4_d8", + "univpll_d4_d4", + "mainpll_d6_d2", + "mainpll_d5_d2", + "msdcpll_d2" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck" +}; + +static const char * const adsp_parents[] = { + "clk26m", + "mainpll_d6", + "mainpll_d5_d2", + "univpll_d4_d4", + "univpll_d4", + "univpll_d6", + "ulposc", + "adsppll_ck" +}; + +static const char * const dpmaif_main_parents[] = { + "clk26m", + "univpll_d4_d4", + "mainpll_d6", + "mainpll_d4_d2", + "univpll_d4_d2" +}; + +static const char * const venc_parents[] = { + "clk26m", + "mmpll_d7", + "mainpll_d6", + "univpll_d4_d2", + "mainpll_d4_d2", + "univpll_d6", + "mmpll_d6", + "mainpll_d5_d2", + "mainpll_d6_d2", + "mmpll_d9", + "univpll_d4_d4", + "mainpll_d4", + "univpll_d4", + "univpll_d5", + "univpll_d5_d2", + "mainpll_d5" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "univpll_192m_d2", + "univpll_d5_d4", + "mainpll_d5", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d5_d2", + "mainpll_d4_d2", + "univpll_d4_d2", + "univpll_d7", + "mmpll_d7", + "mmpll_d6", + "univpll_d5", + "mainpll_d4", + "univpll_d4", + "univpll_d6" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll_d7", + "univpll_d6_d2", + "univpll_d4_d2" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll_d4_d8" +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "univpll_d7", + "apll1_ck", + "apll2_ck" +}; + +static const char * const spmi_mst_parents[] = { + "clk26m", + "csw_f26m_d2", + "osc_d8", + "osc_d10", + "osc_d16", + "osc_d20", + "clk32k" +}; + +static const char * const aes_msdcfde_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d6", + "mainpll_d4_d4", + "univpll_d4_d2", + "univpll_d6" +}; + +static const char * const sflash_parents[] = { + "clk26m", + "mainpll_d7_d8", + "univpll_d6_d8", + "univpll_d5_d8" +}; + +static const char * const apll_i2s_m_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +/* + * CRITICAL CLOCK: + * axi_sel is the main bus clock of whole SOC. + * spm_sel is the clock of the always-on co-processor. + * bus_aximem_sel is clock of the bus that access emi. + */ +static const struct mtk_mux top_mtk_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", + axi_parents, 0x010, 0x014, 0x018, 0, 3, 7, 0x004, 0, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel", + spm_parents, 0x010, 0x014, 0x018, 8, 2, 15, 0x004, 1, + CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", + scp_parents, 0x010, 0x014, 0x018, 16, 3, 23, 0x004, 2), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM_SEL, "bus_aximem_sel", + bus_aximem_parents, 0x010, 0x014, 0x018, 24, 3, 31, 0x004, 3, + CLK_IS_CRITICAL), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_SEL, "disp_sel", + disp_parents, 0x020, 0x024, 0x028, 0, 4, 7, 0x004, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MDP_SEL, "mdp_sel", + mdp_parents, 0x020, 0x024, 0x028, 8, 4, 15, 0x004, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG1_SEL, "img1_sel", + img_parents, 0x020, 0x024, 0x028, 16, 4, 23, 0x004, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG2_SEL, "img2_sel", + img_parents, 0x020, 0x024, 0x028, 24, 4, 31, 0x004, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE_SEL, "ipe_sel", + ipe_parents, 0x030, 0x034, 0x038, 0, 4, 7, 0x004, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPE_SEL, "dpe_sel", + dpe_parents, 0x030, 0x034, 0x038, 8, 3, 15, 0x004, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM_SEL, "cam_sel", + cam_parents, 0x030, 0x034, 0x038, 16, 4, 23, 0x004, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CCU_SEL, "ccu_sel", + ccu_parents, 0x030, 0x034, 0x038, 24, 4, 31, 0x004, 11), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP7_SEL, "dsp7_sel", + dsp7_parents, 0x050, 0x054, 0x058, 0, 3, 7, 0x004, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_REF_SEL, "mfg_ref_sel", + mfg_ref_parents, 0x050, 0x054, 0x058, 16, 2, 23, 0x004, 18), + MUX_CLR_SET_UPD(CLK_TOP_MFG_PLL_SEL, "mfg_pll_sel", + mfg_pll_parents, 0x050, 0x054, 0x058, 18, 1, -1, -1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel", + camtg_parents, 0x050, 0x054, 0x058, 24, 3, 31, 0x004, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2_SEL, "camtg2_sel", + camtg_parents, 0x060, 0x064, 0x068, 0, 3, 7, 0x004, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3_SEL, "camtg3_sel", + camtg_parents, 0x060, 0x064, 0x068, 8, 3, 15, 0x004, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4_SEL, "camtg4_sel", + camtg_parents, 0x060, 0x064, 0x068, 16, 3, 23, 0x004, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5_SEL, "camtg5_sel", + camtg_parents, 0x060, 0x064, 0x068, 24, 3, 31, 0x004, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG6_SEL, "camtg6_sel", + camtg_parents, 0x070, 0x074, 0x078, 0, 3, 7, 0x004, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", + uart_parents, 0x070, 0x074, 0x078, 8, 1, 15, 0x004, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", + spi_parents, 0x070, 0x074, 0x078, 16, 2, 23, 0x004, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_H_SEL, "msdc50_0_h_sel", + msdc50_0_h_parents, 0x070, 0x074, 0x078, 24, 2, 31, 0x004, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x004, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_parents, 0x080, 0x084, 0x088, 8, 3, 15, 0x004, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", + msdc30_parents, 0x080, 0x084, 0x088, 16, 3, 23, 0x004, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", + audio_parents, 0x080, 0x084, 0x088, 24, 2, 31, 0x008, 0), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, 0x090, 0x094, 0x098, 0, 2, 7, 0x008, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWRAP_ULPOSC_SEL, "pwrap_ulposc_sel", + pwrap_ulposc_parents, 0x090, 0x094, 0x098, 8, 3, 15, 0x008, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", + atb_parents, 0x090, 0x094, 0x098, 16, 2, 23, 0x008, 3), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI_SEL, "dpi_sel", + dpi_parents, 0x0a0, 0x0a4, 0x0a8, 0, 3, 7, 0x008, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM_SEL, "scam_sel", + scam_parents, 0x0a0, 0x0a4, 0x0a8, 8, 1, 15, 0x008, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel", + disp_pwm_parents, 0x0a0, 0x0a4, 0x0a8, 16, 3, 23, 0x008, 7), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_SEL, "usb_top_sel", + usb_top_parents, 0x0a0, 0x0a4, 0x0a8, 24, 2, 31, 0x008, 8), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_SEL, "ssusb_xhci_sel", + ssusb_xhci_parents, 0x0b0, 0x0b4, 0x0b8, 0, 2, 7, 0x008, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", + i2c_parents, 0x0b0, 0x0b4, 0x0b8, 8, 2, 15, 0x008, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF_SEL, "seninf_sel", + seninf_parents, 0x0b0, 0x0b4, 0x0b8, 16, 3, 23, 0x008, 11), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1_SEL, "seninf1_sel", + seninf_parents, 0x0b0, 0x0b4, 0x0b8, 24, 3, 31, 0x008, 12), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2_SEL, "seninf2_sel", + seninf_parents, 0x0c0, 0x0c4, 0x0c8, 0, 3, 7, 0x008, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF3_SEL, "seninf3_sel", + seninf_parents, 0x0c0, 0x0c4, 0x0c8, 8, 3, 15, 0x008, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_TL_SEL, "tl_sel", + tl_parents, 0x0c0, 0x0c4, 0x0c8, 16, 2, 23, 0x008, 15), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC_SEL, "dxcc_sel", + dxcc_parents, 0x0c0, 0x0c4, 0x0c8, 24, 2, 31, 0x008, 16), + /* CLK_CFG_12 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", + aud_engen1_parents, 0x0d0, 0x0d4, 0x0d8, 0, 2, 7, 0x008, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", + aud_engen2_parents, 0x0d0, 0x0d4, 0x0d8, 8, 2, 15, 0x008, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_UFSFDE_SEL, "aes_ufsfde_sel", + aes_ufsfde_parents, 0x0d0, 0x0d4, 0x0d8, 16, 3, 23, 0x008, 19), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS_SEL, "ufs_sel", + ufs_parents, 0x0d0, 0x0d4, 0x0d8, 24, 3, 31, 0x008, 20), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel", + aud_1_parents, 0x0e0, 0x0e4, 0x0e8, 0, 1, 7, 0x008, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2_SEL, "aud_2_sel", + aud_2_parents, 0x0e0, 0x0e4, 0x0e8, 8, 1, 15, 0x008, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP_SEL, "adsp_sel", + adsp_parents, 0x0e0, 0x0e4, 0x0e8, 16, 3, 23, 0x008, 23), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF_MAIN_SEL, "dpmaif_main_sel", + dpmaif_main_parents, 0x0e0, 0x0e4, 0x0e8, 24, 3, 31, 0x008, 24), + /* CLK_CFG_14 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC_SEL, "venc_sel", + venc_parents, 0x0f0, 0x0f4, 0x0f8, 0, 4, 7, 0x008, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel", + vdec_parents, 0x0f0, 0x0f4, 0x0f8, 8, 4, 15, 0x008, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", + camtm_parents, 0x0f0, 0x0f4, 0x0f8, 16, 2, 23, 0x008, 27), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", + pwm_parents, 0x0f0, 0x0f4, 0x0f8, 24, 1, 31, 0x008, 28), + /* CLK_CFG_15 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H_SEL, "audio_h_sel", + audio_h_parents, 0x100, 0x104, 0x108, 0, 2, 7, 0x008, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_MST_SEL, "spmi_mst_sel", + spmi_mst_parents, 0x100, 0x104, 0x108, 8, 3, 15, 0x008, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE_SEL, "aes_msdcfde_sel", + aes_msdcfde_parents, 0x100, 0x104, 0x108, 24, 3, 31, 0x00c, 1), + /* CLK_CFG_16 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SFLASH_SEL, "sflash_sel", + sflash_parents, 0x110, 0x114, 0x118, 8, 2, 15, 0x00c, 3), +}; + +static struct mtk_composite top_muxes[] = { + /* CLK_AUDDIV_0 */ + MUX(CLK_TOP_APLL_I2S0_M_SEL, "apll_i2s0_m_sel", apll_i2s_m_parents, 0x320, 16, 1), + MUX(CLK_TOP_APLL_I2S1_M_SEL, "apll_i2s1_m_sel", apll_i2s_m_parents, 0x320, 17, 1), + MUX(CLK_TOP_APLL_I2S2_M_SEL, "apll_i2s2_m_sel", apll_i2s_m_parents, 0x320, 18, 1), + MUX(CLK_TOP_APLL_I2S3_M_SEL, "apll_i2s3_m_sel", apll_i2s_m_parents, 0x320, 19, 1), + MUX(CLK_TOP_APLL_I2S4_M_SEL, "apll_i2s4_m_sel", apll_i2s_m_parents, 0x320, 20, 1), + MUX(CLK_TOP_APLL_I2S5_M_SEL, "apll_i2s5_m_sel", apll_i2s_m_parents, 0x320, 21, 1), + MUX(CLK_TOP_APLL_I2S6_M_SEL, "apll_i2s6_m_sel", apll_i2s_m_parents, 0x320, 22, 1), + MUX(CLK_TOP_APLL_I2S7_M_SEL, "apll_i2s7_m_sel", apll_i2s_m_parents, 0x320, 23, 1), + MUX(CLK_TOP_APLL_I2S8_M_SEL, "apll_i2s8_m_sel", apll_i2s_m_parents, 0x320, 24, 1), + MUX(CLK_TOP_APLL_I2S9_M_SEL, "apll_i2s9_m_sel", apll_i2s_m_parents, 0x320, 25, 1), +}; + +static const struct mtk_composite top_adj_divs[] = { + DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll_i2s0_m_sel", 0x320, 0, 0x328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll_i2s1_m_sel", 0x320, 1, 0x328, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll_i2s2_m_sel", 0x320, 2, 0x328, 8, 16), + DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll_i2s3_m_sel", 0x320, 3, 0x328, 8, 24), + DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll_i2s4_m_sel", 0x320, 4, 0x334, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIVB, "apll12_divb", "apll12_div4", 0x320, 5, 0x334, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll_i2s5_m_sel", 0x320, 6, 0x334, 8, 16), + DIV_GATE(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll_i2s6_m_sel", 0x320, 7, 0x334, 8, 24), + DIV_GATE(CLK_TOP_APLL12_DIV7, "apll12_div7", "apll_i2s7_m_sel", 0x320, 8, 0x338, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIV8, "apll12_div8", "apll_i2s8_m_sel", 0x320, 9, 0x338, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV9, "apll12_div9", "apll_i2s9_m_sel", 0x320, 10, 0x338, 8, 16), +}; + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x14, + .clr_ofs = 0x14, + .sta_ofs = 0x14, +}; + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &apmixed_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_MIPID26M, "mipid26m", "clk26m", 16), +}; + +static const struct mtk_gate_regs infra0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +static const struct mtk_gate_regs infra4_cg_regs = { + .set_ofs = 0xd0, + .clr_ofs = 0xd4, + .sta_ofs = 0xd8, +}; + +static const struct mtk_gate_regs infra5_cg_regs = { + .set_ofs = 0xe0, + .clr_ofs = 0xe4, + .sta_ofs = 0xe8, +}; + +#define GATE_INFRA0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA1(_id, _name, _parent, _shift) \ + GATE_INFRA1_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA3(_id, _name, _parent, _shift) \ + GATE_INFRA3_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA4(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &infra4_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_INFRA5_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra5_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA5(_id, _name, _parent, _shift) \ + GATE_INFRA5_FLAGS(_id, _name, _parent, _shift, 0) + +/* + * CRITICAL CLOCK: + * infra_133m and infra_66m are main peripheral bus clocks of SOC. + * infra_device_apc and infra_device_apc_sync are for device access permission control module. + */ +static const struct mtk_gate infra_clks[] = { + /* INFRA0 */ + GATE_INFRA0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "pwrap_ulposc_sel", 0), + GATE_INFRA0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pwrap_ulposc_sel", 1), + GATE_INFRA0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pwrap_ulposc_sel", 2), + GATE_INFRA0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pwrap_ulposc_sel", 3), + GATE_INFRA0(CLK_INFRA_SCPSYS, "infra_scpsys", "scp_sel", 4), + GATE_INFRA0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5), + GATE_INFRA0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6), + GATE_INFRA0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 8), + GATE_INFRA0(CLK_INFRA_GCE2, "infra_gce2", "axi_sel", 9), + GATE_INFRA0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10), + GATE_INFRA0(CLK_INFRA_I2C0, "infra_i2c0", "i2c_sel", 11), + GATE_INFRA0(CLK_INFRA_AP_DMA_PSEUDO, "infra_ap_dma_pseudo", "axi_sel", 12), + GATE_INFRA0(CLK_INFRA_I2C2, "infra_i2c2", "i2c_sel", 13), + GATE_INFRA0(CLK_INFRA_I2C3, "infra_i2c3", "i2c_sel", 14), + GATE_INFRA0(CLK_INFRA_PWM_H, "infra_pwm_h", "axi_sel", 15), + GATE_INFRA0(CLK_INFRA_PWM1, "infra_pwm1", "pwm_sel", 16), + GATE_INFRA0(CLK_INFRA_PWM2, "infra_pwm2", "pwm_sel", 17), + GATE_INFRA0(CLK_INFRA_PWM3, "infra_pwm3", "pwm_sel", 18), + GATE_INFRA0(CLK_INFRA_PWM4, "infra_pwm4", "pwm_sel", 19), + GATE_INFRA0(CLK_INFRA_PWM, "infra_pwm", "pwm_sel", 21), + GATE_INFRA0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22), + GATE_INFRA0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23), + GATE_INFRA0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24), + GATE_INFRA0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25), + GATE_INFRA0(CLK_INFRA_GCE_26M, "infra_gce_26m", "axi_sel", 27), + GATE_INFRA0(CLK_INFRA_CQ_DMA_FPC, "infra_cq_dma_fpc", "axi_sel", 28), + GATE_INFRA0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31), + /* INFRA1 */ + GATE_INFRA1(CLK_INFRA_SPI0, "infra_spi0", "spi_sel", 1), + GATE_INFRA1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_h_sel", 2), + GATE_INFRA1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc50_0_h_sel", 4), + GATE_INFRA1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc50_0_h_sel", 5), + GATE_INFRA1(CLK_INFRA_MSDC0_SRC, "infra_msdc0_src", "msdc50_0_sel", 6), + GATE_INFRA1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8), + GATE_INFRA1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9), + GATE_INFRA1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10), + GATE_INFRA1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11), + GATE_INFRA1(CLK_INFRA_CCIF1_AP, "infra_ccif1_ap", "axi_sel", 12), + GATE_INFRA1(CLK_INFRA_CCIF1_MD, "infra_ccif1_md", "axi_sel", 13), + GATE_INFRA1(CLK_INFRA_AUXADC_MD, "infra_auxadc_md", "clk26m", 14), + GATE_INFRA1(CLK_INFRA_PCIE_TL_26M, "infra_pcie_tl_26m", "axi_sel", 15), + GATE_INFRA1(CLK_INFRA_MSDC1_SRC, "infra_msdc1_src", "msdc30_1_sel", 16), + GATE_INFRA1(CLK_INFRA_MSDC2_SRC, "infra_msdc2_src", "msdc30_2_sel", 17), + GATE_INFRA1(CLK_INFRA_PCIE_TL_96M, "infra_pcie_tl_96m", "tl_sel", 18), + GATE_INFRA1(CLK_INFRA_PCIE_PL_P_250M, "infra_pcie_pl_p_250m", "axi_sel", 19), + GATE_INFRA1_FLAGS(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20, CLK_IS_CRITICAL), + GATE_INFRA1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23), + GATE_INFRA1(CLK_INFRA_DEBUGSYS, "infra_debugsys", "axi_sel", 24), + GATE_INFRA1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25), + GATE_INFRA1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26), + GATE_INFRA1(CLK_INFRA_DXCC_SEC_CORE, "infra_dxcc_sec_core", "dxcc_sel", 27), + GATE_INFRA1(CLK_INFRA_DXCC_AO, "infra_dxcc_ao", "dxcc_sel", 28), + GATE_INFRA1(CLK_INFRA_DBG_TRACE, "infra_dbg_trace", "axi_sel", 29), + GATE_INFRA1(CLK_INFRA_DEVMPU_B, "infra_devmpu_b", "axi_sel", 30), + GATE_INFRA1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31), + /* INFRA2 */ + GATE_INFRA2(CLK_INFRA_IRTX, "infra_irtx", "clk26m", 0), + GATE_INFRA2(CLK_INFRA_SSUSB, "infra_ssusb", "usb_top_sel", 1), + GATE_INFRA2(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "axi_sel", 2), + GATE_INFRA2(CLK_INFRA_CLDMA_B, "infra_cldma_b", "axi_sel", 3), + GATE_INFRA2(CLK_INFRA_AUDIO_26M_B, "infra_audio_26m_b", "clk26m", 4), + GATE_INFRA2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share", "clk26m", 5), + GATE_INFRA2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 6), + GATE_INFRA2(CLK_INFRA_I2C4, "infra_i2c4", "i2c_sel", 7), + GATE_INFRA2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 9), + GATE_INFRA2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 10), + GATE_INFRA2(CLK_INFRA_UNIPRO_SYS, "infra_unipro_sys", "ufs_sel", 11), + GATE_INFRA2(CLK_INFRA_UNIPRO_TICK, "infra_unipro_tick", "clk26m", 12), + GATE_INFRA2(CLK_INFRA_UFS_MP_SAP_B, "infra_ufs_mp_sap_b", "clk26m", 13), + GATE_INFRA2(CLK_INFRA_MD32_B, "infra_md32_b", "axi_sel", 14), + GATE_INFRA2(CLK_INFRA_UNIPRO_MBIST, "infra_unipro_mbist", "axi_sel", 16), + GATE_INFRA2(CLK_INFRA_I2C5, "infra_i2c5", "i2c_sel", 18), + GATE_INFRA2(CLK_INFRA_I2C5_ARBITER, "infra_i2c5_arbiter", "i2c_sel", 19), + GATE_INFRA2(CLK_INFRA_I2C5_IMM, "infra_i2c5_imm", "i2c_sel", 20), + GATE_INFRA2(CLK_INFRA_I2C1_ARBITER, "infra_i2c1_arbiter", "i2c_sel", 21), + GATE_INFRA2(CLK_INFRA_I2C1_IMM, "infra_i2c1_imm", "i2c_sel", 22), + GATE_INFRA2(CLK_INFRA_I2C2_ARBITER, "infra_i2c2_arbiter", "i2c_sel", 23), + GATE_INFRA2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "i2c_sel", 24), + GATE_INFRA2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 25), + GATE_INFRA2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 26), + GATE_INFRA2(CLK_INFRA_CQ_DMA, "infra_cq_dma", "axi_sel", 27), + GATE_INFRA2(CLK_INFRA_UFS, "infra_ufs", "ufs_sel", 28), + GATE_INFRA2(CLK_INFRA_AES_UFSFDE, "infra_aes_ufsfde", "aes_ufsfde_sel", 29), + GATE_INFRA2(CLK_INFRA_UFS_TICK, "infra_ufs_tick", "ufs_sel", 30), + GATE_INFRA2(CLK_INFRA_SSUSB_XHCI, "infra_ssusb_xhci", "ssusb_xhci_sel", 31), + /* INFRA3 */ + GATE_INFRA3(CLK_INFRA_MSDC0_SELF, "infra_msdc0_self", "msdc50_0_sel", 0), + GATE_INFRA3(CLK_INFRA_MSDC1_SELF, "infra_msdc1_self", "msdc50_0_sel", 1), + GATE_INFRA3(CLK_INFRA_MSDC2_SELF, "infra_msdc2_self", "msdc50_0_sel", 2), + GATE_INFRA3(CLK_INFRA_UFS_AXI, "infra_ufs_axi", "axi_sel", 5), + GATE_INFRA3(CLK_INFRA_I2C6, "infra_i2c6", "i2c_sel", 6), + GATE_INFRA3(CLK_INFRA_AP_MSDC0, "infra_ap_msdc0", "msdc50_0_sel", 7), + GATE_INFRA3(CLK_INFRA_MD_MSDC0, "infra_md_msdc0", "msdc50_0_sel", 8), + GATE_INFRA3(CLK_INFRA_CCIF5_AP, "infra_ccif5_ap", "axi_sel", 9), + GATE_INFRA3(CLK_INFRA_CCIF5_MD, "infra_ccif5_md", "axi_sel", 10), + GATE_INFRA3(CLK_INFRA_PCIE_TOP_H_133M, "infra_pcie_top_h_133m", "axi_sel", 11), + GATE_INFRA3(CLK_INFRA_FLASHIF_TOP_H_133M, "infra_flashif_top_h_133m", "axi_sel", 14), + GATE_INFRA3(CLK_INFRA_PCIE_PERI_26M, "infra_pcie_peri_26m", "axi_sel", 15), + GATE_INFRA3(CLK_INFRA_CCIF2_AP, "infra_ccif2_ap", "axi_sel", 16), + GATE_INFRA3(CLK_INFRA_CCIF2_MD, "infra_ccif2_md", "axi_sel", 17), + GATE_INFRA3(CLK_INFRA_CCIF3_AP, "infra_ccif3_ap", "axi_sel", 18), + GATE_INFRA3(CLK_INFRA_CCIF3_MD, "infra_ccif3_md", "axi_sel", 19), + GATE_INFRA3(CLK_INFRA_SEJ_F13M, "infra_sej_f13m", "clk26m", 20), + GATE_INFRA3(CLK_INFRA_AES, "infra_aes", "axi_sel", 21), + GATE_INFRA3(CLK_INFRA_I2C7, "infra_i2c7", "i2c_sel", 22), + GATE_INFRA3(CLK_INFRA_I2C8, "infra_i2c8", "i2c_sel", 23), + GATE_INFRA3(CLK_INFRA_FBIST2FPC, "infra_fbist2fpc", "msdc50_0_sel", 24), + GATE_INFRA3_FLAGS(CLK_INFRA_DEVICE_APC_SYNC, "infra_device_apc_sync", "axi_sel", 25, + CLK_IS_CRITICAL), + GATE_INFRA3(CLK_INFRA_DPMAIF_MAIN, "infra_dpmaif_main", "dpmaif_main_sel", 26), + GATE_INFRA3(CLK_INFRA_PCIE_TL_32K, "infra_pcie_tl_32k", "axi_sel", 27), + GATE_INFRA3(CLK_INFRA_CCIF4_AP, "infra_ccif4_ap", "axi_sel", 28), + GATE_INFRA3(CLK_INFRA_CCIF4_MD, "infra_ccif4_md", "axi_sel", 29), + GATE_INFRA3(CLK_INFRA_SPI6, "infra_spi6", "spi_sel", 30), + GATE_INFRA3(CLK_INFRA_SPI7, "infra_spi7", "spi_sel", 31), + /* INFRA4 */ + GATE_INFRA4(CLK_INFRA_AP_DMA, "infra_ap_dma", "infra_ap_dma_pseudo", 31), + /* INFRA5 */ + GATE_INFRA5_FLAGS(CLK_INFRA_133M, "infra_133m", "axi_sel", 0, CLK_IS_CRITICAL), + GATE_INFRA5_FLAGS(CLK_INFRA_66M, "infra_66m", "axi_sel", 1, CLK_IS_CRITICAL), + GATE_INFRA5(CLK_INFRA_66M_PERI_BUS, "infra_66m_peri_bus", "axi_sel", 2), + GATE_INFRA5(CLK_INFRA_FREE_DCM_133M, "infra_free_dcm_133m", "axi_sel", 3), + GATE_INFRA5(CLK_INFRA_FREE_DCM_66M, "infra_free_dcm_66m", "axi_sel", 4), + GATE_INFRA5(CLK_INFRA_PERI_BUS_DCM_133M, "infra_peri_bus_dcm_133m", "axi_sel", 5), + GATE_INFRA5(CLK_INFRA_PERI_BUS_DCM_66M, "infra_peri_bus_dcm_66m", "axi_sel", 6), + GATE_INFRA5(CLK_INFRA_FLASHIF_PERI_26M, "infra_flashif_peri_26m", "axi_sel", 30), + GATE_INFRA5(CLK_INFRA_FLASHIF_SFLASH, "infra_flashif_fsflash", "axi_sel", 31), +}; + +static const struct mtk_gate_regs peri_cg_regs = { + .set_ofs = 0x20c, + .clr_ofs = 0x20c, + .sta_ofs = 0x20c, +}; + +#define GATE_PERI(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate peri_clks[] = { + GATE_PERI(CLK_PERI_PERIAXI, "peri_periaxi", "axi_sel", 31), +}; + +static const struct mtk_gate_regs top_cg_regs = { + .set_ofs = 0x150, + .clr_ofs = 0x150, + .sta_ofs = 0x150, +}; + +#define GATE_TOP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate top_clks[] = { + GATE_TOP(CLK_TOP_SSUSB_TOP_REF, "ssusb_top_ref", "clk26m", 24), + GATE_TOP(CLK_TOP_SSUSB_PHY_REF, "ssusb_phy_ref", "clk26m", 25), +}; + +static u16 infra_ao_rst_ofs[] = { + INFRA_RST0_SET_OFFSET, + INFRA_RST1_SET_OFFSET, + INFRA_RST2_SET_OFFSET, + INFRA_RST3_SET_OFFSET, + INFRA_RST4_SET_OFFSET, +}; + +static u16 infra_ao_idx_map[] = { + [MT8192_INFRA_RST0_THERM_CTRL_SWRST] = 0 * RST_NR_PER_BANK + 0, + [MT8192_INFRA_RST2_PEXTP_PHY_SWRST] = 2 * RST_NR_PER_BANK + 15, + [MT8192_INFRA_RST3_THERM_CTRL_PTP_SWRST] = 3 * RST_NR_PER_BANK + 5, + [MT8192_INFRA_RST4_PCIE_TOP_SWRST] = 4 * RST_NR_PER_BANK + 1, + [MT8192_INFRA_RST4_THERM_CTRL_MCU_SWRST] = 4 * RST_NR_PER_BANK + 12, +}; + +static const struct mtk_clk_rst_desc clk_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_ao_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs), + .rst_idx_map = infra_ao_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map), +}; + +#define MT8192_PLL_FMAX (3800UL * MHZ) +#define MT8192_PLL_FMIN (1500UL * MHZ) +#define MT8192_INTEGER_BITS 8 + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift, _pcw_chg_reg, \ + _en_reg, _pll_en_bit) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8192_PLL_FMAX, \ + .fmin = MT8192_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = MT8192_INTEGER_BITS, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .en_reg = _en_reg, \ + .pll_en_bit = _pll_en_bit, \ + } + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift) \ + PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift, 0, 0, 0) + +static const struct mtk_pll_data plls[] = { + PLL_B(CLK_APMIXED_MAINPLL, "mainpll", 0x0340, 0x034c, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0344, 24, 0, 0, 0, 0x0344, 0), + PLL_B(CLK_APMIXED_UNIVPLL, "univpll", 0x0308, 0x0314, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x030c, 24, 0, 0, 0, 0x030c, 0), + PLL(CLK_APMIXED_USBPLL, "usbpll", 0x03c4, 0x03cc, 0x00000000, + 0, 0, 22, 0x03c4, 24, 0, 0, 0, 0x03c4, 0, 0x03c4, 0x03cc, 2), + PLL_B(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0350, 0x035c, 0x00000000, + 0, 0, 22, 0x0354, 24, 0, 0, 0, 0x0354, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0360, 0x036c, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0364, 24, 0, 0, 0, 0x0364, 0), + PLL_B(CLK_APMIXED_ADSPPLL, "adsppll", 0x0370, 0x037c, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x0374, 24, 0, 0, 0, 0x0374, 0), + PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0268, 0x0274, 0x00000000, + 0, 0, 22, 0x026c, 24, 0, 0, 0, 0x026c, 0), + PLL_B(CLK_APMIXED_TVDPLL, "tvdpll", 0x0380, 0x038c, 0x00000000, + 0, 0, 22, 0x0384, 24, 0, 0, 0, 0x0384, 0), + PLL_B(CLK_APMIXED_APLL1, "apll1", 0x0318, 0x0328, 0x00000000, + 0, 0, 32, 0x031c, 24, 0x0040, 0x000c, 0, 0x0320, 0), + PLL_B(CLK_APMIXED_APLL2, "apll2", 0x032c, 0x033c, 0x00000000, + 0, 0, 32, 0x0330, 24, 0, 0, 0, 0x0334, 0), +}; + +static struct clk_hw_onecell_data *top_clk_data; + +static void clk_mt8192_top_init_early(struct device_node *node) +{ + int i; + + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!top_clk_data) + return; + + for (i = 0; i < CLK_TOP_NR_CLK; i++) + top_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER); + + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data); + + of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); +} + +CLK_OF_DECLARE_DRIVER(mt8192_topckgen, "mediatek,mt8192-topckgen", + clk_mt8192_top_init_early); + +/* Register mux notifier for MFG mux */ +static int clk_mt8192_reg_mfg_mux_notifier(struct device *dev, struct clk *clk) +{ + struct mtk_mux_nb *mfg_mux_nb; + int i; + + mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL); + if (!mfg_mux_nb) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(top_mtk_muxes); i++) + if (top_mtk_muxes[i].id == CLK_TOP_MFG_PLL_SEL) + break; + if (i == ARRAY_SIZE(top_mtk_muxes)) + return -EINVAL; + + mfg_mux_nb->ops = top_mtk_muxes[i].ops; + mfg_mux_nb->bypass_index = 0; /* Bypass to 26M crystal */ + + return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb); +} + +static int clk_mt8192_top_probe(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + int r; + void __iomem *base; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); + mtk_clk_register_factors(top_early_divs, ARRAY_SIZE(top_early_divs), top_clk_data); + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, &mt8192_clk_lock, + top_clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, &mt8192_clk_lock, + top_clk_data); + mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, &mt8192_clk_lock, + top_clk_data); + r = mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); + if (r) + return r; + + r = clk_mt8192_reg_mfg_mux_notifier(&pdev->dev, + top_clk_data->hws[CLK_TOP_MFG_PLL_SEL]->clk); + if (r) + return r; + + + return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, + top_clk_data); +} + +static int clk_mt8192_infra_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks), clk_data); + if (r) + goto free_clk_data; + + r = mtk_register_reset_controller_with_dev(&pdev->dev, &clk_rst_desc); + if (r) + goto free_clk_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto free_clk_data; + + return r; + +free_clk_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8192_peri_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks), clk_data); + if (r) + goto free_clk_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto free_clk_data; + + return r; + +free_clk_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8192_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + if (r) + goto free_clk_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto free_clk_data; + + return r; + +free_clk_data: + mtk_free_clk_data(clk_data); + return r; +} + +static const struct of_device_id of_match_clk_mt8192[] = { + { + .compatible = "mediatek,mt8192-apmixedsys", + .data = clk_mt8192_apmixed_probe, + }, { + .compatible = "mediatek,mt8192-topckgen", + .data = clk_mt8192_top_probe, + }, { + .compatible = "mediatek,mt8192-infracfg", + .data = clk_mt8192_infra_probe, + }, { + .compatible = "mediatek,mt8192-pericfg", + .data = clk_mt8192_peri_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt8192_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *pdev); + int r; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + r = clk_probe(pdev); + if (r) + dev_err(&pdev->dev, "could not register clock provider: %s: %d\n", pdev->name, r); + + return r; +} + +static struct platform_driver clk_mt8192_drv = { + .probe = clk_mt8192_probe, + .driver = { + .name = "clk-mt8192", + .of_match_table = of_match_clk_mt8192, + }, +}; + +static int __init clk_mt8192_init(void) +{ + return platform_driver_register(&clk_mt8192_drv); +} + +arch_initcall(clk_mt8192_init); diff --git a/drivers/clk/mediatek/clk-mt8195-apmixedsys.c b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c new file mode 100644 index 000000000..0dfed6ec4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-apmixedsys.c @@ -0,0 +1,169 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs apmixed_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0x8, + .sta_ofs = 0x8, +}; + +#define GATE_APMIXED(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &apmixed_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate apmixed_clks[] = { + GATE_APMIXED(CLK_APMIXED_PLL_SSUSB26M, "pll_ssusb26m", "clk26m", 1), +}; + +#define MT8195_PLL_FMAX (3800UL * MHZ) +#define MT8195_PLL_FMIN (1500UL * MHZ) +#define MT8195_INTEGER_BITS 8 + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _rst_bar_mask, _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift, _pcw_chg_reg, \ + _en_reg, _pll_en_bit) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8195_PLL_FMAX, \ + .fmin = MT8195_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = MT8195_INTEGER_BITS, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .en_reg = _en_reg, \ + .pll_en_bit = _pll_en_bit, \ + } + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_NNAPLL, "nnapll", 0x0390, 0x03a0, 0, + 0, 0, 22, 0x0398, 24, 0, 0, 0, 0x0398, 0, 0x0398, 0, 9), + PLL(CLK_APMIXED_RESPLL, "respll", 0x0190, 0x0320, 0, + 0, 0, 22, 0x0198, 24, 0, 0, 0, 0x0198, 0, 0x0198, 0, 9), + PLL(CLK_APMIXED_ETHPLL, "ethpll", 0x0360, 0x0370, 0, + 0, 0, 22, 0x0368, 24, 0, 0, 0, 0x0368, 0, 0x0368, 0, 9), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0710, 0x0720, 0, + 0, 0, 22, 0x0718, 24, 0, 0, 0, 0x0718, 0, 0x0718, 0, 9), + PLL(CLK_APMIXED_TVDPLL1, "tvdpll1", 0x00a0, 0x00b0, 0, + 0, 0, 22, 0x00a8, 24, 0, 0, 0, 0x00a8, 0, 0x00a8, 0, 9), + PLL(CLK_APMIXED_TVDPLL2, "tvdpll2", 0x00c0, 0x00d0, 0, + 0, 0, 22, 0x00c8, 24, 0, 0, 0, 0x00c8, 0, 0x00c8, 0, 9), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x00e0, 0x00f0, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x00e8, 24, 0, 0, 0, 0x00e8, 0, 0x00e8, 0, 9), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x01d0, 0x01e0, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x01d8, 24, 0, 0, 0, 0x01d8, 0, 0x01d8, 0, 9), + PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x0890, 0x08a0, 0, + 0, 0, 22, 0x0898, 24, 0, 0, 0, 0x0898, 0, 0x0898, 0, 9), + PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0100, 0x0110, 0, + 0, 0, 22, 0x0108, 24, 0, 0, 0, 0x0108, 0, 0x0108, 0, 9), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x01f0, 0x0700, 0xff000000, + HAVE_RST_BAR, BIT(23), 22, 0x01f8, 24, 0, 0, 0, 0x01f8, 0, 0x01f8, 0, 9), + PLL(CLK_APMIXED_HDMIPLL1, "hdmipll1", 0x08c0, 0x08d0, 0, + 0, 0, 22, 0x08c8, 24, 0, 0, 0, 0x08c8, 0, 0x08c8, 0, 9), + PLL(CLK_APMIXED_HDMIPLL2, "hdmipll2", 0x0870, 0x0880, 0, + 0, 0, 22, 0x0878, 24, 0, 0, 0, 0x0878, 0, 0x0878, 0, 9), + PLL(CLK_APMIXED_HDMIRX_APLL, "hdmirx_apll", 0x08e0, 0x0dd4, 0, + 0, 0, 32, 0x08e8, 24, 0, 0, 0, 0x08ec, 0, 0x08e8, 0, 9), + PLL(CLK_APMIXED_USB1PLL, "usb1pll", 0x01a0, 0x01b0, 0, + 0, 0, 22, 0x01a8, 24, 0, 0, 0, 0x01a8, 0, 0x01a8, 0, 9), + PLL(CLK_APMIXED_ADSPPLL, "adsppll", 0x07e0, 0x07f0, 0, + 0, 0, 22, 0x07e8, 24, 0, 0, 0, 0x07e8, 0, 0x07e8, 0, 9), + PLL(CLK_APMIXED_APLL1, "apll1", 0x07c0, 0x0dc0, 0, + 0, 0, 32, 0x07c8, 24, 0x0470, 0x0000, 12, 0x07cc, 0, 0x07c8, 0, 9), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0780, 0x0dc4, 0, + 0, 0, 32, 0x0788, 24, 0x0474, 0x0000, 13, 0x078c, 0, 0x0788, 0, 9), + PLL(CLK_APMIXED_APLL3, "apll3", 0x0760, 0x0dc8, 0, + 0, 0, 32, 0x0768, 24, 0x0478, 0x0000, 14, 0x076c, 0, 0x0768, 0, 9), + PLL(CLK_APMIXED_APLL4, "apll4", 0x0740, 0x0dcc, 0, + 0, 0, 32, 0x0748, 24, 0x047C, 0x0000, 15, 0x074c, 0, 0x0748, 0, 9), + PLL(CLK_APMIXED_APLL5, "apll5", 0x07a0, 0x0dd0, 0x100000, + 0, 0, 32, 0x07a8, 24, 0x0480, 0x0000, 16, 0x07ac, 0, 0x07a8, 0, 9), + PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0340, 0x0350, 0, + 0, 0, 22, 0x0348, 24, 0, 0, 0, 0x0348, 0, 0x0348, 0, 9), + PLL(CLK_APMIXED_DGIPLL, "dgipll", 0x0150, 0x0160, 0, + 0, 0, 22, 0x0158, 24, 0, 0, 0, 0x0158, 0, 0x0158, 0, 9), +}; + +static const struct of_device_id of_match_clk_mt8195_apmixed[] = { + { .compatible = "mediatek,mt8195-apmixedsys", }, + {} +}; + +static int clk_mt8195_apmixed_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (r) + goto free_apmixed_data; + + r = mtk_clk_register_gates(node, apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + if (r) + goto unregister_plls; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); +free_apmixed_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8195_apmixed_remove(struct platform_device *pdev) +{ + struct device_node *node = pdev->dev.of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(apmixed_clks, ARRAY_SIZE(apmixed_clks), clk_data); + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8195_apmixed_drv = { + .probe = clk_mt8195_apmixed_probe, + .remove = clk_mt8195_apmixed_remove, + .driver = { + .name = "clk-mt8195-apmixed", + .of_match_table = of_match_clk_mt8195_apmixed, + }, +}; +builtin_platform_driver(clk_mt8195_apmixed_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-apusys_pll.c b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c new file mode 100644 index 000000000..0b52f6a00 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-apusys_pll.c @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#define MT8195_PLL_FMAX (3800UL * MHZ) +#define MT8195_PLL_FMIN (1500UL * MHZ) +#define MT8195_INTEGER_BITS (8) +#define MT8195_PCW_BITS (22) +#define MT8195_POSDIV_SHIFT (24) +#define MT8195_PLL_EN_BIT (0) +#define MT8195_PCW_SHIFT (0) + +/* + * The "en_reg" and "pcw_chg_reg" fields are standard offset register compared + * with "reg" field, so set zero to imply it. + * No tuner control in apu pll, so set "tuner_XXX" as zero to imply it. + * No rst or post divider enable in apu pll, so set "rst_bar_mask" and "en_mask" + * as zero to imply it. + */ +#define PLL(_id, _name, _reg, _pwr_reg, _pd_reg, _pcw_reg) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = 0, \ + .flags = 0, \ + .rst_bar_mask = 0, \ + .fmax = MT8195_PLL_FMAX, \ + .fmin = MT8195_PLL_FMIN, \ + .pcwbits = MT8195_PCW_BITS, \ + .pcwibits = MT8195_INTEGER_BITS, \ + .pd_reg = _pd_reg, \ + .pd_shift = MT8195_POSDIV_SHIFT, \ + .tuner_reg = 0, \ + .tuner_en_reg = 0, \ + .tuner_en_bit = 0, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = MT8195_PCW_SHIFT, \ + .pcw_chg_reg = 0, \ + .en_reg = 0, \ + .pll_en_bit = MT8195_PLL_EN_BIT, \ + } + +static const struct mtk_pll_data apusys_plls[] = { + PLL(CLK_APUSYS_PLL_APUPLL, "apusys_pll_apupll", 0x008, 0x014, 0x00c, 0x00c), + PLL(CLK_APUSYS_PLL_NPUPLL, "apusys_pll_npupll", 0x018, 0x024, 0x01c, 0x01c), + PLL(CLK_APUSYS_PLL_APUPLL1, "apusys_pll_apupll1", 0x028, 0x034, 0x02c, 0x02c), + PLL(CLK_APUSYS_PLL_APUPLL2, "apusys_pll_apupll2", 0x038, 0x044, 0x03c, 0x03c), +}; + +static int clk_mt8195_apusys_pll_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + clk_data = mtk_alloc_clk_data(CLK_APUSYS_PLL_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_plls(node, apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); + if (r) + goto free_apusys_pll_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_plls; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_plls: + mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); +free_apusys_pll_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8195_apusys_pll_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_plls(apusys_plls, ARRAY_SIZE(apusys_plls), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static const struct of_device_id of_match_clk_mt8195_apusys_pll[] = { + { .compatible = "mediatek,mt8195-apusys_pll", }, + {} +}; + +static struct platform_driver clk_mt8195_apusys_pll_drv = { + .probe = clk_mt8195_apusys_pll_probe, + .remove = clk_mt8195_apusys_pll_remove, + .driver = { + .name = "clk-mt8195-apusys_pll", + .of_match_table = of_match_clk_mt8195_apusys_pll, + }, +}; +builtin_platform_driver(clk_mt8195_apusys_pll_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-cam.c b/drivers/clk/mediatek/clk-mt8195-cam.c new file mode 100644 index 000000000..e4d00fe6e --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-cam.c @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB13, "cam_larb13", "top_cam", 0), + GATE_CAM(CLK_CAM_LARB14, "cam_larb14", "top_cam", 1), + GATE_CAM(CLK_CAM_MAIN_CAM, "cam_main_cam", "top_cam", 3), + GATE_CAM(CLK_CAM_MAIN_CAMTG, "cam_main_camtg", "top_cam", 4), + GATE_CAM(CLK_CAM_SENINF, "cam_seninf", "top_cam", 5), + GATE_CAM(CLK_CAM_GCAMSVA, "cam_gcamsva", "top_cam", 6), + GATE_CAM(CLK_CAM_GCAMSVB, "cam_gcamsvb", "top_cam", 7), + GATE_CAM(CLK_CAM_GCAMSVC, "cam_gcamsvc", "top_cam", 8), + GATE_CAM(CLK_CAM_SCAMSA, "cam_scamsa", "top_cam", 9), + GATE_CAM(CLK_CAM_SCAMSB, "cam_scamsb", "top_cam", 10), + GATE_CAM(CLK_CAM_CAMSV_TOP, "cam_camsv_top", "top_cam", 11), + GATE_CAM(CLK_CAM_CAMSV_CQ, "cam_camsv_cq", "top_cam", 12), + GATE_CAM(CLK_CAM_ADL, "cam_adl", "top_cam", 16), + GATE_CAM(CLK_CAM_ASG, "cam_asg", "top_cam", 17), + GATE_CAM(CLK_CAM_PDA, "cam_pda", "top_cam", 18), + GATE_CAM(CLK_CAM_FAKE_ENG, "cam_fake_eng", "top_cam", 19), + GATE_CAM(CLK_CAM_MAIN_MRAW0, "cam_main_mraw0", "top_cam", 20), + GATE_CAM(CLK_CAM_MAIN_MRAW1, "cam_main_mraw1", "top_cam", 21), + GATE_CAM(CLK_CAM_MAIN_MRAW2, "cam_main_mraw2", "top_cam", 22), + GATE_CAM(CLK_CAM_MAIN_MRAW3, "cam_main_mraw3", "top_cam", 23), + GATE_CAM(CLK_CAM_CAM2MM0_GALS, "cam_cam2mm0_gals", "top_cam", 24), + GATE_CAM(CLK_CAM_CAM2MM1_GALS, "cam_cam2mm1_gals", "top_cam", 25), + GATE_CAM(CLK_CAM_CAM2SYS_GALS, "cam_cam2sys_gals", "top_cam", 26), +}; + +static const struct mtk_gate cam_mraw_clks[] = { + GATE_CAM(CLK_CAM_MRAW_LARBX, "cam_mraw_larbx", "top_cam", 0), + GATE_CAM(CLK_CAM_MRAW_CAMTG, "cam_mraw_camtg", "top_cam", 2), + GATE_CAM(CLK_CAM_MRAW_MRAW0, "cam_mraw_mraw0", "top_cam", 3), + GATE_CAM(CLK_CAM_MRAW_MRAW1, "cam_mraw_mraw1", "top_cam", 4), + GATE_CAM(CLK_CAM_MRAW_MRAW2, "cam_mraw_mraw2", "top_cam", 5), + GATE_CAM(CLK_CAM_MRAW_MRAW3, "cam_mraw_mraw3", "top_cam", 6), +}; + +static const struct mtk_gate cam_rawa_clks[] = { + GATE_CAM(CLK_CAM_RAWA_LARBX, "cam_rawa_larbx", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWA_CAM, "cam_rawa_cam", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWA_CAMTG, "cam_rawa_camtg", "top_cam", 2), +}; + +static const struct mtk_gate cam_rawb_clks[] = { + GATE_CAM(CLK_CAM_RAWB_LARBX, "cam_rawb_larbx", "top_cam", 0), + GATE_CAM(CLK_CAM_RAWB_CAM, "cam_rawb_cam", "top_cam", 1), + GATE_CAM(CLK_CAM_RAWB_CAMTG, "cam_rawb_camtg", "top_cam", 2), +}; + +static const struct mtk_gate cam_yuva_clks[] = { + GATE_CAM(CLK_CAM_YUVA_LARBX, "cam_yuva_larbx", "top_cam", 0), + GATE_CAM(CLK_CAM_YUVA_CAM, "cam_yuva_cam", "top_cam", 1), + GATE_CAM(CLK_CAM_YUVA_CAMTG, "cam_yuva_camtg", "top_cam", 2), +}; + +static const struct mtk_gate cam_yuvb_clks[] = { + GATE_CAM(CLK_CAM_YUVB_LARBX, "cam_yuvb_larbx", "top_cam", 0), + GATE_CAM(CLK_CAM_YUVB_CAM, "cam_yuvb_cam", "top_cam", 1), + GATE_CAM(CLK_CAM_YUVB_CAMTG, "cam_yuvb_camtg", "top_cam", 2), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct mtk_clk_desc cam_mraw_desc = { + .clks = cam_mraw_clks, + .num_clks = ARRAY_SIZE(cam_mraw_clks), +}; + +static const struct mtk_clk_desc cam_rawa_desc = { + .clks = cam_rawa_clks, + .num_clks = ARRAY_SIZE(cam_rawa_clks), +}; + +static const struct mtk_clk_desc cam_rawb_desc = { + .clks = cam_rawb_clks, + .num_clks = ARRAY_SIZE(cam_rawb_clks), +}; + +static const struct mtk_clk_desc cam_yuva_desc = { + .clks = cam_yuva_clks, + .num_clks = ARRAY_SIZE(cam_yuva_clks), +}; + +static const struct mtk_clk_desc cam_yuvb_desc = { + .clks = cam_yuvb_clks, + .num_clks = ARRAY_SIZE(cam_yuvb_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_cam[] = { + { + .compatible = "mediatek,mt8195-camsys", + .data = &cam_desc, + }, { + .compatible = "mediatek,mt8195-camsys_mraw", + .data = &cam_mraw_desc, + }, { + .compatible = "mediatek,mt8195-camsys_rawa", + .data = &cam_rawa_desc, + }, { + .compatible = "mediatek,mt8195-camsys_rawb", + .data = &cam_rawb_desc, + }, { + .compatible = "mediatek,mt8195-camsys_yuva", + .data = &cam_yuva_desc, + }, { + .compatible = "mediatek,mt8195-camsys_yuvb", + .data = &cam_yuvb_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-cam", + .of_match_table = of_match_clk_mt8195_cam, + }, +}; +builtin_platform_driver(clk_mt8195_cam_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-ccu.c b/drivers/clk/mediatek/clk-mt8195-ccu.c new file mode 100644 index 000000000..4e326b630 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-ccu.c @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs ccu_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CCU(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ccu_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate ccu_clks[] = { + GATE_CCU(CLK_CCU_LARB18, "ccu_larb18", "top_ccu", 0), + GATE_CCU(CLK_CCU_AHB, "ccu_ahb", "top_ccu", 1), + GATE_CCU(CLK_CCU_CCU0, "ccu_ccu0", "top_ccu", 2), + GATE_CCU(CLK_CCU_CCU1, "ccu_ccu1", "top_ccu", 3), +}; + +static const struct mtk_clk_desc ccu_desc = { + .clks = ccu_clks, + .num_clks = ARRAY_SIZE(ccu_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_ccu[] = { + { + .compatible = "mediatek,mt8195-ccusys", + .data = &ccu_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_ccu_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-ccu", + .of_match_table = of_match_clk_mt8195_ccu, + }, +}; +builtin_platform_driver(clk_mt8195_ccu_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-img.c b/drivers/clk/mediatek/clk-mt8195-img.c new file mode 100644 index 000000000..12f5c436d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-img.c @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs img_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_IMG(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate img_clks[] = { + GATE_IMG(CLK_IMG_LARB9, "img_larb9", "top_img", 0), + GATE_IMG(CLK_IMG_TRAW0, "img_traw0", "top_img", 1), + GATE_IMG(CLK_IMG_TRAW1, "img_traw1", "top_img", 2), + GATE_IMG(CLK_IMG_TRAW2, "img_traw2", "top_img", 3), + GATE_IMG(CLK_IMG_TRAW3, "img_traw3", "top_img", 4), + GATE_IMG(CLK_IMG_DIP0, "img_dip0", "top_img", 8), + GATE_IMG(CLK_IMG_WPE0, "img_wpe0", "top_img", 9), + GATE_IMG(CLK_IMG_IPE, "img_ipe", "top_img", 10), + GATE_IMG(CLK_IMG_DIP1, "img_dip1", "top_img", 11), + GATE_IMG(CLK_IMG_WPE1, "img_wpe1", "top_img", 12), + GATE_IMG(CLK_IMG_GALS, "img_gals", "top_img", 31), +}; + +static const struct mtk_gate img1_dip_top_clks[] = { + GATE_IMG(CLK_IMG1_DIP_TOP_LARB10, "img1_dip_top_larb10", "top_img", 0), + GATE_IMG(CLK_IMG1_DIP_TOP_DIP_TOP, "img1_dip_top_dip_top", "top_img", 1), +}; + +static const struct mtk_gate img1_dip_nr_clks[] = { + GATE_IMG(CLK_IMG1_DIP_NR_RESERVE, "img1_dip_nr_reserve", "top_img", 0), + GATE_IMG(CLK_IMG1_DIP_NR_DIP_NR, "img1_dip_nr_dip_nr", "top_img", 1), +}; + +static const struct mtk_gate img1_wpe_clks[] = { + GATE_IMG(CLK_IMG1_WPE_LARB11, "img1_wpe_larb11", "top_img", 0), + GATE_IMG(CLK_IMG1_WPE_WPE, "img1_wpe_wpe", "top_img", 1), +}; + +static const struct mtk_clk_desc img_desc = { + .clks = img_clks, + .num_clks = ARRAY_SIZE(img_clks), +}; + +static const struct mtk_clk_desc img1_dip_top_desc = { + .clks = img1_dip_top_clks, + .num_clks = ARRAY_SIZE(img1_dip_top_clks), +}; + +static const struct mtk_clk_desc img1_dip_nr_desc = { + .clks = img1_dip_nr_clks, + .num_clks = ARRAY_SIZE(img1_dip_nr_clks), +}; + +static const struct mtk_clk_desc img1_wpe_desc = { + .clks = img1_wpe_clks, + .num_clks = ARRAY_SIZE(img1_wpe_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_img[] = { + { + .compatible = "mediatek,mt8195-imgsys", + .data = &img_desc, + }, { + .compatible = "mediatek,mt8195-imgsys1_dip_top", + .data = &img1_dip_top_desc, + }, { + .compatible = "mediatek,mt8195-imgsys1_dip_nr", + .data = &img1_dip_nr_desc, + }, { + .compatible = "mediatek,mt8195-imgsys1_wpe", + .data = &img1_wpe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_img_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-img", + .of_match_table = of_match_clk_mt8195_img, + }, +}; +builtin_platform_driver(clk_mt8195_img_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c new file mode 100644 index 000000000..fbc809d05 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-imp_iic_wrap.c @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs imp_iic_wrap_cg_regs = { + .set_ofs = 0xe08, + .clr_ofs = 0xe04, + .sta_ofs = 0xe00, +}; + +#define GATE_IMP_IIC_WRAP(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &imp_iic_wrap_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, CLK_OPS_PARENT_ENABLE) + +static const struct mtk_gate imp_iic_wrap_s_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C5, "imp_iic_wrap_s_i2c5", "top_i2c", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C6, "imp_iic_wrap_s_i2c6", "top_i2c", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_S_I2C7, "imp_iic_wrap_s_i2c7", "top_i2c", 2), +}; + +static const struct mtk_gate imp_iic_wrap_w_clks[] = { + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C0, "imp_iic_wrap_w_i2c0", "top_i2c", 0), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C1, "imp_iic_wrap_w_i2c1", "top_i2c", 1), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C2, "imp_iic_wrap_w_i2c2", "top_i2c", 2), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C3, "imp_iic_wrap_w_i2c3", "top_i2c", 3), + GATE_IMP_IIC_WRAP(CLK_IMP_IIC_WRAP_W_I2C4, "imp_iic_wrap_w_i2c4", "top_i2c", 4), +}; + +static const struct mtk_clk_desc imp_iic_wrap_s_desc = { + .clks = imp_iic_wrap_s_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_s_clks), +}; + +static const struct mtk_clk_desc imp_iic_wrap_w_desc = { + .clks = imp_iic_wrap_w_clks, + .num_clks = ARRAY_SIZE(imp_iic_wrap_w_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_imp_iic_wrap[] = { + { + .compatible = "mediatek,mt8195-imp_iic_wrap_s", + .data = &imp_iic_wrap_s_desc, + }, { + .compatible = "mediatek,mt8195-imp_iic_wrap_w", + .data = &imp_iic_wrap_w_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_imp_iic_wrap_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-imp_iic_wrap", + .of_match_table = of_match_clk_mt8195_imp_iic_wrap, + }, +}; +builtin_platform_driver(clk_mt8195_imp_iic_wrap_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-infra_ao.c b/drivers/clk/mediatek/clk-mt8195-infra_ao.c new file mode 100644 index 000000000..fcd410461 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-infra_ao.c @@ -0,0 +1,241 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <dt-bindings/reset/mt8195-resets.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs infra_ao0_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs infra_ao1_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs infra_ao2_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs infra_ao3_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +static const struct mtk_gate_regs infra_ao4_cg_regs = { + .set_ofs = 0xe0, + .clr_ofs = 0xe4, + .sta_ofs = 0xe8, +}; + +#define GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO0(_id, _name, _parent, _shift) \ + GATE_INFRA_AO0_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO1(_id, _name, _parent, _shift) \ + GATE_INFRA_AO1_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO2(_id, _name, _parent, _shift) \ + GATE_INFRA_AO2_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao3_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO3(_id, _name, _parent, _shift) \ + GATE_INFRA_AO3_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_INFRA_AO4_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &infra_ao4_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flag) + +#define GATE_INFRA_AO4(_id, _name, _parent, _shift) \ + GATE_INFRA_AO4_FLAGS(_id, _name, _parent, _shift, 0) + +static const struct mtk_gate infra_ao_clks[] = { + /* INFRA_AO0 */ + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_TMR, "infra_ao_pmic_tmr", "top_pwrap_ulposc", 0), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_AP, "infra_ao_pmic_ap", "top_pwrap_ulposc", 1), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_MD, "infra_ao_pmic_md", "top_pwrap_ulposc", 2), + GATE_INFRA_AO0(CLK_INFRA_AO_PMIC_CONN, "infra_ao_pmic_conn", "top_pwrap_ulposc", 3), + /* infra_ao_sej is main clock is for secure engine with JTAG support */ + GATE_INFRA_AO0_FLAGS(CLK_INFRA_AO_SEJ, "infra_ao_sej", "top_axi", 5, CLK_IS_CRITICAL), + GATE_INFRA_AO0(CLK_INFRA_AO_APXGPT, "infra_ao_apxgpt", "top_axi", 6), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE, "infra_ao_gce", "top_axi", 8), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE2, "infra_ao_gce2", "top_axi", 9), + GATE_INFRA_AO0(CLK_INFRA_AO_THERM, "infra_ao_therm", "top_axi", 10), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM_H, "infra_ao_pwm_h", "top_axi", 15), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM1, "infra_ao_pwm1", "top_pwm", 16), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM2, "infra_ao_pwm2", "top_pwm", 17), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM3, "infra_ao_pwm3", "top_pwm", 18), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM4, "infra_ao_pwm4", "top_pwm", 19), + GATE_INFRA_AO0(CLK_INFRA_AO_PWM, "infra_ao_pwm", "top_pwm", 21), + GATE_INFRA_AO0(CLK_INFRA_AO_UART0, "infra_ao_uart0", "top_uart", 22), + GATE_INFRA_AO0(CLK_INFRA_AO_UART1, "infra_ao_uart1", "top_uart", 23), + GATE_INFRA_AO0(CLK_INFRA_AO_UART2, "infra_ao_uart2", "top_uart", 24), + GATE_INFRA_AO0(CLK_INFRA_AO_UART3, "infra_ao_uart3", "top_uart", 25), + GATE_INFRA_AO0(CLK_INFRA_AO_UART4, "infra_ao_uart4", "top_uart", 26), + GATE_INFRA_AO0(CLK_INFRA_AO_GCE_26M, "infra_ao_gce_26m", "clk26m", 27), + GATE_INFRA_AO0(CLK_INFRA_AO_CQ_DMA_FPC, "infra_ao_cq_dma_fpc", "fpc", 28), + GATE_INFRA_AO0(CLK_INFRA_AO_UART5, "infra_ao_uart5", "top_uart", 29), + /* INFRA_AO1 */ + GATE_INFRA_AO1(CLK_INFRA_AO_HDMI_26M, "infra_ao_hdmi_26m", "clk26m", 0), + GATE_INFRA_AO1(CLK_INFRA_AO_SPI0, "infra_ao_spi0", "top_spi", 1), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC0, "infra_ao_msdc0", "top_msdc50_0_hclk", 2), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC1, "infra_ao_msdc1", "top_axi", 4), + GATE_INFRA_AO1(CLK_INFRA_AO_CG1_MSDC2, "infra_ao_cg1_msdc2", "top_axi", 5), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC0_SRC, "infra_ao_msdc0_src", "top_msdc50_0", 6), + GATE_INFRA_AO1(CLK_INFRA_AO_TRNG, "infra_ao_trng", "top_axi", 9), + GATE_INFRA_AO1(CLK_INFRA_AO_AUXADC, "infra_ao_auxadc", "clk26m", 10), + GATE_INFRA_AO1(CLK_INFRA_AO_CPUM, "infra_ao_cpum", "top_axi", 11), + GATE_INFRA_AO1(CLK_INFRA_AO_HDMI_32K, "infra_ao_hdmi_32k", "clk32k", 12), + GATE_INFRA_AO1(CLK_INFRA_AO_CEC_66M_H, "infra_ao_cec_66m_h", "top_axi", 13), + GATE_INFRA_AO1(CLK_INFRA_AO_IRRX, "infra_ao_irrx", "top_axi", 14), + GATE_INFRA_AO1(CLK_INFRA_AO_PCIE_TL_26M, "infra_ao_pcie_tl_26m", "clk26m", 15), + GATE_INFRA_AO1(CLK_INFRA_AO_MSDC1_SRC, "infra_ao_msdc1_src", "top_msdc30_1", 16), + GATE_INFRA_AO1(CLK_INFRA_AO_CEC_66M_B, "infra_ao_cec_66m_b", "top_axi", 17), + GATE_INFRA_AO1(CLK_INFRA_AO_PCIE_TL_96M, "infra_ao_pcie_tl_96m", "top_tl", 18), + /* infra_ao_device_apc is for device access permission control module */ + GATE_INFRA_AO1_FLAGS(CLK_INFRA_AO_DEVICE_APC, "infra_ao_device_apc", "top_axi", 20, + CLK_IS_CRITICAL), + GATE_INFRA_AO1(CLK_INFRA_AO_ECC_66M_H, "infra_ao_ecc_66m_h", "top_axi", 23), + GATE_INFRA_AO1(CLK_INFRA_AO_DEBUGSYS, "infra_ao_debugsys", "top_axi", 24), + GATE_INFRA_AO1(CLK_INFRA_AO_AUDIO, "infra_ao_audio", "top_axi", 25), + GATE_INFRA_AO1(CLK_INFRA_AO_PCIE_TL_32K, "infra_ao_pcie_tl_32k", "clk32k", 26), + GATE_INFRA_AO1(CLK_INFRA_AO_DBG_TRACE, "infra_ao_dbg_trace", "top_axi", 29), + GATE_INFRA_AO1(CLK_INFRA_AO_DRAMC_F26M, "infra_ao_dramc_f26m", "clk26m", 31), + /* INFRA_AO2 */ + GATE_INFRA_AO2(CLK_INFRA_AO_IRTX, "infra_ao_irtx", "top_axi", 0), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB, "infra_ao_ssusb", "top_usb_top", 1), + GATE_INFRA_AO2(CLK_INFRA_AO_DISP_PWM, "infra_ao_disp_pwm", "top_disp_pwm0", 2), + GATE_INFRA_AO2(CLK_INFRA_AO_CLDMA_B, "infra_ao_cldma_b", "top_axi", 3), + GATE_INFRA_AO2(CLK_INFRA_AO_AUDIO_26M_B, "infra_ao_audio_26m_b", "clk26m", 4), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI1, "infra_ao_spi1", "top_spi", 6), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI2, "infra_ao_spi2", "top_spi", 9), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI3, "infra_ao_spi3", "top_spi", 10), + GATE_INFRA_AO2(CLK_INFRA_AO_UNIPRO_SYS, "infra_ao_unipro_sys", "top_ufs", 11), + GATE_INFRA_AO2(CLK_INFRA_AO_UNIPRO_TICK, "infra_ao_unipro_tick", "top_ufs_tick1us", 12), + GATE_INFRA_AO2(CLK_INFRA_AO_UFS_MP_SAP_B, "infra_ao_ufs_mp_sap_b", "top_ufs_mp_sap_cfg", 13), + /* pwrmcu is used by ATF for platform PM: clocks must never be disabled by the kernel */ + GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_PWRMCU, "infra_ao_pwrmcu", "top_pwrmcu", 15, + CLK_IS_CRITICAL), + GATE_INFRA_AO2_FLAGS(CLK_INFRA_AO_PWRMCU_BUS_H, "infra_ao_pwrmcu_bus_h", "top_axi", 17, + CLK_IS_CRITICAL), + GATE_INFRA_AO2(CLK_INFRA_AO_APDMA_B, "infra_ao_apdma_b", "top_axi", 18), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI4, "infra_ao_spi4", "top_spi", 25), + GATE_INFRA_AO2(CLK_INFRA_AO_SPI5, "infra_ao_spi5", "top_spi", 26), + GATE_INFRA_AO2(CLK_INFRA_AO_CQ_DMA, "infra_ao_cq_dma", "top_axi", 27), + GATE_INFRA_AO2(CLK_INFRA_AO_AES_UFSFDE, "infra_ao_aes_ufsfde", "top_ufs", 28), + GATE_INFRA_AO2(CLK_INFRA_AO_AES, "infra_ao_aes", "top_aes_ufsfde", 29), + GATE_INFRA_AO2(CLK_INFRA_AO_UFS_TICK, "infra_ao_ufs_tick", "top_ufs_tick1us", 30), + GATE_INFRA_AO2(CLK_INFRA_AO_SSUSB_XHCI, "infra_ao_ssusb_xhci", "top_ssusb_xhci", 31), + /* INFRA_AO3 */ + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC0_SELF, "infra_ao_msdc0f", "top_msdc50_0", 0), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC1_SELF, "infra_ao_msdc1f", "top_msdc50_0", 1), + GATE_INFRA_AO3(CLK_INFRA_AO_MSDC2_SELF, "infra_ao_msdc2f", "top_msdc50_0", 2), + GATE_INFRA_AO3(CLK_INFRA_AO_I2S_DMA, "infra_ao_i2s_dma", "top_axi", 5), + GATE_INFRA_AO3(CLK_INFRA_AO_AP_MSDC0, "infra_ao_ap_msdc0", "top_msdc50_0", 7), + GATE_INFRA_AO3(CLK_INFRA_AO_MD_MSDC0, "infra_ao_md_msdc0", "top_msdc50_0", 8), + GATE_INFRA_AO3(CLK_INFRA_AO_CG3_MSDC2, "infra_ao_cg3_msdc2", "top_msdc30_2", 9), + GATE_INFRA_AO3(CLK_INFRA_AO_GCPU, "infra_ao_gcpu", "top_gcpu", 10), + GATE_INFRA_AO3(CLK_INFRA_AO_PCIE_PERI_26M, "infra_ao_pcie_peri_26m", "clk26m", 15), + GATE_INFRA_AO3(CLK_INFRA_AO_GCPU_66M_B, "infra_ao_gcpu_66m_b", "top_axi", 16), + GATE_INFRA_AO3(CLK_INFRA_AO_GCPU_133M_B, "infra_ao_gcpu_133m_b", "top_axi", 17), + GATE_INFRA_AO3(CLK_INFRA_AO_DISP_PWM1, "infra_ao_disp_pwm1", "top_disp_pwm1", 20), + GATE_INFRA_AO3(CLK_INFRA_AO_FBIST2FPC, "infra_ao_fbist2fpc", "top_msdc50_0", 24), + /* infra_ao_device_apc_sync is for device access permission control module */ + GATE_INFRA_AO3_FLAGS(CLK_INFRA_AO_DEVICE_APC_SYNC, "infra_ao_device_apc_sync", "top_axi", 25, + CLK_IS_CRITICAL), + GATE_INFRA_AO3(CLK_INFRA_AO_PCIE_P1_PERI_26M, "infra_ao_pcie_p1_peri_26m", "clk26m", 26), + GATE_INFRA_AO3(CLK_INFRA_AO_SPIS0, "infra_ao_spis0", "top_spis", 28), + GATE_INFRA_AO3(CLK_INFRA_AO_SPIS1, "infra_ao_spis1", "top_spis", 29), + /* INFRA_AO4 */ + /* infra_ao_133m_m_peri infra_ao_66m_m_peri are main clocks of peripheral */ + GATE_INFRA_AO4_FLAGS(CLK_INFRA_AO_133M_M_PERI, "infra_ao_133m_m_peri", "top_axi", 0, + CLK_IS_CRITICAL), + GATE_INFRA_AO4_FLAGS(CLK_INFRA_AO_66M_M_PERI, "infra_ao_66m_m_peri", "top_axi", 1, + CLK_IS_CRITICAL), + GATE_INFRA_AO4(CLK_INFRA_AO_PCIE_PL_P_250M_P0, "infra_ao_pcie_pl_p_250m_p0", "pextp_pipe", 7), + GATE_INFRA_AO4(CLK_INFRA_AO_PCIE_PL_P_250M_P1, "infra_ao_pcie_pl_p_250m_p1", + "ssusb_u3phy_p1_p_p0", 8), + GATE_INFRA_AO4(CLK_INFRA_AO_PCIE_P1_TL_96M, "infra_ao_pcie_p1_tl_96m", "top_tl_p1", 17), + GATE_INFRA_AO4(CLK_INFRA_AO_AES_MSDCFDE_0P, "infra_ao_aes_msdcfde_0p", "top_aes_msdcfde", 18), + GATE_INFRA_AO4(CLK_INFRA_AO_UFS_TX_SYMBOL, "infra_ao_ufs_tx_symbol", "ufs_tx_symbol", 22), + GATE_INFRA_AO4(CLK_INFRA_AO_UFS_RX_SYMBOL, "infra_ao_ufs_rx_symbol", "ufs_rx_symbol", 23), + GATE_INFRA_AO4(CLK_INFRA_AO_UFS_RX_SYMBOL1, "infra_ao_ufs_rx_symbol1", "ufs_rx_symbol1", 24), + GATE_INFRA_AO4(CLK_INFRA_AO_PERI_UFS_MEM_SUB, "infra_ao_peri_ufs_mem_sub", "mem_466m", 31), +}; + +static u16 infra_ao_rst_ofs[] = { + INFRA_RST0_SET_OFFSET, + INFRA_RST1_SET_OFFSET, + INFRA_RST2_SET_OFFSET, + INFRA_RST3_SET_OFFSET, + INFRA_RST4_SET_OFFSET, +}; + +static u16 infra_ao_idx_map[] = { + [MT8195_INFRA_RST0_THERM_CTRL_SWRST] = 0 * RST_NR_PER_BANK + 0, + [MT8195_INFRA_RST2_USBSIF_P1_SWRST] = 2 * RST_NR_PER_BANK + 18, + [MT8195_INFRA_RST2_PCIE_P0_SWRST] = 2 * RST_NR_PER_BANK + 26, + [MT8195_INFRA_RST2_PCIE_P1_SWRST] = 2 * RST_NR_PER_BANK + 27, + [MT8195_INFRA_RST3_THERM_CTRL_PTP_SWRST] = 3 * RST_NR_PER_BANK + 5, + [MT8195_INFRA_RST4_THERM_CTRL_MCU_SWRST] = 4 * RST_NR_PER_BANK + 10, +}; + +static struct mtk_clk_rst_desc infra_ao_rst_desc = { + .version = MTK_RST_SET_CLR, + .rst_bank_ofs = infra_ao_rst_ofs, + .rst_bank_nr = ARRAY_SIZE(infra_ao_rst_ofs), + .rst_idx_map = infra_ao_idx_map, + .rst_idx_map_nr = ARRAY_SIZE(infra_ao_idx_map), +}; + +static const struct mtk_clk_desc infra_ao_desc = { + .clks = infra_ao_clks, + .num_clks = ARRAY_SIZE(infra_ao_clks), + .rst_desc = &infra_ao_rst_desc, +}; + +static const struct of_device_id of_match_clk_mt8195_infra_ao[] = { + { + .compatible = "mediatek,mt8195-infracfg_ao", + .data = &infra_ao_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_infra_ao_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-infra_ao", + .of_match_table = of_match_clk_mt8195_infra_ao, + }, +}; +builtin_platform_driver(clk_mt8195_infra_ao_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-ipe.c b/drivers/clk/mediatek/clk-mt8195-ipe.c new file mode 100644 index 000000000..b0d745cf7 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-ipe.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs ipe_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_IPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate ipe_clks[] = { + GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "top_ipe", 0), + GATE_IPE(CLK_IPE_FDVT, "ipe_fdvt", "top_ipe", 1), + GATE_IPE(CLK_IPE_ME, "ipe_me", "top_ipe", 2), + GATE_IPE(CLK_IPE_TOP, "ipe_top", "top_ipe", 3), + GATE_IPE(CLK_IPE_SMI_LARB12, "ipe_smi_larb12", "top_ipe", 4), +}; + +static const struct mtk_clk_desc ipe_desc = { + .clks = ipe_clks, + .num_clks = ARRAY_SIZE(ipe_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_ipe[] = { + { + .compatible = "mediatek,mt8195-ipesys", + .data = &ipe_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_ipe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-ipe", + .of_match_table = of_match_clk_mt8195_ipe, + }, +}; +builtin_platform_driver(clk_mt8195_ipe_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-mfg.c b/drivers/clk/mediatek/clk-mt8195-mfg.c new file mode 100644 index 000000000..c94cb71bd --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-mfg.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs mfg_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_MFG(_id, _name, _parent, _shift) \ + GATE_MTK_FLAGS(_id, _name, _parent, &mfg_cg_regs, \ + _shift, &mtk_clk_gate_ops_setclr, \ + CLK_SET_RATE_PARENT) + +static const struct mtk_gate mfg_clks[] = { + GATE_MFG(CLK_MFG_BG3D, "mfg_bg3d", "mfg_ck_fast_ref", 0), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_mfg[] = { + { + .compatible = "mediatek,mt8195-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-mfg", + .of_match_table = of_match_clk_mt8195_mfg, + }, +}; +builtin_platform_driver(clk_mt8195_mfg_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-peri_ao.c b/drivers/clk/mediatek/clk-mt8195-peri_ao.c new file mode 100644 index 000000000..2f6b3bb65 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-peri_ao.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs peri_ao_cg_regs = { + .set_ofs = 0x10, + .clr_ofs = 0x14, + .sta_ofs = 0x18, +}; + +#define GATE_PERI_AO(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &peri_ao_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate peri_ao_clks[] = { + GATE_PERI_AO(CLK_PERI_AO_ETHERNET, "peri_ao_ethernet", "top_axi", 0), + GATE_PERI_AO(CLK_PERI_AO_ETHERNET_BUS, "peri_ao_ethernet_bus", "top_axi", 1), + GATE_PERI_AO(CLK_PERI_AO_FLASHIF_BUS, "peri_ao_flashif_bus", "top_axi", 3), + GATE_PERI_AO(CLK_PERI_AO_FLASHIF_FLASH, "peri_ao_flashif_flash", "top_spinor", 5), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_1P_BUS, "peri_ao_ssusb_1p_bus", "top_usb_top_1p", 7), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_1P_XHCI, "peri_ao_ssusb_1p_xhci", "top_ssusb_xhci_1p", 8), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_2P_BUS, "peri_ao_ssusb_2p_bus", "top_usb_top_2p", 9), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_2P_XHCI, "peri_ao_ssusb_2p_xhci", "top_ssusb_xhci_2p", 10), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_3P_BUS, "peri_ao_ssusb_3p_bus", "top_usb_top_3p", 11), + GATE_PERI_AO(CLK_PERI_AO_SSUSB_3P_XHCI, "peri_ao_ssusb_3p_xhci", "top_ssusb_xhci_3p", 12), + GATE_PERI_AO(CLK_PERI_AO_SPINFI, "peri_ao_spinfi", "top_spinfi_bclk", 15), + GATE_PERI_AO(CLK_PERI_AO_ETHERNET_MAC, "peri_ao_ethernet_mac", "top_snps_eth_250m", 16), + GATE_PERI_AO(CLK_PERI_AO_NFI_H, "peri_ao_nfi_h", "top_axi", 19), + GATE_PERI_AO(CLK_PERI_AO_FNFI1X, "peri_ao_fnfi1x", "top_nfi1x", 20), + GATE_PERI_AO(CLK_PERI_AO_PCIE_P0_MEM, "peri_ao_pcie_p0_mem", "mem_466m", 24), + GATE_PERI_AO(CLK_PERI_AO_PCIE_P1_MEM, "peri_ao_pcie_p1_mem", "mem_466m", 25), +}; + +static const struct mtk_clk_desc peri_ao_desc = { + .clks = peri_ao_clks, + .num_clks = ARRAY_SIZE(peri_ao_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_peri_ao[] = { + { + .compatible = "mediatek,mt8195-pericfg_ao", + .data = &peri_ao_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_peri_ao_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-peri_ao", + .of_match_table = of_match_clk_mt8195_peri_ao, + }, +}; +builtin_platform_driver(clk_mt8195_peri_ao_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-scp_adsp.c b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c new file mode 100644 index 000000000..e16c383f6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-scp_adsp.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs scp_adsp_cg_regs = { + .set_ofs = 0x180, + .clr_ofs = 0x180, + .sta_ofs = 0x180, +}; + +#define GATE_SCP_ADSP(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &scp_adsp_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate scp_adsp_clks[] = { + GATE_SCP_ADSP(CLK_SCP_ADSP_AUDIODSP, "scp_adsp_audiodsp", "top_adsp", 0), +}; + +static const struct mtk_clk_desc scp_adsp_desc = { + .clks = scp_adsp_clks, + .num_clks = ARRAY_SIZE(scp_adsp_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_scp_adsp[] = { + { + .compatible = "mediatek,mt8195-scp_adsp", + .data = &scp_adsp_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_scp_adsp_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-scp_adsp", + .of_match_table = of_match_clk_mt8195_scp_adsp, + }, +}; +builtin_platform_driver(clk_mt8195_scp_adsp_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-topckgen.c b/drivers/clk/mediatek/clk-mt8195-topckgen.c new file mode 100644 index 000000000..1e016329c --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-topckgen.c @@ -0,0 +1,1340 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +static DEFINE_SPINLOCK(mt8195_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_IN_DGI, "in_dgi", NULL, 165000000), + FIXED_CLK(CLK_TOP_ULPOSC1, "ulposc1", NULL, 248000000), + FIXED_CLK(CLK_TOP_ULPOSC2, "ulposc2", NULL, 326000000), + FIXED_CLK(CLK_TOP_MEM_466M, "mem_466m", NULL, 533000000), + FIXED_CLK(CLK_TOP_MPHONE_SLAVE_B, "mphone_slave_b", NULL, 49152000), + FIXED_CLK(CLK_TOP_PEXTP_PIPE, "pextp_pipe", NULL, 250000000), + FIXED_CLK(CLK_TOP_UFS_RX_SYMBOL, "ufs_rx_symbol", NULL, 166000000), + FIXED_CLK(CLK_TOP_UFS_TX_SYMBOL, "ufs_tx_symbol", NULL, 166000000), + FIXED_CLK(CLK_TOP_SSUSB_U3PHY_P1_P_P0, "ssusb_u3phy_p1_p_p0", NULL, 131000000), + FIXED_CLK(CLK_TOP_UFS_RX_SYMBOL1, "ufs_rx_symbol1", NULL, 166000000), + FIXED_CLK(CLK_TOP_FPC, "fpc", NULL, 50000000), + FIXED_CLK(CLK_TOP_HDMIRX_P, "hdmirx_p", NULL, 594000000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_CLK26M_D52, "clk26m_d52", "clk26m", 1, 52), + FACTOR(CLK_TOP_IN_DGI_D2, "in_dgi_d2", "in_dgi", 1, 2), + FACTOR(CLK_TOP_IN_DGI_D4, "in_dgi_d4", "in_dgi", 1, 4), + FACTOR(CLK_TOP_IN_DGI_D6, "in_dgi_d6", "in_dgi", 1, 6), + FACTOR(CLK_TOP_IN_DGI_D8, "in_dgi_d8", "in_dgi", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D4_D2, "mainpll_d4_d2", "mainpll_d4", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D4_D4, "mainpll_d4_d4", "mainpll_d4", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D4_D8, "mainpll_d4_d8", "mainpll_d4", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D5_D2, "mainpll_d5_d2", "mainpll_d5", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D5_D4, "mainpll_d5_d4", "mainpll_d5", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D5_D8, "mainpll_d5_d8", "mainpll_d5", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6), + FACTOR(CLK_TOP_MAINPLL_D6_D2, "mainpll_d6_d2", "mainpll_d6", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D6_D4, "mainpll_d6_d4", "mainpll_d6", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D6_D8, "mainpll_d6_d8", "mainpll_d6", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D7_D2, "mainpll_d7_d2", "mainpll_d7", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D7_D4, "mainpll_d7_d4", "mainpll_d7", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D7_D8, "mainpll_d7_d8", "mainpll_d7", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D9, "mainpll_d9", "mainpll", 1, 9), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D4_D2, "univpll_d4_d2", "univpll_d4", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D4_D4, "univpll_d4_d4", "univpll_d4", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D4_D8, "univpll_d4_d8", "univpll_d4", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D5_D2, "univpll_d5_d2", "univpll_d5", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D5_D4, "univpll_d5_d4", "univpll_d5", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D5_D8, "univpll_d5_d8", "univpll_d5", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL_D6_D2, "univpll_d6_d2", "univpll_d6", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D6_D4, "univpll_d6_d4", "univpll_d6", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D6_D8, "univpll_d6_d8", "univpll_d6", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D6_D16, "univpll_d6_d16", "univpll_d6", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7), + FACTOR(CLK_TOP_UNIVPLL_192M, "univpll_192m", "univpll", 1, 13), + FACTOR(CLK_TOP_UNIVPLL_192M_D4, "univpll_192m_d4", "univpll_192m", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_192M_D8, "univpll_192m_d8", "univpll_192m", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_192M_D16, "univpll_192m_d16", "univpll_192m", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_192M_D32, "univpll_192m_d32", "univpll_192m", 1, 32), + FACTOR(CLK_TOP_APLL1_D3, "apll1_d3", "apll1", 1, 3), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1", 1, 4), + FACTOR(CLK_TOP_APLL2_D3, "apll2_d3", "apll2", 1, 3), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2", 1, 4), + FACTOR(CLK_TOP_APLL3_D4, "apll3_d4", "apll3", 1, 4), + FACTOR(CLK_TOP_APLL4_D4, "apll4_d4", "apll4", 1, 4), + FACTOR(CLK_TOP_APLL5_D4, "apll5_d4", "apll5", 1, 4), + FACTOR(CLK_TOP_HDMIRX_APLL_D3, "hdmirx_apll_d3", "hdmirx_apll", 1, 3), + FACTOR(CLK_TOP_HDMIRX_APLL_D4, "hdmirx_apll_d4", "hdmirx_apll", 1, 4), + FACTOR(CLK_TOP_HDMIRX_APLL_D6, "hdmirx_apll_d6", "hdmirx_apll", 1, 6), + FACTOR(CLK_TOP_MMPLL_D4, "mmpll_d4", "mmpll", 1, 4), + FACTOR(CLK_TOP_MMPLL_D4_D2, "mmpll_d4_d2", "mmpll_d4", 1, 2), + FACTOR(CLK_TOP_MMPLL_D4_D4, "mmpll_d4_d4", "mmpll_d4", 1, 4), + FACTOR(CLK_TOP_MMPLL_D5, "mmpll_d5", "mmpll", 1, 5), + FACTOR(CLK_TOP_MMPLL_D5_D2, "mmpll_d5_d2", "mmpll_d5", 1, 2), + FACTOR(CLK_TOP_MMPLL_D5_D4, "mmpll_d5_d4", "mmpll_d5", 1, 4), + FACTOR(CLK_TOP_MMPLL_D6, "mmpll_d6", "mmpll", 1, 6), + FACTOR(CLK_TOP_MMPLL_D6_D2, "mmpll_d6_d2", "mmpll_d6", 1, 2), + FACTOR(CLK_TOP_MMPLL_D7, "mmpll_d7", "mmpll", 1, 7), + FACTOR(CLK_TOP_MMPLL_D9, "mmpll_d9", "mmpll", 1, 9), + FACTOR(CLK_TOP_TVDPLL1_D2, "tvdpll1_d2", "tvdpll1", 1, 2), + FACTOR(CLK_TOP_TVDPLL1_D4, "tvdpll1_d4", "tvdpll1", 1, 4), + FACTOR(CLK_TOP_TVDPLL1_D8, "tvdpll1_d8", "tvdpll1", 1, 8), + FACTOR(CLK_TOP_TVDPLL1_D16, "tvdpll1_d16", "tvdpll1", 1, 16), + FACTOR(CLK_TOP_TVDPLL2_D2, "tvdpll2_d2", "tvdpll2", 1, 2), + FACTOR(CLK_TOP_TVDPLL2_D4, "tvdpll2_d4", "tvdpll2", 1, 4), + FACTOR(CLK_TOP_TVDPLL2_D8, "tvdpll2_d8", "tvdpll2", 1, 8), + FACTOR(CLK_TOP_TVDPLL2_D16, "tvdpll2_d16", "tvdpll2", 1, 16), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4), + FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, 16), + FACTOR(CLK_TOP_ETHPLL_D2, "ethpll_d2", "ethpll", 1, 2), + FACTOR(CLK_TOP_ETHPLL_D8, "ethpll_d8", "ethpll", 1, 8), + FACTOR(CLK_TOP_ETHPLL_D10, "ethpll_d10", "ethpll", 1, 10), + FACTOR(CLK_TOP_DGIPLL_D2, "dgipll_d2", "dgipll", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D2, "ulposc1_d2", "ulposc1", 1, 2), + FACTOR(CLK_TOP_ULPOSC1_D4, "ulposc1_d4", "ulposc1", 1, 4), + FACTOR(CLK_TOP_ULPOSC1_D7, "ulposc1_d7", "ulposc1", 1, 7), + FACTOR(CLK_TOP_ULPOSC1_D8, "ulposc1_d8", "ulposc1", 1, 8), + FACTOR(CLK_TOP_ULPOSC1_D10, "ulposc1_d10", "ulposc1", 1, 10), + FACTOR(CLK_TOP_ULPOSC1_D16, "ulposc1_d16", "ulposc1", 1, 16), + FACTOR(CLK_TOP_ADSPPLL_D2, "adsppll_d2", "adsppll", 1, 2), + FACTOR(CLK_TOP_ADSPPLL_D4, "adsppll_d4", "adsppll", 1, 4), + FACTOR(CLK_TOP_ADSPPLL_D8, "adsppll_d8", "adsppll", 1, 8), +}; + +static const char * const axi_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d7_d2", + "mainpll_d4_d2", + "mainpll_d5_d2", + "mainpll_d6_d2", + "ulposc1_d4" +}; + +static const char * const spm_parents[] = { + "clk26m", + "ulposc1_d10", + "mainpll_d7_d4", + "clk32k" +}; + +static const char * const scp_parents[] = { + "clk26m", + "univpll_d4", + "mainpll_d6", + "univpll_d6", + "univpll_d4_d2", + "mainpll_d4_d2", + "mainpll_d4", + "mainpll_d6_d2" +}; + +static const char * const bus_aximem_parents[] = { + "clk26m", + "mainpll_d7_d2", + "mainpll_d4_d2", + "mainpll_d5_d2", + "mainpll_d6" +}; + +static const char * const vpp_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d5_d2", + "univpll_d4_d2", + "mmpll_d4_d2", + "mmpll_d7", + "univpll_d6", + "mainpll_d4", + "mmpll_d5", + "tvdpll1", + "tvdpll2", + "univpll_d4", + "mmpll_d4" +}; + +static const char * const ethdr_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d5_d2", + "univpll_d4_d2", + "mmpll_d4_d2", + "mmpll_d7", + "univpll_d6", + "mainpll_d4", + "mmpll_d5_d4", + "tvdpll1", + "tvdpll2", + "univpll_d4", + "mmpll_d4" +}; + +static const char * const ipe_parents[] = { + "clk26m", + "imgpll", + "mainpll_d4", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "mmpll_d4_d2", + "univpll_d4_d2", + "mainpll_d4_d2", + "mmpll_d6_d2", + "univpll_d5_d2" +}; + +static const char * const cam_parents[] = { + "clk26m", + "mainpll_d4", + "mmpll_d4", + "univpll_d4", + "univpll_d5", + "univpll_d6", + "mmpll_d7", + "univpll_d4_d2", + "mainpll_d4_d2", + "imgpll" +}; + +static const char * const ccu_parents[] = { + "clk26m", + "univpll_d6", + "mainpll_d4_d2", + "mainpll_d4", + "univpll_d5", + "mainpll_d6", + "mmpll_d6", + "mmpll_d7", + "univpll_d4_d2", + "univpll_d7" +}; + +static const char * const img_parents[] = { + "clk26m", + "imgpll", + "univpll_d4", + "mainpll_d4", + "univpll_d5", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "mmpll_d4_d2", + "univpll_d4_d2", + "mainpll_d4_d2", + "univpll_d5_d2" +}; + +static const char * const camtm_parents[] = { + "clk26m", + "univpll_d4_d4", + "univpll_d6_d2", + "univpll_d6_d4" +}; + +static const char * const dsp_parents[] = { + "clk26m", + "univpll_d6_d2", + "univpll_d4_d2", + "univpll_d5", + "univpll_d4", + "mmpll_d4", + "mainpll_d3", + "univpll_d3" +}; + +static const char * const dsp1_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d4_d2", + "univpll_d5", + "mmpll_d5", + "univpll_d4", + "mainpll_d3", + "univpll_d3" +}; + +static const char * const dsp2_parents[] = { + "clk26m", + "univpll_d6_d2", + "univpll_d4_d2", + "mainpll_d4", + "univpll_d4", + "mmpll_d4", + "mainpll_d3", + "univpll_d3" +}; + +static const char * const ipu_if_parents[] = { + "clk26m", + "univpll_d6_d2", + "univpll_d5_d2", + "mainpll_d4_d2", + "mainpll_d6", + "univpll_d5", + "univpll_d4", + "mmpll_d4" +}; + +/* + * MFG can be also parented to "univpll_d6" and "univpll_d7": + * these have been removed from the parents list to let us + * achieve GPU DVFS without any special clock handlers. + */ +static const char * const mfg_parents[] = { + "clk26m", + "mainpll_d5_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "univpll_192m_d8", + "univpll_d6_d8", + "univpll_192m_d4", + "univpll_d6_d16", + "clk26m_d2", + "univpll_192m_d16", + "univpll_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll_d6_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "mainpll_d5_d4", + "mainpll_d6_d4", + "msdcpll_d4", + "univpll_d6_d2", + "mainpll_d6_d2", + "mainpll_d4_d4", + "univpll_d5_d4" +}; + +static const char * const spis_parents[] = { + "clk26m", + "univpll_d6", + "mainpll_d6", + "univpll_d4_d2", + "univpll_d6_d2", + "univpll_d4_d4", + "univpll_d6_d4", + "mainpll_d7_d4" +}; + +static const char * const msdc50_0_h_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d6_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll", + "msdcpll_d2", + "univpll_d4_d4", + "mainpll_d6_d2", + "univpll_d4_d2" +}; + +static const char * const msdc30_parents[] = { + "clk26m", + "univpll_d6_d2", + "mainpll_d6_d2", + "mainpll_d7_d2", + "msdcpll_d2" +}; + +static const char * const intdir_parents[] = { + "clk26m", + "univpll_d6", + "mainpll_d4", + "univpll_d4" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d7_d4" +}; + +static const char * const audio_h_parents[] = { + "clk26m", + "univpll_d7", + "apll1", + "apll2" +}; + +static const char * const pwrap_ulposc_parents[] = { + "ulposc1_d10", + "clk26m", + "ulposc1_d4", + "ulposc1_d7", + "ulposc1_d8", + "ulposc1_d16", + "mainpll_d4_d8", + "univpll_d5_d8" +}; + +static const char * const atb_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d5_d2" +}; + +static const char * const pwrmcu_parents[] = { + "clk26m", + "mainpll_d7_d2", + "mainpll_d6_d2", + "mainpll_d5_d2", + "mainpll_d9", + "mainpll_d4_d2" +}; + +static const char * const dp_parents[] = { + "clk26m", + "tvdpll1_d2", + "tvdpll2_d2", + "tvdpll1_d4", + "tvdpll2_d4", + "tvdpll1_d8", + "tvdpll2_d8", + "tvdpll1_d16", + "tvdpll2_d16" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll_d6_d4", + "ulposc1_d2", + "ulposc1_d4", + "ulposc1_d16" +}; + +static const char * const usb_parents[] = { + "clk26m", + "univpll_d5_d4", + "univpll_d6_d4", + "univpll_d5_d2" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "mainpll_d4_d8", + "univpll_d5_d4" +}; + +static const char * const seninf_parents[] = { + "clk26m", + "univpll_d4_d4", + "univpll_d6_d2", + "univpll_d4_d2", + "univpll_d7", + "univpll_d6", + "mmpll_d6", + "univpll_d5" +}; + +static const char * const gcpu_parents[] = { + "clk26m", + "mainpll_d6", + "univpll_d4_d2", + "mmpll_d5_d2", + "univpll_d5_d2" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d4_d4", + "mainpll_d4_d8" +}; + +static const char * const dpmaif_parents[] = { + "clk26m", + "univpll_d4_d4", + "mainpll_d6", + "mainpll_d4_d2", + "univpll_d4_d2" +}; + +static const char * const aes_fde_parents[] = { + "clk26m", + "mainpll_d4_d2", + "mainpll_d6", + "mainpll_d4_d4", + "univpll_d4_d2", + "univpll_d6" +}; + +static const char * const ufs_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d4_d8", + "univpll_d4_d4", + "mainpll_d6_d2", + "univpll_d6_d2", + "msdcpll_d2" +}; + +static const char * const ufs_tick1us_parents[] = { + "clk26m_d52", + "clk26m" +}; + +static const char * const ufs_mp_sap_parents[] = { + "clk26m", + "msdcpll_d16" +}; + +static const char * const venc_parents[] = { + "clk26m", + "mmpll_d4_d2", + "mainpll_d6", + "univpll_d4_d2", + "mainpll_d4_d2", + "univpll_d6", + "mmpll_d6", + "mainpll_d5_d2", + "mainpll_d6_d2", + "mmpll_d9", + "univpll_d4_d4", + "mainpll_d4", + "univpll_d4", + "univpll_d5", + "univpll_d5_d2", + "mainpll_d5" +}; + +static const char * const vdec_parents[] = { + "clk26m", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d4_d2", + "mmpll_d4_d2", + "mainpll_d5", + "mmpll_d6", + "mmpll_d5", + "vdecpll", + "univpll_d4", + "mmpll_d4", + "univpll_d6_d2", + "mmpll_d9", + "univpll_d6", + "univpll_d5", + "mainpll_d4" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll_d4_d8" +}; + +static const char * const mcupm_parents[] = { + "clk26m", + "mainpll_d6_d2", + "mainpll_d7_d4", +}; + +static const char * const spmi_parents[] = { + "clk26m", + "clk26m_d2", + "ulposc1_d8", + "ulposc1_d10", + "ulposc1_d16", + "ulposc1_d7", + "clk32k", + "mainpll_d7_d8", + "mainpll_d6_d8", + "mainpll_d5_d8" +}; + +static const char * const dvfsrc_parents[] = { + "clk26m", + "ulposc1_d10", + "univpll_d6_d8", + "msdcpll_d16" +}; + +static const char * const tl_parents[] = { + "clk26m", + "univpll_d5_d4", + "mainpll_d4_d4" +}; + +static const char * const dsi_occ_parents[] = { + "clk26m", + "mainpll_d6_d2", + "univpll_d5_d2", + "univpll_d4_d2" +}; + +static const char * const wpe_vpp_parents[] = { + "clk26m", + "mainpll_d5_d2", + "mmpll_d6_d2", + "univpll_d5_d2", + "mainpll_d4_d2", + "univpll_d4_d2", + "mmpll_d4_d2", + "mainpll_d6", + "mmpll_d7", + "univpll_d6", + "mainpll_d5", + "univpll_d5", + "mainpll_d4", + "tvdpll1", + "univpll_d4" +}; + +static const char * const hdcp_parents[] = { + "clk26m", + "univpll_d4_d8", + "mainpll_d5_d8", + "univpll_d6_d4" +}; + +static const char * const hdcp_24m_parents[] = { + "clk26m", + "univpll_192m_d4", + "univpll_192m_d8", + "univpll_d6_d8" +}; + +static const char * const hd20_dacr_ref_parents[] = { + "clk26m", + "univpll_d4_d2", + "univpll_d4_d4", + "univpll_d4_d8" +}; + +static const char * const hd20_hdcp_c_parents[] = { + "clk26m", + "msdcpll_d4", + "univpll_d4_d8", + "univpll_d6_d8" +}; + +static const char * const hdmi_xtal_parents[] = { + "clk26m", + "clk26m_d2" +}; + +static const char * const hdmi_apb_parents[] = { + "clk26m", + "univpll_d6_d4", + "msdcpll_d2" +}; + +static const char * const snps_eth_250m_parents[] = { + "clk26m", + "ethpll_d2" +}; + +static const char * const snps_eth_62p4m_ptp_parents[] = { + "apll2_d3", + "apll1_d3", + "clk26m", + "ethpll_d8" +}; + +static const char * const snps_eth_50m_rmii_parents[] = { + "clk26m", + "ethpll_d10" +}; + +static const char * const dgi_out_parents[] = { + "clk26m", + "dgipll", + "dgipll_d2", + "in_dgi", + "in_dgi_d2", + "mmpll_d4_d4" +}; + +static const char * const nna_parents[] = { + "clk26m", + "nnapll", + "univpll_d4", + "mainpll_d4", + "univpll_d5", + "mmpll_d6", + "univpll_d6", + "mainpll_d6", + "mmpll_d4_d2", + "univpll_d4_d2", + "mainpll_d4_d2", + "mmpll_d6_d2" +}; + +static const char * const adsp_parents[] = { + "clk26m", + "clk26m_d2", + "mainpll_d6", + "mainpll_d5_d2", + "univpll_d4_d4", + "univpll_d4", + "univpll_d6", + "ulposc1", + "adsppll", + "adsppll_d2", + "adsppll_d4", + "adsppll_d8" +}; + +static const char * const asm_parents[] = { + "clk26m", + "univpll_d6_d4", + "univpll_d6_d2", + "mainpll_d5_d2" +}; + +static const char * const apll1_parents[] = { + "clk26m", + "apll1_d4" +}; + +static const char * const apll2_parents[] = { + "clk26m", + "apll2_d4" +}; + +static const char * const apll3_parents[] = { + "clk26m", + "apll3_d4" +}; + +static const char * const apll4_parents[] = { + "clk26m", + "apll4_d4" +}; + +static const char * const apll5_parents[] = { + "clk26m", + "apll5_d4" +}; + +static const char * const i2s_parents[] = { + "clk26m", + "apll1", + "apll2", + "apll3", + "apll4", + "apll5", + "hdmirx_apll" +}; + +static const char * const a1sys_hp_parents[] = { + "clk26m", + "apll1_d4" +}; + +static const char * const a2sys_parents[] = { + "clk26m", + "apll2_d4" +}; + +static const char * const a3sys_parents[] = { + "clk26m", + "apll3_d4", + "apll4_d4", + "apll5_d4", + "hdmirx_apll_d3", + "hdmirx_apll_d4", + "hdmirx_apll_d6" +}; + +static const char * const spinfi_b_parents[] = { + "clk26m", + "univpll_d6_d8", + "univpll_d5_d8", + "mainpll_d4_d8", + "mainpll_d7_d4", + "mainpll_d6_d4", + "univpll_d6_d4", + "univpll_d5_d4" +}; + +static const char * const nfi1x_parents[] = { + "clk26m", + "univpll_d5_d4", + "mainpll_d7_d4", + "mainpll_d6_d4", + "univpll_d6_d4", + "mainpll_d4_d4", + "mainpll_d7_d2", + "mainpll_d6_d2" +}; + +static const char * const ecc_parents[] = { + "clk26m", + "mainpll_d4_d4", + "mainpll_d5_d2", + "mainpll_d4_d2", + "mainpll_d6", + "univpll_d6" +}; + +static const char * const audio_local_bus_parents[] = { + "clk26m", + "clk26m_d2", + "mainpll_d4_d4", + "mainpll_d7_d2", + "mainpll_d4_d2", + "mainpll_d5_d2", + "mainpll_d6_d2", + "mainpll_d7", + "univpll_d6", + "ulposc1", + "ulposc1_d4", + "ulposc1_d2" +}; + +static const char * const spinor_parents[] = { + "clk26m", + "clk26m_d2", + "mainpll_d7_d8", + "univpll_d6_d8" +}; + +static const char * const dvio_dgi_ref_parents[] = { + "clk26m", + "in_dgi", + "in_dgi_d2", + "in_dgi_d4", + "in_dgi_d6", + "in_dgi_d8", + "mmpll_d4_d4" +}; + +static const char * const ulposc_parents[] = { + "ulposc1", + "ethpll_d2", + "mainpll_d4_d2", + "ethpll_d10" +}; + +static const char * const ulposc_core_parents[] = { + "ulposc2", + "univpll_d7", + "mainpll_d6", + "ethpll_d10" +}; + +static const char * const srck_parents[] = { + "ulposc1_d10", + "clk26m" +}; + +static const char * const mfg_fast_parents[] = { + "top_mfg_core_tmp", + "mfgpll" +}; + +static const struct mtk_mux top_mtk_muxes[] = { + /* + * CLK_CFG_0 + * top_axi and top_bus_aximem are bus clocks, should not be closed by Linux. + * top_spm and top_scp are main clocks in always-on co-processor. + */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI, "top_axi", + axi_parents, 0x020, 0x024, 0x028, 0, 3, 7, 0x04, 0, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM, "top_spm", + spm_parents, 0x020, 0x024, 0x028, 8, 2, 15, 0x04, 1, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SCP, "top_scp", + scp_parents, 0x020, 0x024, 0x028, 16, 3, 23, 0x04, 2, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_BUS_AXIMEM, "top_bus_aximem", + bus_aximem_parents, 0x020, 0x024, 0x028, 24, 3, 31, 0x04, 3, CLK_IS_CRITICAL), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_VPP, "top_vpp", + vpp_parents, 0x02C, 0x030, 0x034, 0, 4, 7, 0x04, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETHDR, "top_ethdr", + ethdr_parents, 0x02C, 0x030, 0x034, 8, 4, 15, 0x04, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPE, "top_ipe", + ipe_parents, 0x02C, 0x030, 0x034, 16, 4, 23, 0x04, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAM, "top_cam", + cam_parents, 0x02C, 0x030, 0x034, 24, 4, 31, 0x04, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CCU, "top_ccu", + ccu_parents, 0x038, 0x03C, 0x040, 0, 4, 7, 0x04, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IMG, "top_img", + img_parents, 0x038, 0x03C, 0x040, 8, 4, 15, 0x04, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM, "top_camtm", + camtm_parents, 0x038, 0x03C, 0x040, 16, 2, 23, 0x04, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP, "top_dsp", + dsp_parents, 0x038, 0x03C, 0x040, 24, 3, 31, 0x04, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP1, "top_dsp1", + dsp1_parents, 0x044, 0x048, 0x04C, 0, 3, 7, 0x04, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP2, "top_dsp2", + dsp1_parents, 0x044, 0x048, 0x04C, 8, 3, 15, 0x04, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP3, "top_dsp3", + dsp1_parents, 0x044, 0x048, 0x04C, 16, 3, 23, 0x04, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP4, "top_dsp4", + dsp2_parents, 0x044, 0x048, 0x04C, 24, 3, 31, 0x04, 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP5, "top_dsp5", + dsp2_parents, 0x050, 0x054, 0x058, 0, 3, 7, 0x04, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP6, "top_dsp6", + dsp2_parents, 0x050, 0x054, 0x058, 8, 3, 15, 0x04, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP7, "top_dsp7", + dsp_parents, 0x050, 0x054, 0x058, 16, 3, 23, 0x04, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_IPU_IF, "top_ipu_if", + ipu_if_parents, 0x050, 0x054, 0x058, 24, 3, 31, 0x04, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_CORE_TMP, "top_mfg_core_tmp", + mfg_parents, 0x05C, 0x060, 0x064, 0, 2, 7, 0x04, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG, "top_camtg", + camtg_parents, 0x05C, 0x060, 0x064, 8, 3, 15, 0x04, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG2, "top_camtg2", + camtg_parents, 0x05C, 0x060, 0x064, 16, 3, 23, 0x04, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG3, "top_camtg3", + camtg_parents, 0x05C, 0x060, 0x064, 24, 3, 31, 0x04, 23), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG4, "top_camtg4", + camtg_parents, 0x068, 0x06C, 0x070, 0, 3, 7, 0x04, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG5, "top_camtg5", + camtg_parents, 0x068, 0x06C, 0x070, 8, 3, 15, 0x04, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART, "top_uart", + uart_parents, 0x068, 0x06C, 0x070, 16, 1, 23, 0x04, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI, "top_spi", + spi_parents, 0x068, 0x06C, 0x070, 24, 3, 31, 0x04, 27), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPIS, "top_spis", + spis_parents, 0x074, 0x078, 0x07C, 0, 3, 7, 0x04, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HCLK, "top_msdc50_0_hclk", + msdc50_0_h_parents, 0x074, 0x078, 0x07C, 8, 2, 15, 0x04, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0, "top_msdc50_0", + msdc50_0_parents, 0x074, 0x078, 0x07C, 16, 3, 23, 0x04, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1, "top_msdc30_1", + msdc30_parents, 0x074, 0x078, 0x07C, 24, 3, 31, 0x04, 31), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2, "top_msdc30_2", + msdc30_parents, 0x080, 0x084, 0x088, 0, 3, 7, 0x08, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_INTDIR, "top_intdir", + intdir_parents, 0x080, 0x084, 0x088, 8, 2, 15, 0x08, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS, "top_aud_intbus", + aud_intbus_parents, 0x080, 0x084, 0x088, 16, 2, 23, 0x08, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_H, "top_audio_h", + audio_h_parents, 0x080, 0x084, 0x088, 24, 2, 31, 0x08, 3), + /* + * CLK_CFG_9 + * top_pwrmcu is main clock in other co-processor, should not be + * handled by Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWRAP_ULPOSC, "top_pwrap_ulposc", + pwrap_ulposc_parents, 0x08C, 0x090, 0x094, 0, 3, 7, 0x08, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB, "top_atb", + atb_parents, 0x08C, 0x090, 0x094, 8, 2, 15, 0x08, 5), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_PWRMCU, "top_pwrmcu", + pwrmcu_parents, 0x08C, 0x090, 0x094, 16, 3, 23, 0x08, 6, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DP, "top_dp", + dp_parents, 0x08C, 0x090, 0x094, 24, 4, 31, 0x08, 7), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_EDP, "top_edp", + dp_parents, 0x098, 0x09C, 0x0A0, 0, 4, 7, 0x08, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI, "top_dpi", + dp_parents, 0x098, 0x09C, 0x0A0, 8, 4, 15, 0x08, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM0, "top_disp_pwm0", + disp_pwm_parents, 0x098, 0x09C, 0x0A0, 16, 3, 23, 0x08, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM1, "top_disp_pwm1", + disp_pwm_parents, 0x098, 0x09C, 0x0A0, 24, 3, 31, 0x08, 11), + /* CLK_CFG_11 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP, "top_usb_top", + usb_parents, 0x0A4, 0x0A8, 0x0AC, 0, 2, 7, 0x08, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI, "top_ssusb_xhci", + usb_parents, 0x0A4, 0x0A8, 0x0AC, 8, 2, 15, 0x08, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_1P, "top_usb_top_1p", + usb_parents, 0x0A4, 0x0A8, 0x0AC, 16, 2, 23, 0x08, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_1P, "top_ssusb_xhci_1p", + usb_parents, 0x0A4, 0x0A8, 0x0AC, 24, 2, 31, 0x08, 15), + /* CLK_CFG_12 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_2P, "top_usb_top_2p", + usb_parents, 0x0B0, 0x0B4, 0x0B8, 0, 2, 7, 0x08, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_2P, "top_ssusb_xhci_2p", + usb_parents, 0x0B0, 0x0B4, 0x0B8, 8, 2, 15, 0x08, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_USB_TOP_3P, "top_usb_top_3p", + usb_parents, 0x0B0, 0x0B4, 0x0B8, 16, 2, 23, 0x08, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_3P, "top_ssusb_xhci_3p", + usb_parents, 0x0B0, 0x0B4, 0x0B8, 24, 2, 31, 0x08, 19), + /* CLK_CFG_13 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C, "top_i2c", + i2c_parents, 0x0BC, 0x0C0, 0x0C4, 0, 2, 7, 0x08, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF, "top_seninf", + seninf_parents, 0x0BC, 0x0C0, 0x0C4, 8, 3, 15, 0x08, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF1, "top_seninf1", + seninf_parents, 0x0BC, 0x0C0, 0x0C4, 16, 3, 23, 0x08, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF2, "top_seninf2", + seninf_parents, 0x0BC, 0x0C0, 0x0C4, 24, 3, 31, 0x08, 23), + /* CLK_CFG_14 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENINF3, "top_seninf3", + seninf_parents, 0x0C8, 0x0CC, 0x0D0, 0, 3, 7, 0x08, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_GCPU, "top_gcpu", + gcpu_parents, 0x0C8, 0x0CC, 0x0D0, 8, 3, 15, 0x08, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DXCC, "top_dxcc", + dxcc_parents, 0x0C8, 0x0CC, 0x0D0, 16, 2, 23, 0x08, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPMAIF_MAIN, "top_dpmaif_main", + dpmaif_parents, 0x0C8, 0x0CC, 0x0D0, 24, 3, 31, 0x08, 27), + /* CLK_CFG_15 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_UFSFDE, "top_aes_ufsfde", + aes_fde_parents, 0x0D4, 0x0D8, 0x0DC, 0, 3, 7, 0x08, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS, "top_ufs", + ufs_parents, 0x0D4, 0x0D8, 0x0DC, 8, 3, 15, 0x08, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS_TICK1US, "top_ufs_tick1us", + ufs_tick1us_parents, 0x0D4, 0x0D8, 0x0DC, 16, 1, 23, 0x08, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_UFS_MP_SAP_CFG, "top_ufs_mp_sap_cfg", + ufs_mp_sap_parents, 0x0D4, 0x0D8, 0x0DC, 24, 1, 31, 0x08, 31), + /* + * CLK_CFG_16 + * top_mcupm is main clock in other co-processor, should not be + * handled by Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_VENC, "top_venc", + venc_parents, 0x0E0, 0x0E4, 0x0E8, 0, 4, 7, 0x0C, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC, "top_vdec", + vdec_parents, 0x0E0, 0x0E4, 0x0E8, 8, 4, 15, 0x0C, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM, "top_pwm", + pwm_parents, 0x0E0, 0x0E4, 0x0E8, 16, 1, 23, 0x0C, 2), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_MCUPM, "top_mcupm", + mcupm_parents, 0x0E0, 0x0E4, 0x0E8, 24, 2, 31, 0x0C, 3, CLK_IS_CRITICAL), + /* + * CLK_CFG_17 + * top_dvfsrc is for internal DVFS usage, should not be handled by Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_P_MST, "top_spmi_p_mst", + spmi_parents, 0x0EC, 0x0F0, 0x0F4, 0, 4, 7, 0x0C, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPMI_M_MST, "top_spmi_m_mst", + spmi_parents, 0x0EC, 0x0F0, 0x0F4, 8, 4, 15, 0x0C, 5), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DVFSRC, "top_dvfsrc", + dvfsrc_parents, 0x0EC, 0x0F0, 0x0F4, 16, 2, 23, 0x0C, 6, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_TL, "top_tl", + tl_parents, 0x0EC, 0x0F0, 0x0F4, 24, 2, 31, 0x0C, 7), + /* CLK_CFG_18 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_TL_P1, "top_tl_p1", + tl_parents, 0x0F8, 0x0FC, 0x0100, 0, 2, 7, 0x0C, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_MSDCFDE, "top_aes_msdcfde", + aes_fde_parents, 0x0F8, 0x0FC, 0x0100, 8, 3, 15, 0x0C, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSI_OCC, "top_dsi_occ", + dsi_occ_parents, 0x0F8, 0x0FC, 0x0100, 16, 2, 23, 0x0C, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_WPE_VPP, "top_wpe_vpp", + wpe_vpp_parents, 0x0F8, 0x0FC, 0x0100, 24, 4, 31, 0x0C, 11), + /* CLK_CFG_19 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_HDCP, "top_hdcp", + hdcp_parents, 0x0104, 0x0108, 0x010C, 0, 2, 7, 0x0C, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_HDCP_24M, "top_hdcp_24m", + hdcp_24m_parents, 0x0104, 0x0108, 0x010C, 8, 2, 15, 0x0C, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_HD20_DACR_REF_CLK, "top_hd20_dacr_ref_clk", + hd20_dacr_ref_parents, 0x0104, 0x0108, 0x010C, 16, 2, 23, 0x0C, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_HD20_HDCP_CCLK, "top_hd20_hdcp_cclk", + hd20_hdcp_c_parents, 0x0104, 0x0108, 0x010C, 24, 2, 31, 0x0C, 15), + /* CLK_CFG_20 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_HDMI_XTAL, "top_hdmi_xtal", + hdmi_xtal_parents, 0x0110, 0x0114, 0x0118, 0, 1, 7, 0x0C, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_HDMI_APB, "top_hdmi_apb", + hdmi_apb_parents, 0x0110, 0x0114, 0x0118, 8, 2, 15, 0x0C, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SNPS_ETH_250M, "top_snps_eth_250m", + snps_eth_250m_parents, 0x0110, 0x0114, 0x0118, 16, 1, 23, 0x0C, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SNPS_ETH_62P4M_PTP, "top_snps_eth_62p4m_ptp", + snps_eth_62p4m_ptp_parents, 0x0110, 0x0114, 0x0118, 24, 2, 31, 0x0C, 19), + /* CLK_CFG_21 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_SNPS_ETH_50M_RMII, "snps_eth_50m_rmii", + snps_eth_50m_rmii_parents, 0x011C, 0x0120, 0x0124, 0, 1, 7, 0x0C, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DGI_OUT, "top_dgi_out", + dgi_out_parents, 0x011C, 0x0120, 0x0124, 8, 3, 15, 0x0C, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA0, "top_nna0", + nna_parents, 0x011C, 0x0120, 0x0124, 16, 4, 23, 0x0C, 22), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NNA1, "top_nna1", + nna_parents, 0x011C, 0x0120, 0x0124, 24, 4, 31, 0x0C, 23), + /* CLK_CFG_22 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_ADSP, "top_adsp", + adsp_parents, 0x0128, 0x012C, 0x0130, 0, 4, 7, 0x0C, 24), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ASM_H, "top_asm_h", + asm_parents, 0x0128, 0x012C, 0x0130, 8, 2, 15, 0x0C, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ASM_M, "top_asm_m", + asm_parents, 0x0128, 0x012C, 0x0130, 16, 2, 23, 0x0C, 26), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ASM_L, "top_asm_l", + asm_parents, 0x0128, 0x012C, 0x0130, 24, 2, 31, 0x0C, 27), + /* CLK_CFG_23 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_APLL1, "top_apll1", + apll1_parents, 0x0134, 0x0138, 0x013C, 0, 1, 7, 0x0C, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_APLL2, "top_apll2", + apll2_parents, 0x0134, 0x0138, 0x013C, 8, 1, 15, 0x0C, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_APLL3, "top_apll3", + apll3_parents, 0x0134, 0x0138, 0x013C, 16, 1, 23, 0x0C, 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_APLL4, "top_apll4", + apll4_parents, 0x0134, 0x0138, 0x013C, 24, 1, 31, 0x0C, 31), + /* + * CLK_CFG_24 + * i2so4_mck is not used in MT8195. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_APLL5, "top_apll5", + apll5_parents, 0x0140, 0x0144, 0x0148, 0, 1, 7, 0x010, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2SO1_MCK, "top_i2so1_mck", + i2s_parents, 0x0140, 0x0144, 0x0148, 8, 3, 15, 0x010, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2SO2_MCK, "top_i2so2_mck", + i2s_parents, 0x0140, 0x0144, 0x0148, 16, 3, 23, 0x010, 2), + /* + * CLK_CFG_25 + * i2so5_mck and i2si4_mck are not used in MT8195. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2SI1_MCK, "top_i2si1_mck", + i2s_parents, 0x014C, 0x0150, 0x0154, 8, 3, 15, 0x010, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2SI2_MCK, "top_i2si2_mck", + i2s_parents, 0x014C, 0x0150, 0x0154, 16, 3, 23, 0x010, 6), + /* + * CLK_CFG_26 + * i2si5_mck is not used in MT8195. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPTX_MCK, "top_dptx_mck", + i2s_parents, 0x0158, 0x015C, 0x0160, 8, 3, 15, 0x010, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_IEC_CLK, "top_aud_iec_clk", + i2s_parents, 0x0158, 0x015C, 0x0160, 16, 3, 23, 0x010, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A1SYS_HP, "top_a1sys_hp", + a1sys_hp_parents, 0x0158, 0x015C, 0x0160, 24, 1, 31, 0x010, 11), + /* CLK_CFG_27 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_A2SYS_HF, "top_a2sys_hf", + a2sys_parents, 0x0164, 0x0168, 0x016C, 0, 1, 7, 0x010, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A3SYS_HF, "top_a3sys_hf", + a3sys_parents, 0x0164, 0x0168, 0x016C, 8, 3, 15, 0x010, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_A4SYS_HF, "top_a4sys_hf", + a3sys_parents, 0x0164, 0x0168, 0x016C, 16, 3, 23, 0x010, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINFI_BCLK, "top_spinfi_bclk", + spinfi_b_parents, 0x0164, 0x0168, 0x016C, 24, 3, 31, 0x010, 15), + /* CLK_CFG_28 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI1X, "top_nfi1x", + nfi1x_parents, 0x0170, 0x0174, 0x0178, 0, 3, 7, 0x010, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ECC, "top_ecc", + ecc_parents, 0x0170, 0x0174, 0x0178, 8, 3, 15, 0x010, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_LOCAL_BUS, "top_audio_local_bus", + audio_local_bus_parents, 0x0170, 0x0174, 0x0178, 16, 4, 23, 0x010, 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPINOR, "top_spinor", + spinor_parents, 0x0170, 0x0174, 0x0178, 24, 2, 31, 0x010, 19), + /* + * CLK_CFG_29 + * top_ulposc/top_ulposc_core/top_srck are clock source of always on co-processor, + * should not be closed by Linux. + */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_DVIO_DGI_REF, "top_dvio_dgi_ref", + dvio_dgi_ref_parents, 0x017C, 0x0180, 0x0184, 0, 3, 7, 0x010, 20), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC, "top_ulposc", + ulposc_parents, 0x017C, 0x0180, 0x0184, 8, 2, 15, 0x010, 21, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_ULPOSC_CORE, "top_ulposc_core", + ulposc_core_parents, 0x017C, 0x0180, 0x0184, 16, 2, 23, 0x010, 22, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SRCK, "top_srck", + srck_parents, 0x017C, 0x0180, 0x0184, 24, 1, 31, 0x010, 23, CLK_IS_CRITICAL), + /* + * the clocks in CLK_CFG_30 ~ 37 are backup clock source, no need to handled + * by Linux. + */ +}; + +static const struct mtk_composite top_adj_divs[] = { + DIV_GATE(CLK_TOP_APLL12_DIV0, "apll12_div0", "top_i2si1_mck", 0x0320, 0, 0x0328, 8, 0), + DIV_GATE(CLK_TOP_APLL12_DIV1, "apll12_div1", "top_i2si2_mck", 0x0320, 1, 0x0328, 8, 8), + DIV_GATE(CLK_TOP_APLL12_DIV2, "apll12_div2", "top_i2so1_mck", 0x0320, 2, 0x0328, 8, 16), + DIV_GATE(CLK_TOP_APLL12_DIV3, "apll12_div3", "top_i2so2_mck", 0x0320, 3, 0x0328, 8, 24), + DIV_GATE(CLK_TOP_APLL12_DIV4, "apll12_div4", "top_aud_iec_clk", 0x0320, 4, 0x0334, 8, 0), + /* apll12_div5 ~ 8 are not used in MT8195. */ + DIV_GATE(CLK_TOP_APLL12_DIV9, "apll12_div9", "top_dptx_mck", 0x0320, 9, 0x0338, 8, 8), +}; + +static const struct mtk_gate_regs top0_cg_regs = { + .set_ofs = 0x238, + .clr_ofs = 0x238, + .sta_ofs = 0x238, +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x250, + .clr_ofs = 0x250, + .sta_ofs = 0x250, +}; + +#define GATE_TOP0_FLAGS(_id, _name, _parent, _shift, _flag) \ + GATE_MTK_FLAGS(_id, _name, _parent, &top0_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr_inv, _flag) + +#define GATE_TOP0(_id, _name, _parent, _shift) \ + GATE_TOP0_FLAGS(_id, _name, _parent, _shift, 0) + +#define GATE_TOP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate top_clks[] = { + /* TOP0 */ + GATE_TOP0(CLK_TOP_CFG_VPP0, "cfg_vpp0", "top_vpp", 0), + GATE_TOP0(CLK_TOP_CFG_VPP1, "cfg_vpp1", "top_vpp", 1), + GATE_TOP0(CLK_TOP_CFG_VDO0, "cfg_vdo0", "top_vpp", 2), + GATE_TOP0(CLK_TOP_CFG_VDO1, "cfg_vdo1", "top_vpp", 3), + GATE_TOP0(CLK_TOP_CFG_UNIPLL_SES, "cfg_unipll_ses", "univpll_d2", 4), + GATE_TOP0(CLK_TOP_CFG_26M_VPP0, "cfg_26m_vpp0", "clk26m", 5), + GATE_TOP0(CLK_TOP_CFG_26M_VPP1, "cfg_26m_vpp1", "clk26m", 6), + GATE_TOP0(CLK_TOP_CFG_26M_AUD, "cfg_26m_aud", "clk26m", 9), + /* + * cfg_axi_east, cfg_axi_east_north, cfg_axi_north and cfg_axi_south + * are peripheral bus clock branches. + */ + GATE_TOP0_FLAGS(CLK_TOP_CFG_AXI_EAST, "cfg_axi_east", "top_axi", 10, CLK_IS_CRITICAL), + GATE_TOP0_FLAGS(CLK_TOP_CFG_AXI_EAST_NORTH, "cfg_axi_east_north", "top_axi", 11, + CLK_IS_CRITICAL), + GATE_TOP0_FLAGS(CLK_TOP_CFG_AXI_NORTH, "cfg_axi_north", "top_axi", 12, CLK_IS_CRITICAL), + GATE_TOP0_FLAGS(CLK_TOP_CFG_AXI_SOUTH, "cfg_axi_south", "top_axi", 13, CLK_IS_CRITICAL), + GATE_TOP0(CLK_TOP_CFG_EXT_TEST, "cfg_ext_test", "msdcpll_d2", 15), + /* TOP1 */ + GATE_TOP1(CLK_TOP_SSUSB_REF, "ssusb_ref", "clk26m", 0), + GATE_TOP1(CLK_TOP_SSUSB_PHY_REF, "ssusb_phy_ref", "clk26m", 1), + GATE_TOP1(CLK_TOP_SSUSB_P1_REF, "ssusb_p1_ref", "clk26m", 2), + GATE_TOP1(CLK_TOP_SSUSB_PHY_P1_REF, "ssusb_phy_p1_ref", "clk26m", 3), + GATE_TOP1(CLK_TOP_SSUSB_P2_REF, "ssusb_p2_ref", "clk26m", 4), + GATE_TOP1(CLK_TOP_SSUSB_PHY_P2_REF, "ssusb_phy_p2_ref", "clk26m", 5), + GATE_TOP1(CLK_TOP_SSUSB_P3_REF, "ssusb_p3_ref", "clk26m", 6), + GATE_TOP1(CLK_TOP_SSUSB_PHY_P3_REF, "ssusb_phy_p3_ref", "clk26m", 7), +}; + +static const struct of_device_id of_match_clk_mt8195_topck[] = { + { .compatible = "mediatek,mt8195-topckgen", }, + {} +}; + +/* Register mux notifier for MFG mux */ +static int clk_mt8195_reg_mfg_mux_notifier(struct device *dev, struct clk *clk) +{ + struct mtk_mux_nb *mfg_mux_nb; + + mfg_mux_nb = devm_kzalloc(dev, sizeof(*mfg_mux_nb), GFP_KERNEL); + if (!mfg_mux_nb) + return -ENOMEM; + + mfg_mux_nb->ops = &clk_mux_ops; + mfg_mux_nb->bypass_index = 0; /* Bypass to TOP_MFG_CORE_TMP */ + + return devm_mtk_clk_mux_notifier_register(dev, clk, mfg_mux_nb); +} + +static int clk_mt8195_topck_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *top_clk_data; + struct device_node *node = pdev->dev.of_node; + struct clk_hw *hw; + int r; + void __iomem *base; + + top_clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!top_clk_data) + return -ENOMEM; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) { + r = PTR_ERR(base); + goto free_top_data; + } + + r = mtk_clk_register_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), + top_clk_data); + if (r) + goto free_top_data; + + r = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + if (r) + goto unregister_fixed_clks; + + r = mtk_clk_register_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), node, + &mt8195_clk_lock, top_clk_data); + if (r) + goto unregister_factors; + + hw = devm_clk_hw_register_mux(&pdev->dev, "mfg_ck_fast_ref", mfg_fast_parents, + ARRAY_SIZE(mfg_fast_parents), CLK_SET_RATE_PARENT, + (base + 0x250), 8, 1, 0, &mt8195_clk_lock); + if (IS_ERR(hw)) { + r = PTR_ERR(hw); + goto unregister_muxes; + } + top_clk_data->hws[CLK_TOP_MFG_CK_FAST_REF] = hw; + + r = clk_mt8195_reg_mfg_mux_notifier(&pdev->dev, + top_clk_data->hws[CLK_TOP_MFG_CK_FAST_REF]->clk); + if (r) + goto unregister_muxes; + + r = mtk_clk_register_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), base, + &mt8195_clk_lock, top_clk_data); + if (r) + goto unregister_muxes; + + r = mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), top_clk_data); + if (r) + goto unregister_composite_divs; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, top_clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, top_clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(top_clks, ARRAY_SIZE(top_clks), top_clk_data); +unregister_composite_divs: + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), top_clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), top_clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); +free_top_data: + mtk_free_clk_data(top_clk_data); + return r; +} + +static int clk_mt8195_topck_remove(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *top_clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_gates(top_clks, ARRAY_SIZE(top_clks), top_clk_data); + mtk_clk_unregister_composites(top_adj_divs, ARRAY_SIZE(top_adj_divs), top_clk_data); + mtk_clk_unregister_muxes(top_mtk_muxes, ARRAY_SIZE(top_mtk_muxes), top_clk_data); + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), top_clk_data); + mtk_clk_unregister_fixed_clks(top_fixed_clks, ARRAY_SIZE(top_fixed_clks), top_clk_data); + mtk_free_clk_data(top_clk_data); + + return 0; +} + +static struct platform_driver clk_mt8195_topck_drv = { + .probe = clk_mt8195_topck_probe, + .remove = clk_mt8195_topck_remove, + .driver = { + .name = "clk-mt8195-topck", + .of_match_table = of_match_clk_mt8195_topck, + }, +}; +builtin_platform_driver(clk_mt8195_topck_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-vdec.c b/drivers/clk/mediatek/clk-mt8195-vdec.c new file mode 100644 index 000000000..a1446b666 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-vdec.c @@ -0,0 +1,105 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x200, + .clr_ofs = 0x204, + .sta_ofs = 0x200, +}; + +static const struct mtk_gate_regs vdec2_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_VDEC, "vdec_vdec", "top_vdec", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LAT, "vdec_lat", "top_vdec", 0), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_LARB1, "vdec_larb1", "top_vdec", 0), +}; + +static const struct mtk_gate vdec_core1_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_CORE1_VDEC, "vdec_core1_vdec", "top_vdec", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_CORE1_LAT, "vdec_core1_lat", "top_vdec", 0), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_CORE1_LARB1, "vdec_core1_larb1", "top_vdec", 0), +}; + +static const struct mtk_gate vdec_soc_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_SOC_VDEC, "vdec_soc_vdec", "top_vdec", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_SOC_LAT, "vdec_soc_lat", "top_vdec", 0), + /* VDEC2 */ + GATE_VDEC2(CLK_VDEC_SOC_LARB1, "vdec_soc_larb1", "top_vdec", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct mtk_clk_desc vdec_core1_desc = { + .clks = vdec_core1_clks, + .num_clks = ARRAY_SIZE(vdec_core1_clks), +}; + +static const struct mtk_clk_desc vdec_soc_desc = { + .clks = vdec_soc_clks, + .num_clks = ARRAY_SIZE(vdec_soc_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_vdec[] = { + { + .compatible = "mediatek,mt8195-vdecsys", + .data = &vdec_desc, + }, { + .compatible = "mediatek,mt8195-vdecsys_core1", + .data = &vdec_core1_desc, + }, { + .compatible = "mediatek,mt8195-vdecsys_soc", + .data = &vdec_soc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-vdec", + .of_match_table = of_match_clk_mt8195_vdec, + }, +}; +builtin_platform_driver(clk_mt8195_vdec_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-vdo0.c b/drivers/clk/mediatek/clk-mt8195-vdo0.c new file mode 100644 index 000000000..07b46bfd5 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-vdo0.c @@ -0,0 +1,146 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs vdo0_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs vdo0_1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +static const struct mtk_gate_regs vdo0_2_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +#define GATE_VDO0_0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo0_0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO0_1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo0_1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO0_2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo0_2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO0_2_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &vdo0_2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flags) + +static const struct mtk_gate vdo0_clks[] = { + /* VDO0_0 */ + GATE_VDO0_0(CLK_VDO0_DISP_OVL0, "vdo0_disp_ovl0", "top_vpp", 0), + GATE_VDO0_0(CLK_VDO0_DISP_COLOR0, "vdo0_disp_color0", "top_vpp", 2), + GATE_VDO0_0(CLK_VDO0_DISP_COLOR1, "vdo0_disp_color1", "top_vpp", 3), + GATE_VDO0_0(CLK_VDO0_DISP_CCORR0, "vdo0_disp_ccorr0", "top_vpp", 4), + GATE_VDO0_0(CLK_VDO0_DISP_CCORR1, "vdo0_disp_ccorr1", "top_vpp", 5), + GATE_VDO0_0(CLK_VDO0_DISP_AAL0, "vdo0_disp_aal0", "top_vpp", 6), + GATE_VDO0_0(CLK_VDO0_DISP_AAL1, "vdo0_disp_aal1", "top_vpp", 7), + GATE_VDO0_0(CLK_VDO0_DISP_GAMMA0, "vdo0_disp_gamma0", "top_vpp", 8), + GATE_VDO0_0(CLK_VDO0_DISP_GAMMA1, "vdo0_disp_gamma1", "top_vpp", 9), + GATE_VDO0_0(CLK_VDO0_DISP_DITHER0, "vdo0_disp_dither0", "top_vpp", 10), + GATE_VDO0_0(CLK_VDO0_DISP_DITHER1, "vdo0_disp_dither1", "top_vpp", 11), + GATE_VDO0_0(CLK_VDO0_DISP_OVL1, "vdo0_disp_ovl1", "top_vpp", 16), + GATE_VDO0_0(CLK_VDO0_DISP_WDMA0, "vdo0_disp_wdma0", "top_vpp", 17), + GATE_VDO0_0(CLK_VDO0_DISP_WDMA1, "vdo0_disp_wdma1", "top_vpp", 18), + GATE_VDO0_0(CLK_VDO0_DISP_RDMA0, "vdo0_disp_rdma0", "top_vpp", 19), + GATE_VDO0_0(CLK_VDO0_DISP_RDMA1, "vdo0_disp_rdma1", "top_vpp", 20), + GATE_VDO0_0(CLK_VDO0_DSI0, "vdo0_dsi0", "top_vpp", 21), + GATE_VDO0_0(CLK_VDO0_DSI1, "vdo0_dsi1", "top_vpp", 22), + GATE_VDO0_0(CLK_VDO0_DSC_WRAP0, "vdo0_dsc_wrap0", "top_vpp", 23), + GATE_VDO0_0(CLK_VDO0_VPP_MERGE0, "vdo0_vpp_merge0", "top_vpp", 24), + GATE_VDO0_0(CLK_VDO0_DP_INTF0, "vdo0_dp_intf0", "top_vpp", 25), + GATE_VDO0_0(CLK_VDO0_DISP_MUTEX0, "vdo0_disp_mutex0", "top_vpp", 26), + GATE_VDO0_0(CLK_VDO0_DISP_IL_ROT0, "vdo0_disp_il_rot0", "top_vpp", 27), + GATE_VDO0_0(CLK_VDO0_APB_BUS, "vdo0_apb_bus", "top_vpp", 28), + GATE_VDO0_0(CLK_VDO0_FAKE_ENG0, "vdo0_fake_eng0", "top_vpp", 29), + GATE_VDO0_0(CLK_VDO0_FAKE_ENG1, "vdo0_fake_eng1", "top_vpp", 30), + /* VDO0_1 */ + GATE_VDO0_1(CLK_VDO0_DL_ASYNC0, "vdo0_dl_async0", "top_vpp", 0), + GATE_VDO0_1(CLK_VDO0_DL_ASYNC1, "vdo0_dl_async1", "top_vpp", 1), + GATE_VDO0_1(CLK_VDO0_DL_ASYNC2, "vdo0_dl_async2", "top_vpp", 2), + GATE_VDO0_1(CLK_VDO0_DL_ASYNC3, "vdo0_dl_async3", "top_vpp", 3), + GATE_VDO0_1(CLK_VDO0_DL_ASYNC4, "vdo0_dl_async4", "top_vpp", 4), + GATE_VDO0_1(CLK_VDO0_DISP_MONITOR0, "vdo0_disp_monitor0", "top_vpp", 5), + GATE_VDO0_1(CLK_VDO0_DISP_MONITOR1, "vdo0_disp_monitor1", "top_vpp", 6), + GATE_VDO0_1(CLK_VDO0_DISP_MONITOR2, "vdo0_disp_monitor2", "top_vpp", 7), + GATE_VDO0_1(CLK_VDO0_DISP_MONITOR3, "vdo0_disp_monitor3", "top_vpp", 8), + GATE_VDO0_1(CLK_VDO0_DISP_MONITOR4, "vdo0_disp_monitor4", "top_vpp", 9), + GATE_VDO0_1(CLK_VDO0_SMI_GALS, "vdo0_smi_gals", "top_vpp", 10), + GATE_VDO0_1(CLK_VDO0_SMI_COMMON, "vdo0_smi_common", "top_vpp", 11), + GATE_VDO0_1(CLK_VDO0_SMI_EMI, "vdo0_smi_emi", "top_vpp", 12), + GATE_VDO0_1(CLK_VDO0_SMI_IOMMU, "vdo0_smi_iommu", "top_vpp", 13), + GATE_VDO0_1(CLK_VDO0_SMI_LARB, "vdo0_smi_larb", "top_vpp", 14), + GATE_VDO0_1(CLK_VDO0_SMI_RSI, "vdo0_smi_rsi", "top_vpp", 15), + /* VDO0_2 */ + GATE_VDO0_2(CLK_VDO0_DSI0_DSI, "vdo0_dsi0_dsi", "top_dsi_occ", 0), + GATE_VDO0_2(CLK_VDO0_DSI1_DSI, "vdo0_dsi1_dsi", "top_dsi_occ", 8), + GATE_VDO0_2_FLAGS(CLK_VDO0_DP_INTF0_DP_INTF, "vdo0_dp_intf0_dp_intf", + "top_edp", 16, CLK_SET_RATE_PARENT), +}; + +static int clk_mt8195_vdo0_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VDO0_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); + if (r) + goto free_vdo0_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); +free_vdo0_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8195_vdo0_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(vdo0_clks, ARRAY_SIZE(vdo0_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8195_vdo0_drv = { + .probe = clk_mt8195_vdo0_probe, + .remove = clk_mt8195_vdo0_remove, + .driver = { + .name = "clk-mt8195-vdo0", + }, +}; +builtin_platform_driver(clk_mt8195_vdo0_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-vdo1.c b/drivers/clk/mediatek/clk-mt8195-vdo1.c new file mode 100644 index 000000000..835335b9d --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-vdo1.c @@ -0,0 +1,173 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs vdo1_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs vdo1_1_cg_regs = { + .set_ofs = 0x124, + .clr_ofs = 0x128, + .sta_ofs = 0x120, +}; + +static const struct mtk_gate_regs vdo1_2_cg_regs = { + .set_ofs = 0x134, + .clr_ofs = 0x138, + .sta_ofs = 0x130, +}; + +static const struct mtk_gate_regs vdo1_3_cg_regs = { + .set_ofs = 0x144, + .clr_ofs = 0x148, + .sta_ofs = 0x140, +}; + +static const struct mtk_gate_regs vdo1_4_cg_regs = { + .set_ofs = 0x400, + .clr_ofs = 0x400, + .sta_ofs = 0x400, +}; + +#define GATE_VDO1_0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO1_1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO1_2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO1_2_FLAGS(_id, _name, _parent, _shift, _flags) \ + GATE_MTK_FLAGS(_id, _name, _parent, &vdo1_2_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr, _flags) + +#define GATE_VDO1_3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_3_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VDO1_4(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdo1_4_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate vdo1_clks[] = { + /* VDO1_0 */ + GATE_VDO1_0(CLK_VDO1_SMI_LARB2, "vdo1_smi_larb2", "top_vpp", 0), + GATE_VDO1_0(CLK_VDO1_SMI_LARB3, "vdo1_smi_larb3", "top_vpp", 1), + GATE_VDO1_0(CLK_VDO1_GALS, "vdo1_gals", "top_vpp", 2), + GATE_VDO1_0(CLK_VDO1_FAKE_ENG0, "vdo1_fake_eng0", "top_vpp", 3), + GATE_VDO1_0(CLK_VDO1_FAKE_ENG, "vdo1_fake_eng", "top_vpp", 4), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA0, "vdo1_mdp_rdma0", "top_vpp", 5), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA1, "vdo1_mdp_rdma1", "top_vpp", 6), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA2, "vdo1_mdp_rdma2", "top_vpp", 7), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA3, "vdo1_mdp_rdma3", "top_vpp", 8), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE0, "vdo1_vpp_merge0", "top_vpp", 9), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE1, "vdo1_vpp_merge1", "top_vpp", 10), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE2, "vdo1_vpp_merge2", "top_vpp", 11), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE3, "vdo1_vpp_merge3", "top_vpp", 12), + GATE_VDO1_0(CLK_VDO1_VPP_MERGE4, "vdo1_vpp_merge4", "top_vpp", 13), + GATE_VDO1_0(CLK_VDO1_VPP2_TO_VDO1_DL_ASYNC, "vdo1_vpp2_to_vdo1_dl_async", "top_vpp", 14), + GATE_VDO1_0(CLK_VDO1_VPP3_TO_VDO1_DL_ASYNC, "vdo1_vpp3_to_vdo1_dl_async", "top_vpp", 15), + GATE_VDO1_0(CLK_VDO1_DISP_MUTEX, "vdo1_disp_mutex", "top_vpp", 16), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA4, "vdo1_mdp_rdma4", "top_vpp", 17), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA5, "vdo1_mdp_rdma5", "top_vpp", 18), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA6, "vdo1_mdp_rdma6", "top_vpp", 19), + GATE_VDO1_0(CLK_VDO1_MDP_RDMA7, "vdo1_mdp_rdma7", "top_vpp", 20), + GATE_VDO1_0(CLK_VDO1_DP_INTF0_MM, "vdo1_dp_intf0_mm", "top_vpp", 21), + GATE_VDO1_0(CLK_VDO1_DPI0_MM, "vdo1_dpi0_mm", "top_vpp", 22), + GATE_VDO1_0(CLK_VDO1_DPI1_MM, "vdo1_dpi1_mm", "top_vpp", 23), + GATE_VDO1_0(CLK_VDO1_DISP_MONITOR, "vdo1_disp_monitor", "top_vpp", 24), + GATE_VDO1_0(CLK_VDO1_MERGE0_DL_ASYNC, "vdo1_merge0_dl_async", "top_vpp", 25), + GATE_VDO1_0(CLK_VDO1_MERGE1_DL_ASYNC, "vdo1_merge1_dl_async", "top_vpp", 26), + GATE_VDO1_0(CLK_VDO1_MERGE2_DL_ASYNC, "vdo1_merge2_dl_async", "top_vpp", 27), + GATE_VDO1_0(CLK_VDO1_MERGE3_DL_ASYNC, "vdo1_merge3_dl_async", "top_vpp", 28), + GATE_VDO1_0(CLK_VDO1_MERGE4_DL_ASYNC, "vdo1_merge4_dl_async", "top_vpp", 29), + GATE_VDO1_0(CLK_VDO1_VDO0_DSC_TO_VDO1_DL_ASYNC, "vdo1_vdo0_dsc_to_vdo1_dl_async", + "top_vpp", 30), + GATE_VDO1_0(CLK_VDO1_VDO0_MERGE_TO_VDO1_DL_ASYNC, "vdo1_vdo0_merge_to_vdo1_dl_async", + "top_vpp", 31), + /* VDO1_1 */ + GATE_VDO1_1(CLK_VDO1_HDR_VDO_FE0, "vdo1_hdr_vdo_fe0", "top_vpp", 0), + GATE_VDO1_1(CLK_VDO1_HDR_GFX_FE0, "vdo1_hdr_gfx_fe0", "top_vpp", 1), + GATE_VDO1_1(CLK_VDO1_HDR_VDO_BE, "vdo1_hdr_vdo_be", "top_vpp", 2), + GATE_VDO1_1(CLK_VDO1_HDR_VDO_FE1, "vdo1_hdr_vdo_fe1", "top_vpp", 16), + GATE_VDO1_1(CLK_VDO1_HDR_GFX_FE1, "vdo1_hdr_gfx_fe1", "top_vpp", 17), + GATE_VDO1_1(CLK_VDO1_DISP_MIXER, "vdo1_disp_mixer", "top_vpp", 18), + GATE_VDO1_1(CLK_VDO1_HDR_VDO_FE0_DL_ASYNC, "vdo1_hdr_vdo_fe0_dl_async", "top_vpp", 19), + GATE_VDO1_1(CLK_VDO1_HDR_VDO_FE1_DL_ASYNC, "vdo1_hdr_vdo_fe1_dl_async", "top_vpp", 20), + GATE_VDO1_1(CLK_VDO1_HDR_GFX_FE0_DL_ASYNC, "vdo1_hdr_gfx_fe0_dl_async", "top_vpp", 21), + GATE_VDO1_1(CLK_VDO1_HDR_GFX_FE1_DL_ASYNC, "vdo1_hdr_gfx_fe1_dl_async", "top_vpp", 22), + GATE_VDO1_1(CLK_VDO1_HDR_VDO_BE_DL_ASYNC, "vdo1_hdr_vdo_be_dl_async", "top_vpp", 23), + /* VDO1_2 */ + GATE_VDO1_2(CLK_VDO1_DPI0, "vdo1_dpi0", "top_vpp", 0), + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPI0, "vdo1_disp_monitor_dpi0", "top_vpp", 1), + GATE_VDO1_2(CLK_VDO1_DPI1, "vdo1_dpi1", "top_vpp", 8), + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPI1, "vdo1_disp_monitor_dpi1", "top_vpp", 9), + GATE_VDO1_2_FLAGS(CLK_VDO1_DPINTF, "vdo1_dpintf", "top_dp", 16, CLK_SET_RATE_PARENT), + GATE_VDO1_2(CLK_VDO1_DISP_MONITOR_DPINTF, "vdo1_disp_monitor_dpintf", "top_vpp", 17), + /* VDO1_3 */ + GATE_VDO1_3(CLK_VDO1_26M_SLOW, "vdo1_26m_slow", "clk26m", 8), + /* VDO1_4 */ + GATE_VDO1_4(CLK_VDO1_DPI1_HDMI, "vdo1_dpi1_hdmi", "hdmi_txpll", 0), +}; + +static int clk_mt8195_vdo1_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_VDO1_NR_CLK); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates(node, vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); + if (r) + goto free_vdo1_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_gates; + + platform_set_drvdata(pdev, clk_data); + + return r; + +unregister_gates: + mtk_clk_unregister_gates(vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); +free_vdo1_data: + mtk_free_clk_data(clk_data); + return r; +} + +static int clk_mt8195_vdo1_remove(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + + of_clk_del_provider(node); + mtk_clk_unregister_gates(vdo1_clks, ARRAY_SIZE(vdo1_clks), clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} + +static struct platform_driver clk_mt8195_vdo1_drv = { + .probe = clk_mt8195_vdo1_probe, + .remove = clk_mt8195_vdo1_remove, + .driver = { + .name = "clk-mt8195-vdo1", + }, +}; +builtin_platform_driver(clk_mt8195_vdo1_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-venc.c b/drivers/clk/mediatek/clk-mt8195-venc.c new file mode 100644 index 000000000..622f57804 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-venc.c @@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + GATE_VENC(CLK_VENC_LARB, "venc_larb", "top_venc", 0), + GATE_VENC(CLK_VENC_VENC, "venc_venc", "top_venc", 4), + GATE_VENC(CLK_VENC_JPGENC, "venc_jpgenc", "top_venc", 8), + GATE_VENC(CLK_VENC_JPGDEC, "venc_jpgdec", "top_venc", 12), + GATE_VENC(CLK_VENC_JPGDEC_C1, "venc_jpgdec_c1", "top_venc", 16), + GATE_VENC(CLK_VENC_GALS, "venc_gals", "top_venc", 28), +}; + +static const struct mtk_gate venc_core1_clks[] = { + GATE_VENC(CLK_VENC_CORE1_LARB, "venc_core1_larb", "top_venc", 0), + GATE_VENC(CLK_VENC_CORE1_VENC, "venc_core1_venc", "top_venc", 4), + GATE_VENC(CLK_VENC_CORE1_JPGENC, "venc_core1_jpgenc", "top_venc", 8), + GATE_VENC(CLK_VENC_CORE1_JPGDEC, "venc_core1_jpgdec", "top_venc", 12), + GATE_VENC(CLK_VENC_CORE1_JPGDEC_C1, "venc_core1_jpgdec_c1", "top_venc", 16), + GATE_VENC(CLK_VENC_CORE1_GALS, "venc_core1_gals", "top_venc", 28), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct mtk_clk_desc venc_core1_desc = { + .clks = venc_core1_clks, + .num_clks = ARRAY_SIZE(venc_core1_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_venc[] = { + { + .compatible = "mediatek,mt8195-vencsys", + .data = &venc_desc, + }, { + .compatible = "mediatek,mt8195-vencsys_core1", + .data = &venc_core1_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-venc", + .of_match_table = of_match_clk_mt8195_venc, + }, +}; +builtin_platform_driver(clk_mt8195_venc_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-vpp0.c b/drivers/clk/mediatek/clk-mt8195-vpp0.c new file mode 100644 index 000000000..bf2939c3a --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-vpp0.c @@ -0,0 +1,111 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs vpp0_0_cg_regs = { + .set_ofs = 0x24, + .clr_ofs = 0x28, + .sta_ofs = 0x20, +}; + +static const struct mtk_gate_regs vpp0_1_cg_regs = { + .set_ofs = 0x30, + .clr_ofs = 0x34, + .sta_ofs = 0x2c, +}; + +static const struct mtk_gate_regs vpp0_2_cg_regs = { + .set_ofs = 0x3c, + .clr_ofs = 0x40, + .sta_ofs = 0x38, +}; + +#define GATE_VPP0_0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vpp0_0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VPP0_1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vpp0_1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VPP0_2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vpp0_2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate vpp0_clks[] = { + /* VPP0_0 */ + GATE_VPP0_0(CLK_VPP0_MDP_FG, "vpp0_mdp_fg", "top_vpp", 1), + GATE_VPP0_0(CLK_VPP0_STITCH, "vpp0_stitch", "top_vpp", 2), + GATE_VPP0_0(CLK_VPP0_PADDING, "vpp0_padding", "top_vpp", 7), + GATE_VPP0_0(CLK_VPP0_MDP_TCC, "vpp0_mdp_tcc", "top_vpp", 8), + GATE_VPP0_0(CLK_VPP0_WARP0_ASYNC_TX, "vpp0_warp0_async_tx", "top_vpp", 10), + GATE_VPP0_0(CLK_VPP0_WARP1_ASYNC_TX, "vpp0_warp1_async_tx", "top_vpp", 11), + GATE_VPP0_0(CLK_VPP0_MUTEX, "vpp0_mutex", "top_vpp", 13), + GATE_VPP0_0(CLK_VPP0_VPP02VPP1_RELAY, "vpp0_vpp02vpp1_relay", "top_vpp", 14), + GATE_VPP0_0(CLK_VPP0_VPP12VPP0_ASYNC, "vpp0_vpp12vpp0_async", "top_vpp", 15), + GATE_VPP0_0(CLK_VPP0_MMSYSRAM_TOP, "vpp0_mmsysram_top", "top_vpp", 16), + GATE_VPP0_0(CLK_VPP0_MDP_AAL, "vpp0_mdp_aal", "top_vpp", 17), + GATE_VPP0_0(CLK_VPP0_MDP_RSZ, "vpp0_mdp_rsz", "top_vpp", 18), + /* VPP0_1 */ + GATE_VPP0_1(CLK_VPP0_SMI_COMMON, "vpp0_smi_common", "top_vpp", 0), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_LARB0, "vpp0_gals_vdo0_larb0", "top_vpp", 1), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_LARB1, "vpp0_gals_vdo0_larb1", "top_vpp", 2), + GATE_VPP0_1(CLK_VPP0_GALS_VENCSYS, "vpp0_gals_vencsys", "top_vpp", 3), + GATE_VPP0_1(CLK_VPP0_GALS_VENCSYS_CORE1, "vpp0_gals_vencsys_core1", "top_vpp", 4), + GATE_VPP0_1(CLK_VPP0_GALS_INFRA, "vpp0_gals_infra", "top_vpp", 5), + GATE_VPP0_1(CLK_VPP0_GALS_CAMSYS, "vpp0_gals_camsys", "top_vpp", 6), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_LARB5, "vpp0_gals_vpp1_larb5", "top_vpp", 7), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_LARB6, "vpp0_gals_vpp1_larb6", "top_vpp", 8), + GATE_VPP0_1(CLK_VPP0_SMI_REORDER, "vpp0_smi_reorder", "top_vpp", 9), + GATE_VPP0_1(CLK_VPP0_SMI_IOMMU, "vpp0_smi_iommu", "top_vpp", 10), + GATE_VPP0_1(CLK_VPP0_GALS_IMGSYS_CAMSYS, "vpp0_gals_imgsys_camsys", "top_vpp", 11), + GATE_VPP0_1(CLK_VPP0_MDP_RDMA, "vpp0_mdp_rdma", "top_vpp", 12), + GATE_VPP0_1(CLK_VPP0_MDP_WROT, "vpp0_mdp_wrot", "top_vpp", 13), + GATE_VPP0_1(CLK_VPP0_GALS_EMI0_EMI1, "vpp0_gals_emi0_emi1", "top_vpp", 16), + GATE_VPP0_1(CLK_VPP0_SMI_SUB_COMMON_REORDER, "vpp0_smi_sub_common_reorder", "top_vpp", 17), + GATE_VPP0_1(CLK_VPP0_SMI_RSI, "vpp0_smi_rsi", "top_vpp", 18), + GATE_VPP0_1(CLK_VPP0_SMI_COMMON_LARB4, "vpp0_smi_common_larb4", "top_vpp", 19), + GATE_VPP0_1(CLK_VPP0_GALS_VDEC_VDEC_CORE1, "vpp0_gals_vdec_vdec_core1", "top_vpp", 20), + GATE_VPP0_1(CLK_VPP0_GALS_VPP1_WPE, "vpp0_gals_vpp1_wpe", "top_vpp", 21), + GATE_VPP0_1(CLK_VPP0_GALS_VDO0_VDO1_VENCSYS_CORE1, "vpp0_gals_vdo0_vdo1_vencsys_core1", + "top_vpp", 22), + GATE_VPP0_1(CLK_VPP0_FAKE_ENG, "vpp0_fake_eng", "top_vpp", 23), + GATE_VPP0_1(CLK_VPP0_MDP_HDR, "vpp0_mdp_hdr", "top_vpp", 24), + GATE_VPP0_1(CLK_VPP0_MDP_TDSHP, "vpp0_mdp_tdshp", "top_vpp", 25), + GATE_VPP0_1(CLK_VPP0_MDP_COLOR, "vpp0_mdp_color", "top_vpp", 26), + GATE_VPP0_1(CLK_VPP0_MDP_OVL, "vpp0_mdp_ovl", "top_vpp", 27), + /* VPP0_2 */ + GATE_VPP0_2(CLK_VPP0_WARP0_RELAY, "vpp0_warp0_relay", "top_wpe_vpp", 0), + GATE_VPP0_2(CLK_VPP0_WARP0_MDP_DL_ASYNC, "vpp0_warp0_mdp_dl_async", "top_wpe_vpp", 1), + GATE_VPP0_2(CLK_VPP0_WARP1_RELAY, "vpp0_warp1_relay", "top_wpe_vpp", 2), + GATE_VPP0_2(CLK_VPP0_WARP1_MDP_DL_ASYNC, "vpp0_warp1_mdp_dl_async", "top_wpe_vpp", 3), +}; + +static const struct mtk_clk_desc vpp0_desc = { + .clks = vpp0_clks, + .num_clks = ARRAY_SIZE(vpp0_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_vpp0[] = { + { + .compatible = "mediatek,mt8195-vppsys0", + .data = &vpp0_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_vpp0_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-vpp0", + .of_match_table = of_match_clk_mt8195_vpp0, + }, +}; +builtin_platform_driver(clk_mt8195_vpp0_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-vpp1.c b/drivers/clk/mediatek/clk-mt8195-vpp1.c new file mode 100644 index 000000000..ffd52c762 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-vpp1.c @@ -0,0 +1,109 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs vpp1_0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs vpp1_1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +#define GATE_VPP1_0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vpp1_0_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_VPP1_1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vpp1_1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate vpp1_clks[] = { + /* VPP1_0 */ + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_OVL, "vpp1_svpp1_mdp_ovl", "top_vpp", 0), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_TCC, "vpp1_svpp1_mdp_tcc", "top_vpp", 1), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_WROT, "vpp1_svpp1_mdp_wrot", "top_vpp", 2), + GATE_VPP1_0(CLK_VPP1_SVPP1_VPP_PAD, "vpp1_svpp1_vpp_pad", "top_vpp", 3), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_WROT, "vpp1_svpp2_mdp_wrot", "top_vpp", 4), + GATE_VPP1_0(CLK_VPP1_SVPP2_VPP_PAD, "vpp1_svpp2_vpp_pad", "top_vpp", 5), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_WROT, "vpp1_svpp3_mdp_wrot", "top_vpp", 6), + GATE_VPP1_0(CLK_VPP1_SVPP3_VPP_PAD, "vpp1_svpp3_vpp_pad", "top_vpp", 7), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_RDMA, "vpp1_svpp1_mdp_rdma", "top_vpp", 8), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_FG, "vpp1_svpp1_mdp_fg", "top_vpp", 9), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_RDMA, "vpp1_svpp2_mdp_rdma", "top_vpp", 10), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_FG, "vpp1_svpp2_mdp_fg", "top_vpp", 11), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_RDMA, "vpp1_svpp3_mdp_rdma", "top_vpp", 12), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_FG, "vpp1_svpp3_mdp_fg", "top_vpp", 13), + GATE_VPP1_0(CLK_VPP1_VPP_SPLIT, "vpp1_vpp_split", "top_vpp", 14), + GATE_VPP1_0(CLK_VPP1_SVPP2_VDO0_DL_RELAY, "vpp1_svpp2_vdo0_dl_relay", "top_vpp", 15), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_TDSHP, "vpp1_svpp1_mdp_tdshp", "top_vpp", 16), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_COLOR, "vpp1_svpp1_mdp_color", "top_vpp", 17), + GATE_VPP1_0(CLK_VPP1_SVPP3_VDO1_DL_RELAY, "vpp1_svpp3_vdo1_dl_relay", "top_vpp", 18), + GATE_VPP1_0(CLK_VPP1_SVPP2_VPP_MERGE, "vpp1_svpp2_vpp_merge", "top_vpp", 19), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_COLOR, "vpp1_svpp2_mdp_color", "top_vpp", 20), + GATE_VPP1_0(CLK_VPP1_VPPSYS1_GALS, "vpp1_vppsys1_gals", "top_vpp", 21), + GATE_VPP1_0(CLK_VPP1_SVPP3_VPP_MERGE, "vpp1_svpp3_vpp_merge", "top_vpp", 22), + GATE_VPP1_0(CLK_VPP1_SVPP3_MDP_COLOR, "vpp1_svpp3_mdp_color", "top_vpp", 23), + GATE_VPP1_0(CLK_VPP1_VPPSYS1_LARB, "vpp1_vppsys1_larb", "top_vpp", 24), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_RSZ, "vpp1_svpp1_mdp_rsz", "top_vpp", 25), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_HDR, "vpp1_svpp1_mdp_hdr", "top_vpp", 26), + GATE_VPP1_0(CLK_VPP1_SVPP1_MDP_AAL, "vpp1_svpp1_mdp_aal", "top_vpp", 27), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_HDR, "vpp1_svpp2_mdp_hdr", "top_vpp", 28), + GATE_VPP1_0(CLK_VPP1_SVPP2_MDP_AAL, "vpp1_svpp2_mdp_aal", "top_vpp", 29), + GATE_VPP1_0(CLK_VPP1_DL_ASYNC, "vpp1_dl_async", "top_vpp", 30), + GATE_VPP1_0(CLK_VPP1_LARB5_FAKE_ENG, "vpp1_larb5_fake_eng", "top_vpp", 31), + /* VPP1_1 */ + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_HDR, "vpp1_svpp3_mdp_hdr", "top_vpp", 0), + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_AAL, "vpp1_svpp3_mdp_aal", "top_vpp", 1), + GATE_VPP1_1(CLK_VPP1_SVPP2_VDO1_DL_RELAY, "vpp1_svpp2_vdo1_dl_relay", "top_vpp", 2), + GATE_VPP1_1(CLK_VPP1_LARB6_FAKE_ENG, "vpp1_larb6_fake_eng", "top_vpp", 3), + GATE_VPP1_1(CLK_VPP1_SVPP2_MDP_RSZ, "vpp1_svpp2_mdp_rsz", "top_vpp", 4), + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_RSZ, "vpp1_svpp3_mdp_rsz", "top_vpp", 5), + GATE_VPP1_1(CLK_VPP1_SVPP3_VDO0_DL_RELAY, "vpp1_svpp3_vdo0_dl_relay", "top_vpp", 6), + GATE_VPP1_1(CLK_VPP1_DISP_MUTEX, "vpp1_disp_mutex", "top_vpp", 7), + GATE_VPP1_1(CLK_VPP1_SVPP2_MDP_TDSHP, "vpp1_svpp2_mdp_tdshp", "top_vpp", 8), + GATE_VPP1_1(CLK_VPP1_SVPP3_MDP_TDSHP, "vpp1_svpp3_mdp_tdshp", "top_vpp", 9), + GATE_VPP1_1(CLK_VPP1_VPP0_DL1_RELAY, "vpp1_vpp0_dl1_relay", "top_vpp", 10), + GATE_VPP1_1(CLK_VPP1_HDMI_META, "vpp1_hdmi_meta", "hdmirx_p", 11), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_HDMI, "vpp1_vpp_split_hdmi", "hdmirx_p", 12), + GATE_VPP1_1(CLK_VPP1_DGI_IN, "vpp1_dgi_in", "in_dgi", 13), + GATE_VPP1_1(CLK_VPP1_DGI_OUT, "vpp1_dgi_out", "top_dgi_out", 14), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_DGI, "vpp1_vpp_split_dgi", "top_dgi_out", 15), + GATE_VPP1_1(CLK_VPP1_VPP0_DL_ASYNC, "vpp1_vpp0_dl_async", "top_vpp", 16), + GATE_VPP1_1(CLK_VPP1_VPP0_DL_RELAY, "vpp1_vpp0_dl_relay", "top_vpp", 17), + GATE_VPP1_1(CLK_VPP1_VPP_SPLIT_26M, "vpp1_vpp_split_26m", "clk26m", 26), +}; + +static const struct mtk_clk_desc vpp1_desc = { + .clks = vpp1_clks, + .num_clks = ARRAY_SIZE(vpp1_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_vpp1[] = { + { + .compatible = "mediatek,mt8195-vppsys1", + .data = &vpp1_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_vpp1_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-vpp1", + .of_match_table = of_match_clk_mt8195_vpp1, + }, +}; +builtin_platform_driver(clk_mt8195_vpp1_drv); diff --git a/drivers/clk/mediatek/clk-mt8195-wpe.c b/drivers/clk/mediatek/clk-mt8195-wpe.c new file mode 100644 index 000000000..b483fab10 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8195-wpe.c @@ -0,0 +1,144 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright (c) 2021 MediaTek Inc. +// Author: Chun-Jie Chen <chun-jie.chen@mediatek.com> + +#include "clk-gate.h" +#include "clk-mtk.h" + +#include <dt-bindings/clock/mt8195-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +static const struct mtk_gate_regs wpe_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs wpe_vpp0_cg_regs = { + .set_ofs = 0x58, + .clr_ofs = 0x58, + .sta_ofs = 0x58, +}; + +static const struct mtk_gate_regs wpe_vpp1_cg_regs = { + .set_ofs = 0x5c, + .clr_ofs = 0x5c, + .sta_ofs = 0x5c, +}; + +#define GATE_WPE(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wpe_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_WPE_VPP0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wpe_vpp0_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +#define GATE_WPE_VPP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &wpe_vpp1_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr_inv) + +static const struct mtk_gate wpe_clks[] = { + GATE_WPE(CLK_WPE_VPP0, "wpe_vpp0", "top_wpe_vpp", 16), + GATE_WPE(CLK_WPE_VPP1, "wpe_vpp1", "top_wpe_vpp", 17), + GATE_WPE(CLK_WPE_SMI_LARB7, "wpe_smi_larb7", "top_wpe_vpp", 18), + GATE_WPE(CLK_WPE_SMI_LARB8, "wpe_smi_larb8", "top_wpe_vpp", 19), + GATE_WPE(CLK_WPE_EVENT_TX, "wpe_event_tx", "top_wpe_vpp", 20), + GATE_WPE(CLK_WPE_SMI_LARB7_P, "wpe_smi_larb7_p", "top_wpe_vpp", 24), + GATE_WPE(CLK_WPE_SMI_LARB8_P, "wpe_smi_larb8_p", "top_wpe_vpp", 25), +}; + +static const struct mtk_gate wpe_vpp0_clks[] = { + /* WPE_VPP0 */ + GATE_WPE_VPP0(CLK_WPE_VPP0_VGEN, "wpe_vpp0_vgen", "top_img", 0), + GATE_WPE_VPP0(CLK_WPE_VPP0_EXT, "wpe_vpp0_ext", "top_img", 1), + GATE_WPE_VPP0(CLK_WPE_VPP0_VFC, "wpe_vpp0_vfc", "top_img", 2), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH0_TOP, "wpe_vpp0_cach0_top", "top_img", 3), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH0_DMA, "wpe_vpp0_cach0_dma", "top_img", 4), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH1_TOP, "wpe_vpp0_cach1_top", "top_img", 5), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH1_DMA, "wpe_vpp0_cach1_dma", "top_img", 6), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH2_TOP, "wpe_vpp0_cach2_top", "top_img", 7), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH2_DMA, "wpe_vpp0_cach2_dma", "top_img", 8), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH3_TOP, "wpe_vpp0_cach3_top", "top_img", 9), + GATE_WPE_VPP0(CLK_WPE_VPP0_CACH3_DMA, "wpe_vpp0_cach3_dma", "top_img", 10), + GATE_WPE_VPP0(CLK_WPE_VPP0_PSP, "wpe_vpp0_psp", "top_img", 11), + GATE_WPE_VPP0(CLK_WPE_VPP0_PSP2, "wpe_vpp0_psp2", "top_img", 12), + GATE_WPE_VPP0(CLK_WPE_VPP0_SYNC, "wpe_vpp0_sync", "top_img", 13), + GATE_WPE_VPP0(CLK_WPE_VPP0_C24, "wpe_vpp0_c24", "top_img", 14), + GATE_WPE_VPP0(CLK_WPE_VPP0_MDP_CROP, "wpe_vpp0_mdp_crop", "top_img", 15), + GATE_WPE_VPP0(CLK_WPE_VPP0_ISP_CROP, "wpe_vpp0_isp_crop", "top_img", 16), + GATE_WPE_VPP0(CLK_WPE_VPP0_TOP, "wpe_vpp0_top", "top_img", 17), + /* WPE_VPP1 */ + GATE_WPE_VPP1(CLK_WPE_VPP0_VECI, "wpe_vpp0_veci", "top_img", 0), + GATE_WPE_VPP1(CLK_WPE_VPP0_VEC2I, "wpe_vpp0_vec2i", "top_img", 1), + GATE_WPE_VPP1(CLK_WPE_VPP0_VEC3I, "wpe_vpp0_vec3i", "top_img", 2), + GATE_WPE_VPP1(CLK_WPE_VPP0_WPEO, "wpe_vpp0_wpeo", "top_img", 3), + GATE_WPE_VPP1(CLK_WPE_VPP0_MSKO, "wpe_vpp0_msko", "top_img", 4), +}; + +static const struct mtk_gate wpe_vpp1_clks[] = { + /* WPE_VPP0 */ + GATE_WPE_VPP0(CLK_WPE_VPP1_VGEN, "wpe_vpp1_vgen", "top_img", 0), + GATE_WPE_VPP0(CLK_WPE_VPP1_EXT, "wpe_vpp1_ext", "top_img", 1), + GATE_WPE_VPP0(CLK_WPE_VPP1_VFC, "wpe_vpp1_vfc", "top_img", 2), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH0_TOP, "wpe_vpp1_cach0_top", "top_img", 3), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH0_DMA, "wpe_vpp1_cach0_dma", "top_img", 4), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH1_TOP, "wpe_vpp1_cach1_top", "top_img", 5), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH1_DMA, "wpe_vpp1_cach1_dma", "top_img", 6), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH2_TOP, "wpe_vpp1_cach2_top", "top_img", 7), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH2_DMA, "wpe_vpp1_cach2_dma", "top_img", 8), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH3_TOP, "wpe_vpp1_cach3_top", "top_img", 9), + GATE_WPE_VPP0(CLK_WPE_VPP1_CACH3_DMA, "wpe_vpp1_cach3_dma", "top_img", 10), + GATE_WPE_VPP0(CLK_WPE_VPP1_PSP, "wpe_vpp1_psp", "top_img", 11), + GATE_WPE_VPP0(CLK_WPE_VPP1_PSP2, "wpe_vpp1_psp2", "top_img", 12), + GATE_WPE_VPP0(CLK_WPE_VPP1_SYNC, "wpe_vpp1_sync", "top_img", 13), + GATE_WPE_VPP0(CLK_WPE_VPP1_C24, "wpe_vpp1_c24", "top_img", 14), + GATE_WPE_VPP0(CLK_WPE_VPP1_MDP_CROP, "wpe_vpp1_mdp_crop", "top_img", 15), + GATE_WPE_VPP0(CLK_WPE_VPP1_ISP_CROP, "wpe_vpp1_isp_crop", "top_img", 16), + GATE_WPE_VPP0(CLK_WPE_VPP1_TOP, "wpe_vpp1_top", "top_img", 17), + /* WPE_VPP1 */ + GATE_WPE_VPP1(CLK_WPE_VPP1_VECI, "wpe_vpp1_veci", "top_img", 0), + GATE_WPE_VPP1(CLK_WPE_VPP1_VEC2I, "wpe_vpp1_vec2i", "top_img", 1), + GATE_WPE_VPP1(CLK_WPE_VPP1_VEC3I, "wpe_vpp1_vec3i", "top_img", 2), + GATE_WPE_VPP1(CLK_WPE_VPP1_WPEO, "wpe_vpp1_wpeo", "top_img", 3), + GATE_WPE_VPP1(CLK_WPE_VPP1_MSKO, "wpe_vpp1_msko", "top_img", 4), +}; + +static const struct mtk_clk_desc wpe_desc = { + .clks = wpe_clks, + .num_clks = ARRAY_SIZE(wpe_clks), +}; + +static const struct mtk_clk_desc wpe_vpp0_desc = { + .clks = wpe_vpp0_clks, + .num_clks = ARRAY_SIZE(wpe_vpp0_clks), +}; + +static const struct mtk_clk_desc wpe_vpp1_desc = { + .clks = wpe_vpp1_clks, + .num_clks = ARRAY_SIZE(wpe_vpp1_clks), +}; + +static const struct of_device_id of_match_clk_mt8195_wpe[] = { + { + .compatible = "mediatek,mt8195-wpesys", + .data = &wpe_desc, + }, { + .compatible = "mediatek,mt8195-wpesys_vpp0", + .data = &wpe_vpp0_desc, + }, { + .compatible = "mediatek,mt8195-wpesys_vpp1", + .data = &wpe_vpp1_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8195_wpe_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8195-wpe", + .of_match_table = of_match_clk_mt8195_wpe, + }, +}; +builtin_platform_driver(clk_mt8195_wpe_drv); diff --git a/drivers/clk/mediatek/clk-mt8365-apu.c b/drivers/clk/mediatek/clk-mt8365-apu.c new file mode 100644 index 000000000..91ffe89d9 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-apu.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs apu_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_APU(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &apu_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate apu_clks[] = { + GATE_APU(CLK_APU_AHB, "apu_ahb", "ifr_apu_axi", 5), + GATE_APU(CLK_APU_EDMA, "apu_edma", "apu_sel", 4), + GATE_APU(CLK_APU_IF_CK, "apu_if_ck", "apu_if_sel", 3), + GATE_APU(CLK_APU_JTAG, "apu_jtag", "clk26m", 2), + GATE_APU(CLK_APU_AXI, "apu_axi", "apu_sel", 1), + GATE_APU(CLK_APU_IPU_CK, "apu_ck", "apu_sel", 0), +}; + +static const struct mtk_clk_desc apu_desc = { + .clks = apu_clks, + .num_clks = ARRAY_SIZE(apu_clks), +}; + +static const struct of_device_id of_match_clk_mt8365_apu[] = { + { + .compatible = "mediatek,mt8365-apu", + .data = &apu_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8365_apu_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8365-apu", + .of_match_table = of_match_clk_mt8365_apu, + }, +}; +builtin_platform_driver(clk_mt8365_apu_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365-cam.c b/drivers/clk/mediatek/clk-mt8365-cam.c new file mode 100644 index 000000000..31d5b5cd6 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-cam.c @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs cam_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_CAM(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate cam_clks[] = { + GATE_CAM(CLK_CAM_LARB2, "cam_larb2", "mm_sel", 0), + GATE_CAM(CLK_CAM, "cam", "mm_sel", 6), + GATE_CAM(CLK_CAMTG, "camtg", "mm_sel", 7), + GATE_CAM(CLK_CAM_SENIF, "cam_senif", "mm_sel", 8), + GATE_CAM(CLK_CAMSV0, "camsv0", "mm_sel", 9), + GATE_CAM(CLK_CAMSV1, "camsv1", "mm_sel", 10), + GATE_CAM(CLK_CAM_FDVT, "cam_fdvt", "mm_sel", 11), + GATE_CAM(CLK_CAM_WPE, "cam_wpe", "mm_sel", 12), +}; + +static const struct mtk_clk_desc cam_desc = { + .clks = cam_clks, + .num_clks = ARRAY_SIZE(cam_clks), +}; + +static const struct of_device_id of_match_clk_mt8365_cam[] = { + { + .compatible = "mediatek,mt8365-imgsys", + .data = &cam_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8365_cam_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8365-cam", + .of_match_table = of_match_clk_mt8365_cam, + }, +}; +builtin_platform_driver(clk_mt8365_cam_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365-mfg.c b/drivers/clk/mediatek/clk-mt8365-mfg.c new file mode 100644 index 000000000..587b49128 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-mfg.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mfg0_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs mfg1_cg_regs = { + .set_ofs = 0x280, + .clr_ofs = 0x280, + .sta_ofs = 0x280, +}; + +#define GATE_MFG0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_MFG1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mfg1_cg_regs, _shift, \ + &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate mfg_clks[] = { + /* MFG0 */ + GATE_MFG0(CLK_MFG_BG3D, "mfg_bg3d", "mfg_sel", 0), + /* MFG1 */ + GATE_MFG1(CLK_MFG_MBIST_DIAG, "mfg_mbist_diag", "mbist_diag_sel", 24), +}; + +static const struct mtk_clk_desc mfg_desc = { + .clks = mfg_clks, + .num_clks = ARRAY_SIZE(mfg_clks), +}; + +static const struct of_device_id of_match_clk_mt8365_mfg[] = { + { + .compatible = "mediatek,mt8365-mfgcfg", + .data = &mfg_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8365_mfg_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8365-mfg", + .of_match_table = of_match_clk_mt8365_mfg, + }, +}; +builtin_platform_driver(clk_mt8365_mfg_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365-mm.c b/drivers/clk/mediatek/clk-mt8365-mm.c new file mode 100644 index 000000000..5c8bf18ab --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-mm.c @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + * Copyright (c) 2022 BayLibre, SAS + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs mm0_cg_regs = { + .set_ofs = 0x104, + .clr_ofs = 0x108, + .sta_ofs = 0x100, +}; + +static const struct mtk_gate_regs mm1_cg_regs = { + .set_ofs = 0x114, + .clr_ofs = 0x118, + .sta_ofs = 0x110, +}; + +#define GATE_MM0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +#define GATE_MM1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate mm_clks[] = { + /* MM0 */ + GATE_MM0(CLK_MM_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 0), + GATE_MM0(CLK_MM_MM_MDP_CCORR0, "mm_mdp_ccorr0", "mm_sel", 1), + GATE_MM0(CLK_MM_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 2), + GATE_MM0(CLK_MM_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 3), + GATE_MM0(CLK_MM_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 4), + GATE_MM0(CLK_MM_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 5), + GATE_MM0(CLK_MM_MM_MDP_WDMA0, "mm_mdp_wdma0", "mm_sel", 6), + GATE_MM0(CLK_MM_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 7), + GATE_MM0(CLK_MM_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 8), + GATE_MM0(CLK_MM_MM_DISP_RSZ0, "mm_disp_rsz0", "mm_sel", 9), + GATE_MM0(CLK_MM_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 10), + GATE_MM0(CLK_MM_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 11), + GATE_MM0(CLK_MM_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 12), + GATE_MM0(CLK_MM_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 13), + GATE_MM0(CLK_MM_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 14), + GATE_MM0(CLK_MM_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 15), + GATE_MM0(CLK_MM_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 16), + GATE_MM0(CLK_MM_MM_DSI0, "mm_dsi0", "mm_sel", 17), + GATE_MM0(CLK_MM_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 18), + GATE_MM0(CLK_MM_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 19), + GATE_MM0(CLK_MM_DPI0_DPI0, "mm_dpi0_dpi0", "vpll_dpix", 20), + GATE_MM0(CLK_MM_MM_FAKE, "mm_fake", "mm_sel", 21), + GATE_MM0(CLK_MM_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 22), + GATE_MM0(CLK_MM_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 23), + GATE_MM0(CLK_MM_MM_SMI_COMM0, "mm_smi_comm0", "mm_sel", 24), + GATE_MM0(CLK_MM_MM_SMI_COMM1, "mm_smi_comm1", "mm_sel", 25), + GATE_MM0(CLK_MM_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 26), + GATE_MM0(CLK_MM_MM_SMI_IMG, "mm_smi_img", "mm_sel", 27), + GATE_MM0(CLK_MM_MM_SMI_CAM, "mm_smi_cam", "mm_sel", 28), + GATE_MM0(CLK_MM_IMG_IMG_DL_RELAY, "mm_dl_relay", "mm_sel", 29), + GATE_MM0(CLK_MM_IMG_IMG_DL_ASYNC_TOP, "mm_dl_async_top", "mm_sel", 30), + GATE_MM0(CLK_MM_DSI0_DIG_DSI, "mm_dsi0_dig_dsi", "dsi0_lntc_dsick", 31), + /* MM1 */ + GATE_MM1(CLK_MM_26M_HRTWT, "mm_f26m_hrtwt", "clk26m", 0), + GATE_MM1(CLK_MM_MM_DPI0, "mm_dpi0", "mm_sel", 1), + GATE_MM1(CLK_MM_LVDSTX_PXL, "mm_flvdstx_pxl", "vpll_dpix", 2), + GATE_MM1(CLK_MM_LVDSTX_CTS, "mm_flvdstx_cts", "lvdstx_dig_cts", 3), +}; + +static int clk_mt8365_mm_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *node = dev->parent->of_node; + struct clk_hw_onecell_data *clk_data; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK); + + ret = mtk_clk_register_gates_with_dev(node, mm_clks, + ARRAY_SIZE(mm_clks), clk_data, + dev); + if (ret) + goto err_free_clk_data; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto err_unregister_gates; + + return 0; + +err_unregister_gates: + mtk_clk_unregister_gates(mm_clks, ARRAY_SIZE(mm_clks), clk_data); + +err_free_clk_data: + mtk_free_clk_data(clk_data); + + return ret; +} + +static struct platform_driver clk_mt8365_mm_drv = { + .probe = clk_mt8365_mm_probe, + .driver = { + .name = "clk-mt8365-mm", + }, +}; +builtin_platform_driver(clk_mt8365_mm_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365-vdec.c b/drivers/clk/mediatek/clk-mt8365-vdec.c new file mode 100644 index 000000000..cdc678e89 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-vdec.c @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs vdec0_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x4, + .sta_ofs = 0x0, +}; + +static const struct mtk_gate_regs vdec1_cg_regs = { + .set_ofs = 0x8, + .clr_ofs = 0xc, + .sta_ofs = 0x8, +}; + +#define GATE_VDEC0(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +#define GATE_VDEC1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate vdec_clks[] = { + /* VDEC0 */ + GATE_VDEC0(CLK_VDEC_VDEC, "vdec_fvdec_ck", "mm_sel", 0), + /* VDEC1 */ + GATE_VDEC1(CLK_VDEC_LARB1, "vdec_flarb1_ck", "mm_sel", 0), +}; + +static const struct mtk_clk_desc vdec_desc = { + .clks = vdec_clks, + .num_clks = ARRAY_SIZE(vdec_clks), +}; + +static const struct of_device_id of_match_clk_mt8365_vdec[] = { + { + .compatible = "mediatek,mt8365-vdecsys", + .data = &vdec_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8365_vdec_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8365-vdec", + .of_match_table = of_match_clk_mt8365_vdec, + }, +}; +builtin_platform_driver(clk_mt8365_vdec_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365-venc.c b/drivers/clk/mediatek/clk-mt8365-venc.c new file mode 100644 index 000000000..0e080c221 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365-venc.c @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk-provider.h> +#include <linux/platform_device.h> + +#include "clk-gate.h" +#include "clk-mtk.h" + +static const struct mtk_gate_regs venc_cg_regs = { + .set_ofs = 0x4, + .clr_ofs = 0x8, + .sta_ofs = 0x0, +}; + +#define GATE_VENC(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, \ + &mtk_clk_gate_ops_setclr_inv) + +static const struct mtk_gate venc_clks[] = { + /* VENC */ + GATE_VENC(CLK_VENC, "venc_fvenc_ck", "mm_sel", 4), + GATE_VENC(CLK_VENC_JPGENC, "venc_jpgenc_ck", "mm_sel", 8), +}; + +static const struct mtk_clk_desc venc_desc = { + .clks = venc_clks, + .num_clks = ARRAY_SIZE(venc_clks), +}; + +static const struct of_device_id of_match_clk_mt8365_venc[] = { + { + .compatible = "mediatek,mt8365-vencsys", + .data = &venc_desc, + }, { + /* sentinel */ + } +}; + +static struct platform_driver clk_mt8365_venc_drv = { + .probe = mtk_clk_simple_probe, + .remove = mtk_clk_simple_remove, + .driver = { + .name = "clk-mt8365-venc", + .of_match_table = of_match_clk_mt8365_venc, + }, +}; +builtin_platform_driver(clk_mt8365_venc_drv); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8365.c b/drivers/clk/mediatek/clk-mt8365.c new file mode 100644 index 000000000..adfecb618 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8365.c @@ -0,0 +1,1155 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2022 MediaTek Inc. + */ + +#include <dt-bindings/clock/mediatek,mt8365-clk.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/delay.h> +#include <linux/mfd/syscon.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-mux.h" +#include "clk-pll.h" + +static DEFINE_SPINLOCK(mt8365_clk_lock); + +static const struct mtk_fixed_clk top_fixed_clks[] = { + FIXED_CLK(CLK_TOP_I2S0_BCK, "i2s0_bck", NULL, 26000000), + FIXED_CLK(CLK_TOP_DSI0_LNTC_DSICK, "dsi0_lntc_dsick", "clk26m", + 75000000), + FIXED_CLK(CLK_TOP_VPLL_DPIX, "vpll_dpix", "clk26m", 75000000), + FIXED_CLK(CLK_TOP_LVDSTX_CLKDIG_CTS, "lvdstx_dig_cts", "clk26m", + 52500000), +}; + +static const struct mtk_fixed_factor top_divs[] = { + FACTOR(CLK_TOP_SYS_26M_D2, "sys_26m_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 4), + FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 8), + FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 16), + FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll", 1, 32), + FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll", 1, 6), + FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 12), + FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "mainpll", 1, 24), + FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 10), + FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 20), + FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 14), + FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 28), + FACTOR(CLK_TOP_UNIVPLL, "univpll", "univ_en", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL2_D32, "univpll2_d32", "univpll", 1, 96), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 10), + FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 20), + FACTOR(CLK_TOP_MMPLL, "mmpll_ck", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MFGPLL, "mfgpll_ck", "mfgpll", 1, 1), + FACTOR(CLK_TOP_LVDSPLL_D2, "lvdspll_d2", "lvdspll", 1, 2), + FACTOR(CLK_TOP_LVDSPLL_D4, "lvdspll_d4", "lvdspll", 1, 4), + FACTOR(CLK_TOP_LVDSPLL_D8, "lvdspll_d8", "lvdspll", 1, 8), + FACTOR(CLK_TOP_LVDSPLL_D16, "lvdspll_d16", "lvdspll", 1, 16), + FACTOR(CLK_TOP_USB20_192M, "usb20_192m_ck", "usb20_en", 1, 13), + FACTOR(CLK_TOP_USB20_192M_D4, "usb20_192m_d4", "usb20_192m_ck", 1, 4), + FACTOR(CLK_TOP_USB20_192M_D8, "usb20_192m_d8", "usb20_192m_ck", 1, 8), + FACTOR(CLK_TOP_USB20_192M_D16, "usb20_192m_d16", "usb20_192m_ck", + 1, 16), + FACTOR(CLK_TOP_USB20_192M_D32, "usb20_192m_d32", "usb20_192m_ck", + 1, 32), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "apll1_ck", 1, 4), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "apll1_ck", 1, 8), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "apll2_ck", 1, 4), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "apll2_ck", 1, 8), + FACTOR(CLK_TOP_MSDCPLL, "msdcpll_ck", "msdcpll", 1, 1), + FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2), + FACTOR(CLK_TOP_DSPPLL, "dsppll_ck", "dsppll", 1, 1), + FACTOR(CLK_TOP_DSPPLL_D2, "dsppll_d2", "dsppll", 1, 2), + FACTOR(CLK_TOP_DSPPLL_D4, "dsppll_d4", "dsppll", 1, 4), + FACTOR(CLK_TOP_DSPPLL_D8, "dsppll_d8", "dsppll", 1, 8), + FACTOR(CLK_TOP_APUPLL, "apupll_ck", "apupll", 1, 1), + FACTOR(CLK_TOP_CLK26M_D52, "clk26m_d52", "clk26m", 1, 52), +}; + +static const char * const axi_parents[] = { + "clk26m", + "syspll_d7", + "syspll1_d4", + "syspll3_d2" +}; + +static const char * const mem_parents[] = { + "clk26m", + "mmpll_ck", + "syspll_d3", + "syspll1_d2" +}; + +static const char * const mm_parents[] = { + "clk26m", + "mmpll_ck", + "syspll1_d2", + "syspll_d5", + "syspll1_d4", + "univpll_d5", + "univpll1_d2", + "mmpll_d2" +}; + +static const char * const scp_parents[] = { + "clk26m", + "syspll4_d2", + "univpll2_d2", + "syspll1_d2", + "univpll1_d2", + "syspll_d3", + "univpll_d3" +}; + +static const char * const mfg_parents[] = { + "clk26m", + "mfgpll_ck", + "syspll_d3", + "univpll_d3" +}; + +static const char * const atb_parents[] = { + "clk26m", + "syspll1_d4", + "syspll1_d2" +}; + +static const char * const camtg_parents[] = { + "clk26m", + "usb20_192m_d8", + "univpll2_d8", + "usb20_192m_d4", + "univpll2_d32", + "usb20_192m_d16", + "usb20_192m_d32" +}; + +static const char * const uart_parents[] = { + "clk26m", + "univpll2_d8" +}; + +static const char * const spi_parents[] = { + "clk26m", + "univpll2_d2", + "univpll2_d4", + "univpll2_d8" +}; + +static const char * const msdc50_0_hc_parents[] = { + "clk26m", + "syspll1_d2", + "univpll1_d4", + "syspll2_d2" +}; + +static const char * const msdc50_0_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll1_d2", + "syspll1_d2", + "univpll_d5", + "syspll2_d2", + "univpll1_d4", + "syspll4_d2" +}; + +static const char * const msdc50_2_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll_d3", + "univpll1_d2", + "syspll1_d2", + "univpll2_d2", + "syspll2_d2", + "univpll1_d4" +}; + +static const char * const msdc30_1_parents[] = { + "clk26m", + "msdcpll_d2", + "univpll2_d2", + "syspll2_d2", + "univpll1_d4", + "syspll1_d4", + "syspll2_d4", + "univpll2_d8" +}; + +static const char * const audio_parents[] = { + "clk26m", + "syspll3_d4", + "syspll4_d4", + "syspll1_d16" +}; + +static const char * const aud_intbus_parents[] = { + "clk26m", + "syspll1_d4", + "syspll4_d2" +}; + +static const char * const aud_1_parents[] = { + "clk26m", + "apll1_ck" +}; + +static const char * const aud_2_parents[] = { + "clk26m", + "apll2_ck" +}; + +static const char * const aud_engen1_parents[] = { + "clk26m", + "apll1_d2", + "apll1_d4", + "apll1_d8" +}; + +static const char * const aud_engen2_parents[] = { + "clk26m", + "apll2_d2", + "apll2_d4", + "apll2_d8" +}; + +static const char * const aud_spdif_parents[] = { + "clk26m", + "univpll_d2" +}; + +static const char * const disp_pwm_parents[] = { + "clk26m", + "univpll2_d4" +}; + +static const char * const dxcc_parents[] = { + "clk26m", + "syspll1_d2", + "syspll1_d4", + "syspll1_d8" +}; + +static const char * const ssusb_sys_parents[] = { + "clk26m", + "univpll3_d4", + "univpll2_d4", + "univpll3_d2" +}; + +static const char * const spm_parents[] = { + "clk26m", + "syspll1_d8" +}; + +static const char * const i2c_parents[] = { + "clk26m", + "univpll3_d4", + "univpll3_d2", + "syspll1_d8", + "syspll2_d8" +}; + +static const char * const pwm_parents[] = { + "clk26m", + "univpll3_d4", + "syspll1_d8" +}; + +static const char * const senif_parents[] = { + "clk26m", + "univpll1_d4", + "univpll1_d2", + "univpll2_d2" +}; + +static const char * const aes_fde_parents[] = { + "clk26m", + "msdcpll_ck", + "univpll_d3", + "univpll2_d2", + "univpll1_d2", + "syspll1_d2" +}; + +static const char * const dpi0_parents[] = { + "clk26m", + "lvdspll_d2", + "lvdspll_d4", + "lvdspll_d8", + "lvdspll_d16" +}; + +static const char * const dsp_parents[] = { + "clk26m", + "sys_26m_d2", + "dsppll_ck", + "dsppll_d2", + "dsppll_d4", + "dsppll_d8" +}; + +static const char * const nfi2x_parents[] = { + "clk26m", + "syspll2_d2", + "syspll_d7", + "syspll_d3", + "syspll2_d4", + "msdcpll_d2", + "univpll1_d2", + "univpll_d5" +}; + +static const char * const nfiecc_parents[] = { + "clk26m", + "syspll4_d2", + "univpll2_d4", + "syspll_d7", + "univpll1_d2", + "syspll1_d2", + "univpll2_d2", + "syspll_d5" +}; + +static const char * const ecc_parents[] = { + "clk26m", + "univpll2_d2", + "univpll1_d2", + "univpll_d3", + "syspll_d2" +}; + +static const char * const eth_parents[] = { + "clk26m", + "univpll2_d8", + "syspll4_d4", + "syspll1_d8", + "syspll4_d2" +}; + +static const char * const gcpu_parents[] = { + "clk26m", + "univpll_d3", + "univpll2_d2", + "syspll_d3", + "syspll2_d2" +}; + +static const char * const gcpu_cpm_parents[] = { + "clk26m", + "univpll2_d2", + "syspll2_d2" +}; + +static const char * const apu_parents[] = { + "clk26m", + "univpll_d2", + "apupll_ck", + "mmpll_ck", + "syspll_d3", + "univpll1_d2", + "syspll1_d2", + "syspll1_d4" +}; + +static const char * const mbist_diag_parents[] = { + "clk26m", + "syspll4_d4", + "univpll2_d8" +}; + +static const char * const apll_i2s0_parents[] = { + "aud_1_sel", + "aud_2_sel" +}; + +static struct mtk_composite top_misc_mux_gates[] = { + /* CLK_CFG_11 */ + MUX_GATE(CLK_TOP_MBIST_DIAG_SEL, "mbist_diag_sel", mbist_diag_parents, + 0x0ec, 0, 2, 7), +}; + +struct mt8365_clk_audio_mux { + int id; + const char *name; + u8 shift; +}; + +static struct mt8365_clk_audio_mux top_misc_muxes[] = { + { CLK_TOP_APLL_I2S0_SEL, "apll_i2s0_sel", 11}, + { CLK_TOP_APLL_I2S1_SEL, "apll_i2s1_sel", 12}, + { CLK_TOP_APLL_I2S2_SEL, "apll_i2s2_sel", 13}, + { CLK_TOP_APLL_I2S3_SEL, "apll_i2s3_sel", 14}, + { CLK_TOP_APLL_TDMOUT_SEL, "apll_tdmout_sel", 15}, + { CLK_TOP_APLL_TDMIN_SEL, "apll_tdmin_sel", 16}, + { CLK_TOP_APLL_SPDIF_SEL, "apll_spdif_sel", 17}, +}; + +#define CLK_CFG_UPDATE 0x004 +#define CLK_CFG_UPDATE1 0x008 + +static const struct mtk_mux top_muxes[] = { + /* CLK_CFG_0 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_AXI_SEL, "axi_sel", axi_parents, + 0x040, 0x044, 0x048, 0, 2, 7, CLK_CFG_UPDATE, + 0, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MEM_SEL, "mem_sel", mem_parents, 0x040, + 0x044, 0x048, 8, 2, 15, CLK_CFG_UPDATE, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_parents, 0x040, 0x044, + 0x048, 16, 3, 23, CLK_CFG_UPDATE, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_parents, 0x040, + 0x044, 0x048, 24, 3, 31, CLK_CFG_UPDATE, 3), + /* CLK_CFG_1 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_parents, 0x050, + 0x054, 0x058, 0, 2, 7, CLK_CFG_UPDATE, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_parents, 0x050, + 0x054, 0x058, 8, 2, 15, CLK_CFG_UPDATE, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_parents, + 0x050, 0x054, 0x058, 16, 3, 23, CLK_CFG_UPDATE, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG1_SEL, "camtg1_sel", camtg_parents, + 0x050, 0x054, 0x058, 24, 3, 31, CLK_CFG_UPDATE, 7), + /* CLK_CFG_2 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_parents, 0x060, + 0x064, 0x068, 0, 1, 7, CLK_CFG_UPDATE, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, 0x060, + 0x064, 0x068, 8, 2, 15, CLK_CFG_UPDATE, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_HC_SEL, "msdc50_0_hc_sel", + msdc50_0_hc_parents, 0x060, 0x064, 0x068, 16, 2, + 23, CLK_CFG_UPDATE, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC2_2_HC_SEL, "msdc2_2_hc_sel", + msdc50_0_hc_parents, 0x060, 0x064, 0x068, 24, 2, + 31, CLK_CFG_UPDATE, 11), + /* CLK_CFG_3 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", + msdc50_0_parents, 0x070, 0x074, 0x078, 0, 3, 7, + CLK_CFG_UPDATE, 12), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_2_SEL, "msdc50_2_sel", + msdc50_2_parents, 0x070, 0x074, 0x078, 8, 3, 15, + CLK_CFG_UPDATE, 13), + MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", + msdc30_1_parents, 0x070, 0x074, 0x078, 16, 3, 23, + CLK_CFG_UPDATE, 14), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_parents, + 0x070, 0x074, 0x078, 24, 2, 31, CLK_CFG_UPDATE, + 15), + /* CLK_CFG_4 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", + aud_intbus_parents, 0x080, 0x084, 0x088, 0, 2, 7, + CLK_CFG_UPDATE, 16), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_1_SEL, "aud_1_sel", aud_1_parents, + 0x080, 0x084, 0x088, 8, 1, 15, CLK_CFG_UPDATE, 17), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_2_SEL, "aud_2_sel", aud_2_parents, + 0x080, 0x084, 0x088, 16, 1, 23, CLK_CFG_UPDATE, + 18), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", + aud_engen1_parents, 0x080, 0x084, 0x088, 24, 2, 31, + CLK_CFG_UPDATE, 19), + /* CLK_CFG_5 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", + aud_engen2_parents, 0x090, 0x094, 0x098, 0, 2, 7, + CLK_CFG_UPDATE, 20), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD_SPDIF_SEL, "aud_spdif_sel", + aud_spdif_parents, 0x090, 0x094, 0x098, 8, 1, 15, + CLK_CFG_UPDATE, 21), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DISP_PWM_SEL, "disp_pwm_sel", + disp_pwm_parents, 0x090, 0x094, 0x098, 16, 2, 23, + CLK_CFG_UPDATE, 22), + /* CLK_CFG_6 */ + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_DXCC_SEL, "dxcc_sel", dxcc_parents, + 0x0a0, 0x0a4, 0x0a8, 0, 2, 7, CLK_CFG_UPDATE, + 24, CLK_IS_CRITICAL), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_SYS_SEL, "ssusb_sys_sel", + ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 8, 2, 15, + CLK_CFG_UPDATE, 25), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SSUSB_XHCI_SEL, "ssusb_xhci_sel", + ssusb_sys_parents, 0x0a0, 0x0a4, 0x0a8, 16, 2, 23, + CLK_CFG_UPDATE, 26), + MUX_GATE_CLR_SET_UPD_FLAGS(CLK_TOP_SPM_SEL, "spm_sel", spm_parents, + 0x0a0, 0x0a4, 0x0a8, 24, 1, 31, + CLK_CFG_UPDATE, 27, CLK_IS_CRITICAL), + /* CLK_CFG_7 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, 0x0b0, + 0x0b4, 0x0b8, 0, 3, 7, CLK_CFG_UPDATE, 28), + MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, 0x0b0, + 0x0b4, 0x0b8, 8, 2, 15, CLK_CFG_UPDATE, 29), + MUX_GATE_CLR_SET_UPD(CLK_TOP_SENIF_SEL, "senif_sel", senif_parents, + 0x0b0, 0x0b4, 0x0b8, 16, 2, 23, CLK_CFG_UPDATE, + 30), + MUX_GATE_CLR_SET_UPD(CLK_TOP_AES_FDE_SEL, "aes_fde_sel", + aes_fde_parents, 0x0b0, 0x0b4, 0x0b8, 24, 3, 31, + CLK_CFG_UPDATE, 31), + /* CLK_CFG_8 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTM_SEL, "camtm_sel", senif_parents, + 0x0c0, 0x0c4, 0x0c8, 0, 2, 7, CLK_CFG_UPDATE1, 0), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_parents, 0x0c0, + 0x0c4, 0x0c8, 8, 3, 15, CLK_CFG_UPDATE1, 1), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI1_SEL, "dpi1_sel", dpi0_parents, 0x0c0, + 0x0c4, 0x0c8, 16, 3, 23, CLK_CFG_UPDATE1, 2), + MUX_GATE_CLR_SET_UPD(CLK_TOP_DSP_SEL, "dsp_sel", dsp_parents, 0x0c0, + 0x0c4, 0x0c8, 24, 3, 31, CLK_CFG_UPDATE1, 3), + /* CLK_CFG_9 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFI2X_SEL, "nfi2x_sel", nfi2x_parents, + 0x0d0, 0x0d4, 0x0d8, 0, 3, 7, CLK_CFG_UPDATE1, 4), + MUX_GATE_CLR_SET_UPD(CLK_TOP_NFIECC_SEL, "nfiecc_sel", nfiecc_parents, + 0x0d0, 0x0d4, 0x0d8, 8, 3, 15, CLK_CFG_UPDATE1, 5), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ECC_SEL, "ecc_sel", ecc_parents, 0x0d0, + 0x0d4, 0x0d8, 16, 3, 23, CLK_CFG_UPDATE1, 6), + MUX_GATE_CLR_SET_UPD(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, 0x0d0, + 0x0d4, 0x0d8, 24, 3, 31, CLK_CFG_UPDATE1, 7), + /* CLK_CFG_10 */ + MUX_GATE_CLR_SET_UPD(CLK_TOP_GCPU_SEL, "gcpu_sel", gcpu_parents, 0x0e0, + 0x0e4, 0x0e8, 0, 3, 7, CLK_CFG_UPDATE1, 8), + MUX_GATE_CLR_SET_UPD(CLK_TOP_GCPU_CPM_SEL, "gcpu_cpm_sel", + gcpu_cpm_parents, 0x0e0, 0x0e4, 0x0e8, 8, 2, 15, + CLK_CFG_UPDATE1, 9), + MUX_GATE_CLR_SET_UPD(CLK_TOP_APU_SEL, "apu_sel", apu_parents, 0x0e0, + 0x0e4, 0x0e8, 16, 3, 23, CLK_CFG_UPDATE1, 10), + MUX_GATE_CLR_SET_UPD(CLK_TOP_APU_IF_SEL, "apu_if_sel", apu_parents, + 0x0e0, 0x0e4, 0x0e8, 24, 3, 31, CLK_CFG_UPDATE1, + 11), +}; + +static const char * const mcu_bus_parents[] = { + "clk26m", + "armpll", + "mainpll", + "univpll_d2" +}; + +static struct mtk_composite mcu_muxes[] = { + /* bus_pll_divider_cfg */ + MUX_GATE_FLAGS(CLK_MCU_BUS_SEL, "mcu_bus_sel", mcu_bus_parents, 0x7C0, + 9, 2, -1, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), +}; + +#define DIV_ADJ_F(_id, _name, _parent, _reg, _shift, _width, _flags) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ + .clk_divider_flags = _flags, \ +} + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ_F(CLK_TOP_APLL12_CK_DIV0, "apll12_ck_div0", "apll_i2s0_sel", + 0x324, 0, 8, CLK_DIVIDER_ROUND_CLOSEST), + DIV_ADJ_F(CLK_TOP_APLL12_CK_DIV1, "apll12_ck_div1", "apll_i2s1_sel", + 0x324, 8, 8, CLK_DIVIDER_ROUND_CLOSEST), + DIV_ADJ_F(CLK_TOP_APLL12_CK_DIV2, "apll12_ck_div2", "apll_i2s2_sel", + 0x324, 16, 8, CLK_DIVIDER_ROUND_CLOSEST), + DIV_ADJ_F(CLK_TOP_APLL12_CK_DIV3, "apll12_ck_div3", "apll_i2s3_sel", + 0x324, 24, 8, CLK_DIVIDER_ROUND_CLOSEST), + DIV_ADJ_F(CLK_TOP_APLL12_CK_DIV6, "apll12_ck_div6", "apll_spdif_sel", + 0x32c, 0, 8, CLK_DIVIDER_ROUND_CLOSEST), +}; + +struct mtk_simple_gate { + int id; + const char *name; + const char *parent; + u32 reg; + u8 shift; + unsigned long gate_flags; +}; + +static const struct mtk_simple_gate top_clk_gates[] = { + { CLK_TOP_CONN_32K, "conn_32k", "clk32k", 0x0, 10, CLK_GATE_SET_TO_DISABLE }, + { CLK_TOP_CONN_26M, "conn_26m", "clk26m", 0x0, 11, CLK_GATE_SET_TO_DISABLE }, + { CLK_TOP_DSP_32K, "dsp_32k", "clk32k", 0x0, 16, CLK_GATE_SET_TO_DISABLE }, + { CLK_TOP_DSP_26M, "dsp_26m", "clk26m", 0x0, 17, CLK_GATE_SET_TO_DISABLE }, + { CLK_TOP_USB20_48M_EN, "usb20_48m_en", "usb20_192m_d4", 0x104, 8, 0 }, + { CLK_TOP_UNIVPLL_48M_EN, "univpll_48m_en", "usb20_192m_d4", 0x104, 9, 0 }, + { CLK_TOP_LVDSTX_CLKDIG_EN, "lvdstx_dig_en", "lvdstx_dig_cts", 0x104, 20, 0 }, + { CLK_TOP_VPLL_DPIX_EN, "vpll_dpix_en", "vpll_dpix", 0x104, 21, 0 }, + { CLK_TOP_SSUSB_TOP_CK_EN, "ssusb_top_ck_en", NULL, 0x104, 22, 0 }, + { CLK_TOP_SSUSB_PHY_CK_EN, "ssusb_phy_ck_en", NULL, 0x104, 23, 0 }, + { CLK_TOP_AUD_I2S0_M, "aud_i2s0_m_ck", "apll12_ck_div0", 0x320, 0, 0 }, + { CLK_TOP_AUD_I2S1_M, "aud_i2s1_m_ck", "apll12_ck_div1", 0x320, 1, 0 }, + { CLK_TOP_AUD_I2S2_M, "aud_i2s2_m_ck", "apll12_ck_div2", 0x320, 2, 0 }, + { CLK_TOP_AUD_I2S3_M, "aud_i2s3_m_ck", "apll12_ck_div3", 0x320, 3, 0 }, + { CLK_TOP_AUD_TDMOUT_M, "aud_tdmout_m_ck", "apll12_ck_div4", 0x320, 4, 0 }, + { CLK_TOP_AUD_TDMOUT_B, "aud_tdmout_b_ck", "apll12_ck_div4b", 0x320, 5, 0 }, + { CLK_TOP_AUD_TDMIN_M, "aud_tdmin_m_ck", "apll12_ck_div5", 0x320, 6, 0 }, + { CLK_TOP_AUD_TDMIN_B, "aud_tdmin_b_ck", "apll12_ck_div5b", 0x320, 7, 0 }, + { CLK_TOP_AUD_SPDIF_M, "aud_spdif_m_ck", "apll12_ck_div6", 0x320, 8, 0 }, +}; + +static const struct mtk_gate_regs ifr2_cg_regs = { + .set_ofs = 0x80, + .clr_ofs = 0x84, + .sta_ofs = 0x90, +}; + +static const struct mtk_gate_regs ifr3_cg_regs = { + .set_ofs = 0x88, + .clr_ofs = 0x8c, + .sta_ofs = 0x94, +}; + +static const struct mtk_gate_regs ifr4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xa8, + .sta_ofs = 0xac, +}; + +static const struct mtk_gate_regs ifr5_cg_regs = { + .set_ofs = 0xc0, + .clr_ofs = 0xc4, + .sta_ofs = 0xc8, +}; + +static const struct mtk_gate_regs ifr6_cg_regs = { + .set_ofs = 0xd0, + .clr_ofs = 0xd4, + .sta_ofs = 0xd8, +}; + +#define GATE_IFR2(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ifr2_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_IFR3(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ifr3_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_IFR4(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ifr4_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_IFR5(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ifr5_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +#define GATE_IFR6(_id, _name, _parent, _shift) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .regs = &ifr6_cg_regs, \ + .shift = _shift, \ + .ops = &mtk_clk_gate_ops_setclr, \ + } + +static const struct mtk_gate ifr_clks[] = { + /* IFR2 */ + GATE_IFR2(CLK_IFR_PMIC_TMR, "ifr_pmic_tmr", "clk26m", 0), + GATE_IFR2(CLK_IFR_PMIC_AP, "ifr_pmic_ap", "clk26m", 1), + GATE_IFR2(CLK_IFR_PMIC_MD, "ifr_pmic_md", "clk26m", 2), + GATE_IFR2(CLK_IFR_PMIC_CONN, "ifr_pmic_conn", "clk26m", 3), + GATE_IFR2(CLK_IFR_ICUSB, "ifr_icusb", "axi_sel", 8), + GATE_IFR2(CLK_IFR_GCE, "ifr_gce", "axi_sel", 9), + GATE_IFR2(CLK_IFR_THERM, "ifr_therm", "axi_sel", 10), + GATE_IFR2(CLK_IFR_PWM_HCLK, "ifr_pwm_hclk", "axi_sel", 15), + GATE_IFR2(CLK_IFR_PWM1, "ifr_pwm1", "pwm_sel", 16), + GATE_IFR2(CLK_IFR_PWM2, "ifr_pwm2", "pwm_sel", 17), + GATE_IFR2(CLK_IFR_PWM3, "ifr_pwm3", "pwm_sel", 18), + GATE_IFR2(CLK_IFR_PWM4, "ifr_pwm4", "pwm_sel", 19), + GATE_IFR2(CLK_IFR_PWM5, "ifr_pwm5", "pwm_sel", 20), + GATE_IFR2(CLK_IFR_PWM, "ifr_pwm", "pwm_sel", 21), + GATE_IFR2(CLK_IFR_UART0, "ifr_uart0", "uart_sel", 22), + GATE_IFR2(CLK_IFR_UART1, "ifr_uart1", "uart_sel", 23), + GATE_IFR2(CLK_IFR_UART2, "ifr_uart2", "uart_sel", 24), + GATE_IFR2(CLK_IFR_DSP_UART, "ifr_dsp_uart", "uart_sel", 26), + GATE_IFR2(CLK_IFR_GCE_26M, "ifr_gce_26m", "clk26m", 27), + GATE_IFR2(CLK_IFR_CQ_DMA_FPC, "ifr_cq_dma_fpc", "axi_sel", 28), + GATE_IFR2(CLK_IFR_BTIF, "ifr_btif", "axi_sel", 31), + /* IFR3 */ + GATE_IFR3(CLK_IFR_SPI0, "ifr_spi0", "spi_sel", 1), + GATE_IFR3(CLK_IFR_MSDC0_HCLK, "ifr_msdc0", "msdc50_0_hc_sel", 2), + GATE_IFR3(CLK_IFR_MSDC2_HCLK, "ifr_msdc2", "msdc2_2_hc_sel", 3), + GATE_IFR3(CLK_IFR_MSDC1_HCLK, "ifr_msdc1", "axi_sel", 4), + GATE_IFR3(CLK_IFR_DVFSRC, "ifr_dvfsrc", "clk26m", 7), + GATE_IFR3(CLK_IFR_GCPU, "ifr_gcpu", "axi_sel", 8), + GATE_IFR3(CLK_IFR_TRNG, "ifr_trng", "axi_sel", 9), + GATE_IFR3(CLK_IFR_AUXADC, "ifr_auxadc", "clk26m", 10), + GATE_IFR3(CLK_IFR_AUXADC_MD, "ifr_auxadc_md", "clk26m", 14), + GATE_IFR3(CLK_IFR_AP_DMA, "ifr_ap_dma", "axi_sel", 18), + GATE_IFR3(CLK_IFR_DEBUGSYS, "ifr_debugsys", "axi_sel", 24), + GATE_IFR3(CLK_IFR_AUDIO, "ifr_audio", "axi_sel", 25), + /* IFR4 */ + GATE_IFR4(CLK_IFR_PWM_FBCLK6, "ifr_pwm_fbclk6", "pwm_sel", 0), + GATE_IFR4(CLK_IFR_DISP_PWM, "ifr_disp_pwm", "disp_pwm_sel", 2), + GATE_IFR4(CLK_IFR_AUD_26M_BK, "ifr_aud_26m_bk", "clk26m", 4), + GATE_IFR4(CLK_IFR_CQ_DMA, "ifr_cq_dma", "axi_sel", 27), + /* IFR5 */ + GATE_IFR5(CLK_IFR_MSDC0_SF, "ifr_msdc0_sf", "msdc50_0_sel", 0), + GATE_IFR5(CLK_IFR_MSDC1_SF, "ifr_msdc1_sf", "msdc50_0_sel", 1), + GATE_IFR5(CLK_IFR_MSDC2_SF, "ifr_msdc2_sf", "msdc50_0_sel", 2), + GATE_IFR5(CLK_IFR_AP_MSDC0, "ifr_ap_msdc0", "msdc50_0_sel", 7), + GATE_IFR5(CLK_IFR_MD_MSDC0, "ifr_md_msdc0", "msdc50_0_sel", 8), + GATE_IFR5(CLK_IFR_MSDC0_SRC, "ifr_msdc0_src", "msdc50_0_sel", 9), + GATE_IFR5(CLK_IFR_MSDC1_SRC, "ifr_msdc1_src", "msdc30_1_sel", 10), + GATE_IFR5(CLK_IFR_MSDC2_SRC, "ifr_msdc2_src", "msdc50_2_sel", 11), + GATE_IFR5(CLK_IFR_PWRAP_TMR, "ifr_pwrap_tmr", "clk26m", 12), + GATE_IFR5(CLK_IFR_PWRAP_SPI, "ifr_pwrap_spi", "clk26m", 13), + GATE_IFR5(CLK_IFR_PWRAP_SYS, "ifr_pwrap_sys", "clk26m", 14), + GATE_IFR5(CLK_IFR_IRRX_26M, "ifr_irrx_26m", "clk26m", 22), + GATE_IFR5(CLK_IFR_IRRX_32K, "ifr_irrx_32k", "clk32k", 23), + GATE_IFR5(CLK_IFR_I2C0_AXI, "ifr_i2c0_axi", "i2c_sel", 24), + GATE_IFR5(CLK_IFR_I2C1_AXI, "ifr_i2c1_axi", "i2c_sel", 25), + GATE_IFR5(CLK_IFR_I2C2_AXI, "ifr_i2c2_axi", "i2c_sel", 26), + GATE_IFR5(CLK_IFR_I2C3_AXI, "ifr_i2c3_axi", "i2c_sel", 27), + GATE_IFR5(CLK_IFR_NIC_AXI, "ifr_nic_axi", "axi_sel", 28), + GATE_IFR5(CLK_IFR_NIC_SLV_AXI, "ifr_nic_slv_axi", "axi_sel", 29), + GATE_IFR5(CLK_IFR_APU_AXI, "ifr_apu_axi", "axi_sel", 30), + /* IFR6 */ + GATE_IFR6(CLK_IFR_NFIECC, "ifr_nfiecc", "nfiecc_sel", 0), + GATE_IFR6(CLK_IFR_NFI1X_BK, "ifr_nfi1x_bk", "nfi2x_sel", 1), + GATE_IFR6(CLK_IFR_NFIECC_BK, "ifr_nfiecc_bk", "nfi2x_sel", 2), + GATE_IFR6(CLK_IFR_NFI_BK, "ifr_nfi_bk", "axi_sel", 3), + GATE_IFR6(CLK_IFR_MSDC2_AP_BK, "ifr_msdc2_ap_bk", "axi_sel", 4), + GATE_IFR6(CLK_IFR_MSDC2_MD_BK, "ifr_msdc2_md_bk", "axi_sel", 5), + GATE_IFR6(CLK_IFR_MSDC2_BK, "ifr_msdc2_bk", "axi_sel", 6), + GATE_IFR6(CLK_IFR_SUSB_133_BK, "ifr_susb_133_bk", "axi_sel", 7), + GATE_IFR6(CLK_IFR_SUSB_66_BK, "ifr_susb_66_bk", "axi_sel", 8), + GATE_IFR6(CLK_IFR_SSUSB_SYS, "ifr_ssusb_sys", "ssusb_sys_sel", 9), + GATE_IFR6(CLK_IFR_SSUSB_REF, "ifr_ssusb_ref", "ssusb_sys_sel", 10), + GATE_IFR6(CLK_IFR_SSUSB_XHCI, "ifr_ssusb_xhci", "ssusb_xhci_sel", 11), +}; + +static const struct mtk_simple_gate peri_clks[] = { + { CLK_PERIAXI, "periaxi", "axi_sel", 0x20c, 31, 0 }, +}; + +#define MT8365_PLL_FMAX (3800UL * MHZ) +#define MT8365_PLL_FMIN (1500UL * MHZ) +#define CON0_MT8365_RST_BAR BIT(23) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _tuner_en_reg, \ + _tuner_en_bit, _pcw_reg, _pcw_shift, _div_table, \ + _rst_bar_mask, _pcw_chg_reg) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = _rst_bar_mask, \ + .fmax = MT8365_PLL_FMAX, \ + .fmin = MT8365_PLL_FMIN, \ + .pcwbits = _pcwbits, \ + .pcwibits = 8, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .tuner_en_reg = _tuner_en_reg, \ + .tuner_en_bit = _tuner_en_bit, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .pcw_chg_reg = _pcw_chg_reg, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, \ + _tuner_en_reg, _tuner_en_bit, _pcw_reg, \ + _pcw_shift, _rst_bar_mask, _pcw_chg_reg) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, \ + _pcwbits, _pd_reg, _pd_shift, \ + _tuner_reg, _tuner_en_reg, _tuner_en_bit, \ + _pcw_reg, _pcw_shift, NULL, _rst_bar_mask, \ + _pcw_chg_reg) \ + +static const struct mtk_pll_div_table armpll_div_table[] = { + { .div = 0, .freq = MT8365_PLL_FMAX }, + { .div = 1, .freq = 1500 * MHZ }, + { .div = 2, .freq = 750 * MHZ }, + { .div = 3, .freq = 375 * MHZ }, + { .div = 4, .freq = 182500000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table mfgpll_div_table[] = { + { .div = 0, .freq = MT8365_PLL_FMAX }, + { .div = 1, .freq = 1600 * MHZ }, + { .div = 2, .freq = 800 * MHZ }, + { .div = 3, .freq = 400 * MHZ }, + { .div = 4, .freq = 200 * MHZ }, + { } /* sentinel */ +}; + +static const struct mtk_pll_div_table dsppll_div_table[] = { + { .div = 0, .freq = MT8365_PLL_FMAX }, + { .div = 1, .freq = 1600 * MHZ }, + { .div = 2, .freq = 600 * MHZ }, + { .div = 3, .freq = 400 * MHZ }, + { .div = 4, .freq = 200 * MHZ }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL_B(CLK_APMIXED_ARMPLL, "armpll", 0x030C, 0x0318, 0x00000001, PLL_AO, + 22, 0x0310, 24, 0, 0, 0, 0x0310, 0, armpll_div_table, 0, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0228, 0x0234, 0xFF000001, + HAVE_RST_BAR, 22, 0x022C, 24, 0, 0, 0, 0x022C, 0, + CON0_MT8365_RST_BAR, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll2", 0x0208, 0x0214, 0xFF000001, + HAVE_RST_BAR, 22, 0x020C, 24, 0, 0, 0, 0x020C, 0, + CON0_MT8365_RST_BAR, 0), + PLL_B(CLK_APMIXED_MFGPLL, "mfgpll", 0x0218, 0x0224, 0x00000001, 0, 22, + 0x021C, 24, 0, 0, 0, 0x021C, 0, mfgpll_div_table, 0, 0), + PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0350, 0x035C, 0x00000001, 0, 22, + 0x0354, 24, 0, 0, 0, 0x0354, 0, 0, 0), + PLL(CLK_APMIXED_MMPLL, "mmpll", 0x0330, 0x033C, 0x00000001, 0, 22, + 0x0334, 24, 0, 0, 0, 0x0334, 0, 0, 0), + PLL(CLK_APMIXED_APLL1, "apll1", 0x031C, 0x032C, 0x00000001, 0, 32, + 0x0320, 24, 0x0040, 0x000C, 0, 0x0324, 0, 0, 0x0320), + PLL(CLK_APMIXED_APLL2, "apll2", 0x0360, 0x0370, 0x00000001, 0, 32, + 0x0364, 24, 0x004C, 0x000C, 5, 0x0368, 0, 0, 0x0364), + PLL(CLK_APMIXED_LVDSPLL, "lvdspll", 0x0374, 0x0380, 0x00000001, 0, 22, + 0x0378, 24, 0, 0, 0, 0x0378, 0, 0, 0), + PLL_B(CLK_APMIXED_DSPPLL, "dsppll", 0x0390, 0x039C, 0x00000001, 0, 22, + 0x0394, 24, 0, 0, 0, 0x0394, 0, dsppll_div_table, 0, 0), + PLL(CLK_APMIXED_APUPLL, "apupll", 0x03A0, 0x03AC, 0x00000001, 0, 22, + 0x03A4, 24, 0, 0, 0, 0x03A4, 0, 0, 0), +}; + +static int clk_mt8365_apmixed_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct clk_hw *hw; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_devm_alloc_clk_data(dev, CLK_APMIXED_NR_CLK); + if (!clk_data) + return -ENOMEM; + + hw = devm_clk_hw_register_gate(dev, "univ_en", "univpll2", 0, + base + 0x204, 0, 0, NULL); + if (IS_ERR(hw)) + return PTR_ERR(hw); + clk_data->hws[CLK_APMIXED_UNIV_EN] = hw; + + hw = devm_clk_hw_register_gate(dev, "usb20_en", "univ_en", 0, + base + 0x204, 1, 0, NULL); + if (IS_ERR(hw)) + return PTR_ERR(hw); + clk_data->hws[CLK_APMIXED_USB20_EN] = hw; + + ret = mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + if (ret) + return ret; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_plls; + + return 0; + +unregister_plls: + mtk_clk_unregister_plls(plls, ARRAY_SIZE(plls), clk_data); + + return ret; +} + +static int +clk_mt8365_register_mtk_simple_gates(struct device *dev, void __iomem *base, + struct clk_hw_onecell_data *clk_data, + const struct mtk_simple_gate *gates, + unsigned int num_gates) +{ + unsigned int i; + + for (i = 0; i != num_gates; ++i) { + const struct mtk_simple_gate *gate = &gates[i]; + struct clk_hw *hw; + + hw = devm_clk_hw_register_gate(dev, gate->name, gate->parent, 0, + base + gate->reg, gate->shift, + gate->gate_flags, NULL); + if (IS_ERR(hw)) + return PTR_ERR(hw); + + clk_data->hws[gate->id] = hw; + } + + return 0; +} + +static int clk_mt8365_top_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + struct device *dev = &pdev->dev; + int ret; + int i; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_fixed_clks(top_fixed_clks, + ARRAY_SIZE(top_fixed_clks), clk_data); + if (ret) + goto free_clk_data; + + ret = mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), + clk_data); + if (ret) + goto unregister_fixed_clks; + + ret = mtk_clk_register_muxes(top_muxes, ARRAY_SIZE(top_muxes), node, + &mt8365_clk_lock, clk_data); + if (ret) + goto unregister_factors; + + ret = mtk_clk_register_composites(top_misc_mux_gates, + ARRAY_SIZE(top_misc_mux_gates), base, + &mt8365_clk_lock, clk_data); + if (ret) + goto unregister_muxes; + + for (i = 0; i != ARRAY_SIZE(top_misc_muxes); ++i) { + struct mt8365_clk_audio_mux *mux = &top_misc_muxes[i]; + struct clk_hw *hw; + + hw = devm_clk_hw_register_mux(dev, mux->name, apll_i2s0_parents, + ARRAY_SIZE(apll_i2s0_parents), + CLK_SET_RATE_PARENT, base + 0x320, + mux->shift, 1, 0, NULL); + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto unregister_composites; + } + + clk_data->hws[mux->id] = hw; + } + + ret = mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt8365_clk_lock, clk_data); + if (ret) + goto unregister_composites; + + ret = clk_mt8365_register_mtk_simple_gates(dev, base, clk_data, + top_clk_gates, + ARRAY_SIZE(top_clk_gates)); + if (ret) + goto unregister_dividers; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_dividers; + + return 0; +unregister_dividers: + mtk_clk_unregister_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + clk_data); +unregister_composites: + mtk_clk_unregister_composites(top_misc_mux_gates, + ARRAY_SIZE(top_misc_mux_gates), clk_data); +unregister_muxes: + mtk_clk_unregister_muxes(top_muxes, ARRAY_SIZE(top_muxes), clk_data); +unregister_factors: + mtk_clk_unregister_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); +unregister_fixed_clks: + mtk_clk_unregister_fixed_clks(top_fixed_clks, + ARRAY_SIZE(top_fixed_clks), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + + return ret; +} + +static int clk_mt8365_infra_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int ret; + + clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_gates(node, ifr_clks, ARRAY_SIZE(ifr_clks), + clk_data); + if (ret) + goto free_clk_data; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_gates; + + return 0; + +unregister_gates: + mtk_clk_unregister_gates(ifr_clks, ARRAY_SIZE(ifr_clks), clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + + return ret; +} + +static int clk_mt8365_peri_probe(struct platform_device *pdev) +{ + void __iomem *base; + struct clk_hw_onecell_data *clk_data; + struct device *dev = &pdev->dev; + struct device_node *node = dev->of_node; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_devm_alloc_clk_data(dev, CLK_PERI_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = clk_mt8365_register_mtk_simple_gates(dev, base, clk_data, + peri_clks, + ARRAY_SIZE(peri_clks)); + if (ret) + return ret; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + + return ret; +} + +static int clk_mt8365_mcu_probe(struct platform_device *pdev) +{ + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + void __iomem *base; + int ret; + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + clk_data = mtk_alloc_clk_data(CLK_MCU_NR_CLK); + if (!clk_data) + return -ENOMEM; + + ret = mtk_clk_register_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), + base, &mt8365_clk_lock, clk_data); + if (ret) + goto free_clk_data; + + ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (ret) + goto unregister_composites; + + return 0; + +unregister_composites: + mtk_clk_unregister_composites(mcu_muxes, ARRAY_SIZE(mcu_muxes), + clk_data); +free_clk_data: + mtk_free_clk_data(clk_data); + + return ret; +} + +static const struct of_device_id of_match_clk_mt8365[] = { + { + .compatible = "mediatek,mt8365-apmixedsys", + .data = clk_mt8365_apmixed_probe, + }, { + .compatible = "mediatek,mt8365-topckgen", + .data = clk_mt8365_top_probe, + }, { + .compatible = "mediatek,mt8365-infracfg", + .data = clk_mt8365_infra_probe, + }, { + .compatible = "mediatek,mt8365-pericfg", + .data = clk_mt8365_peri_probe, + }, { + .compatible = "mediatek,mt8365-mcucfg", + .data = clk_mt8365_mcu_probe, + }, { + /* sentinel */ + } +}; + +static int clk_mt8365_probe(struct platform_device *pdev) +{ + int (*clk_probe)(struct platform_device *pdev); + int ret; + + clk_probe = of_device_get_match_data(&pdev->dev); + if (!clk_probe) + return -EINVAL; + + ret = clk_probe(pdev); + if (ret) + dev_err(&pdev->dev, + "%s: could not register clock provider: %d\n", + pdev->name, ret); + + return ret; +} + +static struct platform_driver clk_mt8365_drv = { + .probe = clk_mt8365_probe, + .driver = { + .name = "clk-mt8365", + .of_match_table = of_match_clk_mt8365, + }, +}; + +static int __init clk_mt8365_init(void) +{ + return platform_driver_register(&clk_mt8365_drv); +} +arch_initcall(clk_mt8365_init); +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mt8516-aud.c b/drivers/clk/mediatek/clk-mt8516-aud.c new file mode 100644 index 000000000..a3dafc719 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8516-aud.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/clk-provider.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +#include <dt-bindings/clock/mt8516-clk.h> + +static const struct mtk_gate_regs aud_cg_regs = { + .set_ofs = 0x0, + .clr_ofs = 0x0, + .sta_ofs = 0x0, +}; + +#define GATE_AUD(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &aud_cg_regs, _shift, &mtk_clk_gate_ops_no_setclr) + +static const struct mtk_gate aud_clks[] __initconst = { + GATE_AUD(CLK_AUD_AFE, "aud_afe", "clk26m_ck", 2), + GATE_AUD(CLK_AUD_I2S, "aud_i2s", "i2s_infra_bck", 6), + GATE_AUD(CLK_AUD_22M, "aud_22m", "rg_aud_engen1", 8), + GATE_AUD(CLK_AUD_24M, "aud_24m", "rg_aud_engen2", 9), + GATE_AUD(CLK_AUD_INTDIR, "aud_intdir", "rg_aud_spdif_in", 15), + GATE_AUD(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner", "rg_aud_engen2", 18), + GATE_AUD(CLK_AUD_APLL_TUNER, "aud_apll_tuner", "rg_aud_engen1", 19), + GATE_AUD(CLK_AUD_HDMI, "aud_hdmi", "apll12_div4", 20), + GATE_AUD(CLK_AUD_SPDF, "aud_spdf", "apll12_div6", 21), + GATE_AUD(CLK_AUD_ADC, "aud_adc", "aud_afe", 24), + GATE_AUD(CLK_AUD_DAC, "aud_dac", "aud_afe", 25), + GATE_AUD(CLK_AUD_DAC_PREDIS, "aud_dac_predis", "aud_afe", 26), + GATE_AUD(CLK_AUD_TML, "aud_tml", "aud_afe", 27), +}; + +static void __init mtk_audsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + + clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK); + + mtk_clk_register_gates(node, aud_clks, ARRAY_SIZE(aud_clks), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_audsys, "mediatek,mt8516-audsys", mtk_audsys_init); diff --git a/drivers/clk/mediatek/clk-mt8516.c b/drivers/clk/mediatek/clk-mt8516.c new file mode 100644 index 000000000..056953d59 --- /dev/null +++ b/drivers/clk/mediatek/clk-mt8516.c @@ -0,0 +1,775 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2019 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + * Fabien Parent <fparent@baylibre.com> + */ + +#include <linux/delay.h> +#include <linux/of.h> +#include <linux/of_address.h> +#include <linux/slab.h> +#include <linux/mfd/syscon.h> + +#include "clk-gate.h" +#include "clk-mtk.h" +#include "clk-pll.h" + +#include <dt-bindings/clock/mt8516-clk.h> + +static DEFINE_SPINLOCK(mt8516_clk_lock); + +static const struct mtk_fixed_clk fixed_clks[] __initconst = { + FIXED_CLK(CLK_TOP_CLK_NULL, "clk_null", NULL, 0), + FIXED_CLK(CLK_TOP_I2S_INFRA_BCK, "i2s_infra_bck", "clk_null", 26000000), + FIXED_CLK(CLK_TOP_MEMPLL, "mempll", "clk26m", 800000000), +}; + +static const struct mtk_fixed_factor top_divs[] __initconst = { + FACTOR(CLK_TOP_DMPLL, "dmpll_ck", "mempll", 1, 1), + FACTOR(CLK_TOP_MAINPLL_D2, "mainpll_d2", "mainpll", 1, 2), + FACTOR(CLK_TOP_MAINPLL_D4, "mainpll_d4", "mainpll", 1, 4), + FACTOR(CLK_TOP_MAINPLL_D8, "mainpll_d8", "mainpll", 1, 8), + FACTOR(CLK_TOP_MAINPLL_D16, "mainpll_d16", "mainpll", 1, 16), + FACTOR(CLK_TOP_MAINPLL_D11, "mainpll_d11", "mainpll", 1, 11), + FACTOR(CLK_TOP_MAINPLL_D22, "mainpll_d22", "mainpll", 1, 22), + FACTOR(CLK_TOP_MAINPLL_D3, "mainpll_d3", "mainpll", 1, 3), + FACTOR(CLK_TOP_MAINPLL_D6, "mainpll_d6", "mainpll", 1, 6), + FACTOR(CLK_TOP_MAINPLL_D12, "mainpll_d12", "mainpll", 1, 12), + FACTOR(CLK_TOP_MAINPLL_D5, "mainpll_d5", "mainpll", 1, 5), + FACTOR(CLK_TOP_MAINPLL_D10, "mainpll_d10", "mainpll", 1, 10), + FACTOR(CLK_TOP_MAINPLL_D20, "mainpll_d20", "mainpll", 1, 20), + FACTOR(CLK_TOP_MAINPLL_D40, "mainpll_d40", "mainpll", 1, 40), + FACTOR(CLK_TOP_MAINPLL_D7, "mainpll_d7", "mainpll", 1, 7), + FACTOR(CLK_TOP_MAINPLL_D14, "mainpll_d14", "mainpll", 1, 14), + FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2), + FACTOR(CLK_TOP_UNIVPLL_D4, "univpll_d4", "univpll", 1, 4), + FACTOR(CLK_TOP_UNIVPLL_D8, "univpll_d8", "univpll", 1, 8), + FACTOR(CLK_TOP_UNIVPLL_D16, "univpll_d16", "univpll", 1, 16), + FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3), + FACTOR(CLK_TOP_UNIVPLL_D6, "univpll_d6", "univpll", 1, 6), + FACTOR(CLK_TOP_UNIVPLL_D12, "univpll_d12", "univpll", 1, 12), + FACTOR(CLK_TOP_UNIVPLL_D24, "univpll_d24", "univpll", 1, 24), + FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5), + FACTOR(CLK_TOP_UNIVPLL_D20, "univpll_d20", "univpll", 1, 20), + FACTOR(CLK_TOP_MMPLL380M, "mmpll380m", "mmpll", 1, 1), + FACTOR(CLK_TOP_MMPLL_D2, "mmpll_d2", "mmpll", 1, 2), + FACTOR(CLK_TOP_MMPLL_200M, "mmpll_200m", "mmpll", 1, 3), + FACTOR(CLK_TOP_USB_PHY48M, "usb_phy48m_ck", "univpll", 1, 26), + FACTOR(CLK_TOP_APLL1, "apll1_ck", "apll1", 1, 1), + FACTOR(CLK_TOP_APLL1_D2, "apll1_d2", "apll1_ck", 1, 2), + FACTOR(CLK_TOP_APLL1_D4, "apll1_d4", "rg_apll1_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL1_D8, "apll1_d8", "rg_apll1_d4_en", 1, 2), + FACTOR(CLK_TOP_APLL2, "apll2_ck", "apll2", 1, 1), + FACTOR(CLK_TOP_APLL2_D2, "apll2_d2", "apll2_ck", 1, 2), + FACTOR(CLK_TOP_APLL2_D4, "apll2_d4", "rg_apll2_d2_en", 1, 2), + FACTOR(CLK_TOP_APLL2_D8, "apll2_d8", "rg_apll2_d4_en", 1, 2), + FACTOR(CLK_TOP_CLK26M, "clk26m_ck", "clk26m", 1, 1), + FACTOR(CLK_TOP_CLK26M_D2, "clk26m_d2", "clk26m", 1, 2), + FACTOR(CLK_TOP_AHB_INFRA_D2, "ahb_infra_d2", "ahb_infra_sel", 1, 2), + FACTOR(CLK_TOP_NFI1X, "nfi1x_ck", "nfi2x_pad_sel", 1, 2), + FACTOR(CLK_TOP_ETH_D2, "eth_d2_ck", "eth_sel", 1, 2), +}; + +static const char * const uart0_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const ahb_infra_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d11", + "clk_null", + "mainpll_d12", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10" +}; + +static const char * const msdc0_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const uart1_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const msdc1_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const pmicspi_parents[] __initconst = { + "univpll_d20", + "usb_phy48m_ck", + "univpll_d16", + "clk26m_ck" +}; + +static const char * const qaxi_aud26m_parents[] __initconst = { + "clk26m_ck", + "ahb_infra_sel" +}; + +static const char * const aud_intbus_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d22", + "clk_null", + "mainpll_d11" +}; + +static const char * const nfi2x_pad_parents[] __initconst = { + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk26m_ck", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d12", + "mainpll_d8", + "clk_null", + "mainpll_d6", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d4", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "clk_null", + "mainpll_d10", + "mainpll_d7", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfi1x_pad_parents[] __initconst = { + "ahb_infra_sel", + "nfi1x_ck" +}; + +static const char * const usb_78m_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "univpll_d16", + "clk_null", + "mainpll_d20" +}; + +static const char * const spinor_parents[] __initconst = { + "clk26m_d2", + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20", + "mainpll_d16", + "univpll_d12" +}; + +static const char * const msdc2_parents[] __initconst = { + "clk26m_ck", + "univpll_d6", + "mainpll_d8", + "univpll_d8", + "mainpll_d16", + "mmpll_200m", + "mainpll_d12", + "mmpll_d2" +}; + +static const char * const eth_parents[] __initconst = { + "clk26m_ck", + "mainpll_d40", + "univpll_d24", + "univpll_d20", + "mainpll_d20" +}; + +static const char * const aud1_parents[] __initconst = { + "clk26m_ck", + "apll1_ck" +}; + +static const char * const aud2_parents[] __initconst = { + "clk26m_ck", + "apll2_ck" +}; + +static const char * const aud_engen1_parents[] __initconst = { + "clk26m_ck", + "rg_apll1_d2_en", + "rg_apll1_d4_en", + "rg_apll1_d8_en" +}; + +static const char * const aud_engen2_parents[] __initconst = { + "clk26m_ck", + "rg_apll2_d2_en", + "rg_apll2_d4_en", + "rg_apll2_d8_en" +}; + +static const char * const i2c_parents[] __initconst = { + "clk26m_ck", + "univpll_d20", + "univpll_d16", + "univpll_d12" +}; + +static const char * const aud_i2s0_m_parents[] __initconst = { + "rg_aud1", + "rg_aud2" +}; + +static const char * const pwm_parents[] __initconst = { + "clk26m_ck", + "univpll_d12" +}; + +static const char * const spi_parents[] __initconst = { + "clk26m_ck", + "univpll_d12", + "univpll_d8", + "univpll_d6" +}; + +static const char * const aud_spdifin_parents[] __initconst = { + "clk26m_ck", + "univpll_d2" +}; + +static const char * const uart2_parents[] __initconst = { + "clk26m_ck", + "univpll_d24" +}; + +static const char * const bsi_parents[] __initconst = { + "clk26m_ck", + "mainpll_d10", + "mainpll_d12", + "mainpll_d20" +}; + +static const char * const dbg_atclk_parents[] __initconst = { + "clk_null", + "clk26m_ck", + "mainpll_d5", + "clk_null", + "univpll_d5" +}; + +static const char * const csw_nfiecc_parents[] __initconst = { + "clk_null", + "mainpll_d7", + "mainpll_d6", + "clk_null", + "mainpll_d5" +}; + +static const char * const nfiecc_parents[] __initconst = { + "clk_null", + "nfi2x_pad_sel", + "mainpll_d4", + "clk_null", + "csw_nfiecc_sel" +}; + +static struct mtk_composite top_muxes[] __initdata = { + /* CLK_MUX_SEL0 */ + MUX(CLK_TOP_UART0_SEL, "uart0_sel", uart0_parents, + 0x000, 0, 1), + MUX(CLK_TOP_AHB_INFRA_SEL, "ahb_infra_sel", ahb_infra_parents, + 0x000, 4, 4), + MUX(CLK_TOP_MSDC0_SEL, "msdc0_sel", msdc0_parents, + 0x000, 11, 3), + MUX(CLK_TOP_UART1_SEL, "uart1_sel", uart1_parents, + 0x000, 19, 1), + MUX(CLK_TOP_MSDC1_SEL, "msdc1_sel", msdc1_parents, + 0x000, 20, 3), + MUX(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_parents, + 0x000, 24, 2), + MUX(CLK_TOP_QAXI_AUD26M_SEL, "qaxi_aud26m_sel", qaxi_aud26m_parents, + 0x000, 26, 1), + MUX(CLK_TOP_AUD_INTBUS_SEL, "aud_intbus_sel", aud_intbus_parents, + 0x000, 27, 3), + /* CLK_MUX_SEL1 */ + MUX(CLK_TOP_NFI2X_PAD_SEL, "nfi2x_pad_sel", nfi2x_pad_parents, + 0x004, 0, 7), + MUX(CLK_TOP_NFI1X_PAD_SEL, "nfi1x_pad_sel", nfi1x_pad_parents, + 0x004, 7, 1), + MUX(CLK_TOP_USB_78M_SEL, "usb_78m_sel", usb_78m_parents, + 0x004, 20, 3), + /* CLK_MUX_SEL8 */ + MUX(CLK_TOP_SPINOR_SEL, "spinor_sel", spinor_parents, + 0x040, 0, 3), + MUX(CLK_TOP_MSDC2_SEL, "msdc2_sel", msdc2_parents, + 0x040, 3, 3), + MUX(CLK_TOP_ETH_SEL, "eth_sel", eth_parents, + 0x040, 6, 3), + MUX(CLK_TOP_AUD1_SEL, "aud1_sel", aud1_parents, + 0x040, 22, 1), + MUX(CLK_TOP_AUD2_SEL, "aud2_sel", aud2_parents, + 0x040, 23, 1), + MUX(CLK_TOP_AUD_ENGEN1_SEL, "aud_engen1_sel", aud_engen1_parents, + 0x040, 24, 2), + MUX(CLK_TOP_AUD_ENGEN2_SEL, "aud_engen2_sel", aud_engen2_parents, + 0x040, 26, 2), + MUX(CLK_TOP_I2C_SEL, "i2c_sel", i2c_parents, + 0x040, 28, 2), + /* CLK_SEL_9 */ + MUX(CLK_TOP_AUD_I2S0_M_SEL, "aud_i2s0_m_sel", aud_i2s0_m_parents, + 0x044, 12, 1), + MUX(CLK_TOP_AUD_I2S1_M_SEL, "aud_i2s1_m_sel", aud_i2s0_m_parents, + 0x044, 13, 1), + MUX(CLK_TOP_AUD_I2S2_M_SEL, "aud_i2s2_m_sel", aud_i2s0_m_parents, + 0x044, 14, 1), + MUX(CLK_TOP_AUD_I2S3_M_SEL, "aud_i2s3_m_sel", aud_i2s0_m_parents, + 0x044, 15, 1), + MUX(CLK_TOP_AUD_I2S4_M_SEL, "aud_i2s4_m_sel", aud_i2s0_m_parents, + 0x044, 16, 1), + MUX(CLK_TOP_AUD_I2S5_M_SEL, "aud_i2s5_m_sel", aud_i2s0_m_parents, + 0x044, 17, 1), + MUX(CLK_TOP_AUD_SPDIF_B_SEL, "aud_spdif_b_sel", aud_i2s0_m_parents, + 0x044, 18, 1), + /* CLK_MUX_SEL13 */ + MUX(CLK_TOP_PWM_SEL, "pwm_sel", pwm_parents, + 0x07c, 0, 1), + MUX(CLK_TOP_SPI_SEL, "spi_sel", spi_parents, + 0x07c, 1, 2), + MUX(CLK_TOP_AUD_SPDIFIN_SEL, "aud_spdifin_sel", aud_spdifin_parents, + 0x07c, 3, 1), + MUX(CLK_TOP_UART2_SEL, "uart2_sel", uart2_parents, + 0x07c, 4, 1), + MUX(CLK_TOP_BSI_SEL, "bsi_sel", bsi_parents, + 0x07c, 5, 2), + MUX(CLK_TOP_DBG_ATCLK_SEL, "dbg_atclk_sel", dbg_atclk_parents, + 0x07c, 7, 3), + MUX(CLK_TOP_CSW_NFIECC_SEL, "csw_nfiecc_sel", csw_nfiecc_parents, + 0x07c, 10, 3), + MUX(CLK_TOP_NFIECC_SEL, "nfiecc_sel", nfiecc_parents, + 0x07c, 13, 3), +}; + +static const char * const ifr_mux1_parents[] __initconst = { + "clk26m_ck", + "armpll", + "univpll", + "mainpll_d2" +}; + +static const char * const ifr_eth_25m_parents[] __initconst = { + "eth_d2_ck", + "rg_eth" +}; + +static const char * const ifr_i2c0_parents[] __initconst = { + "ahb_infra_d2", + "rg_i2c" +}; + +static const struct mtk_composite ifr_muxes[] __initconst = { + MUX(CLK_IFR_MUX1_SEL, "ifr_mux1_sel", ifr_mux1_parents, 0x000, + 2, 2), + MUX(CLK_IFR_ETH_25M_SEL, "ifr_eth_25m_sel", ifr_eth_25m_parents, 0x080, + 0, 1), + MUX(CLK_IFR_I2C0_SEL, "ifr_i2c0_sel", ifr_i2c0_parents, 0x080, + 1, 1), + MUX(CLK_IFR_I2C1_SEL, "ifr_i2c1_sel", ifr_i2c0_parents, 0x080, + 2, 1), + MUX(CLK_IFR_I2C2_SEL, "ifr_i2c2_sel", ifr_i2c0_parents, 0x080, + 3, 1), +}; + +#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ +} + +static const struct mtk_clk_divider top_adj_divs[] = { + DIV_ADJ(CLK_TOP_APLL12_CK_DIV0, "apll12_ck_div0", "aud_i2s0_m_sel", + 0x0048, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV1, "apll12_ck_div1", "aud_i2s1_m_sel", + 0x0048, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV2, "apll12_ck_div2", "aud_i2s2_m_sel", + 0x0048, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV3, "apll12_ck_div3", "aud_i2s3_m_sel", + 0x0048, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4, "apll12_ck_div4", "aud_i2s4_m_sel", + 0x004c, 0, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV4B, "apll12_ck_div4b", "apll12_div4", + 0x004c, 8, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5, "apll12_ck_div5", "aud_i2s5_m_sel", + 0x004c, 16, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV5B, "apll12_ck_div5b", "apll12_div5", + 0x004c, 24, 8), + DIV_ADJ(CLK_TOP_APLL12_CK_DIV6, "apll12_ck_div6", "aud_spdif_b_sel", + 0x0078, 0, 8), +}; + +static const struct mtk_gate_regs top1_cg_regs = { + .set_ofs = 0x54, + .clr_ofs = 0x84, + .sta_ofs = 0x24, +}; + +static const struct mtk_gate_regs top2_cg_regs = { + .set_ofs = 0x6c, + .clr_ofs = 0x9c, + .sta_ofs = 0x3c, +}; + +static const struct mtk_gate_regs top3_cg_regs = { + .set_ofs = 0xa0, + .clr_ofs = 0xb0, + .sta_ofs = 0x70, +}; + +static const struct mtk_gate_regs top4_cg_regs = { + .set_ofs = 0xa4, + .clr_ofs = 0xb4, + .sta_ofs = 0x74, +}; + +static const struct mtk_gate_regs top5_cg_regs = { + .set_ofs = 0x44, + .clr_ofs = 0x44, + .sta_ofs = 0x44, +}; + +#define GATE_TOP1(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top1_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_TOP2(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top2_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_TOP2_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top2_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_TOP3(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top3_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +#define GATE_TOP4_I(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top4_cg_regs, _shift, &mtk_clk_gate_ops_setclr_inv) + +#define GATE_TOP5(_id, _name, _parent, _shift) \ + GATE_MTK(_id, _name, _parent, &top5_cg_regs, _shift, &mtk_clk_gate_ops_setclr) + +static const struct mtk_gate top_clks[] __initconst = { + /* TOP1 */ + GATE_TOP1(CLK_TOP_THEM, "them", "ahb_infra_sel", 1), + GATE_TOP1(CLK_TOP_APDMA, "apdma", "ahb_infra_sel", 2), + GATE_TOP1(CLK_TOP_I2C0, "i2c0", "ifr_i2c0_sel", 3), + GATE_TOP1(CLK_TOP_I2C1, "i2c1", "ifr_i2c1_sel", 4), + GATE_TOP1(CLK_TOP_AUXADC1, "auxadc1", "ahb_infra_sel", 5), + GATE_TOP1(CLK_TOP_NFI, "nfi", "nfi1x_pad_sel", 6), + GATE_TOP1(CLK_TOP_NFIECC, "nfiecc", "rg_nfiecc", 7), + GATE_TOP1(CLK_TOP_DEBUGSYS, "debugsys", "rg_dbg_atclk", 8), + GATE_TOP1(CLK_TOP_PWM, "pwm", "ahb_infra_sel", 9), + GATE_TOP1(CLK_TOP_UART0, "uart0", "uart0_sel", 10), + GATE_TOP1(CLK_TOP_UART1, "uart1", "uart1_sel", 11), + GATE_TOP1(CLK_TOP_BTIF, "btif", "ahb_infra_sel", 12), + GATE_TOP1(CLK_TOP_USB, "usb", "usb_78m", 13), + GATE_TOP1(CLK_TOP_FLASHIF_26M, "flashif_26m", "clk26m_ck", 14), + GATE_TOP1(CLK_TOP_AUXADC2, "auxadc2", "ahb_infra_sel", 15), + GATE_TOP1(CLK_TOP_I2C2, "i2c2", "ifr_i2c2_sel", 16), + GATE_TOP1(CLK_TOP_MSDC0, "msdc0", "msdc0_sel", 17), + GATE_TOP1(CLK_TOP_MSDC1, "msdc1", "msdc1_sel", 18), + GATE_TOP1(CLK_TOP_NFI2X, "nfi2x", "nfi2x_pad_sel", 19), + GATE_TOP1(CLK_TOP_PMICWRAP_AP, "pwrap_ap", "clk26m_ck", 20), + GATE_TOP1(CLK_TOP_SEJ, "sej", "ahb_infra_sel", 21), + GATE_TOP1(CLK_TOP_MEMSLP_DLYER, "memslp_dlyer", "clk26m_ck", 22), + GATE_TOP1(CLK_TOP_SPI, "spi", "spi_sel", 23), + GATE_TOP1(CLK_TOP_APXGPT, "apxgpt", "clk26m_ck", 24), + GATE_TOP1(CLK_TOP_AUDIO, "audio", "clk26m_ck", 25), + GATE_TOP1(CLK_TOP_PMICWRAP_MD, "pwrap_md", "clk26m_ck", 27), + GATE_TOP1(CLK_TOP_PMICWRAP_CONN, "pwrap_conn", "clk26m_ck", 28), + GATE_TOP1(CLK_TOP_PMICWRAP_26M, "pwrap_26m", "clk26m_ck", 29), + GATE_TOP1(CLK_TOP_AUX_ADC, "aux_adc", "clk26m_ck", 30), + GATE_TOP1(CLK_TOP_AUX_TP, "aux_tp", "clk26m_ck", 31), + /* TOP2 */ + GATE_TOP2(CLK_TOP_MSDC2, "msdc2", "ahb_infra_sel", 0), + GATE_TOP2(CLK_TOP_RBIST, "rbist", "univpll_d12", 1), + GATE_TOP2(CLK_TOP_NFI_BUS, "nfi_bus", "ahb_infra_sel", 2), + GATE_TOP2(CLK_TOP_GCE, "gce", "ahb_infra_sel", 4), + GATE_TOP2(CLK_TOP_TRNG, "trng", "ahb_infra_sel", 5), + GATE_TOP2(CLK_TOP_SEJ_13M, "sej_13m", "clk26m_ck", 6), + GATE_TOP2(CLK_TOP_AES, "aes", "ahb_infra_sel", 7), + GATE_TOP2(CLK_TOP_PWM_B, "pwm_b", "rg_pwm_infra", 8), + GATE_TOP2(CLK_TOP_PWM1_FB, "pwm1_fb", "rg_pwm_infra", 9), + GATE_TOP2(CLK_TOP_PWM2_FB, "pwm2_fb", "rg_pwm_infra", 10), + GATE_TOP2(CLK_TOP_PWM3_FB, "pwm3_fb", "rg_pwm_infra", 11), + GATE_TOP2(CLK_TOP_PWM4_FB, "pwm4_fb", "rg_pwm_infra", 12), + GATE_TOP2(CLK_TOP_PWM5_FB, "pwm5_fb", "rg_pwm_infra", 13), + GATE_TOP2(CLK_TOP_USB_1P, "usb_1p", "usb_78m", 14), + GATE_TOP2(CLK_TOP_FLASHIF_FREERUN, "flashif_freerun", "ahb_infra_sel", + 15), + GATE_TOP2(CLK_TOP_66M_ETH, "eth_66m", "ahb_infra_d2", 19), + GATE_TOP2(CLK_TOP_133M_ETH, "eth_133m", "ahb_infra_sel", 20), + GATE_TOP2(CLK_TOP_FETH_25M, "feth_25m", "ifr_eth_25m_sel", 21), + GATE_TOP2(CLK_TOP_FETH_50M, "feth_50m", "rg_eth", 22), + GATE_TOP2(CLK_TOP_FLASHIF_AXI, "flashif_axi", "ahb_infra_sel", 23), + GATE_TOP2(CLK_TOP_USBIF, "usbif", "ahb_infra_sel", 24), + GATE_TOP2(CLK_TOP_UART2, "uart2", "rg_uart2", 25), + GATE_TOP2(CLK_TOP_BSI, "bsi", "ahb_infra_sel", 26), + GATE_TOP2_I(CLK_TOP_MSDC0_INFRA, "msdc0_infra", "msdc0", 28), + GATE_TOP2_I(CLK_TOP_MSDC1_INFRA, "msdc1_infra", "msdc1", 29), + GATE_TOP2_I(CLK_TOP_MSDC2_INFRA, "msdc2_infra", "rg_msdc2", 30), + GATE_TOP2(CLK_TOP_USB_78M, "usb_78m", "usb_78m_sel", 31), + /* TOP3 */ + GATE_TOP3(CLK_TOP_RG_SPINOR, "rg_spinor", "spinor_sel", 0), + GATE_TOP3(CLK_TOP_RG_MSDC2, "rg_msdc2", "msdc2_sel", 1), + GATE_TOP3(CLK_TOP_RG_ETH, "rg_eth", "eth_sel", 2), + GATE_TOP3(CLK_TOP_RG_AUD1, "rg_aud1", "aud1_sel", 8), + GATE_TOP3(CLK_TOP_RG_AUD2, "rg_aud2", "aud2_sel", 9), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN1, "rg_aud_engen1", "aud_engen1_sel", 10), + GATE_TOP3(CLK_TOP_RG_AUD_ENGEN2, "rg_aud_engen2", "aud_engen2_sel", 11), + GATE_TOP3(CLK_TOP_RG_I2C, "rg_i2c", "i2c_sel", 12), + GATE_TOP3(CLK_TOP_RG_PWM_INFRA, "rg_pwm_infra", "pwm_sel", 13), + GATE_TOP3(CLK_TOP_RG_AUD_SPDIF_IN, "rg_aud_spdif_in", "aud_spdifin_sel", + 14), + GATE_TOP3(CLK_TOP_RG_UART2, "rg_uart2", "uart2_sel", 15), + GATE_TOP3(CLK_TOP_RG_BSI, "rg_bsi", "bsi_sel", 16), + GATE_TOP3(CLK_TOP_RG_DBG_ATCLK, "rg_dbg_atclk", "dbg_atclk_sel", 17), + GATE_TOP3(CLK_TOP_RG_NFIECC, "rg_nfiecc", "nfiecc_sel", 18), + /* TOP4 */ + GATE_TOP4_I(CLK_TOP_RG_APLL1_D2_EN, "rg_apll1_d2_en", "apll1_d2", 8), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D4_EN, "rg_apll1_d4_en", "apll1_d4", 9), + GATE_TOP4_I(CLK_TOP_RG_APLL1_D8_EN, "rg_apll1_d8_en", "apll1_d8", 10), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D2_EN, "rg_apll2_d2_en", "apll2_d2", 11), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D4_EN, "rg_apll2_d4_en", "apll2_d4", 12), + GATE_TOP4_I(CLK_TOP_RG_APLL2_D8_EN, "rg_apll2_d8_en", "apll2_d8", 13), + /* TOP5 */ + GATE_TOP5(CLK_TOP_APLL12_DIV0, "apll12_div0", "apll12_ck_div0", 0), + GATE_TOP5(CLK_TOP_APLL12_DIV1, "apll12_div1", "apll12_ck_div1", 1), + GATE_TOP5(CLK_TOP_APLL12_DIV2, "apll12_div2", "apll12_ck_div2", 2), + GATE_TOP5(CLK_TOP_APLL12_DIV3, "apll12_div3", "apll12_ck_div3", 3), + GATE_TOP5(CLK_TOP_APLL12_DIV4, "apll12_div4", "apll12_ck_div4", 4), + GATE_TOP5(CLK_TOP_APLL12_DIV4B, "apll12_div4b", "apll12_ck_div4b", 5), + GATE_TOP5(CLK_TOP_APLL12_DIV5, "apll12_div5", "apll12_ck_div5", 6), + GATE_TOP5(CLK_TOP_APLL12_DIV5B, "apll12_div5b", "apll12_ck_div5b", 7), + GATE_TOP5(CLK_TOP_APLL12_DIV6, "apll12_div6", "apll12_ck_div6", 8), +}; + +static void __init mtk_topckgen_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK); + + mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), + clk_data); + mtk_clk_register_gates(node, top_clks, ARRAY_SIZE(top_clks), clk_data); + + mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data); + mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base, + &mt8516_clk_lock, clk_data); + mtk_clk_register_dividers(top_adj_divs, ARRAY_SIZE(top_adj_divs), + base, &mt8516_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_topckgen, "mediatek,mt8516-topckgen", mtk_topckgen_init); + +static void __init mtk_infracfg_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + int r; + void __iomem *base; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_IFR_NR_CLK); + + mtk_clk_register_composites(ifr_muxes, ARRAY_SIZE(ifr_muxes), base, + &mt8516_clk_lock, clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); +} +CLK_OF_DECLARE(mtk_infracfg, "mediatek,mt8516-infracfg", mtk_infracfg_init); + +#define MT8516_PLL_FMAX (1502UL * MHZ) + +#define CON0_MT8516_RST_BAR BIT(27) + +#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift, _div_table) { \ + .id = _id, \ + .name = _name, \ + .reg = _reg, \ + .pwr_reg = _pwr_reg, \ + .en_mask = _en_mask, \ + .flags = _flags, \ + .rst_bar_mask = CON0_MT8516_RST_BAR, \ + .fmax = MT8516_PLL_FMAX, \ + .pcwbits = _pcwbits, \ + .pd_reg = _pd_reg, \ + .pd_shift = _pd_shift, \ + .tuner_reg = _tuner_reg, \ + .pcw_reg = _pcw_reg, \ + .pcw_shift = _pcw_shift, \ + .div_table = _div_table, \ + } + +#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, \ + _pcw_shift) \ + PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \ + _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \ + NULL) + +static const struct mtk_pll_div_table mmpll_div_table[] = { + { .div = 0, .freq = MT8516_PLL_FMAX }, + { .div = 1, .freq = 1000000000 }, + { .div = 2, .freq = 604500000 }, + { .div = 3, .freq = 253500000 }, + { .div = 4, .freq = 126750000 }, + { } /* sentinel */ +}; + +static const struct mtk_pll_data plls[] = { + PLL(CLK_APMIXED_ARMPLL, "armpll", 0x0100, 0x0110, 0, 0, + 21, 0x0104, 24, 0, 0x0104, 0), + PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0120, 0x0130, 0, + HAVE_RST_BAR, 21, 0x0124, 24, 0, 0x0124, 0), + PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0140, 0x0150, 0x30000000, + HAVE_RST_BAR, 7, 0x0144, 24, 0, 0x0144, 0), + PLL_B(CLK_APMIXED_MMPLL, "mmpll", 0x0160, 0x0170, 0, 0, + 21, 0x0164, 24, 0, 0x0164, 0, mmpll_div_table), + PLL(CLK_APMIXED_APLL1, "apll1", 0x0180, 0x0190, 0, 0, + 31, 0x0180, 1, 0x0194, 0x0184, 0), + PLL(CLK_APMIXED_APLL2, "apll2", 0x01A0, 0x01B0, 0, 0, + 31, 0x01A0, 1, 0x01B4, 0x01A4, 0), +}; + +static void __init mtk_apmixedsys_init(struct device_node *node) +{ + struct clk_hw_onecell_data *clk_data; + void __iomem *base; + int r; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return; + } + + clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK); + + mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data); + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + pr_err("%s(): could not register clock provider: %d\n", + __func__, r); + +} +CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8516-apmixedsys", + mtk_apmixedsys_init); diff --git a/drivers/clk/mediatek/clk-mtk.c b/drivers/clk/mediatek/clk-mtk.c new file mode 100644 index 000000000..d31f01d0b --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.c @@ -0,0 +1,504 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/bitops.h> +#include <linux/clk-provider.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "clk-mtk.h" +#include "clk-gate.h" + +static void mtk_init_clk_data(struct clk_hw_onecell_data *clk_data, + unsigned int clk_num) +{ + int i; + + clk_data->num = clk_num; + + for (i = 0; i < clk_num; i++) + clk_data->hws[i] = ERR_PTR(-ENOENT); +} + +struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev, + unsigned int clk_num) +{ + struct clk_hw_onecell_data *clk_data; + + clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, clk_num), + GFP_KERNEL); + if (!clk_data) + return NULL; + + mtk_init_clk_data(clk_data, clk_num); + + return clk_data; +} +EXPORT_SYMBOL_GPL(mtk_devm_alloc_clk_data); + +struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num) +{ + struct clk_hw_onecell_data *clk_data; + + clk_data = kzalloc(struct_size(clk_data, hws, clk_num), GFP_KERNEL); + if (!clk_data) + return NULL; + + mtk_init_clk_data(clk_data, clk_num); + + return clk_data; +} +EXPORT_SYMBOL_GPL(mtk_alloc_clk_data); + +void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data) +{ + kfree(clk_data); +} +EXPORT_SYMBOL_GPL(mtk_free_clk_data); + +int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + struct clk_hw *hw; + + if (!clk_data) + return -ENOMEM; + + for (i = 0; i < num; i++) { + const struct mtk_fixed_clk *rc = &clks[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[rc->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", rc->id); + continue; + } + + hw = clk_hw_register_fixed_rate(NULL, rc->name, rc->parent, 0, + rc->rate); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", rc->name, + hw); + goto err; + } + + clk_data->hws[rc->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_fixed_clk *rc = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) + continue; + + clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_fixed_clks); + +void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_fixed_clk *rc = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[rc->id])) + continue; + + clk_hw_unregister_fixed_rate(clk_data->hws[rc->id]); + clk_data->hws[rc->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_fixed_clks); + +int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + struct clk_hw *hw; + + if (!clk_data) + return -ENOMEM; + + for (i = 0; i < num; i++) { + const struct mtk_fixed_factor *ff = &clks[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[ff->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", ff->id); + continue; + } + + hw = clk_hw_register_fixed_factor(NULL, ff->name, ff->parent_name, + CLK_SET_RATE_PARENT, ff->mult, ff->div); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", ff->name, + hw); + goto err; + } + + clk_data->hws[ff->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_fixed_factor *ff = &clks[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) + continue; + + clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_factors); + +void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_fixed_factor *ff = &clks[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[ff->id])) + continue; + + clk_hw_unregister_fixed_factor(clk_data->hws[ff->id]); + clk_data->hws[ff->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_factors); + +static struct clk_hw *mtk_clk_register_composite(const struct mtk_composite *mc, + void __iomem *base, spinlock_t *lock) +{ + struct clk_hw *hw; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL; + const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL; + const char * const *parent_names; + const char *parent; + int num_parents; + int ret; + + if (mc->mux_shift >= 0) { + mux = kzalloc(sizeof(*mux), GFP_KERNEL); + if (!mux) + return ERR_PTR(-ENOMEM); + + mux->reg = base + mc->mux_reg; + mux->mask = BIT(mc->mux_width) - 1; + mux->shift = mc->mux_shift; + mux->lock = lock; + mux->flags = mc->mux_flags; + mux_hw = &mux->hw; + mux_ops = &clk_mux_ops; + + parent_names = mc->parent_names; + num_parents = mc->num_parents; + } else { + parent = mc->parent; + parent_names = &parent; + num_parents = 1; + } + + if (mc->gate_shift >= 0) { + gate = kzalloc(sizeof(*gate), GFP_KERNEL); + if (!gate) { + ret = -ENOMEM; + goto err_out; + } + + gate->reg = base + mc->gate_reg; + gate->bit_idx = mc->gate_shift; + gate->flags = CLK_GATE_SET_TO_DISABLE; + gate->lock = lock; + + gate_hw = &gate->hw; + gate_ops = &clk_gate_ops; + } + + if (mc->divider_shift >= 0) { + div = kzalloc(sizeof(*div), GFP_KERNEL); + if (!div) { + ret = -ENOMEM; + goto err_out; + } + + div->reg = base + mc->divider_reg; + div->shift = mc->divider_shift; + div->width = mc->divider_width; + div->lock = lock; + + div_hw = &div->hw; + div_ops = &clk_divider_ops; + } + + hw = clk_hw_register_composite(NULL, mc->name, parent_names, num_parents, + mux_hw, mux_ops, + div_hw, div_ops, + gate_hw, gate_ops, + mc->flags); + + if (IS_ERR(hw)) { + ret = PTR_ERR(hw); + goto err_out; + } + + return hw; +err_out: + kfree(div); + kfree(gate); + kfree(mux); + + return ERR_PTR(ret); +} + +static void mtk_clk_unregister_composite(struct clk_hw *hw) +{ + struct clk_composite *composite; + struct clk_mux *mux = NULL; + struct clk_gate *gate = NULL; + struct clk_divider *div = NULL; + + if (!hw) + return; + + composite = to_clk_composite(hw); + if (composite->mux_hw) + mux = to_clk_mux(composite->mux_hw); + if (composite->gate_hw) + gate = to_clk_gate(composite->gate_hw); + if (composite->rate_hw) + div = to_clk_divider(composite->rate_hw); + + clk_hw_unregister_composite(hw); + kfree(div); + kfree(gate); + kfree(mux); +} + +int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data) +{ + struct clk_hw *hw; + int i; + + if (!clk_data) + return -ENOMEM; + + for (i = 0; i < num; i++) { + const struct mtk_composite *mc = &mcs[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[mc->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", + mc->id); + continue; + } + + hw = mtk_clk_register_composite(mc, base, lock); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mc->name, + hw); + goto err; + } + + clk_data->hws[mc->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_composite *mc = &mcs[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[mcs->id])) + continue; + + mtk_clk_unregister_composite(clk_data->hws[mc->id]); + clk_data->hws[mc->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_composites); + +void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_composite *mc = &mcs[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[mc->id])) + continue; + + mtk_clk_unregister_composite(clk_data->hws[mc->id]); + clk_data->hws[mc->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_composites); + +int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data) +{ + struct clk_hw *hw; + int i; + + if (!clk_data) + return -ENOMEM; + + for (i = 0; i < num; i++) { + const struct mtk_clk_divider *mcd = &mcds[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[mcd->id])) { + pr_warn("Trying to register duplicate clock ID: %d\n", + mcd->id); + continue; + } + + hw = clk_hw_register_divider(NULL, mcd->name, mcd->parent_name, + mcd->flags, base + mcd->div_reg, mcd->div_shift, + mcd->div_width, mcd->clk_divider_flags, lock); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mcd->name, + hw); + goto err; + } + + clk_data->hws[mcd->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_clk_divider *mcd = &mcds[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) + continue; + + clk_hw_unregister_divider(clk_data->hws[mcd->id]); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_dividers); + +void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_clk_divider *mcd = &mcds[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[mcd->id])) + continue; + + clk_hw_unregister_divider(clk_data->hws[mcd->id]); + clk_data->hws[mcd->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_dividers); + +int mtk_clk_simple_probe(struct platform_device *pdev) +{ + const struct mtk_clk_desc *mcd; + struct clk_hw_onecell_data *clk_data; + struct device_node *node = pdev->dev.of_node; + int r; + + mcd = of_device_get_match_data(&pdev->dev); + if (!mcd) + return -EINVAL; + + clk_data = mtk_alloc_clk_data(mcd->num_clks); + if (!clk_data) + return -ENOMEM; + + r = mtk_clk_register_gates_with_dev(node, mcd->clks, mcd->num_clks, + clk_data, &pdev->dev); + if (r) + goto free_data; + + r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); + if (r) + goto unregister_clks; + + platform_set_drvdata(pdev, clk_data); + + if (mcd->rst_desc) { + r = mtk_register_reset_controller_with_dev(&pdev->dev, + mcd->rst_desc); + if (r) + goto unregister_clks; + } + + return r; + +unregister_clks: + mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); +free_data: + mtk_free_clk_data(clk_data); + return r; +} +EXPORT_SYMBOL_GPL(mtk_clk_simple_probe); + +int mtk_clk_simple_remove(struct platform_device *pdev) +{ + const struct mtk_clk_desc *mcd = of_device_get_match_data(&pdev->dev); + struct clk_hw_onecell_data *clk_data = platform_get_drvdata(pdev); + struct device_node *node = pdev->dev.of_node; + + of_clk_del_provider(node); + mtk_clk_unregister_gates(mcd->clks, mcd->num_clks, clk_data); + mtk_free_clk_data(clk_data); + + return 0; +} +EXPORT_SYMBOL_GPL(mtk_clk_simple_remove); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mtk.h b/drivers/clk/mediatek/clk-mtk.h new file mode 100644 index 000000000..63ae7941a --- /dev/null +++ b/drivers/clk/mediatek/clk-mtk.h @@ -0,0 +1,204 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#ifndef __DRV_CLK_MTK_H +#define __DRV_CLK_MTK_H + +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +#include "reset.h" + +#define MAX_MUX_GATE_BIT 31 +#define INVALID_MUX_GATE_BIT (MAX_MUX_GATE_BIT + 1) + +#define MHZ (1000 * 1000) + +struct platform_device; + +struct mtk_fixed_clk { + int id; + const char *name; + const char *parent; + unsigned long rate; +}; + +#define FIXED_CLK(_id, _name, _parent, _rate) { \ + .id = _id, \ + .name = _name, \ + .parent = _parent, \ + .rate = _rate, \ + } + +int mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_hw_onecell_data *clk_data); +void mtk_clk_unregister_fixed_clks(const struct mtk_fixed_clk *clks, int num, + struct clk_hw_onecell_data *clk_data); + +struct mtk_fixed_factor { + int id; + const char *name; + const char *parent_name; + int mult; + int div; +}; + +#define FACTOR(_id, _name, _parent, _mult, _div) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .mult = _mult, \ + .div = _div, \ + } + +int mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_hw_onecell_data *clk_data); +void mtk_clk_unregister_factors(const struct mtk_fixed_factor *clks, int num, + struct clk_hw_onecell_data *clk_data); + +struct mtk_composite { + int id; + const char *name; + const char * const *parent_names; + const char *parent; + unsigned flags; + + uint32_t mux_reg; + uint32_t divider_reg; + uint32_t gate_reg; + + signed char mux_shift; + signed char mux_width; + signed char gate_shift; + + signed char divider_shift; + signed char divider_width; + + u8 mux_flags; + + signed char num_parents; +}; + +#define MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, _shift, \ + _width, _gate, _flags, _muxflags) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_reg = _reg, \ + .gate_shift = _gate, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = _flags, \ + .mux_flags = _muxflags, \ + } + +/* + * In case the rate change propagation to parent clocks is undesirable, + * this macro allows to specify the clock flags manually. + */ +#define MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ + _gate, _flags) \ + MUX_GATE_FLAGS_2(_id, _name, _parents, _reg, \ + _shift, _width, _gate, _flags, 0) + +/* + * Unless necessary, all MUX_GATE clocks propagate rate changes to their + * parent clock by default. + */ +#define MUX_GATE(_id, _name, _parents, _reg, _shift, _width, _gate) \ + MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width, \ + _gate, CLK_SET_RATE_PARENT) + +#define MUX(_id, _name, _parents, _reg, _shift, _width) \ + MUX_FLAGS(_id, _name, _parents, _reg, \ + _shift, _width, CLK_SET_RATE_PARENT) + +#define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) { \ + .id = _id, \ + .name = _name, \ + .mux_reg = _reg, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_shift = -1, \ + .divider_shift = -1, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = _flags, \ + } + +#define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg, \ + _div_width, _div_shift) { \ + .id = _id, \ + .parent = _parent, \ + .name = _name, \ + .divider_reg = _div_reg, \ + .divider_shift = _div_shift, \ + .divider_width = _div_width, \ + .gate_reg = _gate_reg, \ + .gate_shift = _gate_shift, \ + .mux_shift = -1, \ + .flags = 0, \ + } + +int mtk_clk_register_composites(const struct mtk_composite *mcs, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data); +void mtk_clk_unregister_composites(const struct mtk_composite *mcs, int num, + struct clk_hw_onecell_data *clk_data); + +struct mtk_clk_divider { + int id; + const char *name; + const char *parent_name; + unsigned long flags; + + u32 div_reg; + unsigned char div_shift; + unsigned char div_width; + unsigned char clk_divider_flags; + const struct clk_div_table *clk_div_table; +}; + +#define DIV_ADJ(_id, _name, _parent, _reg, _shift, _width) { \ + .id = _id, \ + .name = _name, \ + .parent_name = _parent, \ + .div_reg = _reg, \ + .div_shift = _shift, \ + .div_width = _width, \ +} + +int mtk_clk_register_dividers(const struct mtk_clk_divider *mcds, int num, + void __iomem *base, spinlock_t *lock, + struct clk_hw_onecell_data *clk_data); +void mtk_clk_unregister_dividers(const struct mtk_clk_divider *mcds, int num, + struct clk_hw_onecell_data *clk_data); + +struct clk_hw_onecell_data *mtk_alloc_clk_data(unsigned int clk_num); +struct clk_hw_onecell_data *mtk_devm_alloc_clk_data(struct device *dev, + unsigned int clk_num); +void mtk_free_clk_data(struct clk_hw_onecell_data *clk_data); + +struct clk_hw *mtk_clk_register_ref2usb_tx(const char *name, + const char *parent_name, void __iomem *reg); +void mtk_clk_unregister_ref2usb_tx(struct clk_hw *hw); + +struct mtk_clk_desc { + const struct mtk_gate *clks; + size_t num_clks; + const struct mtk_clk_rst_desc *rst_desc; +}; + +int mtk_clk_simple_probe(struct platform_device *pdev); +int mtk_clk_simple_remove(struct platform_device *pdev); + +#endif /* __DRV_CLK_MTK_H */ diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c new file mode 100644 index 000000000..ba1720b9e --- /dev/null +++ b/drivers/clk/mediatek/clk-mux.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/compiler_types.h> +#include <linux/container_of.h> +#include <linux/err.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/regmap.h> +#include <linux/spinlock.h> +#include <linux/slab.h> + +#include "clk-mux.h" + +struct mtk_clk_mux { + struct clk_hw hw; + struct regmap *regmap; + const struct mtk_mux *data; + spinlock_t *lock; + bool reparent; +}; + +static inline struct mtk_clk_mux *to_mtk_clk_mux(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_mux, hw); +} + +static int mtk_clk_mux_enable_setclr(struct clk_hw *hw) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + unsigned long flags = 0; + + if (mux->lock) + spin_lock_irqsave(mux->lock, flags); + else + __acquire(mux->lock); + + regmap_write(mux->regmap, mux->data->clr_ofs, + BIT(mux->data->gate_shift)); + + /* + * If the parent has been changed when the clock was disabled, it will + * not be effective yet. Set the update bit to ensure the mux gets + * updated. + */ + if (mux->reparent && mux->data->upd_shift >= 0) { + regmap_write(mux->regmap, mux->data->upd_ofs, + BIT(mux->data->upd_shift)); + mux->reparent = false; + } + + if (mux->lock) + spin_unlock_irqrestore(mux->lock, flags); + else + __release(mux->lock); + + return 0; +} + +static void mtk_clk_mux_disable_setclr(struct clk_hw *hw) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + + regmap_write(mux->regmap, mux->data->set_ofs, + BIT(mux->data->gate_shift)); +} + +static int mtk_clk_mux_is_enabled(struct clk_hw *hw) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + u32 val; + + regmap_read(mux->regmap, mux->data->mux_ofs, &val); + + return (val & BIT(mux->data->gate_shift)) == 0; +} + +static u8 mtk_clk_mux_get_parent(struct clk_hw *hw) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + u32 mask = GENMASK(mux->data->mux_width - 1, 0); + u32 val; + + regmap_read(mux->regmap, mux->data->mux_ofs, &val); + val = (val >> mux->data->mux_shift) & mask; + + return val; +} + +static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + u32 mask = GENMASK(mux->data->mux_width - 1, 0); + u32 val, orig; + unsigned long flags = 0; + + if (mux->lock) + spin_lock_irqsave(mux->lock, flags); + else + __acquire(mux->lock); + + regmap_read(mux->regmap, mux->data->mux_ofs, &orig); + val = (orig & ~(mask << mux->data->mux_shift)) + | (index << mux->data->mux_shift); + + if (val != orig) { + regmap_write(mux->regmap, mux->data->clr_ofs, + mask << mux->data->mux_shift); + regmap_write(mux->regmap, mux->data->set_ofs, + index << mux->data->mux_shift); + + if (mux->data->upd_shift >= 0) { + regmap_write(mux->regmap, mux->data->upd_ofs, + BIT(mux->data->upd_shift)); + mux->reparent = true; + } + } + + if (mux->lock) + spin_unlock_irqrestore(mux->lock, flags); + else + __release(mux->lock); + + return 0; +} + +static int mtk_clk_mux_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + + return clk_mux_determine_rate_flags(hw, req, mux->data->flags); +} + +const struct clk_ops mtk_mux_clr_set_upd_ops = { + .get_parent = mtk_clk_mux_get_parent, + .set_parent = mtk_clk_mux_set_parent_setclr_lock, + .determine_rate = mtk_clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(mtk_mux_clr_set_upd_ops); + +const struct clk_ops mtk_mux_gate_clr_set_upd_ops = { + .enable = mtk_clk_mux_enable_setclr, + .disable = mtk_clk_mux_disable_setclr, + .is_enabled = mtk_clk_mux_is_enabled, + .get_parent = mtk_clk_mux_get_parent, + .set_parent = mtk_clk_mux_set_parent_setclr_lock, + .determine_rate = mtk_clk_mux_determine_rate, +}; +EXPORT_SYMBOL_GPL(mtk_mux_gate_clr_set_upd_ops); + +static struct clk_hw *mtk_clk_register_mux(const struct mtk_mux *mux, + struct regmap *regmap, + spinlock_t *lock) +{ + struct mtk_clk_mux *clk_mux; + struct clk_init_data init = {}; + int ret; + + clk_mux = kzalloc(sizeof(*clk_mux), GFP_KERNEL); + if (!clk_mux) + return ERR_PTR(-ENOMEM); + + init.name = mux->name; + init.flags = mux->flags | CLK_SET_RATE_PARENT; + init.parent_names = mux->parent_names; + init.num_parents = mux->num_parents; + init.ops = mux->ops; + + clk_mux->regmap = regmap; + clk_mux->data = mux; + clk_mux->lock = lock; + clk_mux->hw.init = &init; + + ret = clk_hw_register(NULL, &clk_mux->hw); + if (ret) { + kfree(clk_mux); + return ERR_PTR(ret); + } + + return &clk_mux->hw; +} + +static void mtk_clk_unregister_mux(struct clk_hw *hw) +{ + struct mtk_clk_mux *mux; + if (!hw) + return; + + mux = to_mtk_clk_mux(hw); + + clk_hw_unregister(hw); + kfree(mux); +} + +int mtk_clk_register_muxes(const struct mtk_mux *muxes, + int num, struct device_node *node, + spinlock_t *lock, + struct clk_hw_onecell_data *clk_data) +{ + struct regmap *regmap; + struct clk_hw *hw; + int i; + + regmap = device_node_to_regmap(node); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %pOF: %pe\n", node, regmap); + return PTR_ERR(regmap); + } + + for (i = 0; i < num; i++) { + const struct mtk_mux *mux = &muxes[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[mux->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, mux->id); + continue; + } + + hw = mtk_clk_register_mux(mux, regmap, lock); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", mux->name, + hw); + goto err; + } + + clk_data->hws[mux->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_mux *mux = &muxes[i]; + + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) + continue; + + mtk_clk_unregister_mux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); + } + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_muxes); + +void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, + struct clk_hw_onecell_data *clk_data) +{ + int i; + + if (!clk_data) + return; + + for (i = num; i > 0; i--) { + const struct mtk_mux *mux = &muxes[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[mux->id])) + continue; + + mtk_clk_unregister_mux(clk_data->hws[mux->id]); + clk_data->hws[mux->id] = ERR_PTR(-ENOENT); + } +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_muxes); + +/* + * This clock notifier is called when the frequency of the parent + * PLL clock is to be changed. The idea is to switch the parent to a + * stable clock, such as the main oscillator, while the PLL frequency + * stabilizes. + */ +static int mtk_clk_mux_notifier_cb(struct notifier_block *nb, + unsigned long event, void *_data) +{ + struct clk_notifier_data *data = _data; + struct clk_hw *hw = __clk_get_hw(data->clk); + struct mtk_mux_nb *mux_nb = to_mtk_mux_nb(nb); + int ret = 0; + + switch (event) { + case PRE_RATE_CHANGE: + mux_nb->original_index = mux_nb->ops->get_parent(hw); + ret = mux_nb->ops->set_parent(hw, mux_nb->bypass_index); + break; + case POST_RATE_CHANGE: + case ABORT_RATE_CHANGE: + ret = mux_nb->ops->set_parent(hw, mux_nb->original_index); + break; + } + + return notifier_from_errno(ret); +} + +int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk, + struct mtk_mux_nb *mux_nb) +{ + mux_nb->nb.notifier_call = mtk_clk_mux_notifier_cb; + + return devm_clk_notifier_register(dev, clk, &mux_nb->nb); +} +EXPORT_SYMBOL_GPL(devm_mtk_clk_mux_notifier_register); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h new file mode 100644 index 000000000..83ff420f4 --- /dev/null +++ b/drivers/clk/mediatek/clk-mux.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2018 MediaTek Inc. + * Author: Owen Chen <owen.chen@mediatek.com> + */ + +#ifndef __DRV_CLK_MTK_MUX_H +#define __DRV_CLK_MTK_MUX_H + +#include <linux/notifier.h> +#include <linux/spinlock.h> +#include <linux/types.h> + +struct clk; +struct clk_hw_onecell_data; +struct clk_ops; +struct device; +struct device_node; + +struct mtk_mux { + int id; + const char *name; + const char * const *parent_names; + unsigned int flags; + + u32 mux_ofs; + u32 set_ofs; + u32 clr_ofs; + u32 upd_ofs; + + u8 mux_shift; + u8 mux_width; + u8 gate_shift; + s8 upd_shift; + + const struct clk_ops *ops; + signed char num_parents; +}; + +#define GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + _gate, _upd_ofs, _upd, _flags, _ops) { \ + .id = _id, \ + .name = _name, \ + .mux_ofs = _mux_ofs, \ + .set_ofs = _mux_set_ofs, \ + .clr_ofs = _mux_clr_ofs, \ + .upd_ofs = _upd_ofs, \ + .mux_shift = _shift, \ + .mux_width = _width, \ + .gate_shift = _gate, \ + .upd_shift = _upd, \ + .parent_names = _parents, \ + .num_parents = ARRAY_SIZE(_parents), \ + .flags = _flags, \ + .ops = &_ops, \ + } + +extern const struct clk_ops mtk_mux_clr_set_upd_ops; +extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; + +#define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + _gate, _upd_ofs, _upd, _flags) \ + GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + _gate, _upd_ofs, _upd, _flags, \ + mtk_mux_gate_clr_set_upd_ops) + +#define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + _gate, _upd_ofs, _upd) \ + MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, \ + _mux_ofs, _mux_set_ofs, _mux_clr_ofs, _shift, \ + _width, _gate, _upd_ofs, _upd, \ + CLK_SET_RATE_PARENT) + +#define MUX_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + _upd_ofs, _upd) \ + GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ + _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ + 0, _upd_ofs, _upd, CLK_SET_RATE_PARENT, \ + mtk_mux_clr_set_upd_ops) + +int mtk_clk_register_muxes(const struct mtk_mux *muxes, + int num, struct device_node *node, + spinlock_t *lock, + struct clk_hw_onecell_data *clk_data); + +void mtk_clk_unregister_muxes(const struct mtk_mux *muxes, int num, + struct clk_hw_onecell_data *clk_data); + +struct mtk_mux_nb { + struct notifier_block nb; + const struct clk_ops *ops; + + u8 bypass_index; /* Which parent to temporarily use */ + u8 original_index; /* Set by notifier callback */ +}; + +#define to_mtk_mux_nb(_nb) container_of(_nb, struct mtk_mux_nb, nb) + +int devm_mtk_clk_mux_notifier_register(struct device *dev, struct clk *clk, + struct mtk_mux_nb *mux_nb); + +#endif /* __DRV_CLK_MTK_MUX_H */ diff --git a/drivers/clk/mediatek/clk-pll.c b/drivers/clk/mediatek/clk-pll.c new file mode 100644 index 000000000..54e6cfd29 --- /dev/null +++ b/drivers/clk/mediatek/clk-pll.c @@ -0,0 +1,465 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#include <linux/clk-provider.h> +#include <linux/container_of.h> +#include <linux/delay.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/slab.h> + +#include "clk-pll.h" + +#define MHZ (1000 * 1000) + +#define REG_CON0 0 +#define REG_CON1 4 + +#define CON0_BASE_EN BIT(0) +#define CON0_PWR_ON BIT(0) +#define CON0_ISO_EN BIT(1) +#define PCW_CHG_MASK BIT(31) + +#define AUDPLL_TUNER_EN BIT(31) + +#define POSTDIV_MASK 0x7 + +/* default 7 bits integer, can be overridden with pcwibits. */ +#define INTEGER_BITS 7 + +/* + * MediaTek PLLs are configured through their pcw value. The pcw value describes + * a divider in the PLL feedback loop which consists of 7 bits for the integer + * part and the remaining bits (if present) for the fractional part. Also they + * have a 3 bit power-of-two post divider. + */ + +struct mtk_clk_pll { + struct clk_hw hw; + void __iomem *base_addr; + void __iomem *pd_addr; + void __iomem *pwr_addr; + void __iomem *tuner_addr; + void __iomem *tuner_en_addr; + void __iomem *pcw_addr; + void __iomem *pcw_chg_addr; + void __iomem *en_addr; + const struct mtk_pll_data *data; +}; + +static inline struct mtk_clk_pll *to_mtk_clk_pll(struct clk_hw *hw) +{ + return container_of(hw, struct mtk_clk_pll, hw); +} + +static int mtk_pll_is_prepared(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + return (readl(pll->en_addr) & BIT(pll->data->pll_en_bit)) != 0; +} + +static unsigned long __mtk_pll_recalc_rate(struct mtk_clk_pll *pll, u32 fin, + u32 pcw, int postdiv) +{ + int pcwbits = pll->data->pcwbits; + int pcwfbits = 0; + int ibits; + u64 vco; + u8 c = 0; + + /* The fractional part of the PLL divider. */ + ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS; + if (pcwbits > ibits) + pcwfbits = pcwbits - ibits; + + vco = (u64)fin * pcw; + + if (pcwfbits && (vco & GENMASK(pcwfbits - 1, 0))) + c = 1; + + vco >>= pcwfbits; + + if (c) + vco++; + + return ((unsigned long)vco + postdiv - 1) / postdiv; +} + +static void __mtk_pll_tuner_enable(struct mtk_clk_pll *pll) +{ + u32 r; + + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) | BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { + r = readl(pll->tuner_addr) | AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } +} + +static void __mtk_pll_tuner_disable(struct mtk_clk_pll *pll) +{ + u32 r; + + if (pll->tuner_en_addr) { + r = readl(pll->tuner_en_addr) & ~BIT(pll->data->tuner_en_bit); + writel(r, pll->tuner_en_addr); + } else if (pll->tuner_addr) { + r = readl(pll->tuner_addr) & ~AUDPLL_TUNER_EN; + writel(r, pll->tuner_addr); + } +} + +static void mtk_pll_set_rate_regs(struct mtk_clk_pll *pll, u32 pcw, + int postdiv) +{ + u32 chg, val; + + /* disable tuner */ + __mtk_pll_tuner_disable(pll); + + /* set postdiv */ + val = readl(pll->pd_addr); + val &= ~(POSTDIV_MASK << pll->data->pd_shift); + val |= (ffs(postdiv) - 1) << pll->data->pd_shift; + + /* postdiv and pcw need to set at the same time if on same register */ + if (pll->pd_addr != pll->pcw_addr) { + writel(val, pll->pd_addr); + val = readl(pll->pcw_addr); + } + + /* set pcw */ + val &= ~GENMASK(pll->data->pcw_shift + pll->data->pcwbits - 1, + pll->data->pcw_shift); + val |= pcw << pll->data->pcw_shift; + writel(val, pll->pcw_addr); + chg = readl(pll->pcw_chg_addr) | PCW_CHG_MASK; + writel(chg, pll->pcw_chg_addr); + if (pll->tuner_addr) + writel(val + 1, pll->tuner_addr); + + /* restore tuner_en */ + __mtk_pll_tuner_enable(pll); + + udelay(20); +} + +/* + * mtk_pll_calc_values - calculate good values for a given input frequency. + * @pll: The pll + * @pcw: The pcw value (output) + * @postdiv: The post divider (output) + * @freq: The desired target frequency + * @fin: The input frequency + * + */ +static void mtk_pll_calc_values(struct mtk_clk_pll *pll, u32 *pcw, u32 *postdiv, + u32 freq, u32 fin) +{ + unsigned long fmin = pll->data->fmin ? pll->data->fmin : (1000 * MHZ); + const struct mtk_pll_div_table *div_table = pll->data->div_table; + u64 _pcw; + int ibits; + u32 val; + + if (freq > pll->data->fmax) + freq = pll->data->fmax; + + if (div_table) { + if (freq > div_table[0].freq) + freq = div_table[0].freq; + + for (val = 0; div_table[val + 1].freq != 0; val++) { + if (freq > div_table[val + 1].freq) + break; + } + *postdiv = 1 << val; + } else { + for (val = 0; val < 5; val++) { + *postdiv = 1 << val; + if ((u64)freq * *postdiv >= fmin) + break; + } + } + + /* _pcw = freq * postdiv / fin * 2^pcwfbits */ + ibits = pll->data->pcwibits ? pll->data->pcwibits : INTEGER_BITS; + _pcw = ((u64)freq << val) << (pll->data->pcwbits - ibits); + do_div(_pcw, fin); + + *pcw = (u32)_pcw; +} + +static int mtk_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + u32 postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, parent_rate); + mtk_pll_set_rate_regs(pll, pcw, postdiv); + + return 0; +} + +static unsigned long mtk_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 postdiv; + u32 pcw; + + postdiv = (readl(pll->pd_addr) >> pll->data->pd_shift) & POSTDIV_MASK; + postdiv = 1 << postdiv; + + pcw = readl(pll->pcw_addr) >> pll->data->pcw_shift; + pcw &= GENMASK(pll->data->pcwbits - 1, 0); + + return __mtk_pll_recalc_rate(pll, parent_rate, pcw, postdiv); +} + +static long mtk_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 pcw = 0; + int postdiv; + + mtk_pll_calc_values(pll, &pcw, &postdiv, rate, *prate); + + return __mtk_pll_recalc_rate(pll, *prate, pcw, postdiv); +} + +static int mtk_pll_prepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + r = readl(pll->pwr_addr) | CON0_PWR_ON; + writel(r, pll->pwr_addr); + udelay(1); + + r = readl(pll->pwr_addr) & ~CON0_ISO_EN; + writel(r, pll->pwr_addr); + udelay(1); + + r = readl(pll->en_addr) | BIT(pll->data->pll_en_bit); + writel(r, pll->en_addr); + + if (pll->data->en_mask) { + r = readl(pll->base_addr + REG_CON0) | pll->data->en_mask; + writel(r, pll->base_addr + REG_CON0); + } + + __mtk_pll_tuner_enable(pll); + + udelay(20); + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr + REG_CON0); + r |= pll->data->rst_bar_mask; + writel(r, pll->base_addr + REG_CON0); + } + + return 0; +} + +static void mtk_pll_unprepare(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + u32 r; + + if (pll->data->flags & HAVE_RST_BAR) { + r = readl(pll->base_addr + REG_CON0); + r &= ~pll->data->rst_bar_mask; + writel(r, pll->base_addr + REG_CON0); + } + + __mtk_pll_tuner_disable(pll); + + if (pll->data->en_mask) { + r = readl(pll->base_addr + REG_CON0) & ~pll->data->en_mask; + writel(r, pll->base_addr + REG_CON0); + } + + r = readl(pll->en_addr) & ~BIT(pll->data->pll_en_bit); + writel(r, pll->en_addr); + + r = readl(pll->pwr_addr) | CON0_ISO_EN; + writel(r, pll->pwr_addr); + + r = readl(pll->pwr_addr) & ~CON0_PWR_ON; + writel(r, pll->pwr_addr); +} + +static const struct clk_ops mtk_pll_ops = { + .is_prepared = mtk_pll_is_prepared, + .prepare = mtk_pll_prepare, + .unprepare = mtk_pll_unprepare, + .recalc_rate = mtk_pll_recalc_rate, + .round_rate = mtk_pll_round_rate, + .set_rate = mtk_pll_set_rate, +}; + +static struct clk_hw *mtk_clk_register_pll(const struct mtk_pll_data *data, + void __iomem *base) +{ + struct mtk_clk_pll *pll; + struct clk_init_data init = {}; + int ret; + const char *parent_name = "clk26m"; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->base_addr = base + data->reg; + pll->pwr_addr = base + data->pwr_reg; + pll->pd_addr = base + data->pd_reg; + pll->pcw_addr = base + data->pcw_reg; + if (data->pcw_chg_reg) + pll->pcw_chg_addr = base + data->pcw_chg_reg; + else + pll->pcw_chg_addr = pll->base_addr + REG_CON1; + if (data->tuner_reg) + pll->tuner_addr = base + data->tuner_reg; + if (data->tuner_en_reg || data->tuner_en_bit) + pll->tuner_en_addr = base + data->tuner_en_reg; + if (data->en_reg) + pll->en_addr = base + data->en_reg; + else + pll->en_addr = pll->base_addr + REG_CON0; + pll->hw.init = &init; + pll->data = data; + + init.name = data->name; + init.flags = (data->flags & PLL_AO) ? CLK_IS_CRITICAL : 0; + init.ops = &mtk_pll_ops; + if (data->parent_name) + init.parent_names = &data->parent_name; + else + init.parent_names = &parent_name; + init.num_parents = 1; + + ret = clk_hw_register(NULL, &pll->hw); + + if (ret) { + kfree(pll); + return ERR_PTR(ret); + } + + return &pll->hw; +} + +static void mtk_clk_unregister_pll(struct clk_hw *hw) +{ + struct mtk_clk_pll *pll; + + if (!hw) + return; + + pll = to_mtk_clk_pll(hw); + + clk_hw_unregister(hw); + kfree(pll); +} + +int mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct clk_hw_onecell_data *clk_data) +{ + void __iomem *base; + int i; + struct clk_hw *hw; + + base = of_iomap(node, 0); + if (!base) { + pr_err("%s(): ioremap failed\n", __func__); + return -EINVAL; + } + + for (i = 0; i < num_plls; i++) { + const struct mtk_pll_data *pll = &plls[i]; + + if (!IS_ERR_OR_NULL(clk_data->hws[pll->id])) { + pr_warn("%pOF: Trying to register duplicate clock ID: %d\n", + node, pll->id); + continue; + } + + hw = mtk_clk_register_pll(pll, base); + + if (IS_ERR(hw)) { + pr_err("Failed to register clk %s: %pe\n", pll->name, + hw); + goto err; + } + + clk_data->hws[pll->id] = hw; + } + + return 0; + +err: + while (--i >= 0) { + const struct mtk_pll_data *pll = &plls[i]; + + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + clk_data->hws[pll->id] = ERR_PTR(-ENOENT); + } + + iounmap(base); + + return PTR_ERR(hw); +} +EXPORT_SYMBOL_GPL(mtk_clk_register_plls); + +static __iomem void *mtk_clk_pll_get_base(struct clk_hw *hw, + const struct mtk_pll_data *data) +{ + struct mtk_clk_pll *pll = to_mtk_clk_pll(hw); + + return pll->base_addr - data->reg; +} + +void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, + struct clk_hw_onecell_data *clk_data) +{ + __iomem void *base = NULL; + int i; + + if (!clk_data) + return; + + for (i = num_plls; i > 0; i--) { + const struct mtk_pll_data *pll = &plls[i - 1]; + + if (IS_ERR_OR_NULL(clk_data->hws[pll->id])) + continue; + + /* + * This is quite ugly but unfortunately the clks don't have + * any device tied to them, so there's no place to store the + * pointer to the I/O region base address. We have to fetch + * it from one of the registered clks. + */ + base = mtk_clk_pll_get_base(clk_data->hws[pll->id], pll); + + mtk_clk_unregister_pll(clk_data->hws[pll->id]); + clk_data->hws[pll->id] = ERR_PTR(-ENOENT); + } + + iounmap(base); +} +EXPORT_SYMBOL_GPL(mtk_clk_unregister_plls); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/clk-pll.h b/drivers/clk/mediatek/clk-pll.h new file mode 100644 index 000000000..fe3199715 --- /dev/null +++ b/drivers/clk/mediatek/clk-pll.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014 MediaTek Inc. + * Author: James Liao <jamesjj.liao@mediatek.com> + */ + +#ifndef __DRV_CLK_MTK_PLL_H +#define __DRV_CLK_MTK_PLL_H + +#include <linux/types.h> + +struct clk_ops; +struct clk_hw_onecell_data; +struct device_node; + +struct mtk_pll_div_table { + u32 div; + unsigned long freq; +}; + +#define HAVE_RST_BAR BIT(0) +#define PLL_AO BIT(1) + +struct mtk_pll_data { + int id; + const char *name; + u32 reg; + u32 pwr_reg; + u32 en_mask; + u32 pd_reg; + u32 tuner_reg; + u32 tuner_en_reg; + u8 tuner_en_bit; + int pd_shift; + unsigned int flags; + const struct clk_ops *ops; + u32 rst_bar_mask; + unsigned long fmin; + unsigned long fmax; + int pcwbits; + int pcwibits; + u32 pcw_reg; + int pcw_shift; + u32 pcw_chg_reg; + const struct mtk_pll_div_table *div_table; + const char *parent_name; + u32 en_reg; + u8 pll_en_bit; /* Assume 0, indicates BIT(0) by default */ +}; + +int mtk_clk_register_plls(struct device_node *node, + const struct mtk_pll_data *plls, int num_plls, + struct clk_hw_onecell_data *clk_data); +void mtk_clk_unregister_plls(const struct mtk_pll_data *plls, int num_plls, + struct clk_hw_onecell_data *clk_data); + +#endif /* __DRV_CLK_MTK_PLL_H */ diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c new file mode 100644 index 000000000..290ceda84 --- /dev/null +++ b/drivers/clk/mediatek/reset.c @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2014 MediaTek Inc. + */ + +#include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +#include "reset.h" + +static inline struct mtk_clk_rst_data *to_mtk_clk_rst_data(struct reset_controller_dev *rcdev) +{ + return container_of(rcdev, struct mtk_clk_rst_data, rcdev); +} + +static int mtk_reset_update(struct reset_controller_dev *rcdev, + unsigned long id, bool deassert) +{ + struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); + unsigned int val = deassert ? 0 : ~0; + + return regmap_update_bits(data->regmap, + data->desc->rst_bank_ofs[id / RST_NR_PER_BANK], + BIT(id % RST_NR_PER_BANK), val); +} + +static int mtk_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return mtk_reset_update(rcdev, id, false); +} + +static int mtk_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return mtk_reset_update(rcdev, id, true); +} + +static int mtk_reset(struct reset_controller_dev *rcdev, unsigned long id) +{ + int ret; + + ret = mtk_reset_assert(rcdev, id); + if (ret) + return ret; + + return mtk_reset_deassert(rcdev, id); +} + +static int mtk_reset_update_set_clr(struct reset_controller_dev *rcdev, + unsigned long id, bool deassert) +{ + struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); + unsigned int deassert_ofs = deassert ? 0x4 : 0; + + return regmap_write(data->regmap, + data->desc->rst_bank_ofs[id / RST_NR_PER_BANK] + + deassert_ofs, + BIT(id % RST_NR_PER_BANK)); +} + +static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return mtk_reset_update_set_clr(rcdev, id, false); +} + +static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return mtk_reset_update_set_clr(rcdev, id, true); +} + +static int mtk_reset_set_clr(struct reset_controller_dev *rcdev, + unsigned long id) +{ + int ret; + + ret = mtk_reset_assert_set_clr(rcdev, id); + if (ret) + return ret; + return mtk_reset_deassert_set_clr(rcdev, id); +} + +static const struct reset_control_ops mtk_reset_ops = { + .assert = mtk_reset_assert, + .deassert = mtk_reset_deassert, + .reset = mtk_reset, +}; + +static const struct reset_control_ops mtk_reset_ops_set_clr = { + .assert = mtk_reset_assert_set_clr, + .deassert = mtk_reset_deassert_set_clr, + .reset = mtk_reset_set_clr, +}; + +static int reset_xlate(struct reset_controller_dev *rcdev, + const struct of_phandle_args *reset_spec) +{ + struct mtk_clk_rst_data *data = to_mtk_clk_rst_data(rcdev); + + if (reset_spec->args[0] >= rcdev->nr_resets || + reset_spec->args[0] >= data->desc->rst_idx_map_nr) + return -EINVAL; + + return data->desc->rst_idx_map[reset_spec->args[0]]; +} + +int mtk_register_reset_controller(struct device_node *np, + const struct mtk_clk_rst_desc *desc) +{ + struct regmap *regmap; + const struct reset_control_ops *rcops = NULL; + struct mtk_clk_rst_data *data; + int ret; + + if (!desc) { + pr_err("mtk clock reset desc is NULL\n"); + return -EINVAL; + } + + switch (desc->version) { + case MTK_RST_SIMPLE: + rcops = &mtk_reset_ops; + break; + case MTK_RST_SET_CLR: + rcops = &mtk_reset_ops_set_clr; + break; + default: + pr_err("Unknown reset version %d\n", desc->version); + return -EINVAL; + } + + regmap = device_node_to_regmap(np); + if (IS_ERR(regmap)) { + pr_err("Cannot find regmap for %pOF: %pe\n", np, regmap); + return -EINVAL; + } + + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->desc = desc; + data->regmap = regmap; + data->rcdev.owner = THIS_MODULE; + data->rcdev.ops = rcops; + data->rcdev.of_node = np; + + if (data->desc->rst_idx_map_nr > 0) { + data->rcdev.of_reset_n_cells = 1; + data->rcdev.nr_resets = desc->rst_idx_map_nr; + data->rcdev.of_xlate = reset_xlate; + } else { + data->rcdev.nr_resets = desc->rst_bank_nr * RST_NR_PER_BANK; + } + + ret = reset_controller_register(&data->rcdev); + if (ret) { + pr_err("could not register reset controller: %d\n", ret); + kfree(data); + return ret; + } + + return 0; +} + +int mtk_register_reset_controller_with_dev(struct device *dev, + const struct mtk_clk_rst_desc *desc) +{ + struct device_node *np = dev->of_node; + struct regmap *regmap; + const struct reset_control_ops *rcops = NULL; + struct mtk_clk_rst_data *data; + int ret; + + if (!desc) { + dev_err(dev, "mtk clock reset desc is NULL\n"); + return -EINVAL; + } + + switch (desc->version) { + case MTK_RST_SIMPLE: + rcops = &mtk_reset_ops; + break; + case MTK_RST_SET_CLR: + rcops = &mtk_reset_ops_set_clr; + break; + default: + dev_err(dev, "Unknown reset version %d\n", desc->version); + return -EINVAL; + } + + regmap = device_node_to_regmap(np); + if (IS_ERR(regmap)) { + dev_err(dev, "Cannot find regmap %pe\n", regmap); + return -EINVAL; + } + + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->desc = desc; + data->regmap = regmap; + data->rcdev.owner = THIS_MODULE; + data->rcdev.ops = rcops; + data->rcdev.of_node = np; + data->rcdev.dev = dev; + + if (data->desc->rst_idx_map_nr > 0) { + data->rcdev.of_reset_n_cells = 1; + data->rcdev.nr_resets = desc->rst_idx_map_nr; + data->rcdev.of_xlate = reset_xlate; + } else { + data->rcdev.nr_resets = desc->rst_bank_nr * RST_NR_PER_BANK; + } + + ret = devm_reset_controller_register(dev, &data->rcdev); + if (ret) { + dev_err(dev, "could not register reset controller: %d\n", ret); + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(mtk_register_reset_controller_with_dev); + +MODULE_LICENSE("GPL"); diff --git a/drivers/clk/mediatek/reset.h b/drivers/clk/mediatek/reset.h new file mode 100644 index 000000000..6a58a3d59 --- /dev/null +++ b/drivers/clk/mediatek/reset.h @@ -0,0 +1,82 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022 MediaTek Inc. + */ + +#ifndef __DRV_CLK_MTK_RESET_H +#define __DRV_CLK_MTK_RESET_H + +#include <linux/reset-controller.h> +#include <linux/types.h> + +#define RST_NR_PER_BANK 32 + +/* Infra global controller reset set register */ +#define INFRA_RST0_SET_OFFSET 0x120 +#define INFRA_RST1_SET_OFFSET 0x130 +#define INFRA_RST2_SET_OFFSET 0x140 +#define INFRA_RST3_SET_OFFSET 0x150 +#define INFRA_RST4_SET_OFFSET 0x730 + +/** + * enum mtk_reset_version - Version of MediaTek clock reset controller. + * @MTK_RST_SIMPLE: Use the same registers for bit set and clear. + * @MTK_RST_SET_CLR: Use separate registers for bit set and clear. + * @MTK_RST_MAX: Total quantity of version for MediaTek clock reset controller. + */ +enum mtk_reset_version { + MTK_RST_SIMPLE = 0, + MTK_RST_SET_CLR, + MTK_RST_MAX, +}; + +/** + * struct mtk_clk_rst_desc - Description of MediaTek clock reset. + * @version: Reset version which is defined in enum mtk_reset_version. + * @rst_bank_ofs: Pointer to an array containing base offsets of the reset register. + * @rst_bank_nr: Quantity of reset bank. + * @rst_idx_map:Pointer to an array containing ids if input argument is index. + * This array is not necessary if our input argument does not mean index. + * @rst_idx_map_nr: Quantity of reset index map. + */ +struct mtk_clk_rst_desc { + enum mtk_reset_version version; + u16 *rst_bank_ofs; + u32 rst_bank_nr; + u16 *rst_idx_map; + u32 rst_idx_map_nr; +}; + +/** + * struct mtk_clk_rst_data - Data of MediaTek clock reset controller. + * @regmap: Pointer to base address of reset register address. + * @rcdev: Reset controller device. + * @desc: Pointer to description of the reset controller. + */ +struct mtk_clk_rst_data { + struct regmap *regmap; + struct reset_controller_dev rcdev; + const struct mtk_clk_rst_desc *desc; +}; + +/** + * mtk_register_reset_controller - Register MediaTek clock reset controller + * @np: Pointer to device node. + * @desc: Constant pointer to description of clock reset. + * + * Return: 0 on success and errorno otherwise. + */ +int mtk_register_reset_controller(struct device_node *np, + const struct mtk_clk_rst_desc *desc); + +/** + * mtk_register_reset_controller - Register mediatek clock reset controller with device + * @np: Pointer to device. + * @desc: Constant pointer to description of clock reset. + * + * Return: 0 on success and errorno otherwise. + */ +int mtk_register_reset_controller_with_dev(struct device *dev, + const struct mtk_clk_rst_desc *desc); + +#endif /* __DRV_CLK_MTK_RESET_H */ |