All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Heiko Stübner" <heiko@sntech.de>
To: Kishon Vijay Abraham I <kishon@ti.com>
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
	linux-rockchip@lists.infradead.org, robh+dt@kernel.org,
	robin.murphy@arm.com, linux-arm-kernel@lists.infradead.org,
	zhengyang@rock-chips.com
Subject: Re: [PATCH v3 RESEND 2/2] phy: add Rockchip Innosilicon hdmi phy
Date: Fri, 31 Aug 2018 11:26:01 +0200	[thread overview]
Message-ID: <21954745.lUUHsRAzaY@diego> (raw)
In-Reply-To: <4194245.uYZyAYm7Hd@phil>

Am Dienstag, 14. August 2018, 14:52:00 CEST schrieb Heiko Stuebner:
> Hi Kishon,
> 
> thanks for your review.
> 
> Am Freitag, 3. August 2018, 11:24:06 CEST schrieb Kishon Vijay Abraham I:
> > On Tuesday 10 July 2018 07:19 PM, Heiko Stuebner wrote:
> > > +config PHY_ROCKCHIP_INNO_HDMI
> > > +	tristate "Rockchip INNO HDMI PHY Driver"
> > > +	depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
> > 
> > depends on COMMON_CLK since the phy registers a clock provider?
> 
> ok
> 
> > > +static const struct phy_config rk3228_phy_cfg[] = {
> > > +	{	165000000, {
> > > +			0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +			0x00, 0x00, 0x00, 0x00, 0x00,
> > 
> > If these register configurations are not a tuning value or dividers (which
> > can have absolute values), then we should have macros for each of these
> > configurations.
> That might get difficult.
> 
> That phy register set is completely undocumented even in the vendor TRMs
> of the 2 socs. I pieced together most existing macros from code comments
> and such from the vendor kernel. And Innosilicon is not known to willingly
> share much of their register documentation it seems.
> 
> > > +static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy
> > > *inno,
> > > +					       unsigned long rate)
> > > +{
> > > +	int bus_width = phy_get_bus_width(inno->phy);
> > 
> > hmm, the bus_width could be a member of struct inno_hdmi_phy. PHY API's
> > don't have to be used for getting data within the PHY driver itself.
> > Looking at the phy_get_bus_width() implementation, we should have
> > protected
> > bus-width set and get with mutex. With that there might be a deadlock
> > here.
> 
> ok, so just read phy->attrs.bus_width directly here?
> 
> I don't see how this can be part of struct inno_hdmi_phy, as the bus-width
> depends on the color-depth used on the hdmi-controller side, so
> depending on that it will want to adapt the phy's bus_width.
> 
> Right now our dw_hdmi in mainline only supports one output format
> requiring a bus_width of 8, but the vendor kernel shows [0] how this
> wants to be used with multiple output formats.
> 
> [0]
> https://github.com/rockchip-linux/kernel/blob/release-4.4/drivers/gpu/drm/r
> ockchip/dw_hdmi-rockchip.c#L817
> > > +static irqreturn_t inno_hdmi_phy_rk3328_irq(int irq, void *dev_id)
> > > +{
> > > +	struct inno_hdmi_phy *inno = dev_id;
> > > +
> > > +	inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0);
> > > +	usleep_range(9, 10);
> > 
> > This range looks very narrow. 10 to 20 should be okay?
> 
> ok
> 
> > > +static void inno_hdmi_phy_action(void *data)
> > > +{
> > > +	struct inno_hdmi_phy *inno = data;
> > > +
> > > +	clk_disable_unprepare(inno->refpclk);
> > > +	clk_disable_unprepare(inno->sysclk);
> > > +}
> > > +
> > > +static int inno_hdmi_phy_probe(struct platform_device *pdev)
> > > +{
> > > +	struct inno_hdmi_phy *inno;
> > > +	const struct of_device_id *match;
> > > +	struct phy_provider *phy_provider;
> > > +	struct resource *res;
> > > +	void __iomem *regs;
> > > +	int ret;
> > > +
> 
> [...]
> 
> > > +	/*
> > > +	 * Refpclk needs to be on, on at least the rk3328 for still
> > > +	 * unknown reasons.
> > > +	 */
> > > +	ret = clk_prepare_enable(inno->refpclk);
> > > +	if (ret) {
> > > +		dev_err(inno->dev, "failed to enable refpclk\n");
> > > +		clk_disable_unprepare(inno->sysclk);
> > > +		return ret;
> > > +	}
> > > +
> > > +	ret = devm_add_action_or_reset(inno->dev, inno_hdmi_phy_action,
> > > +				       inno);
> > > +	if (ret) {
> > > +		clk_disable_unprepare(inno->refpclk);
> > > +		clk_disable_unprepare(inno->sysclk);
> > > +		return ret;
> > > +	}
> > > +
> > > +	inno->regmap = devm_regmap_init_mmio(inno->dev, regs,
> > > +					     &inno_hdmi_phy_regmap_config);
> > > +	if (IS_ERR(inno->regmap))
> > 
> > here too clk_disable_unprepare and all error handling below?
> > It's better if we just handle error handling at the bottom of the
> > function.
> 
> Nope ;-) ... I.e. the goal of registering the devm_action above is to have
> the clocks get disabled in the correct order when devm undoes the other
> things in sequence.
> 
> Manual error handling for the clocks would also break devm, as then
> the clocks would get disabled before the devm cleanup kicks in.

but I just realized, that I don't need the initial disable_unprepare calls
anymore as well, as devm_add_action_or_reset will call that itself
in the error case.

WARNING: multiple messages have this Message-ID (diff)
From: heiko@sntech.de (Heiko Stübner)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v3 RESEND 2/2] phy: add Rockchip Innosilicon hdmi phy
Date: Fri, 31 Aug 2018 11:26:01 +0200	[thread overview]
Message-ID: <21954745.lUUHsRAzaY@diego> (raw)
In-Reply-To: <4194245.uYZyAYm7Hd@phil>

Am Dienstag, 14. August 2018, 14:52:00 CEST schrieb Heiko Stuebner:
> Hi Kishon,
> 
> thanks for your review.
> 
> Am Freitag, 3. August 2018, 11:24:06 CEST schrieb Kishon Vijay Abraham I:
> > On Tuesday 10 July 2018 07:19 PM, Heiko Stuebner wrote:
> > > +config PHY_ROCKCHIP_INNO_HDMI
> > > +	tristate "Rockchip INNO HDMI PHY Driver"
> > > +	depends on (ARCH_ROCKCHIP || COMPILE_TEST) && OF
> > 
> > depends on COMMON_CLK since the phy registers a clock provider?
> 
> ok
> 
> > > +static const struct phy_config rk3228_phy_cfg[] = {
> > > +	{	165000000, {
> > > +			0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
> > > +			0x00, 0x00, 0x00, 0x00, 0x00,
> > 
> > If these register configurations are not a tuning value or dividers (which
> > can have absolute values), then we should have macros for each of these
> > configurations.
> That might get difficult.
> 
> That phy register set is completely undocumented even in the vendor TRMs
> of the 2 socs. I pieced together most existing macros from code comments
> and such from the vendor kernel. And Innosilicon is not known to willingly
> share much of their register documentation it seems.
> 
> > > +static unsigned long inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy
> > > *inno,
> > > +					       unsigned long rate)
> > > +{
> > > +	int bus_width = phy_get_bus_width(inno->phy);
> > 
> > hmm, the bus_width could be a member of struct inno_hdmi_phy. PHY API's
> > don't have to be used for getting data within the PHY driver itself.
> > Looking at the phy_get_bus_width() implementation, we should have
> > protected
> > bus-width set and get with mutex. With that there might be a deadlock
> > here.
> 
> ok, so just read phy->attrs.bus_width directly here?
> 
> I don't see how this can be part of struct inno_hdmi_phy, as the bus-width
> depends on the color-depth used on the hdmi-controller side, so
> depending on that it will want to adapt the phy's bus_width.
> 
> Right now our dw_hdmi in mainline only supports one output format
> requiring a bus_width of 8, but the vendor kernel shows [0] how this
> wants to be used with multiple output formats.
> 
> [0]
> https://github.com/rockchip-linux/kernel/blob/release-4.4/drivers/gpu/drm/r
> ockchip/dw_hdmi-rockchip.c#L817
> > > +static irqreturn_t inno_hdmi_phy_rk3328_irq(int irq, void *dev_id)
> > > +{
> > > +	struct inno_hdmi_phy *inno = dev_id;
> > > +
> > > +	inno_update_bits(inno, 0x02, RK3328_PDATA_EN, 0);
> > > +	usleep_range(9, 10);
> > 
> > This range looks very narrow. 10 to 20 should be okay?
> 
> ok
> 
> > > +static void inno_hdmi_phy_action(void *data)
> > > +{
> > > +	struct inno_hdmi_phy *inno = data;
> > > +
> > > +	clk_disable_unprepare(inno->refpclk);
> > > +	clk_disable_unprepare(inno->sysclk);
> > > +}
> > > +
> > > +static int inno_hdmi_phy_probe(struct platform_device *pdev)
> > > +{
> > > +	struct inno_hdmi_phy *inno;
> > > +	const struct of_device_id *match;
> > > +	struct phy_provider *phy_provider;
> > > +	struct resource *res;
> > > +	void __iomem *regs;
> > > +	int ret;
> > > +
> 
> [...]
> 
> > > +	/*
> > > +	 * Refpclk needs to be on, on at least the rk3328 for still
> > > +	 * unknown reasons.
> > > +	 */
> > > +	ret = clk_prepare_enable(inno->refpclk);
> > > +	if (ret) {
> > > +		dev_err(inno->dev, "failed to enable refpclk\n");
> > > +		clk_disable_unprepare(inno->sysclk);
> > > +		return ret;
> > > +	}
> > > +
> > > +	ret = devm_add_action_or_reset(inno->dev, inno_hdmi_phy_action,
> > > +				       inno);
> > > +	if (ret) {
> > > +		clk_disable_unprepare(inno->refpclk);
> > > +		clk_disable_unprepare(inno->sysclk);
> > > +		return ret;
> > > +	}
> > > +
> > > +	inno->regmap = devm_regmap_init_mmio(inno->dev, regs,
> > > +					     &inno_hdmi_phy_regmap_config);
> > > +	if (IS_ERR(inno->regmap))
> > 
> > here too clk_disable_unprepare and all error handling below?
> > It's better if we just handle error handling at the bottom of the
> > function.
> 
> Nope ;-) ... I.e. the goal of registering the devm_action above is to have
> the clocks get disabled in the correct order when devm undoes the other
> things in sequence.
> 
> Manual error handling for the clocks would also break devm, as then
> the clocks would get disabled before the devm cleanup kicks in.

but I just realized, that I don't need the initial disable_unprepare calls
anymore as well, as devm_add_action_or_reset will call that itself
in the error case.

  reply	other threads:[~2018-08-31  9:26 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-07-10 13:49 [PATCH v3 RESEND 1/2] dt-bindings: add binding for Rockchip hdmi phy using an Innosilicon IP Heiko Stuebner
2018-07-10 13:49 ` Heiko Stuebner
2018-07-10 13:49 ` [PATCH v3 RESEND 2/2] phy: add Rockchip Innosilicon hdmi phy Heiko Stuebner
2018-07-10 13:49   ` Heiko Stuebner
2018-08-03  9:24   ` Kishon Vijay Abraham I
2018-08-03  9:24     ` Kishon Vijay Abraham I
2018-08-14 12:52     ` Heiko Stuebner
2018-08-14 12:52       ` Heiko Stuebner
2018-08-31  9:26       ` Heiko Stübner [this message]
2018-08-31  9:26         ` Heiko Stübner
2018-09-06  9:38         ` Kishon Vijay Abraham I
2018-09-06  9:38           ` Kishon Vijay Abraham I
2018-09-06 13:52           ` Heiko Stuebner
2018-09-06 13:52             ` Heiko Stuebner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=21954745.lUUHsRAzaY@diego \
    --to=heiko@sntech.de \
    --cc=devicetree@vger.kernel.org \
    --cc=kishon@ti.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-rockchip@lists.infradead.org \
    --cc=mark.rutland@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=zhengyang@rock-chips.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.