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
|
@ -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>;
|
||||
};
|
|
@ -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
|
||||
divider.
|
||||
- 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==
|
||||
|
||||
|
|
|
@ -12,22 +12,30 @@ Required properties:
|
|||
"allwinner,sun4i-axi-clk" - for the AXI clock
|
||||
"allwinner,sun4i-axi-gates-clk" - for the AXI gates
|
||||
"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-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-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:
|
||||
- reg : shall be the control register address 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
|
||||
"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 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:
|
||||
|
||||
osc24M: osc24M@01c20050 {
|
||||
|
@ -50,102 +58,3 @@ cpu: cpu@01c20054 {
|
|||
reg = <0x01c20054 0x4>;
|
||||
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:
|
||||
"via,vt8500-pll-clock" - for a VT8500/WM8505 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
|
||||
|
||||
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)
|
||||
T: git git://git.linaro.org/people/mturquette/linux.git
|
||||
S: Maintained
|
||||
F: drivers/clk/clk.c
|
||||
F: drivers/clk/clk-*
|
||||
F: drivers/clk/
|
||||
X: drivers/clk/clkdev.c
|
||||
F: include/linux/clk-pr*
|
||||
F: include/linux/clk/
|
||||
|
||||
COMMON INTERNET FILE SYSTEM (CIFS)
|
||||
M: Steve French <sfrench@samba.org>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/irqchip.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
#include <linux/clk-provider.h>
|
||||
|
||||
#include <asm/hardware/cache-l2x0.h>
|
||||
|
||||
|
@ -60,7 +60,7 @@ u32 tegra_uart_config[4] = {
|
|||
#ifdef CONFIG_OF
|
||||
void __init tegra_dt_init_irq(void)
|
||||
{
|
||||
tegra_clocks_init();
|
||||
of_clk_init(NULL);
|
||||
tegra_pmc_init();
|
||||
tegra_init_irq();
|
||||
irqchip_init();
|
||||
|
|
|
@ -76,13 +76,15 @@ void __init ux500_init_irq(void)
|
|||
} else if (cpu_is_u9540()) {
|
||||
prcmu_early_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_CLKRST6_BASE);
|
||||
} else if (cpu_is_u8540()) {
|
||||
prcmu_early_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
|
||||
bool "e500mc Support"
|
||||
select PPC_FPU
|
||||
select COMMON_CLK
|
||||
depends on E500
|
||||
help
|
||||
This must be enabled for running on e500mc (and derivatives
|
||||
|
|
|
@ -42,7 +42,7 @@ config COMMON_CLK_WM831X
|
|||
|
||||
config COMMON_CLK_VERSATILE
|
||||
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---
|
||||
Supports clocking on ARM Reference designs:
|
||||
- Integrator/AP and Integrator/CP
|
||||
|
@ -58,7 +58,6 @@ config COMMON_CLK_MAX77686
|
|||
config COMMON_CLK_SI5351
|
||||
tristate "Clock driver for SiLabs 5351A/B/C"
|
||||
depends on I2C
|
||||
depends on OF
|
||||
select REGMAP_I2C
|
||||
select RATIONAL
|
||||
---help---
|
||||
|
@ -81,6 +80,13 @@ config COMMON_CLK_AXI_CLKGEN
|
|||
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
|
||||
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
|
||||
|
||||
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_NOMADIK) += clk-nomadik.o
|
||||
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
|
||||
obj-$(CONFIG_ARCH_MXS) += mxs/
|
||||
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
|
||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||
|
@ -24,6 +25,7 @@ ifeq ($(CONFIG_COMMON_CLK), y)
|
|||
obj-$(CONFIG_ARCH_MMP) += mmp/
|
||||
endif
|
||||
obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||
obj-$(CONFIG_ARCH_SUNXI) += sunxi/
|
||||
obj-$(CONFIG_ARCH_U8500) += ux500/
|
||||
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_SI5351) += clk-si5351.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);
|
||||
int i, bestdiv = 0;
|
||||
unsigned long parent_rate, best = 0, now, maxdiv;
|
||||
unsigned long parent_rate_saved = *best_parent_rate;
|
||||
|
||||
if (!rate)
|
||||
rate = 1;
|
||||
|
@ -173,6 +174,15 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
|
|||
for (i = 1; i <= maxdiv; i++) {
|
||||
if (!_is_valid_div(divider, i))
|
||||
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),
|
||||
MULT_ROUND_UP(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)
|
||||
spin_lock_irqsave(divider->lock, flags);
|
||||
|
||||
val = readl(divider->reg);
|
||||
val &= ~(div_mask(divider) << divider->shift);
|
||||
if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
|
||||
val = div_mask(divider) << (divider->shift + 16);
|
||||
} else {
|
||||
val = readl(divider->reg);
|
||||
val &= ~(div_mask(divider) << divider->shift);
|
||||
}
|
||||
val |= value << divider->shift;
|
||||
writel(val, divider->reg);
|
||||
|
||||
|
@ -245,6 +259,13 @@ static struct clk *_register_divider(struct device *dev, const char *name,
|
|||
struct clk *clk;
|
||||
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 */
|
||||
div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL);
|
||||
if (!div) {
|
||||
|
|
|
@ -53,12 +53,18 @@ static void clk_gate_endisable(struct clk_hw *hw, int enable)
|
|||
if (gate->lock)
|
||||
spin_lock_irqsave(gate->lock, flags);
|
||||
|
||||
reg = readl(gate->reg);
|
||||
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);
|
||||
|
||||
if (set)
|
||||
reg |= BIT(gate->bit_idx);
|
||||
else
|
||||
reg &= ~BIT(gate->bit_idx);
|
||||
if (set)
|
||||
reg |= BIT(gate->bit_idx);
|
||||
else
|
||||
reg &= ~BIT(gate->bit_idx);
|
||||
}
|
||||
|
||||
writel(reg, gate->reg);
|
||||
|
||||
|
@ -121,6 +127,13 @@ struct clk *clk_register_gate(struct device *dev, const char *name,
|
|||
struct clk *clk;
|
||||
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 */
|
||||
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
|
||||
if (!gate) {
|
||||
|
|
|
@ -86,8 +86,12 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
|||
if (mux->lock)
|
||||
spin_lock_irqsave(mux->lock, flags);
|
||||
|
||||
val = readl(mux->reg);
|
||||
val &= ~(mux->mask << mux->shift);
|
||||
if (mux->flags & CLK_MUX_HIWORD_MASK) {
|
||||
val = mux->mask << (mux->shift + 16);
|
||||
} else {
|
||||
val = readl(mux->reg);
|
||||
val &= ~(mux->mask << mux->shift);
|
||||
}
|
||||
val |= index << mux->shift;
|
||||
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 *clk;
|
||||
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 */
|
||||
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
|
||||
|
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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))
|
||||
pdata->clkout[num].rate = val;
|
||||
|
||||
|
@ -1281,9 +1343,6 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|||
|
||||
/* Disable interrupts */
|
||||
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 */
|
||||
if (drvdata->variant != SI5351_VARIANT_C)
|
||||
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);
|
||||
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 */
|
||||
|
@ -1500,7 +1568,10 @@ static int si5351_i2c_probe(struct i2c_client *client,
|
|||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -81,6 +81,7 @@
|
|||
|
||||
#define SI5351_CLK3_0_DISABLE_STATE 24
|
||||
#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_HIGH 1
|
||||
#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))
|
||||
return PTR_ERR(clkdata->clk);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, clkdata);
|
||||
platform_set_drvdata(pdev, clkdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ struct clk_device {
|
|||
#define PLL_TYPE_VT8500 0
|
||||
#define PLL_TYPE_WM8650 1
|
||||
#define PLL_TYPE_WM8750 2
|
||||
#define PLL_TYPE_WM8850 3
|
||||
|
||||
struct clk_pll {
|
||||
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;
|
||||
|
||||
/* If prate / rate would be decimal, incr the divisor */
|
||||
if (rate * divisor < parent_rate)
|
||||
divisor++;
|
||||
|
||||
if (divisor == cdev->div_mask + 1)
|
||||
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) \
|
||||
((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,
|
||||
u32 *multiplier, u32 *prediv)
|
||||
|
@ -466,6 +472,49 @@ static void wm8750_find_pll_bits(unsigned long rate, unsigned long parent_rate,
|
|||
*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,
|
||||
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);
|
||||
pll_val = WM8750_BITS_TO_VAL(filter, mul, div1, div2);
|
||||
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:
|
||||
pr_err("%s: invalid pll type\n", __func__);
|
||||
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);
|
||||
round_rate = WM8750_BITS_TO_FREQ(*prate, mul, div1, div2);
|
||||
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:
|
||||
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 /= WM8750_PLL_DIV(pll_val);
|
||||
break;
|
||||
case PLL_TYPE_WM8850:
|
||||
pll_freq = parent_rate * WM8850_PLL_MUL(pll_val);
|
||||
pll_freq /= WM8850_PLL_DIV(pll_val);
|
||||
break;
|
||||
default:
|
||||
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);
|
||||
|
||||
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)
|
||||
{
|
||||
if (!base)
|
||||
|
|
|
@ -97,7 +97,7 @@ static int wm831x_fll_prepare(struct clk_hw *hw)
|
|||
struct wm831x *wm831x = clkdata->wm831x;
|
||||
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);
|
||||
if (ret != 0)
|
||||
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;
|
||||
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)
|
||||
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,
|
||||
|
@ -299,8 +299,8 @@ static void wm831x_clkout_unprepare(struct clk_hw *hw)
|
|||
}
|
||||
|
||||
static const char *wm831x_clkout_parents[] = {
|
||||
"xtal",
|
||||
"fll",
|
||||
"xtal",
|
||||
};
|
||||
|
||||
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)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
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))
|
||||
return PTR_ERR(clkdata->clkout);
|
||||
|
||||
dev_set_drvdata(&pdev->dev, clkdata);
|
||||
platform_set_drvdata(pdev, clkdata);
|
||||
|
||||
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",
|
||||
level * 3 + 1, "",
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -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, "\"enable_count\": %d,", c->enable_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)
|
||||
|
@ -534,7 +534,7 @@ static int clk_disable_unused(void)
|
|||
|
||||
return 0;
|
||||
}
|
||||
late_initcall(clk_disable_unused);
|
||||
late_initcall_sync(clk_disable_unused);
|
||||
|
||||
/*** helper functions ***/
|
||||
|
||||
|
@ -1216,7 +1216,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
|||
clk_prepare_lock();
|
||||
|
||||
/* bail early if nothing to do */
|
||||
if (rate == clk->rate)
|
||||
if (rate == clk_get_rate(clk))
|
||||
goto out;
|
||||
|
||||
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;
|
||||
int ret = 0;
|
||||
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);
|
||||
|
||||
flags = clk_enable_lock();
|
||||
|
||||
/* migrate enable */
|
||||
if (clk->enable_count) {
|
||||
__clk_enable(parent);
|
||||
migrated_enable = true;
|
||||
clk_enable(parent);
|
||||
clk_enable(clk);
|
||||
}
|
||||
|
||||
/* update the clk tree topology */
|
||||
flags = clk_enable_lock();
|
||||
clk_reparent(clk, parent);
|
||||
|
||||
clk_enable_unlock(flags);
|
||||
|
||||
/* 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);
|
||||
|
||||
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();
|
||||
|
||||
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);
|
||||
|
||||
if (clk->prepare_count)
|
||||
if (clk->prepare_count) {
|
||||
clk_disable(clk);
|
||||
clk_disable(parent);
|
||||
__clk_unprepare(parent);
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* clean up enable for old parent if migration was done */
|
||||
if (migrated_enable) {
|
||||
flags = clk_enable_lock();
|
||||
__clk_disable(old_parent);
|
||||
clk_enable_unlock(flags);
|
||||
}
|
||||
|
||||
/* clean up prepare for old parent if migration was done */
|
||||
if (clk->prepare_count)
|
||||
/*
|
||||
* Finish the migration of prepare state and undo the changes done
|
||||
* for preventing a race with clk_enable().
|
||||
*/
|
||||
if (clk->prepare_count) {
|
||||
clk_disable(clk);
|
||||
clk_disable(old_parent);
|
||||
__clk_unprepare(old_parent);
|
||||
}
|
||||
|
||||
/* update debugfs with new clk tree topology */
|
||||
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
|
||||
* @parent: the new input to clk
|
||||
*
|
||||
* Re-parent clk to use parent as it's new input source. If clk has the
|
||||
* CLK_SET_PARENT_GATE flag set then clk must be gated for this
|
||||
* operation to succeed. 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.
|
||||
* Re-parent clk to use parent as its new input source. If clk is in
|
||||
* prepared state, the clk will get enabled for the duration of this call. If
|
||||
* that's not acceptable for a specific clk (Eg: the consumer can't handle
|
||||
* that, the reparenting is glitchy in hardware, etc), use the
|
||||
* CLK_SET_PARENT_GATE flag to allow reparenting only when clk is unprepared.
|
||||
*
|
||||
* 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)
|
||||
{
|
||||
|
@ -1494,8 +1493,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
|
|||
}
|
||||
|
||||
/* 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 */
|
||||
if (ret & NOTIFY_STOP_MASK)
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
# Rockchip Clock specific Makefile
|
||||
#
|
||||
|
||||
obj-y += clk-rockchip.o
|
|
@ -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 */
|
||||
struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
|
||||
MUX_F(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT, 0),
|
||||
MUX_FA(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT, 0, "mout_apll"),
|
||||
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_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_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 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,
|
||||
SRC_CPU, 16, 1, "mout_core"),
|
||||
SRC_CPU, 16, 1, "moutcore"),
|
||||
MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
|
||||
SRC_TOP0, 8, 1, "sclk_vpll"),
|
||||
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 */
|
||||
struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
|
||||
MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
|
||||
SRC_CPU, 24, 1),
|
||||
MUX_A(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
|
||||
SRC_CPU, 24, 1, "mout_mpll"),
|
||||
MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 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,
|
||||
|
@ -449,7 +449,8 @@ struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
|
|||
SRC_DMC, 12, 1, "sclk_mpll"),
|
||||
MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
|
||||
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_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 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_audio1", "mout_audio1", DIV_PERIL4, 0, 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_CPU0, 24, 3, "sclk_apll"),
|
||||
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"
|
||||
"\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
|
||||
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("arm_clk"));
|
||||
_get_rate("armclk"));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -144,6 +144,9 @@ struct samsung_mux_clock {
|
|||
#define MUX_F(_id, cname, pnames, o, s, w, f, mf) \
|
||||
__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.
|
||||
* struct samsung_div_clock: information about div clock
|
||||
|
|
|
@ -239,7 +239,7 @@ struct mux_data {
|
|||
u8 shift;
|
||||
};
|
||||
|
||||
static const __initconst struct mux_data cpu_data = {
|
||||
static const __initconst struct mux_data cpu_mux_data = {
|
||||
.shift = 16,
|
||||
};
|
||||
|
||||
|
@ -333,22 +333,34 @@ struct gates_data {
|
|||
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},
|
||||
};
|
||||
|
||||
static const __initconst struct gates_data ahb_gates_data = {
|
||||
static const __initconst struct gates_data sun4i_ahb_gates_data = {
|
||||
.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},
|
||||
};
|
||||
|
||||
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},
|
||||
};
|
||||
|
||||
static const __initconst struct gates_data sun5i_a13_apb1_gates_data = {
|
||||
.mask = {0xa0007},
|
||||
};
|
||||
|
||||
static void __init sunxi_gates_clk_setup(struct device_node *node,
|
||||
struct gates_data *data)
|
||||
{
|
||||
|
@ -421,17 +433,20 @@ static const __initconst struct of_device_id clk_div_match[] = {
|
|||
|
||||
/* Matches for mux clocks */
|
||||
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,},
|
||||
{}
|
||||
};
|
||||
|
||||
/* Matches for gate clocks */
|
||||
static const __initconst struct of_device_id clk_gates_match[] = {
|
||||
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &axi_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-apb0-gates-clk", .data = &apb0_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-apb1-gates-clk", .data = &apb1_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-axi-gates-clk", .data = &sun4i_axi_gates_data,},
|
||||
{.compatible = "allwinner,sun4i-ahb-gates-clk", .data = &sun4i_ahb_gates_data,},
|
||||
{.compatible = "allwinner,sun5i-a13-ahb-gates-clk", .data = &sun5i_a13_ahb_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_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_PLLE_IDDQ_VALUE BIT(5)
|
||||
#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_base(p) pll_readl(p->params->base_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_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_override_writel(val, offset, p) writel(val, p->pmc + offset)
|
||||
|
||||
#define mask(w) ((1 << (w)) - 1)
|
||||
#define divm_mask(p) mask(p->divm_width)
|
||||
#define divn_mask(p) mask(p->divn_width)
|
||||
#define divm_mask(p) mask(p->params->div_nmp->divm_width)
|
||||
#define divn_mask(p) mask(p->params->div_nmp->divn_width)
|
||||
#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 divn_max(p) (divn_mask(p))
|
||||
#define divp_max(p) (1 << (divp_mask(p)))
|
||||
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA_114_SOC
|
||||
/* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */
|
||||
#define PLLXC_PDIV_MAX 14
|
||||
|
||||
/* non-monotonic mapping below is not a typo */
|
||||
static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = {
|
||||
/* 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
|
||||
static struct div_nmp default_nmp = {
|
||||
.divn_shift = PLL_BASE_DIVN_SHIFT,
|
||||
.divn_width = PLL_BASE_DIVN_WIDTH,
|
||||
.divm_shift = PLL_BASE_DIVM_SHIFT,
|
||||
.divm_width = PLL_BASE_DIVM_WIDTH,
|
||||
.divp_shift = PLL_BASE_DIVP_SHIFT,
|
||||
.divp_width = PLL_BASE_DIVP_WIDTH,
|
||||
};
|
||||
|
||||
#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)
|
||||
{
|
||||
u32 val;
|
||||
|
@ -297,6 +286,39 @@ static void clk_pll_disable(struct clk_hw *hw)
|
|||
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,
|
||||
struct tegra_clk_pll_freq_table *cfg,
|
||||
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)
|
||||
{
|
||||
struct tegra_clk_pll *pll = to_clk_pll(hw);
|
||||
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
||||
unsigned long cfreq;
|
||||
u32 p_div = 0;
|
||||
int ret;
|
||||
|
||||
switch (parent_rate) {
|
||||
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) {
|
||||
pr_err("%s: Failed to set %s rate %lu\n",
|
||||
__func__, __clk_get_name(hw->clk), rate);
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (p_tohw) {
|
||||
p_div = 1 << p_div;
|
||||
while (p_tohw->pdiv) {
|
||||
if (p_div <= p_tohw->pdiv) {
|
||||
cfg->p = p_tohw->hw_val;
|
||||
break;
|
||||
}
|
||||
p_tohw++;
|
||||
}
|
||||
if (!p_tohw->pdiv)
|
||||
return -EINVAL;
|
||||
if (pll->params->pdiv_tohw) {
|
||||
ret = _p_div_to_hw(hw, 1 << p_div);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
else
|
||||
cfg->p = ret;
|
||||
} else
|
||||
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)
|
||||
{
|
||||
u32 val;
|
||||
struct tegra_clk_pll_params *params = pll->params;
|
||||
struct div_nmp *div_nmp = params->div_nmp;
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
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 &= ~((divm_mask(pll) << pll->divm_shift) |
|
||||
(divn_mask(pll) << pll->divn_shift) |
|
||||
(divp_mask(pll) << pll->divp_shift));
|
||||
val |= ((cfg->m << pll->divm_shift) |
|
||||
(cfg->n << pll->divn_shift) |
|
||||
(cfg->p << pll->divp_shift));
|
||||
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);
|
||||
|
||||
pll_writel_base(val, pll);
|
||||
val &= ~((divm_mask(pll) << div_nmp->divm_shift) |
|
||||
(divn_mask(pll) << div_nmp->divn_shift) |
|
||||
(divp_mask(pll) << div_nmp->divp_shift));
|
||||
|
||||
val |= ((cfg->m << div_nmp->divm_shift) |
|
||||
(cfg->n << div_nmp->divn_shift) |
|
||||
(cfg->p << div_nmp->divp_shift));
|
||||
|
||||
pll_writel_base(val, pll);
|
||||
}
|
||||
}
|
||||
|
||||
static void _get_pll_mnp(struct tegra_clk_pll *pll,
|
||||
struct tegra_clk_pll_freq_table *cfg)
|
||||
{
|
||||
u32 val;
|
||||
struct tegra_clk_pll_params *params = pll->params;
|
||||
struct div_nmp *div_nmp = params->div_nmp;
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
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);
|
||||
|
||||
cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
|
||||
cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
|
||||
cfg->p = (val >> pll->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);
|
||||
|
||||
cfg->m = (val >> div_nmp->divm_shift) & divm_mask(pll);
|
||||
cfg->n = (val >> div_nmp->divn_shift) & divn_mask(pll);
|
||||
cfg->p = (val >> div_nmp->divp_shift) & divp_mask(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) &&
|
||||
_calc_rate(hw, &cfg, rate, parent_rate))
|
||||
_calc_rate(hw, &cfg, rate, parent_rate)) {
|
||||
WARN_ON(1);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
if (pll->lock)
|
||||
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_freq_table cfg;
|
||||
u64 output_rate = *prate;
|
||||
|
||||
if (pll->flags & TEGRA_PLL_FIXED)
|
||||
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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
output_rate *= cfg.n;
|
||||
do_div(output_rate, cfg.m * (1 << cfg.p));
|
||||
|
||||
return output_rate;
|
||||
return cfg.output_rate;
|
||||
}
|
||||
|
||||
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_freq_table cfg;
|
||||
struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
|
||||
u32 val;
|
||||
u64 rate = parent_rate;
|
||||
int pdiv;
|
||||
|
@ -553,21 +601,11 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
|
|||
|
||||
_get_pll_mnp(pll, &cfg);
|
||||
|
||||
if (p_tohw) {
|
||||
while (p_tohw->pdiv) {
|
||||
if (cfg.p == p_tohw->hw_val) {
|
||||
pdiv = p_tohw->pdiv;
|
||||
break;
|
||||
}
|
||||
p_tohw++;
|
||||
}
|
||||
|
||||
if (!p_tohw->pdiv) {
|
||||
WARN_ON(1);
|
||||
pdiv = 1;
|
||||
}
|
||||
} else
|
||||
pdiv = 1 << cfg.p;
|
||||
pdiv = _hw_to_p_div(hw, cfg.p);
|
||||
if (pdiv < 0) {
|
||||
WARN_ON(1);
|
||||
pdiv = 1;
|
||||
}
|
||||
|
||||
cfg.m *= pdiv;
|
||||
|
||||
|
@ -647,9 +685,9 @@ static int clk_plle_enable(struct clk_hw *hw)
|
|||
val = pll_readl_base(pll);
|
||||
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
||||
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
||||
val |= sel.m << pll->divm_shift;
|
||||
val |= sel.n << pll->divn_shift;
|
||||
val |= sel.p << pll->divp_shift;
|
||||
val |= sel.m << pll->params->div_nmp->divm_shift;
|
||||
val |= sel.n << pll->params->div_nmp->divn_shift;
|
||||
val |= sel.p << pll->params->div_nmp->divp_shift;
|
||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
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;
|
||||
u64 rate = parent_rate;
|
||||
|
||||
divp = (val >> pll->divp_shift) & (divp_mask(pll));
|
||||
divn = (val >> pll->divn_shift) & (divn_mask(pll));
|
||||
divm = (val >> pll->divm_shift) & (divm_mask(pll));
|
||||
divp = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll));
|
||||
divn = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll));
|
||||
divm = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll));
|
||||
divm *= divp;
|
||||
|
||||
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);
|
||||
unsigned int p;
|
||||
int p_div;
|
||||
|
||||
if (!rate)
|
||||
return -EINVAL;
|
||||
|
||||
p = DIV_ROUND_UP(pll->params->vco_min, rate);
|
||||
cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
|
||||
cfg->p = p;
|
||||
cfg->output_rate = rate * cfg->p;
|
||||
cfg->output_rate = rate * p;
|
||||
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)
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -790,18 +834,25 @@ static int _pll_ramp_calc_pll(struct clk_hw *hw,
|
|||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
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);
|
||||
if (err < 0)
|
||||
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);
|
||||
err = -EINVAL;
|
||||
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;
|
||||
|
||||
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;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
u8 old_p;
|
||||
|
||||
ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
|
||||
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);
|
||||
|
||||
old_p = pllxc_p[old_cfg.p];
|
||||
if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_p != cfg.p) {
|
||||
cfg.p -= 1;
|
||||
if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
|
||||
ret = _program_pll(hw, &cfg, rate);
|
||||
}
|
||||
|
||||
if (pll->lock)
|
||||
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)
|
||||
{
|
||||
struct tegra_clk_pll_freq_table cfg;
|
||||
int ret = 0;
|
||||
int ret = 0, p_div;
|
||||
u64 output_rate = *prate;
|
||||
|
||||
ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
p_div = _hw_to_p_div(hw, cfg.p);
|
||||
if (p_div < 0)
|
||||
return p_div;
|
||||
|
||||
output_rate *= cfg.n;
|
||||
do_div(output_rate, cfg.m * cfg.p);
|
||||
do_div(output_rate, cfg.m * p_div);
|
||||
|
||||
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);
|
||||
unsigned long flags = 0;
|
||||
int state, ret = 0;
|
||||
u32 val;
|
||||
|
||||
if (pll->lock)
|
||||
spin_lock_irqsave(pll->lock, flags);
|
||||
|
@ -881,22 +931,7 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
if (ret < 0)
|
||||
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:
|
||||
if (pll->lock)
|
||||
|
@ -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,
|
||||
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);
|
||||
unsigned long flags = 0;
|
||||
int state, ret = 0;
|
||||
u32 val;
|
||||
u16 old_m, old_n;
|
||||
u8 old_p;
|
||||
|
||||
if (pll->lock)
|
||||
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)
|
||||
goto out;
|
||||
|
||||
val = pll_readl_base(pll);
|
||||
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))];
|
||||
_get_pll_mnp(pll, &old_cfg);
|
||||
|
||||
if (cfg.m != old_m) {
|
||||
if (cfg.m != old_cfg.m) {
|
||||
WARN_ON(1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (old_n == cfg.n && old_p == cfg.p)
|
||||
if (old_cfg.n == cfg.n && old_cfg.p == cfg.p)
|
||||
goto out;
|
||||
|
||||
cfg.p -= 1;
|
||||
|
||||
state = clk_pll_is_enabled(hw);
|
||||
if (state)
|
||||
_clk_pllc_disable(hw);
|
||||
|
@ -1178,8 +1205,8 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw)
|
|||
val = pll_readl_base(pll);
|
||||
val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
|
||||
val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
|
||||
val |= sel.m << pll->divm_shift;
|
||||
val |= sel.n << pll->divn_shift;
|
||||
val |= sel.m << pll->params->div_nmp->divm_shift;
|
||||
val |= sel.n << pll->params->div_nmp->divn_shift;
|
||||
val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
|
||||
pll_writel_base(val, pll);
|
||||
udelay(1);
|
||||
|
@ -1240,12 +1267,8 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
|
|||
pll->flags = pll_flags;
|
||||
pll->lock = lock;
|
||||
|
||||
pll->divp_shift = PLL_BASE_DIVP_SHIFT;
|
||||
pll->divp_width = PLL_BASE_DIVP_WIDTH;
|
||||
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;
|
||||
if (!pll_params->div_nmp)
|
||||
pll_params->div_nmp = &default_nmp;
|
||||
|
||||
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 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,
|
||||
freq_table, lock);
|
||||
if (IS_ERR(pll))
|
||||
|
@ -1428,7 +1451,6 @@ struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
|
|||
val &= ~BIT(29);
|
||||
pll_writel_misc(val, pll);
|
||||
|
||||
pll_flags |= TEGRA_PLL_LOCK_MISC;
|
||||
clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
|
||||
&tegra_clk_pllre_ops);
|
||||
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_HAS_LOCK_ENABLE;
|
||||
pll_flags |= TEGRA_PLLM;
|
||||
pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
|
||||
freq_table, lock);
|
||||
if (IS_ERR(pll))
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/clk/tegra.h>
|
||||
|
||||
#include "clk.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
#define RST_DEVICES_L 0x004
|
||||
#define RST_DEVICES_H 0x008
|
||||
#define RST_DEVICES_U 0x00C
|
||||
#define RST_DFLL_DVCO 0x2F4
|
||||
#define RST_DEVICES_V 0x358
|
||||
#define RST_DEVICES_W 0x35C
|
||||
#define RST_DEVICES_X 0x28C
|
||||
|
@ -41,8 +43,36 @@
|
|||
#define RST_DEVICES_CLR_V 0x434
|
||||
#define RST_DEVICES_SET_W 0x438
|
||||
#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
|
||||
|
||||
/* 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_H 0x014
|
||||
#define CLK_OUT_ENB_U 0x018
|
||||
|
@ -127,6 +157,7 @@
|
|||
#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
|
||||
#define PMC_CTRL 0
|
||||
#define PMC_CTRL_BLINK_ENB 7
|
||||
#define PMC_BLINK_TIMER 0x40
|
||||
|
||||
#define OSC_CTRL 0x50
|
||||
#define OSC_CTRL_OSC_FREQ_SHIFT 28
|
||||
|
@ -242,6 +273,8 @@
|
|||
#define CLK_SOURCE_I2CSLOW 0x3fc
|
||||
#define CLK_SOURCE_SE 0x42c
|
||||
#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_XUSB_HOST_SRC 0x600
|
||||
#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
|
||||
|
@ -250,6 +283,10 @@
|
|||
#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
|
||||
#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 */
|
||||
#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(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[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
|
@ -315,6 +361,16 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.stepa_shift = 17,
|
||||
.stepb_shift = 9,
|
||||
.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[] = {
|
||||
|
@ -348,6 +404,8 @@ static struct tegra_clk_pll_params pll_c2_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.pdiv_tohw = pllc_p,
|
||||
.div_nmp = &pllcx_nmp,
|
||||
.max_p = 7,
|
||||
.ext_misc_reg[0] = 0x4f0,
|
||||
.ext_misc_reg[1] = 0x4f4,
|
||||
.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_delay = 300,
|
||||
.pdiv_tohw = pllc_p,
|
||||
.div_nmp = &pllcx_nmp,
|
||||
.max_p = 7,
|
||||
.ext_misc_reg[0] = 0x504,
|
||||
.ext_misc_reg[1] = 0x508,
|
||||
.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[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
|
@ -400,6 +472,18 @@ static struct tegra_clk_pll_params pll_m_params = {
|
|||
.lock_delay = 300,
|
||||
.max_p = 2,
|
||||
.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[] = {
|
||||
|
@ -423,6 +507,7 @@ static struct tegra_clk_pll_params pll_p_params = {
|
|||
.lock_mask = PLL_BASE_LOCK,
|
||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.div_nmp = &pllp_nmp,
|
||||
};
|
||||
|
||||
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_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.div_nmp = &pllp_nmp,
|
||||
};
|
||||
|
||||
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_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 1000,
|
||||
.div_nmp = &pllp_nmp,
|
||||
};
|
||||
|
||||
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_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 1000,
|
||||
.div_nmp = &pllp_nmp,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllu_p[] = {
|
||||
|
@ -506,6 +594,15 @@ static struct pdiv_map pllu_p[] = {
|
|||
{ .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[] = {
|
||||
{12000000, 480000000, 960, 12, 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_delay = 1000,
|
||||
.pdiv_tohw = pllu_p,
|
||||
.div_nmp = &pllu_nmp,
|
||||
};
|
||||
|
||||
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,
|
||||
.stepb_shift = 24,
|
||||
.pdiv_tohw = pllxc_p,
|
||||
.div_nmp = &pllxc_nmp,
|
||||
};
|
||||
|
||||
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},
|
||||
};
|
||||
|
||||
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 = {
|
||||
.input_min = 12000000,
|
||||
.input_max = 1000000000,
|
||||
|
@ -582,6 +690,16 @@ static struct tegra_clk_pll_params pll_e_params = {
|
|||
.lock_mask = PLLE_MISC_LOCK,
|
||||
.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
|
||||
.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 = {
|
||||
|
@ -598,6 +716,7 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
|
|||
.lock_delay = 300,
|
||||
.iddq_reg = PLLRE_MISC,
|
||||
.iddq_bit_idx = PLLRE_IDDQ_BIT,
|
||||
.div_nmp = &pllre_nmp,
|
||||
};
|
||||
|
||||
/* Peripheral clock registers */
|
||||
|
@ -765,6 +884,7 @@ enum tegra114_clk {
|
|||
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,
|
||||
xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
|
||||
dfll_ref = 264, dfll_soc,
|
||||
|
||||
/* Mux clocks */
|
||||
|
||||
|
@ -1202,8 +1322,8 @@ static void __init tegra114_pll_init(void __iomem *clk_base,
|
|||
/* PLLP_OUT2 */
|
||||
clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
|
||||
clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
|
||||
TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
|
||||
&pll_div_lock);
|
||||
TEGRA_DIVIDER_ROUND_UP | TEGRA_DIVIDER_INT, 24,
|
||||
8, 1, &pll_div_lock);
|
||||
clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
|
||||
clk_base + PLLP_OUTA, 17, 16,
|
||||
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 = 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,
|
||||
&clk_out_lock);
|
||||
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 = 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,
|
||||
&clk_out_lock);
|
||||
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;
|
||||
|
||||
/* 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,
|
||||
pmc_base + PMC_DPD_PADS_ORIDE,
|
||||
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",
|
||||
"pll_p_out3", "pll_p_out2", "unused",
|
||||
"pll_p", "pll_p_out2", "unused",
|
||||
"clk_32k", "pll_m_out1" };
|
||||
|
||||
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_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("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("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),
|
||||
|
@ -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_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_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_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),
|
||||
|
@ -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[] = {
|
||||
{uarta, 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},
|
||||
{i2s3, 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. */
|
||||
};
|
||||
|
||||
|
@ -2051,7 +2181,132 @@ static void __init tegra114_clock_apply_init_table(void)
|
|||
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;
|
||||
int i;
|
||||
|
@ -2104,3 +2359,4 @@ void __init tegra114_clock_init(struct device_node *np)
|
|||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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_BURST_POLICY_PLLX 8
|
||||
|
||||
/* PLLM override registers */
|
||||
#define PMC_PLLM_WB0_OVERRIDE 0x1dc
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static struct cpu_clk_suspend_context {
|
||||
u32 pllx_misc;
|
||||
|
@ -563,6 +566,18 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.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 = {
|
||||
.input_min = 2000000,
|
||||
.input_max = 31000000,
|
||||
|
@ -575,6 +590,9 @@ static struct tegra_clk_pll_params pll_m_params = {
|
|||
.lock_mask = PLL_BASE_LOCK,
|
||||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.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 = {
|
||||
|
@ -1223,7 +1241,7 @@ static void __init tegra30_pmc_clk_init(void)
|
|||
|
||||
/* clk_out_2 */
|
||||
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,
|
||||
&clk_out_lock);
|
||||
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 = 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,
|
||||
&clk_out_lock);
|
||||
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;
|
||||
int i;
|
||||
|
@ -2005,3 +2023,4 @@ void __init tegra30_clock_init(struct device_node *np)
|
|||
|
||||
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;
|
||||
|
||||
void __init tegra_clocks_apply_init_table(void)
|
||||
|
|
|
@ -127,6 +127,31 @@ struct pdiv_map {
|
|||
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
|
||||
*
|
||||
|
@ -161,11 +186,14 @@ struct tegra_clk_pll_params {
|
|||
u32 aux_reg;
|
||||
u32 dyn_ramp_reg;
|
||||
u32 ext_misc_reg[3];
|
||||
u32 pmc_divnm_reg;
|
||||
u32 pmc_divp_reg;
|
||||
int stepa_shift;
|
||||
int stepb_shift;
|
||||
int lock_delay;
|
||||
int max_p;
|
||||
struct pdiv_map *pdiv_tohw;
|
||||
struct div_nmp *div_nmp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -179,12 +207,6 @@ struct tegra_clk_pll_params {
|
|||
* @flags: PLL flags
|
||||
* @fixed_rate: PLL rate if it is fixed
|
||||
* @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:
|
||||
* TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
|
||||
|
@ -214,12 +236,6 @@ struct tegra_clk_pll {
|
|||
u32 flags;
|
||||
unsigned long fixed_rate;
|
||||
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_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,
|
||||
struct clk *clks[], int clk_max);
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA_2x_SOC
|
||||
void tegra20_clock_init(struct device_node *np);
|
||||
#else
|
||||
static inline void tegra20_clock_init(struct device_node *np) {}
|
||||
#endif /* CONFIG_ARCH_TEGRA_2x_SOC */
|
||||
|
||||
#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 */
|
||||
void tegra114_clock_tune_cpu_trimmers_high(void);
|
||||
void tegra114_clock_tune_cpu_trimmers_low(void);
|
||||
void tegra114_clock_tune_cpu_trimmers_init(void);
|
||||
void tegra114_clock_assert_dfll_dvco_reset(void);
|
||||
void tegra114_clock_deassert_dfll_dvco_reset(void);
|
||||
|
||||
typedef void (*tegra_clk_apply_init_table_func)(void);
|
||||
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_register_clkdev(clk, "sysclk", "ab8500-usb.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");
|
||||
|
||||
/* ab8500_sysclk2 */
|
||||
|
@ -70,19 +70,19 @@ static int ab8500_reg_clks(struct device *dev)
|
|||
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
||||
AB8500_SYSULPCLKCTRL1_ULPCLKREQ,
|
||||
38400000, 9000, CLK_IS_ROOT);
|
||||
clk_register_clkdev(clk, "ulpclk", "ab85xx-codec.0");
|
||||
clk_register_clkdev(clk, "ulpclk", "snd-soc-mop500.0");
|
||||
|
||||
/* ab8500_intclk */
|
||||
clk = clk_reg_sysctrl_set_parent(dev , "intclk", intclk_parents, 2,
|
||||
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");
|
||||
|
||||
/* ab8500_audioclk */
|
||||
clk = clk_reg_sysctrl_gate(dev , "audioclk", "intclk",
|
||||
AB8500_SYSULPCLKCTRL1, AB8500_SYSULPCLKCTRL1_AUDIOCLKENA,
|
||||
AB8500_SYSULPCLKCTRL1_AUDIOCLKENA, 0, 0);
|
||||
clk_register_clkdev(clk, "audioclk", "ab85xx-codec.0");
|
||||
clk_register_clkdev(clk, "audioclk", "ab8500-codec.0");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -12,10 +12,568 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/mfd/dbx500-prcmu.h>
|
||||
#include <linux/platform_data/clk-ux500.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/mfd/dbx500-prcmu.h>
|
||||
#include <linux/platform_data/clk-ux500.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 */
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ void __init vexpress_osc_of_setup(struct device_node *node)
|
|||
osc->func = vexpress_config_func_get_by_node(node);
|
||||
if (!osc->func) {
|
||||
pr_err("Failed to obtain config func for node '%s'!\n",
|
||||
node->name);
|
||||
node->full_name);
|
||||
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);
|
||||
if (!init.name)
|
||||
init.name = node->name;
|
||||
init.name = node->full_name;
|
||||
|
||||
init.ops = &vexpress_osc_ops;
|
||||
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(PER7CLK, PLL_DIV, 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(HSITXCLK, PLL_DIV, true),
|
||||
CLK_MGT_ENTRY(HSIRXCLK, PLL_DIV, true),
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#define PRCM_PER7CLK_MGT (0x040)
|
||||
#define PRCM_LCDCLK_MGT (0x044)
|
||||
#define PRCM_BMLCLK_MGT (0x04C)
|
||||
#define PRCM_BML8580CLK_MGT (0x108)
|
||||
#define PRCM_HSITXCLK_MGT (0x050)
|
||||
#define PRCM_HSIRXCLK_MGT (0x054)
|
||||
#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
|
||||
* enable the clock. Setting this flag does the opposite: setting the bit
|
||||
* 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_hw hw;
|
||||
|
@ -220,6 +224,7 @@ struct clk_gate {
|
|||
};
|
||||
|
||||
#define CLK_GATE_SET_TO_DISABLE BIT(0)
|
||||
#define CLK_GATE_HIWORD_MASK BIT(1)
|
||||
|
||||
extern const struct clk_ops clk_gate_ops;
|
||||
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
|
||||
* zero divisor by not modifying their input clock
|
||||
* (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_hw hw;
|
||||
|
@ -271,6 +280,7 @@ struct clk_divider {
|
|||
#define CLK_DIVIDER_ONE_BASED BIT(0)
|
||||
#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
|
||||
#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
|
||||
#define CLK_DIVIDER_HIWORD_MASK BIT(3)
|
||||
|
||||
extern const struct clk_ops clk_divider_ops;
|
||||
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:
|
||||
* 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_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_hw hw;
|
||||
|
@ -312,6 +326,7 @@ struct clk_mux {
|
|||
|
||||
#define CLK_MUX_INDEX_ONE BIT(0)
|
||||
#define CLK_MUX_INDEX_BIT BIT(1)
|
||||
#define CLK_MUX_HIWORD_MASK BIT(2)
|
||||
|
||||
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 *);
|
||||
|
||||
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,
|
||||
struct clk *(*clk_src_get)(struct of_phandle_args *args,
|
||||
void *data),
|
||||
|
@ -430,19 +456,39 @@ int of_clk_add_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,
|
||||
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);
|
||||
const char *of_clk_get_parent_name(struct device_node *np, int index);
|
||||
|
||||
void of_clk_init(const struct of_device_id *matches);
|
||||
|
||||
#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 };
|
||||
#else /* !CONFIG_OF */
|
||||
|
||||
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 /* CLK_PROVIDER_H */
|
||||
|
|
|
@ -120,9 +120,13 @@ static inline void tegra_cpu_clock_resume(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_TEGRA
|
||||
void tegra_periph_reset_deassert(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);
|
||||
|
||||
#endif /* __LINUX_CLK_TEGRA_H_ */
|
||||
|
|
|
@ -278,8 +278,8 @@ struct ab8500_sysctrl_platform_data {
|
|||
|
||||
#define AB9540_SYSCLK12CONFCTRL_PLL26TO38ENA BIT(0)
|
||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12USBMUXSEL BIT(1)
|
||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_MASK 0x0C
|
||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL_SHIFT 2
|
||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL0 BIT(2)
|
||||
#define AB9540_SYSCLK12CONFCTRL_INT384MHZMUXSEL1 BIT(3)
|
||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12BUFMUX BIT(4)
|
||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK12PLLMUX BIT(5)
|
||||
#define AB9540_SYSCLK12CONFCTRL_SYSCLK2MUXVALID BIT(6)
|
||||
|
|
|
@ -134,6 +134,11 @@ enum prcmu_clock {
|
|||
PRCMU_SIACLK,
|
||||
PRCMU_SVACLK,
|
||||
PRCMU_ACLK,
|
||||
PRCMU_HVACLK, /* Ux540 only */
|
||||
PRCMU_G1CLK, /* Ux540 only */
|
||||
PRCMU_SDMMCHCLK,
|
||||
PRCMU_CAMCLK,
|
||||
PRCMU_BML8580CLK,
|
||||
PRCMU_NUM_REG_CLOCKS,
|
||||
PRCMU_SYSCLK = PRCMU_NUM_REG_CLOCKS,
|
||||
PRCMU_CDCLK,
|
||||
|
@ -148,6 +153,13 @@ enum prcmu_clock {
|
|||
PRCMU_DSI0ESCCLK,
|
||||
PRCMU_DSI1ESCCLK,
|
||||
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,
|
||||
u32 clkrst5_base, u32 clkrst6_base);
|
||||
void u9540_clk_init(void);
|
||||
void u8540_clk_init(void);
|
||||
void u9540_clk_init(u32 clkrst1_base, u32 clkrst2_base, u32 clkrst3_base,
|
||||
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 */
|
||||
|
|
|
@ -78,6 +78,23 @@ enum si5351_drive_strength {
|
|||
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
|
||||
* @clkout: clkout number
|
||||
|
@ -91,6 +108,7 @@ struct si5351_clkout_config {
|
|||
enum si5351_multisynth_src multisynth_src;
|
||||
enum si5351_clkout_src clkout_src;
|
||||
enum si5351_drive_strength drive;
|
||||
enum si5351_disable_state disable_state;
|
||||
bool pll_master;
|
||||
unsigned long rate;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue