The clk framework and driver changes for 4.5 look pretty typical. The
bulk of the changes are to clk controller drivers, though some improvements to the core and some re-usable blocks/templates also received some love. In this past cycle the clk maintainers developed a good workflow for handling the common case of patch submissions containing a new drivers, new shared Device Tree header and a new Device Tree binding description. This requires coordination with the Device Tree maintainers and with the architecture maintainers (typically the arm-soc tree in our case). This explains the increase in changes to include/dt-bindings/... and to Documentation/devicetree/bindings/clock/... coming from the clk tree. The same commits can be expected to come through those trees on occasion, through the use of shared, immutable branches. -----BEGIN PGP SIGNATURE----- iQIcBAABAgAGBQJWmVD1AAoJEKI6nJvDJaTUWqAQAJRqH+iKSnLyuVek6USYPXdp ZOW1JHIySCUF/ci3fvv9vbIuW/w4Uc9FdRdAfIIaWO32bpk4ljtEogVasvavL/54 geN+0YERZpth+PL/wk+g+Dons/8BgN9AL+0ToaVVh2MsRE903jWpe+l0qWCl+SUn DQF+yB9F4QcVT7gb+KI0B6hr6lv5Mu/t9Ffq3DrK2UG71IEbrv953pVo19foZqbf FgMgduERMHvaM/R6p5xfXxIESbjE+QNMnykEo6bWcHF2wfQrIiYlW1khtnsigNus kze2mYWjG77KGkrOex5kwjuBDPfiaGAstk3jcRCCMB7nRmuFcJgryF8003CD3QvW +cY+ZBSkyXXtL/nrkefebAplQjsvum7dJ+W6hxA32B772jFL8s8ee5rGda0ibw8N nFQRopVcNPoR52tjmSEOxm7Z9vqoDj5qManDdZe62kr6bCFId97E6SzeGgeyDuBQ V7tkss9klHMhx29V37wkyl+A/pWXO+CsGzHLEivH8/L1CysMK1WGhyHJJ2/JTDTR n3z1EYdg67PbHpfhboscuLP+sHcrAefOCe2la4wKxwqd4DGw6J8RhhVZml6XnfQ3 I4yLri8Pguol49G1ac1U87ylebKsXhWR5CRHVas1BFHrt0FGULHnl0ZOLzOu4GRZ h8/nd9ZODLFhB1w7fL1B =nkGr -----END PGP SIGNATURE----- Merge tag 'clk-for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk framework updates from Michael Turquette: "The clk framework and driver changes for 4.5 look pretty typical. The bulk of the changes are to clk controller drivers, though some improvements to the core and some re-usable blocks/templates also received some love. In this past cycle the clk maintainers developed a good workflow for handling the common case of patch submissions containing a new drivers, new shared Device Tree header and a new Device Tree binding description. This requires coordination with the Device Tree maintainers and with the architecture maintainers (typically the arm-soc tree in our case). This explains the increase in changes to include/dt-bindings/... and to Documentation/devicetree/bindings/clock/... coming from the clk tree. The same commits can be expected to come through those trees on occasion, through the use of shared, immutable branches" * tag 'clk-for-linus-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (125 commits) clk: remove duplicated COMMON_CLK_NXP record from clk/Kconfig clk: fix clk-gpio.c with optional clock= DT property clk: rockchip: fix section mismatches with new child-clocks clk: gpio: handle error codes for of_clk_get_parent_count() clk: gpio: fix memory leak clk: shmobile: r8a7795: Add SATA0 clock clk: bcm2835: Add PWM clock support clk: bcm2835: Support for clock parent selection clk: bcm2835: add a round up ability to the clock divisor clk: lpc32xx: add common clock framework driver clk: lpc18xx: add NXP specific COMMON_CLK_NXP configuration symbol dt-bindings: clock: add NXP LPC32xx clock list for consumers dt-bindings: clock: add description of LPC32xx USB clock controller dt-bindings: clock: add description of LPC32xx clock controller clk: rockchip: rk3036: include downstream muxes into fractional dividers clk: add flag for clocks that need to be enabled on rate changes clk: rockchip: Allow the RK3288 SPDIF clocks to change their parent clk: rockchip: include downstream muxes into fractional dividers clk: rockchip: handle mux dependency of fractional dividers clk: bcm2835: Add a driver for the auxiliary peripheral clock gates. ...
This commit is contained in:
commit
ece6267878
|
@ -0,0 +1,31 @@
|
|||
Broadcom BCM2835 auxiliary peripheral support
|
||||
|
||||
This binding uses the common clock binding:
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
The auxiliary peripherals (UART, SPI1, and SPI2) have a small register
|
||||
area controlling clock gating to the peripherals, and providing an IRQ
|
||||
status register.
|
||||
|
||||
Required properties:
|
||||
- compatible: Should be "brcm,bcm2835-aux"
|
||||
- #clock-cells: Should be <1>. The permitted clock-specifier values can be
|
||||
found in include/dt-bindings/clock/bcm2835-aux.h
|
||||
- reg: Specifies base physical address and size of the registers
|
||||
- clocks: The parent clock phandle
|
||||
|
||||
Example:
|
||||
|
||||
clocks: cprman@7e101000 {
|
||||
compatible = "brcm,bcm2835-cprman";
|
||||
#clock-cells = <1>;
|
||||
reg = <0x7e101000 0x2000>;
|
||||
clocks = <&clk_osc>;
|
||||
};
|
||||
|
||||
aux: aux@0x7e215004 {
|
||||
compatible = "brcm,bcm2835-aux";
|
||||
#clock-cells = <1>;
|
||||
reg = <0x7e215000 0x8>;
|
||||
clocks = <&clocks BCM2835_CLOCK_VPU>;
|
||||
};
|
|
@ -208,3 +208,8 @@ These clock IDs are defined in:
|
|||
ch3_unused lcpll_ports 4 BCM_NS2_LCPLL_PORTS_CH3_UNUSED
|
||||
ch4_unused lcpll_ports 5 BCM_NS2_LCPLL_PORTS_CH4_UNUSED
|
||||
ch5_unused lcpll_ports 6 BCM_NS2_LCPLL_PORTS_CH5_UNUSED
|
||||
|
||||
BCM63138
|
||||
--------
|
||||
PLL and leaf clock compatible strings for BCM63138 are:
|
||||
"brcm,bcm63138-armpll"
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
|
||||
|
||||
Required properties:
|
||||
|
||||
- compatible: "cirrus,cs2000-cp"
|
||||
- reg: The chip select number on the I2C bus
|
||||
- clocks: common clock binding for CLK_IN, XTI/REF_CLK
|
||||
- clock-names: CLK_IN : clk_in, XTI/REF_CLK : ref_clk
|
||||
- #clock-cells: must be <0>
|
||||
|
||||
Example:
|
||||
|
||||
&i2c2 {
|
||||
...
|
||||
cs2000: clk_multiplier@4f {
|
||||
#clock-cells = <0>;
|
||||
compatible = "cirrus,cs2000-cp";
|
||||
reg = <0x4f>;
|
||||
clocks = <&rcar_sound 0>, <&x12_clk>;
|
||||
clock-names = "clk_in", "ref_clk";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,56 @@
|
|||
NVIDIA Tegra210 Clock And Reset Controller
|
||||
|
||||
This binding uses the common clock binding:
|
||||
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||
|
||||
The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
|
||||
for muxing and gating Tegra's clocks, and setting their rates.
|
||||
|
||||
Required properties :
|
||||
- compatible : Should be "nvidia,tegra210-car"
|
||||
- reg : Should contain CAR registers location and length
|
||||
- clocks : Should contain phandle and clock specifiers for two clocks:
|
||||
the 32 KHz "32k_in".
|
||||
- #clock-cells : Should be 1.
|
||||
In clock consumers, this cell represents the clock ID exposed by the
|
||||
CAR. The assignments may be found in header file
|
||||
<dt-bindings/clock/tegra210-car.h>.
|
||||
- #reset-cells : Should be 1.
|
||||
In clock consumers, this cell represents the bit number in the CAR's
|
||||
array of CLK_RST_CONTROLLER_RST_DEVICES_* registers.
|
||||
|
||||
Example SoC include file:
|
||||
|
||||
/ {
|
||||
tegra_car: clock {
|
||||
compatible = "nvidia,tegra210-car";
|
||||
reg = <0x60006000 0x1000>;
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
usb@c5004000 {
|
||||
clocks = <&tegra_car TEGRA210_CLK_USB2>;
|
||||
};
|
||||
};
|
||||
|
||||
Example board file:
|
||||
|
||||
/ {
|
||||
clocks {
|
||||
compatible = "simple-bus";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
clk_32k: clock@1 {
|
||||
compatible = "fixed-clock";
|
||||
reg = <1>;
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <32768>;
|
||||
};
|
||||
};
|
||||
|
||||
&tegra_car {
|
||||
clocks = <&clk_32k>;
|
||||
};
|
||||
};
|
|
@ -0,0 +1,30 @@
|
|||
NXP LPC32xx Clock Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "nxp,lpc3220-clk"
|
||||
- reg: should contain clock controller registers location and length
|
||||
- #clock-cells: must be 1, the cell holds id of a clock provided by the
|
||||
clock controller
|
||||
- clocks: phandles of external oscillators, the list must contain one
|
||||
32768 Hz oscillator and may have one optional high frequency oscillator
|
||||
- clock-names: list of external oscillator clock names, must contain
|
||||
"xtal_32k" and may have optional "xtal"
|
||||
|
||||
Examples:
|
||||
|
||||
/* System Control Block */
|
||||
scb {
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0x040004000 0x00001000>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
clk: clock-controller@0 {
|
||||
compatible = "nxp,lpc3220-clk";
|
||||
reg = <0x00 0x114>;
|
||||
#clock-cells = <1>;
|
||||
|
||||
clocks = <&xtal_32k>, <&xtal>;
|
||||
clock-names = "xtal_32k", "xtal";
|
||||
};
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
NXP LPC32xx USB Clock Controller
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "nxp,lpc3220-usb-clk"
|
||||
- reg: should contain clock controller registers location and length
|
||||
- #clock-cells: must be 1, the cell holds id of a clock provided by the
|
||||
USB clock controller
|
||||
|
||||
Examples:
|
||||
|
||||
usb {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
compatible = "simple-bus";
|
||||
ranges = <0x0 0x31020000 0x00001000>;
|
||||
|
||||
usbclk: clock-controller@f00 {
|
||||
compatible = "nxp,lpc3220-usb-clk";
|
||||
reg = <0xf00 0x100>;
|
||||
#clock-cells = <1>;
|
||||
};
|
||||
};
|
|
@ -13,6 +13,7 @@ Required properties :
|
|||
"qcom,gcc-msm8974"
|
||||
"qcom,gcc-msm8974pro"
|
||||
"qcom,gcc-msm8974pro-ac"
|
||||
"qcom,gcc-msm8996"
|
||||
|
||||
- reg : shall contain base register location and length
|
||||
- #clock-cells : shall contain 1
|
||||
|
|
|
@ -9,6 +9,7 @@ Required properties :
|
|||
"qcom,mmcc-msm8660"
|
||||
"qcom,mmcc-msm8960"
|
||||
"qcom,mmcc-msm8974"
|
||||
"qcom,mmcc-msm8996"
|
||||
|
||||
- reg : shall contain base register location and length
|
||||
- #clock-cells : shall contain 1
|
||||
|
|
|
@ -20,6 +20,10 @@ Required Properties:
|
|||
clocks must be specified. For clocks with multiple parents, invalid
|
||||
settings must be specified as "<0>".
|
||||
- #clock-cells: Must be 0
|
||||
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- clock-output-names: The name of the clock as a free-form string
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
* Rockchip RK3036 Clock and Reset Unit
|
||||
|
||||
The RK3036 clock controller generates and supplies clock to various
|
||||
controllers within the SoC and also implements a reset controller for SoC
|
||||
peripherals.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "rockchip,rk3036-cru"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
If missing pll rates are not changeable, due to the missing pll lock status.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
preprocessor macros in the dt-bindings/clock/rk3036-cru.h headers and can be
|
||||
used in device tree sources. Similar macros exist for the reset sources in
|
||||
these files.
|
||||
|
||||
External clocks:
|
||||
|
||||
There are several clocks that are generated outside the SoC. It is expected
|
||||
that they are defined using standard clock bindings with following
|
||||
clock-output-names:
|
||||
- "xin24m" - crystal input - required,
|
||||
- "ext_i2s" - external I2S clock - optional,
|
||||
- "ext_gmac" - external GMAC clock - optional
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
cru: cru@20000000 {
|
||||
compatible = "rockchip,rk3036-cru";
|
||||
reg = <0x20000000 0x1000>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller:
|
||||
|
||||
uart0: serial@20060000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0x20060000 0x100>;
|
||||
interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
clocks = <&cru SCLK_UART0>;
|
||||
};
|
|
@ -0,0 +1,58 @@
|
|||
* Rockchip RK3228 Clock and Reset Unit
|
||||
|
||||
The RK3228 clock controller generates and supplies clock to various
|
||||
controllers within the SoC and also implements a reset controller for SoC
|
||||
peripherals.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "rockchip,rk3228-cru"
|
||||
- reg: physical base address of the controller and length of memory mapped
|
||||
region.
|
||||
- #clock-cells: should be 1.
|
||||
- #reset-cells: should be 1.
|
||||
|
||||
Optional Properties:
|
||||
|
||||
- rockchip,grf: phandle to the syscon managing the "general register files"
|
||||
If missing pll rates are not changeable, due to the missing pll lock status.
|
||||
|
||||
Each clock is assigned an identifier and client nodes can use this identifier
|
||||
to specify the clock which they consume. All available clocks are defined as
|
||||
preprocessor macros in the dt-bindings/clock/rk3228-cru.h headers and can be
|
||||
used in device tree sources. Similar macros exist for the reset sources in
|
||||
these files.
|
||||
|
||||
External clocks:
|
||||
|
||||
There are several clocks that are generated outside the SoC. It is expected
|
||||
that they are defined using standard clock bindings with following
|
||||
clock-output-names:
|
||||
- "xin24m" - crystal input - required,
|
||||
- "ext_i2s" - external I2S clock - optional,
|
||||
- "ext_gmac" - external GMAC clock - optional
|
||||
- "ext_hsadc" - external HSADC clock - optional
|
||||
- "phy_50m_out" - output clock of the pll in the mac phy
|
||||
|
||||
Example: Clock controller node:
|
||||
|
||||
cru: cru@20000000 {
|
||||
compatible = "rockchip,rk3228-cru";
|
||||
reg = <0x20000000 0x1000>;
|
||||
rockchip,grf = <&grf>;
|
||||
|
||||
#clock-cells = <1>;
|
||||
#reset-cells = <1>;
|
||||
};
|
||||
|
||||
Example: UART controller node that consumes the clock generated by the clock
|
||||
controller:
|
||||
|
||||
uart0: serial@10110000 {
|
||||
compatible = "snps,dw-apb-uart";
|
||||
reg = <0x10110000 0x100>;
|
||||
interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
|
||||
reg-shift = <2>;
|
||||
reg-io-width = <4>;
|
||||
clocks = <&cru SCLK_UART0>;
|
||||
};
|
|
@ -27,7 +27,9 @@ Required properties:
|
|||
"allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
|
||||
"allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
|
||||
"allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
|
||||
"allwinner,sun9i-a80-cpus-clk" - for the CPUS on A80
|
||||
"allwinner,sun6i-a31-ahb1-clk" - for the AHB1 clock on A31
|
||||
"allwinner,sun8i-h3-ahb2-clk" - for the AHB2 clock on H3
|
||||
"allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
|
||||
"allwinner,sun8i-a23-ahb1-gates-clk" - for the AHB1 gates on A23
|
||||
"allwinner,sun9i-a80-ahb0-gates-clk" - for the AHB0 gates on A80
|
||||
|
@ -55,6 +57,9 @@ Required properties:
|
|||
"allwinner,sun9i-a80-apb1-gates-clk" - for the APB1 gates on A80
|
||||
"allwinner,sun6i-a31-apb2-gates-clk" - for the APB2 gates on A31
|
||||
"allwinner,sun8i-a23-apb2-gates-clk" - for the APB2 gates on A23
|
||||
"allwinner,sun8i-h3-bus-gates-clk" - for the bus gates on H3
|
||||
"allwinner,sun9i-a80-apbs-gates-clk" - for the APBS gates on A80
|
||||
"allwinner,sun4i-a10-dram-gates-clk" - for the DRAM gates on A10
|
||||
"allwinner,sun5i-a13-mbus-clk" - for the MBUS clock on A13
|
||||
"allwinner,sun4i-a10-mmc-clk" - for the MMC clock
|
||||
"allwinner,sun9i-a80-mmc-clk" - for mmc module clocks on A80
|
||||
|
@ -68,8 +73,10 @@ Required properties:
|
|||
"allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
|
||||
"allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
|
||||
"allwinner,sun8i-a23-usb-clk" - for usb gates + resets on A23
|
||||
"allwinner,sun8i-h3-usb-clk" - for usb gates + resets on H3
|
||||
"allwinner,sun9i-a80-usb-mod-clk" - for usb gates + resets on A80
|
||||
"allwinner,sun9i-a80-usb-phy-clk" - for usb phy gates + resets on A80
|
||||
"allwinner,sun4i-a10-ve-clk" - for the Video Engine clock
|
||||
|
||||
Required properties for all clocks:
|
||||
- reg : shall be the control register address for the clock.
|
||||
|
@ -89,6 +96,9 @@ Required properties for all clocks:
|
|||
And "allwinner,*-usb-clk" clocks also require:
|
||||
- reset-cells : shall be set to 1
|
||||
|
||||
The "allwinner,sun4i-a10-ve-clk" clock also requires:
|
||||
- reset-cells : shall be set to 0
|
||||
|
||||
The "allwinner,sun9i-a80-mmc-config-clk" clock also requires:
|
||||
- #reset-cells : shall be set to 1
|
||||
- resets : shall be the reset control phandle for the mmc block.
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
* Sigma Designs Tango4 Clock Generator
|
||||
|
||||
The Tango4 clock generator outputs cpu_clk and sys_clk (the latter is used
|
||||
for RAM and various peripheral devices). The clock binding described here
|
||||
is applicable to all Tango4 SoCs.
|
||||
|
||||
Required Properties:
|
||||
|
||||
- compatible: should be "sigma,tango4-clkgen".
|
||||
- reg: physical base address of the device and length of memory mapped region.
|
||||
- clocks: phandle of the input clock (crystal oscillator).
|
||||
- clock-output-names: should be "cpuclk" and "sysclk".
|
||||
- #clock-cells: should be set to 1.
|
||||
|
||||
Example:
|
||||
|
||||
clkgen: clkgen@10000 {
|
||||
compatible = "sigma,tango4-clkgen";
|
||||
reg = <0x10000 0x40>;
|
||||
clocks = <&xtal>;
|
||||
clock-output-names = "cpuclk", "sysclk";
|
||||
#clock-cells = <1>;
|
||||
};
|
|
@ -225,5 +225,9 @@ void __init ti_clk_init_features(void)
|
|||
if (omap_rev() == OMAP3430_REV_ES1_0)
|
||||
features.flags |= TI_CLK_DPLL4_DENY_REPROGRAM;
|
||||
|
||||
/* Errata I810 for omap5 / dra7 */
|
||||
if (soc_is_omap54xx() || soc_is_dra7xx())
|
||||
features.flags |= TI_CLK_ERRATA_I810;
|
||||
|
||||
ti_clk_setup_features(&features);
|
||||
}
|
||||
|
|
|
@ -116,6 +116,12 @@ config COMMON_CLK_CDCE925
|
|||
Given a target output frequency, the driver will set the PLL and
|
||||
divider to best approximate the desired output.
|
||||
|
||||
config COMMON_CLK_CS2000_CP
|
||||
tristate "Clock driver for CS2000 Fractional-N Clock Synthesizer & Clock Multiplier"
|
||||
depends on I2C
|
||||
help
|
||||
If you say yes here you get support for the CS2000 clock multiplier.
|
||||
|
||||
config COMMON_CLK_S2MPS11
|
||||
tristate "Clock driver for S2MPS1X/S5M8767 MFD"
|
||||
depends on MFD_SEC_CORE
|
||||
|
@ -161,6 +167,12 @@ config COMMON_CLK_KEYSTONE
|
|||
Supports clock drivers for Keystone based SOCs. These SOCs have local
|
||||
a power sleep control module that gate the clock to the IPs and PLLs.
|
||||
|
||||
config COMMON_CLK_NXP
|
||||
def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX)
|
||||
select REGMAP_MMIO if ARCH_LPC32XX
|
||||
---help---
|
||||
Support for clock providers on NXP platforms.
|
||||
|
||||
config COMMON_CLK_PALMAS
|
||||
tristate "Clock driver for TI Palmas devices"
|
||||
depends on MFD_PALMAS
|
||||
|
|
|
@ -21,6 +21,7 @@ obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
|||
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
||||
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
|
||||
obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
|
||||
obj-$(CONFIG_COMMON_CLK_CS2000_CP) += clk-cs2000-cp.o
|
||||
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
|
||||
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
|
||||
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
|
||||
|
@ -42,6 +43,7 @@ obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
|
|||
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
||||
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
|
||||
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
|
||||
obj-$(CONFIG_ARCH_TANGOX) += clk-tango4.o
|
||||
obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o
|
||||
obj-$(CONFIG_ARCH_U300) += clk-u300.o
|
||||
obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o
|
||||
|
@ -62,13 +64,14 @@ endif
|
|||
obj-$(CONFIG_PLAT_ORION) += mvebu/
|
||||
obj-$(CONFIG_ARCH_MESON) += meson/
|
||||
obj-$(CONFIG_ARCH_MXS) += mxs/
|
||||
obj-$(CONFIG_ARCH_LPC18XX) += nxp/
|
||||
obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
|
||||
obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
|
||||
obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
|
||||
obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
|
||||
obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
|
||||
obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
|
||||
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += shmobile/
|
||||
obj-$(CONFIG_ARCH_RENESAS) += shmobile/
|
||||
obj-$(CONFIG_ARCH_SIRF) += sirf/
|
||||
obj-$(CONFIG_ARCH_SOCFPGA) += socfpga/
|
||||
obj-$(CONFIG_PLAT_SPEAR) += spear/
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -72,8 +71,6 @@ struct clk_sam9x5_slow {
|
|||
|
||||
#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
|
||||
|
||||
static struct clk *slow_clk;
|
||||
|
||||
static int clk_slow_osc_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_slow_osc *osc = to_clk_slow_osc(hw);
|
||||
|
@ -360,8 +357,6 @@ at91_clk_register_sam9x5_slow(void __iomem *sckcr,
|
|||
clk = clk_register(NULL, &slowck->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(slowck);
|
||||
else
|
||||
slow_clk = clk;
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
@ -433,8 +428,6 @@ at91_clk_register_sam9260_slow(struct at91_pmc *pmc,
|
|||
clk = clk_register(NULL, &slowck->hw);
|
||||
if (IS_ERR(clk))
|
||||
kfree(slowck);
|
||||
else
|
||||
slow_clk = clk;
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
@ -462,25 +455,3 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np,
|
|||
|
||||
of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: All slow clk users are not properly claiming it (get + prepare +
|
||||
* enable) before using it.
|
||||
* If all users properly claiming this clock decide that they don't need it
|
||||
* anymore (or are removed), it is disabled while faulty users are still
|
||||
* requiring it, and the system hangs.
|
||||
* Prevent this clock from being disabled until all users are properly
|
||||
* requesting it.
|
||||
* Once this is done we should remove this function and the slow_clk variable.
|
||||
*/
|
||||
static int __init of_at91_clk_slow_retain(void)
|
||||
{
|
||||
if (!slow_clk)
|
||||
return 0;
|
||||
|
||||
__clk_get(slow_clk);
|
||||
clk_prepare_enable(slow_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
arch_initcall(of_at91_clk_slow_retain);
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
config CLK_BCM_63XX
|
||||
bool "Broadcom BCM63xx clock support"
|
||||
depends on ARCH_BCM_63XX || COMPILE_TEST
|
||||
depends on COMMON_CLK
|
||||
select COMMON_CLK_IPROC
|
||||
default ARCH_BCM_63XX
|
||||
help
|
||||
Enable common clock framework support for Broadcom BCM63xx DSL SoCs
|
||||
based on the ARM architecture
|
||||
|
||||
config CLK_BCM_KONA
|
||||
bool "Broadcom Kona CCU clock support"
|
||||
depends on ARCH_BCM_MOBILE || COMPILE_TEST
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.o
|
||||
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
|
||||
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835-aux.o
|
||||
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o
|
||||
obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
|
||||
obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Broadcom
|
||||
*
|
||||
* 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.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/clk/bcm2835.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <dt-bindings/clock/bcm2835-aux.h>
|
||||
|
||||
#define BCM2835_AUXIRQ 0x00
|
||||
#define BCM2835_AUXENB 0x04
|
||||
|
||||
static int bcm2835_aux_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct clk_onecell_data *onecell;
|
||||
const char *parent;
|
||||
struct clk *parent_clk;
|
||||
struct resource *res;
|
||||
void __iomem *reg, *gate;
|
||||
|
||||
parent_clk = devm_clk_get(dev, NULL);
|
||||
if (IS_ERR(parent_clk))
|
||||
return PTR_ERR(parent_clk);
|
||||
parent = __clk_get_name(parent_clk);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
reg = devm_ioremap_resource(dev, res);
|
||||
if (!reg)
|
||||
return -ENODEV;
|
||||
|
||||
onecell = devm_kmalloc(dev, sizeof(*onecell), GFP_KERNEL);
|
||||
if (!onecell)
|
||||
return -ENOMEM;
|
||||
onecell->clk_num = BCM2835_AUX_CLOCK_COUNT;
|
||||
onecell->clks = devm_kcalloc(dev, BCM2835_AUX_CLOCK_COUNT,
|
||||
sizeof(*onecell->clks), GFP_KERNEL);
|
||||
if (!onecell->clks)
|
||||
return -ENOMEM;
|
||||
|
||||
gate = reg + BCM2835_AUXENB;
|
||||
onecell->clks[BCM2835_AUX_CLOCK_UART] =
|
||||
clk_register_gate(dev, "aux_uart", parent, 0, gate, 0, 0, NULL);
|
||||
|
||||
onecell->clks[BCM2835_AUX_CLOCK_SPI1] =
|
||||
clk_register_gate(dev, "aux_spi1", parent, 0, gate, 1, 0, NULL);
|
||||
|
||||
onecell->clks[BCM2835_AUX_CLOCK_SPI2] =
|
||||
clk_register_gate(dev, "aux_spi2", parent, 0, gate, 2, 0, NULL);
|
||||
|
||||
of_clk_add_provider(pdev->dev.of_node, of_clk_src_onecell_get, onecell);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id bcm2835_aux_clk_of_match[] = {
|
||||
{ .compatible = "brcm,bcm2835-aux", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, bcm2835_aux_clk_of_match);
|
||||
|
||||
static struct platform_driver bcm2835_aux_clk_driver = {
|
||||
.driver = {
|
||||
.name = "bcm2835-aux-clk",
|
||||
.of_match_table = bcm2835_aux_clk_of_match,
|
||||
},
|
||||
.probe = bcm2835_aux_clk_probe,
|
||||
};
|
||||
builtin_platform_driver(bcm2835_aux_clk_driver);
|
||||
|
||||
MODULE_AUTHOR("Eric Anholt <eric@anholt.net>");
|
||||
MODULE_DESCRIPTION("BCM2835 auxiliary peripheral clock driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -807,6 +807,16 @@ static const struct bcm2835_clock_data bcm2835_clock_emmc_data = {
|
|||
.frac_bits = 8,
|
||||
};
|
||||
|
||||
static const struct bcm2835_clock_data bcm2835_clock_pwm_data = {
|
||||
.name = "pwm",
|
||||
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
||||
.parents = bcm2835_clock_per_parents,
|
||||
.ctl_reg = CM_PWMCTL,
|
||||
.div_reg = CM_PWMDIV,
|
||||
.int_bits = 12,
|
||||
.frac_bits = 12,
|
||||
};
|
||||
|
||||
struct bcm2835_pll {
|
||||
struct clk_hw hw;
|
||||
struct bcm2835_cprman *cprman;
|
||||
|
@ -1148,22 +1158,24 @@ static int bcm2835_clock_is_on(struct clk_hw *hw)
|
|||
|
||||
static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
unsigned long parent_rate,
|
||||
bool round_up)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
u32 unused_frac_mask = GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0);
|
||||
u32 unused_frac_mask =
|
||||
GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
|
||||
u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
|
||||
u64 rem;
|
||||
u32 div;
|
||||
|
||||
do_div(temp, rate);
|
||||
rem = do_div(temp, rate);
|
||||
div = temp;
|
||||
|
||||
/* Round and mask off the unused bits */
|
||||
if (unused_frac_mask != 0) {
|
||||
div += unused_frac_mask >> 1;
|
||||
/* Round up and mask off the unused bits */
|
||||
if (round_up && ((div & unused_frac_mask) != 0 || rem != 0))
|
||||
div += unused_frac_mask + 1;
|
||||
div &= ~unused_frac_mask;
|
||||
}
|
||||
|
||||
/* Clamp to the limits. */
|
||||
div = max(div, unused_frac_mask + 1);
|
||||
|
@ -1197,16 +1209,6 @@ static long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
|
|||
return temp;
|
||||
}
|
||||
|
||||
static long bcm2835_clock_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
u32 div = bcm2835_clock_choose_div(hw, rate, *parent_rate);
|
||||
|
||||
return bcm2835_clock_rate_from_divisor(clock, *parent_rate, div);
|
||||
}
|
||||
|
||||
static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -1271,20 +1273,82 @@ static int bcm2835_clock_set_rate(struct clk_hw *hw,
|
|||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = clock->cprman;
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
|
||||
u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate, false);
|
||||
|
||||
cprman_write(cprman, data->div_reg, div);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_clock_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
struct clk_hw *parent, *best_parent = NULL;
|
||||
unsigned long rate, best_rate = 0;
|
||||
unsigned long prate, best_prate = 0;
|
||||
size_t i;
|
||||
u32 div;
|
||||
|
||||
/*
|
||||
* Select parent clock that results in the closest but lower rate
|
||||
*/
|
||||
for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
|
||||
parent = clk_hw_get_parent_by_index(hw, i);
|
||||
if (!parent)
|
||||
continue;
|
||||
prate = clk_hw_get_rate(parent);
|
||||
div = bcm2835_clock_choose_div(hw, req->rate, prate, true);
|
||||
rate = bcm2835_clock_rate_from_divisor(clock, prate, div);
|
||||
if (rate > best_rate && rate <= req->rate) {
|
||||
best_parent = parent;
|
||||
best_prate = prate;
|
||||
best_rate = rate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_parent)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_hw = best_parent;
|
||||
req->best_parent_rate = best_prate;
|
||||
|
||||
req->rate = best_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = clock->cprman;
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;
|
||||
|
||||
cprman_write(cprman, data->ctl_reg, src);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
||||
struct bcm2835_cprman *cprman = clock->cprman;
|
||||
const struct bcm2835_clock_data *data = clock->data;
|
||||
u32 src = cprman_read(cprman, data->ctl_reg);
|
||||
|
||||
return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
|
||||
}
|
||||
|
||||
|
||||
static const struct clk_ops bcm2835_clock_clk_ops = {
|
||||
.is_prepared = bcm2835_clock_is_on,
|
||||
.prepare = bcm2835_clock_on,
|
||||
.unprepare = bcm2835_clock_off,
|
||||
.recalc_rate = bcm2835_clock_get_rate,
|
||||
.set_rate = bcm2835_clock_set_rate,
|
||||
.round_rate = bcm2835_clock_round_rate,
|
||||
.determine_rate = bcm2835_clock_determine_rate,
|
||||
.set_parent = bcm2835_clock_set_parent,
|
||||
.get_parent = bcm2835_clock_get_parent,
|
||||
};
|
||||
|
||||
static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
|
||||
|
@ -1300,7 +1364,9 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
|
|||
.is_prepared = bcm2835_vpu_clock_is_on,
|
||||
.recalc_rate = bcm2835_clock_get_rate,
|
||||
.set_rate = bcm2835_clock_set_rate,
|
||||
.round_rate = bcm2835_clock_round_rate,
|
||||
.determine_rate = bcm2835_clock_determine_rate,
|
||||
.set_parent = bcm2835_clock_set_parent,
|
||||
.get_parent = bcm2835_clock_get_parent,
|
||||
};
|
||||
|
||||
static struct clk *bcm2835_register_pll(struct bcm2835_cprman *cprman,
|
||||
|
@ -1394,20 +1460,8 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
|
|||
{
|
||||
struct bcm2835_clock *clock;
|
||||
struct clk_init_data init;
|
||||
const char *parent;
|
||||
|
||||
/*
|
||||
* Most of the clock generators have a mux field, so we
|
||||
* instantiate a generic mux as our parent to handle it.
|
||||
*/
|
||||
if (data->num_mux_parents) {
|
||||
const char *parents[1 << CM_SRC_BITS];
|
||||
int i;
|
||||
|
||||
parent = devm_kasprintf(cprman->dev, GFP_KERNEL,
|
||||
"mux_%s", data->name);
|
||||
if (!parent)
|
||||
return NULL;
|
||||
size_t i;
|
||||
|
||||
/*
|
||||
* Replace our "xosc" references with the oscillator's
|
||||
|
@ -1420,19 +1474,9 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
|
|||
parents[i] = data->parents[i];
|
||||
}
|
||||
|
||||
clk_register_mux(cprman->dev, parent,
|
||||
parents, data->num_mux_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
cprman->regs + data->ctl_reg,
|
||||
CM_SRC_SHIFT, CM_SRC_BITS,
|
||||
0, &cprman->regs_lock);
|
||||
} else {
|
||||
parent = data->parents[0];
|
||||
}
|
||||
|
||||
memset(&init, 0, sizeof(init));
|
||||
init.parent_names = &parent;
|
||||
init.num_parents = 1;
|
||||
init.parent_names = parents;
|
||||
init.num_parents = data->num_mux_parents;
|
||||
init.name = data->name;
|
||||
init.flags = CLK_IGNORE_UNUSED;
|
||||
|
||||
|
@ -1550,6 +1594,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
|
|||
cprman->regs + CM_PERIICTL, CM_GATE_BIT,
|
||||
0, &cprman->regs_lock);
|
||||
|
||||
clks[BCM2835_CLOCK_PWM] =
|
||||
bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data);
|
||||
|
||||
return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
|
||||
&cprman->onecell);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Broadcom Corporation
|
||||
*
|
||||
* 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 version 2.
|
||||
*
|
||||
* This program is distributed "as is" WITHOUT ANY WARRANTY of any
|
||||
* kind, whether express or implied; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/init.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include "clk-iproc.h"
|
||||
|
||||
static void __init bcm63138_armpll_init(struct device_node *node)
|
||||
{
|
||||
iproc_armpll_setup(node);
|
||||
}
|
||||
CLK_OF_DECLARE(bcm63138_armpll, "brcm,bcm63138-armpll", bcm63138_armpll_init);
|
|
@ -0,0 +1,510 @@
|
|||
/*
|
||||
* CS2000 -- CIRRUS LOGIC Fractional-N Clock Synthesizer & Clock Multiplier
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Electronics Corporation
|
||||
* Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
|
||||
*
|
||||
* 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/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#define CH_MAX 4
|
||||
#define RATIO_REG_SIZE 4
|
||||
|
||||
#define DEVICE_ID 0x1
|
||||
#define DEVICE_CTRL 0x2
|
||||
#define DEVICE_CFG1 0x3
|
||||
#define DEVICE_CFG2 0x4
|
||||
#define GLOBAL_CFG 0x5
|
||||
#define Ratio_Add(x, nth) (6 + (x * 4) + (nth))
|
||||
#define Ratio_Val(x, nth) ((x >> (24 - (8 * nth))) & 0xFF)
|
||||
#define Val_Ratio(x, nth) ((x & 0xFF) << (24 - (8 * nth)))
|
||||
#define FUNC_CFG1 0x16
|
||||
#define FUNC_CFG2 0x17
|
||||
|
||||
/* DEVICE_ID */
|
||||
#define REVISION_MASK (0x7)
|
||||
#define REVISION_B2_B3 (0x4)
|
||||
#define REVISION_C1 (0x6)
|
||||
|
||||
/* DEVICE_CTRL */
|
||||
#define PLL_UNLOCK (1 << 7)
|
||||
|
||||
/* DEVICE_CFG1 */
|
||||
#define RSEL(x) (((x) & 0x3) << 3)
|
||||
#define RSEL_MASK RSEL(0x3)
|
||||
#define ENDEV1 (0x1)
|
||||
|
||||
/* GLOBAL_CFG */
|
||||
#define ENDEV2 (0x1)
|
||||
|
||||
#define CH_SIZE_ERR(ch) ((ch < 0) || (ch >= CH_MAX))
|
||||
#define hw_to_priv(_hw) container_of(_hw, struct cs2000_priv, hw)
|
||||
#define priv_to_client(priv) (priv->client)
|
||||
#define priv_to_dev(priv) (&(priv_to_client(priv)->dev))
|
||||
|
||||
#define CLK_IN 0
|
||||
#define REF_CLK 1
|
||||
#define CLK_MAX 2
|
||||
|
||||
struct cs2000_priv {
|
||||
struct clk_hw hw;
|
||||
struct i2c_client *client;
|
||||
struct clk *clk_in;
|
||||
struct clk *ref_clk;
|
||||
struct clk *clk_out;
|
||||
};
|
||||
|
||||
static const struct of_device_id cs2000_of_match[] = {
|
||||
{ .compatible = "cirrus,cs2000-cp", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, cs2000_of_match);
|
||||
|
||||
static const struct i2c_device_id cs2000_id[] = {
|
||||
{ "cs2000-cp", },
|
||||
{}
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, cs2000_id);
|
||||
|
||||
#define cs2000_read(priv, addr) \
|
||||
i2c_smbus_read_byte_data(priv_to_client(priv), addr)
|
||||
#define cs2000_write(priv, addr, val) \
|
||||
i2c_smbus_write_byte_data(priv_to_client(priv), addr, val)
|
||||
|
||||
static int cs2000_bset(struct cs2000_priv *priv, u8 addr, u8 mask, u8 val)
|
||||
{
|
||||
s32 data;
|
||||
|
||||
data = cs2000_read(priv, addr);
|
||||
if (data < 0)
|
||||
return data;
|
||||
|
||||
data &= ~mask;
|
||||
data |= (val & mask);
|
||||
|
||||
return cs2000_write(priv, addr, data);
|
||||
}
|
||||
|
||||
static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cs2000_bset(priv, DEVICE_CFG1, ENDEV1,
|
||||
enable ? ENDEV1 : 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_bset(priv, GLOBAL_CFG, ENDEV2,
|
||||
enable ? ENDEV2 : 0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv,
|
||||
u32 rate_in)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (rate_in >= 32000000 && rate_in < 56000000)
|
||||
val = 0x0;
|
||||
else if (rate_in >= 16000000 && rate_in < 28000000)
|
||||
val = 0x1;
|
||||
else if (rate_in >= 8000000 && rate_in < 14000000)
|
||||
val = 0x2;
|
||||
else
|
||||
return -EINVAL;
|
||||
|
||||
return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3);
|
||||
}
|
||||
|
||||
static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
|
||||
{
|
||||
struct device *dev = priv_to_dev(priv);
|
||||
s32 val;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
val = cs2000_read(priv, DEVICE_CTRL);
|
||||
if (val < 0)
|
||||
return val;
|
||||
if (!(val & PLL_UNLOCK))
|
||||
return 0;
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
dev_err(dev, "pll lock failed\n");
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable)
|
||||
{
|
||||
/* enable both AUX_OUT, CLK_OUT */
|
||||
return cs2000_write(priv, DEVICE_CTRL, enable ? 0 : 0x3);
|
||||
}
|
||||
|
||||
static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out)
|
||||
{
|
||||
u64 ratio;
|
||||
|
||||
/*
|
||||
* ratio = rate_out / rate_in * 2^20
|
||||
*
|
||||
* To avoid over flow, rate_out is u64.
|
||||
* The result should be u32.
|
||||
*/
|
||||
ratio = (u64)rate_out << 20;
|
||||
do_div(ratio, rate_in);
|
||||
|
||||
return ratio;
|
||||
}
|
||||
|
||||
static unsigned long cs2000_ratio_to_rate(u32 ratio, u32 rate_in)
|
||||
{
|
||||
u64 rate_out;
|
||||
|
||||
/*
|
||||
* ratio = rate_out / rate_in * 2^20
|
||||
*
|
||||
* To avoid over flow, rate_out is u64.
|
||||
* The result should be u32 or unsigned long.
|
||||
*/
|
||||
|
||||
rate_out = (u64)ratio * rate_in;
|
||||
return rate_out >> 20;
|
||||
}
|
||||
|
||||
static int cs2000_ratio_set(struct cs2000_priv *priv,
|
||||
int ch, u32 rate_in, u32 rate_out)
|
||||
{
|
||||
u32 val;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
if (CH_SIZE_ERR(ch))
|
||||
return -EINVAL;
|
||||
|
||||
val = cs2000_rate_to_ratio(rate_in, rate_out);
|
||||
for (i = 0; i < RATIO_REG_SIZE; i++) {
|
||||
ret = cs2000_write(priv,
|
||||
Ratio_Add(ch, i),
|
||||
Ratio_Val(val, i));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 cs2000_ratio_get(struct cs2000_priv *priv, int ch)
|
||||
{
|
||||
s32 tmp;
|
||||
u32 val;
|
||||
unsigned int i;
|
||||
|
||||
val = 0;
|
||||
for (i = 0; i < RATIO_REG_SIZE; i++) {
|
||||
tmp = cs2000_read(priv, Ratio_Add(ch, i));
|
||||
if (tmp < 0)
|
||||
return 0;
|
||||
|
||||
val |= Val_Ratio(tmp, i);
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int cs2000_ratio_select(struct cs2000_priv *priv, int ch)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (CH_SIZE_ERR(ch))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* FIXME
|
||||
*
|
||||
* this driver supports static ratio mode only at this point.
|
||||
*/
|
||||
ret = cs2000_bset(priv, DEVICE_CFG1, RSEL_MASK, RSEL(ch));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_write(priv, DEVICE_CFG2, 0x0);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long cs2000_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct cs2000_priv *priv = hw_to_priv(hw);
|
||||
int ch = 0; /* it uses ch0 only at this point */
|
||||
u32 ratio;
|
||||
|
||||
ratio = cs2000_ratio_get(priv, ch);
|
||||
|
||||
return cs2000_ratio_to_rate(ratio, parent_rate);
|
||||
}
|
||||
|
||||
static long cs2000_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent_rate)
|
||||
{
|
||||
u32 ratio;
|
||||
|
||||
ratio = cs2000_rate_to_ratio(*parent_rate, rate);
|
||||
|
||||
return cs2000_ratio_to_rate(ratio, *parent_rate);
|
||||
}
|
||||
|
||||
static int __cs2000_set_rate(struct cs2000_priv *priv, int ch,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = cs2000_clk_in_bound_rate(priv, parent_rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_ratio_set(priv, ch, parent_rate, rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_ratio_select(priv, ch);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_set_rate(struct clk_hw *hw,
|
||||
unsigned long rate, unsigned long parent_rate)
|
||||
{
|
||||
struct cs2000_priv *priv = hw_to_priv(hw);
|
||||
int ch = 0; /* it uses ch0 only at this point */
|
||||
|
||||
return __cs2000_set_rate(priv, ch, rate, parent_rate);
|
||||
}
|
||||
|
||||
static int cs2000_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct cs2000_priv *priv = hw_to_priv(hw);
|
||||
int ret;
|
||||
|
||||
ret = cs2000_enable_dev_config(priv, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_clk_out_enable(priv, true);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_wait_pll_lock(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void cs2000_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct cs2000_priv *priv = hw_to_priv(hw);
|
||||
|
||||
cs2000_enable_dev_config(priv, false);
|
||||
|
||||
cs2000_clk_out_enable(priv, false);
|
||||
}
|
||||
|
||||
static u8 cs2000_get_parent(struct clk_hw *hw)
|
||||
{
|
||||
/* always return REF_CLK */
|
||||
return REF_CLK;
|
||||
}
|
||||
|
||||
static const struct clk_ops cs2000_ops = {
|
||||
.get_parent = cs2000_get_parent,
|
||||
.recalc_rate = cs2000_recalc_rate,
|
||||
.round_rate = cs2000_round_rate,
|
||||
.set_rate = cs2000_set_rate,
|
||||
.prepare = cs2000_enable,
|
||||
.unprepare = cs2000_disable,
|
||||
};
|
||||
|
||||
static int cs2000_clk_get(struct cs2000_priv *priv)
|
||||
{
|
||||
struct i2c_client *client = priv_to_client(priv);
|
||||
struct device *dev = &client->dev;
|
||||
struct clk *clk_in, *ref_clk;
|
||||
|
||||
clk_in = devm_clk_get(dev, "clk_in");
|
||||
/* not yet provided */
|
||||
if (IS_ERR(clk_in))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
ref_clk = devm_clk_get(dev, "ref_clk");
|
||||
/* not yet provided */
|
||||
if (IS_ERR(ref_clk))
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
priv->clk_in = clk_in;
|
||||
priv->ref_clk = ref_clk;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_clk_register(struct cs2000_priv *priv)
|
||||
{
|
||||
struct device *dev = priv_to_dev(priv);
|
||||
struct device_node *np = dev->of_node;
|
||||
struct clk_init_data init;
|
||||
const char *name = np->name;
|
||||
struct clk *clk;
|
||||
static const char *parent_names[CLK_MAX];
|
||||
int ch = 0; /* it uses ch0 only at this point */
|
||||
int rate;
|
||||
int ret;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &name);
|
||||
|
||||
/*
|
||||
* set default rate as 1/1.
|
||||
* otherwise .set_rate which setup ratio
|
||||
* is never called if user requests 1/1 rate
|
||||
*/
|
||||
rate = clk_get_rate(priv->ref_clk);
|
||||
ret = __cs2000_set_rate(priv, ch, rate, rate);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
parent_names[CLK_IN] = __clk_get_name(priv->clk_in);
|
||||
parent_names[REF_CLK] = __clk_get_name(priv->ref_clk);
|
||||
|
||||
init.name = name;
|
||||
init.ops = &cs2000_ops;
|
||||
init.flags = CLK_SET_RATE_GATE;
|
||||
init.parent_names = parent_names;
|
||||
init.num_parents = ARRAY_SIZE(parent_names);
|
||||
|
||||
priv->hw.init = &init;
|
||||
|
||||
clk = clk_register(dev, &priv->hw);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
if (ret < 0) {
|
||||
clk_unregister(clk);
|
||||
return ret;
|
||||
}
|
||||
|
||||
priv->clk_out = clk;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_version_print(struct cs2000_priv *priv)
|
||||
{
|
||||
struct i2c_client *client = priv_to_client(priv);
|
||||
struct device *dev = &client->dev;
|
||||
s32 val;
|
||||
const char *revision;
|
||||
|
||||
val = cs2000_read(priv, DEVICE_ID);
|
||||
if (val < 0)
|
||||
return val;
|
||||
|
||||
/* CS2000 should be 0x0 */
|
||||
if (val >> 3)
|
||||
return -EIO;
|
||||
|
||||
switch (val & REVISION_MASK) {
|
||||
case REVISION_B2_B3:
|
||||
revision = "B2 / B3";
|
||||
break;
|
||||
case REVISION_C1:
|
||||
revision = "C1";
|
||||
break;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
dev_info(dev, "revision - %s\n", revision);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_remove(struct i2c_client *client)
|
||||
{
|
||||
struct cs2000_priv *priv = i2c_get_clientdata(client);
|
||||
struct device *dev = &client->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
|
||||
of_clk_del_provider(np);
|
||||
|
||||
clk_unregister(priv->clk_out);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cs2000_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct cs2000_priv *priv;
|
||||
struct device *dev = &client->dev;
|
||||
int ret;
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->client = client;
|
||||
i2c_set_clientdata(client, priv);
|
||||
|
||||
ret = cs2000_clk_get(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_clk_register(priv);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = cs2000_version_print(priv);
|
||||
if (ret < 0)
|
||||
goto probe_err;
|
||||
|
||||
return 0;
|
||||
|
||||
probe_err:
|
||||
cs2000_remove(client);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct i2c_driver cs2000_driver = {
|
||||
.driver = {
|
||||
.name = "cs2000-cp",
|
||||
.of_match_table = cs2000_of_match,
|
||||
},
|
||||
.probe = cs2000_probe,
|
||||
.remove = cs2000_remove,
|
||||
.id_table = cs2000_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(cs2000_driver);
|
||||
|
||||
MODULE_DESCRIPTION("CS2000-CP driver");
|
||||
MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -32,13 +32,14 @@
|
|||
|
||||
#define div_mask(width) ((1 << (width)) - 1)
|
||||
|
||||
static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
|
||||
static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
|
||||
u8 width)
|
||||
{
|
||||
unsigned int maxdiv = 0;
|
||||
unsigned int maxdiv = 0, mask = div_mask(width);
|
||||
const struct clk_div_table *clkt;
|
||||
|
||||
for (clkt = table; clkt->div; clkt++)
|
||||
if (clkt->div > maxdiv)
|
||||
if (clkt->div > maxdiv && clkt->val <= mask)
|
||||
maxdiv = clkt->div;
|
||||
return maxdiv;
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
|
|||
if (flags & CLK_DIVIDER_POWER_OF_TWO)
|
||||
return 1 << div_mask(width);
|
||||
if (table)
|
||||
return _get_table_maxdiv(table);
|
||||
return _get_table_maxdiv(table, width);
|
||||
return div_mask(width) + 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -264,8 +264,8 @@ static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name,
|
|||
const char * const *parent_names, u8 num_parents,
|
||||
unsigned gpio, bool active_low)
|
||||
{
|
||||
return clk_register_gpio_gate(NULL, name, parent_names[0],
|
||||
gpio, active_low, 0);
|
||||
return clk_register_gpio_gate(NULL, name, parent_names ?
|
||||
parent_names[0] : NULL, gpio, active_low, 0);
|
||||
}
|
||||
|
||||
static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name,
|
||||
|
@ -287,18 +287,26 @@ static void __init of_gpio_clk_setup(struct device_node *node,
|
|||
const char **parent_names;
|
||||
int i, num_parents;
|
||||
|
||||
num_parents = of_clk_get_parent_count(node);
|
||||
if (num_parents < 0)
|
||||
return;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
num_parents = of_clk_get_parent_count(node);
|
||||
|
||||
if (num_parents) {
|
||||
parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
|
||||
if (!parent_names)
|
||||
if (!parent_names) {
|
||||
kfree(data);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < num_parents; i++)
|
||||
parent_names[i] = of_clk_get_parent_name(node, i);
|
||||
} else {
|
||||
parent_names = NULL;
|
||||
}
|
||||
|
||||
data->num_parents = num_parents;
|
||||
data->parent_names = parent_names;
|
||||
|
|
|
@ -71,10 +71,9 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
|
|||
u32 val;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (mux->table)
|
||||
if (mux->table) {
|
||||
index = mux->table[index];
|
||||
|
||||
else {
|
||||
} else {
|
||||
if (mux->flags & CLK_MUX_INDEX_BIT)
|
||||
index = 1 << index;
|
||||
|
||||
|
|
|
@ -1091,6 +1091,13 @@ static int si5351_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
si5351_set_bits(hwdata->drvdata, SI5351_CLK0_CTRL + hwdata->num,
|
||||
SI5351_CLK_POWERDOWN, 0);
|
||||
|
||||
/*
|
||||
* Do a pll soft reset on both plls, needed in some cases to get
|
||||
* all outputs running.
|
||||
*/
|
||||
si5351_reg_write(hwdata->drvdata, SI5351_PLL_RESET,
|
||||
SI5351_PLL_RESET_A | SI5351_PLL_RESET_B);
|
||||
|
||||
dev_dbg(&hwdata->drvdata->client->dev,
|
||||
"%s - %s: rdiv = %u, parent_rate = %lu, rate = %lu\n",
|
||||
__func__, clk_hw_get_name(hw), (1 << rdiv),
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
static struct clk *out[2];
|
||||
static struct clk_onecell_data clk_data = { out, 2 };
|
||||
|
||||
#define SYSCLK_CTRL 0x20
|
||||
#define CPUCLK_CTRL 0x24
|
||||
#define LEGACY_DIV 0x3c
|
||||
|
||||
#define PLL_N(val) (((val) >> 0) & 0x7f)
|
||||
#define PLL_K(val) (((val) >> 13) & 0x7)
|
||||
#define PLL_M(val) (((val) >> 16) & 0x7)
|
||||
#define DIV_INDEX(val) (((val) >> 8) & 0xf)
|
||||
|
||||
static void __init make_pll(int idx, const char *parent, void __iomem *base)
|
||||
{
|
||||
char name[8];
|
||||
u32 val, mul, div;
|
||||
|
||||
sprintf(name, "pll%d", idx);
|
||||
val = readl_relaxed(base + idx*8);
|
||||
mul = PLL_N(val) + 1;
|
||||
div = (PLL_M(val) + 1) << PLL_K(val);
|
||||
clk_register_fixed_factor(NULL, name, parent, 0, mul, div);
|
||||
}
|
||||
|
||||
static int __init get_div(void __iomem *base)
|
||||
{
|
||||
u8 sysclk_tab[16] = { 2, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4 };
|
||||
int idx = DIV_INDEX(readl_relaxed(base + LEGACY_DIV));
|
||||
|
||||
return sysclk_tab[idx];
|
||||
}
|
||||
|
||||
static void __init tango4_clkgen_setup(struct device_node *np)
|
||||
{
|
||||
int div, ret;
|
||||
void __iomem *base = of_iomap(np, 0);
|
||||
const char *parent = of_clk_get_parent_name(np, 0);
|
||||
|
||||
if (!base)
|
||||
panic("%s: invalid address\n", np->full_name);
|
||||
|
||||
make_pll(0, parent, base);
|
||||
make_pll(1, parent, base);
|
||||
|
||||
out[0] = clk_register_divider(NULL, "cpuclk", "pll0", 0,
|
||||
base + CPUCLK_CTRL, 8, 8, CLK_DIVIDER_ONE_BASED, NULL);
|
||||
|
||||
div = readl_relaxed(base + SYSCLK_CTRL) & BIT(23) ? get_div(base) : 4;
|
||||
out[1] = clk_register_fixed_factor(NULL, "sysclk", "pll1", 0, 1, div);
|
||||
|
||||
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||
if (IS_ERR(out[0]) || IS_ERR(out[1]) || ret < 0)
|
||||
panic("%s: clk registration failed\n", np->full_name);
|
||||
}
|
||||
CLK_OF_DECLARE(tango4_clkgen, "sigma,tango4-clkgen", tango4_clkgen_setup);
|
|
@ -351,7 +351,8 @@ static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
/* Set new divider */
|
||||
data = xgene_clk_read(pclk->param.divider_reg +
|
||||
pclk->param.reg_divider_offset);
|
||||
data &= ~((1 << pclk->param.reg_divider_width) - 1);
|
||||
data &= ~((1 << pclk->param.reg_divider_width) - 1)
|
||||
<< pclk->param.reg_divider_shift;
|
||||
data |= divider;
|
||||
xgene_clk_write(data, pclk->param.divider_reg +
|
||||
pclk->param.reg_divider_offset);
|
||||
|
|
|
@ -1443,6 +1443,15 @@ static void clk_change_rate(struct clk_core *core)
|
|||
else if (core->parent)
|
||||
best_parent_rate = core->parent->rate;
|
||||
|
||||
if (core->flags & CLK_SET_RATE_UNGATE) {
|
||||
unsigned long flags;
|
||||
|
||||
clk_core_prepare(core);
|
||||
flags = clk_enable_lock();
|
||||
clk_core_enable(core);
|
||||
clk_enable_unlock(flags);
|
||||
}
|
||||
|
||||
if (core->new_parent && core->new_parent != core->parent) {
|
||||
old_parent = __clk_set_parent_before(core, core->new_parent);
|
||||
trace_clk_set_parent(core, core->new_parent);
|
||||
|
@ -1469,6 +1478,15 @@ static void clk_change_rate(struct clk_core *core)
|
|||
|
||||
core->rate = clk_recalc(core, best_parent_rate);
|
||||
|
||||
if (core->flags & CLK_SET_RATE_UNGATE) {
|
||||
unsigned long flags;
|
||||
|
||||
flags = clk_enable_lock();
|
||||
clk_core_disable(core);
|
||||
clk_enable_unlock(flags);
|
||||
clk_core_unprepare(core);
|
||||
}
|
||||
|
||||
if (core->notifier_count && old_rate != core->rate)
|
||||
__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
|
||||
|
||||
|
@ -1944,7 +1962,7 @@ bool clk_is_match(const struct clk *p, const struct clk *q)
|
|||
if (p == q)
|
||||
return true;
|
||||
|
||||
/* true if clk->core pointers match. Avoid derefing garbage */
|
||||
/* true if clk->core pointers match. Avoid dereferencing garbage */
|
||||
if (!IS_ERR_OR_NULL(p) && !IS_ERR_OR_NULL(q))
|
||||
if (p->core == q->core)
|
||||
return true;
|
||||
|
@ -2482,7 +2500,7 @@ struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id,
|
|||
struct clk *clk;
|
||||
|
||||
/* This is to allow this function to be chained to others */
|
||||
if (!hw || IS_ERR(hw))
|
||||
if (IS_ERR_OR_NULL(hw))
|
||||
return (struct clk *) hw;
|
||||
|
||||
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
|
||||
|
@ -2806,10 +2824,9 @@ void __clk_put(struct clk *clk)
|
|||
* re-enter into the clk framework by calling any top-level clk APIs;
|
||||
* this will cause a nested prepare_lock mutex.
|
||||
*
|
||||
* In all notification cases cases (pre, post and abort rate change) the
|
||||
* original clock rate is passed to the callback via struct
|
||||
* clk_notifier_data.old_rate and the new frequency is passed via struct
|
||||
* clk_notifier_data.new_rate.
|
||||
* In all notification cases (pre, post and abort rate change) the original
|
||||
* clock rate is passed to the callback via struct clk_notifier_data.old_rate
|
||||
* and the new frequency is passed via struct clk_notifier_data.new_rate.
|
||||
*
|
||||
* clk_notifier_register() must be called from non-atomic context.
|
||||
* Returns -EINVAL if called with null arguments, -ENOMEM upon
|
||||
|
@ -3062,9 +3079,6 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
|
|||
int count;
|
||||
struct clk *clk;
|
||||
|
||||
if (index < 0)
|
||||
return NULL;
|
||||
|
||||
rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
|
||||
&clkspec);
|
||||
if (rc)
|
||||
|
@ -3083,6 +3097,9 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
|
|||
}
|
||||
count++;
|
||||
}
|
||||
/* We went off the end of 'clock-indices' without finding it */
|
||||
if (prop && !vp)
|
||||
return NULL;
|
||||
|
||||
if (of_property_read_string_index(clkspec.np, "clock-output-names",
|
||||
index,
|
||||
|
|
|
@ -96,13 +96,11 @@ static struct clk ** const uart_clks[] __initconst = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static int __init __mx25_clocks_init(unsigned long osc_rate,
|
||||
void __iomem *ccm_base)
|
||||
static int __init __mx25_clocks_init(void __iomem *ccm_base)
|
||||
{
|
||||
BUG_ON(!ccm_base);
|
||||
|
||||
clk[dummy] = imx_clk_fixed("dummy", 0);
|
||||
clk[osc] = imx_clk_fixed("osc", osc_rate);
|
||||
clk[mpll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "mpll", "osc", ccm(CCM_MPCTL));
|
||||
clk[upll] = imx_clk_pllv1(IMX_PLLV1_IMX25, "upll", "osc", ccm(CCM_UPCTL));
|
||||
clk[mpll_cpu_3_4] = imx_clk_fixed_factor("mpll_cpu_3_4", "mpll", 3, 4);
|
||||
|
@ -250,22 +248,10 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
|
|||
|
||||
static void __init mx25_clocks_init_dt(struct device_node *np)
|
||||
{
|
||||
struct device_node *refnp;
|
||||
unsigned long osc_rate = 24000000;
|
||||
void __iomem *ccm;
|
||||
|
||||
/* retrieve the freqency of fixed clocks from device tree */
|
||||
for_each_compatible_node(refnp, NULL, "fixed-clock") {
|
||||
u32 rate;
|
||||
if (of_property_read_u32(refnp, "clock-frequency", &rate))
|
||||
continue;
|
||||
|
||||
if (of_device_is_compatible(refnp, "fsl,imx-osc"))
|
||||
osc_rate = rate;
|
||||
}
|
||||
|
||||
ccm = of_iomap(np, 0);
|
||||
__mx25_clocks_init(osc_rate, ccm);
|
||||
__mx25_clocks_init(ccm);
|
||||
|
||||
clk_data.clks = clk;
|
||||
clk_data.clk_num = ARRAY_SIZE(clk);
|
||||
|
|
|
@ -519,10 +519,10 @@ static void __init mx53_clocks_init(struct device_node *np)
|
|||
mx53_ldb_di0_sel, ARRAY_SIZE(mx53_ldb_di0_sel), CLK_SET_RATE_PARENT);
|
||||
clk[IMX5_CLK_LDB_DI0_GATE] = imx_clk_gate2("ldb_di0_gate", "ldb_di0_div", MXC_CCM_CCGR6, 28);
|
||||
clk[IMX5_CLK_LDB_DI1_GATE] = imx_clk_gate2("ldb_di1_gate", "ldb_di1_div", MXC_CCM_CCGR6, 30);
|
||||
clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
|
||||
mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel));
|
||||
clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
|
||||
mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel));
|
||||
clk[IMX5_CLK_IPU_DI0_SEL] = imx_clk_mux_flags("ipu_di0_sel", MXC_CCM_CSCMR2, 26, 3,
|
||||
mx53_ipu_di0_sel, ARRAY_SIZE(mx53_ipu_di0_sel), CLK_SET_RATE_PARENT);
|
||||
clk[IMX5_CLK_IPU_DI1_SEL] = imx_clk_mux_flags("ipu_di1_sel", MXC_CCM_CSCMR2, 29, 3,
|
||||
mx53_ipu_di1_sel, ARRAY_SIZE(mx53_ipu_di1_sel), CLK_SET_RATE_PARENT);
|
||||
clk[IMX5_CLK_TVE_EXT_SEL] = imx_clk_mux_flags("tve_ext_sel", MXC_CCM_CSCMR1, 6, 1,
|
||||
mx53_tve_ext_sel, ARRAY_SIZE(mx53_tve_ext_sel), CLK_SET_RATE_PARENT);
|
||||
clk[IMX5_CLK_TVE_GATE] = imx_clk_gate2("tve_gate", "tve_pred", MXC_CCM_CCGR2, 30);
|
||||
|
|
|
@ -70,7 +70,8 @@ static const char *cko_sels[] = { "cko1", "cko2", };
|
|||
static const char *lvds_sels[] = {
|
||||
"dummy", "dummy", "dummy", "dummy", "dummy", "dummy",
|
||||
"pll4_audio", "pll5_video", "pll8_mlb", "enet_ref",
|
||||
"pcie_ref_125m", "sata_ref_100m",
|
||||
"pcie_ref_125m", "sata_ref_100m", "usbphy1", "usbphy2",
|
||||
"dummy", "dummy", "dummy", "dummy", "osc",
|
||||
};
|
||||
static const char *pll_bypass_src_sels[] = { "osc", "lvds1_in", "lvds2_in", "dummy", };
|
||||
static const char *pll1_bypass_sels[] = { "pll1", "pll1_bypass_src", };
|
||||
|
|
|
@ -399,9 +399,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
|||
/* mask handshake of mmdc */
|
||||
writel_relaxed(BM_CCM_CCDR_MMDC_CH0_MASK, base + CCDR);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clks); i++)
|
||||
if (IS_ERR(clks[i]))
|
||||
pr_err("i.MX6UL clk %d: register failed with %ld\n", i, PTR_ERR(clks[i]));
|
||||
imx_check_clocks(clks, ARRAY_SIZE(clks));
|
||||
|
||||
clk_data.clks = clks;
|
||||
clk_data.clk_num = ARRAY_SIZE(clks);
|
||||
|
|
|
@ -833,10 +833,13 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
|||
|
||||
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(clks); i++)
|
||||
if (IS_ERR(clks[i]))
|
||||
pr_err("i.MX7D clk %d: register failed with %ld\n",
|
||||
i, PTR_ERR(clks[i]));
|
||||
clks[IMX7D_CLK_ARM] = imx_clk_cpu("arm", "arm_a7_root_clk",
|
||||
clks[IMX7D_ARM_A7_ROOT_CLK],
|
||||
clks[IMX7D_ARM_A7_ROOT_SRC],
|
||||
clks[IMX7D_PLL_ARM_MAIN_CLK],
|
||||
clks[IMX7D_PLL_SYS_MAIN_CLK]);
|
||||
|
||||
imx_check_clocks(clks, ARRAY_SIZE(clks));
|
||||
|
||||
clk_data.clks = clks;
|
||||
clk_data.clk_num = ARRAY_SIZE(clks);
|
||||
|
|
|
@ -97,6 +97,16 @@ static void clk_pllv3_unprepare(struct clk_hw *hw)
|
|||
writel_relaxed(val, pll->base);
|
||||
}
|
||||
|
||||
static int clk_pllv3_is_prepared(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_pllv3 *pll = to_clk_pllv3(hw);
|
||||
|
||||
if (readl_relaxed(pll->base) & BM_PLL_LOCK)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long clk_pllv3_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
|
@ -139,6 +149,7 @@ static int clk_pllv3_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
static const struct clk_ops clk_pllv3_ops = {
|
||||
.prepare = clk_pllv3_prepare,
|
||||
.unprepare = clk_pllv3_unprepare,
|
||||
.is_prepared = clk_pllv3_is_prepared,
|
||||
.recalc_rate = clk_pllv3_recalc_rate,
|
||||
.round_rate = clk_pllv3_round_rate,
|
||||
.set_rate = clk_pllv3_set_rate,
|
||||
|
@ -193,6 +204,7 @@ static int clk_pllv3_sys_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
static const struct clk_ops clk_pllv3_sys_ops = {
|
||||
.prepare = clk_pllv3_prepare,
|
||||
.unprepare = clk_pllv3_unprepare,
|
||||
.is_prepared = clk_pllv3_is_prepared,
|
||||
.recalc_rate = clk_pllv3_sys_recalc_rate,
|
||||
.round_rate = clk_pllv3_sys_round_rate,
|
||||
.set_rate = clk_pllv3_sys_set_rate,
|
||||
|
@ -265,6 +277,7 @@ static int clk_pllv3_av_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
static const struct clk_ops clk_pllv3_av_ops = {
|
||||
.prepare = clk_pllv3_prepare,
|
||||
.unprepare = clk_pllv3_unprepare,
|
||||
.is_prepared = clk_pllv3_is_prepared,
|
||||
.recalc_rate = clk_pllv3_av_recalc_rate,
|
||||
.round_rate = clk_pllv3_av_round_rate,
|
||||
.set_rate = clk_pllv3_av_set_rate,
|
||||
|
@ -279,6 +292,7 @@ static unsigned long clk_pllv3_enet_recalc_rate(struct clk_hw *hw,
|
|||
static const struct clk_ops clk_pllv3_enet_ops = {
|
||||
.prepare = clk_pllv3_prepare,
|
||||
.unprepare = clk_pllv3_unprepare,
|
||||
.is_prepared = clk_pllv3_is_prepared,
|
||||
.recalc_rate = clk_pllv3_enet_recalc_rate,
|
||||
};
|
||||
|
||||
|
|
|
@ -7,6 +7,6 @@ obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o
|
|||
obj-$(CONFIG_ARMADA_38X_CLK) += armada-38x.o
|
||||
obj-$(CONFIG_ARMADA_39X_CLK) += armada-39x.o
|
||||
obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o
|
||||
obj-$(CONFIG_DOVE_CLK) += dove.o
|
||||
obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o
|
||||
obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o
|
||||
obj-$(CONFIG_ORION_CLK) += orion.o
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Marvell Dove PMU Core PLL divider driver
|
||||
*
|
||||
* Cleaned up by substantially rewriting, and converted to DT by
|
||||
* Russell King. Origin is not known.
|
||||
*/
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
#include "dove-divider.h"
|
||||
|
||||
struct dove_clk {
|
||||
const char *name;
|
||||
struct clk_hw hw;
|
||||
void __iomem *base;
|
||||
spinlock_t *lock;
|
||||
u8 div_bit_start;
|
||||
u8 div_bit_end;
|
||||
u8 div_bit_load;
|
||||
u8 div_bit_size;
|
||||
u32 *divider_table;
|
||||
};
|
||||
|
||||
enum {
|
||||
DIV_CTRL0 = 0,
|
||||
DIV_CTRL1 = 4,
|
||||
DIV_CTRL1_N_RESET_MASK = BIT(10),
|
||||
};
|
||||
|
||||
#define to_dove_clk(hw) container_of(hw, struct dove_clk, hw)
|
||||
|
||||
static void dove_load_divider(void __iomem *base, u32 val, u32 mask, u32 load)
|
||||
{
|
||||
u32 v;
|
||||
|
||||
v = readl_relaxed(base + DIV_CTRL1) | DIV_CTRL1_N_RESET_MASK;
|
||||
writel_relaxed(v, base + DIV_CTRL1);
|
||||
|
||||
v = (readl_relaxed(base + DIV_CTRL0) & ~(mask | load)) | val;
|
||||
writel_relaxed(v, base + DIV_CTRL0);
|
||||
writel_relaxed(v | load, base + DIV_CTRL0);
|
||||
ndelay(250);
|
||||
writel_relaxed(v, base + DIV_CTRL0);
|
||||
}
|
||||
|
||||
static unsigned int dove_get_divider(struct dove_clk *dc)
|
||||
{
|
||||
unsigned int divider;
|
||||
u32 val;
|
||||
|
||||
val = readl_relaxed(dc->base + DIV_CTRL0);
|
||||
val >>= dc->div_bit_start;
|
||||
|
||||
divider = val & ~(~0 << dc->div_bit_size);
|
||||
|
||||
if (dc->divider_table)
|
||||
divider = dc->divider_table[divider];
|
||||
|
||||
return divider;
|
||||
}
|
||||
|
||||
static int dove_calc_divider(const struct dove_clk *dc, unsigned long rate,
|
||||
unsigned long parent_rate, bool set)
|
||||
{
|
||||
unsigned int divider, max;
|
||||
|
||||
divider = DIV_ROUND_CLOSEST(parent_rate, rate);
|
||||
|
||||
if (dc->divider_table) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; dc->divider_table[i]; i++)
|
||||
if (divider == dc->divider_table[i]) {
|
||||
divider = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!dc->divider_table[i])
|
||||
return -EINVAL;
|
||||
} else {
|
||||
max = 1 << dc->div_bit_size;
|
||||
|
||||
if (set && (divider == 0 || divider >= max))
|
||||
return -EINVAL;
|
||||
if (divider >= max)
|
||||
divider = max - 1;
|
||||
else if (divider == 0)
|
||||
divider = 1;
|
||||
}
|
||||
|
||||
return divider;
|
||||
}
|
||||
|
||||
static unsigned long dove_recalc_rate(struct clk_hw *hw, unsigned long parent)
|
||||
{
|
||||
struct dove_clk *dc = to_dove_clk(hw);
|
||||
unsigned int divider = dove_get_divider(dc);
|
||||
unsigned long rate = DIV_ROUND_CLOSEST(parent, divider);
|
||||
|
||||
pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
|
||||
__func__, dc->name, divider, parent, rate);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static long dove_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *parent)
|
||||
{
|
||||
struct dove_clk *dc = to_dove_clk(hw);
|
||||
unsigned long parent_rate = *parent;
|
||||
int divider;
|
||||
|
||||
divider = dove_calc_divider(dc, rate, parent_rate, false);
|
||||
if (divider < 0)
|
||||
return divider;
|
||||
|
||||
rate = DIV_ROUND_CLOSEST(parent_rate, divider);
|
||||
|
||||
pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
|
||||
__func__, dc->name, divider, parent_rate, rate);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static int dove_set_clock(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct dove_clk *dc = to_dove_clk(hw);
|
||||
u32 mask, load, div;
|
||||
int divider;
|
||||
|
||||
divider = dove_calc_divider(dc, rate, parent_rate, true);
|
||||
if (divider < 0)
|
||||
return divider;
|
||||
|
||||
pr_debug("%s(): %s divider=%u parent=%lu rate=%lu\n",
|
||||
__func__, dc->name, divider, parent_rate, rate);
|
||||
|
||||
div = (u32)divider << dc->div_bit_start;
|
||||
mask = ~(~0 << dc->div_bit_size) << dc->div_bit_start;
|
||||
load = BIT(dc->div_bit_load);
|
||||
|
||||
spin_lock(dc->lock);
|
||||
dove_load_divider(dc->base, div, mask, load);
|
||||
spin_unlock(dc->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops dove_divider_ops = {
|
||||
.set_rate = dove_set_clock,
|
||||
.round_rate = dove_round_rate,
|
||||
.recalc_rate = dove_recalc_rate,
|
||||
};
|
||||
|
||||
static struct clk *clk_register_dove_divider(struct device *dev,
|
||||
struct dove_clk *dc, const char **parent_names, size_t num_parents,
|
||||
void __iomem *base)
|
||||
{
|
||||
char name[32];
|
||||
struct clk_init_data init = {
|
||||
.name = name,
|
||||
.ops = &dove_divider_ops,
|
||||
.parent_names = parent_names,
|
||||
.num_parents = num_parents,
|
||||
};
|
||||
|
||||
strlcpy(name, dc->name, sizeof(name));
|
||||
|
||||
dc->hw.init = &init;
|
||||
dc->base = base;
|
||||
dc->div_bit_size = dc->div_bit_end - dc->div_bit_start + 1;
|
||||
|
||||
return clk_register(dev, &dc->hw);
|
||||
}
|
||||
|
||||
static DEFINE_SPINLOCK(dove_divider_lock);
|
||||
|
||||
static u32 axi_divider[] = {-1, 2, 1, 3, 4, 6, 5, 7, 8, 10, 9, 0};
|
||||
|
||||
static struct dove_clk dove_hw_clocks[4] = {
|
||||
{
|
||||
.name = "axi",
|
||||
.lock = &dove_divider_lock,
|
||||
.div_bit_start = 1,
|
||||
.div_bit_end = 6,
|
||||
.div_bit_load = 7,
|
||||
.divider_table = axi_divider,
|
||||
}, {
|
||||
.name = "gpu",
|
||||
.lock = &dove_divider_lock,
|
||||
.div_bit_start = 8,
|
||||
.div_bit_end = 13,
|
||||
.div_bit_load = 14,
|
||||
}, {
|
||||
.name = "vmeta",
|
||||
.lock = &dove_divider_lock,
|
||||
.div_bit_start = 15,
|
||||
.div_bit_end = 20,
|
||||
.div_bit_load = 21,
|
||||
}, {
|
||||
.name = "lcd",
|
||||
.lock = &dove_divider_lock,
|
||||
.div_bit_start = 22,
|
||||
.div_bit_end = 27,
|
||||
.div_bit_load = 28,
|
||||
},
|
||||
};
|
||||
|
||||
static const char *core_pll[] = {
|
||||
"core-pll",
|
||||
};
|
||||
|
||||
static int dove_divider_init(struct device *dev, void __iomem *base,
|
||||
struct clk **clks)
|
||||
{
|
||||
struct clk *clk;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Create the core PLL clock. We treat this as a fixed rate
|
||||
* clock as we don't know any better, and documentation is sparse.
|
||||
*/
|
||||
clk = clk_register_fixed_rate(dev, core_pll[0], NULL, CLK_IS_ROOT,
|
||||
2000000000UL);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(dove_hw_clocks); i++)
|
||||
clks[i] = clk_register_dove_divider(dev, &dove_hw_clocks[i],
|
||||
core_pll,
|
||||
ARRAY_SIZE(core_pll), base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct clk *dove_divider_clocks[4];
|
||||
|
||||
static struct clk_onecell_data dove_divider_data = {
|
||||
.clks = dove_divider_clocks,
|
||||
.clk_num = ARRAY_SIZE(dove_divider_clocks),
|
||||
};
|
||||
|
||||
void __init dove_divider_clk_init(struct device_node *np)
|
||||
{
|
||||
void *base;
|
||||
|
||||
base = of_iomap(np, 0);
|
||||
if (WARN_ON(!base))
|
||||
return;
|
||||
|
||||
if (WARN_ON(dove_divider_init(NULL, base, dove_divider_clocks))) {
|
||||
iounmap(base);
|
||||
return;
|
||||
}
|
||||
|
||||
of_clk_add_provider(np, of_clk_src_onecell_get, &dove_divider_data);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef DOVE_DIVIDER_H
|
||||
#define DOVE_DIVIDER_H
|
||||
|
||||
void __init dove_divider_clk_init(struct device_node *np);
|
||||
|
||||
#endif
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include "common.h"
|
||||
#include "dove-divider.h"
|
||||
|
||||
/*
|
||||
* Core Clocks
|
||||
|
@ -184,9 +185,14 @@ static void __init dove_clk_init(struct device_node *np)
|
|||
{
|
||||
struct device_node *cgnp =
|
||||
of_find_compatible_node(NULL, NULL, "marvell,dove-gating-clock");
|
||||
struct device_node *ddnp =
|
||||
of_find_compatible_node(NULL, NULL, "marvell,dove-divider-clock");
|
||||
|
||||
mvebu_coreclk_setup(np, &dove_coreclks);
|
||||
|
||||
if (ddnp)
|
||||
dove_divider_clk_init(ddnp);
|
||||
|
||||
if (cgnp)
|
||||
mvebu_clk_gating_setup(cgnp, dove_gating_desc);
|
||||
}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
obj-$(CONFIG_ARCH_LPC18XX) += clk-lpc18xx-cgu.o
|
||||
obj-$(CONFIG_ARCH_LPC18XX) += clk-lpc18xx-ccu.o
|
||||
obj-$(CONFIG_ARCH_LPC32XX) += clk-lpc32xx.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -106,3 +106,20 @@ config MSM_MMCC_8974
|
|||
Support for the multimedia clock controller on msm8974 devices.
|
||||
Say Y if you want to support multimedia devices such as display,
|
||||
graphics, video encode/decode, camera, etc.
|
||||
|
||||
config MSM_GCC_8996
|
||||
tristate "MSM8996 Global Clock Controller"
|
||||
depends on COMMON_CLK_QCOM
|
||||
help
|
||||
Support for the global clock controller on msm8996 devices.
|
||||
Say Y if you want to use peripheral devices such as UART, SPI,
|
||||
i2c, USB, UFS, SD/eMMC, PCIe, etc.
|
||||
|
||||
config MSM_MMCC_8996
|
||||
tristate "MSM8996 Multimedia Clock Controller"
|
||||
select MSM_GCC_8996
|
||||
depends on COMMON_CLK_QCOM
|
||||
help
|
||||
Support for the multimedia clock controller on msm8996 devices.
|
||||
Say Y if you want to support multimedia devices such as display,
|
||||
graphics, video encode/decode, camera, etc.
|
||||
|
|
|
@ -2,6 +2,7 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
|
|||
|
||||
clk-qcom-y += common.o
|
||||
clk-qcom-y += clk-regmap.o
|
||||
clk-qcom-y += clk-alpha-pll.o
|
||||
clk-qcom-y += clk-pll.o
|
||||
clk-qcom-y += clk-rcg.o
|
||||
clk-qcom-y += clk-rcg2.o
|
||||
|
@ -20,5 +21,7 @@ obj-$(CONFIG_MSM_GCC_8916) += gcc-msm8916.o
|
|||
obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
|
||||
obj-$(CONFIG_MSM_LCC_8960) += lcc-msm8960.o
|
||||
obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
|
||||
obj-$(CONFIG_MSM_GCC_8996) += gcc-msm8996.o
|
||||
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
|
||||
obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
|
||||
obj-$(CONFIG_MSM_MMCC_8996) += mmcc-msm8996.o
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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/kernel.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include "clk-alpha-pll.h"
|
||||
|
||||
#define PLL_MODE 0x00
|
||||
# define PLL_OUTCTRL BIT(0)
|
||||
# define PLL_BYPASSNL BIT(1)
|
||||
# define PLL_RESET_N BIT(2)
|
||||
# define PLL_LOCK_COUNT_SHIFT 8
|
||||
# define PLL_LOCK_COUNT_MASK 0x3f
|
||||
# define PLL_BIAS_COUNT_SHIFT 14
|
||||
# define PLL_BIAS_COUNT_MASK 0x3f
|
||||
# define PLL_VOTE_FSM_ENA BIT(20)
|
||||
# define PLL_VOTE_FSM_RESET BIT(21)
|
||||
# define PLL_ACTIVE_FLAG BIT(30)
|
||||
# define PLL_LOCK_DET BIT(31)
|
||||
|
||||
#define PLL_L_VAL 0x04
|
||||
#define PLL_ALPHA_VAL 0x08
|
||||
#define PLL_ALPHA_VAL_U 0x0c
|
||||
|
||||
#define PLL_USER_CTL 0x10
|
||||
# define PLL_POST_DIV_SHIFT 8
|
||||
# define PLL_POST_DIV_MASK 0xf
|
||||
# define PLL_ALPHA_EN BIT(24)
|
||||
# define PLL_VCO_SHIFT 20
|
||||
# define PLL_VCO_MASK 0x3
|
||||
|
||||
#define PLL_USER_CTL_U 0x14
|
||||
|
||||
#define PLL_CONFIG_CTL 0x18
|
||||
#define PLL_TEST_CTL 0x1c
|
||||
#define PLL_TEST_CTL_U 0x20
|
||||
#define PLL_STATUS 0x24
|
||||
|
||||
/*
|
||||
* Even though 40 bits are present, use only 32 for ease of calculation.
|
||||
*/
|
||||
#define ALPHA_REG_BITWIDTH 40
|
||||
#define ALPHA_BITWIDTH 32
|
||||
|
||||
#define to_clk_alpha_pll(_hw) container_of(to_clk_regmap(_hw), \
|
||||
struct clk_alpha_pll, clkr)
|
||||
|
||||
#define to_clk_alpha_pll_postdiv(_hw) container_of(to_clk_regmap(_hw), \
|
||||
struct clk_alpha_pll_postdiv, clkr)
|
||||
|
||||
static int wait_for_pll(struct clk_alpha_pll *pll)
|
||||
{
|
||||
u32 val, mask, off;
|
||||
int count;
|
||||
int ret;
|
||||
const char *name = clk_hw_get_name(&pll->clkr.hw);
|
||||
|
||||
off = pll->offset;
|
||||
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
if (val & PLL_VOTE_FSM_ENA)
|
||||
mask = PLL_ACTIVE_FLAG;
|
||||
else
|
||||
mask = PLL_LOCK_DET;
|
||||
|
||||
/* Wait for pll to enable. */
|
||||
for (count = 100; count > 0; count--) {
|
||||
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
if ((val & mask) == mask)
|
||||
return 0;
|
||||
|
||||
udelay(1);
|
||||
}
|
||||
|
||||
WARN(1, "%s didn't enable after voting for it!\n", name);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
static int clk_alpha_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
int ret;
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 val, mask, off;
|
||||
|
||||
off = pll->offset;
|
||||
|
||||
mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
|
||||
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* If in FSM mode, just vote for it */
|
||||
if (val & PLL_VOTE_FSM_ENA) {
|
||||
ret = clk_enable_regmap(hw);
|
||||
if (ret)
|
||||
return ret;
|
||||
return wait_for_pll(pll);
|
||||
}
|
||||
|
||||
/* Skip if already enabled */
|
||||
if ((val & mask) == mask)
|
||||
return 0;
|
||||
|
||||
ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
|
||||
PLL_BYPASSNL, PLL_BYPASSNL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* H/W requires a 5us delay between disabling the bypass and
|
||||
* de-asserting the reset.
|
||||
*/
|
||||
mb();
|
||||
udelay(5);
|
||||
|
||||
ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
|
||||
PLL_RESET_N, PLL_RESET_N);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = wait_for_pll(pll);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = regmap_update_bits(pll->clkr.regmap, off + PLL_MODE,
|
||||
PLL_OUTCTRL, PLL_OUTCTRL);
|
||||
|
||||
/* Ensure that the write above goes through before returning. */
|
||||
mb();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void clk_alpha_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
int ret;
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 val, mask, off;
|
||||
|
||||
off = pll->offset;
|
||||
|
||||
ret = regmap_read(pll->clkr.regmap, off + PLL_MODE, &val);
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
/* If in FSM mode, just unvote it */
|
||||
if (val & PLL_VOTE_FSM_ENA) {
|
||||
clk_disable_regmap(hw);
|
||||
return;
|
||||
}
|
||||
|
||||
mask = PLL_OUTCTRL;
|
||||
regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
|
||||
|
||||
/* Delay of 2 output clock ticks required until output is disabled */
|
||||
mb();
|
||||
udelay(1);
|
||||
|
||||
mask = PLL_RESET_N | PLL_BYPASSNL;
|
||||
regmap_update_bits(pll->clkr.regmap, off + PLL_MODE, mask, 0);
|
||||
}
|
||||
|
||||
static unsigned long alpha_pll_calc_rate(u64 prate, u32 l, u32 a)
|
||||
{
|
||||
return (prate * l) + ((prate * a) >> ALPHA_BITWIDTH);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
alpha_pll_round_rate(unsigned long rate, unsigned long prate, u32 *l, u64 *a)
|
||||
{
|
||||
u64 remainder;
|
||||
u64 quotient;
|
||||
|
||||
quotient = rate;
|
||||
remainder = do_div(quotient, prate);
|
||||
*l = quotient;
|
||||
|
||||
if (!remainder) {
|
||||
*a = 0;
|
||||
return rate;
|
||||
}
|
||||
|
||||
/* Upper ALPHA_BITWIDTH bits of Alpha */
|
||||
quotient = remainder << ALPHA_BITWIDTH;
|
||||
remainder = do_div(quotient, prate);
|
||||
|
||||
if (remainder)
|
||||
quotient++;
|
||||
|
||||
*a = quotient;
|
||||
return alpha_pll_calc_rate(prate, *l, *a);
|
||||
}
|
||||
|
||||
static const struct pll_vco *
|
||||
alpha_pll_find_vco(const struct clk_alpha_pll *pll, unsigned long rate)
|
||||
{
|
||||
const struct pll_vco *v = pll->vco_table;
|
||||
const struct pll_vco *end = v + pll->num_vco;
|
||||
|
||||
for (; v < end; v++)
|
||||
if (rate >= v->min_freq && rate <= v->max_freq)
|
||||
return v;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
clk_alpha_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
u32 l, low, high, ctl;
|
||||
u64 a = 0, prate = parent_rate;
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 off = pll->offset;
|
||||
|
||||
regmap_read(pll->clkr.regmap, off + PLL_L_VAL, &l);
|
||||
|
||||
regmap_read(pll->clkr.regmap, off + PLL_USER_CTL, &ctl);
|
||||
if (ctl & PLL_ALPHA_EN) {
|
||||
regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL, &low);
|
||||
regmap_read(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, &high);
|
||||
a = (u64)high << 32 | low;
|
||||
a >>= ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH;
|
||||
}
|
||||
|
||||
return alpha_pll_calc_rate(prate, l, a);
|
||||
}
|
||||
|
||||
static int clk_alpha_pll_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
const struct pll_vco *vco;
|
||||
u32 l, off = pll->offset;
|
||||
u64 a;
|
||||
|
||||
rate = alpha_pll_round_rate(rate, prate, &l, &a);
|
||||
vco = alpha_pll_find_vco(pll, rate);
|
||||
if (!vco) {
|
||||
pr_err("alpha pll not in a valid vco range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
a <<= (ALPHA_REG_BITWIDTH - ALPHA_BITWIDTH);
|
||||
|
||||
regmap_write(pll->clkr.regmap, off + PLL_L_VAL, l);
|
||||
regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL, a);
|
||||
regmap_write(pll->clkr.regmap, off + PLL_ALPHA_VAL_U, a >> 32);
|
||||
|
||||
regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL,
|
||||
PLL_VCO_MASK << PLL_VCO_SHIFT,
|
||||
vco->val << PLL_VCO_SHIFT);
|
||||
|
||||
regmap_update_bits(pll->clkr.regmap, off + PLL_USER_CTL, PLL_ALPHA_EN,
|
||||
PLL_ALPHA_EN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long clk_alpha_pll_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
|
||||
u32 l;
|
||||
u64 a;
|
||||
unsigned long min_freq, max_freq;
|
||||
|
||||
rate = alpha_pll_round_rate(rate, *prate, &l, &a);
|
||||
if (alpha_pll_find_vco(pll, rate))
|
||||
return rate;
|
||||
|
||||
min_freq = pll->vco_table[0].min_freq;
|
||||
max_freq = pll->vco_table[pll->num_vco - 1].max_freq;
|
||||
|
||||
return clamp(rate, min_freq, max_freq);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_ops = {
|
||||
.enable = clk_alpha_pll_enable,
|
||||
.disable = clk_alpha_pll_disable,
|
||||
.recalc_rate = clk_alpha_pll_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_round_rate,
|
||||
.set_rate = clk_alpha_pll_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_ops);
|
||||
|
||||
static unsigned long
|
||||
clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||
{
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
u32 ctl;
|
||||
|
||||
regmap_read(pll->clkr.regmap, pll->offset + PLL_USER_CTL, &ctl);
|
||||
|
||||
ctl >>= PLL_POST_DIV_SHIFT;
|
||||
ctl &= PLL_POST_DIV_MASK;
|
||||
|
||||
return parent_rate >> fls(ctl);
|
||||
}
|
||||
|
||||
static const struct clk_div_table clk_alpha_div_table[] = {
|
||||
{ 0x0, 1 },
|
||||
{ 0x1, 2 },
|
||||
{ 0x3, 4 },
|
||||
{ 0x7, 8 },
|
||||
{ 0xf, 16 },
|
||||
{ }
|
||||
};
|
||||
|
||||
static long
|
||||
clk_alpha_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
|
||||
return divider_round_rate(hw, rate, prate, clk_alpha_div_table,
|
||||
pll->width, CLK_DIVIDER_POWER_OF_TWO);
|
||||
}
|
||||
|
||||
static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
|
||||
int div;
|
||||
|
||||
/* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
|
||||
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
|
||||
|
||||
return regmap_update_bits(pll->clkr.regmap, pll->offset + PLL_USER_CTL,
|
||||
PLL_POST_DIV_MASK << PLL_POST_DIV_SHIFT,
|
||||
div << PLL_POST_DIV_SHIFT);
|
||||
}
|
||||
|
||||
const struct clk_ops clk_alpha_pll_postdiv_ops = {
|
||||
.recalc_rate = clk_alpha_pll_postdiv_recalc_rate,
|
||||
.round_rate = clk_alpha_pll_postdiv_round_rate,
|
||||
.set_rate = clk_alpha_pll_postdiv_set_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_alpha_pll_postdiv_ops);
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2, as published by the Free Software Foundation, and
|
||||
* may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __QCOM_CLK_ALPHA_PLL_H__
|
||||
#define __QCOM_CLK_ALPHA_PLL_H__
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include "clk-regmap.h"
|
||||
|
||||
struct pll_vco {
|
||||
unsigned long min_freq;
|
||||
unsigned long max_freq;
|
||||
u32 val;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct clk_alpha_pll - phase locked loop (PLL)
|
||||
* @offset: base address of registers
|
||||
* @vco_table: array of VCO settings
|
||||
* @clkr: regmap clock handle
|
||||
*/
|
||||
struct clk_alpha_pll {
|
||||
u32 offset;
|
||||
|
||||
const struct pll_vco *vco_table;
|
||||
size_t num_vco;
|
||||
|
||||
struct clk_regmap clkr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct clk_alpha_pll_postdiv - phase locked loop (PLL) post-divider
|
||||
* @offset: base address of registers
|
||||
* @width: width of post-divider
|
||||
* @clkr: regmap clock handle
|
||||
*/
|
||||
struct clk_alpha_pll_postdiv {
|
||||
u32 offset;
|
||||
u8 width;
|
||||
|
||||
struct clk_regmap clkr;
|
||||
};
|
||||
|
||||
extern const struct clk_ops clk_alpha_pll_ops;
|
||||
extern const struct clk_ops clk_alpha_pll_postdiv_ops;
|
||||
|
||||
#endif
|
|
@ -178,5 +178,6 @@ extern const struct clk_ops clk_edp_pixel_ops;
|
|||
extern const struct clk_ops clk_byte_ops;
|
||||
extern const struct clk_ops clk_byte2_ops;
|
||||
extern const struct clk_ops clk_pixel_ops;
|
||||
extern const struct clk_ops clk_gfx3d_ops;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -723,3 +723,90 @@ const struct clk_ops clk_pixel_ops = {
|
|||
.determine_rate = clk_pixel_determine_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_pixel_ops);
|
||||
|
||||
static int clk_gfx3d_determine_rate(struct clk_hw *hw,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_rate_request parent_req = { };
|
||||
struct clk_hw *p2, *p8, *p9, *xo;
|
||||
unsigned long p9_rate;
|
||||
int ret;
|
||||
|
||||
xo = clk_hw_get_parent_by_index(hw, 0);
|
||||
if (req->rate == clk_hw_get_rate(xo)) {
|
||||
req->best_parent_hw = xo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
p9 = clk_hw_get_parent_by_index(hw, 2);
|
||||
p2 = clk_hw_get_parent_by_index(hw, 3);
|
||||
p8 = clk_hw_get_parent_by_index(hw, 4);
|
||||
|
||||
/* PLL9 is a fixed rate PLL */
|
||||
p9_rate = clk_hw_get_rate(p9);
|
||||
|
||||
parent_req.rate = req->rate = min(req->rate, p9_rate);
|
||||
if (req->rate == p9_rate) {
|
||||
req->rate = req->best_parent_rate = p9_rate;
|
||||
req->best_parent_hw = p9;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (req->best_parent_hw == p9) {
|
||||
/* Are we going back to a previously used rate? */
|
||||
if (clk_hw_get_rate(p8) == req->rate)
|
||||
req->best_parent_hw = p8;
|
||||
else
|
||||
req->best_parent_hw = p2;
|
||||
} else if (req->best_parent_hw == p8) {
|
||||
req->best_parent_hw = p2;
|
||||
} else {
|
||||
req->best_parent_hw = p8;
|
||||
}
|
||||
|
||||
ret = __clk_determine_rate(req->best_parent_hw, &parent_req);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
req->rate = req->best_parent_rate = parent_req.rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clk_gfx3d_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate, u8 index)
|
||||
{
|
||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||
u32 cfg;
|
||||
int ret;
|
||||
|
||||
/* Just mux it, we don't use the division or m/n hardware */
|
||||
cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
|
||||
ret = regmap_write(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return update_config(rcg);
|
||||
}
|
||||
|
||||
static int clk_gfx3d_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
/*
|
||||
* We should never get here; clk_gfx3d_determine_rate() should always
|
||||
* make us use a different parent than what we're currently using, so
|
||||
* clk_gfx3d_set_rate_and_parent() should always be called.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct clk_ops clk_gfx3d_ops = {
|
||||
.is_enabled = clk_rcg2_is_enabled,
|
||||
.get_parent = clk_rcg2_get_parent,
|
||||
.set_parent = clk_rcg2_set_parent,
|
||||
.recalc_rate = clk_rcg2_recalc_rate,
|
||||
.set_rate = clk_gfx3d_set_rate,
|
||||
.set_rate_and_parent = clk_gfx3d_set_rate_and_parent,
|
||||
.determine_rate = clk_gfx3d_determine_rate,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(clk_gfx3d_ops);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "clk-rcg.h"
|
||||
|
@ -88,6 +89,92 @@ static void qcom_cc_gdsc_unregister(void *data)
|
|||
gdsc_unregister(data);
|
||||
}
|
||||
|
||||
/*
|
||||
* Backwards compatibility with old DTs. Register a pass-through factor 1/1
|
||||
* clock to translate 'path' clk into 'name' clk and regsiter the 'path'
|
||||
* clk as a fixed rate clock if it isn't present.
|
||||
*/
|
||||
static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate,
|
||||
bool add_factor)
|
||||
{
|
||||
struct device_node *node = NULL;
|
||||
struct device_node *clocks_node;
|
||||
struct clk_fixed_factor *factor;
|
||||
struct clk_fixed_rate *fixed;
|
||||
struct clk *clk;
|
||||
struct clk_init_data init_data = { };
|
||||
|
||||
clocks_node = of_find_node_by_path("/clocks");
|
||||
if (clocks_node)
|
||||
node = of_find_node_by_name(clocks_node, path);
|
||||
of_node_put(clocks_node);
|
||||
|
||||
if (!node) {
|
||||
fixed = devm_kzalloc(dev, sizeof(*fixed), GFP_KERNEL);
|
||||
if (!fixed)
|
||||
return -EINVAL;
|
||||
|
||||
fixed->fixed_rate = rate;
|
||||
fixed->hw.init = &init_data;
|
||||
|
||||
init_data.name = path;
|
||||
init_data.flags = CLK_IS_ROOT;
|
||||
init_data.ops = &clk_fixed_rate_ops;
|
||||
|
||||
clk = devm_clk_register(dev, &fixed->hw);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
of_node_put(node);
|
||||
|
||||
if (add_factor) {
|
||||
factor = devm_kzalloc(dev, sizeof(*factor), GFP_KERNEL);
|
||||
if (!factor)
|
||||
return -EINVAL;
|
||||
|
||||
factor->mult = factor->div = 1;
|
||||
factor->hw.init = &init_data;
|
||||
|
||||
init_data.name = name;
|
||||
init_data.parent_names = &path;
|
||||
init_data.num_parents = 1;
|
||||
init_data.flags = 0;
|
||||
init_data.ops = &clk_fixed_factor_ops;
|
||||
|
||||
clk = devm_clk_register(dev, &factor->hw);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate)
|
||||
{
|
||||
bool add_factor = true;
|
||||
struct device_node *node;
|
||||
|
||||
/* The RPM clock driver will add the factor clock if present */
|
||||
if (IS_ENABLED(CONFIG_QCOM_RPMCC)) {
|
||||
node = of_find_compatible_node(NULL, NULL, "qcom,rpmcc");
|
||||
if (of_device_is_available(node))
|
||||
add_factor = false;
|
||||
of_node_put(node);
|
||||
}
|
||||
|
||||
return _qcom_cc_register_board_clk(dev, path, name, rate, add_factor);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_cc_register_board_clk);
|
||||
|
||||
int qcom_cc_register_sleep_clk(struct device *dev)
|
||||
{
|
||||
return _qcom_cc_register_board_clk(dev, "sleep_clk", "sleep_clk_src",
|
||||
32768, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(qcom_cc_register_sleep_clk);
|
||||
|
||||
int qcom_cc_really_probe(struct platform_device *pdev,
|
||||
const struct qcom_cc_desc *desc, struct regmap *regmap)
|
||||
{
|
||||
|
|
|
@ -37,6 +37,10 @@ extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
|
|||
extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
|
||||
u8 src);
|
||||
|
||||
extern int qcom_cc_register_board_clk(struct device *dev, const char *path,
|
||||
const char *name, unsigned long rate);
|
||||
extern int qcom_cc_register_sleep_clk(struct device *dev);
|
||||
|
||||
extern struct regmap *qcom_cc_map(struct platform_device *pdev,
|
||||
const struct qcom_cc_desc *desc);
|
||||
extern int qcom_cc_really_probe(struct platform_device *pdev,
|
||||
|
|
|
@ -3587,6 +3587,7 @@ static const struct regmap_config gcc_apq8084_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x1fc0,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_apq8084_desc = {
|
||||
|
@ -3607,18 +3608,16 @@ MODULE_DEVICE_TABLE(of, gcc_apq8084_match_table);
|
|||
|
||||
static int gcc_apq8084_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
|
||||
CLK_IS_ROOT, 32768);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_sleep_clk(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_cc_probe(pdev, &gcc_apq8084_desc);
|
||||
}
|
||||
|
|
|
@ -3005,6 +3005,7 @@ static const struct regmap_config gcc_ipq806x_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x3e40,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_ipq806x_desc = {
|
||||
|
@ -3023,19 +3024,17 @@ MODULE_DEVICE_TABLE(of, gcc_ipq806x_match_table);
|
|||
|
||||
static int gcc_ipq806x_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct regmap *regmap;
|
||||
int ret;
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 25000000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 25000000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_cc_probe(pdev, &gcc_ipq806x_desc);
|
||||
if (ret)
|
||||
|
|
|
@ -2702,6 +2702,7 @@ static const struct regmap_config gcc_msm8660_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x363c,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_msm8660_desc = {
|
||||
|
@ -2720,17 +2721,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
|
|||
|
||||
static int gcc_msm8660_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_cc_probe(pdev, &gcc_msm8660_desc);
|
||||
}
|
||||
|
|
|
@ -3336,6 +3336,7 @@ static const struct regmap_config gcc_msm8916_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x80000,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_msm8916_desc = {
|
||||
|
@ -3356,18 +3357,16 @@ MODULE_DEVICE_TABLE(of, gcc_msm8916_match_table);
|
|||
|
||||
static int gcc_msm8916_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
|
||||
CLK_IS_ROOT, 32768);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_sleep_clk(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_cc_probe(pdev, &gcc_msm8916_desc);
|
||||
}
|
||||
|
|
|
@ -3468,6 +3468,7 @@ static const struct regmap_config gcc_msm8960_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x3660,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct regmap_config gcc_apq8064_regmap_config = {
|
||||
|
@ -3476,6 +3477,7 @@ static const struct regmap_config gcc_apq8064_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x3880,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_msm8960_desc = {
|
||||
|
@ -3503,7 +3505,6 @@ MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
|
|||
|
||||
static int gcc_msm8960_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct device *dev = &pdev->dev;
|
||||
const struct of_device_id *match;
|
||||
struct platform_device *tsens;
|
||||
|
@ -3513,14 +3514,13 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
|
|||
if (!match)
|
||||
return -EINVAL;
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "cxo_board", "cxo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "pxo_board", "pxo", 27000000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = qcom_cc_probe(pdev, match->data);
|
||||
if (ret)
|
||||
|
|
|
@ -2680,6 +2680,7 @@ static const struct regmap_config gcc_msm8974_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x1fc0,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc gcc_msm8974_desc = {
|
||||
|
@ -2717,7 +2718,7 @@ static void msm8974_pro_clock_override(void)
|
|||
|
||||
static int gcc_msm8974_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
struct device *dev = &pdev->dev;
|
||||
bool pro;
|
||||
const struct of_device_id *id;
|
||||
|
@ -2730,16 +2731,13 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
|
|||
if (pro)
|
||||
msm8974_pro_clock_override();
|
||||
|
||||
/* Temporary until RPM clocks supported */
|
||||
clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_board_clk(dev, "xo_board", "xo", 19200000);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Should move to DT node? */
|
||||
clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
|
||||
CLK_IS_ROOT, 32768);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
ret = qcom_cc_register_sleep_clk(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return qcom_cc_probe(pdev, &gcc_msm8974_desc);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -419,6 +419,7 @@ static const struct regmap_config lcc_ipq806x_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0xfc,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc lcc_ipq806x_desc = {
|
||||
|
|
|
@ -524,6 +524,7 @@ static const struct regmap_config lcc_msm8960_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0xfc,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc lcc_msm8960_desc = {
|
||||
|
|
|
@ -3368,6 +3368,7 @@ static const struct regmap_config mmcc_apq8084_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x5104,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc mmcc_apq8084_desc = {
|
||||
|
|
|
@ -3029,6 +3029,7 @@ static const struct regmap_config mmcc_msm8960_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x334,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct regmap_config mmcc_apq8064_regmap_config = {
|
||||
|
@ -3037,6 +3038,7 @@ static const struct regmap_config mmcc_apq8064_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x350,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc mmcc_msm8960_desc = {
|
||||
|
|
|
@ -2594,6 +2594,7 @@ static const struct regmap_config mmcc_msm8974_regmap_config = {
|
|||
.val_bits = 32,
|
||||
.max_register = 0x5104,
|
||||
.fast_io = true,
|
||||
.val_format_endian = REGMAP_ENDIAN_LITTLE,
|
||||
};
|
||||
|
||||
static const struct qcom_cc_desc mmcc_msm8974_desc = {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,6 +10,8 @@ obj-y += clk-inverter.o
|
|||
obj-y += clk-mmc-phase.o
|
||||
obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
|
||||
|
||||
obj-y += clk-rk3036.o
|
||||
obj-y += clk-rk3188.o
|
||||
obj-y += clk-rk3228.o
|
||||
obj-y += clk-rk3288.o
|
||||
obj-y += clk-rk3368.o
|
||||
|
|
|
@ -242,8 +242,8 @@ struct clk *rockchip_clk_register_cpuclk(const char *name,
|
|||
struct clk *clk, *cclk;
|
||||
int ret;
|
||||
|
||||
if (num_parents != 2) {
|
||||
pr_err("%s: needs two parent clocks\n", __func__);
|
||||
if (num_parents < 2) {
|
||||
pr_err("%s: needs at least two parent clocks\n", __func__);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* Copyright (c) 2014 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* Copyright (c) 2015 Rockchip Electronics Co. Ltd.
|
||||
* Author: Xing Zheng <zhengxing@rock-chips.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -19,6 +22,7 @@
|
|||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/clk.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define PLL_MODE_MASK 0x3
|
||||
|
@ -107,6 +111,252 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
|
|||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
/**
|
||||
* PLL used in RK3036
|
||||
*/
|
||||
|
||||
#define RK3036_PLLCON(i) (i * 0x4)
|
||||
#define RK3036_PLLCON0_FBDIV_MASK 0xfff
|
||||
#define RK3036_PLLCON0_FBDIV_SHIFT 0
|
||||
#define RK3036_PLLCON0_POSTDIV1_MASK 0x7
|
||||
#define RK3036_PLLCON0_POSTDIV1_SHIFT 12
|
||||
#define RK3036_PLLCON1_REFDIV_MASK 0x3f
|
||||
#define RK3036_PLLCON1_REFDIV_SHIFT 0
|
||||
#define RK3036_PLLCON1_POSTDIV2_MASK 0x7
|
||||
#define RK3036_PLLCON1_POSTDIV2_SHIFT 6
|
||||
#define RK3036_PLLCON1_DSMPD_MASK 0x1
|
||||
#define RK3036_PLLCON1_DSMPD_SHIFT 12
|
||||
#define RK3036_PLLCON2_FRAC_MASK 0xffffff
|
||||
#define RK3036_PLLCON2_FRAC_SHIFT 0
|
||||
|
||||
#define RK3036_PLLCON1_PWRDOWN (1 << 13)
|
||||
|
||||
static void rockchip_rk3036_pll_get_params(struct rockchip_clk_pll *pll,
|
||||
struct rockchip_pll_rate_table *rate)
|
||||
{
|
||||
u32 pllcon;
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(0));
|
||||
rate->fbdiv = ((pllcon >> RK3036_PLLCON0_FBDIV_SHIFT)
|
||||
& RK3036_PLLCON0_FBDIV_MASK);
|
||||
rate->postdiv1 = ((pllcon >> RK3036_PLLCON0_POSTDIV1_SHIFT)
|
||||
& RK3036_PLLCON0_POSTDIV1_MASK);
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(1));
|
||||
rate->refdiv = ((pllcon >> RK3036_PLLCON1_REFDIV_SHIFT)
|
||||
& RK3036_PLLCON1_REFDIV_MASK);
|
||||
rate->postdiv2 = ((pllcon >> RK3036_PLLCON1_POSTDIV2_SHIFT)
|
||||
& RK3036_PLLCON1_POSTDIV2_MASK);
|
||||
rate->dsmpd = ((pllcon >> RK3036_PLLCON1_DSMPD_SHIFT)
|
||||
& RK3036_PLLCON1_DSMPD_MASK);
|
||||
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
|
||||
rate->frac = ((pllcon >> RK3036_PLLCON2_FRAC_SHIFT)
|
||||
& RK3036_PLLCON2_FRAC_MASK);
|
||||
}
|
||||
|
||||
static unsigned long rockchip_rk3036_pll_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
struct rockchip_pll_rate_table cur;
|
||||
u64 rate64 = prate;
|
||||
|
||||
rockchip_rk3036_pll_get_params(pll, &cur);
|
||||
|
||||
rate64 *= cur.fbdiv;
|
||||
do_div(rate64, cur.refdiv);
|
||||
|
||||
if (cur.dsmpd == 0) {
|
||||
/* fractional mode */
|
||||
u64 frac_rate64 = prate * cur.frac;
|
||||
|
||||
do_div(frac_rate64, cur.refdiv);
|
||||
rate64 += frac_rate64 >> 24;
|
||||
}
|
||||
|
||||
do_div(rate64, cur.postdiv1);
|
||||
do_div(rate64, cur.postdiv2);
|
||||
|
||||
return (unsigned long)rate64;
|
||||
}
|
||||
|
||||
static int rockchip_rk3036_pll_set_params(struct rockchip_clk_pll *pll,
|
||||
const struct rockchip_pll_rate_table *rate)
|
||||
{
|
||||
const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
|
||||
struct clk_mux *pll_mux = &pll->pll_mux;
|
||||
struct rockchip_pll_rate_table cur;
|
||||
u32 pllcon;
|
||||
int rate_change_remuxed = 0;
|
||||
int cur_parent;
|
||||
int ret;
|
||||
|
||||
pr_debug("%s: rate settings for %lu fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
|
||||
__func__, rate->rate, rate->fbdiv, rate->postdiv1, rate->refdiv,
|
||||
rate->postdiv2, rate->dsmpd, rate->frac);
|
||||
|
||||
rockchip_rk3036_pll_get_params(pll, &cur);
|
||||
cur.rate = 0;
|
||||
|
||||
cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
|
||||
if (cur_parent == PLL_MODE_NORM) {
|
||||
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
|
||||
rate_change_remuxed = 1;
|
||||
}
|
||||
|
||||
/* update pll values */
|
||||
writel_relaxed(HIWORD_UPDATE(rate->fbdiv, RK3036_PLLCON0_FBDIV_MASK,
|
||||
RK3036_PLLCON0_FBDIV_SHIFT) |
|
||||
HIWORD_UPDATE(rate->postdiv1, RK3036_PLLCON0_POSTDIV1_MASK,
|
||||
RK3036_PLLCON0_POSTDIV1_SHIFT),
|
||||
pll->reg_base + RK3036_PLLCON(0));
|
||||
|
||||
writel_relaxed(HIWORD_UPDATE(rate->refdiv, RK3036_PLLCON1_REFDIV_MASK,
|
||||
RK3036_PLLCON1_REFDIV_SHIFT) |
|
||||
HIWORD_UPDATE(rate->postdiv2, RK3036_PLLCON1_POSTDIV2_MASK,
|
||||
RK3036_PLLCON1_POSTDIV2_SHIFT) |
|
||||
HIWORD_UPDATE(rate->dsmpd, RK3036_PLLCON1_DSMPD_MASK,
|
||||
RK3036_PLLCON1_DSMPD_SHIFT),
|
||||
pll->reg_base + RK3036_PLLCON(1));
|
||||
|
||||
/* GPLL CON2 is not HIWORD_MASK */
|
||||
pllcon = readl_relaxed(pll->reg_base + RK3036_PLLCON(2));
|
||||
pllcon &= ~(RK3036_PLLCON2_FRAC_MASK << RK3036_PLLCON2_FRAC_SHIFT);
|
||||
pllcon |= rate->frac << RK3036_PLLCON2_FRAC_SHIFT;
|
||||
writel_relaxed(pllcon, pll->reg_base + RK3036_PLLCON(2));
|
||||
|
||||
/* wait for the pll to lock */
|
||||
ret = rockchip_pll_wait_lock(pll);
|
||||
if (ret) {
|
||||
pr_warn("%s: pll update unsucessful, trying to restore old params\n",
|
||||
__func__);
|
||||
rockchip_rk3036_pll_set_params(pll, &cur);
|
||||
}
|
||||
|
||||
if (rate_change_remuxed)
|
||||
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rockchip_rk3036_pll_set_rate(struct clk_hw *hw, unsigned long drate,
|
||||
unsigned long prate)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
const struct rockchip_pll_rate_table *rate;
|
||||
unsigned long old_rate = rockchip_rk3036_pll_recalc_rate(hw, prate);
|
||||
struct regmap *grf = rockchip_clk_get_grf();
|
||||
|
||||
if (IS_ERR(grf)) {
|
||||
pr_debug("%s: grf regmap not available, aborting rate change\n",
|
||||
__func__);
|
||||
return PTR_ERR(grf);
|
||||
}
|
||||
|
||||
pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n",
|
||||
__func__, __clk_get_name(hw->clk), old_rate, drate, prate);
|
||||
|
||||
/* Get required rate settings from table */
|
||||
rate = rockchip_get_pll_settings(pll, drate);
|
||||
if (!rate) {
|
||||
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
|
||||
drate, __clk_get_name(hw->clk));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rockchip_rk3036_pll_set_params(pll, rate);
|
||||
}
|
||||
|
||||
static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
|
||||
writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
|
||||
pll->reg_base + RK3036_PLLCON(1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rockchip_rk3036_pll_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
|
||||
writel(HIWORD_UPDATE(RK3036_PLLCON1_PWRDOWN,
|
||||
RK3036_PLLCON1_PWRDOWN, 0),
|
||||
pll->reg_base + RK3036_PLLCON(1));
|
||||
}
|
||||
|
||||
static int rockchip_rk3036_pll_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
u32 pllcon = readl(pll->reg_base + RK3036_PLLCON(1));
|
||||
|
||||
return !(pllcon & RK3036_PLLCON1_PWRDOWN);
|
||||
}
|
||||
|
||||
static void rockchip_rk3036_pll_init(struct clk_hw *hw)
|
||||
{
|
||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||
const struct rockchip_pll_rate_table *rate;
|
||||
struct rockchip_pll_rate_table cur;
|
||||
unsigned long drate;
|
||||
|
||||
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
|
||||
return;
|
||||
|
||||
drate = clk_hw_get_rate(hw);
|
||||
rate = rockchip_get_pll_settings(pll, drate);
|
||||
|
||||
/* when no rate setting for the current rate, rely on clk_set_rate */
|
||||
if (!rate)
|
||||
return;
|
||||
|
||||
rockchip_rk3036_pll_get_params(pll, &cur);
|
||||
|
||||
pr_debug("%s: pll %s@%lu: Hz\n", __func__, __clk_get_name(hw->clk),
|
||||
drate);
|
||||
pr_debug("old - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
|
||||
cur.fbdiv, cur.postdiv1, cur.refdiv, cur.postdiv2,
|
||||
cur.dsmpd, cur.frac);
|
||||
pr_debug("new - fbdiv: %d, postdiv1: %d, refdiv: %d, postdiv2: %d, dsmpd: %d, frac: %d\n",
|
||||
rate->fbdiv, rate->postdiv1, rate->refdiv, rate->postdiv2,
|
||||
rate->dsmpd, rate->frac);
|
||||
|
||||
if (rate->fbdiv != cur.fbdiv || rate->postdiv1 != cur.postdiv1 ||
|
||||
rate->refdiv != cur.refdiv || rate->postdiv2 != cur.postdiv2 ||
|
||||
rate->dsmpd != cur.dsmpd || rate->frac != cur.frac) {
|
||||
struct clk *parent = clk_get_parent(hw->clk);
|
||||
|
||||
if (!parent) {
|
||||
pr_warn("%s: parent of %s not available\n",
|
||||
__func__, __clk_get_name(hw->clk));
|
||||
return;
|
||||
}
|
||||
|
||||
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
|
||||
__func__, __clk_get_name(hw->clk));
|
||||
rockchip_rk3036_pll_set_params(pll, rate);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct clk_ops rockchip_rk3036_pll_clk_norate_ops = {
|
||||
.recalc_rate = rockchip_rk3036_pll_recalc_rate,
|
||||
.enable = rockchip_rk3036_pll_enable,
|
||||
.disable = rockchip_rk3036_pll_disable,
|
||||
.is_enabled = rockchip_rk3036_pll_is_enabled,
|
||||
};
|
||||
|
||||
static const struct clk_ops rockchip_rk3036_pll_clk_ops = {
|
||||
.recalc_rate = rockchip_rk3036_pll_recalc_rate,
|
||||
.round_rate = rockchip_pll_round_rate,
|
||||
.set_rate = rockchip_rk3036_pll_set_rate,
|
||||
.enable = rockchip_rk3036_pll_enable,
|
||||
.disable = rockchip_rk3036_pll_disable,
|
||||
.is_enabled = rockchip_rk3036_pll_is_enabled,
|
||||
.init = rockchip_rk3036_pll_init,
|
||||
};
|
||||
|
||||
/**
|
||||
* PLL used in RK3066, RK3188 and RK3288
|
||||
*/
|
||||
|
@ -376,7 +626,7 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
pll_mux->lock = lock;
|
||||
pll_mux->hw.init = &init;
|
||||
|
||||
if (pll_type == pll_rk3066)
|
||||
if (pll_type == pll_rk3036 || pll_type == pll_rk3066)
|
||||
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
|
||||
|
||||
/* the actual muxing is xin24m, pll-output, xin32k */
|
||||
|
@ -421,6 +671,12 @@ struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type,
|
|||
}
|
||||
|
||||
switch (pll_type) {
|
||||
case pll_rk3036:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &rockchip_rk3036_pll_clk_norate_ops;
|
||||
else
|
||||
init.ops = &rockchip_rk3036_pll_clk_ops;
|
||||
break;
|
||||
case pll_rk3066:
|
||||
if (!pll->rate_table)
|
||||
init.ops = &rockchip_rk3066_pll_clk_norate_ops;
|
||||
|
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* Copyright (c) 2014 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* Copyright (c) 2015 Rockchip Electronics Co. Ltd.
|
||||
* Author: Xing Zheng <zhengxing@rock-chips.com>
|
||||
*
|
||||
* 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/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <dt-bindings/clock/rk3036-cru.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define RK3036_GRF_SOC_STATUS0 0x14c
|
||||
|
||||
enum rk3036_plls {
|
||||
apll, dpll, gpll,
|
||||
};
|
||||
|
||||
static struct rockchip_pll_rate_table rk3036_pll_rates[] = {
|
||||
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
|
||||
RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
#define RK3036_DIV_CPU_MASK 0x1f
|
||||
#define RK3036_DIV_CPU_SHIFT 8
|
||||
|
||||
#define RK3036_DIV_PERI_MASK 0xf
|
||||
#define RK3036_DIV_PERI_SHIFT 0
|
||||
#define RK3036_DIV_ACLK_MASK 0x7
|
||||
#define RK3036_DIV_ACLK_SHIFT 4
|
||||
#define RK3036_DIV_HCLK_MASK 0x3
|
||||
#define RK3036_DIV_HCLK_SHIFT 8
|
||||
#define RK3036_DIV_PCLK_MASK 0x7
|
||||
#define RK3036_DIV_PCLK_SHIFT 12
|
||||
|
||||
#define RK3036_CLKSEL1(_core_periph_div) \
|
||||
{ \
|
||||
.reg = RK2928_CLKSEL_CON(1), \
|
||||
.val = HIWORD_UPDATE(_core_periph_div, RK3036_DIV_PERI_MASK, \
|
||||
RK3036_DIV_PERI_SHIFT) \
|
||||
}
|
||||
|
||||
#define RK3036_CPUCLK_RATE(_prate, _core_periph_div) \
|
||||
{ \
|
||||
.prate = _prate, \
|
||||
.divs = { \
|
||||
RK3036_CLKSEL1(_core_periph_div), \
|
||||
}, \
|
||||
}
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3036_cpuclk_rates[] __initdata = {
|
||||
RK3036_CPUCLK_RATE(816000000, 4),
|
||||
RK3036_CPUCLK_RATE(600000000, 4),
|
||||
RK3036_CPUCLK_RATE(312000000, 4),
|
||||
};
|
||||
|
||||
static const struct rockchip_cpuclk_reg_data rk3036_cpuclk_data = {
|
||||
.core_reg = RK2928_CLKSEL_CON(0),
|
||||
.div_core_shift = 0,
|
||||
.div_core_mask = 0x1f,
|
||||
.mux_core_shift = 7,
|
||||
};
|
||||
|
||||
PNAME(mux_pll_p) = { "xin24m", "xin24m" };
|
||||
|
||||
PNAME(mux_armclk_p) = { "apll", "gpll_armclk" };
|
||||
PNAME(mux_busclk_p) = { "apll", "dpll_cpu", "gpll_cpu" };
|
||||
PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" };
|
||||
PNAME(mux_pll_src_3plls_p) = { "apll", "dpll", "gpll" };
|
||||
PNAME(mux_timer_p) = { "xin24m", "pclk_peri_src" };
|
||||
|
||||
PNAME(mux_pll_src_apll_dpll_gpll_usb480m_p) = { "apll", "dpll", "gpll" "usb480m" };
|
||||
|
||||
PNAME(mux_mmc_src_p) = { "apll", "dpll", "gpll", "xin24m" };
|
||||
PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" };
|
||||
PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" };
|
||||
PNAME(mux_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" };
|
||||
PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
|
||||
PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
|
||||
PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
|
||||
PNAME(mux_mac_p) = { "mac_pll_src", "ext_gmac" };
|
||||
PNAME(mux_dclk_p) = { "dclk_lcdc", "dclk_cru" };
|
||||
|
||||
static struct rockchip_pll_clock rk3036_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
|
||||
RK2928_MODE_CON, 0, 5, 0, rk3036_pll_rates),
|
||||
[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4),
|
||||
RK2928_MODE_CON, 4, 4, 0, NULL),
|
||||
[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12),
|
||||
RK2928_MODE_CON, 12, 6, ROCKCHIP_PLL_SYNC_RATE, rk3036_pll_rates),
|
||||
};
|
||||
|
||||
#define MFLAGS CLK_MUX_HIWORD_MASK
|
||||
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
|
||||
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
|
||||
|
||||
static struct rockchip_clk_branch rk3036_uart0_fracmux __initdata =
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3036_uart1_fracmux __initdata =
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3036_uart2_fracmux __initdata =
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3036_i2s_fracmux __initdata =
|
||||
MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3036_spdif_fracmux __initdata =
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3036_clk_branches[] __initdata = {
|
||||
/*
|
||||
* Clock-Architecture Diagram 1
|
||||
*/
|
||||
|
||||
GATE(0, "gpll_armclk", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 6, GFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 2
|
||||
*/
|
||||
|
||||
GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 2, GFLAGS),
|
||||
GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 8, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "ddrphy2x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
|
||||
|
||||
COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(0), 7, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "aclk_core_pre", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(0), 7, GFLAGS),
|
||||
|
||||
GATE(0, "dpll_cpu", "dpll", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
|
||||
GATE(0, "gpll_cpu", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_busclk_p, 0,
|
||||
RK2928_CLKSEL_CON(0), 14, 2, MFLAGS, 8, 5, DFLAGS),
|
||||
GATE(ACLK_CPU, "aclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 3, GFLAGS),
|
||||
COMPOSITE_NOMUX(PCLK_CPU, "pclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(0), 5, GFLAGS),
|
||||
COMPOSITE_NOMUX(HCLK_CPU, "hclk_cpu", "aclk_cpu_src", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(0), 4, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_peri_src", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(10), 14, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 0, GFLAGS),
|
||||
|
||||
GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
|
||||
RK2928_CLKGATE_CON(2), 1, GFLAGS),
|
||||
DIV(0, "pclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
|
||||
GATE(PCLK_PERI, "pclk_peri", "pclk_peri_src", 0,
|
||||
RK2928_CLKGATE_CON(2), 3, GFLAGS),
|
||||
DIV(0, "hclk_peri_src", "aclk_peri_src", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO),
|
||||
GATE(HCLK_PERI, "hclk_peri", "hclk_peri_src", 0,
|
||||
RK2928_CLKGATE_CON(2), 2, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(SCLK_TIMER0, "sclk_timer0", mux_timer_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(2), 4, 1, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 0, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_TIMER1, "sclk_timer1", mux_timer_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(2), 5, 1, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 1, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_TIMER2, "sclk_timer2", mux_timer_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(2), 6, 1, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 4, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_TIMER3, "sclk_timer3", mux_timer_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(2), 7, 1, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 5, GFLAGS),
|
||||
|
||||
MUX(0, "uart_pll_clk", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
|
||||
RK2928_CLKSEL_CON(13), 10, 2, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "uart0_src", "uart_pll_clk", 0,
|
||||
RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "uart1_src", "uart_pll_clk", 0,
|
||||
RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "uart2_src", "uart_pll_clk", 0,
|
||||
RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(17), 0,
|
||||
RK2928_CLKGATE_CON(1), 9, GFLAGS,
|
||||
&rk3036_uart0_fracmux),
|
||||
COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(18), 0,
|
||||
RK2928_CLKGATE_CON(1), 11, GFLAGS,
|
||||
&rk3036_uart1_fracmux),
|
||||
COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(19), 0,
|
||||
RK2928_CLKGATE_CON(1), 13, GFLAGS,
|
||||
&rk3036_uart2_fracmux),
|
||||
|
||||
COMPOSITE(0, "aclk_vcodec", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 11, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_hvec", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(20), 0, 2, MFLAGS, 2, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(10), 6, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_disp1_pre", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 4, GFLAGS),
|
||||
COMPOSITE(0, "hclk_disp_pre", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 11, GFLAGS),
|
||||
COMPOSITE(SCLK_LCDC, "dclk_lcdc", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(28), 0, 2, MFLAGS, 8, 8, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 2, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_sdmmc_src", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(12), 8, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 11, GFLAGS),
|
||||
DIV(SCLK_SDMMC, "sclk_sdmmc", "sclk_sdmmc_src", 0,
|
||||
RK2928_CLKSEL_CON(11), 0, 7, DFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(12), 10, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 13, GFLAGS),
|
||||
DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
|
||||
RK2928_CLKSEL_CON(11), 8, 7, DFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(12), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 14, GFLAGS),
|
||||
|
||||
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3036_SDMMC_CON0, 1),
|
||||
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3036_SDMMC_CON1, 0),
|
||||
|
||||
MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3036_SDIO_CON0, 1),
|
||||
MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3036_SDIO_CON1, 0),
|
||||
|
||||
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3036_EMMC_CON0, 1),
|
||||
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3036_EMMC_CON1, 0),
|
||||
|
||||
COMPOSITE(0, "i2s_src", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 14, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 9, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(7), 0,
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS,
|
||||
&rk3036_i2s_fracmux),
|
||||
COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_clkout", mux_i2s_clkout_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 13, GFLAGS),
|
||||
GATE(SCLK_I2S, "sclk_i2s", "i2s_pre", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "spdif_src", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 10, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 10, GFLAGS),
|
||||
COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", 0,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(2), 12, GFLAGS,
|
||||
&rk3036_spdif_fracmux),
|
||||
|
||||
GATE(SCLK_OTGPHY0, "sclk_otgphy0", "xin12m", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(1), 5, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(34), 8, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SPI, "sclk_spi", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 9, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 8, 2, MFLAGS, 10, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(10), 4, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_apll_dpll_gpll_usb480m_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 0, 2, MFLAGS, 2, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(10), 5, GFLAGS),
|
||||
|
||||
COMPOSITE_NOGATE(0, "mac_pll_src", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(21), 0, 2, MFLAGS, 4, 5, DFLAGS),
|
||||
MUX(SCLK_MACREF, "mac_clk_ref", mux_mac_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(21), 3, 1, MFLAGS),
|
||||
|
||||
COMPOSITE_NOMUX(SCLK_MAC, "mac_clk", "mac_clk_ref", 0,
|
||||
RK2928_CLKSEL_CON(21), 9, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 6, GFLAGS),
|
||||
|
||||
MUX(SCLK_HDMI, "dclk_hdmi", mux_dclk_p, 0,
|
||||
RK2928_CLKSEL_CON(31), 0, 1, MFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 3
|
||||
*/
|
||||
|
||||
/* aclk_cpu gates */
|
||||
GATE(0, "sclk_intmem", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 12, GFLAGS),
|
||||
GATE(0, "aclk_strc_sys", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 10, GFLAGS),
|
||||
|
||||
/* hclk_cpu gates */
|
||||
GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 6, GFLAGS),
|
||||
|
||||
/* pclk_cpu gates */
|
||||
GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(PCLK_DDRUPCTL, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS),
|
||||
GATE(PCLK_ACODEC, "pclk_acodec", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS),
|
||||
GATE(PCLK_HDMI, "pclk_hdmi", "pclk_cpu", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS),
|
||||
|
||||
/* aclk_vio gates */
|
||||
GATE(ACLK_VIO, "aclk_vio", "aclk_disp1_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(6), 13, GFLAGS),
|
||||
GATE(ACLK_LCDC, "aclk_lcdc", "aclk_disp1_pre", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
|
||||
|
||||
GATE(HCLK_VIO_BUS, "hclk_vio_bus", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS),
|
||||
GATE(HCLK_LCDC, "hclk_lcdc", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
|
||||
|
||||
/* hclk_video gates */
|
||||
GATE(HCLK_VCODEC, "hclk_vcodec", "hclk_disp_pre", 0, RK2928_CLKGATE_CON(3), 12, GFLAGS),
|
||||
|
||||
/* xin24m gates */
|
||||
GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK2928_CLKGATE_CON(10), 0, GFLAGS),
|
||||
GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK2928_CLKGATE_CON(10), 1, GFLAGS),
|
||||
|
||||
/* aclk_peri gates */
|
||||
GATE(0, "aclk_peri_axi_matrix", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 3, GFLAGS),
|
||||
GATE(0, "aclk_cpu_peri", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 2, GFLAGS),
|
||||
GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS),
|
||||
GATE(0, "aclk_peri_niu", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 15, GFLAGS),
|
||||
|
||||
/* hclk_peri gates */
|
||||
GATE(0, "hclk_peri_matrix", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 0, GFLAGS),
|
||||
GATE(0, "hclk_usb_peri", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 13, GFLAGS),
|
||||
GATE(0, "hclk_peri_arbi", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 14, GFLAGS),
|
||||
GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS),
|
||||
GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS),
|
||||
GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS),
|
||||
GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS),
|
||||
GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 13, GFLAGS),
|
||||
GATE(HCLK_OTG1, "hclk_otg1", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(7), 3, GFLAGS),
|
||||
GATE(HCLK_I2S, "hclk_i2s", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS),
|
||||
GATE(0, "hclk_sfc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 14, GFLAGS),
|
||||
GATE(0, "hclk_mac", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(3), 15, GFLAGS),
|
||||
|
||||
/* pclk_peri gates */
|
||||
GATE(0, "pclk_peri_matrix", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(4), 1, GFLAGS),
|
||||
GATE(0, "pclk_efuse", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 2, GFLAGS),
|
||||
GATE(PCLK_TIMER, "pclk_timer", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS),
|
||||
GATE(PCLK_PWM, "pclk_pwm", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS),
|
||||
GATE(PCLK_SPI, "pclk_spi", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS),
|
||||
GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS),
|
||||
GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
|
||||
GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
|
||||
GATE(PCLK_I2C0, "pclk_i2c0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
|
||||
GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS),
|
||||
GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
|
||||
GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
|
||||
GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
|
||||
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
|
||||
};
|
||||
|
||||
static const char *const rk3036_critical_clocks[] __initconst = {
|
||||
"aclk_cpu",
|
||||
"aclk_peri",
|
||||
"hclk_peri",
|
||||
"pclk_peri",
|
||||
};
|
||||
|
||||
static void __init rk3036_clk_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: could not map cru region\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
|
||||
|
||||
/* xin12m is created by an cru-internal divider */
|
||||
clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock xin12m: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock usb480m: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "ddrphy", "ddrphy2x", 0, 1, 2);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock ddrphy: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "hclk_vcodec_pre",
|
||||
"aclk_vcodec", 0, 1, 4);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock hclk_vcodec_pre: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "sclk_macref_out",
|
||||
"hclk_peri_src", 0, 1, 2);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock sclk_macref_out: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
rockchip_clk_register_plls(rk3036_pll_clks,
|
||||
ARRAY_SIZE(rk3036_pll_clks),
|
||||
RK3036_GRF_SOC_STATUS0);
|
||||
rockchip_clk_register_branches(rk3036_clk_branches,
|
||||
ARRAY_SIZE(rk3036_clk_branches));
|
||||
rockchip_clk_protect_critical(rk3036_critical_clocks,
|
||||
ARRAY_SIZE(rk3036_critical_clocks));
|
||||
|
||||
rockchip_clk_register_armclk(ARMCLK, "armclk",
|
||||
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
|
||||
&rk3036_cpuclk_data, rk3036_cpuclk_rates,
|
||||
ARRAY_SIZE(rk3036_cpuclk_rates));
|
||||
|
||||
rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
|
||||
}
|
||||
CLK_OF_DECLARE(rk3036_cru, "rockchip,rk3036-cru", rk3036_clk_init);
|
|
@ -247,6 +247,30 @@ static struct clk_div_table div_core_peri_t[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch common_hsadc_out_fracmux __initdata =
|
||||
MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
|
||||
RK2928_CLKSEL_CON(22), 4, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_spdif_fracmux __initdata =
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_uart0_fracmux __initdata =
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
|
||||
RK2928_CLKSEL_CON(13), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_uart1_fracmux __initdata =
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
|
||||
RK2928_CLKSEL_CON(14), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_uart2_fracmux __initdata =
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
|
||||
RK2928_CLKSEL_CON(15), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_uart3_fracmux __initdata =
|
||||
MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
||||
/*
|
||||
* Clock-Architecture Diagram 2
|
||||
|
@ -335,11 +359,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0,
|
||||
RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 6, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", 0,
|
||||
COMPOSITE_FRACMUX(0, "hsadc_frac", "hsadc_src", 0,
|
||||
RK2928_CLKSEL_CON(23), 0,
|
||||
RK2928_CLKGATE_CON(2), 7, GFLAGS),
|
||||
MUX(0, "sclk_hsadc_out", mux_sclk_hsadc_p, 0,
|
||||
RK2928_CLKSEL_CON(22), 4, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(2), 7, GFLAGS,
|
||||
&common_hsadc_out_fracmux),
|
||||
INVERTER(SCLK_HSADC, "sclk_hsadc", "sclk_hsadc_out",
|
||||
RK2928_CLKSEL_CON(22), 7, IFLAGS),
|
||||
|
||||
|
@ -350,11 +373,10 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(5), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 13, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "spdif_pre", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_pll", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(9), 0,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(5), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS,
|
||||
&common_spdif_fracmux),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 4
|
||||
|
@ -385,35 +407,31 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = {
|
|||
COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0,
|
||||
RK2928_CLKSEL_CON(13), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_pre", 0,
|
||||
RK2928_CLKSEL_CON(17), 0,
|
||||
RK2928_CLKGATE_CON(1), 9, GFLAGS),
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0,
|
||||
RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(1), 9, GFLAGS,
|
||||
&common_uart0_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0,
|
||||
RK2928_CLKSEL_CON(14), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 10, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_pre", 0,
|
||||
RK2928_CLKSEL_CON(18), 0,
|
||||
RK2928_CLKGATE_CON(1), 11, GFLAGS),
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0,
|
||||
RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(1), 11, GFLAGS,
|
||||
&common_uart1_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0,
|
||||
RK2928_CLKSEL_CON(15), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 12, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_pre", 0,
|
||||
RK2928_CLKSEL_CON(19), 0,
|
||||
RK2928_CLKGATE_CON(1), 13, GFLAGS),
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0,
|
||||
RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(1), 13, GFLAGS,
|
||||
&common_uart2_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0,
|
||||
RK2928_CLKSEL_CON(16), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 14, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_pre", 0,
|
||||
RK2928_CLKSEL_CON(20), 0,
|
||||
RK2928_CLKGATE_CON(1), 15, GFLAGS),
|
||||
MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(1), 15, GFLAGS,
|
||||
&common_uart3_fracmux),
|
||||
|
||||
GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS),
|
||||
|
||||
|
@ -523,6 +541,18 @@ static struct clk_div_table div_aclk_cpu_t[] = {
|
|||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
static struct rockchip_clk_branch rk3066a_i2s0_fracmux __initdata =
|
||||
MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(2), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3066a_i2s1_fracmux __initdata =
|
||||
MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3066a_i2s2_fracmux __initdata =
|
||||
MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
|
||||
RK2928_CLKSEL_CON(4), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
|
||||
DIVTBL(0, "aclk_cpu_pre", "armclk", 0,
|
||||
RK2928_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, div_aclk_cpu_t),
|
||||
|
@ -584,27 +614,24 @@ static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = {
|
|||
COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(2), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 7, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
|
||||
RK2928_CLKSEL_CON(6), 0,
|
||||
RK2928_CLKGATE_CON(0), 8, GFLAGS),
|
||||
MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(2), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(0), 8, GFLAGS,
|
||||
&rk3066a_i2s0_fracmux),
|
||||
COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 9, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_pre", 0,
|
||||
RK2928_CLKSEL_CON(7), 0,
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS),
|
||||
MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS,
|
||||
&rk3066a_i2s1_fracmux),
|
||||
COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(4), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 11, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_pre", 0,
|
||||
RK2928_CLKSEL_CON(8), 0,
|
||||
RK2928_CLKGATE_CON(0), 12, GFLAGS),
|
||||
MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0,
|
||||
RK2928_CLKSEL_CON(4), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(0), 12, GFLAGS,
|
||||
&rk3066a_i2s2_fracmux),
|
||||
|
||||
GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS),
|
||||
GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS),
|
||||
|
@ -638,6 +665,10 @@ static struct clk_div_table div_rk3188_aclk_core_t[] = {
|
|||
PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1",
|
||||
"gpll", "cpll" };
|
||||
|
||||
static struct rockchip_clk_branch rk3188_i2s0_fracmux __initdata =
|
||||
MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
|
||||
COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
|
@ -691,11 +722,10 @@ static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = {
|
|||
COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0,
|
||||
RK2928_CLKSEL_CON(3), 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 9, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "i2s0_frac", "i2s0_pre", 0,
|
||||
RK2928_CLKSEL_CON(7), 0,
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS),
|
||||
MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS,
|
||||
&rk3188_i2s0_fracmux),
|
||||
|
||||
GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS),
|
||||
GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS),
|
||||
|
@ -750,7 +780,7 @@ static void __init rk3188_common_clk_init(struct device_node *np)
|
|||
rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(RK2928_GLB_SRST_FST);
|
||||
rockchip_register_restart_notifier(RK2928_GLB_SRST_FST, NULL);
|
||||
}
|
||||
|
||||
static void __init rk3066a_clk_init(struct device_node *np)
|
||||
|
|
|
@ -0,0 +1,678 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Rockchip Electronics Co. Ltd.
|
||||
* Author: Xing Zheng <zhengxing@rock-chips.com>
|
||||
* Jeffy Chen <jeffy.chen@rock-chips.com>
|
||||
*
|
||||
* 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/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/syscore_ops.h>
|
||||
#include <dt-bindings/clock/rk3228-cru.h>
|
||||
#include "clk.h"
|
||||
|
||||
#define RK3228_GRF_SOC_STATUS0 0x480
|
||||
|
||||
enum rk3228_plls {
|
||||
apll, dpll, cpll, gpll,
|
||||
};
|
||||
|
||||
static struct rockchip_pll_rate_table rk3228_pll_rates[] = {
|
||||
/* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
|
||||
RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1560000000, 1, 65, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1536000000, 1, 64, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1512000000, 1, 63, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1488000000, 1, 62, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1464000000, 1, 61, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1440000000, 1, 60, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1416000000, 1, 59, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1392000000, 1, 58, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1368000000, 1, 57, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1344000000, 1, 56, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1320000000, 1, 55, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1296000000, 1, 54, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1272000000, 1, 53, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1248000000, 1, 52, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1200000000, 1, 50, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1188000000, 2, 99, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1104000000, 1, 46, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1100000000, 12, 550, 1, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1008000000, 1, 84, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE(1000000000, 6, 500, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 984000000, 1, 82, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 960000000, 1, 80, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 936000000, 1, 78, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 912000000, 1, 76, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 900000000, 4, 300, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 888000000, 1, 74, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 864000000, 1, 72, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 840000000, 1, 70, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 816000000, 1, 68, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 800000000, 6, 400, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 700000000, 6, 350, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 696000000, 1, 58, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 600000000, 1, 75, 3, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 594000000, 2, 99, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 504000000, 1, 63, 3, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 500000000, 6, 250, 2, 1, 1, 0),
|
||||
RK3036_PLL_RATE( 408000000, 1, 68, 2, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 312000000, 1, 52, 2, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 216000000, 1, 72, 4, 2, 1, 0),
|
||||
RK3036_PLL_RATE( 96000000, 1, 64, 4, 4, 1, 0),
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
|
||||
#define RK3228_DIV_CPU_MASK 0x1f
|
||||
#define RK3228_DIV_CPU_SHIFT 8
|
||||
|
||||
#define RK3228_DIV_PERI_MASK 0xf
|
||||
#define RK3228_DIV_PERI_SHIFT 0
|
||||
#define RK3228_DIV_ACLK_MASK 0x7
|
||||
#define RK3228_DIV_ACLK_SHIFT 4
|
||||
#define RK3228_DIV_HCLK_MASK 0x3
|
||||
#define RK3228_DIV_HCLK_SHIFT 8
|
||||
#define RK3228_DIV_PCLK_MASK 0x7
|
||||
#define RK3228_DIV_PCLK_SHIFT 12
|
||||
|
||||
#define RK3228_CLKSEL1(_core_peri_div) \
|
||||
{ \
|
||||
.reg = RK2928_CLKSEL_CON(1), \
|
||||
.val = HIWORD_UPDATE(_core_peri_div, RK3228_DIV_PERI_MASK, \
|
||||
RK3228_DIV_PERI_SHIFT) \
|
||||
}
|
||||
|
||||
#define RK3228_CPUCLK_RATE(_prate, _core_peri_div) \
|
||||
{ \
|
||||
.prate = _prate, \
|
||||
.divs = { \
|
||||
RK3228_CLKSEL1(_core_peri_div), \
|
||||
}, \
|
||||
}
|
||||
|
||||
static struct rockchip_cpuclk_rate_table rk3228_cpuclk_rates[] __initdata = {
|
||||
RK3228_CPUCLK_RATE(816000000, 4),
|
||||
RK3228_CPUCLK_RATE(600000000, 4),
|
||||
RK3228_CPUCLK_RATE(312000000, 4),
|
||||
};
|
||||
|
||||
static const struct rockchip_cpuclk_reg_data rk3228_cpuclk_data = {
|
||||
.core_reg = RK2928_CLKSEL_CON(0),
|
||||
.div_core_shift = 0,
|
||||
.div_core_mask = 0x1f,
|
||||
.mux_core_shift = 6,
|
||||
};
|
||||
|
||||
PNAME(mux_pll_p) = { "clk_24m", "xin24m" };
|
||||
|
||||
PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr", "apll_ddr" };
|
||||
PNAME(mux_armclk_p) = { "apll_core", "gpll_core", "dpll_core" };
|
||||
PNAME(mux_usb480m_phy_p) = { "usb480m_phy0", "usb480m_phy1" };
|
||||
PNAME(mux_usb480m_p) = { "usb480m_phy", "xin24m" };
|
||||
PNAME(mux_hdmiphy_p) = { "hdmiphy_phy", "xin24m" };
|
||||
PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu", "hdmiphy_aclk_cpu" };
|
||||
|
||||
PNAME(mux_pll_src_4plls_p) = { "cpll", "gpll", "hdmiphy" "usb480m" };
|
||||
PNAME(mux_pll_src_3plls_p) = { "cpll", "gpll", "hdmiphy" };
|
||||
PNAME(mux_pll_src_2plls_p) = { "cpll", "gpll" };
|
||||
PNAME(mux_sclk_hdmi_cec_p) = { "cpll", "gpll", "xin24m" };
|
||||
PNAME(mux_aclk_peri_src_p) = { "cpll_peri", "gpll_peri", "hdmiphy_peri" };
|
||||
PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "usb480m" };
|
||||
PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" };
|
||||
|
||||
PNAME(mux_sclk_rga_p) = { "gpll", "cpll", "sclk_rga_src" };
|
||||
|
||||
PNAME(mux_sclk_vop_src_p) = { "gpll_vop", "cpll_vop" };
|
||||
PNAME(mux_dclk_vop_p) = { "hdmiphy", "sclk_vop_pre" };
|
||||
|
||||
PNAME(mux_i2s0_p) = { "i2s0_src", "i2s0_frac", "ext_i2s", "xin12m" };
|
||||
PNAME(mux_i2s1_pre_p) = { "i2s1_src", "i2s1_frac", "ext_i2s", "xin12m" };
|
||||
PNAME(mux_i2s_out_p) = { "i2s1_pre", "xin12m" };
|
||||
PNAME(mux_i2s2_p) = { "i2s2_src", "i2s2_frac", "xin12m" };
|
||||
PNAME(mux_sclk_spdif_p) = { "sclk_spdif_src", "spdif_frac", "xin12m" };
|
||||
|
||||
PNAME(mux_aclk_gpu_pre_p) = { "cpll_gpu", "gpll_gpu", "hdmiphy_gpu", "usb480m_gpu" };
|
||||
|
||||
PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" };
|
||||
PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" };
|
||||
PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" };
|
||||
|
||||
PNAME(mux_sclk_macphy_50m_p) = { "ext_gmac", "phy_50m_out" };
|
||||
PNAME(mux_sclk_gmac_pre_p) = { "sclk_gmac_src", "sclk_macphy_50m" };
|
||||
PNAME(mux_sclk_macphy_p) = { "sclk_gmac_src", "ext_gmac" };
|
||||
|
||||
static struct rockchip_pll_clock rk3228_pll_clks[] __initdata = {
|
||||
[apll] = PLL(pll_rk3036, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0),
|
||||
RK2928_MODE_CON, 0, 7, 0, rk3228_pll_rates),
|
||||
[dpll] = PLL(pll_rk3036, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(3),
|
||||
RK2928_MODE_CON, 4, 6, 0, NULL),
|
||||
[cpll] = PLL(pll_rk3036, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(6),
|
||||
RK2928_MODE_CON, 8, 8, 0, NULL),
|
||||
[gpll] = PLL(pll_rk3036, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(9),
|
||||
RK2928_MODE_CON, 12, 9, ROCKCHIP_PLL_SYNC_RATE, rk3228_pll_rates),
|
||||
};
|
||||
|
||||
#define MFLAGS CLK_MUX_HIWORD_MASK
|
||||
#define DFLAGS CLK_DIVIDER_HIWORD_MASK
|
||||
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
|
||||
|
||||
static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = {
|
||||
/*
|
||||
* Clock-Architecture Diagram 1
|
||||
*/
|
||||
|
||||
DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(4), 8, 5, DFLAGS),
|
||||
|
||||
/* PD_DDR */
|
||||
GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 2, GFLAGS),
|
||||
GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 2, GFLAGS),
|
||||
GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 2, GFLAGS),
|
||||
COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
|
||||
RK2928_CLKGATE_CON(7), 1, GFLAGS),
|
||||
GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(8), 5, GFLAGS),
|
||||
GATE(0, "ddrphy", "ddrphy_pre", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(7), 0, GFLAGS),
|
||||
|
||||
/* PD_CORE */
|
||||
GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 6, GFLAGS),
|
||||
GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 6, GFLAGS),
|
||||
GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 6, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(4), 1, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "armcore", "armclk", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
|
||||
RK2928_CLKGATE_CON(4), 0, GFLAGS),
|
||||
|
||||
/* PD_MISC */
|
||||
MUX(0, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 13, 1, MFLAGS),
|
||||
MUX(0, "usb480m_phy", mux_usb480m_phy_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 14, 1, MFLAGS),
|
||||
MUX(0, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_MISC_CON, 15, 1, MFLAGS),
|
||||
|
||||
/* PD_BUS */
|
||||
GATE(0, "hdmiphy_aclk_cpu", "hdmiphy", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 1, GFLAGS),
|
||||
GATE(0, "gpll_aclk_cpu", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 1, GFLAGS),
|
||||
GATE(0, "cpll_aclk_cpu", "cpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(0), 1, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0,
|
||||
RK2928_CLKSEL_CON(0), 13, 2, MFLAGS, 8, 5, DFLAGS),
|
||||
GATE(ARMCLK, "aclk_cpu", "aclk_cpu_src", 0,
|
||||
RK2928_CLKGATE_CON(6), 0, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "hclk_cpu", "aclk_cpu_src", 0,
|
||||
RK2928_CLKSEL_CON(1), 8, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(6), 1, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "pclk_bus_src", "aclk_cpu_src", 0,
|
||||
RK2928_CLKSEL_CON(1), 12, 3, DFLAGS,
|
||||
RK2928_CLKGATE_CON(6), 2, GFLAGS),
|
||||
GATE(0, "pclk_cpu", "pclk_bus_src", 0,
|
||||
RK2928_CLKGATE_CON(6), 3, GFLAGS),
|
||||
GATE(0, "pclk_phy_pre", "pclk_bus_src", 0,
|
||||
RK2928_CLKGATE_CON(6), 4, GFLAGS),
|
||||
GATE(0, "pclk_ddr_pre", "pclk_bus_src", 0,
|
||||
RK2928_CLKGATE_CON(6), 13, GFLAGS),
|
||||
|
||||
/* PD_VIDEO */
|
||||
COMPOSITE(0, "aclk_vpu_pre", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(32), 5, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 11, GFLAGS),
|
||||
GATE(0, "hclk_vpu_src", "aclk_vpu_pre", 0,
|
||||
RK2928_CLKGATE_CON(4), 4, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_rkvdec_pre", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 2, GFLAGS),
|
||||
GATE(0, "hclk_rkvdec_src", "aclk_rkvdec_pre", 0,
|
||||
RK2928_CLKGATE_CON(4), 5, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_vdec_cabac", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(28), 14, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 3, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_vdec_core", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(34), 13, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 4, GFLAGS),
|
||||
|
||||
/* PD_VIO */
|
||||
COMPOSITE(0, "aclk_iep_pre", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(31), 5, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 0, GFLAGS),
|
||||
DIV(0, "hclk_vio_pre", "aclk_iep_pre", 0,
|
||||
RK2928_CLKSEL_CON(2), 0, 5, DFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_hdcp_pre", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(31), 13, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 4, GFLAGS),
|
||||
|
||||
MUX(0, "sclk_rga_src", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(33), 13, 2, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "aclk_rga_pre", "sclk_rga_src", 0,
|
||||
RK2928_CLKSEL_CON(33), 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 2, GFLAGS),
|
||||
COMPOSITE(0, "sclk_rga", mux_sclk_rga_p, 0,
|
||||
RK2928_CLKSEL_CON(22), 5, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 6, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "aclk_vop_pre", mux_pll_src_4plls_p, 0,
|
||||
RK2928_CLKSEL_CON(33), 5, 2, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 1, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_hdcp", mux_pll_src_3plls_p, 0,
|
||||
RK2928_CLKSEL_CON(23), 14, 2, MFLAGS, 8, 6, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 5, GFLAGS),
|
||||
|
||||
GATE(0, "sclk_hdmi_hdcp", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(3), 7, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_hdmi_cec", mux_sclk_hdmi_cec_p, 0,
|
||||
RK2928_CLKSEL_CON(21), 14, 2, MFLAGS, 0, 14, DFLAGS,
|
||||
RK2928_CLKGATE_CON(3), 8, GFLAGS),
|
||||
|
||||
/* PD_PERI */
|
||||
GATE(0, "cpll_peri", "cpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(2), 0, GFLAGS),
|
||||
GATE(0, "gpll_peri", "gpll", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(2), 0, GFLAGS),
|
||||
GATE(0, "hdmiphy_peri", "hdmiphy", CLK_IGNORE_UNUSED,
|
||||
RK2928_CLKGATE_CON(2), 0, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "aclk_peri_src", mux_aclk_peri_src_p, 0,
|
||||
RK2928_CLKSEL_CON(10), 10, 2, MFLAGS, 0, 5, DFLAGS),
|
||||
COMPOSITE_NOMUX(PCLK_PERI, "pclk_peri", "aclk_peri_src", 0,
|
||||
RK2928_CLKSEL_CON(10), 12, 3, DFLAGS,
|
||||
RK2928_CLKGATE_CON(5), 2, GFLAGS),
|
||||
COMPOSITE_NOMUX(HCLK_PERI, "hclk_peri", "aclk_peri_src", 0,
|
||||
RK2928_CLKSEL_CON(10), 8, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(5), 1, GFLAGS),
|
||||
GATE(ACLK_PERI, "aclk_peri", "aclk_peri_src", 0,
|
||||
RK2928_CLKGATE_CON(5), 0, GFLAGS),
|
||||
|
||||
GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 5, GFLAGS),
|
||||
GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 6, GFLAGS),
|
||||
GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 7, GFLAGS),
|
||||
GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 8, GFLAGS),
|
||||
GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 9, GFLAGS),
|
||||
GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(6), 10, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_crypto", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(24), 5, 1, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 7, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_tsp", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(22), 15, 1, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 6, GFLAGS),
|
||||
|
||||
GATE(0, "sclk_hsadc", "ext_hsadc", 0,
|
||||
RK3288_CLKGATE_CON(10), 12, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_wifi", mux_pll_src_cpll_gpll_usb480m_p, 0,
|
||||
RK2928_CLKSEL_CON(23), 5, 2, MFLAGS, 0, 6, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 15, GFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(11), 8, 2, MFLAGS, 0, 8, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 11, GFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(11), 10, 2, MFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 13, GFLAGS),
|
||||
DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
|
||||
RK2928_CLKSEL_CON(12), 0, 8, DFLAGS),
|
||||
|
||||
COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
|
||||
RK2928_CLKSEL_CON(11), 12, 2, MFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 14, GFLAGS),
|
||||
DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
|
||||
RK2928_CLKSEL_CON(12), 8, 8, DFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 2
|
||||
*/
|
||||
|
||||
GATE(0, "gpll_vop", "gpll", 0,
|
||||
RK2928_CLKGATE_CON(3), 1, GFLAGS),
|
||||
GATE(0, "cpll_vop", "cpll", 0,
|
||||
RK2928_CLKGATE_CON(3), 1, GFLAGS),
|
||||
MUX(0, "sclk_vop_src", mux_sclk_vop_src_p, 0,
|
||||
RK2928_CLKSEL_CON(27), 0, 1, MFLAGS),
|
||||
DIV(0, "dclk_hdmiphy", "sclk_vop_src", 0,
|
||||
RK2928_CLKSEL_CON(29), 0, 3, DFLAGS),
|
||||
DIV(0, "sclk_vop_pre", "sclk_vop_src", 0,
|
||||
RK2928_CLKSEL_CON(27), 8, 8, DFLAGS),
|
||||
MUX(0, "dclk_vop", mux_dclk_vop_p, 0,
|
||||
RK2928_CLKSEL_CON(27), 1, 1, MFLAGS),
|
||||
|
||||
COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(9), 15, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 3, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(8), 0,
|
||||
RK3288_CLKGATE_CON(0), 4, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_I2S0, "sclk_i2s0", mux_i2s0_p, 0,
|
||||
RK2928_CLKSEL_CON(9), 8, 2, MFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 5, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 15, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 10, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(7), 0,
|
||||
RK3288_CLKGATE_CON(0), 11, GFLAGS),
|
||||
MUX(0, "i2s1_pre", mux_i2s1_pre_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 8, 2, MFLAGS),
|
||||
GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", 0,
|
||||
RK2928_CLKGATE_CON(0), 14, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_I2S_OUT, "i2s_out", mux_i2s_out_p, 0,
|
||||
RK2928_CLKSEL_CON(3), 12, 1, MFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 13, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 15, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 7, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(30), 0,
|
||||
RK3288_CLKGATE_CON(0), 8, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_I2S2, "sclk_i2s2", mux_i2s2_p, 0,
|
||||
RK2928_CLKSEL_CON(16), 8, 2, MFLAGS,
|
||||
RK2928_CLKGATE_CON(0), 9, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_spdif_src", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(6), 15, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 10, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "sclk_spdif_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(20), 0,
|
||||
RK3288_CLKGATE_CON(2), 12, GFLAGS),
|
||||
MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0,
|
||||
RK2928_CLKSEL_CON(6), 8, 2, MFLAGS),
|
||||
|
||||
GATE(0, "jtag", "ext_jtag", 0,
|
||||
RK2928_CLKGATE_CON(1), 3, GFLAGS),
|
||||
|
||||
GATE(0, "sclk_otgphy0", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(1), 5, GFLAGS),
|
||||
GATE(0, "sclk_otgphy1", "xin24m", 0,
|
||||
RK2928_CLKGATE_CON(1), 6, GFLAGS),
|
||||
|
||||
COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0,
|
||||
RK2928_CLKSEL_CON(24), 6, 10, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 8, GFLAGS),
|
||||
|
||||
GATE(0, "cpll_gpu", "cpll", 0,
|
||||
RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
||||
GATE(0, "gpll_gpu", "gpll", 0,
|
||||
RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
||||
GATE(0, "hdmiphy_gpu", "hdmiphy", 0,
|
||||
RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
||||
GATE(0, "usb480m_gpu", "usb480m", 0,
|
||||
RK2928_CLKGATE_CON(3), 13, GFLAGS),
|
||||
COMPOSITE_NOGATE(0, "aclk_gpu_pre", mux_aclk_gpu_pre_p, 0,
|
||||
RK2928_CLKSEL_CON(34), 5, 2, MFLAGS, 0, 5, DFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(25), 8, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 9, GFLAGS),
|
||||
|
||||
/* PD_UART */
|
||||
COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gpll_usb480m_p, 0,
|
||||
RK2928_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE(0, "uart1_src", mux_pll_src_cpll_gpll_usb480m_p, 0,
|
||||
RK2928_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 10, GFLAGS),
|
||||
COMPOSITE(0, "uart2_src", mux_pll_src_cpll_gpll_usb480m_p,
|
||||
0, RK2928_CLKSEL_CON(15), 12, 2,
|
||||
MFLAGS, 0, 7, DFLAGS, RK2928_CLKGATE_CON(1), 12, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(17), 0,
|
||||
RK2928_CLKGATE_CON(1), 9, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(18), 0,
|
||||
RK2928_CLKGATE_CON(1), 11, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(19), 0,
|
||||
RK2928_CLKGATE_CON(1), 13, GFLAGS),
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(13), 8, 2, MFLAGS),
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(14), 8, 2, MFLAGS),
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
|
||||
RK2928_CLKSEL_CON(15), 8, 2, MFLAGS),
|
||||
|
||||
COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(2), 14, 1, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 0, GFLAGS),
|
||||
|
||||
COMPOSITE(0, "sclk_gmac_src", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 7, 1, MFLAGS, 0, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(1), 7, GFLAGS),
|
||||
MUX(0, "sclk_macphy_50m", mux_sclk_macphy_50m_p, 0,
|
||||
RK2928_CLKSEL_CON(29), 10, 1, MFLAGS),
|
||||
MUX(0, "sclk_gmac_pre", mux_sclk_gmac_pre_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 5, 1, MFLAGS),
|
||||
GATE(0, "sclk_mac_refout", "sclk_gmac_pre", 0,
|
||||
RK2928_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(0, "sclk_mac_ref", "sclk_gmac_pre", 0,
|
||||
RK2928_CLKGATE_CON(5), 3, GFLAGS),
|
||||
GATE(0, "sclk_mac_rx", "sclk_gmac_pre", 0,
|
||||
RK2928_CLKGATE_CON(5), 5, GFLAGS),
|
||||
GATE(0, "sclk_mac_tx", "sclk_gmac_pre", 0,
|
||||
RK2928_CLKGATE_CON(5), 6, GFLAGS),
|
||||
COMPOSITE(0, "sclk_macphy", mux_sclk_macphy_p, 0,
|
||||
RK2928_CLKSEL_CON(29), 12, 1, MFLAGS, 8, 2, DFLAGS,
|
||||
RK2928_CLKGATE_CON(5), 7, GFLAGS),
|
||||
COMPOSITE(0, "sclk_gmac_out", mux_pll_src_2plls_p, 0,
|
||||
RK2928_CLKSEL_CON(5), 15, 1, MFLAGS, 8, 5, DFLAGS,
|
||||
RK2928_CLKGATE_CON(2), 2, GFLAGS),
|
||||
|
||||
/*
|
||||
* Clock-Architecture Diagram 3
|
||||
*/
|
||||
|
||||
/* PD_VOP */
|
||||
GATE(0, "aclk_rga", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 0, GFLAGS),
|
||||
GATE(0, "aclk_rga_noc", "aclk_rga_pre", 0, RK2928_CLKGATE_CON(13), 11, GFLAGS),
|
||||
GATE(0, "aclk_iep", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 2, GFLAGS),
|
||||
GATE(0, "aclk_iep_noc", "aclk_iep_pre", 0, RK2928_CLKGATE_CON(13), 9, GFLAGS),
|
||||
|
||||
GATE(0, "aclk_vop", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 5, GFLAGS),
|
||||
GATE(0, "aclk_vop_noc", "aclk_vop_pre", 0, RK2928_CLKGATE_CON(13), 12, GFLAGS),
|
||||
|
||||
GATE(0, "aclk_hdcp", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(14), 10, GFLAGS),
|
||||
GATE(0, "aclk_hdcp_noc", "aclk_hdcp_pre", 0, RK2928_CLKGATE_CON(13), 10, GFLAGS),
|
||||
|
||||
GATE(0, "hclk_rga", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 1, GFLAGS),
|
||||
GATE(0, "hclk_iep", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 3, GFLAGS),
|
||||
GATE(0, "hclk_vop", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 6, GFLAGS),
|
||||
GATE(0, "hclk_vio_ahb_arbi", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 7, GFLAGS),
|
||||
GATE(0, "hclk_vio_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 8, GFLAGS),
|
||||
GATE(0, "hclk_vop_noc", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(13), 13, GFLAGS),
|
||||
GATE(0, "hclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 7, GFLAGS),
|
||||
GATE(0, "hclk_hdcp_mmu", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 12, GFLAGS),
|
||||
GATE(0, "pclk_hdmi_ctrl", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 6, GFLAGS),
|
||||
GATE(0, "pclk_vio_h2p", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 8, GFLAGS),
|
||||
GATE(0, "pclk_hdcp", "hclk_vio_pre", 0, RK2928_CLKGATE_CON(14), 11, GFLAGS),
|
||||
|
||||
/* PD_PERI */
|
||||
GATE(0, "aclk_peri_noc", "aclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 0, GFLAGS),
|
||||
GATE(0, "aclk_gmac", "aclk_peri", 0, RK2928_CLKGATE_CON(11), 4, GFLAGS),
|
||||
|
||||
GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 0, GFLAGS),
|
||||
GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 1, GFLAGS),
|
||||
GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 2, GFLAGS),
|
||||
GATE(HCLK_NANDC, "hclk_nandc", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 3, GFLAGS),
|
||||
GATE(0, "hclk_host0", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 6, GFLAGS),
|
||||
GATE(0, "hclk_host0_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 7, GFLAGS),
|
||||
GATE(0, "hclk_host1", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 8, GFLAGS),
|
||||
GATE(0, "hclk_host1_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 9, GFLAGS),
|
||||
GATE(0, "hclk_host2", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 10, GFLAGS),
|
||||
GATE(0, "hclk_otg", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 12, GFLAGS),
|
||||
GATE(0, "hclk_otg_pmu", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 13, GFLAGS),
|
||||
GATE(0, "hclk_host2_arb", "hclk_peri", 0, RK2928_CLKGATE_CON(11), 14, GFLAGS),
|
||||
GATE(0, "hclk_peri_noc", "hclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 1, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_gmac", "pclk_peri", 0, RK2928_CLKGATE_CON(11), 5, GFLAGS),
|
||||
GATE(0, "pclk_peri_noc", "pclk_peri", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(12), 2, GFLAGS),
|
||||
|
||||
/* PD_GPU */
|
||||
GATE(0, "aclk_gpu", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 14, GFLAGS),
|
||||
GATE(0, "aclk_gpu_noc", "aclk_gpu_pre", 0, RK2928_CLKGATE_CON(13), 15, GFLAGS),
|
||||
|
||||
/* PD_BUS */
|
||||
GATE(0, "sclk_initmem_mbist", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS),
|
||||
GATE(0, "aclk_initmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS),
|
||||
GATE(ACLK_DMAC, "aclk_dmac_bus", "aclk_cpu", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS),
|
||||
GATE(0, "aclk_bus_noc", "aclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS),
|
||||
|
||||
GATE(0, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS),
|
||||
GATE(0, "hclk_i2s0_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS),
|
||||
GATE(0, "hclk_i2s1_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS),
|
||||
GATE(0, "hclk_i2s2_2ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS),
|
||||
GATE(0, "hclk_spdif_8ch", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS),
|
||||
GATE(0, "hclk_tsp", "hclk_cpu", 0, RK2928_CLKGATE_CON(10), 11, GFLAGS),
|
||||
GATE(0, "hclk_crypto_mst", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS),
|
||||
GATE(0, "hclk_crypto_slv", "hclk_cpu", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_ddrupctl", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS),
|
||||
GATE(0, "pclk_ddrmon", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS),
|
||||
GATE(0, "pclk_msch_noc", "pclk_ddr_pre", 0, RK2928_CLKGATE_CON(10), 2, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS),
|
||||
GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 14, GFLAGS),
|
||||
GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS),
|
||||
GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS),
|
||||
GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS),
|
||||
GATE(PCLK_I2C3, "pclk_i2c3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS),
|
||||
GATE(PCLK_TIMER, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 4, GFLAGS),
|
||||
GATE(0, "pclk_stimer", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS),
|
||||
GATE(PCLK_SPI0, "pclk_spi0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS),
|
||||
GATE(PCLK_PWM, "pclk_rk_pwm", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 7, GFLAGS),
|
||||
GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 8, GFLAGS),
|
||||
GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 9, GFLAGS),
|
||||
GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 10, GFLAGS),
|
||||
GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 11, GFLAGS),
|
||||
GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 12, GFLAGS),
|
||||
GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 13, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 14, GFLAGS),
|
||||
GATE(0, "pclk_tsadc", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 15, GFLAGS),
|
||||
GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 0, GFLAGS),
|
||||
GATE(0, "pclk_cru", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 1, GFLAGS),
|
||||
GATE(0, "pclk_sgrf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(10), 2, GFLAGS),
|
||||
GATE(0, "pclk_sim", "pclk_cpu", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
|
||||
|
||||
GATE(0, "pclk_ddrphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 3, GFLAGS),
|
||||
GATE(0, "pclk_acodecphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 5, GFLAGS),
|
||||
GATE(0, "pclk_hdmiphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 7, GFLAGS),
|
||||
GATE(0, "pclk_vdacphy", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 8, GFLAGS),
|
||||
GATE(0, "pclk_phy_noc", "pclk_phy_pre", 0, RK2928_CLKGATE_CON(10), 9, GFLAGS),
|
||||
|
||||
GATE(0, "aclk_vpu", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 0, GFLAGS),
|
||||
GATE(0, "aclk_vpu_noc", "aclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 4, GFLAGS),
|
||||
GATE(0, "aclk_rkvdec", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 2, GFLAGS),
|
||||
GATE(0, "aclk_rkvdec_noc", "aclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 6, GFLAGS),
|
||||
GATE(0, "hclk_vpu", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 1, GFLAGS),
|
||||
GATE(0, "hclk_vpu_noc", "hclk_vpu_pre", 0, RK2928_CLKGATE_CON(15), 5, GFLAGS),
|
||||
GATE(0, "hclk_rkvdec", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 3, GFLAGS),
|
||||
GATE(0, "hclk_rkvdec_noc", "hclk_rkvdec_pre", 0, RK2928_CLKGATE_CON(15), 7, GFLAGS),
|
||||
|
||||
/* PD_MMC */
|
||||
MMC(SCLK_SDMMC_DRV, "sdmmc_drv", "sclk_sdmmc", RK3228_SDMMC_CON0, 1),
|
||||
MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK3228_SDMMC_CON1, 1),
|
||||
|
||||
MMC(SCLK_SDIO_DRV, "sdio_drv", "sclk_sdio", RK3228_SDIO_CON0, 1),
|
||||
MMC(SCLK_SDIO_SAMPLE, "sdio_sample", "sclk_sdio", RK3228_SDIO_CON1, 1),
|
||||
|
||||
MMC(SCLK_EMMC_DRV, "emmc_drv", "sclk_emmc", RK3228_EMMC_CON0, 1),
|
||||
MMC(SCLK_EMMC_SAMPLE, "emmc_sample", "sclk_emmc", RK3228_EMMC_CON1, 1),
|
||||
};
|
||||
|
||||
static const char *const rk3228_critical_clocks[] __initconst = {
|
||||
"aclk_cpu",
|
||||
"aclk_peri",
|
||||
"hclk_peri",
|
||||
"pclk_peri",
|
||||
};
|
||||
|
||||
static void __init rk3228_clk_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
pr_err("%s: could not map cru region\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
|
||||
|
||||
/* xin12m is created by an cru-internal divider */
|
||||
clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock xin12m: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "ddrphy_pre", "ddrphy4x", 0, 1, 4);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock ddrphy_pre: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "hclk_vpu_pre",
|
||||
"hclk_vpu_src", 0, 1, 4);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock hclk_vpu_pre: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
clk = clk_register_fixed_factor(NULL, "hclk_rkvdec_pre",
|
||||
"hclk_rkvdec_src", 0, 1, 4);
|
||||
if (IS_ERR(clk))
|
||||
pr_warn("%s: could not register clock hclk_rkvdec_pre: %ld\n",
|
||||
__func__, PTR_ERR(clk));
|
||||
|
||||
rockchip_clk_register_plls(rk3228_pll_clks,
|
||||
ARRAY_SIZE(rk3228_pll_clks),
|
||||
RK3228_GRF_SOC_STATUS0);
|
||||
rockchip_clk_register_branches(rk3228_clk_branches,
|
||||
ARRAY_SIZE(rk3228_clk_branches));
|
||||
rockchip_clk_protect_critical(rk3228_critical_clocks,
|
||||
ARRAY_SIZE(rk3228_critical_clocks));
|
||||
|
||||
rockchip_clk_register_armclk(ARMCLK, "armclk",
|
||||
mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
|
||||
&rk3228_cpuclk_data, rk3228_cpuclk_rates,
|
||||
ARRAY_SIZE(rk3228_cpuclk_rates));
|
||||
|
||||
rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(RK3228_GLB_SRST_FST, NULL);
|
||||
}
|
||||
CLK_OF_DECLARE(rk3228_cru, "rockchip,rk3228-cru", rk3228_clk_init);
|
|
@ -225,6 +225,38 @@ static struct clk_div_table div_hclk_cpu_t[] = {
|
|||
#define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
|
||||
#define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
|
||||
|
||||
static struct rockchip_clk_branch rk3288_i2s_fracmux __initdata =
|
||||
MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(4), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_spdif_fracmux __initdata =
|
||||
MUX(0, "spdif_mux", mux_spdif_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(5), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_spdif_8ch_fracmux __initdata =
|
||||
MUX(0, "spdif_8ch_mux", mux_spdif_8ch_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(40), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_uart0_fracmux __initdata =
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(13), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_uart1_fracmux __initdata =
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(14), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_uart2_fracmux __initdata =
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(15), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_uart3_fracmux __initdata =
|
||||
MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(16), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_uart4_fracmux __initdata =
|
||||
MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(3), 8, 2, MFLAGS);
|
||||
|
||||
static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
||||
/*
|
||||
* Clock-Architecture Diagram 1
|
||||
|
@ -295,7 +327,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
RK3288_CLKGATE_CON(0), 4, GFLAGS),
|
||||
GATE(0, "c2c_host", "aclk_cpu_src", 0,
|
||||
RK3288_CLKGATE_CON(13), 8, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0,
|
||||
COMPOSITE_NOMUX(SCLK_CRYPTO, "crypto", "aclk_cpu_pre", 0,
|
||||
RK3288_CLKSEL_CON(26), 6, 2, DFLAGS,
|
||||
RK3288_CLKGATE_CON(5), 4, GFLAGS),
|
||||
GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", CLK_IGNORE_UNUSED,
|
||||
|
@ -304,11 +336,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0,
|
||||
RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 1, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "i2s_frac", "i2s_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(8), 0,
|
||||
RK3288_CLKGATE_CON(4), 2, GFLAGS),
|
||||
MUX(0, "i2s_pre", mux_i2s_pre_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(4), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(4), 2, GFLAGS,
|
||||
&rk3288_i2s_fracmux),
|
||||
COMPOSITE_NODIV(SCLK_I2S0_OUT, "i2s0_clkout", mux_i2s_clkout_p, 0,
|
||||
RK3288_CLKSEL_CON(4), 12, 1, MFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 0, GFLAGS),
|
||||
|
@ -317,23 +348,23 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
|
||||
MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0,
|
||||
RK3288_CLKSEL_CON(5), 15, 1, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0,
|
||||
COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(5), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 4, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0,
|
||||
COMPOSITE_FRACMUX(0, "spdif_frac", "spdif_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(9), 0,
|
||||
RK3288_CLKGATE_CON(4), 5, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0,
|
||||
RK3288_CLKSEL_CON(5), 8, 2, MFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 5, GFLAGS,
|
||||
&rk3288_spdif_fracmux),
|
||||
GATE(SCLK_SPDIF, "sclk_spdif", "spdif_mux", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKGATE_CON(4), 6, GFLAGS),
|
||||
COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0,
|
||||
COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(40), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 7, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_pre", 0,
|
||||
COMPOSITE_FRACMUX(0, "spdif_8ch_frac", "spdif_8ch_pre", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(41), 0,
|
||||
RK3288_CLKGATE_CON(4), 8, GFLAGS),
|
||||
COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0,
|
||||
RK3288_CLKSEL_CON(40), 8, 2, MFLAGS,
|
||||
RK3288_CLKGATE_CON(4), 8, GFLAGS,
|
||||
&rk3288_spdif_8ch_fracmux),
|
||||
GATE(SCLK_SPDIF8CH, "sclk_spdif_8ch", "spdif_8ch_mux", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKGATE_CON(4), 9, GFLAGS),
|
||||
|
||||
GATE(0, "sclk_acc_efuse", "xin24m", 0,
|
||||
|
@ -536,45 +567,40 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
COMPOSITE(0, "uart0_src", mux_pll_src_cpll_gll_usb_npll_p, 0,
|
||||
RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(1), 8, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(17), 0,
|
||||
RK3288_CLKGATE_CON(1), 9, GFLAGS),
|
||||
MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(13), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(1), 9, GFLAGS,
|
||||
&rk3288_uart0_fracmux),
|
||||
MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0,
|
||||
RK3288_CLKSEL_CON(13), 15, 1, MFLAGS),
|
||||
COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0,
|
||||
RK3288_CLKSEL_CON(14), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(1), 10, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(18), 0,
|
||||
RK3288_CLKGATE_CON(1), 11, GFLAGS),
|
||||
MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(14), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(1), 11, GFLAGS,
|
||||
&rk3288_uart1_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0,
|
||||
RK3288_CLKSEL_CON(15), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(1), 12, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(19), 0,
|
||||
RK3288_CLKGATE_CON(1), 13, GFLAGS),
|
||||
MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(15), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(1), 13, GFLAGS,
|
||||
&rk3288_uart2_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0,
|
||||
RK3288_CLKSEL_CON(16), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(1), 14, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "uart3_frac", "uart3_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(20), 0,
|
||||
RK3288_CLKGATE_CON(1), 15, GFLAGS),
|
||||
MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(16), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(1), 15, GFLAGS,
|
||||
&rk3288_uart3_fracmux),
|
||||
COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0,
|
||||
RK3288_CLKSEL_CON(3), 0, 7, DFLAGS,
|
||||
RK3288_CLKGATE_CON(2), 12, GFLAGS),
|
||||
COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
|
||||
COMPOSITE_FRACMUX(0, "uart4_frac", "uart4_src", CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(7), 0,
|
||||
RK3288_CLKGATE_CON(2), 13, GFLAGS),
|
||||
MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT,
|
||||
RK3288_CLKSEL_CON(3), 8, 2, MFLAGS),
|
||||
RK3288_CLKGATE_CON(2), 13, GFLAGS,
|
||||
&rk3288_uart4_fracmux),
|
||||
|
||||
COMPOSITE(0, "mac_pll_src", mux_pll_src_npll_cpll_gpll_p, 0,
|
||||
RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS,
|
||||
|
@ -644,10 +670,10 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
GATE(PCLK_PUBL0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS),
|
||||
GATE(PCLK_DDRUPCTL1, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS),
|
||||
GATE(PCLK_PUBL1, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS),
|
||||
GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
|
||||
GATE(PCLK_EFUSE1024, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS),
|
||||
GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS),
|
||||
GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS),
|
||||
GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
|
||||
GATE(PCLK_EFUSE256, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS),
|
||||
GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(11), 11, GFLAGS),
|
||||
|
||||
/* ddrctrl [DDR Controller PHY clock] gates */
|
||||
|
@ -709,7 +735,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = {
|
|||
GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS),
|
||||
GATE(SCLK_PVTM_CORE, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS),
|
||||
GATE(SCLK_PVTM_GPU, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS),
|
||||
GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
|
||||
GATE(SCLK_MIPIDSI_24M, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS),
|
||||
|
||||
/* sclk_gpu gates */
|
||||
GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS),
|
||||
|
@ -783,10 +809,10 @@ static const char *const rk3288_critical_clocks[] __initconst = {
|
|||
"pclk_pd_pmu",
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PM_SLEEP
|
||||
static void __iomem *rk3288_cru_base;
|
||||
|
||||
/* Some CRU registers will be reset in maskrom when the system
|
||||
/*
|
||||
* Some CRU registers will be reset in maskrom when the system
|
||||
* wakes up from fastboot.
|
||||
* So save them before suspend, restore them after resume.
|
||||
*/
|
||||
|
@ -840,33 +866,27 @@ static void rk3288_clk_resume(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void rk3288_clk_shutdown(void)
|
||||
{
|
||||
writel_relaxed(0xf3030000, rk3288_cru_base + RK3288_MODE_CON);
|
||||
}
|
||||
|
||||
static struct syscore_ops rk3288_clk_syscore_ops = {
|
||||
.suspend = rk3288_clk_suspend,
|
||||
.resume = rk3288_clk_resume,
|
||||
};
|
||||
|
||||
static void rk3288_clk_sleep_init(void __iomem *reg_base)
|
||||
{
|
||||
rk3288_cru_base = reg_base;
|
||||
register_syscore_ops(&rk3288_clk_syscore_ops);
|
||||
}
|
||||
|
||||
#else /* CONFIG_PM_SLEEP */
|
||||
static void rk3288_clk_sleep_init(void __iomem *reg_base) {}
|
||||
#endif
|
||||
|
||||
static void __init rk3288_clk_init(struct device_node *np)
|
||||
{
|
||||
void __iomem *reg_base;
|
||||
struct clk *clk;
|
||||
|
||||
reg_base = of_iomap(np, 0);
|
||||
if (!reg_base) {
|
||||
rk3288_cru_base = of_iomap(np, 0);
|
||||
if (!rk3288_cru_base) {
|
||||
pr_err("%s: could not map cru region\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rockchip_clk_init(np, reg_base, CLK_NR_CLKS);
|
||||
rockchip_clk_init(np, rk3288_cru_base, CLK_NR_CLKS);
|
||||
|
||||
/* xin12m is created by an cru-internal divider */
|
||||
clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2);
|
||||
|
@ -907,10 +927,12 @@ static void __init rk3288_clk_init(struct device_node *np)
|
|||
&rk3288_cpuclk_data, rk3288_cpuclk_rates,
|
||||
ARRAY_SIZE(rk3288_cpuclk_rates));
|
||||
|
||||
rockchip_register_softrst(np, 12, reg_base + RK3288_SOFTRST_CON(0),
|
||||
rockchip_register_softrst(np, 12,
|
||||
rk3288_cru_base + RK3288_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(RK3288_GLB_SRST_FST);
|
||||
rk3288_clk_sleep_init(reg_base);
|
||||
rockchip_register_restart_notifier(RK3288_GLB_SRST_FST,
|
||||
rk3288_clk_shutdown);
|
||||
register_syscore_ops(&rk3288_clk_syscore_ops);
|
||||
}
|
||||
CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init);
|
||||
|
|
|
@ -184,13 +184,13 @@ static const struct rockchip_cpuclk_reg_data rk3368_cpuclkl_data = {
|
|||
|
||||
#define RK3368_CLKSEL0(_offs, _aclkm) \
|
||||
{ \
|
||||
.reg = RK3288_CLKSEL_CON(0 + _offs), \
|
||||
.reg = RK3368_CLKSEL_CON(0 + _offs), \
|
||||
.val = HIWORD_UPDATE(_aclkm, RK3368_DIV_ACLKM_MASK, \
|
||||
RK3368_DIV_ACLKM_SHIFT), \
|
||||
}
|
||||
#define RK3368_CLKSEL1(_offs, _atclk, _pdbg) \
|
||||
{ \
|
||||
.reg = RK3288_CLKSEL_CON(1 + _offs), \
|
||||
.reg = RK3368_CLKSEL_CON(1 + _offs), \
|
||||
.val = HIWORD_UPDATE(_atclk, RK3368_DIV_ATCLK_MASK, \
|
||||
RK3368_DIV_ATCLK_SHIFT) | \
|
||||
HIWORD_UPDATE(_pdbg, RK3368_DIV_PCLK_DBG_MASK, \
|
||||
|
@ -819,6 +819,13 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
|
|||
};
|
||||
|
||||
static const char *const rk3368_critical_clocks[] __initconst = {
|
||||
"aclk_bus",
|
||||
"aclk_peri",
|
||||
/*
|
||||
* pwm1 supplies vdd_logic on a lot of boards, is currently unhandled
|
||||
* but needs to stay enabled there (including its parents) at all times.
|
||||
*/
|
||||
"pclk_pwm1",
|
||||
"pclk_pd_pmu",
|
||||
};
|
||||
|
||||
|
@ -882,6 +889,6 @@ static void __init rk3368_clk_init(struct device_node *np)
|
|||
rockchip_register_softrst(np, 15, reg_base + RK3368_SOFTRST_CON(0),
|
||||
ROCKCHIP_SOFTRST_HIWORD_MASK);
|
||||
|
||||
rockchip_register_restart_notifier(RK3368_GLB_SRST_FST);
|
||||
rockchip_register_restart_notifier(RK3368_GLB_SRST_FST, NULL);
|
||||
}
|
||||
CLK_OF_DECLARE(rk3368_cru, "rockchip,rk3368-cru", rk3368_clk_init);
|
||||
|
|
|
@ -102,22 +102,82 @@ static struct clk *rockchip_clk_register_branch(const char *name,
|
|||
return clk;
|
||||
}
|
||||
|
||||
struct rockchip_clk_frac {
|
||||
struct notifier_block clk_nb;
|
||||
struct clk_fractional_divider div;
|
||||
struct clk_gate gate;
|
||||
|
||||
struct clk_mux mux;
|
||||
const struct clk_ops *mux_ops;
|
||||
int mux_frac_idx;
|
||||
|
||||
bool rate_change_remuxed;
|
||||
int rate_change_idx;
|
||||
};
|
||||
|
||||
#define to_rockchip_clk_frac_nb(nb) \
|
||||
container_of(nb, struct rockchip_clk_frac, clk_nb)
|
||||
|
||||
static int rockchip_clk_frac_notifier_cb(struct notifier_block *nb,
|
||||
unsigned long event, void *data)
|
||||
{
|
||||
struct clk_notifier_data *ndata = data;
|
||||
struct rockchip_clk_frac *frac = to_rockchip_clk_frac_nb(nb);
|
||||
struct clk_mux *frac_mux = &frac->mux;
|
||||
int ret = 0;
|
||||
|
||||
pr_debug("%s: event %lu, old_rate %lu, new_rate: %lu\n",
|
||||
__func__, event, ndata->old_rate, ndata->new_rate);
|
||||
if (event == PRE_RATE_CHANGE) {
|
||||
frac->rate_change_idx = frac->mux_ops->get_parent(&frac_mux->hw);
|
||||
if (frac->rate_change_idx != frac->mux_frac_idx) {
|
||||
frac->mux_ops->set_parent(&frac_mux->hw, frac->mux_frac_idx);
|
||||
frac->rate_change_remuxed = 1;
|
||||
}
|
||||
} else if (event == POST_RATE_CHANGE) {
|
||||
/*
|
||||
* The POST_RATE_CHANGE notifier runs directly after the
|
||||
* divider clock is set in clk_change_rate, so we'll have
|
||||
* remuxed back to the original parent before clk_change_rate
|
||||
* reaches the mux itself.
|
||||
*/
|
||||
if (frac->rate_change_remuxed) {
|
||||
frac->mux_ops->set_parent(&frac_mux->hw, frac->rate_change_idx);
|
||||
frac->rate_change_remuxed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return notifier_from_errno(ret);
|
||||
}
|
||||
|
||||
static struct clk *rockchip_clk_register_frac_branch(const char *name,
|
||||
const char *const *parent_names, u8 num_parents,
|
||||
void __iomem *base, int muxdiv_offset, u8 div_flags,
|
||||
int gate_offset, u8 gate_shift, u8 gate_flags,
|
||||
unsigned long flags, spinlock_t *lock)
|
||||
unsigned long flags, struct rockchip_clk_branch *child,
|
||||
spinlock_t *lock)
|
||||
{
|
||||
struct rockchip_clk_frac *frac;
|
||||
struct clk *clk;
|
||||
struct clk_gate *gate = NULL;
|
||||
struct clk_fractional_divider *div = NULL;
|
||||
const struct clk_ops *div_ops = NULL, *gate_ops = NULL;
|
||||
|
||||
if (gate_offset >= 0) {
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
if (muxdiv_offset < 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (child && child->branch_type != branch_mux) {
|
||||
pr_err("%s: fractional child clock for %s can only be a mux\n",
|
||||
__func__, name);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
frac = kzalloc(sizeof(*frac), GFP_KERNEL);
|
||||
if (!frac)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
if (gate_offset >= 0) {
|
||||
gate = &frac->gate;
|
||||
gate->flags = gate_flags;
|
||||
gate->reg = base + gate_offset;
|
||||
gate->bit_idx = gate_shift;
|
||||
|
@ -125,13 +185,7 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
|
|||
gate_ops = &clk_gate_ops;
|
||||
}
|
||||
|
||||
if (muxdiv_offset < 0)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
div = &frac->div;
|
||||
div->flags = div_flags;
|
||||
div->reg = base + muxdiv_offset;
|
||||
div->mshift = 16;
|
||||
|
@ -147,7 +201,61 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
|
|||
NULL, NULL,
|
||||
&div->hw, div_ops,
|
||||
gate ? &gate->hw : NULL, gate_ops,
|
||||
flags);
|
||||
flags | CLK_SET_RATE_UNGATE);
|
||||
if (IS_ERR(clk)) {
|
||||
kfree(frac);
|
||||
return clk;
|
||||
}
|
||||
|
||||
if (child) {
|
||||
struct clk_mux *frac_mux = &frac->mux;
|
||||
struct clk_init_data init;
|
||||
struct clk *mux_clk;
|
||||
int i, ret;
|
||||
|
||||
frac->mux_frac_idx = -1;
|
||||
for (i = 0; i < child->num_parents; i++) {
|
||||
if (!strcmp(name, child->parent_names[i])) {
|
||||
pr_debug("%s: found fractional parent in mux at pos %d\n",
|
||||
__func__, i);
|
||||
frac->mux_frac_idx = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
frac->mux_ops = &clk_mux_ops;
|
||||
frac->clk_nb.notifier_call = rockchip_clk_frac_notifier_cb;
|
||||
|
||||
frac_mux->reg = base + child->muxdiv_offset;
|
||||
frac_mux->shift = child->mux_shift;
|
||||
frac_mux->mask = BIT(child->mux_width) - 1;
|
||||
frac_mux->flags = child->mux_flags;
|
||||
frac_mux->lock = lock;
|
||||
frac_mux->hw.init = &init;
|
||||
|
||||
init.name = child->name;
|
||||
init.flags = child->flags | CLK_SET_RATE_PARENT;
|
||||
init.ops = frac->mux_ops;
|
||||
init.parent_names = child->parent_names;
|
||||
init.num_parents = child->num_parents;
|
||||
|
||||
mux_clk = clk_register(NULL, &frac_mux->hw);
|
||||
if (IS_ERR(mux_clk))
|
||||
return clk;
|
||||
|
||||
rockchip_clk_add_lookup(mux_clk, child->id);
|
||||
|
||||
/* notifier on the fraction divider to catch rate changes */
|
||||
if (frac->mux_frac_idx >= 0) {
|
||||
ret = clk_notifier_register(clk, &frac->clk_nb);
|
||||
if (ret)
|
||||
pr_err("%s: failed to register clock notifier for %s\n",
|
||||
__func__, name);
|
||||
} else {
|
||||
pr_warn("%s: could not find %s as parent of %s, rate changes may not work\n",
|
||||
__func__, name, child->name);
|
||||
}
|
||||
}
|
||||
|
||||
return clk;
|
||||
}
|
||||
|
@ -251,7 +359,8 @@ void __init rockchip_clk_register_branches(
|
|||
list->parent_names, list->num_parents,
|
||||
reg_base, list->muxdiv_offset, list->div_flags,
|
||||
list->gate_offset, list->gate_shift,
|
||||
list->gate_flags, flags, &clk_lock);
|
||||
list->gate_flags, flags, list->child,
|
||||
&clk_lock);
|
||||
break;
|
||||
case branch_gate:
|
||||
flags |= CLK_SET_RATE_PARENT;
|
||||
|
@ -341,9 +450,13 @@ void __init rockchip_clk_protect_critical(const char *const clocks[],
|
|||
}
|
||||
|
||||
static unsigned int reg_restart;
|
||||
static void (*cb_restart)(void);
|
||||
static int rockchip_restart_notify(struct notifier_block *this,
|
||||
unsigned long mode, void *cmd)
|
||||
{
|
||||
if (cb_restart)
|
||||
cb_restart();
|
||||
|
||||
writel(0xfdb9, reg_base + reg_restart);
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -353,11 +466,12 @@ static struct notifier_block rockchip_restart_handler = {
|
|||
.priority = 128,
|
||||
};
|
||||
|
||||
void __init rockchip_register_restart_notifier(unsigned int reg)
|
||||
void __init rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void))
|
||||
{
|
||||
int ret;
|
||||
|
||||
reg_restart = reg;
|
||||
cb_restart = cb;
|
||||
ret = register_restart_handler(&rockchip_restart_handler);
|
||||
if (ret)
|
||||
pr_err("%s: cannot register restart handler, %d\n",
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
* Copyright (c) 2014 MundoReader S.L.
|
||||
* Author: Heiko Stuebner <heiko@sntech.de>
|
||||
*
|
||||
* Copyright (c) 2015 Rockchip Electronics Co. Ltd.
|
||||
* Author: Xing Zheng <zhengxing@rock-chips.com>
|
||||
*
|
||||
* based on
|
||||
*
|
||||
* samsung/clk.h
|
||||
|
@ -30,7 +33,7 @@ struct clk;
|
|||
#define HIWORD_UPDATE(val, mask, shift) \
|
||||
((val) << (shift) | (mask) << ((shift) + 16))
|
||||
|
||||
/* register positions shared by RK2928, RK3066 and RK3188 */
|
||||
/* register positions shared by RK2928, RK3036, RK3066, RK3188 and RK3228 */
|
||||
#define RK2928_PLL_CON(x) ((x) * 0x4)
|
||||
#define RK2928_MODE_CON 0x40
|
||||
#define RK2928_CLKSEL_CON(x) ((x) * 0x4 + 0x44)
|
||||
|
@ -40,6 +43,22 @@ struct clk;
|
|||
#define RK2928_SOFTRST_CON(x) ((x) * 0x4 + 0x110)
|
||||
#define RK2928_MISC_CON 0x134
|
||||
|
||||
#define RK3036_SDMMC_CON0 0x144
|
||||
#define RK3036_SDMMC_CON1 0x148
|
||||
#define RK3036_SDIO_CON0 0x14c
|
||||
#define RK3036_SDIO_CON1 0x150
|
||||
#define RK3036_EMMC_CON0 0x154
|
||||
#define RK3036_EMMC_CON1 0x158
|
||||
|
||||
#define RK3228_GLB_SRST_FST 0x1f0
|
||||
#define RK3228_GLB_SRST_SND 0x1f4
|
||||
#define RK3228_SDMMC_CON0 0x1c0
|
||||
#define RK3228_SDMMC_CON1 0x1c4
|
||||
#define RK3228_SDIO_CON0 0x1c8
|
||||
#define RK3228_SDIO_CON1 0x1cc
|
||||
#define RK3228_EMMC_CON0 0x1d8
|
||||
#define RK3228_EMMC_CON1 0x1dc
|
||||
|
||||
#define RK3288_PLL_CON(x) RK2928_PLL_CON(x)
|
||||
#define RK3288_MODE_CON 0x50
|
||||
#define RK3288_CLKSEL_CON(x) ((x) * 0x4 + 0x60)
|
||||
|
@ -74,9 +93,22 @@ struct clk;
|
|||
#define RK3368_EMMC_CON1 0x41c
|
||||
|
||||
enum rockchip_pll_type {
|
||||
pll_rk3036,
|
||||
pll_rk3066,
|
||||
};
|
||||
|
||||
#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
|
||||
_postdiv2, _dsmpd, _frac) \
|
||||
{ \
|
||||
.rate = _rate##U, \
|
||||
.fbdiv = _fbdiv, \
|
||||
.postdiv1 = _postdiv1, \
|
||||
.refdiv = _refdiv, \
|
||||
.postdiv2 = _postdiv2, \
|
||||
.dsmpd = _dsmpd, \
|
||||
.frac = _frac, \
|
||||
}
|
||||
|
||||
#define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \
|
||||
{ \
|
||||
.rate = _rate##U, \
|
||||
|
@ -101,6 +133,13 @@ struct rockchip_pll_rate_table {
|
|||
unsigned int nf;
|
||||
unsigned int no;
|
||||
unsigned int nb;
|
||||
/* for RK3036 */
|
||||
unsigned int fbdiv;
|
||||
unsigned int postdiv1;
|
||||
unsigned int refdiv;
|
||||
unsigned int postdiv2;
|
||||
unsigned int dsmpd;
|
||||
unsigned int frac;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -235,6 +274,7 @@ struct rockchip_clk_branch {
|
|||
int gate_offset;
|
||||
u8 gate_shift;
|
||||
u8 gate_flags;
|
||||
struct rockchip_clk_branch *child;
|
||||
};
|
||||
|
||||
#define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\
|
||||
|
@ -369,6 +409,24 @@ struct rockchip_clk_branch {
|
|||
.gate_flags = gf, \
|
||||
}
|
||||
|
||||
#define COMPOSITE_FRACMUX(_id, cname, pname, f, mo, df, go, gs, gf, ch) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
.branch_type = branch_fraction_divider, \
|
||||
.name = cname, \
|
||||
.parent_names = (const char *[]){ pname }, \
|
||||
.num_parents = 1, \
|
||||
.flags = f, \
|
||||
.muxdiv_offset = mo, \
|
||||
.div_shift = 16, \
|
||||
.div_width = 16, \
|
||||
.div_flags = df, \
|
||||
.gate_offset = go, \
|
||||
.gate_shift = gs, \
|
||||
.gate_flags = gf, \
|
||||
.child = ch, \
|
||||
}
|
||||
|
||||
#define MUX(_id, cname, pnames, f, o, s, w, mf) \
|
||||
{ \
|
||||
.id = _id, \
|
||||
|
@ -464,7 +522,7 @@ void rockchip_clk_register_armclk(unsigned int lookup_id, const char *name,
|
|||
const struct rockchip_cpuclk_rate_table *rates,
|
||||
int nrates);
|
||||
void rockchip_clk_protect_critical(const char *const clocks[], int nclocks);
|
||||
void rockchip_register_restart_notifier(unsigned int reg);
|
||||
void rockchip_register_restart_notifier(unsigned int reg, void (*cb)(void));
|
||||
|
||||
#define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0)
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
|
|||
unsigned long alt_prate = clk_get_rate(cpuclk->alt_parent);
|
||||
unsigned long alt_div = 0, alt_div_mask = DIV_MASK;
|
||||
unsigned long div0, div1 = 0, mux_reg;
|
||||
unsigned long flags;
|
||||
|
||||
/* find out the divider values to use for clock data */
|
||||
while ((cfg_data->prate * 1000) != ndata->new_rate) {
|
||||
|
@ -156,7 +157,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
|
|||
cfg_data++;
|
||||
}
|
||||
|
||||
spin_lock(cpuclk->lock);
|
||||
spin_lock_irqsave(cpuclk->lock, flags);
|
||||
|
||||
/*
|
||||
* For the selected PLL clock frequency, get the pre-defined divider
|
||||
|
@ -212,7 +213,7 @@ static int exynos_cpuclk_pre_rate_change(struct clk_notifier_data *ndata,
|
|||
DIV_MASK_ALL);
|
||||
}
|
||||
|
||||
spin_unlock(cpuclk->lock);
|
||||
spin_unlock_irqrestore(cpuclk->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -223,6 +224,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
|
|||
const struct exynos_cpuclk_cfg_data *cfg_data = cpuclk->cfg;
|
||||
unsigned long div = 0, div_mask = DIV_MASK;
|
||||
unsigned long mux_reg;
|
||||
unsigned long flags;
|
||||
|
||||
/* find out the divider values to use for clock data */
|
||||
if (cpuclk->flags & CLK_CPU_NEEDS_DEBUG_ALT_DIV) {
|
||||
|
@ -233,7 +235,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
|
|||
}
|
||||
}
|
||||
|
||||
spin_lock(cpuclk->lock);
|
||||
spin_lock_irqsave(cpuclk->lock, flags);
|
||||
|
||||
/* select mout_apll as the alternate parent */
|
||||
mux_reg = readl(base + E4210_SRC_CPU);
|
||||
|
@ -246,7 +248,7 @@ static int exynos_cpuclk_post_rate_change(struct clk_notifier_data *ndata,
|
|||
}
|
||||
|
||||
exynos_set_safe_div(base, div, div_mask);
|
||||
spin_unlock(cpuclk->lock);
|
||||
spin_unlock_irqrestore(cpuclk->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/syscore_ops.h>
|
||||
|
||||
#include "clk.h"
|
||||
#include "clk-cpu.h"
|
||||
|
||||
#define APLL_LOCK 0x0
|
||||
#define APLL_CON0 0x100
|
||||
|
@ -616,9 +617,11 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
|
|||
MUX(0, "mout_mspll_kfc", mout_mspll_cpu_p, SRC_TOP7, 8, 2),
|
||||
MUX(0, "mout_mspll_cpu", mout_mspll_cpu_p, SRC_TOP7, 12, 2),
|
||||
|
||||
MUX(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
|
||||
MUX_F(0, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
|
||||
CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
|
||||
MUX(0, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
|
||||
MUX(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1),
|
||||
MUX_F(0, "mout_kpll", mout_kpll_p, SRC_KFC, 0, 1,
|
||||
CLK_SET_RATE_PARENT | CLK_RECALC_NEW_RATES, 0),
|
||||
MUX(0, "mout_kfc", mout_kfc_p, SRC_KFC, 16, 1),
|
||||
|
||||
MUX(0, "mout_aclk200", mout_group1_p, SRC_TOP0, 8, 2),
|
||||
|
@ -677,8 +680,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
|
|||
SRC_TOP5, 20, 1),
|
||||
MUX(CLK_MOUT_USER_ACLK300_DISP1, "mout_user_aclk300_disp1",
|
||||
mout_user_aclk300_disp1_p, SRC_TOP5, 24, 1),
|
||||
MUX(0, "mout_user_aclk300_gscl", mout_user_aclk300_gscl_p,
|
||||
SRC_TOP5, 28, 1),
|
||||
MUX(CLK_MOUT_USER_ACLK300_GSCL, "mout_user_aclk300_gscl",
|
||||
mout_user_aclk300_gscl_p, SRC_TOP5, 28, 1),
|
||||
|
||||
MUX(0, "mout_sclk_mpll", mout_mpll_p, SRC_TOP6, 0, 1),
|
||||
MUX(CLK_MOUT_VPLL, "mout_sclk_vpll", mout_vpll_p, SRC_TOP6, 4, 1),
|
||||
|
@ -729,8 +732,8 @@ static struct samsung_mux_clock exynos5x_mux_clks[] __initdata = {
|
|||
SRC_TOP12, 20, 1),
|
||||
MUX(CLK_MOUT_SW_ACLK300, "mout_sw_aclk300_disp1",
|
||||
mout_sw_aclk300_disp1_p, SRC_TOP12, 24, 1),
|
||||
MUX(0, "mout_sw_aclk300_gscl", mout_sw_aclk300_gscl_p,
|
||||
SRC_TOP12, 28, 1),
|
||||
MUX(CLK_MOUT_SW_ACLK300_GSCL, "mout_sw_aclk300_gscl",
|
||||
mout_sw_aclk300_gscl_p, SRC_TOP12, 28, 1),
|
||||
|
||||
/* DISP1 Block */
|
||||
MUX(0, "mout_mipi1", mout_group2_p, SRC_DISP10, 16, 3),
|
||||
|
@ -926,7 +929,7 @@ static struct samsung_gate_clock exynos5x_gate_clks[] __initdata = {
|
|||
GATE_BUS_TOP, 13, 0, 0),
|
||||
GATE(0, "aclk166", "mout_user_aclk166",
|
||||
GATE_BUS_TOP, 14, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(0, "aclk333", "mout_aclk333",
|
||||
GATE(0, "aclk333", "mout_user_aclk333",
|
||||
GATE_BUS_TOP, 15, CLK_IGNORE_UNUSED, 0),
|
||||
GATE(0, "aclk400_isp", "mout_user_aclk400_isp",
|
||||
GATE_BUS_TOP, 16, 0, 0),
|
||||
|
@ -1246,6 +1249,74 @@ static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = {
|
|||
KPLL_CON0, NULL),
|
||||
};
|
||||
|
||||
#define E5420_EGL_DIV0(apll, pclk_dbg, atb, cpud) \
|
||||
((((apll) << 24) | ((pclk_dbg) << 20) | ((atb) << 16) | \
|
||||
((cpud) << 4)))
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data exynos5420_eglclk_d[] __initconst = {
|
||||
{ 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
|
||||
{ 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1000000, E5420_EGL_DIV0(3, 6, 6, 2), },
|
||||
{ 900000, E5420_EGL_DIV0(3, 6, 6, 2), },
|
||||
{ 800000, E5420_EGL_DIV0(3, 5, 5, 2), },
|
||||
{ 700000, E5420_EGL_DIV0(3, 5, 5, 2), },
|
||||
{ 600000, E5420_EGL_DIV0(3, 4, 4, 2), },
|
||||
{ 500000, E5420_EGL_DIV0(3, 3, 3, 2), },
|
||||
{ 400000, E5420_EGL_DIV0(3, 3, 3, 2), },
|
||||
{ 300000, E5420_EGL_DIV0(3, 3, 3, 2), },
|
||||
{ 200000, E5420_EGL_DIV0(3, 3, 3, 2), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data exynos5800_eglclk_d[] __initconst = {
|
||||
{ 2000000, E5420_EGL_DIV0(3, 7, 7, 4), },
|
||||
{ 1900000, E5420_EGL_DIV0(3, 7, 7, 4), },
|
||||
{ 1800000, E5420_EGL_DIV0(3, 7, 7, 4), },
|
||||
{ 1700000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1600000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1500000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1400000, E5420_EGL_DIV0(3, 7, 7, 3), },
|
||||
{ 1300000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1200000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1100000, E5420_EGL_DIV0(3, 7, 7, 2), },
|
||||
{ 1000000, E5420_EGL_DIV0(3, 7, 6, 2), },
|
||||
{ 900000, E5420_EGL_DIV0(3, 7, 6, 2), },
|
||||
{ 800000, E5420_EGL_DIV0(3, 7, 5, 2), },
|
||||
{ 700000, E5420_EGL_DIV0(3, 7, 5, 2), },
|
||||
{ 600000, E5420_EGL_DIV0(3, 7, 4, 2), },
|
||||
{ 500000, E5420_EGL_DIV0(3, 7, 3, 2), },
|
||||
{ 400000, E5420_EGL_DIV0(3, 7, 3, 2), },
|
||||
{ 300000, E5420_EGL_DIV0(3, 7, 3, 2), },
|
||||
{ 200000, E5420_EGL_DIV0(3, 7, 3, 2), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
#define E5420_KFC_DIV(kpll, pclk, aclk) \
|
||||
((((kpll) << 24) | ((pclk) << 20) | ((aclk) << 4)))
|
||||
|
||||
static const struct exynos_cpuclk_cfg_data exynos5420_kfcclk_d[] __initconst = {
|
||||
{ 1400000, E5420_KFC_DIV(3, 5, 3), }, /* for Exynos5800 */
|
||||
{ 1300000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 1200000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 1100000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 1000000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 900000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 800000, E5420_KFC_DIV(3, 5, 2), },
|
||||
{ 700000, E5420_KFC_DIV(3, 4, 2), },
|
||||
{ 600000, E5420_KFC_DIV(3, 4, 2), },
|
||||
{ 500000, E5420_KFC_DIV(3, 4, 2), },
|
||||
{ 400000, E5420_KFC_DIV(3, 3, 2), },
|
||||
{ 300000, E5420_KFC_DIV(3, 3, 2), },
|
||||
{ 200000, E5420_KFC_DIV(3, 3, 2), },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static const struct of_device_id ext_clk_match[] __initconst = {
|
||||
{ .compatible = "samsung,exynos5420-oscclk", .data = (void *)0, },
|
||||
{ },
|
||||
|
@ -1310,6 +1381,19 @@ static void __init exynos5x_clk_init(struct device_node *np,
|
|||
ARRAY_SIZE(exynos5800_gate_clks));
|
||||
}
|
||||
|
||||
if (soc == EXYNOS5420) {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
mout_cpu_p[0], mout_cpu_p[1], 0x200,
|
||||
exynos5420_eglclk_d, ARRAY_SIZE(exynos5420_eglclk_d), 0);
|
||||
} else {
|
||||
exynos_register_cpu_clock(ctx, CLK_ARM_CLK, "armclk",
|
||||
mout_cpu_p[0], mout_cpu_p[1], 0x200,
|
||||
exynos5800_eglclk_d, ARRAY_SIZE(exynos5800_eglclk_d), 0);
|
||||
}
|
||||
exynos_register_cpu_clock(ctx, CLK_KFC_CLK, "kfcclk",
|
||||
mout_kfc_p[0], mout_kfc_p[1], 0x28200,
|
||||
exynos5420_kfcclk_d, ARRAY_SIZE(exynos5420_kfcclk_d), 0);
|
||||
|
||||
exynos5420_clk_sleep_init();
|
||||
|
||||
samsung_clk_of_add_provider(np, ctx);
|
||||
|
|
|
@ -77,12 +77,11 @@ static u8 s3c24xx_clkout_get_parent(struct clk_hw *hw)
|
|||
static int s3c24xx_clkout_set_parent(struct clk_hw *hw, u8 index)
|
||||
{
|
||||
struct s3c24xx_clkout *clkout = to_s3c24xx_clkout(hw);
|
||||
int ret = 0;
|
||||
|
||||
s3c2410_modify_misccr((clkout->mask << clkout->shift),
|
||||
(index << clkout->shift));
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops s3c24xx_clkout_ops = {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
obj-$(CONFIG_ARCH_EMEV2) += clk-emev2.o
|
||||
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o
|
||||
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o
|
||||
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o
|
||||
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o
|
||||
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o
|
||||
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
|
||||
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R7S72100) += clk-rz.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A73A4) += clk-r8a73a4.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7740) += clk-r8a7740.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7778) += clk-r8a7778.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o clk-mstp.o
|
||||
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7793) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o clk-mstp.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_R8A7795) += renesas-cpg-mssr.o \
|
||||
r8a7795-cpg-mssr.o clk-div6.o
|
||||
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o clk-mstp.o clk-div6.o
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "clk-div6.h"
|
||||
|
||||
#define CPG_DIV6_CKSTP BIT(8)
|
||||
#define CPG_DIV6_DIV(d) ((d) & 0x3f)
|
||||
#define CPG_DIV6_DIV_MASK 0x3f
|
||||
|
@ -172,67 +174,44 @@ static const struct clk_ops cpg_div6_clock_ops = {
|
|||
.set_rate = cpg_div6_clock_set_rate,
|
||||
};
|
||||
|
||||
static void __init cpg_div6_clock_init(struct device_node *np)
|
||||
|
||||
/**
|
||||
* cpg_div6_register - Register a DIV6 clock
|
||||
* @name: Name of the DIV6 clock
|
||||
* @num_parents: Number of parent clocks of the DIV6 clock (1, 4, or 8)
|
||||
* @parent_names: Array containing the names of the parent clocks
|
||||
* @reg: Mapped register used to control the DIV6 clock
|
||||
*/
|
||||
struct clk * __init cpg_div6_register(const char *name,
|
||||
unsigned int num_parents,
|
||||
const char **parent_names,
|
||||
void __iomem *reg)
|
||||
{
|
||||
unsigned int num_parents, valid_parents;
|
||||
const char **parent_names;
|
||||
unsigned int valid_parents;
|
||||
struct clk_init_data init;
|
||||
struct div6_clock *clock;
|
||||
const char *name;
|
||||
struct clk *clk;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock)
|
||||
return;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents < 1) {
|
||||
pr_err("%s: no parent found for %s DIV6 clock\n",
|
||||
__func__, np->name);
|
||||
return;
|
||||
}
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
clock->parents = kmalloc_array(num_parents, sizeof(*clock->parents),
|
||||
GFP_KERNEL);
|
||||
parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
|
||||
GFP_KERNEL);
|
||||
if (!parent_names)
|
||||
return;
|
||||
if (!clock->parents) {
|
||||
clk = ERR_PTR(-ENOMEM);
|
||||
goto free_clock;
|
||||
}
|
||||
|
||||
/* Remap the clock register and read the divisor. Disabling the
|
||||
* clock overwrites the divisor, so we need to cache its value for the
|
||||
* enable operation.
|
||||
clock->reg = reg;
|
||||
|
||||
/*
|
||||
* Read the divisor. Disabling the clock overwrites the divisor, so we
|
||||
* need to cache its value for the enable operation.
|
||||
*/
|
||||
clock->reg = of_iomap(np, 0);
|
||||
if (clock->reg == NULL) {
|
||||
pr_err("%s: failed to map %s DIV6 clock register\n",
|
||||
__func__, np->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
clock->div = (clk_readl(clock->reg) & CPG_DIV6_DIV_MASK) + 1;
|
||||
|
||||
/* Parse the DT properties. */
|
||||
ret = of_property_read_string(np, "clock-output-names", &name);
|
||||
if (ret < 0) {
|
||||
pr_err("%s: failed to get %s DIV6 clock output name\n",
|
||||
__func__, np->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
for (i = 0, valid_parents = 0; i < num_parents; i++) {
|
||||
const char *name = of_clk_get_parent_name(np, i);
|
||||
|
||||
if (name) {
|
||||
parent_names[valid_parents] = name;
|
||||
clock->parents[valid_parents] = i;
|
||||
valid_parents++;
|
||||
}
|
||||
}
|
||||
|
||||
switch (num_parents) {
|
||||
case 1:
|
||||
/* fixed parent clock */
|
||||
|
@ -250,8 +229,18 @@ static void __init cpg_div6_clock_init(struct device_node *np)
|
|||
break;
|
||||
default:
|
||||
pr_err("%s: invalid number of parents for DIV6 clock %s\n",
|
||||
__func__, np->name);
|
||||
goto error;
|
||||
__func__, name);
|
||||
clk = ERR_PTR(-EINVAL);
|
||||
goto free_parents;
|
||||
}
|
||||
|
||||
/* Filter out invalid parents */
|
||||
for (i = 0, valid_parents = 0; i < num_parents; i++) {
|
||||
if (parent_names[i]) {
|
||||
parent_names[valid_parents] = parent_names[i];
|
||||
clock->parents[valid_parents] = i;
|
||||
valid_parents++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Register the clock. */
|
||||
|
@ -264,6 +253,53 @@ static void __init cpg_div6_clock_init(struct device_node *np)
|
|||
clock->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto free_parents;
|
||||
|
||||
return clk;
|
||||
|
||||
free_parents:
|
||||
kfree(clock->parents);
|
||||
free_clock:
|
||||
kfree(clock);
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void __init cpg_div6_clock_init(struct device_node *np)
|
||||
{
|
||||
unsigned int num_parents;
|
||||
const char **parent_names;
|
||||
const char *clk_name = np->name;
|
||||
void __iomem *reg;
|
||||
struct clk *clk;
|
||||
unsigned int i;
|
||||
|
||||
num_parents = of_clk_get_parent_count(np);
|
||||
if (num_parents < 1) {
|
||||
pr_err("%s: no parent found for %s DIV6 clock\n",
|
||||
__func__, np->name);
|
||||
return;
|
||||
}
|
||||
|
||||
parent_names = kmalloc_array(num_parents, sizeof(*parent_names),
|
||||
GFP_KERNEL);
|
||||
if (!parent_names)
|
||||
return;
|
||||
|
||||
reg = of_iomap(np, 0);
|
||||
if (reg == NULL) {
|
||||
pr_err("%s: failed to map %s DIV6 clock register\n",
|
||||
__func__, np->name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Parse the DT properties. */
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
|
||||
for (i = 0; i < num_parents; i++)
|
||||
parent_names[i] = of_clk_get_parent_name(np, i);
|
||||
|
||||
clk = cpg_div6_register(clk_name, num_parents, parent_names, reg);
|
||||
if (IS_ERR(clk)) {
|
||||
pr_err("%s: failed to register %s DIV6 clock (%ld)\n",
|
||||
__func__, np->name, PTR_ERR(clk));
|
||||
|
@ -276,9 +312,8 @@ static void __init cpg_div6_clock_init(struct device_node *np)
|
|||
return;
|
||||
|
||||
error:
|
||||
if (clock->reg)
|
||||
iounmap(clock->reg);
|
||||
if (reg)
|
||||
iounmap(reg);
|
||||
kfree(parent_names);
|
||||
kfree(clock);
|
||||
}
|
||||
CLK_OF_DECLARE(cpg_div6_clk, "renesas,cpg-div6-clock", cpg_div6_clock_init);
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef __SHMOBILE_CLK_DIV6_H__
|
||||
#define __SHMOBILE_CLK_DIV6_H__
|
||||
|
||||
struct clk *cpg_div6_register(const char *name, unsigned int num_parents,
|
||||
const char **parent_names, void __iomem *reg);
|
||||
|
||||
#endif
|
|
@ -115,7 +115,7 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
|||
*
|
||||
* Using experimental measurements, it seems that no more than
|
||||
* ~10 iterations are needed, independently of the CPU rate.
|
||||
* Since this value might be dependant of external xtal rate, pll1
|
||||
* Since this value might be dependent on external xtal rate, pll1
|
||||
* rate or even the other emulation clocks rate, use 1000 as a
|
||||
* "super" safe value.
|
||||
*/
|
||||
|
@ -262,7 +262,7 @@ static struct clk * __init cpg_adsp_clk_register(struct rcar_gen2_cpg *cpg)
|
|||
* 1 1 0 30 / 2 x172/2 x208/2 x106
|
||||
* 1 1 1 30 / 2 x172/2 x208/2 x88
|
||||
*
|
||||
* *1 : Table 7.6 indicates VCO ouput (PLLx = VCO/2)
|
||||
* *1 : Table 7.6 indicates VCO output (PLLx = VCO/2)
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 12) | \
|
||||
(((md) & BIT(13)) >> 12) | \
|
||||
|
|
|
@ -0,0 +1,383 @@
|
|||
/*
|
||||
* r8a7795 Clock Pulse Generator / Module Standby and Software Reset
|
||||
*
|
||||
* Copyright (C) 2015 Glider bvba
|
||||
*
|
||||
* Based on clk-rcar-gen3.c
|
||||
*
|
||||
* Copyright (C) 2015 Renesas Electronics Corp.
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/of.h>
|
||||
|
||||
#include <dt-bindings/clock/r8a7795-cpg-mssr.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
|
||||
|
||||
enum clk_ids {
|
||||
/* Core Clock Outputs exported to DT */
|
||||
LAST_DT_CORE_CLK = R8A7795_CLK_OSC,
|
||||
|
||||
/* External Input Clocks */
|
||||
CLK_EXTAL,
|
||||
CLK_EXTALR,
|
||||
|
||||
/* Internal Core Clocks */
|
||||
CLK_MAIN,
|
||||
CLK_PLL0,
|
||||
CLK_PLL1,
|
||||
CLK_PLL2,
|
||||
CLK_PLL3,
|
||||
CLK_PLL4,
|
||||
CLK_PLL1_DIV2,
|
||||
CLK_PLL1_DIV4,
|
||||
CLK_S0,
|
||||
CLK_S1,
|
||||
CLK_S2,
|
||||
CLK_S3,
|
||||
CLK_SDSRC,
|
||||
CLK_SSPSRC,
|
||||
|
||||
/* Module Clocks */
|
||||
MOD_CLK_BASE
|
||||
};
|
||||
|
||||
enum r8a7795_clk_types {
|
||||
CLK_TYPE_GEN3_MAIN = CLK_TYPE_CUSTOM,
|
||||
CLK_TYPE_GEN3_PLL0,
|
||||
CLK_TYPE_GEN3_PLL1,
|
||||
CLK_TYPE_GEN3_PLL2,
|
||||
CLK_TYPE_GEN3_PLL3,
|
||||
CLK_TYPE_GEN3_PLL4,
|
||||
};
|
||||
|
||||
static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
|
||||
/* External Clock Inputs */
|
||||
DEF_INPUT("extal", CLK_EXTAL),
|
||||
DEF_INPUT("extalr", CLK_EXTALR),
|
||||
|
||||
/* Internal Core Clocks */
|
||||
DEF_BASE(".main", CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
|
||||
DEF_BASE(".pll0", CLK_PLL0, CLK_TYPE_GEN3_PLL0, CLK_MAIN),
|
||||
DEF_BASE(".pll1", CLK_PLL1, CLK_TYPE_GEN3_PLL1, CLK_MAIN),
|
||||
DEF_BASE(".pll2", CLK_PLL2, CLK_TYPE_GEN3_PLL2, CLK_MAIN),
|
||||
DEF_BASE(".pll3", CLK_PLL3, CLK_TYPE_GEN3_PLL3, CLK_MAIN),
|
||||
DEF_BASE(".pll4", CLK_PLL4, CLK_TYPE_GEN3_PLL4, CLK_MAIN),
|
||||
|
||||
DEF_FIXED(".pll1_div2", CLK_PLL1_DIV2, CLK_PLL1, 2, 1),
|
||||
DEF_FIXED(".pll1_div4", CLK_PLL1_DIV4, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_FIXED(".s0", CLK_S0, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_FIXED(".s1", CLK_S1, CLK_PLL1_DIV2, 3, 1),
|
||||
DEF_FIXED(".s2", CLK_S2, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED(".s3", CLK_S3, CLK_PLL1_DIV2, 6, 1),
|
||||
|
||||
/* Core Clock Outputs */
|
||||
DEF_FIXED("ztr", R8A7795_CLK_ZTR, CLK_PLL1_DIV2, 6, 1),
|
||||
DEF_FIXED("ztrd2", R8A7795_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
|
||||
DEF_FIXED("zt", R8A7795_CLK_ZT, CLK_PLL1_DIV2, 4, 1),
|
||||
DEF_FIXED("zx", R8A7795_CLK_ZX, CLK_PLL1_DIV2, 2, 1),
|
||||
DEF_FIXED("s0d1", R8A7795_CLK_S0D1, CLK_S0, 1, 1),
|
||||
DEF_FIXED("s0d4", R8A7795_CLK_S0D4, CLK_S0, 4, 1),
|
||||
DEF_FIXED("s1d1", R8A7795_CLK_S1D1, CLK_S1, 1, 1),
|
||||
DEF_FIXED("s1d2", R8A7795_CLK_S1D2, CLK_S1, 2, 1),
|
||||
DEF_FIXED("s1d4", R8A7795_CLK_S1D4, CLK_S1, 4, 1),
|
||||
DEF_FIXED("s2d1", R8A7795_CLK_S2D1, CLK_S2, 1, 1),
|
||||
DEF_FIXED("s2d2", R8A7795_CLK_S2D2, CLK_S2, 2, 1),
|
||||
DEF_FIXED("s2d4", R8A7795_CLK_S2D4, CLK_S2, 4, 1),
|
||||
DEF_FIXED("s3d1", R8A7795_CLK_S3D1, CLK_S3, 1, 1),
|
||||
DEF_FIXED("s3d2", R8A7795_CLK_S3D2, CLK_S3, 2, 1),
|
||||
DEF_FIXED("s3d4", R8A7795_CLK_S3D4, CLK_S3, 4, 1),
|
||||
DEF_FIXED("cl", R8A7795_CLK_CL, CLK_PLL1_DIV2, 48, 1),
|
||||
DEF_FIXED("cp", R8A7795_CLK_CP, CLK_EXTAL, 2, 1),
|
||||
|
||||
DEF_DIV6P1("mso", R8A7795_CLK_MSO, CLK_PLL1_DIV4, 0x014),
|
||||
DEF_DIV6P1("hdmi", R8A7795_CLK_HDMI, CLK_PLL1_DIV2, 0x250),
|
||||
};
|
||||
|
||||
static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
|
||||
DEF_MOD("scif5", 202, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif4", 203, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif3", 204, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif1", 206, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scif0", 207, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("msiof3", 208, R8A7795_CLK_MSO),
|
||||
DEF_MOD("msiof2", 209, R8A7795_CLK_MSO),
|
||||
DEF_MOD("msiof1", 210, R8A7795_CLK_MSO),
|
||||
DEF_MOD("msiof0", 211, R8A7795_CLK_MSO),
|
||||
DEF_MOD("sys-dmac2", 217, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("sys-dmac1", 218, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("sys-dmac0", 219, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("scif2", 310, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("pcie1", 318, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("pcie0", 319, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("intc-ap", 408, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("audmac0", 502, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("audmac1", 501, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("hscif4", 516, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif3", 517, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif2", 518, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif1", 519, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("hscif0", 520, R8A7795_CLK_S3D1),
|
||||
DEF_MOD("vspd3", 620, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd2", 621, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd1", 622, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspd0", 623, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspbc", 624, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspbd", 626, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi2", 629, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi1", 630, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("vspi0", 631, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("ehci2", 701, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("ehci1", 702, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("ehci0", 703, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("hsusb", 704, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("du3", 721, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("du2", 722, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("du1", 723, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("du0", 724, R8A7795_CLK_S2D1),
|
||||
DEF_MOD("hdmi1", 728, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("hdmi0", 729, R8A7795_CLK_HDMI),
|
||||
DEF_MOD("etheravb", 812, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("sata0", 815, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("gpio7", 905, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio6", 906, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio5", 907, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio4", 908, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio3", 909, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio2", 910, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio1", 911, R8A7795_CLK_CP),
|
||||
DEF_MOD("gpio0", 912, R8A7795_CLK_CP),
|
||||
DEF_MOD("i2c6", 918, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c5", 919, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c4", 927, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c3", 928, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c2", 929, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c1", 930, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("i2c0", 931, R8A7795_CLK_S3D2),
|
||||
DEF_MOD("ssi-all", 1005, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("ssi9", 1006, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi8", 1007, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi7", 1008, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi6", 1009, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi5", 1010, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi4", 1011, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi3", 1012, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi2", 1013, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi1", 1014, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("ssi0", 1015, MOD_CLK_ID(1005)),
|
||||
DEF_MOD("scu-all", 1017, R8A7795_CLK_S3D4),
|
||||
DEF_MOD("scu-dvc1", 1018, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-dvc0", 1019, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-ctu1-mix1", 1020, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-ctu0-mix0", 1021, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src9", 1022, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src8", 1023, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src7", 1024, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src6", 1025, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src5", 1026, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src4", 1027, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src3", 1028, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src2", 1029, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src1", 1030, MOD_CLK_ID(1017)),
|
||||
DEF_MOD("scu-src0", 1031, MOD_CLK_ID(1017)),
|
||||
};
|
||||
|
||||
static const unsigned int r8a7795_crit_mod_clks[] __initconst = {
|
||||
MOD_CLK_ID(408), /* INTC-AP (GIC) */
|
||||
};
|
||||
|
||||
|
||||
#define CPG_PLL0CR 0x00d8
|
||||
#define CPG_PLL2CR 0x002c
|
||||
#define CPG_PLL4CR 0x01f4
|
||||
|
||||
/*
|
||||
* CPG Clock Data
|
||||
*/
|
||||
|
||||
/*
|
||||
* MD EXTAL PLL0 PLL1 PLL2 PLL3 PLL4
|
||||
* 14 13 19 17 (MHz)
|
||||
*-------------------------------------------------------------------
|
||||
* 0 0 0 0 16.66 x 1 x180 x192 x144 x192 x144
|
||||
* 0 0 0 1 16.66 x 1 x180 x192 x144 x128 x144
|
||||
* 0 0 1 0 Prohibited setting
|
||||
* 0 0 1 1 16.66 x 1 x180 x192 x144 x192 x144
|
||||
* 0 1 0 0 20 x 1 x150 x160 x120 x160 x120
|
||||
* 0 1 0 1 20 x 1 x150 x160 x120 x106 x120
|
||||
* 0 1 1 0 Prohibited setting
|
||||
* 0 1 1 1 20 x 1 x150 x160 x120 x160 x120
|
||||
* 1 0 0 0 25 x 1 x120 x128 x96 x128 x96
|
||||
* 1 0 0 1 25 x 1 x120 x128 x96 x84 x96
|
||||
* 1 0 1 0 Prohibited setting
|
||||
* 1 0 1 1 25 x 1 x120 x128 x96 x128 x96
|
||||
* 1 1 0 0 33.33 / 2 x180 x192 x144 x192 x144
|
||||
* 1 1 0 1 33.33 / 2 x180 x192 x144 x128 x144
|
||||
* 1 1 1 0 Prohibited setting
|
||||
* 1 1 1 1 33.33 / 2 x180 x192 x144 x192 x144
|
||||
*/
|
||||
#define CPG_PLL_CONFIG_INDEX(md) ((((md) & BIT(14)) >> 11) | \
|
||||
(((md) & BIT(13)) >> 11) | \
|
||||
(((md) & BIT(19)) >> 18) | \
|
||||
(((md) & BIT(17)) >> 17))
|
||||
|
||||
struct cpg_pll_config {
|
||||
unsigned int extal_div;
|
||||
unsigned int pll1_mult;
|
||||
unsigned int pll3_mult;
|
||||
};
|
||||
|
||||
static const struct cpg_pll_config cpg_pll_configs[16] __initconst = {
|
||||
/* EXTAL div PLL1 mult PLL3 mult */
|
||||
{ 1, 192, 192, },
|
||||
{ 1, 192, 128, },
|
||||
{ 0, /* Prohibited setting */ },
|
||||
{ 1, 192, 192, },
|
||||
{ 1, 160, 160, },
|
||||
{ 1, 160, 106, },
|
||||
{ 0, /* Prohibited setting */ },
|
||||
{ 1, 160, 160, },
|
||||
{ 1, 128, 128, },
|
||||
{ 1, 128, 84, },
|
||||
{ 0, /* Prohibited setting */ },
|
||||
{ 1, 128, 128, },
|
||||
{ 2, 192, 192, },
|
||||
{ 2, 192, 128, },
|
||||
{ 0, /* Prohibited setting */ },
|
||||
{ 2, 192, 192, },
|
||||
};
|
||||
|
||||
static const struct cpg_pll_config *cpg_pll_config __initdata;
|
||||
|
||||
static
|
||||
struct clk * __init r8a7795_cpg_clk_register(struct device *dev,
|
||||
const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct clk **clks,
|
||||
void __iomem *base)
|
||||
{
|
||||
const struct clk *parent;
|
||||
unsigned int mult = 1;
|
||||
unsigned int div = 1;
|
||||
u32 value;
|
||||
|
||||
parent = clks[core->parent];
|
||||
if (IS_ERR(parent))
|
||||
return ERR_CAST(parent);
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_GEN3_MAIN:
|
||||
div = cpg_pll_config->extal_div;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL0:
|
||||
/*
|
||||
* PLL0 is a configurable multiplier clock. Register it as a
|
||||
* fixed factor clock for now as there's no generic multiplier
|
||||
* clock implementation and we currently have no need to change
|
||||
* the multiplier value.
|
||||
*/
|
||||
value = readl(base + CPG_PLL0CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL1:
|
||||
mult = cpg_pll_config->pll1_mult;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL2:
|
||||
/*
|
||||
* PLL2 is a configurable multiplier clock. Register it as a
|
||||
* fixed factor clock for now as there's no generic multiplier
|
||||
* clock implementation and we currently have no need to change
|
||||
* the multiplier value.
|
||||
*/
|
||||
value = readl(base + CPG_PLL2CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL3:
|
||||
mult = cpg_pll_config->pll3_mult;
|
||||
break;
|
||||
|
||||
case CLK_TYPE_GEN3_PLL4:
|
||||
/*
|
||||
* PLL4 is a configurable multiplier clock. Register it as a
|
||||
* fixed factor clock for now as there's no generic multiplier
|
||||
* clock implementation and we currently have no need to change
|
||||
* the multiplier value.
|
||||
*/
|
||||
value = readl(base + CPG_PLL4CR);
|
||||
mult = (((value >> 24) & 0x7f) + 1) * 2;
|
||||
break;
|
||||
|
||||
default:
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
return clk_register_fixed_factor(NULL, core->name,
|
||||
__clk_get_name(parent), 0, mult, div);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset register definitions.
|
||||
*/
|
||||
#define MODEMR 0xe6160060
|
||||
|
||||
static u32 rcar_gen3_read_mode_pins(void)
|
||||
{
|
||||
void __iomem *modemr = ioremap_nocache(MODEMR, 4);
|
||||
u32 mode;
|
||||
|
||||
BUG_ON(!modemr);
|
||||
mode = ioread32(modemr);
|
||||
iounmap(modemr);
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
||||
static int __init r8a7795_cpg_mssr_init(struct device *dev)
|
||||
{
|
||||
u32 cpg_mode = rcar_gen3_read_mode_pins();
|
||||
|
||||
cpg_pll_config = &cpg_pll_configs[CPG_PLL_CONFIG_INDEX(cpg_mode)];
|
||||
if (!cpg_pll_config->extal_div) {
|
||||
dev_err(dev, "Prohibited setting (cpg_mode=0x%x)\n", cpg_mode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
|
||||
/* Core Clocks */
|
||||
.core_clks = r8a7795_core_clks,
|
||||
.num_core_clks = ARRAY_SIZE(r8a7795_core_clks),
|
||||
.last_dt_core_clk = LAST_DT_CORE_CLK,
|
||||
.num_total_core_clks = MOD_CLK_BASE,
|
||||
|
||||
/* Module Clocks */
|
||||
.mod_clks = r8a7795_mod_clks,
|
||||
.num_mod_clks = ARRAY_SIZE(r8a7795_mod_clks),
|
||||
.num_hw_mod_clks = 12 * 32,
|
||||
|
||||
/* Critical Module Clocks */
|
||||
.crit_mod_clks = r8a7795_crit_mod_clks,
|
||||
.num_crit_mod_clks = ARRAY_SIZE(r8a7795_crit_mod_clks),
|
||||
|
||||
/* Callbacks */
|
||||
.init = r8a7795_cpg_mssr_init,
|
||||
.cpg_clk_register = r8a7795_cpg_clk_register,
|
||||
};
|
|
@ -0,0 +1,596 @@
|
|||
/*
|
||||
* Renesas Clock Pulse Generator / Module Standby and Software Reset
|
||||
*
|
||||
* Copyright (C) 2015 Glider bvba
|
||||
*
|
||||
* Based on clk-mstp.c, clk-rcar-gen2.c, and clk-rcar-gen3.c
|
||||
*
|
||||
* Copyright (C) 2013 Ideas On Board SPRL
|
||||
* Copyright (C) 2015 Renesas Electronics Corp.
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_clock.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <dt-bindings/clock/renesas-cpg-mssr.h>
|
||||
|
||||
#include "renesas-cpg-mssr.h"
|
||||
#include "clk-div6.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
#define WARN_DEBUG(x) do { } while (0)
|
||||
#else
|
||||
#define WARN_DEBUG(x) WARN_ON(x)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Module Standby and Software Reset register offets.
|
||||
*
|
||||
* If the registers exist, these are valid for SH-Mobile, R-Mobile,
|
||||
* R-Car Gen 2, and R-Car Gen 3.
|
||||
* These are NOT valid for R-Car Gen1 and RZ/A1!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Module Stop Status Register offsets
|
||||
*/
|
||||
|
||||
static const u16 mstpsr[] = {
|
||||
0x030, 0x038, 0x040, 0x048, 0x04C, 0x03C, 0x1C0, 0x1C4,
|
||||
0x9A0, 0x9A4, 0x9A8, 0x9AC,
|
||||
};
|
||||
|
||||
#define MSTPSR(i) mstpsr[i]
|
||||
|
||||
|
||||
/*
|
||||
* System Module Stop Control Register offsets
|
||||
*/
|
||||
|
||||
static const u16 smstpcr[] = {
|
||||
0x130, 0x134, 0x138, 0x13C, 0x140, 0x144, 0x148, 0x14C,
|
||||
0x990, 0x994, 0x998, 0x99C,
|
||||
};
|
||||
|
||||
#define SMSTPCR(i) smstpcr[i]
|
||||
|
||||
|
||||
/*
|
||||
* Software Reset Register offsets
|
||||
*/
|
||||
|
||||
static const u16 srcr[] = {
|
||||
0x0A0, 0x0A8, 0x0B0, 0x0B8, 0x0BC, 0x0C4, 0x1C8, 0x1CC,
|
||||
0x920, 0x924, 0x928, 0x92C,
|
||||
};
|
||||
|
||||
#define SRCR(i) srcr[i]
|
||||
|
||||
|
||||
/* Realtime Module Stop Control Register offsets */
|
||||
#define RMSTPCR(i) (smstpcr[i] - 0x20)
|
||||
|
||||
/* Modem Module Stop Control Register offsets (r8a73a4) */
|
||||
#define MMSTPCR(i) (smstpcr[i] + 0x20)
|
||||
|
||||
/* Software Reset Clearing Register offsets */
|
||||
#define SRSTCLR(i) (0x940 + (i) * 4)
|
||||
|
||||
|
||||
/**
|
||||
* Clock Pulse Generator / Module Standby and Software Reset Private Data
|
||||
*
|
||||
* @dev: CPG/MSSR device
|
||||
* @base: CPG/MSSR register block base address
|
||||
* @mstp_lock: protects writes to SMSTPCR
|
||||
* @clks: Array containing all Core and Module Clocks
|
||||
* @num_core_clks: Number of Core Clocks in clks[]
|
||||
* @num_mod_clks: Number of Module Clocks in clks[]
|
||||
* @last_dt_core_clk: ID of the last Core Clock exported to DT
|
||||
*/
|
||||
struct cpg_mssr_priv {
|
||||
struct device *dev;
|
||||
void __iomem *base;
|
||||
spinlock_t mstp_lock;
|
||||
|
||||
struct clk **clks;
|
||||
unsigned int num_core_clks;
|
||||
unsigned int num_mod_clks;
|
||||
unsigned int last_dt_core_clk;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct mstp_clock - MSTP gating clock
|
||||
* @hw: handle between common and hardware-specific interfaces
|
||||
* @index: MSTP clock number
|
||||
* @priv: CPG/MSSR private data
|
||||
*/
|
||||
struct mstp_clock {
|
||||
struct clk_hw hw;
|
||||
u32 index;
|
||||
struct cpg_mssr_priv *priv;
|
||||
};
|
||||
|
||||
#define to_mstp_clock(_hw) container_of(_hw, struct mstp_clock, hw)
|
||||
|
||||
static int cpg_mstp_clock_endisable(struct clk_hw *hw, bool enable)
|
||||
{
|
||||
struct mstp_clock *clock = to_mstp_clock(hw);
|
||||
struct cpg_mssr_priv *priv = clock->priv;
|
||||
unsigned int reg = clock->index / 32;
|
||||
unsigned int bit = clock->index % 32;
|
||||
struct device *dev = priv->dev;
|
||||
u32 bitmask = BIT(bit);
|
||||
unsigned long flags;
|
||||
unsigned int i;
|
||||
u32 value;
|
||||
|
||||
dev_dbg(dev, "MSTP %u%02u/%pC %s\n", reg, bit, hw->clk,
|
||||
enable ? "ON" : "OFF");
|
||||
spin_lock_irqsave(&priv->mstp_lock, flags);
|
||||
|
||||
value = clk_readl(priv->base + SMSTPCR(reg));
|
||||
if (enable)
|
||||
value &= ~bitmask;
|
||||
else
|
||||
value |= bitmask;
|
||||
clk_writel(value, priv->base + SMSTPCR(reg));
|
||||
|
||||
spin_unlock_irqrestore(&priv->mstp_lock, flags);
|
||||
|
||||
if (!enable)
|
||||
return 0;
|
||||
|
||||
for (i = 1000; i > 0; --i) {
|
||||
if (!(clk_readl(priv->base + MSTPSR(reg)) &
|
||||
bitmask))
|
||||
break;
|
||||
cpu_relax();
|
||||
}
|
||||
|
||||
if (!i) {
|
||||
dev_err(dev, "Failed to enable SMSTP %p[%d]\n",
|
||||
priv->base + SMSTPCR(reg), bit);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cpg_mstp_clock_enable(struct clk_hw *hw)
|
||||
{
|
||||
return cpg_mstp_clock_endisable(hw, true);
|
||||
}
|
||||
|
||||
static void cpg_mstp_clock_disable(struct clk_hw *hw)
|
||||
{
|
||||
cpg_mstp_clock_endisable(hw, false);
|
||||
}
|
||||
|
||||
static int cpg_mstp_clock_is_enabled(struct clk_hw *hw)
|
||||
{
|
||||
struct mstp_clock *clock = to_mstp_clock(hw);
|
||||
struct cpg_mssr_priv *priv = clock->priv;
|
||||
u32 value;
|
||||
|
||||
value = clk_readl(priv->base + MSTPSR(clock->index / 32));
|
||||
|
||||
return !(value & BIT(clock->index % 32));
|
||||
}
|
||||
|
||||
static const struct clk_ops cpg_mstp_clock_ops = {
|
||||
.enable = cpg_mstp_clock_enable,
|
||||
.disable = cpg_mstp_clock_disable,
|
||||
.is_enabled = cpg_mstp_clock_is_enabled,
|
||||
};
|
||||
|
||||
static
|
||||
struct clk *cpg_mssr_clk_src_twocell_get(struct of_phandle_args *clkspec,
|
||||
void *data)
|
||||
{
|
||||
unsigned int clkidx = clkspec->args[1];
|
||||
struct cpg_mssr_priv *priv = data;
|
||||
struct device *dev = priv->dev;
|
||||
unsigned int idx;
|
||||
const char *type;
|
||||
struct clk *clk;
|
||||
|
||||
switch (clkspec->args[0]) {
|
||||
case CPG_CORE:
|
||||
type = "core";
|
||||
if (clkidx > priv->last_dt_core_clk) {
|
||||
dev_err(dev, "Invalid %s clock index %u\n", type,
|
||||
clkidx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
clk = priv->clks[clkidx];
|
||||
break;
|
||||
|
||||
case CPG_MOD:
|
||||
type = "module";
|
||||
idx = MOD_CLK_PACK(clkidx);
|
||||
if (clkidx % 100 > 31 || idx >= priv->num_mod_clks) {
|
||||
dev_err(dev, "Invalid %s clock index %u\n", type,
|
||||
clkidx);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
clk = priv->clks[priv->num_core_clks + idx];
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(dev, "Invalid CPG clock type %u\n", clkspec->args[0]);
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
|
||||
if (IS_ERR(clk))
|
||||
dev_err(dev, "Cannot get %s clock %u: %ld", type, clkidx,
|
||||
PTR_ERR(clk));
|
||||
else
|
||||
dev_dbg(dev, "clock (%u, %u) is %pC at %pCr Hz\n",
|
||||
clkspec->args[0], clkspec->args[1], clk, clk);
|
||||
return clk;
|
||||
}
|
||||
|
||||
static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct cpg_mssr_priv *priv)
|
||||
{
|
||||
struct clk *clk = NULL, *parent;
|
||||
struct device *dev = priv->dev;
|
||||
unsigned int id = core->id;
|
||||
const char *parent_name;
|
||||
|
||||
WARN_DEBUG(id >= priv->num_core_clks);
|
||||
WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
|
||||
|
||||
switch (core->type) {
|
||||
case CLK_TYPE_IN:
|
||||
clk = of_clk_get_by_name(priv->dev->of_node, core->name);
|
||||
break;
|
||||
|
||||
case CLK_TYPE_FF:
|
||||
case CLK_TYPE_DIV6P1:
|
||||
WARN_DEBUG(core->parent >= priv->num_core_clks);
|
||||
parent = priv->clks[core->parent];
|
||||
if (IS_ERR(parent)) {
|
||||
clk = parent;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
parent_name = __clk_get_name(parent);
|
||||
if (core->type == CLK_TYPE_FF) {
|
||||
clk = clk_register_fixed_factor(NULL, core->name,
|
||||
parent_name, 0,
|
||||
core->mult, core->div);
|
||||
} else {
|
||||
clk = cpg_div6_register(core->name, 1, &parent_name,
|
||||
priv->base + core->offset);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (info->cpg_clk_register)
|
||||
clk = info->cpg_clk_register(dev, core, info,
|
||||
priv->clks, priv->base);
|
||||
else
|
||||
dev_err(dev, "%s has unsupported core clock type %u\n",
|
||||
core->name, core->type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (IS_ERR_OR_NULL(clk))
|
||||
goto fail;
|
||||
|
||||
dev_dbg(dev, "Core clock %pC at %pCr Hz\n", clk, clk);
|
||||
priv->clks[id] = clk;
|
||||
return;
|
||||
|
||||
fail:
|
||||
dev_err(dev, "Failed to register %s clock %s: %ld\n", "core,",
|
||||
core->name, PTR_ERR(clk));
|
||||
}
|
||||
|
||||
static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct cpg_mssr_priv *priv)
|
||||
{
|
||||
struct mstp_clock *clock = NULL;
|
||||
struct device *dev = priv->dev;
|
||||
unsigned int id = mod->id;
|
||||
struct clk_init_data init;
|
||||
struct clk *parent, *clk;
|
||||
const char *parent_name;
|
||||
unsigned int i;
|
||||
|
||||
WARN_DEBUG(id < priv->num_core_clks);
|
||||
WARN_DEBUG(id >= priv->num_core_clks + priv->num_mod_clks);
|
||||
WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
|
||||
WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
|
||||
|
||||
parent = priv->clks[mod->parent];
|
||||
if (IS_ERR(parent)) {
|
||||
clk = parent;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
clock = kzalloc(sizeof(*clock), GFP_KERNEL);
|
||||
if (!clock) {
|
||||
clk = ERR_PTR(-ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
init.name = mod->name;
|
||||
init.ops = &cpg_mstp_clock_ops;
|
||||
init.flags = CLK_IS_BASIC | CLK_SET_RATE_PARENT;
|
||||
for (i = 0; i < info->num_crit_mod_clks; i++)
|
||||
if (id == info->crit_mod_clks[i]) {
|
||||
#ifdef CLK_ENABLE_HAND_OFF
|
||||
dev_dbg(dev, "MSTP %s setting CLK_ENABLE_HAND_OFF\n",
|
||||
mod->name);
|
||||
init.flags |= CLK_ENABLE_HAND_OFF;
|
||||
break;
|
||||
#else
|
||||
dev_dbg(dev, "Ignoring MSTP %s to prevent disabling\n",
|
||||
mod->name);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
parent_name = __clk_get_name(parent);
|
||||
init.parent_names = &parent_name;
|
||||
init.num_parents = 1;
|
||||
|
||||
clock->index = id - priv->num_core_clks;
|
||||
clock->priv = priv;
|
||||
clock->hw.init = &init;
|
||||
|
||||
clk = clk_register(NULL, &clock->hw);
|
||||
if (IS_ERR(clk))
|
||||
goto fail;
|
||||
|
||||
dev_dbg(dev, "Module clock %pC at %pCr Hz\n", clk, clk);
|
||||
priv->clks[id] = clk;
|
||||
return;
|
||||
|
||||
fail:
|
||||
dev_err(dev, "Failed to register %s clock %s: %ld\n", "module,",
|
||||
mod->name, PTR_ERR(clk));
|
||||
kfree(clock);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CONFIG_PM_GENERIC_DOMAINS_OF
|
||||
struct cpg_mssr_clk_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
struct device_node *np;
|
||||
unsigned int num_core_pm_clks;
|
||||
unsigned int core_pm_clks[0];
|
||||
};
|
||||
|
||||
static bool cpg_mssr_is_pm_clk(const struct of_phandle_args *clkspec,
|
||||
struct cpg_mssr_clk_domain *pd)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
if (clkspec->np != pd->np || clkspec->args_count != 2)
|
||||
return false;
|
||||
|
||||
switch (clkspec->args[0]) {
|
||||
case CPG_CORE:
|
||||
for (i = 0; i < pd->num_core_pm_clks; i++)
|
||||
if (clkspec->args[1] == pd->core_pm_clks[i])
|
||||
return true;
|
||||
return false;
|
||||
|
||||
case CPG_MOD:
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static int cpg_mssr_attach_dev(struct generic_pm_domain *genpd,
|
||||
struct device *dev)
|
||||
{
|
||||
struct cpg_mssr_clk_domain *pd =
|
||||
container_of(genpd, struct cpg_mssr_clk_domain, genpd);
|
||||
struct device_node *np = dev->of_node;
|
||||
struct of_phandle_args clkspec;
|
||||
struct clk *clk;
|
||||
int i = 0;
|
||||
int error;
|
||||
|
||||
while (!of_parse_phandle_with_args(np, "clocks", "#clock-cells", i,
|
||||
&clkspec)) {
|
||||
if (cpg_mssr_is_pm_clk(&clkspec, pd))
|
||||
goto found;
|
||||
|
||||
of_node_put(clkspec.np);
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
found:
|
||||
clk = of_clk_get_from_provider(&clkspec);
|
||||
of_node_put(clkspec.np);
|
||||
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
error = pm_clk_create(dev);
|
||||
if (error) {
|
||||
dev_err(dev, "pm_clk_create failed %d\n", error);
|
||||
goto fail_put;
|
||||
}
|
||||
|
||||
error = pm_clk_add_clk(dev, clk);
|
||||
if (error) {
|
||||
dev_err(dev, "pm_clk_add_clk %pC failed %d\n", clk, error);
|
||||
goto fail_destroy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
fail_destroy:
|
||||
pm_clk_destroy(dev);
|
||||
fail_put:
|
||||
clk_put(clk);
|
||||
return error;
|
||||
}
|
||||
|
||||
static void cpg_mssr_detach_dev(struct generic_pm_domain *genpd,
|
||||
struct device *dev)
|
||||
{
|
||||
if (!list_empty(&dev->power.subsys_data->clock_list))
|
||||
pm_clk_destroy(dev);
|
||||
}
|
||||
|
||||
static int __init cpg_mssr_add_clk_domain(struct device *dev,
|
||||
const unsigned int *core_pm_clks,
|
||||
unsigned int num_core_pm_clks)
|
||||
{
|
||||
struct device_node *np = dev->of_node;
|
||||
struct generic_pm_domain *genpd;
|
||||
struct cpg_mssr_clk_domain *pd;
|
||||
size_t pm_size = num_core_pm_clks * sizeof(core_pm_clks[0]);
|
||||
|
||||
pd = devm_kzalloc(dev, sizeof(*pd) + pm_size, GFP_KERNEL);
|
||||
if (!pd)
|
||||
return -ENOMEM;
|
||||
|
||||
pd->np = np;
|
||||
pd->num_core_pm_clks = num_core_pm_clks;
|
||||
memcpy(pd->core_pm_clks, core_pm_clks, pm_size);
|
||||
|
||||
genpd = &pd->genpd;
|
||||
genpd->name = np->name;
|
||||
genpd->flags = GENPD_FLAG_PM_CLK;
|
||||
pm_genpd_init(genpd, &simple_qos_governor, false);
|
||||
genpd->attach_dev = cpg_mssr_attach_dev;
|
||||
genpd->detach_dev = cpg_mssr_detach_dev;
|
||||
|
||||
of_genpd_add_provider_simple(np, genpd);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int cpg_mssr_add_clk_domain(struct device *dev,
|
||||
const unsigned int *core_pm_clks,
|
||||
unsigned int num_core_pm_clks)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* !CONFIG_PM_GENERIC_DOMAINS_OF */
|
||||
|
||||
|
||||
static const struct of_device_id cpg_mssr_match[] = {
|
||||
#ifdef CONFIG_ARCH_R8A7795
|
||||
{
|
||||
.compatible = "renesas,r8a7795-cpg-mssr",
|
||||
.data = &r8a7795_cpg_mssr_info,
|
||||
},
|
||||
#endif
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
static void cpg_mssr_del_clk_provider(void *data)
|
||||
{
|
||||
of_clk_del_provider(data);
|
||||
}
|
||||
|
||||
static int __init cpg_mssr_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
const struct cpg_mssr_info *info;
|
||||
struct cpg_mssr_priv *priv;
|
||||
unsigned int nclks, i;
|
||||
struct resource *res;
|
||||
struct clk **clks;
|
||||
int error;
|
||||
|
||||
info = of_match_node(cpg_mssr_match, np)->data;
|
||||
if (info->init) {
|
||||
error = info->init(dev);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->dev = dev;
|
||||
spin_lock_init(&priv->mstp_lock);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
priv->base = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(priv->base))
|
||||
return PTR_ERR(priv->base);
|
||||
|
||||
nclks = info->num_total_core_clks + info->num_hw_mod_clks;
|
||||
clks = devm_kmalloc_array(dev, nclks, sizeof(*clks), GFP_KERNEL);
|
||||
if (!clks)
|
||||
return -ENOMEM;
|
||||
|
||||
priv->clks = clks;
|
||||
priv->num_core_clks = info->num_total_core_clks;
|
||||
priv->num_mod_clks = info->num_hw_mod_clks;
|
||||
priv->last_dt_core_clk = info->last_dt_core_clk;
|
||||
|
||||
for (i = 0; i < nclks; i++)
|
||||
clks[i] = ERR_PTR(-ENOENT);
|
||||
|
||||
for (i = 0; i < info->num_core_clks; i++)
|
||||
cpg_mssr_register_core_clk(&info->core_clks[i], info, priv);
|
||||
|
||||
for (i = 0; i < info->num_mod_clks; i++)
|
||||
cpg_mssr_register_mod_clk(&info->mod_clks[i], info, priv);
|
||||
|
||||
error = of_clk_add_provider(np, cpg_mssr_clk_src_twocell_get, priv);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
devm_add_action(dev, cpg_mssr_del_clk_provider, np);
|
||||
|
||||
error = cpg_mssr_add_clk_domain(dev, info->core_pm_clks,
|
||||
info->num_core_pm_clks);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver cpg_mssr_driver = {
|
||||
.driver = {
|
||||
.name = "renesas-cpg-mssr",
|
||||
.of_match_table = cpg_mssr_match,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init cpg_mssr_init(void)
|
||||
{
|
||||
return platform_driver_probe(&cpg_mssr_driver, cpg_mssr_probe);
|
||||
}
|
||||
|
||||
subsys_initcall(cpg_mssr_init);
|
||||
|
||||
MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
|
||||
MODULE_LICENSE("GPL v2");
|
|
@ -0,0 +1,132 @@
|
|||
/*
|
||||
* Renesas Clock Pulse Generator / Module Standby and Software Reset
|
||||
*
|
||||
* Copyright (C) 2015 Glider bvba
|
||||
*
|
||||
* 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; version 2 of the License.
|
||||
*/
|
||||
|
||||
#ifndef __CLK_RENESAS_CPG_MSSR_H__
|
||||
#define __CLK_RENESAS_CPG_MSSR_H__
|
||||
|
||||
/*
|
||||
* Definitions of CPG Core Clocks
|
||||
*
|
||||
* These include:
|
||||
* - Clock outputs exported to DT
|
||||
* - External input clocks
|
||||
* - Internal CPG clocks
|
||||
*/
|
||||
|
||||
struct cpg_core_clk {
|
||||
/* Common */
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
unsigned int type;
|
||||
/* Depending on type */
|
||||
unsigned int parent; /* Core Clocks only */
|
||||
unsigned int div;
|
||||
unsigned int mult;
|
||||
unsigned int offset;
|
||||
};
|
||||
|
||||
enum clk_types {
|
||||
/* Generic */
|
||||
CLK_TYPE_IN, /* External Clock Input */
|
||||
CLK_TYPE_FF, /* Fixed Factor Clock */
|
||||
CLK_TYPE_DIV6P1, /* DIV6 Clock with 1 parent clock */
|
||||
|
||||
/* Custom definitions start here */
|
||||
CLK_TYPE_CUSTOM,
|
||||
};
|
||||
|
||||
#define DEF_TYPE(_name, _id, _type...) \
|
||||
{ .name = _name, .id = _id, .type = _type }
|
||||
#define DEF_BASE(_name, _id, _type, _parent...) \
|
||||
DEF_TYPE(_name, _id, _type, .parent = _parent)
|
||||
|
||||
#define DEF_INPUT(_name, _id) \
|
||||
DEF_TYPE(_name, _id, CLK_TYPE_IN)
|
||||
#define DEF_FIXED(_name, _id, _parent, _div, _mult) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_FF, _parent, .div = _div, .mult = _mult)
|
||||
#define DEF_DIV6P1(_name, _id, _parent, _offset) \
|
||||
DEF_BASE(_name, _id, CLK_TYPE_DIV6P1, _parent, .offset = _offset)
|
||||
|
||||
|
||||
/*
|
||||
* Definitions of Module Clocks
|
||||
*/
|
||||
|
||||
struct mssr_mod_clk {
|
||||
const char *name;
|
||||
unsigned int id;
|
||||
unsigned int parent; /* Add MOD_CLK_BASE for Module Clocks */
|
||||
};
|
||||
|
||||
/* Convert from sparse base-100 to packed index space */
|
||||
#define MOD_CLK_PACK(x) ((x) - ((x) / 100) * (100 - 32))
|
||||
|
||||
#define MOD_CLK_ID(x) (MOD_CLK_BASE + MOD_CLK_PACK(x))
|
||||
|
||||
#define DEF_MOD(_name, _mod, _parent...) \
|
||||
{ .name = _name, .id = MOD_CLK_ID(_mod), .parent = _parent }
|
||||
|
||||
|
||||
struct device_node;
|
||||
|
||||
/**
|
||||
* SoC-specific CPG/MSSR Description
|
||||
*
|
||||
* @core_clks: Array of Core Clock definitions
|
||||
* @num_core_clks: Number of entries in core_clks[]
|
||||
* @last_dt_core_clk: ID of the last Core Clock exported to DT
|
||||
* @num_total_core_clks: Total number of Core Clocks (exported + internal)
|
||||
*
|
||||
* @mod_clks: Array of Module Clock definitions
|
||||
* @num_mod_clks: Number of entries in mod_clks[]
|
||||
* @num_hw_mod_clks: Number of Module Clocks supported by the hardware
|
||||
*
|
||||
* @crit_mod_clks: Array with Module Clock IDs of critical clocks that
|
||||
* should not be disabled without a knowledgeable driver
|
||||
* @num_crit_mod_clks: Number of entries in crit_mod_clks[]
|
||||
*
|
||||
* @core_pm_clks: Array with IDs of Core Clocks that are suitable for Power
|
||||
* Management, in addition to Module Clocks
|
||||
* @num_core_pm_clks: Number of entries in core_pm_clks[]
|
||||
*
|
||||
* @init: Optional callback to perform SoC-specific initialization
|
||||
* @cpg_clk_register: Optional callback to handle special Core Clock types
|
||||
*/
|
||||
|
||||
struct cpg_mssr_info {
|
||||
/* Core Clocks */
|
||||
const struct cpg_core_clk *core_clks;
|
||||
unsigned int num_core_clks;
|
||||
unsigned int last_dt_core_clk;
|
||||
unsigned int num_total_core_clks;
|
||||
|
||||
/* Module Clocks */
|
||||
const struct mssr_mod_clk *mod_clks;
|
||||
unsigned int num_mod_clks;
|
||||
unsigned int num_hw_mod_clks;
|
||||
|
||||
/* Critical Module Clocks that should not be disabled */
|
||||
const unsigned int *crit_mod_clks;
|
||||
unsigned int num_crit_mod_clks;
|
||||
|
||||
/* Core Clocks suitable for PM, in addition to the Module Clocks */
|
||||
const unsigned int *core_pm_clks;
|
||||
unsigned int num_core_pm_clks;
|
||||
|
||||
/* Callbacks */
|
||||
int (*init)(struct device *dev);
|
||||
struct clk *(*cpg_clk_register)(struct device *dev,
|
||||
const struct cpg_core_clk *core,
|
||||
const struct cpg_mssr_info *info,
|
||||
struct clk **clks, void __iomem *base);
|
||||
};
|
||||
|
||||
extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
|
||||
#endif
|
|
@ -549,19 +549,20 @@ static int clk_fs660c32_vco_get_params(unsigned long input,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw, unsigned long rate
|
||||
, unsigned long *prate)
|
||||
static long quadfs_pll_fs660c32_round_rate(struct clk_hw *hw,
|
||||
unsigned long rate,
|
||||
unsigned long *prate)
|
||||
{
|
||||
struct stm_fs params;
|
||||
|
||||
if (!clk_fs660c32_vco_get_params(*prate, rate, ¶ms))
|
||||
if (clk_fs660c32_vco_get_params(*prate, rate, ¶ms))
|
||||
return rate;
|
||||
|
||||
clk_fs660c32_vco_get_rate(*prate, ¶ms, &rate);
|
||||
|
||||
pr_debug("%s: %s new rate %ld [sdiv=0x%x,md=0x%x,pe=0x%x,nsdiv3=%u]\n",
|
||||
pr_debug("%s: %s new rate %ld [ndiv=%u]\n",
|
||||
__func__, clk_hw_get_name(hw),
|
||||
rate, (unsigned int)params.sdiv,
|
||||
(unsigned int)params.mdiv,
|
||||
(unsigned int)params.pe, (unsigned int)params.nsdiv);
|
||||
rate, (unsigned int)params.ndiv);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
|
|
@ -7,14 +7,19 @@ obj-y += clk-a10-codec.o
|
|||
obj-y += clk-a10-hosc.o
|
||||
obj-y += clk-a10-mod1.o
|
||||
obj-y += clk-a10-pll2.o
|
||||
obj-y += clk-a10-ve.o
|
||||
obj-y += clk-a20-gmac.o
|
||||
obj-y += clk-mod0.o
|
||||
obj-y += clk-simple-gates.o
|
||||
obj-y += clk-sun8i-bus-gates.o
|
||||
obj-y += clk-sun8i-mbus.o
|
||||
obj-y += clk-sun9i-core.o
|
||||
obj-y += clk-sun9i-mmc.o
|
||||
obj-y += clk-usb.o
|
||||
|
||||
obj-$(CONFIG_MACH_SUN9I) += clk-sun8i-apb0.o
|
||||
obj-$(CONFIG_MACH_SUN9I) += clk-sun9i-cpus.o
|
||||
|
||||
obj-$(CONFIG_MFD_SUN6I_PRCM) += \
|
||||
clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o \
|
||||
clk-sun8i-apb0.o
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright 2015 Chen-Yu Tsai
|
||||
*
|
||||
* Chen-Yu Tsai <wens@csie.org>
|
||||
*
|
||||
* 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/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
static DEFINE_SPINLOCK(ve_lock);
|
||||
|
||||
#define SUN4I_VE_ENABLE 31
|
||||
#define SUN4I_VE_DIVIDER_SHIFT 16
|
||||
#define SUN4I_VE_DIVIDER_WIDTH 3
|
||||
#define SUN4I_VE_RESET 0
|
||||
|
||||
/**
|
||||
* sunxi_ve_reset... - reset bit in ve clk registers handling
|
||||
*/
|
||||
|
||||
struct ve_reset_data {
|
||||
void __iomem *reg;
|
||||
spinlock_t *lock;
|
||||
struct reset_controller_dev rcdev;
|
||||
};
|
||||
|
||||
static int sunxi_ve_reset_assert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct ve_reset_data *data = container_of(rcdev,
|
||||
struct ve_reset_data,
|
||||
rcdev);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(data->lock, flags);
|
||||
|
||||
reg = readl(data->reg);
|
||||
writel(reg & ~BIT(SUN4I_VE_RESET), data->reg);
|
||||
|
||||
spin_unlock_irqrestore(data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sunxi_ve_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
unsigned long id)
|
||||
{
|
||||
struct ve_reset_data *data = container_of(rcdev,
|
||||
struct ve_reset_data,
|
||||
rcdev);
|
||||
unsigned long flags;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(data->lock, flags);
|
||||
|
||||
reg = readl(data->reg);
|
||||
writel(reg | BIT(SUN4I_VE_RESET), data->reg);
|
||||
|
||||
spin_unlock_irqrestore(data->lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev,
|
||||
const struct of_phandle_args *reset_spec)
|
||||
{
|
||||
if (WARN_ON(reset_spec->args_count != 0))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct reset_control_ops sunxi_ve_reset_ops = {
|
||||
.assert = sunxi_ve_reset_assert,
|
||||
.deassert = sunxi_ve_reset_deassert,
|
||||
};
|
||||
|
||||
static void __init sun4i_ve_clk_setup(struct device_node *node)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk_divider *div;
|
||||
struct clk_gate *gate;
|
||||
struct ve_reset_data *reset_data;
|
||||
const char *parent;
|
||||
const char *clk_name = node->name;
|
||||
void __iomem *reg;
|
||||
int err;
|
||||
|
||||
reg = of_io_request_and_map(node, 0, of_node_full_name(node));
|
||||
if (IS_ERR(reg))
|
||||
return;
|
||||
|
||||
div = kzalloc(sizeof(*div), GFP_KERNEL);
|
||||
if (!div)
|
||||
goto err_unmap;
|
||||
|
||||
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
|
||||
if (!gate)
|
||||
goto err_free_div;
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
parent = of_clk_get_parent_name(node, 0);
|
||||
|
||||
gate->reg = reg;
|
||||
gate->bit_idx = SUN4I_VE_ENABLE;
|
||||
gate->lock = &ve_lock;
|
||||
|
||||
div->reg = reg;
|
||||
div->shift = SUN4I_VE_DIVIDER_SHIFT;
|
||||
div->width = SUN4I_VE_DIVIDER_WIDTH;
|
||||
div->lock = &ve_lock;
|
||||
|
||||
clk = clk_register_composite(NULL, clk_name, &parent, 1,
|
||||
NULL, NULL,
|
||||
&div->hw, &clk_divider_ops,
|
||||
&gate->hw, &clk_gate_ops,
|
||||
CLK_SET_RATE_PARENT);
|
||||
if (IS_ERR(clk))
|
||||
goto err_free_gate;
|
||||
|
||||
err = of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||
if (err)
|
||||
goto err_unregister_clk;
|
||||
|
||||
reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL);
|
||||
if (!reset_data)
|
||||
goto err_del_provider;
|
||||
|
||||
reset_data->reg = reg;
|
||||
reset_data->lock = &ve_lock;
|
||||
reset_data->rcdev.nr_resets = 1;
|
||||
reset_data->rcdev.ops = &sunxi_ve_reset_ops;
|
||||
reset_data->rcdev.of_node = node;
|
||||
reset_data->rcdev.of_xlate = sunxi_ve_of_xlate;
|
||||
reset_data->rcdev.of_reset_n_cells = 0;
|
||||
err = reset_controller_register(&reset_data->rcdev);
|
||||
if (err)
|
||||
goto err_free_reset;
|
||||
|
||||
return;
|
||||
|
||||
err_free_reset:
|
||||
kfree(reset_data);
|
||||
err_del_provider:
|
||||
of_clk_del_provider(node);
|
||||
err_unregister_clk:
|
||||
clk_unregister(clk);
|
||||
err_free_gate:
|
||||
kfree(gate);
|
||||
err_free_div:
|
||||
kfree(div);
|
||||
err_unmap:
|
||||
iounmap(reg);
|
||||
}
|
||||
CLK_OF_DECLARE(sun4i_ve, "allwinner,sun4i-a10-ve-clk",
|
||||
sun4i_ve_clk_setup);
|
|
@ -140,6 +140,8 @@ CLK_OF_DECLARE(sun9i_a80_apb0, "allwinner,sun9i-a80-apb0-gates-clk",
|
|||
sunxi_simple_gates_init);
|
||||
CLK_OF_DECLARE(sun9i_a80_apb1, "allwinner,sun9i-a80-apb1-gates-clk",
|
||||
sunxi_simple_gates_init);
|
||||
CLK_OF_DECLARE(sun9i_a80_apbs, "allwinner,sun9i-a80-apbs-gates-clk",
|
||||
sunxi_simple_gates_init);
|
||||
|
||||
static const int sun4i_a10_ahb_critical_clocks[] __initconst = {
|
||||
14, /* ahb_sdram */
|
||||
|
@ -158,3 +160,15 @@ CLK_OF_DECLARE(sun5i_a13_ahb, "allwinner,sun5i-a13-ahb-gates-clk",
|
|||
sun4i_a10_ahb_init);
|
||||
CLK_OF_DECLARE(sun7i_a20_ahb, "allwinner,sun7i-a20-ahb-gates-clk",
|
||||
sun4i_a10_ahb_init);
|
||||
|
||||
static const int sun4i_a10_dram_critical_clocks[] __initconst = {
|
||||
15, /* dram_output */
|
||||
};
|
||||
|
||||
static void __init sun4i_a10_dram_init(struct device_node *node)
|
||||
{
|
||||
sunxi_simple_gates_setup(node, sun4i_a10_dram_critical_clocks,
|
||||
ARRAY_SIZE(sun4i_a10_dram_critical_clocks));
|
||||
}
|
||||
CLK_OF_DECLARE(sun4i_a10_dram, "allwinner,sun4i-a10-dram-gates-clk",
|
||||
sun4i_a10_dram_init);
|
||||
|
|
|
@ -17,13 +17,77 @@
|
|||
#include <linux/clk-provider.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
||||
static struct clk *sun8i_a23_apb0_register(struct device_node *node,
|
||||
void __iomem *reg)
|
||||
{
|
||||
const char *clk_name = node->name;
|
||||
const char *clk_parent;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
clk_parent = of_clk_get_parent_name(node, 0);
|
||||
if (!clk_parent)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
/* The A23 APB0 clock is a standard 2 bit wide divider clock */
|
||||
clk = clk_register_divider(NULL, clk_name, clk_parent, 0, reg,
|
||||
0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
|
||||
if (IS_ERR(clk))
|
||||
return clk;
|
||||
|
||||
ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||
if (ret)
|
||||
goto err_unregister;
|
||||
|
||||
return clk;
|
||||
|
||||
err_unregister:
|
||||
clk_unregister_divider(clk);
|
||||
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
static void sun8i_a23_apb0_setup(struct device_node *node)
|
||||
{
|
||||
void __iomem *reg;
|
||||
struct resource res;
|
||||
struct clk *clk;
|
||||
|
||||
reg = of_io_request_and_map(node, 0, of_node_full_name(node));
|
||||
if (IS_ERR(reg)) {
|
||||
/*
|
||||
* This happens with clk nodes instantiated through mfd,
|
||||
* as those do not have their resources assigned in the
|
||||
* device tree. Do not print an error in this case.
|
||||
*/
|
||||
if (PTR_ERR(reg) != -EINVAL)
|
||||
pr_err("Could not get registers for a23-apb0-clk\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clk = sun8i_a23_apb0_register(node, reg);
|
||||
if (IS_ERR(clk))
|
||||
goto err_unmap;
|
||||
|
||||
return;
|
||||
|
||||
err_unmap:
|
||||
iounmap(reg);
|
||||
of_address_to_resource(node, 0, &res);
|
||||
release_mem_region(res.start, resource_size(&res));
|
||||
}
|
||||
CLK_OF_DECLARE(sun8i_a23_apb0, "allwinner,sun8i-a23-apb0-clk",
|
||||
sun8i_a23_apb0_setup);
|
||||
|
||||
static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *np = pdev->dev.of_node;
|
||||
const char *clk_name = np->name;
|
||||
const char *clk_parent;
|
||||
struct resource *r;
|
||||
void __iomem *reg;
|
||||
struct clk *clk;
|
||||
|
@ -33,19 +97,11 @@ static int sun8i_a23_apb0_clk_probe(struct platform_device *pdev)
|
|||
if (IS_ERR(reg))
|
||||
return PTR_ERR(reg);
|
||||
|
||||
clk_parent = of_clk_get_parent_name(np, 0);
|
||||
if (!clk_parent)
|
||||
return -EINVAL;
|
||||
|
||||
of_property_read_string(np, "clock-output-names", &clk_name);
|
||||
|
||||
/* The A23 APB0 clock is a standard 2 bit wide divider clock */
|
||||
clk = clk_register_divider(&pdev->dev, clk_name, clk_parent, 0, reg,
|
||||
0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL);
|
||||
clk = sun8i_a23_apb0_register(np, reg);
|
||||
if (IS_ERR(clk))
|
||||
return PTR_ERR(clk);
|
||||
|
||||
return of_clk_add_provider(np, of_clk_src_simple_get, clk);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id sun8i_a23_apb0_clk_dt_ids[] = {
|
||||
|
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
|
||||
*
|
||||
* Based on clk-simple-gates.c, which is:
|
||||
* Copyright 2015 Maxime Ripard
|
||||
*
|
||||
* Maxime Ripard <maxime.ripard@free-electrons.com>
|
||||
*
|
||||
* 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.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
static DEFINE_SPINLOCK(gates_lock);
|
||||
|
||||
static void __init sun8i_h3_bus_gates_init(struct device_node *node)
|
||||
{
|
||||
static const char * const names[] = { "ahb1", "ahb2", "apb1", "apb2" };
|
||||
enum { AHB1, AHB2, APB1, APB2, PARENT_MAX } clk_parent;
|
||||
const char *parents[PARENT_MAX];
|
||||
struct clk_onecell_data *clk_data;
|
||||
const char *clk_name;
|
||||
struct property *prop;
|
||||
struct resource res;
|
||||
void __iomem *clk_reg;
|
||||
void __iomem *reg;
|
||||
const __be32 *p;
|
||||
int number, i;
|
||||
u8 clk_bit;
|
||||
int index;
|
||||
|
||||
reg = of_io_request_and_map(node, 0, of_node_full_name(node));
|
||||
if (IS_ERR(reg))
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(names); i++) {
|
||||
int idx = of_property_match_string(node, "clock-names",
|
||||
names[i]);
|
||||
if (idx < 0)
|
||||
return;
|
||||
|
||||
parents[i] = of_clk_get_parent_name(node, idx);
|
||||
}
|
||||
|
||||
clk_data = kmalloc(sizeof(struct clk_onecell_data), GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
goto err_unmap;
|
||||
|
||||
number = of_property_count_u32_elems(node, "clock-indices");
|
||||
of_property_read_u32_index(node, "clock-indices", number - 1, &number);
|
||||
|
||||
clk_data->clks = kcalloc(number + 1, sizeof(struct clk *), GFP_KERNEL);
|
||||
if (!clk_data->clks)
|
||||
goto err_free_data;
|
||||
|
||||
i = 0;
|
||||
of_property_for_each_u32(node, "clock-indices", prop, p, index) {
|
||||
of_property_read_string_index(node, "clock-output-names",
|
||||
i, &clk_name);
|
||||
|
||||
if (index == 17 || (index >= 29 && index <= 31))
|
||||
clk_parent = AHB2;
|
||||
else if (index <= 63 || index >= 128)
|
||||
clk_parent = AHB1;
|
||||
else if (index >= 64 && index <= 95)
|
||||
clk_parent = APB1;
|
||||
else if (index >= 96 && index <= 127)
|
||||
clk_parent = APB2;
|
||||
|
||||
clk_reg = reg + 4 * (index / 32);
|
||||
clk_bit = index % 32;
|
||||
|
||||
clk_data->clks[index] = clk_register_gate(NULL, clk_name,
|
||||
parents[clk_parent],
|
||||
0, clk_reg, clk_bit,
|
||||
0, &gates_lock);
|
||||
i++;
|
||||
|
||||
if (IS_ERR(clk_data->clks[index])) {
|
||||
WARN_ON(true);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
clk_data->clk_num = number + 1;
|
||||
of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||
|
||||
return;
|
||||
|
||||
err_free_data:
|
||||
kfree(clk_data);
|
||||
err_unmap:
|
||||
iounmap(reg);
|
||||
of_address_to_resource(node, 0, &res);
|
||||
release_mem_region(res.start, resource_size(&res));
|
||||
}
|
||||
|
||||
CLK_OF_DECLARE(sun8i_h3_bus_gates, "allwinner,sun8i-h3-bus-gates-clk",
|
||||
sun8i_h3_bus_gates_init);
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* Copyright (C) 2015 Chen-Yu Tsai
|
||||
*
|
||||
* Chen-Yu Tsai <wens@csie.org>
|
||||
*
|
||||
* Allwinner A80 CPUS clock driver
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
|
||||
static DEFINE_SPINLOCK(sun9i_a80_cpus_lock);
|
||||
|
||||
/**
|
||||
* sun9i_a80_cpus_clk_setup() - Setup function for a80 cpus composite clk
|
||||
*/
|
||||
|
||||
#define SUN9I_CPUS_MAX_PARENTS 4
|
||||
#define SUN9I_CPUS_MUX_PARENT_PLL4 3
|
||||
#define SUN9I_CPUS_MUX_SHIFT 16
|
||||
#define SUN9I_CPUS_MUX_MASK GENMASK(17, 16)
|
||||
#define SUN9I_CPUS_MUX_GET_PARENT(reg) ((reg & SUN9I_CPUS_MUX_MASK) >> \
|
||||
SUN9I_CPUS_MUX_SHIFT)
|
||||
|
||||
#define SUN9I_CPUS_DIV_SHIFT 4
|
||||
#define SUN9I_CPUS_DIV_MASK GENMASK(5, 4)
|
||||
#define SUN9I_CPUS_DIV_GET(reg) ((reg & SUN9I_CPUS_DIV_MASK) >> \
|
||||
SUN9I_CPUS_DIV_SHIFT)
|
||||
#define SUN9I_CPUS_DIV_SET(reg, div) ((reg & ~SUN9I_CPUS_DIV_MASK) | \
|
||||
(div << SUN9I_CPUS_DIV_SHIFT))
|
||||
#define SUN9I_CPUS_PLL4_DIV_SHIFT 8
|
||||
#define SUN9I_CPUS_PLL4_DIV_MASK GENMASK(12, 8)
|
||||
#define SUN9I_CPUS_PLL4_DIV_GET(reg) ((reg & SUN9I_CPUS_PLL4_DIV_MASK) >> \
|
||||
SUN9I_CPUS_PLL4_DIV_SHIFT)
|
||||
#define SUN9I_CPUS_PLL4_DIV_SET(reg, div) ((reg & ~SUN9I_CPUS_PLL4_DIV_MASK) | \
|
||||
(div << SUN9I_CPUS_PLL4_DIV_SHIFT))
|
||||
|
||||
struct sun9i_a80_cpus_clk {
|
||||
struct clk_hw hw;
|
||||
void __iomem *reg;
|
||||
};
|
||||
|
||||
#define to_sun9i_a80_cpus_clk(_hw) container_of(_hw, struct sun9i_a80_cpus_clk, hw)
|
||||
|
||||
static unsigned long sun9i_a80_cpus_clk_recalc_rate(struct clk_hw *hw,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
|
||||
unsigned long rate;
|
||||
u32 reg;
|
||||
|
||||
/* Fetch the register value */
|
||||
reg = readl(cpus->reg);
|
||||
|
||||
/* apply pre-divider first if parent is pll4 */
|
||||
if (SUN9I_CPUS_MUX_GET_PARENT(reg) == SUN9I_CPUS_MUX_PARENT_PLL4)
|
||||
parent_rate /= SUN9I_CPUS_PLL4_DIV_GET(reg) + 1;
|
||||
|
||||
/* clk divider */
|
||||
rate = parent_rate / (SUN9I_CPUS_DIV_GET(reg) + 1);
|
||||
|
||||
return rate;
|
||||
}
|
||||
|
||||
static long sun9i_a80_cpus_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
|
||||
u8 parent, unsigned long parent_rate)
|
||||
{
|
||||
u8 div, pre_div = 1;
|
||||
|
||||
/*
|
||||
* clock can only divide, so we will never be able to achieve
|
||||
* frequencies higher than the parent frequency
|
||||
*/
|
||||
if (parent_rate && rate > parent_rate)
|
||||
rate = parent_rate;
|
||||
|
||||
div = DIV_ROUND_UP(parent_rate, rate);
|
||||
|
||||
/* calculate pre-divider if parent is pll4 */
|
||||
if (parent == SUN9I_CPUS_MUX_PARENT_PLL4 && div > 4) {
|
||||
/* pre-divider is 1 ~ 32 */
|
||||
if (div < 32) {
|
||||
pre_div = div;
|
||||
div = 1;
|
||||
} else if (div < 64) {
|
||||
pre_div = DIV_ROUND_UP(div, 2);
|
||||
div = 2;
|
||||
} else if (div < 96) {
|
||||
pre_div = DIV_ROUND_UP(div, 3);
|
||||
div = 3;
|
||||
} else {
|
||||
pre_div = DIV_ROUND_UP(div, 4);
|
||||
div = 4;
|
||||
}
|
||||
}
|
||||
|
||||
/* we were asked to pass back divider values */
|
||||
if (divp) {
|
||||
*divp = div - 1;
|
||||
*pre_divp = pre_div - 1;
|
||||
}
|
||||
|
||||
return parent_rate / pre_div / div;
|
||||
}
|
||||
|
||||
static int sun9i_a80_cpus_clk_determine_rate(struct clk_hw *clk,
|
||||
struct clk_rate_request *req)
|
||||
{
|
||||
struct clk_hw *parent, *best_parent = NULL;
|
||||
int i, num_parents;
|
||||
unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
|
||||
unsigned long rate = req->rate;
|
||||
|
||||
/* find the parent that can help provide the fastest rate <= rate */
|
||||
num_parents = clk_hw_get_num_parents(clk);
|
||||
for (i = 0; i < num_parents; i++) {
|
||||
parent = clk_hw_get_parent_by_index(clk, i);
|
||||
if (!parent)
|
||||
continue;
|
||||
if (clk_hw_get_flags(clk) & CLK_SET_RATE_PARENT)
|
||||
parent_rate = clk_hw_round_rate(parent, rate);
|
||||
else
|
||||
parent_rate = clk_hw_get_rate(parent);
|
||||
|
||||
child_rate = sun9i_a80_cpus_clk_round(rate, NULL, NULL, i,
|
||||
parent_rate);
|
||||
|
||||
if (child_rate <= rate && child_rate > best_child_rate) {
|
||||
best_parent = parent;
|
||||
best = parent_rate;
|
||||
best_child_rate = child_rate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!best_parent)
|
||||
return -EINVAL;
|
||||
|
||||
req->best_parent_hw = best_parent;
|
||||
req->best_parent_rate = best;
|
||||
req->rate = best_child_rate;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sun9i_a80_cpus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||
unsigned long parent_rate)
|
||||
{
|
||||
struct sun9i_a80_cpus_clk *cpus = to_sun9i_a80_cpus_clk(hw);
|
||||
unsigned long flags;
|
||||
u8 div, pre_div, parent;
|
||||
u32 reg;
|
||||
|
||||
spin_lock_irqsave(&sun9i_a80_cpus_lock, flags);
|
||||
|
||||
reg = readl(cpus->reg);
|
||||
|
||||
/* need to know which parent is used to apply pre-divider */
|
||||
parent = SUN9I_CPUS_MUX_GET_PARENT(reg);
|
||||
sun9i_a80_cpus_clk_round(rate, &div, &pre_div, parent, parent_rate);
|
||||
|
||||
reg = SUN9I_CPUS_DIV_SET(reg, div);
|
||||
reg = SUN9I_CPUS_PLL4_DIV_SET(reg, pre_div);
|
||||
writel(reg, cpus->reg);
|
||||
|
||||
spin_unlock_irqrestore(&sun9i_a80_cpus_lock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct clk_ops sun9i_a80_cpus_clk_ops = {
|
||||
.determine_rate = sun9i_a80_cpus_clk_determine_rate,
|
||||
.recalc_rate = sun9i_a80_cpus_clk_recalc_rate,
|
||||
.set_rate = sun9i_a80_cpus_clk_set_rate,
|
||||
};
|
||||
|
||||
static void sun9i_a80_cpus_setup(struct device_node *node)
|
||||
{
|
||||
const char *clk_name = node->name;
|
||||
const char *parents[SUN9I_CPUS_MAX_PARENTS];
|
||||
struct resource res;
|
||||
struct sun9i_a80_cpus_clk *cpus;
|
||||
struct clk_mux *mux;
|
||||
struct clk *clk;
|
||||
int ret;
|
||||
|
||||
cpus = kzalloc(sizeof(*cpus), GFP_KERNEL);
|
||||
if (!cpus)
|
||||
return;
|
||||
|
||||
cpus->reg = of_io_request_and_map(node, 0, of_node_full_name(node));
|
||||
if (IS_ERR(cpus->reg))
|
||||
goto err_free_cpus;
|
||||
|
||||
of_property_read_string(node, "clock-output-names", &clk_name);
|
||||
|
||||
/* we have a mux, we will have >1 parents */
|
||||
ret = of_clk_parent_fill(node, parents, SUN9I_CPUS_MAX_PARENTS);
|
||||
|
||||
mux = kzalloc(sizeof(*mux), GFP_KERNEL);
|
||||
if (!mux)
|
||||
goto err_unmap;
|
||||
|
||||
/* set up clock properties */
|
||||
mux->reg = cpus->reg;
|
||||
mux->shift = SUN9I_CPUS_MUX_SHIFT;
|
||||
/* un-shifted mask is what mux_clk expects */
|
||||
mux->mask = SUN9I_CPUS_MUX_MASK >> SUN9I_CPUS_MUX_SHIFT;
|
||||
mux->lock = &sun9i_a80_cpus_lock;
|
||||
|
||||
clk = clk_register_composite(NULL, clk_name, parents, ret,
|
||||
&mux->hw, &clk_mux_ops,
|
||||
&cpus->hw, &sun9i_a80_cpus_clk_ops,
|
||||
NULL, NULL, 0);
|
||||
if (IS_ERR(clk))
|
||||
goto err_free_mux;
|
||||
|
||||
ret = of_clk_add_provider(node, of_clk_src_simple_get, clk);
|
||||
if (ret)
|
||||
goto err_unregister;
|
||||
|
||||
return;
|
||||
|
||||
err_unregister:
|
||||
clk_unregister(clk);
|
||||
err_free_mux:
|
||||
kfree(mux);
|
||||
err_unmap:
|
||||
iounmap(cpus->reg);
|
||||
of_address_to_resource(node, 0, &res);
|
||||
release_mem_region(res.start, resource_size(&res));
|
||||
err_free_cpus:
|
||||
kfree(cpus);
|
||||
}
|
||||
CLK_OF_DECLARE(sun9i_a80_cpus, "allwinner,sun9i-a80-cpus-clk",
|
||||
sun9i_a80_cpus_setup);
|
|
@ -778,6 +778,10 @@ static const struct mux_data sun6i_a31_ahb1_mux_data __initconst = {
|
|||
.shift = 12,
|
||||
};
|
||||
|
||||
static const struct mux_data sun8i_h3_ahb2_mux_data __initconst = {
|
||||
.shift = 0,
|
||||
};
|
||||
|
||||
static void __init sunxi_mux_clk_setup(struct device_node *node,
|
||||
struct mux_data *data)
|
||||
{
|
||||
|
@ -1130,6 +1134,7 @@ static const struct of_device_id clk_divs_match[] __initconst = {
|
|||
static const struct of_device_id clk_mux_match[] __initconst = {
|
||||
{.compatible = "allwinner,sun4i-a10-cpu-clk", .data = &sun4i_cpu_mux_data,},
|
||||
{.compatible = "allwinner,sun6i-a31-ahb1-mux-clk", .data = &sun6i_a31_ahb1_mux_data,},
|
||||
{.compatible = "allwinner,sun8i-h3-ahb2-clk", .data = &sun8i_h3_ahb2_mux_data,},
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -1212,6 +1217,7 @@ CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
|
|||
CLK_OF_DECLARE(sun6i_a31s_clk_init, "allwinner,sun6i-a31s", sun6i_init_clocks);
|
||||
CLK_OF_DECLARE(sun8i_a23_clk_init, "allwinner,sun8i-a23", sun6i_init_clocks);
|
||||
CLK_OF_DECLARE(sun8i_a33_clk_init, "allwinner,sun8i-a33", sun6i_init_clocks);
|
||||
CLK_OF_DECLARE(sun8i_h3_clk_init, "allwinner,sun8i-h3", sun6i_init_clocks);
|
||||
|
||||
static void __init sun9i_init_clocks(struct device_node *node)
|
||||
{
|
||||
|
|
|
@ -243,3 +243,15 @@ static void __init sun9i_a80_usb_phy_setup(struct device_node *node)
|
|||
sunxi_usb_clk_setup(node, &sun9i_a80_usb_phy_data, &a80_usb_phy_lock);
|
||||
}
|
||||
CLK_OF_DECLARE(sun9i_a80_usb_phy, "allwinner,sun9i-a80-usb-phy-clk", sun9i_a80_usb_phy_setup);
|
||||
|
||||
static const struct usb_clk_data sun8i_h3_usb_clk_data __initconst = {
|
||||
.clk_mask = BIT(19) | BIT(18) | BIT(17) | BIT(16) |
|
||||
BIT(11) | BIT(10) | BIT(9) | BIT(8),
|
||||
.reset_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
|
||||
};
|
||||
|
||||
static void __init sun8i_h3_usb_setup(struct device_node *node)
|
||||
{
|
||||
sunxi_usb_clk_setup(node, &sun8i_h3_usb_clk_data, &sun4i_a10_usb_lock);
|
||||
}
|
||||
CLK_OF_DECLARE(sun8i_h3_usb, "allwinner,sun8i-h3-usb-clk", sun8i_h3_usb_setup);
|
||||
|
|
|
@ -20,3 +20,4 @@ obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124.o
|
|||
obj-$(CONFIG_ARCH_TEGRA_124_SOC) += clk-tegra124-dfll-fcpu.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_132_SOC) += clk-tegra124.o
|
||||
obj-y += cvb.o
|
||||
obj-$(CONFIG_ARCH_TEGRA_210_SOC) += clk-tegra210.o
|
||||
|
|
|
@ -13,6 +13,7 @@ enum clk_id {
|
|||
tegra_clk_amx1,
|
||||
tegra_clk_apbdma,
|
||||
tegra_clk_apbif,
|
||||
tegra_clk_ape,
|
||||
tegra_clk_audio0,
|
||||
tegra_clk_audio0_2x,
|
||||
tegra_clk_audio0_mux,
|
||||
|
@ -38,6 +39,7 @@ enum clk_id {
|
|||
tegra_clk_cile,
|
||||
tegra_clk_clk_32k,
|
||||
tegra_clk_clk72Mhz,
|
||||
tegra_clk_clk72Mhz_8,
|
||||
tegra_clk_clk_m,
|
||||
tegra_clk_clk_m_div2,
|
||||
tegra_clk_clk_m_div4,
|
||||
|
@ -51,17 +53,21 @@ enum clk_id {
|
|||
tegra_clk_cml1,
|
||||
tegra_clk_csi,
|
||||
tegra_clk_csite,
|
||||
tegra_clk_csite_8,
|
||||
tegra_clk_csus,
|
||||
tegra_clk_cve,
|
||||
tegra_clk_dam0,
|
||||
tegra_clk_dam1,
|
||||
tegra_clk_dam2,
|
||||
tegra_clk_d_audio,
|
||||
tegra_clk_dbgapb,
|
||||
tegra_clk_dds,
|
||||
tegra_clk_dfll_ref,
|
||||
tegra_clk_dfll_soc,
|
||||
tegra_clk_disp1,
|
||||
tegra_clk_disp1_8,
|
||||
tegra_clk_disp2,
|
||||
tegra_clk_disp2_8,
|
||||
tegra_clk_dp2,
|
||||
tegra_clk_dpaux,
|
||||
tegra_clk_dsialp,
|
||||
|
@ -71,6 +77,7 @@ enum clk_id {
|
|||
tegra_clk_dtv,
|
||||
tegra_clk_emc,
|
||||
tegra_clk_entropy,
|
||||
tegra_clk_entropy_8,
|
||||
tegra_clk_epp,
|
||||
tegra_clk_epp_8,
|
||||
tegra_clk_extern1,
|
||||
|
@ -85,12 +92,16 @@ enum clk_id {
|
|||
tegra_clk_gr3d_8,
|
||||
tegra_clk_hclk,
|
||||
tegra_clk_hda,
|
||||
tegra_clk_hda_8,
|
||||
tegra_clk_hda2codec_2x,
|
||||
tegra_clk_hda2codec_2x_8,
|
||||
tegra_clk_hda2hdmi,
|
||||
tegra_clk_hdmi,
|
||||
tegra_clk_hdmi_audio,
|
||||
tegra_clk_host1x,
|
||||
tegra_clk_host1x_8,
|
||||
tegra_clk_host1x_9,
|
||||
tegra_clk_hsic_trk,
|
||||
tegra_clk_i2c1,
|
||||
tegra_clk_i2c2,
|
||||
tegra_clk_i2c3,
|
||||
|
@ -110,11 +121,14 @@ enum clk_id {
|
|||
tegra_clk_i2s4_sync,
|
||||
tegra_clk_isp,
|
||||
tegra_clk_isp_8,
|
||||
tegra_clk_isp_9,
|
||||
tegra_clk_ispb,
|
||||
tegra_clk_kbc,
|
||||
tegra_clk_kfuse,
|
||||
tegra_clk_la,
|
||||
tegra_clk_maud,
|
||||
tegra_clk_mipi,
|
||||
tegra_clk_mipibif,
|
||||
tegra_clk_mipi_cal,
|
||||
tegra_clk_mpe,
|
||||
tegra_clk_mselect,
|
||||
|
@ -124,15 +138,24 @@ enum clk_id {
|
|||
tegra_clk_ndspeed,
|
||||
tegra_clk_ndspeed_8,
|
||||
tegra_clk_nor,
|
||||
tegra_clk_nvdec,
|
||||
tegra_clk_nvenc,
|
||||
tegra_clk_nvjpg,
|
||||
tegra_clk_owr,
|
||||
tegra_clk_owr_8,
|
||||
tegra_clk_pcie,
|
||||
tegra_clk_pclk,
|
||||
tegra_clk_pll_a,
|
||||
tegra_clk_pll_a_out0,
|
||||
tegra_clk_pll_a1,
|
||||
tegra_clk_pll_c,
|
||||
tegra_clk_pll_c2,
|
||||
tegra_clk_pll_c3,
|
||||
tegra_clk_pll_c4,
|
||||
tegra_clk_pll_c4_out0,
|
||||
tegra_clk_pll_c4_out1,
|
||||
tegra_clk_pll_c4_out2,
|
||||
tegra_clk_pll_c4_out3,
|
||||
tegra_clk_pll_c_out1,
|
||||
tegra_clk_pll_d,
|
||||
tegra_clk_pll_d2,
|
||||
|
@ -140,19 +163,29 @@ enum clk_id {
|
|||
tegra_clk_pll_d_out0,
|
||||
tegra_clk_pll_dp,
|
||||
tegra_clk_pll_e_out0,
|
||||
tegra_clk_pll_g_ref,
|
||||
tegra_clk_pll_m,
|
||||
tegra_clk_pll_m_out1,
|
||||
tegra_clk_pll_mb,
|
||||
tegra_clk_pll_p,
|
||||
tegra_clk_pll_p_out1,
|
||||
tegra_clk_pll_p_out2,
|
||||
tegra_clk_pll_p_out2_int,
|
||||
tegra_clk_pll_p_out3,
|
||||
tegra_clk_pll_p_out4,
|
||||
tegra_clk_pll_p_out4_cpu,
|
||||
tegra_clk_pll_p_out5,
|
||||
tegra_clk_pll_p_out_hsio,
|
||||
tegra_clk_pll_p_out_xusb,
|
||||
tegra_clk_pll_p_out_cpu,
|
||||
tegra_clk_pll_p_out_adsp,
|
||||
tegra_clk_pll_ref,
|
||||
tegra_clk_pll_re_out,
|
||||
tegra_clk_pll_re_vco,
|
||||
tegra_clk_pll_u,
|
||||
tegra_clk_pll_u_out,
|
||||
tegra_clk_pll_u_out1,
|
||||
tegra_clk_pll_u_out2,
|
||||
tegra_clk_pll_u_12m,
|
||||
tegra_clk_pll_u_480m,
|
||||
tegra_clk_pll_u_48m,
|
||||
|
@ -160,53 +193,80 @@ enum clk_id {
|
|||
tegra_clk_pll_x,
|
||||
tegra_clk_pll_x_out0,
|
||||
tegra_clk_pwm,
|
||||
tegra_clk_qspi,
|
||||
tegra_clk_rtc,
|
||||
tegra_clk_sata,
|
||||
tegra_clk_sata_8,
|
||||
tegra_clk_sata_cold,
|
||||
tegra_clk_sata_oob,
|
||||
tegra_clk_sata_oob_8,
|
||||
tegra_clk_sbc1,
|
||||
tegra_clk_sbc1_8,
|
||||
tegra_clk_sbc1_9,
|
||||
tegra_clk_sbc2,
|
||||
tegra_clk_sbc2_8,
|
||||
tegra_clk_sbc2_9,
|
||||
tegra_clk_sbc3,
|
||||
tegra_clk_sbc3_8,
|
||||
tegra_clk_sbc3_9,
|
||||
tegra_clk_sbc4,
|
||||
tegra_clk_sbc4_8,
|
||||
tegra_clk_sbc4_9,
|
||||
tegra_clk_sbc5,
|
||||
tegra_clk_sbc5_8,
|
||||
tegra_clk_sbc6,
|
||||
tegra_clk_sbc6_8,
|
||||
tegra_clk_sclk,
|
||||
tegra_clk_sdmmc_legacy,
|
||||
tegra_clk_sdmmc1,
|
||||
tegra_clk_sdmmc1_8,
|
||||
tegra_clk_sdmmc1_9,
|
||||
tegra_clk_sdmmc2,
|
||||
tegra_clk_sdmmc2_8,
|
||||
tegra_clk_sdmmc2_9,
|
||||
tegra_clk_sdmmc3,
|
||||
tegra_clk_sdmmc3_8,
|
||||
tegra_clk_sdmmc3_9,
|
||||
tegra_clk_sdmmc4,
|
||||
tegra_clk_sdmmc4_8,
|
||||
tegra_clk_sdmmc4_9,
|
||||
tegra_clk_se,
|
||||
tegra_clk_soc_therm,
|
||||
tegra_clk_soc_therm_8,
|
||||
tegra_clk_sor0,
|
||||
tegra_clk_sor0_lvds,
|
||||
tegra_clk_sor1,
|
||||
tegra_clk_sor1_brick,
|
||||
tegra_clk_sor1_src,
|
||||
tegra_clk_spdif,
|
||||
tegra_clk_spdif_2x,
|
||||
tegra_clk_spdif_in,
|
||||
tegra_clk_spdif_in_8,
|
||||
tegra_clk_spdif_in_sync,
|
||||
tegra_clk_spdif_mux,
|
||||
tegra_clk_spdif_out,
|
||||
tegra_clk_timer,
|
||||
tegra_clk_trace,
|
||||
tegra_clk_tsec,
|
||||
tegra_clk_tsec_8,
|
||||
tegra_clk_tsecb,
|
||||
tegra_clk_tsensor,
|
||||
tegra_clk_tvdac,
|
||||
tegra_clk_tvo,
|
||||
tegra_clk_uarta,
|
||||
tegra_clk_uarta_8,
|
||||
tegra_clk_uartb,
|
||||
tegra_clk_uartb_8,
|
||||
tegra_clk_uartc,
|
||||
tegra_clk_uartc_8,
|
||||
tegra_clk_uartd,
|
||||
tegra_clk_uartd_8,
|
||||
tegra_clk_uarte,
|
||||
tegra_clk_uarte_8,
|
||||
tegra_clk_uartape,
|
||||
tegra_clk_usb2,
|
||||
tegra_clk_usb2_hsic_trk,
|
||||
tegra_clk_usb2_trk,
|
||||
tegra_clk_usb3,
|
||||
tegra_clk_usbd,
|
||||
tegra_clk_vcp,
|
||||
|
@ -216,22 +276,35 @@ enum clk_id {
|
|||
tegra_clk_vi,
|
||||
tegra_clk_vi_8,
|
||||
tegra_clk_vi_9,
|
||||
tegra_clk_vi_10,
|
||||
tegra_clk_vi_i2c,
|
||||
tegra_clk_vic03,
|
||||
tegra_clk_vic03_8,
|
||||
tegra_clk_vim2_clk,
|
||||
tegra_clk_vimclk_sync,
|
||||
tegra_clk_vi_sensor,
|
||||
tegra_clk_vi_sensor2,
|
||||
tegra_clk_vi_sensor_8,
|
||||
tegra_clk_vi_sensor_9,
|
||||
tegra_clk_vi_sensor2,
|
||||
tegra_clk_vi_sensor2_8,
|
||||
tegra_clk_xusb_dev,
|
||||
tegra_clk_xusb_dev_src,
|
||||
tegra_clk_xusb_dev_src_8,
|
||||
tegra_clk_xusb_falcon_src,
|
||||
tegra_clk_xusb_falcon_src_8,
|
||||
tegra_clk_xusb_fs_src,
|
||||
tegra_clk_xusb_gate,
|
||||
tegra_clk_xusb_host,
|
||||
tegra_clk_xusb_host_src,
|
||||
tegra_clk_xusb_host_src_8,
|
||||
tegra_clk_xusb_hs_src,
|
||||
tegra_clk_xusb_hs_src_4,
|
||||
tegra_clk_xusb_ss,
|
||||
tegra_clk_xusb_ss_src,
|
||||
tegra_clk_xusb_ss_src_8,
|
||||
tegra_clk_xusb_ss_div2,
|
||||
tegra_clk_xusb_ssp_src,
|
||||
tegra_clk_sclk_mux,
|
||||
tegra_clk_max,
|
||||
};
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -124,6 +124,20 @@
|
|||
#define CLK_SOURCE_HDMI_AUDIO 0x668
|
||||
#define CLK_SOURCE_VIC03 0x678
|
||||
#define CLK_SOURCE_CLK72MHZ 0x66c
|
||||
#define CLK_SOURCE_DBGAPB 0x718
|
||||
#define CLK_SOURCE_NVENC 0x6a0
|
||||
#define CLK_SOURCE_NVDEC 0x698
|
||||
#define CLK_SOURCE_NVJPG 0x69c
|
||||
#define CLK_SOURCE_APE 0x6c0
|
||||
#define CLK_SOURCE_SOR1 0x410
|
||||
#define CLK_SOURCE_SDMMC_LEGACY 0x694
|
||||
#define CLK_SOURCE_QSPI 0x6c4
|
||||
#define CLK_SOURCE_VI_I2C 0x6c8
|
||||
#define CLK_SOURCE_MIPIBIF 0x660
|
||||
#define CLK_SOURCE_UARTAPE 0x710
|
||||
#define CLK_SOURCE_TSECB 0x6d8
|
||||
#define CLK_SOURCE_MAUD 0x6d4
|
||||
#define CLK_SOURCE_USB2_HSIC_TRK 0x6cc
|
||||
|
||||
#define MASK(x) (BIT(x) - 1)
|
||||
|
||||
|
@ -182,6 +196,13 @@
|
|||
TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
|
||||
_parents##_idx, 0, NULL)
|
||||
|
||||
#define UART8(_name, _parents, _offset,\
|
||||
_clk_num, _clk_id) \
|
||||
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||
29, MASK(3), 0, 0, 16, 1, TEGRA_DIVIDER_UART| \
|
||||
TEGRA_DIVIDER_ROUND_UP, _clk_num, 0, _clk_id,\
|
||||
_parents##_idx, 0, NULL)
|
||||
|
||||
#define I2C(_name, _parents, _offset,\
|
||||
_clk_num, _clk_id) \
|
||||
TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
|
||||
|
@ -221,8 +242,21 @@
|
|||
.flags = _flags \
|
||||
}
|
||||
|
||||
#define DIV8(_name, _parent_name, _offset, _clk_id, _flags) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
.clk_id = _clk_id, \
|
||||
.p.parent_name = _parent_name, \
|
||||
.periph = TEGRA_CLK_PERIPH(0, 0, 0, 0, 8, 1, \
|
||||
TEGRA_DIVIDER_ROUND_UP, 0, 0, \
|
||||
NULL, NULL), \
|
||||
.offset = _offset, \
|
||||
.flags = _flags, \
|
||||
}
|
||||
|
||||
#define PLLP_BASE 0xa0
|
||||
#define PLLP_MISC 0xac
|
||||
#define PLLP_MISC1 0x680
|
||||
#define PLLP_OUTA 0xa4
|
||||
#define PLLP_OUTB 0xa8
|
||||
#define PLLP_OUTC 0x67c
|
||||
|
@ -234,6 +268,7 @@ static DEFINE_SPINLOCK(PLLP_OUTA_lock);
|
|||
static DEFINE_SPINLOCK(PLLP_OUTB_lock);
|
||||
static DEFINE_SPINLOCK(PLLP_OUTC_lock);
|
||||
static DEFINE_SPINLOCK(sor0_lock);
|
||||
static DEFINE_SPINLOCK(sor1_lock);
|
||||
|
||||
#define MUX_I2S_SPDIF(_id) \
|
||||
static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
|
||||
|
@ -285,6 +320,68 @@ static u32 mux_pllp_clkm_idx[] = {
|
|||
[0] = 0, [1] = 3,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_clkm_2[] = {
|
||||
"pll_p", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_clkm_2_idx[] = {
|
||||
[0] = 2, [1] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_pllc2_c_c3_pllp_plla1_clkm[] = {
|
||||
"pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a1", "clk_m"
|
||||
};
|
||||
static u32 mux_pllc2_c_c3_pllp_plla1_clkm_idx[] = {
|
||||
[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 6, [5] = 7,
|
||||
};
|
||||
|
||||
static const char *
|
||||
mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0[] = {
|
||||
"pll_c4_out1", "pll_c", "pll_c4_out2", "pll_p", "clk_m",
|
||||
"pll_a_out0", "pll_c4_out0"
|
||||
};
|
||||
static u32 mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_pllc_pllp_plla[] = {
|
||||
"pll_c", "pll_p", "pll_a_out0"
|
||||
};
|
||||
static u32 mux_pllc_pllp_plla_idx[] = {
|
||||
[0] = 1, [1] = 2, [2] = 3,
|
||||
};
|
||||
|
||||
static const char *mux_clkm_pllc_pllp_plla[] = {
|
||||
"clk_m", "pll_c", "pll_p", "pll_a_out0"
|
||||
};
|
||||
#define mux_clkm_pllc_pllp_plla_idx NULL
|
||||
|
||||
static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm[] = {
|
||||
"pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m"
|
||||
};
|
||||
static u32 mux_pllc_pllp_plla1_pllc2_c3_clkm_idx[] = {
|
||||
[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_pllc2_c_c3_pllp_clkm_plla1_pllc4[] = {
|
||||
"pll_c2", "pll_c", "pll_c3", "pll_p", "clk_m", "pll_a1", "pll_c4_out0",
|
||||
};
|
||||
static u32 mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx[] = {
|
||||
[0] = 1, [1] = 2, [2] = 3, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4[] = {
|
||||
"pll_c", "pll_p", "pll_a1", "pll_c2", "pll_c3", "clk_m", "pll_c4_out0",
|
||||
};
|
||||
#define mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4_idx \
|
||||
mux_pllc2_c_c3_pllp_clkm_plla1_pllc4_idx
|
||||
|
||||
static const char *
|
||||
mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm[] = {
|
||||
"pll_a_out0", "pll_c4_out0", "pll_c", "pll_c4_out1", "pll_p",
|
||||
"pll_c4_out2", "clk_m"
|
||||
};
|
||||
#define mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm_idx NULL
|
||||
|
||||
static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
|
||||
"pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
|
||||
};
|
||||
|
@ -302,12 +399,93 @@ static const char *mux_pllm_pllc_pllp_plla[] = {
|
|||
#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
|
||||
|
||||
static const char *mux_pllp_pllc_clkm[] = {
|
||||
"pll_p", "pll_c", "pll_m"
|
||||
"pll_p", "pll_c", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_pllc_clkm_idx[] = {
|
||||
[0] = 0, [1] = 1, [2] = 3,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllc_clkm_1[] = {
|
||||
"pll_p", "pll_c", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_pllc_clkm_1_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 5,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllc_plla_clkm[] = {
|
||||
"pll_p", "pll_c", "pll_a_out0", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_pllc_plla_clkm_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 4, [3] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2[] = {
|
||||
"pll_p", "pll_c", "pll_c4_out0", "pll_c4_out1", "clk_m", "pll_c4_out2"
|
||||
};
|
||||
static u32 mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 3, [3] = 5, [4] = 6, [5] = 7,
|
||||
};
|
||||
|
||||
static const char *
|
||||
mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
|
||||
"pll_p", "pll_c_out1", "pll_c", "pll_c4_out2", "pll_c4_out1",
|
||||
"clk_m", "pll_c4_out0"
|
||||
};
|
||||
static u32
|
||||
mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = {
|
||||
[0] = 0, [1] = 1, [2] = 2, [3] = 4, [4] = 5, [5] = 6, [6] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0[] = {
|
||||
"pll_p", "pll_c4_out2", "pll_c4_out1", "clk_m", "pll_c4_out0"
|
||||
};
|
||||
static u32 mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0_idx[] = {
|
||||
[0] = 0, [1] = 3, [2] = 4, [3] = 6, [4] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_clkm_pllc4_out2_out1_out0_lj[] = {
|
||||
"pll_p",
|
||||
"pll_c4_out2", "pll_c4_out0", /* LJ input */
|
||||
"pll_c4_out2", "pll_c4_out1",
|
||||
"pll_c4_out1", /* LJ input */
|
||||
"clk_m", "pll_c4_out0"
|
||||
};
|
||||
#define mux_pllp_clkm_pllc4_out2_out1_out0_lj_idx NULL
|
||||
|
||||
static const char *mux_pllp_pllc2_c_c3_clkm[] = {
|
||||
"pll_p", "pll_c2", "pll_c", "pll_c3", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_pllc2_c_c3_clkm_idx[] = {
|
||||
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_clkm_clk32_plle[] = {
|
||||
"pll_p", "clk_m", "clk_32k", "pll_e"
|
||||
};
|
||||
static u32 mux_pllp_clkm_clk32_plle_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 4, [3] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllp_out3_clkm_clk32k_plla[] = {
|
||||
"pll_p", "pll_p_out3", "clk_m", "clk_32k", "pll_a_out0"
|
||||
};
|
||||
#define mux_pllp_pllp_out3_clkm_clk32k_plla_idx NULL
|
||||
|
||||
static const char *mux_pllp_out3_clkm_pllp_pllc4[] = {
|
||||
"pll_p_out3", "clk_m", "pll_p", "pll_c4_out0", "pll_c4_out1",
|
||||
"pll_c4_out2"
|
||||
};
|
||||
static u32 mux_pllp_out3_clkm_pllp_pllc4_idx[] = {
|
||||
[0] = 0, [1] = 3, [2] = 4, [3] = 5, [4] = 6, [5] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_clkm_pllp_pllre[] = {
|
||||
"clk_m", "pll_p_out_xusb", "pll_re_out"
|
||||
};
|
||||
static u32 mux_clkm_pllp_pllre_idx[] = {
|
||||
[0] = 0, [1] = 1, [2] = 5,
|
||||
};
|
||||
|
||||
static const char *mux_pllp_pllc_clkm_clk32[] = {
|
||||
"pll_p", "pll_c", "clk_m", "clk_32k"
|
||||
};
|
||||
|
@ -332,6 +510,11 @@ static u32 mux_clkm_48M_pllp_480M_idx[] = {
|
|||
[0] = 0, [1] = 2, [2] = 4, [3] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_clkm_pllre_clk32_480M[] = {
|
||||
"clk_m", "pll_re_out", "clk_32k", "pll_u_480M"
|
||||
};
|
||||
#define mux_clkm_pllre_clk32_480M_idx NULL
|
||||
|
||||
static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
|
||||
"clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
|
||||
};
|
||||
|
@ -339,10 +522,27 @@ static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
|
|||
[0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
|
||||
};
|
||||
|
||||
static const char *mux_ss_60M[] = {
|
||||
static const char *mux_pllp_out3_pllp_pllc_clkm[] = {
|
||||
"pll_p_out3", "pll_p", "pll_c", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_out3_pllp_pllc_clkm_idx[] = {
|
||||
[0] = 0, [1] = 1, [2] = 2, [3] = 6,
|
||||
};
|
||||
|
||||
static const char *mux_ss_div2_60M[] = {
|
||||
"xusb_ss_div2", "pll_u_60M"
|
||||
};
|
||||
#define mux_ss_60M_idx NULL
|
||||
#define mux_ss_div2_60M_idx NULL
|
||||
|
||||
static const char *mux_ss_div2_60M_ss[] = {
|
||||
"xusb_ss_div2", "pll_u_60M", "xusb_ss_src"
|
||||
};
|
||||
#define mux_ss_div2_60M_ss_idx NULL
|
||||
|
||||
static const char *mux_ss_clkm[] = {
|
||||
"xusb_ss_src", "clk_m"
|
||||
};
|
||||
#define mux_ss_clkm_idx NULL
|
||||
|
||||
static const char *mux_d_audio_clk[] = {
|
||||
"pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
|
||||
|
@ -386,6 +586,32 @@ static u32 mux_pllm_pllc2_c_c3_pllp_plla_pllc4_idx[] = {
|
|||
[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, [6] = 7,
|
||||
};
|
||||
|
||||
/* SOR1 mux'es */
|
||||
static const char *mux_pllp_plld_plld2_clkm[] = {
|
||||
"pll_p", "pll_d_out0", "pll_d2_out0", "clk_m"
|
||||
};
|
||||
static u32 mux_pllp_plld_plld2_clkm_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 5, [3] = 6
|
||||
};
|
||||
|
||||
static const char *mux_plldp_sor1_src[] = {
|
||||
"pll_dp", "clk_sor1_src"
|
||||
};
|
||||
#define mux_plldp_sor1_src_idx NULL
|
||||
|
||||
static const char *mux_clkm_sor1_brick_sor1_src[] = {
|
||||
"clk_m", "sor1_brick", "sor1_src", "sor1_brick"
|
||||
};
|
||||
#define mux_clkm_sor1_brick_sor1_src_idx NULL
|
||||
|
||||
static const char *mux_pllp_pllre_clkm[] = {
|
||||
"pll_p", "pll_re_out1", "clk_m"
|
||||
};
|
||||
|
||||
static u32 mux_pllp_pllre_clkm_idx[] = {
|
||||
[0] = 0, [1] = 2, [2] = 3,
|
||||
};
|
||||
|
||||
static const char *mux_clkm_plldp_sor0lvds[] = {
|
||||
"clk_m", "pll_dp", "sor0_lvds",
|
||||
};
|
||||
|
@ -401,6 +627,7 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
I2C("i2c3", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, tegra_clk_i2c3),
|
||||
I2C("i2c4", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, tegra_clk_i2c4),
|
||||
I2C("i2c5", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, tegra_clk_i2c5),
|
||||
I2C("i2c6", mux_pllp_clkm, CLK_SOURCE_I2C6, 166, tegra_clk_i2c6),
|
||||
INT("vde", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde),
|
||||
INT("vi", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi),
|
||||
INT("epp", mux_pllm_pllc_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp),
|
||||
|
@ -411,14 +638,19 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
INT8("vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, 0, tegra_clk_vde_8),
|
||||
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_8),
|
||||
INT8("vi", mux_pllm_pllc2_c_c3_pllp_plla_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_9),
|
||||
INT8("vi", mux_pllc2_c_c3_pllp_clkm_plla1_pllc4, CLK_SOURCE_VI, 20, 0, tegra_clk_vi_10),
|
||||
INT8("epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, 0, tegra_clk_epp_8),
|
||||
INT8("msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, TEGRA_PERIPH_WAR_1005168, tegra_clk_msenc),
|
||||
INT8("tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec),
|
||||
INT("tsec", mux_pllp_pllc_clkm, CLK_SOURCE_TSEC, 83, 0, tegra_clk_tsec_8),
|
||||
INT8("host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_8),
|
||||
INT8("host1x", mux_pllc4_out1_pllc_pllc4_out2_pllp_clkm_plla_pllc4_out0, CLK_SOURCE_HOST1X, 28, 0, tegra_clk_host1x_9),
|
||||
INT8("se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
|
||||
INT8("se", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_SE, 127, TEGRA_PERIPH_ON_APB, tegra_clk_se),
|
||||
INT8("2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, 0, tegra_clk_gr2d_8),
|
||||
INT8("3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, 0, tegra_clk_gr3d_8),
|
||||
INT8("vic03", mux_pllm_pllc_pllp_plla_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03),
|
||||
INT8("vic03", mux_pllc_pllp_plla1_pllc2_c3_clkm, CLK_SOURCE_VIC03, 178, 0, tegra_clk_vic03_8),
|
||||
INT_FLAGS("mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, 0, tegra_clk_mselect, CLK_IGNORE_UNUSED),
|
||||
MUX("i2s0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, TEGRA_PERIPH_ON_APB, tegra_clk_i2s0),
|
||||
MUX("i2s1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, TEGRA_PERIPH_ON_APB, tegra_clk_i2s1),
|
||||
|
@ -427,22 +659,31 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX("i2s4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, TEGRA_PERIPH_ON_APB, tegra_clk_i2s4),
|
||||
MUX("spdif_out", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_out),
|
||||
MUX("spdif_in", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in),
|
||||
MUX8("spdif_in", mux_pllp_pllc_clkm_1, CLK_SOURCE_SPDIF_IN, 10, TEGRA_PERIPH_ON_APB, tegra_clk_spdif_in_8),
|
||||
MUX("pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, TEGRA_PERIPH_ON_APB, tegra_clk_pwm),
|
||||
MUX("adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, TEGRA_PERIPH_ON_APB, tegra_clk_adx),
|
||||
MUX("amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, TEGRA_PERIPH_ON_APB, tegra_clk_amx),
|
||||
MUX("hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda),
|
||||
MUX("hda", mux_pllp_pllc_clkm, CLK_SOURCE_HDA, 125, TEGRA_PERIPH_ON_APB, tegra_clk_hda_8),
|
||||
MUX("hda2codec_2x", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x),
|
||||
MUX8("hda2codec_2x", mux_pllp_pllc_plla_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, TEGRA_PERIPH_ON_APB, tegra_clk_hda2codec_2x_8),
|
||||
MUX("vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, TEGRA_PERIPH_ON_APB, tegra_clk_vfir),
|
||||
MUX("sdmmc1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1),
|
||||
MUX("sdmmc2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2),
|
||||
MUX("sdmmc3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3),
|
||||
MUX("sdmmc4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4),
|
||||
MUX8("sdmmc1", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_9),
|
||||
MUX8("sdmmc2", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_9),
|
||||
MUX8("sdmmc3", mux_pllp_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_9),
|
||||
MUX8("sdmmc4", mux_pllp_clkm_pllc4_out2_out1_out0_lj, CLK_SOURCE_SDMMC4, 15, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc4_9),
|
||||
MUX("la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, TEGRA_PERIPH_ON_APB, tegra_clk_la),
|
||||
MUX("trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, TEGRA_PERIPH_ON_APB, tegra_clk_trace),
|
||||
MUX("owr", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr),
|
||||
MUX("owr", mux_pllp_pllc_clkm, CLK_SOURCE_OWR, 71, TEGRA_PERIPH_ON_APB, tegra_clk_owr_8),
|
||||
MUX("nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, 0, tegra_clk_nor),
|
||||
MUX("mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, TEGRA_PERIPH_ON_APB, tegra_clk_mipi),
|
||||
MUX("vi_sensor", mux_pllm_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor),
|
||||
MUX("vi_sensor", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_9),
|
||||
MUX("cilab", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, 0, tegra_clk_cilab),
|
||||
MUX("cilcd", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, 0, tegra_clk_cilcd),
|
||||
MUX("cile", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, 0, tegra_clk_cile),
|
||||
|
@ -465,10 +706,13 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX("ndflash", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash),
|
||||
MUX("ndspeed", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed),
|
||||
MUX("sata_oob", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob),
|
||||
MUX("sata_oob", mux_pllp_pllc_clkm, CLK_SOURCE_SATA_OOB, 123, TEGRA_PERIPH_ON_APB, tegra_clk_sata_oob_8),
|
||||
MUX("sata", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata),
|
||||
MUX("sata", mux_pllp_pllc_clkm, CLK_SOURCE_SATA, 124, TEGRA_PERIPH_ON_APB, tegra_clk_sata_8),
|
||||
MUX("adx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX1, 180, TEGRA_PERIPH_ON_APB, tegra_clk_adx1),
|
||||
MUX("amx1", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX1, 185, TEGRA_PERIPH_ON_APB, tegra_clk_amx1),
|
||||
MUX("vi_sensor2", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2),
|
||||
MUX("vi_sensor2", mux_pllc_pllp_plla, CLK_SOURCE_VI_SENSOR2, 165, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor2_8),
|
||||
MUX8("sdmmc1", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC1, 14, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc1_8),
|
||||
MUX8("sdmmc2", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC2, 9, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc2_8),
|
||||
MUX8("sdmmc3", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SDMMC3, 69, TEGRA_PERIPH_ON_APB, tegra_clk_sdmmc3_8),
|
||||
|
@ -479,6 +723,10 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX8("sbc4", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_8),
|
||||
MUX8("sbc5", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC5, 104, TEGRA_PERIPH_ON_APB, tegra_clk_sbc5_8),
|
||||
MUX8("sbc6", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SBC6, 105, TEGRA_PERIPH_ON_APB, tegra_clk_sbc6_8),
|
||||
MUX("sbc1", mux_pllp_pllc_clkm, CLK_SOURCE_SBC1, 41, TEGRA_PERIPH_ON_APB, tegra_clk_sbc1_9),
|
||||
MUX("sbc2", mux_pllp_pllc_clkm, CLK_SOURCE_SBC2, 44, TEGRA_PERIPH_ON_APB, tegra_clk_sbc2_9),
|
||||
MUX("sbc3", mux_pllp_pllc_clkm, CLK_SOURCE_SBC3, 46, TEGRA_PERIPH_ON_APB, tegra_clk_sbc3_9),
|
||||
MUX("sbc4", mux_pllp_pllc_clkm, CLK_SOURCE_SBC4, 68, TEGRA_PERIPH_ON_APB, tegra_clk_sbc4_9),
|
||||
MUX8("ndflash", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, TEGRA_PERIPH_ON_APB, tegra_clk_ndflash_8),
|
||||
MUX8("ndspeed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, TEGRA_PERIPH_ON_APB, tegra_clk_ndspeed_8),
|
||||
MUX8("hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, 0, tegra_clk_hdmi),
|
||||
|
@ -486,27 +734,59 @@ static struct tegra_periph_init_data periph_clks[] = {
|
|||
MUX8("extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, 0, tegra_clk_extern2),
|
||||
MUX8("extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, 0, tegra_clk_extern3),
|
||||
MUX8("soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm),
|
||||
MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
|
||||
MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
|
||||
MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
|
||||
MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9),
|
||||
MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy),
|
||||
MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149, 0, tegra_clk_entropy_8),
|
||||
MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
|
||||
MUX8("clk72mhz", mux_pllp3_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz),
|
||||
MUX8("clk72mhz", mux_pllp_out3_pllp_pllc_clkm, CLK_SOURCE_CLK72MHZ, 177, TEGRA_PERIPH_NO_RESET, tegra_clk_clk72Mhz_8),
|
||||
MUX8_NOGATE_LOCK("sor0_lvds", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_SOR0, tegra_clk_sor0_lvds, &sor0_lock),
|
||||
MUX_FLAGS("csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite, CLK_IGNORE_UNUSED),
|
||||
MUX_FLAGS("csite", mux_pllp_pllre_clkm, CLK_SOURCE_CSITE, 73, TEGRA_PERIPH_ON_APB, tegra_clk_csite_8, CLK_IGNORE_UNUSED),
|
||||
NODIV("disp1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1, NULL),
|
||||
NODIV("disp1", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, 0, tegra_clk_disp1_8, NULL),
|
||||
NODIV("disp2", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2, NULL),
|
||||
NODIV("disp2", mux_pllp_plld_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, 0, tegra_clk_disp2_8, NULL),
|
||||
NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock),
|
||||
UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta),
|
||||
UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb),
|
||||
UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc),
|
||||
UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd),
|
||||
UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte),
|
||||
UART8("uarta", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTA, 6, tegra_clk_uarta_8),
|
||||
UART8("uartb", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTB, 7, tegra_clk_uartb_8),
|
||||
UART8("uartc", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTC, 55, tegra_clk_uartc_8),
|
||||
UART8("uartd", mux_pllp_pllc_pllc4_out0_pllc4_out1_clkm_pllc4_out2, CLK_SOURCE_UARTD, 65, tegra_clk_uartd_8),
|
||||
XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src),
|
||||
XUSB("xusb_host_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src_8),
|
||||
XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src),
|
||||
XUSB("xusb_falcon_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src_8),
|
||||
XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src),
|
||||
XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src),
|
||||
NODIV("xusb_hs_src", mux_ss_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL),
|
||||
XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src_8),
|
||||
NODIV("xusb_hs_src", mux_ss_div2_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL),
|
||||
NODIV("xusb_hs_src", mux_ss_div2_60M_ss, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(2), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src_4, NULL),
|
||||
NODIV("xusb_ssp_src", mux_ss_clkm, CLK_SOURCE_XUSB_SS_SRC, 24, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ssp_src, NULL),
|
||||
XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src),
|
||||
XUSB("xusb_dev_src", mux_clkm_pllp_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src_8),
|
||||
MUX8("dbgapb", mux_pllp_clkm_2, CLK_SOURCE_DBGAPB, 185, TEGRA_PERIPH_NO_RESET, tegra_clk_dbgapb),
|
||||
MUX8("msenc", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVENC, 219, 0, tegra_clk_nvenc),
|
||||
MUX8("nvdec", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVDEC, 194, 0, tegra_clk_nvdec),
|
||||
MUX8("nvjpg", mux_pllc2_c_c3_pllp_plla1_clkm, CLK_SOURCE_NVJPG, 195, 0, tegra_clk_nvjpg),
|
||||
MUX8("ape", mux_plla_pllc4_out0_pllc_pllc4_out1_pllp_pllc4_out2_clkm, CLK_SOURCE_APE, 198, TEGRA_PERIPH_ON_APB, tegra_clk_ape),
|
||||
MUX8_NOGATE_LOCK("sor1_src", mux_pllp_plld_plld2_clkm, CLK_SOURCE_SOR1, tegra_clk_sor1_src, &sor1_lock),
|
||||
NODIV("sor1_brick", mux_plldp_sor1_src, CLK_SOURCE_SOR1, 14, MASK(1), 183, 0, tegra_clk_sor1_brick, &sor1_lock),
|
||||
NODIV("sor1", mux_clkm_sor1_brick_sor1_src, CLK_SOURCE_SOR1, 15, MASK(1), 183, 0, tegra_clk_sor1, &sor1_lock),
|
||||
MUX8("sdmmc_legacy", mux_pllp_out3_clkm_pllp_pllc4, CLK_SOURCE_SDMMC_LEGACY, 193, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_sdmmc_legacy),
|
||||
MUX8("qspi", mux_pllp_pllc_pllc_out1_pllc4_out2_pllc4_out1_clkm_pllc4_out0, CLK_SOURCE_QSPI, 211, TEGRA_PERIPH_ON_APB, tegra_clk_qspi),
|
||||
MUX("vii2c", mux_pllp_pllc_clkm, CLK_SOURCE_VI_I2C, 208, TEGRA_PERIPH_ON_APB, tegra_clk_vi_i2c),
|
||||
MUX("mipibif", mux_pllp_clkm, CLK_SOURCE_MIPIBIF, 173, TEGRA_PERIPH_ON_APB, tegra_clk_mipibif),
|
||||
MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape),
|
||||
MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb),
|
||||
MUX8("maud", mux_pllp_pllp_out3_clkm_clk32k_plla, CLK_SOURCE_MAUD, 202, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_maud),
|
||||
};
|
||||
|
||||
static struct tegra_periph_init_data gate_clks[] = {
|
||||
|
@ -543,6 +823,16 @@ static struct tegra_periph_init_data gate_clks[] = {
|
|||
GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
|
||||
GATE("dpaux", "clk_m", 181, 0, tegra_clk_dpaux, 0),
|
||||
GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
|
||||
GATE("pllg_ref", "pll_ref", 189, 0, tegra_clk_pll_g_ref, 0),
|
||||
GATE("hsic_trk", "usb2_hsic_trk", 209, TEGRA_PERIPH_NO_RESET, tegra_clk_hsic_trk, 0),
|
||||
GATE("usb2_trk", "usb2_hsic_trk", 210, TEGRA_PERIPH_NO_RESET, tegra_clk_usb2_trk, 0),
|
||||
GATE("xusb_gate", "osc", 143, 0, tegra_clk_xusb_gate, 0),
|
||||
GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0),
|
||||
GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0),
|
||||
};
|
||||
|
||||
static struct tegra_periph_init_data div_clks[] = {
|
||||
DIV8("usb2_hsic_trk", "osc", CLK_SOURCE_USB2_HSIC_TRK, tegra_clk_usb2_hsic_trk, 0),
|
||||
};
|
||||
|
||||
struct pll_out_data {
|
||||
|
@ -633,6 +923,33 @@ static void __init gate_clk_init(void __iomem *clk_base,
|
|||
}
|
||||
}
|
||||
|
||||
static void __init div_clk_init(void __iomem *clk_base,
|
||||
struct tegra_clk *tegra_clks)
|
||||
{
|
||||
int i;
|
||||
struct clk *clk;
|
||||
struct clk **dt_clk;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(div_clks); i++) {
|
||||
struct tegra_periph_init_data *data;
|
||||
|
||||
data = div_clks + i;
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(data->clk_id, tegra_clks);
|
||||
if (!dt_clk)
|
||||
continue;
|
||||
|
||||
clk = tegra_clk_register_divider(data->name,
|
||||
data->p.parent_name, clk_base + data->offset,
|
||||
data->flags, data->periph.divider.flags,
|
||||
data->periph.divider.shift,
|
||||
data->periph.divider.width,
|
||||
data->periph.divider.frac_width,
|
||||
data->periph.divider.lock);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
}
|
||||
|
||||
static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
|
||||
struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *pll_params)
|
||||
|
@ -669,6 +986,51 @@ static void __init init_pllp(void __iomem *clk_base, void __iomem *pmc_base,
|
|||
data->lock);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_cpu,
|
||||
tegra_clks);
|
||||
if (dt_clk) {
|
||||
/*
|
||||
* Tegra210 has control on enabling/disabling PLLP branches to
|
||||
* CPU, register a gate clock "pll_p_out_cpu" for this gating
|
||||
* function and parent "pll_p_out4" to it, so when we are
|
||||
* re-parenting CPU off from "pll_p_out4" the PLLP branching to
|
||||
* CPU can be disabled automatically.
|
||||
*/
|
||||
clk = tegra_clk_register_divider("pll_p_out4_div",
|
||||
"pll_p_out_cpu", clk_base + PLLP_OUTB, 0, 0, 24,
|
||||
8, 1, &PLLP_OUTB_lock);
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out4_cpu, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = tegra_clk_register_pll_out("pll_p_out4",
|
||||
"pll_p_out4_div", clk_base + PLLP_OUTB,
|
||||
17, 16, CLK_IGNORE_UNUSED |
|
||||
CLK_SET_RATE_PARENT, 0,
|
||||
&PLLP_OUTB_lock);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
}
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_hsio, tegra_clks);
|
||||
if (dt_clk) {
|
||||
/* PLLP_OUT_HSIO */
|
||||
clk = clk_register_gate(NULL, "pll_p_out_hsio", "pll_p",
|
||||
CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
|
||||
clk_base + PLLP_MISC1, 29, 0, NULL);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_p_out_xusb, tegra_clks);
|
||||
if (dt_clk) {
|
||||
/* PLLP_OUT_XUSB */
|
||||
clk = clk_register_gate(NULL, "pll_p_out_xusb",
|
||||
"pll_p_out_hsio", CLK_SET_RATE_PARENT |
|
||||
CLK_IGNORE_UNUSED, clk_base + PLLP_MISC1, 28, 0,
|
||||
NULL);
|
||||
clk_register_clkdev(clk, "pll_p_out_xusb", NULL);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
}
|
||||
|
||||
void __init tegra_periph_clk_init(void __iomem *clk_base,
|
||||
|
@ -678,4 +1040,5 @@ void __init tegra_periph_clk_init(void __iomem *clk_base,
|
|||
init_pllp(clk_base, pmc_base, tegra_clks, pll_params);
|
||||
periph_clk_init(clk_base, tegra_clks);
|
||||
gate_clk_init(clk_base, tegra_clks);
|
||||
div_clk_init(clk_base, tegra_clks);
|
||||
}
|
||||
|
|
|
@ -34,9 +34,25 @@
|
|||
#define CCLKLP_BURST_POLICY 0x370
|
||||
#define SCLK_BURST_POLICY 0x028
|
||||
#define SYSTEM_CLK_RATE 0x030
|
||||
#define SCLK_DIVIDER 0x2c
|
||||
|
||||
static DEFINE_SPINLOCK(sysrate_lock);
|
||||
|
||||
enum tegra_super_gen {
|
||||
gen4 = 4,
|
||||
gen5,
|
||||
};
|
||||
|
||||
struct tegra_super_gen_info {
|
||||
enum tegra_super_gen gen;
|
||||
const char **sclk_parents;
|
||||
const char **cclk_g_parents;
|
||||
const char **cclk_lp_parents;
|
||||
int num_sclk_parents;
|
||||
int num_cclk_g_parents;
|
||||
int num_cclk_lp_parents;
|
||||
};
|
||||
|
||||
static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
|
||||
"pll_p", "pll_p_out2", "unused",
|
||||
"clk_32k", "pll_m_out1" };
|
||||
|
@ -51,21 +67,81 @@ static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
|
|||
"pll_p", "pll_p_out4", "unused",
|
||||
"unused", "pll_x", "pll_x_out0" };
|
||||
|
||||
const struct tegra_super_gen_info tegra_super_gen_info_gen4 = {
|
||||
.gen = gen4,
|
||||
.sclk_parents = sclk_parents,
|
||||
.cclk_g_parents = cclk_g_parents,
|
||||
.cclk_lp_parents = cclk_lp_parents,
|
||||
.num_sclk_parents = ARRAY_SIZE(sclk_parents),
|
||||
.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents),
|
||||
.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents),
|
||||
};
|
||||
|
||||
static const char *sclk_parents_gen5[] = { "clk_m", "pll_c_out1", "pll_c4_out3",
|
||||
"pll_p", "pll_p_out2", "pll_c4_out1",
|
||||
"clk_32k", "pll_c4_out2" };
|
||||
|
||||
static const char *cclk_g_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
|
||||
"pll_p", "pll_p_out4", "unused",
|
||||
"unused", "pll_x", "unused", "unused",
|
||||
"unused", "unused", "unused", "unused",
|
||||
"dfllCPU_out" };
|
||||
|
||||
static const char *cclk_lp_parents_gen5[] = { "clk_m", "unused", "clk_32k", "unused",
|
||||
"pll_p", "pll_p_out4", "unused",
|
||||
"unused", "pll_x", "unused", "unused",
|
||||
"unused", "unused", "unused", "unused",
|
||||
"dfllCPU_out" };
|
||||
|
||||
const struct tegra_super_gen_info tegra_super_gen_info_gen5 = {
|
||||
.gen = gen5,
|
||||
.sclk_parents = sclk_parents_gen5,
|
||||
.cclk_g_parents = cclk_g_parents_gen5,
|
||||
.cclk_lp_parents = cclk_lp_parents_gen5,
|
||||
.num_sclk_parents = ARRAY_SIZE(sclk_parents_gen5),
|
||||
.num_cclk_g_parents = ARRAY_SIZE(cclk_g_parents_gen5),
|
||||
.num_cclk_lp_parents = ARRAY_SIZE(cclk_lp_parents_gen5),
|
||||
};
|
||||
|
||||
static void __init tegra_sclk_init(void __iomem *clk_base,
|
||||
struct tegra_clk *tegra_clks)
|
||||
struct tegra_clk *tegra_clks,
|
||||
const struct tegra_super_gen_info *gen_info)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk **dt_clk;
|
||||
|
||||
/* SCLK */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
|
||||
/* SCLK_MUX */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk_mux, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = tegra_clk_register_super_mux("sclk", sclk_parents,
|
||||
ARRAY_SIZE(sclk_parents),
|
||||
clk = tegra_clk_register_super_mux("sclk_mux",
|
||||
gen_info->sclk_parents,
|
||||
gen_info->num_sclk_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + SCLK_BURST_POLICY,
|
||||
0, 4, 0, 0, NULL);
|
||||
*dt_clk = clk;
|
||||
|
||||
|
||||
/* SCLK */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = clk_register_divider(NULL, "sclk", "sclk_mux", 0,
|
||||
clk_base + SCLK_DIVIDER, 0, 8,
|
||||
0, &sysrate_lock);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
} else {
|
||||
/* SCLK */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_sclk, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = tegra_clk_register_super_mux("sclk",
|
||||
gen_info->sclk_parents,
|
||||
gen_info->num_sclk_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + SCLK_BURST_POLICY,
|
||||
0, 4, 0, 0, NULL);
|
||||
*dt_clk = clk;
|
||||
}
|
||||
}
|
||||
|
||||
/* HCLK */
|
||||
|
@ -95,10 +171,11 @@ static void __init tegra_sclk_init(void __iomem *clk_base,
|
|||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
|
||||
void __init tegra_super_clk_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base,
|
||||
struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *params)
|
||||
struct tegra_clk_pll_params *params,
|
||||
const struct tegra_super_gen_info *gen_info)
|
||||
{
|
||||
struct clk *clk;
|
||||
struct clk **dt_clk;
|
||||
|
@ -106,28 +183,50 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
|
|||
/* CCLKG */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_g, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
|
||||
ARRAY_SIZE(cclk_g_parents),
|
||||
if (gen_info->gen == gen5) {
|
||||
clk = tegra_clk_register_super_mux("cclk_g",
|
||||
gen_info->cclk_g_parents,
|
||||
gen_info->num_cclk_g_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLKG_BURST_POLICY,
|
||||
0, 4, 8, 0, NULL);
|
||||
} else {
|
||||
clk = tegra_clk_register_super_mux("cclk_g",
|
||||
gen_info->cclk_g_parents,
|
||||
gen_info->num_cclk_g_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLKG_BURST_POLICY,
|
||||
0, 4, 0, 0, NULL);
|
||||
}
|
||||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
/* CCLKLP */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_cclk_lp, tegra_clks);
|
||||
if (dt_clk) {
|
||||
clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
|
||||
ARRAY_SIZE(cclk_lp_parents),
|
||||
if (gen_info->gen == gen5) {
|
||||
clk = tegra_clk_register_super_mux("cclk_lp",
|
||||
gen_info->cclk_lp_parents,
|
||||
gen_info->num_cclk_lp_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLKLP_BURST_POLICY,
|
||||
0, 4, 8, 0, NULL);
|
||||
} else {
|
||||
clk = tegra_clk_register_super_mux("cclk_lp",
|
||||
gen_info->cclk_lp_parents,
|
||||
gen_info->num_cclk_lp_parents,
|
||||
CLK_SET_RATE_PARENT,
|
||||
clk_base + CCLKLP_BURST_POLICY,
|
||||
TEGRA_DIVIDER_2, 4, 8, 9, NULL);
|
||||
}
|
||||
*dt_clk = clk;
|
||||
}
|
||||
|
||||
tegra_sclk_init(clk_base, tegra_clks);
|
||||
tegra_sclk_init(clk_base, tegra_clks, gen_info);
|
||||
|
||||
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || defined(CONFIG_ARCH_TEGRA_124_SOC)
|
||||
#if defined(CONFIG_ARCH_TEGRA_114_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_124_SOC) || \
|
||||
defined(CONFIG_ARCH_TEGRA_210_SOC)
|
||||
/* PLLX */
|
||||
dt_clk = tegra_lookup_dt_id(tegra_clk_pll_x, tegra_clks);
|
||||
if (!dt_clk)
|
||||
|
@ -148,3 +247,20 @@ void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
|
|||
#endif
|
||||
}
|
||||
|
||||
void __init tegra_super_clk_gen4_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base,
|
||||
struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *params)
|
||||
{
|
||||
tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
|
||||
&tegra_super_gen_info_gen4);
|
||||
}
|
||||
|
||||
void __init tegra_super_clk_gen5_init(void __iomem *clk_base,
|
||||
void __iomem *pmc_base,
|
||||
struct tegra_clk *tegra_clks,
|
||||
struct tegra_clk_pll_params *params)
|
||||
{
|
||||
tegra_super_clk_init(clk_base, pmc_base, tegra_clks, params,
|
||||
&tegra_super_gen_info_gen5);
|
||||
}
|
||||
|
|
|
@ -182,7 +182,7 @@ static struct div_nmp pllxc_nmp = {
|
|||
.divp_width = 4,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllxc_p[] = {
|
||||
static const struct pdiv_map pllxc_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
|
@ -202,12 +202,12 @@ static struct pdiv_map pllxc_p[] = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
|
||||
{ 12000000, 624000000, 104, 0, 2},
|
||||
{ 12000000, 600000000, 100, 0, 2},
|
||||
{ 13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 624000000, 104, 1, 2, 0 },
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -232,7 +232,7 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.pdiv_tohw = pllxc_p,
|
||||
.div_nmp = &pllxc_nmp,
|
||||
.freq_table = pll_c_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct div_nmp pllcx_nmp = {
|
||||
|
@ -244,7 +244,7 @@ static struct div_nmp pllcx_nmp = {
|
|||
.divp_width = 3,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllc_p[] = {
|
||||
static const struct pdiv_map pllc_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 4, .hw_val = 3 },
|
||||
|
@ -254,11 +254,11 @@ static struct pdiv_map pllc_p[] = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
|
||||
{12000000, 600000000, 100, 0, 2},
|
||||
{13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */
|
||||
{16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */
|
||||
{19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */
|
||||
{26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -318,18 +318,18 @@ static struct div_nmp pllm_nmp = {
|
|||
.override_divp_shift = 27,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllm_p[] = {
|
||||
static const struct pdiv_map pllm_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
|
||||
{12000000, 800000000, 66, 0, 1}, /* actual: 792.0 MHz */
|
||||
{13000000, 800000000, 61, 0, 1}, /* actual: 793.0 MHz */
|
||||
{16800000, 800000000, 47, 0, 1}, /* actual: 789.6 MHz */
|
||||
{19200000, 800000000, 41, 0, 1}, /* actual: 787.2 MHz */
|
||||
{26000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */
|
||||
{ 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */
|
||||
{ 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */
|
||||
{ 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */
|
||||
{ 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */
|
||||
{ 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -351,7 +351,8 @@ static struct tegra_clk_pll_params pll_m_params = {
|
|||
.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
|
||||
.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
|
||||
.freq_table = pll_m_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
|
||||
TEGRA_PLL_FIXED,
|
||||
};
|
||||
|
||||
static struct div_nmp pllp_nmp = {
|
||||
|
@ -364,11 +365,11 @@ static struct div_nmp pllp_nmp = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
||||
{12000000, 216000000, 432, 12, 1, 8},
|
||||
{13000000, 216000000, 432, 13, 1, 8},
|
||||
{16800000, 216000000, 360, 14, 1, 8},
|
||||
{19200000, 216000000, 360, 16, 1, 8},
|
||||
{26000000, 216000000, 432, 26, 1, 8},
|
||||
{ 12000000, 216000000, 432, 12, 2, 8 },
|
||||
{ 13000000, 216000000, 432, 13, 2, 8 },
|
||||
{ 16800000, 216000000, 360, 14, 2, 8 },
|
||||
{ 19200000, 216000000, 360, 16, 2, 8 },
|
||||
{ 26000000, 216000000, 432, 26, 2, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -386,18 +387,18 @@ static struct tegra_clk_pll_params pll_p_params = {
|
|||
.lock_delay = 300,
|
||||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_p_freq_table,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.fixed_rate = 408000000,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
|
||||
{9600000, 282240000, 147, 5, 0, 4},
|
||||
{9600000, 368640000, 192, 5, 0, 4},
|
||||
{9600000, 240000000, 200, 8, 0, 8},
|
||||
|
||||
{28800000, 282240000, 245, 25, 0, 8},
|
||||
{28800000, 368640000, 320, 25, 0, 8},
|
||||
{28800000, 240000000, 200, 24, 0, 8},
|
||||
{ 9600000, 282240000, 147, 5, 1, 4 },
|
||||
{ 9600000, 368640000, 192, 5, 1, 4 },
|
||||
{ 9600000, 240000000, 200, 8, 1, 8 },
|
||||
{ 28800000, 282240000, 245, 25, 1, 8 },
|
||||
{ 28800000, 368640000, 320, 25, 1, 8 },
|
||||
{ 28800000, 240000000, 200, 24, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -416,27 +417,25 @@ static struct tegra_clk_pll_params pll_a_params = {
|
|||
.lock_delay = 300,
|
||||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_a_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
|
||||
{12000000, 216000000, 864, 12, 2, 12},
|
||||
{13000000, 216000000, 864, 13, 2, 12},
|
||||
{16800000, 216000000, 720, 14, 2, 12},
|
||||
{19200000, 216000000, 720, 16, 2, 12},
|
||||
{26000000, 216000000, 864, 26, 2, 12},
|
||||
|
||||
{12000000, 594000000, 594, 12, 0, 12},
|
||||
{13000000, 594000000, 594, 13, 0, 12},
|
||||
{16800000, 594000000, 495, 14, 0, 12},
|
||||
{19200000, 594000000, 495, 16, 0, 12},
|
||||
{26000000, 594000000, 594, 26, 0, 12},
|
||||
|
||||
{12000000, 1000000000, 1000, 12, 0, 12},
|
||||
{13000000, 1000000000, 1000, 13, 0, 12},
|
||||
{19200000, 1000000000, 625, 12, 0, 12},
|
||||
{26000000, 1000000000, 1000, 26, 0, 12},
|
||||
|
||||
{ 12000000, 216000000, 864, 12, 4, 12 },
|
||||
{ 13000000, 216000000, 864, 13, 4, 12 },
|
||||
{ 16800000, 216000000, 720, 14, 4, 12 },
|
||||
{ 19200000, 216000000, 720, 16, 4, 12 },
|
||||
{ 26000000, 216000000, 864, 26, 4, 12 },
|
||||
{ 12000000, 594000000, 594, 12, 1, 12 },
|
||||
{ 13000000, 594000000, 594, 13, 1, 12 },
|
||||
{ 16800000, 594000000, 495, 14, 1, 12 },
|
||||
{ 19200000, 594000000, 495, 16, 1, 12 },
|
||||
{ 26000000, 594000000, 594, 26, 1, 12 },
|
||||
{ 12000000, 1000000000, 1000, 12, 1, 12 },
|
||||
{ 13000000, 1000000000, 1000, 13, 1, 12 },
|
||||
{ 19200000, 1000000000, 625, 12, 1, 12 },
|
||||
{ 26000000, 1000000000, 1000, 26, 1, 12 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -455,7 +454,7 @@ static struct tegra_clk_pll_params pll_d_params = {
|
|||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_d_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
|
||||
TEGRA_PLL_USE_LOCK,
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_d2_params = {
|
||||
|
@ -473,10 +472,10 @@ static struct tegra_clk_pll_params pll_d2_params = {
|
|||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_d_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
|
||||
TEGRA_PLL_USE_LOCK,
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllu_p[] = {
|
||||
static const struct pdiv_map pllu_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 1 },
|
||||
{ .pdiv = 2, .hw_val = 0 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
|
@ -492,11 +491,11 @@ static struct div_nmp pllu_nmp = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
||||
{12000000, 480000000, 960, 12, 0, 12},
|
||||
{13000000, 480000000, 960, 13, 0, 12},
|
||||
{16800000, 480000000, 400, 7, 0, 5},
|
||||
{19200000, 480000000, 200, 4, 0, 3},
|
||||
{26000000, 480000000, 960, 26, 0, 12},
|
||||
{ 12000000, 480000000, 960, 12, 2, 12 },
|
||||
{ 13000000, 480000000, 960, 13, 2, 12 },
|
||||
{ 16800000, 480000000, 400, 7, 2, 5 },
|
||||
{ 19200000, 480000000, 200, 4, 2, 3 },
|
||||
{ 26000000, 480000000, 960, 26, 2, 12 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -516,17 +515,16 @@ static struct tegra_clk_pll_params pll_u_params = {
|
|||
.div_nmp = &pllu_nmp,
|
||||
.freq_table = pll_u_freq_table,
|
||||
.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
|
||||
TEGRA_PLL_USE_LOCK,
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
|
||||
/* 1 GHz */
|
||||
{12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */
|
||||
{13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */
|
||||
{16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */
|
||||
{19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */
|
||||
{26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */
|
||||
|
||||
{ 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */
|
||||
{ 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */
|
||||
{ 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */
|
||||
{ 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */
|
||||
{ 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -551,7 +549,7 @@ static struct tegra_clk_pll_params pll_x_params = {
|
|||
.pdiv_tohw = pllxc_p,
|
||||
.div_nmp = &pllxc_nmp,
|
||||
.freq_table = pll_x_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||
|
@ -562,6 +560,25 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
|||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct pdiv_map plle_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
{ .pdiv = 4, .hw_val = 3 },
|
||||
{ .pdiv = 5, .hw_val = 4 },
|
||||
{ .pdiv = 6, .hw_val = 5 },
|
||||
{ .pdiv = 8, .hw_val = 6 },
|
||||
{ .pdiv = 10, .hw_val = 7 },
|
||||
{ .pdiv = 12, .hw_val = 8 },
|
||||
{ .pdiv = 16, .hw_val = 9 },
|
||||
{ .pdiv = 12, .hw_val = 10 },
|
||||
{ .pdiv = 16, .hw_val = 11 },
|
||||
{ .pdiv = 20, .hw_val = 12 },
|
||||
{ .pdiv = 24, .hw_val = 13 },
|
||||
{ .pdiv = 32, .hw_val = 14 },
|
||||
{ .pdiv = 0, .hw_val = 0 }
|
||||
};
|
||||
|
||||
static struct div_nmp plle_nmp = {
|
||||
.divm_shift = 0,
|
||||
.divm_width = 8,
|
||||
|
@ -584,9 +601,10 @@ 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,
|
||||
.pdiv_tohw = plle_p,
|
||||
.div_nmp = &plle_nmp,
|
||||
.freq_table = pll_e_freq_table,
|
||||
.flags = TEGRA_PLL_FIXED,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.fixed_rate = 100000000,
|
||||
};
|
||||
|
||||
|
@ -614,7 +632,8 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
|
|||
.iddq_reg = PLLRE_MISC,
|
||||
.iddq_bit_idx = PLLRE_IDDQ_BIT,
|
||||
.div_nmp = &pllre_nmp,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
|
||||
TEGRA_PLL_LOCK_MISC,
|
||||
};
|
||||
|
||||
/* possible OSC frequencies in Hz */
|
||||
|
@ -625,7 +644,7 @@ static unsigned long tegra114_input_freq[] = {
|
|||
[ 5] = 38400000,
|
||||
[ 8] = 12000000,
|
||||
[ 9] = 48000000,
|
||||
[12] = 260000000,
|
||||
[12] = 26000000,
|
||||
};
|
||||
|
||||
#define MASK(x) (BIT(x) - 1)
|
||||
|
@ -644,21 +663,27 @@ struct utmi_clk_param {
|
|||
};
|
||||
|
||||
static const struct utmi_clk_param utmi_parameters[] = {
|
||||
{.osc_frequency = 13000000, .enable_delay_count = 0x02,
|
||||
{
|
||||
.osc_frequency = 13000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x33, .active_delay_count = 0x05,
|
||||
.xtal_freq_count = 0x7F},
|
||||
{.osc_frequency = 19200000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x4B, .active_delay_count = 0x06,
|
||||
.xtal_freq_count = 0xBB},
|
||||
{.osc_frequency = 12000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x2F, .active_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x76},
|
||||
{.osc_frequency = 26000000, .enable_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x7f
|
||||
}, {
|
||||
.osc_frequency = 19200000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x4b, .active_delay_count = 0x06,
|
||||
.xtal_freq_count = 0xbb
|
||||
}, {
|
||||
.osc_frequency = 12000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x2f, .active_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x76
|
||||
}, {
|
||||
.osc_frequency = 26000000, .enable_delay_count = 0x04,
|
||||
.stable_count = 0x66, .active_delay_count = 0x09,
|
||||
.xtal_freq_count = 0xFE},
|
||||
{.osc_frequency = 16800000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x41, .active_delay_count = 0x0A,
|
||||
.xtal_freq_count = 0xA4},
|
||||
.xtal_freq_count = 0xfe
|
||||
}, {
|
||||
.osc_frequency = 16800000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x41, .active_delay_count = 0x0a,
|
||||
.xtal_freq_count = 0xa4
|
||||
},
|
||||
};
|
||||
|
||||
/* peripheral mux definitions */
|
||||
|
@ -965,8 +990,8 @@ static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
|
|||
|
||||
static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
|
||||
if (osc_freq == utmi_parameters[i].osc_frequency)
|
||||
|
@ -1173,7 +1198,7 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
|
|||
{
|
||||
struct clk *clk;
|
||||
struct tegra_periph_init_data *data;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
/* xusb_ss_div2 */
|
||||
clk = clk_register_fixed_factor(NULL, "xusb_ss_div2", "xusb_ss_src", 0,
|
||||
|
@ -1315,7 +1340,7 @@ static struct tegra_clk_init_table init_table[] __initdata = {
|
|||
{ TEGRA114_CLK_XUSB_HS_SRC, TEGRA114_CLK_XUSB_SS_DIV2, 61200000, 0 },
|
||||
{ TEGRA114_CLK_XUSB_FALCON_SRC, TEGRA114_CLK_PLL_P, 204000000, 0 },
|
||||
{ TEGRA114_CLK_XUSB_HOST_SRC, TEGRA114_CLK_PLL_P, 102000000, 0 },
|
||||
/* This MUST be the last entry. */
|
||||
/* must be the last entry */
|
||||
{ TEGRA114_CLK_CLK_MAX, TEGRA114_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
||||
|
|
|
@ -156,7 +156,7 @@ static unsigned long tegra124_input_freq[] = {
|
|||
[ 5] = 38400000,
|
||||
[ 8] = 12000000,
|
||||
[ 9] = 48000000,
|
||||
[12] = 260000000,
|
||||
[12] = 26000000,
|
||||
};
|
||||
|
||||
static struct div_nmp pllxc_nmp = {
|
||||
|
@ -168,7 +168,7 @@ static struct div_nmp pllxc_nmp = {
|
|||
.divp_width = 4,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllxc_p[] = {
|
||||
static const struct pdiv_map pllxc_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
|
@ -189,11 +189,11 @@ static struct pdiv_map pllxc_p[] = {
|
|||
|
||||
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
|
||||
/* 1 GHz */
|
||||
{12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */
|
||||
{13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */
|
||||
{16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */
|
||||
{19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */
|
||||
{26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */
|
||||
{ 12000000, 1000000000, 83, 1, 1, 0 }, /* actual: 996.0 MHz */
|
||||
{ 13000000, 1000000000, 76, 1, 1, 0 }, /* actual: 988.0 MHz */
|
||||
{ 16800000, 1000000000, 59, 1, 1, 0 }, /* actual: 991.2 MHz */
|
||||
{ 19200000, 1000000000, 52, 1, 1, 0 }, /* actual: 998.4 MHz */
|
||||
{ 26000000, 1000000000, 76, 2, 1, 0 }, /* actual: 988.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -218,16 +218,16 @@ static struct tegra_clk_pll_params pll_x_params = {
|
|||
.pdiv_tohw = pllxc_p,
|
||||
.div_nmp = &pllxc_nmp,
|
||||
.freq_table = pll_x_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
|
||||
{ 12000000, 624000000, 104, 1, 2},
|
||||
{ 12000000, 600000000, 100, 1, 2},
|
||||
{ 13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 624000000, 104, 1, 2, 0 },
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -252,7 +252,7 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.pdiv_tohw = pllxc_p,
|
||||
.div_nmp = &pllxc_nmp,
|
||||
.freq_table = pll_c_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct div_nmp pllcx_nmp = {
|
||||
|
@ -264,7 +264,7 @@ static struct div_nmp pllcx_nmp = {
|
|||
.divp_width = 3,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllc_p[] = {
|
||||
static const struct pdiv_map pllc_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
|
@ -277,11 +277,11 @@ static struct pdiv_map pllc_p[] = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
|
||||
{12000000, 600000000, 100, 1, 2},
|
||||
{13000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */
|
||||
{16800000, 600000000, 71, 1, 2}, /* actual: 596.4 MHz */
|
||||
{19200000, 600000000, 62, 1, 2}, /* actual: 595.2 MHz */
|
||||
{26000000, 600000000, 92, 2, 2}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -338,7 +338,7 @@ static struct div_nmp pllss_nmp = {
|
|||
.divp_width = 4,
|
||||
};
|
||||
|
||||
static struct pdiv_map pll12g_ssd_esd_p[] = {
|
||||
static const struct pdiv_map pll12g_ssd_esd_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
|
@ -358,11 +358,11 @@ static struct pdiv_map pll12g_ssd_esd_p[] = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_c4_freq_table[] = {
|
||||
{ 12000000, 600000000, 100, 1, 1},
|
||||
{ 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -386,20 +386,34 @@ static struct tegra_clk_pll_params pll_c4_params = {
|
|||
.ext_misc_reg[1] = 0x5b0,
|
||||
.ext_misc_reg[2] = 0x5b4,
|
||||
.freq_table = pll_c4_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllm_p[] = {
|
||||
static const struct pdiv_map pllm_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
{ .pdiv = 4, .hw_val = 3 },
|
||||
{ .pdiv = 5, .hw_val = 4 },
|
||||
{ .pdiv = 6, .hw_val = 5 },
|
||||
{ .pdiv = 8, .hw_val = 6 },
|
||||
{ .pdiv = 10, .hw_val = 7 },
|
||||
{ .pdiv = 12, .hw_val = 8 },
|
||||
{ .pdiv = 16, .hw_val = 9 },
|
||||
{ .pdiv = 12, .hw_val = 10 },
|
||||
{ .pdiv = 16, .hw_val = 11 },
|
||||
{ .pdiv = 20, .hw_val = 12 },
|
||||
{ .pdiv = 24, .hw_val = 13 },
|
||||
{ .pdiv = 32, .hw_val = 14 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
|
||||
{12000000, 800000000, 66, 1, 1}, /* actual: 792.0 MHz */
|
||||
{13000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */
|
||||
{16800000, 800000000, 47, 1, 1}, /* actual: 789.6 MHz */
|
||||
{19200000, 800000000, 41, 1, 1}, /* actual: 787.2 MHz */
|
||||
{26000000, 800000000, 61, 2, 1}, /* actual: 793.0 MHz */
|
||||
{ 12000000, 800000000, 66, 1, 1, 0 }, /* actual: 792.0 MHz */
|
||||
{ 13000000, 800000000, 61, 1, 1, 0 }, /* actual: 793.0 MHz */
|
||||
{ 16800000, 800000000, 47, 1, 1, 0 }, /* actual: 789.6 MHz */
|
||||
{ 19200000, 800000000, 41, 1, 1, 0 }, /* actual: 787.2 MHz */
|
||||
{ 26000000, 800000000, 61, 2, 1, 0 }, /* actual: 793.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
@ -427,13 +441,13 @@ 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,
|
||||
.max_p = 2,
|
||||
.max_p = 5,
|
||||
.pdiv_tohw = pllm_p,
|
||||
.div_nmp = &pllm_nmp,
|
||||
.pmc_divnm_reg = PMC_PLLM_WB0_OVERRIDE,
|
||||
.pmc_divp_reg = PMC_PLLM_WB0_OVERRIDE_2,
|
||||
.freq_table = pll_m_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||
|
@ -445,6 +459,25 @@ static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
|||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct pdiv_map plle_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
{ .pdiv = 2, .hw_val = 1 },
|
||||
{ .pdiv = 3, .hw_val = 2 },
|
||||
{ .pdiv = 4, .hw_val = 3 },
|
||||
{ .pdiv = 5, .hw_val = 4 },
|
||||
{ .pdiv = 6, .hw_val = 5 },
|
||||
{ .pdiv = 8, .hw_val = 6 },
|
||||
{ .pdiv = 10, .hw_val = 7 },
|
||||
{ .pdiv = 12, .hw_val = 8 },
|
||||
{ .pdiv = 16, .hw_val = 9 },
|
||||
{ .pdiv = 12, .hw_val = 10 },
|
||||
{ .pdiv = 16, .hw_val = 11 },
|
||||
{ .pdiv = 20, .hw_val = 12 },
|
||||
{ .pdiv = 24, .hw_val = 13 },
|
||||
{ .pdiv = 32, .hw_val = 14 },
|
||||
{ .pdiv = 1, .hw_val = 0 },
|
||||
};
|
||||
|
||||
static struct div_nmp plle_nmp = {
|
||||
.divm_shift = 0,
|
||||
.divm_width = 8,
|
||||
|
@ -467,9 +500,10 @@ 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,
|
||||
.pdiv_tohw = plle_p,
|
||||
.div_nmp = &plle_nmp,
|
||||
.freq_table = pll_e_freq_table,
|
||||
.flags = TEGRA_PLL_FIXED,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.fixed_rate = 100000000,
|
||||
};
|
||||
|
||||
|
@ -507,7 +541,8 @@ static struct tegra_clk_pll_params pll_re_vco_params = {
|
|||
.iddq_reg = PLLRE_MISC,
|
||||
.iddq_bit_idx = PLLRE_IDDQ_BIT,
|
||||
.div_nmp = &pllre_nmp,
|
||||
.flags = TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE |
|
||||
TEGRA_PLL_LOCK_MISC,
|
||||
};
|
||||
|
||||
static struct div_nmp pllp_nmp = {
|
||||
|
@ -520,11 +555,11 @@ static struct div_nmp pllp_nmp = {
|
|||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
||||
{12000000, 408000000, 408, 12, 0, 8},
|
||||
{13000000, 408000000, 408, 13, 0, 8},
|
||||
{16800000, 408000000, 340, 14, 0, 8},
|
||||
{19200000, 408000000, 340, 16, 0, 8},
|
||||
{26000000, 408000000, 408, 26, 0, 8},
|
||||
{ 12000000, 408000000, 408, 12, 1, 8 },
|
||||
{ 13000000, 408000000, 408, 13, 1, 8 },
|
||||
{ 16800000, 408000000, 340, 14, 1, 8 },
|
||||
{ 19200000, 408000000, 340, 16, 1, 8 },
|
||||
{ 26000000, 408000000, 408, 26, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -543,17 +578,17 @@ static struct tegra_clk_pll_params pll_p_params = {
|
|||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_p_freq_table,
|
||||
.fixed_rate = 408000000,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
|
||||
{9600000, 282240000, 147, 5, 0, 4},
|
||||
{9600000, 368640000, 192, 5, 0, 4},
|
||||
{9600000, 240000000, 200, 8, 0, 8},
|
||||
|
||||
{28800000, 282240000, 245, 25, 0, 8},
|
||||
{28800000, 368640000, 320, 25, 0, 8},
|
||||
{28800000, 240000000, 200, 24, 0, 8},
|
||||
{ 9600000, 282240000, 147, 5, 1, 4 },
|
||||
{ 9600000, 368640000, 192, 5, 1, 4 },
|
||||
{ 9600000, 240000000, 200, 8, 1, 8 },
|
||||
{ 28800000, 282240000, 245, 25, 1, 8 },
|
||||
{ 28800000, 368640000, 320, 25, 1, 8 },
|
||||
{ 28800000, 240000000, 200, 24, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -571,7 +606,8 @@ static struct tegra_clk_pll_params pll_a_params = {
|
|||
.lock_delay = 300,
|
||||
.div_nmp = &pllp_nmp,
|
||||
.freq_table = pll_a_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct div_nmp plld_nmp = {
|
||||
|
@ -589,18 +625,15 @@ static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
|
|||
{ 16800000, 216000000, 720, 14, 4, 12 },
|
||||
{ 19200000, 216000000, 720, 16, 4, 12 },
|
||||
{ 26000000, 216000000, 864, 26, 4, 12 },
|
||||
|
||||
{ 12000000, 594000000, 594, 12, 1, 12 },
|
||||
{ 13000000, 594000000, 594, 13, 1, 12 },
|
||||
{ 16800000, 594000000, 495, 14, 1, 12 },
|
||||
{ 19200000, 594000000, 495, 16, 1, 12 },
|
||||
{ 26000000, 594000000, 594, 26, 1, 12 },
|
||||
|
||||
{ 12000000, 1000000000, 1000, 12, 1, 12 },
|
||||
{ 13000000, 1000000000, 1000, 13, 1, 12 },
|
||||
{ 19200000, 1000000000, 625, 12, 1, 12 },
|
||||
{ 26000000, 1000000000, 1000, 26, 1, 12 },
|
||||
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -619,15 +652,15 @@ static struct tegra_clk_pll_params pll_d_params = {
|
|||
.div_nmp = &plld_nmp,
|
||||
.freq_table = pll_d_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
|
||||
TEGRA_PLL_USE_LOCK,
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table tegra124_pll_d2_freq_table[] = {
|
||||
{ 12000000, 594000000, 99, 1, 2},
|
||||
{ 13000000, 594000000, 91, 1, 2}, /* actual: 591.5 MHz */
|
||||
{ 16800000, 594000000, 71, 1, 2}, /* actual: 596.4 MHz */
|
||||
{ 19200000, 594000000, 62, 1, 2}, /* actual: 595.2 MHz */
|
||||
{ 26000000, 594000000, 91, 2, 2}, /* actual: 591.5 MHz */
|
||||
{ 12000000, 594000000, 99, 1, 2, 0 },
|
||||
{ 13000000, 594000000, 91, 1, 2, 0 }, /* actual: 591.5 MHz */
|
||||
{ 16800000, 594000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 594000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 594000000, 91, 2, 2, 0 }, /* actual: 591.5 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -652,14 +685,15 @@ static struct tegra_clk_pll_params tegra124_pll_d2_params = {
|
|||
.ext_misc_reg[2] = 0x578,
|
||||
.max_p = 15,
|
||||
.freq_table = tegra124_pll_d2_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_dp_freq_table[] = {
|
||||
{ 12000000, 600000000, 100, 1, 1},
|
||||
{ 13000000, 600000000, 92, 1, 1}, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 1}, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 1}, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 1}, /* actual: 598.0 MHz */
|
||||
{ 12000000, 600000000, 100, 1, 2, 0 },
|
||||
{ 13000000, 600000000, 92, 1, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 16800000, 600000000, 71, 1, 2, 0 }, /* actual: 596.4 MHz */
|
||||
{ 19200000, 600000000, 62, 1, 2, 0 }, /* actual: 595.2 MHz */
|
||||
{ 26000000, 600000000, 92, 2, 2, 0 }, /* actual: 598.0 MHz */
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -684,9 +718,10 @@ static struct tegra_clk_pll_params pll_dp_params = {
|
|||
.ext_misc_reg[2] = 0x5a0,
|
||||
.max_p = 5,
|
||||
.freq_table = pll_dp_freq_table,
|
||||
.flags = TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllu_p[] = {
|
||||
static const struct pdiv_map pllu_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 1 },
|
||||
{ .pdiv = 2, .hw_val = 0 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
|
@ -726,7 +761,7 @@ static struct tegra_clk_pll_params pll_u_params = {
|
|||
.div_nmp = &pllu_nmp,
|
||||
.freq_table = pll_u_freq_table,
|
||||
.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
|
||||
TEGRA_PLL_USE_LOCK,
|
||||
TEGRA_PLL_USE_LOCK | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
struct utmi_clk_param {
|
||||
|
@ -743,21 +778,27 @@ struct utmi_clk_param {
|
|||
};
|
||||
|
||||
static const struct utmi_clk_param utmi_parameters[] = {
|
||||
{.osc_frequency = 13000000, .enable_delay_count = 0x02,
|
||||
{
|
||||
.osc_frequency = 13000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x33, .active_delay_count = 0x05,
|
||||
.xtal_freq_count = 0x7F},
|
||||
{.osc_frequency = 19200000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x4B, .active_delay_count = 0x06,
|
||||
.xtal_freq_count = 0xBB},
|
||||
{.osc_frequency = 12000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x2F, .active_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x76},
|
||||
{.osc_frequency = 26000000, .enable_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x7f
|
||||
}, {
|
||||
.osc_frequency = 19200000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x4b, .active_delay_count = 0x06,
|
||||
.xtal_freq_count = 0xbb
|
||||
}, {
|
||||
.osc_frequency = 12000000, .enable_delay_count = 0x02,
|
||||
.stable_count = 0x2f, .active_delay_count = 0x04,
|
||||
.xtal_freq_count = 0x76
|
||||
}, {
|
||||
.osc_frequency = 26000000, .enable_delay_count = 0x04,
|
||||
.stable_count = 0x66, .active_delay_count = 0x09,
|
||||
.xtal_freq_count = 0xFE},
|
||||
{.osc_frequency = 16800000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x41, .active_delay_count = 0x0A,
|
||||
.xtal_freq_count = 0xA4},
|
||||
.xtal_freq_count = 0xfe
|
||||
}, {
|
||||
.osc_frequency = 16800000, .enable_delay_count = 0x03,
|
||||
.stable_count = 0x41, .active_delay_count = 0x0a,
|
||||
.xtal_freq_count = 0xa4
|
||||
},
|
||||
};
|
||||
|
||||
static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
|
||||
|
@ -1024,8 +1065,8 @@ static struct clk **clks;
|
|||
|
||||
static void tegra124_utmi_param_configure(void __iomem *clk_base)
|
||||
{
|
||||
unsigned int i;
|
||||
u32 reg;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
|
||||
if (osc_freq == utmi_parameters[i].osc_frequency)
|
||||
|
@ -1397,7 +1438,7 @@ static struct tegra_clk_init_table common_init_table[] __initdata = {
|
|||
{ TEGRA124_CLK_MSELECT, TEGRA124_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA124_CLK_CSITE, TEGRA124_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA124_CLK_TSENSOR, TEGRA124_CLK_CLK_M, 400000, 0 },
|
||||
/* This MUST be the last entry. */
|
||||
/* must be the last entry */
|
||||
{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -1406,14 +1447,14 @@ static struct tegra_clk_init_table tegra124_init_table[] __initdata = {
|
|||
{ TEGRA124_CLK_CCLK_G, TEGRA124_CLK_CLK_MAX, 0, 1 },
|
||||
{ TEGRA124_CLK_HDA, TEGRA124_CLK_PLL_P, 102000000, 0 },
|
||||
{ TEGRA124_CLK_HDA2CODEC_2X, TEGRA124_CLK_PLL_P, 48000000, 0 },
|
||||
/* This MUST be the last entry. */
|
||||
/* must be the last entry */
|
||||
{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
||||
/* Tegra132 requires the SOC_THERM clock to remain active */
|
||||
static struct tegra_clk_init_table tegra132_init_table[] __initdata = {
|
||||
{ TEGRA124_CLK_SOC_THERM, TEGRA124_CLK_PLL_P, 51000000, 1 },
|
||||
/* This MUST be the last entry. */
|
||||
/* must be the last entry */
|
||||
{ TEGRA124_CLK_CLK_MAX, TEGRA124_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
||||
|
|
|
@ -166,125 +166,119 @@ static DEFINE_SPINLOCK(emc_lock);
|
|||
static struct clk **clks;
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
|
||||
{ 12000000, 600000000, 600, 12, 0, 8 },
|
||||
{ 13000000, 600000000, 600, 13, 0, 8 },
|
||||
{ 19200000, 600000000, 500, 16, 0, 6 },
|
||||
{ 26000000, 600000000, 600, 26, 0, 8 },
|
||||
{ 12000000, 600000000, 600, 12, 1, 8 },
|
||||
{ 13000000, 600000000, 600, 13, 1, 8 },
|
||||
{ 19200000, 600000000, 500, 16, 1, 6 },
|
||||
{ 26000000, 600000000, 600, 26, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
|
||||
{ 12000000, 666000000, 666, 12, 0, 8},
|
||||
{ 13000000, 666000000, 666, 13, 0, 8},
|
||||
{ 19200000, 666000000, 555, 16, 0, 8},
|
||||
{ 26000000, 666000000, 666, 26, 0, 8},
|
||||
{ 12000000, 600000000, 600, 12, 0, 8},
|
||||
{ 13000000, 600000000, 600, 13, 0, 8},
|
||||
{ 19200000, 600000000, 375, 12, 0, 6},
|
||||
{ 26000000, 600000000, 600, 26, 0, 8},
|
||||
{ 12000000, 666000000, 666, 12, 1, 8 },
|
||||
{ 13000000, 666000000, 666, 13, 1, 8 },
|
||||
{ 19200000, 666000000, 555, 16, 1, 8 },
|
||||
{ 26000000, 666000000, 666, 26, 1, 8 },
|
||||
{ 12000000, 600000000, 600, 12, 1, 8 },
|
||||
{ 13000000, 600000000, 600, 13, 1, 8 },
|
||||
{ 19200000, 600000000, 375, 12, 1, 6 },
|
||||
{ 26000000, 600000000, 600, 26, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
|
||||
{ 12000000, 216000000, 432, 12, 1, 8},
|
||||
{ 13000000, 216000000, 432, 13, 1, 8},
|
||||
{ 19200000, 216000000, 90, 4, 1, 1},
|
||||
{ 26000000, 216000000, 432, 26, 1, 8},
|
||||
{ 12000000, 432000000, 432, 12, 0, 8},
|
||||
{ 13000000, 432000000, 432, 13, 0, 8},
|
||||
{ 19200000, 432000000, 90, 4, 0, 1},
|
||||
{ 26000000, 432000000, 432, 26, 0, 8},
|
||||
{ 12000000, 216000000, 432, 12, 2, 8 },
|
||||
{ 13000000, 216000000, 432, 13, 2, 8 },
|
||||
{ 19200000, 216000000, 90, 4, 2, 1 },
|
||||
{ 26000000, 216000000, 432, 26, 2, 8 },
|
||||
{ 12000000, 432000000, 432, 12, 1, 8 },
|
||||
{ 13000000, 432000000, 432, 13, 1, 8 },
|
||||
{ 19200000, 432000000, 90, 4, 1, 1 },
|
||||
{ 26000000, 432000000, 432, 26, 1, 8 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
|
||||
{ 28800000, 56448000, 49, 25, 0, 1},
|
||||
{ 28800000, 73728000, 64, 25, 0, 1},
|
||||
{ 28800000, 24000000, 5, 6, 0, 1},
|
||||
{ 28800000, 56448000, 49, 25, 1, 1 },
|
||||
{ 28800000, 73728000, 64, 25, 1, 1 },
|
||||
{ 28800000, 24000000, 5, 6, 1, 1 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
|
||||
{ 12000000, 216000000, 216, 12, 0, 4},
|
||||
{ 13000000, 216000000, 216, 13, 0, 4},
|
||||
{ 19200000, 216000000, 135, 12, 0, 3},
|
||||
{ 26000000, 216000000, 216, 26, 0, 4},
|
||||
|
||||
{ 12000000, 594000000, 594, 12, 0, 8},
|
||||
{ 13000000, 594000000, 594, 13, 0, 8},
|
||||
{ 19200000, 594000000, 495, 16, 0, 8},
|
||||
{ 26000000, 594000000, 594, 26, 0, 8},
|
||||
|
||||
{ 12000000, 1000000000, 1000, 12, 0, 12},
|
||||
{ 13000000, 1000000000, 1000, 13, 0, 12},
|
||||
{ 19200000, 1000000000, 625, 12, 0, 8},
|
||||
{ 26000000, 1000000000, 1000, 26, 0, 12},
|
||||
|
||||
{ 12000000, 216000000, 216, 12, 1, 4 },
|
||||
{ 13000000, 216000000, 216, 13, 1, 4 },
|
||||
{ 19200000, 216000000, 135, 12, 1, 3 },
|
||||
{ 26000000, 216000000, 216, 26, 1, 4 },
|
||||
{ 12000000, 594000000, 594, 12, 1, 8 },
|
||||
{ 13000000, 594000000, 594, 13, 1, 8 },
|
||||
{ 19200000, 594000000, 495, 16, 1, 8 },
|
||||
{ 26000000, 594000000, 594, 26, 1, 8 },
|
||||
{ 12000000, 1000000000, 1000, 12, 1, 12 },
|
||||
{ 13000000, 1000000000, 1000, 13, 1, 12 },
|
||||
{ 19200000, 1000000000, 625, 12, 1, 8 },
|
||||
{ 26000000, 1000000000, 1000, 26, 1, 12 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
|
||||
{ 12000000, 480000000, 960, 12, 0, 0},
|
||||
{ 13000000, 480000000, 960, 13, 0, 0},
|
||||
{ 19200000, 480000000, 200, 4, 0, 0},
|
||||
{ 26000000, 480000000, 960, 26, 0, 0},
|
||||
{ 12000000, 480000000, 960, 12, 1, 0 },
|
||||
{ 13000000, 480000000, 960, 13, 1, 0 },
|
||||
{ 19200000, 480000000, 200, 4, 1, 0 },
|
||||
{ 26000000, 480000000, 960, 26, 1, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
|
||||
/* 1 GHz */
|
||||
{ 12000000, 1000000000, 1000, 12, 0, 12},
|
||||
{ 13000000, 1000000000, 1000, 13, 0, 12},
|
||||
{ 19200000, 1000000000, 625, 12, 0, 8},
|
||||
{ 26000000, 1000000000, 1000, 26, 0, 12},
|
||||
|
||||
{ 12000000, 1000000000, 1000, 12, 1, 12 },
|
||||
{ 13000000, 1000000000, 1000, 13, 1, 12 },
|
||||
{ 19200000, 1000000000, 625, 12, 1, 8 },
|
||||
{ 26000000, 1000000000, 1000, 26, 1, 12 },
|
||||
/* 912 MHz */
|
||||
{ 12000000, 912000000, 912, 12, 0, 12},
|
||||
{ 13000000, 912000000, 912, 13, 0, 12},
|
||||
{ 19200000, 912000000, 760, 16, 0, 8},
|
||||
{ 26000000, 912000000, 912, 26, 0, 12},
|
||||
|
||||
{ 12000000, 912000000, 912, 12, 1, 12 },
|
||||
{ 13000000, 912000000, 912, 13, 1, 12 },
|
||||
{ 19200000, 912000000, 760, 16, 1, 8 },
|
||||
{ 26000000, 912000000, 912, 26, 1, 12 },
|
||||
/* 816 MHz */
|
||||
{ 12000000, 816000000, 816, 12, 0, 12},
|
||||
{ 13000000, 816000000, 816, 13, 0, 12},
|
||||
{ 19200000, 816000000, 680, 16, 0, 8},
|
||||
{ 26000000, 816000000, 816, 26, 0, 12},
|
||||
|
||||
{ 12000000, 816000000, 816, 12, 1, 12 },
|
||||
{ 13000000, 816000000, 816, 13, 1, 12 },
|
||||
{ 19200000, 816000000, 680, 16, 1, 8 },
|
||||
{ 26000000, 816000000, 816, 26, 1, 12 },
|
||||
/* 760 MHz */
|
||||
{ 12000000, 760000000, 760, 12, 0, 12},
|
||||
{ 13000000, 760000000, 760, 13, 0, 12},
|
||||
{ 19200000, 760000000, 950, 24, 0, 8},
|
||||
{ 26000000, 760000000, 760, 26, 0, 12},
|
||||
|
||||
{ 12000000, 760000000, 760, 12, 1, 12 },
|
||||
{ 13000000, 760000000, 760, 13, 1, 12 },
|
||||
{ 19200000, 760000000, 950, 24, 1, 8 },
|
||||
{ 26000000, 760000000, 760, 26, 1, 12 },
|
||||
/* 750 MHz */
|
||||
{ 12000000, 750000000, 750, 12, 0, 12},
|
||||
{ 13000000, 750000000, 750, 13, 0, 12},
|
||||
{ 19200000, 750000000, 625, 16, 0, 8},
|
||||
{ 26000000, 750000000, 750, 26, 0, 12},
|
||||
|
||||
{ 12000000, 750000000, 750, 12, 1, 12 },
|
||||
{ 13000000, 750000000, 750, 13, 1, 12 },
|
||||
{ 19200000, 750000000, 625, 16, 1, 8 },
|
||||
{ 26000000, 750000000, 750, 26, 1, 12 },
|
||||
/* 608 MHz */
|
||||
{ 12000000, 608000000, 608, 12, 0, 12},
|
||||
{ 13000000, 608000000, 608, 13, 0, 12},
|
||||
{ 19200000, 608000000, 380, 12, 0, 8},
|
||||
{ 26000000, 608000000, 608, 26, 0, 12},
|
||||
|
||||
{ 12000000, 608000000, 608, 12, 1, 12 },
|
||||
{ 13000000, 608000000, 608, 13, 1, 12 },
|
||||
{ 19200000, 608000000, 380, 12, 1, 8 },
|
||||
{ 26000000, 608000000, 608, 26, 1, 12 },
|
||||
/* 456 MHz */
|
||||
{ 12000000, 456000000, 456, 12, 0, 12},
|
||||
{ 13000000, 456000000, 456, 13, 0, 12},
|
||||
{ 19200000, 456000000, 380, 16, 0, 8},
|
||||
{ 26000000, 456000000, 456, 26, 0, 12},
|
||||
|
||||
{ 12000000, 456000000, 456, 12, 1, 12 },
|
||||
{ 13000000, 456000000, 456, 13, 1, 12 },
|
||||
{ 19200000, 456000000, 380, 16, 1, 8 },
|
||||
{ 26000000, 456000000, 456, 26, 1, 12 },
|
||||
/* 312 MHz */
|
||||
{ 12000000, 312000000, 312, 12, 0, 12},
|
||||
{ 13000000, 312000000, 312, 13, 0, 12},
|
||||
{ 19200000, 312000000, 260, 16, 0, 8},
|
||||
{ 26000000, 312000000, 312, 26, 0, 12},
|
||||
|
||||
{ 12000000, 312000000, 312, 12, 1, 12 },
|
||||
{ 13000000, 312000000, 312, 13, 1, 12 },
|
||||
{ 19200000, 312000000, 260, 16, 1, 8 },
|
||||
{ 26000000, 312000000, 312, 26, 1, 12 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
static const struct pdiv_map plle_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 1 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
|
||||
{ 12000000, 100000000, 200, 24, 0, 0 },
|
||||
{ 12000000, 100000000, 200, 24, 1, 0 },
|
||||
{ 0, 0, 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
|
@ -302,7 +296,7 @@ static struct tegra_clk_pll_params pll_c_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_c_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_m_params = {
|
||||
|
@ -318,7 +312,7 @@ static struct tegra_clk_pll_params pll_m_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_m_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_p_params = {
|
||||
|
@ -334,7 +328,8 @@ static struct tegra_clk_pll_params pll_p_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_p_freq_table,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.fixed_rate = 216000000,
|
||||
};
|
||||
|
||||
|
@ -351,7 +346,7 @@ static struct tegra_clk_pll_params pll_a_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_a_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_d_params = {
|
||||
|
@ -367,10 +362,10 @@ static struct tegra_clk_pll_params pll_d_params = {
|
|||
.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 1000,
|
||||
.freq_table = pll_d_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct pdiv_map pllu_p[] = {
|
||||
static const struct pdiv_map pllu_p[] = {
|
||||
{ .pdiv = 1, .hw_val = 1 },
|
||||
{ .pdiv = 2, .hw_val = 0 },
|
||||
{ .pdiv = 0, .hw_val = 0 },
|
||||
|
@ -390,7 +385,7 @@ static struct tegra_clk_pll_params pll_u_params = {
|
|||
.lock_delay = 1000,
|
||||
.pdiv_tohw = pllu_p,
|
||||
.freq_table = pll_u_freq_table,
|
||||
.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLLU | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_x_params = {
|
||||
|
@ -406,7 +401,7 @@ static struct tegra_clk_pll_params pll_x_params = {
|
|||
.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 300,
|
||||
.freq_table = pll_x_freq_table,
|
||||
.flags = TEGRA_PLL_HAS_CPCON,
|
||||
.flags = TEGRA_PLL_HAS_CPCON | TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
};
|
||||
|
||||
static struct tegra_clk_pll_params pll_e_params = {
|
||||
|
@ -421,8 +416,10 @@ static struct tegra_clk_pll_params pll_e_params = {
|
|||
.lock_mask = PLLE_MISC_LOCK,
|
||||
.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
|
||||
.lock_delay = 0,
|
||||
.pdiv_tohw = plle_p,
|
||||
.freq_table = pll_e_freq_table,
|
||||
.flags = TEGRA_PLL_FIXED,
|
||||
.flags = TEGRA_PLL_FIXED | TEGRA_PLL_LOCK_MISC |
|
||||
TEGRA_PLL_HAS_LOCK_ENABLE,
|
||||
.fixed_rate = 100000000,
|
||||
};
|
||||
|
||||
|
@ -759,7 +756,6 @@ static void __init tegra20_audio_clk_init(void)
|
|||
CLK_SET_RATE_PARENT, 89,
|
||||
periph_clk_enb_refcnt);
|
||||
clks[TEGRA20_CLK_AUDIO_2X] = clk;
|
||||
|
||||
}
|
||||
|
||||
static const char *i2s1_parents[] = { "pll_a_out0", "audio_2x", "pll_p",
|
||||
|
@ -802,7 +798,7 @@ static void __init tegra20_periph_clk_init(void)
|
|||
{
|
||||
struct tegra_periph_init_data *data;
|
||||
struct clk *clk;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
/* ac97 */
|
||||
clk = tegra_clk_register_periph_gate("ac97", "pll_a_out0",
|
||||
|
@ -1062,7 +1058,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
|
|||
{ TEGRA20_CLK_DISP2, TEGRA20_CLK_PLL_P, 600000000, 0 },
|
||||
{ TEGRA20_CLK_GR2D, TEGRA20_CLK_PLL_C, 300000000, 0 },
|
||||
{ TEGRA20_CLK_GR3D, TEGRA20_CLK_PLL_C, 300000000, 0 },
|
||||
{TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0}, /* This MUST be the last entry */
|
||||
/* must be the last entry */
|
||||
{ TEGRA20_CLK_CLK_MAX, TEGRA20_CLK_CLK_MAX, 0, 0 },
|
||||
};
|
||||
|
||||
static void __init tegra20_clock_apply_init_table(void)
|
||||
|
@ -1080,7 +1077,8 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
|
|||
TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-ehci.0", NULL),
|
||||
TEGRA_CLK_DUPLICATE(TEGRA20_CLK_USBD, "tegra-otg", NULL),
|
||||
TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CCLK, NULL, "cpu"),
|
||||
TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL), /* Must be the last entry */
|
||||
/* must be the last entry */
|
||||
TEGRA_CLK_DUPLICATE(TEGRA20_CLK_CLK_MAX, NULL, NULL),
|
||||
};
|
||||
|
||||
static const struct of_device_id pmc_match[] __initconst = {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue