From patchwork Sat Feb 3 12:22:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Wu X-Patchwork-Id: 868897 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 3zYY305sxHz9t5x for ; Sat, 3 Feb 2018 23:25:16 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 50E7FC21E43; Sat, 3 Feb 2018 12:23:22 +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.0 required=5.0 tests=RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2 autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id E1305C21E40; Sat, 3 Feb 2018 12:23:19 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 0C6B6C21D9F; Sat, 3 Feb 2018 12:22:31 +0000 (UTC) Received: from regular1.263xmail.com (regular1.263xmail.com [211.150.99.136]) by lists.denx.de (Postfix) with ESMTPS id B1393C21E16 for ; Sat, 3 Feb 2018 12:22:30 +0000 (UTC) Received: from david.wu?rock-chips.com (unknown [192.168.167.128]) by regular1.263xmail.com (Postfix) with ESMTP id 255883C; Sat, 3 Feb 2018 20:22:27 +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 E95C43D6; Sat, 3 Feb 2018 20:22:26 +0800 (CST) X-RL-SENDER: david.wu@rock-chips.com X-FST-TO: philipp.tomsich@theobroma-systems.com X-SENDER-IP: 220.200.40.59 X-LOGIN-NAME: david.wu@rock-chips.com X-UNIQUE-TAG: X-ATTACHMENT-NUM: 0 X-SENDER: wdc@rock-chips.com X-DNS-TYPE: 0 Received: from localhost.localdomain (unknown [220.200.40.59]) by smtp.263.net (Postfix) whith ESMTP id 26867M1XPO6; Sat, 03 Feb 2018 20:22:27 +0800 (CST) From: David Wu To: philipp.tomsich@theobroma-systems.com Date: Sat, 3 Feb 2018 20:22:24 +0800 Message-Id: <1517660544-22363-1-git-send-email-david.wu@rock-chips.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1517660196-21802-1-git-send-email-david.wu@rock-chips.com> References: <1517660196-21802-1-git-send-email-david.wu@rock-chips.com> Cc: u-boot@lists.denx.de, David Wu Subject: [U-Boot] [PATCH 11/14] clk: rk3328: Implement the gmac2phy clock assignment 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" Implement the setting parent and rate for gmac2phy clock, and add internal pll div set for gmac2phy clk. Signed-off-by: David Wu Acked-by: Philipp Tomsich --- drivers/clk/rockchip/clk_rk3328.c | 86 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/drivers/clk/rockchip/clk_rk3328.c b/drivers/clk/rockchip/clk_rk3328.c index 3f8cdc0..c576262 100644 --- a/drivers/clk/rockchip/clk_rk3328.c +++ b/drivers/clk/rockchip/clk_rk3328.c @@ -95,6 +95,14 @@ enum { PCLK_DBG_DIV_SHIFT = 0, PCLK_DBG_DIV_MASK = 0xF << PCLK_DBG_DIV_SHIFT, + /* CLKSEL_CON26 */ + GMAC2PHY_PLL_SEL_SHIFT = 7, + GMAC2PHY_PLL_SEL_MASK = 1 << GMAC2PHY_PLL_SEL_SHIFT, + GMAC2PHY_PLL_SEL_CPLL = 0, + GMAC2PHY_PLL_SEL_GPLL = 1, + GMAC2PHY_CLK_DIV_MASK = 0x1f, + GMAC2PHY_CLK_DIV_SHIFT = 0, + /* CLKSEL_CON27 */ GMAC2IO_PLL_SEL_SHIFT = 7, GMAC2IO_PLL_SEL_MASK = 1 << GMAC2IO_PLL_SEL_SHIFT, @@ -440,6 +448,39 @@ static ulong rk3328_gmac2io_set_clk(struct rk3328_cru *cru, ulong rate) return ret; } +static ulong rk3328_gmac2phy_src_set_clk(struct rk3328_cru *cru, ulong rate) +{ + u32 con = readl(&cru->clksel_con[26]); + ulong pll_rate; + u8 div; + + if ((con >> GMAC2PHY_PLL_SEL_SHIFT) & GMAC2PHY_PLL_SEL_GPLL) + pll_rate = GPLL_HZ; + else + pll_rate = CPLL_HZ; + + div = DIV_ROUND_UP(pll_rate, rate) - 1; + if (div <= 0x1f) + rk_clrsetreg(&cru->clksel_con[26], GMAC2PHY_CLK_DIV_MASK, + div << GMAC2PHY_CLK_DIV_SHIFT); + else + debug("Unsupported div for gmac:%d\n", div); + + return DIV_TO_RATE(pll_rate, div); +} + +static ulong rk3328_gmac2phy_set_clk(struct rk3328_cru *cru, ulong rate) +{ + struct rk3328_grf_regs *grf; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + if (readl(&grf->mac_con[2]) & BIT(10)) + /* An external clock will always generate the right rate... */ + return rate; + else + return rk3328_gmac2phy_src_set_clk(cru, rate); +} + static ulong rk3328_mmc_get_clk(struct rk3328_cru *cru, uint clk_id) { u32 div, con, con_id; @@ -608,6 +649,12 @@ static ulong rk3328_clk_set_rate(struct clk *clk, ulong rate) case SCLK_MAC2IO: ret = rk3328_gmac2io_set_clk(priv->cru, rate); break; + case SCLK_MAC2PHY: + ret = rk3328_gmac2phy_set_clk(priv->cru, rate); + break; + case SCLK_MAC2PHY_SRC: + ret = rk3328_gmac2phy_src_set_clk(priv->cru, rate); + break; case SCLK_PWM: ret = rk3328_pwm_set_clk(priv->cru, rate); break; @@ -728,6 +775,43 @@ static int rk3328_gmac2io_ext_set_parent(struct clk *clk, struct clk *parent) return -EINVAL; } +static int rk3328_gmac2phy_set_parent(struct clk *clk, struct clk *parent) +{ + struct rk3328_grf_regs *grf; + const char *clock_output_name; + int ret; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + /* + * If the requested parent is in the same clock-controller and the id + * is SCLK_MAC2PHY_SRC ("clk_mac2phy_src"), switch to the internal clock. + */ + if ((parent->dev == clk->dev) && (parent->id == SCLK_MAC2PHY_SRC)) { + debug("%s: switching MAC CLK to SCLK_MAC2IO_PHY\n", __func__); + rk_clrreg(&grf->mac_con[2], BIT(10)); + return 0; + } + + /* + * Otherwise, we need to check the clock-output-names of the + * requested parent to see if the requested id is "phy_50m_out". + */ + ret = dev_read_string_index(parent->dev, "clock-output-names", + parent->id, &clock_output_name); + if (ret < 0) + return -ENODATA; + + /* If this is "phy_50m_out", switch to the external clock input */ + if (!strcmp(clock_output_name, "phy_50m_out")) { + debug("%s: switching MAC CLK to PHY_50M_OUT\n", __func__); + rk_setreg(&grf->mac_con[2], BIT(10)); + return 0; + } + + return -EINVAL; +} + static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) { switch (clk->id) { @@ -735,6 +819,8 @@ static int rk3328_clk_set_parent(struct clk *clk, struct clk *parent) return rk3328_gmac2io_set_parent(clk, parent); case SCLK_MAC2IO_EXT: return rk3328_gmac2io_ext_set_parent(clk, parent); + case SCLK_MAC2PHY: + return rk3328_gmac2phy_set_parent(clk, parent); case DCLK_LCDC: case SCLK_PDM: case SCLK_RTC32K: