aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2011-06-24 14:04:35 -0400
committerShawn Guo <shawn.guo@linaro.org>2011-07-26 21:31:08 -0400
commitca2cc333920690db87a03c2ee3bd6f43adb3e7fb (patch)
treed8a01ac861b42adbc160021f0343f4226fd01883
parent4157ef1b8779b34581ee8b9dc8f7f95188008eca (diff)
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>
-rw-r--r--Documentation/devicetree/bindings/net/fsl-fec.txt24
-rw-r--r--drivers/net/fec.c103
2 files changed, 122 insertions, 5 deletions
diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt b/Documentation/devicetree/bindings/net/fsl-fec.txt
new file mode 100644
index 000000000000..de439517dff0
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -0,0 +1,24 @@
1* Freescale Fast Ethernet Controller (FEC)
2
3Required 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
12Optional properties:
13- local-mac-address : 6 bytes, mac address
14
15Example:
16
17fec@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};
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index ed137bbbcf61..e8266ccf818a 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -44,6 +44,10 @@
44#include <linux/platform_device.h> 44#include <linux/platform_device.h>
45#include <linux/phy.h> 45#include <linux/phy.h>
46#include <linux/fec.h> 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#include <asm/cacheflush.h> 52#include <asm/cacheflush.h>
49 53
@@ -89,6 +93,20 @@ static struct platform_device_id fec_devtype[] = {
89}; 93};
90MODULE_DEVICE_TABLE(platform, fec_devtype); 94MODULE_DEVICE_TABLE(platform, fec_devtype);
91 95
96enum imx_fec_type {
97 IMX25_FEC = 1, /* runs on i.mx25/50/53 */
98 IMX27_FEC, /* runs on i.mx27/35/51 */
99 IMX28_FEC,
100};
101
102static const struct of_device_id fec_dt_ids[] = {
103 { .compatible = "fsl,imx25-fec", .data = &fec_devtype[IMX25_FEC], },
104 { .compatible = "fsl,imx27-fec", .data = &fec_devtype[IMX27_FEC], },
105 { .compatible = "fsl,imx28-fec", .data = &fec_devtype[IMX28_FEC], },
106 { /* sentinel */ }
107};
108MODULE_DEVICE_TABLE(of, fec_dt_ids);
109
92static unsigned char macaddr[ETH_ALEN]; 110static unsigned char macaddr[ETH_ALEN];
93module_param_array(macaddr, byte, NULL, 0); 111module_param_array(macaddr, byte, NULL, 0);
94MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address"); 112MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");
@@ -748,8 +766,22 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
748 */ 766 */
749 iap = macaddr; 767 iap = macaddr;
750 768
769#ifdef CONFIG_OF
770 /*
771 * 2) from device tree data
772 */
773 if (!is_valid_ether_addr(iap)) {
774 struct device_node *np = fep->pdev->dev.of_node;
775 if (np) {
776 const char *mac = of_get_mac_address(np);
777 if (mac)
778 iap = (unsigned char *) mac;
779 }
780 }
781#endif
782
751 /* 783 /*
752 * 2) from flash or fuse (via platform data) 784 * 3) from flash or fuse (via platform data)
753 */ 785 */
754 if (!is_valid_ether_addr(iap)) { 786 if (!is_valid_ether_addr(iap)) {
755#ifdef CONFIG_M5272 787#ifdef CONFIG_M5272
@@ -762,7 +794,7 @@ static void __inline__ fec_get_mac(struct net_device *ndev)
762 } 794 }
763 795
764 /* 796 /*
765 * 3) FEC mac registers set by bootloader 797 * 4) FEC mac registers set by bootloader
766 */ 798 */
767 if (!is_valid_ether_addr(iap)) { 799 if (!is_valid_ether_addr(iap)) {
768 *((unsigned long *) &tmpaddr[0]) = 800 *((unsigned long *) &tmpaddr[0]) =
@@ -1368,6 +1400,52 @@ static int fec_enet_init(struct net_device *ndev)
1368 return 0; 1400 return 0;
1369} 1401}
1370 1402
1403#ifdef CONFIG_OF
1404static int __devinit fec_get_phy_mode_dt(struct platform_device *pdev)
1405{
1406 struct device_node *np = pdev->dev.of_node;
1407
1408 if (np)
1409 return of_get_phy_mode(np);
1410
1411 return -ENODEV;
1412}
1413
1414static int __devinit fec_reset_phy(struct platform_device *pdev)
1415{
1416 int err, phy_reset;
1417 struct device_node *np = pdev->dev.of_node;
1418
1419 if (!np)
1420 return -ENODEV;
1421
1422 phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
1423 err = gpio_request_one(phy_reset, GPIOF_OUT_INIT_LOW, "phy-reset");
1424 if (err) {
1425 pr_warn("FEC: failed to get gpio phy-reset: %d\n", err);
1426 return err;
1427 }
1428 msleep(1);
1429 gpio_set_value(phy_reset, 1);
1430
1431 return 0;
1432}
1433#else /* CONFIG_OF */
1434static inline int fec_get_phy_mode_dt(struct platform_device *pdev)
1435{
1436 return -ENODEV;
1437}
1438
1439static inline int fec_reset_phy(struct platform_device *pdev)
1440{
1441 /*
1442 * In case of platform probe, the reset has been done
1443 * by machine code.
1444 */
1445 return 0;
1446}
1447#endif /* CONFIG_OF */
1448
1371static int __devinit 1449static int __devinit
1372fec_probe(struct platform_device *pdev) 1450fec_probe(struct platform_device *pdev)
1373{ 1451{
@@ -1376,6 +1454,11 @@ fec_probe(struct platform_device *pdev)
1376 struct net_device *ndev; 1454 struct net_device *ndev;
1377 int i, irq, ret = 0; 1455 int i, irq, ret = 0;
1378 struct resource *r; 1456 struct resource *r;
1457 const struct of_device_id *of_id;
1458
1459 of_id = of_match_device(fec_dt_ids, &pdev->dev);
1460 if (of_id)
1461 pdev->id_entry = of_id->data;
1379 1462
1380 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 1463 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1381 if (!r) 1464 if (!r)
@@ -1407,9 +1490,18 @@ fec_probe(struct platform_device *pdev)
1407 1490
1408 platform_set_drvdata(pdev, ndev); 1491 platform_set_drvdata(pdev, ndev);
1409 1492
1410 pdata = pdev->dev.platform_data; 1493 ret = fec_get_phy_mode_dt(pdev);
1411 if (pdata) 1494 if (ret < 0) {
1412 fep->phy_interface = pdata->phy; 1495 pdata = pdev->dev.platform_data;
1496 if (pdata)
1497 fep->phy_interface = pdata->phy;
1498 else
1499 fep->phy_interface = PHY_INTERFACE_MODE_MII;
1500 } else {
1501 fep->phy_interface = ret;
1502 }
1503
1504 fec_reset_phy(pdev);
1413 1505
1414 /* This device has up to three irqs on some platforms */ 1506 /* This device has up to three irqs on some platforms */
1415 for (i = 0; i < 3; i++) { 1507 for (i = 0; i < 3; i++) {
@@ -1544,6 +1636,7 @@ static struct platform_driver fec_driver = {
1544#ifdef CONFIG_PM 1636#ifdef CONFIG_PM
1545 .pm = &fec_pm_ops, 1637 .pm = &fec_pm_ops,
1546#endif 1638#endif
1639 .of_match_table = fec_dt_ids,
1547 }, 1640 },
1548 .id_table = fec_devtype, 1641 .id_table = fec_devtype,
1549 .probe = fec_probe, 1642 .probe = fec_probe,