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:
Linus Torvalds 2015-11-05 12:59:36 -08:00
commit f66477a0ae
144 changed files with 8457 additions and 1035 deletions

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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>;
};

View File

@ -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>;
};
};

View File

@ -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>;
};

View File

@ -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

View File

@ -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:

View File

@ -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";
};

View File

@ -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";
};

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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.

View File

@ -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/

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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);

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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;

288
drivers/clk/bcm/clk-ns2.c Normal file
View File

@ -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);

139
drivers/clk/bcm/clk-nsp.c Normal file
View File

@ -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);

View File

@ -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 },

View File

@ -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 },
}; };

View File

@ -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");
}

View File

@ -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;

View File

@ -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;

View File

@ -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");

View File

@ -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);

379
drivers/clk/clk-si514.c Normal file
View File

@ -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");

View File

@ -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)

View File

@ -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))

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;
} }

View File

@ -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);

View File

@ -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;
} }

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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]);

View File

@ -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);

View File

@ -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;

View File

@ -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));

View File

@ -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);

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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

View File

@ -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;
}

View File

@ -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,

View File

@ -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);

View File

@ -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)
{ {

View File

@ -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);

View File

@ -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);
} }

View File

@ -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;

View File

@ -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) {

View File

@ -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,

View File

@ -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 = {

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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);
} }

View File

@ -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");

View File

@ -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

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;
} }

View File

@ -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,

237
drivers/clk/qcom/gdsc.c Normal file
View File

@ -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);
}

68
drivers/clk/qcom/gdsc.h Normal file
View File

@ -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__ */

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
} }
} }

View File

@ -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;

View File

@ -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),
}; };

View File

@ -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;
} }

View File

@ -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 } },

View File

@ -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]);
} }

View File

@ -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);

View File

@ -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