diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-10 21:42:19 +0300 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2020-06-10 21:42:19 +0300 |
commit | 6f630784cc0d92fb58ea326e2bc01aa056279ecb (patch) | |
tree | f836a2bb79463d7634f92aa51d324bd548a3832b /drivers/clk/socfpga | |
parent | 3a2a8751742133a7bbc49b9d1bcbd52e212edff6 (diff) | |
parent | 9ac1eafa885a9b2d3becd4f2e622829b1f5b9b86 (diff) | |
download | linux-6f630784cc0d92fb58ea326e2bc01aa056279ecb.tar.xz |
Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux
Pull clk updates from Stephen Boyd:
"This time around we have four lines of diff in the core framework,
removing a function that isn't used anymore. Otherwise the main new
thing for the common clk framework is that it is selectable in the
Kconfig language now. Hopefully this will let clk drivers and clk
consumers be testable on more than the architectures that support the
clk framework. The goal is to introduce some Kunit tests for the
framework.
Outside of the core framework we have the usual set of various driver
updates and non-critical fixes. The dirstat shows that the new
Baikal-T1 driver is the largest addition this time around in terms of
lines of code. After that the x86 (Intel), Qualcomm, and Mediatek
drivers introduce many lines to support new or upcoming SoCs. After
that the dirstat shows the usual suspects working on their SoC support
by fixing minor bugs, correcting data and converting some of their DT
bindings to YAML.
Core:
- Allow the COMMON_CLK config to be selectable
New Drivers:
- Clk driver for Baikal-T1 SoCs
- Mediatek MT6765 clock support
- Support for Intel Agilex clks
- Add support for X1830 and X1000 Ingenic SoC clk controllers
- Add support for the new Renesas RZ/G1H (R8A7742) SoC
- Add support for Qualcomm's MSM8939 Generic Clock Controller
Updates:
- Support IDT VersaClock 5P49V5925
- Bunch of updates for HSDK clock generation unit (CGU) driver
- Start making audio and GPU clks work on Marvell MMP2/MMP3 SoCs
- Add some GPU, NPU, and UFS clks to Qualcomm SM8150 driver
- Enable supply regulators for GPU gdscs on Qualcomm SoCs
- Add support for Si5342, Si5344 and Si5345 chips
- Support custom flags in Xilinx zynq firmware
- Various small fixes to the Xilinx clk driver
- A single minor rounding fix for the legacy Allwinner clock support
- A few patches from Abel Vesa as preparation of adding audiomix
clock support on i.MX
- A couple of cleanups from Anson Huang for i.MX clk-sscg-pll and
clk-pllv3 drivers
- Drop dependency on ARM64 for i.MX8M clock driver, to support
aarch32 mode on aarch64 hardware
- A series from Peng Fan to improve i.MX8M clock drivers, using
composite clock for core and bus clk slice
- Set a better parent clock for flexcan on i.MX6UL to support CiA102
defined bit rates
- A couple changes for EMC frequency scaling on Tegra210
- Support for CPU frequency scaling on Tegra20/Tegra30
- New clk gate for CSI test pattern generator on Tegra210
- Regression fixes for Samsung exynos542x and exynos5433 SoCs
- Use of fallthrough; attribute for Samsung s3c24xx
- Updates and fixup HDMI and video clocks on Meson8b
- Fixup reset polarity on Meson8b
- Fix GPU glitch free mux switch on Meson gx and g12
- A minor fix for the currently unused suspend/resume handling on
Renesas RZ/A1 and RZ/A2
- Two more conversions of Renesas DT bindings to json-schema
- Add support for the USB 2.0 clock selector on Renesas R-Car M3-W+"
* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (155 commits)
clk: mediatek: Remove ifr{0,1}_cfg_regs structures
clk: baikal-t1: remove redundant assignment to variable 'divider'
clk: baikal-t1: fix spelling mistake "Uncompatible" -> "Incompatible"
dt-bindings: clock: Add a missing include to MMP Audio Clock binding
dt: Add bindings for IDT VersaClock 5P49V5925
clk: vc5: Add support for IDT VersaClock 5P49V6965
clk: Add Baikal-T1 CCU Dividers driver
clk: Add Baikal-T1 CCU PLLs driver
dt-bindings: clk: Add Baikal-T1 CCU Dividers binding
dt-bindings: clk: Add Baikal-T1 CCU PLLs binding
clk: mediatek: assign the initial value to clk_init_data of mtk_mux
clk: mediatek: Add MT6765 clock support
clk: mediatek: add mt6765 clock IDs
dt-bindings: clock: mediatek: document clk bindings vcodecsys for Mediatek MT6765 SoC
dt-bindings: clock: mediatek: document clk bindings mipi0a for Mediatek MT6765 SoC
dt-bindings: clock: mediatek: document clk bindings for Mediatek MT6765 SoC
CLK: HSDK: CGU: add support for 148.5MHz clock
CLK: HSDK: CGU: support PLL bypassing
CLK: HSDK: CGU: check if PLL is bypassed first
clk: clk-si5341: Add support for the Si5345 series
...
Diffstat (limited to 'drivers/clk/socfpga')
-rw-r--r-- | drivers/clk/socfpga/Makefile | 2 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-agilex.c | 454 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-gate-s10.c | 5 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-periph-s10.c | 10 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-pll-a10.c | 4 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-pll-s10.c | 78 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-pll.c | 4 | ||||
-rw-r--r-- | drivers/clk/socfpga/clk-s10.c | 160 | ||||
-rw-r--r-- | drivers/clk/socfpga/stratix10-clk.h | 10 |
9 files changed, 676 insertions, 51 deletions
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile index ce5aa7802eb8..bf736f8d201a 100644 --- a/drivers/clk/socfpga/Makefile +++ b/drivers/clk/socfpga/Makefile @@ -3,3 +3,5 @@ obj-$(CONFIG_ARCH_SOCFPGA) += clk.o clk-gate.o clk-pll.o clk-periph.o obj-$(CONFIG_ARCH_SOCFPGA) += clk-pll-a10.o clk-periph-a10.o clk-gate-a10.o obj-$(CONFIG_ARCH_STRATIX10) += clk-s10.o obj-$(CONFIG_ARCH_STRATIX10) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o +obj-$(CONFIG_ARCH_AGILEX) += clk-agilex.o +obj-$(CONFIG_ARCH_AGILEX) += clk-pll-s10.o clk-periph-s10.o clk-gate-s10.o diff --git a/drivers/clk/socfpga/clk-agilex.c b/drivers/clk/socfpga/clk-agilex.c new file mode 100644 index 000000000000..699527f7e764 --- /dev/null +++ b/drivers/clk/socfpga/clk-agilex.c @@ -0,0 +1,454 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2019, Intel Corporation + */ +#include <linux/slab.h> +#include <linux/clk-provider.h> +#include <linux/of_device.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include <dt-bindings/clock/agilex-clock.h> + +#include "stratix10-clk.h" + +static const struct clk_parent_data pll_mux[] = { + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data cntr_mux[] = { + { .fw_name = "main_pll", + .name = "main_pll", }, + { .fw_name = "periph_pll", + .name = "periph_pll", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data boot_mux[] = { + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, +}; + +static const struct clk_parent_data mpu_free_mux[] = { + { .fw_name = "main_pll_c0", + .name = "main_pll_c0", }, + { .fw_name = "peri_pll_c0", + .name = "peri_pll_c0", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data noc_free_mux[] = { + { .fw_name = "main_pll_c1", + .name = "main_pll_c1", }, + { .fw_name = "peri_pll_c1", + .name = "peri_pll_c1", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data emaca_free_mux[] = { + { .fw_name = "main_pll_c2", + .name = "main_pll_c2", }, + { .fw_name = "peri_pll_c2", + .name = "peri_pll_c2", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data emacb_free_mux[] = { + { .fw_name = "main_pll_c3", + .name = "main_pll_c3", }, + { .fw_name = "peri_pll_c3", + .name = "peri_pll_c3", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data emac_ptp_free_mux[] = { + { .fw_name = "main_pll_c3", + .name = "main_pll_c3", }, + { .fw_name = "peri_pll_c3", + .name = "peri_pll_c3", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data gpio_db_free_mux[] = { + { .fw_name = "main_pll_c3", + .name = "main_pll_c3", }, + { .fw_name = "peri_pll_c3", + .name = "peri_pll_c3", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data psi_ref_free_mux[] = { + { .fw_name = "main_pll_c3", + .name = "main_pll_c3", }, + { .fw_name = "peri_pll_c3", + .name = "peri_pll_c3", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data sdmmc_free_mux[] = { + { .fw_name = "main_pll_c3", + .name = "main_pll_c3", }, + { .fw_name = "peri_pll_c3", + .name = "peri_pll_c3", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data s2f_usr0_free_mux[] = { + { .fw_name = "main_pll_c2", + .name = "main_pll_c2", }, + { .fw_name = "peri_pll_c2", + .name = "peri_pll_c2", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data s2f_usr1_free_mux[] = { + { .fw_name = "main_pll_c2", + .name = "main_pll_c2", }, + { .fw_name = "peri_pll_c2", + .name = "peri_pll_c2", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data mpu_mux[] = { + { .fw_name = "mpu_free_clk", + .name = "mpu_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_usr0_mux[] = { + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_mux[] = { + { .fw_name = "emaca_free_clk", + .name = "emaca_free_clk", }, + { .fw_name = "emacb_free_clk", + .name = "emacb_free_clk", }, +}; + +static const struct clk_parent_data noc_mux[] = { + { .fw_name = "noc_free_clk", + .name = "noc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +/* clocks in AO (always on) controller */ +static const struct stratix10_pll_clock agilex_pll_clks[] = { + { AGILEX_BOOT_CLK, "boot_clk", boot_mux, ARRAY_SIZE(boot_mux), 0, + 0x0}, + { AGILEX_MAIN_PLL_CLK, "main_pll", pll_mux, ARRAY_SIZE(pll_mux), + 0, 0x48}, + { AGILEX_PERIPH_PLL_CLK, "periph_pll", pll_mux, ARRAY_SIZE(pll_mux), + 0, 0x9c}, +}; + +static const struct stratix10_perip_c_clock agilex_main_perip_c_clks[] = { + { AGILEX_MAIN_PLL_C0_CLK, "main_pll_c0", "main_pll", NULL, 1, 0, 0x58}, + { AGILEX_MAIN_PLL_C1_CLK, "main_pll_c1", "main_pll", NULL, 1, 0, 0x5C}, + { AGILEX_MAIN_PLL_C2_CLK, "main_pll_c2", "main_pll", NULL, 1, 0, 0x64}, + { AGILEX_MAIN_PLL_C3_CLK, "main_pll_c3", "main_pll", NULL, 1, 0, 0x68}, + { AGILEX_PERIPH_PLL_C0_CLK, "peri_pll_c0", "periph_pll", NULL, 1, 0, 0xAC}, + { AGILEX_PERIPH_PLL_C1_CLK, "peri_pll_c1", "periph_pll", NULL, 1, 0, 0xB0}, + { AGILEX_PERIPH_PLL_C2_CLK, "peri_pll_c2", "periph_pll", NULL, 1, 0, 0xB8}, + { AGILEX_PERIPH_PLL_C3_CLK, "peri_pll_c3", "periph_pll", NULL, 1, 0, 0xBC}, +}; + +static const struct stratix10_perip_cnt_clock agilex_main_perip_cnt_clks[] = { + { AGILEX_MPU_FREE_CLK, "mpu_free_clk", NULL, mpu_free_mux, ARRAY_SIZE(mpu_free_mux), + 0, 0x3C, 0, 0, 0}, + { AGILEX_NOC_FREE_CLK, "noc_free_clk", NULL, noc_free_mux, ARRAY_SIZE(noc_free_mux), + 0, 0x40, 0, 0, 1}, + { AGILEX_L4_SYS_FREE_CLK, "l4_sys_free_clk", "noc_free_clk", NULL, 1, 0, + 0, 4, 0, 0}, + { AGILEX_NOC_CLK, "noc_clk", NULL, noc_mux, ARRAY_SIZE(noc_mux), + 0, 0, 0, 0x30, 1}, + { AGILEX_EMAC_A_FREE_CLK, "emaca_free_clk", NULL, emaca_free_mux, ARRAY_SIZE(emaca_free_mux), + 0, 0xD4, 0, 0x88, 0}, + { AGILEX_EMAC_B_FREE_CLK, "emacb_free_clk", NULL, emacb_free_mux, ARRAY_SIZE(emacb_free_mux), + 0, 0xD8, 0, 0x88, 1}, + { AGILEX_EMAC_PTP_FREE_CLK, "emac_ptp_free_clk", NULL, emac_ptp_free_mux, + ARRAY_SIZE(emac_ptp_free_mux), 0, 0xDC, 0, 0x88, 2}, + { AGILEX_GPIO_DB_FREE_CLK, "gpio_db_free_clk", NULL, gpio_db_free_mux, + ARRAY_SIZE(gpio_db_free_mux), 0, 0xE0, 0, 0x88, 3}, + { AGILEX_SDMMC_FREE_CLK, "sdmmc_free_clk", NULL, sdmmc_free_mux, + ARRAY_SIZE(sdmmc_free_mux), 0, 0xE4, 0, 0x88, 4}, + { AGILEX_S2F_USER0_FREE_CLK, "s2f_user0_free_clk", NULL, s2f_usr0_free_mux, + ARRAY_SIZE(s2f_usr0_free_mux), 0, 0xE8, 0, 0, 0}, + { AGILEX_S2F_USER1_FREE_CLK, "s2f_user1_free_clk", NULL, s2f_usr1_free_mux, + ARRAY_SIZE(s2f_usr1_free_mux), 0, 0xEC, 0, 0x88, 5}, + { AGILEX_PSI_REF_FREE_CLK, "psi_ref_free_clk", NULL, psi_ref_free_mux, + ARRAY_SIZE(psi_ref_free_mux), 0, 0xF0, 0, 0x88, 6}, +}; + +static const struct stratix10_gate_clock agilex_gate_clks[] = { + { AGILEX_MPU_CLK, "mpu_clk", NULL, mpu_mux, ARRAY_SIZE(mpu_mux), 0, 0x24, + 0, 0, 0, 0, 0x30, 0, 0}, + { AGILEX_MPU_PERIPH_CLK, "mpu_periph_clk", "mpu_clk", NULL, 1, 0, 0x24, + 0, 0, 0, 0, 0, 0, 4}, + { AGILEX_MPU_L2RAM_CLK, "mpu_l2ram_clk", "mpu_clk", NULL, 1, 0, 0x24, + 0, 0, 0, 0, 0, 0, 2}, + { AGILEX_L4_MAIN_CLK, "l4_main_clk", "noc_clk", NULL, 1, 0, 0x24, + 1, 0x44, 0, 2, 0, 0, 0}, + { AGILEX_L4_MP_CLK, "l4_mp_clk", "noc_clk", NULL, 1, 0, 0x24, + 2, 0x44, 8, 2, 0, 0, 0}, + /* + * The l4_sp_clk feeds a 100 MHz clock to various peripherals, one of them + * being the SP timers, thus cannot get gated. + */ + { AGILEX_L4_SP_CLK, "l4_sp_clk", "noc_clk", NULL, 1, CLK_IS_CRITICAL, 0x24, + 3, 0x44, 16, 2, 0, 0, 0}, + { AGILEX_CS_AT_CLK, "cs_at_clk", "noc_clk", NULL, 1, 0, 0x24, + 4, 0x44, 24, 2, 0, 0, 0}, + { AGILEX_CS_TRACE_CLK, "cs_trace_clk", "noc_clk", NULL, 1, 0, 0x24, + 4, 0x44, 26, 2, 0, 0, 0}, + { AGILEX_CS_PDBG_CLK, "cs_pdbg_clk", "cs_at_clk", NULL, 1, 0, 0x24, + 4, 0x44, 28, 1, 0, 0, 0}, + { AGILEX_CS_TIMER_CLK, "cs_timer_clk", "noc_clk", NULL, 1, 0, 0x24, + 5, 0, 0, 0, 0, 0, 0}, + { AGILEX_S2F_USER0_CLK, "s2f_user0_clk", NULL, s2f_usr0_mux, ARRAY_SIZE(s2f_usr0_mux), 0, 0x24, + 6, 0, 0, 0, 0, 0, 0}, + { AGILEX_EMAC0_CLK, "emac0_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, + 0, 0, 0, 0, 0x94, 26, 0}, + { AGILEX_EMAC1_CLK, "emac1_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, + 1, 0, 0, 0, 0x94, 27, 0}, + { AGILEX_EMAC2_CLK, "emac2_clk", NULL, emac_mux, ARRAY_SIZE(emac_mux), 0, 0x7C, + 2, 0, 0, 0, 0x94, 28, 0}, + { AGILEX_EMAC_PTP_CLK, "emac_ptp_clk", "emac_ptp_free_clk", NULL, 1, 0, 0x7C, + 3, 0, 0, 0, 0, 0, 0}, + { AGILEX_GPIO_DB_CLK, "gpio_db_clk", "gpio_db_free_clk", NULL, 1, 0, 0x7C, + 4, 0x98, 0, 16, 0, 0, 0}, + { AGILEX_SDMMC_CLK, "sdmmc_clk", "sdmmc_free_clk", NULL, 1, 0, 0x7C, + 5, 0, 0, 0, 0, 0, 4}, + { AGILEX_S2F_USER1_CLK, "s2f_user1_clk", "s2f_user1_free_clk", NULL, 1, 0, 0x7C, + 6, 0, 0, 0, 0, 0, 0}, + { AGILEX_PSI_REF_CLK, "psi_ref_clk", "psi_ref_free_clk", NULL, 1, 0, 0x7C, + 7, 0, 0, 0, 0, 0, 0}, + { AGILEX_USB_CLK, "usb_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, + 8, 0, 0, 0, 0, 0, 0}, + { AGILEX_SPI_M_CLK, "spi_m_clk", "l4_mp_clk", NULL, 1, 0, 0x7C, + 9, 0, 0, 0, 0, 0, 0}, + { AGILEX_NAND_CLK, "nand_clk", "l4_main_clk", NULL, 1, 0, 0x7C, + 10, 0, 0, 0, 0, 0, 0}, +}; + +static int agilex_clk_register_c_perip(const struct stratix10_perip_c_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + clk = s10_register_periph(&clks[i], base); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + data->clk_data.clks[clks[i].id] = clk; + } + return 0; +} + +static int agilex_clk_register_cnt_perip(const struct stratix10_perip_cnt_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + clk = s10_register_cnt_periph(&clks[i], base); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + data->clk_data.clks[clks[i].id] = clk; + } + + return 0; +} + +static int agilex_clk_register_gate(const struct stratix10_gate_clock *clks, int nums, struct stratix10_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + clk = s10_register_gate(&clks[i], base); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + data->clk_data.clks[clks[i].id] = clk; + } + + return 0; +} + +static int agilex_clk_register_pll(const struct stratix10_pll_clock *clks, + int nums, struct stratix10_clock_data *data) +{ + struct clk *clk; + void __iomem *base = data->base; + int i; + + for (i = 0; i < nums; i++) { + clk = agilex_register_pll(&clks[i], base); + if (IS_ERR(clk)) { + pr_err("%s: failed to register clock %s\n", + __func__, clks[i].name); + continue; + } + data->clk_data.clks[clks[i].id] = clk; + } + + return 0; +} + +static struct stratix10_clock_data *__socfpga_agilex_clk_init(struct platform_device *pdev, + int nr_clks) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct stratix10_clock_data *clk_data; + struct clk **clk_table; + struct resource *res; + void __iomem *base; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return ERR_CAST(base); + + clk_data = devm_kzalloc(dev, sizeof(*clk_data), GFP_KERNEL); + if (!clk_data) + return ERR_PTR(-ENOMEM); + + clk_data->base = base; + clk_table = devm_kcalloc(dev, nr_clks, sizeof(*clk_table), GFP_KERNEL); + if (!clk_table) + return ERR_PTR(-ENOMEM); + + clk_data->clk_data.clks = clk_table; + clk_data->clk_data.clk_num = nr_clks; + ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data); + if (ret) + return ERR_PTR(ret); + + return clk_data; +} + +static int agilex_clkmgr_probe(struct platform_device *pdev) +{ + struct stratix10_clock_data *clk_data; + + clk_data = __socfpga_agilex_clk_init(pdev, AGILEX_NUM_CLKS); + if (IS_ERR(clk_data)) + return PTR_ERR(clk_data); + + agilex_clk_register_pll(agilex_pll_clks, ARRAY_SIZE(agilex_pll_clks), clk_data); + + agilex_clk_register_c_perip(agilex_main_perip_c_clks, + ARRAY_SIZE(agilex_main_perip_c_clks), clk_data); + + agilex_clk_register_cnt_perip(agilex_main_perip_cnt_clks, + ARRAY_SIZE(agilex_main_perip_cnt_clks), + clk_data); + + agilex_clk_register_gate(agilex_gate_clks, ARRAY_SIZE(agilex_gate_clks), + clk_data); + return 0; +} + +static const struct of_device_id agilex_clkmgr_match_table[] = { + { .compatible = "intel,agilex-clkmgr", + .data = agilex_clkmgr_probe }, + { } +}; + +static struct platform_driver agilex_clkmgr_driver = { + .probe = agilex_clkmgr_probe, + .driver = { + .name = "agilex-clkmgr", + .suppress_bind_attrs = true, + .of_match_table = agilex_clkmgr_match_table, + }, +}; + +static int __init agilex_clk_init(void) +{ + return platform_driver_register(&agilex_clkmgr_driver); +} +core_initcall(agilex_clk_init); diff --git a/drivers/clk/socfpga/clk-gate-s10.c b/drivers/clk/socfpga/clk-gate-s10.c index 8be4722f6064..083b2ec21fdd 100644 --- a/drivers/clk/socfpga/clk-gate-s10.c +++ b/drivers/clk/socfpga/clk-gate-s10.c @@ -70,7 +70,6 @@ struct clk *s10_register_gate(const struct stratix10_gate_clock *clks, void __io struct clk *clk; struct socfpga_gate_clk *socfpga_clk; struct clk_init_data init; - const char * const *parent_names = clks->parent_names; const char *parent_name = clks->parent_name; socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL); @@ -108,7 +107,9 @@ struct clk *s10_register_gate(const struct stratix10_gate_clock *clks, void __io init.flags = clks->flags; init.num_parents = clks->num_parents; - init.parent_names = parent_names ? parent_names : &parent_name; + init.parent_names = parent_name ? &parent_name : NULL; + if (init.parent_names == NULL) + init.parent_data = clks->parent_data; socfpga_clk->hw.hw.init = &init; clk = clk_register(NULL, &socfpga_clk->hw.hw); diff --git a/drivers/clk/socfpga/clk-periph-s10.c b/drivers/clk/socfpga/clk-periph-s10.c index dd6d4056e9de..397b77b89b16 100644 --- a/drivers/clk/socfpga/clk-periph-s10.c +++ b/drivers/clk/socfpga/clk-periph-s10.c @@ -81,7 +81,6 @@ struct clk *s10_register_periph(const struct stratix10_perip_c_clock *clks, struct clk_init_data init; const char *name = clks->name; const char *parent_name = clks->parent_name; - const char * const *parent_names = clks->parent_names; periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); if (WARN_ON(!periph_clk)) @@ -94,7 +93,9 @@ struct clk *s10_register_periph(const struct stratix10_perip_c_clock *clks, init.flags = clks->flags; init.num_parents = clks->num_parents; - init.parent_names = parent_names ? parent_names : &parent_name; + init.parent_names = parent_name ? &parent_name : NULL; + if (init.parent_names == NULL) + init.parent_data = clks->parent_data; periph_clk->hw.hw.init = &init; @@ -114,7 +115,6 @@ struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks struct clk_init_data init; const char *name = clks->name; const char *parent_name = clks->parent_name; - const char * const *parent_names = clks->parent_names; periph_clk = kzalloc(sizeof(*periph_clk), GFP_KERNEL); if (WARN_ON(!periph_clk)) @@ -137,7 +137,9 @@ struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *clks init.flags = clks->flags; init.num_parents = clks->num_parents; - init.parent_names = parent_names ? parent_names : &parent_name; + init.parent_names = parent_name ? &parent_name : NULL; + if (init.parent_names == NULL) + init.parent_data = clks->parent_data; periph_clk->hw.hw.init = &init; diff --git a/drivers/clk/socfpga/clk-pll-a10.c b/drivers/clk/socfpga/clk-pll-a10.c index 3816fc04b274..db54f7d806a0 100644 --- a/drivers/clk/socfpga/clk-pll-a10.c +++ b/drivers/clk/socfpga/clk-pll-a10.c @@ -58,7 +58,7 @@ static u8 clk_pll_get_parent(struct clk_hw *hwclk) CLK_MGR_PLL_CLK_SRC_MASK; } -static struct clk_ops clk_pll_ops = { +static const struct clk_ops clk_pll_ops = { .recalc_rate = clk_pll_recalc_rate, .get_parent = clk_pll_get_parent, }; @@ -102,8 +102,6 @@ static struct clk * __init __socfpga_pll_init(struct device_node *node, pll_clk->hw.hw.init = &init; pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; - clk_pll_ops.enable = clk_gate_ops.enable; - clk_pll_ops.disable = clk_gate_ops.disable; clk = clk_register(NULL, &pll_clk->hw.hw); if (WARN_ON(IS_ERR(clk))) { diff --git a/drivers/clk/socfpga/clk-pll-s10.c b/drivers/clk/socfpga/clk-pll-s10.c index a301bb22f36c..4e268953b7da 100644 --- a/drivers/clk/socfpga/clk-pll-s10.c +++ b/drivers/clk/socfpga/clk-pll-s10.c @@ -18,8 +18,12 @@ #define SOCFPGA_PLL_RESET_MASK 0x2 #define SOCFPGA_PLL_REFDIV_MASK 0x00003F00 #define SOCFPGA_PLL_REFDIV_SHIFT 8 +#define SOCFPGA_PLL_AREFDIV_MASK 0x00000F00 +#define SOCFPGA_PLL_DREFDIV_MASK 0x00003000 +#define SOCFPGA_PLL_DREFDIV_SHIFT 12 #define SOCFPGA_PLL_MDIV_MASK 0xFF000000 #define SOCFPGA_PLL_MDIV_SHIFT 24 +#define SOCFPGA_AGILEX_PLL_MDIV_MASK 0x000003FF #define SWCTRLBTCLKSEL_MASK 0x200 #define SWCTRLBTCLKSEL_SHIFT 9 @@ -27,6 +31,27 @@ #define to_socfpga_clk(p) container_of(p, struct socfpga_pll, hw.hw) +static unsigned long agilex_clk_pll_recalc_rate(struct clk_hw *hwclk, + unsigned long parent_rate) +{ + struct socfpga_pll *socfpgaclk = to_socfpga_clk(hwclk); + unsigned long arefdiv, reg, mdiv; + unsigned long long vco_freq; + + /* read VCO1 reg for numerator and denominator */ + reg = readl(socfpgaclk->hw.reg); + arefdiv = (reg & SOCFPGA_PLL_AREFDIV_MASK) >> SOCFPGA_PLL_REFDIV_SHIFT; + + vco_freq = (unsigned long long)parent_rate / arefdiv; + + /* Read mdiv and fdiv from the fdbck register */ + reg = readl(socfpgaclk->hw.reg + 0x24); + mdiv = reg & SOCFPGA_AGILEX_PLL_MDIV_MASK; + + vco_freq = (unsigned long long)vco_freq * mdiv; + return (unsigned long)vco_freq; +} + static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk, unsigned long parent_rate) { @@ -98,13 +123,19 @@ static int clk_pll_prepare(struct clk_hw *hwclk) return 0; } -static struct clk_ops clk_pll_ops = { +static const struct clk_ops agilex_clk_pll_ops = { + .recalc_rate = agilex_clk_pll_recalc_rate, + .get_parent = clk_pll_get_parent, + .prepare = clk_pll_prepare, +}; + +static const struct clk_ops clk_pll_ops = { .recalc_rate = clk_pll_recalc_rate, .get_parent = clk_pll_get_parent, .prepare = clk_pll_prepare, }; -static struct clk_ops clk_boot_ops = { +static const struct clk_ops clk_boot_ops = { .recalc_rate = clk_boot_clk_recalc_rate, .get_parent = clk_boot_get_parent, .prepare = clk_pll_prepare, @@ -117,7 +148,6 @@ struct clk *s10_register_pll(const struct stratix10_pll_clock *clks, struct socfpga_pll *pll_clk; struct clk_init_data init; const char *name = clks->name; - const char * const *parent_names = clks->parent_names; pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); if (WARN_ON(!pll_clk)) @@ -134,12 +164,48 @@ struct clk *s10_register_pll(const struct stratix10_pll_clock *clks, init.flags = clks->flags; init.num_parents = clks->num_parents; - init.parent_names = parent_names; + init.parent_names = NULL; + init.parent_data = clks->parent_data; + pll_clk->hw.hw.init = &init; + + pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; + + clk = clk_register(NULL, &pll_clk->hw.hw); + if (WARN_ON(IS_ERR(clk))) { + kfree(pll_clk); + return NULL; + } + return clk; +} + +struct clk *agilex_register_pll(const struct stratix10_pll_clock *clks, + void __iomem *reg) +{ + struct clk *clk; + struct socfpga_pll *pll_clk; + struct clk_init_data init; + const char *name = clks->name; + + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); + if (WARN_ON(!pll_clk)) + return NULL; + + pll_clk->hw.reg = reg + clks->offset; + + if (streq(name, SOCFPGA_BOOT_CLK)) + init.ops = &clk_boot_ops; + else + init.ops = &agilex_clk_pll_ops; + + init.name = name; + init.flags = clks->flags; + + init.num_parents = clks->num_parents; + init.parent_names = NULL; + init.parent_data = clks->parent_data; pll_clk->hw.hw.init = &init; pll_clk->hw.bit_idx = SOCFPGA_PLL_POWER; - clk_pll_ops.enable = clk_gate_ops.enable; - clk_pll_ops.disable = clk_gate_ops.disable; clk = clk_register(NULL, &pll_clk->hw.hw); if (WARN_ON(IS_ERR(clk))) { diff --git a/drivers/clk/socfpga/clk-pll.c b/drivers/clk/socfpga/clk-pll.c index dc65cc0fd3bd..e5fb786843f3 100644 --- a/drivers/clk/socfpga/clk-pll.c +++ b/drivers/clk/socfpga/clk-pll.c @@ -65,7 +65,7 @@ static u8 clk_pll_get_parent(struct clk_hw *hwclk) CLK_MGR_PLL_CLK_SRC_MASK; } -static struct clk_ops clk_pll_ops = { +static const struct clk_ops clk_pll_ops = { .recalc_rate = clk_pll_recalc_rate, .get_parent = clk_pll_get_parent, }; @@ -105,8 +105,6 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node, pll_clk->hw.hw.init = &init; pll_clk->hw.bit_idx = SOCFPGA_PLL_EXT_ENA; - clk_pll_ops.enable = clk_gate_ops.enable; - clk_pll_ops.disable = clk_gate_ops.disable; clk = clk_register(NULL, &pll_clk->hw.hw); if (WARN_ON(IS_ERR(clk))) { diff --git a/drivers/clk/socfpga/clk-s10.c b/drivers/clk/socfpga/clk-s10.c index dea7c6c7d269..c1dfc9b34e4e 100644 --- a/drivers/clk/socfpga/clk-s10.c +++ b/drivers/clk/socfpga/clk-s10.c @@ -12,35 +12,137 @@ #include "stratix10-clk.h" -static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk", - "f2s-free-clk",}; -static const char * const cntr_mux[] = { "main_pll", "periph_pll", - "osc1", "cb-intosc-hs-div2-clk", - "f2s-free-clk"}; -static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",}; - -static const char * const noc_free_mux[] = {"main_noc_base_clk", - "peri_noc_base_clk", - "osc1", "cb-intosc-hs-div2-clk", - "f2s-free-clk"}; - -static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"}; -static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"}; -static const char * const emac_ptp_free_mux[] = {"peri_emac_ptp_clk", "boot_clk"}; -static const char * const gpio_db_free_mux[] = {"peri_gpio_db_clk", "boot_clk"}; -static const char * const sdmmc_free_mux[] = {"main_sdmmc_clk", "boot_clk"}; -static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"}; -static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"}; -static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",}; - -static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"}; -static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"}; -static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"}; - -static const char * const mpu_free_mux[] = {"main_mpu_base_clk", - "peri_mpu_base_clk", - "osc1", "cb-intosc-hs-div2-clk", - "f2s-free-clk"}; +static const struct clk_parent_data pll_mux[] = { + { .fw_name = "osc1", + .name = "osc1" }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk" }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk" }, +}; + +static const struct clk_parent_data cntr_mux[] = { + { .fw_name = "main_pll", + .name = "main_pll", }, + { .fw_name = "periph_pll", + .name = "periph_pll", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data boot_mux[] = { + { .fw_name = "osc1", + .name = "osc1" }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk" }, +}; + +static const struct clk_parent_data noc_free_mux[] = { + { .fw_name = "main_noc_base_clk", + .name = "main_noc_base_clk", }, + { .fw_name = "peri_noc_base_clk", + .name = "peri_noc_base_clk", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; + +static const struct clk_parent_data emaca_free_mux[] = { + { .fw_name = "peri_emaca_clk", + .name = "peri_emaca_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emacb_free_mux[] = { + { .fw_name = "peri_emacb_clk", + .name = "peri_emacb_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_ptp_free_mux[] = { + { .fw_name = "peri_emac_ptp_clk", + .name = "peri_emac_ptp_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data gpio_db_free_mux[] = { + { .fw_name = "peri_gpio_db_clk", + .name = "peri_gpio_db_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data sdmmc_free_mux[] = { + { .fw_name = "main_sdmmc_clk", + .name = "main_sdmmc_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_usr1_free_mux[] = { + { .fw_name = "peri_s2f_usr1_clk", + .name = "peri_s2f_usr1_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data psi_ref_free_mux[] = { + { .fw_name = "peri_psi_ref_clk", + .name = "peri_psi_ref_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data mpu_mux[] = { + { .fw_name = "mpu_free_clk", + .name = "mpu_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data s2f_usr0_mux[] = { + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data emac_mux[] = { + { .fw_name = "emaca_free_clk", + .name = "emaca_free_clk", }, + { .fw_name = "emacb_free_clk", + .name = "emacb_free_clk", }, +}; + +static const struct clk_parent_data noc_mux[] = { + { .fw_name = "noc_free_clk", + .name = "noc_free_clk", }, + { .fw_name = "boot_clk", + .name = "boot_clk", }, +}; + +static const struct clk_parent_data mpu_free_mux[] = { + { .fw_name = "main_mpu_base_clk", + .name = "main_mpu_base_clk", }, + { .fw_name = "peri_mpu_base_clk", + .name = "peri_mpu_base_clk", }, + { .fw_name = "osc1", + .name = "osc1", }, + { .fw_name = "cb-intosc-hs-div2-clk", + .name = "cb-intosc-hs-div2-clk", }, + { .fw_name = "f2s-free-clk", + .name = "f2s-free-clk", }, +}; /* clocks in AO (always on) controller */ static const struct stratix10_pll_clock s10_pll_clks[] = { diff --git a/drivers/clk/socfpga/stratix10-clk.h b/drivers/clk/socfpga/stratix10-clk.h index fcabef42249c..f9d5d724c694 100644 --- a/drivers/clk/socfpga/stratix10-clk.h +++ b/drivers/clk/socfpga/stratix10-clk.h @@ -14,7 +14,7 @@ struct stratix10_clock_data { struct stratix10_pll_clock { unsigned int id; const char *name; - const char *const *parent_names; + const struct clk_parent_data *parent_data; u8 num_parents; unsigned long flags; unsigned long offset; @@ -24,7 +24,7 @@ struct stratix10_perip_c_clock { unsigned int id; const char *name; const char *parent_name; - const char *const *parent_names; + const struct clk_parent_data *parent_data; u8 num_parents; unsigned long flags; unsigned long offset; @@ -34,7 +34,7 @@ struct stratix10_perip_cnt_clock { unsigned int id; const char *name; const char *parent_name; - const char *const *parent_names; + const struct clk_parent_data *parent_data; u8 num_parents; unsigned long flags; unsigned long offset; @@ -47,7 +47,7 @@ struct stratix10_gate_clock { unsigned int id; const char *name; const char *parent_name; - const char *const *parent_names; + const struct clk_parent_data *parent_data; u8 num_parents; unsigned long flags; unsigned long gate_reg; @@ -62,6 +62,8 @@ struct stratix10_gate_clock { struct clk *s10_register_pll(const struct stratix10_pll_clock *, void __iomem *); +struct clk *agilex_register_pll(const struct stratix10_pll_clock *, + void __iomem *); struct clk *s10_register_periph(const struct stratix10_perip_c_clock *, void __iomem *); struct clk *s10_register_cnt_periph(const struct stratix10_perip_cnt_clock *, |