Message ID | 20231225084424.30986-2-quic_luoj@quicinc.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a05:7301:6f82:b0:100:9c79:88ff with SMTP id tb2csp295309dyb; Mon, 25 Dec 2023 00:45:54 -0800 (PST) X-Google-Smtp-Source: AGHT+IHOohVzh8oRLek7cVZtdeMgaVEjoTO9gHkbApf017UUbNgE+2w97edkprP1OFyYHHJ0/ElL X-Received: by 2002:a05:6a20:9708:b0:189:c46d:9790 with SMTP id hr8-20020a056a20970800b00189c46d9790mr5568008pzc.30.1703493954635; Mon, 25 Dec 2023 00:45:54 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1703493954; cv=none; d=google.com; s=arc-20160816; b=R96FlCRDNRVXzGK8EEO5WKqzxodrmODgmTZyA94aJchgmmKZHqM+N86gtceFITkV23 N+LMhR4uDFimCV9l6NXDwblKUqfXWTzhGjr+UasYNcwXU3dIror35f78pwVgIWFx4WQa zaFoP/7Rg03MsehF6XuaP/pRVbBWJZJo6viurblTcjiiLF3HHDfm7RcnzLwmT2GTjdDu Bhp6vQX0qpJL1Px1QgbONp+zQ5HtIvPugiwmFE0vQTCHS/taun3e7D3zlI6eyUcekX34 aNGKIlpe2Ob2C6F44kLObs99CylIFoQ4hokiVKBwa5eLxOuq3HIKdbAcfqulez9WpTDm RlkA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:references:in-reply-to:message-id :date:subject:cc:to:from:dkim-signature; bh=FFW+RKQFRS3hNZWC4B1zbsHCDFZ2KKuoWG+X51zxpU8=; fh=+g5tGayWdOm7NVf+9R7F5Bp+AAhjebsKXKT3IUU1ti0=; b=FRQFNeKJStLd5eD8K6hvr5NFq0YVg+Y0Qe+SwnQnokO51ZIE7tsReu/0EB13tm486l iAKMhKTjegn+K4lpmmqSy4dolILelbF266XWtueqEkNX/WEs42U6tkAvlRrOilPP+8hE wdxbLkJ01s97zcdu2wKkw+lojE80sazTYoizwG+oBK/FF7fJC6AwS1o4+8ghE/GqTp0J +IN+lukS56XzEmFEopkqPO/5gX8XGJcXE97lLJ2y409IktApkIFlsAd0P05rOueXmSK2 nog5nI700BGmUpD4q16dljmZLk/s3lp9iQNFSaOZBzvqxx8oV2JI1TAvMkBgVuM905XC dkIA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=R1o5uZ72; spf=pass (google.com: domain of linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from sy.mirrors.kernel.org (sy.mirrors.kernel.org. [147.75.48.161]) by mx.google.com with ESMTPS id o16-20020a17090ac71000b0028bbbd1228esi7770010pjt.145.2023.12.25.00.45.54 for <ouuuleilei@gmail.com> (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 25 Dec 2023 00:45:54 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) client-ip=147.75.48.161; Authentication-Results: mx.google.com; dkim=pass header.i=@quicinc.com header.s=qcppdkim1 header.b=R1o5uZ72; spf=pass (google.com: domain of linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org designates 147.75.48.161 as permitted sender) smtp.mailfrom="linux-kernel+bounces-10957-ouuuleilei=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=quicinc.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by sy.mirrors.kernel.org (Postfix) with ESMTPS id 35B9AB2118C for <ouuuleilei@gmail.com>; Mon, 25 Dec 2023 08:45:45 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 4DB40101C1; Mon, 25 Dec 2023 08:45:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=quicinc.com header.i=@quicinc.com header.b="R1o5uZ72" X-Original-To: linux-kernel@vger.kernel.org Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4A756CA7A; Mon, 25 Dec 2023 08:45:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=quicinc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=quicinc.com Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.17.1.24/8.17.1.24) with ESMTP id 3BP7A3II019837; Mon, 25 Dec 2023 08:44:47 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=quicinc.com; h= from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding:content-type; s= qcppdkim1; bh=FFW+RKQFRS3hNZWC4B1zbsHCDFZ2KKuoWG+X51zxpU8=; b=R1 o5uZ72Yx+TD33LivsZtncTRKRn5FyBJXVyGIiT0gzw8R4wKl9EUGILvXVmN2ETHp fLzeWEq9LYzzmI5N4uASSxiEie1MNxkPFgMRNGxn1dOgviazM14LtcSp3rwvBxWK UJus/JxXoHy9QxSAFSl8jQ133cEP9zYfriSTLnP3VKg6zVu5SQQ3rOhEkF497N/h 6dRrhIJtXOHQMPjMCupJKLuoxYKxhb1eYoAaZi+DkE3mmghx/5GF3zixvtwqIFjE 6+fVhu89C+Uc6c4/trYLwNgq6shNAEAfyOgonXti3L2u/cLzUUOBcDBjAsnUDYzA uZ2Riv18yifi6XE1Pw7g== Received: from nalasppmta03.qualcomm.com (Global_NAT1.qualcomm.com [129.46.96.20]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 3v5mwr3fc6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Dec 2023 08:44:47 +0000 (GMT) Received: from nalasex01c.na.qualcomm.com (nalasex01c.na.qualcomm.com [10.47.97.35]) by NALASPPMTA03.qualcomm.com (8.17.1.5/8.17.1.5) with ESMTPS id 3BP8ikZI025490 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Mon, 25 Dec 2023 08:44:46 GMT Received: from akronite-sh-dev02.qualcomm.com (10.80.80.8) by nalasex01c.na.qualcomm.com (10.47.97.35) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.40; Mon, 25 Dec 2023 00:44:41 -0800 From: Luo Jie <quic_luoj@quicinc.com> To: <agross@kernel.org>, <andersson@kernel.org>, <konrad.dybcio@linaro.org>, <davem@davemloft.net>, <edumazet@google.com>, <kuba@kernel.org>, <pabeni@redhat.com>, <robh+dt@kernel.org>, <krzysztof.kozlowski+dt@linaro.org>, <conor+dt@kernel.org>, <andrew@lunn.ch>, <hkallweit1@gmail.com>, <linux@armlinux.org.uk>, <robert.marko@sartura.hr> CC: <linux-arm-msm@vger.kernel.org>, <netdev@vger.kernel.org>, <devicetree@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <quic_srichara@quicinc.com> Subject: [PATCH v4 1/5] net: mdio: ipq4019: move eth_ldo_rdy before MDIO bus register Date: Mon, 25 Dec 2023 16:44:20 +0800 Message-ID: <20231225084424.30986-2-quic_luoj@quicinc.com> X-Mailer: git-send-email 2.42.0 In-Reply-To: <20231225084424.30986-1-quic_luoj@quicinc.com> References: <20231225084424.30986-1-quic_luoj@quicinc.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: <linux-kernel.vger.kernel.org> List-Subscribe: <mailto:linux-kernel+subscribe@vger.kernel.org> List-Unsubscribe: <mailto:linux-kernel+unsubscribe@vger.kernel.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-ClientProxiedBy: nasanex01a.na.qualcomm.com (10.52.223.231) To nalasex01c.na.qualcomm.com (10.47.97.35) X-QCInternal: smtphost X-Proofpoint-Virus-Version: vendor=nai engine=6200 definitions=5800 signatures=585085 X-Proofpoint-GUID: jg7JjeldXH8xeTi_Hr6Pn8KZS3S8PW8F X-Proofpoint-ORIG-GUID: jg7JjeldXH8xeTi_Hr6Pn8KZS3S8PW8F X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.997,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2023-12-09_02,2023-12-07_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 mlxlogscore=999 clxscore=1015 lowpriorityscore=0 bulkscore=0 malwarescore=0 impostorscore=0 adultscore=0 phishscore=0 mlxscore=0 spamscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.19.0-2311290000 definitions=main-2312250066 X-getmail-retrieved-from-mailbox: INBOX X-GMAIL-THRID: 1786242877325353454 X-GMAIL-MSGID: 1786242877325353454 |
Series |
support ipq5332 platform
|
|
Commit Message
Jie Luo
Dec. 25, 2023, 8:44 a.m. UTC
The ethernet LDO provides the clock for the ethernet PHY that
is connected with PCS, each LDO enables the clock output to
each PCS, after the clock output enablement, the PHY GPIO reset
can take effect.
For the PHY taking the MDIO bus level GPIO reset, the ethernet
LDO should be enabled before the MDIO bus register.
For example, the qca8084 PHY takes the MDIO bus level GPIO
reset for quad PHYs, there is another reason for qca8084 PHY
using MDIO bus level GPIO reset instead of PHY level GPIO
reset as below.
The work sequence of qca8084:
1. enable ethernet LDO.
2. GPIO reset on quad PHYs.
3. register clock provider based on MDIO device of qca8084.
4. PHY probe function called for initializing common clocks.
5. PHY capabilities acquirement.
If qca8084 takes PHY level GPIO reset in the step 4, the clock
provider of qca8084 can't be registered correctly, since the
clock parent(reading the current qca8084 hardware registers in
step 3) of the registered clocks is deserted after GPIO reset.
There are two PCS(UNIPHY) supported in SOC side on ipq5332,
and three PCS(UNIPHY) supported on ipq9574.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
---
drivers/net/mdio/mdio-ipq4019.c | 51 +++++++++++++++++++++------------
1 file changed, 32 insertions(+), 19 deletions(-)
Comments
On 25.12.2023 09:44, Luo Jie wrote: > The ethernet LDO provides the clock for the ethernet PHY that > is connected with PCS, each LDO enables the clock output to > each PCS, after the clock output enablement, the PHY GPIO reset > can take effect. > > For the PHY taking the MDIO bus level GPIO reset, the ethernet > LDO should be enabled before the MDIO bus register. > > For example, the qca8084 PHY takes the MDIO bus level GPIO > reset for quad PHYs, there is another reason for qca8084 PHY > using MDIO bus level GPIO reset instead of PHY level GPIO > reset as below. > > The work sequence of qca8084: > 1. enable ethernet LDO. > 2. GPIO reset on quad PHYs. > 3. register clock provider based on MDIO device of qca8084. > 4. PHY probe function called for initializing common clocks. > 5. PHY capabilities acquirement. > > If qca8084 takes PHY level GPIO reset in the step 4, the clock > provider of qca8084 can't be registered correctly, since the > clock parent(reading the current qca8084 hardware registers in > step 3) of the registered clocks is deserted after GPIO reset. > > There are two PCS(UNIPHY) supported in SOC side on ipq5332, > and three PCS(UNIPHY) supported on ipq9574. > > Signed-off-by: Luo Jie <quic_luoj@quicinc.com> > --- > drivers/net/mdio/mdio-ipq4019.c | 51 +++++++++++++++++++++------------ > 1 file changed, 32 insertions(+), 19 deletions(-) > > diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c > index abd8b508ec16..5273864fabb3 100644 > --- a/drivers/net/mdio/mdio-ipq4019.c > +++ b/drivers/net/mdio/mdio-ipq4019.c > @@ -37,9 +37,12 @@ > > #define IPQ_PHY_SET_DELAY_US 100000 > > +/* Maximum SOC PCS(uniphy) number on IPQ platform */ > +#define ETH_LDO_RDY_CNT 3 > + > struct ipq4019_mdio_data { > - void __iomem *membase; > - void __iomem *eth_ldo_rdy; > + void __iomem *membase; > + void __iomem *eth_ldo_rdy[ETH_LDO_RDY_CNT]; > struct clk *mdio_clk; > }; > > @@ -206,19 +209,8 @@ static int ipq4019_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum, > static int ipq_mdio_reset(struct mii_bus *bus) > { > struct ipq4019_mdio_data *priv = bus->priv; > - u32 val; > int ret; > > - /* To indicate CMN_PLL that ethernet_ldo has been ready if platform resource 1 > - * is specified in the device tree. > - */ > - if (priv->eth_ldo_rdy) { > - val = readl(priv->eth_ldo_rdy); > - val |= BIT(0); > - writel(val, priv->eth_ldo_rdy); > - fsleep(IPQ_PHY_SET_DELAY_US); > - } > - > /* Configure MDIO clock source frequency if clock is specified in the device tree */ > ret = clk_set_rate(priv->mdio_clk, IPQ_MDIO_CLK_RATE); > if (ret) > @@ -236,7 +228,7 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) > struct ipq4019_mdio_data *priv; > struct mii_bus *bus; > struct resource *res; > - int ret; > + int ret, index; > > bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); > if (!bus) > @@ -252,11 +244,32 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) > if (IS_ERR(priv->mdio_clk)) > return PTR_ERR(priv->mdio_clk); > > - /* The platform resource is provided on the chipset IPQ5018 */ > - /* This resource is optional */ > - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); > - if (res) > - priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res); > + /* These platform resources are provided on the chipset IPQ5018 or > + * IPQ5332. > + */ > + /* This resource are optional */ > + for (index = 0; index < ETH_LDO_RDY_CNT; index++) { > + res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); > + if (res) { if (!res) break > + priv->eth_ldo_rdy[index] = devm_ioremap(&pdev->dev, > + res->start, > + resource_size(res)); > + > + /* The ethernet LDO enable is necessary to reset PHY > + * by GPIO, some PHY(such as qca8084) GPIO reset uses > + * the MDIO level reset, so this function should be > + * called before the MDIO bus register. > + */ > + if (priv->eth_ldo_rdy[index]) { > + u32 val; > + > + val = readl(priv->eth_ldo_rdy[index]); > + val |= BIT(0); > + writel(val, priv->eth_ldo_rdy[index]); > + fsleep(IPQ_PHY_SET_DELAY_US); fsleep should only be used when the argument is variable Konrad
On 12/28/2023 5:49 PM, Konrad Dybcio wrote: > On 25.12.2023 09:44, Luo Jie wrote: >> The ethernet LDO provides the clock for the ethernet PHY that >> is connected with PCS, each LDO enables the clock output to >> each PCS, after the clock output enablement, the PHY GPIO reset >> can take effect. >> >> For the PHY taking the MDIO bus level GPIO reset, the ethernet >> LDO should be enabled before the MDIO bus register. >> >> For example, the qca8084 PHY takes the MDIO bus level GPIO >> reset for quad PHYs, there is another reason for qca8084 PHY >> using MDIO bus level GPIO reset instead of PHY level GPIO >> reset as below. >> >> The work sequence of qca8084: >> 1. enable ethernet LDO. >> 2. GPIO reset on quad PHYs. >> 3. register clock provider based on MDIO device of qca8084. >> 4. PHY probe function called for initializing common clocks. >> 5. PHY capabilities acquirement. >> >> If qca8084 takes PHY level GPIO reset in the step 4, the clock >> provider of qca8084 can't be registered correctly, since the >> clock parent(reading the current qca8084 hardware registers in >> step 3) of the registered clocks is deserted after GPIO reset. >> >> There are two PCS(UNIPHY) supported in SOC side on ipq5332, >> and three PCS(UNIPHY) supported on ipq9574. >> >> Signed-off-by: Luo Jie <quic_luoj@quicinc.com> >> --- >> drivers/net/mdio/mdio-ipq4019.c | 51 +++++++++++++++++++++------------ >> 1 file changed, 32 insertions(+), 19 deletions(-) >> >> diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c >> index abd8b508ec16..5273864fabb3 100644 >> --- a/drivers/net/mdio/mdio-ipq4019.c >> +++ b/drivers/net/mdio/mdio-ipq4019.c >> @@ -37,9 +37,12 @@ >> >> #define IPQ_PHY_SET_DELAY_US 100000 >> >> +/* Maximum SOC PCS(uniphy) number on IPQ platform */ >> +#define ETH_LDO_RDY_CNT 3 >> + >> struct ipq4019_mdio_data { >> - void __iomem *membase; >> - void __iomem *eth_ldo_rdy; >> + void __iomem *membase; >> + void __iomem *eth_ldo_rdy[ETH_LDO_RDY_CNT]; >> struct clk *mdio_clk; >> }; >> >> @@ -206,19 +209,8 @@ static int ipq4019_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum, >> static int ipq_mdio_reset(struct mii_bus *bus) >> { >> struct ipq4019_mdio_data *priv = bus->priv; >> - u32 val; >> int ret; >> >> - /* To indicate CMN_PLL that ethernet_ldo has been ready if platform resource 1 >> - * is specified in the device tree. >> - */ >> - if (priv->eth_ldo_rdy) { >> - val = readl(priv->eth_ldo_rdy); >> - val |= BIT(0); >> - writel(val, priv->eth_ldo_rdy); >> - fsleep(IPQ_PHY_SET_DELAY_US); >> - } >> - >> /* Configure MDIO clock source frequency if clock is specified in the device tree */ >> ret = clk_set_rate(priv->mdio_clk, IPQ_MDIO_CLK_RATE); >> if (ret) >> @@ -236,7 +228,7 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) >> struct ipq4019_mdio_data *priv; >> struct mii_bus *bus; >> struct resource *res; >> - int ret; >> + int ret, index; >> >> bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); >> if (!bus) >> @@ -252,11 +244,32 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) >> if (IS_ERR(priv->mdio_clk)) >> return PTR_ERR(priv->mdio_clk); >> >> - /* The platform resource is provided on the chipset IPQ5018 */ >> - /* This resource is optional */ >> - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); >> - if (res) >> - priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res); >> + /* These platform resources are provided on the chipset IPQ5018 or >> + * IPQ5332. >> + */ >> + /* This resource are optional */ >> + for (index = 0; index < ETH_LDO_RDY_CNT; index++) { >> + res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); >> + if (res) { > if (!res) > break will update this. > >> + priv->eth_ldo_rdy[index] = devm_ioremap(&pdev->dev, >> + res->start, >> + resource_size(res)); >> + >> + /* The ethernet LDO enable is necessary to reset PHY >> + * by GPIO, some PHY(such as qca8084) GPIO reset uses >> + * the MDIO level reset, so this function should be >> + * called before the MDIO bus register. >> + */ >> + if (priv->eth_ldo_rdy[index]) { >> + u32 val; >> + >> + val = readl(priv->eth_ldo_rdy[index]); >> + val |= BIT(0); >> + writel(val, priv->eth_ldo_rdy[index]); >> + fsleep(IPQ_PHY_SET_DELAY_US); > fsleep should only be used when the argument is variable > > Konrad Ok, will update to use usleep_range, Thanks.
On Mon, Dec 25, 2023 at 04:44:20PM +0800, Luo Jie wrote: > +/* Maximum SOC PCS(uniphy) number on IPQ platform */ > +#define ETH_LDO_RDY_CNT 3 > + > struct ipq4019_mdio_data { > - void __iomem *membase; > - void __iomem *eth_ldo_rdy; > + void __iomem *membase; > + void __iomem *eth_ldo_rdy[ETH_LDO_RDY_CNT]; Do you have any plans to make use of eth_ldo_rdy other than by code that you touch in this patch? If you don't, what is the point of storing these points in struct ipq4019_mdio_data ? You're using devm_ioremap() which will already store the pointer internally to be able to free the resource at the appropriate moment, so if your only use is shortly after devm_ioremap(), you can use a local variable for this... meaning this becomes (in addition to the other suggestion): > + /* This resource are optional */ > + for (index = 0; index < ETH_LDO_RDY_CNT; index++) { > + res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); > + if (res) { > + priv->eth_ldo_rdy[index] = devm_ioremap(&pdev->dev, > + res->start, > + resource_size(res)); > + > + /* The ethernet LDO enable is necessary to reset PHY > + * by GPIO, some PHY(such as qca8084) GPIO reset uses > + * the MDIO level reset, so this function should be > + * called before the MDIO bus register. > + */ > + if (priv->eth_ldo_rdy[index]) { > + u32 val; > + > + val = readl(priv->eth_ldo_rdy[index]); > + val |= BIT(0); > + writel(val, priv->eth_ldo_rdy[index]); > + fsleep(IPQ_PHY_SET_DELAY_US); > + } > + } void __iomem *eth_ldo_rdy; u32 val; res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); if (!res) break; eth_ldo_rdy = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!eth_ldo_rdy) continue; val = readl(eth_ldo_rdy) | BIT(0); writel(val, eth_ldo_rdy); ... whatever sleep is deemed required ... Other issues: 1. if devm_ioremap() fails (returns NULL) is it right that we should just ignore that resource? 2. Do you need to sleep after each write, or will sleeping after writing all of these do? It may be more efficient to detect when we have at least one eth_ldo_rdy and then sleep once. Thanks.
On 1/3/2024 1:24 AM, Russell King (Oracle) wrote: > On Mon, Dec 25, 2023 at 04:44:20PM +0800, Luo Jie wrote: >> +/* Maximum SOC PCS(uniphy) number on IPQ platform */ >> +#define ETH_LDO_RDY_CNT 3 >> + >> struct ipq4019_mdio_data { >> - void __iomem *membase; >> - void __iomem *eth_ldo_rdy; >> + void __iomem *membase; >> + void __iomem *eth_ldo_rdy[ETH_LDO_RDY_CNT]; > > Do you have any plans to make use of eth_ldo_rdy other than by code that > you touch in this patch? If you don't, what is the point of storing > these points in struct ipq4019_mdio_data ? You're using devm_ioremap() > which will already store the pointer internally to be able to free the > resource at the appropriate moment, so if your only use is shortly after > devm_ioremap(), you can use a local variable for this... meaning this > becomes (in addition to the other suggestion): I will remove the eth_lod_rdy from the structure, which is only for enabling LDO shortly, will update to use the local variable for this. Thanks for review comments. > >> + /* This resource are optional */ >> + for (index = 0; index < ETH_LDO_RDY_CNT; index++) { >> + res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); >> + if (res) { >> + priv->eth_ldo_rdy[index] = devm_ioremap(&pdev->dev, >> + res->start, >> + resource_size(res)); >> + >> + /* The ethernet LDO enable is necessary to reset PHY >> + * by GPIO, some PHY(such as qca8084) GPIO reset uses >> + * the MDIO level reset, so this function should be >> + * called before the MDIO bus register. >> + */ >> + if (priv->eth_ldo_rdy[index]) { >> + u32 val; >> + >> + val = readl(priv->eth_ldo_rdy[index]); >> + val |= BIT(0); >> + writel(val, priv->eth_ldo_rdy[index]); >> + fsleep(IPQ_PHY_SET_DELAY_US); >> + } >> + } > > void __iomem *eth_ldo_rdy; > u32 val; > > res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); > if (!res) > break; > > eth_ldo_rdy = devm_ioremap(&pdev->dev, res->start, > resource_size(res)); > if (!eth_ldo_rdy) > continue; > > val = readl(eth_ldo_rdy) | BIT(0); > writel(val, eth_ldo_rdy); > ... whatever sleep is deemed required ... > > Other issues: > > 1. if devm_ioremap() fails (returns NULL) is it right that we should > just ignore that resource? Since each LDO is independent, each LDO is for controlling the independent Ethernet device, that should be fine to ignore the failed resource. > > 2. Do you need to sleep after each write, or will sleeping after > writing all of these do? It may be more efficient to detect when > we have at least one eth_ldo_rdy and then sleep once. Yes, sleeping can be used after writing all of these, will update the code as you suggest, thanks Russell. > > Thanks. >
diff --git a/drivers/net/mdio/mdio-ipq4019.c b/drivers/net/mdio/mdio-ipq4019.c index abd8b508ec16..5273864fabb3 100644 --- a/drivers/net/mdio/mdio-ipq4019.c +++ b/drivers/net/mdio/mdio-ipq4019.c @@ -37,9 +37,12 @@ #define IPQ_PHY_SET_DELAY_US 100000 +/* Maximum SOC PCS(uniphy) number on IPQ platform */ +#define ETH_LDO_RDY_CNT 3 + struct ipq4019_mdio_data { - void __iomem *membase; - void __iomem *eth_ldo_rdy; + void __iomem *membase; + void __iomem *eth_ldo_rdy[ETH_LDO_RDY_CNT]; struct clk *mdio_clk; }; @@ -206,19 +209,8 @@ static int ipq4019_mdio_write_c22(struct mii_bus *bus, int mii_id, int regnum, static int ipq_mdio_reset(struct mii_bus *bus) { struct ipq4019_mdio_data *priv = bus->priv; - u32 val; int ret; - /* To indicate CMN_PLL that ethernet_ldo has been ready if platform resource 1 - * is specified in the device tree. - */ - if (priv->eth_ldo_rdy) { - val = readl(priv->eth_ldo_rdy); - val |= BIT(0); - writel(val, priv->eth_ldo_rdy); - fsleep(IPQ_PHY_SET_DELAY_US); - } - /* Configure MDIO clock source frequency if clock is specified in the device tree */ ret = clk_set_rate(priv->mdio_clk, IPQ_MDIO_CLK_RATE); if (ret) @@ -236,7 +228,7 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) struct ipq4019_mdio_data *priv; struct mii_bus *bus; struct resource *res; - int ret; + int ret, index; bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*priv)); if (!bus) @@ -252,11 +244,32 @@ static int ipq4019_mdio_probe(struct platform_device *pdev) if (IS_ERR(priv->mdio_clk)) return PTR_ERR(priv->mdio_clk); - /* The platform resource is provided on the chipset IPQ5018 */ - /* This resource is optional */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (res) - priv->eth_ldo_rdy = devm_ioremap_resource(&pdev->dev, res); + /* These platform resources are provided on the chipset IPQ5018 or + * IPQ5332. + */ + /* This resource are optional */ + for (index = 0; index < ETH_LDO_RDY_CNT; index++) { + res = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); + if (res) { + priv->eth_ldo_rdy[index] = devm_ioremap(&pdev->dev, + res->start, + resource_size(res)); + + /* The ethernet LDO enable is necessary to reset PHY + * by GPIO, some PHY(such as qca8084) GPIO reset uses + * the MDIO level reset, so this function should be + * called before the MDIO bus register. + */ + if (priv->eth_ldo_rdy[index]) { + u32 val; + + val = readl(priv->eth_ldo_rdy[index]); + val |= BIT(0); + writel(val, priv->eth_ldo_rdy[index]); + fsleep(IPQ_PHY_SET_DELAY_US); + } + } + } bus->name = "ipq4019_mdio"; bus->read = ipq4019_mdio_read_c22;