We have a small collection of core framework updates this time, mostly around

clk registration by clk providers and debugfs "nice to haves" for rate
 constraints. I'll highlight that we're now setting the clk_init_data pointer
 inside struct clk_hw to NULL during clk_register(), which may break some
 drivers that thought they could use that pointer during normal operations. That
 change has been sitting in next for a while now but maybe something is still
 broken. We'l see. Other than that the core framework changes aren't invasive
 and they're fixing bugs, simplifying, and making things better.
 
 On the clk driver side we got the usual addition of new SoC support, new
 features for existing drivers, and bug fixes scattered throughout. The biggest
 diffstat is the Amlogic driver that gained CPU clk support in addition to
 migrating to the new way of specifying clk parents. After that the Qualcomm,
 i.MX, Mediatek, and Rockchip clk drivers got support for various new SoCs and
 clock controllers from those vendors.
 
 Core:
  - Drop NULL checks in clk debugfs
  - Add min/max rates to clk debugfs
  - Set clk_init_data pointer inside clk_hw to NULL after registration
  - Make clk_bulk_get_all() return an 'id' corresponding to clock-names
  - Evict parents from parent cache when they're unregistered
 
 New Drivers:
  - Add clock driver for i.MX8MN SoCs
  - Support aspeed AST2600 SoCs
  - Support for Mediatek MT6779 SoCs
  - Support qcom SM8150 GCC and RPMh clks
  - Support qcom QCS404 WCSS clks
  - Add CPU clock support for Armada 7K/8K (specifically AP806 and AP807)
  - Addition of clock driver for Rockchip rk3308 SoCs
 
 Updates:
  - Add regulator support to the cdce925 clk driver
  - Add support for Raspberry Pi 4 bcm2711 SoCs
  - Add SDIO gate support to aspeed driver
  - Add missing of_node_put() calls in various clk drivers
  - Migrate Amlogic driver to new clock parent description method
  - Add DVFS support to Amlogic Meson g12
  - Add Amlogic Meson g12a reset support to the axg audio clock controller
  - Add sm1 support to the Amlogic Meson g12a clock controller
  - Switch i.MX8MM clock driver to platform driver
  - Add Hifi4 DSP related clocks for i.MX8QXP SoC
  - Fix Audio PLL setting and parent clock for USB
  - Misc i.MX8 clock driver improvements and corrections
  - Set floor ops for Qualcomm SD clks so that rounding works
  - Fix "always-on" Clock Domains on Renesas R-Car M1A, RZ/A1, RZ/A2, and RZ/N1
  - Enable the Allwinner V3 SoC and fix the i2s clock for H6
 -----BEGIN PGP SIGNATURE-----
 
 iQJFBAABCAAvFiEE9L57QeeUxqYDyoaDrQKIl8bklSUFAl2FQEMRHHNib3lkQGtl
 cm5lbC5vcmcACgkQrQKIl8bklSXHQw//XHnT5DPphpP8ua4x8wuJARdf0n58Vcdb
 8fZxxs4QN7uuKhg6aMI4kgwBn+9tgIr65hvN0Gn9Wm5Bsbs3XZvdIo7DvQDrYg7W
 NE7192iy2Dg+m+C24YLO7ceZgqVepbjeN+6oeUK88Ui+H+XlOKfJvjfnJ+HxN9Ip
 sHnLakIxqlaWvzwTUOHOcsrHyQD2OXupbfNMxLnmr8T/kBh/nqwNEG3aYCppICsg
 LpJL9Bv2V3QSk8uBszTgKK5ybWo14aDQPx4rrhgsneD0h7DSnx6M3jvngxMra6W0
 fnare4FQlkbPmgAj+XtB7RdCzsuwoke/7TJsvDLQrEbyOYTGnl7bYS8NOSrIg5Tp
 w4UPpXrMTQK7e/6okL1OJYAXXYurxep8QjsjpF3nahxC3IVzAZ9uio6ehJrDNEPC
 ErqOSPQTMkjOA2npovsQKCH3Mv/yGzAigpsQassPneWwp//NupMLKmmIm6645Xw2
 6kqSlVFYz81lhzIylGEQKIoiLcszpB6qqWUzGVt0B94joRbvg0m//8BDaZbHeTqP
 m/acRYHRC1utpkAZEnBZRsd79cI+EeuARROUfGsoUMfOueTc4+qQ7Yrjbj4rTvnC
 lLM9Qz9h1QkfyRF1IHHPw/fS5twpNTUdO9c1+3qzS3AQfl5dZWpChoF9Um+ycVPR
 nQrpk05pHEY=
 =z8wK
 -----END PGP SIGNATURE-----

Merge tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux

Pull clk updates from Stephen Boyd:
 "We have a small collection of core framework updates this time, mostly
  around clk registration by clk providers and debugfs "nice to haves"
  for rate constraints. I'll highlight that we're now setting the
  clk_init_data pointer inside struct clk_hw to NULL during
  clk_register(), which may break some drivers that thought they could
  use that pointer during normal operations. That change has been
  sitting in next for a while now but maybe something is still broken.
  We'l see. Other than that the core framework changes aren't invasive
  and they're fixing bugs, simplifying, and making things better.

  On the clk driver side we got the usual addition of new SoC support,
  new features for existing drivers, and bug fixes scattered throughout.
  The biggest diffstat is the Amlogic driver that gained CPU clk support
  in addition to migrating to the new way of specifying clk parents.
  After that the Qualcomm, i.MX, Mediatek, and Rockchip clk drivers got
  support for various new SoCs and clock controllers from those vendors.

  Core:
   - Drop NULL checks in clk debugfs
   - Add min/max rates to clk debugfs
   - Set clk_init_data pointer inside clk_hw to NULL after registration
   - Make clk_bulk_get_all() return an 'id' corresponding to clock-names
   - Evict parents from parent cache when they're unregistered

  New Drivers:
   - Add clock driver for i.MX8MN SoCs
   - Support aspeed AST2600 SoCs
   - Support for Mediatek MT6779 SoCs
   - Support qcom SM8150 GCC and RPMh clks
   - Support qcom QCS404 WCSS clks
   - Add CPU clock support for Armada 7K/8K (specifically AP806 and AP807)
   - Addition of clock driver for Rockchip rk3308 SoCs

  Updates:
   - Add regulator support to the cdce925 clk driver
   - Add support for Raspberry Pi 4 bcm2711 SoCs
   - Add SDIO gate support to aspeed driver
   - Add missing of_node_put() calls in various clk drivers
   - Migrate Amlogic driver to new clock parent description method
   - Add DVFS support to Amlogic Meson g12
   - Add Amlogic Meson g12a reset support to the axg audio clock controller
   - Add sm1 support to the Amlogic Meson g12a clock controller
   - Switch i.MX8MM clock driver to platform driver
   - Add Hifi4 DSP related clocks for i.MX8QXP SoC
   - Fix Audio PLL setting and parent clock for USB
   - Misc i.MX8 clock driver improvements and corrections
   - Set floor ops for Qualcomm SD clks so that rounding works
   - Fix "always-on" Clock Domains on Renesas R-Car M1A, RZ/A1, RZ/A2, and RZ/N1
   - Enable the Allwinner V3 SoC and fix the i2s clock for H6"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (137 commits)
  clk: Drop !clk checks in debugfs dumping
  clk: imx: imx8mn: fix pll mux bit
  clk: imx: imx8mm: fix pll mux bit
  clk: imx: clk-pll14xx: unbypass PLL by default
  clk: imx: pll14xx: avoid glitch when set rate
  clk: mvebu: ap80x: add AP807 clock support
  clk: mvebu: ap806: Prepare the introduction of AP807 clock support
  clk: mvebu: ap806: add AP-DCLK (hclk) to system controller driver
  clk: mvebu: ap806: be more explicit on what SaR is
  clk: mvebu: ap80x-cpu: add AP807 CPU clock support
  clk: mvebu: ap806-cpu: prepare mapping of AP807 CPU clock
  dt-bindings: ap806: Document AP807 clock compatible
  dt-bindings: ap80x: Document AP807 CPU clock compatible
  clk: sprd: add missing kfree
  clk: at91: allow 24 Mhz clock as input for PLL
  clk: Make clk_bulk_get_all() return a valid "id"
  clk: actions: Fix factor clk struct member access
  clk: qcom: rcg: Return failure for RCG update
  clk: remove extra ---help--- tags in Kconfig
  clk: add include guard to clk-conf.h
  ...
This commit is contained in:
Linus Torvalds 2019-09-20 15:45:07 -07:00
commit a703d279c5
137 changed files with 11399 additions and 638 deletions

View File

@ -18,17 +18,19 @@ Clocks:
-------
The Device Tree node representing the AP806 system controller provides
a number of clocks:
The Device Tree node representing the AP806/AP807 system controller
provides a number of clocks:
- 0: clock of CPU cluster 0
- 1: clock of CPU cluster 1
- 0: reference clock of CPU cluster 0
- 1: reference clock of CPU cluster 1
- 2: fixed PLL at 1200 Mhz
- 3: MSS clock, derived from the fixed PLL
Required properties:
- compatible: must be: "marvell,ap806-clock"
- compatible: must be one of:
* "marvell,ap806-clock"
* "marvell,ap807-clock"
- #clock-cells: must be set to 1
Pinctrl:
@ -143,3 +145,33 @@ ap_syscon1: system-controller@6f8000 {
#thermal-sensor-cells = <1>;
};
};
Cluster clocks:
---------------
Device Tree Clock bindings for cluster clock of Marvell
AP806/AP807. Each cluster contain up to 2 CPUs running at the same
frequency.
Required properties:
- compatible: must be one of:
* "marvell,ap806-cpu-clock"
* "marvell,ap807-cpu-clock"
- #clock-cells : should be set to 1.
- clocks : shall be the input parent clock(s) phandle for the clock
(one per cluster)
- reg: register range associated with the cluster clocks
ap_syscon1: system-controller@6f8000 {
compatible = "marvell,armada-ap806-syscon1", "syscon", "simple-mfd";
reg = <0x6f8000 0x1000>;
cpu_clk: clock-cpu@278 {
compatible = "marvell,ap806-cpu-clock";
clocks = <&ap_clk 0>, <&ap_clk 1>;
#clock-cells = <1>;
reg = <0x278 0xa30>;
};
};

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-apmixedsys"
- "mediatek,mt2712-apmixedsys", "syscon"
- "mediatek,mt6779-apmixedsys", "syscon"
- "mediatek,mt6797-apmixedsys"
- "mediatek,mt7622-apmixedsys"
- "mediatek,mt7623-apmixedsys", "mediatek,mt2701-apmixedsys"

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt6779-audio", "syscon"
- "mediatek,mt7622-audsys", "syscon"
- "mediatek,mt7623-audsys", "mediatek,mt2701-audsys", "syscon"
- "mediatek,mt8183-audiosys", "syscon"

View File

@ -6,6 +6,7 @@ The MediaTek camsys controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt6779-camsys", "syscon"
- "mediatek,mt8183-camsys", "syscon"
- #clock-cells: Must be 1

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt2712-imgsys", "syscon"
- "mediatek,mt6779-imgsys", "syscon"
- "mediatek,mt6797-imgsys", "syscon"
- "mediatek,mt7623-imgsys", "mediatek,mt2701-imgsys", "syscon"
- "mediatek,mt8173-imgsys", "syscon"

View File

@ -9,6 +9,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-infracfg", "syscon"
- "mediatek,mt2712-infracfg", "syscon"
- "mediatek,mt6779-infracfg_ao", "syscon"
- "mediatek,mt6797-infracfg", "syscon"
- "mediatek,mt7622-infracfg", "syscon"
- "mediatek,mt7623-infracfg", "mediatek,mt2701-infracfg", "syscon"

View File

@ -0,0 +1,22 @@
Mediatek ipesys controller
============================
The Mediatek ipesys controller provides various clocks to the system.
Required Properties:
- compatible: Should be one of:
- "mediatek,mt6779-ipesys", "syscon"
- #clock-cells: Must be 1
The ipesys 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:
ipesys: clock-controller@1b000000 {
compatible = "mediatek,mt6779-ipesys", "syscon";
reg = <0 0x1b000000 0 0x1000>;
#clock-cells = <1>;
};

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-mfgcfg", "syscon"
- "mediatek,mt6779-mfgcfg", "syscon"
- "mediatek,mt8183-mfgcfg", "syscon"
- #clock-cells: Must be 1

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt2712-mmsys", "syscon"
- "mediatek,mt6779-mmsys", "syscon"
- "mediatek,mt6797-mmsys", "syscon"
- "mediatek,mt7623-mmsys", "mediatek,mt2701-mmsys", "syscon"
- "mediatek,mt8173-mmsys", "syscon"

View File

@ -14,6 +14,7 @@ Required Properties:
- "mediatek,mt7629-pericfg", "syscon"
- "mediatek,mt8135-pericfg", "syscon"
- "mediatek,mt8173-pericfg", "syscon"
- "mediatek,mt8183-pericfg", "syscon"
- #clock-cells: Must be 1
- #reset-cells: Must be 1

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-topckgen"
- "mediatek,mt2712-topckgen", "syscon"
- "mediatek,mt6779-topckgen", "syscon"
- "mediatek,mt6797-topckgen"
- "mediatek,mt7622-topckgen"
- "mediatek,mt7623-topckgen", "mediatek,mt2701-topckgen"

View File

@ -8,6 +8,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt2712-vdecsys", "syscon"
- "mediatek,mt6779-vdecsys", "syscon"
- "mediatek,mt6797-vdecsys", "syscon"
- "mediatek,mt7623-vdecsys", "mediatek,mt2701-vdecsys", "syscon"
- "mediatek,mt8173-vdecsys", "syscon"

View File

@ -7,6 +7,7 @@ Required Properties:
- compatible: Should be one of:
- "mediatek,mt2712-vencsys", "syscon"
- "mediatek,mt6779-vencsys", "syscon"
- "mediatek,mt6797-vencsys", "syscon"
- "mediatek,mt8173-vencsys", "syscon"
- "mediatek,mt8183-vencsys", "syscon"

View File

@ -31,6 +31,7 @@ properties:
- allwinner,sun8i-h3-ccu
- allwinner,sun8i-h3-r-ccu
- allwinner,sun8i-r40-ccu
- allwinner,sun8i-v3-ccu
- allwinner,sun8i-v3s-ccu
- allwinner,sun9i-a80-ccu
- allwinner,sun50i-a64-ccu

View File

@ -12,7 +12,9 @@ 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"
- compatible: should be one of the following,
"brcm,bcm2711-cprman"
"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

View File

@ -23,6 +23,7 @@ Required properties :
"qcom,gcc-sdm630"
"qcom,gcc-sdm660"
"qcom,gcc-sdm845"
"qcom,gcc-sm8150"
- reg : shall contain base register location and length
- #clock-cells : shall contain 1
@ -38,6 +39,13 @@ Documentation/devicetree/bindings/thermal/qcom-tsens.txt
- protected-clocks : Protected clock specifier list as per common clock
binding.
For SM8150 only:
- clocks: a list of phandles and clock-specifier pairs,
one for each entry in clock-names.
- clock-names: "bi_tcxo" (required)
"sleep_clk" (optional)
"aud_ref_clock" (optional)
Example:
clock-controller@900000 {
compatible = "qcom,gcc-msm8960";
@ -71,3 +79,16 @@ Example of GCC with protected-clocks properties:
<GCC_LPASS_Q6_AXI_CLK>,
<GCC_LPASS_SWAY_CLK>;
};
Example of GCC with clocks
gcc: clock-controller@100000 {
compatible = "qcom,gcc-sm8150";
reg = <0x00100000 0x1f0000>;
#clock-cells = <1>;
#reset-cells = <1>;
#power-domain-cells = <1>;
clock-names = "bi_tcxo",
"sleep_clk";
clocks = <&rpmcc RPM_SMD_XO_CLK_SRC>,
<&sleep_clk>;
};

View File

@ -6,9 +6,14 @@ some Qualcomm Technologies Inc. SoCs. It accepts clock requests from
other hardware subsystems via RSC to control clocks.
Required properties :
- compatible : shall contain "qcom,sdm845-rpmh-clk"
- compatible : must be one of:
"qcom,sdm845-rpmh-clk"
"qcom,sm8150-rpmh-clk"
- #clock-cells : must contain 1
- clocks: a list of phandles and clock-specifier pairs,
one for each entry in clock-names.
- clock-names: Parent board clock: "xo".
Example :

View File

@ -0,0 +1,60 @@
* Rockchip RK3308 Clock and Reset Unit
The RK3308 clock controller generates and supplies clock to various
controllers within the SoC and also implements a reset controller for SoC
peripherals.
Required Properties:
- compatible: CRU should be "rockchip,rk3308-cru"
- reg: physical base address of the controller and length of memory mapped
region.
- #clock-cells: should be 1.
- #reset-cells: should be 1.
Optional Properties:
- rockchip,grf: phandle to the syscon managing the "general register files"
If missing, pll rates are not changeable, due to the missing pll lock status.
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clocks are defined as
preprocessor macros in the dt-bindings/clock/rk3308-cru.h headers and can be
used in device tree sources. Similar macros exist for the reset sources in
these files.
External clocks:
There are several clocks that are generated outside the SoC. It is expected
that they are defined using standard clock bindings with following
clock-output-names:
- "xin24m" - crystal input - required,
- "xin32k" - rtc clock - optional,
- "mclk_i2s0_8ch_in", "mclk_i2s1_8ch_in", "mclk_i2s2_8ch_in",
"mclk_i2s3_8ch_in", "mclk_i2s0_2ch_in",
"mclk_i2s1_2ch_in" - external I2S or SPDIF clock - optional,
- "mac_clkin" - external MAC clock - optional
Example: Clock controller node:
cru: clock-controller@ff500000 {
compatible = "rockchip,rk3308-cru";
reg = <0x0 0xff500000 0x0 0x1000>;
rockchip,grf = <&grf>;
#clock-cells = <1>;
#reset-cells = <1>;
};
Example: UART controller node that consumes the clock generated by the clock
controller:
uart0: serial@ff0a0000 {
compatible = "rockchip,rk3308-uart", "snps,dw-apb-uart";
reg = <0x0 0xff0a0000 0x0 0x100>;
interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
clock-names = "baudclk", "apb_pclk";
reg-shift = <2>;
reg-io-width = <4>;
status = "disabled";
};

View File

@ -24,6 +24,8 @@ Required properties:
Optional properties:
- xtal-load-pf: Crystal load-capacitor value to fine-tune performance on a
board, or to compensate for external influences.
- vdd-supply: A regulator node for Vdd
- vddout-supply: A regulator node for Vddout
For all PLL1, PLL2, ... an optional child node can be used to specify spread
spectrum clocking parameters for a board.
@ -41,6 +43,8 @@ Example:
clocks = <&xtal_27Mhz>;
#clock-cells = <1>;
xtal-load-pf = <5>;
vdd-supply = <&1v8-reg>;
vddout-supply = <&3v3-reg>;
/* PLL options to get SSC 1% centered */
PLL2 {
spread-spectrum = <4>;

View File

@ -116,7 +116,6 @@ config COMMON_CLK_SI514
depends on OF
select REGMAP_I2C
help
---help---
This driver supports the Silicon Labs 514 programmable clock
generator.
@ -125,7 +124,6 @@ config COMMON_CLK_SI544
depends on I2C
select REGMAP_I2C
help
---help---
This driver supports the Silicon Labs 544 programmable clock
generator.
@ -135,7 +133,6 @@ config COMMON_CLK_SI570
depends on OF
select REGMAP_I2C
help
---help---
This driver supports Silicon Labs 570/571/598/599 programmable
clock generators.
@ -153,7 +150,6 @@ config COMMON_CLK_CDCE925
depends on OF
select REGMAP_I2C
help
---help---
This driver supports the TI CDCE913/925/937/949 programmable clock
synthesizer. Each chip has different number of PLLs and outputs.
For example, the CDCE925 contains two PLLs with spread-spectrum
@ -212,7 +208,6 @@ config COMMON_CLK_AXI_CLKGEN
tristate "AXI clkgen driver"
depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
help
---help---
Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
FPGAs. It is commonly used in Analog Devices' reference designs.
@ -279,26 +274,22 @@ config COMMON_CLK_VC5
depends on OF
select REGMAP_I2C
help
---help---
This driver supports the IDT VersaClock 5 and VersaClock 6
programmable clock generators.
config COMMON_CLK_STM32MP157
def_bool COMMON_CLK && MACH_STM32MP157
help
---help---
Support for stm32mp157 SoC family clocks
config COMMON_CLK_STM32F
def_bool COMMON_CLK && (MACH_STM32F429 || MACH_STM32F469 || MACH_STM32F746)
help
---help---
Support for stm32f4 and stm32f7 SoC families clocks
config COMMON_CLK_STM32H7
def_bool COMMON_CLK && MACH_STM32H743
help
---help---
Support for stm32h7 SoC family clocks
config COMMON_CLK_BD718XX

View File

@ -30,6 +30,7 @@ obj-$(CONFIG_ARCH_EFM32) += clk-efm32gg.o
obj-$(CONFIG_COMMON_CLK_FIXED_MMIO) += clk-fixed-mmio.o
obj-$(CONFIG_COMMON_CLK_GEMINI) += clk-gemini.o
obj-$(CONFIG_COMMON_CLK_ASPEED) += clk-aspeed.o
obj-$(CONFIG_MACH_ASPEED_G6) += clk-ast2600.o
obj-$(CONFIG_ARCH_HIGHBANK) += clk-highbank.o
obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
obj-$(CONFIG_COMMON_CLK_LOCHNAGAR) += clk-lochnagar.o

View File

@ -68,16 +68,17 @@ int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks)
struct clk_hw *hw;
for (i = 0; i < hw_clks->num; i++) {
const char *name;
hw = hw_clks->hws[i];
if (IS_ERR_OR_NULL(hw))
continue;
name = hw->init->name;
ret = devm_clk_hw_register(dev, hw);
if (ret) {
dev_err(dev, "Couldn't register clock %d - %s\n",
i, hw->init->name);
i, name);
return ret;
}
}

View File

