Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dsa: realtek: add new mdio interface for drivers

This driver is a mdio_driver instead of a platform driver (like
realtek-smi).

ds_ops was duplicated for smi and mdio usage as mdio interfaces uses
phy_{read,write} in ds_ops and the presence of phy_read is incompatible
with external slave_mii_bus allocation.

Signed-off-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
Tested-by: Arınç ÜNAL <arinc.unal@arinc9.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Luiz Angelo Daros de Luca and committed by
David S. Miller
aac94001 765c39a4

+317 -8
+10 -2
drivers/net/dsa/realtek/Kconfig
··· 9 9 help 10 10 Select to enable support for Realtek Ethernet switch chips. 11 11 12 + config NET_DSA_REALTEK_MDIO 13 + tristate "Realtek MDIO connected switch driver" 14 + depends on NET_DSA_REALTEK 15 + default y 16 + help 17 + Select to enable support for registering switches configured 18 + through MDIO. 19 + 12 20 config NET_DSA_REALTEK_SMI 13 21 tristate "Realtek SMI connected switch driver" 14 22 depends on NET_DSA_REALTEK ··· 29 21 tristate "Realtek RTL8365MB switch subdriver" 30 22 default y 31 23 depends on NET_DSA_REALTEK 32 - depends on NET_DSA_REALTEK_SMI 24 + depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO 33 25 select NET_DSA_TAG_RTL8_4 34 26 help 35 27 Select to enable support for Realtek RTL8365MB ··· 38 30 tristate "Realtek RTL8366RB switch subdriver" 39 31 default y 40 32 depends on NET_DSA_REALTEK 41 - depends on NET_DSA_REALTEK_SMI 33 + depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO 42 34 select NET_DSA_TAG_RTL4_A 43 35 help 44 36 Select to enable support for Realtek RTL8366RB
+1
drivers/net/dsa/realtek/Makefile
··· 1 1 # SPDX-License-Identifier: GPL-2.0 2 + obj-$(CONFIG_NET_DSA_REALTEK_MDIO) += realtek-mdio.o 2 3 obj-$(CONFIG_NET_DSA_REALTEK_SMI) += realtek-smi.o 3 4 obj-$(CONFIG_NET_DSA_REALTEK_RTL8366RB) += rtl8366.o 4 5 rtl8366-objs := rtl8366-core.o rtl8366rb.o
+228
drivers/net/dsa/realtek/realtek-mdio.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* Realtek MDIO interface driver 3 + * 4 + * ASICs we intend to support with this driver: 5 + * 6 + * RTL8366 - The original version, apparently 7 + * RTL8369 - Similar enough to have the same datsheet as RTL8366 8 + * RTL8366RB - Probably reads out "RTL8366 revision B", has a quite 9 + * different register layout from the other two 10 + * RTL8366S - Is this "RTL8366 super"? 11 + * RTL8367 - Has an OpenWRT driver as well 12 + * RTL8368S - Seems to be an alternative name for RTL8366RB 13 + * RTL8370 - Also uses SMI 14 + * 15 + * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org> 16 + * Copyright (C) 2010 Antti Seppälä <a.seppala@gmail.com> 17 + * Copyright (C) 2010 Roman Yeryomin <roman@advem.lv> 18 + * Copyright (C) 2011 Colin Leitner <colin.leitner@googlemail.com> 19 + * Copyright (C) 2009-2010 Gabor Juhos <juhosg@openwrt.org> 20 + */ 21 + 22 + #include <linux/module.h> 23 + #include <linux/of_device.h> 24 + #include <linux/regmap.h> 25 + 26 + #include "realtek.h" 27 + 28 + /* Read/write via mdiobus */ 29 + #define REALTEK_MDIO_CTRL0_REG 31 30 + #define REALTEK_MDIO_START_REG 29 31 + #define REALTEK_MDIO_CTRL1_REG 21 32 + #define REALTEK_MDIO_ADDRESS_REG 23 33 + #define REALTEK_MDIO_DATA_WRITE_REG 24 34 + #define REALTEK_MDIO_DATA_READ_REG 25 35 + 36 + #define REALTEK_MDIO_START_OP 0xFFFF 37 + #define REALTEK_MDIO_ADDR_OP 0x000E 38 + #define REALTEK_MDIO_READ_OP 0x0001 39 + #define REALTEK_MDIO_WRITE_OP 0x0003 40 + 41 + static int realtek_mdio_write(void *ctx, u32 reg, u32 val) 42 + { 43 + struct realtek_priv *priv = ctx; 44 + struct mii_bus *bus = priv->bus; 45 + int ret; 46 + 47 + mutex_lock(&bus->mdio_lock); 48 + 49 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); 50 + if (ret) 51 + goto out_unlock; 52 + 53 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg); 54 + if (ret) 55 + goto out_unlock; 56 + 57 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG, val); 58 + if (ret) 59 + goto out_unlock; 60 + 61 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP); 62 + 63 + out_unlock: 64 + mutex_unlock(&bus->mdio_lock); 65 + 66 + return ret; 67 + } 68 + 69 + static int realtek_mdio_read(void *ctx, u32 reg, u32 *val) 70 + { 71 + struct realtek_priv *priv = ctx; 72 + struct mii_bus *bus = priv->bus; 73 + int ret; 74 + 75 + mutex_lock(&bus->mdio_lock); 76 + 77 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP); 78 + if (ret) 79 + goto out_unlock; 80 + 81 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg); 82 + if (ret) 83 + goto out_unlock; 84 + 85 + ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP); 86 + if (ret) 87 + goto out_unlock; 88 + 89 + ret = bus->read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG); 90 + if (ret >= 0) { 91 + *val = ret; 92 + ret = 0; 93 + } 94 + 95 + out_unlock: 96 + mutex_unlock(&bus->mdio_lock); 97 + 98 + return ret; 99 + } 100 + 101 + static const struct regmap_config realtek_mdio_regmap_config = { 102 + .reg_bits = 10, /* A4..A0 R4..R0 */ 103 + .val_bits = 16, 104 + .reg_stride = 1, 105 + /* PHY regs are at 0x8000 */ 106 + .max_register = 0xffff, 107 + .reg_format_endian = REGMAP_ENDIAN_BIG, 108 + .reg_read = realtek_mdio_read, 109 + .reg_write = realtek_mdio_write, 110 + .cache_type = REGCACHE_NONE, 111 + }; 112 + 113 + static int realtek_mdio_probe(struct mdio_device *mdiodev) 114 + { 115 + struct realtek_priv *priv; 116 + struct device *dev = &mdiodev->dev; 117 + const struct realtek_variant *var; 118 + int ret; 119 + struct device_node *np; 120 + 121 + var = of_device_get_match_data(dev); 122 + if (!var) 123 + return -EINVAL; 124 + 125 + priv = devm_kzalloc(&mdiodev->dev, sizeof(*priv), GFP_KERNEL); 126 + if (!priv) 127 + return -ENOMEM; 128 + 129 + priv->map = devm_regmap_init(dev, NULL, priv, &realtek_mdio_regmap_config); 130 + if (IS_ERR(priv->map)) { 131 + ret = PTR_ERR(priv->map); 132 + dev_err(dev, "regmap init failed: %d\n", ret); 133 + return ret; 134 + } 135 + 136 + priv->mdio_addr = mdiodev->addr; 137 + priv->bus = mdiodev->bus; 138 + priv->dev = &mdiodev->dev; 139 + priv->chip_data = (void *)priv + sizeof(*priv); 140 + 141 + priv->clk_delay = var->clk_delay; 142 + priv->cmd_read = var->cmd_read; 143 + priv->cmd_write = var->cmd_write; 144 + priv->ops = var->ops; 145 + 146 + priv->write_reg_noack = realtek_mdio_write; 147 + 148 + np = dev->of_node; 149 + 150 + dev_set_drvdata(dev, priv); 151 + 152 + /* TODO: if power is software controlled, set up any regulators here */ 153 + priv->leds_disabled = of_property_read_bool(np, "realtek,disable-leds"); 154 + 155 + ret = priv->ops->detect(priv); 156 + if (ret) { 157 + dev_err(dev, "unable to detect switch\n"); 158 + return ret; 159 + } 160 + 161 + priv->ds = devm_kzalloc(dev, sizeof(*priv->ds), GFP_KERNEL); 162 + if (!priv->ds) 163 + return -ENOMEM; 164 + 165 + priv->ds->dev = dev; 166 + priv->ds->num_ports = priv->num_ports; 167 + priv->ds->priv = priv; 168 + priv->ds->ops = var->ds_ops_mdio; 169 + 170 + ret = dsa_register_switch(priv->ds); 171 + if (ret) { 172 + dev_err(priv->dev, "unable to register switch ret = %d\n", ret); 173 + return ret; 174 + } 175 + 176 + return 0; 177 + } 178 + 179 + static void realtek_mdio_remove(struct mdio_device *mdiodev) 180 + { 181 + struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); 182 + 183 + if (!priv) 184 + return; 185 + 186 + dsa_unregister_switch(priv->ds); 187 + 188 + dev_set_drvdata(&mdiodev->dev, NULL); 189 + } 190 + 191 + static void realtek_mdio_shutdown(struct mdio_device *mdiodev) 192 + { 193 + struct realtek_priv *priv = dev_get_drvdata(&mdiodev->dev); 194 + 195 + if (!priv) 196 + return; 197 + 198 + dsa_switch_shutdown(priv->ds); 199 + 200 + dev_set_drvdata(&mdiodev->dev, NULL); 201 + } 202 + 203 + static const struct of_device_id realtek_mdio_of_match[] = { 204 + #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8366RB) 205 + { .compatible = "realtek,rtl8366rb", .data = &rtl8366rb_variant, }, 206 + #endif 207 + #if IS_ENABLED(CONFIG_NET_DSA_REALTEK_RTL8365MB) 208 + { .compatible = "realtek,rtl8365mb", .data = &rtl8365mb_variant, }, 209 + #endif 210 + { /* sentinel */ }, 211 + }; 212 + MODULE_DEVICE_TABLE(of, realtek_mdio_of_match); 213 + 214 + static struct mdio_driver realtek_mdio_driver = { 215 + .mdiodrv.driver = { 216 + .name = "realtek-mdio", 217 + .of_match_table = of_match_ptr(realtek_mdio_of_match), 218 + }, 219 + .probe = realtek_mdio_probe, 220 + .remove = realtek_mdio_remove, 221 + .shutdown = realtek_mdio_shutdown, 222 + }; 223 + 224 + mdio_module_driver(realtek_mdio_driver); 225 + 226 + MODULE_AUTHOR("Luiz Angelo Daros de Luca <luizluca@gmail.com>"); 227 + MODULE_DESCRIPTION("Driver for Realtek ethernet switch connected via MDIO interface"); 228 + MODULE_LICENSE("GPL");
+1 -1
drivers/net/dsa/realtek/realtek-smi.c
··· 455 455 priv->ds->num_ports = priv->num_ports; 456 456 priv->ds->priv = priv; 457 457 458 - priv->ds->ops = var->ds_ops; 458 + priv->ds->ops = var->ds_ops_smi; 459 459 ret = dsa_register_switch(priv->ds); 460 460 if (ret) { 461 461 dev_err_probe(dev, ret, "unable to register switch\n");
+4 -1
drivers/net/dsa/realtek/realtek.h
··· 50 50 struct gpio_desc *mdio; 51 51 struct regmap *map; 52 52 struct mii_bus *slave_mii_bus; 53 + struct mii_bus *bus; 54 + int mdio_addr; 53 55 54 56 unsigned int clk_delay; 55 57 u8 cmd_read; ··· 111 109 }; 112 110 113 111 struct realtek_variant { 114 - const struct dsa_switch_ops *ds_ops; 112 + const struct dsa_switch_ops *ds_ops_smi; 113 + const struct dsa_switch_ops *ds_ops_mdio; 115 114 const struct realtek_ops *ops; 116 115 unsigned int clk_delay; 117 116 u8 cmd_read;
+34 -2
drivers/net/dsa/realtek/rtl8365mb.c
··· 730 730 return 0; 731 731 } 732 732 733 + static int rtl8365mb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum) 734 + { 735 + return rtl8365mb_phy_read(ds->priv, phy, regnum); 736 + } 737 + 738 + static int rtl8365mb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum, 739 + u16 val) 740 + { 741 + return rtl8365mb_phy_write(ds->priv, phy, regnum, val); 742 + } 743 + 733 744 static enum dsa_tag_protocol 734 745 rtl8365mb_get_tag_protocol(struct dsa_switch *ds, int port, 735 746 enum dsa_tag_protocol mp) ··· 1964 1953 return 0; 1965 1954 } 1966 1955 1967 - static const struct dsa_switch_ops rtl8365mb_switch_ops = { 1956 + static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = { 1968 1957 .get_tag_protocol = rtl8365mb_get_tag_protocol, 1969 1958 .setup = rtl8365mb_setup, 1970 1959 .teardown = rtl8365mb_teardown, ··· 1982 1971 .get_stats64 = rtl8365mb_get_stats64, 1983 1972 }; 1984 1973 1974 + static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = { 1975 + .get_tag_protocol = rtl8365mb_get_tag_protocol, 1976 + .setup = rtl8365mb_setup, 1977 + .teardown = rtl8365mb_teardown, 1978 + .phylink_validate = rtl8365mb_phylink_validate, 1979 + .phylink_mac_config = rtl8365mb_phylink_mac_config, 1980 + .phylink_mac_link_down = rtl8365mb_phylink_mac_link_down, 1981 + .phylink_mac_link_up = rtl8365mb_phylink_mac_link_up, 1982 + .phy_read = rtl8365mb_dsa_phy_read, 1983 + .phy_write = rtl8365mb_dsa_phy_write, 1984 + .port_stp_state_set = rtl8365mb_port_stp_state_set, 1985 + .get_strings = rtl8365mb_get_strings, 1986 + .get_ethtool_stats = rtl8365mb_get_ethtool_stats, 1987 + .get_sset_count = rtl8365mb_get_sset_count, 1988 + .get_eth_phy_stats = rtl8365mb_get_phy_stats, 1989 + .get_eth_mac_stats = rtl8365mb_get_mac_stats, 1990 + .get_eth_ctrl_stats = rtl8365mb_get_ctrl_stats, 1991 + .get_stats64 = rtl8365mb_get_stats64, 1992 + }; 1993 + 1985 1994 static const struct realtek_ops rtl8365mb_ops = { 1986 1995 .detect = rtl8365mb_detect, 1987 1996 .phy_read = rtl8365mb_phy_read, ··· 2009 1978 }; 2010 1979 2011 1980 const struct realtek_variant rtl8365mb_variant = { 2012 - .ds_ops = &rtl8365mb_switch_ops, 1981 + .ds_ops_smi = &rtl8365mb_switch_ops_smi, 1982 + .ds_ops_mdio = &rtl8365mb_switch_ops_mdio, 2013 1983 .ops = &rtl8365mb_ops, 2014 1984 .clk_delay = 10, 2015 1985 .cmd_read = 0xb9,
+39 -2
drivers/net/dsa/realtek/rtl8366rb.c
··· 1703 1703 return 0; 1704 1704 } 1705 1705 1706 + static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum) 1707 + { 1708 + return rtl8366rb_phy_read(ds->priv, phy, regnum); 1709 + } 1710 + 1711 + static int rtl8366rb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum, 1712 + u16 val) 1713 + { 1714 + return rtl8366rb_phy_write(ds->priv, phy, regnum, val); 1715 + } 1716 + 1706 1717 static int rtl8366rb_reset_chip(struct realtek_priv *priv) 1707 1718 { 1708 1719 int timeout = 10; ··· 1779 1768 return 0; 1780 1769 } 1781 1770 1782 - static const struct dsa_switch_ops rtl8366rb_switch_ops = { 1771 + static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = { 1783 1772 .get_tag_protocol = rtl8366_get_tag_protocol, 1784 1773 .setup = rtl8366rb_setup, 1774 + .phylink_mac_link_up = rtl8366rb_mac_link_up, 1775 + .phylink_mac_link_down = rtl8366rb_mac_link_down, 1776 + .get_strings = rtl8366_get_strings, 1777 + .get_ethtool_stats = rtl8366_get_ethtool_stats, 1778 + .get_sset_count = rtl8366_get_sset_count, 1779 + .port_bridge_join = rtl8366rb_port_bridge_join, 1780 + .port_bridge_leave = rtl8366rb_port_bridge_leave, 1781 + .port_vlan_filtering = rtl8366rb_vlan_filtering, 1782 + .port_vlan_add = rtl8366_vlan_add, 1783 + .port_vlan_del = rtl8366_vlan_del, 1784 + .port_enable = rtl8366rb_port_enable, 1785 + .port_disable = rtl8366rb_port_disable, 1786 + .port_pre_bridge_flags = rtl8366rb_port_pre_bridge_flags, 1787 + .port_bridge_flags = rtl8366rb_port_bridge_flags, 1788 + .port_stp_state_set = rtl8366rb_port_stp_state_set, 1789 + .port_fast_age = rtl8366rb_port_fast_age, 1790 + .port_change_mtu = rtl8366rb_change_mtu, 1791 + .port_max_mtu = rtl8366rb_max_mtu, 1792 + }; 1793 + 1794 + static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = { 1795 + .get_tag_protocol = rtl8366_get_tag_protocol, 1796 + .setup = rtl8366rb_setup, 1797 + .phy_read = rtl8366rb_dsa_phy_read, 1798 + .phy_write = rtl8366rb_dsa_phy_write, 1785 1799 .phylink_mac_link_up = rtl8366rb_mac_link_up, 1786 1800 .phylink_mac_link_down = rtl8366rb_mac_link_down, 1787 1801 .get_strings = rtl8366_get_strings, ··· 1844 1808 }; 1845 1809 1846 1810 const struct realtek_variant rtl8366rb_variant = { 1847 - .ds_ops = &rtl8366rb_switch_ops, 1811 + .ds_ops_smi = &rtl8366rb_switch_ops_smi, 1812 + .ds_ops_mdio = &rtl8366rb_switch_ops_mdio, 1848 1813 .ops = &rtl8366rb_ops, 1849 1814 .clk_delay = 10, 1850 1815 .cmd_read = 0xa9,