Pull clk updates from Stephen Boyd: "The diff is dominated by the Allwinner A10/A20 SoCs getting converted to the sunxi-ng framework. Otherwise, the heavy hitters are various drivers for SoCs like AT91, Amlogic, Renesas, and Rockchip. There are some other new clk drivers in here too but overall this is just a bunch of clk drivers for various different pieces of hardware and a collection of non-critical fixes for clk drivers. New Drivers: - Allwinner R40 SoCs - Renesas R-Car Gen3 USB 2.0 clock selector PHY - Atmel AT91 audio PLL - Uniphier PXs3 SoCs - ARC HSDK Board PLLs - AXS10X Board PLLs - STMicroelectronics STM32H743 SoCs Removed Drivers: - Non-compiling mb86s7x support Updates: - Allwinner A10/A20 SoCs converted to sunxi-ng framework - Allwinner H3 CPU clk fixes - Renesas R-Car D3 SoC - Renesas V2H and M3-W modules - Samsung Exynos5420/5422/5800 audio fixes - Rockchip fractional clk approximation fixes - Rockchip rk3126 SoC support within the rk3128 driver - Amlogic gxbb CEC32 and sd_emmc clks - Amlogic meson8b reset controller support - IDT VersaClock 5P49V5925/5P49V6901 support - Qualcomm MSM8996 SMMU clks - Various 'const' applications for struct clk_ops - si5351 PLL reset bugfix - Uniphier audio on LD11/LD20 and ethernet support on LD11/LD20/Pro4/PXs2 - Assorted Tegra clk driver fixes" * tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (120 commits) clk: si5351: fix PLL reset ASoC: atmel-classd: remove aclk clock ASoC: atmel-classd: remove aclk clock from DT binding clk: at91: clk-generated: make gclk determine audio_pll rate clk: at91: clk-generated: create function to find best_diff clk: at91: add audio pll clock drivers dt-bindings: clk: at91: add audio plls to the compatible list clk: at91: clk-generated: remove useless divisor loop clk: mb86s7x: Drop non-building driver clk: ti: check for null return in strrchr to avoid null dereferencing clk: Don't write error code into divider register clk: uniphier: add video input subsystem clock clk: uniphier: add audio system clock clk: stm32h7: Add stm32h743 clock driver clk: gate: expose clk_gate_ops::is_enabled clk: nxp: clk-lpc32xx: rename clk_gate_is_enabled() clk: uniphier: add PXs3 clock data clk: hi6220: change watchdog clock source clk: Kconfig: Name RK805 in Kconfig for COMMON_CLK_RK808 clk: cs2000: Add cs2000_set_saved_rate ...
Unified · Split
| @@ -5,9 +5,11 @@ controllers within the Always-On part of the SoC. · 4 unmodified lines | ||
| 5 | 5 | |
| 6 | 6 | Required Properties: |
| 7 | 7 | |
| 8 | −- compatible: should be "amlogic,gxbb-aoclkc" | |
| 9 | −- reg: physical base address of the clock controller and length of memory | |
| 10 | − mapped region. | |
| 8 | +- compatible: value should be different for each SoC family as : | |
| 9 | + - GXBB (S905) : "amlogic,meson-gxbb-aoclkc" | |
| 10 | + - GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc" | |
| 11 | + - GXM (S912) : "amlogic,meson-gxm-aoclkc" | |
| 12 | + followed by the common "amlogic,meson-gx-aoclkc" | |
| 11 | 13 | |
| 12 | 14 | - #clock-cells: should be 1. |
| 13 | 15 | |
| @@ -23,14 +25,22 @@ to specify the reset which they consume. All available resets are defined as · 9 unmodified lines | ||
| 23 | 25 | preprocessor macros in the dt-bindings/reset/gxbb-aoclkc.h header and can be |
| 24 | 26 | used in device tree sources. |
| 25 | 27 | |
| 28 | +Parent node should have the following properties : | |
| 29 | +- compatible: "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd" | |
| 30 | +- reg: base address and size of the AO system control register space. | |
| 31 | + | |
| 26 | 32 | Example: AO Clock controller node: |
| 27 | 33 | |
| 28 | − clkc_AO: clock-controller@040 { | |
| 29 | − compatible = "amlogic,gxbb-aoclkc"; | |
| 30 | − reg = <0x0 0x040 0x0 0x4>; | |
| 34 | +ao_sysctrl: sys-ctrl@0 { | |
| 35 | + compatible = "amlogic,meson-gx-ao-sysctrl", "syscon", "simple-mfd"; | |
| 36 | + reg = <0x0 0x0 0x0 0x100>; | |
| 37 | + | |
| 38 | + clkc_AO: clock-controller { | |
| 39 | + compatible = "amlogic,meson-gxbb-aoclkc", "amlogic,meson-gx-aoclkc"; | |
| 31 | 40 | #clock-cells = <1>; |
| 32 | 41 | #reset-cells = <1>; |
| 33 | 42 | }; |
| 43 | +}; | |
| 34 | 44 | |
| 35 | 45 | Example: UART controller node that consumes the clock and reset generated |
| 36 | 46 | by the clock controller: |
| @@ -81,6 +81,16 @@ Required properties: · 80 unmodified lines | ||
| 81 | 81 | "atmel,sama5d2-clk-generated": |
| 82 | 82 | at91 generated clock |
| 83 | 83 | |
| 84 | + "atmel,sama5d2-clk-audio-pll-frac": | |
| 85 | + at91 audio fractional pll | |
| 86 | + | |
| 87 | + "atmel,sama5d2-clk-audio-pll-pad": | |
| 88 | + at91 audio pll CLK_AUDIO output pin | |
| 89 | + | |
| 90 | + "atmel,sama5d2-clk-audio-pll-pmc" | |
| 91 | + at91 audio pll output on AUDIOPLLCLK that feeds the PMC | |
| 92 | + and can be used by peripheral clock or generic clock | |
| 93 | + | |
| 84 | 94 | Required properties for SCKC node: |
| 85 | 95 | - reg : defines the IO memory reserved for the SCKC. |
| 86 | 96 | - #size-cells : shall be 0 (reg is used to encode clk id). |
| @@ -1,24 +1,32 @@ | ||
| 1 | −Binding for IDT VersaClock5 programmable i2c clock generator. | |
| 1 | +Binding for IDT VersaClock 5,6 programmable i2c clock generators. | |
| 2 | 2 | |
| 3 | −The IDT VersaClock5 are programmable i2c clock generators providing | |
| 4 | −from 3 to 12 output clocks. | |
| 3 | +The IDT VersaClock 5 and VersaClock 6 are programmable i2c clock | |
| 4 | +generators providing from 3 to 12 output clocks. | |
| 5 | 5 | |
| 6 | 6 | ==I2C device node== |
| 7 | 7 | |
| 8 | 8 | Required properties: |
| 9 | −- compatible: shall be one of "idt,5p49v5923" , "idt,5p49v5933" , | |
| 10 | − "idt,5p49v5935". | |
| 9 | +- compatible: shall be one of | |
| 10 | + "idt,5p49v5923" | |
| 11 | + "idt,5p49v5925" | |
| 12 | + "idt,5p49v5933" | |
| 13 | + "idt,5p49v5935" | |
| 14 | + "idt,5p49v6901" | |
| 11 | 15 | - reg: i2c device address, shall be 0x68 or 0x6a. |
| 12 | 16 | - #clock-cells: from common clock binding; shall be set to 1. |
| 13 | 17 | - clocks: from common clock binding; list of parent clock handles, |
| 14 | − - 5p49v5923: (required) either or both of XTAL or CLKIN | |
| 18 | + - 5p49v5923 and | |
| 19 | + 5p49v5925 and | |
| 20 | + 5p49v6901: (required) either or both of XTAL or CLKIN | |
| 15 | 21 | reference clock. |
| 16 | 22 | - 5p49v5933 and |
| 17 | 23 | - 5p49v5935: (optional) property not present (internal |
| 18 | 24 | Xtal used) or CLKIN reference |
| 19 | 25 | clock. |
| 20 | 26 | - clock-names: from common clock binding; clock input names, can be |
| 21 | − - 5p49v5923: (required) either or both of "xin", "clkin". | |
| 27 | + - 5p49v5923 and | |
| 28 | + 5p49v5925 and | |
| 29 | + 5p49v6901: (required) either or both of "xin", "clkin". | |
| 22 | 30 | - 5p49v5933 and |
| 23 | 31 | - 5p49v5935: (optional) property not present or "clkin". |
| 24 | 32 | |
| @@ -37,6 +45,7 @@ clock specifier, the following mapping applies: · 12 unmodified lines | ||
| 37 | 45 | 1 -- OUT1 |
| 38 | 46 | 2 -- OUT4 |
| 39 | 47 | |
| 48 | +5P49V5925 and | |
| 40 | 49 | 5P49V5935: |
| 41 | 50 | 0 -- OUT0_SEL_I2CB |
| 42 | 51 | 1 -- OUT1 |
| @@ -44,6 +53,13 @@ clock specifier, the following mapping applies: · 1 unmodified line | ||
| 44 | 53 | 3 -- OUT3 |
| 45 | 54 | 4 -- OUT4 |
| 46 | 55 | |
| 56 | +5P49V6901: | |
| 57 | + 0 -- OUT0_SEL_I2CB | |
| 58 | + 1 -- OUT1 | |
| 59 | + 2 -- OUT2 | |
| 60 | + 3 -- OUT3 | |
| 61 | + 4 -- OUT4 | |
| 62 | + | |
| 47 | 63 | ==Example== |
| 48 | 64 | |
| 49 | 65 | /* 25MHz reference crystal */ |
| @@ -22,6 +22,7 @@ Required Properties: · 21 unmodified lines | ||
| 22 | 22 | - "renesas,r8a7794-cpg-mssr" for the r8a7794 SoC (R-Car E2) |
| 23 | 23 | - "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC (R-Car H3) |
| 24 | 24 | - "renesas,r8a7796-cpg-mssr" for the r8a7796 SoC (R-Car M3-W) |
| 25 | + - "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3) | |
| 25 | 26 | |
| 26 | 27 | - reg: Base address and length of the memory resource used by the CPG/MSSR |
| 27 | 28 | block |
| @@ -30,7 +31,7 @@ Required Properties: · 2 unmodified lines | ||
| 30 | 31 | clock-names |
| 31 | 32 | - clock-names: List of external parent clock names. Valid names are: |
| 32 | 33 | - "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794, |
| 33 | − r8a7795, r8a7796) | |
| 34 | + r8a7795, r8a7796, r8a77995) | |
| 34 | 35 | - "extalr" (r8a7795, r8a7796) |
| 35 | 36 | - "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794) |
| 36 | 37 | |
| @@ -0,0 +1,55 @@ | ||
| 1 | +* Renesas R-Car USB 2.0 clock selector | |
| 2 | + | |
| 3 | +This file provides information on what the device node for the R-Car USB 2.0 | |
| 4 | +clock selector. | |
| 5 | + | |
| 6 | +If you connect an external clock to the USB_EXTAL pin only, you should set | |
| 7 | +the clock rate to "usb_extal" node only. | |
| 8 | +If you connect an oscillator to both the USB_XTAL and USB_EXTAL, this module | |
| 9 | +is not needed because this is default setting. (Of course, you can set the | |
| 10 | +clock rates to both "usb_extal" and "usb_xtal" nodes. | |
| 11 | + | |
| 12 | +Case 1: An external clock connects to R-Car SoC | |
| 13 | + +----------+ +--- R-Car ---------------------+ | |
| 14 | + |External |---|USB_EXTAL ---> all usb channels| | |
| 15 | + |clock | |USB_XTAL | | |
| 16 | + +----------+ +-------------------------------+ | |
| 17 | +In this case, we need this driver with "usb_extal" clock. | |
| 18 | + | |
| 19 | +Case 2: An oscillator connects to R-Car SoC | |
| 20 | + +----------+ +--- R-Car ---------------------+ | |
| 21 | + |Oscillator|---|USB_EXTAL -+-> all usb channels| | |
| 22 | + | |---|USB_XTAL --+ | | |
| 23 | + +----------+ +-------------------------------+ | |
| 24 | +In this case, we don't need this selector. | |
| 25 | + | |
| 26 | +Required properties: | |
| 27 | +- compatible: "renesas,r8a7795-rcar-usb2-clock-sel" if the device is a part of | |
| 28 | + an R8A7795 SoC. | |
| 29 | + "renesas,r8a7796-rcar-usb2-clock-sel" if the device if a part of | |
| 30 | + an R8A7796 SoC. | |
| 31 | + "renesas,rcar-gen3-usb2-clock-sel" for a generic R-Car Gen3 | |
| 32 | + compatible device. | |
| 33 | + | |
| 34 | + When compatible with the generic version, nodes must list the | |
| 35 | + SoC-specific version corresponding to the platform first | |
| 36 | + followed by the generic version. | |
| 37 | + | |
| 38 | +- reg: offset and length of the USB 2.0 clock selector register block. | |
| 39 | +- clocks: A list of phandles and specifier pairs. | |
| 40 | +- clock-names: Name of the clocks. | |
| 41 | + - The functional clock must be "ehci_ohci" | |
| 42 | + - The USB_EXTAL clock pin must be "usb_extal" | |
| 43 | + - The USB_XTAL clock pin must be "usb_xtal" | |
| 44 | +- #clock-cells: Must be 0 | |
| 45 | + | |
| 46 | +Example (R-Car H3): | |
| 47 | + | |
| 48 | + usb2_clksel: clock-controller@e6590630 { | |
| 49 | + compatible = "renesas,r8a77950-rcar-usb2-clock-sel", | |
| 50 | + "renesas,rcar-gen3-usb2-clock-sel"; | |
| 51 | + reg = <0 0xe6590630 0 0x02>; | |
| 52 | + clocks = <&cpg CPG_MOD 703>, <&usb_extal>, <&usb_xtal>; | |
| 53 | + clock-names = "ehci_ohci", "usb_extal", "usb_xtal"; | |
| 54 | + #clock-cells = <0>; | |
| 55 | + }; | |
| @@ -1,12 +1,14 @@ | ||
| 1 | −* Rockchip RK3128 Clock and Reset Unit | |
| 1 | +* Rockchip RK3126/RK3128 Clock and Reset Unit | |
| 2 | 2 | |
| 3 | −The RK3128 clock controller generates and supplies clock to various | |
| 3 | +The RK3126/RK3128 clock controller generates and supplies clock to various | |
| 4 | 4 | controllers within the SoC and also implements a reset controller for SoC |
| 5 | 5 | peripherals. |
| 6 | 6 | |
| 7 | 7 | Required Properties: |
| 8 | 8 | |
| 9 | −- compatible: should be "rockchip,rk3128-cru" | |
| 9 | +- compatible: should be "rockchip,rk3126-cru" or "rockchip,rk3128-cru" | |
| 10 | + "rockchip,rk3126-cru" - controller compatible with RK3126 SoC. | |
| 11 | + "rockchip,rk3128-cru" - controller compatible with RK3128 SoC. | |
| 10 | 12 | - reg: physical base address of the controller and length of memory mapped |
| 11 | 13 | region. |
| 12 | 14 | - #clock-cells: should be 1. |
| @@ -0,0 +1,28 @@ | ||
| 1 | +Binding for the HSDK Generic PLL clock | |
| 2 | + | |
| 3 | +This binding uses the common clock binding[1]. | |
| 4 | + | |
| 5 | +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt | |
| 6 | + | |
| 7 | +Required properties: | |
| 8 | +- compatible: should be "snps,hsdk-<name>-pll-clock" | |
| 9 | + "snps,hsdk-core-pll-clock" | |
| 10 | + "snps,hsdk-gp-pll-clock" | |
| 11 | + "snps,hsdk-hdmi-pll-clock" | |
| 12 | +- reg : should contain base register location and length. | |
| 13 | +- clocks: shall be the input parent clock phandle for the PLL. | |
| 14 | +- #clock-cells: from common clock binding; Should always be set to 0. | |
| 15 | + | |
| 16 | +Example: | |
| 17 | + input_clk: input-clk { | |
| 18 | + clock-frequency = <33333333>; | |
| 19 | + compatible = "fixed-clock"; | |
| 20 | + #clock-cells = <0>; | |
| 21 | + }; | |
| 22 | + | |
| 23 | + cpu_clk: cpu-clk@0 { | |
| 24 | + compatible = "snps,hsdk-core-pll-clock"; | |
| 25 | + reg = <0x00 0x10>; | |
| 26 | + #clock-cells = <0>; | |
| 27 | + clocks = <&input_clk>; | |
| 28 | + }; | |
| @@ -0,0 +1,28 @@ | ||
| 1 | +Binding for the AXS10X Generic PLL clock | |
| 2 | + | |
| 3 | +This binding uses the common clock binding[1]. | |
| 4 | + | |
| 5 | +[1] Documentation/devicetree/bindings/clock/clock-bindings.txt | |
| 6 | + | |
| 7 | +Required properties: | |
| 8 | +- compatible: should be "snps,axs10x-<name>-pll-clock" | |
| 9 | + "snps,axs10x-arc-pll-clock" | |
| 10 | + "snps,axs10x-pgu-pll-clock" | |
| 11 | +- reg: should always contain 2 pairs address - length: first for PLL config | |
| 12 | +registers and second for corresponding LOCK CGU register. | |
| 13 | +- clocks: shall be the input parent clock phandle for the PLL. | |
| 14 | +- #clock-cells: from common clock binding; Should always be set to 0. | |
| 15 | + | |
| 16 | +Example: | |
| 17 | + input-clk: input-clk { | |
| 18 | + clock-frequency = <33333333>; | |
| 19 | + compatible = "fixed-clock"; | |
| 20 | + #clock-cells = <0>; | |
| 21 | + }; | |
| 22 | + | |
| 23 | + core-clk: core-clk@80 { | |
| 24 | + compatible = "snps,axs10x-arc-pll-clock"; | |
| 25 | + reg = <0x80 0x10>, <0x100 0x10>; | |
| 26 | + #clock-cells = <0>; | |
| 27 | + clocks = <&input-clk>; | |
| 28 | + }; | |
| @@ -0,0 +1,71 @@ | ||
| 1 | +STMicroelectronics STM32H7 Reset and Clock Controller | |
| 2 | +===================================================== | |
| 3 | + | |
| 4 | +The RCC IP is both a reset and a clock controller. | |
| 5 | + | |
| 6 | +Please refer to clock-bindings.txt for common clock controller binding usage. | |
| 7 | +Please also refer to reset.txt for common reset controller binding usage. | |
| 8 | + | |
| 9 | +Required properties: | |
| 10 | +- compatible: Should be: | |
| 11 | + "st,stm32h743-rcc" | |
| 12 | + | |
| 13 | +- reg: should be register base and length as documented in the | |
| 14 | + datasheet | |
| 15 | + | |
| 16 | +- #reset-cells: 1, see below | |
| 17 | + | |
| 18 | +- #clock-cells : from common clock binding; shall be set to 1 | |
| 19 | + | |
| 20 | +- clocks: External oscillator clock phandle | |
| 21 | + - high speed external clock signal (HSE) | |
| 22 | + - low speed external clock signal (LSE) | |
| 23 | + - external I2S clock (I2S_CKIN) | |
| 24 | + | |
| 25 | +Optional properties: | |
| 26 | +- st,syscfg: phandle for pwrcfg, mandatory to disable/enable backup domain | |
| 27 | + write protection (RTC clock). | |
| 28 | + | |
| 29 | +Example: | |
| 30 | + | |
| 31 | + rcc: reset-clock-controller@58024400 { | |
| 32 | + compatible = "st,stm32h743-rcc", "st,stm32-rcc"; | |
| 33 | + reg = <0x58024400 0x400>; | |
| 34 | + #reset-cells = <1>; | |
| 35 | + #clock-cells = <2>; | |
| 36 | + clocks = <&clk_hse>, <&clk_lse>, <&clk_i2s_ckin>; | |
| 37 | + | |
| 38 | + st,syscfg = <&pwrcfg>; | |
| 39 | +}; | |
| 40 | + | |
| 41 | +The peripheral clock consumer should specify the desired clock by | |
| 42 | +having the clock ID in its "clocks" phandle cell. | |
| 43 | + | |
| 44 | +Example: | |
| 45 | + | |
| 46 | + timer5: timer@40000c00 { | |
| 47 | + compatible = "st,stm32-timer"; | |
| 48 | + reg = <0x40000c00 0x400>; | |
| 49 | + interrupts = <50>; | |
| 50 | + clocks = <&rcc TIM5_CK>; | |
| 51 | + }; | |
| 52 | + | |
| 53 | +Specifying softreset control of devices | |
| 54 | +======================================= | |
| 55 | + | |
| 56 | +Device nodes should specify the reset channel required in their "resets" | |
| 57 | +property, containing a phandle to the reset device node and an index specifying | |
| 58 | +which channel to use. | |
| 59 | +The index is the bit number within the RCC registers bank, starting from RCC | |
| 60 | +base address. | |
| 61 | +It is calculated as: index = register_offset / 4 * 32 + bit_offset. | |
| 62 | +Where bit_offset is the bit offset within the register. | |
| 63 | + | |
| 64 | +For example, for CRC reset: | |
| 65 | + crc = AHB4RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x88 / 4 * 32 + 19 = 1107 | |
| 66 | + | |
| 67 | +Example: | |
| 68 | + | |
| 69 | + timer2 { | |
| 70 | + resets = <&rcc STM32H7_APB1L_RESET(TIM2)>; | |
| 71 | + }; | |
| @@ -3,18 +3,24 @@ Allwinner Clock Control Unit Binding · 2 unmodified lines | ||
| 3 | 3 | |
| 4 | 4 | Required properties : |
| 5 | 5 | - compatible: must contain one of the following compatibles: |
| 6 | + - "allwinner,sun4i-a10-ccu" | |
| 7 | + - "allwinner,sun5i-a10s-ccu" | |
| 8 | + - "allwinner,sun5i-a13-ccu" | |
| 6 | 9 | - "allwinner,sun6i-a31-ccu" |
| 10 | + - "allwinner,sun7i-a20-ccu" | |
| 7 | 11 | - "allwinner,sun8i-a23-ccu" |
| 8 | 12 | - "allwinner,sun8i-a33-ccu" |
| 9 | 13 | - "allwinner,sun8i-a83t-ccu" |
| 10 | 14 | - "allwinner,sun8i-a83t-r-ccu" |
| 11 | 15 | - "allwinner,sun8i-h3-ccu" |
| 12 | 16 | - "allwinner,sun8i-h3-r-ccu" |
| 17 | ++ - "allwinner,sun8i-r40-ccu" | |
| 13 | 18 | - "allwinner,sun8i-v3s-ccu" |
| 14 | 19 | - "allwinner,sun9i-a80-ccu" |
| 15 | 20 | - "allwinner,sun50i-a64-ccu" |
| 16 | 21 | - "allwinner,sun50i-a64-r-ccu" |
| 17 | 22 | - "allwinner,sun50i-h5-ccu" |
| 23 | + - "nextthing,gr8-ccu" | |
| 18 | 24 | |
| 19 | 25 | - reg: Must contain the registers base address and length |
| 20 | 26 | - clocks: phandle to the oscillators feeding the CCU. Two are needed: |
| @@ -6,7 +6,6 @@ System clock · 5 unmodified lines | ||
| 6 | 6 | |
| 7 | 7 | Required properties: |
| 8 | 8 | - compatible: should be one of the following: |
| 9 | − "socionext,uniphier-sld3-clock" - for sLD3 SoC. | |
| 10 | 9 | "socionext,uniphier-ld4-clock" - for LD4 SoC. |
| 11 | 10 | "socionext,uniphier-pro4-clock" - for Pro4 SoC. |
| 12 | 11 | "socionext,uniphier-sld8-clock" - for sLD8 SoC. |
| @@ -14,6 +13,7 @@ Required properties: · 1 unmodified line | ||
| 14 | 13 | "socionext,uniphier-pxs2-clock" - for PXs2/LD6b SoC. |
| 15 | 14 | "socionext,uniphier-ld11-clock" - for LD11 SoC. |
| 16 | 15 | "socionext,uniphier-ld20-clock" - for LD20 SoC. |
| 16 | + "socionext,uniphier-pxs3-clock" - for PXs3 SoC | |
| 17 | 17 | - #clock-cells: should be 1. |
| 18 | 18 | |
| 19 | 19 | Example: |
| @@ -48,7 +48,6 @@ Media I/O (MIO) clock, SD clock · 28 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | Required properties: |
| 50 | 50 | - compatible: should be one of the following: |
| 51 | − "socionext,uniphier-sld3-mio-clock" - for sLD3 SoC. | |
| 52 | 51 | "socionext,uniphier-ld4-mio-clock" - for LD4 SoC. |
| 53 | 52 | "socionext,uniphier-pro4-mio-clock" - for Pro4 SoC. |
| 54 | 53 | "socionext,uniphier-sld8-mio-clock" - for sLD8 SoC. |
| @@ -56,6 +55,7 @@ Required properties: · 1 unmodified line | ||
| 56 | 55 | "socionext,uniphier-pxs2-sd-clock" - for PXs2/LD6b SoC. |
| 57 | 56 | "socionext,uniphier-ld11-mio-clock" - for LD11 SoC. |
| 58 | 57 | "socionext,uniphier-ld20-sd-clock" - for LD20 SoC. |
| 58 | + "socionext,uniphier-pxs3-sd-clock" - for PXs3 SoC | |
| 59 | 59 | - #clock-cells: should be 1. |
| 60 | 60 | |
| 61 | 61 | Example: |
| @@ -82,11 +82,9 @@ Provided clocks: · 20 unmodified lines | ||
| 82 | 82 | 8: USB2 ch0 host |
| 83 | 83 | 9: USB2 ch1 host |
| 84 | 84 | 10: USB2 ch2 host |
| 85 | −11: USB2 ch3 host | |
| 86 | 85 | 12: USB2 ch0 PHY |
| 87 | 86 | 13: USB2 ch1 PHY |
| 88 | 87 | 14: USB2 ch2 PHY |
| 89 | −15: USB2 ch3 PHY | |
| 90 | 88 | |
| 91 | 89 | |
| 92 | 90 | Peripheral clock |
| @@ -94,7 +92,6 @@ Peripheral clock · 1 unmodified line | ||
| 94 | 92 | |
| 95 | 93 | Required properties: |
| 96 | 94 | - compatible: should be one of the following: |
| 97 | − "socionext,uniphier-sld3-peri-clock" - for sLD3 SoC. | |
| 98 | 95 | "socionext,uniphier-ld4-peri-clock" - for LD4 SoC. |
| 99 | 96 | "socionext,uniphier-pro4-peri-clock" - for Pro4 SoC. |
| 100 | 97 | "socionext,uniphier-sld8-peri-clock" - for sLD8 SoC. |
| @@ -102,6 +99,7 @@ Required properties: · 1 unmodified line | ||
| 102 | 99 | "socionext,uniphier-pxs2-peri-clock" - for PXs2/LD6b SoC. |
| 103 | 100 | "socionext,uniphier-ld11-peri-clock" - for LD11 SoC. |
| 104 | 101 | "socionext,uniphier-ld20-peri-clock" - for LD20 SoC. |
| 102 | + "socionext,uniphier-pxs3-peri-clock" - for PXs3 SoC | |
| 105 | 103 | - #clock-cells: should be 1. |
| 106 | 104 | |
| 107 | 105 | Example: |
| @@ -13,13 +13,11 @@ Required properties: · 12 unmodified lines | ||
| 13 | 13 | Must be "tx". |
| 14 | 14 | - clock-names |
| 15 | 15 | Tuple listing input clock names. |
| 16 | − Required elements: "pclk", "gclk" and "aclk". | |
| 16 | + Required elements: "pclk" and "gclk". | |
| 17 | 17 | - clocks |
| 18 | 18 | Please refer to clock-bindings.txt. |
| 19 | 19 | - assigned-clocks |
| 20 | 20 | Should be <&classd_gclk>. |
| 21 | −- assigned-clock-parents | |
| 22 | − Should be <&audio_pll_pmc>. | |
| 23 | 21 | |
| 24 | 22 | Optional properties: |
| 25 | 23 | - pinctrl-names, pinctrl-0 |
| @@ -45,10 +43,9 @@ classd: classd@fc048000 { · 19 unmodified lines | ||
| 45 | 43 | (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) |
| 46 | 44 | | AT91_XDMAC_DT_PERID(47))>; |
| 47 | 45 | dma-names = "tx"; |
| 48 | − clocks = <&classd_clk>, <&classd_gclk>, <&audio_pll_pmc>; | |
| 49 | − clock-names = "pclk", "gclk", "aclk"; | |
| 46 | + clocks = <&classd_clk>, <&classd_gclk>; | |
| 47 | + clock-names = "pclk", "gclk"; | |
| 50 | 48 | assigned-clocks = <&classd_gclk>; |
| 51 | − assigned-clock-parents = <&audio_pll_pmc>; | |
| 52 | 49 | |
| 53 | 50 | pinctrl-names = "default"; |
| 54 | 51 | pinctrl-0 = <&pinctrl_classd_default>; |
| @@ -12842,6 +12842,18 @@ F: drivers/clocksource/arc_timer.c · 12841 unmodified lines | ||
| 12842 | 12842 | F: drivers/tty/serial/arc_uart.c |
| 12843 | 12843 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc.git |
| 12844 | 12844 | |
| 12845 | +SYNOPSYS ARC HSDK SDP pll clock driver | |
| 12846 | +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | |
| 12847 | +S: Supported | |
| 12848 | +F: drivers/clk/clk-hsdk-pll.c | |
| 12849 | +F: Documentation/devicetree/bindings/clock/snps,hsdk-pll-clock.txt | |
| 12850 | + | |
| 12851 | +SYNOPSYS ARC SDP clock driver | |
| 12852 | +M: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> | |
| 12853 | +S: Supported | |
| 12854 | +F: drivers/clk/axs10x/* | |
| 12855 | +F: Documentation/devicetree/bindings/clock/snps,pll-clock.txt | |
| 12856 | + | |
| 12845 | 12857 | SYNOPSYS ARC SDP platform support |
| 12846 | 12858 | M: Alexey Brodkin <abrodkin@synopsys.com> |
| 12847 | 12859 | S: Supported |
| @@ -26,6 +26,7 @@ config SOC_SAMA5D2 · 25 unmodified lines | ||
| 26 | 26 | select HAVE_AT91_USB_CLK |
| 27 | 27 | select HAVE_AT91_H32MX |
| 28 | 28 | select HAVE_AT91_GENERATED_CLK |
| 29 | + select HAVE_AT91_AUDIO_PLL | |
| 29 | 30 | select PINCTRL_AT91PIO4 |
| 30 | 31 | help |
| 31 | 32 | Select this if ou are using one of Atmel's SAMA5D2 family SoC. |
| @@ -125,6 +126,9 @@ config HAVE_AT91_H32MX · 93 unmodified lines | ||
| 125 | 126 | config HAVE_AT91_GENERATED_CLK |
| 126 | 127 | bool |
| 127 | 128 | |
| 129 | +config HAVE_AT91_AUDIO_PLL | |
| 130 | + bool | |
| 131 | + | |
| 128 | 132 | config SOC_SAM_V4_V5 |
| 129 | 133 | bool |
| 130 | 134 | |
| @@ -31,6 +31,13 @@ config COMMON_CLK_WM831X · 30 unmodified lines | ||
| 31 | 31 | |
| 32 | 32 | source "drivers/clk/versatile/Kconfig" |
| 33 | 33 | |
| 34 | +config CLK_HSDK | |
| 35 | + bool "PLL Driver for HSDK platform" | |
| 36 | + depends on OF || COMPILE_TEST | |
| 37 | + ---help--- | |
| 38 | + This driver supports the HSDK core, system, ddr, tunnel and hdmi PLLs | |
| 39 | + control. | |
| 40 | + | |
| 34 | 41 | config COMMON_CLK_MAX77686 |
| 35 | 42 | tristate "Clock driver for Maxim 77620/77686/77802 MFD" |
| 36 | 43 | depends on MFD_MAX77686 || MFD_MAX77620 || COMPILE_TEST |
| @@ -39,10 +46,10 @@ config COMMON_CLK_MAX77686 · 2 unmodified lines | ||
| 39 | 46 | clock. |
| 40 | 47 | |
| 41 | 48 | config COMMON_CLK_RK808 |
| 42 | − tristate "Clock driver for RK808/RK818" | |
| 49 | + tristate "Clock driver for RK805/RK808/RK818" | |
| 43 | 50 | depends on MFD_RK808 |
| 44 | 51 | ---help--- |
| 45 | − This driver supports RK808 and RK818 crystal oscillator clock. These | |
| 52 | + This driver supports RK805, RK808 and RK818 crystal oscillator clock. These | |
| 46 | 53 | multi-function devices have two fixed-rate oscillators, |
| 47 | 54 | clocked at 32KHz each. Clkout1 is always on, Clkout2 can off |
| 48 | 55 | by control register. |
| @@ -210,14 +217,14 @@ config COMMON_CLK_OXNAS · 161 unmodified lines | ||
| 210 | 217 | Support for the OXNAS SoC Family clocks. |
| 211 | 218 | |
| 212 | 219 | config COMMON_CLK_VC5 |
| 213 | − tristate "Clock driver for IDT VersaClock5 devices" | |
| 220 | + tristate "Clock driver for IDT VersaClock 5,6 devices" | |
| 214 | 221 | depends on I2C |
| 215 | 222 | depends on OF |
| 216 | 223 | select REGMAP_I2C |
| 217 | 224 | help |
| 218 | 225 | ---help--- |
| 219 | − This driver supports the IDT VersaClock5 programmable clock | |
| 220 | − generator. | |
| 226 | + This driver supports the IDT VersaClock 5 and VersaClock 6 | |
| 227 | + programmable clock generators. | |
| 221 | 228 | |
| 222 | 229 | source "drivers/clk/bcm/Kconfig" |
| 223 | 230 | source "drivers/clk/hisilicon/Kconfig" |
| @@ -27,8 +27,8 @@ obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o · 26 unmodified lines | ||
| 27 | 27 | obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o |
| 28 | 28 | obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o |
| 29 | 29 | obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o |
| 30 | +obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o | |
| 30 | 31 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
| 31 | −obj-$(CONFIG_ARCH_MB86S7X) += clk-mb86s7x.o | |
| 32 | 32 | obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o |
| 33 | 33 | obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o |
| 34 | 34 | obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o |
| @@ -44,6 +44,7 @@ obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o · 9 unmodified lines | ||
| 44 | 44 | obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o |
| 45 | 45 | obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o |
| 46 | 46 | obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o |
| 47 | +obj-$(CONFIG_ARCH_STM32) += clk-stm32h7.o | |
| 47 | 48 | obj-$(CONFIG_ARCH_TANGO) += clk-tango4.o |
| 48 | 49 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o |
| 49 | 50 | obj-$(CONFIG_ARCH_U300) += clk-u300.o |
| @@ -6,6 +6,7 @@ obj-y += pmc.o sckc.o · 5 unmodified lines | ||
| 6 | 6 | obj-y += clk-slow.o clk-main.o clk-pll.o clk-plldiv.o clk-master.o |
| 7 | 7 | obj-y += clk-system.o clk-peripheral.o clk-programmable.o |
| 8 | 8 | |
| 9 | +obj-$(CONFIG_HAVE_AT91_AUDIO_PLL) += clk-audio-pll.o | |
| 9 | 10 | obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o |
| 10 | 11 | obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o |
| 11 | 12 | obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o |
| @@ -0,0 +1,536 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2016 Atmel Corporation, | |
| 3 | + * Songjun Wu <songjun.wu@atmel.com>, | |
| 4 | + * Nicolas Ferre <nicolas.ferre@atmel.com> | |
| 5 | + * Copyright (C) 2017 Free Electrons, | |
| 6 | + * Quentin Schulz <quentin.schulz@free-electrons.com> | |
| 7 | + * | |
| 8 | + * This program is free software; you can redistribute it and/or modify | |
| 9 | + * it under the terms of the GNU General Public License as published by | |
| 10 | + * the Free Software Foundation; either version 2 of the License, or | |
| 11 | + * (at your option) any later version. | |
| 12 | + * | |
| 13 | + * The Sama5d2 SoC has two audio PLLs (PMC and PAD) that shares the same parent | |
| 14 | + * (FRAC). FRAC can output between 620 and 700MHz and only multiply the rate of | |
| 15 | + * its own parent. PMC and PAD can then divide the FRAC rate to best match the | |
| 16 | + * asked rate. | |
| 17 | + * | |
| 18 | + * Traits of FRAC clock: | |
| 19 | + * enable - clk_enable writes nd, fracr parameters and enables PLL | |
| 20 | + * rate - rate is adjustable. | |
| 21 | + * clk->rate = parent->rate * ((nd + 1) + (fracr / 2^22)) | |
| 22 | + * parent - fixed parent. No clk_set_parent support | |
| 23 | + * | |
| 24 | + * Traits of PMC clock: | |
| 25 | + * enable - clk_enable writes qdpmc, and enables PMC output | |
| 26 | + * rate - rate is adjustable. | |
| 27 | + * clk->rate = parent->rate / (qdpmc + 1) | |
| 28 | + * parent - fixed parent. No clk_set_parent support | |
| 29 | + * | |
| 30 | + * Traits of PAD clock: | |
| 31 | + * enable - clk_enable writes divisors and enables PAD output | |
| 32 | + * rate - rate is adjustable. | |
| 33 | + * clk->rate = parent->rate / (qdaudio * div)) | |
| 34 | + * parent - fixed parent. No clk_set_parent support | |
| 35 | + * | |
| 36 | + */ | |
| 37 | + | |
| 38 | +#include <linux/clk.h> | |
| 39 | +#include <linux/clk-provider.h> | |
| 40 | +#include <linux/clk/at91_pmc.h> | |
| 41 | +#include <linux/of.h> | |
| 42 | +#include <linux/mfd/syscon.h> | |
| 43 | +#include <linux/regmap.h> | |
| 44 | +#include <linux/slab.h> | |
| 45 | + | |
| 46 | +#define AUDIO_PLL_DIV_FRAC BIT(22) | |
| 47 | +#define AUDIO_PLL_ND_MAX (AT91_PMC_AUDIO_PLL_ND_MASK >> \ | |
| 48 | + AT91_PMC_AUDIO_PLL_ND_OFFSET) | |
| 49 | + | |
| 50 | +#define AUDIO_PLL_QDPAD(qd, div) ((AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(qd) & \ | |
| 51 | + AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK) | \ | |
| 52 | + (AT91_PMC_AUDIO_PLL_QDPAD_DIV(div) & \ | |
| 53 | + AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK)) | |
| 54 | + | |
| 55 | +#define AUDIO_PLL_QDPMC_MAX (AT91_PMC_AUDIO_PLL_QDPMC_MASK >> \ | |
| 56 | + AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | |
| 57 | + | |
| 58 | +#define AUDIO_PLL_FOUT_MIN 620000000UL | |
| 59 | +#define AUDIO_PLL_FOUT_MAX 700000000UL | |
| 60 | + | |
| 61 | +struct clk_audio_frac { | |
| 62 | + struct clk_hw hw; | |
| 63 | + struct regmap *regmap; | |
| 64 | + u32 fracr; | |
| 65 | + u8 nd; | |
| 66 | +}; | |
| 67 | + | |
| 68 | +struct clk_audio_pad { | |
| 69 | + struct clk_hw hw; | |
| 70 | + struct regmap *regmap; | |
| 71 | + u8 qdaudio; | |
| 72 | + u8 div; | |
| 73 | +}; | |
| 74 | + | |
| 75 | +struct clk_audio_pmc { | |
| 76 | + struct clk_hw hw; | |
| 77 | + struct regmap *regmap; | |
| 78 | + u8 qdpmc; | |
| 79 | +}; | |
| 80 | + | |
| 81 | +#define to_clk_audio_frac(hw) container_of(hw, struct clk_audio_frac, hw) | |
| 82 | +#define to_clk_audio_pad(hw) container_of(hw, struct clk_audio_pad, hw) | |
| 83 | +#define to_clk_audio_pmc(hw) container_of(hw, struct clk_audio_pmc, hw) | |
| 84 | + | |
| 85 | +static int clk_audio_pll_frac_enable(struct clk_hw *hw) | |
| 86 | +{ | |
| 87 | + struct clk_audio_frac *frac = to_clk_audio_frac(hw); | |
| 88 | + | |
| 89 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | |
| 90 | + AT91_PMC_AUDIO_PLL_RESETN, 0); | |
| 91 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | |
| 92 | + AT91_PMC_AUDIO_PLL_RESETN, | |
| 93 | + AT91_PMC_AUDIO_PLL_RESETN); | |
| 94 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL1, | |
| 95 | + AT91_PMC_AUDIO_PLL_FRACR_MASK, frac->fracr); | |
| 96 | + | |
| 97 | + /* | |
| 98 | + * reset and enable have to be done in 2 separated writes | |
| 99 | + * for AT91_PMC_AUDIO_PLL0 | |
| 100 | + */ | |
| 101 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | |
| 102 | + AT91_PMC_AUDIO_PLL_PLLEN | | |
| 103 | + AT91_PMC_AUDIO_PLL_ND_MASK, | |
| 104 | + AT91_PMC_AUDIO_PLL_PLLEN | | |
| 105 | + AT91_PMC_AUDIO_PLL_ND(frac->nd)); | |
| 106 | + | |
| 107 | + return 0; | |
| 108 | +} | |
| 109 | + | |
| 110 | +static int clk_audio_pll_pad_enable(struct clk_hw *hw) | |
| 111 | +{ | |
| 112 | + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | |
| 113 | + | |
| 114 | + regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL1, | |
| 115 | + AT91_PMC_AUDIO_PLL_QDPAD_MASK, | |
| 116 | + AUDIO_PLL_QDPAD(apad_ck->qdaudio, apad_ck->div)); | |
| 117 | + regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, | |
| 118 | + AT91_PMC_AUDIO_PLL_PADEN, AT91_PMC_AUDIO_PLL_PADEN); | |
| 119 | + | |
| 120 | + return 0; | |
| 121 | +} | |
| 122 | + | |
| 123 | +static int clk_audio_pll_pmc_enable(struct clk_hw *hw) | |
| 124 | +{ | |
| 125 | + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | |
| 126 | + | |
| 127 | + regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, | |
| 128 | + AT91_PMC_AUDIO_PLL_PMCEN | | |
| 129 | + AT91_PMC_AUDIO_PLL_QDPMC_MASK, | |
| 130 | + AT91_PMC_AUDIO_PLL_PMCEN | | |
| 131 | + AT91_PMC_AUDIO_PLL_QDPMC(apmc_ck->qdpmc)); | |
| 132 | + return 0; | |
| 133 | +} | |
| 134 | + | |
| 135 | +static void clk_audio_pll_frac_disable(struct clk_hw *hw) | |
| 136 | +{ | |
| 137 | + struct clk_audio_frac *frac = to_clk_audio_frac(hw); | |
| 138 | + | |
| 139 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | |
| 140 | + AT91_PMC_AUDIO_PLL_PLLEN, 0); | |
| 141 | + /* do it in 2 separated writes */ | |
| 142 | + regmap_update_bits(frac->regmap, AT91_PMC_AUDIO_PLL0, | |
| 143 | + AT91_PMC_AUDIO_PLL_RESETN, 0); | |
| 144 | +} | |
| 145 | + | |
| 146 | +static void clk_audio_pll_pad_disable(struct clk_hw *hw) | |
| 147 | +{ | |
| 148 | + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | |
| 149 | + | |
| 150 | + regmap_update_bits(apad_ck->regmap, AT91_PMC_AUDIO_PLL0, | |
| 151 | + AT91_PMC_AUDIO_PLL_PADEN, 0); | |
| 152 | +} | |
| 153 | + | |
| 154 | +static void clk_audio_pll_pmc_disable(struct clk_hw *hw) | |
| 155 | +{ | |
| 156 | + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | |
| 157 | + | |
| 158 | + regmap_update_bits(apmc_ck->regmap, AT91_PMC_AUDIO_PLL0, | |
| 159 | + AT91_PMC_AUDIO_PLL_PMCEN, 0); | |
| 160 | +} | |
| 161 | + | |
| 162 | +static unsigned long clk_audio_pll_fout(unsigned long parent_rate, | |
| 163 | + unsigned long nd, unsigned long fracr) | |
| 164 | +{ | |
| 165 | + unsigned long long fr = (unsigned long long)parent_rate * fracr; | |
| 166 | + | |
| 167 | + pr_debug("A PLL: %s, fr = %llu\n", __func__, fr); | |
| 168 | + | |
| 169 | + fr = DIV_ROUND_CLOSEST_ULL(fr, AUDIO_PLL_DIV_FRAC); | |
| 170 | + | |
| 171 | + pr_debug("A PLL: %s, fr = %llu\n", __func__, fr); | |
| 172 | + | |
| 173 | + return parent_rate * (nd + 1) + fr; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static unsigned long clk_audio_pll_frac_recalc_rate(struct clk_hw *hw, | |
| 177 | + unsigned long parent_rate) | |
| 178 | +{ | |
| 179 | + struct clk_audio_frac *frac = to_clk_audio_frac(hw); | |
| 180 | + unsigned long fout; | |
| 181 | + | |
| 182 | + fout = clk_audio_pll_fout(parent_rate, frac->nd, frac->fracr); | |
| 183 | + | |
| 184 | + pr_debug("A PLL: %s, fout = %lu (nd = %u, fracr = %lu)\n", __func__, | |
| 185 | + fout, frac->nd, (unsigned long)frac->fracr); | |
| 186 | + | |
| 187 | + return fout; | |
| 188 | +} | |
| 189 | + | |
| 190 | +static unsigned long clk_audio_pll_pad_recalc_rate(struct clk_hw *hw, | |
| 191 | + unsigned long parent_rate) | |
| 192 | +{ | |
| 193 | + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | |
| 194 | + unsigned long apad_rate = 0; | |
| 195 | + | |
| 196 | + if (apad_ck->qdaudio && apad_ck->div) | |
| 197 | + apad_rate = parent_rate / (apad_ck->qdaudio * apad_ck->div); | |
| 198 | + | |
| 199 | + pr_debug("A PLL/PAD: %s, apad_rate = %lu (div = %u, qdaudio = %u)\n", | |
| 200 | + __func__, apad_rate, apad_ck->div, apad_ck->qdaudio); | |
| 201 | + | |
| 202 | + return apad_rate; | |
| 203 | +} | |
| 204 | + | |
| 205 | +static unsigned long clk_audio_pll_pmc_recalc_rate(struct clk_hw *hw, | |
| 206 | + unsigned long parent_rate) | |
| 207 | +{ | |
| 208 | + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | |
| 209 | + unsigned long apmc_rate = 0; | |
| 210 | + | |
| 211 | + apmc_rate = parent_rate / (apmc_ck->qdpmc + 1); | |
| 212 | + | |
| 213 | + pr_debug("A PLL/PMC: %s, apmc_rate = %lu (qdpmc = %u)\n", __func__, | |
| 214 | + apmc_rate, apmc_ck->qdpmc); | |
| 215 | + | |
| 216 | + return apmc_rate; | |
| 217 | +} | |
| 218 | + | |
| 219 | +static int clk_audio_pll_frac_compute_frac(unsigned long rate, | |
| 220 | + unsigned long parent_rate, | |
| 221 | + unsigned long *nd, | |
| 222 | + unsigned long *fracr) | |
| 223 | +{ | |
| 224 | + unsigned long long tmp, rem; | |
| 225 | + | |
| 226 | + if (!rate) | |
| 227 | + return -EINVAL; | |
| 228 | + | |
| 229 | + tmp = rate; | |
| 230 | + rem = do_div(tmp, parent_rate); | |
| 231 | + if (!tmp || tmp >= AUDIO_PLL_ND_MAX) | |
| 232 | + return -EINVAL; | |
| 233 | + | |
| 234 | + *nd = tmp - 1; | |
| 235 | + | |
| 236 | + tmp = rem * AUDIO_PLL_DIV_FRAC; | |
| 237 | + tmp = DIV_ROUND_CLOSEST_ULL(tmp, parent_rate); | |
| 238 | + if (tmp > AT91_PMC_AUDIO_PLL_FRACR_MASK) | |
| 239 | + return -EINVAL; | |
| 240 | + | |
| 241 | + /* we can cast here as we verified the bounds just above */ | |
| 242 | + *fracr = (unsigned long)tmp; | |
| 243 | + | |
| 244 | + return 0; | |
| 245 | +} | |
| 246 | + | |
| 247 | +static int clk_audio_pll_frac_determine_rate(struct clk_hw *hw, | |
| 248 | + struct clk_rate_request *req) | |
| 249 | +{ | |
| 250 | + unsigned long fracr, nd; | |
| 251 | + int ret; | |
| 252 | + | |
| 253 | + pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, | |
| 254 | + req->rate, req->best_parent_rate); | |
| 255 | + | |
| 256 | + req->rate = clamp(req->rate, AUDIO_PLL_FOUT_MIN, AUDIO_PLL_FOUT_MAX); | |
| 257 | + | |
| 258 | + req->min_rate = max(req->min_rate, AUDIO_PLL_FOUT_MIN); | |
| 259 | + req->max_rate = min(req->max_rate, AUDIO_PLL_FOUT_MAX); | |
| 260 | + | |
| 261 | + ret = clk_audio_pll_frac_compute_frac(req->rate, req->best_parent_rate, | |
| 262 | + &nd, &fracr); | |
| 263 | + if (ret) | |
| 264 | + return ret; | |
| 265 | + | |
| 266 | + req->rate = clk_audio_pll_fout(req->best_parent_rate, nd, fracr); | |
| 267 | + | |
| 268 | + req->best_parent_hw = clk_hw_get_parent(hw); | |
| 269 | + | |
| 270 | + pr_debug("A PLL: %s, best_rate = %lu (nd = %lu, fracr = %lu)\n", | |
| 271 | + __func__, req->rate, nd, fracr); | |
| 272 | + | |
| 273 | + return 0; | |
| 274 | +} | |
| 275 | + | |
| 276 | +static long clk_audio_pll_pad_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 277 | + unsigned long *parent_rate) | |
| 278 | +{ | |
| 279 | + struct clk_hw *pclk = clk_hw_get_parent(hw); | |
| 280 | + long best_rate = -EINVAL; | |
| 281 | + unsigned long best_parent_rate; | |
| 282 | + unsigned long tmp_qd; | |
| 283 | + u32 div; | |
| 284 | + long tmp_rate; | |
| 285 | + int tmp_diff; | |
| 286 | + int best_diff = -1; | |
| 287 | + | |
| 288 | + pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, | |
| 289 | + rate, *parent_rate); | |
| 290 | + | |
| 291 | + /* | |
| 292 | + * Rate divisor is actually made of two different divisors, multiplied | |
| 293 | + * between themselves before dividing the rate. | |
| 294 | + * tmp_qd goes from 1 to 31 and div is either 2 or 3. | |
| 295 | + * In order to avoid testing twice the rate divisor (e.g. divisor 12 can | |
| 296 | + * be found with (tmp_qd, div) = (2, 6) or (3, 4)), we remove any loop | |
| 297 | + * for a rate divisor when div is 2 and tmp_qd is a multiple of 3. | |
| 298 | + * We cannot inverse it (condition div is 3 and tmp_qd is even) or we | |
| 299 | + * would miss some rate divisor that aren't reachable with div being 2 | |
| 300 | + * (e.g. rate divisor 90 is made with div = 3 and tmp_qd = 30, thus | |
| 301 | + * tmp_qd is even so we skip it because we think div 2 could make this | |
| 302 | + * rate divisor which isn't possible since tmp_qd has to be <= 31). | |
| 303 | + */ | |
| 304 | + for (tmp_qd = 1; tmp_qd < AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX; tmp_qd++) | |
| 305 | + for (div = 2; div <= 3; div++) { | |
| 306 | + if (div == 2 && tmp_qd % 3 == 0) | |
| 307 | + continue; | |
| 308 | + | |
| 309 | + best_parent_rate = clk_hw_round_rate(pclk, | |
| 310 | + rate * tmp_qd * div); | |
| 311 | + tmp_rate = best_parent_rate / (div * tmp_qd); | |
| 312 | + tmp_diff = abs(rate - tmp_rate); | |
| 313 | + | |
| 314 | + if (best_diff < 0 || best_diff > tmp_diff) { | |
| 315 | + *parent_rate = best_parent_rate; | |
| 316 | + best_rate = tmp_rate; | |
| 317 | + best_diff = tmp_diff; | |
| 318 | + } | |
| 319 | + } | |
| 320 | + | |
| 321 | + pr_debug("A PLL/PAD: %s, best_rate = %ld, best_parent_rate = %lu\n", | |
| 322 | + __func__, best_rate, best_parent_rate); | |
| 323 | + | |
| 324 | + return best_rate; | |
| 325 | +} | |
| 326 | + | |
| 327 | +static long clk_audio_pll_pmc_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 328 | + unsigned long *parent_rate) | |
| 329 | +{ | |
| 330 | + struct clk_hw *pclk = clk_hw_get_parent(hw); | |
| 331 | + long best_rate = -EINVAL; | |
| 332 | + unsigned long best_parent_rate = 0; | |
| 333 | + u32 tmp_qd = 0, div; | |
| 334 | + long tmp_rate; | |
| 335 | + int tmp_diff; | |
| 336 | + int best_diff = -1; | |
| 337 | + | |
| 338 | + pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, | |
| 339 | + rate, *parent_rate); | |
| 340 | + | |
| 341 | + for (div = 1; div <= AUDIO_PLL_QDPMC_MAX; div++) { | |
| 342 | + best_parent_rate = clk_round_rate(pclk->clk, rate * div); | |
| 343 | + tmp_rate = best_parent_rate / div; | |
| 344 | + tmp_diff = abs(rate - tmp_rate); | |
| 345 | + | |
| 346 | + if (best_diff < 0 || best_diff > tmp_diff) { | |
| 347 | + *parent_rate = best_parent_rate; | |
| 348 | + best_rate = tmp_rate; | |
| 349 | + best_diff = tmp_diff; | |
| 350 | + tmp_qd = div; | |
| 351 | + } | |
| 352 | + } | |
| 353 | + | |
| 354 | + pr_debug("A PLL/PMC: %s, best_rate = %ld, best_parent_rate = %lu (qd = %d)\n", | |
| 355 | + __func__, best_rate, *parent_rate, tmp_qd - 1); | |
| 356 | + | |
| 357 | + return best_rate; | |
| 358 | +} | |
| 359 | + | |
| 360 | +static int clk_audio_pll_frac_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 361 | + unsigned long parent_rate) | |
| 362 | +{ | |
| 363 | + struct clk_audio_frac *frac = to_clk_audio_frac(hw); | |
| 364 | + unsigned long fracr, nd; | |
| 365 | + int ret; | |
| 366 | + | |
| 367 | + pr_debug("A PLL: %s, rate = %lu (parent_rate = %lu)\n", __func__, rate, | |
| 368 | + parent_rate); | |
| 369 | + | |
| 370 | + if (rate < AUDIO_PLL_FOUT_MIN || rate > AUDIO_PLL_FOUT_MAX) | |
| 371 | + return -EINVAL; | |
| 372 | + | |
| 373 | + ret = clk_audio_pll_frac_compute_frac(rate, parent_rate, &nd, &fracr); | |
| 374 | + if (ret) | |
| 375 | + return ret; | |
| 376 | + | |
| 377 | + frac->nd = nd; | |
| 378 | + frac->fracr = fracr; | |
| 379 | + | |
| 380 | + return 0; | |
| 381 | +} | |
| 382 | + | |
| 383 | +static int clk_audio_pll_pad_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 384 | + unsigned long parent_rate) | |
| 385 | +{ | |
| 386 | + struct clk_audio_pad *apad_ck = to_clk_audio_pad(hw); | |
| 387 | + u8 tmp_div; | |
| 388 | + | |
| 389 | + pr_debug("A PLL/PAD: %s, rate = %lu (parent_rate = %lu)\n", __func__, | |
| 390 | + rate, parent_rate); | |
| 391 | + | |
| 392 | + if (!rate) | |
| 393 | + return -EINVAL; | |
| 394 | + | |
| 395 | + tmp_div = parent_rate / rate; | |
| 396 | + if (tmp_div % 3 == 0) { | |
| 397 | + apad_ck->qdaudio = tmp_div / 3; | |
| 398 | + apad_ck->div = 3; | |
| 399 | + } else { | |
| 400 | + apad_ck->qdaudio = tmp_div / 2; | |
| 401 | + apad_ck->div = 2; | |
| 402 | + } | |
| 403 | + | |
| 404 | + return 0; | |
| 405 | +} | |
| 406 | + | |
| 407 | +static int clk_audio_pll_pmc_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 408 | + unsigned long parent_rate) | |
| 409 | +{ | |
| 410 | + struct clk_audio_pmc *apmc_ck = to_clk_audio_pmc(hw); | |
| 411 | + | |
| 412 | + if (!rate) | |
| 413 | + return -EINVAL; | |
| 414 | + | |
| 415 | + pr_debug("A PLL/PMC: %s, rate = %lu (parent_rate = %lu)\n", __func__, | |
| 416 | + rate, parent_rate); | |
| 417 | + | |
| 418 | + apmc_ck->qdpmc = parent_rate / rate - 1; | |
| 419 | + | |
| 420 | + return 0; | |
| 421 | +} | |
| 422 | + | |
| 423 | +static const struct clk_ops audio_pll_frac_ops = { | |
| 424 | + .enable = clk_audio_pll_frac_enable, | |
| 425 | + .disable = clk_audio_pll_frac_disable, | |
| 426 | + .recalc_rate = clk_audio_pll_frac_recalc_rate, | |
| 427 | + .determine_rate = clk_audio_pll_frac_determine_rate, | |
| 428 | + .set_rate = clk_audio_pll_frac_set_rate, | |
| 429 | +}; | |
| 430 | + | |
| 431 | +static const struct clk_ops audio_pll_pad_ops = { | |
| 432 | + .enable = clk_audio_pll_pad_enable, | |
| 433 | + .disable = clk_audio_pll_pad_disable, | |
| 434 | + .recalc_rate = clk_audio_pll_pad_recalc_rate, | |
| 435 | + .round_rate = clk_audio_pll_pad_round_rate, | |
| 436 | + .set_rate = clk_audio_pll_pad_set_rate, | |
| 437 | +}; | |
| 438 | + | |
| 439 | +static const struct clk_ops audio_pll_pmc_ops = { | |
| 440 | + .enable = clk_audio_pll_pmc_enable, | |
| 441 | + .disable = clk_audio_pll_pmc_disable, | |
| 442 | + .recalc_rate = clk_audio_pll_pmc_recalc_rate, | |
| 443 | + .round_rate = clk_audio_pll_pmc_round_rate, | |
| 444 | + .set_rate = clk_audio_pll_pmc_set_rate, | |
| 445 | +}; | |
| 446 | + | |
| 447 | +static int of_sama5d2_clk_audio_pll_setup(struct device_node *np, | |
| 448 | + struct clk_init_data *init, | |
| 449 | + struct clk_hw *hw, | |
| 450 | + struct regmap **clk_audio_regmap) | |
| 451 | +{ | |
| 452 | + struct regmap *regmap; | |
| 453 | + const char *parent_names[1]; | |
| 454 | + int ret; | |
| 455 | + | |
| 456 | + regmap = syscon_node_to_regmap(of_get_parent(np)); | |
| 457 | + if (IS_ERR(regmap)) | |
| 458 | + return PTR_ERR(regmap); | |
| 459 | + | |
| 460 | + init->name = np->name; | |
| 461 | + of_clk_parent_fill(np, parent_names, 1); | |
| 462 | + init->parent_names = parent_names; | |
| 463 | + init->num_parents = 1; | |
| 464 | + | |
| 465 | + hw->init = init; | |
| 466 | + *clk_audio_regmap = regmap; | |
| 467 | + | |
| 468 | + ret = clk_hw_register(NULL, hw); | |
| 469 | + if (ret) | |
| 470 | + return ret; | |
| 471 | + | |
| 472 | + return of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); | |
| 473 | +} | |
| 474 | + | |
| 475 | +static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np) | |
| 476 | +{ | |
| 477 | + struct clk_audio_frac *frac_ck; | |
| 478 | + struct clk_init_data init = {}; | |
| 479 | + | |
| 480 | + frac_ck = kzalloc(sizeof(*frac_ck), GFP_KERNEL); | |
| 481 | + if (!frac_ck) | |
| 482 | + return; | |
| 483 | + | |
| 484 | + init.ops = &audio_pll_frac_ops; | |
| 485 | + init.flags = CLK_SET_RATE_GATE; | |
| 486 | + | |
| 487 | + if (of_sama5d2_clk_audio_pll_setup(np, &init, &frac_ck->hw, | |
| 488 | + &frac_ck->regmap)) | |
| 489 | + kfree(frac_ck); | |
| 490 | +} | |
| 491 | + | |
| 492 | +static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np) | |
| 493 | +{ | |
| 494 | + struct clk_audio_pad *apad_ck; | |
| 495 | + struct clk_init_data init = {}; | |
| 496 | + | |
| 497 | + apad_ck = kzalloc(sizeof(*apad_ck), GFP_KERNEL); | |
| 498 | + if (!apad_ck) | |
| 499 | + return; | |
| 500 | + | |
| 501 | + init.ops = &audio_pll_pad_ops; | |
| 502 | + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | | |
| 503 | + CLK_SET_RATE_PARENT; | |
| 504 | + | |
| 505 | + if (of_sama5d2_clk_audio_pll_setup(np, &init, &apad_ck->hw, | |
| 506 | + &apad_ck->regmap)) | |
| 507 | + kfree(apad_ck); | |
| 508 | +} | |
| 509 | + | |
| 510 | +static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np) | |
| 511 | +{ | |
| 512 | + struct clk_audio_pad *apmc_ck; | |
| 513 | + struct clk_init_data init = {}; | |
| 514 | + | |
| 515 | + apmc_ck = kzalloc(sizeof(*apmc_ck), GFP_KERNEL); | |
| 516 | + if (!apmc_ck) | |
| 517 | + return; | |
| 518 | + | |
| 519 | + init.ops = &audio_pll_pmc_ops; | |
| 520 | + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | | |
| 521 | + CLK_SET_RATE_PARENT; | |
| 522 | + | |
| 523 | + if (of_sama5d2_clk_audio_pll_setup(np, &init, &apmc_ck->hw, | |
| 524 | + &apmc_ck->regmap)) | |
| 525 | + kfree(apmc_ck); | |
| 526 | +} | |
| 527 | + | |
| 528 | +CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_frac_setup, | |
| 529 | + "atmel,sama5d2-clk-audio-pll-frac", | |
| 530 | + of_sama5d2_clk_audio_pll_frac_setup); | |
| 531 | +CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pad_setup, | |
| 532 | + "atmel,sama5d2-clk-audio-pll-pad", | |
| 533 | + of_sama5d2_clk_audio_pll_pad_setup); | |
| 534 | +CLK_OF_DECLARE(of_sama5d2_clk_audio_pll_pmc_setup, | |
| 535 | + "atmel,sama5d2-clk-audio-pll-pmc", | |
| 536 | + of_sama5d2_clk_audio_pll_pmc_setup); | |
| @@ -26,6 +26,13 @@ · 25 unmodified lines | ||
| 26 | 26 | #define GENERATED_SOURCE_MAX 6 |
| 27 | 27 | #define GENERATED_MAX_DIV 255 |
| 28 | 28 | |
| 29 | +#define GCK_ID_SSC0 43 | |
| 30 | +#define GCK_ID_SSC1 44 | |
| 31 | +#define GCK_ID_I2S0 54 | |
| 32 | +#define GCK_ID_I2S1 55 | |
| 33 | +#define GCK_ID_CLASSD 59 | |
| 34 | +#define GCK_INDEX_DT_AUDIO_PLL 5 | |
| 35 | + | |
| 29 | 36 | struct clk_generated { |
| 30 | 37 | struct clk_hw hw; |
| 31 | 38 | struct regmap *regmap; |
| @@ -34,6 +41,7 @@ struct clk_generated { · 2 unmodified lines | ||
| 34 | 41 | u32 id; |
| 35 | 42 | u32 gckdiv; |
| 36 | 43 | u8 parent_id; |
| 44 | + bool audio_pll_allowed; | |
| 37 | 45 | }; |
| 38 | 46 | |
| 39 | 47 | #define to_clk_generated(hw) \ |
| @@ -99,21 +107,41 @@ clk_generated_recalc_rate(struct clk_hw *hw, · 59 unmodified lines | ||
| 99 | 107 | return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1); |
| 100 | 108 | } |
| 101 | 109 | |
| 110 | +static void clk_generated_best_diff(struct clk_rate_request *req, | |
| 111 | + struct clk_hw *parent, | |
| 112 | + unsigned long parent_rate, u32 div, | |
| 113 | + int *best_diff, long *best_rate) | |
| 114 | +{ | |
| 115 | + unsigned long tmp_rate; | |
| 116 | + int tmp_diff; | |
| 117 | + | |
| 118 | + if (!div) | |
| 119 | + tmp_rate = parent_rate; | |
| 120 | + else | |
| 121 | + tmp_rate = parent_rate / div; | |
| 122 | + tmp_diff = abs(req->rate - tmp_rate); | |
| 123 | + | |
| 124 | + if (*best_diff < 0 || *best_diff > tmp_diff) { | |
| 125 | + *best_rate = tmp_rate; | |
| 126 | + *best_diff = tmp_diff; | |
| 127 | + req->best_parent_rate = parent_rate; | |
| 128 | + req->best_parent_hw = parent; | |
| 129 | + } | |
| 130 | +} | |
| 131 | + | |
| 102 | 132 | static int clk_generated_determine_rate(struct clk_hw *hw, |
| 103 | 133 | struct clk_rate_request *req) |
| 104 | 134 | { |
| 105 | 135 | struct clk_generated *gck = to_clk_generated(hw); |
| 106 | 136 | struct clk_hw *parent = NULL; |
| 137 | + struct clk_rate_request req_parent = *req; | |
| 107 | 138 | long best_rate = -EINVAL; |
| 108 | − unsigned long tmp_rate, min_rate; | |
| 139 | + unsigned long min_rate, parent_rate; | |
| 109 | 140 | int best_diff = -1; |
| 110 | − int tmp_diff; | |
| 111 | 141 | int i; |
| 142 | + u32 div; | |
| 112 | 143 | |
| 113 | − for (i = 0; i < clk_hw_get_num_parents(hw); i++) { | |
| 114 | − u32 div; | |
| 115 | − unsigned long parent_rate; | |
| 116 | − | |
| 144 | + for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) { | |
| 117 | 145 | parent = clk_hw_get_parent_by_index(hw, i); |
| 118 | 146 | if (!parent) |
| 119 | 147 | continue; |
| @@ -124,25 +152,43 @@ static int clk_generated_determine_rate(struct clk_hw *hw, · 4 unmodified lines | ||
| 124 | 152 | (gck->range.max && min_rate > gck->range.max)) |
| 125 | 153 | continue; |
| 126 | 154 | |
| 127 | − for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { | |
| 128 | − tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div); | |
| 129 | − tmp_diff = abs(req->rate - tmp_rate); | |
| 155 | + div = DIV_ROUND_CLOSEST(parent_rate, req->rate); | |
| 130 | 156 | |
| 131 | − if (best_diff < 0 || best_diff > tmp_diff) { | |
| 132 | − best_rate = tmp_rate; | |
| 133 | − best_diff = tmp_diff; | |
| 134 | − req->best_parent_rate = parent_rate; | |
| 135 | − req->best_parent_hw = parent; | |
| 136 | − } | |
| 157 | + clk_generated_best_diff(req, parent, parent_rate, div, | |
| 158 | + &best_diff, &best_rate); | |
| 137 | 159 | |
| 138 | − if (!best_diff || tmp_rate < req->rate) | |
| 139 | − break; | |
| 140 | − } | |
| 160 | + if (!best_diff) | |
| 161 | + break; | |
| 162 | + } | |
| 163 | + | |
| 164 | + /* | |
| 165 | + * The audio_pll rate can be modified, unlike the five others clocks | |
| 166 | + * that should never be altered. | |
| 167 | + * The audio_pll can technically be used by multiple consumers. However, | |
| 168 | + * with the rate locking, the first consumer to enable to clock will be | |
| 169 | + * the one definitely setting the rate of the clock. | |
| 170 | + * Since audio IPs are most likely to request the same rate, we enforce | |
| 171 | + * that the only clks able to modify gck rate are those of audio IPs. | |
| 172 | + */ | |
| 173 | + | |
| 174 | + if (!gck->audio_pll_allowed) | |
| 175 | + goto end; | |
| 176 | + | |
| 177 | + parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL); | |
| 178 | + if (!parent) | |
| 179 | + goto end; | |
| 180 | + | |
| 181 | + for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { | |
| 182 | + req_parent.rate = req->rate * div; | |
| 183 | + __clk_determine_rate(parent, &req_parent); | |
| 184 | + clk_generated_best_diff(req, parent, req_parent.rate, div, | |
| 185 | + &best_diff, &best_rate); | |
| 141 | 186 | |
| 142 | 187 | if (!best_diff) |
| 143 | 188 | break; |
| 144 | 189 | } |
| 145 | 190 | |
| 191 | +end: | |
| 146 | 192 | pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n", |
| 147 | 193 | __func__, best_rate, |
| 148 | 194 | __clk_get_name((req->best_parent_hw)->clk), |
| @@ -252,7 +298,8 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, · 103 unmodified lines | ||
| 252 | 298 | init.ops = &generated_ops; |
| 253 | 299 | init.parent_names = parent_names; |
| 254 | 300 | init.num_parents = num_parents; |
| 255 | − init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; | |
| 301 | + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | | |
| 302 | + CLK_SET_RATE_PARENT; | |
| 256 | 303 | |
| 257 | 304 | gck->id = id; |
| 258 | 305 | gck->hw.init = &init; |
| @@ -284,6 +331,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) · 25 unmodified lines | ||
| 284 | 331 | struct device_node *gcknp; |
| 285 | 332 | struct clk_range range = CLK_RANGE(0, 0); |
| 286 | 333 | struct regmap *regmap; |
| 334 | + struct clk_generated *gck; | |
| 287 | 335 | |
| 288 | 336 | num_parents = of_clk_get_parent_count(np); |
| 289 | 337 | if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX) |
| @@ -315,6 +363,21 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) · 25 unmodified lines | ||
| 315 | 363 | hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, |
| 316 | 364 | parent_names, num_parents, |
| 317 | 365 | id, &range); |
| 366 | + | |
| 367 | + gck = to_clk_generated(hw); | |
| 368 | + | |
| 369 | + if (of_device_is_compatible(np, | |
| 370 | + "atmel,sama5d2-clk-generated")) { | |
| 371 | + if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 || | |
| 372 | + gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 || | |
| 373 | + gck->id == GCK_ID_CLASSD) | |
| 374 | + gck->audio_pll_allowed = true; | |
| 375 | + else | |
| 376 | + gck->audio_pll_allowed = false; | |
| 377 | + } else { | |
| 378 | + gck->audio_pll_allowed = false; | |
| 379 | + } | |
| 380 | + | |
| 318 | 381 | if (IS_ERR(hw)) |
| 319 | 382 | continue; |
| 320 | 383 | |
| @@ -1 +1,2 @@ | ||
| 1 | 1 | obj-y += i2s_pll_clock.o |
| 2 | +obj-y += pll_clock.o | |
| @@ -0,0 +1,346 @@ | ||
| 1 | +/* | |
| 2 | + * Synopsys AXS10X SDP Generic PLL clock driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2017 Synopsys | |
| 5 | + * | |
| 6 | + * This file is licensed under the terms of the GNU General Public | |
| 7 | + * License version 2. This program is licensed "as is" without any | |
| 8 | + * warranty of any kind, whether express or implied. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/platform_device.h> | |
| 12 | +#include <linux/module.h> | |
| 13 | +#include <linux/clk-provider.h> | |
| 14 | +#include <linux/delay.h> | |
| 15 | +#include <linux/err.h> | |
| 16 | +#include <linux/device.h> | |
| 17 | +#include <linux/of_address.h> | |
| 18 | +#include <linux/of_device.h> | |
| 19 | +#include <linux/slab.h> | |
| 20 | +#include <linux/of.h> | |
| 21 | + | |
| 22 | +/* PLL registers addresses */ | |
| 23 | +#define PLL_REG_IDIV 0x0 | |
| 24 | +#define PLL_REG_FBDIV 0x4 | |
| 25 | +#define PLL_REG_ODIV 0x8 | |
| 26 | + | |
| 27 | +/* | |
| 28 | + * Bit fields of the PLL IDIV/FBDIV/ODIV registers: | |
| 29 | + * ________________________________________________________________________ | |
| 30 | + * |31 15| 14 | 13 | 12 |11 6|5 0| | |
| 31 | + * |-------RESRVED------|-NOUPDATE-|-BYPASS-|-EDGE-|--HIGHTIME--|--LOWTIME--| | |
| 32 | + * |____________________|__________|________|______|____________|___________| | |
| 33 | + * | |
| 34 | + * Following macros determine the way of access to these registers | |
| 35 | + * They should be set up only using the macros. | |
| 36 | + * reg should be an u32 variable. | |
| 37 | + */ | |
| 38 | + | |
| 39 | +#define PLL_REG_GET_LOW(reg) \ | |
| 40 | + (((reg) & (0x3F << 0)) >> 0) | |
| 41 | +#define PLL_REG_GET_HIGH(reg) \ | |
| 42 | + (((reg) & (0x3F << 6)) >> 6) | |
| 43 | +#define PLL_REG_GET_EDGE(reg) \ | |
| 44 | + (((reg) & (BIT(12))) ? 1 : 0) | |
| 45 | +#define PLL_REG_GET_BYPASS(reg) \ | |
| 46 | + (((reg) & (BIT(13))) ? 1 : 0) | |
| 47 | +#define PLL_REG_GET_NOUPD(reg) \ | |
| 48 | + (((reg) & (BIT(14))) ? 1 : 0) | |
| 49 | +#define PLL_REG_GET_PAD(reg) \ | |
| 50 | + (((reg) & (0x1FFFF << 15)) >> 15) | |
| 51 | + | |
| 52 | +#define PLL_REG_SET_LOW(reg, value) \ | |
| 53 | + { reg |= (((value) & 0x3F) << 0); } | |
| 54 | +#define PLL_REG_SET_HIGH(reg, value) \ | |
| 55 | + { reg |= (((value) & 0x3F) << 6); } | |
| 56 | +#define PLL_REG_SET_EDGE(reg, value) \ | |
| 57 | + { reg |= (((value) & 0x01) << 12); } | |
| 58 | +#define PLL_REG_SET_BYPASS(reg, value) \ | |
| 59 | + { reg |= (((value) & 0x01) << 13); } | |
| 60 | +#define PLL_REG_SET_NOUPD(reg, value) \ | |
| 61 | + { reg |= (((value) & 0x01) << 14); } | |
| 62 | +#define PLL_REG_SET_PAD(reg, value) \ | |
| 63 | + { reg |= (((value) & 0x1FFFF) << 15); } | |
| 64 | + | |
| 65 | +#define PLL_LOCK BIT(0) | |
| 66 | +#define PLL_ERROR BIT(1) | |
| 67 | +#define PLL_MAX_LOCK_TIME 100 /* 100 us */ | |
| 68 | + | |
| 69 | +struct axs10x_pll_cfg { | |
| 70 | + u32 rate; | |
| 71 | + u32 idiv; | |
| 72 | + u32 fbdiv; | |
| 73 | + u32 odiv; | |
| 74 | +}; | |
| 75 | + | |
| 76 | +static const struct axs10x_pll_cfg arc_pll_cfg[] = { | |
| 77 | + { 33333333, 1, 1, 1 }, | |
| 78 | + { 50000000, 1, 30, 20 }, | |
| 79 | + { 75000000, 2, 45, 10 }, | |
| 80 | + { 90000000, 2, 54, 10 }, | |
| 81 | + { 100000000, 1, 30, 10 }, | |
| 82 | + { 125000000, 2, 45, 6 }, | |
| 83 | + {} | |
| 84 | +}; | |
| 85 | + | |
| 86 | +static const struct axs10x_pll_cfg pgu_pll_cfg[] = { | |
| 87 | + { 25200000, 1, 84, 90 }, | |
| 88 | + { 50000000, 1, 100, 54 }, | |
| 89 | + { 74250000, 1, 44, 16 }, | |
| 90 | + {} | |
| 91 | +}; | |
| 92 | + | |
| 93 | +struct axs10x_pll_clk { | |
| 94 | + struct clk_hw hw; | |
| 95 | + void __iomem *base; | |
| 96 | + void __iomem *lock; | |
| 97 | + const struct axs10x_pll_cfg *pll_cfg; | |
| 98 | + struct device *dev; | |
| 99 | +}; | |
| 100 | + | |
| 101 | +static inline void axs10x_pll_write(struct axs10x_pll_clk *clk, u32 reg, | |
| 102 | + u32 val) | |
| 103 | +{ | |
| 104 | + iowrite32(val, clk->base + reg); | |
| 105 | +} | |
| 106 | + | |
| 107 | +static inline u32 axs10x_pll_read(struct axs10x_pll_clk *clk, u32 reg) | |
| 108 | +{ | |
| 109 | + return ioread32(clk->base + reg); | |
| 110 | +} | |
| 111 | + | |
| 112 | +static inline struct axs10x_pll_clk *to_axs10x_pll_clk(struct clk_hw *hw) | |
| 113 | +{ | |
| 114 | + return container_of(hw, struct axs10x_pll_clk, hw); | |
| 115 | +} | |
| 116 | + | |
| 117 | +static inline u32 axs10x_div_get_value(u32 reg) | |
| 118 | +{ | |
| 119 | + if (PLL_REG_GET_BYPASS(reg)) | |
| 120 | + return 1; | |
| 121 | + | |
| 122 | + return PLL_REG_GET_HIGH(reg) + PLL_REG_GET_LOW(reg); | |
| 123 | +} | |
| 124 | + | |
| 125 | +static inline u32 axs10x_encode_div(unsigned int id, int upd) | |
| 126 | +{ | |
| 127 | + u32 div = 0; | |
| 128 | + | |
| 129 | + PLL_REG_SET_LOW(div, (id % 2 == 0) ? id >> 1 : (id >> 1) + 1); | |
| 130 | + PLL_REG_SET_HIGH(div, id >> 1); | |
| 131 | + PLL_REG_SET_EDGE(div, id % 2); | |
| 132 | + PLL_REG_SET_BYPASS(div, id == 1 ? 1 : 0); | |
| 133 | + PLL_REG_SET_NOUPD(div, upd == 0 ? 1 : 0); | |
| 134 | + | |
| 135 | + return div; | |
| 136 | +} | |
| 137 | + | |
| 138 | +static unsigned long axs10x_pll_recalc_rate(struct clk_hw *hw, | |
| 139 | + unsigned long parent_rate) | |
| 140 | +{ | |
| 141 | + u64 rate; | |
| 142 | + u32 idiv, fbdiv, odiv; | |
| 143 | + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | |
| 144 | + | |
| 145 | + idiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_IDIV)); | |
| 146 | + fbdiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_FBDIV)); | |
| 147 | + odiv = axs10x_div_get_value(axs10x_pll_read(clk, PLL_REG_ODIV)); | |
| 148 | + | |
| 149 | + rate = (u64)parent_rate * fbdiv; | |
| 150 | + do_div(rate, idiv * odiv); | |
| 151 | + | |
| 152 | + return rate; | |
| 153 | +} | |
| 154 | + | |
| 155 | +static long axs10x_pll_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 156 | + unsigned long *prate) | |
| 157 | +{ | |
| 158 | + int i; | |
| 159 | + long best_rate; | |
| 160 | + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | |
| 161 | + const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; | |
| 162 | + | |
| 163 | + if (pll_cfg[0].rate == 0) | |
| 164 | + return -EINVAL; | |
| 165 | + | |
| 166 | + best_rate = pll_cfg[0].rate; | |
| 167 | + | |
| 168 | + for (i = 1; pll_cfg[i].rate != 0; i++) { | |
| 169 | + if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) | |
| 170 | + best_rate = pll_cfg[i].rate; | |
| 171 | + } | |
| 172 | + | |
| 173 | + return best_rate; | |
| 174 | +} | |
| 175 | + | |
| 176 | +static int axs10x_pll_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 177 | + unsigned long parent_rate) | |
| 178 | +{ | |
| 179 | + int i; | |
| 180 | + struct axs10x_pll_clk *clk = to_axs10x_pll_clk(hw); | |
| 181 | + const struct axs10x_pll_cfg *pll_cfg = clk->pll_cfg; | |
| 182 | + | |
| 183 | + for (i = 0; pll_cfg[i].rate != 0; i++) { | |
| 184 | + if (pll_cfg[i].rate == rate) { | |
| 185 | + axs10x_pll_write(clk, PLL_REG_IDIV, | |
| 186 | + axs10x_encode_div(pll_cfg[i].idiv, 0)); | |
| 187 | + axs10x_pll_write(clk, PLL_REG_FBDIV, | |
| 188 | + axs10x_encode_div(pll_cfg[i].fbdiv, 0)); | |
| 189 | + axs10x_pll_write(clk, PLL_REG_ODIV, | |
| 190 | + axs10x_encode_div(pll_cfg[i].odiv, 1)); | |
| 191 | + | |
| 192 | + /* | |
| 193 | + * Wait until CGU relocks and check error status. | |
| 194 | + * If after timeout CGU is unlocked yet return error | |
| 195 | + */ | |
| 196 | + udelay(PLL_MAX_LOCK_TIME); | |
| 197 | + if (!(ioread32(clk->lock) & PLL_LOCK)) | |
| 198 | + return -ETIMEDOUT; | |
| 199 | + | |
| 200 | + if (ioread32(clk->lock) & PLL_ERROR) | |
| 201 | + return -EINVAL; | |
| 202 | + | |
| 203 | + return 0; | |
| 204 | + } | |
| 205 | + } | |
| 206 | + | |
| 207 | + dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, | |
| 208 | + parent_rate); | |
| 209 | + return -EINVAL; | |
| 210 | +} | |
| 211 | + | |
| 212 | +static const struct clk_ops axs10x_pll_ops = { | |
| 213 | + .recalc_rate = axs10x_pll_recalc_rate, | |
| 214 | + .round_rate = axs10x_pll_round_rate, | |
| 215 | + .set_rate = axs10x_pll_set_rate, | |
| 216 | +}; | |
| 217 | + | |
| 218 | +static int axs10x_pll_clk_probe(struct platform_device *pdev) | |
| 219 | +{ | |
| 220 | + struct device *dev = &pdev->dev; | |
| 221 | + const char *parent_name; | |
| 222 | + struct axs10x_pll_clk *pll_clk; | |
| 223 | + struct resource *mem; | |
| 224 | + struct clk_init_data init = { }; | |
| 225 | + int ret; | |
| 226 | + | |
| 227 | + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); | |
| 228 | + if (!pll_clk) | |
| 229 | + return -ENOMEM; | |
| 230 | + | |
| 231 | + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 232 | + pll_clk->base = devm_ioremap_resource(dev, mem); | |
| 233 | + if (IS_ERR(pll_clk->base)) | |
| 234 | + return PTR_ERR(pll_clk->base); | |
| 235 | + | |
| 236 | + mem = platform_get_resource(pdev, IORESOURCE_MEM, 1); | |
| 237 | + pll_clk->lock = devm_ioremap_resource(dev, mem); | |
| 238 | + if (IS_ERR(pll_clk->lock)) | |
| 239 | + return PTR_ERR(pll_clk->lock); | |
| 240 | + | |
| 241 | + init.name = dev->of_node->name; | |
| 242 | + init.ops = &axs10x_pll_ops; | |
| 243 | + parent_name = of_clk_get_parent_name(dev->of_node, 0); | |
| 244 | + init.parent_names = &parent_name; | |
| 245 | + init.num_parents = 1; | |
| 246 | + pll_clk->hw.init = &init; | |
| 247 | + pll_clk->dev = dev; | |
| 248 | + pll_clk->pll_cfg = of_device_get_match_data(dev); | |
| 249 | + | |
| 250 | + if (!pll_clk->pll_cfg) { | |
| 251 | + dev_err(dev, "No OF match data provided\n"); | |
| 252 | + return -EINVAL; | |
| 253 | + } | |
| 254 | + | |
| 255 | + ret = devm_clk_hw_register(dev, &pll_clk->hw); | |
| 256 | + if (ret) { | |
| 257 | + dev_err(dev, "failed to register %s clock\n", init.name); | |
| 258 | + return ret; | |
| 259 | + } | |
| 260 | + | |
| 261 | + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, | |
| 262 | + &pll_clk->hw); | |
| 263 | +} | |
| 264 | + | |
| 265 | +static int axs10x_pll_clk_remove(struct platform_device *pdev) | |
| 266 | +{ | |
| 267 | + of_clk_del_provider(pdev->dev.of_node); | |
| 268 | + return 0; | |
| 269 | +} | |
| 270 | + | |
| 271 | +static void __init of_axs10x_pll_clk_setup(struct device_node *node) | |
| 272 | +{ | |
| 273 | + const char *parent_name; | |
| 274 | + struct axs10x_pll_clk *pll_clk; | |
| 275 | + struct clk_init_data init = { }; | |
| 276 | + int ret; | |
| 277 | + | |
| 278 | + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | |
| 279 | + if (!pll_clk) | |
| 280 | + return; | |
| 281 | + | |
| 282 | + pll_clk->base = of_iomap(node, 0); | |
| 283 | + if (!pll_clk->base) { | |
| 284 | + pr_err("failed to map pll div registers\n"); | |
| 285 | + goto err_free_pll_clk; | |
| 286 | + } | |
| 287 | + | |
| 288 | + pll_clk->lock = of_iomap(node, 1); | |
| 289 | + if (!pll_clk->lock) { | |
| 290 | + pr_err("failed to map pll lock register\n"); | |
| 291 | + goto err_unmap_base; | |
| 292 | + } | |
| 293 | + | |
| 294 | + init.name = node->name; | |
| 295 | + init.ops = &axs10x_pll_ops; | |
| 296 | + parent_name = of_clk_get_parent_name(node, 0); | |
| 297 | + init.parent_names = &parent_name; | |
| 298 | + init.num_parents = parent_name ? 1 : 0; | |
| 299 | + pll_clk->hw.init = &init; | |
| 300 | + pll_clk->pll_cfg = arc_pll_cfg; | |
| 301 | + | |
| 302 | + ret = clk_hw_register(NULL, &pll_clk->hw); | |
| 303 | + if (ret) { | |
| 304 | + pr_err("failed to register %s clock\n", node->name); | |
| 305 | + goto err_unmap_lock; | |
| 306 | + } | |
| 307 | + | |
| 308 | + ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw); | |
| 309 | + if (ret) { | |
| 310 | + pr_err("failed to add hw provider for %s clock\n", node->name); | |
| 311 | + goto err_unregister_clk; | |
| 312 | + } | |
| 313 | + | |
| 314 | + return; | |
| 315 | + | |
| 316 | +err_unregister_clk: | |
| 317 | + clk_hw_unregister(&pll_clk->hw); | |
| 318 | +err_unmap_lock: | |
| 319 | + iounmap(pll_clk->lock); | |
| 320 | +err_unmap_base: | |
| 321 | + iounmap(pll_clk->base); | |
| 322 | +err_free_pll_clk: | |
| 323 | + kfree(pll_clk); | |
| 324 | +} | |
| 325 | +CLK_OF_DECLARE(axs10x_pll_clock, "snps,axs10x-arc-pll-clock", | |
| 326 | + of_axs10x_pll_clk_setup); | |
| 327 | + | |
| 328 | +static const struct of_device_id axs10x_pll_clk_id[] = { | |
| 329 | + { .compatible = "snps,axs10x-pgu-pll-clock", .data = &pgu_pll_cfg}, | |
| 330 | + { } | |
| 331 | +}; | |
| 332 | +MODULE_DEVICE_TABLE(of, axs10x_pll_clk_id); | |
| 333 | + | |
| 334 | +static struct platform_driver axs10x_pll_clk_driver = { | |
| 335 | + .driver = { | |
| 336 | + .name = "axs10x-pll-clock", | |
| 337 | + .of_match_table = axs10x_pll_clk_id, | |
| 338 | + }, | |
| 339 | + .probe = axs10x_pll_clk_probe, | |
| 340 | + .remove = axs10x_pll_clk_remove, | |
| 341 | +}; | |
| 342 | +builtin_platform_driver(axs10x_pll_clk_driver); | |
| 343 | + | |
| 344 | +MODULE_AUTHOR("Vlad Zakharov <vzakhar@synopsys.com>"); | |
| 345 | +MODULE_DESCRIPTION("Synopsys AXS10X SDP Generic PLL Clock Driver"); | |
| 346 | +MODULE_LICENSE("GPL v2"); | |
| @@ -679,8 +679,7 @@ static void __init berlin2_clock_setup(struct device_node *np) · 678 unmodified lines | ||
| 679 | 679 | if (!IS_ERR(hws[n])) |
| 680 | 680 | continue; |
| 681 | 681 | |
| 682 | − pr_err("%s: Unable to register leaf clock %d\n", | |
| 683 | − np->full_name, n); | |
| 682 | + pr_err("%pOF: Unable to register leaf clock %d\n", np, n); | |
| 684 | 683 | goto bg2_fail; |
| 685 | 684 | } |
| 686 | 685 | |
| @@ -304,14 +304,14 @@ static void __init berlin2q_clock_setup(struct device_node *np) · 303 unmodified lines | ||
| 304 | 304 | |
| 305 | 305 | gbase = of_iomap(parent_np, 0); |
| 306 | 306 | if (!gbase) { |
| 307 | − pr_err("%s: Unable to map global base\n", np->full_name); | |
| 307 | + pr_err("%pOF: Unable to map global base\n", np); | |
| 308 | 308 | return; |
| 309 | 309 | } |
| 310 | 310 | |
| 311 | 311 | /* BG2Q CPU PLL is not part of global registers */ |
| 312 | 312 | cpupll_base = of_iomap(parent_np, 1); |
| 313 | 313 | if (!cpupll_base) { |
| 314 | − pr_err("%s: Unable to map cpupll base\n", np->full_name); | |
| 314 | + pr_err("%pOF: Unable to map cpupll base\n", np); | |
| 315 | 315 | iounmap(gbase); |
| 316 | 316 | return; |
| 317 | 317 | } |
| @@ -376,8 +376,7 @@ static void __init berlin2q_clock_setup(struct device_node *np) · 58 unmodified lines | ||
| 376 | 376 | if (!IS_ERR(hws[n])) |
| 377 | 377 | continue; |
| 378 | 378 | |
| 379 | − pr_err("%s: Unable to register leaf clock %d\n", | |
| 380 | − np->full_name, n); | |
| 379 | + pr_err("%pOF: Unable to register leaf clock %d\n", np, n); | |
| 381 | 380 | goto bg2q_fail; |
| 382 | 381 | } |
| 383 | 382 | |
| @@ -338,8 +338,8 @@ static void __init asm9260_acc_init(struct device_node *np) · 337 unmodified lines | ||
| 338 | 338 | if (!IS_ERR(hws[n])) |
| 339 | 339 | continue; |
| 340 | 340 | |
| 341 | − pr_err("%s: Unable to register leaf clock %d\n", | |
| 342 | − np->full_name, n); | |
| 341 | + pr_err("%pOF: Unable to register leaf clock %d\n", | |
| 342 | + np, n); | |
| 343 | 343 | goto fail; |
| 344 | 344 | } |
| 345 | 345 | |
| @@ -23,8 +23,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) · 22 unmodified lines | ||
| 23 | 23 | num_parents = of_count_phandle_with_args(node, "assigned-clock-parents", |
| 24 | 24 | "#clock-cells"); |
| 25 | 25 | if (num_parents == -EINVAL) |
| 26 | − pr_err("clk: invalid value of clock-parents property at %s\n", | |
| 27 | − node->full_name); | |
| 26 | + pr_err("clk: invalid value of clock-parents property at %pOF\n", | |
| 27 | + node); | |
| 28 | 28 | |
| 29 | 29 | for (index = 0; index < num_parents; index++) { |
| 30 | 30 | rc = of_parse_phandle_with_args(node, "assigned-clock-parents", |
| @@ -41,8 +41,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) · 10 unmodified lines | ||
| 41 | 41 | pclk = of_clk_get_from_provider(&clkspec); |
| 42 | 42 | if (IS_ERR(pclk)) { |
| 43 | 43 | if (PTR_ERR(pclk) != -EPROBE_DEFER) |
| 44 | − pr_warn("clk: couldn't get parent clock %d for %s\n", | |
| 45 | − index, node->full_name); | |
| 44 | + pr_warn("clk: couldn't get parent clock %d for %pOF\n", | |
| 45 | + index, node); | |
| 46 | 46 | return PTR_ERR(pclk); |
| 47 | 47 | } |
| 48 | 48 | |
| @@ -57,8 +57,8 @@ static int __set_clk_parents(struct device_node *node, bool clk_supplier) · 8 unmodified lines | ||
| 57 | 57 | clk = of_clk_get_from_provider(&clkspec); |
| 58 | 58 | if (IS_ERR(clk)) { |
| 59 | 59 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 60 | − pr_warn("clk: couldn't get assigned clock %d for %s\n", | |
| 61 | − index, node->full_name); | |
| 60 | + pr_warn("clk: couldn't get assigned clock %d for %pOF\n", | |
| 61 | + index, node); | |
| 62 | 62 | rc = PTR_ERR(clk); |
| 63 | 63 | goto err; |
| 64 | 64 | } |
| @@ -102,8 +102,8 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier) · 37 unmodified lines | ||
| 102 | 102 | clk = of_clk_get_from_provider(&clkspec); |
| 103 | 103 | if (IS_ERR(clk)) { |
| 104 | 104 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 105 | − pr_warn("clk: couldn't get clock %d for %s\n", | |
| 106 | − index, node->full_name); | |
| 105 | + pr_warn("clk: couldn't get clock %d for %pOF\n", | |
| 106 | + index, node); | |
| 107 | 107 | return PTR_ERR(clk); |
| 108 | 108 | } |
| 109 | 109 | |
| @@ -343,6 +343,15 @@ static int cs2000_set_rate(struct clk_hw *hw, · 342 unmodified lines | ||
| 343 | 343 | return __cs2000_set_rate(priv, ch, rate, parent_rate); |
| 344 | 344 | } |
| 345 | 345 | |
| 346 | +static int cs2000_set_saved_rate(struct cs2000_priv *priv) | |
| 347 | +{ | |
| 348 | + int ch = 0; /* it uses ch0 only at this point */ | |
| 349 | + | |
| 350 | + return __cs2000_set_rate(priv, ch, | |
| 351 | + priv->saved_rate, | |
| 352 | + priv->saved_parent_rate); | |
| 353 | +} | |
| 354 | + | |
| 346 | 355 | static int cs2000_enable(struct clk_hw *hw) |
| 347 | 356 | { |
| 348 | 357 | struct cs2000_priv *priv = hw_to_priv(hw); |
| @@ -535,11 +544,8 @@ probe_err: · 186 unmodified lines | ||
| 535 | 544 | static int cs2000_resume(struct device *dev) |
| 536 | 545 | { |
| 537 | 546 | struct cs2000_priv *priv = dev_get_drvdata(dev); |
| 538 | − int ch = 0; /* it uses ch0 only at this point */ | |
| 539 | 547 | |
| 540 | − return __cs2000_set_rate(priv, ch, | |
| 541 | − priv->saved_rate, | |
| 542 | − priv->saved_parent_rate); | |
| 548 | + return cs2000_set_saved_rate(priv); | |
| 543 | 549 | } |
| 544 | 550 | |
| 545 | 551 | static const struct dev_pm_ops cs2000_pm_ops = { |
| @@ -385,12 +385,14 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, · 384 unmodified lines | ||
| 385 | 385 | unsigned long parent_rate) |
| 386 | 386 | { |
| 387 | 387 | struct clk_divider *divider = to_clk_divider(hw); |
| 388 | − unsigned int value; | |
| 388 | + int value; | |
| 389 | 389 | unsigned long flags = 0; |
| 390 | 390 | u32 val; |
| 391 | 391 | |
| 392 | 392 | value = divider_get_val(rate, parent_rate, divider->table, |
| 393 | 393 | divider->width, divider->flags); |
| 394 | + if (value < 0) | |
| 395 | + return value; | |
| 394 | 396 | |
| 395 | 397 | if (divider->lock) |
| 396 | 398 | spin_lock_irqsave(divider->lock, flags); |
| @@ -403,7 +405,7 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, · 6 unmodified lines | ||
| 403 | 405 | val = clk_readl(divider->reg); |
| 404 | 406 | val &= ~(div_mask(divider->width) << divider->shift); |
| 405 | 407 | } |
| 406 | − val |= value << divider->shift; | |
| 408 | + val |= (u32)value << divider->shift; | |
| 407 | 409 | clk_writel(val, divider->reg); |
| 408 | 410 | |
| 409 | 411 | if (divider->lock) |
| @@ -49,16 +49,12 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, · 48 unmodified lines | ||
| 49 | 49 | return ret; |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | −static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 53 | − unsigned long *parent_rate) | |
| 52 | +static void clk_fd_general_approximation(struct clk_hw *hw, unsigned long rate, | |
| 53 | + unsigned long *parent_rate, | |
| 54 | + unsigned long *m, unsigned long *n) | |
| 54 | 55 | { |
| 55 | 56 | struct clk_fractional_divider *fd = to_clk_fd(hw); |
| 56 | 57 | unsigned long scale; |
| 57 | − unsigned long m, n; | |
| 58 | − u64 ret; | |
| 59 | − | |
| 60 | − if (!rate || rate >= *parent_rate) | |
| 61 | − return *parent_rate; | |
| 62 | 58 | |
| 63 | 59 | /* |
| 64 | 60 | * Get rate closer to *parent_rate to guarantee there is no overflow |
| @@ -71,7 +67,23 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, · 6 unmodified lines | ||
| 71 | 67 | |
| 72 | 68 | rational_best_approximation(rate, *parent_rate, |
| 73 | 69 | GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), |
| 74 | − &m, &n); | |
| 70 | + m, n); | |
| 71 | +} | |
| 72 | + | |
| 73 | +static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 74 | + unsigned long *parent_rate) | |
| 75 | +{ | |
| 76 | + struct clk_fractional_divider *fd = to_clk_fd(hw); | |
| 77 | + unsigned long m, n; | |
| 78 | + u64 ret; | |
| 79 | + | |
| 80 | + if (!rate || rate >= *parent_rate) | |
| 81 | + return *parent_rate; | |
| 82 | + | |
| 83 | + if (fd->approximation) | |
| 84 | + fd->approximation(hw, rate, parent_rate, &m, &n); | |
| 85 | + else | |
| 86 | + clk_fd_general_approximation(hw, rate, parent_rate, &m, &n); | |
| 75 | 87 | |
| 76 | 88 | ret = (u64)*parent_rate * m; |
| 77 | 89 | do_div(ret, n); |
| @@ -86,7 +86,7 @@ static void clk_gate_disable(struct clk_hw *hw) · 85 unmodified lines | ||
| 86 | 86 | clk_gate_endisable(hw, 0); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | −static int clk_gate_is_enabled(struct clk_hw *hw) | |
| 89 | +int clk_gate_is_enabled(struct clk_hw *hw) | |
| 90 | 90 | { |
| 91 | 91 | u32 reg; |
| 92 | 92 | struct clk_gate *gate = to_clk_gate(hw); |
| @@ -101,6 +101,7 @@ static int clk_gate_is_enabled(struct clk_hw *hw) · 8 unmodified lines | ||
| 101 | 101 | |
| 102 | 102 | return reg ? 1 : 0; |
| 103 | 103 | } |
| 104 | +EXPORT_SYMBOL_GPL(clk_gate_is_enabled); | |
| 104 | 105 | |
| 105 | 106 | const struct clk_ops clk_gate_ops = { |
| 106 | 107 | .enable = clk_gate_enable, |
| @@ -37,7 +37,6 @@ static DEFINE_SPINLOCK(gemini_clk_lock); · 36 unmodified lines | ||
| 37 | 37 | |
| 38 | 38 | #define GEMINI_GLOBAL_MISC_CONTROL 0x30 |
| 39 | 39 | #define PCI_CLK_66MHZ BIT(18) |
| 40 | −#define PCI_CLK_OE BIT(17) | |
| 41 | 40 | |
| 42 | 41 | #define GEMINI_GLOBAL_CLOCK_CONTROL 0x34 |
| 43 | 42 | #define PCI_CLKRUN_EN BIT(16) |
| @@ -159,9 +158,6 @@ static int gemini_pci_enable(struct clk_hw *hw) · 115 unmodified lines | ||
| 159 | 158 | |
| 160 | 159 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, |
| 161 | 160 | 0, PCI_CLKRUN_EN); |
| 162 | − regmap_update_bits(pciclk->map, | |
| 163 | − GEMINI_GLOBAL_MISC_CONTROL, | |
| 164 | − 0, PCI_CLK_OE); | |
| 165 | 161 | return 0; |
| 166 | 162 | } |
| 167 | 163 | |
| @@ -169,9 +165,6 @@ static void gemini_pci_disable(struct clk_hw *hw) · 1 unmodified line | ||
| 169 | 165 | { |
| 170 | 166 | struct clk_gemini_pci *pciclk = to_pciclk(hw); |
| 171 | 167 | |
| 172 | − regmap_update_bits(pciclk->map, | |
| 173 | − GEMINI_GLOBAL_MISC_CONTROL, | |
| 174 | − PCI_CLK_OE, 0); | |
| 175 | 168 | regmap_update_bits(pciclk->map, GEMINI_GLOBAL_CLOCK_CONTROL, |
| 176 | 169 | PCI_CLKRUN_EN, 0); |
| 177 | 170 | } |
| @@ -0,0 +1,431 @@ | ||
| 1 | +/* | |
| 2 | + * Synopsys HSDK SDP Generic PLL clock driver | |
| 3 | + * | |
| 4 | + * Copyright (C) 2017 Synopsys | |
| 5 | + * | |
| 6 | + * This file is licensed under the terms of the GNU General Public | |
| 7 | + * License version 2. This program is licensed "as is" without any | |
| 8 | + * warranty of any kind, whether express or implied. | |
| 9 | + */ | |
| 10 | + | |
| 11 | +#include <linux/clk-provider.h> | |
| 12 | +#include <linux/delay.h> | |
| 13 | +#include <linux/device.h> | |
| 14 | +#include <linux/err.h> | |
| 15 | +#include <linux/of.h> | |
| 16 | +#include <linux/of_address.h> | |
| 17 | +#include <linux/of_device.h> | |
| 18 | +#include <linux/platform_device.h> | |
| 19 | +#include <linux/slab.h> | |
| 20 | + | |
| 21 | +#define CGU_PLL_CTRL 0x000 /* ARC PLL control register */ | |
| 22 | +#define CGU_PLL_STATUS 0x004 /* ARC PLL status register */ | |
| 23 | +#define CGU_PLL_FMEAS 0x008 /* ARC PLL frequency measurement register */ | |
| 24 | +#define CGU_PLL_MON 0x00C /* ARC PLL monitor register */ | |
| 25 | + | |
| 26 | +#define CGU_PLL_CTRL_ODIV_SHIFT 2 | |
| 27 | +#define CGU_PLL_CTRL_IDIV_SHIFT 4 | |
| 28 | +#define CGU_PLL_CTRL_FBDIV_SHIFT 9 | |
| 29 | +#define CGU_PLL_CTRL_BAND_SHIFT 20 | |
| 30 | + | |
| 31 | +#define CGU_PLL_CTRL_ODIV_MASK GENMASK(3, CGU_PLL_CTRL_ODIV_SHIFT) | |
| 32 | +#define CGU_PLL_CTRL_IDIV_MASK GENMASK(8, CGU_PLL_CTRL_IDIV_SHIFT) | |
| 33 | +#define CGU_PLL_CTRL_FBDIV_MASK GENMASK(15, CGU_PLL_CTRL_FBDIV_SHIFT) | |
| 34 | + | |
| 35 | +#define CGU_PLL_CTRL_PD BIT(0) | |
| 36 | +#define CGU_PLL_CTRL_BYPASS BIT(1) | |
| 37 | + | |
| 38 | +#define CGU_PLL_STATUS_LOCK BIT(0) | |
| 39 | +#define CGU_PLL_STATUS_ERR BIT(1) | |
| 40 | + | |
| 41 | +#define HSDK_PLL_MAX_LOCK_TIME 100 /* 100 us */ | |
| 42 | + | |
| 43 | +#define CGU_PLL_SOURCE_MAX 1 | |
| 44 | + | |
| 45 | +#define CORE_IF_CLK_THRESHOLD_HZ 500000000 | |
| 46 | +#define CREG_CORE_IF_CLK_DIV_1 0x0 | |
| 47 | +#define CREG_CORE_IF_CLK_DIV_2 0x1 | |
| 48 | + | |
| 49 | +struct hsdk_pll_cfg { | |
| 50 | + u32 rate; | |
| 51 | + u32 idiv; | |
| 52 | + u32 fbdiv; | |
| 53 | + u32 odiv; | |
| 54 | + u32 band; | |
| 55 | +}; | |
| 56 | + | |
| 57 | +static const struct hsdk_pll_cfg asdt_pll_cfg[] = { | |
| 58 | + { 100000000, 0, 11, 3, 0 }, | |
| 59 | + { 133000000, 0, 15, 3, 0 }, | |
| 60 | + { 200000000, 1, 47, 3, 0 }, | |
| 61 | + { 233000000, 1, 27, 2, 0 }, | |
| 62 | + { 300000000, 1, 35, 2, 0 }, | |
| 63 | + { 333000000, 1, 39, 2, 0 }, | |
| 64 | + { 400000000, 1, 47, 2, 0 }, | |
| 65 | + { 500000000, 0, 14, 1, 0 }, | |
| 66 | + { 600000000, 0, 17, 1, 0 }, | |
| 67 | + { 700000000, 0, 20, 1, 0 }, | |
| 68 | + { 800000000, 0, 23, 1, 0 }, | |
| 69 | + { 900000000, 1, 26, 0, 0 }, | |
| 70 | + { 1000000000, 1, 29, 0, 0 }, | |
| 71 | + { 1100000000, 1, 32, 0, 0 }, | |
| 72 | + { 1200000000, 1, 35, 0, 0 }, | |
| 73 | + { 1300000000, 1, 38, 0, 0 }, | |
| 74 | + { 1400000000, 1, 41, 0, 0 }, | |
| 75 | + { 1500000000, 1, 44, 0, 0 }, | |
| 76 | + { 1600000000, 1, 47, 0, 0 }, | |
| 77 | + {} | |
| 78 | +}; | |
| 79 | + | |
| 80 | +static const struct hsdk_pll_cfg hdmi_pll_cfg[] = { | |
| 81 | + { 297000000, 0, 21, 2, 0 }, | |
| 82 | + { 540000000, 0, 19, 1, 0 }, | |
| 83 | + { 594000000, 0, 21, 1, 0 }, | |
| 84 | + {} | |
| 85 | +}; | |
| 86 | + | |
| 87 | +struct hsdk_pll_clk { | |
| 88 | + struct clk_hw hw; | |
| 89 | + void __iomem *regs; | |
| 90 | + void __iomem *spec_regs; | |
| 91 | + const struct hsdk_pll_devdata *pll_devdata; | |
| 92 | + struct device *dev; | |
| 93 | +}; | |
| 94 | + | |
| 95 | +struct hsdk_pll_devdata { | |
| 96 | + const struct hsdk_pll_cfg *pll_cfg; | |
| 97 | + int (*update_rate)(struct hsdk_pll_clk *clk, unsigned long rate, | |
| 98 | + const struct hsdk_pll_cfg *cfg); | |
| 99 | +}; | |
| 100 | + | |
| 101 | +static int hsdk_pll_core_update_rate(struct hsdk_pll_clk *, unsigned long, | |
| 102 | + const struct hsdk_pll_cfg *); | |
| 103 | +static int hsdk_pll_comm_update_rate(struct hsdk_pll_clk *, unsigned long, | |
| 104 | + const struct hsdk_pll_cfg *); | |
| 105 | + | |
| 106 | +static const struct hsdk_pll_devdata core_pll_devdata = { | |
| 107 | + .pll_cfg = asdt_pll_cfg, | |
| 108 | + .update_rate = hsdk_pll_core_update_rate, | |
| 109 | +}; | |
| 110 | + | |
| 111 | +static const struct hsdk_pll_devdata sdt_pll_devdata = { | |
| 112 | + .pll_cfg = asdt_pll_cfg, | |
| 113 | + .update_rate = hsdk_pll_comm_update_rate, | |
| 114 | +}; | |
| 115 | + | |
| 116 | +static const struct hsdk_pll_devdata hdmi_pll_devdata = { | |
| 117 | + .pll_cfg = hdmi_pll_cfg, | |
| 118 | + .update_rate = hsdk_pll_comm_update_rate, | |
| 119 | +}; | |
| 120 | + | |
| 121 | +static inline void hsdk_pll_write(struct hsdk_pll_clk *clk, u32 reg, u32 val) | |
| 122 | +{ | |
| 123 | + iowrite32(val, clk->regs + reg); | |
| 124 | +} | |
| 125 | + | |
| 126 | +static inline u32 hsdk_pll_read(struct hsdk_pll_clk *clk, u32 reg) | |
| 127 | +{ | |
| 128 | + return ioread32(clk->regs + reg); | |
| 129 | +} | |
| 130 | + | |
| 131 | +static inline void hsdk_pll_set_cfg(struct hsdk_pll_clk *clk, | |
| 132 | + const struct hsdk_pll_cfg *cfg) | |
| 133 | +{ | |
| 134 | + u32 val = 0; | |
| 135 | + | |
| 136 | + /* Powerdown and Bypass bits should be cleared */ | |
| 137 | + val |= cfg->idiv << CGU_PLL_CTRL_IDIV_SHIFT; | |
| 138 | + val |= cfg->fbdiv << CGU_PLL_CTRL_FBDIV_SHIFT; | |
| 139 | + val |= cfg->odiv << CGU_PLL_CTRL_ODIV_SHIFT; | |
| 140 | + val |= cfg->band << CGU_PLL_CTRL_BAND_SHIFT; | |
| 141 | + | |
| 142 | + dev_dbg(clk->dev, "write configurarion: %#x\n", val); | |
| 143 | + | |
| 144 | + hsdk_pll_write(clk, CGU_PLL_CTRL, val); | |
| 145 | +} | |
| 146 | + | |
| 147 | +static inline bool hsdk_pll_is_locked(struct hsdk_pll_clk *clk) | |
| 148 | +{ | |
| 149 | + return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_LOCK); | |
| 150 | +} | |
| 151 | + | |
| 152 | +static inline bool hsdk_pll_is_err(struct hsdk_pll_clk *clk) | |
| 153 | +{ | |
| 154 | + return !!(hsdk_pll_read(clk, CGU_PLL_STATUS) & CGU_PLL_STATUS_ERR); | |
| 155 | +} | |
| 156 | + | |
| 157 | +static inline struct hsdk_pll_clk *to_hsdk_pll_clk(struct clk_hw *hw) | |
| 158 | +{ | |
| 159 | + return container_of(hw, struct hsdk_pll_clk, hw); | |
| 160 | +} | |
| 161 | + | |
| 162 | +static unsigned long hsdk_pll_recalc_rate(struct clk_hw *hw, | |
| 163 | + unsigned long parent_rate) | |
| 164 | +{ | |
| 165 | + u32 val; | |
| 166 | + u64 rate; | |
| 167 | + u32 idiv, fbdiv, odiv; | |
| 168 | + struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | |
| 169 | + | |
| 170 | + val = hsdk_pll_read(clk, CGU_PLL_CTRL); | |
| 171 | + | |
| 172 | + dev_dbg(clk->dev, "current configurarion: %#x\n", val); | |
| 173 | + | |
| 174 | + /* Check if PLL is disabled */ | |
| 175 | + if (val & CGU_PLL_CTRL_PD) | |
| 176 | + return 0; | |
| 177 | + | |
| 178 | + /* Check if PLL is bypassed */ | |
| 179 | + if (val & CGU_PLL_CTRL_BYPASS) | |
| 180 | + return parent_rate; | |
| 181 | + | |
| 182 | + /* input divider = reg.idiv + 1 */ | |
| 183 | + idiv = 1 + ((val & CGU_PLL_CTRL_IDIV_MASK) >> CGU_PLL_CTRL_IDIV_SHIFT); | |
| 184 | + /* fb divider = 2*(reg.fbdiv + 1) */ | |
| 185 | + fbdiv = 2 * (1 + ((val & CGU_PLL_CTRL_FBDIV_MASK) >> CGU_PLL_CTRL_FBDIV_SHIFT)); | |
| 186 | + /* output divider = 2^(reg.odiv) */ | |
| 187 | + odiv = 1 << ((val & CGU_PLL_CTRL_ODIV_MASK) >> CGU_PLL_CTRL_ODIV_SHIFT); | |
| 188 | + | |
| 189 | + rate = (u64)parent_rate * fbdiv; | |
| 190 | + do_div(rate, idiv * odiv); | |
| 191 | + | |
| 192 | + return rate; | |
| 193 | +} | |
| 194 | + | |
| 195 | +static long hsdk_pll_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 196 | + unsigned long *prate) | |
| 197 | +{ | |
| 198 | + int i; | |
| 199 | + unsigned long best_rate; | |
| 200 | + struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | |
| 201 | + const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; | |
| 202 | + | |
| 203 | + if (pll_cfg[0].rate == 0) | |
| 204 | + return -EINVAL; | |
| 205 | + | |
| 206 | + best_rate = pll_cfg[0].rate; | |
| 207 | + | |
| 208 | + for (i = 1; pll_cfg[i].rate != 0; i++) { | |
| 209 | + if (abs(rate - pll_cfg[i].rate) < abs(rate - best_rate)) | |
| 210 | + best_rate = pll_cfg[i].rate; | |
| 211 | + } | |
| 212 | + | |
| 213 | + dev_dbg(clk->dev, "chosen best rate: %lu\n", best_rate); | |
| 214 | + | |
| 215 | + return best_rate; | |
| 216 | +} | |
| 217 | + | |
| 218 | +static int hsdk_pll_comm_update_rate(struct hsdk_pll_clk *clk, | |
| 219 | + unsigned long rate, | |
| 220 | + const struct hsdk_pll_cfg *cfg) | |
| 221 | +{ | |
| 222 | + hsdk_pll_set_cfg(clk, cfg); | |
| 223 | + | |
| 224 | + /* | |
| 225 | + * Wait until CGU relocks and check error status. | |
| 226 | + * If after timeout CGU is unlocked yet return error. | |
| 227 | + */ | |
| 228 | + udelay(HSDK_PLL_MAX_LOCK_TIME); | |
| 229 | + if (!hsdk_pll_is_locked(clk)) | |
| 230 | + return -ETIMEDOUT; | |
| 231 | + | |
| 232 | + if (hsdk_pll_is_err(clk)) | |
| 233 | + return -EINVAL; | |
| 234 | + | |
| 235 | + return 0; | |
| 236 | +} | |
| 237 | + | |
| 238 | +static int hsdk_pll_core_update_rate(struct hsdk_pll_clk *clk, | |
| 239 | + unsigned long rate, | |
| 240 | + const struct hsdk_pll_cfg *cfg) | |
| 241 | +{ | |
| 242 | + /* | |
| 243 | + * When core clock exceeds 500MHz, the divider for the interface | |
| 244 | + * clock must be programmed to div-by-2. | |
| 245 | + */ | |
| 246 | + if (rate > CORE_IF_CLK_THRESHOLD_HZ) | |
| 247 | + iowrite32(CREG_CORE_IF_CLK_DIV_2, clk->spec_regs); | |
| 248 | + | |
| 249 | + hsdk_pll_set_cfg(clk, cfg); | |
| 250 | + | |
| 251 | + /* | |
| 252 | + * Wait until CGU relocks and check error status. | |
| 253 | + * If after timeout CGU is unlocked yet return error. | |
| 254 | + */ | |
| 255 | + udelay(HSDK_PLL_MAX_LOCK_TIME); | |
| 256 | + if (!hsdk_pll_is_locked(clk)) | |
| 257 | + return -ETIMEDOUT; | |
| 258 | + | |
| 259 | + if (hsdk_pll_is_err(clk)) | |
| 260 | + return -EINVAL; | |
| 261 | + | |
| 262 | + /* | |
| 263 | + * Program divider to div-by-1 if we succesfuly set core clock below | |
| 264 | + * 500MHz threshold. | |
| 265 | + */ | |
| 266 | + if (rate <= CORE_IF_CLK_THRESHOLD_HZ) | |
| 267 | + iowrite32(CREG_CORE_IF_CLK_DIV_1, clk->spec_regs); | |
| 268 | + | |
| 269 | + return 0; | |
| 270 | +} | |
| 271 | + | |
| 272 | +static int hsdk_pll_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 273 | + unsigned long parent_rate) | |
| 274 | +{ | |
| 275 | + int i; | |
| 276 | + struct hsdk_pll_clk *clk = to_hsdk_pll_clk(hw); | |
| 277 | + const struct hsdk_pll_cfg *pll_cfg = clk->pll_devdata->pll_cfg; | |
| 278 | + | |
| 279 | + for (i = 0; pll_cfg[i].rate != 0; i++) { | |
| 280 | + if (pll_cfg[i].rate == rate) { | |
| 281 | + return clk->pll_devdata->update_rate(clk, rate, | |
| 282 | + &pll_cfg[i]); | |
| 283 | + } | |
| 284 | + } | |
| 285 | + | |
| 286 | + dev_err(clk->dev, "invalid rate=%ld, parent_rate=%ld\n", rate, | |
| 287 | + parent_rate); | |
| 288 | + | |
| 289 | + return -EINVAL; | |
| 290 | +} | |
| 291 | + | |
| 292 | +static const struct clk_ops hsdk_pll_ops = { | |
| 293 | + .recalc_rate = hsdk_pll_recalc_rate, | |
| 294 | + .round_rate = hsdk_pll_round_rate, | |
| 295 | + .set_rate = hsdk_pll_set_rate, | |
| 296 | +}; | |
| 297 | + | |
| 298 | +static int hsdk_pll_clk_probe(struct platform_device *pdev) | |
| 299 | +{ | |
| 300 | + int ret; | |
| 301 | + struct resource *mem; | |
| 302 | + const char *parent_name; | |
| 303 | + unsigned int num_parents; | |
| 304 | + struct hsdk_pll_clk *pll_clk; | |
| 305 | + struct clk_init_data init = { }; | |
| 306 | + struct device *dev = &pdev->dev; | |
| 307 | + | |
| 308 | + pll_clk = devm_kzalloc(dev, sizeof(*pll_clk), GFP_KERNEL); | |
| 309 | + if (!pll_clk) | |
| 310 | + return -ENOMEM; | |
| 311 | + | |
| 312 | + mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 313 | + pll_clk->regs = devm_ioremap_resource(dev, mem); | |
| 314 | + if (IS_ERR(pll_clk->regs)) | |
| 315 | + return PTR_ERR(pll_clk->regs); | |
| 316 | + | |
| 317 | + init.name = dev->of_node->name; | |
| 318 | + init.ops = &hsdk_pll_ops; | |
| 319 | + parent_name = of_clk_get_parent_name(dev->of_node, 0); | |
| 320 | + init.parent_names = &parent_name; | |
| 321 | + num_parents = of_clk_get_parent_count(dev->of_node); | |
| 322 | + if (num_parents == 0 || num_parents > CGU_PLL_SOURCE_MAX) { | |
| 323 | + dev_err(dev, "wrong clock parents number: %u\n", num_parents); | |
| 324 | + return -EINVAL; | |
| 325 | + } | |
| 326 | + init.num_parents = num_parents; | |
| 327 | + | |
| 328 | + pll_clk->hw.init = &init; | |
| 329 | + pll_clk->dev = dev; | |
| 330 | + pll_clk->pll_devdata = of_device_get_match_data(dev); | |
| 331 | + | |
| 332 | + if (!pll_clk->pll_devdata) { | |
| 333 | + dev_err(dev, "No OF match data provided\n"); | |
| 334 | + return -EINVAL; | |
| 335 | + } | |
| 336 | + | |
| 337 | + ret = devm_clk_hw_register(dev, &pll_clk->hw); | |
| 338 | + if (ret) { | |
| 339 | + dev_err(dev, "failed to register %s clock\n", init.name); | |
| 340 | + return ret; | |
| 341 | + } | |
| 342 | + | |
| 343 | + return of_clk_add_hw_provider(dev->of_node, of_clk_hw_simple_get, | |
| 344 | + &pll_clk->hw); | |
| 345 | +} | |
| 346 | + | |
| 347 | +static int hsdk_pll_clk_remove(struct platform_device *pdev) | |
| 348 | +{ | |
| 349 | + of_clk_del_provider(pdev->dev.of_node); | |
| 350 | + return 0; | |
| 351 | +} | |
| 352 | + | |
| 353 | +static void __init of_hsdk_pll_clk_setup(struct device_node *node) | |
| 354 | +{ | |
| 355 | + int ret; | |
| 356 | + const char *parent_name; | |
| 357 | + unsigned int num_parents; | |
| 358 | + struct hsdk_pll_clk *pll_clk; | |
| 359 | + struct clk_init_data init = { }; | |
| 360 | + | |
| 361 | + pll_clk = kzalloc(sizeof(*pll_clk), GFP_KERNEL); | |
| 362 | + if (!pll_clk) | |
| 363 | + return; | |
| 364 | + | |
| 365 | + pll_clk->regs = of_iomap(node, 0); | |
| 366 | + if (!pll_clk->regs) { | |
| 367 | + pr_err("failed to map pll registers\n"); | |
| 368 | + goto err_free_pll_clk; | |
| 369 | + } | |
| 370 | + | |
| 371 | + pll_clk->spec_regs = of_iomap(node, 1); | |
| 372 | + if (!pll_clk->spec_regs) { | |
| 373 | + pr_err("failed to map pll registers\n"); | |
| 374 | + goto err_unmap_comm_regs; | |
| 375 | + } | |
| 376 | + | |
| 377 | + init.name = node->name; | |
| 378 | + init.ops = &hsdk_pll_ops; | |
| 379 | + parent_name = of_clk_get_parent_name(node, 0); | |
| 380 | + init.parent_names = &parent_name; | |
| 381 | + num_parents = of_clk_get_parent_count(node); | |
| 382 | + if (num_parents > CGU_PLL_SOURCE_MAX) { | |
| 383 | + pr_err("too much clock parents: %u\n", num_parents); | |
| 384 | + goto err_unmap_spec_regs; | |
| 385 | + } | |
| 386 | + init.num_parents = num_parents; | |
| 387 | + | |
| 388 | + pll_clk->hw.init = &init; | |
| 389 | + pll_clk->pll_devdata = &core_pll_devdata; | |
| 390 | + | |
| 391 | + ret = clk_hw_register(NULL, &pll_clk->hw); | |
| 392 | + if (ret) { | |
| 393 | + pr_err("failed to register %s clock\n", node->name); | |
| 394 | + goto err_unmap_spec_regs; | |
| 395 | + } | |
| 396 | + | |
| 397 | + ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clk->hw); | |
| 398 | + if (ret) { | |
| 399 | + pr_err("failed to add hw provider for %s clock\n", node->name); | |
| 400 | + goto err_unmap_spec_regs; | |
| 401 | + } | |
| 402 | + | |
| 403 | + return; | |
| 404 | + | |
| 405 | +err_unmap_spec_regs: | |
| 406 | + iounmap(pll_clk->spec_regs); | |
| 407 | +err_unmap_comm_regs: | |
| 408 | + iounmap(pll_clk->regs); | |
| 409 | +err_free_pll_clk: | |
| 410 | + kfree(pll_clk); | |
| 411 | +} | |
| 412 | + | |
| 413 | +/* Core PLL needed early for ARC cpus timers */ | |
| 414 | +CLK_OF_DECLARE(hsdk_pll_clock, "snps,hsdk-core-pll-clock", | |
| 415 | +of_hsdk_pll_clk_setup); | |
| 416 | + | |
| 417 | +static const struct of_device_id hsdk_pll_clk_id[] = { | |
| 418 | + { .compatible = "snps,hsdk-gp-pll-clock", .data = &sdt_pll_devdata}, | |
| 419 | + { .compatible = "snps,hsdk-hdmi-pll-clock", .data = &hdmi_pll_devdata}, | |
| 420 | + { } | |
| 421 | +}; | |
| 422 | + | |
| 423 | +static struct platform_driver hsdk_pll_clk_driver = { | |
| 424 | + .driver = { | |
| 425 | + .name = "hsdk-gp-pll-clock", | |
| 426 | + .of_match_table = hsdk_pll_clk_id, | |
| 427 | + }, | |
| 428 | + .probe = hsdk_pll_clk_probe, | |
| 429 | + .remove = hsdk_pll_clk_remove, | |
| 430 | +}; | |
| 431 | +builtin_platform_driver(hsdk_pll_clk_driver); | |
| @@ -1,390 +0,0 @@ | ||
| 1 | −/* | |
| 2 | − * Copyright (C) 2013-2015 FUJITSU SEMICONDUCTOR LIMITED | |
| 3 | − * Copyright (C) 2015 Linaro Ltd. | |
| 4 | − * | |
| 5 | − * This program is free software: you can redistribute it and/or modify | |
| 6 | − * it under the terms of the GNU General Public License as published by | |
| 7 | − * the Free Software Foundation, version 2 of the License. | |
| 8 | − * | |
| 9 | − * This program is distributed in the hope that it will be useful, | |
| 10 | − * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | − * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | − * GNU General Public License for more details. | |
| 13 | − */ | |
| 14 | − | |
| 15 | −#include <linux/clkdev.h> | |
| 16 | −#include <linux/err.h> | |
| 17 | −#include <linux/io.h> | |
| 18 | −#include <linux/of.h> | |
| 19 | −#include <linux/cpu.h> | |
| 20 | −#include <linux/clk-provider.h> | |
| 21 | −#include <linux/spinlock.h> | |
| 22 | −#include <linux/module.h> | |
| 23 | −#include <linux/topology.h> | |
| 24 | −#include <linux/mailbox_client.h> | |
| 25 | −#include <linux/platform_device.h> | |
| 26 | − | |
| 27 | −#include <soc/mb86s7x/scb_mhu.h> | |
| 28 | − | |
| 29 | −#define to_crg_clk(p) container_of(p, struct crg_clk, hw) | |
| 30 | −#define to_clc_clk(p) container_of(p, struct cl_clk, hw) | |
| 31 | − | |
| 32 | −struct mb86s7x_peri_clk { | |
| 33 | − u32 payload_size; | |
| 34 | − u32 cntrlr; | |
| 35 | − u32 domain; | |
| 36 | − u32 port; | |
| 37 | − u32 en; | |
| 38 | − u64 frequency; | |
| 39 | −} __packed __aligned(4); | |
| 40 | − | |
| 41 | −struct hack_rate { | |
| 42 | − unsigned clk_id; | |
| 43 | − unsigned long rate; | |
| 44 | − int gated; | |
| 45 | −}; | |
| 46 | − | |
| 47 | −struct crg_clk { | |
| 48 | − struct clk_hw hw; | |
| 49 | − u8 cntrlr, domain, port; | |
| 50 | −}; | |
| 51 | − | |
| 52 | −static int crg_gate_control(struct clk_hw *hw, int en) | |
| 53 | −{ | |
| 54 | − struct crg_clk *crgclk = to_crg_clk(hw); | |
| 55 | − struct mb86s7x_peri_clk cmd; | |
| 56 | − int ret; | |
| 57 | − | |
| 58 | − cmd.payload_size = sizeof(cmd); | |
| 59 | − cmd.cntrlr = crgclk->cntrlr; | |
| 60 | − cmd.domain = crgclk->domain; | |
| 61 | − cmd.port = crgclk->port; | |
| 62 | − cmd.en = en; | |
| 63 | − | |
| 64 | − /* Port is UngatedCLK */ | |
| 65 | − if (cmd.port == 8) | |
| 66 | − return en ? 0 : -EINVAL; | |
| 67 | − | |
| 68 | − pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u En-%u}\n", | |
| 69 | − __func__, __LINE__, cmd.cntrlr, | |
| 70 | − cmd.domain, cmd.port, cmd.en); | |
| 71 | − | |
| 72 | − ret = mb86s7x_send_packet(CMD_PERI_CLOCK_GATE_SET_REQ, | |
| 73 | − &cmd, sizeof(cmd)); | |
| 74 | − if (ret < 0) { | |
| 75 | − pr_err("%s:%d failed!\n", __func__, __LINE__); | |
| 76 | − return ret; | |
| 77 | − } | |
| 78 | − | |
| 79 | − pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u En-%u}\n", | |
| 80 | − __func__, __LINE__, cmd.cntrlr, | |
| 81 | − cmd.domain, cmd.port, cmd.en); | |
| 82 | − | |
| 83 | − /* If the request was rejected */ | |
| 84 | − if (cmd.en != en) | |
| 85 | − ret = -EINVAL; | |
| 86 | − else | |
| 87 | − ret = 0; | |
| 88 | − | |
| 89 | − return ret; | |
| 90 | −} | |
| 91 | − | |
| 92 | −static int crg_port_prepare(struct clk_hw *hw) | |
| 93 | −{ | |
| 94 | − return crg_gate_control(hw, 1); | |
| 95 | −} | |
| 96 | − | |
| 97 | −static void crg_port_unprepare(struct clk_hw *hw) | |
| 98 | −{ | |
| 99 | − crg_gate_control(hw, 0); | |
| 100 | −} | |
| 101 | − | |
| 102 | −static int | |
| 103 | −crg_rate_control(struct clk_hw *hw, int set, unsigned long *rate) | |
| 104 | −{ | |
| 105 | − struct crg_clk *crgclk = to_crg_clk(hw); | |
| 106 | − struct mb86s7x_peri_clk cmd; | |
| 107 | − int code, ret; | |
| 108 | − | |
| 109 | − cmd.payload_size = sizeof(cmd); | |
| 110 | − cmd.cntrlr = crgclk->cntrlr; | |
| 111 | − cmd.domain = crgclk->domain; | |
| 112 | − cmd.port = crgclk->port; | |
| 113 | − cmd.frequency = *rate; | |
| 114 | − | |
| 115 | − if (set) { | |
| 116 | − code = CMD_PERI_CLOCK_RATE_SET_REQ; | |
| 117 | − pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n", | |
| 118 | − __func__, __LINE__, cmd.cntrlr, | |
| 119 | − cmd.domain, cmd.port, cmd.frequency); | |
| 120 | − } else { | |
| 121 | − code = CMD_PERI_CLOCK_RATE_GET_REQ; | |
| 122 | − pr_debug("%s:%d CMD Cntrlr-%u Dom-%u Port-%u Rate-GET}\n", | |
| 123 | − __func__, __LINE__, cmd.cntrlr, | |
| 124 | − cmd.domain, cmd.port); | |
| 125 | − } | |
| 126 | − | |
| 127 | − ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd)); | |
| 128 | − if (ret < 0) { | |
| 129 | − pr_err("%s:%d failed!\n", __func__, __LINE__); | |
| 130 | − return ret; | |
| 131 | − } | |
| 132 | − | |
| 133 | − if (set) | |
| 134 | − pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-SET %lluHz}\n", | |
| 135 | − __func__, __LINE__, cmd.cntrlr, | |
| 136 | − cmd.domain, cmd.port, cmd.frequency); | |
| 137 | − else | |
| 138 | − pr_debug("%s:%d REP Cntrlr-%u Dom-%u Port-%u Rate-GOT %lluHz}\n", | |
| 139 | − __func__, __LINE__, cmd.cntrlr, | |
| 140 | − cmd.domain, cmd.port, cmd.frequency); | |
| 141 | − | |
| 142 | − *rate = cmd.frequency; | |
| 143 | − return 0; | |
| 144 | −} | |
| 145 | − | |
| 146 | −static unsigned long | |
| 147 | −crg_port_recalc_rate(struct clk_hw *hw, unsigned long parent_rate) | |
| 148 | −{ | |
| 149 | − unsigned long rate; | |
| 150 | − | |
| 151 | − crg_rate_control(hw, 0, &rate); | |
| 152 | − | |
| 153 | − return rate; | |
| 154 | −} | |
| 155 | − | |
| 156 | −static long | |
| 157 | −crg_port_round_rate(struct clk_hw *hw, | |
| 158 | − unsigned long rate, unsigned long *pr) | |
| 159 | −{ | |
| 160 | − return rate; | |
| 161 | −} | |
| 162 | − | |
| 163 | −static int | |
| 164 | −crg_port_set_rate(struct clk_hw *hw, | |
| 165 | − unsigned long rate, unsigned long parent_rate) | |
| 166 | −{ | |
| 167 | − return crg_rate_control(hw, 1, &rate); | |
| 168 | −} | |
| 169 | − | |
| 170 | −const struct clk_ops crg_port_ops = { | |
| 171 | − .prepare = crg_port_prepare, | |
| 172 | − .unprepare = crg_port_unprepare, | |
| 173 | − .recalc_rate = crg_port_recalc_rate, | |
| 174 | − .round_rate = crg_port_round_rate, | |
| 175 | − .set_rate = crg_port_set_rate, | |
| 176 | −}; | |
| 177 | − | |
| 178 | −struct mb86s70_crg11 { | |
| 179 | − struct mutex lock; /* protects CLK populating and searching */ | |
| 180 | −}; | |
| 181 | − | |
| 182 | −static struct clk *crg11_get(struct of_phandle_args *clkspec, void *data) | |
| 183 | −{ | |
| 184 | − struct mb86s70_crg11 *crg11 = data; | |
| 185 | − struct clk_init_data init; | |
| 186 | − u32 cntrlr, domain, port; | |
| 187 | − struct crg_clk *crgclk; | |
| 188 | − struct clk *clk; | |
| 189 | − char clkp[20]; | |
| 190 | − | |
| 191 | − if (clkspec->args_count != 3) | |
| 192 | − return ERR_PTR(-EINVAL); | |
| 193 | − | |
| 194 | − cntrlr = clkspec->args[0]; | |
| 195 | − domain = clkspec->args[1]; | |
| 196 | − port = clkspec->args[2]; | |
| 197 | − | |
| 198 | − if (port > 7) | |
| 199 | − snprintf(clkp, 20, "UngatedCLK%d_%X", cntrlr, domain); | |
| 200 | − else | |
| 201 | − snprintf(clkp, 20, "CLK%d_%X_%d", cntrlr, domain, port); | |
| 202 | − | |
| 203 | − mutex_lock(&crg11->lock); | |
| 204 | − | |
| 205 | − clk = __clk_lookup(clkp); | |
| 206 | − if (clk) { | |
| 207 | − mutex_unlock(&crg11->lock); | |
| 208 | − return clk; | |
| 209 | − } | |
| 210 | − | |
| 211 | − crgclk = kzalloc(sizeof(*crgclk), GFP_KERNEL); | |
| 212 | − if (!crgclk) { | |
| 213 | − mutex_unlock(&crg11->lock); | |
| 214 | − return ERR_PTR(-ENOMEM); | |
| 215 | − } | |
| 216 | − | |
| 217 | − init.name = clkp; | |
| 218 | − init.num_parents = 0; | |
| 219 | − init.ops = &crg_port_ops; | |
| 220 | − init.flags = 0; | |
| 221 | − crgclk->hw.init = &init; | |
| 222 | − crgclk->cntrlr = cntrlr; | |
| 223 | − crgclk->domain = domain; | |
| 224 | − crgclk->port = port; | |
| 225 | − clk = clk_register(NULL, &crgclk->hw); | |
| 226 | − if (IS_ERR(clk)) | |
| 227 | − pr_err("%s:%d Error!\n", __func__, __LINE__); | |
| 228 | − else | |
| 229 | − pr_debug("Registered %s\n", clkp); | |
| 230 | − | |
| 231 | − clk_register_clkdev(clk, clkp, NULL); | |
| 232 | − mutex_unlock(&crg11->lock); | |
| 233 | − return clk; | |
| 234 | −} | |
| 235 | − | |
| 236 | −static void __init crg_port_init(struct device_node *node) | |
| 237 | −{ | |
| 238 | − struct mb86s70_crg11 *crg11; | |
| 239 | − | |
| 240 | − crg11 = kzalloc(sizeof(*crg11), GFP_KERNEL); | |
| 241 | − if (!crg11) | |
| 242 | − return; | |
| 243 | − | |
| 244 | − mutex_init(&crg11->lock); | |
| 245 | − | |
| 246 | − of_clk_add_provider(node, crg11_get, crg11); | |
| 247 | −} | |
| 248 | −CLK_OF_DECLARE(crg11_gate, "fujitsu,mb86s70-crg11", crg_port_init); | |
| 249 | − | |
| 250 | −struct cl_clk { | |
| 251 | − struct clk_hw hw; | |
| 252 | − int cluster; | |
| 253 | −}; | |
| 254 | − | |
| 255 | −struct mb86s7x_cpu_freq { | |
| 256 | − u32 payload_size; | |
| 257 | − u32 cluster_class; | |
| 258 | − u32 cluster_id; | |
| 259 | − u32 cpu_id; | |
| 260 | − u64 frequency; | |
| 261 | −}; | |
| 262 | − | |
| 263 | −static void mhu_cluster_rate(struct clk_hw *hw, unsigned long *rate, int get) | |
| 264 | −{ | |
| 265 | − struct cl_clk *clc = to_clc_clk(hw); | |
| 266 | − struct mb86s7x_cpu_freq cmd; | |
| 267 | − int code, ret; | |
| 268 | − | |
| 269 | − cmd.payload_size = sizeof(cmd); | |
| 270 | − cmd.cluster_class = 0; | |
| 271 | − cmd.cluster_id = clc->cluster; | |
| 272 | − cmd.cpu_id = 0; | |
| 273 | − cmd.frequency = *rate; | |
| 274 | − | |
| 275 | − if (get) | |
| 276 | − code = CMD_CPU_CLOCK_RATE_GET_REQ; | |
| 277 | − else | |
| 278 | − code = CMD_CPU_CLOCK_RATE_SET_REQ; | |
| 279 | − | |
| 280 | − pr_debug("%s:%d CMD Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n", | |
| 281 | − __func__, __LINE__, cmd.cluster_class, | |
| 282 | − cmd.cluster_id, cmd.cpu_id, cmd.frequency); | |
| 283 | − | |
| 284 | − ret = mb86s7x_send_packet(code, &cmd, sizeof(cmd)); | |
| 285 | − if (ret < 0) { | |
| 286 | − pr_err("%s:%d failed!\n", __func__, __LINE__); | |
| 287 | − return; | |
| 288 | − } | |
| 289 | − | |
| 290 | − pr_debug("%s:%d REP Cl_Class-%u CL_ID-%u CPU_ID-%u Freq-%llu}\n", | |
| 291 | − __func__, __LINE__, cmd.cluster_class, | |
| 292 | − cmd.cluster_id, cmd.cpu_id, cmd.frequency); | |
| 293 | − | |
| 294 | − *rate = cmd.frequency; | |
| 295 | −} | |
| 296 | − | |
| 297 | −static unsigned long | |
| 298 | −clc_recalc_rate(struct clk_hw *hw, unsigned long unused) | |
| 299 | −{ | |
| 300 | − unsigned long rate; | |
| 301 | − | |
| 302 | − mhu_cluster_rate(hw, &rate, 1); | |
| 303 | − return rate; | |
| 304 | −} | |
| 305 | − | |
| 306 | −static long | |
| 307 | −clc_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 308 | − unsigned long *unused) | |
| 309 | −{ | |
| 310 | − return rate; | |
| 311 | −} | |
| 312 | − | |
| 313 | −static int | |
| 314 | −clc_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 315 | − unsigned long unused) | |
| 316 | −{ | |
| 317 | − unsigned long res = rate; | |
| 318 | − | |
| 319 | − mhu_cluster_rate(hw, &res, 0); | |
| 320 | − | |
| 321 | − return (res == rate) ? 0 : -EINVAL; | |
| 322 | −} | |
| 323 | − | |
| 324 | −static struct clk_ops clk_clc_ops = { | |
| 325 | − .recalc_rate = clc_recalc_rate, | |
| 326 | − .round_rate = clc_round_rate, | |
| 327 | − .set_rate = clc_set_rate, | |
| 328 | −}; | |
| 329 | − | |
| 330 | −static struct clk_hw *mb86s7x_clclk_register(struct device *cpu_dev) | |
| 331 | −{ | |
| 332 | − struct clk_init_data init; | |
| 333 | − struct cl_clk *clc; | |
| 334 | − int ret; | |
| 335 | − | |
| 336 | − clc = kzalloc(sizeof(*clc), GFP_KERNEL); | |
| 337 | − if (!clc) | |
| 338 | − return ERR_PTR(-ENOMEM); | |
| 339 | − | |
| 340 | − clc->hw.init = &init; | |
| 341 | − clc->cluster = topology_physical_package_id(cpu_dev->id); | |
| 342 | − | |
| 343 | − init.name = dev_name(cpu_dev); | |
| 344 | − init.ops = &clk_clc_ops; | |
| 345 | − init.flags = CLK_GET_RATE_NOCACHE; | |
| 346 | − init.num_parents = 0; | |
| 347 | − | |
| 348 | − ret = devm_clk_hw_register(cpu_dev, &clc->hw); | |
| 349 | − if (ret) | |
| 350 | − return ERR_PTR(ret); | |
| 351 | − return &clc->hw; | |
| 352 | −} | |
| 353 | − | |
| 354 | −static int mb86s7x_clclk_of_init(void) | |
| 355 | −{ | |
| 356 | − int cpu, ret = -ENODEV; | |
| 357 | − struct device_node *np; | |
| 358 | − struct clk_hw *hw; | |
| 359 | − | |
| 360 | − np = of_find_compatible_node(NULL, NULL, "fujitsu,mb86s70-scb-1.0"); | |
| 361 | − if (!np || !of_device_is_available(np)) | |
| 362 | − goto exit; | |
| 363 | − | |
| 364 | − for_each_possible_cpu(cpu) { | |
| 365 | − struct device *cpu_dev = get_cpu_device(cpu); | |
| 366 | − | |
| 367 | − if (!cpu_dev) { | |
| 368 | − pr_err("failed to get cpu%d device\n", cpu); | |
| 369 | − continue; | |
| 370 | − } | |
| 371 | − | |
| 372 | − hw = mb86s7x_clclk_register(cpu_dev); | |
| 373 | − if (IS_ERR(hw)) { | |
| 374 | − pr_err("failed to register cpu%d clock\n", cpu); | |
| 375 | − continue; | |
| 376 | − } | |
| 377 | − if (clk_hw_register_clkdev(hw, NULL, dev_name(cpu_dev))) { | |
| 378 | − pr_err("failed to register cpu%d clock lookup\n", cpu); | |
| 379 | − continue; | |
| 380 | − } | |
| 381 | − pr_debug("registered clk for %s\n", dev_name(cpu_dev)); | |
| 382 | − } | |
| 383 | − ret = 0; | |
| 384 | − | |
| 385 | − platform_device_register_simple("arm-bL-cpufreq-dt", -1, NULL, 0); | |
| 386 | −exit: | |
| 387 | − of_node_put(np); | |
| 388 | − return ret; | |
| 389 | −} | |
| 390 | −module_init(mb86s7x_clclk_of_init); | |
| @@ -18,7 +18,7 @@ · 17 unmodified lines | ||
| 18 | 18 | |
| 19 | 19 | static void __init moxart_of_pll_clk_init(struct device_node *node) |
| 20 | 20 | { |
| 21 | − static void __iomem *base; | |
| 21 | + void __iomem *base; | |
| 22 | 22 | struct clk_hw *hw; |
| 23 | 23 | struct clk *ref_clk; |
| 24 | 24 | unsigned int mul; |
| @@ -30,7 +30,7 @@ static void __init moxart_of_pll_clk_init(struct device_node *node) · 5 unmodified lines | ||
| 30 | 30 | |
| 31 | 31 | base = of_iomap(node, 0); |
| 32 | 32 | if (!base) { |
| 33 | − pr_err("%s: of_iomap failed\n", node->full_name); | |
| 33 | + pr_err("%pOF: of_iomap failed\n", node); | |
| 34 | 34 | return; |
| 35 | 35 | } |
| 36 | 36 | |
| @@ -39,13 +39,13 @@ static void __init moxart_of_pll_clk_init(struct device_node *node) · 2 unmodified lines | ||
| 39 | 39 | |
| 40 | 40 | ref_clk = of_clk_get(node, 0); |
| 41 | 41 | if (IS_ERR(ref_clk)) { |
| 42 | − pr_err("%s: of_clk_get failed\n", node->full_name); | |
| 42 | + pr_err("%pOF: of_clk_get failed\n", node); | |
| 43 | 43 | return; |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | 46 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, mul, 1); |
| 47 | 47 | if (IS_ERR(hw)) { |
| 48 | − pr_err("%s: failed to register clock\n", node->full_name); | |
| 48 | + pr_err("%pOF: failed to register clock\n", node); | |
| 49 | 49 | return; |
| 50 | 50 | } |
| 51 | 51 | |
| @@ -57,7 +57,7 @@ CLK_OF_DECLARE(moxart_pll_clock, "moxa,moxart-pll-clock", · 5 unmodified lines | ||
| 57 | 57 | |
| 58 | 58 | static void __init moxart_of_apb_clk_init(struct device_node *node) |
| 59 | 59 | { |
| 60 | − static void __iomem *base; | |
| 60 | + void __iomem *base; | |
| 61 | 61 | struct clk_hw *hw; |
| 62 | 62 | struct clk *pll_clk; |
| 63 | 63 | unsigned int div, val; |
| @@ -70,7 +70,7 @@ static void __init moxart_of_apb_clk_init(struct device_node *node) · 6 unmodified lines | ||
| 70 | 70 | |
| 71 | 71 | base = of_iomap(node, 0); |
| 72 | 72 | if (!base) { |
| 73 | − pr_err("%s: of_iomap failed\n", node->full_name); | |
| 73 | + pr_err("%pOF: of_iomap failed\n", node); | |
| 74 | 74 | return; |
| 75 | 75 | } |
| 76 | 76 | |
| @@ -83,13 +83,13 @@ static void __init moxart_of_apb_clk_init(struct device_node *node) · 6 unmodified lines | ||
| 83 | 83 | |
| 84 | 84 | pll_clk = of_clk_get(node, 0); |
| 85 | 85 | if (IS_ERR(pll_clk)) { |
| 86 | − pr_err("%s: of_clk_get failed\n", node->full_name); | |
| 86 | + pr_err("%pOF: of_clk_get failed\n", node); | |
| 87 | 87 | return; |
| 88 | 88 | } |
| 89 | 89 | |
| 90 | 90 | hw = clk_hw_register_fixed_factor(NULL, name, parent_name, 0, 1, div); |
| 91 | 91 | if (IS_ERR(hw)) { |
| 92 | − pr_err("%s: failed to register clock\n", node->full_name); | |
| 92 | + pr_err("%pOF: failed to register clock\n", node); | |
| 93 | 93 | return; |
| 94 | 94 | } |
| 95 | 95 | |
| @@ -12,6 +12,7 @@ · 11 unmodified lines | ||
| 12 | 12 | |
| 13 | 13 | #include <linux/clk.h> |
| 14 | 14 | #include <linux/clk-provider.h> |
| 15 | +#include <linux/clkdev.h> | |
| 15 | 16 | #include <linux/fsl/guts.h> |
| 16 | 17 | #include <linux/io.h> |
| 17 | 18 | #include <linux/kernel.h> |
| @@ -536,6 +537,17 @@ static const struct clockgen_chipinfo chipinfo[] = { · 518 unmodified lines | ||
| 536 | 537 | .pll_mask = 0x07, |
| 537 | 538 | .flags = CG_PLL_8BIT, |
| 538 | 539 | }, |
| 540 | + { | |
| 541 | + .compat = "fsl,ls1088a-clockgen", | |
| 542 | + .cmux_groups = { | |
| 543 | + &clockgen2_cmux_cga12 | |
| 544 | + }, | |
| 545 | + .cmux_to_group = { | |
| 546 | + 0, 0, -1 | |
| 547 | + }, | |
| 548 | + .pll_mask = 0x07, | |
| 549 | + .flags = CG_VER3 | CG_LITTLE_ENDIAN, | |
| 550 | + }, | |
| 539 | 551 | { |
| 540 | 552 | .compat = "fsl,ls1012a-clockgen", |
| 541 | 553 | .cmux_groups = { |
| @@ -1113,6 +1125,7 @@ static void __init create_one_pll(struct clockgen *cg, int idx) · 571 unmodified lines | ||
| 1113 | 1125 | |
| 1114 | 1126 | for (i = 0; i < ARRAY_SIZE(pll->div); i++) { |
| 1115 | 1127 | struct clk *clk; |
| 1128 | + int ret; | |
| 1116 | 1129 | |
| 1117 | 1130 | snprintf(pll->div[i].name, sizeof(pll->div[i].name), |
| 1118 | 1131 | "cg-pll%d-div%d", idx, i + 1); |
| @@ -1126,6 +1139,11 @@ static void __init create_one_pll(struct clockgen *cg, int idx) · 7 unmodified lines | ||
| 1126 | 1139 | } |
| 1127 | 1140 | |
| 1128 | 1141 | pll->div[i].clk = clk; |
| 1142 | + ret = clk_register_clkdev(clk, pll->div[i].name, NULL); | |
| 1143 | + if (ret != 0) | |
| 1144 | + pr_err("%s: %s: register to lookup table failed %ld\n", | |
| 1145 | + __func__, pll->div[i].name, PTR_ERR(clk)); | |
| 1146 | + | |
| 1129 | 1147 | } |
| 1130 | 1148 | } |
| 1131 | 1149 | |
| @@ -1348,8 +1366,7 @@ static void __init clockgen_init(struct device_node *np) · 216 unmodified lines | ||
| 1348 | 1366 | } |
| 1349 | 1367 | |
| 1350 | 1368 | if (i == ARRAY_SIZE(chipinfo)) { |
| 1351 | − pr_err("%s: unknown clockgen node %s\n", __func__, | |
| 1352 | − np->full_name); | |
| 1369 | + pr_err("%s: unknown clockgen node %pOF\n", __func__, np); | |
| 1353 | 1370 | goto err; |
| 1354 | 1371 | } |
| 1355 | 1372 | clockgen.info = chipinfo[i]; |
| @@ -1362,8 +1379,8 @@ static void __init clockgen_init(struct device_node *np) · 6 unmodified lines | ||
| 1362 | 1379 | if (guts) { |
| 1363 | 1380 | clockgen.guts = of_iomap(guts, 0); |
| 1364 | 1381 | if (!clockgen.guts) { |
| 1365 | − pr_err("%s: Couldn't map %s regs\n", __func__, | |
| 1366 | − guts->full_name); | |
| 1382 | + pr_err("%s: Couldn't map %pOF regs\n", __func__, | |
| 1383 | + guts); | |
| 1367 | 1384 | } |
| 1368 | 1385 | } |
| 1369 | 1386 | |
| @@ -1398,6 +1415,7 @@ CLK_OF_DECLARE(qoriq_clockgen_ls1012a, "fsl,ls1012a-clockgen", clockgen_init); · 28 unmodified lines | ||
| 1398 | 1415 | CLK_OF_DECLARE(qoriq_clockgen_ls1021a, "fsl,ls1021a-clockgen", clockgen_init); |
| 1399 | 1416 | CLK_OF_DECLARE(qoriq_clockgen_ls1043a, "fsl,ls1043a-clockgen", clockgen_init); |
| 1400 | 1417 | CLK_OF_DECLARE(qoriq_clockgen_ls1046a, "fsl,ls1046a-clockgen", clockgen_init); |
| 1418 | +CLK_OF_DECLARE(qoriq_clockgen_ls1088a, "fsl,ls1088a-clockgen", clockgen_init); | |
| 1401 | 1419 | CLK_OF_DECLARE(qoriq_clockgen_ls2080a, "fsl,ls2080a-clockgen", clockgen_init); |
| 1402 | 1420 | |
| 1403 | 1421 | /* Legacy nodes */ |
| @@ -519,6 +519,11 @@ static int si5351_pll_set_rate(struct clk_hw *hw, unsigned long rate, · 518 unmodified lines | ||
| 519 | 519 | SI5351_CLK_INTEGER_MODE, |
| 520 | 520 | (hwdata->params.p2 == 0) ? SI5351_CLK_INTEGER_MODE : 0); |
| 521 | 521 | |
| 522 | + /* Do a pll soft reset on the affected pll */ | |
| 523 | + si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET, | |
| 524 | + hwdata->num == 0 ? SI5351_PLL_RESET_A : | |
| 525 | + SI5351_PLL_RESET_B); | |
| 526 | + | |
| 522 | 527 | dev_dbg(&hwdata->drvdata->client->dev, |
| 523 | 528 | "%s - %s: p1 = %lu, p2 = %lu, p3 = %lu, parent_rate = %lu, rate = %lu\n", |
| 524 | 529 | __func__, clk_hw_get_name(hw), |
| @@ -1091,13 +1096,6 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate, · 566 unmodified lines | ||
| 1091 | 1096 | si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num, |
| 1092 | 1097 | SI5351_CLK_POWERDOWN, 0); |
| 1093 | 1098 | |
| 1094 | − /* | |
| 1095 | − * Do a pll soft reset on both plls, needed in some cases to get | |
| 1096 | − * all outputs running. | |
| 1097 | − */ | |
| 1098 | − si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET, | |
| 1099 | − SI5351_PLL_RESET_A | SI5351_PLL_RESET_B); | |
| 1100 | − | |
| 1101 | 1099 | dev_dbg(&hwdata->drvdata->client->dev, |
| 1102 | 1100 | "%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n", |
| 1103 | 1101 | __func__, clk_hw_get_name(hw), (1 << rdiv), |
| @@ -1541,8 +1541,8 @@ static void __init stm32f4_rcc_init(struct device_node *np) · 1540 unmodified lines | ||
| 1541 | 1541 | base + gd->offset, gd->bit_idx, 0, &stm32f4_clk_lock); |
| 1542 | 1542 | |
| 1543 | 1543 | if (IS_ERR(clks[idx])) { |
| 1544 | − pr_err("%s: Unable to register leaf clock %s\n", | |
| 1545 | − np->full_name, gd->name); | |
| 1544 | + pr_err("%pOF: Unable to register leaf clock %s\n", | |
| 1545 | + np, gd->name); | |
| 1546 | 1546 | goto fail; |
| 1547 | 1547 | } |
| 1548 | 1548 | } |
| @@ -0,0 +1,1410 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) Gabriel Fernandez 2017 | |
| 3 | + * Author: Gabriel Fernandez <gabriel.fernandez@st.com> | |
| 4 | + * | |
| 5 | + * License terms: GPL V2.0. | |
| 6 | + * | |
| 7 | + * This program is free software; you can redistribute it and/or modify it | |
| 8 | + * under the terms and conditions of the GNU General Public License, | |
| 9 | + * version 2, as published by the Free Software Foundation. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope it will be useful, but WITHOUT | |
| 12 | + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| 13 | + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
| 14 | + * more details. | |
| 15 | + * | |
| 16 | + * You should have received a copy of the GNU General Public License along with | |
| 17 | + * this program. If not, see <http://www.gnu.org/licenses/>. | |
| 18 | + */ | |
| 19 | + | |
| 20 | +#include <linux/clk.h> | |
| 21 | +#include <linux/clk-provider.h> | |
| 22 | +#include <linux/err.h> | |
| 23 | +#include <linux/io.h> | |
| 24 | +#include <linux/mfd/syscon.h> | |
| 25 | +#include <linux/of.h> | |
| 26 | +#include <linux/of_address.h> | |
| 27 | +#include <linux/slab.h> | |
| 28 | +#include <linux/spinlock.h> | |
| 29 | +#include <linux/regmap.h> | |
| 30 | + | |
| 31 | +#include <dt-bindings/clock/stm32h7-clks.h> | |
| 32 | + | |
| 33 | +/* Reset Clock Control Registers */ | |
| 34 | +#define RCC_CR 0x00 | |
| 35 | +#define RCC_CFGR 0x10 | |
| 36 | +#define RCC_D1CFGR 0x18 | |
| 37 | +#define RCC_D2CFGR 0x1C | |
| 38 | +#define RCC_D3CFGR 0x20 | |
| 39 | +#define RCC_PLLCKSELR 0x28 | |
| 40 | +#define RCC_PLLCFGR 0x2C | |
| 41 | +#define RCC_PLL1DIVR 0x30 | |
| 42 | +#define RCC_PLL1FRACR 0x34 | |
| 43 | +#define RCC_PLL2DIVR 0x38 | |
| 44 | +#define RCC_PLL2FRACR 0x3C | |
| 45 | +#define RCC_PLL3DIVR 0x40 | |
| 46 | +#define RCC_PLL3FRACR 0x44 | |
| 47 | +#define RCC_D1CCIPR 0x4C | |
| 48 | +#define RCC_D2CCIP1R 0x50 | |
| 49 | +#define RCC_D2CCIP2R 0x54 | |
| 50 | +#define RCC_D3CCIPR 0x58 | |
| 51 | +#define RCC_BDCR 0x70 | |
| 52 | +#define RCC_CSR 0x74 | |
| 53 | +#define RCC_AHB3ENR 0xD4 | |
| 54 | +#define RCC_AHB1ENR 0xD8 | |
| 55 | +#define RCC_AHB2ENR 0xDC | |
| 56 | +#define RCC_AHB4ENR 0xE0 | |
| 57 | +#define RCC_APB3ENR 0xE4 | |
| 58 | +#define RCC_APB1LENR 0xE8 | |
| 59 | +#define RCC_APB1HENR 0xEC | |
| 60 | +#define RCC_APB2ENR 0xF0 | |
| 61 | +#define RCC_APB4ENR 0xF4 | |
| 62 | + | |
| 63 | +static DEFINE_SPINLOCK(stm32rcc_lock); | |
| 64 | + | |
| 65 | +static void __iomem *base; | |
| 66 | +static struct clk_hw **hws; | |
| 67 | + | |
| 68 | +/* System clock parent */ | |
| 69 | +static const char * const sys_src[] = { | |
| 70 | + "hsi_ck", "csi_ck", "hse_ck", "pll1_p" }; | |
| 71 | + | |
| 72 | +static const char * const tracein_src[] = { | |
| 73 | + "hsi_ck", "csi_ck", "hse_ck", "pll1_r" }; | |
| 74 | + | |
| 75 | +static const char * const per_src[] = { | |
| 76 | + "hsi_ker", "csi_ker", "hse_ck", "disabled" }; | |
| 77 | + | |
| 78 | +static const char * const pll_src[] = { | |
| 79 | + "hsi_ck", "csi_ck", "hse_ck", "no clock" }; | |
| 80 | + | |
| 81 | +static const char * const sdmmc_src[] = { "pll1_q", "pll2_r" }; | |
| 82 | + | |
| 83 | +static const char * const dsi_src[] = { "ck_dsi_phy", "pll2_q" }; | |
| 84 | + | |
| 85 | +static const char * const qspi_src[] = { | |
| 86 | + "hclk", "pll1_q", "pll2_r", "per_ck" }; | |
| 87 | + | |
| 88 | +static const char * const fmc_src[] = { | |
| 89 | + "hclk", "pll1_q", "pll2_r", "per_ck" }; | |
| 90 | + | |
| 91 | +/* Kernel clock parent */ | |
| 92 | +static const char * const swp_src[] = { "pclk1", "hsi_ker" }; | |
| 93 | + | |
| 94 | +static const char * const fdcan_src[] = { "hse_ck", "pll1_q", "pll2_q" }; | |
| 95 | + | |
| 96 | +static const char * const dfsdm1_src[] = { "pclk2", "sys_ck" }; | |
| 97 | + | |
| 98 | +static const char * const spdifrx_src[] = { | |
| 99 | + "pll1_q", "pll2_r", "pll3_r", "hsi_ker" }; | |
| 100 | + | |
| 101 | +static const char *spi_src1[5] = { | |
| 102 | + "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; | |
| 103 | + | |
| 104 | +static const char * const spi_src2[] = { | |
| 105 | + "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; | |
| 106 | + | |
| 107 | +static const char * const spi_src3[] = { | |
| 108 | + "pclk4", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "hse_ck" }; | |
| 109 | + | |
| 110 | +static const char * const lptim_src1[] = { | |
| 111 | + "pclk1", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; | |
| 112 | + | |
| 113 | +static const char * const lptim_src2[] = { | |
| 114 | + "pclk4", "pll2_p", "pll3_r", "lse_ck", "lsi_ck", "per_ck" }; | |
| 115 | + | |
| 116 | +static const char * const cec_src[] = {"lse_ck", "lsi_ck", "csi_ker_div122" }; | |
| 117 | + | |
| 118 | +static const char * const usbotg_src[] = {"pll1_q", "pll3_q", "rc48_ck" }; | |
| 119 | + | |
| 120 | +/* i2c 1,2,3 src */ | |
| 121 | +static const char * const i2c_src1[] = { | |
| 122 | + "pclk1", "pll3_r", "hsi_ker", "csi_ker" }; | |
| 123 | + | |
| 124 | +static const char * const i2c_src2[] = { | |
| 125 | + "pclk4", "pll3_r", "hsi_ker", "csi_ker" }; | |
| 126 | + | |
| 127 | +static const char * const rng_src[] = { | |
| 128 | + "rc48_ck", "pll1_q", "lse_ck", "lsi_ck" }; | |
| 129 | + | |
| 130 | +/* usart 1,6 src */ | |
| 131 | +static const char * const usart_src1[] = { | |
| 132 | + "pclk2", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; | |
| 133 | + | |
| 134 | +/* usart 2,3,4,5,7,8 src */ | |
| 135 | +static const char * const usart_src2[] = { | |
| 136 | + "pclk1", "pll2_q", "pll3_q", "hsi_ker", "csi_ker", "lse_ck" }; | |
| 137 | + | |
| 138 | +static const char *sai_src[5] = { | |
| 139 | + "pll1_q", "pll2_p", "pll3_p", NULL, "per_ck" }; | |
| 140 | + | |
| 141 | +static const char * const adc_src[] = { "pll2_p", "pll3_r", "per_ck" }; | |
| 142 | + | |
| 143 | +/* lptim 2,3,4,5 src */ | |
| 144 | +static const char * const lpuart1_src[] = { | |
| 145 | + "pclk3", "pll2_q", "pll3_q", "csi_ker", "lse_ck" }; | |
| 146 | + | |
| 147 | +static const char * const hrtim_src[] = { "tim2_ker", "d1cpre" }; | |
| 148 | + | |
| 149 | +/* RTC clock parent */ | |
| 150 | +static const char * const rtc_src[] = { "off", "lse_ck", "lsi_ck", "hse_1M" }; | |
| 151 | + | |
| 152 | +/* Micro-controller output clock parent */ | |
| 153 | +static const char * const mco_src1[] = { | |
| 154 | + "hsi_ck", "lse_ck", "hse_ck", "pll1_q", "rc48_ck" }; | |
| 155 | + | |
| 156 | +static const char * const mco_src2[] = { | |
| 157 | + "sys_ck", "pll2_p", "hse_ck", "pll1_p", "csi_ck", "lsi_ck" }; | |
| 158 | + | |
| 159 | +/* LCD clock */ | |
| 160 | +static const char * const ltdc_src[] = {"pll3_r"}; | |
| 161 | + | |
| 162 | +/* Gate clock with ready bit and backup domain management */ | |
| 163 | +struct stm32_ready_gate { | |
| 164 | + struct clk_gate gate; | |
| 165 | + u8 bit_rdy; | |
| 166 | +}; | |
| 167 | + | |
| 168 | +#define to_ready_gate_clk(_rgate) container_of(_rgate, struct stm32_ready_gate,\ | |
| 169 | + gate) | |
| 170 | + | |
| 171 | +#define RGATE_TIMEOUT 10000 | |
| 172 | + | |
| 173 | +static int ready_gate_clk_enable(struct clk_hw *hw) | |
| 174 | +{ | |
| 175 | + struct clk_gate *gate = to_clk_gate(hw); | |
| 176 | + struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); | |
| 177 | + int bit_status; | |
| 178 | + unsigned int timeout = RGATE_TIMEOUT; | |
| 179 | + | |
| 180 | + if (clk_gate_ops.is_enabled(hw)) | |
| 181 | + return 0; | |
| 182 | + | |
| 183 | + clk_gate_ops.enable(hw); | |
| 184 | + | |
| 185 | + /* We can't use readl_poll_timeout() because we can blocked if | |
| 186 | + * someone enables this clock before clocksource changes. | |
| 187 | + * Only jiffies counter is available. Jiffies are incremented by | |
| 188 | + * interruptions and enable op does not allow to be interrupted. | |
| 189 | + */ | |
| 190 | + do { | |
| 191 | + bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy)); | |
| 192 | + | |
| 193 | + if (bit_status) | |
| 194 | + udelay(100); | |
| 195 | + | |
| 196 | + } while (bit_status && --timeout); | |
| 197 | + | |
| 198 | + return bit_status; | |
| 199 | +} | |
| 200 | + | |
| 201 | +static void ready_gate_clk_disable(struct clk_hw *hw) | |
| 202 | +{ | |
| 203 | + struct clk_gate *gate = to_clk_gate(hw); | |
| 204 | + struct stm32_ready_gate *rgate = to_ready_gate_clk(gate); | |
| 205 | + int bit_status; | |
| 206 | + unsigned int timeout = RGATE_TIMEOUT; | |
| 207 | + | |
| 208 | + if (!clk_gate_ops.is_enabled(hw)) | |
| 209 | + return; | |
| 210 | + | |
| 211 | + clk_gate_ops.disable(hw); | |
| 212 | + | |
| 213 | + do { | |
| 214 | + bit_status = !!(readl(gate->reg) & BIT(rgate->bit_rdy)); | |
| 215 | + | |
| 216 | + if (bit_status) | |
| 217 | + udelay(100); | |
| 218 | + | |
| 219 | + } while (bit_status && --timeout); | |
| 220 | +} | |
| 221 | + | |
| 222 | +static const struct clk_ops ready_gate_clk_ops = { | |
| 223 | + .enable = ready_gate_clk_enable, | |
| 224 | + .disable = ready_gate_clk_disable, | |
| 225 | + .is_enabled = clk_gate_is_enabled, | |
| 226 | +}; | |
| 227 | + | |
| 228 | +static struct clk_hw *clk_register_ready_gate(struct device *dev, | |
| 229 | + const char *name, const char *parent_name, | |
| 230 | + void __iomem *reg, u8 bit_idx, u8 bit_rdy, | |
| 231 | + unsigned long flags, spinlock_t *lock) | |
| 232 | +{ | |
| 233 | + struct stm32_ready_gate *rgate; | |
| 234 | + struct clk_init_data init = { NULL }; | |
| 235 | + struct clk_hw *hw; | |
| 236 | + int ret; | |
| 237 | + | |
| 238 | + rgate = kzalloc(sizeof(*rgate), GFP_KERNEL); | |
| 239 | + if (!rgate) | |
| 240 | + return ERR_PTR(-ENOMEM); | |
| 241 | + | |
| 242 | + init.name = name; | |
| 243 | + init.ops = &ready_gate_clk_ops; | |
| 244 | + init.flags = flags; | |
| 245 | + init.parent_names = &parent_name; | |
| 246 | + init.num_parents = 1; | |
| 247 | + | |
| 248 | + rgate->bit_rdy = bit_rdy; | |
| 249 | + rgate->gate.lock = lock; | |
| 250 | + rgate->gate.reg = reg; | |
| 251 | + rgate->gate.bit_idx = bit_idx; | |
| 252 | + rgate->gate.hw.init = &init; | |
| 253 | + | |
| 254 | + hw = &rgate->gate.hw; | |
| 255 | + ret = clk_hw_register(dev, hw); | |
| 256 | + if (ret) { | |
| 257 | + kfree(rgate); | |
| 258 | + hw = ERR_PTR(ret); | |
| 259 | + } | |
| 260 | + | |
| 261 | + return hw; | |
| 262 | +} | |
| 263 | + | |
| 264 | +struct gate_cfg { | |
| 265 | + u32 offset; | |
| 266 | + u8 bit_idx; | |
| 267 | +}; | |
| 268 | + | |
| 269 | +struct muxdiv_cfg { | |
| 270 | + u32 offset; | |
| 271 | + u8 shift; | |
| 272 | + u8 width; | |
| 273 | +}; | |
| 274 | + | |
| 275 | +struct composite_clk_cfg { | |
| 276 | + struct gate_cfg *gate; | |
| 277 | + struct muxdiv_cfg *mux; | |
| 278 | + struct muxdiv_cfg *div; | |
| 279 | + const char *name; | |
| 280 | + const char * const *parent_name; | |
| 281 | + int num_parents; | |
| 282 | + u32 flags; | |
| 283 | +}; | |
| 284 | + | |
| 285 | +struct composite_clk_gcfg_t { | |
| 286 | + u8 flags; | |
| 287 | + const struct clk_ops *ops; | |
| 288 | +}; | |
| 289 | + | |
| 290 | +/* | |
| 291 | + * General config definition of a composite clock (only clock diviser for rate) | |
| 292 | + */ | |
| 293 | +struct composite_clk_gcfg { | |
| 294 | + struct composite_clk_gcfg_t *mux; | |
| 295 | + struct composite_clk_gcfg_t *div; | |
| 296 | + struct composite_clk_gcfg_t *gate; | |
| 297 | +}; | |
| 298 | + | |
| 299 | +#define M_CFG_MUX(_mux_ops, _mux_flags)\ | |
| 300 | + .mux = &(struct composite_clk_gcfg_t) { _mux_flags, _mux_ops} | |
| 301 | + | |
| 302 | +#define M_CFG_DIV(_rate_ops, _rate_flags)\ | |
| 303 | + .div = &(struct composite_clk_gcfg_t) {_rate_flags, _rate_ops} | |
| 304 | + | |
| 305 | +#define M_CFG_GATE(_gate_ops, _gate_flags)\ | |
| 306 | + .gate = &(struct composite_clk_gcfg_t) { _gate_flags, _gate_ops} | |
| 307 | + | |
| 308 | +static struct clk_mux *_get_cmux(void __iomem *reg, u8 shift, u8 width, | |
| 309 | + u32 flags, spinlock_t *lock) | |
| 310 | +{ | |
| 311 | + struct clk_mux *mux; | |
| 312 | + | |
| 313 | + mux = kzalloc(sizeof(*mux), GFP_KERNEL); | |
| 314 | + if (!mux) | |
| 315 | + return ERR_PTR(-ENOMEM); | |
| 316 | + | |
| 317 | + mux->reg = reg; | |
| 318 | + mux->shift = shift; | |
| 319 | + mux->mask = (1 << width) - 1; | |
| 320 | + mux->flags = flags; | |
| 321 | + mux->lock = lock; | |
| 322 | + | |
| 323 | + return mux; | |
| 324 | +} | |
| 325 | + | |
| 326 | +static struct clk_divider *_get_cdiv(void __iomem *reg, u8 shift, u8 width, | |
| 327 | + u32 flags, spinlock_t *lock) | |
| 328 | +{ | |
| 329 | + struct clk_divider *div; | |
| 330 | + | |
| 331 | + div = kzalloc(sizeof(*div), GFP_KERNEL); | |
| 332 | + | |
| 333 | + if (!div) | |
| 334 | + return ERR_PTR(-ENOMEM); | |
| 335 | + | |
| 336 | + div->reg = reg; | |
| 337 | + div->shift = shift; | |
| 338 | + div->width = width; | |
| 339 | + div->flags = flags; | |
| 340 | + div->lock = lock; | |
| 341 | + | |
| 342 | + return div; | |
| 343 | +} | |
| 344 | + | |
| 345 | +static struct clk_gate *_get_cgate(void __iomem *reg, u8 bit_idx, u32 flags, | |
| 346 | + spinlock_t *lock) | |
| 347 | +{ | |
| 348 | + struct clk_gate *gate; | |
| 349 | + | |
| 350 | + gate = kzalloc(sizeof(*gate), GFP_KERNEL); | |
| 351 | + if (!gate) | |
| 352 | + return ERR_PTR(-ENOMEM); | |
| 353 | + | |
| 354 | + gate->reg = reg; | |
| 355 | + gate->bit_idx = bit_idx; | |
| 356 | + gate->flags = flags; | |
| 357 | + gate->lock = lock; | |
| 358 | + | |
| 359 | + return gate; | |
| 360 | +} | |
| 361 | + | |
| 362 | +struct composite_cfg { | |
| 363 | + struct clk_hw *mux_hw; | |
| 364 | + struct clk_hw *div_hw; | |
| 365 | + struct clk_hw *gate_hw; | |
| 366 | + | |
| 367 | + const struct clk_ops *mux_ops; | |
| 368 | + const struct clk_ops *div_ops; | |
| 369 | + const struct clk_ops *gate_ops; | |
| 370 | +}; | |
| 371 | + | |
| 372 | +static void get_cfg_composite_div(const struct composite_clk_gcfg *gcfg, | |
| 373 | + const struct composite_clk_cfg *cfg, | |
| 374 | + struct composite_cfg *composite, spinlock_t *lock) | |
| 375 | +{ | |
| 376 | + struct clk_mux *mux = NULL; | |
| 377 | + struct clk_divider *div = NULL; | |
| 378 | + struct clk_gate *gate = NULL; | |
| 379 | + const struct clk_ops *mux_ops, *div_ops, *gate_ops; | |
| 380 | + struct clk_hw *mux_hw; | |
| 381 | + struct clk_hw *div_hw; | |
| 382 | + struct clk_hw *gate_hw; | |
| 383 | + | |
| 384 | + mux_ops = div_ops = gate_ops = NULL; | |
| 385 | + mux_hw = div_hw = gate_hw = NULL; | |
| 386 | + | |
| 387 | + if (gcfg->mux && gcfg->mux) { | |
| 388 | + mux = _get_cmux(base + cfg->mux->offset, | |
| 389 | + cfg->mux->shift, | |
| 390 | + cfg->mux->width, | |
| 391 | + gcfg->mux->flags, lock); | |
| 392 | + | |
| 393 | + if (!IS_ERR(mux)) { | |
| 394 | + mux_hw = &mux->hw; | |
| 395 | + mux_ops = gcfg->mux->ops ? | |
| 396 | + gcfg->mux->ops : &clk_mux_ops; | |
| 397 | + } | |
| 398 | + } | |
| 399 | + | |
| 400 | + if (gcfg->div && cfg->div) { | |
| 401 | + div = _get_cdiv(base + cfg->div->offset, | |
| 402 | + cfg->div->shift, | |
| 403 | + cfg->div->width, | |
| 404 | + gcfg->div->flags, lock); | |
| 405 | + | |
| 406 | + if (!IS_ERR(div)) { | |
| 407 | + div_hw = &div->hw; | |
| 408 | + div_ops = gcfg->div->ops ? | |
| 409 | + gcfg->div->ops : &clk_divider_ops; | |
| 410 | + } | |
| 411 | + } | |
| 412 | + | |
| 413 | + if (gcfg->gate && gcfg->gate) { | |
| 414 | + gate = _get_cgate(base + cfg->gate->offset, | |
| 415 | + cfg->gate->bit_idx, | |
| 416 | + gcfg->gate->flags, lock); | |
| 417 | + | |
| 418 | + if (!IS_ERR(gate)) { | |
| 419 | + gate_hw = &gate->hw; | |
| 420 | + gate_ops = gcfg->gate->ops ? | |
| 421 | + gcfg->gate->ops : &clk_gate_ops; | |
| 422 | + } | |
| 423 | + } | |
| 424 | + | |
| 425 | + composite->mux_hw = mux_hw; | |
| 426 | + composite->mux_ops = mux_ops; | |
| 427 | + | |
| 428 | + composite->div_hw = div_hw; | |
| 429 | + composite->div_ops = div_ops; | |
| 430 | + | |
| 431 | + composite->gate_hw = gate_hw; | |
| 432 | + composite->gate_ops = gate_ops; | |
| 433 | +} | |
| 434 | + | |
| 435 | +/* Kernel Timer */ | |
| 436 | +struct timer_ker { | |
| 437 | + u8 dppre_shift; | |
| 438 | + struct clk_hw hw; | |
| 439 | + spinlock_t *lock; | |
| 440 | +}; | |
| 441 | + | |
| 442 | +#define to_timer_ker(_hw) container_of(_hw, struct timer_ker, hw) | |
| 443 | + | |
| 444 | +static unsigned long timer_ker_recalc_rate(struct clk_hw *hw, | |
| 445 | + unsigned long parent_rate) | |
| 446 | +{ | |
| 447 | + struct timer_ker *clk_elem = to_timer_ker(hw); | |
| 448 | + u32 timpre; | |
| 449 | + u32 dppre_shift = clk_elem->dppre_shift; | |
| 450 | + u32 prescaler; | |
| 451 | + u32 mul; | |
| 452 | + | |
| 453 | + timpre = (readl(base + RCC_CFGR) >> 15) & 0x01; | |
| 454 | + | |
| 455 | + prescaler = (readl(base + RCC_D2CFGR) >> dppre_shift) & 0x03; | |
| 456 | + | |
| 457 | + mul = 2; | |
| 458 | + | |
| 459 | + if (prescaler < 4) | |
| 460 | + mul = 1; | |
| 461 | + | |
| 462 | + else if (timpre && prescaler > 4) | |
| 463 | + mul = 4; | |
| 464 | + | |
| 465 | + return parent_rate * mul; | |
| 466 | +} | |
| 467 | + | |
| 468 | +static const struct clk_ops timer_ker_ops = { | |
| 469 | + .recalc_rate = timer_ker_recalc_rate, | |
| 470 | +}; | |
| 471 | + | |
| 472 | +static struct clk_hw *clk_register_stm32_timer_ker(struct device *dev, | |
| 473 | + const char *name, const char *parent_name, | |
| 474 | + unsigned long flags, | |
| 475 | + u8 dppre_shift, | |
| 476 | + spinlock_t *lock) | |
| 477 | +{ | |
| 478 | + struct timer_ker *element; | |
| 479 | + struct clk_init_data init; | |
| 480 | + struct clk_hw *hw; | |
| 481 | + int err; | |
| 482 | + | |
| 483 | + element = kzalloc(sizeof(*element), GFP_KERNEL); | |
| 484 | + if (!element) | |
| 485 | + return ERR_PTR(-ENOMEM); | |
| 486 | + | |
| 487 | + init.name = name; | |
| 488 | + init.ops = &timer_ker_ops; | |
| 489 | + init.flags = flags; | |
| 490 | + init.parent_names = &parent_name; | |
| 491 | + init.num_parents = 1; | |
| 492 | + | |
| 493 | + element->hw.init = &init; | |
| 494 | + element->lock = lock; | |
| 495 | + element->dppre_shift = dppre_shift; | |
| 496 | + | |
| 497 | + hw = &element->hw; | |
| 498 | + err = clk_hw_register(dev, hw); | |
| 499 | + | |
| 500 | + if (err) { | |
| 501 | + kfree(element); | |
| 502 | + return ERR_PTR(err); | |
| 503 | + } | |
| 504 | + | |
| 505 | + return hw; | |
| 506 | +} | |
| 507 | + | |
| 508 | +static const struct clk_div_table d1cpre_div_table[] = { | |
| 509 | + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, | |
| 510 | + { 4, 1 }, { 5, 1 }, { 6, 1 }, { 7, 1}, | |
| 511 | + { 8, 2 }, { 9, 4 }, { 10, 8 }, { 11, 16 }, | |
| 512 | + { 12, 64 }, { 13, 128 }, { 14, 256 }, | |
| 513 | + { 15, 512 }, | |
| 514 | + { 0 }, | |
| 515 | +}; | |
| 516 | + | |
| 517 | +static const struct clk_div_table ppre_div_table[] = { | |
| 518 | + { 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1}, | |
| 519 | + { 4, 2 }, { 5, 4 }, { 6, 8 }, { 7, 16 }, | |
| 520 | + { 0 }, | |
| 521 | +}; | |
| 522 | + | |
| 523 | +static void register_core_and_bus_clocks(void) | |
| 524 | +{ | |
| 525 | + /* CORE AND BUS */ | |
| 526 | + hws[SYS_D1CPRE] = clk_hw_register_divider_table(NULL, "d1cpre", | |
| 527 | + "sys_ck", CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 8, 4, 0, | |
| 528 | + d1cpre_div_table, &stm32rcc_lock); | |
| 529 | + | |
| 530 | + hws[HCLK] = clk_hw_register_divider_table(NULL, "hclk", "d1cpre", | |
| 531 | + CLK_IGNORE_UNUSED, base + RCC_D1CFGR, 0, 4, 0, | |
| 532 | + d1cpre_div_table, &stm32rcc_lock); | |
| 533 | + | |
| 534 | + /* D1 DOMAIN */ | |
| 535 | + /* * CPU Systick */ | |
| 536 | + hws[CPU_SYSTICK] = clk_hw_register_fixed_factor(NULL, "systick", | |
| 537 | + "d1cpre", 0, 1, 8); | |
| 538 | + | |
| 539 | + /* * APB3 peripheral */ | |
| 540 | + hws[PCLK3] = clk_hw_register_divider_table(NULL, "pclk3", "hclk", 0, | |
| 541 | + base + RCC_D1CFGR, 4, 3, 0, | |
| 542 | + ppre_div_table, &stm32rcc_lock); | |
| 543 | + | |
| 544 | + /* D2 DOMAIN */ | |
| 545 | + /* * APB1 peripheral */ | |
| 546 | + hws[PCLK1] = clk_hw_register_divider_table(NULL, "pclk1", "hclk", 0, | |
| 547 | + base + RCC_D2CFGR, 4, 3, 0, | |
| 548 | + ppre_div_table, &stm32rcc_lock); | |
| 549 | + | |
| 550 | + /* Timers prescaler clocks */ | |
| 551 | + clk_register_stm32_timer_ker(NULL, "tim1_ker", "pclk1", 0, | |
| 552 | + 4, &stm32rcc_lock); | |
| 553 | + | |
| 554 | + /* * APB2 peripheral */ | |
| 555 | + hws[PCLK2] = clk_hw_register_divider_table(NULL, "pclk2", "hclk", 0, | |
| 556 | + base + RCC_D2CFGR, 8, 3, 0, ppre_div_table, | |
| 557 | + &stm32rcc_lock); | |
| 558 | + | |
| 559 | + clk_register_stm32_timer_ker(NULL, "tim2_ker", "pclk2", 0, 8, | |
| 560 | + &stm32rcc_lock); | |
| 561 | + | |
| 562 | + /* D3 DOMAIN */ | |
| 563 | + /* * APB4 peripheral */ | |
| 564 | + hws[PCLK4] = clk_hw_register_divider_table(NULL, "pclk4", "hclk", 0, | |
| 565 | + base + RCC_D3CFGR, 4, 3, 0, | |
| 566 | + ppre_div_table, &stm32rcc_lock); | |
| 567 | +} | |
| 568 | + | |
| 569 | +/* MUX clock configuration */ | |
| 570 | +struct stm32_mux_clk { | |
| 571 | + const char *name; | |
| 572 | + const char * const *parents; | |
| 573 | + u8 num_parents; | |
| 574 | + u32 offset; | |
| 575 | + u8 shift; | |
| 576 | + u8 width; | |
| 577 | + u32 flags; | |
| 578 | +}; | |
| 579 | + | |
| 580 | +#define M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, _flags)\ | |
| 581 | +{\ | |
| 582 | + .name = _name,\ | |
| 583 | + .parents = _parents,\ | |
| 584 | + .num_parents = ARRAY_SIZE(_parents),\ | |
| 585 | + .offset = _mux_offset,\ | |
| 586 | + .shift = _mux_shift,\ | |
| 587 | + .width = _mux_width,\ | |
| 588 | + .flags = _flags,\ | |
| 589 | +} | |
| 590 | + | |
| 591 | +#define M_MCLOC(_name, _parents, _mux_offset, _mux_shift, _mux_width)\ | |
| 592 | + M_MCLOCF(_name, _parents, _mux_offset, _mux_shift, _mux_width, 0)\ | |
| 593 | + | |
| 594 | +static const struct stm32_mux_clk stm32_mclk[] __initconst = { | |
| 595 | + M_MCLOC("per_ck", per_src, RCC_D1CCIPR, 28, 3), | |
| 596 | + M_MCLOC("pllsrc", pll_src, RCC_PLLCKSELR, 0, 3), | |
| 597 | + M_MCLOC("sys_ck", sys_src, RCC_CFGR, 0, 3), | |
| 598 | + M_MCLOC("tracein_ck", tracein_src, RCC_CFGR, 0, 3), | |
| 599 | +}; | |
| 600 | + | |
| 601 | +/* Oscillary clock configuration */ | |
| 602 | +struct stm32_osc_clk { | |
| 603 | + const char *name; | |
| 604 | + const char *parent; | |
| 605 | + u32 gate_offset; | |
| 606 | + u8 bit_idx; | |
| 607 | + u8 bit_rdy; | |
| 608 | + u32 flags; | |
| 609 | +}; | |
| 610 | + | |
| 611 | +#define OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, _flags)\ | |
| 612 | +{\ | |
| 613 | + .name = _name,\ | |
| 614 | + .parent = _parent,\ | |
| 615 | + .gate_offset = _gate_offset,\ | |
| 616 | + .bit_idx = _bit_idx,\ | |
| 617 | + .bit_rdy = _bit_rdy,\ | |
| 618 | + .flags = _flags,\ | |
| 619 | +} | |
| 620 | + | |
| 621 | +#define OSC_CLK(_name, _parent, _gate_offset, _bit_idx, _bit_rdy)\ | |
| 622 | + OSC_CLKF(_name, _parent, _gate_offset, _bit_idx, _bit_rdy, 0) | |
| 623 | + | |
| 624 | +static const struct stm32_osc_clk stm32_oclk[] __initconst = { | |
| 625 | + OSC_CLKF("hsi_ck", "hsidiv", RCC_CR, 0, 2, CLK_IGNORE_UNUSED), | |
| 626 | + OSC_CLKF("hsi_ker", "hsidiv", RCC_CR, 1, 2, CLK_IGNORE_UNUSED), | |
| 627 | + OSC_CLKF("csi_ck", "clk-csi", RCC_CR, 7, 8, CLK_IGNORE_UNUSED), | |
| 628 | + OSC_CLKF("csi_ker", "clk-csi", RCC_CR, 9, 8, CLK_IGNORE_UNUSED), | |
| 629 | + OSC_CLKF("rc48_ck", "clk-rc48", RCC_CR, 12, 13, CLK_IGNORE_UNUSED), | |
| 630 | + OSC_CLKF("lsi_ck", "clk-lsi", RCC_CSR, 0, 1, CLK_IGNORE_UNUSED), | |
| 631 | +}; | |
| 632 | + | |
| 633 | +/* PLL configuration */ | |
| 634 | +struct st32h7_pll_cfg { | |
| 635 | + u8 bit_idx; | |
| 636 | + u32 offset_divr; | |
| 637 | + u8 bit_frac_en; | |
| 638 | + u32 offset_frac; | |
| 639 | + u8 divm; | |
| 640 | +}; | |
| 641 | + | |
| 642 | +struct stm32_pll_data { | |
| 643 | + const char *name; | |
| 644 | + const char *parent_name; | |
| 645 | + unsigned long flags; | |
| 646 | + const struct st32h7_pll_cfg *cfg; | |
| 647 | +}; | |
| 648 | + | |
| 649 | +static const struct st32h7_pll_cfg stm32h7_pll1 = { | |
| 650 | + .bit_idx = 24, | |
| 651 | + .offset_divr = RCC_PLL1DIVR, | |
| 652 | + .bit_frac_en = 0, | |
| 653 | + .offset_frac = RCC_PLL1FRACR, | |
| 654 | + .divm = 4, | |
| 655 | +}; | |
| 656 | + | |
| 657 | +static const struct st32h7_pll_cfg stm32h7_pll2 = { | |
| 658 | + .bit_idx = 26, | |
| 659 | + .offset_divr = RCC_PLL2DIVR, | |
| 660 | + .bit_frac_en = 4, | |
| 661 | + .offset_frac = RCC_PLL2FRACR, | |
| 662 | + .divm = 12, | |
| 663 | +}; | |
| 664 | + | |
| 665 | +static const struct st32h7_pll_cfg stm32h7_pll3 = { | |
| 666 | + .bit_idx = 28, | |
| 667 | + .offset_divr = RCC_PLL3DIVR, | |
| 668 | + .bit_frac_en = 8, | |
| 669 | + .offset_frac = RCC_PLL3FRACR, | |
| 670 | + .divm = 20, | |
| 671 | +}; | |
| 672 | + | |
| 673 | +static const struct stm32_pll_data stm32_pll[] = { | |
| 674 | + { "vco1", "pllsrc", CLK_IGNORE_UNUSED, &stm32h7_pll1 }, | |
| 675 | + { "vco2", "pllsrc", 0, &stm32h7_pll2 }, | |
| 676 | + { "vco3", "pllsrc", 0, &stm32h7_pll3 }, | |
| 677 | +}; | |
| 678 | + | |
| 679 | +struct stm32_fractional_divider { | |
| 680 | + void __iomem *mreg; | |
| 681 | + u8 mshift; | |
| 682 | + u8 mwidth; | |
| 683 | + u32 mmask; | |
| 684 | + | |
| 685 | + void __iomem *nreg; | |
| 686 | + u8 nshift; | |
| 687 | + u8 nwidth; | |
| 688 | + | |
| 689 | + void __iomem *freg_status; | |
| 690 | + u8 freg_bit; | |
| 691 | + void __iomem *freg_value; | |
| 692 | + u8 fshift; | |
| 693 | + u8 fwidth; | |
| 694 | + | |
| 695 | + u8 flags; | |
| 696 | + struct clk_hw hw; | |
| 697 | + spinlock_t *lock; | |
| 698 | +}; | |
| 699 | + | |
| 700 | +struct stm32_pll_obj { | |
| 701 | + spinlock_t *lock; | |
| 702 | + struct stm32_fractional_divider div; | |
| 703 | + struct stm32_ready_gate rgate; | |
| 704 | + struct clk_hw hw; | |
| 705 | +}; | |
| 706 | + | |
| 707 | +#define to_pll(_hw) container_of(_hw, struct stm32_pll_obj, hw) | |
| 708 | + | |
| 709 | +static int pll_is_enabled(struct clk_hw *hw) | |
| 710 | +{ | |
| 711 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 712 | + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | |
| 713 | + | |
| 714 | + __clk_hw_set_clk(_hw, hw); | |
| 715 | + | |
| 716 | + return ready_gate_clk_ops.is_enabled(_hw); | |
| 717 | +} | |
| 718 | + | |
| 719 | +static int pll_enable(struct clk_hw *hw) | |
| 720 | +{ | |
| 721 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 722 | + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | |
| 723 | + | |
| 724 | + __clk_hw_set_clk(_hw, hw); | |
| 725 | + | |
| 726 | + return ready_gate_clk_ops.enable(_hw); | |
| 727 | +} | |
| 728 | + | |
| 729 | +static void pll_disable(struct clk_hw *hw) | |
| 730 | +{ | |
| 731 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 732 | + struct clk_hw *_hw = &clk_elem->rgate.gate.hw; | |
| 733 | + | |
| 734 | + __clk_hw_set_clk(_hw, hw); | |
| 735 | + | |
| 736 | + ready_gate_clk_ops.disable(_hw); | |
| 737 | +} | |
| 738 | + | |
| 739 | +static int pll_frac_is_enabled(struct clk_hw *hw) | |
| 740 | +{ | |
| 741 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 742 | + struct stm32_fractional_divider *fd = &clk_elem->div; | |
| 743 | + | |
| 744 | + return (readl(fd->freg_status) >> fd->freg_bit) & 0x01; | |
| 745 | +} | |
| 746 | + | |
| 747 | +static unsigned long pll_read_frac(struct clk_hw *hw) | |
| 748 | +{ | |
| 749 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 750 | + struct stm32_fractional_divider *fd = &clk_elem->div; | |
| 751 | + | |
| 752 | + return (readl(fd->freg_value) >> fd->fshift) & | |
| 753 | + GENMASK(fd->fwidth - 1, 0); | |
| 754 | +} | |
| 755 | + | |
| 756 | +static unsigned long pll_fd_recalc_rate(struct clk_hw *hw, | |
| 757 | + unsigned long parent_rate) | |
| 758 | +{ | |
| 759 | + struct stm32_pll_obj *clk_elem = to_pll(hw); | |
| 760 | + struct stm32_fractional_divider *fd = &clk_elem->div; | |
| 761 | + unsigned long m, n; | |
| 762 | + u32 val, mask; | |
| 763 | + u64 rate, rate1 = 0; | |
| 764 | + | |
| 765 | + val = readl(fd->mreg); | |
| 766 | + mask = GENMASK(fd->mwidth - 1, 0) << fd->mshift; | |
| 767 | + m = (val & mask) >> fd->mshift; | |
| 768 | + | |
| 769 | + val = readl(fd->nreg); | |
| 770 | + mask = GENMASK(fd->nwidth - 1, 0) << fd->nshift; | |
| 771 | + n = ((val & mask) >> fd->nshift) + 1; | |
| 772 | + | |
| 773 | + if (!n || !m) | |
| 774 | + return parent_rate; | |
| 775 | + | |
| 776 | + rate = (u64)parent_rate * n; | |
| 777 | + do_div(rate, m); | |
| 778 | + | |
| 779 | + if (pll_frac_is_enabled(hw)) { | |
| 780 | + val = pll_read_frac(hw); | |
| 781 | + rate1 = (u64)parent_rate * (u64)val; | |
| 782 | + do_div(rate1, (m * 8191)); | |
| 783 | + } | |
| 784 | + | |
| 785 | + return rate + rate1; | |
| 786 | +} | |
| 787 | + | |
| 788 | +static const struct clk_ops pll_ops = { | |
| 789 | + .enable = pll_enable, | |
| 790 | + .disable = pll_disable, | |
| 791 | + .is_enabled = pll_is_enabled, | |
| 792 | + .recalc_rate = pll_fd_recalc_rate, | |
| 793 | +}; | |
| 794 | + | |
| 795 | +static struct clk_hw *clk_register_stm32_pll(struct device *dev, | |
| 796 | + const char *name, | |
| 797 | + const char *parent, | |
| 798 | + unsigned long flags, | |
| 799 | + const struct st32h7_pll_cfg *cfg, | |
| 800 | + spinlock_t *lock) | |
| 801 | +{ | |
| 802 | + struct stm32_pll_obj *pll; | |
| 803 | + struct clk_init_data init = { NULL }; | |
| 804 | + struct clk_hw *hw; | |
| 805 | + int ret; | |
| 806 | + struct stm32_fractional_divider *div = NULL; | |
| 807 | + struct stm32_ready_gate *rgate; | |
| 808 | + | |
| 809 | + pll = kzalloc(sizeof(*pll), GFP_KERNEL); | |
| 810 | + if (!pll) | |
| 811 | + return ERR_PTR(-ENOMEM); | |
| 812 | + | |
| 813 | + init.name = name; | |
| 814 | + init.ops = &pll_ops; | |
| 815 | + init.flags = flags; | |
| 816 | + init.parent_names = &parent; | |
| 817 | + init.num_parents = 1; | |
| 818 | + pll->hw.init = &init; | |
| 819 | + | |
| 820 | + hw = &pll->hw; | |
| 821 | + rgate = &pll->rgate; | |
| 822 | + | |
| 823 | + rgate->bit_rdy = cfg->bit_idx + 1; | |
| 824 | + rgate->gate.lock = lock; | |
| 825 | + rgate->gate.reg = base + RCC_CR; | |
| 826 | + rgate->gate.bit_idx = cfg->bit_idx; | |
| 827 | + | |
| 828 | + div = &pll->div; | |
| 829 | + div->flags = 0; | |
| 830 | + div->mreg = base + RCC_PLLCKSELR; | |
| 831 | + div->mshift = cfg->divm; | |
| 832 | + div->mwidth = 6; | |
| 833 | + div->nreg = base + cfg->offset_divr; | |
| 834 | + div->nshift = 0; | |
| 835 | + div->nwidth = 9; | |
| 836 | + | |
| 837 | + div->freg_status = base + RCC_PLLCFGR; | |
| 838 | + div->freg_bit = cfg->bit_frac_en; | |
| 839 | + div->freg_value = base + cfg->offset_frac; | |
| 840 | + div->fshift = 3; | |
| 841 | + div->fwidth = 13; | |
| 842 | + | |
| 843 | + div->lock = lock; | |
| 844 | + | |
| 845 | + ret = clk_hw_register(dev, hw); | |
| 846 | + if (ret) { | |
| 847 | + kfree(pll); | |
| 848 | + hw = ERR_PTR(ret); | |
| 849 | + } | |
| 850 | + | |
| 851 | + return hw; | |
| 852 | +} | |
| 853 | + | |
| 854 | +/* ODF CLOCKS */ | |
| 855 | +static unsigned long odf_divider_recalc_rate(struct clk_hw *hw, | |
| 856 | + unsigned long parent_rate) | |
| 857 | +{ | |
| 858 | + return clk_divider_ops.recalc_rate(hw, parent_rate); | |
| 859 | +} | |
| 860 | + | |
| 861 | +static long odf_divider_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 862 | + unsigned long *prate) | |
| 863 | +{ | |
| 864 | + return clk_divider_ops.round_rate(hw, rate, prate); | |
| 865 | +} | |
| 866 | + | |
| 867 | +static int odf_divider_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 868 | + unsigned long parent_rate) | |
| 869 | +{ | |
| 870 | + struct clk_hw *hwp; | |
| 871 | + int pll_status; | |
| 872 | + int ret; | |
| 873 | + | |
| 874 | + hwp = clk_hw_get_parent(hw); | |
| 875 | + | |
| 876 | + pll_status = pll_is_enabled(hwp); | |
| 877 | + | |
| 878 | + if (pll_status) | |
| 879 | + pll_disable(hwp); | |
| 880 | + | |
| 881 | + ret = clk_divider_ops.set_rate(hw, rate, parent_rate); | |
| 882 | + | |
| 883 | + if (pll_status) | |
| 884 | + pll_enable(hwp); | |
| 885 | + | |
| 886 | + return ret; | |
| 887 | +} | |
| 888 | + | |
| 889 | +static const struct clk_ops odf_divider_ops = { | |
| 890 | + .recalc_rate = odf_divider_recalc_rate, | |
| 891 | + .round_rate = odf_divider_round_rate, | |
| 892 | + .set_rate = odf_divider_set_rate, | |
| 893 | +}; | |
| 894 | + | |
| 895 | +static int odf_gate_enable(struct clk_hw *hw) | |
| 896 | +{ | |
| 897 | + struct clk_hw *hwp; | |
| 898 | + int pll_status; | |
| 899 | + int ret; | |
| 900 | + | |
| 901 | + if (clk_gate_ops.is_enabled(hw)) | |
| 902 | + return 0; | |
| 903 | + | |
| 904 | + hwp = clk_hw_get_parent(hw); | |
| 905 | + | |
| 906 | + pll_status = pll_is_enabled(hwp); | |
| 907 | + | |
| 908 | + if (pll_status) | |
| 909 | + pll_disable(hwp); | |
| 910 | + | |
| 911 | + ret = clk_gate_ops.enable(hw); | |
| 912 | + | |
| 913 | + if (pll_status) | |
| 914 | + pll_enable(hwp); | |
| 915 | + | |
| 916 | + return ret; | |
| 917 | +} | |
| 918 | + | |
| 919 | +static void odf_gate_disable(struct clk_hw *hw) | |
| 920 | +{ | |
| 921 | + struct clk_hw *hwp; | |
| 922 | + int pll_status; | |
| 923 | + | |
| 924 | + if (!clk_gate_ops.is_enabled(hw)) | |
| 925 | + return; | |
| 926 | + | |
| 927 | + hwp = clk_hw_get_parent(hw); | |
| 928 | + | |
| 929 | + pll_status = pll_is_enabled(hwp); | |
| 930 | + | |
| 931 | + if (pll_status) | |
| 932 | + pll_disable(hwp); | |
| 933 | + | |
| 934 | + clk_gate_ops.disable(hw); | |
| 935 | + | |
| 936 | + if (pll_status) | |
| 937 | + pll_enable(hwp); | |
| 938 | +} | |
| 939 | + | |
| 940 | +static const struct clk_ops odf_gate_ops = { | |
| 941 | + .enable = odf_gate_enable, | |
| 942 | + .disable = odf_gate_disable, | |
| 943 | + .is_enabled = clk_gate_is_enabled, | |
| 944 | +}; | |
| 945 | + | |
| 946 | +static struct composite_clk_gcfg odf_clk_gcfg = { | |
| 947 | + M_CFG_DIV(&odf_divider_ops, 0), | |
| 948 | + M_CFG_GATE(&odf_gate_ops, 0), | |
| 949 | +}; | |
| 950 | + | |
| 951 | +#define M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | |
| 952 | + _rate_shift, _rate_width, _flags)\ | |
| 953 | +{\ | |
| 954 | + .mux = NULL,\ | |
| 955 | + .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ | |
| 956 | + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx },\ | |
| 957 | + .name = _name,\ | |
| 958 | + .parent_name = &(const char *) {_parent},\ | |
| 959 | + .num_parents = 1,\ | |
| 960 | + .flags = _flags,\ | |
| 961 | +} | |
| 962 | + | |
| 963 | +#define M_ODF(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | |
| 964 | + _rate_shift, _rate_width)\ | |
| 965 | +M_ODF_F(_name, _parent, _gate_offset, _bit_idx, _rate_offset,\ | |
| 966 | + _rate_shift, _rate_width, 0)\ | |
| 967 | + | |
| 968 | +static const struct composite_clk_cfg stm32_odf[3][3] = { | |
| 969 | + { | |
| 970 | + M_ODF_F("pll1_p", "vco1", RCC_PLLCFGR, 16, RCC_PLL1DIVR, 9, 7, | |
| 971 | + CLK_IGNORE_UNUSED), | |
| 972 | + M_ODF_F("pll1_q", "vco1", RCC_PLLCFGR, 17, RCC_PLL1DIVR, 16, 7, | |
| 973 | + CLK_IGNORE_UNUSED), | |
| 974 | + M_ODF_F("pll1_r", "vco1", RCC_PLLCFGR, 18, RCC_PLL1DIVR, 24, 7, | |
| 975 | + CLK_IGNORE_UNUSED), | |
| 976 | + }, | |
| 977 | + | |
| 978 | + { | |
| 979 | + M_ODF("pll2_p", "vco2", RCC_PLLCFGR, 19, RCC_PLL2DIVR, 9, 7), | |
| 980 | + M_ODF("pll2_q", "vco2", RCC_PLLCFGR, 20, RCC_PLL2DIVR, 16, 7), | |
| 981 | + M_ODF("pll2_r", "vco2", RCC_PLLCFGR, 21, RCC_PLL2DIVR, 24, 7), | |
| 982 | + }, | |
| 983 | + { | |
| 984 | + M_ODF("pll3_p", "vco3", RCC_PLLCFGR, 22, RCC_PLL3DIVR, 9, 7), | |
| 985 | + M_ODF("pll3_q", "vco3", RCC_PLLCFGR, 23, RCC_PLL3DIVR, 16, 7), | |
| 986 | + M_ODF("pll3_r", "vco3", RCC_PLLCFGR, 24, RCC_PLL3DIVR, 24, 7), | |
| 987 | + } | |
| 988 | +}; | |
| 989 | + | |
| 990 | +/* PERIF CLOCKS */ | |
| 991 | +struct pclk_t { | |
| 992 | + u32 gate_offset; | |
| 993 | + u8 bit_idx; | |
| 994 | + const char *name; | |
| 995 | + const char *parent; | |
| 996 | + u32 flags; | |
| 997 | +}; | |
| 998 | + | |
| 999 | +#define PER_CLKF(_gate_offset, _bit_idx, _name, _parent, _flags)\ | |
| 1000 | +{\ | |
| 1001 | + .gate_offset = _gate_offset,\ | |
| 1002 | + .bit_idx = _bit_idx,\ | |
| 1003 | + .name = _name,\ | |
| 1004 | + .parent = _parent,\ | |
| 1005 | + .flags = _flags,\ | |
| 1006 | +} | |
| 1007 | + | |
| 1008 | +#define PER_CLK(_gate_offset, _bit_idx, _name, _parent)\ | |
| 1009 | + PER_CLKF(_gate_offset, _bit_idx, _name, _parent, 0) | |
| 1010 | + | |
| 1011 | +static const struct pclk_t pclk[] = { | |
| 1012 | + PER_CLK(RCC_AHB3ENR, 31, "d1sram1", "hclk"), | |
| 1013 | + PER_CLK(RCC_AHB3ENR, 30, "itcm", "hclk"), | |
| 1014 | + PER_CLK(RCC_AHB3ENR, 29, "dtcm2", "hclk"), | |
| 1015 | + PER_CLK(RCC_AHB3ENR, 28, "dtcm1", "hclk"), | |
| 1016 | + PER_CLK(RCC_AHB3ENR, 8, "flitf", "hclk"), | |
| 1017 | + PER_CLK(RCC_AHB3ENR, 5, "jpgdec", "hclk"), | |
| 1018 | + PER_CLK(RCC_AHB3ENR, 4, "dma2d", "hclk"), | |
| 1019 | + PER_CLK(RCC_AHB3ENR, 0, "mdma", "hclk"), | |
| 1020 | + PER_CLK(RCC_AHB1ENR, 28, "usb2ulpi", "hclk"), | |
| 1021 | + PER_CLK(RCC_AHB1ENR, 26, "usb1ulpi", "hclk"), | |
| 1022 | + PER_CLK(RCC_AHB1ENR, 17, "eth1rx", "hclk"), | |
| 1023 | + PER_CLK(RCC_AHB1ENR, 16, "eth1tx", "hclk"), | |
| 1024 | + PER_CLK(RCC_AHB1ENR, 15, "eth1mac", "hclk"), | |
| 1025 | + PER_CLK(RCC_AHB1ENR, 14, "art", "hclk"), | |
| 1026 | + PER_CLK(RCC_AHB1ENR, 1, "dma2", "hclk"), | |
| 1027 | + PER_CLK(RCC_AHB1ENR, 0, "dma1", "hclk"), | |
| 1028 | + PER_CLK(RCC_AHB2ENR, 31, "d2sram3", "hclk"), | |
| 1029 | + PER_CLK(RCC_AHB2ENR, 30, "d2sram2", "hclk"), | |
| 1030 | + PER_CLK(RCC_AHB2ENR, 29, "d2sram1", "hclk"), | |
| 1031 | + PER_CLK(RCC_AHB2ENR, 5, "hash", "hclk"), | |
| 1032 | + PER_CLK(RCC_AHB2ENR, 4, "crypt", "hclk"), | |
| 1033 | + PER_CLK(RCC_AHB2ENR, 0, "camitf", "hclk"), | |
| 1034 | + PER_CLK(RCC_AHB4ENR, 28, "bkpram", "hclk"), | |
| 1035 | + PER_CLK(RCC_AHB4ENR, 25, "hsem", "hclk"), | |
| 1036 | + PER_CLK(RCC_AHB4ENR, 21, "bdma", "hclk"), | |
| 1037 | + PER_CLK(RCC_AHB4ENR, 19, "crc", "hclk"), | |
| 1038 | + PER_CLK(RCC_AHB4ENR, 10, "gpiok", "hclk"), | |
| 1039 | + PER_CLK(RCC_AHB4ENR, 9, "gpioj", "hclk"), | |
| 1040 | + PER_CLK(RCC_AHB4ENR, 8, "gpioi", "hclk"), | |
| 1041 | + PER_CLK(RCC_AHB4ENR, 7, "gpioh", "hclk"), | |
| 1042 | + PER_CLK(RCC_AHB4ENR, 6, "gpiog", "hclk"), | |
| 1043 | + PER_CLK(RCC_AHB4ENR, 5, "gpiof", "hclk"), | |
| 1044 | + PER_CLK(RCC_AHB4ENR, 4, "gpioe", "hclk"), | |
| 1045 | + PER_CLK(RCC_AHB4ENR, 3, "gpiod", "hclk"), | |
| 1046 | + PER_CLK(RCC_AHB4ENR, 2, "gpioc", "hclk"), | |
| 1047 | + PER_CLK(RCC_AHB4ENR, 1, "gpiob", "hclk"), | |
| 1048 | + PER_CLK(RCC_AHB4ENR, 0, "gpioa", "hclk"), | |
| 1049 | + PER_CLK(RCC_APB3ENR, 6, "wwdg1", "pclk3"), | |
| 1050 | + PER_CLK(RCC_APB1LENR, 29, "dac12", "pclk1"), | |
| 1051 | + PER_CLK(RCC_APB1LENR, 11, "wwdg2", "pclk1"), | |
| 1052 | + PER_CLK(RCC_APB1LENR, 8, "tim14", "tim1_ker"), | |
| 1053 | + PER_CLK(RCC_APB1LENR, 7, "tim13", "tim1_ker"), | |
| 1054 | + PER_CLK(RCC_APB1LENR, 6, "tim12", "tim1_ker"), | |
| 1055 | + PER_CLK(RCC_APB1LENR, 5, "tim7", "tim1_ker"), | |
| 1056 | + PER_CLK(RCC_APB1LENR, 4, "tim6", "tim1_ker"), | |
| 1057 | + PER_CLK(RCC_APB1LENR, 3, "tim5", "tim1_ker"), | |
| 1058 | + PER_CLK(RCC_APB1LENR, 2, "tim4", "tim1_ker"), | |
| 1059 | + PER_CLK(RCC_APB1LENR, 1, "tim3", "tim1_ker"), | |
| 1060 | + PER_CLK(RCC_APB1LENR, 0, "tim2", "tim1_ker"), | |
| 1061 | + PER_CLK(RCC_APB1HENR, 5, "mdios", "pclk1"), | |
| 1062 | + PER_CLK(RCC_APB1HENR, 4, "opamp", "pclk1"), | |
| 1063 | + PER_CLK(RCC_APB1HENR, 1, "crs", "pclk1"), | |
| 1064 | + PER_CLK(RCC_APB2ENR, 18, "tim17", "tim2_ker"), | |
| 1065 | + PER_CLK(RCC_APB2ENR, 17, "tim16", "tim2_ker"), | |
| 1066 | + PER_CLK(RCC_APB2ENR, 16, "tim15", "tim2_ker"), | |
| 1067 | + PER_CLK(RCC_APB2ENR, 1, "tim8", "tim2_ker"), | |
| 1068 | + PER_CLK(RCC_APB2ENR, 0, "tim1", "tim2_ker"), | |
| 1069 | + PER_CLK(RCC_APB4ENR, 26, "tmpsens", "pclk4"), | |
| 1070 | + PER_CLK(RCC_APB4ENR, 16, "rtcapb", "pclk4"), | |
| 1071 | + PER_CLK(RCC_APB4ENR, 15, "vref", "pclk4"), | |
| 1072 | + PER_CLK(RCC_APB4ENR, 14, "comp12", "pclk4"), | |
| 1073 | + PER_CLK(RCC_APB4ENR, 1, "syscfg", "pclk4"), | |
| 1074 | +}; | |
| 1075 | + | |
| 1076 | +/* KERNEL CLOCKS */ | |
| 1077 | +#define KER_CLKF(_gate_offset, _bit_idx,\ | |
| 1078 | + _mux_offset, _mux_shift, _mux_width,\ | |
| 1079 | + _name, _parent_name,\ | |
| 1080 | + _flags) \ | |
| 1081 | +{ \ | |
| 1082 | + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ | |
| 1083 | + .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ | |
| 1084 | + .name = _name, \ | |
| 1085 | + .parent_name = _parent_name, \ | |
| 1086 | + .num_parents = ARRAY_SIZE(_parent_name),\ | |
| 1087 | + .flags = _flags,\ | |
| 1088 | +} | |
| 1089 | + | |
| 1090 | +#define KER_CLK(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ | |
| 1091 | + _name, _parent_name) \ | |
| 1092 | +KER_CLKF(_gate_offset, _bit_idx, _mux_offset, _mux_shift, _mux_width,\ | |
| 1093 | + _name, _parent_name, 0)\ | |
| 1094 | + | |
| 1095 | +#define KER_CLKF_NOMUX(_gate_offset, _bit_idx,\ | |
| 1096 | + _name, _parent_name,\ | |
| 1097 | + _flags) \ | |
| 1098 | +{ \ | |
| 1099 | + .gate = &(struct gate_cfg) {_gate_offset, _bit_idx},\ | |
| 1100 | + .mux = NULL,\ | |
| 1101 | + .name = _name, \ | |
| 1102 | + .parent_name = _parent_name, \ | |
| 1103 | + .num_parents = 1,\ | |
| 1104 | + .flags = _flags,\ | |
| 1105 | +} | |
| 1106 | + | |
| 1107 | +static const struct composite_clk_cfg kclk[] = { | |
| 1108 | + KER_CLK(RCC_AHB3ENR, 16, RCC_D1CCIPR, 16, 1, "sdmmc1", sdmmc_src), | |
| 1109 | + KER_CLKF(RCC_AHB3ENR, 14, RCC_D1CCIPR, 4, 2, "quadspi", qspi_src, | |
| 1110 | + CLK_IGNORE_UNUSED), | |
| 1111 | + KER_CLKF(RCC_AHB3ENR, 12, RCC_D1CCIPR, 0, 2, "fmc", fmc_src, | |
| 1112 | + CLK_IGNORE_UNUSED), | |
| 1113 | + KER_CLK(RCC_AHB1ENR, 27, RCC_D2CCIP2R, 20, 2, "usb2otg", usbotg_src), | |
| 1114 | + KER_CLK(RCC_AHB1ENR, 25, RCC_D2CCIP2R, 20, 2, "usb1otg", usbotg_src), | |
| 1115 | + KER_CLK(RCC_AHB1ENR, 5, RCC_D3CCIPR, 16, 2, "adc12", adc_src), | |
| 1116 | + KER_CLK(RCC_AHB2ENR, 9, RCC_D1CCIPR, 16, 1, "sdmmc2", sdmmc_src), | |
| 1117 | + KER_CLK(RCC_AHB2ENR, 6, RCC_D2CCIP2R, 8, 2, "rng", rng_src), | |
| 1118 | + KER_CLK(RCC_AHB4ENR, 24, RCC_D3CCIPR, 16, 2, "adc3", adc_src), | |
| 1119 | + KER_CLKF(RCC_APB3ENR, 4, RCC_D1CCIPR, 8, 1, "dsi", dsi_src, | |
| 1120 | + CLK_SET_RATE_PARENT), | |
| 1121 | + KER_CLKF_NOMUX(RCC_APB3ENR, 3, "ltdc", ltdc_src, CLK_SET_RATE_PARENT), | |
| 1122 | + KER_CLK(RCC_APB1LENR, 31, RCC_D2CCIP2R, 0, 3, "usart8", usart_src2), | |
| 1123 | + KER_CLK(RCC_APB1LENR, 30, RCC_D2CCIP2R, 0, 3, "usart7", usart_src2), | |
| 1124 | + KER_CLK(RCC_APB1LENR, 27, RCC_D2CCIP2R, 22, 2, "hdmicec", cec_src), | |
| 1125 | + KER_CLK(RCC_APB1LENR, 23, RCC_D2CCIP2R, 12, 2, "i2c3", i2c_src1), | |
| 1126 | + KER_CLK(RCC_APB1LENR, 22, RCC_D2CCIP2R, 12, 2, "i2c2", i2c_src1), | |
| 1127 | + KER_CLK(RCC_APB1LENR, 21, RCC_D2CCIP2R, 12, 2, "i2c1", i2c_src1), | |
| 1128 | + KER_CLK(RCC_APB1LENR, 20, RCC_D2CCIP2R, 0, 3, "uart5", usart_src2), | |
| 1129 | + KER_CLK(RCC_APB1LENR, 19, RCC_D2CCIP2R, 0, 3, "uart4", usart_src2), | |
| 1130 | + KER_CLK(RCC_APB1LENR, 18, RCC_D2CCIP2R, 0, 3, "usart3", usart_src2), | |
| 1131 | + KER_CLK(RCC_APB1LENR, 17, RCC_D2CCIP2R, 0, 3, "usart2", usart_src2), | |
| 1132 | + KER_CLK(RCC_APB1LENR, 16, RCC_D2CCIP1R, 20, 2, "spdifrx", spdifrx_src), | |
| 1133 | + KER_CLK(RCC_APB1LENR, 15, RCC_D2CCIP1R, 16, 3, "spi3", spi_src1), | |
| 1134 | + KER_CLK(RCC_APB1LENR, 14, RCC_D2CCIP1R, 16, 3, "spi2", spi_src1), | |
| 1135 | + KER_CLK(RCC_APB1LENR, 9, RCC_D2CCIP2R, 28, 3, "lptim1", lptim_src1), | |
| 1136 | + KER_CLK(RCC_APB1HENR, 8, RCC_D2CCIP1R, 28, 2, "fdcan", fdcan_src), | |
| 1137 | + KER_CLK(RCC_APB1HENR, 2, RCC_D2CCIP1R, 31, 1, "swp", swp_src), | |
| 1138 | + KER_CLK(RCC_APB2ENR, 29, RCC_CFGR, 14, 1, "hrtim", hrtim_src), | |
| 1139 | + KER_CLK(RCC_APB2ENR, 28, RCC_D2CCIP1R, 24, 1, "dfsdm1", dfsdm1_src), | |
| 1140 | + KER_CLKF(RCC_APB2ENR, 24, RCC_D2CCIP1R, 6, 3, "sai3", sai_src, | |
| 1141 | + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | |
| 1142 | + KER_CLKF(RCC_APB2ENR, 23, RCC_D2CCIP1R, 6, 3, "sai2", sai_src, | |
| 1143 | + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | |
| 1144 | + KER_CLKF(RCC_APB2ENR, 22, RCC_D2CCIP1R, 0, 3, "sai1", sai_src, | |
| 1145 | + CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT), | |
| 1146 | + KER_CLK(RCC_APB2ENR, 20, RCC_D2CCIP1R, 16, 3, "spi5", spi_src2), | |
| 1147 | + KER_CLK(RCC_APB2ENR, 13, RCC_D2CCIP1R, 16, 3, "spi4", spi_src2), | |
| 1148 | + KER_CLK(RCC_APB2ENR, 12, RCC_D2CCIP1R, 16, 3, "spi1", spi_src1), | |
| 1149 | + KER_CLK(RCC_APB2ENR, 5, RCC_D2CCIP2R, 3, 3, "usart6", usart_src1), | |
| 1150 | + KER_CLK(RCC_APB2ENR, 4, RCC_D2CCIP2R, 3, 3, "usart1", usart_src1), | |
| 1151 | + KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 24, 3, "sai4b", sai_src), | |
| 1152 | + KER_CLK(RCC_APB4ENR, 21, RCC_D3CCIPR, 21, 3, "sai4a", sai_src), | |
| 1153 | + KER_CLK(RCC_APB4ENR, 12, RCC_D3CCIPR, 13, 3, "lptim5", lptim_src2), | |
| 1154 | + KER_CLK(RCC_APB4ENR, 11, RCC_D3CCIPR, 13, 3, "lptim4", lptim_src2), | |
| 1155 | + KER_CLK(RCC_APB4ENR, 10, RCC_D3CCIPR, 13, 3, "lptim3", lptim_src2), | |
| 1156 | + KER_CLK(RCC_APB4ENR, 9, RCC_D3CCIPR, 10, 3, "lptim2", lptim_src2), | |
| 1157 | + KER_CLK(RCC_APB4ENR, 7, RCC_D3CCIPR, 8, 2, "i2c4", i2c_src2), | |
| 1158 | + KER_CLK(RCC_APB4ENR, 5, RCC_D3CCIPR, 28, 3, "spi6", spi_src3), | |
| 1159 | + KER_CLK(RCC_APB4ENR, 3, RCC_D3CCIPR, 0, 3, "lpuart1", lpuart1_src), | |
| 1160 | +}; | |
| 1161 | + | |
| 1162 | +static struct composite_clk_gcfg kernel_clk_cfg = { | |
| 1163 | + M_CFG_MUX(NULL, 0), | |
| 1164 | + M_CFG_GATE(NULL, 0), | |
| 1165 | +}; | |
| 1166 | + | |
| 1167 | +/* RTC clock */ | |
| 1168 | +/* | |
| 1169 | + * RTC & LSE registers are protected against parasitic write access. | |
| 1170 | + * PWR_CR_DBP bit must be set to enable write access to RTC registers. | |
| 1171 | + */ | |
| 1172 | +/* STM32_PWR_CR */ | |
| 1173 | +#define PWR_CR 0x00 | |
| 1174 | +/* STM32_PWR_CR bit field */ | |
| 1175 | +#define PWR_CR_DBP BIT(8) | |
| 1176 | + | |
| 1177 | +static struct composite_clk_gcfg rtc_clk_cfg = { | |
| 1178 | + M_CFG_MUX(NULL, 0), | |
| 1179 | + M_CFG_GATE(NULL, 0), | |
| 1180 | +}; | |
| 1181 | + | |
| 1182 | +static const struct composite_clk_cfg rtc_clk = | |
| 1183 | + KER_CLK(RCC_BDCR, 15, RCC_BDCR, 8, 2, "rtc_ck", rtc_src); | |
| 1184 | + | |
| 1185 | +/* Micro-controller output clock */ | |
| 1186 | +static struct composite_clk_gcfg mco_clk_cfg = { | |
| 1187 | + M_CFG_MUX(NULL, 0), | |
| 1188 | + M_CFG_DIV(NULL, CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO), | |
| 1189 | +}; | |
| 1190 | + | |
| 1191 | +#define M_MCO_F(_name, _parents, _mux_offset, _mux_shift, _mux_width,\ | |
| 1192 | + _rate_offset, _rate_shift, _rate_width,\ | |
| 1193 | + _flags)\ | |
| 1194 | +{\ | |
| 1195 | + .mux = &(struct muxdiv_cfg) {_mux_offset, _mux_shift, _mux_width },\ | |
| 1196 | + .div = &(struct muxdiv_cfg) {_rate_offset, _rate_shift, _rate_width},\ | |
| 1197 | + .gate = NULL,\ | |
| 1198 | + .name = _name,\ | |
| 1199 | + .parent_name = _parents,\ | |
| 1200 | + .num_parents = ARRAY_SIZE(_parents),\ | |
| 1201 | + .flags = _flags,\ | |
| 1202 | +} | |
| 1203 | + | |
| 1204 | +static const struct composite_clk_cfg mco_clk[] = { | |
| 1205 | + M_MCO_F("mco1", mco_src1, RCC_CFGR, 22, 4, RCC_CFGR, 18, 4, 0), | |
| 1206 | + M_MCO_F("mco2", mco_src2, RCC_CFGR, 29, 3, RCC_CFGR, 25, 4, 0), | |
| 1207 | +}; | |
| 1208 | + | |
| 1209 | +static void __init stm32h7_rcc_init(struct device_node *np) | |
| 1210 | +{ | |
| 1211 | + struct clk_hw_onecell_data *clk_data; | |
| 1212 | + struct composite_cfg c_cfg; | |
| 1213 | + int n; | |
| 1214 | + const char *hse_clk, *lse_clk, *i2s_clk; | |
| 1215 | + struct regmap *pdrm; | |
| 1216 | + | |
| 1217 | + clk_data = kzalloc(sizeof(*clk_data) + | |
| 1218 | + sizeof(*clk_data->hws) * STM32H7_MAX_CLKS, | |
| 1219 | + GFP_KERNEL); | |
| 1220 | + if (!clk_data) | |
| 1221 | + return; | |
| 1222 | + | |
| 1223 | + clk_data->num = STM32H7_MAX_CLKS; | |
| 1224 | + | |
| 1225 | + hws = clk_data->hws; | |
| 1226 | + | |
| 1227 | + for (n = 0; n < STM32H7_MAX_CLKS; n++) | |
| 1228 | + hws[n] = ERR_PTR(-ENOENT); | |
| 1229 | + | |
| 1230 | + /* get RCC base @ from DT */ | |
| 1231 | + base = of_iomap(np, 0); | |
| 1232 | + if (!base) { | |
| 1233 | + pr_err("%s: unable to map resource", np->name); | |
| 1234 | + goto err_free_clks; | |
| 1235 | + } | |
| 1236 | + | |
| 1237 | + pdrm = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); | |
| 1238 | + if (IS_ERR(pdrm)) | |
| 1239 | + pr_warn("%s: Unable to get syscfg\n", __func__); | |
| 1240 | + else | |
| 1241 | + /* In any case disable backup domain write protection | |
| 1242 | + * and will never be enabled. | |
| 1243 | + * Needed by LSE & RTC clocks. | |
| 1244 | + */ | |
| 1245 | + regmap_update_bits(pdrm, PWR_CR, PWR_CR_DBP, PWR_CR_DBP); | |
| 1246 | + | |
| 1247 | + /* Put parent names from DT */ | |
| 1248 | + hse_clk = of_clk_get_parent_name(np, 0); | |
| 1249 | + lse_clk = of_clk_get_parent_name(np, 1); | |
| 1250 | + i2s_clk = of_clk_get_parent_name(np, 2); | |
| 1251 | + | |
| 1252 | + sai_src[3] = i2s_clk; | |
| 1253 | + spi_src1[3] = i2s_clk; | |
| 1254 | + | |
| 1255 | + /* Register Internal oscillators */ | |
| 1256 | + clk_hw_register_fixed_rate(NULL, "clk-hsi", NULL, 0, 64000000); | |
| 1257 | + clk_hw_register_fixed_rate(NULL, "clk-csi", NULL, 0, 4000000); | |
| 1258 | + clk_hw_register_fixed_rate(NULL, "clk-lsi", NULL, 0, 32000); | |
| 1259 | + clk_hw_register_fixed_rate(NULL, "clk-rc48", NULL, 0, 48000); | |
| 1260 | + | |
| 1261 | + /* This clock is coming from outside. Frequencies unknown */ | |
| 1262 | + hws[CK_DSI_PHY] = clk_hw_register_fixed_rate(NULL, "ck_dsi_phy", NULL, | |
| 1263 | + 0, 0); | |
| 1264 | + | |
| 1265 | + hws[HSI_DIV] = clk_hw_register_divider(NULL, "hsidiv", "clk-hsi", 0, | |
| 1266 | + base + RCC_CR, 3, 2, CLK_DIVIDER_POWER_OF_TWO, | |
| 1267 | + &stm32rcc_lock); | |
| 1268 | + | |
| 1269 | + hws[HSE_1M] = clk_hw_register_divider(NULL, "hse_1M", "hse_ck", 0, | |
| 1270 | + base + RCC_CFGR, 8, 6, CLK_DIVIDER_ONE_BASED | | |
| 1271 | + CLK_DIVIDER_ALLOW_ZERO, | |
| 1272 | + &stm32rcc_lock); | |
| 1273 | + | |
| 1274 | + /* Mux system clocks */ | |
| 1275 | + for (n = 0; n < ARRAY_SIZE(stm32_mclk); n++) | |
| 1276 | + hws[MCLK_BANK + n] = clk_hw_register_mux(NULL, | |
| 1277 | + stm32_mclk[n].name, | |
| 1278 | + stm32_mclk[n].parents, | |
| 1279 | + stm32_mclk[n].num_parents, | |
| 1280 | + stm32_mclk[n].flags, | |
| 1281 | + stm32_mclk[n].offset + base, | |
| 1282 | + stm32_mclk[n].shift, | |
| 1283 | + stm32_mclk[n].width, | |
| 1284 | + 0, | |
| 1285 | + &stm32rcc_lock); | |
| 1286 | + | |
| 1287 | + register_core_and_bus_clocks(); | |
| 1288 | + | |
| 1289 | + /* Oscillary clocks */ | |
| 1290 | + for (n = 0; n < ARRAY_SIZE(stm32_oclk); n++) | |
| 1291 | + hws[OSC_BANK + n] = clk_register_ready_gate(NULL, | |
| 1292 | + stm32_oclk[n].name, | |
| 1293 | + stm32_oclk[n].parent, | |
| 1294 | + stm32_oclk[n].gate_offset + base, | |
| 1295 | + stm32_oclk[n].bit_idx, | |
| 1296 | + stm32_oclk[n].bit_rdy, | |
| 1297 | + stm32_oclk[n].flags, | |
| 1298 | + &stm32rcc_lock); | |
| 1299 | + | |
| 1300 | + hws[HSE_CK] = clk_register_ready_gate(NULL, | |
| 1301 | + "hse_ck", | |
| 1302 | + hse_clk, | |
| 1303 | + RCC_CR + base, | |
| 1304 | + 16, 17, | |
| 1305 | + 0, | |
| 1306 | + &stm32rcc_lock); | |
| 1307 | + | |
| 1308 | + hws[LSE_CK] = clk_register_ready_gate(NULL, | |
| 1309 | + "lse_ck", | |
| 1310 | + lse_clk, | |
| 1311 | + RCC_BDCR + base, | |
| 1312 | + 0, 1, | |
| 1313 | + 0, | |
| 1314 | + &stm32rcc_lock); | |
| 1315 | + | |
| 1316 | + hws[CSI_KER_DIV122 + n] = clk_hw_register_fixed_factor(NULL, | |
| 1317 | + "csi_ker_div122", "csi_ker", 0, 1, 122); | |
| 1318 | + | |
| 1319 | + /* PLLs */ | |
| 1320 | + for (n = 0; n < ARRAY_SIZE(stm32_pll); n++) { | |
| 1321 | + int odf; | |
| 1322 | + | |
| 1323 | + /* Register the VCO */ | |
| 1324 | + clk_register_stm32_pll(NULL, stm32_pll[n].name, | |
| 1325 | + stm32_pll[n].parent_name, stm32_pll[n].flags, | |
| 1326 | + stm32_pll[n].cfg, | |
| 1327 | + &stm32rcc_lock); | |
| 1328 | + | |
| 1329 | + /* Register the 3 output dividers */ | |
| 1330 | + for (odf = 0; odf < 3; odf++) { | |
| 1331 | + int idx = n * 3 + odf; | |
| 1332 | + | |
| 1333 | + get_cfg_composite_div(&odf_clk_gcfg, &stm32_odf[n][odf], | |
| 1334 | + &c_cfg, &stm32rcc_lock); | |
| 1335 | + | |
| 1336 | + hws[ODF_BANK + idx] = clk_hw_register_composite(NULL, | |
| 1337 | + stm32_odf[n][odf].name, | |
| 1338 | + stm32_odf[n][odf].parent_name, | |
| 1339 | + stm32_odf[n][odf].num_parents, | |
| 1340 | + c_cfg.mux_hw, c_cfg.mux_ops, | |
| 1341 | + c_cfg.div_hw, c_cfg.div_ops, | |
| 1342 | + c_cfg.gate_hw, c_cfg.gate_ops, | |
| 1343 | + stm32_odf[n][odf].flags); | |
| 1344 | + } | |
| 1345 | + } | |
| 1346 | + | |
| 1347 | + /* Peripheral clocks */ | |
| 1348 | + for (n = 0; n < ARRAY_SIZE(pclk); n++) | |
| 1349 | + hws[PERIF_BANK + n] = clk_hw_register_gate(NULL, pclk[n].name, | |
| 1350 | + pclk[n].parent, | |
| 1351 | + pclk[n].flags, base + pclk[n].gate_offset, | |
| 1352 | + pclk[n].bit_idx, pclk[n].flags, &stm32rcc_lock); | |
| 1353 | + | |
| 1354 | + /* Kernel clocks */ | |
| 1355 | + for (n = 0; n < ARRAY_SIZE(kclk); n++) { | |
| 1356 | + get_cfg_composite_div(&kernel_clk_cfg, &kclk[n], &c_cfg, | |
| 1357 | + &stm32rcc_lock); | |
| 1358 | + | |
| 1359 | + hws[KERN_BANK + n] = clk_hw_register_composite(NULL, | |
| 1360 | + kclk[n].name, | |
| 1361 | + kclk[n].parent_name, | |
| 1362 | + kclk[n].num_parents, | |
| 1363 | + c_cfg.mux_hw, c_cfg.mux_ops, | |
| 1364 | + c_cfg.div_hw, c_cfg.div_ops, | |
| 1365 | + c_cfg.gate_hw, c_cfg.gate_ops, | |
| 1366 | + kclk[n].flags); | |
| 1367 | + } | |
| 1368 | + | |
| 1369 | + /* RTC clock (default state is off) */ | |
| 1370 | + clk_hw_register_fixed_rate(NULL, "off", NULL, 0, 0); | |
| 1371 | + | |
| 1372 | + get_cfg_composite_div(&rtc_clk_cfg, &rtc_clk, &c_cfg, &stm32rcc_lock); | |
| 1373 | + | |
| 1374 | + hws[RTC_CK] = clk_hw_register_composite(NULL, | |
| 1375 | + rtc_clk.name, | |
| 1376 | + rtc_clk.parent_name, | |
| 1377 | + rtc_clk.num_parents, | |
| 1378 | + c_cfg.mux_hw, c_cfg.mux_ops, | |
| 1379 | + c_cfg.div_hw, c_cfg.div_ops, | |
| 1380 | + c_cfg.gate_hw, c_cfg.gate_ops, | |
| 1381 | + rtc_clk.flags); | |
| 1382 | + | |
| 1383 | + /* Micro-controller clocks */ | |
| 1384 | + for (n = 0; n < ARRAY_SIZE(mco_clk); n++) { | |
| 1385 | + get_cfg_composite_div(&mco_clk_cfg, &mco_clk[n], &c_cfg, | |
| 1386 | + &stm32rcc_lock); | |
| 1387 | + | |
| 1388 | + hws[MCO_BANK + n] = clk_hw_register_composite(NULL, | |
| 1389 | + mco_clk[n].name, | |
| 1390 | + mco_clk[n].parent_name, | |
| 1391 | + mco_clk[n].num_parents, | |
| 1392 | + c_cfg.mux_hw, c_cfg.mux_ops, | |
| 1393 | + c_cfg.div_hw, c_cfg.div_ops, | |
| 1394 | + c_cfg.gate_hw, c_cfg.gate_ops, | |
| 1395 | + mco_clk[n].flags); | |
| 1396 | + } | |
| 1397 | + | |
| 1398 | + of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); | |
| 1399 | + | |
| 1400 | + return; | |
| 1401 | + | |
| 1402 | +err_free_clks: | |
| 1403 | + kfree(clk_data); | |
| 1404 | +} | |
| 1405 | + | |
| 1406 | +/* The RCC node is a clock and reset controller, and these | |
| 1407 | + * functionalities are supported by different drivers that | |
| 1408 | + * matches the same compatible strings. | |
| 1409 | + */ | |
| 1410 | +CLK_OF_DECLARE_DRIVER(stm32h7_rcc, "st,stm32h743-rcc", stm32h7_rcc_init); | |
| @@ -57,6 +57,7 @@ · 56 unmodified lines | ||
| 57 | 57 | #define VC5_PRIM_SRC_SHDN 0x10 |
| 58 | 58 | #define VC5_PRIM_SRC_SHDN_EN_XTAL BIT(7) |
| 59 | 59 | #define VC5_PRIM_SRC_SHDN_EN_CLKIN BIT(6) |
| 60 | +#define VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ BIT(3) | |
| 60 | 61 | #define VC5_PRIM_SRC_SHDN_SP BIT(1) |
| 61 | 62 | #define VC5_PRIM_SRC_SHDN_EN_GBL_SHDN BIT(0) |
| 62 | 63 | |
| @@ -122,12 +123,16 @@ · 59 unmodified lines | ||
| 122 | 123 | /* flags to describe chip features */ |
| 123 | 124 | /* chip has built-in oscilator */ |
| 124 | 125 | #define VC5_HAS_INTERNAL_XTAL BIT(0) |
| 126 | +/* chip has PFD requency doubler */ | |
| 127 | +#define VC5_HAS_PFD_FREQ_DBL BIT(1) | |
| 125 | 128 | |
| 126 | 129 | /* Supported IDT VC5 models. */ |
| 127 | 130 | enum vc5_model { |
| 128 | 131 | IDT_VC5_5P49V5923, |
| 132 | + IDT_VC5_5P49V5925, | |
| 129 | 133 | IDT_VC5_5P49V5933, |
| 130 | 134 | IDT_VC5_5P49V5935, |
| 135 | + IDT_VC6_5P49V6901, | |
| 131 | 136 | }; |
| 132 | 137 | |
| 133 | 138 | /* Structure to describe features of a particular VC5 model */ |
| @@ -157,6 +162,8 @@ struct vc5_driver_data { · 23 unmodified lines | ||
| 157 | 162 | struct clk *pin_clkin; |
| 158 | 163 | unsigned char clk_mux_ins; |
| 159 | 164 | struct clk_hw clk_mux; |
| 165 | + struct clk_hw clk_mul; | |
| 166 | + struct clk_hw clk_pfd; | |
| 160 | 167 | struct vc5_hw_data clk_pll; |
| 161 | 168 | struct vc5_hw_data clk_fod[VC5_MAX_FOD_NUM]; |
| 162 | 169 | struct vc5_hw_data clk_out[VC5_MAX_CLK_OUT_NUM]; |
| @@ -166,6 +173,14 @@ static const char * const vc5_mux_names[] = { · 3 unmodified lines | ||
| 166 | 173 | "mux" |
| 167 | 174 | }; |
| 168 | 175 | |
| 176 | +static const char * const vc5_dbl_names[] = { | |
| 177 | + "dbl" | |
| 178 | +}; | |
| 179 | + | |
| 180 | +static const char * const vc5_pfd_names[] = { | |
| 181 | + "pfd" | |
| 182 | +}; | |
| 183 | + | |
| 169 | 184 | static const char * const vc5_pll_names[] = { |
| 170 | 185 | "pll" |
| 171 | 186 | }; |
| @@ -254,11 +269,64 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index) · 82 unmodified lines | ||
| 254 | 269 | return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src); |
| 255 | 270 | } |
| 256 | 271 | |
| 257 | −static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, | |
| 272 | +static const struct clk_ops vc5_mux_ops = { | |
| 273 | + .set_parent = vc5_mux_set_parent, | |
| 274 | + .get_parent = vc5_mux_get_parent, | |
| 275 | +}; | |
| 276 | + | |
| 277 | +static unsigned long vc5_dbl_recalc_rate(struct clk_hw *hw, | |
| 258 | 278 | unsigned long parent_rate) |
| 259 | 279 | { |
| 260 | 280 | struct vc5_driver_data *vc5 = |
| 261 | − container_of(hw, struct vc5_driver_data, clk_mux); | |
| 281 | + container_of(hw, struct vc5_driver_data, clk_mul); | |
| 282 | + unsigned int premul; | |
| 283 | + | |
| 284 | + regmap_read(vc5->regmap, VC5_PRIM_SRC_SHDN, &premul); | |
| 285 | + if (premul & VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ) | |
| 286 | + parent_rate *= 2; | |
| 287 | + | |
| 288 | + return parent_rate; | |
| 289 | +} | |
| 290 | + | |
| 291 | +static long vc5_dbl_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 292 | + unsigned long *parent_rate) | |
| 293 | +{ | |
| 294 | + if ((*parent_rate == rate) || ((*parent_rate * 2) == rate)) | |
| 295 | + return rate; | |
| 296 | + else | |
| 297 | + return -EINVAL; | |
| 298 | +} | |
| 299 | + | |
| 300 | +static int vc5_dbl_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 301 | + unsigned long parent_rate) | |
| 302 | +{ | |
| 303 | + struct vc5_driver_data *vc5 = | |
| 304 | + container_of(hw, struct vc5_driver_data, clk_mul); | |
| 305 | + u32 mask; | |
| 306 | + | |
| 307 | + if ((parent_rate * 2) == rate) | |
| 308 | + mask = VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ; | |
| 309 | + else | |
| 310 | + mask = 0; | |
| 311 | + | |
| 312 | + regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, | |
| 313 | + VC5_PRIM_SRC_SHDN_EN_DOUBLE_XTAL_FREQ, | |
| 314 | + mask); | |
| 315 | + | |
| 316 | + return 0; | |
| 317 | +} | |
| 318 | + | |
| 319 | +static const struct clk_ops vc5_dbl_ops = { | |
| 320 | + .recalc_rate = vc5_dbl_recalc_rate, | |
| 321 | + .round_rate = vc5_dbl_round_rate, | |
| 322 | + .set_rate = vc5_dbl_set_rate, | |
| 323 | +}; | |
| 324 | + | |
| 325 | +static unsigned long vc5_pfd_recalc_rate(struct clk_hw *hw, | |
| 326 | + unsigned long parent_rate) | |
| 327 | +{ | |
| 328 | + struct vc5_driver_data *vc5 = | |
| 329 | + container_of(hw, struct vc5_driver_data, clk_pfd); | |
| 262 | 330 | unsigned int prediv, div; |
| 263 | 331 | |
| 264 | 332 | regmap_read(vc5->regmap, VC5_VCO_CTRL_AND_PREDIV, &prediv); |
| @@ -276,7 +344,7 @@ static unsigned long vc5_mux_recalc_rate(struct clk_hw *hw, · 11 unmodified lines | ||
| 276 | 344 | return parent_rate / VC5_REF_DIVIDER_REF_DIV(div); |
| 277 | 345 | } |
| 278 | 346 | |
| 279 | −static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 347 | +static long vc5_pfd_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 280 | 348 | unsigned long *parent_rate) |
| 281 | 349 | { |
| 282 | 350 | unsigned long idiv; |
| @@ -296,11 +364,11 @@ static long vc5_mux_round_rate(struct clk_hw *hw, unsigned long rate, · 13 unmodified lines | ||
| 296 | 364 | return *parent_rate / idiv; |
| 297 | 365 | } |
| 298 | 366 | |
| 299 | −static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 367 | +static int vc5_pfd_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 300 | 368 | unsigned long parent_rate) |
| 301 | 369 | { |
| 302 | 370 | struct vc5_driver_data *vc5 = |
| 303 | − container_of(hw, struct vc5_driver_data, clk_mux); | |
| 371 | + container_of(hw, struct vc5_driver_data, clk_pfd); | |
| 304 | 372 | unsigned long idiv; |
| 305 | 373 | u8 div; |
| 306 | 374 | |
| @@ -328,12 +396,10 @@ static int vc5_mux_set_rate(struct clk_hw *hw, unsigned long rate, · 21 unmodified lines | ||
| 328 | 396 | return 0; |
| 329 | 397 | } |
| 330 | 398 | |
| 331 | −static const struct clk_ops vc5_mux_ops = { | |
| 332 | − .set_parent = vc5_mux_set_parent, | |
| 333 | − .get_parent = vc5_mux_get_parent, | |
| 334 | − .recalc_rate = vc5_mux_recalc_rate, | |
| 335 | − .round_rate = vc5_mux_round_rate, | |
| 336 | − .set_rate = vc5_mux_set_rate, | |
| 399 | +static const struct clk_ops vc5_pfd_ops = { | |
| 400 | + .recalc_rate = vc5_pfd_recalc_rate, | |
| 401 | + .round_rate = vc5_pfd_round_rate, | |
| 402 | + .set_rate = vc5_pfd_set_rate, | |
| 337 | 403 | }; |
| 338 | 404 | |
| 339 | 405 | /* |
| @@ -426,6 +492,10 @@ static unsigned long vc5_fod_recalc_rate(struct clk_hw *hw, · 86 unmodified lines | ||
| 426 | 492 | div_frc = (od_frc[0] << 22) | (od_frc[1] << 14) | |
| 427 | 493 | (od_frc[2] << 6) | (od_frc[3] >> 2); |
| 428 | 494 | |
| 495 | + /* Avoid division by zero if the output is not configured. */ | |
| 496 | + if (div_int == 0 && div_frc == 0) | |
| 497 | + return 0; | |
| 498 | + | |
| 429 | 499 | /* The PLL divider has 12 integer bits and 30 fractional bits */ |
| 430 | 500 | return div64_u64((u64)f_in << 24ULL, ((u64)div_int << 24ULL) + div_frc); |
| 431 | 501 | } |
| @@ -503,6 +573,25 @@ static int vc5_clk_out_prepare(struct clk_hw *hw) · 71 unmodified lines | ||
| 503 | 573 | { |
| 504 | 574 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); |
| 505 | 575 | struct vc5_driver_data *vc5 = hwdata->vc5; |
| 576 | + const u8 mask = VC5_OUT_DIV_CONTROL_SELB_NORM | | |
| 577 | + VC5_OUT_DIV_CONTROL_SEL_EXT | | |
| 578 | + VC5_OUT_DIV_CONTROL_EN_FOD; | |
| 579 | + unsigned int src; | |
| 580 | + int ret; | |
| 581 | + | |
| 582 | + /* | |
| 583 | + * If the input mux is disabled, enable it first and | |
| 584 | + * select source from matching FOD. | |
| 585 | + */ | |
| 586 | + regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); | |
| 587 | + if ((src & mask) == 0) { | |
| 588 | + src = VC5_OUT_DIV_CONTROL_RESET | VC5_OUT_DIV_CONTROL_EN_FOD; | |
| 589 | + ret = regmap_update_bits(vc5->regmap, | |
| 590 | + VC5_OUT_DIV_CONTROL(hwdata->num), | |
| 591 | + mask | VC5_OUT_DIV_CONTROL_RESET, src); | |
| 592 | + if (ret) | |
| 593 | + return ret; | |
| 594 | + } | |
| 506 | 595 | |
| 507 | 596 | /* Enable the clock buffer */ |
| 508 | 597 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), |
| @@ -516,7 +605,7 @@ static void vc5_clk_out_unprepare(struct clk_hw *hw) · 7 unmodified lines | ||
| 516 | 605 | struct vc5_hw_data *hwdata = container_of(hw, struct vc5_hw_data, hw); |
| 517 | 606 | struct vc5_driver_data *vc5 = hwdata->vc5; |
| 518 | 607 | |
| 519 | − /* Enable the clock buffer */ | |
| 608 | + /* Disable the clock buffer */ | |
| 520 | 609 | regmap_update_bits(vc5->regmap, VC5_CLK_OUTPUT_CFG(hwdata->num, 1), |
| 521 | 610 | VC5_CLK_OUTPUT_CFG1_EN_CLKBUF, 0); |
| 522 | 611 | } |
| @@ -537,6 +626,9 @@ static unsigned char vc5_clk_out_get_parent(struct clk_hw *hw) · 14 unmodified lines | ||
| 537 | 626 | regmap_read(vc5->regmap, VC5_OUT_DIV_CONTROL(hwdata->num), &src); |
| 538 | 627 | src &= mask; |
| 539 | 628 | |
| 629 | + if (src == 0) /* Input mux set to DISABLED */ | |
| 630 | + return 0; | |
| 631 | + | |
| 540 | 632 | if ((src & fodclkmask) == VC5_OUT_DIV_CONTROL_EN_FOD) |
| 541 | 633 | return 0; |
| 542 | 634 | |
| @@ -595,7 +687,9 @@ static int vc5_map_index_to_output(const enum vc5_model model, · 52 unmodified lines | ||
| 595 | 687 | case IDT_VC5_5P49V5933: |
| 596 | 688 | return (n == 0) ? 0 : 3; |
| 597 | 689 | case IDT_VC5_5P49V5923: |
| 690 | + case IDT_VC5_5P49V5925: | |
| 598 | 691 | case IDT_VC5_5P49V5935: |
| 692 | + case IDT_VC6_5P49V6901: | |
| 599 | 693 | default: |
| 600 | 694 | return n; |
| 601 | 695 | } |
| @@ -672,12 +766,46 @@ static int vc5_probe(struct i2c_client *client, · 70 unmodified lines | ||
| 672 | 766 | goto err_clk; |
| 673 | 767 | } |
| 674 | 768 | |
| 769 | + if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) { | |
| 770 | + /* Register frequency doubler */ | |
| 771 | + memset(&init, 0, sizeof(init)); | |
| 772 | + init.name = vc5_dbl_names[0]; | |
| 773 | + init.ops = &vc5_dbl_ops; | |
| 774 | + init.flags = CLK_SET_RATE_PARENT; | |
| 775 | + init.parent_names = vc5_mux_names; | |
| 776 | + init.num_parents = 1; | |
| 777 | + vc5->clk_mul.init = &init; | |
| 778 | + ret = devm_clk_hw_register(&client->dev, &vc5->clk_mul); | |
| 779 | + if (ret) { | |
| 780 | + dev_err(&client->dev, "unable to register %s\n", | |
| 781 | + init.name); | |
| 782 | + goto err_clk; | |
| 783 | + } | |
| 784 | + } | |
| 785 | + | |
| 786 | + /* Register PFD */ | |
| 787 | + memset(&init, 0, sizeof(init)); | |
| 788 | + init.name = vc5_pfd_names[0]; | |
| 789 | + init.ops = &vc5_pfd_ops; | |
| 790 | + init.flags = CLK_SET_RATE_PARENT; | |
| 791 | + if (vc5->chip_info->flags & VC5_HAS_PFD_FREQ_DBL) | |
| 792 | + init.parent_names = vc5_dbl_names; | |
| 793 | + else | |
| 794 | + init.parent_names = vc5_mux_names; | |
| 795 | + init.num_parents = 1; | |
| 796 | + vc5->clk_pfd.init = &init; | |
| 797 | + ret = devm_clk_hw_register(&client->dev, &vc5->clk_pfd); | |
| 798 | + if (ret) { | |
| 799 | + dev_err(&client->dev, "unable to register %s\n", init.name); | |
| 800 | + goto err_clk; | |
| 801 | + } | |
| 802 | + | |
| 675 | 803 | /* Register PLL */ |
| 676 | 804 | memset(&init, 0, sizeof(init)); |
| 677 | 805 | init.name = vc5_pll_names[0]; |
| 678 | 806 | init.ops = &vc5_pll_ops; |
| 679 | 807 | init.flags = CLK_SET_RATE_PARENT; |
| 680 | − init.parent_names = vc5_mux_names; | |
| 808 | + init.parent_names = vc5_pfd_names; | |
| 681 | 809 | init.num_parents = 1; |
| 682 | 810 | vc5->clk_pll.num = 0; |
| 683 | 811 | vc5->clk_pll.vc5 = vc5; |
| @@ -785,6 +913,13 @@ static const struct vc5_chip_info idt_5p49v5923_info = { · 101 unmodified lines | ||
| 785 | 913 | .flags = 0, |
| 786 | 914 | }; |
| 787 | 915 | |
| 916 | +static const struct vc5_chip_info idt_5p49v5925_info = { | |
| 917 | + .model = IDT_VC5_5P49V5925, | |
| 918 | + .clk_fod_cnt = 4, | |
| 919 | + .clk_out_cnt = 5, | |
| 920 | + .flags = 0, | |
| 921 | +}; | |
| 922 | + | |
| 788 | 923 | static const struct vc5_chip_info idt_5p49v5933_info = { |
| 789 | 924 | .model = IDT_VC5_5P49V5933, |
| 790 | 925 | .clk_fod_cnt = 2, |
| @@ -799,18 +934,29 @@ static const struct vc5_chip_info idt_5p49v5935_info = { · 8 unmodified lines | ||
| 799 | 934 | .flags = VC5_HAS_INTERNAL_XTAL, |
| 800 | 935 | }; |
| 801 | 936 | |
| 937 | +static const struct vc5_chip_info idt_5p49v6901_info = { | |
| 938 | + .model = IDT_VC6_5P49V6901, | |
| 939 | + .clk_fod_cnt = 4, | |
| 940 | + .clk_out_cnt = 5, | |
| 941 | + .flags = VC5_HAS_PFD_FREQ_DBL, | |
| 942 | +}; | |
| 943 | + | |
| 802 | 944 | static const struct i2c_device_id vc5_id[] = { |
| 803 | 945 | { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 }, |
| 946 | + { "5p49v5925", .driver_data = IDT_VC5_5P49V5925 }, | |
| 804 | 947 | { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 }, |
| 805 | 948 | { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 }, |
| 949 | + { "5p49v6901", .driver_data = IDT_VC6_5P49V6901 }, | |
| 806 | 950 | { } |
| 807 | 951 | }; |
| 808 | 952 | MODULE_DEVICE_TABLE(i2c, vc5_id); |
| 809 | 953 | |
| 810 | 954 | static const struct of_device_id clk_vc5_of_match[] = { |
| 811 | 955 | { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info }, |
| 956 | + { .compatible = "idt,5p49v5925", .data = &idt_5p49v5925_info }, | |
| 812 | 957 | { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info }, |
| 813 | 958 | { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info }, |
| 959 | + { .compatible = "idt,5p49v6901", .data = &idt_5p49v6901_info }, | |
| 814 | 960 | { }, |
| 815 | 961 | }; |
| 816 | 962 | MODULE_DEVICE_TABLE(of, clk_vc5_of_match); |
| @@ -192,7 +192,7 @@ static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_ty · 191 unmodified lines | ||
| 192 | 192 | |
| 193 | 193 | reg = of_iomap(np, 0); |
| 194 | 194 | if (reg == NULL) { |
| 195 | − pr_err("Unable to map CSR register for %s\n", np->full_name); | |
| 195 | + pr_err("Unable to map CSR register for %pOF\n", np); | |
| 196 | 196 | return; |
| 197 | 197 | } |
| 198 | 198 | of_property_read_string(np, "clock-output-names", &clk_name); |
| @@ -409,12 +409,12 @@ static void xgene_pmdclk_init(struct device_node *np) · 210 unmodified lines | ||
| 409 | 409 | /* Parse the DTS register for resource */ |
| 410 | 410 | rc = of_address_to_resource(np, 0, &res); |
| 411 | 411 | if (rc != 0) { |
| 412 | − pr_err("no DTS register for %s\n", np->full_name); | |
| 412 | + pr_err("no DTS register for %pOF\n", np); | |
| 413 | 413 | return; |
| 414 | 414 | } |
| 415 | 415 | csr_reg = of_iomap(np, 0); |
| 416 | 416 | if (!csr_reg) { |
| 417 | − pr_err("Unable to map resource for %s\n", np->full_name); | |
| 417 | + pr_err("Unable to map resource for %pOF\n", np); | |
| 418 | 418 | return; |
| 419 | 419 | } |
| 420 | 420 | of_property_read_string(np, "clock-output-names", &clk_name); |
| @@ -703,16 +703,14 @@ static void __init xgene_devclk_init(struct device_node *np) · 282 unmodified lines | ||
| 703 | 703 | rc = of_address_to_resource(np, i, &res); |
| 704 | 704 | if (rc != 0) { |
| 705 | 705 | if (i == 0) { |
| 706 | − pr_err("no DTS register for %s\n", | |
| 707 | − np->full_name); | |
| 706 | + pr_err("no DTS register for %pOF\n", np); | |
| 708 | 707 | return; |
| 709 | 708 | } |
| 710 | 709 | break; |
| 711 | 710 | } |
| 712 | 711 | map_res = of_iomap(np, i); |
| 713 | 712 | if (map_res == NULL) { |
| 714 | − pr_err("Unable to map resource %d for %s\n", | |
| 715 | − i, np->full_name); | |
| 713 | + pr_err("Unable to map resource %d for %pOF\n", i, np); | |
| 716 | 714 | goto err; |
| 717 | 715 | } |
| 718 | 716 | if (strcmp(res.name, "div-reg") == 0) |
| @@ -747,8 +745,7 @@ static void __init xgene_devclk_init(struct device_node *np) · 28 unmodified lines | ||
| 747 | 745 | pr_debug("Add %s clock\n", clk_name); |
| 748 | 746 | rc = of_clk_add_provider(np, of_clk_src_simple_get, clk); |
| 749 | 747 | if (rc != 0) |
| 750 | − pr_err("%s: could register provider clk %s\n", __func__, | |
| 751 | − np->full_name); | |
| 748 | + pr_err("%s: could register provider clk %pOF\n", __func__, np); | |
| 752 | 749 | |
| 753 | 750 | return; |
| 754 | 751 | |
| @@ -3132,7 +3132,7 @@ int of_clk_add_provider(struct device_node *np, · 3131 unmodified lines | ||
| 3132 | 3132 | mutex_lock(&of_clk_mutex); |
| 3133 | 3133 | list_add(&cp->link, &of_clk_providers); |
| 3134 | 3134 | mutex_unlock(&of_clk_mutex); |
| 3135 | − pr_debug("Added clock from %s\n", np->full_name); | |
| 3135 | + pr_debug("Added clock from %pOF\n", np); | |
| 3136 | 3136 | |
| 3137 | 3137 | ret = of_clk_set_defaults(np, true); |
| 3138 | 3138 | if (ret < 0) |
| @@ -3167,7 +3167,7 @@ int of_clk_add_hw_provider(struct device_node *np, · 28 unmodified lines | ||
| 3167 | 3167 | mutex_lock(&of_clk_mutex); |
| 3168 | 3168 | list_add(&cp->link, &of_clk_providers); |
| 3169 | 3169 | mutex_unlock(&of_clk_mutex); |
| 3170 | − pr_debug("Added clk_hw provider from %s\n", np->full_name); | |
| 3170 | + pr_debug("Added clk_hw provider from %pOF\n", np); | |
| 3171 | 3171 | |
| 3172 | 3172 | ret = of_clk_set_defaults(np, true); |
| 3173 | 3173 | if (ret < 0) |
| @@ -77,8 +77,8 @@ static struct clk *__of_clk_get_by_name(struct device_node *np, · 76 unmodified lines | ||
| 77 | 77 | break; |
| 78 | 78 | } else if (name && index >= 0) { |
| 79 | 79 | if (PTR_ERR(clk) != -EPROBE_DEFER) |
| 80 | − pr_err("ERROR: could not get clock %s:%s(%i)\n", | |
| 81 | − np->full_name, name ? name : "", index); | |
| 80 | + pr_err("ERROR: could not get clock %pOF:%s(%i)\n", | |
| 81 | + np, name ? name : "", index); | |
| 82 | 82 | return clk; |
| 83 | 83 | } |
| 84 | 84 | |
| @@ -55,9 +55,9 @@ static struct hisi_fixed_factor_clock hi6220_fixed_factor_clks[] __initdata = { · 54 unmodified lines | ||
| 55 | 55 | }; |
| 56 | 56 | |
| 57 | 57 | static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = { |
| 58 | − { HI6220_WDT0_PCLK, "wdt0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, }, | |
| 59 | − { HI6220_WDT1_PCLK, "wdt1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, }, | |
| 60 | − { HI6220_WDT2_PCLK, "wdt2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, }, | |
| 58 | + { HI6220_WDT0_PCLK, "wdt0_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 12, 0, }, | |
| 59 | + { HI6220_WDT1_PCLK, "wdt1_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 13, 0, }, | |
| 60 | + { HI6220_WDT2_PCLK, "wdt2_pclk", "ref32k", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 14, 0, }, | |
| 61 | 61 | { HI6220_TIMER0_PCLK, "timer0_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 15, 0, }, |
| 62 | 62 | { HI6220_TIMER1_PCLK, "timer1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 16, 0, }, |
| 63 | 63 | { HI6220_TIMER2_PCLK, "timer2_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 17, 0, }, |
| @@ -416,10 +416,10 @@ static void __init mx51_clocks_init(struct device_node *np) · 415 unmodified lines | ||
| 416 | 416 | |
| 417 | 417 | clk[IMX5_CLK_LP_APM] = imx_clk_mux("lp_apm", MXC_CCM_CCSR, 9, 1, |
| 418 | 418 | lp_apm_sel, ARRAY_SIZE(lp_apm_sel)); |
| 419 | − clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, | |
| 420 | − mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel)); | |
| 421 | − clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, | |
| 422 | − mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel)); | |
| 419 | + clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3, | |
| 420 | + mx51_ipu_di0_sel, ARRAY_SIZE(mx51_ipu_di0_sel), CLK_SET_RATE_PARENT); | |
| 421 | + clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3, | |
| 422 | + mx51_ipu_di1_sel, ARRAY_SIZE(mx51_ipu_di1_sel), CLK_SET_RATE_PARENT); | |
| 423 | 423 | clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1, |
| 424 | 424 | mx51_tve_ext_sel, ARRAY_SIZE(mx51_tve_ext_sel), CLK_SET_RATE_PARENT); |
| 425 | 425 | clk[IMX5_CLK_TVE_SEL] = imx_clk_mux("tve_sel", MXC_CCM_CSCMR1, 7, 1, |
| @@ -71,7 +71,7 @@ static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", }; · 70 unmodified lines | ||
| 71 | 71 | static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", }; |
| 72 | 72 | static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", }; |
| 73 | 73 | |
| 74 | −static struct clk_div_table clk_enet_ref_table[] = { | |
| 74 | +static const struct clk_div_table clk_enet_ref_table[] = { | |
| 75 | 75 | { .val = 0, .div = 20, }, |
| 76 | 76 | { .val = 1, .div = 10, }, |
| 77 | 77 | { .val = 2, .div = 5, }, |
| @@ -79,14 +79,14 @@ static struct clk_div_table clk_enet_ref_table[] = { · 1 unmodified line | ||
| 79 | 79 | { } |
| 80 | 80 | }; |
| 81 | 81 | |
| 82 | −static struct clk_div_table post_div_table[] = { | |
| 82 | +static const struct clk_div_table post_div_table[] = { | |
| 83 | 83 | { .val = 2, .div = 1, }, |
| 84 | 84 | { .val = 1, .div = 2, }, |
| 85 | 85 | { .val = 0, .div = 4, }, |
| 86 | 86 | { } |
| 87 | 87 | }; |
| 88 | 88 | |
| 89 | −static struct clk_div_table video_div_table[] = { | |
| 89 | +static const struct clk_div_table video_div_table[] = { | |
| 90 | 90 | { .val = 0, .div = 1, }, |
| 91 | 91 | { .val = 1, .div = 2, }, |
| 92 | 92 | { .val = 2, .div = 1, }, |
| @@ -105,7 +105,7 @@ static int const clks_init_on[] __initconst = { · 104 unmodified lines | ||
| 105 | 105 | IMX6SX_CLK_EPIT2, |
| 106 | 106 | }; |
| 107 | 107 | |
| 108 | −static struct clk_div_table clk_enet_ref_table[] = { | |
| 108 | +static const struct clk_div_table clk_enet_ref_table[] = { | |
| 109 | 109 | { .val = 0, .div = 20, }, |
| 110 | 110 | { .val = 1, .div = 10, }, |
| 111 | 111 | { .val = 2, .div = 5, }, |
| @@ -113,14 +113,14 @@ static struct clk_div_table clk_enet_ref_table[] = { · 1 unmodified line | ||
| 113 | 113 | { } |
| 114 | 114 | }; |
| 115 | 115 | |
| 116 | −static struct clk_div_table post_div_table[] = { | |
| 116 | +static const struct clk_div_table post_div_table[] = { | |
| 117 | 117 | { .val = 2, .div = 1, }, |
| 118 | 118 | { .val = 1, .div = 2, }, |
| 119 | 119 | { .val = 0, .div = 4, }, |
| 120 | 120 | { } |
| 121 | 121 | }; |
| 122 | 122 | |
| 123 | −static struct clk_div_table video_div_table[] = { | |
| 123 | +static const struct clk_div_table video_div_table[] = { | |
| 124 | 124 | { .val = 0, .div = 1, }, |
| 125 | 125 | { .val = 1, .div = 2, }, |
| 126 | 126 | { .val = 2, .div = 1, }, |
| @@ -78,7 +78,7 @@ static int const clks_init_on[] __initconst = { · 77 unmodified lines | ||
| 78 | 78 | IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG, |
| 79 | 79 | }; |
| 80 | 80 | |
| 81 | −static struct clk_div_table clk_enet_ref_table[] = { | |
| 81 | +static const struct clk_div_table clk_enet_ref_table[] = { | |
| 82 | 82 | { .val = 0, .div = 20, }, |
| 83 | 83 | { .val = 1, .div = 10, }, |
| 84 | 84 | { .val = 2, .div = 5, }, |
| @@ -86,14 +86,14 @@ static struct clk_div_table clk_enet_ref_table[] = { · 1 unmodified line | ||
| 86 | 86 | { } |
| 87 | 87 | }; |
| 88 | 88 | |
| 89 | −static struct clk_div_table post_div_table[] = { | |
| 89 | +static const struct clk_div_table post_div_table[] = { | |
| 90 | 90 | { .val = 2, .div = 1, }, |
| 91 | 91 | { .val = 1, .div = 2, }, |
| 92 | 92 | { .val = 0, .div = 4, }, |
| 93 | 93 | { } |
| 94 | 94 | }; |
| 95 | 95 | |
| 96 | −static struct clk_div_table video_div_table[] = { | |
| 96 | +static const struct clk_div_table video_div_table[] = { | |
| 97 | 97 | { .val = 0, .div = 1, }, |
| 98 | 98 | { .val = 1, .div = 2, }, |
| 99 | 99 | { .val = 2, .div = 1, }, |
| @@ -27,7 +27,7 @@ static u32 share_count_sai2; · 26 unmodified lines | ||
| 27 | 27 | static u32 share_count_sai3; |
| 28 | 28 | static u32 share_count_nand; |
| 29 | 29 | |
| 30 | −static struct clk_div_table test_div_table[] = { | |
| 30 | +static const struct clk_div_table test_div_table[] = { | |
| 31 | 31 | { .val = 3, .div = 1, }, |
| 32 | 32 | { .val = 2, .div = 1, }, |
| 33 | 33 | { .val = 1, .div = 2, }, |
| @@ -35,7 +35,7 @@ static struct clk_div_table test_div_table[] = { · 1 unmodified line | ||
| 35 | 35 | { } |
| 36 | 36 | }; |
| 37 | 37 | |
| 38 | −static struct clk_div_table post_div_table[] = { | |
| 38 | +static const struct clk_div_table post_div_table[] = { | |
| 39 | 39 | { .val = 3, .div = 4, }, |
| 40 | 40 | { .val = 2, .div = 1, }, |
| 41 | 41 | { .val = 1, .div = 2, }, |
| @@ -102,7 +102,7 @@ static const char *ftm_ext_sels[] = {"sirc_128k", "sxosc", "fxosc_half", "audio_ · 101 unmodified lines | ||
| 102 | 102 | static const char *ftm_fix_sels[] = { "sxosc", "ipg_bus", }; |
| 103 | 103 | |
| 104 | 104 | |
| 105 | −static struct clk_div_table pll4_audio_div_table[] = { | |
| 105 | +static const struct clk_div_table pll4_audio_div_table[] = { | |
| 106 | 106 | { .val = 0, .div = 1 }, |
| 107 | 107 | { .val = 1, .div = 2 }, |
| 108 | 108 | { .val = 2, .div = 6 }, |
| @@ -27,7 +27,6 @@ static inline struct mtk_clk_cpumux *to_mtk_clk_cpumux(struct clk_hw *_hw) · 26 unmodified lines | ||
| 27 | 27 | static u8 clk_cpumux_get_parent(struct clk_hw *hw) |
| 28 | 28 | { |
| 29 | 29 | struct mtk_clk_cpumux *mux = to_mtk_clk_cpumux(hw); |
| 30 | − int num_parents = clk_hw_get_num_parents(hw); | |
| 31 | 30 | unsigned int val; |
| 32 | 31 | |
| 33 | 32 | regmap_read(mux->regmap, mux->reg, &val); |
| @@ -35,9 +34,6 @@ static u8 clk_cpumux_get_parent(struct clk_hw *hw) · 1 unmodified line | ||
| 35 | 34 | val >>= mux->shift; |
| 36 | 35 | val &= mux->mask; |
| 37 | 36 | |
| 38 | − if (val >= num_parents) | |
| 39 | − return -EINVAL; | |
| 40 | − | |
| 41 | 37 | return val; |
| 42 | 38 | } |
| 43 | 39 | |
| @@ -98,7 +94,7 @@ int __init mtk_clk_register_cpumuxes(struct device_node *node, · 54 unmodified lines | ||
| 98 | 94 | |
| 99 | 95 | regmap = syscon_node_to_regmap(node); |
| 100 | 96 | if (IS_ERR(regmap)) { |
| 101 | − pr_err("Cannot find regmap for %s: %ld\n", node->full_name, | |
| 97 | + pr_err("Cannot find regmap for %pOF: %ld\n", node, | |
| 102 | 98 | PTR_ERR(regmap)); |
| 103 | 99 | return PTR_ERR(regmap); |
| 104 | 100 | } |
| @@ -114,7 +114,7 @@ int mtk_clk_register_gates(struct device_node *node, · 113 unmodified lines | ||
| 114 | 114 | |
| 115 | 115 | regmap = syscon_node_to_regmap(node); |
| 116 | 116 | if (IS_ERR(regmap)) { |
| 117 | − pr_err("Cannot find regmap for %s: %ld\n", node->full_name, | |
| 117 | + pr_err("Cannot find regmap for %pOF: %ld\n", node, | |
| 118 | 118 | PTR_ERR(regmap)); |
| 119 | 119 | return PTR_ERR(regmap); |
| 120 | 120 | } |
| @@ -72,7 +72,7 @@ void mtk_register_reset_controller(struct device_node *np, · 71 unmodified lines | ||
| 72 | 72 | |
| 73 | 73 | regmap = syscon_node_to_regmap(np); |
| 74 | 74 | if (IS_ERR(regmap)) { |
| 75 | − pr_err("Cannot find regmap for %s: %ld\n", np->full_name, | |
| 75 | + pr_err("Cannot find regmap for %pOF: %ld\n", np, | |
| 76 | 76 | PTR_ERR(regmap)); |
| 77 | 77 | return; |
| 78 | 78 | } |
| @@ -6,6 +6,7 @@ config COMMON_CLK_AMLOGIC · 5 unmodified lines | ||
| 6 | 6 | config COMMON_CLK_MESON8B |
| 7 | 7 | bool |
| 8 | 8 | depends on COMMON_CLK_AMLOGIC |
| 9 | + select RESET_CONTROLLER | |
| 9 | 10 | help |
| 10 | 11 | Support for the clock controller on AmLogic S802 (Meson8), |
| 11 | 12 | S805 (Meson8b) and S812 (Meson8m2) devices. Say Y if you |
| @@ -4,4 +4,4 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o |
| 6 | 6 | obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o |
| 7 | −obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o | |
| 7 | +obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-regmap.o gxbb-aoclk-32k.o | |
| @@ -0,0 +1,194 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2017 BayLibre, SAS. | |
| 3 | + * Author: Neil Armstrong <narmstrong@baylibre.com> | |
| 4 | + * | |
| 5 | + * SPDX-License-Identifier: GPL-2.0+ | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/clk-provider.h> | |
| 9 | +#include <linux/bitfield.h> | |
| 10 | +#include <linux/regmap.h> | |
| 11 | +#include "gxbb-aoclk.h" | |
| 12 | + | |
| 13 | +/* | |
| 14 | + * The AO Domain embeds a dual/divider to generate a more precise | |
| 15 | + * 32,768KHz clock for low-power suspend mode and CEC. | |
| 16 | + * ______ ______ | |
| 17 | + * | | | | | |
| 18 | + * ______ | Div1 |-| Cnt1 | ______ | |
| 19 | + * | | /|______| |______|\ | | | |
| 20 | + * Xtal-->| Gate |---| ______ ______ X-X--| Gate |--> | |
| 21 | + * |______| | \| | | |/ | |______| | |
| 22 | + * | | Div2 |-| Cnt2 | | | |
| 23 | + * | |______| |______| | | |
| 24 | + * |_______________________| | |
| 25 | + * | |
| 26 | + * The dividing can be switched to single or dual, with a counter | |
| 27 | + * for each divider to set when the switching is done. | |
| 28 | + * The entire dividing mechanism can be also bypassed. | |
| 29 | + */ | |
| 30 | + | |
| 31 | +#define CLK_CNTL0_N1_MASK GENMASK(11, 0) | |
| 32 | +#define CLK_CNTL0_N2_MASK GENMASK(23, 12) | |
| 33 | +#define CLK_CNTL0_DUALDIV_EN BIT(28) | |
| 34 | +#define CLK_CNTL0_OUT_GATE_EN BIT(30) | |
| 35 | +#define CLK_CNTL0_IN_GATE_EN BIT(31) | |
| 36 | + | |
| 37 | +#define CLK_CNTL1_M1_MASK GENMASK(11, 0) | |
| 38 | +#define CLK_CNTL1_M2_MASK GENMASK(23, 12) | |
| 39 | +#define CLK_CNTL1_BYPASS_EN BIT(24) | |
| 40 | +#define CLK_CNTL1_SELECT_OSC BIT(27) | |
| 41 | + | |
| 42 | +#define PWR_CNTL_ALT_32K_SEL GENMASK(13, 10) | |
| 43 | + | |
| 44 | +struct cec_32k_freq_table { | |
| 45 | + unsigned long parent_rate; | |
| 46 | + unsigned long target_rate; | |
| 47 | + bool dualdiv; | |
| 48 | + unsigned int n1; | |
| 49 | + unsigned int n2; | |
| 50 | + unsigned int m1; | |
| 51 | + unsigned int m2; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +static const struct cec_32k_freq_table aoclk_cec_32k_table[] = { | |
| 55 | + [0] = { | |
| 56 | + .parent_rate = 24000000, | |
| 57 | + .target_rate = 32768, | |
| 58 | + .dualdiv = true, | |
| 59 | + .n1 = 733, | |
| 60 | + .n2 = 732, | |
| 61 | + .m1 = 8, | |
| 62 | + .m2 = 11, | |
| 63 | + }, | |
| 64 | +}; | |
| 65 | + | |
| 66 | +/* | |
| 67 | + * If CLK_CNTL0_DUALDIV_EN == 0 | |
| 68 | + * - will use N1 divider only | |
| 69 | + * If CLK_CNTL0_DUALDIV_EN == 1 | |
| 70 | + * - hold M1 cycles of N1 divider then changes to N2 | |
| 71 | + * - hold M2 cycles of N2 divider then changes to N1 | |
| 72 | + * Then we can get more accurate division. | |
| 73 | + */ | |
| 74 | +static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw, | |
| 75 | + unsigned long parent_rate) | |
| 76 | +{ | |
| 77 | + struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); | |
| 78 | + unsigned long n1; | |
| 79 | + u32 reg0, reg1; | |
| 80 | + | |
| 81 | + regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, ®0); | |
| 82 | + regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, ®1); | |
| 83 | + | |
| 84 | + if (reg1 & CLK_CNTL1_BYPASS_EN) | |
| 85 | + return parent_rate; | |
| 86 | + | |
| 87 | + if (reg0 & CLK_CNTL0_DUALDIV_EN) { | |
| 88 | + unsigned long n2, m1, m2, f1, f2, p1, p2; | |
| 89 | + | |
| 90 | + n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; | |
| 91 | + n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1; | |
| 92 | + | |
| 93 | + m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1; | |
| 94 | + m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1; | |
| 95 | + | |
| 96 | + f1 = DIV_ROUND_CLOSEST(parent_rate, n1); | |
| 97 | + f2 = DIV_ROUND_CLOSEST(parent_rate, n2); | |
| 98 | + | |
| 99 | + p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2)); | |
| 100 | + p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2)); | |
| 101 | + | |
| 102 | + return DIV_ROUND_UP(100000000, p1 + p2); | |
| 103 | + } | |
| 104 | + | |
| 105 | + n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1; | |
| 106 | + | |
| 107 | + return DIV_ROUND_CLOSEST(parent_rate, n1); | |
| 108 | +} | |
| 109 | + | |
| 110 | +static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate, | |
| 111 | + unsigned long prate) | |
| 112 | +{ | |
| 113 | + int i; | |
| 114 | + | |
| 115 | + for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i) | |
| 116 | + if (aoclk_cec_32k_table[i].parent_rate == prate && | |
| 117 | + aoclk_cec_32k_table[i].target_rate == rate) | |
| 118 | + return &aoclk_cec_32k_table[i]; | |
| 119 | + | |
| 120 | + return NULL; | |
| 121 | +} | |
| 122 | + | |
| 123 | +static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate, | |
| 124 | + unsigned long *prate) | |
| 125 | +{ | |
| 126 | + const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, | |
| 127 | + *prate); | |
| 128 | + | |
| 129 | + /* If invalid return first one */ | |
| 130 | + if (!freq) | |
| 131 | + return aoclk_cec_32k_table[0].target_rate; | |
| 132 | + | |
| 133 | + return freq->target_rate; | |
| 134 | +} | |
| 135 | + | |
| 136 | +/* | |
| 137 | + * From the Amlogic init procedure, the IN and OUT gates needs to be handled | |
| 138 | + * in the init procedure to avoid any glitches. | |
| 139 | + */ | |
| 140 | + | |
| 141 | +static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate, | |
| 142 | + unsigned long parent_rate) | |
| 143 | +{ | |
| 144 | + const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate, | |
| 145 | + parent_rate); | |
| 146 | + struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw); | |
| 147 | + u32 reg = 0; | |
| 148 | + | |
| 149 | + if (!freq) | |
| 150 | + return -EINVAL; | |
| 151 | + | |
| 152 | + /* Disable clock */ | |
| 153 | + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | |
| 154 | + CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN, 0); | |
| 155 | + | |
| 156 | + reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1); | |
| 157 | + if (freq->dualdiv) | |
| 158 | + reg |= CLK_CNTL0_DUALDIV_EN | | |
| 159 | + FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1); | |
| 160 | + | |
| 161 | + regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, reg); | |
| 162 | + | |
| 163 | + reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1); | |
| 164 | + if (freq->dualdiv) | |
| 165 | + reg |= FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1); | |
| 166 | + | |
| 167 | + regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, reg); | |
| 168 | + | |
| 169 | + /* Enable clock */ | |
| 170 | + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | |
| 171 | + CLK_CNTL0_IN_GATE_EN, CLK_CNTL0_IN_GATE_EN); | |
| 172 | + | |
| 173 | + udelay(200); | |
| 174 | + | |
| 175 | + regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, | |
| 176 | + CLK_CNTL0_OUT_GATE_EN, CLK_CNTL0_OUT_GATE_EN); | |
| 177 | + | |
| 178 | + regmap_update_bits(cec_32k->regmap, AO_CRT_CLK_CNTL1, | |
| 179 | + CLK_CNTL1_SELECT_OSC, CLK_CNTL1_SELECT_OSC); | |
| 180 | + | |
| 181 | + /* Select 32k from XTAL */ | |
| 182 | + regmap_update_bits(cec_32k->regmap, | |
| 183 | + AO_RTI_PWR_CNTL_REG0, | |
| 184 | + PWR_CNTL_ALT_32K_SEL, | |
| 185 | + FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4)); | |
| 186 | + | |
| 187 | + return 0; | |
| 188 | +} | |
| 189 | + | |
| 190 | +const struct clk_ops meson_aoclk_cec_32k_ops = { | |
| 191 | + .recalc_rate = aoclk_cec_32k_recalc_rate, | |
| 192 | + .round_rate = aoclk_cec_32k_round_rate, | |
| 193 | + .set_rate = aoclk_cec_32k_set_rate, | |
| 194 | +}; | |
| @@ -0,0 +1,46 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2017 BayLibre, SAS. | |
| 3 | + * Author: Neil Armstrong <narmstrong@baylibre.com> | |
| 4 | + * | |
| 5 | + * SPDX-License-Identifier: GPL-2.0+ | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#include <linux/clk-provider.h> | |
| 9 | +#include <linux/bitfield.h> | |
| 10 | +#include <linux/regmap.h> | |
| 11 | +#include "gxbb-aoclk.h" | |
| 12 | + | |
| 13 | +static int aoclk_gate_regmap_enable(struct clk_hw *hw) | |
| 14 | +{ | |
| 15 | + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | |
| 16 | + | |
| 17 | + return regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, | |
| 18 | + BIT(gate->bit_idx), BIT(gate->bit_idx)); | |
| 19 | +} | |
| 20 | + | |
| 21 | +static void aoclk_gate_regmap_disable(struct clk_hw *hw) | |
| 22 | +{ | |
| 23 | + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | |
| 24 | + | |
| 25 | + regmap_update_bits(gate->regmap, AO_RTI_GEN_CNTL_REG0, | |
| 26 | + BIT(gate->bit_idx), 0); | |
| 27 | +} | |
| 28 | + | |
| 29 | +static int aoclk_gate_regmap_is_enabled(struct clk_hw *hw) | |
| 30 | +{ | |
| 31 | + struct aoclk_gate_regmap *gate = to_aoclk_gate_regmap(hw); | |
| 32 | + unsigned int val; | |
| 33 | + int ret; | |
| 34 | + | |
| 35 | + ret = regmap_read(gate->regmap, AO_RTI_GEN_CNTL_REG0, &val); | |
| 36 | + if (ret) | |
| 37 | + return ret; | |
| 38 | + | |
| 39 | + return (val & BIT(gate->bit_idx)) != 0; | |
| 40 | +} | |
| 41 | + | |
| 42 | +const struct clk_ops meson_aoclk_gate_regmap_ops = { | |
| 43 | + .enable = aoclk_gate_regmap_enable, | |
| 44 | + .disable = aoclk_gate_regmap_disable, | |
| 45 | + .is_enabled = aoclk_gate_regmap_is_enabled, | |
| 46 | +}; | |
| @@ -56,16 +56,20 @@ · 55 unmodified lines | ||
| 56 | 56 | #include <linux/of_address.h> |
| 57 | 57 | #include <linux/platform_device.h> |
| 58 | 58 | #include <linux/reset-controller.h> |
| 59 | +#include <linux/mfd/syscon.h> | |
| 60 | +#include <linux/regmap.h> | |
| 59 | 61 | #include <linux/init.h> |
| 62 | +#include <linux/delay.h> | |
| 60 | 63 | #include <dt-bindings/clock/gxbb-aoclkc.h> |
| 61 | 64 | #include <dt-bindings/reset/gxbb-aoclkc.h> |
| 65 | +#include "gxbb-aoclk.h" | |
| 62 | 66 | |
| 63 | 67 | static DEFINE_SPINLOCK(gxbb_aoclk_lock); |
| 64 | 68 | |
| 65 | 69 | struct gxbb_aoclk_reset_controller { |
| 66 | 70 | struct reset_controller_dev reset; |
| 67 | 71 | unsigned int *data; |
| 68 | − void __iomem *base; | |
| 72 | + struct regmap *regmap; | |
| 69 | 73 | }; |
| 70 | 74 | |
| 71 | 75 | static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, |
| @@ -74,9 +78,8 @@ static int gxbb_aoclk_do_reset(struct reset_controller_dev *rcdev, · 2 unmodified lines | ||
| 74 | 78 | struct gxbb_aoclk_reset_controller *reset = |
| 75 | 79 | container_of(rcdev, struct gxbb_aoclk_reset_controller, reset); |
| 76 | 80 | |
| 77 | − writel(BIT(reset->data[id]), reset->base); | |
| 78 | − | |
| 79 | − return 0; | |
| 81 | + return regmap_write(reset->regmap, AO_RTI_GEN_CNTL_REG0, | |
| 82 | + BIT(reset->data[id])); | |
| 80 | 83 | } |
| 81 | 84 | |
| 82 | 85 | static const struct reset_control_ops gxbb_aoclk_reset_ops = { |
| @@ -84,13 +87,12 @@ static const struct reset_control_ops gxbb_aoclk_reset_ops = { · 1 unmodified line | ||
| 84 | 87 | }; |
| 85 | 88 | |
| 86 | 89 | #define GXBB_AO_GATE(_name, _bit) \ |
| 87 | −static struct clk_gate _name##_ao = { \ | |
| 88 | − .reg = (void __iomem *)0, \ | |
| 90 | +static struct aoclk_gate_regmap _name##_ao = { \ | |
| 89 | 91 | .bit_idx = (_bit), \ |
| 90 | 92 | .lock = &gxbb_aoclk_lock, \ |
| 91 | 93 | .hw.init = &(struct clk_init_data) { \ |
| 92 | 94 | .name = #_name "_ao", \ |
| 93 | − .ops = &clk_gate_ops, \ | |
| 95 | + .ops = &meson_aoclk_gate_regmap_ops, \ | |
| 94 | 96 | .parent_names = (const char *[]){ "clk81" }, \ |
| 95 | 97 | .num_parents = 1, \ |
| 96 | 98 | .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \ |
| @@ -104,6 +106,17 @@ GXBB_AO_GATE(uart1, 3); · 7 unmodified lines | ||
| 104 | 106 | GXBB_AO_GATE(uart2, 5); |
| 105 | 107 | GXBB_AO_GATE(ir_blaster, 6); |
| 106 | 108 | |
| 109 | +static struct aoclk_cec_32k cec_32k_ao = { | |
| 110 | + .lock = &gxbb_aoclk_lock, | |
| 111 | + .hw.init = &(struct clk_init_data) { | |
| 112 | + .name = "cec_32k_ao", | |
| 113 | + .ops = &meson_aoclk_cec_32k_ops, | |
| 114 | + .parent_names = (const char *[]){ "xtal" }, | |
| 115 | + .num_parents = 1, | |
| 116 | + .flags = CLK_IGNORE_UNUSED, | |
| 117 | + }, | |
| 118 | +}; | |
| 119 | + | |
| 107 | 120 | static unsigned int gxbb_aoclk_reset[] = { |
| 108 | 121 | [RESET_AO_REMOTE] = 16, |
| 109 | 122 | [RESET_AO_I2C_MASTER] = 18, |
| @@ -113,7 +126,7 @@ static unsigned int gxbb_aoclk_reset[] = { · 3 unmodified lines | ||
| 113 | 126 | [RESET_AO_IR_BLASTER] = 23, |
| 114 | 127 | }; |
| 115 | 128 | |
| 116 | −static struct clk_gate *gxbb_aoclk_gate[] = { | |
| 129 | +static struct aoclk_gate_regmap *gxbb_aoclk_gate[] = { | |
| 117 | 130 | [CLKID_AO_REMOTE] = &remote_ao, |
| 118 | 131 | [CLKID_AO_I2C_MASTER] = &i2c_master_ao, |
| 119 | 132 | [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, |
| @@ -130,30 +143,30 @@ static struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { · 10 unmodified lines | ||
| 130 | 143 | [CLKID_AO_UART1] = &uart1_ao.hw, |
| 131 | 144 | [CLKID_AO_UART2] = &uart2_ao.hw, |
| 132 | 145 | [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, |
| 146 | + [CLKID_AO_CEC_32K] = &cec_32k_ao.hw, | |
| 133 | 147 | }, |
| 134 | − .num = ARRAY_SIZE(gxbb_aoclk_gate), | |
| 148 | + .num = 7, | |
| 135 | 149 | }; |
| 136 | 150 | |
| 137 | 151 | static int gxbb_aoclkc_probe(struct platform_device *pdev) |
| 138 | 152 | { |
| 139 | − struct resource *res; | |
| 140 | − void __iomem *base; | |
| 141 | − int ret, clkid; | |
| 142 | − struct device *dev = &pdev->dev; | |
| 143 | 153 | struct gxbb_aoclk_reset_controller *rstc; |
| 154 | + struct device *dev = &pdev->dev; | |
| 155 | + struct regmap *regmap; | |
| 156 | + int ret, clkid; | |
| 144 | 157 | |
| 145 | 158 | rstc = devm_kzalloc(dev, sizeof(*rstc), GFP_KERNEL); |
| 146 | 159 | if (!rstc) |
| 147 | 160 | return -ENOMEM; |
| 148 | 161 | |
| 149 | − /* Generic clocks */ | |
| 150 | − res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 151 | − base = devm_ioremap_resource(dev, res); | |
| 152 | − if (IS_ERR(base)) | |
| 153 | − return PTR_ERR(base); | |
| 162 | + regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); | |
| 163 | + if (IS_ERR(regmap)) { | |
| 164 | + dev_err(dev, "failed to get regmap\n"); | |
| 165 | + return -ENODEV; | |
| 166 | + } | |
| 154 | 167 | |
| 155 | 168 | /* Reset Controller */ |
| 156 | − rstc->base = base; | |
| 169 | + rstc->regmap = regmap; | |
| 157 | 170 | rstc->data = gxbb_aoclk_reset; |
| 158 | 171 | rstc->reset.ops = &gxbb_aoclk_reset_ops; |
| 159 | 172 | rstc->reset.nr_resets = ARRAY_SIZE(gxbb_aoclk_reset); |
| @@ -161,10 +174,10 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 161 | 174 | ret = devm_reset_controller_register(dev, &rstc->reset); |
| 162 | 175 | |
| 163 | 176 | /* |
| 164 | − * Populate base address and register all clks | |
| 177 | + * Populate regmap and register all clks | |
| 165 | 178 | */ |
| 166 | − for (clkid = 0; clkid < gxbb_aoclk_onecell_data.num; clkid++) { | |
| 167 | − gxbb_aoclk_gate[clkid]->reg = base; | |
| 179 | + for (clkid = 0; clkid < ARRAY_SIZE(gxbb_aoclk_gate); clkid++) { | |
| 180 | + gxbb_aoclk_gate[clkid]->regmap = regmap; | |
| 168 | 181 | |
| 169 | 182 | ret = devm_clk_hw_register(dev, |
| 170 | 183 | gxbb_aoclk_onecell_data.hws[clkid]); |
| @@ -172,12 +185,18 @@ static int gxbb_aoclkc_probe(struct platform_device *pdev) · 1 unmodified line | ||
| 172 | 185 | return ret; |
| 173 | 186 | } |
| 174 | 187 | |
| 188 | + /* Specific clocks */ | |
| 189 | + cec_32k_ao.regmap = regmap; | |
| 190 | + ret = devm_clk_hw_register(dev, &cec_32k_ao.hw); | |
| 191 | + if (ret) | |
| 192 | + return ret; | |
| 193 | + | |
| 175 | 194 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, |
| 176 | 195 | &gxbb_aoclk_onecell_data); |
| 177 | 196 | } |
| 178 | 197 | |
| 179 | 198 | static const struct of_device_id gxbb_aoclkc_match_table[] = { |
| 180 | − { .compatible = "amlogic,gxbb-aoclkc" }, | |
| 199 | + { .compatible = "amlogic,meson-gx-aoclkc" }, | |
| 181 | 200 | { } |
| 182 | 201 | }; |
| 183 | 202 | |
| @@ -0,0 +1,42 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2017 BayLibre, SAS | |
| 3 | + * Author: Neil Armstrong <narmstrong@baylibre.com> | |
| 4 | + * | |
| 5 | + * SPDX-License-Identifier: GPL-2.0+ | |
| 6 | + */ | |
| 7 | + | |
| 8 | +#ifndef __GXBB_AOCLKC_H | |
| 9 | +#define __GXBB_AOCLKC_H | |
| 10 | + | |
| 11 | +/* AO Configuration Clock registers offsets */ | |
| 12 | +#define AO_RTI_PWR_CNTL_REG1 0x0c | |
| 13 | +#define AO_RTI_PWR_CNTL_REG0 0x10 | |
| 14 | +#define AO_RTI_GEN_CNTL_REG0 0x40 | |
| 15 | +#define AO_OSCIN_CNTL 0x58 | |
| 16 | +#define AO_CRT_CLK_CNTL1 0x68 | |
| 17 | +#define AO_RTC_ALT_CLK_CNTL0 0x94 | |
| 18 | +#define AO_RTC_ALT_CLK_CNTL1 0x98 | |
| 19 | + | |
| 20 | +struct aoclk_gate_regmap { | |
| 21 | + struct clk_hw hw; | |
| 22 | + unsigned bit_idx; | |
| 23 | + struct regmap *regmap; | |
| 24 | + spinlock_t *lock; | |
| 25 | +}; | |
| 26 | + | |
| 27 | +#define to_aoclk_gate_regmap(_hw) \ | |
| 28 | + container_of(_hw, struct aoclk_gate_regmap, hw) | |
| 29 | + | |
| 30 | +extern const struct clk_ops meson_aoclk_gate_regmap_ops; | |
| 31 | + | |
| 32 | +struct aoclk_cec_32k { | |
| 33 | + struct clk_hw hw; | |
| 34 | + struct regmap *regmap; | |
| 35 | + spinlock_t *lock; | |
| 36 | +}; | |
| 37 | + | |
| 38 | +#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw) | |
| 39 | + | |
| 40 | +extern const struct clk_ops meson_aoclk_cec_32k_ops; | |
| 41 | + | |
| 42 | +#endif /* __GXBB_AOCLKC_H */ | |
| @@ -850,13 +850,14 @@ static struct meson_clk_audio_divider gxbb_cts_amclk_div = { · 849 unmodified lines | ||
| 850 | 850 | .shift = 0, |
| 851 | 851 | .width = 8, |
| 852 | 852 | }, |
| 853 | + .flags = CLK_DIVIDER_ROUND_CLOSEST, | |
| 853 | 854 | .lock = &clk_lock, |
| 854 | 855 | .hw.init = &(struct clk_init_data){ |
| 855 | 856 | .name = "cts_amclk_div", |
| 856 | 857 | .ops = &meson_clk_audio_divider_ops, |
| 857 | 858 | .parent_names = (const char *[]){ "cts_amclk_sel" }, |
| 858 | 859 | .num_parents = 1, |
| 859 | − .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, | |
| 860 | + .flags = CLK_SET_RATE_PARENT, | |
| 860 | 861 | }, |
| 861 | 862 | }; |
| 862 | 863 | |
| @@ -880,7 +881,7 @@ static struct clk_mux gxbb_cts_mclk_i958_sel = { · 17 unmodified lines | ||
| 880 | 881 | /* Default parent unknown (register reset value: 0) */ |
| 881 | 882 | .table = (u32[]){ 1, 2, 3 }, |
| 882 | 883 | .lock = &clk_lock, |
| 883 | − .hw.init = &(struct clk_init_data){ | |
| 884 | + .hw.init = &(struct clk_init_data) { | |
| 884 | 885 | .name = "cts_mclk_i958_sel", |
| 885 | 886 | .ops = &clk_mux_ops, |
| 886 | 887 | .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" }, |
| @@ -894,12 +895,13 @@ static struct clk_divider gxbb_cts_mclk_i958_div = { · 7 unmodified lines | ||
| 894 | 895 | .shift = 16, |
| 895 | 896 | .width = 8, |
| 896 | 897 | .lock = &clk_lock, |
| 897 | − .hw.init = &(struct clk_init_data){ | |
| 898 | + .flags = CLK_DIVIDER_ROUND_CLOSEST, | |
| 899 | + .hw.init = &(struct clk_init_data) { | |
| 898 | 900 | .name = "cts_mclk_i958_div", |
| 899 | 901 | .ops = &clk_divider_ops, |
| 900 | 902 | .parent_names = (const char *[]){ "cts_mclk_i958_sel" }, |
| 901 | 903 | .num_parents = 1, |
| 902 | − .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST, | |
| 904 | + .flags = CLK_SET_RATE_PARENT, | |
| 903 | 905 | }, |
| 904 | 906 | }; |
| 905 | 907 | |
| @@ -979,6 +981,156 @@ static struct clk_mux gxbb_32k_clk_sel = { · 73 unmodified lines | ||
| 979 | 981 | }, |
| 980 | 982 | }; |
| 981 | 983 | |
| 984 | +static const char * const gxbb_sd_emmc_clk0_parent_names[] = { | |
| 985 | + "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", | |
| 986 | + | |
| 987 | + /* | |
| 988 | + * Following these parent clocks, we should also have had mpll2, mpll3 | |
| 989 | + * and gp0_pll but these clocks are too precious to be used here. All | |
| 990 | + * the necessary rates for MMC and NAND operation can be acheived using | |
| 991 | + * xtal or fclk_div clocks | |
| 992 | + */ | |
| 993 | +}; | |
| 994 | + | |
| 995 | +/* SDIO clock */ | |
| 996 | +static struct clk_mux gxbb_sd_emmc_a_clk0_sel = { | |
| 997 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 998 | + .mask = 0x7, | |
| 999 | + .shift = 9, | |
| 1000 | + .lock = &clk_lock, | |
| 1001 | + .hw.init = &(struct clk_init_data) { | |
| 1002 | + .name = "sd_emmc_a_clk0_sel", | |
| 1003 | + .ops = &clk_mux_ops, | |
| 1004 | + .parent_names = gxbb_sd_emmc_clk0_parent_names, | |
| 1005 | + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | |
| 1006 | + .flags = CLK_SET_RATE_PARENT, | |
| 1007 | + }, | |
| 1008 | +}; | |
| 1009 | + | |
| 1010 | +static struct clk_divider gxbb_sd_emmc_a_clk0_div = { | |
| 1011 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 1012 | + .shift = 0, | |
| 1013 | + .width = 7, | |
| 1014 | + .lock = &clk_lock, | |
| 1015 | + .flags = CLK_DIVIDER_ROUND_CLOSEST, | |
| 1016 | + .hw.init = &(struct clk_init_data) { | |
| 1017 | + .name = "sd_emmc_a_clk0_div", | |
| 1018 | + .ops = &clk_divider_ops, | |
| 1019 | + .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" }, | |
| 1020 | + .num_parents = 1, | |
| 1021 | + .flags = CLK_SET_RATE_PARENT, | |
| 1022 | + }, | |
| 1023 | +}; | |
| 1024 | + | |
| 1025 | +static struct clk_gate gxbb_sd_emmc_a_clk0 = { | |
| 1026 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 1027 | + .bit_idx = 7, | |
| 1028 | + .lock = &clk_lock, | |
| 1029 | + .hw.init = &(struct clk_init_data){ | |
| 1030 | + .name = "sd_emmc_a_clk0", | |
| 1031 | + .ops = &clk_gate_ops, | |
| 1032 | + .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" }, | |
| 1033 | + .num_parents = 1, | |
| 1034 | + | |
| 1035 | + /* | |
| 1036 | + * FIXME: | |
| 1037 | + * We need CLK_IGNORE_UNUSED because mmc DT node point to xtal | |
| 1038 | + * instead of this clock. CCF would gate this on boot, killing | |
| 1039 | + * the mmc controller. Please remove this flag once DT properly | |
| 1040 | + * point to this clock instead of xtal | |
| 1041 | + * | |
| 1042 | + * Same goes for emmc B and C clocks | |
| 1043 | + */ | |
| 1044 | + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | |
| 1045 | + }, | |
| 1046 | +}; | |
| 1047 | + | |
| 1048 | +/* SDcard clock */ | |
| 1049 | +static struct clk_mux gxbb_sd_emmc_b_clk0_sel = { | |
| 1050 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 1051 | + .mask = 0x7, | |
| 1052 | + .shift = 25, | |
| 1053 | + .lock = &clk_lock, | |
| 1054 | + .hw.init = &(struct clk_init_data) { | |
| 1055 | + .name = "sd_emmc_b_clk0_sel", | |
| 1056 | + .ops = &clk_mux_ops, | |
| 1057 | + .parent_names = gxbb_sd_emmc_clk0_parent_names, | |
| 1058 | + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | |
| 1059 | + .flags = CLK_SET_RATE_PARENT, | |
| 1060 | + }, | |
| 1061 | +}; | |
| 1062 | + | |
| 1063 | +static struct clk_divider gxbb_sd_emmc_b_clk0_div = { | |
| 1064 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 1065 | + .shift = 16, | |
| 1066 | + .width = 7, | |
| 1067 | + .lock = &clk_lock, | |
| 1068 | + .flags = CLK_DIVIDER_ROUND_CLOSEST, | |
| 1069 | + .hw.init = &(struct clk_init_data) { | |
| 1070 | + .name = "sd_emmc_b_clk0_div", | |
| 1071 | + .ops = &clk_divider_ops, | |
| 1072 | + .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, | |
| 1073 | + .num_parents = 1, | |
| 1074 | + .flags = CLK_SET_RATE_PARENT, | |
| 1075 | + }, | |
| 1076 | +}; | |
| 1077 | + | |
| 1078 | +static struct clk_gate gxbb_sd_emmc_b_clk0 = { | |
| 1079 | + .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | |
| 1080 | + .bit_idx = 23, | |
| 1081 | + .lock = &clk_lock, | |
| 1082 | + .hw.init = &(struct clk_init_data){ | |
| 1083 | + .name = "sd_emmc_b_clk0", | |
| 1084 | + .ops = &clk_gate_ops, | |
| 1085 | + .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, | |
| 1086 | + .num_parents = 1, | |
| 1087 | + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | |
| 1088 | + }, | |
| 1089 | +}; | |
| 1090 | + | |
| 1091 | +/* EMMC/NAND clock */ | |
| 1092 | +static struct clk_mux gxbb_sd_emmc_c_clk0_sel = { | |
| 1093 | + .reg = (void *)HHI_NAND_CLK_CNTL, | |
| 1094 | + .mask = 0x7, | |
| 1095 | + .shift = 9, | |
| 1096 | + .lock = &clk_lock, | |
| 1097 | + .hw.init = &(struct clk_init_data) { | |
| 1098 | + .name = "sd_emmc_c_clk0_sel", | |
| 1099 | + .ops = &clk_mux_ops, | |
| 1100 | + .parent_names = gxbb_sd_emmc_clk0_parent_names, | |
| 1101 | + .num_parents = ARRAY_SIZE(gxbb_sd_emmc_clk0_parent_names), | |
| 1102 | + .flags = CLK_SET_RATE_PARENT, | |
| 1103 | + }, | |
| 1104 | +}; | |
| 1105 | + | |
| 1106 | +static struct clk_divider gxbb_sd_emmc_c_clk0_div = { | |
| 1107 | + .reg = (void *)HHI_NAND_CLK_CNTL, | |
| 1108 | + .shift = 0, | |
| 1109 | + .width = 7, | |
| 1110 | + .lock = &clk_lock, | |
| 1111 | + .flags = CLK_DIVIDER_ROUND_CLOSEST, | |
| 1112 | + .hw.init = &(struct clk_init_data) { | |
| 1113 | + .name = "sd_emmc_c_clk0_div", | |
| 1114 | + .ops = &clk_divider_ops, | |
| 1115 | + .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, | |
| 1116 | + .num_parents = 1, | |
| 1117 | + .flags = CLK_SET_RATE_PARENT, | |
| 1118 | + }, | |
| 1119 | +}; | |
| 1120 | + | |
| 1121 | +static struct clk_gate gxbb_sd_emmc_c_clk0 = { | |
| 1122 | + .reg = (void *)HHI_NAND_CLK_CNTL, | |
| 1123 | + .bit_idx = 7, | |
| 1124 | + .lock = &clk_lock, | |
| 1125 | + .hw.init = &(struct clk_init_data){ | |
| 1126 | + .name = "sd_emmc_c_clk0", | |
| 1127 | + .ops = &clk_gate_ops, | |
| 1128 | + .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, | |
| 1129 | + .num_parents = 1, | |
| 1130 | + .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, | |
| 1131 | + }, | |
| 1132 | +}; | |
| 1133 | + | |
| 982 | 1134 | /* Everything Else (EE) domain gates */ |
| 983 | 1135 | static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0); |
| 984 | 1136 | static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1); |
| @@ -1188,6 +1340,15 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = { · 203 unmodified lines | ||
| 1188 | 1340 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, |
| 1189 | 1341 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, |
| 1190 | 1342 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, |
| 1343 | + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, | |
| 1344 | + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, | |
| 1345 | + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, | |
| 1346 | + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, | |
| 1347 | + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, | |
| 1348 | + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, | |
| 1349 | + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, | |
| 1350 | + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, | |
| 1351 | + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, | |
| 1191 | 1352 | [NR_CLKS] = NULL, |
| 1192 | 1353 | }, |
| 1193 | 1354 | .num = NR_CLKS, |
| @@ -1311,6 +1472,15 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = { · 117 unmodified lines | ||
| 1311 | 1472 | [CLKID_32K_CLK] = &gxbb_32k_clk.hw, |
| 1312 | 1473 | [CLKID_32K_CLK_SEL] = &gxbb_32k_clk_sel.hw, |
| 1313 | 1474 | [CLKID_32K_CLK_DIV] = &gxbb_32k_clk_div.hw, |
| 1475 | + [CLKID_SD_EMMC_A_CLK0_SEL] = &gxbb_sd_emmc_a_clk0_sel.hw, | |
| 1476 | + [CLKID_SD_EMMC_A_CLK0_DIV] = &gxbb_sd_emmc_a_clk0_div.hw, | |
| 1477 | + [CLKID_SD_EMMC_A_CLK0] = &gxbb_sd_emmc_a_clk0.hw, | |
| 1478 | + [CLKID_SD_EMMC_B_CLK0_SEL] = &gxbb_sd_emmc_b_clk0_sel.hw, | |
| 1479 | + [CLKID_SD_EMMC_B_CLK0_DIV] = &gxbb_sd_emmc_b_clk0_div.hw, | |
| 1480 | + [CLKID_SD_EMMC_B_CLK0] = &gxbb_sd_emmc_b_clk0.hw, | |
| 1481 | + [CLKID_SD_EMMC_C_CLK0_SEL] = &gxbb_sd_emmc_c_clk0_sel.hw, | |
| 1482 | + [CLKID_SD_EMMC_C_CLK0_DIV] = &gxbb_sd_emmc_c_clk0_div.hw, | |
| 1483 | + [CLKID_SD_EMMC_C_CLK0] = &gxbb_sd_emmc_c_clk0.hw, | |
| 1314 | 1484 | [NR_CLKS] = NULL, |
| 1315 | 1485 | }, |
| 1316 | 1486 | .num = NR_CLKS, |
| @@ -1427,6 +1597,9 @@ static struct clk_gate *const gxbb_clk_gates[] = { · 110 unmodified lines | ||
| 1427 | 1597 | &gxbb_cts_amclk, |
| 1428 | 1598 | &gxbb_cts_mclk_i958, |
| 1429 | 1599 | &gxbb_32k_clk, |
| 1600 | + &gxbb_sd_emmc_a_clk0, | |
| 1601 | + &gxbb_sd_emmc_b_clk0, | |
| 1602 | + &gxbb_sd_emmc_c_clk0, | |
| 1430 | 1603 | }; |
| 1431 | 1604 | |
| 1432 | 1605 | static struct clk_mux *const gxbb_clk_muxes[] = { |
| @@ -1439,6 +1612,9 @@ static struct clk_mux *const gxbb_clk_muxes[] = { · 6 unmodified lines | ||
| 1439 | 1612 | &gxbb_cts_mclk_i958_sel, |
| 1440 | 1613 | &gxbb_cts_i958, |
| 1441 | 1614 | &gxbb_32k_clk_sel, |
| 1615 | + &gxbb_sd_emmc_a_clk0_sel, | |
| 1616 | + &gxbb_sd_emmc_b_clk0_sel, | |
| 1617 | + &gxbb_sd_emmc_c_clk0_sel, | |
| 1442 | 1618 | }; |
| 1443 | 1619 | |
| 1444 | 1620 | static struct clk_divider *const gxbb_clk_dividers[] = { |
| @@ -1448,6 +1624,9 @@ static struct clk_divider *const gxbb_clk_dividers[] = { · 3 unmodified lines | ||
| 1448 | 1624 | &gxbb_mali_1_div, |
| 1449 | 1625 | &gxbb_cts_mclk_i958_div, |
| 1450 | 1626 | &gxbb_32k_clk_div, |
| 1627 | + &gxbb_sd_emmc_a_clk0_div, | |
| 1628 | + &gxbb_sd_emmc_b_clk0_div, | |
| 1629 | + &gxbb_sd_emmc_c_clk0_div, | |
| 1451 | 1630 | }; |
| 1452 | 1631 | |
| 1453 | 1632 | static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = { |
| @@ -25,6 +25,8 @@ · 24 unmodified lines | ||
| 25 | 25 | #include <linux/clk-provider.h> |
| 26 | 26 | #include <linux/of_address.h> |
| 27 | 27 | #include <linux/platform_device.h> |
| 28 | +#include <linux/reset-controller.h> | |
| 29 | +#include <linux/slab.h> | |
| 28 | 30 | #include <linux/init.h> |
| 29 | 31 | |
| 30 | 32 | #include "clkc.h" |
| @@ -32,6 +34,13 @@ · 1 unmodified line | ||
| 32 | 34 | |
| 33 | 35 | static DEFINE_SPINLOCK(clk_lock); |
| 34 | 36 | |
| 37 | +static void __iomem *clk_base; | |
| 38 | + | |
| 39 | +struct meson8b_clk_reset { | |
| 40 | + struct reset_controller_dev reset; | |
| 41 | + void __iomem *base; | |
| 42 | +}; | |
| 43 | + | |
| 35 | 44 | static const struct pll_rate_table sys_pll_rate_table[] = { |
| 36 | 45 | PLL_RATE(312000000, 52, 1, 2), |
| 37 | 46 | PLL_RATE(336000000, 56, 1, 2), |
| @@ -696,20 +705,114 @@ static struct clk_divider *const meson8b_clk_dividers[] = { · 658 unmodified lines | ||
| 696 | 705 | &meson8b_mpeg_clk_div, |
| 697 | 706 | }; |
| 698 | 707 | |
| 708 | +static const struct meson8b_clk_reset_line { | |
| 709 | + u32 reg; | |
| 710 | + u8 bit_idx; | |
| 711 | +} meson8b_clk_reset_bits[] = { | |
| 712 | + [CLKC_RESET_L2_CACHE_SOFT_RESET] = { | |
| 713 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 30 | |
| 714 | + }, | |
| 715 | + [CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET] = { | |
| 716 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 29 | |
| 717 | + }, | |
| 718 | + [CLKC_RESET_SCU_SOFT_RESET] = { | |
| 719 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 28 | |
| 720 | + }, | |
| 721 | + [CLKC_RESET_CPU3_SOFT_RESET] = { | |
| 722 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 27 | |
| 723 | + }, | |
| 724 | + [CLKC_RESET_CPU2_SOFT_RESET] = { | |
| 725 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 26 | |
| 726 | + }, | |
| 727 | + [CLKC_RESET_CPU1_SOFT_RESET] = { | |
| 728 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 25 | |
| 729 | + }, | |
| 730 | + [CLKC_RESET_CPU0_SOFT_RESET] = { | |
| 731 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 24 | |
| 732 | + }, | |
| 733 | + [CLKC_RESET_A5_GLOBAL_RESET] = { | |
| 734 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 18 | |
| 735 | + }, | |
| 736 | + [CLKC_RESET_A5_AXI_SOFT_RESET] = { | |
| 737 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 17 | |
| 738 | + }, | |
| 739 | + [CLKC_RESET_A5_ABP_SOFT_RESET] = { | |
| 740 | + .reg = HHI_SYS_CPU_CLK_CNTL0, .bit_idx = 16 | |
| 741 | + }, | |
| 742 | + [CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET] = { | |
| 743 | + .reg = HHI_SYS_CPU_CLK_CNTL1, .bit_idx = 30 | |
| 744 | + }, | |
| 745 | + [CLKC_RESET_VID_CLK_CNTL_SOFT_RESET] = { | |
| 746 | + .reg = HHI_VID_CLK_CNTL, .bit_idx = 15 | |
| 747 | + }, | |
| 748 | + [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST] = { | |
| 749 | + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 7 | |
| 750 | + }, | |
| 751 | + [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE] = { | |
| 752 | + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 3 | |
| 753 | + }, | |
| 754 | + [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST] = { | |
| 755 | + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 1 | |
| 756 | + }, | |
| 757 | + [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE] = { | |
| 758 | + .reg = HHI_VID_DIVIDER_CNTL, .bit_idx = 0 | |
| 759 | + }, | |
| 760 | +}; | |
| 761 | + | |
| 762 | +static int meson8b_clk_reset_update(struct reset_controller_dev *rcdev, | |
| 763 | + unsigned long id, bool assert) | |
| 764 | +{ | |
| 765 | + struct meson8b_clk_reset *meson8b_clk_reset = | |
| 766 | + container_of(rcdev, struct meson8b_clk_reset, reset); | |
| 767 | + unsigned long flags; | |
| 768 | + const struct meson8b_clk_reset_line *reset; | |
| 769 | + u32 val; | |
| 770 | + | |
| 771 | + if (id >= ARRAY_SIZE(meson8b_clk_reset_bits)) | |
| 772 | + return -EINVAL; | |
| 773 | + | |
| 774 | + reset = &meson8b_clk_reset_bits[id]; | |
| 775 | + | |
| 776 | + spin_lock_irqsave(&clk_lock, flags); | |
| 777 | + | |
| 778 | + val = readl(meson8b_clk_reset->base + reset->reg); | |
| 779 | + if (assert) | |
| 780 | + val |= BIT(reset->bit_idx); | |
| 781 | + else | |
| 782 | + val &= ~BIT(reset->bit_idx); | |
| 783 | + writel(val, meson8b_clk_reset->base + reset->reg); | |
| 784 | + | |
| 785 | + spin_unlock_irqrestore(&clk_lock, flags); | |
| 786 | + | |
| 787 | + return 0; | |
| 788 | +} | |
| 789 | + | |
| 790 | +static int meson8b_clk_reset_assert(struct reset_controller_dev *rcdev, | |
| 791 | + unsigned long id) | |
| 792 | +{ | |
| 793 | + return meson8b_clk_reset_update(rcdev, id, true); | |
| 794 | +} | |
| 795 | + | |
| 796 | +static int meson8b_clk_reset_deassert(struct reset_controller_dev *rcdev, | |
| 797 | + unsigned long id) | |
| 798 | +{ | |
| 799 | + return meson8b_clk_reset_update(rcdev, id, false); | |
| 800 | +} | |
| 801 | + | |
| 802 | +static const struct reset_control_ops meson8b_clk_reset_ops = { | |
| 803 | + .assert = meson8b_clk_reset_assert, | |
| 804 | + .deassert = meson8b_clk_reset_deassert, | |
| 805 | +}; | |
| 806 | + | |
| 699 | 807 | static int meson8b_clkc_probe(struct platform_device *pdev) |
| 700 | 808 | { |
| 701 | − void __iomem *clk_base; | |
| 702 | 809 | int ret, clkid, i; |
| 703 | 810 | struct clk_hw *parent_hw; |
| 704 | 811 | struct clk *parent_clk; |
| 705 | 812 | struct device *dev = &pdev->dev; |
| 706 | 813 | |
| 707 | − /* Generic clocks and PLLs */ | |
| 708 | − clk_base = of_iomap(dev->of_node, 1); | |
| 709 | − if (!clk_base) { | |
| 710 | − pr_err("%s: Unable to map clk base\n", __func__); | |
| 814 | + if (!clk_base) | |
| 711 | 815 | return -ENXIO; |
| 712 | − } | |
| 713 | 816 | |
| 714 | 817 | /* Populate base address for PLLs */ |
| 715 | 818 | for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) |
| @@ -749,7 +852,7 @@ static int meson8b_clkc_probe(struct platform_device *pdev) · 33 unmodified lines | ||
| 749 | 852 | /* FIXME convert to devm_clk_register */ |
| 750 | 853 | ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]); |
| 751 | 854 | if (ret) |
| 752 | − goto iounmap; | |
| 855 | + return ret; | |
| 753 | 856 | } |
| 754 | 857 | |
| 755 | 858 | /* |
| @@ -772,15 +875,11 @@ static int meson8b_clkc_probe(struct platform_device *pdev) · 16 unmodified lines | ||
| 772 | 875 | if (ret) { |
| 773 | 876 | pr_err("%s: failed to register clock notifier for cpu_clk\n", |
| 774 | 877 | __func__); |
| 775 | − goto iounmap; | |
| 878 | + return ret; | |
| 776 | 879 | } |
| 777 | 880 | |
| 778 | 881 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, |
| 779 | 882 | &meson8b_hw_onecell_data); |
| 780 | − | |
| 781 | −iounmap: | |
| 782 | − iounmap(clk_base); | |
| 783 | − return ret; | |
| 784 | 883 | } |
| 785 | 884 | |
| 786 | 885 | static const struct of_device_id meson8b_clkc_match_table[] = { |
| @@ -799,3 +898,39 @@ static struct platform_driver meson8b_driver = { · 12 unmodified lines | ||
| 799 | 898 | }; |
| 800 | 899 | |
| 801 | 900 | builtin_platform_driver(meson8b_driver); |
| 901 | + | |
| 902 | +static void __init meson8b_clkc_reset_init(struct device_node *np) | |
| 903 | +{ | |
| 904 | + struct meson8b_clk_reset *rstc; | |
| 905 | + int ret; | |
| 906 | + | |
| 907 | + /* Generic clocks, PLLs and some of the reset-bits */ | |
| 908 | + clk_base = of_iomap(np, 1); | |
| 909 | + if (!clk_base) { | |
| 910 | + pr_err("%s: Unable to map clk base\n", __func__); | |
| 911 | + return; | |
| 912 | + } | |
| 913 | + | |
| 914 | + rstc = kzalloc(sizeof(*rstc), GFP_KERNEL); | |
| 915 | + if (!rstc) | |
| 916 | + return; | |
| 917 | + | |
| 918 | + /* Reset Controller */ | |
| 919 | + rstc->base = clk_base; | |
| 920 | + rstc->reset.ops = &meson8b_clk_reset_ops; | |
| 921 | + rstc->reset.nr_resets = ARRAY_SIZE(meson8b_clk_reset_bits); | |
| 922 | + rstc->reset.of_node = np; | |
| 923 | + ret = reset_controller_register(&rstc->reset); | |
| 924 | + if (ret) { | |
| 925 | + pr_err("%s: Failed to register clkc reset controller: %d\n", | |
| 926 | + __func__, ret); | |
| 927 | + return; | |
| 928 | + } | |
| 929 | +} | |
| 930 | + | |
| 931 | +CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", | |
| 932 | + meson8b_clkc_reset_init); | |
| 933 | +CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", | |
| 934 | + meson8b_clkc_reset_init); | |
| 935 | +CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", | |
| 936 | + meson8b_clkc_reset_init); | |
| @@ -37,6 +37,9 @@ · 36 unmodified lines | ||
| 37 | 37 | #define HHI_GCLK_AO 0x154 /* 0x55 offset in data sheet */ |
| 38 | 38 | #define HHI_SYS_CPU_CLK_CNTL1 0x15c /* 0x57 offset in data sheet */ |
| 39 | 39 | #define HHI_MPEG_CLK_CNTL 0x174 /* 0x5d offset in data sheet */ |
| 40 | +#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */ | |
| 41 | +#define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */ | |
| 42 | +#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ | |
| 40 | 43 | #define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ |
| 41 | 44 | #define HHI_SYS_PLL_CNTL 0x300 /* 0xc0 offset in data sheet */ |
| 42 | 45 | #define HHI_VID_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */ |
| @@ -68,7 +71,11 @@ · 25 unmodified lines | ||
| 68 | 71 | |
| 69 | 72 | #define CLK_NR_CLKS 96 |
| 70 | 73 | |
| 71 | −/* include the CLKIDs that have been made part of the stable DT binding */ | |
| 74 | +/* | |
| 75 | + * include the CLKID and RESETID that have | |
| 76 | + * been made part of the stable DT binding | |
| 77 | + */ | |
| 72 | 78 | #include <dt-bindings/clock/meson8b-clkc.h> |
| 79 | +#include <dt-bindings/reset/amlogic,meson8b-clkc-reset.h> | |
| 73 | 80 | |
| 74 | 81 | #endif /* __MESON8B_H */ |
| @@ -9,7 +9,7 @@ · 8 unmodified lines | ||
| 9 | 9 | void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit, |
| 10 | 10 | int nr_clks) |
| 11 | 11 | { |
| 12 | − static struct clk **clk_table; | |
| 12 | + struct clk **clk_table; | |
| 13 | 13 | |
| 14 | 14 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); |
| 15 | 15 | if (!clk_table) |
| @@ -885,7 +885,7 @@ static const struct clk_ops clk_usb_i2c_ops = { · 884 unmodified lines | ||
| 885 | 885 | .recalc_rate = clk_usb_i2c_recalc_rate, |
| 886 | 886 | }; |
| 887 | 887 | |
| 888 | −static int clk_gate_enable(struct clk_hw *hw) | |
| 888 | +static int lpc32xx_clk_gate_enable(struct clk_hw *hw) | |
| 889 | 889 | { |
| 890 | 890 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 891 | 891 | u32 mask = BIT(clk->bit_idx); |
| @@ -894,7 +894,7 @@ static int clk_gate_enable(struct clk_hw *hw) · 2 unmodified lines | ||
| 894 | 894 | return regmap_update_bits(clk_regmap, clk->reg, mask, val); |
| 895 | 895 | } |
| 896 | 896 | |
| 897 | −static void clk_gate_disable(struct clk_hw *hw) | |
| 897 | +static void lpc32xx_clk_gate_disable(struct clk_hw *hw) | |
| 898 | 898 | { |
| 899 | 899 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 900 | 900 | u32 mask = BIT(clk->bit_idx); |
| @@ -903,7 +903,7 @@ static void clk_gate_disable(struct clk_hw *hw) · 2 unmodified lines | ||
| 903 | 903 | regmap_update_bits(clk_regmap, clk->reg, mask, val); |
| 904 | 904 | } |
| 905 | 905 | |
| 906 | −static int clk_gate_is_enabled(struct clk_hw *hw) | |
| 906 | +static int lpc32xx_clk_gate_is_enabled(struct clk_hw *hw) | |
| 907 | 907 | { |
| 908 | 908 | struct lpc32xx_clk_gate *clk = to_lpc32xx_gate(hw); |
| 909 | 909 | u32 val; |
| @@ -916,9 +916,9 @@ static int clk_gate_is_enabled(struct clk_hw *hw) · 6 unmodified lines | ||
| 916 | 916 | } |
| 917 | 917 | |
| 918 | 918 | static const struct clk_ops lpc32xx_clk_gate_ops = { |
| 919 | − .enable = clk_gate_enable, | |
| 920 | − .disable = clk_gate_disable, | |
| 921 | − .is_enabled = clk_gate_is_enabled, | |
| 919 | + .enable = lpc32xx_clk_gate_enable, | |
| 920 | + .disable = lpc32xx_clk_gate_disable, | |
| 921 | + .is_enabled = lpc32xx_clk_gate_is_enabled, | |
| 922 | 922 | }; |
| 923 | 923 | |
| 924 | 924 | #define div_mask(width) ((1 << (width)) - 1) |
| @@ -412,8 +412,6 @@ static const struct clk_ops clk_smd_rpm_ops = { · 411 unmodified lines | ||
| 412 | 412 | static const struct clk_ops clk_smd_rpm_branch_ops = { |
| 413 | 413 | .prepare = clk_smd_rpm_prepare, |
| 414 | 414 | .unprepare = clk_smd_rpm_unprepare, |
| 415 | − .round_rate = clk_smd_rpm_round_rate, | |
| 416 | − .recalc_rate = clk_smd_rpm_recalc_rate, | |
| 417 | 415 | }; |
| 418 | 416 | |
| 419 | 417 | /* msm8916 */ |
| @@ -1176,7 +1176,7 @@ static struct clk_rcg2 bimc_gpu_clk_src = { · 1175 unmodified lines | ||
| 1176 | 1176 | .parent_names = gcc_xo_gpll0_bimc, |
| 1177 | 1177 | .num_parents = 3, |
| 1178 | 1178 | .flags = CLK_GET_RATE_NOCACHE, |
| 1179 | − .ops = &clk_rcg2_shared_ops, | |
| 1179 | + .ops = &clk_rcg2_ops, | |
| 1180 | 1180 | }, |
| 1181 | 1181 | }; |
| 1182 | 1182 | |
| @@ -2730,6 +2730,32 @@ static struct clk_fixed_factor ufs_rx_cfg_clk_src = { · 2729 unmodified lines | ||
| 2730 | 2730 | }, |
| 2731 | 2731 | }; |
| 2732 | 2732 | |
| 2733 | +static struct clk_branch gcc_hlos1_vote_lpass_core_smmu_clk = { | |
| 2734 | + .halt_reg = 0x7d010, | |
| 2735 | + .halt_check = BRANCH_HALT_VOTED, | |
| 2736 | + .clkr = { | |
| 2737 | + .enable_reg = 0x7d010, | |
| 2738 | + .enable_mask = BIT(0), | |
| 2739 | + .hw.init = &(struct clk_init_data){ | |
| 2740 | + .name = "hlos1_vote_lpass_core_smmu_clk", | |
| 2741 | + .ops = &clk_branch2_ops, | |
| 2742 | + }, | |
| 2743 | + }, | |
| 2744 | +}; | |
| 2745 | + | |
| 2746 | +static struct clk_branch gcc_hlos1_vote_lpass_adsp_smmu_clk = { | |
| 2747 | + .halt_reg = 0x7d014, | |
| 2748 | + .halt_check = BRANCH_HALT_VOTED, | |
| 2749 | + .clkr = { | |
| 2750 | + .enable_reg = 0x7d014, | |
| 2751 | + .enable_mask = BIT(0), | |
| 2752 | + .hw.init = &(struct clk_init_data){ | |
| 2753 | + .name = "hlos1_vote_lpass_adsp_smmu_clk", | |
| 2754 | + .ops = &clk_branch2_ops, | |
| 2755 | + }, | |
| 2756 | + }, | |
| 2757 | +}; | |
| 2758 | + | |
| 2733 | 2759 | static struct clk_branch gcc_ufs_rx_cfg_clk = { |
| 2734 | 2760 | .halt_reg = 0x75014, |
| 2735 | 2761 | .clkr = { |
| @@ -3307,6 +3333,8 @@ static struct clk_regmap *gcc_msm8996_clocks[] = { · 571 unmodified lines | ||
| 3307 | 3333 | [GCC_UFS_AHB_CLK] = &gcc_ufs_ahb_clk.clkr, |
| 3308 | 3334 | [GCC_UFS_TX_CFG_CLK] = &gcc_ufs_tx_cfg_clk.clkr, |
| 3309 | 3335 | [GCC_UFS_RX_CFG_CLK] = &gcc_ufs_rx_cfg_clk.clkr, |
| 3336 | + [GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK] = &gcc_hlos1_vote_lpass_core_smmu_clk.clkr, | |
| 3337 | + [GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK] = &gcc_hlos1_vote_lpass_adsp_smmu_clk.clkr, | |
| 3310 | 3338 | [GCC_UFS_TX_SYMBOL_0_CLK] = &gcc_ufs_tx_symbol_0_clk.clkr, |
| 3311 | 3339 | [GCC_UFS_RX_SYMBOL_0_CLK] = &gcc_ufs_rx_symbol_0_clk.clkr, |
| 3312 | 3340 | [GCC_UFS_RX_SYMBOL_1_CLK] = &gcc_ufs_rx_symbol_1_clk.clkr, |
| @@ -15,6 +15,7 @@ config CLK_RENESAS · 14 unmodified lines | ||
| 15 | 15 | select CLK_R8A7794 if ARCH_R8A7794 |
| 16 | 16 | select CLK_R8A7795 if ARCH_R8A7795 |
| 17 | 17 | select CLK_R8A7796 if ARCH_R8A7796 |
| 18 | + select CLK_R8A77995 if ARCH_R8A77995 | |
| 18 | 19 | select CLK_SH73A0 if ARCH_SH73A0 |
| 19 | 20 | |
| 20 | 21 | if CLK_RENESAS |
| @@ -34,94 +35,103 @@ config CLK_EMEV2 · 13 unmodified lines | ||
| 34 | 35 | bool "Emma Mobile EV2 clock support" if COMPILE_TEST |
| 35 | 36 | |
| 36 | 37 | config CLK_RZA1 |
| 37 | − bool | |
| 38 | + bool "RZ/A1H clock support" if COMPILE_TEST | |
| 38 | 39 | select CLK_RENESAS_CPG_MSTP |
| 39 | 40 | |
| 40 | 41 | config CLK_R8A73A4 |
| 41 | − bool | |
| 42 | + bool "R-Mobile APE6 clock support" if COMPILE_TEST | |
| 42 | 43 | select CLK_RENESAS_CPG_MSTP |
| 43 | 44 | select CLK_RENESAS_DIV6 |
| 44 | 45 | |
| 45 | 46 | config CLK_R8A7740 |
| 46 | − bool | |
| 47 | + bool "R-Mobile A1 clock support" if COMPILE_TEST | |
| 47 | 48 | select CLK_RENESAS_CPG_MSTP |
| 48 | 49 | select CLK_RENESAS_DIV6 |
| 49 | 50 | |
| 50 | 51 | config CLK_R8A7743 |
| 51 | − bool | |
| 52 | + bool "RZ/G1M clock support" if COMPILE_TEST | |
| 52 | 53 | select CLK_RCAR_GEN2_CPG |
| 53 | 54 | |
| 54 | 55 | config CLK_R8A7745 |
| 55 | − bool | |
| 56 | + bool "RZ/G1E clock support" if COMPILE_TEST | |
| 56 | 57 | select CLK_RCAR_GEN2_CPG |
| 57 | 58 | |
| 58 | 59 | config CLK_R8A7778 |
| 59 | − bool | |
| 60 | + bool "R-Car M1A clock support" if COMPILE_TEST | |
| 60 | 61 | select CLK_RENESAS_CPG_MSTP |
| 61 | 62 | |
| 62 | 63 | config CLK_R8A7779 |
| 63 | − bool | |
| 64 | + bool "R-Car H1 clock support" if COMPILE_TEST | |
| 64 | 65 | select CLK_RENESAS_CPG_MSTP |
| 65 | 66 | |
| 66 | 67 | config CLK_R8A7790 |
| 67 | − bool | |
| 68 | + bool "R-Car H2 clock support" if COMPILE_TEST | |
| 68 | 69 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 69 | 70 | select CLK_RCAR_GEN2_CPG |
| 70 | 71 | select CLK_RENESAS_DIV6 |
| 71 | 72 | |
| 72 | 73 | config CLK_R8A7791 |
| 73 | − bool | |
| 74 | + bool "R-Car M2-W/N clock support" if COMPILE_TEST | |
| 74 | 75 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 75 | 76 | select CLK_RCAR_GEN2_CPG |
| 76 | 77 | select CLK_RENESAS_DIV6 |
| 77 | 78 | |
| 78 | 79 | config CLK_R8A7792 |
| 79 | − bool | |
| 80 | + bool "R-Car V2H clock support" if COMPILE_TEST | |
| 80 | 81 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 81 | 82 | select CLK_RCAR_GEN2_CPG |
| 82 | 83 | |
| 83 | 84 | config CLK_R8A7794 |
| 84 | − bool | |
| 85 | + bool "R-Car E2 clock support" if COMPILE_TEST | |
| 85 | 86 | select CLK_RCAR_GEN2 if CLK_RENESAS_LEGACY |
| 86 | 87 | select CLK_RCAR_GEN2_CPG |
| 87 | 88 | select CLK_RENESAS_DIV6 |
| 88 | 89 | |
| 89 | 90 | config CLK_R8A7795 |
| 90 | − bool | |
| 91 | + bool "R-Car H3 clock support" if COMPILE_TEST | |
| 91 | 92 | select CLK_RCAR_GEN3_CPG |
| 92 | 93 | |
| 93 | 94 | config CLK_R8A7796 |
| 94 | − bool | |
| 95 | + bool "R-Car M3-W clock support" if COMPILE_TEST | |
| 96 | + select CLK_RCAR_GEN3_CPG | |
| 97 | + | |
| 98 | +config CLK_R8A77995 | |
| 99 | + bool "R-Car D3 clock support" if COMPILE_TEST | |
| 95 | 100 | select CLK_RCAR_GEN3_CPG |
| 96 | 101 | |
| 97 | 102 | config CLK_SH73A0 |
| 98 | − bool | |
| 103 | + bool "SH-Mobile AG5 clock support" if COMPILE_TEST | |
| 99 | 104 | select CLK_RENESAS_CPG_MSTP |
| 100 | 105 | select CLK_RENESAS_DIV6 |
| 101 | 106 | |
| 102 | 107 | |
| 103 | 108 | # Family |
| 104 | 109 | config CLK_RCAR_GEN2 |
| 105 | − bool | |
| 110 | + bool "R-Car Gen2 legacy clock support" if COMPILE_TEST | |
| 106 | 111 | select CLK_RENESAS_CPG_MSTP |
| 107 | 112 | select CLK_RENESAS_DIV6 |
| 108 | 113 | |
| 109 | 114 | config CLK_RCAR_GEN2_CPG |
| 110 | − bool | |
| 115 | + bool "R-Car Gen2 CPG clock support" if COMPILE_TEST | |
| 111 | 116 | select CLK_RENESAS_CPG_MSSR |
| 112 | 117 | |
| 113 | 118 | config CLK_RCAR_GEN3_CPG |
| 114 | − bool | |
| 119 | + bool "R-Car Gen3 CPG clock support" if COMPILE_TEST | |
| 115 | 120 | select CLK_RENESAS_CPG_MSSR |
| 116 | 121 | |
| 122 | +config CLK_RCAR_USB2_CLOCK_SEL | |
| 123 | + bool "Renesas R-Car USB2 clock selector support" | |
| 124 | + depends on ARCH_RENESAS || COMPILE_TEST | |
| 125 | + help | |
| 126 | + This is a driver for R-Car USB2 clock selector | |
| 117 | 127 | |
| 118 | 128 | # Generic |
| 119 | 129 | config CLK_RENESAS_CPG_MSSR |
| 120 | − bool | |
| 130 | + bool "CPG/MSSR clock support" if COMPILE_TEST | |
| 121 | 131 | select CLK_RENESAS_DIV6 |
| 122 | 132 | |
| 123 | 133 | config CLK_RENESAS_CPG_MSTP |
| 124 | − bool | |
| 134 | + bool "MSTP clock support" if COMPILE_TEST | |
| 125 | 135 | |
| 126 | 136 | config CLK_RENESAS_DIV6 |
| 127 | 137 | bool "DIV6 clock support" if COMPILE_TEST |
| @@ -13,12 +13,14 @@ obj-$(CONFIG_CLK_R8A7792) += r8a7792-cpg-mssr.o · 12 unmodified lines | ||
| 13 | 13 | obj-$(CONFIG_CLK_R8A7794) += r8a7794-cpg-mssr.o |
| 14 | 14 | obj-$(CONFIG_CLK_R8A7795) += r8a7795-cpg-mssr.o |
| 15 | 15 | obj-$(CONFIG_CLK_R8A7796) += r8a7796-cpg-mssr.o |
| 16 | +obj-$(CONFIG_CLK_R8A77995) += r8a77995-cpg-mssr.o | |
| 16 | 17 | obj-$(CONFIG_CLK_SH73A0) += clk-sh73a0.o |
| 17 | 18 | |
| 18 | 19 | # Family |
| 19 | 20 | obj-$(CONFIG_CLK_RCAR_GEN2) += clk-rcar-gen2.o |
| 20 | 21 | obj-$(CONFIG_CLK_RCAR_GEN2_CPG) += rcar-gen2-cpg.o |
| 21 | 22 | obj-$(CONFIG_CLK_RCAR_GEN3_CPG) += rcar-gen3-cpg.o |
| 23 | +obj-$(CONFIG_CLK_RCAR_USB2_CLOCK_SEL) += rcar-usb2-clock-sel.o | |
| 22 | 24 | |
| 23 | 25 | # Generic |
| 24 | 26 | obj-$(CONFIG_CLK_RENESAS_CPG_MSSR) += renesas-cpg-mssr.o |
| @@ -29,6 +29,9 @@ · 28 unmodified lines | ||
| 29 | 29 | * @hw: handle between common and hardware-specific interfaces |
| 30 | 30 | * @reg: IO-remapped register |
| 31 | 31 | * @div: divisor value (1-64) |
| 32 | + * @src_shift: Shift to access the register bits to select the parent clock | |
| 33 | + * @src_width: Number of register bits to select the parent clock (may be 0) | |
| 34 | + * @parents: Array to map from valid parent clocks indices to hardware indices | |
| 32 | 35 | */ |
| 33 | 36 | struct div6_clock { |
| 34 | 37 | struct clk_hw hw; |
| @@ -335,7 +335,7 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np) · 334 unmodified lines | ||
| 335 | 335 | u32 ncells; |
| 336 | 336 | |
| 337 | 337 | if (of_property_read_u32(np, "#power-domain-cells", &ncells)) { |
| 338 | − pr_warn("%s lacks #power-domain-cells\n", np->full_name); | |
| 338 | + pr_warn("%pOF lacks #power-domain-cells\n", np); | |
| 339 | 339 | return; |
| 340 | 340 | } |
| 341 | 341 | |
| @@ -407,8 +407,7 @@ static void __init rcar_gen2_cpg_clocks_init(struct device_node *np) · 406 unmodified lines | ||
| 407 | 407 | |
| 408 | 408 | if (rcar_rst_read_mode_pins(&cpg_mode)) { |
| 409 | 409 | /* Backward-compatibility with old DT */ |
| 410 | − pr_warn("%s: failed to obtain mode pins from RST\n", | |
| 411 | − np->full_name); | |
| 410 | + pr_warn("%pOF: failed to obtain mode pins from RST\n", np); | |
| 412 | 411 | cpg_mode = rcar_gen2_read_mode_pins(); |
| 413 | 412 | } |
| 414 | 413 | |
| @@ -118,6 +118,13 @@ static const struct mssr_mod_clk r8a7792_mod_clks[] __initconst = { · 117 unmodified lines | ||
| 118 | 118 | DEF_MOD("vin1", 810, R8A7792_CLK_ZG), |
| 119 | 119 | DEF_MOD("vin0", 811, R8A7792_CLK_ZG), |
| 120 | 120 | DEF_MOD("etheravb", 812, R8A7792_CLK_HP), |
| 121 | + DEF_MOD("imr-lx3", 821, R8A7792_CLK_ZG), | |
| 122 | + DEF_MOD("imr-lsx3-1", 822, R8A7792_CLK_ZG), | |
| 123 | + DEF_MOD("imr-lsx3-0", 823, R8A7792_CLK_ZG), | |
| 124 | + DEF_MOD("imr-lsx3-5", 825, R8A7792_CLK_ZG), | |
| 125 | + DEF_MOD("imr-lsx3-4", 826, R8A7792_CLK_ZG), | |
| 126 | + DEF_MOD("imr-lsx3-3", 827, R8A7792_CLK_ZG), | |
| 127 | + DEF_MOD("imr-lsx3-2", 828, R8A7792_CLK_ZG), | |
| 121 | 128 | DEF_MOD("gyro-adc", 901, R8A7792_CLK_P), |
| 122 | 129 | DEF_MOD("gpio7", 904, R8A7792_CLK_CP), |
| 123 | 130 | DEF_MOD("gpio6", 905, R8A7792_CLK_CP), |
| @@ -305,23 +305,23 @@ static const unsigned int r8a7795_crit_mod_clks[] __initconst = { · 304 unmodified lines | ||
| 305 | 305 | (((md) & BIT(17)) >> 17)) |
| 306 | 306 | |
| 307 | 307 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { |
| 308 | − /* EXTAL div PLL1 mult PLL3 mult */ | |
| 309 | − { 1, 192, 192, }, | |
| 310 | − { 1, 192, 128, }, | |
| 311 | − { 0, /* Prohibited setting */ }, | |
| 312 | − { 1, 192, 192, }, | |
| 313 | − { 1, 160, 160, }, | |
| 314 | − { 1, 160, 106, }, | |
| 315 | − { 0, /* Prohibited setting */ }, | |
| 316 | − { 1, 160, 160, }, | |
| 317 | − { 1, 128, 128, }, | |
| 318 | − { 1, 128, 84, }, | |
| 319 | − { 0, /* Prohibited setting */ }, | |
| 320 | − { 1, 128, 128, }, | |
| 321 | − { 2, 192, 192, }, | |
| 322 | − { 2, 192, 128, }, | |
| 323 | − { 0, /* Prohibited setting */ }, | |
| 324 | − { 2, 192, 192, }, | |
| 308 | + /* EXTAL div PLL1 mult/div PLL3 mult/div */ | |
| 309 | + { 1, 192, 1, 192, 1, }, | |
| 310 | + { 1, 192, 1, 128, 1, }, | |
| 311 | + { 0, /* Prohibited setting */ }, | |
| 312 | + { 1, 192, 1, 192, 1, }, | |
| 313 | + { 1, 160, 1, 160, 1, }, | |
| 314 | + { 1, 160, 1, 106, 1, }, | |
| 315 | + { 0, /* Prohibited setting */ }, | |
| 316 | + { 1, 160, 1, 160, 1, }, | |
| 317 | + { 1, 128, 1, 128, 1, }, | |
| 318 | + { 1, 128, 1, 84, 1, }, | |
| 319 | + { 0, /* Prohibited setting */ }, | |
| 320 | + { 1, 128, 1, 128, 1, }, | |
| 321 | + { 2, 192, 1, 192, 1, }, | |
| 322 | + { 2, 192, 1, 128, 1, }, | |
| 323 | + { 0, /* Prohibited setting */ }, | |
| 324 | + { 2, 192, 1, 192, 1, }, | |
| 325 | 325 | }; |
| 326 | 326 | |
| 327 | 327 | static const struct soc_device_attribute r8a7795es1[] __initconst = { |
| @@ -138,6 +138,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = { · 137 unmodified lines | ||
| 138 | 138 | DEF_MOD("sdif0", 314, R8A7796_CLK_SD0), |
| 139 | 139 | DEF_MOD("pcie1", 318, R8A7796_CLK_S3D1), |
| 140 | 140 | DEF_MOD("pcie0", 319, R8A7796_CLK_S3D1), |
| 141 | + DEF_MOD("usb3-if0", 328, R8A7796_CLK_S3D1), | |
| 141 | 142 | DEF_MOD("usb-dmac0", 330, R8A7796_CLK_S3D1), |
| 142 | 143 | DEF_MOD("usb-dmac1", 331, R8A7796_CLK_S3D1), |
| 143 | 144 | DEF_MOD("rwdt", 402, R8A7796_CLK_R), |
| @@ -277,23 +278,23 @@ static const unsigned int r8a7796_crit_mod_clks[] __initconst = { · 133 unmodified lines | ||
| 277 | 278 | (((md) & BIT(17)) >> 17)) |
| 278 | 279 | |
| 279 | 280 | static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = { |
| 280 | − /* EXTAL div PLL1 mult PLL3 mult */ | |
| 281 | − { 1, 192, 192, }, | |
| 282 | − { 1, 192, 128, }, | |
| 283 | − { 0, /* Prohibited setting */ }, | |
| 284 | − { 1, 192, 192, }, | |
| 285 | − { 1, 160, 160, }, | |
| 286 | − { 1, 160, 106, }, | |
| 287 | − { 0, /* Prohibited setting */ }, | |
| 288 | − { 1, 160, 160, }, | |
| 289 | − { 1, 128, 128, }, | |
| 290 | − { 1, 128, 84, }, | |
| 291 | − { 0, /* Prohibited setting */ }, | |
| 292 | − { 1, 128, 128, }, | |
| 293 | − { 2, 192, 192, }, | |
| 294 | − { 2, 192, 128, }, | |
| 295 | − { 0, /* Prohibited setting */ }, | |
| 296 | − { 2, 192, 192, }, | |
| 281 | + /* EXTAL div PLL1 mult/div PLL3 mult/div */ | |
| 282 | + { 1, 192, 1, 192, 1, }, | |
| 283 | + { 1, 192, 1, 128, 1, }, | |
| 284 | + { 0, /* Prohibited setting */ }, | |
| 285 | + { 1, 192, 1, 192, 1, }, | |
| 286 | + { 1, 160, 1, 160, 1, }, | |
| 287 | + { 1, 160, 1, 106, 1, }, | |
| 288 | + { 0, /* Prohibited setting */ }, | |
| 289 | + { 1, 160, 1, 160, 1, }, | |
| 290 | + { 1, 128, 1, 128, 1, }, | |
| 291 | + { 1, 128, 1, 84, 1, }, | |
| 292 | + { 0, /* Prohibited setting */ }, | |
| 293 | + { 1, 128, 1, 128, 1, }, | |
| 294 | + { 2, 192, 1, 192, 1, }, | |
| 295 | + { 2, 192, 1, 128, 1, }, | |
| 296 | + { 0, /* Prohibited setting */ }, | |
| 297 | + { 2, 192, 1, 192, 1, }, | |
| 297 | 298 | }; |
| 298 | 299 | |
| 299 | 300 | static int __init r8a7796_cpg_mssr_init(struct device *dev) |
| @@ -0,0 +1,236 @@ | ||
| 1 | +/* | |
| 2 | + * r8a77995 Clock Pulse Generator / Module Standby and Software Reset | |
| 3 | + * | |
| 4 | + * Copyright (C) 2017 Glider bvba | |
| 5 | + * | |
| 6 | + * Based on r8a7795-cpg-mssr.c | |
| 7 | + * | |
| 8 | + * Copyright (C) 2015 Glider bvba | |
| 9 | + * Copyright (C) 2015 Renesas Electronics Corp. | |
| 10 | + * | |
| 11 | + * This program is free software; you can redistribute it and/or modify | |
| 12 | + * it under the terms of the GNU General Public License as published by | |
| 13 | + * the Free Software Foundation; version 2 of the License. | |
| 14 | + */ | |
| 15 | + | |
| 16 | +#include <linux/device.h> | |
| 17 | +#include <linux/init.h> | |
| 18 | +#include <linux/kernel.h> | |
| 19 | +#include <linux/soc/renesas/rcar-rst.h> | |
| 20 | + | |
| 21 | +#include <dt-bindings/clock/r8a77995-cpg-mssr.h> | |
| 22 | + | |
| 23 | +#include "renesas-cpg-mssr.h" | |
| 24 | +#include "rcar-gen3-cpg.h" | |
| 25 | + | |
| 26 | +enum clk_ids { | |
| 27 | + /* Core Clock Outputs exported to DT */ | |
| 28 | + LAST_DT_CORE_CLK = R8A77995_CLK_CP, | |
| 29 | + | |
| 30 | + /* External Input Clocks */ | |
| 31 | + CLK_EXTAL, | |
| 32 | + | |
| 33 | + /* Internal Core Clocks */ | |
| 34 | + CLK_MAIN, | |
| 35 | + CLK_PLL0, | |
| 36 | + CLK_PLL1, | |
| 37 | + CLK_PLL3, | |
| 38 | + CLK_PLL0D2, | |
| 39 | + CLK_PLL0D3, | |
| 40 | + CLK_PLL0D5, | |
| 41 | + CLK_PLL1D2, | |
| 42 | + CLK_PE, | |
| 43 | + CLK_S0, | |
| 44 | + CLK_S1, | |
| 45 | + CLK_S2, | |
| 46 | + CLK_S3, | |
| 47 | + CLK_SDSRC, | |
| 48 | + CLK_SSPSRC, | |
| 49 | + | |
| 50 | + /* Module Clocks */ | |
| 51 | + MOD_CLK_BASE | |
| 52 | +}; | |
| 53 | + | |
| 54 | +static const struct cpg_core_clk r8a77995_core_clks[] __initconst = { | |
| 55 | + /* External Clock Inputs */ | |
| 56 | + DEF_INPUT("extal", CLK_EXTAL), | |
| 57 | + | |
| 58 | + /* Internal Core Clocks */ | |
| 59 | + DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL), | |
| 60 | + DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN), | |
| 61 | + DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN), | |
| 62 | + | |
| 63 | + DEF_FIXED(".pll0", CLK_PLL0, CLK_MAIN, 4, 250), | |
| 64 | + DEF_FIXED(".pll0d2", CLK_PLL0D2, CLK_PLL0, 2, 1), | |
| 65 | + DEF_FIXED(".pll0d3", CLK_PLL0D3, CLK_PLL0, 3, 1), | |
| 66 | + DEF_FIXED(".pll0d5", CLK_PLL0D5, CLK_PLL0, 5, 1), | |
| 67 | + DEF_FIXED(".pll1d2", CLK_PLL1D2, CLK_PLL1, 2, 1), | |
| 68 | + DEF_FIXED(".pe", CLK_PE, CLK_PLL0D3, 4, 1), | |
| 69 | + DEF_FIXED(".s0", CLK_S0, CLK_PLL1, 2, 1), | |
| 70 | + DEF_FIXED(".s1", CLK_S1, CLK_PLL1, 3, 1), | |
| 71 | + DEF_FIXED(".s2", CLK_S2, CLK_PLL1, 4, 1), | |
| 72 | + DEF_FIXED(".s3", CLK_S3, CLK_PLL1, 6, 1), | |
| 73 | + DEF_FIXED(".sdsrc", CLK_SDSRC, CLK_PLL1, 2, 1), | |
| 74 | + | |
| 75 | + /* Core Clock Outputs */ | |
| 76 | + DEF_FIXED("z2", R8A77995_CLK_Z2, CLK_PLL0D3, 1, 1), | |
| 77 | + DEF_FIXED("ztr", R8A77995_CLK_ZTR, CLK_PLL1, 6, 1), | |
| 78 | + DEF_FIXED("zt", R8A77995_CLK_ZT, CLK_PLL1, 4, 1), | |
| 79 | + DEF_FIXED("zx", R8A77995_CLK_ZX, CLK_PLL1, 3, 1), | |
| 80 | + DEF_FIXED("s0d1", R8A77995_CLK_S0D1, CLK_S0, 1, 1), | |
| 81 | + DEF_FIXED("s1d1", R8A77995_CLK_S1D1, CLK_S1, 1, 1), | |
| 82 | + DEF_FIXED("s1d2", R8A77995_CLK_S1D2, CLK_S1, 2, 1), | |
| 83 | + DEF_FIXED("s1d4", R8A77995_CLK_S1D4, CLK_S1, 4, 1), | |
| 84 | + DEF_FIXED("s2d1", R8A77995_CLK_S2D1, CLK_S2, 1, 1), | |
| 85 | + DEF_FIXED("s2d2", R8A77995_CLK_S2D2, CLK_S2, 2, 1), | |
| 86 | + DEF_FIXED("s2d4", R8A77995_CLK_S2D4, CLK_S2, 4, 1), | |
| 87 | + DEF_FIXED("s3d1", R8A77995_CLK_S3D1, CLK_S3, 1, 1), | |
| 88 | + DEF_FIXED("s3d2", R8A77995_CLK_S3D2, CLK_S3, 2, 1), | |
| 89 | + DEF_FIXED("s3d4", R8A77995_CLK_S3D4, CLK_S3, 4, 1), | |
| 90 | + | |
| 91 | + DEF_FIXED("cl", R8A77995_CLK_CL, CLK_PLL1, 48, 1), | |
| 92 | + DEF_FIXED("cp", R8A77995_CLK_CP, CLK_EXTAL, 2, 1), | |
| 93 | + DEF_FIXED("osc", R8A77995_CLK_OSC, CLK_EXTAL, 384, 1), | |
| 94 | + DEF_FIXED("r", R8A77995_CLK_R, CLK_EXTAL, 1536, 1), | |
| 95 | + | |
| 96 | + DEF_GEN3_PE("s1d4c", R8A77995_CLK_S1D4C, CLK_S1, 4, CLK_PE, 2), | |
| 97 | + DEF_GEN3_PE("s3d1c", R8A77995_CLK_S3D1C, CLK_S3, 1, CLK_PE, 1), | |
| 98 | + DEF_GEN3_PE("s3d2c", R8A77995_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2), | |
| 99 | + DEF_GEN3_PE("s3d4c", R8A77995_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4), | |
| 100 | + | |
| 101 | + DEF_GEN3_SD("sd0", R8A77995_CLK_SD0, CLK_SDSRC, 0x268), | |
| 102 | + | |
| 103 | + DEF_DIV6P1("canfd", R8A77995_CLK_CANFD, CLK_PLL0D3, 0x244), | |
| 104 | + DEF_DIV6P1("mso", R8A77995_CLK_MSO, CLK_PLL1D2, 0x014), | |
| 105 | +}; | |
| 106 | + | |
| 107 | +static const struct mssr_mod_clk r8a77995_mod_clks[] __initconst = { | |
| 108 | + DEF_MOD("scif5", 202, R8A77995_CLK_S3D4C), | |
| 109 | + DEF_MOD("scif4", 203, R8A77995_CLK_S3D4C), | |
| 110 | + DEF_MOD("scif3", 204, R8A77995_CLK_S3D4C), | |
| 111 | + DEF_MOD("scif1", 206, R8A77995_CLK_S3D4C), | |
| 112 | + DEF_MOD("scif0", 207, R8A77995_CLK_S3D4C), | |
| 113 | + DEF_MOD("msiof3", 208, R8A77995_CLK_MSO), | |
| 114 | + DEF_MOD("msiof2", 209, R8A77995_CLK_MSO), | |
| 115 | + DEF_MOD("msiof1", 210, R8A77995_CLK_MSO), | |
| 116 | + DEF_MOD("msiof0", 211, R8A77995_CLK_MSO), | |
| 117 | + DEF_MOD("sys-dmac2", 217, R8A77995_CLK_S3D1), | |
| 118 | + DEF_MOD("sys-dmac1", 218, R8A77995_CLK_S3D1), | |
| 119 | + DEF_MOD("sys-dmac0", 219, R8A77995_CLK_S3D1), | |
| 120 | + DEF_MOD("cmt3", 300, R8A77995_CLK_R), | |
| 121 | + DEF_MOD("cmt2", 301, R8A77995_CLK_R), | |
| 122 | + DEF_MOD("cmt1", 302, R8A77995_CLK_R), | |
| 123 | + DEF_MOD("cmt0", 303, R8A77995_CLK_R), | |
| 124 | + DEF_MOD("scif2", 310, R8A77995_CLK_S3D4C), | |
| 125 | + DEF_MOD("emmc0", 312, R8A77995_CLK_SD0), | |
| 126 | + DEF_MOD("usb-dmac0", 330, R8A77995_CLK_S3D1), | |
| 127 | + DEF_MOD("usb-dmac1", 331, R8A77995_CLK_S3D1), | |
| 128 | + DEF_MOD("rwdt", 402, R8A77995_CLK_R), | |
| 129 | + DEF_MOD("intc-ex", 407, R8A77995_CLK_CP), | |
| 130 | + DEF_MOD("intc-ap", 408, R8A77995_CLK_S3D1), | |
| 131 | + DEF_MOD("audmac0", 502, R8A77995_CLK_S3D1), | |
| 132 | + DEF_MOD("hscif3", 517, R8A77995_CLK_S3D1C), | |
| 133 | + DEF_MOD("hscif0", 520, R8A77995_CLK_S3D1C), | |
| 134 | + DEF_MOD("thermal", 522, R8A77995_CLK_CP), | |
| 135 | + DEF_MOD("pwm", 523, R8A77995_CLK_S3D4C), | |
| 136 | + DEF_MOD("fcpvd1", 602, R8A77995_CLK_S1D2), | |
| 137 | + DEF_MOD("fcpvd0", 603, R8A77995_CLK_S1D2), | |
| 138 | + DEF_MOD("fcpvbs", 607, R8A77995_CLK_S0D1), | |
| 139 | + DEF_MOD("vspd1", 622, R8A77995_CLK_S1D2), | |
| 140 | + DEF_MOD("vspd0", 623, R8A77995_CLK_S1D2), | |
| 141 | + DEF_MOD("vspbs", 627, R8A77995_CLK_S0D1), | |
| 142 | + DEF_MOD("ehci0", 703, R8A77995_CLK_S3D2), | |
| 143 | + DEF_MOD("hsusb", 704, R8A77995_CLK_S3D2), | |
| 144 | + DEF_MOD("du1", 723, R8A77995_CLK_S2D1), | |
| 145 | + DEF_MOD("du0", 724, R8A77995_CLK_S2D1), | |
| 146 | + DEF_MOD("lvds", 727, R8A77995_CLK_S2D1), | |
| 147 | + DEF_MOD("vin7", 804, R8A77995_CLK_S1D2), | |
| 148 | + DEF_MOD("vin6", 805, R8A77995_CLK_S1D2), | |
| 149 | + DEF_MOD("vin5", 806, R8A77995_CLK_S1D2), | |
| 150 | + DEF_MOD("vin4", 807, R8A77995_CLK_S1D2), | |
| 151 | + DEF_MOD("etheravb", 812, R8A77995_CLK_S3D2), | |
| 152 | + DEF_MOD("imr0", 823, R8A77995_CLK_S1D2), | |
| 153 | + DEF_MOD("gpio6", 906, R8A77995_CLK_S3D4), | |
| 154 | + DEF_MOD("gpio5", 907, R8A77995_CLK_S3D4), | |
| 155 | + DEF_MOD("gpio4", 908, R8A77995_CLK_S3D4), | |
| 156 | + DEF_MOD("gpio3", 909, R8A77995_CLK_S3D4), | |
| 157 | + DEF_MOD("gpio2", 910, R8A77995_CLK_S3D4), | |
| 158 | + DEF_MOD("gpio1", 911, R8A77995_CLK_S3D4), | |
| 159 | + DEF_MOD("gpio0", 912, R8A77995_CLK_S3D4), | |
| 160 | + DEF_MOD("can-fd", 914, R8A77995_CLK_S3D2), | |
| 161 | + DEF_MOD("can-if1", 915, R8A77995_CLK_S3D4), | |
| 162 | + DEF_MOD("can-if0", 916, R8A77995_CLK_S3D4), | |
| 163 | + DEF_MOD("i2c3", 928, R8A77995_CLK_S3D2), | |
| 164 | + DEF_MOD("i2c2", 929, R8A77995_CLK_S3D2), | |
| 165 | + DEF_MOD("i2c1", 930, R8A77995_CLK_S3D2), | |
| 166 | + DEF_MOD("i2c0", 931, R8A77995_CLK_S3D2), | |
| 167 | + DEF_MOD("ssi-all", 1005, R8A77995_CLK_S3D4), | |
| 168 | + DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)), | |
| 169 | + DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)), | |
| 170 | + DEF_MOD("scu-all", 1017, R8A77995_CLK_S3D4), | |
| 171 | + DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)), | |
| 172 | + DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)), | |
| 173 | + DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)), | |
| 174 | + DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)), | |
| 175 | + DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)), | |
| 176 | + DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)), | |
| 177 | +}; | |
| 178 | + | |
| 179 | +static const unsigned int r8a77995_crit_mod_clks[] __initconst = { | |
| 180 | + MOD_CLK_ID(408), /* INTC-AP (GIC) */ | |
| 181 | +}; | |
| 182 | + | |
| 183 | + | |
| 184 | +/* | |
| 185 | + * CPG Clock Data | |
| 186 | + */ | |
| 187 | + | |
| 188 | +/* | |
| 189 | + * MD19 EXTAL (MHz) PLL0 PLL1 PLL3 | |
| 190 | + *-------------------------------------------------------------------- | |
| 191 | + * 0 48 x 1 x250/4 x100/3 x100/3 | |
| 192 | + * 1 48 x 1 x250/4 x100/3 x116/6 | |
| 193 | + */ | |
| 194 | +#define CPG_PLL_CONFIG_INDEX(md) (((md) & BIT(19)) >> 19) | |
| 195 | + | |
| 196 | +static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[2] __initconst = { | |
| 197 | + /* EXTAL div PLL1 mult/div PLL3 mult/div */ | |
| 198 | + { 1, 100, 3, 100, 3, }, | |
| 199 | + { 1, 100, 3, 116, 6, }, | |
| 200 | +}; | |
| 201 | + | |
| 202 | +static int __init r8a77995_cpg_mssr_init(struct device *dev) | |
| 203 | +{ | |
| 204 | + const struct rcar_gen3_cpg_pll_config *cpg_pll_config; | |
| 205 | + u32 cpg_mode; | |
| 206 | + int error; | |
| 207 | + | |
| 208 | + error = rcar_rst_read_mode_pins(&cpg_mode); | |
| 209 | + if (error) | |
| 210 | + return error; | |
| 211 | + | |
| 212 | + cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)]; | |
| 213 | + | |
| 214 | + return rcar_gen3_cpg_init(cpg_pll_config, 0, cpg_mode); | |
| 215 | +} | |
| 216 | + | |
| 217 | +const struct cpg_mssr_info r8a77995_cpg_mssr_info __initconst = { | |
| 218 | + /* Core Clocks */ | |
| 219 | + .core_clks = r8a77995_core_clks, | |
| 220 | + .num_core_clks = ARRAY_SIZE(r8a77995_core_clks), | |
| 221 | + .last_dt_core_clk = LAST_DT_CORE_CLK, | |
| 222 | + .num_total_core_clks = MOD_CLK_BASE, | |
| 223 | + | |
| 224 | + /* Module Clocks */ | |
| 225 | + .mod_clks = r8a77995_mod_clks, | |
| 226 | + .num_mod_clks = ARRAY_SIZE(r8a77995_mod_clks), | |
| 227 | + .num_hw_mod_clks = 12 * 32, | |
| 228 | + | |
| 229 | + /* Critical Module Clocks */ | |
| 230 | + .crit_mod_clks = r8a77995_crit_mod_clks, | |
| 231 | + .num_crit_mod_clks = ARRAY_SIZE(r8a77995_crit_mod_clks), | |
| 232 | + | |
| 233 | + /* Callbacks */ | |
| 234 | + .init = r8a77995_cpg_mssr_init, | |
| 235 | + .cpg_clk_register = rcar_gen3_cpg_clk_register, | |
| 236 | +}; | |
| @@ -60,6 +60,7 @@ struct sd_clock { · 59 unmodified lines | ||
| 60 | 60 | unsigned int div_num; |
| 61 | 61 | unsigned int div_min; |
| 62 | 62 | unsigned int div_max; |
| 63 | + unsigned int cur_div_idx; | |
| 63 | 64 | }; |
| 64 | 65 | |
| 65 | 66 | /* SDn divider |
| @@ -96,21 +97,10 @@ static const struct sd_div_table cpg_sd_div_table[] = { · 30 unmodified lines | ||
| 96 | 97 | static int cpg_sd_clock_enable(struct clk_hw *hw) |
| 97 | 98 | { |
| 98 | 99 | struct sd_clock *clock = to_sd_clock(hw); |
| 99 | − u32 val, sd_fc; | |
| 100 | − unsigned int i; | |
| 101 | − | |
| 102 | − val = readl(clock->reg); | |
| 103 | − | |
| 104 | − sd_fc = val & CPG_SD_FC_MASK; | |
| 105 | − for (i = 0; i < clock->div_num; i++) | |
| 106 | − if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | |
| 107 | − break; | |
| 108 | − | |
| 109 | − if (i >= clock->div_num) | |
| 110 | − return -EINVAL; | |
| 100 | + u32 val = readl(clock->reg); | |
| 111 | 101 | |
| 112 | 102 | val &= ~(CPG_SD_STP_MASK); |
| 113 | − val |= clock->div_table[i].val & CPG_SD_STP_MASK; | |
| 103 | + val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK; | |
| 114 | 104 | |
| 115 | 105 | writel(val, clock->reg); |
| 116 | 106 | |
| @@ -135,21 +125,9 @@ static unsigned long cpg_sd_clock_recalc_rate(struct clk_hw *hw, · 18 unmodified lines | ||
| 135 | 125 | unsigned long parent_rate) |
| 136 | 126 | { |
| 137 | 127 | struct sd_clock *clock = to_sd_clock(hw); |
| 138 | − unsigned long rate = parent_rate; | |
| 139 | − u32 val, sd_fc; | |
| 140 | − unsigned int i; | |
| 141 | 128 | |
| 142 | − val = readl(clock->reg); | |
| 143 | − | |
| 144 | − sd_fc = val & CPG_SD_FC_MASK; | |
| 145 | − for (i = 0; i < clock->div_num; i++) | |
| 146 | − if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | |
| 147 | − break; | |
| 148 | − | |
| 149 | − if (i >= clock->div_num) | |
| 150 | − return -EINVAL; | |
| 151 | − | |
| 152 | − return DIV_ROUND_CLOSEST(rate, clock->div_table[i].div); | |
| 129 | + return DIV_ROUND_CLOSEST(parent_rate, | |
| 130 | + clock->div_table[clock->cur_div_idx].div); | |
| 153 | 131 | } |
| 154 | 132 | |
| 155 | 133 | static unsigned int cpg_sd_clock_calc_div(struct sd_clock *clock, |
| @@ -190,6 +168,8 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate, · 34 unmodified lines | ||
| 190 | 168 | if (i >= clock->div_num) |
| 191 | 169 | return -EINVAL; |
| 192 | 170 | |
| 171 | + clock->cur_div_idx = i; | |
| 172 | + | |
| 193 | 173 | val = readl(clock->reg); |
| 194 | 174 | val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK); |
| 195 | 175 | val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK); |
| @@ -215,6 +195,7 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, · 19 unmodified lines | ||
| 215 | 195 | struct sd_clock *clock; |
| 216 | 196 | struct clk *clk; |
| 217 | 197 | unsigned int i; |
| 198 | + u32 sd_fc; | |
| 218 | 199 | |
| 219 | 200 | clock = kzalloc(sizeof(*clock), GFP_KERNEL); |
| 220 | 201 | if (!clock) |
| @@ -231,6 +212,18 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core, · 10 unmodified lines | ||
| 231 | 212 | clock->div_table = cpg_sd_div_table; |
| 232 | 213 | clock->div_num = ARRAY_SIZE(cpg_sd_div_table); |
| 233 | 214 | |
| 215 | + sd_fc = readl(clock->reg) & CPG_SD_FC_MASK; | |
| 216 | + for (i = 0; i < clock->div_num; i++) | |
| 217 | + if (sd_fc == (clock->div_table[i].val & CPG_SD_FC_MASK)) | |
| 218 | + break; | |
| 219 | + | |
| 220 | + if (WARN_ON(i >= clock->div_num)) { | |
| 221 | + kfree(clock); | |
| 222 | + return ERR_PTR(-EINVAL); | |
| 223 | + } | |
| 224 | + | |
| 225 | + clock->cur_div_idx = i; | |
| 226 | + | |
| 234 | 227 | clock->div_max = clock->div_table[0].div; |
| 235 | 228 | clock->div_min = clock->div_max; |
| 236 | 229 | for (i = 1; i < clock->div_num; i++) { |
| @@ -279,7 +272,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, · 42 unmodified lines | ||
| 279 | 272 | unsigned int div = 1; |
| 280 | 273 | u32 value; |
| 281 | 274 | |
| 282 | − parent = clks[core->parent]; | |
| 275 | + parent = clks[core->parent & 0xffff]; /* CLK_TYPE_PE uses high bits */ | |
| 283 | 276 | if (IS_ERR(parent)) |
| 284 | 277 | return ERR_CAST(parent); |
| 285 | 278 | |
| @@ -303,6 +296,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, · 17 unmodified lines | ||
| 303 | 296 | |
| 304 | 297 | case CLK_TYPE_GEN3_PLL1: |
| 305 | 298 | mult = cpg_pll_config->pll1_mult; |
| 299 | + div = cpg_pll_config->pll1_div; | |
| 306 | 300 | break; |
| 307 | 301 | |
| 308 | 302 | case CLK_TYPE_GEN3_PLL2: |
| @@ -320,6 +314,7 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, · 11 unmodified lines | ||
| 320 | 314 | |
| 321 | 315 | case CLK_TYPE_GEN3_PLL3: |
| 322 | 316 | mult = cpg_pll_config->pll3_mult; |
| 317 | + div = cpg_pll_config->pll3_div; | |
| 323 | 318 | break; |
| 324 | 319 | |
| 325 | 320 | case CLK_TYPE_GEN3_PLL4: |
| @@ -360,6 +355,24 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev, · 34 unmodified lines | ||
| 360 | 355 | parent = clks[cpg_clk_extalr]; |
| 361 | 356 | break; |
| 362 | 357 | |
| 358 | + case CLK_TYPE_GEN3_PE: | |
| 359 | + /* | |
| 360 | + * Peripheral clock with a fixed divider, selectable between | |
| 361 | + * clean and spread spectrum parents using MD12 | |
| 362 | + */ | |
| 363 | + if (cpg_mode & BIT(12)) { | |
| 364 | + /* Clean */ | |
| 365 | + div = core->div & 0xffff; | |
| 366 | + } else { | |
| 367 | + /* SCCG */ | |
| 368 | + parent = clks[core->parent >> 16]; | |
| 369 | + if (IS_ERR(parent)) | |
| 370 | + return ERR_CAST(parent); | |
| 371 | + div = core->div >> 16; | |
| 372 | + } | |
| 373 | + mult = 1; | |
| 374 | + break; | |
| 375 | + | |
| 363 | 376 | default: |
| 364 | 377 | return ERR_PTR(-EINVAL); |
| 365 | 378 | } |
| @@ -20,15 +20,24 @@ enum rcar_gen3_clk_types { · 19 unmodified lines | ||
| 20 | 20 | CLK_TYPE_GEN3_PLL4, |
| 21 | 21 | CLK_TYPE_GEN3_SD, |
| 22 | 22 | CLK_TYPE_GEN3_R, |
| 23 | + CLK_TYPE_GEN3_PE, | |
| 23 | 24 | }; |
| 24 | 25 | |
| 25 | 26 | #define DEF_GEN3_SD(_name, _id, _parent, _offset) \ |
| 26 | 27 | DEF_BASE(_name, _id, CLK_TYPE_GEN3_SD, _parent, .offset = _offset) |
| 27 | 28 | |
| 29 | +#define DEF_GEN3_PE(_name, _id, _parent_sscg, _div_sscg, _parent_clean, \ | |
| 30 | + _div_clean) \ | |
| 31 | + DEF_BASE(_name, _id, CLK_TYPE_GEN3_PE, \ | |
| 32 | + (_parent_sscg) << 16 | (_parent_clean), \ | |
| 33 | + .div = (_div_sscg) << 16 | (_div_clean)) | |
| 34 | + | |
| 28 | 35 | struct rcar_gen3_cpg_pll_config { |
| 29 | − unsigned int extal_div; | |
| 30 | − unsigned int pll1_mult; | |
| 31 | − unsigned int pll3_mult; | |
| 36 | + u8 extal_div; | |
| 37 | + u8 pll1_mult; | |
| 38 | + u8 pll1_div; | |
| 39 | + u8 pll3_mult; | |
| 40 | + u8 pll3_div; | |
| 32 | 41 | }; |
| 33 | 42 | |
| 34 | 43 | #define CPG_RCKCR 0x240 |
| @@ -0,0 +1,188 @@ | ||
| 1 | +/* | |
| 2 | + * Renesas R-Car USB2.0 clock selector | |
| 3 | + * | |
| 4 | + * Copyright (C) 2017 Renesas Electronics Corp. | |
| 5 | + * | |
| 6 | + * Based on renesas-cpg-mssr.c | |
| 7 | + * | |
| 8 | + * Copyright (C) 2015 Glider bvba | |
| 9 | + * | |
| 10 | + * This program is free software; you can redistribute it and/or modify | |
| 11 | + * it under the terms of the GNU General Public License as published by | |
| 12 | + * the Free Software Foundation; version 2 of the License. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#include <linux/clk.h> | |
| 16 | +#include <linux/clk-provider.h> | |
| 17 | +#include <linux/device.h> | |
| 18 | +#include <linux/init.h> | |
| 19 | +#include <linux/module.h> | |
| 20 | +#include <linux/of_device.h> | |
| 21 | +#include <linux/platform_device.h> | |
| 22 | +#include <linux/pm.h> | |
| 23 | +#include <linux/pm_runtime.h> | |
| 24 | +#include <linux/slab.h> | |
| 25 | + | |
| 26 | +#define USB20_CLKSET0 0x00 | |
| 27 | +#define CLKSET0_INTCLK_EN BIT(11) | |
| 28 | +#define CLKSET0_PRIVATE BIT(0) | |
| 29 | +#define CLKSET0_EXTAL_ONLY (CLKSET0_INTCLK_EN | CLKSET0_PRIVATE) | |
| 30 | + | |
| 31 | +struct usb2_clock_sel_priv { | |
| 32 | + void __iomem *base; | |
| 33 | + struct clk_hw hw; | |
| 34 | + bool extal; | |
| 35 | + bool xtal; | |
| 36 | +}; | |
| 37 | +#define to_priv(_hw) container_of(_hw, struct usb2_clock_sel_priv, hw) | |
| 38 | + | |
| 39 | +static void usb2_clock_sel_enable_extal_only(struct usb2_clock_sel_priv *priv) | |
| 40 | +{ | |
| 41 | + u16 val = readw(priv->base + USB20_CLKSET0); | |
| 42 | + | |
| 43 | + pr_debug("%s: enter %d %d %x\n", __func__, | |
| 44 | + priv->extal, priv->xtal, val); | |
| 45 | + | |
| 46 | + if (priv->extal && !priv->xtal && val != CLKSET0_EXTAL_ONLY) | |
| 47 | + writew(CLKSET0_EXTAL_ONLY, priv->base + USB20_CLKSET0); | |
| 48 | +} | |
| 49 | + | |
| 50 | +static void usb2_clock_sel_disable_extal_only(struct usb2_clock_sel_priv *priv) | |
| 51 | +{ | |
| 52 | + if (priv->extal && !priv->xtal) | |
| 53 | + writew(CLKSET0_PRIVATE, priv->base + USB20_CLKSET0); | |
| 54 | +} | |
| 55 | + | |
| 56 | +static int usb2_clock_sel_enable(struct clk_hw *hw) | |
| 57 | +{ | |
| 58 | + usb2_clock_sel_enable_extal_only(to_priv(hw)); | |
| 59 | + | |
| 60 | + return 0; | |
| 61 | +} | |
| 62 | + | |
| 63 | +static void usb2_clock_sel_disable(struct clk_hw *hw) | |
| 64 | +{ | |
| 65 | + usb2_clock_sel_disable_extal_only(to_priv(hw)); | |
| 66 | +} | |
| 67 | + | |
| 68 | +/* | |
| 69 | + * This module seems a mux, but this driver assumes a gate because | |
| 70 | + * ehci/ohci platform drivers don't support clk_set_parent() for now. | |
| 71 | + * If this driver acts as a gate, ehci/ohci-platform drivers don't need | |
| 72 | + * any modification. | |
| 73 | + */ | |
| 74 | +static const struct clk_ops usb2_clock_sel_clock_ops = { | |
| 75 | + .enable = usb2_clock_sel_enable, | |
| 76 | + .disable = usb2_clock_sel_disable, | |
| 77 | +}; | |
| 78 | + | |
| 79 | +static const struct of_device_id rcar_usb2_clock_sel_match[] = { | |
| 80 | + { .compatible = "renesas,rcar-gen3-usb2-clock-sel" }, | |
| 81 | + { } | |
| 82 | +}; | |
| 83 | + | |
| 84 | +static int rcar_usb2_clock_sel_suspend(struct device *dev) | |
| 85 | +{ | |
| 86 | + struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev); | |
| 87 | + | |
| 88 | + usb2_clock_sel_disable_extal_only(priv); | |
| 89 | + pm_runtime_put(dev); | |
| 90 | + | |
| 91 | + return 0; | |
| 92 | +} | |
| 93 | + | |
| 94 | +static int rcar_usb2_clock_sel_resume(struct device *dev) | |
| 95 | +{ | |
| 96 | + struct usb2_clock_sel_priv *priv = dev_get_drvdata(dev); | |
| 97 | + | |
| 98 | + pm_runtime_get_sync(dev); | |
| 99 | + usb2_clock_sel_enable_extal_only(priv); | |
| 100 | + | |
| 101 | + return 0; | |
| 102 | +} | |
| 103 | + | |
| 104 | +static int rcar_usb2_clock_sel_remove(struct platform_device *pdev) | |
| 105 | +{ | |
| 106 | + struct device *dev = &pdev->dev; | |
| 107 | + struct usb2_clock_sel_priv *priv = platform_get_drvdata(pdev); | |
| 108 | + | |
| 109 | + of_clk_del_provider(dev->of_node); | |
| 110 | + clk_hw_unregister(&priv->hw); | |
| 111 | + pm_runtime_put(dev); | |
| 112 | + pm_runtime_disable(dev); | |
| 113 | + | |
| 114 | + return 0; | |
| 115 | +} | |
| 116 | + | |
| 117 | +static int rcar_usb2_clock_sel_probe(struct platform_device *pdev) | |
| 118 | +{ | |
| 119 | + struct device *dev = &pdev->dev; | |
| 120 | + struct device_node *np = dev->of_node; | |
| 121 | + struct usb2_clock_sel_priv *priv; | |
| 122 | + struct resource *res; | |
| 123 | + struct clk *clk; | |
| 124 | + struct clk_init_data init; | |
| 125 | + | |
| 126 | + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); | |
| 127 | + if (!priv) | |
| 128 | + return -ENOMEM; | |
| 129 | + | |
| 130 | + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
| 131 | + priv->base = devm_ioremap_resource(dev, res); | |
| 132 | + if (IS_ERR(priv->base)) | |
| 133 | + return PTR_ERR(priv->base); | |
| 134 | + | |
| 135 | + pm_runtime_enable(dev); | |
| 136 | + pm_runtime_get_sync(dev); | |
| 137 | + | |
| 138 | + clk = devm_clk_get(dev, "usb_extal"); | |
| 139 | + if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { | |
| 140 | + priv->extal = !!clk_get_rate(clk); | |
| 141 | + clk_disable_unprepare(clk); | |
| 142 | + } | |
| 143 | + clk = devm_clk_get(dev, "usb_xtal"); | |
| 144 | + if (!IS_ERR(clk) && !clk_prepare_enable(clk)) { | |
| 145 | + priv->xtal = !!clk_get_rate(clk); | |
| 146 | + clk_disable_unprepare(clk); | |
| 147 | + } | |
| 148 | + | |
| 149 | + if (!priv->extal && !priv->xtal) { | |
| 150 | + dev_err(dev, "This driver needs usb_extal or usb_xtal\n"); | |
| 151 | + return -ENOENT; | |
| 152 | + } | |
| 153 | + | |
| 154 | + platform_set_drvdata(pdev, priv); | |
| 155 | + dev_set_drvdata(dev, priv); | |
| 156 | + | |
| 157 | + init.name = "rcar_usb2_clock_sel"; | |
| 158 | + init.ops = &usb2_clock_sel_clock_ops; | |
| 159 | + init.flags = 0; | |
| 160 | + init.parent_names = NULL; | |
| 161 | + init.num_parents = 0; | |
| 162 | + priv->hw.init = &init; | |
| 163 | + | |
| 164 | + clk = clk_register(NULL, &priv->hw); | |
| 165 | + if (IS_ERR(clk)) | |
| 166 | + return PTR_ERR(clk); | |
| 167 | + | |
| 168 | + return of_clk_add_hw_provider(np, of_clk_hw_simple_get, &priv->hw); | |
| 169 | +} | |
| 170 | + | |
| 171 | +static const struct dev_pm_ops rcar_usb2_clock_sel_pm_ops = { | |
| 172 | + .suspend = rcar_usb2_clock_sel_suspend, | |
| 173 | + .resume = rcar_usb2_clock_sel_resume, | |
| 174 | +}; | |
| 175 | + | |
| 176 | +static struct platform_driver rcar_usb2_clock_sel_driver = { | |
| 177 | + .driver = { | |
| 178 | + .name = "rcar-usb2-clock-sel", | |
| 179 | + .of_match_table = rcar_usb2_clock_sel_match, | |
| 180 | + .pm = &rcar_usb2_clock_sel_pm_ops, | |
| 181 | + }, | |
| 182 | + .probe = rcar_usb2_clock_sel_probe, | |
| 183 | + .remove = rcar_usb2_clock_sel_remove, | |
| 184 | +}; | |
| 185 | +builtin_platform_driver(rcar_usb2_clock_sel_driver); | |
| 186 | + | |
| 187 | +MODULE_DESCRIPTION("Renesas R-Car USB2 clock selector Driver"); | |
| 188 | +MODULE_LICENSE("GPL v2"); | |
| @@ -679,6 +679,12 @@ static const struct of_device_id cpg_mssr_match[] = { · 678 unmodified lines | ||
| 679 | 679 | .compatible = "renesas,r8a7796-cpg-mssr", |
| 680 | 680 | .data = &r8a7796_cpg_mssr_info, |
| 681 | 681 | }, |
| 682 | +#endif | |
| 683 | +#ifdef CONFIG_CLK_R8A77995 | |
| 684 | + { | |
| 685 | + .compatible = "renesas,r8a77995-cpg-mssr", | |
| 686 | + .data = &r8a77995_cpg_mssr_info, | |
| 687 | + }, | |
| 682 | 688 | #endif |
| 683 | 689 | { /* sentinel */ } |
| 684 | 690 | }; |
| @@ -138,6 +138,7 @@ extern const struct cpg_mssr_info r8a7792_cpg_mssr_info; · 137 unmodified lines | ||
| 138 | 138 | extern const struct cpg_mssr_info r8a7794_cpg_mssr_info; |
| 139 | 139 | extern const struct cpg_mssr_info r8a7795_cpg_mssr_info; |
| 140 | 140 | extern const struct cpg_mssr_info r8a7796_cpg_mssr_info; |
| 141 | +extern const struct cpg_mssr_info r8a77995_cpg_mssr_info; | |
| 141 | 142 | |
| 142 | 143 | |
| 143 | 144 | /* |
| @@ -201,7 +201,7 @@ static struct rockchip_clk_branch rk3128_uart2_fracmux __initdata = · 200 unmodified lines | ||
| 201 | 201 | MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, |
| 202 | 202 | RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); |
| 203 | 203 | |
| 204 | −static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |
| 204 | +static struct rockchip_clk_branch common_clk_branches[] __initdata = { | |
| 205 | 205 | /* |
| 206 | 206 | * Clock-Architecture Diagram 1 |
| 207 | 207 | */ |
| @@ -459,10 +459,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { · 251 unmodified lines | ||
| 459 | 459 | RK2928_CLKSEL_CON(2), 14, 2, MFLAGS, 8, 5, DFLAGS, |
| 460 | 460 | RK2928_CLKGATE_CON(10), 15, GFLAGS), |
| 461 | 461 | |
| 462 | − COMPOSITE(SCLK_SFC, "sclk_sfc", mux_sclk_sfc_src_p, 0, | |
| 463 | − RK2928_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 464 | − RK2928_CLKGATE_CON(3), 15, GFLAGS), | |
| 465 | − | |
| 466 | 462 | COMPOSITE_NOMUX(PCLK_PMU_PRE, "pclk_pmu_pre", "cpll", 0, |
| 467 | 463 | RK2928_CLKSEL_CON(29), 8, 6, DFLAGS, |
| 468 | 464 | RK2928_CLKGATE_CON(1), 0, GFLAGS), |
| @@ -495,7 +491,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { · 26 unmodified lines | ||
| 495 | 491 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), |
| 496 | 492 | GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS), |
| 497 | 493 | GATE(0, "aclk_cpu_to_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS), |
| 498 | − GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), | |
| 499 | 494 | |
| 500 | 495 | GATE(HCLK_I2S_8CH, "hclk_i2s_8ch", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), |
| 501 | 496 | GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS), |
| @@ -541,7 +536,6 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { · 39 unmodified lines | ||
| 541 | 536 | GATE(0, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS), |
| 542 | 537 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), |
| 543 | 538 | |
| 544 | − GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), | |
| 545 | 539 | GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS), |
| 546 | 540 | GATE(0, "pclk_ddrupctl", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 7, GFLAGS), |
| 547 | 541 | GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), |
| @@ -561,6 +555,21 @@ static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { · 13 unmodified lines | ||
| 561 | 555 | MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 0), |
| 562 | 556 | }; |
| 563 | 557 | |
| 558 | +static struct rockchip_clk_branch rk3126_clk_branches[] __initdata = { | |
| 559 | + GATE(0, "pclk_stimer", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS), | |
| 560 | + GATE(0, "pclk_s_efuse", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS), | |
| 561 | + GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 8, GFLAGS), | |
| 562 | +}; | |
| 563 | + | |
| 564 | +static struct rockchip_clk_branch rk3128_clk_branches[] __initdata = { | |
| 565 | + COMPOSITE(SCLK_SFC, "sclk_sfc", mux_sclk_sfc_src_p, 0, | |
| 566 | + RK2928_CLKSEL_CON(11), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 567 | + RK2928_CLKGATE_CON(3), 15, GFLAGS), | |
| 568 | + | |
| 569 | + GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), | |
| 570 | + GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), | |
| 571 | +}; | |
| 572 | + | |
| 564 | 573 | static const char *const rk3128_critical_clocks[] __initconst = { |
| 565 | 574 | "aclk_cpu", |
| 566 | 575 | "hclk_cpu", |
| @@ -570,7 +579,7 @@ static const char *const rk3128_critical_clocks[] __initconst = { · 3 unmodified lines | ||
| 570 | 579 | "pclk_peri", |
| 571 | 580 | }; |
| 572 | 581 | |
| 573 | −static void __init rk3128_clk_init(struct device_node *np) | |
| 582 | +static struct rockchip_clk_provider *__init rk3128_common_clk_init(struct device_node *np) | |
| 574 | 583 | { |
| 575 | 584 | struct rockchip_clk_provider *ctx; |
| 576 | 585 | void __iomem *reg_base; |
| @@ -578,23 +587,21 @@ static void __init rk3128_clk_init(struct device_node *np) · 1 unmodified line | ||
| 578 | 587 | reg_base = of_iomap(np, 0); |
| 579 | 588 | if (!reg_base) { |
| 580 | 589 | pr_err("%s: could not map cru region\n", __func__); |
| 581 | − return; | |
| 590 | + return ERR_PTR(-ENOMEM); | |
| 582 | 591 | } |
| 583 | 592 | |
| 584 | 593 | ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); |
| 585 | 594 | if (IS_ERR(ctx)) { |
| 586 | 595 | pr_err("%s: rockchip clk init failed\n", __func__); |
| 587 | 596 | iounmap(reg_base); |
| 588 | − return; | |
| 597 | + return ERR_PTR(-ENOMEM); | |
| 589 | 598 | } |
| 590 | 599 | |
| 591 | 600 | rockchip_clk_register_plls(ctx, rk3128_pll_clks, |
| 592 | 601 | ARRAY_SIZE(rk3128_pll_clks), |
| 593 | 602 | RK3128_GRF_SOC_STATUS0); |
| 594 | − rockchip_clk_register_branches(ctx, rk3128_clk_branches, | |
| 595 | − ARRAY_SIZE(rk3128_clk_branches)); | |
| 596 | − rockchip_clk_protect_critical(rk3128_critical_clocks, | |
| 597 | − ARRAY_SIZE(rk3128_critical_clocks)); | |
| 603 | + rockchip_clk_register_branches(ctx, common_clk_branches, | |
| 604 | + ARRAY_SIZE(common_clk_branches)); | |
| 598 | 605 | |
| 599 | 606 | rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", |
| 600 | 607 | mux_armclk_p, ARRAY_SIZE(mux_armclk_p), |
| @@ -606,6 +613,40 @@ static void __init rk3128_clk_init(struct device_node *np) · 5 unmodified lines | ||
| 606 | 613 | |
| 607 | 614 | rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); |
| 608 | 615 | |
| 616 | + return ctx; | |
| 617 | +} | |
| 618 | + | |
| 619 | +static void __init rk3126_clk_init(struct device_node *np) | |
| 620 | +{ | |
| 621 | + struct rockchip_clk_provider *ctx; | |
| 622 | + | |
| 623 | + ctx = rk3128_common_clk_init(np); | |
| 624 | + if (IS_ERR(ctx)) | |
| 625 | + return; | |
| 626 | + | |
| 627 | + rockchip_clk_register_branches(ctx, rk3126_clk_branches, | |
| 628 | + ARRAY_SIZE(rk3126_clk_branches)); | |
| 629 | + rockchip_clk_protect_critical(rk3128_critical_clocks, | |
| 630 | + ARRAY_SIZE(rk3128_critical_clocks)); | |
| 631 | + | |
| 632 | + rockchip_clk_of_add_provider(np, ctx); | |
| 633 | +} | |
| 634 | + | |
| 635 | +CLK_OF_DECLARE(rk3126_cru, "rockchip,rk3126-cru", rk3126_clk_init); | |
| 636 | + | |
| 637 | +static void __init rk3128_clk_init(struct device_node *np) | |
| 638 | +{ | |
| 639 | + struct rockchip_clk_provider *ctx; | |
| 640 | + | |
| 641 | + ctx = rk3128_common_clk_init(np); | |
| 642 | + if (IS_ERR(ctx)) | |
| 643 | + return; | |
| 644 | + | |
| 645 | + rockchip_clk_register_branches(ctx, rk3128_clk_branches, | |
| 646 | + ARRAY_SIZE(rk3128_clk_branches)); | |
| 647 | + rockchip_clk_protect_critical(rk3128_critical_clocks, | |
| 648 | + ARRAY_SIZE(rk3128_critical_clocks)); | |
| 649 | + | |
| 609 | 650 | rockchip_clk_of_add_provider(np, ctx); |
| 610 | 651 | } |
| 611 | 652 | |
| @@ -391,7 +391,7 @@ static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { · 390 unmodified lines | ||
| 391 | 391 | RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS, |
| 392 | 392 | RK2928_CLKGATE_CON(2), 11, GFLAGS), |
| 393 | 393 | |
| 394 | − COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0, | |
| 394 | + COMPOSITE_NODIV(SCLK_SDIO_SRC, "sclk_sdio_src", mux_mmc_src_p, 0, | |
| 395 | 395 | RK2928_CLKSEL_CON(11), 10, 2, MFLAGS, |
| 396 | 396 | RK2928_CLKGATE_CON(2), 13, GFLAGS), |
| 397 | 397 | DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0, |
| @@ -93,9 +93,24 @@ static struct rockchip_pll_rate_table rv1108_pll_rates[] = { · 92 unmodified lines | ||
| 93 | 93 | } |
| 94 | 94 | |
| 95 | 95 | static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = { |
| 96 | − RV1108_CPUCLK_RATE(816000000, 4), | |
| 97 | − RV1108_CPUCLK_RATE(600000000, 4), | |
| 98 | − RV1108_CPUCLK_RATE(312000000, 4), | |
| 96 | + RV1108_CPUCLK_RATE(1608000000, 7), | |
| 97 | + RV1108_CPUCLK_RATE(1512000000, 7), | |
| 98 | + RV1108_CPUCLK_RATE(1488000000, 5), | |
| 99 | + RV1108_CPUCLK_RATE(1416000000, 5), | |
| 100 | + RV1108_CPUCLK_RATE(1392000000, 5), | |
| 101 | + RV1108_CPUCLK_RATE(1296000000, 5), | |
| 102 | + RV1108_CPUCLK_RATE(1200000000, 5), | |
| 103 | + RV1108_CPUCLK_RATE(1104000000, 5), | |
| 104 | + RV1108_CPUCLK_RATE(1008000000, 5), | |
| 105 | + RV1108_CPUCLK_RATE(912000000, 5), | |
| 106 | + RV1108_CPUCLK_RATE(816000000, 3), | |
| 107 | + RV1108_CPUCLK_RATE(696000000, 3), | |
| 108 | + RV1108_CPUCLK_RATE(600000000, 3), | |
| 109 | + RV1108_CPUCLK_RATE(500000000, 3), | |
| 110 | + RV1108_CPUCLK_RATE(408000000, 1), | |
| 111 | + RV1108_CPUCLK_RATE(312000000, 1), | |
| 112 | + RV1108_CPUCLK_RATE(216000000, 1), | |
| 113 | + RV1108_CPUCLK_RATE(96000000, 1), | |
| 99 | 114 | }; |
| 100 | 115 | |
| 101 | 116 | static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { |
| @@ -105,7 +120,7 @@ static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = { · 3 unmodified lines | ||
| 105 | 120 | .mux_core_alt = 1, |
| 106 | 121 | .mux_core_main = 0, |
| 107 | 122 | .mux_core_shift = 8, |
| 108 | − .mux_core_mask = 0x1, | |
| 123 | + .mux_core_mask = 0x3, | |
| 109 | 124 | }; |
| 110 | 125 | |
| 111 | 126 | PNAME(mux_pll_p) = { "xin24m", "xin24m"}; |
| @@ -114,30 +129,42 @@ PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" }; · 2 unmodified lines | ||
| 114 | 129 | PNAME(mux_usb480m_pre_p) = { "usbphy", "xin24m" }; |
| 115 | 130 | PNAME(mux_hdmiphy_phy_p) = { "hdmiphy", "xin24m" }; |
| 116 | 131 | PNAME(mux_dclk_hdmiphy_pre_p) = { "dclk_hdmiphy_src_gpll", "dclk_hdmiphy_src_dpll" }; |
| 117 | −PNAME(mux_pll_src_4plls_p) = { "dpll", "hdmiphy", "gpll", "usb480m" }; | |
| 132 | +PNAME(mux_pll_src_4plls_p) = { "dpll", "gpll", "hdmiphy", "usb480m" }; | |
| 118 | 133 | PNAME(mux_pll_src_3plls_p) = { "apll", "gpll", "dpll" }; |
| 119 | 134 | PNAME(mux_pll_src_2plls_p) = { "dpll", "gpll" }; |
| 120 | 135 | PNAME(mux_pll_src_apll_gpll_p) = { "apll", "gpll" }; |
| 121 | −PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_dpll", "aclk_peri_src_gpll" }; | |
| 136 | +PNAME(mux_aclk_peri_src_p) = { "aclk_peri_src_gpll", "aclk_peri_src_dpll" }; | |
| 122 | 137 | PNAME(mux_aclk_bus_src_p) = { "aclk_bus_src_gpll", "aclk_bus_src_apll", "aclk_bus_src_dpll" }; |
| 123 | 138 | PNAME(mux_mmc_src_p) = { "dpll", "gpll", "xin24m", "usb480m" }; |
| 124 | 139 | PNAME(mux_pll_src_dpll_gpll_usb480m_p) = { "dpll", "gpll", "usb480m" }; |
| 125 | 140 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; |
| 126 | 141 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; |
| 127 | 142 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; |
| 128 | −PNAME(mux_sclk_macphy_p) = { "sclk_macphy_pre", "ext_gmac" }; | |
| 143 | +PNAME(mux_sclk_mac_p) = { "sclk_mac_pre", "ext_gmac" }; | |
| 129 | 144 | PNAME(mux_i2s0_pre_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" }; |
| 130 | 145 | PNAME(mux_i2s_out_p) = { "i2s0_pre", "xin12m" }; |
| 131 | −PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "xin12m" }; | |
| 132 | −PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" }; | |
| 146 | +PNAME(mux_i2s1_p) = { "i2s1_src", "i2s1_frac", "dummy", "xin12m" }; | |
| 147 | +PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "dummy", "xin12m" }; | |
| 148 | +PNAME(mux_wifi_src_p) = { "gpll", "xin24m" }; | |
| 149 | +PNAME(mux_cifout_src_p) = { "hdmiphy", "gpll" }; | |
| 150 | +PNAME(mux_cifout_p) = { "sclk_cifout_src", "xin24m" }; | |
| 151 | +PNAME(mux_sclk_cif0_src_p) = { "pclk_vip", "clk_cif0_chn_out", "pclkin_cvbs2cif" }; | |
| 152 | +PNAME(mux_sclk_cif1_src_p) = { "pclk_vip", "clk_cif1_chn_out", "pclkin_cvbs2cif" }; | |
| 153 | +PNAME(mux_sclk_cif2_src_p) = { "pclk_vip", "clk_cif2_chn_out", "pclkin_cvbs2cif" }; | |
| 154 | +PNAME(mux_sclk_cif3_src_p) = { "pclk_vip", "clk_cif3_chn_out", "pclkin_cvbs2cif" }; | |
| 155 | +PNAME(mux_dsp_src_p) = { "dpll", "gpll", "apll", "usb480m" }; | |
| 156 | +PNAME(mux_dclk_hdmiphy_p) = { "hdmiphy", "xin24m" }; | |
| 157 | +PNAME(mux_dclk_vop_p) = { "dclk_hdmiphy", "dclk_vop_src" }; | |
| 158 | +PNAME(mux_hdmi_cec_src_p) = { "dpll", "gpll", "xin24m" }; | |
| 159 | +PNAME(mux_cvbs_src_p) = { "apll", "io_cvbs_clkin", "hdmiphy", "gpll" }; | |
| 133 | 160 | |
| 134 | 161 | static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = { |
| 135 | 162 | [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0), |
| 136 | − RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates), | |
| 163 | + RV1108_PLL_CON(3), 8, 0, 0, rv1108_pll_rates), | |
| 137 | 164 | [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8), |
| 138 | − RV1108_PLL_CON(11), 8, 31, 0, NULL), | |
| 165 | + RV1108_PLL_CON(11), 8, 1, 0, NULL), | |
| 139 | 166 | [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16), |
| 140 | − RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates), | |
| 167 | + RV1108_PLL_CON(19), 8, 2, 0, rv1108_pll_rates), | |
| 141 | 168 | }; |
| 142 | 169 | |
| 143 | 170 | #define MFLAGS CLK_MUX_HIWORD_MASK |
| @@ -170,10 +197,10 @@ static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata = · 26 unmodified lines | ||
| 170 | 197 | RV1108_CLKSEL_CON(7), 12, 2, MFLAGS); |
| 171 | 198 | |
| 172 | 199 | static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { |
| 173 | − MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, | |
| 174 | − RV1108_MISC_CON, 13, 2, MFLAGS), | |
| 200 | + MUX(0, "hdmiphy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, | |
| 201 | + RV1108_MISC_CON, 13, 1, MFLAGS), | |
| 175 | 202 | MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, |
| 176 | − RV1108_MISC_CON, 15, 2, MFLAGS), | |
| 203 | + RV1108_MISC_CON, 15, 1, MFLAGS), | |
| 177 | 204 | /* |
| 178 | 205 | * Clock-Architecture Diagram 2 |
| 179 | 206 | */ |
| @@ -197,50 +224,212 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 17 unmodified lines | ||
| 197 | 224 | RV1108_CLKGATE_CON(11), 1, GFLAGS), |
| 198 | 225 | |
| 199 | 226 | /* PD_RKVENC */ |
| 227 | + COMPOSITE(0, "aclk_rkvenc_pre", mux_pll_src_4plls_p, 0, | |
| 228 | + RV1108_CLKSEL_CON(37), 6, 2, MFLAGS, 0, 5, DFLAGS, | |
| 229 | + RV1108_CLKGATE_CON(8), 8, GFLAGS), | |
| 230 | + FACTOR_GATE(0, "hclk_rkvenc_pre", "aclk_rkvenc_pre", 0, 1, 4, | |
| 231 | + RV1108_CLKGATE_CON(8), 10, GFLAGS), | |
| 232 | + COMPOSITE(SCLK_VENC_CORE, "clk_venc_core", mux_pll_src_4plls_p, 0, | |
| 233 | + RV1108_CLKSEL_CON(37), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 234 | + RV1108_CLKGATE_CON(8), 9, GFLAGS), | |
| 235 | + GATE(ACLK_RKVENC, "aclk_rkvenc", "aclk_rkvenc_pre", 0, | |
| 236 | + RV1108_CLKGATE_CON(19), 8, GFLAGS), | |
| 237 | + GATE(HCLK_RKVENC, "hclk_rkvenc", "hclk_rkvenc_pre", 0, | |
| 238 | + RV1108_CLKGATE_CON(19), 9, GFLAGS), | |
| 239 | + GATE(0, "aclk_rkvenc_niu", "aclk_rkvenc_pre", CLK_IGNORE_UNUSED, | |
| 240 | + RV1108_CLKGATE_CON(19), 11, GFLAGS), | |
| 241 | + GATE(0, "hclk_rkvenc_niu", "hclk_rkvenc_pre", CLK_IGNORE_UNUSED, | |
| 242 | + RV1108_CLKGATE_CON(19), 10, GFLAGS), | |
| 200 | 243 | |
| 201 | 244 | /* PD_RKVDEC */ |
| 245 | + COMPOSITE(SCLK_HEVC_CORE, "sclk_hevc_core", mux_pll_src_4plls_p, 0, | |
| 246 | + RV1108_CLKSEL_CON(36), 6, 2, MFLAGS, 0, 5, DFLAGS, | |
| 247 | + RV1108_CLKGATE_CON(8), 2, GFLAGS), | |
| 248 | + FACTOR_GATE(0, "hclk_rkvdec_pre", "sclk_hevc_core", 0, 1, 4, | |
| 249 | + RV1108_CLKGATE_CON(8), 10, GFLAGS), | |
| 250 | + COMPOSITE(SCLK_HEVC_CABAC, "clk_hevc_cabac", mux_pll_src_4plls_p, 0, | |
| 251 | + RV1108_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 252 | + RV1108_CLKGATE_CON(8), 1, GFLAGS), | |
| 253 | + | |
| 254 | + COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0, | |
| 255 | + RV1108_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, | |
| 256 | + RV1108_CLKGATE_CON(8), 0, GFLAGS), | |
| 257 | + COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0, | |
| 258 | + RV1108_CLKSEL_CON(36), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 259 | + RV1108_CLKGATE_CON(8), 3, GFLAGS), | |
| 260 | + GATE(ACLK_RKVDEC, "aclk_rkvdec", "aclk_rkvdec_pre", 0, | |
| 261 | + RV1108_CLKGATE_CON(19), 0, GFLAGS), | |
| 262 | + GATE(ACLK_VPU, "aclk_vpu", "aclk_vpu_pre", 0, | |
| 263 | + RV1108_CLKGATE_CON(19), 1, GFLAGS), | |
| 264 | + GATE(HCLK_RKVDEC, "hclk_rkvdec", "hclk_rkvdec_pre", 0, | |
| 265 | + RV1108_CLKGATE_CON(19), 2, GFLAGS), | |
| 266 | + GATE(HCLK_VPU, "hclk_vpu", "hclk_rkvdec_pre", 0, | |
| 267 | + RV1108_CLKGATE_CON(19), 3, GFLAGS), | |
| 268 | + GATE(0, "aclk_rkvdec_niu", "aclk_rkvdec_pre", CLK_IGNORE_UNUSED, | |
| 269 | + RV1108_CLKGATE_CON(19), 4, GFLAGS), | |
| 270 | + GATE(0, "hclk_rkvdec_niu", "hclk_rkvdec_pre", CLK_IGNORE_UNUSED, | |
| 271 | + RV1108_CLKGATE_CON(19), 5, GFLAGS), | |
| 272 | + GATE(0, "aclk_vpu_niu", "aclk_vpu_pre", CLK_IGNORE_UNUSED, | |
| 273 | + RV1108_CLKGATE_CON(19), 6, GFLAGS), | |
| 202 | 274 | |
| 203 | 275 | /* PD_PMU_wrapper */ |
| 204 | 276 | COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED, |
| 205 | 277 | RV1108_CLKSEL_CON(38), 0, 5, DFLAGS, |
| 206 | 278 | RV1108_CLKGATE_CON(8), 12, GFLAGS), |
| 207 | − GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 279 | + GATE(0, "pclk_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 208 | 280 | RV1108_CLKGATE_CON(10), 0, GFLAGS), |
| 209 | − GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 281 | + GATE(0, "pclk_intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 210 | 282 | RV1108_CLKGATE_CON(10), 1, GFLAGS), |
| 211 | − GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 283 | + GATE(PCLK_GPIO0_PMU, "pclk_gpio0_pmu", "pmu_24m_ena", 0, | |
| 212 | 284 | RV1108_CLKGATE_CON(10), 2, GFLAGS), |
| 213 | − GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 285 | + GATE(0, "pclk_pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 214 | 286 | RV1108_CLKGATE_CON(10), 3, GFLAGS), |
| 215 | − GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 287 | + GATE(0, "pclk_pmu_niu", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 216 | 288 | RV1108_CLKGATE_CON(10), 4, GFLAGS), |
| 217 | − GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 289 | + GATE(PCLK_I2C0_PMU, "pclk_i2c0_pmu", "pmu_24m_ena", 0, | |
| 218 | 290 | RV1108_CLKGATE_CON(10), 5, GFLAGS), |
| 219 | − GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED, | |
| 291 | + GATE(PCLK_PWM0_PMU, "pclk_pwm0_pmu", "pmu_24m_ena", 0, | |
| 220 | 292 | RV1108_CLKGATE_CON(10), 6, GFLAGS), |
| 221 | − COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 293 | + COMPOSITE(SCLK_PWM0_PMU, "sclk_pwm0_pmu", mux_pll_src_2plls_p, 0, | |
| 222 | 294 | RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 223 | 295 | RV1108_CLKGATE_CON(8), 15, GFLAGS), |
| 224 | − COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 296 | + COMPOSITE(SCLK_I2C0_PMU, "sclk_i2c0_pmu", mux_pll_src_2plls_p, 0, | |
| 225 | 297 | RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS, |
| 226 | 298 | RV1108_CLKGATE_CON(8), 14, GFLAGS), |
| 227 | 299 | GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED, |
| 228 | 300 | RV1108_CLKGATE_CON(8), 13, GFLAGS), |
| 229 | 301 | |
| 302 | + /* | |
| 303 | + * Clock-Architecture Diagram 3 | |
| 304 | + */ | |
| 305 | + COMPOSITE(SCLK_WIFI, "sclk_wifi", mux_wifi_src_p, 0, | |
| 306 | + RV1108_CLKSEL_CON(28), 15, 1, MFLAGS, 8, 6, DFLAGS, | |
| 307 | + RV1108_CLKGATE_CON(9), 8, GFLAGS), | |
| 308 | + COMPOSITE_NODIV(0, "sclk_cifout_src", mux_cifout_src_p, 0, | |
| 309 | + RV1108_CLKSEL_CON(40), 8, 1, MFLAGS, | |
| 310 | + RV1108_CLKGATE_CON(9), 11, GFLAGS), | |
| 311 | + COMPOSITE_NOGATE(SCLK_CIFOUT, "sclk_cifout", mux_cifout_p, 0, | |
| 312 | + RV1108_CLKSEL_CON(40), 12, 1, MFLAGS, 0, 5, DFLAGS), | |
| 313 | + COMPOSITE_NOMUX(SCLK_MIPI_CSI_OUT, "sclk_mipi_csi_out", "xin24m", 0, | |
| 314 | + RV1108_CLKSEL_CON(41), 0, 5, DFLAGS, | |
| 315 | + RV1108_CLKGATE_CON(9), 12, GFLAGS), | |
| 316 | + | |
| 317 | + GATE(0, "pclk_acodecphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | |
| 318 | + RV1108_CLKGATE_CON(14), 6, GFLAGS), | |
| 319 | + GATE(0, "pclk_usbgrf", "pclk_top_pre", CLK_IGNORE_UNUSED, | |
| 320 | + RV1108_CLKGATE_CON(14), 14, GFLAGS), | |
| 321 | + | |
| 322 | + GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio1_pre", 0, | |
| 323 | + RV1108_CLKGATE_CON(18), 10, GFLAGS), | |
| 324 | + GATE(HCLK_CIF0, "hclk_cif0", "hclk_vio_pre", 0, | |
| 325 | + RV1108_CLKGATE_CON(18), 10, GFLAGS), | |
| 326 | + COMPOSITE_NODIV(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_src_p, 0, | |
| 327 | + RV1108_CLKSEL_CON(31), 0, 2, MFLAGS, | |
| 328 | + RV1108_CLKGATE_CON(7), 9, GFLAGS), | |
| 329 | + GATE(ACLK_CIF1, "aclk_cif1", "aclk_vio1_pre", 0, | |
| 330 | + RV1108_CLKGATE_CON(17), 6, GFLAGS), | |
| 331 | + GATE(HCLK_CIF1, "hclk_cif1", "hclk_vio_pre", 0, | |
| 332 | + RV1108_CLKGATE_CON(17), 7, GFLAGS), | |
| 333 | + COMPOSITE_NODIV(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_src_p, 0, | |
| 334 | + RV1108_CLKSEL_CON(31), 2, 2, MFLAGS, | |
| 335 | + RV1108_CLKGATE_CON(7), 10, GFLAGS), | |
| 336 | + GATE(ACLK_CIF2, "aclk_cif2", "aclk_vio1_pre", 0, | |
| 337 | + RV1108_CLKGATE_CON(17), 8, GFLAGS), | |
| 338 | + GATE(HCLK_CIF2, "hclk_cif2", "hclk_vio_pre", 0, | |
| 339 | + RV1108_CLKGATE_CON(17), 9, GFLAGS), | |
| 340 | + COMPOSITE_NODIV(SCLK_CIF2, "sclk_cif2", mux_sclk_cif2_src_p, 0, | |
| 341 | + RV1108_CLKSEL_CON(31), 4, 2, MFLAGS, | |
| 342 | + RV1108_CLKGATE_CON(7), 11, GFLAGS), | |
| 343 | + GATE(ACLK_CIF3, "aclk_cif3", "aclk_vio1_pre", 0, | |
| 344 | + RV1108_CLKGATE_CON(17), 10, GFLAGS), | |
| 345 | + GATE(HCLK_CIF3, "hclk_cif3", "hclk_vio_pre", 0, | |
| 346 | + RV1108_CLKGATE_CON(17), 11, GFLAGS), | |
| 347 | + COMPOSITE_NODIV(SCLK_CIF3, "sclk_cif3", mux_sclk_cif3_src_p, 0, | |
| 348 | + RV1108_CLKSEL_CON(31), 6, 2, MFLAGS, | |
| 349 | + RV1108_CLKGATE_CON(7), 12, GFLAGS), | |
| 350 | + GATE(0, "pclk_cif1to4", "pclk_vip", CLK_IGNORE_UNUSED, | |
| 351 | + RV1108_CLKGATE_CON(7), 8, GFLAGS), | |
| 352 | + | |
| 353 | + /* PD_DSP_wrapper */ | |
| 354 | + COMPOSITE(SCLK_DSP, "sclk_dsp", mux_dsp_src_p, 0, | |
| 355 | + RV1108_CLKSEL_CON(42), 8, 2, MFLAGS, 0, 5, DFLAGS, | |
| 356 | + RV1108_CLKGATE_CON(9), 0, GFLAGS), | |
| 357 | + GATE(0, "clk_dsp_sys_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 358 | + RV1108_CLKGATE_CON(16), 0, GFLAGS), | |
| 359 | + GATE(0, "clk_dsp_epp_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 360 | + RV1108_CLKGATE_CON(16), 1, GFLAGS), | |
| 361 | + GATE(0, "clk_dsp_edp_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 362 | + RV1108_CLKGATE_CON(16), 2, GFLAGS), | |
| 363 | + GATE(0, "clk_dsp_iop_wd", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 364 | + RV1108_CLKGATE_CON(16), 3, GFLAGS), | |
| 365 | + GATE(0, "clk_dsp_free", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 366 | + RV1108_CLKGATE_CON(16), 13, GFLAGS), | |
| 367 | + COMPOSITE_NOMUX(SCLK_DSP_IOP, "sclk_dsp_iop", "sclk_dsp", 0, | |
| 368 | + RV1108_CLKSEL_CON(44), 0, 5, DFLAGS, | |
| 369 | + RV1108_CLKGATE_CON(9), 1, GFLAGS), | |
| 370 | + COMPOSITE_NOMUX(SCLK_DSP_EPP, "sclk_dsp_epp", "sclk_dsp", 0, | |
| 371 | + RV1108_CLKSEL_CON(44), 8, 5, DFLAGS, | |
| 372 | + RV1108_CLKGATE_CON(9), 2, GFLAGS), | |
| 373 | + COMPOSITE_NOMUX(SCLK_DSP_EDP, "sclk_dsp_edp", "sclk_dsp", 0, | |
| 374 | + RV1108_CLKSEL_CON(45), 0, 5, DFLAGS, | |
| 375 | + RV1108_CLKGATE_CON(9), 3, GFLAGS), | |
| 376 | + COMPOSITE_NOMUX(SCLK_DSP_EDAP, "sclk_dsp_edap", "sclk_dsp", 0, | |
| 377 | + RV1108_CLKSEL_CON(45), 8, 5, DFLAGS, | |
| 378 | + RV1108_CLKGATE_CON(9), 4, GFLAGS), | |
| 379 | + GATE(0, "pclk_dsp_iop_niu", "sclk_dsp_iop", CLK_IGNORE_UNUSED, | |
| 380 | + RV1108_CLKGATE_CON(16), 4, GFLAGS), | |
| 381 | + GATE(0, "aclk_dsp_epp_niu", "sclk_dsp_epp", CLK_IGNORE_UNUSED, | |
| 382 | + RV1108_CLKGATE_CON(16), 5, GFLAGS), | |
| 383 | + GATE(0, "aclk_dsp_edp_niu", "sclk_dsp_edp", CLK_IGNORE_UNUSED, | |
| 384 | + RV1108_CLKGATE_CON(16), 6, GFLAGS), | |
| 385 | + GATE(0, "pclk_dsp_dbg_niu", "sclk_dsp", CLK_IGNORE_UNUSED, | |
| 386 | + RV1108_CLKGATE_CON(16), 7, GFLAGS), | |
| 387 | + GATE(0, "aclk_dsp_edap_niu", "sclk_dsp_edap", CLK_IGNORE_UNUSED, | |
| 388 | + RV1108_CLKGATE_CON(16), 14, GFLAGS), | |
| 389 | + COMPOSITE_NOMUX(SCLK_DSP_PFM, "sclk_dsp_pfm", "sclk_dsp", 0, | |
| 390 | + RV1108_CLKSEL_CON(43), 0, 5, DFLAGS, | |
| 391 | + RV1108_CLKGATE_CON(9), 5, GFLAGS), | |
| 392 | + COMPOSITE_NOMUX(PCLK_DSP_CFG, "pclk_dsp_cfg", "sclk_dsp", 0, | |
| 393 | + RV1108_CLKSEL_CON(43), 8, 5, DFLAGS, | |
| 394 | + RV1108_CLKGATE_CON(9), 6, GFLAGS), | |
| 395 | + GATE(0, "pclk_dsp_cfg_niu", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | |
| 396 | + RV1108_CLKGATE_CON(16), 8, GFLAGS), | |
| 397 | + GATE(0, "pclk_dsp_pfm_mon", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | |
| 398 | + RV1108_CLKGATE_CON(16), 9, GFLAGS), | |
| 399 | + GATE(0, "pclk_intc", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | |
| 400 | + RV1108_CLKGATE_CON(16), 10, GFLAGS), | |
| 401 | + GATE(0, "pclk_dsp_grf", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | |
| 402 | + RV1108_CLKGATE_CON(16), 11, GFLAGS), | |
| 403 | + GATE(0, "pclk_mailbox", "pclk_dsp_cfg", CLK_IGNORE_UNUSED, | |
| 404 | + RV1108_CLKGATE_CON(16), 12, GFLAGS), | |
| 405 | + GATE(0, "aclk_dsp_epp_perf", "sclk_dsp_epp", CLK_IGNORE_UNUSED, | |
| 406 | + RV1108_CLKGATE_CON(16), 15, GFLAGS), | |
| 407 | + GATE(0, "aclk_dsp_edp_perf", "sclk_dsp_edp", CLK_IGNORE_UNUSED, | |
| 408 | + RV1108_CLKGATE_CON(11), 8, GFLAGS), | |
| 409 | + | |
| 230 | 410 | /* |
| 231 | 411 | * Clock-Architecture Diagram 4 |
| 232 | 412 | */ |
| 233 | − COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, | |
| 413 | + COMPOSITE(0, "aclk_vio0_pre", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, | |
| 234 | 414 | RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS, |
| 235 | 415 | RV1108_CLKGATE_CON(6), 0, GFLAGS), |
| 236 | − GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED, | |
| 416 | + GATE(ACLK_VIO0, "aclk_vio0", "aclk_vio0_pre", 0, | |
| 237 | 417 | RV1108_CLKGATE_CON(17), 0, GFLAGS), |
| 238 | 418 | COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0, |
| 239 | 419 | RV1108_CLKSEL_CON(29), 0, 5, DFLAGS, |
| 240 | 420 | RV1108_CLKGATE_CON(7), 2, GFLAGS), |
| 421 | + GATE(HCLK_VIO, "hclk_vio", "hclk_vio_pre", 0, | |
| 422 | + RV1108_CLKGATE_CON(17), 2, GFLAGS), | |
| 241 | 423 | COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0, |
| 242 | 424 | RV1108_CLKSEL_CON(29), 8, 5, DFLAGS, |
| 243 | 425 | RV1108_CLKGATE_CON(7), 3, GFLAGS), |
| 426 | + GATE(PCLK_VIO, "pclk_vio", "pclk_vio_pre", 0, | |
| 427 | + RV1108_CLKGATE_CON(17), 3, GFLAGS), | |
| 428 | + COMPOSITE(0, "aclk_vio1_pre", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED, | |
| 429 | + RV1108_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 430 | + RV1108_CLKGATE_CON(6), 1, GFLAGS), | |
| 431 | + GATE(ACLK_VIO1, "aclk_vio1", "aclk_vio1_pre", 0, | |
| 432 | + RV1108_CLKGATE_CON(17), 1, GFLAGS), | |
| 244 | 433 | |
| 245 | 434 | INVERTER(0, "pclk_vip", "ext_vip", |
| 246 | 435 | RV1108_CLKSEL_CON(31), 8, IFLAGS), |
| @@ -252,8 +441,63 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 5 unmodified lines | ||
| 252 | 441 | RV1108_CLKGATE_CON(6), 5, GFLAGS), |
| 253 | 442 | GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED, |
| 254 | 443 | RV1108_CLKGATE_CON(6), 4, GFLAGS), |
| 255 | − COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0, | |
| 256 | − RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS), | |
| 444 | + COMPOSITE_NOGATE(0, "dclk_hdmiphy_pre", mux_dclk_hdmiphy_pre_p, 0, | |
| 445 | + RV1108_CLKSEL_CON(32), 6, 1, MFLAGS, 8, 6, DFLAGS), | |
| 446 | + COMPOSITE_NOGATE(DCLK_VOP_SRC, "dclk_vop_src", mux_dclk_hdmiphy_pre_p, 0, | |
| 447 | + RV1108_CLKSEL_CON(32), 6, 1, MFLAGS, 0, 6, DFLAGS), | |
| 448 | + MUX(DCLK_HDMIPHY, "dclk_hdmiphy", mux_dclk_hdmiphy_p, CLK_SET_RATE_PARENT, | |
| 449 | + RV1108_CLKSEL_CON(32), 15, 1, MFLAGS), | |
| 450 | + MUX(DCLK_VOP, "dclk_vop", mux_dclk_vop_p, CLK_SET_RATE_PARENT, | |
| 451 | + RV1108_CLKSEL_CON(32), 7, 1, MFLAGS), | |
| 452 | + GATE(ACLK_VOP, "aclk_vop", "aclk_vio0_pre", 0, | |
| 453 | + RV1108_CLKGATE_CON(18), 0, GFLAGS), | |
| 454 | + GATE(HCLK_VOP, "hclk_vop", "hclk_vio_pre", 0, | |
| 455 | + RV1108_CLKGATE_CON(18), 1, GFLAGS), | |
| 456 | + GATE(ACLK_IEP, "aclk_iep", "aclk_vio0_pre", 0, | |
| 457 | + RV1108_CLKGATE_CON(18), 2, GFLAGS), | |
| 458 | + GATE(HCLK_IEP, "hclk_iep", "hclk_vio_pre", 0, | |
| 459 | + RV1108_CLKGATE_CON(18), 3, GFLAGS), | |
| 460 | + | |
| 461 | + GATE(ACLK_RGA, "aclk_rga", "aclk_vio1_pre", 0, | |
| 462 | + RV1108_CLKGATE_CON(18), 4, GFLAGS), | |
| 463 | + GATE(HCLK_RGA, "hclk_rga", "hclk_vio_pre", 0, | |
| 464 | + RV1108_CLKGATE_CON(18), 5, GFLAGS), | |
| 465 | + COMPOSITE(SCLK_RGA, "sclk_rga", mux_pll_src_4plls_p, 0, | |
| 466 | + RV1108_CLKSEL_CON(33), 6, 2, MFLAGS, 0, 5, DFLAGS, | |
| 467 | + RV1108_CLKGATE_CON(6), 6, GFLAGS), | |
| 468 | + | |
| 469 | + COMPOSITE(SCLK_CVBS_HOST, "sclk_cvbs_host", mux_cvbs_src_p, 0, | |
| 470 | + RV1108_CLKSEL_CON(33), 13, 2, MFLAGS, 8, 5, DFLAGS, | |
| 471 | + RV1108_CLKGATE_CON(6), 7, GFLAGS), | |
| 472 | + FACTOR(0, "sclk_cvbs_27m", "sclk_cvbs_host", 0, 1, 2), | |
| 473 | + | |
| 474 | + GATE(SCLK_HDMI_SFR, "sclk_hdmi_sfr", "xin24m", 0, | |
| 475 | + RV1108_CLKGATE_CON(6), 8, GFLAGS), | |
| 476 | + | |
| 477 | + COMPOSITE(SCLK_HDMI_CEC, "sclk_hdmi_cec", mux_hdmi_cec_src_p, 0, | |
| 478 | + RV1108_CLKSEL_CON(34), 14, 2, MFLAGS, 0, 14, DFLAGS, | |
| 479 | + RV1108_CLKGATE_CON(6), 9, GFLAGS), | |
| 480 | + GATE(PCLK_MIPI_DSI, "pclk_mipi_dsi", "pclk_vio_pre", 0, | |
| 481 | + RV1108_CLKGATE_CON(18), 8, GFLAGS), | |
| 482 | + GATE(PCLK_HDMI_CTRL, "pclk_hdmi_ctrl", "pclk_vio_pre", 0, | |
| 483 | + RV1108_CLKGATE_CON(18), 9, GFLAGS), | |
| 484 | + | |
| 485 | + GATE(ACLK_ISP, "aclk_isp", "aclk_vio1_pre", 0, | |
| 486 | + RV1108_CLKGATE_CON(18), 12, GFLAGS), | |
| 487 | + GATE(HCLK_ISP, "hclk_isp", "hclk_vio_pre", 0, | |
| 488 | + RV1108_CLKGATE_CON(18), 11, GFLAGS), | |
| 489 | + COMPOSITE(SCLK_ISP, "sclk_isp", mux_pll_src_4plls_p, 0, | |
| 490 | + RV1108_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 491 | + RV1108_CLKGATE_CON(6), 3, GFLAGS), | |
| 492 | + | |
| 493 | + GATE(0, "clk_dsiphy24m", "xin24m", CLK_IGNORE_UNUSED, | |
| 494 | + RV1108_CLKGATE_CON(9), 10, GFLAGS), | |
| 495 | + GATE(0, "pclk_vdacphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | |
| 496 | + RV1108_CLKGATE_CON(14), 9, GFLAGS), | |
| 497 | + GATE(0, "pclk_mipi_dsiphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | |
| 498 | + RV1108_CLKGATE_CON(14), 11, GFLAGS), | |
| 499 | + GATE(0, "pclk_mipi_csiphy", "pclk_top_pre", CLK_IGNORE_UNUSED, | |
| 500 | + RV1108_CLKGATE_CON(14), 12, GFLAGS), | |
| 257 | 501 | |
| 258 | 502 | /* |
| 259 | 503 | * Clock-Architecture Diagram 5 |
| @@ -261,10 +505,11 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 1 unmodified line | ||
| 261 | 505 | |
| 262 | 506 | FACTOR(0, "xin12m", "xin24m", 0, 1, 2), |
| 263 | 507 | |
| 264 | − COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0, | |
| 508 | + | |
| 509 | + COMPOSITE(SCLK_I2S0_SRC, "i2s0_src", mux_pll_src_2plls_p, 0, | |
| 265 | 510 | RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 266 | 511 | RV1108_CLKGATE_CON(2), 0, GFLAGS), |
| 267 | − COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, | |
| 512 | + COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT, | |
| 268 | 513 | RV1108_CLKSEL_CON(8), 0, |
| 269 | 514 | RV1108_CLKGATE_CON(2), 1, GFLAGS, |
| 270 | 515 | &rv1108_i2s0_fracmux), |
| @@ -274,7 +519,7 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 3 unmodified lines | ||
| 274 | 519 | RV1108_CLKSEL_CON(5), 15, 1, MFLAGS, |
| 275 | 520 | RV1108_CLKGATE_CON(2), 3, GFLAGS), |
| 276 | 521 | |
| 277 | − COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0, | |
| 522 | + COMPOSITE(SCLK_I2S1_SRC, "i2s1_src", mux_pll_src_2plls_p, 0, | |
| 278 | 523 | RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 279 | 524 | RV1108_CLKGATE_CON(2), 4, GFLAGS), |
| 280 | 525 | COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT, |
| @@ -284,7 +529,7 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 3 unmodified lines | ||
| 284 | 529 | GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT, |
| 285 | 530 | RV1108_CLKGATE_CON(2), 6, GFLAGS), |
| 286 | 531 | |
| 287 | − COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0, | |
| 532 | + COMPOSITE(SCLK_I2S2_SRC, "i2s2_src", mux_pll_src_2plls_p, 0, | |
| 288 | 533 | RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS, |
| 289 | 534 | RV1108_CLKGATE_CON(3), 8, GFLAGS), |
| 290 | 535 | COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT, |
| @@ -303,32 +548,53 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 12 unmodified lines | ||
| 303 | 548 | RV1108_CLKGATE_CON(1), 2, GFLAGS), |
| 304 | 549 | COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0, |
| 305 | 550 | RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS), |
| 306 | − COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0, | |
| 551 | + COMPOSITE_NOMUX(HCLK_BUS, "hclk_bus_pre", "aclk_bus_pre", 0, | |
| 307 | 552 | RV1108_CLKSEL_CON(3), 0, 5, DFLAGS, |
| 308 | 553 | RV1108_CLKGATE_CON(1), 4, GFLAGS), |
| 309 | − COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0, | |
| 554 | + COMPOSITE_NOMUX(0, "pclk_bus_pre", "aclk_bus_pre", 0, | |
| 310 | 555 | RV1108_CLKSEL_CON(3), 8, 5, DFLAGS, |
| 311 | 556 | RV1108_CLKGATE_CON(1), 5, GFLAGS), |
| 312 | − GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED, | |
| 557 | + GATE(PCLK_BUS, "pclk_bus", "pclk_bus_pre", 0, | |
| 313 | 558 | RV1108_CLKGATE_CON(1), 6, GFLAGS), |
| 314 | − GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED, | |
| 559 | + GATE(0, "pclk_top_pre", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 315 | 560 | RV1108_CLKGATE_CON(1), 7, GFLAGS), |
| 316 | − GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED, | |
| 561 | + GATE(0, "pclk_ddr_pre", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 317 | 562 | RV1108_CLKGATE_CON(1), 8, GFLAGS), |
| 318 | − GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED, | |
| 563 | + GATE(SCLK_TIMER0, "clk_timer0", "xin24m", 0, | |
| 319 | 564 | RV1108_CLKGATE_CON(1), 9, GFLAGS), |
| 320 | − GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED, | |
| 565 | + GATE(SCLK_TIMER1, "clk_timer1", "xin24m", CLK_IGNORE_UNUSED, | |
| 321 | 566 | RV1108_CLKGATE_CON(1), 10, GFLAGS), |
| 322 | − GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 567 | + GATE(PCLK_TIMER, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 323 | 568 | RV1108_CLKGATE_CON(13), 4, GFLAGS), |
| 324 | 569 | |
| 325 | − COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 570 | + GATE(HCLK_I2S0_8CH, "hclk_i2s0_8ch", "hclk_bus_pre", 0, | |
| 571 | + RV1108_CLKGATE_CON(12), 7, GFLAGS), | |
| 572 | + GATE(HCLK_I2S1_2CH, "hclk_i2s1_2ch", "hclk_bus_pre", 0, | |
| 573 | + RV1108_CLKGATE_CON(12), 8, GFLAGS), | |
| 574 | + GATE(HCLK_I2S2_2CH, "hclk_i2s2_2ch", "hclk_bus_pre", 0, | |
| 575 | + RV1108_CLKGATE_CON(12), 9, GFLAGS), | |
| 576 | + | |
| 577 | + GATE(HCLK_CRYPTO_MST, "hclk_crypto_mst", "hclk_bus_pre", 0, | |
| 578 | + RV1108_CLKGATE_CON(12), 10, GFLAGS), | |
| 579 | + GATE(HCLK_CRYPTO_SLV, "hclk_crypto_slv", "hclk_bus_pre", 0, | |
| 580 | + RV1108_CLKGATE_CON(12), 11, GFLAGS), | |
| 581 | + COMPOSITE(SCLK_CRYPTO, "sclk_crypto", mux_pll_src_2plls_p, 0, | |
| 582 | + RV1108_CLKSEL_CON(11), 7, 1, MFLAGS, 0, 5, DFLAGS, | |
| 583 | + RV1108_CLKGATE_CON(2), 12, GFLAGS), | |
| 584 | + | |
| 585 | + COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_2plls_p, 0, | |
| 586 | + RV1108_CLKSEL_CON(11), 15, 1, MFLAGS, 8, 5, DFLAGS, | |
| 587 | + RV1108_CLKGATE_CON(3), 0, GFLAGS), | |
| 588 | + GATE(PCLK_SPI, "pclk_spi", "pclk_bus_pre", 0, | |
| 589 | + RV1108_CLKGATE_CON(13), 5, GFLAGS), | |
| 590 | + | |
| 591 | + COMPOSITE(SCLK_UART0_SRC, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 326 | 592 | RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 327 | 593 | RV1108_CLKGATE_CON(3), 1, GFLAGS), |
| 328 | − COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 594 | + COMPOSITE(SCLK_UART1_SRC, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 329 | 595 | RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 330 | 596 | RV1108_CLKGATE_CON(3), 3, GFLAGS), |
| 331 | − COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 597 | + COMPOSITE(SCLK_UART2_SRC, "uart2_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED, | |
| 332 | 598 | RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS, |
| 333 | 599 | RV1108_CLKGATE_CON(3), 5, GFLAGS), |
| 334 | 600 | |
| @@ -344,44 +610,58 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 9 unmodified lines | ||
| 344 | 610 | RV1108_CLKSEL_CON(18), 0, |
| 345 | 611 | RV1108_CLKGATE_CON(3), 6, GFLAGS, |
| 346 | 612 | &rv1108_uart2_fracmux), |
| 347 | − GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 613 | + GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", 0, | |
| 348 | 614 | RV1108_CLKGATE_CON(13), 10, GFLAGS), |
| 349 | − GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 615 | + GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", 0, | |
| 350 | 616 | RV1108_CLKGATE_CON(13), 11, GFLAGS), |
| 351 | − GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 617 | + GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", 0, | |
| 352 | 618 | RV1108_CLKGATE_CON(13), 12, GFLAGS), |
| 353 | 619 | |
| 354 | − COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 355 | − RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS, | |
| 620 | + COMPOSITE(SCLK_I2C1, "clk_i2c1", mux_pll_src_2plls_p, 0, | |
| 621 | + RV1108_CLKSEL_CON(19), 15, 1, MFLAGS, 8, 7, DFLAGS, | |
| 356 | 622 | RV1108_CLKGATE_CON(3), 7, GFLAGS), |
| 357 | − COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 358 | − RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS, | |
| 623 | + COMPOSITE(SCLK_I2C2, "clk_i2c2", mux_pll_src_2plls_p, 0, | |
| 624 | + RV1108_CLKSEL_CON(20), 7, 1, MFLAGS, 0, 7, DFLAGS, | |
| 359 | 625 | RV1108_CLKGATE_CON(3), 8, GFLAGS), |
| 360 | − COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 361 | − RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS, | |
| 626 | + COMPOSITE(SCLK_I2C3, "clk_i2c3", mux_pll_src_2plls_p, 0, | |
| 627 | + RV1108_CLKSEL_CON(20), 15, 1, MFLAGS, 8, 7, DFLAGS, | |
| 362 | 628 | RV1108_CLKGATE_CON(3), 9, GFLAGS), |
| 363 | − GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 629 | + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_bus_pre", 0, | |
| 364 | 630 | RV1108_CLKGATE_CON(13), 0, GFLAGS), |
| 365 | − GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 631 | + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_bus_pre", 0, | |
| 366 | 632 | RV1108_CLKGATE_CON(13), 1, GFLAGS), |
| 367 | − GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 633 | + GATE(PCLK_I2C3, "pclk_i2c3", "pclk_bus_pre", 0, | |
| 368 | 634 | RV1108_CLKGATE_CON(13), 2, GFLAGS), |
| 369 | − COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED, | |
| 635 | + COMPOSITE(SCLK_PWM, "clk_pwm", mux_pll_src_2plls_p, 0, | |
| 370 | 636 | RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS, |
| 371 | 637 | RV1108_CLKGATE_CON(3), 10, GFLAGS), |
| 372 | − GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 638 | + GATE(PCLK_PWM, "pclk_pwm", "pclk_bus_pre", 0, | |
| 373 | 639 | RV1108_CLKGATE_CON(13), 6, GFLAGS), |
| 374 | − GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 640 | + GATE(PCLK_WDT, "pclk_wdt", "pclk_bus_pre", 0, | |
| 375 | 641 | RV1108_CLKGATE_CON(13), 3, GFLAGS), |
| 376 | − GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 642 | + GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_bus_pre", 0, | |
| 377 | 643 | RV1108_CLKGATE_CON(13), 7, GFLAGS), |
| 378 | − GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 644 | + GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_bus_pre", 0, | |
| 379 | 645 | RV1108_CLKGATE_CON(13), 8, GFLAGS), |
| 380 | − GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED, | |
| 646 | + GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_bus_pre", 0, | |
| 381 | 647 | RV1108_CLKGATE_CON(13), 9, GFLAGS), |
| 382 | 648 | |
| 383 | 649 | GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED, |
| 384 | 650 | RV1108_CLKGATE_CON(14), 0, GFLAGS), |
| 651 | + GATE(PCLK_EFUSE0, "pclk_efuse0", "pclk_bus_pre", 0, | |
| 652 | + RV1108_CLKGATE_CON(12), 12, GFLAGS), | |
| 653 | + GATE(PCLK_EFUSE1, "pclk_efuse1", "pclk_bus_pre", 0, | |
| 654 | + RV1108_CLKGATE_CON(12), 13, GFLAGS), | |
| 655 | + GATE(PCLK_TSADC, "pclk_tsadc", "pclk_bus_pre", 0, | |
| 656 | + RV1108_CLKGATE_CON(13), 13, GFLAGS), | |
| 657 | + COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin24m", 0, | |
| 658 | + RV1108_CLKSEL_CON(21), 0, 10, DFLAGS, | |
| 659 | + RV1108_CLKGATE_CON(3), 11, GFLAGS), | |
| 660 | + GATE(PCLK_SARADC, "pclk_saradc", "pclk_bus_pre", 0, | |
| 661 | + RV1108_CLKGATE_CON(13), 14, GFLAGS), | |
| 662 | + COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, | |
| 663 | + RV1108_CLKSEL_CON(22), 0, 10, DFLAGS, | |
| 664 | + RV1108_CLKGATE_CON(3), 12, GFLAGS), | |
| 385 | 665 | |
| 386 | 666 | GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0, |
| 387 | 667 | RV1108_CLKGATE_CON(12), 2, GFLAGS), |
| @@ -397,18 +677,24 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 9 unmodified lines | ||
| 397 | 677 | RV1108_CLKGATE_CON(0), 9, GFLAGS), |
| 398 | 678 | GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, |
| 399 | 679 | RV1108_CLKGATE_CON(0), 10, GFLAGS), |
| 400 | − COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, | |
| 680 | + COMPOSITE_NOGATE(0, "clk_ddrphy_src", mux_ddrphy_p, CLK_IGNORE_UNUSED, | |
| 401 | 681 | RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3, |
| 402 | − DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | |
| 682 | + DFLAGS | CLK_DIVIDER_POWER_OF_TWO), | |
| 683 | + FACTOR(0, "clk_ddr", "clk_ddrphy_src", 0, 1, 2), | |
| 684 | + GATE(0, "clk_ddrphy4x", "clk_ddr", CLK_IGNORE_UNUSED, | |
| 403 | 685 | RV1108_CLKGATE_CON(10), 9, GFLAGS), |
| 404 | − GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED, | |
| 686 | + GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | |
| 405 | 687 | RV1108_CLKGATE_CON(12), 4, GFLAGS), |
| 406 | − GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED, | |
| 688 | + GATE(0, "nclk_ddrupctl", "clk_ddr", CLK_IGNORE_UNUSED, | |
| 407 | 689 | RV1108_CLKGATE_CON(12), 5, GFLAGS), |
| 408 | − GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED, | |
| 690 | + GATE(0, "pclk_ddrmon", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | |
| 409 | 691 | RV1108_CLKGATE_CON(12), 6, GFLAGS), |
| 410 | 692 | GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED, |
| 411 | 693 | RV1108_CLKGATE_CON(0), 11, GFLAGS), |
| 694 | + GATE(0, "pclk_mschniu", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | |
| 695 | + RV1108_CLKGATE_CON(14), 2, GFLAGS), | |
| 696 | + GATE(0, "pclk_ddrphy", "pclk_ddr_pre", CLK_IGNORE_UNUSED, | |
| 697 | + RV1108_CLKGATE_CON(14), 4, GFLAGS), | |
| 412 | 698 | |
| 413 | 699 | /* |
| 414 | 700 | * Clock-Architecture Diagram 6 |
| @@ -418,23 +704,23 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 3 unmodified lines | ||
| 418 | 704 | COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0, |
| 419 | 705 | RV1108_CLKSEL_CON(23), 10, 5, DFLAGS, |
| 420 | 706 | RV1108_CLKGATE_CON(4), 5, GFLAGS), |
| 421 | − GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, | |
| 707 | + GATE(PCLK_PERI, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED, | |
| 422 | 708 | RV1108_CLKGATE_CON(15), 13, GFLAGS), |
| 423 | 709 | COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0, |
| 424 | 710 | RV1108_CLKSEL_CON(23), 5, 5, DFLAGS, |
| 425 | 711 | RV1108_CLKGATE_CON(4), 4, GFLAGS), |
| 426 | − GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, | |
| 712 | + GATE(HCLK_PERI, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED, | |
| 427 | 713 | RV1108_CLKGATE_CON(15), 12, GFLAGS), |
| 428 | 714 | |
| 429 | 715 | GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED, |
| 430 | 716 | RV1108_CLKGATE_CON(4), 1, GFLAGS), |
| 431 | 717 | GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED, |
| 432 | 718 | RV1108_CLKGATE_CON(4), 2, GFLAGS), |
| 433 | − COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED, | |
| 434 | − RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS, | |
| 719 | + COMPOSITE(ACLK_PERI, "aclk_periph", mux_aclk_peri_src_p, 0, | |
| 720 | + RV1108_CLKSEL_CON(23), 15, 1, MFLAGS, 0, 5, DFLAGS, | |
| 435 | 721 | RV1108_CLKGATE_CON(15), 11, GFLAGS), |
| 436 | 722 | |
| 437 | − COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, | |
| 723 | + COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, | |
| 438 | 724 | RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS, |
| 439 | 725 | RV1108_CLKGATE_CON(5), 0, GFLAGS), |
| 440 | 726 | |
| @@ -454,23 +740,31 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 13 unmodified lines | ||
| 454 | 740 | GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS), |
| 455 | 741 | |
| 456 | 742 | COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0, |
| 457 | − RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS, | |
| 743 | + RV1108_CLKSEL_CON(27), 14, 1, MFLAGS, 8, 5, DFLAGS, | |
| 458 | 744 | RV1108_CLKGATE_CON(5), 3, GFLAGS), |
| 459 | 745 | GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS), |
| 460 | 746 | |
| 747 | + GATE(HCLK_HOST0, "hclk_host0", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 6, GFLAGS), | |
| 748 | + GATE(0, "hclk_host0_arb", "hclk_periph", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(15), 7, GFLAGS), | |
| 749 | + GATE(HCLK_OTG, "hclk_otg", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 8, GFLAGS), | |
| 750 | + GATE(0, "hclk_otg_pmu", "hclk_periph", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(15), 9, GFLAGS), | |
| 751 | + GATE(SCLK_USBPHY, "clk_usbphy", "xin24m", CLK_IGNORE_UNUSED, RV1108_CLKGATE_CON(5), 5, GFLAGS), | |
| 752 | + | |
| 461 | 753 | COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0, |
| 462 | − RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS, | |
| 754 | + RV1108_CLKSEL_CON(27), 7, 1, MFLAGS, 0, 7, DFLAGS, | |
| 463 | 755 | RV1108_CLKGATE_CON(5), 4, GFLAGS), |
| 464 | 756 | GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS), |
| 465 | 757 | |
| 466 | − COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0, | |
| 467 | − RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS, | |
| 758 | + COMPOSITE(SCLK_MAC_PRE, "sclk_mac_pre", mux_pll_src_apll_gpll_p, 0, | |
| 759 | + RV1108_CLKSEL_CON(24), 12, 1, MFLAGS, 0, 5, DFLAGS, | |
| 468 | 760 | RV1108_CLKGATE_CON(4), 10, GFLAGS), |
| 469 | − MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT, | |
| 470 | − RV1108_CLKSEL_CON(24), 8, 2, MFLAGS), | |
| 471 | − GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), | |
| 472 | − GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), | |
| 473 | − GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), | |
| 761 | + MUX(SCLK_MAC, "sclk_mac", mux_sclk_mac_p, CLK_SET_RATE_PARENT, | |
| 762 | + RV1108_CLKSEL_CON(24), 8, 1, MFLAGS), | |
| 763 | + GATE(SCLK_MAC_RX, "sclk_mac_rx", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS), | |
| 764 | + GATE(SCLK_MAC_REF, "sclk_mac_ref", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS), | |
| 765 | + GATE(SCLK_MAC_REFOUT, "sclk_mac_refout", "sclk_mac", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS), | |
| 766 | + GATE(ACLK_GMAC, "aclk_gmac", "aclk_periph", 0, RV1108_CLKGATE_CON(15), 4, GFLAGS), | |
| 767 | + GATE(PCLK_GMAC, "pclk_gmac", "pclk_periph", 0, RV1108_CLKGATE_CON(15), 5, GFLAGS), | |
| 474 | 768 | |
| 475 | 769 | MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RV1108_SDMMC_CON0, 1), |
| 476 | 770 | MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1), |
| @@ -484,10 +778,16 @@ static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = { · 7 unmodified lines | ||
| 484 | 778 | |
| 485 | 779 | static const char *const rv1108_critical_clocks[] __initconst = { |
| 486 | 780 | "aclk_core", |
| 487 | − "aclk_bus_src_gpll", | |
| 781 | + "aclk_bus", | |
| 782 | + "hclk_bus", | |
| 783 | + "pclk_bus", | |
| 488 | 784 | "aclk_periph", |
| 489 | 785 | "hclk_periph", |
| 490 | 786 | "pclk_periph", |
| 787 | + "nclk_ddrupctl", | |
| 788 | + "pclk_ddrmon", | |
| 789 | + "pclk_acodecphy", | |
| 790 | + "pclk_pmu", | |
| 491 | 791 | }; |
| 492 | 792 | |
| 493 | 793 | static void __init rv1108_clk_init(struct device_node *np) |
| @@ -29,6 +29,7 @@ · 28 unmodified lines | ||
| 29 | 29 | #include <linux/mfd/syscon.h> |
| 30 | 30 | #include <linux/regmap.h> |
| 31 | 31 | #include <linux/reboot.h> |
| 32 | +#include <linux/rational.h> | |
| 32 | 33 | #include "clk.h" |
| 33 | 34 | |
| 34 | 35 | /** |
| @@ -164,6 +165,40 @@ static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb, · 129 unmodified lines | ||
| 164 | 165 | return notifier_from_errno(ret); |
| 165 | 166 | } |
| 166 | 167 | |
| 168 | +/** | |
| 169 | + * fractional divider must set that denominator is 20 times larger than | |
| 170 | + * numerator to generate precise clock frequency. | |
| 171 | + */ | |
| 172 | +static void rockchip_fractional_approximation(struct clk_hw *hw, | |
| 173 | + unsigned long rate, unsigned long *parent_rate, | |
| 174 | + unsigned long *m, unsigned long *n) | |
| 175 | +{ | |
| 176 | + struct clk_fractional_divider *fd = to_clk_fd(hw); | |
| 177 | + unsigned long p_rate, p_parent_rate; | |
| 178 | + struct clk_hw *p_parent; | |
| 179 | + unsigned long scale; | |
| 180 | + | |
| 181 | + p_rate = clk_hw_get_rate(clk_hw_get_parent(hw)); | |
| 182 | + if ((rate * 20 > p_rate) && (p_rate % rate != 0)) { | |
| 183 | + p_parent = clk_hw_get_parent(clk_hw_get_parent(hw)); | |
| 184 | + p_parent_rate = clk_hw_get_rate(p_parent); | |
| 185 | + *parent_rate = p_parent_rate; | |
| 186 | + } | |
| 187 | + | |
| 188 | + /* | |
| 189 | + * Get rate closer to *parent_rate to guarantee there is no overflow | |
| 190 | + * for m and n. In the result it will be the nearest rate left shifted | |
| 191 | + * by (scale - fd->nwidth) bits. | |
| 192 | + */ | |
| 193 | + scale = fls_long(*parent_rate / rate - 1); | |
| 194 | + if (scale > fd->nwidth) | |
| 195 | + rate <<= scale - fd->nwidth; | |
| 196 | + | |
| 197 | + rational_best_approximation(rate, *parent_rate, | |
| 198 | + GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0), | |
| 199 | + m, n); | |
| 200 | +} | |
| 201 | + | |
| 167 | 202 | static struct clk *rockchip_clk_register_frac_branch( |
| 168 | 203 | struct rockchip_clk_provider *ctx, const char *name, |
| 169 | 204 | const char *const *parent_names, u8 num_parents, |
| @@ -210,6 +245,7 @@ static struct clk *rockchip_clk_register_frac_branch( · 40 unmodified lines | ||
| 210 | 245 | div->nwidth = 16; |
| 211 | 246 | div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift; |
| 212 | 247 | div->lock = lock; |
| 248 | + div->approximation = rockchip_fractional_approximation; | |
| 213 | 249 | div_ops = &clk_fractional_divider_ops; |
| 214 | 250 | |
| 215 | 251 | clk = clk_register_composite(NULL, name, parent_names, num_parents, |
| @@ -180,7 +180,7 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) · 179 unmodified lines | ||
| 180 | 180 | } |
| 181 | 181 | clk_table[EXYNOS_MOUT_AUDSS] = clk_hw_register_mux(NULL, "mout_audss", |
| 182 | 182 | mout_audss_p, ARRAY_SIZE(mout_audss_p), |
| 183 | − CLK_SET_RATE_NO_REPARENT, | |
| 183 | + CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, | |
| 184 | 184 | reg_base + ASS_CLK_SRC, 0, 1, 0, &lock); |
| 185 | 185 | |
| 186 | 186 | cdclk = devm_clk_get(&pdev->dev, "cdclk"); |
| @@ -195,11 +195,11 @@ static int exynos_audss_clk_probe(struct platform_device *pdev) · 8 unmodified lines | ||
| 195 | 195 | reg_base + ASS_CLK_SRC, 2, 2, 0, &lock); |
| 196 | 196 | |
| 197 | 197 | clk_table[EXYNOS_DOUT_SRP] = clk_hw_register_divider(NULL, "dout_srp", |
| 198 | − "mout_audss", 0, reg_base + ASS_CLK_DIV, 0, 4, | |
| 199 | − 0, &lock); | |
| 198 | + "mout_audss", CLK_SET_RATE_PARENT, | |
| 199 | + reg_base + ASS_CLK_DIV, 0, 4, 0, &lock); | |
| 200 | 200 | |
| 201 | 201 | clk_table[EXYNOS_DOUT_AUD_BUS] = clk_hw_register_divider(NULL, |
| 202 | − "dout_aud_bus", "dout_srp", 0, | |
| 202 | + "dout_aud_bus", "dout_srp", CLK_SET_RATE_PARENT, | |
| 203 | 203 | reg_base + ASS_CLK_DIV, 4, 4, 0, &lock); |
| 204 | 204 | |
| 205 | 205 | clk_table[EXYNOS_DOUT_I2S] = clk_hw_register_divider(NULL, "dout_i2s", |
| @@ -537,8 +537,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { · 536 unmodified lines | ||
| 537 | 537 | |
| 538 | 538 | MUX(CLK_MOUT_MX_MSPLL_CCORE, "mout_mx_mspll_ccore", |
| 539 | 539 | mout_mx_mspll_ccore_p, SRC_TOP7, 16, 2), |
| 540 | − MUX(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, | |
| 541 | − SRC_TOP7, 20, 2), | |
| 540 | + MUX_F(CLK_MOUT_MAU_EPLL, "mout_mau_epll_clk", mout_mau_epll_clk_5800_p, | |
| 541 | + SRC_TOP7, 20, 2, CLK_SET_RATE_PARENT, 0), | |
| 542 | 542 | MUX(0, "sclk_bpll", mout_bpll_p, SRC_TOP7, 24, 1), |
| 543 | 543 | MUX(0, "mout_epll2", mout_epll2_5800_p, SRC_TOP7, 28, 1), |
| 544 | 544 | |
| @@ -547,8 +547,8 @@ static const struct samsung_mux_clock exynos5800_mux_clks[] __initconst = { · 2 unmodified lines | ||
| 547 | 547 | MUX(0, "mout_aclk432_cam", mout_group6_5800_p, SRC_TOP8, 24, 2), |
| 548 | 548 | MUX(0, "mout_aclk432_scaler", mout_group6_5800_p, SRC_TOP8, 28, 2), |
| 549 | 549 | |
| 550 | − MUX(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p, | |
| 551 | − SRC_TOP9, 8, 1), | |
| 550 | + MUX_F(CLK_MOUT_USER_MAU_EPLL, "mout_user_mau_epll", mout_group16_5800_p, | |
| 551 | + SRC_TOP9, 8, 1, CLK_SET_RATE_PARENT, 0), | |
| 552 | 552 | MUX(0, "mout_user_aclk550_cam", mout_group15_5800_p, |
| 553 | 553 | SRC_TOP9, 16, 1), |
| 554 | 554 | MUX(0, "mout_user_aclkfl1_550_cam", mout_group13_5800_p, |
| @@ -590,6 +590,8 @@ static const struct samsung_gate_clock exynos5800_gate_clks[] __initconst = { · 35 unmodified lines | ||
| 590 | 590 | GATE_BUS_TOP, 24, 0, 0), |
| 591 | 591 | GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", |
| 592 | 592 | GATE_BUS_TOP, 27, CLK_IS_CRITICAL, 0), |
| 593 | + GATE(CLK_MAU_EPLL, "mau_epll", "mout_user_mau_epll", | |
| 594 | + SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0), | |
| 593 | 595 | }; |
| 594 | 596 | |
| 595 | 597 | static const struct samsung_mux_clock exynos5420_mux_clks[] __initconst = { |
| @@ -629,6 +631,11 @@ static const struct samsung_div_clock exynos5420_div_clks[] __initconst = { · 33 unmodified lines | ||
| 629 | 631 | "mout_aclk400_wcore_bpll", DIV_TOP0, 16, 3), |
| 630 | 632 | }; |
| 631 | 633 | |
| 634 | +static const struct samsung_gate_clock exynos5420_gate_clks[] __initconst = { | |
| 635 | + GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", | |
| 636 | + SRC_MASK_TOP7, 20, CLK_SET_RATE_PARENT, 0), | |
| 637 | +}; | |
| 638 | + | |
| 632 | 639 | static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { |
| 633 | 640 | MUX(0, "mout_user_pclk66_gpio", mout_user_pclk66_gpio_p, |
| 634 | 641 | SRC_TOP7, 4, 1), |
| @@ -706,7 +713,8 @@ static const struct samsung_mux_clock exynos5x_mux_clks[] __initconst = { · 71 unmodified lines | ||
| 706 | 713 | MUX(0, "mout_sclk_spll", mout_spll_p, SRC_TOP6, 8, 1), |
| 707 | 714 | MUX(0, "mout_sclk_ipll", mout_ipll_p, SRC_TOP6, 12, 1), |
| 708 | 715 | MUX(0, "mout_sclk_rpll", mout_rpll_p, SRC_TOP6, 16, 1), |
| 709 | − MUX(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1), | |
| 716 | + MUX_F(CLK_MOUT_EPLL, "mout_sclk_epll", mout_epll_p, SRC_TOP6, 20, 1, | |
| 717 | + CLK_SET_RATE_PARENT, 0), | |
| 710 | 718 | MUX(0, "mout_sclk_dpll", mout_dpll_p, SRC_TOP6, 24, 1), |
| 711 | 719 | MUX(0, "mout_sclk_cpll", mout_cpll_p, SRC_TOP6, 28, 1), |
| 712 | 720 | |
| @@ -1001,9 +1009,6 @@ static const struct samsung_gate_clock exynos5x_gate_clks[] __initconst = { · 288 unmodified lines | ||
| 1001 | 1009 | GATE(0, "aclk300_disp1", "mout_user_aclk300_disp1", |
| 1002 | 1010 | SRC_MASK_TOP2, 24, CLK_IS_CRITICAL, 0), |
| 1003 | 1011 | |
| 1004 | − GATE(CLK_MAU_EPLL, "mau_epll", "mout_mau_epll_clk", | |
| 1005 | − SRC_MASK_TOP7, 20, 0, 0), | |
| 1006 | − | |
| 1007 | 1012 | /* sclk */ |
| 1008 | 1013 | GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_uart0", |
| 1009 | 1014 | GATE_TOP_SCLK_PERIC, 0, CLK_SET_RATE_PARENT, 0), |
| @@ -1440,6 +1445,8 @@ static void __init exynos5x_clk_init(struct device_node *np, · 430 unmodified lines | ||
| 1440 | 1445 | ARRAY_SIZE(exynos5420_mux_clks)); |
| 1441 | 1446 | samsung_clk_register_div(ctx, exynos5420_div_clks, |
| 1442 | 1447 | ARRAY_SIZE(exynos5420_div_clks)); |
| 1448 | + samsung_clk_register_gate(ctx, exynos5420_gate_clks, | |
| 1449 | + ARRAY_SIZE(exynos5420_gate_clks)); | |
| 1443 | 1450 | } else { |
| 1444 | 1451 | samsung_clk_register_fixed_factor( |
| 1445 | 1452 | ctx, exynos5800_fixed_factor_clks, |
| @@ -11,6 +11,19 @@ config SUN50I_A64_CCU · 10 unmodified lines | ||
| 11 | 11 | default ARM64 && ARCH_SUNXI |
| 12 | 12 | depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST |
| 13 | 13 | |
| 14 | +config SUN4I_A10_CCU | |
| 15 | + bool "Support for the Allwinner A10/A20 CCU" | |
| 16 | + select SUNXI_CCU_DIV | |
| 17 | + select SUNXI_CCU_MULT | |
| 18 | + select SUNXI_CCU_NK | |
| 19 | + select SUNXI_CCU_NKM | |
| 20 | + select SUNXI_CCU_NM | |
| 21 | + select SUNXI_CCU_MP | |
| 22 | + select SUNXI_CCU_PHASE | |
| 23 | + default MACH_SUN4I | |
| 24 | + default MACH_SUN7I | |
| 25 | + depends on MACH_SUN4I || MACH_SUN7I || COMPILE_TEST | |
| 26 | + | |
| 14 | 27 | config SUN5I_CCU |
| 15 | 28 | bool "Support for the Allwinner sun5i family CCM" |
| 16 | 29 | default MACH_SUN5I |
| @@ -48,6 +61,11 @@ config SUN8I_V3S_CCU · 31 unmodified lines | ||
| 48 | 61 | config SUN8I_DE2_CCU |
| 49 | 62 | bool "Support for the Allwinner SoCs DE2 CCU" |
| 50 | 63 | |
| 64 | +config SUN8I_R40_CCU | |
| 65 | + bool "Support for the Allwinner R40 CCU" | |
| 66 | + default MACH_SUN8I | |
| 67 | + depends on MACH_SUN8I || COMPILE_TEST | |
| 68 | + | |
| 51 | 69 | config SUN9I_A80_CCU |
| 52 | 70 | bool "Support for the Allwinner A80 CCU" |
| 53 | 71 | default MACH_SUN9I |
| @@ -20,6 +20,7 @@ lib-$(CONFIG_SUNXI_CCU) += ccu_mp.o · 19 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | # SoC support |
| 22 | 22 | obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o |
| 23 | +obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o | |
| 23 | 24 | obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o |
| 24 | 25 | obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o |
| 25 | 26 | obj-$(CONFIG_SUN8I_A23_CCU) += ccu-sun8i-a23.o |
| @@ -29,6 +30,7 @@ obj-$(CONFIG_SUN8I_H3_CCU) += ccu-sun8i-h3.o · 3 unmodified lines | ||
| 29 | 30 | obj-$(CONFIG_SUN8I_V3S_CCU) += ccu-sun8i-v3s.o |
| 30 | 31 | obj-$(CONFIG_SUN8I_DE2_CCU) += ccu-sun8i-de2.o |
| 31 | 32 | obj-$(CONFIG_SUN8I_R_CCU) += ccu-sun8i-r.o |
| 33 | +obj-$(CONFIG_SUN8I_R40_CCU) += ccu-sun8i-r40.o | |
| 32 | 34 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80.o |
| 33 | 35 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-de.o |
| 34 | 36 | obj-$(CONFIG_SUN9I_A80_CCU) += ccu-sun9i-a80-usb.o |
| @@ -0,0 +1,1456 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2017 Priit Laes <plaes@plaes.org>. | |
| 3 | + * Copyright (c) 2017 Maxime Ripard. | |
| 4 | + * Copyright (c) 2017 Jonathan Liu. | |
| 5 | + * | |
| 6 | + * This software is licensed under the terms of the GNU General Public | |
| 7 | + * License version 2, as published by the Free Software Foundation, and | |
| 8 | + * may be copied, distributed, and modified under those terms. | |
| 9 | + * | |
| 10 | + * This program is distributed in the hope that it will be useful, | |
| 11 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 12 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 13 | + * GNU General Public License for more details. | |
| 14 | + */ | |
| 15 | + | |
| 16 | +#include <linux/clk-provider.h> | |
| 17 | +#include <linux/of_address.h> | |
| 18 | + | |
| 19 | +#include "ccu_common.h" | |
| 20 | +#include "ccu_reset.h" | |
| 21 | + | |
| 22 | +#include "ccu_div.h" | |
| 23 | +#include "ccu_gate.h" | |
| 24 | +#include "ccu_mp.h" | |
| 25 | +#include "ccu_mult.h" | |
| 26 | +#include "ccu_nk.h" | |
| 27 | +#include "ccu_nkm.h" | |
| 28 | +#include "ccu_nkmp.h" | |
| 29 | +#include "ccu_nm.h" | |
| 30 | +#include "ccu_phase.h" | |
| 31 | + | |
| 32 | +#include "ccu-sun4i-a10.h" | |
| 33 | + | |
| 34 | +static struct ccu_nkmp pll_core_clk = { | |
| 35 | + .enable = BIT(31), | |
| 36 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 37 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 38 | + .m = _SUNXI_CCU_DIV(0, 2), | |
| 39 | + .p = _SUNXI_CCU_DIV(16, 2), | |
| 40 | + .common = { | |
| 41 | + .reg = 0x000, | |
| 42 | + .hw.init = CLK_HW_INIT("pll-core", | |
| 43 | + "hosc", | |
| 44 | + &ccu_nkmp_ops, | |
| 45 | + 0), | |
| 46 | + }, | |
| 47 | +}; | |
| 48 | + | |
| 49 | +/* | |
| 50 | + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from | |
| 51 | + * the base (2x, 4x and 8x), and one variable divider (the one true | |
| 52 | + * pll audio). | |
| 53 | + * | |
| 54 | + * We don't have any need for the variable divider for now, so we just | |
| 55 | + * hardcode it to match with the clock names. | |
| 56 | + */ | |
| 57 | +#define SUN4I_PLL_AUDIO_REG 0x008 | |
| 58 | +static struct ccu_nm pll_audio_base_clk = { | |
| 59 | + .enable = BIT(31), | |
| 60 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 7, 0), | |
| 61 | + .m = _SUNXI_CCU_DIV_OFFSET(0, 5, 0), | |
| 62 | + .common = { | |
| 63 | + .reg = 0x008, | |
| 64 | + .hw.init = CLK_HW_INIT("pll-audio-base", | |
| 65 | + "hosc", | |
| 66 | + &ccu_nm_ops, | |
| 67 | + 0), | |
| 68 | + }, | |
| 69 | + | |
| 70 | +}; | |
| 71 | + | |
| 72 | +static struct ccu_mult pll_video0_clk = { | |
| 73 | + .enable = BIT(31), | |
| 74 | + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), | |
| 75 | + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), | |
| 76 | + 270000000, 297000000), | |
| 77 | + .common = { | |
| 78 | + .reg = 0x010, | |
| 79 | + .features = (CCU_FEATURE_FRACTIONAL | | |
| 80 | + CCU_FEATURE_ALL_PREDIV), | |
| 81 | + .prediv = 8, | |
| 82 | + .hw.init = CLK_HW_INIT("pll-video0", | |
| 83 | + "hosc", | |
| 84 | + &ccu_mult_ops, | |
| 85 | + 0), | |
| 86 | + }, | |
| 87 | +}; | |
| 88 | + | |
| 89 | +static struct ccu_nkmp pll_ve_sun4i_clk = { | |
| 90 | + .enable = BIT(31), | |
| 91 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 92 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 93 | + .m = _SUNXI_CCU_DIV(0, 2), | |
| 94 | + .p = _SUNXI_CCU_DIV(16, 2), | |
| 95 | + .common = { | |
| 96 | + .reg = 0x018, | |
| 97 | + .hw.init = CLK_HW_INIT("pll-ve", | |
| 98 | + "hosc", | |
| 99 | + &ccu_nkmp_ops, | |
| 100 | + 0), | |
| 101 | + }, | |
| 102 | +}; | |
| 103 | + | |
| 104 | +static struct ccu_nk pll_ve_sun7i_clk = { | |
| 105 | + .enable = BIT(31), | |
| 106 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 107 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 108 | + .common = { | |
| 109 | + .reg = 0x018, | |
| 110 | + .hw.init = CLK_HW_INIT("pll-ve", | |
| 111 | + "hosc", | |
| 112 | + &ccu_nk_ops, | |
| 113 | + 0), | |
| 114 | + }, | |
| 115 | +}; | |
| 116 | + | |
| 117 | +static struct ccu_nk pll_ddr_base_clk = { | |
| 118 | + .enable = BIT(31), | |
| 119 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 120 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 121 | + .common = { | |
| 122 | + .reg = 0x020, | |
| 123 | + .hw.init = CLK_HW_INIT("pll-ddr-base", | |
| 124 | + "hosc", | |
| 125 | + &ccu_nk_ops, | |
| 126 | + 0), | |
| 127 | + }, | |
| 128 | +}; | |
| 129 | + | |
| 130 | +static SUNXI_CCU_M(pll_ddr_clk, "pll-ddr", "pll-ddr-base", 0x020, 0, 2, | |
| 131 | + CLK_IS_CRITICAL); | |
| 132 | + | |
| 133 | +static struct ccu_div pll_ddr_other_clk = { | |
| 134 | + .div = _SUNXI_CCU_DIV_FLAGS(16, 2, CLK_DIVIDER_POWER_OF_TWO), | |
| 135 | + .common = { | |
| 136 | + .reg = 0x020, | |
| 137 | + .hw.init = CLK_HW_INIT("pll-ddr-other", "pll-ddr-base", | |
| 138 | + &ccu_div_ops, | |
| 139 | + 0), | |
| 140 | + }, | |
| 141 | +}; | |
| 142 | + | |
| 143 | +static struct ccu_nk pll_periph_base_clk = { | |
| 144 | + .enable = BIT(31), | |
| 145 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 146 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 147 | + .common = { | |
| 148 | + .reg = 0x028, | |
| 149 | + .hw.init = CLK_HW_INIT("pll-periph-base", | |
| 150 | + "hosc", | |
| 151 | + &ccu_nk_ops, | |
| 152 | + 0), | |
| 153 | + }, | |
| 154 | +}; | |
| 155 | + | |
| 156 | +static CLK_FIXED_FACTOR(pll_periph_clk, "pll-periph", "pll-periph-base", | |
| 157 | + 2, 1, CLK_SET_RATE_PARENT); | |
| 158 | + | |
| 159 | +/* Not documented on A10 */ | |
| 160 | +static struct ccu_div pll_periph_sata_clk = { | |
| 161 | + .enable = BIT(14), | |
| 162 | + .div = _SUNXI_CCU_DIV(0, 2), | |
| 163 | + .fixed_post_div = 6, | |
| 164 | + .common = { | |
| 165 | + .reg = 0x028, | |
| 166 | + .features = CCU_FEATURE_FIXED_POSTDIV, | |
| 167 | + .hw.init = CLK_HW_INIT("pll-periph-sata", | |
| 168 | + "pll-periph-base", | |
| 169 | + &ccu_div_ops, 0), | |
| 170 | + }, | |
| 171 | +}; | |
| 172 | + | |
| 173 | +static struct ccu_mult pll_video1_clk = { | |
| 174 | + .enable = BIT(31), | |
| 175 | + .mult = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(0, 7, 0, 9, 127), | |
| 176 | + .frac = _SUNXI_CCU_FRAC(BIT(15), BIT(14), | |
| 177 | + 270000000, 297000000), | |
| 178 | + .common = { | |
| 179 | + .reg = 0x030, | |
| 180 | + .features = (CCU_FEATURE_FRACTIONAL | | |
| 181 | + CCU_FEATURE_ALL_PREDIV), | |
| 182 | + .prediv = 8, | |
| 183 | + .hw.init = CLK_HW_INIT("pll-video1", | |
| 184 | + "hosc", | |
| 185 | + &ccu_mult_ops, | |
| 186 | + 0), | |
| 187 | + }, | |
| 188 | +}; | |
| 189 | + | |
| 190 | +/* Not present on A10 */ | |
| 191 | +static struct ccu_nk pll_gpu_clk = { | |
| 192 | + .enable = BIT(31), | |
| 193 | + .n = _SUNXI_CCU_MULT_OFFSET(8, 5, 0), | |
| 194 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 195 | + .common = { | |
| 196 | + .reg = 0x040, | |
| 197 | + .hw.init = CLK_HW_INIT("pll-gpu", | |
| 198 | + "hosc", | |
| 199 | + &ccu_nk_ops, | |
| 200 | + 0), | |
| 201 | + }, | |
| 202 | +}; | |
| 203 | + | |
| 204 | +static SUNXI_CCU_GATE(hosc_clk, "hosc", "osc24M", 0x050, BIT(0), 0); | |
| 205 | + | |
| 206 | +static const char *const cpu_parents[] = { "osc32k", "hosc", | |
| 207 | + "pll-core", "pll-periph" }; | |
| 208 | +static const struct ccu_mux_fixed_prediv cpu_predivs[] = { | |
| 209 | + { .index = 3, .div = 3, }, | |
| 210 | +}; | |
| 211 | + | |
| 212 | +#define SUN4I_AHB_REG 0x054 | |
| 213 | +static struct ccu_mux cpu_clk = { | |
| 214 | + .mux = { | |
| 215 | + .shift = 16, | |
| 216 | + .width = 2, | |
| 217 | + .fixed_predivs = cpu_predivs, | |
| 218 | + .n_predivs = ARRAY_SIZE(cpu_predivs), | |
| 219 | + }, | |
| 220 | + .common = { | |
| 221 | + .reg = 0x054, | |
| 222 | + .features = CCU_FEATURE_FIXED_PREDIV, | |
| 223 | + .hw.init = CLK_HW_INIT_PARENTS("cpu", | |
| 224 | + cpu_parents, | |
| 225 | + &ccu_mux_ops, | |
| 226 | + CLK_IS_CRITICAL), | |
| 227 | + } | |
| 228 | +}; | |
| 229 | + | |
| 230 | +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x054, 0, 2, 0); | |
| 231 | + | |
| 232 | +static struct ccu_div ahb_sun4i_clk = { | |
| 233 | + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | |
| 234 | + .common = { | |
| 235 | + .reg = 0x054, | |
| 236 | + .hw.init = CLK_HW_INIT("ahb", "axi", &ccu_div_ops, 0), | |
| 237 | + }, | |
| 238 | +}; | |
| 239 | + | |
| 240 | +static const char *const ahb_sun7i_parents[] = { "axi", "pll-periph", | |
| 241 | + "pll-periph" }; | |
| 242 | +static const struct ccu_mux_fixed_prediv ahb_sun7i_predivs[] = { | |
| 243 | + { .index = 1, .div = 2, }, | |
| 244 | + { /* Sentinel */ }, | |
| 245 | +}; | |
| 246 | +static struct ccu_div ahb_sun7i_clk = { | |
| 247 | + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | |
| 248 | + .mux = { | |
| 249 | + .shift = 6, | |
| 250 | + .width = 2, | |
| 251 | + .fixed_predivs = ahb_sun7i_predivs, | |
| 252 | + .n_predivs = ARRAY_SIZE(ahb_sun7i_predivs), | |
| 253 | + }, | |
| 254 | + | |
| 255 | + .common = { | |
| 256 | + .reg = 0x054, | |
| 257 | + .hw.init = CLK_HW_INIT_PARENTS("ahb", | |
| 258 | + ahb_sun7i_parents, | |
| 259 | + &ccu_div_ops, | |
| 260 | + 0), | |
| 261 | + }, | |
| 262 | +}; | |
| 263 | + | |
| 264 | +static struct clk_div_table apb0_div_table[] = { | |
| 265 | + { .val = 0, .div = 2 }, | |
| 266 | + { .val = 1, .div = 2 }, | |
| 267 | + { .val = 2, .div = 4 }, | |
| 268 | + { .val = 3, .div = 8 }, | |
| 269 | + { /* Sentinel */ }, | |
| 270 | +}; | |
| 271 | +static SUNXI_CCU_DIV_TABLE(apb0_clk, "apb0", "ahb", | |
| 272 | + 0x054, 8, 2, apb0_div_table, 0); | |
| 273 | + | |
| 274 | +static const char *const apb1_parents[] = { "hosc", "pll-periph", "osc32k" }; | |
| 275 | +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb1_parents, 0x058, | |
| 276 | + 0, 5, /* M */ | |
| 277 | + 16, 2, /* P */ | |
| 278 | + 24, 2, /* mux */ | |
| 279 | + 0); | |
| 280 | + | |
| 281 | +/* Not present on A20 */ | |
| 282 | +static SUNXI_CCU_GATE(axi_dram_clk, "axi-dram", "ahb", | |
| 283 | + 0x05c, BIT(31), 0); | |
| 284 | + | |
| 285 | +static SUNXI_CCU_GATE(ahb_otg_clk, "ahb-otg", "ahb", | |
| 286 | + 0x060, BIT(0), 0); | |
| 287 | +static SUNXI_CCU_GATE(ahb_ehci0_clk, "ahb-ehci0", "ahb", | |
| 288 | + 0x060, BIT(1), 0); | |
| 289 | +static SUNXI_CCU_GATE(ahb_ohci0_clk, "ahb-ohci0", "ahb", | |
| 290 | + 0x060, BIT(2), 0); | |
| 291 | +static SUNXI_CCU_GATE(ahb_ehci1_clk, "ahb-ehci1", "ahb", | |
| 292 | + 0x060, BIT(3), 0); | |
| 293 | +static SUNXI_CCU_GATE(ahb_ohci1_clk, "ahb-ohci1", "ahb", | |
| 294 | + 0x060, BIT(4), 0); | |
| 295 | +static SUNXI_CCU_GATE(ahb_ss_clk, "ahb-ss", "ahb", | |
| 296 | + 0x060, BIT(5), 0); | |
| 297 | +static SUNXI_CCU_GATE(ahb_dma_clk, "ahb-dma", "ahb", | |
| 298 | + 0x060, BIT(6), 0); | |
| 299 | +static SUNXI_CCU_GATE(ahb_bist_clk, "ahb-bist", "ahb", | |
| 300 | + 0x060, BIT(7), 0); | |
| 301 | +static SUNXI_CCU_GATE(ahb_mmc0_clk, "ahb-mmc0", "ahb", | |
| 302 | + 0x060, BIT(8), 0); | |
| 303 | +static SUNXI_CCU_GATE(ahb_mmc1_clk, "ahb-mmc1", "ahb", | |
| 304 | + 0x060, BIT(9), 0); | |
| 305 | +static SUNXI_CCU_GATE(ahb_mmc2_clk, "ahb-mmc2", "ahb", | |
| 306 | + 0x060, BIT(10), 0); | |
| 307 | +static SUNXI_CCU_GATE(ahb_mmc3_clk, "ahb-mmc3", "ahb", | |
| 308 | + 0x060, BIT(11), 0); | |
| 309 | +static SUNXI_CCU_GATE(ahb_ms_clk, "ahb-ms", "ahb", | |
| 310 | + 0x060, BIT(12), 0); | |
| 311 | +static SUNXI_CCU_GATE(ahb_nand_clk, "ahb-nand", "ahb", | |
| 312 | + 0x060, BIT(13), 0); | |
| 313 | +static SUNXI_CCU_GATE(ahb_sdram_clk, "ahb-sdram", "ahb", | |
| 314 | + 0x060, BIT(14), CLK_IS_CRITICAL); | |
| 315 | + | |
| 316 | +static SUNXI_CCU_GATE(ahb_ace_clk, "ahb-ace", "ahb", | |
| 317 | + 0x060, BIT(16), 0); | |
| 318 | +static SUNXI_CCU_GATE(ahb_emac_clk, "ahb-emac", "ahb", | |
| 319 | + 0x060, BIT(17), 0); | |
| 320 | +static SUNXI_CCU_GATE(ahb_ts_clk, "ahb-ts", "ahb", | |
| 321 | + 0x060, BIT(18), 0); | |
| 322 | +static SUNXI_CCU_GATE(ahb_spi0_clk, "ahb-spi0", "ahb", | |
| 323 | + 0x060, BIT(20), 0); | |
| 324 | +static SUNXI_CCU_GATE(ahb_spi1_clk, "ahb-spi1", "ahb", | |
| 325 | + 0x060, BIT(21), 0); | |
| 326 | +static SUNXI_CCU_GATE(ahb_spi2_clk, "ahb-spi2", "ahb", | |
| 327 | + 0x060, BIT(22), 0); | |
| 328 | +static SUNXI_CCU_GATE(ahb_spi3_clk, "ahb-spi3", "ahb", | |
| 329 | + 0x060, BIT(23), 0); | |
| 330 | +static SUNXI_CCU_GATE(ahb_pata_clk, "ahb-pata", "ahb", | |
| 331 | + 0x060, BIT(24), 0); | |
| 332 | +/* Not documented on A20 */ | |
| 333 | +static SUNXI_CCU_GATE(ahb_sata_clk, "ahb-sata", "ahb", | |
| 334 | + 0x060, BIT(25), 0); | |
| 335 | +/* Not present on A20 */ | |
| 336 | +static SUNXI_CCU_GATE(ahb_gps_clk, "ahb-gps", "ahb", | |
| 337 | + 0x060, BIT(26), 0); | |
| 338 | +/* Not present on A10 */ | |
| 339 | +static SUNXI_CCU_GATE(ahb_hstimer_clk, "ahb-hstimer", "ahb", | |
| 340 | + 0x060, BIT(28), 0); | |
| 341 | + | |
| 342 | +static SUNXI_CCU_GATE(ahb_ve_clk, "ahb-ve", "ahb", | |
| 343 | + 0x064, BIT(0), 0); | |
| 344 | +static SUNXI_CCU_GATE(ahb_tvd_clk, "ahb-tvd", "ahb", | |
| 345 | + 0x064, BIT(1), 0); | |
| 346 | +static SUNXI_CCU_GATE(ahb_tve0_clk, "ahb-tve0", "ahb", | |
| 347 | + 0x064, BIT(2), 0); | |
| 348 | +static SUNXI_CCU_GATE(ahb_tve1_clk, "ahb-tve1", "ahb", | |
| 349 | + 0x064, BIT(3), 0); | |
| 350 | +static SUNXI_CCU_GATE(ahb_lcd0_clk, "ahb-lcd0", "ahb", | |
| 351 | + 0x064, BIT(4), 0); | |
| 352 | +static SUNXI_CCU_GATE(ahb_lcd1_clk, "ahb-lcd1", "ahb", | |
| 353 | + 0x064, BIT(5), 0); | |
| 354 | +static SUNXI_CCU_GATE(ahb_csi0_clk, "ahb-csi0", "ahb", | |
| 355 | + 0x064, BIT(8), 0); | |
| 356 | +static SUNXI_CCU_GATE(ahb_csi1_clk, "ahb-csi1", "ahb", | |
| 357 | + 0x064, BIT(9), 0); | |
| 358 | +/* Not present on A10 */ | |
| 359 | +static SUNXI_CCU_GATE(ahb_hdmi1_clk, "ahb-hdmi1", "ahb", | |
| 360 | + 0x064, BIT(10), 0); | |
| 361 | +static SUNXI_CCU_GATE(ahb_hdmi0_clk, "ahb-hdmi0", "ahb", | |
| 362 | + 0x064, BIT(11), 0); | |
| 363 | +static SUNXI_CCU_GATE(ahb_de_be0_clk, "ahb-de-be0", "ahb", | |
| 364 | + 0x064, BIT(12), 0); | |
| 365 | +static SUNXI_CCU_GATE(ahb_de_be1_clk, "ahb-de-be1", "ahb", | |
| 366 | + 0x064, BIT(13), 0); | |
| 367 | +static SUNXI_CCU_GATE(ahb_de_fe0_clk, "ahb-de-fe0", "ahb", | |
| 368 | + 0x064, BIT(14), 0); | |
| 369 | +static SUNXI_CCU_GATE(ahb_de_fe1_clk, "ahb-de-fe1", "ahb", | |
| 370 | + 0x064, BIT(15), 0); | |
| 371 | +/* Not present on A10 */ | |
| 372 | +static SUNXI_CCU_GATE(ahb_gmac_clk, "ahb-gmac", "ahb", | |
| 373 | + 0x064, BIT(17), 0); | |
| 374 | +static SUNXI_CCU_GATE(ahb_mp_clk, "ahb-mp", "ahb", | |
| 375 | + 0x064, BIT(18), 0); | |
| 376 | +static SUNXI_CCU_GATE(ahb_gpu_clk, "ahb-gpu", "ahb", | |
| 377 | + 0x064, BIT(20), 0); | |
| 378 | + | |
| 379 | +static SUNXI_CCU_GATE(apb0_codec_clk, "apb0-codec", "apb0", | |
| 380 | + 0x068, BIT(0), 0); | |
| 381 | +static SUNXI_CCU_GATE(apb0_spdif_clk, "apb0-spdif", "apb0", | |
| 382 | + 0x068, BIT(1), 0); | |
| 383 | +static SUNXI_CCU_GATE(apb0_ac97_clk, "apb0-ac97", "apb0", | |
| 384 | + 0x068, BIT(2), 0); | |
| 385 | +static SUNXI_CCU_GATE(apb0_i2s0_clk, "apb0-i2s0", "apb0", | |
| 386 | + 0x068, BIT(3), 0); | |
| 387 | +/* Not present on A10 */ | |
| 388 | +static SUNXI_CCU_GATE(apb0_i2s1_clk, "apb0-i2s1", "apb0", | |
| 389 | + 0x068, BIT(4), 0); | |
| 390 | +static SUNXI_CCU_GATE(apb0_pio_clk, "apb0-pio", "apb0", | |
| 391 | + 0x068, BIT(5), 0); | |
| 392 | +static SUNXI_CCU_GATE(apb0_ir0_clk, "apb0-ir0", "apb0", | |
| 393 | + 0x068, BIT(6), 0); | |
| 394 | +static SUNXI_CCU_GATE(apb0_ir1_clk, "apb0-ir1", "apb0", | |
| 395 | + 0x068, BIT(7), 0); | |
| 396 | +/* Not present on A10 */ | |
| 397 | +static SUNXI_CCU_GATE(apb0_i2s2_clk, "apb0-i2s2", "apb0", | |
| 398 | + 0x068, BIT(8), 0); | |
| 399 | +static SUNXI_CCU_GATE(apb0_keypad_clk, "apb0-keypad", "apb0", | |
| 400 | + 0x068, BIT(10), 0); | |
| 401 | + | |
| 402 | +static SUNXI_CCU_GATE(apb1_i2c0_clk, "apb1-i2c0", "apb1", | |
| 403 | + 0x06c, BIT(0), 0); | |
| 404 | +static SUNXI_CCU_GATE(apb1_i2c1_clk, "apb1-i2c1", "apb1", | |
| 405 | + 0x06c, BIT(1), 0); | |
| 406 | +static SUNXI_CCU_GATE(apb1_i2c2_clk, "apb1-i2c2", "apb1", | |
| 407 | + 0x06c, BIT(2), 0); | |
| 408 | +/* Not present on A10 */ | |
| 409 | +static SUNXI_CCU_GATE(apb1_i2c3_clk, "apb1-i2c3", "apb1", | |
| 410 | + 0x06c, BIT(3), 0); | |
| 411 | +static SUNXI_CCU_GATE(apb1_can_clk, "apb1-can", "apb1", | |
| 412 | + 0x06c, BIT(4), 0); | |
| 413 | +static SUNXI_CCU_GATE(apb1_scr_clk, "apb1-scr", "apb1", | |
| 414 | + 0x06c, BIT(5), 0); | |
| 415 | +static SUNXI_CCU_GATE(apb1_ps20_clk, "apb1-ps20", "apb1", | |
| 416 | + 0x06c, BIT(6), 0); | |
| 417 | +static SUNXI_CCU_GATE(apb1_ps21_clk, "apb1-ps21", "apb1", | |
| 418 | + 0x06c, BIT(7), 0); | |
| 419 | +/* Not present on A10 */ | |
| 420 | +static SUNXI_CCU_GATE(apb1_i2c4_clk, "apb1-i2c4", "apb1", | |
| 421 | + 0x06c, BIT(15), 0); | |
| 422 | +static SUNXI_CCU_GATE(apb1_uart0_clk, "apb1-uart0", "apb1", | |
| 423 | + 0x06c, BIT(16), 0); | |
| 424 | +static SUNXI_CCU_GATE(apb1_uart1_clk, "apb1-uart1", "apb1", | |
| 425 | + 0x06c, BIT(17), 0); | |
| 426 | +static SUNXI_CCU_GATE(apb1_uart2_clk, "apb1-uart2", "apb1", | |
| 427 | + 0x06c, BIT(18), 0); | |
| 428 | +static SUNXI_CCU_GATE(apb1_uart3_clk, "apb1-uart3", "apb1", | |
| 429 | + 0x06c, BIT(19), 0); | |
| 430 | +static SUNXI_CCU_GATE(apb1_uart4_clk, "apb1-uart4", "apb1", | |
| 431 | + 0x06c, BIT(20), 0); | |
| 432 | +static SUNXI_CCU_GATE(apb1_uart5_clk, "apb1-uart5", "apb1", | |
| 433 | + 0x06c, BIT(21), 0); | |
| 434 | +static SUNXI_CCU_GATE(apb1_uart6_clk, "apb1-uart6", "apb1", | |
| 435 | + 0x06c, BIT(22), 0); | |
| 436 | +static SUNXI_CCU_GATE(apb1_uart7_clk, "apb1-uart7", "apb1", | |
| 437 | + 0x06c, BIT(23), 0); | |
| 438 | + | |
| 439 | +static const char *const mod0_default_parents[] = { "hosc", "pll-periph", | |
| 440 | + "pll-ddr-other" }; | |
| 441 | +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, | |
| 442 | + 0, 4, /* M */ | |
| 443 | + 16, 2, /* P */ | |
| 444 | + 24, 2, /* mux */ | |
| 445 | + BIT(31), /* gate */ | |
| 446 | + 0); | |
| 447 | + | |
| 448 | +/* Undocumented on A10 */ | |
| 449 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ms_clk, "ms", mod0_default_parents, 0x084, | |
| 450 | + 0, 4, /* M */ | |
| 451 | + 16, 2, /* P */ | |
| 452 | + 24, 2, /* mux */ | |
| 453 | + BIT(31), /* gate */ | |
| 454 | + 0); | |
| 455 | + | |
| 456 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, | |
| 457 | + 0, 4, /* M */ | |
| 458 | + 16, 2, /* P */ | |
| 459 | + 24, 2, /* mux */ | |
| 460 | + BIT(31), /* gate */ | |
| 461 | + 0); | |
| 462 | + | |
| 463 | +/* MMC output and sample clocks are not present on A10 */ | |
| 464 | +static SUNXI_CCU_PHASE(mmc0_output_clk, "mmc0_output", "mmc0", | |
| 465 | + 0x088, 8, 3, 0); | |
| 466 | +static SUNXI_CCU_PHASE(mmc0_sample_clk, "mmc0_sample", "mmc0", | |
| 467 | + 0x088, 20, 3, 0); | |
| 468 | + | |
| 469 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, | |
| 470 | + 0, 4, /* M */ | |
| 471 | + 16, 2, /* P */ | |
| 472 | + 24, 2, /* mux */ | |
| 473 | + BIT(31), /* gate */ | |
| 474 | + 0); | |
| 475 | + | |
| 476 | +/* MMC output and sample clocks are not present on A10 */ | |
| 477 | +static SUNXI_CCU_PHASE(mmc1_output_clk, "mmc1_output", "mmc1", | |
| 478 | + 0x08c, 8, 3, 0); | |
| 479 | +static SUNXI_CCU_PHASE(mmc1_sample_clk, "mmc1_sample", "mmc1", | |
| 480 | + 0x08c, 20, 3, 0); | |
| 481 | + | |
| 482 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, | |
| 483 | + 0, 4, /* M */ | |
| 484 | + 16, 2, /* P */ | |
| 485 | + 24, 2, /* mux */ | |
| 486 | + BIT(31), /* gate */ | |
| 487 | + 0); | |
| 488 | + | |
| 489 | +/* MMC output and sample clocks are not present on A10 */ | |
| 490 | +static SUNXI_CCU_PHASE(mmc2_output_clk, "mmc2_output", "mmc2", | |
| 491 | + 0x090, 8, 3, 0); | |
| 492 | +static SUNXI_CCU_PHASE(mmc2_sample_clk, "mmc2_sample", "mmc2", | |
| 493 | + 0x090, 20, 3, 0); | |
| 494 | + | |
| 495 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, | |
| 496 | + 0, 4, /* M */ | |
| 497 | + 16, 2, /* P */ | |
| 498 | + 24, 2, /* mux */ | |
| 499 | + BIT(31), /* gate */ | |
| 500 | + 0); | |
| 501 | + | |
| 502 | +/* MMC output and sample clocks are not present on A10 */ | |
| 503 | +static SUNXI_CCU_PHASE(mmc3_output_clk, "mmc3_output", "mmc3", | |
| 504 | + 0x094, 8, 3, 0); | |
| 505 | +static SUNXI_CCU_PHASE(mmc3_sample_clk, "mmc3_sample", "mmc3", | |
| 506 | + 0x094, 20, 3, 0); | |
| 507 | + | |
| 508 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", mod0_default_parents, 0x098, | |
| 509 | + 0, 4, /* M */ | |
| 510 | + 16, 2, /* P */ | |
| 511 | + 24, 2, /* mux */ | |
| 512 | + BIT(31), /* gate */ | |
| 513 | + 0); | |
| 514 | + | |
| 515 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ss_clk, "ss", mod0_default_parents, 0x09c, | |
| 516 | + 0, 4, /* M */ | |
| 517 | + 16, 2, /* P */ | |
| 518 | + 24, 2, /* mux */ | |
| 519 | + BIT(31), /* gate */ | |
| 520 | + 0); | |
| 521 | + | |
| 522 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, | |
| 523 | + 0, 4, /* M */ | |
| 524 | + 16, 2, /* P */ | |
| 525 | + 24, 2, /* mux */ | |
| 526 | + BIT(31), /* gate */ | |
| 527 | + 0); | |
| 528 | + | |
| 529 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, | |
| 530 | + 0, 4, /* M */ | |
| 531 | + 16, 2, /* P */ | |
| 532 | + 24, 2, /* mux */ | |
| 533 | + BIT(31), /* gate */ | |
| 534 | + 0); | |
| 535 | + | |
| 536 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, | |
| 537 | + 0, 4, /* M */ | |
| 538 | + 16, 2, /* P */ | |
| 539 | + 24, 2, /* mux */ | |
| 540 | + BIT(31), /* gate */ | |
| 541 | + 0); | |
| 542 | + | |
| 543 | +/* Undocumented on A10 */ | |
| 544 | +static SUNXI_CCU_MP_WITH_MUX_GATE(pata_clk, "pata", mod0_default_parents, 0x0ac, | |
| 545 | + 0, 4, /* M */ | |
| 546 | + 16, 2, /* P */ | |
| 547 | + 24, 2, /* mux */ | |
| 548 | + BIT(31), /* gate */ | |
| 549 | + 0); | |
| 550 | + | |
| 551 | +/* TODO: Check whether A10 actually supports osc32k as 4th parent? */ | |
| 552 | +static const char *const ir_parents_sun4i[] = { "hosc", "pll-periph", | |
| 553 | + "pll-ddr-other" }; | |
| 554 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun4i_clk, "ir0", ir_parents_sun4i, 0x0b0, | |
| 555 | + 0, 4, /* M */ | |
| 556 | + 16, 2, /* P */ | |
| 557 | + 24, 2, /* mux */ | |
| 558 | + BIT(31), /* gate */ | |
| 559 | + 0); | |
| 560 | + | |
| 561 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun4i_clk, "ir1", ir_parents_sun4i, 0x0b4, | |
| 562 | + 0, 4, /* M */ | |
| 563 | + 16, 2, /* P */ | |
| 564 | + 24, 2, /* mux */ | |
| 565 | + BIT(31), /* gate */ | |
| 566 | + 0); | |
| 567 | +static const char *const ir_parents_sun7i[] = { "hosc", "pll-periph", | |
| 568 | + "pll-ddr-other", "osc32k" }; | |
| 569 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_sun7i_clk, "ir0", ir_parents_sun7i, 0x0b0, | |
| 570 | + 0, 4, /* M */ | |
| 571 | + 16, 2, /* P */ | |
| 572 | + 24, 2, /* mux */ | |
| 573 | + BIT(31), /* gate */ | |
| 574 | + 0); | |
| 575 | + | |
| 576 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_sun7i_clk, "ir1", ir_parents_sun7i, 0x0b4, | |
| 577 | + 0, 4, /* M */ | |
| 578 | + 16, 2, /* P */ | |
| 579 | + 24, 2, /* mux */ | |
| 580 | + BIT(31), /* gate */ | |
| 581 | + 0); | |
| 582 | + | |
| 583 | +static const char *const audio_parents[] = { "pll-audio-8x", "pll-audio-4x", | |
| 584 | + "pll-audio-2x", "pll-audio" }; | |
| 585 | +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", audio_parents, | |
| 586 | + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 587 | + | |
| 588 | +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", audio_parents, | |
| 589 | + 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 590 | + | |
| 591 | +/* Undocumented on A10 */ | |
| 592 | +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", audio_parents, | |
| 593 | + 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 594 | + | |
| 595 | +static const char *const keypad_parents[] = { "hosc", "losc"}; | |
| 596 | +static const u8 keypad_table[] = { 0, 2 }; | |
| 597 | +static struct ccu_mp keypad_clk = { | |
| 598 | + .enable = BIT(31), | |
| 599 | + .m = _SUNXI_CCU_DIV(0, 5), | |
| 600 | + .p = _SUNXI_CCU_DIV(16, 2), | |
| 601 | + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), | |
| 602 | + .common = { | |
| 603 | + .reg = 0x0c4, | |
| 604 | + .hw.init = CLK_HW_INIT_PARENTS("keypad", | |
| 605 | + keypad_parents, | |
| 606 | + &ccu_mp_ops, | |
| 607 | + 0), | |
| 608 | + }, | |
| 609 | +}; | |
| 610 | + | |
| 611 | +/* | |
| 612 | + * SATA supports external clock as parent via BIT(24) and is probably an | |
| 613 | + * optional crystal or oscillator that can be connected to the | |
| 614 | + * SATA-CLKM / SATA-CLKP pins. | |
| 615 | + */ | |
| 616 | +static const char *const sata_parents[] = {"pll-periph-sata", "sata-ext"}; | |
| 617 | +static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, | |
| 618 | + 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); | |
| 619 | + | |
| 620 | + | |
| 621 | +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "pll-periph", | |
| 622 | + 0x0cc, BIT(6), 0); | |
| 623 | +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "pll-periph", | |
| 624 | + 0x0cc, BIT(7), 0); | |
| 625 | +static SUNXI_CCU_GATE(usb_phy_clk, "usb-phy", "pll-periph", | |
| 626 | + 0x0cc, BIT(8), 0); | |
| 627 | + | |
| 628 | +/* TODO: GPS CLK 0x0d0 */ | |
| 629 | + | |
| 630 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0d4, | |
| 631 | + 0, 4, /* M */ | |
| 632 | + 16, 2, /* P */ | |
| 633 | + 24, 2, /* mux */ | |
| 634 | + BIT(31), /* gate */ | |
| 635 | + 0); | |
| 636 | + | |
| 637 | +/* Not present on A10 */ | |
| 638 | +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", audio_parents, | |
| 639 | + 0x0d8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 640 | + | |
| 641 | +/* Not present on A10 */ | |
| 642 | +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", audio_parents, | |
| 643 | + 0x0dc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 644 | + | |
| 645 | +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "pll-ddr", | |
| 646 | + 0x100, BIT(0), 0); | |
| 647 | +static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "pll-ddr", | |
| 648 | + 0x100, BIT(1), 0); | |
| 649 | +static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "pll-ddr", | |
| 650 | + 0x100, BIT(2), 0); | |
| 651 | +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "pll-ddr", | |
| 652 | + 0x100, BIT(3), 0); | |
| 653 | +static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "pll-ddr", | |
| 654 | + 0x100, BIT(4), 0); | |
| 655 | +static SUNXI_CCU_GATE(dram_tve0_clk, "dram-tve0", "pll-ddr", | |
| 656 | + 0x100, BIT(5), 0); | |
| 657 | +static SUNXI_CCU_GATE(dram_tve1_clk, "dram-tve1", "pll-ddr", | |
| 658 | + 0x100, BIT(6), 0); | |
| 659 | + | |
| 660 | +/* Clock seems to be critical only on sun4i */ | |
| 661 | +static SUNXI_CCU_GATE(dram_out_clk, "dram-out", "pll-ddr", | |
| 662 | + 0x100, BIT(15), CLK_IS_CRITICAL); | |
| 663 | +static SUNXI_CCU_GATE(dram_de_fe1_clk, "dram-de-fe1", "pll-ddr", | |
| 664 | + 0x100, BIT(24), 0); | |
| 665 | +static SUNXI_CCU_GATE(dram_de_fe0_clk, "dram-de-fe0", "pll-ddr", | |
| 666 | + 0x100, BIT(25), 0); | |
| 667 | +static SUNXI_CCU_GATE(dram_de_be0_clk, "dram-de-be0", "pll-ddr", | |
| 668 | + 0x100, BIT(26), 0); | |
| 669 | +static SUNXI_CCU_GATE(dram_de_be1_clk, "dram-de-be1", "pll-ddr", | |
| 670 | + 0x100, BIT(27), 0); | |
| 671 | +static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "pll-ddr", | |
| 672 | + 0x100, BIT(28), 0); | |
| 673 | +static SUNXI_CCU_GATE(dram_ace_clk, "dram-ace", "pll-ddr", | |
| 674 | + 0x100, BIT(29), 0); | |
| 675 | + | |
| 676 | +static const char *const de_parents[] = { "pll-video0", "pll-video1", | |
| 677 | + "pll-ddr-other" }; | |
| 678 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_be0_clk, "de-be0", de_parents, | |
| 679 | + 0x104, 0, 4, 24, 2, BIT(31), 0); | |
| 680 | + | |
| 681 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_be1_clk, "de-be1", de_parents, | |
| 682 | + 0x108, 0, 4, 24, 2, BIT(31), 0); | |
| 683 | + | |
| 684 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe0_clk, "de-fe0", de_parents, | |
| 685 | + 0x10c, 0, 4, 24, 2, BIT(31), 0); | |
| 686 | + | |
| 687 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_fe1_clk, "de-fe1", de_parents, | |
| 688 | + 0x110, 0, 4, 24, 2, BIT(31), 0); | |
| 689 | + | |
| 690 | +/* Undocumented on A10 */ | |
| 691 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_mp_clk, "de-mp", de_parents, | |
| 692 | + 0x114, 0, 4, 24, 2, BIT(31), 0); | |
| 693 | + | |
| 694 | +static const char *const disp_parents[] = { "pll-video0", "pll-video1", | |
| 695 | + "pll-video0-2x", "pll-video1-2x" }; | |
| 696 | +static SUNXI_CCU_MUX_WITH_GATE(tcon0_ch0_clk, "tcon0-ch0-sclk", disp_parents, | |
| 697 | + 0x118, 24, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 698 | +static SUNXI_CCU_MUX_WITH_GATE(tcon1_ch0_clk, "tcon1-ch0-sclk", disp_parents, | |
| 699 | + 0x11c, 24, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 700 | + | |
| 701 | +static const char *const csi_sclk_parents[] = { "pll-video0", "pll-ve", | |
| 702 | + "pll-ddr-other", "pll-periph" }; | |
| 703 | + | |
| 704 | +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", | |
| 705 | + csi_sclk_parents, | |
| 706 | + 0x120, 0, 4, 24, 2, BIT(31), 0); | |
| 707 | + | |
| 708 | +/* TVD clock setup for A10 */ | |
| 709 | +static const char *const tvd_parents[] = { "pll-video0", "pll-video1" }; | |
| 710 | +static SUNXI_CCU_MUX_WITH_GATE(tvd_sun4i_clk, "tvd", tvd_parents, | |
| 711 | + 0x128, 24, 1, BIT(31), 0); | |
| 712 | + | |
| 713 | +/* TVD clock setup for A20 */ | |
| 714 | +static SUNXI_CCU_MP_WITH_MUX_GATE(tvd_sclk2_sun7i_clk, | |
| 715 | + "tvd-sclk2", tvd_parents, | |
| 716 | + 0x128, | |
| 717 | + 0, 4, /* M */ | |
| 718 | + 16, 4, /* P */ | |
| 719 | + 8, 1, /* mux */ | |
| 720 | + BIT(15), /* gate */ | |
| 721 | + 0); | |
| 722 | + | |
| 723 | +static SUNXI_CCU_M_WITH_GATE(tvd_sclk1_sun7i_clk, "tvd-sclk1", "tvd-sclk2", | |
| 724 | + 0x128, 0, 4, BIT(31), 0); | |
| 725 | + | |
| 726 | +static SUNXI_CCU_M_WITH_MUX_GATE(tcon0_ch1_sclk2_clk, "tcon0-ch1-sclk2", | |
| 727 | + disp_parents, | |
| 728 | + 0x12c, 0, 4, 24, 2, BIT(31), | |
| 729 | + CLK_SET_RATE_PARENT); | |
| 730 | + | |
| 731 | +static SUNXI_CCU_M_WITH_GATE(tcon0_ch1_clk, | |
| 732 | + "tcon0-ch1-sclk1", "tcon0-ch1-sclk2", | |
| 733 | + 0x12c, 11, 1, BIT(15), | |
| 734 | + CLK_SET_RATE_PARENT); | |
| 735 | + | |
| 736 | +static SUNXI_CCU_M_WITH_MUX_GATE(tcon1_ch1_sclk2_clk, "tcon1-ch1-sclk2", | |
| 737 | + disp_parents, | |
| 738 | + 0x130, 0, 4, 24, 2, BIT(31), | |
| 739 | + CLK_SET_RATE_PARENT); | |
| 740 | + | |
| 741 | +static SUNXI_CCU_M_WITH_GATE(tcon1_ch1_clk, | |
| 742 | + "tcon1-ch1-sclk1", "tcon1-ch1-sclk2", | |
| 743 | + 0x130, 11, 1, BIT(15), | |
| 744 | + CLK_SET_RATE_PARENT); | |
| 745 | + | |
| 746 | +static const char *const csi_parents[] = { "hosc", "pll-video0", "pll-video1", | |
| 747 | + "pll-video0-2x", "pll-video1-2x"}; | |
| 748 | +static const u8 csi_table[] = { 0, 1, 2, 5, 6}; | |
| 749 | +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi0_clk, "csi0", | |
| 750 | + csi_parents, csi_table, | |
| 751 | + 0x134, 0, 5, 24, 3, BIT(31), 0); | |
| 752 | + | |
| 753 | +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi1_clk, "csi1", | |
| 754 | + csi_parents, csi_table, | |
| 755 | + 0x138, 0, 5, 24, 3, BIT(31), 0); | |
| 756 | + | |
| 757 | +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", 0x13c, 16, 8, BIT(31), 0); | |
| 758 | + | |
| 759 | +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", | |
| 760 | + 0x140, BIT(31), CLK_SET_RATE_PARENT); | |
| 761 | + | |
| 762 | +static SUNXI_CCU_GATE(avs_clk, "avs", "hosc", 0x144, BIT(31), 0); | |
| 763 | + | |
| 764 | +static const char *const ace_parents[] = { "pll-ve", "pll-ddr-other" }; | |
| 765 | +static SUNXI_CCU_M_WITH_MUX_GATE(ace_clk, "ace", ace_parents, | |
| 766 | + 0x148, 0, 4, 24, 1, BIT(31), 0); | |
| 767 | + | |
| 768 | +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", disp_parents, | |
| 769 | + 0x150, 0, 4, 24, 2, BIT(31), | |
| 770 | + CLK_SET_RATE_PARENT); | |
| 771 | + | |
| 772 | +static const char *const gpu_parents_sun4i[] = { "pll-video0", "pll-ve", | |
| 773 | + "pll-ddr-other", | |
| 774 | + "pll-video1" }; | |
| 775 | +static SUNXI_CCU_M_WITH_MUX_GATE(gpu_sun4i_clk, "gpu", gpu_parents_sun4i, | |
| 776 | + 0x154, 0, 4, 24, 2, BIT(31), | |
| 777 | + CLK_SET_RATE_PARENT); | |
| 778 | + | |
| 779 | +static const char *const gpu_parents_sun7i[] = { "pll-video0", "pll-ve", | |
| 780 | + "pll-ddr-other", "pll-video1", | |
| 781 | + "pll-gpu" }; | |
| 782 | +static const u8 gpu_table_sun7i[] = { 0, 1, 2, 3, 4 }; | |
| 783 | +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(gpu_sun7i_clk, "gpu", | |
| 784 | + gpu_parents_sun7i, gpu_table_sun7i, | |
| 785 | + 0x154, 0, 4, 24, 3, BIT(31), | |
| 786 | + CLK_SET_RATE_PARENT); | |
| 787 | + | |
| 788 | +static const char *const mbus_sun4i_parents[] = { "hosc", "pll-periph", | |
| 789 | + "pll-ddr-other" }; | |
| 790 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun4i_clk, "mbus", mbus_sun4i_parents, | |
| 791 | + 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), | |
| 792 | + 0); | |
| 793 | +static const char *const mbus_sun7i_parents[] = { "hosc", "pll-periph-base", | |
| 794 | + "pll-ddr-other" }; | |
| 795 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_sun7i_clk, "mbus", mbus_sun7i_parents, | |
| 796 | + 0x15c, 0, 4, 16, 2, 24, 2, BIT(31), | |
| 797 | + CLK_IS_CRITICAL); | |
| 798 | + | |
| 799 | +static SUNXI_CCU_GATE(hdmi1_slow_clk, "hdmi1-slow", "hosc", 0x178, BIT(31), 0); | |
| 800 | + | |
| 801 | +static const char *const hdmi1_parents[] = { "pll-video0", "pll-video1" }; | |
| 802 | +static const u8 hdmi1_table[] = { 0, 1}; | |
| 803 | +static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(hdmi1_clk, "hdmi1", | |
| 804 | + hdmi1_parents, hdmi1_table, | |
| 805 | + 0x17c, 0, 4, 24, 2, BIT(31), | |
| 806 | + CLK_SET_RATE_PARENT); | |
| 807 | + | |
| 808 | +static const char *const out_parents[] = { "hosc", "osc32k", "hosc" }; | |
| 809 | +static const struct ccu_mux_fixed_prediv clk_out_predivs[] = { | |
| 810 | + { .index = 0, .div = 750, }, | |
| 811 | +}; | |
| 812 | + | |
| 813 | +static struct ccu_mp out_a_clk = { | |
| 814 | + .enable = BIT(31), | |
| 815 | + .m = _SUNXI_CCU_DIV(8, 5), | |
| 816 | + .p = _SUNXI_CCU_DIV(20, 2), | |
| 817 | + .mux = { | |
| 818 | + .shift = 24, | |
| 819 | + .width = 2, | |
| 820 | + .fixed_predivs = clk_out_predivs, | |
| 821 | + .n_predivs = ARRAY_SIZE(clk_out_predivs), | |
| 822 | + }, | |
| 823 | + .common = { | |
| 824 | + .reg = 0x1f0, | |
| 825 | + .features = CCU_FEATURE_FIXED_PREDIV, | |
| 826 | + .hw.init = CLK_HW_INIT_PARENTS("out-a", | |
| 827 | + out_parents, | |
| 828 | + &ccu_mp_ops, | |
| 829 | + 0), | |
| 830 | + }, | |
| 831 | +}; | |
| 832 | +static struct ccu_mp out_b_clk = { | |
| 833 | + .enable = BIT(31), | |
| 834 | + .m = _SUNXI_CCU_DIV(8, 5), | |
| 835 | + .p = _SUNXI_CCU_DIV(20, 2), | |
| 836 | + .mux = { | |
| 837 | + .shift = 24, | |
| 838 | + .width = 2, | |
| 839 | + .fixed_predivs = clk_out_predivs, | |
| 840 | + .n_predivs = ARRAY_SIZE(clk_out_predivs), | |
| 841 | + }, | |
| 842 | + .common = { | |
| 843 | + .reg = 0x1f4, | |
| 844 | + .features = CCU_FEATURE_FIXED_PREDIV, | |
| 845 | + .hw.init = CLK_HW_INIT_PARENTS("out-b", | |
| 846 | + out_parents, | |
| 847 | + &ccu_mp_ops, | |
| 848 | + 0), | |
| 849 | + }, | |
| 850 | +}; | |
| 851 | + | |
| 852 | +static struct ccu_common *sun4i_sun7i_ccu_clks[] = { | |
| 853 | + &hosc_clk.common, | |
| 854 | + &pll_core_clk.common, | |
| 855 | + &pll_audio_base_clk.common, | |
| 856 | + &pll_video0_clk.common, | |
| 857 | + &pll_ve_sun4i_clk.common, | |
| 858 | + &pll_ve_sun7i_clk.common, | |
| 859 | + &pll_ddr_base_clk.common, | |
| 860 | + &pll_ddr_clk.common, | |
| 861 | + &pll_ddr_other_clk.common, | |
| 862 | + &pll_periph_base_clk.common, | |
| 863 | + &pll_periph_sata_clk.common, | |
| 864 | + &pll_video1_clk.common, | |
| 865 | + &pll_gpu_clk.common, | |
| 866 | + &cpu_clk.common, | |
| 867 | + &axi_clk.common, | |
| 868 | + &axi_dram_clk.common, | |
| 869 | + &ahb_sun4i_clk.common, | |
| 870 | + &ahb_sun7i_clk.common, | |
| 871 | + &apb0_clk.common, | |
| 872 | + &apb1_clk.common, | |
| 873 | + &ahb_otg_clk.common, | |
| 874 | + &ahb_ehci0_clk.common, | |
| 875 | + &ahb_ohci0_clk.common, | |
| 876 | + &ahb_ehci1_clk.common, | |
| 877 | + &ahb_ohci1_clk.common, | |
| 878 | + &ahb_ss_clk.common, | |
| 879 | + &ahb_dma_clk.common, | |
| 880 | + &ahb_bist_clk.common, | |
| 881 | + &ahb_mmc0_clk.common, | |
| 882 | + &ahb_mmc1_clk.common, | |
| 883 | + &ahb_mmc2_clk.common, | |
| 884 | + &ahb_mmc3_clk.common, | |
| 885 | + &ahb_ms_clk.common, | |
| 886 | + &ahb_nand_clk.common, | |
| 887 | + &ahb_sdram_clk.common, | |
| 888 | + &ahb_ace_clk.common, | |
| 889 | + &ahb_emac_clk.common, | |
| 890 | + &ahb_ts_clk.common, | |
| 891 | + &ahb_spi0_clk.common, | |
| 892 | + &ahb_spi1_clk.common, | |
| 893 | + &ahb_spi2_clk.common, | |
| 894 | + &ahb_spi3_clk.common, | |
| 895 | + &ahb_pata_clk.common, | |
| 896 | + &ahb_sata_clk.common, | |
| 897 | + &ahb_gps_clk.common, | |
| 898 | + &ahb_hstimer_clk.common, | |
| 899 | + &ahb_ve_clk.common, | |
| 900 | + &ahb_tvd_clk.common, | |
| 901 | + &ahb_tve0_clk.common, | |
| 902 | + &ahb_tve1_clk.common, | |
| 903 | + &ahb_lcd0_clk.common, | |
| 904 | + &ahb_lcd1_clk.common, | |
| 905 | + &ahb_csi0_clk.common, | |
| 906 | + &ahb_csi1_clk.common, | |
| 907 | + &ahb_hdmi1_clk.common, | |
| 908 | + &ahb_hdmi0_clk.common, | |
| 909 | + &ahb_de_be0_clk.common, | |
| 910 | + &ahb_de_be1_clk.common, | |
| 911 | + &ahb_de_fe0_clk.common, | |
| 912 | + &ahb_de_fe1_clk.common, | |
| 913 | + &ahb_gmac_clk.common, | |
| 914 | + &ahb_mp_clk.common, | |
| 915 | + &ahb_gpu_clk.common, | |
| 916 | + &apb0_codec_clk.common, | |
| 917 | + &apb0_spdif_clk.common, | |
| 918 | + &apb0_ac97_clk.common, | |
| 919 | + &apb0_i2s0_clk.common, | |
| 920 | + &apb0_i2s1_clk.common, | |
| 921 | + &apb0_pio_clk.common, | |
| 922 | + &apb0_ir0_clk.common, | |
| 923 | + &apb0_ir1_clk.common, | |
| 924 | + &apb0_i2s2_clk.common, | |
| 925 | + &apb0_keypad_clk.common, | |
| 926 | + &apb1_i2c0_clk.common, | |
| 927 | + &apb1_i2c1_clk.common, | |
| 928 | + &apb1_i2c2_clk.common, | |
| 929 | + &apb1_i2c3_clk.common, | |
| 930 | + &apb1_can_clk.common, | |
| 931 | + &apb1_scr_clk.common, | |
| 932 | + &apb1_ps20_clk.common, | |
| 933 | + &apb1_ps21_clk.common, | |
| 934 | + &apb1_i2c4_clk.common, | |
| 935 | + &apb1_uart0_clk.common, | |
| 936 | + &apb1_uart1_clk.common, | |
| 937 | + &apb1_uart2_clk.common, | |
| 938 | + &apb1_uart3_clk.common, | |
| 939 | + &apb1_uart4_clk.common, | |
| 940 | + &apb1_uart5_clk.common, | |
| 941 | + &apb1_uart6_clk.common, | |
| 942 | + &apb1_uart7_clk.common, | |
| 943 | + &nand_clk.common, | |
| 944 | + &ms_clk.common, | |
| 945 | + &mmc0_clk.common, | |
| 946 | + &mmc0_output_clk.common, | |
| 947 | + &mmc0_sample_clk.common, | |
| 948 | + &mmc1_clk.common, | |
| 949 | + &mmc1_output_clk.common, | |
| 950 | + &mmc1_sample_clk.common, | |
| 951 | + &mmc2_clk.common, | |
| 952 | + &mmc2_output_clk.common, | |
| 953 | + &mmc2_sample_clk.common, | |
| 954 | + &mmc3_clk.common, | |
| 955 | + &mmc3_output_clk.common, | |
| 956 | + &mmc3_sample_clk.common, | |
| 957 | + &ts_clk.common, | |
| 958 | + &ss_clk.common, | |
| 959 | + &spi0_clk.common, | |
| 960 | + &spi1_clk.common, | |
| 961 | + &spi2_clk.common, | |
| 962 | + &pata_clk.common, | |
| 963 | + &ir0_sun4i_clk.common, | |
| 964 | + &ir1_sun4i_clk.common, | |
| 965 | + &ir0_sun7i_clk.common, | |
| 966 | + &ir1_sun7i_clk.common, | |
| 967 | + &i2s0_clk.common, | |
| 968 | + &ac97_clk.common, | |
| 969 | + &spdif_clk.common, | |
| 970 | + &keypad_clk.common, | |
| 971 | + &sata_clk.common, | |
| 972 | + &usb_ohci0_clk.common, | |
| 973 | + &usb_ohci1_clk.common, | |
| 974 | + &usb_phy_clk.common, | |
| 975 | + &spi3_clk.common, | |
| 976 | + &i2s1_clk.common, | |
| 977 | + &i2s2_clk.common, | |
| 978 | + &dram_ve_clk.common, | |
| 979 | + &dram_csi0_clk.common, | |
| 980 | + &dram_csi1_clk.common, | |
| 981 | + &dram_ts_clk.common, | |
| 982 | + &dram_tvd_clk.common, | |
| 983 | + &dram_tve0_clk.common, | |
| 984 | + &dram_tve1_clk.common, | |
| 985 | + &dram_out_clk.common, | |
| 986 | + &dram_de_fe1_clk.common, | |
| 987 | + &dram_de_fe0_clk.common, | |
| 988 | + &dram_de_be0_clk.common, | |
| 989 | + &dram_de_be1_clk.common, | |
| 990 | + &dram_mp_clk.common, | |
| 991 | + &dram_ace_clk.common, | |
| 992 | + &de_be0_clk.common, | |
| 993 | + &de_be1_clk.common, | |
| 994 | + &de_fe0_clk.common, | |
| 995 | + &de_fe1_clk.common, | |
| 996 | + &de_mp_clk.common, | |
| 997 | + &tcon0_ch0_clk.common, | |
| 998 | + &tcon1_ch0_clk.common, | |
| 999 | + &csi_sclk_clk.common, | |
| 1000 | + &tvd_sun4i_clk.common, | |
| 1001 | + &tvd_sclk1_sun7i_clk.common, | |
| 1002 | + &tvd_sclk2_sun7i_clk.common, | |
| 1003 | + &tcon0_ch1_sclk2_clk.common, | |
| 1004 | + &tcon0_ch1_clk.common, | |
| 1005 | + &tcon1_ch1_sclk2_clk.common, | |
| 1006 | + &tcon1_ch1_clk.common, | |
| 1007 | + &csi0_clk.common, | |
| 1008 | + &csi1_clk.common, | |
| 1009 | + &ve_clk.common, | |
| 1010 | + &codec_clk.common, | |
| 1011 | + &avs_clk.common, | |
| 1012 | + &ace_clk.common, | |
| 1013 | + &hdmi_clk.common, | |
| 1014 | + &gpu_sun4i_clk.common, | |
| 1015 | + &gpu_sun7i_clk.common, | |
| 1016 | + &mbus_sun4i_clk.common, | |
| 1017 | + &mbus_sun7i_clk.common, | |
| 1018 | + &hdmi1_slow_clk.common, | |
| 1019 | + &hdmi1_clk.common, | |
| 1020 | + &out_a_clk.common, | |
| 1021 | + &out_b_clk.common | |
| 1022 | +}; | |
| 1023 | + | |
| 1024 | +/* Post-divider for pll-audio is hardcoded to 4 */ | |
| 1025 | +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", | |
| 1026 | + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); | |
| 1027 | +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", | |
| 1028 | + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); | |
| 1029 | +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", | |
| 1030 | + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); | |
| 1031 | +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", | |
| 1032 | + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); | |
| 1033 | +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", | |
| 1034 | + "pll-video0", 1, 2, CLK_SET_RATE_PARENT); | |
| 1035 | +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", | |
| 1036 | + "pll-video1", 1, 2, CLK_SET_RATE_PARENT); | |
| 1037 | + | |
| 1038 | + | |
| 1039 | +static struct clk_hw_onecell_data sun4i_a10_hw_clks = { | |
| 1040 | + .hws = { | |
| 1041 | + [CLK_HOSC] = &hosc_clk.common.hw, | |
| 1042 | + [CLK_PLL_CORE] = &pll_core_clk.common.hw, | |
| 1043 | + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | |
| 1044 | + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | |
| 1045 | + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | |
| 1046 | + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | |
| 1047 | + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | |
| 1048 | + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | |
| 1049 | + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | |
| 1050 | + [CLK_PLL_VE] = &pll_ve_sun4i_clk.common.hw, | |
| 1051 | + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, | |
| 1052 | + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, | |
| 1053 | + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, | |
| 1054 | + [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, | |
| 1055 | + [CLK_PLL_PERIPH] = &pll_periph_clk.hw, | |
| 1056 | + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, | |
| 1057 | + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | |
| 1058 | + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | |
| 1059 | + [CLK_CPU] = &cpu_clk.common.hw, | |
| 1060 | + [CLK_AXI] = &axi_clk.common.hw, | |
| 1061 | + [CLK_AXI_DRAM] = &axi_dram_clk.common.hw, | |
| 1062 | + [CLK_AHB] = &ahb_sun4i_clk.common.hw, | |
| 1063 | + [CLK_APB0] = &apb0_clk.common.hw, | |
| 1064 | + [CLK_APB1] = &apb1_clk.common.hw, | |
| 1065 | + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, | |
| 1066 | + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, | |
| 1067 | + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, | |
| 1068 | + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, | |
| 1069 | + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, | |
| 1070 | + [CLK_AHB_SS] = &ahb_ss_clk.common.hw, | |
| 1071 | + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, | |
| 1072 | + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, | |
| 1073 | + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, | |
| 1074 | + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, | |
| 1075 | + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, | |
| 1076 | + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, | |
| 1077 | + [CLK_AHB_MS] = &ahb_ms_clk.common.hw, | |
| 1078 | + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, | |
| 1079 | + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, | |
| 1080 | + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, | |
| 1081 | + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, | |
| 1082 | + [CLK_AHB_TS] = &ahb_ts_clk.common.hw, | |
| 1083 | + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, | |
| 1084 | + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, | |
| 1085 | + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, | |
| 1086 | + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, | |
| 1087 | + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, | |
| 1088 | + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, | |
| 1089 | + [CLK_AHB_GPS] = &ahb_gps_clk.common.hw, | |
| 1090 | + [CLK_AHB_VE] = &ahb_ve_clk.common.hw, | |
| 1091 | + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, | |
| 1092 | + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, | |
| 1093 | + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, | |
| 1094 | + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, | |
| 1095 | + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, | |
| 1096 | + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, | |
| 1097 | + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, | |
| 1098 | + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, | |
| 1099 | + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, | |
| 1100 | + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, | |
| 1101 | + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, | |
| 1102 | + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, | |
| 1103 | + [CLK_AHB_MP] = &ahb_mp_clk.common.hw, | |
| 1104 | + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, | |
| 1105 | + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, | |
| 1106 | + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, | |
| 1107 | + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, | |
| 1108 | + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, | |
| 1109 | + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | |
| 1110 | + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, | |
| 1111 | + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, | |
| 1112 | + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, | |
| 1113 | + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, | |
| 1114 | + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, | |
| 1115 | + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, | |
| 1116 | + [CLK_APB1_CAN] = &apb1_can_clk.common.hw, | |
| 1117 | + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, | |
| 1118 | + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, | |
| 1119 | + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, | |
| 1120 | + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, | |
| 1121 | + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, | |
| 1122 | + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, | |
| 1123 | + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, | |
| 1124 | + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, | |
| 1125 | + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, | |
| 1126 | + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, | |
| 1127 | + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, | |
| 1128 | + [CLK_NAND] = &nand_clk.common.hw, | |
| 1129 | + [CLK_MS] = &ms_clk.common.hw, | |
| 1130 | + [CLK_MMC0] = &mmc0_clk.common.hw, | |
| 1131 | + [CLK_MMC1] = &mmc1_clk.common.hw, | |
| 1132 | + [CLK_MMC2] = &mmc2_clk.common.hw, | |
| 1133 | + [CLK_MMC3] = &mmc3_clk.common.hw, | |
| 1134 | + [CLK_TS] = &ts_clk.common.hw, | |
| 1135 | + [CLK_SS] = &ss_clk.common.hw, | |
| 1136 | + [CLK_SPI0] = &spi0_clk.common.hw, | |
| 1137 | + [CLK_SPI1] = &spi1_clk.common.hw, | |
| 1138 | + [CLK_SPI2] = &spi2_clk.common.hw, | |
| 1139 | + [CLK_PATA] = &pata_clk.common.hw, | |
| 1140 | + [CLK_IR0] = &ir0_sun4i_clk.common.hw, | |
| 1141 | + [CLK_IR1] = &ir1_sun4i_clk.common.hw, | |
| 1142 | + [CLK_I2S0] = &i2s0_clk.common.hw, | |
| 1143 | + [CLK_AC97] = &ac97_clk.common.hw, | |
| 1144 | + [CLK_SPDIF] = &spdif_clk.common.hw, | |
| 1145 | + [CLK_KEYPAD] = &keypad_clk.common.hw, | |
| 1146 | + [CLK_SATA] = &sata_clk.common.hw, | |
| 1147 | + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | |
| 1148 | + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | |
| 1149 | + [CLK_USB_PHY] = &usb_phy_clk.common.hw, | |
| 1150 | + /* CLK_GPS is unimplemented */ | |
| 1151 | + [CLK_SPI3] = &spi3_clk.common.hw, | |
| 1152 | + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | |
| 1153 | + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | |
| 1154 | + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | |
| 1155 | + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | |
| 1156 | + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | |
| 1157 | + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, | |
| 1158 | + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, | |
| 1159 | + [CLK_DRAM_OUT] = &dram_out_clk.common.hw, | |
| 1160 | + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, | |
| 1161 | + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, | |
| 1162 | + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, | |
| 1163 | + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, | |
| 1164 | + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | |
| 1165 | + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, | |
| 1166 | + [CLK_DE_BE0] = &de_be0_clk.common.hw, | |
| 1167 | + [CLK_DE_BE1] = &de_be1_clk.common.hw, | |
| 1168 | + [CLK_DE_FE0] = &de_fe0_clk.common.hw, | |
| 1169 | + [CLK_DE_FE1] = &de_fe1_clk.common.hw, | |
| 1170 | + [CLK_DE_MP] = &de_mp_clk.common.hw, | |
| 1171 | + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, | |
| 1172 | + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, | |
| 1173 | + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | |
| 1174 | + [CLK_TVD] = &tvd_sun4i_clk.common.hw, | |
| 1175 | + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, | |
| 1176 | + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, | |
| 1177 | + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, | |
| 1178 | + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, | |
| 1179 | + [CLK_CSI0] = &csi0_clk.common.hw, | |
| 1180 | + [CLK_CSI1] = &csi1_clk.common.hw, | |
| 1181 | + [CLK_VE] = &ve_clk.common.hw, | |
| 1182 | + [CLK_CODEC] = &codec_clk.common.hw, | |
| 1183 | + [CLK_AVS] = &avs_clk.common.hw, | |
| 1184 | + [CLK_ACE] = &ace_clk.common.hw, | |
| 1185 | + [CLK_HDMI] = &hdmi_clk.common.hw, | |
| 1186 | + [CLK_GPU] = &gpu_sun7i_clk.common.hw, | |
| 1187 | + [CLK_MBUS] = &mbus_sun4i_clk.common.hw, | |
| 1188 | + }, | |
| 1189 | + .num = CLK_NUMBER_SUN4I, | |
| 1190 | +}; | |
| 1191 | +static struct clk_hw_onecell_data sun7i_a20_hw_clks = { | |
| 1192 | + .hws = { | |
| 1193 | + [CLK_HOSC] = &hosc_clk.common.hw, | |
| 1194 | + [CLK_PLL_CORE] = &pll_core_clk.common.hw, | |
| 1195 | + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | |
| 1196 | + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | |
| 1197 | + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | |
| 1198 | + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | |
| 1199 | + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | |
| 1200 | + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | |
| 1201 | + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | |
| 1202 | + [CLK_PLL_VE] = &pll_ve_sun7i_clk.common.hw, | |
| 1203 | + [CLK_PLL_DDR_BASE] = &pll_ddr_base_clk.common.hw, | |
| 1204 | + [CLK_PLL_DDR] = &pll_ddr_clk.common.hw, | |
| 1205 | + [CLK_PLL_DDR_OTHER] = &pll_ddr_other_clk.common.hw, | |
| 1206 | + [CLK_PLL_PERIPH_BASE] = &pll_periph_base_clk.common.hw, | |
| 1207 | + [CLK_PLL_PERIPH] = &pll_periph_clk.hw, | |
| 1208 | + [CLK_PLL_PERIPH_SATA] = &pll_periph_sata_clk.common.hw, | |
| 1209 | + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | |
| 1210 | + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | |
| 1211 | + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, | |
| 1212 | + [CLK_CPU] = &cpu_clk.common.hw, | |
| 1213 | + [CLK_AXI] = &axi_clk.common.hw, | |
| 1214 | + [CLK_AHB] = &ahb_sun7i_clk.common.hw, | |
| 1215 | + [CLK_APB0] = &apb0_clk.common.hw, | |
| 1216 | + [CLK_APB1] = &apb1_clk.common.hw, | |
| 1217 | + [CLK_AHB_OTG] = &ahb_otg_clk.common.hw, | |
| 1218 | + [CLK_AHB_EHCI0] = &ahb_ehci0_clk.common.hw, | |
| 1219 | + [CLK_AHB_OHCI0] = &ahb_ohci0_clk.common.hw, | |
| 1220 | + [CLK_AHB_EHCI1] = &ahb_ehci1_clk.common.hw, | |
| 1221 | + [CLK_AHB_OHCI1] = &ahb_ohci1_clk.common.hw, | |
| 1222 | + [CLK_AHB_SS] = &ahb_ss_clk.common.hw, | |
| 1223 | + [CLK_AHB_DMA] = &ahb_dma_clk.common.hw, | |
| 1224 | + [CLK_AHB_BIST] = &ahb_bist_clk.common.hw, | |
| 1225 | + [CLK_AHB_MMC0] = &ahb_mmc0_clk.common.hw, | |
| 1226 | + [CLK_AHB_MMC1] = &ahb_mmc1_clk.common.hw, | |
| 1227 | + [CLK_AHB_MMC2] = &ahb_mmc2_clk.common.hw, | |
| 1228 | + [CLK_AHB_MMC3] = &ahb_mmc3_clk.common.hw, | |
| 1229 | + [CLK_AHB_MS] = &ahb_ms_clk.common.hw, | |
| 1230 | + [CLK_AHB_NAND] = &ahb_nand_clk.common.hw, | |
| 1231 | + [CLK_AHB_SDRAM] = &ahb_sdram_clk.common.hw, | |
| 1232 | + [CLK_AHB_ACE] = &ahb_ace_clk.common.hw, | |
| 1233 | + [CLK_AHB_EMAC] = &ahb_emac_clk.common.hw, | |
| 1234 | + [CLK_AHB_TS] = &ahb_ts_clk.common.hw, | |
| 1235 | + [CLK_AHB_SPI0] = &ahb_spi0_clk.common.hw, | |
| 1236 | + [CLK_AHB_SPI1] = &ahb_spi1_clk.common.hw, | |
| 1237 | + [CLK_AHB_SPI2] = &ahb_spi2_clk.common.hw, | |
| 1238 | + [CLK_AHB_SPI3] = &ahb_spi3_clk.common.hw, | |
| 1239 | + [CLK_AHB_PATA] = &ahb_pata_clk.common.hw, | |
| 1240 | + [CLK_AHB_SATA] = &ahb_sata_clk.common.hw, | |
| 1241 | + [CLK_AHB_HSTIMER] = &ahb_hstimer_clk.common.hw, | |
| 1242 | + [CLK_AHB_VE] = &ahb_ve_clk.common.hw, | |
| 1243 | + [CLK_AHB_TVD] = &ahb_tvd_clk.common.hw, | |
| 1244 | + [CLK_AHB_TVE0] = &ahb_tve0_clk.common.hw, | |
| 1245 | + [CLK_AHB_TVE1] = &ahb_tve1_clk.common.hw, | |
| 1246 | + [CLK_AHB_LCD0] = &ahb_lcd0_clk.common.hw, | |
| 1247 | + [CLK_AHB_LCD1] = &ahb_lcd1_clk.common.hw, | |
| 1248 | + [CLK_AHB_CSI0] = &ahb_csi0_clk.common.hw, | |
| 1249 | + [CLK_AHB_CSI1] = &ahb_csi1_clk.common.hw, | |
| 1250 | + [CLK_AHB_HDMI1] = &ahb_hdmi1_clk.common.hw, | |
| 1251 | + [CLK_AHB_HDMI0] = &ahb_hdmi0_clk.common.hw, | |
| 1252 | + [CLK_AHB_DE_BE0] = &ahb_de_be0_clk.common.hw, | |
| 1253 | + [CLK_AHB_DE_BE1] = &ahb_de_be1_clk.common.hw, | |
| 1254 | + [CLK_AHB_DE_FE0] = &ahb_de_fe0_clk.common.hw, | |
| 1255 | + [CLK_AHB_DE_FE1] = &ahb_de_fe1_clk.common.hw, | |
| 1256 | + [CLK_AHB_GMAC] = &ahb_gmac_clk.common.hw, | |
| 1257 | + [CLK_AHB_MP] = &ahb_mp_clk.common.hw, | |
| 1258 | + [CLK_AHB_GPU] = &ahb_gpu_clk.common.hw, | |
| 1259 | + [CLK_APB0_CODEC] = &apb0_codec_clk.common.hw, | |
| 1260 | + [CLK_APB0_SPDIF] = &apb0_spdif_clk.common.hw, | |
| 1261 | + [CLK_APB0_AC97] = &apb0_ac97_clk.common.hw, | |
| 1262 | + [CLK_APB0_I2S0] = &apb0_i2s0_clk.common.hw, | |
| 1263 | + [CLK_APB0_I2S1] = &apb0_i2s1_clk.common.hw, | |
| 1264 | + [CLK_APB0_PIO] = &apb0_pio_clk.common.hw, | |
| 1265 | + [CLK_APB0_IR0] = &apb0_ir0_clk.common.hw, | |
| 1266 | + [CLK_APB0_IR1] = &apb0_ir1_clk.common.hw, | |
| 1267 | + [CLK_APB0_I2S2] = &apb0_i2s2_clk.common.hw, | |
| 1268 | + [CLK_APB0_KEYPAD] = &apb0_keypad_clk.common.hw, | |
| 1269 | + [CLK_APB1_I2C0] = &apb1_i2c0_clk.common.hw, | |
| 1270 | + [CLK_APB1_I2C1] = &apb1_i2c1_clk.common.hw, | |
| 1271 | + [CLK_APB1_I2C2] = &apb1_i2c2_clk.common.hw, | |
| 1272 | + [CLK_APB1_I2C3] = &apb1_i2c3_clk.common.hw, | |
| 1273 | + [CLK_APB1_CAN] = &apb1_can_clk.common.hw, | |
| 1274 | + [CLK_APB1_SCR] = &apb1_scr_clk.common.hw, | |
| 1275 | + [CLK_APB1_PS20] = &apb1_ps20_clk.common.hw, | |
| 1276 | + [CLK_APB1_PS21] = &apb1_ps21_clk.common.hw, | |
| 1277 | + [CLK_APB1_I2C4] = &apb1_i2c4_clk.common.hw, | |
| 1278 | + [CLK_APB1_UART0] = &apb1_uart0_clk.common.hw, | |
| 1279 | + [CLK_APB1_UART1] = &apb1_uart1_clk.common.hw, | |
| 1280 | + [CLK_APB1_UART2] = &apb1_uart2_clk.common.hw, | |
| 1281 | + [CLK_APB1_UART3] = &apb1_uart3_clk.common.hw, | |
| 1282 | + [CLK_APB1_UART4] = &apb1_uart4_clk.common.hw, | |
| 1283 | + [CLK_APB1_UART5] = &apb1_uart5_clk.common.hw, | |
| 1284 | + [CLK_APB1_UART6] = &apb1_uart6_clk.common.hw, | |
| 1285 | + [CLK_APB1_UART7] = &apb1_uart7_clk.common.hw, | |
| 1286 | + [CLK_NAND] = &nand_clk.common.hw, | |
| 1287 | + [CLK_MS] = &ms_clk.common.hw, | |
| 1288 | + [CLK_MMC0] = &mmc0_clk.common.hw, | |
| 1289 | + [CLK_MMC0_OUTPUT] = &mmc0_output_clk.common.hw, | |
| 1290 | + [CLK_MMC0_SAMPLE] = &mmc0_sample_clk.common.hw, | |
| 1291 | + [CLK_MMC1] = &mmc1_clk.common.hw, | |
| 1292 | + [CLK_MMC1_OUTPUT] = &mmc1_output_clk.common.hw, | |
| 1293 | + [CLK_MMC1_SAMPLE] = &mmc1_sample_clk.common.hw, | |
| 1294 | + [CLK_MMC2] = &mmc2_clk.common.hw, | |
| 1295 | + [CLK_MMC2_OUTPUT] = &mmc2_output_clk.common.hw, | |
| 1296 | + [CLK_MMC2_SAMPLE] = &mmc2_sample_clk.common.hw, | |
| 1297 | + [CLK_MMC3] = &mmc3_clk.common.hw, | |
| 1298 | + [CLK_MMC3_OUTPUT] = &mmc3_output_clk.common.hw, | |
| 1299 | + [CLK_MMC3_SAMPLE] = &mmc3_sample_clk.common.hw, | |
| 1300 | + [CLK_TS] = &ts_clk.common.hw, | |
| 1301 | + [CLK_SS] = &ss_clk.common.hw, | |
| 1302 | + [CLK_SPI0] = &spi0_clk.common.hw, | |
| 1303 | + [CLK_SPI1] = &spi1_clk.common.hw, | |
| 1304 | + [CLK_SPI2] = &spi2_clk.common.hw, | |
| 1305 | + [CLK_PATA] = &pata_clk.common.hw, | |
| 1306 | + [CLK_IR0] = &ir0_sun7i_clk.common.hw, | |
| 1307 | + [CLK_IR1] = &ir1_sun7i_clk.common.hw, | |
| 1308 | + [CLK_I2S0] = &i2s0_clk.common.hw, | |
| 1309 | + [CLK_AC97] = &ac97_clk.common.hw, | |
| 1310 | + [CLK_SPDIF] = &spdif_clk.common.hw, | |
| 1311 | + [CLK_KEYPAD] = &keypad_clk.common.hw, | |
| 1312 | + [CLK_SATA] = &sata_clk.common.hw, | |
| 1313 | + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | |
| 1314 | + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | |
| 1315 | + [CLK_USB_PHY] = &usb_phy_clk.common.hw, | |
| 1316 | + /* CLK_GPS is unimplemented */ | |
| 1317 | + [CLK_SPI3] = &spi3_clk.common.hw, | |
| 1318 | + [CLK_I2S1] = &i2s1_clk.common.hw, | |
| 1319 | + [CLK_I2S2] = &i2s2_clk.common.hw, | |
| 1320 | + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | |
| 1321 | + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | |
| 1322 | + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | |
| 1323 | + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | |
| 1324 | + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | |
| 1325 | + [CLK_DRAM_TVE0] = &dram_tve0_clk.common.hw, | |
| 1326 | + [CLK_DRAM_TVE1] = &dram_tve1_clk.common.hw, | |
| 1327 | + [CLK_DRAM_OUT] = &dram_out_clk.common.hw, | |
| 1328 | + [CLK_DRAM_DE_FE1] = &dram_de_fe1_clk.common.hw, | |
| 1329 | + [CLK_DRAM_DE_FE0] = &dram_de_fe0_clk.common.hw, | |
| 1330 | + [CLK_DRAM_DE_BE0] = &dram_de_be0_clk.common.hw, | |
| 1331 | + [CLK_DRAM_DE_BE1] = &dram_de_be1_clk.common.hw, | |
| 1332 | + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | |
| 1333 | + [CLK_DRAM_ACE] = &dram_ace_clk.common.hw, | |
| 1334 | + [CLK_DE_BE0] = &de_be0_clk.common.hw, | |
| 1335 | + [CLK_DE_BE1] = &de_be1_clk.common.hw, | |
| 1336 | + [CLK_DE_FE0] = &de_fe0_clk.common.hw, | |
| 1337 | + [CLK_DE_FE1] = &de_fe1_clk.common.hw, | |
| 1338 | + [CLK_DE_MP] = &de_mp_clk.common.hw, | |
| 1339 | + [CLK_TCON0_CH0] = &tcon0_ch0_clk.common.hw, | |
| 1340 | + [CLK_TCON1_CH0] = &tcon1_ch0_clk.common.hw, | |
| 1341 | + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | |
| 1342 | + [CLK_TVD_SCLK2] = &tvd_sclk2_sun7i_clk.common.hw, | |
| 1343 | + [CLK_TVD] = &tvd_sclk1_sun7i_clk.common.hw, | |
| 1344 | + [CLK_TCON0_CH1_SCLK2] = &tcon0_ch1_sclk2_clk.common.hw, | |
| 1345 | + [CLK_TCON0_CH1] = &tcon0_ch1_clk.common.hw, | |
| 1346 | + [CLK_TCON1_CH1_SCLK2] = &tcon1_ch1_sclk2_clk.common.hw, | |
| 1347 | + [CLK_TCON1_CH1] = &tcon1_ch1_clk.common.hw, | |
| 1348 | + [CLK_CSI0] = &csi0_clk.common.hw, | |
| 1349 | + [CLK_CSI1] = &csi1_clk.common.hw, | |
| 1350 | + [CLK_VE] = &ve_clk.common.hw, | |
| 1351 | + [CLK_CODEC] = &codec_clk.common.hw, | |
| 1352 | + [CLK_AVS] = &avs_clk.common.hw, | |
| 1353 | + [CLK_ACE] = &ace_clk.common.hw, | |
| 1354 | + [CLK_HDMI] = &hdmi_clk.common.hw, | |
| 1355 | + [CLK_GPU] = &gpu_sun7i_clk.common.hw, | |
| 1356 | + [CLK_MBUS] = &mbus_sun7i_clk.common.hw, | |
| 1357 | + [CLK_HDMI1_SLOW] = &hdmi1_slow_clk.common.hw, | |
| 1358 | + [CLK_HDMI1] = &hdmi1_clk.common.hw, | |
| 1359 | + [CLK_OUT_A] = &out_a_clk.common.hw, | |
| 1360 | + [CLK_OUT_B] = &out_b_clk.common.hw, | |
| 1361 | + }, | |
| 1362 | + .num = CLK_NUMBER_SUN7I, | |
| 1363 | +}; | |
| 1364 | + | |
| 1365 | +static struct ccu_reset_map sunxi_a10_a20_ccu_resets[] = { | |
| 1366 | + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, | |
| 1367 | + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, | |
| 1368 | + [RST_USB_PHY2] = { 0x0cc, BIT(2) }, | |
| 1369 | + [RST_GPS] = { 0x0d0, BIT(0) }, | |
| 1370 | + [RST_DE_BE0] = { 0x104, BIT(30) }, | |
| 1371 | + [RST_DE_BE1] = { 0x108, BIT(30) }, | |
| 1372 | + [RST_DE_FE0] = { 0x10c, BIT(30) }, | |
| 1373 | + [RST_DE_FE1] = { 0x110, BIT(30) }, | |
| 1374 | + [RST_DE_MP] = { 0x114, BIT(30) }, | |
| 1375 | + [RST_TVE0] = { 0x118, BIT(29) }, | |
| 1376 | + [RST_TCON0] = { 0x118, BIT(30) }, | |
| 1377 | + [RST_TVE1] = { 0x11c, BIT(29) }, | |
| 1378 | + [RST_TCON1] = { 0x11c, BIT(30) }, | |
| 1379 | + [RST_CSI0] = { 0x134, BIT(30) }, | |
| 1380 | + [RST_CSI1] = { 0x138, BIT(30) }, | |
| 1381 | + [RST_VE] = { 0x13c, BIT(0) }, | |
| 1382 | + [RST_ACE] = { 0x148, BIT(16) }, | |
| 1383 | + [RST_LVDS] = { 0x14c, BIT(0) }, | |
| 1384 | + [RST_GPU] = { 0x154, BIT(30) }, | |
| 1385 | + [RST_HDMI_H] = { 0x170, BIT(0) }, | |
| 1386 | + [RST_HDMI_SYS] = { 0x170, BIT(1) }, | |
| 1387 | + [RST_HDMI_AUDIO_DMA] = { 0x170, BIT(2) }, | |
| 1388 | +}; | |
| 1389 | + | |
| 1390 | +static const struct sunxi_ccu_desc sun4i_a10_ccu_desc = { | |
| 1391 | + .ccu_clks = sun4i_sun7i_ccu_clks, | |
| 1392 | + .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), | |
| 1393 | + | |
| 1394 | + .hw_clks = &sun4i_a10_hw_clks, | |
| 1395 | + | |
| 1396 | + .resets = sunxi_a10_a20_ccu_resets, | |
| 1397 | + .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), | |
| 1398 | +}; | |
| 1399 | + | |
| 1400 | +static const struct sunxi_ccu_desc sun7i_a20_ccu_desc = { | |
| 1401 | + .ccu_clks = sun4i_sun7i_ccu_clks, | |
| 1402 | + .num_ccu_clks = ARRAY_SIZE(sun4i_sun7i_ccu_clks), | |
| 1403 | + | |
| 1404 | + .hw_clks = &sun7i_a20_hw_clks, | |
| 1405 | + | |
| 1406 | + .resets = sunxi_a10_a20_ccu_resets, | |
| 1407 | + .num_resets = ARRAY_SIZE(sunxi_a10_a20_ccu_resets), | |
| 1408 | +}; | |
| 1409 | + | |
| 1410 | +static void __init sun4i_ccu_init(struct device_node *node, | |
| 1411 | + const struct sunxi_ccu_desc *desc) | |
| 1412 | +{ | |
| 1413 | + void __iomem *reg; | |
| 1414 | + u32 val; | |
| 1415 | + | |
| 1416 | + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | |
| 1417 | + if (IS_ERR(reg)) { | |
| 1418 | + pr_err("%s: Could not map the clock registers\n", | |
| 1419 | + of_node_full_name(node)); | |
| 1420 | + return; | |
| 1421 | + } | |
| 1422 | + | |
| 1423 | + /* Force the PLL-Audio-1x divider to 4 */ | |
| 1424 | + val = readl(reg + SUN4I_PLL_AUDIO_REG); | |
| 1425 | + val &= ~GENMASK(29, 26); | |
| 1426 | + writel(val | (4 << 26), reg + SUN4I_PLL_AUDIO_REG); | |
| 1427 | + | |
| 1428 | + /* | |
| 1429 | + * Use the peripheral PLL6 as the AHB parent, instead of CPU / | |
| 1430 | + * AXI which have rate changes due to cpufreq. | |
| 1431 | + * | |
| 1432 | + * This is especially a big deal for the HS timer whose parent | |
| 1433 | + * clock is AHB. | |
| 1434 | + * | |
| 1435 | + * NB! These bits are undocumented in A10 manual. | |
| 1436 | + */ | |
| 1437 | + val = readl(reg + SUN4I_AHB_REG); | |
| 1438 | + val &= ~GENMASK(7, 6); | |
| 1439 | + writel(val | (2 << 6), reg + SUN4I_AHB_REG); | |
| 1440 | + | |
| 1441 | + sunxi_ccu_probe(node, reg, desc); | |
| 1442 | +} | |
| 1443 | + | |
| 1444 | +static void __init sun4i_a10_ccu_setup(struct device_node *node) | |
| 1445 | +{ | |
| 1446 | + sun4i_ccu_init(node, &sun4i_a10_ccu_desc); | |
| 1447 | +} | |
| 1448 | +CLK_OF_DECLARE(sun4i_a10_ccu, "allwinner,sun4i-a10-ccu", | |
| 1449 | + sun4i_a10_ccu_setup); | |
| 1450 | + | |
| 1451 | +static void __init sun7i_a20_ccu_setup(struct device_node *node) | |
| 1452 | +{ | |
| 1453 | + sun4i_ccu_init(node, &sun7i_a20_ccu_desc); | |
| 1454 | +} | |
| 1455 | +CLK_OF_DECLARE(sun7i_a20_ccu, "allwinner,sun7i-a20-ccu", | |
| 1456 | + sun7i_a20_ccu_setup); | |
| @@ -0,0 +1,61 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2017 Priit Laes | |
| 3 | + * | |
| 4 | + * Priit Laes <plaes@plaes.org> | |
| 5 | + * | |
| 6 | + * This program is free software; you can redistribute it and/or modify | |
| 7 | + * it under the terms of the GNU General Public License as published by | |
| 8 | + * the Free Software Foundation; either version 2 of the License, or | |
| 9 | + * (at your option) any later version. | |
| 10 | + * | |
| 11 | + * This program is distributed in the hope that it will be useful, | |
| 12 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 13 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 14 | + * GNU General Public License for more details. | |
| 15 | + */ | |
| 16 | + | |
| 17 | +#ifndef _CCU_SUN4I_A10_H_ | |
| 18 | +#define _CCU_SUN4I_A10_H_ | |
| 19 | + | |
| 20 | +#include <dt-bindings/clock/sun4i-a10-ccu.h> | |
| 21 | +#include <dt-bindings/clock/sun7i-a20-ccu.h> | |
| 22 | +#include <dt-bindings/reset/sun4i-a10-ccu.h> | |
| 23 | + | |
| 24 | +/* The HOSC is exported */ | |
| 25 | +#define CLK_PLL_CORE 2 | |
| 26 | +#define CLK_PLL_AUDIO_BASE 3 | |
| 27 | +#define CLK_PLL_AUDIO 4 | |
| 28 | +#define CLK_PLL_AUDIO_2X 5 | |
| 29 | +#define CLK_PLL_AUDIO_4X 6 | |
| 30 | +#define CLK_PLL_AUDIO_8X 7 | |
| 31 | +#define CLK_PLL_VIDEO0 8 | |
| 32 | +#define CLK_PLL_VIDEO0_2X 9 | |
| 33 | +#define CLK_PLL_VE 10 | |
| 34 | +#define CLK_PLL_DDR_BASE 11 | |
| 35 | +#define CLK_PLL_DDR 12 | |
| 36 | +#define CLK_PLL_DDR_OTHER 13 | |
| 37 | +#define CLK_PLL_PERIPH_BASE 14 | |
| 38 | +#define CLK_PLL_PERIPH 15 | |
| 39 | +#define CLK_PLL_PERIPH_SATA 16 | |
| 40 | +#define CLK_PLL_VIDEO1 17 | |
| 41 | +#define CLK_PLL_VIDEO1_2X 18 | |
| 42 | +#define CLK_PLL_GPU 19 | |
| 43 | + | |
| 44 | +/* The CPU clock is exported */ | |
| 45 | +#define CLK_AXI 21 | |
| 46 | +#define CLK_AXI_DRAM 22 | |
| 47 | +#define CLK_AHB 23 | |
| 48 | +#define CLK_APB0 24 | |
| 49 | +#define CLK_APB1 25 | |
| 50 | + | |
| 51 | +/* AHB gates are exported (23..68) */ | |
| 52 | +/* APB0 gates are exported (69..78) */ | |
| 53 | +/* APB1 gates are exported (79..95) */ | |
| 54 | +/* IP module clocks are exported (96..128) */ | |
| 55 | +/* DRAM gates are exported (129..142)*/ | |
| 56 | +/* Media (display engine clocks & etc) are exported (143..169) */ | |
| 57 | + | |
| 58 | +#define CLK_NUMBER_SUN4I (CLK_MBUS + 1) | |
| 59 | +#define CLK_NUMBER_SUN7I (CLK_OUT_B + 1) | |
| 60 | + | |
| 61 | +#endif /* _CCU_SUN4I_A10_H_ */ | |
| @@ -976,8 +976,7 @@ static void __init sun5i_ccu_init(struct device_node *node, · 975 unmodified lines | ||
| 976 | 976 | |
| 977 | 977 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 978 | 978 | if (IS_ERR(reg)) { |
| 979 | − pr_err("%s: Could not map the clock registers\n", | |
| 980 | − of_node_full_name(node)); | |
| 979 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 981 | 980 | return; |
| 982 | 981 | } |
| 983 | 982 | |
| @@ -1217,8 +1217,7 @@ static void __init sun6i_a31_ccu_setup(struct device_node *node) · 1216 unmodified lines | ||
| 1217 | 1217 | |
| 1218 | 1218 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 1219 | 1219 | if (IS_ERR(reg)) { |
| 1220 | − pr_err("%s: Could not map the clock registers\n", | |
| 1221 | − of_node_full_name(node)); | |
| 1220 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 1222 | 1221 | return; |
| 1223 | 1222 | } |
| 1224 | 1223 | |
| @@ -716,8 +716,7 @@ static void __init sun8i_a23_ccu_setup(struct device_node *node) · 715 unmodified lines | ||
| 716 | 716 | |
| 717 | 717 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 718 | 718 | if (IS_ERR(reg)) { |
| 719 | − pr_err("%s: Could not map the clock registers\n", | |
| 720 | − of_node_full_name(node)); | |
| 719 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 721 | 720 | return; |
| 722 | 721 | } |
| 723 | 722 | |
| @@ -777,8 +777,7 @@ static void __init sun8i_a33_ccu_setup(struct device_node *node) · 776 unmodified lines | ||
| 777 | 777 | |
| 778 | 778 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 779 | 779 | if (IS_ERR(reg)) { |
| 780 | − pr_err("%s: Could not map the clock registers\n", | |
| 781 | − of_node_full_name(node)); | |
| 780 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 782 | 781 | return; |
| 783 | 782 | } |
| 784 | 783 | |
| @@ -135,7 +135,7 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", · 134 unmodified lines | ||
| 135 | 135 | static const char * const cpux_parents[] = { "osc32k", "osc24M", |
| 136 | 136 | "pll-cpux" , "pll-cpux" }; |
| 137 | 137 | static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, |
| 138 | − 0x050, 16, 2, CLK_IS_CRITICAL); | |
| 138 | + 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); | |
| 139 | 139 | |
| 140 | 140 | static SUNXI_CCU_M(axi_clk, "axi", "cpux", 0x050, 0, 2, 0); |
| 141 | 141 | |
| @@ -1103,6 +1103,13 @@ static const struct sunxi_ccu_desc sun50i_h5_ccu_desc = { · 961 unmodified lines | ||
| 1103 | 1103 | .num_resets = ARRAY_SIZE(sun50i_h5_ccu_resets), |
| 1104 | 1104 | }; |
| 1105 | 1105 | |
| 1106 | +static struct ccu_pll_nb sun8i_h3_pll_cpu_nb = { | |
| 1107 | + .common = &pll_cpux_clk.common, | |
| 1108 | + /* copy from pll_cpux_clk */ | |
| 1109 | + .enable = BIT(31), | |
| 1110 | + .lock = BIT(28), | |
| 1111 | +}; | |
| 1112 | + | |
| 1106 | 1113 | static struct ccu_mux_nb sun8i_h3_cpu_nb = { |
| 1107 | 1114 | .common = &cpux_clk.common, |
| 1108 | 1115 | .cm = &cpux_clk.mux, |
| @@ -1118,8 +1125,7 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, · 9 unmodified lines | ||
| 1118 | 1125 | |
| 1119 | 1126 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 1120 | 1127 | if (IS_ERR(reg)) { |
| 1121 | − pr_err("%s: Could not map the clock registers\n", | |
| 1122 | − of_node_full_name(node)); | |
| 1128 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 1123 | 1129 | return; |
| 1124 | 1130 | } |
| 1125 | 1131 | |
| @@ -1130,6 +1136,10 @@ static void __init sunxi_h3_h5_ccu_init(struct device_node *node, · 4 unmodified lines | ||
| 1130 | 1136 | |
| 1131 | 1137 | sunxi_ccu_probe(node, reg, desc); |
| 1132 | 1138 | |
| 1139 | + /* Gate then ungate PLL CPU after any rate changes */ | |
| 1140 | + ccu_pll_notifier_register(&sun8i_h3_pll_cpu_nb); | |
| 1141 | + | |
| 1142 | + /* Reparent CPU during PLL CPU rate changes */ | |
| 1133 | 1143 | ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, |
| 1134 | 1144 | &sun8i_h3_cpu_nb); |
| 1135 | 1145 | } |
| @@ -290,8 +290,7 @@ static void __init sunxi_r_ccu_init(struct device_node *node, · 289 unmodified lines | ||
| 290 | 290 | |
| 291 | 291 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 292 | 292 | if (IS_ERR(reg)) { |
| 293 | − pr_err("%s: Could not map the clock registers\n", | |
| 294 | − of_node_full_name(node)); | |
| 293 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 295 | 294 | return; |
| 296 | 295 | } |
| 297 | 296 | |
| @@ -13,7 +13,7 @@ · 12 unmodified lines | ||
| 13 | 13 | */ |
| 14 | 14 | |
| 15 | 15 | #ifndef _CCU_SUN8I_R_H |
| 16 | −#define _CCU_SUN8I_R_H_ | |
| 16 | +#define _CCU_SUN8I_R_H | |
| 17 | 17 | |
| 18 | 18 | #include <dt-bindings/clock/sun8i-r-ccu.h> |
| 19 | 19 | #include <dt-bindings/reset/sun8i-r-ccu.h> |
| @@ -0,0 +1,1290 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (c) 2017 Icenowy Zheng <icenowy@aosc.io> | |
| 3 | + * | |
| 4 | + * This software is licensed under the terms of the GNU General Public | |
| 5 | + * License version 2, as published by the Free Software Foundation, and | |
| 6 | + * may be copied, distributed, and modified under those terms. | |
| 7 | + * | |
| 8 | + * This program is distributed in the hope that it will be useful, | |
| 9 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 10 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 11 | + * GNU General Public License for more details. | |
| 12 | + */ | |
| 13 | + | |
| 14 | +#include <linux/clk-provider.h> | |
| 15 | +#include <linux/of_address.h> | |
| 16 | + | |
| 17 | +#include "ccu_common.h" | |
| 18 | +#include "ccu_reset.h" | |
| 19 | + | |
| 20 | +#include "ccu_div.h" | |
| 21 | +#include "ccu_gate.h" | |
| 22 | +#include "ccu_mp.h" | |
| 23 | +#include "ccu_mult.h" | |
| 24 | +#include "ccu_nk.h" | |
| 25 | +#include "ccu_nkm.h" | |
| 26 | +#include "ccu_nkmp.h" | |
| 27 | +#include "ccu_nm.h" | |
| 28 | +#include "ccu_phase.h" | |
| 29 | + | |
| 30 | +#include "ccu-sun8i-r40.h" | |
| 31 | + | |
| 32 | +/* TODO: The result of N*K is required to be in [10, 88] range. */ | |
| 33 | +static struct ccu_nkmp pll_cpu_clk = { | |
| 34 | + .enable = BIT(31), | |
| 35 | + .lock = BIT(28), | |
| 36 | + .n = _SUNXI_CCU_MULT(8, 5), | |
| 37 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 38 | + .m = _SUNXI_CCU_DIV(0, 2), | |
| 39 | + .p = _SUNXI_CCU_DIV_MAX(16, 2, 4), | |
| 40 | + .common = { | |
| 41 | + .reg = 0x000, | |
| 42 | + .hw.init = CLK_HW_INIT("pll-cpu", | |
| 43 | + "osc24M", | |
| 44 | + &ccu_nkmp_ops, | |
| 45 | + CLK_SET_RATE_UNGATE), | |
| 46 | + }, | |
| 47 | +}; | |
| 48 | + | |
| 49 | +/* | |
| 50 | + * The Audio PLL is supposed to have 4 outputs: 3 fixed factors from | |
| 51 | + * the base (2x, 4x and 8x), and one variable divider (the one true | |
| 52 | + * pll audio). | |
| 53 | + * | |
| 54 | + * We don't have any need for the variable divider for now, so we just | |
| 55 | + * hardcode it to match with the clock names | |
| 56 | + */ | |
| 57 | +#define SUN8I_R40_PLL_AUDIO_REG 0x008 | |
| 58 | + | |
| 59 | +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_audio_base_clk, "pll-audio-base", | |
| 60 | + "osc24M", 0x008, | |
| 61 | + 8, 7, /* N */ | |
| 62 | + 0, 5, /* M */ | |
| 63 | + BIT(31), /* gate */ | |
| 64 | + BIT(28), /* lock */ | |
| 65 | + CLK_SET_RATE_UNGATE); | |
| 66 | + | |
| 67 | +/* TODO: The result of N/M is required to be in [8, 25] range. */ | |
| 68 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video0_clk, "pll-video0", | |
| 69 | + "osc24M", 0x0010, | |
| 70 | + 8, 7, /* N */ | |
| 71 | + 0, 4, /* M */ | |
| 72 | + BIT(24), /* frac enable */ | |
| 73 | + BIT(25), /* frac select */ | |
| 74 | + 270000000, /* frac rate 0 */ | |
| 75 | + 297000000, /* frac rate 1 */ | |
| 76 | + BIT(31), /* gate */ | |
| 77 | + BIT(28), /* lock */ | |
| 78 | + CLK_SET_RATE_UNGATE); | |
| 79 | + | |
| 80 | +/* TODO: The result of N/M is required to be in [8, 25] range. */ | |
| 81 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_ve_clk, "pll-ve", | |
| 82 | + "osc24M", 0x0018, | |
| 83 | + 8, 7, /* N */ | |
| 84 | + 0, 4, /* M */ | |
| 85 | + BIT(24), /* frac enable */ | |
| 86 | + BIT(25), /* frac select */ | |
| 87 | + 270000000, /* frac rate 0 */ | |
| 88 | + 297000000, /* frac rate 1 */ | |
| 89 | + BIT(31), /* gate */ | |
| 90 | + BIT(28), /* lock */ | |
| 91 | + CLK_SET_RATE_UNGATE); | |
| 92 | + | |
| 93 | +/* TODO: The result of N*K is required to be in [10, 77] range. */ | |
| 94 | +static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_ddr0_clk, "pll-ddr0", | |
| 95 | + "osc24M", 0x020, | |
| 96 | + 8, 5, /* N */ | |
| 97 | + 4, 2, /* K */ | |
| 98 | + 0, 2, /* M */ | |
| 99 | + BIT(31), /* gate */ | |
| 100 | + BIT(28), /* lock */ | |
| 101 | + CLK_SET_RATE_UNGATE); | |
| 102 | + | |
| 103 | +/* TODO: The result of N*K is required to be in [21, 58] range. */ | |
| 104 | +static struct ccu_nk pll_periph0_clk = { | |
| 105 | + .enable = BIT(31), | |
| 106 | + .lock = BIT(28), | |
| 107 | + .n = _SUNXI_CCU_MULT(8, 5), | |
| 108 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 109 | + .fixed_post_div = 2, | |
| 110 | + .common = { | |
| 111 | + .reg = 0x028, | |
| 112 | + .features = CCU_FEATURE_FIXED_POSTDIV, | |
| 113 | + .hw.init = CLK_HW_INIT("pll-periph0", "osc24M", | |
| 114 | + &ccu_nk_ops, | |
| 115 | + CLK_SET_RATE_UNGATE), | |
| 116 | + }, | |
| 117 | +}; | |
| 118 | + | |
| 119 | +static struct ccu_div pll_periph0_sata_clk = { | |
| 120 | + .enable = BIT(24), | |
| 121 | + .div = _SUNXI_CCU_DIV(0, 2), | |
| 122 | + /* | |
| 123 | + * The formula of pll-periph0 (1x) is 24MHz*N*K/2, and the formula | |
| 124 | + * of pll-periph0-sata is 24MHz*N*K/M/6, so the postdiv here is | |
| 125 | + * 6/2 = 3. | |
| 126 | + */ | |
| 127 | + .fixed_post_div = 3, | |
| 128 | + .common = { | |
| 129 | + .reg = 0x028, | |
| 130 | + .features = CCU_FEATURE_FIXED_POSTDIV, | |
| 131 | + .hw.init = CLK_HW_INIT("pll-periph0-sata", | |
| 132 | + "pll-periph0", | |
| 133 | + &ccu_div_ops, 0), | |
| 134 | + }, | |
| 135 | +}; | |
| 136 | + | |
| 137 | +/* TODO: The result of N*K is required to be in [21, 58] range. */ | |
| 138 | +static struct ccu_nk pll_periph1_clk = { | |
| 139 | + .enable = BIT(31), | |
| 140 | + .lock = BIT(28), | |
| 141 | + .n = _SUNXI_CCU_MULT(8, 5), | |
| 142 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 143 | + .fixed_post_div = 2, | |
| 144 | + .common = { | |
| 145 | + .reg = 0x02c, | |
| 146 | + .features = CCU_FEATURE_FIXED_POSTDIV, | |
| 147 | + .hw.init = CLK_HW_INIT("pll-periph1", "osc24M", | |
| 148 | + &ccu_nk_ops, | |
| 149 | + CLK_SET_RATE_UNGATE), | |
| 150 | + }, | |
| 151 | +}; | |
| 152 | + | |
| 153 | +/* TODO: The result of N/M is required to be in [8, 25] range. */ | |
| 154 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_video1_clk, "pll-video1", | |
| 155 | + "osc24M", 0x030, | |
| 156 | + 8, 7, /* N */ | |
| 157 | + 0, 4, /* M */ | |
| 158 | + BIT(24), /* frac enable */ | |
| 159 | + BIT(25), /* frac select */ | |
| 160 | + 270000000, /* frac rate 0 */ | |
| 161 | + 297000000, /* frac rate 1 */ | |
| 162 | + BIT(31), /* gate */ | |
| 163 | + BIT(28), /* lock */ | |
| 164 | + CLK_SET_RATE_UNGATE); | |
| 165 | + | |
| 166 | +static struct ccu_nkm pll_sata_clk = { | |
| 167 | + .enable = BIT(31), | |
| 168 | + .lock = BIT(28), | |
| 169 | + .n = _SUNXI_CCU_MULT(8, 5), | |
| 170 | + .k = _SUNXI_CCU_MULT(4, 2), | |
| 171 | + .m = _SUNXI_CCU_DIV(0, 2), | |
| 172 | + .fixed_post_div = 6, | |
| 173 | + .common = { | |
| 174 | + .reg = 0x034, | |
| 175 | + .features = CCU_FEATURE_FIXED_POSTDIV, | |
| 176 | + .hw.init = CLK_HW_INIT("pll-sata", "osc24M", | |
| 177 | + &ccu_nkm_ops, | |
| 178 | + CLK_SET_RATE_UNGATE), | |
| 179 | + }, | |
| 180 | +}; | |
| 181 | + | |
| 182 | +static const char * const pll_sata_out_parents[] = { "pll-sata", | |
| 183 | + "pll-periph0-sata" }; | |
| 184 | +static SUNXI_CCU_MUX_WITH_GATE(pll_sata_out_clk, "pll-sata-out", | |
| 185 | + pll_sata_out_parents, 0x034, | |
| 186 | + 30, 1, /* mux */ | |
| 187 | + BIT(14), /* gate */ | |
| 188 | + CLK_SET_RATE_PARENT); | |
| 189 | + | |
| 190 | +/* TODO: The result of N/M is required to be in [8, 25] range. */ | |
| 191 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_gpu_clk, "pll-gpu", | |
| 192 | + "osc24M", 0x038, | |
| 193 | + 8, 7, /* N */ | |
| 194 | + 0, 4, /* M */ | |
| 195 | + BIT(24), /* frac enable */ | |
| 196 | + BIT(25), /* frac select */ | |
| 197 | + 270000000, /* frac rate 0 */ | |
| 198 | + 297000000, /* frac rate 1 */ | |
| 199 | + BIT(31), /* gate */ | |
| 200 | + BIT(28), /* lock */ | |
| 201 | + CLK_SET_RATE_UNGATE); | |
| 202 | + | |
| 203 | +/* | |
| 204 | + * The MIPI PLL has 2 modes: "MIPI" and "HDMI". | |
| 205 | + * | |
| 206 | + * The MIPI mode is a standard NKM-style clock. The HDMI mode is an | |
| 207 | + * integer / fractional clock with switchable multipliers and dividers. | |
| 208 | + * This is not supported here. We hardcode the PLL to MIPI mode. | |
| 209 | + * | |
| 210 | + * TODO: In the MIPI mode, M/N is required to be equal or lesser than 3, | |
| 211 | + * which cannot be implemented now. | |
| 212 | + */ | |
| 213 | +#define SUN8I_R40_PLL_MIPI_REG 0x040 | |
| 214 | + | |
| 215 | +static const char * const pll_mipi_parents[] = { "pll-video0" }; | |
| 216 | +static struct ccu_nkm pll_mipi_clk = { | |
| 217 | + .enable = BIT(31) | BIT(23) | BIT(22), | |
| 218 | + .lock = BIT(28), | |
| 219 | + .n = _SUNXI_CCU_MULT(8, 4), | |
| 220 | + .k = _SUNXI_CCU_MULT_MIN(4, 2, 2), | |
| 221 | + .m = _SUNXI_CCU_DIV(0, 4), | |
| 222 | + .mux = _SUNXI_CCU_MUX(21, 1), | |
| 223 | + .common = { | |
| 224 | + .reg = 0x040, | |
| 225 | + .hw.init = CLK_HW_INIT_PARENTS("pll-mipi", | |
| 226 | + pll_mipi_parents, | |
| 227 | + &ccu_nkm_ops, | |
| 228 | + CLK_SET_RATE_UNGATE) | |
| 229 | + }, | |
| 230 | +}; | |
| 231 | + | |
| 232 | +/* TODO: The result of N/M is required to be in [8, 25] range. */ | |
| 233 | +static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de", | |
| 234 | + "osc24M", 0x048, | |
| 235 | + 8, 7, /* N */ | |
| 236 | + 0, 4, /* M */ | |
| 237 | + BIT(24), /* frac enable */ | |
| 238 | + BIT(25), /* frac select */ | |
| 239 | + 270000000, /* frac rate 0 */ | |
| 240 | + 297000000, /* frac rate 1 */ | |
| 241 | + BIT(31), /* gate */ | |
| 242 | + BIT(28), /* lock */ | |
| 243 | + CLK_SET_RATE_UNGATE); | |
| 244 | + | |
| 245 | +/* TODO: The N factor is required to be in [16, 75] range. */ | |
| 246 | +static SUNXI_CCU_NM_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1", | |
| 247 | + "osc24M", 0x04c, | |
| 248 | + 8, 7, /* N */ | |
| 249 | + 0, 2, /* M */ | |
| 250 | + BIT(31), /* gate */ | |
| 251 | + BIT(28), /* lock */ | |
| 252 | + CLK_SET_RATE_UNGATE); | |
| 253 | + | |
| 254 | +static const char * const cpu_parents[] = { "osc32k", "osc24M", | |
| 255 | + "pll-cpu", "pll-cpu" }; | |
| 256 | +static SUNXI_CCU_MUX(cpu_clk, "cpu", cpu_parents, | |
| 257 | + 0x050, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT); | |
| 258 | + | |
| 259 | +static SUNXI_CCU_M(axi_clk, "axi", "cpu", 0x050, 0, 2, 0); | |
| 260 | + | |
| 261 | +static const char * const ahb1_parents[] = { "osc32k", "osc24M", | |
| 262 | + "axi", "pll-periph0" }; | |
| 263 | +static const struct ccu_mux_var_prediv ahb1_predivs[] = { | |
| 264 | + { .index = 3, .shift = 6, .width = 2 }, | |
| 265 | +}; | |
| 266 | +static struct ccu_div ahb1_clk = { | |
| 267 | + .div = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO), | |
| 268 | + | |
| 269 | + .mux = { | |
| 270 | + .shift = 12, | |
| 271 | + .width = 2, | |
| 272 | + | |
| 273 | + .var_predivs = ahb1_predivs, | |
| 274 | + .n_var_predivs = ARRAY_SIZE(ahb1_predivs), | |
| 275 | + }, | |
| 276 | + | |
| 277 | + .common = { | |
| 278 | + .reg = 0x054, | |
| 279 | + .features = CCU_FEATURE_VARIABLE_PREDIV, | |
| 280 | + .hw.init = CLK_HW_INIT_PARENTS("ahb1", | |
| 281 | + ahb1_parents, | |
| 282 | + &ccu_div_ops, | |
| 283 | + 0), | |
| 284 | + }, | |
| 285 | +}; | |
| 286 | + | |
| 287 | +static struct clk_div_table apb1_div_table[] = { | |
| 288 | + { .val = 0, .div = 2 }, | |
| 289 | + { .val = 1, .div = 2 }, | |
| 290 | + { .val = 2, .div = 4 }, | |
| 291 | + { .val = 3, .div = 8 }, | |
| 292 | + { /* Sentinel */ }, | |
| 293 | +}; | |
| 294 | +static SUNXI_CCU_DIV_TABLE(apb1_clk, "apb1", "ahb1", | |
| 295 | + 0x054, 8, 2, apb1_div_table, 0); | |
| 296 | + | |
| 297 | +static const char * const apb2_parents[] = { "osc32k", "osc24M", | |
| 298 | + "pll-periph0-2x", | |
| 299 | + "pll-periph0-2x" }; | |
| 300 | +static SUNXI_CCU_MP_WITH_MUX(apb2_clk, "apb2", apb2_parents, 0x058, | |
| 301 | + 0, 5, /* M */ | |
| 302 | + 16, 2, /* P */ | |
| 303 | + 24, 2, /* mux */ | |
| 304 | + 0); | |
| 305 | + | |
| 306 | +static SUNXI_CCU_GATE(bus_mipi_dsi_clk, "bus-mipi-dsi", "ahb1", | |
| 307 | + 0x060, BIT(1), 0); | |
| 308 | +static SUNXI_CCU_GATE(bus_ce_clk, "bus-ce", "ahb1", | |
| 309 | + 0x060, BIT(5), 0); | |
| 310 | +static SUNXI_CCU_GATE(bus_dma_clk, "bus-dma", "ahb1", | |
| 311 | + 0x060, BIT(6), 0); | |
| 312 | +static SUNXI_CCU_GATE(bus_mmc0_clk, "bus-mmc0", "ahb1", | |
| 313 | + 0x060, BIT(8), 0); | |
| 314 | +static SUNXI_CCU_GATE(bus_mmc1_clk, "bus-mmc1", "ahb1", | |
| 315 | + 0x060, BIT(9), 0); | |
| 316 | +static SUNXI_CCU_GATE(bus_mmc2_clk, "bus-mmc2", "ahb1", | |
| 317 | + 0x060, BIT(10), 0); | |
| 318 | +static SUNXI_CCU_GATE(bus_mmc3_clk, "bus-mmc3", "ahb1", | |
| 319 | + 0x060, BIT(11), 0); | |
| 320 | +static SUNXI_CCU_GATE(bus_nand_clk, "bus-nand", "ahb1", | |
| 321 | + 0x060, BIT(13), 0); | |
| 322 | +static SUNXI_CCU_GATE(bus_dram_clk, "bus-dram", "ahb1", | |
| 323 | + 0x060, BIT(14), 0); | |
| 324 | +static SUNXI_CCU_GATE(bus_emac_clk, "bus-emac", "ahb1", | |
| 325 | + 0x060, BIT(17), 0); | |
| 326 | +static SUNXI_CCU_GATE(bus_ts_clk, "bus-ts", "ahb1", | |
| 327 | + 0x060, BIT(18), 0); | |
| 328 | +static SUNXI_CCU_GATE(bus_hstimer_clk, "bus-hstimer", "ahb1", | |
| 329 | + 0x060, BIT(19), 0); | |
| 330 | +static SUNXI_CCU_GATE(bus_spi0_clk, "bus-spi0", "ahb1", | |
| 331 | + 0x060, BIT(20), 0); | |
| 332 | +static SUNXI_CCU_GATE(bus_spi1_clk, "bus-spi1", "ahb1", | |
| 333 | + 0x060, BIT(21), 0); | |
| 334 | +static SUNXI_CCU_GATE(bus_spi2_clk, "bus-spi2", "ahb1", | |
| 335 | + 0x060, BIT(22), 0); | |
| 336 | +static SUNXI_CCU_GATE(bus_spi3_clk, "bus-spi3", "ahb1", | |
| 337 | + 0x060, BIT(23), 0); | |
| 338 | +static SUNXI_CCU_GATE(bus_sata_clk, "bus-sata", "ahb1", | |
| 339 | + 0x060, BIT(24), 0); | |
| 340 | +static SUNXI_CCU_GATE(bus_otg_clk, "bus-otg", "ahb1", | |
| 341 | + 0x060, BIT(25), 0); | |
| 342 | +static SUNXI_CCU_GATE(bus_ehci0_clk, "bus-ehci0", "ahb1", | |
| 343 | + 0x060, BIT(26), 0); | |
| 344 | +static SUNXI_CCU_GATE(bus_ehci1_clk, "bus-ehci1", "ahb1", | |
| 345 | + 0x060, BIT(27), 0); | |
| 346 | +static SUNXI_CCU_GATE(bus_ehci2_clk, "bus-ehci2", "ahb1", | |
| 347 | + 0x060, BIT(28), 0); | |
| 348 | +static SUNXI_CCU_GATE(bus_ohci0_clk, "bus-ohci0", "ahb1", | |
| 349 | + 0x060, BIT(29), 0); | |
| 350 | +static SUNXI_CCU_GATE(bus_ohci1_clk, "bus-ohci1", "ahb1", | |
| 351 | + 0x060, BIT(30), 0); | |
| 352 | +static SUNXI_CCU_GATE(bus_ohci2_clk, "bus-ohci2", "ahb1", | |
| 353 | + 0x060, BIT(31), 0); | |
| 354 | + | |
| 355 | +static SUNXI_CCU_GATE(bus_ve_clk, "bus-ve", "ahb1", | |
| 356 | + 0x064, BIT(0), 0); | |
| 357 | +static SUNXI_CCU_GATE(bus_mp_clk, "bus-mp", "ahb1", | |
| 358 | + 0x064, BIT(2), 0); | |
| 359 | +static SUNXI_CCU_GATE(bus_deinterlace_clk, "bus-deinterlace", "ahb1", | |
| 360 | + 0x064, BIT(5), 0); | |
| 361 | +static SUNXI_CCU_GATE(bus_csi0_clk, "bus-csi0", "ahb1", | |
| 362 | + 0x064, BIT(8), 0); | |
| 363 | +static SUNXI_CCU_GATE(bus_csi1_clk, "bus-csi1", "ahb1", | |
| 364 | + 0x064, BIT(9), 0); | |
| 365 | +static SUNXI_CCU_GATE(bus_hdmi0_clk, "bus-hdmi0", "ahb1", | |
| 366 | + 0x064, BIT(10), 0); | |
| 367 | +static SUNXI_CCU_GATE(bus_hdmi1_clk, "bus-hdmi1", "ahb1", | |
| 368 | + 0x064, BIT(11), 0); | |
| 369 | +static SUNXI_CCU_GATE(bus_de_clk, "bus-de", "ahb1", | |
| 370 | + 0x064, BIT(12), 0); | |
| 371 | +static SUNXI_CCU_GATE(bus_tve0_clk, "bus-tve0", "ahb1", | |
| 372 | + 0x064, BIT(13), 0); | |
| 373 | +static SUNXI_CCU_GATE(bus_tve1_clk, "bus-tve1", "ahb1", | |
| 374 | + 0x064, BIT(14), 0); | |
| 375 | +static SUNXI_CCU_GATE(bus_tve_top_clk, "bus-tve-top", "ahb1", | |
| 376 | + 0x064, BIT(15), 0); | |
| 377 | +static SUNXI_CCU_GATE(bus_gmac_clk, "bus-gmac", "ahb1", | |
| 378 | + 0x064, BIT(17), 0); | |
| 379 | +static SUNXI_CCU_GATE(bus_gpu_clk, "bus-gpu", "ahb1", | |
| 380 | + 0x064, BIT(20), 0); | |
| 381 | +static SUNXI_CCU_GATE(bus_tvd0_clk, "bus-tvd0", "ahb1", | |
| 382 | + 0x064, BIT(21), 0); | |
| 383 | +static SUNXI_CCU_GATE(bus_tvd1_clk, "bus-tvd1", "ahb1", | |
| 384 | + 0x064, BIT(22), 0); | |
| 385 | +static SUNXI_CCU_GATE(bus_tvd2_clk, "bus-tvd2", "ahb1", | |
| 386 | + 0x064, BIT(23), 0); | |
| 387 | +static SUNXI_CCU_GATE(bus_tvd3_clk, "bus-tvd3", "ahb1", | |
| 388 | + 0x064, BIT(24), 0); | |
| 389 | +static SUNXI_CCU_GATE(bus_tvd_top_clk, "bus-tvd-top", "ahb1", | |
| 390 | + 0x064, BIT(25), 0); | |
| 391 | +static SUNXI_CCU_GATE(bus_tcon_lcd0_clk, "bus-tcon-lcd0", "ahb1", | |
| 392 | + 0x064, BIT(26), 0); | |
| 393 | +static SUNXI_CCU_GATE(bus_tcon_lcd1_clk, "bus-tcon-lcd1", "ahb1", | |
| 394 | + 0x064, BIT(27), 0); | |
| 395 | +static SUNXI_CCU_GATE(bus_tcon_tv0_clk, "bus-tcon-tv0", "ahb1", | |
| 396 | + 0x064, BIT(28), 0); | |
| 397 | +static SUNXI_CCU_GATE(bus_tcon_tv1_clk, "bus-tcon-tv1", "ahb1", | |
| 398 | + 0x064, BIT(29), 0); | |
| 399 | +static SUNXI_CCU_GATE(bus_tcon_top_clk, "bus-tcon-top", "ahb1", | |
| 400 | + 0x064, BIT(30), 0); | |
| 401 | + | |
| 402 | +static SUNXI_CCU_GATE(bus_codec_clk, "bus-codec", "apb1", | |
| 403 | + 0x068, BIT(0), 0); | |
| 404 | +static SUNXI_CCU_GATE(bus_spdif_clk, "bus-spdif", "apb1", | |
| 405 | + 0x068, BIT(1), 0); | |
| 406 | +static SUNXI_CCU_GATE(bus_ac97_clk, "bus-ac97", "apb1", | |
| 407 | + 0x068, BIT(2), 0); | |
| 408 | +static SUNXI_CCU_GATE(bus_pio_clk, "bus-pio", "apb1", | |
| 409 | + 0x068, BIT(5), 0); | |
| 410 | +static SUNXI_CCU_GATE(bus_ir0_clk, "bus-ir0", "apb1", | |
| 411 | + 0x068, BIT(6), 0); | |
| 412 | +static SUNXI_CCU_GATE(bus_ir1_clk, "bus-ir1", "apb1", | |
| 413 | + 0x068, BIT(7), 0); | |
| 414 | +static SUNXI_CCU_GATE(bus_ths_clk, "bus-ths", "apb1", | |
| 415 | + 0x068, BIT(8), 0); | |
| 416 | +static SUNXI_CCU_GATE(bus_keypad_clk, "bus-keypad", "apb1", | |
| 417 | + 0x068, BIT(10), 0); | |
| 418 | +static SUNXI_CCU_GATE(bus_i2s0_clk, "bus-i2s0", "apb1", | |
| 419 | + 0x068, BIT(12), 0); | |
| 420 | +static SUNXI_CCU_GATE(bus_i2s1_clk, "bus-i2s1", "apb1", | |
| 421 | + 0x068, BIT(13), 0); | |
| 422 | +static SUNXI_CCU_GATE(bus_i2s2_clk, "bus-i2s2", "apb1", | |
| 423 | + 0x068, BIT(14), 0); | |
| 424 | + | |
| 425 | +static SUNXI_CCU_GATE(bus_i2c0_clk, "bus-i2c0", "apb2", | |
| 426 | + 0x06c, BIT(0), 0); | |
| 427 | +static SUNXI_CCU_GATE(bus_i2c1_clk, "bus-i2c1", "apb2", | |
| 428 | + 0x06c, BIT(1), 0); | |
| 429 | +static SUNXI_CCU_GATE(bus_i2c2_clk, "bus-i2c2", "apb2", | |
| 430 | + 0x06c, BIT(2), 0); | |
| 431 | +static SUNXI_CCU_GATE(bus_i2c3_clk, "bus-i2c3", "apb2", | |
| 432 | + 0x06c, BIT(3), 0); | |
| 433 | +/* | |
| 434 | + * In datasheet here's "Reserved", however the gate exists in BSP soucre | |
| 435 | + * code. | |
| 436 | + */ | |
| 437 | +static SUNXI_CCU_GATE(bus_can_clk, "bus-can", "apb2", | |
| 438 | + 0x06c, BIT(4), 0); | |
| 439 | +static SUNXI_CCU_GATE(bus_scr_clk, "bus-scr", "apb2", | |
| 440 | + 0x06c, BIT(5), 0); | |
| 441 | +static SUNXI_CCU_GATE(bus_ps20_clk, "bus-ps20", "apb2", | |
| 442 | + 0x06c, BIT(6), 0); | |
| 443 | +static SUNXI_CCU_GATE(bus_ps21_clk, "bus-ps21", "apb2", | |
| 444 | + 0x06c, BIT(7), 0); | |
| 445 | +static SUNXI_CCU_GATE(bus_i2c4_clk, "bus-i2c4", "apb2", | |
| 446 | + 0x06c, BIT(15), 0); | |
| 447 | +static SUNXI_CCU_GATE(bus_uart0_clk, "bus-uart0", "apb2", | |
| 448 | + 0x06c, BIT(16), 0); | |
| 449 | +static SUNXI_CCU_GATE(bus_uart1_clk, "bus-uart1", "apb2", | |
| 450 | + 0x06c, BIT(17), 0); | |
| 451 | +static SUNXI_CCU_GATE(bus_uart2_clk, "bus-uart2", "apb2", | |
| 452 | + 0x06c, BIT(18), 0); | |
| 453 | +static SUNXI_CCU_GATE(bus_uart3_clk, "bus-uart3", "apb2", | |
| 454 | + 0x06c, BIT(19), 0); | |
| 455 | +static SUNXI_CCU_GATE(bus_uart4_clk, "bus-uart4", "apb2", | |
| 456 | + 0x06c, BIT(20), 0); | |
| 457 | +static SUNXI_CCU_GATE(bus_uart5_clk, "bus-uart5", "apb2", | |
| 458 | + 0x06c, BIT(21), 0); | |
| 459 | +static SUNXI_CCU_GATE(bus_uart6_clk, "bus-uart6", "apb2", | |
| 460 | + 0x06c, BIT(22), 0); | |
| 461 | +static SUNXI_CCU_GATE(bus_uart7_clk, "bus-uart7", "apb2", | |
| 462 | + 0x06c, BIT(23), 0); | |
| 463 | + | |
| 464 | +static SUNXI_CCU_GATE(bus_dbg_clk, "bus-dbg", "ahb1", | |
| 465 | + 0x070, BIT(7), 0); | |
| 466 | + | |
| 467 | +static const char * const ths_parents[] = { "osc24M" }; | |
| 468 | +static struct ccu_div ths_clk = { | |
| 469 | + .enable = BIT(31), | |
| 470 | + .div = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO), | |
| 471 | + .mux = _SUNXI_CCU_MUX(24, 2), | |
| 472 | + .common = { | |
| 473 | + .reg = 0x074, | |
| 474 | + .hw.init = CLK_HW_INIT_PARENTS("ths", | |
| 475 | + ths_parents, | |
| 476 | + &ccu_div_ops, | |
| 477 | + 0), | |
| 478 | + }, | |
| 479 | +}; | |
| 480 | + | |
| 481 | +static const char * const mod0_default_parents[] = { "osc24M", "pll-periph0", | |
| 482 | + "pll-periph1" }; | |
| 483 | +static SUNXI_CCU_MP_WITH_MUX_GATE(nand_clk, "nand", mod0_default_parents, 0x080, | |
| 484 | + 0, 4, /* M */ | |
| 485 | + 16, 2, /* P */ | |
| 486 | + 24, 2, /* mux */ | |
| 487 | + BIT(31), /* gate */ | |
| 488 | + 0); | |
| 489 | + | |
| 490 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mod0_default_parents, 0x088, | |
| 491 | + 0, 4, /* M */ | |
| 492 | + 16, 2, /* P */ | |
| 493 | + 24, 2, /* mux */ | |
| 494 | + BIT(31), /* gate */ | |
| 495 | + 0); | |
| 496 | + | |
| 497 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mod0_default_parents, 0x08c, | |
| 498 | + 0, 4, /* M */ | |
| 499 | + 16, 2, /* P */ | |
| 500 | + 24, 2, /* mux */ | |
| 501 | + BIT(31), /* gate */ | |
| 502 | + 0); | |
| 503 | + | |
| 504 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mod0_default_parents, 0x090, | |
| 505 | + 0, 4, /* M */ | |
| 506 | + 16, 2, /* P */ | |
| 507 | + 24, 2, /* mux */ | |
| 508 | + BIT(31), /* gate */ | |
| 509 | + 0); | |
| 510 | + | |
| 511 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc3_clk, "mmc3", mod0_default_parents, 0x094, | |
| 512 | + 0, 4, /* M */ | |
| 513 | + 16, 2, /* P */ | |
| 514 | + 24, 2, /* mux */ | |
| 515 | + BIT(31), /* gate */ | |
| 516 | + 0); | |
| 517 | + | |
| 518 | +static const char * const ts_parents[] = { "osc24M", "pll-periph0", }; | |
| 519 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ts_clk, "ts", ts_parents, 0x098, | |
| 520 | + 0, 4, /* M */ | |
| 521 | + 16, 2, /* P */ | |
| 522 | + 24, 4, /* mux */ | |
| 523 | + BIT(31), /* gate */ | |
| 524 | + 0); | |
| 525 | + | |
| 526 | +static const char * const ce_parents[] = { "osc24M", "pll-periph0-2x", | |
| 527 | + "pll-periph1-2x" }; | |
| 528 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x09c, | |
| 529 | + 0, 4, /* M */ | |
| 530 | + 16, 2, /* P */ | |
| 531 | + 24, 2, /* mux */ | |
| 532 | + BIT(31), /* gate */ | |
| 533 | + 0); | |
| 534 | + | |
| 535 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", mod0_default_parents, 0x0a0, | |
| 536 | + 0, 4, /* M */ | |
| 537 | + 16, 2, /* P */ | |
| 538 | + 24, 2, /* mux */ | |
| 539 | + BIT(31), /* gate */ | |
| 540 | + 0); | |
| 541 | + | |
| 542 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", mod0_default_parents, 0x0a4, | |
| 543 | + 0, 4, /* M */ | |
| 544 | + 16, 2, /* P */ | |
| 545 | + 24, 2, /* mux */ | |
| 546 | + BIT(31), /* gate */ | |
| 547 | + 0); | |
| 548 | + | |
| 549 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi2_clk, "spi2", mod0_default_parents, 0x0a8, | |
| 550 | + 0, 4, /* M */ | |
| 551 | + 16, 2, /* P */ | |
| 552 | + 24, 2, /* mux */ | |
| 553 | + BIT(31), /* gate */ | |
| 554 | + 0); | |
| 555 | + | |
| 556 | +static SUNXI_CCU_MP_WITH_MUX_GATE(spi3_clk, "spi3", mod0_default_parents, 0x0ac, | |
| 557 | + 0, 4, /* M */ | |
| 558 | + 16, 2, /* P */ | |
| 559 | + 24, 2, /* mux */ | |
| 560 | + BIT(31), /* gate */ | |
| 561 | + 0); | |
| 562 | + | |
| 563 | +static const char * const i2s_parents[] = { "pll-audio-8x", "pll-audio-4x", | |
| 564 | + "pll-audio-2x", "pll-audio" }; | |
| 565 | +static SUNXI_CCU_MUX_WITH_GATE(i2s0_clk, "i2s0", i2s_parents, | |
| 566 | + 0x0b0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 567 | + | |
| 568 | +static SUNXI_CCU_MUX_WITH_GATE(i2s1_clk, "i2s1", i2s_parents, | |
| 569 | + 0x0b4, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 570 | + | |
| 571 | +static SUNXI_CCU_MUX_WITH_GATE(i2s2_clk, "i2s2", i2s_parents, | |
| 572 | + 0x0b8, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 573 | + | |
| 574 | +static SUNXI_CCU_MUX_WITH_GATE(ac97_clk, "ac97", i2s_parents, | |
| 575 | + 0x0bc, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 576 | + | |
| 577 | +static SUNXI_CCU_MUX_WITH_GATE(spdif_clk, "spdif", i2s_parents, | |
| 578 | + 0x0c0, 16, 2, BIT(31), CLK_SET_RATE_PARENT); | |
| 579 | + | |
| 580 | +static const char * const keypad_parents[] = { "osc24M", "osc32k" }; | |
| 581 | +static const u8 keypad_table[] = { 0, 2 }; | |
| 582 | +static struct ccu_mp keypad_clk = { | |
| 583 | + .enable = BIT(31), | |
| 584 | + .m = _SUNXI_CCU_DIV(0, 5), | |
| 585 | + .p = _SUNXI_CCU_DIV(16, 2), | |
| 586 | + .mux = _SUNXI_CCU_MUX_TABLE(24, 2, keypad_table), | |
| 587 | + .common = { | |
| 588 | + .reg = 0x0c4, | |
| 589 | + .hw.init = CLK_HW_INIT_PARENTS("keypad", | |
| 590 | + keypad_parents, | |
| 591 | + &ccu_mp_ops, | |
| 592 | + 0), | |
| 593 | + } | |
| 594 | +}; | |
| 595 | + | |
| 596 | +static const char * const sata_parents[] = { "pll-sata-out", "sata-ext" }; | |
| 597 | +static SUNXI_CCU_MUX_WITH_GATE(sata_clk, "sata", sata_parents, | |
| 598 | + 0x0c8, 24, 1, BIT(31), CLK_SET_RATE_PARENT); | |
| 599 | + | |
| 600 | +/* | |
| 601 | + * There are 3 OHCI 12M clock source selection bits in this register. | |
| 602 | + * We will force them to 0 (12M divided from 48M). | |
| 603 | + */ | |
| 604 | +#define SUN8I_R40_USB_CLK_REG 0x0cc | |
| 605 | + | |
| 606 | +static SUNXI_CCU_GATE(usb_phy0_clk, "usb-phy0", "osc24M", | |
| 607 | + 0x0cc, BIT(8), 0); | |
| 608 | +static SUNXI_CCU_GATE(usb_phy1_clk, "usb-phy1", "osc24M", | |
| 609 | + 0x0cc, BIT(9), 0); | |
| 610 | +static SUNXI_CCU_GATE(usb_phy2_clk, "usb-phy2", "osc24M", | |
| 611 | + 0x0cc, BIT(10), 0); | |
| 612 | +static SUNXI_CCU_GATE(usb_ohci0_clk, "usb-ohci0", "osc12M", | |
| 613 | + 0x0cc, BIT(16), 0); | |
| 614 | +static SUNXI_CCU_GATE(usb_ohci1_clk, "usb-ohci1", "osc12M", | |
| 615 | + 0x0cc, BIT(17), 0); | |
| 616 | +static SUNXI_CCU_GATE(usb_ohci2_clk, "usb-ohci2", "osc12M", | |
| 617 | + 0x0cc, BIT(18), 0); | |
| 618 | + | |
| 619 | +static const char * const ir_parents[] = { "osc24M", "pll-periph0", | |
| 620 | + "pll-periph1", "osc32k" }; | |
| 621 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir0_clk, "ir0", ir_parents, 0x0d0, | |
| 622 | + 0, 4, /* M */ | |
| 623 | + 16, 2, /* P */ | |
| 624 | + 24, 2, /* mux */ | |
| 625 | + BIT(31), /* gate */ | |
| 626 | + 0); | |
| 627 | + | |
| 628 | +static SUNXI_CCU_MP_WITH_MUX_GATE(ir1_clk, "ir1", ir_parents, 0x0d4, | |
| 629 | + 0, 4, /* M */ | |
| 630 | + 16, 2, /* P */ | |
| 631 | + 24, 2, /* mux */ | |
| 632 | + BIT(31), /* gate */ | |
| 633 | + 0); | |
| 634 | + | |
| 635 | +static const char * const dram_parents[] = { "pll-ddr0", "pll-ddr1" }; | |
| 636 | +static SUNXI_CCU_M_WITH_MUX(dram_clk, "dram", dram_parents, | |
| 637 | + 0x0f4, 0, 2, 20, 2, CLK_IS_CRITICAL); | |
| 638 | + | |
| 639 | +static SUNXI_CCU_GATE(dram_ve_clk, "dram-ve", "dram", | |
| 640 | + 0x100, BIT(0), 0); | |
| 641 | +static SUNXI_CCU_GATE(dram_csi0_clk, "dram-csi0", "dram", | |
| 642 | + 0x100, BIT(1), 0); | |
| 643 | +static SUNXI_CCU_GATE(dram_csi1_clk, "dram-csi1", "dram", | |
| 644 | + 0x100, BIT(2), 0); | |
| 645 | +static SUNXI_CCU_GATE(dram_ts_clk, "dram-ts", "dram", | |
| 646 | + 0x100, BIT(3), 0); | |
| 647 | +static SUNXI_CCU_GATE(dram_tvd_clk, "dram-tvd", "dram", | |
| 648 | + 0x100, BIT(4), 0); | |
| 649 | +static SUNXI_CCU_GATE(dram_mp_clk, "dram-mp", "dram", | |
| 650 | + 0x100, BIT(5), 0); | |
| 651 | +static SUNXI_CCU_GATE(dram_deinterlace_clk, "dram-deinterlace", "dram", | |
| 652 | + 0x100, BIT(6), 0); | |
| 653 | + | |
| 654 | +static const char * const de_parents[] = { "pll-periph0-2x", "pll-de" }; | |
| 655 | +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents, | |
| 656 | + 0x104, 0, 4, 24, 3, BIT(31), 0); | |
| 657 | +static SUNXI_CCU_M_WITH_MUX_GATE(mp_clk, "mp", de_parents, | |
| 658 | + 0x108, 0, 4, 24, 3, BIT(31), 0); | |
| 659 | + | |
| 660 | +static const char * const tcon_parents[] = { "pll-video0", "pll-video1", | |
| 661 | + "pll-video0-2x", "pll-video1-2x", | |
| 662 | + "pll-mipi" }; | |
| 663 | +static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd0_clk, "tcon-lcd0", tcon_parents, | |
| 664 | + 0x110, 24, 3, BIT(31), CLK_SET_RATE_PARENT); | |
| 665 | +static SUNXI_CCU_MUX_WITH_GATE(tcon_lcd1_clk, "tcon-lcd1", tcon_parents, | |
| 666 | + 0x114, 24, 3, BIT(31), CLK_SET_RATE_PARENT); | |
| 667 | +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv0_clk, "tcon-tv0", tcon_parents, | |
| 668 | + 0x118, 0, 4, 24, 3, BIT(31), 0); | |
| 669 | +static SUNXI_CCU_M_WITH_MUX_GATE(tcon_tv1_clk, "tcon-tv1", tcon_parents, | |
| 670 | + 0x11c, 0, 4, 24, 3, BIT(31), 0); | |
| 671 | + | |
| 672 | +static const char * const deinterlace_parents[] = { "pll-periph0", | |
| 673 | + "pll-periph1" }; | |
| 674 | +static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", | |
| 675 | + deinterlace_parents, 0x124, 0, 4, 24, 3, | |
| 676 | + BIT(31), 0); | |
| 677 | + | |
| 678 | +static const char * const csi_mclk_parents[] = { "osc24M", "pll-video1", | |
| 679 | + "pll-periph1" }; | |
| 680 | +static SUNXI_CCU_M_WITH_MUX_GATE(csi1_mclk_clk, "csi1-mclk", csi_mclk_parents, | |
| 681 | + 0x130, 0, 5, 8, 3, BIT(15), 0); | |
| 682 | + | |
| 683 | +static const char * const csi_sclk_parents[] = { "pll-periph0", "pll-periph1" }; | |
| 684 | +static SUNXI_CCU_M_WITH_MUX_GATE(csi_sclk_clk, "csi-sclk", csi_sclk_parents, | |
| 685 | + 0x134, 16, 4, 24, 3, BIT(31), 0); | |
| 686 | + | |
| 687 | +static SUNXI_CCU_M_WITH_MUX_GATE(csi0_mclk_clk, "csi0-mclk", csi_mclk_parents, | |
| 688 | + 0x134, 0, 5, 8, 3, BIT(15), 0); | |
| 689 | + | |
| 690 | +static SUNXI_CCU_M_WITH_GATE(ve_clk, "ve", "pll-ve", | |
| 691 | + 0x13c, 16, 3, BIT(31), CLK_SET_RATE_PARENT); | |
| 692 | + | |
| 693 | +static SUNXI_CCU_GATE(codec_clk, "codec", "pll-audio", | |
| 694 | + 0x140, BIT(31), CLK_SET_RATE_PARENT); | |
| 695 | +static SUNXI_CCU_GATE(avs_clk, "avs", "osc24M", | |
| 696 | + 0x144, BIT(31), 0); | |
| 697 | + | |
| 698 | +static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" }; | |
| 699 | +static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents, | |
| 700 | + 0x150, 0, 4, 24, 2, BIT(31), 0); | |
| 701 | + | |
| 702 | +static SUNXI_CCU_GATE(hdmi_slow_clk, "hdmi-slow", "osc24M", | |
| 703 | + 0x154, BIT(31), 0); | |
| 704 | + | |
| 705 | +/* | |
| 706 | + * In the SoC's user manual, the P factor is mentioned, but not used in | |
| 707 | + * the frequency formula. | |
| 708 | + * | |
| 709 | + * Here the factor is included, according to the BSP kernel source, | |
| 710 | + * which contains the P factor of this clock. | |
| 711 | + */ | |
| 712 | +static const char * const mbus_parents[] = { "osc24M", "pll-periph0-2x", | |
| 713 | + "pll-ddr0" }; | |
| 714 | +static SUNXI_CCU_MP_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents, 0x15c, | |
| 715 | + 0, 4, /* M */ | |
| 716 | + 16, 2, /* P */ | |
| 717 | + 24, 2, /* mux */ | |
| 718 | + BIT(31), /* gate */ | |
| 719 | + CLK_IS_CRITICAL); | |
| 720 | + | |
| 721 | +static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-video1", | |
| 722 | + "pll-periph0" }; | |
| 723 | +static SUNXI_CCU_M_WITH_MUX_GATE(dsi_dphy_clk, "dsi-dphy", dsi_dphy_parents, | |
| 724 | + 0x168, 0, 4, 8, 2, BIT(15), 0); | |
| 725 | + | |
| 726 | +static SUNXI_CCU_M_WITH_MUX_GATE(tve0_clk, "tve0", tcon_parents, | |
| 727 | + 0x180, 0, 4, 24, 3, BIT(31), 0); | |
| 728 | +static SUNXI_CCU_M_WITH_MUX_GATE(tve1_clk, "tve1", tcon_parents, | |
| 729 | + 0x184, 0, 4, 24, 3, BIT(31), 0); | |
| 730 | + | |
| 731 | +static const char * const tvd_parents[] = { "pll-video0", "pll-video1", | |
| 732 | + "pll-video0-2x", "pll-video1-2x" }; | |
| 733 | +static SUNXI_CCU_M_WITH_MUX_GATE(tvd0_clk, "tvd0", tvd_parents, | |
| 734 | + 0x188, 0, 4, 24, 3, BIT(31), 0); | |
| 735 | +static SUNXI_CCU_M_WITH_MUX_GATE(tvd1_clk, "tvd1", tvd_parents, | |
| 736 | + 0x18c, 0, 4, 24, 3, BIT(31), 0); | |
| 737 | +static SUNXI_CCU_M_WITH_MUX_GATE(tvd2_clk, "tvd2", tvd_parents, | |
| 738 | + 0x190, 0, 4, 24, 3, BIT(31), 0); | |
| 739 | +static SUNXI_CCU_M_WITH_MUX_GATE(tvd3_clk, "tvd3", tvd_parents, | |
| 740 | + 0x194, 0, 4, 24, 3, BIT(31), 0); | |
| 741 | + | |
| 742 | +static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu", | |
| 743 | + 0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT); | |
| 744 | + | |
| 745 | +static const char * const out_parents[] = { "osc24M", "osc32k", "osc24M" }; | |
| 746 | +static const struct ccu_mux_fixed_prediv out_predivs[] = { | |
| 747 | + { .index = 0, .div = 750, }, | |
| 748 | +}; | |
| 749 | + | |
| 750 | +static struct ccu_mp outa_clk = { | |
| 751 | + .enable = BIT(31), | |
| 752 | + .m = _SUNXI_CCU_DIV(8, 5), | |
| 753 | + .p = _SUNXI_CCU_DIV(20, 2), | |
| 754 | + .mux = { | |
| 755 | + .shift = 24, | |
| 756 | + .width = 2, | |
| 757 | + .fixed_predivs = out_predivs, | |
| 758 | + .n_predivs = ARRAY_SIZE(out_predivs), | |
| 759 | + }, | |
| 760 | + .common = { | |
| 761 | + .reg = 0x1f0, | |
| 762 | + .features = CCU_FEATURE_FIXED_PREDIV, | |
| 763 | + .hw.init = CLK_HW_INIT_PARENTS("outa", out_parents, | |
| 764 | + &ccu_mp_ops, 0), | |
| 765 | + } | |
| 766 | +}; | |
| 767 | + | |
| 768 | +static struct ccu_mp outb_clk = { | |
| 769 | + .enable = BIT(31), | |
| 770 | + .m = _SUNXI_CCU_DIV(8, 5), | |
| 771 | + .p = _SUNXI_CCU_DIV(20, 2), | |
| 772 | + .mux = { | |
| 773 | + .shift = 24, | |
| 774 | + .width = 2, | |
| 775 | + .fixed_predivs = out_predivs, | |
| 776 | + .n_predivs = ARRAY_SIZE(out_predivs), | |
| 777 | + }, | |
| 778 | + .common = { | |
| 779 | + .reg = 0x1f4, | |
| 780 | + .features = CCU_FEATURE_FIXED_PREDIV, | |
| 781 | + .hw.init = CLK_HW_INIT_PARENTS("outb", out_parents, | |
| 782 | + &ccu_mp_ops, 0), | |
| 783 | + } | |
| 784 | +}; | |
| 785 | + | |
| 786 | +static struct ccu_common *sun8i_r40_ccu_clks[] = { | |
| 787 | + &pll_cpu_clk.common, | |
| 788 | + &pll_audio_base_clk.common, | |
| 789 | + &pll_video0_clk.common, | |
| 790 | + &pll_ve_clk.common, | |
| 791 | + &pll_ddr0_clk.common, | |
| 792 | + &pll_periph0_clk.common, | |
| 793 | + &pll_periph0_sata_clk.common, | |
| 794 | + &pll_periph1_clk.common, | |
| 795 | + &pll_video1_clk.common, | |
| 796 | + &pll_sata_clk.common, | |
| 797 | + &pll_sata_out_clk.common, | |
| 798 | + &pll_gpu_clk.common, | |
| 799 | + &pll_mipi_clk.common, | |
| 800 | + &pll_de_clk.common, | |
| 801 | + &pll_ddr1_clk.common, | |
| 802 | + &cpu_clk.common, | |
| 803 | + &axi_clk.common, | |
| 804 | + &ahb1_clk.common, | |
| 805 | + &apb1_clk.common, | |
| 806 | + &apb2_clk.common, | |
| 807 | + &bus_mipi_dsi_clk.common, | |
| 808 | + &bus_ce_clk.common, | |
| 809 | + &bus_dma_clk.common, | |
| 810 | + &bus_mmc0_clk.common, | |
| 811 | + &bus_mmc1_clk.common, | |
| 812 | + &bus_mmc2_clk.common, | |
| 813 | + &bus_mmc3_clk.common, | |
| 814 | + &bus_nand_clk.common, | |
| 815 | + &bus_dram_clk.common, | |
| 816 | + &bus_emac_clk.common, | |
| 817 | + &bus_ts_clk.common, | |
| 818 | + &bus_hstimer_clk.common, | |
| 819 | + &bus_spi0_clk.common, | |
| 820 | + &bus_spi1_clk.common, | |
| 821 | + &bus_spi2_clk.common, | |
| 822 | + &bus_spi3_clk.common, | |
| 823 | + &bus_sata_clk.common, | |
| 824 | + &bus_otg_clk.common, | |
| 825 | + &bus_ehci0_clk.common, | |
| 826 | + &bus_ehci1_clk.common, | |
| 827 | + &bus_ehci2_clk.common, | |
| 828 | + &bus_ohci0_clk.common, | |
| 829 | + &bus_ohci1_clk.common, | |
| 830 | + &bus_ohci2_clk.common, | |
| 831 | + &bus_ve_clk.common, | |
| 832 | + &bus_mp_clk.common, | |
| 833 | + &bus_deinterlace_clk.common, | |
| 834 | + &bus_csi0_clk.common, | |
| 835 | + &bus_csi1_clk.common, | |
| 836 | + &bus_hdmi0_clk.common, | |
| 837 | + &bus_hdmi1_clk.common, | |
| 838 | + &bus_de_clk.common, | |
| 839 | + &bus_tve0_clk.common, | |
| 840 | + &bus_tve1_clk.common, | |
| 841 | + &bus_tve_top_clk.common, | |
| 842 | + &bus_gmac_clk.common, | |
| 843 | + &bus_gpu_clk.common, | |
| 844 | + &bus_tvd0_clk.common, | |
| 845 | + &bus_tvd1_clk.common, | |
| 846 | + &bus_tvd2_clk.common, | |
| 847 | + &bus_tvd3_clk.common, | |
| 848 | + &bus_tvd_top_clk.common, | |
| 849 | + &bus_tcon_lcd0_clk.common, | |
| 850 | + &bus_tcon_lcd1_clk.common, | |
| 851 | + &bus_tcon_tv0_clk.common, | |
| 852 | + &bus_tcon_tv1_clk.common, | |
| 853 | + &bus_tcon_top_clk.common, | |
| 854 | + &bus_codec_clk.common, | |
| 855 | + &bus_spdif_clk.common, | |
| 856 | + &bus_ac97_clk.common, | |
| 857 | + &bus_pio_clk.common, | |
| 858 | + &bus_ir0_clk.common, | |
| 859 | + &bus_ir1_clk.common, | |
| 860 | + &bus_ths_clk.common, | |
| 861 | + &bus_keypad_clk.common, | |
| 862 | + &bus_i2s0_clk.common, | |
| 863 | + &bus_i2s1_clk.common, | |
| 864 | + &bus_i2s2_clk.common, | |
| 865 | + &bus_i2c0_clk.common, | |
| 866 | + &bus_i2c1_clk.common, | |
| 867 | + &bus_i2c2_clk.common, | |
| 868 | + &bus_i2c3_clk.common, | |
| 869 | + &bus_can_clk.common, | |
| 870 | + &bus_scr_clk.common, | |
| 871 | + &bus_ps20_clk.common, | |
| 872 | + &bus_ps21_clk.common, | |
| 873 | + &bus_i2c4_clk.common, | |
| 874 | + &bus_uart0_clk.common, | |
| 875 | + &bus_uart1_clk.common, | |
| 876 | + &bus_uart2_clk.common, | |
| 877 | + &bus_uart3_clk.common, | |
| 878 | + &bus_uart4_clk.common, | |
| 879 | + &bus_uart5_clk.common, | |
| 880 | + &bus_uart6_clk.common, | |
| 881 | + &bus_uart7_clk.common, | |
| 882 | + &bus_dbg_clk.common, | |
| 883 | + &ths_clk.common, | |
| 884 | + &nand_clk.common, | |
| 885 | + &mmc0_clk.common, | |
| 886 | + &mmc1_clk.common, | |
| 887 | + &mmc2_clk.common, | |
| 888 | + &mmc3_clk.common, | |
| 889 | + &ts_clk.common, | |
| 890 | + &ce_clk.common, | |
| 891 | + &spi0_clk.common, | |
| 892 | + &spi1_clk.common, | |
| 893 | + &spi2_clk.common, | |
| 894 | + &spi3_clk.common, | |
| 895 | + &i2s0_clk.common, | |
| 896 | + &i2s1_clk.common, | |
| 897 | + &i2s2_clk.common, | |
| 898 | + &ac97_clk.common, | |
| 899 | + &spdif_clk.common, | |
| 900 | + &keypad_clk.common, | |
| 901 | + &sata_clk.common, | |
| 902 | + &usb_phy0_clk.common, | |
| 903 | + &usb_phy1_clk.common, | |
| 904 | + &usb_phy2_clk.common, | |
| 905 | + &usb_ohci0_clk.common, | |
| 906 | + &usb_ohci1_clk.common, | |
| 907 | + &usb_ohci2_clk.common, | |
| 908 | + &ir0_clk.common, | |
| 909 | + &ir1_clk.common, | |
| 910 | + &dram_clk.common, | |
| 911 | + &dram_ve_clk.common, | |
| 912 | + &dram_csi0_clk.common, | |
| 913 | + &dram_csi1_clk.common, | |
| 914 | + &dram_ts_clk.common, | |
| 915 | + &dram_tvd_clk.common, | |
| 916 | + &dram_mp_clk.common, | |
| 917 | + &dram_deinterlace_clk.common, | |
| 918 | + &de_clk.common, | |
| 919 | + &mp_clk.common, | |
| 920 | + &tcon_lcd0_clk.common, | |
| 921 | + &tcon_lcd1_clk.common, | |
| 922 | + &tcon_tv0_clk.common, | |
| 923 | + &tcon_tv1_clk.common, | |
| 924 | + &deinterlace_clk.common, | |
| 925 | + &csi1_mclk_clk.common, | |
| 926 | + &csi_sclk_clk.common, | |
| 927 | + &csi0_mclk_clk.common, | |
| 928 | + &ve_clk.common, | |
| 929 | + &codec_clk.common, | |
| 930 | + &avs_clk.common, | |
| 931 | + &hdmi_clk.common, | |
| 932 | + &hdmi_slow_clk.common, | |
| 933 | + &mbus_clk.common, | |
| 934 | + &dsi_dphy_clk.common, | |
| 935 | + &tve0_clk.common, | |
| 936 | + &tve1_clk.common, | |
| 937 | + &tvd0_clk.common, | |
| 938 | + &tvd1_clk.common, | |
| 939 | + &tvd2_clk.common, | |
| 940 | + &tvd3_clk.common, | |
| 941 | + &gpu_clk.common, | |
| 942 | + &outa_clk.common, | |
| 943 | + &outb_clk.common, | |
| 944 | +}; | |
| 945 | + | |
| 946 | +/* Fixed Factor clocks */ | |
| 947 | +static CLK_FIXED_FACTOR(osc12M_clk, "osc12M", "osc24M", 2, 1, 0); | |
| 948 | + | |
| 949 | +/* We hardcode the divider to 4 for now */ | |
| 950 | +static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio", | |
| 951 | + "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT); | |
| 952 | +static CLK_FIXED_FACTOR(pll_audio_2x_clk, "pll-audio-2x", | |
| 953 | + "pll-audio-base", 2, 1, CLK_SET_RATE_PARENT); | |
| 954 | +static CLK_FIXED_FACTOR(pll_audio_4x_clk, "pll-audio-4x", | |
| 955 | + "pll-audio-base", 1, 1, CLK_SET_RATE_PARENT); | |
| 956 | +static CLK_FIXED_FACTOR(pll_audio_8x_clk, "pll-audio-8x", | |
| 957 | + "pll-audio-base", 1, 2, CLK_SET_RATE_PARENT); | |
| 958 | +static CLK_FIXED_FACTOR(pll_periph0_2x_clk, "pll-periph0-2x", | |
| 959 | + "pll-periph0", 1, 2, 0); | |
| 960 | +static CLK_FIXED_FACTOR(pll_periph1_2x_clk, "pll-periph1-2x", | |
| 961 | + "pll-periph1", 1, 2, 0); | |
| 962 | +static CLK_FIXED_FACTOR(pll_video0_2x_clk, "pll-video0-2x", | |
| 963 | + "pll-video0", 1, 2, 0); | |
| 964 | +static CLK_FIXED_FACTOR(pll_video1_2x_clk, "pll-video1-2x", | |
| 965 | + "pll-video1", 1, 2, 0); | |
| 966 | + | |
| 967 | +static struct clk_hw_onecell_data sun8i_r40_hw_clks = { | |
| 968 | + .hws = { | |
| 969 | + [CLK_OSC_12M] = &osc12M_clk.hw, | |
| 970 | + [CLK_PLL_CPU] = &pll_cpu_clk.common.hw, | |
| 971 | + [CLK_PLL_AUDIO_BASE] = &pll_audio_base_clk.common.hw, | |
| 972 | + [CLK_PLL_AUDIO] = &pll_audio_clk.hw, | |
| 973 | + [CLK_PLL_AUDIO_2X] = &pll_audio_2x_clk.hw, | |
| 974 | + [CLK_PLL_AUDIO_4X] = &pll_audio_4x_clk.hw, | |
| 975 | + [CLK_PLL_AUDIO_8X] = &pll_audio_8x_clk.hw, | |
| 976 | + [CLK_PLL_VIDEO0] = &pll_video0_clk.common.hw, | |
| 977 | + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, | |
| 978 | + [CLK_PLL_VE] = &pll_ve_clk.common.hw, | |
| 979 | + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, | |
| 980 | + [CLK_PLL_PERIPH0] = &pll_periph0_clk.common.hw, | |
| 981 | + [CLK_PLL_PERIPH0_SATA] = &pll_periph0_sata_clk.common.hw, | |
| 982 | + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.hw, | |
| 983 | + [CLK_PLL_PERIPH1] = &pll_periph1_clk.common.hw, | |
| 984 | + [CLK_PLL_PERIPH1_2X] = &pll_periph1_2x_clk.hw, | |
| 985 | + [CLK_PLL_VIDEO1] = &pll_video1_clk.common.hw, | |
| 986 | + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, | |
| 987 | + [CLK_PLL_SATA] = &pll_sata_clk.common.hw, | |
| 988 | + [CLK_PLL_SATA_OUT] = &pll_sata_out_clk.common.hw, | |
| 989 | + [CLK_PLL_GPU] = &pll_gpu_clk.common.hw, | |
| 990 | + [CLK_PLL_MIPI] = &pll_mipi_clk.common.hw, | |
| 991 | + [CLK_PLL_DE] = &pll_de_clk.common.hw, | |
| 992 | + [CLK_PLL_DDR1] = &pll_ddr1_clk.common.hw, | |
| 993 | + [CLK_CPU] = &cpu_clk.common.hw, | |
| 994 | + [CLK_AXI] = &axi_clk.common.hw, | |
| 995 | + [CLK_AHB1] = &ahb1_clk.common.hw, | |
| 996 | + [CLK_APB1] = &apb1_clk.common.hw, | |
| 997 | + [CLK_APB2] = &apb2_clk.common.hw, | |
| 998 | + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, | |
| 999 | + [CLK_BUS_CE] = &bus_ce_clk.common.hw, | |
| 1000 | + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, | |
| 1001 | + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, | |
| 1002 | + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, | |
| 1003 | + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, | |
| 1004 | + [CLK_BUS_MMC3] = &bus_mmc3_clk.common.hw, | |
| 1005 | + [CLK_BUS_NAND] = &bus_nand_clk.common.hw, | |
| 1006 | + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, | |
| 1007 | + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, | |
| 1008 | + [CLK_BUS_TS] = &bus_ts_clk.common.hw, | |
| 1009 | + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, | |
| 1010 | + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, | |
| 1011 | + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, | |
| 1012 | + [CLK_BUS_SPI2] = &bus_spi2_clk.common.hw, | |
| 1013 | + [CLK_BUS_SPI3] = &bus_spi3_clk.common.hw, | |
| 1014 | + [CLK_BUS_SATA] = &bus_sata_clk.common.hw, | |
| 1015 | + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, | |
| 1016 | + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, | |
| 1017 | + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, | |
| 1018 | + [CLK_BUS_EHCI2] = &bus_ehci2_clk.common.hw, | |
| 1019 | + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, | |
| 1020 | + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, | |
| 1021 | + [CLK_BUS_OHCI2] = &bus_ohci2_clk.common.hw, | |
| 1022 | + [CLK_BUS_VE] = &bus_ve_clk.common.hw, | |
| 1023 | + [CLK_BUS_MP] = &bus_mp_clk.common.hw, | |
| 1024 | + [CLK_BUS_DEINTERLACE] = &bus_deinterlace_clk.common.hw, | |
| 1025 | + [CLK_BUS_CSI0] = &bus_csi0_clk.common.hw, | |
| 1026 | + [CLK_BUS_CSI1] = &bus_csi1_clk.common.hw, | |
| 1027 | + [CLK_BUS_HDMI0] = &bus_hdmi0_clk.common.hw, | |
| 1028 | + [CLK_BUS_HDMI1] = &bus_hdmi1_clk.common.hw, | |
| 1029 | + [CLK_BUS_DE] = &bus_de_clk.common.hw, | |
| 1030 | + [CLK_BUS_TVE0] = &bus_tve0_clk.common.hw, | |
| 1031 | + [CLK_BUS_TVE1] = &bus_tve1_clk.common.hw, | |
| 1032 | + [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, | |
| 1033 | + [CLK_BUS_GMAC] = &bus_gmac_clk.common.hw, | |
| 1034 | + [CLK_BUS_GPU] = &bus_gpu_clk.common.hw, | |
| 1035 | + [CLK_BUS_TVD0] = &bus_tvd0_clk.common.hw, | |
| 1036 | + [CLK_BUS_TVD1] = &bus_tvd1_clk.common.hw, | |
| 1037 | + [CLK_BUS_TVD2] = &bus_tvd2_clk.common.hw, | |
| 1038 | + [CLK_BUS_TVD3] = &bus_tvd3_clk.common.hw, | |
| 1039 | + [CLK_BUS_TVD_TOP] = &bus_tvd_top_clk.common.hw, | |
| 1040 | + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw, | |
| 1041 | + [CLK_BUS_TCON_LCD1] = &bus_tcon_lcd1_clk.common.hw, | |
| 1042 | + [CLK_BUS_TCON_TV0] = &bus_tcon_tv0_clk.common.hw, | |
| 1043 | + [CLK_BUS_TCON_TV1] = &bus_tcon_tv1_clk.common.hw, | |
| 1044 | + [CLK_BUS_TCON_TOP] = &bus_tcon_top_clk.common.hw, | |
| 1045 | + [CLK_BUS_CODEC] = &bus_codec_clk.common.hw, | |
| 1046 | + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, | |
| 1047 | + [CLK_BUS_AC97] = &bus_ac97_clk.common.hw, | |
| 1048 | + [CLK_BUS_PIO] = &bus_pio_clk.common.hw, | |
| 1049 | + [CLK_BUS_IR0] = &bus_ir0_clk.common.hw, | |
| 1050 | + [CLK_BUS_IR1] = &bus_ir1_clk.common.hw, | |
| 1051 | + [CLK_BUS_THS] = &bus_ths_clk.common.hw, | |
| 1052 | + [CLK_BUS_KEYPAD] = &bus_keypad_clk.common.hw, | |
| 1053 | + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, | |
| 1054 | + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, | |
| 1055 | + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, | |
| 1056 | + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, | |
| 1057 | + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, | |
| 1058 | + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, | |
| 1059 | + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, | |
| 1060 | + [CLK_BUS_CAN] = &bus_can_clk.common.hw, | |
| 1061 | + [CLK_BUS_SCR] = &bus_scr_clk.common.hw, | |
| 1062 | + [CLK_BUS_PS20] = &bus_ps20_clk.common.hw, | |
| 1063 | + [CLK_BUS_PS21] = &bus_ps21_clk.common.hw, | |
| 1064 | + [CLK_BUS_I2C4] = &bus_i2c4_clk.common.hw, | |
| 1065 | + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, | |
| 1066 | + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, | |
| 1067 | + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, | |
| 1068 | + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, | |
| 1069 | + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, | |
| 1070 | + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, | |
| 1071 | + [CLK_BUS_UART6] = &bus_uart6_clk.common.hw, | |
| 1072 | + [CLK_BUS_UART7] = &bus_uart7_clk.common.hw, | |
| 1073 | + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, | |
| 1074 | + [CLK_THS] = &ths_clk.common.hw, | |
| 1075 | + [CLK_NAND] = &nand_clk.common.hw, | |
| 1076 | + [CLK_MMC0] = &mmc0_clk.common.hw, | |
| 1077 | + [CLK_MMC1] = &mmc1_clk.common.hw, | |
| 1078 | + [CLK_MMC2] = &mmc2_clk.common.hw, | |
| 1079 | + [CLK_MMC3] = &mmc3_clk.common.hw, | |
| 1080 | + [CLK_TS] = &ts_clk.common.hw, | |
| 1081 | + [CLK_CE] = &ce_clk.common.hw, | |
| 1082 | + [CLK_SPI0] = &spi0_clk.common.hw, | |
| 1083 | + [CLK_SPI1] = &spi1_clk.common.hw, | |
| 1084 | + [CLK_SPI2] = &spi2_clk.common.hw, | |
| 1085 | + [CLK_SPI3] = &spi3_clk.common.hw, | |
| 1086 | + [CLK_I2S0] = &i2s0_clk.common.hw, | |
| 1087 | + [CLK_I2S1] = &i2s1_clk.common.hw, | |
| 1088 | + [CLK_I2S2] = &i2s2_clk.common.hw, | |
| 1089 | + [CLK_AC97] = &ac97_clk.common.hw, | |
| 1090 | + [CLK_SPDIF] = &spdif_clk.common.hw, | |
| 1091 | + [CLK_KEYPAD] = &keypad_clk.common.hw, | |
| 1092 | + [CLK_SATA] = &sata_clk.common.hw, | |
| 1093 | + [CLK_USB_PHY0] = &usb_phy0_clk.common.hw, | |
| 1094 | + [CLK_USB_PHY1] = &usb_phy1_clk.common.hw, | |
| 1095 | + [CLK_USB_PHY2] = &usb_phy2_clk.common.hw, | |
| 1096 | + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, | |
| 1097 | + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, | |
| 1098 | + [CLK_USB_OHCI2] = &usb_ohci2_clk.common.hw, | |
| 1099 | + [CLK_IR0] = &ir0_clk.common.hw, | |
| 1100 | + [CLK_IR1] = &ir1_clk.common.hw, | |
| 1101 | + [CLK_DRAM] = &dram_clk.common.hw, | |
| 1102 | + [CLK_DRAM_VE] = &dram_ve_clk.common.hw, | |
| 1103 | + [CLK_DRAM_CSI0] = &dram_csi0_clk.common.hw, | |
| 1104 | + [CLK_DRAM_CSI1] = &dram_csi1_clk.common.hw, | |
| 1105 | + [CLK_DRAM_TS] = &dram_ts_clk.common.hw, | |
| 1106 | + [CLK_DRAM_TVD] = &dram_tvd_clk.common.hw, | |
| 1107 | + [CLK_DRAM_MP] = &dram_mp_clk.common.hw, | |
| 1108 | + [CLK_DRAM_DEINTERLACE] = &dram_deinterlace_clk.common.hw, | |
| 1109 | + [CLK_DE] = &de_clk.common.hw, | |
| 1110 | + [CLK_MP] = &mp_clk.common.hw, | |
| 1111 | + [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw, | |
| 1112 | + [CLK_TCON_LCD1] = &tcon_lcd1_clk.common.hw, | |
| 1113 | + [CLK_TCON_TV0] = &tcon_tv0_clk.common.hw, | |
| 1114 | + [CLK_TCON_TV1] = &tcon_tv1_clk.common.hw, | |
| 1115 | + [CLK_DEINTERLACE] = &deinterlace_clk.common.hw, | |
| 1116 | + [CLK_CSI1_MCLK] = &csi1_mclk_clk.common.hw, | |
| 1117 | + [CLK_CSI_SCLK] = &csi_sclk_clk.common.hw, | |
| 1118 | + [CLK_CSI0_MCLK] = &csi0_mclk_clk.common.hw, | |
| 1119 | + [CLK_VE] = &ve_clk.common.hw, | |
| 1120 | + [CLK_CODEC] = &codec_clk.common.hw, | |
| 1121 | + [CLK_AVS] = &avs_clk.common.hw, | |
| 1122 | + [CLK_HDMI] = &hdmi_clk.common.hw, | |
| 1123 | + [CLK_HDMI_SLOW] = &hdmi_slow_clk.common.hw, | |
| 1124 | + [CLK_MBUS] = &mbus_clk.common.hw, | |
| 1125 | + [CLK_DSI_DPHY] = &dsi_dphy_clk.common.hw, | |
| 1126 | + [CLK_TVE0] = &tve0_clk.common.hw, | |
| 1127 | + [CLK_TVE1] = &tve1_clk.common.hw, | |
| 1128 | + [CLK_TVD0] = &tvd0_clk.common.hw, | |
| 1129 | + [CLK_TVD1] = &tvd1_clk.common.hw, | |
| 1130 | + [CLK_TVD2] = &tvd2_clk.common.hw, | |
| 1131 | + [CLK_TVD3] = &tvd3_clk.common.hw, | |
| 1132 | + [CLK_GPU] = &gpu_clk.common.hw, | |
| 1133 | + [CLK_OUTA] = &outa_clk.common.hw, | |
| 1134 | + [CLK_OUTB] = &outb_clk.common.hw, | |
| 1135 | + }, | |
| 1136 | + .num = CLK_NUMBER, | |
| 1137 | +}; | |
| 1138 | + | |
| 1139 | +static struct ccu_reset_map sun8i_r40_ccu_resets[] = { | |
| 1140 | + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, | |
| 1141 | + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, | |
| 1142 | + [RST_USB_PHY2] = { 0x0cc, BIT(2) }, | |
| 1143 | + | |
| 1144 | + [RST_DRAM] = { 0x0f4, BIT(31) }, | |
| 1145 | + [RST_MBUS] = { 0x0fc, BIT(31) }, | |
| 1146 | + | |
| 1147 | + [RST_BUS_MIPI_DSI] = { 0x2c0, BIT(1) }, | |
| 1148 | + [RST_BUS_CE] = { 0x2c0, BIT(5) }, | |
| 1149 | + [RST_BUS_DMA] = { 0x2c0, BIT(6) }, | |
| 1150 | + [RST_BUS_MMC0] = { 0x2c0, BIT(8) }, | |
| 1151 | + [RST_BUS_MMC1] = { 0x2c0, BIT(9) }, | |
| 1152 | + [RST_BUS_MMC2] = { 0x2c0, BIT(10) }, | |
| 1153 | + [RST_BUS_MMC3] = { 0x2c0, BIT(11) }, | |
| 1154 | + [RST_BUS_NAND] = { 0x2c0, BIT(13) }, | |
| 1155 | + [RST_BUS_DRAM] = { 0x2c0, BIT(14) }, | |
| 1156 | + [RST_BUS_EMAC] = { 0x2c0, BIT(17) }, | |
| 1157 | + [RST_BUS_TS] = { 0x2c0, BIT(18) }, | |
| 1158 | + [RST_BUS_HSTIMER] = { 0x2c0, BIT(19) }, | |
| 1159 | + [RST_BUS_SPI0] = { 0x2c0, BIT(20) }, | |
| 1160 | + [RST_BUS_SPI1] = { 0x2c0, BIT(21) }, | |
| 1161 | + [RST_BUS_SPI2] = { 0x2c0, BIT(22) }, | |
| 1162 | + [RST_BUS_SPI3] = { 0x2c0, BIT(23) }, | |
| 1163 | + [RST_BUS_SATA] = { 0x2c0, BIT(24) }, | |
| 1164 | + [RST_BUS_OTG] = { 0x2c0, BIT(25) }, | |
| 1165 | + [RST_BUS_EHCI0] = { 0x2c0, BIT(26) }, | |
| 1166 | + [RST_BUS_EHCI1] = { 0x2c0, BIT(27) }, | |
| 1167 | + [RST_BUS_EHCI2] = { 0x2c0, BIT(28) }, | |
| 1168 | + [RST_BUS_OHCI0] = { 0x2c0, BIT(29) }, | |
| 1169 | + [RST_BUS_OHCI1] = { 0x2c0, BIT(30) }, | |
| 1170 | + [RST_BUS_OHCI2] = { 0x2c0, BIT(31) }, | |
| 1171 | + | |
| 1172 | + [RST_BUS_VE] = { 0x2c4, BIT(0) }, | |
| 1173 | + [RST_BUS_MP] = { 0x2c4, BIT(2) }, | |
| 1174 | + [RST_BUS_DEINTERLACE] = { 0x2c4, BIT(5) }, | |
| 1175 | + [RST_BUS_CSI0] = { 0x2c4, BIT(8) }, | |
| 1176 | + [RST_BUS_CSI1] = { 0x2c4, BIT(9) }, | |
| 1177 | + [RST_BUS_HDMI0] = { 0x2c4, BIT(10) }, | |
| 1178 | + [RST_BUS_HDMI1] = { 0x2c4, BIT(11) }, | |
| 1179 | + [RST_BUS_DE] = { 0x2c4, BIT(12) }, | |
| 1180 | + [RST_BUS_TVE0] = { 0x2c4, BIT(13) }, | |
| 1181 | + [RST_BUS_TVE1] = { 0x2c4, BIT(14) }, | |
| 1182 | + [RST_BUS_TVE_TOP] = { 0x2c4, BIT(15) }, | |
| 1183 | + [RST_BUS_GMAC] = { 0x2c4, BIT(17) }, | |
| 1184 | + [RST_BUS_GPU] = { 0x2c4, BIT(20) }, | |
| 1185 | + [RST_BUS_TVD0] = { 0x2c4, BIT(21) }, | |
| 1186 | + [RST_BUS_TVD1] = { 0x2c4, BIT(22) }, | |
| 1187 | + [RST_BUS_TVD2] = { 0x2c4, BIT(23) }, | |
| 1188 | + [RST_BUS_TVD3] = { 0x2c4, BIT(24) }, | |
| 1189 | + [RST_BUS_TVD_TOP] = { 0x2c4, BIT(25) }, | |
| 1190 | + [RST_BUS_TCON_LCD0] = { 0x2c4, BIT(26) }, | |
| 1191 | + [RST_BUS_TCON_LCD1] = { 0x2c4, BIT(27) }, | |
| 1192 | + [RST_BUS_TCON_TV0] = { 0x2c4, BIT(28) }, | |
| 1193 | + [RST_BUS_TCON_TV1] = { 0x2c4, BIT(29) }, | |
| 1194 | + [RST_BUS_TCON_TOP] = { 0x2c4, BIT(30) }, | |
| 1195 | + [RST_BUS_DBG] = { 0x2c4, BIT(31) }, | |
| 1196 | + | |
| 1197 | + [RST_BUS_LVDS] = { 0x2c8, BIT(0) }, | |
| 1198 | + | |
| 1199 | + [RST_BUS_CODEC] = { 0x2d0, BIT(0) }, | |
| 1200 | + [RST_BUS_SPDIF] = { 0x2d0, BIT(1) }, | |
| 1201 | + [RST_BUS_AC97] = { 0x2d0, BIT(2) }, | |
| 1202 | + [RST_BUS_IR0] = { 0x2d0, BIT(6) }, | |
| 1203 | + [RST_BUS_IR1] = { 0x2d0, BIT(7) }, | |
| 1204 | + [RST_BUS_THS] = { 0x2d0, BIT(8) }, | |
| 1205 | + [RST_BUS_KEYPAD] = { 0x2d0, BIT(10) }, | |
| 1206 | + [RST_BUS_I2S0] = { 0x2d0, BIT(12) }, | |
| 1207 | + [RST_BUS_I2S1] = { 0x2d0, BIT(13) }, | |
| 1208 | + [RST_BUS_I2S2] = { 0x2d0, BIT(14) }, | |
| 1209 | + | |
| 1210 | + [RST_BUS_I2C0] = { 0x2d8, BIT(0) }, | |
| 1211 | + [RST_BUS_I2C1] = { 0x2d8, BIT(1) }, | |
| 1212 | + [RST_BUS_I2C2] = { 0x2d8, BIT(2) }, | |
| 1213 | + [RST_BUS_I2C3] = { 0x2d8, BIT(3) }, | |
| 1214 | + [RST_BUS_CAN] = { 0x2d8, BIT(4) }, | |
| 1215 | + [RST_BUS_SCR] = { 0x2d8, BIT(5) }, | |
| 1216 | + [RST_BUS_PS20] = { 0x2d8, BIT(6) }, | |
| 1217 | + [RST_BUS_PS21] = { 0x2d8, BIT(7) }, | |
| 1218 | + [RST_BUS_I2C4] = { 0x2d8, BIT(15) }, | |
| 1219 | + [RST_BUS_UART0] = { 0x2d8, BIT(16) }, | |
| 1220 | + [RST_BUS_UART1] = { 0x2d8, BIT(17) }, | |
| 1221 | + [RST_BUS_UART2] = { 0x2d8, BIT(18) }, | |
| 1222 | + [RST_BUS_UART3] = { 0x2d8, BIT(19) }, | |
| 1223 | + [RST_BUS_UART4] = { 0x2d8, BIT(20) }, | |
| 1224 | + [RST_BUS_UART5] = { 0x2d8, BIT(21) }, | |
| 1225 | + [RST_BUS_UART6] = { 0x2d8, BIT(22) }, | |
| 1226 | + [RST_BUS_UART7] = { 0x2d8, BIT(23) }, | |
| 1227 | +}; | |
| 1228 | + | |
| 1229 | +static const struct sunxi_ccu_desc sun8i_r40_ccu_desc = { | |
| 1230 | + .ccu_clks = sun8i_r40_ccu_clks, | |
| 1231 | + .num_ccu_clks = ARRAY_SIZE(sun8i_r40_ccu_clks), | |
| 1232 | + | |
| 1233 | + .hw_clks = &sun8i_r40_hw_clks, | |
| 1234 | + | |
| 1235 | + .resets = sun8i_r40_ccu_resets, | |
| 1236 | + .num_resets = ARRAY_SIZE(sun8i_r40_ccu_resets), | |
| 1237 | +}; | |
| 1238 | + | |
| 1239 | +static struct ccu_pll_nb sun8i_r40_pll_cpu_nb = { | |
| 1240 | + .common = &pll_cpu_clk.common, | |
| 1241 | + /* copy from pll_cpu_clk */ | |
| 1242 | + .enable = BIT(31), | |
| 1243 | + .lock = BIT(28), | |
| 1244 | +}; | |
| 1245 | + | |
| 1246 | +static struct ccu_mux_nb sun8i_r40_cpu_nb = { | |
| 1247 | + .common = &cpu_clk.common, | |
| 1248 | + .cm = &cpu_clk.mux, | |
| 1249 | + .delay_us = 1, /* > 8 clock cycles at 24 MHz */ | |
| 1250 | + .bypass_index = 1, /* index of 24 MHz oscillator */ | |
| 1251 | +}; | |
| 1252 | + | |
| 1253 | +static void __init sun8i_r40_ccu_setup(struct device_node *node) | |
| 1254 | +{ | |
| 1255 | + void __iomem *reg; | |
| 1256 | + u32 val; | |
| 1257 | + | |
| 1258 | + reg = of_io_request_and_map(node, 0, of_node_full_name(node)); | |
| 1259 | + if (IS_ERR(reg)) { | |
| 1260 | + pr_err("%s: Could not map the clock registers\n", | |
| 1261 | + of_node_full_name(node)); | |
| 1262 | + return; | |
| 1263 | + } | |
| 1264 | + | |
| 1265 | + /* Force the PLL-Audio-1x divider to 4 */ | |
| 1266 | + val = readl(reg + SUN8I_R40_PLL_AUDIO_REG); | |
| 1267 | + val &= ~GENMASK(19, 16); | |
| 1268 | + writel(val | (3 << 16), reg + SUN8I_R40_PLL_AUDIO_REG); | |
| 1269 | + | |
| 1270 | + /* Force PLL-MIPI to MIPI mode */ | |
| 1271 | + val = readl(reg + SUN8I_R40_PLL_MIPI_REG); | |
| 1272 | + val &= ~BIT(16); | |
| 1273 | + writel(val, reg + SUN8I_R40_PLL_MIPI_REG); | |
| 1274 | + | |
| 1275 | + /* Force OHCI 12M parent to 12M divided from 48M */ | |
| 1276 | + val = readl(reg + SUN8I_R40_USB_CLK_REG); | |
| 1277 | + val &= ~GENMASK(25, 20); | |
| 1278 | + writel(val, reg + SUN8I_R40_USB_CLK_REG); | |
| 1279 | + | |
| 1280 | + sunxi_ccu_probe(node, reg, &sun8i_r40_ccu_desc); | |
| 1281 | + | |
| 1282 | + /* Gate then ungate PLL CPU after any rate changes */ | |
| 1283 | + ccu_pll_notifier_register(&sun8i_r40_pll_cpu_nb); | |
| 1284 | + | |
| 1285 | + /* Reparent CPU during PLL CPU rate changes */ | |
| 1286 | + ccu_mux_notifier_register(pll_cpu_clk.common.hw.clk, | |
| 1287 | + &sun8i_r40_cpu_nb); | |
| 1288 | +} | |
| 1289 | +CLK_OF_DECLARE(sun8i_r40_ccu, "allwinner,sun8i-r40-ccu", | |
| 1290 | + sun8i_r40_ccu_setup); | |
| @@ -0,0 +1,69 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright 2017 Icenowy Zheng <icenowy@aosc.io> | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 2 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + * | |
| 9 | + * This program is distributed in the hope that it will be useful, | |
| 10 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 | + * GNU General Public License for more details. | |
| 13 | + */ | |
| 14 | + | |
| 15 | +#ifndef _CCU_SUN8I_R40_H_ | |
| 16 | +#define _CCU_SUN8I_R40_H_ | |
| 17 | + | |
| 18 | +#include <dt-bindings/clock/sun8i-r40-ccu.h> | |
| 19 | +#include <dt-bindings/reset/sun8i-r40-ccu.h> | |
| 20 | + | |
| 21 | +#define CLK_OSC_12M 0 | |
| 22 | +#define CLK_PLL_CPU 1 | |
| 23 | +#define CLK_PLL_AUDIO_BASE 2 | |
| 24 | +#define CLK_PLL_AUDIO 3 | |
| 25 | +#define CLK_PLL_AUDIO_2X 4 | |
| 26 | +#define CLK_PLL_AUDIO_4X 5 | |
| 27 | +#define CLK_PLL_AUDIO_8X 6 | |
| 28 | +#define CLK_PLL_VIDEO0 7 | |
| 29 | +#define CLK_PLL_VIDEO0_2X 8 | |
| 30 | +#define CLK_PLL_VE 9 | |
| 31 | +#define CLK_PLL_DDR0 10 | |
| 32 | +#define CLK_PLL_PERIPH0 11 | |
| 33 | +#define CLK_PLL_PERIPH0_SATA 12 | |
| 34 | +#define CLK_PLL_PERIPH0_2X 13 | |
| 35 | +#define CLK_PLL_PERIPH1 14 | |
| 36 | +#define CLK_PLL_PERIPH1_2X 15 | |
| 37 | +#define CLK_PLL_VIDEO1 16 | |
| 38 | +#define CLK_PLL_VIDEO1_2X 17 | |
| 39 | +#define CLK_PLL_SATA 18 | |
| 40 | +#define CLK_PLL_SATA_OUT 19 | |
| 41 | +#define CLK_PLL_GPU 20 | |
| 42 | +#define CLK_PLL_MIPI 21 | |
| 43 | +#define CLK_PLL_DE 22 | |
| 44 | +#define CLK_PLL_DDR1 23 | |
| 45 | + | |
| 46 | +/* The CPU clock is exported */ | |
| 47 | + | |
| 48 | +#define CLK_AXI 25 | |
| 49 | +#define CLK_AHB1 26 | |
| 50 | +#define CLK_APB1 27 | |
| 51 | +#define CLK_APB2 28 | |
| 52 | + | |
| 53 | +/* All the bus gates are exported */ | |
| 54 | + | |
| 55 | +/* The first bunch of module clocks are exported */ | |
| 56 | + | |
| 57 | +#define CLK_DRAM 132 | |
| 58 | + | |
| 59 | +/* All the DRAM gates are exported */ | |
| 60 | + | |
| 61 | +/* Some more module clocks are exported */ | |
| 62 | + | |
| 63 | +#define CLK_MBUS 155 | |
| 64 | + | |
| 65 | +/* Another bunch of module clocks are exported */ | |
| 66 | + | |
| 67 | +#define CLK_NUMBER (CLK_OUTB + 1) | |
| 68 | + | |
| 69 | +#endif /* _CCU_SUN8I_R40_H_ */ | |
| @@ -575,8 +575,7 @@ static void __init sun8i_v3s_ccu_setup(struct device_node *node) · 574 unmodified lines | ||
| 575 | 575 | |
| 576 | 576 | reg = of_io_request_and_map(node, 0, of_node_full_name(node)); |
| 577 | 577 | if (IS_ERR(reg)) { |
| 578 | − pr_err("%s: Could not map the clock registers\n", | |
| 579 | − of_node_full_name(node)); | |
| 578 | + pr_err("%pOF: Could not map the clock registers\n", node); | |
| 580 | 579 | return; |
| 581 | 580 | } |
| 582 | 581 | |
| @@ -21,10 +21,18 @@ static unsigned long ccu_div_round_rate(struct ccu_mux_internal *mux, · 20 unmodified lines | ||
| 21 | 21 | { |
| 22 | 22 | struct ccu_div *cd = data; |
| 23 | 23 | |
| 24 | − return divider_round_rate_parent(&cd->common.hw, parent, | |
| 24 | + if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 25 | + rate *= cd->fixed_post_div; | |
| 26 | + | |
| 27 | + rate = divider_round_rate_parent(&cd->common.hw, parent, | |
| 25 | 28 | rate, parent_rate, |
| 26 | 29 | cd->div.table, cd->div.width, |
| 27 | 30 | cd->div.flags); |
| 31 | + | |
| 32 | + if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 33 | + rate /= cd->fixed_post_div; | |
| 34 | + | |
| 35 | + return rate; | |
| 28 | 36 | } |
| 29 | 37 | |
| 30 | 38 | static void ccu_div_disable(struct clk_hw *hw) |
| @@ -62,8 +70,13 @@ static unsigned long ccu_div_recalc_rate(struct clk_hw *hw, · 31 unmodified lines | ||
| 62 | 70 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, |
| 63 | 71 | parent_rate); |
| 64 | 72 | |
| 65 | − return divider_recalc_rate(hw, parent_rate, val, cd->div.table, | |
| 66 | − cd->div.flags); | |
| 73 | + val = divider_recalc_rate(hw, parent_rate, val, cd->div.table, | |
| 74 | + cd->div.flags); | |
| 75 | + | |
| 76 | + if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 77 | + val /= cd->fixed_post_div; | |
| 78 | + | |
| 79 | + return val; | |
| 67 | 80 | } |
| 68 | 81 | |
| 69 | 82 | static int ccu_div_determine_rate(struct clk_hw *hw, |
| @@ -86,6 +99,9 @@ static int ccu_div_set_rate(struct clk_hw *hw, unsigned long rate, · 16 unmodified lines | ||
| 86 | 99 | parent_rate = ccu_mux_helper_apply_prediv(&cd->common, &cd->mux, -1, |
| 87 | 100 | parent_rate); |
| 88 | 101 | |
| 102 | + if (cd->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 103 | + rate *= cd->fixed_post_div; | |
| 104 | + | |
| 89 | 105 | val = divider_get_val(rate, parent_rate, cd->div.table, cd->div.width, |
| 90 | 106 | cd->div.flags); |
| 91 | 107 | |
| @@ -86,9 +86,10 @@ struct ccu_div_internal { · 85 unmodified lines | ||
| 86 | 86 | struct ccu_div { |
| 87 | 87 | u32 enable; |
| 88 | 88 | |
| 89 | − struct ccu_div_internal div; | |
| 89 | + struct ccu_div_internal div; | |
| 90 | 90 | struct ccu_mux_internal mux; |
| 91 | 91 | struct ccu_common common; |
| 92 | + unsigned int fixed_post_div; | |
| 92 | 93 | }; |
| 93 | 94 | |
| 94 | 95 | #define SUNXI_CCU_DIV_TABLE_WITH_GATE(_struct, _name, _parent, _reg, \ |
| @@ -67,25 +67,25 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, · 66 unmodified lines | ||
| 67 | 67 | { |
| 68 | 68 | u32 reg; |
| 69 | 69 | |
| 70 | − printk("%s: Read fractional\n", clk_hw_get_name(&common->hw)); | |
| 70 | + pr_debug("%s: Read fractional\n", clk_hw_get_name(&common->hw)); | |
| 71 | 71 | |
| 72 | 72 | if (!(common->features & CCU_FEATURE_FRACTIONAL)) |
| 73 | 73 | return 0; |
| 74 | 74 | |
| 75 | − printk("%s: clock is fractional (rates %lu and %lu)\n", | |
| 76 | − clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]); | |
| 75 | + pr_debug("%s: clock is fractional (rates %lu and %lu)\n", | |
| 76 | + clk_hw_get_name(&common->hw), cf->rates[0], cf->rates[1]); | |
| 77 | 77 | |
| 78 | 78 | reg = readl(common->base + common->reg); |
| 79 | 79 | |
| 80 | − printk("%s: clock reg is 0x%x (select is 0x%x)\n", | |
| 81 | − clk_hw_get_name(&common->hw), reg, cf->select); | |
| 80 | + pr_debug("%s: clock reg is 0x%x (select is 0x%x)\n", | |
| 81 | + clk_hw_get_name(&common->hw), reg, cf->select); | |
| 82 | 82 | |
| 83 | 83 | return (reg & cf->select) ? cf->rates[1] : cf->rates[0]; |
| 84 | 84 | } |
| 85 | 85 | |
| 86 | 86 | int ccu_frac_helper_set_rate(struct ccu_common *common, |
| 87 | 87 | struct ccu_frac_internal *cf, |
| 88 | − unsigned long rate) | |
| 88 | + unsigned long rate, u32 lock) | |
| 89 | 89 | { |
| 90 | 90 | unsigned long flags; |
| 91 | 91 | u32 reg, sel; |
| @@ -106,5 +106,7 @@ int ccu_frac_helper_set_rate(struct ccu_common *common, · 14 unmodified lines | ||
| 106 | 106 | writel(reg | sel, common->base + common->reg); |
| 107 | 107 | spin_unlock_irqrestore(common->lock, flags); |
| 108 | 108 | |
| 109 | + ccu_helper_wait_for_lock(common, lock); | |
| 110 | + | |
| 109 | 111 | return 0; |
| 110 | 112 | } |
| @@ -48,6 +48,6 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common, · 47 unmodified lines | ||
| 48 | 48 | |
| 49 | 49 | int ccu_frac_helper_set_rate(struct ccu_common *common, |
| 50 | 50 | struct ccu_frac_internal *cf, |
| 51 | − unsigned long rate); | |
| 51 | + unsigned long rate, u32 lock); | |
| 52 | 52 | |
| 53 | 53 | #endif /* _CCU_FRAC_H_ */ |
| @@ -111,10 +111,14 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate, · 110 unmodified lines | ||
| 111 | 111 | unsigned long flags; |
| 112 | 112 | u32 reg; |
| 113 | 113 | |
| 114 | − if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) | |
| 115 | − return ccu_frac_helper_set_rate(&cm->common, &cm->frac, rate); | |
| 116 | − else | |
| 114 | + if (ccu_frac_helper_has_rate(&cm->common, &cm->frac, rate)) { | |
| 115 | + ccu_frac_helper_enable(&cm->common, &cm->frac); | |
| 116 | + | |
| 117 | + return ccu_frac_helper_set_rate(&cm->common, &cm->frac, | |
| 118 | + rate, cm->lock); | |
| 119 | + } else { | |
| 117 | 120 | ccu_frac_helper_disable(&cm->common, &cm->frac); |
| 121 | + } | |
| 118 | 122 | |
| 119 | 123 | parent_rate = ccu_mux_helper_apply_prediv(&cm->common, &cm->mux, -1, |
| 120 | 124 | parent_rate); |
| @@ -75,7 +75,7 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, · 74 unmodified lines | ||
| 75 | 75 | unsigned long parent_rate) |
| 76 | 76 | { |
| 77 | 77 | struct ccu_nkm *nkm = hw_to_ccu_nkm(hw); |
| 78 | − unsigned long n, m, k; | |
| 78 | + unsigned long n, m, k, rate; | |
| 79 | 79 | u32 reg; |
| 80 | 80 | |
| 81 | 81 | reg = readl(nkm->common.base + nkm->common.reg); |
| @@ -98,7 +98,12 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw, · 16 unmodified lines | ||
| 98 | 98 | if (!m) |
| 99 | 99 | m++; |
| 100 | 100 | |
| 101 | − return parent_rate * n * k / m; | |
| 101 | + rate = parent_rate * n * k / m; | |
| 102 | + | |
| 103 | + if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 104 | + rate /= nkm->fixed_post_div; | |
| 105 | + | |
| 106 | + return rate; | |
| 102 | 107 | } |
| 103 | 108 | |
| 104 | 109 | static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, |
| @@ -117,9 +122,17 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux, · 12 unmodified lines | ||
| 117 | 122 | _nkm.min_m = 1; |
| 118 | 123 | _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width; |
| 119 | 124 | |
| 125 | + if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 126 | + rate *= nkm->fixed_post_div; | |
| 127 | + | |
| 120 | 128 | ccu_nkm_find_best(*parent_rate, rate, &_nkm); |
| 121 | 129 | |
| 122 | − return *parent_rate * _nkm.n * _nkm.k / _nkm.m; | |
| 130 | + rate = *parent_rate * _nkm.n * _nkm.k / _nkm.m; | |
| 131 | + | |
| 132 | + if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 133 | + rate /= nkm->fixed_post_div; | |
| 134 | + | |
| 135 | + return rate; | |
| 123 | 136 | } |
| 124 | 137 | |
| 125 | 138 | static int ccu_nkm_determine_rate(struct clk_hw *hw, |
| @@ -139,6 +152,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate, · 13 unmodified lines | ||
| 139 | 152 | unsigned long flags; |
| 140 | 153 | u32 reg; |
| 141 | 154 | |
| 155 | + if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV) | |
| 156 | + rate *= nkm->fixed_post_div; | |
| 157 | + | |
| 142 | 158 | _nkm.min_n = nkm->n.min ?: 1; |
| 143 | 159 | _nkm.max_n = nkm->n.max ?: 1 << nkm->n.width; |
| 144 | 160 | _nkm.min_k = nkm->k.min ?: 1; |
| @@ -34,6 +34,8 @@ struct ccu_nkm { · 33 unmodified lines | ||
| 34 | 34 | struct ccu_div_internal m; |
| 35 | 35 | struct ccu_mux_internal mux; |
| 36 | 36 | |
| 37 | + unsigned int fixed_post_div; | |
| 38 | + | |
| 37 | 39 | struct ccu_common common; |
| 38 | 40 | }; |
| 39 | 41 | |
| @@ -117,10 +117,23 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate, · 116 unmodified lines | ||
| 117 | 117 | unsigned long flags; |
| 118 | 118 | u32 reg; |
| 119 | 119 | |
| 120 | − if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) | |
| 121 | − return ccu_frac_helper_set_rate(&nm->common, &nm->frac, rate); | |
| 122 | − else | |
| 120 | + if (ccu_frac_helper_has_rate(&nm->common, &nm->frac, rate)) { | |
| 121 | + spin_lock_irqsave(nm->common.lock, flags); | |
| 122 | + | |
| 123 | + /* most SoCs require M to be 0 if fractional mode is used */ | |
| 124 | + reg = readl(nm->common.base + nm->common.reg); | |
| 125 | + reg &= ~GENMASK(nm->m.width + nm->m.shift - 1, nm->m.shift); | |
| 126 | + writel(reg, nm->common.base + nm->common.reg); | |
| 127 | + | |
| 128 | + spin_unlock_irqrestore(nm->common.lock, flags); | |
| 129 | + | |
| 130 | + ccu_frac_helper_enable(&nm->common, &nm->frac); | |
| 131 | + | |
| 132 | + return ccu_frac_helper_set_rate(&nm->common, &nm->frac, | |
| 133 | + rate, nm->lock); | |
| 134 | + } else { | |
| 123 | 135 | ccu_frac_helper_disable(&nm->common, &nm->frac); |
| 136 | + } | |
| 124 | 137 | |
| 125 | 138 | _nm.min_n = nm->n.min ?: 1; |
| 126 | 139 | _nm.max_n = nm->n.max ?: 1 << nm->n.width; |
| @@ -78,6 +78,10 @@ static void __init sun8i_h3_bus_gates_init(struct device_node *node) · 77 unmodified lines | ||
| 78 | 78 | clk_parent = APB1; |
| 79 | 79 | else if (index >= 96 && index <= 127) |
| 80 | 80 | clk_parent = APB2; |
| 81 | + else { | |
| 82 | + WARN_ON(true); | |
| 83 | + continue; | |
| 84 | + } | |
| 81 | 85 | |
| 82 | 86 | clk_reg = reg + 4 * (index / 32); |
| 83 | 87 | clk_bit = index % 32; |
| @@ -666,15 +666,14 @@ static struct clk * __init sunxi_mux_clk_setup(struct device_node *node, · 665 unmodified lines | ||
| 666 | 666 | |
| 667 | 667 | reg = of_iomap(node, 0); |
| 668 | 668 | if (!reg) { |
| 669 | − pr_err("Could not map registers for mux-clk: %s\n", | |
| 670 | − of_node_full_name(node)); | |
| 669 | + pr_err("Could not map registers for mux-clk: %pOF\n", node); | |
| 671 | 670 | return NULL; |
| 672 | 671 | } |
| 673 | 672 | |
| 674 | 673 | i = of_clk_parent_fill(node, parents, SUNXI_MAX_PARENTS); |
| 675 | 674 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { |
| 676 | − pr_err("%s: could not read clock-output-names from \"%s\"\n", | |
| 677 | − __func__, of_node_full_name(node)); | |
| 675 | + pr_err("%s: could not read clock-output-names from \"%pOF\"\n", | |
| 676 | + __func__, node); | |
| 678 | 677 | goto out_unmap; |
| 679 | 678 | } |
| 680 | 679 | |
| @@ -797,16 +796,15 @@ static void __init sunxi_divider_clk_setup(struct device_node *node, · 116 unmodified lines | ||
| 797 | 796 | |
| 798 | 797 | reg = of_iomap(node, 0); |
| 799 | 798 | if (!reg) { |
| 800 | − pr_err("Could not map registers for mux-clk: %s\n", | |
| 801 | − of_node_full_name(node)); | |
| 799 | + pr_err("Could not map registers for mux-clk: %pOF\n", node); | |
| 802 | 800 | return; |
| 803 | 801 | } |
| 804 | 802 | |
| 805 | 803 | clk_parent = of_clk_get_parent_name(node, 0); |
| 806 | 804 | |
| 807 | 805 | if (of_property_read_string(node, "clock-output-names", &clk_name)) { |
| 808 | − pr_err("%s: could not read clock-output-names from \"%s\"\n", | |
| 809 | − __func__, of_node_full_name(node)); | |
| 806 | + pr_err("%s: could not read clock-output-names from \"%pOF\"\n", | |
| 807 | + __func__, node); | |
| 810 | 808 | goto out_unmap; |
| 811 | 809 | } |
| 812 | 810 | |
| @@ -1010,8 +1008,7 @@ static struct clk ** __init sunxi_divs_clk_setup(struct device_node *node, · 197 unmodified lines | ||
| 1010 | 1008 | |
| 1011 | 1009 | reg = of_iomap(node, 0); |
| 1012 | 1010 | if (!reg) { |
| 1013 | − pr_err("Could not map registers for divs-clk: %s\n", | |
| 1014 | − of_node_full_name(node)); | |
| 1011 | + pr_err("Could not map registers for divs-clk: %pOF\n", node); | |
| 1015 | 1012 | return NULL; |
| 1016 | 1013 | } |
| 1017 | 1014 | |
| @@ -378,7 +378,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, · 377 unmodified lines | ||
| 378 | 378 | |
| 379 | 379 | err = of_property_read_u32(node, "clock-frequency", &tmp); |
| 380 | 380 | if (err) { |
| 381 | − pr_err("timing %s: failed to read rate\n", node->full_name); | |
| 381 | + pr_err("timing %pOF: failed to read rate\n", node); | |
| 382 | 382 | return err; |
| 383 | 383 | } |
| 384 | 384 | |
| @@ -386,8 +386,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, · 1 unmodified line | ||
| 386 | 386 | |
| 387 | 387 | err = of_property_read_u32(node, "nvidia,parent-clock-frequency", &tmp); |
| 388 | 388 | if (err) { |
| 389 | − pr_err("timing %s: failed to read parent rate\n", | |
| 390 | − node->full_name); | |
| 389 | + pr_err("timing %pOF: failed to read parent rate\n", node); | |
| 391 | 390 | return err; |
| 392 | 391 | } |
| 393 | 392 | |
| @@ -395,8 +394,7 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, · 1 unmodified line | ||
| 395 | 394 | |
| 396 | 395 | timing->parent = of_clk_get_by_name(node, "emc-parent"); |
| 397 | 396 | if (IS_ERR(timing->parent)) { |
| 398 | − pr_err("timing %s: failed to get parent clock\n", | |
| 399 | − node->full_name); | |
| 397 | + pr_err("timing %pOF: failed to get parent clock\n", node); | |
| 400 | 398 | return PTR_ERR(timing->parent); |
| 401 | 399 | } |
| 402 | 400 | |
| @@ -409,8 +407,8 @@ static int load_one_timing_from_dt(struct tegra_clk_emc *tegra, · 6 unmodified lines | ||
| 409 | 407 | } |
| 410 | 408 | } |
| 411 | 409 | if (timing->parent_index == 0xff) { |
| 412 | − pr_err("timing %s: %s is not a valid parent\n", | |
| 413 | − node->full_name, __clk_get_name(timing->parent)); | |
| 410 | + pr_err("timing %pOF: %s is not a valid parent\n", | |
| 411 | + node, __clk_get_name(timing->parent)); | |
| 414 | 412 | clk_put(timing->parent); |
| 415 | 413 | return -EINVAL; |
| 416 | 414 | } |
| @@ -363,7 +363,7 @@ static void _clk_pll_enable(struct clk_hw *hw) · 362 unmodified lines | ||
| 363 | 363 | val = pll_readl(pll->params->iddq_reg, pll); |
| 364 | 364 | val &= ~BIT(pll->params->iddq_bit_idx); |
| 365 | 365 | pll_writel(val, pll->params->iddq_reg, pll); |
| 366 | − udelay(2); | |
| 366 | + udelay(5); | |
| 367 | 367 | } |
| 368 | 368 | |
| 369 | 369 | if (pll->params->reset_reg) { |
| @@ -418,6 +418,26 @@ static void _clk_pll_disable(struct clk_hw *hw) · 48 unmodified lines | ||
| 418 | 418 | } |
| 419 | 419 | } |
| 420 | 420 | |
| 421 | +static void pll_clk_start_ss(struct tegra_clk_pll *pll) | |
| 422 | +{ | |
| 423 | + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | |
| 424 | + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | |
| 425 | + | |
| 426 | + val |= pll->params->ssc_ctrl_en_mask; | |
| 427 | + pll_writel(val, pll->params->ssc_ctrl_reg, pll); | |
| 428 | + } | |
| 429 | +} | |
| 430 | + | |
| 431 | +static void pll_clk_stop_ss(struct tegra_clk_pll *pll) | |
| 432 | +{ | |
| 433 | + if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | |
| 434 | + u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | |
| 435 | + | |
| 436 | + val &= ~pll->params->ssc_ctrl_en_mask; | |
| 437 | + pll_writel(val, pll->params->ssc_ctrl_reg, pll); | |
| 438 | + } | |
| 439 | +} | |
| 440 | + | |
| 421 | 441 | static int clk_pll_enable(struct clk_hw *hw) |
| 422 | 442 | { |
| 423 | 443 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
| @@ -431,6 +451,8 @@ static int clk_pll_enable(struct clk_hw *hw) · 7 unmodified lines | ||
| 431 | 451 | |
| 432 | 452 | ret = clk_pll_wait_for_lock(pll); |
| 433 | 453 | |
| 454 | + pll_clk_start_ss(pll); | |
| 455 | + | |
| 434 | 456 | if (pll->lock) |
| 435 | 457 | spin_unlock_irqrestore(pll->lock, flags); |
| 436 | 458 | |
| @@ -445,6 +467,8 @@ static void clk_pll_disable(struct clk_hw *hw) · 8 unmodified lines | ||
| 445 | 467 | if (pll->lock) |
| 446 | 468 | spin_lock_irqsave(pll->lock, flags); |
| 447 | 469 | |
| 470 | + pll_clk_stop_ss(pll); | |
| 471 | + | |
| 448 | 472 | _clk_pll_disable(hw); |
| 449 | 473 | |
| 450 | 474 | if (pll->lock) |
| @@ -666,6 +690,8 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, · 215 unmodified lines | ||
| 666 | 690 | struct tegra_clk_pll_params *params = pll->params; |
| 667 | 691 | struct div_nmp *div_nmp = params->div_nmp; |
| 668 | 692 | |
| 693 | + *cfg = (struct tegra_clk_pll_freq_table) { }; | |
| 694 | + | |
| 669 | 695 | if ((params->flags & (TEGRA_PLLM | TEGRA_PLLMB)) && |
| 670 | 696 | (pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) & |
| 671 | 697 | PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) { |
| @@ -716,26 +742,6 @@ static void _update_pll_cpcon(struct tegra_clk_pll *pll, · 44 unmodified lines | ||
| 716 | 742 | pll_writel_misc(val, pll); |
| 717 | 743 | } |
| 718 | 744 | |
| 719 | −static void pll_clk_start_ss(struct tegra_clk_pll *pll) | |
| 720 | −{ | |
| 721 | − if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | |
| 722 | − u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | |
| 723 | − | |
| 724 | − val |= pll->params->ssc_ctrl_en_mask; | |
| 725 | − pll_writel(val, pll->params->ssc_ctrl_reg, pll); | |
| 726 | − } | |
| 727 | −} | |
| 728 | − | |
| 729 | −static void pll_clk_stop_ss(struct tegra_clk_pll *pll) | |
| 730 | −{ | |
| 731 | − if (pll->params->defaults_set && pll->params->ssc_ctrl_reg) { | |
| 732 | − u32 val = pll_readl(pll->params->ssc_ctrl_reg, pll); | |
| 733 | − | |
| 734 | − val &= ~pll->params->ssc_ctrl_en_mask; | |
| 735 | − pll_writel(val, pll->params->ssc_ctrl_reg, pll); | |
| 736 | − } | |
| 737 | −} | |
| 738 | − | |
| 739 | 745 | static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, |
| 740 | 746 | unsigned long rate) |
| 741 | 747 | { |
| @@ -2251,7 +2257,7 @@ tegra_clk_register_pllu_tegra114(const char *name, const char *parent_name, · 1509 unmodified lines | ||
| 2251 | 2257 | } |
| 2252 | 2258 | #endif |
| 2253 | 2259 | |
| 2254 | −#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) | |
| 2260 | +#if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) || defined(CONFIG_ARCH_TEGRA_210_SOC) | |
| 2255 | 2261 | static const struct clk_ops tegra_clk_pllss_ops = { |
| 2256 | 2262 | .is_enabled = clk_pll_is_enabled, |
| 2257 | 2263 | .enable = clk_pll_enable, |
| @@ -2349,7 +2355,6 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, · 91 unmodified lines | ||
| 2349 | 2355 | struct tegra_clk_pll_params *pll_params, |
| 2350 | 2356 | spinlock_t *lock, unsigned long parent_rate) |
| 2351 | 2357 | { |
| 2352 | − u32 val; | |
| 2353 | 2358 | struct tegra_clk_pll *pll; |
| 2354 | 2359 | struct clk *clk; |
| 2355 | 2360 | |
| @@ -2363,26 +2368,8 @@ struct clk *tegra_clk_register_pllre_tegra210(const char *name, · 7 unmodified lines | ||
| 2363 | 2368 | if (IS_ERR(pll)) |
| 2364 | 2369 | return ERR_CAST(pll); |
| 2365 | 2370 | |
| 2366 | − /* program minimum rate by default */ | |
| 2367 | − | |
| 2368 | − val = pll_readl_base(pll); | |
| 2369 | − if (val & PLL_BASE_ENABLE) | |
| 2370 | − WARN_ON(readl_relaxed(clk_base + pll_params->iddq_reg) & | |
| 2371 | − BIT(pll_params->iddq_bit_idx)); | |
| 2372 | − else { | |
| 2373 | − val = 0x4 << divm_shift(pll); | |
| 2374 | − val |= 0x41 << divn_shift(pll); | |
| 2375 | − pll_writel_base(val, pll); | |
| 2376 | − } | |
| 2377 | − | |
| 2378 | − /* disable lock override */ | |
| 2379 | − | |
| 2380 | − val = pll_readl_misc(pll); | |
| 2381 | − val &= ~BIT(29); | |
| 2382 | − pll_writel_misc(val, pll); | |
| 2383 | − | |
| 2384 | 2371 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, |
| 2385 | − &tegra_clk_pllre_ops); | |
| 2372 | + &tegra_clk_pll_ops); | |
| 2386 | 2373 | if (IS_ERR(clk)) |
| 2387 | 2374 | kfree(pll); |
| 2388 | 2375 | |
| @@ -2604,46 +2591,6 @@ struct clk *tegra_clk_register_pllc_tegra210(const char *name, · 215 unmodified lines | ||
| 2604 | 2591 | return clk; |
| 2605 | 2592 | } |
| 2606 | 2593 | |
| 2607 | −struct clk *tegra_clk_register_pllxc_tegra210(const char *name, | |
| 2608 | − const char *parent_name, void __iomem *clk_base, | |
| 2609 | − void __iomem *pmc, unsigned long flags, | |
| 2610 | − struct tegra_clk_pll_params *pll_params, | |
| 2611 | − spinlock_t *lock) | |
| 2612 | −{ | |
| 2613 | − struct tegra_clk_pll *pll; | |
| 2614 | − struct clk *clk, *parent; | |
| 2615 | − unsigned long parent_rate; | |
| 2616 | − | |
| 2617 | − parent = __clk_lookup(parent_name); | |
| 2618 | − if (!parent) { | |
| 2619 | − WARN(1, "parent clk %s of %s must be registered first\n", | |
| 2620 | − name, parent_name); | |
| 2621 | − return ERR_PTR(-EINVAL); | |
| 2622 | − } | |
| 2623 | − | |
| 2624 | − if (!pll_params->pdiv_tohw) | |
| 2625 | − return ERR_PTR(-EINVAL); | |
| 2626 | − | |
| 2627 | − parent_rate = clk_get_rate(parent); | |
| 2628 | − | |
| 2629 | − pll_params->vco_min = _clip_vco_min(pll_params->vco_min, parent_rate); | |
| 2630 | − | |
| 2631 | − if (pll_params->adjust_vco) | |
| 2632 | − pll_params->vco_min = pll_params->adjust_vco(pll_params, | |
| 2633 | − parent_rate); | |
| 2634 | − | |
| 2635 | − pll = _tegra_init_pll(clk_base, pmc, pll_params, lock); | |
| 2636 | − if (IS_ERR(pll)) | |
| 2637 | − return ERR_CAST(pll); | |
| 2638 | − | |
| 2639 | − clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | |
| 2640 | − &tegra_clk_pll_ops); | |
| 2641 | − if (IS_ERR(clk)) | |
| 2642 | − kfree(pll); | |
| 2643 | − | |
| 2644 | − return clk; | |
| 2645 | −} | |
| 2646 | − | |
| 2647 | 2594 | struct clk *tegra_clk_register_pllss_tegra210(const char *name, |
| 2648 | 2595 | const char *parent_name, void __iomem *clk_base, |
| 2649 | 2596 | unsigned long flags, |
| @@ -2652,10 +2599,8 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, · 2 unmodified lines | ||
| 2652 | 2599 | { |
| 2653 | 2600 | struct tegra_clk_pll *pll; |
| 2654 | 2601 | struct clk *clk, *parent; |
| 2655 | − struct tegra_clk_pll_freq_table cfg; | |
| 2656 | 2602 | unsigned long parent_rate; |
| 2657 | 2603 | u32 val; |
| 2658 | − int i; | |
| 2659 | 2604 | |
| 2660 | 2605 | if (!pll_params->div_nmp) |
| 2661 | 2606 | return ERR_PTR(-EINVAL); |
| @@ -2667,13 +2612,11 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, · 5 unmodified lines | ||
| 2667 | 2612 | return ERR_PTR(-EINVAL); |
| 2668 | 2613 | } |
| 2669 | 2614 | |
| 2670 | − pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); | |
| 2671 | − if (IS_ERR(pll)) | |
| 2672 | − return ERR_CAST(pll); | |
| 2673 | − | |
| 2674 | − val = pll_readl_base(pll); | |
| 2675 | − val &= ~PLLSS_REF_SRC_SEL_MASK; | |
| 2676 | − pll_writel_base(val, pll); | |
| 2615 | + val = readl_relaxed(clk_base + pll_params->base_reg); | |
| 2616 | + if (val & PLLSS_REF_SRC_SEL_MASK) { | |
| 2617 | + WARN(1, "not supported reference clock for %s\n", name); | |
| 2618 | + return ERR_PTR(-EINVAL); | |
| 2619 | + } | |
| 2677 | 2620 | |
| 2678 | 2621 | parent_rate = clk_get_rate(parent); |
| 2679 | 2622 | |
| @@ -2683,36 +2626,10 @@ struct clk *tegra_clk_register_pllss_tegra210(const char *name, · 3 unmodified lines | ||
| 2683 | 2626 | pll_params->vco_min = pll_params->adjust_vco(pll_params, |
| 2684 | 2627 | parent_rate); |
| 2685 | 2628 | |
| 2686 | − /* initialize PLL to minimum rate */ | |
| 2687 | − | |
| 2688 | − cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); | |
| 2689 | − cfg.n = cfg.m * pll_params->vco_min / parent_rate; | |
| 2690 | − | |
| 2691 | − for (i = 0; pll_params->pdiv_tohw[i].pdiv; i++) | |
| 2692 | − ; | |
| 2693 | − if (!i) { | |
| 2694 | − kfree(pll); | |
| 2695 | − return ERR_PTR(-EINVAL); | |
| 2696 | − } | |
| 2697 | − | |
| 2698 | − cfg.p = pll_params->pdiv_tohw[i-1].hw_val; | |
| 2699 | − | |
| 2700 | − _update_pll_mnp(pll, &cfg); | |
| 2701 | − | |
| 2702 | − pll_writel_misc(PLLSS_MISC_DEFAULT, pll); | |
| 2703 | − | |
| 2704 | − val = pll_readl_base(pll); | |
| 2705 | − if (val & PLL_BASE_ENABLE) { | |
| 2706 | − if (val & BIT(pll_params->iddq_bit_idx)) { | |
| 2707 | − WARN(1, "%s is on but IDDQ set\n", name); | |
| 2708 | − kfree(pll); | |
| 2709 | − return ERR_PTR(-EINVAL); | |
| 2710 | − } | |
| 2711 | − } else | |
| 2712 | − val |= BIT(pll_params->iddq_bit_idx); | |
| 2713 | − | |
| 2714 | − val &= ~PLLSS_LOCK_OVERRIDE; | |
| 2715 | − pll_writel_base(val, pll); | |
| 2629 | + pll_params->flags |= TEGRA_PLL_BYPASS; | |
| 2630 | + pll = _tegra_init_pll(clk_base, NULL, pll_params, lock); | |
| 2631 | + if (IS_ERR(pll)) | |
| 2632 | + return ERR_CAST(pll); | |
| 2716 | 2633 | |
| 2717 | 2634 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, |
| 2718 | 2635 | &tegra_clk_pll_ops); |
| @@ -216,7 +216,8 @@ · 215 unmodified lines | ||
| 216 | 216 | _clk_num, _clk_id) \ |
| 217 | 217 | TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\ |
| 218 | 218 | 30, MASK(2), 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,\ |
| 219 | − _clk_num, 0, _clk_id, _parents##_idx, 0, NULL) | |
| 219 | + _clk_num, TEGRA_PERIPH_ON_APB, _clk_id, \ | |
| 220 | + _parents##_idx, 0, NULL) | |
| 220 | 221 | |
| 221 | 222 | #define XUSB(_name, _parents, _offset, \ |
| 222 | 223 | _clk_num, _gate_flags, _clk_id) \ |
| @@ -232,8 +232,15 @@ static void __init tegra_super_clk_init(void __iomem *clk_base, · 231 unmodified lines | ||
| 232 | 232 | if (!dt_clk) |
| 233 | 233 | return; |
| 234 | 234 | |
| 235 | − clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, | |
| 236 | − pmc_base, CLK_IGNORE_UNUSED, params, NULL); | |
| 235 | +#if defined(CONFIG_ARCH_TEGRA_210_SOC) | |
| 236 | + if (gen_info->gen == gen5) | |
| 237 | + clk = tegra_clk_register_pllc_tegra210("pll_x", "pll_ref", | |
| 238 | + clk_base, pmc_base, CLK_IGNORE_UNUSED, params, NULL); | |
| 239 | + else | |
| 240 | +#endif | |
| 241 | + clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, | |
| 242 | + pmc_base, CLK_IGNORE_UNUSED, params, NULL); | |
| 243 | + | |
| 237 | 244 | *dt_clk = clk; |
| 238 | 245 | |
| 239 | 246 | /* PLLX_OUT0 */ |
| @@ -146,7 +146,7 @@ · 145 unmodified lines | ||
| 146 | 146 | #define PLLD_SDM_EN_MASK BIT(16) |
| 147 | 147 | |
| 148 | 148 | #define PLLD2_SDM_EN_MASK BIT(31) |
| 149 | −#define PLLD2_SSC_EN_MASK BIT(30) | |
| 149 | +#define PLLD2_SSC_EN_MASK 0 | |
| 150 | 150 | |
| 151 | 151 | #define PLLDP_SS_CFG 0x598 |
| 152 | 152 | #define PLLDP_SDM_EN_MASK BIT(31) |
| @@ -241,6 +241,9 @@ · 88 unmodified lines | ||
| 241 | 241 | #define PLL_SDM_COEFF BIT(13) |
| 242 | 242 | #define sdin_din_to_data(din) ((u16)((din) ? : 0xFFFFU)) |
| 243 | 243 | #define sdin_data_to_din(dat) (((dat) == 0xFFFFU) ? 0 : (s16)dat) |
| 244 | +/* This macro returns ndiv effective scaled to SDM range */ | |
| 245 | +#define sdin_get_n_eff(cfg) ((cfg)->n * PLL_SDM_COEFF + ((cfg)->sdm_data ? \ | |
| 246 | + (PLL_SDM_COEFF/2 + sdin_data_to_din((cfg)->sdm_data)) : 0)) | |
| 244 | 247 | |
| 245 | 248 | /* Tegra CPU clock and reset control regs */ |
| 246 | 249 | #define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470 |
| @@ -715,8 +718,6 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, · 468 unmodified lines | ||
| 715 | 718 | plldss->params->defaults_set = true; |
| 716 | 719 | |
| 717 | 720 | if (val & PLL_ENABLE) { |
| 718 | − pr_warn("%s already enabled. Postponing set full defaults\n", | |
| 719 | − pll_name); | |
| 720 | 721 | |
| 721 | 722 | /* |
| 722 | 723 | * PLL is ON: check if defaults already set, then set those |
| @@ -755,6 +756,10 @@ static void plldss_defaults(const char *pll_name, struct tegra_clk_pll *plldss, · 32 unmodified lines | ||
| 755 | 756 | (~PLLDSS_MISC1_CFG_EN_SDM)); |
| 756 | 757 | } |
| 757 | 758 | |
| 759 | + if (!plldss->params->defaults_set) | |
| 760 | + pr_warn("%s already enabled. Postponing set full defaults\n", | |
| 761 | + pll_name); | |
| 762 | + | |
| 758 | 763 | /* Enable lock detect */ |
| 759 | 764 | if (val & PLLDSS_BASE_LOCK_OVERRIDE) { |
| 760 | 765 | val &= ~PLLDSS_BASE_LOCK_OVERRIDE; |
| @@ -1288,8 +1293,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, · 527 unmodified lines | ||
| 1288 | 1293 | s -= PLL_SDM_COEFF / 2; |
| 1289 | 1294 | cfg->sdm_data = sdin_din_to_data(s); |
| 1290 | 1295 | } |
| 1291 | − cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + | |
| 1292 | − sdin_data_to_din(cfg->sdm_data); | |
| 1296 | + cfg->output_rate *= sdin_get_n_eff(cfg); | |
| 1293 | 1297 | cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF; |
| 1294 | 1298 | } else { |
| 1295 | 1299 | cfg->output_rate *= cfg->n; |
| @@ -1314,8 +1318,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw, · 18 unmodified lines | ||
| 1314 | 1318 | */ |
| 1315 | 1319 | static void tegra210_clk_pll_set_gain(struct tegra_clk_pll_freq_table *cfg) |
| 1316 | 1320 | { |
| 1317 | − cfg->n = cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 + | |
| 1318 | − sdin_data_to_din(cfg->sdm_data); | |
| 1321 | + cfg->n = sdin_get_n_eff(cfg); | |
| 1319 | 1322 | cfg->m *= PLL_SDM_COEFF; |
| 1320 | 1323 | } |
| 1321 | 1324 | |
| @@ -2204,7 +2207,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = { · 882 unmodified lines | ||
| 2204 | 2207 | [tegra_clk_gpu] = { .dt_id = TEGRA210_CLK_GPU, .present = true }, |
| 2205 | 2208 | [tegra_clk_pll_g_ref] = { .dt_id = TEGRA210_CLK_PLL_G_REF, .present = true, }, |
| 2206 | 2209 | [tegra_clk_uartb_8] = { .dt_id = TEGRA210_CLK_UARTB, .present = true }, |
| 2207 | − [tegra_clk_vfir] = { .dt_id = TEGRA210_CLK_VFIR, .present = true }, | |
| 2208 | 2210 | [tegra_clk_spdif_in_8] = { .dt_id = TEGRA210_CLK_SPDIF_IN, .present = true }, |
| 2209 | 2211 | [tegra_clk_spdif_out] = { .dt_id = TEGRA210_CLK_SPDIF_OUT, .present = true }, |
| 2210 | 2212 | [tegra_clk_vi_10] = { .dt_id = TEGRA210_CLK_VI, .present = true }, |
| @@ -2470,15 +2472,14 @@ static void tegra210_utmi_param_configure(void) · 259 unmodified lines | ||
| 2470 | 2472 | reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); |
| 2471 | 2473 | |
| 2472 | 2474 | reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); |
| 2473 | − | |
| 2474 | 2475 | reg |= |
| 2475 | 2476 | UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count); |
| 2476 | 2477 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); |
| 2477 | 2478 | |
| 2478 | 2479 | /* Program UTMIP PLL delay and oscillator frequency counts */ |
| 2479 | 2480 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); |
| 2480 | − reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); | |
| 2481 | 2481 | |
| 2482 | + reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); | |
| 2482 | 2483 | reg |= |
| 2483 | 2484 | UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count); |
| 2484 | 2485 | |
| @@ -2494,7 +2495,8 @@ static void tegra210_utmi_param_configure(void) · 9 unmodified lines | ||
| 2494 | 2495 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; |
| 2495 | 2496 | reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; |
| 2496 | 2497 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); |
| 2497 | − udelay(1); | |
| 2498 | + | |
| 2499 | + udelay(20); | |
| 2498 | 2500 | |
| 2499 | 2501 | /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */ |
| 2500 | 2502 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); |
| @@ -2552,6 +2554,7 @@ static int tegra210_enable_pllu(void) · 51 unmodified lines | ||
| 2552 | 2554 | reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]); |
| 2553 | 2555 | reg &= ~BIT(pllu.params->iddq_bit_idx); |
| 2554 | 2556 | writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]); |
| 2557 | + udelay(5); | |
| 2555 | 2558 | |
| 2556 | 2559 | reg = readl_relaxed(clk_base + PLLU_BASE); |
| 2557 | 2560 | reg &= ~GENMASK(20, 0); |
| @@ -2559,6 +2562,7 @@ static int tegra210_enable_pllu(void) · 1 unmodified line | ||
| 2559 | 2562 | reg |= fentry->n << 8; |
| 2560 | 2563 | reg |= fentry->p << 16; |
| 2561 | 2564 | writel(reg, clk_base + PLLU_BASE); |
| 2565 | + udelay(1); | |
| 2562 | 2566 | reg |= PLL_ENABLE; |
| 2563 | 2567 | writel(reg, clk_base + PLLU_BASE); |
| 2564 | 2568 | |
| @@ -2699,7 +2703,7 @@ static void __init tegra210_pll_init(void __iomem *clk_base, · 134 unmodified lines | ||
| 2699 | 2703 | struct clk *clk; |
| 2700 | 2704 | |
| 2701 | 2705 | /* PLLC */ |
| 2702 | − clk = tegra_clk_register_pllxc_tegra210("pll_c", "pll_ref", clk_base, | |
| 2706 | + clk = tegra_clk_register_pllc_tegra210("pll_c", "pll_ref", clk_base, | |
| 2703 | 2707 | pmc, 0, &pll_c_params, NULL); |
| 2704 | 2708 | if (!WARN_ON(IS_ERR(clk))) |
| 2705 | 2709 | clk_register_clkdev(clk, "pll_c", NULL); |
| @@ -2798,14 +2802,14 @@ static void __init tegra210_pll_init(void __iomem *clk_base, · 92 unmodified lines | ||
| 2798 | 2802 | /* PLLU_60M */ |
| 2799 | 2803 | clk = clk_register_gate(NULL, "pll_u_60M", "pll_u_out2", |
| 2800 | 2804 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, |
| 2801 | − 23, 0, NULL); | |
| 2805 | + 23, 0, &pll_u_lock); | |
| 2802 | 2806 | clk_register_clkdev(clk, "pll_u_60M", NULL); |
| 2803 | 2807 | clks[TEGRA210_CLK_PLL_U_60M] = clk; |
| 2804 | 2808 | |
| 2805 | 2809 | /* PLLU_48M */ |
| 2806 | 2810 | clk = clk_register_gate(NULL, "pll_u_48M", "pll_u_out1", |
| 2807 | 2811 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, |
| 2808 | − 25, 0, NULL); | |
| 2812 | + 25, 0, &pll_u_lock); | |
| 2809 | 2813 | clk_register_clkdev(clk, "pll_u_48M", NULL); |
| 2810 | 2814 | clks[TEGRA210_CLK_PLL_U_48M] = clk; |
| 2811 | 2815 | |
| @@ -362,12 +362,6 @@ struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, · 361 unmodified lines | ||
| 362 | 362 | struct tegra_clk_pll_params *pll_params, |
| 363 | 363 | spinlock_t *lock); |
| 364 | 364 | |
| 365 | −struct clk *tegra_clk_register_pllxc_tegra210(const char *name, | |
| 366 | − const char *parent_name, void __iomem *clk_base, | |
| 367 | − void __iomem *pmc, unsigned long flags, | |
| 368 | − struct tegra_clk_pll_params *pll_params, | |
| 369 | − spinlock_t *lock); | |
| 370 | − | |
| 371 | 365 | struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, |
| 372 | 366 | void __iomem *clk_base, void __iomem *pmc, |
| 373 | 367 | unsigned long flags, |
| @@ -222,7 +222,7 @@ static int ti_adpll_setup_clock(struct ti_adpll_data *d, struct clk *clock, · 221 unmodified lines | ||
| 222 | 222 | |
| 223 | 223 | /* Separate con_id in format "pll040dcoclkldo" to fit MAX_CON_ID */ |
| 224 | 224 | postfix = strrchr(name, '.'); |
| 225 | − if (strlen(postfix) > 1) { | |
| 225 | + if (postfix && strlen(postfix) > 1) { | |
| 226 | 226 | if (strlen(postfix) > ADPLL_MAX_CON_ID) |
| 227 | 227 | dev_warn(d->dev, "clock %s con_id lookup may fail\n", |
| 228 | 228 | name); |
| @@ -486,7 +486,7 @@ static u8 ti_adpll_get_parent(struct clk_hw *hw) · 257 unmodified lines | ||
| 486 | 486 | return 0; |
| 487 | 487 | } |
| 488 | 488 | |
| 489 | −static struct clk_ops ti_adpll_ops = { | |
| 489 | +static const struct clk_ops ti_adpll_ops = { | |
| 490 | 490 | .prepare = ti_adpll_prepare, |
| 491 | 491 | .unprepare = ti_adpll_unprepare, |
| 492 | 492 | .is_prepared = ti_adpll_is_prepared, |
| @@ -304,7 +304,7 @@ static void omap2_apll_disable(struct clk_hw *hw) · 303 unmodified lines | ||
| 304 | 304 | ti_clk_ll_ops->clk_writel(v, &ad->control_reg); |
| 305 | 305 | } |
| 306 | 306 | |
| 307 | −static struct clk_ops omap2_apll_ops = { | |
| 307 | +static const struct clk_ops omap2_apll_ops = { | |
| 308 | 308 | .enable = &omap2_apll_enable, |
| 309 | 309 | .disable = &omap2_apll_disable, |
| 310 | 310 | .is_enabled = &omap2_apll_is_enabled, |
| @@ -138,8 +138,8 @@ static void __init of_ti_clockdomain_setup(struct device_node *node) · 137 unmodified lines | ||
| 138 | 138 | for (i = 0; i < num_clks; i++) { |
| 139 | 139 | clk = of_clk_get(node, i); |
| 140 | 140 | if (IS_ERR(clk)) { |
| 141 | − pr_err("%s: Failed get %s' clock nr %d (%ld)\n", | |
| 142 | − __func__, node->full_name, i, PTR_ERR(clk)); | |
| 141 | + pr_err("%s: Failed get %pOF' clock nr %d (%ld)\n", | |
| 142 | + __func__, node, i, PTR_ERR(clk)); | |
| 143 | 143 | continue; |
| 144 | 144 | } |
| 145 | 145 | clk_hw = __clk_get_hw(clk); |
| @@ -268,7 +268,7 @@ static int ti_fapll_set_rate(struct clk_hw *hw, unsigned long rate, · 267 unmodified lines | ||
| 268 | 268 | return 0; |
| 269 | 269 | } |
| 270 | 270 | |
| 271 | −static struct clk_ops ti_fapll_ops = { | |
| 271 | +static const struct clk_ops ti_fapll_ops = { | |
| 272 | 272 | .enable = ti_fapll_enable, |
| 273 | 273 | .disable = ti_fapll_disable, |
| 274 | 274 | .is_enabled = ti_fapll_is_enabled, |
| @@ -478,7 +478,7 @@ static int ti_fapll_synth_set_rate(struct clk_hw *hw, unsigned long rate, · 203 unmodified lines | ||
| 478 | 478 | return 0; |
| 479 | 479 | } |
| 480 | 480 | |
| 481 | −static struct clk_ops ti_fapll_synt_ops = { | |
| 481 | +static const struct clk_ops ti_fapll_synt_ops = { | |
| 482 | 482 | .enable = ti_fapll_synth_enable, |
| 483 | 483 | .disable = ti_fapll_synth_disable, |
| 484 | 484 | .is_enabled = ti_fapll_synth_is_enabled, |
| @@ -110,10 +110,6 @@ static int uniphier_clk_remove(struct platform_device *pdev) · 109 unmodified lines | ||
| 110 | 110 | |
| 111 | 111 | static const struct of_device_id uniphier_clk_match[] = { |
| 112 | 112 | /* System clock */ |
| 113 | − { | |
| 114 | − .compatible = "socionext,uniphier-sld3-clock", | |
| 115 | − .data = uniphier_sld3_sys_clk_data, | |
| 116 | − }, | |
| 117 | 113 | { |
| 118 | 114 | .compatible = "socionext,uniphier-ld4-clock", |
| 119 | 115 | .data = uniphier_ld4_sys_clk_data, |
| @@ -142,22 +138,22 @@ static const struct of_device_id uniphier_clk_match[] = { · 22 unmodified lines | ||
| 142 | 138 | .compatible = "socionext,uniphier-ld20-clock", |
| 143 | 139 | .data = uniphier_ld20_sys_clk_data, |
| 144 | 140 | }, |
| 145 | − /* Media I/O clock, SD clock */ | |
| 146 | 141 | { |
| 147 | − .compatible = "socionext,uniphier-sld3-mio-clock", | |
| 148 | − .data = uniphier_sld3_mio_clk_data, | |
| 142 | + .compatible = "socionext,uniphier-pxs3-clock", | |
| 143 | + .data = uniphier_pxs3_sys_clk_data, | |
| 149 | 144 | }, |
| 145 | + /* Media I/O clock, SD clock */ | |
| 150 | 146 | { |
| 151 | 147 | .compatible = "socionext,uniphier-ld4-mio-clock", |
| 152 | − .data = uniphier_sld3_mio_clk_data, | |
| 148 | + .data = uniphier_ld4_mio_clk_data, | |
| 153 | 149 | }, |
| 154 | 150 | { |
| 155 | 151 | .compatible = "socionext,uniphier-pro4-mio-clock", |
| 156 | − .data = uniphier_sld3_mio_clk_data, | |
| 152 | + .data = uniphier_ld4_mio_clk_data, | |
| 157 | 153 | }, |
| 158 | 154 | { |
| 159 | 155 | .compatible = "socionext,uniphier-sld8-mio-clock", |
| 160 | − .data = uniphier_sld3_mio_clk_data, | |
| 156 | + .data = uniphier_ld4_mio_clk_data, | |
| 161 | 157 | }, |
| 162 | 158 | { |
| 163 | 159 | .compatible = "socionext,uniphier-pro5-sd-clock", |
| @@ -169,12 +165,16 @@ static const struct of_device_id uniphier_clk_match[] = { · 5 unmodified lines | ||
| 169 | 165 | }, |
| 170 | 166 | { |
| 171 | 167 | .compatible = "socionext,uniphier-ld11-mio-clock", |
| 172 | − .data = uniphier_sld3_mio_clk_data, | |
| 168 | + .data = uniphier_ld4_mio_clk_data, | |
| 173 | 169 | }, |
| 174 | 170 | { |
| 175 | 171 | .compatible = "socionext,uniphier-ld20-sd-clock", |
| 176 | 172 | .data = uniphier_pro5_sd_clk_data, |
| 177 | 173 | }, |
| 174 | + { | |
| 175 | + .compatible = "socionext,uniphier-pxs3-sd-clock", | |
| 176 | + .data = uniphier_pro5_sd_clk_data, | |
| 177 | + }, | |
| 178 | 178 | /* Peripheral clock */ |
| 179 | 179 | { |
| 180 | 180 | .compatible = "socionext,uniphier-ld4-peri-clock", |
| @@ -204,6 +204,10 @@ static const struct of_device_id uniphier_clk_match[] = { · 23 unmodified lines | ||
| 204 | 204 | .compatible = "socionext,uniphier-ld20-peri-clock", |
| 205 | 205 | .data = uniphier_pro4_peri_clk_data, |
| 206 | 206 | }, |
| 207 | + { | |
| 208 | + .compatible = "socionext,uniphier-pxs3-peri-clock", | |
| 209 | + .data = uniphier_pro4_peri_clk_data, | |
| 210 | + }, | |
| 207 | 211 | { /* sentinel */ } |
| 208 | 212 | }; |
| 209 | 213 | |
| @@ -76,7 +76,7 @@ · 75 unmodified lines | ||
| 76 | 76 | #define UNIPHIER_MIO_CLK_DMAC(idx) \ |
| 77 | 77 | UNIPHIER_CLK_GATE("miodmac", (idx), "stdmac", 0x20, 25) |
| 78 | 78 | |
| 79 | −const struct uniphier_clk_data uniphier_sld3_mio_clk_data[] = { | |
| 79 | +const struct uniphier_clk_data uniphier_ld4_mio_clk_data[] = { | |
| 80 | 80 | UNIPHIER_MIO_CLK_SD_FIXED, |
| 81 | 81 | UNIPHIER_MIO_CLK_SD(0, 0), |
| 82 | 82 | UNIPHIER_MIO_CLK_SD(1, 1), |
| @@ -85,11 +85,9 @@ const struct uniphier_clk_data uniphier_sld3_mio_clk_data[] = { · 2 unmodified lines | ||
| 85 | 85 | UNIPHIER_MIO_CLK_USB2(8, 0), |
| 86 | 86 | UNIPHIER_MIO_CLK_USB2(9, 1), |
| 87 | 87 | UNIPHIER_MIO_CLK_USB2(10, 2), |
| 88 | − UNIPHIER_MIO_CLK_USB2(11, 3), | |
| 89 | 88 | UNIPHIER_MIO_CLK_USB2_PHY(12, 0), |
| 90 | 89 | UNIPHIER_MIO_CLK_USB2_PHY(13, 1), |
| 91 | 90 | UNIPHIER_MIO_CLK_USB2_PHY(14, 2), |
| 92 | − UNIPHIER_MIO_CLK_USB2_PHY(15, 3), | |
| 93 | 91 | { /* sentinel */ } |
| 94 | 92 | }; |
| 95 | 93 | |
| @@ -17,7 +17,7 @@ · 16 unmodified lines | ||
| 17 | 17 | |
| 18 | 18 | #include "clk-uniphier.h" |
| 19 | 19 | |
| 20 | −#define UNIPHIER_SLD3_SYS_CLK_SD \ | |
| 20 | +#define UNIPHIER_LD4_SYS_CLK_SD \ | |
| 21 | 21 | UNIPHIER_CLK_FACTOR("sd-200m", -1, "spll", 1, 8), \ |
| 22 | 22 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "vpll27a", 1, 2) |
| 23 | 23 | |
| @@ -30,7 +30,7 @@ · 6 unmodified lines | ||
| 30 | 30 | UNIPHIER_CLK_FACTOR("sd-133m", -1, "spll", 1, 15) |
| 31 | 31 | |
| 32 | 32 | /* Denali driver requires clk_x rate (clk: 50MHz, clk_x & ecc_clk: 200MHz) */ |
| 33 | −#define UNIPHIER_SLD3_SYS_CLK_NAND(idx) \ | |
| 33 | +#define UNIPHIER_LD4_SYS_CLK_NAND(idx) \ | |
| 34 | 34 | UNIPHIER_CLK_FACTOR("nand-200m", -1, "spll", 1, 8), \ |
| 35 | 35 | UNIPHIER_CLK_GATE("nand", (idx), "nand-200m", 0x2104, 2) |
| 36 | 36 | |
| @@ -45,7 +45,7 @@ · 8 unmodified lines | ||
| 45 | 45 | #define UNIPHIER_LD11_SYS_CLK_EMMC(idx) \ |
| 46 | 46 | UNIPHIER_CLK_GATE("emmc", (idx), NULL, 0x210c, 2) |
| 47 | 47 | |
| 48 | −#define UNIPHIER_SLD3_SYS_CLK_STDMAC(idx) \ | |
| 48 | +#define UNIPHIER_LD4_SYS_CLK_STDMAC(idx) \ | |
| 49 | 49 | UNIPHIER_CLK_GATE("stdmac", (idx), NULL, 0x2104, 10) |
| 50 | 50 | |
| 51 | 51 | #define UNIPHIER_LD11_SYS_CLK_STDMAC(idx) \ |
| @@ -57,19 +57,23 @@ · 5 unmodified lines | ||
| 57 | 57 | #define UNIPHIER_PRO4_SYS_CLK_USB3(idx, ch) \ |
| 58 | 58 | UNIPHIER_CLK_GATE("usb3" #ch, (idx), NULL, 0x2104, 16 + (ch)) |
| 59 | 59 | |
| 60 | −const struct uniphier_clk_data uniphier_sld3_sys_clk_data[] = { | |
| 61 | − UNIPHIER_CLK_FACTOR("spll", -1, "ref", 65, 1), /* 1597.44 MHz */ | |
| 62 | − UNIPHIER_CLK_FACTOR("upll", -1, "ref", 6000, 512), /* 288 MHz */ | |
| 63 | − UNIPHIER_CLK_FACTOR("a2pll", -1, "ref", 24, 1), /* 589.824 MHz */ | |
| 64 | − UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 5625, 512), /* 270 MHz */ | |
| 65 | − UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 16), | |
| 66 | − UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), | |
| 67 | − UNIPHIER_SLD3_SYS_CLK_NAND(2), | |
| 68 | − UNIPHIER_SLD3_SYS_CLK_SD, | |
| 69 | − UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), | |
| 70 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), | |
| 71 | − { /* sentinel */ } | |
| 72 | −}; | |
| 60 | +#define UNIPHIER_LD11_SYS_CLK_AIO(idx) \ | |
| 61 | + UNIPHIER_CLK_FACTOR("aio-io200m", -1, "spll", 1, 10), \ | |
| 62 | + UNIPHIER_CLK_GATE("aio", (idx), "aio-io200m", 0x2108, 0) | |
| 63 | + | |
| 64 | +#define UNIPHIER_LD11_SYS_CLK_EVEA(idx) \ | |
| 65 | + UNIPHIER_CLK_FACTOR("evea-io100m", -1, "spll", 1, 20), \ | |
| 66 | + UNIPHIER_CLK_GATE("evea", (idx), "evea-io100m", 0x2108, 1) | |
| 67 | + | |
| 68 | +#define UNIPHIER_LD11_SYS_CLK_EXIV(idx) \ | |
| 69 | + UNIPHIER_CLK_FACTOR("exiv-io200m", -1, "spll", 1, 10), \ | |
| 70 | + UNIPHIER_CLK_GATE("exiv", (idx), "exiv-io200m", 0x2110, 2) | |
| 71 | + | |
| 72 | +#define UNIPHIER_PRO4_SYS_CLK_ETHER(idx) \ | |
| 73 | + UNIPHIER_CLK_GATE("ether", (idx), NULL, 0x2104, 12) | |
| 74 | + | |
| 75 | +#define UNIPHIER_LD11_SYS_CLK_ETHER(idx) \ | |
| 76 | + UNIPHIER_CLK_GATE("ether", (idx), NULL, 0x210c, 6) | |
| 73 | 77 | |
| 74 | 78 | const struct uniphier_clk_data uniphier_ld4_sys_clk_data[] = { |
| 75 | 79 | UNIPHIER_CLK_FACTOR("spll", -1, "ref", 65, 1), /* 1597.44 MHz */ |
| @@ -78,10 +82,10 @@ const struct uniphier_clk_data uniphier_ld4_sys_clk_data[] = { · 2 unmodified lines | ||
| 78 | 82 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 5625, 512), /* 270 MHz */ |
| 79 | 83 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 16), |
| 80 | 84 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), |
| 81 | − UNIPHIER_SLD3_SYS_CLK_NAND(2), | |
| 82 | − UNIPHIER_SLD3_SYS_CLK_SD, | |
| 85 | + UNIPHIER_LD4_SYS_CLK_NAND(2), | |
| 86 | + UNIPHIER_LD4_SYS_CLK_SD, | |
| 83 | 87 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 84 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | |
| 88 | + UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | |
| 85 | 89 | { /* sentinel */ } |
| 86 | 90 | }; |
| 87 | 91 | |
| @@ -92,10 +96,11 @@ const struct uniphier_clk_data uniphier_pro4_sys_clk_data[] = { · 4 unmodified lines | ||
| 92 | 96 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ |
| 93 | 97 | UNIPHIER_CLK_FACTOR("uart", 0, "a2pll", 1, 8), |
| 94 | 98 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 32), |
| 95 | − UNIPHIER_SLD3_SYS_CLK_NAND(2), | |
| 96 | − UNIPHIER_SLD3_SYS_CLK_SD, | |
| 99 | + UNIPHIER_LD4_SYS_CLK_NAND(2), | |
| 100 | + UNIPHIER_LD4_SYS_CLK_SD, | |
| 97 | 101 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 98 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC, MIO, RLE */ | |
| 102 | + UNIPHIER_PRO4_SYS_CLK_ETHER(6), | |
| 103 | + UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC, MIO, RLE */ | |
| 99 | 104 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* Ether, SATA, USB3 */ |
| 100 | 105 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 101 | 106 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -108,10 +113,10 @@ const struct uniphier_clk_data uniphier_sld8_sys_clk_data[] = { · 6 unmodified lines | ||
| 108 | 113 | UNIPHIER_CLK_FACTOR("vpll27a", -1, "ref", 270, 25), /* 270 MHz */ |
| 109 | 114 | UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 20), |
| 110 | 115 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 16), |
| 111 | − UNIPHIER_SLD3_SYS_CLK_NAND(2), | |
| 112 | − UNIPHIER_SLD3_SYS_CLK_SD, | |
| 116 | + UNIPHIER_LD4_SYS_CLK_NAND(2), | |
| 117 | + UNIPHIER_LD4_SYS_CLK_SD, | |
| 113 | 118 | UNIPHIER_CLK_FACTOR("usb2", -1, "upll", 1, 12), |
| 114 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | |
| 119 | + UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* Ether, HSC, MIO */ | |
| 115 | 120 | { /* sentinel */ } |
| 116 | 121 | }; |
| 117 | 122 | |
| @@ -123,7 +128,7 @@ const struct uniphier_clk_data uniphier_pro5_sys_clk_data[] = { · 5 unmodified lines | ||
| 123 | 128 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), |
| 124 | 129 | UNIPHIER_PRO5_SYS_CLK_NAND(2), |
| 125 | 130 | UNIPHIER_PRO5_SYS_CLK_SD, |
| 126 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC */ | |
| 131 | + UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC */ | |
| 127 | 132 | UNIPHIER_PRO4_SYS_CLK_GIO(12), /* PCIe, USB3 */ |
| 128 | 133 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 129 | 134 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -136,7 +141,8 @@ const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[] = { · 6 unmodified lines | ||
| 136 | 141 | UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 48), |
| 137 | 142 | UNIPHIER_PRO5_SYS_CLK_NAND(2), |
| 138 | 143 | UNIPHIER_PRO5_SYS_CLK_SD, |
| 139 | − UNIPHIER_SLD3_SYS_CLK_STDMAC(8), /* HSC, RLE */ | |
| 144 | + UNIPHIER_PRO4_SYS_CLK_ETHER(6), | |
| 145 | + UNIPHIER_LD4_SYS_CLK_STDMAC(8), /* HSC, RLE */ | |
| 140 | 146 | /* GIO is always clock-enabled: no function for 0x2104 bit6 */ |
| 141 | 147 | UNIPHIER_PRO4_SYS_CLK_USB3(14, 0), |
| 142 | 148 | UNIPHIER_PRO4_SYS_CLK_USB3(15, 1), |
| @@ -156,8 +162,12 @@ const struct uniphier_clk_data uniphier_ld11_sys_clk_data[] = { · 13 unmodified lines | ||
| 156 | 162 | UNIPHIER_LD11_SYS_CLK_NAND(2), |
| 157 | 163 | UNIPHIER_LD11_SYS_CLK_EMMC(4), |
| 158 | 164 | /* Index 5 reserved for eMMC PHY */ |
| 165 | + UNIPHIER_LD11_SYS_CLK_ETHER(6), | |
| 159 | 166 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC, MIO */ |
| 160 | 167 | UNIPHIER_CLK_FACTOR("usb2", -1, "ref", 24, 25), |
| 168 | + UNIPHIER_LD11_SYS_CLK_AIO(40), | |
| 169 | + UNIPHIER_LD11_SYS_CLK_EVEA(41), | |
| 170 | + UNIPHIER_LD11_SYS_CLK_EXIV(42), | |
| 161 | 171 | /* CPU gears */ |
| 162 | 172 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), |
| 163 | 173 | UNIPHIER_CLK_DIV4("mpll", 2, 3, 4, 8), |
| @@ -185,6 +195,7 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { · 21 unmodified lines | ||
| 185 | 195 | UNIPHIER_LD11_SYS_CLK_EMMC(4), |
| 186 | 196 | /* Index 5 reserved for eMMC PHY */ |
| 187 | 197 | UNIPHIER_LD20_SYS_CLK_SD, |
| 198 | + UNIPHIER_LD11_SYS_CLK_ETHER(6), | |
| 188 | 199 | UNIPHIER_LD11_SYS_CLK_STDMAC(8), /* HSC */ |
| 189 | 200 | /* GIO is always clock-enabled: no function for 0x210c bit5 */ |
| 190 | 201 | /* |
| @@ -194,6 +205,9 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { · 3 unmodified lines | ||
| 194 | 205 | UNIPHIER_CLK_GATE("usb30", 14, NULL, 0x210c, 14), |
| 195 | 206 | UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 12), |
| 196 | 207 | UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 13), |
| 208 | + UNIPHIER_LD11_SYS_CLK_AIO(40), | |
| 209 | + UNIPHIER_LD11_SYS_CLK_EVEA(41), | |
| 210 | + UNIPHIER_LD11_SYS_CLK_EXIV(42), | |
| 197 | 211 | /* CPU gears */ |
| 198 | 212 | UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), |
| 199 | 213 | UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8), |
| @@ -209,3 +223,33 @@ const struct uniphier_clk_data uniphier_ld20_sys_clk_data[] = { · 9 unmodified lines | ||
| 209 | 223 | "spll/4", "spll/8", "s2pll/4", "s2pll/8"), |
| 210 | 224 | { /* sentinel */ } |
| 211 | 225 | }; |
| 226 | + | |
| 227 | +const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[] = { | |
| 228 | + UNIPHIER_CLK_FACTOR("cpll", -1, "ref", 104, 1), /* ARM: 2600 MHz */ | |
| 229 | + UNIPHIER_CLK_FACTOR("spll", -1, "ref", 80, 1), /* 2000 MHz */ | |
| 230 | + UNIPHIER_CLK_FACTOR("s2pll", -1, "ref", 88, 1), /* IPP: 2400 MHz */ | |
| 231 | + UNIPHIER_CLK_FACTOR("uart", 0, "spll", 1, 34), | |
| 232 | + UNIPHIER_CLK_FACTOR("i2c", 1, "spll", 1, 40), | |
| 233 | + UNIPHIER_LD20_SYS_CLK_SD, | |
| 234 | + UNIPHIER_LD11_SYS_CLK_NAND(2), | |
| 235 | + UNIPHIER_LD11_SYS_CLK_EMMC(4), | |
| 236 | + UNIPHIER_CLK_GATE("usb30", 12, NULL, 0x2104, 4), /* =GIO0 */ | |
| 237 | + UNIPHIER_CLK_GATE("usb31-0", 13, NULL, 0x2104, 5), /* =GIO1 */ | |
| 238 | + UNIPHIER_CLK_GATE("usb31-1", 14, NULL, 0x2104, 6), /* =GIO1-1 */ | |
| 239 | + UNIPHIER_CLK_GATE("usb30-phy0", 16, NULL, 0x210c, 16), | |
| 240 | + UNIPHIER_CLK_GATE("usb30-phy1", 17, NULL, 0x210c, 18), | |
| 241 | + UNIPHIER_CLK_GATE("usb30-phy2", 18, NULL, 0x210c, 20), | |
| 242 | + UNIPHIER_CLK_GATE("usb31-phy0", 20, NULL, 0x210c, 17), | |
| 243 | + UNIPHIER_CLK_GATE("usb31-phy1", 21, NULL, 0x210c, 19), | |
| 244 | + /* CPU gears */ | |
| 245 | + UNIPHIER_CLK_DIV4("cpll", 2, 3, 4, 8), | |
| 246 | + UNIPHIER_CLK_DIV4("spll", 2, 3, 4, 8), | |
| 247 | + UNIPHIER_CLK_DIV4("s2pll", 2, 3, 4, 8), | |
| 248 | + UNIPHIER_CLK_CPUGEAR("cpu-ca53", 33, 0x8080, 0xf, 8, | |
| 249 | + "cpll/2", "spll/2", "cpll/3", "spll/3", | |
| 250 | + "spll/4", "spll/8", "cpll/4", "cpll/8"), | |
| 251 | + UNIPHIER_CLK_CPUGEAR("cpu-ipp", 34, 0x8100, 0xf, 8, | |
| 252 | + "s2pll/2", "spll/2", "s2pll/3", "spll/3", | |
| 253 | + "spll/4", "spll/8", "s2pll/4", "s2pll/8"), | |
| 254 | + { /* sentinel */ } | |
| 255 | +}; | |
| @@ -147,7 +147,6 @@ struct clk_hw *uniphier_clk_register_mux(struct device *dev, · 146 unmodified lines | ||
| 147 | 147 | const char *name, |
| 148 | 148 | const struct uniphier_clk_mux_data *data); |
| 149 | 149 | |
| 150 | −extern const struct uniphier_clk_data uniphier_sld3_sys_clk_data[]; | |
| 151 | 150 | extern const struct uniphier_clk_data uniphier_ld4_sys_clk_data[]; |
| 152 | 151 | extern const struct uniphier_clk_data uniphier_pro4_sys_clk_data[]; |
| 153 | 152 | extern const struct uniphier_clk_data uniphier_sld8_sys_clk_data[]; |
| @@ -155,7 +154,8 @@ extern const struct uniphier_clk_data uniphier_pro5_sys_clk_data[]; · 1 unmodified line | ||
| 155 | 154 | extern const struct uniphier_clk_data uniphier_pxs2_sys_clk_data[]; |
| 156 | 155 | extern const struct uniphier_clk_data uniphier_ld11_sys_clk_data[]; |
| 157 | 156 | extern const struct uniphier_clk_data uniphier_ld20_sys_clk_data[]; |
| 158 | −extern const struct uniphier_clk_data uniphier_sld3_mio_clk_data[]; | |
| 157 | +extern const struct uniphier_clk_data uniphier_pxs3_sys_clk_data[]; | |
| 158 | +extern const struct uniphier_clk_data uniphier_ld4_mio_clk_data[]; | |
| 159 | 159 | extern const struct uniphier_clk_data uniphier_pro5_sd_clk_data[]; |
| 160 | 160 | extern const struct uniphier_clk_data uniphier_ld4_peri_clk_data[]; |
| 161 | 161 | extern const struct uniphier_clk_data uniphier_pro4_peri_clk_data[]; |
| @@ -79,13 +79,13 @@ static int clk_prcc_is_enabled(struct clk_hw *hw) · 78 unmodified lines | ||
| 79 | 79 | return clk->is_enabled; |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | −static struct clk_ops clk_prcc_pclk_ops = { | |
| 82 | +static const struct clk_ops clk_prcc_pclk_ops = { | |
| 83 | 83 | .enable = clk_prcc_pclk_enable, |
| 84 | 84 | .disable = clk_prcc_pclk_disable, |
| 85 | 85 | .is_enabled = clk_prcc_is_enabled, |
| 86 | 86 | }; |
| 87 | 87 | |
| 88 | −static struct clk_ops clk_prcc_kclk_ops = { | |
| 88 | +static const struct clk_ops clk_prcc_kclk_ops = { | |
| 89 | 89 | .enable = clk_prcc_kclk_enable, |
| 90 | 90 | .disable = clk_prcc_kclk_disable, |
| 91 | 91 | .is_enabled = clk_prcc_is_enabled, |
| @@ -96,7 +96,7 @@ static struct clk *clk_reg_prcc(const char *name, · 4 unmodified lines | ||
| 96 | 96 | resource_size_t phy_base, |
| 97 | 97 | u32 cg_sel, |
| 98 | 98 | unsigned long flags, |
| 99 | − struct clk_ops *clk_prcc_ops) | |
| 99 | + const struct clk_ops *clk_prcc_ops) | |
| 100 | 100 | { |
| 101 | 101 | struct clk_prcc *clk; |
| 102 | 102 | struct clk_init_data clk_prcc_init; |
| @@ -186,7 +186,7 @@ static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) · 185 unmodified lines | ||
| 186 | 186 | clk->is_prepared = 0; |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | −static struct clk_ops clk_prcmu_scalable_ops = { | |
| 189 | +static const struct clk_ops clk_prcmu_scalable_ops = { | |
| 190 | 190 | .prepare = clk_prcmu_prepare, |
| 191 | 191 | .unprepare = clk_prcmu_unprepare, |
| 192 | 192 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -198,7 +198,7 @@ static struct clk_ops clk_prcmu_scalable_ops = { · 5 unmodified lines | ||
| 198 | 198 | .set_rate = clk_prcmu_set_rate, |
| 199 | 199 | }; |
| 200 | 200 | |
| 201 | −static struct clk_ops clk_prcmu_gate_ops = { | |
| 201 | +static const struct clk_ops clk_prcmu_gate_ops = { | |
| 202 | 202 | .prepare = clk_prcmu_prepare, |
| 203 | 203 | .unprepare = clk_prcmu_unprepare, |
| 204 | 204 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -208,19 +208,19 @@ static struct clk_ops clk_prcmu_gate_ops = { · 3 unmodified lines | ||
| 208 | 208 | .recalc_rate = clk_prcmu_recalc_rate, |
| 209 | 209 | }; |
| 210 | 210 | |
| 211 | −static struct clk_ops clk_prcmu_scalable_rate_ops = { | |
| 211 | +static const struct clk_ops clk_prcmu_scalable_rate_ops = { | |
| 212 | 212 | .is_enabled = clk_prcmu_is_enabled, |
| 213 | 213 | .recalc_rate = clk_prcmu_recalc_rate, |
| 214 | 214 | .round_rate = clk_prcmu_round_rate, |
| 215 | 215 | .set_rate = clk_prcmu_set_rate, |
| 216 | 216 | }; |
| 217 | 217 | |
| 218 | −static struct clk_ops clk_prcmu_rate_ops = { | |
| 218 | +static const struct clk_ops clk_prcmu_rate_ops = { | |
| 219 | 219 | .is_enabled = clk_prcmu_is_enabled, |
| 220 | 220 | .recalc_rate = clk_prcmu_recalc_rate, |
| 221 | 221 | }; |
| 222 | 222 | |
| 223 | −static struct clk_ops clk_prcmu_opp_gate_ops = { | |
| 223 | +static const struct clk_ops clk_prcmu_opp_gate_ops = { | |
| 224 | 224 | .prepare = clk_prcmu_opp_prepare, |
| 225 | 225 | .unprepare = clk_prcmu_opp_unprepare, |
| 226 | 226 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -230,7 +230,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = { · 3 unmodified lines | ||
| 230 | 230 | .recalc_rate = clk_prcmu_recalc_rate, |
| 231 | 231 | }; |
| 232 | 232 | |
| 233 | −static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | |
| 233 | +static const struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | |
| 234 | 234 | .prepare = clk_prcmu_opp_volt_prepare, |
| 235 | 235 | .unprepare = clk_prcmu_opp_volt_unprepare, |
| 236 | 236 | .is_prepared = clk_prcmu_is_prepared, |
| @@ -247,7 +247,7 @@ static struct clk *clk_reg_prcmu(const char *name, · 10 unmodified lines | ||
| 247 | 247 | u8 cg_sel, |
| 248 | 248 | unsigned long rate, |
| 249 | 249 | unsigned long flags, |
| 250 | − struct clk_ops *clk_prcmu_ops) | |
| 250 | + const struct clk_ops *clk_prcmu_ops) | |
| 251 | 251 | { |
| 252 | 252 | struct clk_prcmu *clk; |
| 253 | 253 | struct clk_init_data clk_prcmu_init; |
| @@ -98,18 +98,18 @@ static u8 clk_sysctrl_get_parent(struct clk_hw *hw) · 97 unmodified lines | ||
| 98 | 98 | return clk->parent_index; |
| 99 | 99 | } |
| 100 | 100 | |
| 101 | −static struct clk_ops clk_sysctrl_gate_ops = { | |
| 101 | +static const struct clk_ops clk_sysctrl_gate_ops = { | |
| 102 | 102 | .prepare = clk_sysctrl_prepare, |
| 103 | 103 | .unprepare = clk_sysctrl_unprepare, |
| 104 | 104 | }; |
| 105 | 105 | |
| 106 | −static struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { | |
| 106 | +static const struct clk_ops clk_sysctrl_gate_fixed_rate_ops = { | |
| 107 | 107 | .prepare = clk_sysctrl_prepare, |
| 108 | 108 | .unprepare = clk_sysctrl_unprepare, |
| 109 | 109 | .recalc_rate = clk_sysctrl_recalc_rate, |
| 110 | 110 | }; |
| 111 | 111 | |
| 112 | −static struct clk_ops clk_sysctrl_set_parent_ops = { | |
| 112 | +static const struct clk_ops clk_sysctrl_set_parent_ops = { | |
| 113 | 113 | .set_parent = clk_sysctrl_set_parent, |
| 114 | 114 | .get_parent = clk_sysctrl_get_parent, |
| 115 | 115 | }; |
| @@ -124,7 +124,7 @@ static struct clk *clk_reg_sysctrl(struct device *dev, · 8 unmodified lines | ||
| 124 | 124 | unsigned long rate, |
| 125 | 125 | unsigned long enable_delay_us, |
| 126 | 126 | unsigned long flags, |
| 127 | − struct clk_ops *clk_sysctrl_ops) | |
| 127 | + const struct clk_ops *clk_sysctrl_ops) | |
| 128 | 128 | { |
| 129 | 129 | struct clk_sysctrl *clk; |
| 130 | 130 | struct clk_init_data clk_sysctrl_init; |
| @@ -61,7 +61,7 @@ static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate, · 60 unmodified lines | ||
| 61 | 61 | return regmap_write(osc->reg, 0, rate); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | −static struct clk_ops vexpress_osc_ops = { | |
| 64 | +static const struct clk_ops vexpress_osc_ops = { | |
| 65 | 65 | .recalc_rate = vexpress_osc_recalc_rate, |
| 66 | 66 | .round_rate = vexpress_osc_round_rate, |
| 67 | 67 | .set_rate = vexpress_osc_set_rate, |
| @@ -451,7 +451,7 @@ static struct zx_clk_fixed_factor top_ffactor_clk[] = { · 450 unmodified lines | ||
| 451 | 451 | FFACTOR(0, "emmc_mux_div2", "emmc_mux", 1, 2, CLK_SET_RATE_PARENT), |
| 452 | 452 | }; |
| 453 | 453 | |
| 454 | −static struct clk_div_table noc_div_table[] = { | |
| 454 | +static const struct clk_div_table noc_div_table[] = { | |
| 455 | 455 | { .val = 1, .div = 2, }, |
| 456 | 456 | { .val = 3, .div = 4, }, |
| 457 | 457 | }; |
| @@ -644,7 +644,7 @@ static int __init top_clocks_init(struct device_node *np) · 186 unmodified lines | ||
| 644 | 644 | return 0; |
| 645 | 645 | } |
| 646 | 646 | |
| 647 | −static struct clk_div_table common_even_div_table[] = { | |
| 647 | +static const struct clk_div_table common_even_div_table[] = { | |
| 648 | 648 | { .val = 0, .div = 1, }, |
| 649 | 649 | { .val = 1, .div = 2, }, |
| 650 | 650 | { .val = 3, .div = 4, }, |
| @@ -656,7 +656,7 @@ static struct clk_div_table common_even_div_table[] = { · 5 unmodified lines | ||
| 656 | 656 | { .val = 15, .div = 16, }, |
| 657 | 657 | }; |
| 658 | 658 | |
| 659 | −static struct clk_div_table common_div_table[] = { | |
| 659 | +static const struct clk_div_table common_div_table[] = { | |
| 660 | 660 | { .val = 0, .div = 1, }, |
| 661 | 661 | { .val = 1, .div = 2, }, |
| 662 | 662 | { .val = 2, .div = 3, }, |
| @@ -233,6 +233,8 @@ · 232 unmodified lines | ||
| 233 | 233 | #define GCC_PCIE_CLKREF_CLK 216 |
| 234 | 234 | #define GCC_RX2_USB2_CLKREF_CLK 217 |
| 235 | 235 | #define GCC_RX1_USB2_CLKREF_CLK 218 |
| 236 | +#define GCC_HLOS1_VOTE_LPASS_CORE_SMMU_CLK 219 | |
| 237 | +#define GCC_HLOS1_VOTE_LPASS_ADSP_SMMU_CLK 220 | |
| 236 | 238 | |
| 237 | 239 | #define GCC_SYSTEM_NOC_BCR 0 |
| 238 | 240 | #define GCC_CONFIG_NOC_BCR 1 |
| @@ -0,0 +1,57 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Glider bvba | |
| 3 | + * | |
| 4 | + * This program is free software; you can redistribute it and/or modify | |
| 5 | + * it under the terms of the GNU General Public License as published by | |
| 6 | + * the Free Software Foundation; either version 2 of the License, or | |
| 7 | + * (at your option) any later version. | |
| 8 | + */ | |
| 9 | +#ifndef __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ | |
| 10 | +#define __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ | |
| 11 | + | |
| 12 | +#include <dt-bindings/clock/renesas-cpg-mssr.h> | |
| 13 | + | |
| 14 | +/* r8a77995 CPG Core Clocks */ | |
| 15 | +#define R8A77995_CLK_Z2 0 | |
| 16 | +#define R8A77995_CLK_ZG 1 | |
| 17 | +#define R8A77995_CLK_ZTR 2 | |
| 18 | +#define R8A77995_CLK_ZT 3 | |
| 19 | +#define R8A77995_CLK_ZX 4 | |
| 20 | +#define R8A77995_CLK_S0D1 5 | |
| 21 | +#define R8A77995_CLK_S1D1 6 | |
| 22 | +#define R8A77995_CLK_S1D2 7 | |
| 23 | +#define R8A77995_CLK_S1D4 8 | |
| 24 | +#define R8A77995_CLK_S2D1 9 | |
| 25 | +#define R8A77995_CLK_S2D2 10 | |
| 26 | +#define R8A77995_CLK_S2D4 11 | |
| 27 | +#define R8A77995_CLK_S3D1 12 | |
| 28 | +#define R8A77995_CLK_S3D2 13 | |
| 29 | +#define R8A77995_CLK_S3D4 14 | |
| 30 | +#define R8A77995_CLK_S1D4C 15 | |
| 31 | +#define R8A77995_CLK_S3D1C 16 | |
| 32 | +#define R8A77995_CLK_S3D2C 17 | |
| 33 | +#define R8A77995_CLK_S3D4C 18 | |
| 34 | +#define R8A77995_CLK_LB 19 | |
| 35 | +#define R8A77995_CLK_CL 20 | |
| 36 | +#define R8A77995_CLK_ZB3 21 | |
| 37 | +#define R8A77995_CLK_ZB3D2 22 | |
| 38 | +#define R8A77995_CLK_CR 23 | |
| 39 | +#define R8A77995_CLK_CRD2 24 | |
| 40 | +#define R8A77995_CLK_SD0H 25 | |
| 41 | +#define R8A77995_CLK_SD0 26 | |
| 42 | +#define R8A77995_CLK_SSP2 27 | |
| 43 | +#define R8A77995_CLK_SSP1 28 | |
| 44 | +#define R8A77995_CLK_RPC 29 | |
| 45 | +#define R8A77995_CLK_RPCD2 30 | |
| 46 | +#define R8A77995_CLK_ZA2 31 | |
| 47 | +#define R8A77995_CLK_ZA8 32 | |
| 48 | +#define R8A77995_CLK_Z2D 33 | |
| 49 | +#define R8A77995_CLK_CANFD 34 | |
| 50 | +#define R8A77995_CLK_MSO 35 | |
| 51 | +#define R8A77995_CLK_R 36 | |
| 52 | +#define R8A77995_CLK_OSC 37 | |
| 53 | +#define R8A77995_CLK_LV0 38 | |
| 54 | +#define R8A77995_CLK_LV1 39 | |
| 55 | +#define R8A77995_CLK_CP 40 | |
| 56 | + | |
| 57 | +#endif /* __DT_BINDINGS_CLOCK_R8A77995_CPG_MSSR_H__ */ | |
| @@ -49,6 +49,7 @@ · 48 unmodified lines | ||
| 49 | 49 | #define SCLK_EMMC_DRV 117 |
| 50 | 50 | #define SCLK_SDMMC_SAMPLE 118 |
| 51 | 51 | #define SCLK_SDIO_SAMPLE 119 |
| 52 | +#define SCLK_SDIO_SRC 120 | |
| 52 | 53 | #define SCLK_EMMC_SAMPLE 121 |
| 53 | 54 | #define SCLK_VOP 122 |
| 54 | 55 | #define SCLK_HDMI_HDCP 123 |
| @@ -67,9 +67,9 @@ · 66 unmodified lines | ||
| 67 | 67 | #define SCLK_SPI 108 |
| 68 | 68 | #define SCLK_SARADC 109 |
| 69 | 69 | #define SCLK_TSADC 110 |
| 70 | −#define SCLK_MACPHY_PRE 111 | |
| 71 | −#define SCLK_MACPHY 112 | |
| 72 | −#define SCLK_MACPHY_RX 113 | |
| 70 | +#define SCLK_MAC_PRE 111 | |
| 71 | +#define SCLK_MAC 112 | |
| 72 | +#define SCLK_MAC_RX 113 | |
| 73 | 73 | #define SCLK_MAC_REF 114 |
| 74 | 74 | #define SCLK_MAC_REFOUT 115 |
| 75 | 75 | #define SCLK_DSP_PFM 116 |
| @@ -110,6 +110,7 @@ · 34 unmodified lines | ||
| 110 | 110 | #define ACLK_CIF2 207 |
| 111 | 111 | #define ACLK_CIF3 208 |
| 112 | 112 | #define ACLK_PERI 209 |
| 113 | +#define ACLK_GMAC 210 | |
| 113 | 114 | |
| 114 | 115 | /* pclk gates */ |
| 115 | 116 | #define PCLK_GPIO1 256 |
| @@ -141,6 +142,7 @@ · 25 unmodified lines | ||
| 141 | 142 | #define PCLK_EFUSE0 282 |
| 142 | 143 | #define PCLK_EFUSE1 283 |
| 143 | 144 | #define PCLK_WDT 284 |
| 145 | +#define PCLK_GMAC 285 | |
| 144 | 146 | |
| 145 | 147 | /* hclk gates */ |
| 146 | 148 | #define HCLK_I2S0_8CH 320 |
| @@ -0,0 +1,165 @@ | ||
| 1 | +/* SYS, CORE AND BUS CLOCKS */ | |
| 2 | +#define SYS_D1CPRE 0 | |
| 3 | +#define HCLK 1 | |
| 4 | +#define PCLK1 2 | |
| 5 | +#define PCLK2 3 | |
| 6 | +#define PCLK3 4 | |
| 7 | +#define PCLK4 5 | |
| 8 | +#define HSI_DIV 6 | |
| 9 | +#define HSE_1M 7 | |
| 10 | +#define I2S_CKIN 8 | |
| 11 | +#define CK_DSI_PHY 9 | |
| 12 | +#define HSE_CK 10 | |
| 13 | +#define LSE_CK 11 | |
| 14 | +#define CSI_KER_DIV122 12 | |
| 15 | +#define RTC_CK 13 | |
| 16 | +#define CPU_SYSTICK 14 | |
| 17 | + | |
| 18 | +/* OSCILLATOR BANK */ | |
| 19 | +#define OSC_BANK 18 | |
| 20 | +#define HSI_CK 18 | |
| 21 | +#define HSI_KER_CK 19 | |
| 22 | +#define CSI_CK 20 | |
| 23 | +#define CSI_KER_CK 21 | |
| 24 | +#define RC48_CK 22 | |
| 25 | +#define LSI_CK 23 | |
| 26 | + | |
| 27 | +/* MCLOCK BANK */ | |
| 28 | +#define MCLK_BANK 28 | |
| 29 | +#define PER_CK 28 | |
| 30 | +#define PLLSRC 29 | |
| 31 | +#define SYS_CK 30 | |
| 32 | +#define TRACEIN_CK 31 | |
| 33 | + | |
| 34 | +/* ODF BANK */ | |
| 35 | +#define ODF_BANK 32 | |
| 36 | +#define PLL1_P 32 | |
| 37 | +#define PLL1_Q 33 | |
| 38 | +#define PLL1_R 34 | |
| 39 | +#define PLL2_P 35 | |
| 40 | +#define PLL2_Q 36 | |
| 41 | +#define PLL2_R 37 | |
| 42 | +#define PLL3_P 38 | |
| 43 | +#define PLL3_Q 39 | |
| 44 | +#define PLL3_R 40 | |
| 45 | + | |
| 46 | +/* MCO BANK */ | |
| 47 | +#define MCO_BANK 41 | |
| 48 | +#define MCO1 41 | |
| 49 | +#define MCO2 42 | |
| 50 | + | |
| 51 | +/* PERIF BANK */ | |
| 52 | +#define PERIF_BANK 50 | |
| 53 | +#define D1SRAM1_CK 50 | |
| 54 | +#define ITCM_CK 51 | |
| 55 | +#define DTCM2_CK 52 | |
| 56 | +#define DTCM1_CK 53 | |
| 57 | +#define FLITF_CK 54 | |
| 58 | +#define JPGDEC_CK 55 | |
| 59 | +#define DMA2D_CK 56 | |
| 60 | +#define MDMA_CK 57 | |
| 61 | +#define USB2ULPI_CK 58 | |
| 62 | +#define USB1ULPI_CK 59 | |
| 63 | +#define ETH1RX_CK 60 | |
| 64 | +#define ETH1TX_CK 61 | |
| 65 | +#define ETH1MAC_CK 62 | |
| 66 | +#define ART_CK 63 | |
| 67 | +#define DMA2_CK 64 | |
| 68 | +#define DMA1_CK 65 | |
| 69 | +#define D2SRAM3_CK 66 | |
| 70 | +#define D2SRAM2_CK 67 | |
| 71 | +#define D2SRAM1_CK 68 | |
| 72 | +#define HASH_CK 69 | |
| 73 | +#define CRYPT_CK 70 | |
| 74 | +#define CAMITF_CK 71 | |
| 75 | +#define BKPRAM_CK 72 | |
| 76 | +#define HSEM_CK 73 | |
| 77 | +#define BDMA_CK 74 | |
| 78 | +#define CRC_CK 75 | |
| 79 | +#define GPIOK_CK 76 | |
| 80 | +#define GPIOJ_CK 77 | |
| 81 | +#define GPIOI_CK 78 | |
| 82 | +#define GPIOH_CK 79 | |
| 83 | +#define GPIOG_CK 80 | |
| 84 | +#define GPIOF_CK 81 | |
| 85 | +#define GPIOE_CK 82 | |
| 86 | +#define GPIOD_CK 83 | |
| 87 | +#define GPIOC_CK 84 | |
| 88 | +#define GPIOB_CK 85 | |
| 89 | +#define GPIOA_CK 86 | |
| 90 | +#define WWDG1_CK 87 | |
| 91 | +#define DAC12_CK 88 | |
| 92 | +#define WWDG2_CK 89 | |
| 93 | +#define TIM14_CK 90 | |
| 94 | +#define TIM13_CK 91 | |
| 95 | +#define TIM12_CK 92 | |
| 96 | +#define TIM7_CK 93 | |
| 97 | +#define TIM6_CK 94 | |
| 98 | +#define TIM5_CK 95 | |
| 99 | +#define TIM4_CK 96 | |
| 100 | +#define TIM3_CK 97 | |
| 101 | +#define TIM2_CK 98 | |
| 102 | +#define MDIOS_CK 99 | |
| 103 | +#define OPAMP_CK 100 | |
| 104 | +#define CRS_CK 101 | |
| 105 | +#define TIM17_CK 102 | |
| 106 | +#define TIM16_CK 103 | |
| 107 | +#define TIM15_CK 104 | |
| 108 | +#define TIM8_CK 105 | |
| 109 | +#define TIM1_CK 106 | |
| 110 | +#define TMPSENS_CK 107 | |
| 111 | +#define RTCAPB_CK 108 | |
| 112 | +#define VREF_CK 109 | |
| 113 | +#define COMP12_CK 110 | |
| 114 | +#define SYSCFG_CK 111 | |
| 115 | + | |
| 116 | +/* KERNEL BANK */ | |
| 117 | +#define KERN_BANK 120 | |
| 118 | +#define SDMMC1_CK 120 | |
| 119 | +#define QUADSPI_CK 121 | |
| 120 | +#define FMC_CK 122 | |
| 121 | +#define USB2OTG_CK 123 | |
| 122 | +#define USB1OTG_CK 124 | |
| 123 | +#define ADC12_CK 125 | |
| 124 | +#define SDMMC2_CK 126 | |
| 125 | +#define RNG_CK 127 | |
| 126 | +#define ADC3_CK 128 | |
| 127 | +#define DSI_CK 129 | |
| 128 | +#define LTDC_CK 130 | |
| 129 | +#define USART8_CK 131 | |
| 130 | +#define USART7_CK 132 | |
| 131 | +#define HDMICEC_CK 133 | |
| 132 | +#define I2C3_CK 134 | |
| 133 | +#define I2C2_CK 135 | |
| 134 | +#define I2C1_CK 136 | |
| 135 | +#define UART5_CK 137 | |
| 136 | +#define UART4_CK 138 | |
| 137 | +#define USART3_CK 139 | |
| 138 | +#define USART2_CK 140 | |
| 139 | +#define SPDIFRX_CK 141 | |
| 140 | +#define SPI3_CK 142 | |
| 141 | +#define SPI2_CK 143 | |
| 142 | +#define LPTIM1_CK 144 | |
| 143 | +#define FDCAN_CK 145 | |
| 144 | +#define SWP_CK 146 | |
| 145 | +#define HRTIM_CK 147 | |
| 146 | +#define DFSDM1_CK 148 | |
| 147 | +#define SAI3_CK 149 | |
| 148 | +#define SAI2_CK 150 | |
| 149 | +#define SAI1_CK 151 | |
| 150 | +#define SPI5_CK 152 | |
| 151 | +#define SPI4_CK 153 | |
| 152 | +#define SPI1_CK 154 | |
| 153 | +#define USART6_CK 155 | |
| 154 | +#define USART1_CK 156 | |
| 155 | +#define SAI4B_CK 157 | |
| 156 | +#define SAI4A_CK 158 | |
| 157 | +#define LPTIM5_CK 159 | |
| 158 | +#define LPTIM4_CK 160 | |
| 159 | +#define LPTIM3_CK 161 | |
| 160 | +#define LPTIM2_CK 162 | |
| 161 | +#define I2C4_CK 163 | |
| 162 | +#define SPI6_CK 164 | |
| 163 | +#define LPUART1_CK 165 | |
| 164 | + | |
| 165 | +#define STM32H7_MAX_CLKS 166 | |
| @@ -0,0 +1,200 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | |
| 3 | + * | |
| 4 | + * This file is dual-licensed: you can use it either under the terms | |
| 5 | + * of the GPL or the X11 license, at your option. Note that this dual | |
| 6 | + * licensing only applies to this file, and not this project as a | |
| 7 | + * whole. | |
| 8 | + * | |
| 9 | + * a) This file is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU General Public License as | |
| 11 | + * published by the Free Software Foundation; either version 2 of the | |
| 12 | + * License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This file is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * Or, alternatively, | |
| 20 | + * | |
| 21 | + * b) Permission is hereby granted, free of charge, to any person | |
| 22 | + * obtaining a copy of this software and associated documentation | |
| 23 | + * files (the "Software"), to deal in the Software without | |
| 24 | + * restriction, including without limitation the rights to use, | |
| 25 | + * copy, modify, merge, publish, distribute, sublicense, and/or | |
| 26 | + * sell copies of the Software, and to permit persons to whom the | |
| 27 | + * Software is furnished to do so, subject to the following | |
| 28 | + * conditions: | |
| 29 | + * | |
| 30 | + * The above copyright notice and this permission notice shall be | |
| 31 | + * included in all copies or substantial portions of the Software. | |
| 32 | + * | |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 34 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 35 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 36 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| 37 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 38 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 39 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 40 | + */ | |
| 41 | + | |
| 42 | +#ifndef _DT_BINDINGS_CLK_SUN4I_A10_H_ | |
| 43 | +#define _DT_BINDINGS_CLK_SUN4I_A10_H_ | |
| 44 | + | |
| 45 | +#define CLK_HOSC 1 | |
| 46 | +#define CLK_CPU 20 | |
| 47 | + | |
| 48 | +/* AHB Gates */ | |
| 49 | +#define CLK_AHB_OTG 26 | |
| 50 | +#define CLK_AHB_EHCI0 27 | |
| 51 | +#define CLK_AHB_OHCI0 28 | |
| 52 | +#define CLK_AHB_EHCI1 29 | |
| 53 | +#define CLK_AHB_OHCI1 30 | |
| 54 | +#define CLK_AHB_SS 31 | |
| 55 | +#define CLK_AHB_DMA 32 | |
| 56 | +#define CLK_AHB_BIST 33 | |
| 57 | +#define CLK_AHB_MMC0 34 | |
| 58 | +#define CLK_AHB_MMC1 35 | |
| 59 | +#define CLK_AHB_MMC2 36 | |
| 60 | +#define CLK_AHB_MMC3 37 | |
| 61 | +#define CLK_AHB_MS 38 | |
| 62 | +#define CLK_AHB_NAND 39 | |
| 63 | +#define CLK_AHB_SDRAM 40 | |
| 64 | +#define CLK_AHB_ACE 41 | |
| 65 | +#define CLK_AHB_EMAC 42 | |
| 66 | +#define CLK_AHB_TS 43 | |
| 67 | +#define CLK_AHB_SPI0 44 | |
| 68 | +#define CLK_AHB_SPI1 45 | |
| 69 | +#define CLK_AHB_SPI2 46 | |
| 70 | +#define CLK_AHB_SPI3 47 | |
| 71 | +#define CLK_AHB_PATA 48 | |
| 72 | +#define CLK_AHB_SATA 49 | |
| 73 | +#define CLK_AHB_GPS 50 | |
| 74 | +#define CLK_AHB_HSTIMER 51 | |
| 75 | +#define CLK_AHB_VE 52 | |
| 76 | +#define CLK_AHB_TVD 53 | |
| 77 | +#define CLK_AHB_TVE0 54 | |
| 78 | +#define CLK_AHB_TVE1 55 | |
| 79 | +#define CLK_AHB_LCD0 56 | |
| 80 | +#define CLK_AHB_LCD1 57 | |
| 81 | +#define CLK_AHB_CSI0 58 | |
| 82 | +#define CLK_AHB_CSI1 59 | |
| 83 | +#define CLK_AHB_HDMI0 60 | |
| 84 | +#define CLK_AHB_HDMI1 61 | |
| 85 | +#define CLK_AHB_DE_BE0 62 | |
| 86 | +#define CLK_AHB_DE_BE1 63 | |
| 87 | +#define CLK_AHB_DE_FE0 64 | |
| 88 | +#define CLK_AHB_DE_FE1 65 | |
| 89 | +#define CLK_AHB_GMAC 66 | |
| 90 | +#define CLK_AHB_MP 67 | |
| 91 | +#define CLK_AHB_GPU 68 | |
| 92 | + | |
| 93 | +/* APB0 Gates */ | |
| 94 | +#define CLK_APB0_CODEC 69 | |
| 95 | +#define CLK_APB0_SPDIF 70 | |
| 96 | +#define CLK_APB0_I2S0 71 | |
| 97 | +#define CLK_APB0_AC97 72 | |
| 98 | +#define CLK_APB0_I2S1 73 | |
| 99 | +#define CLK_APB0_PIO 74 | |
| 100 | +#define CLK_APB0_IR0 75 | |
| 101 | +#define CLK_APB0_IR1 76 | |
| 102 | +#define CLK_APB0_I2S2 77 | |
| 103 | +#define CLK_APB0_KEYPAD 78 | |
| 104 | + | |
| 105 | +/* APB1 Gates */ | |
| 106 | +#define CLK_APB1_I2C0 79 | |
| 107 | +#define CLK_APB1_I2C1 80 | |
| 108 | +#define CLK_APB1_I2C2 81 | |
| 109 | +#define CLK_APB1_I2C3 82 | |
| 110 | +#define CLK_APB1_CAN 83 | |
| 111 | +#define CLK_APB1_SCR 84 | |
| 112 | +#define CLK_APB1_PS20 85 | |
| 113 | +#define CLK_APB1_PS21 86 | |
| 114 | +#define CLK_APB1_I2C4 87 | |
| 115 | +#define CLK_APB1_UART0 88 | |
| 116 | +#define CLK_APB1_UART1 89 | |
| 117 | +#define CLK_APB1_UART2 90 | |
| 118 | +#define CLK_APB1_UART3 91 | |
| 119 | +#define CLK_APB1_UART4 92 | |
| 120 | +#define CLK_APB1_UART5 93 | |
| 121 | +#define CLK_APB1_UART6 94 | |
| 122 | +#define CLK_APB1_UART7 95 | |
| 123 | + | |
| 124 | +/* IP clocks */ | |
| 125 | +#define CLK_NAND 96 | |
| 126 | +#define CLK_MS 97 | |
| 127 | +#define CLK_MMC0 98 | |
| 128 | +#define CLK_MMC0_OUTPUT 99 | |
| 129 | +#define CLK_MMC0_SAMPLE 100 | |
| 130 | +#define CLK_MMC1 101 | |
| 131 | +#define CLK_MMC1_OUTPUT 102 | |
| 132 | +#define CLK_MMC1_SAMPLE 103 | |
| 133 | +#define CLK_MMC2 104 | |
| 134 | +#define CLK_MMC2_OUTPUT 105 | |
| 135 | +#define CLK_MMC2_SAMPLE 106 | |
| 136 | +#define CLK_MMC3 107 | |
| 137 | +#define CLK_MMC3_OUTPUT 108 | |
| 138 | +#define CLK_MMC3_SAMPLE 109 | |
| 139 | +#define CLK_TS 110 | |
| 140 | +#define CLK_SS 111 | |
| 141 | +#define CLK_SPI0 112 | |
| 142 | +#define CLK_SPI1 113 | |
| 143 | +#define CLK_SPI2 114 | |
| 144 | +#define CLK_PATA 115 | |
| 145 | +#define CLK_IR0 116 | |
| 146 | +#define CLK_IR1 117 | |
| 147 | +#define CLK_I2S0 118 | |
| 148 | +#define CLK_AC97 119 | |
| 149 | +#define CLK_SPDIF 120 | |
| 150 | +#define CLK_KEYPAD 121 | |
| 151 | +#define CLK_SATA 122 | |
| 152 | +#define CLK_USB_OHCI0 123 | |
| 153 | +#define CLK_USB_OHCI1 124 | |
| 154 | +#define CLK_USB_PHY 125 | |
| 155 | +#define CLK_GPS 126 | |
| 156 | +#define CLK_SPI3 127 | |
| 157 | +#define CLK_I2S1 128 | |
| 158 | +#define CLK_I2S2 129 | |
| 159 | + | |
| 160 | +/* DRAM Gates */ | |
| 161 | +#define CLK_DRAM_VE 130 | |
| 162 | +#define CLK_DRAM_CSI0 131 | |
| 163 | +#define CLK_DRAM_CSI1 132 | |
| 164 | +#define CLK_DRAM_TS 133 | |
| 165 | +#define CLK_DRAM_TVD 134 | |
| 166 | +#define CLK_DRAM_TVE0 135 | |
| 167 | +#define CLK_DRAM_TVE1 136 | |
| 168 | +#define CLK_DRAM_OUT 137 | |
| 169 | +#define CLK_DRAM_DE_FE1 138 | |
| 170 | +#define CLK_DRAM_DE_FE0 139 | |
| 171 | +#define CLK_DRAM_DE_BE0 140 | |
| 172 | +#define CLK_DRAM_DE_BE1 141 | |
| 173 | +#define CLK_DRAM_MP 142 | |
| 174 | +#define CLK_DRAM_ACE 143 | |
| 175 | + | |
| 176 | +/* Display Engine Clocks */ | |
| 177 | +#define CLK_DE_BE0 144 | |
| 178 | +#define CLK_DE_BE1 145 | |
| 179 | +#define CLK_DE_FE0 146 | |
| 180 | +#define CLK_DE_FE1 147 | |
| 181 | +#define CLK_DE_MP 148 | |
| 182 | +#define CLK_TCON0_CH0 149 | |
| 183 | +#define CLK_TCON1_CH0 150 | |
| 184 | +#define CLK_CSI_SCLK 151 | |
| 185 | +#define CLK_TVD_SCLK2 152 | |
| 186 | +#define CLK_TVD 153 | |
| 187 | +#define CLK_TCON0_CH1_SCLK2 154 | |
| 188 | +#define CLK_TCON0_CH1 155 | |
| 189 | +#define CLK_TCON1_CH1_SCLK2 156 | |
| 190 | +#define CLK_TCON1_CH1 157 | |
| 191 | +#define CLK_CSI0 158 | |
| 192 | +#define CLK_CSI1 159 | |
| 193 | +#define CLK_CODEC 160 | |
| 194 | +#define CLK_VE 161 | |
| 195 | +#define CLK_AVS 162 | |
| 196 | +#define CLK_ACE 163 | |
| 197 | +#define CLK_HDMI 164 | |
| 198 | +#define CLK_GPU 165 | |
| 199 | + | |
| 200 | +#endif /* _DT_BINDINGS_CLK_SUN4I_A10_H_ */ | |
| @@ -0,0 +1,53 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | |
| 3 | + * | |
| 4 | + * This file is dual-licensed: you can use it either under the terms | |
| 5 | + * of the GPL or the X11 license, at your option. Note that this dual | |
| 6 | + * licensing only applies to this file, and not this project as a | |
| 7 | + * whole. | |
| 8 | + * | |
| 9 | + * a) This file is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU General Public License as | |
| 11 | + * published by the Free Software Foundation; either version 2 of the | |
| 12 | + * License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This file is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * Or, alternatively, | |
| 20 | + * | |
| 21 | + * b) Permission is hereby granted, free of charge, to any person | |
| 22 | + * obtaining a copy of this software and associated documentation | |
| 23 | + * files (the "Software"), to deal in the Software without | |
| 24 | + * restriction, including without limitation the rights to use, | |
| 25 | + * copy, modify, merge, publish, distribute, sublicense, and/or | |
| 26 | + * sell copies of the Software, and to permit persons to whom the | |
| 27 | + * Software is furnished to do so, subject to the following | |
| 28 | + * conditions: | |
| 29 | + * | |
| 30 | + * The above copyright notice and this permission notice shall be | |
| 31 | + * included in all copies or substantial portions of the Software. | |
| 32 | + * | |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 34 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 35 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 36 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| 37 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 38 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 39 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 40 | + */ | |
| 41 | + | |
| 42 | +#ifndef _DT_BINDINGS_CLK_SUN7I_A20_H_ | |
| 43 | +#define _DT_BINDINGS_CLK_SUN7I_A20_H_ | |
| 44 | + | |
| 45 | +#include <dt-bindings/clock/sun4i-a10-ccu.h> | |
| 46 | + | |
| 47 | +#define CLK_MBUS 166 | |
| 48 | +#define CLK_HDMI1_SLOW 167 | |
| 49 | +#define CLK_HDMI1 168 | |
| 50 | +#define CLK_OUT_A 169 | |
| 51 | +#define CLK_OUT_B 170 | |
| 52 | + | |
| 53 | +#endif /* _DT_BINDINGS_CLK_SUN7I_A20_H_ */ | |
| @@ -0,0 +1,187 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io> | |
| 3 | + * | |
| 4 | + * This file is dual-licensed: you can use it either under the terms | |
| 5 | + * of the GPL or the X11 license, at your option. Note that this dual | |
| 6 | + * licensing only applies to this file, and not this project as a | |
| 7 | + * whole. | |
| 8 | + * | |
| 9 | + * a) This file is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU General Public License as | |
| 11 | + * published by the Free Software Foundation; either version 2 of the | |
| 12 | + * License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This file is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * Or, alternatively, | |
| 20 | + * | |
| 21 | + * b) Permission is hereby granted, free of charge, to any person | |
| 22 | + * obtaining a copy of this software and associated documentation | |
| 23 | + * files (the "Software"), to deal in the Software without | |
| 24 | + * restriction, including without limitation the rights to use, | |
| 25 | + * copy, modify, merge, publish, distribute, sublicense, and/or | |
| 26 | + * sell copies of the Software, and to permit persons to whom the | |
| 27 | + * Software is furnished to do so, subject to the following | |
| 28 | + * conditions: | |
| 29 | + * | |
| 30 | + * The above copyright notice and this permission notice shall be | |
| 31 | + * included in all copies or substantial portions of the Software. | |
| 32 | + * | |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 34 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 35 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 36 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| 37 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 38 | + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 39 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 40 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 41 | + */ | |
| 42 | + | |
| 43 | +#ifndef _DT_BINDINGS_CLK_SUN8I_R40_H_ | |
| 44 | +#define _DT_BINDINGS_CLK_SUN8I_R40_H_ | |
| 45 | + | |
| 46 | +#define CLK_CPU 24 | |
| 47 | + | |
| 48 | +#define CLK_BUS_MIPI_DSI 29 | |
| 49 | +#define CLK_BUS_CE 30 | |
| 50 | +#define CLK_BUS_DMA 31 | |
| 51 | +#define CLK_BUS_MMC0 32 | |
| 52 | +#define CLK_BUS_MMC1 33 | |
| 53 | +#define CLK_BUS_MMC2 34 | |
| 54 | +#define CLK_BUS_MMC3 35 | |
| 55 | +#define CLK_BUS_NAND 36 | |
| 56 | +#define CLK_BUS_DRAM 37 | |
| 57 | +#define CLK_BUS_EMAC 38 | |
| 58 | +#define CLK_BUS_TS 39 | |
| 59 | +#define CLK_BUS_HSTIMER 40 | |
| 60 | +#define CLK_BUS_SPI0 41 | |
| 61 | +#define CLK_BUS_SPI1 42 | |
| 62 | +#define CLK_BUS_SPI2 43 | |
| 63 | +#define CLK_BUS_SPI3 44 | |
| 64 | +#define CLK_BUS_SATA 45 | |
| 65 | +#define CLK_BUS_OTG 46 | |
| 66 | +#define CLK_BUS_EHCI0 47 | |
| 67 | +#define CLK_BUS_EHCI1 48 | |
| 68 | +#define CLK_BUS_EHCI2 49 | |
| 69 | +#define CLK_BUS_OHCI0 50 | |
| 70 | +#define CLK_BUS_OHCI1 51 | |
| 71 | +#define CLK_BUS_OHCI2 52 | |
| 72 | +#define CLK_BUS_VE 53 | |
| 73 | +#define CLK_BUS_MP 54 | |
| 74 | +#define CLK_BUS_DEINTERLACE 55 | |
| 75 | +#define CLK_BUS_CSI0 56 | |
| 76 | +#define CLK_BUS_CSI1 57 | |
| 77 | +#define CLK_BUS_HDMI1 58 | |
| 78 | +#define CLK_BUS_HDMI0 59 | |
| 79 | +#define CLK_BUS_DE 60 | |
| 80 | +#define CLK_BUS_TVE0 61 | |
| 81 | +#define CLK_BUS_TVE1 62 | |
| 82 | +#define CLK_BUS_TVE_TOP 63 | |
| 83 | +#define CLK_BUS_GMAC 64 | |
| 84 | +#define CLK_BUS_GPU 65 | |
| 85 | +#define CLK_BUS_TVD0 66 | |
| 86 | +#define CLK_BUS_TVD1 67 | |
| 87 | +#define CLK_BUS_TVD2 68 | |
| 88 | +#define CLK_BUS_TVD3 69 | |
| 89 | +#define CLK_BUS_TVD_TOP 70 | |
| 90 | +#define CLK_BUS_TCON_LCD0 71 | |
| 91 | +#define CLK_BUS_TCON_LCD1 72 | |
| 92 | +#define CLK_BUS_TCON_TV0 73 | |
| 93 | +#define CLK_BUS_TCON_TV1 74 | |
| 94 | +#define CLK_BUS_TCON_TOP 75 | |
| 95 | +#define CLK_BUS_CODEC 76 | |
| 96 | +#define CLK_BUS_SPDIF 77 | |
| 97 | +#define CLK_BUS_AC97 78 | |
| 98 | +#define CLK_BUS_PIO 79 | |
| 99 | +#define CLK_BUS_IR0 80 | |
| 100 | +#define CLK_BUS_IR1 81 | |
| 101 | +#define CLK_BUS_THS 82 | |
| 102 | +#define CLK_BUS_KEYPAD 83 | |
| 103 | +#define CLK_BUS_I2S0 84 | |
| 104 | +#define CLK_BUS_I2S1 85 | |
| 105 | +#define CLK_BUS_I2S2 86 | |
| 106 | +#define CLK_BUS_I2C0 87 | |
| 107 | +#define CLK_BUS_I2C1 88 | |
| 108 | +#define CLK_BUS_I2C2 89 | |
| 109 | +#define CLK_BUS_I2C3 90 | |
| 110 | +#define CLK_BUS_CAN 91 | |
| 111 | +#define CLK_BUS_SCR 92 | |
| 112 | +#define CLK_BUS_PS20 93 | |
| 113 | +#define CLK_BUS_PS21 94 | |
| 114 | +#define CLK_BUS_I2C4 95 | |
| 115 | +#define CLK_BUS_UART0 96 | |
| 116 | +#define CLK_BUS_UART1 97 | |
| 117 | +#define CLK_BUS_UART2 98 | |
| 118 | +#define CLK_BUS_UART3 99 | |
| 119 | +#define CLK_BUS_UART4 100 | |
| 120 | +#define CLK_BUS_UART5 101 | |
| 121 | +#define CLK_BUS_UART6 102 | |
| 122 | +#define CLK_BUS_UART7 103 | |
| 123 | +#define CLK_BUS_DBG 104 | |
| 124 | + | |
| 125 | +#define CLK_THS 105 | |
| 126 | +#define CLK_NAND 106 | |
| 127 | +#define CLK_MMC0 107 | |
| 128 | +#define CLK_MMC1 108 | |
| 129 | +#define CLK_MMC2 109 | |
| 130 | +#define CLK_MMC3 110 | |
| 131 | +#define CLK_TS 111 | |
| 132 | +#define CLK_CE 112 | |
| 133 | +#define CLK_SPI0 113 | |
| 134 | +#define CLK_SPI1 114 | |
| 135 | +#define CLK_SPI2 115 | |
| 136 | +#define CLK_SPI3 116 | |
| 137 | +#define CLK_I2S0 117 | |
| 138 | +#define CLK_I2S1 118 | |
| 139 | +#define CLK_I2S2 119 | |
| 140 | +#define CLK_AC97 120 | |
| 141 | +#define CLK_SPDIF 121 | |
| 142 | +#define CLK_KEYPAD 122 | |
| 143 | +#define CLK_SATA 123 | |
| 144 | +#define CLK_USB_PHY0 124 | |
| 145 | +#define CLK_USB_PHY1 125 | |
| 146 | +#define CLK_USB_PHY2 126 | |
| 147 | +#define CLK_USB_OHCI0 127 | |
| 148 | +#define CLK_USB_OHCI1 128 | |
| 149 | +#define CLK_USB_OHCI2 129 | |
| 150 | +#define CLK_IR0 130 | |
| 151 | +#define CLK_IR1 131 | |
| 152 | + | |
| 153 | +#define CLK_DRAM_VE 133 | |
| 154 | +#define CLK_DRAM_CSI0 134 | |
| 155 | +#define CLK_DRAM_CSI1 135 | |
| 156 | +#define CLK_DRAM_TS 136 | |
| 157 | +#define CLK_DRAM_TVD 137 | |
| 158 | +#define CLK_DRAM_MP 138 | |
| 159 | +#define CLK_DRAM_DEINTERLACE 139 | |
| 160 | +#define CLK_DE 140 | |
| 161 | +#define CLK_MP 141 | |
| 162 | +#define CLK_TCON_LCD0 142 | |
| 163 | +#define CLK_TCON_LCD1 143 | |
| 164 | +#define CLK_TCON_TV0 144 | |
| 165 | +#define CLK_TCON_TV1 145 | |
| 166 | +#define CLK_DEINTERLACE 146 | |
| 167 | +#define CLK_CSI1_MCLK 147 | |
| 168 | +#define CLK_CSI_SCLK 148 | |
| 169 | +#define CLK_CSI0_MCLK 149 | |
| 170 | +#define CLK_VE 150 | |
| 171 | +#define CLK_CODEC 151 | |
| 172 | +#define CLK_AVS 152 | |
| 173 | +#define CLK_HDMI 153 | |
| 174 | +#define CLK_HDMI_SLOW 154 | |
| 175 | + | |
| 176 | +#define CLK_DSI_DPHY 156 | |
| 177 | +#define CLK_TVE0 157 | |
| 178 | +#define CLK_TVE1 158 | |
| 179 | +#define CLK_TVD0 159 | |
| 180 | +#define CLK_TVD1 160 | |
| 181 | +#define CLK_TVD2 161 | |
| 182 | +#define CLK_TVD3 162 | |
| 183 | +#define CLK_GPU 163 | |
| 184 | +#define CLK_OUTA 164 | |
| 185 | +#define CLK_OUTB 165 | |
| 186 | + | |
| 187 | +#endif /* _DT_BINDINGS_CLK_SUN8I_R40_H_ */ | |
| @@ -0,0 +1,136 @@ | ||
| 1 | +/* | |
| 2 | + * This header provides constants for the STM32H7 RCC IP | |
| 3 | + */ | |
| 4 | + | |
| 5 | +#ifndef _DT_BINDINGS_MFD_STM32H7_RCC_H | |
| 6 | +#define _DT_BINDINGS_MFD_STM32H7_RCC_H | |
| 7 | + | |
| 8 | +/* AHB3 */ | |
| 9 | +#define STM32H7_RCC_AHB3_MDMA 0 | |
| 10 | +#define STM32H7_RCC_AHB3_DMA2D 4 | |
| 11 | +#define STM32H7_RCC_AHB3_JPGDEC 5 | |
| 12 | +#define STM32H7_RCC_AHB3_FMC 12 | |
| 13 | +#define STM32H7_RCC_AHB3_QUADSPI 14 | |
| 14 | +#define STM32H7_RCC_AHB3_SDMMC1 16 | |
| 15 | +#define STM32H7_RCC_AHB3_CPU 31 | |
| 16 | + | |
| 17 | +#define STM32H7_AHB3_RESET(bit) (STM32H7_RCC_AHB3_##bit + (0x7C * 8)) | |
| 18 | + | |
| 19 | +/* AHB1 */ | |
| 20 | +#define STM32H7_RCC_AHB1_DMA1 0 | |
| 21 | +#define STM32H7_RCC_AHB1_DMA2 1 | |
| 22 | +#define STM32H7_RCC_AHB1_ADC12 5 | |
| 23 | +#define STM32H7_RCC_AHB1_ART 14 | |
| 24 | +#define STM32H7_RCC_AHB1_ETH1MAC 15 | |
| 25 | +#define STM32H7_RCC_AHB1_USB1OTG 25 | |
| 26 | +#define STM32H7_RCC_AHB1_USB2OTG 27 | |
| 27 | + | |
| 28 | +#define STM32H7_AHB1_RESET(bit) (STM32H7_RCC_AHB1_##bit + (0x80 * 8)) | |
| 29 | + | |
| 30 | +/* AHB2 */ | |
| 31 | +#define STM32H7_RCC_AHB2_CAMITF 0 | |
| 32 | +#define STM32H7_RCC_AHB2_CRYPT 4 | |
| 33 | +#define STM32H7_RCC_AHB2_HASH 5 | |
| 34 | +#define STM32H7_RCC_AHB2_RNG 6 | |
| 35 | +#define STM32H7_RCC_AHB2_SDMMC2 9 | |
| 36 | + | |
| 37 | +#define STM32H7_AHB2_RESET(bit) (STM32H7_RCC_AHB2_##bit + (0x84 * 8)) | |
| 38 | + | |
| 39 | +/* AHB4 */ | |
| 40 | +#define STM32H7_RCC_AHB4_GPIOA 0 | |
| 41 | +#define STM32H7_RCC_AHB4_GPIOB 1 | |
| 42 | +#define STM32H7_RCC_AHB4_GPIOC 2 | |
| 43 | +#define STM32H7_RCC_AHB4_GPIOD 3 | |
| 44 | +#define STM32H7_RCC_AHB4_GPIOE 4 | |
| 45 | +#define STM32H7_RCC_AHB4_GPIOF 5 | |
| 46 | +#define STM32H7_RCC_AHB4_GPIOG 6 | |
| 47 | +#define STM32H7_RCC_AHB4_GPIOH 7 | |
| 48 | +#define STM32H7_RCC_AHB4_GPIOI 8 | |
| 49 | +#define STM32H7_RCC_AHB4_GPIOJ 9 | |
| 50 | +#define STM32H7_RCC_AHB4_GPIOK 10 | |
| 51 | +#define STM32H7_RCC_AHB4_CRC 19 | |
| 52 | +#define STM32H7_RCC_AHB4_BDMA 21 | |
| 53 | +#define STM32H7_RCC_AHB4_ADC3 24 | |
| 54 | +#define STM32H7_RCC_AHB4_HSEM 25 | |
| 55 | + | |
| 56 | +#define STM32H7_AHB4_RESET(bit) (STM32H7_RCC_AHB4_##bit + (0x88 * 8)) | |
| 57 | + | |
| 58 | +/* APB3 */ | |
| 59 | +#define STM32H7_RCC_APB3_LTDC 3 | |
| 60 | +#define STM32H7_RCC_APB3_DSI 4 | |
| 61 | + | |
| 62 | +#define STM32H7_APB3_RESET(bit) (STM32H7_RCC_APB3_##bit + (0x8C * 8)) | |
| 63 | + | |
| 64 | +/* APB1L */ | |
| 65 | +#define STM32H7_RCC_APB1L_TIM2 0 | |
| 66 | +#define STM32H7_RCC_APB1L_TIM3 1 | |
| 67 | +#define STM32H7_RCC_APB1L_TIM4 2 | |
| 68 | +#define STM32H7_RCC_APB1L_TIM5 3 | |
| 69 | +#define STM32H7_RCC_APB1L_TIM6 4 | |
| 70 | +#define STM32H7_RCC_APB1L_TIM7 5 | |
| 71 | +#define STM32H7_RCC_APB1L_TIM12 6 | |
| 72 | +#define STM32H7_RCC_APB1L_TIM13 7 | |
| 73 | +#define STM32H7_RCC_APB1L_TIM14 8 | |
| 74 | +#define STM32H7_RCC_APB1L_LPTIM1 9 | |
| 75 | +#define STM32H7_RCC_APB1L_SPI2 14 | |
| 76 | +#define STM32H7_RCC_APB1L_SPI3 15 | |
| 77 | +#define STM32H7_RCC_APB1L_SPDIF_RX 16 | |
| 78 | +#define STM32H7_RCC_APB1L_USART2 17 | |
| 79 | +#define STM32H7_RCC_APB1L_USART3 18 | |
| 80 | +#define STM32H7_RCC_APB1L_UART4 19 | |
| 81 | +#define STM32H7_RCC_APB1L_UART5 20 | |
| 82 | +#define STM32H7_RCC_APB1L_I2C1 21 | |
| 83 | +#define STM32H7_RCC_APB1L_I2C2 22 | |
| 84 | +#define STM32H7_RCC_APB1L_I2C3 23 | |
| 85 | +#define STM32H7_RCC_APB1L_HDMICEC 27 | |
| 86 | +#define STM32H7_RCC_APB1L_DAC12 29 | |
| 87 | +#define STM32H7_RCC_APB1L_USART7 30 | |
| 88 | +#define STM32H7_RCC_APB1L_USART8 31 | |
| 89 | + | |
| 90 | +#define STM32H7_APB1L_RESET(bit) (STM32H7_RCC_APB1L_##bit + (0x90 * 8)) | |
| 91 | + | |
| 92 | +/* APB1H */ | |
| 93 | +#define STM32H7_RCC_APB1H_CRS 1 | |
| 94 | +#define STM32H7_RCC_APB1H_SWP 2 | |
| 95 | +#define STM32H7_RCC_APB1H_OPAMP 4 | |
| 96 | +#define STM32H7_RCC_APB1H_MDIOS 5 | |
| 97 | +#define STM32H7_RCC_APB1H_FDCAN 8 | |
| 98 | + | |
| 99 | +#define STM32H7_APB1H_RESET(bit) (STM32H7_RCC_APB1H_##bit + (0x94 * 8)) | |
| 100 | + | |
| 101 | +/* APB2 */ | |
| 102 | +#define STM32H7_RCC_APB2_TIM1 0 | |
| 103 | +#define STM32H7_RCC_APB2_TIM8 1 | |
| 104 | +#define STM32H7_RCC_APB2_USART1 4 | |
| 105 | +#define STM32H7_RCC_APB2_USART6 5 | |
| 106 | +#define STM32H7_RCC_APB2_SPI1 12 | |
| 107 | +#define STM32H7_RCC_APB2_SPI4 13 | |
| 108 | +#define STM32H7_RCC_APB2_TIM15 16 | |
| 109 | +#define STM32H7_RCC_APB2_TIM16 17 | |
| 110 | +#define STM32H7_RCC_APB2_TIM17 18 | |
| 111 | +#define STM32H7_RCC_APB2_SPI5 20 | |
| 112 | +#define STM32H7_RCC_APB2_SAI1 22 | |
| 113 | +#define STM32H7_RCC_APB2_SAI2 23 | |
| 114 | +#define STM32H7_RCC_APB2_SAI3 24 | |
| 115 | +#define STM32H7_RCC_APB2_DFSDM1 28 | |
| 116 | +#define STM32H7_RCC_APB2_HRTIM 29 | |
| 117 | + | |
| 118 | +#define STM32H7_APB2_RESET(bit) (STM32H7_RCC_APB2_##bit + (0x98 * 8)) | |
| 119 | + | |
| 120 | +/* APB4 */ | |
| 121 | +#define STM32H7_RCC_APB4_SYSCFG 1 | |
| 122 | +#define STM32H7_RCC_APB4_LPUART1 3 | |
| 123 | +#define STM32H7_RCC_APB4_SPI6 5 | |
| 124 | +#define STM32H7_RCC_APB4_I2C4 7 | |
| 125 | +#define STM32H7_RCC_APB4_LPTIM2 9 | |
| 126 | +#define STM32H7_RCC_APB4_LPTIM3 10 | |
| 127 | +#define STM32H7_RCC_APB4_LPTIM4 11 | |
| 128 | +#define STM32H7_RCC_APB4_LPTIM5 12 | |
| 129 | +#define STM32H7_RCC_APB4_COMP12 14 | |
| 130 | +#define STM32H7_RCC_APB4_VREF 15 | |
| 131 | +#define STM32H7_RCC_APB4_SAI4 21 | |
| 132 | +#define STM32H7_RCC_APB4_TMPSENS 26 | |
| 133 | + | |
| 134 | +#define STM32H7_APB4_RESET(bit) (STM32H7_RCC_APB4_##bit + (0x9C * 8)) | |
| 135 | + | |
| 136 | +#endif /* _DT_BINDINGS_MFD_STM32H7_RCC_H */ | |
| @@ -0,0 +1,69 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Priit Laes <plaes@plaes.org> | |
| 3 | + * | |
| 4 | + * This file is dual-licensed: you can use it either under the terms | |
| 5 | + * of the GPL or the X11 license, at your option. Note that this dual | |
| 6 | + * licensing only applies to this file, and not this project as a | |
| 7 | + * whole. | |
| 8 | + * | |
| 9 | + * a) This file is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU General Public License as | |
| 11 | + * published by the Free Software Foundation; either version 2 of the | |
| 12 | + * License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This file is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * Or, alternatively, | |
| 20 | + * | |
| 21 | + * b) Permission is hereby granted, free of charge, to any person | |
| 22 | + * obtaining a copy of this software and associated documentation | |
| 23 | + * files (the "Software"), to deal in the Software without | |
| 24 | + * restriction, including without limitation the rights to use, | |
| 25 | + * copy, modify, merge, publish, distribute, sublicense, and/or | |
| 26 | + * sell copies of the Software, and to permit persons to whom the | |
| 27 | + * Software is furnished to do so, subject to the following | |
| 28 | + * conditions: | |
| 29 | + * | |
| 30 | + * The above copyright notice and this permission notice shall be | |
| 31 | + * included in all copies or substantial portions of the Software. | |
| 32 | + * | |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 34 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 35 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 36 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| 37 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 38 | + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 39 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 40 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 41 | + */ | |
| 42 | + | |
| 43 | +#ifndef _DT_BINDINGS_RST_SUN4I_A10_H | |
| 44 | +#define _DT_BINDINGS_RST_SUN4I_A10_H | |
| 45 | + | |
| 46 | +#define RST_USB_PHY0 1 | |
| 47 | +#define RST_USB_PHY1 2 | |
| 48 | +#define RST_USB_PHY2 3 | |
| 49 | +#define RST_GPS 4 | |
| 50 | +#define RST_DE_BE0 5 | |
| 51 | +#define RST_DE_BE1 6 | |
| 52 | +#define RST_DE_FE0 7 | |
| 53 | +#define RST_DE_FE1 8 | |
| 54 | +#define RST_DE_MP 9 | |
| 55 | +#define RST_TVE0 10 | |
| 56 | +#define RST_TCON0 11 | |
| 57 | +#define RST_TVE1 12 | |
| 58 | +#define RST_TCON1 13 | |
| 59 | +#define RST_CSI0 14 | |
| 60 | +#define RST_CSI1 15 | |
| 61 | +#define RST_VE 16 | |
| 62 | +#define RST_ACE 17 | |
| 63 | +#define RST_LVDS 18 | |
| 64 | +#define RST_GPU 19 | |
| 65 | +#define RST_HDMI_H 20 | |
| 66 | +#define RST_HDMI_SYS 21 | |
| 67 | +#define RST_HDMI_AUDIO_DMA 22 | |
| 68 | + | |
| 69 | +#endif /* DT_BINDINGS_RST_SUN4I_A10_H */ | |
| @@ -0,0 +1,130 @@ | ||
| 1 | +/* | |
| 2 | + * Copyright (C) 2017 Icenowy Zheng <icenowy@aosc.io> | |
| 3 | + * | |
| 4 | + * This file is dual-licensed: you can use it either under the terms | |
| 5 | + * of the GPL or the X11 license, at your option. Note that this dual | |
| 6 | + * licensing only applies to this file, and not this project as a | |
| 7 | + * whole. | |
| 8 | + * | |
| 9 | + * a) This file is free software; you can redistribute it and/or | |
| 10 | + * modify it under the terms of the GNU General Public License as | |
| 11 | + * published by the Free Software Foundation; either version 2 of the | |
| 12 | + * License, or (at your option) any later version. | |
| 13 | + * | |
| 14 | + * This file is distributed in the hope that it will be useful, | |
| 15 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 16 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 17 | + * GNU General Public License for more details. | |
| 18 | + * | |
| 19 | + * Or, alternatively, | |
| 20 | + * | |
| 21 | + * b) Permission is hereby granted, free of charge, to any person | |
| 22 | + * obtaining a copy of this software and associated documentation | |
| 23 | + * files (the "Software"), to deal in the Software without | |
| 24 | + * restriction, including without limitation the rights to use, | |
| 25 | + * copy, modify, merge, publish, distribute, sublicense, and/or | |
| 26 | + * sell copies of the Software, and to permit persons to whom the | |
| 27 | + * Software is furnished to do so, subject to the following | |
| 28 | + * conditions: | |
| 29 | + * | |
| 30 | + * The above copyright notice and this permission notice shall be | |
| 31 | + * included in all copies or substantial portions of the Software. | |
| 32 | + * | |
| 33 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| 34 | + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
| 35 | + * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
| 36 | + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
| 37 | + * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
| 38 | + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
| 39 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
| 40 | + * OTHER DEALINGS IN THE SOFTWARE. | |
| 41 | + */ | |
| 42 | + | |
| 43 | +#ifndef _DT_BINDINGS_RST_SUN8I_R40_H_ | |
| 44 | +#define _DT_BINDINGS_RST_SUN8I_R40_H_ | |
| 45 | + | |
| 46 | +#define RST_USB_PHY0 0 | |
| 47 | +#define RST_USB_PHY1 1 | |
| 48 | +#define RST_USB_PHY2 2 | |
| 49 | + | |
| 50 | +#define RST_DRAM 3 | |
| 51 | +#define RST_MBUS 4 | |
| 52 | + | |
| 53 | +#define RST_BUS_MIPI_DSI 5 | |
| 54 | +#define RST_BUS_CE 6 | |
| 55 | +#define RST_BUS_DMA 7 | |
| 56 | +#define RST_BUS_MMC0 8 | |
| 57 | +#define RST_BUS_MMC1 9 | |
| 58 | +#define RST_BUS_MMC2 10 | |
| 59 | +#define RST_BUS_MMC3 11 | |
| 60 | +#define RST_BUS_NAND 12 | |
| 61 | +#define RST_BUS_DRAM 13 | |
| 62 | +#define RST_BUS_EMAC 14 | |
| 63 | +#define RST_BUS_TS 15 | |
| 64 | +#define RST_BUS_HSTIMER 16 | |
| 65 | +#define RST_BUS_SPI0 17 | |
| 66 | +#define RST_BUS_SPI1 18 | |
| 67 | +#define RST_BUS_SPI2 19 | |
| 68 | +#define RST_BUS_SPI3 20 | |
| 69 | +#define RST_BUS_SATA 21 | |
| 70 | +#define RST_BUS_OTG 22 | |
| 71 | +#define RST_BUS_EHCI0 23 | |
| 72 | +#define RST_BUS_EHCI1 24 | |
| 73 | +#define RST_BUS_EHCI2 25 | |
| 74 | +#define RST_BUS_OHCI0 26 | |
| 75 | +#define RST_BUS_OHCI1 27 | |
| 76 | +#define RST_BUS_OHCI2 28 | |
| 77 | +#define RST_BUS_VE 29 | |
| 78 | +#define RST_BUS_MP 30 | |
| 79 | +#define RST_BUS_DEINTERLACE 31 | |
| 80 | +#define RST_BUS_CSI0 32 | |
| 81 | +#define RST_BUS_CSI1 33 | |
| 82 | +#define RST_BUS_HDMI0 34 | |
| 83 | +#define RST_BUS_HDMI1 35 | |
| 84 | +#define RST_BUS_DE 36 | |
| 85 | +#define RST_BUS_TVE0 37 | |
| 86 | +#define RST_BUS_TVE1 38 | |
| 87 | +#define RST_BUS_TVE_TOP 39 | |
| 88 | +#define RST_BUS_GMAC 40 | |
| 89 | +#define RST_BUS_GPU 41 | |
| 90 | +#define RST_BUS_TVD0 42 | |
| 91 | +#define RST_BUS_TVD1 43 | |
| 92 | +#define RST_BUS_TVD2 44 | |
| 93 | +#define RST_BUS_TVD3 45 | |
| 94 | +#define RST_BUS_TVD_TOP 46 | |
| 95 | +#define RST_BUS_TCON_LCD0 47 | |
| 96 | +#define RST_BUS_TCON_LCD1 48 | |
| 97 | +#define RST_BUS_TCON_TV0 49 | |
| 98 | +#define RST_BUS_TCON_TV1 50 | |
| 99 | +#define RST_BUS_TCON_TOP 51 | |
| 100 | +#define RST_BUS_DBG 52 | |
| 101 | +#define RST_BUS_LVDS 53 | |
| 102 | +#define RST_BUS_CODEC 54 | |
| 103 | +#define RST_BUS_SPDIF 55 | |
| 104 | +#define RST_BUS_AC97 56 | |
| 105 | +#define RST_BUS_IR0 57 | |
| 106 | +#define RST_BUS_IR1 58 | |
| 107 | +#define RST_BUS_THS 59 | |
| 108 | +#define RST_BUS_KEYPAD 60 | |
| 109 | +#define RST_BUS_I2S0 61 | |
| 110 | +#define RST_BUS_I2S1 62 | |
| 111 | +#define RST_BUS_I2S2 63 | |
| 112 | +#define RST_BUS_I2C0 64 | |
| 113 | +#define RST_BUS_I2C1 65 | |
| 114 | +#define RST_BUS_I2C2 66 | |
| 115 | +#define RST_BUS_I2C3 67 | |
| 116 | +#define RST_BUS_CAN 68 | |
| 117 | +#define RST_BUS_SCR 69 | |
| 118 | +#define RST_BUS_PS20 70 | |
| 119 | +#define RST_BUS_PS21 71 | |
| 120 | +#define RST_BUS_I2C4 72 | |
| 121 | +#define RST_BUS_UART0 73 | |
| 122 | +#define RST_BUS_UART1 74 | |
| 123 | +#define RST_BUS_UART2 75 | |
| 124 | +#define RST_BUS_UART3 76 | |
| 125 | +#define RST_BUS_UART4 77 | |
| 126 | +#define RST_BUS_UART5 78 | |
| 127 | +#define RST_BUS_UART6 79 | |
| 128 | +#define RST_BUS_UART7 80 | |
| 129 | + | |
| 130 | +#endif /* _DT_BINDINGS_RST_SUN8I_R40_H_ */ | |
| @@ -343,6 +343,7 @@ struct clk_hw *clk_hw_register_gate(struct device *dev, const char *name, · 342 unmodified lines | ||
| 343 | 343 | u8 clk_gate_flags, spinlock_t *lock); |
| 344 | 344 | void clk_unregister_gate(struct clk *clk); |
| 345 | 345 | void clk_hw_unregister_gate(struct clk_hw *hw); |
| 346 | +int clk_gate_is_enabled(struct clk_hw *hw); | |
| 346 | 347 | |
| 347 | 348 | struct clk_div_table { |
| 348 | 349 | unsigned int val; |
| @@ -565,6 +566,9 @@ struct clk_fractional_divider { · 216 unmodified lines | ||
| 565 | 566 | u8 nwidth; |
| 566 | 567 | u32 nmask; |
| 567 | 568 | u8 flags; |
| 569 | + void (*approximation)(struct clk_hw *hw, | |
| 570 | + unsigned long rate, unsigned long *parent_rate, | |
| 571 | + unsigned long *m, unsigned long *n); | |
| 568 | 572 | spinlock_t *lock; |
| 569 | 573 | }; |
| 570 | 574 | |
| @@ -185,4 +185,29 @@ · 184 unmodified lines | ||
| 185 | 185 | #define AT91_PMC_PCR_EN (0x1 << 28) /* Enable */ |
| 186 | 186 | #define AT91_PMC_PCR_GCKEN (0x1 << 29) /* GCK Enable */ |
| 187 | 187 | |
| 188 | +#define AT91_PMC_AUDIO_PLL0 0x14c | |
| 189 | +#define AT91_PMC_AUDIO_PLL_PLLEN (1 << 0) | |
| 190 | +#define AT91_PMC_AUDIO_PLL_PADEN (1 << 1) | |
| 191 | +#define AT91_PMC_AUDIO_PLL_PMCEN (1 << 2) | |
| 192 | +#define AT91_PMC_AUDIO_PLL_RESETN (1 << 3) | |
| 193 | +#define AT91_PMC_AUDIO_PLL_ND_OFFSET 8 | |
| 194 | +#define AT91_PMC_AUDIO_PLL_ND_MASK (0x7f << AT91_PMC_AUDIO_PLL_ND_OFFSET) | |
| 195 | +#define AT91_PMC_AUDIO_PLL_ND(n) ((n) << AT91_PMC_AUDIO_PLL_ND_OFFSET) | |
| 196 | +#define AT91_PMC_AUDIO_PLL_QDPMC_OFFSET 16 | |
| 197 | +#define AT91_PMC_AUDIO_PLL_QDPMC_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | |
| 198 | +#define AT91_PMC_AUDIO_PLL_QDPMC(n) ((n) << AT91_PMC_AUDIO_PLL_QDPMC_OFFSET) | |
| 199 | + | |
| 200 | +#define AT91_PMC_AUDIO_PLL1 0x150 | |
| 201 | +#define AT91_PMC_AUDIO_PLL_FRACR_MASK 0x3fffff | |
| 202 | +#define AT91_PMC_AUDIO_PLL_QDPAD_OFFSET 24 | |
| 203 | +#define AT91_PMC_AUDIO_PLL_QDPAD_MASK (0x7f << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) | |
| 204 | +#define AT91_PMC_AUDIO_PLL_QDPAD(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_OFFSET) | |
| 205 | +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET AT91_PMC_AUDIO_PLL_QDPAD_OFFSET | |
| 206 | +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV_MASK (0x3 << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) | |
| 207 | +#define AT91_PMC_AUDIO_PLL_QDPAD_DIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_DIV_OFFSET) | |
| 208 | +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET 26 | |
| 209 | +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX 0x1f | |
| 210 | +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MASK (AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_MAX << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) | |
| 211 | +#define AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV(n) ((n) << AT91_PMC_AUDIO_PLL_QDPAD_EXTDIV_OFFSET) | |
| 212 | + | |
| 188 | 213 | #endif |
| @@ -32,7 +32,6 @@ struct atmel_classd { · 31 unmodified lines | ||
| 32 | 32 | struct regmap *regmap; |
| 33 | 33 | struct clk *pclk; |
| 34 | 34 | struct clk *gclk; |
| 35 | − struct clk *aclk; | |
| 36 | 35 | int irq; |
| 37 | 36 | const struct atmel_classd_pdata *pdata; |
| 38 | 37 | }; |
| @@ -330,11 +329,6 @@ static int atmel_classd_codec_dai_startup(struct snd_pcm_substream *substream, · 291 unmodified lines | ||
| 330 | 329 | { |
| 331 | 330 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
| 332 | 331 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); |
| 333 | − int ret; | |
| 334 | − | |
| 335 | − ret = clk_prepare_enable(dd->aclk); | |
| 336 | − if (ret) | |
| 337 | − return ret; | |
| 338 | 332 | |
| 339 | 333 | return clk_prepare_enable(dd->gclk); |
| 340 | 334 | } |
| @@ -357,31 +351,31 @@ static int atmel_classd_codec_dai_digital_mute(struct snd_soc_dai *codec_dai, · 16 unmodified lines | ||
| 357 | 351 | return 0; |
| 358 | 352 | } |
| 359 | 353 | |
| 360 | −#define CLASSD_ACLK_RATE_11M2896_MPY_8 (112896 * 100 * 8) | |
| 361 | −#define CLASSD_ACLK_RATE_12M288_MPY_8 (12288 * 1000 * 8) | |
| 354 | +#define CLASSD_GCLK_RATE_11M2896_MPY_8 (112896 * 100 * 8) | |
| 355 | +#define CLASSD_GCLK_RATE_12M288_MPY_8 (12288 * 1000 * 8) | |
| 362 | 356 | |
| 363 | 357 | static struct { |
| 364 | 358 | int rate; |
| 365 | 359 | int sample_rate; |
| 366 | 360 | int dsp_clk; |
| 367 | − unsigned long aclk_rate; | |
| 361 | + unsigned long gclk_rate; | |
| 368 | 362 | } const sample_rates[] = { |
| 369 | 363 | { 8000, CLASSD_INTPMR_FRAME_8K, |
| 370 | − CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | |
| 364 | + CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, | |
| 371 | 365 | { 16000, CLASSD_INTPMR_FRAME_16K, |
| 372 | − CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | |
| 366 | + CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, | |
| 373 | 367 | { 32000, CLASSD_INTPMR_FRAME_32K, |
| 374 | − CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | |
| 368 | + CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, | |
| 375 | 369 | { 48000, CLASSD_INTPMR_FRAME_48K, |
| 376 | − CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | |
| 370 | + CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, | |
| 377 | 371 | { 96000, CLASSD_INTPMR_FRAME_96K, |
| 378 | − CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_ACLK_RATE_12M288_MPY_8 }, | |
| 372 | + CLASSD_INTPMR_DSP_CLK_FREQ_12M288, CLASSD_GCLK_RATE_12M288_MPY_8 }, | |
| 379 | 373 | { 22050, CLASSD_INTPMR_FRAME_22K, |
| 380 | − CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | |
| 374 | + CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, | |
| 381 | 375 | { 44100, CLASSD_INTPMR_FRAME_44K, |
| 382 | − CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | |
| 376 | + CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, | |
| 383 | 377 | { 88200, CLASSD_INTPMR_FRAME_88K, |
| 384 | − CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_ACLK_RATE_11M2896_MPY_8 }, | |
| 378 | + CLASSD_INTPMR_DSP_CLK_FREQ_11M2896, CLASSD_GCLK_RATE_11M2896_MPY_8 }, | |
| 385 | 379 | }; |
| 386 | 380 | |
| 387 | 381 | static int |
| @@ -410,13 +404,12 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, · 22 unmodified lines | ||
| 410 | 404 | } |
| 411 | 405 | |
| 412 | 406 | dev_dbg(codec->dev, |
| 413 | − "Selected SAMPLE_RATE of %dHz, ACLK_RATE of %ldHz\n", | |
| 414 | − sample_rates[best].rate, sample_rates[best].aclk_rate); | |
| 407 | + "Selected SAMPLE_RATE of %dHz, GCLK_RATE of %ldHz\n", | |
| 408 | + sample_rates[best].rate, sample_rates[best].gclk_rate); | |
| 415 | 409 | |
| 416 | 410 | clk_disable_unprepare(dd->gclk); |
| 417 | − clk_disable_unprepare(dd->aclk); | |
| 418 | 411 | |
| 419 | − ret = clk_set_rate(dd->aclk, sample_rates[best].aclk_rate); | |
| 412 | + ret = clk_set_rate(dd->gclk, sample_rates[best].gclk_rate); | |
| 420 | 413 | if (ret) |
| 421 | 414 | return ret; |
| 422 | 415 | |
| @@ -426,10 +419,6 @@ atmel_classd_codec_dai_hw_params(struct snd_pcm_substream *substream, · 3 unmodified lines | ||
| 426 | 419 | |
| 427 | 420 | snd_soc_update_bits(codec, CLASSD_INTPMR, mask, val); |
| 428 | 421 | |
| 429 | − ret = clk_prepare_enable(dd->aclk); | |
| 430 | − if (ret) | |
| 431 | − return ret; | |
| 432 | − | |
| 433 | 422 | return clk_prepare_enable(dd->gclk); |
| 434 | 423 | } |
| 435 | 424 | |
| @@ -441,7 +430,6 @@ atmel_classd_codec_dai_shutdown(struct snd_pcm_substream *substream, · 5 unmodified lines | ||
| 441 | 430 | struct atmel_classd *dd = snd_soc_card_get_drvdata(rtd->card); |
| 442 | 431 | |
| 443 | 432 | clk_disable_unprepare(dd->gclk); |
| 444 | − clk_disable_unprepare(dd->aclk); | |
| 445 | 433 | } |
| 446 | 434 | |
| 447 | 435 | static int atmel_classd_codec_dai_prepare(struct snd_pcm_substream *substream, |
| @@ -596,13 +584,6 @@ static int atmel_classd_probe(struct platform_device *pdev) · 148 unmodified lines | ||
| 596 | 584 | return ret; |
| 597 | 585 | } |
| 598 | 586 | |
| 599 | − dd->aclk = devm_clk_get(dev, "aclk"); | |
| 600 | − if (IS_ERR(dd->aclk)) { | |
| 601 | − ret = PTR_ERR(dd->aclk); | |
| 602 | − dev_err(dev, "failed to get audio clock: %d\n", ret); | |
| 603 | − return ret; | |
| 604 | − } | |
| 605 | − | |
| 606 | 587 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 607 | 588 | io_base = devm_ioremap_resource(dev, res); |
| 608 | 589 | if (IS_ERR(io_base)) { |