Commit e0a1d139 authored by Stephen Boyd's avatar Stephen Boyd

Merge branches 'clk-spear', 'clk-fract', 'clk-rockchip' and 'clk-imx' into clk-next

 - Debugfs support for fractional divider clk

* clk-spear:
  clk: spear: Fix SSP clock definition on SPEAr600
  clk: spear: Fix CLCD clock definition on SPEAr600

* clk-fract:
  clk: fractional-divider: Regroup inclusions
  clk: fractional-divider: Show numerator and denominator in debugfs
  clk: fractional-divider: Split out clk_fd_get_div() helper

* clk-rockchip:
  clk: rockchip: Fix memory leak in rockchip_clk_register_pll()
  clk: rockchip: add clock controller for the RK3588
  clk: rockchip: add lookup table support
  clk: rockchip: simplify rockchip_clk_add_lookup
  clk: rockchip: allow additional mux options for cpu-clock frequency changes
  clk: rockchip: add pll type for RK3588
  clk: rockchip: add register offset of the cores select parent
  dt-bindings: clock: add rk3588 cru bindings
  dt-bindings: reset: add rk3588 reset definitions
  dt-bindings: clock: add rk3588 clock definitions
  clk: rockchip: use proper crypto0 name on rk3399

* clk-imx:
  clk: imx: rename imx_obtain_fixed_clk_hw() to imx_get_clk_hw_by_name()
  clk: imx8mn: fix imx8mn_enet_phy_sels clocks list
  clk: imx8mn: fix imx8mn_sai2_sels clocks list
  clk: imx: rename video_pll1 to video_pll
  clk: imx: replace osc_hdmi with dummy
  clk: imx8mn: rename vpu_pll to m7_alt_pll
  clk: imx: imxrt1050: add IMXRT1050_CLK_LCDIF_PIX clock gate
  clk: imx: imxrt1050: fix IMXRT1050_CLK_LCDIF_APB offsets
  clk: imx8mp: Add audio shared gate
  dt-bindings: clock: imx8mp: Add ids for the audio shared gate
  clk: imx: pll14xx: Add 320 MHz and 640 MHz entries for PLL146x
  clk: imx93: keep sys ctr clock always on
  clk: imx: keep hsio bus clock always on
  clk: imx93: drop tpm1/3, lpit1/2 clk
  dt-bindings: clock: imx93: drop TPM1/3 LPIT1/2 entry
  clk: imx93: correct enet clock
  clk: imx93: unmap anatop base in error handling path
  clk: imx: imx8mp: add shared clk gate for usb suspend clk
  dt-bindings: clocks: imx8mp: Add ID for usb suspend clock
  clk: imx93: correct the flexspi1 clock setting
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/clock/rockchip,rk3588-cru.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Rockchip rk3588 Family Clock and Reset Control Module
maintainers:
- Elaine Zhang <zhangqing@rock-chips.com>
- Heiko Stuebner <heiko@sntech.de>
description: |
The RK3588 clock controller generates the clock and also implements a reset
controller for SoC peripherals. For example it provides SCLK_UART2 and
PCLK_UART2, as well as SRST_P_UART2 and SRST_S_UART2 for the second UART
module.
Each clock is assigned an identifier and client nodes can use this identifier
to specify the clock which they consume. All available clock and reset IDs
are defined as preprocessor macros in dt-binding headers.
properties:
compatible:
enum:
- rockchip,rk3588-cru
reg:
maxItems: 1
"#clock-cells":
const: 1
"#reset-cells":
const: 1
clocks:
minItems: 2
maxItems: 2
clock-names:
items:
- const: xin24m
- const: xin32k
assigned-clocks: true
assigned-clock-rates: true
rockchip,grf:
$ref: /schemas/types.yaml#/definitions/phandle
description: >
phandle to the syscon managing the "general register files". It is used
for GRF muxes, if missing any muxes present in the GRF will not be
available.
required:
- compatible
- reg
- "#clock-cells"
- "#reset-cells"
additionalProperties: false
examples:
- |
cru: clock-controller@fd7c0000 {
compatible = "rockchip,rk3588-cru";
reg = <0xfd7c0000 0x5c000>;
#clock-cells = <1>;
#reset-cells = <1>;
};
......@@ -38,12 +38,15 @@
* saturated values.
*/
#include <linux/clk-provider.h>
#include <linux/debugfs.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/rational.h>
#include <linux/slab.h>
#include <linux/clk-provider.h>
#include "clk-fractional-divider.h"
......@@ -63,14 +66,12 @@ static inline void clk_fd_writel(struct clk_fractional_divider *fd, u32 val)
writel(val, fd->reg);
}
static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
static void clk_fd_get_div(struct clk_hw *hw, struct u32_fract *fract)
{
struct clk_fractional_divider *fd = to_clk_fd(hw);
unsigned long flags = 0;
unsigned long m, n;
u32 val;
u64 ret;
if (fd->lock)
spin_lock_irqsave(fd->lock, flags);
......@@ -92,11 +93,22 @@ static unsigned long clk_fd_recalc_rate(struct clk_hw *hw,
n++;
}
if (!n || !m)
fract->numerator = m;
fract->denominator = n;
}
static unsigned long clk_fd_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
{
struct u32_fract fract;
u64 ret;
clk_fd_get_div(hw, &fract);
if (!fract.numerator || !fract.denominator)
return parent_rate;
ret = (u64)parent_rate * m;
do_div(ret, n);
ret = (u64)parent_rate * fract.numerator;
do_div(ret, fract.denominator);
return ret;
}
......@@ -183,10 +195,45 @@ static int clk_fd_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
#ifdef CONFIG_DEBUG_FS
static int clk_fd_numerator_get(void *hw, u64 *val)
{
struct u32_fract fract;
clk_fd_get_div(hw, &fract);
*val = fract.numerator;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_numerator_fops, clk_fd_numerator_get, NULL, "%llu\n");
static int clk_fd_denominator_get(void *hw, u64 *val)
{
struct u32_fract fract;
clk_fd_get_div(hw, &fract);
*val = fract.denominator;
return 0;
}
DEFINE_DEBUGFS_ATTRIBUTE(clk_fd_denominator_fops, clk_fd_denominator_get, NULL, "%llu\n");
static void clk_fd_debug_init(struct clk_hw *hw, struct dentry *dentry)
{
debugfs_create_file("numerator", 0444, dentry, hw, &clk_fd_numerator_fops);
debugfs_create_file("denominator", 0444, dentry, hw, &clk_fd_denominator_fops);
}
#endif
const struct clk_ops clk_fractional_divider_ops = {
.recalc_rate = clk_fd_recalc_rate,
.round_rate = clk_fd_round_rate,
.set_rate = clk_fd_set_rate,
#ifdef CONFIG_DEBUG_FS
.debug_init = clk_fd_debug_init,
#endif
};
EXPORT_SYMBOL_GPL(clk_fractional_divider_ops);
......
......@@ -91,12 +91,12 @@ static void __init imx6sll_clocks_init(struct device_node *ccm_node)
hws[IMX6SLL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX6SLL_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
hws[IMX6SLL_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
hws[IMX6SLL_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
hws[IMX6SLL_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
hws[IMX6SLL_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
hws[IMX6SLL_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
hws[IMX6SLL_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
hws[IMX6SLL_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6sll-anatop");
base = of_iomap(np, 0);
......
......@@ -132,16 +132,16 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
hws[IMX6SX_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX6SX_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
hws[IMX6SX_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
hws[IMX6SX_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
hws[IMX6SX_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
hws[IMX6SX_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
hws[IMX6SX_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
hws[IMX6SX_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
hws[IMX6SX_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
/* Clock source from external clock via CLK1/2 PAD */
hws[IMX6SX_CLK_ANACLK1] = imx_obtain_fixed_clk_hw(ccm_node, "anaclk1");
hws[IMX6SX_CLK_ANACLK2] = imx_obtain_fixed_clk_hw(ccm_node, "anaclk2");
hws[IMX6SX_CLK_ANACLK1] = imx_get_clk_hw_by_name(ccm_node, "anaclk1");
hws[IMX6SX_CLK_ANACLK2] = imx_get_clk_hw_by_name(ccm_node, "anaclk2");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop");
base = of_iomap(np, 0);
......
......@@ -126,12 +126,12 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
hws[IMX6UL_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX6UL_CLK_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
hws[IMX6UL_CLK_OSC] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
hws[IMX6UL_CLK_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
hws[IMX6UL_CLK_OSC] = imx_get_clk_hw_by_name(ccm_node, "osc");
/* ipp_di clock is external input */
hws[IMX6UL_CLK_IPP_DI0] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di0");
hws[IMX6UL_CLK_IPP_DI1] = imx_obtain_fixed_clk_hw(ccm_node, "ipp_di1");
hws[IMX6UL_CLK_IPP_DI0] = imx_get_clk_hw_by_name(ccm_node, "ipp_di0");
hws[IMX6UL_CLK_IPP_DI1] = imx_get_clk_hw_by_name(ccm_node, "ipp_di1");
np = of_find_compatible_node(NULL, NULL, "fsl,imx6ul-anatop");
base = of_iomap(np, 0);
......
......@@ -391,8 +391,8 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
hws = clk_hw_data->hws;
hws[IMX7D_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX7D_OSC_24M_CLK] = imx_obtain_fixed_clk_hw(ccm_node, "osc");
hws[IMX7D_CKIL] = imx_obtain_fixed_clk_hw(ccm_node, "ckil");
hws[IMX7D_OSC_24M_CLK] = imx_get_clk_hw_by_name(ccm_node, "osc");
hws[IMX7D_CKIL] = imx_get_clk_hw_by_name(ccm_node, "ckil");
np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
base = of_iomap(np, 0);
......
......@@ -59,11 +59,11 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
hws[IMX7ULP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX7ULP_CLK_ROSC] = imx_obtain_fixed_clk_hw(np, "rosc");
hws[IMX7ULP_CLK_SOSC] = imx_obtain_fixed_clk_hw(np, "sosc");
hws[IMX7ULP_CLK_SIRC] = imx_obtain_fixed_clk_hw(np, "sirc");
hws[IMX7ULP_CLK_FIRC] = imx_obtain_fixed_clk_hw(np, "firc");
hws[IMX7ULP_CLK_UPLL] = imx_obtain_fixed_clk_hw(np, "upll");
hws[IMX7ULP_CLK_ROSC] = imx_get_clk_hw_by_name(np, "rosc");
hws[IMX7ULP_CLK_SOSC] = imx_get_clk_hw_by_name(np, "sosc");
hws[IMX7ULP_CLK_SIRC] = imx_get_clk_hw_by_name(np, "sirc");
hws[IMX7ULP_CLK_FIRC] = imx_get_clk_hw_by_name(np, "firc");
hws[IMX7ULP_CLK_UPLL] = imx_get_clk_hw_by_name(np, "upll");
/* SCG1 */
base = of_iomap(np, 0);
......
......@@ -312,12 +312,12 @@ static int imx8mm_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MM_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX8MM_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
hws[IMX8MM_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
hws[IMX8MM_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
hws[IMX8MM_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
hws[IMX8MM_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
hws[IMX8MM_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
hws[IMX8MM_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
hws[IMX8MM_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
hws[IMX8MM_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
hws[IMX8MM_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
hws[IMX8MM_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
hws[IMX8MM_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
base = of_iomap(np, 0);
......
This diff is collapsed.
......@@ -17,6 +17,8 @@
static u32 share_count_nand;
static u32 share_count_media;
static u32 share_count_usb;
static u32 share_count_audio;
static const char * const pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
......@@ -436,12 +438,12 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MP_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX8MP_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
hws[IMX8MP_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
hws[IMX8MP_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
hws[IMX8MP_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
hws[IMX8MP_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
hws[IMX8MP_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
hws[IMX8MP_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
hws[IMX8MP_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
hws[IMX8MP_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
hws[IMX8MP_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
hws[IMX8MP_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
hws[IMX8MP_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
hws[IMX8MP_AUDIO_PLL1_REF_SEL] = imx_clk_hw_mux("audio_pll1_ref_sel", anatop_base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
hws[IMX8MP_AUDIO_PLL2_REF_SEL] = imx_clk_hw_mux("audio_pll2_ref_sel", anatop_base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
......@@ -673,7 +675,8 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_UART2_ROOT] = imx_clk_hw_gate4("uart2_root_clk", "uart2", ccm_base + 0x44a0, 0);
hws[IMX8MP_CLK_UART3_ROOT] = imx_clk_hw_gate4("uart3_root_clk", "uart3", ccm_base + 0x44b0, 0);
hws[IMX8MP_CLK_UART4_ROOT] = imx_clk_hw_gate4("uart4_root_clk", "uart4", ccm_base + 0x44c0, 0);
hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate4("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0);
hws[IMX8MP_CLK_USB_ROOT] = imx_clk_hw_gate2_shared2("usb_root_clk", "hsio_axi", ccm_base + 0x44d0, 0, &share_count_usb);
hws[IMX8MP_CLK_USB_SUSP] = imx_clk_hw_gate2_shared2("usb_suspend_clk", "osc_32k", ccm_base + 0x44d0, 0, &share_count_usb);
hws[IMX8MP_CLK_USB_PHY_ROOT] = imx_clk_hw_gate4("usb_phy_root_clk", "usb_phy_ref", ccm_base + 0x44f0, 0);
hws[IMX8MP_CLK_USDHC1_ROOT] = imx_clk_hw_gate4("usdhc1_root_clk", "usdhc1", ccm_base + 0x4510, 0);
hws[IMX8MP_CLK_USDHC2_ROOT] = imx_clk_hw_gate4("usdhc2_root_clk", "usdhc2", ccm_base + 0x4520, 0);
......@@ -699,7 +702,16 @@ static int imx8mp_clocks_probe(struct platform_device *pdev)
hws[IMX8MP_CLK_HDMI_ROOT] = imx_clk_hw_gate4("hdmi_root_clk", "hdmi_axi", ccm_base + 0x45f0, 0);
hws[IMX8MP_CLK_TSENSOR_ROOT] = imx_clk_hw_gate4("tsensor_root_clk", "ipg_root", ccm_base + 0x4620, 0);
hws[IMX8MP_CLK_VPU_ROOT] = imx_clk_hw_gate4("vpu_root_clk", "vpu_bus", ccm_base + 0x4630, 0);
hws[IMX8MP_CLK_AUDIO_ROOT] = imx_clk_hw_gate4("audio_root_clk", "audio_ahb", ccm_base + 0x4650, 0);
hws[IMX8MP_CLK_AUDIO_AHB_ROOT] = imx_clk_hw_gate2_shared2("audio_ahb_root", "audio_ahb", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_AUDIO_AXI_ROOT] = imx_clk_hw_gate2_shared2("audio_axi_root", "audio_axi", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI1_ROOT] = imx_clk_hw_gate2_shared2("sai1_root", "sai1", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI2_ROOT] = imx_clk_hw_gate2_shared2("sai2_root", "sai2", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI3_ROOT] = imx_clk_hw_gate2_shared2("sai3_root", "sai3", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI5_ROOT] = imx_clk_hw_gate2_shared2("sai5_root", "sai5", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI6_ROOT] = imx_clk_hw_gate2_shared2("sai6_root", "sai6", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_SAI7_ROOT] = imx_clk_hw_gate2_shared2("sai7_root", "sai7", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_PDM_ROOT] = imx_clk_hw_gate2_shared2("pdm_root", "pdm", ccm_base + 0x4650, 0, &share_count_audio);
hws[IMX8MP_CLK_ARM] = imx_clk_hw_cpu("arm", "arm_a53_core",
hws[IMX8MP_CLK_A53_CORE]->clk,
......
......@@ -297,13 +297,13 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
hws = clk_hw_data->hws;
hws[IMX8MQ_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
hws[IMX8MQ_CLK_32K] = imx_obtain_fixed_clk_hw(np, "ckil");
hws[IMX8MQ_CLK_25M] = imx_obtain_fixed_clk_hw(np, "osc_25m");
hws[IMX8MQ_CLK_27M] = imx_obtain_fixed_clk_hw(np, "osc_27m");
hws[IMX8MQ_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
hws[IMX8MQ_CLK_EXT2] = imx_obtain_fixed_clk_hw(np, "clk_ext2");
hws[IMX8MQ_CLK_EXT3] = imx_obtain_fixed_clk_hw(np, "clk_ext3");
hws[IMX8MQ_CLK_EXT4] = imx_obtain_fixed_clk_hw(np, "clk_ext4");
hws[IMX8MQ_CLK_32K] = imx_get_clk_hw_by_name(np, "ckil");
hws[IMX8MQ_CLK_25M] = imx_get_clk_hw_by_name(np, "osc_25m");
hws[IMX8MQ_CLK_27M] = imx_get_clk_hw_by_name(np, "osc_27m");
hws[IMX8MQ_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
hws[IMX8MQ_CLK_EXT2] = imx_get_clk_hw_by_name(np, "clk_ext2");
hws[IMX8MQ_CLK_EXT3] = imx_get_clk_hw_by_name(np, "clk_ext3");
hws[IMX8MQ_CLK_EXT4] = imx_get_clk_hw_by_name(np, "clk_ext4");
np = of_find_compatible_node(NULL, NULL, "fsl,imx8mq-anatop");
base = of_iomap(np, 0);
......
......@@ -64,13 +64,9 @@ static const struct imx93_clk_root {
{ IMX93_CLK_M33_SYSTICK, "m33_systick_root", 0x0480, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_FLEXIO1, "flexio1_root", 0x0500, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_FLEXIO2, "flexio2_root", 0x0580, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPIT1, "lpit1_root", 0x0600, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPIT2, "lpit2_root", 0x0680, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPTMR1, "lptmr1_root", 0x0700, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_LPTMR2, "lptmr2_root", 0x0780, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_TPM1, "tpm1_root", 0x0800, TPM_SEL, },
{ IMX93_CLK_TPM2, "tpm2_root", 0x0880, TPM_SEL, },
{ IMX93_CLK_TPM3, "tpm3_root", 0x0900, TPM_SEL, },
{ IMX93_CLK_TPM4, "tpm4_root", 0x0980, TPM_SEL, },
{ IMX93_CLK_TPM5, "tpm5_root", 0x0a00, TPM_SEL, },
{ IMX93_CLK_TPM6, "tpm6_root", 0x0a80, TPM_SEL, },
......@@ -113,7 +109,11 @@ static const struct imx93_clk_root {
{ IMX93_CLK_CCM_CKO2, "ccm_cko2_root", 0x1d00, CKO2_SEL, },
{ IMX93_CLK_CCM_CKO3, "ccm_cko3_root", 0x1d80, CKO1_SEL, },
{ IMX93_CLK_CCM_CKO4, "ccm_cko4_root", 0x1e00, CKO2_SEL, },
{ IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, },
/*
* Critical because clk is used for handshake between HSIOMIX and NICMIX when
* NICMIX power down/on during system suspend/resume
*/
{ IMX93_CLK_HSIO, "hsio_root", 0x1e80, LOW_SPEED_IO_SEL, CLK_IS_CRITICAL},
{ IMX93_CLK_HSIO_USB_TEST_60M, "hsio_usb_test_60m_root", 0x1f00, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_80M, "hsio_acscan_80m_root", 0x1f80, LOW_SPEED_IO_SEL, },
{ IMX93_CLK_HSIO_ACSCAN_480M, "hsio_acscan_480m_root", 0x2000, MISC_SEL, },
......@@ -170,20 +170,20 @@ static const struct imx93_clk_ccgr {
{ IMX93_CLK_MU2_B_GATE, "mu2_b", "bus_wakeup_root", 0x8500, 0, &share_count_mub },
{ IMX93_CLK_EDMA1_GATE, "edma1", "m33_root", 0x8540, },
{ IMX93_CLK_EDMA2_GATE, "edma2", "wakeup_axi_root", 0x8580, },
{ IMX93_CLK_FLEXSPI1_GATE, "flexspi", "flexspi_root", 0x8640, },
{ IMX93_CLK_FLEXSPI1_GATE, "flexspi1", "flexspi1_root", 0x8640, },
{ IMX93_CLK_GPIO1_GATE, "gpio1", "m33_root", 0x8880, },
{ IMX93_CLK_GPIO2_GATE, "gpio2", "bus_wakeup_root", 0x88c0, },
{ IMX93_CLK_GPIO3_GATE, "gpio3", "bus_wakeup_root", 0x8900, },
{ IMX93_CLK_GPIO4_GATE, "gpio4", "bus_wakeup_root", 0x8940, },
{ IMX93_CLK_FLEXIO1_GATE, "flexio1", "flexio1_root", 0x8980, },
{ IMX93_CLK_FLEXIO2_GATE, "flexio2", "flexio2_root", 0x89c0, },
{ IMX93_CLK_LPIT1_GATE, "lpit1", "lpit1_root", 0x8a00, },
{ IMX93_CLK_LPIT2_GATE, "lpit2", "lpit2_root", 0x8a40, },
{ IMX93_CLK_LPIT1_GATE, "lpit1", "bus_aon_root", 0x8a00, },
{ IMX93_CLK_LPIT2_GATE, "lpit2", "bus_wakeup_root", 0x8a40, },
{ IMX93_CLK_LPTMR1_GATE, "lptmr1", "lptmr1_root", 0x8a80, },
{ IMX93_CLK_LPTMR2_GATE, "lptmr2", "lptmr2_root", 0x8ac0, },
{ IMX93_CLK_TPM1_GATE, "tpm1", "tpm1_root", 0x8b00, },
{ IMX93_CLK_TPM1_GATE, "tpm1", "bus_aon_root", 0x8b00, },
{ IMX93_CLK_TPM2_GATE, "tpm2", "tpm2_root", 0x8b40, },
{ IMX93_CLK_TPM3_GATE, "tpm3", "tpm3_root", 0x8b80, },
{ IMX93_CLK_TPM3_GATE, "tpm3", "bus_wakeup_root", 0x8b80, },
{ IMX93_CLK_TPM4_GATE, "tpm4", "tpm4_root", 0x8bc0, },
{ IMX93_CLK_TPM5_GATE, "tpm5", "tpm5_root", 0x8c00, },
{ IMX93_CLK_TPM6_GATE, "tpm6", "tpm6_root", 0x8c40, },
......@@ -240,9 +240,10 @@ static const struct imx93_clk_ccgr {
{ IMX93_CLK_AUD_XCVR_GATE, "aud_xcvr", "audio_xcvr_root", 0x9b80, },
{ IMX93_CLK_SPDIF_GATE, "spdif", "spdif_root", 0x9c00, },
{ IMX93_CLK_HSIO_32K_GATE, "hsio_32k", "osc_32k", 0x9dc0, },
{ IMX93_CLK_ENET1_GATE, "enet1", "enet_root", 0x9e00, },
{ IMX93_CLK_ENET1_GATE, "enet1", "wakeup_axi_root", 0x9e00, },
{ IMX93_CLK_ENET_QOS_GATE, "enet_qos", "wakeup_axi_root", 0x9e40, },
{ IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, },
/* Critical because clk accessed during CPU idle */
{ IMX93_CLK_SYS_CNT_GATE, "sys_cnt", "osc_24m", 0x9e80, CLK_IS_CRITICAL},
{ IMX93_CLK_TSTMR1_GATE, "tstmr1", "bus_aon_root", 0x9ec0, },
{ IMX93_CLK_TSTMR2_GATE, "tstmr2", "bus_wakeup_root", 0x9f00, },
{ IMX93_CLK_TMC_GATE, "tmc", "osc_24m", 0x9f40, },
......@@ -258,7 +259,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
struct device_node *np = dev->of_node;
const struct imx93_clk_root *root;
const struct imx93_clk_ccgr *ccgr;
void __iomem *base = NULL;
void __iomem *base, *anatop_base;
int i, ret;
clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
......@@ -270,9 +271,9 @@ static int imx93_clocks_probe(struct platform_device *pdev)
clks = clk_hw_data->hws;
clks[IMX93_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0);
clks[IMX93_CLK_24M] = imx_obtain_fixed_clk_hw(np, "osc_24m");
clks[IMX93_CLK_32K] = imx_obtain_fixed_clk_hw(np, "osc_32k");
clks[IMX93_CLK_EXT1] = imx_obtain_fixed_clk_hw(np, "clk_ext1");
clks[IMX93_CLK_24M] = imx_get_clk_hw_by_name(np, "osc_24m");
clks[IMX93_CLK_32K] = imx_get_clk_hw_by_name(np, "osc_32k");
clks[IMX93_CLK_EXT1] = imx_get_clk_hw_by_name(np, "clk_ext1");
clks[IMX93_CLK_SYS_PLL_PFD0] = imx_clk_hw_fixed("sys_pll_pfd0", 1000000000);
clks[IMX93_CLK_SYS_PLL_PFD0_DIV2] = imx_clk_hw_fixed_factor("sys_pll_pfd0_div2",
......@@ -285,20 +286,22 @@ static int imx93_clocks_probe(struct platform_device *pdev)
"sys_pll_pfd2", 1, 2);
np = of_find_compatible_node(NULL, NULL, "fsl,imx93-anatop");
base = of_iomap(np, 0);
anatop_base = of_iomap(np, 0);
of_node_put(np);
if (WARN_ON(!base))
if (WARN_ON(!anatop_base))
return -ENOMEM;
clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", base + 0x1200,
clks[IMX93_CLK_AUDIO_PLL] = imx_clk_fracn_gppll("audio_pll", "osc_24m", anatop_base + 0x1200,
&imx_fracn_gppll);
clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", base + 0x1400,
clks[IMX93_CLK_VIDEO_PLL] = imx_clk_fracn_gppll("video_pll", "osc_24m", anatop_base + 0x1400,
&imx_fracn_gppll);
np = dev->of_node;
base = devm_platform_ioremap_resource(pdev, 0);
if (WARN_ON(IS_ERR(base)))
if (WARN_ON(IS_ERR(base))) {
iounmap(anatop_base);
return PTR_ERR(base);
}
for (i = 0; i < ARRAY_SIZE(root_array); i++) {
root = &root_array[i];
......@@ -327,6 +330,7 @@ static int imx93_clocks_probe(struct platform_device *pdev)
unregister_hws:
imx_unregister_hw_clocks(clks, IMX93_CLK_END);
iounmap(anatop_base);
return ret;
}
......
......@@ -50,7 +50,7 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
clk_hw_data->num = IMXRT1050_CLK_END;
hws = clk_hw_data->hws;
hws[IMXRT1050_CLK_OSC] = imx_obtain_fixed_clk_hw(np, "osc");
hws[IMXRT1050_CLK_OSC] = imx_get_clk_hw_by_name(np, "osc");
anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
pll_base = of_iomap(anp, 0);
......@@ -140,7 +140,8 @@ static int imxrt1050_clocks_probe(struct platform_device *pdev)
hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2);
hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4);
hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24);
hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10);
hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x70, 28);
hws[IMXRT1050_CLK_LCDIF_PIX] = imx_clk_hw_gate2("lcdif_pix", "lcdif", ccm_base + 0x74, 10);
hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6);
hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7);
imx_check_clk_hws(hws, IMXRT1050_CLK_END);
......
......@@ -54,7 +54,9 @@ static const struct imx_pll14xx_rate_table imx_pll1416x_tbl[] = {
PLL_1416X_RATE(800000000U, 200, 3, 1),
PLL_1416X_RATE(750000000U, 250, 2, 2),
PLL_1416X_RATE(700000000U, 350, 3, 2),
PLL_1416X_RATE(640000000U, 320, 3, 2),
PLL_1416X_RATE(600000000U, 300, 3, 2),
PLL_1416X_RATE(320000000U, 160, 3, 2),
};
static const struct imx_pll14xx_rate_table imx_pll1443x_tbl[] = {
......
......@@ -110,8 +110,7 @@ struct clk_hw *imx_obtain_fixed_clock_hw(
return __clk_get_hw(clk);
}
struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
const char *name)
struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name)
{
struct clk *clk;
......@@ -121,7 +120,7 @@ struct clk_hw * imx_obtain_fixed_clk_hw(struct device_node *np,
return __clk_get_hw(clk);
}
EXPORT_SYMBOL_GPL(imx_obtain_fixed_clk_hw);
EXPORT_SYMBOL_GPL(imx_get_clk_hw_by_name);
/*
* This fixups the register CCM_CSCMR1 write value.
......
......@@ -288,8 +288,7 @@ struct clk * imx_obtain_fixed_clock(
struct clk_hw *imx_obtain_fixed_clock_hw(
const char *name, unsigned long rate);
struct clk_hw *imx_obtain_fixed_clk_hw(struct device_node *np,
const char *name);
struct clk_hw *imx_get_clk_hw_by_name(struct device_node *np, const char *name);
struct clk_hw *imx_clk_hw_gate_exclusive(const char *name, const char *parent,
void __iomem *reg, u8 shift, u32 exclusive_mask);
......
......@@ -99,4 +99,12 @@ config CLK_RK3568
default y
help
Build the driver for RK3568 Clock Driver.
config CLK_RK3588
bool "Rockchip RK3588 clock controller support"
depends on ARM64 || COMPILE_TEST
default y
help
Build the driver for RK3588 Clock Driver.
endif
......@@ -28,3 +28,4 @@ obj-$(CONFIG_CLK_RK3328) += clk-rk3328.o
obj-$(CONFIG_CLK_RK3368) += clk-rk3368.o
obj-$(CONFIG_CLK_RK3399) += clk-rk3399.o
obj-$(CONFIG_CLK_RK3568) += clk-rk3568.o
obj-$(CONFIG_CLK_RK3588) += clk-rk3588.o rst-rk3588.o
......@@ -113,6 +113,42 @@ static void rockchip_cpuclk_set_dividers(struct rockchip_cpuclk *cpuclk,
}
}
static void rockchip_cpuclk_set_pre_muxs(struct rockchip_cpuclk *cpuclk,
const struct rockchip_cpuclk_rate_table *rate)
{
int i;
/* alternate parent is active now. set the pre_muxs */
for (i = 0; i < ARRAY_SIZE(rate->pre_muxs); i++) {
const struct rockchip_cpuclk_clksel *clksel = &rate->pre_muxs[i];
if (!clksel->reg)
break;
pr_debug("%s: setting reg 0x%x to 0x%x\n",
__func__, clksel->reg, clksel->val);
writel(clksel->val, cpuclk->reg_base + clksel->reg);
}
}
static void rockchip_cpuclk_set_post_muxs(struct rockchip_cpuclk *cpuclk,
const struct rockchip_cpuclk_rate_table *rate)
{
int i;
/* alternate parent is active now. set the muxs */
for (i = 0; i < ARRAY_SIZE(rate->post_muxs); i++) {
const struct rockchip_cpuclk_clksel *clksel = &rate->post_muxs[i];
if (!clksel->reg)
break;
pr_debug("%s: setting reg 0x%x to 0x%x\n",
__func__, clksel->reg, clksel->val);
writel(clksel->val, cpuclk->reg_base + clksel->reg);
}
}
static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
struct clk_notifier_data *ndata)
{
......@@ -165,11 +201,20 @@ static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk,
cpuclk->reg_base + reg_data->core_reg[i]);
}
}
rockchip_cpuclk_set_pre_muxs(cpuclk, rate);
/* select alternate parent */
writel(HIWORD_UPDATE(reg_data->mux_core_alt,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->core_reg[0]);
if (reg_data->mux_core_reg)
writel(HIWORD_UPDATE(reg_data->mux_core_alt,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->mux_core_reg);
else
writel(HIWORD_UPDATE(reg_data->mux_core_alt,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->core_reg[0]);
spin_unlock_irqrestore(cpuclk->lock, flags);
return 0;
......@@ -202,10 +247,18 @@ static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk,
* primary parent by the extra dividers that were needed for the alt.
*/
writel(HIWORD_UPDATE(reg_data->mux_core_main,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->core_reg[0]);
if (reg_data->mux_core_reg)
writel(HIWORD_UPDATE(reg_data->mux_core_main,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->mux_core_reg);
else
writel(HIWORD_UPDATE(reg_data->mux_core_main,
reg_data->mux_core_mask,
reg_data->mux_core_shift),
cpuclk->reg_base + reg_data->core_reg[0]);
rockchip_cpuclk_set_post_muxs(cpuclk, rate);
/* remove dividers */
for (i = 0; i < reg_data->num_cores; i++) {
......
......@@ -842,6 +842,213 @@ static const struct clk_ops rockchip_rk3399_pll_clk_ops = {
.init = rockchip_rk3399_pll_init,
};
/*
* PLL used in RK3588
*/
#define RK3588_PLLCON(i) (i * 0x4)
#define RK3588_PLLCON0_M_MASK 0x3ff
#define RK3588_PLLCON0_M_SHIFT 0
#define RK3588_PLLCON1_P_MASK 0x3f
#define RK3588_PLLCON1_P_SHIFT 0
#define RK3588_PLLCON1_S_MASK 0x7
#define RK3588_PLLCON1_S_SHIFT 6
#define RK3588_PLLCON2_K_MASK 0xffff
#define RK3588_PLLCON2_K_SHIFT 0
#define RK3588_PLLCON1_PWRDOWN BIT(13)
#define RK3588_PLLCON6_LOCK_STATUS BIT(15)
static int rockchip_rk3588_pll_wait_lock(struct rockchip_clk_pll *pll)
{
u32 pllcon;
int ret;
/*
* Lock time typical 250, max 500 input clock cycles @24MHz
* So define a very safe maximum of 1000us, meaning 24000 cycles.
*/
ret = readl_relaxed_poll_timeout(pll->reg_base + RK3588_PLLCON(6),
pllcon,
pllcon & RK3588_PLLCON6_LOCK_STATUS,
0, 1000);
if (ret)
pr_err("%s: timeout waiting for pll to lock\n", __func__);
return ret;
}
static void rockchip_rk3588_pll_get_params(struct rockchip_clk_pll *pll,
struct rockchip_pll_rate_table *rate)
{
u32 pllcon;
pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(0));
rate->m = ((pllcon >> RK3588_PLLCON0_M_SHIFT) & RK3588_PLLCON0_M_MASK);
pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(1));
rate->p = ((pllcon >> RK3588_PLLCON1_P_SHIFT) & RK3588_PLLCON1_P_MASK);
rate->s = ((pllcon >> RK3588_PLLCON1_S_SHIFT) & RK3588_PLLCON1_S_MASK);
pllcon = readl_relaxed(pll->reg_base + RK3588_PLLCON(2));
rate->k = ((pllcon >> RK3588_PLLCON2_K_SHIFT) & RK3588_PLLCON2_K_MASK);
}
static unsigned long rockchip_rk3588_pll_recalc_rate(struct clk_hw *hw, unsigned long prate)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
struct rockchip_pll_rate_table cur;
u64 rate64 = prate, postdiv;
rockchip_rk3588_pll_get_params(pll, &cur);
rate64 *= cur.m;
do_div(rate64, cur.p);
if (cur.k) {
/* fractional mode */
u64 frac_rate64 = prate * cur.k;
postdiv = cur.p * 65535;
do_div(frac_rate64, postdiv);
rate64 += frac_rate64;
}
rate64 = rate64 >> cur.s;
return (unsigned long)rate64;
}
static int rockchip_rk3588_pll_set_params(struct rockchip_clk_pll *pll,
const struct rockchip_pll_rate_table *rate)
{
const struct clk_ops *pll_mux_ops = pll->pll_mux_ops;
struct clk_mux *pll_mux = &pll->pll_mux;
struct rockchip_pll_rate_table cur;
int rate_change_remuxed = 0;
int cur_parent;
int ret;
pr_debug("%s: rate settings for %lu p: %d, m: %d, s: %d, k: %d\n",
__func__, rate->rate, rate->p, rate->m, rate->s, rate->k);
rockchip_rk3588_pll_get_params(pll, &cur);
cur.rate = 0;
if (pll->type == pll_rk3588) {
cur_parent = pll_mux_ops->get_parent(&pll_mux->hw);
if (cur_parent == PLL_MODE_NORM) {
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW);
rate_change_remuxed = 1;
}
}
/* set pll power down */
writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN,
RK3588_PLLCON1_PWRDOWN, 0),
pll->reg_base + RK3399_PLLCON(1));
/* update pll values */
writel_relaxed(HIWORD_UPDATE(rate->m, RK3588_PLLCON0_M_MASK, RK3588_PLLCON0_M_SHIFT),
pll->reg_base + RK3399_PLLCON(0));
writel_relaxed(HIWORD_UPDATE(rate->p, RK3588_PLLCON1_P_MASK, RK3588_PLLCON1_P_SHIFT) |
HIWORD_UPDATE(rate->s, RK3588_PLLCON1_S_MASK, RK3588_PLLCON1_S_SHIFT),
pll->reg_base + RK3399_PLLCON(1));
writel_relaxed(HIWORD_UPDATE(rate->k, RK3588_PLLCON2_K_MASK, RK3588_PLLCON2_K_SHIFT),
pll->reg_base + RK3399_PLLCON(2));
/* set pll power up */
writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
pll->reg_base + RK3588_PLLCON(1));
/* wait for the pll to lock */
ret = rockchip_rk3588_pll_wait_lock(pll);
if (ret) {
pr_warn("%s: pll update unsuccessful, trying to restore old params\n",
__func__);
rockchip_rk3588_pll_set_params(pll, &cur);
}
if ((pll->type == pll_rk3588) && rate_change_remuxed)
pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM);
return ret;
}
static int rockchip_rk3588_pll_set_rate(struct clk_hw *hw, unsigned long drate,
unsigned long prate)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
const struct rockchip_pll_rate_table *rate;
pr_debug("%s: changing %s to %lu with a parent rate of %lu\n",
__func__, __clk_get_name(hw->clk), drate, prate);
/* Get required rate settings from table */
rate = rockchip_get_pll_settings(pll, drate);
if (!rate) {
pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
drate, __clk_get_name(hw->clk));
return -EINVAL;
}
return rockchip_rk3588_pll_set_params(pll, rate);
}
static int rockchip_rk3588_pll_enable(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
writel(HIWORD_UPDATE(0, RK3588_PLLCON1_PWRDOWN, 0),
pll->reg_base + RK3588_PLLCON(1));
rockchip_rk3588_pll_wait_lock(pll);
return 0;
}
static void rockchip_rk3588_pll_disable(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
writel(HIWORD_UPDATE(RK3588_PLLCON1_PWRDOWN, RK3588_PLLCON1_PWRDOWN, 0),
pll->reg_base + RK3588_PLLCON(1));
}
static int rockchip_rk3588_pll_is_enabled(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
u32 pllcon = readl(pll->reg_base + RK3588_PLLCON(1));
return !(pllcon & RK3588_PLLCON1_PWRDOWN);
}
static int rockchip_rk3588_pll_init(struct clk_hw *hw)
{
struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw);
if (!(pll->flags & ROCKCHIP_PLL_SYNC_RATE))
return 0;
return 0;
}
static const struct clk_ops rockchip_rk3588_pll_clk_norate_ops = {
.recalc_rate = rockchip_rk3588_pll_recalc_rate,
.enable = rockchip_rk3588_pll_enable,
.disable = rockchip_rk3588_pll_disable,
.is_enabled = rockchip_rk3588_pll_is_enabled,
};
static const struct clk_ops rockchip_rk3588_pll_clk_ops = {
.recalc_rate = rockchip_rk3588_pll_recalc_rate,
.round_rate = rockchip_pll_round_rate,
.set_rate = rockchip_rk3588_pll_set_rate,
.enable = rockchip_rk3588_pll_enable,
.disable = rockchip_rk3588_pll_disable,
.is_enabled = rockchip_rk3588_pll_is_enabled,
.init = rockchip_rk3588_pll_init,
};
/*
* Common registering of pll clocks
*/
......@@ -890,7 +1097,8 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
if (pll_type == pll_rk3036 ||
pll_type == pll_rk3066 ||
pll_type == pll_rk3328 ||
pll_type == pll_rk3399)
pll_type == pll_rk3399 ||
pll_type == pll_rk3588)
pll_mux->flags |= CLK_MUX_HIWORD_MASK;
/* the actual muxing is xin24m, pll-output, xin32k */
......@@ -957,6 +1165,14 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
else
init.ops = &rockchip_rk3399_pll_clk_ops;
break;
case pll_rk3588:
case pll_rk3588_core:
if (!pll->rate_table)
init.ops = &rockchip_rk3588_pll_clk_norate_ops;
else
init.ops = &rockchip_rk3588_pll_clk_ops;
init.flags = flags;
break;
default:
pr_warn("%s: Unknown pll type for pll clk %s\n",
__func__, name);
......@@ -981,6 +1197,7 @@ struct clk *rockchip_clk_register_pll(struct rockchip_clk_provider *ctx,
return mux_clk;
err_pll:
kfree(pll->rate_table);
clk_unregister(mux_clk);
mux_clk = pll_clk;
err_mux:
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -197,6 +197,12 @@ static void rockchip_fractional_approximation(struct clk_hw *hw,
clk_fractional_divider_general_approximation(hw, rate, parent_rate, m, n);
}
static void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
struct clk *clk, unsigned int id)
{
ctx->clk_data.clks[id] = clk;
}
static struct clk *rockchip_clk_register_frac_branch(
struct rockchip_clk_provider *ctx, const char *name,
const char *const *parent_names, u8 num_parents,
......@@ -400,14 +406,6 @@ void rockchip_clk_of_add_provider(struct device_node *np,
}
EXPORT_SYMBOL_GPL(rockchip_clk_of_add_provider);
void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
struct clk *clk, unsigned int id)
{
if (ctx->clk_data.clks && id)
ctx->clk_data.clks[id] = clk;
}
EXPORT_SYMBOL_GPL(rockchip_clk_add_lookup);
void rockchip_clk_register_plls(struct rockchip_clk_provider *ctx,
struct rockchip_pll_clock *list,
unsigned int nr_pll, int grf_lock_offset)
......
......@@ -235,11 +235,58 @@ struct clk;
#define RK3568_PMU_CLKGATE_CON(x) ((x) * 0x4 + 0x180)
#define RK3568_PMU_SOFTRST_CON(x) ((x) * 0x4 + 0x200)
#define RK3588_PHP_CRU_BASE 0x8000
#define RK3588_PMU_CRU_BASE 0x30000
#define RK3588_BIGCORE0_CRU_BASE 0x50000
#define RK3588_BIGCORE1_CRU_BASE 0x52000
#define RK3588_DSU_CRU_BASE 0x58000
#define RK3588_PLL_CON(x) RK2928_PLL_CON(x)
#define RK3588_MODE_CON0 0x280
#define RK3588_B0_PLL_MODE_CON0 (RK3588_BIGCORE0_CRU_BASE + 0x280)
#define RK3588_B1_PLL_MODE_CON0 (RK3588_BIGCORE1_CRU_BASE + 0x280)
#define RK3588_LPLL_MODE_CON0 (RK3588_DSU_CRU_BASE + 0x280)
#define RK3588_CLKSEL_CON(x) ((x) * 0x4 + 0x300)
#define RK3588_CLKGATE_CON(x) ((x) * 0x4 + 0x800)
#define RK3588_SOFTRST_CON(x) ((x) * 0x4 + 0xa00)
#define RK3588_GLB_CNT_TH 0xc00
#define RK3588_GLB_SRST_FST 0xc08
#define RK3588_GLB_SRST_SND 0xc0c
#define RK3588_GLB_RST_CON 0xc10
#define RK3588_GLB_RST_ST 0xc04
#define RK3588_SDIO_CON0 0xC24
#define RK3588_SDIO_CON1 0xC28
#define RK3588_SDMMC_CON0 0xC30
#define RK3588_SDMMC_CON1 0xC34
#define RK3588_PHP_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0x800)
#define RK3588_PHP_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE + 0xa00)
#define RK3588_PMU_PLL_CON(x) ((x) * 0x4 + RK3588_PHP_CRU_BASE)
#define RK3588_PMU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x300)
#define RK3588_PMU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0x800)
#define RK3588_PMU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_PMU_CRU_BASE + 0xa00)
#define RK3588_B0_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE)
#define RK3588_BIGCORE0_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x300)
#define RK3588_BIGCORE0_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0x800)
#define RK3588_BIGCORE0_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE0_CRU_BASE + 0xa00)
#define RK3588_B1_PLL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE)
#define RK3588_BIGCORE1_CLKSEL_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x300)
#define RK3588_BIGCORE1_CLKGATE_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0x800)
#define RK3588_BIGCORE1_SOFTRST_CON(x) ((x) * 0x4 + RK3588_BIGCORE1_CRU_BASE + 0xa00)
#define RK3588_LPLL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE)
#define RK3588_DSU_CLKSEL_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x300)
#define RK3588_DSU_CLKGATE_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0x800)
#define RK3588_DSU_SOFTRST_CON(x) ((x) * 0x4 + RK3588_DSU_CRU_BASE + 0xa00)
enum rockchip_pll_type {
pll_rk3036,
pll_rk3066,
pll_rk3328,
pll_rk3399,
pll_rk3588,
pll_rk3588_core,
};
#define RK3036_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, \
......@@ -272,6 +319,15 @@ enum rockchip_pll_type {
.nb = _nb, \
}
#define RK3588_PLL_RATE(_rate, _p, _m, _s, _k) \
{ \
.rate = _rate##U, \
.p = _p, \
.m = _m, \
.s = _s, \
.k = _k, \
}
/**
* struct rockchip_clk_provider - information about clock provider
* @reg_base: virtual address for the register base.
......@@ -307,6 +363,13 @@ struct rockchip_pll_rate_table {
unsigned int dsmpd;
unsigned int frac;
};
struct {
/* for RK3588 */
unsigned int m;
unsigned int p;
unsigned int s;
unsigned int k;
};
};
};
......@@ -376,11 +439,13 @@ struct rockchip_cpuclk_clksel {
u32 val;
};
#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 5
#define ROCKCHIP_CPUCLK_NUM_DIVIDERS 6
#define ROCKCHIP_CPUCLK_MAX_CORES 4
struct rockchip_cpuclk_rate_table {
unsigned long prate;
struct rockchip_cpuclk_clksel divs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
struct rockchip_cpuclk_clksel pre_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
struct rockchip_cpuclk_clksel post_muxs[ROCKCHIP_CPUCLK_NUM_DIVIDERS];
};
/**
......@@ -389,6 +454,8 @@ struct rockchip_cpuclk_rate_table {
* @div_core_shift[]: cores divider offset used to divide the pll value
* @div_core_mask[]: cores divider mask
* @num_cores: number of cpu cores
* @mux_core_reg: register offset of the cores select parent
* @mux_core_alt: mux value to select alternate parent
* @mux_core_main: mux value to select main parent of core
* @mux_core_shift: offset of the core multiplexer
* @mux_core_mask: core multiplexer mask
......@@ -398,6 +465,7 @@ struct rockchip_cpuclk_reg_data {
u8 div_core_shift[ROCKCHIP_CPUCLK_MAX_CORES];
u32 div_core_mask[ROCKCHIP_CPUCLK_MAX_CORES];
int num_cores;
int mux_core_reg;
u8 mux_core_alt;
u8 mux_core_main;
u8 mux_core_shift;
......@@ -905,8 +973,6 @@ struct rockchip_clk_provider *rockchip_clk_init(struct device_node *np,
void __iomem *base, unsigned long nr_clks);
void rockchip_clk_of_add_provider(struct device_node *np,
struct rockchip_clk_provider *ctx);
void rockchip_clk_add_lookup(struct rockchip_clk_provider *ctx,
struct clk *clk, unsigned int id);
void rockchip_clk_register_branches(struct rockchip_clk_provider *ctx,
struct rockchip_clk_branch *list,
unsigned int nr_clk);
......@@ -937,15 +1003,26 @@ struct clk *rockchip_clk_register_halfdiv(const char *name,
spinlock_t *lock);
#ifdef CONFIG_RESET_CONTROLLER
void rockchip_register_softrst(struct device_node *np,
unsigned int num_regs,
void __iomem *base, u8 flags);
void rockchip_register_softrst_lut(struct device_node *np,
const int *lookup_table,
unsigned int num_regs,
void __iomem *base, u8 flags);
#else
static inline void rockchip_register_softrst(struct device_node *np,
unsigned int num_regs,
void __iomem *base, u8 flags)
static inline void rockchip_register_softrst_lut(struct device_node *np,
const int *lookup_table,
unsigned int num_regs,
void __iomem *base, u8 flags)
{
}
#endif
static inline void rockchip_register_softrst(struct device_node *np,
unsigned int num_regs,
void __iomem *base, u8 flags)
{
return rockchip_register_softrst_lut(np, NULL, num_regs, base, flags);
}
void rk3588_rst_init(struct device_node *np, void __iomem *reg_base);
#endif
This diff is collapsed.
......@@ -12,6 +12,7 @@
struct rockchip_softrst {
struct reset_controller_dev rcdev;
const int *lut;
void __iomem *reg_base;
int num_regs;
int num_per_reg;
......@@ -25,8 +26,13 @@ static int rockchip_softrst_assert(struct reset_controller_dev *rcdev,
struct rockchip_softrst *softrst = container_of(rcdev,
struct rockchip_softrst,
rcdev);
int bank = id / softrst->num_per_reg;
int offset = id % softrst->num_per_reg;
int bank, offset;
if (softrst->lut)
id = softrst->lut[id];
bank = id / softrst->num_per_reg;
offset = id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
writel(BIT(offset) | (BIT(offset) << 16),
......@@ -52,8 +58,13 @@ static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev,
struct rockchip_softrst *softrst = container_of(rcdev,
struct rockchip_softrst,
rcdev);
int bank = id / softrst->num_per_reg;
int offset = id % softrst->num_per_reg;
int bank, offset;
if (softrst->lut)
id = softrst->lut[id];
bank = id / softrst->num_per_reg;
offset = id % softrst->num_per_reg;
if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) {
writel((BIT(offset) << 16), softrst->reg_base + (bank * 4));
......@@ -77,9 +88,10 @@ static const struct reset_control_ops rockchip_softrst_ops = {
.deassert = rockchip_softrst_deassert,
};
void rockchip_register_softrst(struct device_node *np,
unsigned int num_regs,
void __iomem *base, u8 flags)
void rockchip_register_softrst_lut(struct device_node *np,
const int *lookup_table,
unsigned int num_regs,
void __iomem *base, u8 flags)
{
struct rockchip_softrst *softrst;
int ret;
......@@ -91,13 +103,17 @@ void rockchip_register_softrst(struct device_node *np,
spin_lock_init(&softrst->lock);
softrst->reg_base = base;
softrst->lut = lookup_table;
softrst->flags = flags;
softrst->num_regs = num_regs;
softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16
: 32;
softrst->rcdev.owner = THIS_MODULE;
softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
if (lookup_table)
softrst->rcdev.nr_resets = num_regs;
else
softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg;
softrst->rcdev.ops = &rockchip_softrst_ops;
softrst->rcdev.of_node = np;
ret = reset_controller_register(&softrst->rcdev);
......@@ -107,4 +123,4 @@ void rockchip_register_softrst(struct device_node *np,
kfree(softrst);
}
};
EXPORT_SYMBOL_GPL(rockchip_register_softrst);
EXPORT_SYMBOL_GPL(rockchip_register_softrst_lut);
......@@ -207,7 +207,7 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0,
PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "clcd");
clk_register_clkdev(clk, NULL, "fc200000.clcd");
/* gpt clocks */
clk = clk_register_gpt("gpt0_1_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
......@@ -326,13 +326,13 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP0_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.0");
clk_register_clkdev(clk, NULL, "d0100000.spi");
clk = clk_register_gate(NULL, "ssp1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP1_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.1");
clk_register_clkdev(clk, NULL, "d0180000.spi");
clk = clk_register_gate(NULL, "ssp2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
SSP2_CLK_ENB, 0, &_lock);
clk_register_clkdev(clk, NULL, "ssp-pl022.2");
clk_register_clkdev(clk, NULL, "d8180000.spi");
}
......@@ -16,40 +16,48 @@
#define IMX8MN_CLK_EXT4 7
#define IMX8MN_AUDIO_PLL1_REF_SEL 8
#define IMX8MN_AUDIO_PLL2_REF_SEL 9
#define IMX8MN_VIDEO_PLL1_REF_SEL 10
#define IMX8MN_VIDEO_PLL_REF_SEL 10
#define IMX8MN_VIDEO_PLL1_REF_SEL IMX8MN_VIDEO_PLL_REF_SEL
#define IMX8MN_DRAM_PLL_REF_SEL 11
#define IMX8MN_GPU_PLL_REF_SEL 12
#define IMX8MN_VPU_PLL_REF_SEL 13
#define IMX8MN_M7_ALT_PLL_REF_SEL 13
#define IMX8MN_VPU_PLL_REF_SEL IMX8MN_M7_ALT_PLL_REF_SEL
#define IMX8MN_ARM_PLL_REF_SEL 14
#define IMX8MN_SYS_PLL1_REF_SEL 15
#define IMX8MN_SYS_PLL2_REF_SEL 16
#define IMX8MN_SYS_PLL3_REF_SEL 17
#define IMX8MN_AUDIO_PLL1 18
#define IMX8MN_AUDIO_PLL2 19
#define IMX8MN_VIDEO_PLL1 20
#define IMX8MN_VIDEO_PLL 20
#define IMX8MN_VIDEO_PLL1 IMX8MN_VIDEO_PLL
#define IMX8MN_DRAM_PLL 21
#define IMX8MN_GPU_PLL 22
#define IMX8MN_VPU_PLL 23
#define IMX8MN_M7_ALT_PLL 23
#define IMX8MN_VPU_PLL IMX8MN_M7_ALT_PLL
#define IMX8MN_ARM_PLL 24
#define IMX8MN_SYS_PLL1 25
#define IMX8MN_SYS_PLL2 26
#define IMX8MN_SYS_PLL3 27
#define IMX8MN_AUDIO_PLL1_BYPASS 28
#define IMX8MN_AUDIO_PLL2_BYPASS 29
#define IMX8MN_VIDEO_PLL1_BYPASS 30
#define IMX8MN_VIDEO_PLL_BYPASS 30
#define IMX8MN_VIDEO_PLL1_BYPASS IMX8MN_VIDEO_PLL_BYPASS
#define IMX8MN_DRAM_PLL_BYPASS 31
#define IMX8MN_GPU_PLL_BYPASS 32
#define IMX8MN_VPU_PLL_BYPASS 33
#define IMX8MN_M7_ALT_PLL_BYPASS 33
#define IMX8MN_VPU_PLL_BYPASS IMX8MN_M7_ALT_PLL_BYPASS
#define IMX8MN_ARM_PLL_BYPASS 34
#define IMX8MN_SYS_PLL1_BYPASS 35
#define IMX8MN_SYS_PLL2_BYPASS 36
#define IMX8MN_SYS_PLL3_BYPASS 37
#define IMX8MN_AUDIO_PLL1_OUT 38
#define IMX8MN_AUDIO_PLL2_OUT 39
#define IMX8MN_VIDEO_PLL1_OUT 40
#define IMX8MN_VIDEO_PLL_OUT 40
#define IMX8MN_VIDEO_PLL1_OUT IMX8MN_VIDEO_PLL_OUT
#define IMX8MN_DRAM_PLL_OUT 41
#define IMX8MN_GPU_PLL_OUT 42
#define IMX8MN_VPU_PLL_OUT 43
#define IMX8MN_M7_ALT_PLL_OUT 43
#define IMX8MN_VPU_PLL_OUT IMX8MN_M7_ALT_PLL_OUT
#define IMX8MN_ARM_PLL_OUT 44
#define IMX8MN_SYS_PLL1_OUT 45
#define IMX8MN_SYS_PLL2_OUT 46
......
......@@ -324,8 +324,18 @@
#define IMX8MP_CLK_CLKOUT2_SEL 317
#define IMX8MP_CLK_CLKOUT2_DIV 318
#define IMX8MP_CLK_CLKOUT2 319
#define IMX8MP_CLK_USB_SUSP 320
#define IMX8MP_CLK_AUDIO_AHB_ROOT IMX8MP_CLK_AUDIO_ROOT
#define IMX8MP_CLK_AUDIO_AXI_ROOT 321
#define IMX8MP_CLK_SAI1_ROOT 322
#define IMX8MP_CLK_SAI2_ROOT 323
#define IMX8MP_CLK_SAI3_ROOT 324
#define IMX8MP_CLK_SAI5_ROOT 325
#define IMX8MP_CLK_SAI6_ROOT 326
#define IMX8MP_CLK_SAI7_ROOT 327
#define IMX8MP_CLK_PDM_ROOT 328
#define IMX8MP_CLK_END 320
#define IMX8MP_CLK_END 329
#define IMX8MP_CLK_AUDIOMIX_SAI1_IPG 0
#define IMX8MP_CLK_AUDIOMIX_SAI1_MCLK1 1
......
......@@ -28,13 +28,9 @@
#define IMX93_CLK_M33_SYSTICK 19
#define IMX93_CLK_FLEXIO1 20
#define IMX93_CLK_FLEXIO2 21
#define IMX93_CLK_LPIT1 22
#define IMX93_CLK_LPIT2 23
#define IMX93_CLK_LPTMR1 24
#define IMX93_CLK_LPTMR2 25
#define IMX93_CLK_TPM1 26
#define IMX93_CLK_TPM2 27
#define IMX93_CLK_TPM3 28
#define IMX93_CLK_TPM4 29
#define IMX93_CLK_TPM5 30
#define IMX93_CLK_TPM6 31
......
......@@ -547,8 +547,8 @@
#define SRST_H_PERILP0 171
#define SRST_H_PERILP0_NOC 172
#define SRST_ROM 173
#define SRST_CRYPTO_S 174
#define SRST_CRYPTO_M 175
#define SRST_CRYPTO0_S 174
#define SRST_CRYPTO0_M 175
/* cru_softrst_con11 */
#define SRST_P_DCF 176
......@@ -556,7 +556,7 @@
#define SRST_CM0S 178
#define SRST_CM0S_DBG 179
#define SRST_CM0S_PO 180
#define SRST_CRYPTO 181
#define SRST_CRYPTO0 181
#define SRST_P_PERILP1_SGRF 182
#define SRST_P_PERILP1_GRF 183
#define SRST_CRYPTO1_S 184
......
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