The common clock framework changes for 3.11 include new clock drivers
across several different platforms and architectures, fixes to existing drivers, a MAINTAINERS file fix and improvements to the basic clock types that allow them to be of use to more platforms than before. Only a few fixes to the core framework are included with most all of the changes landing in the various clock drivers themselves. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAABAgAGBQJR0hFpAAoJEDqPOy9afJhJcr4P/iA83uEGXIncUzFsbCIsKNGl g8yoasz1mpcAng31kK54lasNpFvUYIEBLKWkJBN56h2J5gJ3OKpi7basnQGRykjh +rCg2dV4gKDBQzypdeg5kPxf0YLJ8KrwyngcRm5KA3oxKYtmLHt/M2jmDd3DXP0h dKo2bkR52eQ7E+ij6/MWgUObxWiFnH0C5Lf+L0tGHsRlRvZTV6NMymX2v0sIOCw9 hpsrL+7Hqf/+PBfWBljH0IAiI72I5dGEaJoesdTRWz8qut+duwF+OGlzMZnkclMf XU444HnvCq3bWGP5NYf9ASO4RRA2IGEoN/eDeiVX5hvkAjeUNHVNhkcUk28Xn9vI ZxCxwBXki4wGayiQm4TTgORozmp4i+NwbOuG+s3For1qQU43aA7ppwysFHGXngQa bxXT2pNECLX8WR91vkmEdqeQVm6s++R3zltHFUry1VRjTIs5y18Dt9kR6T16NKKQ ztoegeQQ8SI7HOLd+tR2v19VXH4zoV3NYAdkCKJX+VXFg+4mgJERmXoU350V3d8D wxde7WU4KLO4+1Fngror8wocP8jRRHfhx5jbBVVJ5n6BnF/Mos24g7KI1VPis3Wr XZQibxLW0kZ7/hTHykZCff8D4aNqR4fT/UCKyy2Xw1aR0zkD9ZAQq5oWhL99lsnt cCe9GBP0Lum9Zq9jjMwL =SwMB -----END PGP SIGNATURE----- Merge tag 'clk-for-linus-3.11' of git://git.linaro.org/people/mturquette/linux Pull clock framework updates from Mike Turquette: "The common clock framework changes for 3.11 include new clock drivers across several different platforms and architectures, fixes to existing drivers, a MAINTAINERS file fix and improvements to the basic clock types that allow them to be of use to more platforms than before. Only a few fixes to the core framework are included with most all of the changes landing in the various clock drivers themselves." * tag 'clk-for-linus-3.11' of git://git.linaro.org/people/mturquette/linux: (55 commits) clk: tegra: fix ifdef for tegra_periph_reset_assert inline clk: tegra: provide tegra_periph_reset_assert alternative clk: exynos4: Fix clock aliases for cpufreq related clocks clk: samsung: Add MUX_FA macro to pass flag and alias clk: add support for Rockchip gate clocks clk: vexpress: Make the clock drivers directly available for arm64 clk: vexpress: Use full node name to identify individual clocks clk: tegra: T114: add DFLL DVCO reset control clk: tegra: T114: add DFLL source clocks clk: tegra: T114: add FCPU clock shaper programming, needed by the DFLL clk: gate: add CLK_GATE_HIWORD_MASK clk: divider: add CLK_DIVIDER_HIWORD_MASK flag clk: mux: add CLK_MUX_HIWORD_MASK clk: Always notify whole subtree when reparenting MAINTAINERS: make drivers/clk entry match subdirs clk: honor CLK_GET_RATE_NOCACHE in clk_set_rate clk: use clk_get_rate() for debugfs clk: tegra: Use override bits when needed clk: tegra: override bits for Tegra30 PLLM clk: tegra: override bits for Tegra114 PLLM ...
This commit is contained in:
commit
92295f632c
47 changed files with 2259 additions and 413 deletions
24
Documentation/devicetree/bindings/clock/nspire-clock.txt
Normal file
24
Documentation/devicetree/bindings/clock/nspire-clock.txt
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
TI-NSPIRE Clocks
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Valid compatible properties include:
|
||||||
|
"lsi,nspire-cx-ahb-divider" for the AHB divider in the CX model
|
||||||
|
"lsi,nspire-classic-ahb-divider" for the AHB divider in the older model
|
||||||
|
"lsi,nspire-cx-clock" for the base clock in the CX model
|
||||||
|
"lsi,nspire-classic-clock" for the base clock in the older model
|
||||||
|
|
||||||
|
- reg: Physical base address of the controller and length of memory mapped
|
||||||
|
region.
|
||||||
|
|
||||||
|
Optional:
|
||||||
|
- clocks: For the "nspire-*-ahb-divider" compatible clocks, this is the parent
|
||||||
|
clock where it divides the rate from.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
ahb_clk {
|
||||||
|
#clock-cells = <0>;
|
||||||
|
compatible = "lsi,nspire-cx-clock";
|
||||||
|
reg = <0x900B0000 0x4>;
|
||||||
|
clocks = <&base_clk>;
|
||||||
|
};
|
74
Documentation/devicetree/bindings/clock/rockchip.txt
Normal file
74
Documentation/devicetree/bindings/clock/rockchip.txt
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
Device Tree Clock bindings for arch-rockchip
|
||||||
|
|
||||||
|
This binding uses the common clock binding[1].
|
||||||
|
|
||||||
|
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
|
||||||
|
== Gate clocks ==
|
||||||
|
|
||||||
|
The gate registers form a continuos block which makes the dt node
|
||||||
|
structure a matter of taste, as either all gates can be put into
|
||||||
|
one gate clock spanning all registers or they can be divided into
|
||||||
|
the 10 individual gates containing 16 clocks each.
|
||||||
|
The code supports both approaches.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible : "rockchip,rk2928-gate-clk"
|
||||||
|
- reg : shall be the control register address(es) for the clock.
|
||||||
|
- #clock-cells : from common clock binding; shall be set to 1
|
||||||
|
- clock-output-names : the corresponding gate names that the clock controls
|
||||||
|
- clocks : should contain the parent clock for each individual gate,
|
||||||
|
therefore the number of clocks elements should match the number of
|
||||||
|
clock-output-names
|
||||||
|
|
||||||
|
Example using multiple gate clocks:
|
||||||
|
|
||||||
|
clk_gates0: gate-clk@200000d0 {
|
||||||
|
compatible = "rockchip,rk2928-gate-clk";
|
||||||
|
reg = <0x200000d0 0x4>;
|
||||||
|
clocks = <&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>,
|
||||||
|
<&dummy>, <&dummy>;
|
||||||
|
|
||||||
|
clock-output-names =
|
||||||
|
"gate_core_periph", "gate_cpu_gpll",
|
||||||
|
"gate_ddrphy", "gate_aclk_cpu",
|
||||||
|
"gate_hclk_cpu", "gate_pclk_cpu",
|
||||||
|
"gate_atclk_cpu", "gate_i2s0",
|
||||||
|
"gate_i2s0_frac", "gate_i2s1",
|
||||||
|
"gate_i2s1_frac", "gate_i2s2",
|
||||||
|
"gate_i2s2_frac", "gate_spdif",
|
||||||
|
"gate_spdif_frac", "gate_testclk";
|
||||||
|
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
||||||
|
|
||||||
|
clk_gates1: gate-clk@200000d4 {
|
||||||
|
compatible = "rockchip,rk2928-gate-clk";
|
||||||
|
reg = <0x200000d4 0x4>;
|
||||||
|
clocks = <&xin24m>, <&xin24m>,
|
||||||
|
<&xin24m>, <&dummy>,
|
||||||
|
<&dummy>, <&xin24m>,
|
||||||
|
<&xin24m>, <&dummy>,
|
||||||
|
<&xin24m>, <&dummy>,
|
||||||
|
<&xin24m>, <&dummy>,
|
||||||
|
<&xin24m>, <&dummy>,
|
||||||
|
<&xin24m>, <&dummy>;
|
||||||
|
|
||||||
|
clock-output-names =
|
||||||
|
"gate_timer0", "gate_timer1",
|
||||||
|
"gate_timer2", "gate_jtag",
|
||||||
|
"gate_aclk_lcdc1_src", "gate_otgphy0",
|
||||||
|
"gate_otgphy1", "gate_ddr_gpll",
|
||||||
|
"gate_uart0", "gate_frac_uart0",
|
||||||
|
"gate_uart1", "gate_frac_uart1",
|
||||||
|
"gate_uart2", "gate_frac_uart2",
|
||||||
|
"gate_uart3", "gate_frac_uart3";
|
||||||
|
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -44,6 +44,11 @@ Optional child node properties:
|
||||||
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
|
- silabs,multisynth-source: source pll A(0) or B(1) of corresponding multisynth
|
||||||
divider.
|
divider.
|
||||||
- silabs,pll-master: boolean, multisynth can change pll frequency.
|
- silabs,pll-master: boolean, multisynth can change pll frequency.
|
||||||
|
- silabs,disable-state : clock output disable state, shall be
|
||||||
|
0 = clock output is driven LOW when disabled
|
||||||
|
1 = clock output is driven HIGH when disabled
|
||||||
|
2 = clock output is FLOATING (HIGH-Z) when disabled
|
||||||
|
3 = clock output is NEVER disabled
|
||||||
|
|
||||||
==Example==
|
==Example==
|
||||||
|
|
||||||
|
|
|
@ -12,22 +12,30 @@ Required properties:
|
||||||
"allwinner,sun4i-axi-clk" - for the AXI clock
|
"allwinner,sun4i-axi-clk" - for the AXI clock
|
||||||
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
|
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
|
||||||
"allwinner,sun4i-ahb-clk" - for the AHB clock
|
"allwinner,sun4i-ahb-clk" - for the AHB clock
|
||||||
"allwinner,sun4i-ahb-gates-clk" - for the AHB gates
|
"allwinner,sun4i-ahb-gates-clk" - for the AHB gates on A10
|
||||||
|
"allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
|
||||||
"allwinner,sun4i-apb0-clk" - for the APB0 clock
|
"allwinner,sun4i-apb0-clk" - for the APB0 clock
|
||||||
"allwinner,sun4i-apb0-gates-clk" - for the APB0 gates
|
"allwinner,sun4i-apb0-gates-clk" - for the APB0 gates on A10
|
||||||
|
"allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
|
||||||
"allwinner,sun4i-apb1-clk" - for the APB1 clock
|
"allwinner,sun4i-apb1-clk" - for the APB1 clock
|
||||||
"allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
|
"allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
|
||||||
"allwinner,sun4i-apb1-gates-clk" - for the APB1 gates
|
"allwinner,sun4i-apb1-gates-clk" - for the APB1 gates on A10
|
||||||
|
"allwinner,sun5i-a13-apb1-gates-clk" - for the APB1 gates on A13
|
||||||
|
|
||||||
Required properties for all clocks:
|
Required properties for all clocks:
|
||||||
- reg : shall be the control register address for the clock.
|
- reg : shall be the control register address for the clock.
|
||||||
- clocks : shall be the input parent clock(s) phandle for the clock
|
- clocks : shall be the input parent clock(s) phandle for the clock
|
||||||
- #clock-cells : from common clock binding; shall be set to 0 except for
|
- #clock-cells : from common clock binding; shall be set to 0 except for
|
||||||
"allwinner,sun4i-*-gates-clk" where it shall be set to 1
|
"allwinner,*-gates-clk" where it shall be set to 1
|
||||||
|
|
||||||
Additionally, "allwinner,sun4i-*-gates-clk" clocks require:
|
Additionally, "allwinner,*-gates-clk" clocks require:
|
||||||
- clock-output-names : the corresponding gate names that the clock controls
|
- clock-output-names : the corresponding gate names that the clock controls
|
||||||
|
|
||||||
|
Clock consumers should specify the desired clocks they use with a
|
||||||
|
"clocks" phandle cell. Consumers that are using a gated clock should
|
||||||
|
provide an additional ID in their clock property. The values of this
|
||||||
|
ID are documented in sunxi/<soc>-gates.txt.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
osc24M: osc24M@01c20050 {
|
osc24M: osc24M@01c20050 {
|
||||||
|
@ -50,102 +58,3 @@ cpu: cpu@01c20054 {
|
||||||
reg = <0x01c20054 0x4>;
|
reg = <0x01c20054 0x4>;
|
||||||
clocks = <&osc32k>, <&osc24M>, <&pll1>;
|
clocks = <&osc32k>, <&osc24M>, <&pll1>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Gate clock outputs
|
|
||||||
|
|
||||||
The "allwinner,sun4i-*-gates-clk" clocks provide several gatable outputs;
|
|
||||||
their corresponding offsets as present on sun4i are listed below. Note that
|
|
||||||
some of these gates are not present on sun5i.
|
|
||||||
|
|
||||||
* AXI gates ("allwinner,sun4i-axi-gates-clk")
|
|
||||||
|
|
||||||
DRAM 0
|
|
||||||
|
|
||||||
* AHB gates ("allwinner,sun4i-ahb-gates-clk")
|
|
||||||
|
|
||||||
USB0 0
|
|
||||||
EHCI0 1
|
|
||||||
OHCI0 2*
|
|
||||||
EHCI1 3
|
|
||||||
OHCI1 4*
|
|
||||||
SS 5
|
|
||||||
DMA 6
|
|
||||||
BIST 7
|
|
||||||
MMC0 8
|
|
||||||
MMC1 9
|
|
||||||
MMC2 10
|
|
||||||
MMC3 11
|
|
||||||
MS 12**
|
|
||||||
NAND 13
|
|
||||||
SDRAM 14
|
|
||||||
|
|
||||||
ACE 16
|
|
||||||
EMAC 17
|
|
||||||
TS 18
|
|
||||||
|
|
||||||
SPI0 20
|
|
||||||
SPI1 21
|
|
||||||
SPI2 22
|
|
||||||
SPI3 23
|
|
||||||
PATA 24
|
|
||||||
SATA 25**
|
|
||||||
GPS 26*
|
|
||||||
|
|
||||||
VE 32
|
|
||||||
TVD 33
|
|
||||||
TVE0 34
|
|
||||||
TVE1 35
|
|
||||||
LCD0 36
|
|
||||||
LCD1 37
|
|
||||||
|
|
||||||
CSI0 40
|
|
||||||
CSI1 41
|
|
||||||
|
|
||||||
HDMI 43
|
|
||||||
DE_BE0 44
|
|
||||||
DE_BE1 45
|
|
||||||
DE_FE0 46
|
|
||||||
DE_FE1 47
|
|
||||||
|
|
||||||
MP 50
|
|
||||||
|
|
||||||
MALI400 52
|
|
||||||
|
|
||||||
* APB0 gates ("allwinner,sun4i-apb0-gates-clk")
|
|
||||||
|
|
||||||
CODEC 0
|
|
||||||
SPDIF 1*
|
|
||||||
AC97 2
|
|
||||||
IIS 3
|
|
||||||
|
|
||||||
PIO 5
|
|
||||||
IR0 6
|
|
||||||
IR1 7
|
|
||||||
|
|
||||||
KEYPAD 10
|
|
||||||
|
|
||||||
* APB1 gates ("allwinner,sun4i-apb1-gates-clk")
|
|
||||||
|
|
||||||
I2C0 0
|
|
||||||
I2C1 1
|
|
||||||
I2C2 2
|
|
||||||
|
|
||||||
CAN 4
|
|
||||||
SCR 5
|
|
||||||
PS20 6
|
|
||||||
PS21 7
|
|
||||||
|
|
||||||
UART0 16
|
|
||||||
UART1 17
|
|
||||||
UART2 18
|
|
||||||
UART3 19
|
|
||||||
UART4 20
|
|
||||||
UART5 21
|
|
||||||
UART6 22
|
|
||||||
UART7 23
|
|
||||||
|
|
||||||
Notation:
|
|
||||||
[*]: The datasheet didn't mention these, but they are present on AW code
|
|
||||||
[**]: The datasheet had this marked as "NC" but they are used on AW code
|
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
Gate clock outputs
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* AXI gates ("allwinner,sun4i-axi-gates-clk")
|
||||||
|
|
||||||
|
DRAM 0
|
||||||
|
|
||||||
|
* AHB gates ("allwinner,sun4i-ahb-gates-clk")
|
||||||
|
|
||||||
|
USB0 0
|
||||||
|
EHCI0 1
|
||||||
|
OHCI0 2*
|
||||||
|
EHCI1 3
|
||||||
|
OHCI1 4*
|
||||||
|
SS 5
|
||||||
|
DMA 6
|
||||||
|
BIST 7
|
||||||
|
MMC0 8
|
||||||
|
MMC1 9
|
||||||
|
MMC2 10
|
||||||
|
MMC3 11
|
||||||
|
MS 12**
|
||||||
|
NAND 13
|
||||||
|
SDRAM 14
|
||||||
|
|
||||||
|
ACE 16
|
||||||
|
EMAC 17
|
||||||
|
TS 18
|
||||||
|
|
||||||
|
SPI0 20
|
||||||
|
SPI1 21
|
||||||
|
SPI2 22
|
||||||
|
SPI3 23
|
||||||
|
PATA 24
|
||||||
|
SATA 25**
|
||||||
|
GPS 26*
|
||||||
|
|
||||||
|
VE 32
|
||||||
|
TVD 33
|
||||||
|
TVE0 34
|
||||||
|
TVE1 35
|
||||||
|
LCD0 36
|
||||||
|
LCD1 37
|
||||||
|
|
||||||
|
CSI0 40
|
||||||
|
CSI1 41
|
||||||
|
|
||||||
|
HDMI 43
|
||||||
|
DE_BE0 44
|
||||||
|
DE_BE1 45
|
||||||
|
DE_FE1 46
|
||||||
|
DE_FE1 47
|
||||||
|
|
||||||
|
MP 50
|
||||||
|
|
||||||
|
MALI400 52
|
||||||
|
|
||||||
|
* APB0 gates ("allwinner,sun4i-apb0-gates-clk")
|
||||||
|
|
||||||
|
CODEC 0
|
||||||
|
SPDIF 1*
|
||||||
|
AC97 2
|
||||||
|
IIS 3
|
||||||
|
|
||||||
|
PIO 5
|
||||||
|
IR0 6
|
||||||
|
IR1 7
|
||||||
|
|
||||||
|
KEYPAD 10
|
||||||
|
|
||||||
|
* APB1 gates ("allwinner,sun4i-apb1-gates-clk")
|
||||||
|
|
||||||
|
I2C0 0
|
||||||
|
I2C1 1
|
||||||
|
I2C2 2
|
||||||
|
|
||||||
|
CAN 4
|
||||||
|
SCR 5
|
||||||
|
PS20 6
|
||||||
|
PS21 7
|
||||||
|
|
||||||
|
UART0 16
|
||||||
|
UART1 17
|
||||||
|
UART2 18
|
||||||
|
UART3 19
|
||||||
|
UART4 20
|
||||||
|
UART5 21
|
||||||
|
UART6 22
|
||||||
|
UART7 23
|
||||||
|
|
||||||
|
Notation:
|
||||||
|
[*]: The datasheet didn't mention these, but they are present on AW code
|
||||||
|
[**]: The datasheet had this marked as "NC" but they are used on AW code
|
|
@ -0,0 +1,58 @@
|
||||||
|
Gate clock outputs
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* AXI gates ("allwinner,sun4i-axi-gates-clk")
|
||||||
|
|
||||||
|
DRAM 0
|
||||||
|
|
||||||
|
* AHB gates ("allwinner,sun5i-a13-ahb-gates-clk")
|
||||||
|
|
||||||
|
USBOTG 0
|
||||||
|
EHCI 1
|
||||||
|
OHCI 2
|
||||||
|
|
||||||
|
SS 5
|
||||||
|
DMA 6
|
||||||
|
BIST 7
|
||||||
|
MMC0 8
|
||||||
|
MMC1 9
|
||||||
|
MMC2 10
|
||||||
|
|
||||||
|
NAND 13
|
||||||
|
SDRAM 14
|
||||||
|
|
||||||
|
SPI0 20
|
||||||
|
SPI1 21
|
||||||
|
SPI2 22
|
||||||
|
|
||||||
|
STIMER 28
|
||||||
|
|
||||||
|
VE 32
|
||||||
|
|
||||||
|
LCD 36
|
||||||
|
|
||||||
|
CSI 40
|
||||||
|
|
||||||
|
DE_BE 44
|
||||||
|
|
||||||
|
DE_FE 46
|
||||||
|
|
||||||
|
IEP 51
|
||||||
|
MALI400 52
|
||||||
|
|
||||||
|
* APB0 gates ("allwinner,sun5i-a13-apb0-gates-clk")
|
||||||
|
|
||||||
|
CODEC 0
|
||||||
|
|
||||||
|
PIO 5
|
||||||
|
IR 6
|
||||||
|
|
||||||
|
* APB1 gates ("allwinner,sun5i-a13-apb1-gates-clk")
|
||||||
|
|
||||||
|
I2C0 0
|
||||||
|
I2C1 1
|
||||||
|
I2C2 2
|
||||||
|
|
||||||
|
UART1 17
|
||||||
|
|
||||||
|
UART3 19
|
|
@ -8,6 +8,8 @@ Required properties:
|
||||||
- compatible : shall be one of the following:
|
- compatible : shall be one of the following:
|
||||||
"via,vt8500-pll-clock" - for a VT8500/WM8505 PLL clock
|
"via,vt8500-pll-clock" - for a VT8500/WM8505 PLL clock
|
||||||
"wm,wm8650-pll-clock" - for a WM8650 PLL clock
|
"wm,wm8650-pll-clock" - for a WM8650 PLL clock
|
||||||
|
"wm,wm8750-pll-clock" - for a WM8750 PLL clock
|
||||||
|
"wm,wm8850-pll-clock" - for a WM8850 PLL clock
|
||||||
"via,vt8500-device-clock" - for a VT/WM device clock
|
"via,vt8500-device-clock" - for a VT/WM device clock
|
||||||
|
|
||||||
Required properties for PLL clocks:
|
Required properties for PLL clocks:
|
||||||
|
|
|
@ -2131,9 +2131,10 @@ M: Mike Turquette <mturquette@linaro.org>
|
||||||
L: linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV)
|
L: linux-arm-kernel@lists.infradead.org (same as CLK API & CLKDEV)
|
||||||
T: git git://git.linaro.org/people/mturquette/linux.git
|
T: git git://git.linaro.org/people/mturquette/linux.git
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: drivers/clk/clk.c
|
F: drivers/clk/
|
||||||
F: drivers/clk/clk-*
|
X: drivers/clk/clkdev.c
|
||||||
F: include/linux/clk-pr*
|
F: include/linux/clk-pr*
|
||||||
|
F: include/linux/clk/
|
||||||
|
|
||||||
COMMON INTERNET FILE SYSTEM (CIFS)
|
COMMON INTERNET FILE SYSTEM (CIFS)
|
||||||
M: Steve French <sfrench@samba.org>
|
M: Steve French <sfrench@samba.org>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
#include <linux/irqchip.h>
|
#include <linux/irqchip.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk-provider.h>
|
||||||
|
|
||||||
#include <asm/hardware/cache-l2x0.h>
|
#include <asm/hardware/cache-l2x0.h>
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ u32 tegra_uart_config[4] = {
|
||||||
#ifdef CONFIG_OF
|
#ifdef CONFIG_OF
|
||||||
void __init tegra_dt_init_irq(void)
|
void __init tegra_dt_init_irq(void)
|
||||||
{
|
{
|
||||||
tegra_clocks_init();
|
of_clk_init(NULL);
|
||||||
tegra_pmc_init();
|
tegra_pmc_init();
|
||||||
tegra_init_irq();
|
tegra_init_irq();
|
||||||
irqchip_init();
|
irqchip_init();
|
||||||
|
|
|
@ -76,13 +76,15 @@ void __init ux500_init_irq(void)
|
||||||
} else if (cpu_is_u9540()) {
|
} else if (cpu_is_u9540()) {
|
||||||
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||||
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K - 1);
|
||||||
u8500_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
|
u9540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
|
||||||
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
|
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
|
||||||
U8500_CLKRST6_BASE);
|
U8500_CLKRST6_BASE);
|
||||||
} else if (cpu_is_u8540()) {
|
} else if (cpu_is_u8540()) {
|
||||||
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
prcmu_early_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
||||||
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
ux500_pm_init(U8500_PRCMU_BASE, SZ_8K + SZ_4K - 1);
|
||||||
u8540_clk_init();
|
u8540_clk_init(U8500_CLKRST1_BASE, U8500_CLKRST2_BASE,
|
||||||
|
U8500_CLKRST3_BASE, U8500_CLKRST5_BASE,
|
||||||
|
U8500_CLKRST6_BASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,6 +158,7 @@ config E500
|
||||||
config PPC_E500MC
|
config PPC_E500MC
|
||||||
bool "e500mc Support"
|
bool "e500mc Support"
|
||||||
select PPC_FPU
|
select PPC_FPU
|
||||||
|
select COMMON_CLK
|
||||||
depends on E500
|
depends on E500
|
||||||
help
|
help
|
||||||
This must be enabled for running on e500mc (and derivatives
|
This must be enabled for running on e500mc (and derivatives
|
||||||
|
|
|
@ -42,7 +42,7 @@ config COMMON_CLK_WM831X
|
||||||
|
|
||||||
config COMMON_CLK_VERSATILE
|
config COMMON_CLK_VERSATILE
|
||||||
bool "Clock driver for ARM Reference designs"
|
bool "Clock driver for ARM Reference designs"
|
||||||
depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS
|
depends on ARCH_INTEGRATOR || ARCH_REALVIEW || ARCH_VEXPRESS || ARM64
|
||||||
---help---
|
---help---
|
||||||
Supports clocking on ARM Reference designs:
|
Supports clocking on ARM Reference designs:
|
||||||
- Integrator/AP and Integrator/CP
|
- Integrator/AP and Integrator/CP
|
||||||
|
@ -58,7 +58,6 @@ config COMMON_CLK_MAX77686
|
||||||
config COMMON_CLK_SI5351
|
config COMMON_CLK_SI5351
|
||||||
tristate "Clock driver for SiLabs 5351A/B/C"
|
tristate "Clock driver for SiLabs 5351A/B/C"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
depends on OF
|
|
||||||
select REGMAP_I2C
|
select REGMAP_I2C
|
||||||
select RATIONAL
|
select RATIONAL
|
||||||
---help---
|
---help---
|
||||||
|
@ -81,6 +80,13 @@ config COMMON_CLK_AXI_CLKGEN
|
||||||
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
|
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
|
||||||
FPGAs. It is commonly used in Analog Devices' reference designs.
|
FPGAs. It is commonly used in Analog Devices' reference designs.
|
||||||
|
|
||||||
|
config CLK_PPC_CORENET
|
||||||
|
bool "Clock driver for PowerPC corenet platforms"
|
||||||
|
depends on PPC_E500MC && OF
|
||||||
|
---help---
|
||||||
|
This adds the clock driver support for Freescale PowerPC corenet
|
||||||
|
platforms using common clock framework.
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
||||||
source "drivers/clk/mvebu/Kconfig"
|
source "drivers/clk/mvebu/Kconfig"
|
||||||
|
|
|
@ -13,6 +13,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-composite.o
|
||||||
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
|
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
|
||||||
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
|
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
|
||||||
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||||
|
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
|
||||||
obj-$(CONFIG_ARCH_MXS) += mxs/
|
obj-$(CONFIG_ARCH_MXS) += mxs/
|
||||||
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
|
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
|
||||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||||
|
@ -24,6 +25,7 @@ ifeq ($(CONFIG_COMMON_CLK), y)
|
||||||
obj-$(CONFIG_ARCH_MMP) += mmp/
|
obj-$(CONFIG_ARCH_MMP) += mmp/
|
||||||
endif
|
endif
|
||||||
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
|
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
|
||||||
|
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||||
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
||||||
|
@ -39,3 +41,4 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
|
||||||
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
|
||||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||||
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
|
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
|
||||||
|
obj-$(CONFIG_CLK_PPC_CORENET) += clk-ppc-corenet.o
|
||||||
|
|
|
@ -150,6 +150,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
|
||||||
struct clk_divider *divider = to_clk_divider(hw);
|
struct clk_divider *divider = to_clk_divider(hw);
|
||||||
int i, bestdiv = 0;
|
int i, bestdiv = 0;
|
||||||
unsigned long parent_rate, best = 0, now, maxdiv;
|
unsigned long parent_rate, best = 0, now, maxdiv;
|
||||||
|
unsigned long parent_rate_saved = *best_parent_rate;
|
||||||
|
|
||||||
if (!rate)
|
if (!rate)
|
||||||
rate = 1;
|
rate = 1;
|
||||||
|
@ -173,6 +174,15 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
|
||||||
for (i = 1; i <= maxdiv; i++) {
|
for (i = 1; i <= maxdiv; i++) {
|
||||||
if (!_is_valid_div(divider, i))
|
if (!_is_valid_div(divider, i))
|
||||||
continue;
|
continue;
|
||||||
|
if (rate * i == parent_rate_saved) {
|
||||||
|
/*
|
||||||
|
* It's the most ideal case if the requested rate can be
|
||||||
|
* divided from parent clock without needing to change
|
||||||
|
* parent rate, so return the divider immediately.
|
||||||
|
*/
|
||||||
|
*best_parent_rate = parent_rate_saved;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
|
parent_rate = __clk_round_rate(__clk_get_parent(hw->clk),
|
||||||
MULT_ROUND_UP(rate, i));
|
MULT_ROUND_UP(rate, i));
|
||||||
now = parent_rate / i;
|
now = parent_rate / i;
|
||||||
|
@ -217,8 +227,12 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
if (divider->lock)
|
if (divider->lock)
|
||||||
spin_lock_irqsave(divider->lock, flags);
|
spin_lock_irqsave(divider->lock, flags);
|
||||||
|
|
||||||
|
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
|
||||||
|
val = div_mask(divider) << (divider->shift + 16);
|
||||||
|
} else {
|
||||||
val = readl(divider->reg);
|
val = readl(divider->reg);
|
||||||
val &= ~(div_mask(divider) << divider->shift);
|
val &= ~(div_mask(divider) << divider->shift);
|
||||||
|
}
|
||||||
val |= value << divider->shift;
|
val |= value << divider->shift;
|
||||||
writel(val, divider->reg);
|
writel(val, divider->reg);
|
||||||
|
|
||||||
|
@ -245,6 +259,13 @@ static struct clk *_register_divider(struct device *dev, const char *name,
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
if (clk_divider_flags & CLK_DIVIDER_HIWORD_MASK) {
|
||||||
|
if (width + shift > 16) {
|
||||||
|
pr_warn("divider value exceeds LOWORD field\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate the divider */
|
/* allocate the divider */
|
||||||
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
|
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
|
||||||
if (!div) {
|
if (!div) {
|
||||||
|
|
|
@ -53,12 +53,18 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
|
||||||
if (gate->lock)
|
if (gate->lock)
|
||||||
spin_lock_irqsave(gate->lock, flags);
|
spin_lock_irqsave(gate->lock, flags);
|
||||||
|
|
||||||
|
if (gate->flags & CLK_GATE_HIWORD_MASK) {
|
||||||
|
reg = BIT(gate->bit_idx + 16);
|
||||||
|
if (set)
|
||||||
|
reg |= BIT(gate->bit_idx);
|
||||||
|
} else {
|
||||||
reg = readl(gate->reg);
|
reg = readl(gate->reg);
|
||||||
|
|
||||||
if (set)
|
if (set)
|
||||||
reg |= BIT(gate->bit_idx);
|
reg |= BIT(gate->bit_idx);
|
||||||
else
|
else
|
||||||
reg &= ~BIT(gate->bit_idx);
|
reg &= ~BIT(gate->bit_idx);
|
||||||
|
}
|
||||||
|
|
||||||
writel(reg, gate->reg);
|
writel(reg, gate->reg);
|
||||||
|
|
||||||
|
@ -121,6 +127,13 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
if (clk_gate_flags & CLK_GATE_HIWORD_MASK) {
|
||||||
|
if (bit_idx > 16) {
|
||||||
|
pr_err("gate bit exceeds LOWORD field\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate the gate */
|
/* allocate the gate */
|
||||||
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
|
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
|
||||||
if (!gate) {
|
if (!gate) {
|
||||||
|
|
|
@ -86,8 +86,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
||||||
if (mux->lock)
|
if (mux->lock)
|
||||||
spin_lock_irqsave(mux->lock, flags);
|
spin_lock_irqsave(mux->lock, flags);
|
||||||
|
|
||||||
|
if (mux->flags & CLK_MUX_HIWORD_MASK) {
|
||||||
|
val = mux->mask << (mux->shift + 16);
|
||||||
|
} else {
|
||||||
val = readl(mux->reg);
|
val = readl(mux->reg);
|
||||||
val &= ~(mux->mask << mux->shift);
|
val &= ~(mux->mask << mux->shift);
|
||||||
|
}
|
||||||
val |= index << mux->shift;
|
val |= index << mux->shift;
|
||||||
writel(val, mux->reg);
|
writel(val, mux->reg);
|
||||||
|
|
||||||
|
@ -111,6 +115,15 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
|
||||||
struct clk_mux *mux;
|
struct clk_mux *mux;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
|
u8 width = 0;
|
||||||
|
|
||||||
|
if (clk_mux_flags & CLK_MUX_HIWORD_MASK) {
|
||||||
|
width = fls(mask) - ffs(mask) + 1;
|
||||||
|
if (width + shift > 16) {
|
||||||
|
pr_err("mux value exceeds LOWORD field\n");
|
||||||
|
return ERR_PTR(-EINVAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate the mux */
|
/* allocate the mux */
|
||||||
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
|
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
|
||||||
|
|
153
drivers/clk/clk-nspire.c
Normal file
153
drivers/clk/clk-nspire.c
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Copyright (C) 2013 Daniel Tang <tangrs@tangrs.id.au>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
#define MHZ (1000 * 1000)
|
||||||
|
|
||||||
|
#define BASE_CPU_SHIFT 1
|
||||||
|
#define BASE_CPU_MASK 0x7F
|
||||||
|
|
||||||
|
#define CPU_AHB_SHIFT 12
|
||||||
|
#define CPU_AHB_MASK 0x07
|
||||||
|
|
||||||
|
#define FIXED_BASE_SHIFT 8
|
||||||
|
#define FIXED_BASE_MASK 0x01
|
||||||
|
|
||||||
|
#define CLASSIC_BASE_SHIFT 16
|
||||||
|
#define CLASSIC_BASE_MASK 0x1F
|
||||||
|
|
||||||
|
#define CX_BASE_SHIFT 15
|
||||||
|
#define CX_BASE_MASK 0x3F
|
||||||
|
|
||||||
|
#define CX_UNKNOWN_SHIFT 21
|
||||||
|
#define CX_UNKNOWN_MASK 0x03
|
||||||
|
|
||||||
|
struct nspire_clk_info {
|
||||||
|
u32 base_clock;
|
||||||
|
u16 base_cpu_ratio;
|
||||||
|
u16 base_ahb_ratio;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#define EXTRACT(var, prop) (((var)>>prop##_SHIFT) & prop##_MASK)
|
||||||
|
static void nspire_clkinfo_cx(u32 val, struct nspire_clk_info *clk)
|
||||||
|
{
|
||||||
|
if (EXTRACT(val, FIXED_BASE))
|
||||||
|
clk->base_clock = 48 * MHZ;
|
||||||
|
else
|
||||||
|
clk->base_clock = 6 * EXTRACT(val, CX_BASE) * MHZ;
|
||||||
|
|
||||||
|
clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * EXTRACT(val, CX_UNKNOWN);
|
||||||
|
clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nspire_clkinfo_classic(u32 val, struct nspire_clk_info *clk)
|
||||||
|
{
|
||||||
|
if (EXTRACT(val, FIXED_BASE))
|
||||||
|
clk->base_clock = 27 * MHZ;
|
||||||
|
else
|
||||||
|
clk->base_clock = (300 - 6 * EXTRACT(val, CLASSIC_BASE)) * MHZ;
|
||||||
|
|
||||||
|
clk->base_cpu_ratio = EXTRACT(val, BASE_CPU) * 2;
|
||||||
|
clk->base_ahb_ratio = clk->base_cpu_ratio * (EXTRACT(val, CPU_AHB) + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init nspire_ahbdiv_setup(struct device_node *node,
|
||||||
|
void (*get_clkinfo)(u32, struct nspire_clk_info *))
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
void __iomem *io;
|
||||||
|
struct clk *clk;
|
||||||
|
const char *clk_name = node->name;
|
||||||
|
const char *parent_name;
|
||||||
|
struct nspire_clk_info info;
|
||||||
|
|
||||||
|
io = of_iomap(node, 0);
|
||||||
|
if (!io)
|
||||||
|
return;
|
||||||
|
val = readl(io);
|
||||||
|
iounmap(io);
|
||||||
|
|
||||||
|
get_clkinfo(val, &info);
|
||||||
|
|
||||||
|
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||||
|
parent_name = of_clk_get_parent_name(node, 0);
|
||||||
|
|
||||||
|
clk = clk_register_fixed_factor(NULL, clk_name, parent_name, 0,
|
||||||
|
1, info.base_ahb_ratio);
|
||||||
|
if (!IS_ERR(clk))
|
||||||
|
of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init nspire_ahbdiv_setup_cx(struct device_node *node)
|
||||||
|
{
|
||||||
|
nspire_ahbdiv_setup(node, nspire_clkinfo_cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init nspire_ahbdiv_setup_classic(struct device_node *node)
|
||||||
|
{
|
||||||
|
nspire_ahbdiv_setup(node, nspire_clkinfo_classic);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLK_OF_DECLARE(nspire_ahbdiv_cx, "lsi,nspire-cx-ahb-divider",
|
||||||
|
nspire_ahbdiv_setup_cx);
|
||||||
|
CLK_OF_DECLARE(nspire_ahbdiv_classic, "lsi,nspire-classic-ahb-divider",
|
||||||
|
nspire_ahbdiv_setup_classic);
|
||||||
|
|
||||||
|
static void __init nspire_clk_setup(struct device_node *node,
|
||||||
|
void (*get_clkinfo)(u32, struct nspire_clk_info *))
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
void __iomem *io;
|
||||||
|
struct clk *clk;
|
||||||
|
const char *clk_name = node->name;
|
||||||
|
struct nspire_clk_info info;
|
||||||
|
|
||||||
|
io = of_iomap(node, 0);
|
||||||
|
if (!io)
|
||||||
|
return;
|
||||||
|
val = readl(io);
|
||||||
|
iounmap(io);
|
||||||
|
|
||||||
|
get_clkinfo(val, &info);
|
||||||
|
|
||||||
|
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||||
|
|
||||||
|
clk = clk_register_fixed_rate(NULL, clk_name, NULL, CLK_IS_ROOT,
|
||||||
|
info.base_clock);
|
||||||
|
if (!IS_ERR(clk))
|
||||||
|
of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
pr_info("TI-NSPIRE Base: %uMHz CPU: %uMHz AHB: %uMHz\n",
|
||||||
|
info.base_clock / MHZ,
|
||||||
|
info.base_clock / info.base_cpu_ratio / MHZ,
|
||||||
|
info.base_clock / info.base_ahb_ratio / MHZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init nspire_clk_setup_cx(struct device_node *node)
|
||||||
|
{
|
||||||
|
nspire_clk_setup(node, nspire_clkinfo_cx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init nspire_clk_setup_classic(struct device_node *node)
|
||||||
|
{
|
||||||
|
nspire_clk_setup(node, nspire_clkinfo_classic);
|
||||||
|
}
|
||||||
|
|
||||||
|
CLK_OF_DECLARE(nspire_clk_cx, "lsi,nspire-cx-clock", nspire_clk_setup_cx);
|
||||||
|
CLK_OF_DECLARE(nspire_clk_classic, "lsi,nspire-classic-clock",
|
||||||
|
nspire_clk_setup_classic);
|
280
drivers/clk/clk-ppc-corenet.c
Normal file
280
drivers/clk/clk-ppc-corenet.c
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2013 Freescale Semiconductor, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* clock driver for Freescale PowerPC corenet SoCs.
|
||||||
|
*/
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
struct cmux_clk {
|
||||||
|
struct clk_hw hw;
|
||||||
|
void __iomem *reg;
|
||||||
|
u32 flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PLL_KILL BIT(31)
|
||||||
|
#define CLKSEL_SHIFT 27
|
||||||
|
#define CLKSEL_ADJUST BIT(0)
|
||||||
|
#define to_cmux_clk(p) container_of(p, struct cmux_clk, hw)
|
||||||
|
|
||||||
|
static void __iomem *base;
|
||||||
|
static unsigned int clocks_per_pll;
|
||||||
|
|
||||||
|
static int cmux_set_parent(struct clk_hw *hw, u8 idx)
|
||||||
|
{
|
||||||
|
struct cmux_clk *clk = to_cmux_clk(hw);
|
||||||
|
u32 clksel;
|
||||||
|
|
||||||
|
clksel = ((idx / clocks_per_pll) << 2) + idx % clocks_per_pll;
|
||||||
|
if (clk->flags & CLKSEL_ADJUST)
|
||||||
|
clksel += 8;
|
||||||
|
clksel = (clksel & 0xf) << CLKSEL_SHIFT;
|
||||||
|
iowrite32be(clksel, clk->reg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 cmux_get_parent(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct cmux_clk *clk = to_cmux_clk(hw);
|
||||||
|
u32 clksel;
|
||||||
|
|
||||||
|
clksel = ioread32be(clk->reg);
|
||||||
|
clksel = (clksel >> CLKSEL_SHIFT) & 0xf;
|
||||||
|
if (clk->flags & CLKSEL_ADJUST)
|
||||||
|
clksel -= 8;
|
||||||
|
clksel = (clksel >> 2) * clocks_per_pll + clksel % 4;
|
||||||
|
|
||||||
|
return clksel;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct clk_ops cmux_ops = {
|
||||||
|
.get_parent = cmux_get_parent,
|
||||||
|
.set_parent = cmux_set_parent,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init core_mux_init(struct device_node *np)
|
||||||
|
{
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk_init_data init;
|
||||||
|
struct cmux_clk *cmux_clk;
|
||||||
|
struct device_node *node;
|
||||||
|
int rc, count, i;
|
||||||
|
u32 offset;
|
||||||
|
const char *clk_name;
|
||||||
|
const char **parent_names;
|
||||||
|
|
||||||
|
rc = of_property_read_u32(np, "reg", &offset);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: could not get reg property\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the input clock source count */
|
||||||
|
count = of_property_count_strings(np, "clock-names");
|
||||||
|
if (count < 0) {
|
||||||
|
pr_err("%s: get clock count error\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
parent_names = kzalloc((sizeof(char *) * count), GFP_KERNEL);
|
||||||
|
if (!parent_names) {
|
||||||
|
pr_err("%s: could not allocate parent_names\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||||
|
|
||||||
|
cmux_clk = kzalloc(sizeof(struct cmux_clk), GFP_KERNEL);
|
||||||
|
if (!cmux_clk) {
|
||||||
|
pr_err("%s: could not allocate cmux_clk\n", __func__);
|
||||||
|
goto err_name;
|
||||||
|
}
|
||||||
|
cmux_clk->reg = base + offset;
|
||||||
|
|
||||||
|
node = of_find_compatible_node(NULL, NULL, "fsl,p4080-clockgen");
|
||||||
|
if (node && (offset >= 0x80))
|
||||||
|
cmux_clk->flags = CLKSEL_ADJUST;
|
||||||
|
|
||||||
|
rc = of_property_read_string_index(np, "clock-output-names",
|
||||||
|
0, &clk_name);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: read clock names error\n", np->name);
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
init.name = clk_name;
|
||||||
|
init.ops = &cmux_ops;
|
||||||
|
init.parent_names = parent_names;
|
||||||
|
init.num_parents = count;
|
||||||
|
init.flags = 0;
|
||||||
|
cmux_clk->hw.init = &init;
|
||||||
|
|
||||||
|
clk = clk_register(NULL, &cmux_clk->hw);
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
pr_err("%s: could not register clock\n", clk_name);
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("Could not register clock provider for node:%s\n",
|
||||||
|
np->name);
|
||||||
|
goto err_clk;
|
||||||
|
}
|
||||||
|
goto err_name;
|
||||||
|
|
||||||
|
err_clk:
|
||||||
|
kfree(cmux_clk);
|
||||||
|
err_name:
|
||||||
|
/* free *_names because they are reallocated when registered */
|
||||||
|
kfree(parent_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __init core_pll_init(struct device_node *np)
|
||||||
|
{
|
||||||
|
u32 offset, mult;
|
||||||
|
int i, rc, count;
|
||||||
|
const char *clk_name, *parent_name;
|
||||||
|
struct clk_onecell_data *onecell_data;
|
||||||
|
struct clk **subclks;
|
||||||
|
|
||||||
|
rc = of_property_read_u32(np, "reg", &offset);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: could not get reg property\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the multiple of PLL */
|
||||||
|
mult = ioread32be(base + offset);
|
||||||
|
|
||||||
|
/* check if this PLL is disabled */
|
||||||
|
if (mult & PLL_KILL) {
|
||||||
|
pr_debug("PLL:%s is disabled\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mult = (mult >> 1) & 0x3f;
|
||||||
|
|
||||||
|
parent_name = of_clk_get_parent_name(np, 0);
|
||||||
|
if (!parent_name) {
|
||||||
|
pr_err("PLL: %s must have a parent\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = of_property_count_strings(np, "clock-output-names");
|
||||||
|
if (count < 0 || count > 4) {
|
||||||
|
pr_err("%s: clock is not supported\n", np->name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* output clock number per PLL */
|
||||||
|
clocks_per_pll = count;
|
||||||
|
|
||||||
|
subclks = kzalloc(sizeof(struct clk *) * count, GFP_KERNEL);
|
||||||
|
if (!subclks) {
|
||||||
|
pr_err("%s: could not allocate subclks\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onecell_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
|
||||||
|
if (!onecell_data) {
|
||||||
|
pr_err("%s: could not allocate onecell_data\n", __func__);
|
||||||
|
goto err_clks;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
rc = of_property_read_string_index(np, "clock-output-names",
|
||||||
|
i, &clk_name);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: could not get clock names\n", np->name);
|
||||||
|
goto err_cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* when count == 4, there are 4 output clocks:
|
||||||
|
* /1, /2, /3, /4 respectively
|
||||||
|
* when count < 4, there are at least 2 output clocks:
|
||||||
|
* /1, /2, (/4, if count == 3) respectively.
|
||||||
|
*/
|
||||||
|
if (count == 4)
|
||||||
|
subclks[i] = clk_register_fixed_factor(NULL, clk_name,
|
||||||
|
parent_name, 0, mult, 1 + i);
|
||||||
|
else
|
||||||
|
|
||||||
|
subclks[i] = clk_register_fixed_factor(NULL, clk_name,
|
||||||
|
parent_name, 0, mult, 1 << i);
|
||||||
|
|
||||||
|
if (IS_ERR(subclks[i])) {
|
||||||
|
pr_err("%s: could not register clock\n", clk_name);
|
||||||
|
goto err_cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onecell_data->clks = subclks;
|
||||||
|
onecell_data->clk_num = count;
|
||||||
|
|
||||||
|
rc = of_clk_add_provider(np, of_clk_src_onecell_get, onecell_data);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("Could not register clk provider for node:%s\n",
|
||||||
|
np->name);
|
||||||
|
goto err_cell;
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
err_cell:
|
||||||
|
kfree(onecell_data);
|
||||||
|
err_clks:
|
||||||
|
kfree(subclks);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id clk_match[] __initconst = {
|
||||||
|
{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
|
||||||
|
{ .compatible = "fsl,core-pll-clock", .data = core_pll_init, },
|
||||||
|
{ .compatible = "fsl,core-mux-clock", .data = core_mux_init, },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init ppc_corenet_clk_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device_node *np;
|
||||||
|
|
||||||
|
np = pdev->dev.of_node;
|
||||||
|
base = of_iomap(np, 0);
|
||||||
|
if (!base) {
|
||||||
|
dev_err(&pdev->dev, "iomap error\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
of_clk_init(clk_match);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id ppc_clk_ids[] __initconst = {
|
||||||
|
{ .compatible = "fsl,qoriq-clockgen-1.0", },
|
||||||
|
{ .compatible = "fsl,qoriq-clockgen-2.0", },
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver ppc_corenet_clk_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "ppc_corenet_clock",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = ppc_clk_ids,
|
||||||
|
},
|
||||||
|
.probe = ppc_corenet_clk_probe,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init ppc_corenet_clk_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&ppc_corenet_clk_driver);
|
||||||
|
}
|
||||||
|
subsys_initcall(ppc_corenet_clk_init);
|
|
@ -851,6 +851,41 @@ static int _si5351_clkout_set_drive_strength(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _si5351_clkout_set_disable_state(
|
||||||
|
struct si5351_driver_data *drvdata, int num,
|
||||||
|
enum si5351_disable_state state)
|
||||||
|
{
|
||||||
|
u8 reg = (num < 4) ? SI5351_CLK3_0_DISABLE_STATE :
|
||||||
|
SI5351_CLK7_4_DISABLE_STATE;
|
||||||
|
u8 shift = (num < 4) ? (2 * num) : (2 * (num-4));
|
||||||
|
u8 mask = SI5351_CLK_DISABLE_STATE_MASK << shift;
|
||||||
|
u8 val;
|
||||||
|
|
||||||
|
if (num > 8)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case SI5351_DISABLE_LOW:
|
||||||
|
val = SI5351_CLK_DISABLE_STATE_LOW;
|
||||||
|
break;
|
||||||
|
case SI5351_DISABLE_HIGH:
|
||||||
|
val = SI5351_CLK_DISABLE_STATE_HIGH;
|
||||||
|
break;
|
||||||
|
case SI5351_DISABLE_FLOATING:
|
||||||
|
val = SI5351_CLK_DISABLE_STATE_FLOAT;
|
||||||
|
break;
|
||||||
|
case SI5351_DISABLE_NEVER:
|
||||||
|
val = SI5351_CLK_DISABLE_STATE_NEVER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
si5351_set_bits(drvdata, reg, mask, val << shift);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int si5351_clkout_prepare(struct clk_hw *hw)
|
static int si5351_clkout_prepare(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct si5351_hw_data *hwdata =
|
struct si5351_hw_data *hwdata =
|
||||||
|
@ -1225,6 +1260,33 @@ static int si5351_dt_parse(struct i2c_client *client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!of_property_read_u32(child, "silabs,disable-state",
|
||||||
|
&val)) {
|
||||||
|
switch (val) {
|
||||||
|
case 0:
|
||||||
|
pdata->clkout[num].disable_state =
|
||||||
|
SI5351_DISABLE_LOW;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
pdata->clkout[num].disable_state =
|
||||||
|
SI5351_DISABLE_HIGH;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pdata->clkout[num].disable_state =
|
||||||
|
SI5351_DISABLE_FLOATING;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
pdata->clkout[num].disable_state =
|
||||||
|
SI5351_DISABLE_NEVER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"invalid disable state %d for clkout %d\n",
|
||||||
|
val, num);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!of_property_read_u32(child, "clock-frequency", &val))
|
if (!of_property_read_u32(child, "clock-frequency", &val))
|
||||||
pdata->clkout[num].rate = val;
|
pdata->clkout[num].rate = val;
|
||||||
|
|
||||||
|
@ -1281,9 +1343,6 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
||||||
|
|
||||||
/* Disable interrupts */
|
/* Disable interrupts */
|
||||||
si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
|
si5351_reg_write(drvdata, SI5351_INTERRUPT_MASK, 0xf0);
|
||||||
/* Set disabled output drivers to drive low */
|
|
||||||
si5351_reg_write(drvdata, SI5351_CLK3_0_DISABLE_STATE, 0x00);
|
|
||||||
si5351_reg_write(drvdata, SI5351_CLK7_4_DISABLE_STATE, 0x00);
|
|
||||||
/* Ensure pll select is on XTAL for Si5351A/B */
|
/* Ensure pll select is on XTAL for Si5351A/B */
|
||||||
if (drvdata->variant != SI5351_VARIANT_C)
|
if (drvdata->variant != SI5351_VARIANT_C)
|
||||||
si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
|
si5351_set_bits(drvdata, SI5351_PLL_INPUT_SOURCE,
|
||||||
|
@ -1327,6 +1386,15 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
||||||
n, pdata->clkout[n].drive);
|
n, pdata->clkout[n].drive);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = _si5351_clkout_set_disable_state(drvdata, n,
|
||||||
|
pdata->clkout[n].disable_state);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"failed set disable state of clkout%d to %d\n",
|
||||||
|
n, pdata->clkout[n].disable_state);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register xtal input clock gate */
|
/* register xtal input clock gate */
|
||||||
|
@ -1500,7 +1568,10 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct i2c_device_id si5351_i2c_ids[] = {
|
static const struct i2c_device_id si5351_i2c_ids[] = {
|
||||||
{ "silabs,si5351", 0 },
|
{ "si5351a", 0 },
|
||||||
|
{ "si5351a-msop", 0 },
|
||||||
|
{ "si5351b", 0 },
|
||||||
|
{ "si5351c", 0 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
|
MODULE_DEVICE_TABLE(i2c, si5351_i2c_ids);
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
|
|
||||||
#define SI5351_CLK3_0_DISABLE_STATE 24
|
#define SI5351_CLK3_0_DISABLE_STATE 24
|
||||||
#define SI5351_CLK7_4_DISABLE_STATE 25
|
#define SI5351_CLK7_4_DISABLE_STATE 25
|
||||||
|
#define SI5351_CLK_DISABLE_STATE_MASK 3
|
||||||
#define SI5351_CLK_DISABLE_STATE_LOW 0
|
#define SI5351_CLK_DISABLE_STATE_LOW 0
|
||||||
#define SI5351_CLK_DISABLE_STATE_HIGH 1
|
#define SI5351_CLK_DISABLE_STATE_HIGH 1
|
||||||
#define SI5351_CLK_DISABLE_STATE_FLOAT 2
|
#define SI5351_CLK_DISABLE_STATE_FLOAT 2
|
||||||
|
|
|
@ -95,14 +95,14 @@ static int twl6040_clk_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(clkdata->clk))
|
if (IS_ERR(clkdata->clk))
|
||||||
return PTR_ERR(clkdata->clk);
|
return PTR_ERR(clkdata->clk);
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, clkdata);
|
platform_set_drvdata(pdev, clkdata);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int twl6040_clk_remove(struct platform_device *pdev)
|
static int twl6040_clk_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct twl6040_clk *clkdata = dev_get_drvdata(&pdev->dev);
|
struct twl6040_clk *clkdata = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
clk_unregister(clkdata->clk);
|
clk_unregister(clkdata->clk);
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ struct clk_device {
|
||||||
#define PLL_TYPE_VT8500 0
|
#define PLL_TYPE_VT8500 0
|
||||||
#define PLL_TYPE_WM8650 1
|
#define PLL_TYPE_WM8650 1
|
||||||
#define PLL_TYPE_WM8750 2
|
#define PLL_TYPE_WM8750 2
|
||||||
|
#define PLL_TYPE_WM8850 3
|
||||||
|
|
||||||
struct clk_pll {
|
struct clk_pll {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
@ -156,10 +157,6 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|
||||||
divisor = parent_rate / rate;
|
divisor = parent_rate / rate;
|
||||||
|
|
||||||
/* If prate / rate would be decimal, incr the divisor */
|
|
||||||
if (rate * divisor < parent_rate)
|
|
||||||
divisor++;
|
|
||||||
|
|
||||||
if (divisor == cdev->div_mask + 1)
|
if (divisor == cdev->div_mask + 1)
|
||||||
divisor = 0;
|
divisor = 0;
|
||||||
|
|
||||||
|
@ -327,6 +324,15 @@ CLK_OF_DECLARE(vt8500_device, "via,vt8500-device-clock", vtwm_device_clk_init);
|
||||||
#define WM8750_BITS_TO_VAL(f, m, d1, d2) \
|
#define WM8750_BITS_TO_VAL(f, m, d1, d2) \
|
||||||
((f << 24) | ((m - 1) << 16) | ((d1 - 1) << 8) | d2)
|
((f << 24) | ((m - 1) << 16) | ((d1 - 1) << 8) | d2)
|
||||||
|
|
||||||
|
/* Helper macros for PLL_WM8850 */
|
||||||
|
#define WM8850_PLL_MUL(x) ((((x >> 16) & 0x7F) + 1) * 2)
|
||||||
|
#define WM8850_PLL_DIV(x) ((((x >> 8) & 1) + 1) * (1 << (x & 3)))
|
||||||
|
|
||||||
|
#define WM8850_BITS_TO_FREQ(r, m, d1, d2) \
|
||||||
|
(r * ((m + 1) * 2) / ((d1+1) * (1 << d2)))
|
||||||
|
|
||||||
|
#define WM8850_BITS_TO_VAL(m, d1, d2) \
|
||||||
|
((((m / 2) - 1) << 16) | ((d1 - 1) << 8) | d2)
|
||||||
|
|
||||||
static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
|
static void vt8500_find_pll_bits(unsigned long rate, unsigned long parent_rate,
|
||||||
u32 *multiplier, u32 *prediv)
|
u32 *multiplier, u32 *prediv)
|
||||||
|
@ -466,6 +472,49 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
|
||||||
*divisor2 = best_div2;
|
*divisor2 = best_div2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wm8850_find_pll_bits(unsigned long rate, unsigned long parent_rate,
|
||||||
|
u32 *multiplier, u32 *divisor1, u32 *divisor2)
|
||||||
|
{
|
||||||
|
u32 mul, div1, div2;
|
||||||
|
u32 best_mul, best_div1, best_div2;
|
||||||
|
unsigned long tclk, rate_err, best_err;
|
||||||
|
|
||||||
|
best_err = (unsigned long)-1;
|
||||||
|
|
||||||
|
/* Find the closest match (lower or equal to requested) */
|
||||||
|
for (div1 = 1; div1 >= 0; div1--)
|
||||||
|
for (div2 = 3; div2 >= 0; div2--)
|
||||||
|
for (mul = 0; mul <= 127; mul++) {
|
||||||
|
tclk = parent_rate * ((mul + 1) * 2) /
|
||||||
|
((div1 + 1) * (1 << div2));
|
||||||
|
if (tclk > rate)
|
||||||
|
continue;
|
||||||
|
/* error will always be +ve */
|
||||||
|
rate_err = rate - tclk;
|
||||||
|
if (rate_err == 0) {
|
||||||
|
*multiplier = mul;
|
||||||
|
*divisor1 = div1;
|
||||||
|
*divisor2 = div2;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rate_err < best_err) {
|
||||||
|
best_err = rate_err;
|
||||||
|
best_mul = mul;
|
||||||
|
best_div1 = div1;
|
||||||
|
best_div2 = div2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if we got here, it wasn't an exact match */
|
||||||
|
pr_warn("%s: requested rate %lu, found rate %lu\n", __func__, rate,
|
||||||
|
rate - best_err);
|
||||||
|
|
||||||
|
*multiplier = best_mul;
|
||||||
|
*divisor1 = best_div1;
|
||||||
|
*divisor2 = best_div2;
|
||||||
|
}
|
||||||
|
|
||||||
static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
|
@ -489,6 +538,10 @@ static int vtwm_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
|
wm8750_find_pll_bits(rate, parent_rate, &filter, &mul, &div1, &div2);
|
||||||
pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
|
pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
|
||||||
break;
|
break;
|
||||||
|
case PLL_TYPE_WM8850:
|
||||||
|
wm8850_find_pll_bits(rate, parent_rate, &mul, &div1, &div2);
|
||||||
|
pll_val = WM8850_BITS_TO_VAL(mul, div1, div2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pr_err("%s: invalid pll type\n", __func__);
|
pr_err("%s: invalid pll type\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -525,6 +578,10 @@ static long vtwm_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
|
wm8750_find_pll_bits(rate, *prate, &filter, &mul, &div1, &div2);
|
||||||
round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
|
round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
|
||||||
break;
|
break;
|
||||||
|
case PLL_TYPE_WM8850:
|
||||||
|
wm8850_find_pll_bits(rate, *prate, &mul, &div1, &div2);
|
||||||
|
round_rate = WM8850_BITS_TO_FREQ(*prate, mul, div1, div2);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
round_rate = 0;
|
round_rate = 0;
|
||||||
}
|
}
|
||||||
|
@ -552,6 +609,10 @@ static unsigned long vtwm_pll_recalc_rate(struct clk_hw *hw,
|
||||||
pll_freq = parent_rate * WM8750_PLL_MUL(pll_val);
|
pll_freq = parent_rate * WM8750_PLL_MUL(pll_val);
|
||||||
pll_freq /= WM8750_PLL_DIV(pll_val);
|
pll_freq /= WM8750_PLL_DIV(pll_val);
|
||||||
break;
|
break;
|
||||||
|
case PLL_TYPE_WM8850:
|
||||||
|
pll_freq = parent_rate * WM8850_PLL_MUL(pll_val);
|
||||||
|
pll_freq /= WM8850_PLL_DIV(pll_val);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
pll_freq = 0;
|
pll_freq = 0;
|
||||||
}
|
}
|
||||||
|
@ -628,6 +689,12 @@ static void __init wm8750_pll_init(struct device_node *node)
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(wm8750_pll, "wm,wm8750-pll-clock", wm8750_pll_init);
|
CLK_OF_DECLARE(wm8750_pll, "wm,wm8750-pll-clock", wm8750_pll_init);
|
||||||
|
|
||||||
|
static void __init wm8850_pll_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
vtwm_pll_clk_init(node, PLL_TYPE_WM8850);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(wm8850_pll, "wm,wm8850-pll-clock", wm8850_pll_init);
|
||||||
|
|
||||||
void __init vtwm_clk_init(void __iomem *base)
|
void __init vtwm_clk_init(void __iomem *base)
|
||||||
{
|
{
|
||||||
if (!base)
|
if (!base)
|
||||||
|
|
|
@ -97,7 +97,7 @@ static int wm831x_fll_prepare(struct clk_hw *hw)
|
||||||
struct wm831x *wm831x = clkdata->wm831x;
|
struct wm831x *wm831x = clkdata->wm831x;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2,
|
ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1,
|
||||||
WM831X_FLL_ENA, WM831X_FLL_ENA);
|
WM831X_FLL_ENA, WM831X_FLL_ENA);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
|
dev_crit(wm831x->dev, "Failed to enable FLL: %d\n", ret);
|
||||||
|
@ -114,9 +114,9 @@ static void wm831x_fll_unprepare(struct clk_hw *hw)
|
||||||
struct wm831x *wm831x = clkdata->wm831x;
|
struct wm831x *wm831x = clkdata->wm831x;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_2, WM831X_FLL_ENA, 0);
|
ret = wm831x_set_bits(wm831x, WM831X_FLL_CONTROL_1, WM831X_FLL_ENA, 0);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
dev_crit(wm831x->dev, "Failed to disaable FLL: %d\n", ret);
|
dev_crit(wm831x->dev, "Failed to disable FLL: %d\n", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
|
static unsigned long wm831x_fll_recalc_rate(struct clk_hw *hw,
|
||||||
|
@ -299,8 +299,8 @@ static void wm831x_clkout_unprepare(struct clk_hw *hw)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *wm831x_clkout_parents[] = {
|
static const char *wm831x_clkout_parents[] = {
|
||||||
"xtal",
|
|
||||||
"fll",
|
"fll",
|
||||||
|
"xtal",
|
||||||
};
|
};
|
||||||
|
|
||||||
static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
|
static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
|
||||||
|
@ -318,9 +318,9 @@ static u8 wm831x_clkout_get_parent(struct clk_hw *hw)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret & WM831X_CLKOUT_SRC)
|
if (ret & WM831X_CLKOUT_SRC)
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
|
static int wm831x_clkout_set_parent(struct clk_hw *hw, u8 parent)
|
||||||
|
@ -384,7 +384,7 @@ static int wm831x_clk_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(clkdata->clkout))
|
if (IS_ERR(clkdata->clkout))
|
||||||
return PTR_ERR(clkdata->clkout);
|
return PTR_ERR(clkdata->clkout);
|
||||||
|
|
||||||
dev_set_drvdata(&pdev->dev, clkdata);
|
platform_set_drvdata(pdev, clkdata);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ static void clk_summary_show_one(struct seq_file *s, struct clk *c, int level)
|
||||||
seq_printf(s, "%*s%-*s %-11d %-12d %-10lu",
|
seq_printf(s, "%*s%-*s %-11d %-12d %-10lu",
|
||||||
level * 3 + 1, "",
|
level * 3 + 1, "",
|
||||||
30 - level * 3, c->name,
|
30 - level * 3, c->name,
|
||||||
c->enable_count, c->prepare_count, c->rate);
|
c->enable_count, c->prepare_count, clk_get_rate(c));
|
||||||
seq_printf(s, "\n");
|
seq_printf(s, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ static void clk_dump_one(struct seq_file *s, struct clk *c, int level)
|
||||||
seq_printf(s, "\"%s\": { ", c->name);
|
seq_printf(s, "\"%s\": { ", c->name);
|
||||||
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
|
seq_printf(s, "\"enable_count\": %d,", c->enable_count);
|
||||||
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
|
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
|
||||||
seq_printf(s, "\"rate\": %lu", c->rate);
|
seq_printf(s, "\"rate\": %lu", clk_get_rate(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
|
static void clk_dump_subtree(struct seq_file *s, struct clk *c, int level)
|
||||||
|
@ -534,7 +534,7 @@ static int clk_disable_unused(void)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
late_initcall(clk_disable_unused);
|
late_initcall_sync(clk_disable_unused);
|
||||||
|
|
||||||
/*** helper functions ***/
|
/*** helper functions ***/
|
||||||
|
|
||||||
|
@ -1216,7 +1216,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
||||||
clk_prepare_lock();
|
clk_prepare_lock();
|
||||||
|
|
||||||
/* bail early if nothing to do */
|
/* bail early if nothing to do */
|
||||||
if (rate == clk->rate)
|
if (rate == clk_get_rate(clk))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
|
if ((clk->flags & CLK_SET_RATE_GATE) && clk->prepare_count) {
|
||||||
|
@ -1377,23 +1377,33 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
struct clk *old_parent = clk->parent;
|
struct clk *old_parent = clk->parent;
|
||||||
bool migrated_enable = false;
|
|
||||||
|
|
||||||
/* migrate prepare */
|
/*
|
||||||
if (clk->prepare_count)
|
* Migrate prepare state between parents and prevent race with
|
||||||
|
* clk_enable().
|
||||||
|
*
|
||||||
|
* If the clock is not prepared, then a race with
|
||||||
|
* clk_enable/disable() is impossible since we already have the
|
||||||
|
* prepare lock (future calls to clk_enable() need to be preceded by
|
||||||
|
* a clk_prepare()).
|
||||||
|
*
|
||||||
|
* If the clock is prepared, migrate the prepared state to the new
|
||||||
|
* parent and also protect against a race with clk_enable() by
|
||||||
|
* forcing the clock and the new parent on. This ensures that all
|
||||||
|
* future calls to clk_enable() are practically NOPs with respect to
|
||||||
|
* hardware and software states.
|
||||||
|
*
|
||||||
|
* See also: Comment for clk_set_parent() below.
|
||||||
|
*/
|
||||||
|
if (clk->prepare_count) {
|
||||||
__clk_prepare(parent);
|
__clk_prepare(parent);
|
||||||
|
clk_enable(parent);
|
||||||
flags = clk_enable_lock();
|
clk_enable(clk);
|
||||||
|
|
||||||
/* migrate enable */
|
|
||||||
if (clk->enable_count) {
|
|
||||||
__clk_enable(parent);
|
|
||||||
migrated_enable = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* update the clk tree topology */
|
/* update the clk tree topology */
|
||||||
|
flags = clk_enable_lock();
|
||||||
clk_reparent(clk, parent);
|
clk_reparent(clk, parent);
|
||||||
|
|
||||||
clk_enable_unlock(flags);
|
clk_enable_unlock(flags);
|
||||||
|
|
||||||
/* change clock input source */
|
/* change clock input source */
|
||||||
|
@ -1401,43 +1411,27 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
|
||||||
ret = clk->ops->set_parent(clk->hw, p_index);
|
ret = clk->ops->set_parent(clk->hw, p_index);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
/*
|
|
||||||
* The error handling is tricky due to that we need to release
|
|
||||||
* the spinlock while issuing the .set_parent callback. This
|
|
||||||
* means the new parent might have been enabled/disabled in
|
|
||||||
* between, which must be considered when doing rollback.
|
|
||||||
*/
|
|
||||||
flags = clk_enable_lock();
|
flags = clk_enable_lock();
|
||||||
|
|
||||||
clk_reparent(clk, old_parent);
|
clk_reparent(clk, old_parent);
|
||||||
|
|
||||||
if (migrated_enable && clk->enable_count) {
|
|
||||||
__clk_disable(parent);
|
|
||||||
} else if (migrated_enable && (clk->enable_count == 0)) {
|
|
||||||
__clk_disable(old_parent);
|
|
||||||
} else if (!migrated_enable && clk->enable_count) {
|
|
||||||
__clk_disable(parent);
|
|
||||||
__clk_enable(old_parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
clk_enable_unlock(flags);
|
clk_enable_unlock(flags);
|
||||||
|
|
||||||
if (clk->prepare_count)
|
if (clk->prepare_count) {
|
||||||
|
clk_disable(clk);
|
||||||
|
clk_disable(parent);
|
||||||
__clk_unprepare(parent);
|
__clk_unprepare(parent);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up enable for old parent if migration was done */
|
/*
|
||||||
if (migrated_enable) {
|
* Finish the migration of prepare state and undo the changes done
|
||||||
flags = clk_enable_lock();
|
* for preventing a race with clk_enable().
|
||||||
__clk_disable(old_parent);
|
*/
|
||||||
clk_enable_unlock(flags);
|
if (clk->prepare_count) {
|
||||||
}
|
clk_disable(clk);
|
||||||
|
clk_disable(old_parent);
|
||||||
/* clean up prepare for old parent if migration was done */
|
|
||||||
if (clk->prepare_count)
|
|
||||||
__clk_unprepare(old_parent);
|
__clk_unprepare(old_parent);
|
||||||
|
}
|
||||||
|
|
||||||
/* update debugfs with new clk tree topology */
|
/* update debugfs with new clk tree topology */
|
||||||
clk_debug_reparent(clk, parent);
|
clk_debug_reparent(clk, parent);
|
||||||
|
@ -1449,12 +1443,17 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
|
||||||
* @clk: the mux clk whose input we are switching
|
* @clk: the mux clk whose input we are switching
|
||||||
* @parent: the new input to clk
|
* @parent: the new input to clk
|
||||||
*
|
*
|
||||||
* Re-parent clk to use parent as it's new input source. If clk has the
|
* Re-parent clk to use parent as its new input source. If clk is in
|
||||||
* CLK_SET_PARENT_GATE flag set then clk must be gated for this
|
* prepared state, the clk will get enabled for the duration of this call. If
|
||||||
* operation to succeed. After successfully changing clk's parent
|
* that's not acceptable for a specific clk (Eg: the consumer can't handle
|
||||||
* clk_set_parent will update the clk topology, sysfs topology and
|
* that, the reparenting is glitchy in hardware, etc), use the
|
||||||
* propagate rate recalculation via __clk_recalc_rates. Returns 0 on
|
* CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
|
||||||
* success, -EERROR otherwise.
|
*
|
||||||
|
* After successfully changing clk's parent clk_set_parent will update the
|
||||||
|
* clk topology, sysfs topology and propagate rate recalculation via
|
||||||
|
* __clk_recalc_rates.
|
||||||
|
*
|
||||||
|
* Returns 0 on success, -EERROR otherwise.
|
||||||
*/
|
*/
|
||||||
int clk_set_parent(struct clk *clk, struct clk *parent)
|
int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||||
{
|
{
|
||||||
|
@ -1494,7 +1493,6 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* propagate PRE_RATE_CHANGE notifications */
|
/* propagate PRE_RATE_CHANGE notifications */
|
||||||
if (clk->notifier_count)
|
|
||||||
ret = __clk_speculate_rates(clk, p_rate);
|
ret = __clk_speculate_rates(clk, p_rate);
|
||||||
|
|
||||||
/* abort if a driver objects */
|
/* abort if a driver objects */
|
||||||
|
|
5
drivers/clk/rockchip/Makefile
Normal file
5
drivers/clk/rockchip/Makefile
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#
|
||||||
|
# Rockchip Clock specific Makefile
|
||||||
|
#
|
||||||
|
|
||||||
|
obj-y += clk-rockchip.o
|
94
drivers/clk/rockchip/clk-rockchip.c
Normal file
94
drivers/clk/rockchip/clk-rockchip.c
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2013 MundoReader S.L.
|
||||||
|
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
static DEFINE_SPINLOCK(clk_lock);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gate clocks
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void __init rk2928_gate_clk_init(struct device_node *node,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
const char *clk_parent;
|
||||||
|
const char *clk_name;
|
||||||
|
void __iomem *reg;
|
||||||
|
void __iomem *reg_idx;
|
||||||
|
int flags;
|
||||||
|
int qty;
|
||||||
|
int reg_bit;
|
||||||
|
int clkflags = CLK_SET_RATE_PARENT;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
qty = of_property_count_strings(node, "clock-output-names");
|
||||||
|
if (qty < 0) {
|
||||||
|
pr_err("%s: error in clock-output-names %d\n", __func__, qty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qty == 0) {
|
||||||
|
pr_info("%s: nothing to do\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = of_iomap(node, 0);
|
||||||
|
|
||||||
|
clk_data = kzalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
|
||||||
|
if (!clk_data)
|
||||||
|
return;
|
||||||
|
|
||||||
|
clk_data->clks = kzalloc(qty * sizeof(struct clk *), GFP_KERNEL);
|
||||||
|
if (!clk_data->clks) {
|
||||||
|
kfree(clk_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flags = CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE;
|
||||||
|
|
||||||
|
for (i = 0; i < qty; i++) {
|
||||||
|
of_property_read_string_index(node, "clock-output-names",
|
||||||
|
i, &clk_name);
|
||||||
|
|
||||||
|
/* ignore empty slots */
|
||||||
|
if (!strcmp("reserved", clk_name))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
clk_parent = of_clk_get_parent_name(node, i);
|
||||||
|
|
||||||
|
/* keep all gates untouched for now */
|
||||||
|
clkflags |= CLK_IGNORE_UNUSED;
|
||||||
|
|
||||||
|
reg_idx = reg + (4 * (i / 16));
|
||||||
|
reg_bit = (i % 16);
|
||||||
|
|
||||||
|
clk_data->clks[i] = clk_register_gate(NULL, clk_name,
|
||||||
|
clk_parent, clkflags,
|
||||||
|
reg_idx, reg_bit,
|
||||||
|
flags,
|
||||||
|
&clk_lock);
|
||||||
|
WARN_ON(IS_ERR(clk_data->clks[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_data->clk_num = qty;
|
||||||
|
|
||||||
|
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(rk2928_gate, "rockchip,rk2928-gate-clk", rk2928_gate_clk_init);
|
|
@ -356,8 +356,8 @@ struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
|
||||||
|
|
||||||
/* list of mux clocks supported in all exynos4 soc's */
|
/* list of mux clocks supported in all exynos4 soc's */
|
||||||
struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
|
struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
|
||||||
MUX_F(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||||
CLK_SET_RATE_PARENT, 0),
|
CLK_SET_RATE_PARENT, 0, "mout_apll"),
|
||||||
MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
|
MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
|
||||||
MUX(none, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
|
MUX(none, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
|
||||||
MUX(none, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
|
MUX(none, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
|
||||||
|
@ -385,9 +385,9 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
|
||||||
MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
|
MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
|
||||||
MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
|
MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
|
||||||
MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
|
MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
|
||||||
MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "sclk_mpll"),
|
MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "mout_mpll"),
|
||||||
MUX_A(mout_core, "mout_core", mout_core_p4210,
|
MUX_A(mout_core, "mout_core", mout_core_p4210,
|
||||||
SRC_CPU, 16, 1, "mout_core"),
|
SRC_CPU, 16, 1, "moutcore"),
|
||||||
MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
|
MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
|
||||||
SRC_TOP0, 8, 1, "sclk_vpll"),
|
SRC_TOP0, 8, 1, "sclk_vpll"),
|
||||||
MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
|
MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
|
||||||
|
@ -424,8 +424,8 @@ struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
|
||||||
|
|
||||||
/* list of mux clocks supported in exynos4x12 soc */
|
/* list of mux clocks supported in exynos4x12 soc */
|
||||||
struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
|
struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
|
||||||
MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
|
MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
|
||||||
SRC_CPU, 24, 1),
|
SRC_CPU, 24, 1, "mout_mpll"),
|
||||||
MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
|
MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
|
||||||
MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
|
MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
|
||||||
MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12,
|
MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12,
|
||||||
|
@ -449,7 +449,8 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
|
||||||
SRC_DMC, 12, 1, "sclk_mpll"),
|
SRC_DMC, 12, 1, "sclk_mpll"),
|
||||||
MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
|
MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
|
||||||
SRC_TOP0, 8, 1, "sclk_vpll"),
|
SRC_TOP0, 8, 1, "sclk_vpll"),
|
||||||
MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
|
MUX_A(mout_core, "mout_core", mout_core_p4x12,
|
||||||
|
SRC_CPU, 16, 1, "moutcore"),
|
||||||
MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
|
MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
|
||||||
MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
|
MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
|
||||||
MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
|
MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
|
||||||
|
@ -537,7 +538,7 @@ struct samsung_div_clock exynos4_div_clks[] __initdata = {
|
||||||
DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
|
DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
|
||||||
DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
|
DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
|
||||||
DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
|
DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
|
||||||
DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "arm_clk"),
|
DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "armclk"),
|
||||||
DIV_A(sclk_apll, "sclk_apll", "mout_apll",
|
DIV_A(sclk_apll, "sclk_apll", "mout_apll",
|
||||||
DIV_CPU0, 24, 3, "sclk_apll"),
|
DIV_CPU0, 24, 3, "sclk_apll"),
|
||||||
DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
|
DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
|
||||||
|
@ -1070,9 +1071,9 @@ void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_so
|
||||||
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
|
pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
|
||||||
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
|
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
|
||||||
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
|
exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
|
||||||
_get_rate("sclk_apll"), _get_rate("sclk_mpll"),
|
_get_rate("sclk_apll"), _get_rate("mout_mpll"),
|
||||||
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
|
_get_rate("sclk_epll"), _get_rate("sclk_vpll"),
|
||||||
_get_rate("arm_clk"));
|
_get_rate("armclk"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,9 @@ struct samsung_mux_clock {
|
||||||
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
|
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
|
||||||
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
|
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
|
||||||
|
|
||||||
|
#define MUX_FA(_id, cname, pnames, o, s, w, f, mf, a) \
|
||||||
|
__MUX(_id, NULL, cname, pnames, o, s, w, f, mf, a)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @id: platform specific id of the clock.
|
* @id: platform specific id of the clock.
|
||||||
* struct samsung_div_clock: information about div clock
|
* struct samsung_div_clock: information about div clock
|
||||||
|
|
|
@ -239,7 +239,7 @@ struct mux_data {
|
||||||
u8 shift;
|
u8 shift;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __initconst struct mux_data cpu_data = {
|
static const __initconst struct mux_data cpu_mux_data = {
|
||||||
.shift = 16,
|
.shift = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -333,22 +333,34 @@ struct gates_data {
|
||||||
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
|
DECLARE_BITMAP(mask, SUNXI_GATES_MAX_SIZE);
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __initconst struct gates_data axi_gates_data = {
|
static const __initconst struct gates_data sun4i_axi_gates_data = {
|
||||||
.mask = {1},
|
.mask = {1},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __initconst struct gates_data ahb_gates_data = {
|
static const __initconst struct gates_data sun4i_ahb_gates_data = {
|
||||||
.mask = {0x7F77FFF, 0x14FB3F},
|
.mask = {0x7F77FFF, 0x14FB3F},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __initconst struct gates_data apb0_gates_data = {
|
static const __initconst struct gates_data sun5i_a13_ahb_gates_data = {
|
||||||
|
.mask = {0x107067e7, 0x185111},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const __initconst struct gates_data sun4i_apb0_gates_data = {
|
||||||
.mask = {0x4EF},
|
.mask = {0x4EF},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const __initconst struct gates_data apb1_gates_data = {
|
static const __initconst struct gates_data sun5i_a13_apb0_gates_data = {
|
||||||
|
.mask = {0x61},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const __initconst struct gates_data sun4i_apb1_gates_data = {
|
||||||
.mask = {0xFF00F7},
|
.mask = {0xFF00F7},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const __initconst struct gates_data sun5i_a13_apb1_gates_data = {
|
||||||
|
.mask = {0xa0007},
|
||||||
|
};
|
||||||
|
|
||||||
static void __init sunxi_gates_clk_setup(struct device_node *node,
|
static void __init sunxi_gates_clk_setup(struct device_node *node,
|
||||||
struct gates_data *data)
|
struct gates_data *data)
|
||||||
{
|
{
|
||||||
|
@ -421,17 +433,20 @@ static const __initconst struct of_device_id clk_div_match[] = {
|
||||||
|
|
||||||
/* Matches for mux clocks */
|
/* Matches for mux clocks */
|
||||||
static const __initconst struct of_device_id clk_mux_match[] = {
|
static const __initconst struct of_device_id clk_mux_match[] = {
|
||||||
{.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,},
|
{.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_mux_data,},
|
||||||
{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,},
|
{.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Matches for gate clocks */
|
/* Matches for gate clocks */
|
||||||
static const __initconst struct of_device_id clk_gates_match[] = {
|
static const __initconst struct of_device_id clk_gates_match[] = {
|
||||||
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &axi_gates_data,},
|
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
|
||||||
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &ahb_gates_data,},
|
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
|
||||||
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &apb0_gates_data,},
|
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_gates_data,},
|
||||||
{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &apb1_gates_data,},
|
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &sun4i_apb0_gates_data,},
|
||||||
|
{.compatible = "allwinner,sun5i-a13-apb0-gates-clk", .data = &sun5i_a13_apb0_gates_data,},
|
||||||
|
{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &sun4i_apb1_gates_data,},
|
||||||
|
{.compatible = "allwinner,sun5i-a13-apb1-gates-clk", .data = &sun5i_a13_apb1_gates_data,},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -117,10 +117,6 @@
|
||||||
#define PLLCX_MISC2_DEFAULT 0x30211200
|
#define PLLCX_MISC2_DEFAULT 0x30211200
|
||||||
#define PLLCX_MISC3_DEFAULT 0x200
|
#define PLLCX_MISC3_DEFAULT 0x200
|
||||||
|
|
||||||
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
|
|
||||||
#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
|
|
||||||
#define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27)
|
|
||||||
|
|
||||||
#define PMC_SATA_PWRGT 0x1ac
|
#define PMC_SATA_PWRGT 0x1ac
|
||||||
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
|
#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
|
||||||
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
|
#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
|
||||||
|
@ -128,39 +124,32 @@
|
||||||
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
|
#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
|
||||||
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
|
#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
|
||||||
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
|
#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
|
||||||
|
#define pll_override_readl(offset, p) readl_relaxed(p->pmc + offset)
|
||||||
|
|
||||||
#define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset)
|
#define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset)
|
||||||
#define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p)
|
#define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p)
|
||||||
#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
|
#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
|
||||||
|
#define pll_override_writel(val, offset, p) writel(val, p->pmc + offset)
|
||||||
|
|
||||||
#define mask(w) ((1 << (w)) - 1)
|
#define mask(w) ((1 << (w)) - 1)
|
||||||
#define divm_mask(p) mask(p->divm_width)
|
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
|
||||||
#define divn_mask(p) mask(p->divn_width)
|
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
|
||||||
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
|
#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \
|
||||||
mask(p->divp_width))
|
mask(p->params->div_nmp->divp_width))
|
||||||
|
|
||||||
#define divm_max(p) (divm_mask(p))
|
#define divm_max(p) (divm_mask(p))
|
||||||
#define divn_max(p) (divn_mask(p))
|
#define divn_max(p) (divn_mask(p))
|
||||||
#define divp_max(p) (1 << (divp_mask(p)))
|
#define divp_max(p) (1 << (divp_mask(p)))
|
||||||
|
|
||||||
|
static struct div_nmp default_nmp = {
|
||||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
.divn_shift = PLL_BASE_DIVN_SHIFT,
|
||||||
/* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */
|
.divn_width = PLL_BASE_DIVN_WIDTH,
|
||||||
#define PLLXC_PDIV_MAX 14
|
.divm_shift = PLL_BASE_DIVM_SHIFT,
|
||||||
|
.divm_width = PLL_BASE_DIVM_WIDTH,
|
||||||
/* non-monotonic mapping below is not a typo */
|
.divp_shift = PLL_BASE_DIVP_SHIFT,
|
||||||
static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = {
|
.divp_width = PLL_BASE_DIVP_WIDTH,
|
||||||
/* PDIV: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */
|
|
||||||
/* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define PLLCX_PDIV_MAX 7
|
|
||||||
static u8 pllcx_p[PLLCX_PDIV_MAX + 1] = {
|
|
||||||
/* PDIV: 0, 1, 2, 3, 4, 5, 6, 7 */
|
|
||||||
/* p: */ 1, 2, 3, 4, 6, 8, 12, 16
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
|
static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
@ -297,6 +286,39 @@ static void clk_pll_disable(struct clk_hw *hw)
|
||||||
spin_unlock_irqrestore(pll->lock, flags);
|
spin_unlock_irqrestore(pll->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int _p_div_to_hw(struct clk_hw *hw, u8 p_div)
|
||||||
|
{
|
||||||
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
|
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
||||||
|
|
||||||
|
if (p_tohw) {
|
||||||
|
while (p_tohw->pdiv) {
|
||||||
|
if (p_div <= p_tohw->pdiv)
|
||||||
|
return p_tohw->hw_val;
|
||||||
|
p_tohw++;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _hw_to_p_div(struct clk_hw *hw, u8 p_div_hw)
|
||||||
|
{
|
||||||
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
|
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
||||||
|
|
||||||
|
if (p_tohw) {
|
||||||
|
while (p_tohw->pdiv) {
|
||||||
|
if (p_div_hw == p_tohw->hw_val)
|
||||||
|
return p_tohw->pdiv;
|
||||||
|
p_tohw++;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1 << p_div_hw;
|
||||||
|
}
|
||||||
|
|
||||||
static int _get_table_rate(struct clk_hw *hw,
|
static int _get_table_rate(struct clk_hw *hw,
|
||||||
struct tegra_clk_pll_freq_table *cfg,
|
struct tegra_clk_pll_freq_table *cfg,
|
||||||
unsigned long rate, unsigned long parent_rate)
|
unsigned long rate, unsigned long parent_rate)
|
||||||
|
@ -326,9 +348,9 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
||||||
unsigned long rate, unsigned long parent_rate)
|
unsigned long rate, unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
|
||||||
unsigned long cfreq;
|
unsigned long cfreq;
|
||||||
u32 p_div = 0;
|
u32 p_div = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
switch (parent_rate) {
|
switch (parent_rate) {
|
||||||
case 12000000:
|
case 12000000:
|
||||||
|
@ -369,20 +391,16 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
|
||||||
|| cfg->output_rate > pll->params->vco_max) {
|
|| cfg->output_rate > pll->params->vco_max) {
|
||||||
pr_err("%s: Failed to set %s rate %lu\n",
|
pr_err("%s: Failed to set %s rate %lu\n",
|
||||||
__func__, __clk_get_name(hw->clk), rate);
|
__func__, __clk_get_name(hw->clk), rate);
|
||||||
|
WARN_ON(1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_tohw) {
|
if (pll->params->pdiv_tohw) {
|
||||||
p_div = 1 << p_div;
|
ret = _p_div_to_hw(hw, 1 << p_div);
|
||||||
while (p_tohw->pdiv) {
|
if (ret < 0)
|
||||||
if (p_div <= p_tohw->pdiv) {
|
return ret;
|
||||||
cfg->p = p_tohw->hw_val;
|
else
|
||||||
break;
|
cfg->p = ret;
|
||||||
}
|
|
||||||
p_tohw++;
|
|
||||||
}
|
|
||||||
if (!p_tohw->pdiv)
|
|
||||||
return -EINVAL;
|
|
||||||
} else
|
} else
|
||||||
cfg->p = p_div;
|
cfg->p = p_div;
|
||||||
|
|
||||||
|
@ -393,29 +411,61 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll,
|
||||||
struct tegra_clk_pll_freq_table *cfg)
|
struct tegra_clk_pll_freq_table *cfg)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
struct tegra_clk_pll_params *params = pll->params;
|
||||||
|
struct div_nmp *div_nmp = params->div_nmp;
|
||||||
|
|
||||||
|
if ((pll->flags & TEGRA_PLLM) &&
|
||||||
|
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
||||||
|
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
||||||
|
val = pll_override_readl(params->pmc_divp_reg, pll);
|
||||||
|
val &= ~(divp_mask(pll) << div_nmp->override_divp_shift);
|
||||||
|
val |= cfg->p << div_nmp->override_divp_shift;
|
||||||
|
pll_override_writel(val, params->pmc_divp_reg, pll);
|
||||||
|
|
||||||
|
val = pll_override_readl(params->pmc_divnm_reg, pll);
|
||||||
|
val &= ~(divm_mask(pll) << div_nmp->override_divm_shift) |
|
||||||
|
~(divn_mask(pll) << div_nmp->override_divn_shift);
|
||||||
|
val |= (cfg->m << div_nmp->override_divm_shift) |
|
||||||
|
(cfg->n << div_nmp->override_divn_shift);
|
||||||
|
pll_override_writel(val, params->pmc_divnm_reg, pll);
|
||||||
|
} else {
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
|
|
||||||
val &= ~((divm_mask(pll) << pll->divm_shift) |
|
val &= ~((divm_mask(pll) << div_nmp->divm_shift) |
|
||||||
(divn_mask(pll) << pll->divn_shift) |
|
(divn_mask(pll) << div_nmp->divn_shift) |
|
||||||
(divp_mask(pll) << pll->divp_shift));
|
(divp_mask(pll) << div_nmp->divp_shift));
|
||||||
val |= ((cfg->m << pll->divm_shift) |
|
|
||||||
(cfg->n << pll->divn_shift) |
|
val |= ((cfg->m << div_nmp->divm_shift) |
|
||||||
(cfg->p << pll->divp_shift));
|
(cfg->n << div_nmp->divn_shift) |
|
||||||
|
(cfg->p << div_nmp->divp_shift));
|
||||||
|
|
||||||
pll_writel_base(val, pll);
|
pll_writel_base(val, pll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _get_pll_mnp(struct tegra_clk_pll *pll,
|
static void _get_pll_mnp(struct tegra_clk_pll *pll,
|
||||||
struct tegra_clk_pll_freq_table *cfg)
|
struct tegra_clk_pll_freq_table *cfg)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
|
struct tegra_clk_pll_params *params = pll->params;
|
||||||
|
struct div_nmp *div_nmp = params->div_nmp;
|
||||||
|
|
||||||
|
if ((pll->flags & TEGRA_PLLM) &&
|
||||||
|
(pll_override_readl(PMC_PLLP_WB0_OVERRIDE, pll) &
|
||||||
|
PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)) {
|
||||||
|
val = pll_override_readl(params->pmc_divp_reg, pll);
|
||||||
|
cfg->p = (val >> div_nmp->override_divp_shift) & divp_mask(pll);
|
||||||
|
|
||||||
|
val = pll_override_readl(params->pmc_divnm_reg, pll);
|
||||||
|
cfg->m = (val >> div_nmp->override_divm_shift) & divm_mask(pll);
|
||||||
|
cfg->n = (val >> div_nmp->override_divn_shift) & divn_mask(pll);
|
||||||
|
} else {
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
|
|
||||||
cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
|
cfg->m = (val >> div_nmp->divm_shift) & divm_mask(pll);
|
||||||
cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
|
cfg->n = (val >> div_nmp->divn_shift) & divn_mask(pll);
|
||||||
cfg->p = (val >> pll->divp_shift) & (divp_mask(pll));
|
cfg->p = (val >> div_nmp->divp_shift) & divp_mask(pll);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _update_pll_cpcon(struct tegra_clk_pll *pll,
|
static void _update_pll_cpcon(struct tegra_clk_pll *pll,
|
||||||
|
@ -485,9 +535,10 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
|
if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
|
||||||
_calc_rate(hw, &cfg, rate, parent_rate))
|
_calc_rate(hw, &cfg, rate, parent_rate)) {
|
||||||
|
WARN_ON(1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
spin_lock_irqsave(pll->lock, flags);
|
spin_lock_irqsave(pll->lock, flags);
|
||||||
|
|
||||||
|
@ -507,7 +558,6 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
struct tegra_clk_pll_freq_table cfg;
|
struct tegra_clk_pll_freq_table cfg;
|
||||||
u64 output_rate = *prate;
|
|
||||||
|
|
||||||
if (pll->flags & TEGRA_PLL_FIXED)
|
if (pll->flags & TEGRA_PLL_FIXED)
|
||||||
return pll->fixed_rate;
|
return pll->fixed_rate;
|
||||||
|
@ -517,13 +567,12 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
return __clk_get_rate(hw->clk);
|
return __clk_get_rate(hw->clk);
|
||||||
|
|
||||||
if (_get_table_rate(hw, &cfg, rate, *prate) &&
|
if (_get_table_rate(hw, &cfg, rate, *prate) &&
|
||||||
_calc_rate(hw, &cfg, rate, *prate))
|
_calc_rate(hw, &cfg, rate, *prate)) {
|
||||||
|
WARN_ON(1);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
output_rate *= cfg.n;
|
return cfg.output_rate;
|
||||||
do_div(output_rate, cfg.m * (1 << cfg.p));
|
|
||||||
|
|
||||||
return output_rate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
||||||
|
@ -531,7 +580,6 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
struct tegra_clk_pll_freq_table cfg;
|
struct tegra_clk_pll_freq_table cfg;
|
||||||
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
|
||||||
u32 val;
|
u32 val;
|
||||||
u64 rate = parent_rate;
|
u64 rate = parent_rate;
|
||||||
int pdiv;
|
int pdiv;
|
||||||
|
@ -553,21 +601,11 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
||||||
|
|
||||||
_get_pll_mnp(pll, &cfg);
|
_get_pll_mnp(pll, &cfg);
|
||||||
|
|
||||||
if (p_tohw) {
|
pdiv = _hw_to_p_div(hw, cfg.p);
|
||||||
while (p_tohw->pdiv) {
|
if (pdiv < 0) {
|
||||||
if (cfg.p == p_tohw->hw_val) {
|
|
||||||
pdiv = p_tohw->pdiv;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
p_tohw++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_tohw->pdiv) {
|
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
pdiv = 1;
|
pdiv = 1;
|
||||||
}
|
}
|
||||||
} else
|
|
||||||
pdiv = 1 << cfg.p;
|
|
||||||
|
|
||||||
cfg.m *= pdiv;
|
cfg.m *= pdiv;
|
||||||
|
|
||||||
|
@ -647,9 +685,9 @@ static int clk_plle_enable(struct clk_hw *hw)
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
||||||
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
||||||
val |= sel.m << pll->divm_shift;
|
val |= sel.m << pll->params->div_nmp->divm_shift;
|
||||||
val |= sel.n << pll->divn_shift;
|
val |= sel.n << pll->params->div_nmp->divn_shift;
|
||||||
val |= sel.p << pll->divp_shift;
|
val |= sel.p << pll->params->div_nmp->divp_shift;
|
||||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||||
pll_writel_base(val, pll);
|
pll_writel_base(val, pll);
|
||||||
}
|
}
|
||||||
|
@ -680,9 +718,9 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
|
||||||
u32 divn = 0, divm = 0, divp = 0;
|
u32 divn = 0, divm = 0, divp = 0;
|
||||||
u64 rate = parent_rate;
|
u64 rate = parent_rate;
|
||||||
|
|
||||||
divp = (val >> pll->divp_shift) & (divp_mask(pll));
|
divp = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
|
||||||
divn = (val >> pll->divn_shift) & (divn_mask(pll));
|
divn = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
|
||||||
divm = (val >> pll->divm_shift) & (divm_mask(pll));
|
divm = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
|
||||||
divm *= divp;
|
divm *= divp;
|
||||||
|
|
||||||
rate *= divn;
|
rate *= divn;
|
||||||
|
@ -769,16 +807,22 @@ static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
unsigned int p;
|
unsigned int p;
|
||||||
|
int p_div;
|
||||||
|
|
||||||
if (!rate)
|
if (!rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
p = DIV_ROUND_UP(pll->params->vco_min, rate);
|
p = DIV_ROUND_UP(pll->params->vco_min, rate);
|
||||||
cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
|
cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
|
||||||
cfg->p = p;
|
cfg->output_rate = rate * p;
|
||||||
cfg->output_rate = rate * cfg->p;
|
|
||||||
cfg->n = cfg->output_rate * cfg->m / parent_rate;
|
cfg->n = cfg->output_rate * cfg->m / parent_rate;
|
||||||
|
|
||||||
|
p_div = _p_div_to_hw(hw, p);
|
||||||
|
if (p_div < 0)
|
||||||
|
return p_div;
|
||||||
|
else
|
||||||
|
cfg->p = p_div;
|
||||||
|
|
||||||
if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
|
if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
@ -790,18 +834,25 @@ static int _pll_ramp_calc_pll(struct clk_hw *hw,
|
||||||
unsigned long rate, unsigned long parent_rate)
|
unsigned long rate, unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
int err = 0;
|
int err = 0, p_div;
|
||||||
|
|
||||||
err = _get_table_rate(hw, cfg, rate, parent_rate);
|
err = _get_table_rate(hw, cfg, rate, parent_rate);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
|
err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
|
||||||
else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
|
else {
|
||||||
|
if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
p_div = _p_div_to_hw(hw, cfg->p);
|
||||||
|
if (p_div < 0)
|
||||||
|
return p_div;
|
||||||
|
else
|
||||||
|
cfg->p = p_div;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cfg->p || (cfg->p > pll->params->max_p))
|
if (cfg->p > pll->params->max_p)
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
@ -815,7 +866,6 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
struct tegra_clk_pll_freq_table cfg, old_cfg;
|
struct tegra_clk_pll_freq_table cfg, old_cfg;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u8 old_p;
|
|
||||||
|
|
||||||
ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
|
ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
|
@ -826,11 +876,8 @@ static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|
||||||
_get_pll_mnp(pll, &old_cfg);
|
_get_pll_mnp(pll, &old_cfg);
|
||||||
|
|
||||||
old_p = pllxc_p[old_cfg.p];
|
if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
|
||||||
if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_p != cfg.p) {
|
|
||||||
cfg.p -= 1;
|
|
||||||
ret = _program_pll(hw, &cfg, rate);
|
ret = _program_pll(hw, &cfg, rate);
|
||||||
}
|
|
||||||
|
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
spin_unlock_irqrestore(pll->lock, flags);
|
spin_unlock_irqrestore(pll->lock, flags);
|
||||||
|
@ -842,15 +889,19 @@ static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long *prate)
|
unsigned long *prate)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll_freq_table cfg;
|
struct tegra_clk_pll_freq_table cfg;
|
||||||
int ret = 0;
|
int ret = 0, p_div;
|
||||||
u64 output_rate = *prate;
|
u64 output_rate = *prate;
|
||||||
|
|
||||||
ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
|
ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
p_div = _hw_to_p_div(hw, cfg.p);
|
||||||
|
if (p_div < 0)
|
||||||
|
return p_div;
|
||||||
|
|
||||||
output_rate *= cfg.n;
|
output_rate *= cfg.n;
|
||||||
do_div(output_rate, cfg.m * cfg.p);
|
do_div(output_rate, cfg.m * p_div);
|
||||||
|
|
||||||
return output_rate;
|
return output_rate;
|
||||||
}
|
}
|
||||||
|
@ -862,7 +913,6 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
int state, ret = 0;
|
int state, ret = 0;
|
||||||
u32 val;
|
|
||||||
|
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
spin_lock_irqsave(pll->lock, flags);
|
spin_lock_irqsave(pll->lock, flags);
|
||||||
|
@ -881,23 +931,8 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
cfg.p -= 1;
|
|
||||||
|
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
|
|
||||||
if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) {
|
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
|
|
||||||
val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) :
|
|
||||||
(val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK);
|
|
||||||
writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
|
|
||||||
|
|
||||||
val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
|
|
||||||
val &= ~(divn_mask(pll) | divm_mask(pll));
|
|
||||||
val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift);
|
|
||||||
writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
|
|
||||||
} else
|
|
||||||
_update_pll_mnp(pll, &cfg);
|
_update_pll_mnp(pll, &cfg);
|
||||||
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
spin_unlock_irqrestore(pll->lock, flags);
|
spin_unlock_irqrestore(pll->lock, flags);
|
||||||
|
@ -1010,13 +1045,10 @@ static int _pllcx_update_dynamic_coef(struct tegra_clk_pll *pll,
|
||||||
static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct tegra_clk_pll_freq_table cfg;
|
struct tegra_clk_pll_freq_table cfg, old_cfg;
|
||||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
int state, ret = 0;
|
int state, ret = 0;
|
||||||
u32 val;
|
|
||||||
u16 old_m, old_n;
|
|
||||||
u8 old_p;
|
|
||||||
|
|
||||||
if (pll->lock)
|
if (pll->lock)
|
||||||
spin_lock_irqsave(pll->lock, flags);
|
spin_lock_irqsave(pll->lock, flags);
|
||||||
|
@ -1025,21 +1057,16 @@ static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
val = pll_readl_base(pll);
|
_get_pll_mnp(pll, &old_cfg);
|
||||||
old_m = (val >> pll->divm_shift) & (divm_mask(pll));
|
|
||||||
old_n = (val >> pll->divn_shift) & (divn_mask(pll));
|
|
||||||
old_p = pllcx_p[(val >> pll->divp_shift) & (divp_mask(pll))];
|
|
||||||
|
|
||||||
if (cfg.m != old_m) {
|
if (cfg.m != old_cfg.m) {
|
||||||
WARN_ON(1);
|
WARN_ON(1);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (old_n == cfg.n && old_p == cfg.p)
|
if (old_cfg.n == cfg.n && old_cfg.p == cfg.p)
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
cfg.p -= 1;
|
|
||||||
|
|
||||||
state = clk_pll_is_enabled(hw);
|
state = clk_pll_is_enabled(hw);
|
||||||
if (state)
|
if (state)
|
||||||
_clk_pllc_disable(hw);
|
_clk_pllc_disable(hw);
|
||||||
|
@ -1178,8 +1205,8 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
|
||||||
val = pll_readl_base(pll);
|
val = pll_readl_base(pll);
|
||||||
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
||||||
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
||||||
val |= sel.m << pll->divm_shift;
|
val |= sel.m << pll->params->div_nmp->divm_shift;
|
||||||
val |= sel.n << pll->divn_shift;
|
val |= sel.n << pll->params->div_nmp->divn_shift;
|
||||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||||
pll_writel_base(val, pll);
|
pll_writel_base(val, pll);
|
||||||
udelay(1);
|
udelay(1);
|
||||||
|
@ -1240,12 +1267,8 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
||||||
pll->flags = pll_flags;
|
pll->flags = pll_flags;
|
||||||
pll->lock = lock;
|
pll->lock = lock;
|
||||||
|
|
||||||
pll->divp_shift = PLL_BASE_DIVP_SHIFT;
|
if (!pll_params->div_nmp)
|
||||||
pll->divp_width = PLL_BASE_DIVP_WIDTH;
|
pll_params->div_nmp = &default_nmp;
|
||||||
pll->divn_shift = PLL_BASE_DIVN_SHIFT;
|
|
||||||
pll->divn_width = PLL_BASE_DIVN_WIDTH;
|
|
||||||
pll->divm_shift = PLL_BASE_DIVM_SHIFT;
|
|
||||||
pll->divm_width = PLL_BASE_DIVM_WIDTH;
|
|
||||||
|
|
||||||
return pll;
|
return pll;
|
||||||
}
|
}
|
||||||
|
@ -1401,7 +1424,7 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
||||||
struct tegra_clk_pll *pll;
|
struct tegra_clk_pll *pll;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE | TEGRA_PLL_LOCK_MISC;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||||
freq_table, lock);
|
freq_table, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
|
@ -1428,7 +1451,6 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
||||||
val &= ~BIT(29);
|
val &= ~BIT(29);
|
||||||
pll_writel_misc(val, pll);
|
pll_writel_misc(val, pll);
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_LOCK_MISC;
|
|
||||||
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
|
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
|
||||||
&tegra_clk_pllre_ops);
|
&tegra_clk_pllre_ops);
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
|
@ -1453,6 +1475,7 @@ struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
|
||||||
|
|
||||||
pll_flags |= TEGRA_PLL_BYPASS;
|
pll_flags |= TEGRA_PLL_BYPASS;
|
||||||
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
|
||||||
|
pll_flags |= TEGRA_PLLM;
|
||||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||||
freq_table, lock);
|
freq_table, lock);
|
||||||
if (IS_ERR(pll))
|
if (IS_ERR(pll))
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/delay.h>
|
#include <linux/delay.h>
|
||||||
|
#include <linux/export.h>
|
||||||
#include <linux/clk/tegra.h>
|
#include <linux/clk/tegra.h>
|
||||||
|
|
||||||
#include "clk.h"
|
#include "clk.h"
|
||||||
|
@ -28,6 +29,7 @@
|
||||||
#define RST_DEVICES_L 0x004
|
#define RST_DEVICES_L 0x004
|
||||||
#define RST_DEVICES_H 0x008
|
#define RST_DEVICES_H 0x008
|
||||||
#define RST_DEVICES_U 0x00C
|
#define RST_DEVICES_U 0x00C
|
||||||
|
#define RST_DFLL_DVCO 0x2F4
|
||||||
#define RST_DEVICES_V 0x358
|
#define RST_DEVICES_V 0x358
|
||||||
#define RST_DEVICES_W 0x35C
|
#define RST_DEVICES_W 0x35C
|
||||||
#define RST_DEVICES_X 0x28C
|
#define RST_DEVICES_X 0x28C
|
||||||
|
@ -41,8 +43,36 @@
|
||||||
#define RST_DEVICES_CLR_V 0x434
|
#define RST_DEVICES_CLR_V 0x434
|
||||||
#define RST_DEVICES_SET_W 0x438
|
#define RST_DEVICES_SET_W 0x438
|
||||||
#define RST_DEVICES_CLR_W 0x43c
|
#define RST_DEVICES_CLR_W 0x43c
|
||||||
|
#define CPU_FINETRIM_SELECT 0x4d4 /* override default prop dlys */
|
||||||
|
#define CPU_FINETRIM_DR 0x4d8 /* rise->rise prop dly A */
|
||||||
|
#define CPU_FINETRIM_R 0x4e4 /* rise->rise prop dly inc A */
|
||||||
#define RST_DEVICES_NUM 5
|
#define RST_DEVICES_NUM 5
|
||||||
|
|
||||||
|
/* RST_DFLL_DVCO bitfields */
|
||||||
|
#define DVFS_DFLL_RESET_SHIFT 0
|
||||||
|
|
||||||
|
/* CPU_FINETRIM_SELECT and CPU_FINETRIM_DR bitfields */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_1 BIT(0) /* fcpu0 */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_2 BIT(1) /* fcpu1 */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_3 BIT(2) /* fcpu2 */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_4 BIT(3) /* fcpu3 */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_5 BIT(4) /* fl2 */
|
||||||
|
#define CPU_FINETRIM_1_FCPU_6 BIT(5) /* ftop */
|
||||||
|
|
||||||
|
/* CPU_FINETRIM_R bitfields */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_1_SHIFT 0 /* fcpu0 */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_1_MASK (0x3 << CPU_FINETRIM_R_FCPU_1_SHIFT)
|
||||||
|
#define CPU_FINETRIM_R_FCPU_2_SHIFT 2 /* fcpu1 */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_2_MASK (0x3 << CPU_FINETRIM_R_FCPU_2_SHIFT)
|
||||||
|
#define CPU_FINETRIM_R_FCPU_3_SHIFT 4 /* fcpu2 */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_3_MASK (0x3 << CPU_FINETRIM_R_FCPU_3_SHIFT)
|
||||||
|
#define CPU_FINETRIM_R_FCPU_4_SHIFT 6 /* fcpu3 */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_4_MASK (0x3 << CPU_FINETRIM_R_FCPU_4_SHIFT)
|
||||||
|
#define CPU_FINETRIM_R_FCPU_5_SHIFT 8 /* fl2 */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_5_MASK (0x3 << CPU_FINETRIM_R_FCPU_5_SHIFT)
|
||||||
|
#define CPU_FINETRIM_R_FCPU_6_SHIFT 10 /* ftop */
|
||||||
|
#define CPU_FINETRIM_R_FCPU_6_MASK (0x3 << CPU_FINETRIM_R_FCPU_6_SHIFT)
|
||||||
|
|
||||||
#define CLK_OUT_ENB_L 0x010
|
#define CLK_OUT_ENB_L 0x010
|
||||||
#define CLK_OUT_ENB_H 0x014
|
#define CLK_OUT_ENB_H 0x014
|
||||||
#define CLK_OUT_ENB_U 0x018
|
#define CLK_OUT_ENB_U 0x018
|
||||||
|
@ -127,6 +157,7 @@
|
||||||
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
|
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
|
||||||
#define PMC_CTRL 0
|
#define PMC_CTRL 0
|
||||||
#define PMC_CTRL_BLINK_ENB 7
|
#define PMC_CTRL_BLINK_ENB 7
|
||||||
|
#define PMC_BLINK_TIMER 0x40
|
||||||
|
|
||||||
#define OSC_CTRL 0x50
|
#define OSC_CTRL 0x50
|
||||||
#define OSC_CTRL_OSC_FREQ_SHIFT 28
|
#define OSC_CTRL_OSC_FREQ_SHIFT 28
|
||||||
|
@ -242,6 +273,8 @@
|
||||||
#define CLK_SOURCE_I2CSLOW 0x3fc
|
#define CLK_SOURCE_I2CSLOW 0x3fc
|
||||||
#define CLK_SOURCE_SE 0x42c
|
#define CLK_SOURCE_SE 0x42c
|
||||||
#define CLK_SOURCE_MSELECT 0x3b4
|
#define CLK_SOURCE_MSELECT 0x3b4
|
||||||
|
#define CLK_SOURCE_DFLL_REF 0x62c
|
||||||
|
#define CLK_SOURCE_DFLL_SOC 0x630
|
||||||
#define CLK_SOURCE_SOC_THERM 0x644
|
#define CLK_SOURCE_SOC_THERM 0x644
|
||||||
#define CLK_SOURCE_XUSB_HOST_SRC 0x600
|
#define CLK_SOURCE_XUSB_HOST_SRC 0x600
|
||||||
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
|
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
|
||||||
|
@ -250,6 +283,10 @@
|
||||||
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
|
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
|
||||||
#define CLK_SOURCE_EMC 0x19c
|
#define CLK_SOURCE_EMC 0x19c
|
||||||
|
|
||||||
|
/* PLLM override registers */
|
||||||
|
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
|
||||||
|
#define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
|
||||||
|
|
||||||
/* Tegra CPU clock and reset control regs */
|
/* Tegra CPU clock and reset control regs */
|
||||||
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
|
#define CLK_RST_CONTROLLER_CPU_CMPLX_STATUS 0x470
|
||||||
|
|
||||||
|
@ -267,6 +304,15 @@ static DEFINE_SPINLOCK(clk_doubler_lock);
|
||||||
static DEFINE_SPINLOCK(clk_out_lock);
|
static DEFINE_SPINLOCK(clk_out_lock);
|
||||||
static DEFINE_SPINLOCK(sysrate_lock);
|
static DEFINE_SPINLOCK(sysrate_lock);
|
||||||
|
|
||||||
|
static struct div_nmp pllxc_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 8,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 8,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 4,
|
||||||
|
};
|
||||||
|
|
||||||
static struct pdiv_map pllxc_p[] = {
|
static struct pdiv_map pllxc_p[] = {
|
||||||
{ .pdiv = 1, .hw_val = 0 },
|
{ .pdiv = 1, .hw_val = 0 },
|
||||||
{ .pdiv = 2, .hw_val = 1 },
|
{ .pdiv = 2, .hw_val = 1 },
|
||||||
|
@ -315,6 +361,16 @@ static struct tegra_clk_pll_params pll_c_params = {
|
||||||
.stepa_shift = 17,
|
.stepa_shift = 17,
|
||||||
.stepb_shift = 9,
|
.stepb_shift = 9,
|
||||||
.pdiv_tohw = pllxc_p,
|
.pdiv_tohw = pllxc_p,
|
||||||
|
.div_nmp = &pllxc_nmp,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllcx_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 2,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 8,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pdiv_map pllc_p[] = {
|
static struct pdiv_map pllc_p[] = {
|
||||||
|
@ -348,6 +404,8 @@ static struct tegra_clk_pll_params pll_c2_params = {
|
||||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
.pdiv_tohw = pllc_p,
|
.pdiv_tohw = pllc_p,
|
||||||
|
.div_nmp = &pllcx_nmp,
|
||||||
|
.max_p = 7,
|
||||||
.ext_misc_reg[0] = 0x4f0,
|
.ext_misc_reg[0] = 0x4f0,
|
||||||
.ext_misc_reg[1] = 0x4f4,
|
.ext_misc_reg[1] = 0x4f4,
|
||||||
.ext_misc_reg[2] = 0x4f8,
|
.ext_misc_reg[2] = 0x4f8,
|
||||||
|
@ -366,11 +424,25 @@ static struct tegra_clk_pll_params pll_c3_params = {
|
||||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
.pdiv_tohw = pllc_p,
|
.pdiv_tohw = pllc_p,
|
||||||
|
.div_nmp = &pllcx_nmp,
|
||||||
|
.max_p = 7,
|
||||||
.ext_misc_reg[0] = 0x504,
|
.ext_misc_reg[0] = 0x504,
|
||||||
.ext_misc_reg[1] = 0x508,
|
.ext_misc_reg[1] = 0x508,
|
||||||
.ext_misc_reg[2] = 0x50c,
|
.ext_misc_reg[2] = 0x50c,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllm_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 8,
|
||||||
|
.override_divm_shift = 0,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 8,
|
||||||
|
.override_divn_shift = 8,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 1,
|
||||||
|
.override_divp_shift = 27,
|
||||||
|
};
|
||||||
|
|
||||||
static struct pdiv_map pllm_p[] = {
|
static struct pdiv_map pllm_p[] = {
|
||||||
{ .pdiv = 1, .hw_val = 0 },
|
{ .pdiv = 1, .hw_val = 0 },
|
||||||
{ .pdiv = 2, .hw_val = 1 },
|
{ .pdiv = 2, .hw_val = 1 },
|
||||||
|
@ -400,6 +472,18 @@ static struct tegra_clk_pll_params pll_m_params = {
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
.max_p = 2,
|
.max_p = 2,
|
||||||
.pdiv_tohw = pllm_p,
|
.pdiv_tohw = pllm_p,
|
||||||
|
.div_nmp = &pllm_nmp,
|
||||||
|
.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
|
||||||
|
.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllp_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 5,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 10,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
||||||
|
@ -423,6 +507,7 @@ static struct tegra_clk_pll_params pll_p_params = {
|
||||||
.lock_mask = PLL_BASE_LOCK,
|
.lock_mask = PLL_BASE_LOCK,
|
||||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
|
.div_nmp = &pllp_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
|
||||||
|
@ -449,6 +534,7 @@ static struct tegra_clk_pll_params pll_a_params = {
|
||||||
.lock_mask = PLL_BASE_LOCK,
|
.lock_mask = PLL_BASE_LOCK,
|
||||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
|
.div_nmp = &pllp_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
|
||||||
|
@ -484,6 +570,7 @@ static struct tegra_clk_pll_params pll_d_params = {
|
||||||
.lock_mask = PLL_BASE_LOCK,
|
.lock_mask = PLL_BASE_LOCK,
|
||||||
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 1000,
|
.lock_delay = 1000,
|
||||||
|
.div_nmp = &pllp_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_params pll_d2_params = {
|
static struct tegra_clk_pll_params pll_d2_params = {
|
||||||
|
@ -498,6 +585,7 @@ static struct tegra_clk_pll_params pll_d2_params = {
|
||||||
.lock_mask = PLL_BASE_LOCK,
|
.lock_mask = PLL_BASE_LOCK,
|
||||||
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 1000,
|
.lock_delay = 1000,
|
||||||
|
.div_nmp = &pllp_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct pdiv_map pllu_p[] = {
|
static struct pdiv_map pllu_p[] = {
|
||||||
|
@ -506,6 +594,15 @@ static struct pdiv_map pllu_p[] = {
|
||||||
{ .pdiv = 0, .hw_val = 0 },
|
{ .pdiv = 0, .hw_val = 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllu_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 5,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 10,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 1,
|
||||||
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
||||||
{12000000, 480000000, 960, 12, 0, 12},
|
{12000000, 480000000, 960, 12, 0, 12},
|
||||||
{13000000, 480000000, 960, 13, 0, 12},
|
{13000000, 480000000, 960, 13, 0, 12},
|
||||||
|
@ -528,6 +625,7 @@ static struct tegra_clk_pll_params pll_u_params = {
|
||||||
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 1000,
|
.lock_delay = 1000,
|
||||||
.pdiv_tohw = pllu_p,
|
.pdiv_tohw = pllu_p,
|
||||||
|
.div_nmp = &pllu_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
|
||||||
|
@ -560,6 +658,7 @@ static struct tegra_clk_pll_params pll_x_params = {
|
||||||
.stepa_shift = 16,
|
.stepa_shift = 16,
|
||||||
.stepb_shift = 24,
|
.stepb_shift = 24,
|
||||||
.pdiv_tohw = pllxc_p,
|
.pdiv_tohw = pllxc_p,
|
||||||
|
.div_nmp = &pllxc_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||||
|
@ -569,6 +668,15 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||||
{0, 0, 0, 0, 0, 0},
|
{0, 0, 0, 0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct div_nmp plle_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 8,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 8,
|
||||||
|
.divp_shift = 24,
|
||||||
|
.divp_width = 4,
|
||||||
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_params pll_e_params = {
|
static struct tegra_clk_pll_params pll_e_params = {
|
||||||
.input_min = 12000000,
|
.input_min = 12000000,
|
||||||
.input_max = 1000000000,
|
.input_max = 1000000000,
|
||||||
|
@ -582,6 +690,16 @@ static struct tegra_clk_pll_params pll_e_params = {
|
||||||
.lock_mask = PLLE_MISC_LOCK,
|
.lock_mask = PLLE_MISC_LOCK,
|
||||||
.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
|
.div_nmp = &plle_nmp,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllre_nmp = {
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 8,
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 8,
|
||||||
|
.divp_shift = 16,
|
||||||
|
.divp_width = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_params pll_re_vco_params = {
|
static struct tegra_clk_pll_params pll_re_vco_params = {
|
||||||
|
@ -598,6 +716,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
.iddq_reg = PLLRE_MISC,
|
.iddq_reg = PLLRE_MISC,
|
||||||
.iddq_bit_idx = PLLRE_IDDQ_BIT,
|
.iddq_bit_idx = PLLRE_IDDQ_BIT,
|
||||||
|
.div_nmp = &pllre_nmp,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Peripheral clock registers */
|
/* Peripheral clock registers */
|
||||||
|
@ -765,6 +884,7 @@ enum tegra114_clk {
|
||||||
audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
|
audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
|
||||||
blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src,
|
blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src,
|
||||||
xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
|
xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
|
||||||
|
dfll_ref = 264, dfll_soc,
|
||||||
|
|
||||||
/* Mux clocks */
|
/* Mux clocks */
|
||||||
|
|
||||||
|
@ -1202,8 +1322,8 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
||||||
/* PLLP_OUT2 */
|
/* PLLP_OUT2 */
|
||||||
clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
|
clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
|
||||||
clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
|
clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
|
||||||
TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
|
TEGRA_DIVIDER_ROUND_UP | TEGRA_DIVIDER_INT, 24,
|
||||||
&pll_div_lock);
|
8, 1, &pll_div_lock);
|
||||||
clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
|
clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
|
||||||
clk_base + PLLP_OUTA, 17, 16,
|
clk_base + PLLP_OUTA, 17, 16,
|
||||||
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
|
CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
|
||||||
|
@ -1605,7 +1725,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
|
||||||
|
|
||||||
/* clk_out_2 */
|
/* clk_out_2 */
|
||||||
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
|
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
|
||||||
ARRAY_SIZE(clk_out1_parents), 0,
|
ARRAY_SIZE(clk_out2_parents), 0,
|
||||||
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
|
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
|
||||||
&clk_out_lock);
|
&clk_out_lock);
|
||||||
clks[clk_out_2_mux] = clk;
|
clks[clk_out_2_mux] = clk;
|
||||||
|
@ -1617,7 +1737,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
|
||||||
|
|
||||||
/* clk_out_3 */
|
/* clk_out_3 */
|
||||||
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
|
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
|
||||||
ARRAY_SIZE(clk_out1_parents), 0,
|
ARRAY_SIZE(clk_out3_parents), 0,
|
||||||
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
|
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
|
||||||
&clk_out_lock);
|
&clk_out_lock);
|
||||||
clks[clk_out_3_mux] = clk;
|
clks[clk_out_3_mux] = clk;
|
||||||
|
@ -1628,6 +1748,8 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
|
||||||
clks[clk_out_3] = clk;
|
clks[clk_out_3] = clk;
|
||||||
|
|
||||||
/* blink */
|
/* blink */
|
||||||
|
/* clear the blink timer register to directly output clk_32k */
|
||||||
|
writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
|
||||||
clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
|
clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
|
||||||
pmc_base + PMC_DPD_PADS_ORIDE,
|
pmc_base + PMC_DPD_PADS_ORIDE,
|
||||||
PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
|
PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
|
||||||
|
@ -1640,7 +1762,7 @@ static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
||||||
"pll_p_out3", "pll_p_out2", "unused",
|
"pll_p", "pll_p_out2", "unused",
|
||||||
"clk_32k", "pll_m_out1" };
|
"clk_32k", "pll_m_out1" };
|
||||||
|
|
||||||
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
||||||
|
@ -1750,7 +1872,7 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = {
|
||||||
TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
|
TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
|
||||||
TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
|
TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
|
||||||
TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
|
TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
|
||||||
TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc),
|
TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_u_regs, TEGRA_PERIPH_WAR_1005168, msenc),
|
||||||
TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
|
TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
|
||||||
TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
|
TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
|
||||||
TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
|
TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
|
||||||
|
@ -1767,6 +1889,8 @@ static struct tegra_periph_init_data tegra_periph_clk_list[] = {
|
||||||
TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
|
TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
|
||||||
TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
|
TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
|
||||||
TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
|
TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
|
||||||
|
TEGRA_INIT_DATA_MUX("dfll_ref", "ref", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_REF, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_ref),
|
||||||
|
TEGRA_INIT_DATA_MUX("dfll_soc", "soc", "t114_dfll", mux_pllp_clkm, CLK_SOURCE_DFLL_SOC, 155, &periph_w_regs, TEGRA_PERIPH_ON_APB, dfll_soc),
|
||||||
TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
|
TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
|
||||||
TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
|
TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
|
||||||
TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
|
TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
|
||||||
|
@ -2028,6 +2152,10 @@ static const struct of_device_id pmc_match[] __initconst = {
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* dfll_soc/dfll_ref apparently must be kept enabled, otherwise I2C5
|
||||||
|
* breaks
|
||||||
|
*/
|
||||||
static __initdata struct tegra_clk_init_table init_table[] = {
|
static __initdata struct tegra_clk_init_table init_table[] = {
|
||||||
{uarta, pll_p, 408000000, 0},
|
{uarta, pll_p, 408000000, 0},
|
||||||
{uartb, pll_p, 408000000, 0},
|
{uartb, pll_p, 408000000, 0},
|
||||||
|
@ -2043,6 +2171,8 @@ static __initdata struct tegra_clk_init_table init_table[] = {
|
||||||
{i2s2, pll_a_out0, 11289600, 0},
|
{i2s2, pll_a_out0, 11289600, 0},
|
||||||
{i2s3, pll_a_out0, 11289600, 0},
|
{i2s3, pll_a_out0, 11289600, 0},
|
||||||
{i2s4, pll_a_out0, 11289600, 0},
|
{i2s4, pll_a_out0, 11289600, 0},
|
||||||
|
{dfll_soc, pll_p, 51000000, 1},
|
||||||
|
{dfll_ref, pll_p, 51000000, 1},
|
||||||
{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
|
{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2051,7 +2181,132 @@ static void __init tegra114_clock_apply_init_table(void)
|
||||||
tegra_init_from_table(init_table, clks, clk_max);
|
tegra_init_from_table(init_table, clks, clk_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __init tegra114_clock_init(struct device_node *np)
|
|
||||||
|
/**
|
||||||
|
* tegra114_car_barrier - wait for pending writes to the CAR to complete
|
||||||
|
*
|
||||||
|
* Wait for any outstanding writes to the CAR MMIO space from this CPU
|
||||||
|
* to complete before continuing execution. No return value.
|
||||||
|
*/
|
||||||
|
static void tegra114_car_barrier(void)
|
||||||
|
{
|
||||||
|
wmb(); /* probably unnecessary */
|
||||||
|
readl_relaxed(clk_base + CPU_FINETRIM_SELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tegra114_clock_tune_cpu_trimmers_high - use high-voltage propagation delays
|
||||||
|
*
|
||||||
|
* When the CPU rail voltage is in the high-voltage range, use the
|
||||||
|
* built-in hardwired clock propagation delays in the CPU clock
|
||||||
|
* shaper. No return value.
|
||||||
|
*/
|
||||||
|
void tegra114_clock_tune_cpu_trimmers_high(void)
|
||||||
|
{
|
||||||
|
u32 select = 0;
|
||||||
|
|
||||||
|
/* Use hardwired rise->rise & fall->fall clock propagation delays */
|
||||||
|
select |= ~(CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
|
||||||
|
CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
|
||||||
|
CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
|
||||||
|
writel_relaxed(select, clk_base + CPU_FINETRIM_SELECT);
|
||||||
|
|
||||||
|
tegra114_car_barrier();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_high);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tegra114_clock_tune_cpu_trimmers_low - use low-voltage propagation delays
|
||||||
|
*
|
||||||
|
* When the CPU rail voltage is in the low-voltage range, use the
|
||||||
|
* extended clock propagation delays set by
|
||||||
|
* tegra114_clock_tune_cpu_trimmers_init(). The intention is to
|
||||||
|
* maintain the input clock duty cycle that the FCPU subsystem
|
||||||
|
* expects. No return value.
|
||||||
|
*/
|
||||||
|
void tegra114_clock_tune_cpu_trimmers_low(void)
|
||||||
|
{
|
||||||
|
u32 select = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use software-specified rise->rise & fall->fall clock
|
||||||
|
* propagation delays (from
|
||||||
|
* tegra114_clock_tune_cpu_trimmers_init()
|
||||||
|
*/
|
||||||
|
select |= (CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
|
||||||
|
CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
|
||||||
|
CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
|
||||||
|
writel_relaxed(select, clk_base + CPU_FINETRIM_SELECT);
|
||||||
|
|
||||||
|
tegra114_car_barrier();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_low);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tegra114_clock_tune_cpu_trimmers_init - set up and enable clk prop delays
|
||||||
|
*
|
||||||
|
* Program extended clock propagation delays into the FCPU clock
|
||||||
|
* shaper and enable them. XXX Define the purpose - peak current
|
||||||
|
* reduction? No return value.
|
||||||
|
*/
|
||||||
|
/* XXX Initial voltage rail state assumption issues? */
|
||||||
|
void tegra114_clock_tune_cpu_trimmers_init(void)
|
||||||
|
{
|
||||||
|
u32 dr = 0, r = 0;
|
||||||
|
|
||||||
|
/* Increment the rise->rise clock delay by four steps */
|
||||||
|
r |= (CPU_FINETRIM_R_FCPU_1_MASK | CPU_FINETRIM_R_FCPU_2_MASK |
|
||||||
|
CPU_FINETRIM_R_FCPU_3_MASK | CPU_FINETRIM_R_FCPU_4_MASK |
|
||||||
|
CPU_FINETRIM_R_FCPU_5_MASK | CPU_FINETRIM_R_FCPU_6_MASK);
|
||||||
|
writel_relaxed(r, clk_base + CPU_FINETRIM_R);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the rise->rise clock propagation delay specified in the
|
||||||
|
* r field
|
||||||
|
*/
|
||||||
|
dr |= (CPU_FINETRIM_1_FCPU_1 | CPU_FINETRIM_1_FCPU_2 |
|
||||||
|
CPU_FINETRIM_1_FCPU_3 | CPU_FINETRIM_1_FCPU_4 |
|
||||||
|
CPU_FINETRIM_1_FCPU_5 | CPU_FINETRIM_1_FCPU_6);
|
||||||
|
writel_relaxed(dr, clk_base + CPU_FINETRIM_DR);
|
||||||
|
|
||||||
|
tegra114_clock_tune_cpu_trimmers_low();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra114_clock_tune_cpu_trimmers_init);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tegra114_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
|
||||||
|
*
|
||||||
|
* Assert the reset line of the DFLL's DVCO. No return value.
|
||||||
|
*/
|
||||||
|
void tegra114_clock_assert_dfll_dvco_reset(void)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||||
|
v |= (1 << DVFS_DFLL_RESET_SHIFT);
|
||||||
|
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||||
|
tegra114_car_barrier();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra114_clock_assert_dfll_dvco_reset);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* tegra114_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
|
||||||
|
*
|
||||||
|
* Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
|
||||||
|
* operate. No return value.
|
||||||
|
*/
|
||||||
|
void tegra114_clock_deassert_dfll_dvco_reset(void)
|
||||||
|
{
|
||||||
|
u32 v;
|
||||||
|
|
||||||
|
v = readl_relaxed(clk_base + RST_DFLL_DVCO);
|
||||||
|
v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
|
||||||
|
writel_relaxed(v, clk_base + RST_DFLL_DVCO);
|
||||||
|
tegra114_car_barrier();
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra114_clock_deassert_dfll_dvco_reset);
|
||||||
|
|
||||||
|
static void __init tegra114_clock_init(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
int i;
|
int i;
|
||||||
|
@ -2104,3 +2359,4 @@ void __init tegra114_clock_init(struct device_node *np)
|
||||||
|
|
||||||
tegra_cpu_car_ops = &tegra114_cpu_car_ops;
|
tegra_cpu_car_ops = &tegra114_cpu_car_ops;
|
||||||
}
|
}
|
||||||
|
CLK_OF_DECLARE(tegra114, "nvidia,tegra114-car", tegra114_clock_init);
|
||||||
|
|
|
@ -1287,7 +1287,7 @@ static const struct of_device_id pmc_match[] __initconst = {
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init tegra20_clock_init(struct device_node *np)
|
static void __init tegra20_clock_init(struct device_node *np)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
|
@ -1339,3 +1339,4 @@ void __init tegra20_clock_init(struct device_node *np)
|
||||||
|
|
||||||
tegra_cpu_car_ops = &tegra20_cpu_car_ops;
|
tegra_cpu_car_ops = &tegra20_cpu_car_ops;
|
||||||
}
|
}
|
||||||
|
CLK_OF_DECLARE(tegra20, "nvidia,tegra20-car", tegra20_clock_init);
|
||||||
|
|
|
@ -252,6 +252,9 @@
|
||||||
#define CLK_RESET_CCLK_RUN_POLICY 2
|
#define CLK_RESET_CCLK_RUN_POLICY 2
|
||||||
#define CLK_RESET_CCLK_BURST_POLICY_PLLX 8
|
#define CLK_RESET_CCLK_BURST_POLICY_PLLX 8
|
||||||
|
|
||||||
|
/* PLLM override registers */
|
||||||
|
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
|
||||||
|
|
||||||
#ifdef CONFIG_PM_SLEEP
|
#ifdef CONFIG_PM_SLEEP
|
||||||
static struct cpu_clk_suspend_context {
|
static struct cpu_clk_suspend_context {
|
||||||
u32 pllx_misc;
|
u32 pllx_misc;
|
||||||
|
@ -563,6 +566,18 @@ static struct tegra_clk_pll_params pll_c_params = {
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct div_nmp pllm_nmp = {
|
||||||
|
.divn_shift = 8,
|
||||||
|
.divn_width = 10,
|
||||||
|
.override_divn_shift = 5,
|
||||||
|
.divm_shift = 0,
|
||||||
|
.divm_width = 5,
|
||||||
|
.override_divm_shift = 0,
|
||||||
|
.divp_shift = 20,
|
||||||
|
.divp_width = 3,
|
||||||
|
.override_divp_shift = 15,
|
||||||
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_params pll_m_params = {
|
static struct tegra_clk_pll_params pll_m_params = {
|
||||||
.input_min = 2000000,
|
.input_min = 2000000,
|
||||||
.input_max = 31000000,
|
.input_max = 31000000,
|
||||||
|
@ -575,6 +590,9 @@ static struct tegra_clk_pll_params pll_m_params = {
|
||||||
.lock_mask = PLL_BASE_LOCK,
|
.lock_mask = PLL_BASE_LOCK,
|
||||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||||
.lock_delay = 300,
|
.lock_delay = 300,
|
||||||
|
.div_nmp = &pllm_nmp,
|
||||||
|
.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
|
||||||
|
.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tegra_clk_pll_params pll_p_params = {
|
static struct tegra_clk_pll_params pll_p_params = {
|
||||||
|
@ -1223,7 +1241,7 @@ static void __init tegra30_pmc_clk_init(void)
|
||||||
|
|
||||||
/* clk_out_2 */
|
/* clk_out_2 */
|
||||||
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
|
clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
|
||||||
ARRAY_SIZE(clk_out1_parents), 0,
|
ARRAY_SIZE(clk_out2_parents), 0,
|
||||||
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
|
pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
|
||||||
&clk_out_lock);
|
&clk_out_lock);
|
||||||
clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
|
clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
|
||||||
|
@ -1234,7 +1252,7 @@ static void __init tegra30_pmc_clk_init(void)
|
||||||
|
|
||||||
/* clk_out_3 */
|
/* clk_out_3 */
|
||||||
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
|
clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
|
||||||
ARRAY_SIZE(clk_out1_parents), 0,
|
ARRAY_SIZE(clk_out3_parents), 0,
|
||||||
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
|
pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
|
||||||
&clk_out_lock);
|
&clk_out_lock);
|
||||||
clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
|
clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
|
||||||
|
@ -1954,7 +1972,7 @@ static const struct of_device_id pmc_match[] __initconst = {
|
||||||
{},
|
{},
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init tegra30_clock_init(struct device_node *np)
|
static void __init tegra30_clock_init(struct device_node *np)
|
||||||
{
|
{
|
||||||
struct device_node *node;
|
struct device_node *node;
|
||||||
int i;
|
int i;
|
||||||
|
@ -2005,3 +2023,4 @@ void __init tegra30_clock_init(struct device_node *np)
|
||||||
|
|
||||||
tegra_cpu_car_ops = &tegra30_cpu_car_ops;
|
tegra_cpu_car_ops = &tegra30_cpu_car_ops;
|
||||||
}
|
}
|
||||||
|
CLK_OF_DECLARE(tegra30, "nvidia,tegra30-car", tegra30_clock_init);
|
||||||
|
|
|
@ -74,18 +74,6 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct of_device_id tegra_dt_clk_match[] = {
|
|
||||||
{ .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init },
|
|
||||||
{ .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init },
|
|
||||||
{ .compatible = "nvidia,tegra114-car", .data = tegra114_clock_init },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
void __init tegra_clocks_init(void)
|
|
||||||
{
|
|
||||||
of_clk_init(tegra_dt_clk_match);
|
|
||||||
}
|
|
||||||
|
|
||||||
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
||||||
|
|
||||||
void __init tegra_clocks_apply_init_table(void)
|
void __init tegra_clocks_apply_init_table(void)
|
||||||
|
|
|
@ -127,6 +127,31 @@ struct pdiv_map {
|
||||||
u8 hw_val;
|
u8 hw_val;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct div_nmp - offset and width of m,n and p fields
|
||||||
|
*
|
||||||
|
* @divn_shift: shift to the feedback divider bit field
|
||||||
|
* @divn_width: width of the feedback divider bit field
|
||||||
|
* @divm_shift: shift to the input divider bit field
|
||||||
|
* @divm_width: width of the input divider bit field
|
||||||
|
* @divp_shift: shift to the post divider bit field
|
||||||
|
* @divp_width: width of the post divider bit field
|
||||||
|
* @override_divn_shift: shift to the feedback divider bitfield in override reg
|
||||||
|
* @override_divm_shift: shift to the input divider bitfield in override reg
|
||||||
|
* @override_divp_shift: shift to the post divider bitfield in override reg
|
||||||
|
*/
|
||||||
|
struct div_nmp {
|
||||||
|
u8 divn_shift;
|
||||||
|
u8 divn_width;
|
||||||
|
u8 divm_shift;
|
||||||
|
u8 divm_width;
|
||||||
|
u8 divp_shift;
|
||||||
|
u8 divp_width;
|
||||||
|
u8 override_divn_shift;
|
||||||
|
u8 override_divm_shift;
|
||||||
|
u8 override_divp_shift;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct clk_pll_params - PLL parameters
|
* struct clk_pll_params - PLL parameters
|
||||||
*
|
*
|
||||||
|
@ -161,11 +186,14 @@ struct tegra_clk_pll_params {
|
||||||
u32 aux_reg;
|
u32 aux_reg;
|
||||||
u32 dyn_ramp_reg;
|
u32 dyn_ramp_reg;
|
||||||
u32 ext_misc_reg[3];
|
u32 ext_misc_reg[3];
|
||||||
|
u32 pmc_divnm_reg;
|
||||||
|
u32 pmc_divp_reg;
|
||||||
int stepa_shift;
|
int stepa_shift;
|
||||||
int stepb_shift;
|
int stepb_shift;
|
||||||
int lock_delay;
|
int lock_delay;
|
||||||
int max_p;
|
int max_p;
|
||||||
struct pdiv_map *pdiv_tohw;
|
struct pdiv_map *pdiv_tohw;
|
||||||
|
struct div_nmp *div_nmp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -179,12 +207,6 @@ struct tegra_clk_pll_params {
|
||||||
* @flags: PLL flags
|
* @flags: PLL flags
|
||||||
* @fixed_rate: PLL rate if it is fixed
|
* @fixed_rate: PLL rate if it is fixed
|
||||||
* @lock: register lock
|
* @lock: register lock
|
||||||
* @divn_shift: shift to the feedback divider bit field
|
|
||||||
* @divn_width: width of the feedback divider bit field
|
|
||||||
* @divm_shift: shift to the input divider bit field
|
|
||||||
* @divm_width: width of the input divider bit field
|
|
||||||
* @divp_shift: shift to the post divider bit field
|
|
||||||
* @divp_width: width of the post divider bit field
|
|
||||||
*
|
*
|
||||||
* Flags:
|
* Flags:
|
||||||
* TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
|
* TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
|
||||||
|
@ -214,12 +236,6 @@ struct tegra_clk_pll {
|
||||||
u32 flags;
|
u32 flags;
|
||||||
unsigned long fixed_rate;
|
unsigned long fixed_rate;
|
||||||
spinlock_t *lock;
|
spinlock_t *lock;
|
||||||
u8 divn_shift;
|
|
||||||
u8 divn_width;
|
|
||||||
u8 divm_shift;
|
|
||||||
u8 divm_width;
|
|
||||||
u8 divp_shift;
|
|
||||||
u8 divp_width;
|
|
||||||
struct tegra_clk_pll_freq_table *freq_table;
|
struct tegra_clk_pll_freq_table *freq_table;
|
||||||
struct tegra_clk_pll_params *params;
|
struct tegra_clk_pll_params *params;
|
||||||
};
|
};
|
||||||
|
@ -571,23 +587,11 @@ void tegra_init_from_table(struct tegra_clk_init_table *tbl,
|
||||||
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
|
||||||
struct clk *clks[], int clk_max);
|
struct clk *clks[], int clk_max);
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
void tegra114_clock_tune_cpu_trimmers_high(void);
|
||||||
void tegra20_clock_init(struct device_node *np);
|
void tegra114_clock_tune_cpu_trimmers_low(void);
|
||||||
#else
|
void tegra114_clock_tune_cpu_trimmers_init(void);
|
||||||
static inline void tegra20_clock_init(struct device_node *np) {}
|
void tegra114_clock_assert_dfll_dvco_reset(void);
|
||||||
#endif /* CONFIG_ARCH_TEGRA_2x_SOC */
|
void tegra114_clock_deassert_dfll_dvco_reset(void);
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_3x_SOC
|
|
||||||
void tegra30_clock_init(struct device_node *np);
|
|
||||||
#else
|
|
||||||
static inline void tegra30_clock_init(struct device_node *np) {}
|
|
||||||
#endif /* CONFIG_ARCH_TEGRA_3x_SOC */
|
|
||||||
|
|
||||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
|
||||||
void tegra114_clock_init(struct device_node *np);
|
|
||||||
#else
|
|
||||||
static inline void tegra114_clock_init(struct device_node *np) {}
|
|
||||||
#endif /* CONFIG_ARCH_TEGRA114_SOC */
|
|
||||||
|
|
||||||
typedef void (*tegra_clk_apply_init_table_func)(void);
|
typedef void (*tegra_clk_apply_init_table_func)(void);
|
||||||
extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
|
||||||
|
|
|
@ -45,7 +45,7 @@ static int ab8500_reg_clks(struct device *dev)
|
||||||
CLK_IS_ROOT);
|
CLK_IS_ROOT);
|
||||||
clk_register_clkdev(clk, "sysclk", "ab8500-usb.0");
|
clk_register_clkdev(clk, "sysclk", "ab8500-usb.0");
|
||||||
clk_register_clkdev(clk, "sysclk", "ab-iddet.0");
|
clk_register_clkdev(clk, "sysclk", "ab-iddet.0");
|
||||||
clk_register_clkdev(clk, "sysclk", "ab85xx-codec.0");
|
clk_register_clkdev(clk, "sysclk", "snd-soc-mop500.0");
|
||||||
clk_register_clkdev(clk, "sysclk", "shrm_bus");
|
clk_register_clkdev(clk, "sysclk", "shrm_bus");
|
||||||
|
|
||||||
/* ab8500_sysclk2 */
|
/* ab8500_sysclk2 */
|
||||||
|
@ -70,19 +70,19 @@ static int ab8500_reg_clks(struct device *dev)
|
||||||
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
||||||
AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
||||||
38400000, 9000, CLK_IS_ROOT);
|
38400000, 9000, CLK_IS_ROOT);
|
||||||
clk_register_clkdev(clk, "ulpclk", "ab85xx-codec.0");
|
clk_register_clkdev(clk, "ulpclk", "snd-soc-mop500.0");
|
||||||
|
|
||||||
/* ab8500_intclk */
|
/* ab8500_intclk */
|
||||||
clk = clk_reg_sysctrl_set_parent(dev , "intclk", intclk_parents, 2,
|
clk = clk_reg_sysctrl_set_parent(dev , "intclk", intclk_parents, 2,
|
||||||
intclk_reg_sel, intclk_reg_mask, intclk_reg_bits, 0);
|
intclk_reg_sel, intclk_reg_mask, intclk_reg_bits, 0);
|
||||||
clk_register_clkdev(clk, "intclk", "ab85xx-codec.0");
|
clk_register_clkdev(clk, "intclk", "snd-soc-mop500.0");
|
||||||
clk_register_clkdev(clk, NULL, "ab8500-pwm.1");
|
clk_register_clkdev(clk, NULL, "ab8500-pwm.1");
|
||||||
|
|
||||||
/* ab8500_audioclk */
|
/* ab8500_audioclk */
|
||||||
clk = clk_reg_sysctrl_gate(dev , "audioclk", "intclk",
|
clk = clk_reg_sysctrl_gate(dev , "audioclk", "intclk",
|
||||||
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_AUDIOCLKENA,
|
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_AUDIOCLKENA,
|
||||||
AB8500_SYSULPCLKCTRL1_AUDIOCLKENA, 0, 0);
|
AB8500_SYSULPCLKCTRL1_AUDIOCLKENA, 0, 0);
|
||||||
clk_register_clkdev(clk, "audioclk", "ab85xx-codec.0");
|
clk_register_clkdev(clk, "audioclk", "ab8500-codec.0");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,568 @@
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/mfd/dbx500-prcmu.h>
|
#include <linux/mfd/dbx500-prcmu.h>
|
||||||
#include <linux/platform_data/clk-ux500.h>
|
#include <linux/platform_data/clk-ux500.h>
|
||||||
|
|
||||||
#include "clk.h"
|
#include "clk.h"
|
||||||
|
|
||||||
void u8540_clk_init(void)
|
void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||||
|
u32 clkrst5_base, u32 clkrst6_base)
|
||||||
{
|
{
|
||||||
/* register clocks here */
|
struct clk *clk;
|
||||||
|
|
||||||
|
/* Clock sources. */
|
||||||
|
/* Fixed ClockGen */
|
||||||
|
clk = clk_reg_prcmu_gate("soc0_pll", NULL, PRCMU_PLLSOC0,
|
||||||
|
CLK_IS_ROOT|CLK_IGNORE_UNUSED);
|
||||||
|
clk_register_clkdev(clk, "soc0_pll", NULL);
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("soc1_pll", NULL, PRCMU_PLLSOC1,
|
||||||
|
CLK_IS_ROOT|CLK_IGNORE_UNUSED);
|
||||||
|
clk_register_clkdev(clk, "soc1_pll", NULL);
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("ddr_pll", NULL, PRCMU_PLLDDR,
|
||||||
|
CLK_IS_ROOT|CLK_IGNORE_UNUSED);
|
||||||
|
clk_register_clkdev(clk, "ddr_pll", NULL);
|
||||||
|
|
||||||
|
clk = clk_register_fixed_rate(NULL, "rtc32k", NULL,
|
||||||
|
CLK_IS_ROOT|CLK_IGNORE_UNUSED,
|
||||||
|
32768);
|
||||||
|
clk_register_clkdev(clk, "clk32k", NULL);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "rtc-pl031");
|
||||||
|
|
||||||
|
clk = clk_register_fixed_rate(NULL, "ulp38m4", NULL,
|
||||||
|
CLK_IS_ROOT|CLK_IGNORE_UNUSED,
|
||||||
|
38400000);
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("uartclk", NULL, PRCMU_UARTCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "UART");
|
||||||
|
|
||||||
|
/* msp02clk needs a abx500 clk as parent. Handle by abx500 clk driver */
|
||||||
|
clk = clk_reg_prcmu_gate("msp02clk", "ab9540_sysclk12_b1",
|
||||||
|
PRCMU_MSP02CLK, 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "MSP02");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("msp1clk", NULL, PRCMU_MSP1CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "MSP1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("i2cclk", NULL, PRCMU_I2CCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "I2C");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("slimclk", NULL, PRCMU_SLIMCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "slim");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per1clk", NULL, PRCMU_PER1CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per2clk", NULL, PRCMU_PER2CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per3clk", NULL, PRCMU_PER3CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per5clk", NULL, PRCMU_PER5CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH5");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per6clk", NULL, PRCMU_PER6CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH6");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("per7clk", NULL, PRCMU_PER7CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "PERIPH7");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("lcdclk", NULL, PRCMU_LCDCLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "lcd");
|
||||||
|
clk_register_clkdev(clk, "lcd", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_opp_gate("bmlclk", NULL, PRCMU_BML8580CLK,
|
||||||
|
CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "bml");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("hsitxclk", NULL, PRCMU_HSITXCLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("hsirxclk", NULL, PRCMU_HSIRXCLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("hdmiclk", NULL, PRCMU_HDMICLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "hdmi");
|
||||||
|
clk_register_clkdev(clk, "hdmi", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("apeatclk", NULL, PRCMU_APEATCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "apeat");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("apetraceclk", NULL, PRCMU_APETRACECLK,
|
||||||
|
CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "apetrace");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("mcdeclk", NULL, PRCMU_MCDECLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "mcde");
|
||||||
|
clk_register_clkdev(clk, "mcde", "mcde");
|
||||||
|
clk_register_clkdev(clk, NULL, "dsilink.0");
|
||||||
|
clk_register_clkdev(clk, NULL, "dsilink.1");
|
||||||
|
clk_register_clkdev(clk, NULL, "dsilink.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_opp_gate("ipi2cclk", NULL, PRCMU_IPI2CCLK,
|
||||||
|
CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "ipi2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("dsialtclk", NULL, PRCMU_DSIALTCLK,
|
||||||
|
CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "dsialt");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("dmaclk", NULL, PRCMU_DMACLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "dma40.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("b2r2clk", NULL, PRCMU_B2R2CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "b2r2");
|
||||||
|
clk_register_clkdev(clk, NULL, "b2r2_core");
|
||||||
|
clk_register_clkdev(clk, NULL, "U8500-B2R2.0");
|
||||||
|
clk_register_clkdev(clk, NULL, "b2r2_1_core");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("tvclk", NULL, PRCMU_TVCLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "tv");
|
||||||
|
clk_register_clkdev(clk, "tv", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("sspclk", NULL, PRCMU_SSPCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "SSP");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("rngclk", NULL, PRCMU_RNGCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "rngclk");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("uiccclk", NULL, PRCMU_UICCCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "uicc");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("timclk", NULL, PRCMU_TIMCLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "mtu0");
|
||||||
|
clk_register_clkdev(clk, NULL, "mtu1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_opp_volt_scalable("sdmmcclk", NULL,
|
||||||
|
PRCMU_SDMMCCLK, 100000000,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdmmc");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_opp_volt_scalable("sdmmchclk", NULL,
|
||||||
|
PRCMU_SDMMCHCLK, 400000000,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdmmchclk");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("hvaclk", NULL, PRCMU_HVACLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "hva");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_gate("g1clk", NULL, PRCMU_G1CLK, CLK_IS_ROOT);
|
||||||
|
clk_register_clkdev(clk, NULL, "g1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("spare1clk", NULL, PRCMU_SPARE1CLK, 0,
|
||||||
|
CLK_IS_ROOT|CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsilcd", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi_pll", "hdmiclk",
|
||||||
|
PRCMU_PLLDSI, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsihs2", "mcde");
|
||||||
|
clk_register_clkdev(clk, "hs_clk", "dsilink.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsilcd_pll", "spare1clk",
|
||||||
|
PRCMU_PLLDSI_LCD, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsilcd_pll", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi0clk", "dsi_pll",
|
||||||
|
PRCMU_DSI0CLK, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsihs0", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi0lcdclk", "dsilcd_pll",
|
||||||
|
PRCMU_DSI0CLK_LCD, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsihs0", "mcde");
|
||||||
|
clk_register_clkdev(clk, "hs_clk", "dsilink.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi1clk", "dsi_pll",
|
||||||
|
PRCMU_DSI1CLK, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsihs1", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi1lcdclk", "dsilcd_pll",
|
||||||
|
PRCMU_DSI1CLK_LCD, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "dsihs1", "mcde");
|
||||||
|
clk_register_clkdev(clk, "hs_clk", "dsilink.1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi0escclk", "tvclk",
|
||||||
|
PRCMU_DSI0ESCCLK, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "lp_clk", "dsilink.0");
|
||||||
|
clk_register_clkdev(clk, "dsilp0", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi1escclk", "tvclk",
|
||||||
|
PRCMU_DSI1ESCCLK, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "lp_clk", "dsilink.1");
|
||||||
|
clk_register_clkdev(clk, "dsilp1", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable("dsi2escclk", "tvclk",
|
||||||
|
PRCMU_DSI2ESCCLK, 0, CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, "lp_clk", "dsilink.2");
|
||||||
|
clk_register_clkdev(clk, "dsilp2", "mcde");
|
||||||
|
|
||||||
|
clk = clk_reg_prcmu_scalable_rate("armss", NULL,
|
||||||
|
PRCMU_ARMSS, 0, CLK_IS_ROOT|CLK_IGNORE_UNUSED);
|
||||||
|
clk_register_clkdev(clk, "armss", NULL);
|
||||||
|
|
||||||
|
clk = clk_register_fixed_factor(NULL, "smp_twd", "armss",
|
||||||
|
CLK_IGNORE_UNUSED, 1, 2);
|
||||||
|
clk_register_clkdev(clk, NULL, "smp_twd");
|
||||||
|
|
||||||
|
/* PRCC P-clocks */
|
||||||
|
/* Peripheral 1 : PRCC P-clocks */
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk0", "per1clk", clkrst1_base,
|
||||||
|
BIT(0), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "uart0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk1", "per1clk", clkrst1_base,
|
||||||
|
BIT(1), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "uart1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk2", "per1clk", clkrst1_base,
|
||||||
|
BIT(2), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk3", "per1clk", clkrst1_base,
|
||||||
|
BIT(3), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "msp0");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk4", "per1clk", clkrst1_base,
|
||||||
|
BIT(4), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "msp1");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk5", "per1clk", clkrst1_base,
|
||||||
|
BIT(5), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk6", "per1clk", clkrst1_base,
|
||||||
|
BIT(6), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk7", "per1clk", clkrst1_base,
|
||||||
|
BIT(7), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "spi3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk8", "per1clk", clkrst1_base,
|
||||||
|
BIT(8), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "slimbus0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk9", "per1clk", clkrst1_base,
|
||||||
|
BIT(9), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.0");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.1");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpioblock0");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "ab85xx-codec.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk10", "per1clk", clkrst1_base,
|
||||||
|
BIT(10), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.4");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p1_pclk11", "per1clk", clkrst1_base,
|
||||||
|
BIT(11), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "msp3");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.3");
|
||||||
|
|
||||||
|
/* Peripheral 2 : PRCC P-clocks */
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk0", "per2clk", clkrst2_base,
|
||||||
|
BIT(0), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk1", "per2clk", clkrst2_base,
|
||||||
|
BIT(1), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "spi2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk2", "per2clk", clkrst2_base,
|
||||||
|
BIT(2), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "spi1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk3", "per2clk", clkrst2_base,
|
||||||
|
BIT(3), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "pwl");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk4", "per2clk", clkrst2_base,
|
||||||
|
BIT(4), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi4");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk5", "per2clk", clkrst2_base,
|
||||||
|
BIT(5), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "msp2");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "dbx5x0-msp-i2s.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk6", "per2clk", clkrst2_base,
|
||||||
|
BIT(6), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk7", "per2clk", clkrst2_base,
|
||||||
|
BIT(7), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk8", "per2clk", clkrst2_base,
|
||||||
|
BIT(8), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "spi0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk9", "per2clk", clkrst2_base,
|
||||||
|
BIT(9), 0);
|
||||||
|
clk_register_clkdev(clk, "hsir_hclk", "ste_hsi.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk10", "per2clk", clkrst2_base,
|
||||||
|
BIT(10), 0);
|
||||||
|
clk_register_clkdev(clk, "hsit_hclk", "ste_hsi.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk11", "per2clk", clkrst2_base,
|
||||||
|
BIT(11), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.6");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.7");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpioblock1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p2_pclk12", "per2clk", clkrst2_base,
|
||||||
|
BIT(12), 0);
|
||||||
|
clk_register_clkdev(clk, "msp4-pclk", "ab85xx-codec.0");
|
||||||
|
|
||||||
|
/* Peripheral 3 : PRCC P-clocks */
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk0", "per3clk", clkrst3_base,
|
||||||
|
BIT(0), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "fsmc");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk1", "per3clk", clkrst3_base,
|
||||||
|
BIT(1), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "ssp0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk2", "per3clk", clkrst3_base,
|
||||||
|
BIT(2), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "ssp1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk3", "per3clk", clkrst3_base,
|
||||||
|
BIT(3), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk4", "per3clk", clkrst3_base,
|
||||||
|
BIT(4), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk5", "per3clk", clkrst3_base,
|
||||||
|
BIT(5), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "ske");
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-ske-keypad");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk6", "per3clk", clkrst3_base,
|
||||||
|
BIT(6), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "uart2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk7", "per3clk", clkrst3_base,
|
||||||
|
BIT(7), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "sdi5");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk8", "per3clk", clkrst3_base,
|
||||||
|
BIT(8), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.2");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.3");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.4");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.5");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpioblock2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk9", "per3clk", clkrst3_base,
|
||||||
|
BIT(9), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.5");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk10", "per3clk", clkrst3_base,
|
||||||
|
BIT(10), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "nmk-i2c.6");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk11", "per3clk", clkrst3_base,
|
||||||
|
BIT(11), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "uart3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p3_pclk12", "per3clk", clkrst3_base,
|
||||||
|
BIT(12), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "uart4");
|
||||||
|
|
||||||
|
/* Peripheral 5 : PRCC P-clocks */
|
||||||
|
clk = clk_reg_prcc_pclk("p5_pclk0", "per5clk", clkrst5_base,
|
||||||
|
BIT(0), 0);
|
||||||
|
clk_register_clkdev(clk, "usb", "musb-ux500.0");
|
||||||
|
clk_register_clkdev(clk, "usbclk", "ab-iddet.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p5_pclk1", "per5clk", clkrst5_base,
|
||||||
|
BIT(1), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "gpio.8");
|
||||||
|
clk_register_clkdev(clk, NULL, "gpioblock3");
|
||||||
|
|
||||||
|
/* Peripheral 6 : PRCC P-clocks */
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk0", "per6clk", clkrst6_base,
|
||||||
|
BIT(0), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "rng");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk1", "per6clk", clkrst6_base,
|
||||||
|
BIT(1), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "cryp0");
|
||||||
|
clk_register_clkdev(clk, NULL, "cryp1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk2", "per6clk", clkrst6_base,
|
||||||
|
BIT(2), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "hash0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk3", "per6clk", clkrst6_base,
|
||||||
|
BIT(3), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "pka");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk4", "per6clk", clkrst6_base,
|
||||||
|
BIT(4), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "db8540-hash1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk5", "per6clk", clkrst6_base,
|
||||||
|
BIT(5), 0);
|
||||||
|
clk_register_clkdev(clk, NULL, "cfgreg");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk6", "per6clk", clkrst6_base,
|
||||||
|
BIT(6), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "mtu0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_pclk("p6_pclk7", "per6clk", clkrst6_base,
|
||||||
|
BIT(7), 0);
|
||||||
|
clk_register_clkdev(clk, "apb_pclk", "mtu1");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRCC K-clocks ==> see table PRCC_PCKEN/PRCC_KCKEN
|
||||||
|
* This differs from the internal implementation:
|
||||||
|
* We don't use the PERPIH[n| clock as parent, since those _should_
|
||||||
|
* only be used as parents for the P-clocks.
|
||||||
|
* TODO: "parentjoin" with corresponding P-clocks for all K-clocks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Peripheral 1 : PRCC K-clocks */
|
||||||
|
clk = clk_reg_prcc_kclk("p1_uart0_kclk", "uartclk",
|
||||||
|
clkrst1_base, BIT(0), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "uart0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_uart1_kclk", "uartclk",
|
||||||
|
clkrst1_base, BIT(1), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "uart1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_i2c1_kclk", "i2cclk",
|
||||||
|
clkrst1_base, BIT(2), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_msp0_kclk", "msp02clk",
|
||||||
|
clkrst1_base, BIT(3), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "msp0");
|
||||||
|
clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_msp1_kclk", "msp1clk",
|
||||||
|
clkrst1_base, BIT(4), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "msp1");
|
||||||
|
clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_sdi0_kclk", "sdmmchclk",
|
||||||
|
clkrst1_base, BIT(5), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_i2c2_kclk", "i2cclk",
|
||||||
|
clkrst1_base, BIT(6), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_slimbus0_kclk", "slimclk",
|
||||||
|
clkrst1_base, BIT(8), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "slimbus0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_i2c4_kclk", "i2cclk",
|
||||||
|
clkrst1_base, BIT(9), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.4");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p1_msp3_kclk", "msp1clk",
|
||||||
|
clkrst1_base, BIT(10), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "msp3");
|
||||||
|
clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.3");
|
||||||
|
|
||||||
|
/* Peripheral 2 : PRCC K-clocks */
|
||||||
|
clk = clk_reg_prcc_kclk("p2_i2c3_kclk", "i2cclk",
|
||||||
|
clkrst2_base, BIT(0), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_pwl_kclk", "rtc32k",
|
||||||
|
clkrst2_base, BIT(1), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "pwl");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_sdi4_kclk", "sdmmchclk",
|
||||||
|
clkrst2_base, BIT(2), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi4");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_msp2_kclk", "msp02clk",
|
||||||
|
clkrst2_base, BIT(3), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "msp2");
|
||||||
|
clk_register_clkdev(clk, NULL, "dbx5x0-msp-i2s.2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_sdi1_kclk", "sdmmchclk",
|
||||||
|
clkrst2_base, BIT(4), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_sdi3_kclk", "sdmmcclk",
|
||||||
|
clkrst2_base, BIT(5), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_ssirx_kclk", "hsirxclk",
|
||||||
|
clkrst2_base, BIT(6),
|
||||||
|
CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
|
||||||
|
clk_register_clkdev(clk, "hsir_hsirxclk", "ste_hsi.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p2_ssitx_kclk", "hsitxclk",
|
||||||
|
clkrst2_base, BIT(7),
|
||||||
|
CLK_SET_RATE_GATE|CLK_SET_RATE_PARENT);
|
||||||
|
clk_register_clkdev(clk, "hsit_hsitxclk", "ste_hsi.0");
|
||||||
|
|
||||||
|
/* Should only be 9540, but might be added for 85xx as well */
|
||||||
|
clk = clk_reg_prcc_kclk("p2_msp4_kclk", "msp02clk",
|
||||||
|
clkrst2_base, BIT(9), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "msp4");
|
||||||
|
clk_register_clkdev(clk, "msp4", "ab85xx-codec.0");
|
||||||
|
|
||||||
|
/* Peripheral 3 : PRCC K-clocks */
|
||||||
|
clk = clk_reg_prcc_kclk("p3_ssp0_kclk", "sspclk",
|
||||||
|
clkrst3_base, BIT(1), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "ssp0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_ssp1_kclk", "sspclk",
|
||||||
|
clkrst3_base, BIT(2), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "ssp1");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_i2c0_kclk", "i2cclk",
|
||||||
|
clkrst3_base, BIT(3), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.0");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_sdi2_kclk", "sdmmchclk",
|
||||||
|
clkrst3_base, BIT(4), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_ske_kclk", "rtc32k",
|
||||||
|
clkrst3_base, BIT(5), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "ske");
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-ske-keypad");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_uart2_kclk", "uartclk",
|
||||||
|
clkrst3_base, BIT(6), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "uart2");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_sdi5_kclk", "sdmmcclk",
|
||||||
|
clkrst3_base, BIT(7), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "sdi5");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_i2c5_kclk", "i2cclk",
|
||||||
|
clkrst3_base, BIT(8), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.5");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_i2c6_kclk", "i2cclk",
|
||||||
|
clkrst3_base, BIT(9), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "nmk-i2c.6");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_uart3_kclk", "uartclk",
|
||||||
|
clkrst3_base, BIT(10), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "uart3");
|
||||||
|
|
||||||
|
clk = clk_reg_prcc_kclk("p3_uart4_kclk", "uartclk",
|
||||||
|
clkrst3_base, BIT(11), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "uart4");
|
||||||
|
|
||||||
|
/* Peripheral 6 : PRCC K-clocks */
|
||||||
|
clk = clk_reg_prcc_kclk("p6_rng_kclk", "rngclk",
|
||||||
|
clkrst6_base, BIT(0), CLK_SET_RATE_GATE);
|
||||||
|
clk_register_clkdev(clk, NULL, "rng");
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/mfd/dbx500-prcmu.h>
|
#include <linux/mfd/dbx500-prcmu.h>
|
||||||
#include <linux/platform_data/clk-ux500.h>
|
#include <linux/platform_data/clk-ux500.h>
|
||||||
|
|
||||||
#include "clk.h"
|
#include "clk.h"
|
||||||
|
|
||||||
void u9540_clk_init(void)
|
void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||||
|
u32 clkrst5_base, u32 clkrst6_base)
|
||||||
{
|
{
|
||||||
/* register clocks here */
|
/* register clocks here */
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,7 +107,7 @@ void __init vexpress_osc_of_setup(struct device_node *node)
|
||||||
osc->func = vexpress_config_func_get_by_node(node);
|
osc->func = vexpress_config_func_get_by_node(node);
|
||||||
if (!osc->func) {
|
if (!osc->func) {
|
||||||
pr_err("Failed to obtain config func for node '%s'!\n",
|
pr_err("Failed to obtain config func for node '%s'!\n",
|
||||||
node->name);
|
node->full_name);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ void __init vexpress_osc_of_setup(struct device_node *node)
|
||||||
|
|
||||||
of_property_read_string(node, "clock-output-names", &init.name);
|
of_property_read_string(node, "clock-output-names", &init.name);
|
||||||
if (!init.name)
|
if (!init.name)
|
||||||
init.name = node->name;
|
init.name = node->full_name;
|
||||||
|
|
||||||
init.ops = &vexpress_osc_ops;
|
init.ops = &vexpress_osc_ops;
|
||||||
init.flags = CLK_IS_ROOT;
|
init.flags = CLK_IS_ROOT;
|
||||||
|
|
|
@ -480,6 +480,7 @@ struct clk_mgt clk_mgt[PRCMU_NUM_REG_CLOCKS] = {
|
||||||
CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
|
CLK_MGT_ENTRY(PER6CLK, PLL_DIV, true),
|
||||||
CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
|
CLK_MGT_ENTRY(PER7CLK, PLL_DIV, true),
|
||||||
CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
|
CLK_MGT_ENTRY(LCDCLK, PLL_FIX, true),
|
||||||
|
CLK_MGT_ENTRY(BML8580CLK, PLL_DIV, true),
|
||||||
CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
|
CLK_MGT_ENTRY(BMLCLK, PLL_DIV, true),
|
||||||
CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
|
CLK_MGT_ENTRY(HSITXCLK, PLL_DIV, true),
|
||||||
CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
|
CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define PRCM_PER7CLK_MGT (0x040)
|
#define PRCM_PER7CLK_MGT (0x040)
|
||||||
#define PRCM_LCDCLK_MGT (0x044)
|
#define PRCM_LCDCLK_MGT (0x044)
|
||||||
#define PRCM_BMLCLK_MGT (0x04C)
|
#define PRCM_BMLCLK_MGT (0x04C)
|
||||||
|
#define PRCM_BML8580CLK_MGT (0x108)
|
||||||
#define PRCM_HSITXCLK_MGT (0x050)
|
#define PRCM_HSITXCLK_MGT (0x050)
|
||||||
#define PRCM_HSIRXCLK_MGT (0x054)
|
#define PRCM_HSIRXCLK_MGT (0x054)
|
||||||
#define PRCM_HDMICLK_MGT (0x058)
|
#define PRCM_HDMICLK_MGT (0x058)
|
||||||
|
|
|
@ -210,6 +210,10 @@ void of_fixed_clk_setup(struct device_node *np);
|
||||||
* CLK_GATE_SET_TO_DISABLE - by default this clock sets the bit at bit_idx to
|
* CLK_GATE_SET_TO_DISABLE - by default this clock sets the bit at bit_idx to
|
||||||
* enable the clock. Setting this flag does the opposite: setting the bit
|
* enable the clock. Setting this flag does the opposite: setting the bit
|
||||||
* disable the clock and clearing it enables the clock
|
* disable the clock and clearing it enables the clock
|
||||||
|
* CLK_GATE_HIWORD_MASK - The gate settings are only in lower 16-bit
|
||||||
|
* of this register, and mask of gate bits are in higher 16-bit of this
|
||||||
|
* register. While setting the gate bits, higher 16-bit should also be
|
||||||
|
* updated to indicate changing gate bits.
|
||||||
*/
|
*/
|
||||||
struct clk_gate {
|
struct clk_gate {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
@ -220,6 +224,7 @@ struct clk_gate {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CLK_GATE_SET_TO_DISABLE BIT(0)
|
#define CLK_GATE_SET_TO_DISABLE BIT(0)
|
||||||
|
#define CLK_GATE_HIWORD_MASK BIT(1)
|
||||||
|
|
||||||
extern const struct clk_ops clk_gate_ops;
|
extern const struct clk_ops clk_gate_ops;
|
||||||
struct clk *clk_register_gate(struct device *dev, const char *name,
|
struct clk *clk_register_gate(struct device *dev, const char *name,
|
||||||
|
@ -257,6 +262,10 @@ struct clk_div_table {
|
||||||
* Some hardware implementations gracefully handle this case and allow a
|
* Some hardware implementations gracefully handle this case and allow a
|
||||||
* zero divisor by not modifying their input clock
|
* zero divisor by not modifying their input clock
|
||||||
* (divide by one / bypass).
|
* (divide by one / bypass).
|
||||||
|
* CLK_DIVIDER_HIWORD_MASK - The divider settings are only in lower 16-bit
|
||||||
|
* of this register, and mask of divider bits are in higher 16-bit of this
|
||||||
|
* register. While setting the divider bits, higher 16-bit should also be
|
||||||
|
* updated to indicate changing divider bits.
|
||||||
*/
|
*/
|
||||||
struct clk_divider {
|
struct clk_divider {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
@ -271,6 +280,7 @@ struct clk_divider {
|
||||||
#define CLK_DIVIDER_ONE_BASED BIT(0)
|
#define CLK_DIVIDER_ONE_BASED BIT(0)
|
||||||
#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
|
#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
|
||||||
#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
|
#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
|
||||||
|
#define CLK_DIVIDER_HIWORD_MASK BIT(3)
|
||||||
|
|
||||||
extern const struct clk_ops clk_divider_ops;
|
extern const struct clk_ops clk_divider_ops;
|
||||||
struct clk *clk_register_divider(struct device *dev, const char *name,
|
struct clk *clk_register_divider(struct device *dev, const char *name,
|
||||||
|
@ -299,6 +309,10 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
|
||||||
* Flags:
|
* Flags:
|
||||||
* CLK_MUX_INDEX_ONE - register index starts at 1, not 0
|
* CLK_MUX_INDEX_ONE - register index starts at 1, not 0
|
||||||
* CLK_MUX_INDEX_BIT - register index is a single bit (power of two)
|
* CLK_MUX_INDEX_BIT - register index is a single bit (power of two)
|
||||||
|
* CLK_MUX_HIWORD_MASK - The mux settings are only in lower 16-bit of this
|
||||||
|
* register, and mask of mux bits are in higher 16-bit of this register.
|
||||||
|
* While setting the mux bits, higher 16-bit should also be updated to
|
||||||
|
* indicate changing mux bits.
|
||||||
*/
|
*/
|
||||||
struct clk_mux {
|
struct clk_mux {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
@ -312,6 +326,7 @@ struct clk_mux {
|
||||||
|
|
||||||
#define CLK_MUX_INDEX_ONE BIT(0)
|
#define CLK_MUX_INDEX_ONE BIT(0)
|
||||||
#define CLK_MUX_INDEX_BIT BIT(1)
|
#define CLK_MUX_INDEX_BIT BIT(1)
|
||||||
|
#define CLK_MUX_HIWORD_MASK BIT(2)
|
||||||
|
|
||||||
extern const struct clk_ops clk_mux_ops;
|
extern const struct clk_ops clk_mux_ops;
|
||||||
|
|
||||||
|
@ -423,6 +438,17 @@ struct of_device_id;
|
||||||
|
|
||||||
typedef void (*of_clk_init_cb_t)(struct device_node *);
|
typedef void (*of_clk_init_cb_t)(struct device_node *);
|
||||||
|
|
||||||
|
struct clk_onecell_data {
|
||||||
|
struct clk **clks;
|
||||||
|
unsigned int clk_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CLK_OF_DECLARE(name, compat, fn) \
|
||||||
|
static const struct of_device_id __clk_of_table_##name \
|
||||||
|
__used __section(__clk_of_table) \
|
||||||
|
= { .compatible = compat, .data = fn };
|
||||||
|
|
||||||
|
#ifdef CONFIG_OF
|
||||||
int of_clk_add_provider(struct device_node *np,
|
int of_clk_add_provider(struct device_node *np,
|
||||||
struct clk *(*clk_src_get)(struct of_phandle_args *args,
|
struct clk *(*clk_src_get)(struct of_phandle_args *args,
|
||||||
void *data),
|
void *data),
|
||||||
|
@ -430,19 +456,39 @@ int of_clk_add_provider(struct device_node *np,
|
||||||
void of_clk_del_provider(struct device_node *np);
|
void of_clk_del_provider(struct device_node *np);
|
||||||
struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
|
struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec,
|
||||||
void *data);
|
void *data);
|
||||||
struct clk_onecell_data {
|
|
||||||
struct clk **clks;
|
|
||||||
unsigned int clk_num;
|
|
||||||
};
|
|
||||||
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
|
struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data);
|
||||||
const char *of_clk_get_parent_name(struct device_node *np, int index);
|
const char *of_clk_get_parent_name(struct device_node *np, int index);
|
||||||
|
|
||||||
void of_clk_init(const struct of_device_id *matches);
|
void of_clk_init(const struct of_device_id *matches);
|
||||||
|
|
||||||
#define CLK_OF_DECLARE(name, compat, fn) \
|
#else /* !CONFIG_OF */
|
||||||
static const struct of_device_id __clk_of_table_##name \
|
|
||||||
__used __section(__clk_of_table) \
|
|
||||||
= { .compatible = compat, .data = fn };
|
|
||||||
|
|
||||||
|
static inline int of_clk_add_provider(struct device_node *np,
|
||||||
|
struct clk *(*clk_src_get)(struct of_phandle_args *args,
|
||||||
|
void *data),
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define of_clk_del_provider(np) \
|
||||||
|
{ while (0); }
|
||||||
|
static inline struct clk *of_clk_src_simple_get(
|
||||||
|
struct of_phandle_args *clkspec, void *data)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENOENT);
|
||||||
|
}
|
||||||
|
static inline struct clk *of_clk_src_onecell_get(
|
||||||
|
struct of_phandle_args *clkspec, void *data)
|
||||||
|
{
|
||||||
|
return ERR_PTR(-ENOENT);
|
||||||
|
}
|
||||||
|
static inline const char *of_clk_get_parent_name(struct device_node *np,
|
||||||
|
int index)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#define of_clk_init(matches) \
|
||||||
|
{ while (0); }
|
||||||
|
#endif /* CONFIG_OF */
|
||||||
#endif /* CONFIG_COMMON_CLK */
|
#endif /* CONFIG_COMMON_CLK */
|
||||||
#endif /* CLK_PROVIDER_H */
|
#endif /* CLK_PROVIDER_H */
|
||||||
|
|
|
@ -120,9 +120,13 @@ static inline void tegra_cpu_clock_resume(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_ARCH_TEGRA
|
||||||
void tegra_periph_reset_deassert(struct clk *c);
|
void tegra_periph_reset_deassert(struct clk *c);
|
||||||
void tegra_periph_reset_assert(struct clk *c);
|
void tegra_periph_reset_assert(struct clk *c);
|
||||||
void tegra_clocks_init(void);
|
#else
|
||||||
|
static inline void tegra_periph_reset_deassert(struct clk *c) {}
|
||||||
|
static inline void tegra_periph_reset_assert(struct clk *c) {}
|
||||||
|
#endif
|
||||||
void tegra_clocks_apply_init_table(void);
|
void tegra_clocks_apply_init_table(void);
|
||||||
|
|
||||||
#endif /* __LINUX_CLK_TEGRA_H_ */
|
#endif /* __LINUX_CLK_TEGRA_H_ */
|
||||||
|
|
|
@ -278,8 +278,8 @@ struct ab8500_sysctrl_platform_data {
|
||||||
|
|
||||||
#define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0)
|
#define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1)
|
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_MASK 0x0C
|
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL0 BIT(2)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_SHIFT 2
|
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL1 BIT(3)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4)
|
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5)
|
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5)
|
||||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6)
|
#define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6)
|
||||||
|
|
|
@ -134,6 +134,11 @@ enum prcmu_clock {
|
||||||
PRCMU_SIACLK,
|
PRCMU_SIACLK,
|
||||||
PRCMU_SVACLK,
|
PRCMU_SVACLK,
|
||||||
PRCMU_ACLK,
|
PRCMU_ACLK,
|
||||||
|
PRCMU_HVACLK, /* Ux540 only */
|
||||||
|
PRCMU_G1CLK, /* Ux540 only */
|
||||||
|
PRCMU_SDMMCHCLK,
|
||||||
|
PRCMU_CAMCLK,
|
||||||
|
PRCMU_BML8580CLK,
|
||||||
PRCMU_NUM_REG_CLOCKS,
|
PRCMU_NUM_REG_CLOCKS,
|
||||||
PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
|
PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
|
||||||
PRCMU_CDCLK,
|
PRCMU_CDCLK,
|
||||||
|
@ -148,6 +153,13 @@ enum prcmu_clock {
|
||||||
PRCMU_DSI0ESCCLK,
|
PRCMU_DSI0ESCCLK,
|
||||||
PRCMU_DSI1ESCCLK,
|
PRCMU_DSI1ESCCLK,
|
||||||
PRCMU_DSI2ESCCLK,
|
PRCMU_DSI2ESCCLK,
|
||||||
|
/* LCD DSI PLL - Ux540 only */
|
||||||
|
PRCMU_PLLDSI_LCD,
|
||||||
|
PRCMU_DSI0CLK_LCD,
|
||||||
|
PRCMU_DSI1CLK_LCD,
|
||||||
|
PRCMU_DSI0ESCCLK_LCD,
|
||||||
|
PRCMU_DSI1ESCCLK_LCD,
|
||||||
|
PRCMU_DSI2ESCCLK_LCD,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
|
|
||||||
void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
void u8500_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||||
u32 clkrst5_base, u32 clkrst6_base);
|
u32 clkrst5_base, u32 clkrst6_base);
|
||||||
void u9540_clk_init(void);
|
void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||||
void u8540_clk_init(void);
|
u32 clkrst5_base, u32 clkrst6_base);
|
||||||
|
void u8540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||||
|
u32 clkrst5_base, u32 clkrst6_base);
|
||||||
|
|
||||||
#endif /* __CLK_UX500_H */
|
#endif /* __CLK_UX500_H */
|
||||||
|
|
|
@ -78,6 +78,23 @@ enum si5351_drive_strength {
|
||||||
SI5351_DRIVE_8MA = 8,
|
SI5351_DRIVE_8MA = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum si5351_disable_state - Si5351 clock output disable state
|
||||||
|
* @SI5351_DISABLE_DEFAULT: default, do not change eeprom config
|
||||||
|
* @SI5351_DISABLE_LOW: CLKx is set to a LOW state when disabled
|
||||||
|
* @SI5351_DISABLE_HIGH: CLKx is set to a HIGH state when disabled
|
||||||
|
* @SI5351_DISABLE_FLOATING: CLKx is set to a FLOATING state when
|
||||||
|
* disabled
|
||||||
|
* @SI5351_DISABLE_NEVER: CLKx is NEVER disabled
|
||||||
|
*/
|
||||||
|
enum si5351_disable_state {
|
||||||
|
SI5351_DISABLE_DEFAULT = 0,
|
||||||
|
SI5351_DISABLE_LOW,
|
||||||
|
SI5351_DISABLE_HIGH,
|
||||||
|
SI5351_DISABLE_FLOATING,
|
||||||
|
SI5351_DISABLE_NEVER,
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct si5351_clkout_config - Si5351 clock output configuration
|
* struct si5351_clkout_config - Si5351 clock output configuration
|
||||||
* @clkout: clkout number
|
* @clkout: clkout number
|
||||||
|
@ -91,6 +108,7 @@ struct si5351_clkout_config {
|
||||||
enum si5351_multisynth_src multisynth_src;
|
enum si5351_multisynth_src multisynth_src;
|
||||||
enum si5351_clkout_src clkout_src;
|
enum si5351_clkout_src clkout_src;
|
||||||
enum si5351_drive_strength drive;
|
enum si5351_drive_strength drive;
|
||||||
|
enum si5351_disable_state disable_state;
|
||||||
bool pll_master;
|
bool pll_master;
|
||||||
unsigned long rate;
|
unsigned long rate;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue