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 mac_dev->fman_dev = &of_dev->dev; 159 160 /* Get the FMan cell-index */ 161 err = of_property_read_u32(dev_node, "cell-index", &val); 162 if (err) { 163 dev_err(dev, "failed to read cell-index for %pOF\n", dev_node); 164 err = -EINVAL; 165 goto _return_dev_put; 166 } 167 /* cell-index 0 => FMan id 1 */ 168 fman_id = (u8)(val + 1); 169 170 priv->fman = fman_bind(mac_dev->fman_dev); 171 if (!priv->fman) { 172 dev_err(dev, "fman_bind(%pOF) failed\n", dev_node); 173 err = -ENODEV; 174 goto _return_dev_put; 175 } 176 177 /* Two references have been taken in of_find_device_by_node() 178 * and fman_bind(). Release one of them here. The second one 179 * will be released in mac_remove(). 180 */ 181 put_device(mac_dev->fman_dev); 182 of_node_put(dev_node); 183 dev_node = NULL; 184 185 /* Get the address of the memory mapped registers */ 186 mac_dev->res = platform_get_mem_or_io(_of_dev, 0); 187 if (!mac_dev->res) { 188 dev_err(dev, "could not get registers\n"); 189 err = -EINVAL; 190 goto _return_dev_put; 191 } 192 193 err = devm_request_resource(dev, fman_get_mem_region(priv->fman), 194 mac_dev->res); 195 if (err) { 196 dev_err_probe(dev, err, "could not request resource\n"); 197 goto _return_dev_put; 198 } 199 200 mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start, 201 resource_size(mac_dev->res)); 202 if (!mac_dev->vaddr) { 203 dev_err(dev, "devm_ioremap() failed\n"); 204 err = -EIO; 205 goto _return_dev_put; 206 } 207 208 if (!of_device_is_available(mac_node)) { 209 err = -ENODEV; 210 goto _return_dev_put; 211 } 212 213 /* Get the cell-index */ 214 err = of_property_read_u32(mac_node, "cell-index", &val); 215 if (err) { 216 dev_err(dev, "failed to read cell-index for %pOF\n", mac_node); 217 err = -EINVAL; 218 goto _return_dev_put; 219 } 220 if (val >= MAX_NUM_OF_MACS) { 221 dev_err(dev, "cell-index value is too big for %pOF\n", mac_node); 222 err = -EINVAL; 223 goto _return_dev_put; 224 } 225 priv->cell_index = (u8)val; 226 227 /* Get the MAC address */ 228 err = of_get_mac_address(mac_node, mac_dev->addr); 229 if (err) 230 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node); 231 232 /* Get the port handles */ 233 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); 234 if (unlikely(nph < 0)) { 235 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n", 236 mac_node); 237 err = nph; 238 goto _return_dev_put; 239 } 240 241 if (nph != ARRAY_SIZE(mac_dev->port)) { 242 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n", 243 mac_node); 244 err = -EINVAL; 245 goto _return_dev_put; 246 } 247 248 /* PORT_NUM determines the size of the port array */ 249 for (i = 0; i < PORT_NUM; i++) { 250 /* Find the port node */ 251 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i); 252 if (!dev_node) { 253 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n", 254 mac_node); 255 err = -EINVAL; 256 goto _return_dev_arr_put; 257 } 258 259 of_dev = of_find_device_by_node(dev_node); 260 if (!of_dev) { 261 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", 262 dev_node); 263 err = -EINVAL; 264 goto _return_dev_arr_put; 265 } 266 mac_dev->fman_port_devs[i] = &of_dev->dev; 267 268 mac_dev->port[i] = fman_port_bind(mac_dev->fman_port_devs[i]); 269 if (!mac_dev->port[i]) { 270 dev_err(dev, "dev_get_drvdata(%pOF) failed\n", 271 dev_node); 272 err = -EINVAL; 273 goto _return_dev_arr_put; 274 } 275 /* Two references have been taken in of_find_device_by_node() 276 * and fman_port_bind(). Release one of them here. The second 277 * one will be released in mac_remove(). 278 */ 279 put_device(mac_dev->fman_port_devs[i]); 280 of_node_put(dev_node); 281 dev_node = NULL; 282 } 283 284 /* Get the PHY connection type */ 285 err = of_get_phy_mode(mac_node, &phy_if); 286 if (err) { 287 dev_warn(dev, 288 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n", 289 mac_node); 290 phy_if = PHY_INTERFACE_MODE_SGMII; 291 } 292 mac_dev->phy_if = phy_if; 293 294 params.mac_id = priv->cell_index; 295 params.fm = (void *)priv->fman; 296 params.exception_cb = mac_exception; 297 params.event_cb = mac_exception; 298 299 err = init(mac_dev, mac_node, ¶ms); 300 if (err < 0) 301 goto _return_dev_arr_put; 302 303 if (!is_zero_ether_addr(mac_dev->addr)) 304 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); 305 306 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); 307 if (IS_ERR(priv->eth_dev)) { 308 err = PTR_ERR(priv->eth_dev); 309 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", 310 priv->cell_index); 311 priv->eth_dev = NULL; 312 } 313 314 return err; 315 316 _return_dev_arr_put: 317 /* mac_dev is kzalloc'ed */ 318 for (i = 0; i < PORT_NUM; i++) 319 put_device(mac_dev->fman_port_devs[i]); 320 _return_dev_put: 321 put_device(mac_dev->fman_dev); 322 _return_of_node_put: 323 of_node_put(dev_node); 324 return err; 325 } 326 327 static void mac_remove(struct platform_device *pdev) 328 { 329 struct mac_device *mac_dev = platform_get_drvdata(pdev); 330 int i; 331 332 for (i = 0; i < PORT_NUM; i++) 333 put_device(mac_dev->fman_port_devs[i]); 334 put_device(mac_dev->fman_dev); 335 336 platform_device_unregister(mac_dev->priv->eth_dev); 337 } 338 339 static struct platform_driver mac_driver = { 340 .driver = { 341 .name = KBUILD_MODNAME, 342 .of_match_table = mac_match, 343 }, 344 .probe = mac_probe, 345 .remove = mac_remove, 346 }; 347 348 builtin_platform_driver(mac_driver); 349