From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.2 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_PATCH,MAILING_LIST_MULTI, SIGNED_OFF_BY,SPF_PASS,UNWANTED_LANGUAGE_BODY,URIBL_BLOCKED, USER_AGENT_NEOMUTT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8E238C4360F for ; Wed, 3 Apr 2019 09:49:20 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 579802084B for ; Wed, 3 Apr 2019 09:49:20 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (2048-bit key) header.d=lists.infradead.org header.i=@lists.infradead.org header.b="L2tOwpqh"; dkim=fail reason="signature verification failed" (2048-bit key) header.d=armlinux.org.uk header.i=@armlinux.org.uk header.b="JAzlNv/b" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 579802084B Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=armlinux.org.uk Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=fm9jNAVttq5Pqd/vTptSsjU0JDrur8QAYJLlJ4+GqzU=; b=L2tOwpqhjatY4H FuQ7ud7pvH7uxXlIsf9cmojiNl9M78xdixspmiCijjaGP0Vg5RqzReiDACOZYNy2oAxSL1TN7fgrg Np+kEuN5oPOeTVqxA35MNcqRj882RMkEy/dl+Z/AYGSBaGZPIrVJyylJjikSJO4kF9FqYe/ePkGu1 xbDXzuFuIw10v4hcHM7ahij425pdLjd1rTPIgiGJ9bUqC6LYUNmV8z9ruNOlLHTLlRxB4VMiAfN/H ns1/abQ+60YTDCdRP1sTHygtLKRzrkyr9cp0nNcNDbUjXbVsz+OAuf/1wzw6wvqvdV85VTmk91DRh r+MA/pgaax0pSizLtNvw==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hBcW9-0006wY-8w; Wed, 03 Apr 2019 09:49:13 +0000 Received: from pandora.armlinux.org.uk ([2001:4d48:ad52:3201:214:fdff:fe10:1be6]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hBcW4-0006w4-W6 for linux-arm-kernel@lists.infradead.org; Wed, 03 Apr 2019 09:49:11 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=armlinux.org.uk; s=pandora-2019; h=Sender:In-Reply-To:Content-Type: MIME-Version:References:Message-ID:Subject:Cc:To:From:Date:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=oeWiunlvePInCzSlDTB1KVHn5yUIG+oJc82h8aF2XQk=; b=JAzlNv/bYFWBLoY/JZb/lKxxB 8c6SSvP4lSmHaIX2g4lHBeDe/rGrgfBByyVZ8hP+Bx9C2Wx+K70Vp1woKwkkYRdXrl6tocrtfl2fj FhY3jgsQ2g2cPB5/B4LWltCoLH0N0ZDA8z4HSEslRj1r/igGP93yUqJ2NfZ23f1JM0zRxiWQRsJwA R4eaLQDOiS4h4pcr79on4bRCCkvmpE2bkGIn53ySCKMCcfzPc+HwDY1r122jdFjOi+/KTsngXmOlL VmVtMFwNB7mhc3xF6vJgg6IKCl1Bku2pJxiKcSaqHFaOYEPrktdCOO6+bLWcBLL548Gg2CoVF/PXO NyXxcCFfw==; Received: from shell.armlinux.org.uk ([2002:4e20:1eda:1:5054:ff:fe00:4ec]:37596) by pandora.armlinux.org.uk with esmtpsa (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1hBcVj-0002IE-DK; Wed, 03 Apr 2019 10:48:47 +0100 Received: from linux by shell.armlinux.org.uk with local (Exim 4.89) (envelope-from ) id 1hBcVg-0004lj-8E; Wed, 03 Apr 2019 10:48:44 +0100 Date: Wed, 3 Apr 2019 10:48:44 +0100 From: Russell King - ARM Linux admin To: Miquel Raynal Subject: Re: [PATCH 02/15] phy: mvebu-cp110-comphy: Add SMC call support Message-ID: <20190403094844.stcoqhh433fqkqa5@shell.armlinux.org.uk> References: <20190401165131.23370-1-miquel.raynal@bootlin.com> <20190401165131.23370-3-miquel.raynal@bootlin.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20190401165131.23370-3-miquel.raynal@bootlin.com> User-Agent: NeoMutt/20170113 (1.7.2) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190403_024909_406433_C225B12E X-CRM114-Status: GOOD ( 28.53 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Andrew Lunn , Jason Cooper , devicetree@vger.kernel.org, Antoine Tenart , Gregory Clement , Kishon Vijay Abraham I , Nadav Haklai , Rob Herring , Thomas Petazzoni , Maxime Chevallier , linux-arm-kernel@lists.infradead.org, Sebastian Hesselbarth Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+infradead-linux-arm-kernel=archiver.kernel.org@lists.infradead.org On Mon, Apr 01, 2019 at 06:51:18PM +0200, Miquel Raynal wrote: > Keep the exact same list of supported configurations but first try to > use the firmware's implementation. If it fails, try the legacy method: > Linux implementation. > > Signed-off-by: Miquel Raynal > --- > drivers/phy/marvell/phy-mvebu-cp110-comphy.c | 200 +++++++++++++++---- > 1 file changed, 164 insertions(+), 36 deletions(-) > > diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c > index 3f50a1521f01..4aaf161503d6 100644 > --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c > +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c > @@ -5,6 +5,7 @@ > * Antoine Tenart > */ > > +#include > #include > #include > #include > @@ -115,51 +116,88 @@ > #define MVEBU_COMPHY_LANES 6 > #define MVEBU_COMPHY_PORTS 3 > > +#define COMPHY_SIP_POWER_ON 0x82000001 > +#define COMPHY_SIP_POWER_OFF 0x82000002 > + > +/* > + * A lane is described by the following bitfields: > + * [ 1- 0]: COMPHY polarity invertion > + * [ 2- 7]: COMPHY speed > + * [ 5-11]: COMPHY port index > + * [12-16]: COMPHY mode > + * [17]: Clock source > + */ > +#define COMPHY_FW_POL_OFFSET 0 > +#define COMPHY_FW_POL_MASK GENMASK(1, 0) > +#define COMPHY_FW_SPEED_OFFSET 2 > +#define COMPHY_FW_SPEED_MASK GENMASK(7, 2) > +#define COMPHY_FW_SPEED_MAX COMPHY_FW_SPEED_MASK > +#define COMPHY_FW_PORT_OFFSET 8 > +#define COMPHY_FW_PORT_MASK GENMASK(11, 8) > +#define COMPHY_FW_MODE_OFFSET 12 > +#define COMPHY_FW_MODE_MASK GENMASK(16, 12) > + > +#define COMPHY_FW_PARAM_FULL(mode, port, speed, pol) \ > + ((((pol) << COMPHY_FW_POL_OFFSET) & COMPHY_FW_POL_MASK) | \ > + (((mode) << COMPHY_FW_MODE_OFFSET) & COMPHY_FW_MODE_MASK) | \ > + (((port) << COMPHY_FW_PORT_OFFSET) & COMPHY_FW_PORT_MASK) | \ > + (((speed) << COMPHY_FW_SPEED_OFFSET) & COMPHY_FW_SPEED_MASK)) > + > +#define COMPHY_FW_PARAM(mode, port) \ > + COMPHY_FW_PARAM_FULL(mode, port, COMPHY_FW_SPEED_MAX, 0) > + > +#define COMPHY_FW_MODE_SGMII 0x2 /* SGMII 1G */ > +#define COMPHY_FW_MODE_HS_SGMII 0x3 /* SGMII 2.5G */ > +#define COMPHY_FW_MODE_SFI 0x9 /* XFI: 0x8 (is treated like SFI) */ > + > struct mvebu_comphy_conf { > enum phy_mode mode; > int submode; > unsigned lane; > unsigned port; > u32 mux; > + u32 fw_mode; > }; > > -#define MVEBU_COMPHY_CONF(_lane, _port, _submode, _mux) \ > +#define MVEBU_COMPHY_CONF(_lane, _port, _submode, _mux, _fw) \ > { \ > .lane = _lane, \ > .port = _port, \ > .mode = PHY_MODE_ETHERNET, \ > .submode = _submode, \ > .mux = _mux, \ > + .fw_mode = _fw, \ > } > > static const struct mvebu_comphy_conf mvebu_comphy_cp110_modes[] = { > /* lane 0 */ > - MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1), > - MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1), > + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(0, 1, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_HS_SGMII), > /* lane 1 */ > - MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1), > - MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), > + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(1, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_HS_SGMII), > /* lane 2 */ > - MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1), > - MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1), > - MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1), > + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_HS_SGMII), > + MVEBU_COMPHY_CONF(2, 0, PHY_INTERFACE_MODE_10GKR, 0x1, COMPHY_FW_MODE_SFI), > /* lane 3 */ > - MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2), > - MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2), > + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_SGMII, 0x2, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(3, 1, PHY_INTERFACE_MODE_2500BASEX, 0x2, COMPHY_FW_MODE_HS_SGMII), > /* lane 4 */ > - MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2), > - MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2), > - MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2), > - MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1), > + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_SGMII, 0x2, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_2500BASEX, 0x2, COMPHY_FW_MODE_HS_SGMII), > + MVEBU_COMPHY_CONF(4, 0, PHY_INTERFACE_MODE_10GKR, 0x2, COMPHY_FW_MODE_SFI), > + MVEBU_COMPHY_CONF(4, 1, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), > /* lane 5 */ > - MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1), > - MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1), > + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_SGMII, 0x1, COMPHY_FW_MODE_SGMII), > + MVEBU_COMPHY_CONF(5, 2, PHY_INTERFACE_MODE_2500BASEX, 0x1, COMPHY_FW_MODE_HS_SGMII), > }; > > struct mvebu_comphy_priv { > void __iomem *base; > struct regmap *regmap; > struct device *dev; > + unsigned long cp_phys; > }; > > struct mvebu_comphy_lane { > @@ -170,8 +208,18 @@ struct mvebu_comphy_lane { > int port; > }; > > -static int mvebu_comphy_get_mux(int lane, int port, > - enum phy_mode mode, int submode) > +static int mvebu_comphy_smc(unsigned long function, unsigned long phys, > + unsigned long lane, unsigned long mode) > +{ > + struct arm_smccc_res res; > + > + arm_smccc_smc(function, phys, lane, mode, 0, 0, 0, 0, &res); Before we switch to using the ATF implementation, I have serious concerns about the API here. The physical address is passed from the kernel to ATF for the hardware, and ATF does very little validation of that address. This means that it's trivially possible to overrun arrays in ATF, and even get ATF to read/write other areas of memory. I would rather this issue was resolved before the kernel starts to use what is a badly defined interface. > + > + return res.a0; > +} > + > +static int mvebu_comphy_get_mode(bool fw_mode, int lane, int port, > + enum phy_mode mode, int submode) > { > int i, n = ARRAY_SIZE(mvebu_comphy_cp110_modes); > > @@ -190,7 +238,22 @@ static int mvebu_comphy_get_mux(int lane, int port, > if (i == n) > return -EINVAL; > > - return mvebu_comphy_cp110_modes[i].mux; > + if (fw_mode) > + return mvebu_comphy_cp110_modes[i].fw_mode; > + else > + return mvebu_comphy_cp110_modes[i].mux; > +} > + > +static inline int mvebu_comphy_get_mux(int lane, int port, > + enum phy_mode mode, int submode) > +{ > + return mvebu_comphy_get_mode(false, lane, port, mode, submode); > +} > + > +static inline int mvebu_comphy_get_fw_mode(int lane, int port, > + enum phy_mode mode, int submode) > +{ > + return mvebu_comphy_get_mode(true, lane, port, mode, submode); > } > > static void mvebu_comphy_ethernet_init_reset(struct mvebu_comphy_lane *lane) > @@ -476,7 +539,7 @@ static int mvebu_comphy_set_mode_10gkr(struct phy *phy) > return mvebu_comphy_init_plls(lane); > } > > -static int mvebu_comphy_power_on(struct phy *phy) > +static int mvebu_comphy_power_on_legacy(struct phy *phy) > { > struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); > struct mvebu_comphy_priv *priv = lane->priv; > @@ -517,6 +580,50 @@ static int mvebu_comphy_power_on(struct phy *phy) > return ret; > } > > +static int mvebu_comphy_power_on(struct phy *phy) > +{ > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); > + struct mvebu_comphy_priv *priv = lane->priv; > + u32 fw_param = 0; > + int fw_mode; > + int ret; > + > + fw_mode = mvebu_comphy_get_fw_mode(lane->id, lane->port, > + lane->mode, lane->submode); > + if (fw_mode < 0) > + goto try_legacy; > + > + /* Try SMC flow first */ > + switch (lane->mode) { > + case PHY_MODE_ETHERNET: > + dev_dbg(priv->dev, "set lane %d to Ethernet mode\n", lane->id); > + switch (lane->submode) { > + case PHY_INTERFACE_MODE_SGMII: > + case PHY_INTERFACE_MODE_2500BASEX: > + case PHY_INTERFACE_MODE_10GKR: > + fw_param = COMPHY_FW_PARAM(fw_mode, lane->port); > + break; > + default: > + dev_err(priv->dev, "unsupported Ethernet mode (%d)\n", > + lane->submode); > + return -ENOTSUPP; > + } > + break; > + default: > + dev_err(priv->dev, "unsupported PHY mode (%d)\n", lane->mode); > + return -ENOTSUPP; > + } > + > + ret = mvebu_comphy_smc(COMPHY_SIP_POWER_ON, priv->cp_phys, lane->id, > + fw_param); > + if (!ret) > + return ret; > + > +try_legacy: > + /* Fallback to Linux's implementation */ > + return mvebu_comphy_power_on_legacy(phy); > +} > + > static int mvebu_comphy_set_mode(struct phy *phy, > enum phy_mode mode, int submode) > { > @@ -528,7 +635,7 @@ static int mvebu_comphy_set_mode(struct phy *phy, > if (submode == PHY_INTERFACE_MODE_1000BASEX) > submode = PHY_INTERFACE_MODE_SGMII; > > - if (mvebu_comphy_get_mux(lane->id, lane->port, mode, submode) < 0) > + if (mvebu_comphy_get_fw_mode(lane->id, lane->port, mode, submode) < 0) > return -EINVAL; > > lane->mode = mode; > @@ -536,27 +643,42 @@ static int mvebu_comphy_set_mode(struct phy *phy, > return 0; > } > > +static int mvebu_comphy_power_off_legacy(struct phy *phy) > +{ > + struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); > + struct mvebu_comphy_priv *priv = lane->priv; > + u32 val; > + > + val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id)); > + val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET | > + MVEBU_COMPHY_SERDES_CFG1_CORE_RESET | > + MVEBU_COMPHY_SERDES_CFG1_RF_RESET); > + writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id)); > + > + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val); > + val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); > + regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); > + > + regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val); > + val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id)); > + regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val); > + > + return 0; > +} > + > static int mvebu_comphy_power_off(struct phy *phy) > { > struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); > struct mvebu_comphy_priv *priv = lane->priv; > - u32 val; > + int ret; > > - val = readl(priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id)); > - val &= ~(MVEBU_COMPHY_SERDES_CFG1_RESET | > - MVEBU_COMPHY_SERDES_CFG1_CORE_RESET | > - MVEBU_COMPHY_SERDES_CFG1_RF_RESET); > - writel(val, priv->base + MVEBU_COMPHY_SERDES_CFG1(lane->id)); > + ret = mvebu_comphy_smc(COMPHY_SIP_POWER_OFF, priv->cp_phys, > + lane->id, 0); > + if (!ret) > + return ret; > > - regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val); > - val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); > - regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); > - > - regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val); > - val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id)); > - regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val); > - > - return 0; > + /* Fallback to Linux's implementation */ > + return mvebu_comphy_power_off_legacy(phy); > } > > static const struct phy_ops mvebu_comphy_ops = { > @@ -607,6 +729,12 @@ static int mvebu_comphy_probe(struct platform_device *pdev) > if (IS_ERR(priv->base)) > return PTR_ERR(priv->base); > > + /* > + * Hack to retrieve a physical offset relative to this CP that will be > + * given to the firmware > + */ > + priv->cp_phys = res->start; > + > for_each_available_child_of_node(pdev->dev.of_node, child) { > struct mvebu_comphy_lane *lane; > struct phy *phy; > -- > 2.19.1 > > -- RMK's Patch system: https://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line in suburbia: sync at 12.1Mbps down 622kbps up According to speedtest.net: 11.9Mbps down 500kbps up _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel