Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net/fec: add device tree probe support

It adds device tree probe support for fec driver.

Signed-off-by: Jason Liu <jason.hui@linaro.org>
Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
Cc: David S. Miller <davem@davemloft.net>
Cc: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: David S. Miller <davem@davemloft.net>

Shawn Guo ca2cc333 4157ef1b

+122 -5
+24
Documentation/devicetree/bindings/net/fsl-fec.txt
··· 1 + * Freescale Fast Ethernet Controller (FEC) 2 + 3 + Required properties: 4 + - compatible : Should be "fsl,<soc>-fec" 5 + - reg : Address and length of the register set for the device 6 + - interrupts : Should contain fec interrupt 7 + - phy-mode : String, operation mode of the PHY interface. 8 + Supported values are: "mii", "gmii", "sgmii", "tbi", "rmii", 9 + "rgmii", "rgmii-id", "rgmii-rxid", "rgmii-txid", "rtbi", "smii". 10 + - phy-reset-gpios : Should specify the gpio for phy reset 11 + 12 + Optional properties: 13 + - local-mac-address : 6 bytes, mac address 14 + 15 + Example: 16 + 17 + fec@83fec000 { 18 + compatible = "fsl,imx51-fec", "fsl,imx27-fec"; 19 + reg = <0x83fec000 0x4000>; 20 + interrupts = <87>; 21 + phy-mode = "mii"; 22 + phy-reset-gpios = <&gpio1 14 0>; /* GPIO2_14 */ 23 + local-mac-address = [00 04 9F 01 1B B9]; 24 + };
+98 -5
drivers/net/fec.c
··· 44 44 #include <linux/platform_device.h> 45 45 #include <linux/phy.h> 46 46 #include <linux/fec.h> 47 + #include <linux/of.h> 48 + #include <linux/of_device.h> 49 + #include <linux/of_gpio.h> 50 + #include <linux/of_net.h> 47 51 48 52 #include <asm/cacheflush.h> 49 53 ··· 92 88 } 93 89 }; 94 90 MODULE_DEVICE_TABLE(platform, fec_devtype); 91 + 92 + enum imx_fec_type { 93 + IMX25_FEC = 1, /* runs on i.mx25/50/53 */ 94 + IMX27_FEC, /* runs on i.mx27/35/51 */ 95 + IMX28_FEC, 96 + }; 97 + 98 + static const struct of_device_id fec_dt_ids[] = { 99 + { .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], }, 100 + { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], }, 101 + { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], }, 102 + { /* sentinel */ } 103 + }; 104 + MODULE_DEVICE_TABLE(of, fec_dt_ids); 95 105 96 106 static unsigned char macaddr[ETH_ALEN]; 97 107 module_param_array(macaddr, byte, NULL, 0); ··· 766 748 */ 767 749 iap = macaddr; 768 750 751 + #ifdef CONFIG_OF 769 752 /* 770 - * 2) from flash or fuse (via platform data) 753 + * 2) from device tree data 754 + */ 755 + if (!is_valid_ether_addr(iap)) { 756 + struct device_node *np = fep->pdev->dev.of_node; 757 + if (np) { 758 + const char *mac = of_get_mac_address(np); 759 + if (mac) 760 + iap = (unsigned char *) mac; 761 + } 762 + } 763 + #endif 764 + 765 + /* 766 + * 3) from flash or fuse (via platform data) 771 767 */ 772 768 if (!is_valid_ether_addr(iap)) { 773 769 #ifdef CONFIG_M5272 ··· 794 762 } 795 763 796 764 /* 797 - * 3) FEC mac registers set by bootloader 765 + * 4) FEC mac registers set by bootloader 798 766 */ 799 767 if (!is_valid_ether_addr(iap)) { 800 768 *((unsigned long *) &tmpaddr[0]) = ··· 1400 1368 return 0; 1401 1369 } 1402 1370 1371 + #ifdef CONFIG_OF 1372 + static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev) 1373 + { 1374 + struct device_node *np = pdev->dev.of_node; 1375 + 1376 + if (np) 1377 + return of_get_phy_mode(np); 1378 + 1379 + return -ENODEV; 1380 + } 1381 + 1382 + static int __devinit fec_reset_phy(struct platform_device *pdev) 1383 + { 1384 + int err, phy_reset; 1385 + struct device_node *np = pdev->dev.of_node; 1386 + 1387 + if (!np) 1388 + return -ENODEV; 1389 + 1390 + phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0); 1391 + err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset"); 1392 + if (err) { 1393 + pr_warn("FEC: failed to get gpio phy-reset: %d\n", err); 1394 + return err; 1395 + } 1396 + msleep(1); 1397 + gpio_set_value(phy_reset, 1); 1398 + 1399 + return 0; 1400 + } 1401 + #else /* CONFIG_OF */ 1402 + static inline int fec_get_phy_mode_dt(struct platform_device *pdev) 1403 + { 1404 + return -ENODEV; 1405 + } 1406 + 1407 + static inline int fec_reset_phy(struct platform_device *pdev) 1408 + { 1409 + /* 1410 + * In case of platform probe, the reset has been done 1411 + * by machine code. 1412 + */ 1413 + return 0; 1414 + } 1415 + #endif /* CONFIG_OF */ 1416 + 1403 1417 static int __devinit 1404 1418 fec_probe(struct platform_device *pdev) 1405 1419 { ··· 1454 1376 struct net_device *ndev; 1455 1377 int i, irq, ret = 0; 1456 1378 struct resource *r; 1379 + const struct of_device_id *of_id; 1380 + 1381 + of_id = of_match_device(fec_dt_ids, &pdev->dev); 1382 + if (of_id) 1383 + pdev->id_entry = of_id->data; 1457 1384 1458 1385 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1459 1386 if (!r) ··· 1490 1407 1491 1408 platform_set_drvdata(pdev, ndev); 1492 1409 1493 - pdata = pdev->dev.platform_data; 1494 - if (pdata) 1495 - fep->phy_interface = pdata->phy; 1410 + ret = fec_get_phy_mode_dt(pdev); 1411 + if (ret < 0) { 1412 + pdata = pdev->dev.platform_data; 1413 + if (pdata) 1414 + fep->phy_interface = pdata->phy; 1415 + else 1416 + fep->phy_interface = PHY_INTERFACE_MODE_MII; 1417 + } else { 1418 + fep->phy_interface = ret; 1419 + } 1420 + 1421 + fec_reset_phy(pdev); 1496 1422 1497 1423 /* This device has up to three irqs on some platforms */ 1498 1424 for (i = 0; i < 3; i++) { ··· 1636 1544 #ifdef CONFIG_PM 1637 1545 .pm = &fec_pm_ops, 1638 1546 #endif 1547 + .of_match_table = fec_dt_ids, 1639 1548 }, 1640 1549 .id_table = fec_devtype, 1641 1550 .probe = fec_probe,