@ -64,11 +64,10 @@ static unsigned int _get_table_val(const struct clk_factor_table *table,
return val;
}
static int clk_val_best(struct clk_hw *hw, unsigned long rate,
static int owl_clk_val_best(const struct owl_factor_hw *factor_hw,
struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate)
{
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
const struct clk_factor_table *clkt = factor_hw->table;
unsigned long parent_rate, try_parent_rate, best = 0, cur_rate;
unsigned long parent_rate_saved = *best_parent_rate;
@ -126,7 +125,7 @@ long owl_factor_helper_round_rate(struct owl_clk_common *common,
const struct clk_factor_table *clkt = factor_hw->table;
unsigned int val, mul = 0, div = 1;
val = clk_val_best(&common->hw, rate, parent_rate);
val = owl_clk_val_best(factor_hw, &common->hw, rate, parent_rate);
_get_table_div_mul(clkt, val, &mul, &div);
return *parent_rate * mul / div;

View File

@ -21,6 +21,10 @@
#define MOR_KEY_MASK (0xff << 16)
#define clk_main_parent_select(s) (((s) & \
(AT91_PMC_MOSCEN | \
AT91_PMC_OSCBYPASS)) ? 1 : 0)
struct clk_main_osc {
struct clk_hw hw;
struct regmap *regmap;
@ -113,7 +117,7 @@ static int clk_main_osc_is_prepared(struct clk_hw *hw)
regmap_read(regmap, AT91_PMC_SR, &status);
return (status & AT91_PMC_MOSCS) && (tmp & AT91_PMC_MOSCEN);
return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
}
static const struct clk_ops main_osc_ops = {
@ -152,7 +156,7 @@ at91_clk_register_main_osc(struct regmap *regmap,
if (bypass)
regmap_update_bits(regmap,
AT91_CKGR_MOR, MOR_KEY_MASK |
AT91_PMC_MOSCEN,
AT91_PMC_OSCBYPASS,
AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
hw = &osc->hw;
@ -450,7 +454,7 @@ static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
return status & AT91_PMC_MOSCEN ? 1 : 0;
return clk_main_parent_select(status);
}
static const struct clk_ops sam9x5_main_ops = {
@ -492,7 +496,7 @@ at91_clk_register_sam9x5_main(struct regmap *regmap,
clkmain->hw.init = &init;
clkmain->regmap = regmap;
regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
clkmain->parent = status & AT91_PMC_MOSCEN ? 1 : 0;
clkmain->parent = clk_main_parent_select(status);
hw = &clkmain->hw;
ret = clk_hw_register(NULL, &clkmain->hw);

View File

@ -21,7 +21,7 @@ static const struct clk_range plla_outputs[] = {
};
static const struct clk_pll_characteristics plla_characteristics = {
.input = { .min = 12000000, .max = 12000000 },
.input = { .min = 12000000, .max = 24000000 },
.num_output = ARRAY_SIZE(plla_outputs),
.output = plla_outputs,
.icpll = plla_icpll,

View File

@ -31,7 +31,7 @@
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <dt-bindings/clock/bcm2835.h>
@ -114,6 +114,8 @@
#define CM_AVEODIV 0x1bc
#define CM_EMMCCTL 0x1c0
#define CM_EMMCDIV 0x1c4
#define CM_EMMC2CTL 0x1d0
#define CM_EMMC2DIV 0x1d4
/* General bits for the CM_*CTL regs */
# define CM_ENABLE BIT(4)
@ -289,6 +291,10 @@
#define LOCK_TIMEOUT_NS 100000000
#define BCM2835_MAX_FB_RATE 1750000000u
#define SOC_BCM2835 BIT(0)
#define SOC_BCM2711 BIT(1)
#define SOC_ALL (SOC_BCM2835 | SOC_BCM2711)
/*
* Names of clocks used within the driver that need to be replaced
* with an external parent's name. This array is in the order that
@ -320,6 +326,10 @@ struct bcm2835_cprman {
struct clk_hw_onecell_data onecell;
};
struct cprman_plat_data {
unsigned int soc;
};
static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
{
writel(CM_PASSWORD | val, cprman->regs + reg);
@ -1451,22 +1461,28 @@ typedef struct clk_hw *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
const void *data);
struct bcm2835_clk_desc {
bcm2835_clk_register clk_register;
unsigned int supported;
const void *data;
};
/* assignment helper macros for different clock types */
#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
.data = __VA_ARGS__ }
#define REGISTER_PLL(...) _REGISTER(&bcm2835_register_pll, \
#define _REGISTER(f, s, ...) { .clk_register = (bcm2835_clk_register)f, \
.supported = s, \
.data = __VA_ARGS__ }
#define REGISTER_PLL(s, ...) _REGISTER(&bcm2835_register_pll, \
s, \
&(struct bcm2835_pll_data) \
{__VA_ARGS__})
#define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \
&(struct bcm2835_pll_divider_data) \
{__VA_ARGS__})
#define REGISTER_CLK(...) _REGISTER(&bcm2835_register_clock, \
#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
s, \
&(struct bcm2835_pll_divider_data) \
{__VA_ARGS__})
#define REGISTER_CLK(s, ...) _REGISTER(&bcm2835_register_clock, \
s, \
&(struct bcm2835_clock_data) \
{__VA_ARGS__})
#define REGISTER_GATE(...) _REGISTER(&bcm2835_register_gate, \
#define REGISTER_GATE(s, ...) _REGISTER(&bcm2835_register_gate, \
s, \
&(struct bcm2835_gate_data) \
{__VA_ARGS__})
@ -1480,7 +1496,8 @@ static const char *const bcm2835_clock_osc_parents[] = {
"testdebug1"
};
#define REGISTER_OSC_CLK(...) REGISTER_CLK( \
#define REGISTER_OSC_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), \
.parents = bcm2835_clock_osc_parents, \
__VA_ARGS__)
@ -1497,7 +1514,8 @@ static const char *const bcm2835_clock_per_parents[] = {
"pllh_aux",
};
#define REGISTER_PER_CLK(...) REGISTER_CLK( \
#define REGISTER_PER_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \
.parents = bcm2835_clock_per_parents, \
__VA_ARGS__)
@ -1522,7 +1540,8 @@ static const char *const bcm2835_pcm_per_parents[] = {
"-",
};
#define REGISTER_PCM_CLK(...) REGISTER_CLK( \
#define REGISTER_PCM_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents), \
.parents = bcm2835_pcm_per_parents, \
__VA_ARGS__)
@ -1541,7 +1560,8 @@ static const char *const bcm2835_clock_vpu_parents[] = {
"pllc_core2",
};
#define REGISTER_VPU_CLK(...) REGISTER_CLK( \
#define REGISTER_VPU_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), \
.parents = bcm2835_clock_vpu_parents, \
__VA_ARGS__)
@ -1577,12 +1597,14 @@ static const char *const bcm2835_clock_dsi1_parents[] = {
"dsi1_byte_inv",
};
#define REGISTER_DSI0_CLK(...) REGISTER_CLK( \
#define REGISTER_DSI0_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents), \
.parents = bcm2835_clock_dsi0_parents, \
__VA_ARGS__)
#define REGISTER_DSI1_CLK(...) REGISTER_CLK( \
#define REGISTER_DSI1_CLK(s, ...) REGISTER_CLK( \
s, \
.num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \
.parents = bcm2835_clock_dsi1_parents, \
__VA_ARGS__)
@ -1602,6 +1624,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* AUDIO domain is on.
*/
[BCM2835_PLLA] = REGISTER_PLL(
SOC_ALL,
.name = "plla",
.cm_ctrl_reg = CM_PLLA,
.a2w_ctrl_reg = A2W_PLLA_CTRL,
@ -1616,6 +1639,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.max_rate = 2400000000u,
.max_fb_rate = BCM2835_MAX_FB_RATE),
[BCM2835_PLLA_CORE] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plla_core",
.source_pll = "plla",
.cm_reg = CM_PLLA,
@ -1625,6 +1649,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plla_per",
.source_pll = "plla",
.cm_reg = CM_PLLA,
@ -1634,6 +1659,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plla_dsi0",
.source_pll = "plla",
.cm_reg = CM_PLLA,
@ -1642,6 +1668,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.hold_mask = CM_PLLA_HOLDDSI0,
.fixed_divider = 1),
[BCM2835_PLLA_CCP2] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plla_ccp2",
.source_pll = "plla",
.cm_reg = CM_PLLA,
@ -1663,6 +1690,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* AUDIO domain is on.
*/
[BCM2835_PLLC] = REGISTER_PLL(
SOC_ALL,
.name = "pllc",
.cm_ctrl_reg = CM_PLLC,
.a2w_ctrl_reg = A2W_PLLC_CTRL,
@ -1677,6 +1705,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.max_rate = 3000000000u,
.max_fb_rate = BCM2835_MAX_FB_RATE),
[BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "pllc_core0",
.source_pll = "pllc",
.cm_reg = CM_PLLC,
@ -1686,6 +1715,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "pllc_core1",
.source_pll = "pllc",
.cm_reg = CM_PLLC,
@ -1695,6 +1725,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "pllc_core2",
.source_pll = "pllc",
.cm_reg = CM_PLLC,
@ -1704,6 +1735,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLC_PER] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "pllc_per",
.source_pll = "pllc",
.cm_reg = CM_PLLC,
@ -1720,6 +1752,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* AUDIO domain is on.
*/
[BCM2835_PLLD] = REGISTER_PLL(
SOC_ALL,
.name = "plld",
.cm_ctrl_reg = CM_PLLD,
.a2w_ctrl_reg = A2W_PLLD_CTRL,
@ -1734,6 +1767,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.max_rate = 2400000000u,
.max_fb_rate = BCM2835_MAX_FB_RATE),
[BCM2835_PLLD_CORE] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plld_core",
.source_pll = "plld",
.cm_reg = CM_PLLD,
@ -1742,7 +1776,13 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.hold_mask = CM_PLLD_HOLDCORE,
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
/*
* VPU firmware assumes that PLLD_PER isn't disabled by the ARM core.
* Otherwise this could cause firmware lookups. That's why we mark
* it as critical.
*/
[BCM2835_PLLD_PER] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plld_per",
.source_pll = "plld",
.cm_reg = CM_PLLD,
@ -1750,8 +1790,9 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.load_mask = CM_PLLD_LOADPER,
.hold_mask = CM_PLLD_HOLDPER,
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
.flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
[BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plld_dsi0",
.source_pll = "plld",
.cm_reg = CM_PLLD,
@ -1760,6 +1801,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.hold_mask = CM_PLLD_HOLDDSI0,
.fixed_divider = 1),
[BCM2835_PLLD_DSI1] = REGISTER_PLL_DIV(
SOC_ALL,
.name = "plld_dsi1",
.source_pll = "plld",
.cm_reg = CM_PLLD,
@ -1775,6 +1817,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* It is in the HDMI power domain.
*/
[BCM2835_PLLH] = REGISTER_PLL(
SOC_BCM2835,
"pllh",
.cm_ctrl_reg = CM_PLLH,
.a2w_ctrl_reg = A2W_PLLH_CTRL,
@ -1789,6 +1832,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.max_rate = 3000000000u,
.max_fb_rate = BCM2835_MAX_FB_RATE),
[BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV(
SOC_BCM2835,
.name = "pllh_rcal",
.source_pll = "pllh",
.cm_reg = CM_PLLH,
@ -1798,6 +1842,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 10,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(
SOC_BCM2835,
.name = "pllh_aux",
.source_pll = "pllh",
.cm_reg = CM_PLLH,
@ -1807,6 +1852,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.fixed_divider = 1,
.flags = CLK_SET_RATE_PARENT),
[BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(
SOC_BCM2835,
.name = "pllh_pix",
.source_pll = "pllh",
.cm_reg = CM_PLLH,
@ -1822,6 +1868,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* One Time Programmable Memory clock. Maximum 10Mhz. */
[BCM2835_CLOCK_OTP] = REGISTER_OSC_CLK(
SOC_ALL,
.name = "otp",
.ctl_reg = CM_OTPCTL,
.div_reg = CM_OTPDIV,
@ -1833,6 +1880,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* bythe watchdog timer and the camera pulse generator.
*/
[BCM2835_CLOCK_TIMER] = REGISTER_OSC_CLK(
SOC_ALL,
.name = "timer",
.ctl_reg = CM_TIMERCTL,
.div_reg = CM_TIMERDIV,
@ -1843,12 +1891,14 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* Generally run at 2Mhz, max 5Mhz.
*/
[BCM2835_CLOCK_TSENS] = REGISTER_OSC_CLK(
SOC_ALL,
.name = "tsens",
.ctl_reg = CM_TSENSCTL,
.div_reg = CM_TSENSDIV,
.int_bits = 5,
.frac_bits = 0),
[BCM2835_CLOCK_TEC] = REGISTER_OSC_CLK(
SOC_ALL,
.name = "tec",
.ctl_reg = CM_TECCTL,
.div_reg = CM_TECDIV,
@ -1857,6 +1907,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* clocks with vpu parent mux */
[BCM2835_CLOCK_H264] = REGISTER_VPU_CLK(
SOC_ALL,
.name = "h264",
.ctl_reg = CM_H264CTL,
.div_reg = CM_H264DIV,
@ -1864,6 +1915,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 1),
[BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK(
SOC_ALL,
.name = "isp",
.ctl_reg = CM_ISPCTL,
.div_reg = CM_ISPDIV,
@ -1876,6 +1928,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* in the SDRAM controller can't be used.
*/
[BCM2835_CLOCK_SDRAM] = REGISTER_VPU_CLK(
SOC_ALL,
.name = "sdram",
.ctl_reg = CM_SDCCTL,
.div_reg = CM_SDCDIV,
@ -1883,6 +1936,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 0,
.tcnt_mux = 3),
[BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
SOC_ALL,
.name = "v3d",
.ctl_reg = CM_V3DCTL,
.div_reg = CM_V3DDIV,
@ -1896,6 +1950,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* in various hardware documentation.
*/
[BCM2835_CLOCK_VPU] = REGISTER_VPU_CLK(
SOC_ALL,
.name = "vpu",
.ctl_reg = CM_VPUCTL,
.div_reg = CM_VPUDIV,
@ -1907,6 +1962,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* clocks with per parent mux */
[BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK(
SOC_ALL,
.name = "aveo",
.ctl_reg = CM_AVEOCTL,
.div_reg = CM_AVEODIV,
@ -1914,6 +1970,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 0,
.tcnt_mux = 38),
[BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK(
SOC_ALL,
.name = "cam0",
.ctl_reg = CM_CAM0CTL,
.div_reg = CM_CAM0DIV,
@ -1921,6 +1978,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 14),
[BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK(
SOC_ALL,
.name = "cam1",
.ctl_reg = CM_CAM1CTL,
.div_reg = CM_CAM1DIV,
@ -1928,12 +1986,14 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 15),
[BCM2835_CLOCK_DFT] = REGISTER_PER_CLK(
SOC_ALL,
.name = "dft",
.ctl_reg = CM_DFTCTL,
.div_reg = CM_DFTDIV,
.int_bits = 5,
.frac_bits = 0),
[BCM2835_CLOCK_DPI] = REGISTER_PER_CLK(
SOC_ALL,
.name = "dpi",
.ctl_reg = CM_DPICTL,
.div_reg = CM_DPIDIV,
@ -1943,6 +2003,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* Arasan EMMC clock */
[BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK(
SOC_ALL,
.name = "emmc",
.ctl_reg = CM_EMMCCTL,
.div_reg = CM_EMMCDIV,
@ -1950,8 +2011,19 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 39),
/* EMMC2 clock (only available for BCM2711) */
[BCM2711_CLOCK_EMMC2] = REGISTER_PER_CLK(
SOC_BCM2711,
.name = "emmc2",
.ctl_reg = CM_EMMC2CTL,
.div_reg = CM_EMMC2DIV,
.int_bits = 4,
.frac_bits = 8,
.tcnt_mux = 42),
/* General purpose (GPIO) clocks */
[BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
SOC_ALL,
.name = "gp0",
.ctl_reg = CM_GP0CTL,
.div_reg = CM_GP0DIV,
@ -1960,6 +2032,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.is_mash_clock = true,
.tcnt_mux = 20),
[BCM2835_CLOCK_GP1] = REGISTER_PER_CLK(
SOC_ALL,
.name = "gp1",
.ctl_reg = CM_GP1CTL,
.div_reg = CM_GP1DIV,
@ -1969,6 +2042,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.is_mash_clock = true,
.tcnt_mux = 21),
[BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
SOC_ALL,
.name = "gp2",
.ctl_reg = CM_GP2CTL,
.div_reg = CM_GP2DIV,
@ -1978,6 +2052,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* HDMI state machine */
[BCM2835_CLOCK_HSM] = REGISTER_PER_CLK(
SOC_ALL,
.name = "hsm",
.ctl_reg = CM_HSMCTL,
.div_reg = CM_HSMDIV,
@ -1985,6 +2060,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 22),
[BCM2835_CLOCK_PCM] = REGISTER_PCM_CLK(
SOC_ALL,
.name = "pcm",
.ctl_reg = CM_PCMCTL,
.div_reg = CM_PCMDIV,
@ -1994,6 +2070,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.low_jitter = true,
.tcnt_mux = 23),
[BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
SOC_ALL,
.name = "pwm",
.ctl_reg = CM_PWMCTL,
.div_reg = CM_PWMDIV,
@ -2002,6 +2079,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.is_mash_clock = true,
.tcnt_mux = 24),
[BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK(
SOC_ALL,
.name = "slim",
.ctl_reg = CM_SLIMCTL,
.div_reg = CM_SLIMDIV,
@ -2010,6 +2088,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.is_mash_clock = true,
.tcnt_mux = 25),
[BCM2835_CLOCK_SMI] = REGISTER_PER_CLK(
SOC_ALL,
.name = "smi",
.ctl_reg = CM_SMICTL,
.div_reg = CM_SMIDIV,
@ -2017,6 +2096,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 27),
[BCM2835_CLOCK_UART] = REGISTER_PER_CLK(
SOC_ALL,
.name = "uart",
.ctl_reg = CM_UARTCTL,
.div_reg = CM_UARTDIV,
@ -2026,6 +2106,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* TV encoder clock. Only operating frequency is 108Mhz. */
[BCM2835_CLOCK_VEC] = REGISTER_PER_CLK(
SOC_ALL,
.name = "vec",
.ctl_reg = CM_VECCTL,
.div_reg = CM_VECDIV,
@ -2040,6 +2121,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
/* dsi clocks */
[BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
SOC_ALL,
.name = "dsi0e",
.ctl_reg = CM_DSI0ECTL,
.div_reg = CM_DSI0EDIV,
@ -2047,6 +2129,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 18),
[BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK(
SOC_ALL,
.name = "dsi1e",
.ctl_reg = CM_DSI1ECTL,
.div_reg = CM_DSI1EDIV,
@ -2054,6 +2137,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 8,
.tcnt_mux = 19),
[BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK(
SOC_ALL,
.name = "dsi0p",
.ctl_reg = CM_DSI0PCTL,
.div_reg = CM_DSI0PDIV,
@ -2061,6 +2145,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
.frac_bits = 0,
.tcnt_mux = 12),
[BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK(
SOC_ALL,
.name = "dsi1p",
.ctl_reg = CM_DSI1PCTL,
.div_reg = CM_DSI1PDIV,
@ -2077,6 +2162,7 @@ static const struct bcm2835_clk_desc clk_desc_array[] = {
* non-stop vpu clock.
*/
[BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
SOC_ALL,
.name = "peri_image",
.parent = "vpu",
.ctl_reg = CM_PERIICTL),
@ -2109,9 +2195,14 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
struct resource *res;
const struct bcm2835_clk_desc *desc;
const size_t asize = ARRAY_SIZE(clk_desc_array);
const struct cprman_plat_data *pdata;
size_t i;
int ret;
pdata = of_device_get_match_data(&pdev->dev);
if (!pdata)
return -ENODEV;
cprman = devm_kzalloc(dev,
struct_size(cprman, onecell.hws, asize),
GFP_KERNEL);
@ -2147,8 +2238,10 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
for (i = 0; i < asize; i++) {
desc = &clk_desc_array[i];
if (desc->clk_register && desc->data)
if (desc->clk_register && desc->data &&
(desc->supported & pdata->soc)) {
hws[i] = desc->clk_register(cprman, desc->data);
}
}
ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
@ -2159,8 +2252,17 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
&cprman->onecell);
}
static const struct cprman_plat_data cprman_bcm2835_plat_data = {
.soc = SOC_BCM2835,
};
static const struct cprman_plat_data cprman_bcm2711_plat_data = {
.soc = SOC_BCM2711,
};
static const struct of_device_id bcm2835_clk_of_match[] = {
{ .compatible = "brcm,bcm2835-cprman", },
{ .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
{ .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
{}
};
MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);

View File

@ -146,7 +146,6 @@ static int clk_bcm63xx_probe(struct platform_device *pdev)
{
const struct clk_bcm63xx_table_entry *entry, *table;
struct clk_bcm63xx_hw *hw;
struct resource *r;
u8 maxbit = 0;
int i, ret;
@ -170,8 +169,7 @@ static int clk_bcm63xx_probe(struct platform_device *pdev)
for (i = 0; i < maxbit; i++)
hw->data.hws[i] = ERR_PTR(-ENODEV);
r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hw->regs = devm_ioremap_resource(&pdev->dev, r);
hw->regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(hw->regs))
return PTR_ERR(hw->regs);

View File

@ -1,19 +1,19 @@
// SPDX-License-Identifier: GPL-2.0+
// Copyright IBM Corp
#define pr_fmt(fmt) "clk-aspeed: " fmt
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <dt-bindings/clock/aspeed-clock.h>
#include "clk-aspeed.h"
#define ASPEED_NUM_CLKS 36
#define ASPEED_RESET2_OFFSET 32
@ -42,48 +42,6 @@ static struct clk_hw_onecell_data *aspeed_clk_data;
static void __iomem *scu_base;
/**
* struct aspeed_gate_data - Aspeed gated clocks
* @clock_idx: bit used to gate this clock in the clock register
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
* reset is required when enabling the clock
* @name: the clock name
* @parent_name: the name of the parent clock
* @flags: standard clock framework flags
*/
struct aspeed_gate_data {
u8 clock_idx;
s8 reset_idx;
const char *name;
const char *parent_name;
unsigned long flags;
};
/**
* struct aspeed_clk_gate - Aspeed specific clk_gate structure
* @hw: handle between common and hardware-specific interfaces
* @reg: register controlling gate
* @clock_idx: bit used to gate this clock in the clock register
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
* reset is required when enabling the clock
* @flags: hardware-specific flags
* @lock: register lock
*
* Some of the clocks in the Aspeed SoC must be put in reset before enabling.
* This modified version of clk_gate allows an optional reset bit to be
* specified.
*/
struct aspeed_clk_gate {
struct clk_hw hw;
struct regmap *map;
u8 clock_idx;
s8 reset_idx;
u8 flags;
spinlock_t *lock;
};
#define to_aspeed_clk_gate(_hw) container_of(_hw, struct aspeed_clk_gate, hw)
/* TODO: ask Aspeed about the actual parent data */
static const struct aspeed_gate_data aspeed_gates[] = {
/* clk rst name parent flags */
@ -208,13 +166,6 @@ static struct clk_hw *aspeed_ast2500_calc_pll(const char *name, u32 val)
mult, div);
}
struct aspeed_clk_soc_data {
const struct clk_div_table *div_table;
const struct clk_div_table *eclk_div_table;
const struct clk_div_table *mac_div_table;
struct clk_hw *(*calc_pll)(const char *name, u32 val);
};
static const struct aspeed_clk_soc_data ast2500_data = {
.div_table = ast2500_div_table,
.eclk_div_table = ast2500_eclk_div_table,
@ -315,18 +266,6 @@ static const struct clk_ops aspeed_clk_gate_ops = {
.is_enabled = aspeed_clk_is_enabled,
};
/**
* struct aspeed_reset - Aspeed reset controller
* @map: regmap to access the containing system controller
* @rcdev: reset controller device
*/
struct aspeed_reset {
struct regmap *map;
struct reset_controller_dev rcdev;
};
#define to_aspeed_reset(p) container_of((p), struct aspeed_reset, rcdev)
static const u8 aspeed_resets[] = {
/* SCU04 resets */
[ASPEED_RESET_XDMA] = 25,
@ -500,9 +439,14 @@ static int aspeed_clk_probe(struct platform_device *pdev)
return PTR_ERR(hw);
aspeed_clk_data->hws[ASPEED_CLK_MPLL] = hw;
/* SD/SDIO clock divider (TODO: There's a gate too) */
hw = clk_hw_register_divider_table(dev, "sdio", "hpll", 0,
scu_base + ASPEED_CLK_SELECTION, 12, 3, 0,
/* SD/SDIO clock divider and gate */
hw = clk_hw_register_gate(dev, "sd_extclk_gate", "hpll", 0,
scu_base + ASPEED_CLK_SELECTION, 15, 0,
&aspeed_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
hw = clk_hw_register_divider_table(dev, "sd_extclk", "sd_extclk_gate",
0, scu_base + ASPEED_CLK_SELECTION, 12, 3, 0,
soc_data->div_table,
&aspeed_clk_lock);
if (IS_ERR(hw))

82
drivers/clk/clk-aspeed.h Normal file
View File

@ -0,0 +1,82 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
* Structures used by ASPEED clock drivers
*
* Copyright 2019 IBM Corp.
*/
#include <linux/clk-provider.h>
#include <linux/kernel.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
struct clk_div_table;
struct regmap;
/**
* struct aspeed_gate_data - Aspeed gated clocks
* @clock_idx: bit used to gate this clock in the clock register
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
* reset is required when enabling the clock
* @name: the clock name
* @parent_name: the name of the parent clock
* @flags: standard clock framework flags
*/
struct aspeed_gate_data {
u8 clock_idx;
s8 reset_idx;
const char *name;
const char *parent_name;
unsigned long flags;
};
/**
* struct aspeed_clk_gate - Aspeed specific clk_gate structure
* @hw: handle between common and hardware-specific interfaces
* @reg: register controlling gate
* @clock_idx: bit used to gate this clock in the clock register
* @reset_idx: bit used to reset this IP in the reset register. -1 if no
* reset is required when enabling the clock
* @flags: hardware-specific flags
* @lock: register lock
*
* Some of the clocks in the Aspeed SoC must be put in reset before enabling.
* This modified version of clk_gate allows an optional reset bit to be
* specified.
*/
struct aspeed_clk_gate {
struct clk_hw hw;
struct regmap *map;
u8 clock_idx;
s8 reset_idx;
u8 flags;
spinlock_t *lock;
};
#define to_aspeed_clk_gate(_hw) container_of(_hw, struct aspeed_clk_gate, hw)
/**
* struct aspeed_reset - Aspeed reset controller
* @map: regmap to access the containing system controller
* @rcdev: reset controller device
*/
struct aspeed_reset {
struct regmap *map;
struct reset_controller_dev rcdev;
};
#define to_aspeed_reset(p) container_of((p), struct aspeed_reset, rcdev)
/**
* struct aspeed_clk_soc_data - Aspeed SoC specific divisor information
* @div_table: Common divider lookup table
* @eclk_div_table: Divider lookup table for ECLK
* @mac_div_table: Divider lookup table for MAC (Ethernet) clocks
* @calc_pll: Callback to maculate common PLL settings
*/
struct aspeed_clk_soc_data {
const struct clk_div_table *div_table;
const struct clk_div_table *eclk_div_table;
const struct clk_div_table *mac_div_table;
struct clk_hw *(*calc_pll)(const char *name, u32 val);
};

704
drivers/clk/clk-ast2600.c Normal file
View File

@ -0,0 +1,704 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// Copyright IBM Corp
// Copyright ASPEED Technology
#define pr_fmt(fmt) "clk-ast2600: " fmt
#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <dt-bindings/clock/ast2600-clock.h>
#include "clk-aspeed.h"
#define ASPEED_G6_NUM_CLKS 67
#define ASPEED_G6_SILICON_REV 0x004
#define ASPEED_G6_RESET_CTRL 0x040
#define ASPEED_G6_RESET_CTRL2 0x050
#define ASPEED_G6_CLK_STOP_CTRL 0x080
#define ASPEED_G6_CLK_STOP_CTRL2 0x090
#define ASPEED_G6_MISC_CTRL 0x0C0
#define UART_DIV13_EN BIT(12)
#define ASPEED_G6_CLK_SELECTION1 0x300
#define ASPEED_G6_CLK_SELECTION2 0x304
#define ASPEED_G6_CLK_SELECTION4 0x310
#define ASPEED_HPLL_PARAM 0x200
#define ASPEED_APLL_PARAM 0x210
#define ASPEED_MPLL_PARAM 0x220
#define ASPEED_EPLL_PARAM 0x240
#define ASPEED_DPLL_PARAM 0x260
#define ASPEED_G6_STRAP1 0x500
/* Globally visible clocks */
static DEFINE_SPINLOCK(aspeed_g6_clk_lock);
/* Keeps track of all clocks */
static struct clk_hw_onecell_data *aspeed_g6_clk_data;
static void __iomem *scu_g6_base;
/*
* Clocks marked with CLK_IS_CRITICAL:
*
* ref0 and ref1 are essential for the SoC to operate
* mpll is required if SDRAM is used
*/
static const struct aspeed_gate_data aspeed_g6_gates[] = {
/* clk rst name parent flags */
[ASPEED_CLK_GATE_MCLK] = { 0, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */
[ASPEED_CLK_GATE_ECLK] = { 1, -1, "eclk-gate", "eclk", 0 }, /* Video Engine */
[ASPEED_CLK_GATE_GCLK] = { 2, 7, "gclk-gate", NULL, 0 }, /* 2D engine */
/* vclk parent - dclk/d1clk/hclk/mclk */
[ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */
[ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */
/* From dpll */
[ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, CLK_IS_CRITICAL }, /* DAC */
[ASPEED_CLK_GATE_REF0CLK] = { 6, -1, "ref0clk-gate", "clkin", CLK_IS_CRITICAL },
[ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */
/* Reserved 8 */
[ASPEED_CLK_GATE_USBUHCICLK] = { 9, 15, "usb-uhci-gate", NULL, 0 }, /* USB1.1 (requires port 2 enabled) */
/* From dpll/epll/40mhz usb p1 phy/gpioc6/dp phy pll */
[ASPEED_CLK_GATE_D1CLK] = { 10, 13, "d1clk-gate", "d1clk", 0 }, /* GFX CRT */
/* Reserved 11/12 */
[ASPEED_CLK_GATE_YCLK] = { 13, 4, "yclk-gate", NULL, 0 }, /* HAC */
[ASPEED_CLK_GATE_USBPORT1CLK] = { 14, 14, "usb-port1-gate", NULL, 0 }, /* USB2 hub/USB2 host port 1/USB1.1 dev */
[ASPEED_CLK_GATE_UART5CLK] = { 15, -1, "uart5clk-gate", "uart", 0 }, /* UART5 */
/* Reserved 16/19 */
[ASPEED_CLK_GATE_MAC1CLK] = { 20, 11, "mac1clk-gate", "mac12", 0 }, /* MAC1 */
[ASPEED_CLK_GATE_MAC2CLK] = { 21, 12, "mac2clk-gate", "mac12", 0 }, /* MAC2 */
/* Reserved 22/23 */
[ASPEED_CLK_GATE_RSACLK] = { 24, 4, "rsaclk-gate", NULL, 0 }, /* HAC */
[ASPEED_CLK_GATE_RVASCLK] = { 25, 9, "rvasclk-gate", NULL, 0 }, /* RVAS */
/* Reserved 26 */
[ASPEED_CLK_GATE_EMMCCLK] = { 27, 16, "emmcclk-gate", NULL, 0 }, /* For card clk */
/* Reserved 28/29/30 */
[ASPEED_CLK_GATE_LCLK] = { 32, 32, "lclk-gate", NULL, 0 }, /* LPC */
[ASPEED_CLK_GATE_ESPICLK] = { 33, -1, "espiclk-gate", NULL, 0 }, /* eSPI */
[ASPEED_CLK_GATE_REF1CLK] = { 34, -1, "ref1clk-gate", "clkin", CLK_IS_CRITICAL },
/* Reserved 35 */
[ASPEED_CLK_GATE_SDCLK] = { 36, 56, "sdclk-gate", NULL, 0 }, /* SDIO/SD */
[ASPEED_CLK_GATE_LHCCLK] = { 37, -1, "lhclk-gate", "lhclk", 0 }, /* LPC master/LPC+ */
/* Reserved 38 RSA: no longer used */
/* Reserved 39 */
[ASPEED_CLK_GATE_I3C0CLK] = { 40, 40, "i3c0clk-gate", NULL, 0 }, /* I3C0 */
[ASPEED_CLK_GATE_I3C1CLK] = { 41, 41, "i3c1clk-gate", NULL, 0 }, /* I3C1 */
[ASPEED_CLK_GATE_I3C2CLK] = { 42, 42, "i3c2clk-gate", NULL, 0 }, /* I3C2 */
[ASPEED_CLK_GATE_I3C3CLK] = { 43, 43, "i3c3clk-gate", NULL, 0 }, /* I3C3 */
[ASPEED_CLK_GATE_I3C4CLK] = { 44, 44, "i3c4clk-gate", NULL, 0 }, /* I3C4 */
[ASPEED_CLK_GATE_I3C5CLK] = { 45, 45, "i3c5clk-gate", NULL, 0 }, /* I3C5 */
[ASPEED_CLK_GATE_I3C6CLK] = { 46, 46, "i3c6clk-gate", NULL, 0 }, /* I3C6 */
[ASPEED_CLK_GATE_I3C7CLK] = { 47, 47, "i3c7clk-gate", NULL, 0 }, /* I3C7 */
[ASPEED_CLK_GATE_UART1CLK] = { 48, -1, "uart1clk-gate", "uart", 0 }, /* UART1 */
[ASPEED_CLK_GATE_UART2CLK] = { 49, -1, "uart2clk-gate", "uart", 0 }, /* UART2 */
[ASPEED_CLK_GATE_UART3CLK] = { 50, -1, "uart3clk-gate", "uart", 0 }, /* UART3 */
[ASPEED_CLK_GATE_UART4CLK] = { 51, -1, "uart4clk-gate", "uart", 0 }, /* UART4 */
[ASPEED_CLK_GATE_MAC3CLK] = { 52, 52, "mac3clk-gate", "mac34", 0 }, /* MAC3 */
[ASPEED_CLK_GATE_MAC4CLK] = { 53, 53, "mac4clk-gate", "mac34", 0 }, /* MAC4 */
[ASPEED_CLK_GATE_UART6CLK] = { 54, -1, "uart6clk-gate", "uartx", 0 }, /* UART6 */
[ASPEED_CLK_GATE_UART7CLK] = { 55, -1, "uart7clk-gate", "uartx", 0 }, /* UART7 */
[ASPEED_CLK_GATE_UART8CLK] = { 56, -1, "uart8clk-gate", "uartx", 0 }, /* UART8 */
[ASPEED_CLK_GATE_UART9CLK] = { 57, -1, "uart9clk-gate", "uartx", 0 }, /* UART9 */
[ASPEED_CLK_GATE_UART10CLK] = { 58, -1, "uart10clk-gate", "uartx", 0 }, /* UART10 */
[ASPEED_CLK_GATE_UART11CLK] = { 59, -1, "uart11clk-gate", "uartx", 0 }, /* UART11 */
[ASPEED_CLK_GATE_UART12CLK] = { 60, -1, "uart12clk-gate", "uartx", 0 }, /* UART12 */
[ASPEED_CLK_GATE_UART13CLK] = { 61, -1, "uart13clk-gate", "uartx", 0 }, /* UART13 */
[ASPEED_CLK_GATE_FSICLK] = { 62, 59, "fsiclk-gate", NULL, 0 }, /* FSI */
};
static const char * const eclk_parent_names[] = { "mpll", "hpll", "dpll" };
static const struct clk_div_table ast2600_eclk_div_table[] = {
{ 0x0, 2 },
{ 0x1, 2 },
{ 0x2, 3 },
{ 0x3, 4 },
{ 0x4, 5 },
{ 0x5, 6 },
{ 0x6, 7 },
{ 0x7, 8 },
{ 0 }
};
static const struct clk_div_table ast2600_mac_div_table[] = {
{ 0x0, 4 },
{ 0x1, 4 },
{ 0x2, 6 },
{ 0x3, 8 },
{ 0x4, 10 },
{ 0x5, 12 },
{ 0x6, 14 },
{ 0x7, 16 },
{ 0 }
};
static const struct clk_div_table ast2600_div_table[] = {
{ 0x0, 4 },
{ 0x1, 8 },
{ 0x2, 12 },
{ 0x3, 16 },
{ 0x4, 20 },
{ 0x5, 24 },
{ 0x6, 28 },
{ 0x7, 32 },
{ 0 }
};
/* For hpll/dpll/epll/mpll */
static struct clk_hw *ast2600_calc_pll(const char *name, u32 val)
{
unsigned int mult, div;
if (val & BIT(24)) {
/* Pass through mode */
mult = div = 1;
} else {
/* F = 25Mhz * [(M + 2) / (n + 1)] / (p + 1) */
u32 m = val & 0x1fff;
u32 n = (val >> 13) & 0x3f;
u32 p = (val >> 19) & 0xf;
mult = (m + 1) / (n + 1);
div = (p + 1);
}
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
mult, div);
};
static struct clk_hw *ast2600_calc_apll(const char *name, u32 val)
{
unsigned int mult, div;
if (val & BIT(20)) {
/* Pass through mode */
mult = div = 1;
} else {
/* F = 25Mhz * (2-od) * [(m + 2) / (n + 1)] */
u32 m = (val >> 5) & 0x3f;
u32 od = (val >> 4) & 0x1;
u32 n = val & 0xf;
mult = (2 - od) * (m + 2);
div = n + 1;
}
return clk_hw_register_fixed_factor(NULL, name, "clkin", 0,
mult, div);
};
static u32 get_bit(u8 idx)
{
return BIT(idx % 32);
}
static u32 get_reset_reg(struct aspeed_clk_gate *gate)
{
if (gate->reset_idx < 32)
return ASPEED_G6_RESET_CTRL;
return ASPEED_G6_RESET_CTRL2;
}
static u32 get_clock_reg(struct aspeed_clk_gate *gate)
{
if (gate->clock_idx < 32)
return ASPEED_G6_CLK_STOP_CTRL;
return ASPEED_G6_CLK_STOP_CTRL2;
}
static int aspeed_g6_clk_is_enabled(struct clk_hw *hw)
{
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
u32 clk = get_bit(gate->clock_idx);
u32 rst = get_bit(gate->reset_idx);
u32 reg;
u32 enval;
/*
* If the IP is in reset, treat the clock as not enabled,
* this happens with some clocks such as the USB one when
* coming from cold reset. Without this, aspeed_clk_enable()
* will fail to lift the reset.
*/
if (gate->reset_idx >= 0) {
regmap_read(gate->map, get_reset_reg(gate), &reg);
if (reg & rst)
return 0;
}
regmap_read(gate->map, get_clock_reg(gate), &reg);
enval = (gate->flags & CLK_GATE_SET_TO_DISABLE) ? 0 : clk;
return ((reg & clk) == enval) ? 1 : 0;
}
static int aspeed_g6_clk_enable(struct clk_hw *hw)
{
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
unsigned long flags;
u32 clk = get_bit(gate->clock_idx);
u32 rst = get_bit(gate->reset_idx);
spin_lock_irqsave(gate->lock, flags);
if (aspeed_g6_clk_is_enabled(hw)) {
spin_unlock_irqrestore(gate->lock, flags);
return 0;
}
if (gate->reset_idx >= 0) {
/* Put IP in reset */
regmap_write(gate->map, get_reset_reg(gate), rst);
/* Delay 100us */
udelay(100);
}
/* Enable clock */
if (gate->flags & CLK_GATE_SET_TO_DISABLE) {
regmap_write(gate->map, get_clock_reg(gate), clk);
} else {
/* Use set to clear register */
regmap_write(gate->map, get_clock_reg(gate) + 0x04, clk);
}
if (gate->reset_idx >= 0) {
/* A delay of 10ms is specified by the ASPEED docs */
mdelay(10);
/* Take IP out of reset */
regmap_write(gate->map, get_reset_reg(gate) + 0x4, rst);
}
spin_unlock_irqrestore(gate->lock, flags);
return 0;
}
static void aspeed_g6_clk_disable(struct clk_hw *hw)
{
struct aspeed_clk_gate *gate = to_aspeed_clk_gate(hw);
unsigned long flags;
u32 clk = get_bit(gate->clock_idx);
spin_lock_irqsave(gate->lock, flags);
if (gate->flags & CLK_GATE_SET_TO_DISABLE) {
regmap_write(gate->map, get_clock_reg(gate), clk);
} else {
/* Use set to clear register */
regmap_write(gate->map, get_clock_reg(gate) + 0x4, clk);
}
spin_unlock_irqrestore(gate->lock, flags);
}
static const struct clk_ops aspeed_g6_clk_gate_ops = {
.enable = aspeed_g6_clk_enable,
.disable = aspeed_g6_clk_disable,
.is_enabled = aspeed_g6_clk_is_enabled,
};
static int aspeed_g6_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
u32 rst = get_bit(id);
u32 reg = id >= 32 ? ASPEED_G6_RESET_CTRL2 : ASPEED_G6_RESET_CTRL;
/* Use set to clear register */
return regmap_write(ar->map, reg + 0x04, rst);
}
static int aspeed_g6_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
u32 rst = get_bit(id);
u32 reg = id >= 32 ? ASPEED_G6_RESET_CTRL2 : ASPEED_G6_RESET_CTRL;
return regmap_write(ar->map, reg, rst);
}
static int aspeed_g6_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
int ret;
u32 val;
u32 rst = get_bit(id);
u32 reg = id >= 32 ? ASPEED_G6_RESET_CTRL2 : ASPEED_G6_RESET_CTRL;
ret = regmap_read(ar->map, reg, &val);
if (ret)
return ret;
return !!(val & rst);
}
static const struct reset_control_ops aspeed_g6_reset_ops = {
.assert = aspeed_g6_reset_assert,
.deassert = aspeed_g6_reset_deassert,
.status = aspeed_g6_reset_status,
};
static struct clk_hw *aspeed_g6_clk_hw_register_gate(struct device *dev,
const char *name, const char *parent_name, unsigned long flags,
struct regmap *map, u8 clock_idx, u8 reset_idx,
u8 clk_gate_flags, spinlock_t *lock)
{
struct aspeed_clk_gate *gate;
struct clk_init_data init;
struct clk_hw *hw;
int ret;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
init.name = name;
init.ops = &aspeed_g6_clk_gate_ops;
init.flags = flags;
init.parent_names = parent_name ? &parent_name : NULL;
init.num_parents = parent_name ? 1 : 0;
gate->map = map;
gate->clock_idx = clock_idx;
gate->reset_idx = reset_idx;
gate->flags = clk_gate_flags;
gate->lock = lock;
gate->hw.init = &init;
hw = &gate->hw;
ret = clk_hw_register(dev, hw);
if (ret) {
kfree(gate);
hw = ERR_PTR(ret);
}
return hw;
}
static const char * const vclk_parent_names[] = {
"dpll",
"d1pll",
"hclk",
"mclk",
};
static const char * const d1clk_parent_names[] = {
"dpll",
"epll",
"usb-phy-40m",
"gpioc6_clkin",
"dp_phy_pll",
};
static int aspeed_g6_clk_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct aspeed_reset *ar;
struct regmap *map;
struct clk_hw *hw;
u32 val, rate;
int i, ret;
map = syscon_node_to_regmap(dev->of_node);
if (IS_ERR(map)) {
dev_err(dev, "no syscon regmap\n");
return PTR_ERR(map);
}
ar = devm_kzalloc(dev, sizeof(*ar), GFP_KERNEL);
if (!ar)
return -ENOMEM;
ar->map = map;
ar->rcdev.owner = THIS_MODULE;
ar->rcdev.nr_resets = 64;
ar->rcdev.ops = &aspeed_g6_reset_ops;
ar->rcdev.of_node = dev->of_node;
ret = devm_reset_controller_register(dev, &ar->rcdev);
if (ret) {
dev_err(dev, "could not register reset controller\n");
return ret;
}
/* UART clock div13 setting */
regmap_read(map, ASPEED_G6_MISC_CTRL, &val);
if (val & UART_DIV13_EN)
rate = 24000000 / 13;
else
rate = 24000000;
hw = clk_hw_register_fixed_rate(dev, "uart", NULL, 0, rate);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_UART] = hw;
/* UART6~13 clock div13 setting */
regmap_read(map, 0x80, &val);
if (val & BIT(31))
rate = 24000000 / 13;
else
rate = 24000000;
hw = clk_hw_register_fixed_rate(dev, "uartx", NULL, 0, rate);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_UARTX] = hw;
/* EMMC ext clock divider */
hw = clk_hw_register_gate(dev, "emmc_extclk_gate", "hpll", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 15, 0,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
hw = clk_hw_register_divider_table(dev, "emmc_extclk", "emmc_extclk_gate", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 12, 3, 0,
ast2600_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_EMMC] = hw;
/* SD/SDIO clock divider and gate */
hw = clk_hw_register_gate(dev, "sd_extclk_gate", "hpll", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION4, 31, 0,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
hw = clk_hw_register_divider_table(dev, "sd_extclk", "sd_extclk_gate",
0, scu_g6_base + ASPEED_G6_CLK_SELECTION4, 28, 3, 0,
ast2600_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_SDIO] = hw;
/* MAC1/2 AHB bus clock divider */
hw = clk_hw_register_divider_table(dev, "mac12", "hpll", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 16, 3, 0,
ast2600_mac_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_MAC12] = hw;
/* MAC3/4 AHB bus clock divider */
hw = clk_hw_register_divider_table(dev, "mac34", "hpll", 0,
scu_g6_base + 0x310, 24, 3, 0,
ast2600_mac_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_MAC34] = hw;
/* LPC Host (LHCLK) clock divider */
hw = clk_hw_register_divider_table(dev, "lhclk", "hpll", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 20, 3, 0,
ast2600_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_LHCLK] = hw;
/* gfx d1clk : use dp clk */
regmap_update_bits(map, ASPEED_G6_CLK_SELECTION1, GENMASK(10, 8), BIT(10));
/* SoC Display clock selection */
hw = clk_hw_register_mux(dev, "d1clk", d1clk_parent_names,
ARRAY_SIZE(d1clk_parent_names), 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 8, 3, 0,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_D1CLK] = hw;
/* d1 clk div 0x308[17:15] x [14:12] - 8,7,6,5,4,3,2,1 */
regmap_write(map, 0x308, 0x12000); /* 3x3 = 9 */
/* P-Bus (BCLK) clock divider */
hw = clk_hw_register_divider_table(dev, "bclk", "hpll", 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 20, 3, 0,
ast2600_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_BCLK] = hw;
/* Video Capture clock selection */
hw = clk_hw_register_mux(dev, "vclk", vclk_parent_names,
ARRAY_SIZE(vclk_parent_names), 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION2, 12, 3, 0,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_VCLK] = hw;
/* Video Engine clock divider */
hw = clk_hw_register_divider_table(dev, "eclk", NULL, 0,
scu_g6_base + ASPEED_G6_CLK_SELECTION1, 28, 3, 0,
ast2600_eclk_div_table,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[ASPEED_CLK_ECLK] = hw;
for (i = 0; i < ARRAY_SIZE(aspeed_g6_gates); i++) {
const struct aspeed_gate_data *gd = &aspeed_g6_gates[i];
u32 gate_flags;
/*
* Special case: the USB port 1 clock (bit 14) is always
* working the opposite way from the other ones.
*/
gate_flags = (gd->clock_idx == 14) ? 0 : CLK_GATE_SET_TO_DISABLE;
hw = aspeed_g6_clk_hw_register_gate(dev,
gd->name,
gd->parent_name,
gd->flags,
map,
gd->clock_idx,
gd->reset_idx,
gate_flags,
&aspeed_g6_clk_lock);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_g6_clk_data->hws[i] = hw;
}
return 0;
};
static const struct of_device_id aspeed_g6_clk_dt_ids[] = {
{ .compatible = "aspeed,ast2600-scu" },
{ }
};
static struct platform_driver aspeed_g6_clk_driver = {
.probe = aspeed_g6_clk_probe,
.driver = {
.name = "ast2600-clk",
.of_match_table = aspeed_g6_clk_dt_ids,
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(aspeed_g6_clk_driver);
static const u32 ast2600_a0_axi_ahb_div_table[] = {
2, 2, 3, 5,
};
static const u32 ast2600_a1_axi_ahb_div_table[] = {
4, 6, 2, 4,
};
static void __init aspeed_g6_cc(struct regmap *map)
{
struct clk_hw *hw;
u32 val, div, chip_id, axi_div, ahb_div;
clk_hw_register_fixed_rate(NULL, "clkin", NULL, 0, 25000000);
/*
* High-speed PLL clock derived from the crystal. This the CPU clock,
* and we assume that it is enabled
*/
regmap_read(map, ASPEED_HPLL_PARAM, &val);
aspeed_g6_clk_data->hws[ASPEED_CLK_HPLL] = ast2600_calc_pll("hpll", val);
regmap_read(map, ASPEED_MPLL_PARAM, &val);
aspeed_g6_clk_data->hws[ASPEED_CLK_MPLL] = ast2600_calc_pll("mpll", val);
regmap_read(map, ASPEED_DPLL_PARAM, &val);
aspeed_g6_clk_data->hws[ASPEED_CLK_DPLL] = ast2600_calc_pll("dpll", val);
regmap_read(map, ASPEED_EPLL_PARAM, &val);
aspeed_g6_clk_data->hws[ASPEED_CLK_EPLL] = ast2600_calc_pll("epll", val);
regmap_read(map, ASPEED_APLL_PARAM, &val);
aspeed_g6_clk_data->hws[ASPEED_CLK_APLL] = ast2600_calc_apll("apll", val);
/* Strap bits 12:11 define the AXI/AHB clock frequency ratio (aka HCLK)*/
regmap_read(map, ASPEED_G6_STRAP1, &val);
if (val & BIT(16))
axi_div = 1;
else
axi_div = 2;
regmap_read(map, ASPEED_G6_SILICON_REV, &chip_id);
if (chip_id & BIT(16))
ahb_div = ast2600_a1_axi_ahb_div_table[(val >> 11) & 0x3];
else
ahb_div = ast2600_a0_axi_ahb_div_table[(val >> 11) & 0x3];
hw = clk_hw_register_fixed_factor(NULL, "ahb", "hpll", 0, 1, axi_div * ahb_div);
aspeed_g6_clk_data->hws[ASPEED_CLK_AHB] = hw;
regmap_read(map, ASPEED_G6_CLK_SELECTION1, &val);
val = (val >> 23) & 0x7;
div = 4 * (val + 1);
hw = clk_hw_register_fixed_factor(NULL, "apb1", "hpll", 0, 1, div);
aspeed_g6_clk_data->hws[ASPEED_CLK_APB1] = hw;
regmap_read(map, ASPEED_G6_CLK_SELECTION4, &val);
val = (val >> 9) & 0x7;
div = 2 * (val + 1);
hw = clk_hw_register_fixed_factor(NULL, "apb2", "ahb", 0, 1, div);
aspeed_g6_clk_data->hws[ASPEED_CLK_APB2] = hw;
/* USB 2.0 port1 phy 40MHz clock */
hw = clk_hw_register_fixed_rate(NULL, "usb-phy-40m", NULL, 0, 40000000);
aspeed_g6_clk_data->hws[ASPEED_CLK_USBPHY_40M] = hw;
};
static void __init aspeed_g6_cc_init(struct device_node *np)
{
struct regmap *map;
int ret;
int i;
scu_g6_base = of_iomap(np, 0);
if (!scu_g6_base)
return;
aspeed_g6_clk_data = kzalloc(struct_size(aspeed_g6_clk_data, hws,
ASPEED_G6_NUM_CLKS), GFP_KERNEL);
if (!aspeed_g6_clk_data)
return;
/*
* This way all clocks fetched before the platform device probes,
* except those we assign here for early use, will be deferred.
*/
for (i = 0; i < ASPEED_G6_NUM_CLKS; i++)
aspeed_g6_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
/*
* We check that the regmap works on this very first access,
* but as this is an MMIO-backed regmap, subsequent regmap
* access is not going to fail and we skip error checks from
* this point.
*/
map = syscon_node_to_regmap(np);
if (IS_ERR(map)) {
pr_err("no syscon regmap\n");
return;
}
aspeed_g6_cc(map);
aspeed_g6_clk_data->num = ASPEED_G6_NUM_CLKS;
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, aspeed_g6_clk_data);
if (ret)
pr_err("failed to add DT provider: %d\n", ret);
};
CLK_OF_DECLARE_DRIVER(aspeed_cc_g6, "aspeed,ast2600-scu", aspeed_g6_cc_init);

View File

@ -18,10 +18,13 @@ static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
int ret;
int i;
for (i = 0; i < num_clks; i++)
for (i = 0; i < num_clks; i++) {
clks[i].id = NULL;
clks[i].clk = NULL;
}
for (i = 0; i < num_clks; i++) {
of_property_read_string_index(np, "clock-names", i, &clks[i].id);
clks[i].clk = of_clk_get(np, i);
if (IS_ERR(clks[i].clk)) {
ret = PTR_ERR(clks[i].clk);

View File

@ -16,6 +16,7 @@
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/gcd.h>
@ -602,6 +603,30 @@ of_clk_cdce925_get(struct of_phandle_args *clkspec, void *_data)
return &data->clk[idx].hw;
}
static void cdce925_regulator_disable(void *regulator)
{
regulator_disable(regulator);
}
static int cdce925_regulator_enable(struct device *dev, const char *name)
{
struct regulator *regulator;
int err;
regulator = devm_regulator_get(dev, name);
if (IS_ERR(regulator))
return PTR_ERR(regulator);
err = regulator_enable(regulator);
if (err) {
dev_err(dev, "Failed to enable %s: %d\n", name, err);
return err;
}
return devm_add_action_or_reset(dev, cdce925_regulator_disable,
regulator);
}
/* The CDCE925 uses a funky way to read/write registers. Bulk mode is
* just weird, so just use the single byte mode exclusively. */
static struct regmap_bus regmap_cdce925_bus = {
@ -630,6 +655,15 @@ static int cdce925_probe(struct i2c_client *client,
};
dev_dbg(&client->dev, "%s\n", __func__);
err = cdce925_regulator_enable(&client->dev, "vdd");
if (err)
return err;
err = cdce925_regulator_enable(&client->dev, "vddout");
if (err)
return err;
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;

View File

@ -3,7 +3,6 @@
* Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/err.h>
#include <linux/slab.h>

View File

@ -198,7 +198,7 @@ static u8 lochnagar_clk_get_parent(struct clk_hw *hw)
if (ret < 0) {
dev_dbg(priv->dev, "Failed to read parent of %s: %d\n",
lclk->name, ret);
return hw->init->num_parents;
return clk_hw_get_num_parents(hw);
}
val &= lclk->src_mask;

View File

@ -437,7 +437,7 @@ static int m10v_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
if (readl_poll_timeout(divider->write_valid_reg, val,
!val, M10V_UPOLL_RATE, M10V_UTIMEOUT))
pr_err("%s:%s couldn't stabilize\n",
__func__, divider->hw.init->name);
__func__, clk_hw_get_name(hw));
}
if (divider->lock)

View File

@ -686,7 +686,7 @@ static const struct clockgen_chipinfo chipinfo[] = {
.guts_compat = "fsl,qoriq-device-config-1.0",
.init_periph = p5020_init_periph,
.cmux_groups = {
&p2041_cmux_grp1, &p2041_cmux_grp2
&p5020_cmux_grp1, &p5020_cmux_grp2
},
.cmux_to_group = {
0, 1, -1

View File

@ -547,7 +547,6 @@ static int si5341_synth_clk_set_rate(struct clk_hw *hw, unsigned long rate,
bool is_integer;
n_num = synth->data->freq_vco;
n_den = rate;
/* see if there's an integer solution */
r = do_div(n_num, rate);

View File

@ -37,6 +37,12 @@ static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
static LIST_HEAD(clk_notifier_list);
static struct hlist_head *all_lists[] = {
&clk_root_list,
&clk_orphan_list,
NULL,
};
/*** private data structures ***/
struct clk_parent_map {
@ -615,6 +621,8 @@ static void clk_core_get_boundaries(struct clk_core *core,
{
struct clk *clk_user;
lockdep_assert_held(&prepare_lock);
*min_rate = core->min_rate;
*max_rate = core->max_rate;
@ -2460,7 +2468,7 @@ static int clk_core_set_parent_nolock(struct clk_core *core,
if (core->parent == parent)
return 0;
/* verify ops for for multi-parent clks */
/* verify ops for multi-parent clks */
if (core->num_parents > 1 && !core->ops->set_parent)
return -EPERM;
@ -2862,12 +2870,6 @@ static int inited = 0;
static DEFINE_MUTEX(clk_debug_lock);
static HLIST_HEAD(clk_debug_list);
static struct hlist_head *all_lists[] = {
&clk_root_list,
&clk_orphan_list,
NULL,
};
static struct hlist_head *orphan_list[] = {
&clk_orphan_list,
NULL,
@ -2876,9 +2878,6 @@ static struct hlist_head *orphan_list[] = {
static void clk_summary_show_one(struct seq_file *s, struct clk_core *c,
int level)
{
if (!c)
return;
seq_printf(s, "%*s%-*s %7d %8d %8d %11lu %10lu %5d %6d\n",
level * 3 + 1, "",
30 - level * 3, c->name,
@ -2893,9 +2892,6 @@ static void clk_summary_show_subtree(struct seq_file *s, struct clk_core *c,
{
struct clk_core *child;
if (!c)
return;
clk_summary_show_one(s, c, level);
hlist_for_each_entry(child, &c->children, child_node)
@ -2925,8 +2921,9 @@ DEFINE_SHOW_ATTRIBUTE(clk_summary);
static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
{
if (!c)
return;
unsigned long min_rate, max_rate;
clk_core_get_boundaries(c, &min_rate, &max_rate);
/* This should be JSON format, i.e. elements separated with a comma */
seq_printf(s, "\"%s\": { ", c->name);
@ -2934,6 +2931,8 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
seq_printf(s, "\"prepare_count\": %d,", c->prepare_count);
seq_printf(s, "\"protect_count\": %d,", c->protect_count);
seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
seq_printf(s, "\"min_rate\": %lu,", min_rate);
seq_printf(s, "\"max_rate\": %lu,", max_rate);
seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
seq_printf(s, "\"duty_cycle\": %u",
@ -2944,9 +2943,6 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
{
struct clk_core *child;
if (!c)
return;
clk_dump_one(s, c, level);
hlist_for_each_entry(child, &c->children, child_node) {
@ -3042,15 +3038,15 @@ static void possible_parent_show(struct seq_file *s, struct clk_core *core,
*/
parent = clk_core_get_parent_by_index(core, i);
if (parent)
seq_printf(s, "%s", parent->name);
seq_puts(s, parent->name);
else if (core->parents[i].name)
seq_printf(s, "%s", core->parents[i].name);
seq_puts(s, core->parents[i].name);
else if (core->parents[i].fw_name)
seq_printf(s, "<%s>(fw)", core->parents[i].fw_name);
else if (core->parents[i].index >= 0)
seq_printf(s, "%s",
of_clk_get_parent_name(core->of_node,
core->parents[i].index));
seq_puts(s,
of_clk_get_parent_name(core->of_node,
core->parents[i].index));
else
seq_puts(s, "(missing)");
@ -3093,6 +3089,34 @@ static int clk_duty_cycle_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(clk_duty_cycle);
static int clk_min_rate_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
unsigned long min_rate, max_rate;
clk_prepare_lock();
clk_core_get_boundaries(core, &min_rate, &max_rate);
clk_prepare_unlock();
seq_printf(s, "%lu\n", min_rate);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(clk_min_rate);
static int clk_max_rate_show(struct seq_file *s, void *data)
{
struct clk_core *core = s->private;
unsigned long min_rate, max_rate;
clk_prepare_lock();
clk_core_get_boundaries(core, &min_rate, &max_rate);
clk_prepare_unlock();
seq_printf(s, "%lu\n", max_rate);
return 0;
}
DEFINE_SHOW_ATTRIBUTE(clk_max_rate);
static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
struct dentry *root;
@ -3104,6 +3128,8 @@ static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
core->dentry = root;
debugfs_create_ulong("clk_rate", 0444, root, &core->rate);
debugfs_create_file("clk_min_rate", 0444, root, core, &clk_min_rate_fops);
debugfs_create_file("clk_max_rate", 0444, root, core, &clk_max_rate_fops);
debugfs_create_ulong("clk_accuracy", 0444, root, &core->accuracy);
debugfs_create_u32("clk_phase", 0444, root, &core->phase);
debugfs_create_file("clk_flags", 0444, root, core, &clk_flags_fops);
@ -3513,9 +3539,9 @@ static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
return 0;
}
static int clk_core_populate_parent_map(struct clk_core *core)
static int clk_core_populate_parent_map(struct clk_core *core,
const struct clk_init_data *init)
{
const struct clk_init_data *init = core->hw->init;
u8 num_parents = init->num_parents;
const char * const *parent_names = init->parent_names;
const struct clk_hw **parent_hws = init->parent_hws;
@ -3595,6 +3621,14 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
{
int ret;
struct clk_core *core;
const struct clk_init_data *init = hw->init;
/*
* The init data is not supposed to be used outside of registration path.
* Set it to NULL so that provider drivers can't use it either and so that
* we catch use of hw->init early on in the core.
*/
hw->init = NULL;
core = kzalloc(sizeof(*core), GFP_KERNEL);
if (!core) {
@ -3602,17 +3636,17 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
goto fail_out;
}
core->name = kstrdup_const(hw->init->name, GFP_KERNEL);
core->name = kstrdup_const(init->name, GFP_KERNEL);
if (!core->name) {
ret = -ENOMEM;
goto fail_name;
}
if (WARN_ON(!hw->init->ops)) {
if (WARN_ON(!init->ops)) {
ret = -EINVAL;
goto fail_ops;
}
core->ops = hw->init->ops;
core->ops = init->ops;
if (dev && pm_runtime_enabled(dev))
core->rpm_enabled = true;
@ -3621,13 +3655,13 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
if (dev && dev->driver)
core->owner = dev->driver->owner;
core->hw = hw;
core->flags = hw->init->flags;
core->num_parents = hw->init->num_parents;
core->flags = init->flags;
core->num_parents = init->num_parents;
core->min_rate = 0;
core->max_rate = ULONG_MAX;
hw->core = core;
ret = clk_core_populate_parent_map(core);
ret = clk_core_populate_parent_map(core, init);
if (ret)
goto fail_parents;
@ -3766,6 +3800,34 @@ static const struct clk_ops clk_nodrv_ops = {
.set_parent = clk_nodrv_set_parent,
};
static void clk_core_evict_parent_cache_subtree(struct clk_core *root,
struct clk_core *target)
{
int i;
struct clk_core *child;
for (i = 0; i < root->num_parents; i++)
if (root->parents[i].core == target)
root->parents[i].core = NULL;
hlist_for_each_entry(child, &root->children, child_node)
clk_core_evict_parent_cache_subtree(child, target);
}
/* Remove this clk from all parent caches */
static void clk_core_evict_parent_cache(struct clk_core *core)
{
struct hlist_head **lists;
struct clk_core *root;
lockdep_assert_held(&prepare_lock);
for (lists = all_lists; *lists; lists++)
hlist_for_each_entry(root, *lists, child_node)
clk_core_evict_parent_cache_subtree(root, core);
}
/**
* clk_unregister - unregister a currently registered clock
* @clk: clock to unregister
@ -3804,6 +3866,8 @@ void clk_unregister(struct clk *clk)
clk_core_set_parent_nolock(child, NULL);
}
clk_core_evict_parent_cache(clk->core);
hlist_del_init(&clk->core->child_node);
if (clk->core->prepare_count)
@ -4345,12 +4409,43 @@ void devm_of_clk_del_provider(struct device *dev)
}
EXPORT_SYMBOL(devm_of_clk_del_provider);
/*
* Beware the return values when np is valid, but no clock provider is found.
* If name == NULL, the function returns -ENOENT.
* If name != NULL, the function returns -EINVAL. This is because
* of_parse_phandle_with_args() is called even if of_property_match_string()
* returns an error.
/**
* of_parse_clkspec() - Parse a DT clock specifier for a given device node
* @np: device node to parse clock specifier from
* @index: index of phandle to parse clock out of. If index < 0, @name is used
* @name: clock name to find and parse. If name is NULL, the index is used
* @out_args: Result of parsing the clock specifier
*
* Parses a device node's "clocks" and "clock-names" properties to find the
* phandle and cells for the index or name that is desired. The resulting clock
* specifier is placed into @out_args, or an errno is returned when there's a
* parsing error. The @index argument is ignored if @name is non-NULL.
*
* Example:
*
* phandle1: clock-controller@1 {
* #clock-cells = <2>;
* }
*
* phandle2: clock-controller@2 {
* #clock-cells = <1>;
* }
*
* clock-consumer@3 {
* clocks = <&phandle1 1 2 &phandle2 3>;
* clock-names = "name1", "name2";
* }
*
* To get a device_node for `clock-controller@2' node you may call this
* function a few different ways:
*
* of_parse_clkspec(clock-consumer@3, -1, "name2", &args);
* of_parse_clkspec(clock-consumer@3, 1, NULL, &args);
* of_parse_clkspec(clock-consumer@3, 1, "name2", &args);
*
* Return: 0 upon successfully parsing the clock specifier. Otherwise, -ENOENT
* if @name is NULL or -EINVAL if @name is non-NULL and it can't be found in
* the "clock-names" property of @np.
*/
static int of_parse_clkspec(const struct device_node *np, int index,
const char *name, struct of_phandle_args *out_args)

View File

@ -778,12 +778,15 @@ int of_davinci_pll_init(struct device *dev, struct device_node *node,
int i;
clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
if (!clk_data)
if (!clk_data) {
of_node_put(child);
return -ENOMEM;
}
clks = kmalloc_array(n_clks, sizeof(*clks), GFP_KERNEL);
if (!clks) {
kfree(clk_data);
of_node_put(child);
return -ENOMEM;
}

View File

@ -42,6 +42,19 @@ static const struct clk_div_table ulp_div_table[] = {
{ .val = 7, .div = 64, },
};
static const int pcc2_uart_clk_ids[] __initconst = {
IMX7ULP_CLK_LPUART4,
IMX7ULP_CLK_LPUART5,
};
static const int pcc3_uart_clk_ids[] __initconst = {
IMX7ULP_CLK_LPUART6,
IMX7ULP_CLK_LPUART7,
};
static struct clk **pcc2_uart_clks[ARRAY_SIZE(pcc2_uart_clk_ids) + 1] __initdata;
static struct clk **pcc3_uart_clks[ARRAY_SIZE(pcc3_uart_clk_ids) + 1] __initdata;
static void __init imx7ulp_clk_scg1_init(struct device_node *np)
{
struct clk_hw_onecell_data *clk_data;
@ -135,6 +148,7 @@ static void __init imx7ulp_clk_pcc2_init(struct device_node *np)
struct clk_hw_onecell_data *clk_data;
struct clk_hw **clks;
void __iomem *base;
int i;
clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC2_END),
GFP_KERNEL);
@ -173,6 +187,14 @@ static void __init imx7ulp_clk_pcc2_init(struct device_node *np)
imx_check_clk_hws(clks, clk_data->num);
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
for (i = 0; i < ARRAY_SIZE(pcc2_uart_clk_ids); i++) {
int index = pcc2_uart_clk_ids[i];
pcc2_uart_clks[i] = &clks[index]->clk;
}
imx_register_uart_clocks(pcc2_uart_clks);
}
CLK_OF_DECLARE(imx7ulp_clk_pcc2, "fsl,imx7ulp-pcc2", imx7ulp_clk_pcc2_init);
@ -181,6 +203,7 @@ static void __init imx7ulp_clk_pcc3_init(struct device_node *np)
struct clk_hw_onecell_data *clk_data;
struct clk_hw **clks;
void __iomem *base;
int i;
clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC3_END),
GFP_KERNEL);
@ -218,6 +241,14 @@ static void __init imx7ulp_clk_pcc3_init(struct device_node *np)
imx_check_clk_hws(clks, clk_data->num);
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
for (i = 0; i < ARRAY_SIZE(pcc3_uart_clk_ids); i++) {
int index = pcc3_uart_clk_ids[i];
pcc3_uart_clks[i] = &clks[index]->clk;
}
imx_register_uart_clocks(pcc3_uart_clks);
}
CLK_OF_DECLARE(imx7ulp_clk_pcc3, "fsl,imx7ulp-pcc3", imx7ulp_clk_pcc3_init);

View File

@ -22,7 +22,7 @@ static u32 share_count_sai3;
static u32 share_count_sai4;
static u32 share_count_sai5;
static u32 share_count_sai6;
static u32 share_count_dcss;
static u32 share_count_disp;
static u32 share_count_pdm;
static u32 share_count_nand;
@ -38,8 +38,8 @@ static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
};
static const struct imx_pll14xx_rate_table imx8mm_audiopll_tbl[] = {
PLL_1443X_RATE(786432000U, 655, 5, 2, 23593),
PLL_1443X_RATE(722534400U, 301, 5, 1, 3670),
PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
};
static const struct imx_pll14xx_rate_table imx8mm_videopll_tbl[] = {
@ -51,43 +51,43 @@ static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
};
static struct imx_pll14xx_clk imx8mm_audio_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_audio_pll = {
.type = PLL_1443X,
.rate_table = imx8mm_audiopll_tbl,
.rate_count = ARRAY_SIZE(imx8mm_audiopll_tbl),
};
static struct imx_pll14xx_clk imx8mm_video_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_video_pll = {
.type = PLL_1443X,
.rate_table = imx8mm_videopll_tbl,
.rate_count = ARRAY_SIZE(imx8mm_videopll_tbl),
};
static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_dram_pll = {
.type = PLL_1443X,
.rate_table = imx8mm_drampll_tbl,
.rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
};
static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_arm_pll = {
.type = PLL_1416X,
.rate_table = imx8mm_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mm_gpu_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_gpu_pll = {
.type = PLL_1416X,
.rate_table = imx8mm_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mm_vpu_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_vpu_pll = {
.type = PLL_1416X,
.rate_table = imx8mm_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
static struct imx_pll14xx_clk imx8mm_sys_pll = {
.type = PLL_1416X,
.rate_table = imx8mm_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
@ -175,10 +175,10 @@ static const char *imx8mm_vpu_g1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_8
static const char *imx8mm_vpu_g2_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
"sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
static const char *imx8mm_disp_dtrc_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
static const char *imx8mm_disp_dtrc_sels[] = {"osc_24m", "dummy", "sys_pll1_800m", "sys_pll2_1000m",
"sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
static const char *imx8mm_disp_dc8000_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
static const char *imx8mm_disp_dc8000_sels[] = {"osc_24m", "dummy", "sys_pll1_800m", "sys_pll2_1000m",
"sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
static const char *imx8mm_pcie1_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
@ -232,7 +232,7 @@ static const char *imx8mm_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll
static const char *imx8mm_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", "sys_pll1_400m",
"audio_pll2_out", "sys_pll3_out", "sys_pll2_250m", "video_pll1_out", };
static const char *imx8mm_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
static const char *imx8mm_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m", "sys_pll2_500m",
"audio_pll2_out", "sys_pll1_266m", "sys_pll3_out", "sys_pll1_100m", };
static const char *imx8mm_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
@ -287,13 +287,13 @@ static const char *imx8mm_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_1
"sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
static const char *imx8mm_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
"sys3_pll2_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
"sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
static const char *imx8mm_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
"sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
static const char *imx8mm_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", "sys_pll1_40m",
"video_pll1_out", "sys_pll1_800m", "audio_pll1_out", "clk_ext1" };
"video_pll1_out", "sys_pll1_80m", "audio_pll1_out", "clk_ext1" };
static const char *imx8mm_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
"sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
@ -347,7 +347,7 @@ static const char *imx8mm_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_
"sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
static const char *imx8mm_vpu_h1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
"audio_pll2_out", "sys_pll2_125m", "sys_pll3_clk", "audio_pll1_out", };
"audio_pll2_out", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
@ -357,7 +357,7 @@ static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
static struct clk *clks[IMX8MM_CLK_END];
static struct clk_onecell_data clk_data;
static struct clk ** const uart_clks[] __initconst = {
static struct clk ** const uart_clks[] = {
&clks[IMX8MM_CLK_UART1_ROOT],
&clks[IMX8MM_CLK_UART2_ROOT],
&clks[IMX8MM_CLK_UART3_ROOT],
@ -365,19 +365,20 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
static int __init imx8mm_clocks_init(struct device_node *ccm_node)
static int imx8mm_clocks_probe(struct platform_device *pdev)
{
struct device_node *np;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
void __iomem *base;
int ret;
clks[IMX8MM_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
clks[IMX8MM_CLK_24M] = of_clk_get_by_name(ccm_node, "osc_24m");
clks[IMX8MM_CLK_32K] = of_clk_get_by_name(ccm_node, "osc_32k");
clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(ccm_node, "clk_ext1");
clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(ccm_node, "clk_ext2");
clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(ccm_node, "clk_ext3");
clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(ccm_node, "clk_ext4");
clks[IMX8MM_CLK_24M] = of_clk_get_by_name(np, "osc_24m");
clks[IMX8MM_CLK_32K] = of_clk_get_by_name(np, "osc_32k");
clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(np, "clk_ext1");
clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(np, "clk_ext2");
clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(np, "clk_ext3");
clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
base = of_iomap(np, 0);
@ -407,28 +408,16 @@ static int __init imx8mm_clocks_init(struct device_node *ccm_node)
clks[IMX8MM_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mm_sys_pll);
/* PLL bypass out */
clks[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
/* unbypass all the plls */
clk_set_parent(clks[IMX8MM_AUDIO_PLL1_BYPASS], clks[IMX8MM_AUDIO_PLL1]);
clk_set_parent(clks[IMX8MM_AUDIO_PLL2_BYPASS], clks[IMX8MM_AUDIO_PLL2]);
clk_set_parent(clks[IMX8MM_VIDEO_PLL1_BYPASS], clks[IMX8MM_VIDEO_PLL1]);
clk_set_parent(clks[IMX8MM_DRAM_PLL_BYPASS], clks[IMX8MM_DRAM_PLL]);
clk_set_parent(clks[IMX8MM_GPU_PLL_BYPASS], clks[IMX8MM_GPU_PLL]);
clk_set_parent(clks[IMX8MM_VPU_PLL_BYPASS], clks[IMX8MM_VPU_PLL]);
clk_set_parent(clks[IMX8MM_ARM_PLL_BYPASS], clks[IMX8MM_ARM_PLL]);
clk_set_parent(clks[IMX8MM_SYS_PLL1_BYPASS], clks[IMX8MM_SYS_PLL1]);
clk_set_parent(clks[IMX8MM_SYS_PLL2_BYPASS], clks[IMX8MM_SYS_PLL2]);
clk_set_parent(clks[IMX8MM_SYS_PLL3_BYPASS], clks[IMX8MM_SYS_PLL3]);
clks[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 28, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 28, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MM_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
/* PLL out gate */
clks[IMX8MM_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
@ -463,10 +452,10 @@ static int __init imx8mm_clocks_init(struct device_node *ccm_node)
clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
clks[IMX8MM_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
np = ccm_node;
base = of_iomap(np, 0);
if (WARN_ON(!base))
return -ENOMEM;
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base)))
return PTR_ERR(base);
/* Core Slice */
clks[IMX8MM_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels));
@ -614,7 +603,7 @@ static int __init imx8mm_clocks_init(struct device_node *ccm_node)
clks[IMX8MM_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
clks[IMX8MM_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
clks[IMX8MM_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
clks[IMX8MM_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
clks[IMX8MM_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0);
clks[IMX8MM_CLK_GPU3D_ROOT] = imx_clk_gate4("gpu3d_root_clk", "gpu3d_div", base + 0x44f0, 0);
clks[IMX8MM_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
clks[IMX8MM_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
@ -627,10 +616,10 @@ static int __init imx8mm_clocks_init(struct device_node *ccm_node)
clks[IMX8MM_CLK_VPU_G2_ROOT] = imx_clk_gate4("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0);
clks[IMX8MM_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", base + 0x45b0, 0, &share_count_pdm);
clks[IMX8MM_CLK_PDM_IPG] = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", base + 0x45b0, 0, &share_count_pdm);
clks[IMX8MM_CLK_DISP_ROOT] = imx_clk_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MM_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MM_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MM_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MM_CLK_DISP_ROOT] = imx_clk_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0, &share_count_disp);
clks[IMX8MM_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_disp);
clks[IMX8MM_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_disp);
clks[IMX8MM_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0, &share_count_disp);
clks[IMX8MM_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0);
clks[IMX8MM_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0);
clks[IMX8MM_CLK_VPU_DEC_ROOT] = imx_clk_gate4("vpu_dec_root_clk", "vpu_bus", base + 0x4630, 0);
@ -658,11 +647,30 @@ static int __init imx8mm_clocks_init(struct device_node *ccm_node)
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
if (ret < 0) {
pr_err("failed to register clks for i.MX8MM\n");
return -EINVAL;
goto unregister_clks;
}
imx_register_uart_clocks(uart_clks);
return 0;
unregister_clks:
imx_unregister_clocks(clks, ARRAY_SIZE(clks));
return ret;
}
CLK_OF_DECLARE_DRIVER(imx8mm, "fsl,imx8mm-ccm", imx8mm_clocks_init);
static const struct of_device_id imx8mm_clk_of_match[] = {
{ .compatible = "fsl,imx8mm-ccm" },
{ /* Sentinel */ },
};
MODULE_DEVICE_TABLE(of, imx8mm_clk_of_match);
static struct platform_driver imx8mm_clk_driver = {
.probe = imx8mm_clocks_probe,
.driver = {
.name = "imx8mm-ccm",
.of_match_table = of_match_ptr(imx8mm_clk_of_match),
},
};
module_platform_driver(imx8mm_clk_driver);

View File

@ -42,6 +42,8 @@ enum {
static const struct imx_pll14xx_rate_table imx8mn_pll1416x_tbl[] = {
PLL_1416X_RATE(1800000000U, 225, 3, 0),
PLL_1416X_RATE(1600000000U, 200, 3, 0),
PLL_1416X_RATE(1500000000U, 375, 3, 1),
PLL_1416X_RATE(1400000000U, 350, 3, 1),
PLL_1416X_RATE(1200000000U, 300, 3, 1),
PLL_1416X_RATE(1000000000U, 250, 3, 1),
PLL_1416X_RATE(800000000U, 200, 3, 1),
@ -51,8 +53,8 @@ static const struct imx_pll14xx_rate_table imx8mn_pll1416x_tbl[] = {
};
static const struct imx_pll14xx_rate_table imx8mn_audiopll_tbl[] = {
PLL_1443X_RATE(786432000U, 655, 5, 2, 23593),
PLL_1443X_RATE(722534400U, 301, 5, 1, 3670),
PLL_1443X_RATE(393216000U, 262, 2, 3, 9437),
PLL_1443X_RATE(361267200U, 361, 3, 3, 17511),
};
static const struct imx_pll14xx_rate_table imx8mn_videopll_tbl[] = {
@ -67,36 +69,43 @@ static const struct imx_pll14xx_rate_table imx8mn_drampll_tbl[] = {
static struct imx_pll14xx_clk imx8mn_audio_pll = {
.type = PLL_1443X,
.rate_table = imx8mn_audiopll_tbl,
.rate_count = ARRAY_SIZE(imx8mn_audiopll_tbl),
};
static struct imx_pll14xx_clk imx8mn_video_pll = {
.type = PLL_1443X,
.rate_table = imx8mn_videopll_tbl,
.rate_count = ARRAY_SIZE(imx8mn_videopll_tbl),
};
static struct imx_pll14xx_clk imx8mn_dram_pll = {
.type = PLL_1443X,
.rate_table = imx8mn_drampll_tbl,
.rate_count = ARRAY_SIZE(imx8mn_drampll_tbl),
};
static struct imx_pll14xx_clk imx8mn_arm_pll = {
.type = PLL_1416X,
.rate_table = imx8mn_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mn_gpu_pll = {
.type = PLL_1416X,
.rate_table = imx8mn_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mn_vpu_pll = {
.type = PLL_1416X,
.rate_table = imx8mn_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl),
};
static struct imx_pll14xx_clk imx8mn_sys_pll = {
.type = PLL_1416X,
.rate_table = imx8mn_pll1416x_tbl,
.rate_count = ARRAY_SIZE(imx8mn_pll1416x_tbl),
};
static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
@ -140,7 +149,7 @@ static const char * const imx8mn_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m",
"clk_ext1", "clk_ext4", };
static const char * const imx8mn_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m",
"sys_pll3_out", "sys1_pll_40m", "audio_pll2_out",
"sys_pll3_out", "sys_pll1_40m", "audio_pll2_out",
"clk_ext1", "clk_ext3", };
static const char * const imx8mn_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m",
@ -219,9 +228,9 @@ static const char * const imx8mn_nand_sels[] = {"osc_24m", "sys_pll2_500m", "aud
"sys_pll1_400m", "audio_pll2_out", "sys_pll3_out",
"sys_pll2_250m", "video_pll1_out", };
static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys1_pll_400m", "sys_pll1_800m",
"sys2_pll_500m", "audio_pll2_out", "sys1_pll_266m",
"sys3_pll2_out", "sys1_pll_100m", };
static const char * const imx8mn_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll2_333m",
"sys_pll2_500m", "audio_pll2_out", "sys_pll1_266m",
"sys_pll3_out", "sys_pll1_100m", };
static const char * const imx8mn_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
@ -271,6 +280,10 @@ static const char * const imx8mn_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "
"sys_pll2_100m", "sys_pll2_200m", "clk_ext2",
"clk_ext3", "audio_pll2_out", };
static const char * const imx8mn_gic_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll2_100m", "sys_pll1_800m", "clk_ext2",
"clk_ext4", "audio_pll2_out" };
static const char * const imx8mn_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m",
"sys_pll1_160m", "sys_pll1_800m", "sys_pll3_out",
"sys_pll2_250m", "audio_pll2_out", };
@ -288,7 +301,7 @@ static const char * const imx8mn_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys
"sys_pll1_80m", "video_pll1_out", };
static const char * const imx8mn_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
"sys_pll1_40m", "sys3_pll2_out", "clk_ext2",
"sys_pll1_40m", "sys_pll3_out", "clk_ext2",
"sys_pll1_80m", "video_pll1_out", };
static const char * const imx8mn_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m",
@ -317,7 +330,7 @@ static const char * const imx8mn_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "
static const char * const imx8mn_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m",
"sys_pll2_500m", "sys_pll3_out", "sys_pll1_266m",
"audio_pll2_clk", "sys_pll1_100m", };
"audio_pll2_out", "sys_pll1_100m", };
static const char * const imx8mn_camera_pixel_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m",
"sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out",
@ -346,7 +359,7 @@ static const char * const imx8mn_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audi
static const char * const imx8mn_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
static const char * const imx8mn_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m",
"sys_pll1_200m", "audio_pll2_clk", "vpu_pll",
"sys_pll1_200m", "audio_pll2_out", "vpu_pll",
"sys_pll1_80m", };
static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_400m",
"sys_pll2_166m", "sys_pll3_out", "audio_pll1_out",
@ -355,6 +368,14 @@ static const char * const imx8mn_clko2_sels[] = {"osc_24m", "sys_pll2_200m", "sy
static struct clk *clks[IMX8MN_CLK_END];
static struct clk_onecell_data clk_data;
static struct clk ** const uart_clks[] = {
&clks[IMX8MN_CLK_UART1_ROOT],
&clks[IMX8MN_CLK_UART2_ROOT],
&clks[IMX8MN_CLK_UART3_ROOT],
&clks[IMX8MN_CLK_UART4_ROOT],
NULL
};
static int imx8mn_clocks_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@ -400,40 +421,28 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
clks[IMX8MN_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mn_sys_pll);
/* PLL bypass out */
clks[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
/* unbypass all the plls */
clk_set_parent(clks[IMX8MN_AUDIO_PLL1_BYPASS], clks[IMX8MN_AUDIO_PLL1]);
clk_set_parent(clks[IMX8MN_AUDIO_PLL2_BYPASS], clks[IMX8MN_AUDIO_PLL2]);
clk_set_parent(clks[IMX8MN_VIDEO_PLL1_BYPASS], clks[IMX8MN_VIDEO_PLL1]);
clk_set_parent(clks[IMX8MN_DRAM_PLL_BYPASS], clks[IMX8MN_DRAM_PLL]);
clk_set_parent(clks[IMX8MN_GPU_PLL_BYPASS], clks[IMX8MN_GPU_PLL]);
clk_set_parent(clks[IMX8MN_VPU_PLL_BYPASS], clks[IMX8MN_VPU_PLL]);
clk_set_parent(clks[IMX8MN_ARM_PLL_BYPASS], clks[IMX8MN_ARM_PLL]);
clk_set_parent(clks[IMX8MN_SYS_PLL1_BYPASS], clks[IMX8MN_SYS_PLL1]);
clk_set_parent(clks[IMX8MN_SYS_PLL2_BYPASS], clks[IMX8MN_SYS_PLL2]);
clk_set_parent(clks[IMX8MN_SYS_PLL3_BYPASS], clks[IMX8MN_SYS_PLL3]);
clks[IMX8MN_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 16, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 16, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 16, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 16, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 28, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 28, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 28, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 28, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 28, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
clks[IMX8MN_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 28, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
/* PLL out gate */
clks[IMX8MN_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
clks[IMX8MN_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
clks[IMX8MN_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
clks[IMX8MN_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
clks[IMX8MN_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13);
clks[IMX8MN_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13);
clks[IMX8MN_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13);
clks[IMX8MN_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13);
clks[IMX8MN_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13);
clks[IMX8MN_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13);
clks[IMX8MN_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 11);
clks[IMX8MN_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 11);
clks[IMX8MN_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 11);
clks[IMX8MN_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 11);
clks[IMX8MN_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 11);
clks[IMX8MN_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 11);
/* SYS PLL fixed output */
clks[IMX8MN_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
@ -516,6 +525,7 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
clks[IMX8MN_CLK_UART4] = imx8m_clk_composite("uart4", imx8mn_uart4_sels, base + 0xb080);
clks[IMX8MN_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mn_usb_core_sels, base + 0xb100);
clks[IMX8MN_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mn_usb_phy_sels, base + 0xb180);
clks[IMX8MN_CLK_GIC] = imx8m_clk_composite_critical("gic", imx8mn_gic_sels, base + 0xb200);
clks[IMX8MN_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mn_ecspi1_sels, base + 0xb280);
clks[IMX8MN_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mn_ecspi2_sels, base + 0xb300);
clks[IMX8MN_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mn_pwm1_sels, base + 0xb380);
@ -612,6 +622,8 @@ static int imx8mn_clocks_probe(struct platform_device *pdev)
goto unregister_clks;
}
imx_register_uart_clocks(uart_clks);
return 0;
unregister_clks:

View File

@ -41,34 +41,34 @@ static const char * const dram_pll_out_sels[] = {"dram_pll1_ref_sel", };
/* CCM ROOT */
static const char * const imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
"sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "sys3_pll2_out", };
"sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "sys3_pll_out", };
static const char * const imx8mq_arm_m4_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_250m", "sys1_pll_266m",
"sys1_pll_800m", "audio_pll1_out", "video_pll1_out", "sys3_pll2_out", };
"sys1_pll_800m", "audio_pll1_out", "video_pll1_out", "sys3_pll_out", };
static const char * const imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
"sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "vpu_pll_out", };
static const char * const imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
static const char * const imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll_out",
"sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
static const char * const imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll_out",
"sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", "sys1_pll_800m", "sys2_pll_250m",
"sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
static const char * const imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m",
"sys2_pll_200m", "audio_pll1_out", "video_pll1_out", "sys3_pll2_out", };
"sys2_pll_200m", "audio_pll1_out", "video_pll1_out", "sys3_pll_out", };
static const char * const imx8mq_nand_usdhc_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_200m",
"sys1_pll_133m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll1_out", };
"sys1_pll_133m", "sys3_pll_out", "sys2_pll_250m", "audio_pll1_out", };
static const char * const imx8mq_vpu_bus_sels[] = {"osc_25m", "sys1_pll_800m", "vpu_pll_out", "audio_pll2_out", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_200m", "sys1_pll_100m", };
static const char * const imx8mq_vpu_bus_sels[] = {"osc_25m", "sys1_pll_800m", "vpu_pll_out", "audio_pll2_out", "sys3_pll_out", "sys2_pll_1000m", "sys2_pll_200m", "sys1_pll_100m", };
static const char * const imx8mq_disp_axi_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out", "sys1_pll_400m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
static const char * const imx8mq_disp_axi_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll_out", "sys1_pll_400m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
static const char * const imx8mq_disp_apb_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out",
static const char * const imx8mq_disp_apb_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll_out",
"sys1_pll_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", };
static const char * const imx8mq_disp_rtrm_sels[] = {"osc_25m", "sys1_pll_800m", "sys2_pll_200m", "sys1_pll_400m",
@ -77,53 +77,53 @@ static const char * const imx8mq_disp_rtrm_sels[] = {"osc_25m", "sys1_pll_800m",
static const char * const imx8mq_usb_bus_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m",
"sys2_pll_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", };
static const char * const imx8mq_gpu_axi_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
static const char * const imx8mq_gpu_axi_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll_out", "sys2_pll_1000m",
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_gpu_ahb_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
static const char * const imx8mq_gpu_ahb_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll_out", "sys2_pll_1000m",
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_noc_sels[] = {"osc_25m", "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_500m",
static const char * const imx8mq_noc_sels[] = {"osc_25m", "sys1_pll_800m", "sys3_pll_out", "sys2_pll_1000m", "sys2_pll_500m",
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_noc_apb_sels[] = {"osc_25m", "sys1_pll_400m", "sys3_pll2_out", "sys2_pll_333m", "sys2_pll_200m",
static const char * const imx8mq_noc_apb_sels[] = {"osc_25m", "sys1_pll_400m", "sys3_pll_out", "sys2_pll_333m", "sys2_pll_200m",
"sys1_pll_800m", "audio_pll1_out", "video_pll1_out", };
static const char * const imx8mq_ahb_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m",
"sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", };
"sys2_pll_125m", "sys3_pll_out", "audio_pll1_out", "video_pll1_out", };
static const char * const imx8mq_audio_ahb_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_1000m",
"sys2_pll_166m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", };
"sys2_pll_166m", "sys3_pll_out", "audio_pll1_out", "video_pll1_out", };
static const char * const imx8mq_dsi_ahb_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out"};
"sys2_pll_1000m", "sys3_pll_out", "clk_ext3", "audio_pll2_out"};
static const char * const imx8mq_dram_alt_sels[] = {"osc_25m", "sys1_pll_800m", "sys1_pll_100m", "sys2_pll_500m",
"sys2_pll_250m", "sys1_pll_400m", "audio_pll1_out", "sys1_pll_266m", };
static const char * const imx8mq_dram_apb_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
"sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
"sys1_pll_800m", "sys3_pll_out", "sys2_pll_250m", "audio_pll2_out", };
static const char * const imx8mq_vpu_g1_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
static const char * const imx8mq_vpu_g1_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll_out", "audio_pll1_out", };
static const char * const imx8mq_vpu_g2_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
static const char * const imx8mq_vpu_g2_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll_out", "audio_pll1_out", };
static const char * const imx8mq_disp_dtrc_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
static const char * const imx8mq_disp_dtrc_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll_out", "audio_pll2_out", };
static const char * const imx8mq_disp_dc8000_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
static const char * const imx8mq_disp_dc8000_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll_out", "audio_pll2_out", };
static const char * const imx8mq_pcie1_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
"sys1_pll_800m", "sys2_pll_500m", "sys2_pll_250m", "sys3_pll2_out", };
"sys1_pll_800m", "sys2_pll_500m", "sys2_pll_250m", "sys3_pll_out", };
static const char * const imx8mq_pcie1_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1", "clk_ext2",
"clk_ext3", "clk_ext4", };
static const char * const imx8mq_pcie1_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_500m", "sys3_pll2_out",
static const char * const imx8mq_pcie1_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_500m", "sys3_pll_out",
"sys2_pll_100m", "sys1_pll_80m", "sys1_pll_160m", "sys1_pll_200m", };
static const char * const imx8mq_dc_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
static const char * const imx8mq_dc_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll_out", "clk_ext4", };
static const char * const imx8mq_lcdif_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
static const char * const imx8mq_lcdif_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll_out", "clk_ext4", };
static const char * const imx8mq_sai1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", };
@ -151,40 +151,40 @@ static const char * const imx8mq_enet_phy_sels[] = {"osc_25m", "sys2_pll_50m", "
"audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
static const char * const imx8mq_nand_sels[] = {"osc_25m", "sys2_pll_500m", "audio_pll1_out", "sys1_pll_400m",
"audio_pll2_out", "sys3_pll2_out", "sys2_pll_250m", "video_pll1_out", };
"audio_pll2_out", "sys3_pll_out", "sys2_pll_250m", "video_pll1_out", };
static const char * const imx8mq_qspi_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
"audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
static const char * const imx8mq_usdhc1_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
"audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
static const char * const imx8mq_usdhc2_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
"audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
"audio_pll2_out", "sys1_pll_266m", "sys3_pll_out", "sys1_pll_100m", };
static const char * const imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
static const char * const imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
static const char * const imx8mq_i2c2_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
static const char * const imx8mq_i2c2_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
static const char * const imx8mq_i2c3_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
static const char * const imx8mq_i2c3_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
static const char * const imx8mq_i2c4_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
static const char * const imx8mq_i2c4_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll_out", "audio_pll1_out",
"video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
static const char * const imx8mq_uart1_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
"sys3_pll2_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
"sys3_pll_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
static const char * const imx8mq_uart2_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
"sys3_pll2_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
"sys3_pll_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
static const char * const imx8mq_uart3_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
"sys3_pll2_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
"sys3_pll_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
static const char * const imx8mq_uart4_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
"sys3_pll2_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
"sys3_pll_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
static const char * const imx8mq_usb_core_sels[] = {"osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m",
"sys2_pll_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
@ -196,79 +196,79 @@ static const char * const imx8mq_gic_sels[] = {"osc_25m", "sys2_pll_200m", "sys1
"sys2_pll_200m", "clk_ext2", "clk_ext3", "audio_pll2_out" };
static const char * const imx8mq_ecspi1_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
"sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
"sys1_pll_800m", "sys3_pll_out", "sys2_pll_250m", "audio_pll2_out", };
static const char * const imx8mq_ecspi2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
"sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
"sys1_pll_800m", "sys3_pll_out", "sys2_pll_250m", "audio_pll2_out", };
static const char * const imx8mq_pwm1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
"sys3_pll2_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
"sys3_pll_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
static const char * const imx8mq_pwm2_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
"sys3_pll2_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
"sys3_pll_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
static const char * const imx8mq_pwm3_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
"sys3_pll2_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
"sys3_pll_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
static const char * const imx8mq_pwm4_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
"sys3_pll2_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
"sys3_pll_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
static const char * const imx8mq_gpt1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_400m", "sys1_pll_40m",
"sys1_pll_80m", "audio_pll1_out", "clk_ext1", };
static const char * const imx8mq_wdog_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_160m", "vpu_pll_out",
"sys2_pll_125m", "sys3_pll2_out", "sys1_pll_80m", "sys2_pll_166m", };
"sys2_pll_125m", "sys3_pll_out", "sys1_pll_80m", "sys2_pll_166m", };
static const char * const imx8mq_wrclk_sels[] = {"osc_25m", "sys1_pll_40m", "vpu_pll_out", "sys3_pll2_out", "sys2_pll_200m",
static const char * const imx8mq_wrclk_sels[] = {"osc_25m", "sys1_pll_40m", "vpu_pll_out", "sys3_pll_out", "sys2_pll_200m",
"sys1_pll_266m", "sys2_pll_500m", "sys1_pll_100m", };
static const char * const imx8mq_dsi_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_dsi_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_dsi_dbi_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_dsi_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
"sys2_pll_1000m", "sys3_pll_out", "clk_ext3", "audio_pll2_out", };
static const char * const imx8mq_csi1_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
"sys2_pll_1000m", "sys3_pll_out", "clk_ext3", "audio_pll2_out", };
static const char * const imx8mq_csi2_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
"sys2_pll_1000m", "sys3_pll_out", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
"sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
static const char * const imx8mq_csi2_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
"sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
"sys2_pll_1000m", "sys3_pll_out", "clk_ext3", "audio_pll2_out", };
static const char * const imx8mq_pcie2_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
"sys1_pll_800m", "sys2_pll_500m", "sys2_pll_333m", "sys3_pll2_out", };
"sys1_pll_800m", "sys2_pll_500m", "sys2_pll_333m", "sys3_pll_out", };
static const char * const imx8mq_pcie2_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1",
"clk_ext2", "clk_ext3", "clk_ext4", "sys1_pll_400m", };
static const char * const imx8mq_pcie2_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_50m", "sys3_pll2_out",
static const char * const imx8mq_pcie2_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_50m", "sys3_pll_out",
"sys2_pll_100m", "sys1_pll_80m", "sys1_pll_160m", "sys1_pll_200m", };
static const char * const imx8mq_ecspi3_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
"sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
"sys1_pll_800m", "sys3_pll_out", "sys2_pll_250m", "audio_pll2_out", };
static const char * const imx8mq_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
static const char * const imx8mq_clko1_sels[] = {"osc_25m", "sys1_pll_800m", "osc_27m", "sys1_pll_200m",
"audio_pll2_out", "sys2_pll_500m", "vpu_pll_out", "sys1_pll_80m", };
static const char * const imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m",
"sys3_pll2_out", "audio_pll1_out", "video_pll1_out", "ckil", };
"sys3_pll_out", "audio_pll1_out", "video_pll1_out", "ckil", };
static struct clk_onecell_data clk_data;
@ -406,7 +406,8 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
clks[IMX8MQ_CLK_NOC_APB] = imx8m_clk_composite_critical("noc_apb", imx8mq_noc_apb_sels, base + 0x8d80);
/* AHB */
clks[IMX8MQ_CLK_AHB] = imx8m_clk_composite("ahb", imx8mq_ahb_sels, base + 0x9000);
/* AHB clock is used by the AHB bus therefore marked as critical */
clks[IMX8MQ_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mq_ahb_sels, base + 0x9000);
clks[IMX8MQ_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mq_audio_ahb_sels, base + 0x9100);
/* IPG */
@ -523,8 +524,8 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
clks[IMX8MQ_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
clks[IMX8MQ_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
clks[IMX8MQ_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
clks[IMX8MQ_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
clks[IMX8MQ_CLK_USB2_CTRL_ROOT] = imx_clk_gate4("usb2_ctrl_root_clk", "usb_core_ref", base + 0x44e0, 0);
clks[IMX8MQ_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_bus", base + 0x44d0, 0);
clks[IMX8MQ_CLK_USB2_CTRL_ROOT] = imx_clk_gate4("usb2_ctrl_root_clk", "usb_bus", base + 0x44e0, 0);
clks[IMX8MQ_CLK_USB1_PHY_ROOT] = imx_clk_gate4("usb1_phy_root_clk", "usb_phy_ref", base + 0x44f0, 0);
clks[IMX8MQ_CLK_USB2_PHY_ROOT] = imx_clk_gate4("usb2_phy_root_clk", "usb_phy_ref", base + 0x4500, 0);
clks[IMX8MQ_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
@ -539,7 +540,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
clks[IMX8MQ_CLK_DISP_AXI_ROOT] = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MQ_CLK_DISP_APB_ROOT] = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MQ_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0, &share_count_dcss);
clks[IMX8MQ_CLK_TMU_ROOT] = imx_clk_gate4_flags("tmu_root_clk", "ipg_root", base + 0x4620, 0, CLK_IS_CRITICAL);
clks[IMX8MQ_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0);
clks[IMX8MQ_CLK_VPU_DEC_ROOT] = imx_clk_gate2_flags("vpu_dec_root_clk", "vpu_bus", base + 0x4630, 0, CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE);
clks[IMX8MQ_CLK_CSI1_ROOT] = imx_clk_gate4("csi1_root_clk", "csi1_core", base + 0x4650, 0);
clks[IMX8MQ_CLK_CSI2_ROOT] = imx_clk_gate4("csi2_root_clk", "csi2_core", base + 0x4660, 0);
@ -561,10 +562,18 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
clk_data.clk_num = ARRAY_SIZE(clks);
err = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
WARN_ON(err);
if (err < 0) {
dev_err(dev, "failed to register clks for i.MX8MQ\n");
goto unregister_clks;
}
imx_register_uart_clocks(uart_clks);
return 0;
unregister_clks:
imx_unregister_clocks(clks, ARRAY_SIZE(clks));
return err;
}

View File

@ -191,6 +191,10 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
tmp &= ~RST_MASK;
writel_relaxed(tmp, pll->base);
/* Enable BYPASS */
tmp |= BYPASS_MASK;
writel(tmp, pll->base);
div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
(rate->sdiv << SDIV_SHIFT);
writel_relaxed(div_val, pll->base + 0x4);
@ -250,6 +254,10 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
tmp &= ~RST_MASK;
writel_relaxed(tmp, pll->base);
/* Enable BYPASS */
tmp |= BYPASS_MASK;
writel_relaxed(tmp, pll->base);
div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
(rate->sdiv << SDIV_SHIFT);
writel_relaxed(div_val, pll->base + 0x4);
@ -283,16 +291,28 @@ static int clk_pll14xx_prepare(struct clk_hw *hw)
{
struct clk_pll14xx *pll = to_clk_pll14xx(hw);
u32 val;
int ret;
/*
* RESETB = 1 from 0, PLL starts its normal
* operation after lock time
*/
val = readl_relaxed(pll->base + GNRL_CTL);
if (val & RST_MASK)
return 0;
val |= BYPASS_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
val |= RST_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
return clk_pll14xx_wait_lock(pll);
ret = clk_pll14xx_wait_lock(pll);
if (ret)
return ret;
val &= ~BYPASS_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
return 0;
}
static int clk_pll14xx_is_prepared(struct clk_hw *hw)
@ -348,6 +368,7 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
struct clk_pll14xx *pll;
struct clk *clk;
struct clk_init_data init;
u32 val;
pll = kzalloc(sizeof(*pll), GFP_KERNEL);
if (!pll)
@ -379,6 +400,10 @@ struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
pll->rate_table = pll_clk->rate_table;
pll->rate_count = pll_clk->rate_count;
val = readl_relaxed(pll->base + GNRL_CTL);
val &= ~BYPASS_MASK;
writel_relaxed(val, pll->base + GNRL_CTL);
clk = clk_register(NULL, &pll->hw);
if (IS_ERR(clk)) {
pr_err("%s: failed to register pll %s %lu\n",

View File

@ -10,7 +10,6 @@ extern spinlock_t imx_ccm_lock;
void imx_check_clocks(struct clk *clks[], unsigned int count);
void imx_check_clk_hws(struct clk_hw *clks[], unsigned int count);
void imx_register_uart_clocks(struct clk ** const clks[]);
void imx_register_uart_clocks_hws(struct clk_hw ** const hws[]);
void imx_mmdc_mask_handshake(void __iomem *ccm_base, unsigned int chn);
void imx_unregister_clocks(struct clk *clks[], unsigned int count);
@ -51,12 +50,6 @@ struct imx_pll14xx_clk {
int flags;
};
#define imx_clk_busy_divider(name, parent_name, reg, shift, width, busy_reg, busy_shift) \
imx_clk_hw_busy_divider(name, parent_name, reg, shift, width, busy_reg, busy_shift)->clk
#define imx_clk_busy_mux(name, reg, shift, width, busy_reg, busy_shift, parent_names, num_parents) \
imx_clk_hw_busy_mux(name, reg, shift, width, busy_reg, busy_shift, parent_names, num_parents)->clk
#define imx_clk_cpu(name, parent_name, div, mux, pll, step) \
imx_clk_hw_cpu(name, parent_name, div, mux, pll, step)->clk
@ -74,15 +67,6 @@ struct imx_pll14xx_clk {
#define imx_clk_gate_exclusive(name, parent, reg, shift, exclusive_mask) \
imx_clk_hw_gate_exclusive(name, parent, reg, shift, exclusive_mask)->clk
#define imx_clk_fixup_divider(name, parent, reg, shift, width, fixup) \
imx_clk_hw_fixup_divider(name, parent, reg, shift, width, fixup)->clk
#define imx_clk_fixup_mux(name, reg, shift, width, parents, num_parents, fixup) \
imx_clk_hw_fixup_mux(name, reg, shift, width, parents, num_parents, fixup)->clk
#define imx_clk_mux_ldb(name, reg, shift, width, parents, num_parents) \
imx_clk_hw_mux_ldb(name, reg, shift, width, parents, num_parents)->clk
#define imx_clk_fixed_factor(name, parent, mult, div) \
imx_clk_hw_fixed_factor(name, parent, mult, div)->clk
@ -92,21 +76,12 @@ struct imx_pll14xx_clk {
#define imx_clk_gate_dis(name, parent, reg, shift) \
imx_clk_hw_gate_dis(name, parent, reg, shift)->clk
#define imx_clk_gate_dis_flags(name, parent, reg, shift, flags) \
imx_clk_hw_gate_dis_flags(name, parent, reg, shift, flags)->clk
#define imx_clk_gate_flags(name, parent, reg, shift, flags) \
imx_clk_hw_gate_flags(name, parent, reg, shift, flags)->clk
#define imx_clk_gate2(name, parent, reg, shift) \
imx_clk_hw_gate2(name, parent, reg, shift)->clk
#define imx_clk_gate2_flags(name, parent, reg, shift, flags) \
imx_clk_hw_gate2_flags(name, parent, reg, shift, flags)->clk
#define imx_clk_gate2_shared(name, parent, reg, shift, share_count) \
imx_clk_hw_gate2_shared(name, parent, reg, shift, share_count)->clk
#define imx_clk_gate2_shared2(name, parent, reg, shift, share_count) \
imx_clk_hw_gate2_shared2(name, parent, reg, shift, share_count)->clk

View File

@ -257,4 +257,4 @@ static void __init jz4725b_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-cgu", jz4725b_cgu_init);

View File

@ -53,6 +53,10 @@ static const u8 jz4740_cgu_cpccr_div_table[] = {
1, 2, 3, 4, 6, 8, 12, 16, 24, 32,
};
static const u8 jz4740_cgu_pll_half_div_table[] = {
2, 1,
};
static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
/* External clocks */
@ -86,7 +90,10 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
[JZ4740_CLK_PLL_HALF] = {
"pll half", CGU_CLK_DIV,
.parents = { JZ4740_CLK_PLL, -1, -1, -1 },
.div = { CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1 },
.div = {
CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1,
jz4740_cgu_pll_half_div_table,
},
},
[JZ4740_CLK_CCLK] = {
@ -241,4 +248,4 @@ static void __init jz4740_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-cgu", jz4740_cgu_init);

View File

@ -443,4 +443,4 @@ static void __init jz4770_cgu_init(struct device_node *np)
}
/* We only probe via devicetree, no need for a platform driver */
CLK_OF_DECLARE(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-cgu", jz4770_cgu_init);

View File

@ -725,4 +725,4 @@ static void __init jz4780_cgu_init(struct device_node *np)
ingenic_cgu_register_syscore_ops(cgu);
}
CLK_OF_DECLARE(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);
CLK_OF_DECLARE_DRIVER(jz4780_cgu, "ingenic,jz4780-cgu", jz4780_cgu_init);

View File

@ -117,6 +117,62 @@ config COMMON_CLK_MT2712_VENCSYS
---help---
This driver supports MediaTek MT2712 vencsys clocks.
config COMMON_CLK_MT6779
bool "Clock driver for MediaTek MT6779"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
select COMMON_CLK_MEDIATEK
default ARCH_MEDIATEK && ARM64
help
This driver supports MediaTek MT6779 basic clocks.
config COMMON_CLK_MT6779_MMSYS
bool "Clock driver for MediaTek MT6779 mmsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 mmsys clocks.
config COMMON_CLK_MT6779_IMGSYS
bool "Clock driver for MediaTek MT6779 imgsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 imgsys clocks.
config COMMON_CLK_MT6779_IPESYS
bool "Clock driver for MediaTek MT6779 ipesys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 ipesys clocks.
config COMMON_CLK_MT6779_CAMSYS
bool "Clock driver for MediaTek MT6779 camsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 camsys clocks.
config COMMON_CLK_MT6779_VDECSYS
bool "Clock driver for MediaTek MT6779 vdecsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 vdecsys clocks.
config COMMON_CLK_MT6779_VENCSYS
bool "Clock driver for MediaTek MT6779 vencsys"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 vencsys clocks.
config COMMON_CLK_MT6779_MFGCFG
bool "Clock driver for MediaTek MT6779 mfgcfg"
depends on COMMON_CLK_MT6779
help
This driver supports MediaTek MT6779 mfgcfg clocks.
config COMMON_CLK_MT6779_AUDSYS
bool "Clock driver for Mediatek MT6779 audsys"
depends on COMMON_CLK_MT6779
help
This driver supports Mediatek MT6779 audsys clocks.
config COMMON_CLK_MT6797
bool "Clock driver for MediaTek MT6797"
depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST

View File

@ -1,6 +1,15 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o clk-cpumux.o reset.o clk-mux.o
obj-$(CONFIG_COMMON_CLK_MT6779) += clk-mt6779.o
obj-$(CONFIG_COMMON_CLK_MT6779_MMSYS) += clk-mt6779-mm.o
obj-$(CONFIG_COMMON_CLK_MT6779_IMGSYS) += clk-mt6779-img.o
obj-$(CONFIG_COMMON_CLK_MT6779_IPESYS) += clk-mt6779-ipe.o
obj-$(CONFIG_COMMON_CLK_MT6779_CAMSYS) += clk-mt6779-cam.o
obj-$(CONFIG_COMMON_CLK_MT6779_VDECSYS) += clk-mt6779-vdec.o
obj-$(CONFIG_COMMON_CLK_MT6779_VENCSYS) += clk-mt6779-venc.o
obj-$(CONFIG_COMMON_CLK_MT6779_MFGCFG) += clk-mt6779-mfg.o
obj-$(CONFIG_COMMON_CLK_MT6779_AUDSYS) += clk-mt6779-aud.o
obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o

View File

@ -150,7 +150,8 @@ struct clk *mtk_clk_register_gate(
int sta_ofs,
u8 bit,
const struct clk_ops *ops,
unsigned long flags)
unsigned long flags,
struct device *dev)
{
struct mtk_clk_gate *cg;
struct clk *clk;
@ -174,7 +175,7 @@ struct clk *mtk_clk_register_gate(
cg->hw.init = &init;
clk = clk_register(NULL, &cg->hw);
clk = clk_register(dev, &cg->hw);
if (IS_ERR(clk))
kfree(cg);

View File

@ -40,7 +40,8 @@ struct clk *mtk_clk_register_gate(
int sta_ofs,
u8 bit,
const struct clk_ops *ops,
unsigned long flags);
unsigned long flags,
struct device *dev);
#define GATE_MTK_FLAGS(_id, _name, _parent, _regs, _shift, \
_ops, _flags) { \

View File

@ -0,0 +1,117 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs audio0_cg_regs = {
.set_ofs = 0x0,
.clr_ofs = 0x0,
.sta_ofs = 0x0,
};
static const struct mtk_gate_regs audio1_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x4,
.sta_ofs = 0x4,
};
#define GATE_AUDIO0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio0_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr)
#define GATE_AUDIO1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &audio1_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr)
static const struct mtk_gate audio_clks[] = {
/* AUDIO0 */
GATE_AUDIO0(CLK_AUD_AFE, "aud_afe", "audio_sel", 2),
GATE_AUDIO0(CLK_AUD_22M, "aud_22m", "aud_eng1_sel", 8),
GATE_AUDIO0(CLK_AUD_24M, "aud_24m", "aud_eng2_sel", 9),
GATE_AUDIO0(CLK_AUD_APLL2_TUNER, "aud_apll2_tuner",
"aud_eng2_sel", 18),
GATE_AUDIO0(CLK_AUD_APLL_TUNER, "aud_apll_tuner",
"aud_eng1_sel", 19),
GATE_AUDIO0(CLK_AUD_TDM, "aud_tdm", "aud_eng1_sel", 20),
GATE_AUDIO0(CLK_AUD_ADC, "aud_adc", "audio_sel", 24),
GATE_AUDIO0(CLK_AUD_DAC, "aud_dac", "audio_sel", 25),
GATE_AUDIO0(CLK_AUD_DAC_PREDIS, "aud_dac_predis",
"audio_sel", 26),
GATE_AUDIO0(CLK_AUD_TML, "aud_tml", "audio_sel", 27),
GATE_AUDIO0(CLK_AUD_NLE, "aud_nle", "audio_sel", 28),
/* AUDIO1 */
GATE_AUDIO1(CLK_AUD_I2S1_BCLK_SW, "aud_i2s1_bclk",
"audio_sel", 4),
GATE_AUDIO1(CLK_AUD_I2S2_BCLK_SW, "aud_i2s2_bclk",
"audio_sel", 5),
GATE_AUDIO1(CLK_AUD_I2S3_BCLK_SW, "aud_i2s3_bclk",
"audio_sel", 6),
GATE_AUDIO1(CLK_AUD_I2S4_BCLK_SW, "aud_i2s4_bclk",
"audio_sel", 7),
GATE_AUDIO1(CLK_AUD_I2S5_BCLK_SW, "aud_i2s5_bclk",
"audio_sel", 8),
GATE_AUDIO1(CLK_AUD_CONN_I2S_ASRC, "aud_conn_i2s",
"audio_sel", 12),
GATE_AUDIO1(CLK_AUD_GENERAL1_ASRC, "aud_general1",
"audio_sel", 13),
GATE_AUDIO1(CLK_AUD_GENERAL2_ASRC, "aud_general2",
"audio_sel", 14),
GATE_AUDIO1(CLK_AUD_DAC_HIRES, "aud_dac_hires",
"audio_h_sel", 15),
GATE_AUDIO1(CLK_AUD_ADC_HIRES, "aud_adc_hires",
"audio_h_sel", 16),
GATE_AUDIO1(CLK_AUD_ADC_HIRES_TML, "aud_adc_hires_tml",
"audio_h_sel", 17),
GATE_AUDIO1(CLK_AUD_PDN_ADDA6_ADC, "aud_pdn_adda6_adc",
"audio_sel", 20),
GATE_AUDIO1(CLK_AUD_ADDA6_ADC_HIRES, "aud_adda6_adc_hires",
"audio_h_sel",
21),
GATE_AUDIO1(CLK_AUD_3RD_DAC, "aud_3rd_dac", "audio_sel",
28),
GATE_AUDIO1(CLK_AUD_3RD_DAC_PREDIS, "aud_3rd_dac_predis",
"audio_sel", 29),
GATE_AUDIO1(CLK_AUD_3RD_DAC_TML, "aud_3rd_dac_tml",
"audio_sel", 30),
GATE_AUDIO1(CLK_AUD_3RD_DAC_HIRES, "aud_3rd_dac_hires",
"audio_h_sel", 31),
};
static const struct of_device_id of_match_clk_mt6779_aud[] = {
{ .compatible = "mediatek,mt6779-audio", },
{}
};
static int clk_mt6779_aud_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_AUD_NR_CLK);
mtk_clk_register_gates(node, audio_clks, ARRAY_SIZE(audio_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_aud_drv = {
.probe = clk_mt6779_aud_probe,
.driver = {
.name = "clk-mt6779-aud",
.of_match_table = of_match_clk_mt6779_aud,
},
};
builtin_platform_driver(clk_mt6779_aud_drv);

View File

@ -0,0 +1,66 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs cam_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_CAM(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &cam_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate cam_clks[] = {
GATE_CAM(CLK_CAM_LARB10, "camsys_larb10", "cam_sel", 0),
GATE_CAM(CLK_CAM_DFP_VAD, "camsys_dfp_vad", "cam_sel", 1),
GATE_CAM(CLK_CAM_LARB11, "camsys_larb11", "cam_sel", 2),
GATE_CAM(CLK_CAM_LARB9, "camsys_larb9", "cam_sel", 3),
GATE_CAM(CLK_CAM_CAM, "camsys_cam", "cam_sel", 6),
GATE_CAM(CLK_CAM_CAMTG, "camsys_camtg", "cam_sel", 7),
GATE_CAM(CLK_CAM_SENINF, "camsys_seninf", "cam_sel", 8),
GATE_CAM(CLK_CAM_CAMSV0, "camsys_camsv0", "cam_sel", 9),
GATE_CAM(CLK_CAM_CAMSV1, "camsys_camsv1", "cam_sel", 10),
GATE_CAM(CLK_CAM_CAMSV2, "camsys_camsv2", "cam_sel", 11),
GATE_CAM(CLK_CAM_CAMSV3, "camsys_camsv3", "cam_sel", 12),
GATE_CAM(CLK_CAM_CCU, "camsys_ccu", "cam_sel", 13),
GATE_CAM(CLK_CAM_FAKE_ENG, "camsys_fake_eng", "cam_sel", 14),
};
static const struct of_device_id of_match_clk_mt6779_cam[] = {
{ .compatible = "mediatek,mt6779-camsys", },
{}
};
static int clk_mt6779_cam_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_CAM_NR_CLK);
mtk_clk_register_gates(node, cam_clks, ARRAY_SIZE(cam_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_cam_drv = {
.probe = clk_mt6779_cam_probe,
.driver = {
.name = "clk-mt6779-cam",
.of_match_table = of_match_clk_mt6779_cam,
},
};
builtin_platform_driver(clk_mt6779_cam_drv);

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs img_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_IMG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &img_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate img_clks[] = {
GATE_IMG(CLK_IMG_LARB5, "imgsys_larb5", "img_sel", 0),
GATE_IMG(CLK_IMG_LARB6, "imgsys_larb6", "img_sel", 1),
GATE_IMG(CLK_IMG_DIP, "imgsys_dip", "img_sel", 2),
GATE_IMG(CLK_IMG_MFB, "imgsys_mfb", "img_sel", 6),
GATE_IMG(CLK_IMG_WPE_A, "imgsys_wpe_a", "img_sel", 7),
};
static const struct of_device_id of_match_clk_mt6779_img[] = {
{ .compatible = "mediatek,mt6779-imgsys", },
{}
};
static int clk_mt6779_img_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IMG_NR_CLK);
mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_img_drv = {
.probe = clk_mt6779_img_probe,
.driver = {
.name = "clk-mt6779-img",
.of_match_table = of_match_clk_mt6779_img,
},
};
builtin_platform_driver(clk_mt6779_img_drv);

View File

@ -0,0 +1,60 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs ipe_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_IPE(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &ipe_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate ipe_clks[] = {
GATE_IPE(CLK_IPE_LARB7, "ipe_larb7", "ipe_sel", 0),
GATE_IPE(CLK_IPE_LARB8, "ipe_larb8", "ipe_sel", 1),
GATE_IPE(CLK_IPE_SMI_SUBCOM, "ipe_smi_subcom", "ipe_sel", 2),
GATE_IPE(CLK_IPE_FD, "ipe_fd", "ipe_sel", 3),
GATE_IPE(CLK_IPE_FE, "ipe_fe", "ipe_sel", 4),
GATE_IPE(CLK_IPE_RSC, "ipe_rsc", "ipe_sel", 5),
GATE_IPE(CLK_IPE_DPE, "ipe_dpe", "ipe_sel", 6),
};
static const struct of_device_id of_match_clk_mt6779_ipe[] = {
{ .compatible = "mediatek,mt6779-ipesys", },
{}
};
static int clk_mt6779_ipe_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_IPE_NR_CLK);
mtk_clk_register_gates(node, ipe_clks, ARRAY_SIZE(ipe_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_ipe_drv = {
.probe = clk_mt6779_ipe_probe,
.driver = {
.name = "clk-mt6779-ipe",
.of_match_table = of_match_clk_mt6779_ipe,
},
};
builtin_platform_driver(clk_mt6779_ipe_drv);

View File

@ -0,0 +1,55 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs mfg_cg_regs = {
.set_ofs = 0x4,
.clr_ofs = 0x8,
.sta_ofs = 0x0,
};
#define GATE_MFG(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mfg_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate mfg_clks[] = {
GATE_MFG(CLK_MFGCFG_BG3D, "mfg_bg3d", "mfg_sel", 0),
};
static int clk_mt6779_mfg_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MFGCFG_NR_CLK);
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static const struct of_device_id of_match_clk_mt6779_mfg[] = {
{ .compatible = "mediatek,mt6779-mfgcfg", },
{}
};
static struct platform_driver clk_mt6779_mfg_drv = {
.probe = clk_mt6779_mfg_probe,
.driver = {
.name = "clk-mt6779-mfg",
.of_match_table = of_match_clk_mt6779_mfg,
},
};
builtin_platform_driver(clk_mt6779_mfg_drv);

View File

@ -0,0 +1,113 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <dt-bindings/clock/mt6779-clk.h>
#include "clk-mtk.h"
#include "clk-gate.h"
static const struct mtk_gate_regs mm0_cg_regs = {
.set_ofs = 0x0104,
.clr_ofs = 0x0108,
.sta_ofs = 0x0100,
};
static const struct mtk_gate_regs mm1_cg_regs = {
.set_ofs = 0x0114,
.clr_ofs = 0x0118,
.sta_ofs = 0x0110,
};
#define GATE_MM0(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mm0_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
#define GATE_MM1(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &mm1_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr)
static const struct mtk_gate mm_clks[] = {
/* 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_SMI_LARB1, "mm_smi_larb1", "mm_sel", 2),
GATE_MM0(CLK_MM_GALS_COMM0, "mm_gals_comm0", "mm_sel", 3),
GATE_MM0(CLK_MM_GALS_COMM1, "mm_gals_comm1", "mm_sel", 4),
GATE_MM0(CLK_MM_GALS_CCU2MM, "mm_gals_ccu2mm", "mm_sel", 5),
GATE_MM0(CLK_MM_GALS_IPU12MM, "mm_gals_ipu12mm", "mm_sel", 6),
GATE_MM0(CLK_MM_GALS_IMG2MM, "mm_gals_img2mm", "mm_sel", 7),
GATE_MM0(CLK_MM_GALS_CAM2MM, "mm_gals_cam2mm", "mm_sel", 8),
GATE_MM0(CLK_MM_GALS_IPU2MM, "mm_gals_ipu2mm", "mm_sel", 9),
GATE_MM0(CLK_MM_MDP_DL_TXCK, "mm_mdp_dl_txck", "mm_sel", 10),
GATE_MM0(CLK_MM_IPU_DL_TXCK, "mm_ipu_dl_txck", "mm_sel", 11),
GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 12),
GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 13),
GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 14),
GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 15),
GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 16),
GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 17),
GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 18),
GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 19),
GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 20),
GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 21),
GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 22),
GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 23),
GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 24),
GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 25),
GATE_MM0(CLK_MM_DISP_COLOR0, "mm_disp_color0", "mm_sel", 26),
GATE_MM0(CLK_MM_DISP_CCORR0, "mm_disp_ccorr0", "mm_sel", 27),
GATE_MM0(CLK_MM_DISP_AAL0, "mm_disp_aal0", "mm_sel", 28),
GATE_MM0(CLK_MM_DISP_GAMMA0, "mm_disp_gamma0", "mm_sel", 29),
GATE_MM0(CLK_MM_DISP_DITHER0, "mm_disp_dither0", "mm_sel", 30),
GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
/* MM1 */
GATE_MM1(CLK_MM_DSI0_MM_CK, "mm_dsi0_mmck", "mm_sel", 0),
GATE_MM1(CLK_MM_DSI0_IF_CK, "mm_dsi0_ifck", "mm_sel", 1),
GATE_MM1(CLK_MM_DPI_MM_CK, "mm_dpi_mmck", "mm_sel", 2),
GATE_MM1(CLK_MM_DPI_IF_CK, "mm_dpi_ifck", "dpi0_sel", 3),
GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 4),
GATE_MM1(CLK_MM_MDP_DL_RX_CK, "mm_mdp_dl_rxck", "mm_sel", 5),
GATE_MM1(CLK_MM_IPU_DL_RX_CK, "mm_ipu_dl_rxck", "mm_sel", 6),
GATE_MM1(CLK_MM_26M, "mm_26m", "f_f26m_ck", 7),
GATE_MM1(CLK_MM_MM_R2Y, "mm_mmsys_r2y", "mm_sel", 8),
GATE_MM1(CLK_MM_DISP_RSZ, "mm_disp_rsz", "mm_sel", 9),
GATE_MM1(CLK_MM_MDP_AAL, "mm_mdp_aal", "mm_sel", 10),
GATE_MM1(CLK_MM_MDP_HDR, "mm_mdp_hdr", "mm_sel", 11),
GATE_MM1(CLK_MM_DBI_MM_CK, "mm_dbi_mmck", "mm_sel", 12),
GATE_MM1(CLK_MM_DBI_IF_CK, "mm_dbi_ifck", "dpi0_sel", 13),
GATE_MM1(CLK_MM_DISP_POSTMASK0, "mm_disp_pm0", "mm_sel", 14),
GATE_MM1(CLK_MM_DISP_HRT_BW, "mm_disp_hrt_bw", "mm_sel", 15),
GATE_MM1(CLK_MM_DISP_OVL_FBDC, "mm_disp_ovl_fbdc", "mm_sel", 16),
};
static const struct of_device_id of_match_clk_mt6779_mm[] = {
{ .compatible = "mediatek,mt6779-mmsys", },
{}
};
static int clk_mt6779_mm_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_MM_NR_CLK);
mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_mm_drv = {
.probe = clk_mt6779_mm_probe,
.driver = {
.name = "clk-mt6779-mm",
.of_match_table = of_match_clk_mt6779_mm,
},
};
builtin_platform_driver(clk_mt6779_mm_drv);

View File

@ -0,0 +1,67 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs vdec0_cg_regs = {
.set_ofs = 0x0000,
.clr_ofs = 0x0004,
.sta_ofs = 0x0000,
};
static const struct mtk_gate_regs vdec1_cg_regs = {
.set_ofs = 0x0008,
.clr_ofs = 0x000c,
.sta_ofs = 0x0008,
};
#define GATE_VDEC0_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec0_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
#define GATE_VDEC1_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &vdec1_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate vdec_clks[] = {
/* VDEC0 */
GATE_VDEC0_I(CLK_VDEC_VDEC, "vdec_cken", "vdec_sel", 0),
/* VDEC1 */
GATE_VDEC1_I(CLK_VDEC_LARB1, "vdec_larb1_cken", "vdec_sel", 0),
};
static const struct of_device_id of_match_clk_mt6779_vdec[] = {
{ .compatible = "mediatek,mt6779-vdecsys", },
{}
};
static int clk_mt6779_vdec_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VDEC_GCON_NR_CLK);
mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_vdec_drv = {
.probe = clk_mt6779_vdec_probe,
.driver = {
.name = "clk-mt6779-vdec",
.of_match_table = of_match_clk_mt6779_vdec,
},
};
builtin_platform_driver(clk_mt6779_vdec_drv);

View File

@ -0,0 +1,58 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2019 MediaTek Inc.
* Author: Wendell Lin <wendell.lin@mediatek.com>
*/
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
#include <dt-bindings/clock/mt6779-clk.h>
static const struct mtk_gate_regs venc_cg_regs = {
.set_ofs = 0x0004,
.clr_ofs = 0x0008,
.sta_ofs = 0x0000,
};
#define GATE_VENC_I(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &venc_cg_regs, _shift, \
&mtk_clk_gate_ops_setclr_inv)
static const struct mtk_gate venc_clks[] = {
GATE_VENC_I(CLK_VENC_GCON_LARB, "venc_larb", "venc_sel", 0),
GATE_VENC_I(CLK_VENC_GCON_VENC, "venc_venc", "venc_sel", 4),
GATE_VENC_I(CLK_VENC_GCON_JPGENC, "venc_jpgenc", "venc_sel", 8),
GATE_VENC_I(CLK_VENC_GCON_GALS, "venc_gals", "venc_sel", 28),
};
static const struct of_device_id of_match_clk_mt6779_venc[] = {
{ .compatible = "mediatek,mt6779-vencsys", },
{}
};
static int clk_mt6779_venc_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_VENC_GCON_NR_CLK);
mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
static struct platform_driver clk_mt6779_venc_drv = {
.probe = clk_mt6779_venc_probe,
.driver = {
.name = "clk-mt6779-venc",
.of_match_table = of_match_clk_mt6779_venc,
},
};
builtin_platform_driver(clk_mt6779_venc_drv);

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,7 @@
#include <linux/clk-provider.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include "clk-mtk.h"
#include "clk-gate.h"
@ -30,10 +31,12 @@ static int clk_mt8183_mfg_probe(struct platform_device *pdev)
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
pm_runtime_enable(&pdev->dev);
clk_data = mtk_alloc_clk_data(CLK_MFG_NR_CLK);
mtk_clk_register_gates(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data);
mtk_clk_register_gates_with_dev(node, mfg_clks, ARRAY_SIZE(mfg_clks),
clk_data, &pdev->dev);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}

View File

@ -17,6 +17,9 @@
#include <dt-bindings/clock/mt8183-clk.h>
/* Infra global controller reset set register */
#define INFRA_RST0_SET_OFFSET 0x120
static DEFINE_SPINLOCK(mt8183_clk_lock);
static const struct mtk_fixed_clk top_fixed_clks[] = {
@ -1001,6 +1004,20 @@ static const struct mtk_gate infra_clks[] = {
"msdc50_0_sel", 24),
};
static const struct mtk_gate_regs peri_cg_regs = {
.set_ofs = 0x20c,
.clr_ofs = 0x20c,
.sta_ofs = 0x20c,
};
#define GATE_PERI(_id, _name, _parent, _shift) \
GATE_MTK(_id, _name, _parent, &peri_cg_regs, _shift, \
&mtk_clk_gate_ops_no_setclr_inv)
static const struct mtk_gate peri_clks[] = {
GATE_PERI(CLK_PERI_AXI, "peri_axi", "axi_sel", 31),
};
static const struct mtk_gate_regs apmixed_cg_regs = {
.set_ofs = 0x20,
.clr_ofs = 0x20,
@ -1207,12 +1224,36 @@ static int clk_mt8183_infra_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
int r;
clk_data = mtk_alloc_clk_data(CLK_INFRA_NR_CLK);
mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
clk_data);
r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
if (r) {
dev_err(&pdev->dev,
"%s(): could not register clock provider: %d\n",
__func__, r);
return r;
}
mtk_register_reset_controller_set_clr(node, 4, INFRA_RST0_SET_OFFSET);
return r;
}
static int clk_mt8183_peri_probe(struct platform_device *pdev)
{
struct clk_onecell_data *clk_data;
struct device_node *node = pdev->dev.of_node;
clk_data = mtk_alloc_clk_data(CLK_PERI_NR_CLK);
mtk_clk_register_gates(node, peri_clks, ARRAY_SIZE(peri_clks),
clk_data);
return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
}
@ -1245,6 +1286,9 @@ static const struct of_device_id of_match_clk_mt8183[] = {
}, {
.compatible = "mediatek,mt8183-infracfg",
.data = clk_mt8183_infra_probe,
}, {
.compatible = "mediatek,mt8183-pericfg",
.data = clk_mt8183_peri_probe,
}, {
.compatible = "mediatek,mt8183-mcucfg",
.data = clk_mt8183_mcu_probe,

View File

@ -12,6 +12,7 @@
#include <linux/delay.h>
#include <linux/clkdev.h>
#include <linux/mfd/syscon.h>
#include <linux/device.h>
#include "clk-mtk.h"
#include "clk-gate.h"
@ -93,9 +94,10 @@ void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
}
}
int mtk_clk_register_gates(struct device_node *node,
int mtk_clk_register_gates_with_dev(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,
struct device *dev)
{
int i;
struct clk *clk;
@ -122,7 +124,7 @@ int mtk_clk_register_gates(struct device_node *node,
gate->regs->set_ofs,
gate->regs->clr_ofs,
gate->regs->sta_ofs,
gate->shift, gate->ops, gate->flags);
gate->shift, gate->ops, gate->flags, dev);
if (IS_ERR(clk)) {
pr_err("Failed to register clk %s: %ld\n",
@ -136,6 +138,14 @@ int mtk_clk_register_gates(struct device_node *node,
return 0;
}
int mtk_clk_register_gates(struct device_node *node,
const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data)
{
return mtk_clk_register_gates_with_dev(node,
clks, num, clk_data, NULL);
}
struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
void __iomem *base, spinlock_t *lock)
{

View File

@ -169,6 +169,11 @@ int mtk_clk_register_gates(struct device_node *node,
const struct mtk_gate *clks, int num,
struct clk_onecell_data *clk_data);
int mtk_clk_register_gates_with_dev(struct device_node *node,
const struct mtk_gate *clks,
int num, struct clk_onecell_data *clk_data,
struct device *dev);
struct mtk_clk_divider {
int id;
const char *name;
@ -240,4 +245,7 @@ struct clk *mtk_clk_register_ref2usb_tx(const char *name,
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs);
void mtk_register_reset_controller_set_clr(struct device_node *np,
unsigned int num_regs, int regofs);
#endif /* __DRV_CLK_MTK_H */

View File

@ -19,6 +19,24 @@ struct mtk_reset {
struct reset_controller_dev rcdev;
};
static int mtk_reset_assert_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
unsigned int reg = data->regofs + ((id / 32) << 4);
return regmap_write(data->regmap, reg, 1);
}
static int mtk_reset_deassert_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct mtk_reset *data = container_of(rcdev, struct mtk_reset, rcdev);
unsigned int reg = data->regofs + ((id / 32) << 4) + 0x4;
return regmap_write(data->regmap, reg, 1);
}
static int mtk_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
@ -49,14 +67,32 @@ static int mtk_reset(struct reset_controller_dev *rcdev,
return mtk_reset_deassert(rcdev, id);
}
static int mtk_reset_set_clr(struct reset_controller_dev *rcdev,
unsigned long id)
{
int ret;
ret = mtk_reset_assert_set_clr(rcdev, id);
if (ret)
return ret;
return mtk_reset_deassert_set_clr(rcdev, id);
}
static const struct reset_control_ops mtk_reset_ops = {
.assert = mtk_reset_assert,
.deassert = mtk_reset_deassert,
.reset = mtk_reset,
};
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs)
static const struct reset_control_ops mtk_reset_ops_set_clr = {
.assert = mtk_reset_assert_set_clr,
.deassert = mtk_reset_deassert_set_clr,
.reset = mtk_reset_set_clr,
};
static void mtk_register_reset_controller_common(struct device_node *np,
unsigned int num_regs, int regofs,
const struct reset_control_ops *reset_ops)
{
struct mtk_reset *data;
int ret;
@ -77,7 +113,7 @@ void mtk_register_reset_controller(struct device_node *np,
data->regofs = regofs;
data->rcdev.owner = THIS_MODULE;
data->rcdev.nr_resets = num_regs * 32;
data->rcdev.ops = &mtk_reset_ops;
data->rcdev.ops = reset_ops;
data->rcdev.of_node = np;
ret = reset_controller_register(&data->rcdev);
@ -87,3 +123,17 @@ void mtk_register_reset_controller(struct device_node *np,
return;
}
}
void mtk_register_reset_controller(struct device_node *np,
unsigned int num_regs, int regofs)
{
mtk_register_reset_controller_common(np, num_regs, regofs,
&mtk_reset_ops);
}
void mtk_register_reset_controller_set_clr(struct device_node *np,
unsigned int num_regs, int regofs)
{
mtk_register_reset_controller_common(np, num_regs, regofs,
&mtk_reset_ops_set_clr);
}

View File

@ -12,6 +12,7 @@
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/reset.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include "axg-audio.h"
@ -918,6 +919,84 @@ static int devm_clk_get_enable(struct device *dev, char *id)
return 0;
}
struct axg_audio_reset_data {
struct reset_controller_dev rstc;
struct regmap *map;
unsigned int offset;
};
static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
unsigned long id,
unsigned int *reg,
unsigned int *bit)
{
unsigned int stride = regmap_get_reg_stride(rst->map);
*reg = (id / (stride * BITS_PER_BYTE)) * stride;
*reg += rst->offset;
*bit = id % (stride * BITS_PER_BYTE);
}
static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int offset, bit;
axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
regmap_update_bits(rst->map, offset, BIT(bit),
assert ? BIT(bit) : 0);
return 0;
}
static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct axg_audio_reset_data *rst =
container_of(rcdev, struct axg_audio_reset_data, rstc);
unsigned int val, offset, bit;
axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
regmap_read(rst->map, offset, &val);
return !!(val & BIT(bit));
}
static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, true);
}
static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
return axg_audio_reset_update(rcdev, id, false);
}
static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
unsigned long id)
{
int ret;
ret = axg_audio_reset_assert(rcdev, id);
if (ret)
return ret;
return axg_audio_reset_deassert(rcdev, id);
}
static const struct reset_control_ops axg_audio_rstc_ops = {
.assert = axg_audio_reset_assert,
.deassert = axg_audio_reset_deassert,
.reset = axg_audio_reset_toggle,
.status = axg_audio_reset_status,
};
static const struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@ -927,12 +1006,15 @@ static const struct regmap_config axg_audio_regmap_cfg = {
struct audioclk_data {
struct clk_hw_onecell_data *hw_onecell_data;
unsigned int reset_offset;
unsigned int reset_num;
};
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
struct axg_audio_reset_data *rst;
struct regmap *map;
struct resource *res;
void __iomem *regs;
@ -971,21 +1053,43 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
/* Take care to skip the registered input clocks */
for (i = AUD_CLKID_DDR_ARB; i < data->hw_onecell_data->num; i++) {
const char *name;
hw = data->hw_onecell_data->hws[i];
/* array might be sparse */
if (!hw)
continue;
name = hw->init->name;
ret = devm_clk_hw_register(dev, hw);
if (ret) {
dev_err(dev, "failed to register clock %s\n",
hw->init->name);
dev_err(dev, "failed to register clock %s\n", name);
return ret;
}
}
return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
data->hw_onecell_data);
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
data->hw_onecell_data);
if (ret)
return ret;
/* Stop here if there is no reset */
if (!data->reset_num)
return 0;
rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
if (!rst)
return -ENOMEM;
rst->map = map;
rst->offset = data->reset_offset;
rst->rstc.nr_resets = data->reset_num;
rst->rstc.ops = &axg_audio_rstc_ops;
rst->rstc.of_node = dev->of_node;
rst->rstc.owner = THIS_MODULE;
return devm_reset_controller_register(dev, &rst->rstc);
}
static const struct audioclk_data axg_audioclk_data = {
@ -994,6 +1098,8 @@ static const struct audioclk_data axg_audioclk_data = {
static const struct audioclk_data g12a_audioclk_data = {
.hw_onecell_data = &g12a_audio_hw_onecell_data,
.reset_offset = AUDIO_SW_RESET,
.reset_num = 26,
};
static const struct of_device_id clkc_match_table[] = {

View File

@ -22,6 +22,7 @@
#define AUDIO_MCLK_F_CTRL 0x018
#define AUDIO_MST_PAD_CTRL0 0x01c
#define AUDIO_MST_PAD_CTRL1 0x020
#define AUDIO_SW_RESET 0x024
#define AUDIO_MST_A_SCLK_CTRL0 0x040
#define AUDIO_MST_A_SCLK_CTRL1 0x044
#define AUDIO_MST_B_SCLK_CTRL0 0x048

View File

@ -676,6 +676,226 @@ static struct clk_regmap g12b_cpub_clk = {
},
};
static struct clk_regmap sm1_gp1_pll;
/* Datasheet names this field as "premux0" */
static struct clk_regmap sm1_dsu_clk_premux0 = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x3,
.shift = 0,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn0_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &g12a_fclk_div2.hw },
{ .hw = &g12a_fclk_div3.hw },
{ .hw = &sm1_gp1_pll.hw },
},
.num_parents = 4,
},
};
/* Datasheet names this field as "premux1" */
static struct clk_regmap sm1_dsu_clk_premux1 = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x3,
.shift = 16,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn1_sel",
.ops = &clk_regmap_mux_ro_ops,
.parent_data = (const struct clk_parent_data []) {
{ .fw_name = "xtal", },
{ .hw = &g12a_fclk_div2.hw },
{ .hw = &g12a_fclk_div3.hw },
{ .hw = &sm1_gp1_pll.hw },
},
.num_parents = 4,
},
};
/* Datasheet names this field as "Mux0_divn_tcnt" */
static struct clk_regmap sm1_dsu_clk_mux0_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.shift = 4,
.width = 6,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn0_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_premux0.hw
},
.num_parents = 1,
},
};
/* Datasheet names this field as "postmux0" */
static struct clk_regmap sm1_dsu_clk_postmux0 = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x1,
.shift = 2,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn0",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_premux0.hw,
&sm1_dsu_clk_mux0_div.hw,
},
.num_parents = 2,
},
};
/* Datasheet names this field as "Mux1_divn_tcnt" */
static struct clk_regmap sm1_dsu_clk_mux1_div = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.shift = 20,
.width = 6,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn1_div",
.ops = &clk_regmap_divider_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_premux1.hw
},
.num_parents = 1,
},
};
/* Datasheet names this field as "postmux1" */
static struct clk_regmap sm1_dsu_clk_postmux1 = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x1,
.shift = 18,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn1",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_premux1.hw,
&sm1_dsu_clk_mux1_div.hw,
},
.num_parents = 2,
},
};
/* Datasheet names this field as "Final_dyn_mux_sel" */
static struct clk_regmap sm1_dsu_clk_dyn = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x1,
.shift = 10,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_dyn",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_postmux0.hw,
&sm1_dsu_clk_postmux1.hw,
},
.num_parents = 2,
},
};
/* Datasheet names this field as "Final_mux_sel" */
static struct clk_regmap sm1_dsu_final_clk = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL5,
.mask = 0x1,
.shift = 11,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk_final",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_dsu_clk_dyn.hw,
&g12a_sys_pll.hw,
},
.num_parents = 2,
},
};
/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 0 */
static struct clk_regmap sm1_cpu1_clk = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL6,
.mask = 0x1,
.shift = 24,
},
.hw.init = &(struct clk_init_data){
.name = "cpu1_clk",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&g12a_cpu_clk.hw,
/* This CPU also have a dedicated clock tree */
},
.num_parents = 1,
},
};
/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 1 */
static struct clk_regmap sm1_cpu2_clk = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL6,
.mask = 0x1,
.shift = 25,
},
.hw.init = &(struct clk_init_data){
.name = "cpu2_clk",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&g12a_cpu_clk.hw,
/* This CPU also have a dedicated clock tree */
},
.num_parents = 1,
},
};
/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 2 */
static struct clk_regmap sm1_cpu3_clk = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL6,
.mask = 0x1,
.shift = 26,
},
.hw.init = &(struct clk_init_data){
.name = "cpu3_clk",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&g12a_cpu_clk.hw,
/* This CPU also have a dedicated clock tree */
},
.num_parents = 1,
},
};
/* Datasheet names this field as "Cpu_clk_sync_mux_sel" bit 4 */
static struct clk_regmap sm1_dsu_clk = {
.data = &(struct clk_regmap_mux_data){
.offset = HHI_SYS_CPU_CLK_CNTL6,
.mask = 0x1,
.shift = 27,
},
.hw.init = &(struct clk_init_data){
.name = "dsu_clk",
.ops = &clk_regmap_mux_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&g12a_cpu_clk.hw,
&sm1_dsu_final_clk.hw,
},
.num_parents = 2,
},
};
static int g12a_cpu_clk_mux_notifier_cb(struct notifier_block *nb,
unsigned long event, void *data)
{
@ -1443,6 +1663,69 @@ static struct clk_regmap g12a_gp0_pll = {
},
};
static struct clk_regmap sm1_gp1_pll_dco = {
.data = &(struct meson_clk_pll_data){
.en = {
.reg_off = HHI_GP1_PLL_CNTL0,
.shift = 28,
.width = 1,
},
.m = {
.reg_off = HHI_GP1_PLL_CNTL0,
.shift = 0,
.width = 8,
},
.n = {
.reg_off = HHI_GP1_PLL_CNTL0,
.shift = 10,
.width = 5,
},
.frac = {
.reg_off = HHI_GP1_PLL_CNTL1,
.shift = 0,
.width = 17,
},
.l = {
.reg_off = HHI_GP1_PLL_CNTL0,
.shift = 31,
.width = 1,
},
.rst = {
.reg_off = HHI_GP1_PLL_CNTL0,
.shift = 29,
.width = 1,
},
},
.hw.init = &(struct clk_init_data){
.name = "gp1_pll_dco",
.ops = &meson_clk_pll_ro_ops,
.parent_data = &(const struct clk_parent_data) {
.fw_name = "xtal",
},
.num_parents = 1,
/* This clock feeds the DSU, avoid disabling it */
.flags = CLK_IS_CRITICAL,
},
};
static struct clk_regmap sm1_gp1_pll = {
.data = &(struct clk_regmap_div_data){
.offset = HHI_GP1_PLL_CNTL0,
.shift = 16,
.width = 3,
.flags = (CLK_DIVIDER_POWER_OF_TWO |
CLK_DIVIDER_ROUND_CLOSEST),
},
.hw.init = &(struct clk_init_data){
.name = "gp1_pll",
.ops = &clk_regmap_divider_ro_ops,
.parent_hws = (const struct clk_hw *[]) {
&sm1_gp1_pll_dco.hw
},
.num_parents = 1,
},
};
/*
* Internal hifi pll emulation configuration parameters
*/
@ -4121,6 +4404,240 @@ static struct clk_hw_onecell_data g12b_hw_onecell_data = {
.num = NR_CLKS,
};
static struct clk_hw_onecell_data sm1_hw_onecell_data = {
.hws = {
[CLKID_SYS_PLL] = &g12a_sys_pll.hw,
[CLKID_FIXED_PLL] = &g12a_fixed_pll.hw,
[CLKID_FCLK_DIV2] = &g12a_fclk_div2.hw,
[CLKID_FCLK_DIV3] = &g12a_fclk_div3.hw,
[CLKID_FCLK_DIV4] = &g12a_fclk_div4.hw,
[CLKID_FCLK_DIV5] = &g12a_fclk_div5.hw,
[CLKID_FCLK_DIV7] = &g12a_fclk_div7.hw,
[CLKID_FCLK_DIV2P5] = &g12a_fclk_div2p5.hw,
[CLKID_GP0_PLL] = &g12a_gp0_pll.hw,
[CLKID_MPEG_SEL] = &g12a_mpeg_clk_sel.hw,
[CLKID_MPEG_DIV] = &g12a_mpeg_clk_div.hw,
[CLKID_CLK81] = &g12a_clk81.hw,
[CLKID_MPLL0] = &g12a_mpll0.hw,
[CLKID_MPLL1] = &g12a_mpll1.hw,
[CLKID_MPLL2] = &g12a_mpll2.hw,
[CLKID_MPLL3] = &g12a_mpll3.hw,
[CLKID_DDR] = &g12a_ddr.hw,
[CLKID_DOS] = &g12a_dos.hw,
[CLKID_AUDIO_LOCKER] = &g12a_audio_locker.hw,
[CLKID_MIPI_DSI_HOST] = &g12a_mipi_dsi_host.hw,
[CLKID_ETH_PHY] = &g12a_eth_phy.hw,
[CLKID_ISA] = &g12a_isa.hw,
[CLKID_PL301] = &g12a_pl301.hw,
[CLKID_PERIPHS] = &g12a_periphs.hw,
[CLKID_SPICC0] = &g12a_spicc_0.hw,
[CLKID_I2C] = &g12a_i2c.hw,
[CLKID_SANA] = &g12a_sana.hw,
[CLKID_SD] = &g12a_sd.hw,
[CLKID_RNG0] = &g12a_rng0.hw,
[CLKID_UART0] = &g12a_uart0.hw,
[CLKID_SPICC1] = &g12a_spicc_1.hw,
[CLKID_HIU_IFACE] = &g12a_hiu_reg.hw,
[CLKID_MIPI_DSI_PHY] = &g12a_mipi_dsi_phy.hw,
[CLKID_ASSIST_MISC] = &g12a_assist_misc.hw,
[CLKID_SD_EMMC_A] = &g12a_emmc_a.hw,
[CLKID_SD_EMMC_B] = &g12a_emmc_b.hw,
[CLKID_SD_EMMC_C] = &g12a_emmc_c.hw,
[CLKID_AUDIO_CODEC] = &g12a_audio_codec.hw,
[CLKID_AUDIO] = &g12a_audio.hw,
[CLKID_ETH] = &g12a_eth_core.hw,
[CLKID_DEMUX] = &g12a_demux.hw,
[CLKID_AUDIO_IFIFO] = &g12a_audio_ififo.hw,
[CLKID_ADC] = &g12a_adc.hw,
[CLKID_UART1] = &g12a_uart1.hw,
[CLKID_G2D] = &g12a_g2d.hw,
[CLKID_RESET] = &g12a_reset.hw,
[CLKID_PCIE_COMB] = &g12a_pcie_comb.hw,
[CLKID_PARSER] = &g12a_parser.hw,
[CLKID_USB] = &g12a_usb_general.hw,
[CLKID_PCIE_PHY] = &g12a_pcie_phy.hw,
[CLKID_AHB_ARB0] = &g12a_ahb_arb0.hw,
[CLKID_AHB_DATA_BUS] = &g12a_ahb_data_bus.hw,
[CLKID_AHB_CTRL_BUS] = &g12a_ahb_ctrl_bus.hw,
[CLKID_HTX_HDCP22] = &g12a_htx_hdcp22.hw,
[CLKID_HTX_PCLK] = &g12a_htx_pclk.hw,
[CLKID_BT656] = &g12a_bt656.hw,
[CLKID_USB1_DDR_BRIDGE] = &g12a_usb1_to_ddr.hw,
[CLKID_MMC_PCLK] = &g12a_mmc_pclk.hw,
[CLKID_UART2] = &g12a_uart2.hw,
[CLKID_VPU_INTR] = &g12a_vpu_intr.hw,
[CLKID_GIC] = &g12a_gic.hw,
[CLKID_SD_EMMC_A_CLK0_SEL] = &g12a_sd_emmc_a_clk0_sel.hw,
[CLKID_SD_EMMC_A_CLK0_DIV] = &g12a_sd_emmc_a_clk0_div.hw,
[CLKID_SD_EMMC_A_CLK0] = &g12a_sd_emmc_a_clk0.hw,
[CLKID_SD_EMMC_B_CLK0_SEL] = &g12a_sd_emmc_b_clk0_sel.hw,
[CLKID_SD_EMMC_B_CLK0_DIV] = &g12a_sd_emmc_b_clk0_div.hw,
[CLKID_SD_EMMC_B_CLK0] = &g12a_sd_emmc_b_clk0.hw,
[CLKID_SD_EMMC_C_CLK0_SEL] = &g12a_sd_emmc_c_clk0_sel.hw,
[CLKID_SD_EMMC_C_CLK0_DIV] = &g12a_sd_emmc_c_clk0_div.hw,
[CLKID_SD_EMMC_C_CLK0] = &g12a_sd_emmc_c_clk0.hw,
[CLKID_MPLL0_DIV] = &g12a_mpll0_div.hw,
[CLKID_MPLL1_DIV] = &g12a_mpll1_div.hw,
[CLKID_MPLL2_DIV] = &g12a_mpll2_div.hw,
[CLKID_MPLL3_DIV] = &g12a_mpll3_div.hw,
[CLKID_FCLK_DIV2_DIV] = &g12a_fclk_div2_div.hw,
[CLKID_FCLK_DIV3_DIV] = &g12a_fclk_div3_div.hw,
[CLKID_FCLK_DIV4_DIV] = &g12a_fclk_div4_div.hw,
[CLKID_FCLK_DIV5_DIV] = &g12a_fclk_div5_div.hw,
[CLKID_FCLK_DIV7_DIV] = &g12a_fclk_div7_div.hw,
[CLKID_FCLK_DIV2P5_DIV] = &g12a_fclk_div2p5_div.hw,
[CLKID_HIFI_PLL] = &g12a_hifi_pll.hw,
[CLKID_VCLK2_VENCI0] = &g12a_vclk2_venci0.hw,
[CLKID_VCLK2_VENCI1] = &g12a_vclk2_venci1.hw,
[CLKID_VCLK2_VENCP0] = &g12a_vclk2_vencp0.hw,
[CLKID_VCLK2_VENCP1] = &g12a_vclk2_vencp1.hw,
[CLKID_VCLK2_VENCT0] = &g12a_vclk2_venct0.hw,
[CLKID_VCLK2_VENCT1] = &g12a_vclk2_venct1.hw,
[CLKID_VCLK2_OTHER] = &g12a_vclk2_other.hw,
[CLKID_VCLK2_ENCI] = &g12a_vclk2_enci.hw,
[CLKID_VCLK2_ENCP] = &g12a_vclk2_encp.hw,
[CLKID_DAC_CLK] = &g12a_dac_clk.hw,
[CLKID_AOCLK] = &g12a_aoclk_gate.hw,
[CLKID_IEC958] = &g12a_iec958_gate.hw,
[CLKID_ENC480P] = &g12a_enc480p.hw,
[CLKID_RNG1] = &g12a_rng1.hw,
[CLKID_VCLK2_ENCT] = &g12a_vclk2_enct.hw,
[CLKID_VCLK2_ENCL] = &g12a_vclk2_encl.hw,
[CLKID_VCLK2_VENCLMMC] = &g12a_vclk2_venclmmc.hw,
[CLKID_VCLK2_VENCL] = &g12a_vclk2_vencl.hw,
[CLKID_VCLK2_OTHER1] = &g12a_vclk2_other1.hw,
[CLKID_FIXED_PLL_DCO] = &g12a_fixed_pll_dco.hw,
[CLKID_SYS_PLL_DCO] = &g12a_sys_pll_dco.hw,
[CLKID_GP0_PLL_DCO] = &g12a_gp0_pll_dco.hw,
[CLKID_HIFI_PLL_DCO] = &g12a_hifi_pll_dco.hw,
[CLKID_DMA] = &g12a_dma.hw,
[CLKID_EFUSE] = &g12a_efuse.hw,
[CLKID_ROM_BOOT] = &g12a_rom_boot.hw,
[CLKID_RESET_SEC] = &g12a_reset_sec.hw,
[CLKID_SEC_AHB_APB3] = &g12a_sec_ahb_apb3.hw,
[CLKID_MPLL_PREDIV] = &g12a_mpll_prediv.hw,
[CLKID_VPU_0_SEL] = &g12a_vpu_0_sel.hw,
[CLKID_VPU_0_DIV] = &g12a_vpu_0_div.hw,
[CLKID_VPU_0] = &g12a_vpu_0.hw,
[CLKID_VPU_1_SEL] = &g12a_vpu_1_sel.hw,
[CLKID_VPU_1_DIV] = &g12a_vpu_1_div.hw,
[CLKID_VPU_1] = &g12a_vpu_1.hw,
[CLKID_VPU] = &g12a_vpu.hw,
[CLKID_VAPB_0_SEL] = &g12a_vapb_0_sel.hw,
[CLKID_VAPB_0_DIV] = &g12a_vapb_0_div.hw,
[CLKID_VAPB_0] = &g12a_vapb_0.hw,
[CLKID_VAPB_1_SEL] = &g12a_vapb_1_sel.hw,
[CLKID_VAPB_1_DIV] = &g12a_vapb_1_div.hw,
[CLKID_VAPB_1] = &g12a_vapb_1.hw,
[CLKID_VAPB_SEL] = &g12a_vapb_sel.hw,
[CLKID_VAPB] = &g12a_vapb.hw,
[CLKID_HDMI_PLL_DCO] = &g12a_hdmi_pll_dco.hw,
[CLKID_HDMI_PLL_OD] = &g12a_hdmi_pll_od.hw,
[CLKID_HDMI_PLL_OD2] = &g12a_hdmi_pll_od2.hw,
[CLKID_HDMI_PLL] = &g12a_hdmi_pll.hw,
[CLKID_VID_PLL] = &g12a_vid_pll_div.hw,
[CLKID_VID_PLL_SEL] = &g12a_vid_pll_sel.hw,
[CLKID_VID_PLL_DIV] = &g12a_vid_pll.hw,
[CLKID_VCLK_SEL] = &g12a_vclk_sel.hw,
[CLKID_VCLK2_SEL] = &g12a_vclk2_sel.hw,
[CLKID_VCLK_INPUT] = &g12a_vclk_input.hw,
[CLKID_VCLK2_INPUT] = &g12a_vclk2_input.hw,
[CLKID_VCLK_DIV] = &g12a_vclk_div.hw,
[CLKID_VCLK2_DIV] = &g12a_vclk2_div.hw,
[CLKID_VCLK] = &g12a_vclk.hw,
[CLKID_VCLK2] = &g12a_vclk2.hw,
[CLKID_VCLK_DIV1] = &g12a_vclk_div1.hw,
[CLKID_VCLK_DIV2_EN] = &g12a_vclk_div2_en.hw,
[CLKID_VCLK_DIV4_EN] = &g12a_vclk_div4_en.hw,
[CLKID_VCLK_DIV6_EN] = &g12a_vclk_div6_en.hw,
[CLKID_VCLK_DIV12_EN] = &g12a_vclk_div12_en.hw,
[CLKID_VCLK2_DIV1] = &g12a_vclk2_div1.hw,
[CLKID_VCLK2_DIV2_EN] = &g12a_vclk2_div2_en.hw,
[CLKID_VCLK2_DIV4_EN] = &g12a_vclk2_div4_en.hw,
[CLKID_VCLK2_DIV6_EN] = &g12a_vclk2_div6_en.hw,
[CLKID_VCLK2_DIV12_EN] = &g12a_vclk2_div12_en.hw,
[CLKID_VCLK_DIV2] = &g12a_vclk_div2.hw,
[CLKID_VCLK_DIV4] = &g12a_vclk_div4.hw,
[CLKID_VCLK_DIV6] = &g12a_vclk_div6.hw,
[CLKID_VCLK_DIV12] = &g12a_vclk_div12.hw,
[CLKID_VCLK2_DIV2] = &g12a_vclk2_div2.hw,
[CLKID_VCLK2_DIV4] = &g12a_vclk2_div4.hw,
[CLKID_VCLK2_DIV6] = &g12a_vclk2_div6.hw,
[CLKID_VCLK2_DIV12] = &g12a_vclk2_div12.hw,
[CLKID_CTS_ENCI_SEL] = &g12a_cts_enci_sel.hw,
[CLKID_CTS_ENCP_SEL] = &g12a_cts_encp_sel.hw,
[CLKID_CTS_VDAC_SEL] = &g12a_cts_vdac_sel.hw,
[CLKID_HDMI_TX_SEL] = &g12a_hdmi_tx_sel.hw,
[CLKID_CTS_ENCI] = &g12a_cts_enci.hw,
[CLKID_CTS_ENCP] = &g12a_cts_encp.hw,
[CLKID_CTS_VDAC] = &g12a_cts_vdac.hw,
[CLKID_HDMI_TX] = &g12a_hdmi_tx.hw,
[CLKID_HDMI_SEL] = &g12a_hdmi_sel.hw,
[CLKID_HDMI_DIV] = &g12a_hdmi_div.hw,
[CLKID_HDMI] = &g12a_hdmi.hw,
[CLKID_MALI_0_SEL] = &g12a_mali_0_sel.hw,
[CLKID_MALI_0_DIV] = &g12a_mali_0_div.hw,
[CLKID_MALI_0] = &g12a_mali_0.hw,
[CLKID_MALI_1_SEL] = &g12a_mali_1_sel.hw,
[CLKID_MALI_1_DIV] = &g12a_mali_1_div.hw,
[CLKID_MALI_1] = &g12a_mali_1.hw,
[CLKID_MALI] = &g12a_mali.hw,
[CLKID_MPLL_50M_DIV] = &g12a_mpll_50m_div.hw,
[CLKID_MPLL_50M] = &g12a_mpll_50m.hw,
[CLKID_SYS_PLL_DIV16_EN] = &g12a_sys_pll_div16_en.hw,
[CLKID_SYS_PLL_DIV16] = &g12a_sys_pll_div16.hw,
[CLKID_CPU_CLK_DYN0_SEL] = &g12a_cpu_clk_premux0.hw,
[CLKID_CPU_CLK_DYN0_DIV] = &g12a_cpu_clk_mux0_div.hw,
[CLKID_CPU_CLK_DYN0] = &g12a_cpu_clk_postmux0.hw,
[CLKID_CPU_CLK_DYN1_SEL] = &g12a_cpu_clk_premux1.hw,
[CLKID_CPU_CLK_DYN1_DIV] = &g12a_cpu_clk_mux1_div.hw,
[CLKID_CPU_CLK_DYN1] = &g12a_cpu_clk_postmux1.hw,
[CLKID_CPU_CLK_DYN] = &g12a_cpu_clk_dyn.hw,
[CLKID_CPU_CLK] = &g12a_cpu_clk.hw,
[CLKID_CPU_CLK_DIV16_EN] = &g12a_cpu_clk_div16_en.hw,
[CLKID_CPU_CLK_DIV16] = &g12a_cpu_clk_div16.hw,
[CLKID_CPU_CLK_APB_DIV] = &g12a_cpu_clk_apb_div.hw,
[CLKID_CPU_CLK_APB] = &g12a_cpu_clk_apb.hw,
[CLKID_CPU_CLK_ATB_DIV] = &g12a_cpu_clk_atb_div.hw,
[CLKID_CPU_CLK_ATB] = &g12a_cpu_clk_atb.hw,
[CLKID_CPU_CLK_AXI_DIV] = &g12a_cpu_clk_axi_div.hw,
[CLKID_CPU_CLK_AXI] = &g12a_cpu_clk_axi.hw,
[CLKID_CPU_CLK_TRACE_DIV] = &g12a_cpu_clk_trace_div.hw,
[CLKID_CPU_CLK_TRACE] = &g12a_cpu_clk_trace.hw,
[CLKID_PCIE_PLL_DCO] = &g12a_pcie_pll_dco.hw,
[CLKID_PCIE_PLL_DCO_DIV2] = &g12a_pcie_pll_dco_div2.hw,
[CLKID_PCIE_PLL_OD] = &g12a_pcie_pll_od.hw,
[CLKID_PCIE_PLL] = &g12a_pcie_pll.hw,
[CLKID_VDEC_1_SEL] = &g12a_vdec_1_sel.hw,
[CLKID_VDEC_1_DIV] = &g12a_vdec_1_div.hw,
[CLKID_VDEC_1] = &g12a_vdec_1.hw,
[CLKID_VDEC_HEVC_SEL] = &g12a_vdec_hevc_sel.hw,
[CLKID_VDEC_HEVC_DIV] = &g12a_vdec_hevc_div.hw,
[CLKID_VDEC_HEVC] = &g12a_vdec_hevc.hw,
[CLKID_VDEC_HEVCF_SEL] = &g12a_vdec_hevcf_sel.hw,
[CLKID_VDEC_HEVCF_DIV] = &g12a_vdec_hevcf_div.hw,
[CLKID_VDEC_HEVCF] = &g12a_vdec_hevcf.hw,
[CLKID_TS_DIV] = &g12a_ts_div.hw,
[CLKID_TS] = &g12a_ts.hw,
[CLKID_GP1_PLL_DCO] = &sm1_gp1_pll_dco.hw,
[CLKID_GP1_PLL] = &sm1_gp1_pll.hw,
[CLKID_DSU_CLK_DYN0_SEL] = &sm1_dsu_clk_premux0.hw,
[CLKID_DSU_CLK_DYN0_DIV] = &sm1_dsu_clk_premux1.hw,
[CLKID_DSU_CLK_DYN0] = &sm1_dsu_clk_mux0_div.hw,
[CLKID_DSU_CLK_DYN1_SEL] = &sm1_dsu_clk_postmux0.hw,
[CLKID_DSU_CLK_DYN1_DIV] = &sm1_dsu_clk_mux1_div.hw,
[CLKID_DSU_CLK_DYN1] = &sm1_dsu_clk_postmux1.hw,
[CLKID_DSU_CLK_DYN] = &sm1_dsu_clk_dyn.hw,
[CLKID_DSU_CLK_FINAL] = &sm1_dsu_final_clk.hw,
[CLKID_DSU_CLK] = &sm1_dsu_clk.hw,
[CLKID_CPU1_CLK] = &sm1_cpu1_clk.hw,
[CLKID_CPU2_CLK] = &sm1_cpu2_clk.hw,
[CLKID_CPU3_CLK] = &sm1_cpu3_clk.hw,
[NR_CLKS] = NULL,
},
.num = NR_CLKS,
};
/* Convenience table to populate regmap in .probe */
static struct clk_regmap *const g12a_clk_regmaps[] = {
&g12a_clk81,
@ -4336,6 +4853,20 @@ static struct clk_regmap *const g12a_clk_regmaps[] = {
&g12b_cpub_clk_axi,
&g12b_cpub_clk_trace_sel,
&g12b_cpub_clk_trace,
&sm1_gp1_pll_dco,
&sm1_gp1_pll,
&sm1_dsu_clk_premux0,
&sm1_dsu_clk_premux1,
&sm1_dsu_clk_mux0_div,
&sm1_dsu_clk_postmux0,
&sm1_dsu_clk_mux1_div,
&sm1_dsu_clk_postmux1,
&sm1_dsu_clk_dyn,
&sm1_dsu_final_clk,
&sm1_dsu_clk,
&sm1_cpu1_clk,
&sm1_cpu2_clk,
&sm1_cpu3_clk,
};
static const struct reg_sequence g12a_init_regs[] = {
@ -4532,6 +5063,15 @@ static const struct meson_g12a_data g12b_clkc_data = {
.dvfs_setup = meson_g12b_dvfs_setup,
};
static const struct meson_g12a_data sm1_clkc_data = {
.eeclkc_data = {
.regmap_clks = g12a_clk_regmaps,
.regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
.hw_onecell_data = &sm1_hw_onecell_data,
},
.dvfs_setup = meson_g12a_dvfs_setup,
};
static const struct of_device_id clkc_match_table[] = {
{
.compatible = "amlogic,g12a-clkc",
@ -4541,6 +5081,10 @@ static const struct of_device_id clkc_match_table[] = {
.compatible = "amlogic,g12b-clkc",
.data = &g12b_clkc_data.eeclkc_data
},
{
.compatible = "amlogic,sm1-clkc",
.data = &sm1_clkc_data.eeclkc_data
},
{}
};

View File

@ -29,6 +29,14 @@
#define HHI_GP0_PLL_CNTL5 0x054
#define HHI_GP0_PLL_CNTL6 0x058
#define HHI_GP0_PLL_STS 0x05C
#define HHI_GP1_PLL_CNTL0 0x060
#define HHI_GP1_PLL_CNTL1 0x064
#define HHI_GP1_PLL_CNTL2 0x068
#define HHI_GP1_PLL_CNTL3 0x06C
#define HHI_GP1_PLL_CNTL4 0x070
#define HHI_GP1_PLL_CNTL5 0x074
#define HHI_GP1_PLL_CNTL6 0x078
#define HHI_GP1_PLL_STS 0x07C
#define HHI_PCIE_PLL_CNTL0 0x098
#define HHI_PCIE_PLL_CNTL1 0x09C
#define HHI_PCIE_PLL_CNTL2 0x0A0
@ -72,6 +80,11 @@
#define HHI_SYS_CPUB_CLK_CNTL1 0x200
#define HHI_SYS_CPUB_CLK_CNTL 0x208
#define HHI_VPU_CLKB_CNTL 0x20C
#define HHI_SYS_CPU_CLK_CNTL2 0x210
#define HHI_SYS_CPU_CLK_CNTL3 0x214
#define HHI_SYS_CPU_CLK_CNTL4 0x218
#define HHI_SYS_CPU_CLK_CNTL5 0x21c
#define HHI_SYS_CPU_CLK_CNTL6 0x220
#define HHI_GEN_CLK_CNTL 0x228
#define HHI_VDIN_MEAS_CLK_CNTL 0x250
#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254
@ -233,8 +246,17 @@
#define CLKID_CPUB_CLK_AXI 239
#define CLKID_CPUB_CLK_TRACE_SEL 240
#define CLKID_CPUB_CLK_TRACE 241
#define CLKID_GP1_PLL_DCO 242
#define CLKID_DSU_CLK_DYN0_SEL 244
#define CLKID_DSU_CLK_DYN0_DIV 245
#define CLKID_DSU_CLK_DYN0 246
#define CLKID_DSU_CLK_DYN1_SEL 247
#define CLKID_DSU_CLK_DYN1_DIV 248
#define CLKID_DSU_CLK_DYN1 249
#define CLKID_DSU_CLK_DYN 250
#define CLKID_DSU_CLK_FINAL 251
#define NR_CLKS 242
#define NR_CLKS 256
/* include the CLKIDs that have been made part of the DT binding */
#include <dt-bindings/clock/g12a-clkc.h>

View File

@ -8,6 +8,9 @@ config MVEBU_CLK_CPU
config MVEBU_CLK_COREDIV
bool
config ARMADA_AP_CP_HELPER
bool
config ARMADA_370_CLK
bool
select MVEBU_CLK_COMMON
@ -35,9 +38,14 @@ config ARMADA_XP_CLK
config ARMADA_AP806_SYSCON
bool
select ARMADA_AP_CP_HELPER
config ARMADA_AP_CPU_CLK
bool
config ARMADA_CP110_SYSCON
bool
select ARMADA_AP_CP_HELPER
config DOVE_CLK
bool

View File

@ -2,6 +2,7 @@
obj-$(CONFIG_MVEBU_CLK_COMMON) += common.o
obj-$(CONFIG_MVEBU_CLK_CPU) += clk-cpu.o
obj-$(CONFIG_MVEBU_CLK_COREDIV) += clk-corediv.o
obj-$(CONFIG_ARMADA_AP_CP_HELPER) += armada_ap_cp_helper.o
obj-$(CONFIG_ARMADA_370_CLK) += armada-370.o
obj-$(CONFIG_ARMADA_375_CLK) += armada-375.o
@ -12,6 +13,7 @@ obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-tbg.o
obj-$(CONFIG_ARMADA_37XX_CLK) += armada-37xx-periph.o
obj-$(CONFIG_ARMADA_XP_CLK) += armada-xp.o mv98dx3236.o
obj-$(CONFIG_ARMADA_AP806_SYSCON) += ap806-system-controller.o
obj-$(CONFIG_ARMADA_AP_CPU_CLK) += ap-cpu-clk.o
obj-$(CONFIG_ARMADA_CP110_SYSCON) += cp110-system-controller.o
obj-$(CONFIG_DOVE_CLK) += dove.o dove-divider.o
obj-$(CONFIG_KIRKWOOD_CLK) += kirkwood.o

View File

@ -0,0 +1,356 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Marvell Armada AP CPU Clock Controller
*
* Copyright (C) 2018 Marvell
*
* Omri Itach <omrii@marvell.com>
* Gregory Clement <gregory.clement@bootlin.com>
*/
#define pr_fmt(fmt) "ap-cpu-clk: " fmt
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "armada_ap_cp_helper.h"
#define AP806_CPU_CLUSTER0 0
#define AP806_CPU_CLUSTER1 1
#define AP806_CPUS_PER_CLUSTER 2
#define APN806_CPU1_MASK 0x1
#define APN806_CLUSTER_NUM_OFFSET 8
#define APN806_CLUSTER_NUM_MASK BIT(APN806_CLUSTER_NUM_OFFSET)
#define APN806_MAX_DIVIDER 32
/**
* struct cpu_dfs_regs: CPU DFS register mapping
* @divider_reg: full integer ratio from PLL frequency to CPU clock frequency
* @force_reg: request to force new ratio regardless of relation to other clocks
* @ratio_reg: central request to switch ratios
*/
struct cpu_dfs_regs {
unsigned int divider_reg;
unsigned int force_reg;
unsigned int ratio_reg;
unsigned int ratio_state_reg;
unsigned int divider_mask;
unsigned int cluster_offset;
unsigned int force_mask;
int divider_offset;
int divider_ratio;
int ratio_offset;
int ratio_state_offset;
int ratio_state_cluster_offset;
};
/* AP806 CPU DFS register mapping*/
#define AP806_CA72MP2_0_PLL_CR_0_REG_OFFSET 0x278
#define AP806_CA72MP2_0_PLL_CR_1_REG_OFFSET 0x280
#define AP806_CA72MP2_0_PLL_CR_2_REG_OFFSET 0x284
#define AP806_CA72MP2_0_PLL_SR_REG_OFFSET 0xC94
#define AP806_CA72MP2_0_PLL_CR_CLUSTER_OFFSET 0x14
#define AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET 0
#define AP806_PLL_CR_CPU_CLK_DIV_RATIO 0
#define AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET)
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET 24
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK \
(0x1 << AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET)
#define AP806_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET 16
#define AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET 0
#define AP806_CA72MP2_0_PLL_RATIO_STATE 11
#define STATUS_POLL_PERIOD_US 1
#define STATUS_POLL_TIMEOUT_US 1000000
#define to_ap_cpu_clk(_hw) container_of(_hw, struct ap_cpu_clk, hw)
static const struct cpu_dfs_regs ap806_dfs_regs = {
.divider_reg = AP806_CA72MP2_0_PLL_CR_0_REG_OFFSET,
.force_reg = AP806_CA72MP2_0_PLL_CR_1_REG_OFFSET,
.ratio_reg = AP806_CA72MP2_0_PLL_CR_2_REG_OFFSET,
.ratio_state_reg = AP806_CA72MP2_0_PLL_SR_REG_OFFSET,
.divider_mask = AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK,
.cluster_offset = AP806_CA72MP2_0_PLL_CR_CLUSTER_OFFSET,
.force_mask = AP806_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK,
.divider_offset = AP806_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET,
.divider_ratio = AP806_PLL_CR_CPU_CLK_DIV_RATIO,
.ratio_offset = AP806_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET,
.ratio_state_offset = AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET,
.ratio_state_cluster_offset = AP806_CA72MP2_0_PLL_RATIO_STABLE_OFFSET,
};
/* AP807 CPU DFS register mapping */
#define AP807_DEVICE_GENERAL_CONTROL_10_REG_OFFSET 0x278
#define AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET 0x27c
#define AP807_DEVICE_GENERAL_STATUS_6_REG_OFFSET 0xc98
#define AP807_CA72MP2_0_PLL_CR_CLUSTER_OFFSET 0x8
#define AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET 18
#define AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET)
#define AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET 12
#define AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_MASK \
(0x3f << AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET)
#define AP807_PLL_CR_CPU_CLK_DIV_RATIO 3
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET 0
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK \
(0x3 << AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_OFFSET)
#define AP807_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET 6
#define AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_OFFSET 20
#define AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_CLUSTER_OFFSET 3
static const struct cpu_dfs_regs ap807_dfs_regs = {
.divider_reg = AP807_DEVICE_GENERAL_CONTROL_10_REG_OFFSET,
.force_reg = AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET,
.ratio_reg = AP807_DEVICE_GENERAL_CONTROL_11_REG_OFFSET,
.ratio_state_reg = AP807_DEVICE_GENERAL_STATUS_6_REG_OFFSET,
.divider_mask = AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_MASK,
.cluster_offset = AP807_CA72MP2_0_PLL_CR_CLUSTER_OFFSET,
.force_mask = AP807_PLL_CR_0_CPU_CLK_RELOAD_FORCE_MASK,
.divider_offset = AP807_PLL_CR_0_CPU_CLK_DIV_RATIO_OFFSET,
.divider_ratio = AP807_PLL_CR_CPU_CLK_DIV_RATIO,
.ratio_offset = AP807_PLL_CR_0_CPU_CLK_RELOAD_RATIO_OFFSET,
.ratio_state_offset = AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_OFFSET,
.ratio_state_cluster_offset =
AP807_CA72MP2_0_PLL_CLKDIV_RATIO_STABLE_CLUSTER_OFFSET
};
/*
* struct ap806_clk: CPU cluster clock controller instance
* @cluster: Cluster clock controller index
* @clk_name: Cluster clock controller name
* @dev : Cluster clock device
* @hw: HW specific structure of Cluster clock controller
* @pll_cr_base: CA72MP2 Register base (Device Sample at Reset register)
*/
struct ap_cpu_clk {
unsigned int cluster;
const char *clk_name;
struct device *dev;
struct clk_hw hw;
struct regmap *pll_cr_base;
const struct cpu_dfs_regs *pll_regs;
};
static unsigned long ap_cpu_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct ap_cpu_clk *clk = to_ap_cpu_clk(hw);
unsigned int cpu_clkdiv_reg;
int cpu_clkdiv_ratio;
cpu_clkdiv_reg = clk->pll_regs->divider_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
regmap_read(clk->pll_cr_base, cpu_clkdiv_reg, &cpu_clkdiv_ratio);
cpu_clkdiv_ratio &= clk->pll_regs->divider_mask;
cpu_clkdiv_ratio >>= clk->pll_regs->divider_offset;
return parent_rate / cpu_clkdiv_ratio;
}
static int ap_cpu_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct ap_cpu_clk *clk = to_ap_cpu_clk(hw);
int ret, reg, divider = parent_rate / rate;
unsigned int cpu_clkdiv_reg, cpu_force_reg, cpu_ratio_reg, stable_bit;
cpu_clkdiv_reg = clk->pll_regs->divider_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
cpu_force_reg = clk->pll_regs->force_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
cpu_ratio_reg = clk->pll_regs->ratio_reg +
(clk->cluster * clk->pll_regs->cluster_offset);
regmap_read(clk->pll_cr_base, cpu_clkdiv_reg, &reg);
reg &= ~(clk->pll_regs->divider_mask);
reg |= (divider << clk->pll_regs->divider_offset);
/*
* AP807 CPU divider has two channels with ratio 1:3 and divider_ratio
* is 1. Otherwise, in the case of the AP806, divider_ratio is 0.
*/
if (clk->pll_regs->divider_ratio) {
reg &= ~(AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_MASK);
reg |= ((divider * clk->pll_regs->divider_ratio) <<
AP807_PLL_CR_1_CPU_CLK_DIV_RATIO_OFFSET);
}
regmap_write(clk->pll_cr_base, cpu_clkdiv_reg, reg);
regmap_update_bits(clk->pll_cr_base, cpu_force_reg,
clk->pll_regs->force_mask,
clk->pll_regs->force_mask);
regmap_update_bits(clk->pll_cr_base, cpu_ratio_reg,
BIT(clk->pll_regs->ratio_offset),
BIT(clk->pll_regs->ratio_offset));
stable_bit = BIT(clk->pll_regs->ratio_state_offset +
clk->cluster *
clk->pll_regs->ratio_state_cluster_offset),
ret = regmap_read_poll_timeout(clk->pll_cr_base,
clk->pll_regs->ratio_state_reg, reg,
reg & stable_bit, STATUS_POLL_PERIOD_US,
STATUS_POLL_TIMEOUT_US);
if (ret)
return ret;
regmap_update_bits(clk->pll_cr_base, cpu_ratio_reg,
BIT(clk->pll_regs->ratio_offset), 0);
return 0;
}
static long ap_cpu_clk_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
int divider = *parent_rate / rate;
divider = min(divider, APN806_MAX_DIVIDER);
return *parent_rate / divider;
}
static const struct clk_ops ap_cpu_clk_ops = {
.recalc_rate = ap_cpu_clk_recalc_rate,
.round_rate = ap_cpu_clk_round_rate,
.set_rate = ap_cpu_clk_set_rate,
};
static int ap_cpu_clock_probe(struct platform_device *pdev)
{
int ret, nclusters = 0, cluster_index = 0;
struct device *dev = &pdev->dev;
struct device_node *dn, *np = dev->of_node;
struct clk_hw_onecell_data *ap_cpu_data;
struct ap_cpu_clk *ap_cpu_clk;
struct regmap *regmap;
regmap = syscon_node_to_regmap(np->parent);
if (IS_ERR(regmap)) {
pr_err("cannot get pll_cr_base regmap\n");
return PTR_ERR(regmap);
}
/*
* AP806 has 4 cpus and DFS for AP806 is controlled per
* cluster (2 CPUs per cluster), cpu0 and cpu1 are fixed to
* cluster0 while cpu2 and cpu3 are fixed to cluster1 whether
* they are enabled or not. Since cpu0 is the boot cpu, then
* cluster0 must exist. If cpu2 or cpu3 is enabled, cluster1
* will exist and the cluster number is 2; otherwise the
* cluster number is 1.
*/
nclusters = 1;
for_each_of_cpu_node(dn) {
int cpu, err;
err = of_property_read_u32(dn, "reg", &cpu);
if (WARN_ON(err))
return err;
/* If cpu2 or cpu3 is enabled */
if (cpu & APN806_CLUSTER_NUM_MASK) {
nclusters = 2;
break;
}
}
/*
* DFS for AP806 is controlled per cluster (2 CPUs per cluster),
* so allocate structs per cluster
*/
ap_cpu_clk = devm_kcalloc(dev, nclusters, sizeof(*ap_cpu_clk),
GFP_KERNEL);
if (!ap_cpu_clk)
return -ENOMEM;
ap_cpu_data = devm_kzalloc(dev, sizeof(*ap_cpu_data) +
sizeof(struct clk_hw *) * nclusters,
GFP_KERNEL);
if (!ap_cpu_data)
return -ENOMEM;
for_each_of_cpu_node(dn) {
char *clk_name = "cpu-cluster-0";
struct clk_init_data init;
const char *parent_name;
struct clk *parent;
int cpu, err;
err = of_property_read_u32(dn, "reg", &cpu);
if (WARN_ON(err))
return err;
cluster_index = cpu & APN806_CLUSTER_NUM_MASK;
cluster_index >>= APN806_CLUSTER_NUM_OFFSET;
/* Initialize once for one cluster */
if (ap_cpu_data->hws[cluster_index])
continue;
parent = of_clk_get(np, cluster_index);
if (IS_ERR(parent)) {
dev_err(dev, "Could not get the clock parent\n");
return -EINVAL;
}
parent_name = __clk_get_name(parent);
clk_name[12] += cluster_index;
ap_cpu_clk[cluster_index].clk_name =
ap_cp_unique_name(dev, np->parent, clk_name);
ap_cpu_clk[cluster_index].cluster = cluster_index;
ap_cpu_clk[cluster_index].pll_cr_base = regmap;
ap_cpu_clk[cluster_index].hw.init = &init;
ap_cpu_clk[cluster_index].dev = dev;
ap_cpu_clk[cluster_index].pll_regs = of_device_get_match_data(&pdev->dev);
init.name = ap_cpu_clk[cluster_index].clk_name;
init.ops = &ap_cpu_clk_ops;
init.num_parents = 1;
init.parent_names = &parent_name;
ret = devm_clk_hw_register(dev, &ap_cpu_clk[cluster_index].hw);
if (ret)
return ret;
ap_cpu_data->hws[cluster_index] = &ap_cpu_clk[cluster_index].hw;
}
ap_cpu_data->num = cluster_index + 1;
ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, ap_cpu_data);
if (ret)
dev_err(dev, "failed to register OF clock provider\n");
return ret;
}
static const struct of_device_id ap_cpu_clock_of_match[] = {
{
.compatible = "marvell,ap806-cpu-clock",
.data = &ap806_dfs_regs,
},
{
.compatible = "marvell,ap807-cpu-clock",
.data = &ap807_dfs_regs,
},
{ }
};
static struct platform_driver ap_cpu_clock_driver = {
.probe = ap_cpu_clock_probe,
.driver = {
.name = "marvell-ap-cpu-clock",
.of_match_table = ap_cpu_clock_of_match,
.suppress_bind_attrs = true,
},
};
builtin_platform_driver(ap_cpu_clock_driver);

