Received: by 2002:a05:6a10:6744:0:0:0:0 with SMTP id w4csp398337pxu; Fri, 23 Oct 2020 03:59:23 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxQ4J/5hXoegy5RNe6/5p9fupgxaley6TEiIbzkKxfegJqbuFnEBWKXvAUp5lpIYevgEm3G X-Received: by 2002:a05:6402:602:: with SMTP id n2mr1557332edv.327.1603450763387; Fri, 23 Oct 2020 03:59:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1603450763; cv=none; d=google.com; s=arc-20160816; b=rLcc8xzL+Kysk+7ZSH0v5bCV0i/1oO5XtlrLWfeCenIr9G6j7uGi1GM1b1IAGL6til h19rq/QF3J6GmXnA37IZUFTBJuipU9JevMHMZ1wXpJQdP7/6wxhCMIC3vyW8iPIP0mWr +RvV66ChGigdSud1LeYvuvytzESROeam9bo3JRoDwfawgiMUm4O87gymmsbPowgO1qO1 4BkNnIykwWFvotHC/wVv17A7aZNJkQRrqpm91USrA8r0u9VPxaT3M/WVYIhOE6iR/pPN M1HJsRIGGgB/7V0zzlPxLjji3q2RG3x8FKJfW7uWCIhiSgEG6Kj8Q5BT92o1GpfrA4yJ HqzQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=Kf70dBO+2v/dlJGUjXcL5PqvCQ7YizgpbAKROHcW/R8=; b=vxKsbpw8/wIVl5kSvkiIKcdi07Cy5MmeEA16QltHYis9SkJM8WU91tOndJDPVO6JQR YBEbDBo7eXbwhkhS2y1/M9xHNz5bfeyjFGVil2i0nfdBpMuih5oCJqL4mrAptAgEjiJT xXCcHZgO5VIlmMJp14re6qxr5jPsDSJ0u8vUMEGdYm/+f0ViFIUQLnGtQ4ai+FNpS4x5 S2kfPxqzRin944uJH49fMUhXbmhcFVVXmDDzeB9Rla83pmfChmnqc3ow1H2qDMX111Qs CEAlH3F8VE2ckQKjNr2gx+tyVeaw8x6rM1GRMwVaTOw5bA5dDeG2Tii0mxp86fpO6VMk pMiQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id p5si623713ejb.630.2020.10.23.03.59.01; Fri, 23 Oct 2020 03:59:23 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S462566AbgJWK4j (ORCPT + 99 others); Fri, 23 Oct 2020 06:56:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:52832 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S462548AbgJWK4g (ORCPT ); Fri, 23 Oct 2020 06:56:36 -0400 Received: from metis.ext.pengutronix.de (metis.ext.pengutronix.de [IPv6:2001:67c:670:201:290:27ff:fe1d:cc33]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 746FEC0613CE for ; Fri, 23 Oct 2020 03:56:36 -0700 (PDT) Received: from dude.hi.pengutronix.de ([2001:67c:670:100:1d::7]) by metis.ext.pengutronix.de with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kVukG-00087r-Kr; Fri, 23 Oct 2020 12:56:28 +0200 Received: from ore by dude.hi.pengutronix.de with local (Exim 4.92) (envelope-from ) id 1kVukF-0001km-H8; Fri, 23 Oct 2020 12:56:27 +0200 From: Oleksij Rempel To: Andrew Lunn , "David S. Miller" , Florian Fainelli , Heiner Kallweit , Jakub Kicinski , Oliver Hartkopp Cc: Oleksij Rempel , David Jander , kernel@pengutronix.de, linux-kernel@vger.kernel.org, netdev@vger.kernel.org, Russell King , mkl@pengutronix.de, Marek Vasut , linux-can@vger.kernel.org Subject: [RFC PATCH v1 5/6] can: flexcan: add phylink support Date: Fri, 23 Oct 2020 12:56:25 +0200 Message-Id: <20201023105626.6534-6-o.rempel@pengutronix.de> X-Mailer: git-send-email 2.28.0 In-Reply-To: <20201023105626.6534-1-o.rempel@pengutronix.de> References: <20201023105626.6534-1-o.rempel@pengutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SA-Exim-Connect-IP: 2001:67c:670:100:1d::7 X-SA-Exim-Mail-From: ore@pengutronix.de X-SA-Exim-Scanned: No (on metis.ext.pengutronix.de); SAEximRunCond expanded to false X-PTX-Original-Recipient: linux-kernel@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Signed-off-by: Oleksij Rempel --- drivers/net/can/Kconfig | 2 + drivers/net/can/flexcan.c | 133 +++++++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index 424970939fd4..fc5db96a34be 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -98,6 +98,8 @@ config CAN_AT91 config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" depends on OF && HAS_IOMEM + select PHYLINK + select CAN_PHY help Say Y here if you want to support for Freescale FlexCAN. diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 881799bd9c5e..c320eed31322 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -361,6 +365,10 @@ struct flexcan_priv { /* Read and Write APIs */ u32 (*read)(void __iomem *addr); void (*write)(u32 val, void __iomem *addr); + + phy_interface_t phy_if_mode; + struct phylink *phylink; + struct phylink_config phylink_config; }; static const struct flexcan_devtype_data fsl_p1010_devtype_data = { @@ -1653,9 +1661,16 @@ static int flexcan_open(struct net_device *dev) return -EINVAL; } + err = phylink_of_phy_connect(priv->phylink, priv->dev->of_node, 0); + if (err) { + netdev_err(dev, "phylink_of_phy_connect filed with err: %i\n", + err); + return err; + } + err = pm_runtime_get_sync(priv->dev); if (err < 0) - return err; + goto out_phy_put; err = open_candev(dev); if (err) @@ -1710,6 +1725,8 @@ static int flexcan_open(struct net_device *dev) can_rx_offload_enable(&priv->offload); netif_start_queue(dev); + phylink_start(priv->phylink); + return 0; out_offload_del: @@ -1720,6 +1737,8 @@ static int flexcan_open(struct net_device *dev) close_candev(dev); out_runtime_put: pm_runtime_put(priv->dev); + out_phy_put: + phylink_disconnect_phy(priv->phylink); return err; } @@ -1740,6 +1759,104 @@ static int flexcan_close(struct net_device *dev) can_led_event(dev, CAN_LED_EVENT_STOP); + phylink_stop(priv->phylink); + phylink_disconnect_phy(priv->phylink); + + return 0; +} + +static void flexcan_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ + /* Not Supported */ +} + +static void flexcan_mac_validate(struct phylink_config *config, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct flexcan_priv *priv = netdev_priv(to_net_dev(config->dev)); + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + + switch (state->interface) { + case PHY_INTERFACE_MODE_NA: + case PHY_INTERFACE_MODE_CAN: + break; + default: + goto unsupported; + } + + phylink_set(mask, CAN_HS); + phylink_set(mask, CAN_LS); + phylink_set(mask, CAN_SW); + + /* max bitrate supported by the controller */ + if (!state->max_bitrate || state->max_bitrate > 1000000) + state->max_bitrate = 1000000; + + priv->can.bitrate_max = state->max_bitrate; + + bitmap_and(supported, supported, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + bitmap_and(state->advertising, state->advertising, mask, + __ETHTOOL_LINK_MODE_MASK_NBITS); + + return; +unsupported: + bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); +} + +static void flexcan_mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state) +{ + state->link = 0; +} + +static void flexcan_mac_an_restart(struct phylink_config *config) +{ + /* Not Supported */ +} + +static void flexcan_mac_link_down(struct phylink_config *config, + unsigned int mode, phy_interface_t interface) +{ + /* Not Supported */ +} + +static void flexcan_mac_link_up(struct phylink_config *config, + struct phy_device *phy, + unsigned int mode, phy_interface_t interface, + int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + /* Not Supported */ +} + + + +static const struct phylink_mac_ops flexcan_phylink_mac_ops = { + .validate = flexcan_mac_validate, + .mac_pcs_get_state = flexcan_mac_pcs_get_state, + .mac_an_restart = flexcan_mac_an_restart, + .mac_config = flexcan_mac_config, + .mac_link_down = flexcan_mac_link_down, + .mac_link_up = flexcan_mac_link_up, +}; + +static int flexcan_phylink_setup(struct flexcan_priv *priv, + struct net_device *dev) +{ + struct phylink *phylink; + + priv->phylink_config.dev = &dev->dev; + priv->phylink_config.type = PHYLINK_NETDEV; + + phylink = phylink_create(&priv->phylink_config, priv->dev->fwnode, + priv->phy_if_mode, &flexcan_phylink_mac_ops); + if (IS_ERR(phylink)) + return PTR_ERR(phylink); + + priv->phylink = phylink; return 0; } @@ -1818,6 +1935,12 @@ static int register_flexcandev(struct net_device *dev) if (err) goto out_chip_disable; + err = flexcan_phylink_setup(priv, dev); + if (err) { + netdev_err(dev, "failed to setup phylink (%d)\n", err); + goto out_chip_disable; + } + /* Disable core and let pm_runtime_put() disable the clocks. * If CONFIG_PM is not enabled, the clocks will stay powered. */ @@ -1921,6 +2044,7 @@ static int flexcan_probe(struct platform_device *pdev) { const struct of_device_id *of_id; const struct flexcan_devtype_data *devtype_data; + phy_interface_t phy_if_mode; struct net_device *dev; struct flexcan_priv *priv; struct regulator *reg_xceiver; @@ -1943,6 +2067,12 @@ static int flexcan_probe(struct platform_device *pdev) "clock-frequency", &clock_freq); of_property_read_u8(pdev->dev.of_node, "fsl,clk-source", &clk_src); + can_phy_register(pdev->dev.of_node); + err = of_get_phy_mode(pdev->dev.of_node, &phy_if_mode); + if (err) { + dev_err(&pdev->dev, "missing phy-mode property in DT\n"); + return err; + } } if (!clock_freq) { @@ -2019,6 +2149,7 @@ static int flexcan_probe(struct platform_device *pdev) priv->clk_src = clk_src; priv->devtype_data = devtype_data; priv->reg_xceiver = reg_xceiver; + priv->phy_if_mode = phy_if_mode; if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) { priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | -- 2.28.0