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 Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 43793C433F5 for ; Fri, 31 Dec 2021 04:34:55 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S242691AbhLaEew (ORCPT ); Thu, 30 Dec 2021 23:34:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:55008 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S242690AbhLaEet (ORCPT ); Thu, 30 Dec 2021 23:34:49 -0500 Received: from mail-qt1-x829.google.com (mail-qt1-x829.google.com [IPv6:2607:f8b0:4864:20::829]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4E5F6C061574 for ; Thu, 30 Dec 2021 20:34:49 -0800 (PST) Received: by mail-qt1-x829.google.com with SMTP id z9so23439311qtj.9 for ; Thu, 30 Dec 2021 20:34:49 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=bTy35kBRJm3MjOlxQA/M3Ehok6BnLEFWDAglMZw3cTY=; b=WfLUieUhdyGKDLrSmIG9rjaBpumjSW7TB9Iug8a6ew/akATdath8e5AYwzDI+y4gFy tv8c/Sqfa/8GIVstExMZTEldOT0oGi/zTWrbehGeuSYkblKxw/VBO4b1e1/pVnJY/BMP U+Ep/QLipoxTw/nJEWWA0P3QCd3GXU80GLIjYgxR6KYdLe1fyeh5zuB2HPCCEB06anCF +l4wMbBPWiCYfewddFFc7+/X7n2VgetcD7PIUh0pM3oqq1WCkDQP3iU+FwhMgXvpRd+7 Hm6mtxLUp/MSnQ8HTtDQqxncxAYru68oZAX9PSCekN/kFgksT5fPS7d5EpBKaCTyaFyE qC9Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=bTy35kBRJm3MjOlxQA/M3Ehok6BnLEFWDAglMZw3cTY=; b=sOxon/rAF84kCvbaAqXaeCK9LwbgV8PNBFtYAkT/E5Gs7lxL2j0S4SP57et091ihGl FeR1Cxfsc4upo1SqjBHJ/KaMYzormpXt/XJRXBl5mLbNWI1bsTNdr6SrHqy1QNxuXXOC Bq5baTWDXFIAkSwIzc70Cin7Xo1tsFPTGpSulSQmxbCyoG3GtEnQ33ETiCPKUasPVocB Upk8wzVJgHcXY5BTdSmRJ5CQgttYrMYpHNaGW5pA4mCXuKQCa59I3z62/AFVDz8ceiCY IFKLndB89WSZoxZSVmuUGeR3JW+ZfXpH9IyjiUkLnn91LeiTo08xjhedhg9/nXp6AauE 9vNg== X-Gm-Message-State: AOAM5332eZzYosz207Zc+Y92ZGZr2ZHJLQiAdLzh1S235JeAD28wZ+5y w6UyEvP+TehhfqOTbtXlq/q42egCNLTteMA+ X-Google-Smtp-Source: ABdhPJz7A5AeUqGmCF/RIJyJ2GjIsoOLt6ZD078+khYvlC9sr2JLklpQxQL1x69dww1BUcXIssYYfw== X-Received: by 2002:ac8:590a:: with SMTP id 10mr29234579qty.186.1640925288213; Thu, 30 Dec 2021 20:34:48 -0800 (PST) Received: from tresc043793.tre-sc.gov.br ([187.94.103.218]) by smtp.gmail.com with ESMTPSA id i5sm8020030qti.27.2021.12.30.20.34.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 30 Dec 2021 20:34:47 -0800 (PST) From: Luiz Angelo Daros de Luca To: netdev@vger.kernel.org Cc: linus.walleij@linaro.org, andrew@lunn.ch, vivien.didelot@gmail.com, f.fainelli@gmail.com, olteanv@gmail.com, alsi@bang-olufsen.dk, arinc.unal@arinc9.com, frank-w@public-files.de, Luiz Angelo Daros de Luca Subject: [PATCH net-next v3 06/11] net: dsa: realtek: add new mdio interface for drivers Date: Fri, 31 Dec 2021 01:33:01 -0300 Message-Id: <20211231043306.12322-7-luizluca@gmail.com> X-Mailer: git-send-email 2.34.0 In-Reply-To: <20211231043306.12322-1-luizluca@gmail.com> References: <20211231043306.12322-1-luizluca@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org This driver is a mdio_driver instead of a platform driver (like realtek-smi). Signed-off-by: Luiz Angelo Daros de Luca Tested-by: Arınç ÜNAL --- drivers/net/dsa/realtek/Kconfig | 11 +- drivers/net/dsa/realtek/Makefile | 1 + drivers/net/dsa/realtek/realtek-mdio.c | 221 +++++++++++++++++++++++++ drivers/net/dsa/realtek/realtek.h | 2 + 4 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 drivers/net/dsa/realtek/realtek-mdio.c diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig index cd1aa95b7bf0..73b26171fade 100644 --- a/drivers/net/dsa/realtek/Kconfig +++ b/drivers/net/dsa/realtek/Kconfig @@ -9,6 +9,13 @@ menuconfig NET_DSA_REALTEK help Select to enable support for Realtek Ethernet switch chips. +config NET_DSA_REALTEK_MDIO + tristate "Realtek MDIO connected switch driver" + depends on NET_DSA_REALTEK + default y + help + Select to enable support for registering switches configured + through MDIO. config NET_DSA_REALTEK_SMI tristate "Realtek SMI connected switch driver" depends on NET_DSA_REALTEK @@ -21,7 +28,7 @@ config NET_DSA_REALTEK_RTL8365MB tristate "Realtek RTL8365MB switch subdriver" default y depends on NET_DSA_REALTEK - depends on NET_DSA_REALTEK_SMI + depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO select NET_DSA_TAG_RTL8_4 help Select to enable support for Realtek RTL8365MB @@ -30,7 +37,7 @@ config NET_DSA_REALTEK_RTL8366RB tristate "Realtek RTL8366RB switch subdriver" default y depends on NET_DSA_REALTEK - depends on NET_DSA_REALTEK_SMI + depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO select NET_DSA_TAG_RTL4_A help Select to enable support for Realtek RTL8366RB diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile index 8b5a4abcedd3..0aab57252a7c 100644 --- a/drivers/net/dsa/realtek/Makefile +++ b/drivers/net/dsa/realtek/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o rtl8366-objs := rtl8366-core.o rtl8366rb.o diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c new file mode 100644 index 000000000000..ee10a0ecaab6 --- /dev/null +++ b/drivers/net/dsa/realtek/realtek-mdio.c @@ -0,0 +1,221 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* Realtek MDIO interface driver + * + * ASICs we intend to support with this driver: + * + * RTL8366 - The original version, apparently + * RTL8369 - Similar enough to have the same datsheet as RTL8366 + * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite + * different register layout from the other two + * RTL8366S - Is this "RTL8366 super"? + * RTL8367 - Has an OpenWRT driver as well + * RTL8368S - Seems to be an alternative name for RTL8366RB + * RTL8370 - Also uses SMI + * + * Copyright (C) 2017 Linus Walleij + * Copyright (C) 2010 Antti Seppälä + * Copyright (C) 2010 Roman Yeryomin + * Copyright (C) 2011 Colin Leitner + * Copyright (C) 2009-2010 Gabor Juhos + */ + +#include +#include +#include + +#include "realtek.h" + +/* Read/write via mdiobus */ +#define REALTEK_MDIO_CTRL0_REG 31 +#define REALTEK_MDIO_START_REG 29 +#define REALTEK_MDIO_CTRL1_REG 21 +#define REALTEK_MDIO_ADDRESS_REG 23 +#define REALTEK_MDIO_DATA_WRITE_REG 24 +#define REALTEK_MDIO_DATA_READ_REG 25 + +#define REALTEK_MDIO_START_OP 0xFFFF +#define REALTEK_MDIO_ADDR_OP 0x000E +#define REALTEK_MDIO_READ_OP 0x0001 +#define REALTEK_MDIO_WRITE_OP 0x0003 + +int realtek_mdio_read_reg(struct realtek_priv *priv, u32 addr, u32 *data) +{ + u32 phy_id = priv->phy_id; + struct mii_bus *bus = priv->bus; + + mutex_lock(&bus->mdio_lock); + + bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + *data = bus->read(bus, phy_id, REALTEK_MDIO_DATA_READ_REG); + + mutex_unlock(&bus->mdio_lock); + + return 0; +} + +static int realtek_mdio_write_reg(struct realtek_priv *priv, u32 addr, u32 data) +{ + u32 phy_id = priv->phy_id; + struct mii_bus *bus = priv->bus; + + mutex_lock(&bus->mdio_lock); + + bus->write(bus, phy_id, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + bus->write(bus, phy_id, REALTEK_MDIO_ADDRESS_REG, addr); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + bus->write(bus, phy_id, REALTEK_MDIO_DATA_WRITE_REG, data); + bus->write(bus, phy_id, REALTEK_MDIO_START_REG, REALTEK_MDIO_START_OP); + bus->write(bus, phy_id, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP); + + mutex_unlock(&bus->mdio_lock); + + return 0; +} + +/* Regmap accessors */ + +static int realtek_mdio_write(void *ctx, u32 reg, u32 val) +{ + struct realtek_priv *priv = ctx; + + return realtek_mdio_write_reg(priv, reg, val); +} + +static int realtek_mdio_read(void *ctx, u32 reg, u32 *val) +{ + struct realtek_priv *priv = ctx; + + return realtek_mdio_read_reg(priv, reg, val); +} + +static const struct regmap_config realtek_mdio_regmap_config = { + .reg_bits = 10, /* A4..A0 R4..R0 */ + .val_bits = 16, + .reg_stride = 1, + /* PHY regs are at 0x8000 */ + .max_register = 0xffff, + .reg_format_endian = REGMAP_ENDIAN_BIG, + .reg_read = realtek_mdio_read, + .reg_write = realtek_mdio_write, + .cache_type = REGCACHE_NONE, +}; + +static int realtek_mdio_probe(struct mdio_device *mdiodev) +{ + struct realtek_priv *priv; + struct device *dev = &mdiodev->dev; + const struct realtek_variant *var; + int ret; + struct device_node *np; + + var = of_device_get_match_data(dev); + priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config); + if (IS_ERR(priv->map)) { + ret = PTR_ERR(priv->map); + dev_err(dev, "regmap init failed: %d\n", ret); + return ret; + } + + priv->phy_id = mdiodev->addr; + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; + priv->chip_data = (void *)priv + sizeof(*priv); + + priv->clk_delay = var->clk_delay; + priv->cmd_read = var->cmd_read; + priv->cmd_write = var->cmd_write; + priv->ops = var->ops; + + priv->write_reg_noack = realtek_mdio_write_reg; + + np = dev->of_node; + + dev_set_drvdata(dev, priv); + + /* TODO: if power is software controlled, set up any regulators here */ + priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds"); + + ret = priv->ops->detect(priv); + if (ret) { + dev_err(dev, "unable to detect switch\n"); + return ret; + } + + priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); + if (!priv->ds) + return -ENOMEM; + + priv->ds->dev = dev; + priv->ds->num_ports = priv->num_ports; + priv->ds->priv = priv; + priv->ds->ops = var->ds_ops; + + ret = dsa_register_switch(priv->ds); + if (ret) { + dev_err(priv->dev, "unable to register switch ret = %d\n", ret); + return ret; + } + + return 0; +} + +static void realtek_mdio_remove(struct mdio_device *mdiodev) +{ + struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); + + if (!priv) + return; + + dsa_unregister_switch(priv->ds); + + dev_set_drvdata(&mdiodev->dev, NULL); +} + +static void realtek_mdio_shutdown(struct mdio_device *mdiodev) +{ + struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); + + if (!priv) + return; + + dsa_switch_shutdown(priv->ds); + + dev_set_drvdata(&mdiodev->dev, NULL); +} + +static const struct of_device_id realtek_mdio_of_match[] = { +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB) + { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, }, +#endif +#if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB) + { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, }, +#endif + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, realtek_mdio_of_match); + +static struct mdio_driver realtek_mdio_driver = { + .mdiodrv.driver = { + .name = "realtek-mdio", + .of_match_table = of_match_ptr(realtek_mdio_of_match), + }, + .probe = realtek_mdio_probe, + .remove = realtek_mdio_remove, + .shutdown = realtek_mdio_shutdown, +}; + +mdio_module_driver(realtek_mdio_driver); + +MODULE_AUTHOR("Luiz Angelo Daros de Luca "); +MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/realtek/realtek.h b/drivers/net/dsa/realtek/realtek.h index a03de15c4a94..97274273cb3b 100644 --- a/drivers/net/dsa/realtek/realtek.h +++ b/drivers/net/dsa/realtek/realtek.h @@ -50,6 +50,8 @@ struct realtek_priv { struct gpio_desc *mdio; struct regmap *map; struct mii_bus *slave_mii_bus; + struct mii_bus *bus; + int phy_id; unsigned int clk_delay; u8 cmd_read; -- 2.34.0