Commit 6419945e authored by Linus Torvalds's avatar Linus Torvalds

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

Pull clk updates from Stephen Boyd:
 "This time we have a good set of changes to the core framework that do
  some general cleanups, but nothing too major. The majority of the diff
  goes to two SoCs, Actions Semi and Qualcomm. A brand new driver is
  introduced for Actions Semi so it takes up some lines to add all the
  different types, and the Qualcomm diff is there because we add support
  for two SoCs and it's quite a bit of data.

  Otherwise the big driver updates are on TI Davinci and Amlogic
  platforms. And then the long tail of driver updates for various fixes
  and stuff follows after that.

  Core:
   - debugfs cleanups removing error checking and an unused provider API
   - Removal of a clk init typedef that isn't used
   - Usage of match_string() to simplify parent string name matching
   - OF clk helpers moved to their own file (linux/of_clk.h)
   - Make clk warnings more readable across kernel versions

  New Drivers:
   - Qualcomm SDM845 GCC and Video clk controllers
   - Qualcomm MSM8998 GCC
   - Actions Semi S900 SoC support
   - Nuvoton npcm750 microcontroller clks
   - Amlogic axg AO clock controller

  Removed Drivers:
   - Deprecated Rockchip clk-gate driver

  Updates:
   - debugfs functions stopped checking return values
   - Support for the MSIOF module clocks on Rensas R-Car M3-N
   - Support for the new Rensas RZ/G1C and R-Car E3 SoCs
   - Qualcomm GDSC, RCG, and PLL updates for clk changes in new SoCs
   - Berlin and Amlogic SPDX tagging
   - Usage of of_clk_get_parent_count() in more places
   - Proper implementation of the CDEV1/2 clocks on Tegra20
   - Allwinner H6 PRCM clock support and R40 EMAC support
   - Add critical flag to meson8b's fdiv2 as temporary fixup for ethernet
   - Round closest support for meson's mpll driver
   - Support for meson8b nand clocks and gxbb video decoder clocks
   - Mediatek mali clks
   - STM32MP1 fixes
   - Uniphier LD11/LD20 stream demux system clock"

* tag 'clk-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux: (134 commits)
  clk: qcom: Export clk_fabia_pll_configure()
  clk: bcm: Update and add Stingray clock entries
  dt-bindings: clk: Update Stingray binding doc
  clk-si544: Properly round requested frequency to nearest match
  clk: ingenic: jz4770: Add 150us delay after enabling VPU clock
  clk: ingenic: jz4770: Enable power of AHB1 bus after ungating VPU clock
  clk: ingenic: jz4770: Modify C1CLK clock to disable CPU clock stop on idle
  clk: ingenic: jz4770: Change OTG from custom to standard gated clock
  clk: ingenic: Support specifying "wait for clock stable" delay
  clk: ingenic: Add support for clocks whose gate bit is inverted
  clk: use match_string() helper
  clk: bcm2835: use match_string() helper
  clk: Return void from debug_init op
  clk: remove clk_debugfs_add_file()
  clk: tegra: no need to check return value of debugfs_create functions
  clk: davinci: no need to check return value of debugfs_create functions
  clk: bcm2835: no need to check return value of debugfs_create functions
  clk: no need to check return value of debugfs_create functions
  clk: imx6: add EPIT clock support
  clk: mvebu: use correct bit for 98DX3236 NAND
  ...
