From patchwork Tue Jun 8 09:25:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 456429 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=-15.8 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT 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 76B95C4743E for ; Tue, 8 Jun 2021 09:27:01 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 560ED60241 for ; Tue, 8 Jun 2021 09:27:01 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230519AbhFHJ2u (ORCPT ); Tue, 8 Jun 2021 05:28:50 -0400 Received: from mail-ej1-f47.google.com ([209.85.218.47]:37600 "EHLO mail-ej1-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229536AbhFHJ2o (ORCPT ); Tue, 8 Jun 2021 05:28:44 -0400 Received: by mail-ej1-f47.google.com with SMTP id ce15so31493029ejb.4 for ; Tue, 08 Jun 2021 02:26:51 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ToKAeI2JQi7vdsmaDuy6bvnKQhNqELD4Tw6sXjBW/8M=; b=XbJ7L3sL6QVtE4Ycqu5gAR+Li1zJ5t18af7oADsIB9QA+XXfL2SGLygi/fJEzyYt5h YuxlEu+EKOyB01N+yRKbZxxPVH3aBaSgCIBMjgvGIJBsBQ6uACo03XW4l+8Tyeau62be VgE8GidlOO5JXJvpjEYETI6eH1sMF1K02H/ujS2Ee58WvIKuK53QpXwiXJOElDwp5EbO 7dHT1uJl6cF3O8vDJTB7Kt8RI0ONy1bAbM6lYk1ucBeIc7pclSDYpeP4/ORVm6xueXLY QZI3NBo2HE23fwFVvHhtpeeZiXXT/Ug31kqNqEcQbhtDCelwITHC8603+afL/HEYOQfT zrQQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ToKAeI2JQi7vdsmaDuy6bvnKQhNqELD4Tw6sXjBW/8M=; b=smum43GfUPNKhZzIaezDZlak39232fbvvfyzmEYjJfIiPGGXsrr2eT439aG3kVcoNA SFlAlwrRfXbX7kBs7N7hP1gwbSCumVeNvEWLdFgMnO/KRq6MebD2rTZCkFT0RsgQx78Q +o3OSuqKqajNPR6kD9PtdZ8nd/yjt9aA1MYuMko2XeID+OkUcp+aDmKPKQ41XdO44N00 0CVeAgisza99dFmzLmMiPnEoG8suLF7maXJPjf10VBP6bKCyjOXk7QWZLrE5HmXqXooB nSs6VlZDmfWUWDi5kpCtFPAW7m0bN6Gz1gxQJitYh/4ZqHl0qGfUnBxbtZlOFeFpR+ML aImA== X-Gm-Message-State: AOAM533g/rFY5kbpF5THMcLNK9aoIQeuCgTe0R9a2ZG+R/R8mRcoS1nO PconT07deF0Kp1QYMPvWaFk= X-Google-Smtp-Source: ABdhPJzfXysua39Ex9LTKEfJjtCzJ0l7qkpof+7Xt5+/7VlxH1dBVOhWK2uAOAbyMrpuaUak2sSiDA== X-Received: by 2002:a17:906:848:: with SMTP id f8mr21893912ejd.198.1623144351279; Tue, 08 Jun 2021 02:25:51 -0700 (PDT) Received: from localhost.localdomain ([188.26.52.84]) by smtp.gmail.com with ESMTPSA id x9sm639783ejc.37.2021.06.08.02.25.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Jun 2021 02:25:51 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Vladimir Oltean Subject: [PATCH v3 net-next 3/4] net: dsa: sja1105: make sure the retagging port is enabled for SJA1110 Date: Tue, 8 Jun 2021 12:25:37 +0300 Message-Id: <20210608092538.3920217-4-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210608092538.3920217-1-olteanv@gmail.com> References: <20210608092538.3920217-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean The SJA1110 has an extra configuration in the General Parameters Table through which the user can select the buffer reservation config. Signed-off-by: Vladimir Oltean --- v2->v3: Patch is new. drivers/net/dsa/sja1105/sja1105_main.c | 56 +++++++++++++++++++ .../net/dsa/sja1105/sja1105_static_config.c | 1 + .../net/dsa/sja1105/sja1105_static_config.h | 1 + 3 files changed, 58 insertions(+) diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 2b3b6c402b34..801cf47d9572 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -565,6 +565,60 @@ void sja1105_frame_memory_partitioning(struct sja1105_private *priv) vl_fwd_params->partspc[0] = SJA1105_VL_FRAME_MEMORY; } +/* SJA1110 TDMACONFIGIDX values: + * + * | 100 Mbps ports | 1Gbps ports | 2.5Gbps ports | Disabled ports + * -----+----------------+---------------+---------------+--------------- + * 0 | 0, [5:10] | [1:2] | [3:4] | retag + * 1 |0, [5:10], retag| [1:2] | [3:4] | - + * 2 | 0, [5:10] | [1:3], retag | 4 | - + * 3 | 0, [5:10] |[1:2], 4, retag| 3 | - + * 4 | 0, 2, [5:10] | 1, retag | [3:4] | - + * 5 | 0, 1, [5:10] | 2, retag | [3:4] | - + * 14 | 0, [5:10] | [1:4], retag | - | - + * 15 | [5:10] | [0:4], retag | - | - + */ +static void sja1110_select_tdmaconfigidx(struct sja1105_private *priv) +{ + struct sja1105_general_params_entry *general_params; + struct sja1105_table *table; + bool port_1_is_base_tx; + bool port_3_is_2500; + bool port_4_is_2500; + u64 tdmaconfigidx; + + if (priv->info->device_id != SJA1110_DEVICE_ID) + return; + + table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS]; + general_params = table->entries; + + /* All the settings below are "as opposed to SGMII", which is the + * other pinmuxing option. + */ + port_1_is_base_tx = priv->phy_mode[1] == PHY_INTERFACE_MODE_INTERNAL; + port_3_is_2500 = priv->phy_mode[3] == PHY_INTERFACE_MODE_2500BASEX; + port_4_is_2500 = priv->phy_mode[4] == PHY_INTERFACE_MODE_2500BASEX; + + if (port_1_is_base_tx) + /* Retagging port will operate at 1 Gbps */ + tdmaconfigidx = 5; + else if (port_3_is_2500 && port_4_is_2500) + /* Retagging port will operate at 100 Mbps */ + tdmaconfigidx = 1; + else if (port_3_is_2500) + /* Retagging port will operate at 1 Gbps */ + tdmaconfigidx = 3; + else if (port_4_is_2500) + /* Retagging port will operate at 1 Gbps */ + tdmaconfigidx = 2; + else + /* Retagging port will operate at 1 Gbps */ + tdmaconfigidx = 14; + + general_params->tdmaconfigidx = tdmaconfigidx; +} + static int sja1105_init_general_params(struct sja1105_private *priv) { struct sja1105_general_params_entry default_general_params = { @@ -640,6 +694,8 @@ static int sja1105_init_general_params(struct sja1105_private *priv) ((struct sja1105_general_params_entry *)table->entries)[0] = default_general_params; + sja1110_select_tdmaconfigidx(priv); + return 0; } diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c index 4eba79bdedbf..eda571819d45 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.c +++ b/drivers/net/dsa/sja1105/sja1105_static_config.c @@ -211,6 +211,7 @@ size_t sja1110_general_params_entry_packing(void *buf, void *entry_ptr, sja1105_packing(buf, &entry->egrmirrpcp, 113, 111, size, op); sja1105_packing(buf, &entry->egrmirrdei, 110, 110, size, op); sja1105_packing(buf, &entry->replay_port, 109, 106, size, op); + sja1105_packing(buf, &entry->tdmaconfigidx, 70, 67, size, op); sja1105_packing(buf, &entry->tte_en, 16, 16, size, op); return size; } diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.h b/drivers/net/dsa/sja1105/sja1105_static_config.h index d24227f78a72..9bef51791bff 100644 --- a/drivers/net/dsa/sja1105/sja1105_static_config.h +++ b/drivers/net/dsa/sja1105/sja1105_static_config.h @@ -216,6 +216,7 @@ struct sja1105_general_params_entry { u64 replay_port; /* SJA1110 only */ u64 tte_en; + u64 tdmaconfigidx; }; struct sja1105_schedule_entry_points_entry { From patchwork Tue Jun 8 09:25:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Oltean X-Patchwork-Id: 456428 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=-12.9 required=3.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FORGED_FROMDOMAIN,FREEMAIL_FROM, HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,UNWANTED_LANGUAGE_BODY, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable 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 3CC2AC4743D for ; Tue, 8 Jun 2021 09:27:10 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 21EAC6124C for ; Tue, 8 Jun 2021 09:27:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231157AbhFHJ3C (ORCPT ); Tue, 8 Jun 2021 05:29:02 -0400 Received: from mail-ej1-f47.google.com ([209.85.218.47]:41726 "EHLO mail-ej1-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229507AbhFHJ3A (ORCPT ); Tue, 8 Jun 2021 05:29:00 -0400 Received: by mail-ej1-f47.google.com with SMTP id ho18so20516575ejc.8; Tue, 08 Jun 2021 02:26:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=hO+43ZlBya5VwFbDK66fIGeDDhZ0ig2Bu501KkTdwa0=; b=r/EHsk9uv/R5SQIwCVy2ZjhSjEfXIEiShJqhqBhHPYWaNlgPAGI1X5F63frN8soQBe rH+rA+3hDg3CJIloImkhCIb4XsV6cctFNpkPCflMf1aSCJOmu18bstzPMT0w65RASxdW tHeUTgml2p08orkOvGCwTC/ShyN6/ULsYAc+xLmBMh/9zGHY5wZLJobsJMD4Bc2m/DvQ Td2mlSSsMABRtAlN80mSLsXrMf7748SGy4414MxVcCyGWbWVv+nR2sLQ66p7bVqSTekV GcuKa/Dm3Ds6DETi1zFd6Nk57h+Gp6K2S43Gnmt4sf6GLv6CimX71/CPROWUI3Ds4cV5 hdxw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=hO+43ZlBya5VwFbDK66fIGeDDhZ0ig2Bu501KkTdwa0=; b=HYtQ9m3AxSf4AssZk1vn6J48m5Iy4H9Lw8B9y9UTfkInr0RQPw0yYmQBiQahazsK3L mTQfLNiWI+jA0uXsG6AcSvNHzoclWIwKW4qKqf1OwHxG2HVwb2T2LP0epplVNZDxBOsq 3Iks+fHalKtdjtvAFFwVxVtxLNKN4Hr6402A4RREEKHfMDOEnqRaY0t1yb9bcwarL7Qm 0cXK8Te700tL/otomS3rZw+r26fsn3wcpqtxqdlBJHdhbhoaCSwKzF+8WaO6Ioj1fed3 JK4E30szealXG1ataIh7u+LQo6CN4JOK3vdasRMj2eHhztCwg9kk97ZnCwJpxz9sZ0/A xyPg== X-Gm-Message-State: AOAM533yt5Zu9xqqUdpJHIEJLJX/RFFw0pl3sRD/B97V0ZZDxzB8r3pd S/2HroKYApfX/x2GFF9wz6kqzpIsGj4= X-Google-Smtp-Source: ABdhPJxEHH6IzfEOhLJHe5a57moajFcioxgTY5tbiejU8vqeikz56e9Y0Di198RGS5F0S+9Vp+QllQ== X-Received: by 2002:a17:906:17c4:: with SMTP id u4mr22688725eje.481.1623144352248; Tue, 08 Jun 2021 02:25:52 -0700 (PDT) Received: from localhost.localdomain ([188.26.52.84]) by smtp.gmail.com with ESMTPSA id x9sm639783ejc.37.2021.06.08.02.25.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Jun 2021 02:25:52 -0700 (PDT) From: Vladimir Oltean To: Jakub Kicinski , "David S. Miller" , netdev@vger.kernel.org Cc: Florian Fainelli , Andrew Lunn , Vivien Didelot , Vladimir Oltean , Russell King , Heiner Kallweit , Rob Herring , devicetree@vger.kernel.org Subject: [PATCH v3 net-next 4/4] net: dsa: sja1105: register the MDIO buses for 100base-T1 and 100base-TX Date: Tue, 8 Jun 2021 12:25:38 +0300 Message-Id: <20210608092538.3920217-5-olteanv@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210608092538.3920217-1-olteanv@gmail.com> References: <20210608092538.3920217-1-olteanv@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Vladimir Oltean The SJA1110 contains two types of integrated PHYs: one 100base-TX PHY and multiple 100base-T1 PHYs. The access procedure for the 100base-T1 PHYs is also different than it is for the 100base-TX one. So we register 2 MDIO buses, one for the base-TX and the other for the base-T1. Each bus has an OF node which is a child of the "mdio" subnode of the switch, and they are recognized by compatible string. Cc: Russell King Cc: Heiner Kallweit Cc: Rob Herring Cc: devicetree@vger.kernel.org Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli --- v1->v2: s/"mdio"/"mdios"/ for the name of the container OF node. v2->v3: none drivers/net/dsa/sja1105/Makefile | 1 + drivers/net/dsa/sja1105/sja1105.h | 19 ++ drivers/net/dsa/sja1105/sja1105_main.c | 21 +- drivers/net/dsa/sja1105/sja1105_mdio.c | 288 +++++++++++++++++++++++++ drivers/net/dsa/sja1105/sja1105_spi.c | 30 +++ 5 files changed, 358 insertions(+), 1 deletion(-) create mode 100644 drivers/net/dsa/sja1105/sja1105_mdio.c diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile index a860e3a910be..40d69e6c0bae 100644 --- a/drivers/net/dsa/sja1105/Makefile +++ b/drivers/net/dsa/sja1105/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_NET_DSA_SJA1105) += sja1105.o sja1105-objs := \ sja1105_spi.o \ sja1105_main.o \ + sja1105_mdio.o \ sja1105_flower.o \ sja1105_ethtool.o \ sja1105_devlink.o \ diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h index ef6e22c78373..f762f5488a76 100644 --- a/drivers/net/dsa/sja1105/sja1105.h +++ b/drivers/net/dsa/sja1105/sja1105.h @@ -67,6 +67,12 @@ struct sja1105_regs { u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS]; u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS]; u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS]; + u64 mdio_100base_tx; + u64 mdio_100base_t1; +}; + +struct sja1105_mdio_private { + struct sja1105_private *priv; }; enum { @@ -78,6 +84,12 @@ enum { SJA1105_SPEED_MAX, }; +enum sja1105_internal_phy_t { + SJA1105_NO_PHY = 0, + SJA1105_PHY_BASE_TX, + SJA1105_PHY_BASE_T1, +}; + struct sja1105_info { u64 device_id; /* Needed for distinction between P and R, and between Q and S @@ -123,6 +135,7 @@ struct sja1105_info { bool supports_rgmii[SJA1105_MAX_NUM_PORTS]; bool supports_sgmii[SJA1105_MAX_NUM_PORTS]; bool supports_2500basex[SJA1105_MAX_NUM_PORTS]; + enum sja1105_internal_phy_t internal_phy[SJA1105_MAX_NUM_PORTS]; const u64 port_speed[SJA1105_SPEED_MAX]; }; @@ -246,6 +259,8 @@ struct sja1105_private { enum sja1105_vlan_state vlan_state; struct devlink_region **regions; struct sja1105_cbs_entry *cbs; + struct mii_bus *mdio_base_t1; + struct mii_bus *mdio_base_tx; struct sja1105_tagger_data tagger_data; struct sja1105_ptp_data ptp_data; struct sja1105_tas_data tas_data; @@ -275,6 +290,10 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled, struct netlink_ext_ack *extack); void sja1105_frame_memory_partitioning(struct sja1105_private *priv); +/* From sja1105_mdio.c */ +int sja1105_mdiobus_register(struct dsa_switch *ds); +void sja1105_mdiobus_unregister(struct dsa_switch *ds); + /* From sja1105_devlink.c */ int sja1105_devlink_setup(struct dsa_switch *ds); void sja1105_devlink_teardown(struct dsa_switch *ds); diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 801cf47d9572..3b031864ad74 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -168,6 +168,15 @@ static int sja1105_init_mii_settings(struct sja1105_private *priv) continue; switch (priv->phy_mode[i]) { + case PHY_INTERFACE_MODE_INTERNAL: + if (priv->info->internal_phy[i] == SJA1105_NO_PHY) + goto unsupported; + + mii->xmii_mode[i] = XMII_MODE_MII; + if (priv->info->internal_phy[i] == SJA1105_PHY_BASE_TX) + mii->special[i] = true; + + break; case PHY_INTERFACE_MODE_REVMII: role = XMII_PHY; fallthrough; @@ -3109,11 +3118,19 @@ static int sja1105_setup(struct dsa_switch *ds) dev_err(ds->dev, "Failed to register PTP clock: %d\n", rc); return rc; } + + rc = sja1105_mdiobus_register(ds); + if (rc < 0) { + dev_err(ds->dev, "Failed to register MDIO bus: %pe\n", + ERR_PTR(rc)); + goto out_ptp_clock_unregister; + } + /* Create and send configuration down to device */ rc = sja1105_static_config_load(priv); if (rc < 0) { dev_err(ds->dev, "Failed to load static config: %d\n", rc); - goto out_ptp_clock_unregister; + goto out_mdiobus_unregister; } /* Configure the CGU (PHY link modes and speeds) */ rc = priv->info->clocking_setup(priv); @@ -3156,6 +3173,8 @@ static int sja1105_setup(struct dsa_switch *ds) out_devlink_teardown: sja1105_devlink_teardown(ds); +out_mdiobus_unregister: + sja1105_mdiobus_unregister(ds); out_ptp_clock_unregister: sja1105_ptp_clock_unregister(ds); out_static_config_free: diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c new file mode 100644 index 000000000000..8dfd06318b23 --- /dev/null +++ b/drivers/net/dsa/sja1105/sja1105_mdio.c @@ -0,0 +1,288 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright 2021, NXP Semiconductors + */ +#include +#include "sja1105.h" + +enum sja1105_mdio_opcode { + SJA1105_C45_ADDR = 0, + SJA1105_C22 = 1, + SJA1105_C45_DATA = 2, + SJA1105_C45_DATA_AUTOINC = 3, +}; + +static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv, + int phy, enum sja1105_mdio_opcode op, + int xad) +{ + const struct sja1105_regs *regs = priv->info->regs; + + return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0); +} + +static int sja1105_base_t1_mdio_read(struct mii_bus *bus, int phy, int reg) +{ + struct sja1105_mdio_private *mdio_priv = bus->priv; + struct sja1105_private *priv = mdio_priv->priv; + u64 addr; + u32 tmp; + int rc; + + if (reg & MII_ADDR_C45) { + u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f; + + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, + mmd); + + tmp = reg & MII_REGADDR_C45_MASK; + + rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); + if (rc < 0) + return rc; + + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, + mmd); + + rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL); + if (rc < 0) + return rc; + + return tmp & 0xffff; + } + + /* Clause 22 read */ + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f); + + rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL); + if (rc < 0) + return rc; + + return tmp & 0xffff; +} + +static int sja1105_base_t1_mdio_write(struct mii_bus *bus, int phy, int reg, + u16 val) +{ + struct sja1105_mdio_private *mdio_priv = bus->priv; + struct sja1105_private *priv = mdio_priv->priv; + u64 addr; + u32 tmp; + int rc; + + if (reg & MII_ADDR_C45) { + u16 mmd = (reg >> MII_DEVADDR_C45_SHIFT) & 0x1f; + + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, + mmd); + + tmp = reg & MII_REGADDR_C45_MASK; + + rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); + if (rc < 0) + return rc; + + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, + mmd); + + tmp = val & 0xffff; + + rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); + if (rc < 0) + return rc; + + return 0; + } + + /* Clause 22 write */ + addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f); + + tmp = val & 0xffff; + + return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL); +} + +static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg) +{ + struct sja1105_mdio_private *mdio_priv = bus->priv; + struct sja1105_private *priv = mdio_priv->priv; + const struct sja1105_regs *regs = priv->info->regs; + u32 tmp; + int rc; + + rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg, + &tmp, NULL); + if (rc < 0) + return rc; + + return tmp & 0xffff; +} + +static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg, + u16 val) +{ + struct sja1105_mdio_private *mdio_priv = bus->priv; + struct sja1105_private *priv = mdio_priv->priv; + const struct sja1105_regs *regs = priv->info->regs; + u32 tmp = val; + + return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg, + &tmp, NULL); +} + +static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv, + struct device_node *mdio_node) +{ + struct sja1105_mdio_private *mdio_priv; + struct device_node *np; + struct mii_bus *bus; + int rc = 0; + + np = of_find_compatible_node(mdio_node, NULL, + "nxp,sja1110-base-tx-mdio"); + if (!np) + return 0; + + if (!of_device_is_available(np)) + goto out_put_np; + + bus = mdiobus_alloc_size(sizeof(*mdio_priv)); + if (!bus) { + rc = -ENOMEM; + goto out_put_np; + } + + bus->name = "SJA1110 100base-TX MDIO bus"; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx", + dev_name(priv->ds->dev)); + bus->read = sja1105_base_tx_mdio_read; + bus->write = sja1105_base_tx_mdio_write; + bus->parent = priv->ds->dev; + mdio_priv = bus->priv; + mdio_priv->priv = priv; + + rc = of_mdiobus_register(bus, np); + if (rc) { + mdiobus_free(bus); + goto out_put_np; + } + + priv->mdio_base_tx = bus; + +out_put_np: + of_node_put(np); + + return 0; +} + +static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv) +{ + if (!priv->mdio_base_tx) + return; + + mdiobus_unregister(priv->mdio_base_tx); + mdiobus_free(priv->mdio_base_tx); + priv->mdio_base_tx = NULL; +} + +static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv, + struct device_node *mdio_node) +{ + struct sja1105_mdio_private *mdio_priv; + struct device_node *np; + struct mii_bus *bus; + int rc = 0; + + np = of_find_compatible_node(mdio_node, NULL, + "nxp,sja1110-base-t1-mdio"); + if (!np) + return 0; + + if (!of_device_is_available(np)) + goto out_put_np; + + bus = mdiobus_alloc_size(sizeof(*mdio_priv)); + if (!bus) { + rc = -ENOMEM; + goto out_put_np; + } + + bus->name = "SJA1110 100base-T1 MDIO bus"; + snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1", + dev_name(priv->ds->dev)); + bus->read = sja1105_base_t1_mdio_read; + bus->write = sja1105_base_t1_mdio_write; + bus->parent = priv->ds->dev; + mdio_priv = bus->priv; + mdio_priv->priv = priv; + + rc = of_mdiobus_register(bus, np); + if (rc) { + mdiobus_free(bus); + goto out_put_np; + } + + priv->mdio_base_t1 = bus; + +out_put_np: + of_node_put(np); + + return rc; +} + +static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv) +{ + if (!priv->mdio_base_t1) + return; + + mdiobus_unregister(priv->mdio_base_t1); + mdiobus_free(priv->mdio_base_t1); + priv->mdio_base_t1 = NULL; +} + +int sja1105_mdiobus_register(struct dsa_switch *ds) +{ + struct sja1105_private *priv = ds->priv; + const struct sja1105_regs *regs = priv->info->regs; + struct device_node *switch_node = ds->dev->of_node; + struct device_node *mdio_node; + int rc; + + mdio_node = of_get_child_by_name(switch_node, "mdios"); + if (!mdio_node) + return 0; + + if (!of_device_is_available(mdio_node)) + goto out_put_mdio_node; + + if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) { + rc = sja1105_mdiobus_base_tx_register(priv, mdio_node); + if (rc) + goto err_put_mdio_node; + } + + if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) { + rc = sja1105_mdiobus_base_t1_register(priv, mdio_node); + if (rc) + goto err_free_base_tx_mdiobus; + } + +out_put_mdio_node: + of_node_put(mdio_node); + + return 0; + +err_free_base_tx_mdiobus: + sja1105_mdiobus_base_tx_unregister(priv); +err_put_mdio_node: + of_node_put(mdio_node); + + return rc; +} + +void sja1105_mdiobus_unregister(struct dsa_switch *ds) +{ + struct sja1105_private *priv = ds->priv; + + sja1105_mdiobus_base_t1_unregister(priv); + sja1105_mdiobus_base_tx_unregister(priv); +} diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c index 187c9fbbd397..54ecb5565761 100644 --- a/drivers/net/dsa/sja1105/sja1105_spi.c +++ b/drivers/net/dsa/sja1105/sja1105_spi.c @@ -436,6 +436,8 @@ static struct sja1105_regs sja1105et_regs = { .ptpclkval = 0x18, /* Spans 0x18 to 0x19 */ .ptpclkrate = 0x1A, .ptpclkcorp = 0x1D, + .mdio_100base_tx = SJA1105_RSV_ADDR, + .mdio_100base_t1 = SJA1105_RSV_ADDR, }; static struct sja1105_regs sja1105pqrs_regs = { @@ -473,6 +475,8 @@ static struct sja1105_regs sja1105pqrs_regs = { .ptpclkrate = 0x1B, .ptpclkcorp = 0x1E, .ptpsyncts = 0x1F, + .mdio_100base_tx = SJA1105_RSV_ADDR, + .mdio_100base_t1 = SJA1105_RSV_ADDR, }; static struct sja1105_regs sja1110_regs = { @@ -555,6 +559,8 @@ static struct sja1105_regs sja1110_regs = { .ptpclkrate = SJA1110_SPI_ADDR(0x74), .ptpclkcorp = SJA1110_SPI_ADDR(0x80), .ptpsyncts = SJA1110_SPI_ADDR(0x84), + .mdio_100base_tx = 0x1c2400, + .mdio_100base_t1 = 0x1c1000, }; const struct sja1105_info sja1105e_info = { @@ -785,6 +791,12 @@ const struct sja1105_info sja1110a_info = { false, false, false, false, false, false}, .supports_2500basex = {false, false, false, true, true, false, false, false, false, false, false}, + .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1}, .name = "SJA1110A", }; @@ -824,6 +836,12 @@ const struct sja1105_info sja1110b_info = { false, false, false, false, false, false}, .supports_2500basex = {false, false, false, true, true, false, false, false, false, false, false}, + .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_NO_PHY}, .name = "SJA1110B", }; @@ -863,6 +881,12 @@ const struct sja1105_info sja1110c_info = { false, false, false, false, false, false}, .supports_2500basex = {false, false, false, false, true, false, false, false, false, false, false}, + .internal_phy = {SJA1105_NO_PHY, SJA1105_PHY_BASE_TX, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY}, .name = "SJA1110C", }; @@ -900,5 +924,11 @@ const struct sja1105_info sja1110d_info = { false, false, false, false, false, false}, .supports_sgmii = {false, true, true, true, true, false, false, false, false, false, false}, + .internal_phy = {SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY, SJA1105_PHY_BASE_T1, + SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1, + SJA1105_NO_PHY, SJA1105_NO_PHY, + SJA1105_NO_PHY}, .name = "SJA1110D", };