diff options
111 files changed, 3013 insertions, 8543 deletions
diff --git a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml index 0d06387184d6..983033fe5b17 100644 --- a/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml +++ b/Documentation/devicetree/bindings/clock/adi,axi-clkgen.yaml @@ -20,6 +20,7 @@ properties: compatible: enum: - adi,axi-clkgen-2.00.a + - adi,zynqmp-axi-clkgen-2.00.a clocks: description: diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml index 3b45344ed758..a27025cd3909 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml @@ -41,6 +41,8 @@ properties: - allwinner,sun50i-h5-ccu - allwinner,sun50i-h6-ccu - allwinner,sun50i-h6-r-ccu + - allwinner,sun50i-h616-ccu + - allwinner,sun50i-h616-r-ccu - allwinner,suniv-f1c100s-ccu - nextthing,gr8-ccu @@ -82,6 +84,7 @@ if: - allwinner,sun50i-a64-r-ccu - allwinner,sun50i-a100-r-ccu - allwinner,sun50i-h6-r-ccu + - allwinner,sun50i-h616-r-ccu then: properties: @@ -100,6 +103,7 @@ else: enum: - allwinner,sun50i-a100-ccu - allwinner,sun50i-h6-ccu + - allwinner,sun50i-h616-ccu then: properties: diff --git a/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt b/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt deleted file mode 100644 index 54d6d1358339..000000000000 --- a/Documentation/devicetree/bindings/clock/csr,atlas7-car.txt +++ /dev/null @@ -1,55 +0,0 @@ -* Clock and reset bindings for CSR atlas7 - -Required properties: -- compatible: Should be "sirf,atlas7-car" -- reg: Address and length of the register set -- #clock-cells: Should be <1> -- #reset-cells: Should be <1> - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. -The ID list atlas7_clks defined in drivers/clk/sirf/clk-atlas7.c - -The reset consumer should specify the desired reset by having the reset -ID in its "reset" phandle cell. -The ID list atlas7_reset_unit defined in drivers/clk/sirf/clk-atlas7.c - -Examples: Clock and reset controller node: - -car: clock-controller@18620000 { - compatible = "sirf,atlas7-car"; - reg = <0x18620000 0x1000>; - #clock-cells = <1>; - #reset-cells = <1>; -}; - -Examples: Consumers using clock or reset: - -timer@10dc0000 { - compatible = "sirf,macro-tick"; - reg = <0x10dc0000 0x1000>; - clocks = <&car 54>; - interrupts = <0 0 0>, - <0 1 0>, - <0 2 0>, - <0 49 0>, - <0 50 0>, - <0 51 0>; -}; - -uart1: uart@18020000 { - cell-index = <1>; - compatible = "sirf,macro-uart"; - reg = <0x18020000 0x1000>; - clocks = <&clks 95>; - interrupts = <0 18 0>; - fifosize = <32>; -}; - -vpp@13110000 { - compatible = "sirf,prima2-vpp"; - reg = <0x13110000 0x10000>; - interrupts = <0 31 0>; - clocks = <&car 85>; - resets = <&car 29>; -}; diff --git a/Documentation/devicetree/bindings/clock/imx27-clock.yaml b/Documentation/devicetree/bindings/clock/imx27-clock.yaml index a75365453dbc..160268f24487 100644 --- a/Documentation/devicetree/bindings/clock/imx27-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx27-clock.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Clock bindings for Freescale i.MX27 maintainers: - - Fabio Estevam <fabio.estevam@nxp.com> + - Fabio Estevam <festevam@gmail.com> description: | The clock consumer should specify the desired clock by having the clock diff --git a/Documentation/devicetree/bindings/clock/imx31-clock.yaml b/Documentation/devicetree/bindings/clock/imx31-clock.yaml index a25a374b3b2a..d2336261c922 100644 --- a/Documentation/devicetree/bindings/clock/imx31-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx31-clock.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Clock bindings for Freescale i.MX31 maintainers: - - Fabio Estevam <fabio.estevam@nxp.com> + - Fabio Estevam <festevam@gmail.com> description: | The clock consumer should specify the desired clock by having the clock diff --git a/Documentation/devicetree/bindings/clock/imx5-clock.yaml b/Documentation/devicetree/bindings/clock/imx5-clock.yaml index 90775c2669b8..b1740d7abe68 100644 --- a/Documentation/devicetree/bindings/clock/imx5-clock.yaml +++ b/Documentation/devicetree/bindings/clock/imx5-clock.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Clock bindings for Freescale i.MX5 maintainers: - - Fabio Estevam <fabio.estevam@nxp.com> + - Fabio Estevam <festevam@gmail.com> description: | The clock consumer should specify the desired clock by having the clock diff --git a/Documentation/devicetree/bindings/clock/prima2-clock.txt b/Documentation/devicetree/bindings/clock/prima2-clock.txt deleted file mode 100644 index 5016979c0f78..000000000000 --- a/Documentation/devicetree/bindings/clock/prima2-clock.txt +++ /dev/null @@ -1,73 +0,0 @@ -* Clock bindings for CSR SiRFprimaII - -Required properties: -- compatible: Should be "sirf,prima2-clkc" -- reg: Address and length of the register set -- interrupts: Should contain clock controller interrupt -- #clock-cells: Should be <1> - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. The following is a full list of prima2 -clocks and IDs. - - Clock ID - --------------------------- - rtc 0 - osc 1 - pll1 2 - pll2 3 - pll3 4 - mem 5 - sys 6 - security 7 - dsp 8 - gps 9 - mf 10 - io 11 - cpu 12 - uart0 13 - uart1 14 - uart2 15 - tsc 16 - i2c0 17 - i2c1 18 - spi0 19 - spi1 20 - pwmc 21 - efuse 22 - pulse 23 - dmac0 24 - dmac1 25 - nand 26 - audio 27 - usp0 28 - usp1 29 - usp2 30 - vip 31 - gfx 32 - mm 33 - lcd 34 - vpp 35 - mmc01 36 - mmc23 37 - mmc45 38 - usbpll 39 - usb0 40 - usb1 41 - -Examples: - -clks: clock-controller@88000000 { - compatible = "sirf,prima2-clkc"; - reg = <0x88000000 0x1000>; - interrupts = <3>; - #clock-cells = <1>; -}; - -i2c0: i2c@b00e0000 { - cell-index = <0>; - compatible = "sirf,prima2-i2c"; - reg = <0xb00e0000 0x10000>; - interrupts = <24>; - clocks = <&clks 17>; -}; diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml index 5be1229b3d6e..6eaabb4d82ec 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml @@ -35,6 +35,9 @@ properties: compatible: items: - enum: + - renesas,r8a774a1-rcar-usb2-clock-sel # RZ/G2M + - renesas,r8a774b1-rcar-usb2-clock-sel # RZ/G2N + - renesas,r8a774e1-rcar-usb2-clock-sel # RZ/G2H - renesas,r8a7795-rcar-usb2-clock-sel # R-Car H3 - renesas,r8a7796-rcar-usb2-clock-sel # R-Car M3-W - renesas,r8a77961-rcar-usb2-clock-sel # R-Car M3-W+ diff --git a/Documentation/devicetree/bindings/clock/silabs,si570.txt b/Documentation/devicetree/bindings/clock/silabs,si570.txt index 901935e929d2..5dda17df1ac5 100644 --- a/Documentation/devicetree/bindings/clock/silabs,si570.txt +++ b/Documentation/devicetree/bindings/clock/silabs,si570.txt @@ -28,6 +28,8 @@ Optional properties: - clock-frequency: Output frequency to generate. This defines the output frequency set during boot. It can be reprogrammed during runtime through the common clock framework. + - silabs,skip-recall: Do not perform NVM->RAM recall operation. It will rely + on hardware loading of RAM from NVM at power on. Example: si570: clock-generator@5d { diff --git a/Documentation/devicetree/bindings/clock/ste-u300-syscon-clock.txt b/Documentation/devicetree/bindings/clock/ste-u300-syscon-clock.txt deleted file mode 100644 index 7cafcb98ead7..000000000000 --- a/Documentation/devicetree/bindings/clock/ste-u300-syscon-clock.txt +++ /dev/null @@ -1,80 +0,0 @@ -Clock bindings for ST-Ericsson U300 System Controller Clocks - -Bindings for the gated system controller clocks: - -Required properties: -- compatible: must be "stericsson,u300-syscon-clk" -- #clock-cells: must be <0> -- clock-type: specifies the type of clock: - 0 = slow clock - 1 = fast clock - 2 = rest/remaining clock -- clock-id: specifies the clock in the type range - -Optional properties: -- clocks: parent clock(s) - -The available clocks per type are as follows: - -Type: ID: Clock: -------------------- -0 0 Slow peripheral bridge clock -0 1 UART0 clock -0 4 GPIO clock -0 6 RTC clock -0 7 Application timer clock -0 8 Access timer clock - -1 0 Fast peripheral bridge clock -1 1 I2C bus 0 clock -1 2 I2C bus 1 clock -1 5 MMC interface peripheral (silicon) clock -1 6 SPI clock - -2 3 CPU clock -2 4 DMA controller clock -2 5 External Memory Interface (EMIF) clock -2 6 NAND flask interface clock -2 8 XGAM graphics engine clock -2 9 Shared External Memory Interface (SEMI) clock -2 10 AHB Subsystem Bridge clock -2 12 Interrupt controller clock - -Example: - -gpio_clk: gpio_clk@13M { - #clock-cells = <0>; - compatible = "stericsson,u300-syscon-clk"; - clock-type = <0>; /* Slow */ - clock-id = <4>; - clocks = <&slow_clk>; -}; - -gpio: gpio@c0016000 { - compatible = "stericsson,gpio-coh901"; - (...) - clocks = <&gpio_clk>; -}; - - -Bindings for the MMC/SD card clock: - -Required properties: -- compatible: must be "stericsson,u300-syscon-mclk" -- #clock-cells: must be <0> - -Optional properties: -- clocks: parent clock(s) - -mmc_mclk: mmc_mclk { - #clock-cells = <0>; - compatible = "stericsson,u300-syscon-mclk"; - clocks = <&mmc_pclk>; -}; - -mmcsd: mmcsd@c0001000 { - compatible = "arm,pl18x", "arm,primecell"; - clocks = <&mmc_pclk>, <&mmc_mclk>; - clock-names = "apb_pclk", "mclk"; - (...) -}; diff --git a/Documentation/devicetree/bindings/clock/tango4-clock.txt b/Documentation/devicetree/bindings/clock/tango4-clock.txt deleted file mode 100644 index 19c580a7bda2..000000000000 --- a/Documentation/devicetree/bindings/clock/tango4-clock.txt +++ /dev/null @@ -1,23 +0,0 @@ -* Sigma Designs Tango4 Clock Generator - -The Tango4 clock generator outputs cpu_clk and sys_clk (the latter is used -for RAM and various peripheral devices). The clock binding described here -is applicable to all Tango4 SoCs. - -Required Properties: - -- compatible: should be "sigma,tango4-clkgen". -- reg: physical base address of the device and length of memory mapped region. -- clocks: phandle of the input clock (crystal oscillator). -- clock-output-names: should be "cpuclk" and "sysclk". -- #clock-cells: should be set to 1. - -Example: - - clkgen: clkgen@10000 { - compatible = "sigma,tango4-clkgen"; - reg = <0x10000 0x40>; - clocks = <&xtal>; - clock-output-names = "cpuclk", "sysclk"; - #clock-cells = <1>; - }; diff --git a/Documentation/devicetree/bindings/clock/zx296702-clk.txt b/Documentation/devicetree/bindings/clock/zx296702-clk.txt deleted file mode 100644 index 5c91c9e4f1be..000000000000 --- a/Documentation/devicetree/bindings/clock/zx296702-clk.txt +++ /dev/null @@ -1,34 +0,0 @@ -Device Tree Clock bindings for ZTE zx296702 - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be one of the following: - "zte,zx296702-topcrm-clk": - zx296702 top clock selection, divider and gating - - "zte,zx296702-lsp0crpm-clk" and - "zte,zx296702-lsp1crpm-clk": - zx296702 device level clock selection and gating - -- reg: Address and length of the register set - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296702-clock.h -for the full list of zx296702 clock IDs. - - -topclk: topcrm@09800000 { - compatible = "zte,zx296702-topcrm-clk"; - reg = <0x09800000 0x1000>; - #clock-cells = <1>; -}; - -uart0: serial@09405000 { - compatible = "zte,zx296702-uart"; - reg = <0x09405000 0x1000>; - interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&lsp1clk ZX296702_UART0_PCLK>; -}; diff --git a/Documentation/devicetree/bindings/clock/zx296718-clk.txt b/Documentation/devicetree/bindings/clock/zx296718-clk.txt deleted file mode 100644 index 3a46bf0b2540..000000000000 --- a/Documentation/devicetree/bindings/clock/zx296718-clk.txt +++ /dev/null @@ -1,37 +0,0 @@ -Device Tree Clock bindings for ZTE zx296718 - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be one of the following: - "zte,zx296718-topcrm": - zx296718 top clock selection, divider and gating - - "zte,zx296718-lsp0crm" and - "zte,zx296718-lsp1crm": - zx296718 device level clock selection and gating - - "zte,zx296718-audiocrm": - zx296718 audio clock selection, divider and gating - -- reg: Address and length of the register set - -The clock consumer should specify the desired clock by having the clock -ID in its "clocks" phandle cell. See include/dt-bindings/clock/zx296718-clock.h -for the full list of zx296718 clock IDs. - - -topclk: topcrm@1461000 { - compatible = "zte,zx296718-topcrm-clk"; - reg = <0x01461000 0x1000>; - #clock-cells = <1>; -}; - -usbphy0:usb-phy0 { - compatible = "zte,zx296718-usb-phy"; - #phy-cells = <0>; - clocks = <&topclk USB20_PHY_CLK>; - clock-names = "phyclk"; -}; diff --git a/MAINTAINERS b/MAINTAINERS index 546aa66428c9..df6b53c07547 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -12751,6 +12751,13 @@ F: drivers/iio/gyro/fxas21002c_core.c F: drivers/iio/gyro/fxas21002c_i2c.c F: drivers/iio/gyro/fxas21002c_spi.c +NXP i.MX CLOCK DRIVERS +M: Abel Vesa <abel.vesa@nxp.com> +L: linux-clk@vger.kernel.org +L: linux-imx@nxp.com +S: Maintained +F: drivers/clk/imx/ + NXP i.MX 8MQ DCSS DRIVER M: Laurentiu Palcu <laurentiu.palcu@oss.nxp.com> R: Lucas Stach <l.stach@pengutronix.de> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h index 2d76e2c6c99e..2b004cc4f95e 100644 --- a/arch/arm/mach-imx/common.h +++ b/arch/arm/mach-imx/common.h @@ -85,7 +85,6 @@ void imx_anatop_pre_suspend(void); void imx_anatop_post_resume(void); int imx6_set_lpm(enum mxc_cpu_pwr_mode mode); void imx6_set_int_mem_clk_lpm(bool enable); -void imx6sl_set_wait_clk(bool enter); int imx_mmdc_get_ddr_type(void); int imx7ulp_set_lpm(enum ulp_cpu_pwr_mode mode); diff --git a/arch/arm/mach-imx/cpuidle-imx6sl.c b/arch/arm/mach-imx/cpuidle-imx6sl.c index 4521e5352bf6..b86ffbeb28e4 100644 --- a/arch/arm/mach-imx/cpuidle-imx6sl.c +++ b/arch/arm/mach-imx/cpuidle-imx6sl.c @@ -3,6 +3,7 @@ * Copyright (C) 2014 Freescale Semiconductor, Inc. */ +#include <linux/clk/imx.h> #include <linux/cpuidle.h> #include <linux/module.h> #include <asm/cpuidle.h> diff --git a/arch/arm/mach-imx/pm-imx6.c b/arch/arm/mach-imx/pm-imx6.c index 40c74b4c4d73..9244437cb1b9 100644 --- a/arch/arm/mach-imx/pm-imx6.c +++ b/arch/arm/mach-imx/pm-imx6.c @@ -4,6 +4,7 @@ * Copyright 2011 Linaro Ltd. */ +#include <linux/clk/imx.h> #include <linux/delay.h> #include <linux/init.h> #include <linux/io.h> diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 85856cff506c..7c5dc348c16f 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -247,7 +247,8 @@ config CLK_TWL6040 config COMMON_CLK_AXI_CLKGEN tristate "AXI clkgen driver" - depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST + depends on HAS_IOMEM || COMPILE_TEST + depends on OF help Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx FPGAs. It is commonly used in Analog Devices' reference designs. @@ -392,6 +393,7 @@ source "drivers/clk/tegra/Kconfig" source "drivers/clk/ti/Kconfig" source "drivers/clk/uniphier/Kconfig" source "drivers/clk/x86/Kconfig" +source "drivers/clk/xilinx/Kconfig" source "drivers/clk/zynqmp/Kconfig" endif diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index dbdc590e7de3..5325847469e9 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -27,7 +27,6 @@ obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o -obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o obj-$(CONFIG_ARCH_SPARX5) += clk-sparx5.o obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o obj-$(CONFIG_COMMON_CLK_FSL_FLEXSPI) += clk-fsl-flexspi.o @@ -63,9 +62,7 @@ obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o obj-$(CONFIG_COMMON_CLK_STM32F) += clk-stm32f4.o obj-$(CONFIG_COMMON_CLK_STM32H7) += clk-stm32h7.o obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o -obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o -obj-$(CONFIG_ARCH_U300) += clk-u300.o obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o obj-$(CONFIG_COMMON_CLK_VC5) += clk-versaclock5.o obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o @@ -105,7 +102,6 @@ obj-y += renesas/ obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/ obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/ obj-$(CONFIG_CLK_SIFIVE) += sifive/ -obj-$(CONFIG_ARCH_SIRF) += sirf/ obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/ obj-$(CONFIG_ARCH_AGILEX) += socfpga/ obj-$(CONFIG_ARCH_STRATIX10) += socfpga/ @@ -122,6 +118,6 @@ obj-y += versatile/ ifeq ($(CONFIG_COMMON_CLK), y) obj-$(CONFIG_X86) += x86/ endif -obj-$(CONFIG_ARCH_ZX) += zte/ +obj-y += xilinx/ obj-$(CONFIG_ARCH_ZYNQ) += zynq/ obj-$(CONFIG_COMMON_CLK_ZYNQMP) += zynqmp/ diff --git a/drivers/clk/at91/at91rm9200.c b/drivers/clk/at91/at91rm9200.c index 0fad1009f315..428a6f4b9ebc 100644 --- a/drivers/clk/at91/at91rm9200.c +++ b/drivers/clk/at91/at91rm9200.c @@ -215,5 +215,4 @@ err_free: * deferring properly. Once this is fixed, this can be switched to a platform * driver. */ -CLK_OF_DECLARE_DRIVER(at91rm9200_pmc, "atmel,at91rm9200-pmc", - at91rm9200_pmc_setup); +CLK_OF_DECLARE(at91rm9200_pmc, "atmel,at91rm9200-pmc", at91rm9200_pmc_setup); diff --git a/drivers/clk/at91/at91sam9260.c b/drivers/clk/at91/at91sam9260.c index ceb5495f723a..b29843bea278 100644 --- a/drivers/clk/at91/at91sam9260.c +++ b/drivers/clk/at91/at91sam9260.c @@ -491,26 +491,26 @@ static void __init at91sam9260_pmc_setup(struct device_node *np) { at91sam926x_pmc_setup(np, &at91sam9260_data); } -CLK_OF_DECLARE_DRIVER(at91sam9260_pmc, "atmel,at91sam9260-pmc", - at91sam9260_pmc_setup); + +CLK_OF_DECLARE(at91sam9260_pmc, "atmel,at91sam9260-pmc", at91sam9260_pmc_setup); static void __init at91sam9261_pmc_setup(struct device_node *np) { at91sam926x_pmc_setup(np, &at91sam9261_data); } -CLK_OF_DECLARE_DRIVER(at91sam9261_pmc, "atmel,at91sam9261-pmc", - at91sam9261_pmc_setup); + +CLK_OF_DECLARE(at91sam9261_pmc, "atmel,at91sam9261-pmc", at91sam9261_pmc_setup); static void __init at91sam9263_pmc_setup(struct device_node *np) { at91sam926x_pmc_setup(np, &at91sam9263_data); } -CLK_OF_DECLARE_DRIVER(at91sam9263_pmc, "atmel,at91sam9263-pmc", - at91sam9263_pmc_setup); + +CLK_OF_DECLARE(at91sam9263_pmc, "atmel,at91sam9263-pmc", at91sam9263_pmc_setup); static void __init at91sam9g20_pmc_setup(struct device_node *np) { at91sam926x_pmc_setup(np, &at91sam9g20_data); } -CLK_OF_DECLARE_DRIVER(at91sam9g20_pmc, "atmel,at91sam9g20-pmc", - at91sam9g20_pmc_setup); + +CLK_OF_DECLARE(at91sam9g20_pmc, "atmel,at91sam9g20-pmc", at91sam9g20_pmc_setup); diff --git a/drivers/clk/at91/at91sam9g45.c b/drivers/clk/at91/at91sam9g45.c index 0214333dedd3..15da0dfe3ef2 100644 --- a/drivers/clk/at91/at91sam9g45.c +++ b/drivers/clk/at91/at91sam9g45.c @@ -228,5 +228,4 @@ err_free: * The TCB is used as the clocksource so its clock is needed early. This means * this can't be a platform driver. */ -CLK_OF_DECLARE_DRIVER(at91sam9g45_pmc, "atmel,at91sam9g45-pmc", - at91sam9g45_pmc_setup); +CLK_OF_DECLARE(at91sam9g45_pmc, "atmel,at91sam9g45-pmc", at91sam9g45_pmc_setup); diff --git a/drivers/clk/at91/at91sam9n12.c b/drivers/clk/at91/at91sam9n12.c index f9db5316a7f1..7fe435f4b46b 100644 --- a/drivers/clk/at91/at91sam9n12.c +++ b/drivers/clk/at91/at91sam9n12.c @@ -255,5 +255,4 @@ err_free: * The TCB is used as the clocksource so its clock is needed early. This means * this can't be a platform driver. */ -CLK_OF_DECLARE_DRIVER(at91sam9n12_pmc, "atmel,at91sam9n12-pmc", - at91sam9n12_pmc_setup); +CLK_OF_DECLARE(at91sam9n12_pmc, "atmel,at91sam9n12-pmc", at91sam9n12_pmc_setup); diff --git a/drivers/clk/at91/at91sam9rl.c b/drivers/clk/at91/at91sam9rl.c index 66736e03cfef..ecbabf5162bd 100644 --- a/drivers/clk/at91/at91sam9rl.c +++ b/drivers/clk/at91/at91sam9rl.c @@ -186,4 +186,5 @@ static void __init at91sam9rl_pmc_setup(struct device_node *np) err_free: kfree(at91sam9rl_pmc); } -CLK_OF_DECLARE_DRIVER(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup); + +CLK_OF_DECLARE(at91sam9rl_pmc, "atmel,at91sam9rl-pmc", at91sam9rl_pmc_setup); diff --git a/drivers/clk/at91/at91sam9x5.c b/drivers/clk/at91/at91sam9x5.c index 79b9d3667228..5cce48c64ea2 100644 --- a/drivers/clk/at91/at91sam9x5.c +++ b/drivers/clk/at91/at91sam9x5.c @@ -302,33 +302,33 @@ static void __init at91sam9g15_pmc_setup(struct device_node *np) { at91sam9x5_pmc_setup(np, at91sam9g15_periphck, true); } -CLK_OF_DECLARE_DRIVER(at91sam9g15_pmc, "atmel,at91sam9g15-pmc", - at91sam9g15_pmc_setup); + +CLK_OF_DECLARE(at91sam9g15_pmc, "atmel,at91sam9g15-pmc", at91sam9g15_pmc_setup); static void __init at91sam9g25_pmc_setup(struct device_node *np) { at91sam9x5_pmc_setup(np, at91sam9g25_periphck, false); } -CLK_OF_DECLARE_DRIVER(at91sam9g25_pmc, "atmel,at91sam9g25-pmc", - at91sam9g25_pmc_setup); + +CLK_OF_DECLARE(at91sam9g25_pmc, "atmel,at91sam9g25-pmc", at91sam9g25_pmc_setup); static void __init at91sam9g35_pmc_setup(struct device_node *np) { at91sam9x5_pmc_setup(np, at91sam9g35_periphck, true); } -CLK_OF_DECLARE_DRIVER(at91sam9g35_pmc, "atmel,at91sam9g35-pmc", - at91sam9g35_pmc_setup); + +CLK_OF_DECLARE(at91sam9g35_pmc, "atmel,at91sam9g35-pmc", at91sam9g35_pmc_setup); static void __init at91sam9x25_pmc_setup(struct device_node *np) { at91sam9x5_pmc_setup(np, at91sam9x25_periphck, false); } -CLK_OF_DECLARE_DRIVER(at91sam9x25_pmc, "atmel,at91sam9x25-pmc", - at91sam9x25_pmc_setup); + +CLK_OF_DECLARE(at91sam9x25_pmc, "atmel,at91sam9x25-pmc", at91sam9x25_pmc_setup); static void __init at91sam9x35_pmc_setup(struct device_node *np) { at91sam9x5_pmc_setup(np, at91sam9x35_periphck, true); } -CLK_OF_DECLARE_DRIVER(at91sam9x35_pmc, "atmel,at91sam9x35-pmc", - at91sam9x35_pmc_setup); + +CLK_OF_DECLARE(at91sam9x35_pmc, "atmel,at91sam9x35-pmc", at91sam9x35_pmc_setup); diff --git a/drivers/clk/at91/sama5d2.c b/drivers/clk/at91/sama5d2.c index 9a5cbc7cd55a..3d1f78176c3e 100644 --- a/drivers/clk/at91/sama5d2.c +++ b/drivers/clk/at91/sama5d2.c @@ -372,4 +372,5 @@ static void __init sama5d2_pmc_setup(struct device_node *np) err_free: kfree(sama5d2_pmc); } -CLK_OF_DECLARE_DRIVER(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup); + +CLK_OF_DECLARE(sama5d2_pmc, "atmel,sama5d2-pmc", sama5d2_pmc_setup); diff --git a/drivers/clk/at91/sama5d3.c b/drivers/clk/at91/sama5d3.c index 87009ee8effc..d376257807d2 100644 --- a/drivers/clk/at91/sama5d3.c +++ b/drivers/clk/at91/sama5d3.c @@ -255,4 +255,4 @@ err_free: * The TCB is used as the clocksource so its clock is needed early. This means * this can't be a platform driver. */ -CLK_OF_DECLARE_DRIVER(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup); +CLK_OF_DECLARE(sama5d3_pmc, "atmel,sama5d3-pmc", sama5d3_pmc_setup); diff --git a/drivers/clk/at91/sama5d4.c b/drivers/clk/at91/sama5d4.c index 57fff790188b..5cbaac68da44 100644 --- a/drivers/clk/at91/sama5d4.c +++ b/drivers/clk/at91/sama5d4.c @@ -286,4 +286,5 @@ static void __init sama5d4_pmc_setup(struct device_node *np) err_free: kfree(sama5d4_pmc); } -CLK_OF_DECLARE_DRIVER(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup); + +CLK_OF_DECLARE(sama5d4_pmc, "atmel,sama5d4-pmc", sama5d4_pmc_setup); diff --git a/drivers/clk/clk-ast2600.c b/drivers/clk/clk-ast2600.c index 177368cac6dd..a55b37fc2c8b 100644 --- a/drivers/clk/clk-ast2600.c +++ b/drivers/clk/clk-ast2600.c @@ -17,7 +17,8 @@ #define ASPEED_G6_NUM_CLKS 71 -#define ASPEED_G6_SILICON_REV 0x004 +#define ASPEED_G6_SILICON_REV 0x014 +#define CHIP_REVISION_ID GENMASK(23, 16) #define ASPEED_G6_RESET_CTRL 0x040 #define ASPEED_G6_RESET_CTRL2 0x050 @@ -190,18 +191,34 @@ static struct clk_hw *ast2600_calc_pll(const char *name, u32 val) static struct clk_hw *ast2600_calc_apll(const char *name, u32 val) { unsigned int mult, div; + u32 chip_id = readl(scu_g6_base + ASPEED_G6_SILICON_REV); - if (val & BIT(20)) { - /* Pass through mode */ - mult = div = 1; + if (((chip_id & CHIP_REVISION_ID) >> 16) >= 2) { + if (val & BIT(24)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * [(m + 1) / (n + 1)] / (p + 1) */ + u32 m = val & 0x1fff; + u32 n = (val >> 13) & 0x3f; + u32 p = (val >> 19) & 0xf; + + mult = (m + 1); + div = (n + 1) * (p + 1); + } } else { - /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ - u32 m = (val >> 5) & 0x3f; - u32 od = (val >> 4) & 0x1; - u32 n = val & 0xf; + if (val & BIT(20)) { + /* Pass through mode */ + mult = div = 1; + } else { + /* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */ + u32 m = (val >> 5) & 0x3f; + u32 od = (val >> 4) & 0x1; + u32 n = val & 0xf; - mult = (2 - od) * (m + 2); - div = n + 1; + mult = (2 - od) * (m + 2); + div = n + 1; + } } return clk_hw_register_fixed_factor(NULL, name, "clkin", 0, mult, div); diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c index ad86e031ba3e..ac6ff736ac8f 100644 --- a/drivers/clk/clk-axi-clkgen.c +++ b/drivers/clk/clk-axi-clkgen.c @@ -108,6 +108,13 @@ static uint32_t axi_clkgen_lookup_lock(unsigned int m) return 0x1f1f00fa; } +static const struct axi_clkgen_limits axi_clkgen_zynqmp_default_limits = { + .fpfd_min = 10000, + .fpfd_max = 450000, + .fvco_min = 800000, + .fvco_max = 1600000, +}; + static const struct axi_clkgen_limits axi_clkgen_zynq_default_limits = { .fpfd_min = 10000, .fpfd_max = 300000, @@ -503,7 +510,6 @@ static int axi_clkgen_probe(struct platform_device *pdev) struct clk_init_data init; const char *parent_names[2]; const char *clk_name; - struct resource *mem; unsigned int i; int ret; @@ -515,8 +521,7 @@ static int axi_clkgen_probe(struct platform_device *pdev) if (!axi_clkgen) return -ENOMEM; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); + axi_clkgen->base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(axi_clkgen->base)) return PTR_ERR(axi_clkgen->base); @@ -561,6 +566,10 @@ static int axi_clkgen_remove(struct platform_device *pdev) static const struct of_device_id axi_clkgen_ids[] = { { + .compatible = "adi,zynqmp-axi-clkgen-2.00.a", + .data = &axi_clkgen_zynqmp_default_limits, + }, + { .compatible = "adi,axi-clkgen-2.00.a", .data = &axi_clkgen_zynq_default_limits, }, diff --git a/drivers/clk/clk-bd718x7.c b/drivers/clk/clk-bd718x7.c index b52e8d6f660c..17d90e09f1c0 100644 --- a/drivers/clk/clk-bd718x7.c +++ b/drivers/clk/clk-bd718x7.c @@ -31,12 +31,12 @@ struct bd718xx_clk { u8 reg; u8 mask; struct platform_device *pdev; - struct rohm_regmap_dev *mfd; + struct regmap *regmap; }; static int bd71837_clk_set(struct bd718xx_clk *c, unsigned int status) { - return regmap_update_bits(c->mfd->regmap, c->reg, c->mask, status); + return regmap_update_bits(c->regmap, c->reg, c->mask, status); } static void bd71837_clk_disable(struct clk_hw *hw) @@ -62,7 +62,7 @@ static int bd71837_clk_is_enabled(struct clk_hw *hw) int rval; struct bd718xx_clk *c = container_of(hw, struct bd718xx_clk, hw); - rval = regmap_read(c->mfd->regmap, c->reg, &enabled); + rval = regmap_read(c->regmap, c->reg, &enabled); if (rval) return rval; @@ -82,7 +82,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) int rval = -ENOMEM; const char *parent_clk; struct device *parent = pdev->dev.parent; - struct rohm_regmap_dev *mfd = dev_get_drvdata(parent); struct clk_init_data init = { .name = "bd718xx-32k-out", .ops = &bd71837_clk_ops, @@ -93,6 +92,10 @@ static int bd71837_clk_probe(struct platform_device *pdev) if (!c) return -ENOMEM; + c->regmap = dev_get_regmap(pdev->dev.parent, NULL); + if (!c->regmap) + return -ENODEV; + init.num_parents = 1; parent_clk = of_clk_get_parent_name(parent->of_node, 0); @@ -119,7 +122,6 @@ static int bd71837_clk_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Unknown clk chip\n"); return -EINVAL; } - c->mfd = mfd; c->pdev = pdev; c->hw.init = &init; diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c index c499799693cc..344997203f0e 100644 --- a/drivers/clk/clk-divider.c +++ b/drivers/clk/clk-divider.c @@ -494,8 +494,13 @@ struct clk_hw *__clk_hw_register_divider(struct device *dev, else init.ops = &clk_divider_ops; init.flags = flags; - init.parent_names = (parent_name ? &parent_name: NULL); - init.num_parents = (parent_name ? 1 : 0); + init.parent_names = parent_name ? &parent_name : NULL; + init.parent_hws = parent_hw ? &parent_hw : NULL; + init.parent_data = parent_data; + if (parent_name || parent_hw || parent_data) + init.num_parents = 1; + else + init.num_parents = 0; /* struct clk_divider assignments */ div->reg = reg; diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c deleted file mode 100644 index 85beaacb4088..000000000000 --- a/drivers/clk/clk-efm32gg.c +++ /dev/null @@ -1,84 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013 Pengutronix - * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de> - */ -#include <linux/io.h> -#include <linux/clk-provider.h> -#include <linux/of.h> -#include <linux/of_address.h> -#include <linux/slab.h> - -#include <dt-bindings/clock/efm32-cmu.h> - -#define CMU_HFPERCLKEN0 0x44 -#define CMU_MAX_CLKS 37 - -static struct clk_hw_onecell_data *clk_data; - -static void __init efm32gg_cmu_init(struct device_node *np) -{ - int i; - void __iomem *base; - struct clk_hw **hws; - - clk_data = kzalloc(struct_size(clk_data, hws, CMU_MAX_CLKS), - GFP_KERNEL); - - if (!clk_data) - return; - - hws = clk_data->hws; - - for (i = 0; i < CMU_MAX_CLKS; ++i) - hws[i] = ERR_PTR(-ENOENT); - - base = of_iomap(np, 0); - if (!base) { - pr_warn("Failed to map address range for efm32gg,cmu node\n"); - return; - } - - hws[clk_HFXO] = clk_hw_register_fixed_rate(NULL, "HFXO", NULL, 0, - 48000000); - - hws[clk_HFPERCLKUSART0] = clk_hw_register_gate(NULL, "HFPERCLK.USART0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 0, 0, NULL); - hws[clk_HFPERCLKUSART1] = clk_hw_register_gate(NULL, "HFPERCLK.USART1", - "HFXO", 0, base + CMU_HFPERCLKEN0, 1, 0, NULL); - hws[clk_HFPERCLKUSART2] = clk_hw_register_gate(NULL, "HFPERCLK.USART2", - "HFXO", 0, base + CMU_HFPERCLKEN0, 2, 0, NULL); - hws[clk_HFPERCLKUART0] = clk_hw_register_gate(NULL, "HFPERCLK.UART0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 3, 0, NULL); - hws[clk_HFPERCLKUART1] = clk_hw_register_gate(NULL, "HFPERCLK.UART1", - "HFXO", 0, base + CMU_HFPERCLKEN0, 4, 0, NULL); - hws[clk_HFPERCLKTIMER0] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 5, 0, NULL); - hws[clk_HFPERCLKTIMER1] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER1", - "HFXO", 0, base + CMU_HFPERCLKEN0, 6, 0, NULL); - hws[clk_HFPERCLKTIMER2] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER2", - "HFXO", 0, base + CMU_HFPERCLKEN0, 7, 0, NULL); - hws[clk_HFPERCLKTIMER3] = clk_hw_register_gate(NULL, "HFPERCLK.TIMER3", - "HFXO", 0, base + CMU_HFPERCLKEN0, 8, 0, NULL); - hws[clk_HFPERCLKACMP0] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 9, 0, NULL); - hws[clk_HFPERCLKACMP1] = clk_hw_register_gate(NULL, "HFPERCLK.ACMP1", - "HFXO", 0, base + CMU_HFPERCLKEN0, 10, 0, NULL); - hws[clk_HFPERCLKI2C0] = clk_hw_register_gate(NULL, "HFPERCLK.I2C0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 11, 0, NULL); - hws[clk_HFPERCLKI2C1] = clk_hw_register_gate(NULL, "HFPERCLK.I2C1", - "HFXO", 0, base + CMU_HFPERCLKEN0, 12, 0, NULL); - hws[clk_HFPERCLKGPIO] = clk_hw_register_gate(NULL, "HFPERCLK.GPIO", - "HFXO", 0, base + CMU_HFPERCLKEN0, 13, 0, NULL); - hws[clk_HFPERCLKVCMP] = clk_hw_register_gate(NULL, "HFPERCLK.VCMP", - "HFXO", 0, base + CMU_HFPERCLKEN0, 14, 0, NULL); - hws[clk_HFPERCLKPRS] = clk_hw_register_gate(NULL, "HFPERCLK.PRS", - "HFXO", 0, base + CMU_HFPERCLKEN0, 15, 0, NULL); - hws[clk_HFPERCLKADC0] = clk_hw_register_gate(NULL, "HFPERCLK.ADC0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 16, 0, NULL); - hws[clk_HFPERCLKDAC0] = clk_hw_register_gate(NULL, "HFPERCLK.DAC0", - "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL); - - of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); -} -CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init); diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 70aa521e7e7f..88898b97a443 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright 2013 Freescale Semiconductor, Inc. + * Copyright 2021 NXP * * clock driver for Freescale QorIQ SoCs. */ @@ -564,7 +565,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, 1, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, { @@ -580,7 +583,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, 1, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, { @@ -591,7 +596,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,ls1028a-clockgen", @@ -605,7 +611,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -620,7 +627,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -635,7 +643,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -649,7 +658,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -660,7 +670,7 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), }, { .compat = "fsl,ls2080a-clockgen", @@ -670,7 +680,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x37, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -681,7 +693,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, 1, 1, 1, 1, -1 }, - .pll_mask = 0x37, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_VER3 | CG_LITTLE_ENDIAN, }, { @@ -694,7 +708,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p3041-clockgen", @@ -706,7 +721,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p4080-clockgen", @@ -718,7 +734,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, 1, 1, 1, 1, -1 }, - .pll_mask = 0x1f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | + BIT(CGA_PLL3) | BIT(CGA_PLL4), }, { .compat = "fsl,p5020-clockgen", @@ -730,7 +748,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 1, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), }, { .compat = "fsl,p5040-clockgen", @@ -742,7 +761,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, 1, -1 }, - .pll_mask = 0x0f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3), }, { .compat = "fsl,t1023-clockgen", @@ -757,7 +777,7 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, -1 }, - .pll_mask = 0x03, + .pll_mask = BIT(PLATFORM_PLL) | BIT(CGA_PLL1), .flags = CG_PLL_8BIT, }, { @@ -770,7 +790,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 0, 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -786,7 +807,8 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, -1 }, - .pll_mask = 0x07, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2), .flags = CG_PLL_8BIT, }, { @@ -802,7 +824,9 @@ static const struct clockgen_chipinfo chipinfo[] = { .cmux_to_group = { 0, 0, 1, -1 }, - .pll_mask = 0x3f, + .pll_mask = BIT(PLATFORM_PLL) | + BIT(CGA_PLL1) | BIT(CGA_PLL2) | BIT(CGA_PLL3) | + BIT(CGB_PLL1) | BIT(CGB_PLL2), .flags = CG_PLL_8BIT, }, {}, diff --git a/drivers/clk/clk-si570.c b/drivers/clk/clk-si570.c index 34b25609f55f..eea50121718a 100644 --- a/drivers/clk/clk-si570.c +++ b/drivers/clk/clk-si570.c @@ -4,7 +4,7 @@ * * Copyright (C) 2010, 2011 Ericsson AB. * Copyright (C) 2011 Guenter Roeck. - * Copyright (C) 2011 - 2013 Xilinx Inc. + * Copyright (C) 2011 - 2021 Xilinx Inc. * * Author: Guenter Roeck <guenter.roeck@ericsson.com> * Sören Brinkmann <soren.brinkmann@xilinx.com> @@ -123,14 +123,18 @@ static int si570_get_divs(struct clk_si570 *data, u64 *rfreq, * si570_get_defaults() - Get default values * @data: Driver data structure * @fout: Factory frequency output + * @skip_recall: If true, don't recall NVM into RAM * Returns 0 on success, negative errno otherwise. */ -static int si570_get_defaults(struct clk_si570 *data, u64 fout) +static int si570_get_defaults(struct clk_si570 *data, u64 fout, + bool skip_recall) { int err; u64 fdco; - regmap_write(data->regmap, SI570_REG_CONTROL, SI570_CNTRL_RECALL); + if (!skip_recall) + regmap_write(data->regmap, SI570_REG_CONTROL, + SI570_CNTRL_RECALL); err = si570_get_divs(data, &data->rfreq, &data->n1, &data->hs_div); if (err) @@ -400,6 +404,7 @@ static int si570_probe(struct i2c_client *client, struct clk_si570 *data; struct clk_init_data init; u32 initial_fout, factory_fout, stability; + bool skip_recall; int err; enum clk_si570_variant variant = id->driver_data; @@ -441,6 +446,9 @@ static int si570_probe(struct i2c_client *client, return err; } + skip_recall = of_property_read_bool(client->dev.of_node, + "silabs,skip-recall"); + data->regmap = devm_regmap_init_i2c(client, &si570_regmap_config); if (IS_ERR(data->regmap)) { dev_err(&client->dev, "failed to allocate register map\n"); @@ -448,7 +456,7 @@ static int si570_probe(struct i2c_client *client, } i2c_set_clientdata(client, data); - err = si570_get_defaults(data, factory_fout); + err = si570_get_defaults(data, factory_fout, skip_recall); if (err) return err; diff --git a/drivers/clk/clk-tango4.c b/drivers/clk/clk-tango4.c deleted file mode 100644 index fe12a43f7a40..000000000000 --- a/drivers/clk/clk-tango4.c +++ /dev/null @@ -1,85 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include <linux/kernel.h> -#include <linux/clk-provider.h> -#include <linux/of_address.h> -#include <linux/init.h> -#include <linux/io.h> - -#define CLK_COUNT 4 /* cpu_clk, sys_clk, usb_clk, sdio_clk */ -static struct clk *clks[CLK_COUNT]; -static struct clk_onecell_data clk_data = { clks, CLK_COUNT }; - -#define SYSCLK_DIV 0x20 -#define CPUCLK_DIV 0x24 -#define DIV_BYPASS BIT(23) - -/*** CLKGEN_PLL ***/ -#define extract_pll_n(val) ((val >> 0) & ((1u << 7) - 1)) -#define extract_pll_k(val) ((val >> 13) & ((1u << 3) - 1)) -#define extract_pll_m(val) ((val >> 16) & ((1u << 3) - 1)) -#define extract_pll_isel(val) ((val >> 24) & ((1u << 3) - 1)) - -static void __init make_pll(int idx, const char *parent, void __iomem *base) -{ - char name[8]; - u32 val, mul, div; - - sprintf(name, "pll%d", idx); - val = readl(base + idx * 8); - mul = extract_pll_n(val) + 1; - div = (extract_pll_m(val) + 1) << extract_pll_k(val); - clk_register_fixed_factor(NULL, name, parent, 0, mul, div); - if (extract_pll_isel(val) != 1) - panic("%s: input not set to XTAL_IN\n", name); -} - -static void __init make_cd(int idx, void __iomem *base) -{ - char name[8]; - u32 val, mul, div; - - sprintf(name, "cd%d", idx); - val = readl(base + idx * 8); - mul = 1 << 27; - div = (2 << 27) + val; - clk_register_fixed_factor(NULL, name, "pll2", 0, mul, div); - if (val > 0xf0000000) - panic("%s: unsupported divider %x\n", name, val); -} - -static void __init tango4_clkgen_setup(struct device_node *np) -{ - struct clk **pp = clk_data.clks; - void __iomem *base = of_iomap(np, 0); - const char *parent = of_clk_get_parent_name(np, 0); - - if (!base) - panic("%pOFn: invalid address\n", np); - - if (readl(base + CPUCLK_DIV) & DIV_BYPASS) - panic("%pOFn: unsupported cpuclk setup\n", np); - - if (readl(base + SYSCLK_DIV) & DIV_BYPASS) - panic("%pOFn: unsupported sysclk setup\n", np); - - writel(0x100, base + CPUCLK_DIV); /* disable frequency ramping */ - - make_pll(0, parent, base); - make_pll(1, parent, base); - make_pll(2, parent, base); - make_cd(2, base + 0x80); - make_cd(6, base + 0x80); - - pp[0] = clk_register_divider(NULL, "cpu_clk", "pll0", 0, - base + CPUCLK_DIV, 8, 8, CLK_DIVIDER_ONE_BASED, NULL); - pp[1] = clk_register_fixed_factor(NULL, "sys_clk", "pll1", 0, 1, 4); - pp[2] = clk_register_fixed_factor(NULL, "usb_clk", "cd2", 0, 1, 2); - pp[3] = clk_register_fixed_factor(NULL, "sdio_clk", "cd6", 0, 1, 2); - - if (IS_ERR(pp[0]) || IS_ERR(pp[1]) || IS_ERR(pp[2]) || IS_ERR(pp[3])) - panic("%pOFn: clk registration failed\n", np); - - if (of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data)) - panic("%pOFn: clk provider registration failed\n", np); -} -CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup); diff --git a/drivers/clk/clk-u300.c b/drivers/clk/clk-u300.c deleted file mode 100644 index e228c07c4c6e..000000000000 --- a/drivers/clk/clk-u300.c +++ /dev/null @@ -1,1199 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * U300 clock implementation - * Copyright (C) 2007-2012 ST-Ericsson AB - * Author: Linus Walleij <linus.walleij@stericsson.com> - * Author: Jonas Aaberg <jonas.aberg@stericsson.com> - */ -#include <linux/clkdev.h> -#include <linux/slab.h> -#include <linux/err.h> -#include <linux/io.h> -#include <linux/clk-provider.h> -#include <linux/spinlock.h> -#include <linux/of.h> -#include <linux/platform_data/clk-u300.h> - -/* APP side SYSCON registers */ -/* CLK Control Register 16bit (R/W) */ -#define U300_SYSCON_CCR (0x0000) -#define U300_SYSCON_CCR_I2S1_USE_VCXO (0x0040) -#define U300_SYSCON_CCR_I2S0_USE_VCXO (0x0020) -#define U300_SYSCON_CCR_TURN_VCXO_ON (0x0008) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK (0x0007) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER (0x04) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW (0x03) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE (0x02) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH (0x01) -#define U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST (0x00) -/* CLK Status Register 16bit (R/W) */ -#define U300_SYSCON_CSR (0x0004) -#define U300_SYSCON_CSR_PLL208_LOCK_IND (0x0002) -#define U300_SYSCON_CSR_PLL13_LOCK_IND (0x0001) -/* Reset lines for SLOW devices 16bit (R/W) */ -#define U300_SYSCON_RSR (0x0014) -#define U300_SYSCON_RSR_PPM_RESET_EN (0x0200) -#define U300_SYSCON_RSR_ACC_TMR_RESET_EN (0x0100) -#define U300_SYSCON_RSR_APP_TMR_RESET_EN (0x0080) -#define U300_SYSCON_RSR_RTC_RESET_EN (0x0040) -#define U300_SYSCON_RSR_KEYPAD_RESET_EN (0x0020) -#define U300_SYSCON_RSR_GPIO_RESET_EN (0x0010) -#define U300_SYSCON_RSR_EH_RESET_EN (0x0008) -#define U300_SYSCON_RSR_BTR_RESET_EN (0x0004) -#define U300_SYSCON_RSR_UART_RESET_EN (0x0002) -#define U300_SYSCON_RSR_SLOW_BRIDGE_RESET_EN (0x0001) -/* Reset lines for FAST devices 16bit (R/W) */ -#define U300_SYSCON_RFR (0x0018) -#define U300_SYSCON_RFR_UART1_RESET_ENABLE (0x0080) -#define U300_SYSCON_RFR_SPI_RESET_ENABLE (0x0040) -#define U300_SYSCON_RFR_MMC_RESET_ENABLE (0x0020) -#define U300_SYSCON_RFR_PCM_I2S1_RESET_ENABLE (0x0010) -#define U300_SYSCON_RFR_PCM_I2S0_RESET_ENABLE (0x0008) -#define U300_SYSCON_RFR_I2C1_RESET_ENABLE (0x0004) -#define U300_SYSCON_RFR_I2C0_RESET_ENABLE (0x0002) -#define U300_SYSCON_RFR_FAST_BRIDGE_RESET_ENABLE (0x0001) -/* Reset lines for the rest of the peripherals 16bit (R/W) */ -#define U300_SYSCON_RRR (0x001c) -#define U300_SYSCON_RRR_CDS_RESET_EN (0x4000) -#define U300_SYSCON_RRR_ISP_RESET_EN (0x2000) -#define U300_SYSCON_RRR_INTCON_RESET_EN (0x1000) -#define U300_SYSCON_RRR_MSPRO_RESET_EN (0x0800) -#define U300_SYSCON_RRR_XGAM_RESET_EN (0x0100) -#define U300_SYSCON_RRR_XGAM_VC_SYNC_RESET_EN (0x0080) -#define U300_SYSCON_RRR_NANDIF_RESET_EN (0x0040) -#define U300_SYSCON_RRR_EMIF_RESET_EN (0x0020) -#define U300_SYSCON_RRR_DMAC_RESET_EN (0x0010) -#define U300_SYSCON_RRR_CPU_RESET_EN (0x0008) -#define U300_SYSCON_RRR_APEX_RESET_EN (0x0004) -#define U300_SYSCON_RRR_AHB_RESET_EN (0x0002) -#define U300_SYSCON_RRR_AAIF_RESET_EN (0x0001) -/* Clock enable for SLOW peripherals 16bit (R/W) */ -#define U300_SYSCON_CESR (0x0020) -#define U300_SYSCON_CESR_PPM_CLK_EN (0x0200) -#define U300_SYSCON_CESR_ACC_TMR_CLK_EN (0x0100) -#define U300_SYSCON_CESR_APP_TMR_CLK_EN (0x0080) -#define U300_SYSCON_CESR_KEYPAD_CLK_EN (0x0040) -#define U300_SYSCON_CESR_GPIO_CLK_EN (0x0010) -#define U300_SYSCON_CESR_EH_CLK_EN (0x0008) -#define U300_SYSCON_CESR_BTR_CLK_EN (0x0004) -#define U300_SYSCON_CESR_UART_CLK_EN (0x0002) -#define U300_SYSCON_CESR_SLOW_BRIDGE_CLK_EN (0x0001) -/* Clock enable for FAST peripherals 16bit (R/W) */ -#define U300_SYSCON_CEFR (0x0024) -#define U300_SYSCON_CEFR_UART1_CLK_EN (0x0200) -#define U300_SYSCON_CEFR_I2S1_CORE_CLK_EN (0x0100) -#define U300_SYSCON_CEFR_I2S0_CORE_CLK_EN (0x0080) -#define U300_SYSCON_CEFR_SPI_CLK_EN (0x0040) -#define U300_SYSCON_CEFR_MMC_CLK_EN (0x0020) -#define U300_SYSCON_CEFR_I2S1_CLK_EN (0x0010) -#define U300_SYSCON_CEFR_I2S0_CLK_EN (0x0008) -#define U300_SYSCON_CEFR_I2C1_CLK_EN (0x0004) -#define U300_SYSCON_CEFR_I2C0_CLK_EN (0x0002) -#define U300_SYSCON_CEFR_FAST_BRIDGE_CLK_EN (0x0001) -/* Clock enable for the rest of the peripherals 16bit (R/W) */ -#define U300_SYSCON_CERR (0x0028) -#define U300_SYSCON_CERR_CDS_CLK_EN (0x2000) -#define U300_SYSCON_CERR_ISP_CLK_EN (0x1000) -#define U300_SYSCON_CERR_MSPRO_CLK_EN (0x0800) -#define U300_SYSCON_CERR_AHB_SUBSYS_BRIDGE_CLK_EN (0x0400) -#define U300_SYSCON_CERR_SEMI_CLK_EN (0x0200) -#define U300_SYSCON_CERR_XGAM_CLK_EN (0x0100) -#define U300_SYSCON_CERR_VIDEO_ENC_CLK_EN (0x0080) -#define U300_SYSCON_CERR_NANDIF_CLK_EN (0x0040) -#define U300_SYSCON_CERR_EMIF_CLK_EN (0x0020) -#define U300_SYSCON_CERR_DMAC_CLK_EN (0x0010) -#define U300_SYSCON_CERR_CPU_CLK_EN (0x0008) -#define U300_SYSCON_CERR_APEX_CLK_EN (0x0004) -#define U300_SYSCON_CERR_AHB_CLK_EN (0x0002) -#define U300_SYSCON_CERR_AAIF_CLK_EN (0x0001) -/* Single block clock enable 16bit (-/W) */ -#define U300_SYSCON_SBCER (0x002c) -#define U300_SYSCON_SBCER_PPM_CLK_EN (0x0009) -#define U300_SYSCON_SBCER_ACC_TMR_CLK_EN (0x0008) -#define U300_SYSCON_SBCER_APP_TMR_CLK_EN (0x0007) -#define U300_SYSCON_SBCER_KEYPAD_CLK_EN (0x0006) -#define U300_SYSCON_SBCER_GPIO_CLK_EN (0x0004) -#define U300_SYSCON_SBCER_EH_CLK_EN (0x0003) -#define U300_SYSCON_SBCER_BTR_CLK_EN (0x0002) -#define U300_SYSCON_SBCER_UART_CLK_EN (0x0001) -#define U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN (0x0000) -#define U300_SYSCON_SBCER_UART1_CLK_EN (0x0019) -#define U300_SYSCON_SBCER_I2S1_CORE_CLK_EN (0x0018) -#define U300_SYSCON_SBCER_I2S0_CORE_CLK_EN (0x0017) -#define U300_SYSCON_SBCER_SPI_CLK_EN (0x0016) -#define U300_SYSCON_SBCER_MMC_CLK_EN (0x0015) -#define U300_SYSCON_SBCER_I2S1_CLK_EN (0x0014) -#define U300_SYSCON_SBCER_I2S0_CLK_EN (0x0013) -#define U300_SYSCON_SBCER_I2C1_CLK_EN (0x0012) -#define U300_SYSCON_SBCER_I2C0_CLK_EN (0x0011) -#define U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN (0x0010) -#define U300_SYSCON_SBCER_CDS_CLK_EN (0x002D) -#define U300_SYSCON_SBCER_ISP_CLK_EN (0x002C) -#define U300_SYSCON_SBCER_MSPRO_CLK_EN (0x002B) -#define U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN (0x002A) -#define U300_SYSCON_SBCER_SEMI_CLK_EN (0x0029) -#define U300_SYSCON_SBCER_XGAM_CLK_EN (0x0028) -#define U300_SYSCON_SBCER_VIDEO_ENC_CLK_EN (0x0027) -#define U300_SYSCON_SBCER_NANDIF_CLK_EN (0x0026) -#define U300_SYSCON_SBCER_EMIF_CLK_EN (0x0025) -#define U300_SYSCON_SBCER_DMAC_CLK_EN (0x0024) -#define U300_SYSCON_SBCER_CPU_CLK_EN (0x0023) -#define U300_SYSCON_SBCER_APEX_CLK_EN (0x0022) -#define U300_SYSCON_SBCER_AHB_CLK_EN (0x0021) -#define U300_SYSCON_SBCER_AAIF_CLK_EN (0x0020) -/* Single block clock disable 16bit (-/W) */ -#define U300_SYSCON_SBCDR (0x0030) -/* Same values as above for SBCER */ -/* Clock force SLOW peripherals 16bit (R/W) */ -#define U300_SYSCON_CFSR (0x003c) -#define U300_SYSCON_CFSR_PPM_CLK_FORCE_EN (0x0200) -#define U300_SYSCON_CFSR_ACC_TMR_CLK_FORCE_EN (0x0100) -#define U300_SYSCON_CFSR_APP_TMR_CLK_FORCE_EN (0x0080) -#define U300_SYSCON_CFSR_KEYPAD_CLK_FORCE_EN (0x0020) -#define U300_SYSCON_CFSR_GPIO_CLK_FORCE_EN (0x0010) -#define U300_SYSCON_CFSR_EH_CLK_FORCE_EN (0x0008) -#define U300_SYSCON_CFSR_BTR_CLK_FORCE_EN (0x0004) -#define U300_SYSCON_CFSR_UART_CLK_FORCE_EN (0x0002) -#define U300_SYSCON_CFSR_SLOW_BRIDGE_CLK_FORCE_EN (0x0001) -/* Clock force FAST peripherals 16bit (R/W) */ -#define U300_SYSCON_CFFR (0x40) -/* Values not defined. Define if you want to use them. */ -/* Clock force the rest of the peripherals 16bit (R/W) */ -#define U300_SYSCON_CFRR (0x44) -#define U300_SYSCON_CFRR_CDS_CLK_FORCE_EN (0x2000) -#define U300_SYSCON_CFRR_ISP_CLK_FORCE_EN (0x1000) -#define U300_SYSCON_CFRR_MSPRO_CLK_FORCE_EN (0x0800) -#define U300_SYSCON_CFRR_AHB_SUBSYS_BRIDGE_CLK_FORCE_EN (0x0400) -#define U300_SYSCON_CFRR_SEMI_CLK_FORCE_EN (0x0200) -#define U300_SYSCON_CFRR_XGAM_CLK_FORCE_EN (0x0100) -#define U300_SYSCON_CFRR_VIDEO_ENC_CLK_FORCE_EN (0x0080) -#define U300_SYSCON_CFRR_NANDIF_CLK_FORCE_EN (0x0040) -#define U300_SYSCON_CFRR_EMIF_CLK_FORCE_EN (0x0020) -#define U300_SYSCON_CFRR_DMAC_CLK_FORCE_EN (0x0010) -#define U300_SYSCON_CFRR_CPU_CLK_FORCE_EN (0x0008) -#define U300_SYSCON_CFRR_APEX_CLK_FORCE_EN (0x0004) -#define U300_SYSCON_CFRR_AHB_CLK_FORCE_EN (0x0002) -#define U300_SYSCON_CFRR_AAIF_CLK_FORCE_EN (0x0001) -/* PLL208 Frequency Control 16bit (R/W) */ -#define U300_SYSCON_PFCR (0x48) -#define U300_SYSCON_PFCR_DPLL_MULT_NUM (0x000F) -/* Power Management Control 16bit (R/W) */ -#define U300_SYSCON_PMCR (0x50) -#define U300_SYSCON_PMCR_DCON_ENABLE (0x0002) -#define U300_SYSCON_PMCR_PWR_MGNT_ENABLE (0x0001) -/* Reset Out 16bit (R/W) */ -#define U300_SYSCON_RCR (0x6c) -#define U300_SYSCON_RCR_RESOUT0_RST_N_DISABLE (0x0001) -/* EMIF Slew Rate Control 16bit (R/W) */ -#define U300_SYSCON_SRCLR (0x70) -#define U300_SYSCON_SRCLR_MASK (0x03FF) -#define U300_SYSCON_SRCLR_VALUE (0x03FF) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_B (0x0200) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_5_A (0x0100) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_B (0x0080) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_4_A (0x0040) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_B (0x0020) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_3_A (0x0010) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_B (0x0008) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_2_A (0x0004) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_B (0x0002) -#define U300_SYSCON_SRCLR_EMIF_1_SLRC_1_A (0x0001) -/* EMIF Clock Control Register 16bit (R/W) */ -#define U300_SYSCON_ECCR (0x0078) -#define U300_SYSCON_ECCR_MASK (0x000F) -#define U300_SYSCON_ECCR_EMIF_1_STATIC_CLK_EN_N_DISABLE (0x0008) -#define U300_SYSCON_ECCR_EMIF_1_RET_OUT_CLK_EN_N_DISABLE (0x0004) -#define U300_SYSCON_ECCR_EMIF_MEMCLK_RET_EN_N_DISABLE (0x0002) -#define U300_SYSCON_ECCR_EMIF_SDRCLK_RET_EN_N_DISABLE (0x0001) -/* MMC/MSPRO frequency divider register 0 16bit (R/W) */ -#define U300_SYSCON_MMF0R (0x90) -#define U300_SYSCON_MMF0R_MASK (0x00FF) -#define U300_SYSCON_MMF0R_FREQ_0_HIGH_MASK (0x00F0) -#define U300_SYSCON_MMF0R_FREQ_0_LOW_MASK (0x000F) -/* MMC/MSPRO frequency divider register 1 16bit (R/W) */ -#define U300_SYSCON_MMF1R (0x94) -#define U300_SYSCON_MMF1R_MASK (0x00FF) -#define U300_SYSCON_MMF1R_FREQ_1_HIGH_MASK (0x00F0) -#define U300_SYSCON_MMF1R_FREQ_1_LOW_MASK (0x000F) -/* Clock control for the MMC and MSPRO blocks 16bit (R/W) */ -#define U300_SYSCON_MMCR (0x9C) -#define U300_SYSCON_MMCR_MASK (0x0003) -#define U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE (0x0002) -#define U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE (0x0001) -/* SYS_0_CLK_CONTROL first clock control 16bit (R/W) */ -#define U300_SYSCON_S0CCR (0x120) -#define U300_SYSCON_S0CCR_FIELD_MASK (0x43FF) -#define U300_SYSCON_S0CCR_CLOCK_REQ (0x4000) -#define U300_SYSCON_S0CCR_CLOCK_REQ_MONITOR (0x2000) -#define U300_SYSCON_S0CCR_CLOCK_INV (0x0200) -#define U300_SYSCON_S0CCR_CLOCK_FREQ_MASK (0x01E0) -#define U300_SYSCON_S0CCR_CLOCK_SELECT_MASK (0x001E) -#define U300_SYSCON_S0CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S0CCR_SEL_MCLK (0x8 << 1) -#define U300_SYSCON_S0CCR_SEL_ACC_FSM_CLK (0xA << 1) -#define U300_SYSCON_S0CCR_SEL_PLL60_48_CLK (0xC << 1) -#define U300_SYSCON_S0CCR_SEL_PLL60_60_CLK (0xD << 1) -#define U300_SYSCON_S0CCR_SEL_ACC_PLL208_CLK (0xE << 1) -#define U300_SYSCON_S0CCR_SEL_APP_PLL13_CLK (0x0 << 1) -#define U300_SYSCON_S0CCR_SEL_APP_FSM_CLK (0x2 << 1) -#define U300_SYSCON_S0CCR_SEL_RTC_CLK (0x4 << 1) -#define U300_SYSCON_S0CCR_SEL_APP_PLL208_CLK (0x6 << 1) -/* SYS_1_CLK_CONTROL second clock control 16 bit (R/W) */ -#define U300_SYSCON_S1CCR (0x124) -#define U300_SYSCON_S1CCR_FIELD_MASK (0x43FF) -#define U300_SYSCON_S1CCR_CLOCK_REQ (0x4000) -#define U300_SYSCON_S1CCR_CLOCK_REQ_MONITOR (0x2000) -#define U300_SYSCON_S1CCR_CLOCK_INV (0x0200) -#define U300_SYSCON_S1CCR_CLOCK_FREQ_MASK (0x01E0) -#define U300_SYSCON_S1CCR_CLOCK_SELECT_MASK (0x001E) -#define U300_SYSCON_S1CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S1CCR_SEL_MCLK (0x8 << 1) -#define U300_SYSCON_S1CCR_SEL_ACC_FSM_CLK (0xA << 1) -#define U300_SYSCON_S1CCR_SEL_PLL60_48_CLK (0xC << 1) -#define U300_SYSCON_S1CCR_SEL_PLL60_60_CLK (0xD << 1) -#define U300_SYSCON_S1CCR_SEL_ACC_PLL208_CLK (0xE << 1) -#define U300_SYSCON_S1CCR_SEL_ACC_PLL13_CLK (0x0 << 1) -#define U300_SYSCON_S1CCR_SEL_APP_FSM_CLK (0x2 << 1) -#define U300_SYSCON_S1CCR_SEL_RTC_CLK (0x4 << 1) -#define U300_SYSCON_S1CCR_SEL_APP_PLL208_CLK (0x6 << 1) -/* SYS_2_CLK_CONTROL third clock control 16 bit (R/W) */ -#define U300_SYSCON_S2CCR (0x128) -#define U300_SYSCON_S2CCR_FIELD_MASK (0xC3FF) -#define U300_SYSCON_S2CCR_CLK_STEAL (0x8000) -#define U300_SYSCON_S2CCR_CLOCK_REQ (0x4000) -#define U300_SYSCON_S2CCR_CLOCK_REQ_MONITOR (0x2000) -#define U300_SYSCON_S2CCR_CLOCK_INV (0x0200) -#define U300_SYSCON_S2CCR_CLOCK_FREQ_MASK (0x01E0) -#define U300_SYSCON_S2CCR_CLOCK_SELECT_MASK (0x001E) -#define U300_SYSCON_S2CCR_CLOCK_ENABLE (0x0001) -#define U300_SYSCON_S2CCR_SEL_MCLK (0x8 << 1) -#define U300_SYSCON_S2CCR_SEL_ACC_FSM_CLK (0xA << 1) -#define U300_SYSCON_S2CCR_SEL_PLL60_48_CLK (0xC << 1) -#define U300_SYSCON_S2CCR_SEL_PLL60_60_CLK (0xD << 1) -#define U300_SYSCON_S2CCR_SEL_ACC_PLL208_CLK (0xE << 1) -#define U300_SYSCON_S2CCR_SEL_ACC_PLL13_CLK (0x0 << 1) -#define U300_SYSCON_S2CCR_SEL_APP_FSM_CLK (0x2 << 1) -#define U300_SYSCON_S2CCR_SEL_RTC_CLK (0x4 << 1) -#define U300_SYSCON_S2CCR_SEL_APP_PLL208_CLK (0x6 << 1) -/* SC_PLL_IRQ_CONTROL 16bit (R/W) */ -#define U300_SYSCON_PICR (0x0130) -#define U300_SYSCON_PICR_MASK (0x00FF) -#define U300_SYSCON_PICR_FORCE_PLL208_LOCK_LOW_ENABLE (0x0080) -#define U300_SYSCON_PICR_FORCE_PLL208_LOCK_HIGH_ENABLE (0x0040) -#define U300_SYSCON_PICR_FORCE_PLL13_LOCK_LOW_ENABLE (0x0020) -#define U300_SYSCON_PICR_FORCE_PLL13_LOCK_HIGH_ENABLE (0x0010) -#define U300_SYSCON_PICR_IRQMASK_PLL13_UNLOCK_ENABLE (0x0008) -#define U300_SYSCON_PICR_IRQMASK_PLL13_LOCK_ENABLE (0x0004) -#define U300_SYSCON_PICR_IRQMASK_PLL208_UNLOCK_ENABLE (0x0002) -#define U300_SYSCON_PICR_IRQMASK_PLL208_LOCK_ENABLE (0x0001) -/* SC_PLL_IRQ_STATUS 16 bit (R/-) */ -#define U300_SYSCON_PISR (0x0134) -#define U300_SYSCON_PISR_MASK (0x000F) -#define U300_SYSCON_PISR_PLL13_UNLOCK_IND (0x0008) -#define U300_SYSCON_PISR_PLL13_LOCK_IND (0x0004) -#define U300_SYSCON_PISR_PLL208_UNLOCK_IND (0x0002) -#define U300_SYSCON_PISR_PLL208_LOCK_IND (0x0001) -/* SC_PLL_IRQ_CLEAR 16 bit (-/W) */ -#define U300_SYSCON_PICLR (0x0138) -#define U300_SYSCON_PICLR_MASK (0x000F) -#define U300_SYSCON_PICLR_RWMASK (0x0000) -#define U300_SYSCON_PICLR_PLL13_UNLOCK_SC (0x0008) -#define U300_SYSCON_PICLR_PLL13_LOCK_SC (0x0004) -#define U300_SYSCON_PICLR_PLL208_UNLOCK_SC (0x0002) -#define U300_SYSCON_PICLR_PLL208_LOCK_SC (0x0001) -/* Clock activity observability register 0 */ -#define U300_SYSCON_C0OAR (0x140) -#define U300_SYSCON_C0OAR_MASK (0xFFFF) -#define U300_SYSCON_C0OAR_VALUE (0xFFFF) -#define U300_SYSCON_C0OAR_BT_H_CLK (0x8000) -#define U300_SYSCON_C0OAR_ASPB_P_CLK (0x4000) -#define U300_SYSCON_C0OAR_APP_SEMI_H_CLK (0x2000) -#define U300_SYSCON_C0OAR_APP_SEMI_CLK (0x1000) -#define U300_SYSCON_C0OAR_APP_MMC_MSPRO_CLK (0x0800) -#define U300_SYSCON_C0OAR_APP_I2S1_CLK (0x0400) -#define U300_SYSCON_C0OAR_APP_I2S0_CLK (0x0200) -#define U300_SYSCON_C0OAR_APP_CPU_CLK (0x0100) -#define U300_SYSCON_C0OAR_APP_52_CLK (0x0080) -#define U300_SYSCON_C0OAR_APP_208_CLK (0x0040) -#define U300_SYSCON_C0OAR_APP_104_CLK (0x0020) -#define U300_SYSCON_C0OAR_APEX_CLK (0x0010) -#define U300_SYSCON_C0OAR_AHPB_M_H_CLK (0x0008) -#define U300_SYSCON_C0OAR_AHB_CLK (0x0004) -#define U300_SYSCON_C0OAR_AFPB_P_CLK (0x0002) -#define U300_SYSCON_C0OAR_AAIF_CLK (0x0001) -/* Clock activity observability register 1 */ -#define U300_SYSCON_C1OAR (0x144) -#define U300_SYSCON_C1OAR_MASK (0x3FFE) -#define U300_SYSCON_C1OAR_VALUE (0x3FFE) -#define U300_SYSCON_C1OAR_NFIF_F_CLK (0x2000) -#define U300_SYSCON_C1OAR_MSPRO_CLK (0x1000) -#define U300_SYSCON_C1OAR_MMC_P_CLK (0x0800) -#define U300_SYSCON_C1OAR_MMC_CLK (0x0400) -#define U300_SYSCON_C1OAR_KP_P_CLK (0x0200) -#define U300_SYSCON_C1OAR_I2C1_P_CLK (0x0100) -#define U300_SYSCON_C1OAR_I2C0_P_CLK (0x0080) -#define U300_SYSCON_C1OAR_GPIO_CLK (0x0040) -#define U300_SYSCON_C1OAR_EMIF_MPMC_CLK (0x0020) -#define U300_SYSCON_C1OAR_EMIF_H_CLK (0x0010) -#define U300_SYSCON_C1OAR_EVHIST_CLK (0x0008) -#define U300_SYSCON_C1OAR_PPM_CLK (0x0004) -#define U300_SYSCON_C1OAR_DMA_CLK (0x0002) -/* Clock activity observability register 2 */ -#define U300_SYSCON_C2OAR (0x148) -#define U300_SYSCON_C2OAR_MASK (0x0FFF) -#define U300_SYSCON_C2OAR_VALUE (0x0FFF) -#define U300_SYSCON_C2OAR_XGAM_CDI_CLK (0x0800) -#define U300_SYSCON_C2OAR_XGAM_CLK (0x0400) -#define U300_SYSCON_C2OAR_VC_H_CLK (0x0200) -#define U300_SYSCON_C2OAR_VC_CLK (0x0100) -#define U300_SYSCON_C2OAR_UA_P_CLK (0x0080) -#define U300_SYSCON_C2OAR_TMR1_CLK (0x0040) -#define U300_SYSCON_C2OAR_TMR0_CLK (0x0020) -#define U300_SYSCON_C2OAR_SPI_P_CLK (0x0010) -#define U300_SYSCON_C2OAR_PCM_I2S1_CORE_CLK (0x0008) -#define U300_SYSCON_C2OAR_PCM_I2S1_CLK (0x0004) -#define U300_SYSCON_C2OAR_PCM_I2S0_CORE_CLK (0x0002) -#define U300_SYSCON_C2OAR_PCM_I2S0_CLK (0x0001) - - -/* - * The clocking hierarchy currently looks like this. - * NOTE: the idea is NOT to show how the clocks are routed on the chip! - * The ideas is to show dependencies, so a clock higher up in the - * hierarchy has to be on in order for another clock to be on. Now, - * both CPU and DMA can actually be on top of the hierarchy, and that - * is not modeled currently. Instead we have the backbone AMBA bus on - * top. This bus cannot be programmed in any way but conceptually it - * needs to be active for the bridges and devices to transport data. - * - * Please be aware that a few clocks are hw controlled, which mean that - * the hw itself can turn on/off or change the rate of the clock when - * needed! - * - * AMBA bus - * | - * +- CPU - * +- FSMC NANDIF NAND Flash interface - * +- SEMI Shared Memory interface - * +- ISP Image Signal Processor (U335 only) - * +- CDS (U335 only) - * +- DMA Direct Memory Access Controller - * +- AAIF APP/ACC Interface (Mobile Scalable Link, MSL) - * +- APEX - * +- VIDEO_ENC AVE2/3 Video Encoder - * +- XGAM Graphics Accelerator Controller - * +- AHB - * | - * +- ahb:0 AHB Bridge - * | | - * | +- ahb:1 INTCON Interrupt controller - * | +- ahb:3 MSPRO Memory Stick Pro controller - * | +- ahb:4 EMIF External Memory interface - * | - * +- fast:0 FAST bridge - * | | - * | +- fast:1 MMCSD MMC/SD card reader controller - * | +- fast:2 I2S0 PCM I2S channel 0 controller - * | +- fast:3 I2S1 PCM I2S channel 1 controller - * | +- fast:4 I2C0 I2C channel 0 controller - * | +- fast:5 I2C1 I2C channel 1 controller - * | +- fast:6 SPI SPI controller - * | +- fast:7 UART1 Secondary UART (U335 only) - * | - * +- slow:0 SLOW bridge - * | - * +- slow:1 SYSCON (not possible to control) - * +- slow:2 WDOG Watchdog - * +- slow:3 UART0 primary UART - * +- slow:4 TIMER_APP Application timer - used in Linux - * +- slow:5 KEYPAD controller - * +- slow:6 GPIO controller - * +- slow:7 RTC controller - * +- slow:8 BT Bus Tracer (not used currently) - * +- slow:9 EH Event Handler (not used currently) - * +- slow:a TIMER_ACC Access style timer (not used currently) - * +- slow:b PPM (U335 only, what is that?) - */ - -/* Global syscon virtual base */ -static void __iomem *syscon_vbase; - -/** - * struct clk_syscon - U300 syscon clock - * @hw: corresponding clock hardware entry - * @hw_ctrld: whether this clock is hardware controlled (for refcount etc) - * and does not need any magic pokes to be enabled/disabled - * @reset: state holder, whether this block's reset line is asserted or not - * @res_reg: reset line enable/disable flag register - * @res_bit: bit for resetting or taking this consumer out of reset - * @en_reg: clock line enable/disable flag register - * @en_bit: bit for enabling/disabling this consumer clock line - * @clk_val: magic value to poke in the register to enable/disable - * this one clock - */ -struct clk_syscon { - struct clk_hw hw; - bool hw_ctrld; - bool reset; - void __iomem *res_reg; - u8 res_bit; - void __iomem *en_reg; - u8 en_bit; - u16 clk_val; -}; - -#define to_syscon(_hw) container_of(_hw, struct clk_syscon, hw) - -static DEFINE_SPINLOCK(syscon_resetreg_lock); - -/* - * Reset control functions. We remember if a block has been - * taken out of reset and don't remove the reset assertion again - * and vice versa. Currently we only remove resets so the - * enablement function is defined out. - */ -static void syscon_block_reset_enable(struct clk_syscon *sclk) -{ - unsigned long iflags; - u16 val; - - /* Not all blocks support resetting */ - if (!sclk->res_reg) - return; - spin_lock_irqsave(&syscon_resetreg_lock, iflags); - val = readw(sclk->res_reg); - val |= BIT(sclk->res_bit); - writew(val, sclk->res_reg); - spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); - sclk->reset = true; -} - -static void syscon_block_reset_disable(struct clk_syscon *sclk) -{ - unsigned long iflags; - u16 val; - - /* Not all blocks support resetting */ - if (!sclk->res_reg) - return; - spin_lock_irqsave(&syscon_resetreg_lock, iflags); - val = readw(sclk->res_reg); - val &= ~BIT(sclk->res_bit); - writew(val, sclk->res_reg); - spin_unlock_irqrestore(&syscon_resetreg_lock, iflags); - sclk->reset = false; -} - -static int syscon_clk_prepare(struct clk_hw *hw) -{ - struct clk_syscon *sclk = to_syscon(hw); - - /* If the block is in reset, bring it out */ - if (sclk->reset) - syscon_block_reset_disable(sclk); - return 0; -} - -static void syscon_clk_unprepare(struct clk_hw *hw) -{ - struct clk_syscon *sclk = to_syscon(hw); - - /* Please don't force the console into reset */ - if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN) - return; - /* When unpreparing, force block into reset */ - if (!sclk->reset) - syscon_block_reset_enable(sclk); -} - -static int syscon_clk_enable(struct clk_hw *hw) -{ - struct clk_syscon *sclk = to_syscon(hw); - - /* Don't touch the hardware controlled clocks */ - if (sclk->hw_ctrld) - return 0; - /* These cannot be controlled */ - if (sclk->clk_val == 0xFFFFU) - return 0; - - writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCER); - return 0; -} - -static void syscon_clk_disable(struct clk_hw *hw) -{ - struct clk_syscon *sclk = to_syscon(hw); - - /* Don't touch the hardware controlled clocks */ - if (sclk->hw_ctrld) - return; - if (sclk->clk_val == 0xFFFFU) - return; - /* Please don't disable the console port */ - if (sclk->clk_val == U300_SYSCON_SBCER_UART_CLK_EN) - return; - - writew(sclk->clk_val, syscon_vbase + U300_SYSCON_SBCDR); -} - -static int syscon_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_syscon *sclk = to_syscon(hw); - u16 val; - - /* If no enable register defined, it's always-on */ - if (!sclk->en_reg) - return 1; - - val = readw(sclk->en_reg); - val &= BIT(sclk->en_bit); - - return val ? 1 : 0; -} - -static u16 syscon_get_perf(void) -{ - u16 val; - - val = readw(syscon_vbase + U300_SYSCON_CCR); - val &= U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; - return val; -} - -static unsigned long -syscon_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_syscon *sclk = to_syscon(hw); - u16 perf = syscon_get_perf(); - - switch (sclk->clk_val) { - case U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN: - case U300_SYSCON_SBCER_I2C0_CLK_EN: - case U300_SYSCON_SBCER_I2C1_CLK_EN: - case U300_SYSCON_SBCER_MMC_CLK_EN: - case U300_SYSCON_SBCER_SPI_CLK_EN: - /* The FAST clocks have one progression */ - switch (perf) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - default: - return parent_rate; /* 26 MHz */ - } - case U300_SYSCON_SBCER_DMAC_CLK_EN: - case U300_SYSCON_SBCER_NANDIF_CLK_EN: - case U300_SYSCON_SBCER_XGAM_CLK_EN: - /* AMBA interconnect peripherals */ - switch (perf) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 6500000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 26000000; - default: - return parent_rate; /* 52 MHz */ - } - case U300_SYSCON_SBCER_SEMI_CLK_EN: - case U300_SYSCON_SBCER_EMIF_CLK_EN: - /* EMIF speeds */ - switch (perf) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 52000000; - default: - return 104000000; - } - case U300_SYSCON_SBCER_CPU_CLK_EN: - /* And the fast CPU clock */ - switch (perf) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - return 52000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - return 104000000; - default: - return parent_rate; /* 208 MHz */ - } - default: - /* - * The SLOW clocks and default just inherit the rate of - * their parent (typically PLL13 13 MHz). - */ - return parent_rate; - } -} - -static long -syscon_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_syscon *sclk = to_syscon(hw); - - if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN) - return *prate; - /* We really only support setting the rate of the CPU clock */ - if (rate <= 13000000) - return 13000000; - if (rate <= 52000000) - return 52000000; - if (rate <= 104000000) - return 104000000; - return 208000000; -} - -static int syscon_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_syscon *sclk = to_syscon(hw); - u16 val; - - /* We only support setting the rate of the CPU clock */ - if (sclk->clk_val != U300_SYSCON_SBCER_CPU_CLK_EN) - return -EINVAL; - switch (rate) { - case 13000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER; - break; - case 52000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE; - break; - case 104000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH; - break; - case 208000000: - val = U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST; - break; - default: - return -EINVAL; - } - val |= readw(syscon_vbase + U300_SYSCON_CCR) & - ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK ; - writew(val, syscon_vbase + U300_SYSCON_CCR); - return 0; -} - -static const struct clk_ops syscon_clk_ops = { - .prepare = syscon_clk_prepare, - .unprepare = syscon_clk_unprepare, - .enable = syscon_clk_enable, - .disable = syscon_clk_disable, - .is_enabled = syscon_clk_is_enabled, - .recalc_rate = syscon_clk_recalc_rate, - .round_rate = syscon_clk_round_rate, - .set_rate = syscon_clk_set_rate, -}; - -static struct clk_hw * __init -syscon_clk_register(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - bool hw_ctrld, - void __iomem *res_reg, u8 res_bit, - void __iomem *en_reg, u8 en_bit, - u16 clk_val) -{ - struct clk_hw *hw; - struct clk_syscon *sclk; - struct clk_init_data init; - int ret; - - sclk = kzalloc(sizeof(*sclk), GFP_KERNEL); - if (!sclk) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &syscon_clk_ops; - init.flags = flags; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - sclk->hw.init = &init; - sclk->hw_ctrld = hw_ctrld; - /* Assume the block is in reset at registration */ - sclk->reset = true; - sclk->res_reg = res_reg; - sclk->res_bit = res_bit; - sclk->en_reg = en_reg; - sclk->en_bit = en_bit; - sclk->clk_val = clk_val; - - hw = &sclk->hw; - ret = clk_hw_register(dev, hw); - if (ret) { - kfree(sclk); - hw = ERR_PTR(ret); - } - - return hw; -} - -#define U300_CLK_TYPE_SLOW 0 -#define U300_CLK_TYPE_FAST 1 -#define U300_CLK_TYPE_REST 2 - -/** - * struct u300_clock - defines the bits and pieces for a certain clock - * @type: the clock type, slow fast or rest - * @id: the bit in the slow/fast/rest register for this clock - * @hw_ctrld: whether the clock is hardware controlled - * @clk_val: a value to poke in the one-write enable/disable registers - */ -struct u300_clock { - u8 type; - u8 id; - bool hw_ctrld; - u16 clk_val; -}; - -static struct u300_clock const u300_clk_lookup[] __initconst = { - { - .type = U300_CLK_TYPE_REST, - .id = 3, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_CPU_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 4, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_DMAC_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 5, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_EMIF_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 6, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_NANDIF_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 8, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_XGAM_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 9, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_SEMI_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 10, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_AHB_SUBSYS_BRIDGE_CLK_EN, - }, - { - .type = U300_CLK_TYPE_REST, - .id = 12, - .hw_ctrld = false, - /* INTCON: cannot be enabled, just taken out of reset */ - .clk_val = 0xFFFFU, - }, - { - .type = U300_CLK_TYPE_FAST, - .id = 0, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_FAST_BRIDGE_CLK_EN, - }, - { - .type = U300_CLK_TYPE_FAST, - .id = 1, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_I2C0_CLK_EN, - }, - { - .type = U300_CLK_TYPE_FAST, - .id = 2, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_I2C1_CLK_EN, - }, - { - .type = U300_CLK_TYPE_FAST, - .id = 5, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_MMC_CLK_EN, - }, - { - .type = U300_CLK_TYPE_FAST, - .id = 6, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_SPI_CLK_EN, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 0, - .hw_ctrld = true, - .clk_val = U300_SYSCON_SBCER_SLOW_BRIDGE_CLK_EN, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 1, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_UART_CLK_EN, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 4, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_GPIO_CLK_EN, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 6, - .hw_ctrld = true, - /* No clock enable register bit */ - .clk_val = 0xFFFFU, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 7, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_APP_TMR_CLK_EN, - }, - { - .type = U300_CLK_TYPE_SLOW, - .id = 8, - .hw_ctrld = false, - .clk_val = U300_SYSCON_SBCER_ACC_TMR_CLK_EN, - }, -}; - -static void __init of_u300_syscon_clk_init(struct device_node *np) -{ - struct clk_hw *hw = ERR_PTR(-EINVAL); - const char *clk_name = np->name; - const char *parent_name; - void __iomem *res_reg; - void __iomem *en_reg; - u32 clk_type; - u32 clk_id; - int i; - - if (of_property_read_u32(np, "clock-type", &clk_type)) { - pr_err("%s: syscon clock \"%s\" missing clock-type property\n", - __func__, clk_name); - return; - } - if (of_property_read_u32(np, "clock-id", &clk_id)) { - pr_err("%s: syscon clock \"%s\" missing clock-id property\n", - __func__, clk_name); - return; - } - parent_name = of_clk_get_parent_name(np, 0); - - switch (clk_type) { - case U300_CLK_TYPE_SLOW: - res_reg = syscon_vbase + U300_SYSCON_RSR; - en_reg = syscon_vbase + U300_SYSCON_CESR; - break; - case U300_CLK_TYPE_FAST: - res_reg = syscon_vbase + U300_SYSCON_RFR; - en_reg = syscon_vbase + U300_SYSCON_CEFR; - break; - case U300_CLK_TYPE_REST: - res_reg = syscon_vbase + U300_SYSCON_RRR; - en_reg = syscon_vbase + U300_SYSCON_CERR; - break; - default: - pr_err("unknown clock type %x specified\n", clk_type); - return; - } - - for (i = 0; i < ARRAY_SIZE(u300_clk_lookup); i++) { - const struct u300_clock *u3clk = &u300_clk_lookup[i]; - - if (u3clk->type == clk_type && u3clk->id == clk_id) - hw = syscon_clk_register(NULL, clk_name, parent_name, - 0, u3clk->hw_ctrld, - res_reg, u3clk->id, - en_reg, u3clk->id, - u3clk->clk_val); - } - - if (!IS_ERR(hw)) { - of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); - - /* - * Some few system clocks - device tree does not - * represent clocks without a corresponding device node. - * for now we add these three clocks here. - */ - if (clk_type == U300_CLK_TYPE_REST && clk_id == 5) - clk_hw_register_clkdev(hw, NULL, "pl172"); - if (clk_type == U300_CLK_TYPE_REST && clk_id == 9) - clk_hw_register_clkdev(hw, NULL, "semi"); - if (clk_type == U300_CLK_TYPE_REST && clk_id == 12) - clk_hw_register_clkdev(hw, NULL, "intcon"); - } -} - -/** - * struct clk_mclk - U300 MCLK clock (MMC/SD clock) - * @hw: corresponding clock hardware entry - * @is_mspro: if this is the memory stick clock rather than MMC/SD - */ -struct clk_mclk { - struct clk_hw hw; - bool is_mspro; -}; - -#define to_mclk(_hw) container_of(_hw, struct clk_mclk, hw) - -static int mclk_clk_prepare(struct clk_hw *hw) -{ - struct clk_mclk *mclk = to_mclk(hw); - u16 val; - - /* The MMC and MSPRO clocks need some special set-up */ - if (!mclk->is_mspro) { - /* Set default MMC clock divisor to 18.9 MHz */ - writew(0x0054U, syscon_vbase + U300_SYSCON_MMF0R); - val = readw(syscon_vbase + U300_SYSCON_MMCR); - /* Disable the MMC feedback clock */ - val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; - /* Disable MSPRO frequency */ - val &= ~U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; - writew(val, syscon_vbase + U300_SYSCON_MMCR); - } else { - val = readw(syscon_vbase + U300_SYSCON_MMCR); - /* Disable the MMC feedback clock */ - val &= ~U300_SYSCON_MMCR_MMC_FB_CLK_SEL_ENABLE; - /* Enable MSPRO frequency */ - val |= U300_SYSCON_MMCR_MSPRO_FREQSEL_ENABLE; - writew(val, syscon_vbase + U300_SYSCON_MMCR); - } - - return 0; -} - -static unsigned long -mclk_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - u16 perf = syscon_get_perf(); - - switch (perf) { - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW_POWER: - /* - * Here, the 208 MHz PLL gets shut down and the always - * on 13 MHz PLL used for RTC etc kicks into use - * instead. - */ - return 13000000; - case U300_SYSCON_CCR_CLKING_PERFORMANCE_LOW: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_INTERMEDIATE: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_HIGH: - case U300_SYSCON_CCR_CLKING_PERFORMANCE_BEST: - { - /* - * This clock is under program control. The register is - * divided in two nybbles, bit 7-4 gives cycles-1 to count - * high, bit 3-0 gives cycles-1 to count low. Distribute - * these with no more than 1 cycle difference between - * low and high and add low and high to get the actual - * divisor. The base PLL is 208 MHz. Writing 0x00 will - * divide by 1 and 1 so the highest frequency possible - * is 104 MHz. - * - * e.g. 0x54 => - * f = 208 / ((5+1) + (4+1)) = 208 / 11 = 18.9 MHz - */ - u16 val = readw(syscon_vbase + U300_SYSCON_MMF0R) & - U300_SYSCON_MMF0R_MASK; - switch (val) { - case 0x0054: - return 18900000; - case 0x0044: - return 20800000; - case 0x0043: - return 23100000; - case 0x0033: - return 26000000; - case 0x0032: - return 29700000; - case 0x0022: - return 34700000; - case 0x0021: - return 41600000; - case 0x0011: - return 52000000; - case 0x0000: - return 104000000; - default: - break; - } - } - default: - break; - } - return parent_rate; -} - -static long -mclk_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - if (rate <= 18900000) - return 18900000; - if (rate <= 20800000) - return 20800000; - if (rate <= 23100000) - return 23100000; - if (rate <= 26000000) - return 26000000; - if (rate <= 29700000) - return 29700000; - if (rate <= 34700000) - return 34700000; - if (rate <= 41600000) - return 41600000; - /* Highest rate */ - return 52000000; -} - -static int mclk_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - u16 val; - u16 reg; - - switch (rate) { - case 18900000: - val = 0x0054; - break; - case 20800000: - val = 0x0044; - break; - case 23100000: - val = 0x0043; - break; - case 26000000: - val = 0x0033; - break; - case 29700000: - val = 0x0032; - break; - case 34700000: - val = 0x0022; - break; - case 41600000: - val = 0x0021; - break; - case 52000000: - val = 0x0011; - break; - case 104000000: - val = 0x0000; - break; - default: - return -EINVAL; - } - - reg = readw(syscon_vbase + U300_SYSCON_MMF0R) & - ~U300_SYSCON_MMF0R_MASK; - writew(reg | val, syscon_vbase + U300_SYSCON_MMF0R); - return 0; -} - -static const struct clk_ops mclk_ops = { - .prepare = mclk_clk_prepare, - .recalc_rate = mclk_clk_recalc_rate, - .round_rate = mclk_clk_round_rate, - .set_rate = mclk_clk_set_rate, -}; - -static struct clk_hw * __init -mclk_clk_register(struct device *dev, const char *name, - const char *parent_name, bool is_mspro) -{ - struct clk_hw *hw; - struct clk_mclk *mclk; - struct clk_init_data init; - int ret; - - mclk = kzalloc(sizeof(*mclk), GFP_KERNEL); - if (!mclk) - return ERR_PTR(-ENOMEM); - - init.name = "mclk"; - init.ops = &mclk_ops; - init.flags = 0; - init.parent_names = (parent_name ? &parent_name : NULL); - init.num_parents = (parent_name ? 1 : 0); - mclk->hw.init = &init; - mclk->is_mspro = is_mspro; - - hw = &mclk->hw; - ret = clk_hw_register(dev, hw); - if (ret) { - kfree(mclk); - hw = ERR_PTR(ret); - } - - return hw; -} - -static void __init of_u300_syscon_mclk_init(struct device_node *np) -{ - struct clk_hw *hw; - const char *clk_name = np->name; - const char *parent_name; - - parent_name = of_clk_get_parent_name(np, 0); - hw = mclk_clk_register(NULL, clk_name, parent_name, false); - if (!IS_ERR(hw)) - of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); -} - -static const struct of_device_id u300_clk_match[] __initconst = { - { - .compatible = "fixed-clock", - .data = of_fixed_clk_setup, - }, - { - .compatible = "fixed-factor-clock", - .data = of_fixed_factor_clk_setup, - }, - { - .compatible = "stericsson,u300-syscon-clk", - .data = of_u300_syscon_clk_init, - }, - { - .compatible = "stericsson,u300-syscon-mclk", - .data = of_u300_syscon_mclk_init, - }, - {} -}; - - -void __init u300_clk_init(void __iomem *base) -{ - u16 val; - - syscon_vbase = base; - - /* Set system to run at PLL208, max performance, a known state. */ - val = readw(syscon_vbase + U300_SYSCON_CCR); - val &= ~U300_SYSCON_CCR_CLKING_PERFORMANCE_MASK; - writew(val, syscon_vbase + U300_SYSCON_CCR); - /* Wait for the PLL208 to lock if not locked in yet */ - while (!(readw(syscon_vbase + U300_SYSCON_CSR) & - U300_SYSCON_CSR_PLL208_LOCK_IND)); - - /* Power management enable */ - val = readw(syscon_vbase + U300_SYSCON_PMCR); - val |= U300_SYSCON_PMCR_PWR_MGNT_ENABLE; - writew(val, syscon_vbase + U300_SYSCON_PMCR); - - of_clk_init(u300_clk_match); -} diff --git a/drivers/clk/imx/clk-imx31.c b/drivers/clk/imx/clk-imx31.c index 7b13fb57d842..c44e18c6f63f 100644 --- a/drivers/clk/imx/clk-imx31.c +++ b/drivers/clk/imx/clk-imx31.c @@ -51,16 +51,6 @@ enum mx31_clks { static struct clk *clk[clk_max]; static struct clk_onecell_data clk_data; -static struct clk ** const uart_clks[] __initconst = { - &clk[ipg], - &clk[uart1_gate], - &clk[uart2_gate], - &clk[uart3_gate], - &clk[uart4_gate], - &clk[uart5_gate], - NULL -}; - static void __init _mx31_clocks_init(void __iomem *base, unsigned long fref) { clk[dummy] = imx_clk_fixed("dummy", 0); diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c index b2ff187cedab..521d6136d22c 100644 --- a/drivers/clk/imx/clk-imx6q.c +++ b/drivers/clk/imx/clk-imx6q.c @@ -338,10 +338,10 @@ static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base) of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]); for (i = 0; i < 2; i++) { - /* Warn if a glitch might have been introduced already */ + /* Print a notice if a glitch might have been introduced already */ if (sel[i][0] != 3) { - pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n", - i, sel[i][0]); + pr_notice("ccm: possible glitch: ldb_di%d_sel already changed from reset value: %d\n", + i, sel[i][0]); } if (sel[i][0] == sel[i][3]) diff --git a/drivers/clk/imx/clk-imx6sl.c b/drivers/clk/imx/clk-imx6sl.c index 2f9361946a0e..29eab05c9068 100644 --- a/drivers/clk/imx/clk-imx6sl.c +++ b/drivers/clk/imx/clk-imx6sl.c @@ -6,6 +6,7 @@ #include <linux/bits.h> #include <linux/clk.h> #include <linux/clkdev.h> +#include <linux/clk/imx.h> #include <linux/err.h> #include <linux/of.h> #include <linux/of_address.h> diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c index 7c905861af5d..6a01eec36dd0 100644 --- a/drivers/clk/imx/clk-imx8mm.c +++ b/drivers/clk/imx/clk-imx8mm.c @@ -288,6 +288,11 @@ static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "dummy", " static const char *imx8mm_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m", "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "osc_32k", }; +static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out", + "dummy", "dummy", "gpu_pll_out", "vpu_pll_out", + "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3", + "dummy", "dummy", "osc_24m", "dummy", "osc_32k"}; + static struct clk_hw_onecell_data *clk_hw_data; static struct clk_hw **hws; @@ -410,6 +415,13 @@ static int imx8mm_clocks_probe(struct platform_device *pdev) hws[IMX8MM_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); hws[IMX8MM_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); + hws[IMX8MM_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); + hws[IMX8MM_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4); + hws[IMX8MM_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8); + hws[IMX8MM_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); + hws[IMX8MM_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4); + hws[IMX8MM_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24); + np = dev->of_node; base = devm_platform_ioremap_resource(pdev, 0); if (WARN_ON(IS_ERR(base))) diff --git a/drivers/clk/imx/clk-imx8mn.c b/drivers/clk/imx/clk-imx8mn.c index 3c21db942d5b..324c5fd0aa04 100644 --- a/drivers/clk/imx/clk-imx8mn.c +++ b/drivers/clk/imx/clk-imx8mn.c @@ -281,6 +281,11 @@ static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sy "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", "osc_32k", }; +static const char * const clkout_sels[] = {"audio_pll1_out", "audio_pll2_out", "video_pll1_out", + "dummy", "dummy", "gpu_pll_out", "dummy", + "arm_pll_out", "sys_pll1", "sys_pll2", "sys_pll3", + "dummy", "dummy", "osc_24m", "dummy", "osc_32k"}; + static struct clk_hw_onecell_data *clk_hw_data; static struct clk_hw **hws; @@ -405,6 +410,13 @@ static int imx8mn_clocks_probe(struct platform_device *pdev) hws[IMX8MN_SYS_PLL2_500M] = imx_clk_hw_fixed_factor("sys_pll2_500m", "sys_pll2_500m_cg", 1, 2); hws[IMX8MN_SYS_PLL2_1000M] = imx_clk_hw_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1); + hws[IMX8MN_CLK_CLKOUT1_SEL] = imx_clk_hw_mux("clkout1_sel", base + 0x128, 4, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); + hws[IMX8MN_CLK_CLKOUT1_DIV] = imx_clk_hw_divider("clkout1_div", "clkout1_sel", base + 0x128, 0, 4); + hws[IMX8MN_CLK_CLKOUT1] = imx_clk_hw_gate("clkout1", "clkout1_div", base + 0x128, 8); + hws[IMX8MN_CLK_CLKOUT2_SEL] = imx_clk_hw_mux("clkout2_sel", base + 0x128, 20, 4, clkout_sels, ARRAY_SIZE(clkout_sels)); + hws[IMX8MN_CLK_CLKOUT2_DIV] = imx_clk_hw_divider("clkout2_div", "clkout2_sel", base + 0x128, 16, 4); + hws[IMX8MN_CLK_CLKOUT2] = imx_clk_hw_gate("clkout2", "clkout2_div", base + 0x128, 24); + np = dev->of_node; base = devm_platform_ioremap_resource(pdev, 0); if (WARN_ON(IS_ERR(base))) { diff --git a/drivers/clk/imx/clk-imx8mq.c b/drivers/clk/imx/clk-imx8mq.c index 779ea69e639c..4dd4ae9d022b 100644 --- a/drivers/clk/imx/clk-imx8mq.c +++ b/drivers/clk/imx/clk-imx8mq.c @@ -270,6 +270,14 @@ static const char * const imx8mq_clko1_sels[] = {"osc_25m", "sys1_pll_800m", "os static const char * const imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m", "sys3_pll_out", "audio_pll1_out", "video_pll1_out", "ckil", }; +static const char * const pllout_monitor_sels[] = {"osc_25m", "osc_27m", "dummy", "dummy", "ckil", + "audio_pll1_out_monitor", "audio_pll2_out_monitor", + "video_pll1_out_monitor", "gpu_pll_out_monitor", + "vpu_pll_out_monitor", "arm_pll_out_monitor", + "sys_pll1_out_monitor", "sys_pll2_out_monitor", + "sys_pll3_out_monitor", "dram_pll_out_monitor", + "video_pll2_out_monitor", }; + static struct clk_hw_onecell_data *clk_hw_data; static struct clk_hw **hws; @@ -399,6 +407,20 @@ static int imx8mq_clocks_probe(struct platform_device *pdev) hws[IMX8MQ_SYS2_PLL_500M] = imx_clk_hw_fixed_factor("sys2_pll_500m", "sys2_pll_500m_cg", 1, 2); hws[IMX8MQ_SYS2_PLL_1000M] = imx_clk_hw_fixed_factor("sys2_pll_1000m", "sys2_pll_1000m_cg", 1, 1); + hws[IMX8MQ_CLK_MON_AUDIO_PLL1_DIV] = imx_clk_hw_divider("audio_pll1_out_monitor", "audio_pll1_bypass", base + 0x78, 0, 3); + hws[IMX8MQ_CLK_MON_AUDIO_PLL2_DIV] = imx_clk_hw_divider("audio_pll2_out_monitor", "audio_pll2_bypass", base + 0x78, 4, 3); + hws[IMX8MQ_CLK_MON_VIDEO_PLL1_DIV] = imx_clk_hw_divider("video_pll1_out_monitor", "video_pll1_bypass", base + 0x78, 8, 3); + hws[IMX8MQ_CLK_MON_GPU_PLL_DIV] = imx_clk_hw_divider("gpu_pll_out_monitor", "gpu_pll_bypass", base + 0x78, 12, 3); + hws[IMX8MQ_CLK_MON_VPU_PLL_DIV] = imx_clk_hw_divider("vpu_pll_out_monitor", "vpu_pll_bypass", base + 0x78, 16, 3); + hws[IMX8MQ_CLK_MON_ARM_PLL_DIV] = imx_clk_hw_divider("arm_pll_out_monitor", "arm_pll_bypass", base + 0x78, 20, 3); + hws[IMX8MQ_CLK_MON_SYS_PLL1_DIV] = imx_clk_hw_divider("sys_pll1_out_monitor", "sys1_pll_out", base + 0x7c, 0, 3); + hws[IMX8MQ_CLK_MON_SYS_PLL2_DIV] = imx_clk_hw_divider("sys_pll2_out_monitor", "sys2_pll_out", base + 0x7c, 4, 3); + hws[IMX8MQ_CLK_MON_SYS_PLL3_DIV] = imx_clk_hw_divider("sys_pll3_out_monitor", "sys3_pll_out", base + 0x7c, 8, 3); + hws[IMX8MQ_CLK_MON_DRAM_PLL_DIV] = imx_clk_hw_divider("dram_pll_out_monitor", "dram_pll_out", base + 0x7c, 12, 3); + hws[IMX8MQ_CLK_MON_VIDEO_PLL2_DIV] = imx_clk_hw_divider("video_pll2_out_monitor", "video2_pll_out", base + 0x7c, 16, 3); + hws[IMX8MQ_CLK_MON_SEL] = imx_clk_hw_mux("pllout_monitor_sel", base + 0x74, 0, 4, pllout_monitor_sels, ARRAY_SIZE(pllout_monitor_sels)); + hws[IMX8MQ_CLK_MON_CLK2_OUT] = imx_clk_hw_gate("pllout_monitor_clk2", "pllout_monitor_sel", base + 0x74, 4); + np = dev->of_node; base = devm_platform_ioremap_resource(pdev, 0); if (WARN_ON(IS_ERR(base))) diff --git a/drivers/clk/imx/clk-imx8qxp.c b/drivers/clk/imx/clk-imx8qxp.c index 5b3d4ede7c7c..fbf1170c09ed 100644 --- a/drivers/clk/imx/clk-imx8qxp.c +++ b/drivers/clk/imx/clk-imx8qxp.c @@ -17,6 +17,14 @@ #include <dt-bindings/clock/imx8-clock.h> #include <dt-bindings/firmware/imx/rsrc.h> +static const char *dc0_sels[] = { + "clk_dummy", + "clk_dummy", + "dc0_pll0_clk", + "dc0_pll1_clk", + "dc0_bypass0_clk", +}; + static int imx8qxp_clk_probe(struct platform_device *pdev) { struct device_node *ccm_node = pdev->dev.of_node; @@ -115,12 +123,26 @@ static int imx8qxp_clk_probe(struct platform_device *pdev) clks[IMX_CONN_USB2_LPM_CLK] = imx_clk_scu("usb3_lpm_div", IMX_SC_R_USB_2, IMX_SC_PM_CLK_MISC, clk_cells); /* Display controller SS */ - clks[IMX_DC0_DISP0_CLK] = imx_clk_scu("dc0_disp0_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells); - clks[IMX_DC0_DISP1_CLK] = imx_clk_scu("dc0_disp1_clk", IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells); + clks[IMX_DC0_DISP0_CLK] = imx_clk_scu2("dc0_disp0_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC0, clk_cells); + clks[IMX_DC0_DISP1_CLK] = imx_clk_scu2("dc0_disp1_clk", dc0_sels, ARRAY_SIZE(dc0_sels), IMX_SC_R_DC_0, IMX_SC_PM_CLK_MISC1, clk_cells); + clks[IMX_DC0_PLL0_CLK] = imx_clk_scu("dc0_pll0_clk", IMX_SC_R_DC_0_PLL_0, IMX_SC_PM_CLK_PLL, clk_cells); + clks[IMX_DC0_PLL1_CLK] = imx_clk_scu("dc0_pll1_clk", IMX_SC_R_DC_0_PLL_1, IMX_SC_PM_CLK_PLL, clk_cells); + clks[IMX_DC0_BYPASS0_CLK] = imx_clk_scu("dc0_bypass0_clk", IMX_SC_R_DC_0_VIDEO0, IMX_SC_PM_CLK_BYPASS, clk_cells); + clks[IMX_DC0_BYPASS1_CLK] = imx_clk_scu("dc0_bypass1_clk", IMX_SC_R_DC_0_VIDEO1, IMX_SC_PM_CLK_BYPASS, clk_cells); /* MIPI-LVDS SS */ + clks[IMX_MIPI0_LVDS_PIXEL_CLK] = imx_clk_scu("mipi0_lvds_pixel_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI0_LVDS_BYPASS_CLK] = imx_clk_scu("mipi0_lvds_bypass_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_BYPASS, clk_cells); + clks[IMX_MIPI0_LVDS_PHY_CLK] = imx_clk_scu("mipi0_lvds_phy_clk", IMX_SC_R_LVDS_0, IMX_SC_PM_CLK_MISC3, clk_cells); clks[IMX_MIPI0_I2C0_CLK] = imx_clk_scu("mipi0_i2c0_clk", IMX_SC_R_MIPI_0_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); clks[IMX_MIPI0_I2C1_CLK] = imx_clk_scu("mipi0_i2c1_clk", IMX_SC_R_MIPI_0_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI0_PWM0_CLK] = imx_clk_scu("mipi0_pwm0_clk", IMX_SC_R_MIPI_0_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); + clks[IMX_MIPI1_LVDS_PIXEL_CLK] = imx_clk_scu("mipi1_lvds_pixel_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI1_LVDS_BYPASS_CLK] = imx_clk_scu("mipi1_lvds_bypass_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_BYPASS, clk_cells); + clks[IMX_MIPI1_LVDS_PHY_CLK] = imx_clk_scu("mipi1_lvds_phy_clk", IMX_SC_R_LVDS_1, IMX_SC_PM_CLK_MISC3, clk_cells); + clks[IMX_MIPI1_I2C0_CLK] = imx_clk_scu("mipi1_i2c0_clk", IMX_SC_R_MIPI_1_I2C_0, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI1_I2C1_CLK] = imx_clk_scu("mipi1_i2c1_clk", IMX_SC_R_MIPI_1_I2C_1, IMX_SC_PM_CLK_MISC2, clk_cells); + clks[IMX_MIPI1_PWM0_CLK] = imx_clk_scu("mipi1_pwm0_clk", IMX_SC_R_MIPI_1_PWM_0, IMX_SC_PM_CLK_PER, clk_cells); /* MIPI CSI SS */ clks[IMX_CSI0_CORE_CLK] = imx_clk_scu("mipi_csi0_core_clk", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, clk_cells); diff --git a/drivers/clk/mediatek/Kconfig b/drivers/clk/mediatek/Kconfig index ce8475098b31..886e2d9fced5 100644 --- a/drivers/clk/mediatek/Kconfig +++ b/drivers/clk/mediatek/Kconfig @@ -426,66 +426,77 @@ config COMMON_CLK_MT8183 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. diff --git a/drivers/clk/mediatek/clk-mux.c b/drivers/clk/mediatek/clk-mux.c index dcc1352bf13c..b0c61709bacc 100644 --- a/drivers/clk/mediatek/clk-mux.c +++ b/drivers/clk/mediatek/clk-mux.c @@ -17,29 +17,36 @@ 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(struct clk_hw *hw) +static int mtk_clk_mux_enable_setclr(struct clk_hw *hw) { struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); - u32 mask = BIT(mux->data->gate_shift); - - return regmap_update_bits(mux->regmap, mux->data->mux_ofs, - mask, ~mask); -} + unsigned long flags = 0; -static void mtk_clk_mux_disable(struct clk_hw *hw) -{ - struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); - u32 mask = BIT(mux->data->gate_shift); + if (mux->lock) + spin_lock_irqsave(mux->lock, flags); + else + __acquire(mux->lock); - regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask, mask); -} + 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; + } -static int mtk_clk_mux_enable_setclr(struct clk_hw *hw) -{ - struct mtk_clk_mux *mux = to_mtk_clk_mux(hw); + if (mux->lock) + spin_unlock_irqrestore(mux->lock, flags); + else + __release(mux->lock); - return regmap_write(mux->regmap, mux->data->clr_ofs, - BIT(mux->data->gate_shift)); + return 0; } static void mtk_clk_mux_disable_setclr(struct clk_hw *hw) @@ -72,28 +79,6 @@ static u8 mtk_clk_mux_get_parent(struct clk_hw *hw) return val; } -static int mtk_clk_mux_set_parent_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); - unsigned long flags = 0; - - if (mux->lock) - spin_lock_irqsave(mux->lock, flags); - else - __acquire(mux->lock); - - regmap_update_bits(mux->regmap, mux->data->mux_ofs, mask, - index << mux->data->mux_shift); - - if (mux->lock) - spin_unlock_irqrestore(mux->lock, flags); - else - __release(mux->lock); - - return 0; -} - 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); @@ -116,9 +101,11 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index) regmap_write(mux->regmap, mux->data->set_ofs, index << mux->data->mux_shift); - if (mux->data->upd_shift >= 0) + 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) @@ -129,25 +116,7 @@ static int mtk_clk_mux_set_parent_setclr_lock(struct clk_hw *hw, u8 index) return 0; } -const struct clk_ops mtk_mux_ops = { - .get_parent = mtk_clk_mux_get_parent, - .set_parent = mtk_clk_mux_set_parent_lock, -}; - -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, -}; - -const struct clk_ops mtk_mux_gate_ops = { - .enable = mtk_clk_mux_enable, - .disable = mtk_clk_mux_disable, - .is_enabled = mtk_clk_mux_is_enabled, - .get_parent = mtk_clk_mux_get_parent, - .set_parent = mtk_clk_mux_set_parent_lock, -}; - -const struct clk_ops mtk_mux_gate_clr_set_upd_ops = { +static const struct clk_ops mtk_mux_ops = { .enable = mtk_clk_mux_enable_setclr, .disable = mtk_clk_mux_disable_setclr, .is_enabled = mtk_clk_mux_is_enabled, @@ -171,7 +140,7 @@ static struct clk *mtk_clk_register_mux(const struct mtk_mux *mux, init.flags = mux->flags | CLK_SET_RATE_PARENT; init.parent_names = mux->parent_names; init.num_parents = mux->num_parents; - init.ops = mux->ops; + init.ops = &mtk_mux_ops; clk_mux->regmap = regmap; clk_mux->data = mux; diff --git a/drivers/clk/mediatek/clk-mux.h b/drivers/clk/mediatek/clk-mux.h index 8e2f927dd2ff..f1946161ade1 100644 --- a/drivers/clk/mediatek/clk-mux.h +++ b/drivers/clk/mediatek/clk-mux.h @@ -14,6 +14,7 @@ struct mtk_clk_mux { struct regmap *regmap; const struct mtk_mux *data; spinlock_t *lock; + bool reparent; }; struct mtk_mux { @@ -32,19 +33,12 @@ struct mtk_mux { u8 gate_shift; s8 upd_shift; - const struct clk_ops *ops; - signed char num_parents; }; -extern const struct clk_ops mtk_mux_ops; -extern const struct clk_ops mtk_mux_clr_set_upd_ops; -extern const struct clk_ops mtk_mux_gate_ops; -extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; - #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) { \ + _gate, _upd_ofs, _upd, _flags) { \ .id = _id, \ .name = _name, \ .mux_ofs = _mux_ofs, \ @@ -58,7 +52,6 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; .parent_names = _parents, \ .num_parents = ARRAY_SIZE(_parents), \ .flags = _flags, \ - .ops = &_ops, \ } #define MUX_GATE_CLR_SET_UPD_FLAGS(_id, _name, _parents, _mux_ofs, \ @@ -66,8 +59,7 @@ extern const struct clk_ops mtk_mux_gate_clr_set_upd_ops; _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) + _gate, _upd_ofs, _upd, _flags) \ #define MUX_GATE_CLR_SET_UPD(_id, _name, _parents, _mux_ofs, \ _mux_set_ofs, _mux_clr_ofs, _shift, _width, \ diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 0e44695b8772..2ad3801398dc 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -1879,7 +1879,6 @@ static MESON_GATE(axg_mmc_pclk, HHI_GCLK_MPEG2, 11); static MESON_GATE(axg_vpu_intr, HHI_GCLK_MPEG2, 25); static MESON_GATE(axg_sec_ahb_ahb3_bridge, HHI_GCLK_MPEG2, 26); static MESON_GATE(axg_gic, HHI_GCLK_MPEG2, 30); -static MESON_GATE(axg_mipi_enable, HHI_MIPI_CNTL0, 29); /* Always On (AO) domain gates */ @@ -1974,7 +1973,6 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { [CLKID_PCIE_REF] = &axg_pcie_ref.hw, [CLKID_PCIE_CML_EN0] = &axg_pcie_cml_en0.hw, [CLKID_PCIE_CML_EN1] = &axg_pcie_cml_en1.hw, - [CLKID_MIPI_ENABLE] = &axg_mipi_enable.hw, [CLKID_GEN_CLK_SEL] = &axg_gen_clk_sel.hw, [CLKID_GEN_CLK_DIV] = &axg_gen_clk_div.hw, [CLKID_GEN_CLK] = &axg_gen_clk.hw, @@ -2115,7 +2113,6 @@ static struct clk_regmap *const axg_clk_regmaps[] = { &axg_pcie_ref, &axg_pcie_cml_en0, &axg_pcie_cml_en1, - &axg_mipi_enable, &axg_gen_clk_sel, &axg_gen_clk_div, &axg_gen_clk, diff --git a/drivers/clk/meson/axg.h b/drivers/clk/meson/axg.h index 481b307ea3cb..23ea87964af2 100644 --- a/drivers/clk/meson/axg.h +++ b/drivers/clk/meson/axg.h @@ -16,7 +16,6 @@ * Register offsets from the data sheet must be multiplied by 4 before * adding them to the base address to get the right value. */ -#define HHI_MIPI_CNTL0 0x00 #define HHI_GP0_PLL_CNTL 0x40 #define HHI_GP0_PLL_CNTL2 0x44 #define HHI_GP0_PLL_CNTL3 0x48 diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c index b17a13e9337c..49f27fe53213 100644 --- a/drivers/clk/meson/clk-pll.c +++ b/drivers/clk/meson/clk-pll.c @@ -365,13 +365,14 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, { struct clk_regmap *clk = to_clk_regmap(hw); struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); - unsigned int enabled, m, n, frac = 0, ret; + unsigned int enabled, m, n, frac = 0; unsigned long old_rate; + int ret; if (parent_rate == 0 || rate == 0) return -EINVAL; - old_rate = rate; + old_rate = clk_hw_get_rate(hw); ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll); if (ret) @@ -393,7 +394,8 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, if (!enabled) return 0; - if (meson_clk_pll_enable(hw)) { + ret = meson_clk_pll_enable(hw); + if (ret) { pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", __func__, old_rate); /* @@ -405,7 +407,7 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, meson_clk_pll_set_rate(hw, old_rate, parent_rate); } - return 0; + return ret; } /* diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 862f0756b50f..a844d35b553a 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -52,15 +52,6 @@ static const struct pll_params_table sys_pll_params_table[] = { { /* sentinel */ }, }; -static struct clk_fixed_rate meson8b_xtal = { - .fixed_rate = 24000000, - .hw.init = &(struct clk_init_data){ - .name = "xtal", - .num_parents = 0, - .ops = &clk_fixed_rate_ops, - }, -}; - static struct clk_regmap meson8b_fixed_pll_dco = { .data = &(struct meson_clk_pll_data){ .en = { @@ -2715,7 +2706,6 @@ static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3); static struct clk_hw_onecell_data meson8_hw_onecell_data = { .hws = { - [CLKID_XTAL] = &meson8b_xtal.hw, [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, [CLKID_PLL_VID] = &meson8b_vid_pll.hw, [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, @@ -2922,7 +2912,6 @@ static struct clk_hw_onecell_data meson8_hw_onecell_data = { static struct clk_hw_onecell_data meson8b_hw_onecell_data = { .hws = { - [CLKID_XTAL] = &meson8b_xtal.hw, [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, [CLKID_PLL_VID] = &meson8b_vid_pll.hw, [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, @@ -3140,7 +3129,6 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = { static struct clk_hw_onecell_data meson8m2_hw_onecell_data = { .hws = { - [CLKID_XTAL] = &meson8b_xtal.hw, [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw, [CLKID_PLL_VID] = &meson8b_vid_pll.hw, [CLKID_PLL_SYS] = &meson8b_sys_pll.hw, @@ -3725,36 +3713,19 @@ static struct meson8b_nb_data meson8b_cpu_nb_data = { .nb.notifier_call = meson8b_cpu_clk_notifier_cb, }; -static const struct regmap_config clkc_regmap_config = { - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, -}; - static void __init meson8b_clkc_init_common(struct device_node *np, struct clk_hw_onecell_data *clk_hw_onecell_data) { struct meson8b_clk_reset *rstc; const char *notifier_clk_name; struct clk *notifier_clk; - void __iomem *clk_base; struct regmap *map; int i, ret; map = syscon_node_to_regmap(of_get_parent(np)); if (IS_ERR(map)) { - pr_info("failed to get HHI regmap - Trying obsolete regs\n"); - - /* Generic clocks, PLLs and some of the reset-bits */ - clk_base = of_iomap(np, 1); - if (!clk_base) { - pr_err("%s: Unable to map clk base\n", __func__); - return; - } - - map = regmap_init_mmio(NULL, clk_base, &clkc_regmap_config); - if (IS_ERR(map)) - return; + pr_err("failed to get HHI regmap - Trying obsolete regs\n"); + return; } rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); @@ -3778,16 +3749,10 @@ static void __init meson8b_clkc_init_common(struct device_node *np, meson8b_clk_regmaps[i]->map = map; /* - * always skip CLKID_UNUSED and also skip XTAL if the .dtb provides the - * XTAL clock as input. + * register all clks and start with the first used ID (which is + * CLKID_PLL_FIXED) */ - if (!IS_ERR(of_clk_get_by_name(np, "xtal"))) - i = CLKID_PLL_FIXED; - else - i = CLKID_XTAL; - - /* register all clks */ - for (; i < CLK_NR_CLKS; i++) { + for (i = CLKID_PLL_FIXED; i < CLK_NR_CLKS; i++) { /* array might be sparse */ if (!clk_hw_onecell_data->hws[i]) continue; diff --git a/drivers/clk/renesas/Kconfig b/drivers/clk/renesas/Kconfig index 18915d668a30..607e64a17d72 100644 --- a/drivers/clk/renesas/Kconfig +++ b/drivers/clk/renesas/Kconfig @@ -148,6 +148,7 @@ config CLK_R8A77995 config CLK_R8A779A0 bool "R-Car V3U clock support" if COMPILE_TEST + select CLK_RCAR_CPG_LIB select CLK_RENESAS_CPG_MSSR config CLK_R9A06G032 @@ -162,12 +163,16 @@ config CLK_SH73A0 # Family +config CLK_RCAR_CPG_LIB + bool "CPG/MSSR library functions" if COMPILE_TEST + config CLK_RCAR_GEN2_CPG bool "R-Car Gen2 CPG clock support" if COMPILE_TEST select CLK_RENESAS_CPG_MSSR config CLK_RCAR_GEN3_CPG bool "R-Car Gen3 and RZ/G2 CPG clock support" if COMPILE_TEST + select CLK_RCAR_CPG_LIB select CLK_RENESAS_CPG_MSSR config CLK_RCAR_USB2_CLOCK_SEL diff --git a/drivers/clk/renesas/Makefile b/drivers/clk/renesas/Makefile index c803912ef2ce..ef0d2bba92bf 100644 --- a/drivers/clk/renesas/Makefile +++ b/drivers/clk/renesas/Makefile @@ -32,6 +32,7 @@ obj-$(CONFIG_CLK_R9A06G032) += r9a06g032-clocks.o obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o # Family +obj-$(CONFIG_CLK_RCAR_CPG_LIB) += rcar-cpg-lib.o obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o diff --git a/drivers/clk/renesas/r8a7796-cpg-mssr.c b/drivers/clk/renesas/r8a7796-cpg-mssr.c index 2cd6e3876fbd..41593c126faf 100644 --- a/drivers/clk/renesas/r8a7796-cpg-mssr.c +++ b/drivers/clk/renesas/r8a7796-cpg-mssr.c @@ -128,6 +128,11 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = { static struct mssr_mod_clk r8a7796_mod_clks[] __initdata = { DEF_MOD("fdp1-0", 119, R8A7796_CLK_S0D1), + DEF_MOD("tmu4", 121, R8A7796_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A7796_CLK_S3D2), + DEF_MOD("tmu2", 123, R8A7796_CLK_S3D2), + DEF_MOD("tmu1", 124, R8A7796_CLK_S3D2), + DEF_MOD("tmu0", 125, R8A7796_CLK_CP), DEF_MOD("scif5", 202, R8A7796_CLK_S3D4), DEF_MOD("scif4", 203, R8A7796_CLK_S3D4), DEF_MOD("scif3", 204, R8A7796_CLK_S3D4), diff --git a/drivers/clk/renesas/r8a77965-cpg-mssr.c b/drivers/clk/renesas/r8a77965-cpg-mssr.c index 2b55a06ac5cf..46a157732759 100644 --- a/drivers/clk/renesas/r8a77965-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77965-cpg-mssr.c @@ -123,6 +123,11 @@ static const struct cpg_core_clk r8a77965_core_clks[] __initconst = { static const struct mssr_mod_clk r8a77965_mod_clks[] __initconst = { DEF_MOD("fdp1-0", 119, R8A77965_CLK_S0D1), + DEF_MOD("tmu4", 121, R8A77965_CLK_S0D6), + DEF_MOD("tmu3", 122, R8A77965_CLK_S3D2), + DEF_MOD("tmu2", 123, R8A77965_CLK_S3D2), + DEF_MOD("tmu1", 124, R8A77965_CLK_S3D2), + DEF_MOD("tmu0", 125, R8A77965_CLK_CP), DEF_MOD("scif5", 202, R8A77965_CLK_S3D4), DEF_MOD("scif4", 203, R8A77965_CLK_S3D4), DEF_MOD("scif3", 204, R8A77965_CLK_S3D4), diff --git a/drivers/clk/renesas/r8a77990-cpg-mssr.c b/drivers/clk/renesas/r8a77990-cpg-mssr.c index 2b97ab61d044..2d172f80b34c 100644 --- a/drivers/clk/renesas/r8a77990-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77990-cpg-mssr.c @@ -124,6 +124,11 @@ static const struct cpg_core_clk r8a77990_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a77990_mod_clks[] __initconst = { + DEF_MOD("tmu4", 121, R8A77990_CLK_S0D6C), + DEF_MOD("tmu3", 122, R8A77990_CLK_S3D2C), + DEF_MOD("tmu2", 123, R8A77990_CLK_S3D2C), + DEF_MOD("tmu1", 124, R8A77990_CLK_S3D2C), + DEF_MOD("tmu0", 125, R8A77990_CLK_CP), DEF_MOD("scif5", 202, R8A77990_CLK_S3D4C), DEF_MOD("scif4", 203, R8A77990_CLK_S3D4C), DEF_MOD("scif3", 204, R8A77990_CLK_S3D4C), diff --git a/drivers/clk/renesas/r8a77995-cpg-mssr.c b/drivers/clk/renesas/r8a77995-cpg-mssr.c index 5b4691117b47..9cfd00cf4e69 100644 --- a/drivers/clk/renesas/r8a77995-cpg-mssr.c +++ b/drivers/clk/renesas/r8a77995-cpg-mssr.c @@ -111,6 +111,11 @@ static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { + DEF_MOD("tmu4", 121, R8A77995_CLK_S1D4C), + DEF_MOD("tmu3", 122, R8A77995_CLK_S3D2C), + DEF_MOD("tmu2", 123, R8A77995_CLK_S3D2C), + DEF_MOD("tmu1", 124, R8A77995_CLK_S3D2C), + DEF_MOD("tmu0", 125, R8A77995_CLK_CP), DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C), DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C), DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C), diff --git a/drivers/clk/renesas/r8a779a0-cpg-mssr.c b/drivers/clk/renesas/r8a779a0-cpg-mssr.c index aa5389b04d74..f23fe9d5e5e1 100644 --- a/drivers/clk/renesas/r8a779a0-cpg-mssr.c +++ b/drivers/clk/renesas/r8a779a0-cpg-mssr.c @@ -25,6 +25,7 @@ #include <dt-bindings/clock/r8a779a0-cpg-mssr.h> +#include "rcar-cpg-lib.h" #include "renesas-cpg-mssr.h" enum rcar_r8a779a0_clk_types { @@ -32,6 +33,7 @@ enum rcar_r8a779a0_clk_types { CLK_TYPE_R8A779A0_PLL1, CLK_TYPE_R8A779A0_PLL2X_3X, /* PLL[23][01] */ CLK_TYPE_R8A779A0_PLL5, + CLK_TYPE_R8A779A0_SD, CLK_TYPE_R8A779A0_MDSEL, /* Select parent/divider using mode pin */ CLK_TYPE_R8A779A0_OSC, /* OSC EXTAL predivider and fixed divider */ }; @@ -69,7 +71,6 @@ enum clk_ids { CLK_PLL5_DIV2, CLK_PLL5_DIV4, CLK_S1, - CLK_S2, CLK_S3, CLK_SDSRC, CLK_RPCSRC, @@ -83,6 +84,9 @@ enum clk_ids { DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_PLL2X_3X, CLK_MAIN, \ .offset = _offset) +#define DEF_SD(_name, _id, _parent, _offset) \ + DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_SD, _parent, .offset = _offset) + #define DEF_MDSEL(_name, _id, _md, _parent0, _div0, _parent1, _div1) \ DEF_BASE(_name, _id, CLK_TYPE_R8A779A0_MDSEL, \ (_parent0) << 16 | (_parent1), \ @@ -114,6 +118,7 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED(".pll5_div4", CLK_PLL5_DIV4, CLK_PLL5_DIV2, 2, 1), DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 2, 1), DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 4, 1), + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL5_DIV4, 1, 1), DEF_RATE(".oco", CLK_OCO, 32768), /* Core Clock Outputs */ @@ -137,7 +142,10 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { DEF_FIXED("icu", R8A779A0_CLK_ICU, CLK_PLL5_DIV4, 2, 1), DEF_FIXED("icud2", R8A779A0_CLK_ICUD2, CLK_PLL5_DIV4, 4, 1), DEF_FIXED("vcbus", R8A779A0_CLK_VCBUS, CLK_PLL5_DIV4, 1, 1), - DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_MAIN, 2, 1), + DEF_FIXED("cbfusa", R8A779A0_CLK_CBFUSA, CLK_EXTAL, 2, 1), + DEF_FIXED("cp", R8A779A0_CLK_CP, CLK_EXTAL, 2, 1), + + DEF_SD("sd0", R8A779A0_CLK_SD0, CLK_SDSRC, 0x870), DEF_DIV6P1("mso", R8A779A0_CLK_MSO, CLK_PLL5_DIV4, 0x87c), DEF_DIV6P1("canfd", R8A779A0_CLK_CANFD, CLK_PLL5_DIV4, 0x878), @@ -148,14 +156,42 @@ static const struct cpg_core_clk r8a779a0_core_clks[] __initconst = { }; static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { + DEF_MOD("avb0", 211, R8A779A0_CLK_S3D2), + DEF_MOD("avb1", 212, R8A779A0_CLK_S3D2), + DEF_MOD("avb2", 213, R8A779A0_CLK_S3D2), + DEF_MOD("avb3", 214, R8A779A0_CLK_S3D2), + DEF_MOD("avb4", 215, R8A779A0_CLK_S3D2), + DEF_MOD("avb5", 216, R8A779A0_CLK_S3D2), DEF_MOD("csi40", 331, R8A779A0_CLK_CSI0), DEF_MOD("csi41", 400, R8A779A0_CLK_CSI0), DEF_MOD("csi42", 401, R8A779A0_CLK_CSI0), DEF_MOD("csi43", 402, R8A779A0_CLK_CSI0), + DEF_MOD("fcpvd0", 508, R8A779A0_CLK_S3D1), + DEF_MOD("fcpvd1", 509, R8A779A0_CLK_S3D1), + DEF_MOD("hscif0", 514, R8A779A0_CLK_S1D2), + DEF_MOD("hscif1", 515, R8A779A0_CLK_S1D2), + DEF_MOD("hscif2", 516, R8A779A0_CLK_S1D2), + DEF_MOD("hscif3", 517, R8A779A0_CLK_S1D2), + DEF_MOD("i2c0", 518, R8A779A0_CLK_S1D4), + DEF_MOD("i2c1", 519, R8A779A0_CLK_S1D4), + DEF_MOD("i2c2", 520, R8A779A0_CLK_S1D4), + DEF_MOD("i2c3", 521, R8A779A0_CLK_S1D4), + DEF_MOD("i2c4", 522, R8A779A0_CLK_S1D4), + DEF_MOD("i2c5", 523, R8A779A0_CLK_S1D4), + DEF_MOD("i2c6", 524, R8A779A0_CLK_S1D4), + DEF_MOD("msi0", 618, R8A779A0_CLK_MSO), + DEF_MOD("msi1", 619, R8A779A0_CLK_MSO), + DEF_MOD("msi2", 620, R8A779A0_CLK_MSO), + DEF_MOD("msi3", 621, R8A779A0_CLK_MSO), + DEF_MOD("msi4", 622, R8A779A0_CLK_MSO), + DEF_MOD("msi5", 623, R8A779A0_CLK_MSO), DEF_MOD("scif0", 702, R8A779A0_CLK_S1D8), DEF_MOD("scif1", 703, R8A779A0_CLK_S1D8), DEF_MOD("scif3", 704, R8A779A0_CLK_S1D8), DEF_MOD("scif4", 705, R8A779A0_CLK_S1D8), + DEF_MOD("sdhi0", 706, R8A779A0_CLK_SD0), + DEF_MOD("sydm1", 709, R8A779A0_CLK_S1D2), + DEF_MOD("sydm2", 710, R8A779A0_CLK_S1D2), DEF_MOD("vin00", 730, R8A779A0_CLK_S1D1), DEF_MOD("vin01", 731, R8A779A0_CLK_S1D1), DEF_MOD("vin02", 800, R8A779A0_CLK_S1D1), @@ -188,10 +224,19 @@ static const struct mssr_mod_clk r8a779a0_mod_clks[] __initconst = { DEF_MOD("vin35", 827, R8A779A0_CLK_S1D1), DEF_MOD("vin36", 828, R8A779A0_CLK_S1D1), DEF_MOD("vin37", 829, R8A779A0_CLK_S1D1), + DEF_MOD("vspd0", 830, R8A779A0_CLK_S3D1), + DEF_MOD("vspd1", 831, R8A779A0_CLK_S3D1), + DEF_MOD("rwdt", 907, R8A779A0_CLK_R), + DEF_MOD("pfc0", 915, R8A779A0_CLK_CP), + DEF_MOD("pfc1", 916, R8A779A0_CLK_CP), + DEF_MOD("pfc2", 917, R8A779A0_CLK_CP), + DEF_MOD("pfc3", 918, R8A779A0_CLK_CP), + DEF_MOD("vspx0", 1028, R8A779A0_CLK_S1D1), + DEF_MOD("vspx1", 1029, R8A779A0_CLK_S1D1), + DEF_MOD("vspx2", 1030, R8A779A0_CLK_S1D1), + DEF_MOD("vspx3", 1031, R8A779A0_CLK_S1D1), }; -static spinlock_t cpg_lock; - static const struct rcar_r8a779a0_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; @@ -230,6 +275,12 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, div = cpg_pll_config->pll5_div; break; + case CLK_TYPE_R8A779A0_SD: + return cpg_sd_clk_register(core->name, base, core->offset, + __clk_get_name(parent), notifiers, + false); + break; + case CLK_TYPE_R8A779A0_MDSEL: /* * Clock selectable between two parents and two fixed dividers @@ -261,6 +312,10 @@ static struct clk * __init rcar_r8a779a0_cpg_clk_register(struct device *dev, __clk_get_name(parent), 0, mult, div); } +static const unsigned int r8a779a0_crit_mod_clks[] __initconst = { + MOD_CLK_ID(907), /* RWDT */ +}; + /* * CPG Clock Data */ @@ -311,6 +366,10 @@ const struct cpg_mssr_info r8a779a0_cpg_mssr_info __initconst = { .num_mod_clks = ARRAY_SIZE(r8a779a0_mod_clks), .num_hw_mod_clks = 15 * 32, + /* Critical Module Clocks */ + .crit_mod_clks = r8a779a0_crit_mod_clks, + .num_crit_mod_clks = ARRAY_SIZE(r8a779a0_crit_mod_clks), + /* Callbacks */ .init = r8a779a0_cpg_mssr_init, .cpg_clk_register = rcar_r8a779a0_cpg_clk_register, diff --git a/drivers/clk/renesas/rcar-cpg-lib.c b/drivers/clk/renesas/rcar-cpg-lib.c new file mode 100644 index 000000000000..7e7e5d1341d5 --- /dev/null +++ b/drivers/clk/renesas/rcar-cpg-lib.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * R-Car Gen3 Clock Pulse Generator Library + * + * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2019 Renesas Electronics Corp. + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/err.h> +#include <linux/init.h> +#include <linux/io.h> +#include <linux/pm.h> +#include <linux/slab.h> +#include <linux/sys_soc.h> + +#include "rcar-cpg-lib.h" + +spinlock_t cpg_lock; + +void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&cpg_lock, flags); + val = readl(reg); + val &= ~clear; + val |= set; + writel(val, reg); + spin_unlock_irqrestore(&cpg_lock, flags); +}; + +static int cpg_simple_notifier_call(struct notifier_block *nb, + unsigned long action, void *data) +{ + struct cpg_simple_notifier *csn = + container_of(nb, struct cpg_simple_notifier, nb); + + switch (action) { + case PM_EVENT_SUSPEND: + csn->saved = readl(csn->reg); + return NOTIFY_OK; + + case PM_EVENT_RESUME: + writel(csn->saved, csn->reg); + return NOTIFY_OK; + } + return NOTIFY_DONE; +} + +void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn) +{ + csn->nb.notifier_call = cpg_simple_notifier_call; + raw_notifier_chain_register(notifiers, &csn->nb); +} + +/* + * SDn Clock + */ +#define CPG_SD_STP_HCK BIT(9) +#define CPG_SD_STP_CK BIT(8) + +#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) +#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) + +#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ +{ \ + .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ + ((sd_srcfc) << 2) | \ + ((sd_fc) << 0), \ + .div = (sd_div), \ +} + +struct sd_div_table { + u32 val; + unsigned int div; +}; + +struct sd_clock { + struct clk_hw hw; + const struct sd_div_table *div_table; + struct cpg_simple_notifier csn; + unsigned int div_num; + unsigned int cur_div_idx; +}; + +/* SDn divider + * sd_srcfc sd_fc div + * stp_hck (div) (div) = sd_srcfc x sd_fc + *--------------------------------------------------------- + * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) + * 0 1 (2) 1 (4) 8 : SDR50 + * 1 2 (4) 1 (4) 16 : HS / SDR25 + * 1 3 (8) 1 (4) 32 : NS / SDR12 + * 1 4 (16) 1 (4) 64 + * 0 0 (1) 0 (2) 2 + * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) + * 1 2 (4) 0 (2) 8 + * 1 3 (8) 0 (2) 16 + * 1 4 (16) 0 (2) 32 + * + * NOTE: There is a quirk option to ignore the first row of the dividers + * table when searching for suitable settings. This is because HS400 on + * early ES versions of H3 and M3-W requires a specific setting to work. + */ +static const struct sd_div_table cpg_sd_div_table[] = { +/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ + CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), + CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), + CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), + CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), + CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), + CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), + CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), + CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), + CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), + CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), +}; + +#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) + +static int cpg_sd_clock_enable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, + clock->div_table[clock->cur_div_idx].val & + CPG_SD_STP_MASK); + + return 0; +} + +static void cpg_sd_clock_disable(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); +} + +static int cpg_sd_clock_is_enabled(struct clk_hw *hw) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); +} + +static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + + return DIV_ROUND_CLOSEST(parent_rate, + clock->div_table[clock->cur_div_idx].div); +} + +static int cpg_sd_clock_determine_rate(struct clk_hw *hw, + struct clk_rate_request *req) +{ + unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX; + struct sd_clock *clock = to_sd_clock(hw); + unsigned long calc_rate, diff; + unsigned int i; + + for (i = 0; i < clock->div_num; i++) { + calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, + clock->div_table[i].div); + if (calc_rate < req->min_rate || calc_rate > req->max_rate) + continue; + + diff = calc_rate > req->rate ? calc_rate - req->rate + : req->rate - calc_rate; + if (diff < diff_min) { + best_rate = calc_rate; + diff_min = diff; + } + } + + if (best_rate == ULONG_MAX) + return -EINVAL; + + req->rate = best_rate; + return 0; +} + +static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct sd_clock *clock = to_sd_clock(hw); + unsigned int i; + + for (i = 0; i < clock->div_num; i++) + if (rate == DIV_ROUND_CLOSEST(parent_rate, + clock->div_table[i].div)) + break; + + if (i >= clock->div_num) + return -EINVAL; + + clock->cur_div_idx = i; + + cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, + clock->div_table[i].val & + (CPG_SD_STP_MASK | CPG_SD_FC_MASK)); + + return 0; +} + +static const struct clk_ops cpg_sd_clock_ops = { + .enable = cpg_sd_clock_enable, + .disable = cpg_sd_clock_disable, + .is_enabled = cpg_sd_clock_is_enabled, + .recalc_rate = cpg_sd_clock_recalc_rate, + .determine_rate = cpg_sd_clock_determine_rate, + .set_rate = cpg_sd_clock_set_rate, +}; + +struct clk * __init cpg_sd_clk_register(const char *name, + void __iomem *base, unsigned int offset, const char *parent_name, + struct raw_notifier_head *notifiers, bool skip_first) +{ + struct clk_init_data init; + struct sd_clock *clock; + struct clk *clk; + u32 val; + + clock = kzalloc(sizeof(*clock), GFP_KERNEL); + if (!clock) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &cpg_sd_clock_ops; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + + clock->csn.reg = base + offset; + clock->hw.init = &init; + clock->div_table = cpg_sd_div_table; + clock->div_num = ARRAY_SIZE(cpg_sd_div_table); + + if (skip_first) { + clock->div_table++; + clock->div_num--; + } + + val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK; + val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); + writel(val, clock->csn.reg); + + clk = clk_register(NULL, &clock->hw); + if (IS_ERR(clk)) + goto free_clock; + + cpg_simple_notifier_register(notifiers, &clock->csn); + return clk; + +free_clock: + kfree(clock); + return clk; +} + + diff --git a/drivers/clk/renesas/rcar-cpg-lib.h b/drivers/clk/renesas/rcar-cpg-lib.h new file mode 100644 index 000000000000..d00c91b116ca --- /dev/null +++ b/drivers/clk/renesas/rcar-cpg-lib.h @@ -0,0 +1,33 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * R-Car Gen3 Clock Pulse Generator Library + * + * Copyright (C) 2015-2018 Glider bvba + * Copyright (C) 2019 Renesas Electronics Corp. + * + * Based on clk-rcar-gen3.c + * + * Copyright (C) 2015 Renesas Electronics Corp. + */ + +#ifndef __CLK_RENESAS_RCAR_CPG_LIB_H__ +#define __CLK_RENESAS_RCAR_CPG_LIB_H__ + +extern spinlock_t cpg_lock; + +struct cpg_simple_notifier { + struct notifier_block nb; + void __iomem *reg; + u32 saved; +}; + +void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, + struct cpg_simple_notifier *csn); + +void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set); + +struct clk * __init cpg_sd_clk_register(const char *name, + void __iomem *base, unsigned int offset, const char *parent_name, + struct raw_notifier_head *notifiers, bool skip_first); + +#endif diff --git a/drivers/clk/renesas/rcar-gen3-cpg.c b/drivers/clk/renesas/rcar-gen3-cpg.c index 063b61151488..17826599e9dd 100644 --- a/drivers/clk/renesas/rcar-gen3-cpg.c +++ b/drivers/clk/renesas/rcar-gen3-cpg.c @@ -23,6 +23,7 @@ #include <linux/sys_soc.h> #include "renesas-cpg-mssr.h" +#include "rcar-cpg-lib.h" #include "rcar-gen3-cpg.h" #define CPG_PLL0CR 0x00d8 @@ -31,52 +32,6 @@ #define CPG_RCKCR_CKSEL BIT(15) /* RCLK Clock Source Select */ -static spinlock_t cpg_lock; - -static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set) -{ - unsigned long flags; - u32 val; - - spin_lock_irqsave(&cpg_lock, flags); - val = readl(reg); - val &= ~clear; - val |= set; - writel(val, reg); - spin_unlock_irqrestore(&cpg_lock, flags); -}; - -struct cpg_simple_notifier { - struct notifier_block nb; - void __iomem *reg; - u32 saved; -}; - -static int cpg_simple_notifier_call(struct notifier_block *nb, - unsigned long action, void *data) -{ - struct cpg_simple_notifier *csn = - container_of(nb, struct cpg_simple_notifier, nb); - - switch (action) { - case PM_EVENT_SUSPEND: - csn->saved = readl(csn->reg); - return NOTIFY_OK; - - case PM_EVENT_RESUME: - writel(csn->saved, csn->reg); - return NOTIFY_OK; - } - return NOTIFY_DONE; -} - -static void cpg_simple_notifier_register(struct raw_notifier_head *notifiers, - struct cpg_simple_notifier *csn) -{ - csn->nb.notifier_call = cpg_simple_notifier_call; - raw_notifier_chain_register(notifiers, &csn->nb); -} - /* * Z Clock & Z2 Clock * @@ -215,217 +170,6 @@ static struct clk * __init cpg_z_clk_register(const char *name, return clk; } -/* - * SDn Clock - */ -#define CPG_SD_STP_HCK BIT(9) -#define CPG_SD_STP_CK BIT(8) - -#define CPG_SD_STP_MASK (CPG_SD_STP_HCK | CPG_SD_STP_CK) -#define CPG_SD_FC_MASK (0x7 << 2 | 0x3 << 0) - -#define CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) \ -{ \ - .val = ((stp_hck) ? CPG_SD_STP_HCK : 0) | \ - ((sd_srcfc) << 2) | \ - ((sd_fc) << 0), \ - .div = (sd_div), \ -} - -struct sd_div_table { - u32 val; - unsigned int div; -}; - -struct sd_clock { - struct clk_hw hw; - const struct sd_div_table *div_table; - struct cpg_simple_notifier csn; - unsigned int div_num; - unsigned int cur_div_idx; -}; - -/* SDn divider - * sd_srcfc sd_fc div - * stp_hck (div) (div) = sd_srcfc x sd_fc - *--------------------------------------------------------- - * 0 0 (1) 1 (4) 4 : SDR104 / HS200 / HS400 (8 TAP) - * 0 1 (2) 1 (4) 8 : SDR50 - * 1 2 (4) 1 (4) 16 : HS / SDR25 - * 1 3 (8) 1 (4) 32 : NS / SDR12 - * 1 4 (16) 1 (4) 64 - * 0 0 (1) 0 (2) 2 - * 0 1 (2) 0 (2) 4 : SDR104 / HS200 / HS400 (4 TAP) - * 1 2 (4) 0 (2) 8 - * 1 3 (8) 0 (2) 16 - * 1 4 (16) 0 (2) 32 - * - * NOTE: There is a quirk option to ignore the first row of the dividers - * table when searching for suitable settings. This is because HS400 on - * early ES versions of H3 and M3-W requires a specific setting to work. - */ -static const struct sd_div_table cpg_sd_div_table[] = { -/* CPG_SD_DIV_TABLE_DATA(stp_hck, sd_srcfc, sd_fc, sd_div) */ - CPG_SD_DIV_TABLE_DATA(0, 0, 1, 4), - CPG_SD_DIV_TABLE_DATA(0, 1, 1, 8), - CPG_SD_DIV_TABLE_DATA(1, 2, 1, 16), - CPG_SD_DIV_TABLE_DATA(1, 3, 1, 32), - CPG_SD_DIV_TABLE_DATA(1, 4, 1, 64), - CPG_SD_DIV_TABLE_DATA(0, 0, 0, 2), - CPG_SD_DIV_TABLE_DATA(0, 1, 0, 4), - CPG_SD_DIV_TABLE_DATA(1, 2, 0, 8), - CPG_SD_DIV_TABLE_DATA(1, 3, 0, 16), - CPG_SD_DIV_TABLE_DATA(1, 4, 0, 32), -}; - -#define to_sd_clock(_hw) container_of(_hw, struct sd_clock, hw) - -static int cpg_sd_clock_enable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK, - clock->div_table[clock->cur_div_idx].val & - CPG_SD_STP_MASK); - - return 0; -} - -static void cpg_sd_clock_disable(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK); -} - -static int cpg_sd_clock_is_enabled(struct clk_hw *hw) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return !(readl(clock->csn.reg) & CPG_SD_STP_MASK); -} - -static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - - return DIV_ROUND_CLOSEST(parent_rate, - clock->div_table[clock->cur_div_idx].div); -} - -static int cpg_sd_clock_determine_rate(struct clk_hw *hw, - struct clk_rate_request *req) -{ - unsigned long best_rate = ULONG_MAX, diff_min = ULONG_MAX; - struct sd_clock *clock = to_sd_clock(hw); - unsigned long calc_rate, diff; - unsigned int i; - - for (i = 0; i < clock->div_num; i++) { - calc_rate = DIV_ROUND_CLOSEST(req->best_parent_rate, - clock->div_table[i].div); - if (calc_rate < req->min_rate || calc_rate > req->max_rate) - continue; - - diff = calc_rate > req->rate ? calc_rate - req->rate - : req->rate - calc_rate; - if (diff < diff_min) { - best_rate = calc_rate; - diff_min = diff; - } - } - - if (best_rate == ULONG_MAX) - return -EINVAL; - - req->rate = best_rate; - return 0; -} - -static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct sd_clock *clock = to_sd_clock(hw); - unsigned int i; - - for (i = 0; i < clock->div_num; i++) - if (rate == DIV_ROUND_CLOSEST(parent_rate, - clock->div_table[i].div)) - break; - - if (i >= clock->div_num) - return -EINVAL; - - clock->cur_div_idx = i; - - cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK, - clock->div_table[i].val & - (CPG_SD_STP_MASK | CPG_SD_FC_MASK)); - - return 0; -} - -static const struct clk_ops cpg_sd_clock_ops = { - .enable = cpg_sd_clock_enable, - .disable = cpg_sd_clock_disable, - .is_enabled = cpg_sd_clock_is_enabled, - .recalc_rate = cpg_sd_clock_recalc_rate, - .determine_rate = cpg_sd_clock_determine_rate, - .set_rate = cpg_sd_clock_set_rate, -}; - -static u32 cpg_quirks __initdata; - -#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */ -#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ -#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */ - -static struct clk * __init cpg_sd_clk_register(const char *name, - void __iomem *base, unsigned int offset, const char *parent_name, - struct raw_notifier_head *notifiers) -{ - struct clk_init_data init; - struct sd_clock *clock; - struct clk *clk; - u32 val; - - clock = kzalloc(sizeof(*clock), GFP_KERNEL); - if (!clock) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &cpg_sd_clock_ops; - init.flags = CLK_SET_RATE_PARENT; - init.parent_names = &parent_name; - init.num_parents = 1; - - clock->csn.reg = base + offset; - clock->hw.init = &init; - clock->div_table = cpg_sd_div_table; - clock->div_num = ARRAY_SIZE(cpg_sd_div_table); - - if (cpg_quirks & SD_SKIP_FIRST) { - clock->div_table++; - clock->div_num--; - } - - val = readl(clock->csn.reg) & ~CPG_SD_FC_MASK; - val |= CPG_SD_STP_MASK | (clock->div_table[0].val & CPG_SD_FC_MASK); - writel(val, clock->csn.reg); - - clk = clk_register(NULL, &clock->hw); - if (IS_ERR(clk)) - goto free_clock; - - cpg_simple_notifier_register(notifiers, &clock->csn); - return clk; - -free_clock: - kfree(clock); - return clk; -} - struct rpc_clock { struct clk_divider div; struct clk_gate gate; @@ -518,6 +262,12 @@ static struct clk * __init cpg_rpcd2_clk_register(const char *name, static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata; static unsigned int cpg_clk_extalr __initdata; static u32 cpg_mode __initdata; +static u32 cpg_quirks __initdata; + +#define PLL_ERRATA BIT(0) /* Missing PLL0/2/4 post-divider */ +#define RCKCR_CKSEL BIT(1) /* Manual RCLK parent selection */ +#define SD_SKIP_FIRST BIT(2) /* Skip first clock in SD table */ + static const struct soc_device_attribute cpg_quirks_match[] __initconst = { { @@ -613,7 +363,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, case CLK_TYPE_GEN3_SD: return cpg_sd_clk_register(core->name, base, core->offset, - __clk_get_name(parent), notifiers); + __clk_get_name(parent), notifiers, + cpg_quirks & SD_SKIP_FIRST); case CLK_TYPE_GEN3_R: if (cpg_quirks & RCKCR_CKSEL) { diff --git a/drivers/clk/renesas/renesas-cpg-mssr.c b/drivers/clk/renesas/renesas-cpg-mssr.c index 1c3215dc4877..bffbc3d2faf5 100644 --- a/drivers/clk/renesas/renesas-cpg-mssr.c +++ b/drivers/clk/renesas/renesas-cpg-mssr.c @@ -136,8 +136,8 @@ static const u16 srstclr_for_v3u[] = { * @control_regs: Pointer to control registers array * @reset_regs: Pointer to reset registers array * @reset_clear_regs: Pointer to reset clearing registers array - * @smstpcr_saved[].mask: Mask of SMSTPCR[] bits under our control - * @smstpcr_saved[].val: Saved values of SMSTPCR[] + * @smstpcr_saved: [].mask: Mask of SMSTPCR[] bits under our control + * [].val: Saved values of SMSTPCR[] * @clks: Array containing all Core and Module Clocks */ struct cpg_mssr_priv { diff --git a/drivers/clk/rockchip/clk-cpu.c b/drivers/clk/rockchip/clk-cpu.c index 0dc478a19451..fa9027fb1920 100644 --- a/drivers/clk/rockchip/clk-cpu.c +++ b/drivers/clk/rockchip/clk-cpu.c @@ -51,10 +51,6 @@ */ struct rockchip_cpuclk { struct clk_hw hw; - - struct clk_mux cpu_mux; - const struct clk_ops *cpu_mux_ops; - struct clk *alt_parent; void __iomem *reg_base; struct notifier_block clk_nb; diff --git a/drivers/clk/rockchip/clk-half-divider.c b/drivers/clk/rockchip/clk-half-divider.c index ccd5c270c213..64f7faad2148 100644 --- a/drivers/clk/rockchip/clk-half-divider.c +++ b/drivers/clk/rockchip/clk-half-divider.c @@ -145,7 +145,7 @@ static const struct clk_ops clk_half_divider_ops = { .set_rate = clk_half_divider_set_rate, }; -/** +/* * Register a clock branch. * Most clock branches have a form like * diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c index 4c6c9167ef50..fe937bcdb487 100644 --- a/drivers/clk/rockchip/clk-pll.c +++ b/drivers/clk/rockchip/clk-pll.c @@ -97,7 +97,7 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) return ret; } -/** +/* * PLL used in RK3036 */ @@ -358,7 +358,7 @@ static const struct clk_ops rockchip_rk3036_pll_clk_ops = { .init = rockchip_rk3036_pll_init, }; -/** +/* * PLL used in RK3066, RK3188 and RK3288 */ @@ -577,7 +577,7 @@ static const struct clk_ops rockchip_rk3066_pll_clk_ops = { .init = rockchip_rk3066_pll_init, }; -/** +/* * PLL used in RK3399 */ diff --git a/drivers/clk/rockchip/clk-rk3368.c b/drivers/clk/rockchip/clk-rk3368.c index 55443349439b..9a0dab9448db 100644 --- a/drivers/clk/rockchip/clk-rk3368.c +++ b/drivers/clk/rockchip/clk-rk3368.c @@ -474,7 +474,7 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, RK3368_CLKSEL_CON(21), 15, 1, MFLAGS, RK3368_CLKGATE_CON(4), 5, GFLAGS), - COMPOSITE_NOGATE(0, "sclk_vip_out", mux_vip_out_p, 0, + COMPOSITE_NOGATE(SCLK_VIP_OUT, "sclk_vip_out", mux_vip_out_p, 0, RK3368_CLKSEL_CON(21), 14, 1, MFLAGS, 8, 5, DFLAGS), COMPOSITE_NODIV(SCLK_EDP_24M, "sclk_edp_24m", mux_edp_24m_p, 0, @@ -818,8 +818,8 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { * pclk_vio gates * pclk_vio comes from the exactly same source as hclk_vio */ - GATE(0, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), - GATE(0, "pclk_dphytx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(14), 8, GFLAGS), + GATE(PCLK_DPHYRX, "pclk_dphyrx", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 11, GFLAGS), + GATE(PCLK_DPHYTX0, "pclk_dphytx0", "hclk_vio", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(22), 10, GFLAGS), /* pclk_pd_pmu gates */ GATE(PCLK_PMUGRF, "pclk_pmugrf", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 5, GFLAGS), diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c index 336481bc6cc7..049e5e0b64f6 100644 --- a/drivers/clk/rockchip/clk.c +++ b/drivers/clk/rockchip/clk.c @@ -24,7 +24,7 @@ #include <linux/rational.h> #include "clk.h" -/** +/* * Register a clock branch. * Most clock branches have a form like * @@ -170,7 +170,7 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, return notifier_from_errno(ret); } -/** +/* * fractional divider must set that denominator is 20 times larger than * numerator to generate precise clock frequency. */ diff --git a/drivers/clk/sirf/Makefile b/drivers/clk/sirf/Makefile deleted file mode 100644 index 0ff61f87cddb..000000000000 --- a/drivers/clk/sirf/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for sirf specific clk -# - -obj-$(CONFIG_ARCH_SIRF) += clk-prima2.o clk-atlas6.o clk-atlas7.o diff --git a/drivers/clk/sirf/atlas6.h b/drivers/clk/sirf/atlas6.h deleted file mode 100644 index cb871e30a175..000000000000 --- a/drivers/clk/sirf/atlas6.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#define SIRFSOC_CLKC_CLK_EN0 0x0000 -#define SIRFSOC_CLKC_CLK_EN1 0x0004 -#define SIRFSOC_CLKC_REF_CFG 0x0020 -#define SIRFSOC_CLKC_CPU_CFG 0x0024 -#define SIRFSOC_CLKC_MEM_CFG 0x0028 -#define SIRFSOC_CLKC_MEMDIV_CFG 0x002C -#define SIRFSOC_CLKC_SYS_CFG 0x0030 -#define SIRFSOC_CLKC_IO_CFG 0x0034 -#define SIRFSOC_CLKC_DSP_CFG 0x0038 -#define SIRFSOC_CLKC_GFX_CFG 0x003c -#define SIRFSOC_CLKC_MM_CFG 0x0040 -#define SIRFSOC_CLKC_GFX2D_CFG 0x0040 -#define SIRFSOC_CLKC_LCD_CFG 0x0044 -#define SIRFSOC_CLKC_MMC01_CFG 0x0048 -#define SIRFSOC_CLKC_MMC23_CFG 0x004C -#define SIRFSOC_CLKC_MMC45_CFG 0x0050 -#define SIRFSOC_CLKC_NAND_CFG 0x0054 -#define SIRFSOC_CLKC_NANDDIV_CFG 0x0058 -#define SIRFSOC_CLKC_PLL1_CFG0 0x0080 -#define SIRFSOC_CLKC_PLL2_CFG0 0x0084 -#define SIRFSOC_CLKC_PLL3_CFG0 0x0088 -#define SIRFSOC_CLKC_PLL1_CFG1 0x008c -#define SIRFSOC_CLKC_PLL2_CFG1 0x0090 -#define SIRFSOC_CLKC_PLL3_CFG1 0x0094 -#define SIRFSOC_CLKC_PLL1_CFG2 0x0098 -#define SIRFSOC_CLKC_PLL2_CFG2 0x009c -#define SIRFSOC_CLKC_PLL3_CFG2 0x00A0 -#define SIRFSOC_USBPHY_PLL_CTRL 0x0008 -#define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1) -#define SIRFSOC_USBPHY_PLL_BYPASS BIT(2) -#define SIRFSOC_USBPHY_PLL_LOCK BIT(3) diff --git a/drivers/clk/sirf/clk-atlas6.c b/drivers/clk/sirf/clk-atlas6.c deleted file mode 100644 index b95483bb6a5e..000000000000 --- a/drivers/clk/sirf/clk-atlas6.c +++ /dev/null @@ -1,150 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Clock tree for CSR SiRFatlasVI - * - * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group - * company. - */ - -#include <linux/module.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/clkdev.h> -#include <linux/clk-provider.h> -#include <linux/of_address.h> -#include <linux/syscore_ops.h> - -#include "atlas6.h" -#include "clk-common.c" - -static struct clk_dmn clk_mmc01 = { - .regofs = SIRFSOC_CLKC_MMC01_CFG, - .enable_bit = 59, - .hw = { - .init = &clk_mmc01_init, - }, -}; - -static struct clk_dmn clk_mmc23 = { - .regofs = SIRFSOC_CLKC_MMC23_CFG, - .enable_bit = 60, - .hw = { - .init = &clk_mmc23_init, - }, -}; - -static struct clk_dmn clk_mmc45 = { - .regofs = SIRFSOC_CLKC_MMC45_CFG, - .enable_bit = 61, - .hw = { - .init = &clk_mmc45_init, - }, -}; - -static const struct clk_init_data clk_nand_init = { - .name = "nand", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_nand = { - .regofs = SIRFSOC_CLKC_NAND_CFG, - .enable_bit = 34, - .hw = { - .init = &clk_nand_init, - }, -}; - -enum atlas6_clk_index { - /* 0 1 2 3 4 5 6 7 8 9 */ - rtc, osc, pll1, pll2, pll3, mem, sys, security, dsp, gps, - mf, io, cpu, uart0, uart1, uart2, tsc, i2c0, i2c1, spi0, - spi1, pwmc, efuse, pulse, dmac0, dmac1, nand, audio, usp0, usp1, - usp2, vip, gfx, gfx2d, lcd, vpp, mmc01, mmc23, mmc45, usbpll, - usb0, usb1, cphif, maxclk, -}; - -static __initdata struct clk_hw *atlas6_clk_hw_array[maxclk] = { - NULL, /* dummy */ - NULL, - &clk_pll1.hw, - &clk_pll2.hw, - &clk_pll3.hw, - &clk_mem.hw, - &clk_sys.hw, - &clk_security.hw, - &clk_dsp.hw, - &clk_gps.hw, - &clk_mf.hw, - &clk_io.hw, - &clk_cpu.hw, - &clk_uart0.hw, - &clk_uart1.hw, - &clk_uart2.hw, - &clk_tsc.hw, - &clk_i2c0.hw, - &clk_i2c1.hw, - &clk_spi0.hw, - &clk_spi1.hw, - &clk_pwmc.hw, - &clk_efuse.hw, - &clk_pulse.hw, - &clk_dmac0.hw, - &clk_dmac1.hw, - &clk_nand.hw, - &clk_audio.hw, - &clk_usp0.hw, - &clk_usp1.hw, - &clk_usp2.hw, - &clk_vip.hw, - &clk_gfx.hw, - &clk_gfx2d.hw, - &clk_lcd.hw, - &clk_vpp.hw, - &clk_mmc01.hw, - &clk_mmc23.hw, - &clk_mmc45.hw, - &usb_pll_clk_hw, - &clk_usb0.hw, - &clk_usb1.hw, - &clk_cphif.hw, -}; - -static struct clk *atlas6_clks[maxclk]; - -static void __init atlas6_clk_init(struct device_node *np) -{ - struct device_node *rscnp; - int i; - - rscnp = of_find_compatible_node(NULL, NULL, "sirf,prima2-rsc"); - sirfsoc_rsc_vbase = of_iomap(rscnp, 0); - if (!sirfsoc_rsc_vbase) - panic("unable to map rsc registers\n"); - of_node_put(rscnp); - - sirfsoc_clk_vbase = of_iomap(np, 0); - if (!sirfsoc_clk_vbase) - panic("unable to map clkc registers\n"); - - /* These are always available (RTC and 26MHz OSC)*/ - atlas6_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); - atlas6_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, - 26000000); - - for (i = pll1; i < maxclk; i++) { - atlas6_clks[i] = clk_register(NULL, atlas6_clk_hw_array[i]); - BUG_ON(IS_ERR(atlas6_clks[i])); - } - clk_register_clkdev(atlas6_clks[cpu], NULL, "cpu"); - clk_register_clkdev(atlas6_clks[io], NULL, "io"); - clk_register_clkdev(atlas6_clks[mem], NULL, "mem"); - clk_register_clkdev(atlas6_clks[mem], NULL, "osc"); - - clk_data.clks = atlas6_clks; - clk_data.clk_num = maxclk; - - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -} -CLK_OF_DECLARE(atlas6_clk, "sirf,atlas6-clkc", atlas6_clk_init); diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c deleted file mode 100644 index 3f57fefd13bb..000000000000 --- a/drivers/clk/sirf/clk-atlas7.c +++ /dev/null @@ -1,1682 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Clock tree for CSR SiRFAtlas7 - * - * Copyright (c) 2014 Cambridge Silicon Radio Limited, a CSR plc group company. - */ - -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/clk-provider.h> -#include <linux/delay.h> -#include <linux/of_address.h> -#include <linux/reset-controller.h> -#include <linux/slab.h> - -#define SIRFSOC_CLKC_MEMPLL_AB_FREQ 0x0000 -#define SIRFSOC_CLKC_MEMPLL_AB_SSC 0x0004 -#define SIRFSOC_CLKC_MEMPLL_AB_CTRL0 0x0008 -#define SIRFSOC_CLKC_MEMPLL_AB_CTRL1 0x000c -#define SIRFSOC_CLKC_MEMPLL_AB_STATUS 0x0010 -#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_ADDR 0x0014 -#define SIRFSOC_CLKC_MEMPLL_AB_SSRAM_DATA 0x0018 - -#define SIRFSOC_CLKC_CPUPLL_AB_FREQ 0x001c -#define SIRFSOC_CLKC_CPUPLL_AB_SSC 0x0020 -#define SIRFSOC_CLKC_CPUPLL_AB_CTRL0 0x0024 -#define SIRFSOC_CLKC_CPUPLL_AB_CTRL1 0x0028 -#define SIRFSOC_CLKC_CPUPLL_AB_STATUS 0x002c - -#define SIRFSOC_CLKC_SYS0PLL_AB_FREQ 0x0030 -#define SIRFSOC_CLKC_SYS0PLL_AB_SSC 0x0034 -#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL0 0x0038 -#define SIRFSOC_CLKC_SYS0PLL_AB_CTRL1 0x003c -#define SIRFSOC_CLKC_SYS0PLL_AB_STATUS 0x0040 - -#define SIRFSOC_CLKC_SYS1PLL_AB_FREQ 0x0044 -#define SIRFSOC_CLKC_SYS1PLL_AB_SSC 0x0048 -#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL0 0x004c -#define SIRFSOC_CLKC_SYS1PLL_AB_CTRL1 0x0050 -#define SIRFSOC_CLKC_SYS1PLL_AB_STATUS 0x0054 - -#define SIRFSOC_CLKC_SYS2PLL_AB_FREQ 0x0058 -#define SIRFSOC_CLKC_SYS2PLL_AB_SSC 0x005c -#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL0 0x0060 -#define SIRFSOC_CLKC_SYS2PLL_AB_CTRL1 0x0064 -#define SIRFSOC_CLKC_SYS2PLL_AB_STATUS 0x0068 - -#define SIRFSOC_CLKC_SYS3PLL_AB_FREQ 0x006c -#define SIRFSOC_CLKC_SYS3PLL_AB_SSC 0x0070 -#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL0 0x0074 -#define SIRFSOC_CLKC_SYS3PLL_AB_CTRL1 0x0078 -#define SIRFSOC_CLKC_SYS3PLL_AB_STATUS 0x007c - -#define SIRFSOC_ABPLL_CTRL0_SSEN 0x00001000 -#define SIRFSOC_ABPLL_CTRL0_BYPASS 0x00000010 -#define SIRFSOC_ABPLL_CTRL0_RESET 0x00000001 - -#define SIRFSOC_CLKC_AUDIO_DTO_INC 0x0088 -#define SIRFSOC_CLKC_DISP0_DTO_INC 0x008c -#define SIRFSOC_CLKC_DISP1_DTO_INC 0x0090 - -#define SIRFSOC_CLKC_AUDIO_DTO_SRC 0x0094 -#define SIRFSOC_CLKC_AUDIO_DTO_ENA 0x0098 -#define SIRFSOC_CLKC_AUDIO_DTO_DROFF 0x009c - -#define SIRFSOC_CLKC_DISP0_DTO_SRC 0x00a0 -#define SIRFSOC_CLKC_DISP0_DTO_ENA 0x00a4 -#define SIRFSOC_CLKC_DISP0_DTO_DROFF 0x00a8 - -#define SIRFSOC_CLKC_DISP1_DTO_SRC 0x00ac -#define SIRFSOC_CLKC_DISP1_DTO_ENA 0x00b0 -#define SIRFSOC_CLKC_DISP1_DTO_DROFF 0x00b4 - -#define SIRFSOC_CLKC_I2S_CLK_SEL 0x00b8 -#define SIRFSOC_CLKC_I2S_SEL_STAT 0x00bc - -#define SIRFSOC_CLKC_USBPHY_CLKDIV_CFG 0x00c0 -#define SIRFSOC_CLKC_USBPHY_CLKDIV_ENA 0x00c4 -#define SIRFSOC_CLKC_USBPHY_CLK_SEL 0x00c8 -#define SIRFSOC_CLKC_USBPHY_CLK_SEL_STAT 0x00cc - -#define SIRFSOC_CLKC_BTSS_CLKDIV_CFG 0x00d0 -#define SIRFSOC_CLKC_BTSS_CLKDIV_ENA 0x00d4 -#define SIRFSOC_CLKC_BTSS_CLK_SEL 0x00d8 -#define SIRFSOC_CLKC_BTSS_CLK_SEL_STAT 0x00dc - -#define SIRFSOC_CLKC_RGMII_CLKDIV_CFG 0x00e0 -#define SIRFSOC_CLKC_RGMII_CLKDIV_ENA 0x00e4 -#define SIRFSOC_CLKC_RGMII_CLK_SEL 0x00e8 -#define SIRFSOC_CLKC_RGMII_CLK_SEL_STAT 0x00ec - -#define SIRFSOC_CLKC_CPU_CLKDIV_CFG 0x00f0 -#define SIRFSOC_CLKC_CPU_CLKDIV_ENA 0x00f4 -#define SIRFSOC_CLKC_CPU_CLK_SEL 0x00f8 -#define SIRFSOC_CLKC_CPU_CLK_SEL_STAT 0x00fc - -#define SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG 0x0100 -#define SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA 0x0104 -#define SIRFSOC_CLKC_SDPHY01_CLK_SEL 0x0108 -#define SIRFSOC_CLKC_SDPHY01_CLK_SEL_STAT 0x010c - -#define SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG 0x0110 -#define SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA 0x0114 -#define SIRFSOC_CLKC_SDPHY23_CLK_SEL 0x0118 -#define SIRFSOC_CLKC_SDPHY23_CLK_SEL_STAT 0x011c - -#define SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG 0x0120 -#define SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA 0x0124 -#define SIRFSOC_CLKC_SDPHY45_CLK_SEL 0x0128 -#define SIRFSOC_CLKC_SDPHY45_CLK_SEL_STAT 0x012c - -#define SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG 0x0130 -#define SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA 0x0134 -#define SIRFSOC_CLKC_SDPHY67_CLK_SEL 0x0138 -#define SIRFSOC_CLKC_SDPHY67_CLK_SEL_STAT 0x013c - -#define SIRFSOC_CLKC_CAN_CLKDIV_CFG 0x0140 -#define SIRFSOC_CLKC_CAN_CLKDIV_ENA 0x0144 -#define SIRFSOC_CLKC_CAN_CLK_SEL 0x0148 -#define SIRFSOC_CLKC_CAN_CLK_SEL_STAT 0x014c - -#define SIRFSOC_CLKC_DEINT_CLKDIV_CFG 0x0150 -#define SIRFSOC_CLKC_DEINT_CLKDIV_ENA 0x0154 -#define SIRFSOC_CLKC_DEINT_CLK_SEL 0x0158 -#define SIRFSOC_CLKC_DEINT_CLK_SEL_STAT 0x015c - -#define SIRFSOC_CLKC_NAND_CLKDIV_CFG 0x0160 -#define SIRFSOC_CLKC_NAND_CLKDIV_ENA 0x0164 -#define SIRFSOC_CLKC_NAND_CLK_SEL 0x0168 -#define SIRFSOC_CLKC_NAND_CLK_SEL_STAT 0x016c - -#define SIRFSOC_CLKC_DISP0_CLKDIV_CFG 0x0170 -#define SIRFSOC_CLKC_DISP0_CLKDIV_ENA 0x0174 -#define SIRFSOC_CLKC_DISP0_CLK_SEL 0x0178 -#define SIRFSOC_CLKC_DISP0_CLK_SEL_STAT 0x017c - -#define SIRFSOC_CLKC_DISP1_CLKDIV_CFG 0x0180 -#define SIRFSOC_CLKC_DISP1_CLKDIV_ENA 0x0184 -#define SIRFSOC_CLKC_DISP1_CLK_SEL 0x0188 -#define SIRFSOC_CLKC_DISP1_CLK_SEL_STAT 0x018c - -#define SIRFSOC_CLKC_GPU_CLKDIV_CFG 0x0190 -#define SIRFSOC_CLKC_GPU_CLKDIV_ENA 0x0194 -#define SIRFSOC_CLKC_GPU_CLK_SEL 0x0198 -#define SIRFSOC_CLKC_GPU_CLK_SEL_STAT 0x019c - -#define SIRFSOC_CLKC_GNSS_CLKDIV_CFG 0x01a0 -#define SIRFSOC_CLKC_GNSS_CLKDIV_ENA 0x01a4 -#define SIRFSOC_CLKC_GNSS_CLK_SEL 0x01a8 -#define SIRFSOC_CLKC_GNSS_CLK_SEL_STAT 0x01ac - -#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG0 0x01b0 -#define SIRFSOC_CLKC_SHARED_DIVIDER_CFG1 0x01b4 -#define SIRFSOC_CLKC_SHARED_DIVIDER_ENA 0x01b8 - -#define SIRFSOC_CLKC_SYS_CLK_SEL 0x01bc -#define SIRFSOC_CLKC_SYS_CLK_SEL_STAT 0x01c0 -#define SIRFSOC_CLKC_IO_CLK_SEL 0x01c4 -#define SIRFSOC_CLKC_IO_CLK_SEL_STAT 0x01c8 -#define SIRFSOC_CLKC_G2D_CLK_SEL 0x01cc -#define SIRFSOC_CLKC_G2D_CLK_SEL_STAT 0x01d0 -#define SIRFSOC_CLKC_JPENC_CLK_SEL 0x01d4 -#define SIRFSOC_CLKC_JPENC_CLK_SEL_STAT 0x01d8 -#define SIRFSOC_CLKC_VDEC_CLK_SEL 0x01dc -#define SIRFSOC_CLKC_VDEC_CLK_SEL_STAT 0x01e0 -#define SIRFSOC_CLKC_GMAC_CLK_SEL 0x01e4 -#define SIRFSOC_CLKC_GMAC_CLK_SEL_STAT 0x01e8 -#define SIRFSOC_CLKC_USB_CLK_SEL 0x01ec -#define SIRFSOC_CLKC_USB_CLK_SEL_STAT 0x01f0 -#define SIRFSOC_CLKC_KAS_CLK_SEL 0x01f4 -#define SIRFSOC_CLKC_KAS_CLK_SEL_STAT 0x01f8 -#define SIRFSOC_CLKC_SEC_CLK_SEL 0x01fc -#define SIRFSOC_CLKC_SEC_CLK_SEL_STAT 0x0200 -#define SIRFSOC_CLKC_SDR_CLK_SEL 0x0204 -#define SIRFSOC_CLKC_SDR_CLK_SEL_STAT 0x0208 -#define SIRFSOC_CLKC_VIP_CLK_SEL 0x020c -#define SIRFSOC_CLKC_VIP_CLK_SEL_STAT 0x0210 -#define SIRFSOC_CLKC_NOCD_CLK_SEL 0x0214 -#define SIRFSOC_CLKC_NOCD_CLK_SEL_STAT 0x0218 -#define SIRFSOC_CLKC_NOCR_CLK_SEL 0x021c -#define SIRFSOC_CLKC_NOCR_CLK_SEL_STAT 0x0220 -#define SIRFSOC_CLKC_TPIU_CLK_SEL 0x0224 -#define SIRFSOC_CLKC_TPIU_CLK_SEL_STAT 0x0228 - -#define SIRFSOC_CLKC_ROOT_CLK_EN0_SET 0x022c -#define SIRFSOC_CLKC_ROOT_CLK_EN0_CLR 0x0230 -#define SIRFSOC_CLKC_ROOT_CLK_EN0_STAT 0x0234 -#define SIRFSOC_CLKC_ROOT_CLK_EN1_SET 0x0238 -#define SIRFSOC_CLKC_ROOT_CLK_EN1_CLR 0x023c -#define SIRFSOC_CLKC_ROOT_CLK_EN1_STAT 0x0240 - -#define SIRFSOC_CLKC_LEAF_CLK_EN0_SET 0x0244 -#define SIRFSOC_CLKC_LEAF_CLK_EN0_CLR 0x0248 -#define SIRFSOC_CLKC_LEAF_CLK_EN0_STAT 0x024c - -#define SIRFSOC_CLKC_RSTC_A7_SW_RST 0x0308 - -#define SIRFSOC_CLKC_LEAF_CLK_EN1_SET 0x04a0 -#define SIRFSOC_CLKC_LEAF_CLK_EN2_SET 0x04b8 -#define SIRFSOC_CLKC_LEAF_CLK_EN3_SET 0x04d0 -#define SIRFSOC_CLKC_LEAF_CLK_EN4_SET 0x04e8 -#define SIRFSOC_CLKC_LEAF_CLK_EN5_SET 0x0500 -#define SIRFSOC_CLKC_LEAF_CLK_EN6_SET 0x0518 -#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET 0x0530 -#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET 0x0548 - -#define SIRFSOC_NOC_CLK_IDLEREQ_SET 0x02D0 -#define SIRFSOC_NOC_CLK_IDLEREQ_CLR 0x02D4 -#define SIRFSOC_NOC_CLK_SLVRDY_SET 0x02E8 -#define SIRFSOC_NOC_CLK_SLVRDY_CLR 0x02EC -#define SIRFSOC_NOC_CLK_IDLE_STATUS 0x02F4 - -struct clk_pll { - struct clk_hw hw; - u16 regofs; /* register offset */ -}; -#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) - -struct clk_dto { - struct clk_hw hw; - u16 inc_offset; /* dto increment offset */ - u16 src_offset; /* dto src offset */ -}; -#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw) - -enum clk_unit_type { - CLK_UNIT_NOC_OTHER, - CLK_UNIT_NOC_CLOCK, - CLK_UNIT_NOC_SOCKET, -}; - -struct clk_unit { - struct clk_hw hw; - u16 regofs; - u16 bit; - u32 type; - u8 idle_bit; - spinlock_t *lock; -}; -#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw) - -struct atlas7_div_init_data { - const char *div_name; - const char *parent_name; - const char *gate_name; - unsigned long flags; - u8 divider_flags; - u8 gate_flags; - u32 div_offset; - u8 shift; - u8 width; - u32 gate_offset; - u8 gate_bit; - spinlock_t *lock; -}; - -struct atlas7_mux_init_data { - const char *mux_name; - const char * const *parent_names; - u8 parent_num; - unsigned long flags; - u8 mux_flags; - u32 mux_offset; - u8 shift; - u8 width; -}; - -struct atlas7_unit_init_data { - u32 index; - const char *unit_name; - const char *parent_name; - unsigned long flags; - u32 regofs; - u8 bit; - u32 type; - u8 idle_bit; - spinlock_t *lock; -}; - -struct atlas7_reset_desc { - const char *name; - u32 clk_ofs; - u8 clk_bit; - u32 rst_ofs; - u8 rst_bit; - spinlock_t *lock; -}; - -static void __iomem *sirfsoc_clk_vbase; -static struct clk_onecell_data clk_data; - -static const struct clk_div_table pll_div_table[] = { - { .val = 0, .div = 1 }, - { .val = 1, .div = 2 }, - { .val = 2, .div = 4 }, - { .val = 3, .div = 8 }, - { .val = 4, .div = 16 }, - { .val = 5, .div = 32 }, -}; - -static DEFINE_SPINLOCK(cpupll_ctrl1_lock); -static DEFINE_SPINLOCK(mempll_ctrl1_lock); -static DEFINE_SPINLOCK(sys0pll_ctrl1_lock); -static DEFINE_SPINLOCK(sys1pll_ctrl1_lock); -static DEFINE_SPINLOCK(sys2pll_ctrl1_lock); -static DEFINE_SPINLOCK(sys3pll_ctrl1_lock); -static DEFINE_SPINLOCK(usbphy_div_lock); -static DEFINE_SPINLOCK(btss_div_lock); -static DEFINE_SPINLOCK(rgmii_div_lock); -static DEFINE_SPINLOCK(cpu_div_lock); -static DEFINE_SPINLOCK(sdphy01_div_lock); -static DEFINE_SPINLOCK(sdphy23_div_lock); -static DEFINE_SPINLOCK(sdphy45_div_lock); -static DEFINE_SPINLOCK(sdphy67_div_lock); -static DEFINE_SPINLOCK(can_div_lock); -static DEFINE_SPINLOCK(deint_div_lock); -static DEFINE_SPINLOCK(nand_div_lock); -static DEFINE_SPINLOCK(disp0_div_lock); -static DEFINE_SPINLOCK(disp1_div_lock); -static DEFINE_SPINLOCK(gpu_div_lock); -static DEFINE_SPINLOCK(gnss_div_lock); -/* gate register shared */ -static DEFINE_SPINLOCK(share_div_lock); -static DEFINE_SPINLOCK(root0_gate_lock); -static DEFINE_SPINLOCK(root1_gate_lock); -static DEFINE_SPINLOCK(leaf0_gate_lock); -static DEFINE_SPINLOCK(leaf1_gate_lock); -static DEFINE_SPINLOCK(leaf2_gate_lock); -static DEFINE_SPINLOCK(leaf3_gate_lock); -static DEFINE_SPINLOCK(leaf4_gate_lock); -static DEFINE_SPINLOCK(leaf5_gate_lock); -static DEFINE_SPINLOCK(leaf6_gate_lock); -static DEFINE_SPINLOCK(leaf7_gate_lock); -static DEFINE_SPINLOCK(leaf8_gate_lock); - -static inline unsigned long clkc_readl(unsigned reg) -{ - return readl(sirfsoc_clk_vbase + reg); -} - -static inline void clkc_writel(u32 val, unsigned reg) -{ - writel(val, sirfsoc_clk_vbase + reg); -} - -/* -* ABPLL -* integer mode: Fvco = Fin * 2 * NF / NR -* Spread Spectrum mode: Fvco = Fin * SSN / NR -* SSN = 2^24 / (256 * ((ssdiv >> ssdepth) << ssdepth) + (ssmod << ssdepth)) -*/ -static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long fin = parent_rate; - struct clk_pll *clk = to_pllclk(hw); - u64 rate; - u32 regctrl0 = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_CTRL0 - - SIRFSOC_CLKC_MEMPLL_AB_FREQ); - u32 regfreq = clkc_readl(clk->regofs); - u32 regssc = clkc_readl(clk->regofs + SIRFSOC_CLKC_MEMPLL_AB_SSC - - SIRFSOC_CLKC_MEMPLL_AB_FREQ); - u32 nr = (regfreq >> 16 & (BIT(3) - 1)) + 1; - u32 nf = (regfreq & (BIT(9) - 1)) + 1; - u32 ssdiv = regssc >> 8 & (BIT(12) - 1); - u32 ssdepth = regssc >> 20 & (BIT(2) - 1); - u32 ssmod = regssc & (BIT(8) - 1); - - if (regctrl0 & SIRFSOC_ABPLL_CTRL0_BYPASS) - return fin; - - if (regctrl0 & SIRFSOC_ABPLL_CTRL0_SSEN) { - rate = fin; - rate *= 1 << 24; - do_div(rate, nr); - do_div(rate, (256 * ((ssdiv >> ssdepth) << ssdepth) - + (ssmod << ssdepth))); - } else { - rate = 2 * fin; - rate *= nf; - do_div(rate, nr); - } - return rate; -} - -static const struct clk_ops ab_pll_ops = { - .recalc_rate = pll_clk_recalc_rate, -}; - -static const char * const pll_clk_parents[] = { - "xin", -}; - -static const struct clk_init_data clk_cpupll_init = { - .name = "cpupll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_cpupll = { - .regofs = SIRFSOC_CLKC_CPUPLL_AB_FREQ, - .hw = { - .init = &clk_cpupll_init, - }, -}; - -static const struct clk_init_data clk_mempll_init = { - .name = "mempll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_mempll = { - .regofs = SIRFSOC_CLKC_MEMPLL_AB_FREQ, - .hw = { - .init = &clk_mempll_init, - }, -}; - -static const struct clk_init_data clk_sys0pll_init = { - .name = "sys0pll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_sys0pll = { - .regofs = SIRFSOC_CLKC_SYS0PLL_AB_FREQ, - .hw = { - .init = &clk_sys0pll_init, - }, -}; - -static const struct clk_init_data clk_sys1pll_init = { - .name = "sys1pll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_sys1pll = { - .regofs = SIRFSOC_CLKC_SYS1PLL_AB_FREQ, - .hw = { - .init = &clk_sys1pll_init, - }, -}; - -static const struct clk_init_data clk_sys2pll_init = { - .name = "sys2pll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_sys2pll = { - .regofs = SIRFSOC_CLKC_SYS2PLL_AB_FREQ, - .hw = { - .init = &clk_sys2pll_init, - }, -}; - -static const struct clk_init_data clk_sys3pll_init = { - .name = "sys3pll_vco", - .ops = &ab_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_sys3pll = { - .regofs = SIRFSOC_CLKC_SYS3PLL_AB_FREQ, - .hw = { - .init = &clk_sys3pll_init, - }, -}; - -/* - * DTO in clkc, default enable double resolution mode - * double resolution mode:fout = fin * finc / 2^29 - * normal mode:fout = fin * finc / 2^28 - */ -#define DTO_RESL_DOUBLE (1ULL << 29) -#define DTO_RESL_NORMAL (1ULL << 28) - -static int dto_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_dto *clk = to_dtoclk(hw); - int reg; - - reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC; - - return !!(clkc_readl(reg) & BIT(0)); -} - -static int dto_clk_enable(struct clk_hw *hw) -{ - u32 val, reg; - struct clk_dto *clk = to_dtoclk(hw); - - reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC; - - val = clkc_readl(reg) | BIT(0); - clkc_writel(val, reg); - return 0; -} - -static void dto_clk_disable(struct clk_hw *hw) -{ - u32 val, reg; - struct clk_dto *clk = to_dtoclk(hw); - - reg = clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_ENA - SIRFSOC_CLKC_AUDIO_DTO_SRC; - - val = clkc_readl(reg) & ~BIT(0); - clkc_writel(val, reg); -} - -static unsigned long dto_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - u64 rate = parent_rate; - struct clk_dto *clk = to_dtoclk(hw); - u32 finc = clkc_readl(clk->inc_offset); - u32 droff = clkc_readl(clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC); - - rate *= finc; - if (droff & BIT(0)) - /* Double resolution off */ - do_div(rate, DTO_RESL_NORMAL); - else - do_div(rate, DTO_RESL_DOUBLE); - - return rate; -} - -static long dto_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - u64 dividend = rate * DTO_RESL_DOUBLE; - - do_div(dividend, *parent_rate); - dividend *= *parent_rate; - do_div(dividend, DTO_RESL_DOUBLE); - - return dividend; -} - -static int dto_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - u64 dividend = rate * DTO_RESL_DOUBLE; - struct clk_dto *clk = to_dtoclk(hw); - - do_div(dividend, parent_rate); - clkc_writel(0, clk->src_offset + SIRFSOC_CLKC_AUDIO_DTO_DROFF - SIRFSOC_CLKC_AUDIO_DTO_SRC); - clkc_writel(dividend, clk->inc_offset); - - return 0; -} - -static u8 dto_clk_get_parent(struct clk_hw *hw) -{ - struct clk_dto *clk = to_dtoclk(hw); - - return clkc_readl(clk->src_offset); -} - -/* - * dto need CLK_SET_PARENT_GATE - */ -static int dto_clk_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_dto *clk = to_dtoclk(hw); - - clkc_writel(index, clk->src_offset); - return 0; -} - -static const struct clk_ops dto_ops = { - .is_enabled = dto_clk_is_enabled, - .enable = dto_clk_enable, - .disable = dto_clk_disable, - .recalc_rate = dto_clk_recalc_rate, - .round_rate = dto_clk_round_rate, - .set_rate = dto_clk_set_rate, - .get_parent = dto_clk_get_parent, - .set_parent = dto_clk_set_parent, -}; - -/* dto parent clock as syspllvco/clk1 */ -static const char * const audiodto_clk_parents[] = { - "sys0pll_clk1", - "sys1pll_clk1", - "sys3pll_clk1", -}; - -static const struct clk_init_data clk_audiodto_init = { - .name = "audio_dto", - .ops = &dto_ops, - .parent_names = audiodto_clk_parents, - .num_parents = ARRAY_SIZE(audiodto_clk_parents), -}; - -static struct clk_dto clk_audio_dto = { - .inc_offset = SIRFSOC_CLKC_AUDIO_DTO_INC, - .src_offset = SIRFSOC_CLKC_AUDIO_DTO_SRC, - .hw = { - .init = &clk_audiodto_init, - }, -}; - -static const char * const disp0dto_clk_parents[] = { - "sys0pll_clk1", - "sys1pll_clk1", - "sys3pll_clk1", -}; - -static const struct clk_init_data clk_disp0dto_init = { - .name = "disp0_dto", - .ops = &dto_ops, - .parent_names = disp0dto_clk_parents, - .num_parents = ARRAY_SIZE(disp0dto_clk_parents), -}; - -static struct clk_dto clk_disp0_dto = { - .inc_offset = SIRFSOC_CLKC_DISP0_DTO_INC, - .src_offset = SIRFSOC_CLKC_DISP0_DTO_SRC, - .hw = { - .init = &clk_disp0dto_init, - }, -}; - -static const char * const disp1dto_clk_parents[] = { - "sys0pll_clk1", - "sys1pll_clk1", - "sys3pll_clk1", -}; - -static const struct clk_init_data clk_disp1dto_init = { - .name = "disp1_dto", - .ops = &dto_ops, - .parent_names = disp1dto_clk_parents, - .num_parents = ARRAY_SIZE(disp1dto_clk_parents), -}; - -static struct clk_dto clk_disp1_dto = { - .inc_offset = SIRFSOC_CLKC_DISP1_DTO_INC, - .src_offset = SIRFSOC_CLKC_DISP1_DTO_SRC, - .hw = { - .init = &clk_disp1dto_init, - }, -}; - -static struct atlas7_div_init_data divider_list[] __initdata = { - /* div_name, parent_name, gate_name, clk_flag, divider_flag, gate_flag, div_offset, shift, wdith, gate_offset, bit_enable, lock */ - { "sys0pll_qa1", "sys0pll_fixdiv", "sys0pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 0, &usbphy_div_lock }, - { "sys1pll_qa1", "sys1pll_fixdiv", "sys1pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 4, &usbphy_div_lock }, - { "sys2pll_qa1", "sys2pll_fixdiv", "sys2pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 8, &usbphy_div_lock }, - { "sys3pll_qa1", "sys3pll_fixdiv", "sys3pll_a1", 0, 0, 0, SIRFSOC_CLKC_USBPHY_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_USBPHY_CLKDIV_ENA, 12, &usbphy_div_lock }, - { "sys0pll_qa2", "sys0pll_fixdiv", "sys0pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 0, &btss_div_lock }, - { "sys1pll_qa2", "sys1pll_fixdiv", "sys1pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 4, &btss_div_lock }, - { "sys2pll_qa2", "sys2pll_fixdiv", "sys2pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 8, &btss_div_lock }, - { "sys3pll_qa2", "sys3pll_fixdiv", "sys3pll_a2", 0, 0, 0, SIRFSOC_CLKC_BTSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_BTSS_CLKDIV_ENA, 12, &btss_div_lock }, - { "sys0pll_qa3", "sys0pll_fixdiv", "sys0pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 0, &rgmii_div_lock }, - { "sys1pll_qa3", "sys1pll_fixdiv", "sys1pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 4, &rgmii_div_lock }, - { "sys2pll_qa3", "sys2pll_fixdiv", "sys2pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 8, &rgmii_div_lock }, - { "sys3pll_qa3", "sys3pll_fixdiv", "sys3pll_a3", 0, 0, 0, SIRFSOC_CLKC_RGMII_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_RGMII_CLKDIV_ENA, 12, &rgmii_div_lock }, - { "sys0pll_qa4", "sys0pll_fixdiv", "sys0pll_a4", 0, 0, 0, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 0, &cpu_div_lock }, - { "sys1pll_qa4", "sys1pll_fixdiv", "sys1pll_a4", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_CPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CPU_CLKDIV_ENA, 4, &cpu_div_lock }, - { "sys0pll_qa5", "sys0pll_fixdiv", "sys0pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 0, &sdphy01_div_lock }, - { "sys1pll_qa5", "sys1pll_fixdiv", "sys1pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 4, &sdphy01_div_lock }, - { "sys2pll_qa5", "sys2pll_fixdiv", "sys2pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 8, &sdphy01_div_lock }, - { "sys3pll_qa5", "sys3pll_fixdiv", "sys3pll_a5", 0, 0, 0, SIRFSOC_CLKC_SDPHY01_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY01_CLKDIV_ENA, 12, &sdphy01_div_lock }, - { "sys0pll_qa6", "sys0pll_fixdiv", "sys0pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 0, &sdphy23_div_lock }, - { "sys1pll_qa6", "sys1pll_fixdiv", "sys1pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 4, &sdphy23_div_lock }, - { "sys2pll_qa6", "sys2pll_fixdiv", "sys2pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 8, &sdphy23_div_lock }, - { "sys3pll_qa6", "sys3pll_fixdiv", "sys3pll_a6", 0, 0, 0, SIRFSOC_CLKC_SDPHY23_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY23_CLKDIV_ENA, 12, &sdphy23_div_lock }, - { "sys0pll_qa7", "sys0pll_fixdiv", "sys0pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 0, &sdphy45_div_lock }, - { "sys1pll_qa7", "sys1pll_fixdiv", "sys1pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 4, &sdphy45_div_lock }, - { "sys2pll_qa7", "sys2pll_fixdiv", "sys2pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 8, &sdphy45_div_lock }, - { "sys3pll_qa7", "sys3pll_fixdiv", "sys3pll_a7", 0, 0, 0, SIRFSOC_CLKC_SDPHY45_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY45_CLKDIV_ENA, 12, &sdphy45_div_lock }, - { "sys0pll_qa8", "sys0pll_fixdiv", "sys0pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 0, &sdphy67_div_lock }, - { "sys1pll_qa8", "sys1pll_fixdiv", "sys1pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 4, &sdphy67_div_lock }, - { "sys2pll_qa8", "sys2pll_fixdiv", "sys2pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 8, &sdphy67_div_lock }, - { "sys3pll_qa8", "sys3pll_fixdiv", "sys3pll_a8", 0, 0, 0, SIRFSOC_CLKC_SDPHY67_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_SDPHY67_CLKDIV_ENA, 12, &sdphy67_div_lock }, - { "sys0pll_qa9", "sys0pll_fixdiv", "sys0pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 0, &can_div_lock }, - { "sys1pll_qa9", "sys1pll_fixdiv", "sys1pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 4, &can_div_lock }, - { "sys2pll_qa9", "sys2pll_fixdiv", "sys2pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 8, &can_div_lock }, - { "sys3pll_qa9", "sys3pll_fixdiv", "sys3pll_a9", 0, 0, 0, SIRFSOC_CLKC_CAN_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_CAN_CLKDIV_ENA, 12, &can_div_lock }, - { "sys0pll_qa10", "sys0pll_fixdiv", "sys0pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 0, &deint_div_lock }, - { "sys1pll_qa10", "sys1pll_fixdiv", "sys1pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 4, &deint_div_lock }, - { "sys2pll_qa10", "sys2pll_fixdiv", "sys2pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 8, &deint_div_lock }, - { "sys3pll_qa10", "sys3pll_fixdiv", "sys3pll_a10", 0, 0, 0, SIRFSOC_CLKC_DEINT_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DEINT_CLKDIV_ENA, 12, &deint_div_lock }, - { "sys0pll_qa11", "sys0pll_fixdiv", "sys0pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 0, &nand_div_lock }, - { "sys1pll_qa11", "sys1pll_fixdiv", "sys1pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 4, &nand_div_lock }, - { "sys2pll_qa11", "sys2pll_fixdiv", "sys2pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 8, &nand_div_lock }, - { "sys3pll_qa11", "sys3pll_fixdiv", "sys3pll_a11", 0, 0, 0, SIRFSOC_CLKC_NAND_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_NAND_CLKDIV_ENA, 12, &nand_div_lock }, - { "sys0pll_qa12", "sys0pll_fixdiv", "sys0pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 0, &disp0_div_lock }, - { "sys1pll_qa12", "sys1pll_fixdiv", "sys1pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 4, &disp0_div_lock }, - { "sys2pll_qa12", "sys2pll_fixdiv", "sys2pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 8, &disp0_div_lock }, - { "sys3pll_qa12", "sys3pll_fixdiv", "sys3pll_a12", 0, 0, 0, SIRFSOC_CLKC_DISP0_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP0_CLKDIV_ENA, 12, &disp0_div_lock }, - { "sys0pll_qa13", "sys0pll_fixdiv", "sys0pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 0, &disp1_div_lock }, - { "sys1pll_qa13", "sys1pll_fixdiv", "sys1pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 4, &disp1_div_lock }, - { "sys2pll_qa13", "sys2pll_fixdiv", "sys2pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 8, &disp1_div_lock }, - { "sys3pll_qa13", "sys3pll_fixdiv", "sys3pll_a13", 0, 0, 0, SIRFSOC_CLKC_DISP1_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_DISP1_CLKDIV_ENA, 12, &disp1_div_lock }, - { "sys0pll_qa14", "sys0pll_fixdiv", "sys0pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 0, &gpu_div_lock }, - { "sys1pll_qa14", "sys1pll_fixdiv", "sys1pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 4, &gpu_div_lock }, - { "sys2pll_qa14", "sys2pll_fixdiv", "sys2pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 8, &gpu_div_lock }, - { "sys3pll_qa14", "sys3pll_fixdiv", "sys3pll_a14", 0, 0, 0, SIRFSOC_CLKC_GPU_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GPU_CLKDIV_ENA, 12, &gpu_div_lock }, - { "sys0pll_qa15", "sys0pll_fixdiv", "sys0pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 0, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 0, &gnss_div_lock }, - { "sys1pll_qa15", "sys1pll_fixdiv", "sys1pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 8, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 4, &gnss_div_lock }, - { "sys2pll_qa15", "sys2pll_fixdiv", "sys2pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 16, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 8, &gnss_div_lock }, - { "sys3pll_qa15", "sys3pll_fixdiv", "sys3pll_a15", 0, 0, 0, SIRFSOC_CLKC_GNSS_CLKDIV_CFG, 24, 6, SIRFSOC_CLKC_GNSS_CLKDIV_ENA, 12, &gnss_div_lock }, - { "sys1pll_qa18", "sys1pll_fixdiv", "sys1pll_a18", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 24, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 12, &share_div_lock }, - { "sys1pll_qa19", "sys1pll_fixdiv", "sys1pll_a19", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 16, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 8, &share_div_lock }, - { "sys1pll_qa20", "sys1pll_fixdiv", "sys1pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 4, &share_div_lock }, - { "sys2pll_qa20", "sys2pll_fixdiv", "sys2pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG0, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 0, &share_div_lock }, - { "sys1pll_qa17", "sys1pll_fixdiv", "sys1pll_a17", 0, 0, CLK_IGNORE_UNUSED, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 8, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 20, &share_div_lock }, - { "sys0pll_qa20", "sys0pll_fixdiv", "sys0pll_a20", 0, 0, 0, SIRFSOC_CLKC_SHARED_DIVIDER_CFG1, 0, 6, SIRFSOC_CLKC_SHARED_DIVIDER_ENA, 16, &share_div_lock }, -}; - -static const char * const i2s_clk_parents[] = { - "xin", - "xinw", - "audio_dto", - /* "pwm_i2s01" */ -}; - -static const char * const usbphy_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a1", - "sys1pll_a1", - "sys2pll_a1", - "sys3pll_a1", -}; - -static const char * const btss_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a2", - "sys1pll_a2", - "sys2pll_a2", - "sys3pll_a2", -}; - -static const char * const rgmii_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a3", - "sys1pll_a3", - "sys2pll_a3", - "sys3pll_a3", -}; - -static const char * const cpu_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a4", - "sys1pll_a4", - "cpupll_clk1", -}; - -static const char * const sdphy01_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a5", - "sys1pll_a5", - "sys2pll_a5", - "sys3pll_a5", -}; - -static const char * const sdphy23_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a6", - "sys1pll_a6", - "sys2pll_a6", - "sys3pll_a6", -}; - -static const char * const sdphy45_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a7", - "sys1pll_a7", - "sys2pll_a7", - "sys3pll_a7", -}; - -static const char * const sdphy67_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a8", - "sys1pll_a8", - "sys2pll_a8", - "sys3pll_a8", -}; - -static const char * const can_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a9", - "sys1pll_a9", - "sys2pll_a9", - "sys3pll_a9", -}; - -static const char * const deint_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a10", - "sys1pll_a10", - "sys2pll_a10", - "sys3pll_a10", -}; - -static const char * const nand_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a11", - "sys1pll_a11", - "sys2pll_a11", - "sys3pll_a11", -}; - -static const char * const disp0_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a12", - "sys1pll_a12", - "sys2pll_a12", - "sys3pll_a12", - "disp0_dto", -}; - -static const char * const disp1_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a13", - "sys1pll_a13", - "sys2pll_a13", - "sys3pll_a13", - "disp1_dto", -}; - -static const char * const gpu_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a14", - "sys1pll_a14", - "sys2pll_a14", - "sys3pll_a14", -}; - -static const char * const gnss_clk_parents[] = { - "xin", - "xinw", - "sys0pll_a15", - "sys1pll_a15", - "sys2pll_a15", - "sys3pll_a15", -}; - -static const char * const sys_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const io_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const g2d_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const jpenc_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const vdec_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const gmac_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const usb_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const kas_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const sec_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const sdr_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const vip_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const nocd_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const nocr_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static const char * const tpiu_clk_parents[] = { - "xin", - "xinw", - "sys2pll_a20", - "sys1pll_a20", - "sys1pll_a19", - "sys1pll_a18", - "sys0pll_a20", - "sys1pll_a17", -}; - -static struct atlas7_mux_init_data mux_list[] __initdata = { - /* mux_name, parent_names, parent_num, flags, mux_flags, mux_offset, shift, width */ - { "i2s_mux", i2s_clk_parents, ARRAY_SIZE(i2s_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 2 }, - { "usbphy_mux", usbphy_clk_parents, ARRAY_SIZE(usbphy_clk_parents), 0, 0, SIRFSOC_CLKC_I2S_CLK_SEL, 0, 3 }, - { "btss_mux", btss_clk_parents, ARRAY_SIZE(btss_clk_parents), 0, 0, SIRFSOC_CLKC_BTSS_CLK_SEL, 0, 3 }, - { "rgmii_mux", rgmii_clk_parents, ARRAY_SIZE(rgmii_clk_parents), 0, 0, SIRFSOC_CLKC_RGMII_CLK_SEL, 0, 3 }, - { "cpu_mux", cpu_clk_parents, ARRAY_SIZE(cpu_clk_parents), 0, 0, SIRFSOC_CLKC_CPU_CLK_SEL, 0, 3 }, - { "sdphy01_mux", sdphy01_clk_parents, ARRAY_SIZE(sdphy01_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY01_CLK_SEL, 0, 3 }, - { "sdphy23_mux", sdphy23_clk_parents, ARRAY_SIZE(sdphy23_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY23_CLK_SEL, 0, 3 }, - { "sdphy45_mux", sdphy45_clk_parents, ARRAY_SIZE(sdphy45_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY45_CLK_SEL, 0, 3 }, - { "sdphy67_mux", sdphy67_clk_parents, ARRAY_SIZE(sdphy67_clk_parents), 0, 0, SIRFSOC_CLKC_SDPHY67_CLK_SEL, 0, 3 }, - { "can_mux", can_clk_parents, ARRAY_SIZE(can_clk_parents), 0, 0, SIRFSOC_CLKC_CAN_CLK_SEL, 0, 3 }, - { "deint_mux", deint_clk_parents, ARRAY_SIZE(deint_clk_parents), 0, 0, SIRFSOC_CLKC_DEINT_CLK_SEL, 0, 3 }, - { "nand_mux", nand_clk_parents, ARRAY_SIZE(nand_clk_parents), 0, 0, SIRFSOC_CLKC_NAND_CLK_SEL, 0, 3 }, - { "disp0_mux", disp0_clk_parents, ARRAY_SIZE(disp0_clk_parents), 0, 0, SIRFSOC_CLKC_DISP0_CLK_SEL, 0, 3 }, - { "disp1_mux", disp1_clk_parents, ARRAY_SIZE(disp1_clk_parents), 0, 0, SIRFSOC_CLKC_DISP1_CLK_SEL, 0, 3 }, - { "gpu_mux", gpu_clk_parents, ARRAY_SIZE(gpu_clk_parents), 0, 0, SIRFSOC_CLKC_GPU_CLK_SEL, 0, 3 }, - { "gnss_mux", gnss_clk_parents, ARRAY_SIZE(gnss_clk_parents), 0, 0, SIRFSOC_CLKC_GNSS_CLK_SEL, 0, 3 }, - { "sys_mux", sys_clk_parents, ARRAY_SIZE(sys_clk_parents), 0, 0, SIRFSOC_CLKC_SYS_CLK_SEL, 0, 3 }, - { "io_mux", io_clk_parents, ARRAY_SIZE(io_clk_parents), 0, 0, SIRFSOC_CLKC_IO_CLK_SEL, 0, 3 }, - { "g2d_mux", g2d_clk_parents, ARRAY_SIZE(g2d_clk_parents), 0, 0, SIRFSOC_CLKC_G2D_CLK_SEL, 0, 3 }, - { "jpenc_mux", jpenc_clk_parents, ARRAY_SIZE(jpenc_clk_parents), 0, 0, SIRFSOC_CLKC_JPENC_CLK_SEL, 0, 3 }, - { "vdec_mux", vdec_clk_parents, ARRAY_SIZE(vdec_clk_parents), 0, 0, SIRFSOC_CLKC_VDEC_CLK_SEL, 0, 3 }, - { "gmac_mux", gmac_clk_parents, ARRAY_SIZE(gmac_clk_parents), 0, 0, SIRFSOC_CLKC_GMAC_CLK_SEL, 0, 3 }, - { "usb_mux", usb_clk_parents, ARRAY_SIZE(usb_clk_parents), 0, 0, SIRFSOC_CLKC_USB_CLK_SEL, 0, 3 }, - { "kas_mux", kas_clk_parents, ARRAY_SIZE(kas_clk_parents), 0, 0, SIRFSOC_CLKC_KAS_CLK_SEL, 0, 3 }, - { "sec_mux", sec_clk_parents, ARRAY_SIZE(sec_clk_parents), 0, 0, SIRFSOC_CLKC_SEC_CLK_SEL, 0, 3 }, - { "sdr_mux", sdr_clk_parents, ARRAY_SIZE(sdr_clk_parents), 0, 0, SIRFSOC_CLKC_SDR_CLK_SEL, 0, 3 }, - { "vip_mux", vip_clk_parents, ARRAY_SIZE(vip_clk_parents), 0, 0, SIRFSOC_CLKC_VIP_CLK_SEL, 0, 3 }, - { "nocd_mux", nocd_clk_parents, ARRAY_SIZE(nocd_clk_parents), 0, 0, SIRFSOC_CLKC_NOCD_CLK_SEL, 0, 3 }, - { "nocr_mux", nocr_clk_parents, ARRAY_SIZE(nocr_clk_parents), 0, 0, SIRFSOC_CLKC_NOCR_CLK_SEL, 0, 3 }, - { "tpiu_mux", tpiu_clk_parents, ARRAY_SIZE(tpiu_clk_parents), 0, 0, SIRFSOC_CLKC_TPIU_CLK_SEL, 0, 3 }, -}; - - /* new unit should add start from the tail of list */ -static struct atlas7_unit_init_data unit_list[] __initdata = { - /* unit_name, parent_name, flags, regofs, bit, lock */ - { 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, 0, 0, &root0_gate_lock }, - { 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, 0, 0, &root0_gate_lock }, - { 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, 0, 0, &root0_gate_lock }, - { 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, 0, 0, &root0_gate_lock }, - { 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, 0, 0, &root0_gate_lock }, - { 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, 0, 0, &root0_gate_lock }, - { 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, 0, 0, &root0_gate_lock }, - { 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, 0, 0, &root0_gate_lock }, - { 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, 0, 0, &root0_gate_lock }, - { 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, 0, 0, &root0_gate_lock }, - { 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, 0, 0, &root0_gate_lock }, - { 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, 0, 0, &root0_gate_lock }, - { 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, 0, 0, &root0_gate_lock }, - { 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, 0, 0, &root0_gate_lock }, - { 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, 0, 0, &root0_gate_lock }, - { 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, 0, 0, &root0_gate_lock }, - { 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, 0, 0, &root0_gate_lock }, - { 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, 0, 0, &root0_gate_lock }, - { 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, 0, 0, &root0_gate_lock }, - { 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, 0, 0, &root0_gate_lock }, - { 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, 0, 0, &root0_gate_lock }, - { 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, 0, 0, &root0_gate_lock }, - { 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, 0, 0, &root0_gate_lock }, - { 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, 0, 0, &root1_gate_lock }, - { 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, 0, 0, &root1_gate_lock }, - { 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, 0, 0, &root1_gate_lock }, - { 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, 0, 0, &root1_gate_lock }, - { 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, 0, 0, &root1_gate_lock }, - { 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, 0, 0, &root1_gate_lock }, - { 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, 0, 0, &root1_gate_lock }, - { 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, 0, 0, &root1_gate_lock }, - { 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, 0, 0, &root1_gate_lock }, - { 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, 0, 0, &root1_gate_lock }, - { 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, 0, 0, &root1_gate_lock }, - { 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, 0, 0, &root1_gate_lock }, - { 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, 0, 0, &root1_gate_lock }, - { 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, 0, 0, &root1_gate_lock }, - { 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, 0, 0, &root1_gate_lock }, - { 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, 0, 0, &root1_gate_lock }, - { 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, 0, 0, &root1_gate_lock }, - { 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, 0, 0, &root1_gate_lock }, - { 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, 0, 0, &root1_gate_lock }, - { 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, 0, 0, &root1_gate_lock }, - { 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, 0, 0, &root1_gate_lock }, - { 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, 0, 0, &root1_gate_lock }, - { 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, 0, 0, &root1_gate_lock }, - { 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, CLK_UNIT_NOC_CLOCK, 4, &leaf1_gate_lock }, - { 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, 0, 0, &leaf1_gate_lock }, - { 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, 0, 0, &leaf1_gate_lock }, - { 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, 0, 0, &leaf1_gate_lock }, - { 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, 0, 0, &leaf1_gate_lock }, - { 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, 0, 0, &leaf1_gate_lock }, - { 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, 0, 0, &leaf1_gate_lock }, - { 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, CLK_UNIT_NOC_SOCKET, 7, &leaf1_gate_lock }, - { 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, CLK_UNIT_NOC_SOCKET, 8, &leaf1_gate_lock }, - { 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock }, - { 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, 0, 0, &leaf1_gate_lock }, - { 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, CLK_UNIT_NOC_SOCKET, 4, &leaf1_gate_lock }, - { 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, CLK_UNIT_NOC_SOCKET, 5, &leaf1_gate_lock }, - { 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, CLK_UNIT_NOC_SOCKET, 6, &leaf1_gate_lock }, - { 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, CLK_UNIT_NOC_SOCKET, 1, &leaf1_gate_lock }, - { 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, CLK_UNIT_NOC_SOCKET, 2, &leaf1_gate_lock }, - { 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, CLK_UNIT_NOC_SOCKET, 0, &leaf1_gate_lock }, - { 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock }, - { 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, 0, 0, &leaf1_gate_lock }, - { 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, 0, 0, &leaf1_gate_lock }, - { 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, CLK_UNIT_NOC_CLOCK, 20, &leaf2_gate_lock }, - { 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, 0, 0, &leaf2_gate_lock }, - { 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, 0, 0, &leaf2_gate_lock }, - { 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, 0, 0, &leaf2_gate_lock }, - { 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, 0, 0, &leaf2_gate_lock }, - { 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, 0, 0, &leaf2_gate_lock }, - { 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, 0, 0, &leaf2_gate_lock }, - { 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, 0, 0, &leaf2_gate_lock }, - { 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, CLK_UNIT_NOC_CLOCK, 21, &leaf2_gate_lock }, - { 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, 0, 0, &leaf2_gate_lock }, - { 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, 0, 0, &leaf2_gate_lock }, - { 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, 0, 0, &leaf2_gate_lock }, - { 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, CLK_UNIT_NOC_CLOCK, 22, &leaf2_gate_lock }, - { 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, CLK_UNIT_NOC_CLOCK, 18, &leaf2_gate_lock }, - { 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, CLK_UNIT_NOC_CLOCK, 23, &leaf2_gate_lock }, - { 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, CLK_UNIT_NOC_CLOCK, 19, &leaf2_gate_lock }, - { 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, CLK_UNIT_NOC_CLOCK, 17, &leaf2_gate_lock }, - { 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, 0, 0, &leaf2_gate_lock }, - { 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, 0, 0, &leaf2_gate_lock }, - { 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, 0, 0, &leaf2_gate_lock }, - { 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, 0, 0, &leaf3_gate_lock }, - { 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, CLK_UNIT_NOC_CLOCK, 10, &leaf3_gate_lock }, - { 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, CLK_UNIT_NOC_SOCKET, 14, &leaf3_gate_lock }, - { 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, CLK_UNIT_NOC_SOCKET, 11, &leaf3_gate_lock }, - { 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, CLK_UNIT_NOC_SOCKET, 13, &leaf3_gate_lock }, - { 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, CLK_UNIT_NOC_SOCKET, 15, &leaf3_gate_lock }, - { 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, CLK_UNIT_NOC_SOCKET, 16, &leaf3_gate_lock }, - { 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, CLK_UNIT_NOC_SOCKET, 17, &leaf3_gate_lock }, - { 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, CLK_UNIT_NOC_SOCKET, 18, &leaf3_gate_lock }, - { 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, CLK_UNIT_NOC_SOCKET, 12, &leaf3_gate_lock }, - { 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, 0, 0, &leaf3_gate_lock }, - { 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, CLK_UNIT_NOC_CLOCK, 7, &leaf3_gate_lock }, - { 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, CLK_UNIT_NOC_CLOCK, 9, &leaf3_gate_lock }, - { 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, CLK_UNIT_NOC_CLOCK, 8, &leaf3_gate_lock }, - { 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, 0, 0, &leaf3_gate_lock }, - { 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, 0, 0, &leaf3_gate_lock }, - { 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, CLK_UNIT_NOC_CLOCK, 3, &leaf4_gate_lock }, - { 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, CLK_UNIT_NOC_CLOCK, 1, &leaf4_gate_lock }, - { 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, CLK_UNIT_NOC_CLOCK, 12, &leaf4_gate_lock }, - { 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, CLK_UNIT_NOC_SOCKET, 21, &leaf4_gate_lock }, - { 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, CLK_UNIT_NOC_SOCKET, 20, &leaf4_gate_lock }, - { 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, CLK_UNIT_NOC_SOCKET, 19, &leaf4_gate_lock }, - { 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, 0, 0, &leaf4_gate_lock }, - { 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, 0, 0, &leaf4_gate_lock }, - { 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, CLK_UNIT_NOC_CLOCK, 13, &leaf4_gate_lock }, - { 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, 0, 0, &leaf4_gate_lock }, - { 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, CLK_UNIT_NOC_CLOCK, 14, &leaf4_gate_lock }, - { 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, CLK_UNIT_NOC_CLOCK, 15, &leaf4_gate_lock }, - { 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, CLK_UNIT_NOC_CLOCK, 16, &leaf4_gate_lock }, - { 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, 0, 0, &leaf4_gate_lock }, - { 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, 0, 0, &leaf4_gate_lock }, - { 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, 0, 0, &leaf4_gate_lock }, - { 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, 0, 0, &leaf5_gate_lock }, - { 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, 0, 0, &leaf5_gate_lock }, - { 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, 0, 0, &leaf5_gate_lock }, - { 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, 0, 0, &leaf5_gate_lock }, - { 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, CLK_UNIT_NOC_SOCKET, 9, &leaf6_gate_lock }, - { 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, CLK_UNIT_NOC_SOCKET, 10, &leaf6_gate_lock }, - { 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, 0, 0, &leaf6_gate_lock }, - { 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, 0, 0, &leaf6_gate_lock }, - { 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, CLK_UNIT_NOC_CLOCK, 0, &leaf7_gate_lock }, - { 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, CLK_UNIT_NOC_CLOCK, 11, &leaf7_gate_lock }, - { 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, 0, 0, &leaf7_gate_lock }, - { 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, 0, 0, &leaf8_gate_lock }, - { 130, "dmac4_io", "a7ca_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, 0, 0, &leaf8_gate_lock }, - { 131, "uart6_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, 0, 0, &leaf8_gate_lock }, - { 132, "usp3_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, 0, 0, &leaf8_gate_lock }, - { 133, "a7ca_io", "noc_btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, 0, 0, &leaf8_gate_lock }, - { 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, 0, 0, &leaf8_gate_lock }, - { 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, 0, 0, &leaf8_gate_lock }, - { 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, 0, 0, &root1_gate_lock }, - { 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, 0, 0, &leaf8_gate_lock }, - { 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, 0, 0, &leaf0_gate_lock }, - { 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, 0, 0, &leaf0_gate_lock }, - { 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, 0, 0, &leaf0_gate_lock }, - { 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, 0, 0, &leaf0_gate_lock }, -}; - -static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)]; - -static int unit_clk_is_enabled(struct clk_hw *hw) -{ - struct clk_unit *clk = to_unitclk(hw); - u32 reg; - - reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_STAT - SIRFSOC_CLKC_ROOT_CLK_EN0_SET; - - return !!(clkc_readl(reg) & BIT(clk->bit)); -} - -static int unit_clk_enable(struct clk_hw *hw) -{ - u32 reg; - struct clk_unit *clk = to_unitclk(hw); - unsigned long flags; - - reg = clk->regofs; - - spin_lock_irqsave(clk->lock, flags); - clkc_writel(BIT(clk->bit), reg); - if (clk->type == CLK_UNIT_NOC_CLOCK) - clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR); - else if (clk->type == CLK_UNIT_NOC_SOCKET) - clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_SET); - - spin_unlock_irqrestore(clk->lock, flags); - return 0; -} - -static void unit_clk_disable(struct clk_hw *hw) -{ - u32 reg; - u32 i = 0; - struct clk_unit *clk = to_unitclk(hw); - unsigned long flags; - - reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET; - spin_lock_irqsave(clk->lock, flags); - if (clk->type == CLK_UNIT_NOC_CLOCK) { - clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_SET); - while (!(clkc_readl(SIRFSOC_NOC_CLK_IDLE_STATUS) & - BIT(clk->idle_bit)) && (i++ < 100)) { - cpu_relax(); - udelay(10); - } - - if (i == 100) { - pr_err("unit NoC Clock disconnect Error:timeout\n"); - /*once timeout, undo idlereq by CLR*/ - clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR); - goto err; - } - - } else if (clk->type == CLK_UNIT_NOC_SOCKET) - clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_CLR); - - clkc_writel(BIT(clk->bit), reg); -err: - spin_unlock_irqrestore(clk->lock, flags); -} - -static const struct clk_ops unit_clk_ops = { - .is_enabled = unit_clk_is_enabled, - .enable = unit_clk_enable, - .disable = unit_clk_disable, -}; - -static struct clk * __init -atlas7_unit_clk_register(struct device *dev, const char *name, - const char * const parent_name, unsigned long flags, - u32 regofs, u8 bit, u32 type, u8 idle_bit, spinlock_t *lock) -{ - struct clk *clk; - struct clk_unit *unit; - struct clk_init_data init; - - unit = kzalloc(sizeof(*unit), GFP_KERNEL); - if (!unit) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.parent_names = &parent_name; - init.num_parents = 1; - init.ops = &unit_clk_ops; - init.flags = flags; - - unit->hw.init = &init; - unit->regofs = regofs; - unit->bit = bit; - - unit->type = type; - unit->idle_bit = idle_bit; - unit->lock = lock; - - clk = clk_register(dev, &unit->hw); - if (IS_ERR(clk)) - kfree(unit); - - return clk; -} - -static struct atlas7_reset_desc atlas7_reset_unit[] = { - { "PWM", 0x0244, 0, 0x0320, 0, &leaf0_gate_lock }, /* 0-5 */ - { "THCGUM", 0x0244, 3, 0x0320, 1, &leaf0_gate_lock }, - { "CVD", 0x04A0, 0, 0x032C, 0, &leaf1_gate_lock }, - { "TIMER", 0x04A0, 1, 0x032C, 1, &leaf1_gate_lock }, - { "PULSEC", 0x04A0, 2, 0x032C, 2, &leaf1_gate_lock }, - { "TSC", 0x04A0, 3, 0x032C, 3, &leaf1_gate_lock }, - { "IOCTOP", 0x04A0, 4, 0x032C, 4, &leaf1_gate_lock }, /* 6-10 */ - { "RSC", 0x04A0, 5, 0x032C, 5, &leaf1_gate_lock }, - { "DVM", 0x04A0, 6, 0x032C, 6, &leaf1_gate_lock }, - { "LVDS", 0x04A0, 7, 0x032C, 7, &leaf1_gate_lock }, - { "KAS", 0x04A0, 8, 0x032C, 8, &leaf1_gate_lock }, - { "AC97", 0x04A0, 9, 0x032C, 9, &leaf1_gate_lock }, /* 11-15 */ - { "USP0", 0x04A0, 10, 0x032C, 10, &leaf1_gate_lock }, - { "USP1", 0x04A0, 11, 0x032C, 11, &leaf1_gate_lock }, - { "USP2", 0x04A0, 12, 0x032C, 12, &leaf1_gate_lock }, - { "DMAC2", 0x04A0, 13, 0x032C, 13, &leaf1_gate_lock }, - { "DMAC3", 0x04A0, 14, 0x032C, 14, &leaf1_gate_lock }, /* 16-20 */ - { "AUDIO", 0x04A0, 15, 0x032C, 15, &leaf1_gate_lock }, - { "I2S1", 0x04A0, 17, 0x032C, 16, &leaf1_gate_lock }, - { "PMU_AUDIO", 0x04A0, 22, 0x032C, 17, &leaf1_gate_lock }, - { "THAUDMSCM", 0x04A0, 23, 0x032C, 18, &leaf1_gate_lock }, - { "SYS2PCI", 0x04B8, 0, 0x0338, 0, &leaf2_gate_lock }, /* 21-25 */ - { "PCIARB", 0x04B8, 1, 0x0338, 1, &leaf2_gate_lock }, - { "PCICOPY", 0x04B8, 2, 0x0338, 2, &leaf2_gate_lock }, - { "ROM", 0x04B8, 3, 0x0338, 3, &leaf2_gate_lock }, - { "SDIO23", 0x04B8, 4, 0x0338, 4, &leaf2_gate_lock }, - { "SDIO45", 0x04B8, 5, 0x0338, 5, &leaf2_gate_lock }, /* 26-30 */ - { "SDIO67", 0x04B8, 6, 0x0338, 6, &leaf2_gate_lock }, - { "VIP1", 0x04B8, 7, 0x0338, 7, &leaf2_gate_lock }, - { "VPP0", 0x04B8, 11, 0x0338, 8, &leaf2_gate_lock }, - { "LCD0", 0x04B8, 12, 0x0338, 9, &leaf2_gate_lock }, - { "VPP1", 0x04B8, 13, 0x0338, 10, &leaf2_gate_lock }, /* 31-35 */ - { "LCD1", 0x04B8, 14, 0x0338, 11, &leaf2_gate_lock }, - { "DCU", 0x04B8, 15, 0x0338, 12, &leaf2_gate_lock }, - { "GPIO", 0x04B8, 18, 0x0338, 13, &leaf2_gate_lock }, - { "DAPA_VDIFM", 0x04B8, 17, 0x0338, 15, &leaf2_gate_lock }, - { "THVDIFM", 0x04B8, 19, 0x0338, 16, &leaf2_gate_lock }, /* 36-40 */ - { "RGMII", 0x04D0, 0, 0x0344, 0, &leaf3_gate_lock }, - { "GMAC", 0x04D0, 1, 0x0344, 1, &leaf3_gate_lock }, - { "UART1", 0x04D0, 2, 0x0344, 2, &leaf3_gate_lock }, - { "DMAC0", 0x04D0, 3, 0x0344, 3, &leaf3_gate_lock }, - { "UART0", 0x04D0, 4, 0x0344, 4, &leaf3_gate_lock }, /* 41-45 */ - { "UART2", 0x04D0, 5, 0x0344, 5, &leaf3_gate_lock }, - { "UART3", 0x04D0, 6, 0x0344, 6, &leaf3_gate_lock }, - { "UART4", 0x04D0, 7, 0x0344, 7, &leaf3_gate_lock }, - { "UART5", 0x04D0, 8, 0x0344, 8, &leaf3_gate_lock }, - { "SPI1", 0x04D0, 9, 0x0344, 9, &leaf3_gate_lock }, /* 46-50 */ - { "GNSS_SYS_M0", 0x04D0, 10, 0x0344, 10, &leaf3_gate_lock }, - { "CANBUS1", 0x04D0, 12, 0x0344, 11, &leaf3_gate_lock }, - { "CCSEC", 0x04D0, 15, 0x0344, 12, &leaf3_gate_lock }, - { "CCPUB", 0x04D0, 16, 0x0344, 13, &leaf3_gate_lock }, - { "DAPA_GNSSM", 0x04D0, 13, 0x0344, 14, &leaf3_gate_lock }, /* 51-55 */ - { "THGNSSM", 0x04D0, 14, 0x0344, 15, &leaf3_gate_lock }, - { "VDEC", 0x04E8, 0, 0x0350, 0, &leaf4_gate_lock }, - { "JPENC", 0x04E8, 1, 0x0350, 1, &leaf4_gate_lock }, - { "G2D", 0x04E8, 2, 0x0350, 2, &leaf4_gate_lock }, - { "I2C0", 0x04E8, 3, 0x0350, 3, &leaf4_gate_lock }, /* 56-60 */ - { "I2C1", 0x04E8, 4, 0x0350, 4, &leaf4_gate_lock }, - { "GPIO0", 0x04E8, 5, 0x0350, 5, &leaf4_gate_lock }, - { "NAND", 0x04E8, 6, 0x0350, 6, &leaf4_gate_lock }, - { "SDIO01", 0x04E8, 7, 0x0350, 7, &leaf4_gate_lock }, - { "SYS2PCI2", 0x04E8, 8, 0x0350, 8, &leaf4_gate_lock }, /* 61-65 */ - { "USB0", 0x04E8, 11, 0x0350, 9, &leaf4_gate_lock }, - { "USB1", 0x04E8, 12, 0x0350, 10, &leaf4_gate_lock }, - { "THMEDIAM", 0x04E8, 15, 0x0350, 11, &leaf4_gate_lock }, - { "MEMC_DDRPHY", 0x0500, 0, 0x035C, 0, &leaf5_gate_lock }, - { "MEMC_UPCTL", 0x0500, 0, 0x035C, 1, &leaf5_gate_lock }, /* 66-70 */ - { "DAPA_MEM", 0x0500, 1, 0x035C, 2, &leaf5_gate_lock }, - { "MEMC_MEMDIV", 0x0500, 0, 0x035C, 3, &leaf5_gate_lock }, - { "THDDRM", 0x0500, 3, 0x035C, 4, &leaf5_gate_lock }, - { "CORESIGHT", 0x0518, 3, 0x0368, 13, &leaf6_gate_lock }, - { "THCPUM", 0x0518, 4, 0x0368, 17, &leaf6_gate_lock }, /* 71-75 */ - { "GRAPHIC", 0x0530, 0, 0x0374, 0, &leaf7_gate_lock }, - { "VSS_SDR", 0x0530, 1, 0x0374, 1, &leaf7_gate_lock }, - { "THGPUM", 0x0530, 2, 0x0374, 2, &leaf7_gate_lock }, - { "DMAC4", 0x0548, 2, 0x0380, 1, &leaf8_gate_lock }, - { "UART6", 0x0548, 3, 0x0380, 2, &leaf8_gate_lock }, /* 76- */ - { "USP3", 0x0548, 4, 0x0380, 3, &leaf8_gate_lock }, - { "THBTM", 0x0548, 5, 0x0380, 5, &leaf8_gate_lock }, - { "A7CA", 0x0548, 1, 0x0380, 0, &leaf8_gate_lock }, - { "A7CA_APB", 0x0548, 5, 0x0380, 4, &leaf8_gate_lock }, -}; - -static int atlas7_reset_module(struct reset_controller_dev *rcdev, - unsigned long reset_idx) -{ - struct atlas7_reset_desc *reset = &atlas7_reset_unit[reset_idx]; - unsigned long flags; - - /* - * HW suggest unit reset sequence: - * assert sw reset (0) - * setting sw clk_en to if the clock was disabled before reset - * delay 16 clocks - * disable clock (sw clk_en = 0) - * de-assert reset (1) - * after this sequence, restore clock or not is decided by SW - */ - - spin_lock_irqsave(reset->lock, flags); - /* clock enable or not */ - if (clkc_readl(reset->clk_ofs + 8) & (1 << reset->clk_bit)) { - clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4); - udelay(2); - clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4); - clkc_writel(1 << reset->rst_bit, reset->rst_ofs); - /* restore clock enable */ - clkc_writel(1 << reset->clk_bit, reset->clk_ofs); - } else { - clkc_writel(1 << reset->rst_bit, reset->rst_ofs + 4); - clkc_writel(1 << reset->clk_bit, reset->clk_ofs); - udelay(2); - clkc_writel(1 << reset->clk_bit, reset->clk_ofs + 4); - clkc_writel(1 << reset->rst_bit, reset->rst_ofs); - } - spin_unlock_irqrestore(reset->lock, flags); - - return 0; -} - -static const struct reset_control_ops atlas7_rst_ops = { - .reset = atlas7_reset_module, -}; - -static struct reset_controller_dev atlas7_rst_ctlr = { - .ops = &atlas7_rst_ops, - .owner = THIS_MODULE, - .of_reset_n_cells = 1, -}; - -static void __init atlas7_clk_init(struct device_node *np) -{ - struct clk *clk; - struct atlas7_div_init_data *div; - struct atlas7_mux_init_data *mux; - struct atlas7_unit_init_data *unit; - int i; - int ret; - - sirfsoc_clk_vbase = of_iomap(np, 0); - if (!sirfsoc_clk_vbase) - panic("unable to map clkc registers\n"); - - of_node_put(np); - - clk = clk_register(NULL, &clk_cpupll.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_mempll.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_sys0pll.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_sys1pll.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_sys2pll.hw); - BUG_ON(!clk); - clk = clk_register(NULL, &clk_sys3pll.hw); - BUG_ON(!clk); - - clk = clk_register_divider_table(NULL, "cpupll_div1", "cpupll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &cpupll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "cpupll_div2", "cpupll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &cpupll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "cpupll_div3", "cpupll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &cpupll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_divider_table(NULL, "mempll_div1", "mempll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &mempll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "mempll_div2", "mempll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &mempll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "mempll_div3", "mempll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &mempll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_divider_table(NULL, "sys0pll_div1", "sys0pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys0pll_div2", "sys0pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys0pll_div3", "sys0pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_fixed_factor(NULL, "sys0pll_fixdiv", "sys0pll_vco", - CLK_SET_RATE_PARENT, 1, 2); - - clk = clk_register_divider_table(NULL, "sys1pll_div1", "sys1pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys1pll_div2", "sys1pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys1pll_div3", "sys1pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_fixed_factor(NULL, "sys1pll_fixdiv", "sys1pll_vco", - CLK_SET_RATE_PARENT, 1, 2); - - clk = clk_register_divider_table(NULL, "sys2pll_div1", "sys2pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys2pll_div2", "sys2pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys2pll_div3", "sys2pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_fixed_factor(NULL, "sys2pll_fixdiv", "sys2pll_vco", - CLK_SET_RATE_PARENT, 1, 2); - - clk = clk_register_divider_table(NULL, "sys3pll_div1", "sys3pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 0, 3, 0, - pll_div_table, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys3pll_div2", "sys3pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 4, 3, 0, - pll_div_table, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_divider_table(NULL, "sys3pll_div3", "sys3pll_vco", 0, - sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, 8, 3, 0, - pll_div_table, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_fixed_factor(NULL, "sys3pll_fixdiv", "sys3pll_vco", - CLK_SET_RATE_PARENT, 1, 2); - - BUG_ON(!clk); - clk = clk_register_fixed_factor(NULL, "xinw_fixdiv_btslow", "xinw", - CLK_SET_RATE_PARENT, 1, 4); - - BUG_ON(!clk); - clk = clk_register_gate(NULL, "cpupll_clk1", "cpupll_div1", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, - 12, 0, &cpupll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "cpupll_clk2", "cpupll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, - 13, 0, &cpupll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "cpupll_clk3", "cpupll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_CPUPLL_AB_CTRL1, - 14, 0, &cpupll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_gate(NULL, "mempll_clk1", "mempll_div1", - CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, - sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, - 12, 0, &mempll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "mempll_clk2", "mempll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, - 13, 0, &mempll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "mempll_clk3", "mempll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_MEMPLL_AB_CTRL1, - 14, 0, &mempll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_gate(NULL, "sys0pll_clk1", "sys0pll_div1", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, - 12, 0, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys0pll_clk2", "sys0pll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, - 13, 0, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys0pll_clk3", "sys0pll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS0PLL_AB_CTRL1, - 14, 0, &sys0pll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_gate(NULL, "sys1pll_clk1", "sys1pll_div1", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, - 12, 0, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys1pll_clk2", "sys1pll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, - 13, 0, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys1pll_clk3", "sys1pll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS1PLL_AB_CTRL1, - 14, 0, &sys1pll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_gate(NULL, "sys2pll_clk1", "sys2pll_div1", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, - 12, 0, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys2pll_clk2", "sys2pll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, - 13, 0, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys2pll_clk3", "sys2pll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS2PLL_AB_CTRL1, - 14, 0, &sys2pll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register_gate(NULL, "sys3pll_clk1", "sys3pll_div1", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, - 12, 0, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys3pll_clk2", "sys3pll_div2", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, - 13, 0, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, "sys3pll_clk3", "sys3pll_div3", - CLK_SET_RATE_PARENT, sirfsoc_clk_vbase + SIRFSOC_CLKC_SYS3PLL_AB_CTRL1, - 14, 0, &sys3pll_ctrl1_lock); - BUG_ON(!clk); - - clk = clk_register(NULL, &clk_audio_dto.hw); - BUG_ON(!clk); - - clk = clk_register(NULL, &clk_disp0_dto.hw); - BUG_ON(!clk); - - clk = clk_register(NULL, &clk_disp1_dto.hw); - BUG_ON(!clk); - - for (i = 0; i < ARRAY_SIZE(divider_list); i++) { - div = ÷r_list[i]; - clk = clk_register_divider(NULL, div->div_name, - div->parent_name, div->divider_flags, sirfsoc_clk_vbase + div->div_offset, - div->shift, div->width, 0, div->lock); - BUG_ON(!clk); - clk = clk_register_gate(NULL, div->gate_name, div->div_name, - div->gate_flags, sirfsoc_clk_vbase + div->gate_offset, - div->gate_bit, 0, div->lock); - BUG_ON(!clk); - } - /* ignore selector status register check */ - for (i = 0; i < ARRAY_SIZE(mux_list); i++) { - mux = &mux_list[i]; - clk = clk_register_mux(NULL, mux->mux_name, mux->parent_names, - mux->parent_num, mux->flags, - sirfsoc_clk_vbase + mux->mux_offset, - mux->shift, mux->width, - mux->mux_flags, NULL); - atlas7_clks[ARRAY_SIZE(unit_list) + i] = clk; - BUG_ON(!clk); - } - - for (i = 0; i < ARRAY_SIZE(unit_list); i++) { - unit = &unit_list[i]; - atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name, - unit->flags, unit->regofs, unit->bit, unit->type, unit->idle_bit, unit->lock); - BUG_ON(!atlas7_clks[i]); - } - - clk_data.clks = atlas7_clks; - clk_data.clk_num = ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list); - - ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); - BUG_ON(ret); - - atlas7_rst_ctlr.of_node = np; - atlas7_rst_ctlr.nr_resets = ARRAY_SIZE(atlas7_reset_unit); - reset_controller_register(&atlas7_rst_ctlr); -} -CLK_OF_DECLARE(atlas7_clk, "sirf,atlas7-car", atlas7_clk_init); diff --git a/drivers/clk/sirf/clk-common.c b/drivers/clk/sirf/clk-common.c deleted file mode 100644 index dcf4e25a0216..000000000000 --- a/drivers/clk/sirf/clk-common.c +++ /dev/null @@ -1,1037 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * common clks module for all SiRF SoCs - * - * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group - * company. - */ - -#include <linux/clk.h> - -#define KHZ 1000 -#define MHZ (KHZ * KHZ) - -static void __iomem *sirfsoc_clk_vbase; -static void __iomem *sirfsoc_rsc_vbase; -static struct clk_onecell_data clk_data; - -/* - * SiRFprimaII clock controller - * - 2 oscillators: osc-26MHz, rtc-32.768KHz - * - 3 standard configurable plls: pll1, pll2 & pll3 - * - 2 exclusive plls: usb phy pll and sata phy pll - * - 8 clock domains: cpu/cpudiv, mem/memdiv, sys/io, dsp, graphic, multimedia, - * display and sdphy. - * Each clock domain can select its own clock source from five clock sources, - * X_XIN, X_XINW, PLL1, PLL2 and PLL3. The domain clock is used as the source - * clock of the group clock. - * - dsp domain: gps, mf - * - io domain: dmac, nand, audio, uart, i2c, spi, usp, pwm, pulse - * - sys domain: security - */ - -struct clk_pll { - struct clk_hw hw; - unsigned short regofs; /* register offset */ -}; - -#define to_pllclk(_hw) container_of(_hw, struct clk_pll, hw) - -struct clk_dmn { - struct clk_hw hw; - signed char enable_bit; /* enable bit: 0 ~ 63 */ - unsigned short regofs; /* register offset */ -}; - -#define to_dmnclk(_hw) container_of(_hw, struct clk_dmn, hw) - -struct clk_std { - struct clk_hw hw; - signed char enable_bit; /* enable bit: 0 ~ 63 */ -}; - -#define to_stdclk(_hw) container_of(_hw, struct clk_std, hw) - -static int std_clk_is_enabled(struct clk_hw *hw); -static int std_clk_enable(struct clk_hw *hw); -static void std_clk_disable(struct clk_hw *hw); - -static inline unsigned long clkc_readl(unsigned reg) -{ - return readl(sirfsoc_clk_vbase + reg); -} - -static inline void clkc_writel(u32 val, unsigned reg) -{ - writel(val, sirfsoc_clk_vbase + reg); -} - -/* - * std pll - */ - -static unsigned long pll_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned long fin = parent_rate; - struct clk_pll *clk = to_pllclk(hw); - u32 regcfg2 = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - - SIRFSOC_CLKC_PLL1_CFG0; - - if (clkc_readl(regcfg2) & BIT(2)) { - /* pll bypass mode */ - return fin; - } else { - /* fout = fin * nf / nr / od */ - u32 cfg0 = clkc_readl(clk->regofs); - u32 nf = (cfg0 & (BIT(13) - 1)) + 1; - u32 nr = ((cfg0 >> 13) & (BIT(6) - 1)) + 1; - u32 od = ((cfg0 >> 19) & (BIT(4) - 1)) + 1; - WARN_ON(fin % MHZ); - return fin / MHZ * nf / nr / od * MHZ; - } -} - -static long pll_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long fin, nf, nr, od; - u64 dividend; - - /* - * fout = fin * nf / (nr * od); - * set od = 1, nr = fin/MHz, so fout = nf * MHz - */ - rate = rate - rate % MHZ; - - nf = rate / MHZ; - if (nf > BIT(13)) - nf = BIT(13); - if (nf < 1) - nf = 1; - - fin = *parent_rate; - - nr = fin / MHZ; - if (nr > BIT(6)) - nr = BIT(6); - od = 1; - - dividend = (u64)fin * nf; - do_div(dividend, nr * od); - - return (long)dividend; -} - -static int pll_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_pll *clk = to_pllclk(hw); - unsigned long fin, nf, nr, od, reg; - - /* - * fout = fin * nf / (nr * od); - * set od = 1, nr = fin/MHz, so fout = nf * MHz - */ - - nf = rate / MHZ; - if (unlikely((rate % MHZ) || nf > BIT(13) || nf < 1)) - return -EINVAL; - - fin = parent_rate; - BUG_ON(fin < MHZ); - - nr = fin / MHZ; - BUG_ON((fin % MHZ) || nr > BIT(6)); - - od = 1; - - reg = (nf - 1) | ((nr - 1) << 13) | ((od - 1) << 19); - clkc_writel(reg, clk->regofs); - - reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG1 - SIRFSOC_CLKC_PLL1_CFG0; - clkc_writel((nf >> 1) - 1, reg); - - reg = clk->regofs + SIRFSOC_CLKC_PLL1_CFG2 - SIRFSOC_CLKC_PLL1_CFG0; - while (!(clkc_readl(reg) & BIT(6))) - cpu_relax(); - - return 0; -} - -static long cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - /* - * SiRF SoC has not cpu clock control, - * So bypass to it's parent pll. - */ - struct clk_hw *parent_clk = clk_hw_get_parent(hw); - struct clk_hw *pll_parent_clk = clk_hw_get_parent(parent_clk); - unsigned long pll_parent_rate = clk_hw_get_rate(pll_parent_clk); - return pll_clk_round_rate(parent_clk, rate, &pll_parent_rate); -} - -static unsigned long cpu_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - /* - * SiRF SoC has not cpu clock control, - * So return the parent pll rate. - */ - struct clk_hw *parent_clk = clk_hw_get_parent(hw); - return clk_hw_get_rate(parent_clk); -} - -static const struct clk_ops std_pll_ops = { - .recalc_rate = pll_clk_recalc_rate, - .round_rate = pll_clk_round_rate, - .set_rate = pll_clk_set_rate, -}; - -static const char * const pll_clk_parents[] = { - "osc", -}; - -static const struct clk_init_data clk_pll1_init = { - .name = "pll1", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static const struct clk_init_data clk_pll2_init = { - .name = "pll2", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static const struct clk_init_data clk_pll3_init = { - .name = "pll3", - .ops = &std_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_pll clk_pll1 = { - .regofs = SIRFSOC_CLKC_PLL1_CFG0, - .hw = { - .init = &clk_pll1_init, - }, -}; - -static struct clk_pll clk_pll2 = { - .regofs = SIRFSOC_CLKC_PLL2_CFG0, - .hw = { - .init = &clk_pll2_init, - }, -}; - -static struct clk_pll clk_pll3 = { - .regofs = SIRFSOC_CLKC_PLL3_CFG0, - .hw = { - .init = &clk_pll3_init, - }, -}; - -/* - * usb uses specified pll - */ - -static int usb_pll_clk_enable(struct clk_hw *hw) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - reg &= ~(SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); - writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - while (!(readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL) & - SIRFSOC_USBPHY_PLL_LOCK)) - cpu_relax(); - - return 0; -} - -static void usb_pll_clk_disable(struct clk_hw *clk) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - reg |= (SIRFSOC_USBPHY_PLL_POWERDOWN | SIRFSOC_USBPHY_PLL_BYPASS); - writel(reg, sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); -} - -static unsigned long usb_pll_clk_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) -{ - u32 reg = readl(sirfsoc_rsc_vbase + SIRFSOC_USBPHY_PLL_CTRL); - return (reg & SIRFSOC_USBPHY_PLL_BYPASS) ? parent_rate : 48*MHZ; -} - -static const struct clk_ops usb_pll_ops = { - .enable = usb_pll_clk_enable, - .disable = usb_pll_clk_disable, - .recalc_rate = usb_pll_clk_recalc_rate, -}; - -static const struct clk_init_data clk_usb_pll_init = { - .name = "usb_pll", - .ops = &usb_pll_ops, - .parent_names = pll_clk_parents, - .num_parents = ARRAY_SIZE(pll_clk_parents), -}; - -static struct clk_hw usb_pll_clk_hw = { - .init = &clk_usb_pll_init, -}; - -/* - * clock domains - cpu, mem, sys/io, dsp, gfx - */ - -static const char * const dmn_clk_parents[] = { - "rtc", - "osc", - "pll1", - "pll2", - "pll3", -}; - -static u8 dmn_clk_get_parent(struct clk_hw *hw) -{ - struct clk_dmn *clk = to_dmnclk(hw); - u32 cfg = clkc_readl(clk->regofs); - const char *name = clk_hw_get_name(hw); - - /* parent of io domain can only be pll3 */ - if (strcmp(name, "io") == 0) - return 4; - - WARN_ON((cfg & (BIT(3) - 1)) > 4); - - return cfg & (BIT(3) - 1); -} - -static int dmn_clk_set_parent(struct clk_hw *hw, u8 parent) -{ - struct clk_dmn *clk = to_dmnclk(hw); - u32 cfg = clkc_readl(clk->regofs); - const char *name = clk_hw_get_name(hw); - - /* parent of io domain can only be pll3 */ - if (strcmp(name, "io") == 0) - return -EINVAL; - - cfg &= ~(BIT(3) - 1); - clkc_writel(cfg | parent, clk->regofs); - /* BIT(3) - switching status: 1 - busy, 0 - done */ - while (clkc_readl(clk->regofs) & BIT(3)) - cpu_relax(); - - return 0; -} - -static unsigned long dmn_clk_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) - -{ - unsigned long fin = parent_rate; - struct clk_dmn *clk = to_dmnclk(hw); - - u32 cfg = clkc_readl(clk->regofs); - - if (cfg & BIT(24)) { - /* fcd bypass mode */ - return fin; - } else { - /* - * wait count: bit[19:16], hold count: bit[23:20] - */ - u32 wait = (cfg >> 16) & (BIT(4) - 1); - u32 hold = (cfg >> 20) & (BIT(4) - 1); - - return fin / (wait + hold + 2); - } -} - -static long dmn_clk_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - unsigned long fin; - unsigned ratio, wait, hold; - const char *name = clk_hw_get_name(hw); - unsigned bits = (strcmp(name, "mem") == 0) ? 3 : 4; - - fin = *parent_rate; - ratio = fin / rate; - - if (ratio < 2) - ratio = 2; - if (ratio > BIT(bits + 1)) - ratio = BIT(bits + 1); - - wait = (ratio >> 1) - 1; - hold = ratio - wait - 2; - - return fin / (wait + hold + 2); -} - -static int dmn_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_dmn *clk = to_dmnclk(hw); - unsigned long fin; - unsigned ratio, wait, hold, reg; - const char *name = clk_hw_get_name(hw); - unsigned bits = (strcmp(name, "mem") == 0) ? 3 : 4; - - fin = parent_rate; - ratio = fin / rate; - - if (unlikely(ratio < 2 || ratio > BIT(bits + 1))) - return -EINVAL; - - WARN_ON(fin % rate); - - wait = (ratio >> 1) - 1; - hold = ratio - wait - 2; - - reg = clkc_readl(clk->regofs); - reg &= ~(((BIT(bits) - 1) << 16) | ((BIT(bits) - 1) << 20)); - reg |= (wait << 16) | (hold << 20) | BIT(25); - clkc_writel(reg, clk->regofs); - - /* waiting FCD been effective */ - while (clkc_readl(clk->regofs) & BIT(25)) - cpu_relax(); - - return 0; -} - -static int cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int ret1, ret2; - struct clk *cur_parent; - - if (rate == clk_get_rate(clk_pll1.hw.clk)) { - ret1 = clk_set_parent(hw->clk, clk_pll1.hw.clk); - return ret1; - } - - if (rate == clk_get_rate(clk_pll2.hw.clk)) { - ret1 = clk_set_parent(hw->clk, clk_pll2.hw.clk); - return ret1; - } - - if (rate == clk_get_rate(clk_pll3.hw.clk)) { - ret1 = clk_set_parent(hw->clk, clk_pll3.hw.clk); - return ret1; - } - - cur_parent = clk_get_parent(hw->clk); - - /* switch to tmp pll before setting parent clock's rate */ - if (cur_parent == clk_pll1.hw.clk) { - ret1 = clk_set_parent(hw->clk, clk_pll2.hw.clk); - BUG_ON(ret1); - } - - ret2 = clk_set_rate(clk_pll1.hw.clk, rate); - - ret1 = clk_set_parent(hw->clk, clk_pll1.hw.clk); - - return ret2 ? ret2 : ret1; -} - -static const struct clk_ops msi_ops = { - .set_rate = dmn_clk_set_rate, - .round_rate = dmn_clk_round_rate, - .recalc_rate = dmn_clk_recalc_rate, - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, -}; - -static const struct clk_init_data clk_mem_init = { - .name = "mem", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mem = { - .regofs = SIRFSOC_CLKC_MEM_CFG, - .hw = { - .init = &clk_mem_init, - }, -}; - -static const struct clk_init_data clk_sys_init = { - .name = "sys", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), - .flags = CLK_SET_RATE_GATE, -}; - -static struct clk_dmn clk_sys = { - .regofs = SIRFSOC_CLKC_SYS_CFG, - .hw = { - .init = &clk_sys_init, - }, -}; - -static const struct clk_init_data clk_io_init = { - .name = "io", - .ops = &msi_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_io = { - .regofs = SIRFSOC_CLKC_IO_CFG, - .hw = { - .init = &clk_io_init, - }, -}; - -static const struct clk_ops cpu_ops = { - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, - .set_rate = cpu_clk_set_rate, - .round_rate = cpu_clk_round_rate, - .recalc_rate = cpu_clk_recalc_rate, -}; - -static const struct clk_init_data clk_cpu_init = { - .name = "cpu", - .ops = &cpu_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), - .flags = CLK_SET_RATE_PARENT, -}; - -static struct clk_dmn clk_cpu = { - .regofs = SIRFSOC_CLKC_CPU_CFG, - .hw = { - .init = &clk_cpu_init, - }, -}; - -static const struct clk_ops dmn_ops = { - .is_enabled = std_clk_is_enabled, - .enable = std_clk_enable, - .disable = std_clk_disable, - .set_rate = dmn_clk_set_rate, - .round_rate = dmn_clk_round_rate, - .recalc_rate = dmn_clk_recalc_rate, - .set_parent = dmn_clk_set_parent, - .get_parent = dmn_clk_get_parent, -}; - -/* dsp, gfx, mm, lcd and vpp domain */ - -static const struct clk_init_data clk_dsp_init = { - .name = "dsp", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_dsp = { - .regofs = SIRFSOC_CLKC_DSP_CFG, - .enable_bit = 0, - .hw = { - .init = &clk_dsp_init, - }, -}; - -static const struct clk_init_data clk_gfx_init = { - .name = "gfx", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_gfx = { - .regofs = SIRFSOC_CLKC_GFX_CFG, - .enable_bit = 8, - .hw = { - .init = &clk_gfx_init, - }, -}; - -static const struct clk_init_data clk_mm_init = { - .name = "mm", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_mm = { - .regofs = SIRFSOC_CLKC_MM_CFG, - .enable_bit = 9, - .hw = { - .init = &clk_mm_init, - }, -}; - -/* - * for atlas6, gfx2d holds the bit of prima2's clk_mm - */ -#define clk_gfx2d clk_mm - -static const struct clk_init_data clk_lcd_init = { - .name = "lcd", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_lcd = { - .regofs = SIRFSOC_CLKC_LCD_CFG, - .enable_bit = 10, - .hw = { - .init = &clk_lcd_init, - }, -}; - -static const struct clk_init_data clk_vpp_init = { - .name = "vpp", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static struct clk_dmn clk_vpp = { - .regofs = SIRFSOC_CLKC_LCD_CFG, - .enable_bit = 11, - .hw = { - .init = &clk_vpp_init, - }, -}; - -static const struct clk_init_data clk_mmc01_init = { - .name = "mmc01", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static const struct clk_init_data clk_mmc23_init = { - .name = "mmc23", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -static const struct clk_init_data clk_mmc45_init = { - .name = "mmc45", - .ops = &dmn_ops, - .parent_names = dmn_clk_parents, - .num_parents = ARRAY_SIZE(dmn_clk_parents), -}; - -/* - * peripheral controllers in io domain - */ - -static int std_clk_is_enabled(struct clk_hw *hw) -{ - u32 reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - return !!(clkc_readl(reg) & BIT(bit)); -} - -static int std_clk_enable(struct clk_hw *hw) -{ - u32 val, reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - val = clkc_readl(reg) | BIT(bit); - clkc_writel(val, reg); - return 0; -} - -static void std_clk_disable(struct clk_hw *hw) -{ - u32 val, reg; - int bit; - struct clk_std *clk = to_stdclk(hw); - - BUG_ON(clk->enable_bit < 0 || clk->enable_bit > 63); - - bit = clk->enable_bit % 32; - reg = clk->enable_bit / 32; - reg = SIRFSOC_CLKC_CLK_EN0 + reg * sizeof(reg); - - val = clkc_readl(reg) & ~BIT(bit); - clkc_writel(val, reg); -} - -static const char * const std_clk_io_parents[] = { - "io", -}; - -static const struct clk_ops ios_ops = { - .is_enabled = std_clk_is_enabled, - .enable = std_clk_enable, - .disable = std_clk_disable, -}; - -static const struct clk_init_data clk_cphif_init = { - .name = "cphif", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_cphif = { - .enable_bit = 20, - .hw = { - .init = &clk_cphif_init, - }, -}; - -static const struct clk_init_data clk_dmac0_init = { - .name = "dmac0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_dmac0 = { - .enable_bit = 32, - .hw = { - .init = &clk_dmac0_init, - }, -}; - -static const struct clk_init_data clk_dmac1_init = { - .name = "dmac1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_dmac1 = { - .enable_bit = 33, - .hw = { - .init = &clk_dmac1_init, - }, -}; - -static const struct clk_init_data clk_audio_init = { - .name = "audio", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_audio = { - .enable_bit = 35, - .hw = { - .init = &clk_audio_init, - }, -}; - -static const struct clk_init_data clk_uart0_init = { - .name = "uart0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart0 = { - .enable_bit = 36, - .hw = { - .init = &clk_uart0_init, - }, -}; - -static const struct clk_init_data clk_uart1_init = { - .name = "uart1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart1 = { - .enable_bit = 37, - .hw = { - .init = &clk_uart1_init, - }, -}; - -static const struct clk_init_data clk_uart2_init = { - .name = "uart2", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_uart2 = { - .enable_bit = 38, - .hw = { - .init = &clk_uart2_init, - }, -}; - -static const struct clk_init_data clk_usp0_init = { - .name = "usp0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp0 = { - .enable_bit = 39, - .hw = { - .init = &clk_usp0_init, - }, -}; - -static const struct clk_init_data clk_usp1_init = { - .name = "usp1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp1 = { - .enable_bit = 40, - .hw = { - .init = &clk_usp1_init, - }, -}; - -static const struct clk_init_data clk_usp2_init = { - .name = "usp2", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_usp2 = { - .enable_bit = 41, - .hw = { - .init = &clk_usp2_init, - }, -}; - -static const struct clk_init_data clk_vip_init = { - .name = "vip", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_vip = { - .enable_bit = 42, - .hw = { - .init = &clk_vip_init, - }, -}; - -static const struct clk_init_data clk_spi0_init = { - .name = "spi0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_spi0 = { - .enable_bit = 43, - .hw = { - .init = &clk_spi0_init, - }, -}; - -static const struct clk_init_data clk_spi1_init = { - .name = "spi1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_spi1 = { - .enable_bit = 44, - .hw = { - .init = &clk_spi1_init, - }, -}; - -static const struct clk_init_data clk_tsc_init = { - .name = "tsc", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_tsc = { - .enable_bit = 45, - .hw = { - .init = &clk_tsc_init, - }, -}; - -static const struct clk_init_data clk_i2c0_init = { - .name = "i2c0", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_i2c0 = { - .enable_bit = 46, - .hw = { - .init = &clk_i2c0_init, - }, -}; - -static const struct clk_init_data clk_i2c1_init = { - .name = "i2c1", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_i2c1 = { - .enable_bit = 47, - .hw = { - .init = &clk_i2c1_init, - }, -}; - -static const struct clk_init_data clk_pwmc_init = { - .name = "pwmc", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_pwmc = { - .enable_bit = 48, - .hw = { - .init = &clk_pwmc_init, - }, -}; - -static const struct clk_init_data clk_efuse_init = { - .name = "efuse", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_efuse = { - .enable_bit = 49, - .hw = { - .init = &clk_efuse_init, - }, -}; - -static const struct clk_init_data clk_pulse_init = { - .name = "pulse", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_pulse = { - .enable_bit = 50, - .hw = { - .init = &clk_pulse_init, - }, -}; - -static const char * const std_clk_dsp_parents[] = { - "dsp", -}; - -static const struct clk_init_data clk_gps_init = { - .name = "gps", - .ops = &ios_ops, - .parent_names = std_clk_dsp_parents, - .num_parents = ARRAY_SIZE(std_clk_dsp_parents), -}; - -static struct clk_std clk_gps = { - .enable_bit = 1, - .hw = { - .init = &clk_gps_init, - }, -}; - -static const struct clk_init_data clk_mf_init = { - .name = "mf", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_mf = { - .enable_bit = 2, - .hw = { - .init = &clk_mf_init, - }, -}; - -static const char * const std_clk_sys_parents[] = { - "sys", -}; - -static const struct clk_init_data clk_security_init = { - .name = "security", - .ops = &ios_ops, - .parent_names = std_clk_sys_parents, - .num_parents = ARRAY_SIZE(std_clk_sys_parents), -}; - -static struct clk_std clk_security = { - .enable_bit = 19, - .hw = { - .init = &clk_security_init, - }, -}; - -static const char * const std_clk_usb_parents[] = { - "usb_pll", -}; - -static const struct clk_init_data clk_usb0_init = { - .name = "usb0", - .ops = &ios_ops, - .parent_names = std_clk_usb_parents, - .num_parents = ARRAY_SIZE(std_clk_usb_parents), -}; - -static struct clk_std clk_usb0 = { - .enable_bit = 16, - .hw = { - .init = &clk_usb0_init, - }, -}; - -static const struct clk_init_data clk_usb1_init = { - .name = "usb1", - .ops = &ios_ops, - .parent_names = std_clk_usb_parents, - .num_parents = ARRAY_SIZE(std_clk_usb_parents), -}; - -static struct clk_std clk_usb1 = { - .enable_bit = 17, - .hw = { - .init = &clk_usb1_init, - }, -}; diff --git a/drivers/clk/sirf/clk-prima2.c b/drivers/clk/sirf/clk-prima2.c deleted file mode 100644 index d17b345f4d2d..000000000000 --- a/drivers/clk/sirf/clk-prima2.c +++ /dev/null @@ -1,149 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Clock tree for CSR SiRFprimaII - * - * Copyright (c) 2011 - 2014 Cambridge Silicon Radio Limited, a CSR plc group - * company. - */ - -#include <linux/module.h> -#include <linux/bitops.h> -#include <linux/io.h> -#include <linux/clkdev.h> -#include <linux/clk-provider.h> -#include <linux/of_address.h> -#include <linux/syscore_ops.h> - -#include "prima2.h" -#include "clk-common.c" - -static struct clk_dmn clk_mmc01 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 59, - .hw = { - .init = &clk_mmc01_init, - }, -}; - -static struct clk_dmn clk_mmc23 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 60, - .hw = { - .init = &clk_mmc23_init, - }, -}; - -static struct clk_dmn clk_mmc45 = { - .regofs = SIRFSOC_CLKC_MMC_CFG, - .enable_bit = 61, - .hw = { - .init = &clk_mmc45_init, - }, -}; - -static const struct clk_init_data clk_nand_init = { - .name = "nand", - .ops = &ios_ops, - .parent_names = std_clk_io_parents, - .num_parents = ARRAY_SIZE(std_clk_io_parents), -}; - -static struct clk_std clk_nand = { - .enable_bit = 34, - .hw = { - .init = &clk_nand_init, - }, -}; - -enum prima2_clk_index { - /* 0 1 2 3 4 5 6 7 8 9 */ - rtc, osc, pll1, pll2, pll3, mem, sys, security, dsp, gps, - mf, io, cpu, uart0, uart1, uart2, tsc, i2c0, i2c1, spi0, - spi1, pwmc, efuse, pulse, dmac0, dmac1, nand, audio, usp0, usp1, - usp2, vip, gfx, mm, lcd, vpp, mmc01, mmc23, mmc45, usbpll, - usb0, usb1, cphif, maxclk, -}; - -static __initdata struct clk_hw *prima2_clk_hw_array[maxclk] = { - NULL, /* dummy */ - NULL, - &clk_pll1.hw, - &clk_pll2.hw, - &clk_pll3.hw, - &clk_mem.hw, - &clk_sys.hw, - &clk_security.hw, - &clk_dsp.hw, - &clk_gps.hw, - &clk_mf.hw, - &clk_io.hw, - &clk_cpu.hw, - &clk_uart0.hw, - &clk_uart1.hw, - &clk_uart2.hw, - &clk_tsc.hw, - &clk_i2c0.hw, - &clk_i2c1.hw, - &clk_spi0.hw, - &clk_spi1.hw, - &clk_pwmc.hw, - &clk_efuse.hw, - &clk_pulse.hw, - &clk_dmac0.hw, - &clk_dmac1.hw, - &clk_nand.hw, - &clk_audio.hw, - &clk_usp0.hw, - &clk_usp1.hw, - &clk_usp2.hw, - &clk_vip.hw, - &clk_gfx.hw, - &clk_mm.hw, - &clk_lcd.hw, - &clk_vpp.hw, - &clk_mmc01.hw, - &clk_mmc23.hw, - &clk_mmc45.hw, - &usb_pll_clk_hw, - &clk_usb0.hw, - &clk_usb1.hw, - &clk_cphif.hw, -}; - -static struct clk *prima2_clks[maxclk]; - -static void __init prima2_clk_init(struct device_node *np) -{ - struct device_node *rscnp; - int i; - - rscnp = of_find_compatible_node(NULL, NULL, "sirf,prima2-rsc"); - sirfsoc_rsc_vbase = of_iomap(rscnp, 0); - if (!sirfsoc_rsc_vbase) - panic("unable to map rsc registers\n"); - of_node_put(rscnp); - - sirfsoc_clk_vbase = of_iomap(np, 0); - if (!sirfsoc_clk_vbase) - panic("unable to map clkc registers\n"); - - /* These are always available (RTC and 26MHz OSC)*/ - prima2_clks[rtc] = clk_register_fixed_rate(NULL, "rtc", NULL, 0, 32768); - prima2_clks[osc] = clk_register_fixed_rate(NULL, "osc", NULL, 0, - 26000000); - - for (i = pll1; i < maxclk; i++) { - prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); - BUG_ON(IS_ERR(prima2_clks[i])); - } - clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); - clk_register_clkdev(prima2_clks[io], NULL, "io"); - clk_register_clkdev(prima2_clks[mem], NULL, "mem"); - clk_register_clkdev(prima2_clks[mem], NULL, "osc"); - - clk_data.clks = prima2_clks; - clk_data.clk_num = maxclk; - - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); -} -CLK_OF_DECLARE(prima2_clk, "sirf,prima2-clkc", prima2_clk_init); diff --git a/drivers/clk/sirf/prima2.h b/drivers/clk/sirf/prima2.h deleted file mode 100644 index 2fb56941795d..000000000000 --- a/drivers/clk/sirf/prima2.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#define SIRFSOC_CLKC_CLK_EN0 0x0000 -#define SIRFSOC_CLKC_CLK_EN1 0x0004 -#define SIRFSOC_CLKC_REF_CFG 0x0014 -#define SIRFSOC_CLKC_CPU_CFG 0x0018 -#define SIRFSOC_CLKC_MEM_CFG 0x001c -#define SIRFSOC_CLKC_SYS_CFG 0x0020 -#define SIRFSOC_CLKC_IO_CFG 0x0024 -#define SIRFSOC_CLKC_DSP_CFG 0x0028 -#define SIRFSOC_CLKC_GFX_CFG 0x002c -#define SIRFSOC_CLKC_MM_CFG 0x0030 -#define SIRFSOC_CLKC_LCD_CFG 0x0034 -#define SIRFSOC_CLKC_MMC_CFG 0x0038 -#define SIRFSOC_CLKC_PLL1_CFG0 0x0040 -#define SIRFSOC_CLKC_PLL2_CFG0 0x0044 -#define SIRFSOC_CLKC_PLL3_CFG0 0x0048 -#define SIRFSOC_CLKC_PLL1_CFG1 0x004c -#define SIRFSOC_CLKC_PLL2_CFG1 0x0050 -#define SIRFSOC_CLKC_PLL3_CFG1 0x0054 -#define SIRFSOC_CLKC_PLL1_CFG2 0x0058 -#define SIRFSOC_CLKC_PLL2_CFG2 0x005c -#define SIRFSOC_CLKC_PLL3_CFG2 0x0060 -#define SIRFSOC_USBPHY_PLL_CTRL 0x0008 -#define SIRFSOC_USBPHY_PLL_POWERDOWN BIT(1) -#define SIRFSOC_USBPHY_PLL_BYPASS BIT(2) -#define SIRFSOC_USBPHY_PLL_LOCK BIT(3) diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index ce5f5847d5d3..cd46d8853876 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -32,8 +32,13 @@ config SUN50I_H6_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN50I_H616_CCU + bool "Support for the Allwinner H616 CCU" + default ARM64 && ARCH_SUNXI + depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST + config SUN50I_H6_R_CCU - bool "Support for the Allwinner H6 PRCM CCU" + bool "Support for the Allwinner H6 and H616 PRCM CCU" default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 3eb5cff40eac..96c324306d97 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o +obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c index 50f8d1bc7046..f8909a7ed553 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c @@ -91,6 +91,8 @@ static SUNXI_CCU_GATE(r_apb2_uart_clk, "r-apb2-uart", "r-apb2", 0x18c, BIT(0), 0); static SUNXI_CCU_GATE(r_apb2_i2c_clk, "r-apb2-i2c", "r-apb2", 0x19c, BIT(0), 0); +static SUNXI_CCU_GATE(r_apb2_rsb_clk, "r-apb2-rsb", "r-apb2", + 0x1bc, BIT(0), 0); static SUNXI_CCU_GATE(r_apb1_ir_clk, "r-apb1-ir", "r-apb1", 0x1cc, BIT(0), 0); static SUNXI_CCU_GATE(r_apb1_w1_clk, "r-apb1-w1", "r-apb1", @@ -130,12 +132,23 @@ static struct ccu_common *sun50i_h6_r_ccu_clks[] = { &r_apb1_pwm_clk.common, &r_apb2_uart_clk.common, &r_apb2_i2c_clk.common, + &r_apb2_rsb_clk.common, &r_apb1_ir_clk.common, &r_apb1_w1_clk.common, &ir_clk.common, &w1_clk.common, }; +static struct ccu_common *sun50i_h616_r_ccu_clks[] = { + &r_apb1_clk.common, + &r_apb2_clk.common, + &r_apb1_twd_clk.common, + &r_apb2_i2c_clk.common, + &r_apb2_rsb_clk.common, + &r_apb1_ir_clk.common, + &ir_clk.common, +}; + static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { .hws = { [CLK_AR100] = &ar100_clk.common.hw, @@ -147,6 +160,7 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { [CLK_R_APB1_PWM] = &r_apb1_pwm_clk.common.hw, [CLK_R_APB2_UART] = &r_apb2_uart_clk.common.hw, [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, + [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, [CLK_R_APB1_W1] = &r_apb1_w1_clk.common.hw, [CLK_IR] = &ir_clk.common.hw, @@ -155,16 +169,38 @@ static struct clk_hw_onecell_data sun50i_h6_r_hw_clks = { .num = CLK_NUMBER, }; +static struct clk_hw_onecell_data sun50i_h616_r_hw_clks = { + .hws = { + [CLK_R_AHB] = &r_ahb_clk.hw, + [CLK_R_APB1] = &r_apb1_clk.common.hw, + [CLK_R_APB2] = &r_apb2_clk.common.hw, + [CLK_R_APB1_TWD] = &r_apb1_twd_clk.common.hw, + [CLK_R_APB2_I2C] = &r_apb2_i2c_clk.common.hw, + [CLK_R_APB2_RSB] = &r_apb2_rsb_clk.common.hw, + [CLK_R_APB1_IR] = &r_apb1_ir_clk.common.hw, + [CLK_IR] = &ir_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + static struct ccu_reset_map sun50i_h6_r_ccu_resets[] = { [RST_R_APB1_TIMER] = { 0x11c, BIT(16) }, [RST_R_APB1_TWD] = { 0x12c, BIT(16) }, [RST_R_APB1_PWM] = { 0x13c, BIT(16) }, [RST_R_APB2_UART] = { 0x18c, BIT(16) }, [RST_R_APB2_I2C] = { 0x19c, BIT(16) }, + [RST_R_APB2_RSB] = { 0x1bc, BIT(16) }, [RST_R_APB1_IR] = { 0x1cc, BIT(16) }, [RST_R_APB1_W1] = { 0x1ec, BIT(16) }, }; +static struct ccu_reset_map sun50i_h616_r_ccu_resets[] = { + [RST_R_APB1_TWD] = { 0x12c, BIT(16) }, + [RST_R_APB2_I2C] = { 0x19c, BIT(16) }, + [RST_R_APB2_RSB] = { 0x1bc, BIT(16) }, + [RST_R_APB1_IR] = { 0x1cc, BIT(16) }, +}; + static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = { .ccu_clks = sun50i_h6_r_ccu_clks, .num_ccu_clks = ARRAY_SIZE(sun50i_h6_r_ccu_clks), @@ -175,6 +211,16 @@ static const struct sunxi_ccu_desc sun50i_h6_r_ccu_desc = { .num_resets = ARRAY_SIZE(sun50i_h6_r_ccu_resets), }; +static const struct sunxi_ccu_desc sun50i_h616_r_ccu_desc = { + .ccu_clks = sun50i_h616_r_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_r_ccu_clks), + + .hw_clks = &sun50i_h616_r_hw_clks, + + .resets = sun50i_h616_r_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_h616_r_ccu_resets), +}; + static void __init sunxi_r_ccu_init(struct device_node *node, const struct sunxi_ccu_desc *desc) { @@ -195,3 +241,10 @@ static void __init sun50i_h6_r_ccu_setup(struct device_node *node) } CLK_OF_DECLARE(sun50i_h6_r_ccu, "allwinner,sun50i-h6-r-ccu", sun50i_h6_r_ccu_setup); + +static void __init sun50i_h616_r_ccu_setup(struct device_node *node) +{ + sunxi_r_ccu_init(node, &sun50i_h616_r_ccu_desc); +} +CLK_OF_DECLARE(sun50i_h616_r_ccu, "allwinner,sun50i-h616-r-ccu", + sun50i_h616_r_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h index 782117dc0b28..7e290b840803 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.h @@ -14,6 +14,6 @@ #define CLK_R_APB2 3 -#define CLK_NUMBER (CLK_W1 + 1) +#define CLK_NUMBER (CLK_R_APB2_RSB + 1) #endif /* _CCU_SUN50I_H6_R_H */ diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c index f2497d0a4683..bff446b78290 100644 --- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c @@ -237,7 +237,7 @@ static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", psi_ahb1_ahb2_parents, 0x510, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -246,19 +246,19 @@ static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", "psi-ahb1-ahb2", "pll-periph0" }; static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, - 0, 5, /* M */ + 0, 2, /* M */ 8, 2, /* P */ 24, 2, /* mux */ 0); @@ -682,7 +682,7 @@ static struct ccu_mux hdmi_cec_clk = { .common = { .reg = 0xb10, - .features = CCU_FEATURE_VARIABLE_PREDIV, + .features = CCU_FEATURE_FIXED_PREDIV, .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", hdmi_cec_parents, &ccu_mux_ops, diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c new file mode 100644 index 000000000000..225307305880 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c @@ -0,0 +1,1150 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 Arm Ltd. + * Based on the H6 CCU driver, which is: + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> + */ + +#include <linux/clk-provider.h> +#include <linux/io.h> +#include <linux/of_address.h> +#include <linux/platform_device.h> + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" + +#include "ccu-sun50i-h616.h" + +/* + * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However + * P should only be used for output frequencies lower than 288 MHz. + * + * For now we can just model it as a multiplier clock, and force P to /1. + * + * The M factor is present in the register's description, but not in the + * frequency formula, and it's documented as "M is only used for backdoor + * testing", so it's not modelled and then force to 0. + */ +#define SUN50I_H616_PLL_CPUX_REG 0x000 +static struct ccu_mult pll_cpux_clk = { + .enable = BIT(31), + .lock = BIT(28), + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT("pll-cpux", "osc24M", + &ccu_mult_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ +#define SUN50I_H616_PLL_DDR0_REG 0x010 +static struct ccu_nkmp pll_ddr0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x010, + .hw.init = CLK_HW_INIT("pll-ddr0", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_DDR1_REG 0x018 +static struct ccu_nkmp pll_ddr1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x018, + .hw.init = CLK_HW_INIT("pll-ddr1", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_PERIPH0_REG 0x020 +static struct ccu_nkmp pll_periph0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x020, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_PERIPH1_REG 0x028 +static struct ccu_nkmp pll_periph1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .fixed_post_div = 2, + .common = { + .reg = 0x028, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_GPU_REG 0x030 +static struct ccu_nkmp pll_gpu_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x030, + .hw.init = CLK_HW_INIT("pll-gpu", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * For Video PLLs, the output divider is described as "used for testing" + * in the user manual. So it's not modelled and forced to 0. + */ +#define SUN50I_H616_PLL_VIDEO0_REG 0x040 +static struct ccu_nm pll_video0_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x040, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video0", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VIDEO1_REG 0x048 +static struct ccu_nm pll_video1_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x048, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video1", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VIDEO2_REG 0x050 +static struct ccu_nm pll_video2_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .fixed_post_div = 4, + .min_rate = 288000000, + .max_rate = 2400000000UL, + .common = { + .reg = 0x050, + .features = CCU_FEATURE_FIXED_POSTDIV, + .hw.init = CLK_HW_INIT("pll-video2", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_VE_REG 0x058 +static struct ccu_nkmp pll_ve_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x058, + .hw.init = CLK_HW_INIT("pll-ve", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN50I_H616_PLL_DE_REG 0x060 +static struct ccu_nkmp pll_de_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x060, + .hw.init = CLK_HW_INIT("pll-de", "osc24M", + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * TODO: Determine SDM settings for the audio PLL. The manual suggests + * PLL_FACTOR_N=16, PLL_POST_DIV_P=2, OUTPUT_DIV=2, pattern=0xe000c49b + * for 24.576 MHz, and PLL_FACTOR_N=22, PLL_POST_DIV_P=3, OUTPUT_DIV=2, + * pattern=0xe001288c for 22.5792 MHz. + * This clashes with our fixed PLL_POST_DIV_P. + */ +#define SUN50I_H616_PLL_AUDIO_REG 0x078 +static struct ccu_nm pll_audio_hs_clk = { + .enable = BIT(31), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .common = { + .reg = 0x078, + .hw.init = CLK_HW_INIT("pll-audio-hs", "osc24M", + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const char * const cpux_parents[] = { "osc24M", "osc32k", + "iosc", "pll-cpux", "pll-periph0" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); +static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x500, 0, 2, 0); +static SUNXI_CCU_M(cpux_apb_clk, "cpux-apb", "cpux", 0x500, 8, 2, 0); + +static const char * const psi_ahb1_ahb2_parents[] = { "osc24M", "osc32k", + "iosc", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(psi_ahb1_ahb2_clk, "psi-ahb1-ahb2", + psi_ahb1_ahb2_parents, + 0x510, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const ahb3_apb1_apb2_parents[] = { "osc24M", "osc32k", + "psi-ahb1-ahb2", + "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(ahb3_clk, "ahb3", ahb3_apb1_apb2_parents, 0x51c, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", ahb3_apb1_apb2_parents, 0x520, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", ahb3_apb1_apb2_parents, 0x524, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", + "pll-ddr0", "pll-ddr1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x540, + 0, 3, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_IS_CRITICAL); + +static const char * const de_parents[] = { "pll-de", "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, 0x600, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "psi-ahb1-ahb2", + 0x60c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", + de_parents, + 0x620, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "psi-ahb1-ahb2", + 0x62c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_parents, 0x630, + 0, 4, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_g2d_clk, "bus-g2d", "psi-ahb1-ahb2", + 0x63c, BIT(0), 0); + +static const char * const gpu0_parents[] = { "pll-gpu", "gpu1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(gpu0_clk, "gpu0", gpu0_parents, 0x670, + 0, 2, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M_WITH_GATE(gpu1_clk, "gpu1", "pll-periph0-2x", 0x674, + 0, 2, /* M */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "psi-ahb1-ahb2", + 0x67c, BIT(0), 0); + +static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 1, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "psi-ahb1-ahb2", + 0x68c, BIT(0), 0); + +static const char * const ve_parents[] = { "pll-ve" }; +static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, + 0, 3, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "psi-ahb1-ahb2", + 0x69c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "psi-ahb1-ahb2", + 0x70c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "psi-ahb1-ahb2", + 0x73c, BIT(0), 0); + +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", 0x740, BIT(31), 0); + +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "psi-ahb1-ahb2", + 0x78c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_psi_clk, "bus-psi", "psi-ahb1-ahb2", + 0x79c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_pwm_clk, "bus-pwm", "apb1", 0x7ac, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_iommu_clk, "bus-iommu", "apb1", 0x7bc, BIT(0), 0); + +static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; +static struct ccu_div dram_clk = { + .div = _SUNXI_CCU_DIV(0, 2), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0x800, + .hw.init = CLK_HW_INIT_PARENTS("dram", + dram_parents, + &ccu_div_ops, + CLK_IS_CRITICAL), + }, +}; + +static SUNXI_CCU_GATE(mbus_dma_clk, "mbus-dma", "mbus", + 0x804, BIT(0), 0); +static SUNXI_CCU_GATE(mbus_ve_clk, "mbus-ve", "mbus", + 0x804, BIT(1), 0); +static SUNXI_CCU_GATE(mbus_ce_clk, "mbus-ce", "mbus", + 0x804, BIT(2), 0); +static SUNXI_CCU_GATE(mbus_ts_clk, "mbus-ts", "mbus", + 0x804, BIT(3), 0); +static SUNXI_CCU_GATE(mbus_nand_clk, "mbus-nand", "mbus", + 0x804, BIT(5), 0); +static SUNXI_CCU_GATE(mbus_g2d_clk, "mbus-g2d", "mbus", + 0x804, BIT(10), 0); + +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "psi-ahb1-ahb2", + 0x80c, BIT(0), CLK_IS_CRITICAL); + +static const char * const nand_spi_parents[] = { "osc24M", "pll-periph0", + "pll-periph1", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(nand0_clk, "nand0", nand_spi_parents, 0x810, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(nand1_clk, "nand1", nand_spi_parents, 0x814, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb3", 0x82c, BIT(0), 0); + +static const char * const mmc_parents[] = { "osc24M", "pll-periph0-2x", + "pll-periph1-2x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc0_clk, "mmc0", mmc_parents, 0x830, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc1_clk, "mmc1", mmc_parents, 0x834, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE_POSTDIV(mmc2_clk, "mmc2", mmc_parents, 0x838, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 2, /* post-div */ + 0); + +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb3", 0x84c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb3", 0x84c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb3", 0x84c, BIT(2), 0); + +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", 0x90c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", 0x90c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", 0x90c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", 0x90c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", 0x90c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", 0x90c, BIT(5), 0); + +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", 0x91c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", 0x91c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", 0x91c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", 0x91c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", 0x91c, BIT(4), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", nand_spi_parents, 0x940, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", nand_spi_parents, 0x944, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 3, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb3", 0x96c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb3", 0x96c, BIT(1), 0); + +static SUNXI_CCU_GATE(emac_25m_clk, "emac-25m", "ahb3", 0x970, + BIT(31) | BIT(30), 0); + +static SUNXI_CCU_GATE(bus_emac0_clk, "bus-emac0", "ahb3", 0x97c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_emac1_clk, "bus-emac1", "ahb3", 0x97c, BIT(1), 0); + +static const char * const ts_parents[] = { "osc24M", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x9b0, + 0, 4, /* M */ + 8, 2, /* N */ + 24, 1, /* mux */ + BIT(31),/* gate */ + 0); + +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb3", 0x9bc, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", 0x9fc, BIT(0), 0); + +static const char * const audio_parents[] = { "pll-audio-1x", "pll-audio-2x", + "pll-audio-4x", "pll-audio-hs" }; +static struct ccu_div spdif_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa20, + .hw.init = CLK_HW_INIT_PARENTS("spdif", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", 0xa2c, BIT(0), 0); + +static struct ccu_div dmic_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa40, + .hw.init = CLK_HW_INIT_PARENTS("dmic", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_dmic_clk, "bus-dmic", "apb1", 0xa4c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_1x_clk, "audio-codec-1x", + audio_parents, 0xa50, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_M_WITH_MUX_GATE(audio_codec_4x_clk, "audio-codec-4x", + audio_parents, 0xa54, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_audio_codec_clk, "bus-audio-codec", "apb1", 0xa5c, + BIT(0), 0); + +static struct ccu_div audio_hub_clk = { + .enable = BIT(31), + .div = _SUNXI_CCU_DIV_FLAGS(8, 2, CLK_DIVIDER_POWER_OF_TWO), + .mux = _SUNXI_CCU_MUX(24, 2), + .common = { + .reg = 0xa60, + .hw.init = CLK_HW_INIT_PARENTS("audio-hub", + audio_parents, + &ccu_div_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_audio_hub_clk, "bus-audio-hub", "apb1", 0xa6c, BIT(0), 0); + +/* + * There are OHCI 12M clock source selection bits for the four USB 2.0 ports. + * We will force them to 0 (12M divided from 48M). + */ +#define SUN50I_H616_USB0_CLK_REG 0xa70 +#define SUN50I_H616_USB1_CLK_REG 0xa74 +#define SUN50I_H616_USB2_CLK_REG 0xa78 +#define SUN50I_H616_USB3_CLK_REG 0xa7c + +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", 0xa70, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", 0xa70, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", 0xa74, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", 0xa74, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", 0xa78, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", 0xa78, BIT(29), 0); + +static SUNXI_CCU_GATE(usb_ohci3_clk, "usb-ohci3", "osc12M", 0xa7c, BIT(31), 0); +static SUNXI_CCU_GATE(usb_phy3_clk, "usb-phy3", "osc24M", 0xa7c, BIT(29), 0); + +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb3", 0xa8c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb3", 0xa8c, BIT(1), 0); +static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb3", 0xa8c, BIT(2), 0); +static SUNXI_CCU_GATE(bus_ohci3_clk, "bus-ohci3", "ahb3", 0xa8c, BIT(3), 0); +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb3", 0xa8c, BIT(4), 0); +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb3", 0xa8c, BIT(5), 0); +static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb3", 0xa8c, BIT(6), 0); +static SUNXI_CCU_GATE(bus_ehci3_clk, "bus-ehci3", "ahb3", 0xa8c, BIT(7), 0); +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb3", 0xa8c, BIT(8), 0); + +static SUNXI_CCU_GATE(bus_keyadc_clk, "bus-keyadc", "apb1", 0xa9c, BIT(0), 0); + +static const char * const hdmi_parents[] = { "pll-video0", "pll-video0-4x", + "pll-video2", "pll-video2-4x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, 0xb00, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", 0xb04, BIT(31), 0); + +static const char * const hdmi_cec_parents[] = { "osc32k", "pll-periph0-2x" }; +static const struct ccu_mux_fixed_prediv hdmi_cec_predivs[] = { + { .index = 1, .div = 36621 }, +}; + +#define SUN50I_H616_HDMI_CEC_CLK_REG 0xb10 +static struct ccu_mux hdmi_cec_clk = { + .enable = BIT(31) | BIT(30), + + .mux = { + .shift = 24, + .width = 2, + + .fixed_predivs = hdmi_cec_predivs, + .n_predivs = ARRAY_SIZE(hdmi_cec_predivs), + }, + + .common = { + .reg = 0xb10, + .features = CCU_FEATURE_FIXED_PREDIV, + .hw.init = CLK_HW_INIT_PARENTS("hdmi-cec", + hdmi_cec_parents, + &ccu_mux_ops, + 0), + }, +}; + +static SUNXI_CCU_GATE(bus_hdmi_clk, "bus-hdmi", "ahb3", 0xb1c, BIT(0), 0); + +static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb3", + 0xb5c, BIT(0), 0); + +static const char * const tcon_tv_parents[] = { "pll-video0", + "pll-video0-4x", + "pll-video1", + "pll-video1-4x" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", + tcon_tv_parents, 0xb80, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", + tcon_tv_parents, 0xb84, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb3", + 0xb9c, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb3", + 0xb9c, BIT(1), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(tve0_clk, "tve0", + tcon_tv_parents, 0xbb0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb3", + 0xbbc, BIT(0), 0); +static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb3", + 0xbbc, BIT(1), 0); + +static const char * const hdcp_parents[] = { "pll-periph0", "pll-periph1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(hdcp_clk, "hdcp", hdcp_parents, 0xc40, + 0, 4, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE(bus_hdcp_clk, "bus-hdcp", "ahb3", 0xc4c, BIT(0), 0); + +/* Fixed factor clocks */ +static CLK_FIXED_FACTOR_FW_NAME(osc12M_clk, "osc12M", "hosc", 2, 1, 0); + +static const struct clk_hw *clk_parent_pll_audio[] = { + &pll_audio_hs_clk.common.hw +}; + +/* + * The divider of pll-audio is fixed to 24 for now, so 24576000 and 22579200 + * rates can be set exactly in conjunction with sigma-delta modulation. + */ +static CLK_FIXED_FACTOR_HWS(pll_audio_1x_clk, "pll-audio-1x", + clk_parent_pll_audio, + 96, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_audio_2x_clk, "pll-audio-2x", + clk_parent_pll_audio, + 48, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_audio_4x_clk, "pll-audio-4x", + clk_parent_pll_audio, + 24, 1, CLK_SET_RATE_PARENT); + +static const struct clk_hw *pll_periph0_parents[] = { + &pll_periph0_clk.common.hw +}; + +static CLK_FIXED_FACTOR_HWS(pll_periph0_2x_clk, "pll-periph0-2x", + pll_periph0_parents, + 1, 2, 0); + +static const struct clk_hw *pll_periph1_parents[] = { + &pll_periph1_clk.common.hw +}; + +static CLK_FIXED_FACTOR_HWS(pll_periph1_2x_clk, "pll-periph1-2x", + pll_periph1_parents, + 1, 2, 0); + +static CLK_FIXED_FACTOR_HW(pll_video0_4x_clk, "pll-video0-4x", + &pll_video0_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HW(pll_video1_4x_clk, "pll-video1-4x", + &pll_video1_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HW(pll_video2_4x_clk, "pll-video2-4x", + &pll_video2_clk.common.hw, + 1, 4, CLK_SET_RATE_PARENT); + +static struct ccu_common *sun50i_h616_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_ddr0_clk.common, + &pll_ddr1_clk.common, + &pll_periph0_clk.common, + &pll_periph1_clk.common, + &pll_gpu_clk.common, + &pll_video0_clk.common, + &pll_video1_clk.common, + &pll_video2_clk.common, + &pll_ve_clk.common, + &pll_de_clk.common, + &pll_audio_hs_clk.common, + &cpux_clk.common, + &axi_clk.common, + &cpux_apb_clk.common, + &psi_ahb1_ahb2_clk.common, + &ahb3_clk.common, + &apb1_clk.common, + &apb2_clk.common, + &mbus_clk.common, + &de_clk.common, + &bus_de_clk.common, + &deinterlace_clk.common, + &bus_deinterlace_clk.common, + &g2d_clk.common, + &bus_g2d_clk.common, + &gpu0_clk.common, + &bus_gpu_clk.common, + &gpu1_clk.common, + &ce_clk.common, + &bus_ce_clk.common, + &ve_clk.common, + &bus_ve_clk.common, + &bus_dma_clk.common, + &bus_hstimer_clk.common, + &avs_clk.common, + &bus_dbg_clk.common, + &bus_psi_clk.common, + &bus_pwm_clk.common, + &bus_iommu_clk.common, + &dram_clk.common, + &mbus_dma_clk.common, + &mbus_ve_clk.common, + &mbus_ce_clk.common, + &mbus_ts_clk.common, + &mbus_nand_clk.common, + &mbus_g2d_clk.common, + &bus_dram_clk.common, + &nand0_clk.common, + &nand1_clk.common, + &bus_nand_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_uart5_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_i2c3_clk.common, + &bus_i2c4_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &emac_25m_clk.common, + &bus_emac0_clk.common, + &bus_emac1_clk.common, + &ts_clk.common, + &bus_ts_clk.common, + &bus_ths_clk.common, + &spdif_clk.common, + &bus_spdif_clk.common, + &dmic_clk.common, + &bus_dmic_clk.common, + &audio_codec_1x_clk.common, + &audio_codec_4x_clk.common, + &bus_audio_codec_clk.common, + &audio_hub_clk.common, + &bus_audio_hub_clk.common, + &usb_ohci0_clk.common, + &usb_phy0_clk.common, + &usb_ohci1_clk.common, + &usb_phy1_clk.common, + &usb_ohci2_clk.common, + &usb_phy2_clk.common, + &usb_ohci3_clk.common, + &usb_phy3_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ohci2_clk.common, + &bus_ohci3_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_ehci2_clk.common, + &bus_ehci3_clk.common, + &bus_otg_clk.common, + &bus_keyadc_clk.common, + &hdmi_clk.common, + &hdmi_slow_clk.common, + &hdmi_cec_clk.common, + &bus_hdmi_clk.common, + &bus_tcon_top_clk.common, + &tcon_tv0_clk.common, + &tcon_tv1_clk.common, + &bus_tcon_tv0_clk.common, + &bus_tcon_tv1_clk.common, + &tve0_clk.common, + &bus_tve_top_clk.common, + &bus_tve0_clk.common, + &hdcp_clk.common, + &bus_hdcp_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_h616_hw_clks = { + .hws = { + [CLK_OSC12M] = &osc12M_clk.hw, + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, + [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, + [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.hw, + [CLK_PLL_VIDEO2] = &pll_video2_clk.common.hw, + [CLK_PLL_VIDEO2_4X] = &pll_video2_4x_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_DE] = &pll_de_clk.common.hw, + [CLK_PLL_AUDIO_HS] = &pll_audio_hs_clk.common.hw, + [CLK_PLL_AUDIO_1X] = &pll_audio_1x_clk.hw, + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_AXI] = &axi_clk.common.hw, + [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, + [CLK_PSI_AHB1_AHB2] = &psi_ahb1_ahb2_clk.common.hw, + [CLK_AHB3] = &ahb3_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_APB2] = &apb2_clk.common.hw, + [CLK_MBUS] = &mbus_clk.common.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, + [CLK_G2D] = &g2d_clk.common.hw, + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, + [CLK_GPU0] = &gpu0_clk.common.hw, + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, + [CLK_GPU1] = &gpu1_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_BUS_PSI] = &bus_psi_clk.common.hw, + [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, + [CLK_MBUS_TS] = &mbus_ts_clk.common.hw, + [CLK_MBUS_NAND] = &mbus_nand_clk.common.hw, + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_NAND0] = &nand0_clk.common.hw, + [CLK_NAND1] = &nand1_clk.common.hw, + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_EMAC_25M] = &emac_25m_clk.common.hw, + [CLK_BUS_EMAC0] = &bus_emac0_clk.common.hw, + [CLK_BUS_EMAC1] = &bus_emac1_clk.common.hw, + [CLK_TS] = &ts_clk.common.hw, + [CLK_BUS_TS] = &bus_ts_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_SPDIF] = &spdif_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_DMIC] = &dmic_clk.common.hw, + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, + [CLK_AUDIO_CODEC_1X] = &audio_codec_1x_clk.common.hw, + [CLK_AUDIO_CODEC_4X] = &audio_codec_4x_clk.common.hw, + [CLK_BUS_AUDIO_CODEC] = &bus_audio_codec_clk.common.hw, + [CLK_AUDIO_HUB] = &audio_hub_clk.common.hw, + [CLK_BUS_AUDIO_HUB] = &bus_audio_hub_clk.common.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, + [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, + [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, + [CLK_USB_OHCI3] = &usb_ohci3_clk.common.hw, + [CLK_USB_PHY3] = &usb_phy3_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, + [CLK_BUS_OHCI3] = &bus_ohci3_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, + [CLK_BUS_EHCI3] = &bus_ehci3_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_KEYADC] = &bus_keyadc_clk.common.hw, + [CLK_HDMI] = &hdmi_clk.common.hw, + [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, + [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw, + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, + [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, + [CLK_TVE0] = &tve0_clk.common.hw, + [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, + [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, + [CLK_HDCP] = &hdcp_clk.common.hw, + [CLK_BUS_HDCP] = &bus_hdcp_clk.common.hw, + }, + .num = CLK_NUMBER, +}; + +static struct ccu_reset_map sun50i_h616_ccu_resets[] = { + [RST_MBUS] = { 0x540, BIT(30) }, + + [RST_BUS_DE] = { 0x60c, BIT(16) }, + [RST_BUS_DEINTERLACE] = { 0x62c, BIT(16) }, + [RST_BUS_GPU] = { 0x67c, BIT(16) }, + [RST_BUS_CE] = { 0x68c, BIT(16) }, + [RST_BUS_VE] = { 0x69c, BIT(16) }, + [RST_BUS_DMA] = { 0x70c, BIT(16) }, + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, + [RST_BUS_DBG] = { 0x78c, BIT(16) }, + [RST_BUS_PSI] = { 0x79c, BIT(16) }, + [RST_BUS_PWM] = { 0x7ac, BIT(16) }, + [RST_BUS_IOMMU] = { 0x7bc, BIT(16) }, + [RST_BUS_DRAM] = { 0x80c, BIT(16) }, + [RST_BUS_NAND] = { 0x82c, BIT(16) }, + [RST_BUS_MMC0] = { 0x84c, BIT(16) }, + [RST_BUS_MMC1] = { 0x84c, BIT(17) }, + [RST_BUS_MMC2] = { 0x84c, BIT(18) }, + [RST_BUS_UART0] = { 0x90c, BIT(16) }, + [RST_BUS_UART1] = { 0x90c, BIT(17) }, + [RST_BUS_UART2] = { 0x90c, BIT(18) }, + [RST_BUS_UART3] = { 0x90c, BIT(19) }, + [RST_BUS_UART4] = { 0x90c, BIT(20) }, + [RST_BUS_UART5] = { 0x90c, BIT(21) }, + [RST_BUS_I2C0] = { 0x91c, BIT(16) }, + [RST_BUS_I2C1] = { 0x91c, BIT(17) }, + [RST_BUS_I2C2] = { 0x91c, BIT(18) }, + [RST_BUS_I2C3] = { 0x91c, BIT(19) }, + [RST_BUS_I2C4] = { 0x91c, BIT(20) }, + [RST_BUS_SPI0] = { 0x96c, BIT(16) }, + [RST_BUS_SPI1] = { 0x96c, BIT(17) }, + [RST_BUS_EMAC0] = { 0x97c, BIT(16) }, + [RST_BUS_EMAC1] = { 0x97c, BIT(17) }, + [RST_BUS_TS] = { 0x9bc, BIT(16) }, + [RST_BUS_THS] = { 0x9fc, BIT(16) }, + [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, + [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, + [RST_BUS_AUDIO_CODEC] = { 0xa5c, BIT(16) }, + [RST_BUS_AUDIO_HUB] = { 0xa6c, BIT(16) }, + + [RST_USB_PHY0] = { 0xa70, BIT(30) }, + [RST_USB_PHY1] = { 0xa74, BIT(30) }, + [RST_USB_PHY2] = { 0xa78, BIT(30) }, + [RST_USB_PHY3] = { 0xa7c, BIT(30) }, + [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, + [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, + [RST_BUS_OHCI2] = { 0xa8c, BIT(18) }, + [RST_BUS_OHCI3] = { 0xa8c, BIT(19) }, + [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, + [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, + [RST_BUS_EHCI2] = { 0xa8c, BIT(22) }, + [RST_BUS_EHCI3] = { 0xa8c, BIT(23) }, + [RST_BUS_OTG] = { 0xa8c, BIT(24) }, + [RST_BUS_KEYADC] = { 0xa9c, BIT(16) }, + + [RST_BUS_HDMI] = { 0xb1c, BIT(16) }, + [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) }, + [RST_BUS_TCON_TOP] = { 0xb5c, BIT(16) }, + [RST_BUS_TCON_TV0] = { 0xb9c, BIT(16) }, + [RST_BUS_TCON_TV1] = { 0xb9c, BIT(17) }, + [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, + [RST_BUS_TVE0] = { 0xbbc, BIT(17) }, + [RST_BUS_HDCP] = { 0xc4c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun50i_h616_ccu_desc = { + .ccu_clks = sun50i_h616_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_ccu_clks), + + .hw_clks = &sun50i_h616_hw_clks, + + .resets = sun50i_h616_ccu_resets, + .num_resets = ARRAY_SIZE(sun50i_h616_ccu_resets), +}; + +static const u32 pll_regs[] = { + SUN50I_H616_PLL_CPUX_REG, + SUN50I_H616_PLL_DDR0_REG, + SUN50I_H616_PLL_DDR1_REG, + SUN50I_H616_PLL_PERIPH0_REG, + SUN50I_H616_PLL_PERIPH1_REG, + SUN50I_H616_PLL_GPU_REG, + SUN50I_H616_PLL_VIDEO0_REG, + SUN50I_H616_PLL_VIDEO1_REG, + SUN50I_H616_PLL_VIDEO2_REG, + SUN50I_H616_PLL_VE_REG, + SUN50I_H616_PLL_DE_REG, + SUN50I_H616_PLL_AUDIO_REG, +}; + +static const u32 pll_video_regs[] = { + SUN50I_H616_PLL_VIDEO0_REG, + SUN50I_H616_PLL_VIDEO1_REG, + SUN50I_H616_PLL_VIDEO2_REG, +}; + +static const u32 usb2_clk_regs[] = { + SUN50I_H616_USB0_CLK_REG, + SUN50I_H616_USB1_CLK_REG, + SUN50I_H616_USB2_CLK_REG, + SUN50I_H616_USB3_CLK_REG, +}; + +static void __init sun50i_h616_ccu_setup(struct device_node *node) +{ + void __iomem *reg; + u32 val; + int i; + + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); + if (IS_ERR(reg)) { + pr_err("%pOF: Could not map clock registers\n", node); + return; + } + + /* Enable the lock bits and the output enable bits on all PLLs */ + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { + val = readl(reg + pll_regs[i]); + val |= BIT(29) | BIT(27); + writel(val, reg + pll_regs[i]); + } + + /* + * Force the output divider of video PLLs to 0. + * + * See the comment before pll-video0 definition for the reason. + */ + for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { + val = readl(reg + pll_video_regs[i]); + val &= ~BIT(0); + writel(val, reg + pll_video_regs[i]); + } + + /* + * Force OHCI 12M clock sources to 00 (12MHz divided from 48MHz) + * + * This clock mux is still mysterious, and the code just enforces + * it to have a valid clock parent. + */ + for (i = 0; i < ARRAY_SIZE(usb2_clk_regs); i++) { + val = readl(reg + usb2_clk_regs[i]); + val &= ~GENMASK(25, 24); + writel(val, reg + usb2_clk_regs[i]); + } + + /* + * Force the post-divider of pll-audio to 12 and the output divider + * of it to 2, so 24576000 and 22579200 rates can be set exactly. + */ + val = readl(reg + SUN50I_H616_PLL_AUDIO_REG); + val &= ~(GENMASK(21, 16) | BIT(0)); + writel(val | (11 << 16) | BIT(0), reg + SUN50I_H616_PLL_AUDIO_REG); + + /* + * First clock parent (osc32K) is unusable for CEC. But since there + * is no good way to force parent switch (both run with same frequency), + * just set second clock parent here. + */ + val = readl(reg + SUN50I_H616_HDMI_CEC_CLK_REG); + val |= BIT(24); + writel(val, reg + SUN50I_H616_HDMI_CEC_CLK_REG); + + i = sunxi_ccu_probe(node, reg, &sun50i_h616_ccu_desc); + if (i) + pr_err("%pOF: probing clocks fails: %d\n", node, i); +} + +CLK_OF_DECLARE(sun50i_h616_ccu, "allwinner,sun50i-h616-ccu", + sun50i_h616_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.h b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h new file mode 100644 index 000000000000..dd671b413f22 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.h @@ -0,0 +1,56 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2020 Arm Ltd. + */ + +#ifndef _CCU_SUN50I_H616_H_ +#define _CCU_SUN50I_H616_H_ + +#include <dt-bindings/clock/sun50i-h616-ccu.h> +#include <dt-bindings/reset/sun50i-h616-ccu.h> + +#define CLK_OSC12M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_DDR0 2 +#define CLK_PLL_DDR1 3 + +/* PLL_PERIPH0 exported for PRCM */ + +#define CLK_PLL_PERIPH0_2X 5 +#define CLK_PLL_PERIPH1 6 +#define CLK_PLL_PERIPH1_2X 7 +#define CLK_PLL_GPU 8 +#define CLK_PLL_VIDEO0 9 +#define CLK_PLL_VIDEO0_4X 10 +#define CLK_PLL_VIDEO1 11 +#define CLK_PLL_VIDEO1_4X 12 +#define CLK_PLL_VIDEO2 13 +#define CLK_PLL_VIDEO2_4X 14 +#define CLK_PLL_VE 15 +#define CLK_PLL_DE 16 +#define CLK_PLL_AUDIO_HS 17 +#define CLK_PLL_AUDIO_1X 18 +#define CLK_PLL_AUDIO_2X 19 +#define CLK_PLL_AUDIO_4X 20 + +/* CPUX clock exported for DVFS */ + +#define CLK_AXI 22 +#define CLK_CPUX_APB 23 +#define CLK_PSI_AHB1_AHB2 24 +#define CLK_AHB3 25 + +/* APB1 clock exported for PIO */ + +#define CLK_APB2 27 +#define CLK_MBUS 28 + +/* All module clocks and bus gates are exported except DRAM */ + +#define CLK_DRAM 49 + +#define CLK_BUS_DRAM 56 + +#define CLK_NUMBER (CLK_BUS_HDCP + 1) + +#endif /* _CCU_SUN50I_H616_H_ */ diff --git a/drivers/clk/sunxi/clk-a10-ve.c b/drivers/clk/sunxi/clk-a10-ve.c index cb5daa4b37db..65810937a13a 100644 --- a/drivers/clk/sunxi/clk-a10-ve.c +++ b/drivers/clk/sunxi/clk-a10-ve.c @@ -20,7 +20,7 @@ static DEFINE_SPINLOCK(ve_lock); #define SUN4I_VE_DIVIDER_WIDTH 3 #define SUN4I_VE_RESET 0 -/** +/* * sunxi_ve_reset... - reset bit in ve clk registers handling */ diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index 0cca91e075a5..f9d715ec9908 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -14,7 +14,7 @@ #include "clk-factors.h" -/** +/* * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks * MOD0 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c index e1aa1fbac48a..5fe7049ea693 100644 --- a/drivers/clk/sunxi/clk-sunxi.c +++ b/drivers/clk/sunxi/clk-sunxi.c @@ -23,7 +23,7 @@ static DEFINE_SPINLOCK(clk_lock); /* Maximum number of parents our clocks have */ #define SUNXI_MAX_PARENTS 5 -/** +/* * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1 * PLL1 rate is calculated as follows * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); @@ -71,7 +71,7 @@ static void sun4i_get_pll1_factors(struct factors_request *req) req->n = div / 4; } -/** +/* * sun6i_a31_get_pll1_factors() - calculates n, k and m factors for PLL1 * PLL1 rate is calculated as follows * rate = parent_rate * (n + 1) * (k + 1) / (m + 1); @@ -147,7 +147,7 @@ static void sun6i_a31_get_pll1_factors(struct factors_request *req) } } -/** +/* * sun8i_a23_get_pll1_factors() - calculates n, k, m, p factors for PLL1 * PLL1 rate is calculated as follows * rate = (parent_rate * (n + 1) * (k + 1) >> p) / (m + 1); @@ -191,7 +191,7 @@ static void sun8i_a23_get_pll1_factors(struct factors_request *req) req->n = div / 4 - 1; } -/** +/* * sun4i_get_pll5_factors() - calculates n, k factors for PLL5 * PLL5 rate is calculated as follows * rate = parent_rate * n * (k + 1) @@ -218,7 +218,7 @@ static void sun4i_get_pll5_factors(struct factors_request *req) req->n = DIV_ROUND_UP(div, (req->k + 1)); } -/** +/* * sun6i_a31_get_pll6_factors() - calculates n, k factors for A31 PLL6x2 * PLL6x2 rate is calculated as follows * rate = parent_rate * (n + 1) * (k + 1) @@ -240,7 +240,7 @@ static void sun6i_a31_get_pll6_factors(struct factors_request *req) req->n = DIV_ROUND_UP(div, (req->k + 1)) - 1; } -/** +/* * sun5i_a13_get_ahb_factors() - calculates m, p factors for AHB * AHB rate is calculated as follows * rate = parent_rate >> p @@ -276,7 +276,7 @@ static void sun5i_a13_get_ahb_factors(struct factors_request *req) #define SUN6I_AHB1_PARENT_PLL6 3 -/** +/* * sun6i_a31_get_ahb_factors() - calculates m, p factors for AHB * AHB rate is calculated as follows * rate = parent_rate >> p @@ -320,7 +320,7 @@ static void sun6i_get_ahb1_factors(struct factors_request *req) req->m = calcm - 1; } -/** +/* * sun6i_ahb1_recalc() - calculates AHB clock rate from m, p factors and * parent index */ @@ -336,7 +336,7 @@ static void sun6i_ahb1_recalc(struct factors_request *req) req->rate >>= req->p; } -/** +/* * sun4i_get_apb1_factors() - calculates m, p factors for APB1 * APB1 rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); @@ -375,7 +375,7 @@ static void sun4i_get_apb1_factors(struct factors_request *req) -/** +/* * sun7i_a20_get_out_factors() - calculates m, p factors for CLK_OUT_A/B * CLK_OUT rate is calculated as follows * rate = (parent_rate >> p) / (m + 1); @@ -408,7 +408,7 @@ static void sun7i_a20_get_out_factors(struct factors_request *req) req->p = calcp; } -/** +/* * sunxi_factors_clk_setup() - Setup function for factor clocks */ @@ -625,7 +625,7 @@ CLK_OF_DECLARE(sun7i_out, "allwinner,sun7i-a20-out-clk", sun7i_out_clk_setup); -/** +/* * sunxi_mux_clk_setup() - Setup function for muxes */ @@ -717,7 +717,7 @@ CLK_OF_DECLARE(sun8i_ahb2, "allwinner,sun8i-h3-ahb2-clk", sun8i_ahb2_clk_setup); -/** +/* * sunxi_divider_clk_setup() - Setup function for simple divider clocks */ @@ -853,7 +853,7 @@ CLK_OF_DECLARE(sun8i_axi, "allwinner,sun8i-a23-axi-clk", -/** +/* * sunxi_gates_clk_setup() - Setup function for leaf gates on clocks */ @@ -863,7 +863,7 @@ struct gates_data { DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE); }; -/** +/* * sunxi_divs_clk_setup() helper data */ @@ -929,7 +929,7 @@ static const struct divs_data sun6i_a31_pll6_divs_data __initconst = { } }; -/** +/* * sunxi_divs_clk_setup() - Setup function for leaf divisors on clocks * * These clocks look something like this diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig new file mode 100644 index 000000000000..5224114176ed --- /dev/null +++ b/drivers/clk/xilinx/Kconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: GPL-2.0 + +config XILINX_VCU + tristate "Xilinx VCU logicoreIP Init" + depends on HAS_IOMEM && COMMON_CLK + select REGMAP_MMIO + help + Provides the driver to enable and disable the isolation between the + processing system and programmable logic part by using the logicoreIP + register set. This driver also configures the frequency based on the + clock information from the logicoreIP register set. + + If you say yes here you get support for the logicoreIP. + + If unsure, say N. + + To compile this driver as a module, choose M here: the + module will be called xlnx_vcu. + diff --git a/drivers/clk/xilinx/Makefile b/drivers/clk/xilinx/Makefile new file mode 100644 index 000000000000..dee8fd51e303 --- /dev/null +++ b/drivers/clk/xilinx/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o diff --git a/drivers/clk/xilinx/xlnx_vcu.c b/drivers/clk/xilinx/xlnx_vcu.c new file mode 100644 index 000000000000..d66b1315114e --- /dev/null +++ b/drivers/clk/xilinx/xlnx_vcu.c @@ -0,0 +1,743 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx VCU Init + * + * Copyright (C) 2016 - 2017 Xilinx, Inc. + * + * Contacts Dhaval Shah <dshah@xilinx.com> + */ +#include <linux/bitfield.h> +#include <linux/clk.h> +#include <linux/clk-provider.h> +#include <linux/device.h> +#include <linux/errno.h> +#include <linux/io.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/xlnx-vcu.h> +#include <linux/module.h> +#include <linux/of_platform.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include <dt-bindings/clock/xlnx-vcu.h> + +#define VCU_PLL_CTRL 0x24 +#define VCU_PLL_CTRL_RESET BIT(0) +#define VCU_PLL_CTRL_POR_IN BIT(1) +#define VCU_PLL_CTRL_PWR_POR BIT(2) +#define VCU_PLL_CTRL_BYPASS BIT(3) +#define VCU_PLL_CTRL_FBDIV GENMASK(14, 8) +#define VCU_PLL_CTRL_CLKOUTDIV GENMASK(18, 16) + +#define VCU_PLL_CFG 0x28 +#define VCU_PLL_CFG_RES GENMASK(3, 0) +#define VCU_PLL_CFG_CP GENMASK(8, 5) +#define VCU_PLL_CFG_LFHF GENMASK(12, 10) +#define VCU_PLL_CFG_LOCK_CNT GENMASK(22, 13) +#define VCU_PLL_CFG_LOCK_DLY GENMASK(31, 25) +#define VCU_ENC_CORE_CTRL 0x30 +#define VCU_ENC_MCU_CTRL 0x34 +#define VCU_DEC_CORE_CTRL 0x38 +#define VCU_DEC_MCU_CTRL 0x3c +#define VCU_PLL_STATUS 0x60 +#define VCU_PLL_STATUS_LOCK_STATUS BIT(0) + +#define MHZ 1000000 +#define FVCO_MIN (1500U * MHZ) +#define FVCO_MAX (3000U * MHZ) + +/** + * struct xvcu_device - Xilinx VCU init device structure + * @dev: Platform device + * @pll_ref: pll ref clock source + * @aclk: axi clock source + * @logicore_reg_ba: logicore reg base address + * @vcu_slcr_ba: vcu_slcr Register base address + * @pll: handle for the VCU PLL + * @pll_post: handle for the VCU PLL post divider + * @clk_data: clocks provided by the vcu clock provider + */ +struct xvcu_device { + struct device *dev; + struct clk *pll_ref; + struct clk *aclk; + struct regmap *logicore_reg_ba; + void __iomem *vcu_slcr_ba; + struct clk_hw *pll; + struct clk_hw *pll_post; + struct clk_hw_onecell_data *clk_data; +}; + +static struct regmap_config vcu_settings_regmap_config = { + .name = "regmap", + .reg_bits = 32, + .val_bits = 32, + .reg_stride = 4, + .max_register = 0xfff, + .cache_type = REGCACHE_NONE, +}; + +/** + * struct xvcu_pll_cfg - Helper data + * @fbdiv: The integer portion of the feedback divider to the PLL + * @cp: PLL charge pump control + * @res: PLL loop filter resistor control + * @lfhf: PLL loop filter high frequency capacitor control + * @lock_dly: Lock circuit configuration settings for lock windowsize + * @lock_cnt: Lock circuit counter setting + */ +struct xvcu_pll_cfg { + u32 fbdiv; + u32 cp; + u32 res; + u32 lfhf; + u32 lock_dly; + u32 lock_cnt; +}; + +static const struct xvcu_pll_cfg xvcu_pll_cfg[] = { + { 25, 3, 10, 3, 63, 1000 }, + { 26, 3, 10, 3, 63, 1000 }, + { 27, 4, 6, 3, 63, 1000 }, + { 28, 4, 6, 3, 63, 1000 }, + { 29, 4, 6, 3, 63, 1000 }, + { 30, 4, 6, 3, 63, 1000 }, + { 31, 6, 1, 3, 63, 1000 }, + { 32, 6, 1, 3, 63, 1000 }, + { 33, 4, 10, 3, 63, 1000 }, + { 34, 5, 6, 3, 63, 1000 }, + { 35, 5, 6, 3, 63, 1000 }, + { 36, 5, 6, 3, 63, 1000 }, + { 37, 5, 6, 3, 63, 1000 }, + { 38, 5, 6, 3, 63, 975 }, + { 39, 3, 12, 3, 63, 950 }, + { 40, 3, 12, 3, 63, 925 }, + { 41, 3, 12, 3, 63, 900 }, + { 42, 3, 12, 3, 63, 875 }, + { 43, 3, 12, 3, 63, 850 }, + { 44, 3, 12, 3, 63, 850 }, + { 45, 3, 12, 3, 63, 825 }, + { 46, 3, 12, 3, 63, 800 }, + { 47, 3, 12, 3, 63, 775 }, + { 48, 3, 12, 3, 63, 775 }, + { 49, 3, 12, 3, 63, 750 }, + { 50, 3, 12, 3, 63, 750 }, + { 51, 3, 2, 3, 63, 725 }, + { 52, 3, 2, 3, 63, 700 }, + { 53, 3, 2, 3, 63, 700 }, + { 54, 3, 2, 3, 63, 675 }, + { 55, 3, 2, 3, 63, 675 }, + { 56, 3, 2, 3, 63, 650 }, + { 57, 3, 2, 3, 63, 650 }, + { 58, 3, 2, 3, 63, 625 }, + { 59, 3, 2, 3, 63, 625 }, + { 60, 3, 2, 3, 63, 625 }, + { 61, 3, 2, 3, 63, 600 }, + { 62, 3, 2, 3, 63, 600 }, + { 63, 3, 2, 3, 63, 600 }, + { 64, 3, 2, 3, 63, 600 }, + { 65, 3, 2, 3, 63, 600 }, + { 66, 3, 2, 3, 63, 600 }, + { 67, 3, 2, 3, 63, 600 }, + { 68, 3, 2, 3, 63, 600 }, + { 69, 3, 2, 3, 63, 600 }, + { 70, 3, 2, 3, 63, 600 }, + { 71, 3, 2, 3, 63, 600 }, + { 72, 3, 2, 3, 63, 600 }, + { 73, 3, 2, 3, 63, 600 }, + { 74, 3, 2, 3, 63, 600 }, + { 75, 3, 2, 3, 63, 600 }, + { 76, 3, 2, 3, 63, 600 }, + { 77, 3, 2, 3, 63, 600 }, + { 78, 3, 2, 3, 63, 600 }, + { 79, 3, 2, 3, 63, 600 }, + { 80, 3, 2, 3, 63, 600 }, + { 81, 3, 2, 3, 63, 600 }, + { 82, 3, 2, 3, 63, 600 }, + { 83, 4, 2, 3, 63, 600 }, + { 84, 4, 2, 3, 63, 600 }, + { 85, 4, 2, 3, 63, 600 }, + { 86, 4, 2, 3, 63, 600 }, + { 87, 4, 2, 3, 63, 600 }, + { 88, 4, 2, 3, 63, 600 }, + { 89, 4, 2, 3, 63, 600 }, + { 90, 4, 2, 3, 63, 600 }, + { 91, 4, 2, 3, 63, 600 }, + { 92, 4, 2, 3, 63, 600 }, + { 93, 4, 2, 3, 63, 600 }, + { 94, 4, 2, 3, 63, 600 }, + { 95, 4, 2, 3, 63, 600 }, + { 96, 4, 2, 3, 63, 600 }, + { 97, 4, 2, 3, 63, 600 }, + { 98, 4, 2, 3, 63, 600 }, + { 99, 4, 2, 3, 63, 600 }, + { 100, 4, 2, 3, 63, 600 }, + { 101, 4, 2, 3, 63, 600 }, + { 102, 4, 2, 3, 63, 600 }, + { 103, 5, 2, 3, 63, 600 }, + { 104, 5, 2, 3, 63, 600 }, + { 105, 5, 2, 3, 63, 600 }, + { 106, 5, 2, 3, 63, 600 }, + { 107, 3, 4, 3, 63, 600 }, + { 108, 3, 4, 3, 63, 600 }, + { 109, 3, 4, 3, 63, 600 }, + { 110, 3, 4, 3, 63, 600 }, + { 111, 3, 4, 3, 63, 600 }, + { 112, 3, 4, 3, 63, 600 }, + { 113, 3, 4, 3, 63, 600 }, + { 114, 3, 4, 3, 63, 600 }, + { 115, 3, 4, 3, 63, 600 }, + { 116, 3, 4, 3, 63, 600 }, + { 117, 3, 4, 3, 63, 600 }, + { 118, 3, 4, 3, 63, 600 }, + { 119, 3, 4, 3, 63, 600 }, + { 120, 3, 4, 3, 63, 600 }, + { 121, 3, 4, 3, 63, 600 }, + { 122, 3, 4, 3, 63, 600 }, + { 123, 3, 4, 3, 63, 600 }, + { 124, 3, 4, 3, 63, 600 }, + { 125, 3, 4, 3, 63, 600 }, +}; + +/** + * xvcu_read - Read from the VCU register space + * @iomem: vcu reg space base address + * @offset: vcu reg offset from base + * + * Return: Returns 32bit value from VCU register specified + * + */ +static inline u32 xvcu_read(void __iomem *iomem, u32 offset) +{ + return ioread32(iomem + offset); +} + +/** + * xvcu_write - Write to the VCU register space + * @iomem: vcu reg space base address + * @offset: vcu reg offset from base + * @value: Value to write + */ +static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) +{ + iowrite32(value, iomem + offset); +} + +#define to_vcu_pll(_hw) container_of(_hw, struct vcu_pll, hw) + +struct vcu_pll { + struct clk_hw hw; + void __iomem *reg_base; + unsigned long fvco_min; + unsigned long fvco_max; +}; + +static int xvcu_pll_wait_for_lock(struct vcu_pll *pll) +{ + void __iomem *base = pll->reg_base; + unsigned long timeout; + u32 lock_status; + + timeout = jiffies + msecs_to_jiffies(2000); + do { + lock_status = xvcu_read(base, VCU_PLL_STATUS); + if (lock_status & VCU_PLL_STATUS_LOCK_STATUS) + return 0; + } while (!time_after(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static struct clk_hw *xvcu_register_pll_post(struct device *dev, + const char *name, + const struct clk_hw *parent_hw, + void __iomem *reg_base) +{ + u32 div; + u32 vcu_pll_ctrl; + + /* + * The output divider of the PLL must be set to 1/2 to meet the + * timing in the design. + */ + vcu_pll_ctrl = xvcu_read(reg_base, VCU_PLL_CTRL); + div = FIELD_GET(VCU_PLL_CTRL_CLKOUTDIV, vcu_pll_ctrl); + if (div != 1) + return ERR_PTR(-EINVAL); + + return clk_hw_register_fixed_factor(dev, "vcu_pll_post", + clk_hw_get_name(parent_hw), + CLK_SET_RATE_PARENT, 1, 2); +} + +static const struct xvcu_pll_cfg *xvcu_find_cfg(int div) +{ + const struct xvcu_pll_cfg *cfg = NULL; + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(xvcu_pll_cfg) - 1; i++) + if (xvcu_pll_cfg[i].fbdiv == div) + cfg = &xvcu_pll_cfg[i]; + + return cfg; +} + +static int xvcu_pll_set_div(struct vcu_pll *pll, int div) +{ + void __iomem *base = pll->reg_base; + const struct xvcu_pll_cfg *cfg = NULL; + u32 vcu_pll_ctrl; + u32 cfg_val; + + cfg = xvcu_find_cfg(div); + if (!cfg) + return -EINVAL; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_FBDIV; + vcu_pll_ctrl |= FIELD_PREP(VCU_PLL_CTRL_FBDIV, cfg->fbdiv); + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + cfg_val = FIELD_PREP(VCU_PLL_CFG_RES, cfg->res) | + FIELD_PREP(VCU_PLL_CFG_CP, cfg->cp) | + FIELD_PREP(VCU_PLL_CFG_LFHF, cfg->lfhf) | + FIELD_PREP(VCU_PLL_CFG_LOCK_CNT, cfg->lock_cnt) | + FIELD_PREP(VCU_PLL_CFG_LOCK_DLY, cfg->lock_dly); + xvcu_write(base, VCU_PLL_CFG, cfg_val); + + return 0; +} + +static long xvcu_pll_round_rate(struct clk_hw *hw, + unsigned long rate, unsigned long *parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + unsigned int feedback_div; + + rate = clamp_t(unsigned long, rate, pll->fvco_min, pll->fvco_max); + + feedback_div = DIV_ROUND_CLOSEST_ULL(rate, *parent_rate); + feedback_div = clamp_t(unsigned int, feedback_div, 25, 125); + + return *parent_rate * feedback_div; +} + +static unsigned long xvcu_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + unsigned int div; + u32 vcu_pll_ctrl; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + div = FIELD_GET(VCU_PLL_CTRL_FBDIV, vcu_pll_ctrl); + + return div * parent_rate; +} + +static int xvcu_pll_set_rate(struct clk_hw *hw, + unsigned long rate, unsigned long parent_rate) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + + return xvcu_pll_set_div(pll, rate / parent_rate); +} + +static int xvcu_pll_enable(struct clk_hw *hw) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + u32 vcu_pll_ctrl; + int ret; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl |= VCU_PLL_CTRL_BYPASS; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_POR_IN; + vcu_pll_ctrl &= ~VCU_PLL_CTRL_PWR_POR; + vcu_pll_ctrl &= ~VCU_PLL_CTRL_RESET; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + + ret = xvcu_pll_wait_for_lock(pll); + if (ret) { + pr_err("VCU PLL is not locked\n"); + goto err; + } + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl &= ~VCU_PLL_CTRL_BYPASS; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); + +err: + return ret; +} + +static void xvcu_pll_disable(struct clk_hw *hw) +{ + struct vcu_pll *pll = to_vcu_pll(hw); + void __iomem *base = pll->reg_base; + u32 vcu_pll_ctrl; + + vcu_pll_ctrl = xvcu_read(base, VCU_PLL_CTRL); + vcu_pll_ctrl |= VCU_PLL_CTRL_POR_IN; + vcu_pll_ctrl |= VCU_PLL_CTRL_PWR_POR; + vcu_pll_ctrl |= VCU_PLL_CTRL_RESET; + xvcu_write(base, VCU_PLL_CTRL, vcu_pll_ctrl); +} + +static const struct clk_ops vcu_pll_ops = { + .enable = xvcu_pll_enable, + .disable = xvcu_pll_disable, + .round_rate = xvcu_pll_round_rate, + .recalc_rate = xvcu_pll_recalc_rate, + .set_rate = xvcu_pll_set_rate, +}; + +static struct clk_hw *xvcu_register_pll(struct device *dev, + void __iomem *reg_base, + const char *name, const char *parent, + unsigned long flags) +{ + struct vcu_pll *pll; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + init.name = name; + init.parent_names = &parent; + init.ops = &vcu_pll_ops; + init.num_parents = 1; + init.flags = flags; + + pll = devm_kmalloc(dev, sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + pll->hw.init = &init; + pll->reg_base = reg_base; + pll->fvco_min = FVCO_MIN; + pll->fvco_max = FVCO_MAX; + + hw = &pll->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + + clk_hw_set_rate_range(hw, pll->fvco_min, pll->fvco_max); + + return hw; +} + +static struct clk_hw *xvcu_clk_hw_register_leaf(struct device *dev, + const char *name, + const struct clk_parent_data *parent_data, + u8 num_parents, + void __iomem *reg) +{ + u8 mux_flags = CLK_MUX_ROUND_CLOSEST; + u8 divider_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO | + CLK_DIVIDER_ROUND_CLOSEST; + struct clk_hw *mux = NULL; + struct clk_hw *divider = NULL; + struct clk_hw *gate = NULL; + char *name_mux; + char *name_div; + int err; + /* Protect register shared by clocks */ + spinlock_t *lock; + + lock = devm_kzalloc(dev, sizeof(*lock), GFP_KERNEL); + if (!lock) + return ERR_PTR(-ENOMEM); + spin_lock_init(lock); + + name_mux = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_mux"); + if (!name_mux) + return ERR_PTR(-ENOMEM); + mux = clk_hw_register_mux_parent_data(dev, name_mux, + parent_data, num_parents, + CLK_SET_RATE_PARENT, + reg, 0, 1, mux_flags, lock); + if (IS_ERR(mux)) + return mux; + + name_div = devm_kasprintf(dev, GFP_KERNEL, "%s%s", name, "_div"); + if (!name_div) { + err = -ENOMEM; + goto unregister_mux; + } + divider = clk_hw_register_divider_parent_hw(dev, name_div, mux, + CLK_SET_RATE_PARENT, + reg, 4, 6, divider_flags, + lock); + if (IS_ERR(divider)) { + err = PTR_ERR(divider); + goto unregister_mux; + } + + gate = clk_hw_register_gate_parent_hw(dev, name, divider, + CLK_SET_RATE_PARENT, reg, 12, 0, + lock); + if (IS_ERR(gate)) { + err = PTR_ERR(gate); + goto unregister_divider; + } + + return gate; + +unregister_divider: + clk_hw_unregister_divider(divider); +unregister_mux: + clk_hw_unregister_mux(mux); + + return ERR_PTR(err); +} + +static void xvcu_clk_hw_unregister_leaf(struct clk_hw *hw) +{ + struct clk_hw *gate = hw; + struct clk_hw *divider; + struct clk_hw *mux; + + if (!gate) + return; + + divider = clk_hw_get_parent(gate); + clk_hw_unregister_gate(gate); + if (!divider) + return; + + mux = clk_hw_get_parent(divider); + clk_hw_unregister_mux(mux); + if (!divider) + return; + + clk_hw_unregister_divider(divider); +} + +static int xvcu_register_clock_provider(struct xvcu_device *xvcu) +{ + struct device *dev = xvcu->dev; + struct clk_parent_data parent_data[2] = { 0 }; + struct clk_hw_onecell_data *data; + struct clk_hw **hws; + struct clk_hw *hw; + void __iomem *reg_base = xvcu->vcu_slcr_ba; + + data = devm_kzalloc(dev, struct_size(data, hws, CLK_XVCU_NUM_CLOCKS), GFP_KERNEL); + if (!data) + return -ENOMEM; + data->num = CLK_XVCU_NUM_CLOCKS; + hws = data->hws; + + xvcu->clk_data = data; + + hw = xvcu_register_pll(dev, reg_base, + "vcu_pll", __clk_get_name(xvcu->pll_ref), + CLK_SET_RATE_NO_REPARENT | CLK_OPS_PARENT_ENABLE); + if (IS_ERR(hw)) + return PTR_ERR(hw); + xvcu->pll = hw; + + hw = xvcu_register_pll_post(dev, "vcu_pll_post", xvcu->pll, reg_base); + if (IS_ERR(hw)) + return PTR_ERR(hw); + xvcu->pll_post = hw; + + parent_data[0].fw_name = "pll_ref"; + parent_data[1].hw = xvcu->pll_post; + + hws[CLK_XVCU_ENC_CORE] = + xvcu_clk_hw_register_leaf(dev, "venc_core_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_ENC_CORE_CTRL); + hws[CLK_XVCU_ENC_MCU] = + xvcu_clk_hw_register_leaf(dev, "venc_mcu_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_ENC_MCU_CTRL); + hws[CLK_XVCU_DEC_CORE] = + xvcu_clk_hw_register_leaf(dev, "vdec_core_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_DEC_CORE_CTRL); + hws[CLK_XVCU_DEC_MCU] = + xvcu_clk_hw_register_leaf(dev, "vdec_mcu_clk", + parent_data, + ARRAY_SIZE(parent_data), + reg_base + VCU_DEC_MCU_CTRL); + + return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, data); +} + +static void xvcu_unregister_clock_provider(struct xvcu_device *xvcu) +{ + struct clk_hw_onecell_data *data = xvcu->clk_data; + struct clk_hw **hws = data->hws; + + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_MCU])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_MCU]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_DEC_CORE])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_DEC_CORE]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_MCU])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_MCU]); + if (!IS_ERR_OR_NULL(hws[CLK_XVCU_ENC_CORE])) + xvcu_clk_hw_unregister_leaf(hws[CLK_XVCU_ENC_CORE]); + + clk_hw_unregister_fixed_factor(xvcu->pll_post); +} + +/** + * xvcu_probe - Probe existence of the logicoreIP + * and initialize PLL + * + * @pdev: Pointer to the platform_device structure + * + * Return: Returns 0 on success + * Negative error code otherwise + */ +static int xvcu_probe(struct platform_device *pdev) +{ + struct resource *res; + struct xvcu_device *xvcu; + void __iomem *regs; + int ret; + + xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); + if (!xvcu) + return -ENOMEM; + + xvcu->dev = &pdev->dev; + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); + if (!res) { + dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); + return -ENODEV; + } + + xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, + resource_size(res)); + if (!xvcu->vcu_slcr_ba) { + dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); + return -ENOMEM; + } + + xvcu->logicore_reg_ba = + syscon_regmap_lookup_by_compatible("xlnx,vcu-settings"); + if (IS_ERR(xvcu->logicore_reg_ba)) { + dev_info(&pdev->dev, + "could not find xlnx,vcu-settings: trying direct register access\n"); + + res = platform_get_resource_byname(pdev, + IORESOURCE_MEM, "logicore"); + if (!res) { + dev_err(&pdev->dev, "get logicore memory resource failed.\n"); + return -ENODEV; + } + + regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); + if (!regs) { + dev_err(&pdev->dev, "logicore register mapping failed.\n"); + return -ENOMEM; + } + + xvcu->logicore_reg_ba = + devm_regmap_init_mmio(&pdev->dev, regs, + &vcu_settings_regmap_config); + if (IS_ERR(xvcu->logicore_reg_ba)) { + dev_err(&pdev->dev, "failed to init regmap\n"); + return PTR_ERR(xvcu->logicore_reg_ba); + } + } + + xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); + if (IS_ERR(xvcu->aclk)) { + dev_err(&pdev->dev, "Could not get aclk clock\n"); + return PTR_ERR(xvcu->aclk); + } + + xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); + if (IS_ERR(xvcu->pll_ref)) { + dev_err(&pdev->dev, "Could not get pll_ref clock\n"); + return PTR_ERR(xvcu->pll_ref); + } + + ret = clk_prepare_enable(xvcu->aclk); + if (ret) { + dev_err(&pdev->dev, "aclk clock enable failed\n"); + return ret; + } + + /* + * Do the Gasket isolation and put the VCU out of reset + * Bit 0 : Gasket isolation + * Bit 1 : put VCU out of reset + */ + regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); + + ret = xvcu_register_clock_provider(xvcu); + if (ret) { + dev_err(&pdev->dev, "failed to register clock provider\n"); + goto error_clk_provider; + } + + dev_set_drvdata(&pdev->dev, xvcu); + + return 0; + +error_clk_provider: + xvcu_unregister_clock_provider(xvcu); + clk_disable_unprepare(xvcu->aclk); + return ret; +} + +/** + * xvcu_remove - Insert gasket isolation + * and disable the clock + * @pdev: Pointer to the platform_device structure + * + * Return: Returns 0 on success + * Negative error code otherwise + */ +static int xvcu_remove(struct platform_device *pdev) +{ + struct xvcu_device *xvcu; + + xvcu = platform_get_drvdata(pdev); + if (!xvcu) + return -ENODEV; + + xvcu_unregister_clock_provider(xvcu); + + /* Add the Gasket isolation and put the VCU in reset. */ + regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); + + clk_disable_unprepare(xvcu->aclk); + + return 0; +} + +static const struct of_device_id xvcu_of_id_table[] = { + { .compatible = "xlnx,vcu" }, + { .compatible = "xlnx,vcu-logicoreip-1.0" }, + { } +}; +MODULE_DEVICE_TABLE(of, xvcu_of_id_table); + +static struct platform_driver xvcu_driver = { + .driver = { + .name = "xilinx-vcu", + .of_match_table = xvcu_of_id_table, + }, + .probe = xvcu_probe, + .remove = xvcu_remove, +}; + +module_platform_driver(xvcu_driver); + +MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>"); +MODULE_DESCRIPTION("Xilinx VCU init Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/clk/zte/Makefile b/drivers/clk/zte/Makefile deleted file mode 100644 index f130643b695d..000000000000 --- a/drivers/clk/zte/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y := clk.o -obj-$(CONFIG_SOC_ZX296702) += clk-zx296702.o -obj-$(CONFIG_ARCH_ZX) += clk-zx296718.o diff --git a/drivers/clk/zte/clk-zx296702.c b/drivers/clk/zte/clk-zx296702.c deleted file mode 100644 index e846f2a34feb..000000000000 --- a/drivers/clk/zte/clk-zx296702.c +++ /dev/null @@ -1,741 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2014 Linaro Ltd. - * Copyright (C) 2014 ZTE Corporation. - */ - -#include <linux/clk-provider.h> -#include <linux/of_address.h> -#include <dt-bindings/clock/zx296702-clock.h> -#include "clk.h" - -static DEFINE_SPINLOCK(reg_lock); - -static void __iomem *topcrm_base; -static void __iomem *lsp0crpm_base; -static void __iomem *lsp1crpm_base; - -static struct clk *topclk[ZX296702_TOPCLK_END]; -static struct clk *lsp0clk[ZX296702_LSP0CLK_END]; -static struct clk *lsp1clk[ZX296702_LSP1CLK_END]; - -static struct clk_onecell_data topclk_data; -static struct clk_onecell_data lsp0clk_data; -static struct clk_onecell_data lsp1clk_data; - -#define CLK_MUX (topcrm_base + 0x04) -#define CLK_DIV (topcrm_base + 0x08) -#define CLK_EN0 (topcrm_base + 0x0c) -#define CLK_EN1 (topcrm_base + 0x10) -#define VOU_LOCAL_CLKEN (topcrm_base + 0x68) -#define VOU_LOCAL_CLKSEL (topcrm_base + 0x70) -#define VOU_LOCAL_DIV2_SET (topcrm_base + 0x74) -#define CLK_MUX1 (topcrm_base + 0x8c) - -#define CLK_SDMMC1 (lsp0crpm_base + 0x0c) -#define CLK_GPIO (lsp0crpm_base + 0x2c) -#define CLK_SPDIF0 (lsp0crpm_base + 0x10) -#define SPDIF0_DIV (lsp0crpm_base + 0x14) -#define CLK_I2S0 (lsp0crpm_base + 0x18) -#define I2S0_DIV (lsp0crpm_base + 0x1c) -#define CLK_I2S1 (lsp0crpm_base + 0x20) -#define I2S1_DIV (lsp0crpm_base + 0x24) -#define CLK_I2S2 (lsp0crpm_base + 0x34) -#define I2S2_DIV (lsp0crpm_base + 0x38) - -#define CLK_UART0 (lsp1crpm_base + 0x20) -#define CLK_UART1 (lsp1crpm_base + 0x24) -#define CLK_SDMMC0 (lsp1crpm_base + 0x2c) -#define CLK_SPDIF1 (lsp1crpm_base + 0x30) -#define SPDIF1_DIV (lsp1crpm_base + 0x34) - -static const struct zx_pll_config pll_a9_config[] = { - { .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 }, - { .rate = 800000000, .cfg0 = 0x80040691, .cfg1 = 0x04aaaaaa }, - { .rate = 900000000, .cfg0 = 0x80040791, .cfg1 = 0x04000000 }, - { .rate = 1000000000, .cfg0 = 0x80040851, .cfg1 = 0x04555555 }, - { .rate = 1100000000, .cfg0 = 0x80040911, .cfg1 = 0x04aaaaaa }, - { .rate = 1200000000, .cfg0 = 0x80040a11, .cfg1 = 0x04000000 }, -}; - -static const struct clk_div_table main_hlk_div[] = { - { .val = 1, .div = 2, }, - { .val = 3, .div = 4, }, - { /* sentinel */ } -}; - -static const struct clk_div_table a9_as1_aclk_divider[] = { - { .val = 0, .div = 1, }, - { .val = 1, .div = 2, }, - { .val = 3, .div = 4, }, - { /* sentinel */ } -}; - -static const struct clk_div_table sec_wclk_divider[] = { - { .val = 0, .div = 1, }, - { .val = 1, .div = 2, }, - { .val = 3, .div = 4, }, - { .val = 5, .div = 6, }, - { .val = 7, .div = 8, }, - { /* sentinel */ } -}; - -static const char * const matrix_aclk_sel[] = { - "pll_mm0_198M", - "osc", - "clk_148M5", - "pll_lsp_104M", -}; - -static const char * const a9_wclk_sel[] = { - "pll_a9", - "osc", - "clk_500", - "clk_250", -}; - -static const char * const a9_as1_aclk_sel[] = { - "clk_250", - "osc", - "pll_mm0_396M", - "pll_mac_333M", -}; - -static const char * const a9_trace_clkin_sel[] = { - "clk_74M25", - "pll_mm1_108M", - "clk_125", - "clk_148M5", -}; - -static const char * const decppu_aclk_sel[] = { - "clk_250", - "pll_mm0_198M", - "pll_lsp_104M", - "pll_audio_294M912", -}; - -static const char * const vou_main_wclk_sel[] = { - "clk_148M5", - "clk_74M25", - "clk_27", - "pll_mm1_54M", -}; - -static const char * const vou_scaler_wclk_sel[] = { - "clk_250", - "pll_mac_333M", - "pll_audio_294M912", - "pll_mm0_198M", -}; - -static const char * const r2d_wclk_sel[] = { - "pll_audio_294M912", - "pll_mac_333M", - "pll_a9_350M", - "pll_mm0_396M", -}; - -static const char * const ddr_wclk_sel[] = { - "pll_mac_333M", - "pll_ddr_266M", - "pll_audio_294M912", - "pll_mm0_198M", -}; - -static const char * const nand_wclk_sel[] = { - "pll_lsp_104M", - "osc", -}; - -static const char * const lsp_26_wclk_sel[] = { - "pll_lsp_26M", - "osc", -}; - -static const char * const vl0_sel[] = { - "vou_main_channel_div", - "vou_aux_channel_div", -}; - -static const char * const hdmi_sel[] = { - "vou_main_channel_wclk", - "vou_aux_channel_wclk", -}; - -static const char * const sdmmc0_wclk_sel[] = { - "lsp1_104M_wclk", - "lsp1_26M_wclk", -}; - -static const char * const sdmmc1_wclk_sel[] = { - "lsp0_104M_wclk", - "lsp0_26M_wclk", -}; - -static const char * const uart_wclk_sel[] = { - "lsp1_104M_wclk", - "lsp1_26M_wclk", -}; - -static const char * const spdif0_wclk_sel[] = { - "lsp0_104M_wclk", - "lsp0_26M_wclk", -}; - -static const char * const spdif1_wclk_sel[] = { - "lsp1_104M_wclk", - "lsp1_26M_wclk", -}; - -static const char * const i2s_wclk_sel[] = { - "lsp0_104M_wclk", - "lsp0_26M_wclk", -}; - -static inline struct clk *zx_divtbl(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width, - const struct clk_div_table *table) -{ - return clk_register_divider_table(NULL, name, parent, 0, reg, shift, - width, 0, table, ®_lock); -} - -static inline struct clk *zx_div(const char *name, const char *parent, - void __iomem *reg, u8 shift, u8 width) -{ - return clk_register_divider(NULL, name, parent, 0, - reg, shift, width, 0, ®_lock); -} - -static inline struct clk *zx_mux(const char *name, const char * const *parents, - int num_parents, void __iomem *reg, u8 shift, u8 width) -{ - return clk_register_mux(NULL, name, parents, num_parents, - 0, reg, shift, width, 0, ®_lock); -} - -static inline struct clk *zx_gate(const char *name, const char *parent, - void __iomem *reg, u8 shift) -{ - return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED, - reg, shift, CLK_SET_RATE_PARENT, ®_lock); -} - -static void __init zx296702_top_clocks_init(struct device_node *np) -{ - struct clk **clk = topclk; - int i; - - topcrm_base = of_iomap(np, 0); - WARN_ON(!topcrm_base); - - clk[ZX296702_OSC] = - clk_register_fixed_rate(NULL, "osc", NULL, 0, 30000000); - clk[ZX296702_PLL_A9] = - clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base - + 0x01c, pll_a9_config, - ARRAY_SIZE(pll_a9_config), ®_lock); - - /* TODO: pll_a9_350M look like changeble follow a9 pll */ - clk[ZX296702_PLL_A9_350M] = - clk_register_fixed_rate(NULL, "pll_a9_350M", "osc", 0, - 350000000); - clk[ZX296702_PLL_MAC_1000M] = - clk_register_fixed_rate(NULL, "pll_mac_1000M", "osc", 0, - 1000000000); - clk[ZX296702_PLL_MAC_333M] = - clk_register_fixed_rate(NULL, "pll_mac_333M", "osc", 0, - 333000000); - clk[ZX296702_PLL_MM0_1188M] = - clk_register_fixed_rate(NULL, "pll_mm0_1188M", "osc", 0, - 1188000000); - clk[ZX296702_PLL_MM0_396M] = - clk_register_fixed_rate(NULL, "pll_mm0_396M", "osc", 0, - 396000000); - clk[ZX296702_PLL_MM0_198M] = - clk_register_fixed_rate(NULL, "pll_mm0_198M", "osc", 0, - 198000000); - clk[ZX296702_PLL_MM1_108M] = - clk_register_fixed_rate(NULL, "pll_mm1_108M", "osc", 0, - 108000000); - clk[ZX296702_PLL_MM1_72M] = - clk_register_fixed_rate(NULL, "pll_mm1_72M", "osc", 0, - 72000000); - clk[ZX296702_PLL_MM1_54M] = - clk_register_fixed_rate(NULL, "pll_mm1_54M", "osc", 0, - 54000000); - clk[ZX296702_PLL_LSP_104M] = - clk_register_fixed_rate(NULL, "pll_lsp_104M", "osc", 0, - 104000000); - clk[ZX296702_PLL_LSP_26M] = - clk_register_fixed_rate(NULL, "pll_lsp_26M", "osc", 0, - 26000000); - clk[ZX296702_PLL_DDR_266M] = - clk_register_fixed_rate(NULL, "pll_ddr_266M", "osc", 0, - 266000000); - clk[ZX296702_PLL_AUDIO_294M912] = - clk_register_fixed_rate(NULL, "pll_audio_294M912", "osc", 0, - 294912000); - - /* bus clock */ - clk[ZX296702_MATRIX_ACLK] = - zx_mux("matrix_aclk", matrix_aclk_sel, - ARRAY_SIZE(matrix_aclk_sel), CLK_MUX, 2, 2); - clk[ZX296702_MAIN_HCLK] = - zx_divtbl("main_hclk", "matrix_aclk", CLK_DIV, 0, 2, - main_hlk_div); - clk[ZX296702_MAIN_PCLK] = - zx_divtbl("main_pclk", "matrix_aclk", CLK_DIV, 2, 2, - main_hlk_div); - - /* cpu clock */ - clk[ZX296702_CLK_500] = - clk_register_fixed_factor(NULL, "clk_500", "pll_mac_1000M", 0, - 1, 2); - clk[ZX296702_CLK_250] = - clk_register_fixed_factor(NULL, "clk_250", "pll_mac_1000M", 0, - 1, 4); - clk[ZX296702_CLK_125] = - clk_register_fixed_factor(NULL, "clk_125", "clk_250", 0, 1, 2); - clk[ZX296702_CLK_148M5] = - clk_register_fixed_factor(NULL, "clk_148M5", "pll_mm0_1188M", 0, - 1, 8); - clk[ZX296702_CLK_74M25] = - clk_register_fixed_factor(NULL, "clk_74M25", "pll_mm0_1188M", 0, - 1, 16); - clk[ZX296702_A9_WCLK] = - zx_mux("a9_wclk", a9_wclk_sel, ARRAY_SIZE(a9_wclk_sel), CLK_MUX, - 0, 2); - clk[ZX296702_A9_AS1_ACLK_MUX] = - zx_mux("a9_as1_aclk_mux", a9_as1_aclk_sel, - ARRAY_SIZE(a9_as1_aclk_sel), CLK_MUX, 4, 2); - clk[ZX296702_A9_TRACE_CLKIN_MUX] = - zx_mux("a9_trace_clkin_mux", a9_trace_clkin_sel, - ARRAY_SIZE(a9_trace_clkin_sel), CLK_MUX1, 0, 2); - clk[ZX296702_A9_AS1_ACLK_DIV] = - zx_divtbl("a9_as1_aclk_div", "a9_as1_aclk_mux", CLK_DIV, 4, 2, - a9_as1_aclk_divider); - - /* multi-media clock */ - clk[ZX296702_CLK_2] = - clk_register_fixed_factor(NULL, "clk_2", "pll_mm1_72M", 0, - 1, 36); - clk[ZX296702_CLK_27] = - clk_register_fixed_factor(NULL, "clk_27", "pll_mm1_54M", 0, - 1, 2); - clk[ZX296702_DECPPU_ACLK_MUX] = - zx_mux("decppu_aclk_mux", decppu_aclk_sel, - ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 6, 2); - clk[ZX296702_PPU_ACLK_MUX] = - zx_mux("ppu_aclk_mux", decppu_aclk_sel, - ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 8, 2); - clk[ZX296702_MALI400_ACLK_MUX] = - zx_mux("mali400_aclk_mux", decppu_aclk_sel, - ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 12, 2); - clk[ZX296702_VOU_ACLK_MUX] = - zx_mux("vou_aclk_mux", decppu_aclk_sel, - ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 10, 2); - clk[ZX296702_VOU_MAIN_WCLK_MUX] = - zx_mux("vou_main_wclk_mux", vou_main_wclk_sel, - ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 14, 2); - clk[ZX296702_VOU_AUX_WCLK_MUX] = - zx_mux("vou_aux_wclk_mux", vou_main_wclk_sel, - ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 16, 2); - clk[ZX296702_VOU_SCALER_WCLK_MUX] = - zx_mux("vou_scaler_wclk_mux", vou_scaler_wclk_sel, - ARRAY_SIZE(vou_scaler_wclk_sel), CLK_MUX, - 18, 2); - clk[ZX296702_R2D_ACLK_MUX] = - zx_mux("r2d_aclk_mux", decppu_aclk_sel, - ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 20, 2); - clk[ZX296702_R2D_WCLK_MUX] = - zx_mux("r2d_wclk_mux", r2d_wclk_sel, - ARRAY_SIZE(r2d_wclk_sel), CLK_MUX, 22, 2); - - /* other clock */ - clk[ZX296702_CLK_50] = - clk_register_fixed_factor(NULL, "clk_50", "pll_mac_1000M", - 0, 1, 20); - clk[ZX296702_CLK_25] = - clk_register_fixed_factor(NULL, "clk_25", "pll_mac_1000M", - 0, 1, 40); - clk[ZX296702_CLK_12] = - clk_register_fixed_factor(NULL, "clk_12", "pll_mm1_72M", - 0, 1, 6); - clk[ZX296702_CLK_16M384] = - clk_register_fixed_factor(NULL, "clk_16M384", - "pll_audio_294M912", 0, 1, 18); - clk[ZX296702_CLK_32K768] = - clk_register_fixed_factor(NULL, "clk_32K768", "clk_16M384", - 0, 1, 500); - clk[ZX296702_SEC_WCLK_DIV] = - zx_divtbl("sec_wclk_div", "pll_lsp_104M", CLK_DIV, 6, 3, - sec_wclk_divider); - clk[ZX296702_DDR_WCLK_MUX] = - zx_mux("ddr_wclk_mux", ddr_wclk_sel, - ARRAY_SIZE(ddr_wclk_sel), CLK_MUX, 24, 2); - clk[ZX296702_NAND_WCLK_MUX] = - zx_mux("nand_wclk_mux", nand_wclk_sel, - ARRAY_SIZE(nand_wclk_sel), CLK_MUX, 24, 2); - clk[ZX296702_LSP_26_WCLK_MUX] = - zx_mux("lsp_26_wclk_mux", lsp_26_wclk_sel, - ARRAY_SIZE(lsp_26_wclk_sel), CLK_MUX, 27, 1); - - /* gates */ - clk[ZX296702_A9_AS0_ACLK] = - zx_gate("a9_as0_aclk", "matrix_aclk", CLK_EN0, 0); - clk[ZX296702_A9_AS1_ACLK] = - zx_gate("a9_as1_aclk", "a9_as1_aclk_div", CLK_EN0, 1); - clk[ZX296702_A9_TRACE_CLKIN] = - zx_gate("a9_trace_clkin", "a9_trace_clkin_mux", CLK_EN0, 2); - clk[ZX296702_DECPPU_AXI_M_ACLK] = - zx_gate("decppu_axi_m_aclk", "decppu_aclk_mux", CLK_EN0, 3); - clk[ZX296702_DECPPU_AHB_S_HCLK] = - zx_gate("decppu_ahb_s_hclk", "main_hclk", CLK_EN0, 4); - clk[ZX296702_PPU_AXI_M_ACLK] = - zx_gate("ppu_axi_m_aclk", "ppu_aclk_mux", CLK_EN0, 5); - clk[ZX296702_PPU_AHB_S_HCLK] = - zx_gate("ppu_ahb_s_hclk", "main_hclk", CLK_EN0, 6); - clk[ZX296702_VOU_AXI_M_ACLK] = - zx_gate("vou_axi_m_aclk", "vou_aclk_mux", CLK_EN0, 7); - clk[ZX296702_VOU_APB_PCLK] = - zx_gate("vou_apb_pclk", "main_pclk", CLK_EN0, 8); - clk[ZX296702_VOU_MAIN_CHANNEL_WCLK] = - zx_gate("vou_main_channel_wclk", "vou_main_wclk_mux", - CLK_EN0, 9); - clk[ZX296702_VOU_AUX_CHANNEL_WCLK] = - zx_gate("vou_aux_channel_wclk", "vou_aux_wclk_mux", - CLK_EN0, 10); - clk[ZX296702_VOU_HDMI_OSCLK_CEC] = - zx_gate("vou_hdmi_osclk_cec", "clk_2", CLK_EN0, 11); - clk[ZX296702_VOU_SCALER_WCLK] = - zx_gate("vou_scaler_wclk", "vou_scaler_wclk_mux", CLK_EN0, 12); - clk[ZX296702_MALI400_AXI_M_ACLK] = - zx_gate("mali400_axi_m_aclk", "mali400_aclk_mux", CLK_EN0, 13); - clk[ZX296702_MALI400_APB_PCLK] = - zx_gate("mali400_apb_pclk", "main_pclk", CLK_EN0, 14); - clk[ZX296702_R2D_WCLK] = - zx_gate("r2d_wclk", "r2d_wclk_mux", CLK_EN0, 15); - clk[ZX296702_R2D_AXI_M_ACLK] = - zx_gate("r2d_axi_m_aclk", "r2d_aclk_mux", CLK_EN0, 16); - clk[ZX296702_R2D_AHB_HCLK] = - zx_gate("r2d_ahb_hclk", "main_hclk", CLK_EN0, 17); - clk[ZX296702_DDR3_AXI_S0_ACLK] = - zx_gate("ddr3_axi_s0_aclk", "matrix_aclk", CLK_EN0, 18); - clk[ZX296702_DDR3_APB_PCLK] = - zx_gate("ddr3_apb_pclk", "main_pclk", CLK_EN0, 19); - clk[ZX296702_DDR3_WCLK] = - zx_gate("ddr3_wclk", "ddr_wclk_mux", CLK_EN0, 20); - clk[ZX296702_USB20_0_AHB_HCLK] = - zx_gate("usb20_0_ahb_hclk", "main_hclk", CLK_EN0, 21); - clk[ZX296702_USB20_0_EXTREFCLK] = - zx_gate("usb20_0_extrefclk", "clk_12", CLK_EN0, 22); - clk[ZX296702_USB20_1_AHB_HCLK] = - zx_gate("usb20_1_ahb_hclk", "main_hclk", CLK_EN0, 23); - clk[ZX296702_USB20_1_EXTREFCLK] = - zx_gate("usb20_1_extrefclk", "clk_12", CLK_EN0, 24); - clk[ZX296702_USB20_2_AHB_HCLK] = - zx_gate("usb20_2_ahb_hclk", "main_hclk", CLK_EN0, 25); - clk[ZX296702_USB20_2_EXTREFCLK] = - zx_gate("usb20_2_extrefclk", "clk_12", CLK_EN0, 26); - clk[ZX296702_GMAC_AXI_M_ACLK] = - zx_gate("gmac_axi_m_aclk", "matrix_aclk", CLK_EN0, 27); - clk[ZX296702_GMAC_APB_PCLK] = - zx_gate("gmac_apb_pclk", "main_pclk", CLK_EN0, 28); - clk[ZX296702_GMAC_125_CLKIN] = - zx_gate("gmac_125_clkin", "clk_125", CLK_EN0, 29); - clk[ZX296702_GMAC_RMII_CLKIN] = - zx_gate("gmac_rmii_clkin", "clk_50", CLK_EN0, 30); - clk[ZX296702_GMAC_25M_CLK] = - zx_gate("gmac_25M_clk", "clk_25", CLK_EN0, 31); - clk[ZX296702_NANDFLASH_AHB_HCLK] = - zx_gate("nandflash_ahb_hclk", "main_hclk", CLK_EN1, 0); - clk[ZX296702_NANDFLASH_WCLK] = - zx_gate("nandflash_wclk", "nand_wclk_mux", CLK_EN1, 1); - clk[ZX296702_LSP0_APB_PCLK] = - zx_gate("lsp0_apb_pclk", "main_pclk", CLK_EN1, 2); - clk[ZX296702_LSP0_AHB_HCLK] = - zx_gate("lsp0_ahb_hclk", "main_hclk", CLK_EN1, 3); - clk[ZX296702_LSP0_26M_WCLK] = - zx_gate("lsp0_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 4); - clk[ZX296702_LSP0_104M_WCLK] = - zx_gate("lsp0_104M_wclk", "pll_lsp_104M", CLK_EN1, 5); - clk[ZX296702_LSP0_16M384_WCLK] = - zx_gate("lsp0_16M384_wclk", "clk_16M384", CLK_EN1, 6); - clk[ZX296702_LSP1_APB_PCLK] = - zx_gate("lsp1_apb_pclk", "main_pclk", CLK_EN1, 7); - /* FIXME: wclk enable bit is bit8. We hack it as reserved 31 for - * UART does not work after parent clk is disabled/enabled */ - clk[ZX296702_LSP1_26M_WCLK] = - zx_gate("lsp1_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 31); - clk[ZX296702_LSP1_104M_WCLK] = - zx_gate("lsp1_104M_wclk", "pll_lsp_104M", CLK_EN1, 9); - clk[ZX296702_LSP1_32K_CLK] = - zx_gate("lsp1_32K_clk", "clk_32K768", CLK_EN1, 10); - clk[ZX296702_AON_HCLK] = - zx_gate("aon_hclk", "main_hclk", CLK_EN1, 11); - clk[ZX296702_SYS_CTRL_PCLK] = - zx_gate("sys_ctrl_pclk", "main_pclk", CLK_EN1, 12); - clk[ZX296702_DMA_PCLK] = - zx_gate("dma_pclk", "main_pclk", CLK_EN1, 13); - clk[ZX296702_DMA_ACLK] = - zx_gate("dma_aclk", "matrix_aclk", CLK_EN1, 14); - clk[ZX296702_SEC_HCLK] = - zx_gate("sec_hclk", "main_hclk", CLK_EN1, 15); - clk[ZX296702_AES_WCLK] = - zx_gate("aes_wclk", "sec_wclk_div", CLK_EN1, 16); - clk[ZX296702_DES_WCLK] = - zx_gate("des_wclk", "sec_wclk_div", CLK_EN1, 17); - clk[ZX296702_IRAM_ACLK] = - zx_gate("iram_aclk", "matrix_aclk", CLK_EN1, 18); - clk[ZX296702_IROM_ACLK] = - zx_gate("irom_aclk", "matrix_aclk", CLK_EN1, 19); - clk[ZX296702_BOOT_CTRL_HCLK] = - zx_gate("boot_ctrl_hclk", "main_hclk", CLK_EN1, 20); - clk[ZX296702_EFUSE_CLK_30] = - zx_gate("efuse_clk_30", "osc", CLK_EN1, 21); - - /* TODO: add VOU Local clocks */ - clk[ZX296702_VOU_MAIN_CHANNEL_DIV] = - zx_div("vou_main_channel_div", "vou_main_channel_wclk", - VOU_LOCAL_DIV2_SET, 1, 1); - clk[ZX296702_VOU_AUX_CHANNEL_DIV] = - zx_div("vou_aux_channel_div", "vou_aux_channel_wclk", - VOU_LOCAL_DIV2_SET, 0, 1); - clk[ZX296702_VOU_TV_ENC_HD_DIV] = - zx_div("vou_tv_enc_hd_div", "vou_tv_enc_hd_mux", - VOU_LOCAL_DIV2_SET, 3, 1); - clk[ZX296702_VOU_TV_ENC_SD_DIV] = - zx_div("vou_tv_enc_sd_div", "vou_tv_enc_sd_mux", - VOU_LOCAL_DIV2_SET, 2, 1); - clk[ZX296702_VL0_MUX] = - zx_mux("vl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 8, 1); - clk[ZX296702_VL1_MUX] = - zx_mux("vl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 9, 1); - clk[ZX296702_VL2_MUX] = - zx_mux("vl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 10, 1); - clk[ZX296702_GL0_MUX] = - zx_mux("gl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 5, 1); - clk[ZX296702_GL1_MUX] = - zx_mux("gl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 6, 1); - clk[ZX296702_GL2_MUX] = - zx_mux("gl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 7, 1); - clk[ZX296702_WB_MUX] = - zx_mux("wb_mux", vl0_sel, ARRAY_SIZE(vl0_sel), - VOU_LOCAL_CLKSEL, 11, 1); - clk[ZX296702_HDMI_MUX] = - zx_mux("hdmi_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), - VOU_LOCAL_CLKSEL, 4, 1); - clk[ZX296702_VOU_TV_ENC_HD_MUX] = - zx_mux("vou_tv_enc_hd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), - VOU_LOCAL_CLKSEL, 3, 1); - clk[ZX296702_VOU_TV_ENC_SD_MUX] = - zx_mux("vou_tv_enc_sd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), - VOU_LOCAL_CLKSEL, 2, 1); - clk[ZX296702_VL0_CLK] = - zx_gate("vl0_clk", "vl0_mux", VOU_LOCAL_CLKEN, 8); - clk[ZX296702_VL1_CLK] = - zx_gate("vl1_clk", "vl1_mux", VOU_LOCAL_CLKEN, 9); - clk[ZX296702_VL2_CLK] = - zx_gate("vl2_clk", "vl2_mux", VOU_LOCAL_CLKEN, 10); - clk[ZX296702_GL0_CLK] = - zx_gate("gl0_clk", "gl0_mux", VOU_LOCAL_CLKEN, 5); - clk[ZX296702_GL1_CLK] = - zx_gate("gl1_clk", "gl1_mux", VOU_LOCAL_CLKEN, 6); - clk[ZX296702_GL2_CLK] = - zx_gate("gl2_clk", "gl2_mux", VOU_LOCAL_CLKEN, 7); - clk[ZX296702_WB_CLK] = - zx_gate("wb_clk", "wb_mux", VOU_LOCAL_CLKEN, 11); - clk[ZX296702_CL_CLK] = - zx_gate("cl_clk", "vou_main_channel_div", VOU_LOCAL_CLKEN, 12); - clk[ZX296702_MAIN_MIX_CLK] = - zx_gate("main_mix_clk", "vou_main_channel_div", - VOU_LOCAL_CLKEN, 4); - clk[ZX296702_AUX_MIX_CLK] = - zx_gate("aux_mix_clk", "vou_aux_channel_div", - VOU_LOCAL_CLKEN, 3); - clk[ZX296702_HDMI_CLK] = - zx_gate("hdmi_clk", "hdmi_mux", VOU_LOCAL_CLKEN, 2); - clk[ZX296702_VOU_TV_ENC_HD_DAC_CLK] = - zx_gate("vou_tv_enc_hd_dac_clk", "vou_tv_enc_hd_div", - VOU_LOCAL_CLKEN, 1); - clk[ZX296702_VOU_TV_ENC_SD_DAC_CLK] = - zx_gate("vou_tv_enc_sd_dac_clk", "vou_tv_enc_sd_div", - VOU_LOCAL_CLKEN, 0); - - /* CA9 PERIPHCLK = a9_wclk / 2 */ - clk[ZX296702_A9_PERIPHCLK] = - clk_register_fixed_factor(NULL, "a9_periphclk", "a9_wclk", - 0, 1, 2); - - for (i = 0; i < ARRAY_SIZE(topclk); i++) { - if (IS_ERR(clk[i])) { - pr_err("zx296702 clk %d: register failed with %ld\n", - i, PTR_ERR(clk[i])); - return; - } - } - - topclk_data.clks = topclk; - topclk_data.clk_num = ARRAY_SIZE(topclk); - of_clk_add_provider(np, of_clk_src_onecell_get, &topclk_data); -} -CLK_OF_DECLARE(zx296702_top_clk, "zte,zx296702-topcrm-clk", - zx296702_top_clocks_init); - -static void __init zx296702_lsp0_clocks_init(struct device_node *np) -{ - struct clk **clk = lsp0clk; - int i; - - lsp0crpm_base = of_iomap(np, 0); - WARN_ON(!lsp0crpm_base); - - /* SDMMC1 */ - clk[ZX296702_SDMMC1_WCLK_MUX] = - zx_mux("sdmmc1_wclk_mux", sdmmc1_wclk_sel, - ARRAY_SIZE(sdmmc1_wclk_sel), CLK_SDMMC1, 4, 1); - clk[ZX296702_SDMMC1_WCLK_DIV] = - zx_div("sdmmc1_wclk_div", "sdmmc1_wclk_mux", CLK_SDMMC1, 12, 4); - clk[ZX296702_SDMMC1_WCLK] = - zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1); - clk[ZX296702_SDMMC1_PCLK] = - zx_gate("sdmmc1_pclk", "lsp0_apb_pclk", CLK_SDMMC1, 0); - - clk[ZX296702_GPIO_CLK] = - zx_gate("gpio_clk", "lsp0_apb_pclk", CLK_GPIO, 0); - - /* SPDIF */ - clk[ZX296702_SPDIF0_WCLK_MUX] = - zx_mux("spdif0_wclk_mux", spdif0_wclk_sel, - ARRAY_SIZE(spdif0_wclk_sel), CLK_SPDIF0, 4, 1); - clk[ZX296702_SPDIF0_WCLK] = - zx_gate("spdif0_wclk", "spdif0_wclk_mux", CLK_SPDIF0, 1); - clk[ZX296702_SPDIF0_PCLK] = - zx_gate("spdif0_pclk", "lsp0_apb_pclk", CLK_SPDIF0, 0); - - clk[ZX296702_SPDIF0_DIV] = - clk_register_zx_audio("spdif0_div", "spdif0_wclk", 0, - SPDIF0_DIV); - - /* I2S */ - clk[ZX296702_I2S0_WCLK_MUX] = - zx_mux("i2s0_wclk_mux", i2s_wclk_sel, - ARRAY_SIZE(i2s_wclk_sel), CLK_I2S0, 4, 1); - clk[ZX296702_I2S0_WCLK] = - zx_gate("i2s0_wclk", "i2s0_wclk_mux", CLK_I2S0, 1); - clk[ZX296702_I2S0_PCLK] = - zx_gate("i2s0_pclk", "lsp0_apb_pclk", CLK_I2S0, 0); - - clk[ZX296702_I2S0_DIV] = - clk_register_zx_audio("i2s0_div", "i2s0_wclk", 0, I2S0_DIV); - - clk[ZX296702_I2S1_WCLK_MUX] = - zx_mux("i2s1_wclk_mux", i2s_wclk_sel, - ARRAY_SIZE(i2s_wclk_sel), CLK_I2S1, 4, 1); - clk[ZX296702_I2S1_WCLK] = - zx_gate("i2s1_wclk", "i2s1_wclk_mux", CLK_I2S1, 1); - clk[ZX296702_I2S1_PCLK] = - zx_gate("i2s1_pclk", "lsp0_apb_pclk", CLK_I2S1, 0); - - clk[ZX296702_I2S1_DIV] = - clk_register_zx_audio("i2s1_div", "i2s1_wclk", 0, I2S1_DIV); - - clk[ZX296702_I2S2_WCLK_MUX] = - zx_mux("i2s2_wclk_mux", i2s_wclk_sel, - ARRAY_SIZE(i2s_wclk_sel), CLK_I2S2, 4, 1); - clk[ZX296702_I2S2_WCLK] = - zx_gate("i2s2_wclk", "i2s2_wclk_mux", CLK_I2S2, 1); - clk[ZX296702_I2S2_PCLK] = - zx_gate("i2s2_pclk", "lsp0_apb_pclk", CLK_I2S2, 0); - - clk[ZX296702_I2S2_DIV] = - clk_register_zx_audio("i2s2_div", "i2s2_wclk", 0, I2S2_DIV); - - for (i = 0; i < ARRAY_SIZE(lsp0clk); i++) { - if (IS_ERR(clk[i])) { - pr_err("zx296702 clk %d: register failed with %ld\n", - i, PTR_ERR(clk[i])); - return; - } - } - - lsp0clk_data.clks = lsp0clk; - lsp0clk_data.clk_num = ARRAY_SIZE(lsp0clk); - of_clk_add_provider(np, of_clk_src_onecell_get, &lsp0clk_data); -} -CLK_OF_DECLARE(zx296702_lsp0_clk, "zte,zx296702-lsp0crpm-clk", - zx296702_lsp0_clocks_init); - -static void __init zx296702_lsp1_clocks_init(struct device_node *np) -{ - struct clk **clk = lsp1clk; - int i; - - lsp1crpm_base = of_iomap(np, 0); - WARN_ON(!lsp1crpm_base); - - /* UART0 */ - clk[ZX296702_UART0_WCLK_MUX] = - zx_mux("uart0_wclk_mux", uart_wclk_sel, - ARRAY_SIZE(uart_wclk_sel), CLK_UART0, 4, 1); - /* FIXME: uart wclk enable bit is bit1 in. We hack it as reserved 31 for - * UART does not work after parent clk is disabled/enabled */ - clk[ZX296702_UART0_WCLK] = - zx_gate("uart0_wclk", "uart0_wclk_mux", CLK_UART0, 31); - clk[ZX296702_UART0_PCLK] = - zx_gate("uart0_pclk", "lsp1_apb_pclk", CLK_UART0, 0); - - /* UART1 */ - clk[ZX296702_UART1_WCLK_MUX] = - zx_mux("uart1_wclk_mux", uart_wclk_sel, - ARRAY_SIZE(uart_wclk_sel), CLK_UART1, 4, 1); - clk[ZX296702_UART1_WCLK] = - zx_gate("uart1_wclk", "uart1_wclk_mux", CLK_UART1, 1); - clk[ZX296702_UART1_PCLK] = - zx_gate("uart1_pclk", "lsp1_apb_pclk", CLK_UART1, 0); - - /* SDMMC0 */ - clk[ZX296702_SDMMC0_WCLK_MUX] = - zx_mux("sdmmc0_wclk_mux", sdmmc0_wclk_sel, - ARRAY_SIZE(sdmmc0_wclk_sel), CLK_SDMMC0, 4, 1); - clk[ZX296702_SDMMC0_WCLK_DIV] = - zx_div("sdmmc0_wclk_div", "sdmmc0_wclk_mux", CLK_SDMMC0, 12, 4); - clk[ZX296702_SDMMC0_WCLK] = - zx_gate("sdmmc0_wclk", "sdmmc0_wclk_div", CLK_SDMMC0, 1); - clk[ZX296702_SDMMC0_PCLK] = - zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0); - - clk[ZX296702_SPDIF1_WCLK_MUX] = - zx_mux("spdif1_wclk_mux", spdif1_wclk_sel, - ARRAY_SIZE(spdif1_wclk_sel), CLK_SPDIF1, 4, 1); - clk[ZX296702_SPDIF1_WCLK] = - zx_gate("spdif1_wclk", "spdif1_wclk_mux", CLK_SPDIF1, 1); - clk[ZX296702_SPDIF1_PCLK] = - zx_gate("spdif1_pclk", "lsp1_apb_pclk", CLK_SPDIF1, 0); - - clk[ZX296702_SPDIF1_DIV] = - clk_register_zx_audio("spdif1_div", "spdif1_wclk", 0, - SPDIF1_DIV); - - for (i = 0; i < ARRAY_SIZE(lsp1clk); i++) { - if (IS_ERR(clk[i])) { - pr_err("zx296702 clk %d: register failed with %ld\n", - i, PTR_ERR(clk[i])); - return; - } - } - - lsp1clk_data.clks = lsp1clk; - lsp1clk_data.clk_num = ARRAY_SIZE(lsp1clk); - of_clk_add_provider(np, of_clk_src_onecell_get, &lsp1clk_data); -} -CLK_OF_DECLARE(zx296702_lsp1_clk, "zte,zx296702-lsp1crpm-clk", - zx296702_lsp1_clocks_init); diff --git a/drivers/clk/zte/clk-zx296718.c b/drivers/clk/zte/clk-zx296718.c deleted file mode 100644 index dd7045bc48c1..000000000000 --- a/drivers/clk/zte/clk-zx296718.c +++ /dev/null @@ -1,1074 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2015 - 2016 ZTE Corporation. - * Copyright (C) 2016 Linaro Ltd. - */ -#include <linux/clk-provider.h> -#include <linux/device.h> -#include <linux/kernel.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/platform_device.h> - -#include <dt-bindings/clock/zx296718-clock.h> -#include "clk.h" - -/* TOP CRM */ -#define TOP_CLK_MUX0 0x04 -#define TOP_CLK_MUX1 0x08 -#define TOP_CLK_MUX2 0x0c -#define TOP_CLK_MUX3 0x10 -#define TOP_CLK_MUX4 0x14 -#define TOP_CLK_MUX5 0x18 -#define TOP_CLK_MUX6 0x1c -#define TOP_CLK_MUX7 0x20 -#define TOP_CLK_MUX9 0x28 - - -#define TOP_CLK_GATE0 0x34 -#define TOP_CLK_GATE1 0x38 -#define TOP_CLK_GATE2 0x3c -#define TOP_CLK_GATE3 0x40 -#define TOP_CLK_GATE4 0x44 -#define TOP_CLK_GATE5 0x48 -#define TOP_CLK_GATE6 0x4c - -#define TOP_CLK_DIV0 0x58 - -#define PLL_CPU_REG 0x80 -#define PLL_VGA_REG 0xb0 -#define PLL_DDR_REG 0xa0 - -/* LSP0 CRM */ -#define LSP0_TIMER3_CLK 0x4 -#define LSP0_TIMER4_CLK 0x8 -#define LSP0_TIMER5_CLK 0xc -#define LSP0_UART3_CLK 0x10 -#define LSP0_UART1_CLK 0x14 -#define LSP0_UART2_CLK 0x18 -#define LSP0_SPIFC0_CLK 0x1c -#define LSP0_I2C4_CLK 0x20 -#define LSP0_I2C5_CLK 0x24 -#define LSP0_SSP0_CLK 0x28 -#define LSP0_SSP1_CLK 0x2c -#define LSP0_USIM0_CLK 0x30 -#define LSP0_GPIO_CLK 0x34 -#define LSP0_I2C3_CLK 0x38 - -/* LSP1 CRM */ -#define LSP1_UART4_CLK 0x08 -#define LSP1_UART5_CLK 0x0c -#define LSP1_PWM_CLK 0x10 -#define LSP1_I2C2_CLK 0x14 -#define LSP1_SSP2_CLK 0x1c -#define LSP1_SSP3_CLK 0x20 -#define LSP1_SSP4_CLK 0x24 -#define LSP1_USIM1_CLK 0x28 - -/* audio lsp */ -#define AUDIO_I2S0_DIV_CFG1 0x10 -#define AUDIO_I2S0_DIV_CFG2 0x14 -#define AUDIO_I2S0_CLK 0x18 -#define AUDIO_I2S1_DIV_CFG1 0x20 -#define AUDIO_I2S1_DIV_CFG2 0x24 -#define AUDIO_I2S1_CLK 0x28 -#define AUDIO_I2S2_DIV_CFG1 0x30 -#define AUDIO_I2S2_DIV_CFG2 0x34 -#define AUDIO_I2S2_CLK 0x38 -#define AUDIO_I2S3_DIV_CFG1 0x40 -#define AUDIO_I2S3_DIV_CFG2 0x44 -#define AUDIO_I2S3_CLK 0x48 -#define AUDIO_I2C0_CLK 0x50 -#define AUDIO_SPDIF0_DIV_CFG1 0x60 -#define AUDIO_SPDIF0_DIV_CFG2 0x64 -#define AUDIO_SPDIF0_CLK 0x68 -#define AUDIO_SPDIF1_DIV_CFG1 0x70 -#define AUDIO_SPDIF1_DIV_CFG2 0x74 -#define AUDIO_SPDIF1_CLK 0x78 -#define AUDIO_TIMER_CLK 0x80 -#define AUDIO_TDM_CLK 0x90 -#define AUDIO_TS_CLK 0xa0 - -static DEFINE_SPINLOCK(clk_lock); - -static const struct zx_pll_config pll_cpu_table[] = { - PLL_RATE(1312000000, 0x00103621, 0x04aaaaaa), - PLL_RATE(1407000000, 0x00103a21, 0x04aaaaaa), - PLL_RATE(1503000000, 0x00103e21, 0x04aaaaaa), - PLL_RATE(1600000000, 0x00104221, 0x04aaaaaa), -}; - -static const struct zx_pll_config pll_vga_table[] = { - PLL_RATE(36000000, 0x00102464, 0x04000000), /* 800x600@56 */ - PLL_RATE(40000000, 0x00102864, 0x04000000), /* 800x600@60 */ - PLL_RATE(49500000, 0x00103164, 0x04800000), /* 800x600@75 */ - PLL_RATE(50000000, 0x00103264, 0x04000000), /* 800x600@72 */ - PLL_RATE(56250000, 0x00103864, 0x04400000), /* 800x600@85 */ - PLL_RATE(65000000, 0x00104164, 0x04000000), /* 1024x768@60 */ - PLL_RATE(74375000, 0x00104a64, 0x04600000), /* 1280x720@60 */ - PLL_RATE(75000000, 0x00104b64, 0x04800000), /* 1024x768@70 */ - PLL_RATE(78750000, 0x00104e64, 0x04c00000), /* 1024x768@75 */ - PLL_RATE(85500000, 0x00105564, 0x04800000), /* 1360x768@60 */ - PLL_RATE(106500000, 0x00106a64, 0x04800000), /* 1440x900@60 */ - PLL_RATE(108000000, 0x00106c64, 0x04000000), /* 1280x1024@60 */ - PLL_RATE(110000000, 0x00106e64, 0x04000000), /* 1024x768@85 */ - PLL_RATE(135000000, 0x00105a44, 0x04000000), /* 1280x1024@75 */ - PLL_RATE(136750000, 0x00104462, 0x04600000), /* 1440x900@75 */ - PLL_RATE(148500000, 0x00104a62, 0x04400000), /* 1920x1080@60 */ - PLL_RATE(157000000, 0x00104e62, 0x04800000), /* 1440x900@85 */ - PLL_RATE(157500000, 0x00104e62, 0x04c00000), /* 1280x1024@85 */ - PLL_RATE(162000000, 0x00105162, 0x04000000), /* 1600x1200@60 */ - PLL_RATE(193250000, 0x00106062, 0x04a00000), /* 1920x1200@60 */ -}; - -PNAME(osc) = { - "osc24m", - "osc32k", -}; - -PNAME(dbg_wclk_p) = { - "clk334m", - "clk466m", - "clk396m", - "clk250m", -}; - -PNAME(a72_coreclk_p) = { - "osc24m", - "pll_mm0_1188m", - "pll_mm1_1296m", - "clk1000m", - "clk648m", - "clk1600m", - "pll_audio_1800m", - "pll_vga_1800m", -}; - -PNAME(cpu_periclk_p) = { - "osc24m", - "clk500m", - "clk594m", - "clk466m", - "clk294m", - "clk334m", - "clk250m", - "clk125m", -}; - -PNAME(a53_coreclk_p) = { - "osc24m", - "clk1000m", - "pll_mm0_1188m", - "clk648m", - "clk500m", - "clk800m", - "clk1600m", - "pll_audio_1800m", -}; - -PNAME(sec_wclk_p) = { - "osc24m", - "clk396m", - "clk334m", - "clk297m", - "clk250m", - "clk198m", - "clk148m5", - "clk99m", -}; - -PNAME(sd_nand_wclk_p) = { - "osc24m", - "clk49m5", - "clk99m", - "clk198m", - "clk167m", - "clk148m5", - "clk125m", - "clk216m", -}; - -PNAME(emmc_wclk_p) = { - "osc24m", - "clk198m", - "clk99m", - "clk396m", - "clk334m", - "clk297m", - "clk250m", - "clk148m5", -}; - -PNAME(clk32_p) = { - "osc32k", - "clk32k768", -}; - -PNAME(usb_ref24m_p) = { - "osc32k", - "clk32k768", -}; - -PNAME(sys_noc_alck_p) = { - "osc24m", - "clk250m", - "clk198m", - "clk148m5", - "clk108m", - "clk54m", - "clk216m", - "clk240m", -}; - -PNAME(vde_aclk_p) = { - "clk334m", - "clk594m", - "clk500m", - "clk432m", - "clk480m", - "clk297m", - "clk_vga", /*600MHz*/ - "clk294m", -}; - -PNAME(vce_aclk_p) = { - "clk334m", - "clk594m", - "clk500m", - "clk432m", - "clk396m", - "clk297m", - "clk_vga", /*600MHz*/ - "clk294m", -}; - -PNAME(hde_aclk_p) = { - "clk334m", - "clk594m", - "clk500m", - "clk432m", - "clk396m", - "clk297m", - "clk_vga", /*600MHz*/ - "clk294m", -}; - -PNAME(gpu_aclk_p) = { - "clk334m", - "clk648m", - "clk594m", - "clk500m", - "clk396m", - "clk297m", - "clk_vga", /*600MHz*/ - "clk294m", -}; - -PNAME(sappu_aclk_p) = { - "clk396m", - "clk500m", - "clk250m", - "clk148m5", -}; - -PNAME(sappu_wclk_p) = { - "clk198m", - "clk396m", - "clk334m", - "clk297m", - "clk250m", - "clk148m5", - "clk125m", - "clk99m", -}; - -PNAME(vou_aclk_p) = { - "clk334m", - "clk594m", - "clk500m", - "clk432m", - "clk396m", - "clk297m", - "clk_vga", /*600MHz*/ - "clk294m", -}; - -PNAME(vou_main_wclk_p) = { - "clk108m", - "clk594m", - "clk297m", - "clk148m5", - "clk74m25", - "clk54m", - "clk27m", - "clk_vga", -}; - -PNAME(vou_aux_wclk_p) = { - "clk108m", - "clk148m5", - "clk74m25", - "clk54m", - "clk27m", - "clk_vga", - "clk54m_mm0", - "clk" -}; - -PNAME(vou_ppu_wclk_p) = { - "clk334m", - "clk432m", - "clk396m", - "clk297m", - "clk250m", - "clk125m", - "clk198m", - "clk99m", -}; - -PNAME(vga_i2c_wclk_p) = { - "osc24m", - "clk99m", -}; - -PNAME(viu_m0_aclk_p) = { - "clk334m", - "clk432m", - "clk396m", - "clk297m", - "clk250m", - "clk125m", - "clk198m", - "osc24m", -}; - -PNAME(viu_m1_aclk_p) = { - "clk198m", - "clk250m", - "clk297m", - "clk125m", - "clk396m", - "clk334m", - "clk148m5", - "osc24m", -}; - -PNAME(viu_clk_p) = { - "clk198m", - "clk334m", - "clk297m", - "clk250m", - "clk396m", - "clk125m", - "clk99m", - "clk148m5", -}; - -PNAME(viu_jpeg_clk_p) = { - "clk334m", - "clk480m", - "clk432m", - "clk396m", - "clk297m", - "clk250m", - "clk125m", - "clk198m", -}; - -PNAME(ts_sys_clk_p) = { - "clk192m", - "clk167m", - "clk125m", - "clk99m", -}; - -PNAME(wdt_ares_p) = { - "osc24m", - "clk32k" -}; - -static struct clk_zx_pll zx296718_pll_clk[] = { - ZX296718_PLL("pll_cpu", "osc24m", PLL_CPU_REG, pll_cpu_table), - ZX296718_PLL("pll_vga", "osc24m", PLL_VGA_REG, pll_vga_table), -}; - -static struct zx_clk_fixed_factor top_ffactor_clk[] = { - FFACTOR(0, "clk4m", "osc24m", 1, 6, 0), - FFACTOR(0, "clk2m", "osc24m", 1, 12, 0), - /* pll cpu */ - FFACTOR(0, "clk1600m", "pll_cpu", 1, 1, CLK_SET_RATE_PARENT), - FFACTOR(0, "clk800m", "pll_cpu", 1, 2, CLK_SET_RATE_PARENT), - /* pll mac */ - FFACTOR(0, "clk25m", "pll_mac", 1, 40, 0), - FFACTOR(0, "clk125m", "pll_mac", 1, 8, 0), - FFACTOR(0, "clk250m", "pll_mac", 1, 4, 0), - FFACTOR(0, "clk50m", "pll_mac", 1, 20, 0), - FFACTOR(0, "clk500m", "pll_mac", 1, 2, 0), - FFACTOR(0, "clk1000m", "pll_mac", 1, 1, 0), - FFACTOR(0, "clk334m", "pll_mac", 1, 3, 0), - FFACTOR(0, "clk167m", "pll_mac", 1, 6, 0), - /* pll mm */ - FFACTOR(0, "clk54m_mm0", "pll_mm0", 1, 22, 0), - FFACTOR(0, "clk74m25", "pll_mm0", 1, 16, 0), - FFACTOR(0, "clk148m5", "pll_mm0", 1, 8, 0), - FFACTOR(0, "clk297m", "pll_mm0", 1, 4, 0), - FFACTOR(0, "clk594m", "pll_mm0", 1, 2, 0), - FFACTOR(0, "pll_mm0_1188m", "pll_mm0", 1, 1, 0), - FFACTOR(0, "clk396m", "pll_mm0", 1, 3, 0), - FFACTOR(0, "clk198m", "pll_mm0", 1, 6, 0), - FFACTOR(0, "clk99m", "pll_mm0", 1, 12, 0), - FFACTOR(0, "clk49m5", "pll_mm0", 1, 24, 0), - /* pll mm */ - FFACTOR(0, "clk324m", "pll_mm1", 1, 4, 0), - FFACTOR(0, "clk648m", "pll_mm1", 1, 2, 0), - FFACTOR(0, "pll_mm1_1296m", "pll_mm1", 1, 1, 0), - FFACTOR(0, "clk216m", "pll_mm1", 1, 6, 0), - FFACTOR(0, "clk432m", "pll_mm1", 1, 3, 0), - FFACTOR(0, "clk108m", "pll_mm1", 1, 12, 0), - FFACTOR(0, "clk72m", "pll_mm1", 1, 18, 0), - FFACTOR(0, "clk27m", "pll_mm1", 1, 48, 0), - FFACTOR(0, "clk54m", "pll_mm1", 1, 24, 0), - /* vga */ - FFACTOR(0, "pll_vga_1800m", "pll_vga", 1, 1, 0), - FFACTOR(0, "clk_vga", "pll_vga", 1, 1, CLK_SET_RATE_PARENT), - /* pll ddr */ - FFACTOR(0, "clk466m", "pll_ddr", 1, 2, 0), - - /* pll audio */ - FFACTOR(0, "pll_audio_1800m", "pll_audio", 1, 1, 0), - FFACTOR(0, "clk32k768", "pll_audio", 1, 27000, 0), - FFACTOR(0, "clk16m384", "pll_audio", 1, 54, 0), - FFACTOR(0, "clk294m", "pll_audio", 1, 3, 0), - - /* pll hsic*/ - FFACTOR(0, "clk240m", "pll_hsic", 1, 4, 0), - FFACTOR(0, "clk480m", "pll_hsic", 1, 2, 0), - FFACTOR(0, "clk192m", "pll_hsic", 1, 5, 0), - FFACTOR(0, "clk_pll_24m", "pll_hsic", 1, 40, 0), - FFACTOR(0, "emmc_mux_div2", "emmc_mux", 1, 2, CLK_SET_RATE_PARENT), -}; - -static const struct clk_div_table noc_div_table[] = { - { .val = 1, .div = 2, }, - { .val = 3, .div = 4, }, -}; -static struct zx_clk_div top_div_clk[] = { - DIV_T(0, "sys_noc_hclk", "sys_noc_aclk", TOP_CLK_DIV0, 0, 2, 0, noc_div_table), - DIV_T(0, "sys_noc_pclk", "sys_noc_aclk", TOP_CLK_DIV0, 4, 2, 0, noc_div_table), -}; - -static struct zx_clk_mux top_mux_clk[] = { - MUX(0, "dbg_mux", dbg_wclk_p, TOP_CLK_MUX0, 12, 2), - MUX(0, "a72_mux", a72_coreclk_p, TOP_CLK_MUX0, 8, 3), - MUX(0, "cpu_peri_mux", cpu_periclk_p, TOP_CLK_MUX0, 4, 3), - MUX_F(0, "a53_mux", a53_coreclk_p, TOP_CLK_MUX0, 0, 3, CLK_SET_RATE_PARENT, 0), - MUX(0, "sys_noc_aclk", sys_noc_alck_p, TOP_CLK_MUX1, 0, 3), - MUX(0, "sec_mux", sec_wclk_p, TOP_CLK_MUX2, 16, 3), - MUX(0, "sd1_mux", sd_nand_wclk_p, TOP_CLK_MUX2, 12, 3), - MUX(0, "sd0_mux", sd_nand_wclk_p, TOP_CLK_MUX2, 8, 3), - MUX(0, "emmc_mux", emmc_wclk_p, TOP_CLK_MUX2, 4, 3), - MUX(0, "nand_mux", sd_nand_wclk_p, TOP_CLK_MUX2, 0, 3), - MUX(0, "usb_ref24m_mux", usb_ref24m_p, TOP_CLK_MUX9, 16, 1), - MUX(0, "clk32k", clk32_p, TOP_CLK_MUX9, 12, 1), - MUX_F(0, "wdt_mux", wdt_ares_p, TOP_CLK_MUX9, 8, 1, CLK_SET_RATE_PARENT, 0), - MUX(0, "timer_mux", osc, TOP_CLK_MUX9, 4, 1), - MUX(0, "vde_mux", vde_aclk_p, TOP_CLK_MUX4, 0, 3), - MUX(0, "vce_mux", vce_aclk_p, TOP_CLK_MUX4, 4, 3), - MUX(0, "hde_mux", hde_aclk_p, TOP_CLK_MUX4, 8, 3), - MUX(0, "gpu_mux", gpu_aclk_p, TOP_CLK_MUX5, 0, 3), - MUX(0, "sappu_a_mux", sappu_aclk_p, TOP_CLK_MUX5, 4, 2), - MUX(0, "sappu_w_mux", sappu_wclk_p, TOP_CLK_MUX5, 8, 3), - MUX(0, "vou_a_mux", vou_aclk_p, TOP_CLK_MUX7, 0, 3), - MUX_F(0, "vou_main_w_mux", vou_main_wclk_p, TOP_CLK_MUX7, 4, 3, CLK_SET_RATE_PARENT, 0), - MUX_F(0, "vou_aux_w_mux", vou_aux_wclk_p, TOP_CLK_MUX7, 8, 3, CLK_SET_RATE_PARENT, 0), - MUX(0, "vou_ppu_w_mux", vou_ppu_wclk_p, TOP_CLK_MUX7, 12, 3), - MUX(0, "vga_i2c_mux", vga_i2c_wclk_p, TOP_CLK_MUX7, 16, 1), - MUX(0, "viu_m0_a_mux", viu_m0_aclk_p, TOP_CLK_MUX6, 0, 3), - MUX(0, "viu_m1_a_mux", viu_m1_aclk_p, TOP_CLK_MUX6, 4, 3), - MUX(0, "viu_w_mux", viu_clk_p, TOP_CLK_MUX6, 8, 3), - MUX(0, "viu_jpeg_w_mux", viu_jpeg_clk_p, TOP_CLK_MUX6, 12, 3), - MUX(0, "ts_sys_mux", ts_sys_clk_p, TOP_CLK_MUX6, 16, 2), -}; - -static struct zx_clk_gate top_gate_clk[] = { - GATE(CPU_DBG_GATE, "dbg_wclk", "dbg_mux", TOP_CLK_GATE0, 4, CLK_SET_RATE_PARENT, 0), - GATE(A72_GATE, "a72_coreclk", "a72_mux", TOP_CLK_GATE0, 3, CLK_SET_RATE_PARENT, 0), - GATE(CPU_PERI_GATE, "cpu_peri", "cpu_peri_mux", TOP_CLK_GATE0, 1, CLK_SET_RATE_PARENT, 0), - GATE(A53_GATE, "a53_coreclk", "a53_mux", TOP_CLK_GATE0, 0, CLK_SET_RATE_PARENT, 0), - GATE(SD1_WCLK, "sd1_wclk", "sd1_mux", TOP_CLK_GATE1, 13, CLK_SET_RATE_PARENT, 0), - GATE(SD0_WCLK, "sd0_wclk", "sd0_mux", TOP_CLK_GATE1, 9, CLK_SET_RATE_PARENT, 0), - GATE(EMMC_WCLK, "emmc_wclk", "emmc_mux_div2", TOP_CLK_GATE0, 5, CLK_SET_RATE_PARENT, 0), - GATE(EMMC_NAND_AXI, "emmc_nand_aclk", "sys_noc_aclk", TOP_CLK_GATE1, 4, CLK_SET_RATE_PARENT, 0), - GATE(NAND_WCLK, "nand_wclk", "nand_mux", TOP_CLK_GATE0, 1, CLK_SET_RATE_PARENT, 0), - GATE(EMMC_NAND_AHB, "emmc_nand_hclk", "sys_noc_hclk", TOP_CLK_GATE1, 0, CLK_SET_RATE_PARENT, 0), - GATE(0, "lsp1_pclk", "sys_noc_pclk", TOP_CLK_GATE2, 31, 0, 0), - GATE(LSP1_148M5, "lsp1_148m5", "clk148m5", TOP_CLK_GATE2, 30, 0, 0), - GATE(LSP1_99M, "lsp1_99m", "clk99m", TOP_CLK_GATE2, 29, 0, 0), - GATE(LSP1_24M, "lsp1_24m", "osc24m", TOP_CLK_GATE2, 28, 0, 0), - GATE(LSP0_74M25, "lsp0_74m25", "clk74m25", TOP_CLK_GATE2, 25, 0, 0), - GATE(0, "lsp0_pclk", "sys_noc_pclk", TOP_CLK_GATE2, 24, 0, 0), - GATE(LSP0_32K, "lsp0_32k", "osc32k", TOP_CLK_GATE2, 23, 0, 0), - GATE(LSP0_148M5, "lsp0_148m5", "clk148m5", TOP_CLK_GATE2, 22, 0, 0), - GATE(LSP0_99M, "lsp0_99m", "clk99m", TOP_CLK_GATE2, 21, 0, 0), - GATE(LSP0_24M, "lsp0_24m", "osc24m", TOP_CLK_GATE2, 20, 0, 0), - GATE(AUDIO_99M, "audio_99m", "clk99m", TOP_CLK_GATE5, 27, 0, 0), - GATE(AUDIO_24M, "audio_24m", "osc24m", TOP_CLK_GATE5, 28, 0, 0), - GATE(AUDIO_16M384, "audio_16m384", "clk16m384", TOP_CLK_GATE5, 29, 0, 0), - GATE(AUDIO_32K, "audio_32k", "clk32k", TOP_CLK_GATE5, 30, 0, 0), - GATE(WDT_WCLK, "wdt_wclk", "wdt_mux", TOP_CLK_GATE6, 9, CLK_SET_RATE_PARENT, 0), - GATE(TIMER_WCLK, "timer_wclk", "timer_mux", TOP_CLK_GATE6, 5, CLK_SET_RATE_PARENT, 0), - GATE(VDE_ACLK, "vde_aclk", "vde_mux", TOP_CLK_GATE3, 0, CLK_SET_RATE_PARENT, 0), - GATE(VCE_ACLK, "vce_aclk", "vce_mux", TOP_CLK_GATE3, 4, CLK_SET_RATE_PARENT, 0), - GATE(HDE_ACLK, "hde_aclk", "hde_mux", TOP_CLK_GATE3, 8, CLK_SET_RATE_PARENT, 0), - GATE(GPU_ACLK, "gpu_aclk", "gpu_mux", TOP_CLK_GATE3, 16, CLK_SET_RATE_PARENT, 0), - GATE(SAPPU_ACLK, "sappu_aclk", "sappu_a_mux", TOP_CLK_GATE3, 20, CLK_SET_RATE_PARENT, 0), - GATE(SAPPU_WCLK, "sappu_wclk", "sappu_w_mux", TOP_CLK_GATE3, 22, CLK_SET_RATE_PARENT, 0), - GATE(VOU_ACLK, "vou_aclk", "vou_a_mux", TOP_CLK_GATE4, 16, CLK_SET_RATE_PARENT, 0), - GATE(VOU_MAIN_WCLK, "vou_main_wclk", "vou_main_w_mux", TOP_CLK_GATE4, 18, CLK_SET_RATE_PARENT, 0), - GATE(VOU_AUX_WCLK, "vou_aux_wclk", "vou_aux_w_mux", TOP_CLK_GATE4, 19, CLK_SET_RATE_PARENT, 0), - GATE(VOU_PPU_WCLK, "vou_ppu_wclk", "vou_ppu_w_mux", TOP_CLK_GATE4, 20, CLK_SET_RATE_PARENT, 0), - GATE(MIPI_CFG_CLK, "mipi_cfg_clk", "osc24m", TOP_CLK_GATE4, 21, 0, 0), - GATE(VGA_I2C_WCLK, "vga_i2c_wclk", "vga_i2c_mux", TOP_CLK_GATE4, 23, CLK_SET_RATE_PARENT, 0), - GATE(MIPI_REF_CLK, "mipi_ref_clk", "clk27m", TOP_CLK_GATE4, 24, 0, 0), - GATE(HDMI_OSC_CEC, "hdmi_osc_cec", "clk2m", TOP_CLK_GATE4, 22, 0, 0), - GATE(HDMI_OSC_CLK, "hdmi_osc_clk", "clk240m", TOP_CLK_GATE4, 25, 0, 0), - GATE(HDMI_XCLK, "hdmi_xclk", "osc24m", TOP_CLK_GATE4, 26, 0, 0), - GATE(VIU_M0_ACLK, "viu_m0_aclk", "viu_m0_a_mux", TOP_CLK_GATE4, 0, CLK_SET_RATE_PARENT, 0), - GATE(VIU_M1_ACLK, "viu_m1_aclk", "viu_m1_a_mux", TOP_CLK_GATE4, 1, CLK_SET_RATE_PARENT, 0), - GATE(VIU_WCLK, "viu_wclk", "viu_w_mux", TOP_CLK_GATE4, 2, CLK_SET_RATE_PARENT, 0), - GATE(VIU_JPEG_WCLK, "viu_jpeg_wclk", "viu_jpeg_w_mux", TOP_CLK_GATE4, 3, CLK_SET_RATE_PARENT, 0), - GATE(VIU_CFG_CLK, "viu_cfg_clk", "osc24m", TOP_CLK_GATE4, 6, 0, 0), - GATE(TS_SYS_WCLK, "ts_sys_wclk", "ts_sys_mux", TOP_CLK_GATE5, 2, CLK_SET_RATE_PARENT, 0), - GATE(TS_SYS_108M, "ts_sys_108m", "clk108m", TOP_CLK_GATE5, 3, 0, 0), - GATE(USB20_HCLK, "usb20_hclk", "sys_noc_hclk", TOP_CLK_GATE2, 12, 0, 0), - GATE(USB20_PHY_CLK, "usb20_phy_clk", "usb_ref24m_mux", TOP_CLK_GATE2, 13, 0, 0), - GATE(USB21_HCLK, "usb21_hclk", "sys_noc_hclk", TOP_CLK_GATE2, 14, 0, 0), - GATE(USB21_PHY_CLK, "usb21_phy_clk", "usb_ref24m_mux", TOP_CLK_GATE2, 15, 0, 0), - GATE(GMAC_RMIICLK, "gmac_rmii_clk", "clk50m", TOP_CLK_GATE2, 3, 0, 0), - GATE(GMAC_PCLK, "gmac_pclk", "clk198m", TOP_CLK_GATE2, 1, 0, 0), - GATE(GMAC_ACLK, "gmac_aclk", "clk49m5", TOP_CLK_GATE2, 0, 0, 0), - GATE(GMAC_RFCLK, "gmac_refclk", "clk25m", TOP_CLK_GATE2, 4, 0, 0), - GATE(SD1_AHB, "sd1_hclk", "sys_noc_hclk", TOP_CLK_GATE1, 12, 0, 0), - GATE(SD0_AHB, "sd0_hclk", "sys_noc_hclk", TOP_CLK_GATE1, 8, 0, 0), - GATE(TEMPSENSOR_GATE, "tempsensor_gate", "clk4m", TOP_CLK_GATE5, 31, 0, 0), -}; - -static struct clk_hw_onecell_data top_hw_onecell_data = { - .num = TOP_NR_CLKS, - .hws = { - [TOP_NR_CLKS - 1] = NULL, - }, -}; - -static int __init top_clocks_init(struct device_node *np) -{ - void __iomem *reg_base; - int i, ret; - const char *name; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - pr_err("%s: Unable to map clk base\n", __func__); - return -ENXIO; - } - - for (i = 0; i < ARRAY_SIZE(zx296718_pll_clk); i++) { - zx296718_pll_clk[i].reg_base += (uintptr_t)reg_base; - name = zx296718_pll_clk[i].hw.init->name; - ret = clk_hw_register(NULL, &zx296718_pll_clk[i].hw); - if (ret) - pr_warn("top clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(top_ffactor_clk); i++) { - if (top_ffactor_clk[i].id) - top_hw_onecell_data.hws[top_ffactor_clk[i].id] = - &top_ffactor_clk[i].factor.hw; - - name = top_ffactor_clk[i].factor.hw.init->name; - ret = clk_hw_register(NULL, &top_ffactor_clk[i].factor.hw); - if (ret) - pr_warn("top clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(top_mux_clk); i++) { - if (top_mux_clk[i].id) - top_hw_onecell_data.hws[top_mux_clk[i].id] = - &top_mux_clk[i].mux.hw; - - top_mux_clk[i].mux.reg += (uintptr_t)reg_base; - name = top_mux_clk[i].mux.hw.init->name; - ret = clk_hw_register(NULL, &top_mux_clk[i].mux.hw); - if (ret) - pr_warn("top clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(top_gate_clk); i++) { - if (top_gate_clk[i].id) - top_hw_onecell_data.hws[top_gate_clk[i].id] = - &top_gate_clk[i].gate.hw; - - top_gate_clk[i].gate.reg += (uintptr_t)reg_base; - name = top_gate_clk[i].gate.hw.init->name; - ret = clk_hw_register(NULL, &top_gate_clk[i].gate.hw); - if (ret) - pr_warn("top clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(top_div_clk); i++) { - if (top_div_clk[i].id) - top_hw_onecell_data.hws[top_div_clk[i].id] = - &top_div_clk[i].div.hw; - - top_div_clk[i].div.reg += (uintptr_t)reg_base; - name = top_div_clk[i].div.hw.init->name; - ret = clk_hw_register(NULL, &top_div_clk[i].div.hw); - if (ret) - pr_warn("top clk %s init error!\n", name); - } - - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, - &top_hw_onecell_data); - if (ret) { - pr_err("failed to register top clk provider: %d\n", ret); - return ret; - } - - return 0; -} - -static const struct clk_div_table common_even_div_table[] = { - { .val = 0, .div = 1, }, - { .val = 1, .div = 2, }, - { .val = 3, .div = 4, }, - { .val = 5, .div = 6, }, - { .val = 7, .div = 8, }, - { .val = 9, .div = 10, }, - { .val = 11, .div = 12, }, - { .val = 13, .div = 14, }, - { .val = 15, .div = 16, }, -}; - -static const struct clk_div_table common_div_table[] = { - { .val = 0, .div = 1, }, - { .val = 1, .div = 2, }, - { .val = 2, .div = 3, }, - { .val = 3, .div = 4, }, - { .val = 4, .div = 5, }, - { .val = 5, .div = 6, }, - { .val = 6, .div = 7, }, - { .val = 7, .div = 8, }, - { .val = 8, .div = 9, }, - { .val = 9, .div = 10, }, - { .val = 10, .div = 11, }, - { .val = 11, .div = 12, }, - { .val = 12, .div = 13, }, - { .val = 13, .div = 14, }, - { .val = 14, .div = 15, }, - { .val = 15, .div = 16, }, -}; - -PNAME(lsp0_wclk_common_p) = { - "lsp0_24m", - "lsp0_99m", -}; - -PNAME(lsp0_wclk_timer3_p) = { - "timer3_div", - "lsp0_32k" -}; - -PNAME(lsp0_wclk_timer4_p) = { - "timer4_div", - "lsp0_32k" -}; - -PNAME(lsp0_wclk_timer5_p) = { - "timer5_div", - "lsp0_32k" -}; - -PNAME(lsp0_wclk_spifc0_p) = { - "lsp0_148m5", - "lsp0_24m", - "lsp0_99m", - "lsp0_74m25" -}; - -PNAME(lsp0_wclk_ssp_p) = { - "lsp0_148m5", - "lsp0_99m", - "lsp0_24m", -}; - -static struct zx_clk_mux lsp0_mux_clk[] = { - MUX(0, "timer3_wclk_mux", lsp0_wclk_timer3_p, LSP0_TIMER3_CLK, 4, 1), - MUX(0, "timer4_wclk_mux", lsp0_wclk_timer4_p, LSP0_TIMER4_CLK, 4, 1), - MUX(0, "timer5_wclk_mux", lsp0_wclk_timer5_p, LSP0_TIMER5_CLK, 4, 1), - MUX(0, "uart3_wclk_mux", lsp0_wclk_common_p, LSP0_UART3_CLK, 4, 1), - MUX(0, "uart1_wclk_mux", lsp0_wclk_common_p, LSP0_UART1_CLK, 4, 1), - MUX(0, "uart2_wclk_mux", lsp0_wclk_common_p, LSP0_UART2_CLK, 4, 1), - MUX(0, "spifc0_wclk_mux", lsp0_wclk_spifc0_p, LSP0_SPIFC0_CLK, 4, 2), - MUX(0, "i2c4_wclk_mux", lsp0_wclk_common_p, LSP0_I2C4_CLK, 4, 1), - MUX(0, "i2c5_wclk_mux", lsp0_wclk_common_p, LSP0_I2C5_CLK, 4, 1), - MUX(0, "ssp0_wclk_mux", lsp0_wclk_ssp_p, LSP0_SSP0_CLK, 4, 1), - MUX(0, "ssp1_wclk_mux", lsp0_wclk_ssp_p, LSP0_SSP1_CLK, 4, 1), - MUX(0, "i2c3_wclk_mux", lsp0_wclk_common_p, LSP0_I2C3_CLK, 4, 1), -}; - -static struct zx_clk_gate lsp0_gate_clk[] = { - GATE(LSP0_TIMER3_WCLK, "timer3_wclk", "timer3_wclk_mux", LSP0_TIMER3_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_TIMER4_WCLK, "timer4_wclk", "timer4_wclk_mux", LSP0_TIMER4_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_TIMER5_WCLK, "timer5_wclk", "timer5_wclk_mux", LSP0_TIMER5_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_UART3_WCLK, "uart3_wclk", "uart3_wclk_mux", LSP0_UART3_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_UART1_WCLK, "uart1_wclk", "uart1_wclk_mux", LSP0_UART1_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_UART2_WCLK, "uart2_wclk", "uart2_wclk_mux", LSP0_UART2_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_SPIFC0_WCLK, "spifc0_wclk", "spifc0_wclk_mux", LSP0_SPIFC0_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_I2C4_WCLK, "i2c4_wclk", "i2c4_wclk_mux", LSP0_I2C4_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_I2C5_WCLK, "i2c5_wclk", "i2c5_wclk_mux", LSP0_I2C5_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_SSP0_WCLK, "ssp0_wclk", "ssp0_div", LSP0_SSP0_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_SSP1_WCLK, "ssp1_wclk", "ssp1_div", LSP0_SSP1_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP0_I2C3_WCLK, "i2c3_wclk", "i2c3_wclk_mux", LSP0_I2C3_CLK, 1, CLK_SET_RATE_PARENT, 0), -}; - -static struct zx_clk_div lsp0_div_clk[] = { - DIV_T(0, "timer3_div", "lsp0_24m", LSP0_TIMER3_CLK, 12, 4, 0, common_even_div_table), - DIV_T(0, "timer4_div", "lsp0_24m", LSP0_TIMER4_CLK, 12, 4, 0, common_even_div_table), - DIV_T(0, "timer5_div", "lsp0_24m", LSP0_TIMER5_CLK, 12, 4, 0, common_even_div_table), - DIV_T(0, "ssp0_div", "ssp0_wclk_mux", LSP0_SSP0_CLK, 12, 4, 0, common_even_div_table), - DIV_T(0, "ssp1_div", "ssp1_wclk_mux", LSP0_SSP1_CLK, 12, 4, 0, common_even_div_table), -}; - -static struct clk_hw_onecell_data lsp0_hw_onecell_data = { - .num = LSP0_NR_CLKS, - .hws = { - [LSP0_NR_CLKS - 1] = NULL, - }, -}; - -static int __init lsp0_clocks_init(struct device_node *np) -{ - void __iomem *reg_base; - int i, ret; - const char *name; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - pr_err("%s: Unable to map clk base\n", __func__); - return -ENXIO; - } - - for (i = 0; i < ARRAY_SIZE(lsp0_mux_clk); i++) { - if (lsp0_mux_clk[i].id) - lsp0_hw_onecell_data.hws[lsp0_mux_clk[i].id] = - &lsp0_mux_clk[i].mux.hw; - - lsp0_mux_clk[i].mux.reg += (uintptr_t)reg_base; - name = lsp0_mux_clk[i].mux.hw.init->name; - ret = clk_hw_register(NULL, &lsp0_mux_clk[i].mux.hw); - if (ret) - pr_warn("lsp0 clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(lsp0_gate_clk); i++) { - if (lsp0_gate_clk[i].id) - lsp0_hw_onecell_data.hws[lsp0_gate_clk[i].id] = - &lsp0_gate_clk[i].gate.hw; - - lsp0_gate_clk[i].gate.reg += (uintptr_t)reg_base; - name = lsp0_gate_clk[i].gate.hw.init->name; - ret = clk_hw_register(NULL, &lsp0_gate_clk[i].gate.hw); - if (ret) - pr_warn("lsp0 clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(lsp0_div_clk); i++) { - if (lsp0_div_clk[i].id) - lsp0_hw_onecell_data.hws[lsp0_div_clk[i].id] = - &lsp0_div_clk[i].div.hw; - - lsp0_div_clk[i].div.reg += (uintptr_t)reg_base; - name = lsp0_div_clk[i].div.hw.init->name; - ret = clk_hw_register(NULL, &lsp0_div_clk[i].div.hw); - if (ret) - pr_warn("lsp0 clk %s init error!\n", name); - } - - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, - &lsp0_hw_onecell_data); - if (ret) { - pr_err("failed to register lsp0 clk provider: %d\n", ret); - return ret; - } - - return 0; -} - -PNAME(lsp1_wclk_common_p) = { - "lsp1_24m", - "lsp1_99m", -}; - -PNAME(lsp1_wclk_ssp_p) = { - "lsp1_148m5", - "lsp1_99m", - "lsp1_24m", -}; - -static struct zx_clk_mux lsp1_mux_clk[] = { - MUX(0, "uart4_wclk_mux", lsp1_wclk_common_p, LSP1_UART4_CLK, 4, 1), - MUX(0, "uart5_wclk_mux", lsp1_wclk_common_p, LSP1_UART5_CLK, 4, 1), - MUX(0, "pwm_wclk_mux", lsp1_wclk_common_p, LSP1_PWM_CLK, 4, 1), - MUX(0, "i2c2_wclk_mux", lsp1_wclk_common_p, LSP1_I2C2_CLK, 4, 1), - MUX(0, "ssp2_wclk_mux", lsp1_wclk_ssp_p, LSP1_SSP2_CLK, 4, 2), - MUX(0, "ssp3_wclk_mux", lsp1_wclk_ssp_p, LSP1_SSP3_CLK, 4, 2), - MUX(0, "ssp4_wclk_mux", lsp1_wclk_ssp_p, LSP1_SSP4_CLK, 4, 2), - MUX(0, "usim1_wclk_mux", lsp1_wclk_common_p, LSP1_USIM1_CLK, 4, 1), -}; - -static struct zx_clk_div lsp1_div_clk[] = { - DIV_T(0, "pwm_div", "pwm_wclk_mux", LSP1_PWM_CLK, 12, 4, CLK_SET_RATE_PARENT, common_div_table), - DIV_T(0, "ssp2_div", "ssp2_wclk_mux", LSP1_SSP2_CLK, 12, 4, CLK_SET_RATE_PARENT, common_even_div_table), - DIV_T(0, "ssp3_div", "ssp3_wclk_mux", LSP1_SSP3_CLK, 12, 4, CLK_SET_RATE_PARENT, common_even_div_table), - DIV_T(0, "ssp4_div", "ssp4_wclk_mux", LSP1_SSP4_CLK, 12, 4, CLK_SET_RATE_PARENT, common_even_div_table), -}; - -static struct zx_clk_gate lsp1_gate_clk[] = { - GATE(LSP1_UART4_WCLK, "lsp1_uart4_wclk", "uart4_wclk_mux", LSP1_UART4_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_UART5_WCLK, "lsp1_uart5_wclk", "uart5_wclk_mux", LSP1_UART5_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_PWM_WCLK, "lsp1_pwm_wclk", "pwm_div", LSP1_PWM_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_PWM_PCLK, "lsp1_pwm_pclk", "lsp1_pclk", LSP1_PWM_CLK, 0, 0, 0), - GATE(LSP1_I2C2_WCLK, "lsp1_i2c2_wclk", "i2c2_wclk_mux", LSP1_I2C2_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_SSP2_WCLK, "lsp1_ssp2_wclk", "ssp2_div", LSP1_SSP2_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_SSP3_WCLK, "lsp1_ssp3_wclk", "ssp3_div", LSP1_SSP3_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_SSP4_WCLK, "lsp1_ssp4_wclk", "ssp4_div", LSP1_SSP4_CLK, 1, CLK_SET_RATE_PARENT, 0), - GATE(LSP1_USIM1_WCLK, "lsp1_usim1_wclk", "usim1_wclk_mux", LSP1_USIM1_CLK, 1, CLK_SET_RATE_PARENT, 0), -}; - -static struct clk_hw_onecell_data lsp1_hw_onecell_data = { - .num = LSP1_NR_CLKS, - .hws = { - [LSP1_NR_CLKS - 1] = NULL, - }, -}; - -static int __init lsp1_clocks_init(struct device_node *np) -{ - void __iomem *reg_base; - int i, ret; - const char *name; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - pr_err("%s: Unable to map clk base\n", __func__); - return -ENXIO; - } - - for (i = 0; i < ARRAY_SIZE(lsp1_mux_clk); i++) { - if (lsp1_mux_clk[i].id) - lsp1_hw_onecell_data.hws[lsp1_mux_clk[i].id] = - &lsp0_mux_clk[i].mux.hw; - - lsp1_mux_clk[i].mux.reg += (uintptr_t)reg_base; - name = lsp1_mux_clk[i].mux.hw.init->name; - ret = clk_hw_register(NULL, &lsp1_mux_clk[i].mux.hw); - if (ret) - pr_warn("lsp1 clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(lsp1_gate_clk); i++) { - if (lsp1_gate_clk[i].id) - lsp1_hw_onecell_data.hws[lsp1_gate_clk[i].id] = - &lsp1_gate_clk[i].gate.hw; - - lsp1_gate_clk[i].gate.reg += (uintptr_t)reg_base; - name = lsp1_gate_clk[i].gate.hw.init->name; - ret = clk_hw_register(NULL, &lsp1_gate_clk[i].gate.hw); - if (ret) - pr_warn("lsp1 clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(lsp1_div_clk); i++) { - if (lsp1_div_clk[i].id) - lsp1_hw_onecell_data.hws[lsp1_div_clk[i].id] = - &lsp1_div_clk[i].div.hw; - - lsp1_div_clk[i].div.reg += (uintptr_t)reg_base; - name = lsp1_div_clk[i].div.hw.init->name; - ret = clk_hw_register(NULL, &lsp1_div_clk[i].div.hw); - if (ret) - pr_warn("lsp1 clk %s init error!\n", name); - } - - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, - &lsp1_hw_onecell_data); - if (ret) { - pr_err("failed to register lsp1 clk provider: %d\n", ret); - return ret; - } - - return 0; -} - -PNAME(audio_wclk_common_p) = { - "audio_99m", - "audio_24m", -}; - -PNAME(audio_timer_p) = { - "audio_24m", - "audio_32k", -}; - -static struct zx_clk_mux audio_mux_clk[] = { - MUX(I2S0_WCLK_MUX, "i2s0_wclk_mux", audio_wclk_common_p, AUDIO_I2S0_CLK, 0, 1), - MUX(I2S1_WCLK_MUX, "i2s1_wclk_mux", audio_wclk_common_p, AUDIO_I2S1_CLK, 0, 1), - MUX(I2S2_WCLK_MUX, "i2s2_wclk_mux", audio_wclk_common_p, AUDIO_I2S2_CLK, 0, 1), - MUX(I2S3_WCLK_MUX, "i2s3_wclk_mux", audio_wclk_common_p, AUDIO_I2S3_CLK, 0, 1), - MUX(0, "i2c0_wclk_mux", audio_wclk_common_p, AUDIO_I2C0_CLK, 0, 1), - MUX(0, "spdif0_wclk_mux", audio_wclk_common_p, AUDIO_SPDIF0_CLK, 0, 1), - MUX(0, "spdif1_wclk_mux", audio_wclk_common_p, AUDIO_SPDIF1_CLK, 0, 1), - MUX(0, "timer_wclk_mux", audio_timer_p, AUDIO_TIMER_CLK, 0, 1), -}; - -static struct clk_zx_audio_divider audio_adiv_clk[] = { - AUDIO_DIV(0, "i2s0_wclk_div", "i2s0_wclk_mux", AUDIO_I2S0_DIV_CFG1), - AUDIO_DIV(0, "i2s1_wclk_div", "i2s1_wclk_mux", AUDIO_I2S1_DIV_CFG1), - AUDIO_DIV(0, "i2s2_wclk_div", "i2s2_wclk_mux", AUDIO_I2S2_DIV_CFG1), - AUDIO_DIV(0, "i2s3_wclk_div", "i2s3_wclk_mux", AUDIO_I2S3_DIV_CFG1), - AUDIO_DIV(0, "spdif0_wclk_div", "spdif0_wclk_mux", AUDIO_SPDIF0_DIV_CFG1), - AUDIO_DIV(0, "spdif1_wclk_div", "spdif1_wclk_mux", AUDIO_SPDIF1_DIV_CFG1), -}; - -static struct zx_clk_div audio_div_clk[] = { - DIV_T(0, "tdm_wclk_div", "audio_16m384", AUDIO_TDM_CLK, 8, 4, 0, common_div_table), -}; - -static struct zx_clk_gate audio_gate_clk[] = { - GATE(AUDIO_I2S0_WCLK, "i2s0_wclk", "i2s0_wclk_div", AUDIO_I2S0_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_I2S1_WCLK, "i2s1_wclk", "i2s1_wclk_div", AUDIO_I2S1_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_I2S2_WCLK, "i2s2_wclk", "i2s2_wclk_div", AUDIO_I2S2_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_I2S3_WCLK, "i2s3_wclk", "i2s3_wclk_div", AUDIO_I2S3_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_I2S0_PCLK, "i2s0_pclk", "clk49m5", AUDIO_I2S0_CLK, 8, 0, 0), - GATE(AUDIO_I2S1_PCLK, "i2s1_pclk", "clk49m5", AUDIO_I2S1_CLK, 8, 0, 0), - GATE(AUDIO_I2S2_PCLK, "i2s2_pclk", "clk49m5", AUDIO_I2S2_CLK, 8, 0, 0), - GATE(AUDIO_I2S3_PCLK, "i2s3_pclk", "clk49m5", AUDIO_I2S3_CLK, 8, 0, 0), - GATE(AUDIO_I2C0_WCLK, "i2c0_wclk", "i2c0_wclk_mux", AUDIO_I2C0_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_SPDIF0_WCLK, "spdif0_wclk", "spdif0_wclk_div", AUDIO_SPDIF0_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_SPDIF1_WCLK, "spdif1_wclk", "spdif1_wclk_div", AUDIO_SPDIF1_CLK, 9, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_TDM_WCLK, "tdm_wclk", "tdm_wclk_div", AUDIO_TDM_CLK, 17, CLK_SET_RATE_PARENT, 0), - GATE(AUDIO_TS_PCLK, "tempsensor_pclk", "clk49m5", AUDIO_TS_CLK, 1, 0, 0), -}; - -static struct clk_hw_onecell_data audio_hw_onecell_data = { - .num = AUDIO_NR_CLKS, - .hws = { - [AUDIO_NR_CLKS - 1] = NULL, - }, -}; - -static int __init audio_clocks_init(struct device_node *np) -{ - void __iomem *reg_base; - int i, ret; - const char *name; - - reg_base = of_iomap(np, 0); - if (!reg_base) { - pr_err("%s: Unable to map audio clk base\n", __func__); - return -ENXIO; - } - - for (i = 0; i < ARRAY_SIZE(audio_mux_clk); i++) { - if (audio_mux_clk[i].id) - audio_hw_onecell_data.hws[audio_mux_clk[i].id] = - &audio_mux_clk[i].mux.hw; - - audio_mux_clk[i].mux.reg += (uintptr_t)reg_base; - name = audio_mux_clk[i].mux.hw.init->name; - ret = clk_hw_register(NULL, &audio_mux_clk[i].mux.hw); - if (ret) - pr_warn("audio clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(audio_adiv_clk); i++) { - if (audio_adiv_clk[i].id) - audio_hw_onecell_data.hws[audio_adiv_clk[i].id] = - &audio_adiv_clk[i].hw; - - audio_adiv_clk[i].reg_base += (uintptr_t)reg_base; - name = audio_adiv_clk[i].hw.init->name; - ret = clk_hw_register(NULL, &audio_adiv_clk[i].hw); - if (ret) - pr_warn("audio clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(audio_div_clk); i++) { - if (audio_div_clk[i].id) - audio_hw_onecell_data.hws[audio_div_clk[i].id] = - &audio_div_clk[i].div.hw; - - audio_div_clk[i].div.reg += (uintptr_t)reg_base; - name = audio_div_clk[i].div.hw.init->name; - ret = clk_hw_register(NULL, &audio_div_clk[i].div.hw); - if (ret) - pr_warn("audio clk %s init error!\n", name); - } - - for (i = 0; i < ARRAY_SIZE(audio_gate_clk); i++) { - if (audio_gate_clk[i].id) - audio_hw_onecell_data.hws[audio_gate_clk[i].id] = - &audio_gate_clk[i].gate.hw; - - audio_gate_clk[i].gate.reg += (uintptr_t)reg_base; - name = audio_gate_clk[i].gate.hw.init->name; - ret = clk_hw_register(NULL, &audio_gate_clk[i].gate.hw); - if (ret) - pr_warn("audio clk %s init error!\n", name); - } - - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, - &audio_hw_onecell_data); - if (ret) { - pr_err("failed to register audio clk provider: %d\n", ret); - return ret; - } - - return 0; -} - -static const struct of_device_id zx_clkc_match_table[] = { - { .compatible = "zte,zx296718-topcrm", .data = &top_clocks_init }, - { .compatible = "zte,zx296718-lsp0crm", .data = &lsp0_clocks_init }, - { .compatible = "zte,zx296718-lsp1crm", .data = &lsp1_clocks_init }, - { .compatible = "zte,zx296718-audiocrm", .data = &audio_clocks_init }, - { } -}; - -static int zx_clkc_probe(struct platform_device *pdev) -{ - int (*init_fn)(struct device_node *np); - struct device_node *np = pdev->dev.of_node; - - init_fn = of_device_get_match_data(&pdev->dev); - if (!init_fn) { - dev_err(&pdev->dev, "Error: No device match found\n"); - return -ENODEV; - } - - return init_fn(np); -} - -static struct platform_driver zx_clk_driver = { - .probe = zx_clkc_probe, - .driver = { - .name = "zx296718-clkc", - .of_match_table = zx_clkc_match_table, - }, -}; - -static int __init zx_clk_init(void) -{ - return platform_driver_register(&zx_clk_driver); -} -core_initcall(zx_clk_init); diff --git a/drivers/clk/zte/clk.c b/drivers/clk/zte/clk.c deleted file mode 100644 index 8bda6d41ad3a..000000000000 --- a/drivers/clk/zte/clk.c +++ /dev/null @@ -1,446 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2014 Linaro Ltd. - * Copyright (C) 2014 ZTE Corporation. - */ - -#include <linux/clk-provider.h> -#include <linux/err.h> -#include <linux/gcd.h> -#include <linux/io.h> -#include <linux/iopoll.h> -#include <linux/slab.h> -#include <linux/spinlock.h> -#include <asm/div64.h> - -#include "clk.h" - -#define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw) -#define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw) - -#define CFG0_CFG1_OFFSET 4 -#define LOCK_FLAG 30 -#define POWER_DOWN 31 - -static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate) -{ - const struct zx_pll_config *config = zx_pll->lookup_table; - int i; - - for (i = 0; i < zx_pll->count; i++) { - if (config[i].rate > rate) - return i > 0 ? i - 1 : 0; - - if (config[i].rate == rate) - return i; - } - - return i - 1; -} - -static int hw_to_idx(struct clk_zx_pll *zx_pll) -{ - const struct zx_pll_config *config = zx_pll->lookup_table; - u32 hw_cfg0, hw_cfg1; - int i; - - hw_cfg0 = readl_relaxed(zx_pll->reg_base); - hw_cfg1 = readl_relaxed(zx_pll->reg_base + CFG0_CFG1_OFFSET); - - /* For matching the value in lookup table */ - hw_cfg0 &= ~BIT(zx_pll->lock_bit); - - /* Check availability of pd_bit */ - if (zx_pll->pd_bit < 32) - hw_cfg0 |= BIT(zx_pll->pd_bit); - - for (i = 0; i < zx_pll->count; i++) { - if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1) - return i; - } - - return -EINVAL; -} - -static unsigned long zx_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - int idx; - - idx = hw_to_idx(zx_pll); - if (unlikely(idx == -EINVAL)) - return 0; - - return zx_pll->lookup_table[idx].rate; -} - -static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - int idx; - - idx = rate_to_idx(zx_pll, rate); - - return zx_pll->lookup_table[idx].rate; -} - -static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - /* Assume current cpu is not running on current PLL */ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - const struct zx_pll_config *config; - int idx; - - idx = rate_to_idx(zx_pll, rate); - config = &zx_pll->lookup_table[idx]; - - writel_relaxed(config->cfg0, zx_pll->reg_base); - writel_relaxed(config->cfg1, zx_pll->reg_base + CFG0_CFG1_OFFSET); - - return 0; -} - -static int zx_pll_enable(struct clk_hw *hw) -{ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - u32 reg; - - /* If pd_bit is not available, simply return success. */ - if (zx_pll->pd_bit > 31) - return 0; - - reg = readl_relaxed(zx_pll->reg_base); - writel_relaxed(reg & ~BIT(zx_pll->pd_bit), zx_pll->reg_base); - - return readl_relaxed_poll_timeout(zx_pll->reg_base, reg, - reg & BIT(zx_pll->lock_bit), 0, 100); -} - -static void zx_pll_disable(struct clk_hw *hw) -{ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - u32 reg; - - if (zx_pll->pd_bit > 31) - return; - - reg = readl_relaxed(zx_pll->reg_base); - writel_relaxed(reg | BIT(zx_pll->pd_bit), zx_pll->reg_base); -} - -static int zx_pll_is_enabled(struct clk_hw *hw) -{ - struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw); - u32 reg; - - reg = readl_relaxed(zx_pll->reg_base); - - return !(reg & BIT(zx_pll->pd_bit)); -} - -const struct clk_ops zx_pll_ops = { - .recalc_rate = zx_pll_recalc_rate, - .round_rate = zx_pll_round_rate, - .set_rate = zx_pll_set_rate, - .enable = zx_pll_enable, - .disable = zx_pll_disable, - .is_enabled = zx_pll_is_enabled, -}; -EXPORT_SYMBOL(zx_pll_ops); - -struct clk *clk_register_zx_pll(const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg_base, - const struct zx_pll_config *lookup_table, - int count, spinlock_t *lock) -{ - struct clk_zx_pll *zx_pll; - struct clk *clk; - struct clk_init_data init; - - zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL); - if (!zx_pll) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &zx_pll_ops; - init.flags = flags; - init.parent_names = parent_name ? &parent_name : NULL; - init.num_parents = parent_name ? 1 : 0; - - zx_pll->reg_base = reg_base; - zx_pll->lookup_table = lookup_table; - zx_pll->count = count; - zx_pll->lock_bit = LOCK_FLAG; - zx_pll->pd_bit = POWER_DOWN; - zx_pll->lock = lock; - zx_pll->hw.init = &init; - - clk = clk_register(NULL, &zx_pll->hw); - if (IS_ERR(clk)) - kfree(zx_pll); - - return clk; -} - -#define BPAR 1000000 -static u32 calc_reg(u32 parent_rate, u32 rate) -{ - u32 sel, integ, fra_div, tmp; - u64 tmp64 = (u64)parent_rate * BPAR; - - do_div(tmp64, rate); - integ = (u32)tmp64 / BPAR; - integ = integ >> 1; - - tmp = (u32)tmp64 % BPAR; - sel = tmp / BPAR; - - tmp = tmp % BPAR; - fra_div = tmp * 0xff / BPAR; - tmp = (sel << 24) | (integ << 16) | (0xff << 8) | fra_div; - - /* Set I2S integer divider as 1. This bit is reserved for SPDIF - * and do no harm. - */ - tmp |= BIT(28); - return tmp; -} - -static u32 calc_rate(u32 reg, u32 parent_rate) -{ - u32 sel, integ, fra_div, tmp; - u64 tmp64 = (u64)parent_rate * BPAR; - - tmp = reg; - sel = (tmp >> 24) & BIT(0); - integ = (tmp >> 16) & 0xff; - fra_div = tmp & 0xff; - - tmp = fra_div * BPAR; - tmp = tmp / 0xff; - tmp += sel * BPAR; - tmp += 2 * integ * BPAR; - do_div(tmp64, tmp); - - return (u32)tmp64; -} - -static unsigned long zx_audio_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw); - u32 reg; - - reg = readl_relaxed(zx_audio->reg_base); - return calc_rate(reg, parent_rate); -} - -static long zx_audio_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - u32 reg; - - if (rate * 2 > *prate) - return -EINVAL; - - reg = calc_reg(*prate, rate); - return calc_rate(reg, *prate); -} - -static int zx_audio_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw); - u32 reg; - - reg = calc_reg(parent_rate, rate); - writel_relaxed(reg, zx_audio->reg_base); - - return 0; -} - -#define ZX_AUDIO_EN BIT(25) -static int zx_audio_enable(struct clk_hw *hw) -{ - struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw); - u32 reg; - - reg = readl_relaxed(zx_audio->reg_base); - writel_relaxed(reg & ~ZX_AUDIO_EN, zx_audio->reg_base); - return 0; -} - -static void zx_audio_disable(struct clk_hw *hw) -{ - struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw); - u32 reg; - - reg = readl_relaxed(zx_audio->reg_base); - writel_relaxed(reg | ZX_AUDIO_EN, zx_audio->reg_base); -} - -static const struct clk_ops zx_audio_ops = { - .recalc_rate = zx_audio_recalc_rate, - .round_rate = zx_audio_round_rate, - .set_rate = zx_audio_set_rate, - .enable = zx_audio_enable, - .disable = zx_audio_disable, -}; - -struct clk *clk_register_zx_audio(const char *name, - const char * const parent_name, - unsigned long flags, - void __iomem *reg_base) -{ - struct clk_zx_audio *zx_audio; - struct clk *clk; - struct clk_init_data init; - - zx_audio = kzalloc(sizeof(*zx_audio), GFP_KERNEL); - if (!zx_audio) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &zx_audio_ops; - init.flags = flags; - init.parent_names = parent_name ? &parent_name : NULL; - init.num_parents = parent_name ? 1 : 0; - - zx_audio->reg_base = reg_base; - zx_audio->hw.init = &init; - - clk = clk_register(NULL, &zx_audio->hw); - if (IS_ERR(clk)) - kfree(zx_audio); - - return clk; -} - -#define CLK_AUDIO_DIV_FRAC BIT(0) -#define CLK_AUDIO_DIV_INT BIT(1) -#define CLK_AUDIO_DIV_UNCOMMON BIT(1) - -#define CLK_AUDIO_DIV_FRAC_NSHIFT 16 -#define CLK_AUDIO_DIV_INT_FRAC_RE BIT(16) -#define CLK_AUDIO_DIV_INT_FRAC_MAX (0xffff) -#define CLK_AUDIO_DIV_INT_FRAC_MIN (0x2) -#define CLK_AUDIO_DIV_INT_INT_SHIFT 24 -#define CLK_AUDIO_DIV_INT_INT_WIDTH 4 - -struct zx_clk_audio_div_table { - unsigned long rate; - unsigned int int_reg; - unsigned int frac_reg; -}; - -#define to_clk_zx_audio_div(_hw) container_of(_hw, struct clk_zx_audio_divider, hw) - -static unsigned long audio_calc_rate(struct clk_zx_audio_divider *audio_div, - u32 reg_frac, u32 reg_int, - unsigned long parent_rate) -{ - unsigned long rate, m, n; - - m = reg_frac & 0xffff; - n = (reg_frac >> 16) & 0xffff; - - m = (reg_int & 0xffff) * n + m; - rate = (parent_rate * n) / m; - - return rate; -} - -static void audio_calc_reg(struct clk_zx_audio_divider *audio_div, - struct zx_clk_audio_div_table *div_table, - unsigned long rate, unsigned long parent_rate) -{ - unsigned int reg_int, reg_frac; - unsigned long m, n, div; - - reg_int = parent_rate / rate; - - if (reg_int > CLK_AUDIO_DIV_INT_FRAC_MAX) - reg_int = CLK_AUDIO_DIV_INT_FRAC_MAX; - else if (reg_int < CLK_AUDIO_DIV_INT_FRAC_MIN) - reg_int = 0; - m = parent_rate - rate * reg_int; - n = rate; - - div = gcd(m, n); - m = m / div; - n = n / div; - - if ((m >> 16) || (n >> 16)) { - if (m > n) { - n = n * 0xffff / m; - m = 0xffff; - } else { - m = m * 0xffff / n; - n = 0xffff; - } - } - reg_frac = m | (n << 16); - - div_table->rate = parent_rate * n / (reg_int * n + m); - div_table->int_reg = reg_int; - div_table->frac_reg = reg_frac; -} - -static unsigned long zx_audio_div_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw); - u32 reg_frac, reg_int; - - reg_frac = readl_relaxed(zx_audio_div->reg_base); - reg_int = readl_relaxed(zx_audio_div->reg_base + 0x4); - - return audio_calc_rate(zx_audio_div, reg_frac, reg_int, parent_rate); -} - -static long zx_audio_div_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw); - struct zx_clk_audio_div_table divt; - - audio_calc_reg(zx_audio_div, &divt, rate, *prate); - - return audio_calc_rate(zx_audio_div, divt.frac_reg, divt.int_reg, *prate); -} - -static int zx_audio_div_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw); - struct zx_clk_audio_div_table divt; - unsigned int val; - - audio_calc_reg(zx_audio_div, &divt, rate, parent_rate); - if (divt.rate != rate) - pr_debug("the real rate is:%ld", divt.rate); - - writel_relaxed(divt.frac_reg, zx_audio_div->reg_base); - - val = readl_relaxed(zx_audio_div->reg_base + 0x4); - val &= ~0xffff; - val |= divt.int_reg | CLK_AUDIO_DIV_INT_FRAC_RE; - writel_relaxed(val, zx_audio_div->reg_base + 0x4); - - mdelay(1); - - val = readl_relaxed(zx_audio_div->reg_base + 0x4); - val &= ~CLK_AUDIO_DIV_INT_FRAC_RE; - writel_relaxed(val, zx_audio_div->reg_base + 0x4); - - return 0; -} - -const struct clk_ops zx_audio_div_ops = { - .recalc_rate = zx_audio_div_recalc_rate, - .round_rate = zx_audio_div_round_rate, - .set_rate = zx_audio_div_set_rate, -}; diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h deleted file mode 100644 index aeaf2a380ba6..000000000000 --- a/drivers/clk/zte/clk.h +++ /dev/null @@ -1,174 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright 2015 Linaro Ltd. - * Copyright (C) 2014 ZTE Corporation. - */ - -#ifndef __ZTE_CLK_H -#define __ZTE_CLK_H -#include <linux/clk-provider.h> -#include <linux/spinlock.h> - -#define PNAME(x) static const char *x[] - -struct zx_pll_config { - unsigned long rate; - u32 cfg0; - u32 cfg1; -}; - -struct clk_zx_pll { - struct clk_hw hw; - void __iomem *reg_base; - const struct zx_pll_config *lookup_table; /* order by rate asc */ - int count; - spinlock_t *lock; - u8 pd_bit; /* power down bit */ - u8 lock_bit; /* pll lock flag bit */ -}; - -#define PLL_RATE(_rate, _cfg0, _cfg1) \ -{ \ - .rate = _rate, \ - .cfg0 = _cfg0, \ - .cfg1 = _cfg1, \ -} - -#define ZX_PLL(_name, _parent, _reg, _table, _pd, _lock) \ -{ \ - .reg_base = (void __iomem *) _reg, \ - .lookup_table = _table, \ - .count = ARRAY_SIZE(_table), \ - .pd_bit = _pd, \ - .lock_bit = _lock, \ - .hw.init = CLK_HW_INIT(_name, _parent, &zx_pll_ops, \ - CLK_GET_RATE_NOCACHE), \ -} - -/* - * The pd_bit is not available on ZX296718, so let's pass something - * bigger than 31, e.g. 0xff, to indicate that. - */ -#define ZX296718_PLL(_name, _parent, _reg, _table) \ -ZX_PLL(_name, _parent, _reg, _table, 0xff, 30) - -struct zx_clk_gate { - struct clk_gate gate; - u16 id; -}; - -#define GATE(_id, _name, _parent, _reg, _bit, _flag, _gflags) \ -{ \ - .gate = { \ - .reg = (void __iomem *) _reg, \ - .bit_idx = (_bit), \ - .flags = _gflags, \ - .lock = &clk_lock, \ - .hw.init = CLK_HW_INIT(_name, \ - _parent, \ - &clk_gate_ops, \ - _flag | CLK_IGNORE_UNUSED), \ - }, \ - .id = _id, \ -} - -struct zx_clk_fixed_factor { - struct clk_fixed_factor factor; - u16 id; -}; - -#define FFACTOR(_id, _name, _parent, _mult, _div, _flag) \ -{ \ - .factor = { \ - .div = _div, \ - .mult = _mult, \ - .hw.init = CLK_HW_INIT(_name, \ - _parent, \ - &clk_fixed_factor_ops, \ - _flag), \ - }, \ - .id = _id, \ -} - -struct zx_clk_mux { - struct clk_mux mux; - u16 id; -}; - -#define MUX_F(_id, _name, _parent, _reg, _shift, _width, _flag, _mflag) \ -{ \ - .mux = { \ - .reg = (void __iomem *) _reg, \ - .mask = BIT(_width) - 1, \ - .shift = _shift, \ - .flags = _mflag, \ - .lock = &clk_lock, \ - .hw.init = CLK_HW_INIT_PARENTS(_name, \ - _parent, \ - &clk_mux_ops, \ - _flag), \ - }, \ - .id = _id, \ -} - -#define MUX(_id, _name, _parent, _reg, _shift, _width) \ -MUX_F(_id, _name, _parent, _reg, _shift, _width, 0, 0) - -struct zx_clk_div { - struct clk_divider div; - u16 id; -}; - -#define DIV_T(_id, _name, _parent, _reg, _shift, _width, _flag, _table) \ -{ \ - .div = { \ - .reg = (void __iomem *) _reg, \ - .shift = _shift, \ - .width = _width, \ - .flags = 0, \ - .table = _table, \ - .lock = &clk_lock, \ - .hw.init = CLK_HW_INIT(_name, \ - _parent, \ - &clk_divider_ops, \ - _flag), \ - }, \ - .id = _id, \ -} - -struct clk_zx_audio_divider { - struct clk_hw hw; - void __iomem *reg_base; - unsigned int rate_count; - spinlock_t *lock; - u16 id; -}; - -#define AUDIO_DIV(_id, _name, _parent, _reg) \ -{ \ - .reg_base = (void __iomem *) _reg, \ - .lock = &clk_lock, \ - .hw.init = CLK_HW_INIT(_name, \ - _parent, \ - &zx_audio_div_ops, \ - 0), \ - .id = _id, \ -} - -struct clk *clk_register_zx_pll(const char *name, const char *parent_name, - unsigned long flags, void __iomem *reg_base, - const struct zx_pll_config *lookup_table, int count, spinlock_t *lock); - -struct clk_zx_audio { - struct clk_hw hw; - void __iomem *reg_base; -}; - -struct clk *clk_register_zx_audio(const char *name, - const char * const parent_name, - unsigned long flags, void __iomem *reg_base); - -extern const struct clk_ops zx_pll_ops; -extern const struct clk_ops zx_audio_div_ops; - -#endif diff --git a/drivers/soc/xilinx/Kconfig b/drivers/soc/xilinx/Kconfig index 0b1708dae361..53af9115dc31 100644 --- a/drivers/soc/xilinx/Kconfig +++ b/drivers/soc/xilinx/Kconfig @@ -1,23 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 menu "Xilinx SoC drivers" -config XILINX_VCU - tristate "Xilinx VCU logicoreIP Init" - depends on HAS_IOMEM - select REGMAP_MMIO - help - Provides the driver to enable and disable the isolation between the - processing system and programmable logic part by using the logicoreIP - register set. This driver also configures the frequency based on the - clock information from the logicoreIP register set. - - If you say yes here you get support for the logicoreIP. - - If unsure, say N. - - To compile this driver as a module, choose M here: the - module will be called xlnx_vcu. - config ZYNQMP_POWER bool "Enable Xilinx Zynq MPSoC Power Management driver" depends on PM && ZYNQMP_FIRMWARE diff --git a/drivers/soc/xilinx/Makefile b/drivers/soc/xilinx/Makefile index f66bfea5de17..9854e6f6086b 100644 --- a/drivers/soc/xilinx/Makefile +++ b/drivers/soc/xilinx/Makefile @@ -1,4 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 -obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o obj-$(CONFIG_ZYNQMP_POWER) += zynqmp_power.o obj-$(CONFIG_ZYNQMP_PM_DOMAINS) += zynqmp_pm_domains.o diff --git a/drivers/soc/xilinx/xlnx_vcu.c b/drivers/soc/xilinx/xlnx_vcu.c deleted file mode 100644 index 14daad4efc58..000000000000 --- a/drivers/soc/xilinx/xlnx_vcu.c +++ /dev/null @@ -1,628 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx VCU Init - * - * Copyright (C) 2016 - 2017 Xilinx, Inc. - * - * Contacts Dhaval Shah <dshah@xilinx.com> - */ -#include <linux/clk.h> -#include <linux/device.h> -#include <linux/errno.h> -#include <linux/io.h> -#include <linux/mfd/syscon.h> -#include <linux/mfd/syscon/xlnx-vcu.h> -#include <linux/module.h> -#include <linux/of_platform.h> -#include <linux/platform_device.h> -#include <linux/regmap.h> - -/* vcu slcr registers, bitmask and shift */ -#define VCU_PLL_CTRL 0x24 -#define VCU_PLL_CTRL_RESET_MASK 0x01 -#define VCU_PLL_CTRL_RESET_SHIFT 0 -#define VCU_PLL_CTRL_BYPASS_MASK 0x01 -#define VCU_PLL_CTRL_BYPASS_SHIFT 3 -#define VCU_PLL_CTRL_FBDIV_MASK 0x7f -#define VCU_PLL_CTRL_FBDIV_SHIFT 8 -#define VCU_PLL_CTRL_POR_IN_MASK 0x01 -#define VCU_PLL_CTRL_POR_IN_SHIFT 1 -#define VCU_PLL_CTRL_PWR_POR_MASK 0x01 -#define VCU_PLL_CTRL_PWR_POR_SHIFT 2 -#define VCU_PLL_CTRL_CLKOUTDIV_MASK 0x03 -#define VCU_PLL_CTRL_CLKOUTDIV_SHIFT 16 -#define VCU_PLL_CTRL_DEFAULT 0 -#define VCU_PLL_DIV2 2 - -#define VCU_PLL_CFG 0x28 -#define VCU_PLL_CFG_RES_MASK 0x0f -#define VCU_PLL_CFG_RES_SHIFT 0 -#define VCU_PLL_CFG_CP_MASK 0x0f -#define VCU_PLL_CFG_CP_SHIFT 5 -#define VCU_PLL_CFG_LFHF_MASK 0x03 -#define VCU_PLL_CFG_LFHF_SHIFT 10 -#define VCU_PLL_CFG_LOCK_CNT_MASK 0x03ff -#define VCU_PLL_CFG_LOCK_CNT_SHIFT 13 -#define VCU_PLL_CFG_LOCK_DLY_MASK 0x7f -#define VCU_PLL_CFG_LOCK_DLY_SHIFT 25 -#define VCU_ENC_CORE_CTRL 0x30 -#define VCU_ENC_MCU_CTRL 0x34 -#define VCU_DEC_CORE_CTRL 0x38 -#define VCU_DEC_MCU_CTRL 0x3c -#define VCU_PLL_DIVISOR_MASK 0x3f -#define VCU_PLL_DIVISOR_SHIFT 4 -#define VCU_SRCSEL_MASK 0x01 -#define VCU_SRCSEL_SHIFT 0 -#define VCU_SRCSEL_PLL 1 - -#define VCU_PLL_STATUS 0x60 -#define VCU_PLL_STATUS_LOCK_STATUS_MASK 0x01 - -#define MHZ 1000000 -#define FVCO_MIN (1500U * MHZ) -#define FVCO_MAX (3000U * MHZ) -#define DIVISOR_MIN 0 -#define DIVISOR_MAX 63 -#define FRAC 100 -#define LIMIT (10 * MHZ) - -/** - * struct xvcu_device - Xilinx VCU init device structure - * @dev: Platform device - * @pll_ref: pll ref clock source - * @aclk: axi clock source - * @logicore_reg_ba: logicore reg base address - * @vcu_slcr_ba: vcu_slcr Register base address - * @coreclk: core clock frequency - */ -struct xvcu_device { - struct device *dev; - struct clk *pll_ref; - struct clk *aclk; - struct regmap *logicore_reg_ba; - void __iomem *vcu_slcr_ba; - u32 coreclk; -}; - -static struct regmap_config vcu_settings_regmap_config = { - .name = "regmap", - .reg_bits = 32, - .val_bits = 32, - .reg_stride = 4, - .max_register = 0xfff, - .cache_type = REGCACHE_NONE, -}; - -/** - * struct xvcu_pll_cfg - Helper data - * @fbdiv: The integer portion of the feedback divider to the PLL - * @cp: PLL charge pump control - * @res: PLL loop filter resistor control - * @lfhf: PLL loop filter high frequency capacitor control - * @lock_dly: Lock circuit configuration settings for lock windowsize - * @lock_cnt: Lock circuit counter setting - */ -struct xvcu_pll_cfg { - u32 fbdiv; - u32 cp; - u32 res; - u32 lfhf; - u32 lock_dly; - u32 lock_cnt; -}; - -static const struct xvcu_pll_cfg xvcu_pll_cfg[] = { - { 25, 3, 10, 3, 63, 1000 }, - { 26, 3, 10, 3, 63, 1000 }, - { 27, 4, 6, 3, 63, 1000 }, - { 28, 4, 6, 3, 63, 1000 }, - { 29, 4, 6, 3, 63, 1000 }, - { 30, 4, 6, 3, 63, 1000 }, - { 31, 6, 1, 3, 63, 1000 }, - { 32, 6, 1, 3, 63, 1000 }, - { 33, 4, 10, 3, 63, 1000 }, - { 34, 5, 6, 3, 63, 1000 }, - { 35, 5, 6, 3, 63, 1000 }, - { 36, 5, 6, 3, 63, 1000 }, - { 37, 5, 6, 3, 63, 1000 }, - { 38, 5, 6, 3, 63, 975 }, - { 39, 3, 12, 3, 63, 950 }, - { 40, 3, 12, 3, 63, 925 }, - { 41, 3, 12, 3, 63, 900 }, - { 42, 3, 12, 3, 63, 875 }, - { 43, 3, 12, 3, 63, 850 }, - { 44, 3, 12, 3, 63, 850 }, - { 45, 3, 12, 3, 63, 825 }, - { 46, 3, 12, 3, 63, 800 }, - { 47, 3, 12, 3, 63, 775 }, - { 48, 3, 12, 3, 63, 775 }, - { 49, 3, 12, 3, 63, 750 }, - { 50, 3, 12, 3, 63, 750 }, - { 51, 3, 2, 3, 63, 725 }, - { 52, 3, 2, 3, 63, 700 }, - { 53, 3, 2, 3, 63, 700 }, - { 54, 3, 2, 3, 63, 675 }, - { 55, 3, 2, 3, 63, 675 }, - { 56, 3, 2, 3, 63, 650 }, - { 57, 3, 2, 3, 63, 650 }, - { 58, 3, 2, 3, 63, 625 }, - { 59, 3, 2, 3, 63, 625 }, - { 60, 3, 2, 3, 63, 625 }, - { 61, 3, 2, 3, 63, 600 }, - { 62, 3, 2, 3, 63, 600 }, - { 63, 3, 2, 3, 63, 600 }, - { 64, 3, 2, 3, 63, 600 }, - { 65, 3, 2, 3, 63, 600 }, - { 66, 3, 2, 3, 63, 600 }, - { 67, 3, 2, 3, 63, 600 }, - { 68, 3, 2, 3, 63, 600 }, - { 69, 3, 2, 3, 63, 600 }, - { 70, 3, 2, 3, 63, 600 }, - { 71, 3, 2, 3, 63, 600 }, - { 72, 3, 2, 3, 63, 600 }, - { 73, 3, 2, 3, 63, 600 }, - { 74, 3, 2, 3, 63, 600 }, - { 75, 3, 2, 3, 63, 600 }, - { 76, 3, 2, 3, 63, 600 }, - { 77, 3, 2, 3, 63, 600 }, - { 78, 3, 2, 3, 63, 600 }, - { 79, 3, 2, 3, 63, 600 }, - { 80, 3, 2, 3, 63, 600 }, - { 81, 3, 2, 3, 63, 600 }, - { 82, 3, 2, 3, 63, 600 }, - { 83, 4, 2, 3, 63, 600 }, - { 84, 4, 2, 3, 63, 600 }, - { 85, 4, 2, 3, 63, 600 }, - { 86, 4, 2, 3, 63, 600 }, - { 87, 4, 2, 3, 63, 600 }, - { 88, 4, 2, 3, 63, 600 }, - { 89, 4, 2, 3, 63, 600 }, - { 90, 4, 2, 3, 63, 600 }, - { 91, 4, 2, 3, 63, 600 }, - { 92, 4, 2, 3, 63, 600 }, - { 93, 4, 2, 3, 63, 600 }, - { 94, 4, 2, 3, 63, 600 }, - { 95, 4, 2, 3, 63, 600 }, - { 96, 4, 2, 3, 63, 600 }, - { 97, 4, 2, 3, 63, 600 }, - { 98, 4, 2, 3, 63, 600 }, - { 99, 4, 2, 3, 63, 600 }, - { 100, 4, 2, 3, 63, 600 }, - { 101, 4, 2, 3, 63, 600 }, - { 102, 4, 2, 3, 63, 600 }, - { 103, 5, 2, 3, 63, 600 }, - { 104, 5, 2, 3, 63, 600 }, - { 105, 5, 2, 3, 63, 600 }, - { 106, 5, 2, 3, 63, 600 }, - { 107, 3, 4, 3, 63, 600 }, - { 108, 3, 4, 3, 63, 600 }, - { 109, 3, 4, 3, 63, 600 }, - { 110, 3, 4, 3, 63, 600 }, - { 111, 3, 4, 3, 63, 600 }, - { 112, 3, 4, 3, 63, 600 }, - { 113, 3, 4, 3, 63, 600 }, - { 114, 3, 4, 3, 63, 600 }, - { 115, 3, 4, 3, 63, 600 }, - { 116, 3, 4, 3, 63, 600 }, - { 117, 3, 4, 3, 63, 600 }, - { 118, 3, 4, 3, 63, 600 }, - { 119, 3, 4, 3, 63, 600 }, - { 120, 3, 4, 3, 63, 600 }, - { 121, 3, 4, 3, 63, 600 }, - { 122, 3, 4, 3, 63, 600 }, - { 123, 3, 4, 3, 63, 600 }, - { 124, 3, 4, 3, 63, 600 }, - { 125, 3, 4, 3, 63, 600 }, -}; - -/** - * xvcu_read - Read from the VCU register space - * @iomem: vcu reg space base address - * @offset: vcu reg offset from base - * - * Return: Returns 32bit value from VCU register specified - * - */ -static inline u32 xvcu_read(void __iomem *iomem, u32 offset) -{ - return ioread32(iomem + offset); -} - -/** - * xvcu_write - Write to the VCU register space - * @iomem: vcu reg space base address - * @offset: vcu reg offset from base - * @value: Value to write - */ -static inline void xvcu_write(void __iomem *iomem, u32 offset, u32 value) -{ - iowrite32(value, iomem + offset); -} - -/** - * xvcu_write_field_reg - Write to the vcu reg field - * @iomem: vcu reg space base address - * @offset: vcu reg offset from base - * @field: vcu reg field to write to - * @mask: vcu reg mask - * @shift: vcu reg number of bits to shift the bitfield - */ -static void xvcu_write_field_reg(void __iomem *iomem, int offset, - u32 field, u32 mask, int shift) -{ - u32 val = xvcu_read(iomem, offset); - - val &= ~(mask << shift); - val |= (field & mask) << shift; - - xvcu_write(iomem, offset, val); -} - -/** - * xvcu_set_vcu_pll_info - Set the VCU PLL info - * @xvcu: Pointer to the xvcu_device structure - * - * Programming the VCU PLL based on the user configuration - * (ref clock freq, core clock freq, mcu clock freq). - * Core clock frequency has higher priority than mcu clock frequency - * Errors in following cases - * - When mcu or clock clock get from logicoreIP is 0 - * - When VCU PLL DIV related bits value other than 1 - * - When proper data not found for given data - * - When sis570_1 clocksource related operation failed - * - * Return: Returns status, either success or error+reason - */ -static int xvcu_set_vcu_pll_info(struct xvcu_device *xvcu) -{ - u32 refclk, coreclk, mcuclk, inte, deci; - u32 divisor_mcu, divisor_core, fvco; - u32 clkoutdiv, vcu_pll_ctrl, pll_clk; - u32 cfg_val, mod, ctrl; - int ret, i; - const struct xvcu_pll_cfg *found = NULL; - - regmap_read(xvcu->logicore_reg_ba, VCU_PLL_CLK, &inte); - regmap_read(xvcu->logicore_reg_ba, VCU_PLL_CLK_DEC, &deci); - regmap_read(xvcu->logicore_reg_ba, VCU_CORE_CLK, &coreclk); - coreclk *= MHZ; - regmap_read(xvcu->logicore_reg_ba, VCU_MCU_CLK, &mcuclk); - mcuclk *= MHZ; - if (!mcuclk || !coreclk) { - dev_err(xvcu->dev, "Invalid mcu and core clock data\n"); - return -EINVAL; - } - - refclk = (inte * MHZ) + (deci * (MHZ / FRAC)); - dev_dbg(xvcu->dev, "Ref clock from logicoreIP is %uHz\n", refclk); - dev_dbg(xvcu->dev, "Core clock from logicoreIP is %uHz\n", coreclk); - dev_dbg(xvcu->dev, "Mcu clock from logicoreIP is %uHz\n", mcuclk); - - clk_disable_unprepare(xvcu->pll_ref); - ret = clk_set_rate(xvcu->pll_ref, refclk); - if (ret) - dev_warn(xvcu->dev, "failed to set logicoreIP refclk rate\n"); - - ret = clk_prepare_enable(xvcu->pll_ref); - if (ret) { - dev_err(xvcu->dev, "failed to enable pll_ref clock source\n"); - return ret; - } - - refclk = clk_get_rate(xvcu->pll_ref); - - /* - * The divide-by-2 should be always enabled (==1) - * to meet the timing in the design. - * Otherwise, it's an error - */ - vcu_pll_ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_PLL_CTRL); - clkoutdiv = vcu_pll_ctrl >> VCU_PLL_CTRL_CLKOUTDIV_SHIFT; - clkoutdiv = clkoutdiv & VCU_PLL_CTRL_CLKOUTDIV_MASK; - if (clkoutdiv != 1) { - dev_err(xvcu->dev, "clkoutdiv value is invalid\n"); - return -EINVAL; - } - - for (i = ARRAY_SIZE(xvcu_pll_cfg) - 1; i >= 0; i--) { - const struct xvcu_pll_cfg *cfg = &xvcu_pll_cfg[i]; - - fvco = cfg->fbdiv * refclk; - if (fvco >= FVCO_MIN && fvco <= FVCO_MAX) { - pll_clk = fvco / VCU_PLL_DIV2; - if (fvco % VCU_PLL_DIV2 != 0) - pll_clk++; - mod = pll_clk % coreclk; - if (mod < LIMIT) { - divisor_core = pll_clk / coreclk; - } else if (coreclk - mod < LIMIT) { - divisor_core = pll_clk / coreclk; - divisor_core++; - } else { - continue; - } - if (divisor_core >= DIVISOR_MIN && - divisor_core <= DIVISOR_MAX) { - found = cfg; - divisor_mcu = pll_clk / mcuclk; - mod = pll_clk % mcuclk; - if (mcuclk - mod < LIMIT) - divisor_mcu++; - break; - } - } - } - - if (!found) { - dev_err(xvcu->dev, "Invalid clock combination.\n"); - return -EINVAL; - } - - xvcu->coreclk = pll_clk / divisor_core; - mcuclk = pll_clk / divisor_mcu; - dev_dbg(xvcu->dev, "Actual Ref clock freq is %uHz\n", refclk); - dev_dbg(xvcu->dev, "Actual Core clock freq is %uHz\n", xvcu->coreclk); - dev_dbg(xvcu->dev, "Actual Mcu clock freq is %uHz\n", mcuclk); - - vcu_pll_ctrl &= ~(VCU_PLL_CTRL_FBDIV_MASK << VCU_PLL_CTRL_FBDIV_SHIFT); - vcu_pll_ctrl |= (found->fbdiv & VCU_PLL_CTRL_FBDIV_MASK) << - VCU_PLL_CTRL_FBDIV_SHIFT; - vcu_pll_ctrl &= ~(VCU_PLL_CTRL_POR_IN_MASK << - VCU_PLL_CTRL_POR_IN_SHIFT); - vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_POR_IN_MASK) << - VCU_PLL_CTRL_POR_IN_SHIFT; - vcu_pll_ctrl &= ~(VCU_PLL_CTRL_PWR_POR_MASK << - VCU_PLL_CTRL_PWR_POR_SHIFT); - vcu_pll_ctrl |= (VCU_PLL_CTRL_DEFAULT & VCU_PLL_CTRL_PWR_POR_MASK) << - VCU_PLL_CTRL_PWR_POR_SHIFT; - xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, vcu_pll_ctrl); - - /* Set divisor for the core and mcu clock */ - ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL); - ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); - ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) << - VCU_PLL_DIVISOR_SHIFT; - ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); - ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; - xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_CORE_CTRL, ctrl); - - ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL); - ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); - ctrl |= (divisor_core & VCU_PLL_DIVISOR_MASK) << - VCU_PLL_DIVISOR_SHIFT; - ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); - ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; - xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_CORE_CTRL, ctrl); - - ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL); - ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); - ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT; - ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); - ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; - xvcu_write(xvcu->vcu_slcr_ba, VCU_ENC_MCU_CTRL, ctrl); - - ctrl = xvcu_read(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL); - ctrl &= ~(VCU_PLL_DIVISOR_MASK << VCU_PLL_DIVISOR_SHIFT); - ctrl |= (divisor_mcu & VCU_PLL_DIVISOR_MASK) << VCU_PLL_DIVISOR_SHIFT; - ctrl &= ~(VCU_SRCSEL_MASK << VCU_SRCSEL_SHIFT); - ctrl |= (VCU_SRCSEL_PLL & VCU_SRCSEL_MASK) << VCU_SRCSEL_SHIFT; - xvcu_write(xvcu->vcu_slcr_ba, VCU_DEC_MCU_CTRL, ctrl); - - /* Set RES, CP, LFHF, LOCK_CNT and LOCK_DLY cfg values */ - cfg_val = (found->res << VCU_PLL_CFG_RES_SHIFT) | - (found->cp << VCU_PLL_CFG_CP_SHIFT) | - (found->lfhf << VCU_PLL_CFG_LFHF_SHIFT) | - (found->lock_cnt << VCU_PLL_CFG_LOCK_CNT_SHIFT) | - (found->lock_dly << VCU_PLL_CFG_LOCK_DLY_SHIFT); - xvcu_write(xvcu->vcu_slcr_ba, VCU_PLL_CFG, cfg_val); - - return 0; -} - -/** - * xvcu_set_pll - PLL init sequence - * @xvcu: Pointer to the xvcu_device structure - * - * Call the api to set the PLL info and once that is done then - * init the PLL sequence to make the PLL stable. - * - * Return: Returns status, either success or error+reason - */ -static int xvcu_set_pll(struct xvcu_device *xvcu) -{ - u32 lock_status; - unsigned long timeout; - int ret; - - ret = xvcu_set_vcu_pll_info(xvcu); - if (ret) { - dev_err(xvcu->dev, "failed to set pll info\n"); - return ret; - } - - xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, - 1, VCU_PLL_CTRL_BYPASS_MASK, - VCU_PLL_CTRL_BYPASS_SHIFT); - xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, - 1, VCU_PLL_CTRL_RESET_MASK, - VCU_PLL_CTRL_RESET_SHIFT); - xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, - 0, VCU_PLL_CTRL_RESET_MASK, - VCU_PLL_CTRL_RESET_SHIFT); - /* - * Defined the timeout for the max time to wait the - * PLL_STATUS to be locked. - */ - timeout = jiffies + msecs_to_jiffies(2000); - do { - lock_status = xvcu_read(xvcu->vcu_slcr_ba, VCU_PLL_STATUS); - if (lock_status & VCU_PLL_STATUS_LOCK_STATUS_MASK) { - xvcu_write_field_reg(xvcu->vcu_slcr_ba, VCU_PLL_CTRL, - 0, VCU_PLL_CTRL_BYPASS_MASK, - VCU_PLL_CTRL_BYPASS_SHIFT); - return 0; - } - } while (!time_after(jiffies, timeout)); - - /* PLL is not locked even after the timeout of the 2sec */ - dev_err(xvcu->dev, "PLL is not locked\n"); - return -ETIMEDOUT; -} - -/** - * xvcu_probe - Probe existence of the logicoreIP - * and initialize PLL - * - * @pdev: Pointer to the platform_device structure - * - * Return: Returns 0 on success - * Negative error code otherwise - */ -static int xvcu_probe(struct platform_device *pdev) -{ - struct resource *res; - struct xvcu_device *xvcu; - void __iomem *regs; - int ret; - - xvcu = devm_kzalloc(&pdev->dev, sizeof(*xvcu), GFP_KERNEL); - if (!xvcu) - return -ENOMEM; - - xvcu->dev = &pdev->dev; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vcu_slcr"); - if (!res) { - dev_err(&pdev->dev, "get vcu_slcr memory resource failed.\n"); - return -ENODEV; - } - - xvcu->vcu_slcr_ba = devm_ioremap(&pdev->dev, res->start, - resource_size(res)); - if (!xvcu->vcu_slcr_ba) { - dev_err(&pdev->dev, "vcu_slcr register mapping failed.\n"); - return -ENOMEM; - } - - xvcu->logicore_reg_ba = - syscon_regmap_lookup_by_compatible("xlnx,vcu-settings"); - if (IS_ERR(xvcu->logicore_reg_ba)) { - dev_info(&pdev->dev, - "could not find xlnx,vcu-settings: trying direct register access\n"); - - res = platform_get_resource_byname(pdev, - IORESOURCE_MEM, "logicore"); - if (!res) { - dev_err(&pdev->dev, "get logicore memory resource failed.\n"); - return -ENODEV; - } - - regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); - if (!regs) { - dev_err(&pdev->dev, "logicore register mapping failed.\n"); - return -ENOMEM; - } - - xvcu->logicore_reg_ba = - devm_regmap_init_mmio(&pdev->dev, regs, - &vcu_settings_regmap_config); - if (IS_ERR(xvcu->logicore_reg_ba)) { - dev_err(&pdev->dev, "failed to init regmap\n"); - return PTR_ERR(xvcu->logicore_reg_ba); - } - } - - xvcu->aclk = devm_clk_get(&pdev->dev, "aclk"); - if (IS_ERR(xvcu->aclk)) { - dev_err(&pdev->dev, "Could not get aclk clock\n"); - return PTR_ERR(xvcu->aclk); - } - - xvcu->pll_ref = devm_clk_get(&pdev->dev, "pll_ref"); - if (IS_ERR(xvcu->pll_ref)) { - dev_err(&pdev->dev, "Could not get pll_ref clock\n"); - return PTR_ERR(xvcu->pll_ref); - } - - ret = clk_prepare_enable(xvcu->aclk); - if (ret) { - dev_err(&pdev->dev, "aclk clock enable failed\n"); - return ret; - } - - ret = clk_prepare_enable(xvcu->pll_ref); - if (ret) { - dev_err(&pdev->dev, "pll_ref clock enable failed\n"); - goto error_aclk; - } - - /* - * Do the Gasket isolation and put the VCU out of reset - * Bit 0 : Gasket isolation - * Bit 1 : put VCU out of reset - */ - regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, VCU_GASKET_VALUE); - - /* Do the PLL Settings based on the ref clk,core and mcu clk freq */ - ret = xvcu_set_pll(xvcu); - if (ret) { - dev_err(&pdev->dev, "Failed to set the pll\n"); - goto error_pll_ref; - } - - dev_set_drvdata(&pdev->dev, xvcu); - - return 0; - -error_pll_ref: - clk_disable_unprepare(xvcu->pll_ref); -error_aclk: - clk_disable_unprepare(xvcu->aclk); - return ret; -} - -/** - * xvcu_remove - Insert gasket isolation - * and disable the clock - * @pdev: Pointer to the platform_device structure - * - * Return: Returns 0 on success - * Negative error code otherwise - */ -static int xvcu_remove(struct platform_device *pdev) -{ - struct xvcu_device *xvcu; - - xvcu = platform_get_drvdata(pdev); - if (!xvcu) - return -ENODEV; - - /* Add the the Gasket isolation and put the VCU in reset. */ - regmap_write(xvcu->logicore_reg_ba, VCU_GASKET_INIT, 0); - - clk_disable_unprepare(xvcu->pll_ref); - clk_disable_unprepare(xvcu->aclk); - - return 0; -} - -static const struct of_device_id xvcu_of_id_table[] = { - { .compatible = "xlnx,vcu" }, - { .compatible = "xlnx,vcu-logicoreip-1.0" }, - { } -}; -MODULE_DEVICE_TABLE(of, xvcu_of_id_table); - -static struct platform_driver xvcu_driver = { - .driver = { - .name = "xilinx-vcu", - .of_match_table = xvcu_of_id_table, - }, - .probe = xvcu_probe, - .remove = xvcu_remove, -}; - -module_platform_driver(xvcu_driver); - -MODULE_AUTHOR("Dhaval Shah <dshah@xilinx.com>"); -MODULE_DESCRIPTION("Xilinx VCU init Driver"); -MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/clock/axg-clkc.h b/include/dt-bindings/clock/axg-clkc.h index e2749dbc74b8..93752ea107e3 100644 --- a/include/dt-bindings/clock/axg-clkc.h +++ b/include/dt-bindings/clock/axg-clkc.h @@ -70,7 +70,6 @@ #define CLKID_HIFI_PLL 69 #define CLKID_PCIE_CML_EN0 79 #define CLKID_PCIE_CML_EN1 80 -#define CLKID_MIPI_ENABLE 81 #define CLKID_GEN_CLK 84 #define CLKID_VPU_0_SEL 92 #define CLKID_VPU_0 93 diff --git a/include/dt-bindings/clock/imx8-clock.h b/include/dt-bindings/clock/imx8-clock.h index 673a8c662340..82b1fc8d1ee0 100644 --- a/include/dt-bindings/clock/imx8-clock.h +++ b/include/dt-bindings/clock/imx8-clock.h @@ -64,6 +64,8 @@ #define IMX_DC0_PLL1_CLK 81 #define IMX_DC0_DISP0_CLK 82 #define IMX_DC0_DISP1_CLK 83 +#define IMX_DC0_BYPASS0_CLK 84 +#define IMX_DC0_BYPASS1_CLK 85 /* MIPI-LVDS SS */ #define IMX_MIPI_IPG_CLK 90 diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h index e63a5530aed7..47c6f7f9582c 100644 --- a/include/dt-bindings/clock/imx8mm-clock.h +++ b/include/dt-bindings/clock/imx8mm-clock.h @@ -274,6 +274,14 @@ #define IMX8MM_CLK_A53_CORE 251 -#define IMX8MM_CLK_END 252 +#define IMX8MM_CLK_CLKOUT1_SEL 252 +#define IMX8MM_CLK_CLKOUT1_DIV 253 +#define IMX8MM_CLK_CLKOUT1 254 +#define IMX8MM_CLK_CLKOUT2_SEL 255 +#define IMX8MM_CLK_CLKOUT2_DIV 256 +#define IMX8MM_CLK_CLKOUT2 257 + + +#define IMX8MM_CLK_END 258 #endif diff --git a/include/dt-bindings/clock/imx8mn-clock.h b/include/dt-bindings/clock/imx8mn-clock.h index 621ea0e87c67..d24b627cb2e7 100644 --- a/include/dt-bindings/clock/imx8mn-clock.h +++ b/include/dt-bindings/clock/imx8mn-clock.h @@ -234,6 +234,13 @@ #define IMX8MN_CLK_A53_CORE 214 -#define IMX8MN_CLK_END 215 +#define IMX8MN_CLK_CLKOUT1_SEL 215 +#define IMX8MN_CLK_CLKOUT1_DIV 216 +#define IMX8MN_CLK_CLKOUT1 217 +#define IMX8MN_CLK_CLKOUT2_SEL 218 +#define IMX8MN_CLK_CLKOUT2_DIV 219 +#define IMX8MN_CLK_CLKOUT2 220 + +#define IMX8MN_CLK_END 221 #endif diff --git a/include/dt-bindings/clock/imx8mq-clock.h b/include/dt-bindings/clock/imx8mq-clock.h index 9b8045d75b8b..82e907ce7bdd 100644 --- a/include/dt-bindings/clock/imx8mq-clock.h +++ b/include/dt-bindings/clock/imx8mq-clock.h @@ -431,6 +431,20 @@ #define IMX8MQ_CLK_A53_CORE 289 -#define IMX8MQ_CLK_END 290 +#define IMX8MQ_CLK_MON_AUDIO_PLL1_DIV 290 +#define IMX8MQ_CLK_MON_AUDIO_PLL2_DIV 291 +#define IMX8MQ_CLK_MON_VIDEO_PLL1_DIV 292 +#define IMX8MQ_CLK_MON_GPU_PLL_DIV 293 +#define IMX8MQ_CLK_MON_VPU_PLL_DIV 294 +#define IMX8MQ_CLK_MON_ARM_PLL_DIV 295 +#define IMX8MQ_CLK_MON_SYS_PLL1_DIV 296 +#define IMX8MQ_CLK_MON_SYS_PLL2_DIV 297 +#define IMX8MQ_CLK_MON_SYS_PLL3_DIV 298 +#define IMX8MQ_CLK_MON_DRAM_PLL_DIV 299 +#define IMX8MQ_CLK_MON_VIDEO_PLL2_DIV 300 +#define IMX8MQ_CLK_MON_SEL 301 +#define IMX8MQ_CLK_MON_CLK2_OUT 302 + +#define IMX8MQ_CLK_END 303 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */ diff --git a/include/dt-bindings/clock/meson8b-clkc.h b/include/dt-bindings/clock/meson8b-clkc.h index 4c5965ae1df4..f33781338eda 100644 --- a/include/dt-bindings/clock/meson8b-clkc.h +++ b/include/dt-bindings/clock/meson8b-clkc.h @@ -6,8 +6,6 @@ #ifndef __MESON8B_CLKC_H #define __MESON8B_CLKC_H -#define CLKID_UNUSED 0 -#define CLKID_XTAL 1 #define CLKID_PLL_FIXED 2 #define CLKID_PLL_VID 3 #define CLKID_PLL_SYS 4 diff --git a/include/dt-bindings/clock/rk3368-cru.h b/include/dt-bindings/clock/rk3368-cru.h index 0a06c5f514d7..83c72a163fd3 100644 --- a/include/dt-bindings/clock/rk3368-cru.h +++ b/include/dt-bindings/clock/rk3368-cru.h @@ -78,6 +78,7 @@ #define SCLK_TIMER13 136 #define SCLK_TIMER14 137 #define SCLK_TIMER15 138 +#define SCLK_VIP_OUT 139 #define DCLK_VOP 190 #define MCLK_CRYPTO 191 @@ -148,6 +149,8 @@ #define PCLK_VIP 367 #define PCLK_WDT 368 #define PCLK_EFUSE256 369 +#define PCLK_DPHYRX 370 +#define PCLK_DPHYTX0 371 /* hclk gates */ #define HCLK_SFC 448 diff --git a/include/dt-bindings/clock/sun50i-h6-r-ccu.h b/include/dt-bindings/clock/sun50i-h6-r-ccu.h index 76136132a13e..890368d252c4 100644 --- a/include/dt-bindings/clock/sun50i-h6-r-ccu.h +++ b/include/dt-bindings/clock/sun50i-h6-r-ccu.h @@ -21,4 +21,6 @@ #define CLK_IR 11 #define CLK_W1 12 +#define CLK_R_APB2_RSB 13 + #endif /* _DT_BINDINGS_CLK_SUN50I_H6_R_CCU_H_ */ diff --git a/include/dt-bindings/clock/sun50i-h616-ccu.h b/include/dt-bindings/clock/sun50i-h616-ccu.h new file mode 100644 index 000000000000..4fc08b0df2f3 --- /dev/null +++ b/include/dt-bindings/clock/sun50i-h616-ccu.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2020 Arm Ltd. + */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_H616_H_ +#define _DT_BINDINGS_CLK_SUN50I_H616_H_ + +#define CLK_PLL_PERIPH0 4 + +#define CLK_CPUX 21 + +#define CLK_APB1 26 + +#define CLK_DE 29 +#define CLK_BUS_DE 30 +#define CLK_DEINTERLACE 31 +#define CLK_BUS_DEINTERLACE 32 +#define CLK_G2D 33 +#define CLK_BUS_G2D 34 +#define CLK_GPU0 35 +#define CLK_BUS_GPU 36 +#define CLK_GPU1 37 +#define CLK_CE 38 +#define CLK_BUS_CE 39 +#define CLK_VE 40 +#define CLK_BUS_VE 41 +#define CLK_BUS_DMA 42 +#define CLK_BUS_HSTIMER 43 +#define CLK_AVS 44 +#define CLK_BUS_DBG 45 +#define CLK_BUS_PSI 46 +#define CLK_BUS_PWM 47 +#define CLK_BUS_IOMMU 48 + +#define CLK_MBUS_DMA 50 +#define CLK_MBUS_VE 51 +#define CLK_MBUS_CE 52 +#define CLK_MBUS_TS 53 +#define CLK_MBUS_NAND 54 +#define CLK_MBUS_G2D 55 + +#define CLK_NAND0 57 +#define CLK_NAND1 58 +#define CLK_BUS_NAND 59 +#define CLK_MMC0 60 +#define CLK_MMC1 61 +#define CLK_MMC2 62 +#define CLK_BUS_MMC0 63 +#define CLK_BUS_MMC1 64 +#define CLK_BUS_MMC2 65 +#define CLK_BUS_UART0 66 +#define CLK_BUS_UART1 67 +#define CLK_BUS_UART2 68 +#define CLK_BUS_UART3 69 +#define CLK_BUS_UART4 70 +#define CLK_BUS_UART5 71 +#define CLK_BUS_I2C0 72 +#define CLK_BUS_I2C1 73 +#define CLK_BUS_I2C2 74 +#define CLK_BUS_I2C3 75 +#define CLK_BUS_I2C4 76 +#define CLK_SPI0 77 +#define CLK_SPI1 78 +#define CLK_BUS_SPI0 79 +#define CLK_BUS_SPI1 80 +#define CLK_EMAC_25M 81 +#define CLK_BUS_EMAC0 82 +#define CLK_BUS_EMAC1 83 +#define CLK_TS 84 +#define CLK_BUS_TS 85 +#define CLK_BUS_THS 86 +#define CLK_SPDIF 87 +#define CLK_BUS_SPDIF 88 +#define CLK_DMIC 89 +#define CLK_BUS_DMIC 90 +#define CLK_AUDIO_CODEC_1X 91 +#define CLK_AUDIO_CODEC_4X 92 +#define CLK_BUS_AUDIO_CODEC 93 +#define CLK_AUDIO_HUB 94 +#define CLK_BUS_AUDIO_HUB 95 +#define CLK_USB_OHCI0 96 +#define CLK_USB_PHY0 97 +#define CLK_USB_OHCI1 98 +#define CLK_USB_PHY1 99 +#define CLK_USB_OHCI2 100 +#define CLK_USB_PHY2 101 +#define CLK_USB_OHCI3 102 +#define CLK_USB_PHY3 103 +#define CLK_BUS_OHCI0 104 +#define CLK_BUS_OHCI1 105 +#define CLK_BUS_OHCI2 106 +#define CLK_BUS_OHCI3 107 +#define CLK_BUS_EHCI0 108 +#define CLK_BUS_EHCI1 109 +#define CLK_BUS_EHCI2 110 +#define CLK_BUS_EHCI3 111 +#define CLK_BUS_OTG 112 +#define CLK_BUS_KEYADC 113 +#define CLK_HDMI 114 +#define CLK_HDMI_SLOW 115 +#define CLK_HDMI_CEC 116 +#define CLK_BUS_HDMI 117 +#define CLK_BUS_TCON_TOP 118 +#define CLK_TCON_TV0 119 +#define CLK_TCON_TV1 120 +#define CLK_BUS_TCON_TV0 121 +#define CLK_BUS_TCON_TV1 122 +#define CLK_TVE0 123 +#define CLK_BUS_TVE_TOP 124 +#define CLK_BUS_TVE0 125 +#define CLK_HDCP 126 +#define CLK_BUS_HDCP 127 + +#endif /* _DT_BINDINGS_CLK_SUN50I_H616_H_ */ diff --git a/include/dt-bindings/clock/xlnx-vcu.h b/include/dt-bindings/clock/xlnx-vcu.h new file mode 100644 index 000000000000..1ed76b9563b6 --- /dev/null +++ b/include/dt-bindings/clock/xlnx-vcu.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2020 Pengutronix, Michael Tretter <kernel@pengutronix.de> + */ + +#ifndef _DT_BINDINGS_CLOCK_XLNX_VCU_H +#define _DT_BINDINGS_CLOCK_XLNX_VCU_H + +#define CLK_XVCU_ENC_CORE 0 +#define CLK_XVCU_ENC_MCU 1 +#define CLK_XVCU_DEC_CORE 2 +#define CLK_XVCU_DEC_MCU 3 +#define CLK_XVCU_NUM_CLOCKS 4 + +#endif /* _DT_BINDINGS_CLOCK_XLNX_VCU_H */ diff --git a/include/dt-bindings/clock/zx296702-clock.h b/include/dt-bindings/clock/zx296702-clock.h deleted file mode 100644 index e04126111aae..000000000000 --- a/include/dt-bindings/clock/zx296702-clock.h +++ /dev/null @@ -1,180 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright 2014 Linaro Ltd. - * Copyright (C) 2014 ZTE Corporation. - */ - -#ifndef __DT_BINDINGS_CLOCK_ZX296702_H -#define __DT_BINDINGS_CLOCK_ZX296702_H - -#define ZX296702_OSC 0 -#define ZX296702_PLL_A9 1 -#define ZX296702_PLL_A9_350M 2 -#define ZX296702_PLL_MAC_1000M 3 -#define ZX296702_PLL_MAC_333M 4 -#define ZX296702_PLL_MM0_1188M 5 -#define ZX296702_PLL_MM0_396M 6 -#define ZX296702_PLL_MM0_198M 7 -#define ZX296702_PLL_MM1_108M 8 -#define ZX296702_PLL_MM1_72M 9 -#define ZX296702_PLL_MM1_54M 10 -#define ZX296702_PLL_LSP_104M 11 -#define ZX296702_PLL_LSP_26M 12 -#define ZX296702_PLL_AUDIO_294M912 13 -#define ZX296702_PLL_DDR_266M 14 -#define ZX296702_CLK_148M5 15 -#define ZX296702_MATRIX_ACLK 16 -#define ZX296702_MAIN_HCLK 17 -#define ZX296702_MAIN_PCLK 18 -#define ZX296702_CLK_500 19 -#define ZX296702_CLK_250 20 -#define ZX296702_CLK_125 21 -#define ZX296702_CLK_74M25 22 -#define ZX296702_A9_WCLK 23 -#define ZX296702_A9_AS1_ACLK_MUX 24 -#define ZX296702_A9_TRACE_CLKIN_MUX 25 -#define ZX296702_A9_AS1_ACLK_DIV 26 -#define ZX296702_CLK_2 27 -#define ZX296702_CLK_27 28 -#define ZX296702_DECPPU_ACLK_MUX 29 -#define ZX296702_PPU_ACLK_MUX 30 -#define ZX296702_MALI400_ACLK_MUX 31 -#define ZX296702_VOU_ACLK_MUX 32 -#define ZX296702_VOU_MAIN_WCLK_MUX 33 -#define ZX296702_VOU_AUX_WCLK_MUX 34 -#define ZX296702_VOU_SCALER_WCLK_MUX 35 -#define ZX296702_R2D_ACLK_MUX 36 -#define ZX296702_R2D_WCLK_MUX 37 -#define ZX296702_CLK_50 38 -#define ZX296702_CLK_25 39 -#define ZX296702_CLK_12 40 -#define ZX296702_CLK_16M384 41 -#define ZX296702_CLK_32K768 42 -#define ZX296702_SEC_WCLK_DIV 43 -#define ZX296702_DDR_WCLK_MUX 44 -#define ZX296702_NAND_WCLK_MUX 45 -#define ZX296702_LSP_26_WCLK_MUX 46 -#define ZX296702_A9_AS0_ACLK 47 -#define ZX296702_A9_AS1_ACLK 48 -#define ZX296702_A9_TRACE_CLKIN 49 -#define ZX296702_DECPPU_AXI_M_ACLK 50 -#define ZX296702_DECPPU_AHB_S_HCLK 51 -#define ZX296702_PPU_AXI_M_ACLK 52 -#define ZX296702_PPU_AHB_S_HCLK 53 -#define ZX296702_VOU_AXI_M_ACLK 54 -#define ZX296702_VOU_APB_PCLK 55 -#define ZX296702_VOU_MAIN_CHANNEL_WCLK 56 -#define ZX296702_VOU_AUX_CHANNEL_WCLK 57 -#define ZX296702_VOU_HDMI_OSCLK_CEC 58 -#define ZX296702_VOU_SCALER_WCLK 59 -#define ZX296702_MALI400_AXI_M_ACLK 60 -#define ZX296702_MALI400_APB_PCLK 61 -#define ZX296702_R2D_WCLK 62 -#define ZX296702_R2D_AXI_M_ACLK 63 -#define ZX296702_R2D_AHB_HCLK 64 -#define ZX296702_DDR3_AXI_S0_ACLK 65 -#define ZX296702_DDR3_APB_PCLK 66 -#define ZX296702_DDR3_WCLK 67 -#define ZX296702_USB20_0_AHB_HCLK 68 -#define ZX296702_USB20_0_EXTREFCLK 69 -#define ZX296702_USB20_1_AHB_HCLK 70 -#define ZX296702_USB20_1_EXTREFCLK 71 -#define ZX296702_USB20_2_AHB_HCLK 72 -#define ZX296702_USB20_2_EXTREFCLK 73 -#define ZX296702_GMAC_AXI_M_ACLK 74 -#define ZX296702_GMAC_APB_PCLK 75 -#define ZX296702_GMAC_125_CLKIN 76 -#define ZX296702_GMAC_RMII_CLKIN 77 -#define ZX296702_GMAC_25M_CLK 78 -#define ZX296702_NANDFLASH_AHB_HCLK 79 -#define ZX296702_NANDFLASH_WCLK 80 -#define ZX296702_LSP0_APB_PCLK 81 -#define ZX296702_LSP0_AHB_HCLK 82 -#define ZX296702_LSP0_26M_WCLK 83 -#define ZX296702_LSP0_104M_WCLK 84 -#define ZX296702_LSP0_16M384_WCLK 85 -#define ZX296702_LSP1_APB_PCLK 86 -#define ZX296702_LSP1_26M_WCLK 87 -#define ZX296702_LSP1_104M_WCLK 88 -#define ZX296702_LSP1_32K_CLK 89 -#define ZX296702_AON_HCLK 90 -#define ZX296702_SYS_CTRL_PCLK 91 -#define ZX296702_DMA_PCLK 92 -#define ZX296702_DMA_ACLK 93 -#define ZX296702_SEC_HCLK 94 -#define ZX296702_AES_WCLK 95 -#define ZX296702_DES_WCLK 96 -#define ZX296702_IRAM_ACLK 97 -#define ZX296702_IROM_ACLK 98 -#define ZX296702_BOOT_CTRL_HCLK 99 -#define ZX296702_EFUSE_CLK_30 100 -#define ZX296702_VOU_MAIN_CHANNEL_DIV 101 -#define ZX296702_VOU_AUX_CHANNEL_DIV 102 -#define ZX296702_VOU_TV_ENC_HD_DIV 103 -#define ZX296702_VOU_TV_ENC_SD_DIV 104 -#define ZX296702_VL0_MUX 105 -#define ZX296702_VL1_MUX 106 -#define ZX296702_VL2_MUX 107 -#define ZX296702_GL0_MUX 108 -#define ZX296702_GL1_MUX 109 -#define ZX296702_GL2_MUX 110 -#define ZX296702_WB_MUX 111 -#define ZX296702_HDMI_MUX 112 -#define ZX296702_VOU_TV_ENC_HD_MUX 113 -#define ZX296702_VOU_TV_ENC_SD_MUX 114 -#define ZX296702_VL0_CLK 115 -#define ZX296702_VL1_CLK 116 -#define ZX296702_VL2_CLK 117 -#define ZX296702_GL0_CLK 118 -#define ZX296702_GL1_CLK 119 -#define ZX296702_GL2_CLK 120 -#define ZX296702_WB_CLK 121 -#define ZX296702_CL_CLK 122 -#define ZX296702_MAIN_MIX_CLK 123 -#define ZX296702_AUX_MIX_CLK 124 -#define ZX296702_HDMI_CLK 125 -#define ZX296702_VOU_TV_ENC_HD_DAC_CLK 126 -#define ZX296702_VOU_TV_ENC_SD_DAC_CLK 127 -#define ZX296702_A9_PERIPHCLK 128 -#define ZX296702_TOPCLK_END 129 - -#define ZX296702_SDMMC1_WCLK_MUX 0 -#define ZX296702_SDMMC1_WCLK_DIV 1 -#define ZX296702_SDMMC1_WCLK 2 -#define ZX296702_SDMMC1_PCLK 3 -#define ZX296702_SPDIF0_WCLK_MUX 4 -#define ZX296702_SPDIF0_WCLK 5 -#define ZX296702_SPDIF0_PCLK 6 -#define ZX296702_SPDIF0_DIV 7 -#define ZX296702_I2S0_WCLK_MUX 8 -#define ZX296702_I2S0_WCLK 9 -#define ZX296702_I2S0_PCLK 10 -#define ZX296702_I2S0_DIV 11 -#define ZX296702_I2S1_WCLK_MUX 12 -#define ZX296702_I2S1_WCLK 13 -#define ZX296702_I2S1_PCLK 14 -#define ZX296702_I2S1_DIV 15 -#define ZX296702_I2S2_WCLK_MUX 16 -#define ZX296702_I2S2_WCLK 17 -#define ZX296702_I2S2_PCLK 18 -#define ZX296702_I2S2_DIV 19 -#define ZX296702_GPIO_CLK 20 -#define ZX296702_LSP0CLK_END 21 - -#define ZX296702_UART0_WCLK_MUX 0 -#define ZX296702_UART0_WCLK 1 -#define ZX296702_UART0_PCLK 2 -#define ZX296702_UART1_WCLK_MUX 3 -#define ZX296702_UART1_WCLK 4 -#define ZX296702_UART1_PCLK 5 -#define ZX296702_SDMMC0_WCLK_MUX 6 -#define ZX296702_SDMMC0_WCLK_DIV 7 -#define ZX296702_SDMMC0_WCLK 8 -#define ZX296702_SDMMC0_PCLK 9 -#define ZX296702_SPDIF1_WCLK_MUX 10 -#define ZX296702_SPDIF1_WCLK 11 -#define ZX296702_SPDIF1_PCLK 12 -#define ZX296702_SPDIF1_DIV 13 -#define ZX296702_LSP1CLK_END 14 - -#endif /* __DT_BINDINGS_CLOCK_ZX296702_H */ diff --git a/include/dt-bindings/reset/sun50i-h6-r-ccu.h b/include/dt-bindings/reset/sun50i-h6-r-ccu.h index 01c84dba49a4..7950e799c76d 100644 --- a/include/dt-bindings/reset/sun50i-h6-r-ccu.h +++ b/include/dt-bindings/reset/sun50i-h6-r-ccu.h @@ -13,5 +13,6 @@ #define RST_R_APB2_I2C 4 #define RST_R_APB1_IR 5 #define RST_R_APB1_W1 6 +#define RST_R_APB2_RSB 7 #endif /* _DT_BINDINGS_RST_SUN50I_H6_R_CCU_H_ */ diff --git a/include/dt-bindings/reset/sun50i-h616-ccu.h b/include/dt-bindings/reset/sun50i-h616-ccu.h new file mode 100644 index 000000000000..cb6285a8d128 --- /dev/null +++ b/include/dt-bindings/reset/sun50i-h616-ccu.h @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2020 Arm Ltd. + */ + +#ifndef _DT_BINDINGS_RESET_SUN50I_H616_H_ +#define _DT_BINDINGS_RESET_SUN50I_H616_H_ + +#define RST_MBUS 0 +#define RST_BUS_DE 1 +#define RST_BUS_DEINTERLACE 2 +#define RST_BUS_GPU 3 +#define RST_BUS_CE 4 +#define RST_BUS_VE 5 +#define RST_BUS_DMA 6 +#define RST_BUS_HSTIMER 7 +#define RST_BUS_DBG 8 +#define RST_BUS_PSI 9 +#define RST_BUS_PWM 10 +#define RST_BUS_IOMMU 11 +#define RST_BUS_DRAM 12 +#define RST_BUS_NAND 13 +#define RST_BUS_MMC0 14 +#define RST_BUS_MMC1 15 +#define RST_BUS_MMC2 16 +#define RST_BUS_UART0 17 +#define RST_BUS_UART1 18 +#define RST_BUS_UART2 19 +#define RST_BUS_UART3 20 +#define RST_BUS_UART4 21 +#define RST_BUS_UART5 22 +#define RST_BUS_I2C0 23 +#define RST_BUS_I2C1 24 +#define RST_BUS_I2C2 25 +#define RST_BUS_I2C3 26 +#define RST_BUS_I2C4 27 +#define RST_BUS_SPI0 28 +#define RST_BUS_SPI1 29 +#define RST_BUS_EMAC0 30 +#define RST_BUS_EMAC1 31 +#define RST_BUS_TS 32 +#define RST_BUS_THS 33 +#define RST_BUS_SPDIF 34 +#define RST_BUS_DMIC 35 +#define RST_BUS_AUDIO_CODEC 36 +#define RST_BUS_AUDIO_HUB 37 +#define RST_USB_PHY0 38 +#define RST_USB_PHY1 39 +#define RST_USB_PHY2 40 +#define RST_USB_PHY3 41 +#define RST_BUS_OHCI0 42 +#define RST_BUS_OHCI1 43 +#define RST_BUS_OHCI2 44 +#define RST_BUS_OHCI3 45 +#define RST_BUS_EHCI0 46 +#define RST_BUS_EHCI1 47 +#define RST_BUS_EHCI2 48 +#define RST_BUS_EHCI3 49 +#define RST_BUS_OTG 50 +#define RST_BUS_HDMI 51 +#define RST_BUS_HDMI_SUB 52 +#define RST_BUS_TCON_TOP 53 +#define RST_BUS_TCON_TV0 54 +#define RST_BUS_TCON_TV1 55 +#define RST_BUS_TVE_TOP 56 +#define RST_BUS_TVE0 57 +#define RST_BUS_HDCP 58 +#define RST_BUS_KEYADC 59 + +#endif /* _DT_BINDINGS_RESET_SUN50I_H616_H_ */ diff --git a/include/linux/clk.h b/include/linux/clk.h index 31ff1bf1b79f..45e698b74178 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -92,7 +92,7 @@ struct clk_bulk_data { #ifdef CONFIG_COMMON_CLK /** - * clk_notifier_register: register a clock rate-change notifier callback + * clk_notifier_register - register a clock rate-change notifier callback * @clk: clock whose rate we are interested in * @nb: notifier block with callback function pointer * @@ -103,7 +103,7 @@ struct clk_bulk_data { int clk_notifier_register(struct clk *clk, struct notifier_block *nb); /** - * clk_notifier_unregister: unregister a clock rate-change notifier callback + * clk_notifier_unregister - unregister a clock rate-change notifier callback * @clk: clock whose rate we are no longer interested in * @nb: notifier block which will be unregistered */ diff --git a/include/linux/clk/imx.h b/include/linux/clk/imx.h new file mode 100644 index 000000000000..75a0d9696552 --- /dev/null +++ b/include/linux/clk/imx.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2020 Freescale Semiconductor, Inc. + * + * Author: Lee Jones <lee.jones@linaro.org> + */ + +#ifndef __LINUX_CLK_IMX_H +#define __LINUX_CLK_IMX_H + +#include <linux/types.h> + +void imx6sl_set_wait_clk(bool enter); + +#endif diff --git a/include/linux/platform_data/clk-u300.h b/include/linux/platform_data/clk-u300.h deleted file mode 100644 index 8429e73911a1..000000000000 --- a/include/linux/platform_data/clk-u300.h +++ /dev/null @@ -1 +0,0 @@ -void __init u300_clk_init(void __iomem *base); |