Merge https://gitlab.denx.de/u-boot/custodians/u-boot-fsl-qoriq
[oweals/u-boot.git] / drivers / clk / aspeed / clk_ast2500.c
index ccf47a1da11c648dc6cec27a713f8dcf94d34afc..f4a441ad684a5e5830882970dcf8f35314a5205c 100644 (file)
@@ -1,7 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * (C) Copyright 2016 Google, Inc
- *
- * SPDX-License-Identifier:    GPL-2.0
  */
 
 #include <common.h>
@@ -11,6 +10,7 @@
 #include <asm/arch/scu_ast2500.h>
 #include <dm/lists.h>
 #include <dt-bindings/clock/ast2500-scu.h>
+#include <linux/err.h>
 
 /*
  * MAC Clock Delay settings, taken from Aspeed SDK
@@ -144,6 +144,17 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
                        rate = rate / apb_div;
                }
                break;
+       case BCLK_SDCLK:
+               {
+                       ulong apb_div = 4 + 4 * ((readl(&priv->scu->clk_sel1)
+                                                 & SCU_SDCLK_DIV_MASK)
+                                                >> SCU_SDCLK_DIV_SHIFT);
+                       rate = ast2500_get_hpll_rate(clkin,
+                                                    readl(&priv->
+                                                          scu->h_pll_param));
+                       rate = rate / apb_div;
+               }
+               break;
        case PCLK_UART1:
                rate = ast2500_get_uart_clk_rate(priv->scu, 1);
                break;
@@ -166,6 +177,35 @@ static ulong ast2500_clk_get_rate(struct clk *clk)
        return rate;
 }
 
+struct ast2500_clock_config {
+       ulong input_rate;
+       ulong rate;
+       struct ast2500_div_config cfg;
+};
+
+static const struct ast2500_clock_config ast2500_clock_config_defaults[] = {
+       { 24000000, 250000000, { .num = 124, .denum = 1, .post_div = 5 } },
+};
+
+static bool ast2500_get_clock_config_default(ulong input_rate,
+                                            ulong requested_rate,
+                                            struct ast2500_div_config *cfg)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(ast2500_clock_config_defaults); i++) {
+               const struct ast2500_clock_config *default_cfg =
+                       &ast2500_clock_config_defaults[i];
+               if (default_cfg->input_rate == input_rate &&
+                   default_cfg->rate == requested_rate) {
+                       *cfg = default_cfg->cfg;
+                       return true;
+               }
+       }
+
+       return false;
+}
+
 /*
  * @input_rate - the rate of input clock in Hz
  * @requested_rate - desired output rate in Hz
@@ -190,6 +230,12 @@ static ulong ast2500_calc_clock_config(ulong input_rate, ulong requested_rate,
        ulong delta = rate_khz;
        ulong new_rate_khz = 0;
 
+       /*
+        * Look for a well known frequency first.
+        */
+       if (ast2500_get_clock_config_default(input_rate, requested_rate, cfg))
+               return requested_rate;
+
        for (; it.denum <= max_vals.denum; ++it.denum) {
                for (it.post_div = 0; it.post_div <= max_vals.post_div;
                     ++it.post_div) {
@@ -319,6 +365,9 @@ static ulong ast2500_configure_d2pll(struct ast2500_scu *scu, ulong rate)
        /*
         * The values and the meaning of the next three
         * parameters are undocumented. Taken from Aspeed SDK.
+        *
+        * TODO(clg@kaod.org): the SIP and SIC values depend on the
+        * Numerator value
         */
        const u32 d2_pll_ext_param = 0x2c;
        const u32 d2_pll_sip = 0x11;
@@ -399,6 +448,22 @@ static int ast2500_clk_enable(struct clk *clk)
        struct ast2500_clk_priv *priv = dev_get_priv(clk->dev);
 
        switch (clk->id) {
+       case BCLK_SDCLK:
+               if (readl(&priv->scu->clk_stop_ctrl1) & SCU_CLKSTOP_SDCLK) {
+                       ast_scu_unlock(priv->scu);
+
+                       setbits_le32(&priv->scu->sysreset_ctrl1,
+                                    SCU_SYSRESET_SDIO);
+                       udelay(100);
+                       clrbits_le32(&priv->scu->clk_stop_ctrl1,
+                                    SCU_CLKSTOP_SDCLK);
+                       mdelay(10);
+                       clrbits_le32(&priv->scu->sysreset_ctrl1,
+                                    SCU_SYSRESET_SDIO);
+
+                       ast_scu_lock(priv->scu);
+               }
+               break;
        /*
         * For MAC clocks the clock rate is
         * configured based on whether RGMII or RMII mode has been selected
@@ -412,6 +477,7 @@ static int ast2500_clk_enable(struct clk *clk)
                break;
        case PLL_D2PLL:
                ast2500_configure_d2pll(priv->scu, D2PLL_DEFAULT_RATE);
+               break;
        default:
                return -ENOENT;
        }
@@ -425,11 +491,11 @@ struct clk_ops ast2500_clk_ops = {
        .enable = ast2500_clk_enable,
 };
 
-static int ast2500_clk_probe(struct udevice *dev)
+static int ast2500_clk_ofdata_to_platdata(struct udevice *dev)
 {
        struct ast2500_clk_priv *priv = dev_get_priv(dev);
 
-       priv->scu = dev_get_addr_ptr(dev);
+       priv->scu = devfdt_get_addr_ptr(dev);
        if (IS_ERR(priv->scu))
                return PTR_ERR(priv->scu);
 
@@ -460,5 +526,5 @@ U_BOOT_DRIVER(aspeed_ast2500_scu) = {
        .priv_auto_alloc_size = sizeof(struct ast2500_clk_priv),
        .ops            = &ast2500_clk_ops,
        .bind           = ast2500_clk_bind,
-       .probe          = ast2500_clk_probe,
+       .ofdata_to_platdata             = ast2500_clk_ofdata_to_platdata,
 };