aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Hesselbarth <sebastian.hesselbarth@gmail.com>2013-10-07 16:25:11 -0400
committerJason Cooper <jason@lakedaemon.net>2013-10-08 12:59:21 -0400
commitebd7d3ab50f960e780e7c825a42b5cb6e21ee376 (patch)
treebc397ae5e8ba5095fef1b2ae5a8c9b8fd7249a75
parent3839c08d3ae44cf39b26eecefdae07f7b2443e7e (diff)
ARM: kirkwood: retain MAC address for DT ethernet
Ethernet IP on Kirkwood SoCs loose their MAC address register content if clock gated. To allow modular ethernet driver setups and gated clocks also on non-DT capable bootloaders, we fixup port device nodes with no valid MAC address property. This patch copies MAC address register contents set up by bootloaders early, notably before ethernet clocks are gated. While at it, also reorder call sequence in _dt_init. Signed-off-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Reviewed-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Reviewed-by: Ezequiel Garcia <ezequiel.garcia@free-electrons.com> Reviewed-by: Mike Turquette <mturquette@linaro.org> Tested-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Jason Cooper <jason@lakedaemon.net>
-rw-r--r--arch/arm/mach-kirkwood/board-dt.c85
1 files changed, 83 insertions, 2 deletions
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index d8b666c39fd1..27c1877e6dda 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -13,6 +13,8 @@
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/of.h> 15#include <linux/of.h>
16#include <linux/of_address.h>
17#include <linux/of_net.h>
16#include <linux/of_platform.h> 18#include <linux/of_platform.h>
17#include <linux/clk-provider.h> 19#include <linux/clk-provider.h>
18#include <linux/clocksource.h> 20#include <linux/clocksource.h>
@@ -58,6 +60,85 @@ static void __init kirkwood_legacy_clk_init(void)
58 clk_prepare_enable(clk); 60 clk_prepare_enable(clk);
59} 61}
60 62
63#define MV643XX_ETH_MAC_ADDR_LOW 0x0414
64#define MV643XX_ETH_MAC_ADDR_HIGH 0x0418
65
66static void __init kirkwood_dt_eth_fixup(void)
67{
68 struct device_node *np;
69
70 /*
71 * The ethernet interfaces forget the MAC address assigned by u-boot
72 * if the clocks are turned off. Usually, u-boot on kirkwood boards
73 * has no DT support to properly set local-mac-address property.
74 * As a workaround, we get the MAC address from mv643xx_eth registers
75 * and update the port device node if no valid MAC address is set.
76 */
77 for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
78 struct device_node *pnp = of_get_parent(np);
79 struct clk *clk;
80 struct property *pmac;
81 void __iomem *io;
82 u8 *macaddr;
83 u32 reg;
84
85 if (!pnp)
86 continue;
87
88 /* skip disabled nodes or nodes with valid MAC address*/
89 if (!of_device_is_available(pnp) || of_get_mac_address(np))
90 goto eth_fixup_skip;
91
92 clk = of_clk_get(pnp, 0);
93 if (IS_ERR(clk))
94 goto eth_fixup_skip;
95
96 io = of_iomap(pnp, 0);
97 if (!io)
98 goto eth_fixup_no_map;
99
100 /* ensure port clock is not gated to not hang CPU */
101 clk_prepare_enable(clk);
102
103 /* store MAC address register contents in local-mac-address */
104 pr_err(FW_INFO "%s: local-mac-address is not set\n",
105 np->full_name);
106
107 pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
108 if (!pmac)
109 goto eth_fixup_no_mem;
110
111 pmac->value = pmac + 1;
112 pmac->length = 6;
113 pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
114 if (!pmac->name) {
115 kfree(pmac);
116 goto eth_fixup_no_mem;
117 }
118
119 macaddr = pmac->value;
120 reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
121 macaddr[0] = (reg >> 24) & 0xff;
122 macaddr[1] = (reg >> 16) & 0xff;
123 macaddr[2] = (reg >> 8) & 0xff;
124 macaddr[3] = reg & 0xff;
125
126 reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
127 macaddr[4] = (reg >> 8) & 0xff;
128 macaddr[5] = reg & 0xff;
129
130 of_update_property(np, pmac);
131
132eth_fixup_no_mem:
133 iounmap(io);
134 clk_disable_unprepare(clk);
135eth_fixup_no_map:
136 clk_put(clk);
137eth_fixup_skip:
138 of_node_put(pnp);
139 }
140}
141
61static void __init kirkwood_dt_time_init(void) 142static void __init kirkwood_dt_time_init(void)
62{ 143{
63 of_clk_init(NULL); 144 of_clk_init(NULL);
@@ -82,12 +163,12 @@ static void __init kirkwood_dt_init(void)
82 kirkwood_l2_init(); 163 kirkwood_l2_init();
83 164
84 kirkwood_cpufreq_init(); 165 kirkwood_cpufreq_init();
85 166 kirkwood_cpuidle_init();
86 /* Setup clocks for legacy devices */ 167 /* Setup clocks for legacy devices */
87 kirkwood_legacy_clk_init(); 168 kirkwood_legacy_clk_init();
88 169
89 kirkwood_pm_init(); 170 kirkwood_pm_init();
90 kirkwood_cpuidle_init(); 171 kirkwood_dt_eth_fixup();
91 172
92#ifdef CONFIG_KEXEC 173#ifdef CONFIG_KEXEC
93 kexec_reinit = kirkwood_enable_pcie; 174 kexec_reinit = kirkwood_enable_pcie;