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