Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758270AbcJYCbK (ORCPT ); Mon, 24 Oct 2016 22:31:10 -0400 Received: from mail-db5eur01on0086.outbound.protection.outlook.com ([104.47.2.86]:20736 "EHLO EUR01-DB5-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1754734AbcJYCbI (ORCPT ); Mon, 24 Oct 2016 22:31:08 -0400 From: Andy Duan To: Manfred Schlaegl CC: "netdev@vger.kernel.org" , "linux-kernel@vger.kernel.org" Subject: RE: [PATCH] net: fec: hard phy reset on open Thread-Topic: [PATCH] net: fec: hard phy reset on open Thread-Index: AQHSLdiZneLHT4/sUkO9hsavltavBKC3obwwgAAMZ4CAALX+0A== Date: Tue, 25 Oct 2016 01:56:01 +0000 Message-ID: References: <7c3c37c0-7c24-a63c-b441-b1e8085a3c96@gmx.at> In-Reply-To: Accept-Language: zh-CN, en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: spf=none (sender IP is ) smtp.mailfrom=fugang.duan@nxp.com; x-originating-ip: [192.158.241.86] x-ms-office365-filtering-correlation-id: 4174fdd5-80ce-47b9-819d-08d3fc7a12cb x-microsoft-exchange-diagnostics: 1;AM4PR0401MB2259;7:7YQC8+EBE0l+lpcvjjpYOapQKOjTP2VID6QzoCoGp7SpDxp/i2eTceBXjXw+l+lMYBjaQ1yThOnSZPABuK/7a4NHlCl4aRK+vAmfA8o/C2eFK1mC88JsukrNvAyO6Qaj/8Pt9lSY0r9hfquPr3x7GGYlLzXX/gbPL9IRXz/RZFgQG0OckUm7jILoDvE4sKtSoVU+CPaot3+XVGwsdi7Y1chHdTYRrHAsgmL/GrIaN2x/DoyQCHv0TXIfhpY5ZZmqkFDszh1vP3TEVlpvf6oY8adL6+3Zxz9qgxKNaqpdEgVYvKNDZSQZaZpxscmfVXOzNryncIHtqnci5J3zM02QTUOm+JmwW17YLkkWxDU2f40= x-microsoft-antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:AM4PR0401MB2259; x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(9452136761055)(185117386973197); x-exchange-antispam-report-cfa-test: BCL:0;PCL:0;RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6055026);SRVR:AM4PR0401MB2259;BCL:0;PCL:0;RULEID:;SRVR:AM4PR0401MB2259; x-forefront-prvs: 01068D0A20 x-forefront-antispam-report: SFV:NSPM;SFS:(10009020)(979002)(6009001)(7916002)(199003)(24454002)(377454003)(377424004)(189002)(33656002)(19580395003)(101416001)(19580405001)(7846002)(5002640100001)(9686002)(7736002)(3900700001)(7696004)(586003)(4326007)(6116002)(97736004)(10400500002)(87936001)(102836003)(3846002)(3280700002)(3660700001)(77096005)(2900100001)(189998001)(81166006)(74316002)(105586002)(106116001)(81156014)(2906002)(2950100002)(8676002)(6916009)(92566002)(11100500001)(8936002)(106356001)(305945005)(76576001)(110136003)(122556002)(66066001)(86362001)(50986999)(4001150100001)(5660300001)(76176999)(54356999)(68736007)(309714004)(969003)(989001)(999001)(1009001)(1019001);DIR:OUT;SFP:1101;SCL:1;SRVR:AM4PR0401MB2259;H:AM4PR0401MB2260.eurprd04.prod.outlook.com;FPR:;SPF:None;PTR:InfoNoRecords;A:1;MX:1;LANG:en; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-Type: text/plain; charset="iso-8859-1" MIME-Version: 1.0 X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-originalarrivaltime: 25 Oct 2016 01:56:01.9747 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0401MB2259 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by mail.home.local id u9P2VFEC019110 Content-Length: 8319 Lines: 254 From: Manfred Schlaegl Sent: Monday, October 24, 2016 10:43 PM > To: Andy Duan > Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org > Subject: Re: [PATCH] net: fec: hard phy reset on open > > On 2016-10-24 16:03, Andy Duan wrote: > > From: manfred.schlaegl@gmx.at Sent: > Monday, > > October 24, 2016 5:26 PM > >> To: Andy Duan > >> Cc: netdev@vger.kernel.org; linux-kernel@vger.kernel.org > >> Subject: [PATCH] net: fec: hard phy reset on open > >> > >> We have seen some problems with auto negotiation on i.MX6 using > >> LAN8720, after interface down/up. > >> > >> In our configuration, the ptp clock is used externally as reference > >> clock for the phy. Some phys (e.g. LAN8720) needs a stable clock > >> while and after hard reset. > >> Before this patch, the driver disabled the clock on close but did no > >> hard reset on open, after enabling the clocks again. > >> > >> A solution that prevents disabling the clocks on close was > >> considered, but discarded because of bad power saving behavior. > >> > >> This patch saves the reset dt properties on probe and does a reset on > >> every open after clocks where enabled, to make sure the clock is > >> stable while and after hard reset. > >> > >> Tested on i.MX6 and i.MX28, both using LAN8720. > >> > >> Signed-off-by: Manfred Schlaegl > >> --- > > > This patch did hard reset to let phy stable. > > > Firstly, you should do reset before clock enable. > I have to disagree here. > The phy demands(datasheet + tests) a stable clock at the time of (hard- > )reset and after this. Therefore the clock has to be enabled before the hard > reset. > (This is exactly the reason for the patch.) > > Generally: The sense of a reset is to defer the start of digital circuit until the > environment (power, clocks, ...) has stabilized. > > Furthermore: Before this patch the hard reset was done in fec_probe. And > here also after the clocks were enabled. > > Whats was your argument to do it the other way in this special case? > I check some different vendor phy, hard reset assert after clock stable. But I still don't ensure all phys are this action. > > Secondly, we suggest to do phy reset in phy driver, not MAC driver. > I was not sure, if you meant a soft-, or hard-reset here. > > In case you are talking about soft reset: > Yes, the phy drivers perform a soft reset. Sadly a soft reset is not sufficient in > this case - The phy recovers only on a hard reset from lost clock. (datasheet + > tests) > > In case you're talking about hard reset: > Intuitively I would also think, that the (hard-)reset should be handled by the > phy driver, but this is not reality in given implementations. > > Documentation/devicetree/bindings/net/fsl-fec.txt says > > - phy-reset-gpios : Should specify the gpio for phy reset > > It is explicitly talked about phy-reset here. And the (hard-)reset was handled > by the fec driver also before this patch (once on probe). > I suggest to do phy hard reset in phy driver like: drivers/net/phy/spi_ks8995.c: and Uwe Kleine-K?nig's patch "phy: add support for a reset-gpio specification" (I don't know why the patch is reverted now.) Regards, Andy > > > > Regards, > > Andy > > Thanks for your feedback! > > Best regards, > Manfred > > > > > > >> drivers/net/ethernet/freescale/fec.h | 4 ++ > >> drivers/net/ethernet/freescale/fec_main.c | 77 > >> +++++++++++++++++------- > >> ------- > >> 2 files changed, 47 insertions(+), 34 deletions(-) > >> > >> diff --git a/drivers/net/ethernet/freescale/fec.h > >> b/drivers/net/ethernet/freescale/fec.h > >> index c865135..379e619 100644 > >> --- a/drivers/net/ethernet/freescale/fec.h > >> +++ b/drivers/net/ethernet/freescale/fec.h > >> @@ -498,6 +498,10 @@ struct fec_enet_private { > >> struct clk *clk_enet_out; > >> struct clk *clk_ptp; > >> > >> + int phy_reset; > >> + bool phy_reset_active_high; > >> + int phy_reset_msec; > >> + > >> bool ptp_clk_on; > >> struct mutex ptp_clk_mutex; > >> unsigned int num_tx_queues; > >> diff --git a/drivers/net/ethernet/freescale/fec_main.c > >> b/drivers/net/ethernet/freescale/fec_main.c > >> index 48a033e..8cc1ec5 100644 > >> --- a/drivers/net/ethernet/freescale/fec_main.c > >> +++ b/drivers/net/ethernet/freescale/fec_main.c > >> @@ -2802,6 +2802,22 @@ static int fec_enet_alloc_buffers(struct > >> net_device *ndev) > >> return 0; > >> } > >> > >> +static void fec_reset_phy(struct fec_enet_private *fep) { > >> + if (!gpio_is_valid(fep->phy_reset)) > >> + return; > >> + > >> + gpio_set_value_cansleep(fep->phy_reset, !!fep- > >>> phy_reset_active_high); > >> + > >> + if (fep->phy_reset_msec > 20) > >> + msleep(fep->phy_reset_msec); > >> + else > >> + usleep_range(fep->phy_reset_msec * 1000, > >> + fep->phy_reset_msec * 1000 + 1000); > >> + > >> + gpio_set_value_cansleep(fep->phy_reset, !fep- > >>> phy_reset_active_high); > >> +} > >> + > >> static int > >> fec_enet_open(struct net_device *ndev) { @@ -2817,6 +2833,8 @@ > >> fec_enet_open(struct net_device *ndev) > >> if (ret) > >> goto clk_enable; > >> > >> + fec_reset_phy(fep); > >> + > >> /* I should reset the ring buffers here, but I don't yet know > >> * a simple way to do that. > >> */ > >> @@ -3183,52 +3201,39 @@ static int fec_enet_init(struct net_device > *ndev) > >> return 0; > >> } > >> > >> -#ifdef CONFIG_OF > >> -static void fec_reset_phy(struct platform_device *pdev) > >> +static int > >> +fec_get_reset_phy(struct platform_device *pdev, int *msec, int > >> *phy_reset, > >> + bool *active_high) > >> { > >> - int err, phy_reset; > >> - bool active_high = false; > >> - int msec = 1; > >> + int err; > >> struct device_node *np = pdev->dev.of_node; > >> > >> - if (!np) > >> - return; > >> + if (!np || !of_device_is_available(np)) > >> + return 0; > >> > >> - of_property_read_u32(np, "phy-reset-duration", &msec); > >> + of_property_read_u32(np, "phy-reset-duration", msec); > >> /* A sane reset duration should not be longer than 1s */ > >> - if (msec > 1000) > >> - msec = 1; > >> + if (*msec > 1000) > >> + *msec = 1; > >> > >> - phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); > >> - if (!gpio_is_valid(phy_reset)) > >> - return; > >> + *phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); > >> + if (!gpio_is_valid(*phy_reset)) > >> + return 0; > >> > >> - active_high = of_property_read_bool(np, "phy-reset-active-high"); > >> + *active_high = of_property_read_bool(np, "phy-reset-active-high"); > >> > >> - err = devm_gpio_request_one(&pdev->dev, phy_reset, > >> - active_high ? GPIOF_OUT_INIT_HIGH : > >> GPIOF_OUT_INIT_LOW, > >> - "phy-reset"); > >> + err = devm_gpio_request_one(&pdev->dev, *phy_reset, > >> + *active_high ? > >> + GPIOF_OUT_INIT_HIGH : > >> + GPIOF_OUT_INIT_LOW, > >> + "phy-reset"); > >> if (err) { > >> dev_err(&pdev->dev, "failed to get phy-reset-gpios: %d\n", > err); > >> - return; > >> + return err; > >> } > >> > >> - if (msec > 20) > >> - msleep(msec); > >> - else > >> - usleep_range(msec * 1000, msec * 1000 + 1000); > >> - > >> - gpio_set_value_cansleep(phy_reset, !active_high); > >> -} > >> -#else /* CONFIG_OF */ > >> -static void fec_reset_phy(struct platform_device *pdev) -{ > >> - /* > >> - * In case of platform probe, the reset has been done > >> - * by machine code. > >> - */ > >> + return 0; > >> } > >> -#endif /* CONFIG_OF */ > >> > >> static void > >> fec_enet_get_queue_num(struct platform_device *pdev, int *num_tx, > >> int > >> *num_rx) @@ -3409,7 +3414,10 @@ fec_probe(struct platform_device > >> *pdev) > >> pm_runtime_set_active(&pdev->dev); > >> pm_runtime_enable(&pdev->dev); > >> > >> - fec_reset_phy(pdev); > >> + ret = fec_get_reset_phy(pdev, &fep->phy_reset_msec, &fep- > >>> phy_reset, > >> + &fep->phy_reset_active_high); > >> + if (ret) > >> + goto failed_reset; > >> > >> if (fep->bufdesc_ex) > >> fec_ptp_init(pdev); > >> @@ -3467,6 +3475,7 @@ fec_probe(struct platform_device *pdev) > >> failed_mii_init: > >> failed_irq: > >> failed_init: > >> +failed_reset: > >> fec_ptp_stop(pdev); > >> if (fep->reg_phy) > >> regulator_disable(fep->reg_phy); > >> -- > >> 2.1.4 >