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 priv->cell_index = (u8)val; 221 222 /* Get the MAC address */ 223 err = of_get_mac_address(mac_node, mac_dev->addr); 224 if (err) 225 dev_warn(dev, "of_get_mac_address(%pOF) failed\n", mac_node); 226 227 /* Get the port handles */ 228 nph = of_count_phandle_with_args(mac_node, "fsl,fman-ports", NULL); 229 if (unlikely(nph < 0)) { 230 dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n", 231 mac_node); 232 err = nph; 233 goto _return_dev_put; 234 } 235 236 if (nph != ARRAY_SIZE(mac_dev->port)) { 237 dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n", 238 mac_node); 239 err = -EINVAL; 240 goto _return_dev_put; 241 } 242 243 /* PORT_NUM determines the size of the port array */ 244 for (i = 0; i < PORT_NUM; i++) { 245 /* Find the port node */ 246 dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i); 247 if (!dev_node) { 248 dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n", 249 mac_node); 250 err = -EINVAL; 251 goto _return_dev_arr_put; 252 } 253 254 of_dev = of_find_device_by_node(dev_node); 255 if (!of_dev) { 256 dev_err(dev, "of_find_device_by_node(%pOF) failed\n", 257 dev_node); 258 err = -EINVAL; 259 goto _return_dev_arr_put; 260 } 261 mac_dev->fman_port_devs[i] = &of_dev->dev; 262 263 mac_dev->port[i] = fman_port_bind(mac_dev->fman_port_devs[i]); 264 if (!mac_dev->port[i]) { 265 dev_err(dev, "dev_get_drvdata(%pOF) failed\n", 266 dev_node); 267 err = -EINVAL; 268 goto _return_dev_arr_put; 269 } 270 /* Two references have been taken in of_find_device_by_node() 271 * and fman_port_bind(). Release one of them here. The second 272 * one will be released in mac_remove(). 273 */ 274 put_device(mac_dev->fman_port_devs[i]); 275 of_node_put(dev_node); 276 dev_node = NULL; 277 } 278 279 /* Get the PHY connection type */ 280 err = of_get_phy_mode(mac_node, &phy_if); 281 if (err) { 282 dev_warn(dev, 283 "of_get_phy_mode() for %pOF failed. Defaulting to SGMII\n", 284 mac_node); 285 phy_if = PHY_INTERFACE_MODE_SGMII; 286 } 287 mac_dev->phy_if = phy_if; 288 289 params.mac_id = priv->cell_index; 290 params.fm = (void *)priv->fman; 291 params.exception_cb = mac_exception; 292 params.event_cb = mac_exception; 293 294 err = init(mac_dev, mac_node, ¶ms); 295 if (err < 0) 296 goto _return_dev_arr_put; 297 298 if (!is_zero_ether_addr(mac_dev->addr)) 299 dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr); 300 301 priv->eth_dev = dpaa_eth_add_device(fman_id, mac_dev); 302 if (IS_ERR(priv->eth_dev)) { 303 err = PTR_ERR(priv->eth_dev); 304 dev_err(dev, "failed to add Ethernet platform device for MAC %d\n", 305 priv->cell_index); 306 priv->eth_dev = NULL; 307 } 308 309 return err; 310 311 _return_dev_arr_put: 312 /* mac_dev is kzalloc'ed */ 313 for (i = 0; i < PORT_NUM; i++) 314 put_device(mac_dev->fman_port_devs[i]); 315 _return_dev_put: 316 put_device(mac_dev->fman_dev); 317 _return_of_node_put: 318 of_node_put(dev_node); 319 return err; 320 } 321 322 static void mac_remove(struct platform_device *pdev) 323 { 324 struct mac_device *mac_dev = platform_get_drvdata(pdev); 325 int i; 326 327 for (i = 0; i < PORT_NUM; i++) 328 put_device(mac_dev->fman_port_devs[i]); 329 put_device(mac_dev->fman_dev); 330 331 platform_device_unregister(mac_dev->priv->eth_dev); 332 } 333 334 static struct platform_driver mac_driver = { 335 .driver = { 336 .name = KBUILD_MODNAME, 337 .of_match_table = mac_match, 338 }, 339 .probe = mac_probe, 340 .remove = mac_remove, 341 }; 342 343 builtin_platform_driver(mac_driver); 344