View File

@ -10,18 +10,18 @@
#define pr_fmt(fmt) "ap806-system-controller: " fmt
#include "armada_ap_cp_helper.h"
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#define AP806_SAR_REG 0x400
#define AP806_SAR_CLKFREQ_MODE_MASK 0x1f
#define AP806_CLK_NUM 5
#define AP806_CLK_NUM 6
static struct clk *ap806_clks[AP806_CLK_NUM];
@ -30,22 +30,106 @@ static struct clk_onecell_data ap806_clk_data = {
.clk_num = AP806_CLK_NUM,
};
static char *ap806_unique_name(struct device *dev, struct device_node *np,
char *name)
static int ap806_get_sar_clocks(unsigned int freq_mode,
unsigned int *cpuclk_freq,
unsigned int *dclk_freq)
{
const __be32 *reg;
u64 addr;
switch (freq_mode) {
case 0x0:
*cpuclk_freq = 2000;
*dclk_freq = 600;
break;
case 0x1:
*cpuclk_freq = 2000;
*dclk_freq = 525;
break;
case 0x6:
*cpuclk_freq = 1800;
*dclk_freq = 600;
break;
case 0x7:
*cpuclk_freq = 1800;
*dclk_freq = 525;
break;
case 0x4:
*cpuclk_freq = 1600;
*dclk_freq = 400;
break;
case 0xB:
*cpuclk_freq = 1600;
*dclk_freq = 450;
break;
case 0xD:
*cpuclk_freq = 1600;
*dclk_freq = 525;
break;
case 0x1a:
*cpuclk_freq = 1400;
*dclk_freq = 400;
break;
case 0x14:
*cpuclk_freq = 1300;
*dclk_freq = 400;
break;
case 0x17:
*cpuclk_freq = 1300;
*dclk_freq = 325;
break;
case 0x19:
*cpuclk_freq = 1200;
*dclk_freq = 400;
break;
case 0x13:
*cpuclk_freq = 1000;
*dclk_freq = 325;
break;
case 0x1d:
*cpuclk_freq = 1000;
*dclk_freq = 400;
break;
case 0x1c:
*cpuclk_freq = 800;
*dclk_freq = 400;
break;
case 0x1b:
*cpuclk_freq = 600;
*dclk_freq = 400;
break;
default:
return -EINVAL;
}
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
return 0;
}
static int ap807_get_sar_clocks(unsigned int freq_mode,
unsigned int *cpuclk_freq,
unsigned int *dclk_freq)
{
switch (freq_mode) {
case 0x0:
*cpuclk_freq = 2000;
*dclk_freq = 1200;
break;
case 0x6:
*cpuclk_freq = 2200;
*dclk_freq = 1200;
break;
case 0xD:
*cpuclk_freq = 1600;
*dclk_freq = 1200;
break;
default:
return -EINVAL;
}
return 0;
}
static int ap806_syscon_common_probe(struct platform_device *pdev,
struct device_node *syscon_node)
{
unsigned int freq_mode, cpuclk_freq;
unsigned int freq_mode, cpuclk_freq, dclk_freq;
const char *name, *fixedclk_name;
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
@ -66,50 +150,29 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
freq_mode = reg & AP806_SAR_CLKFREQ_MODE_MASK;
switch (freq_mode) {
case 0x0:
case 0x1:
cpuclk_freq = 2000;
break;
case 0x6:
case 0x7:
cpuclk_freq = 1800;
break;
case 0x4:
case 0xB:
case 0xD:
cpuclk_freq = 1600;
break;
case 0x1a:
cpuclk_freq = 1400;
break;
case 0x14:
case 0x17:
cpuclk_freq = 1300;
break;
case 0x19:
cpuclk_freq = 1200;
break;
case 0x13:
case 0x1d:
cpuclk_freq = 1000;
break;
case 0x1c:
cpuclk_freq = 800;
break;
case 0x1b:
cpuclk_freq = 600;
break;
default:
dev_err(dev, "invalid SAR value\n");
if (of_device_is_compatible(pdev->dev.of_node,
"marvell,ap806-clock")) {
ret = ap806_get_sar_clocks(freq_mode, &cpuclk_freq, &dclk_freq);
} else if (of_device_is_compatible(pdev->dev.of_node,
"marvell,ap807-clock")) {
ret = ap807_get_sar_clocks(freq_mode, &cpuclk_freq, &dclk_freq);
} else {
dev_err(dev, "compatible not supported\n");
return -EINVAL;
}
if (ret) {
dev_err(dev, "invalid Sample at Reset value\n");
return ret;
}
/* Convert to hertz */
cpuclk_freq *= 1000 * 1000;
dclk_freq *= 1000 * 1000;
/* CPU clocks depend on the Sample At Reset configuration */
name = ap806_unique_name(dev, syscon_node, "cpu-cluster-0");
name = ap_cp_unique_name(dev, syscon_node, "pll-cluster-0");
ap806_clks[0] = clk_register_fixed_rate(dev, name, NULL,
0, cpuclk_freq);
if (IS_ERR(ap806_clks[0])) {
@ -117,7 +180,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
goto fail0;
}
name = ap806_unique_name(dev, syscon_node, "cpu-cluster-1");
name = ap_cp_unique_name(dev, syscon_node, "pll-cluster-1");
ap806_clks[1] = clk_register_fixed_rate(dev, name, NULL, 0,
cpuclk_freq);
if (IS_ERR(ap806_clks[1])) {
@ -126,7 +189,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* Fixed clock is always 1200 Mhz */
fixedclk_name = ap806_unique_name(dev, syscon_node, "fixed");
fixedclk_name = ap_cp_unique_name(dev, syscon_node, "fixed");
ap806_clks[2] = clk_register_fixed_rate(dev, fixedclk_name, NULL,
0, 1200 * 1000 * 1000);
if (IS_ERR(ap806_clks[2])) {
@ -135,7 +198,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* MSS Clock is fixed clock divided by 6 */
name = ap806_unique_name(dev, syscon_node, "mss");
name = ap_cp_unique_name(dev, syscon_node, "mss");
ap806_clks[3] = clk_register_fixed_factor(NULL, name, fixedclk_name,
0, 1, 6);
if (IS_ERR(ap806_clks[3])) {
@ -144,7 +207,7 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
}
/* SDIO(/eMMC) Clock is fixed clock divided by 3 */
name = ap806_unique_name(dev, syscon_node, "sdio");
name = ap_cp_unique_name(dev, syscon_node, "sdio");
ap806_clks[4] = clk_register_fixed_factor(NULL, name,
fixedclk_name,
0, 1, 3);
@ -153,6 +216,14 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
goto fail4;
}
/* AP-DCLK(HCLK) Clock is DDR clock divided by 2 */
name = ap_cp_unique_name(dev, syscon_node, "ap-dclk");
ap806_clks[5] = clk_register_fixed_rate(dev, name, NULL, 0, dclk_freq);
if (IS_ERR(ap806_clks[5])) {
ret = PTR_ERR(ap806_clks[5]);
goto fail5;
}
ret = of_clk_add_provider(np, of_clk_src_onecell_get, &ap806_clk_data);
if (ret)
goto fail_clk_add;
@ -160,6 +231,8 @@ static int ap806_syscon_common_probe(struct platform_device *pdev,
return 0;
fail_clk_add:
clk_unregister_fixed_factor(ap806_clks[5]);
fail5:
clk_unregister_fixed_factor(ap806_clks[4]);
fail4:
clk_unregister_fixed_factor(ap806_clks[3]);
@ -206,6 +279,7 @@ builtin_platform_driver(ap806_syscon_legacy_driver);
static const struct of_device_id ap806_clock_of_match[] = {
{ .compatible = "marvell,ap806-clock", },
{ .compatible = "marvell,ap807-clock", },
{ }
};

View File

@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* Marvell Armada AP and CP110 helper
*
* Copyright (C) 2018 Marvell
*
* Gregory Clement <gregory.clement@bootlin.com>
*
*/
#include "armada_ap_cp_helper.h"
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
char *ap_cp_unique_name(struct device *dev, struct device_node *np,
const char *name)
{
const __be32 *reg;
u64 addr;
/* Do not create a name if there is no clock */
if (!name)
return NULL;
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
}

View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#ifndef __ARMADA_AP_CP_HELPER_H
#define __ARMADA_AP_CP_HELPER_H
struct device;
struct device_node;
char *ap_cp_unique_name(struct device *dev, struct device_node *np,
const char *name);
#endif

View File

@ -26,11 +26,11 @@
#define pr_fmt(fmt) "cp110-system-controller: " fmt
#include "armada_ap_cp_helper.h"
#include <linux/clk-provider.h>
#include <linux/mfd/syscon.h>
#include <linux/init.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@ -212,22 +212,6 @@ static struct clk_hw *cp110_of_clk_get(struct of_phandle_args *clkspec,
return ERR_PTR(-EINVAL);
}
static char *cp110_unique_name(struct device *dev, struct device_node *np,
const char *name)
{
const __be32 *reg;
u64 addr;
/* Do not create a name if there is no clock */
if (!name)
return NULL;
reg = of_get_property(np, "reg", NULL);
addr = of_translate_address(np, reg);
return devm_kasprintf(dev, GFP_KERNEL, "%llx-%s",
(unsigned long long)addr, name);
}
static int cp110_syscon_common_probe(struct platform_device *pdev,
struct device_node *syscon_node)
{
@ -261,7 +245,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clk_data->num = CP110_CLK_NUM;
/* Register the PLL0 which is the root of the hw tree */
pll0_name = cp110_unique_name(dev, syscon_node, "pll0");
pll0_name = ap_cp_unique_name(dev, syscon_node, "pll0");
hw = clk_hw_register_fixed_rate(NULL, pll0_name, NULL, 0,
1000 * 1000 * 1000);
if (IS_ERR(hw)) {
@ -272,7 +256,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_PLL0] = hw;
/* PPv2 is PLL0/3 */
ppv2_name = cp110_unique_name(dev, syscon_node, "ppv2-core");
ppv2_name = ap_cp_unique_name(dev, syscon_node, "ppv2-core");
hw = clk_hw_register_fixed_factor(NULL, ppv2_name, pll0_name, 0, 1, 3);
if (IS_ERR(hw)) {
ret = PTR_ERR(hw);
@ -282,7 +266,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_PPV2] = hw;
/* X2CORE clock is PLL0/2 */
x2core_name = cp110_unique_name(dev, syscon_node, "x2core");
x2core_name = ap_cp_unique_name(dev, syscon_node, "x2core");
hw = clk_hw_register_fixed_factor(NULL, x2core_name, pll0_name,
0, 1, 2);
if (IS_ERR(hw)) {
@ -293,7 +277,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_X2CORE] = hw;
/* Core clock is X2CORE/2 */
core_name = cp110_unique_name(dev, syscon_node, "core");
core_name = ap_cp_unique_name(dev, syscon_node, "core");
hw = clk_hw_register_fixed_factor(NULL, core_name, x2core_name,
0, 1, 2);
if (IS_ERR(hw)) {
@ -303,7 +287,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_CORE] = hw;
/* NAND can be either PLL0/2.5 or core clock */
nand_name = cp110_unique_name(dev, syscon_node, "nand-core");
nand_name = ap_cp_unique_name(dev, syscon_node, "nand-core");
if (nand_clk_ctrl & NF_CLOCK_SEL_400_MASK)
hw = clk_hw_register_fixed_factor(NULL, nand_name,
pll0_name, 0, 2, 5);
@ -318,7 +302,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
cp110_clks[CP110_CORE_NAND] = hw;
/* SDIO clock is PLL0/2.5 */
sdio_name = cp110_unique_name(dev, syscon_node, "sdio-core");
sdio_name = ap_cp_unique_name(dev, syscon_node, "sdio-core");
hw = clk_hw_register_fixed_factor(NULL, sdio_name,
pll0_name, 0, 2, 5);
if (IS_ERR(hw)) {
@ -330,7 +314,7 @@ static int cp110_syscon_common_probe(struct platform_device *pdev,
/* create the unique name for all the gate clocks */
for (i = 0; i < ARRAY_SIZE(gate_base_names); i++)
gate_name[i] = cp110_unique_name(dev, syscon_node,
gate_name[i] = ap_cp_unique_name(dev, syscon_node,
gate_base_names[i]);
for (i = 0; i < ARRAY_SIZE(gate_base_names); i++) {

View File

@ -21,7 +21,6 @@ if COMMON_CLK_QCOM
config QCOM_A53PLL
tristate "MSM8916 A53 PLL"
default ARCH_QCOM
help
Support for the A53 PLL on MSM8916 devices. It provides
the CPU with frequencies above 1GHz.
@ -31,7 +30,6 @@ config QCOM_A53PLL
config QCOM_CLK_APCS_MSM8916
tristate "MSM8916 APCS Clock Controller"
depends on QCOM_APCS_IPC || COMPILE_TEST
default ARCH_QCOM
help
Support for the APCS Clock Controller on msm8916 devices. The
APCS is managing the mux and divider which feeds the CPUs.
@ -292,6 +290,13 @@ config SDM_LPASSCC_845
Say Y if you want to use the LPASS branch clocks of the LPASS clock
controller to reset the LPASS subsystem.
config SM_GCC_8150
tristate "SM8150 Global Clock Controller"
help
Support for the global clock controller on SM8150 devices.
Say Y if you want to use peripheral devices such as UART,
SPI, I2C, USB, SD/UFS, PCIe etc.
config SPMI_PMIC_CLKDIV
tristate "SPMI PMIC clkdiv Support"
depends on SPMI || COMPILE_TEST

View File

@ -50,6 +50,7 @@ obj-$(CONFIG_SDM_GCC_845) += gcc-sdm845.o
obj-$(CONFIG_SDM_GPUCC_845) += gpucc-sdm845.o
obj-$(CONFIG_SDM_LPASSCC_845) += lpasscc-sdm845.o
obj-$(CONFIG_SDM_VIDEOCC_845) += videocc-sdm845.o
obj-$(CONFIG_SM_GCC_8150) += gcc-sm8150.o
obj-$(CONFIG_SPMI_PMIC_CLKDIV) += clk-spmi-pmic-div.o
obj-$(CONFIG_KPSS_XCC) += kpss-xcc.o
obj-$(CONFIG_QCOM_HFPLL) += hfpll.o

View File

@ -32,6 +32,7 @@
# define PLL_LOCK_DET BIT(31)
#define PLL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_L_VAL])
#define PLL_CAL_L_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_L_VAL])
#define PLL_ALPHA_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL])
#define PLL_ALPHA_VAL_U(p) ((p)->offset + (p)->regs[PLL_OFF_ALPHA_VAL_U])
@ -44,14 +45,17 @@
# define PLL_VCO_MASK 0x3
#define PLL_USER_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U])
#define PLL_USER_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_USER_CTL_U1])
#define PLL_CONFIG_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL])
#define PLL_CONFIG_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U])
#define PLL_CONFIG_CTL_U1(p) ((p)->offset + (p)->regs[PLL_OFF_CONFIG_CTL_U1])
#define PLL_TEST_CTL(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL])
#define PLL_TEST_CTL_U(p) ((p)->offset + (p)->regs[PLL_OFF_TEST_CTL_U])
#define PLL_STATUS(p) ((p)->offset + (p)->regs[PLL_OFF_STATUS])
#define PLL_OPMODE(p) ((p)->offset + (p)->regs[PLL_OFF_OPMODE])
#define PLL_FRAC(p) ((p)->offset + (p)->regs[PLL_OFF_FRAC])
#define PLL_CAL_VAL(p) ((p)->offset + (p)->regs[PLL_OFF_CAL_VAL])
const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[CLK_ALPHA_PLL_TYPE_DEFAULT] = {
@ -96,6 +100,22 @@ const u8 clk_alpha_pll_regs[][PLL_OFF_MAX_REGS] = {
[PLL_OFF_OPMODE] = 0x2c,
[PLL_OFF_FRAC] = 0x38,
},
[CLK_ALPHA_PLL_TYPE_TRION] = {
[PLL_OFF_L_VAL] = 0x04,
[PLL_OFF_CAL_L_VAL] = 0x08,
[PLL_OFF_USER_CTL] = 0x0c,
[PLL_OFF_USER_CTL_U] = 0x10,
[PLL_OFF_USER_CTL_U1] = 0x14,
[PLL_OFF_CONFIG_CTL] = 0x18,
[PLL_OFF_CONFIG_CTL_U] = 0x1c,
[PLL_OFF_CONFIG_CTL_U1] = 0x20,
[PLL_OFF_TEST_CTL] = 0x24,
[PLL_OFF_TEST_CTL_U] = 0x28,
[PLL_OFF_STATUS] = 0x30,
[PLL_OFF_OPMODE] = 0x38,
[PLL_OFF_ALPHA_VAL] = 0x40,
[PLL_OFF_CAL_VAL] = 0x44,
},
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
@ -120,6 +140,10 @@ EXPORT_SYMBOL_GPL(clk_alpha_pll_regs);
#define FABIA_PLL_OUT_MASK 0x7
#define FABIA_PLL_RATE_MARGIN 500
#define TRION_PLL_STANDBY 0x0
#define TRION_PLL_RUN 0x1
#define TRION_PLL_OUT_MASK 0x7
#define pll_alpha_width(p) \
((PLL_ALPHA_VAL_U(p) - PLL_ALPHA_VAL(p) == 4) ? \
ALPHA_REG_BITWIDTH : ALPHA_REG_16BIT_WIDTH)
@ -730,6 +754,130 @@ static long alpha_pll_huayra_round_rate(struct clk_hw *hw, unsigned long rate,
return alpha_huayra_pll_round_rate(rate, *prate, &l, &a);
}
static int trion_pll_is_enabled(struct clk_alpha_pll *pll,
struct regmap *regmap)
{
u32 mode_regval, opmode_regval;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &mode_regval);
ret |= regmap_read(regmap, PLL_OPMODE(pll), &opmode_regval);
if (ret)
return 0;
return ((opmode_regval & TRION_PLL_RUN) && (mode_regval & PLL_OUTCTRL));
}
static int clk_trion_pll_is_enabled(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
return trion_pll_is_enabled(pll, pll->clkr.regmap);
}
static int clk_trion_pll_enable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 val;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return ret;
/* If in FSM mode, just vote for it */
if (val & PLL_VOTE_FSM_ENA) {
ret = clk_enable_regmap(hw);
if (ret)
return ret;
return wait_for_pll_enable_active(pll);
}
/* Set operation mode to RUN */
regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_RUN);
ret = wait_for_pll_enable_lock(pll);
if (ret)
return ret;
/* Enable the PLL outputs */
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),
TRION_PLL_OUT_MASK, TRION_PLL_OUT_MASK);
if (ret)
return ret;
/* Enable the global PLL outputs */
return regmap_update_bits(regmap, PLL_MODE(pll),
PLL_OUTCTRL, PLL_OUTCTRL);
}
static void clk_trion_pll_disable(struct clk_hw *hw)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 val;
int ret;
ret = regmap_read(regmap, PLL_MODE(pll), &val);
if (ret)
return;
/* If in FSM mode, just unvote it */
if (val & PLL_VOTE_FSM_ENA) {
clk_disable_regmap(hw);
return;
}
/* Disable the global PLL output */
ret = regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0);
if (ret)
return;
/* Disable the PLL outputs */
ret = regmap_update_bits(regmap, PLL_USER_CTL(pll),
TRION_PLL_OUT_MASK, 0);
if (ret)
return;
/* Place the PLL mode in STANDBY */
regmap_write(regmap, PLL_OPMODE(pll), TRION_PLL_STANDBY);
regmap_update_bits(regmap, PLL_MODE(pll), PLL_RESET_N, PLL_RESET_N);
}
static unsigned long
clk_trion_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 l, frac;
u64 prate = parent_rate;
regmap_read(regmap, PLL_L_VAL(pll), &l);
regmap_read(regmap, PLL_ALPHA_VAL(pll), &frac);
return alpha_pll_calc_rate(prate, l, frac, ALPHA_REG_16BIT_WIDTH);
}
static long clk_trion_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll *pll = to_clk_alpha_pll(hw);
unsigned long min_freq, max_freq;
u32 l;
u64 a;
rate = alpha_pll_round_rate(rate, *prate,
&l, &a, ALPHA_REG_16BIT_WIDTH);
if (!pll->vco_table || alpha_pll_find_vco(pll, rate))
return rate;
min_freq = pll->vco_table[0].min_freq;
max_freq = pll->vco_table[pll->num_vco - 1].max_freq;
return clamp(rate, min_freq, max_freq);
}
const struct clk_ops clk_alpha_pll_ops = {
.enable = clk_alpha_pll_enable,
.disable = clk_alpha_pll_disable,
@ -760,6 +908,15 @@ const struct clk_ops clk_alpha_pll_hwfsm_ops = {
};
EXPORT_SYMBOL_GPL(clk_alpha_pll_hwfsm_ops);
const struct clk_ops clk_trion_fixed_pll_ops = {
.enable = clk_trion_pll_enable,
.disable = clk_trion_pll_disable,
.is_enabled = clk_trion_pll_is_enabled,
.recalc_rate = clk_trion_pll_recalc_rate,
.round_rate = clk_trion_pll_round_rate,
};
EXPORT_SYMBOL_GPL(clk_trion_fixed_pll_ops);
static unsigned long
clk_alpha_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
@ -832,7 +989,7 @@ static int clk_alpha_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
int div;
/* 16 -> 0xf, 8 -> 0x7, 4 -> 0x3, 2 -> 0x1, 1 -> 0x0 */
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
div = DIV_ROUND_UP_ULL(parent_rate, rate) - 1;
return regmap_update_bits(pll->clkr.regmap, PLL_USER_CTL(pll),
PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
@ -1036,11 +1193,6 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw,
u32 i, div = 1, val;
int ret;
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
ret = regmap_read(pll->clkr.regmap, PLL_USER_CTL(pll), &val);
if (ret)
return ret;
@ -1058,16 +1210,71 @@ static unsigned long clk_alpha_pll_postdiv_fabia_recalc_rate(struct clk_hw *hw,
return (parent_rate / div);
}
static unsigned long
clk_trion_pll_postdiv_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
struct regmap *regmap = pll->clkr.regmap;
u32 i, div = 1, val;
regmap_read(regmap, PLL_USER_CTL(pll), &val);
val >>= pll->post_div_shift;
val &= PLL_POST_DIV_MASK(pll);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].val == val) {
div = pll->post_div_table[i].div;
break;
}
}
return (parent_rate / div);
}
static long
clk_trion_pll_postdiv_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
return divider_round_rate(hw, rate, prate, pll->post_div_table,
pll->width, CLK_DIVIDER_ROUND_CLOSEST);
};
static int
clk_trion_pll_postdiv_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
struct regmap *regmap = pll->clkr.regmap;
int i, val = 0, div;
div = DIV_ROUND_UP_ULL(parent_rate, rate);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].div == div) {
val = pll->post_div_table[i].val;
break;
}
}
return regmap_update_bits(regmap, PLL_USER_CTL(pll),
PLL_POST_DIV_MASK(pll) << PLL_POST_DIV_SHIFT,
val << PLL_POST_DIV_SHIFT);
}
const struct clk_ops clk_trion_pll_postdiv_ops = {
.recalc_rate = clk_trion_pll_postdiv_recalc_rate,
.round_rate = clk_trion_pll_postdiv_round_rate,
.set_rate = clk_trion_pll_postdiv_set_rate,
};
EXPORT_SYMBOL_GPL(clk_trion_pll_postdiv_ops);
static long clk_alpha_pll_postdiv_fabia_round_rate(struct clk_hw *hw,
unsigned long rate, unsigned long *prate)
{
struct clk_alpha_pll_postdiv *pll = to_clk_alpha_pll_postdiv(hw);
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
return divider_round_rate(hw, rate, prate, pll->post_div_table,
pll->width, CLK_DIVIDER_ROUND_CLOSEST);
}
@ -1089,12 +1296,7 @@ static int clk_alpha_pll_postdiv_fabia_set_rate(struct clk_hw *hw,
if (val & PLL_VOTE_FSM_ENA)
return 0;
if (!pll->post_div_table) {
pr_err("Missing the post_div_table for the PLL\n");
return -EINVAL;
}
div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
div = DIV_ROUND_UP_ULL(parent_rate, rate);
for (i = 0; i < pll->num_post_div; i++) {
if (pll->post_div_table[i].div == div) {
val = pll->post_div_table[i].val;

View File

@ -13,22 +13,27 @@ enum {
CLK_ALPHA_PLL_TYPE_HUAYRA,
CLK_ALPHA_PLL_TYPE_BRAMMO,
CLK_ALPHA_PLL_TYPE_FABIA,
CLK_ALPHA_PLL_TYPE_TRION,
CLK_ALPHA_PLL_TYPE_MAX,
};
enum {
PLL_OFF_L_VAL,
PLL_OFF_CAL_L_VAL,
PLL_OFF_ALPHA_VAL,
PLL_OFF_ALPHA_VAL_U,
PLL_OFF_USER_CTL,
PLL_OFF_USER_CTL_U,
PLL_OFF_USER_CTL_U1,
PLL_OFF_CONFIG_CTL,
PLL_OFF_CONFIG_CTL_U,
PLL_OFF_CONFIG_CTL_U1,
PLL_OFF_TEST_CTL,
PLL_OFF_TEST_CTL_U,
PLL_OFF_STATUS,
PLL_OFF_OPMODE,
PLL_OFF_FRAC,
PLL_OFF_CAL_VAL,
PLL_OFF_MAX_REGS
};
@ -117,5 +122,7 @@ void clk_alpha_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
void clk_fabia_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap,
const struct alpha_pll_config *config);
extern const struct clk_ops clk_trion_fixed_pll_ops;
extern const struct clk_ops clk_trion_pll_postdiv_ops;
#endif

View File

@ -119,7 +119,7 @@ static int update_config(struct clk_rcg2 *rcg)
}
WARN(1, "%s: rcg didn't update its configuration.", name);
return 0;
return -EBUSY;
}
static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
@ -1105,8 +1105,6 @@ static int clk_rcg2_enable_dfs(const struct clk_rcg_dfs_data *data,
rcg->freq_tbl = NULL;
pr_debug("DFS registered for clk %s\n", init->name);
return 0;
}
@ -1117,12 +1115,8 @@ int qcom_cc_register_rcg_dfs(struct regmap *regmap,
for (i = 0; i < len; i++) {
ret = clk_rcg2_enable_dfs(&rcgs[i], regmap);
if (ret) {
const char *name = rcgs[i].init->name;
pr_err("DFS register failed for clk %s\n", name);
if (ret)
return ret;
}
}
return 0;

View File

@ -85,7 +85,10 @@ static DEFINE_MUTEX(rpmh_clk_lock);
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpmh_ops, \
.name = #_name, \
.parent_names = (const char *[]){ "xo_board" }, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = "xo", \
.name = "xo_board", \
}, \
.num_parents = 1, \
}, \
}; \
@ -100,7 +103,10 @@ static DEFINE_MUTEX(rpmh_clk_lock);
.hw.init = &(struct clk_init_data){ \
.ops = &clk_rpmh_ops, \
.name = #_name_active, \
.parent_names = (const char *[]){ "xo_board" }, \
.parent_data = &(const struct clk_parent_data){ \
.fw_name = "xo", \
.name = "xo_board", \
}, \
.num_parents = 1, \
}, \
}
@ -358,6 +364,33 @@ static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
.num_clks = ARRAY_SIZE(sdm845_rpmh_clocks),
};
DEFINE_CLK_RPMH_ARC(sm8150, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
DEFINE_CLK_RPMH_VRM(sm8150, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk1, rf_clk1_ao, "rfclka1", 1);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk2, rf_clk2_ao, "rfclka2", 1);
DEFINE_CLK_RPMH_VRM(sm8150, rf_clk3, rf_clk3_ao, "rfclka3", 1);
static struct clk_hw *sm8150_rpmh_clocks[] = {
[RPMH_CXO_CLK] = &sm8150_bi_tcxo.hw,
[RPMH_CXO_CLK_A] = &sm8150_bi_tcxo_ao.hw,
[RPMH_LN_BB_CLK2] = &sm8150_ln_bb_clk2.hw,
[RPMH_LN_BB_CLK2_A] = &sm8150_ln_bb_clk2_ao.hw,
[RPMH_LN_BB_CLK3] = &sm8150_ln_bb_clk3.hw,
[RPMH_LN_BB_CLK3_A] = &sm8150_ln_bb_clk3_ao.hw,
[RPMH_RF_CLK1] = &sm8150_rf_clk1.hw,
[RPMH_RF_CLK1_A] = &sm8150_rf_clk1_ao.hw,
[RPMH_RF_CLK2] = &sm8150_rf_clk2.hw,
[RPMH_RF_CLK2_A] = &sm8150_rf_clk2_ao.hw,
[RPMH_RF_CLK3] = &sm8150_rf_clk3.hw,
[RPMH_RF_CLK3_A] = &sm8150_rf_clk3_ao.hw,
};
static const struct clk_rpmh_desc clk_rpmh_sm8150 = {
.clks = sm8150_rpmh_clocks,
.num_clks = ARRAY_SIZE(sm8150_rpmh_clocks),
};
static struct clk_hw *of_clk_rpmh_hw_get(struct of_phandle_args *clkspec,
void *data)
{
@ -386,6 +419,7 @@ static int clk_rpmh_probe(struct platform_device *pdev)
hw_clks = desc->clks;
for (i = 0; i < desc->num_clks; i++) {
const char *name = hw_clks[i]->init->name;
u32 res_addr;
size_t aux_data_len;
const struct bcm_db *data;
@ -416,8 +450,7 @@ static int clk_rpmh_probe(struct platform_device *pdev)
ret = devm_clk_hw_register(&pdev->dev, hw_clks[i]);
if (ret) {
dev_err(&pdev->dev, "failed to register %s\n",
hw_clks[i]->init->name);
dev_err(&pdev->dev, "failed to register %s\n", name);
return ret;
}
}
@ -437,6 +470,7 @@ static int clk_rpmh_probe(struct platform_device *pdev)
static const struct of_device_id clk_rpmh_match_table[] = {
{ .compatible = "qcom,sdm845-rpmh-clk", .data = &clk_rpmh_sdm845},
{ .compatible = "qcom,sm8150-rpmh-clk", .data = &clk_rpmh_sm8150},
{ }
};
MODULE_DEVICE_TABLE(of, clk_rpmh_match_table);

View File

@ -306,4 +306,24 @@ int qcom_cc_probe(struct platform_device *pdev, const struct qcom_cc_desc *desc)
}
EXPORT_SYMBOL_GPL(qcom_cc_probe);
int qcom_cc_probe_by_index(struct platform_device *pdev, int index,
const struct qcom_cc_desc *desc)
{
struct regmap *regmap;
struct resource *res;
void __iomem *base;
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return -ENOMEM;
regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return qcom_cc_really_probe(pdev, desc, regmap);
}
EXPORT_SYMBOL_GPL(qcom_cc_probe_by_index);
MODULE_LICENSE("GPL v2");

View File

@ -61,5 +61,7 @@ extern int qcom_cc_really_probe(struct platform_device *pdev,
struct regmap *regmap);
extern int qcom_cc_probe(struct platform_device *pdev,
const struct qcom_cc_desc *desc);
extern int qcom_cc_probe_by_index(struct platform_device *pdev, int index,
const struct qcom_cc_desc *desc);
#endif

View File

@ -1108,7 +1108,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_xo_gpll0_gpll2_gpll0_out_main_div2,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@ -1042,7 +1042,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_4,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@ -1066,7 +1066,7 @@ static struct clk_rcg2 sdcc4_apps_clk_src = {
.name = "sdcc4_apps_clk_src",
.parent_names = gcc_parent_names_1,
.num_parents = 3,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@ -1057,7 +1057,7 @@ static struct clk_rcg2 sdcc1_apps_clk_src = {
.name = "sdcc1_apps_clk_src",
.parent_names = gcc_parent_names_13,
.num_parents = 5,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@ -1103,7 +1103,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_14,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@ -2604,6 +2604,32 @@ static struct clk_branch gcc_usb_hs_system_clk = {
},
};
static struct clk_branch gcc_wdsp_q6ss_ahbs_clk = {
.halt_reg = 0x1e004,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1e004,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_wdsp_q6ss_ahbs_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_branch gcc_wdsp_q6ss_axim_clk = {
.halt_reg = 0x1e008,
.halt_check = BRANCH_HALT,
.clkr = {
.enable_reg = 0x1e008,
.enable_mask = BIT(0),
.hw.init = &(struct clk_init_data){
.name = "gcc_wdsp_q6ss_axim_clk",
.ops = &clk_branch2_ops,
},
},
};
static struct clk_hw *gcc_qcs404_hws[] = {
&cxo.hw,
};
@ -2749,6 +2775,9 @@ static struct clk_regmap *gcc_qcs404_clocks[] = {
[GCC_QDSS_DAP_CLK] = &gcc_qdss_dap_clk.clkr,
[GCC_DCC_CLK] = &gcc_dcc_clk.clkr,
[GCC_DCC_XO_CLK] = &gcc_dcc_xo_clk.clkr,
[GCC_WCSS_Q6_AHB_CLK] = &gcc_wdsp_q6ss_ahbs_clk.clkr,
[GCC_WCSS_Q6_AXIM_CLK] = &gcc_wdsp_q6ss_axim_clk.clkr,
};
static const struct qcom_reset_map gcc_qcs404_resets[] = {
@ -2774,6 +2803,7 @@ static const struct qcom_reset_map gcc_qcs404_resets[] = {
[GCC_PCIE_0_SLEEP_ARES] = { 0x3e040, 1 },
[GCC_PCIE_0_PIPE_ARES] = { 0x3e040, 0 },
[GCC_EMAC_BCR] = { 0x4e000 },
[GCC_WDSP_RESTART] = {0x19000},
};
static const struct regmap_config gcc_qcs404_regmap_config = {

View File

@ -787,7 +787,7 @@ static struct clk_rcg2 sdcc2_apps_clk_src = {
.name = "sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_xo_gpll0_gpll0_early_div_gpll4,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

View File

@ -685,7 +685,7 @@ static struct clk_rcg2 gcc_sdcc2_apps_clk_src = {
.name = "gcc_sdcc2_apps_clk_src",
.parent_names = gcc_parent_names_10,
.num_parents = 5,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};
@ -709,7 +709,7 @@ static struct clk_rcg2 gcc_sdcc4_apps_clk_src = {
.name = "gcc_sdcc4_apps_clk_src",
.parent_names = gcc_parent_names_0,
.num_parents = 4,
.ops = &clk_rcg2_ops,
.ops = &clk_rcg2_floor_ops,
},
};

File diff suppressed because it is too large Load Diff

View File

@ -112,25 +112,6 @@ static const struct qcom_cc_desc lpass_qdsp6ss_sdm845_desc = {
.num_clks = ARRAY_SIZE(lpass_qdsp6ss_sdm845_clocks),
};
static int lpass_clocks_sdm845_probe(struct platform_device *pdev, int index,
const struct qcom_cc_desc *desc)
{
struct regmap *regmap;
struct resource *res;
void __iomem *base;
res = platform_get_resource(pdev, IORESOURCE_MEM, index);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(&pdev->dev, base, desc->config);
if (IS_ERR(regmap))
return PTR_ERR(regmap);
return qcom_cc_really_probe(pdev, desc, regmap);
}
static int lpass_cc_sdm845_probe(struct platform_device *pdev)
{
const struct qcom_cc_desc *desc;
@ -139,14 +120,14 @@ static int lpass_cc_sdm845_probe(struct platform_device *pdev)
lpass_regmap_config.name = "cc";
desc = &lpass_cc_sdm845_desc;
ret = lpass_clocks_sdm845_probe(pdev, 0, desc);
ret = qcom_cc_probe_by_index(pdev, 0, desc);
if (ret)
return ret;
lpass_regmap_config.name = "qdsp6ss";
desc = &lpass_qdsp6ss_sdm845_desc;
return lpass_clocks_sdm845_probe(pdev, 1, desc);
return qcom_cc_probe_by_index(pdev, 1, desc);
}
static const struct of_device_id lpass_cc_sdm845_match_table[] = {

View File

@ -96,7 +96,7 @@ static const struct regmap_config turingcc_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x30000,
.max_register = 0x23004,
.fast_io = true,
};

View File

@ -334,7 +334,8 @@ void __init cpg_mstp_add_clk_domain(struct device_node *np)
return;
pd->name = np->name;
pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
GENPD_FLAG_ACTIVE_WAKEUP;
pd->attach_dev = cpg_mstp_attach_dev;
pd->detach_dev = cpg_mstp_detach_dev;
pm_genpd_init(pd, &pm_domain_always_on_gov, false);

View File

@ -421,7 +421,8 @@ static int r9a06g032_add_clk_domain(struct device *dev)
return -ENOMEM;
pd->name = np->name;
pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
pd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
GENPD_FLAG_ACTIVE_WAKEUP;
pd->attach_dev = r9a06g032_attach_dev;
pd->detach_dev = r9a06g032_detach_dev;
pm_genpd_init(pd, &pm_domain_always_on_gov, false);

View File

@ -117,7 +117,6 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
struct usb2_clock_sel_priv *priv;
struct resource *res;
struct clk *clk;
struct clk_init_data init;
@ -125,8 +124,7 @@ static int rcar_usb2_clock_sel_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
priv->base = devm_ioremap_resource(dev, res);
priv->base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);

View File

@ -551,7 +551,8 @@ static int __init cpg_mssr_add_clk_domain(struct device *dev,
genpd = &pd->genpd;
genpd->name = np->name;
genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ACTIVE_WAKEUP;
genpd->flags = GENPD_FLAG_PM_CLK | GENPD_FLAG_ALWAYS_ON |
GENPD_FLAG_ACTIVE_WAKEUP;
genpd->attach_dev = cpg_mssr_attach_dev;
genpd->detach_dev = cpg_mssr_detach_dev;
pm_genpd_init(genpd, &pm_domain_always_on_gov, false);

View File

@ -20,6 +20,7 @@ obj-y += clk-rk3128.o
obj-y += clk-rk3188.o
obj-y += clk-rk3228.o
obj-y += clk-rk3288.o
obj-y += clk-rk3308.o
obj-y += clk-rk3328.o
obj-y += clk-rk3368.o
obj-y += clk-rk3399.o

Some files were not shown because too many files have changed in this diff Show More