1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-or-later 2 /* 3 * Copyright 2008 - 2015 Freescale Semiconductor Inc. 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <linux/init.h> 9 #include <linux/module.h> 10 #include <linux/of_address.h> 11 #include <linux/of_platform.h> 12 #include <linux/of_net.h> 13 #include <linux/of_mdio.h> 14 #include <linux/device.h> 15 #include <linux/phy.h> 16 #include <linux/netdevice.h> 17 #include <linux/phy_fixed.h> 18 #include <linux/phylink.h> 19 #include <linux/etherdevice.h> 20 #include <linux/libfdt_env.h> 21 #include <linux/platform_device.h> 22 23 #include "mac.h" 24 #include "fman_mac.h" 25 #include "fman_dtsec.h" 26 #include "fman_tgec.h" 27 #include "fman_memac.h" 28 29 MODULE_LICENSE("Dual BSD/GPL"); 30 MODULE_DESCRIPTION("FSL FMan MAC API based driver"); 31 32 struct mac_priv_s { 33 u8 cell_index; 34 struct fman *fman; 35 struct platform_device *eth_dev; 36 u16 speed; 37 }; 38 39 struct mac_address { 40 u8 addr[ETH_ALEN]; 41 struct list_head list; 42 }; 43 44 static void mac_exception(struct mac_device *mac_dev, 45 enum fman_mac_exceptions ex) 46 { 47 if (ex == FM_MAC_EX_10G_RX_FIFO_OVFL) { 48 /* don't flag RX FIFO after the first */ 49 mac_dev->set_exception(mac_dev->fman_mac, 50 FM_MAC_EX_10G_RX_FIFO_OVFL, false); 51 dev_err(mac_dev->dev, "10G MAC got RX FIFO Error = %x\n", ex); 52 } 53 54 dev_dbg(mac_dev->dev, "%s:%s() -> %d\n", KBUILD_BASENAME ".c", 55 __func__, ex); 56 } 57 58 static DEFINE_MUTEX(eth_lock); 59 60 static struct platform_device *dpaa_eth_add_device(int fman_id, 61 struct mac_device *mac_dev) 62 { 63 struct platform_device *pdev; 64 struct dpaa_eth_data data; 65 struct mac_priv_s *priv; 66 static int dpaa_eth_dev_cnt; 67 int ret; 68 69 priv = mac_dev->priv; 70 71 data.mac_dev = mac_dev; 72 data.mac_hw_id = priv->cell_index; 73 data.fman_hw_id = fman_id; 74 75 mutex_lock(ð_lock); 76 pdev = platform_device_alloc("dpaa-ethernet", dpaa_eth_dev_cnt); 77 if (!pdev) { 78 ret = -ENOMEM; 79 goto no_mem; 80 } 81 82 pdev->dev.parent = mac_dev->dev; 83 84 ret = platform_device_add_data(pdev, &data, sizeof(data)); 85 if (ret) 86 goto err; 87 88 ret = platform_device_add(pdev); 89 if (ret) 90 goto err; 91 92 dpaa_eth_dev_cnt++; 93 mutex_unlock(ð_lock); 94 95 return pdev; 96 97 err: 98 platform_device_put(pdev); 99 no_mem: 100 mutex_unlock(ð_lock); 101 102 return ERR_PTR(ret); 103 } 104 105 static const struct of_device_id mac_match[] = { 106 { .compatible = "fsl,fman-dtsec", .data = dtsec_initialization }, 107 { .compatible = "fsl,fman-xgec", .data = tgec_initialization }, 108 { .compatible = "fsl,fman-memac", .data = memac_initialization }, 109 {} 110 }; 111 MODULE_DEVICE_TABLE(of, mac_match); 112 113 static int mac_probe(struct platform_device *_of_dev) 114 { 115 int err, i, nph; 116 int (*init)(struct mac_device *mac_dev, struct device_node *mac_node, 117 struct fman_mac_params *params); 118 struct device *dev; 119 struct device_node *mac_node, *dev_node; 120 struct mac_device *mac_dev; 121 struct platform_device *of_dev; 122 struct mac_priv_s *priv; 123 struct fman_mac_params params; 124 u32 val; 125 u8 fman_id; 126 phy_interface_t phy_if; 127 128 dev = &_of_dev->dev; 129 mac_node = dev->of_node; 130 init = of_device_get_match_data(dev); 131 132 mac_dev = devm_kzalloc(dev, sizeof(*mac_dev), GFP_KERNEL); 133 if (!mac_dev) 134 return -ENOMEM; 135 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 136 if (!priv) 137 return -ENOMEM; 138 platform_set_drvdata(_of_dev, mac_dev); 139 140 /* Save private information */ 141 mac_dev->priv = priv; 142 mac_dev->dev = dev; 143 144 /* Get the FM node */ 145 dev_node = of_get_parent(mac_node); 146 if (!dev_node) { 147 dev_err(dev, "of_get_parent(%pOF) failed\n", 148 mac_node); 149 return -EINVAL; 150 } 151 152 of_dev = of_find_device_by_node(dev_node); 153 if (!of_dev) { 154 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", dev_node); 155 err = -EINVAL; 156 goto _return_of_node_put; 157 } 158 159 /* Get the FMan cell-index */ 160 err = of_property_read_u32(dev_node, "cell-index", &val); 161 if (err) { 162 dev_err(dev, "failed to read cell-index for %pOF\n", dev_node); 163 err = -EINVAL; 164 goto _return_of_node_put; 165 } 166 /* cell-index 0 => FMan id 1 */ 167 fman_id = (u8)(val + 1); 168 169 priv->fman = fman_bind(&of_dev->dev); 170 if (!priv->fman) { 171 dev_err(dev, "fman_bind(%pOF) failed\n", dev_node); 172 err = -ENODEV; 173 goto _return_of_node_put; 174 } 175 176 of_node_put(dev_node); 177 178 /* Get the address of the memory mapped registers */ 179 mac_dev->res = platform_get_mem_or_io(_of_dev, 0); 180 if (!mac_dev->res) { 181 dev_err(dev, "could not get registers\n"); 182 return -EINVAL; 183 } 184 185 err = devm_request_resource(dev, fman_get_mem_region(priv->fman), 186 mac_dev->res); 187 if (err) { 188 dev_err_probe(dev, err, "could not request resource\n"); 189 return err; 190 } 191 192 mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start, 193 resource_size(mac_dev->res)); 194 if (!mac_dev->vaddr) { 195 dev_err(dev, "devm_ioremap() failed\n"); 196 return -EIO; 197 } 198 199 if (!of_device_is_available(mac_node)) 200 return -ENODEV; 201 202 /* Get the cell-index */ 203 err = of_property_read_u32(mac_node, "cell-index", &val); 204 if (err) { 205 dev_err(dev, "failed to read cell-index for %pOF\n", mac_node); 206 return -EINVAL; 207 } 208 priv->cell_index = (u8)val; 209 210 /* Get the MAC address */ 211 err = of_get_mac_address(mac_node, mac_dev->addr); 212 if (err) 213 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node); 214 215 /* Get the port handles */ 216 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); 217 if (unlikely(nph < 0)) { 218 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n", 219 mac_node); 220 return nph; 221 } 222 223 if (nph != ARRAY_SIZE(mac_dev->port)) { 224 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n", 225 mac_node); 226 return -EINVAL; 227 } 228 229 for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) { 230 /* Find the port node */ 231 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i); 232 if (!dev_node) { 233 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n", 234 mac_node); 235 return -EINVAL; 236 } 237 238 of_dev = of_find_device_by_node(dev_node); 239 if (!of_dev) { 240 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", 241 dev_node); 242 err = -EINVAL; 243 goto _return_of_node_put; 244 } 245 246 mac_dev->port[i] = fman_port_bind(&of_dev->dev); 247 if (!mac_dev->port[i]) { 248 dev_err(dev, "dev_get_drvdata(%pOF) failed\n", 249 dev_node); 250 err = -EINVAL; 251 goto _return_of_node_put; 252 } 253 of_node_put(dev_node); 254 } 255 256 /* Get the PHY connection type */ 257 err = of_get_phy_mode(mac_node, &phy_if); 258 if (err) { 259 dev_warn(dev, 260 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n", 261 mac_node); 262 phy_if = PHY_INTERFACE_MODE_SGMII; 263 } 264 mac_dev->phy_if = phy_if; 265 266 params.mac_id = priv->cell_index; 267 params.fm = (void *)priv->fman; 268 params.exception_cb = mac_exception; 269 params.event_cb = mac_exception; 270 271 err = init(mac_dev, mac_node, ¶ms); 272 if (err < 0) 273 return err; 274 275 if (!is_zero_ether_addr(mac_dev->addr)) 276 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); 277 278 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); 279 if (IS_ERR(priv->eth_dev)) { 280 err = PTR_ERR(priv->eth_dev); 281 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", 282 priv->cell_index); 283 priv->eth_dev = NULL; 284 } 285 286 return err; 287 288 _return_of_node_put: 289 of_node_put(dev_node); 290 return err; 291 } 292 293 static void mac_remove(struct platform_device *pdev) 294 { 295 struct mac_device *mac_dev = platform_get_drvdata(pdev); 296 297 platform_device_unregister(mac_dev->priv->eth_dev); 298 } 299 300 static struct platform_driver mac_driver = { 301 .driver = { 302 .name = KBUILD_MODNAME, 303 .of_match_table = mac_match, 304 }, 305 .probe = mac_probe, 306 .remove = mac_remove, 307 }; 308 309 builtin_platform_driver(mac_driver); 310