The majority of the changes are driver updates and new device
support. The core framework is mostly unchanged this time around, with only a couple patches to expose a clk provider API and make getting clk parent names from DT more robust. Driver updates: - Support for clock controllers found on Broadcom Northstar SoCs and bcm2835 SoC - Support for Allwinner audio clocks - A few cleanup patches for Tegra drivers and support for the highest DFLL frequencies on Tegra124 - Samsung exynos7 fixes and improvements - i.Mx SoC updates to add a few missing clocks and keep debug uart clocks on during kernel intialization - Some mediatek cleanups and support for more subsystem clocks - Support for msm8916 gpu/audio clocks and qcom's GDSC power domain controllers - A new driver for the Silabs si514 clock chip -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABCAAGBQJWOov3AAoJENidgRMleOc9qF4P/Rj/Gw/E0dyjE1fE3j4V9iNJ YJere7Zzr1ueG2THfMk335JGN7hQQkP8ofe8QzS4Opbo0m/Y+RxWo++1PDLUytxv wu79HGFKNCEXqqWvIfm30cgoZ59sjjHpVaZHgDDL17YEG2GxWlzstjKXp/E3EDer UOW75sKQ5E9AoWiqySmzZSUunWrgwOBoCA6OR9JhBRa5rzXisu1inIOw8K+zw1q1 WtOekpricaodajIsI+2dFTtAokBOqRsrhcBptYI9ZpZtqVMc+wVWjHqEQHzEkLC0 q4VMVUspt+/dnI3zjM5KkOe553A8wXqehuIek6y0osdwDtCgwAcU/dL9e27MmqvE 0jbJ+vu1UlHkFsSaxYxEQKvQONqVEAPOFomW+9qabF/pMNiXloBVEGCKpV8R8HtB NyJvOcdTFouESGvFntvn6MV5GHFveFiRWRKacq+9QVvitEsu6Xg7mP4kTh0hf1C6 zb1o3s1Z1iGnWcEjAPTNBHEte17mkR9magxkoyB4GzaNxempWHyZ+MXLEiTgQyjA MMTROM1Lg4aftPaASBtMvL//YHSXAd0P924I2KKTTf1X+yP60XLLSVrdMvPgTXy1 bV1L7Vszo1BMVYbFD9YG+pGnXFzia2NJafQoLgw+Cm3Mo2ApqjCdtj/UADFT+/Bz X0ZKA7w9nUM+rD2EMSi1 =K6iN -----END PGP SIGNATURE----- Merge tag 'clk-for-linus-20151104' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux Pull clk updates from Stephen Boyd: "The majority of the changes are driver updates and new device support. The core framework is mostly unchanged this time around, with only a couple patches to expose a clk provider API and make getting clk parent names from DT more robust. Driver updates: - Support for clock controllers found on Broadcom Northstar SoCs and bcm2835 SoC - Support for Allwinner audio clocks - A few cleanup patches for Tegra drivers and support for the highest DFLL frequencies on Tegra124 - Samsung exynos7 fixes and improvements - i.Mx SoC updates to add a few missing clocks and keep debug uart clocks on during kernel intialization - Some mediatek cleanups and support for more subsystem clocks - Support for msm8916 gpu/audio clocks and qcom's GDSC power domain controllers - A new driver for the Silabs si514 clock chip" * tag 'clk-for-linus-20151104' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (143 commits) clk: qcom: msm8960: Fix dsi1/2 halt bits clk: lpc18xx-cgu: fix potential system hang when disabling unused clocks clk: lpc18xx-ccu: fix potential system hang when disabling unused clocks clk: Add clk_hw_is_enabled() for use by clk providers clk: Add stubs for of_clk_*() APIs when CONFIG_OF=n clk: versatile-icst: fix memory leak clk: Remove clk_{register,unregister}_multiplier() clk: iproc: define Broadcom NS2 iProc clock binding clk: iproc: define Broadcom NSP iProc clock binding clk: ns2: add clock support for Broadcom Northstar 2 SoC clk: iproc: Separate status and control variables clk: iproc: Split off dig_filter clk: iproc: Add PLL base write function clk: nsp: add clock support for Broadcom Northstar Plus SoC clk: iproc: Add PWRCTRL support clk: cygnus: Convert all macros to all caps ARM: cygnus: fix link failures when CONFIG_COMMON_CLK_IPROC is disabled clk: imx31: add missing of_node_put clk: imx27: add missing of_node_put clk: si5351: add missing of_node_put ...
This commit is contained in:
commit
f66477a0ae
|
@ -0,0 +1,22 @@
|
||||||
|
Mediatek imgsys controller
|
||||||
|
============================
|
||||||
|
|
||||||
|
The Mediatek imgsys controller provides various clocks to the system.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
|
||||||
|
- compatible: Should be:
|
||||||
|
- "mediatek,mt8173-imgsys", "syscon"
|
||||||
|
- #clock-cells: Must be 1
|
||||||
|
|
||||||
|
The imgsys controller uses the common clk binding from
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
imgsys: clock-controller@15000000 {
|
||||||
|
compatible = "mediatek,mt8173-imgsys", "syscon";
|
||||||
|
reg = <0 0x15000000 0 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
Mediatek mmsys controller
|
||||||
|
============================
|
||||||
|
|
||||||
|
The Mediatek mmsys controller provides various clocks to the system.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
|
||||||
|
- compatible: Should be:
|
||||||
|
- "mediatek,mt8173-mmsys", "syscon"
|
||||||
|
- #clock-cells: Must be 1
|
||||||
|
|
||||||
|
The mmsys controller uses the common clk binding from
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
mmsys: clock-controller@14000000 {
|
||||||
|
compatible = "mediatek,mt8173-mmsys", "syscon";
|
||||||
|
reg = <0 0x14000000 0 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
Mediatek vdecsys controller
|
||||||
|
============================
|
||||||
|
|
||||||
|
The Mediatek vdecsys controller provides various clocks to the system.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
|
||||||
|
- compatible: Should be:
|
||||||
|
- "mediatek,mt8173-vdecsys", "syscon"
|
||||||
|
- #clock-cells: Must be 1
|
||||||
|
|
||||||
|
The vdecsys controller uses the common clk binding from
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
vdecsys: clock-controller@16000000 {
|
||||||
|
compatible = "mediatek,mt8173-vdecsys", "syscon";
|
||||||
|
reg = <0 0x16000000 0 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
Mediatek vencltsys controller
|
||||||
|
============================
|
||||||
|
|
||||||
|
The Mediatek vencltsys controller provides various clocks to the system.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
|
||||||
|
- compatible: Should be:
|
||||||
|
- "mediatek,mt8173-vencltsys", "syscon"
|
||||||
|
- #clock-cells: Must be 1
|
||||||
|
|
||||||
|
The vencltsys controller uses the common clk binding from
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
vencltsys: clock-controller@19000000 {
|
||||||
|
compatible = "mediatek,mt8173-vencltsys", "syscon";
|
||||||
|
reg = <0 0x19000000 0 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
Mediatek vencsys controller
|
||||||
|
============================
|
||||||
|
|
||||||
|
The Mediatek vencsys controller provides various clocks to the system.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
|
||||||
|
- compatible: Should be:
|
||||||
|
- "mediatek,mt8173-vencsys", "syscon"
|
||||||
|
- #clock-cells: Must be 1
|
||||||
|
|
||||||
|
The vencsys controller uses the common clk binding from
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
The available clocks are defined in dt-bindings/clock/mt*-clk.h.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
vencsys: clock-controller@18000000 {
|
||||||
|
compatible = "mediatek,mt8173-vencsys", "syscon";
|
||||||
|
reg = <0 0x18000000 0 0x1000>;
|
||||||
|
#clock-cells = <1>;
|
||||||
|
};
|
|
@ -77,6 +77,9 @@ Required properties:
|
||||||
"atmel,sama5d4-clk-h32mx":
|
"atmel,sama5d4-clk-h32mx":
|
||||||
at91 h32mx clock
|
at91 h32mx clock
|
||||||
|
|
||||||
|
"atmel,sama5d2-clk-generated":
|
||||||
|
at91 generated clock
|
||||||
|
|
||||||
Required properties for SCKC node:
|
Required properties for SCKC node:
|
||||||
- reg : defines the IO memory reserved for the SCKC.
|
- reg : defines the IO memory reserved for the SCKC.
|
||||||
- #size-cells : shall be 0 (reg is used to encode clk id).
|
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||||
|
@ -461,3 +464,35 @@ For example:
|
||||||
compatible = "atmel,sama5d4-clk-h32mx";
|
compatible = "atmel,sama5d4-clk-h32mx";
|
||||||
clocks = <&mck>;
|
clocks = <&mck>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Required properties for generated clocks:
|
||||||
|
- #size-cells : shall be 0 (reg is used to encode clk id).
|
||||||
|
- #address-cells : shall be 1 (reg is used to encode clk id).
|
||||||
|
- clocks : shall be the generated clock source phandles.
|
||||||
|
e.g. clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
|
||||||
|
- name: device tree node describing a specific generated clock.
|
||||||
|
* #clock-cells : from common clock binding; shall be set to 0.
|
||||||
|
* reg: peripheral id. See Atmel's datasheets to get a full
|
||||||
|
list of peripheral ids.
|
||||||
|
* atmel,clk-output-range : minimum and maximum clock frequency
|
||||||
|
(two u32 fields).
|
||||||
|
|
||||||
|
For example:
|
||||||
|
gck {
|
||||||
|
compatible = "atmel,sama5d2-clk-generated";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
clocks = <&clk32k>, <&main>, <&plladiv>, <&utmi>, <&mck>, <&audio_pll_pmc>;
|
||||||
|
|
||||||
|
tcb0_gclk: tcb0_gclk {
|
||||||
|
#clock-cells = <0>;
|
||||||
|
reg = <35>;
|
||||||
|
atmel,clk-output-range = <0 83000000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_gclk: pwm_gclk {
|
||||||
|
#clock-cells = <0>;
|
||||||
|
reg = <38>;
|
||||||
|
atmel,clk-output-range = <0 83000000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
Broadcom BCM2835 CPRMAN clocks
|
||||||
|
|
||||||
|
This binding uses the common clock binding:
|
||||||
|
Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
|
||||||
|
The CPRMAN clock controller generates clocks in the audio power domain
|
||||||
|
of the BCM2835. There is a level of PLLs deriving from an external
|
||||||
|
oscillator, a level of PLL dividers that produce channels off of the
|
||||||
|
few PLLs, and a level of mostly-generic clock generators sourcing from
|
||||||
|
the PLL channels. Most other hardware components source from the
|
||||||
|
clock generators, but a few (like the ARM or HDMI) will source from
|
||||||
|
the PLL dividers directly.
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Should be "brcm,bcm2835-cprman"
|
||||||
|
- #clock-cells: Should be <1>. The permitted clock-specifier values can be
|
||||||
|
found in include/dt-bindings/clock/bcm2835.h
|
||||||
|
- reg: Specifies base physical address and size of the registers
|
||||||
|
- clocks: The external oscillator clock phandle
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
clk_osc: clock@3 {
|
||||||
|
compatible = "fixed-clock";
|
||||||
|
reg = <3>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
clock-output-names = "osc";
|
||||||
|
clock-frequency = <19200000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
clocks: cprman@7e101000 {
|
||||||
|
compatible = "brcm,bcm2835-cprman";
|
||||||
|
#clock-cells = <1>;
|
||||||
|
reg = <0x7e101000 0x2000>;
|
||||||
|
clocks = <&clk_osc>;
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c0: i2c@7e205000 {
|
||||||
|
compatible = "brcm,bcm2835-i2c";
|
||||||
|
reg = <0x7e205000 0x1000>;
|
||||||
|
interrupts = <2 21>;
|
||||||
|
clocks = <&clocks BCM2835_CLOCK_VPU>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
};
|
|
@ -130,3 +130,81 @@ These clock IDs are defined in:
|
||||||
ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED
|
ch3_unused mipipll 4 BCM_CYGNUS_MIPIPLL_CH3_UNUSED
|
||||||
ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED
|
ch4_unused mipipll 5 BCM_CYGNUS_MIPIPLL_CH4_UNUSED
|
||||||
ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED
|
ch5_unused mipipll 6 BCM_CYGNUS_MIPIPLL_CH5_UNUSED
|
||||||
|
|
||||||
|
Northstar and Northstar Plus
|
||||||
|
------
|
||||||
|
PLL and leaf clock compatible strings for Northstar and Northstar Plus are:
|
||||||
|
"brcm,nsp-armpll"
|
||||||
|
"brcm,nsp-genpll"
|
||||||
|
"brcm,nsp-lcpll0"
|
||||||
|
|
||||||
|
The following table defines the set of PLL/clock index and ID for Northstar and
|
||||||
|
Northstar Plus. These clock IDs are defined in:
|
||||||
|
"include/dt-bindings/clock/bcm-nsp.h"
|
||||||
|
|
||||||
|
Clock Source Index ID
|
||||||
|
--- ----- ----- ---------
|
||||||
|
crystal N/A N/A N/A
|
||||||
|
|
||||||
|
armpll crystal N/A N/A
|
||||||
|
|
||||||
|
genpll crystal 0 BCM_NSP_GENPLL
|
||||||
|
phy genpll 1 BCM_NSP_GENPLL_PHY_CLK
|
||||||
|
ethernetclk genpll 2 BCM_NSP_GENPLL_ENET_SW_CLK
|
||||||
|
usbclk genpll 3 BCM_NSP_GENPLL_USB_PHY_REF_CLK
|
||||||
|
iprocfast genpll 4 BCM_NSP_GENPLL_IPROCFAST_CLK
|
||||||
|
sata1 genpll 5 BCM_NSP_GENPLL_SATA1_CLK
|
||||||
|
sata2 genpll 6 BCM_NSP_GENPLL_SATA2_CLK
|
||||||
|
|
||||||
|
lcpll0 crystal 0 BCM_NSP_LCPLL0
|
||||||
|
pcie_phy lcpll0 1 BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK
|
||||||
|
sdio lcpll0 2 BCM_NSP_LCPLL0_SDIO_CLK
|
||||||
|
ddr_phy lcpll0 3 BCM_NSP_LCPLL0_DDR_PHY_CLK
|
||||||
|
|
||||||
|
Northstar 2
|
||||||
|
-----------
|
||||||
|
PLL and leaf clock compatible strings for Northstar 2 are:
|
||||||
|
"brcm,ns2-genpll-scr"
|
||||||
|
"brcm,ns2-genpll-sw"
|
||||||
|
"brcm,ns2-lcpll-ddr"
|
||||||
|
"brcm,ns2-lcpll-ports"
|
||||||
|
|
||||||
|
The following table defines the set of PLL/clock index and ID for Northstar 2.
|
||||||
|
These clock IDs are defined in:
|
||||||
|
"include/dt-bindings/clock/bcm-ns2.h"
|
||||||
|
|
||||||
|
Clock Source Index ID
|
||||||
|
--- ----- ----- ---------
|
||||||
|
crystal N/A N/A N/A
|
||||||
|
|
||||||
|
genpll_scr crystal 0 BCM_NS2_GENPLL_SCR
|
||||||
|
scr genpll_scr 1 BCM_NS2_GENPLL_SCR_SCR_CLK
|
||||||
|
fs genpll_scr 2 BCM_NS2_GENPLL_SCR_FS_CLK
|
||||||
|
audio_ref genpll_scr 3 BCM_NS2_GENPLL_SCR_AUDIO_CLK
|
||||||
|
ch3_unused genpll_scr 4 BCM_NS2_GENPLL_SCR_CH3_UNUSED
|
||||||
|
ch4_unused genpll_scr 5 BCM_NS2_GENPLL_SCR_CH4_UNUSED
|
||||||
|
ch5_unused genpll_scr 6 BCM_NS2_GENPLL_SCR_CH5_UNUSED
|
||||||
|
|
||||||
|
genpll_sw crystal 0 BCM_NS2_GENPLL_SW
|
||||||
|
rpe genpll_sw 1 BCM_NS2_GENPLL_SW_RPE_CLK
|
||||||
|
250 genpll_sw 2 BCM_NS2_GENPLL_SW_250_CLK
|
||||||
|
nic genpll_sw 3 BCM_NS2_GENPLL_SW_NIC_CLK
|
||||||
|
chimp genpll_sw 4 BCM_NS2_GENPLL_SW_CHIMP_CLK
|
||||||
|
port genpll_sw 5 BCM_NS2_GENPLL_SW_PORT_CLK
|
||||||
|
sdio genpll_sw 6 BCM_NS2_GENPLL_SW_SDIO_CLK
|
||||||
|
|
||||||
|
lcpll_ddr crystal 0 BCM_NS2_LCPLL_DDR
|
||||||
|
pcie_sata_usb lcpll_ddr 1 BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK
|
||||||
|
ddr lcpll_ddr 2 BCM_NS2_LCPLL_DDR_DDR_CLK
|
||||||
|
ch2_unused lcpll_ddr 3 BCM_NS2_LCPLL_DDR_CH2_UNUSED
|
||||||
|
ch3_unused lcpll_ddr 4 BCM_NS2_LCPLL_DDR_CH3_UNUSED
|
||||||
|
ch4_unused lcpll_ddr 5 BCM_NS2_LCPLL_DDR_CH4_UNUSED
|
||||||
|
ch5_unused lcpll_ddr 6 BCM_NS2_LCPLL_DDR_CH5_UNUSED
|
||||||
|
|
||||||
|
lcpll_ports crystal 0 BCM_NS2_LCPLL_PORTS
|
||||||
|
wan lcpll_ports 1 BCM_NS2_LCPLL_PORTS_WAN_CLK
|
||||||
|
rgmii lcpll_ports 2 BCM_NS2_LCPLL_PORTS_RGMII_CLK
|
||||||
|
ch2_unused lcpll_ports 3 BCM_NS2_LCPLL_PORTS_CH2_UNUSED
|
||||||
|
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
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
* Renesas CPG DIV6 Clock
|
* Renesas CPG DIV6 Clock
|
||||||
|
|
||||||
The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse
|
The CPG DIV6 clocks are variable factor clocks provided by the Clock Pulse
|
||||||
Generator (CPG). They clock input is divided by a configurable factor from 1
|
Generator (CPG). Their clock input is divided by a configurable factor from 1
|
||||||
to 64.
|
to 64.
|
||||||
|
|
||||||
Required Properties:
|
Required Properties:
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
* Renesas Clock Pulse Generator / Module Standby and Software Reset
|
||||||
|
|
||||||
|
On Renesas ARM SoCs (SH/R-Mobile, R-Car, RZ), the CPG (Clock Pulse Generator)
|
||||||
|
and MSSR (Module Standby and Software Reset) blocks are intimately connected,
|
||||||
|
and share the same register block.
|
||||||
|
|
||||||
|
They provide the following functionalities:
|
||||||
|
- The CPG block generates various core clocks,
|
||||||
|
- The MSSR block provides two functions:
|
||||||
|
1. Module Standby, providing a Clock Domain to control the clock supply
|
||||||
|
to individual SoC devices,
|
||||||
|
2. Reset Control, to perform a software reset of individual SoC devices.
|
||||||
|
|
||||||
|
Required Properties:
|
||||||
|
- compatible: Must be one of:
|
||||||
|
- "renesas,r8a7795-cpg-mssr" for the r8a7795 SoC
|
||||||
|
|
||||||
|
- reg: Base address and length of the memory resource used by the CPG/MSSR
|
||||||
|
block
|
||||||
|
|
||||||
|
- clocks: References to external parent clocks, one entry for each entry in
|
||||||
|
clock-names
|
||||||
|
- clock-names: List of external parent clock names. Valid names are:
|
||||||
|
- "extal" (r8a7795)
|
||||||
|
- "extalr" (r8a7795)
|
||||||
|
|
||||||
|
- #clock-cells: Must be 2
|
||||||
|
- For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
|
||||||
|
and a core clock reference, as defined in
|
||||||
|
<dt-bindings/clock/*-cpg-mssr.h>.
|
||||||
|
- For module clocks, the two clock specifier cells must be "CPG_MOD" and
|
||||||
|
a module number, as defined in the datasheet.
|
||||||
|
|
||||||
|
- #power-domain-cells: Must be 0
|
||||||
|
- SoC devices that are part of the CPG/MSSR Clock Domain and can be
|
||||||
|
power-managed through Module Standby should refer to the CPG device
|
||||||
|
node in their "power-domains" property, as documented by the generic PM
|
||||||
|
Domain bindings in
|
||||||
|
Documentation/devicetree/bindings/power/power_domain.txt.
|
||||||
|
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
- CPG device node:
|
||||||
|
|
||||||
|
cpg: clock-controller@e6150000 {
|
||||||
|
compatible = "renesas,r8a7795-cpg-mssr";
|
||||||
|
reg = <0 0xe6150000 0 0x1000>;
|
||||||
|
clocks = <&extal_clk>, <&extalr_clk>;
|
||||||
|
clock-names = "extal", "extalr";
|
||||||
|
#clock-cells = <2>;
|
||||||
|
#power-domain-cells = <0>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
- CPG/MSSR Clock Domain member device node:
|
||||||
|
|
||||||
|
scif2: serial@e6e88000 {
|
||||||
|
compatible = "renesas,scif-r8a7795", "renesas,scif";
|
||||||
|
reg = <0 0xe6e88000 0 64>;
|
||||||
|
interrupts = <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
clocks = <&cpg CPG_MOD 310>;
|
||||||
|
clock-names = "sci_ick";
|
||||||
|
dmas = <&dmac1 0x13>, <&dmac1 0x12>;
|
||||||
|
dma-names = "tx", "rx";
|
||||||
|
power-domains = <&cpg>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
|
@ -0,0 +1,24 @@
|
||||||
|
Binding for Silicon Labs 514 programmable I2C clock generator.
|
||||||
|
|
||||||
|
Reference
|
||||||
|
This binding uses the common clock binding[1]. Details about the device can be
|
||||||
|
found in the datasheet[2].
|
||||||
|
|
||||||
|
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
|
||||||
|
[2] Si514 datasheet
|
||||||
|
http://www.silabs.com/Support%20Documents/TechnicalDocs/si514.pdf
|
||||||
|
|
||||||
|
Required properties:
|
||||||
|
- compatible: Shall be "silabs,si514"
|
||||||
|
- reg: I2C device address.
|
||||||
|
- #clock-cells: From common clock bindings: Shall be 0.
|
||||||
|
|
||||||
|
Optional properties:
|
||||||
|
- clock-output-names: From common clock bindings. Recommended to be "si514".
|
||||||
|
|
||||||
|
Example:
|
||||||
|
si514: clock-generator@55 {
|
||||||
|
reg = <0x55>;
|
||||||
|
#clock-cells = <0>;
|
||||||
|
compatible = "silabs,si514";
|
||||||
|
};
|
|
@ -23,6 +23,7 @@ Required properties:
|
||||||
"st,stih407-plls-c32-a9", "st,clkgen-plls-c32"
|
"st,stih407-plls-c32-a9", "st,clkgen-plls-c32"
|
||||||
"sst,plls-c32-cx_0", "st,clkgen-plls-c32"
|
"sst,plls-c32-cx_0", "st,clkgen-plls-c32"
|
||||||
"sst,plls-c32-cx_1", "st,clkgen-plls-c32"
|
"sst,plls-c32-cx_1", "st,clkgen-plls-c32"
|
||||||
|
"st,stih418-plls-c28-a9", "st,clkgen-plls-c32"
|
||||||
|
|
||||||
"st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32"
|
"st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32"
|
||||||
"st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32"
|
"st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32"
|
||||||
|
|
|
@ -102,6 +102,9 @@ config HAVE_AT91_SMD
|
||||||
config HAVE_AT91_H32MX
|
config HAVE_AT91_H32MX
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
config HAVE_AT91_GENERATED_CLK
|
||||||
|
bool
|
||||||
|
|
||||||
config SOC_SAM_V4_V5
|
config SOC_SAM_V4_V5
|
||||||
bool
|
bool
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ config ARCH_BCM_IPROC
|
||||||
select HAVE_ARM_SCU if SMP
|
select HAVE_ARM_SCU if SMP
|
||||||
select HAVE_ARM_TWD if SMP
|
select HAVE_ARM_TWD if SMP
|
||||||
select ARM_GLOBAL_TIMER
|
select ARM_GLOBAL_TIMER
|
||||||
|
select COMMON_CLK_IPROC
|
||||||
select CLKSRC_MMIO
|
select CLKSRC_MMIO
|
||||||
select ARCH_REQUIRE_GPIOLIB
|
select ARCH_REQUIRE_GPIOLIB
|
||||||
select ARM_AMBA
|
select ARM_AMBA
|
||||||
|
|
|
@ -1353,6 +1353,7 @@ int pm_genpd_add_subdomain(struct generic_pm_domain *genpd,
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm_genpd_add_subdomain);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
|
* pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain.
|
||||||
|
@ -1400,6 +1401,7 @@ out:
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(pm_genpd_remove_subdomain);
|
||||||
|
|
||||||
/* Default device callbacks for generic PM domains. */
|
/* Default device callbacks for generic PM domains. */
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ config COMMON_CLK
|
||||||
select HAVE_CLK_PREPARE
|
select HAVE_CLK_PREPARE
|
||||||
select CLKDEV_LOOKUP
|
select CLKDEV_LOOKUP
|
||||||
select SRCU
|
select SRCU
|
||||||
|
select RATIONAL
|
||||||
---help---
|
---help---
|
||||||
The common clock framework is a single definition of struct
|
The common clock framework is a single definition of struct
|
||||||
clk, useful across many platforms, as well as an
|
clk, useful across many platforms, as well as an
|
||||||
|
@ -68,6 +69,16 @@ config COMMON_CLK_SI5351
|
||||||
This driver supports Silicon Labs 5351A/B/C programmable clock
|
This driver supports Silicon Labs 5351A/B/C programmable clock
|
||||||
generators.
|
generators.
|
||||||
|
|
||||||
|
config COMMON_CLK_SI514
|
||||||
|
tristate "Clock driver for SiLabs 514 devices"
|
||||||
|
depends on I2C
|
||||||
|
depends on OF
|
||||||
|
select REGMAP_I2C
|
||||||
|
help
|
||||||
|
---help---
|
||||||
|
This driver supports the Silicon Labs 514 programmable clock
|
||||||
|
generator.
|
||||||
|
|
||||||
config COMMON_CLK_SI570
|
config COMMON_CLK_SI570
|
||||||
tristate "Clock driver for SiLabs 570 and compatible devices"
|
tristate "Clock driver for SiLabs 570 and compatible devices"
|
||||||
depends on I2C
|
depends on I2C
|
||||||
|
@ -113,7 +124,7 @@ config CLK_TWL6040
|
||||||
|
|
||||||
config COMMON_CLK_AXI_CLKGEN
|
config COMMON_CLK_AXI_CLKGEN
|
||||||
tristate "AXI clkgen driver"
|
tristate "AXI clkgen driver"
|
||||||
depends on ARCH_ZYNQ || MICROBLAZE
|
depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
|
||||||
help
|
help
|
||||||
---help---
|
---help---
|
||||||
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
|
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
|
||||||
|
@ -121,7 +132,7 @@ config COMMON_CLK_AXI_CLKGEN
|
||||||
|
|
||||||
config CLK_QORIQ
|
config CLK_QORIQ
|
||||||
bool "Clock driver for Freescale QorIQ platforms"
|
bool "Clock driver for Freescale QorIQ platforms"
|
||||||
depends on (PPC_E500MC || ARM) && OF
|
depends on (PPC_E500MC || ARM || COMPILE_TEST) && OF
|
||||||
---help---
|
---help---
|
||||||
This adds the clock driver support for Freescale QorIQ platforms
|
This adds the clock driver support for Freescale QorIQ platforms
|
||||||
using common clock framework.
|
using common clock framework.
|
||||||
|
@ -129,13 +140,13 @@ config CLK_QORIQ
|
||||||
config COMMON_CLK_XGENE
|
config COMMON_CLK_XGENE
|
||||||
bool "Clock driver for APM XGene SoC"
|
bool "Clock driver for APM XGene SoC"
|
||||||
default y
|
default y
|
||||||
depends on ARM64
|
depends on ARM64 || COMPILE_TEST
|
||||||
---help---
|
---help---
|
||||||
Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
|
Sypport for the APM X-Gene SoC reference, PLL, and device clocks.
|
||||||
|
|
||||||
config COMMON_CLK_KEYSTONE
|
config COMMON_CLK_KEYSTONE
|
||||||
tristate "Clock drivers for Keystone based SOCs"
|
tristate "Clock drivers for Keystone based SOCs"
|
||||||
depends on ARCH_KEYSTONE && OF
|
depends on (ARCH_KEYSTONE || COMPILE_TEST) && OF
|
||||||
---help---
|
---help---
|
||||||
Supports clock drivers for Keystone based SOCs. These SOCs have local
|
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.
|
a power sleep control module that gate the clock to the IPs and PLLs.
|
||||||
|
|
|
@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-divider.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
|
obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
|
obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-gate.o
|
obj-$(CONFIG_COMMON_CLK) += clk-gate.o
|
||||||
|
obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
|
obj-$(CONFIG_COMMON_CLK) += clk-mux.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
|
obj-$(CONFIG_COMMON_CLK) += clk-composite.o
|
||||||
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
|
obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
|
||||||
|
@ -19,7 +20,6 @@ endif
|
||||||
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
obj-$(CONFIG_MACH_ASM9260) += clk-asm9260.o
|
||||||
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
|
||||||
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
|
obj-$(CONFIG_ARCH_AXXIA) += clk-axm5516.o
|
||||||
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
|
|
||||||
obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
|
obj-$(CONFIG_COMMON_CLK_CDCE706) += clk-cdce706.o
|
||||||
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
|
obj-$(CONFIG_ARCH_CLPS711X) += clk-clps711x.o
|
||||||
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
|
obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
|
||||||
|
@ -37,6 +37,7 @@ obj-$(CONFIG_CLK_QORIQ) += clk-qoriq.o
|
||||||
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
|
obj-$(CONFIG_COMMON_CLK_RK808) += clk-rk808.o
|
||||||
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
obj-$(CONFIG_COMMON_CLK_S2MPS11) += clk-s2mps11.o
|
||||||
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
obj-$(CONFIG_COMMON_CLK_SI5351) += clk-si5351.o
|
||||||
|
obj-$(CONFIG_COMMON_CLK_SI514) += clk-si514.o
|
||||||
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
obj-$(CONFIG_COMMON_CLK_SI570) += clk-si570.o
|
||||||
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
|
obj-$(CONFIG_COMMON_CLK_CDCE925) += clk-cdce925.o
|
||||||
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
|
obj-$(CONFIG_ARCH_STM32) += clk-stm32f4.o
|
||||||
|
@ -47,7 +48,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
|
||||||
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
|
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
|
||||||
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
|
obj-$(CONFIG_COMMON_CLK_PWM) += clk-pwm.o
|
||||||
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
|
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
|
||||||
obj-$(CONFIG_ARCH_BCM) += bcm/
|
obj-y += bcm/
|
||||||
obj-$(CONFIG_ARCH_BERLIN) += berlin/
|
obj-$(CONFIG_ARCH_BERLIN) += berlin/
|
||||||
obj-$(CONFIG_ARCH_HISI) += hisilicon/
|
obj-$(CONFIG_ARCH_HISI) += hisilicon/
|
||||||
obj-$(CONFIG_ARCH_MXC) += imx/
|
obj-$(CONFIG_ARCH_MXC) += imx/
|
||||||
|
|
|
@ -10,3 +10,4 @@ obj-$(CONFIG_HAVE_AT91_UTMI) += clk-utmi.o
|
||||||
obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
|
obj-$(CONFIG_HAVE_AT91_USB_CLK) += clk-usb.o
|
||||||
obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
|
obj-$(CONFIG_HAVE_AT91_SMD) += clk-smd.o
|
||||||
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
|
obj-$(CONFIG_HAVE_AT91_H32MX) += clk-h32mx.o
|
||||||
|
obj-$(CONFIG_HAVE_AT91_GENERATED_CLK) += clk-generated.o
|
||||||
|
|
|
@ -0,0 +1,306 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Atmel Corporation,
|
||||||
|
* Nicolas Ferre <nicolas.ferre@atmel.com>
|
||||||
|
*
|
||||||
|
* Based on clk-programmable & clk-peripheral drivers by Boris BREZILLON.
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/clk/at91_pmc.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
|
||||||
|
#include "pmc.h"
|
||||||
|
|
||||||
|
#define PERIPHERAL_MAX 64
|
||||||
|
#define PERIPHERAL_ID_MIN 2
|
||||||
|
|
||||||
|
#define GENERATED_SOURCE_MAX 6
|
||||||
|
#define GENERATED_MAX_DIV 255
|
||||||
|
|
||||||
|
struct clk_generated {
|
||||||
|
struct clk_hw hw;
|
||||||
|
struct at91_pmc *pmc;
|
||||||
|
struct clk_range range;
|
||||||
|
u32 id;
|
||||||
|
u32 gckdiv;
|
||||||
|
u8 parent_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define to_clk_generated(hw) \
|
||||||
|
container_of(hw, struct clk_generated, hw)
|
||||||
|
|
||||||
|
static int clk_generated_enable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
struct at91_pmc *pmc = gck->pmc;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
pr_debug("GCLK: %s, gckdiv = %d, parent id = %d\n",
|
||||||
|
__func__, gck->gckdiv, gck->parent_id);
|
||||||
|
|
||||||
|
pmc_lock(pmc);
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
|
||||||
|
tmp = pmc_read(pmc, AT91_PMC_PCR) &
|
||||||
|
~(AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK);
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_GCKCSS(gck->parent_id)
|
||||||
|
| AT91_PMC_PCR_CMD
|
||||||
|
| AT91_PMC_PCR_GCKDIV(gck->gckdiv)
|
||||||
|
| AT91_PMC_PCR_GCKEN);
|
||||||
|
pmc_unlock(pmc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clk_generated_disable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
struct at91_pmc *pmc = gck->pmc;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
pmc_lock(pmc);
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
|
||||||
|
tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_GCKEN;
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
|
||||||
|
pmc_unlock(pmc);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_generated_is_enabled(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
struct at91_pmc *pmc = gck->pmc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pmc_lock(pmc);
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
|
||||||
|
ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_GCKEN);
|
||||||
|
pmc_unlock(pmc);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
clk_generated_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
|
||||||
|
return DIV_ROUND_CLOSEST(parent_rate, gck->gckdiv + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_generated_determine_rate(struct clk_hw *hw,
|
||||||
|
struct clk_rate_request *req)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
struct clk_hw *parent = NULL;
|
||||||
|
long best_rate = -EINVAL;
|
||||||
|
unsigned long tmp_rate, min_rate;
|
||||||
|
int best_diff = -1;
|
||||||
|
int tmp_diff;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
|
||||||
|
u32 div;
|
||||||
|
unsigned long parent_rate;
|
||||||
|
|
||||||
|
parent = clk_hw_get_parent_by_index(hw, i);
|
||||||
|
if (!parent)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
parent_rate = clk_hw_get_rate(parent);
|
||||||
|
min_rate = DIV_ROUND_CLOSEST(parent_rate, GENERATED_MAX_DIV + 1);
|
||||||
|
if (!parent_rate ||
|
||||||
|
(gck->range.max && min_rate > gck->range.max))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (div = 1; div < GENERATED_MAX_DIV + 2; div++) {
|
||||||
|
tmp_rate = DIV_ROUND_CLOSEST(parent_rate, div);
|
||||||
|
tmp_diff = abs(req->rate - tmp_rate);
|
||||||
|
|
||||||
|
if (best_diff < 0 || best_diff > tmp_diff) {
|
||||||
|
best_rate = tmp_rate;
|
||||||
|
best_diff = tmp_diff;
|
||||||
|
req->best_parent_rate = parent_rate;
|
||||||
|
req->best_parent_hw = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!best_diff || tmp_rate < req->rate)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!best_diff)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n",
|
||||||
|
__func__, best_rate,
|
||||||
|
__clk_get_name((req->best_parent_hw)->clk),
|
||||||
|
req->best_parent_rate);
|
||||||
|
|
||||||
|
if (best_rate < 0)
|
||||||
|
return best_rate;
|
||||||
|
|
||||||
|
req->rate = best_rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No modification of hardware as we have the flag CLK_SET_PARENT_GATE set */
|
||||||
|
static int clk_generated_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
|
||||||
|
if (index >= clk_hw_get_num_parents(hw))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
gck->parent_id = index;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 clk_generated_get_parent(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
|
||||||
|
return gck->parent_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No modification of hardware as we have the flag CLK_SET_RATE_GATE set */
|
||||||
|
static int clk_generated_set_rate(struct clk_hw *hw,
|
||||||
|
unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck = to_clk_generated(hw);
|
||||||
|
u32 div;
|
||||||
|
|
||||||
|
if (!rate)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (gck->range.max && rate > gck->range.max)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
div = DIV_ROUND_CLOSEST(parent_rate, rate);
|
||||||
|
if (div > GENERATED_MAX_DIV + 1 || !div)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
gck->gckdiv = div - 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops generated_ops = {
|
||||||
|
.enable = clk_generated_enable,
|
||||||
|
.disable = clk_generated_disable,
|
||||||
|
.is_enabled = clk_generated_is_enabled,
|
||||||
|
.recalc_rate = clk_generated_recalc_rate,
|
||||||
|
.determine_rate = clk_generated_determine_rate,
|
||||||
|
.get_parent = clk_generated_get_parent,
|
||||||
|
.set_parent = clk_generated_set_parent,
|
||||||
|
.set_rate = clk_generated_set_rate,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* clk_generated_startup - Initialize a given clock to its default parent and
|
||||||
|
* divisor parameter.
|
||||||
|
*
|
||||||
|
* @gck: Generated clock to set the startup parameters for.
|
||||||
|
*
|
||||||
|
* Take parameters from the hardware and update local clock configuration
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
static void clk_generated_startup(struct clk_generated *gck)
|
||||||
|
{
|
||||||
|
struct at91_pmc *pmc = gck->pmc;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
pmc_lock(pmc);
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, (gck->id & AT91_PMC_PCR_PID_MASK));
|
||||||
|
tmp = pmc_read(pmc, AT91_PMC_PCR);
|
||||||
|
pmc_unlock(pmc);
|
||||||
|
|
||||||
|
gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
|
||||||
|
>> AT91_PMC_PCR_GCKCSS_OFFSET;
|
||||||
|
gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
|
||||||
|
>> AT91_PMC_PCR_GCKDIV_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clk * __init
|
||||||
|
at91_clk_register_generated(struct at91_pmc *pmc, const char *name,
|
||||||
|
const char **parent_names, u8 num_parents,
|
||||||
|
u8 id, const struct clk_range *range)
|
||||||
|
{
|
||||||
|
struct clk_generated *gck;
|
||||||
|
struct clk *clk = NULL;
|
||||||
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
gck = kzalloc(sizeof(*gck), GFP_KERNEL);
|
||||||
|
if (!gck)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &generated_ops;
|
||||||
|
init.parent_names = parent_names;
|
||||||
|
init.num_parents = num_parents;
|
||||||
|
init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;
|
||||||
|
|
||||||
|
gck->id = id;
|
||||||
|
gck->hw.init = &init;
|
||||||
|
gck->pmc = pmc;
|
||||||
|
gck->range = *range;
|
||||||
|
|
||||||
|
clk = clk_register(NULL, &gck->hw);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(gck);
|
||||||
|
else
|
||||||
|
clk_generated_startup(gck);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init of_sama5d2_clk_generated_setup(struct device_node *np,
|
||||||
|
struct at91_pmc *pmc)
|
||||||
|
{
|
||||||
|
int num;
|
||||||
|
u32 id;
|
||||||
|
const char *name;
|
||||||
|
struct clk *clk;
|
||||||
|
int num_parents;
|
||||||
|
const char *parent_names[GENERATED_SOURCE_MAX];
|
||||||
|
struct device_node *gcknp;
|
||||||
|
struct clk_range range = CLK_RANGE(0, 0);
|
||||||
|
|
||||||
|
num_parents = of_clk_get_parent_count(np);
|
||||||
|
if (num_parents <= 0 || num_parents > GENERATED_SOURCE_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
of_clk_parent_fill(np, parent_names, num_parents);
|
||||||
|
|
||||||
|
num = of_get_child_count(np);
|
||||||
|
if (!num || num > PERIPHERAL_MAX)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for_each_child_of_node(np, gcknp) {
|
||||||
|
if (of_property_read_u32(gcknp, "reg", &id))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (id < PERIPHERAL_ID_MIN || id >= PERIPHERAL_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (of_property_read_string(np, "clock-output-names", &name))
|
||||||
|
name = gcknp->name;
|
||||||
|
|
||||||
|
of_at91_get_clk_range(gcknp, "atmel,clk-output-range",
|
||||||
|
&range);
|
||||||
|
|
||||||
|
clk = at91_clk_register_generated(pmc, name, parent_names,
|
||||||
|
num_parents, id, &range);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
of_clk_add_provider(gcknp, of_clk_src_simple_get, clk);
|
||||||
|
}
|
||||||
|
}
|
|
@ -161,14 +161,18 @@ static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
|
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
|
||||||
struct at91_pmc *pmc = periph->pmc;
|
struct at91_pmc *pmc = periph->pmc;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
if (periph->id < PERIPHERAL_ID_MIN)
|
if (periph->id < PERIPHERAL_ID_MIN)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
|
pmc_lock(pmc);
|
||||||
AT91_PMC_PCR_CMD |
|
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
|
||||||
AT91_PMC_PCR_DIV(periph->div) |
|
tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_DIV_MASK;
|
||||||
AT91_PMC_PCR_EN);
|
pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_DIV(periph->div)
|
||||||
|
| AT91_PMC_PCR_CMD
|
||||||
|
| AT91_PMC_PCR_EN);
|
||||||
|
pmc_unlock(pmc);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,12 +180,16 @@ static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
|
struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
|
||||||
struct at91_pmc *pmc = periph->pmc;
|
struct at91_pmc *pmc = periph->pmc;
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
if (periph->id < PERIPHERAL_ID_MIN)
|
if (periph->id < PERIPHERAL_ID_MIN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID) |
|
pmc_lock(pmc);
|
||||||
AT91_PMC_PCR_CMD);
|
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
|
||||||
|
tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_EN;
|
||||||
|
pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
|
||||||
|
pmc_unlock(pmc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
|
static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
|
||||||
|
@ -194,7 +202,7 @@ static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
pmc_lock(pmc);
|
pmc_lock(pmc);
|
||||||
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
|
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
|
||||||
ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN);
|
ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN);
|
||||||
pmc_unlock(pmc);
|
pmc_unlock(pmc);
|
||||||
|
|
||||||
|
@ -213,7 +221,7 @@ clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
|
||||||
return parent_rate;
|
return parent_rate;
|
||||||
|
|
||||||
pmc_lock(pmc);
|
pmc_lock(pmc);
|
||||||
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID));
|
pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
|
||||||
tmp = pmc_read(pmc, AT91_PMC_PCR);
|
tmp = pmc_read(pmc, AT91_PMC_PCR);
|
||||||
pmc_unlock(pmc);
|
pmc_unlock(pmc);
|
||||||
|
|
||||||
|
|
|
@ -138,7 +138,8 @@ at91_clk_register_system(struct at91_pmc *pmc, const char *name,
|
||||||
|
|
||||||
clk = clk_register(NULL, &sys->hw);
|
clk = clk_register(NULL, &sys->hw);
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(clk)) {
|
||||||
free_irq(sys->irq, sys);
|
if (irq)
|
||||||
|
free_irq(sys->irq, sys);
|
||||||
kfree(sys);
|
kfree(sys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ static int clk_utmi_prepare(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_utmi *utmi = to_clk_utmi(hw);
|
struct clk_utmi *utmi = to_clk_utmi(hw);
|
||||||
struct at91_pmc *pmc = utmi->pmc;
|
struct at91_pmc *pmc = utmi->pmc;
|
||||||
u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) | AT91_PMC_UPLLEN |
|
u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) | AT91_PMC_UPLLEN |
|
||||||
AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN;
|
AT91_PMC_UPLLCOUNT | AT91_PMC_BIASEN;
|
||||||
|
|
||||||
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
|
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
|
||||||
|
@ -73,7 +73,7 @@ static void clk_utmi_unprepare(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_utmi *utmi = to_clk_utmi(hw);
|
struct clk_utmi *utmi = to_clk_utmi(hw);
|
||||||
struct at91_pmc *pmc = utmi->pmc;
|
struct at91_pmc *pmc = utmi->pmc;
|
||||||
u32 tmp = at91_pmc_read(AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN;
|
u32 tmp = pmc_read(pmc, AT91_CKGR_UCKR) & ~AT91_PMC_UPLLEN;
|
||||||
|
|
||||||
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
|
pmc_write(pmc, AT91_CKGR_UCKR, tmp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -206,6 +206,14 @@ static const struct at91_pmc_caps at91sam9x5_caps = {
|
||||||
AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
|
AT91_PMC_MOSCRCS | AT91_PMC_CFDEV,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct at91_pmc_caps sama5d2_caps = {
|
||||||
|
.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
|
||||||
|
AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
|
||||||
|
AT91_PMC_PCK1RDY | AT91_PMC_PCK2RDY |
|
||||||
|
AT91_PMC_MOSCSELS | AT91_PMC_MOSCRCS |
|
||||||
|
AT91_PMC_CFDEV | AT91_PMC_GCKRDY,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct at91_pmc_caps sama5d3_caps = {
|
static const struct at91_pmc_caps sama5d3_caps = {
|
||||||
.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
|
.available_irqs = AT91_PMC_MOSCS | AT91_PMC_LOCKA | AT91_PMC_MCKRDY |
|
||||||
AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
|
AT91_PMC_LOCKU | AT91_PMC_PCK0RDY |
|
||||||
|
@ -368,6 +376,12 @@ static const struct of_device_id pmc_clk_ids[] __initconst = {
|
||||||
.compatible = "atmel,sama5d4-clk-h32mx",
|
.compatible = "atmel,sama5d4-clk-h32mx",
|
||||||
.data = of_sama5d4_clk_h32mx_setup,
|
.data = of_sama5d4_clk_h32mx_setup,
|
||||||
},
|
},
|
||||||
|
#endif
|
||||||
|
#if defined(CONFIG_HAVE_AT91_GENERATED_CLK)
|
||||||
|
{
|
||||||
|
.compatible = "atmel,sama5d2-clk-generated",
|
||||||
|
.data = of_sama5d2_clk_generated_setup,
|
||||||
|
},
|
||||||
#endif
|
#endif
|
||||||
{ /*sentinel*/ }
|
{ /*sentinel*/ }
|
||||||
};
|
};
|
||||||
|
@ -436,6 +450,13 @@ static void __init of_at91sam9x5_pmc_setup(struct device_node *np)
|
||||||
CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
|
CLK_OF_DECLARE(at91sam9x5_clk_pmc, "atmel,at91sam9x5-pmc",
|
||||||
of_at91sam9x5_pmc_setup);
|
of_at91sam9x5_pmc_setup);
|
||||||
|
|
||||||
|
static void __init of_sama5d2_pmc_setup(struct device_node *np)
|
||||||
|
{
|
||||||
|
of_at91_pmc_setup(np, &sama5d2_caps);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(sama5d2_clk_pmc, "atmel,sama5d2-pmc",
|
||||||
|
of_sama5d2_pmc_setup);
|
||||||
|
|
||||||
static void __init of_sama5d3_pmc_setup(struct device_node *np)
|
static void __init of_sama5d3_pmc_setup(struct device_node *np)
|
||||||
{
|
{
|
||||||
of_at91_pmc_setup(np, &sama5d3_caps);
|
of_at91_pmc_setup(np, &sama5d3_caps);
|
||||||
|
|
|
@ -118,4 +118,7 @@ void of_at91sam9x5_clk_smd_setup(struct device_node *np,
|
||||||
void of_sama5d4_clk_h32mx_setup(struct device_node *np,
|
void of_sama5d4_clk_h32mx_setup(struct device_node *np,
|
||||||
struct at91_pmc *pmc);
|
struct at91_pmc *pmc);
|
||||||
|
|
||||||
|
void of_sama5d2_clk_generated_setup(struct device_node *np,
|
||||||
|
struct at91_pmc *pmc);
|
||||||
|
|
||||||
#endif /* __PMC_H_ */
|
#endif /* __PMC_H_ */
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
config CLK_BCM_KONA
|
config CLK_BCM_KONA
|
||||||
bool "Broadcom Kona CCU clock support"
|
bool "Broadcom Kona CCU clock support"
|
||||||
depends on ARCH_BCM_MOBILE
|
depends on ARCH_BCM_MOBILE || COMPILE_TEST
|
||||||
depends on COMMON_CLK
|
depends on COMMON_CLK
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
|
@ -9,10 +9,8 @@ config CLK_BCM_KONA
|
||||||
in the BCM281xx and BCM21664 families.
|
in the BCM281xx and BCM21664 families.
|
||||||
|
|
||||||
config COMMON_CLK_IPROC
|
config COMMON_CLK_IPROC
|
||||||
bool "Broadcom iProc clock support"
|
bool
|
||||||
depends on ARCH_BCM_IPROC
|
|
||||||
depends on COMMON_CLK
|
depends on COMMON_CLK
|
||||||
default ARCH_BCM_IPROC
|
|
||||||
help
|
help
|
||||||
Enable common clock framework support for Broadcom SoCs
|
Enable common clock framework support for Broadcom SoCs
|
||||||
based on the iProc architecture
|
based on the iProc architecture
|
||||||
|
|
|
@ -3,4 +3,8 @@ obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
|
||||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
|
||||||
obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm21664.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_COMMON_CLK_IPROC) += clk-iproc-armpll.o clk-iproc-pll.o clk-iproc-asiu.o
|
||||||
|
obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o
|
||||||
|
obj-$(CONFIG_COMMON_CLK_IPROC) += clk-ns2.o
|
||||||
obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
|
obj-$(CONFIG_ARCH_BCM_CYGNUS) += clk-cygnus.o
|
||||||
|
obj-$(CONFIG_ARCH_BCM_NSP) += clk-nsp.o
|
||||||
|
obj-$(CONFIG_ARCH_BCM_5301X) += clk-nsp.o
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,28 +23,30 @@
|
||||||
#include <dt-bindings/clock/bcm-cygnus.h>
|
#include <dt-bindings/clock/bcm-cygnus.h>
|
||||||
#include "clk-iproc.h"
|
#include "clk-iproc.h"
|
||||||
|
|
||||||
#define reg_val(o, s, w) { .offset = o, .shift = s, .width = w, }
|
#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
|
||||||
|
|
||||||
#define aon_val(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
|
#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
|
||||||
.pwr_shift = ps, .iso_shift = is }
|
.pwr_shift = ps, .iso_shift = is }
|
||||||
|
|
||||||
#define sw_ctrl_val(o, s) { .offset = o, .shift = s, }
|
#define SW_CTRL_VAL(o, s) { .offset = o, .shift = s, }
|
||||||
|
|
||||||
#define asiu_div_val(o, es, hs, hw, ls, lw) \
|
#define ASIU_DIV_VAL(o, es, hs, hw, ls, lw) \
|
||||||
{ .offset = o, .en_shift = es, .high_shift = hs, \
|
{ .offset = o, .en_shift = es, .high_shift = hs, \
|
||||||
.high_width = hw, .low_shift = ls, .low_width = lw }
|
.high_width = hw, .low_shift = ls, .low_width = lw }
|
||||||
|
|
||||||
#define reset_val(o, rs, prs, kis, kiw, kps, kpw, kas, kaw) { .offset = o, \
|
#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
|
||||||
.reset_shift = rs, .p_reset_shift = prs, .ki_shift = kis, \
|
.p_reset_shift = prs }
|
||||||
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
|
|
||||||
|
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
|
||||||
|
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
|
||||||
.ka_width = kaw }
|
.ka_width = kaw }
|
||||||
|
|
||||||
#define vco_ctrl_val(uo, lo) { .u_offset = uo, .l_offset = lo }
|
#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
|
||||||
|
|
||||||
#define enable_val(o, es, hs, bs) { .offset = o, .enable_shift = es, \
|
#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
|
||||||
.hold_shift = hs, .bypass_shift = bs }
|
.hold_shift = hs, .bypass_shift = bs }
|
||||||
|
|
||||||
#define asiu_gate_val(o, es) { .offset = o, .en_shift = es }
|
#define ASIU_GATE_VAL(o, es) { .offset = o, .en_shift = es }
|
||||||
|
|
||||||
static void __init cygnus_armpll_init(struct device_node *node)
|
static void __init cygnus_armpll_init(struct device_node *node)
|
||||||
{
|
{
|
||||||
|
@ -55,52 +57,53 @@ CLK_OF_DECLARE(cygnus_armpll, "brcm,cygnus-armpll", cygnus_armpll_init);
|
||||||
static const struct iproc_pll_ctrl genpll = {
|
static const struct iproc_pll_ctrl genpll = {
|
||||||
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
|
||||||
IPROC_CLK_PLL_NEEDS_SW_CFG,
|
IPROC_CLK_PLL_NEEDS_SW_CFG,
|
||||||
.aon = aon_val(0x0, 2, 1, 0),
|
.aon = AON_VAL(0x0, 2, 1, 0),
|
||||||
.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 3),
|
.reset = RESET_VAL(0x0, 11, 10),
|
||||||
.sw_ctrl = sw_ctrl_val(0x10, 31),
|
.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
|
||||||
.ndiv_int = reg_val(0x10, 20, 10),
|
.sw_ctrl = SW_CTRL_VAL(0x10, 31),
|
||||||
.ndiv_frac = reg_val(0x10, 0, 20),
|
.ndiv_int = REG_VAL(0x10, 20, 10),
|
||||||
.pdiv = reg_val(0x14, 0, 4),
|
.ndiv_frac = REG_VAL(0x10, 0, 20),
|
||||||
.vco_ctrl = vco_ctrl_val(0x18, 0x1c),
|
.pdiv = REG_VAL(0x14, 0, 4),
|
||||||
.status = reg_val(0x28, 12, 1),
|
.vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
|
||||||
|
.status = REG_VAL(0x28, 12, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iproc_clk_ctrl genpll_clk[] = {
|
static const struct iproc_clk_ctrl genpll_clk[] = {
|
||||||
[BCM_CYGNUS_GENPLL_AXI21_CLK] = {
|
[BCM_CYGNUS_GENPLL_AXI21_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
|
.channel = BCM_CYGNUS_GENPLL_AXI21_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 6, 0, 12),
|
.enable = ENABLE_VAL(0x4, 6, 0, 12),
|
||||||
.mdiv = reg_val(0x20, 0, 8),
|
.mdiv = REG_VAL(0x20, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
|
[BCM_CYGNUS_GENPLL_250MHZ_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
|
.channel = BCM_CYGNUS_GENPLL_250MHZ_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 7, 1, 13),
|
.enable = ENABLE_VAL(0x4, 7, 1, 13),
|
||||||
.mdiv = reg_val(0x20, 10, 8),
|
.mdiv = REG_VAL(0x20, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
|
[BCM_CYGNUS_GENPLL_IHOST_SYS_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
|
.channel = BCM_CYGNUS_GENPLL_IHOST_SYS_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 8, 2, 14),
|
.enable = ENABLE_VAL(0x4, 8, 2, 14),
|
||||||
.mdiv = reg_val(0x20, 20, 8),
|
.mdiv = REG_VAL(0x20, 20, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
|
[BCM_CYGNUS_GENPLL_ENET_SW_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
|
.channel = BCM_CYGNUS_GENPLL_ENET_SW_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 9, 3, 15),
|
.enable = ENABLE_VAL(0x4, 9, 3, 15),
|
||||||
.mdiv = reg_val(0x24, 0, 8),
|
.mdiv = REG_VAL(0x24, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
|
[BCM_CYGNUS_GENPLL_AUDIO_125_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
|
.channel = BCM_CYGNUS_GENPLL_AUDIO_125_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 10, 4, 16),
|
.enable = ENABLE_VAL(0x4, 10, 4, 16),
|
||||||
.mdiv = reg_val(0x24, 10, 8),
|
.mdiv = REG_VAL(0x24, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_GENPLL_CAN_CLK] = {
|
[BCM_CYGNUS_GENPLL_CAN_CLK] = {
|
||||||
.channel = BCM_CYGNUS_GENPLL_CAN_CLK,
|
.channel = BCM_CYGNUS_GENPLL_CAN_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x4, 11, 5, 17),
|
.enable = ENABLE_VAL(0x4, 11, 5, 17),
|
||||||
.mdiv = reg_val(0x24, 20, 8),
|
.mdiv = REG_VAL(0x24, 20, 8),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -113,51 +116,52 @@ CLK_OF_DECLARE(cygnus_genpll, "brcm,cygnus-genpll", cygnus_genpll_clk_init);
|
||||||
|
|
||||||
static const struct iproc_pll_ctrl lcpll0 = {
|
static const struct iproc_pll_ctrl lcpll0 = {
|
||||||
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_NEEDS_SW_CFG,
|
||||||
.aon = aon_val(0x0, 2, 5, 4),
|
.aon = AON_VAL(0x0, 2, 5, 4),
|
||||||
.reset = reset_val(0x0, 31, 30, 27, 3, 23, 4, 19, 4),
|
.reset = RESET_VAL(0x0, 31, 30),
|
||||||
.sw_ctrl = sw_ctrl_val(0x4, 31),
|
.dig_filter = DF_VAL(0x0, 27, 3, 23, 4, 19, 4),
|
||||||
.ndiv_int = reg_val(0x4, 16, 10),
|
.sw_ctrl = SW_CTRL_VAL(0x4, 31),
|
||||||
.pdiv = reg_val(0x4, 26, 4),
|
.ndiv_int = REG_VAL(0x4, 16, 10),
|
||||||
.vco_ctrl = vco_ctrl_val(0x10, 0x14),
|
.pdiv = REG_VAL(0x4, 26, 4),
|
||||||
.status = reg_val(0x18, 12, 1),
|
.vco_ctrl = VCO_CTRL_VAL(0x10, 0x14),
|
||||||
|
.status = REG_VAL(0x18, 12, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iproc_clk_ctrl lcpll0_clk[] = {
|
static const struct iproc_clk_ctrl lcpll0_clk[] = {
|
||||||
[BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
|
[BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
|
.channel = BCM_CYGNUS_LCPLL0_PCIE_PHY_REF_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 7, 1, 13),
|
.enable = ENABLE_VAL(0x0, 7, 1, 13),
|
||||||
.mdiv = reg_val(0x8, 0, 8),
|
.mdiv = REG_VAL(0x8, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
|
[BCM_CYGNUS_LCPLL0_DDR_PHY_CLK] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
|
.channel = BCM_CYGNUS_LCPLL0_DDR_PHY_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 8, 2, 14),
|
.enable = ENABLE_VAL(0x0, 8, 2, 14),
|
||||||
.mdiv = reg_val(0x8, 10, 8),
|
.mdiv = REG_VAL(0x8, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
|
[BCM_CYGNUS_LCPLL0_SDIO_CLK] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
|
.channel = BCM_CYGNUS_LCPLL0_SDIO_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 9, 3, 15),
|
.enable = ENABLE_VAL(0x0, 9, 3, 15),
|
||||||
.mdiv = reg_val(0x8, 20, 8),
|
.mdiv = REG_VAL(0x8, 20, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
|
[BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
|
.channel = BCM_CYGNUS_LCPLL0_USB_PHY_REF_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 10, 4, 16),
|
.enable = ENABLE_VAL(0x0, 10, 4, 16),
|
||||||
.mdiv = reg_val(0xc, 0, 8),
|
.mdiv = REG_VAL(0xc, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
|
[BCM_CYGNUS_LCPLL0_SMART_CARD_CLK] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
|
.channel = BCM_CYGNUS_LCPLL0_SMART_CARD_CLK,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 11, 5, 17),
|
.enable = ENABLE_VAL(0x0, 11, 5, 17),
|
||||||
.mdiv = reg_val(0xc, 10, 8),
|
.mdiv = REG_VAL(0xc, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
|
[BCM_CYGNUS_LCPLL0_CH5_UNUSED] = {
|
||||||
.channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
|
.channel = BCM_CYGNUS_LCPLL0_CH5_UNUSED,
|
||||||
.flags = IPROC_CLK_AON,
|
.flags = IPROC_CLK_AON,
|
||||||
.enable = enable_val(0x0, 12, 6, 18),
|
.enable = ENABLE_VAL(0x0, 12, 6, 18),
|
||||||
.mdiv = reg_val(0xc, 20, 8),
|
.mdiv = REG_VAL(0xc, 20, 8),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -189,52 +193,53 @@ static const struct iproc_pll_vco_param mipipll_vco_params[] = {
|
||||||
static const struct iproc_pll_ctrl mipipll = {
|
static const struct iproc_pll_ctrl mipipll = {
|
||||||
.flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
|
.flags = IPROC_CLK_PLL_ASIU | IPROC_CLK_PLL_HAS_NDIV_FRAC |
|
||||||
IPROC_CLK_NEEDS_READ_BACK,
|
IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.aon = aon_val(0x0, 4, 17, 16),
|
.aon = AON_VAL(0x0, 4, 17, 16),
|
||||||
.asiu = asiu_gate_val(0x0, 3),
|
.asiu = ASIU_GATE_VAL(0x0, 3),
|
||||||
.reset = reset_val(0x0, 11, 10, 4, 3, 0, 4, 7, 4),
|
.reset = RESET_VAL(0x0, 11, 10),
|
||||||
.ndiv_int = reg_val(0x10, 20, 10),
|
.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 4),
|
||||||
.ndiv_frac = reg_val(0x10, 0, 20),
|
.ndiv_int = REG_VAL(0x10, 20, 10),
|
||||||
.pdiv = reg_val(0x14, 0, 4),
|
.ndiv_frac = REG_VAL(0x10, 0, 20),
|
||||||
.vco_ctrl = vco_ctrl_val(0x18, 0x1c),
|
.pdiv = REG_VAL(0x14, 0, 4),
|
||||||
.status = reg_val(0x28, 12, 1),
|
.vco_ctrl = VCO_CTRL_VAL(0x18, 0x1c),
|
||||||
|
.status = REG_VAL(0x28, 12, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iproc_clk_ctrl mipipll_clk[] = {
|
static const struct iproc_clk_ctrl mipipll_clk[] = {
|
||||||
[BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
|
[BCM_CYGNUS_MIPIPLL_CH0_UNUSED] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
|
.channel = BCM_CYGNUS_MIPIPLL_CH0_UNUSED,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 12, 6, 18),
|
.enable = ENABLE_VAL(0x4, 12, 6, 18),
|
||||||
.mdiv = reg_val(0x20, 0, 8),
|
.mdiv = REG_VAL(0x20, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
|
[BCM_CYGNUS_MIPIPLL_CH1_LCD] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
|
.channel = BCM_CYGNUS_MIPIPLL_CH1_LCD,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 13, 7, 19),
|
.enable = ENABLE_VAL(0x4, 13, 7, 19),
|
||||||
.mdiv = reg_val(0x20, 10, 8),
|
.mdiv = REG_VAL(0x20, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
|
[BCM_CYGNUS_MIPIPLL_CH2_V3D] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
|
.channel = BCM_CYGNUS_MIPIPLL_CH2_V3D,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 14, 8, 20),
|
.enable = ENABLE_VAL(0x4, 14, 8, 20),
|
||||||
.mdiv = reg_val(0x20, 20, 8),
|
.mdiv = REG_VAL(0x20, 20, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
|
[BCM_CYGNUS_MIPIPLL_CH3_UNUSED] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
|
.channel = BCM_CYGNUS_MIPIPLL_CH3_UNUSED,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 15, 9, 21),
|
.enable = ENABLE_VAL(0x4, 15, 9, 21),
|
||||||
.mdiv = reg_val(0x24, 0, 8),
|
.mdiv = REG_VAL(0x24, 0, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
|
[BCM_CYGNUS_MIPIPLL_CH4_UNUSED] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
|
.channel = BCM_CYGNUS_MIPIPLL_CH4_UNUSED,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 16, 10, 22),
|
.enable = ENABLE_VAL(0x4, 16, 10, 22),
|
||||||
.mdiv = reg_val(0x24, 10, 8),
|
.mdiv = REG_VAL(0x24, 10, 8),
|
||||||
},
|
},
|
||||||
[BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
|
[BCM_CYGNUS_MIPIPLL_CH5_UNUSED] = {
|
||||||
.channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
|
.channel = BCM_CYGNUS_MIPIPLL_CH5_UNUSED,
|
||||||
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
.flags = IPROC_CLK_NEEDS_READ_BACK,
|
||||||
.enable = enable_val(0x4, 17, 11, 23),
|
.enable = ENABLE_VAL(0x4, 17, 11, 23),
|
||||||
.mdiv = reg_val(0x24, 20, 8),
|
.mdiv = REG_VAL(0x24, 20, 8),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -247,15 +252,15 @@ static void __init cygnus_mipipll_clk_init(struct device_node *node)
|
||||||
CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
|
CLK_OF_DECLARE(cygnus_mipipll, "brcm,cygnus-mipipll", cygnus_mipipll_clk_init);
|
||||||
|
|
||||||
static const struct iproc_asiu_div asiu_div[] = {
|
static const struct iproc_asiu_div asiu_div[] = {
|
||||||
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_div_val(0x0, 31, 16, 10, 0, 10),
|
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_DIV_VAL(0x0, 31, 16, 10, 0, 10),
|
||||||
[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_div_val(0x4, 31, 16, 10, 0, 10),
|
[BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_DIV_VAL(0x4, 31, 16, 10, 0, 10),
|
||||||
[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_div_val(0x8, 31, 16, 10, 0, 10),
|
[BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_DIV_VAL(0x8, 31, 16, 10, 0, 10),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct iproc_asiu_gate asiu_gate[] = {
|
static const struct iproc_asiu_gate asiu_gate[] = {
|
||||||
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = asiu_gate_val(0x0, 7),
|
[BCM_CYGNUS_ASIU_KEYPAD_CLK] = ASIU_GATE_VAL(0x0, 7),
|
||||||
[BCM_CYGNUS_ASIU_ADC_CLK] = asiu_gate_val(0x0, 9),
|
[BCM_CYGNUS_ASIU_ADC_CLK] = ASIU_GATE_VAL(0x0, 9),
|
||||||
[BCM_CYGNUS_ASIU_PWM_CLK] = asiu_gate_val(IPROC_CLK_INVALID_OFFSET, 0),
|
[BCM_CYGNUS_ASIU_PWM_CLK] = ASIU_GATE_VAL(IPROC_CLK_INVALID_OFFSET, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static void __init cygnus_asiu_init(struct device_node *node)
|
static void __init cygnus_asiu_init(struct device_node *node)
|
||||||
|
|
|
@ -74,7 +74,8 @@ struct iproc_clk {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iproc_pll {
|
struct iproc_pll {
|
||||||
void __iomem *pll_base;
|
void __iomem *status_base;
|
||||||
|
void __iomem *control_base;
|
||||||
void __iomem *pwr_base;
|
void __iomem *pwr_base;
|
||||||
void __iomem *asiu_base;
|
void __iomem *asiu_base;
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
|
|
||||||
for (i = 0; i < LOCK_DELAY; i++) {
|
for (i = 0; i < LOCK_DELAY; i++) {
|
||||||
u32 val = readl(pll->pll_base + ctrl->status.offset);
|
u32 val = readl(pll->status_base + ctrl->status.offset);
|
||||||
|
|
||||||
if (val & (1 << ctrl->status.shift))
|
if (val & (1 << ctrl->status.shift))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -137,6 +138,18 @@ static int pll_wait_for_lock(struct iproc_pll *pll)
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void iproc_pll_write(const struct iproc_pll *pll, void __iomem *base,
|
||||||
|
const u32 offset, u32 val)
|
||||||
|
{
|
||||||
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
|
|
||||||
|
writel(val, base + offset);
|
||||||
|
|
||||||
|
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK &&
|
||||||
|
(base == pll->status_base || base == pll->control_base)))
|
||||||
|
val = readl(base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
static void __pll_disable(struct iproc_pll *pll)
|
static void __pll_disable(struct iproc_pll *pll)
|
||||||
{
|
{
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
|
@ -145,17 +158,25 @@ static void __pll_disable(struct iproc_pll *pll)
|
||||||
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
||||||
val = readl(pll->asiu_base + ctrl->asiu.offset);
|
val = readl(pll->asiu_base + ctrl->asiu.offset);
|
||||||
val &= ~(1 << ctrl->asiu.en_shift);
|
val &= ~(1 << ctrl->asiu.en_shift);
|
||||||
writel(val, pll->asiu_base + ctrl->asiu.offset);
|
iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* latch input value so core power can be shut down */
|
if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
|
||||||
val = readl(pll->pwr_base + ctrl->aon.offset);
|
val = readl(pll->control_base + ctrl->aon.offset);
|
||||||
val |= (1 << ctrl->aon.iso_shift);
|
val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
|
||||||
writel(val, pll->pwr_base + ctrl->aon.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* power down the core */
|
if (pll->pwr_base) {
|
||||||
val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
|
/* latch input value so core power can be shut down */
|
||||||
writel(val, pll->pwr_base + ctrl->aon.offset);
|
val = readl(pll->pwr_base + ctrl->aon.offset);
|
||||||
|
val |= 1 << ctrl->aon.iso_shift;
|
||||||
|
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
|
||||||
|
|
||||||
|
/* power down the core */
|
||||||
|
val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
|
||||||
|
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __pll_enable(struct iproc_pll *pll)
|
static int __pll_enable(struct iproc_pll *pll)
|
||||||
|
@ -163,17 +184,25 @@ static int __pll_enable(struct iproc_pll *pll)
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* power up the PLL and make sure it's not latched */
|
if (ctrl->flags & IPROC_CLK_EMBED_PWRCTRL) {
|
||||||
val = readl(pll->pwr_base + ctrl->aon.offset);
|
val = readl(pll->control_base + ctrl->aon.offset);
|
||||||
val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
|
val &= ~(bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift);
|
||||||
val &= ~(1 << ctrl->aon.iso_shift);
|
iproc_pll_write(pll, pll->control_base, ctrl->aon.offset, val);
|
||||||
writel(val, pll->pwr_base + ctrl->aon.offset);
|
}
|
||||||
|
|
||||||
|
if (pll->pwr_base) {
|
||||||
|
/* power up the PLL and make sure it's not latched */
|
||||||
|
val = readl(pll->pwr_base + ctrl->aon.offset);
|
||||||
|
val |= bit_mask(ctrl->aon.pwr_width) << ctrl->aon.pwr_shift;
|
||||||
|
val &= ~(1 << ctrl->aon.iso_shift);
|
||||||
|
iproc_pll_write(pll, pll->pwr_base, ctrl->aon.offset, val);
|
||||||
|
}
|
||||||
|
|
||||||
/* certain PLLs also need to be ungated from the ASIU top level */
|
/* certain PLLs also need to be ungated from the ASIU top level */
|
||||||
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
if (ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
||||||
val = readl(pll->asiu_base + ctrl->asiu.offset);
|
val = readl(pll->asiu_base + ctrl->asiu.offset);
|
||||||
val |= (1 << ctrl->asiu.en_shift);
|
val |= (1 << ctrl->asiu.en_shift);
|
||||||
writel(val, pll->asiu_base + ctrl->asiu.offset);
|
iproc_pll_write(pll, pll->asiu_base, ctrl->asiu.offset, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -185,11 +214,9 @@ static void __pll_put_in_reset(struct iproc_pll *pll)
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
|
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
|
||||||
|
|
||||||
val = readl(pll->pll_base + reset->offset);
|
val = readl(pll->control_base + reset->offset);
|
||||||
val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
|
val &= ~(1 << reset->reset_shift | 1 << reset->p_reset_shift);
|
||||||
writel(val, pll->pll_base + reset->offset);
|
iproc_pll_write(pll, pll->control_base, reset->offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + reset->offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
|
static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
|
||||||
|
@ -198,17 +225,19 @@ static void __pll_bring_out_reset(struct iproc_pll *pll, unsigned int kp,
|
||||||
u32 val;
|
u32 val;
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
|
const struct iproc_pll_reset_ctrl *reset = &ctrl->reset;
|
||||||
|
const struct iproc_pll_dig_filter_ctrl *dig_filter = &ctrl->dig_filter;
|
||||||
|
|
||||||
val = readl(pll->pll_base + reset->offset);
|
val = readl(pll->control_base + dig_filter->offset);
|
||||||
val &= ~(bit_mask(reset->ki_width) << reset->ki_shift |
|
val &= ~(bit_mask(dig_filter->ki_width) << dig_filter->ki_shift |
|
||||||
bit_mask(reset->kp_width) << reset->kp_shift |
|
bit_mask(dig_filter->kp_width) << dig_filter->kp_shift |
|
||||||
bit_mask(reset->ka_width) << reset->ka_shift);
|
bit_mask(dig_filter->ka_width) << dig_filter->ka_shift);
|
||||||
val |= ki << reset->ki_shift | kp << reset->kp_shift |
|
val |= ki << dig_filter->ki_shift | kp << dig_filter->kp_shift |
|
||||||
ka << reset->ka_shift;
|
ka << dig_filter->ka_shift;
|
||||||
|
iproc_pll_write(pll, pll->control_base, dig_filter->offset, val);
|
||||||
|
|
||||||
|
val = readl(pll->control_base + reset->offset);
|
||||||
val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
|
val |= 1 << reset->reset_shift | 1 << reset->p_reset_shift;
|
||||||
writel(val, pll->pll_base + reset->offset);
|
iproc_pll_write(pll, pll->control_base, reset->offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + reset->offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
|
static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
|
||||||
|
@ -263,10 +292,9 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
|
||||||
/* put PLL in reset */
|
/* put PLL in reset */
|
||||||
__pll_put_in_reset(pll);
|
__pll_put_in_reset(pll);
|
||||||
|
|
||||||
writel(0, pll->pll_base + ctrl->vco_ctrl.u_offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.u_offset, 0);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->vco_ctrl.u_offset);
|
val = readl(pll->control_base + ctrl->vco_ctrl.l_offset);
|
||||||
val = readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
|
|
||||||
|
|
||||||
if (rate >= VCO_LOW && rate < VCO_MID)
|
if (rate >= VCO_LOW && rate < VCO_MID)
|
||||||
val |= (1 << PLL_VCO_LOW_SHIFT);
|
val |= (1 << PLL_VCO_LOW_SHIFT);
|
||||||
|
@ -276,36 +304,29 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
|
||||||
else
|
else
|
||||||
val |= (1 << PLL_VCO_HIGH_SHIFT);
|
val |= (1 << PLL_VCO_HIGH_SHIFT);
|
||||||
|
|
||||||
writel(val, pll->pll_base + ctrl->vco_ctrl.l_offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->vco_ctrl.l_offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->vco_ctrl.l_offset);
|
|
||||||
|
|
||||||
/* program integer part of NDIV */
|
/* program integer part of NDIV */
|
||||||
val = readl(pll->pll_base + ctrl->ndiv_int.offset);
|
val = readl(pll->control_base + ctrl->ndiv_int.offset);
|
||||||
val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
|
val &= ~(bit_mask(ctrl->ndiv_int.width) << ctrl->ndiv_int.shift);
|
||||||
val |= vco->ndiv_int << ctrl->ndiv_int.shift;
|
val |= vco->ndiv_int << ctrl->ndiv_int.shift;
|
||||||
writel(val, pll->pll_base + ctrl->ndiv_int.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->ndiv_int.offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->ndiv_int.offset);
|
|
||||||
|
|
||||||
/* program fractional part of NDIV */
|
/* program fractional part of NDIV */
|
||||||
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
|
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
|
||||||
val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
|
val = readl(pll->control_base + ctrl->ndiv_frac.offset);
|
||||||
val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
|
val &= ~(bit_mask(ctrl->ndiv_frac.width) <<
|
||||||
ctrl->ndiv_frac.shift);
|
ctrl->ndiv_frac.shift);
|
||||||
val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
|
val |= vco->ndiv_frac << ctrl->ndiv_frac.shift;
|
||||||
writel(val, pll->pll_base + ctrl->ndiv_frac.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->ndiv_frac.offset,
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
val);
|
||||||
readl(pll->pll_base + ctrl->ndiv_frac.offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* program PDIV */
|
/* program PDIV */
|
||||||
val = readl(pll->pll_base + ctrl->pdiv.offset);
|
val = readl(pll->control_base + ctrl->pdiv.offset);
|
||||||
val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
|
val &= ~(bit_mask(ctrl->pdiv.width) << ctrl->pdiv.shift);
|
||||||
val |= vco->pdiv << ctrl->pdiv.shift;
|
val |= vco->pdiv << ctrl->pdiv.shift;
|
||||||
writel(val, pll->pll_base + ctrl->pdiv.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->pdiv.offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->pdiv.offset);
|
|
||||||
|
|
||||||
__pll_bring_out_reset(pll, kp, ka, ki);
|
__pll_bring_out_reset(pll, kp, ka, ki);
|
||||||
|
|
||||||
|
@ -345,14 +366,14 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
|
||||||
struct iproc_pll *pll = clk->pll;
|
struct iproc_pll *pll = clk->pll;
|
||||||
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
const struct iproc_pll_ctrl *ctrl = pll->ctrl;
|
||||||
u32 val;
|
u32 val;
|
||||||
u64 ndiv;
|
u64 ndiv, ndiv_int, ndiv_frac;
|
||||||
unsigned int ndiv_int, ndiv_frac, pdiv;
|
unsigned int pdiv;
|
||||||
|
|
||||||
if (parent_rate == 0)
|
if (parent_rate == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* PLL needs to be locked */
|
/* PLL needs to be locked */
|
||||||
val = readl(pll->pll_base + ctrl->status.offset);
|
val = readl(pll->status_base + ctrl->status.offset);
|
||||||
if ((val & (1 << ctrl->status.shift)) == 0) {
|
if ((val & (1 << ctrl->status.shift)) == 0) {
|
||||||
clk->rate = 0;
|
clk->rate = 0;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -363,25 +384,22 @@ static unsigned long iproc_pll_recalc_rate(struct clk_hw *hw,
|
||||||
*
|
*
|
||||||
* ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
|
* ((ndiv_int + ndiv_frac / 2^20) * (parent clock rate / pdiv)
|
||||||
*/
|
*/
|
||||||
val = readl(pll->pll_base + ctrl->ndiv_int.offset);
|
val = readl(pll->control_base + ctrl->ndiv_int.offset);
|
||||||
ndiv_int = (val >> ctrl->ndiv_int.shift) &
|
ndiv_int = (val >> ctrl->ndiv_int.shift) &
|
||||||
bit_mask(ctrl->ndiv_int.width);
|
bit_mask(ctrl->ndiv_int.width);
|
||||||
ndiv = (u64)ndiv_int << ctrl->ndiv_int.shift;
|
ndiv = ndiv_int << 20;
|
||||||
|
|
||||||
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
|
if (ctrl->flags & IPROC_CLK_PLL_HAS_NDIV_FRAC) {
|
||||||
val = readl(pll->pll_base + ctrl->ndiv_frac.offset);
|
val = readl(pll->control_base + ctrl->ndiv_frac.offset);
|
||||||
ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
|
ndiv_frac = (val >> ctrl->ndiv_frac.shift) &
|
||||||
bit_mask(ctrl->ndiv_frac.width);
|
bit_mask(ctrl->ndiv_frac.width);
|
||||||
|
ndiv += ndiv_frac;
|
||||||
if (ndiv_frac != 0)
|
|
||||||
ndiv = ((u64)ndiv_int << ctrl->ndiv_int.shift) |
|
|
||||||
ndiv_frac;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val = readl(pll->pll_base + ctrl->pdiv.offset);
|
val = readl(pll->control_base + ctrl->pdiv.offset);
|
||||||
pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
|
pdiv = (val >> ctrl->pdiv.shift) & bit_mask(ctrl->pdiv.width);
|
||||||
|
|
||||||
clk->rate = (ndiv * parent_rate) >> ctrl->ndiv_int.shift;
|
clk->rate = (ndiv * parent_rate) >> 20;
|
||||||
|
|
||||||
if (pdiv == 0)
|
if (pdiv == 0)
|
||||||
clk->rate *= 2;
|
clk->rate *= 2;
|
||||||
|
@ -443,16 +461,14 @@ static int iproc_clk_enable(struct clk_hw *hw)
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
/* channel enable is active low */
|
/* channel enable is active low */
|
||||||
val = readl(pll->pll_base + ctrl->enable.offset);
|
val = readl(pll->control_base + ctrl->enable.offset);
|
||||||
val &= ~(1 << ctrl->enable.enable_shift);
|
val &= ~(1 << ctrl->enable.enable_shift);
|
||||||
writel(val, pll->pll_base + ctrl->enable.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
|
||||||
|
|
||||||
/* also make sure channel is not held */
|
/* also make sure channel is not held */
|
||||||
val = readl(pll->pll_base + ctrl->enable.offset);
|
val = readl(pll->control_base + ctrl->enable.offset);
|
||||||
val &= ~(1 << ctrl->enable.hold_shift);
|
val &= ~(1 << ctrl->enable.hold_shift);
|
||||||
writel(val, pll->pll_base + ctrl->enable.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->enable.offset);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -467,11 +483,9 @@ static void iproc_clk_disable(struct clk_hw *hw)
|
||||||
if (ctrl->flags & IPROC_CLK_AON)
|
if (ctrl->flags & IPROC_CLK_AON)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
val = readl(pll->pll_base + ctrl->enable.offset);
|
val = readl(pll->control_base + ctrl->enable.offset);
|
||||||
val |= 1 << ctrl->enable.enable_shift;
|
val |= 1 << ctrl->enable.enable_shift;
|
||||||
writel(val, pll->pll_base + ctrl->enable.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->enable.offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->enable.offset);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
|
static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
|
||||||
|
@ -486,7 +500,7 @@ static unsigned long iproc_clk_recalc_rate(struct clk_hw *hw,
|
||||||
if (parent_rate == 0)
|
if (parent_rate == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
val = readl(pll->pll_base + ctrl->mdiv.offset);
|
val = readl(pll->control_base + ctrl->mdiv.offset);
|
||||||
mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
|
mdiv = (val >> ctrl->mdiv.shift) & bit_mask(ctrl->mdiv.width);
|
||||||
if (mdiv == 0)
|
if (mdiv == 0)
|
||||||
mdiv = 256;
|
mdiv = 256;
|
||||||
|
@ -533,16 +547,14 @@ static int iproc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
if (div > 256)
|
if (div > 256)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
val = readl(pll->pll_base + ctrl->mdiv.offset);
|
val = readl(pll->control_base + ctrl->mdiv.offset);
|
||||||
if (div == 256) {
|
if (div == 256) {
|
||||||
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
|
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
|
||||||
} else {
|
} else {
|
||||||
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
|
val &= ~(bit_mask(ctrl->mdiv.width) << ctrl->mdiv.shift);
|
||||||
val |= div << ctrl->mdiv.shift;
|
val |= div << ctrl->mdiv.shift;
|
||||||
}
|
}
|
||||||
writel(val, pll->pll_base + ctrl->mdiv.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->mdiv.offset, val);
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
|
||||||
readl(pll->pll_base + ctrl->mdiv.offset);
|
|
||||||
clk->rate = parent_rate / div;
|
clk->rate = parent_rate / div;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -567,11 +579,10 @@ static void iproc_pll_sw_cfg(struct iproc_pll *pll)
|
||||||
if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
|
if (ctrl->flags & IPROC_CLK_PLL_NEEDS_SW_CFG) {
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
val = readl(pll->pll_base + ctrl->sw_ctrl.offset);
|
val = readl(pll->control_base + ctrl->sw_ctrl.offset);
|
||||||
val |= BIT(ctrl->sw_ctrl.shift);
|
val |= BIT(ctrl->sw_ctrl.shift);
|
||||||
writel(val, pll->pll_base + ctrl->sw_ctrl.offset);
|
iproc_pll_write(pll, pll->control_base, ctrl->sw_ctrl.offset,
|
||||||
if (unlikely(ctrl->flags & IPROC_CLK_NEEDS_READ_BACK))
|
val);
|
||||||
readl(pll->pll_base + ctrl->sw_ctrl.offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -606,13 +617,12 @@ void __init iproc_pll_clk_setup(struct device_node *node,
|
||||||
if (WARN_ON(!pll->clks))
|
if (WARN_ON(!pll->clks))
|
||||||
goto err_clks;
|
goto err_clks;
|
||||||
|
|
||||||
pll->pll_base = of_iomap(node, 0);
|
pll->control_base = of_iomap(node, 0);
|
||||||
if (WARN_ON(!pll->pll_base))
|
if (WARN_ON(!pll->control_base))
|
||||||
goto err_pll_iomap;
|
goto err_pll_iomap;
|
||||||
|
|
||||||
|
/* Some SoCs do not require the pwr_base, thus failing is not fatal */
|
||||||
pll->pwr_base = of_iomap(node, 1);
|
pll->pwr_base = of_iomap(node, 1);
|
||||||
if (WARN_ON(!pll->pwr_base))
|
|
||||||
goto err_pwr_iomap;
|
|
||||||
|
|
||||||
/* some PLLs require gating control at the top ASIU level */
|
/* some PLLs require gating control at the top ASIU level */
|
||||||
if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
if (pll_ctrl->flags & IPROC_CLK_PLL_ASIU) {
|
||||||
|
@ -621,6 +631,16 @@ void __init iproc_pll_clk_setup(struct device_node *node,
|
||||||
goto err_asiu_iomap;
|
goto err_asiu_iomap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pll_ctrl->flags & IPROC_CLK_PLL_SPLIT_STAT_CTRL) {
|
||||||
|
/* Some SoCs have a split status/control. If this does not
|
||||||
|
* exist, assume they are unified.
|
||||||
|
*/
|
||||||
|
pll->status_base = of_iomap(node, 2);
|
||||||
|
if (!pll->status_base)
|
||||||
|
goto err_status_iomap;
|
||||||
|
} else
|
||||||
|
pll->status_base = pll->control_base;
|
||||||
|
|
||||||
/* initialize and register the PLL itself */
|
/* initialize and register the PLL itself */
|
||||||
pll->ctrl = pll_ctrl;
|
pll->ctrl = pll_ctrl;
|
||||||
|
|
||||||
|
@ -691,14 +711,18 @@ err_clk_register:
|
||||||
clk_unregister(pll->clk_data.clks[i]);
|
clk_unregister(pll->clk_data.clks[i]);
|
||||||
|
|
||||||
err_pll_register:
|
err_pll_register:
|
||||||
|
if (pll->status_base != pll->control_base)
|
||||||
|
iounmap(pll->status_base);
|
||||||
|
|
||||||
|
err_status_iomap:
|
||||||
if (pll->asiu_base)
|
if (pll->asiu_base)
|
||||||
iounmap(pll->asiu_base);
|
iounmap(pll->asiu_base);
|
||||||
|
|
||||||
err_asiu_iomap:
|
err_asiu_iomap:
|
||||||
iounmap(pll->pwr_base);
|
if (pll->pwr_base)
|
||||||
|
iounmap(pll->pwr_base);
|
||||||
|
|
||||||
err_pwr_iomap:
|
iounmap(pll->control_base);
|
||||||
iounmap(pll->pll_base);
|
|
||||||
|
|
||||||
err_pll_iomap:
|
err_pll_iomap:
|
||||||
kfree(pll->clks);
|
kfree(pll->clks);
|
||||||
|
|
|
@ -48,6 +48,18 @@
|
||||||
*/
|
*/
|
||||||
#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
|
#define IPROC_CLK_PLL_NEEDS_SW_CFG BIT(4)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some PLLs use a different way to control clock power, via the PWRDWN bit in
|
||||||
|
* the PLL control register
|
||||||
|
*/
|
||||||
|
#define IPROC_CLK_EMBED_PWRCTRL BIT(5)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some PLLs have separate registers for Status and Control. Identify this to
|
||||||
|
* let the driver know if additional registers need to be used
|
||||||
|
*/
|
||||||
|
#define IPROC_CLK_PLL_SPLIT_STAT_CTRL BIT(6)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameters for VCO frequency configuration
|
* Parameters for VCO frequency configuration
|
||||||
*
|
*
|
||||||
|
@ -88,12 +100,19 @@ struct iproc_pll_aon_pwr_ctrl {
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Control of the PLL reset, with Ki, Kp, and Ka parameters
|
* Control of the PLL reset
|
||||||
*/
|
*/
|
||||||
struct iproc_pll_reset_ctrl {
|
struct iproc_pll_reset_ctrl {
|
||||||
unsigned int offset;
|
unsigned int offset;
|
||||||
unsigned int reset_shift;
|
unsigned int reset_shift;
|
||||||
unsigned int p_reset_shift;
|
unsigned int p_reset_shift;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Control of the Ki, Kp, and Ka parameters
|
||||||
|
*/
|
||||||
|
struct iproc_pll_dig_filter_ctrl {
|
||||||
|
unsigned int offset;
|
||||||
unsigned int ki_shift;
|
unsigned int ki_shift;
|
||||||
unsigned int ki_width;
|
unsigned int ki_width;
|
||||||
unsigned int kp_shift;
|
unsigned int kp_shift;
|
||||||
|
@ -123,6 +142,7 @@ struct iproc_pll_ctrl {
|
||||||
struct iproc_pll_aon_pwr_ctrl aon;
|
struct iproc_pll_aon_pwr_ctrl aon;
|
||||||
struct iproc_asiu_gate asiu;
|
struct iproc_asiu_gate asiu;
|
||||||
struct iproc_pll_reset_ctrl reset;
|
struct iproc_pll_reset_ctrl reset;
|
||||||
|
struct iproc_pll_dig_filter_ctrl dig_filter;
|
||||||
struct iproc_pll_sw_ctrl sw_ctrl;
|
struct iproc_pll_sw_ctrl sw_ctrl;
|
||||||
struct iproc_clk_reg_op ndiv_int;
|
struct iproc_clk_reg_op ndiv_int;
|
||||||
struct iproc_clk_reg_op ndiv_frac;
|
struct iproc_clk_reg_op ndiv_frac;
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
/*
|
||||||
|
* 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/kernel.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/clock/bcm-ns2.h>
|
||||||
|
#include "clk-iproc.h"
|
||||||
|
|
||||||
|
#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
|
||||||
|
|
||||||
|
#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
|
||||||
|
.pwr_shift = ps, .iso_shift = is }
|
||||||
|
|
||||||
|
#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
|
||||||
|
.p_reset_shift = prs }
|
||||||
|
|
||||||
|
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
|
||||||
|
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
|
||||||
|
.ka_width = kaw }
|
||||||
|
|
||||||
|
#define VCO_CTRL_VAL(uo, lo) { .u_offset = uo, .l_offset = lo }
|
||||||
|
|
||||||
|
#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
|
||||||
|
.hold_shift = hs, .bypass_shift = bs }
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl genpll_scr = {
|
||||||
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
|
||||||
|
.aon = AON_VAL(0x0, 1, 15, 12),
|
||||||
|
.reset = RESET_VAL(0x4, 2, 1),
|
||||||
|
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
|
||||||
|
.ndiv_int = REG_VAL(0x8, 4, 10),
|
||||||
|
.pdiv = REG_VAL(0x8, 0, 4),
|
||||||
|
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
|
||||||
|
.status = REG_VAL(0x0, 27, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl genpll_scr_clk[] = {
|
||||||
|
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
|
||||||
|
* in NS2. However, it doesn't appear to be used anywhere, so setting
|
||||||
|
* it to 0.
|
||||||
|
*/
|
||||||
|
[BCM_NS2_GENPLL_SCR_SCR_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_SCR_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 18, 12, 0),
|
||||||
|
.mdiv = REG_VAL(0x18, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SCR_FS_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_FS_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 19, 13, 0),
|
||||||
|
.mdiv = REG_VAL(0x18, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SCR_AUDIO_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_AUDIO_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 20, 14, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SCR_CH3_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_CH3_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 21, 15, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SCR_CH4_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_CH4_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 22, 16, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SCR_CH5_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SCR_CH5_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 23, 17, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 24, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init ns2_genpll_scr_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &genpll_scr, NULL, 0, genpll_scr_clk,
|
||||||
|
ARRAY_SIZE(genpll_scr_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
|
||||||
|
ns2_genpll_scr_clk_init);
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl genpll_sw = {
|
||||||
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
|
||||||
|
.aon = AON_VAL(0x0, 2, 9, 8),
|
||||||
|
.reset = RESET_VAL(0x4, 2, 1),
|
||||||
|
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
|
||||||
|
.ndiv_int = REG_VAL(0x8, 4, 10),
|
||||||
|
.pdiv = REG_VAL(0x8, 0, 4),
|
||||||
|
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
|
||||||
|
.status = REG_VAL(0x0, 13, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl genpll_sw_clk[] = {
|
||||||
|
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
|
||||||
|
* in NS2. However, it doesn't appear to be used anywhere, so setting
|
||||||
|
* it to 0.
|
||||||
|
*/
|
||||||
|
[BCM_NS2_GENPLL_SW_RPE_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_RPE_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 18, 12, 0),
|
||||||
|
.mdiv = REG_VAL(0x18, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SW_250_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_250_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 19, 13, 0),
|
||||||
|
.mdiv = REG_VAL(0x18, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SW_NIC_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_NIC_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 20, 14, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SW_CHIMP_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_CHIMP_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 21, 15, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SW_PORT_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_PORT_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 22, 16, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_GENPLL_SW_SDIO_CLK] = {
|
||||||
|
.channel = BCM_NS2_GENPLL_SW_SDIO_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 23, 17, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 24, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init ns2_genpll_sw_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &genpll_sw, NULL, 0, genpll_sw_clk,
|
||||||
|
ARRAY_SIZE(genpll_sw_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(ns2_genpll_sw_clk, "brcm,ns2-genpll-sw",
|
||||||
|
ns2_genpll_sw_clk_init);
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl lcpll_ddr = {
|
||||||
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
|
||||||
|
.aon = AON_VAL(0x0, 2, 1, 0),
|
||||||
|
.reset = RESET_VAL(0x4, 2, 1),
|
||||||
|
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
|
||||||
|
.ndiv_int = REG_VAL(0x8, 4, 10),
|
||||||
|
.pdiv = REG_VAL(0x8, 0, 4),
|
||||||
|
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
|
||||||
|
.status = REG_VAL(0x0, 0, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl lcpll_ddr_clk[] = {
|
||||||
|
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
|
||||||
|
* in NS2. However, it doesn't appear to be used anywhere, so setting
|
||||||
|
* it to 0.
|
||||||
|
*/
|
||||||
|
[BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_PCIE_SATA_USB_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 18, 12, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_DDR_DDR_CLK] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_DDR_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 19, 13, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_DDR_CH2_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_CH2_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 20, 14, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_DDR_CH3_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_CH3_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 21, 15, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_DDR_CH4_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_CH4_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 22, 16, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_DDR_CH5_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_DDR_CH5_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 23, 17, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 24, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init ns2_lcpll_ddr_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &lcpll_ddr, NULL, 0, lcpll_ddr_clk,
|
||||||
|
ARRAY_SIZE(lcpll_ddr_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(ns2_lcpll_ddr_clk, "brcm,ns2-lcpll-ddr",
|
||||||
|
ns2_lcpll_ddr_clk_init);
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl lcpll_ports = {
|
||||||
|
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
|
||||||
|
.aon = AON_VAL(0x0, 2, 5, 4),
|
||||||
|
.reset = RESET_VAL(0x4, 2, 1),
|
||||||
|
.dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 1, 4),
|
||||||
|
.ndiv_int = REG_VAL(0x8, 4, 10),
|
||||||
|
.pdiv = REG_VAL(0x8, 0, 4),
|
||||||
|
.vco_ctrl = VCO_CTRL_VAL(0x10, 0xc),
|
||||||
|
.status = REG_VAL(0x0, 0, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl lcpll_ports_clk[] = {
|
||||||
|
/* bypass_shift, the last value passed into ENABLE_VAL(), is not defined
|
||||||
|
* in NS2. However, it doesn't appear to be used anywhere, so setting
|
||||||
|
* it to 0.
|
||||||
|
*/
|
||||||
|
[BCM_NS2_LCPLL_PORTS_WAN_CLK] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_WAN_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 18, 12, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_PORTS_RGMII_CLK] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_RGMII_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 19, 13, 0),
|
||||||
|
.mdiv = REG_VAL(0x14, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_PORTS_CH2_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_CH2_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 20, 14, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_PORTS_CH3_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_CH3_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 21, 15, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_PORTS_CH4_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_CH4_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 22, 16, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NS2_LCPLL_PORTS_CH5_UNUSED] = {
|
||||||
|
.channel = BCM_NS2_LCPLL_PORTS_CH5_UNUSED,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 23, 17, 0),
|
||||||
|
.mdiv = REG_VAL(0x10, 24, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init ns2_lcpll_ports_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &lcpll_ports, NULL, 0, lcpll_ports_clk,
|
||||||
|
ARRAY_SIZE(lcpll_ports_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(ns2_lcpll_ports_clk, "brcm,ns2-lcpll-ports",
|
||||||
|
ns2_lcpll_ports_clk_init);
|
|
@ -0,0 +1,139 @@
|
||||||
|
/*
|
||||||
|
* 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/kernel.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/clock/bcm-nsp.h>
|
||||||
|
#include "clk-iproc.h"
|
||||||
|
|
||||||
|
#define REG_VAL(o, s, w) { .offset = o, .shift = s, .width = w, }
|
||||||
|
|
||||||
|
#define AON_VAL(o, pw, ps, is) { .offset = o, .pwr_width = pw, \
|
||||||
|
.pwr_shift = ps, .iso_shift = is }
|
||||||
|
|
||||||
|
#define RESET_VAL(o, rs, prs) { .offset = o, .reset_shift = rs, \
|
||||||
|
.p_reset_shift = prs }
|
||||||
|
|
||||||
|
#define DF_VAL(o, kis, kiw, kps, kpw, kas, kaw) { .offset = o, .ki_shift = kis,\
|
||||||
|
.ki_width = kiw, .kp_shift = kps, .kp_width = kpw, .ka_shift = kas, \
|
||||||
|
.ka_width = kaw }
|
||||||
|
|
||||||
|
#define ENABLE_VAL(o, es, hs, bs) { .offset = o, .enable_shift = es, \
|
||||||
|
.hold_shift = hs, .bypass_shift = bs }
|
||||||
|
|
||||||
|
static void __init nsp_armpll_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_armpll_setup(node);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(nsp_armpll, "brcm,nsp-armpll", nsp_armpll_init);
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl genpll = {
|
||||||
|
.flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
|
||||||
|
.aon = AON_VAL(0x0, 1, 12, 0),
|
||||||
|
.reset = RESET_VAL(0x0, 11, 10),
|
||||||
|
.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
|
||||||
|
.ndiv_int = REG_VAL(0x14, 20, 10),
|
||||||
|
.ndiv_frac = REG_VAL(0x14, 0, 20),
|
||||||
|
.pdiv = REG_VAL(0x18, 24, 3),
|
||||||
|
.status = REG_VAL(0x20, 12, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl genpll_clk[] = {
|
||||||
|
[BCM_NSP_GENPLL_PHY_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_PHY_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 12, 6, 18),
|
||||||
|
.mdiv = REG_VAL(0x18, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_GENPLL_ENET_SW_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_ENET_SW_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 13, 7, 19),
|
||||||
|
.mdiv = REG_VAL(0x18, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_GENPLL_USB_PHY_REF_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_USB_PHY_REF_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 14, 8, 20),
|
||||||
|
.mdiv = REG_VAL(0x18, 0, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_GENPLL_IPROCFAST_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_IPROCFAST_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 15, 9, 21),
|
||||||
|
.mdiv = REG_VAL(0x1c, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_GENPLL_SATA1_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_SATA1_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 16, 10, 22),
|
||||||
|
.mdiv = REG_VAL(0x1c, 8, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_GENPLL_SATA2_CLK] = {
|
||||||
|
.channel = BCM_NSP_GENPLL_SATA2_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x4, 17, 11, 23),
|
||||||
|
.mdiv = REG_VAL(0x1c, 0, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init nsp_genpll_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &genpll, NULL, 0, genpll_clk,
|
||||||
|
ARRAY_SIZE(genpll_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(nsp_genpll_clk, "brcm,nsp-genpll", nsp_genpll_clk_init);
|
||||||
|
|
||||||
|
static const struct iproc_pll_ctrl lcpll0 = {
|
||||||
|
.flags = IPROC_CLK_PLL_HAS_NDIV_FRAC | IPROC_CLK_EMBED_PWRCTRL,
|
||||||
|
.aon = AON_VAL(0x0, 1, 24, 0),
|
||||||
|
.reset = RESET_VAL(0x0, 23, 22),
|
||||||
|
.dig_filter = DF_VAL(0x0, 16, 3, 12, 4, 19, 4),
|
||||||
|
.ndiv_int = REG_VAL(0x4, 20, 8),
|
||||||
|
.ndiv_frac = REG_VAL(0x4, 0, 20),
|
||||||
|
.pdiv = REG_VAL(0x4, 28, 3),
|
||||||
|
.status = REG_VAL(0x10, 12, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct iproc_clk_ctrl lcpll0_clk[] = {
|
||||||
|
[BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK] = {
|
||||||
|
.channel = BCM_NSP_LCPLL0_PCIE_PHY_REF_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 6, 3, 9),
|
||||||
|
.mdiv = REG_VAL(0x8, 24, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_LCPLL0_SDIO_CLK] = {
|
||||||
|
.channel = BCM_NSP_LCPLL0_SDIO_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 7, 4, 10),
|
||||||
|
.mdiv = REG_VAL(0x8, 16, 8),
|
||||||
|
},
|
||||||
|
[BCM_NSP_LCPLL0_DDR_PHY_CLK] = {
|
||||||
|
.channel = BCM_NSP_LCPLL0_DDR_PHY_CLK,
|
||||||
|
.flags = IPROC_CLK_AON,
|
||||||
|
.enable = ENABLE_VAL(0x0, 8, 5, 11),
|
||||||
|
.mdiv = REG_VAL(0x8, 8, 8),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init nsp_lcpll0_clk_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
iproc_pll_clk_setup(node, &lcpll0, NULL, 0, lcpll0_clk,
|
||||||
|
ARRAY_SIZE(lcpll0_clk));
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(nsp_lcpll0_clk, "brcm,nsp-lcpll0", nsp_lcpll0_clk_init);
|
|
@ -490,8 +490,8 @@ static const struct berlin2_gate_data bg2_gates[] __initconst = {
|
||||||
{ "usb0", "perif", 11 },
|
{ "usb0", "perif", 11 },
|
||||||
{ "usb1", "perif", 12 },
|
{ "usb1", "perif", 12 },
|
||||||
{ "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
|
{ "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
|
||||||
{ "sdio0", "perif", 14, CLK_IGNORE_UNUSED },
|
{ "sdio0", "perif", 14 },
|
||||||
{ "sdio1", "perif", 15, CLK_IGNORE_UNUSED },
|
{ "sdio1", "perif", 15 },
|
||||||
{ "nfc", "perif", 17 },
|
{ "nfc", "perif", 17 },
|
||||||
{ "smemc", "perif", 19 },
|
{ "smemc", "perif", 19 },
|
||||||
{ "audiohd", "audiohd_pll", 26 },
|
{ "audiohd", "audiohd_pll", 26 },
|
||||||
|
|
|
@ -283,7 +283,7 @@ static const struct berlin2_gate_data bg2q_gates[] __initconst = {
|
||||||
{ "usb2", "perif", 13 },
|
{ "usb2", "perif", 13 },
|
||||||
{ "usb3", "perif", 14 },
|
{ "usb3", "perif", 14 },
|
||||||
{ "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
|
{ "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
|
||||||
{ "sdio", "perif", 16, CLK_IGNORE_UNUSED },
|
{ "sdio", "perif", 16 },
|
||||||
{ "nfc", "perif", 18 },
|
{ "nfc", "perif", 18 },
|
||||||
{ "pcie", "perif", 22 },
|
{ "pcie", "perif", 22 },
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,55 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Broadcom
|
|
||||||
* Copyright (C) 2012 Stephen Warren
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/clk-provider.h>
|
|
||||||
#include <linux/clkdev.h>
|
|
||||||
#include <linux/clk/bcm2835.h>
|
|
||||||
#include <linux/of.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* These are fixed clocks. They're probably not all root clocks and it may
|
|
||||||
* be possible to turn them on and off but until this is mapped out better
|
|
||||||
* it's the only way they can be used.
|
|
||||||
*/
|
|
||||||
void __init bcm2835_init_clocks(void)
|
|
||||||
{
|
|
||||||
struct clk *clk;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT,
|
|
||||||
126000000);
|
|
||||||
if (IS_ERR(clk))
|
|
||||||
pr_err("apb_pclk not registered\n");
|
|
||||||
|
|
||||||
clk = clk_register_fixed_rate(NULL, "uart0_pclk", NULL, CLK_IS_ROOT,
|
|
||||||
3000000);
|
|
||||||
if (IS_ERR(clk))
|
|
||||||
pr_err("uart0_pclk not registered\n");
|
|
||||||
ret = clk_register_clkdev(clk, NULL, "20201000.uart");
|
|
||||||
if (ret)
|
|
||||||
pr_err("uart0_pclk alias not registered\n");
|
|
||||||
|
|
||||||
clk = clk_register_fixed_rate(NULL, "uart1_pclk", NULL, CLK_IS_ROOT,
|
|
||||||
125000000);
|
|
||||||
if (IS_ERR(clk))
|
|
||||||
pr_err("uart1_pclk not registered\n");
|
|
||||||
ret = clk_register_clkdev(clk, NULL, "20215000.uart");
|
|
||||||
if (ret)
|
|
||||||
pr_err("uart1_pclk alias not registered\n");
|
|
||||||
}
|
|
|
@ -24,7 +24,7 @@
|
||||||
* Traits of this clock:
|
* Traits of this clock:
|
||||||
* prepare - clk_prepare only ensures that parents are prepared
|
* prepare - clk_prepare only ensures that parents are prepared
|
||||||
* enable - clk_enable only ensures that parents are enabled
|
* enable - clk_enable only ensures that parents are enabled
|
||||||
* rate - rate is adjustable. clk->rate = DIV_ROUND_UP(parent->rate / divisor)
|
* rate - rate is adjustable. clk->rate = ceiling(parent->rate / divisor)
|
||||||
* parent - fixed parent. No clk_set_parent support
|
* parent - fixed parent. No clk_set_parent support
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ unsigned long divider_recalc_rate(struct clk_hw *hw, unsigned long parent_rate,
|
||||||
return parent_rate;
|
return parent_rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DIV_ROUND_UP(parent_rate, div);
|
return DIV_ROUND_UP_ULL((u64)parent_rate, div);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(divider_recalc_rate);
|
EXPORT_SYMBOL_GPL(divider_recalc_rate);
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ static int _div_round_up(const struct clk_div_table *table,
|
||||||
unsigned long parent_rate, unsigned long rate,
|
unsigned long parent_rate, unsigned long rate,
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
int div = DIV_ROUND_UP(parent_rate, rate);
|
int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||||
|
|
||||||
if (flags & CLK_DIVIDER_POWER_OF_TWO)
|
if (flags & CLK_DIVIDER_POWER_OF_TWO)
|
||||||
div = __roundup_pow_of_two(div);
|
div = __roundup_pow_of_two(div);
|
||||||
|
@ -227,7 +227,7 @@ static int _div_round_closest(const struct clk_div_table *table,
|
||||||
int up, down;
|
int up, down;
|
||||||
unsigned long up_rate, down_rate;
|
unsigned long up_rate, down_rate;
|
||||||
|
|
||||||
up = DIV_ROUND_UP(parent_rate, rate);
|
up = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||||
down = parent_rate / rate;
|
down = parent_rate / rate;
|
||||||
|
|
||||||
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
|
if (flags & CLK_DIVIDER_POWER_OF_TWO) {
|
||||||
|
@ -238,8 +238,8 @@ static int _div_round_closest(const struct clk_div_table *table,
|
||||||
down = _round_down_table(table, down);
|
down = _round_down_table(table, down);
|
||||||
}
|
}
|
||||||
|
|
||||||
up_rate = DIV_ROUND_UP(parent_rate, up);
|
up_rate = DIV_ROUND_UP_ULL((u64)parent_rate, up);
|
||||||
down_rate = DIV_ROUND_UP(parent_rate, down);
|
down_rate = DIV_ROUND_UP_ULL((u64)parent_rate, down);
|
||||||
|
|
||||||
return (rate - up_rate) <= (down_rate - rate) ? up : down;
|
return (rate - up_rate) <= (down_rate - rate) ? up : down;
|
||||||
}
|
}
|
||||||
|
@ -318,7 +318,7 @@ static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
|
||||||
}
|
}
|
||||||
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||||
rate * i);
|
rate * i);
|
||||||
now = DIV_ROUND_UP(parent_rate, i);
|
now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
|
||||||
if (_is_best_div(rate, now, best, flags)) {
|
if (_is_best_div(rate, now, best, flags)) {
|
||||||
bestdiv = i;
|
bestdiv = i;
|
||||||
best = now;
|
best = now;
|
||||||
|
@ -342,7 +342,7 @@ long divider_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|
||||||
div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
|
div = clk_divider_bestdiv(hw, rate, prate, table, width, flags);
|
||||||
|
|
||||||
return DIV_ROUND_UP(*prate, div);
|
return DIV_ROUND_UP_ULL((u64)*prate, div);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(divider_round_rate);
|
EXPORT_SYMBOL_GPL(divider_round_rate);
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
bestdiv &= div_mask(divider->width);
|
bestdiv &= div_mask(divider->width);
|
||||||
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
|
bestdiv = _get_div(divider->table, bestdiv, divider->flags,
|
||||||
divider->width);
|
divider->width);
|
||||||
return DIV_ROUND_UP(*prate, bestdiv);
|
return DIV_ROUND_UP_ULL((u64)*prate, bestdiv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return divider_round_rate(hw, rate, prate, divider->table,
|
return divider_round_rate(hw, rate, prate, divider->table,
|
||||||
|
@ -371,7 +371,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
|
||||||
{
|
{
|
||||||
unsigned int div, value;
|
unsigned int div, value;
|
||||||
|
|
||||||
div = DIV_ROUND_UP(parent_rate, rate);
|
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
|
||||||
|
|
||||||
if (!_is_valid_div(table, div, flags))
|
if (!_is_valid_div(table, div, flags))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -7,13 +7,14 @@
|
||||||
*
|
*
|
||||||
* Adjustable fractional divider clock implementation.
|
* Adjustable fractional divider clock implementation.
|
||||||
* Output rate = (m / n) * parent_rate.
|
* Output rate = (m / n) * parent_rate.
|
||||||
|
* Uses rational best approximation algorithm.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/gcd.h>
|
#include <linux/rational.h>
|
||||||
|
|
||||||
#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
|
#define to_clk_fd(_hw) container_of(_hw, struct clk_fractional_divider, hw)
|
||||||
|
|
||||||
|
@ -22,7 +23,8 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
|
||||||
{
|
{
|
||||||
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
u32 val, m, n;
|
unsigned long m, n;
|
||||||
|
u32 val;
|
||||||
u64 ret;
|
u64 ret;
|
||||||
|
|
||||||
if (fd->lock)
|
if (fd->lock)
|
||||||
|
@ -50,23 +52,33 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
|
static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long *prate)
|
unsigned long *parent_rate)
|
||||||
{
|
{
|
||||||
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
||||||
unsigned maxn = (fd->nmask >> fd->nshift) + 1;
|
unsigned long scale;
|
||||||
unsigned div;
|
unsigned long m, n;
|
||||||
|
u64 ret;
|
||||||
|
|
||||||
if (!rate || rate >= *prate)
|
if (!rate || rate >= *parent_rate)
|
||||||
return *prate;
|
return *parent_rate;
|
||||||
|
|
||||||
div = gcd(*prate, rate);
|
/*
|
||||||
|
* Get rate closer to *parent_rate to guarantee there is no overflow
|
||||||
|
* for m and n. In the result it will be the nearest rate left shifted
|
||||||
|
* by (scale - fd->nwidth) bits.
|
||||||
|
*/
|
||||||
|
scale = fls_long(*parent_rate / rate - 1);
|
||||||
|
if (scale > fd->nwidth)
|
||||||
|
rate <<= scale - fd->nwidth;
|
||||||
|
|
||||||
while ((*prate / div) > maxn) {
|
rational_best_approximation(rate, *parent_rate,
|
||||||
div <<= 1;
|
GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
|
||||||
rate <<= 1;
|
&m, &n);
|
||||||
}
|
|
||||||
|
|
||||||
return rate;
|
ret = (u64)*parent_rate * m;
|
||||||
|
do_div(ret, n);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
@ -74,13 +86,12 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
{
|
{
|
||||||
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
struct clk_fractional_divider *fd = to_clk_fd(hw);
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
unsigned long div;
|
unsigned long m, n;
|
||||||
unsigned n, m;
|
|
||||||
u32 val;
|
u32 val;
|
||||||
|
|
||||||
div = gcd(parent_rate, rate);
|
rational_best_approximation(rate, parent_rate,
|
||||||
m = rate / div;
|
GENMASK(fd->mwidth - 1, 0), GENMASK(fd->nwidth - 1, 0),
|
||||||
n = parent_rate / div;
|
&m, &n);
|
||||||
|
|
||||||
if (fd->lock)
|
if (fd->lock)
|
||||||
spin_lock_irqsave(fd->lock, flags);
|
spin_lock_irqsave(fd->lock, flags);
|
||||||
|
@ -128,9 +139,11 @@ struct clk *clk_register_fractional_divider(struct device *dev,
|
||||||
|
|
||||||
fd->reg = reg;
|
fd->reg = reg;
|
||||||
fd->mshift = mshift;
|
fd->mshift = mshift;
|
||||||
fd->mmask = (BIT(mwidth) - 1) << mshift;
|
fd->mwidth = mwidth;
|
||||||
|
fd->mmask = GENMASK(mwidth - 1, 0) << mshift;
|
||||||
fd->nshift = nshift;
|
fd->nshift = nshift;
|
||||||
fd->nmask = (BIT(nwidth) - 1) << nshift;
|
fd->nwidth = nwidth;
|
||||||
|
fd->nmask = GENMASK(nwidth - 1, 0) << nshift;
|
||||||
fd->flags = clk_divider_flags;
|
fd->flags = clk_divider_flags;
|
||||||
fd->lock = lock;
|
fd->lock = lock;
|
||||||
fd->hw.init = &init;
|
fd->hw.init = &init;
|
||||||
|
|
|
@ -94,5 +94,5 @@ static struct platform_driver max77802_clk_driver = {
|
||||||
module_platform_driver(max77802_clk_driver);
|
module_platform_driver(max77802_clk_driver);
|
||||||
|
|
||||||
MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
|
MODULE_DESCRIPTION("MAXIM 77802 Clock Driver");
|
||||||
MODULE_AUTHOR("Javier Martinez Canillas <javier.martinez@collabora.co.uk>");
|
MODULE_AUTHOR("Javier Martinez Canillas <javier@osg.samsung.com");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
|
@ -0,0 +1,130 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2015 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 version 2 as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/export.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
|
||||||
|
|
||||||
|
static unsigned long __get_mult(struct clk_multiplier *mult,
|
||||||
|
unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
|
||||||
|
return DIV_ROUND_CLOSEST(rate, parent_rate);
|
||||||
|
|
||||||
|
return rate / parent_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_multiplier *mult = to_clk_multiplier(hw);
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
val = clk_readl(mult->reg) >> mult->shift;
|
||||||
|
val &= GENMASK(mult->width - 1, 0);
|
||||||
|
|
||||||
|
if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
|
||||||
|
val = 1;
|
||||||
|
|
||||||
|
return parent_rate * val;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __is_best_rate(unsigned long rate, unsigned long new,
|
||||||
|
unsigned long best, unsigned long flags)
|
||||||
|
{
|
||||||
|
if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
|
||||||
|
return abs(rate - new) < abs(rate - best);
|
||||||
|
|
||||||
|
return new >= rate && new < best;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *best_parent_rate,
|
||||||
|
u8 width, unsigned long flags)
|
||||||
|
{
|
||||||
|
unsigned long orig_parent_rate = *best_parent_rate;
|
||||||
|
unsigned long parent_rate, current_rate, best_rate = ~0;
|
||||||
|
unsigned int i, bestmult = 0;
|
||||||
|
|
||||||
|
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
|
||||||
|
return rate / *best_parent_rate;
|
||||||
|
|
||||||
|
for (i = 1; i < ((1 << width) - 1); i++) {
|
||||||
|
if (rate == orig_parent_rate * i) {
|
||||||
|
/*
|
||||||
|
* This is the best case for us if we have a
|
||||||
|
* perfect match without changing the parent
|
||||||
|
* rate.
|
||||||
|
*/
|
||||||
|
*best_parent_rate = orig_parent_rate;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
|
||||||
|
rate / i);
|
||||||
|
current_rate = parent_rate * i;
|
||||||
|
|
||||||
|
if (__is_best_rate(rate, current_rate, best_rate, flags)) {
|
||||||
|
bestmult = i;
|
||||||
|
best_rate = current_rate;
|
||||||
|
*best_parent_rate = parent_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bestmult;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_multiplier *mult = to_clk_multiplier(hw);
|
||||||
|
unsigned long factor = __bestmult(hw, rate, parent_rate,
|
||||||
|
mult->width, mult->flags);
|
||||||
|
|
||||||
|
return *parent_rate * factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_multiplier *mult = to_clk_multiplier(hw);
|
||||||
|
unsigned long factor = __get_mult(mult, rate, parent_rate);
|
||||||
|
unsigned long flags = 0;
|
||||||
|
unsigned long val;
|
||||||
|
|
||||||
|
if (mult->lock)
|
||||||
|
spin_lock_irqsave(mult->lock, flags);
|
||||||
|
else
|
||||||
|
__acquire(mult->lock);
|
||||||
|
|
||||||
|
val = clk_readl(mult->reg);
|
||||||
|
val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
|
||||||
|
val |= factor << mult->shift;
|
||||||
|
clk_writel(val, mult->reg);
|
||||||
|
|
||||||
|
if (mult->lock)
|
||||||
|
spin_unlock_irqrestore(mult->lock, flags);
|
||||||
|
else
|
||||||
|
__release(mult->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct clk_ops clk_multiplier_ops = {
|
||||||
|
.recalc_rate = clk_multiplier_recalc_rate,
|
||||||
|
.round_rate = clk_multiplier_round_rate,
|
||||||
|
.set_rate = clk_multiplier_set_rate,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_multiplier_ops);
|
|
@ -0,0 +1,379 @@
|
||||||
|
/*
|
||||||
|
* Driver for Silicon Labs Si514 Programmable Oscillator
|
||||||
|
*
|
||||||
|
* Copyright (C) 2015 Topic Embedded Products
|
||||||
|
*
|
||||||
|
* Author: Mike Looijmans <mike.looijmans@topic.nl>
|
||||||
|
*
|
||||||
|
* 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/delay.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/i2c.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
/* I2C registers */
|
||||||
|
#define SI514_REG_LP 0
|
||||||
|
#define SI514_REG_M_FRAC1 5
|
||||||
|
#define SI514_REG_M_FRAC2 6
|
||||||
|
#define SI514_REG_M_FRAC3 7
|
||||||
|
#define SI514_REG_M_INT_FRAC 8
|
||||||
|
#define SI514_REG_M_INT 9
|
||||||
|
#define SI514_REG_HS_DIV 10
|
||||||
|
#define SI514_REG_LS_HS_DIV 11
|
||||||
|
#define SI514_REG_OE_STATE 14
|
||||||
|
#define SI514_REG_RESET 128
|
||||||
|
#define SI514_REG_CONTROL 132
|
||||||
|
|
||||||
|
/* Register values */
|
||||||
|
#define SI514_RESET_RST BIT(7)
|
||||||
|
|
||||||
|
#define SI514_CONTROL_FCAL BIT(0)
|
||||||
|
#define SI514_CONTROL_OE BIT(2)
|
||||||
|
|
||||||
|
#define SI514_MIN_FREQ 100000U
|
||||||
|
#define SI514_MAX_FREQ 250000000U
|
||||||
|
|
||||||
|
#define FXO 31980000U
|
||||||
|
|
||||||
|
#define FVCO_MIN 2080000000U
|
||||||
|
#define FVCO_MAX 2500000000U
|
||||||
|
|
||||||
|
#define HS_DIV_MAX 1022
|
||||||
|
|
||||||
|
struct clk_si514 {
|
||||||
|
struct clk_hw hw;
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct i2c_client *i2c_client;
|
||||||
|
};
|
||||||
|
#define to_clk_si514(_hw) container_of(_hw, struct clk_si514, hw)
|
||||||
|
|
||||||
|
/* Multiplier/divider settings */
|
||||||
|
struct clk_si514_muldiv {
|
||||||
|
u32 m_frac; /* 29-bit Fractional part of multiplier M */
|
||||||
|
u8 m_int; /* Integer part of multiplier M, 65..78 */
|
||||||
|
u8 ls_div_bits; /* 2nd divider, as 2^x */
|
||||||
|
u16 hs_div; /* 1st divider, must be even and 10<=x<=1022 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Enables or disables the output driver */
|
||||||
|
static int si514_enable_output(struct clk_si514 *data, bool enable)
|
||||||
|
{
|
||||||
|
return regmap_update_bits(data->regmap, SI514_REG_CONTROL,
|
||||||
|
SI514_CONTROL_OE, enable ? SI514_CONTROL_OE : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Retrieve clock multiplier and dividers from hardware */
|
||||||
|
static int si514_get_muldiv(struct clk_si514 *data,
|
||||||
|
struct clk_si514_muldiv *settings)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
u8 reg[7];
|
||||||
|
|
||||||
|
err = regmap_bulk_read(data->regmap, SI514_REG_M_FRAC1,
|
||||||
|
reg, ARRAY_SIZE(reg));
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
settings->m_frac = reg[0] | reg[1] << 8 | reg[2] << 16 |
|
||||||
|
(reg[3] & 0x1F) << 24;
|
||||||
|
settings->m_int = (reg[4] & 0x3f) << 3 | reg[3] >> 5;
|
||||||
|
settings->ls_div_bits = (reg[6] >> 4) & 0x07;
|
||||||
|
settings->hs_div = (reg[6] & 0x03) << 8 | reg[5];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int si514_set_muldiv(struct clk_si514 *data,
|
||||||
|
struct clk_si514_muldiv *settings)
|
||||||
|
{
|
||||||
|
u8 lp;
|
||||||
|
u8 reg[7];
|
||||||
|
int err;
|
||||||
|
|
||||||
|
/* Calculate LP1/LP2 according to table 13 in the datasheet */
|
||||||
|
/* 65.259980246 */
|
||||||
|
if (settings->m_int < 65 ||
|
||||||
|
(settings->m_int == 65 && settings->m_frac <= 139575831))
|
||||||
|
lp = 0x22;
|
||||||
|
/* 67.859763463 */
|
||||||
|
else if (settings->m_int < 67 ||
|
||||||
|
(settings->m_int == 67 && settings->m_frac <= 461581994))
|
||||||
|
lp = 0x23;
|
||||||
|
/* 72.937624981 */
|
||||||
|
else if (settings->m_int < 72 ||
|
||||||
|
(settings->m_int == 72 && settings->m_frac <= 503383578))
|
||||||
|
lp = 0x33;
|
||||||
|
/* 75.843265046 */
|
||||||
|
else if (settings->m_int < 75 ||
|
||||||
|
(settings->m_int == 75 && settings->m_frac <= 452724474))
|
||||||
|
lp = 0x34;
|
||||||
|
else
|
||||||
|
lp = 0x44;
|
||||||
|
|
||||||
|
err = regmap_write(data->regmap, SI514_REG_LP, lp);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
reg[0] = settings->m_frac;
|
||||||
|
reg[1] = settings->m_frac >> 8;
|
||||||
|
reg[2] = settings->m_frac >> 16;
|
||||||
|
reg[3] = settings->m_frac >> 24 | settings->m_int << 5;
|
||||||
|
reg[4] = settings->m_int >> 3;
|
||||||
|
reg[5] = settings->hs_div;
|
||||||
|
reg[6] = (settings->hs_div >> 8) | (settings->ls_div_bits << 4);
|
||||||
|
|
||||||
|
err = regmap_bulk_write(data->regmap, SI514_REG_HS_DIV, reg + 5, 2);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
/*
|
||||||
|
* Writing to SI514_REG_M_INT_FRAC triggers the clock change, so that
|
||||||
|
* must be written last
|
||||||
|
*/
|
||||||
|
return regmap_bulk_write(data->regmap, SI514_REG_M_FRAC1, reg, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate divider settings for a given frequency */
|
||||||
|
static int si514_calc_muldiv(struct clk_si514_muldiv *settings,
|
||||||
|
unsigned long frequency)
|
||||||
|
{
|
||||||
|
u64 m;
|
||||||
|
u32 ls_freq;
|
||||||
|
u32 tmp;
|
||||||
|
u8 res;
|
||||||
|
|
||||||
|
if ((frequency < SI514_MIN_FREQ) || (frequency > SI514_MAX_FREQ))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Determine the minimum value of LS_DIV and resulting target freq. */
|
||||||
|
ls_freq = frequency;
|
||||||
|
if (frequency >= (FVCO_MIN / HS_DIV_MAX))
|
||||||
|
settings->ls_div_bits = 0;
|
||||||
|
else {
|
||||||
|
res = 1;
|
||||||
|
tmp = 2 * HS_DIV_MAX;
|
||||||
|
while (tmp <= (HS_DIV_MAX * 32)) {
|
||||||
|
if ((frequency * tmp) >= FVCO_MIN)
|
||||||
|
break;
|
||||||
|
++res;
|
||||||
|
tmp <<= 1;
|
||||||
|
}
|
||||||
|
settings->ls_div_bits = res;
|
||||||
|
ls_freq = frequency << res;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine minimum HS_DIV, round up to even number */
|
||||||
|
settings->hs_div = DIV_ROUND_UP(FVCO_MIN >> 1, ls_freq) << 1;
|
||||||
|
|
||||||
|
/* M = LS_DIV x HS_DIV x frequency / F_XO (in fixed-point) */
|
||||||
|
m = ((u64)(ls_freq * settings->hs_div) << 29) + (FXO / 2);
|
||||||
|
do_div(m, FXO);
|
||||||
|
settings->m_frac = (u32)m & (BIT(29) - 1);
|
||||||
|
settings->m_int = (u32)(m >> 29);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calculate resulting frequency given the register settings */
|
||||||
|
static unsigned long si514_calc_rate(struct clk_si514_muldiv *settings)
|
||||||
|
{
|
||||||
|
u64 m = settings->m_frac | ((u64)settings->m_int << 29);
|
||||||
|
u32 d = settings->hs_div * BIT(settings->ls_div_bits);
|
||||||
|
|
||||||
|
return ((u32)(((m * FXO) + (FXO / 2)) >> 29)) / d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long si514_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_si514 *data = to_clk_si514(hw);
|
||||||
|
struct clk_si514_muldiv settings;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = si514_get_muldiv(data, &settings);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&data->i2c_client->dev, "unable to retrieve settings\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return si514_calc_rate(&settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static long si514_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_si514_muldiv settings;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (!rate)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
err = si514_calc_muldiv(&settings, rate);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return si514_calc_rate(&settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update output frequency for big frequency changes (> 1000 ppm).
|
||||||
|
* The chip supports <1000ppm changes "on the fly", we haven't implemented
|
||||||
|
* that here.
|
||||||
|
*/
|
||||||
|
static int si514_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_si514 *data = to_clk_si514(hw);
|
||||||
|
struct clk_si514_muldiv settings;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = si514_calc_muldiv(&settings, rate);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
si514_enable_output(data, false);
|
||||||
|
|
||||||
|
err = si514_set_muldiv(data, &settings);
|
||||||
|
if (err < 0)
|
||||||
|
return err; /* Undefined state now, best to leave disabled */
|
||||||
|
|
||||||
|
/* Trigger calibration */
|
||||||
|
err = regmap_write(data->regmap, SI514_REG_CONTROL, SI514_CONTROL_FCAL);
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
/* Applying a new frequency can take up to 10ms */
|
||||||
|
usleep_range(10000, 12000);
|
||||||
|
|
||||||
|
si514_enable_output(data, true);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops si514_clk_ops = {
|
||||||
|
.recalc_rate = si514_recalc_rate,
|
||||||
|
.round_rate = si514_round_rate,
|
||||||
|
.set_rate = si514_set_rate,
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool si514_regmap_is_volatile(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case SI514_REG_CONTROL:
|
||||||
|
case SI514_REG_RESET:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool si514_regmap_is_writeable(struct device *dev, unsigned int reg)
|
||||||
|
{
|
||||||
|
switch (reg) {
|
||||||
|
case SI514_REG_LP:
|
||||||
|
case SI514_REG_M_FRAC1 ... SI514_REG_LS_HS_DIV:
|
||||||
|
case SI514_REG_OE_STATE:
|
||||||
|
case SI514_REG_RESET:
|
||||||
|
case SI514_REG_CONTROL:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct regmap_config si514_regmap_config = {
|
||||||
|
.reg_bits = 8,
|
||||||
|
.val_bits = 8,
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
.max_register = SI514_REG_CONTROL,
|
||||||
|
.writeable_reg = si514_regmap_is_writeable,
|
||||||
|
.volatile_reg = si514_regmap_is_volatile,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int si514_probe(struct i2c_client *client,
|
||||||
|
const struct i2c_device_id *id)
|
||||||
|
{
|
||||||
|
struct clk_si514 *data;
|
||||||
|
struct clk_init_data init;
|
||||||
|
struct clk *clk;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
init.ops = &si514_clk_ops;
|
||||||
|
init.flags = CLK_IS_ROOT;
|
||||||
|
init.num_parents = 0;
|
||||||
|
data->hw.init = &init;
|
||||||
|
data->i2c_client = client;
|
||||||
|
|
||||||
|
if (of_property_read_string(client->dev.of_node, "clock-output-names",
|
||||||
|
&init.name))
|
||||||
|
init.name = client->dev.of_node->name;
|
||||||
|
|
||||||
|
data->regmap = devm_regmap_init_i2c(client, &si514_regmap_config);
|
||||||
|
if (IS_ERR(data->regmap)) {
|
||||||
|
dev_err(&client->dev, "failed to allocate register map\n");
|
||||||
|
return PTR_ERR(data->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
i2c_set_clientdata(client, data);
|
||||||
|
|
||||||
|
clk = devm_clk_register(&client->dev, &data->hw);
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
dev_err(&client->dev, "clock registration failed\n");
|
||||||
|
return PTR_ERR(clk);
|
||||||
|
}
|
||||||
|
err = of_clk_add_provider(client->dev.of_node, of_clk_src_simple_get,
|
||||||
|
clk);
|
||||||
|
if (err) {
|
||||||
|
dev_err(&client->dev, "unable to add clk provider\n");
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int si514_remove(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
of_clk_del_provider(client->dev.of_node);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id si514_id[] = {
|
||||||
|
{ "si514", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, si514_id);
|
||||||
|
|
||||||
|
static const struct of_device_id clk_si514_of_match[] = {
|
||||||
|
{ .compatible = "silabs,si514" },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, clk_si514_of_match);
|
||||||
|
|
||||||
|
static struct i2c_driver si514_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "si514",
|
||||||
|
.of_match_table = clk_si514_of_match,
|
||||||
|
},
|
||||||
|
.probe = si514_probe,
|
||||||
|
.remove = si514_remove,
|
||||||
|
.id_table = si514_id,
|
||||||
|
};
|
||||||
|
module_i2c_driver(si514_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Mike Looijmans <mike.looijmans@topic.nl>");
|
||||||
|
MODULE_DESCRIPTION("Si514 driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -1183,13 +1183,13 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
if (of_property_read_u32(child, "reg", &num)) {
|
if (of_property_read_u32(child, "reg", &num)) {
|
||||||
dev_err(&client->dev, "missing reg property of %s\n",
|
dev_err(&client->dev, "missing reg property of %s\n",
|
||||||
child->name);
|
child->name);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num >= 8 ||
|
if (num >= 8 ||
|
||||||
(variant == SI5351_VARIANT_A3 && num >= 3)) {
|
(variant == SI5351_VARIANT_A3 && num >= 3)) {
|
||||||
dev_err(&client->dev, "invalid clkout %d\n", num);
|
dev_err(&client->dev, "invalid clkout %d\n", num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!of_property_read_u32(child, "silabs,multisynth-source",
|
if (!of_property_read_u32(child, "silabs,multisynth-source",
|
||||||
|
@ -1207,7 +1207,7 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid parent %d for multisynth %d\n",
|
"invalid parent %d for multisynth %d\n",
|
||||||
val, num);
|
val, num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1230,7 +1230,7 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid parent %d for clkout %d\n",
|
"invalid parent %d for clkout %d\n",
|
||||||
val, num);
|
val, num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
pdata->clkout[num].clkout_src =
|
pdata->clkout[num].clkout_src =
|
||||||
SI5351_CLKOUT_SRC_CLKIN;
|
SI5351_CLKOUT_SRC_CLKIN;
|
||||||
|
@ -1239,7 +1239,7 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid parent %d for clkout %d\n",
|
"invalid parent %d for clkout %d\n",
|
||||||
val, num);
|
val, num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1256,7 +1256,7 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid drive strength %d for clkout %d\n",
|
"invalid drive strength %d for clkout %d\n",
|
||||||
val, num);
|
val, num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1283,7 +1283,7 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
dev_err(&client->dev,
|
dev_err(&client->dev,
|
||||||
"invalid disable state %d for clkout %d\n",
|
"invalid disable state %d for clkout %d\n",
|
||||||
val, num);
|
val, num);
|
||||||
return -EINVAL;
|
goto put_child;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1296,6 +1296,9 @@ static int si5351_dt_parse(struct i2c_client *client,
|
||||||
client->dev.platform_data = pdata;
|
client->dev.platform_data = pdata;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
put_child:
|
||||||
|
of_node_put(child);
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int si5351_dt_parse(struct i2c_client *client, enum si5351_variant variant)
|
static int si5351_dt_parse(struct i2c_client *client, enum si5351_variant variant)
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <linux/clkdev.h>
|
#include <linux/clkdev.h>
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <asm/setup.h>
|
|
||||||
|
|
||||||
/* Register SCU_PCPPLL bit fields */
|
/* Register SCU_PCPPLL bit fields */
|
||||||
#define N_DIV_RD(src) (((src) & 0x000001ff))
|
#define N_DIV_RD(src) (((src) & 0x000001ff))
|
||||||
|
|
|
@ -272,7 +272,7 @@ late_initcall_sync(clk_disable_unused);
|
||||||
|
|
||||||
/*** helper functions ***/
|
/*** helper functions ***/
|
||||||
|
|
||||||
const char *__clk_get_name(struct clk *clk)
|
const char *__clk_get_name(const struct clk *clk)
|
||||||
{
|
{
|
||||||
return !clk ? NULL : clk->core->name;
|
return !clk ? NULL : clk->core->name;
|
||||||
}
|
}
|
||||||
|
@ -427,6 +427,11 @@ bool clk_hw_is_prepared(const struct clk_hw *hw)
|
||||||
return clk_core_is_prepared(hw->core);
|
return clk_core_is_prepared(hw->core);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool clk_hw_is_enabled(const struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
return clk_core_is_enabled(hw->core);
|
||||||
|
}
|
||||||
|
|
||||||
bool __clk_is_enabled(struct clk *clk)
|
bool __clk_is_enabled(struct clk *clk)
|
||||||
{
|
{
|
||||||
if (!clk)
|
if (!clk)
|
||||||
|
@ -1685,7 +1690,7 @@ static struct clk_core *__clk_init_parent(struct clk_core *core)
|
||||||
"%s: multi-parent clocks must implement .get_parent\n",
|
"%s: multi-parent clocks must implement .get_parent\n",
|
||||||
__func__);
|
__func__);
|
||||||
goto out;
|
goto out;
|
||||||
};
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Do our best to cache parent clocks in core->parents. This prevents
|
* Do our best to cache parent clocks in core->parents. This prevents
|
||||||
|
@ -2932,7 +2937,7 @@ struct clk *of_clk_src_onecell_get(struct of_phandle_args *clkspec, void *data)
|
||||||
unsigned int idx = clkspec->args[0];
|
unsigned int idx = clkspec->args[0];
|
||||||
|
|
||||||
if (idx >= clk_data->clk_num) {
|
if (idx >= clk_data->clk_num) {
|
||||||
pr_err("%s: invalid clock index %d\n", __func__, idx);
|
pr_err("%s: invalid clock index %u\n", __func__, idx);
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3055,6 +3060,7 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
|
||||||
u32 pv;
|
u32 pv;
|
||||||
int rc;
|
int rc;
|
||||||
int count;
|
int count;
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3080,8 +3086,25 @@ const char *of_clk_get_parent_name(struct device_node *np, int index)
|
||||||
|
|
||||||
if (of_property_read_string_index(clkspec.np, "clock-output-names",
|
if (of_property_read_string_index(clkspec.np, "clock-output-names",
|
||||||
index,
|
index,
|
||||||
&clk_name) < 0)
|
&clk_name) < 0) {
|
||||||
clk_name = clkspec.np->name;
|
/*
|
||||||
|
* Best effort to get the name if the clock has been
|
||||||
|
* registered with the framework. If the clock isn't
|
||||||
|
* registered, we return the node name as the name of
|
||||||
|
* the clock as long as #clock-cells = 0.
|
||||||
|
*/
|
||||||
|
clk = of_clk_get_from_provider(&clkspec);
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
if (clkspec.args_count == 0)
|
||||||
|
clk_name = clkspec.np->name;
|
||||||
|
else
|
||||||
|
clk_name = NULL;
|
||||||
|
} else {
|
||||||
|
clk_name = __clk_get_name(clk);
|
||||||
|
clk_put(clk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
of_node_put(clkspec.np);
|
of_node_put(clkspec.np);
|
||||||
return clk_name;
|
return clk_name;
|
||||||
|
@ -3179,13 +3202,15 @@ void __init of_clk_init(const struct of_device_id *matches)
|
||||||
list_for_each_entry_safe(clk_provider, next,
|
list_for_each_entry_safe(clk_provider, next,
|
||||||
&clk_provider_list, node) {
|
&clk_provider_list, node) {
|
||||||
list_del(&clk_provider->node);
|
list_del(&clk_provider->node);
|
||||||
|
of_node_put(clk_provider->np);
|
||||||
kfree(clk_provider);
|
kfree(clk_provider);
|
||||||
}
|
}
|
||||||
|
of_node_put(np);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent->clk_init_cb = match->data;
|
parent->clk_init_cb = match->data;
|
||||||
parent->np = np;
|
parent->np = of_node_get(np);
|
||||||
list_add_tail(&parent->node, &clk_provider_list);
|
list_add_tail(&parent->node, &clk_provider_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3199,6 +3224,7 @@ void __init of_clk_init(const struct of_device_id *matches)
|
||||||
of_clk_set_defaults(clk_provider->np, true);
|
of_clk_set_defaults(clk_provider->np, true);
|
||||||
|
|
||||||
list_del(&clk_provider->node);
|
list_del(&clk_provider->node);
|
||||||
|
of_node_put(clk_provider->np);
|
||||||
kfree(clk_provider);
|
kfree(clk_provider);
|
||||||
is_init_done = true;
|
is_init_done = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,7 @@ static int hi6220_stub_clk_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(stub_clk->mbox)) {
|
if (IS_ERR(stub_clk->mbox)) {
|
||||||
dev_err(dev, "failed get mailbox channel\n");
|
dev_err(dev, "failed get mailbox channel\n");
|
||||||
return PTR_ERR(stub_clk->mbox);
|
return PTR_ERR(stub_clk->mbox);
|
||||||
};
|
}
|
||||||
|
|
||||||
init.name = "acpu0";
|
init.name = "acpu0";
|
||||||
init.ops = &hi6220_stub_clk_ops;
|
init.ops = &hi6220_stub_clk_ops;
|
||||||
|
|
|
@ -86,6 +86,16 @@ enum mx25_clks {
|
||||||
|
|
||||||
static struct clk *clk[clk_max];
|
static struct clk *clk[clk_max];
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[uart_ipg_per],
|
||||||
|
&clk[uart1_ipg],
|
||||||
|
&clk[uart2_ipg],
|
||||||
|
&clk[uart3_ipg],
|
||||||
|
&clk[uart4_ipg],
|
||||||
|
&clk[uart5_ipg],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static int __init __mx25_clocks_init(unsigned long osc_rate,
|
static int __init __mx25_clocks_init(unsigned long osc_rate,
|
||||||
void __iomem *ccm_base)
|
void __iomem *ccm_base)
|
||||||
{
|
{
|
||||||
|
@ -233,6 +243,8 @@ static int __init __mx25_clocks_init(unsigned long osc_rate,
|
||||||
*/
|
*/
|
||||||
clk_set_parent(clk[cko_sel], clk[ipg]);
|
clk_set_parent(clk[cko_sel], clk[ipg]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,17 @@ static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
|
||||||
static struct clk *clk[IMX27_CLK_MAX];
|
static struct clk *clk[IMX27_CLK_MAX];
|
||||||
static struct clk_onecell_data clk_data;
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[IMX27_CLK_PER1_GATE],
|
||||||
|
&clk[IMX27_CLK_UART1_IPG_GATE],
|
||||||
|
&clk[IMX27_CLK_UART2_IPG_GATE],
|
||||||
|
&clk[IMX27_CLK_UART3_IPG_GATE],
|
||||||
|
&clk[IMX27_CLK_UART4_IPG_GATE],
|
||||||
|
&clk[IMX27_CLK_UART5_IPG_GATE],
|
||||||
|
&clk[IMX27_CLK_UART6_IPG_GATE],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init _mx27_clocks_init(unsigned long fref)
|
static void __init _mx27_clocks_init(unsigned long fref)
|
||||||
{
|
{
|
||||||
BUG_ON(!ccm);
|
BUG_ON(!ccm);
|
||||||
|
@ -163,6 +174,8 @@ static void __init _mx27_clocks_init(unsigned long fref)
|
||||||
|
|
||||||
clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
|
clk_prepare_enable(clk[IMX27_CLK_EMI_AHB_GATE]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
|
|
||||||
imx_print_silicon_rev("i.MX27", mx27_revision());
|
imx_print_silicon_rev("i.MX27", mx27_revision());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +261,10 @@ static void __init mx27_clocks_init_dt(struct device_node *np)
|
||||||
if (!of_device_is_compatible(refnp, "fsl,imx-osc26m"))
|
if (!of_device_is_compatible(refnp, "fsl,imx-osc26m"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!of_property_read_u32(refnp, "clock-frequency", &fref))
|
if (!of_property_read_u32(refnp, "clock-frequency", &fref)) {
|
||||||
|
of_node_put(refnp);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ccm = of_iomap(np, 0);
|
ccm = of_iomap(np, 0);
|
||||||
|
|
|
@ -62,7 +62,17 @@ enum mx31_clks {
|
||||||
static struct clk *clk[clk_max];
|
static struct clk *clk[clk_max];
|
||||||
static struct clk_onecell_data clk_data;
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
int __init mx31_clocks_init(unsigned long fref)
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[ipg],
|
||||||
|
&clk[uart1_gate],
|
||||||
|
&clk[uart2_gate],
|
||||||
|
&clk[uart3_gate],
|
||||||
|
&clk[uart4_gate],
|
||||||
|
&clk[uart5_gate],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init _mx31_clocks_init(unsigned long fref)
|
||||||
{
|
{
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -132,6 +142,12 @@ int __init mx31_clocks_init(unsigned long fref)
|
||||||
|
|
||||||
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
||||||
|
|
||||||
|
clk_set_parent(clk[csi], clk[upll]);
|
||||||
|
clk_prepare_enable(clk[emi_gate]);
|
||||||
|
clk_prepare_enable(clk[iim_gate]);
|
||||||
|
mx31_revision();
|
||||||
|
clk_disable_unprepare(clk[iim_gate]);
|
||||||
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
|
np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
|
||||||
|
|
||||||
if (np) {
|
if (np) {
|
||||||
|
@ -139,6 +155,13 @@ int __init mx31_clocks_init(unsigned long fref)
|
||||||
clk_data.clk_num = ARRAY_SIZE(clk);
|
clk_data.clk_num = ARRAY_SIZE(clk);
|
||||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init mx31_clocks_init(void)
|
||||||
|
{
|
||||||
|
u32 fref = 26000000; /* default */
|
||||||
|
|
||||||
|
_mx31_clocks_init(fref);
|
||||||
|
|
||||||
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
|
clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
|
||||||
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
|
clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
|
||||||
|
@ -194,12 +217,8 @@ int __init mx31_clocks_init(unsigned long fref)
|
||||||
clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
|
clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
|
||||||
clk_register_clkdev(clk[iim_gate], "iim", NULL);
|
clk_register_clkdev(clk[iim_gate], "iim", NULL);
|
||||||
|
|
||||||
clk_set_parent(clk[csi], clk[upll]);
|
|
||||||
clk_prepare_enable(clk[emi_gate]);
|
|
||||||
clk_prepare_enable(clk[iim_gate]);
|
|
||||||
mx31_revision();
|
|
||||||
clk_disable_unprepare(clk[iim_gate]);
|
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
|
mxc_timer_init(MX31_GPT1_BASE_ADDR, MX31_INT_GPT, GPT_TYPE_IMX31);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -214,9 +233,13 @@ int __init mx31_clocks_init_dt(void)
|
||||||
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
|
if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!of_property_read_u32(np, "clock-frequency", &fref))
|
if (!of_property_read_u32(np, "clock-frequency", &fref)) {
|
||||||
|
of_node_put(np);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mx31_clocks_init(fref);
|
_mx31_clocks_init(fref);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,15 @@ enum mx35_clks {
|
||||||
|
|
||||||
static struct clk *clk[clk_max];
|
static struct clk *clk[clk_max];
|
||||||
|
|
||||||
int __init mx35_clocks_init(void)
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[ipg],
|
||||||
|
&clk[uart1_gate],
|
||||||
|
&clk[uart2_gate],
|
||||||
|
&clk[uart3_gate],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static void __init _mx35_clocks_init(void)
|
||||||
{
|
{
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
u32 pdr0, consumer_sel, hsp_sel;
|
u32 pdr0, consumer_sel, hsp_sel;
|
||||||
|
@ -220,6 +228,32 @@ int __init mx35_clocks_init(void)
|
||||||
|
|
||||||
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
||||||
|
|
||||||
|
clk_prepare_enable(clk[spba_gate]);
|
||||||
|
clk_prepare_enable(clk[gpio1_gate]);
|
||||||
|
clk_prepare_enable(clk[gpio2_gate]);
|
||||||
|
clk_prepare_enable(clk[gpio3_gate]);
|
||||||
|
clk_prepare_enable(clk[iim_gate]);
|
||||||
|
clk_prepare_enable(clk[emi_gate]);
|
||||||
|
clk_prepare_enable(clk[max_gate]);
|
||||||
|
clk_prepare_enable(clk[iomuxc_gate]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCC is needed to boot via mmc after a watchdog reset. The clock code
|
||||||
|
* before conversion to common clk also enabled UART1 (which isn't
|
||||||
|
* handled here and not needed for mmc) and IIM (which is enabled
|
||||||
|
* unconditionally above).
|
||||||
|
*/
|
||||||
|
clk_prepare_enable(clk[scc_gate]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
|
|
||||||
|
imx_print_silicon_rev("i.MX35", mx35_revision());
|
||||||
|
}
|
||||||
|
|
||||||
|
int __init mx35_clocks_init(void)
|
||||||
|
{
|
||||||
|
_mx35_clocks_init();
|
||||||
|
|
||||||
clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
|
clk_register_clkdev(clk[pata_gate], NULL, "pata_imx");
|
||||||
clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
|
clk_register_clkdev(clk[can1_gate], NULL, "flexcan.0");
|
||||||
clk_register_clkdev(clk[can2_gate], NULL, "flexcan.1");
|
clk_register_clkdev(clk[can2_gate], NULL, "flexcan.1");
|
||||||
|
@ -279,25 +313,6 @@ int __init mx35_clocks_init(void)
|
||||||
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
|
clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
|
||||||
clk_register_clkdev(clk[admux_gate], "audmux", NULL);
|
clk_register_clkdev(clk[admux_gate], "audmux", NULL);
|
||||||
|
|
||||||
clk_prepare_enable(clk[spba_gate]);
|
|
||||||
clk_prepare_enable(clk[gpio1_gate]);
|
|
||||||
clk_prepare_enable(clk[gpio2_gate]);
|
|
||||||
clk_prepare_enable(clk[gpio3_gate]);
|
|
||||||
clk_prepare_enable(clk[iim_gate]);
|
|
||||||
clk_prepare_enable(clk[emi_gate]);
|
|
||||||
clk_prepare_enable(clk[max_gate]);
|
|
||||||
clk_prepare_enable(clk[iomuxc_gate]);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* SCC is needed to boot via mmc after a watchdog reset. The clock code
|
|
||||||
* before conversion to common clk also enabled UART1 (which isn't
|
|
||||||
* handled here and not needed for mmc) and IIM (which is enabled
|
|
||||||
* unconditionally above).
|
|
||||||
*/
|
|
||||||
clk_prepare_enable(clk[scc_gate]);
|
|
||||||
|
|
||||||
imx_print_silicon_rev("i.MX35", mx35_revision());
|
|
||||||
|
|
||||||
mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31);
|
mxc_timer_init(MX35_GPT1_BASE_ADDR, MX35_INT_GPT, GPT_TYPE_IMX31);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -305,10 +320,10 @@ int __init mx35_clocks_init(void)
|
||||||
|
|
||||||
static void __init mx35_clocks_init_dt(struct device_node *ccm_node)
|
static void __init mx35_clocks_init_dt(struct device_node *ccm_node)
|
||||||
{
|
{
|
||||||
|
_mx35_clocks_init();
|
||||||
|
|
||||||
clk_data.clks = clk;
|
clk_data.clks = clk;
|
||||||
clk_data.clk_num = ARRAY_SIZE(clk);
|
clk_data.clk_num = ARRAY_SIZE(clk);
|
||||||
of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
|
of_clk_add_provider(ccm_node, of_clk_src_onecell_get, &clk_data);
|
||||||
|
|
||||||
mx35_clocks_init();
|
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt);
|
CLK_OF_DECLARE(imx35, "fsl,imx35-ccm", mx35_clocks_init_dt);
|
||||||
|
|
|
@ -130,6 +130,20 @@ static const char *cpu_podf_sels[] = { "pll1_sw", "step_sel" };
|
||||||
static struct clk *clk[IMX5_CLK_END];
|
static struct clk *clk[IMX5_CLK_END];
|
||||||
static struct clk_onecell_data clk_data;
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[IMX5_CLK_UART1_IPG_GATE],
|
||||||
|
&clk[IMX5_CLK_UART1_PER_GATE],
|
||||||
|
&clk[IMX5_CLK_UART2_IPG_GATE],
|
||||||
|
&clk[IMX5_CLK_UART2_PER_GATE],
|
||||||
|
&clk[IMX5_CLK_UART3_IPG_GATE],
|
||||||
|
&clk[IMX5_CLK_UART3_PER_GATE],
|
||||||
|
&clk[IMX5_CLK_UART4_IPG_GATE],
|
||||||
|
&clk[IMX5_CLK_UART4_PER_GATE],
|
||||||
|
&clk[IMX5_CLK_UART5_IPG_GATE],
|
||||||
|
&clk[IMX5_CLK_UART5_PER_GATE],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init mx5_clocks_common_init(void __iomem *ccm_base)
|
static void __init mx5_clocks_common_init(void __iomem *ccm_base)
|
||||||
{
|
{
|
||||||
clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
|
clk[IMX5_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
|
||||||
|
@ -310,6 +324,8 @@ static void __init mx5_clocks_common_init(void __iomem *ccm_base)
|
||||||
clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
|
clk_prepare_enable(clk[IMX5_CLK_TMAX1]);
|
||||||
clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
|
clk_prepare_enable(clk[IMX5_CLK_TMAX2]); /* esdhc2, fec */
|
||||||
clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
|
clk_prepare_enable(clk[IMX5_CLK_TMAX3]); /* esdhc1, esdhc4 */
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init mx50_clocks_init(struct device_node *np)
|
static void __init mx50_clocks_init(struct device_node *np)
|
||||||
|
|
|
@ -119,6 +119,7 @@ static unsigned int share_count_ssi1;
|
||||||
static unsigned int share_count_ssi2;
|
static unsigned int share_count_ssi2;
|
||||||
static unsigned int share_count_ssi3;
|
static unsigned int share_count_ssi3;
|
||||||
static unsigned int share_count_mipi_core_cfg;
|
static unsigned int share_count_mipi_core_cfg;
|
||||||
|
static unsigned int share_count_spdif;
|
||||||
|
|
||||||
static inline int clk_on_imx6q(void)
|
static inline int clk_on_imx6q(void)
|
||||||
{
|
{
|
||||||
|
@ -130,6 +131,12 @@ static inline int clk_on_imx6dl(void)
|
||||||
return of_machine_is_compatible("fsl,imx6dl");
|
return of_machine_is_compatible("fsl,imx6dl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clk[IMX6QDL_CLK_UART_IPG],
|
||||||
|
&clk[IMX6QDL_CLK_UART_SERIAL],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -456,7 +463,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
||||||
clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4);
|
clk[IMX6QDL_CLK_SATA] = imx_clk_gate2("sata", "ahb", base + 0x7c, 4);
|
||||||
clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
|
clk[IMX6QDL_CLK_SDMA] = imx_clk_gate2("sdma", "ahb", base + 0x7c, 6);
|
||||||
clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
clk[IMX6QDL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
||||||
clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif_podf", base + 0x7c, 14);
|
clk[IMX6QDL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_spdif);
|
||||||
|
clk[IMX6QDL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_spdif);
|
||||||
clk[IMX6QDL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
clk[IMX6QDL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
||||||
clk[IMX6QDL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
clk[IMX6QDL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
||||||
clk[IMX6QDL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
clk[IMX6QDL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
||||||
|
@ -541,5 +549,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
|
||||||
/* All existing boards with PCIe use LVDS1 */
|
/* All existing boards with PCIe use LVDS1 */
|
||||||
if (IS_ENABLED(CONFIG_PCI_IMX6))
|
if (IS_ENABLED(CONFIG_PCI_IMX6))
|
||||||
clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
|
clk_set_parent(clk[IMX6QDL_CLK_LVDS1_SEL], clk[IMX6QDL_CLK_SATA_REF_100M]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
|
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);
|
||||||
|
|
|
@ -97,6 +97,7 @@ static struct clk_div_table video_div_table[] = {
|
||||||
static unsigned int share_count_ssi1;
|
static unsigned int share_count_ssi1;
|
||||||
static unsigned int share_count_ssi2;
|
static unsigned int share_count_ssi2;
|
||||||
static unsigned int share_count_ssi3;
|
static unsigned int share_count_ssi3;
|
||||||
|
static unsigned int share_count_spdif;
|
||||||
|
|
||||||
static struct clk *clks[IMX6SL_CLK_END];
|
static struct clk *clks[IMX6SL_CLK_END];
|
||||||
static struct clk_onecell_data clk_data;
|
static struct clk_onecell_data clk_data;
|
||||||
|
@ -184,6 +185,12 @@ void imx6sl_set_wait_clk(bool enter)
|
||||||
imx6sl_enable_pll_arm(false);
|
imx6sl_enable_pll_arm(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clks[IMX6SL_CLK_UART],
|
||||||
|
&clks[IMX6SL_CLK_UART_SERIAL],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init imx6sl_clocks_init(struct device_node *ccm_node)
|
static void __init imx6sl_clocks_init(struct device_node *ccm_node)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -391,7 +398,8 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
|
||||||
clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
|
clks[IMX6SL_CLK_PWM4] = imx_clk_gate2("pwm4", "perclk", base + 0x78, 22);
|
||||||
clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6);
|
clks[IMX6SL_CLK_SDMA] = imx_clk_gate2("sdma", "ipg", base + 0x7c, 6);
|
||||||
clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
clks[IMX6SL_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
||||||
clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2("spdif", "spdif0_podf", base + 0x7c, 14);
|
clks[IMX6SL_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif0_podf", base + 0x7c, 14, &share_count_spdif);
|
||||||
|
clks[IMX6SL_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_spdif);
|
||||||
clks[IMX6SL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
clks[IMX6SL_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
||||||
clks[IMX6SL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
clks[IMX6SL_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
||||||
clks[IMX6SL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
clks[IMX6SL_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
||||||
|
@ -439,5 +447,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
|
||||||
|
|
||||||
clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
|
clk_set_parent(clks[IMX6SL_CLK_LCDIF_AXI_SEL],
|
||||||
clks[IMX6SL_CLK_PLL2_PFD2]);
|
clks[IMX6SL_CLK_PLL2_PFD2]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
|
CLK_OF_DECLARE(imx6sl, "fsl,imx6sl-ccm", imx6sl_clocks_init);
|
||||||
|
|
|
@ -135,6 +135,12 @@ static u32 share_count_ssi1;
|
||||||
static u32 share_count_ssi2;
|
static u32 share_count_ssi2;
|
||||||
static u32 share_count_ssi3;
|
static u32 share_count_ssi3;
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clks[IMX6SX_CLK_UART_IPG],
|
||||||
|
&clks[IMX6SX_CLK_UART_SERIAL],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
|
static void __init imx6sx_clocks_init(struct device_node *ccm_node)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -454,6 +460,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
|
||||||
clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
clks[IMX6SX_CLK_SPBA] = imx_clk_gate2("spba", "ipg", base + 0x7c, 12);
|
||||||
clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio);
|
clks[IMX6SX_CLK_AUDIO] = imx_clk_gate2_shared("audio", "audio_podf", base + 0x7c, 14, &share_count_audio);
|
||||||
clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
|
clks[IMX6SX_CLK_SPDIF] = imx_clk_gate2_shared("spdif", "spdif_podf", base + 0x7c, 14, &share_count_audio);
|
||||||
|
clks[IMX6SX_CLK_SPDIF_GCLK] = imx_clk_gate2_shared("spdif_gclk", "ipg", base + 0x7c, 14, &share_count_audio);
|
||||||
clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
clks[IMX6SX_CLK_SSI1_IPG] = imx_clk_gate2_shared("ssi1_ipg", "ipg", base + 0x7c, 18, &share_count_ssi1);
|
||||||
clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
clks[IMX6SX_CLK_SSI2_IPG] = imx_clk_gate2_shared("ssi2_ipg", "ipg", base + 0x7c, 20, &share_count_ssi2);
|
||||||
clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
clks[IMX6SX_CLK_SSI3_IPG] = imx_clk_gate2_shared("ssi3_ipg", "ipg", base + 0x7c, 22, &share_count_ssi3);
|
||||||
|
@ -557,5 +564,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
|
||||||
|
|
||||||
clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
|
clk_set_parent(clks[IMX6SX_CLK_QSPI1_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
|
||||||
clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
|
clk_set_parent(clks[IMX6SX_CLK_QSPI2_SEL], clks[IMX6SX_CLK_PLL2_BUS]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
|
CLK_OF_DECLARE(imx6sx, "fsl,imx6sx-ccm", imx6sx_clocks_init);
|
||||||
|
|
|
@ -407,6 +407,24 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
|
||||||
clk_data.clk_num = ARRAY_SIZE(clks);
|
clk_data.clk_num = ARRAY_SIZE(clks);
|
||||||
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lower the AHB clock rate before changing the parent clock source,
|
||||||
|
* as AHB clock rate can NOT be higher than 133MHz, but its parent
|
||||||
|
* will be switched from 396MHz PFD to 528MHz PLL in order to increase
|
||||||
|
* AXI clock rate, so we need to lower AHB rate first to make sure at
|
||||||
|
* any time, AHB rate is <= 133MHz.
|
||||||
|
*/
|
||||||
|
clk_set_rate(clks[IMX6UL_CLK_AHB], 99000000);
|
||||||
|
|
||||||
|
/* Change periph_pre clock to pll2_bus to adjust AXI rate to 264MHz */
|
||||||
|
clk_set_parent(clks[IMX6UL_CLK_PERIPH_CLK2_SEL], clks[IMX6UL_CLK_PLL3_USB_OTG]);
|
||||||
|
clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_CLK2]);
|
||||||
|
clk_set_parent(clks[IMX6UL_CLK_PERIPH_PRE], clks[IMX6UL_CLK_PLL2_BUS]);
|
||||||
|
clk_set_parent(clks[IMX6UL_CLK_PERIPH], clks[IMX6UL_CLK_PERIPH_PRE]);
|
||||||
|
|
||||||
|
/* Make sure AHB rate is 132MHz */
|
||||||
|
clk_set_rate(clks[IMX6UL_CLK_AHB], 132000000);
|
||||||
|
|
||||||
/* set perclk to from OSC */
|
/* set perclk to from OSC */
|
||||||
clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
|
clk_set_parent(clks[IMX6UL_CLK_PERCLK_SEL], clks[IMX6UL_CLK_OSC]);
|
||||||
|
|
||||||
|
|
|
@ -363,6 +363,17 @@ static const char *pll_video_bypass_sel[] = { "pll_video_main", "pll_video_main_
|
||||||
|
|
||||||
static struct clk_onecell_data clk_data;
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
|
static struct clk ** const uart_clks[] __initconst = {
|
||||||
|
&clks[IMX7D_UART1_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART2_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART3_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART4_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART5_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART6_ROOT_CLK],
|
||||||
|
&clks[IMX7D_UART7_ROOT_CLK],
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||||
{
|
{
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
@ -818,6 +829,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||||
clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
|
clks[IMX7D_CSI_MCLK_ROOT_CLK] = imx_clk_gate2("csi_mclk_root_clk", "csi_mclk_post_div", base + 0x4490, 0);
|
||||||
clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
|
clks[IMX7D_AUDIO_MCLK_ROOT_CLK] = imx_clk_gate2("audio_mclk_root_clk", "audio_mclk_post_div", base + 0x4790, 0);
|
||||||
clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
|
clks[IMX7D_WRCLK_ROOT_CLK] = imx_clk_gate2("wrclk_root_clk", "wrclk_post_div", base + 0x47a0, 0);
|
||||||
|
clks[IMX7D_ADC_ROOT_CLK] = imx_clk_gate2("adc_root_clk", "ipg_root_clk", base + 0x4200, 0);
|
||||||
|
|
||||||
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
|
clks[IMX7D_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc", 1, 8);
|
||||||
|
|
||||||
|
@ -856,5 +868,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
|
||||||
/* set uart module clock's parent clock source that must be great then 80MHz */
|
/* set uart module clock's parent clock source that must be great then 80MHz */
|
||||||
clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
|
clk_set_parent(clks[IMX7D_UART1_ROOT_SRC], clks[IMX7D_OSC_24M_CLK]);
|
||||||
|
|
||||||
|
imx_register_uart_clocks(uart_clks);
|
||||||
|
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
|
CLK_OF_DECLARE(imx7d, "fsl,imx7d-ccm", imx7d_clocks_init);
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct clk_pllv2 {
|
||||||
static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
|
static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
|
||||||
u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn)
|
u32 dp_ctl, u32 dp_op, u32 dp_mfd, u32 dp_mfn)
|
||||||
{
|
{
|
||||||
long mfi, mfn, mfd, pdf, ref_clk, mfn_abs;
|
long mfi, mfn, mfd, pdf, ref_clk;
|
||||||
unsigned long dbl;
|
unsigned long dbl;
|
||||||
s64 temp;
|
s64 temp;
|
||||||
|
|
||||||
|
@ -87,19 +87,15 @@ static unsigned long __clk_pllv2_recalc_rate(unsigned long parent_rate,
|
||||||
mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
|
mfi = (dp_op & MXC_PLL_DP_OP_MFI_MASK) >> MXC_PLL_DP_OP_MFI_OFFSET;
|
||||||
mfi = (mfi <= 5) ? 5 : mfi;
|
mfi = (mfi <= 5) ? 5 : mfi;
|
||||||
mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
|
mfd = dp_mfd & MXC_PLL_DP_MFD_MASK;
|
||||||
mfn = mfn_abs = dp_mfn & MXC_PLL_DP_MFN_MASK;
|
mfn = dp_mfn & MXC_PLL_DP_MFN_MASK;
|
||||||
/* Sign extend to 32-bits */
|
mfn = sign_extend32(mfn, 26);
|
||||||
if (mfn >= 0x04000000) {
|
|
||||||
mfn |= 0xFC000000;
|
|
||||||
mfn_abs = -mfn;
|
|
||||||
}
|
|
||||||
|
|
||||||
ref_clk = 2 * parent_rate;
|
ref_clk = 2 * parent_rate;
|
||||||
if (dbl != 0)
|
if (dbl != 0)
|
||||||
ref_clk *= 2;
|
ref_clk *= 2;
|
||||||
|
|
||||||
ref_clk /= (pdf + 1);
|
ref_clk /= (pdf + 1);
|
||||||
temp = (u64) ref_clk * mfn_abs;
|
temp = (u64) ref_clk * abs(mfn);
|
||||||
do_div(temp, mfd + 1);
|
do_div(temp, mfd + 1);
|
||||||
if (mfn < 0)
|
if (mfn < 0)
|
||||||
temp = -temp;
|
temp = -temp;
|
||||||
|
|
|
@ -387,6 +387,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
|
||||||
|
|
||||||
clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
|
clk[VF610_CLK_SNVS] = imx_clk_gate2("snvs-rtc", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(7));
|
||||||
clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24);
|
clk[VF610_CLK_DAP] = imx_clk_gate("dap", "platform_bus", CCM_CCSR, 24);
|
||||||
|
clk[VF610_CLK_OCOTP] = imx_clk_gate("ocotp", "ipg_bus", CCM_CCGR6, CCM_CCGRx_CGn(5));
|
||||||
|
|
||||||
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
imx_check_clocks(clk, ARRAY_SIZE(clk));
|
||||||
|
|
||||||
|
|
|
@ -73,3 +73,41 @@ void imx_cscmr1_fixup(u32 *val)
|
||||||
*val ^= CSCMR1_FIXUP;
|
*val ^= CSCMR1_FIXUP;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int imx_keep_uart_clocks __initdata;
|
||||||
|
static struct clk ** const *imx_uart_clocks __initdata;
|
||||||
|
|
||||||
|
static int __init imx_keep_uart_clocks_param(char *str)
|
||||||
|
{
|
||||||
|
imx_keep_uart_clocks = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
__setup_param("earlycon", imx_keep_uart_earlycon,
|
||||||
|
imx_keep_uart_clocks_param, 0);
|
||||||
|
__setup_param("earlyprintk", imx_keep_uart_earlyprintk,
|
||||||
|
imx_keep_uart_clocks_param, 0);
|
||||||
|
|
||||||
|
void __init imx_register_uart_clocks(struct clk ** const clks[])
|
||||||
|
{
|
||||||
|
if (imx_keep_uart_clocks) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
imx_uart_clocks = clks;
|
||||||
|
for (i = 0; imx_uart_clocks[i]; i++)
|
||||||
|
clk_prepare_enable(*imx_uart_clocks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __init imx_clk_disable_uart(void)
|
||||||
|
{
|
||||||
|
if (imx_keep_uart_clocks && imx_uart_clocks) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; imx_uart_clocks[i]; i++)
|
||||||
|
clk_disable_unprepare(*imx_uart_clocks[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
late_initcall_sync(imx_clk_disable_uart);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
extern spinlock_t imx_ccm_lock;
|
extern spinlock_t imx_ccm_lock;
|
||||||
|
|
||||||
void imx_check_clocks(struct clk *clks[], unsigned int count);
|
void imx_check_clocks(struct clk *clks[], unsigned int count);
|
||||||
|
void imx_register_uart_clocks(struct clk ** const clks[]);
|
||||||
|
|
||||||
extern void imx_cscmr1_fixup(u32 *val);
|
extern void imx_cscmr1_fixup(u32 *val);
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ out:
|
||||||
* _of_clk_init - PLL initialisation via DT
|
* _of_clk_init - PLL initialisation via DT
|
||||||
* @node: device tree node for this clock
|
* @node: device tree node for this clock
|
||||||
* @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
|
* @pllctrl: If true, lower 6 bits of multiplier is in pllm register of
|
||||||
* pll controller, else it is in the control regsiter0(bit 11-6)
|
* pll controller, else it is in the control register0(bit 11-6)
|
||||||
*/
|
*/
|
||||||
static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
|
static void __init _of_pll_clk_init(struct device_node *node, bool pllctrl)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
obj-y += clk-mtk.o clk-pll.o clk-gate.o
|
obj-y += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
|
||||||
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
obj-$(CONFIG_RESET_CONTROLLER) += reset.o
|
||||||
obj-y += clk-mt8135.o
|
obj-y += clk-mt8135.o
|
||||||
obj-y += clk-mt8173.o
|
obj-y += clk-mt8173.o
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015 MediaTek Inc.
|
||||||
|
* Author: James Liao <jamesjj.liao@mediatek.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.
|
||||||
|
*
|
||||||
|
* 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/delay.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
|
||||||
|
#include "clk-mtk.h"
|
||||||
|
|
||||||
|
#define REF2USB_TX_EN BIT(0)
|
||||||
|
#define REF2USB_TX_LPF_EN BIT(1)
|
||||||
|
#define REF2USB_TX_OUT_EN BIT(2)
|
||||||
|
#define REF2USB_EN_MASK (REF2USB_TX_EN | REF2USB_TX_LPF_EN | \
|
||||||
|
REF2USB_TX_OUT_EN)
|
||||||
|
|
||||||
|
struct mtk_ref2usb_tx {
|
||||||
|
struct clk_hw hw;
|
||||||
|
void __iomem *base_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct mtk_ref2usb_tx *to_mtk_ref2usb_tx(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
return container_of(hw, struct mtk_ref2usb_tx, hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_ref2usb_tx_is_prepared(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
|
||||||
|
|
||||||
|
return (readl(tx->base_addr) & REF2USB_EN_MASK) == REF2USB_EN_MASK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mtk_ref2usb_tx_prepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = readl(tx->base_addr);
|
||||||
|
|
||||||
|
val |= REF2USB_TX_EN;
|
||||||
|
writel(val, tx->base_addr);
|
||||||
|
udelay(100);
|
||||||
|
|
||||||
|
val |= REF2USB_TX_LPF_EN;
|
||||||
|
writel(val, tx->base_addr);
|
||||||
|
|
||||||
|
val |= REF2USB_TX_OUT_EN;
|
||||||
|
writel(val, tx->base_addr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mtk_ref2usb_tx_unprepare(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct mtk_ref2usb_tx *tx = to_mtk_ref2usb_tx(hw);
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
val = readl(tx->base_addr);
|
||||||
|
val &= ~REF2USB_EN_MASK;
|
||||||
|
writel(val, tx->base_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops mtk_ref2usb_tx_ops = {
|
||||||
|
.is_prepared = mtk_ref2usb_tx_is_prepared,
|
||||||
|
.prepare = mtk_ref2usb_tx_prepare,
|
||||||
|
.unprepare = mtk_ref2usb_tx_unprepare,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk * __init mtk_clk_register_ref2usb_tx(const char *name,
|
||||||
|
const char *parent_name, void __iomem *reg)
|
||||||
|
{
|
||||||
|
struct mtk_ref2usb_tx *tx;
|
||||||
|
struct clk_init_data init = {};
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
|
tx = kzalloc(sizeof(*tx), GFP_KERNEL);
|
||||||
|
if (!tx)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
tx->base_addr = reg;
|
||||||
|
tx->hw.init = &init;
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &mtk_ref2usb_tx_ops;
|
||||||
|
init.parent_names = &parent_name;
|
||||||
|
init.num_parents = 1;
|
||||||
|
|
||||||
|
clk = clk_register(NULL, &tx->hw);
|
||||||
|
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
pr_err("Failed to register clk %s: %ld\n", name, PTR_ERR(clk));
|
||||||
|
kfree(tx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
|
@ -97,7 +97,7 @@ const struct clk_ops mtk_clk_gate_ops_setclr_inv = {
|
||||||
.disable = mtk_cg_disable_inv,
|
.disable = mtk_cg_disable_inv,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct clk *mtk_clk_register_gate(
|
struct clk * __init mtk_clk_register_gate(
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *parent_name,
|
const char *parent_name,
|
||||||
struct regmap *regmap,
|
struct regmap *regmap,
|
||||||
|
|
|
@ -15,21 +15,28 @@
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/slab.h>
|
|
||||||
#include <linux/mfd/syscon.h>
|
|
||||||
|
|
||||||
#include "clk-mtk.h"
|
#include "clk-mtk.h"
|
||||||
#include "clk-gate.h"
|
#include "clk-gate.h"
|
||||||
|
|
||||||
#include <dt-bindings/clock/mt8173-clk.h>
|
#include <dt-bindings/clock/mt8173-clk.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For some clocks, we don't care what their actual rates are. And these
|
||||||
|
* clocks may change their rate on different products or different scenarios.
|
||||||
|
* So we model these clocks' rate as 0, to denote it's not an actual rate.
|
||||||
|
*/
|
||||||
|
#define DUMMY_RATE 0
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(mt8173_clk_lock);
|
static DEFINE_SPINLOCK(mt8173_clk_lock);
|
||||||
|
|
||||||
static const struct mtk_fixed_factor root_clk_alias[] __initconst = {
|
static const struct mtk_fixed_clk fixed_clks[] __initconst = {
|
||||||
FACTOR(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk_null", 1, 1),
|
FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", "clk26m", DUMMY_RATE),
|
||||||
FACTOR(CLK_TOP_DPI, "dpi_ck", "clk_null", 1, 1),
|
FIXED_CLK(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk26m", 125 * MHZ),
|
||||||
FACTOR(CLK_TOP_USB_SYSPLL_125M, "usb_syspll_125m", "clk_null", 1, 1),
|
FIXED_CLK(CLK_TOP_DSI0_DIG, "dsi0_dig", "clk26m", DUMMY_RATE),
|
||||||
FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "clk_null", 1, 1),
|
FIXED_CLK(CLK_TOP_DSI1_DIG, "dsi1_dig", "clk26m", DUMMY_RATE),
|
||||||
|
FIXED_CLK(CLK_TOP_LVDS_PXL, "lvds_pxl", "lvdspll", DUMMY_RATE),
|
||||||
|
FIXED_CLK(CLK_TOP_LVDS_CTS, "lvds_cts", "lvdspll", DUMMY_RATE),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mtk_fixed_factor top_divs[] __initconst = {
|
static const struct mtk_fixed_factor top_divs[] __initconst = {
|
||||||
|
@ -54,6 +61,7 @@ static const struct mtk_fixed_factor top_divs[] __initconst = {
|
||||||
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
|
FACTOR(CLK_TOP_CLKRTC_INT, "clkrtc_int", "clk26m", 1, 793),
|
||||||
FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
|
FACTOR(CLK_TOP_FPC, "fpc_ck", "clk26m", 1, 1),
|
||||||
|
|
||||||
|
FACTOR(CLK_TOP_HDMITX_DIG_CTS, "hdmitx_dig_cts", "tvdpll_445p5m", 1, 3),
|
||||||
FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
|
FACTOR(CLK_TOP_HDMITXPLL_D2, "hdmitxpll_d2", "hdmitx_dig_cts", 1, 2),
|
||||||
FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
|
FACTOR(CLK_TOP_HDMITXPLL_D3, "hdmitxpll_d3", "hdmitx_dig_cts", 1, 3),
|
||||||
|
|
||||||
|
@ -590,7 +598,7 @@ static const struct mtk_composite top_muxes[] __initconst = {
|
||||||
MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
|
MUX(CLK_TOP_I2S3_B_SEL, "i2s3_b_ck_sel", i2s3_b_ck_parents, 0x120, 8, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mtk_gate_regs infra_cg_regs = {
|
static const struct mtk_gate_regs infra_cg_regs __initconst = {
|
||||||
.set_ofs = 0x0040,
|
.set_ofs = 0x0040,
|
||||||
.clr_ofs = 0x0044,
|
.clr_ofs = 0x0044,
|
||||||
.sta_ofs = 0x0048,
|
.sta_ofs = 0x0048,
|
||||||
|
@ -612,20 +620,24 @@ static const struct mtk_gate infra_clks[] __initconst = {
|
||||||
GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
|
GATE_ICG(CLK_INFRA_GCE, "infra_gce", "axi_sel", 6),
|
||||||
GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
|
GATE_ICG(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "axi_sel", 7),
|
||||||
GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
|
GATE_ICG(CLK_INFRA_M4U, "infra_m4u", "mem_sel", 8),
|
||||||
GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "clk_null", 15),
|
GATE_ICG(CLK_INFRA_CPUM, "infra_cpum", "cpum_ck", 15),
|
||||||
GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
|
GATE_ICG(CLK_INFRA_KP, "infra_kp", "axi_sel", 16),
|
||||||
GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
|
GATE_ICG(CLK_INFRA_CEC, "infra_cec", "clk26m", 18),
|
||||||
GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
|
GATE_ICG(CLK_INFRA_PMICSPI, "infra_pmicspi", "pmicspi_sel", 22),
|
||||||
GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
|
GATE_ICG(CLK_INFRA_PMICWRAP, "infra_pmicwrap", "axi_sel", 23),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mtk_gate_regs peri0_cg_regs = {
|
static const struct mtk_fixed_factor infra_divs[] __initconst = {
|
||||||
|
FACTOR(CLK_INFRA_CLK_13M, "clk13m", "clk26m", 1, 2),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs peri0_cg_regs __initconst = {
|
||||||
.set_ofs = 0x0008,
|
.set_ofs = 0x0008,
|
||||||
.clr_ofs = 0x0010,
|
.clr_ofs = 0x0010,
|
||||||
.sta_ofs = 0x0018,
|
.sta_ofs = 0x0018,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct mtk_gate_regs peri1_cg_regs = {
|
static const struct mtk_gate_regs peri1_cg_regs __initconst = {
|
||||||
.set_ofs = 0x000c,
|
.set_ofs = 0x000c,
|
||||||
.clr_ofs = 0x0014,
|
.clr_ofs = 0x0014,
|
||||||
.sta_ofs = 0x001c,
|
.sta_ofs = 0x001c,
|
||||||
|
@ -701,6 +713,183 @@ static const struct mtk_composite peri_clks[] __initconst = {
|
||||||
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
|
MUX(CLK_PERI_UART3_SEL, "uart3_ck_sel", uart_ck_sel_parents, 0x40c, 3, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs cg_regs_4_8_0 __initconst = {
|
||||||
|
.set_ofs = 0x0004,
|
||||||
|
.clr_ofs = 0x0008,
|
||||||
|
.sta_ofs = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GATE_IMG(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &cg_regs_4_8_0, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_gate img_clks[] __initconst = {
|
||||||
|
GATE_IMG(CLK_IMG_LARB2_SMI, "img_larb2_smi", "mm_sel", 0),
|
||||||
|
GATE_IMG(CLK_IMG_CAM_SMI, "img_cam_smi", "mm_sel", 5),
|
||||||
|
GATE_IMG(CLK_IMG_CAM_CAM, "img_cam_cam", "mm_sel", 6),
|
||||||
|
GATE_IMG(CLK_IMG_SEN_TG, "img_sen_tg", "camtg_sel", 7),
|
||||||
|
GATE_IMG(CLK_IMG_SEN_CAM, "img_sen_cam", "mm_sel", 8),
|
||||||
|
GATE_IMG(CLK_IMG_CAM_SV, "img_cam_sv", "mm_sel", 9),
|
||||||
|
GATE_IMG(CLK_IMG_FD, "img_fd", "mm_sel", 11),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs mm0_cg_regs __initconst = {
|
||||||
|
.set_ofs = 0x0104,
|
||||||
|
.clr_ofs = 0x0108,
|
||||||
|
.sta_ofs = 0x0100,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs mm1_cg_regs __initconst = {
|
||||||
|
.set_ofs = 0x0114,
|
||||||
|
.clr_ofs = 0x0118,
|
||||||
|
.sta_ofs = 0x0110,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GATE_MM0(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &mm0_cg_regs, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GATE_MM1(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &mm1_cg_regs, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_gate mm_clks[] __initconst = {
|
||||||
|
/* MM0 */
|
||||||
|
GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
|
||||||
|
GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
|
||||||
|
GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 2),
|
||||||
|
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 3),
|
||||||
|
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 4),
|
||||||
|
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 5),
|
||||||
|
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 6),
|
||||||
|
GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 7),
|
||||||
|
GATE_MM0(CLK_MM_MDP_TDSHP0, "mm_mdp_tdshp0", "mm_sel", 8),
|
||||||
|
GATE_MM0(CLK_MM_MDP_TDSHP1, "mm_mdp_tdshp1", "mm_sel", 9),
|
||||||
|
GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
|
||||||
|
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
|
||||||
|
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
|
||||||
|
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
|
||||||
|
GATE_MM0(CLK_MM_MUTEX_32K, "mm_mutex_32k", "rtc_sel", 15),
|
||||||
|
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 16),
|
||||||
|
GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 17),
|
||||||
|
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 18),
|
||||||
|
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 19),
|
||||||
|
GATE_MM0(CLK_MM_DISP_RDMA2, "mm_disp_rdma2", "mm_sel", 20),
|
||||||
|
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
|
||||||
|
GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
|
||||||
|
GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 23),
|
||||||
|
GATE_MM0(CLK_MM_DISP_COLOR1, "mm_disp_color1", "mm_sel", 24),
|
||||||
|
GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
|
||||||
|
GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
|
||||||
|
GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 27),
|
||||||
|
GATE_MM0(CLK_MM_DISP_SPLIT0, "mm_disp_split0", "mm_sel", 28),
|
||||||
|
GATE_MM0(CLK_MM_DISP_SPLIT1, "mm_disp_split1", "mm_sel", 29),
|
||||||
|
GATE_MM0(CLK_MM_DISP_MERGE, "mm_disp_merge", "mm_sel", 30),
|
||||||
|
GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 31),
|
||||||
|
/* MM1 */
|
||||||
|
GATE_MM1(CLK_MM_DISP_PWM0MM, "mm_disp_pwm0mm", "mm_sel", 0),
|
||||||
|
GATE_MM1(CLK_MM_DISP_PWM026M, "mm_disp_pwm026m", "pwm_sel", 1),
|
||||||
|
GATE_MM1(CLK_MM_DISP_PWM1MM, "mm_disp_pwm1mm", "mm_sel", 2),
|
||||||
|
GATE_MM1(CLK_MM_DISP_PWM126M, "mm_disp_pwm126m", "pwm_sel", 3),
|
||||||
|
GATE_MM1(CLK_MM_DSI0_ENGINE, "mm_dsi0_engine", "mm_sel", 4),
|
||||||
|
GATE_MM1(CLK_MM_DSI0_DIGITAL, "mm_dsi0_digital", "dsi0_dig", 5),
|
||||||
|
GATE_MM1(CLK_MM_DSI1_ENGINE, "mm_dsi1_engine", "mm_sel", 6),
|
||||||
|
GATE_MM1(CLK_MM_DSI1_DIGITAL, "mm_dsi1_digital", "dsi1_dig", 7),
|
||||||
|
GATE_MM1(CLK_MM_DPI_PIXEL, "mm_dpi_pixel", "dpi0_sel", 8),
|
||||||
|
GATE_MM1(CLK_MM_DPI_ENGINE, "mm_dpi_engine", "mm_sel", 9),
|
||||||
|
GATE_MM1(CLK_MM_DPI1_PIXEL, "mm_dpi1_pixel", "lvds_pxl", 10),
|
||||||
|
GATE_MM1(CLK_MM_DPI1_ENGINE, "mm_dpi1_engine", "mm_sel", 11),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_PIXEL, "mm_hdmi_pixel", "dpi0_sel", 12),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_PLLCK, "mm_hdmi_pllck", "hdmi_sel", 13),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_AUDIO, "mm_hdmi_audio", "apll1", 14),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_SPDIF, "mm_hdmi_spdif", "apll2", 15),
|
||||||
|
GATE_MM1(CLK_MM_LVDS_PIXEL, "mm_lvds_pixel", "lvds_pxl", 16),
|
||||||
|
GATE_MM1(CLK_MM_LVDS_CTS, "mm_lvds_cts", "lvds_cts", 17),
|
||||||
|
GATE_MM1(CLK_MM_SMI_LARB4, "mm_smi_larb4", "mm_sel", 18),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_HDCP, "mm_hdmi_hdcp", "hdcp_sel", 19),
|
||||||
|
GATE_MM1(CLK_MM_HDMI_HDCP24M, "mm_hdmi_hdcp24m", "hdcp_24m_sel", 20),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs vdec0_cg_regs __initconst = {
|
||||||
|
.set_ofs = 0x0000,
|
||||||
|
.clr_ofs = 0x0004,
|
||||||
|
.sta_ofs = 0x0000,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_gate_regs vdec1_cg_regs __initconst = {
|
||||||
|
.set_ofs = 0x0008,
|
||||||
|
.clr_ofs = 0x000c,
|
||||||
|
.sta_ofs = 0x0008,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GATE_VDEC0(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &vdec0_cg_regs, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GATE_VDEC1(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &vdec1_cg_regs, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_gate vdec_clks[] __initconst = {
|
||||||
|
GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
|
||||||
|
GATE_VDEC1(CLK_VDEC_LARB_CKEN, "vdec_larb_cken", "mm_sel", 0),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GATE_VENC(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &cg_regs_4_8_0, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_gate venc_clks[] __initconst = {
|
||||||
|
GATE_VENC(CLK_VENC_CKE0, "venc_cke0", "mm_sel", 0),
|
||||||
|
GATE_VENC(CLK_VENC_CKE1, "venc_cke1", "venc_sel", 4),
|
||||||
|
GATE_VENC(CLK_VENC_CKE2, "venc_cke2", "venc_sel", 8),
|
||||||
|
GATE_VENC(CLK_VENC_CKE3, "venc_cke3", "venc_sel", 12),
|
||||||
|
};
|
||||||
|
|
||||||
|
#define GATE_VENCLT(_id, _name, _parent, _shift) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent_name = _parent, \
|
||||||
|
.regs = &cg_regs_4_8_0, \
|
||||||
|
.shift = _shift, \
|
||||||
|
.ops = &mtk_clk_gate_ops_setclr_inv, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_gate venclt_clks[] __initconst = {
|
||||||
|
GATE_VENCLT(CLK_VENCLT_CKE0, "venclt_cke0", "mm_sel", 0),
|
||||||
|
GATE_VENCLT(CLK_VENCLT_CKE1, "venclt_cke1", "venclt_sel", 4),
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_onecell_data *mt8173_top_clk_data __initdata;
|
static struct clk_onecell_data *mt8173_top_clk_data __initdata;
|
||||||
static struct clk_onecell_data *mt8173_pll_clk_data __initdata;
|
static struct clk_onecell_data *mt8173_pll_clk_data __initdata;
|
||||||
|
|
||||||
|
@ -731,7 +920,7 @@ static void __init mtk_topckgen_init(struct device_node *node)
|
||||||
|
|
||||||
mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
mt8173_top_clk_data = clk_data = mtk_alloc_clk_data(CLK_TOP_NR_CLK);
|
||||||
|
|
||||||
mtk_clk_register_factors(root_clk_alias, ARRAY_SIZE(root_clk_alias), clk_data);
|
mtk_clk_register_fixed_clks(fixed_clks, ARRAY_SIZE(fixed_clks), clk_data);
|
||||||
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
mtk_clk_register_factors(top_divs, ARRAY_SIZE(top_divs), clk_data);
|
||||||
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
|
mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
|
||||||
&mt8173_clk_lock, clk_data);
|
&mt8173_clk_lock, clk_data);
|
||||||
|
@ -754,6 +943,7 @@ static void __init mtk_infrasys_init(struct device_node *node)
|
||||||
|
|
||||||
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
|
||||||
clk_data);
|
clk_data);
|
||||||
|
mtk_clk_register_factors(infra_divs, ARRAY_SIZE(infra_divs), clk_data);
|
||||||
|
|
||||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
if (r)
|
if (r)
|
||||||
|
@ -792,6 +982,24 @@ static void __init mtk_pericfg_init(struct device_node *node)
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
|
CLK_OF_DECLARE(mtk_pericfg, "mediatek,mt8173-pericfg", mtk_pericfg_init);
|
||||||
|
|
||||||
|
struct mtk_clk_usb {
|
||||||
|
int id;
|
||||||
|
const char *name;
|
||||||
|
const char *parent;
|
||||||
|
u32 reg_ofs;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define APMIXED_USB(_id, _name, _parent, _reg_ofs) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent = _parent, \
|
||||||
|
.reg_ofs = _reg_ofs, \
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct mtk_clk_usb apmixed_usb[] __initconst = {
|
||||||
|
APMIXED_USB(CLK_APMIXED_REF2USB_TX, "ref2usb_tx", "clk26m", 0x8),
|
||||||
|
};
|
||||||
|
|
||||||
#define MT8173_PLL_FMAX (3000UL * MHZ)
|
#define MT8173_PLL_FMAX (3000UL * MHZ)
|
||||||
|
|
||||||
#define CON0_MT8173_RST_BAR BIT(24)
|
#define CON0_MT8173_RST_BAR BIT(24)
|
||||||
|
@ -852,6 +1060,15 @@ static const struct mtk_pll_data plls[] = {
|
||||||
static void __init mtk_apmixedsys_init(struct device_node *node)
|
static void __init mtk_apmixedsys_init(struct device_node *node)
|
||||||
{
|
{
|
||||||
struct clk_onecell_data *clk_data;
|
struct clk_onecell_data *clk_data;
|
||||||
|
void __iomem *base;
|
||||||
|
struct clk *clk;
|
||||||
|
int r, i;
|
||||||
|
|
||||||
|
base = of_iomap(node, 0);
|
||||||
|
if (!base) {
|
||||||
|
pr_err("%s(): ioremap failed\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
mt8173_pll_clk_data = clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR_CLK);
|
||||||
if (!clk_data)
|
if (!clk_data)
|
||||||
|
@ -859,7 +1076,113 @@ static void __init mtk_apmixedsys_init(struct device_node *node)
|
||||||
|
|
||||||
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(apmixed_usb); i++) {
|
||||||
|
const struct mtk_clk_usb *cku = &apmixed_usb[i];
|
||||||
|
|
||||||
|
clk = mtk_clk_register_ref2usb_tx(cku->name, cku->parent,
|
||||||
|
base + cku->reg_ofs);
|
||||||
|
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
pr_err("Failed to register clk %s: %ld\n", cku->name,
|
||||||
|
PTR_ERR(clk));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_data->clks[cku->id] = clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
|
||||||
mtk_clk_enable_critical();
|
mtk_clk_enable_critical();
|
||||||
}
|
}
|
||||||
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
|
CLK_OF_DECLARE(mtk_apmixedsys, "mediatek,mt8173-apmixedsys",
|
||||||
mtk_apmixedsys_init);
|
mtk_apmixedsys_init);
|
||||||
|
|
||||||
|
static void __init mtk_imgsys_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
|
||||||
|
|
||||||
|
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
|
||||||
|
clk_data);
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(mtk_imgsys, "mediatek,mt8173-imgsys", mtk_imgsys_init);
|
||||||
|
|
||||||
|
static void __init mtk_mmsys_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
|
||||||
|
|
||||||
|
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
|
||||||
|
clk_data);
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(mtk_mmsys, "mediatek,mt8173-mmsys", mtk_mmsys_init);
|
||||||
|
|
||||||
|
static void __init mtk_vdecsys_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
clk_data = mtk_alloc_clk_data(CLK_VDEC_NR_CLK);
|
||||||
|
|
||||||
|
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
|
||||||
|
clk_data);
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(mtk_vdecsys, "mediatek,mt8173-vdecsys", mtk_vdecsys_init);
|
||||||
|
|
||||||
|
static void __init mtk_vencsys_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
clk_data = mtk_alloc_clk_data(CLK_VENC_NR_CLK);
|
||||||
|
|
||||||
|
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
|
||||||
|
clk_data);
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(mtk_vencsys, "mediatek,mt8173-vencsys", mtk_vencsys_init);
|
||||||
|
|
||||||
|
static void __init mtk_vencltsys_init(struct device_node *node)
|
||||||
|
{
|
||||||
|
struct clk_onecell_data *clk_data;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
clk_data = mtk_alloc_clk_data(CLK_VENCLT_NR_CLK);
|
||||||
|
|
||||||
|
mtk_clk_register_gates(node, venclt_clks, ARRAY_SIZE(venclt_clks),
|
||||||
|
clk_data);
|
||||||
|
|
||||||
|
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
||||||
|
if (r)
|
||||||
|
pr_err("%s(): could not register clock provider: %d\n",
|
||||||
|
__func__, r);
|
||||||
|
}
|
||||||
|
CLK_OF_DECLARE(mtk_vencltsys, "mediatek,mt8173-vencltsys", mtk_vencltsys_init);
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "clk-mtk.h"
|
#include "clk-mtk.h"
|
||||||
#include "clk-gate.h"
|
#include "clk-gate.h"
|
||||||
|
|
||||||
struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
|
struct clk_onecell_data * __init mtk_alloc_clk_data(unsigned int clk_num)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct clk_onecell_data *clk_data;
|
struct clk_onecell_data *clk_data;
|
||||||
|
@ -49,8 +49,31 @@ err_out:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
|
void __init mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
|
||||||
struct clk_onecell_data *clk_data)
|
int num, struct clk_onecell_data *clk_data)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct clk *clk;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
const struct mtk_fixed_clk *rc = &clks[i];
|
||||||
|
|
||||||
|
clk = clk_register_fixed_rate(NULL, rc->name, rc->parent,
|
||||||
|
rc->parent ? 0 : CLK_IS_ROOT, rc->rate);
|
||||||
|
|
||||||
|
if (IS_ERR(clk)) {
|
||||||
|
pr_err("Failed to register clk %s: %ld\n",
|
||||||
|
rc->name, PTR_ERR(clk));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clk_data)
|
||||||
|
clk_data->clks[rc->id] = clk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __init mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
|
||||||
|
int num, struct clk_onecell_data *clk_data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
@ -72,7 +95,8 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks, int num,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks,
|
int __init mtk_clk_register_gates(struct device_node *node,
|
||||||
|
const struct mtk_gate *clks,
|
||||||
int num, struct clk_onecell_data *clk_data)
|
int num, struct clk_onecell_data *clk_data)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -111,7 +135,7 @@ int mtk_clk_register_gates(struct device_node *node, const struct mtk_gate *clks
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
|
struct clk * __init mtk_clk_register_composite(const struct mtk_composite *mc,
|
||||||
void __iomem *base, spinlock_t *lock)
|
void __iomem *base, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
@ -196,7 +220,7 @@ err_out:
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void mtk_clk_register_composites(const struct mtk_composite *mcs,
|
void __init mtk_clk_register_composites(const struct mtk_composite *mcs,
|
||||||
int num, void __iomem *base, spinlock_t *lock,
|
int num, void __iomem *base, spinlock_t *lock,
|
||||||
struct clk_onecell_data *clk_data)
|
struct clk_onecell_data *clk_data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,23 @@ struct clk;
|
||||||
|
|
||||||
#define MHZ (1000 * 1000)
|
#define MHZ (1000 * 1000)
|
||||||
|
|
||||||
|
struct mtk_fixed_clk {
|
||||||
|
int id;
|
||||||
|
const char *name;
|
||||||
|
const char *parent;
|
||||||
|
unsigned long rate;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FIXED_CLK(_id, _name, _parent, _rate) { \
|
||||||
|
.id = _id, \
|
||||||
|
.name = _name, \
|
||||||
|
.parent = _parent, \
|
||||||
|
.rate = _rate, \
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
|
||||||
|
int num, struct clk_onecell_data *clk_data);
|
||||||
|
|
||||||
struct mtk_fixed_factor {
|
struct mtk_fixed_factor {
|
||||||
int id;
|
int id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -42,7 +59,7 @@ struct mtk_fixed_factor {
|
||||||
.div = _div, \
|
.div = _div, \
|
||||||
}
|
}
|
||||||
|
|
||||||
extern void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
|
void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
|
||||||
int num, struct clk_onecell_data *clk_data);
|
int num, struct clk_onecell_data *clk_data);
|
||||||
|
|
||||||
struct mtk_composite {
|
struct mtk_composite {
|
||||||
|
@ -159,10 +176,13 @@ struct mtk_pll_data {
|
||||||
const struct mtk_pll_div_table *div_table;
|
const struct mtk_pll_div_table *div_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
void __init mtk_clk_register_plls(struct device_node *node,
|
void mtk_clk_register_plls(struct device_node *node,
|
||||||
const struct mtk_pll_data *plls, int num_plls,
|
const struct mtk_pll_data *plls, int num_plls,
|
||||||
struct clk_onecell_data *clk_data);
|
struct clk_onecell_data *clk_data);
|
||||||
|
|
||||||
|
struct clk *mtk_clk_register_ref2usb_tx(const char *name,
|
||||||
|
const char *parent_name, void __iomem *reg);
|
||||||
|
|
||||||
#ifdef CONFIG_RESET_CONTROLLER
|
#ifdef CONFIG_RESET_CONTROLLER
|
||||||
void mtk_register_reset_controller(struct device_node *np,
|
void mtk_register_reset_controller(struct device_node *np,
|
||||||
unsigned int num_regs, int regofs);
|
unsigned int num_regs, int regofs);
|
||||||
|
|
|
@ -317,7 +317,7 @@ void __init mtk_clk_register_plls(struct device_node *node,
|
||||||
const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
|
const struct mtk_pll_data *plls, int num_plls, struct clk_onecell_data *clk_data)
|
||||||
{
|
{
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
int r, i;
|
int i;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
|
|
||||||
base = of_iomap(node, 0);
|
base = of_iomap(node, 0);
|
||||||
|
@ -339,9 +339,4 @@ void __init mtk_clk_register_plls(struct device_node *node,
|
||||||
|
|
||||||
clk_data->clks[pll->id] = clk;
|
clk_data->clks[pll->id] = clk;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
|
|
||||||
if (r)
|
|
||||||
pr_err("%s(): could not register clock provider: %d\n",
|
|
||||||
__func__, r);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -197,7 +197,6 @@ static void __init of_cpu_clk_setup(struct device_node *node)
|
||||||
for_each_node_by_type(dn, "cpu") {
|
for_each_node_by_type(dn, "cpu") {
|
||||||
struct clk_init_data init;
|
struct clk_init_data init;
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk *parent_clk;
|
|
||||||
char *clk_name = kzalloc(5, GFP_KERNEL);
|
char *clk_name = kzalloc(5, GFP_KERNEL);
|
||||||
int cpu, err;
|
int cpu, err;
|
||||||
|
|
||||||
|
@ -209,9 +208,8 @@ static void __init of_cpu_clk_setup(struct device_node *node)
|
||||||
goto bail_out;
|
goto bail_out;
|
||||||
|
|
||||||
sprintf(clk_name, "cpu%d", cpu);
|
sprintf(clk_name, "cpu%d", cpu);
|
||||||
parent_clk = of_clk_get(node, 0);
|
|
||||||
|
|
||||||
cpuclk[cpu].parent_name = __clk_get_name(parent_clk);
|
cpuclk[cpu].parent_name = of_clk_get_parent_name(node, 0);
|
||||||
cpuclk[cpu].clk_name = clk_name;
|
cpuclk[cpu].clk_name = clk_name;
|
||||||
cpuclk[cpu].cpu = cpu;
|
cpuclk[cpu].cpu = cpu;
|
||||||
cpuclk[cpu].reg_base = clock_complex_base;
|
cpuclk[cpu].reg_base = clock_complex_base;
|
||||||
|
|
|
@ -165,7 +165,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
|
||||||
clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
|
clk_data.clks[2+n] = clk_register_fixed_factor(NULL, rclk_name,
|
||||||
cpuclk_name, 0, mult, div);
|
cpuclk_name, 0, mult, div);
|
||||||
WARN_ON(IS_ERR(clk_data.clks[2+n]));
|
WARN_ON(IS_ERR(clk_data.clks[2+n]));
|
||||||
};
|
}
|
||||||
|
|
||||||
/* Register optional refclk */
|
/* Register optional refclk */
|
||||||
if (desc->get_refclk_freq) {
|
if (desc->get_refclk_freq) {
|
||||||
|
|
|
@ -41,11 +41,13 @@ static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
|
||||||
{
|
{
|
||||||
struct clk_frac *frac = to_clk_frac(hw);
|
struct clk_frac *frac = to_clk_frac(hw);
|
||||||
u32 div;
|
u32 div;
|
||||||
|
u64 tmp_rate;
|
||||||
|
|
||||||
div = readl_relaxed(frac->reg) >> frac->shift;
|
div = readl_relaxed(frac->reg) >> frac->shift;
|
||||||
div &= (1 << frac->width) - 1;
|
div &= (1 << frac->width) - 1;
|
||||||
|
|
||||||
return (parent_rate >> frac->width) * div;
|
tmp_rate = (u64)parent_rate * div;
|
||||||
|
return tmp_rate >> frac->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
|
static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
@ -54,7 +56,7 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
struct clk_frac *frac = to_clk_frac(hw);
|
struct clk_frac *frac = to_clk_frac(hw);
|
||||||
unsigned long parent_rate = *prate;
|
unsigned long parent_rate = *prate;
|
||||||
u32 div;
|
u32 div;
|
||||||
u64 tmp;
|
u64 tmp, tmp_rate, result;
|
||||||
|
|
||||||
if (rate > parent_rate)
|
if (rate > parent_rate)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -67,7 +69,11 @@ static long clk_frac_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
if (!div)
|
if (!div)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
return (parent_rate >> frac->width) * div;
|
tmp_rate = (u64)parent_rate * div;
|
||||||
|
result = tmp_rate >> frac->width;
|
||||||
|
if ((result << frac->width) < tmp_rate)
|
||||||
|
result += 1;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
static int clk_frac_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
|
|
@ -179,9 +179,22 @@ static void lpc18xx_ccu_gate_disable(struct clk_hw *hw)
|
||||||
|
|
||||||
static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
|
static int lpc18xx_ccu_gate_is_enabled(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct clk_gate *gate = to_clk_gate(hw);
|
const struct clk_hw *parent;
|
||||||
|
|
||||||
return clk_readl(gate->reg) & LPC18XX_CCU_RUN;
|
/*
|
||||||
|
* The branch clock registers are only accessible
|
||||||
|
* if the base (parent) clock is enabled. Register
|
||||||
|
* access with a disabled base clock will hang the
|
||||||
|
* system.
|
||||||
|
*/
|
||||||
|
parent = clk_hw_get_parent(hw);
|
||||||
|
if (!parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!clk_hw_is_enabled(parent))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return clk_gate_ops.is_enabled(hw);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct clk_ops lpc18xx_ccu_gate_ops = {
|
static const struct clk_ops lpc18xx_ccu_gate_ops = {
|
||||||
|
|
|
@ -480,6 +480,42 @@ static const struct clk_ops lpc18xx_pll1_ops = {
|
||||||
.recalc_rate = lpc18xx_pll1_recalc_rate,
|
.recalc_rate = lpc18xx_pll1_recalc_rate,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int lpc18xx_cgu_gate_enable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
return clk_gate_ops.enable(hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void lpc18xx_cgu_gate_disable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
clk_gate_ops.disable(hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lpc18xx_cgu_gate_is_enabled(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
const struct clk_hw *parent;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The consumer of base clocks needs know if the
|
||||||
|
* base clock is really enabled before it can be
|
||||||
|
* accessed. It is therefore necessary to verify
|
||||||
|
* this all the way up.
|
||||||
|
*/
|
||||||
|
parent = clk_hw_get_parent(hw);
|
||||||
|
if (!parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!clk_hw_is_enabled(parent))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return clk_gate_ops.is_enabled(hw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct clk_ops lpc18xx_gate_ops = {
|
||||||
|
.enable = lpc18xx_cgu_gate_enable,
|
||||||
|
.disable = lpc18xx_cgu_gate_disable,
|
||||||
|
.is_enabled = lpc18xx_cgu_gate_is_enabled,
|
||||||
|
};
|
||||||
|
|
||||||
static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
|
static struct lpc18xx_cgu_pll_clk lpc18xx_cgu_src_clk_plls[] = {
|
||||||
LPC1XX_CGU_CLK_PLL(PLL0USB, pll0_src_ids, pll0_ops),
|
LPC1XX_CGU_CLK_PLL(PLL0USB, pll0_src_ids, pll0_ops),
|
||||||
LPC1XX_CGU_CLK_PLL(PLL0AUDIO, pll0_src_ids, pll0_ops),
|
LPC1XX_CGU_CLK_PLL(PLL0AUDIO, pll0_src_ids, pll0_ops),
|
||||||
|
@ -510,7 +546,7 @@ static struct clk *lpc18xx_cgu_register_div(struct lpc18xx_cgu_src_clk_div *clk,
|
||||||
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
||||||
&clk->mux.hw, &clk_mux_ops,
|
&clk->mux.hw, &clk_mux_ops,
|
||||||
&clk->div.hw, &clk_divider_ops,
|
&clk->div.hw, &clk_divider_ops,
|
||||||
&clk->gate.hw, &clk_gate_ops, 0);
|
&clk->gate.hw, &lpc18xx_gate_ops, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -538,7 +574,7 @@ static struct clk *lpc18xx_register_base_clk(struct lpc18xx_cgu_base_clk *clk,
|
||||||
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
||||||
&clk->mux.hw, &clk_mux_ops,
|
&clk->mux.hw, &clk_mux_ops,
|
||||||
NULL, NULL,
|
NULL, NULL,
|
||||||
&clk->gate.hw, &clk_gate_ops, 0);
|
&clk->gate.hw, &lpc18xx_gate_ops, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -557,7 +593,7 @@ static struct clk *lpc18xx_cgu_register_pll(struct lpc18xx_cgu_pll_clk *clk,
|
||||||
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
return clk_register_composite(NULL, name, parents, clk->n_parents,
|
||||||
&clk->mux.hw, &clk_mux_ops,
|
&clk->mux.hw, &clk_mux_ops,
|
||||||
&clk->pll.hw, clk->pll_ops,
|
&clk->pll.hw, clk->pll_ops,
|
||||||
&clk->gate.hw, &clk_gate_ops, 0);
|
&clk->gate.hw, &lpc18xx_gate_ops, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __init lpc18xx_cgu_register_source_clks(struct device_node *np,
|
static void __init lpc18xx_cgu_register_source_clks(struct device_node *np,
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
config QCOM_GDSC
|
||||||
|
bool
|
||||||
|
select PM_GENERIC_DOMAINS if PM
|
||||||
|
|
||||||
config COMMON_CLK_QCOM
|
config COMMON_CLK_QCOM
|
||||||
tristate "Support for Qualcomm's clock controllers"
|
tristate "Support for Qualcomm's clock controllers"
|
||||||
depends on OF
|
depends on OF
|
||||||
|
@ -7,6 +11,7 @@ config COMMON_CLK_QCOM
|
||||||
|
|
||||||
config APQ_GCC_8084
|
config APQ_GCC_8084
|
||||||
tristate "APQ8084 Global Clock Controller"
|
tristate "APQ8084 Global Clock Controller"
|
||||||
|
select QCOM_GDSC
|
||||||
depends on COMMON_CLK_QCOM
|
depends on COMMON_CLK_QCOM
|
||||||
help
|
help
|
||||||
Support for the global clock controller on apq8084 devices.
|
Support for the global clock controller on apq8084 devices.
|
||||||
|
@ -16,6 +21,7 @@ config APQ_GCC_8084
|
||||||
config APQ_MMCC_8084
|
config APQ_MMCC_8084
|
||||||
tristate "APQ8084 Multimedia Clock Controller"
|
tristate "APQ8084 Multimedia Clock Controller"
|
||||||
select APQ_GCC_8084
|
select APQ_GCC_8084
|
||||||
|
select QCOM_GDSC
|
||||||
depends on COMMON_CLK_QCOM
|
depends on COMMON_CLK_QCOM
|
||||||
help
|
help
|
||||||
Support for the multimedia clock controller on apq8084 devices.
|
Support for the multimedia clock controller on apq8084 devices.
|
||||||
|
@ -49,6 +55,7 @@ config MSM_GCC_8660
|
||||||
|
|
||||||
config MSM_GCC_8916
|
config MSM_GCC_8916
|
||||||
tristate "MSM8916 Global Clock Controller"
|
tristate "MSM8916 Global Clock Controller"
|
||||||
|
select QCOM_GDSC
|
||||||
depends on COMMON_CLK_QCOM
|
depends on COMMON_CLK_QCOM
|
||||||
help
|
help
|
||||||
Support for the global clock controller on msm8916 devices.
|
Support for the global clock controller on msm8916 devices.
|
||||||
|
@ -83,6 +90,7 @@ config MSM_MMCC_8960
|
||||||
|
|
||||||
config MSM_GCC_8974
|
config MSM_GCC_8974
|
||||||
tristate "MSM8974 Global Clock Controller"
|
tristate "MSM8974 Global Clock Controller"
|
||||||
|
select QCOM_GDSC
|
||||||
depends on COMMON_CLK_QCOM
|
depends on COMMON_CLK_QCOM
|
||||||
help
|
help
|
||||||
Support for the global clock controller on msm8974 devices.
|
Support for the global clock controller on msm8974 devices.
|
||||||
|
@ -92,6 +100,7 @@ config MSM_GCC_8974
|
||||||
config MSM_MMCC_8974
|
config MSM_MMCC_8974
|
||||||
tristate "MSM8974 Multimedia Clock Controller"
|
tristate "MSM8974 Multimedia Clock Controller"
|
||||||
select MSM_GCC_8974
|
select MSM_GCC_8974
|
||||||
|
select QCOM_GDSC
|
||||||
depends on COMMON_CLK_QCOM
|
depends on COMMON_CLK_QCOM
|
||||||
help
|
help
|
||||||
Support for the multimedia clock controller on msm8974 devices.
|
Support for the multimedia clock controller on msm8974 devices.
|
||||||
|
|
|
@ -9,6 +9,7 @@ clk-qcom-y += clk-branch.o
|
||||||
clk-qcom-y += clk-regmap-divider.o
|
clk-qcom-y += clk-regmap-divider.o
|
||||||
clk-qcom-y += clk-regmap-mux.o
|
clk-qcom-y += clk-regmap-mux.o
|
||||||
clk-qcom-y += reset.o
|
clk-qcom-y += reset.o
|
||||||
|
clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
|
||||||
|
|
||||||
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
|
obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
|
||||||
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
|
obj-$(CONFIG_APQ_MMCC_8084) += mmcc-apq8084.o
|
||||||
|
|
|
@ -542,6 +542,200 @@ static int clk_rcg_bypass_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
|
return __clk_rcg_set_rate(rcg, rcg->freq_tbl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_bypass2_determine_rate(struct clk_hw *hw,
|
||||||
|
struct clk_rate_request *req)
|
||||||
|
{
|
||||||
|
struct clk_hw *p;
|
||||||
|
|
||||||
|
p = req->best_parent_hw;
|
||||||
|
req->best_parent_rate = clk_hw_round_rate(p, req->rate);
|
||||||
|
req->rate = req->best_parent_rate;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_bypass2_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
|
struct freq_tbl f = { 0 };
|
||||||
|
u32 ns, src;
|
||||||
|
int i, ret, num_parents = clk_hw_get_num_parents(hw);
|
||||||
|
|
||||||
|
ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
src = ns_to_src(&rcg->s, ns);
|
||||||
|
f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < num_parents; i++) {
|
||||||
|
if (src == rcg->s.parent_map[i].cfg) {
|
||||||
|
f.src = rcg->s.parent_map[i].src;
|
||||||
|
return __clk_rcg_set_rate(rcg, &f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_bypass2_set_rate_and_parent(struct clk_hw *hw,
|
||||||
|
unsigned long rate, unsigned long parent_rate, u8 index)
|
||||||
|
{
|
||||||
|
/* Read the hardware to determine parent during set_rate */
|
||||||
|
return clk_rcg_bypass2_set_rate(hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct frac_entry {
|
||||||
|
int num;
|
||||||
|
int den;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct frac_entry pixel_table[] = {
|
||||||
|
{ 1, 2 },
|
||||||
|
{ 1, 3 },
|
||||||
|
{ 3, 16 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int clk_rcg_pixel_determine_rate(struct clk_hw *hw,
|
||||||
|
struct clk_rate_request *req)
|
||||||
|
{
|
||||||
|
int delta = 100000;
|
||||||
|
const struct frac_entry *frac = pixel_table;
|
||||||
|
unsigned long request, src_rate;
|
||||||
|
|
||||||
|
for (; frac->num; frac++) {
|
||||||
|
request = (req->rate * frac->den) / frac->num;
|
||||||
|
|
||||||
|
src_rate = clk_hw_round_rate(req->best_parent_hw, request);
|
||||||
|
|
||||||
|
if ((src_rate < (request - delta)) ||
|
||||||
|
(src_rate > (request + delta)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
req->best_parent_rate = src_rate;
|
||||||
|
req->rate = (src_rate * frac->num) / frac->den;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
|
int delta = 100000;
|
||||||
|
const struct frac_entry *frac = pixel_table;
|
||||||
|
unsigned long request;
|
||||||
|
struct freq_tbl f = { 0 };
|
||||||
|
u32 ns, src;
|
||||||
|
int i, ret, num_parents = clk_hw_get_num_parents(hw);
|
||||||
|
|
||||||
|
ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
src = ns_to_src(&rcg->s, ns);
|
||||||
|
f.pre_div = ns_to_pre_div(&rcg->p, ns) + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < num_parents; i++) {
|
||||||
|
if (src == rcg->s.parent_map[i].cfg) {
|
||||||
|
f.src = rcg->s.parent_map[i].src;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* let us find appropriate m/n values for this */
|
||||||
|
for (; frac->num; frac++) {
|
||||||
|
request = (rate * frac->den) / frac->num;
|
||||||
|
|
||||||
|
if ((parent_rate < (request - delta)) ||
|
||||||
|
(parent_rate > (request + delta)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
f.m = frac->num;
|
||||||
|
f.n = frac->den;
|
||||||
|
|
||||||
|
return __clk_rcg_set_rate(rcg, &f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_pixel_set_rate_and_parent(struct clk_hw *hw,
|
||||||
|
unsigned long rate, unsigned long parent_rate, u8 index)
|
||||||
|
{
|
||||||
|
return clk_rcg_pixel_set_rate(hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_esc_determine_rate(struct clk_hw *hw,
|
||||||
|
struct clk_rate_request *req)
|
||||||
|
{
|
||||||
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
|
int pre_div_max = BIT(rcg->p.pre_div_width);
|
||||||
|
int div;
|
||||||
|
unsigned long src_rate;
|
||||||
|
|
||||||
|
if (req->rate == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
src_rate = clk_hw_get_rate(req->best_parent_hw);
|
||||||
|
|
||||||
|
div = src_rate / req->rate;
|
||||||
|
|
||||||
|
if (div >= 1 && div <= pre_div_max) {
|
||||||
|
req->best_parent_rate = src_rate;
|
||||||
|
req->rate = src_rate / div;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_esc_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg *rcg = to_clk_rcg(hw);
|
||||||
|
struct freq_tbl f = { 0 };
|
||||||
|
int pre_div_max = BIT(rcg->p.pre_div_width);
|
||||||
|
int div;
|
||||||
|
u32 ns;
|
||||||
|
int i, ret, num_parents = clk_hw_get_num_parents(hw);
|
||||||
|
|
||||||
|
if (rate == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
ret = regmap_read(rcg->clkr.regmap, rcg->ns_reg, &ns);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ns = ns_to_src(&rcg->s, ns);
|
||||||
|
|
||||||
|
for (i = 0; i < num_parents; i++) {
|
||||||
|
if (ns == rcg->s.parent_map[i].cfg) {
|
||||||
|
f.src = rcg->s.parent_map[i].src;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
div = parent_rate / rate;
|
||||||
|
|
||||||
|
if (div >= 1 && div <= pre_div_max) {
|
||||||
|
f.pre_div = div;
|
||||||
|
return __clk_rcg_set_rate(rcg, &f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg_esc_set_rate_and_parent(struct clk_hw *hw,
|
||||||
|
unsigned long rate, unsigned long parent_rate, u8 index)
|
||||||
|
{
|
||||||
|
return clk_rcg_esc_set_rate(hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This type of clock has a glitch-free mux that switches between the output of
|
* This type of clock has a glitch-free mux that switches between the output of
|
||||||
* the M/N counter and an always on clock source (XO). When clk_set_rate() is
|
* the M/N counter and an always on clock source (XO). When clk_set_rate() is
|
||||||
|
@ -639,6 +833,42 @@ const struct clk_ops clk_rcg_bypass_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
|
EXPORT_SYMBOL_GPL(clk_rcg_bypass_ops);
|
||||||
|
|
||||||
|
const struct clk_ops clk_rcg_bypass2_ops = {
|
||||||
|
.enable = clk_enable_regmap,
|
||||||
|
.disable = clk_disable_regmap,
|
||||||
|
.get_parent = clk_rcg_get_parent,
|
||||||
|
.set_parent = clk_rcg_set_parent,
|
||||||
|
.recalc_rate = clk_rcg_recalc_rate,
|
||||||
|
.determine_rate = clk_rcg_bypass2_determine_rate,
|
||||||
|
.set_rate = clk_rcg_bypass2_set_rate,
|
||||||
|
.set_rate_and_parent = clk_rcg_bypass2_set_rate_and_parent,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_rcg_bypass2_ops);
|
||||||
|
|
||||||
|
const struct clk_ops clk_rcg_pixel_ops = {
|
||||||
|
.enable = clk_enable_regmap,
|
||||||
|
.disable = clk_disable_regmap,
|
||||||
|
.get_parent = clk_rcg_get_parent,
|
||||||
|
.set_parent = clk_rcg_set_parent,
|
||||||
|
.recalc_rate = clk_rcg_recalc_rate,
|
||||||
|
.determine_rate = clk_rcg_pixel_determine_rate,
|
||||||
|
.set_rate = clk_rcg_pixel_set_rate,
|
||||||
|
.set_rate_and_parent = clk_rcg_pixel_set_rate_and_parent,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_rcg_pixel_ops);
|
||||||
|
|
||||||
|
const struct clk_ops clk_rcg_esc_ops = {
|
||||||
|
.enable = clk_enable_regmap,
|
||||||
|
.disable = clk_disable_regmap,
|
||||||
|
.get_parent = clk_rcg_get_parent,
|
||||||
|
.set_parent = clk_rcg_set_parent,
|
||||||
|
.recalc_rate = clk_rcg_recalc_rate,
|
||||||
|
.determine_rate = clk_rcg_esc_determine_rate,
|
||||||
|
.set_rate = clk_rcg_esc_set_rate,
|
||||||
|
.set_rate_and_parent = clk_rcg_esc_set_rate_and_parent,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_rcg_esc_ops);
|
||||||
|
|
||||||
const struct clk_ops clk_rcg_lcc_ops = {
|
const struct clk_ops clk_rcg_lcc_ops = {
|
||||||
.enable = clk_rcg_lcc_enable,
|
.enable = clk_rcg_lcc_enable,
|
||||||
.disable = clk_rcg_lcc_disable,
|
.disable = clk_rcg_lcc_disable,
|
||||||
|
|
|
@ -106,6 +106,9 @@ struct clk_rcg {
|
||||||
|
|
||||||
extern const struct clk_ops clk_rcg_ops;
|
extern const struct clk_ops clk_rcg_ops;
|
||||||
extern const struct clk_ops clk_rcg_bypass_ops;
|
extern const struct clk_ops clk_rcg_bypass_ops;
|
||||||
|
extern const struct clk_ops clk_rcg_bypass2_ops;
|
||||||
|
extern const struct clk_ops clk_rcg_pixel_ops;
|
||||||
|
extern const struct clk_ops clk_rcg_esc_ops;
|
||||||
extern const struct clk_ops clk_rcg_lcc_ops;
|
extern const struct clk_ops clk_rcg_lcc_ops;
|
||||||
|
|
||||||
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
|
#define to_clk_rcg(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg, clkr)
|
||||||
|
@ -153,8 +156,8 @@ extern const struct clk_ops clk_dyn_rcg_ops;
|
||||||
* @hid_width: number of bits in half integer divider
|
* @hid_width: number of bits in half integer divider
|
||||||
* @parent_map: map from software's parent index to hardware's src_sel field
|
* @parent_map: map from software's parent index to hardware's src_sel field
|
||||||
* @freq_tbl: frequency table
|
* @freq_tbl: frequency table
|
||||||
|
* @current_freq: last cached frequency when using branches with shared RCGs
|
||||||
* @clkr: regmap clock handle
|
* @clkr: regmap clock handle
|
||||||
* @lock: register lock
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct clk_rcg2 {
|
struct clk_rcg2 {
|
||||||
|
@ -163,14 +166,17 @@ struct clk_rcg2 {
|
||||||
u8 hid_width;
|
u8 hid_width;
|
||||||
const struct parent_map *parent_map;
|
const struct parent_map *parent_map;
|
||||||
const struct freq_tbl *freq_tbl;
|
const struct freq_tbl *freq_tbl;
|
||||||
|
unsigned long current_freq;
|
||||||
struct clk_regmap clkr;
|
struct clk_regmap clkr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
|
#define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
|
||||||
|
|
||||||
extern const struct clk_ops clk_rcg2_ops;
|
extern const struct clk_ops clk_rcg2_ops;
|
||||||
|
extern const struct clk_ops clk_rcg2_shared_ops;
|
||||||
extern const struct clk_ops clk_edp_pixel_ops;
|
extern const struct clk_ops clk_edp_pixel_ops;
|
||||||
extern const struct clk_ops clk_byte_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_pixel_ops;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -300,6 +300,85 @@ const struct clk_ops clk_rcg2_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
|
EXPORT_SYMBOL_GPL(clk_rcg2_ops);
|
||||||
|
|
||||||
|
static int clk_rcg2_shared_force_enable(struct clk_hw *hw, unsigned long rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
const char *name = clk_hw_get_name(hw);
|
||||||
|
int ret, count;
|
||||||
|
|
||||||
|
/* force enable RCG */
|
||||||
|
ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
|
||||||
|
CMD_ROOT_EN, CMD_ROOT_EN);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* wait for RCG to turn ON */
|
||||||
|
for (count = 500; count > 0; count--) {
|
||||||
|
ret = clk_rcg2_is_enabled(hw);
|
||||||
|
if (ret)
|
||||||
|
break;
|
||||||
|
udelay(1);
|
||||||
|
}
|
||||||
|
if (!count)
|
||||||
|
pr_err("%s: RCG did not turn on\n", name);
|
||||||
|
|
||||||
|
/* set clock rate */
|
||||||
|
ret = __clk_rcg2_set_rate(hw, rate);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* clear force enable RCG */
|
||||||
|
return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
|
||||||
|
CMD_ROOT_EN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
|
||||||
|
/* cache the rate */
|
||||||
|
rcg->current_freq = rate;
|
||||||
|
|
||||||
|
if (!__clk_is_enabled(hw->clk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned long
|
||||||
|
clk_rcg2_shared_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
|
||||||
|
return rcg->current_freq = clk_rcg2_recalc_rate(hw, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_rcg2_shared_enable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
|
||||||
|
return clk_rcg2_shared_force_enable(hw, rcg->current_freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clk_rcg2_shared_disable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
|
||||||
|
/* switch to XO, which is the lowest entry in the freq table */
|
||||||
|
clk_rcg2_shared_set_rate(hw, rcg->freq_tbl[0].freq, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct clk_ops clk_rcg2_shared_ops = {
|
||||||
|
.enable = clk_rcg2_shared_enable,
|
||||||
|
.disable = clk_rcg2_shared_disable,
|
||||||
|
.get_parent = clk_rcg2_get_parent,
|
||||||
|
.recalc_rate = clk_rcg2_shared_recalc_rate,
|
||||||
|
.determine_rate = clk_rcg2_determine_rate,
|
||||||
|
.set_rate = clk_rcg2_shared_set_rate,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_rcg2_shared_ops);
|
||||||
|
|
||||||
struct frac_entry {
|
struct frac_entry {
|
||||||
int num;
|
int num;
|
||||||
int den;
|
int den;
|
||||||
|
@ -485,6 +564,76 @@ const struct clk_ops clk_byte_ops = {
|
||||||
};
|
};
|
||||||
EXPORT_SYMBOL_GPL(clk_byte_ops);
|
EXPORT_SYMBOL_GPL(clk_byte_ops);
|
||||||
|
|
||||||
|
static int clk_byte2_determine_rate(struct clk_hw *hw,
|
||||||
|
struct clk_rate_request *req)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
unsigned long parent_rate, div;
|
||||||
|
u32 mask = BIT(rcg->hid_width) - 1;
|
||||||
|
struct clk_hw *p;
|
||||||
|
unsigned long rate = req->rate;
|
||||||
|
|
||||||
|
if (rate == 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
p = req->best_parent_hw;
|
||||||
|
req->best_parent_rate = parent_rate = clk_hw_round_rate(p, rate);
|
||||||
|
|
||||||
|
div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
|
||||||
|
div = min_t(u32, div, mask);
|
||||||
|
|
||||||
|
req->rate = calc_rate(parent_rate, 0, 0, 0, div);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_byte2_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
|
struct freq_tbl f = { 0 };
|
||||||
|
unsigned long div;
|
||||||
|
int i, num_parents = clk_hw_get_num_parents(hw);
|
||||||
|
u32 mask = BIT(rcg->hid_width) - 1;
|
||||||
|
u32 cfg;
|
||||||
|
|
||||||
|
div = DIV_ROUND_UP((2 * parent_rate), rate) - 1;
|
||||||
|
div = min_t(u32, div, mask);
|
||||||
|
|
||||||
|
f.pre_div = div;
|
||||||
|
|
||||||
|
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
|
||||||
|
cfg &= CFG_SRC_SEL_MASK;
|
||||||
|
cfg >>= CFG_SRC_SEL_SHIFT;
|
||||||
|
|
||||||
|
for (i = 0; i < num_parents; i++) {
|
||||||
|
if (cfg == rcg->parent_map[i].cfg) {
|
||||||
|
f.src = rcg->parent_map[i].src;
|
||||||
|
return clk_rcg2_configure(rcg, &f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int clk_byte2_set_rate_and_parent(struct clk_hw *hw,
|
||||||
|
unsigned long rate, unsigned long parent_rate, u8 index)
|
||||||
|
{
|
||||||
|
/* Read the hardware to determine parent during set_rate */
|
||||||
|
return clk_byte2_set_rate(hw, rate, parent_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct clk_ops clk_byte2_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_byte2_set_rate,
|
||||||
|
.set_rate_and_parent = clk_byte2_set_rate_and_parent,
|
||||||
|
.determine_rate = clk_byte2_determine_rate,
|
||||||
|
};
|
||||||
|
EXPORT_SYMBOL_GPL(clk_byte2_ops);
|
||||||
|
|
||||||
static const struct frac_entry frac_table_pixel[] = {
|
static const struct frac_entry frac_table_pixel[] = {
|
||||||
{ 3, 8 },
|
{ 3, 8 },
|
||||||
{ 2, 9 },
|
{ 2, 9 },
|
||||||
|
@ -496,14 +645,9 @@ static const struct frac_entry frac_table_pixel[] = {
|
||||||
static int clk_pixel_determine_rate(struct clk_hw *hw,
|
static int clk_pixel_determine_rate(struct clk_hw *hw,
|
||||||
struct clk_rate_request *req)
|
struct clk_rate_request *req)
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
|
||||||
unsigned long request, src_rate;
|
unsigned long request, src_rate;
|
||||||
int delta = 100000;
|
int delta = 100000;
|
||||||
const struct freq_tbl *f = rcg->freq_tbl;
|
|
||||||
const struct frac_entry *frac = frac_table_pixel;
|
const struct frac_entry *frac = frac_table_pixel;
|
||||||
int index = qcom_find_src_index(hw, rcg->parent_map, f->src);
|
|
||||||
|
|
||||||
req->best_parent_hw = clk_hw_get_parent_by_index(hw, index);
|
|
||||||
|
|
||||||
for (; frac->num; frac++) {
|
for (; frac->num; frac++) {
|
||||||
request = (req->rate * frac->den) / frac->num;
|
request = (req->rate * frac->den) / frac->num;
|
||||||
|
@ -525,12 +669,23 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long parent_rate)
|
unsigned long parent_rate)
|
||||||
{
|
{
|
||||||
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
|
||||||
struct freq_tbl f = *rcg->freq_tbl;
|
struct freq_tbl f = { 0 };
|
||||||
const struct frac_entry *frac = frac_table_pixel;
|
const struct frac_entry *frac = frac_table_pixel;
|
||||||
unsigned long request;
|
unsigned long request;
|
||||||
int delta = 100000;
|
int delta = 100000;
|
||||||
u32 mask = BIT(rcg->hid_width) - 1;
|
u32 mask = BIT(rcg->hid_width) - 1;
|
||||||
u32 hid_div;
|
u32 hid_div, cfg;
|
||||||
|
int i, num_parents = clk_hw_get_num_parents(hw);
|
||||||
|
|
||||||
|
regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
|
||||||
|
cfg &= CFG_SRC_SEL_MASK;
|
||||||
|
cfg >>= CFG_SRC_SEL_SHIFT;
|
||||||
|
|
||||||
|
for (i = 0; i < num_parents; i++)
|
||||||
|
if (cfg == rcg->parent_map[i].cfg) {
|
||||||
|
f.src = rcg->parent_map[i].src;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
for (; frac->num; frac++) {
|
for (; frac->num; frac++) {
|
||||||
request = (rate * frac->den) / frac->num;
|
request = (rate * frac->den) / frac->num;
|
||||||
|
@ -555,7 +710,6 @@ static int clk_pixel_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
|
static int clk_pixel_set_rate_and_parent(struct clk_hw *hw, unsigned long rate,
|
||||||
unsigned long parent_rate, u8 index)
|
unsigned long parent_rate, u8 index)
|
||||||
{
|
{
|
||||||
/* Parent index is set statically in frequency table */
|
|
||||||
return clk_pixel_set_rate(hw, rate, parent_rate);
|
return clk_pixel_set_rate(hw, rate, parent_rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-regmap.h"
|
#include "clk-regmap.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
struct qcom_cc {
|
struct qcom_cc {
|
||||||
struct qcom_reset_controller reset;
|
struct qcom_reset_controller reset;
|
||||||
|
@ -72,6 +73,21 @@ qcom_cc_map(struct platform_device *pdev, const struct qcom_cc_desc *desc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(qcom_cc_map);
|
EXPORT_SYMBOL_GPL(qcom_cc_map);
|
||||||
|
|
||||||
|
static void qcom_cc_del_clk_provider(void *data)
|
||||||
|
{
|
||||||
|
of_clk_del_provider(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qcom_cc_reset_unregister(void *data)
|
||||||
|
{
|
||||||
|
reset_controller_unregister(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qcom_cc_gdsc_unregister(void *data)
|
||||||
|
{
|
||||||
|
gdsc_unregister(data);
|
||||||
|
}
|
||||||
|
|
||||||
int qcom_cc_really_probe(struct platform_device *pdev,
|
int qcom_cc_really_probe(struct platform_device *pdev,
|
||||||
const struct qcom_cc_desc *desc, struct regmap *regmap)
|
const struct qcom_cc_desc *desc, struct regmap *regmap)
|
||||||
{
|
{
|
||||||
|
@ -110,6 +126,8 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
devm_add_action(dev, qcom_cc_del_clk_provider, pdev->dev.of_node);
|
||||||
|
|
||||||
reset = &cc->reset;
|
reset = &cc->reset;
|
||||||
reset->rcdev.of_node = dev->of_node;
|
reset->rcdev.of_node = dev->of_node;
|
||||||
reset->rcdev.ops = &qcom_reset_ops;
|
reset->rcdev.ops = &qcom_reset_ops;
|
||||||
|
@ -117,13 +135,24 @@ int qcom_cc_really_probe(struct platform_device *pdev,
|
||||||
reset->rcdev.nr_resets = desc->num_resets;
|
reset->rcdev.nr_resets = desc->num_resets;
|
||||||
reset->regmap = regmap;
|
reset->regmap = regmap;
|
||||||
reset->reset_map = desc->resets;
|
reset->reset_map = desc->resets;
|
||||||
platform_set_drvdata(pdev, &reset->rcdev);
|
|
||||||
|
|
||||||
ret = reset_controller_register(&reset->rcdev);
|
ret = reset_controller_register(&reset->rcdev);
|
||||||
if (ret)
|
if (ret)
|
||||||
of_clk_del_provider(dev->of_node);
|
return ret;
|
||||||
|
|
||||||
return ret;
|
devm_add_action(dev, qcom_cc_reset_unregister, &reset->rcdev);
|
||||||
|
|
||||||
|
if (desc->gdscs && desc->num_gdscs) {
|
||||||
|
ret = gdsc_register(dev, desc->gdscs, desc->num_gdscs,
|
||||||
|
&reset->rcdev, regmap);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
devm_add_action(dev, qcom_cc_gdsc_unregister, dev);
|
||||||
|
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
|
EXPORT_SYMBOL_GPL(qcom_cc_really_probe);
|
||||||
|
|
||||||
|
@ -139,11 +168,4 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(qcom_cc_probe);
|
EXPORT_SYMBOL_GPL(qcom_cc_probe);
|
||||||
|
|
||||||
void qcom_cc_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
of_clk_del_provider(pdev->dev.of_node);
|
|
||||||
reset_controller_unregister(platform_get_drvdata(pdev));
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(qcom_cc_remove);
|
|
||||||
|
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
|
|
@ -28,6 +28,8 @@ struct qcom_cc_desc {
|
||||||
size_t num_clks;
|
size_t num_clks;
|
||||||
const struct qcom_reset_map *resets;
|
const struct qcom_reset_map *resets;
|
||||||
size_t num_resets;
|
size_t num_resets;
|
||||||
|
struct gdsc **gdscs;
|
||||||
|
size_t num_gdscs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
|
extern const struct freq_tbl *qcom_find_freq(const struct freq_tbl *f,
|
||||||
|
@ -43,6 +45,4 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
|
||||||
extern int qcom_cc_probe(struct platform_device *pdev,
|
extern int qcom_cc_probe(struct platform_device *pdev,
|
||||||
const struct qcom_cc_desc *desc);
|
const struct qcom_cc_desc *desc);
|
||||||
|
|
||||||
extern void qcom_cc_remove(struct platform_device *pdev);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-branch.h"
|
#include "clk-branch.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
P_XO,
|
P_XO,
|
||||||
|
@ -3254,6 +3255,38 @@ static struct clk_branch gcc_usb_hsic_system_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc usb_hs_hsic_gdsc = {
|
||||||
|
.gdscr = 0x404,
|
||||||
|
.pd = {
|
||||||
|
.name = "usb_hs_hsic",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc pcie0_gdsc = {
|
||||||
|
.gdscr = 0x1ac4,
|
||||||
|
.pd = {
|
||||||
|
.name = "pcie0",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc pcie1_gdsc = {
|
||||||
|
.gdscr = 0x1b44,
|
||||||
|
.pd = {
|
||||||
|
.name = "pcie1",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc usb30_gdsc = {
|
||||||
|
.gdscr = 0x1e84,
|
||||||
|
.pd = {
|
||||||
|
.name = "usb30",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_regmap *gcc_apq8084_clocks[] = {
|
static struct clk_regmap *gcc_apq8084_clocks[] = {
|
||||||
[GPLL0] = &gpll0.clkr,
|
[GPLL0] = &gpll0.clkr,
|
||||||
[GPLL0_VOTE] = &gpll0_vote,
|
[GPLL0_VOTE] = &gpll0_vote,
|
||||||
|
@ -3447,6 +3480,13 @@ static struct clk_regmap *gcc_apq8084_clocks[] = {
|
||||||
[GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
|
[GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.clkr,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc *gcc_apq8084_gdscs[] = {
|
||||||
|
[USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc,
|
||||||
|
[PCIE0_GDSC] = &pcie0_gdsc,
|
||||||
|
[PCIE1_GDSC] = &pcie1_gdsc,
|
||||||
|
[USB30_GDSC] = &usb30_gdsc,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct qcom_reset_map gcc_apq8084_resets[] = {
|
static const struct qcom_reset_map gcc_apq8084_resets[] = {
|
||||||
[GCC_SYSTEM_NOC_BCR] = { 0x0100 },
|
[GCC_SYSTEM_NOC_BCR] = { 0x0100 },
|
||||||
[GCC_CONFIG_NOC_BCR] = { 0x0140 },
|
[GCC_CONFIG_NOC_BCR] = { 0x0140 },
|
||||||
|
@ -3555,6 +3595,8 @@ static const struct qcom_cc_desc gcc_apq8084_desc = {
|
||||||
.num_clks = ARRAY_SIZE(gcc_apq8084_clocks),
|
.num_clks = ARRAY_SIZE(gcc_apq8084_clocks),
|
||||||
.resets = gcc_apq8084_resets,
|
.resets = gcc_apq8084_resets,
|
||||||
.num_resets = ARRAY_SIZE(gcc_apq8084_resets),
|
.num_resets = ARRAY_SIZE(gcc_apq8084_resets),
|
||||||
|
.gdscs = gcc_apq8084_gdscs,
|
||||||
|
.num_gdscs = ARRAY_SIZE(gcc_apq8084_gdscs),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id gcc_apq8084_match_table[] = {
|
static const struct of_device_id gcc_apq8084_match_table[] = {
|
||||||
|
@ -3581,15 +3623,8 @@ static int gcc_apq8084_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_probe(pdev, &gcc_apq8084_desc);
|
return qcom_cc_probe(pdev, &gcc_apq8084_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_apq8084_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver gcc_apq8084_driver = {
|
static struct platform_driver gcc_apq8084_driver = {
|
||||||
.probe = gcc_apq8084_probe,
|
.probe = gcc_apq8084_probe,
|
||||||
.remove = gcc_apq8084_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "gcc-apq8084",
|
.name = "gcc-apq8084",
|
||||||
.of_match_table = gcc_apq8084_match_table,
|
.of_match_table = gcc_apq8084_match_table,
|
||||||
|
|
|
@ -3058,15 +3058,8 @@ static int gcc_ipq806x_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_ipq806x_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver gcc_ipq806x_driver = {
|
static struct platform_driver gcc_ipq806x_driver = {
|
||||||
.probe = gcc_ipq806x_probe,
|
.probe = gcc_ipq806x_probe,
|
||||||
.remove = gcc_ipq806x_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "gcc-ipq806x",
|
.name = "gcc-ipq806x",
|
||||||
.of_match_table = gcc_ipq806x_match_table,
|
.of_match_table = gcc_ipq806x_match_table,
|
||||||
|
|
|
@ -2735,15 +2735,8 @@ static int gcc_msm8660_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_probe(pdev, &gcc_msm8660_desc);
|
return qcom_cc_probe(pdev, &gcc_msm8660_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_msm8660_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver gcc_msm8660_driver = {
|
static struct platform_driver gcc_msm8660_driver = {
|
||||||
.probe = gcc_msm8660_probe,
|
.probe = gcc_msm8660_probe,
|
||||||
.remove = gcc_msm8660_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "gcc-msm8660",
|
.name = "gcc-msm8660",
|
||||||
.of_match_table = gcc_msm8660_match_table,
|
.of_match_table = gcc_msm8660_match_table,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-branch.h"
|
#include "clk-branch.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
P_XO,
|
P_XO,
|
||||||
|
@ -44,6 +45,9 @@ enum {
|
||||||
P_SLEEP_CLK,
|
P_SLEEP_CLK,
|
||||||
P_DSI0_PHYPLL_BYTE,
|
P_DSI0_PHYPLL_BYTE,
|
||||||
P_DSI0_PHYPLL_DSI,
|
P_DSI0_PHYPLL_DSI,
|
||||||
|
P_EXT_PRI_I2S,
|
||||||
|
P_EXT_SEC_I2S,
|
||||||
|
P_EXT_MCLK,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct parent_map gcc_xo_gpll0_map[] = {
|
static const struct parent_map gcc_xo_gpll0_map[] = {
|
||||||
|
@ -190,6 +194,76 @@ static const char * const gcc_xo_gpll0a_gpll1_gpll2[] = {
|
||||||
"gpll2_vote",
|
"gpll2_vote",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct parent_map gcc_xo_gpll0_gpll1_sleep_map[] = {
|
||||||
|
{ P_XO, 0 },
|
||||||
|
{ P_GPLL0, 1 },
|
||||||
|
{ P_GPLL1, 2 },
|
||||||
|
{ P_SLEEP_CLK, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const gcc_xo_gpll0_gpll1_sleep[] = {
|
||||||
|
"xo",
|
||||||
|
"gpll0_vote",
|
||||||
|
"gpll1_vote",
|
||||||
|
"sleep_clk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct parent_map gcc_xo_gpll1_epi2s_emclk_sleep_map[] = {
|
||||||
|
{ P_XO, 0 },
|
||||||
|
{ P_GPLL1, 1 },
|
||||||
|
{ P_EXT_PRI_I2S, 2 },
|
||||||
|
{ P_EXT_MCLK, 3 },
|
||||||
|
{ P_SLEEP_CLK, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const gcc_xo_gpll1_epi2s_emclk_sleep[] = {
|
||||||
|
"xo",
|
||||||
|
"gpll1_vote",
|
||||||
|
"ext_pri_i2s",
|
||||||
|
"ext_mclk",
|
||||||
|
"sleep_clk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct parent_map gcc_xo_gpll1_esi2s_emclk_sleep_map[] = {
|
||||||
|
{ P_XO, 0 },
|
||||||
|
{ P_GPLL1, 1 },
|
||||||
|
{ P_EXT_SEC_I2S, 2 },
|
||||||
|
{ P_EXT_MCLK, 3 },
|
||||||
|
{ P_SLEEP_CLK, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const gcc_xo_gpll1_esi2s_emclk_sleep[] = {
|
||||||
|
"xo",
|
||||||
|
"gpll1_vote",
|
||||||
|
"ext_sec_i2s",
|
||||||
|
"ext_mclk",
|
||||||
|
"sleep_clk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct parent_map gcc_xo_sleep_map[] = {
|
||||||
|
{ P_XO, 0 },
|
||||||
|
{ P_SLEEP_CLK, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const gcc_xo_sleep[] = {
|
||||||
|
"xo",
|
||||||
|
"sleep_clk",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct parent_map gcc_xo_gpll1_emclk_sleep_map[] = {
|
||||||
|
{ P_XO, 0 },
|
||||||
|
{ P_GPLL1, 1 },
|
||||||
|
{ P_EXT_MCLK, 2 },
|
||||||
|
{ P_SLEEP_CLK, 6 }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const gcc_xo_gpll1_emclk_sleep[] = {
|
||||||
|
"xo",
|
||||||
|
"gpll1_vote",
|
||||||
|
"ext_mclk",
|
||||||
|
"sleep_clk",
|
||||||
|
};
|
||||||
|
|
||||||
#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
|
#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
|
||||||
|
|
||||||
static struct clk_pll gpll0 = {
|
static struct clk_pll gpll0 = {
|
||||||
|
@ -906,21 +980,15 @@ static struct clk_rcg2 gp3_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct freq_tbl ftbl_gcc_mdss_byte0_clk[] = {
|
|
||||||
{ .src = P_DSI0_PHYPLL_BYTE },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct clk_rcg2 byte0_clk_src = {
|
static struct clk_rcg2 byte0_clk_src = {
|
||||||
.cmd_rcgr = 0x4d044,
|
.cmd_rcgr = 0x4d044,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = gcc_xo_gpll0a_dsibyte_map,
|
.parent_map = gcc_xo_gpll0a_dsibyte_map,
|
||||||
.freq_tbl = ftbl_gcc_mdss_byte0_clk,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "byte0_clk_src",
|
.name = "byte0_clk_src",
|
||||||
.parent_names = gcc_xo_gpll0a_dsibyte,
|
.parent_names = gcc_xo_gpll0a_dsibyte,
|
||||||
.num_parents = 3,
|
.num_parents = 3,
|
||||||
.ops = &clk_byte_ops,
|
.ops = &clk_byte2_ops,
|
||||||
.flags = CLK_SET_RATE_PARENT,
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -968,17 +1036,11 @@ static struct clk_rcg2 mdp_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct freq_tbl ftbl_gcc_mdss_pclk[] = {
|
|
||||||
{ .src = P_DSI0_PHYPLL_DSI },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct clk_rcg2 pclk0_clk_src = {
|
static struct clk_rcg2 pclk0_clk_src = {
|
||||||
.cmd_rcgr = 0x4d000,
|
.cmd_rcgr = 0x4d000,
|
||||||
.mnd_width = 8,
|
.mnd_width = 8,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = gcc_xo_gpll0a_dsiphy_map,
|
.parent_map = gcc_xo_gpll0a_dsiphy_map,
|
||||||
.freq_tbl = ftbl_gcc_mdss_pclk,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "pclk0_clk_src",
|
.name = "pclk0_clk_src",
|
||||||
.parent_names = gcc_xo_gpll0a_dsiphy,
|
.parent_names = gcc_xo_gpll0a_dsiphy,
|
||||||
|
@ -1094,6 +1156,30 @@ static struct clk_rcg2 apss_tcu_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct freq_tbl ftbl_gcc_bimc_gpu_clk[] = {
|
||||||
|
F(19200000, P_XO, 1, 0, 0),
|
||||||
|
F(100000000, P_GPLL0, 8, 0, 0),
|
||||||
|
F(200000000, P_GPLL0, 4, 0, 0),
|
||||||
|
F(266500000, P_BIMC, 4, 0, 0),
|
||||||
|
F(400000000, P_GPLL0, 2, 0, 0),
|
||||||
|
F(533000000, P_BIMC, 2, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 bimc_gpu_clk_src = {
|
||||||
|
.cmd_rcgr = 0x31028,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_gpll0_bimc_map,
|
||||||
|
.freq_tbl = ftbl_gcc_bimc_gpu_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "bimc_gpu_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll0_bimc,
|
||||||
|
.num_parents = 3,
|
||||||
|
.flags = CLK_GET_RATE_NOCACHE,
|
||||||
|
.ops = &clk_rcg2_shared_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
|
static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
|
||||||
F(80000000, P_GPLL0, 10, 0, 0),
|
F(80000000, P_GPLL0, 10, 0, 0),
|
||||||
{ }
|
{ }
|
||||||
|
@ -1112,6 +1198,305 @@ static struct clk_rcg2 usb_hs_system_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct freq_tbl ftbl_gcc_ultaudio_ahb_clk[] = {
|
||||||
|
F(3200000, P_XO, 6, 0, 0),
|
||||||
|
F(6400000, P_XO, 3, 0, 0),
|
||||||
|
F(9600000, P_XO, 2, 0, 0),
|
||||||
|
F(19200000, P_XO, 1, 0, 0),
|
||||||
|
F(40000000, P_GPLL0, 10, 1, 2),
|
||||||
|
F(66670000, P_GPLL0, 12, 0, 0),
|
||||||
|
F(80000000, P_GPLL0, 10, 0, 0),
|
||||||
|
F(100000000, P_GPLL0, 8, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 ultaudio_ahbfabric_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c010,
|
||||||
|
.hid_width = 5,
|
||||||
|
.mnd_width = 8,
|
||||||
|
.parent_map = gcc_xo_gpll0_gpll1_sleep_map,
|
||||||
|
.freq_tbl = ftbl_gcc_ultaudio_ahb_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "ultaudio_ahbfabric_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll0_gpll1_sleep,
|
||||||
|
.num_parents = 4,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_clk = {
|
||||||
|
.halt_reg = 0x1c028,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c028,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_ahbfabric_ixfabric_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_ahbfabric_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_ahbfabric_ixfabric_lpm_clk = {
|
||||||
|
.halt_reg = 0x1c024,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c024,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_ahbfabric_ixfabric_lpm_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_ahbfabric_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct freq_tbl ftbl_gcc_ultaudio_lpaif_i2s_clk[] = {
|
||||||
|
F(256000, P_XO, 5, 1, 15),
|
||||||
|
F(512000, P_XO, 5, 2, 15),
|
||||||
|
F(705600, P_GPLL1, 16, 1, 80),
|
||||||
|
F(768000, P_XO, 5, 1, 5),
|
||||||
|
F(800000, P_XO, 5, 5, 24),
|
||||||
|
F(1024000, P_GPLL1, 14, 1, 63),
|
||||||
|
F(1152000, P_XO, 1, 3, 50),
|
||||||
|
F(1411200, P_GPLL1, 16, 1, 40),
|
||||||
|
F(1536000, P_XO, 1, 2, 25),
|
||||||
|
F(1600000, P_XO, 12, 0, 0),
|
||||||
|
F(2048000, P_GPLL1, 9, 1, 49),
|
||||||
|
F(2400000, P_XO, 8, 0, 0),
|
||||||
|
F(2822400, P_GPLL1, 16, 1, 20),
|
||||||
|
F(3072000, P_GPLL1, 14, 1, 21),
|
||||||
|
F(4096000, P_GPLL1, 9, 2, 49),
|
||||||
|
F(4800000, P_XO, 4, 0, 0),
|
||||||
|
F(5644800, P_GPLL1, 16, 1, 10),
|
||||||
|
F(6144000, P_GPLL1, 7, 1, 21),
|
||||||
|
F(8192000, P_GPLL1, 9, 4, 49),
|
||||||
|
F(9600000, P_XO, 2, 0, 0),
|
||||||
|
F(11289600, P_GPLL1, 16, 1, 5),
|
||||||
|
F(12288000, P_GPLL1, 7, 2, 21),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 ultaudio_lpaif_pri_i2s_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c054,
|
||||||
|
.hid_width = 5,
|
||||||
|
.mnd_width = 8,
|
||||||
|
.parent_map = gcc_xo_gpll1_epi2s_emclk_sleep_map,
|
||||||
|
.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "ultaudio_lpaif_pri_i2s_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll1_epi2s_emclk_sleep,
|
||||||
|
.num_parents = 5,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_lpaif_pri_i2s_clk = {
|
||||||
|
.halt_reg = 0x1c068,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c068,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_lpaif_pri_i2s_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_lpaif_pri_i2s_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 ultaudio_lpaif_sec_i2s_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c06c,
|
||||||
|
.hid_width = 5,
|
||||||
|
.mnd_width = 8,
|
||||||
|
.parent_map = gcc_xo_gpll1_esi2s_emclk_sleep_map,
|
||||||
|
.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "ultaudio_lpaif_sec_i2s_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll1_esi2s_emclk_sleep,
|
||||||
|
.num_parents = 5,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_lpaif_sec_i2s_clk = {
|
||||||
|
.halt_reg = 0x1c080,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c080,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_lpaif_sec_i2s_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_lpaif_sec_i2s_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 ultaudio_lpaif_aux_i2s_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c084,
|
||||||
|
.hid_width = 5,
|
||||||
|
.mnd_width = 8,
|
||||||
|
.parent_map = gcc_xo_gpll1_emclk_sleep_map,
|
||||||
|
.freq_tbl = ftbl_gcc_ultaudio_lpaif_i2s_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "ultaudio_lpaif_aux_i2s_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll1_esi2s_emclk_sleep,
|
||||||
|
.num_parents = 5,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_lpaif_aux_i2s_clk = {
|
||||||
|
.halt_reg = 0x1c098,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c098,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_lpaif_aux_i2s_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_lpaif_aux_i2s_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct freq_tbl ftbl_gcc_ultaudio_xo_clk[] = {
|
||||||
|
F(19200000, P_XO, 1, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 ultaudio_xo_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c034,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_sleep_map,
|
||||||
|
.freq_tbl = ftbl_gcc_ultaudio_xo_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "ultaudio_xo_clk_src",
|
||||||
|
.parent_names = gcc_xo_sleep,
|
||||||
|
.num_parents = 2,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_avsync_xo_clk = {
|
||||||
|
.halt_reg = 0x1c04c,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c04c,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_avsync_xo_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_xo_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_stc_xo_clk = {
|
||||||
|
.halt_reg = 0x1c050,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c050,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_stc_xo_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"ultaudio_xo_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct freq_tbl ftbl_codec_clk[] = {
|
||||||
|
F(19200000, P_XO, 1, 0, 0),
|
||||||
|
F(11289600, P_EXT_MCLK, 1, 0, 0),
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 codec_digcodec_clk_src = {
|
||||||
|
.cmd_rcgr = 0x1c09c,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_gpll1_emclk_sleep_map,
|
||||||
|
.freq_tbl = ftbl_codec_clk,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "codec_digcodec_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll1_emclk_sleep,
|
||||||
|
.num_parents = 4,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_codec_digcodec_clk = {
|
||||||
|
.halt_reg = 0x1c0b0,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c0b0,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_codec_digcodec_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"codec_digcodec_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_pcnoc_mport_clk = {
|
||||||
|
.halt_reg = 0x1c000,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c000,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_pcnoc_mport_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"pcnoc_bfdcd_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_ultaudio_pcnoc_sway_clk = {
|
||||||
|
.halt_reg = 0x1c004,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x1c004,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_ultaudio_pcnoc_sway_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"pcnoc_bfdcd_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
|
static const struct freq_tbl ftbl_gcc_venus0_vcodec0_clk[] = {
|
||||||
F(100000000, P_GPLL0, 8, 0, 0),
|
F(100000000, P_GPLL0, 8, 0, 0),
|
||||||
F(160000000, P_GPLL0, 5, 0, 0),
|
F(160000000, P_GPLL0, 5, 0, 0),
|
||||||
|
@ -2358,6 +2743,51 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg2 bimc_ddr_clk_src = {
|
||||||
|
.cmd_rcgr = 0x32004,
|
||||||
|
.hid_width = 5,
|
||||||
|
.parent_map = gcc_xo_gpll0_bimc_map,
|
||||||
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "bimc_ddr_clk_src",
|
||||||
|
.parent_names = gcc_xo_gpll0_bimc,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg2_ops,
|
||||||
|
.flags = CLK_GET_RATE_NOCACHE,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_apss_tcu_clk = {
|
||||||
|
.halt_reg = 0x12018,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x4500c,
|
||||||
|
.enable_mask = BIT(1),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_apss_tcu_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"bimc_ddr_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_gfx_tcu_clk = {
|
||||||
|
.halt_reg = 0x12020,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x4500c,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_gfx_tcu_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"bimc_ddr_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_branch gcc_gtcu_ahb_clk = {
|
static struct clk_branch gcc_gtcu_ahb_clk = {
|
||||||
.halt_reg = 0x12044,
|
.halt_reg = 0x12044,
|
||||||
.clkr = {
|
.clkr = {
|
||||||
|
@ -2375,6 +2805,40 @@ static struct clk_branch gcc_gtcu_ahb_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_bimc_gfx_clk = {
|
||||||
|
.halt_reg = 0x31024,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x31024,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_bimc_gfx_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"bimc_gpu_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch gcc_bimc_gpu_clk = {
|
||||||
|
.halt_reg = 0x31040,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x31040,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "gcc_bimc_gpu_clk",
|
||||||
|
.parent_names = (const char *[]){
|
||||||
|
"bimc_gpu_clk_src",
|
||||||
|
},
|
||||||
|
.num_parents = 1,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
.ops = &clk_branch2_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_branch gcc_jpeg_tbu_clk = {
|
static struct clk_branch gcc_jpeg_tbu_clk = {
|
||||||
.halt_reg = 0x12034,
|
.halt_reg = 0x12034,
|
||||||
.clkr = {
|
.clkr = {
|
||||||
|
@ -2562,6 +3026,46 @@ static struct clk_branch gcc_venus0_vcodec0_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc venus_gdsc = {
|
||||||
|
.gdscr = 0x4c018,
|
||||||
|
.pd = {
|
||||||
|
.name = "venus",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc mdss_gdsc = {
|
||||||
|
.gdscr = 0x4d078,
|
||||||
|
.pd = {
|
||||||
|
.name = "mdss",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc jpeg_gdsc = {
|
||||||
|
.gdscr = 0x5701c,
|
||||||
|
.pd = {
|
||||||
|
.name = "jpeg",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc vfe_gdsc = {
|
||||||
|
.gdscr = 0x58034,
|
||||||
|
.pd = {
|
||||||
|
.name = "vfe",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc oxili_gdsc = {
|
||||||
|
.gdscr = 0x5901c,
|
||||||
|
.pd = {
|
||||||
|
.name = "oxili",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_regmap *gcc_msm8916_clocks[] = {
|
static struct clk_regmap *gcc_msm8916_clocks[] = {
|
||||||
[GPLL0] = &gpll0.clkr,
|
[GPLL0] = &gpll0.clkr,
|
||||||
[GPLL0_VOTE] = &gpll0_vote,
|
[GPLL0_VOTE] = &gpll0_vote,
|
||||||
|
@ -2701,6 +3205,36 @@ static struct clk_regmap *gcc_msm8916_clocks[] = {
|
||||||
[GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
|
[GCC_VENUS0_AHB_CLK] = &gcc_venus0_ahb_clk.clkr,
|
||||||
[GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
|
[GCC_VENUS0_AXI_CLK] = &gcc_venus0_axi_clk.clkr,
|
||||||
[GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
|
[GCC_VENUS0_VCODEC0_CLK] = &gcc_venus0_vcodec0_clk.clkr,
|
||||||
|
[BIMC_DDR_CLK_SRC] = &bimc_ddr_clk_src.clkr,
|
||||||
|
[GCC_APSS_TCU_CLK] = &gcc_apss_tcu_clk.clkr,
|
||||||
|
[GCC_GFX_TCU_CLK] = &gcc_gfx_tcu_clk.clkr,
|
||||||
|
[BIMC_GPU_CLK_SRC] = &bimc_gpu_clk_src.clkr,
|
||||||
|
[GCC_BIMC_GFX_CLK] = &gcc_bimc_gfx_clk.clkr,
|
||||||
|
[GCC_BIMC_GPU_CLK] = &gcc_bimc_gpu_clk.clkr,
|
||||||
|
[ULTAUDIO_AHBFABRIC_CLK_SRC] = &ultaudio_ahbfabric_clk_src.clkr,
|
||||||
|
[ULTAUDIO_LPAIF_PRI_I2S_CLK_SRC] = &ultaudio_lpaif_pri_i2s_clk_src.clkr,
|
||||||
|
[ULTAUDIO_LPAIF_SEC_I2S_CLK_SRC] = &ultaudio_lpaif_sec_i2s_clk_src.clkr,
|
||||||
|
[ULTAUDIO_LPAIF_AUX_I2S_CLK_SRC] = &ultaudio_lpaif_aux_i2s_clk_src.clkr,
|
||||||
|
[ULTAUDIO_XO_CLK_SRC] = &ultaudio_xo_clk_src.clkr,
|
||||||
|
[CODEC_DIGCODEC_CLK_SRC] = &codec_digcodec_clk_src.clkr,
|
||||||
|
[GCC_ULTAUDIO_PCNOC_MPORT_CLK] = &gcc_ultaudio_pcnoc_mport_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_PCNOC_SWAY_CLK] = &gcc_ultaudio_pcnoc_sway_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_AVSYNC_XO_CLK] = &gcc_ultaudio_avsync_xo_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_STC_XO_CLK] = &gcc_ultaudio_stc_xo_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_AHBFABRIC_IXFABRIC_LPM_CLK] = &gcc_ultaudio_ahbfabric_ixfabric_lpm_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_LPAIF_PRI_I2S_CLK] = &gcc_ultaudio_lpaif_pri_i2s_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_LPAIF_SEC_I2S_CLK] = &gcc_ultaudio_lpaif_sec_i2s_clk.clkr,
|
||||||
|
[GCC_ULTAUDIO_LPAIF_AUX_I2S_CLK] = &gcc_ultaudio_lpaif_aux_i2s_clk.clkr,
|
||||||
|
[GCC_CODEC_DIGCODEC_CLK] = &gcc_codec_digcodec_clk.clkr,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc *gcc_msm8916_gdscs[] = {
|
||||||
|
[VENUS_GDSC] = &venus_gdsc,
|
||||||
|
[MDSS_GDSC] = &mdss_gdsc,
|
||||||
|
[JPEG_GDSC] = &jpeg_gdsc,
|
||||||
|
[VFE_GDSC] = &vfe_gdsc,
|
||||||
|
[OXILI_GDSC] = &oxili_gdsc,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_reset_map gcc_msm8916_resets[] = {
|
static const struct qcom_reset_map gcc_msm8916_resets[] = {
|
||||||
|
@ -2810,6 +3344,8 @@ static const struct qcom_cc_desc gcc_msm8916_desc = {
|
||||||
.num_clks = ARRAY_SIZE(gcc_msm8916_clocks),
|
.num_clks = ARRAY_SIZE(gcc_msm8916_clocks),
|
||||||
.resets = gcc_msm8916_resets,
|
.resets = gcc_msm8916_resets,
|
||||||
.num_resets = ARRAY_SIZE(gcc_msm8916_resets),
|
.num_resets = ARRAY_SIZE(gcc_msm8916_resets),
|
||||||
|
.gdscs = gcc_msm8916_gdscs,
|
||||||
|
.num_gdscs = ARRAY_SIZE(gcc_msm8916_gdscs),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id gcc_msm8916_match_table[] = {
|
static const struct of_device_id gcc_msm8916_match_table[] = {
|
||||||
|
@ -2836,15 +3372,8 @@ static int gcc_msm8916_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_probe(pdev, &gcc_msm8916_desc);
|
return qcom_cc_probe(pdev, &gcc_msm8916_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_msm8916_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver gcc_msm8916_driver = {
|
static struct platform_driver gcc_msm8916_driver = {
|
||||||
.probe = gcc_msm8916_probe,
|
.probe = gcc_msm8916_probe,
|
||||||
.remove = gcc_msm8916_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "gcc-msm8916",
|
.name = "gcc-msm8916",
|
||||||
.of_match_table = gcc_msm8916_match_table,
|
.of_match_table = gcc_msm8916_match_table,
|
||||||
|
|
|
@ -3506,6 +3506,8 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
const struct of_device_id *match;
|
const struct of_device_id *match;
|
||||||
|
struct platform_device *tsens;
|
||||||
|
int ret;
|
||||||
|
|
||||||
match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
|
match = of_match_device(gcc_msm8960_match_table, &pdev->dev);
|
||||||
if (!match)
|
if (!match)
|
||||||
|
@ -3520,12 +3522,26 @@ static int gcc_msm8960_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
return PTR_ERR(clk);
|
return PTR_ERR(clk);
|
||||||
|
|
||||||
return qcom_cc_probe(pdev, match->data);
|
ret = qcom_cc_probe(pdev, match->data);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
tsens = platform_device_register_data(&pdev->dev, "qcom-tsens", -1,
|
||||||
|
NULL, 0);
|
||||||
|
if (IS_ERR(tsens))
|
||||||
|
return PTR_ERR(tsens);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, tsens);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_msm8960_remove(struct platform_device *pdev)
|
static int gcc_msm8960_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
qcom_cc_remove(pdev);
|
struct platform_device *tsens = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
platform_device_unregister(tsens);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-branch.h"
|
#include "clk-branch.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
P_XO,
|
P_XO,
|
||||||
|
@ -2432,6 +2433,14 @@ static struct clk_branch gcc_usb_hsic_system_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc usb_hs_hsic_gdsc = {
|
||||||
|
.gdscr = 0x404,
|
||||||
|
.pd = {
|
||||||
|
.name = "usb_hs_hsic",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_regmap *gcc_msm8974_clocks[] = {
|
static struct clk_regmap *gcc_msm8974_clocks[] = {
|
||||||
[GPLL0] = &gpll0.clkr,
|
[GPLL0] = &gpll0.clkr,
|
||||||
[GPLL0_VOTE] = &gpll0_vote,
|
[GPLL0_VOTE] = &gpll0_vote,
|
||||||
|
@ -2661,6 +2670,10 @@ static const struct qcom_reset_map gcc_msm8974_resets[] = {
|
||||||
[GCC_VENUS_RESTART] = { 0x1740 },
|
[GCC_VENUS_RESTART] = { 0x1740 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc *gcc_msm8974_gdscs[] = {
|
||||||
|
[USB_HS_HSIC_GDSC] = &usb_hs_hsic_gdsc,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config gcc_msm8974_regmap_config = {
|
static const struct regmap_config gcc_msm8974_regmap_config = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
|
@ -2675,6 +2688,8 @@ static const struct qcom_cc_desc gcc_msm8974_desc = {
|
||||||
.num_clks = ARRAY_SIZE(gcc_msm8974_clocks),
|
.num_clks = ARRAY_SIZE(gcc_msm8974_clocks),
|
||||||
.resets = gcc_msm8974_resets,
|
.resets = gcc_msm8974_resets,
|
||||||
.num_resets = ARRAY_SIZE(gcc_msm8974_resets),
|
.num_resets = ARRAY_SIZE(gcc_msm8974_resets),
|
||||||
|
.gdscs = gcc_msm8974_gdscs,
|
||||||
|
.num_gdscs = ARRAY_SIZE(gcc_msm8974_gdscs),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id gcc_msm8974_match_table[] = {
|
static const struct of_device_id gcc_msm8974_match_table[] = {
|
||||||
|
@ -2729,15 +2744,8 @@ static int gcc_msm8974_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_probe(pdev, &gcc_msm8974_desc);
|
return qcom_cc_probe(pdev, &gcc_msm8974_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gcc_msm8974_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver gcc_msm8974_driver = {
|
static struct platform_driver gcc_msm8974_driver = {
|
||||||
.probe = gcc_msm8974_probe,
|
.probe = gcc_msm8974_probe,
|
||||||
.remove = gcc_msm8974_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "gcc-msm8974",
|
.name = "gcc-msm8974",
|
||||||
.of_match_table = gcc_msm8974_match_table,
|
.of_match_table = gcc_msm8974_match_table,
|
||||||
|
|
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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/bitops.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/reset-controller.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
|
#define PWR_ON_MASK BIT(31)
|
||||||
|
#define EN_REST_WAIT_MASK GENMASK_ULL(23, 20)
|
||||||
|
#define EN_FEW_WAIT_MASK GENMASK_ULL(19, 16)
|
||||||
|
#define CLK_DIS_WAIT_MASK GENMASK_ULL(15, 12)
|
||||||
|
#define SW_OVERRIDE_MASK BIT(2)
|
||||||
|
#define HW_CONTROL_MASK BIT(1)
|
||||||
|
#define SW_COLLAPSE_MASK BIT(0)
|
||||||
|
|
||||||
|
/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
|
||||||
|
#define EN_REST_WAIT_VAL (0x2 << 20)
|
||||||
|
#define EN_FEW_WAIT_VAL (0x8 << 16)
|
||||||
|
#define CLK_DIS_WAIT_VAL (0x2 << 12)
|
||||||
|
|
||||||
|
#define RETAIN_MEM BIT(14)
|
||||||
|
#define RETAIN_PERIPH BIT(13)
|
||||||
|
|
||||||
|
#define TIMEOUT_US 100
|
||||||
|
|
||||||
|
#define domain_to_gdsc(domain) container_of(domain, struct gdsc, pd)
|
||||||
|
|
||||||
|
static int gdsc_is_enabled(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
u32 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = regmap_read(sc->regmap, sc->gdscr, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return !!(val & PWR_ON_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gdsc_toggle_logic(struct gdsc *sc, bool en)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
u32 val = en ? 0 : SW_COLLAPSE_MASK;
|
||||||
|
u32 check = en ? PWR_ON_MASK : 0;
|
||||||
|
unsigned long timeout;
|
||||||
|
|
||||||
|
ret = regmap_update_bits(sc->regmap, sc->gdscr, SW_COLLAPSE_MASK, val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
timeout = jiffies + usecs_to_jiffies(TIMEOUT_US);
|
||||||
|
do {
|
||||||
|
ret = regmap_read(sc->regmap, sc->gdscr, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((val & PWR_ON_MASK) == check)
|
||||||
|
return 0;
|
||||||
|
} while (time_before(jiffies, timeout));
|
||||||
|
|
||||||
|
ret = regmap_read(sc->regmap, sc->gdscr, &val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if ((val & PWR_ON_MASK) == check)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int gdsc_deassert_reset(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sc->reset_count; i++)
|
||||||
|
sc->rcdev->ops->deassert(sc->rcdev, sc->resets[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int gdsc_assert_reset(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < sc->reset_count; i++)
|
||||||
|
sc->rcdev->ops->assert(sc->rcdev, sc->resets[i]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gdsc_force_mem_on(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 mask = RETAIN_MEM | RETAIN_PERIPH;
|
||||||
|
|
||||||
|
for (i = 0; i < sc->cxc_count; i++)
|
||||||
|
regmap_update_bits(sc->regmap, sc->cxcs[i], mask, mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gdsc_clear_mem_on(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 mask = RETAIN_MEM | RETAIN_PERIPH;
|
||||||
|
|
||||||
|
for (i = 0; i < sc->cxc_count; i++)
|
||||||
|
regmap_update_bits(sc->regmap, sc->cxcs[i], mask, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gdsc_enable(struct generic_pm_domain *domain)
|
||||||
|
{
|
||||||
|
struct gdsc *sc = domain_to_gdsc(domain);
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (sc->pwrsts == PWRSTS_ON)
|
||||||
|
return gdsc_deassert_reset(sc);
|
||||||
|
|
||||||
|
ret = gdsc_toggle_logic(sc, true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
if (sc->pwrsts & PWRSTS_OFF)
|
||||||
|
gdsc_force_mem_on(sc);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If clocks to this power domain were already on, they will take an
|
||||||
|
* additional 4 clock cycles to re-enable after the power domain is
|
||||||
|
* enabled. Delay to account for this. A delay is also needed to ensure
|
||||||
|
* clocks are not enabled within 400ns of enabling power to the
|
||||||
|
* memories.
|
||||||
|
*/
|
||||||
|
udelay(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gdsc_disable(struct generic_pm_domain *domain)
|
||||||
|
{
|
||||||
|
struct gdsc *sc = domain_to_gdsc(domain);
|
||||||
|
|
||||||
|
if (sc->pwrsts == PWRSTS_ON)
|
||||||
|
return gdsc_assert_reset(sc);
|
||||||
|
|
||||||
|
if (sc->pwrsts & PWRSTS_OFF)
|
||||||
|
gdsc_clear_mem_on(sc);
|
||||||
|
|
||||||
|
return gdsc_toggle_logic(sc, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gdsc_init(struct gdsc *sc)
|
||||||
|
{
|
||||||
|
u32 mask, val;
|
||||||
|
int on, ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable HW trigger: collapse/restore occur based on registers writes.
|
||||||
|
* Disable SW override: Use hardware state-machine for sequencing.
|
||||||
|
* Configure wait time between states.
|
||||||
|
*/
|
||||||
|
mask = HW_CONTROL_MASK | SW_OVERRIDE_MASK |
|
||||||
|
EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK;
|
||||||
|
val = EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
|
||||||
|
ret = regmap_update_bits(sc->regmap, sc->gdscr, mask, val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* Force gdsc ON if only ON state is supported */
|
||||||
|
if (sc->pwrsts == PWRSTS_ON) {
|
||||||
|
ret = gdsc_toggle_logic(sc, true);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
on = gdsc_is_enabled(sc);
|
||||||
|
if (on < 0)
|
||||||
|
return on;
|
||||||
|
|
||||||
|
if (on || (sc->pwrsts & PWRSTS_RET))
|
||||||
|
gdsc_force_mem_on(sc);
|
||||||
|
else
|
||||||
|
gdsc_clear_mem_on(sc);
|
||||||
|
|
||||||
|
sc->pd.power_off = gdsc_disable;
|
||||||
|
sc->pd.power_on = gdsc_enable;
|
||||||
|
pm_genpd_init(&sc->pd, NULL, !on);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int gdsc_register(struct device *dev, struct gdsc **scs, size_t num,
|
||||||
|
struct reset_controller_dev *rcdev, struct regmap *regmap)
|
||||||
|
{
|
||||||
|
int i, ret;
|
||||||
|
struct genpd_onecell_data *data;
|
||||||
|
|
||||||
|
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
|
||||||
|
if (!data)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->domains = devm_kcalloc(dev, num, sizeof(*data->domains),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!data->domains)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
data->num_domains = num;
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
if (!scs[i])
|
||||||
|
continue;
|
||||||
|
scs[i]->regmap = regmap;
|
||||||
|
scs[i]->rcdev = rcdev;
|
||||||
|
ret = gdsc_init(scs[i]);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
data->domains[i] = &scs[i]->pd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return of_genpd_add_provider_onecell(dev->of_node, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gdsc_unregister(struct device *dev)
|
||||||
|
{
|
||||||
|
of_genpd_del_provider(dev->of_node);
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, The Linux Foundation. All rights reserved.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 and
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* 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_GDSC_H__
|
||||||
|
#define __QCOM_GDSC_H__
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
|
|
||||||
|
struct regmap;
|
||||||
|
struct reset_controller_dev;
|
||||||
|
|
||||||
|
/* Powerdomain allowable state bitfields */
|
||||||
|
#define PWRSTS_OFF BIT(0)
|
||||||
|
#define PWRSTS_RET BIT(1)
|
||||||
|
#define PWRSTS_ON BIT(2)
|
||||||
|
#define PWRSTS_OFF_ON (PWRSTS_OFF | PWRSTS_ON)
|
||||||
|
#define PWRSTS_RET_ON (PWRSTS_RET | PWRSTS_ON)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* struct gdsc - Globally Distributed Switch Controller
|
||||||
|
* @pd: generic power domain
|
||||||
|
* @regmap: regmap for MMIO accesses
|
||||||
|
* @gdscr: gsdc control register
|
||||||
|
* @cxcs: offsets of branch registers to toggle mem/periph bits in
|
||||||
|
* @cxc_count: number of @cxcs
|
||||||
|
* @pwrsts: Possible powerdomain power states
|
||||||
|
* @resets: ids of resets associated with this gdsc
|
||||||
|
* @reset_count: number of @resets
|
||||||
|
* @rcdev: reset controller
|
||||||
|
*/
|
||||||
|
struct gdsc {
|
||||||
|
struct generic_pm_domain pd;
|
||||||
|
struct regmap *regmap;
|
||||||
|
unsigned int gdscr;
|
||||||
|
unsigned int *cxcs;
|
||||||
|
unsigned int cxc_count;
|
||||||
|
const u8 pwrsts;
|
||||||
|
struct reset_controller_dev *rcdev;
|
||||||
|
unsigned int *resets;
|
||||||
|
unsigned int reset_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_QCOM_GDSC
|
||||||
|
int gdsc_register(struct device *, struct gdsc **, size_t n,
|
||||||
|
struct reset_controller_dev *, struct regmap *);
|
||||||
|
void gdsc_unregister(struct device *);
|
||||||
|
#else
|
||||||
|
static inline int gdsc_register(struct device *d, struct gdsc **g, size_t n,
|
||||||
|
struct reset_controller_dev *rcdev,
|
||||||
|
struct regmap *r)
|
||||||
|
{
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void gdsc_unregister(struct device *d) {};
|
||||||
|
#endif /* CONFIG_QCOM_GDSC */
|
||||||
|
#endif /* __QCOM_GDSC_H__ */
|
|
@ -452,15 +452,8 @@ static int lcc_ipq806x_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
|
return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lcc_ipq806x_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver lcc_ipq806x_driver = {
|
static struct platform_driver lcc_ipq806x_driver = {
|
||||||
.probe = lcc_ipq806x_probe,
|
.probe = lcc_ipq806x_probe,
|
||||||
.remove = lcc_ipq806x_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "lcc-ipq806x",
|
.name = "lcc-ipq806x",
|
||||||
.of_match_table = lcc_ipq806x_match_table,
|
.of_match_table = lcc_ipq806x_match_table,
|
||||||
|
|
|
@ -565,15 +565,8 @@ static int lcc_msm8960_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap);
|
return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int lcc_msm8960_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver lcc_msm8960_driver = {
|
static struct platform_driver lcc_msm8960_driver = {
|
||||||
.probe = lcc_msm8960_probe,
|
.probe = lcc_msm8960_probe,
|
||||||
.remove = lcc_msm8960_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "lcc-msm8960",
|
.name = "lcc-msm8960",
|
||||||
.of_match_table = lcc_msm8960_match_table,
|
.of_match_table = lcc_msm8960_match_table,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2014, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||||
*
|
*
|
||||||
* This software is licensed under the terms of the GNU General Public
|
* This software is licensed under the terms of the GNU General Public
|
||||||
* License version 2, as published by the Free Software Foundation, and
|
* License version 2, as published by the Free Software Foundation, and
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-branch.h"
|
#include "clk-branch.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
P_XO,
|
P_XO,
|
||||||
|
@ -571,17 +572,11 @@ static struct clk_rcg2 jpeg2_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct freq_tbl pixel_freq_tbl[] = {
|
|
||||||
{ .src = P_DSI0PLL },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct clk_rcg2 pclk0_clk_src = {
|
static struct clk_rcg2 pclk0_clk_src = {
|
||||||
.cmd_rcgr = 0x2000,
|
.cmd_rcgr = 0x2000,
|
||||||
.mnd_width = 8,
|
.mnd_width = 8,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = pixel_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "pclk0_clk_src",
|
.name = "pclk0_clk_src",
|
||||||
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
||||||
|
@ -596,7 +591,6 @@ static struct clk_rcg2 pclk1_clk_src = {
|
||||||
.mnd_width = 8,
|
.mnd_width = 8,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = pixel_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "pclk1_clk_src",
|
.name = "pclk1_clk_src",
|
||||||
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
||||||
|
@ -844,21 +838,15 @@ static struct clk_rcg2 cpp_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct freq_tbl byte_freq_tbl[] = {
|
|
||||||
{ .src = P_DSI0PLL_BYTE },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct clk_rcg2 byte0_clk_src = {
|
static struct clk_rcg2 byte0_clk_src = {
|
||||||
.cmd_rcgr = 0x2120,
|
.cmd_rcgr = 0x2120,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = byte_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "byte0_clk_src",
|
.name = "byte0_clk_src",
|
||||||
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
||||||
.num_parents = 6,
|
.num_parents = 6,
|
||||||
.ops = &clk_byte_ops,
|
.ops = &clk_byte2_ops,
|
||||||
.flags = CLK_SET_RATE_PARENT,
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -867,12 +855,11 @@ static struct clk_rcg2 byte1_clk_src = {
|
||||||
.cmd_rcgr = 0x2140,
|
.cmd_rcgr = 0x2140,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsibyte_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = byte_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "byte1_clk_src",
|
.name = "byte1_clk_src",
|
||||||
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
||||||
.num_parents = 6,
|
.num_parents = 6,
|
||||||
.ops = &clk_byte_ops,
|
.ops = &clk_byte2_ops,
|
||||||
.flags = CLK_SET_RATE_PARENT,
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -3077,6 +3064,76 @@ static const struct pll_config mmpll3_config = {
|
||||||
.aux_output_mask = BIT(1),
|
.aux_output_mask = BIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc venus0_gdsc = {
|
||||||
|
.gdscr = 0x1024,
|
||||||
|
.pd = {
|
||||||
|
.name = "venus0",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc venus0_core0_gdsc = {
|
||||||
|
.gdscr = 0x1040,
|
||||||
|
.pd = {
|
||||||
|
.name = "venus0_core0",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc venus0_core1_gdsc = {
|
||||||
|
.gdscr = 0x1044,
|
||||||
|
.pd = {
|
||||||
|
.name = "venus0_core1",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc mdss_gdsc = {
|
||||||
|
.gdscr = 0x2304,
|
||||||
|
.cxcs = (unsigned int []){ 0x231c, 0x2320 },
|
||||||
|
.cxc_count = 2,
|
||||||
|
.pd = {
|
||||||
|
.name = "mdss",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc camss_jpeg_gdsc = {
|
||||||
|
.gdscr = 0x35a4,
|
||||||
|
.pd = {
|
||||||
|
.name = "camss_jpeg",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc camss_vfe_gdsc = {
|
||||||
|
.gdscr = 0x36a4,
|
||||||
|
.cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x36b0 },
|
||||||
|
.cxc_count = 3,
|
||||||
|
.pd = {
|
||||||
|
.name = "camss_vfe",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc oxili_gdsc = {
|
||||||
|
.gdscr = 0x4024,
|
||||||
|
.cxcs = (unsigned int []){ 0x4028 },
|
||||||
|
.cxc_count = 1,
|
||||||
|
.pd = {
|
||||||
|
.name = "oxili",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc oxilicx_gdsc = {
|
||||||
|
.gdscr = 0x4034,
|
||||||
|
.pd = {
|
||||||
|
.name = "oxilicx",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_regmap *mmcc_apq8084_clocks[] = {
|
static struct clk_regmap *mmcc_apq8084_clocks[] = {
|
||||||
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
|
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
|
||||||
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
|
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
|
||||||
|
@ -3294,6 +3351,17 @@ static const struct qcom_reset_map mmcc_apq8084_resets[] = {
|
||||||
[MMSSNOCAXI_RESET] = { 0x5060 },
|
[MMSSNOCAXI_RESET] = { 0x5060 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc *mmcc_apq8084_gdscs[] = {
|
||||||
|
[VENUS0_GDSC] = &venus0_gdsc,
|
||||||
|
[VENUS0_CORE0_GDSC] = &venus0_core0_gdsc,
|
||||||
|
[VENUS0_CORE1_GDSC] = &venus0_core1_gdsc,
|
||||||
|
[MDSS_GDSC] = &mdss_gdsc,
|
||||||
|
[CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc,
|
||||||
|
[CAMSS_VFE_GDSC] = &camss_vfe_gdsc,
|
||||||
|
[OXILI_GDSC] = &oxili_gdsc,
|
||||||
|
[OXILICX_GDSC] = &oxilicx_gdsc,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config mmcc_apq8084_regmap_config = {
|
static const struct regmap_config mmcc_apq8084_regmap_config = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
|
@ -3308,6 +3376,8 @@ static const struct qcom_cc_desc mmcc_apq8084_desc = {
|
||||||
.num_clks = ARRAY_SIZE(mmcc_apq8084_clocks),
|
.num_clks = ARRAY_SIZE(mmcc_apq8084_clocks),
|
||||||
.resets = mmcc_apq8084_resets,
|
.resets = mmcc_apq8084_resets,
|
||||||
.num_resets = ARRAY_SIZE(mmcc_apq8084_resets),
|
.num_resets = ARRAY_SIZE(mmcc_apq8084_resets),
|
||||||
|
.gdscs = mmcc_apq8084_gdscs,
|
||||||
|
.num_gdscs = ARRAY_SIZE(mmcc_apq8084_gdscs),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id mmcc_apq8084_match_table[] = {
|
static const struct of_device_id mmcc_apq8084_match_table[] = {
|
||||||
|
@ -3332,15 +3402,8 @@ static int mmcc_apq8084_probe(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmcc_apq8084_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver mmcc_apq8084_driver = {
|
static struct platform_driver mmcc_apq8084_driver = {
|
||||||
.probe = mmcc_apq8084_probe,
|
.probe = mmcc_apq8084_probe,
|
||||||
.remove = mmcc_apq8084_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mmcc-apq8084",
|
.name = "mmcc-apq8084",
|
||||||
.of_match_table = mmcc_apq8084_match_table,
|
.of_match_table = mmcc_apq8084_match_table,
|
||||||
|
|
|
@ -41,6 +41,10 @@ enum {
|
||||||
P_PLL3,
|
P_PLL3,
|
||||||
P_PLL15,
|
P_PLL15,
|
||||||
P_HDMI_PLL,
|
P_HDMI_PLL,
|
||||||
|
P_DSI1_PLL_DSICLK,
|
||||||
|
P_DSI2_PLL_DSICLK,
|
||||||
|
P_DSI1_PLL_BYTECLK,
|
||||||
|
P_DSI2_PLL_BYTECLK,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
|
#define F_MN(f, s, _m, _n) { .freq = f, .src = s, .m = _m, .n = _n }
|
||||||
|
@ -85,6 +89,30 @@ static const char * const mmcc_pxo_pll8_pll2_pll3[] = {
|
||||||
"pll3",
|
"pll3",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct parent_map mmcc_pxo_dsi2_dsi1_map[] = {
|
||||||
|
{ P_PXO, 0 },
|
||||||
|
{ P_DSI2_PLL_DSICLK, 1 },
|
||||||
|
{ P_DSI1_PLL_DSICLK, 3 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const mmcc_pxo_dsi2_dsi1[] = {
|
||||||
|
"pxo",
|
||||||
|
"dsi2pll",
|
||||||
|
"dsi1pll",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct parent_map mmcc_pxo_dsi1_dsi2_byte_map[] = {
|
||||||
|
{ P_PXO, 0 },
|
||||||
|
{ P_DSI1_PLL_BYTECLK, 1 },
|
||||||
|
{ P_DSI2_PLL_BYTECLK, 2 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const mmcc_pxo_dsi1_dsi2_byte[] = {
|
||||||
|
"pxo",
|
||||||
|
"dsi1pllbyte",
|
||||||
|
"dsi2pllbyte",
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_pll pll2 = {
|
static struct clk_pll pll2 = {
|
||||||
.l_reg = 0x320,
|
.l_reg = 0x320,
|
||||||
.m_reg = 0x324,
|
.m_reg = 0x324,
|
||||||
|
@ -2042,6 +2070,350 @@ static struct clk_branch dsi2_s_ahb_clk = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi1_src = {
|
||||||
|
.ns_reg = 0x0054,
|
||||||
|
.md_reg = 0x0050,
|
||||||
|
.mn = {
|
||||||
|
.mnctr_en_bit = 5,
|
||||||
|
.mnctr_reset_bit = 7,
|
||||||
|
.mnctr_mode_shift = 6,
|
||||||
|
.n_val_shift = 24,
|
||||||
|
.m_val_shift = 8,
|
||||||
|
.width = 8,
|
||||||
|
},
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 14,
|
||||||
|
.pre_div_width = 2,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi2_dsi1_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x004c,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi2_dsi1,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_bypass2_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi1_clk = {
|
||||||
|
.halt_reg = 0x01d0,
|
||||||
|
.halt_bit = 2,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x004c,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi1_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi2_src = {
|
||||||
|
.ns_reg = 0x012c,
|
||||||
|
.md_reg = 0x00a8,
|
||||||
|
.mn = {
|
||||||
|
.mnctr_en_bit = 5,
|
||||||
|
.mnctr_reset_bit = 7,
|
||||||
|
.mnctr_mode_shift = 6,
|
||||||
|
.n_val_shift = 24,
|
||||||
|
.m_val_shift = 8,
|
||||||
|
.width = 8,
|
||||||
|
},
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 14,
|
||||||
|
.pre_div_width = 2,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi2_dsi1_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x003c,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi2_dsi1,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_bypass2_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi2_clk = {
|
||||||
|
.halt_reg = 0x01d0,
|
||||||
|
.halt_bit = 20,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x003c,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi2_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi1_byte_src = {
|
||||||
|
.ns_reg = 0x00b0,
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0090,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_byte_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi1_dsi2_byte,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_bypass2_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi1_byte_clk = {
|
||||||
|
.halt_reg = 0x01cc,
|
||||||
|
.halt_bit = 21,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0090,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_byte_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi1_byte_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi2_byte_src = {
|
||||||
|
.ns_reg = 0x012c,
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0130,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_byte_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi1_dsi2_byte,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_bypass2_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi2_byte_clk = {
|
||||||
|
.halt_reg = 0x01cc,
|
||||||
|
.halt_bit = 20,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x00b4,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_byte_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi2_byte_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi1_esc_src = {
|
||||||
|
.ns_reg = 0x0011c,
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x00cc,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_esc_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi1_dsi2_byte,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_esc_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi1_esc_clk = {
|
||||||
|
.halt_reg = 0x01e8,
|
||||||
|
.halt_bit = 1,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x00cc,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_esc_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi1_esc_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi2_esc_src = {
|
||||||
|
.ns_reg = 0x0150,
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi1_dsi2_byte_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x013c,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_esc_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi1_dsi2_byte,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_esc_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi2_esc_clk = {
|
||||||
|
.halt_reg = 0x01e8,
|
||||||
|
.halt_bit = 3,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x013c,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_esc_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi2_esc_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi1_pixel_src = {
|
||||||
|
.ns_reg = 0x0138,
|
||||||
|
.md_reg = 0x0134,
|
||||||
|
.mn = {
|
||||||
|
.mnctr_en_bit = 5,
|
||||||
|
.mnctr_reset_bit = 7,
|
||||||
|
.mnctr_mode_shift = 6,
|
||||||
|
.n_val_shift = 16,
|
||||||
|
.m_val_shift = 8,
|
||||||
|
.width = 8,
|
||||||
|
},
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi2_dsi1_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0130,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi1_pixel_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi2_dsi1,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_pixel_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi1_pixel_clk = {
|
||||||
|
.halt_reg = 0x01d0,
|
||||||
|
.halt_bit = 6,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0130,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "mdp_pclk1_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi1_pixel_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_rcg dsi2_pixel_src = {
|
||||||
|
.ns_reg = 0x00e4,
|
||||||
|
.md_reg = 0x00b8,
|
||||||
|
.mn = {
|
||||||
|
.mnctr_en_bit = 5,
|
||||||
|
.mnctr_reset_bit = 7,
|
||||||
|
.mnctr_mode_shift = 6,
|
||||||
|
.n_val_shift = 16,
|
||||||
|
.m_val_shift = 8,
|
||||||
|
.width = 8,
|
||||||
|
},
|
||||||
|
.p = {
|
||||||
|
.pre_div_shift = 12,
|
||||||
|
.pre_div_width = 4,
|
||||||
|
},
|
||||||
|
.s = {
|
||||||
|
.src_sel_shift = 0,
|
||||||
|
.parent_map = mmcc_pxo_dsi2_dsi1_map,
|
||||||
|
},
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0094,
|
||||||
|
.enable_mask = BIT(2),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "dsi2_pixel_src",
|
||||||
|
.parent_names = mmcc_pxo_dsi2_dsi1,
|
||||||
|
.num_parents = 3,
|
||||||
|
.ops = &clk_rcg_pixel_ops,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct clk_branch dsi2_pixel_clk = {
|
||||||
|
.halt_reg = 0x01d0,
|
||||||
|
.halt_bit = 19,
|
||||||
|
.clkr = {
|
||||||
|
.enable_reg = 0x0094,
|
||||||
|
.enable_mask = BIT(0),
|
||||||
|
.hw.init = &(struct clk_init_data){
|
||||||
|
.name = "mdp_pclk2_clk",
|
||||||
|
.parent_names = (const char *[]){ "dsi2_pixel_src" },
|
||||||
|
.num_parents = 1,
|
||||||
|
.ops = &clk_branch_ops,
|
||||||
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_branch gfx2d0_ahb_clk = {
|
static struct clk_branch gfx2d0_ahb_clk = {
|
||||||
.hwcg_reg = 0x0038,
|
.hwcg_reg = 0x0038,
|
||||||
.hwcg_bit = 28,
|
.hwcg_bit = 28,
|
||||||
|
@ -2325,6 +2697,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
|
||||||
[CSI2_SRC] = &csi2_src.clkr,
|
[CSI2_SRC] = &csi2_src.clkr,
|
||||||
[CSI2_CLK] = &csi2_clk.clkr,
|
[CSI2_CLK] = &csi2_clk.clkr,
|
||||||
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
|
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
|
||||||
|
[DSI_SRC] = &dsi1_src.clkr,
|
||||||
|
[DSI_CLK] = &dsi1_clk.clkr,
|
||||||
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
|
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
|
||||||
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
|
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
|
||||||
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
|
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
|
||||||
|
@ -2345,6 +2719,18 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
|
||||||
[MDP_SRC] = &mdp_src.clkr,
|
[MDP_SRC] = &mdp_src.clkr,
|
||||||
[MDP_CLK] = &mdp_clk.clkr,
|
[MDP_CLK] = &mdp_clk.clkr,
|
||||||
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
|
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
|
||||||
|
[DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
|
||||||
|
[DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
|
||||||
|
[DSI2_SRC] = &dsi2_src.clkr,
|
||||||
|
[DSI2_CLK] = &dsi2_clk.clkr,
|
||||||
|
[DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
|
||||||
|
[DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
|
||||||
|
[DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
|
||||||
|
[DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
|
||||||
|
[DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
|
||||||
|
[DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
|
||||||
|
[DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
|
||||||
|
[DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
|
||||||
[ROT_SRC] = &rot_src.clkr,
|
[ROT_SRC] = &rot_src.clkr,
|
||||||
[ROT_CLK] = &rot_clk.clkr,
|
[ROT_CLK] = &rot_clk.clkr,
|
||||||
[TV_ENC_CLK] = &tv_enc_clk.clkr,
|
[TV_ENC_CLK] = &tv_enc_clk.clkr,
|
||||||
|
@ -2359,6 +2745,8 @@ static struct clk_regmap *mmcc_msm8960_clks[] = {
|
||||||
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
|
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
|
||||||
[VPE_SRC] = &vpe_src.clkr,
|
[VPE_SRC] = &vpe_src.clkr,
|
||||||
[VPE_CLK] = &vpe_clk.clkr,
|
[VPE_CLK] = &vpe_clk.clkr,
|
||||||
|
[DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
|
||||||
|
[DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
|
||||||
[CAMCLK0_SRC] = &camclk0_src.clkr,
|
[CAMCLK0_SRC] = &camclk0_src.clkr,
|
||||||
[CAMCLK0_CLK] = &camclk0_clk.clkr,
|
[CAMCLK0_CLK] = &camclk0_clk.clkr,
|
||||||
[CAMCLK1_SRC] = &camclk1_src.clkr,
|
[CAMCLK1_SRC] = &camclk1_src.clkr,
|
||||||
|
@ -2490,6 +2878,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
|
||||||
[CSI2_SRC] = &csi2_src.clkr,
|
[CSI2_SRC] = &csi2_src.clkr,
|
||||||
[CSI2_CLK] = &csi2_clk.clkr,
|
[CSI2_CLK] = &csi2_clk.clkr,
|
||||||
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
|
[CSI2_PHY_CLK] = &csi2_phy_clk.clkr,
|
||||||
|
[DSI_SRC] = &dsi1_src.clkr,
|
||||||
|
[DSI_CLK] = &dsi1_clk.clkr,
|
||||||
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
|
[CSI_PIX_CLK] = &csi_pix_clk.clkr,
|
||||||
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
|
[CSI_RDI_CLK] = &csi_rdi_clk.clkr,
|
||||||
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
|
[MDP_VSYNC_CLK] = &mdp_vsync_clk.clkr,
|
||||||
|
@ -2506,6 +2896,18 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
|
||||||
[MDP_SRC] = &mdp_src.clkr,
|
[MDP_SRC] = &mdp_src.clkr,
|
||||||
[MDP_CLK] = &mdp_clk.clkr,
|
[MDP_CLK] = &mdp_clk.clkr,
|
||||||
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
|
[MDP_LUT_CLK] = &mdp_lut_clk.clkr,
|
||||||
|
[DSI2_PIXEL_SRC] = &dsi2_pixel_src.clkr,
|
||||||
|
[DSI2_PIXEL_CLK] = &dsi2_pixel_clk.clkr,
|
||||||
|
[DSI2_SRC] = &dsi2_src.clkr,
|
||||||
|
[DSI2_CLK] = &dsi2_clk.clkr,
|
||||||
|
[DSI1_BYTE_SRC] = &dsi1_byte_src.clkr,
|
||||||
|
[DSI1_BYTE_CLK] = &dsi1_byte_clk.clkr,
|
||||||
|
[DSI2_BYTE_SRC] = &dsi2_byte_src.clkr,
|
||||||
|
[DSI2_BYTE_CLK] = &dsi2_byte_clk.clkr,
|
||||||
|
[DSI1_ESC_SRC] = &dsi1_esc_src.clkr,
|
||||||
|
[DSI1_ESC_CLK] = &dsi1_esc_clk.clkr,
|
||||||
|
[DSI2_ESC_SRC] = &dsi2_esc_src.clkr,
|
||||||
|
[DSI2_ESC_CLK] = &dsi2_esc_clk.clkr,
|
||||||
[ROT_SRC] = &rot_src.clkr,
|
[ROT_SRC] = &rot_src.clkr,
|
||||||
[ROT_CLK] = &rot_clk.clkr,
|
[ROT_CLK] = &rot_clk.clkr,
|
||||||
[TV_DAC_CLK] = &tv_dac_clk.clkr,
|
[TV_DAC_CLK] = &tv_dac_clk.clkr,
|
||||||
|
@ -2519,6 +2921,8 @@ static struct clk_regmap *mmcc_apq8064_clks[] = {
|
||||||
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
|
[VFE_CSI_CLK] = &vfe_csi_clk.clkr,
|
||||||
[VPE_SRC] = &vpe_src.clkr,
|
[VPE_SRC] = &vpe_src.clkr,
|
||||||
[VPE_CLK] = &vpe_clk.clkr,
|
[VPE_CLK] = &vpe_clk.clkr,
|
||||||
|
[DSI_PIXEL_SRC] = &dsi1_pixel_src.clkr,
|
||||||
|
[DSI_PIXEL_CLK] = &dsi1_pixel_clk.clkr,
|
||||||
[CAMCLK0_SRC] = &camclk0_src.clkr,
|
[CAMCLK0_SRC] = &camclk0_src.clkr,
|
||||||
[CAMCLK0_CLK] = &camclk0_clk.clkr,
|
[CAMCLK0_CLK] = &camclk0_clk.clkr,
|
||||||
[CAMCLK1_SRC] = &camclk1_src.clkr,
|
[CAMCLK1_SRC] = &camclk1_src.clkr,
|
||||||
|
@ -2686,15 +3090,8 @@ static int mmcc_msm8960_probe(struct platform_device *pdev)
|
||||||
return qcom_cc_really_probe(pdev, match->data, regmap);
|
return qcom_cc_really_probe(pdev, match->data, regmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmcc_msm8960_remove(struct platform_device *pdev)
|
|
||||||
{
|
|
||||||
qcom_cc_remove(pdev);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct platform_driver mmcc_msm8960_driver = {
|
static struct platform_driver mmcc_msm8960_driver = {
|
||||||
.probe = mmcc_msm8960_probe,
|
.probe = mmcc_msm8960_probe,
|
||||||
.remove = mmcc_msm8960_remove,
|
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mmcc-msm8960",
|
.name = "mmcc-msm8960",
|
||||||
.of_match_table = mmcc_msm8960_match_table,
|
.of_match_table = mmcc_msm8960_match_table,
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "clk-rcg.h"
|
#include "clk-rcg.h"
|
||||||
#include "clk-branch.h"
|
#include "clk-branch.h"
|
||||||
#include "reset.h"
|
#include "reset.h"
|
||||||
|
#include "gdsc.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
P_XO,
|
P_XO,
|
||||||
|
@ -522,17 +523,11 @@ static struct clk_rcg2 jpeg2_clk_src = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct freq_tbl pixel_freq_tbl[] = {
|
|
||||||
{ .src = P_DSI0PLL },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct clk_rcg2 pclk0_clk_src = {
|
static struct clk_rcg2 pclk0_clk_src = {
|
||||||
.cmd_rcgr = 0x2000,
|
.cmd_rcgr = 0x2000,
|
||||||
.mnd_width = 8,
|
.mnd_width = 8,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = pixel_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "pclk0_clk_src",
|
.name = "pclk0_clk_src",
|
||||||
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
||||||
|
@ -547,7 +542,6 @@ static struct clk_rcg2 pclk1_clk_src = {
|
||||||
.mnd_width = 8,
|
.mnd_width = 8,
|
||||||
.hid_width = 5,
|
.hid_width = 5,
|
||||||
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
|
||||||
.freq_tbl = pixel_freq_tbl,
|
|
||||||
.clkr.hw.init = &(struct clk_init_data){
|
.clkr.hw.init = &(struct clk_init_data){
|
||||||
.name = "pclk1_clk_src",
|
.name = "pclk1_clk_src",
|
||||||
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
|
||||||
|
@ -785,7 +779,7 @@ static struct clk_rcg2 byte0_clk_src = {
|
||||||
.name = "byte0_clk_src",
|
.name = "byte0_clk_src",
|
||||||
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
||||||
.num_parents = 6,
|
.num_parents = 6,
|
||||||
.ops = &clk_byte_ops,
|
.ops = &clk_byte2_ops,
|
||||||
.flags = CLK_SET_RATE_PARENT,
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -799,7 +793,7 @@ static struct clk_rcg2 byte1_clk_src = {
|
||||||
.name = "byte1_clk_src",
|
.name = "byte1_clk_src",
|
||||||
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
.parent_names = mmcc_xo_dsibyte_hdmi_edp_gpll0,
|
||||||
.num_parents = 6,
|
.num_parents = 6,
|
||||||
.ops = &clk_byte_ops,
|
.ops = &clk_byte2_ops,
|
||||||
.flags = CLK_SET_RATE_PARENT,
|
.flags = CLK_SET_RATE_PARENT,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -2349,6 +2343,66 @@ static struct pll_config mmpll3_config = {
|
||||||
.aux_output_mask = BIT(1),
|
.aux_output_mask = BIT(1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc venus0_gdsc = {
|
||||||
|
.gdscr = 0x1024,
|
||||||
|
.cxcs = (unsigned int []){ 0x1028 },
|
||||||
|
.cxc_count = 1,
|
||||||
|
.resets = (unsigned int []){ VENUS0_RESET },
|
||||||
|
.reset_count = 1,
|
||||||
|
.pd = {
|
||||||
|
.name = "venus0",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc mdss_gdsc = {
|
||||||
|
.gdscr = 0x2304,
|
||||||
|
.cxcs = (unsigned int []){ 0x231c, 0x2320 },
|
||||||
|
.cxc_count = 2,
|
||||||
|
.pd = {
|
||||||
|
.name = "mdss",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_RET_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc camss_jpeg_gdsc = {
|
||||||
|
.gdscr = 0x35a4,
|
||||||
|
.cxcs = (unsigned int []){ 0x35a8, 0x35ac, 0x35b0 },
|
||||||
|
.cxc_count = 3,
|
||||||
|
.pd = {
|
||||||
|
.name = "camss_jpeg",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc camss_vfe_gdsc = {
|
||||||
|
.gdscr = 0x36a4,
|
||||||
|
.cxcs = (unsigned int []){ 0x36a8, 0x36ac, 0x3704, 0x3714, 0x36b0 },
|
||||||
|
.cxc_count = 5,
|
||||||
|
.pd = {
|
||||||
|
.name = "camss_vfe",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc oxili_gdsc = {
|
||||||
|
.gdscr = 0x4024,
|
||||||
|
.cxcs = (unsigned int []){ 0x4028 },
|
||||||
|
.cxc_count = 1,
|
||||||
|
.pd = {
|
||||||
|
.name = "oxili",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gdsc oxilicx_gdsc = {
|
||||||
|
.gdscr = 0x4034,
|
||||||
|
.pd = {
|
||||||
|
.name = "oxilicx",
|
||||||
|
},
|
||||||
|
.pwrsts = PWRSTS_OFF_ON,
|
||||||
|
};
|
||||||
|
|
||||||
static struct clk_regmap *mmcc_msm8974_clocks[] = {
|
static struct clk_regmap *mmcc_msm8974_clocks[] = {
|
||||||
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
|
[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.clkr,
|
||||||
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
|
[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.clkr,
|
||||||
|
@ -2525,6 +2579,15 @@ static const struct qcom_reset_map mmcc_msm8974_resets[] = {
|
||||||
[OCMEMNOC_RESET] = { 0x50b0 },
|
[OCMEMNOC_RESET] = { 0x50b0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static struct gdsc *mmcc_msm8974_gdscs[] = {
|
||||||
|
[VENUS0_GDSC] = &venus0_gdsc,
|
||||||
|
[MDSS_GDSC] = &mdss_gdsc,
|
||||||
|
[CAMSS_JPEG_GDSC] = &camss_jpeg_gdsc,
|
||||||
|
[CAMSS_VFE_GDSC] = &camss_vfe_gdsc,
|
||||||
|
[OXILI_GDSC] = &oxili_gdsc,
|
||||||
|
[OXILICX_GDSC] = &oxilicx_gdsc,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct regmap_config mmcc_msm8974_regmap_config = {
|
static const struct regmap_config mmcc_msm8974_regmap_config = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
|
@ -2539,6 +2602,8 @@ static const struct qcom_cc_desc mmcc_msm8974_desc = {
|
||||||
.num_clks = ARRAY_SIZE(mmcc_msm8974_clocks),
|
.num_clks = ARRAY_SIZE(mmcc_msm8974_clocks),
|
||||||
.resets = mmcc_msm8974_resets,
|
.resets = mmcc_msm8974_resets,
|
||||||
.num_resets = ARRAY_SIZE(mmcc_msm8974_resets),
|
.num_resets = ARRAY_SIZE(mmcc_msm8974_resets),
|
||||||
|
.gdscs = mmcc_msm8974_gdscs,
|
||||||
|
.num_gdscs = ARRAY_SIZE(mmcc_msm8974_gdscs),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id mmcc_msm8974_match_table[] = {
|
static const struct of_device_id mmcc_msm8974_match_table[] = {
|
||||||
|
@ -2550,6 +2615,7 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
|
||||||
static int mmcc_msm8974_probe(struct platform_device *pdev)
|
static int mmcc_msm8974_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
|
int ret;
|
||||||
|
|
||||||
regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
|
regmap = qcom_cc_map(pdev, &mmcc_msm8974_desc);
|
||||||
if (IS_ERR(regmap))
|
if (IS_ERR(regmap))
|
||||||
|
@ -2558,12 +2624,16 @@ static int mmcc_msm8974_probe(struct platform_device *pdev)
|
||||||
clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
|
clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
|
||||||
clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
|
clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
|
||||||
|
|
||||||
return qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
|
ret = qcom_cc_really_probe(pdev, &mmcc_msm8974_desc, regmap);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return pm_genpd_add_subdomain(&oxili_gdsc.pd, &oxilicx_gdsc.pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mmcc_msm8974_remove(struct platform_device *pdev)
|
static int mmcc_msm8974_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
qcom_cc_remove(pdev);
|
pm_genpd_remove_subdomain(&oxili_gdsc.pd, &oxilicx_gdsc.pd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,8 @@ static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
|
||||||
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
|
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
|
||||||
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
|
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
|
||||||
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
|
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
|
||||||
|
#define ROCKCHIP_MMC_INIT_STATE_RESET 0x1
|
||||||
|
#define ROCKCHIP_MMC_INIT_STATE_SHIFT 1
|
||||||
|
|
||||||
#define PSECS_PER_SEC 1000000000000LL
|
#define PSECS_PER_SEC 1000000000000LL
|
||||||
|
|
||||||
|
@ -159,6 +161,15 @@ struct clk *rockchip_clk_register_mmc(const char *name,
|
||||||
mmc_clock->reg = reg;
|
mmc_clock->reg = reg;
|
||||||
mmc_clock->shift = shift;
|
mmc_clock->shift = shift;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Assert init_state to soft reset the CLKGEN
|
||||||
|
* for mmc tuning phase and degree
|
||||||
|
*/
|
||||||
|
if (mmc_clock->shift == ROCKCHIP_MMC_INIT_STATE_SHIFT)
|
||||||
|
writel(HIWORD_UPDATE(ROCKCHIP_MMC_INIT_STATE_RESET,
|
||||||
|
ROCKCHIP_MMC_INIT_STATE_RESET,
|
||||||
|
mmc_clock->shift), mmc_clock->reg);
|
||||||
|
|
||||||
clk = clk_register(NULL, &mmc_clock->hw);
|
clk = clk_register(NULL, &mmc_clock->hw);
|
||||||
if (IS_ERR(clk))
|
if (IS_ERR(clk))
|
||||||
goto err_free;
|
goto err_free;
|
||||||
|
|
|
@ -126,11 +126,32 @@ static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll)
|
||||||
#define RK3066_PLLCON3_PWRDOWN (1 << 1)
|
#define RK3066_PLLCON3_PWRDOWN (1 << 1)
|
||||||
#define RK3066_PLLCON3_BYPASS (1 << 0)
|
#define RK3066_PLLCON3_BYPASS (1 << 0)
|
||||||
|
|
||||||
|
static void rockchip_rk3066_pll_get_params(struct rockchip_clk_pll *pll,
|
||||||
|
struct rockchip_pll_rate_table *rate)
|
||||||
|
{
|
||||||
|
u32 pllcon;
|
||||||
|
|
||||||
|
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
|
||||||
|
rate->nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT)
|
||||||
|
& RK3066_PLLCON0_NR_MASK) + 1;
|
||||||
|
rate->no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT)
|
||||||
|
& RK3066_PLLCON0_OD_MASK) + 1;
|
||||||
|
|
||||||
|
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
|
||||||
|
rate->nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT)
|
||||||
|
& RK3066_PLLCON1_NF_MASK) + 1;
|
||||||
|
|
||||||
|
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
|
||||||
|
rate->nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT)
|
||||||
|
& RK3066_PLLCON2_NB_MASK) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
|
static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
|
||||||
unsigned long prate)
|
unsigned long prate)
|
||||||
{
|
{
|
||||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||||
u64 nf, nr, no, rate64 = prate;
|
struct rockchip_pll_rate_table cur;
|
||||||
|
u64 rate64 = prate;
|
||||||
u32 pllcon;
|
u32 pllcon;
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
|
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3));
|
||||||
|
@ -140,53 +161,31 @@ static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw,
|
||||||
return prate;
|
return prate;
|
||||||
}
|
}
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
|
rockchip_rk3066_pll_get_params(pll, &cur);
|
||||||
nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK;
|
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
|
rate64 *= cur.nf;
|
||||||
nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK;
|
do_div(rate64, cur.nr);
|
||||||
no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK;
|
do_div(rate64, cur.no);
|
||||||
|
|
||||||
rate64 *= (nf + 1);
|
|
||||||
do_div(rate64, nr + 1);
|
|
||||||
do_div(rate64, no + 1);
|
|
||||||
|
|
||||||
return (unsigned long)rate64;
|
return (unsigned long)rate64;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
|
static int rockchip_rk3066_pll_set_params(struct rockchip_clk_pll *pll,
|
||||||
unsigned long prate)
|
const struct rockchip_pll_rate_table *rate)
|
||||||
{
|
{
|
||||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
|
||||||
const struct rockchip_pll_rate_table *rate;
|
|
||||||
unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate);
|
|
||||||
struct regmap *grf = rockchip_clk_get_grf();
|
|
||||||
struct clk_mux *pll_mux = &pll->pll_mux;
|
|
||||||
const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
|
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;
|
||||||
int rate_change_remuxed = 0;
|
int rate_change_remuxed = 0;
|
||||||
int cur_parent;
|
int cur_parent;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
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_hw_get_name(hw), 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_hw_get_name(hw));
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
|
pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n",
|
||||||
__func__, rate->rate, rate->nr, rate->no, rate->nf);
|
__func__, rate->rate, rate->nr, rate->no, rate->nf);
|
||||||
|
|
||||||
|
rockchip_rk3066_pll_get_params(pll, &cur);
|
||||||
|
cur.rate = 0;
|
||||||
|
|
||||||
cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
|
cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
|
||||||
if (cur_parent == PLL_MODE_NORM) {
|
if (cur_parent == PLL_MODE_NORM) {
|
||||||
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
|
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
|
||||||
|
@ -219,9 +218,9 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
|
||||||
/* wait for the pll to lock */
|
/* wait for the pll to lock */
|
||||||
ret = rockchip_pll_wait_lock(pll);
|
ret = rockchip_pll_wait_lock(pll);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
|
pr_warn("%s: pll update unsucessful, trying to restore old params\n",
|
||||||
__func__, old_rate);
|
__func__);
|
||||||
rockchip_rk3066_pll_set_rate(hw, old_rate, prate);
|
rockchip_rk3066_pll_set_params(pll, &cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rate_change_remuxed)
|
if (rate_change_remuxed)
|
||||||
|
@ -230,6 +229,34 @@ static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int rockchip_rk3066_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_rk3066_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_hw_get_name(hw), 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_hw_get_name(hw));
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rockchip_rk3066_pll_set_params(pll, rate);
|
||||||
|
}
|
||||||
|
|
||||||
static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
|
static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||||
|
@ -261,9 +288,8 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
|
||||||
const struct rockchip_pll_rate_table *rate;
|
const struct rockchip_pll_rate_table *rate;
|
||||||
unsigned int nf, nr, no, nb;
|
struct rockchip_pll_rate_table cur;
|
||||||
unsigned long drate;
|
unsigned long drate;
|
||||||
u32 pllcon;
|
|
||||||
|
|
||||||
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
|
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
|
||||||
return;
|
return;
|
||||||
|
@ -275,34 +301,21 @@ static void rockchip_rk3066_pll_init(struct clk_hw *hw)
|
||||||
if (!rate)
|
if (!rate)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0));
|
rockchip_rk3066_pll_get_params(pll, &cur);
|
||||||
nr = ((pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK) + 1;
|
|
||||||
no = ((pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK) + 1;
|
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1));
|
|
||||||
nf = ((pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK) + 1;
|
|
||||||
|
|
||||||
pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(2));
|
|
||||||
nb = ((pllcon >> RK3066_PLLCON2_NB_SHIFT) & RK3066_PLLCON2_NB_MASK) + 1;
|
|
||||||
|
|
||||||
pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
|
pr_debug("%s: pll %s@%lu: nr (%d:%d); no (%d:%d); nf(%d:%d), nb(%d:%d)\n",
|
||||||
__func__, clk_hw_get_name(hw), drate, rate->nr, nr,
|
__func__, clk_hw_get_name(hw), drate, rate->nr, cur.nr,
|
||||||
rate->no, no, rate->nf, nf, rate->nb, nb);
|
rate->no, cur.no, rate->nf, cur.nf, rate->nb, cur.nb);
|
||||||
if (rate->nr != nr || rate->no != no || rate->nf != nf
|
if (rate->nr != cur.nr || rate->no != cur.no || rate->nf != cur.nf
|
||||||
|| rate->nb != nb) {
|
|| rate->nb != cur.nb) {
|
||||||
struct clk_hw *parent = clk_hw_get_parent(hw);
|
struct regmap *grf = rockchip_clk_get_grf();
|
||||||
unsigned long prate;
|
|
||||||
|
|
||||||
if (!parent) {
|
if (IS_ERR(grf))
|
||||||
pr_warn("%s: parent of %s not available\n",
|
|
||||||
__func__, clk_hw_get_name(hw));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
|
pr_debug("%s: pll %s: rate params do not match rate table, adjusting\n",
|
||||||
__func__, clk_hw_get_name(hw));
|
__func__, clk_hw_get_name(hw));
|
||||||
prate = clk_hw_get_rate(parent);
|
rockchip_rk3066_pll_set_params(pll, rate);
|
||||||
rockchip_rk3066_pll_set_rate(hw, drate, prate);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -135,9 +135,11 @@ static struct clk *rockchip_clk_register_frac_branch(const char *name,
|
||||||
div->flags = div_flags;
|
div->flags = div_flags;
|
||||||
div->reg = base + muxdiv_offset;
|
div->reg = base + muxdiv_offset;
|
||||||
div->mshift = 16;
|
div->mshift = 16;
|
||||||
div->mmask = 0xffff0000;
|
div->mwidth = 16;
|
||||||
|
div->mmask = GENMASK(div->mwidth - 1, 0) << div->mshift;
|
||||||
div->nshift = 0;
|
div->nshift = 0;
|
||||||
div->nmask = 0xffff;
|
div->nwidth = 16;
|
||||||
|
div->nmask = GENMASK(div->nwidth - 1, 0) << div->nshift;
|
||||||
div->lock = lock;
|
div->lock = lock;
|
||||||
div_ops = &clk_fractional_divider_ops;
|
div_ops = &clk_fractional_divider_ops;
|
||||||
|
|
||||||
|
|
|
@ -32,39 +32,41 @@
|
||||||
#define DIV_TOPC0 0x0600
|
#define DIV_TOPC0 0x0600
|
||||||
#define DIV_TOPC1 0x0604
|
#define DIV_TOPC1 0x0604
|
||||||
#define DIV_TOPC3 0x060C
|
#define DIV_TOPC3 0x060C
|
||||||
|
#define ENABLE_ACLK_TOPC0 0x0800
|
||||||
#define ENABLE_ACLK_TOPC1 0x0804
|
#define ENABLE_ACLK_TOPC1 0x0804
|
||||||
|
#define ENABLE_SCLK_TOPC1 0x0A04
|
||||||
|
|
||||||
static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
|
static struct samsung_fixed_factor_clock topc_fixed_factor_clks[] __initdata = {
|
||||||
FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_bus0_pll_ctrl", 1, 2, 0),
|
FFACTOR(0, "ffac_topc_bus0_pll_div2", "mout_topc_bus0_pll", 1, 2, 0),
|
||||||
FFACTOR(0, "ffac_topc_bus0_pll_div4",
|
FFACTOR(0, "ffac_topc_bus0_pll_div4",
|
||||||
"ffac_topc_bus0_pll_div2", 1, 2, 0),
|
"ffac_topc_bus0_pll_div2", 1, 2, 0),
|
||||||
FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_bus1_pll_ctrl", 1, 2, 0),
|
FFACTOR(0, "ffac_topc_bus1_pll_div2", "mout_topc_bus1_pll", 1, 2, 0),
|
||||||
FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_cc_pll_ctrl", 1, 2, 0),
|
FFACTOR(0, "ffac_topc_cc_pll_div2", "mout_topc_cc_pll", 1, 2, 0),
|
||||||
FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_mfc_pll_ctrl", 1, 2, 0),
|
FFACTOR(0, "ffac_topc_mfc_pll_div2", "mout_topc_mfc_pll", 1, 2, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_TOPC */
|
/* List of parent clocks for Muxes in CMU_TOPC */
|
||||||
PNAME(mout_aud_pll_ctrl_p) = { "fin_pll", "fout_aud_pll" };
|
PNAME(mout_topc_aud_pll_ctrl_p) = { "fin_pll", "fout_aud_pll" };
|
||||||
PNAME(mout_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" };
|
PNAME(mout_topc_bus0_pll_ctrl_p) = { "fin_pll", "fout_bus0_pll" };
|
||||||
PNAME(mout_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" };
|
PNAME(mout_topc_bus1_pll_ctrl_p) = { "fin_pll", "fout_bus1_pll" };
|
||||||
PNAME(mout_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" };
|
PNAME(mout_topc_cc_pll_ctrl_p) = { "fin_pll", "fout_cc_pll" };
|
||||||
PNAME(mout_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" };
|
PNAME(mout_topc_mfc_pll_ctrl_p) = { "fin_pll", "fout_mfc_pll" };
|
||||||
|
|
||||||
PNAME(mout_topc_group2) = { "mout_sclk_bus0_pll_cmuc",
|
PNAME(mout_topc_group2) = { "mout_topc_bus0_pll_half",
|
||||||
"mout_sclk_bus1_pll_cmuc", "mout_sclk_cc_pll_cmuc",
|
"mout_topc_bus1_pll_half", "mout_topc_cc_pll_half",
|
||||||
"mout_sclk_mfc_pll_cmuc" };
|
"mout_topc_mfc_pll_half" };
|
||||||
|
|
||||||
PNAME(mout_sclk_bus0_pll_cmuc_p) = { "mout_bus0_pll_ctrl",
|
PNAME(mout_topc_bus0_pll_half_p) = { "mout_topc_bus0_pll",
|
||||||
"ffac_topc_bus0_pll_div2", "ffac_topc_bus0_pll_div4"};
|
"ffac_topc_bus0_pll_div2", "ffac_topc_bus0_pll_div4"};
|
||||||
PNAME(mout_sclk_bus1_pll_cmuc_p) = { "mout_bus1_pll_ctrl",
|
PNAME(mout_topc_bus1_pll_half_p) = { "mout_topc_bus1_pll",
|
||||||
"ffac_topc_bus1_pll_div2"};
|
"ffac_topc_bus1_pll_div2"};
|
||||||
PNAME(mout_sclk_cc_pll_cmuc_p) = { "mout_cc_pll_ctrl",
|
PNAME(mout_topc_cc_pll_half_p) = { "mout_topc_cc_pll",
|
||||||
"ffac_topc_cc_pll_div2"};
|
"ffac_topc_cc_pll_div2"};
|
||||||
PNAME(mout_sclk_mfc_pll_cmuc_p) = { "mout_mfc_pll_ctrl",
|
PNAME(mout_topc_mfc_pll_half_p) = { "mout_topc_mfc_pll",
|
||||||
"ffac_topc_mfc_pll_div2"};
|
"ffac_topc_mfc_pll_div2"};
|
||||||
|
|
||||||
|
|
||||||
PNAME(mout_sclk_bus0_pll_out_p) = {"mout_bus0_pll_ctrl",
|
PNAME(mout_topc_bus0_pll_out_p) = {"mout_topc_bus0_pll",
|
||||||
"ffac_topc_bus0_pll_div2"};
|
"ffac_topc_bus0_pll_div2"};
|
||||||
|
|
||||||
static unsigned long topc_clk_regs[] __initdata = {
|
static unsigned long topc_clk_regs[] __initdata = {
|
||||||
|
@ -88,23 +90,27 @@ static unsigned long topc_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock topc_mux_clks[] __initdata = {
|
static struct samsung_mux_clock topc_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_bus0_pll_ctrl", mout_bus0_pll_ctrl_p, MUX_SEL_TOPC0, 0, 1),
|
MUX(0, "mout_topc_bus0_pll", mout_topc_bus0_pll_ctrl_p,
|
||||||
MUX(0, "mout_bus1_pll_ctrl", mout_bus1_pll_ctrl_p, MUX_SEL_TOPC0, 4, 1),
|
MUX_SEL_TOPC0, 0, 1),
|
||||||
MUX(0, "mout_cc_pll_ctrl", mout_cc_pll_ctrl_p, MUX_SEL_TOPC0, 8, 1),
|
MUX(0, "mout_topc_bus1_pll", mout_topc_bus1_pll_ctrl_p,
|
||||||
MUX(0, "mout_mfc_pll_ctrl", mout_mfc_pll_ctrl_p, MUX_SEL_TOPC0, 12, 1),
|
MUX_SEL_TOPC0, 4, 1),
|
||||||
|
MUX(0, "mout_topc_cc_pll", mout_topc_cc_pll_ctrl_p,
|
||||||
MUX(0, "mout_sclk_bus0_pll_cmuc", mout_sclk_bus0_pll_cmuc_p,
|
MUX_SEL_TOPC0, 8, 1),
|
||||||
|
MUX(0, "mout_topc_mfc_pll", mout_topc_mfc_pll_ctrl_p,
|
||||||
|
MUX_SEL_TOPC0, 12, 1),
|
||||||
|
MUX(0, "mout_topc_bus0_pll_half", mout_topc_bus0_pll_half_p,
|
||||||
MUX_SEL_TOPC0, 16, 2),
|
MUX_SEL_TOPC0, 16, 2),
|
||||||
MUX(0, "mout_sclk_bus1_pll_cmuc", mout_sclk_bus1_pll_cmuc_p,
|
MUX(0, "mout_topc_bus1_pll_half", mout_topc_bus1_pll_half_p,
|
||||||
MUX_SEL_TOPC0, 20, 1),
|
MUX_SEL_TOPC0, 20, 1),
|
||||||
MUX(0, "mout_sclk_cc_pll_cmuc", mout_sclk_cc_pll_cmuc_p,
|
MUX(0, "mout_topc_cc_pll_half", mout_topc_cc_pll_half_p,
|
||||||
MUX_SEL_TOPC0, 24, 1),
|
MUX_SEL_TOPC0, 24, 1),
|
||||||
MUX(0, "mout_sclk_mfc_pll_cmuc", mout_sclk_mfc_pll_cmuc_p,
|
MUX(0, "mout_topc_mfc_pll_half", mout_topc_mfc_pll_half_p,
|
||||||
MUX_SEL_TOPC0, 28, 1),
|
MUX_SEL_TOPC0, 28, 1),
|
||||||
|
|
||||||
MUX(0, "mout_sclk_bus0_pll_out", mout_sclk_bus0_pll_out_p,
|
MUX(0, "mout_topc_aud_pll", mout_topc_aud_pll_ctrl_p,
|
||||||
|
MUX_SEL_TOPC1, 0, 1),
|
||||||
|
MUX(0, "mout_topc_bus0_pll_out", mout_topc_bus0_pll_out_p,
|
||||||
MUX_SEL_TOPC1, 16, 1),
|
MUX_SEL_TOPC1, 16, 1),
|
||||||
MUX(0, "mout_aud_pll_ctrl", mout_aud_pll_ctrl_p, MUX_SEL_TOPC1, 0, 1),
|
|
||||||
|
|
||||||
MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2),
|
MUX(0, "mout_aclk_ccore_133", mout_topc_group2, MUX_SEL_TOPC2, 4, 2),
|
||||||
|
|
||||||
|
@ -121,16 +127,16 @@ static struct samsung_div_clock topc_div_clks[] __initdata = {
|
||||||
DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66",
|
DIV(DOUT_ACLK_PERIS, "dout_aclk_peris_66", "mout_aclk_peris_66",
|
||||||
DIV_TOPC1, 24, 4),
|
DIV_TOPC1, 24, 4),
|
||||||
|
|
||||||
DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_sclk_bus0_pll_out",
|
DIV(DOUT_SCLK_BUS0_PLL, "dout_sclk_bus0_pll", "mout_topc_bus0_pll_out",
|
||||||
DIV_TOPC3, 0, 3),
|
DIV_TOPC3, 0, 4),
|
||||||
DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_bus1_pll_ctrl",
|
DIV(DOUT_SCLK_BUS1_PLL, "dout_sclk_bus1_pll", "mout_topc_bus1_pll",
|
||||||
DIV_TOPC3, 8, 3),
|
DIV_TOPC3, 8, 4),
|
||||||
DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_cc_pll_ctrl",
|
DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_topc_cc_pll",
|
||||||
DIV_TOPC3, 12, 3),
|
DIV_TOPC3, 12, 4),
|
||||||
DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_mfc_pll_ctrl",
|
DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_topc_mfc_pll",
|
||||||
DIV_TOPC3, 16, 3),
|
DIV_TOPC3, 16, 4),
|
||||||
DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_aud_pll_ctrl",
|
DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_topc_aud_pll",
|
||||||
DIV_TOPC3, 28, 3),
|
DIV_TOPC3, 28, 4),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
|
static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
|
||||||
|
@ -139,8 +145,33 @@ static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock topc_gate_clks[] __initdata = {
|
static struct samsung_gate_clock topc_gate_clks[] __initdata = {
|
||||||
|
GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133",
|
||||||
|
ENABLE_ACLK_TOPC0, 4, 0, 0),
|
||||||
|
|
||||||
GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532",
|
GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532",
|
||||||
ENABLE_ACLK_TOPC1, 20, 0, 0),
|
ENABLE_ACLK_TOPC1, 20, 0, 0),
|
||||||
|
|
||||||
|
GATE(ACLK_PERIS_66, "aclk_peris_66", "dout_aclk_peris_66",
|
||||||
|
ENABLE_ACLK_TOPC1, 24, 0, 0),
|
||||||
|
|
||||||
|
GATE(SCLK_AUD_PLL, "sclk_aud_pll", "dout_sclk_aud_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 20, 0, 0),
|
||||||
|
GATE(SCLK_MFC_PLL_B, "sclk_mfc_pll_b", "dout_sclk_mfc_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 17, 0, 0),
|
||||||
|
GATE(SCLK_MFC_PLL_A, "sclk_mfc_pll_a", "dout_sclk_mfc_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 16, 0, 0),
|
||||||
|
GATE(SCLK_BUS1_PLL_B, "sclk_bus1_pll_b", "dout_sclk_bus1_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 13, 0, 0),
|
||||||
|
GATE(SCLK_BUS1_PLL_A, "sclk_bus1_pll_a", "dout_sclk_bus1_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 12, 0, 0),
|
||||||
|
GATE(SCLK_BUS0_PLL_B, "sclk_bus0_pll_b", "dout_sclk_bus0_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 5, 0, 0),
|
||||||
|
GATE(SCLK_BUS0_PLL_A, "sclk_bus0_pll_a", "dout_sclk_bus0_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 4, 0, 0),
|
||||||
|
GATE(SCLK_CC_PLL_B, "sclk_cc_pll_b", "dout_sclk_cc_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 1, 0, 0),
|
||||||
|
GATE(SCLK_CC_PLL_A, "sclk_cc_pll_a", "dout_sclk_cc_pll",
|
||||||
|
ENABLE_SCLK_TOPC1, 0, 0, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_pll_clock topc_pll_clks[] __initdata = {
|
static struct samsung_pll_clock topc_pll_clks[] __initdata = {
|
||||||
|
@ -193,36 +224,37 @@ CLK_OF_DECLARE(exynos7_clk_topc, "samsung,exynos7-clock-topc",
|
||||||
#define DIV_TOP0_PERIC1 0x0634
|
#define DIV_TOP0_PERIC1 0x0634
|
||||||
#define DIV_TOP0_PERIC2 0x0638
|
#define DIV_TOP0_PERIC2 0x0638
|
||||||
#define DIV_TOP0_PERIC3 0x063C
|
#define DIV_TOP0_PERIC3 0x063C
|
||||||
|
#define ENABLE_ACLK_TOP03 0x080C
|
||||||
#define ENABLE_SCLK_TOP0_PERIC0 0x0A30
|
#define ENABLE_SCLK_TOP0_PERIC0 0x0A30
|
||||||
#define ENABLE_SCLK_TOP0_PERIC1 0x0A34
|
#define ENABLE_SCLK_TOP0_PERIC1 0x0A34
|
||||||
#define ENABLE_SCLK_TOP0_PERIC2 0x0A38
|
#define ENABLE_SCLK_TOP0_PERIC2 0x0A38
|
||||||
#define ENABLE_SCLK_TOP0_PERIC3 0x0A3C
|
#define ENABLE_SCLK_TOP0_PERIC3 0x0A3C
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_TOP0 */
|
/* List of parent clocks for Muxes in CMU_TOP0 */
|
||||||
PNAME(mout_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" };
|
PNAME(mout_top0_bus0_pll_user_p) = { "fin_pll", "sclk_bus0_pll_a" };
|
||||||
PNAME(mout_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll" };
|
PNAME(mout_top0_bus1_pll_user_p) = { "fin_pll", "sclk_bus1_pll_a" };
|
||||||
PNAME(mout_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll" };
|
PNAME(mout_top0_cc_pll_user_p) = { "fin_pll", "sclk_cc_pll_a" };
|
||||||
PNAME(mout_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll" };
|
PNAME(mout_top0_mfc_pll_user_p) = { "fin_pll", "sclk_mfc_pll_a" };
|
||||||
PNAME(mout_aud_pll_p) = { "fin_pll", "dout_sclk_aud_pll" };
|
PNAME(mout_top0_aud_pll_user_p) = { "fin_pll", "sclk_aud_pll" };
|
||||||
|
|
||||||
PNAME(mout_top0_half_bus0_pll_p) = {"mout_top0_bus0_pll",
|
PNAME(mout_top0_bus0_pll_half_p) = {"mout_top0_bus0_pll_user",
|
||||||
"ffac_top0_bus0_pll_div2"};
|
"ffac_top0_bus0_pll_div2"};
|
||||||
PNAME(mout_top0_half_bus1_pll_p) = {"mout_top0_bus1_pll",
|
PNAME(mout_top0_bus1_pll_half_p) = {"mout_top0_bus1_pll_user",
|
||||||
"ffac_top0_bus1_pll_div2"};
|
"ffac_top0_bus1_pll_div2"};
|
||||||
PNAME(mout_top0_half_cc_pll_p) = {"mout_top0_cc_pll",
|
PNAME(mout_top0_cc_pll_half_p) = {"mout_top0_cc_pll_user",
|
||||||
"ffac_top0_cc_pll_div2"};
|
"ffac_top0_cc_pll_div2"};
|
||||||
PNAME(mout_top0_half_mfc_pll_p) = {"mout_top0_mfc_pll",
|
PNAME(mout_top0_mfc_pll_half_p) = {"mout_top0_mfc_pll_user",
|
||||||
"ffac_top0_mfc_pll_div2"};
|
"ffac_top0_mfc_pll_div2"};
|
||||||
|
|
||||||
PNAME(mout_top0_group1) = {"mout_top0_half_bus0_pll",
|
PNAME(mout_top0_group1) = {"mout_top0_bus0_pll_half",
|
||||||
"mout_top0_half_bus1_pll", "mout_top0_half_cc_pll",
|
"mout_top0_bus1_pll_half", "mout_top0_cc_pll_half",
|
||||||
"mout_top0_half_mfc_pll"};
|
"mout_top0_mfc_pll_half"};
|
||||||
PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
|
PNAME(mout_top0_group3) = {"ioclk_audiocdclk0",
|
||||||
"ioclk_audiocdclk1", "ioclk_spdif_extclk",
|
"ioclk_audiocdclk1", "ioclk_spdif_extclk",
|
||||||
"mout_top0_aud_pll", "mout_top0_half_bus0_pll",
|
"mout_top0_aud_pll_user", "mout_top0_bus0_pll_half",
|
||||||
"mout_top0_half_bus1_pll"};
|
"mout_top0_bus1_pll_half"};
|
||||||
PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll",
|
PNAME(mout_top0_group4) = {"ioclk_audiocdclk1", "mout_top0_aud_pll_user",
|
||||||
"mout_top0_half_bus0_pll", "mout_top0_half_bus1_pll"};
|
"mout_top0_bus0_pll_half", "mout_top0_bus1_pll_half"};
|
||||||
|
|
||||||
static unsigned long top0_clk_regs[] __initdata = {
|
static unsigned long top0_clk_regs[] __initdata = {
|
||||||
MUX_SEL_TOP00,
|
MUX_SEL_TOP00,
|
||||||
|
@ -244,19 +276,24 @@ static unsigned long top0_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock top0_mux_clks[] __initdata = {
|
static struct samsung_mux_clock top0_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_top0_aud_pll", mout_aud_pll_p, MUX_SEL_TOP00, 0, 1),
|
MUX(0, "mout_top0_aud_pll_user", mout_top0_aud_pll_user_p,
|
||||||
MUX(0, "mout_top0_mfc_pll", mout_mfc_pll_p, MUX_SEL_TOP00, 4, 1),
|
MUX_SEL_TOP00, 0, 1),
|
||||||
MUX(0, "mout_top0_cc_pll", mout_cc_pll_p, MUX_SEL_TOP00, 8, 1),
|
MUX(0, "mout_top0_mfc_pll_user", mout_top0_mfc_pll_user_p,
|
||||||
MUX(0, "mout_top0_bus1_pll", mout_bus1_pll_p, MUX_SEL_TOP00, 12, 1),
|
MUX_SEL_TOP00, 4, 1),
|
||||||
MUX(0, "mout_top0_bus0_pll", mout_bus0_pll_p, MUX_SEL_TOP00, 16, 1),
|
MUX(0, "mout_top0_cc_pll_user", mout_top0_cc_pll_user_p,
|
||||||
|
MUX_SEL_TOP00, 8, 1),
|
||||||
|
MUX(0, "mout_top0_bus1_pll_user", mout_top0_bus1_pll_user_p,
|
||||||
|
MUX_SEL_TOP00, 12, 1),
|
||||||
|
MUX(0, "mout_top0_bus0_pll_user", mout_top0_bus0_pll_user_p,
|
||||||
|
MUX_SEL_TOP00, 16, 1),
|
||||||
|
|
||||||
MUX(0, "mout_top0_half_mfc_pll", mout_top0_half_mfc_pll_p,
|
MUX(0, "mout_top0_mfc_pll_half", mout_top0_mfc_pll_half_p,
|
||||||
MUX_SEL_TOP01, 4, 1),
|
MUX_SEL_TOP01, 4, 1),
|
||||||
MUX(0, "mout_top0_half_cc_pll", mout_top0_half_cc_pll_p,
|
MUX(0, "mout_top0_cc_pll_half", mout_top0_cc_pll_half_p,
|
||||||
MUX_SEL_TOP01, 8, 1),
|
MUX_SEL_TOP01, 8, 1),
|
||||||
MUX(0, "mout_top0_half_bus1_pll", mout_top0_half_bus1_pll_p,
|
MUX(0, "mout_top0_bus1_pll_half", mout_top0_bus1_pll_half_p,
|
||||||
MUX_SEL_TOP01, 12, 1),
|
MUX_SEL_TOP01, 12, 1),
|
||||||
MUX(0, "mout_top0_half_bus0_pll", mout_top0_half_bus0_pll_p,
|
MUX(0, "mout_top0_bus0_pll_half", mout_top0_bus0_pll_half_p,
|
||||||
MUX_SEL_TOP01, 16, 1),
|
MUX_SEL_TOP01, 16, 1),
|
||||||
|
|
||||||
MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2),
|
MUX(0, "mout_aclk_peric1_66", mout_top0_group1, MUX_SEL_TOP03, 12, 2),
|
||||||
|
@ -302,6 +339,11 @@ static struct samsung_div_clock top0_div_clks[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock top0_gate_clks[] __initdata = {
|
static struct samsung_gate_clock top0_gate_clks[] __initdata = {
|
||||||
|
GATE(CLK_ACLK_PERIC0_66, "aclk_peric0_66", "dout_aclk_peric0_66",
|
||||||
|
ENABLE_ACLK_TOP03, 20, CLK_SET_RATE_PARENT, 0),
|
||||||
|
GATE(CLK_ACLK_PERIC1_66, "aclk_peric1_66", "dout_aclk_peric1_66",
|
||||||
|
ENABLE_ACLK_TOP03, 12, CLK_SET_RATE_PARENT, 0),
|
||||||
|
|
||||||
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif",
|
GATE(CLK_SCLK_SPDIF, "sclk_spdif", "dout_sclk_spdif",
|
||||||
ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
|
ENABLE_SCLK_TOP0_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
|
||||||
GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_sclk_pcm1",
|
GATE(CLK_SCLK_PCM1, "sclk_pcm1", "dout_sclk_pcm1",
|
||||||
|
@ -331,10 +373,12 @@ static struct samsung_gate_clock top0_gate_clks[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
|
static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = {
|
||||||
FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll", 1, 2, 0),
|
FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll_user",
|
||||||
FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll", 1, 2, 0),
|
1, 2, 0),
|
||||||
FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll", 1, 2, 0),
|
FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll_user",
|
||||||
FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll", 1, 2, 0),
|
1, 2, 0),
|
||||||
|
FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll_user", 1, 2, 0),
|
||||||
|
FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll_user", 1, 2, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_cmu_info top0_cmu_info __initdata = {
|
static struct samsung_cmu_info top0_cmu_info __initdata = {
|
||||||
|
@ -365,31 +409,34 @@ CLK_OF_DECLARE(exynos7_clk_top0, "samsung,exynos7-clock-top0",
|
||||||
#define MUX_SEL_TOP13 0x020C
|
#define MUX_SEL_TOP13 0x020C
|
||||||
#define MUX_SEL_TOP1_FSYS0 0x0224
|
#define MUX_SEL_TOP1_FSYS0 0x0224
|
||||||
#define MUX_SEL_TOP1_FSYS1 0x0228
|
#define MUX_SEL_TOP1_FSYS1 0x0228
|
||||||
|
#define MUX_SEL_TOP1_FSYS11 0x022C
|
||||||
#define DIV_TOP13 0x060C
|
#define DIV_TOP13 0x060C
|
||||||
#define DIV_TOP1_FSYS0 0x0624
|
#define DIV_TOP1_FSYS0 0x0624
|
||||||
#define DIV_TOP1_FSYS1 0x0628
|
#define DIV_TOP1_FSYS1 0x0628
|
||||||
|
#define DIV_TOP1_FSYS11 0x062C
|
||||||
#define ENABLE_ACLK_TOP13 0x080C
|
#define ENABLE_ACLK_TOP13 0x080C
|
||||||
#define ENABLE_SCLK_TOP1_FSYS0 0x0A24
|
#define ENABLE_SCLK_TOP1_FSYS0 0x0A24
|
||||||
#define ENABLE_SCLK_TOP1_FSYS1 0x0A28
|
#define ENABLE_SCLK_TOP1_FSYS1 0x0A28
|
||||||
|
#define ENABLE_SCLK_TOP1_FSYS11 0x0A2C
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_TOP1 */
|
/* List of parent clocks for Muxes in CMU_TOP1 */
|
||||||
PNAME(mout_top1_bus0_pll_p) = { "fin_pll", "dout_sclk_bus0_pll" };
|
PNAME(mout_top1_bus0_pll_user_p) = { "fin_pll", "sclk_bus0_pll_b" };
|
||||||
PNAME(mout_top1_bus1_pll_p) = { "fin_pll", "dout_sclk_bus1_pll_b" };
|
PNAME(mout_top1_bus1_pll_user_p) = { "fin_pll", "sclk_bus1_pll_b" };
|
||||||
PNAME(mout_top1_cc_pll_p) = { "fin_pll", "dout_sclk_cc_pll_b" };
|
PNAME(mout_top1_cc_pll_user_p) = { "fin_pll", "sclk_cc_pll_b" };
|
||||||
PNAME(mout_top1_mfc_pll_p) = { "fin_pll", "dout_sclk_mfc_pll_b" };
|
PNAME(mout_top1_mfc_pll_user_p) = { "fin_pll", "sclk_mfc_pll_b" };
|
||||||
|
|
||||||
PNAME(mout_top1_half_bus0_pll_p) = {"mout_top1_bus0_pll",
|
PNAME(mout_top1_bus0_pll_half_p) = {"mout_top1_bus0_pll_user",
|
||||||
"ffac_top1_bus0_pll_div2"};
|
"ffac_top1_bus0_pll_div2"};
|
||||||
PNAME(mout_top1_half_bus1_pll_p) = {"mout_top1_bus1_pll",
|
PNAME(mout_top1_bus1_pll_half_p) = {"mout_top1_bus1_pll_user",
|
||||||
"ffac_top1_bus1_pll_div2"};
|
"ffac_top1_bus1_pll_div2"};
|
||||||
PNAME(mout_top1_half_cc_pll_p) = {"mout_top1_cc_pll",
|
PNAME(mout_top1_cc_pll_half_p) = {"mout_top1_cc_pll_user",
|
||||||
"ffac_top1_cc_pll_div2"};
|
"ffac_top1_cc_pll_div2"};
|
||||||
PNAME(mout_top1_half_mfc_pll_p) = {"mout_top1_mfc_pll",
|
PNAME(mout_top1_mfc_pll_half_p) = {"mout_top1_mfc_pll_user",
|
||||||
"ffac_top1_mfc_pll_div2"};
|
"ffac_top1_mfc_pll_div2"};
|
||||||
|
|
||||||
PNAME(mout_top1_group1) = {"mout_top1_half_bus0_pll",
|
PNAME(mout_top1_group1) = {"mout_top1_bus0_pll_half",
|
||||||
"mout_top1_half_bus1_pll", "mout_top1_half_cc_pll",
|
"mout_top1_bus1_pll_half", "mout_top1_cc_pll_half",
|
||||||
"mout_top1_half_mfc_pll"};
|
"mout_top1_mfc_pll_half"};
|
||||||
|
|
||||||
static unsigned long top1_clk_regs[] __initdata = {
|
static unsigned long top1_clk_regs[] __initdata = {
|
||||||
MUX_SEL_TOP10,
|
MUX_SEL_TOP10,
|
||||||
|
@ -397,40 +444,54 @@ static unsigned long top1_clk_regs[] __initdata = {
|
||||||
MUX_SEL_TOP13,
|
MUX_SEL_TOP13,
|
||||||
MUX_SEL_TOP1_FSYS0,
|
MUX_SEL_TOP1_FSYS0,
|
||||||
MUX_SEL_TOP1_FSYS1,
|
MUX_SEL_TOP1_FSYS1,
|
||||||
|
MUX_SEL_TOP1_FSYS11,
|
||||||
DIV_TOP13,
|
DIV_TOP13,
|
||||||
DIV_TOP1_FSYS0,
|
DIV_TOP1_FSYS0,
|
||||||
DIV_TOP1_FSYS1,
|
DIV_TOP1_FSYS1,
|
||||||
|
DIV_TOP1_FSYS11,
|
||||||
ENABLE_ACLK_TOP13,
|
ENABLE_ACLK_TOP13,
|
||||||
ENABLE_SCLK_TOP1_FSYS0,
|
ENABLE_SCLK_TOP1_FSYS0,
|
||||||
ENABLE_SCLK_TOP1_FSYS1,
|
ENABLE_SCLK_TOP1_FSYS1,
|
||||||
|
ENABLE_SCLK_TOP1_FSYS11,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock top1_mux_clks[] __initdata = {
|
static struct samsung_mux_clock top1_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_top1_mfc_pll", mout_top1_mfc_pll_p, MUX_SEL_TOP10, 4, 1),
|
MUX(0, "mout_top1_mfc_pll_user", mout_top1_mfc_pll_user_p,
|
||||||
MUX(0, "mout_top1_cc_pll", mout_top1_cc_pll_p, MUX_SEL_TOP10, 8, 1),
|
MUX_SEL_TOP10, 4, 1),
|
||||||
MUX(0, "mout_top1_bus1_pll", mout_top1_bus1_pll_p,
|
MUX(0, "mout_top1_cc_pll_user", mout_top1_cc_pll_user_p,
|
||||||
|
MUX_SEL_TOP10, 8, 1),
|
||||||
|
MUX(0, "mout_top1_bus1_pll_user", mout_top1_bus1_pll_user_p,
|
||||||
MUX_SEL_TOP10, 12, 1),
|
MUX_SEL_TOP10, 12, 1),
|
||||||
MUX(0, "mout_top1_bus0_pll", mout_top1_bus0_pll_p,
|
MUX(0, "mout_top1_bus0_pll_user", mout_top1_bus0_pll_user_p,
|
||||||
MUX_SEL_TOP10, 16, 1),
|
MUX_SEL_TOP10, 16, 1),
|
||||||
|
|
||||||
MUX(0, "mout_top1_half_mfc_pll", mout_top1_half_mfc_pll_p,
|
MUX(0, "mout_top1_mfc_pll_half", mout_top1_mfc_pll_half_p,
|
||||||
MUX_SEL_TOP11, 4, 1),
|
MUX_SEL_TOP11, 4, 1),
|
||||||
MUX(0, "mout_top1_half_cc_pll", mout_top1_half_cc_pll_p,
|
MUX(0, "mout_top1_cc_pll_half", mout_top1_cc_pll_half_p,
|
||||||
MUX_SEL_TOP11, 8, 1),
|
MUX_SEL_TOP11, 8, 1),
|
||||||
MUX(0, "mout_top1_half_bus1_pll", mout_top1_half_bus1_pll_p,
|
MUX(0, "mout_top1_bus1_pll_half", mout_top1_bus1_pll_half_p,
|
||||||
MUX_SEL_TOP11, 12, 1),
|
MUX_SEL_TOP11, 12, 1),
|
||||||
MUX(0, "mout_top1_half_bus0_pll", mout_top1_half_bus0_pll_p,
|
MUX(0, "mout_top1_bus0_pll_half", mout_top1_bus0_pll_half_p,
|
||||||
MUX_SEL_TOP11, 16, 1),
|
MUX_SEL_TOP11, 16, 1),
|
||||||
|
|
||||||
MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2),
|
MUX(0, "mout_aclk_fsys1_200", mout_top1_group1, MUX_SEL_TOP13, 24, 2),
|
||||||
MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2),
|
MUX(0, "mout_aclk_fsys0_200", mout_top1_group1, MUX_SEL_TOP13, 28, 2),
|
||||||
|
|
||||||
MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 24, 2),
|
MUX(0, "mout_sclk_phy_fsys0_26m", mout_top1_group1,
|
||||||
|
MUX_SEL_TOP1_FSYS0, 0, 2),
|
||||||
|
MUX(0, "mout_sclk_mmc2", mout_top1_group1, MUX_SEL_TOP1_FSYS0, 16, 2),
|
||||||
MUX(0, "mout_sclk_usbdrd300", mout_top1_group1,
|
MUX(0, "mout_sclk_usbdrd300", mout_top1_group1,
|
||||||
MUX_SEL_TOP1_FSYS0, 28, 2),
|
MUX_SEL_TOP1_FSYS0, 28, 2),
|
||||||
|
|
||||||
MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 24, 2),
|
MUX(0, "mout_sclk_phy_fsys1", mout_top1_group1,
|
||||||
MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS1, 28, 2),
|
MUX_SEL_TOP1_FSYS1, 0, 2),
|
||||||
|
MUX(0, "mout_sclk_ufsunipro20", mout_top1_group1,
|
||||||
|
MUX_SEL_TOP1_FSYS1, 16, 2),
|
||||||
|
|
||||||
|
MUX(0, "mout_sclk_mmc1", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 0, 2),
|
||||||
|
MUX(0, "mout_sclk_mmc0", mout_top1_group1, MUX_SEL_TOP1_FSYS11, 12, 2),
|
||||||
|
MUX(0, "mout_sclk_phy_fsys1_26m", mout_top1_group1,
|
||||||
|
MUX_SEL_TOP1_FSYS11, 24, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_div_clock top1_div_clks[] __initdata = {
|
static struct samsung_div_clock top1_div_clks[] __initdata = {
|
||||||
|
@ -439,34 +500,61 @@ static struct samsung_div_clock top1_div_clks[] __initdata = {
|
||||||
DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200",
|
DIV(DOUT_ACLK_FSYS0_200, "dout_aclk_fsys0_200", "mout_aclk_fsys0_200",
|
||||||
DIV_TOP13, 28, 4),
|
DIV_TOP13, 28, 4),
|
||||||
|
|
||||||
|
DIV(DOUT_SCLK_PHY_FSYS1, "dout_sclk_phy_fsys1",
|
||||||
|
"mout_sclk_phy_fsys1", DIV_TOP1_FSYS1, 0, 6),
|
||||||
|
|
||||||
|
DIV(DOUT_SCLK_UFSUNIPRO20, "dout_sclk_ufsunipro20",
|
||||||
|
"mout_sclk_ufsunipro20",
|
||||||
|
DIV_TOP1_FSYS1, 16, 6),
|
||||||
|
|
||||||
DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2",
|
DIV(DOUT_SCLK_MMC2, "dout_sclk_mmc2", "mout_sclk_mmc2",
|
||||||
DIV_TOP1_FSYS0, 24, 4),
|
DIV_TOP1_FSYS0, 16, 10),
|
||||||
DIV(0, "dout_sclk_usbdrd300", "mout_sclk_usbdrd300",
|
DIV(0, "dout_sclk_usbdrd300", "mout_sclk_usbdrd300",
|
||||||
DIV_TOP1_FSYS0, 28, 4),
|
DIV_TOP1_FSYS0, 28, 4),
|
||||||
|
|
||||||
DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1",
|
DIV(DOUT_SCLK_MMC1, "dout_sclk_mmc1", "mout_sclk_mmc1",
|
||||||
DIV_TOP1_FSYS1, 24, 4),
|
DIV_TOP1_FSYS11, 0, 10),
|
||||||
DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0",
|
DIV(DOUT_SCLK_MMC0, "dout_sclk_mmc0", "mout_sclk_mmc0",
|
||||||
DIV_TOP1_FSYS1, 28, 4),
|
DIV_TOP1_FSYS11, 12, 10),
|
||||||
|
|
||||||
|
DIV(DOUT_SCLK_PHY_FSYS1_26M, "dout_sclk_phy_fsys1_26m",
|
||||||
|
"mout_sclk_phy_fsys1_26m", DIV_TOP1_FSYS11, 24, 6),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock top1_gate_clks[] __initdata = {
|
static struct samsung_gate_clock top1_gate_clks[] __initdata = {
|
||||||
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
|
GATE(CLK_SCLK_MMC2, "sclk_mmc2", "dout_sclk_mmc2",
|
||||||
ENABLE_SCLK_TOP1_FSYS0, 24, CLK_SET_RATE_PARENT, 0),
|
ENABLE_SCLK_TOP1_FSYS0, 16, CLK_SET_RATE_PARENT, 0),
|
||||||
GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
|
GATE(0, "sclk_usbdrd300", "dout_sclk_usbdrd300",
|
||||||
ENABLE_SCLK_TOP1_FSYS0, 28, 0, 0),
|
ENABLE_SCLK_TOP1_FSYS0, 28, 0, 0),
|
||||||
|
|
||||||
|
GATE(CLK_SCLK_PHY_FSYS1, "sclk_phy_fsys1", "dout_sclk_phy_fsys1",
|
||||||
|
ENABLE_SCLK_TOP1_FSYS1, 0, CLK_SET_RATE_PARENT, 0),
|
||||||
|
|
||||||
|
GATE(CLK_SCLK_UFSUNIPRO20, "sclk_ufsunipro20", "dout_sclk_ufsunipro20",
|
||||||
|
ENABLE_SCLK_TOP1_FSYS1, 16, CLK_SET_RATE_PARENT, 0),
|
||||||
|
|
||||||
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1",
|
GATE(CLK_SCLK_MMC1, "sclk_mmc1", "dout_sclk_mmc1",
|
||||||
ENABLE_SCLK_TOP1_FSYS1, 24, CLK_SET_RATE_PARENT, 0),
|
ENABLE_SCLK_TOP1_FSYS11, 0, CLK_SET_RATE_PARENT, 0),
|
||||||
GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0",
|
GATE(CLK_SCLK_MMC0, "sclk_mmc0", "dout_sclk_mmc0",
|
||||||
ENABLE_SCLK_TOP1_FSYS1, 28, CLK_SET_RATE_PARENT, 0),
|
ENABLE_SCLK_TOP1_FSYS11, 12, CLK_SET_RATE_PARENT, 0),
|
||||||
|
|
||||||
|
GATE(CLK_ACLK_FSYS0_200, "aclk_fsys0_200", "dout_aclk_fsys0_200",
|
||||||
|
ENABLE_ACLK_TOP13, 28, CLK_SET_RATE_PARENT, 0),
|
||||||
|
GATE(CLK_ACLK_FSYS1_200, "aclk_fsys1_200", "dout_aclk_fsys1_200",
|
||||||
|
ENABLE_ACLK_TOP13, 24, CLK_SET_RATE_PARENT, 0),
|
||||||
|
|
||||||
|
GATE(CLK_SCLK_PHY_FSYS1_26M, "sclk_phy_fsys1_26m",
|
||||||
|
"dout_sclk_phy_fsys1_26m", ENABLE_SCLK_TOP1_FSYS11,
|
||||||
|
24, CLK_SET_RATE_PARENT, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
|
static struct samsung_fixed_factor_clock top1_fixed_factor_clks[] __initdata = {
|
||||||
FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll", 1, 2, 0),
|
FFACTOR(0, "ffac_top1_bus0_pll_div2", "mout_top1_bus0_pll_user",
|
||||||
FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll", 1, 2, 0),
|
1, 2, 0),
|
||||||
FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll", 1, 2, 0),
|
FFACTOR(0, "ffac_top1_bus1_pll_div2", "mout_top1_bus1_pll_user",
|
||||||
FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll", 1, 2, 0),
|
1, 2, 0),
|
||||||
|
FFACTOR(0, "ffac_top1_cc_pll_div2", "mout_top1_cc_pll_user", 1, 2, 0),
|
||||||
|
FFACTOR(0, "ffac_top1_mfc_pll_div2", "mout_top1_mfc_pll_user", 1, 2, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_cmu_info top1_cmu_info __initdata = {
|
static struct samsung_cmu_info top1_cmu_info __initdata = {
|
||||||
|
@ -501,7 +589,7 @@ CLK_OF_DECLARE(exynos7_clk_top1, "samsung,exynos7-clock-top1",
|
||||||
/*
|
/*
|
||||||
* List of parent clocks for Muxes in CMU_CCORE
|
* List of parent clocks for Muxes in CMU_CCORE
|
||||||
*/
|
*/
|
||||||
PNAME(mout_aclk_ccore_133_p) = { "fin_pll", "dout_aclk_ccore_133" };
|
PNAME(mout_aclk_ccore_133_user_p) = { "fin_pll", "aclk_ccore_133" };
|
||||||
|
|
||||||
static unsigned long ccore_clk_regs[] __initdata = {
|
static unsigned long ccore_clk_regs[] __initdata = {
|
||||||
MUX_SEL_CCORE,
|
MUX_SEL_CCORE,
|
||||||
|
@ -509,7 +597,7 @@ static unsigned long ccore_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock ccore_mux_clks[] __initdata = {
|
static struct samsung_mux_clock ccore_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_p,
|
MUX(0, "mout_aclk_ccore_133_user", mout_aclk_ccore_133_user_p,
|
||||||
MUX_SEL_CCORE, 1, 1),
|
MUX_SEL_CCORE, 1, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -542,8 +630,8 @@ CLK_OF_DECLARE(exynos7_clk_ccore, "samsung,exynos7-clock-ccore",
|
||||||
#define ENABLE_SCLK_PERIC0 0x0A00
|
#define ENABLE_SCLK_PERIC0 0x0A00
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_PERIC0 */
|
/* List of parent clocks for Muxes in CMU_PERIC0 */
|
||||||
PNAME(mout_aclk_peric0_66_p) = { "fin_pll", "dout_aclk_peric0_66" };
|
PNAME(mout_aclk_peric0_66_user_p) = { "fin_pll", "aclk_peric0_66" };
|
||||||
PNAME(mout_sclk_uart0_p) = { "fin_pll", "sclk_uart0" };
|
PNAME(mout_sclk_uart0_user_p) = { "fin_pll", "sclk_uart0" };
|
||||||
|
|
||||||
static unsigned long peric0_clk_regs[] __initdata = {
|
static unsigned long peric0_clk_regs[] __initdata = {
|
||||||
MUX_SEL_PERIC0,
|
MUX_SEL_PERIC0,
|
||||||
|
@ -552,9 +640,9 @@ static unsigned long peric0_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock peric0_mux_clks[] __initdata = {
|
static struct samsung_mux_clock peric0_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_p,
|
MUX(0, "mout_aclk_peric0_66_user", mout_aclk_peric0_66_user_p,
|
||||||
MUX_SEL_PERIC0, 0, 1),
|
MUX_SEL_PERIC0, 0, 1),
|
||||||
MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_p,
|
MUX(0, "mout_sclk_uart0_user", mout_sclk_uart0_user_p,
|
||||||
MUX_SEL_PERIC0, 16, 1),
|
MUX_SEL_PERIC0, 16, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -611,15 +699,15 @@ CLK_OF_DECLARE(exynos7_clk_peric0, "samsung,exynos7-clock-peric0",
|
||||||
exynos7_clk_peric0_init);
|
exynos7_clk_peric0_init);
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_PERIC1 */
|
/* List of parent clocks for Muxes in CMU_PERIC1 */
|
||||||
PNAME(mout_aclk_peric1_66_p) = { "fin_pll", "dout_aclk_peric1_66" };
|
PNAME(mout_aclk_peric1_66_user_p) = { "fin_pll", "aclk_peric1_66" };
|
||||||
PNAME(mout_sclk_uart1_p) = { "fin_pll", "sclk_uart1" };
|
PNAME(mout_sclk_uart1_user_p) = { "fin_pll", "sclk_uart1" };
|
||||||
PNAME(mout_sclk_uart2_p) = { "fin_pll", "sclk_uart2" };
|
PNAME(mout_sclk_uart2_user_p) = { "fin_pll", "sclk_uart2" };
|
||||||
PNAME(mout_sclk_uart3_p) = { "fin_pll", "sclk_uart3" };
|
PNAME(mout_sclk_uart3_user_p) = { "fin_pll", "sclk_uart3" };
|
||||||
PNAME(mout_sclk_spi0_p) = { "fin_pll", "sclk_spi0" };
|
PNAME(mout_sclk_spi0_user_p) = { "fin_pll", "sclk_spi0" };
|
||||||
PNAME(mout_sclk_spi1_p) = { "fin_pll", "sclk_spi1" };
|
PNAME(mout_sclk_spi1_user_p) = { "fin_pll", "sclk_spi1" };
|
||||||
PNAME(mout_sclk_spi2_p) = { "fin_pll", "sclk_spi2" };
|
PNAME(mout_sclk_spi2_user_p) = { "fin_pll", "sclk_spi2" };
|
||||||
PNAME(mout_sclk_spi3_p) = { "fin_pll", "sclk_spi3" };
|
PNAME(mout_sclk_spi3_user_p) = { "fin_pll", "sclk_spi3" };
|
||||||
PNAME(mout_sclk_spi4_p) = { "fin_pll", "sclk_spi4" };
|
PNAME(mout_sclk_spi4_user_p) = { "fin_pll", "sclk_spi4" };
|
||||||
|
|
||||||
static unsigned long peric1_clk_regs[] __initdata = {
|
static unsigned long peric1_clk_regs[] __initdata = {
|
||||||
MUX_SEL_PERIC10,
|
MUX_SEL_PERIC10,
|
||||||
|
@ -630,24 +718,24 @@ static unsigned long peric1_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
|
static struct samsung_mux_clock peric1_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_p,
|
MUX(0, "mout_aclk_peric1_66_user", mout_aclk_peric1_66_user_p,
|
||||||
MUX_SEL_PERIC10, 0, 1),
|
MUX_SEL_PERIC10, 0, 1),
|
||||||
|
|
||||||
MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_p,
|
MUX_F(0, "mout_sclk_spi0_user", mout_sclk_spi0_user_p,
|
||||||
MUX_SEL_PERIC11, 0, 1, CLK_SET_RATE_PARENT, 0),
|
MUX_SEL_PERIC11, 0, 1, CLK_SET_RATE_PARENT, 0),
|
||||||
MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_p,
|
MUX_F(0, "mout_sclk_spi1_user", mout_sclk_spi1_user_p,
|
||||||
MUX_SEL_PERIC11, 4, 1, CLK_SET_RATE_PARENT, 0),
|
MUX_SEL_PERIC11, 4, 1, CLK_SET_RATE_PARENT, 0),
|
||||||
MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_p,
|
MUX_F(0, "mout_sclk_spi2_user", mout_sclk_spi2_user_p,
|
||||||
MUX_SEL_PERIC11, 8, 1, CLK_SET_RATE_PARENT, 0),
|
MUX_SEL_PERIC11, 8, 1, CLK_SET_RATE_PARENT, 0),
|
||||||
MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_p,
|
MUX_F(0, "mout_sclk_spi3_user", mout_sclk_spi3_user_p,
|
||||||
MUX_SEL_PERIC11, 12, 1, CLK_SET_RATE_PARENT, 0),
|
MUX_SEL_PERIC11, 12, 1, CLK_SET_RATE_PARENT, 0),
|
||||||
MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_p,
|
MUX_F(0, "mout_sclk_spi4_user", mout_sclk_spi4_user_p,
|
||||||
MUX_SEL_PERIC11, 16, 1, CLK_SET_RATE_PARENT, 0),
|
MUX_SEL_PERIC11, 16, 1, CLK_SET_RATE_PARENT, 0),
|
||||||
MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_p,
|
MUX(0, "mout_sclk_uart1_user", mout_sclk_uart1_user_p,
|
||||||
MUX_SEL_PERIC11, 20, 1),
|
MUX_SEL_PERIC11, 20, 1),
|
||||||
MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_p,
|
MUX(0, "mout_sclk_uart2_user", mout_sclk_uart2_user_p,
|
||||||
MUX_SEL_PERIC11, 24, 1),
|
MUX_SEL_PERIC11, 24, 1),
|
||||||
MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_p,
|
MUX(0, "mout_sclk_uart3_user", mout_sclk_uart3_user_p,
|
||||||
MUX_SEL_PERIC11, 28, 1),
|
MUX_SEL_PERIC11, 28, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -735,7 +823,7 @@ CLK_OF_DECLARE(exynos7_clk_peric1, "samsung,exynos7-clock-peric1",
|
||||||
#define ENABLE_SCLK_PERIS_SECURE_CHIPID 0x0A10
|
#define ENABLE_SCLK_PERIS_SECURE_CHIPID 0x0A10
|
||||||
|
|
||||||
/* List of parent clocks for Muxes in CMU_PERIS */
|
/* List of parent clocks for Muxes in CMU_PERIS */
|
||||||
PNAME(mout_aclk_peris_66_p) = { "fin_pll", "dout_aclk_peris_66" };
|
PNAME(mout_aclk_peris_66_user_p) = { "fin_pll", "aclk_peris_66" };
|
||||||
|
|
||||||
static unsigned long peris_clk_regs[] __initdata = {
|
static unsigned long peris_clk_regs[] __initdata = {
|
||||||
MUX_SEL_PERIS,
|
MUX_SEL_PERIS,
|
||||||
|
@ -747,7 +835,7 @@ static unsigned long peris_clk_regs[] __initdata = {
|
||||||
|
|
||||||
static struct samsung_mux_clock peris_mux_clks[] __initdata = {
|
static struct samsung_mux_clock peris_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_peris_66_user",
|
MUX(0, "mout_aclk_peris_66_user",
|
||||||
mout_aclk_peris_66_p, MUX_SEL_PERIS, 0, 1),
|
mout_aclk_peris_66_user_p, MUX_SEL_PERIS, 0, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock peris_gate_clks[] __initdata = {
|
static struct samsung_gate_clock peris_gate_clks[] __initdata = {
|
||||||
|
@ -795,17 +883,17 @@ CLK_OF_DECLARE(exynos7_clk_peris, "samsung,exynos7-clock-peris",
|
||||||
/*
|
/*
|
||||||
* List of parent clocks for Muxes in CMU_FSYS0
|
* List of parent clocks for Muxes in CMU_FSYS0
|
||||||
*/
|
*/
|
||||||
PNAME(mout_aclk_fsys0_200_p) = { "fin_pll", "dout_aclk_fsys0_200" };
|
PNAME(mout_aclk_fsys0_200_user_p) = { "fin_pll", "aclk_fsys0_200" };
|
||||||
PNAME(mout_sclk_mmc2_p) = { "fin_pll", "sclk_mmc2" };
|
PNAME(mout_sclk_mmc2_user_p) = { "fin_pll", "sclk_mmc2" };
|
||||||
|
|
||||||
PNAME(mout_sclk_usbdrd300_p) = { "fin_pll", "sclk_usbdrd300" };
|
PNAME(mout_sclk_usbdrd300_user_p) = { "fin_pll", "sclk_usbdrd300" };
|
||||||
PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_p) = { "fin_pll",
|
PNAME(mout_phyclk_usbdrd300_udrd30_phyclk_user_p) = { "fin_pll",
|
||||||
"phyclk_usbdrd300_udrd30_phyclock" };
|
"phyclk_usbdrd300_udrd30_phyclock" };
|
||||||
PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_p) = { "fin_pll",
|
PNAME(mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p) = { "fin_pll",
|
||||||
"phyclk_usbdrd300_udrd30_pipe_pclk" };
|
"phyclk_usbdrd300_udrd30_pipe_pclk" };
|
||||||
|
|
||||||
/* fixed rate clocks used in the FSYS0 block */
|
/* fixed rate clocks used in the FSYS0 block */
|
||||||
struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
|
static struct samsung_fixed_rate_clock fixed_rate_clks_fsys0[] __initdata = {
|
||||||
FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL,
|
FRATE(0, "phyclk_usbdrd300_udrd30_phyclock", NULL,
|
||||||
CLK_IS_ROOT, 60000000),
|
CLK_IS_ROOT, 60000000),
|
||||||
FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL,
|
FRATE(0, "phyclk_usbdrd300_udrd30_pipe_pclk", NULL,
|
||||||
|
@ -824,29 +912,30 @@ static unsigned long fsys0_clk_regs[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
|
static struct samsung_mux_clock fsys0_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_p,
|
MUX(0, "mout_aclk_fsys0_200_user", mout_aclk_fsys0_200_user_p,
|
||||||
MUX_SEL_FSYS00, 24, 1),
|
MUX_SEL_FSYS00, 24, 1),
|
||||||
|
|
||||||
MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_p, MUX_SEL_FSYS01, 24, 1),
|
MUX(0, "mout_sclk_mmc2_user", mout_sclk_mmc2_user_p,
|
||||||
MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_p,
|
MUX_SEL_FSYS01, 24, 1),
|
||||||
|
MUX(0, "mout_sclk_usbdrd300_user", mout_sclk_usbdrd300_user_p,
|
||||||
MUX_SEL_FSYS01, 28, 1),
|
MUX_SEL_FSYS01, 28, 1),
|
||||||
|
|
||||||
MUX(0, "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user",
|
MUX(0, "mout_phyclk_usbdrd300_udrd30_pipe_pclk_user",
|
||||||
mout_phyclk_usbdrd300_udrd30_pipe_pclk_p,
|
mout_phyclk_usbdrd300_udrd30_pipe_pclk_user_p,
|
||||||
MUX_SEL_FSYS02, 24, 1),
|
MUX_SEL_FSYS02, 24, 1),
|
||||||
MUX(0, "mout_phyclk_usbdrd300_udrd30_phyclk_user",
|
MUX(0, "mout_phyclk_usbdrd300_udrd30_phyclk_user",
|
||||||
mout_phyclk_usbdrd300_udrd30_phyclk_p,
|
mout_phyclk_usbdrd300_udrd30_phyclk_user_p,
|
||||||
MUX_SEL_FSYS02, 28, 1),
|
MUX_SEL_FSYS02, 28, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
|
static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
|
||||||
GATE(ACLK_AXIUS_USBDRD30X_FSYS0X, "aclk_axius_usbdrd30x_fsys0x",
|
|
||||||
"mout_aclk_fsys0_200_user",
|
|
||||||
ENABLE_ACLK_FSYS00, 19, 0, 0),
|
|
||||||
GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
|
GATE(ACLK_PDMA1, "aclk_pdma1", "mout_aclk_fsys0_200_user",
|
||||||
ENABLE_ACLK_FSYS00, 3, 0, 0),
|
ENABLE_ACLK_FSYS00, 3, 0, 0),
|
||||||
GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
|
GATE(ACLK_PDMA0, "aclk_pdma0", "mout_aclk_fsys0_200_user",
|
||||||
ENABLE_ACLK_FSYS00, 4, 0, 0),
|
ENABLE_ACLK_FSYS00, 4, 0, 0),
|
||||||
|
GATE(ACLK_AXIUS_USBDRD30X_FSYS0X, "aclk_axius_usbdrd30x_fsys0x",
|
||||||
|
"mout_aclk_fsys0_200_user",
|
||||||
|
ENABLE_ACLK_FSYS00, 19, 0, 0),
|
||||||
|
|
||||||
GATE(ACLK_USBDRD300, "aclk_usbdrd300", "mout_aclk_fsys0_200_user",
|
GATE(ACLK_USBDRD300, "aclk_usbdrd300", "mout_aclk_fsys0_200_user",
|
||||||
ENABLE_ACLK_FSYS01, 29, 0, 0),
|
ENABLE_ACLK_FSYS01, 29, 0, 0),
|
||||||
|
@ -874,11 +963,13 @@ static struct samsung_gate_clock fsys0_gate_clks[] __initdata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_cmu_info fsys0_cmu_info __initdata = {
|
static struct samsung_cmu_info fsys0_cmu_info __initdata = {
|
||||||
|
.fixed_clks = fixed_rate_clks_fsys0,
|
||||||
|
.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys0),
|
||||||
.mux_clks = fsys0_mux_clks,
|
.mux_clks = fsys0_mux_clks,
|
||||||
.nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks),
|
.nr_mux_clks = ARRAY_SIZE(fsys0_mux_clks),
|
||||||
.gate_clks = fsys0_gate_clks,
|
.gate_clks = fsys0_gate_clks,
|
||||||
.nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks),
|
.nr_gate_clks = ARRAY_SIZE(fsys0_gate_clks),
|
||||||
.nr_clk_ids = TOP1_NR_CLK,
|
.nr_clk_ids = FSYS0_NR_CLK,
|
||||||
.clk_regs = fsys0_clk_regs,
|
.clk_regs = fsys0_clk_regs,
|
||||||
.nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs),
|
.nr_clk_regs = ARRAY_SIZE(fsys0_clk_regs),
|
||||||
};
|
};
|
||||||
|
@ -894,42 +985,122 @@ CLK_OF_DECLARE(exynos7_clk_fsys0, "samsung,exynos7-clock-fsys0",
|
||||||
/* Register Offset definitions for CMU_FSYS1 (0x156E0000) */
|
/* Register Offset definitions for CMU_FSYS1 (0x156E0000) */
|
||||||
#define MUX_SEL_FSYS10 0x0200
|
#define MUX_SEL_FSYS10 0x0200
|
||||||
#define MUX_SEL_FSYS11 0x0204
|
#define MUX_SEL_FSYS11 0x0204
|
||||||
|
#define MUX_SEL_FSYS12 0x0208
|
||||||
|
#define DIV_FSYS1 0x0600
|
||||||
#define ENABLE_ACLK_FSYS1 0x0800
|
#define ENABLE_ACLK_FSYS1 0x0800
|
||||||
|
#define ENABLE_PCLK_FSYS1 0x0900
|
||||||
|
#define ENABLE_SCLK_FSYS11 0x0A04
|
||||||
|
#define ENABLE_SCLK_FSYS12 0x0A08
|
||||||
|
#define ENABLE_SCLK_FSYS13 0x0A0C
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List of parent clocks for Muxes in CMU_FSYS1
|
* List of parent clocks for Muxes in CMU_FSYS1
|
||||||
*/
|
*/
|
||||||
PNAME(mout_aclk_fsys1_200_p) = { "fin_pll", "dout_aclk_fsys1_200" };
|
PNAME(mout_aclk_fsys1_200_user_p) = { "fin_pll", "aclk_fsys1_200" };
|
||||||
PNAME(mout_sclk_mmc0_p) = { "fin_pll", "sclk_mmc0" };
|
PNAME(mout_fsys1_group_p) = { "fin_pll", "fin_pll_26m",
|
||||||
PNAME(mout_sclk_mmc1_p) = { "fin_pll", "sclk_mmc1" };
|
"sclk_phy_fsys1_26m" };
|
||||||
|
PNAME(mout_sclk_mmc0_user_p) = { "fin_pll", "sclk_mmc0" };
|
||||||
|
PNAME(mout_sclk_mmc1_user_p) = { "fin_pll", "sclk_mmc1" };
|
||||||
|
PNAME(mout_sclk_ufsunipro20_user_p) = { "fin_pll", "sclk_ufsunipro20" };
|
||||||
|
PNAME(mout_phyclk_ufs20_tx0_user_p) = { "fin_pll", "phyclk_ufs20_tx0_symbol" };
|
||||||
|
PNAME(mout_phyclk_ufs20_rx0_user_p) = { "fin_pll", "phyclk_ufs20_rx0_symbol" };
|
||||||
|
PNAME(mout_phyclk_ufs20_rx1_user_p) = { "fin_pll", "phyclk_ufs20_rx1_symbol" };
|
||||||
|
|
||||||
|
/* fixed rate clocks used in the FSYS1 block */
|
||||||
|
static struct samsung_fixed_rate_clock fixed_rate_clks_fsys1[] __initdata = {
|
||||||
|
FRATE(PHYCLK_UFS20_TX0_SYMBOL, "phyclk_ufs20_tx0_symbol", NULL,
|
||||||
|
CLK_IS_ROOT, 300000000),
|
||||||
|
FRATE(PHYCLK_UFS20_RX0_SYMBOL, "phyclk_ufs20_rx0_symbol", NULL,
|
||||||
|
CLK_IS_ROOT, 300000000),
|
||||||
|
FRATE(PHYCLK_UFS20_RX1_SYMBOL, "phyclk_ufs20_rx1_symbol", NULL,
|
||||||
|
CLK_IS_ROOT, 300000000),
|
||||||
|
};
|
||||||
|
|
||||||
static unsigned long fsys1_clk_regs[] __initdata = {
|
static unsigned long fsys1_clk_regs[] __initdata = {
|
||||||
MUX_SEL_FSYS10,
|
MUX_SEL_FSYS10,
|
||||||
MUX_SEL_FSYS11,
|
MUX_SEL_FSYS11,
|
||||||
|
MUX_SEL_FSYS12,
|
||||||
|
DIV_FSYS1,
|
||||||
ENABLE_ACLK_FSYS1,
|
ENABLE_ACLK_FSYS1,
|
||||||
|
ENABLE_PCLK_FSYS1,
|
||||||
|
ENABLE_SCLK_FSYS11,
|
||||||
|
ENABLE_SCLK_FSYS12,
|
||||||
|
ENABLE_SCLK_FSYS13,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
|
static struct samsung_mux_clock fsys1_mux_clks[] __initdata = {
|
||||||
MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_p,
|
MUX(MOUT_FSYS1_PHYCLK_SEL1, "mout_fsys1_phyclk_sel1",
|
||||||
|
mout_fsys1_group_p, MUX_SEL_FSYS10, 16, 2),
|
||||||
|
MUX(0, "mout_fsys1_phyclk_sel0", mout_fsys1_group_p,
|
||||||
|
MUX_SEL_FSYS10, 20, 2),
|
||||||
|
MUX(0, "mout_aclk_fsys1_200_user", mout_aclk_fsys1_200_user_p,
|
||||||
MUX_SEL_FSYS10, 28, 1),
|
MUX_SEL_FSYS10, 28, 1),
|
||||||
|
|
||||||
MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_p, MUX_SEL_FSYS11, 24, 1),
|
MUX(0, "mout_sclk_mmc1_user", mout_sclk_mmc1_user_p,
|
||||||
MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_p, MUX_SEL_FSYS11, 28, 1),
|
MUX_SEL_FSYS11, 24, 1),
|
||||||
|
MUX(0, "mout_sclk_mmc0_user", mout_sclk_mmc0_user_p,
|
||||||
|
MUX_SEL_FSYS11, 28, 1),
|
||||||
|
MUX(0, "mout_sclk_ufsunipro20_user", mout_sclk_ufsunipro20_user_p,
|
||||||
|
MUX_SEL_FSYS11, 20, 1),
|
||||||
|
|
||||||
|
MUX(0, "mout_phyclk_ufs20_rx1_symbol_user",
|
||||||
|
mout_phyclk_ufs20_rx1_user_p, MUX_SEL_FSYS12, 16, 1),
|
||||||
|
MUX(0, "mout_phyclk_ufs20_rx0_symbol_user",
|
||||||
|
mout_phyclk_ufs20_rx0_user_p, MUX_SEL_FSYS12, 24, 1),
|
||||||
|
MUX(0, "mout_phyclk_ufs20_tx0_symbol_user",
|
||||||
|
mout_phyclk_ufs20_tx0_user_p, MUX_SEL_FSYS12, 28, 1),
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct samsung_div_clock fsys1_div_clks[] __initdata = {
|
||||||
|
DIV(DOUT_PCLK_FSYS1, "dout_pclk_fsys1", "mout_aclk_fsys1_200_user",
|
||||||
|
DIV_FSYS1, 0, 2),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
|
static struct samsung_gate_clock fsys1_gate_clks[] __initdata = {
|
||||||
|
GATE(SCLK_UFSUNIPRO20_USER, "sclk_ufsunipro20_user",
|
||||||
|
"mout_sclk_ufsunipro20_user",
|
||||||
|
ENABLE_SCLK_FSYS11, 20, 0, 0),
|
||||||
|
|
||||||
GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user",
|
GATE(ACLK_MMC1, "aclk_mmc1", "mout_aclk_fsys1_200_user",
|
||||||
ENABLE_ACLK_FSYS1, 29, 0, 0),
|
ENABLE_ACLK_FSYS1, 29, 0, 0),
|
||||||
GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user",
|
GATE(ACLK_MMC0, "aclk_mmc0", "mout_aclk_fsys1_200_user",
|
||||||
ENABLE_ACLK_FSYS1, 30, 0, 0),
|
ENABLE_ACLK_FSYS1, 30, 0, 0),
|
||||||
|
|
||||||
|
GATE(ACLK_UFS20_LINK, "aclk_ufs20_link", "dout_pclk_fsys1",
|
||||||
|
ENABLE_ACLK_FSYS1, 31, 0, 0),
|
||||||
|
GATE(PCLK_GPIO_FSYS1, "pclk_gpio_fsys1", "mout_aclk_fsys1_200_user",
|
||||||
|
ENABLE_PCLK_FSYS1, 30, 0, 0),
|
||||||
|
|
||||||
|
GATE(PHYCLK_UFS20_RX1_SYMBOL_USER, "phyclk_ufs20_rx1_symbol_user",
|
||||||
|
"mout_phyclk_ufs20_rx1_symbol_user",
|
||||||
|
ENABLE_SCLK_FSYS12, 16, 0, 0),
|
||||||
|
GATE(PHYCLK_UFS20_RX0_SYMBOL_USER, "phyclk_ufs20_rx0_symbol_user",
|
||||||
|
"mout_phyclk_ufs20_rx0_symbol_user",
|
||||||
|
ENABLE_SCLK_FSYS12, 24, 0, 0),
|
||||||
|
GATE(PHYCLK_UFS20_TX0_SYMBOL_USER, "phyclk_ufs20_tx0_symbol_user",
|
||||||
|
"mout_phyclk_ufs20_tx0_symbol_user",
|
||||||
|
ENABLE_SCLK_FSYS12, 28, 0, 0),
|
||||||
|
|
||||||
|
GATE(OSCCLK_PHY_CLKOUT_EMBEDDED_COMBO_PHY,
|
||||||
|
"oscclk_phy_clkout_embedded_combo_phy",
|
||||||
|
"fin_pll",
|
||||||
|
ENABLE_SCLK_FSYS12, 4, CLK_IGNORE_UNUSED, 0),
|
||||||
|
|
||||||
|
GATE(SCLK_COMBO_PHY_EMBEDDED_26M, "sclk_combo_phy_embedded_26m",
|
||||||
|
"mout_fsys1_phyclk_sel1",
|
||||||
|
ENABLE_SCLK_FSYS13, 24, CLK_IGNORE_UNUSED, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct samsung_cmu_info fsys1_cmu_info __initdata = {
|
static struct samsung_cmu_info fsys1_cmu_info __initdata = {
|
||||||
|
.fixed_clks = fixed_rate_clks_fsys1,
|
||||||
|
.nr_fixed_clks = ARRAY_SIZE(fixed_rate_clks_fsys1),
|
||||||
.mux_clks = fsys1_mux_clks,
|
.mux_clks = fsys1_mux_clks,
|
||||||
.nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks),
|
.nr_mux_clks = ARRAY_SIZE(fsys1_mux_clks),
|
||||||
|
.div_clks = fsys1_div_clks,
|
||||||
|
.nr_div_clks = ARRAY_SIZE(fsys1_div_clks),
|
||||||
.gate_clks = fsys1_gate_clks,
|
.gate_clks = fsys1_gate_clks,
|
||||||
.nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks),
|
.nr_gate_clks = ARRAY_SIZE(fsys1_gate_clks),
|
||||||
.nr_clk_ids = TOP1_NR_CLK,
|
.nr_clk_ids = FSYS1_NR_CLK,
|
||||||
.clk_regs = fsys1_clk_regs,
|
.clk_regs = fsys1_clk_regs,
|
||||||
.nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs),
|
.nr_clk_regs = ARRAY_SIZE(fsys1_clk_regs),
|
||||||
};
|
};
|
||||||
|
|
|
@ -214,7 +214,7 @@ static void __init cpg_mstp_clocks_init(struct device_node *np)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (clkidx >= MSTP_MAX_CLOCKS) {
|
if (clkidx >= MSTP_MAX_CLOCKS) {
|
||||||
pr_err("%s: invalid clock %s %s index %u)\n",
|
pr_err("%s: invalid clock %s %s index %u\n",
|
||||||
__func__, np->name, name, clkidx);
|
__func__, np->name, name, clkidx);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,10 +20,10 @@ struct r8a7778_cpg {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
|
/* PLL multipliers per bits 11, 12, and 18 of MODEMR */
|
||||||
struct {
|
static const struct {
|
||||||
unsigned long plla_mult;
|
unsigned long plla_mult;
|
||||||
unsigned long pllb_mult;
|
unsigned long pllb_mult;
|
||||||
} r8a7778_rates[] __initdata = {
|
} r8a7778_rates[] __initconst = {
|
||||||
[0] = { 21, 21 },
|
[0] = { 21, 21 },
|
||||||
[1] = { 24, 24 },
|
[1] = { 24, 24 },
|
||||||
[2] = { 28, 28 },
|
[2] = { 28, 28 },
|
||||||
|
@ -34,10 +34,10 @@ struct {
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Clock dividers per bits 1 and 2 of MODEMR */
|
/* Clock dividers per bits 1 and 2 of MODEMR */
|
||||||
struct {
|
static const struct {
|
||||||
const char *name;
|
const char *name;
|
||||||
unsigned int div[4];
|
unsigned int div[4];
|
||||||
} r8a7778_divs[6] __initdata = {
|
} r8a7778_divs[6] __initconst = {
|
||||||
{ "b", { 12, 12, 16, 18 } },
|
{ "b", { 12, 12, 16, 18 } },
|
||||||
{ "out", { 12, 12, 16, 18 } },
|
{ "out", { 12, 12, 16, 18 } },
|
||||||
{ "p", { 16, 12, 16, 12 } },
|
{ "p", { 16, 12, 16, 12 } },
|
||||||
|
|
|
@ -205,18 +205,11 @@
|
||||||
#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET 0x0530
|
#define SIRFSOC_CLKC_LEAF_CLK_EN7_SET 0x0530
|
||||||
#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET 0x0548
|
#define SIRFSOC_CLKC_LEAF_CLK_EN8_SET 0x0548
|
||||||
|
|
||||||
|
#define SIRFSOC_NOC_CLK_IDLEREQ_SET 0x02D0
|
||||||
static void __iomem *sirfsoc_clk_vbase;
|
#define SIRFSOC_NOC_CLK_IDLEREQ_CLR 0x02D4
|
||||||
static struct clk_onecell_data clk_data;
|
#define SIRFSOC_NOC_CLK_SLVRDY_SET 0x02E8
|
||||||
|
#define SIRFSOC_NOC_CLK_SLVRDY_CLR 0x02EC
|
||||||
static const struct clk_div_table pll_div_table[] = {
|
#define SIRFSOC_NOC_CLK_IDLE_STATUS 0x02F4
|
||||||
{ .val = 0, .div = 1 },
|
|
||||||
{ .val = 1, .div = 2 },
|
|
||||||
{ .val = 2, .div = 4 },
|
|
||||||
{ .val = 3, .div = 8 },
|
|
||||||
{ .val = 4, .div = 16 },
|
|
||||||
{ .val = 5, .div = 32 },
|
|
||||||
};
|
|
||||||
|
|
||||||
struct clk_pll {
|
struct clk_pll {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
|
@ -231,10 +224,18 @@ struct clk_dto {
|
||||||
};
|
};
|
||||||
#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
|
#define to_dtoclk(_hw) container_of(_hw, struct clk_dto, hw)
|
||||||
|
|
||||||
|
enum clk_unit_type {
|
||||||
|
CLK_UNIT_NOC_OTHER,
|
||||||
|
CLK_UNIT_NOC_CLOCK,
|
||||||
|
CLK_UNIT_NOC_SOCKET,
|
||||||
|
};
|
||||||
|
|
||||||
struct clk_unit {
|
struct clk_unit {
|
||||||
struct clk_hw hw;
|
struct clk_hw hw;
|
||||||
u16 regofs;
|
u16 regofs;
|
||||||
u16 bit;
|
u16 bit;
|
||||||
|
u32 type;
|
||||||
|
u8 idle_bit;
|
||||||
spinlock_t *lock;
|
spinlock_t *lock;
|
||||||
};
|
};
|
||||||
#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
|
#define to_unitclk(_hw) container_of(_hw, struct clk_unit, hw)
|
||||||
|
@ -272,6 +273,8 @@ struct atlas7_unit_init_data {
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 regofs;
|
u32 regofs;
|
||||||
u8 bit;
|
u8 bit;
|
||||||
|
u32 type;
|
||||||
|
u8 idle_bit;
|
||||||
spinlock_t *lock;
|
spinlock_t *lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -284,6 +287,18 @@ struct atlas7_reset_desc {
|
||||||
spinlock_t *lock;
|
spinlock_t *lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void __iomem *sirfsoc_clk_vbase;
|
||||||
|
static struct clk_onecell_data clk_data;
|
||||||
|
|
||||||
|
static const struct clk_div_table pll_div_table[] = {
|
||||||
|
{ .val = 0, .div = 1 },
|
||||||
|
{ .val = 1, .div = 2 },
|
||||||
|
{ .val = 2, .div = 4 },
|
||||||
|
{ .val = 3, .div = 8 },
|
||||||
|
{ .val = 4, .div = 16 },
|
||||||
|
{ .val = 5, .div = 32 },
|
||||||
|
};
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
|
static DEFINE_SPINLOCK(cpupll_ctrl1_lock);
|
||||||
static DEFINE_SPINLOCK(mempll_ctrl1_lock);
|
static DEFINE_SPINLOCK(mempll_ctrl1_lock);
|
||||||
static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
|
static DEFINE_SPINLOCK(sys0pll_ctrl1_lock);
|
||||||
|
@ -1040,148 +1055,148 @@ static struct atlas7_mux_init_data mux_list[] __initdata = {
|
||||||
/* new unit should add start from the tail of list */
|
/* new unit should add start from the tail of list */
|
||||||
static struct atlas7_unit_init_data unit_list[] __initdata = {
|
static struct atlas7_unit_init_data unit_list[] __initdata = {
|
||||||
/* unit_name, parent_name, flags, regofs, bit, lock */
|
/* unit_name, parent_name, flags, regofs, bit, lock */
|
||||||
{ 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, &root0_gate_lock },
|
{ 0, "audmscm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 0, 0, 0, &root0_gate_lock },
|
||||||
{ 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, &root0_gate_lock },
|
{ 1, "gnssm_gnss", "gnss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 1, 0, 0, &root0_gate_lock },
|
||||||
{ 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, &root0_gate_lock },
|
{ 2, "gpum_gpu", "gpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 2, 0, 0, &root0_gate_lock },
|
||||||
{ 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, &root0_gate_lock },
|
{ 3, "mediam_g2d", "g2d_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 3, 0, 0, &root0_gate_lock },
|
||||||
{ 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, &root0_gate_lock },
|
{ 4, "mediam_jpenc", "jpenc_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 4, 0, 0, &root0_gate_lock },
|
||||||
{ 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, &root0_gate_lock },
|
{ 5, "vdifm_disp0", "disp0_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 5, 0, 0, &root0_gate_lock },
|
||||||
{ 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, &root0_gate_lock },
|
{ 6, "vdifm_disp1", "disp1_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 6, 0, 0, &root0_gate_lock },
|
||||||
{ 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, &root0_gate_lock },
|
{ 7, "audmscm_i2s", "i2s_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 8, 0, 0, &root0_gate_lock },
|
||||||
{ 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, &root0_gate_lock },
|
{ 8, "audmscm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 11, 0, 0, &root0_gate_lock },
|
||||||
{ 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, &root0_gate_lock },
|
{ 9, "vdifm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 12, 0, 0, &root0_gate_lock },
|
||||||
{ 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, &root0_gate_lock },
|
{ 10, "gnssm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 13, 0, 0, &root0_gate_lock },
|
||||||
{ 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, &root0_gate_lock },
|
{ 11, "mediam_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 14, 0, 0, &root0_gate_lock },
|
||||||
{ 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, &root0_gate_lock },
|
{ 12, "btm_io", "io_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 17, 0, 0, &root0_gate_lock },
|
||||||
{ 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, &root0_gate_lock },
|
{ 13, "mediam_sdphy01", "sdphy01_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 18, 0, 0, &root0_gate_lock },
|
||||||
{ 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, &root0_gate_lock },
|
{ 14, "vdifm_sdphy23", "sdphy23_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 19, 0, 0, &root0_gate_lock },
|
||||||
{ 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, &root0_gate_lock },
|
{ 15, "vdifm_sdphy45", "sdphy45_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 20, 0, 0, &root0_gate_lock },
|
||||||
{ 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, &root0_gate_lock },
|
{ 16, "vdifm_sdphy67", "sdphy67_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 21, 0, 0, &root0_gate_lock },
|
||||||
{ 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, &root0_gate_lock },
|
{ 17, "audmscm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 22, 0, 0, &root0_gate_lock },
|
||||||
{ 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, &root0_gate_lock },
|
{ 18, "mediam_nand", "nand_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 27, 0, 0, &root0_gate_lock },
|
||||||
{ 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, &root0_gate_lock },
|
{ 19, "gnssm_sec", "sec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 28, 0, 0, &root0_gate_lock },
|
||||||
{ 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, &root0_gate_lock },
|
{ 20, "cpum_cpu", "cpu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 29, 0, 0, &root0_gate_lock },
|
||||||
{ 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, &root0_gate_lock },
|
{ 21, "gnssm_xin", "xin", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 30, 0, 0, &root0_gate_lock },
|
||||||
{ 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, &root0_gate_lock },
|
{ 22, "vdifm_vip", "vip_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN0_SET, 31, 0, 0, &root0_gate_lock },
|
||||||
{ 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, &root1_gate_lock },
|
{ 23, "btm_btss", "btss_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 0, 0, 0, &root1_gate_lock },
|
||||||
{ 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, &root1_gate_lock },
|
{ 24, "mediam_usbphy", "usbphy_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 1, 0, 0, &root1_gate_lock },
|
||||||
{ 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, &root1_gate_lock },
|
{ 25, "rtcm_kas", "kas_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 2, 0, 0, &root1_gate_lock },
|
||||||
{ 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, &root1_gate_lock },
|
{ 26, "audmscm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 3, 0, 0, &root1_gate_lock },
|
||||||
{ 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, &root1_gate_lock },
|
{ 27, "vdifm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 4, 0, 0, &root1_gate_lock },
|
||||||
{ 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, &root1_gate_lock },
|
{ 28, "gnssm_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 5, 0, 0, &root1_gate_lock },
|
||||||
{ 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, &root1_gate_lock },
|
{ 29, "mediam_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 6, 0, 0, &root1_gate_lock },
|
||||||
{ 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, &root1_gate_lock },
|
{ 30, "cpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 8, 0, 0, &root1_gate_lock },
|
||||||
{ 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, &root1_gate_lock },
|
{ 31, "gpum_nocd", "nocd_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 9, 0, 0, &root1_gate_lock },
|
||||||
{ 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, &root1_gate_lock },
|
{ 32, "audmscm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 11, 0, 0, &root1_gate_lock },
|
||||||
{ 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, &root1_gate_lock },
|
{ 33, "vdifm_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 12, 0, 0, &root1_gate_lock },
|
||||||
{ 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, &root1_gate_lock },
|
{ 34, "gnssm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 13, 0, 0, &root1_gate_lock },
|
||||||
{ 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, &root1_gate_lock },
|
{ 35, "mediam_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 14, 0, 0, &root1_gate_lock },
|
||||||
{ 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, &root1_gate_lock },
|
{ 36, "ddrm_nocr", "nocr_mux", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 15, 0, 0, &root1_gate_lock },
|
||||||
{ 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, &root1_gate_lock },
|
{ 37, "cpum_tpiu", "tpiu_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 16, 0, 0, &root1_gate_lock },
|
||||||
{ 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, &root1_gate_lock },
|
{ 38, "gpum_nocr", "nocr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 17, 0, 0, &root1_gate_lock },
|
||||||
{ 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, &root1_gate_lock },
|
{ 39, "gnssm_rgmii", "rgmii_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 20, 0, 0, &root1_gate_lock },
|
||||||
{ 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, &root1_gate_lock },
|
{ 40, "mediam_vdec", "vdec_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 21, 0, 0, &root1_gate_lock },
|
||||||
{ 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, &root1_gate_lock },
|
{ 41, "gpum_sdr", "sdr_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 22, 0, 0, &root1_gate_lock },
|
||||||
{ 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, &root1_gate_lock },
|
{ 42, "vdifm_deint", "deint_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 23, 0, 0, &root1_gate_lock },
|
||||||
{ 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, &root1_gate_lock },
|
{ 43, "gnssm_can", "can_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 26, 0, 0, &root1_gate_lock },
|
||||||
{ 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, &root1_gate_lock },
|
{ 44, "mediam_usb", "usb_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 28, 0, 0, &root1_gate_lock },
|
||||||
{ 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, &root1_gate_lock },
|
{ 45, "gnssm_gmac", "gmac_mux", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 29, 0, 0, &root1_gate_lock },
|
||||||
{ 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, &leaf1_gate_lock },
|
{ 46, "cvd_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 0, CLK_UNIT_NOC_CLOCK, 4, &leaf1_gate_lock },
|
||||||
{ 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, &leaf1_gate_lock },
|
{ 47, "timer_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 1, 0, 0, &leaf1_gate_lock },
|
||||||
{ 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, &leaf1_gate_lock },
|
{ 48, "pulse_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 2, 0, 0, &leaf1_gate_lock },
|
||||||
{ 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, &leaf1_gate_lock },
|
{ 49, "tsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 3, 0, 0, &leaf1_gate_lock },
|
||||||
{ 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, &leaf1_gate_lock },
|
{ 50, "tsc_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 21, 0, 0, &leaf1_gate_lock },
|
||||||
{ 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, &leaf1_gate_lock },
|
{ 51, "ioctop_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 4, 0, 0, &leaf1_gate_lock },
|
||||||
{ 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, &leaf1_gate_lock },
|
{ 52, "rsc_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 5, 0, 0, &leaf1_gate_lock },
|
||||||
{ 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, &leaf1_gate_lock },
|
{ 53, "dvm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 6, CLK_UNIT_NOC_SOCKET, 7, &leaf1_gate_lock },
|
||||||
{ 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, &leaf1_gate_lock },
|
{ 54, "lvds_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 7, CLK_UNIT_NOC_SOCKET, 8, &leaf1_gate_lock },
|
||||||
{ 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, &leaf1_gate_lock },
|
{ 55, "kas_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 8, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock },
|
||||||
{ 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, &leaf1_gate_lock },
|
{ 56, "ac97_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 9, 0, 0, &leaf1_gate_lock },
|
||||||
{ 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, &leaf1_gate_lock },
|
{ 57, "usp0_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 10, CLK_UNIT_NOC_SOCKET, 4, &leaf1_gate_lock },
|
||||||
{ 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, &leaf1_gate_lock },
|
{ 58, "usp1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 11, CLK_UNIT_NOC_SOCKET, 5, &leaf1_gate_lock },
|
||||||
{ 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, &leaf1_gate_lock },
|
{ 59, "usp2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 12, CLK_UNIT_NOC_SOCKET, 6, &leaf1_gate_lock },
|
||||||
{ 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, &leaf1_gate_lock },
|
{ 60, "dmac2_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 13, CLK_UNIT_NOC_SOCKET, 1, &leaf1_gate_lock },
|
||||||
{ 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, &leaf1_gate_lock },
|
{ 61, "dmac3_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 14, CLK_UNIT_NOC_SOCKET, 2, &leaf1_gate_lock },
|
||||||
{ 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, &leaf1_gate_lock },
|
{ 62, "audioif_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 15, CLK_UNIT_NOC_SOCKET, 0, &leaf1_gate_lock },
|
||||||
{ 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, &leaf1_gate_lock },
|
{ 63, "i2s1_kas", "audmscm_kas", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 17, CLK_UNIT_NOC_CLOCK, 2, &leaf1_gate_lock },
|
||||||
{ 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, &leaf1_gate_lock },
|
{ 64, "thaudmscm_io", "audmscm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 22, 0, 0, &leaf1_gate_lock },
|
||||||
{ 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, &leaf1_gate_lock },
|
{ 65, "analogtest_xin", "audmscm_xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN1_SET, 23, 0, 0, &leaf1_gate_lock },
|
||||||
{ 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, &leaf2_gate_lock },
|
{ 66, "sys2pci_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 0, CLK_UNIT_NOC_CLOCK, 20, &leaf2_gate_lock },
|
||||||
{ 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, &leaf2_gate_lock },
|
{ 67, "pciarb_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 1, 0, 0, &leaf2_gate_lock },
|
||||||
{ 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, &leaf2_gate_lock },
|
{ 68, "pcicopy_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 2, 0, 0, &leaf2_gate_lock },
|
||||||
{ 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, &leaf2_gate_lock },
|
{ 69, "rom_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 3, 0, 0, &leaf2_gate_lock },
|
||||||
{ 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, &leaf2_gate_lock },
|
{ 70, "sdio23_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 4, 0, 0, &leaf2_gate_lock },
|
||||||
{ 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, &leaf2_gate_lock },
|
{ 71, "sdio45_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 5, 0, 0, &leaf2_gate_lock },
|
||||||
{ 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, &leaf2_gate_lock },
|
{ 72, "sdio67_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 6, 0, 0, &leaf2_gate_lock },
|
||||||
{ 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, &leaf2_gate_lock },
|
{ 73, "vip1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 7, 0, 0, &leaf2_gate_lock },
|
||||||
{ 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, &leaf2_gate_lock },
|
{ 74, "vip1_vip", "vdifm_vip", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 16, CLK_UNIT_NOC_CLOCK, 21, &leaf2_gate_lock },
|
||||||
{ 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, &leaf2_gate_lock },
|
{ 75, "sdio23_sdphy23", "vdifm_sdphy23", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 8, 0, 0, &leaf2_gate_lock },
|
||||||
{ 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, &leaf2_gate_lock },
|
{ 76, "sdio45_sdphy45", "vdifm_sdphy45", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 9, 0, 0, &leaf2_gate_lock },
|
||||||
{ 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, &leaf2_gate_lock },
|
{ 77, "sdio67_sdphy67", "vdifm_sdphy67", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 10, 0, 0, &leaf2_gate_lock },
|
||||||
{ 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, &leaf2_gate_lock },
|
{ 78, "vpp0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 11, CLK_UNIT_NOC_CLOCK, 22, &leaf2_gate_lock },
|
||||||
{ 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, &leaf2_gate_lock },
|
{ 79, "lcd0_disp0", "vdifm_disp0", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 12, CLK_UNIT_NOC_CLOCK, 18, &leaf2_gate_lock },
|
||||||
{ 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, &leaf2_gate_lock },
|
{ 80, "vpp1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 13, CLK_UNIT_NOC_CLOCK, 23, &leaf2_gate_lock },
|
||||||
{ 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, &leaf2_gate_lock },
|
{ 81, "lcd1_disp1", "vdifm_disp1", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 14, CLK_UNIT_NOC_CLOCK, 19, &leaf2_gate_lock },
|
||||||
{ 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, &leaf2_gate_lock },
|
{ 82, "dcu_deint", "vdifm_deint", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 15, CLK_UNIT_NOC_CLOCK, 17, &leaf2_gate_lock },
|
||||||
{ 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, &leaf2_gate_lock },
|
{ 83, "vdifm_dapa_r_nocr", "vdifm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 17, 0, 0, &leaf2_gate_lock },
|
||||||
{ 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, &leaf2_gate_lock },
|
{ 84, "gpio1_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 18, 0, 0, &leaf2_gate_lock },
|
||||||
{ 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, &leaf2_gate_lock },
|
{ 85, "thvdifm_io", "vdifm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN2_SET, 19, 0, 0, &leaf2_gate_lock },
|
||||||
{ 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, &leaf3_gate_lock },
|
{ 86, "gmac_rgmii", "gnssm_rgmii", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 0, 0, 0, &leaf3_gate_lock },
|
||||||
{ 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, &leaf3_gate_lock },
|
{ 87, "gmac_gmac", "gnssm_gmac", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 1, CLK_UNIT_NOC_CLOCK, 10, &leaf3_gate_lock },
|
||||||
{ 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, &leaf3_gate_lock },
|
{ 88, "uart1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 2, CLK_UNIT_NOC_SOCKET, 14, &leaf3_gate_lock },
|
||||||
{ 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, &leaf3_gate_lock },
|
{ 89, "dmac0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 3, CLK_UNIT_NOC_SOCKET, 11, &leaf3_gate_lock },
|
||||||
{ 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, &leaf3_gate_lock },
|
{ 90, "uart0_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 4, CLK_UNIT_NOC_SOCKET, 13, &leaf3_gate_lock },
|
||||||
{ 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, &leaf3_gate_lock },
|
{ 91, "uart2_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 5, CLK_UNIT_NOC_SOCKET, 15, &leaf3_gate_lock },
|
||||||
{ 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, &leaf3_gate_lock },
|
{ 92, "uart3_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 6, CLK_UNIT_NOC_SOCKET, 16, &leaf3_gate_lock },
|
||||||
{ 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, &leaf3_gate_lock },
|
{ 93, "uart4_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 7, CLK_UNIT_NOC_SOCKET, 17, &leaf3_gate_lock },
|
||||||
{ 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, &leaf3_gate_lock },
|
{ 94, "uart5_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 8, CLK_UNIT_NOC_SOCKET, 18, &leaf3_gate_lock },
|
||||||
{ 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, &leaf3_gate_lock },
|
{ 95, "spi1_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 9, CLK_UNIT_NOC_SOCKET, 12, &leaf3_gate_lock },
|
||||||
{ 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, &leaf3_gate_lock },
|
{ 96, "gnss_gnss", "gnssm_gnss", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 10, 0, 0, &leaf3_gate_lock },
|
||||||
{ 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, &leaf3_gate_lock },
|
{ 97, "canbus1_can", "gnssm_can", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 12, CLK_UNIT_NOC_CLOCK, 7, &leaf3_gate_lock },
|
||||||
{ 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, &leaf3_gate_lock },
|
{ 98, "ccsec_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 15, CLK_UNIT_NOC_CLOCK, 9, &leaf3_gate_lock },
|
||||||
{ 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, &leaf3_gate_lock },
|
{ 99, "ccpub_sec", "gnssm_sec", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 16, CLK_UNIT_NOC_CLOCK, 8, &leaf3_gate_lock },
|
||||||
{ 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, &leaf3_gate_lock },
|
{ 100, "gnssm_dapa_r_nocr", "gnssm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 13, 0, 0, &leaf3_gate_lock },
|
||||||
{ 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, &leaf3_gate_lock },
|
{ 101, "thgnssm_io", "gnssm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN3_SET, 14, 0, 0, &leaf3_gate_lock },
|
||||||
{ 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, &leaf4_gate_lock },
|
{ 102, "media_vdec", "mediam_vdec", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 0, CLK_UNIT_NOC_CLOCK, 3, &leaf4_gate_lock },
|
||||||
{ 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, &leaf4_gate_lock },
|
{ 103, "media_jpenc", "mediam_jpenc", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 1, CLK_UNIT_NOC_CLOCK, 1, &leaf4_gate_lock },
|
||||||
{ 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, &leaf4_gate_lock },
|
{ 104, "g2d_g2d", "mediam_g2d", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 2, CLK_UNIT_NOC_CLOCK, 12, &leaf4_gate_lock },
|
||||||
{ 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, &leaf4_gate_lock },
|
{ 105, "i2c0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 3, CLK_UNIT_NOC_SOCKET, 21, &leaf4_gate_lock },
|
||||||
{ 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, &leaf4_gate_lock },
|
{ 106, "i2c1_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 4, CLK_UNIT_NOC_SOCKET, 20, &leaf4_gate_lock },
|
||||||
{ 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, &leaf4_gate_lock },
|
{ 107, "gpio0_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 5, CLK_UNIT_NOC_SOCKET, 19, &leaf4_gate_lock },
|
||||||
{ 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, &leaf4_gate_lock },
|
{ 108, "nand_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 6, 0, 0, &leaf4_gate_lock },
|
||||||
{ 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, &leaf4_gate_lock },
|
{ 109, "sdio01_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 7, 0, 0, &leaf4_gate_lock },
|
||||||
{ 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, &leaf4_gate_lock },
|
{ 110, "sys2pci2_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 8, CLK_UNIT_NOC_CLOCK, 13, &leaf4_gate_lock },
|
||||||
{ 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, &leaf4_gate_lock },
|
{ 111, "sdio01_sdphy01", "mediam_sdphy01", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 9, 0, 0, &leaf4_gate_lock },
|
||||||
{ 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, &leaf4_gate_lock },
|
{ 112, "nand_nand", "mediam_nand", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 10, CLK_UNIT_NOC_CLOCK, 14, &leaf4_gate_lock },
|
||||||
{ 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, &leaf4_gate_lock },
|
{ 113, "usb0_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 11, CLK_UNIT_NOC_CLOCK, 15, &leaf4_gate_lock },
|
||||||
{ 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, &leaf4_gate_lock },
|
{ 114, "usb1_usb", "mediam_usb", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 12, CLK_UNIT_NOC_CLOCK, 16, &leaf4_gate_lock },
|
||||||
{ 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, &leaf4_gate_lock },
|
{ 115, "usbphy0_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 13, 0, 0, &leaf4_gate_lock },
|
||||||
{ 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, &leaf4_gate_lock },
|
{ 116, "usbphy1_usbphy", "mediam_usbphy", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 14, 0, 0, &leaf4_gate_lock },
|
||||||
{ 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, &leaf4_gate_lock },
|
{ 117, "thmediam_io", "mediam_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN4_SET, 15, 0, 0, &leaf4_gate_lock },
|
||||||
{ 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, &leaf5_gate_lock },
|
{ 118, "memc_mem", "mempll_clk1", CLK_IGNORE_UNUSED, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 0, 0, 0, &leaf5_gate_lock },
|
||||||
{ 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, &leaf5_gate_lock },
|
{ 119, "dapa_mem", "mempll_clk1", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 1, 0, 0, &leaf5_gate_lock },
|
||||||
{ 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, &leaf5_gate_lock },
|
{ 120, "nocddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 2, 0, 0, &leaf5_gate_lock },
|
||||||
{ 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, &leaf5_gate_lock },
|
{ 121, "thddrm_nocr", "ddrm_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN5_SET, 3, 0, 0, &leaf5_gate_lock },
|
||||||
{ 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, &leaf6_gate_lock },
|
{ 122, "spram1_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 0, CLK_UNIT_NOC_SOCKET, 9, &leaf6_gate_lock },
|
||||||
{ 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, &leaf6_gate_lock },
|
{ 123, "spram2_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 1, CLK_UNIT_NOC_SOCKET, 10, &leaf6_gate_lock },
|
||||||
{ 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, &leaf6_gate_lock },
|
{ 124, "coresight_cpudiv2", "cpum_cpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 2, 0, 0, &leaf6_gate_lock },
|
||||||
{ 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, &leaf6_gate_lock },
|
{ 125, "coresight_tpiu", "cpum_tpiu", 0, SIRFSOC_CLKC_LEAF_CLK_EN6_SET, 3, 0, 0, &leaf6_gate_lock },
|
||||||
{ 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, &leaf7_gate_lock },
|
{ 126, "graphic_gpu", "gpum_gpu", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 0, CLK_UNIT_NOC_CLOCK, 0, &leaf7_gate_lock },
|
||||||
{ 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, &leaf7_gate_lock },
|
{ 127, "vss_sdr", "gpum_sdr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 1, CLK_UNIT_NOC_CLOCK, 11, &leaf7_gate_lock },
|
||||||
{ 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, &leaf7_gate_lock },
|
{ 128, "thgpum_nocr", "gpum_nocr", 0, SIRFSOC_CLKC_LEAF_CLK_EN7_SET, 2, 0, 0, &leaf7_gate_lock },
|
||||||
{ 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, &leaf8_gate_lock },
|
{ 129, "a7ca_btss", "btm_btss", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 1, 0, 0, &leaf8_gate_lock },
|
||||||
{ 130, "dmac4_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, &leaf8_gate_lock },
|
{ 130, "dmac4_io", "a7ca_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 2, 0, 0, &leaf8_gate_lock },
|
||||||
{ 131, "uart6_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, &leaf8_gate_lock },
|
{ 131, "uart6_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 3, 0, 0, &leaf8_gate_lock },
|
||||||
{ 132, "usp3_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, &leaf8_gate_lock },
|
{ 132, "usp3_io", "dmac4_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 4, 0, 0, &leaf8_gate_lock },
|
||||||
{ 133, "a7ca_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, &leaf8_gate_lock },
|
{ 133, "a7ca_io", "noc_btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 5, 0, 0, &leaf8_gate_lock },
|
||||||
{ 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, &leaf8_gate_lock },
|
{ 134, "noc_btm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 6, 0, 0, &leaf8_gate_lock },
|
||||||
{ 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, &leaf8_gate_lock },
|
{ 135, "thbtm_io", "btm_io", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 7, 0, 0, &leaf8_gate_lock },
|
||||||
{ 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, &root1_gate_lock },
|
{ 136, "btslow", "xinw_fixdiv_btslow", 0, SIRFSOC_CLKC_ROOT_CLK_EN1_SET, 25, 0, 0, &root1_gate_lock },
|
||||||
{ 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, &leaf8_gate_lock },
|
{ 137, "a7ca_btslow", "btslow", 0, SIRFSOC_CLKC_LEAF_CLK_EN8_SET, 0, 0, 0, &leaf8_gate_lock },
|
||||||
{ 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, &leaf0_gate_lock },
|
{ 138, "pwm_io", "io_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 0, 0, 0, &leaf0_gate_lock },
|
||||||
{ 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, &leaf0_gate_lock },
|
{ 139, "pwm_xin", "xin", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 1, 0, 0, &leaf0_gate_lock },
|
||||||
{ 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, &leaf0_gate_lock },
|
{ 140, "pwm_xinw", "xinw", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 2, 0, 0, &leaf0_gate_lock },
|
||||||
{ 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, &leaf0_gate_lock },
|
{ 141, "thcgum_sys", "sys_mux", 0, SIRFSOC_CLKC_LEAF_CLK_EN0_SET, 3, 0, 0, &leaf0_gate_lock },
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)];
|
static struct clk *atlas7_clks[ARRAY_SIZE(unit_list) + ARRAY_SIZE(mux_list)];
|
||||||
|
@ -1206,20 +1221,44 @@ static int unit_clk_enable(struct clk_hw *hw)
|
||||||
|
|
||||||
spin_lock_irqsave(clk->lock, flags);
|
spin_lock_irqsave(clk->lock, flags);
|
||||||
clkc_writel(BIT(clk->bit), reg);
|
clkc_writel(BIT(clk->bit), reg);
|
||||||
|
if (clk->type == CLK_UNIT_NOC_CLOCK)
|
||||||
|
clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR);
|
||||||
|
else if (clk->type == CLK_UNIT_NOC_SOCKET)
|
||||||
|
clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_SET);
|
||||||
|
|
||||||
spin_unlock_irqrestore(clk->lock, flags);
|
spin_unlock_irqrestore(clk->lock, flags);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void unit_clk_disable(struct clk_hw *hw)
|
static void unit_clk_disable(struct clk_hw *hw)
|
||||||
{
|
{
|
||||||
u32 reg;
|
u32 reg;
|
||||||
|
u32 i = 0;
|
||||||
struct clk_unit *clk = to_unitclk(hw);
|
struct clk_unit *clk = to_unitclk(hw);
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
|
reg = clk->regofs + SIRFSOC_CLKC_ROOT_CLK_EN0_CLR - SIRFSOC_CLKC_ROOT_CLK_EN0_SET;
|
||||||
|
|
||||||
spin_lock_irqsave(clk->lock, flags);
|
spin_lock_irqsave(clk->lock, flags);
|
||||||
|
if (clk->type == CLK_UNIT_NOC_CLOCK) {
|
||||||
|
clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_SET);
|
||||||
|
while (!(clkc_readl(SIRFSOC_NOC_CLK_IDLE_STATUS) &
|
||||||
|
BIT(clk->idle_bit)) && (i++ < 100)) {
|
||||||
|
cpu_relax();
|
||||||
|
udelay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 100) {
|
||||||
|
pr_err("unit NoC Clock disconnect Error:timeout\n");
|
||||||
|
/*once timeout, undo idlereq by CLR*/
|
||||||
|
clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_IDLEREQ_CLR);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (clk->type == CLK_UNIT_NOC_SOCKET)
|
||||||
|
clkc_writel(BIT(clk->idle_bit), SIRFSOC_NOC_CLK_SLVRDY_CLR);
|
||||||
|
|
||||||
clkc_writel(BIT(clk->bit), reg);
|
clkc_writel(BIT(clk->bit), reg);
|
||||||
|
err:
|
||||||
spin_unlock_irqrestore(clk->lock, flags);
|
spin_unlock_irqrestore(clk->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1232,7 +1271,7 @@ static const struct clk_ops unit_clk_ops = {
|
||||||
static struct clk * __init
|
static struct clk * __init
|
||||||
atlas7_unit_clk_register(struct device *dev, const char *name,
|
atlas7_unit_clk_register(struct device *dev, const char *name,
|
||||||
const char * const parent_name, unsigned long flags,
|
const char * const parent_name, unsigned long flags,
|
||||||
u32 regofs, u8 bit, spinlock_t *lock)
|
u32 regofs, u8 bit, u32 type, u8 idle_bit, spinlock_t *lock)
|
||||||
{
|
{
|
||||||
struct clk *clk;
|
struct clk *clk;
|
||||||
struct clk_unit *unit;
|
struct clk_unit *unit;
|
||||||
|
@ -1251,6 +1290,9 @@ atlas7_unit_clk_register(struct device *dev, const char *name,
|
||||||
unit->hw.init = &init;
|
unit->hw.init = &init;
|
||||||
unit->regofs = regofs;
|
unit->regofs = regofs;
|
||||||
unit->bit = bit;
|
unit->bit = bit;
|
||||||
|
|
||||||
|
unit->type = type;
|
||||||
|
unit->idle_bit = idle_bit;
|
||||||
unit->lock = lock;
|
unit->lock = lock;
|
||||||
|
|
||||||
clk = clk_register(dev, &unit->hw);
|
clk = clk_register(dev, &unit->hw);
|
||||||
|
@ -1624,7 +1666,7 @@ static void __init atlas7_clk_init(struct device_node *np)
|
||||||
for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
|
for (i = 0; i < ARRAY_SIZE(unit_list); i++) {
|
||||||
unit = &unit_list[i];
|
unit = &unit_list[i];
|
||||||
atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
|
atlas7_clks[i] = atlas7_unit_clk_register(NULL, unit->unit_name, unit->parent_name,
|
||||||
unit->flags, unit->regofs, unit->bit, unit->lock);
|
unit->flags, unit->regofs, unit->bit, unit->type, unit->idle_bit, unit->lock);
|
||||||
BUG_ON(!atlas7_clks[i]);
|
BUG_ON(!atlas7_clks[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,7 @@ static void __init st_of_flexgen_setup(struct device_node *np)
|
||||||
int num_parents, i;
|
int num_parents, i;
|
||||||
spinlock_t *rlock = NULL;
|
spinlock_t *rlock = NULL;
|
||||||
unsigned long flex_flags = 0;
|
unsigned long flex_flags = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
pnode = of_get_parent(np);
|
pnode = of_get_parent(np);
|
||||||
if (!pnode)
|
if (!pnode)
|
||||||
|
@ -285,13 +286,13 @@ static void __init st_of_flexgen_setup(struct device_node *np)
|
||||||
if (!clk_data)
|
if (!clk_data)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
clk_data->clk_num = of_property_count_strings(np ,
|
ret = of_property_count_strings(np, "clock-output-names");
|
||||||
"clock-output-names");
|
if (ret <= 0) {
|
||||||
if (clk_data->clk_num <= 0) {
|
|
||||||
pr_err("%s: Failed to get number of output clocks (%d)",
|
pr_err("%s: Failed to get number of output clocks (%d)",
|
||||||
__func__, clk_data->clk_num);
|
__func__, clk_data->clk_num);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
clk_data->clk_num = ret;
|
||||||
|
|
||||||
clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
|
clk_data->clks = kcalloc(clk_data->clk_num, sizeof(struct clk *),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/clk-provider.h>
|
#include <linux/clk-provider.h>
|
||||||
|
#include "clkgen.h"
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(clkgena_divmux_lock);
|
static DEFINE_SPINLOCK(clkgena_divmux_lock);
|
||||||
static DEFINE_SPINLOCK(clkgenf_lock);
|
static DEFINE_SPINLOCK(clkgenf_lock);
|
||||||
|
@ -576,6 +577,7 @@ static struct clkgen_mux_data stih415_a9_mux_data = {
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
.shift = 1,
|
.shift = 1,
|
||||||
.width = 2,
|
.width = 2,
|
||||||
|
.lock = &clkgen_a9_lock,
|
||||||
};
|
};
|
||||||
static struct clkgen_mux_data stih416_a9_mux_data = {
|
static struct clkgen_mux_data stih416_a9_mux_data = {
|
||||||
.offset = 0,
|
.offset = 0,
|
||||||
|
@ -586,6 +588,7 @@ static struct clkgen_mux_data stih407_a9_mux_data = {
|
||||||
.offset = 0x1a4,
|
.offset = 0x1a4,
|
||||||
.shift = 0,
|
.shift = 0,
|
||||||
.width = 2,
|
.width = 2,
|
||||||
|
.lock = &clkgen_a9_lock,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id mux_of_match[] = {
|
static const struct of_device_id mux_of_match[] = {
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue