Merge remote-tracking branches 'asoc/fix/atmel', 'asoc/fix/fsl', 'asoc/fix/tegra...
[linux-drm-fsl-dcu.git] / arch / arm / mach-kirkwood / board-dt.c
1 /*
2  * Copyright 2012 (C), Jason Cooper <jason@lakedaemon.net>
3  *
4  * arch/arm/mach-kirkwood/board-dt.c
5  *
6  * Flattened Device Tree board initialization
7  *
8  * This file is licensed under the terms of the GNU General Public
9  * License version 2.  This program is licensed "as is" without any
10  * warranty of any kind, whether express or implied.
11  */
12
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/of.h>
16 #include <linux/of_address.h>
17 #include <linux/of_net.h>
18 #include <linux/of_platform.h>
19 #include <linux/clk-provider.h>
20 #include <linux/dma-mapping.h>
21 #include <linux/irqchip.h>
22 #include <linux/kexec.h>
23 #include <asm/mach/arch.h>
24 #include <asm/mach/map.h>
25 #include <mach/bridge-regs.h>
26 #include <linux/platform_data/usb-ehci-orion.h>
27 #include <plat/irq.h>
28 #include <plat/common.h>
29 #include "common.h"
30
31 /*
32  * There are still devices that doesn't know about DT yet.  Get clock
33  * gates here and add a clock lookup alias, so that old platform
34  * devices still work.
35 */
36
37 static void __init kirkwood_legacy_clk_init(void)
38 {
39
40         struct device_node *np = of_find_compatible_node(
41                 NULL, NULL, "marvell,kirkwood-gating-clock");
42         struct of_phandle_args clkspec;
43         struct clk *clk;
44
45         clkspec.np = np;
46         clkspec.args_count = 1;
47
48         /*
49          * The ethernet interfaces forget the MAC address assigned by
50          * u-boot if the clocks are turned off. Until proper DT support
51          * is available we always enable them for now.
52          */
53         clkspec.args[0] = CGC_BIT_GE0;
54         clk = of_clk_get_from_provider(&clkspec);
55         clk_prepare_enable(clk);
56
57         clkspec.args[0] = CGC_BIT_GE1;
58         clk = of_clk_get_from_provider(&clkspec);
59         clk_prepare_enable(clk);
60 }
61
62 #define MV643XX_ETH_MAC_ADDR_LOW        0x0414
63 #define MV643XX_ETH_MAC_ADDR_HIGH       0x0418
64
65 static void __init kirkwood_dt_eth_fixup(void)
66 {
67         struct device_node *np;
68
69         /*
70          * The ethernet interfaces forget the MAC address assigned by u-boot
71          * if the clocks are turned off. Usually, u-boot on kirkwood boards
72          * has no DT support to properly set local-mac-address property.
73          * As a workaround, we get the MAC address from mv643xx_eth registers
74          * and update the port device node if no valid MAC address is set.
75          */
76         for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
77                 struct device_node *pnp = of_get_parent(np);
78                 struct clk *clk;
79                 struct property *pmac;
80                 void __iomem *io;
81                 u8 *macaddr;
82                 u32 reg;
83
84                 if (!pnp)
85                         continue;
86
87                 /* skip disabled nodes or nodes with valid MAC address*/
88                 if (!of_device_is_available(pnp) || of_get_mac_address(np))
89                         goto eth_fixup_skip;
90
91                 clk = of_clk_get(pnp, 0);
92                 if (IS_ERR(clk))
93                         goto eth_fixup_skip;
94
95                 io = of_iomap(pnp, 0);
96                 if (!io)
97                         goto eth_fixup_no_map;
98
99                 /* ensure port clock is not gated to not hang CPU */
100                 clk_prepare_enable(clk);
101
102                 /* store MAC address register contents in local-mac-address */
103                 pr_err(FW_INFO "%s: local-mac-address is not set\n",
104                        np->full_name);
105
106                 pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
107                 if (!pmac)
108                         goto eth_fixup_no_mem;
109
110                 pmac->value = pmac + 1;
111                 pmac->length = 6;
112                 pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
113                 if (!pmac->name) {
114                         kfree(pmac);
115                         goto eth_fixup_no_mem;
116                 }
117
118                 macaddr = pmac->value;
119                 reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
120                 macaddr[0] = (reg >> 24) & 0xff;
121                 macaddr[1] = (reg >> 16) & 0xff;
122                 macaddr[2] = (reg >> 8) & 0xff;
123                 macaddr[3] = reg & 0xff;
124
125                 reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
126                 macaddr[4] = (reg >> 8) & 0xff;
127                 macaddr[5] = reg & 0xff;
128
129                 of_update_property(np, pmac);
130
131 eth_fixup_no_mem:
132                 iounmap(io);
133                 clk_disable_unprepare(clk);
134 eth_fixup_no_map:
135                 clk_put(clk);
136 eth_fixup_skip:
137                 of_node_put(pnp);
138         }
139 }
140
141 static void __init kirkwood_dt_init(void)
142 {
143         pr_info("Kirkwood: %s, TCLK=%d.\n", kirkwood_id(), kirkwood_tclk);
144
145         /*
146          * Disable propagation of mbus errors to the CPU local bus,
147          * as this causes mbus errors (which can occur for example
148          * for PCI aborts) to throw CPU aborts, which we're not set
149          * up to deal with.
150          */
151         writel(readl(CPU_CONFIG) & ~CPU_CONFIG_ERROR_PROP, CPU_CONFIG);
152
153         BUG_ON(mvebu_mbus_dt_init());
154
155         kirkwood_l2_init();
156
157         kirkwood_cpufreq_init();
158         kirkwood_cpuidle_init();
159         /* Setup clocks for legacy devices */
160         kirkwood_legacy_clk_init();
161
162         kirkwood_pm_init();
163         kirkwood_dt_eth_fixup();
164
165 #ifdef CONFIG_KEXEC
166         kexec_reinit = kirkwood_enable_pcie;
167 #endif
168
169         if (of_machine_is_compatible("marvell,mv88f6281gtw-ge"))
170                 mv88f6281gtw_ge_init();
171
172         of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
173 }
174
175 static const char * const kirkwood_dt_board_compat[] = {
176         "marvell,kirkwood",
177         NULL
178 };
179
180 DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
181         /* Maintainer: Jason Cooper <jason@lakedaemon.net> */
182         .map_io         = kirkwood_map_io,
183         .init_machine   = kirkwood_dt_init,
184         .restart        = kirkwood_restart,
185         .dt_compat      = kirkwood_dt_board_compat,
186 MACHINE_END