1 // SPDX-License-Identifier: GPL-2.0+ 2 /* Copyright (c) Tehuti Networks Ltd. */ 3 4 #include <linux/netdevice.h> 5 #include <linux/pci.h> 6 #include <linux/phylink.h> 7 8 #include "tn40.h" 9 10 #define TN40_MDIO_DEVAD_MASK GENMASK(4, 0) 11 #define TN40_MDIO_PRTAD_MASK GENMASK(9, 5) 12 #define TN40_MDIO_CMD_VAL(device, port) \ 13 (FIELD_PREP(TN40_MDIO_DEVAD_MASK, (device)) | \ 14 (FIELD_PREP(TN40_MDIO_PRTAD_MASK, (port)))) 15 #define TN40_MDIO_CMD_READ BIT(15) 16 17 #define AQR105_FIRMWARE "tehuti/aqr105-tn40xx.cld" 18 19 static void tn40_mdio_set_speed(struct tn40_priv *priv, u32 speed) 20 { 21 void __iomem *regs = priv->regs; 22 int mdio_cfg; 23 24 if (speed == TN40_MDIO_SPEED_1MHZ) 25 mdio_cfg = (0x7d << 7) | 0x08; /* 1MHz */ 26 else 27 mdio_cfg = 0xA08; /* 6MHz */ 28 mdio_cfg |= (1 << 6); 29 writel(mdio_cfg, regs + TN40_REG_MDIO_CMD_STAT); 30 msleep(100); 31 } 32 33 static u32 tn40_mdio_stat(struct tn40_priv *priv) 34 { 35 void __iomem *regs = priv->regs; 36 37 return readl(regs + TN40_REG_MDIO_CMD_STAT); 38 } 39 40 static int tn40_mdio_wait_nobusy(struct tn40_priv *priv, u32 *val) 41 { 42 u32 stat; 43 int ret; 44 45 ret = readx_poll_timeout_atomic(tn40_mdio_stat, priv, stat, 46 TN40_GET_MDIO_BUSY(stat) == 0, 10, 47 10000); 48 if (val) 49 *val = stat; 50 return ret; 51 } 52 53 static int tn40_mdio_read(struct tn40_priv *priv, int port, int device, 54 u16 regnum) 55 { 56 void __iomem *regs = priv->regs; 57 u32 i; 58 59 /* wait until MDIO is not busy */ 60 if (tn40_mdio_wait_nobusy(priv, NULL)) 61 return -EIO; 62 63 i = TN40_MDIO_CMD_VAL(device, port); 64 writel(i, regs + TN40_REG_MDIO_CMD); 65 writel((u32)regnum, regs + TN40_REG_MDIO_ADDR); 66 if (tn40_mdio_wait_nobusy(priv, NULL)) 67 return -EIO; 68 69 writel(TN40_MDIO_CMD_READ | i, regs + TN40_REG_MDIO_CMD); 70 /* read CMD_STAT until not busy */ 71 if (tn40_mdio_wait_nobusy(priv, NULL)) 72 return -EIO; 73 74 return lower_16_bits(readl(regs + TN40_REG_MDIO_DATA)); 75 } 76 77 static int tn40_mdio_write(struct tn40_priv *priv, int port, int device, 78 u16 regnum, u16 data) 79 { 80 void __iomem *regs = priv->regs; 81 u32 tmp_reg = 0; 82 int ret; 83 84 /* wait until MDIO is not busy */ 85 if (tn40_mdio_wait_nobusy(priv, NULL)) 86 return -EIO; 87 writel(TN40_MDIO_CMD_VAL(device, port), regs + TN40_REG_MDIO_CMD); 88 writel((u32)regnum, regs + TN40_REG_MDIO_ADDR); 89 if (tn40_mdio_wait_nobusy(priv, NULL)) 90 return -EIO; 91 writel((u32)data, regs + TN40_REG_MDIO_DATA); 92 /* read CMD_STAT until not busy */ 93 ret = tn40_mdio_wait_nobusy(priv, &tmp_reg); 94 if (ret) 95 return -EIO; 96 97 if (TN40_GET_MDIO_RD_ERR(tmp_reg)) { 98 dev_err(&priv->pdev->dev, "MDIO error after write command\n"); 99 return -EIO; 100 } 101 return 0; 102 } 103 104 static int tn40_mdio_read_c45(struct mii_bus *mii_bus, int addr, int devnum, 105 int regnum) 106 { 107 return tn40_mdio_read(mii_bus->priv, addr, devnum, regnum); 108 } 109 110 static int tn40_mdio_write_c45(struct mii_bus *mii_bus, int addr, int devnum, 111 int regnum, u16 val) 112 { 113 return tn40_mdio_write(mii_bus->priv, addr, devnum, regnum, val); 114 } 115 116 /* registers an mdio node and an aqr105 PHY at address 1 117 * tn40_mdio-%id { 118 * ethernet-phy@1 { 119 * compatible = "ethernet-phy-id03a1.b4a3"; 120 * reg = <1>; 121 * firmware-name = AQR105_FIRMWARE; 122 * }; 123 * }; 124 */ 125 static int tn40_swnodes_register(struct tn40_priv *priv) 126 { 127 struct tn40_nodes *nodes = &priv->nodes; 128 struct pci_dev *pdev = priv->pdev; 129 struct software_node *swnodes; 130 u32 id; 131 132 id = pci_dev_id(pdev); 133 134 snprintf(nodes->phy_name, sizeof(nodes->phy_name), "ethernet-phy@1"); 135 snprintf(nodes->mdio_name, sizeof(nodes->mdio_name), "tn40_mdio-%x", 136 id); 137 138 swnodes = nodes->swnodes; 139 140 swnodes[SWNODE_MDIO] = NODE_PROP(nodes->mdio_name, NULL); 141 142 nodes->phy_props[0] = PROPERTY_ENTRY_STRING("compatible", 143 "ethernet-phy-id03a1.b4a3"); 144 nodes->phy_props[1] = PROPERTY_ENTRY_U32("reg", 1); 145 nodes->phy_props[2] = PROPERTY_ENTRY_STRING("firmware-name", 146 AQR105_FIRMWARE); 147 swnodes[SWNODE_PHY] = NODE_PAR_PROP(nodes->phy_name, 148 &swnodes[SWNODE_MDIO], 149 nodes->phy_props); 150 151 nodes->group[SWNODE_PHY] = &swnodes[SWNODE_PHY]; 152 nodes->group[SWNODE_MDIO] = &swnodes[SWNODE_MDIO]; 153 return software_node_register_node_group(nodes->group); 154 } 155 156 void tn40_swnodes_cleanup(struct tn40_priv *priv) 157 { 158 /* cleanup of swnodes is only needed for AQR105-based cards */ 159 if (priv->pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { 160 fwnode_handle_put(dev_fwnode(&priv->mdio->dev)); 161 device_remove_software_node(&priv->mdio->dev); 162 software_node_unregister_node_group(priv->nodes.group); 163 } 164 } 165 166 int tn40_mdiobus_init(struct tn40_priv *priv) 167 { 168 struct pci_dev *pdev = priv->pdev; 169 struct mii_bus *bus; 170 int ret; 171 172 bus = devm_mdiobus_alloc(&pdev->dev); 173 if (!bus) 174 return -ENOMEM; 175 176 bus->name = TN40_DRV_NAME; 177 bus->parent = &pdev->dev; 178 snprintf(bus->id, MII_BUS_ID_SIZE, "tn40xx-%x-%x", 179 pci_domain_nr(pdev->bus), pci_dev_id(pdev)); 180 bus->priv = priv; 181 182 bus->read_c45 = tn40_mdio_read_c45; 183 bus->write_c45 = tn40_mdio_write_c45; 184 priv->mdio = bus; 185 186 /* provide swnodes for AQR105-based cards only */ 187 if (pdev->device == PCI_DEVICE_ID_TEHUTI_TN9510) { 188 ret = tn40_swnodes_register(priv); 189 if (ret) { 190 pr_err("swnodes failed\n"); 191 return ret; 192 } 193 194 ret = device_add_software_node(&bus->dev, 195 priv->nodes.group[SWNODE_MDIO]); 196 if (ret) { 197 dev_err(&pdev->dev, 198 "device_add_software_node failed: %d\n", ret); 199 goto err_swnodes_unregister; 200 } 201 } 202 203 tn40_mdio_set_speed(priv, TN40_MDIO_SPEED_6MHZ); 204 ret = devm_mdiobus_register(&pdev->dev, bus); 205 if (ret) { 206 dev_err(&pdev->dev, "failed to register mdiobus %d %u %u\n", 207 ret, bus->state, MDIOBUS_UNREGISTERED); 208 goto err_swnodes_cleanup; 209 } 210 return 0; 211 212 err_swnodes_unregister: 213 software_node_unregister_node_group(priv->nodes.group); 214 return ret; 215 err_swnodes_cleanup: 216 tn40_swnodes_cleanup(priv); 217 return ret; 218 } 219 220 MODULE_FIRMWARE(AQR105_FIRMWARE); 221