Received: by 2002:ac0:a594:0:0:0:0:0 with SMTP id m20-v6csp4604909imm; Fri, 18 May 2018 07:49:20 -0700 (PDT) X-Google-Smtp-Source: AB8JxZqwF9AT/jXuVugRHpYOw7mCEglXHKh3WiNc49QJ+LPA0KNHqVlI0rLgBkrkHPLSHDrh4UJu X-Received: by 2002:a63:9302:: with SMTP id b2-v6mr7898313pge.263.1526654960102; Fri, 18 May 2018 07:49:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1526654960; cv=none; d=google.com; s=arc-20160816; b=Js4/p11RVUQyP52iKlUQ30x++dxKv2XgXEf9NaDDmlpySmSvZ0butpoNHXeBIg97kj qU+1HMu+Etdz31UlddfVcK5hszU2mclkBqOAYRvRcTAhng7syLWBISNmRS5x/v9wHXH+ lPd6PlakE7TbVWQ8uzeLavfc9KiQZkeObErIzAM/eLcolEohouhac3DizLvzgvvydKZ2 Sb3xbXmgU7U9SdwxhwYH76uMATANiQTu901fXUsE/qSHsVsBU/nnIKK9ydIXX3AUuTEv YJnkIigHhSzwYjegUcgxI7k5N0dO2l4+kx02XBwBPTvTrEAxYF89I78mngZjLRfTifnB 0FYw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=i//O4CbPBQCuV4DPpP8Q1TxdKa2Afm5VDPWCPRY821Y=; b=fItAwkYSD481J2lE3RZZWgHDu0ejZwrJYQzwCDpAgaKoexX8Hd4AKenaPTnuh1p4E1 gxtAnJxX2M47+gS8yirQxkLioCBeERujgwACNXhDi6xV9J53gbpyhh7DyCNFcYUvb2uc 5CefHIK/h0Xg7rwvkccWv8exL6WWkbgSw/F3QBSwX1qiQ6to8aaU2DYIE1NggNVTdLt0 ExOhjsbSHyL4V86RiNAfzzVQX7AwfK0wpaJnHIqdYaclBNfF76rvekdh/S3mHSGLHi03 /cqMSxz3XMTTcSXQUVhgHqKe4/HIHYTF9Gegl547iaDNr87+IZfpZqf5ELJpnBQF0knf OuCQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id u4-v6si6129263pgc.223.2018.05.18.07.49.05; Fri, 18 May 2018 07:49:20 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752062AbeEROr2 (ORCPT + 99 others); Fri, 18 May 2018 10:47:28 -0400 Received: from mailout3.siol.net ([213.250.19.130]:45708 "EHLO mail.siol.net" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751971AbeEROrZ (ORCPT ); Fri, 18 May 2018 10:47:25 -0400 Received: from localhost (localhost [127.0.0.1]) by mail.siol.net (Zimbra) with ESMTP id E1107520467; Fri, 18 May 2018 16:47:22 +0200 (CEST) X-Virus-Scanned: amavisd-new at psrvmta12.zcs-production.pri Received: from mail.siol.net ([127.0.0.1]) by localhost (psrvmta12.zcs-production.pri [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id IMhTKuDRhN0s; Fri, 18 May 2018 16:47:21 +0200 (CEST) Received: from mail.siol.net (localhost [127.0.0.1]) by mail.siol.net (Zimbra) with ESMTPS id 8B5BB520465; Fri, 18 May 2018 16:47:21 +0200 (CEST) Received: from jernej-laptop.localnet (unknown [194.152.15.144]) (Authenticated sender: 031275009) by mail.siol.net (Zimbra) with ESMTPA id 9495E520469; Fri, 18 May 2018 16:47:17 +0200 (CEST) From: Jernej =?utf-8?B?xaBrcmFiZWM=?= To: Maxime Ripard Cc: Jagan Teki , Chen-Yu Tsai , Icenowy Zheng , Rob Herring , Mark Rutland , Catalin Marinas , Will Deacon , David Airlie , dri-devel@lists.freedesktop.org, Michael Turquette , Stephen Boyd , linux-clk@vger.kernel.org, Michael Trimarchi , linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-sunxi@googlegroups.com Subject: Re: [PATCH v2 12/26] drm/sun4i: Add support for multiple DW HDMI PHY clock parents Date: Fri, 18 May 2018 16:46:41 +0200 Message-ID: <4909574.Q3IFWM0xt6@jernej-laptop> In-Reply-To: <20180518100116.4bf2qcffg7ekxa7u@flea> References: <20180518094536.17201-1-jagan@amarulasolutions.com> <20180518094536.17201-13-jagan@amarulasolutions.com> <20180518100116.4bf2qcffg7ekxa7u@flea> MIME-Version: 1.0 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Hi, Dne petek, 18. maj 2018 ob 12:01:16 CEST je Maxime Ripard napisal(a): > On Fri, May 18, 2018 at 03:15:22PM +0530, Jagan Teki wrote: > > From: Jernej Skrabec > > > > Some SoCs with DW HDMI have multiple possible clock parents, like A64 > > and R40. > > > > Expand HDMI PHY clock driver to support second clock parent. > > > > Signed-off-by: Jernej Skrabec > > Signed-off-by: Jagan Teki > > --- > > Changes for v2: > > - new patch > > > > drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h | 9 ++- > > drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c | 33 ++++++++--- > > drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c | 89 > > ++++++++++++++++++++++-------- 3 files changed, 96 insertions(+), 35 > > deletions(-) > > > > diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h > > b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h index 79154f0f674a..303189d6602c > > 100644 > > --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h > > +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.h > > @@ -98,7 +98,8 @@ > > > > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO2_EN BIT(29) > > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO1_EN BIT(28) > > #define SUN8I_HDMI_PHY_PLL_CFG1_HV_IS_33 BIT(27) > > > > -#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL BIT(26) > > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK BIT(26) > > +#define SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT 26 > > > > #define SUN8I_HDMI_PHY_PLL_CFG1_PLLEN BIT(25) > > #define SUN8I_HDMI_PHY_PLL_CFG1_LDO_VSET(x) ((x) << 22) > > #define SUN8I_HDMI_PHY_PLL_CFG1_UNKNOWN(x) ((x) << 20) > > > > @@ -146,7 +147,7 @@ > > > > struct sun8i_hdmi_phy; > > > > struct sun8i_hdmi_phy_variant { > > > > - bool has_phy_clk; > > + int phy_clk_num; > > > > void (*phy_init)(struct sun8i_hdmi_phy *phy); > > void (*phy_disable)(struct dw_hdmi *hdmi, > > > > struct sun8i_hdmi_phy *phy); > > > > @@ -160,6 +161,7 @@ struct sun8i_hdmi_phy { > > > > struct clk *clk_mod; > > struct clk *clk_phy; > > struct clk *clk_pll0; > > > > + struct clk *clk_pll1; > > > > unsigned int rcal; > > struct regmap *regs; > > struct reset_control *rst_phy; > > > > @@ -188,6 +190,7 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi > > *hdmi); > > > > void sun8i_hdmi_phy_init(struct sun8i_hdmi_phy *phy); > > const struct dw_hdmi_phy_ops *sun8i_hdmi_phy_get_ops(void); > > > > -int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev); > > +int sun8i_phy_clk_create(struct sun8i_hdmi_phy *phy, struct device *dev, > > + int clk_num); > > > > #endif /* _SUN8I_DW_HDMI_H_ */ > > > > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c > > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c index 5a52fc489a9d..0eadf087fc46 > > 100644 > > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c > > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy.c > > @@ -183,7 +183,13 @@ static int sun8i_hdmi_phy_config_h3(struct dw_hdmi > > *hdmi,> > > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_ANA_CFG1_REG, > > > > SUN8I_HDMI_PHY_ANA_CFG1_TXEN_MASK, 0); > > > > - regmap_write(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, pll_cfg1_init); > > + /* > > + * NOTE: We have to be careful not to overwrite PHY parent > > + * clock selection bit and clock divider. > > + */ > > + regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, > > + (u32)~SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, > > + pll_cfg1_init); > > > > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_PLL_CFG2_REG, > > > > (u32)~SUN8I_HDMI_PHY_PLL_CFG2_PREDIV_MSK, > > pll_cfg2_init); > > > > @@ -232,7 +238,7 @@ static int sun8i_hdmi_phy_config(struct dw_hdmi *hdmi, > > void *data,> > > regmap_update_bits(phy->regs, SUN8I_HDMI_PHY_DBG_CTRL_REG, > > > > SUN8I_HDMI_PHY_DBG_CTRL_POL_MASK, val); > > > > - if (phy->variant->has_phy_clk) > > + if (phy->variant->phy_clk_num) > > > > clk_set_rate(phy->clk_phy, mode->crtc_clock * 1000); > > > > return phy->variant->phy_config(hdmi, phy, mode->crtc_clock * 1000); > > > > @@ -393,7 +399,7 @@ static const struct sun8i_hdmi_phy_variant > > sun8i_a83t_hdmi_phy = {> > > }; > > > > static const struct sun8i_hdmi_phy_variant sun8i_h3_hdmi_phy = { > > > > - .has_phy_clk = true, > > + .phy_clk_num = 1, > > > > .phy_init = &sun8i_hdmi_phy_init_h3, > > .phy_disable = &sun8i_hdmi_phy_disable_h3, > > .phy_config = &sun8i_hdmi_phy_config_h3, > > > > @@ -464,7 +470,7 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, > > struct device_node *node)> > > goto err_put_clk_bus; > > > > } > > > > - if (phy->variant->has_phy_clk) { > > + if (phy->variant->phy_clk_num) { > > > > phy->clk_pll0 = of_clk_get_by_name(node, "pll-0"); > > if (IS_ERR(phy->clk_pll0)) { > > > > dev_err(dev, "Could not get pll-0 clock\n"); > > > > @@ -472,7 +478,16 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, > > struct device_node *node)> > > goto err_put_clk_mod; > > > > } > > > > - ret = sun8i_phy_clk_create(phy, dev); > > + if (phy->variant->phy_clk_num) { > > + phy->clk_pll1 = of_clk_get_by_name(node, "pll-1"); > > + if (IS_ERR(phy->clk_pll1)) { > > + dev_err(dev, "Could not get pll-1 clock\n"); > > + ret = PTR_ERR(phy->clk_pll1); > > + goto err_put_clk_mod; > > + } > > + } > > + > > You have a bug here. If phy_clk_num == 1, you'll still try to lookup > pll-1. This is actually WIP patch taken from my github. This issue was fixed already locally on disk. I thought Jagan will not use it until SRAM C patches land. > > And this is a bit sloppy, since if phy_clk_num == 3, you won't try to > lookup pll-2 either. It is highly unlikely this will be higher than 2, at least for this HDMI PHY, since it has only 1 bit reserved for parent selection. But since I have to fix it, I'll add ">= 2" > > > + ret = sun8i_phy_clk_create(phy, dev, phy->variant->phy_clk_num); > > > > if (ret) { > > > > dev_err(dev, "Couldn't create the PHY clock\n"); > > goto err_put_clk_pll0; > > > > @@ -515,8 +530,8 @@ int sun8i_hdmi_phy_probe(struct sun8i_dw_hdmi *hdmi, > > struct device_node *node)> > > err_put_rst_phy: > > reset_control_put(phy->rst_phy); > > > > err_put_clk_pll0: > > - if (phy->variant->has_phy_clk) > > - clk_put(phy->clk_pll0); > > + clk_put(phy->clk_pll0); > > + clk_put(phy->clk_pll1); > > > > err_put_clk_mod: > > clk_put(phy->clk_mod); > > > > err_put_clk_bus: > > @@ -536,8 +551,8 @@ void sun8i_hdmi_phy_remove(struct sun8i_dw_hdmi *hdmi) > > > > reset_control_put(phy->rst_phy); > > > > - if (phy->variant->has_phy_clk) > > - clk_put(phy->clk_pll0); > > + clk_put(phy->clk_pll0); > > + clk_put(phy->clk_pll1); > > > > clk_put(phy->clk_mod); > > clk_put(phy->clk_bus); > > > > } > > > > diff --git a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c > > b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c index > > faea449812f8..85b12fc96dbc 100644 > > --- a/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c > > +++ b/drivers/gpu/drm/sun4i/sun8i_hdmi_phy_clk.c > > @@ -22,29 +22,36 @@ static int sun8i_phy_clk_determine_rate(struct clk_hw > > *hw,> > > { > > > > unsigned long rate = req->rate; > > unsigned long best_rate = 0; > > > > - struct clk_hw *parent; > > + struct clk_hw *best_parent = NULL; > > + struct clk_hw *parent = NULL; > > > > int best_div = 1; > > > > - int i; > > + int i, p; > > > > - parent = clk_hw_get_parent(hw); > > - > > - for (i = 1; i <= 16; i++) { > > - unsigned long ideal = rate * i; > > - unsigned long rounded; > > - > > - rounded = clk_hw_round_rate(parent, ideal); > > - > > - if (rounded == ideal) { > > - best_rate = rounded; > > - best_div = i; > > - break; > > - } > > + for (p = 0; p < clk_hw_get_num_parents(hw); p++) { > > + parent = clk_hw_get_parent_by_index(hw, p); > > + if (!parent) > > + continue; > > > > - if (!best_rate || > > - abs(rate - rounded / i) < > > - abs(rate - best_rate / best_div)) { > > - best_rate = rounded; > > - best_div = i; > > + for (i = 1; i <= 16; i++) { > > + unsigned long ideal = rate * i; > > + unsigned long rounded; > > + > > + rounded = clk_hw_round_rate(parent, ideal); > > + > > + if (rounded == ideal) { > > + best_rate = rounded; > > + best_div = i; > > + best_parent = parent; > > + break; > > + } > > + > > + if (!best_rate || > > + abs(rate - rounded / i) < > > + abs(rate - best_rate / best_div)) { > > + best_rate = rounded; > > + best_div = i; > > + best_parent = parent; > > + } > > > > } > > > > } > > > > @@ -95,22 +102,58 @@ static int sun8i_phy_clk_set_rate(struct clk_hw *hw, > > unsigned long rate,> > > return 0; > > > > } > > > > +static u8 sun8i_phy_clk_get_parent(struct clk_hw *hw) > > +{ > > + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw); > > + u32 reg; > > + > > + regmap_read(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, ®); > > + reg = (reg & SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK) >> > > + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT; > > + > > + return reg; > > +} > > + > > +static int sun8i_phy_clk_set_parent(struct clk_hw *hw, u8 index) > > +{ > > + struct sun8i_phy_clk *priv = hw_to_phy_clk(hw); > > + > > + if (index > 1) > > + return -EINVAL; > > + > > + regmap_update_bits(priv->phy->regs, SUN8I_HDMI_PHY_PLL_CFG1_REG, > > + SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_MSK, > > + index << SUN8I_HDMI_PHY_PLL_CFG1_CKIN_SEL_SHIFT); > > + > > + return 0; > > +} > > + > > The DT bindings changes and the clk changes should be part of separate > patches. By DT bindings changes you mean code which reads DT and not DT documentation, right? Ok, I'll split it. BTW, I'll resend fixed version of this patch for my R40 HDMI series, since there is nothing to hold it back, unlike for this. Best regards, Jernej