parents d60dafdc 55913c2d
MediaTek g3dsys controller
============================
The MediaTek g3dsys controller provides various clocks and reset controller to
the GPU.
Required Properties:
- compatible: Should be:
- "mediatek,mt2701-g3dsys", "syscon":
for MT2701 SoC
- "mediatek,mt7623-g3dsys", "mediatek,mt2701-g3dsys", "syscon":
for MT7623 SoC
- #clock-cells: Must be 1
- #reset-cells: Must be 1
The g3dsys 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:
g3dsys: clock-controller@13000000 {
compatible = "mediatek,mt7623-g3dsys",
"mediatek,mt2701-g3dsys",
"syscon";
reg = <0 0x13000000 0 0x200>;
#clock-cells = <1>;
#reset-cells = <1>;
};
* Actions S900 Clock Management Unit (CMU)
The Actions S900 clock management unit generates and supplies clock to various
controllers within the SoC. The clock binding described here is applicable to
S900 SoC.
Required Properties:
- compatible: should be "actions,s900-cmu"
- reg: physical base address of the controller and length of memory mapped
region.
- clocks: Reference to the parent clocks ("hosc", "losc")
- #clock-cells: should be 1.
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
dt-bindings/clock/actions,s900-cmu.h header and can be used in device
tree sources.
External clocks:
The hosc clock used as input for the plls is generated outside the SoC. It is
expected that it is defined using standard clock bindings as "hosc".
Actions S900 CMU also requires one more clock:
- "losc" - internal low frequency oscillator
Example: Clock Management Unit node:
cmu: clock-controller@e0160000 {
compatible = "actions,s900-cmu";
reg = <0x0 0xe0160000 0x0 0x1000>;
clocks = <&hosc>, <&losc>;
#clock-cells = <1>;
};
Example: UART controller node that consumes clock generated by the clock
management unit:
uart: serial@e012a000 {
compatible = "actions,s900-uart", "actions,owl-uart";
reg = <0x0 0xe012a000 0x0 0x2000>;
interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cmu CLK_UART5>;
};
......@@ -9,6 +9,7 @@ Required Properties:
- GXBB (S905) : "amlogic,meson-gxbb-aoclkc"
- GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc"
- GXM (S912) : "amlogic,meson-gxm-aoclkc"
- AXG (A113D, A113X) : "amlogic,meson-axg-aoclkc"
followed by the common "amlogic,meson-gx-aoclkc"
- #clock-cells: should be 1.
......
......@@ -276,36 +276,38 @@ These clock IDs are defined in:
clk_ts_500_ref genpll2 2 BCM_SR_GENPLL2_TS_500_REF_CLK
clk_125_nitro genpll2 3 BCM_SR_GENPLL2_125_NITRO_CLK
clk_chimp genpll2 4 BCM_SR_GENPLL2_CHIMP_CLK
clk_nic_flash genpll2 5 BCM_SR_GENPLL2_NIC_FLASH
clk_nic_flash genpll2 5 BCM_SR_GENPLL2_NIC_FLASH_CLK
clk_fs genpll2 6 BCM_SR_GENPLL2_FS_CLK
genpll3 crystal 0 BCM_SR_GENPLL3
clk_hsls genpll3 1 BCM_SR_GENPLL3_HSLS_CLK
clk_sdio genpll3 2 BCM_SR_GENPLL3_SDIO_CLK
genpll4 crystal 0 BCM_SR_GENPLL4
ccn genpll4 1 BCM_SR_GENPLL4_CCN_CLK
clk_ccn genpll4 1 BCM_SR_GENPLL4_CCN_CLK
clk_tpiu_pll genpll4 2 BCM_SR_GENPLL4_TPIU_PLL_CLK
noc_clk genpll4 3 BCM_SR_GENPLL4_NOC_CLK
clk_noc genpll4 3 BCM_SR_GENPLL4_NOC_CLK
clk_chclk_fs4 genpll4 4 BCM_SR_GENPLL4_CHCLK_FS4_CLK
clk_bridge_fscpu genpll4 5 BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK
genpll5 crystal 0 BCM_SR_GENPLL5
fs4_hf_clk genpll5 1 BCM_SR_GENPLL5_FS4_HF_CLK
crypto_ae_clk genpll5 2 BCM_SR_GENPLL5_CRYPTO_AE_CLK
raid_ae_clk genpll5 3 BCM_SR_GENPLL5_RAID_AE_CLK
clk_fs4_hf genpll5 1 BCM_SR_GENPLL5_FS4_HF_CLK
clk_crypto_ae genpll5 2 BCM_SR_GENPLL5_CRYPTO_AE_CLK
clk_raid_ae genpll5 3 BCM_SR_GENPLL5_RAID_AE_CLK
genpll6 crystal 0 BCM_SR_GENPLL6
48_usb genpll6 1 BCM_SR_GENPLL6_48_USB_CLK
clk_48_usb genpll6 1 BCM_SR_GENPLL6_48_USB_CLK
lcpll0 crystal 0 BCM_SR_LCPLL0
clk_sata_refp lcpll0 1 BCM_SR_LCPLL0_SATA_REFP_CLK
clk_sata_refn lcpll0 2 BCM_SR_LCPLL0_SATA_REFN_CLK
clk_usb_ref lcpll0 3 BCM_SR_LCPLL0_USB_REF_CLK
sata_refpn lcpll0 3 BCM_SR_LCPLL0_SATA_REFPN_CLK
clk_sata_350 lcpll0 3 BCM_SR_LCPLL0_SATA_350_CLK
clk_sata_500 lcpll0 4 BCM_SR_LCPLL0_SATA_500_CLK
lcpll1 crystal 0 BCM_SR_LCPLL1
wan lcpll1 1 BCM_SR_LCPLL0_WAN_CLK
clk_wan lcpll1 1 BCM_SR_LCPLL1_WAN_CLK
clk_usb_ref lcpll1 2 BCM_SR_LCPLL1_USB_REF_CLK
clk_crmu_ts lcpll1 3 BCM_SR_LCPLL1_CRMU_TS_CLK
lcpll_pcie crystal 0 BCM_SR_LCPLL_PCIE
pcie_phy_ref lcpll1 1 BCM_SR_LCPLL_PCIE_PHY_REF_CLK
clk_pcie_phy_ref lcpll1 1 BCM_SR_LCPLL_PCIE_PHY_REF_CLK
* Nuvoton NPCM7XX Clock Controller
Nuvoton Poleg BMC NPCM7XX contains an integrated clock controller, which
generates and supplies clocks to all modules within the BMC.
External clocks:
There are six fixed clocks that are generated outside the BMC. All clocks are of
a known fixed value that cannot be changed. clk_refclk, clk_mcbypck and
clk_sysbypck are inputs to the clock controller.
clk_rg1refck, clk_rg2refck and clk_xin are external clocks suppling the
network. They are set on the device tree, but not used by the clock module. The
network devices use them directly.
Example can be found below.
All available clocks are defined as preprocessor macros in:
dt-bindings/clock/nuvoton,npcm7xx-clock.h
and can be reused as DT sources.
Required Properties of clock controller:
- compatible: "nuvoton,npcm750-clk" : for clock controller of Nuvoton
Poleg BMC NPCM750
- reg: physical base address of the clock controller and length of
memory mapped region.
- #clock-cells: should be 1.
Example: Clock controller node:
clk: clock-controller@f0801000 {
compatible = "nuvoton,npcm750-clk";
#clock-cells = <1>;
reg = <0xf0801000 0x1000>;
clock-names = "refclk", "sysbypck", "mcbypck";
clocks = <&clk_refclk>, <&clk_sysbypck>, <&clk_mcbypck>;
};
Example: Required external clocks for network:
/* external reference clock */
clk_refclk: clk-refclk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <25000000>;
clock-output-names = "refclk";
};
/* external reference clock for cpu. float in normal operation */
clk_sysbypck: clk-sysbypck {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <800000000>;
clock-output-names = "sysbypck";
};
/* external reference clock for MC. float in normal operation */
clk_mcbypck: clk-mcbypck {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <800000000>;
clock-output-names = "mcbypck";
};
/* external clock signal rg1refck, supplied by the phy */
clk_rg1refck: clk-rg1refck {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <125000000>;
clock-output-names = "clk_rg1refck";
};
/* external clock signal rg2refck, supplied by the phy */
clk_rg2refck: clk-rg2refck {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <125000000>;
clock-output-names = "clk_rg2refck";
};
clk_xin: clk-xin {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <50000000>;
clock-output-names = "clk_xin";
};
Example: GMAC controller node that consumes two clocks: a generated clk by the
clock controller and a fixed clock from DT (clk_rg1refck).
ethernet0: ethernet@f0802000 {
compatible = "snps,dwmac";
reg = <0xf0802000 0x2000>;
interrupts = <0 14 4>;
interrupt-names = "macirq";
clocks = <&clk_rg1refck>, <&clk NPCM7XX_CLK_AHB>;
clock-names = "stmmaceth", "clk_gmac";
};
......@@ -17,7 +17,9 @@ Required properties :
"qcom,gcc-msm8974pro-ac"
"qcom,gcc-msm8994"
"qcom,gcc-msm8996"
"qcom,gcc-msm8998"
"qcom,gcc-mdm9615"
"qcom,gcc-sdm845"
- reg : shall contain base register location and length
- #clock-cells : shall contain 1
......
Qualcomm Technologies, Inc. RPMh Clocks
-------------------------------------------------------
Resource Power Manager Hardened (RPMh) manages shared resources on
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"
- #clock-cells : must contain 1
Example :
#include <dt-bindings/clock/qcom,rpmh.h>
&apps_rsc {
rpmhcc: clock-controller {
compatible = "qcom,sdm845-rpmh-clk";
#clock-cells = <1>;
};
};
Qualcomm Video Clock & Reset Controller Binding
-----------------------------------------------
Required properties :
- compatible : shall contain "qcom,sdm845-videocc"
- reg : shall contain base register location and length
- #clock-cells : from common clock binding, shall contain 1.
- #power-domain-cells : from generic power domain binding, shall contain 1.
Optional properties :
- #reset-cells : from common reset binding, shall contain 1.
Example:
videocc: clock-controller@ab00000 {
compatible = "qcom,sdm845-videocc";
reg = <0xab00000 0x10000>;
#clock-cells = <1>;
#power-domain-cells = <1>;
};
......@@ -15,6 +15,7 @@ Required Properties:
- compatible: Must be one of:
- "renesas,r8a7743-cpg-mssr" for the r8a7743 SoC (RZ/G1M)
- "renesas,r8a7745-cpg-mssr" for the r8a7745 SoC (RZ/G1E)
- "renesas,r8a77470-cpg-mssr" for the r8a77470 SoC (RZ/G1C)
- "renesas,r8a7790-cpg-mssr" for the r8a7790 SoC (R-Car H2)
- "renesas,r8a7791-cpg-mssr" for the r8a7791 SoC (R-Car M2-W)
- "renesas,r8a7792-cpg-mssr" for the r8a7792 SoC (R-Car V2H)
......@@ -25,6 +26,7 @@ Required Properties:
- "renesas,r8a77965-cpg-mssr" for the r8a77965 SoC (R-Car M3-N)
- "renesas,r8a77970-cpg-mssr" for the r8a77970 SoC (R-Car V3M)
- "renesas,r8a77980-cpg-mssr" for the r8a77980 SoC (R-Car V3H)
- "renesas,r8a77990-cpg-mssr" for the r8a77990 SoC (R-Car E3)
- "renesas,r8a77995-cpg-mssr" for the r8a77995 SoC (R-Car D3)
- reg: Base address and length of the memory resource used by the CPG/MSSR
......@@ -33,10 +35,12 @@ Required Properties:
- clocks: References to external parent clocks, one entry for each entry in
clock-names
- clock-names: List of external parent clock names. Valid names are:
- "extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7792, r8a7793, r8a7794,
r8a7795, r8a7796, r8a77965, r8a77970, r8a77980, r8a77995)
- "extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7792,
r8a7793, r8a7794, r8a7795, r8a7796, r8a77965, r8a77970,
r8a77980, r8a77990, r8a77995)
- "extalr" (r8a7795, r8a7796, r8a77965, r8a77970, r8a77980)
- "usb_extal" (r8a7743, r8a7745, r8a7790, r8a7791, r8a7793, r8a7794)
- "usb_extal" (r8a7743, r8a7745, r8a77470, r8a7790, r8a7791, r8a7793,
r8a7794)
- #clock-cells: Must be 2
- For CPG core clocks, the two clock specifier cells must be "CPG_CORE"
......
Device Tree Clock bindings for arch-rockchip
This binding uses the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
== Gate clocks ==
These bindings are deprecated!
Please use the soc specific CRU bindings instead.
The gate registers form a continuos block which makes the dt node
structure a matter of taste, as either all gates can be put into
one gate clock spanning all registers or they can be divided into
the 10 individual gates containing 16 clocks each.
The code supports both approaches.
Required properties:
- compatible : "rockchip,rk2928-gate-clk"
- reg : shall be the control register address(es) for the clock.
- #clock-cells : from common clock binding; shall be set to 1
- clock-output-names : the corresponding gate names that the clock controls
- clocks : should contain the parent clock for each individual gate,
therefore the number of clocks elements should match the number of
clock-output-names
Example using multiple gate clocks:
clk_gates0: gate-clk@200000d0 {
compatible = "rockchip,rk2928-gate-clk";
reg = <0x200000d0 0x4>;
clocks = <&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>,
<&dummy>, <&dummy>;
clock-output-names =
"gate_core_periph", "gate_cpu_gpll",
"gate_ddrphy", "gate_aclk_cpu",
"gate_hclk_cpu", "gate_pclk_cpu",
"gate_atclk_cpu", "gate_i2s0",
"gate_i2s0_frac", "gate_i2s1",
"gate_i2s1_frac", "gate_i2s2",
"gate_i2s2_frac", "gate_spdif",
"gate_spdif_frac", "gate_testclk";
#clock-cells = <1>;
};
clk_gates1: gate-clk@200000d4 {
compatible = "rockchip,rk2928-gate-clk";
reg = <0x200000d4 0x4>;
clocks = <&xin24m>, <&xin24m>,
<&xin24m>, <&dummy>,
<&dummy>, <&xin24m>,
<&xin24m>, <&dummy>,
<&xin24m>, <&dummy>,
<&xin24m>, <&dummy>,
<&xin24m>, <&dummy>,
<&xin24m>, <&dummy>;
clock-output-names =
"gate_timer0", "gate_timer1",
"gate_timer2", "gate_jtag",
"gate_aclk_lcdc1_src", "gate_otgphy0",
"gate_otgphy1", "gate_ddr_gpll",
"gate_uart0", "gate_frac_uart0",
"gate_uart1", "gate_frac_uart1",
"gate_uart2", "gate_frac_uart2",
"gate_uart3", "gate_frac_uart3";
#clock-cells = <1>;
};
......@@ -21,6 +21,7 @@ Required properties :
- "allwinner,sun50i-a64-r-ccu"
- "allwinner,sun50i-h5-ccu"
- "allwinner,sun50i-h6-ccu"
- "allwinner,sun50i-h6-r-ccu"
- "nextthing,gr8-ccu"
- reg: Must contain the registers base address and length
......@@ -35,7 +36,7 @@ Required properties :
For the main CCU on H6, one more clock is needed:
- "iosc": the SoC's internal frequency oscillator
For the PRCM CCUs on A83T/H3/A64, two more clocks are needed:
For the PRCM CCUs on A83T/H3/A64/H6, two more clocks are needed:
- "pll-periph": the SoC's peripheral PLL from the main CCU
- "iosc": the SoC's internal frequency oscillator
......
......@@ -96,7 +96,7 @@ the operations defined in clk-provider.h::
int (*get_phase)(struct clk_hw *hw);
int (*set_phase)(struct clk_hw *hw, int degrees);
void (*init)(struct clk_hw *hw);
int (*debug_init)(struct clk_hw *hw,
void (*debug_init)(struct clk_hw *hw,
struct dentry *dentry);
};
......
......@@ -3587,6 +3587,7 @@ F: drivers/clk/
X: drivers/clk/clkdev.c
F: include/linux/clk-pr*
F: include/linux/clk/
F: include/linux/of_clk.h
COMMON INTERNET FILE SYSTEM (CIFS)
M: Steve French <sfrench@samba.org>
......
......@@ -120,7 +120,7 @@ fec2: ethernet@30bf0000 {
<GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
clocks = <&clks IMX7D_ENET2_IPG_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET2_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,
......
......@@ -1092,7 +1092,7 @@ fec1: ethernet@30be0000 {
<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_ENET_AXI_ROOT_CLK>,
clocks = <&clks IMX7D_ENET1_IPG_ROOT_CLK>,
<&clks IMX7D_ENET_AXI_ROOT_CLK>,
<&clks IMX7D_ENET1_TIME_ROOT_CLK>,
<&clks IMX7D_PLL_ENET_MAIN_125M_CLK>,
......
......@@ -277,6 +277,7 @@ config COMMON_CLK_STM32H7
---help---
Support for stm32h7 SoC family clocks
source "drivers/clk/actions/Kconfig"
source "drivers/clk/bcm/Kconfig"
source "drivers/clk/hisilicon/Kconfig"
source "drivers/clk/imgtec/Kconfig"
......
......@@ -33,6 +33,7 @@ obj-$(CONFIG_CLK_HSDK) += clk-hsdk-pll.o
obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
obj-$(CONFIG_ARCH_MOXART) += clk-moxart.o
obj-$(CONFIG_ARCH_NOMADIK) += clk-nomadik.o
obj-$(CONFIG_ARCH_NPCM7XX) += clk-npcm7xx.o
obj-$(CONFIG_ARCH_NSPIRE) += clk-nspire.o
obj-$(CONFIG_COMMON_CLK_OXNAS) += clk-oxnas.o
obj-$(CONFIG_COMMON_CLK_PALMAS) += clk-palmas.o
......@@ -59,6 +60,7 @@ obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o
# please keep this section sorted lexicographically by directory path name
obj-y += actions/
obj-$(CONFIG_COMMON_CLK_AT91) += at91/
obj-$(CONFIG_ARCH_ARTPEC) += axis/
obj-$(CONFIG_ARC_PLAT_AXS10X) += axs10x/
......
config CLK_ACTIONS
bool "Clock driver for Actions Semi SoCs"
depends on ARCH_ACTIONS || COMPILE_TEST
default ARCH_ACTIONS
if CLK_ACTIONS
# SoC Drivers
config CLK_OWL_S900
bool "Support for the Actions Semi OWL S900 clocks"
depends on (ARM64 && ARCH_ACTIONS) || COMPILE_TEST
default ARM64 && ARCH_ACTIONS
endif
obj-$(CONFIG_CLK_ACTIONS) += clk-owl.o
clk-owl-y += owl-common.o
clk-owl-y += owl-gate.o
clk-owl-y += owl-mux.o
clk-owl-y += owl-divider.o
clk-owl-y += owl-factor.o
clk-owl-y += owl-composite.o
clk-owl-y += owl-pll.o
# SoC support
obj-$(CONFIG_CLK_OWL_S900) += owl-s900.o
// SPDX-License-Identifier: GPL-2.0+
//
// OWL common clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/of_address.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include "owl-common.h"
static const struct regmap_config owl_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = 0x00cc,
.fast_io = true,
};
static void owl_clk_set_regmap(const struct owl_clk_desc *desc,
struct regmap *regmap)
{
int i;
struct owl_clk_common *clks;
for (i = 0; i < desc->num_clks; i++) {
clks = desc->clks[i];
if (!clks)
continue;
clks->regmap = regmap;
}
}
int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc)
{
void __iomem *base;
struct regmap *regmap;
struct resource *res;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
base = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
regmap = devm_regmap_init_mmio(&pdev->dev, base, &owl_regmap_config);
if (IS_ERR(regmap)) {
pr_err("failed to init regmap\n");
return PTR_ERR(regmap);
}
owl_clk_set_regmap(desc, regmap);
return 0;
}
int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks)
{
int i, ret;
struct clk_hw *hw;
for (i = 0; i < hw_clks->num; i++) {
hw = hw_clks->hws[i];
if (IS_ERR_OR_NULL(hw))
continue;
ret = devm_clk_hw_register(dev, hw);
if (ret) {
dev_err(dev, "Couldn't register clock %d - %s\n",
i, hw->init->name);
return ret;
}
}
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_clks);
if (ret)
dev_err(dev, "Failed to add clock provider\n");
return ret;
}
// SPDX-License-Identifier: GPL-2.0+
//
// OWL common clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_COMMON_H_
#define _OWL_COMMON_H_
#include <linux/clk-provider.h>
#include <linux/of_platform.h>
#include <linux/regmap.h>
struct device_node;
struct owl_clk_common {
struct regmap *regmap;
struct clk_hw hw;
};
struct owl_clk_desc {
struct owl_clk_common **clks;
unsigned long num_clks;
struct clk_hw_onecell_data *hw_clks;
};
static inline struct owl_clk_common *
hw_to_owl_clk_common(const struct clk_hw *hw)
{
return container_of(hw, struct owl_clk_common, hw);
}
int owl_clk_regmap_init(struct platform_device *pdev,
const struct owl_clk_desc *desc);
int owl_clk_probe(struct device *dev, struct clk_hw_onecell_data *hw_clks);
#endif /* _OWL_COMMON_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL composite clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "owl-composite.h"
static u8 owl_comp_get_parent(struct clk_hw *hw)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_mux_helper_get_parent(&comp->common, &comp->mux_hw);
}
static int owl_comp_set_parent(struct clk_hw *hw, u8 index)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_mux_helper_set_parent(&comp->common, &comp->mux_hw, index);
}
static void owl_comp_disable(struct clk_hw *hw)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct owl_clk_common *common = &comp->common;
owl_gate_set(common, &comp->gate_hw, false);
}
static int owl_comp_enable(struct clk_hw *hw)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct owl_clk_common *common = &comp->common;
owl_gate_set(common, &comp->gate_hw, true);
return 0;
}
static int owl_comp_is_enabled(struct clk_hw *hw)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct owl_clk_common *common = &comp->common;
return owl_gate_clk_is_enabled(common, &comp->gate_hw);
}
static long owl_comp_div_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_divider_helper_round_rate(&comp->common, &comp->rate.div_hw,
rate, parent_rate);
}
static unsigned long owl_comp_div_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_divider_helper_recalc_rate(&comp->common, &comp->rate.div_hw,
parent_rate);
}
static int owl_comp_div_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_divider_helper_set_rate(&comp->common, &comp->rate.div_hw,
rate, parent_rate);
}
static long owl_comp_fact_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_factor_helper_round_rate(&comp->common,
&comp->rate.factor_hw,
rate, parent_rate);
}
static unsigned long owl_comp_fact_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_factor_helper_recalc_rate(&comp->common,
&comp->rate.factor_hw,
parent_rate);
}
static int owl_comp_fact_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
return owl_factor_helper_set_rate(&comp->common,
&comp->rate.factor_hw,
rate, parent_rate);
}
static long owl_comp_fix_fact_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
return comp->fix_fact_ops->round_rate(&fix_fact_hw->hw, rate, parent_rate);
}
static unsigned long owl_comp_fix_fact_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_composite *comp = hw_to_owl_comp(hw);
struct clk_fixed_factor *fix_fact_hw = &comp->rate.fix_fact_hw;
return comp->fix_fact_ops->recalc_rate(&fix_fact_hw->hw, parent_rate);
}
static int owl_comp_fix_fact_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
/*
* We must report success but we can do so unconditionally because
* owl_comp_fix_fact_round_rate returns values that ensure this call is
* a nop.
*/
return 0;
}
const struct clk_ops owl_comp_div_ops = {
/* mux_ops */
.get_parent = owl_comp_get_parent,
.set_parent = owl_comp_set_parent,
/* gate_ops */
.disable = owl_comp_disable,
.enable = owl_comp_enable,
.is_enabled = owl_comp_is_enabled,
/* div_ops */
.round_rate = owl_comp_div_round_rate,
.recalc_rate = owl_comp_div_recalc_rate,
.set_rate = owl_comp_div_set_rate,
};
const struct clk_ops owl_comp_fact_ops = {
/* mux_ops */
.get_parent = owl_comp_get_parent,
.set_parent = owl_comp_set_parent,
/* gate_ops */
.disable = owl_comp_disable,
.enable = owl_comp_enable,
.is_enabled = owl_comp_is_enabled,
/* fact_ops */
.round_rate = owl_comp_fact_round_rate,
.recalc_rate = owl_comp_fact_recalc_rate,
.set_rate = owl_comp_fact_set_rate,
};
const struct clk_ops owl_comp_fix_fact_ops = {
/* gate_ops */
.disable = owl_comp_disable,
.enable = owl_comp_enable,
.is_enabled = owl_comp_is_enabled,
/* fix_fact_ops */
.round_rate = owl_comp_fix_fact_round_rate,
.recalc_rate = owl_comp_fix_fact_recalc_rate,
.set_rate = owl_comp_fix_fact_set_rate,
};
const struct clk_ops owl_comp_pass_ops = {
/* mux_ops */
.get_parent = owl_comp_get_parent,
.set_parent = owl_comp_set_parent,
/* gate_ops */
.disable = owl_comp_disable,
.enable = owl_comp_enable,
.is_enabled = owl_comp_is_enabled,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL composite clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_COMPOSITE_H_
#define _OWL_COMPOSITE_H_
#include "owl-common.h"
#include "owl-mux.h"
#include "owl-gate.h"
#include "owl-factor.h"
#include "owl-fixed-factor.h"
#include "owl-divider.h"
union owl_rate {
struct owl_divider_hw div_hw;
struct owl_factor_hw factor_hw;
struct clk_fixed_factor fix_fact_hw;
};
struct owl_composite {
struct owl_mux_hw mux_hw;
struct owl_gate_hw gate_hw;
union owl_rate rate;
const struct clk_ops *fix_fact_ops;
struct owl_clk_common common;
};
#define OWL_COMP_DIV(_struct, _name, _parent, \
_mux, _gate, _div, _flags) \
struct owl_composite _struct = { \
.mux_hw = _mux, \
.gate_hw = _gate, \
.rate.div_hw = _div, \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parent, \
&owl_comp_div_ops,\
_flags), \
}, \
}
#define OWL_COMP_DIV_FIXED(_struct, _name, _parent, \
_gate, _div, _flags) \
struct owl_composite _struct = { \
.gate_hw = _gate, \
.rate.div_hw = _div, \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_comp_div_ops,\
_flags), \
}, \
}
#define OWL_COMP_FACTOR(_struct, _name, _parent, \
_mux, _gate, _factor, _flags) \
struct owl_composite _struct = { \
.mux_hw = _mux, \
.gate_hw = _gate, \
.rate.factor_hw = _factor, \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parent, \
&owl_comp_fact_ops,\
_flags), \
}, \
}
#define OWL_COMP_FIXED_FACTOR(_struct, _name, _parent, \
_gate, _mul, _div, _flags) \
struct owl_composite _struct = { \
.gate_hw = _gate, \
.rate.fix_fact_hw.mult = _mul, \
.rate.fix_fact_hw.div = _div, \
.fix_fact_ops = &clk_fixed_factor_ops, \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_comp_fix_fact_ops,\
_flags), \
}, \
}
#define OWL_COMP_PASS(_struct, _name, _parent, \
_mux, _gate, _flags) \
struct owl_composite _struct = { \
.mux_hw = _mux, \
.gate_hw = _gate, \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parent, \
&owl_comp_pass_ops,\
_flags), \
}, \
}
static inline struct owl_composite *hw_to_owl_comp(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_composite, common);
}
extern const struct clk_ops owl_comp_div_ops;
extern const struct clk_ops owl_comp_fact_ops;
extern const struct clk_ops owl_comp_fix_fact_ops;
extern const struct clk_ops owl_comp_pass_ops;
extern const struct clk_ops clk_fixed_factor_ops;
#endif /* _OWL_COMPOSITE_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL divider clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "owl-divider.h"
long owl_divider_helper_round_rate(struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long rate,
unsigned long *parent_rate)
{
return divider_round_rate(&common->hw, rate, parent_rate,
div_hw->table, div_hw->width,
div_hw->div_flags);
}
static long owl_divider_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_divider *div = hw_to_owl_divider(hw);
return owl_divider_helper_round_rate(&div->common, &div->div_hw,
rate, parent_rate);
}
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long parent_rate)
{
unsigned long val;
unsigned int reg;
regmap_read(common->regmap, div_hw->reg, &reg);
val = reg >> div_hw->shift;
val &= (1 << div_hw->width) - 1;
return divider_recalc_rate(&common->hw, parent_rate,
val, div_hw->table,
div_hw->div_flags,
div_hw->width);
}
static unsigned long owl_divider_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_divider *div = hw_to_owl_divider(hw);
return owl_divider_helper_recalc_rate(&div->common,
&div->div_hw, parent_rate);
}
int owl_divider_helper_set_rate(const struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long rate,
unsigned long parent_rate)
{
unsigned long val;
unsigned int reg;
val = divider_get_val(rate, parent_rate, div_hw->table,
div_hw->width, 0);
regmap_read(common->regmap, div_hw->reg, &reg);
reg &= ~GENMASK(div_hw->width + div_hw->shift - 1, div_hw->shift);
regmap_write(common->regmap, div_hw->reg,
reg | (val << div_hw->shift));
return 0;
}
static int owl_divider_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct owl_divider *div = hw_to_owl_divider(hw);
return owl_divider_helper_set_rate(&div->common, &div->div_hw,
rate, parent_rate);
}
const struct clk_ops owl_divider_ops = {
.recalc_rate = owl_divider_recalc_rate,
.round_rate = owl_divider_round_rate,
.set_rate = owl_divider_set_rate,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL divider clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_DIVIDER_H_
#define _OWL_DIVIDER_H_
#include "owl-common.h"
struct owl_divider_hw {
u32 reg;
u8 shift;
u8 width;
u8 div_flags;
struct clk_div_table *table;
};
struct owl_divider {
struct owl_divider_hw div_hw;
struct owl_clk_common common;
};
#define OWL_DIVIDER_HW(_reg, _shift, _width, _div_flags, _table) \
{ \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.div_flags = _div_flags, \
.table = _table, \
}
#define OWL_DIVIDER(_struct, _name, _parent, _reg, \
_shift, _width, _table, _div_flags, _flags) \
struct owl_divider _struct = { \
.div_hw = OWL_DIVIDER_HW(_reg, _shift, _width, \
_div_flags, _table), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_divider_ops, \
_flags), \
}, \
}
static inline struct owl_divider *hw_to_owl_divider(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_divider, common);
}
long owl_divider_helper_round_rate(struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long rate,
unsigned long *parent_rate);
unsigned long owl_divider_helper_recalc_rate(struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long parent_rate);
int owl_divider_helper_set_rate(const struct owl_clk_common *common,
const struct owl_divider_hw *div_hw,
unsigned long rate,
unsigned long parent_rate);
extern const struct clk_ops owl_divider_ops;
#endif /* _OWL_DIVIDER_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL factor clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include "owl-factor.h"
static unsigned int _get_table_maxval(const struct clk_factor_table *table)
{
unsigned int maxval = 0;
const struct clk_factor_table *clkt;
for (clkt = table; clkt->div; clkt++)
if (clkt->val > maxval)
maxval = clkt->val;
return maxval;
}
static int _get_table_div_mul(const struct clk_factor_table *table,
unsigned int val, unsigned int *mul, unsigned int *div)
{
const struct clk_factor_table *clkt;
for (clkt = table; clkt->div; clkt++) {
if (clkt->val == val) {
*mul = clkt->mul;
*div = clkt->div;
return 1;
}
}
return 0;
}
static unsigned int _get_table_val(const struct clk_factor_table *table,
unsigned long rate, unsigned long parent_rate)
{
const struct clk_factor_table *clkt;
int val = -1;
u64 calc_rate;
for (clkt = table; clkt->div; clkt++) {
calc_rate = parent_rate * clkt->mul;
do_div(calc_rate, clkt->div);
if ((unsigned long)calc_rate <= rate) {
val = clkt->val;
break;
}
}
if (val == -1)
val = _get_table_maxval(table);
return val;
}
static int clk_val_best(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;
int bestval = 0;
if (!rate)
rate = 1;
if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
parent_rate = *best_parent_rate;
bestval = _get_table_val(clkt, rate, parent_rate);
return bestval;
}
for (clkt = factor_hw->table; clkt->div; clkt++) {
try_parent_rate = rate * clkt->div / clkt->mul;
if (try_parent_rate == parent_rate_saved) {
pr_debug("%s: [%d %d %d] found try_parent_rate %ld\n",
__func__, clkt->val, clkt->mul, clkt->div,
try_parent_rate);
/*
* It's the most ideal case if the requested rate can be
* divided from parent clock without any need to change
* parent rate, so return the divider immediately.
*/
*best_parent_rate = parent_rate_saved;
return clkt->val;
}
parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
try_parent_rate);
cur_rate = DIV_ROUND_UP(parent_rate, clkt->div) * clkt->mul;
if (cur_rate <= rate && cur_rate > best) {
bestval = clkt->val;
best = cur_rate;
*best_parent_rate = parent_rate;
}
}
if (!bestval) {
bestval = _get_table_maxval(clkt);
*best_parent_rate = clk_hw_round_rate(
clk_hw_get_parent(hw), 1);
}
return bestval;
}
long owl_factor_helper_round_rate(struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long rate,
unsigned long *parent_rate)
{
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);
_get_table_div_mul(clkt, val, &mul, &div);
return *parent_rate * mul / div;
}
static long owl_factor_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
return owl_factor_helper_round_rate(&factor->common, factor_hw,
rate, parent_rate);
}
unsigned long owl_factor_helper_recalc_rate(struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long parent_rate)
{
const struct clk_factor_table *clkt = factor_hw->table;
unsigned long long int rate;
u32 reg, val, mul, div;
div = 0;
mul = 0;
regmap_read(common->regmap, factor_hw->reg, &reg);
val = reg >> factor_hw->shift;
val &= div_mask(factor_hw);
_get_table_div_mul(clkt, val, &mul, &div);
if (!div) {
WARN(!(factor_hw->fct_flags & CLK_DIVIDER_ALLOW_ZERO),
"%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
__clk_get_name(common->hw.clk));
return parent_rate;
}
rate = (unsigned long long int)parent_rate * mul;
do_div(rate, div);
return rate;
}
static unsigned long owl_factor_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
struct owl_clk_common *common = &factor->common;
return owl_factor_helper_recalc_rate(common, factor_hw, parent_rate);
}
int owl_factor_helper_set_rate(const struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long rate,
unsigned long parent_rate)
{
u32 val, reg;
val = _get_table_val(factor_hw->table, rate, parent_rate);
if (val > div_mask(factor_hw))
val = div_mask(factor_hw);
regmap_read(common->regmap, factor_hw->reg, &reg);
reg &= ~(div_mask(factor_hw) << factor_hw->shift);
reg |= val << factor_hw->shift;
regmap_write(common->regmap, factor_hw->reg, reg);
return 0;
}
static int owl_factor_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct owl_factor *factor = hw_to_owl_factor(hw);
struct owl_factor_hw *factor_hw = &factor->factor_hw;
struct owl_clk_common *common = &factor->common;
return owl_factor_helper_set_rate(common, factor_hw,
rate, parent_rate);
}
const struct clk_ops owl_factor_ops = {
.round_rate = owl_factor_round_rate,
.recalc_rate = owl_factor_recalc_rate,
.set_rate = owl_factor_set_rate,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL factor clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_FACTOR_H_
#define _OWL_FACTOR_H_
#include "owl-common.h"
struct clk_factor_table {
unsigned int val;
unsigned int mul;
unsigned int div;
};
struct owl_factor_hw {
u32 reg;
u8 shift;
u8 width;
u8 fct_flags;
struct clk_factor_table *table;
};
struct owl_factor {
struct owl_factor_hw factor_hw;
struct owl_clk_common common;
};
#define OWL_FACTOR_HW(_reg, _shift, _width, _fct_flags, _table) \
{ \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
.fct_flags = _fct_flags, \
.table = _table, \
}
#define OWL_FACTOR(_struct, _name, _parent, _reg, \
_shift, _width, _table, _fct_flags, _flags) \
struct owl_factor _struct = { \
.factor_hw = OWL_FACTOR_HW(_reg, _shift, \
_width, _fct_flags, _table), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_factor_ops, \
_flags), \
}, \
}
#define div_mask(d) ((1 << ((d)->width)) - 1)
static inline struct owl_factor *hw_to_owl_factor(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_factor, common);
}
long owl_factor_helper_round_rate(struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long rate,
unsigned long *parent_rate);
unsigned long owl_factor_helper_recalc_rate(struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long parent_rate);
int owl_factor_helper_set_rate(const struct owl_clk_common *common,
const struct owl_factor_hw *factor_hw,
unsigned long rate,
unsigned long parent_rate);
extern const struct clk_ops owl_factor_ops;
#endif /* _OWL_FACTOR_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL fixed factor clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_FIXED_FACTOR_H_
#define _OWL_FIXED_FACTOR_H_
#include "owl-common.h"
#define OWL_FIX_FACT(_struct, _name, _parent, _mul, _div, _flags) \
struct clk_fixed_factor _struct = { \
.mult = _mul, \
.div = _div, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&clk_fixed_factor_ops, \
_flags), \
}
extern const struct clk_ops clk_fixed_factor_ops;
#endif /* _OWL_FIXED_FACTOR_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL gate clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "owl-gate.h"
void owl_gate_set(const struct owl_clk_common *common,
const struct owl_gate_hw *gate_hw, bool enable)
{
int set = gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
u32 reg;
set ^= enable;
regmap_read(common->regmap, gate_hw->reg, &reg);
if (set)
reg |= BIT(gate_hw->bit_idx);
else
reg &= ~BIT(gate_hw->bit_idx);
regmap_write(common->regmap, gate_hw->reg, reg);
}
static void owl_gate_disable(struct clk_hw *hw)
{
struct owl_gate *gate = hw_to_owl_gate(hw);
struct owl_clk_common *common = &gate->common;
owl_gate_set(common, &gate->gate_hw, false);
}
static int owl_gate_enable(struct clk_hw *hw)
{
struct owl_gate *gate = hw_to_owl_gate(hw);
struct owl_clk_common *common = &gate->common;
owl_gate_set(common, &gate->gate_hw, true);
return 0;
}
int owl_gate_clk_is_enabled(const struct owl_clk_common *common,
const struct owl_gate_hw *gate_hw)
{
u32 reg;
regmap_read(common->regmap, gate_hw->reg, &reg);
if (gate_hw->gate_flags & CLK_GATE_SET_TO_DISABLE)
reg ^= BIT(gate_hw->bit_idx);
return !!(reg & BIT(gate_hw->bit_idx));
}
static int owl_gate_is_enabled(struct clk_hw *hw)
{
struct owl_gate *gate = hw_to_owl_gate(hw);
struct owl_clk_common *common = &gate->common;
return owl_gate_clk_is_enabled(common, &gate->gate_hw);
}
const struct clk_ops owl_gate_ops = {
.disable = owl_gate_disable,
.enable = owl_gate_enable,
.is_enabled = owl_gate_is_enabled,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL gate clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_GATE_H_
#define _OWL_GATE_H_
#include "owl-common.h"
struct owl_gate_hw {
u32 reg;
u8 bit_idx;
u8 gate_flags;
};
struct owl_gate {
struct owl_gate_hw gate_hw;
struct owl_clk_common common;
};
#define OWL_GATE_HW(_reg, _bit_idx, _gate_flags) \
{ \
.reg = _reg, \
.bit_idx = _bit_idx, \
.gate_flags = _gate_flags, \
}
#define OWL_GATE(_struct, _name, _parent, _reg, \
_bit_idx, _gate_flags, _flags) \
struct owl_gate _struct = { \
.gate_hw = OWL_GATE_HW(_reg, _bit_idx, _gate_flags), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_gate_ops, \
_flags), \
} \
} \
#define OWL_GATE_NO_PARENT(_struct, _name, _reg, \
_bit_idx, _gate_flags, _flags) \
struct owl_gate _struct = { \
.gate_hw = OWL_GATE_HW(_reg, _bit_idx, _gate_flags), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_NO_PARENT(_name, \
&owl_gate_ops, \
_flags), \
}, \
} \
static inline struct owl_gate *hw_to_owl_gate(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_gate, common);
}
void owl_gate_set(const struct owl_clk_common *common,
const struct owl_gate_hw *gate_hw, bool enable);
int owl_gate_clk_is_enabled(const struct owl_clk_common *common,
const struct owl_gate_hw *gate_hw);
extern const struct clk_ops owl_gate_ops;
#endif /* _OWL_GATE_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL mux clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/regmap.h>
#include "owl-mux.h"
u8 owl_mux_helper_get_parent(const struct owl_clk_common *common,
const struct owl_mux_hw *mux_hw)
{
u32 reg;
u8 parent;
regmap_read(common->regmap, mux_hw->reg, &reg);
parent = reg >> mux_hw->shift;
parent &= BIT(mux_hw->width) - 1;
return parent;
}
static u8 owl_mux_get_parent(struct clk_hw *hw)
{
struct owl_mux *mux = hw_to_owl_mux(hw);
return owl_mux_helper_get_parent(&mux->common, &mux->mux_hw);
}
int owl_mux_helper_set_parent(const struct owl_clk_common *common,
struct owl_mux_hw *mux_hw, u8 index)
{
u32 reg;
regmap_read(common->regmap, mux_hw->reg, &reg);
reg &= ~GENMASK(mux_hw->width + mux_hw->shift - 1, mux_hw->shift);
regmap_write(common->regmap, mux_hw->reg,
reg | (index << mux_hw->shift));
return 0;
}
static int owl_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct owl_mux *mux = hw_to_owl_mux(hw);
return owl_mux_helper_set_parent(&mux->common, &mux->mux_hw, index);
}
const struct clk_ops owl_mux_ops = {
.get_parent = owl_mux_get_parent,
.set_parent = owl_mux_set_parent,
.determine_rate = __clk_mux_determine_rate,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL mux clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_MUX_H_
#define _OWL_MUX_H_
#include "owl-common.h"
struct owl_mux_hw {
u32 reg;
u8 shift;
u8 width;
};
struct owl_mux {
struct owl_mux_hw mux_hw;
struct owl_clk_common common;
};
#define OWL_MUX_HW(_reg, _shift, _width) \
{ \
.reg = _reg, \
.shift = _shift, \
.width = _width, \
}
#define OWL_MUX(_struct, _name, _parents, _reg, \
_shift, _width, _flags) \
struct owl_mux _struct = { \
.mux_hw = OWL_MUX_HW(_reg, _shift, _width), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_PARENTS(_name, \
_parents, \
&owl_mux_ops, \
_flags), \
}, \
}
static inline struct owl_mux *hw_to_owl_mux(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_mux, common);
}
u8 owl_mux_helper_get_parent(const struct owl_clk_common *common,
const struct owl_mux_hw *mux_hw);
int owl_mux_helper_set_parent(const struct owl_clk_common *common,
struct owl_mux_hw *mux_hw, u8 index);
extern const struct clk_ops owl_mux_ops;
#endif /* _OWL_MUX_H_ */
// SPDX-License-Identifier: GPL-2.0+
//
// OWL pll clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#include <linux/clk-provider.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/delay.h>
#include "owl-pll.h"
static u32 owl_pll_calculate_mul(struct owl_pll_hw *pll_hw, unsigned long rate)
{
u32 mul;
mul = DIV_ROUND_CLOSEST(rate, pll_hw->bfreq);
if (mul < pll_hw->min_mul)
mul = pll_hw->min_mul;
else if (mul > pll_hw->max_mul)
mul = pll_hw->max_mul;
return mul &= mul_mask(pll_hw);
}
static unsigned long _get_table_rate(const struct clk_pll_table *table,
unsigned int val)
{
const struct clk_pll_table *clkt;
for (clkt = table; clkt->rate; clkt++)
if (clkt->val == val)
return clkt->rate;
return 0;
}
static const struct clk_pll_table *_get_pll_table(
const struct clk_pll_table *table, unsigned long rate)
{
const struct clk_pll_table *clkt;
for (clkt = table; clkt->rate; clkt++) {
if (clkt->rate == rate) {
table = clkt;
break;
} else if (clkt->rate < rate)
table = clkt;
}
return table;
}
static long owl_pll_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *parent_rate)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
struct owl_pll_hw *pll_hw = &pll->pll_hw;
const struct clk_pll_table *clkt;
u32 mul;
if (pll_hw->table) {
clkt = _get_pll_table(pll_hw->table, rate);
return clkt->rate;
}
/* fixed frequency */
if (pll_hw->width == 0)
return pll_hw->bfreq;
mul = owl_pll_calculate_mul(pll_hw, rate);
return pll_hw->bfreq * mul;
}
static unsigned long owl_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
struct owl_pll_hw *pll_hw = &pll->pll_hw;
const struct owl_clk_common *common = &pll->common;
u32 val;
if (pll_hw->table) {
regmap_read(common->regmap, pll_hw->reg, &val);
val = val >> pll_hw->shift;
val &= mul_mask(pll_hw);
return _get_table_rate(pll_hw->table, val);
}
/* fixed frequency */
if (pll_hw->width == 0)
return pll_hw->bfreq;
regmap_read(common->regmap, pll_hw->reg, &val);
val = val >> pll_hw->shift;
val &= mul_mask(pll_hw);
return pll_hw->bfreq * val;
}
static int owl_pll_is_enabled(struct clk_hw *hw)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
struct owl_pll_hw *pll_hw = &pll->pll_hw;
const struct owl_clk_common *common = &pll->common;
u32 reg;
regmap_read(common->regmap, pll_hw->reg, &reg);
return !!(reg & BIT(pll_hw->bit_idx));
}
static void owl_pll_set(const struct owl_clk_common *common,
const struct owl_pll_hw *pll_hw, bool enable)
{
u32 reg;
regmap_read(common->regmap, pll_hw->reg, &reg);
if (enable)
reg |= BIT(pll_hw->bit_idx);
else
reg &= ~BIT(pll_hw->bit_idx);
regmap_write(common->regmap, pll_hw->reg, reg);
}
static int owl_pll_enable(struct clk_hw *hw)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
const struct owl_clk_common *common = &pll->common;
owl_pll_set(common, &pll->pll_hw, true);
return 0;
}
static void owl_pll_disable(struct clk_hw *hw)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
const struct owl_clk_common *common = &pll->common;
owl_pll_set(common, &pll->pll_hw, false);
}
static int owl_pll_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct owl_pll *pll = hw_to_owl_pll(hw);
struct owl_pll_hw *pll_hw = &pll->pll_hw;
const struct owl_clk_common *common = &pll->common;
const struct clk_pll_table *clkt;
u32 val, reg;
/* fixed frequency */
if (pll_hw->width == 0)
return 0;
if (pll_hw->table) {
clkt = _get_pll_table(pll_hw->table, rate);
val = clkt->val;
} else {
val = owl_pll_calculate_mul(pll_hw, rate);
}
regmap_read(common->regmap, pll_hw->reg, &reg);
reg &= ~mul_mask(pll_hw);
reg |= val << pll_hw->shift;
regmap_write(common->regmap, pll_hw->reg, reg);
udelay(PLL_STABILITY_WAIT_US);
return 0;
}
const struct clk_ops owl_pll_ops = {
.enable = owl_pll_enable,
.disable = owl_pll_disable,
.is_enabled = owl_pll_is_enabled,
.round_rate = owl_pll_round_rate,
.recalc_rate = owl_pll_recalc_rate,
.set_rate = owl_pll_set_rate,
};
// SPDX-License-Identifier: GPL-2.0+
//
// OWL pll clock driver
//
// Copyright (c) 2014 Actions Semi Inc.
// Author: David Liu <liuwei@actions-semi.com>
//
// Copyright (c) 2018 Linaro Ltd.
// Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
#ifndef _OWL_PLL_H_
#define _OWL_PLL_H_
#include "owl-common.h"
/* last entry should have rate = 0 */
struct clk_pll_table {
unsigned int val;
unsigned long rate;
};
struct owl_pll_hw {
u32 reg;
u32 bfreq;
u8 bit_idx;
u8 shift;
u8 width;
u8 min_mul;
u8 max_mul;
const struct clk_pll_table *table;
};
struct owl_pll {
struct owl_pll_hw pll_hw;
struct owl_clk_common common;
};
#define OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift, \
_width, _min_mul, _max_mul, _table) \
{ \
.reg = _reg, \
.bfreq = _bfreq, \
.bit_idx = _bit_idx, \
.shift = _shift, \
.width = _width, \
.min_mul = _min_mul, \
.max_mul = _max_mul, \
.table = _table, \
}
#define OWL_PLL(_struct, _name, _parent, _reg, _bfreq, _bit_idx, \
_shift, _width, _min_mul, _max_mul, _table, _flags) \
struct owl_pll _struct = { \
.pll_hw = OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift, \
_width, _min_mul, \
_max_mul, _table), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT(_name, \
_parent, \
&owl_pll_ops, \
_flags), \
}, \
}
#define OWL_PLL_NO_PARENT(_struct, _name, _reg, _bfreq, _bit_idx, \
_shift, _width, _min_mul, _max_mul, _table, _flags) \
struct owl_pll _struct = { \
.pll_hw = OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift, \
_width, _min_mul, \
_max_mul, _table), \
.common = { \
.regmap = NULL, \
.hw.init = CLK_HW_INIT_NO_PARENT(_name, \
&owl_pll_ops, \
_flags), \
}, \
}
#define mul_mask(m) ((1 << ((m)->width)) - 1)
#define PLL_STABILITY_WAIT_US (50)
static inline struct owl_pll *hw_to_owl_pll(const struct clk_hw *hw)
{
struct owl_clk_common *common = hw_to_owl_clk_common(hw);
return container_of(common, struct owl_pll, common);
}
extern const struct clk_ops owl_pll_ops;
#endif /* _OWL_PLL_H_ */
This diff is collapsed.
......@@ -132,19 +132,8 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct clk_pll *pll = to_clk_pll(hw);
unsigned int pllr;
u16 mul;
u8 div;
regmap_read(pll->regmap, PLL_REG(pll->id), &pllr);
div = PLL_DIV(pllr);
mul = PLL_MUL(pllr, pll->layout);
if (!div || !mul)
return 0;
return (parent_rate / div) * (mul + 1);
return (parent_rate / pll->div) * (pll->mul + 1);
}
static long clk_pll_get_best_div_mul(struct clk_pll *pll, unsigned long rate,
......
......@@ -394,25 +394,21 @@ static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman,
return count * 1000;
}
static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
static void bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
struct debugfs_reg32 *regs, size_t nregs,
struct dentry *dentry)
{
struct dentry *regdump;
struct debugfs_regset32 *regset;
regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL);
if (!regset)
return -ENOMEM;
return;
regset->regs = regs;
regset->nregs = nregs;
regset->base = cprman->regs + base;
regdump = debugfs_create_regset32("regdump", S_IRUGO, dentry,
regset);
return regdump ? 0 : -ENOMEM;
debugfs_create_regset32("regdump", S_IRUGO, dentry, regset);
}
struct bcm2835_pll_data {
......@@ -730,7 +726,7 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
return 0;
}
static int bcm2835_pll_debug_init(struct clk_hw *hw,
static void bcm2835_pll_debug_init(struct clk_hw *hw,
struct dentry *dentry)
{
struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
......@@ -740,7 +736,7 @@ static int bcm2835_pll_debug_init(struct clk_hw *hw,
regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
if (!regs)
return -ENOMEM;
return;
regs[0].name = "cm_ctrl";
regs[0].offset = data->cm_ctrl_reg;
......@@ -757,7 +753,7 @@ static int bcm2835_pll_debug_init(struct clk_hw *hw,
regs[6].name = "ana3";
regs[6].offset = data->ana_reg_base + 3 * 4;
return bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry);
bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry);
}
static const struct clk_ops bcm2835_pll_clk_ops = {
......@@ -861,8 +857,8 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
return 0;
}
static int bcm2835_pll_divider_debug_init(struct clk_hw *hw,
struct dentry *dentry)
static void bcm2835_pll_divider_debug_init(struct clk_hw *hw,
struct dentry *dentry)
{
struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
struct bcm2835_cprman *cprman = divider->cprman;
......@@ -871,14 +867,14 @@ static int bcm2835_pll_divider_debug_init(struct clk_hw *hw,
regs = devm_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
if (!regs)
return -ENOMEM;
return;
regs[0].name = "cm";
regs[0].offset = data->cm_reg;
regs[1].name = "a2w";
regs[1].offset = data->a2w_reg;
return bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry);
bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry);
}
static const struct clk_ops bcm2835_pll_divider_clk_ops = {
......@@ -1254,15 +1250,14 @@ static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
},
};
static int bcm2835_clock_debug_init(struct clk_hw *hw,
static void bcm2835_clock_debug_init(struct clk_hw *hw,
struct dentry *dentry)
{
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
struct bcm2835_cprman *cprman = clock->cprman;
const struct bcm2835_clock_data *data = clock->data;
return bcm2835_debugfs_regset(
cprman, data->ctl_reg,
bcm2835_debugfs_regset(cprman, data->ctl_reg,
bcm2835_debugfs_clock_reg32,
ARRAY_SIZE(bcm2835_debugfs_clock_reg32),
dentry);
......@@ -1395,7 +1390,7 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
struct bcm2835_clock *clock;
struct clk_init_data init;
const char *parents[1 << CM_SRC_BITS];
size_t i, j;
size_t i;
int ret;
/*
......@@ -1405,12 +1400,11 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
for (i = 0; i < data->num_mux_parents; i++) {
parents[i] = data->parents[i];
for (j = 0; j < ARRAY_SIZE(cprman_parent_names); j++) {
if (strcmp(parents[i], cprman_parent_names[j]) == 0) {
parents[i] = cprman->real_parent_names[j];
break;
}
}
ret = match_string(cprman_parent_names,
ARRAY_SIZE(cprman_parent_names),
parents[i]);
if (ret >= 0)
parents[i] = cprman->real_parent_names[ret];
}
memset(&init, 0, sizeof(init));
......
......@@ -56,8 +56,8 @@ static const struct iproc_pll_ctrl sr_genpll0 = {
};
static const struct iproc_clk_ctrl sr_genpll0_clk[] = {
[BCM_SR_GENPLL0_SATA_CLK] = {
.channel = BCM_SR_GENPLL0_SATA_CLK,
[BCM_SR_GENPLL0_125M_CLK] = {
.channel = BCM_SR_GENPLL0_125M_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 6, 0, 12),
.mdiv = REG_VAL(0x18, 0, 9),
......@@ -102,6 +102,65 @@ static int sr_genpll0_clk_init(struct platform_device *pdev)
return 0;
}
static const struct iproc_pll_ctrl sr_genpll2 = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_PLL_NEEDS_SW_CFG,
.aon = AON_VAL(0x0, 1, 13, 12),
.reset = RESET_VAL(0x0, 12, 11),
.dig_filter = DF_VAL(0x0, 4, 3, 0, 4, 7, 3),
.sw_ctrl = SW_CTRL_VAL(0x10, 31),
.ndiv_int = REG_VAL(0x10, 20, 10),
.ndiv_frac = REG_VAL(0x10, 0, 20),
.pdiv = REG_VAL(0x14, 0, 4),
.status = REG_VAL(0x30, 12, 1),
};
static const struct iproc_clk_ctrl sr_genpll2_clk[] = {
[BCM_SR_GENPLL2_NIC_CLK] = {
.channel = BCM_SR_GENPLL2_NIC_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 6, 0, 12),
.mdiv = REG_VAL(0x18, 0, 9),
},
[BCM_SR_GENPLL2_TS_500_CLK] = {
.channel = BCM_SR_GENPLL2_TS_500_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 7, 1, 13),
.mdiv = REG_VAL(0x18, 10, 9),
},
[BCM_SR_GENPLL2_125_NITRO_CLK] = {
.channel = BCM_SR_GENPLL2_125_NITRO_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 8, 2, 14),
.mdiv = REG_VAL(0x18, 20, 9),
},
[BCM_SR_GENPLL2_CHIMP_CLK] = {
.channel = BCM_SR_GENPLL2_CHIMP_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 9, 3, 15),
.mdiv = REG_VAL(0x1c, 0, 9),
},
[BCM_SR_GENPLL2_NIC_FLASH_CLK] = {
.channel = BCM_SR_GENPLL2_NIC_FLASH_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 10, 4, 16),
.mdiv = REG_VAL(0x1c, 10, 9),
},
[BCM_SR_GENPLL2_FS4_CLK] = {
.channel = BCM_SR_GENPLL2_FS4_CLK,
.enable = ENABLE_VAL(0x4, 11, 5, 17),
.mdiv = REG_VAL(0x1c, 20, 9),
},
};
static int sr_genpll2_clk_init(struct platform_device *pdev)
{
iproc_pll_clk_setup(pdev->dev.of_node,
&sr_genpll2, NULL, 0, sr_genpll2_clk,
ARRAY_SIZE(sr_genpll2_clk));
return 0;
}
static const struct iproc_pll_ctrl sr_genpll3 = {
.flags = IPROC_CLK_AON | IPROC_CLK_PLL_HAS_NDIV_FRAC |
IPROC_CLK_PLL_NEEDS_SW_CFG,
......@@ -157,6 +216,30 @@ static const struct iproc_clk_ctrl sr_genpll4_clk[] = {
.enable = ENABLE_VAL(0x4, 6, 0, 12),
.mdiv = REG_VAL(0x18, 0, 9),
},
[BCM_SR_GENPLL4_TPIU_PLL_CLK] = {
.channel = BCM_SR_GENPLL4_TPIU_PLL_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 7, 1, 13),
.mdiv = REG_VAL(0x18, 10, 9),
},
[BCM_SR_GENPLL4_NOC_CLK] = {
.channel = BCM_SR_GENPLL4_NOC_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 8, 2, 14),
.mdiv = REG_VAL(0x18, 20, 9),
},
[BCM_SR_GENPLL4_CHCLK_FS4_CLK] = {
.channel = BCM_SR_GENPLL4_CHCLK_FS4_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 9, 3, 15),
.mdiv = REG_VAL(0x1c, 0, 9),
},
[BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK] = {
.channel = BCM_SR_GENPLL4_BRIDGE_FSCPU_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 10, 4, 16),
.mdiv = REG_VAL(0x1c, 10, 9),
},
};
static int sr_genpll4_clk_init(struct platform_device *pdev)
......@@ -181,18 +264,21 @@ static const struct iproc_pll_ctrl sr_genpll5 = {
};
static const struct iproc_clk_ctrl sr_genpll5_clk[] = {
[BCM_SR_GENPLL5_FS_CLK] = {
.channel = BCM_SR_GENPLL5_FS_CLK,
.flags = IPROC_CLK_AON,
[BCM_SR_GENPLL5_FS4_HF_CLK] = {
.channel = BCM_SR_GENPLL5_FS4_HF_CLK,
.enable = ENABLE_VAL(0x4, 6, 0, 12),
.mdiv = REG_VAL(0x18, 0, 9),
},
[BCM_SR_GENPLL5_SPU_CLK] = {
.channel = BCM_SR_GENPLL5_SPU_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x4, 6, 0, 12),
[BCM_SR_GENPLL5_CRYPTO_AE_CLK] = {
.channel = BCM_SR_GENPLL5_CRYPTO_AE_CLK,
.enable = ENABLE_VAL(0x4, 7, 1, 12),
.mdiv = REG_VAL(0x18, 10, 9),
},
[BCM_SR_GENPLL5_RAID_AE_CLK] = {
.channel = BCM_SR_GENPLL5_RAID_AE_CLK,
.enable = ENABLE_VAL(0x4, 8, 2, 14),
.mdiv = REG_VAL(0x18, 20, 9),
},
};
static int sr_genpll5_clk_init(struct platform_device *pdev)
......@@ -214,24 +300,30 @@ static const struct iproc_pll_ctrl sr_lcpll0 = {
};
static const struct iproc_clk_ctrl sr_lcpll0_clk[] = {
[BCM_SR_LCPLL0_SATA_REF_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_REF_CLK,
[BCM_SR_LCPLL0_SATA_REFP_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_REFP_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 7, 1, 13),
.mdiv = REG_VAL(0x14, 0, 9),
},
[BCM_SR_LCPLL0_USB_REF_CLK] = {
.channel = BCM_SR_LCPLL0_USB_REF_CLK,
[BCM_SR_LCPLL0_SATA_REFN_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_REFN_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 8, 2, 14),
.mdiv = REG_VAL(0x14, 10, 9),
},
[BCM_SR_LCPLL0_SATA_REFPN_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_REFPN_CLK,
[BCM_SR_LCPLL0_SATA_350_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_350_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 9, 3, 15),
.mdiv = REG_VAL(0x14, 20, 9),
},
[BCM_SR_LCPLL0_SATA_500_CLK] = {
.channel = BCM_SR_LCPLL0_SATA_500_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 10, 4, 16),
.mdiv = REG_VAL(0x18, 0, 9),
},
};
static int sr_lcpll0_clk_init(struct platform_device *pdev)
......@@ -259,6 +351,18 @@ static const struct iproc_clk_ctrl sr_lcpll1_clk[] = {
.enable = ENABLE_VAL(0x0, 7, 1, 13),
.mdiv = REG_VAL(0x14, 0, 9),
},
[BCM_SR_LCPLL1_USB_REF_CLK] = {
.channel = BCM_SR_LCPLL1_USB_REF_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 8, 2, 14),
.mdiv = REG_VAL(0x14, 10, 9),
},
[BCM_SR_LCPLL1_CRMU_TS_CLK] = {
.channel = BCM_SR_LCPLL1_CRMU_TS_CLK,
.flags = IPROC_CLK_AON,
.enable = ENABLE_VAL(0x0, 9, 3, 15),
.mdiv = REG_VAL(0x14, 20, 9),
},
};
static int sr_lcpll1_clk_init(struct platform_device *pdev)
......@@ -298,6 +402,7 @@ static int sr_lcpll_pcie_clk_init(struct platform_device *pdev)
static const struct of_device_id sr_clk_dt_ids[] = {
{ .compatible = "brcm,sr-genpll0", .data = sr_genpll0_clk_init },
{ .compatible = "brcm,sr-genpll2", .data = sr_genpll2_clk_init },
{ .compatible = "brcm,sr-genpll4", .data = sr_genpll4_clk_init },
{ .compatible = "brcm,sr-genpll5", .data = sr_genpll5_clk_init },
{ .compatible = "brcm,sr-lcpll0", .data = sr_lcpll0_clk_init },
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BERLIN2_AVPLL_H
#define __BERLIN2_AVPLL_H
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/bitops.h>
#include <linux/clk-provider.h>
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BERLIN2_DIV_H
#define __BERLIN2_DIV_H
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk-provider.h>
#include <linux/io.h>
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BERLIN2_PLL_H
#define __BERLIN2_PLL_H
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
......
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2014 Marvell Technology Group Ltd.
*
* Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
* Alexandre Belloni <alexandre.belloni@free-electrons.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __BERLIN2_COMMON_H
#define __BERLIN2_COMMON_H
......
......@@ -14,7 +14,9 @@
#include <dt-bindings/clock/aspeed-clock.h>
#define ASPEED_NUM_CLKS 35
#define ASPEED_NUM_CLKS 36
#define ASPEED_RESET2_OFFSET 32
#define ASPEED_RESET_CTRL 0x04
#define ASPEED_CLK_SELECTION 0x08
......@@ -30,6 +32,7 @@
#define CLKIN_25MHZ_EN BIT(23)
#define AST2400_CLK_SOURCE_SEL BIT(18)
#define ASPEED_CLK_SELECTION_2 0xd8
#define ASPEED_RESET_CTRL2 0xd4
/* Globally visible clocks */
static DEFINE_SPINLOCK(aspeed_clk_lock);
......@@ -88,7 +91,7 @@ static const struct aspeed_gate_data aspeed_gates[] = {
[ASPEED_CLK_GATE_GCLK] = { 1, 7, "gclk-gate", NULL, 0 }, /* 2D engine */
[ASPEED_CLK_GATE_MCLK] = { 2, -1, "mclk-gate", "mpll", CLK_IS_CRITICAL }, /* SDRAM */
[ASPEED_CLK_GATE_VCLK] = { 3, 6, "vclk-gate", NULL, 0 }, /* Video Capture */
[ASPEED_CLK_GATE_BCLK] = { 4, 10, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */
[ASPEED_CLK_GATE_BCLK] = { 4, 8, "bclk-gate", "bclk", 0 }, /* PCIe/PCI */
[ASPEED_CLK_GATE_DCLK] = { 5, -1, "dclk-gate", NULL, 0 }, /* DAC */
[ASPEED_CLK_GATE_REFCLK] = { 6, -1, "refclk-gate", "clkin", CLK_IS_CRITICAL },
[ASPEED_CLK_GATE_USBPORT2CLK] = { 7, 3, "usb-port2-gate", NULL, 0 }, /* USB2.0 Host port 2 */
......@@ -291,47 +294,72 @@ struct aspeed_reset {
#define to_aspeed_reset(p) container_of((p), struct aspeed_reset, rcdev)
static const u8 aspeed_resets[] = {
/* SCU04 resets */
[ASPEED_RESET_XDMA] = 25,
[ASPEED_RESET_MCTP] = 24,
[ASPEED_RESET_ADC] = 23,
[ASPEED_RESET_JTAG_MASTER] = 22,
[ASPEED_RESET_MIC] = 18,
[ASPEED_RESET_PWM] = 9,
[ASPEED_RESET_PCIVGA] = 8,
[ASPEED_RESET_PECI] = 10,
[ASPEED_RESET_I2C] = 2,
[ASPEED_RESET_AHB] = 1,
/*
* SCUD4 resets start at an offset to separate them from
* the SCU04 resets.
*/
[ASPEED_RESET_CRT1] = ASPEED_RESET2_OFFSET + 5,
};
static int aspeed_reset_deassert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
u32 rst = BIT(aspeed_resets[id]);
u32 reg = ASPEED_RESET_CTRL;
u32 bit = aspeed_resets[id];
return regmap_update_bits(ar->map, ASPEED_RESET_CTRL, rst, 0);
if (bit >= ASPEED_RESET2_OFFSET) {
bit -= ASPEED_RESET2_OFFSET;
reg = ASPEED_RESET_CTRL2;
}
return regmap_update_bits(ar->map, reg, BIT(bit), 0);
}
static int aspeed_reset_assert(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
u32 rst = BIT(aspeed_resets[id]);
u32 reg = ASPEED_RESET_CTRL;
u32 bit = aspeed_resets[id];
if (bit >= ASPEED_RESET2_OFFSET) {
bit -= ASPEED_RESET2_OFFSET;
reg = ASPEED_RESET_CTRL2;
}
return regmap_update_bits(ar->map, ASPEED_RESET_CTRL, rst, rst);
return regmap_update_bits(ar->map, reg, BIT(bit), BIT(bit));
}
static int aspeed_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct aspeed_reset *ar = to_aspeed_reset(rcdev);
u32 val, rst = BIT(aspeed_resets[id]);
int ret;
u32 reg = ASPEED_RESET_CTRL;
u32 bit = aspeed_resets[id];
int ret, val;
if (bit >= ASPEED_RESET2_OFFSET) {
bit -= ASPEED_RESET2_OFFSET;
reg = ASPEED_RESET_CTRL2;
}
ret = regmap_read(ar->map, ASPEED_RESET_CTRL, &val);
ret = regmap_read(ar->map, reg, &val);
if (ret)
return ret;
return !!(val & rst);
return !!(val & BIT(bit));
}
static const struct reset_control_ops aspeed_reset_ops = {
......@@ -474,6 +502,13 @@ static int aspeed_clk_probe(struct platform_device *pdev)
return PTR_ERR(hw);
aspeed_clk_data->hws[ASPEED_CLK_BCLK] = hw;
/* Fixed 24MHz clock */
hw = clk_hw_register_fixed_rate(NULL, "fixed-24m", "clkin",
0, 24000000);
if (IS_ERR(hw))
return PTR_ERR(hw);
aspeed_clk_data->hws[ASPEED_CLK_24M] = hw;
/*
* TODO: There are a number of clocks that not included in this driver
* as more information is required:
......
......@@ -42,8 +42,9 @@ int __must_check clk_bulk_get(struct device *dev, int num_clks,
clks[i].clk = clk_get(dev, clks[i].id);
if (IS_ERR(clks[i].clk)) {
ret = PTR_ERR(clks[i].clk);
dev_err(dev, "Failed to get clk '%s': %d\n",
clks[i].id, ret);
if (ret != -EPROBE_DEFER)
dev_err(dev, "Failed to get clk '%s': %d\n",
clks[i].id, ret);
clks[i].clk = NULL;
goto err;
}
......
This diff is collapsed.
......@@ -207,6 +207,7 @@ static int si544_calc_muldiv(struct clk_si544_muldiv *settings,
/* And the fractional bits using the remainder */
vco = (u64)tmp << 32;
vco += FXO / 2; /* Round to nearest multiple */
do_div(vco, FXO);
settings->fb_div_frac = vco;
......
......@@ -579,14 +579,9 @@ clk_stm32_register_gate_ops(struct device *dev,
spinlock_t *lock)
{
struct clk_init_data init = { NULL };
struct clk_gate *gate;
struct clk_hw *hw;
int ret;
gate = kzalloc(sizeof(*gate), GFP_KERNEL);
if (!gate)
return ERR_PTR(-ENOMEM);
init.name = name;
init.parent_names = &parent_name;
init.num_parents = 1;
......@@ -604,10 +599,8 @@ clk_stm32_register_gate_ops(struct device *dev,
hw->init = &init;
ret = clk_hw_register(dev, hw);
if (ret) {
kfree(gate);
if (ret)
hw = ERR_PTR(ret);
}
return hw;
}
......@@ -1988,7 +1981,8 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
_DIV(RCC_MCO2CFGR, 4, 4, 0, NULL)),
/* Debug clocks */
GATE(CK_DBG, "ck_sys_dbg", "ck_axi", 0, RCC_DBGCFGR, 8, 0),
GATE(CK_DBG, "ck_sys_dbg", "ck_axi", CLK_IGNORE_UNUSED,
RCC_DBGCFGR, 8, 0),
COMPOSITE(CK_TRACE, "ck_trace", ck_trace_src, CLK_OPS_PARENT_ENABLE,
_GATE(RCC_DBGCFGR, 9, 0),
......
......@@ -549,7 +549,8 @@ static void clk_core_rate_unprotect(struct clk_core *core)
if (!core)
return;
if (WARN_ON(core->protect_count == 0))
if (WARN(core->protect_count == 0,
"%s already unprotected\n", core->name))
return;
if (--core->protect_count > 0)
......@@ -682,16 +683,18 @@ static void clk_core_unprepare(struct clk_core *core)
if (!core)
return;
if (WARN_ON(core->prepare_count == 0))
if (WARN(core->prepare_count == 0,
"%s already unprepared\n", core->name))
return;
if (WARN_ON(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL))
if (WARN(core->prepare_count == 1 && core->flags & CLK_IS_CRITICAL,
"Unpreparing critical %s\n", core->name))
return;
if (--core->prepare_count > 0)
return;
WARN_ON(core->enable_count > 0);
WARN(core->enable_count > 0, "Unpreparing enabled %s\n", core->name);
trace_clk_unprepare(core);
......@@ -809,10 +812,11 @@ static void clk_core_disable(struct clk_core *core)
if (!core)
return;
if (WARN_ON(core->enable_count == 0))
if (WARN(core->enable_count == 0, "%s already disabled\n", core->name))
return;
if (WARN_ON(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL))
if (WARN(core->enable_count == 1 && core->flags & CLK_IS_CRITICAL,
"Disabling critical %s\n", core->name))
return;
if (--core->enable_count > 0)
......@@ -867,7 +871,8 @@ static int clk_core_enable(struct clk_core *core)
if (!core)
return 0;
if (WARN_ON(core->prepare_count == 0))
if (WARN(core->prepare_count == 0,
"Enabling unprepared %s\n", core->name))
return -ESHUTDOWN;
if (core->enable_count == 0) {
......@@ -2171,7 +2176,6 @@ void clk_hw_reparent(struct clk_hw *hw, struct clk_hw *new_parent)
bool clk_has_parent(struct clk *clk, struct clk *parent)
{
struct clk_core *core, *parent_core;
unsigned int i;
/* NULL clocks should be nops, so return success if either is NULL. */
if (!clk || !parent)
......@@ -2184,11 +2188,8 @@ bool clk_has_parent(struct clk *clk, struct clk *parent)
if (core->parent == parent_core)
return true;
for (i = 0; i < core->num_parents; i++)
if (strcmp(core->parent_names[i], parent_core->name) == 0)
return true;
return false;
return match_string(core->parent_names, core->num_parents,
parent_core->name) >= 0;
}
EXPORT_SYMBOL_GPL(clk_has_parent);
......@@ -2609,81 +2610,31 @@ static int possible_parents_show(struct seq_file *s, void *data)
}
DEFINE_SHOW_ATTRIBUTE(possible_parents);
static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
static void clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
{
struct dentry *d;
int ret = -ENOMEM;
if (!core || !pdentry) {
ret = -EINVAL;
goto out;
}
d = debugfs_create_dir(core->name, pdentry);
if (!d)
goto out;
struct dentry *root;
core->dentry = d;
d = debugfs_create_ulong("clk_rate", 0444, core->dentry, &core->rate);
if (!d)
goto err_out;
d = debugfs_create_ulong("clk_accuracy", 0444, core->dentry,
&core->accuracy);
if (!d)
goto err_out;
d = debugfs_create_u32("clk_phase", 0444, core->dentry, &core->phase);
if (!d)
goto err_out;
d = debugfs_create_file("clk_flags", 0444, core->dentry, core,
&clk_flags_fops);
if (!d)
goto err_out;
d = debugfs_create_u32("clk_prepare_count", 0444, core->dentry,
&core->prepare_count);
if (!d)
goto err_out;
d = debugfs_create_u32("clk_enable_count", 0444, core->dentry,
&core->enable_count);
if (!d)
goto err_out;
d = debugfs_create_u32("clk_protect_count", 0444, core->dentry,
&core->protect_count);
if (!d)
goto err_out;
d = debugfs_create_u32("clk_notifier_count", 0444, core->dentry,
&core->notifier_count);
if (!d)
goto err_out;
if (!core || !pdentry)
return;
if (core->num_parents > 1) {
d = debugfs_create_file("clk_possible_parents", 0444,
core->dentry, core, &possible_parents_fops);
if (!d)
goto err_out;
}
root = debugfs_create_dir(core->name, pdentry);
core->dentry = root;
if (core->ops->debug_init) {
ret = core->ops->debug_init(core->hw, core->dentry);
if (ret)
goto err_out;
}
debugfs_create_ulong("clk_rate", 0444, root, &core->rate);
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);
debugfs_create_u32("clk_prepare_count", 0444, root, &core->prepare_count);
debugfs_create_u32("clk_enable_count", 0444, root, &core->enable_count);
debugfs_create_u32("clk_protect_count", 0444, root, &core->protect_count);
debugfs_create_u32("clk_notifier_count", 0444, root, &core->notifier_count);
ret = 0;
goto out;
if (core->num_parents > 1)
debugfs_create_file("clk_possible_parents", 0444, root, core,
&possible_parents_fops);
err_out:
debugfs_remove_recursive(core->dentry);
core->dentry = NULL;
out:
return ret;
if (core->ops->debug_init)
core->ops->debug_init(core->hw, core->dentry);
}
/**
......@@ -2694,17 +2645,13 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
* initialized. Otherwise it bails out early since the debugfs clk directory
* will be created lazily by clk_debug_init as part of a late_initcall.
*/
static int clk_debug_register(struct clk_core *core)
static void clk_debug_register(struct clk_core *core)
{
int ret = 0;
mutex_lock(&clk_debug_lock);
hlist_add_head(&core->debug_node, &clk_debug_list);
if (inited)
ret = clk_debug_create_one(core, rootdir);
clk_debug_create_one(core, rootdir);
mutex_unlock(&clk_debug_lock);
return ret;
}
/**
......@@ -2724,19 +2671,6 @@ static void clk_debug_unregister(struct clk_core *core)
mutex_unlock(&clk_debug_lock);
}
struct dentry *clk_debugfs_add_file(struct clk_hw *hw, char *name, umode_t mode,
void *data, const struct file_operations *fops)
{
struct dentry *d = NULL;
if (hw->core->dentry)
d = debugfs_create_file(name, mode, hw->core->dentry, data,
fops);
return d;
}
EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
/**
* clk_debug_init - lazily populate the debugfs clk directory
*
......@@ -2749,32 +2683,17 @@ EXPORT_SYMBOL_GPL(clk_debugfs_add_file);
static int __init clk_debug_init(void)
{
struct clk_core *core;
struct dentry *d;
rootdir = debugfs_create_dir("clk", NULL);
if (!rootdir)
return -ENOMEM;
d = debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
&clk_summary_fops);
if (!d)
return -ENOMEM;
d = debugfs_create_file("clk_dump", 0444, rootdir, &all_lists,
&clk_dump_fops);
if (!d)
return -ENOMEM;
d = debugfs_create_file("clk_orphan_summary", 0444, rootdir,
&orphan_list, &clk_summary_fops);
if (!d)
return -ENOMEM;
d = debugfs_create_file("clk_orphan_dump", 0444, rootdir,
&orphan_list, &clk_dump_fops);
if (!d)
return -ENOMEM;
debugfs_create_file("clk_summary", 0444, rootdir, &all_lists,
&clk_summary_fops);
debugfs_create_file("clk_dump", 0444, rootdir, &all_lists,
&clk_dump_fops);
debugfs_create_file("clk_orphan_summary", 0444, rootdir, &orphan_list,
&clk_summary_fops);
debugfs_create_file("clk_orphan_dump", 0444, rootdir, &orphan_list,
&clk_dump_fops);
mutex_lock(&clk_debug_lock);
hlist_for_each_entry(core, &clk_debug_list, debug_node)
......@@ -2787,7 +2706,7 @@ static int __init clk_debug_init(void)
}
late_initcall(clk_debug_init);
#else
static inline int clk_debug_register(struct clk_core *core) { return 0; }
static inline void clk_debug_register(struct clk_core *core) { }
static inline void clk_debug_reparent(struct clk_core *core,
struct clk_core *new_parent)
{
......@@ -3907,7 +3826,7 @@ int of_clk_parent_fill(struct device_node *np, const char **parents,
EXPORT_SYMBOL_GPL(of_clk_parent_fill);
struct clock_provider {
of_clk_init_cb_t clk_init_cb;
void (*clk_init_cb)(struct device_node *);
struct device_node *np;
struct list_head node;
};
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clkdev.h>
#include <linux/clk/davinci.h>
#include <linux/bitops.h>
#include <linux/init.h>
#include <linux/types.h>
......@@ -36,11 +37,11 @@ SYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0);
SYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_FIXED_DIV);
SYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0);
int da830_pll_init(struct device *dev, void __iomem *base)
int da830_pll_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base);
davinci_pll_clk_register(dev, &da830_pll_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base);
clk_register_clkdev(clk, "pll0_sysclk2", "da830-psc0");
......
......@@ -7,10 +7,14 @@
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/device.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/mfd/da8xx-cfgchip.h>
#include <linux/mfd/syscon.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/types.h>
......@@ -81,11 +85,11 @@ static const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = {
.ocsrc_mask = GENMASK(4, 0),
};
int da850_pll0_init(struct device *dev, void __iomem *base)
int da850_pll0_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base);
davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base);
clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0");
......@@ -134,11 +138,22 @@ static const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = {
NULL
};
int of_da850_pll0_init(struct device *dev, void __iomem *base)
void of_da850_pll0_init(struct device_node *node)
{
return of_davinci_pll_init(dev, &da850_pll0_info,
&da850_pll0_obsclk_info,
da850_pll0_sysclk_info, 7, base);
void __iomem *base;
struct regmap *cfgchip;
base = of_iomap(node, 0);
if (!base) {
pr_err("%s: ioremap failed\n", __func__);
return;
}
cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip");
of_davinci_pll_init(NULL, node, &da850_pll0_info,
&da850_pll0_obsclk_info,
da850_pll0_sysclk_info, 7, base, cfgchip);
}
static const struct davinci_pll_clk_info da850_pll1_info = {
......@@ -179,11 +194,11 @@ static const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = {
.ocsrc_mask = GENMASK(4, 0),
};
int da850_pll1_init(struct device *dev, void __iomem *base)
int da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base);
davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base, cfgchip);
davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
......@@ -204,9 +219,9 @@ static const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = {
NULL
};
int of_da850_pll1_init(struct device *dev, void __iomem *base)
int of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
return of_davinci_pll_init(dev, &da850_pll1_info,
return of_davinci_pll_init(dev, dev->of_node, &da850_pll1_info,
&da850_pll1_obsclk_info,
da850_pll1_sysclk_info, 3, base);
da850_pll1_sysclk_info, 3, base, cfgchip);
}
......@@ -6,6 +6,7 @@
*/
#include <linux/bitops.h>
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/types.h>
......@@ -22,16 +23,16 @@ static const struct davinci_pll_clk_info dm355_pll1_info = {
PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
};
SYSCLK(1, pll1_sysclk1, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll1_sysclk3, pll1, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll1_sysclk4, pll1, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(2, pll1_sysclk2, pll1_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(3, pll1_sysclk3, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
SYSCLK(4, pll1_sysclk4, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED);
int dm355_pll1_init(struct device *dev, void __iomem *base)
int dm355_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base);
davinci_pll_clk_register(dev, &dm355_pll1_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm355-psc");
......@@ -62,17 +63,14 @@ static const struct davinci_pll_clk_info dm355_pll2_info = {
PLL_POSTDIV_ALWAYS_ENABLED | PLL_POSTDIV_FIXED_DIV,
};
SYSCLK(1, pll2_sysclk1, pll2, 5, SYSCLK_FIXED_DIV);
SYSCLK(2, pll2_sysclk2, pll2, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
SYSCLK(1, pll2_sysclk1, pll2_pllen, 5, SYSCLK_FIXED_DIV | SYSCLK_ALWAYS_ENABLED);
int dm355_pll2_init(struct device *dev, void __iomem *base)
int dm355_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base);
davinci_pll_clk_register(dev, &dm355_pll2_info, "oscin", base, cfgchip);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
davinci_pll_sysclk_register(dev, &pll2_sysclk2, base);
davinci_pll_sysclkbp_clk_register(dev, "pll2_sysclkbp", base);
return 0;
......
......@@ -7,6 +7,7 @@
#include <linux/bitops.h>
#include <linux/clkdev.h>
#include <linux/clk/davinci.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/types.h>
......@@ -56,11 +57,11 @@ static const struct davinci_pll_obsclk_info dm365_pll1_obsclk_info = {
.ocsrc_mask = BIT(4),
};
int dm365_pll1_init(struct device *dev, void __iomem *base)
int dm365_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base);
davinci_pll_clk_register(dev, &dm365_pll1_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm365-psc");
......@@ -119,11 +120,11 @@ static const struct davinci_pll_obsclk_info dm365_pll2_obsclk_info = {
.ocsrc_mask = BIT(4),
};
int dm365_pll2_init(struct device *dev, void __iomem *base)
int dm365_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base);
davinci_pll_clk_register(dev, &dm365_pll2_info, "oscin", base, cfgchip);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
......
......@@ -6,6 +6,7 @@
*/
#include <linux/bitops.h>
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/types.h>
......@@ -27,11 +28,11 @@ SYSCLK(2, pll1_sysclk2, pll1_pllen, 4, SYSCLK_FIXED_DIV);
SYSCLK(3, pll1_sysclk3, pll1_pllen, 4, SYSCLK_FIXED_DIV);
SYSCLK(5, pll1_sysclk5, pll1_pllen, 4, SYSCLK_FIXED_DIV);
int dm644x_pll1_init(struct device *dev, void __iomem *base)
int dm644x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm644x_pll1_info, "ref_clk", base);
davinci_pll_clk_register(dev, &dm644x_pll1_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm644x-psc");
......@@ -66,9 +67,9 @@ static const struct davinci_pll_clk_info dm644x_pll2_info = {
SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0);
SYSCLK(2, pll2_sysclk2, pll2_pllen, 4, 0);
int dm644x_pll2_init(struct device *dev, void __iomem *base)
int dm644x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
davinci_pll_clk_register(dev, &dm644x_pll2_info, "oscin", base);
davinci_pll_clk_register(dev, &dm644x_pll2_info, "oscin", base, cfgchip);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/init.h>
#include <linux/types.h>
......@@ -29,11 +30,11 @@ SYSCLK(6, pll1_sysclk6, pll1_pllen, 4, 0);
SYSCLK(8, pll1_sysclk8, pll1_pllen, 4, 0);
SYSCLK(9, pll1_sysclk9, pll1_pllen, 4, 0);
int dm646x_pll1_init(struct device *dev, void __iomem *base)
int dm646x_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
struct clk *clk;
davinci_pll_clk_register(dev, &dm646x_pll1_info, "ref_clk", base);
davinci_pll_clk_register(dev, &dm646x_pll1_info, "ref_clk", base, cfgchip);
clk = davinci_pll_sysclk_register(dev, &pll1_sysclk1, base);
clk_register_clkdev(clk, "pll1_sysclk1", "dm646x-psc");
......@@ -72,11 +73,11 @@ static const struct davinci_pll_clk_info dm646x_pll2_info = {
.flags = 0,
};
SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, 0);
SYSCLK(1, pll2_sysclk1, pll2_pllen, 4, SYSCLK_ALWAYS_ENABLED);
int dm646x_pll2_init(struct device *dev, void __iomem *base)
int dm646x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip)
{
davinci_pll_clk_register(dev, &dm646x_pll2_info, "oscin", base);
davinci_pll_clk_register(dev, &dm646x_pll2_info, "oscin", base, cfgchip);
davinci_pll_sysclk_register(dev, &pll2_sysclk1, base);
......
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/clk-provider.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/types.h>
#define PLL_HAS_CLKMODE BIT(0) /* PLL has PLLCTL[CLKMODE] */
......@@ -94,7 +95,8 @@ struct davinci_pll_obsclk_info {
struct clk *davinci_pll_clk_register(struct device *dev,
const struct davinci_pll_clk_info *info,
const char *parent_name,
void __iomem *base);
void __iomem *base,
struct regmap *cfgchip);
struct clk *davinci_pll_auxclk_register(struct device *dev,
const char *name,
void __iomem *base);
......@@ -110,32 +112,29 @@ davinci_pll_sysclk_register(struct device *dev,
const struct davinci_pll_sysclk_info *info,
void __iomem *base);
int of_davinci_pll_init(struct device *dev,
int of_davinci_pll_init(struct device *dev, struct device_node *node,
const struct davinci_pll_clk_info *info,
const struct davinci_pll_obsclk_info *obsclk_info,
const struct davinci_pll_sysclk_info **div_info,
u8 max_sysclk_id,
void __iomem *base);
void __iomem *base,
struct regmap *cfgchip);
/* Platform-specific callbacks */
int da830_pll_init(struct device *dev, void __iomem *base);
int da850_pll0_init(struct device *dev, void __iomem *base);
int da850_pll1_init(struct device *dev, void __iomem *base);
int of_da850_pll0_init(struct device *dev, void __iomem *base);
int of_da850_pll1_init(struct device *dev, void __iomem *base);
int dm355_pll1_init(struct device *dev, void __iomem *base);
int dm355_pll2_init(struct device *dev, void __iomem *base);
int dm365_pll1_init(struct device *dev, void __iomem *base);
int dm365_pll2_init(struct device *dev, void __iomem *base);
int dm644x_pll1_init(struct device *dev, void __iomem *base);
int dm644x_pll2_init(struct device *dev, void __iomem *base);
int dm646x_pll1_init(struct device *dev, void __iomem *base);
int dm646x_pll2_init(struct device *dev, void __iomem *base);
#ifdef CONFIG_ARCH_DAVINCI_DA850
int da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
void of_da850_pll0_init(struct device_node *node);
int of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM355
int dm355_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM644x
int dm644x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM646x
int dm646x_pll2_init(struct device *dev, void __iomem *base, struct regmap *cfgchip);
#endif
#endif /* __CLK_DAVINCI_PLL_H___ */
......@@ -55,7 +55,8 @@ const struct davinci_psc_init_data da830_psc0_init_data = {
.psc_init = &da830_psc0_init,
};
LPSC_CLKDEV2(usb0_clkdev, NULL, "musb-da8xx",
LPSC_CLKDEV3(usb0_clkdev, "fck", "da830-usb-phy-clks",
NULL, "musb-da8xx",
NULL, "cppi41-dmaengine");
LPSC_CLKDEV1(usb1_clkdev, NULL, "ohci-da8xx");
/* REVISIT: gpio-davinci.c should be modified to drop con_id */
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/init.h>
......@@ -41,14 +42,14 @@ static const struct davinci_lpsc_clk_info dm355_psc_info[] = {
LPSC(5, 0, timer3, pll1_auxclk, NULL, 0),
LPSC(6, 0, spi1, pll1_sysclk2, spi1_clkdev, 0),
LPSC(7, 0, mmcsd1, pll1_sysclk2, mmcsd1_clkdev, 0),
LPSC(8, 0, asp1, pll1_sysclk2, NULL, 0),
LPSC(8, 0, asp1, pll1_sysclk2, mcbsp1_clkdev, 0),
LPSC(9, 0, usb, pll1_sysclk2, usb_clkdev, 0),
LPSC(10, 0, pwm3, pll1_auxclk, NULL, 0),
LPSC(11, 0, spi2, pll1_sysclk2, spi2_clkdev, 0),
LPSC(12, 0, rto, pll1_auxclk, NULL, 0),
LPSC(14, 0, aemif, pll1_sysclk2, aemif_clkdev, 0),
LPSC(15, 0, mmcsd0, pll1_sysclk2, mmcsd0_clkdev, 0),
LPSC(17, 0, asp0, pll1_sysclk2, NULL, 0),
LPSC(17, 0, asp0, pll1_sysclk2, mcbsp0_clkdev, 0),
LPSC(18, 0, i2c, pll1_auxclk, i2c_clkdev, 0),
LPSC(19, 0, uart0, pll1_auxclk, uart0_clkdev, 0),
LPSC(20, 0, uart1, pll1_auxclk, uart1_clkdev, 0),
......@@ -68,7 +69,7 @@ static const struct davinci_lpsc_clk_info dm355_psc_info[] = {
{ }
};
static int dm355_psc_init(struct device *dev, void __iomem *base)
int dm355_psc_init(struct device *dev, void __iomem *base)
{
return davinci_psc_register_clocks(dev, dm355_psc_info, 42, base);
}
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/init.h>
......@@ -65,15 +66,28 @@ static const struct davinci_lpsc_clk_info dm365_psc_info[] = {
LPSC(31, 0, arm, pll2_sysclk2, NULL, LPSC_ALWAYS_ENABLED),
LPSC(38, 0, spi3, pll1_sysclk4, spi3_clkdev, 0),
LPSC(39, 0, spi4, pll1_auxclk, spi4_clkdev, 0),
LPSC(40, 0, emac, pll2_sysclk4, emac_clkdev, 0),
LPSC(44, 1, voice_codec, pll1_sysclk3, voice_codec_clkdev, 0),
LPSC(46, 1, vpss_dac, pll1_sysclk3, vpss_dac_clkdev, 0),
LPSC(40, 0, emac, pll1_sysclk4, emac_clkdev, 0),
/*
* The TRM (ARM Subsystem User's Guide) shows two clocks input into
* voice codec module (PLL2 SYSCLK4 with a DIV2 and PLL1 SYSCLK4). Its
* not fully clear from documentation which clock should be considered
* as parent for PSC. The clock chosen here is to maintain
* compatibility with existing code in arch/arm/mach-davinci/dm365.c
*/
LPSC(44, 0, voice_codec, pll2_sysclk4, voice_codec_clkdev, 0),
/*
* Its not fully clear from TRM (ARM Subsystem User's Guide) as to what
* the parent of VPSS DAC LPSC should actually be. PLL1 SYSCLK3 feeds
* into HDVICP and MJCP. The clock chosen here is to remain compatible
* with code existing in arch/arm/mach-davinci/dm365.c
*/
LPSC(46, 0, vpss_dac, pll1_sysclk3, vpss_dac_clkdev, 0),
LPSC(47, 0, vpss_master, pll1_sysclk5, vpss_master_clkdev, 0),
LPSC(50, 0, mjcp, pll1_sysclk3, NULL, 0),
{ }
};
static int dm365_psc_init(struct device *dev, void __iomem *base)
int dm365_psc_init(struct device *dev, void __iomem *base)
{
return davinci_psc_register_clocks(dev, dm365_psc_info, 52, base);
}
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/init.h>
......@@ -63,7 +64,7 @@ static const struct davinci_lpsc_clk_info dm644x_psc_info[] = {
{ }
};
static int dm644x_psc_init(struct device *dev, void __iomem *base)
int dm644x_psc_init(struct device *dev, void __iomem *base)
{
return davinci_psc_register_clocks(dev, dm644x_psc_info, 41, base);
}
......
......@@ -6,6 +6,7 @@
*/
#include <linux/clk-provider.h>
#include <linux/clk/davinci.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/init.h>
......@@ -58,7 +59,7 @@ static const struct davinci_lpsc_clk_info dm646x_psc_info[] = {
{ }
};
static int dm646x_psc_init(struct device *dev, void __iomem *base)
int dm646x_psc_init(struct device *dev, void __iomem *base)
{
return davinci_psc_register_clocks(dev, dm646x_psc_info, 46, base);
}
......
......@@ -15,6 +15,7 @@
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/clk/davinci.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/of_address.h>
......@@ -63,7 +64,7 @@ struct davinci_psc_data {
/**
* struct davinci_lpsc_clk - LPSC clock structure
* @dev: the device that provides this LPSC
* @dev: the device that provides this LPSC or NULL
* @hw: clk_hw for the LPSC
* @pm_domain: power domain for the LPSC
* @genpd_clk: clock reference owned by @pm_domain
......@@ -221,6 +222,7 @@ static void davinci_psc_genpd_detach_dev(struct generic_pm_domain *pm_domain,
/**
* davinci_lpsc_clk_register - register LPSC clock
* @dev: the clocks's device or NULL
* @name: name of this clock
* @parent_name: name of clock's parent
* @regmap: PSC MMIO region
......@@ -238,7 +240,7 @@ davinci_lpsc_clk_register(struct device *dev, const char *name,
int ret;
bool is_on;
lpsc = devm_kzalloc(dev, sizeof(*lpsc), GFP_KERNEL);
lpsc = kzalloc(sizeof(*lpsc), GFP_KERNEL);
if (!lpsc)
return ERR_PTR(-ENOMEM);
......@@ -261,9 +263,15 @@ davinci_lpsc_clk_register(struct device *dev, const char *name,
lpsc->pd = pd;
lpsc->flags = flags;
ret = devm_clk_hw_register(dev, &lpsc->hw);
if (ret < 0)
ret = clk_hw_register(dev, &lpsc->hw);
if (ret < 0) {
kfree(lpsc);
return ERR_PTR(ret);
}
/* for now, genpd is only registered when using device-tree */
if (!dev || !dev->of_node)
return lpsc;
/* genpd attach needs a way to look up this clock */
ret = clk_hw_register_clkdev(&lpsc->hw, name, best_dev_name(dev));
......@@ -378,13 +386,15 @@ __davinci_psc_register_clocks(struct device *dev,
struct regmap *regmap;
int i, ret;
psc = devm_kzalloc(dev, sizeof(*psc), GFP_KERNEL);
psc = kzalloc(sizeof(*psc), GFP_KERNEL);
if (!psc)
return ERR_PTR(-ENOMEM);
clks = devm_kmalloc_array(dev, num_clks, sizeof(*clks), GFP_KERNEL);
if (!clks)
return ERR_PTR(-ENOMEM);
clks = kmalloc_array(num_clks, sizeof(*clks), GFP_KERNEL);
if (!clks) {
ret = -ENOMEM;
goto err_free_psc;
}
psc->clk_data.clks = clks;
psc->clk_data.clk_num = num_clks;
......@@ -396,16 +406,20 @@ __davinci_psc_register_clocks(struct device *dev,
for (i = 0; i < num_clks; i++)
clks[i] = ERR_PTR(-ENOENT);
pm_domains = devm_kcalloc(dev, num_clks, sizeof(*pm_domains), GFP_KERNEL);
if (!pm_domains)
return ERR_PTR(-ENOMEM);
pm_domains = kcalloc(num_clks, sizeof(*pm_domains), GFP_KERNEL);
if (!pm_domains) {
ret = -ENOMEM;
goto err_free_clks;
}
psc->pm_data.domains = pm_domains;
psc->pm_data.num_domains = num_clks;
regmap = devm_regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
if (IS_ERR(regmap))
return ERR_CAST(regmap);
regmap = regmap_init_mmio(dev, base, &davinci_psc_regmap_config);
if (IS_ERR(regmap)) {
ret = PTR_ERR(regmap);
goto err_free_pm_domains;
}
for (; info->name; info++) {
struct davinci_lpsc_clk *lpsc;
......@@ -423,6 +437,13 @@ __davinci_psc_register_clocks(struct device *dev,
pm_domains[info->md] = &lpsc->pm_domain;
}
/*
* for now, a reset controller is only registered when there is a device
* to associate it with.
*/
if (!dev)
return psc;
psc->rcdev.ops = &davinci_psc_reset_ops;
psc->rcdev.owner = THIS_MODULE;
psc->rcdev.dev = dev;
......@@ -436,6 +457,15 @@ __davinci_psc_register_clocks(struct device *dev,
dev_warn(dev, "Failed to register reset controller (%d)\n", ret);
return psc;
err_free_pm_domains:
kfree(pm_domains);
err_free_clks:
kfree(clks);
err_free_psc:
kfree(psc);
return ERR_PTR(ret);
}
int davinci_psc_register_clocks(struct device *dev,
......@@ -483,20 +513,34 @@ int of_davinci_psc_clk_init(struct device *dev,
}
static const struct of_device_id davinci_psc_of_match[] = {
#ifdef CONFIG_ARCH_DAVINCI_DA850
{ .compatible = "ti,da850-psc0", .data = &of_da850_psc0_init_data },
{ .compatible = "ti,da850-psc1", .data = &of_da850_psc1_init_data },
#endif
{ }
};
static const struct platform_device_id davinci_psc_id_table[] = {
#ifdef CONFIG_ARCH_DAVINCI_DA830
{ .name = "da830-psc0", .driver_data = (kernel_ulong_t)&da830_psc0_init_data },
{ .name = "da830-psc1", .driver_data = (kernel_ulong_t)&da830_psc1_init_data },
#endif
#ifdef CONFIG_ARCH_DAVINCI_DA850
{ .name = "da850-psc0", .driver_data = (kernel_ulong_t)&da850_psc0_init_data },
{ .name = "da850-psc1", .driver_data = (kernel_ulong_t)&da850_psc1_init_data },
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM355
{ .name = "dm355-psc", .driver_data = (kernel_ulong_t)&dm355_psc_init_data },
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM365
{ .name = "dm365-psc", .driver_data = (kernel_ulong_t)&dm365_psc_init_data },
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM644x
{ .name = "dm644x-psc", .driver_data = (kernel_ulong_t)&dm644x_psc_init_data },
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM646x
{ .name = "dm646x-psc", .driver_data = (kernel_ulong_t)&dm646x_psc_init_data },
#endif
{ }
};
......
......@@ -94,15 +94,27 @@ struct davinci_psc_init_data {
int (*psc_init)(struct device *dev, void __iomem *base);
};
#ifdef CONFIG_ARCH_DAVINCI_DA830
extern const struct davinci_psc_init_data da830_psc0_init_data;
extern const struct davinci_psc_init_data da830_psc1_init_data;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DA850
extern const struct davinci_psc_init_data da850_psc0_init_data;
extern const struct davinci_psc_init_data da850_psc1_init_data;
extern const struct davinci_psc_init_data of_da850_psc0_init_data;
extern const struct davinci_psc_init_data of_da850_psc1_init_data;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM355
extern const struct davinci_psc_init_data dm355_psc_init_data;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM356
extern const struct davinci_psc_init_data dm365_psc_init_data;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM644x
extern const struct davinci_psc_init_data dm644x_psc_init_data;
#endif
#ifdef CONFIG_ARCH_DAVINCI_DM646x
extern const struct davinci_psc_init_data dm646x_psc_init_data;
#endif
#endif /* __CLK_DAVINCI_PSC_H__ */
......@@ -44,14 +44,17 @@ config RESET_HISI
Build reset controller driver for HiSilicon device chipsets.
config STUB_CLK_HI6220
bool "Hi6220 Stub Clock Driver"
depends on COMMON_CLK_HI6220 && MAILBOX
default ARCH_HISI
bool "Hi6220 Stub Clock Driver" if EXPERT
depends on (COMMON_CLK_HI6220 || COMPILE_TEST)
depends on MAILBOX
default COMMON_CLK_HI6220
help
Build the Hisilicon Hi6220 stub clock driver.
config STUB_CLK_HI3660
bool "Hi3660 Stub Clock Driver"
depends on COMMON_CLK_HI3660 && MAILBOX
bool "Hi3660 Stub Clock Driver" if EXPERT
depends on (COMMON_CLK_HI3660 || COMPILE_TEST)
depends on MAILBOX
default COMMON_CLK_HI3660
help
Build the Hisilicon Hi3660 stub clock driver.
......@@ -186,6 +186,23 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
CLK_SET_RATE_PARENT, 0xbc, 0, 0 },
{ HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",
CLK_SET_RATE_PARENT, 0xbc, 2, 0 },
/* USB3 */
{ HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,
CLK_SET_RATE_PARENT, 0xb0, 0, 0 },
{ HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,
CLK_SET_RATE_PARENT, 0xb0, 4, 0 },
{ HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,
CLK_SET_RATE_PARENT, 0xb0, 3, 0 },
{ HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,
CLK_SET_RATE_PARENT, 0xb0, 2, 0 },
{ HISTB_USB3_BUS_CLK1, "clk_u3_bus1", NULL,
CLK_SET_RATE_PARENT, 0xb0, 16, 0 },
{ HISTB_USB3_UTMI_CLK1, "clk_u3_utmi1", NULL,
CLK_SET_RATE_PARENT, 0xb0, 20, 0 },
{ HISTB_USB3_PIPE_CLK1, "clk_u3_pipe1", NULL,
CLK_SET_RATE_PARENT, 0xb0, 19, 0 },
{ HISTB_USB3_SUSPEND_CLK1, "clk_u3_suspend1", NULL,
CLK_SET_RATE_PARENT, 0xb0, 18, 0 },
};
static struct hisi_clock_data *hi3798cv200_clk_register(
......
......@@ -753,6 +753,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
else
clk[IMX6Q_CLK_ECSPI5] = imx_clk_gate2("ecspi5", "ecspi_root", base + 0x6c, 8);
clk[IMX6QDL_CLK_ENET] = imx_clk_gate2("enet", "ipg", base + 0x6c, 10);
clk[IMX6QDL_CLK_EPIT1] = imx_clk_gate2("epit1", "ipg", base + 0x6c, 12);
clk[IMX6QDL_CLK_EPIT2] = imx_clk_gate2("epit2", "ipg", base + 0x6c, 14);
clk[IMX6QDL_CLK_ESAI_EXTAL] = imx_clk_gate2_shared("esai_extal", "esai_podf", base + 0x6c, 16, &share_count_esai);
clk[IMX6QDL_CLK_ESAI_IPG] = imx_clk_gate2_shared("esai_ipg", "ahb", base + 0x6c, 16, &share_count_esai);
clk[IMX6QDL_CLK_ESAI_MEM] = imx_clk_gate2_shared("esai_mem", "ahb", base + 0x6c, 16, &share_count_esai);
......
......@@ -330,7 +330,7 @@ static void __init imx6sl_clocks_init(struct device_node *ccm_node)
clks[IMX6SL_CLK_PERIPH2] = imx_clk_busy_mux("periph2", base + 0x14, 26, 1, base + 0x48, 3, periph2_sels, ARRAY_SIZE(periph2_sels));
/* name parent_name reg shift width */
clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3);
clks[IMX6SL_CLK_OCRAM_PODF] = imx_clk_busy_divider("ocram_podf", "ocram_sel", base + 0x14, 16, 3, base + 0x48, 0);
clks[IMX6SL_CLK_PERIPH_CLK2_PODF] = imx_clk_divider("periph_clk2_podf", "periph_clk2_sel", base + 0x14, 27, 3);
clks[IMX6SL_CLK_PERIPH2_CLK2_PODF] = imx_clk_divider("periph2_clk2_podf", "periph2_clk2_sel", base + 0x14, 0, 3);
clks[IMX6SL_CLK_IPG] = imx_clk_divider("ipg", "ahb", base + 0x14, 8, 2);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -9,6 +9,7 @@ obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
obj-$(CONFIG_COMMON_CLK_MT2701_AUDSYS) += clk-mt2701-aud.o
obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
obj-$(CONFIG_COMMON_CLK_MT2701_G3DSYS) += clk-mt2701-g3d.o
obj-$(CONFIG_COMMON_CLK_MT2701_HIFSYS) += clk-mt2701-hif.o
obj-$(CONFIG_COMMON_CLK_MT2701_IMGSYS) += clk-mt2701-img.o
obj-$(CONFIG_COMMON_CLK_MT2701_MMSYS) += clk-mt2701-mm.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment