rockchip: clk: rk3399: allow requests for all UART clocks
[platform/kernel/u-boot.git] / drivers / clk / rockchip / clk_rk3399.c
index 42926ba..aa6a8ad 100644 (file)
@@ -1,8 +1,7 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * (C) Copyright 2015 Google, Inc
  * (C) 2017 Theobroma Systems Design und Consulting GmbH
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <common.h>
 #include <syscon.h>
 #include <bitfield.h>
 #include <asm/io.h>
-#include <asm/arch/clock.h>
-#include <asm/arch/cru_rk3399.h>
-#include <asm/arch/hardware.h>
+#include <asm/arch-rockchip/clock.h>
+#include <asm/arch-rockchip/cru_rk3399.h>
+#include <asm/arch-rockchip/hardware.h>
 #include <dm/lists.h>
 #include <dt-bindings/clock/rk3399-cru.h>
 
-DECLARE_GLOBAL_DATA_PTR;
-
 #if CONFIG_IS_ENABLED(OF_PLATDATA)
 struct rk3399_clk_plat {
        struct dtd_rockchip_rk3399_cru dtd;
@@ -64,6 +61,11 @@ static const struct pll_div *apll_l_cfgs[] = {
        [APLL_L_600_MHZ] = &apll_l_600_cfg,
 };
 
+static const struct pll_div apll_b_600_cfg = PLL_DIVISORS(600*MHz, 1, 2, 1);
+static const struct pll_div *apll_b_cfgs[] = {
+       [APLL_B_600_MHZ] = &apll_b_600_cfg,
+};
+
 enum {
        /* PLL_CON0 */
        PLL_FBDIV_MASK                  = 0xfff,
@@ -131,6 +133,24 @@ enum {
        ATCLK_CORE_L_DIV_SHIFT          = 0,
        ATCLK_CORE_L_DIV_MASK           = 0x1f << ATCLK_CORE_L_DIV_SHIFT,
 
+       /* CLKSEL_CON2 */
+       ACLKM_CORE_B_DIV_CON_SHIFT      = 8,
+       ACLKM_CORE_B_DIV_CON_MASK       = 0x1f << ACLKM_CORE_B_DIV_CON_SHIFT,
+       CLK_CORE_B_PLL_SEL_SHIFT        = 6,
+       CLK_CORE_B_PLL_SEL_MASK         = 3 << CLK_CORE_B_PLL_SEL_SHIFT,
+       CLK_CORE_B_PLL_SEL_ALPLL        = 0x0,
+       CLK_CORE_B_PLL_SEL_ABPLL        = 0x1,
+       CLK_CORE_B_PLL_SEL_DPLL         = 0x10,
+       CLK_CORE_B_PLL_SEL_GPLL         = 0x11,
+       CLK_CORE_B_DIV_MASK             = 0x1f,
+       CLK_CORE_B_DIV_SHIFT            = 0,
+
+       /* CLKSEL_CON3 */
+       PCLK_DBG_B_DIV_SHIFT            = 0x8,
+       PCLK_DBG_B_DIV_MASK             = 0x1f << PCLK_DBG_B_DIV_SHIFT,
+       ATCLK_CORE_B_DIV_SHIFT          = 0,
+       ATCLK_CORE_B_DIV_MASK           = 0x1f << ATCLK_CORE_B_DIV_SHIFT,
+
        /* CLKSEL_CON14 */
        PCLK_PERIHP_DIV_CON_SHIFT       = 12,
        PCLK_PERIHP_DIV_CON_MASK        = 0x7 << PCLK_PERIHP_DIV_CON_SHIFT,
@@ -398,25 +418,26 @@ static int pll_para_config(u32 freq_hz, struct pll_div *div)
        return 0;
 }
 
-void rk3399_configure_cpu(struct rk3399_cru *cru,
-                         enum apll_l_frequencies apll_l_freq)
+void rk3399_configure_cpu_l(struct rk3399_cru *cru,
+                           enum apll_l_frequencies apll_l_freq)
 {
        u32 aclkm_div;
        u32 pclk_dbg_div;
        u32 atclk_div;
 
+       /* Setup cluster L */
        rkclk_set_pll(&cru->apll_l_con[0], apll_l_cfgs[apll_l_freq]);
 
-       aclkm_div = APLL_HZ / ACLKM_CORE_HZ - 1;
-       assert((aclkm_div + 1) * ACLKM_CORE_HZ == APLL_HZ &&
+       aclkm_div = LPLL_HZ / ACLKM_CORE_L_HZ - 1;
+       assert((aclkm_div + 1) * ACLKM_CORE_L_HZ == LPLL_HZ &&
               aclkm_div < 0x1f);
 
-       pclk_dbg_div = APLL_HZ / PCLK_DBG_HZ - 1;
-       assert((pclk_dbg_div + 1) * PCLK_DBG_HZ == APLL_HZ &&
+       pclk_dbg_div = LPLL_HZ / PCLK_DBG_L_HZ - 1;
+       assert((pclk_dbg_div + 1) * PCLK_DBG_L_HZ == LPLL_HZ &&
               pclk_dbg_div < 0x1f);
 
-       atclk_div = APLL_HZ / ATCLK_CORE_HZ - 1;
-       assert((atclk_div + 1) * ATCLK_CORE_HZ == APLL_HZ &&
+       atclk_div = LPLL_HZ / ATCLK_CORE_L_HZ - 1;
+       assert((atclk_div + 1) * ATCLK_CORE_L_HZ == LPLL_HZ &&
               atclk_div < 0x1f);
 
        rk_clrsetreg(&cru->clksel_con[0],
@@ -431,6 +452,42 @@ void rk3399_configure_cpu(struct rk3399_cru *cru,
                     pclk_dbg_div << PCLK_DBG_L_DIV_SHIFT |
                     atclk_div << ATCLK_CORE_L_DIV_SHIFT);
 }
+
+void rk3399_configure_cpu_b(struct rk3399_cru *cru,
+                           enum apll_b_frequencies apll_b_freq)
+{
+       u32 aclkm_div;
+       u32 pclk_dbg_div;
+       u32 atclk_div;
+
+       /* Setup cluster B */
+       rkclk_set_pll(&cru->apll_b_con[0], apll_b_cfgs[apll_b_freq]);
+
+       aclkm_div = BPLL_HZ / ACLKM_CORE_B_HZ - 1;
+       assert((aclkm_div + 1) * ACLKM_CORE_B_HZ == BPLL_HZ &&
+              aclkm_div < 0x1f);
+
+       pclk_dbg_div = BPLL_HZ / PCLK_DBG_B_HZ - 1;
+       assert((pclk_dbg_div + 1) * PCLK_DBG_B_HZ == BPLL_HZ &&
+              pclk_dbg_div < 0x1f);
+
+       atclk_div = BPLL_HZ / ATCLK_CORE_B_HZ - 1;
+       assert((atclk_div + 1) * ATCLK_CORE_B_HZ == BPLL_HZ &&
+              atclk_div < 0x1f);
+
+       rk_clrsetreg(&cru->clksel_con[2],
+                    ACLKM_CORE_B_DIV_CON_MASK | CLK_CORE_B_PLL_SEL_MASK |
+                    CLK_CORE_B_DIV_MASK,
+                    aclkm_div << ACLKM_CORE_B_DIV_CON_SHIFT |
+                    CLK_CORE_B_PLL_SEL_ABPLL << CLK_CORE_B_PLL_SEL_SHIFT |
+                    0 << CLK_CORE_B_DIV_SHIFT);
+
+       rk_clrsetreg(&cru->clksel_con[3],
+                    PCLK_DBG_B_DIV_MASK | ATCLK_CORE_B_DIV_MASK,
+                    pclk_dbg_div << PCLK_DBG_B_DIV_SHIFT |
+                    atclk_div << ATCLK_CORE_B_DIV_SHIFT);
+}
+
 #define I2C_CLK_REG_MASK(bus) \
                        (I2C_DIV_CON_MASK << \
                        CLK_I2C ##bus## _DIV_CON_SHIFT | \
@@ -855,7 +912,9 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
                rate = rk3399_spi_get_clk(priv->cru, clk->id);
                break;
        case SCLK_UART0:
+       case SCLK_UART1:
        case SCLK_UART2:
+       case SCLK_UART3:
                return 24000000;
                break;
        case PCLK_HDMI_CTRL:
@@ -868,7 +927,13 @@ static ulong rk3399_clk_get_rate(struct clk *clk)
        case SCLK_SARADC:
                rate = rk3399_saradc_get_clk(priv->cru);
                break;
+       case ACLK_VIO:
+       case ACLK_HDCP:
+       case ACLK_GIC_PRE:
+       case PCLK_DDR:
+               break;
        default:
+               log_debug("Unknown clock %lu\n", clk->id);
                return -ENOENT;
        }
 
@@ -936,7 +1001,13 @@ static ulong rk3399_clk_set_rate(struct clk *clk, ulong rate)
        case SCLK_SARADC:
                ret = rk3399_saradc_set_clk(priv->cru, rate);
                break;
+       case ACLK_VIO:
+       case ACLK_HDCP:
+       case ACLK_GIC_PRE:
+       case PCLK_DDR:
+               return 0;
        default:
+               log_debug("Unknown clock %lu\n", clk->id);
                return -ENOENT;
        }
 
@@ -997,6 +1068,16 @@ static int rk3399_clk_enable(struct clk *clk)
        case HCLK_HOST1:
        case HCLK_HOST1_ARB:
                return 0;
+
+       case SCLK_MAC:
+       case SCLK_MAC_RX:
+       case SCLK_MAC_TX:
+       case SCLK_MACREF:
+       case SCLK_MACREF_OUT:
+       case ACLK_GMAC:
+       case PCLK_GMAC:
+               /* Required to successfully probe the Designware GMAC driver */
+               return 0;
        }
 
        debug("%s: unsupported clk %ld\n", __func__, clk->id);
@@ -1019,7 +1100,8 @@ static void rkclk_init(struct rk3399_cru *cru)
        u32 hclk_div;
        u32 pclk_div;
 
-       rk3399_configure_cpu(cru, APLL_L_600_MHZ);
+       rk3399_configure_cpu_l(cru, APLL_L_600_MHZ);
+       rk3399_configure_cpu_b(cru, APLL_B_600_MHZ);
        /*
         * some cru registers changed by bootrom, we'd better reset them to
         * reset/default values described in TRM to avoid confusion in kernel.
@@ -1236,6 +1318,8 @@ static ulong rk3399_pmuclk_get_rate(struct clk *clk)
        ulong rate = 0;
 
        switch (clk->id) {
+       case PLL_PPLL:
+               return PPLL_HZ;
        case PCLK_RKPWM_PMU:
                rate = rk3399_pwm_get_clk(priv->pmucru);
                break;
@@ -1257,6 +1341,13 @@ static ulong rk3399_pmuclk_set_rate(struct clk *clk, ulong rate)
        ulong ret = 0;
 
        switch (clk->id) {
+       case PLL_PPLL:
+               /*
+                * This has already been set up and we don't want/need
+                * to change it here.  Accept the request though, as the
+                * device-tree has this in an 'assigned-clocks' list.
+                */
+               return PPLL_HZ;
        case SCLK_I2C0_PMU:
        case SCLK_I2C4_PMU:
        case SCLK_I2C8_PMU: