diff options
author | Stefan Roese <sr@denx.de> | 2013-02-11 22:05:38 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-02-12 16:15:10 -0500 |
commit | db98f081888cbdd995c7c4cfd407781da35e33ba (patch) | |
tree | 21226907ec97affeb3c85c5433f34a823b34d61b | |
parent | af32de0ecda35e933848090bbab490174504c731 (diff) |
net: fec_mpc52xx: Read MAC address from device-tree
Until now, the MPC5200 FEC ethernet driver relied upon the bootloader
(U-Boot) to write the MAC address into the ethernet controller
registers. The Linux driver should not rely on such a thing. So
lets read the MAC address from the DT as it should be done here.
The following priority is now used to read the MAC address:
1) First, try OF node MAC address, if not present or invalid, then:
2) Read from MAC address registers, if invalid, then:
3) Log a warning message, and choose a random MAC address.
This fixes a problem with a MPC5200 board that uses the SPL U-Boot
version without FEC initialization before Linux booting for
boot speedup.
Additionally a status line is now be printed upon successful
driver probing, also displaying this MAC address.
Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Anatolij Gustschin <agust@denx.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/freescale/fec_mpc52xx.c | 62 |
1 files changed, 38 insertions, 24 deletions
diff --git a/drivers/net/ethernet/freescale/fec_mpc52xx.c b/drivers/net/ethernet/freescale/fec_mpc52xx.c index 817d081d2cd8..7f91b0c5c264 100644 --- a/drivers/net/ethernet/freescale/fec_mpc52xx.c +++ b/drivers/net/ethernet/freescale/fec_mpc52xx.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/of_device.h> | 30 | #include <linux/of_device.h> |
31 | #include <linux/of_mdio.h> | 31 | #include <linux/of_mdio.h> |
32 | #include <linux/of_net.h> | ||
32 | #include <linux/of_platform.h> | 33 | #include <linux/of_platform.h> |
33 | 34 | ||
34 | #include <linux/netdevice.h> | 35 | #include <linux/netdevice.h> |
@@ -76,10 +77,6 @@ static void mpc52xx_fec_stop(struct net_device *dev); | |||
76 | static void mpc52xx_fec_start(struct net_device *dev); | 77 | static void mpc52xx_fec_start(struct net_device *dev); |
77 | static void mpc52xx_fec_reset(struct net_device *dev); | 78 | static void mpc52xx_fec_reset(struct net_device *dev); |
78 | 79 | ||
79 | static u8 mpc52xx_fec_mac_addr[6]; | ||
80 | module_param_array_named(mac, mpc52xx_fec_mac_addr, byte, NULL, 0); | ||
81 | MODULE_PARM_DESC(mac, "six hex digits, ie. 0x1,0x2,0xc0,0x01,0xba,0xbe"); | ||
82 | |||
83 | #define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ | 80 | #define MPC52xx_MESSAGES_DEFAULT ( NETIF_MSG_DRV | NETIF_MSG_PROBE | \ |
84 | NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) | 81 | NETIF_MSG_LINK | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP) |
85 | static int debug = -1; /* the above default */ | 82 | static int debug = -1; /* the above default */ |
@@ -110,15 +107,6 @@ static void mpc52xx_fec_set_paddr(struct net_device *dev, u8 *mac) | |||
110 | out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); | 107 | out_be32(&fec->paddr2, (*(u16 *)(&mac[4]) << 16) | FEC_PADDR2_TYPE); |
111 | } | 108 | } |
112 | 109 | ||
113 | static void mpc52xx_fec_get_paddr(struct net_device *dev, u8 *mac) | ||
114 | { | ||
115 | struct mpc52xx_fec_priv *priv = netdev_priv(dev); | ||
116 | struct mpc52xx_fec __iomem *fec = priv->fec; | ||
117 | |||
118 | *(u32 *)(&mac[0]) = in_be32(&fec->paddr1); | ||
119 | *(u16 *)(&mac[4]) = in_be32(&fec->paddr2) >> 16; | ||
120 | } | ||
121 | |||
122 | static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) | 110 | static int mpc52xx_fec_set_mac_address(struct net_device *dev, void *addr) |
123 | { | 111 | { |
124 | struct sockaddr *sock = addr; | 112 | struct sockaddr *sock = addr; |
@@ -853,6 +841,8 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
853 | struct resource mem; | 841 | struct resource mem; |
854 | const u32 *prop; | 842 | const u32 *prop; |
855 | int prop_size; | 843 | int prop_size; |
844 | struct device_node *np = op->dev.of_node; | ||
845 | const char *mac_addr; | ||
856 | 846 | ||
857 | phys_addr_t rx_fifo; | 847 | phys_addr_t rx_fifo; |
858 | phys_addr_t tx_fifo; | 848 | phys_addr_t tx_fifo; |
@@ -866,7 +856,7 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
866 | priv->ndev = ndev; | 856 | priv->ndev = ndev; |
867 | 857 | ||
868 | /* Reserve FEC control zone */ | 858 | /* Reserve FEC control zone */ |
869 | rv = of_address_to_resource(op->dev.of_node, 0, &mem); | 859 | rv = of_address_to_resource(np, 0, &mem); |
870 | if (rv) { | 860 | if (rv) { |
871 | printk(KERN_ERR DRIVER_NAME ": " | 861 | printk(KERN_ERR DRIVER_NAME ": " |
872 | "Error while parsing device node resource\n" ); | 862 | "Error while parsing device node resource\n" ); |
@@ -919,7 +909,7 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
919 | 909 | ||
920 | /* Get the IRQ we need one by one */ | 910 | /* Get the IRQ we need one by one */ |
921 | /* Control */ | 911 | /* Control */ |
922 | ndev->irq = irq_of_parse_and_map(op->dev.of_node, 0); | 912 | ndev->irq = irq_of_parse_and_map(np, 0); |
923 | 913 | ||
924 | /* RX */ | 914 | /* RX */ |
925 | priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); | 915 | priv->r_irq = bcom_get_task_irq(priv->rx_dmatsk); |
@@ -927,11 +917,33 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
927 | /* TX */ | 917 | /* TX */ |
928 | priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); | 918 | priv->t_irq = bcom_get_task_irq(priv->tx_dmatsk); |
929 | 919 | ||
930 | /* MAC address init */ | 920 | /* |
931 | if (!is_zero_ether_addr(mpc52xx_fec_mac_addr)) | 921 | * MAC address init: |
932 | memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6); | 922 | * |
933 | else | 923 | * First try to read MAC address from DT |
934 | mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); | 924 | */ |
925 | mac_addr = of_get_mac_address(np); | ||
926 | if (mac_addr) { | ||
927 | memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); | ||
928 | } else { | ||
929 | struct mpc52xx_fec __iomem *fec = priv->fec; | ||
930 | |||
931 | /* | ||
932 | * If the MAC addresse is not provided via DT then read | ||
933 | * it back from the controller regs | ||
934 | */ | ||
935 | *(u32 *)(&ndev->dev_addr[0]) = in_be32(&fec->paddr1); | ||
936 | *(u16 *)(&ndev->dev_addr[4]) = in_be32(&fec->paddr2) >> 16; | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Check if the MAC address is valid, if not get a random one | ||
941 | */ | ||
942 | if (!is_valid_ether_addr(ndev->dev_addr)) { | ||
943 | eth_hw_addr_random(ndev); | ||
944 | dev_warn(&ndev->dev, "using random MAC address %pM\n", | ||
945 | ndev->dev_addr); | ||
946 | } | ||
935 | 947 | ||
936 | priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); | 948 | priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); |
937 | 949 | ||
@@ -942,20 +954,20 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
942 | /* Start with safe defaults for link connection */ | 954 | /* Start with safe defaults for link connection */ |
943 | priv->speed = 100; | 955 | priv->speed = 100; |
944 | priv->duplex = DUPLEX_HALF; | 956 | priv->duplex = DUPLEX_HALF; |
945 | priv->mdio_speed = ((mpc5xxx_get_bus_frequency(op->dev.of_node) >> 20) / 5) << 1; | 957 | priv->mdio_speed = ((mpc5xxx_get_bus_frequency(np) >> 20) / 5) << 1; |
946 | 958 | ||
947 | /* The current speed preconfigures the speed of the MII link */ | 959 | /* The current speed preconfigures the speed of the MII link */ |
948 | prop = of_get_property(op->dev.of_node, "current-speed", &prop_size); | 960 | prop = of_get_property(np, "current-speed", &prop_size); |
949 | if (prop && (prop_size >= sizeof(u32) * 2)) { | 961 | if (prop && (prop_size >= sizeof(u32) * 2)) { |
950 | priv->speed = prop[0]; | 962 | priv->speed = prop[0]; |
951 | priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; | 963 | priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; |
952 | } | 964 | } |
953 | 965 | ||
954 | /* If there is a phy handle, then get the PHY node */ | 966 | /* If there is a phy handle, then get the PHY node */ |
955 | priv->phy_node = of_parse_phandle(op->dev.of_node, "phy-handle", 0); | 967 | priv->phy_node = of_parse_phandle(np, "phy-handle", 0); |
956 | 968 | ||
957 | /* the 7-wire property means don't use MII mode */ | 969 | /* the 7-wire property means don't use MII mode */ |
958 | if (of_find_property(op->dev.of_node, "fsl,7-wire-mode", NULL)) { | 970 | if (of_find_property(np, "fsl,7-wire-mode", NULL)) { |
959 | priv->seven_wire_mode = 1; | 971 | priv->seven_wire_mode = 1; |
960 | dev_info(&ndev->dev, "using 7-wire PHY mode\n"); | 972 | dev_info(&ndev->dev, "using 7-wire PHY mode\n"); |
961 | } | 973 | } |
@@ -970,6 +982,8 @@ static int mpc52xx_fec_probe(struct platform_device *op) | |||
970 | 982 | ||
971 | /* We're done ! */ | 983 | /* We're done ! */ |
972 | dev_set_drvdata(&op->dev, ndev); | 984 | dev_set_drvdata(&op->dev, ndev); |
985 | printk(KERN_INFO "%s: %s MAC %pM\n", | ||
986 | ndev->name, op->dev.of_node->full_name, ndev->dev_addr); | ||
973 | 987 | ||
974 | return 0; | 988 | return 0; |
975 | 989 | ||