From patchwork Sat Jan 13 06:06:33 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Wu X-Patchwork-Id: 860299 X-Patchwork-Delegate: philipp.tomsich@theobroma-systems.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 3zJTk556GGz9t5Q for ; Sat, 13 Jan 2018 17:10:21 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 4F769C21F22; Sat, 13 Jan 2018 06:07:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=0.6 required=5.0 tests=RCVD_IN_SORBS_WEB autolearn=no autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 8C25EC21F38; Sat, 13 Jan 2018 06:06:56 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 5E3D0C21F30; Sat, 13 Jan 2018 06:06:46 +0000 (UTC) Received: from regular1.263xmail.com (regular1.263xmail.com [211.150.99.136]) by lists.denx.de (Postfix) with ESMTPS id A4E9DC21EF2 for ; Sat, 13 Jan 2018 06:06:42 +0000 (UTC) Received: from david.wu?rock-chips.com (unknown [192.168.167.234]) by regular1.263xmail.com (Postfix) with ESMTP id DE31A39; Sat, 13 Jan 2018 14:06:36 +0800 (CST) X-263anti-spam: KSV:0; X-MAIL-GRAY: 0 X-MAIL-DELIVERY: 1 X-KSVirus-check: 0 X-ABS-CHECKED: 4 Received: from localhost.localdomain (localhost [127.0.0.1]) by smtp.263.net (Postfix) with ESMTPA id 67CD1383; Sat, 13 Jan 2018 14:06:35 +0800 (CST) X-RL-SENDER: david.wu@rock-chips.com X-FST-TO: philipp.tomsich@theobroma-systems.com X-SENDER-IP: 58.22.7.114 X-LOGIN-NAME: david.wu@rock-chips.com X-UNIQUE-TAG: <47fde4c80a43714b16f1458f44a1752d> X-ATTACHMENT-NUM: 0 X-SENDER: wdc@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [58.22.7.114]) by smtp.263.net (Postfix) whith ESMTP id 277998YAJ7I; Sat, 13 Jan 2018 14:06:36 +0800 (CST) From: David Wu To: philipp.tomsich@theobroma-systems.com, sjg@chromium.org Date: Sat, 13 Jan 2018 14:06:33 +0800 Message-Id: <1515823593-53092-1-git-send-email-david.wu@rock-chips.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1515822853-52036-1-git-send-email-david.wu@rock-chips.com> References: <1515822853-52036-1-git-send-email-david.wu@rock-chips.com> Cc: huangtao@rock-chips.com, joe.hershberger@ni.com, u-boot@lists.denx.de, David Wu , andy.yan@rock-chips.com Subject: [U-Boot] [PATCH v3 19/20] clk: rockchip: clk_rk3288: Implement "assign-clock-parent" and "assign-clock-rate" X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" The RK3288 CRU-node assigns rates to a number of clocks that are not implemented in the RK3288 clock-driver (but which have been sufficiently initialised from rkclk_init()): for these clocks, we implement the gmac clock set parent, but simply ignore the others' set_rate() operation and return 0 to signal success. Signed-off-by: David Wu Acked-by: Philipp Tomsich Reviewed-by: Philipp Tomsich --- Changes in v3: - New patch Changes in v2: None drivers/clk/rockchip/clk_rk3288.c | 106 ++++++++++++++++++++++++++++++--- include/dt-bindings/clock/rk3288-cru.h | 1 + 2 files changed, 99 insertions(+), 8 deletions(-) diff --git a/drivers/clk/rockchip/clk_rk3288.c b/drivers/clk/rockchip/clk_rk3288.c index b64c107..baa8122 100644 --- a/drivers/clk/rockchip/clk_rk3288.c +++ b/drivers/clk/rockchip/clk_rk3288.c @@ -295,15 +295,42 @@ static int pll_para_config(ulong freq_hz, struct pll_div *div, uint *ext_div) return 0; } -static int rockchip_mac_set_clk(struct rk3288_cru *cru, - int periph, uint freq) +static int rockchip_mac_set_clk(struct rk3288_cru *cru, uint freq) { - /* Assuming mac_clk is fed by an external clock */ - rk_clrsetreg(&cru->cru_clksel_con[21], - RMII_EXTCLK_MASK, - RMII_EXTCLK_SELECT_EXT_CLK << RMII_EXTCLK_SHIFT); + ulong ret; - return 0; + /* + * The gmac clock can be derived either from an external clock + * or can be generated from internally by a divider from SCLK_MAC. + */ + if (readl(&cru->cru_clksel_con[21]) & RMII_EXTCLK_MASK) { + /* An external clock will always generate the right rate... */ + ret = freq; + } else { + u32 con = readl(&cru->cru_clksel_con[21]); + ulong pll_rate; + u8 div; + + if (((con >> EMAC_PLL_SHIFT) & EMAC_PLL_MASK) == + EMAC_PLL_SELECT_GENERAL) + pll_rate = GPLL_HZ; + else if (((con >> EMAC_PLL_SHIFT) & EMAC_PLL_MASK) == + EMAC_PLL_SELECT_CODEC) + pll_rate = CPLL_HZ; + else + pll_rate = NPLL_HZ; + + div = DIV_ROUND_UP(pll_rate, freq) - 1; + if (div <= 0x1f) + rk_clrsetreg(&cru->cru_clksel_con[21], MAC_DIV_CON_MASK, + div << MAC_DIV_CON_SHIFT); + else + debug("Unsupported div for gmac:%d\n", div); + + return DIV_TO_RATE(pll_rate, div); + } + + return ret; } static int rockchip_vop_set_clk(struct rk3288_cru *cru, struct rk3288_grf *grf, @@ -744,7 +771,7 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate) break; #ifndef CONFIG_SPL_BUILD case SCLK_MAC: - new_rate = rockchip_mac_set_clk(priv->cru, clk->id, rate); + new_rate = rockchip_mac_set_clk(priv->cru, rate); break; case DCLK_VOP0: case DCLK_VOP1: @@ -797,6 +824,17 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate) case SCLK_SARADC: new_rate = rockchip_saradc_set_clk(priv->cru, rate); break; + case PLL_GPLL: + case PLL_CPLL: + case PLL_NPLL: + case ACLK_CPU: + case HCLK_CPU: + case PCLK_CPU: + case ACLK_PERI: + case HCLK_PERI: + case PCLK_PERI: + case SCLK_UART0: + return 0; default: return -ENOENT; } @@ -804,9 +842,61 @@ static ulong rk3288_clk_set_rate(struct clk *clk, ulong rate) return new_rate; } +static int rk3288_gmac_set_parent(struct clk *clk, struct clk *parent) +{ + struct rk3288_clk_priv *priv = dev_get_priv(clk->dev); + struct rk3288_cru *cru = priv->cru; + const char *clock_output_name; + int ret; + + /* + * If the requested parent is in the same clock-controller and + * the id is SCLK_MAC_PLL ("mac_pll_src"), switch to the internal + * clock. + */ + if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC_PLL)) { + debug("%s: switching GAMC to SCLK_MAC_PLL\n", __func__); + rk_clrsetreg(&cru->cru_clksel_con[21], RMII_EXTCLK_MASK, 0); + return 0; + } + + /* + * Otherwise, we need to check the clock-output-names of the + * requested parent to see if the requested id is "ext_gmac". + */ + ret = dev_read_string_index(parent->dev, "clock-output-names", + parent->id, &clock_output_name); + if (ret < 0) + return -ENODATA; + + /* If this is "ext_gmac", switch to the external clock input */ + if (!strcmp(clock_output_name, "ext_gmac")) { + debug("%s: switching GMAC to external clock\n", __func__); + rk_clrsetreg(&cru->cru_clksel_con[21], RMII_EXTCLK_MASK, + RMII_EXTCLK_SELECT_EXT_CLK << RMII_EXTCLK_SHIFT); + return 0; + } + + return -EINVAL; +} + +static int rk3288_clk_set_parent(struct clk *clk, struct clk *parent) +{ + switch (clk->id) { + case SCLK_MAC: + return rk3288_gmac_set_parent(clk, parent); + case SCLK_USBPHY480M_SRC: + return 0; + } + + debug("%s: unsupported clk %ld\n", __func__, clk->id); + return -ENOENT; +} + static struct clk_ops rk3288_clk_ops = { .get_rate = rk3288_clk_get_rate, .set_rate = rk3288_clk_set_rate, + .set_parent = rk3288_clk_set_parent, }; static int rk3288_clk_ofdata_to_platdata(struct udevice *dev) diff --git a/include/dt-bindings/clock/rk3288-cru.h b/include/dt-bindings/clock/rk3288-cru.h index 216eee5..e37113a 100644 --- a/include/dt-bindings/clock/rk3288-cru.h +++ b/include/dt-bindings/clock/rk3288-cru.h @@ -76,6 +76,7 @@ #define SCLK_PVTM_CORE 123 #define SCLK_PVTM_GPU 124 +#define SCLK_MAC_PLL 150 #define SCLK_MAC 151 #define SCLK_MACREF_OUT 152