Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
  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/clk.h>
 14#include <linux/kernel.h>
 15#include <linux/init.h>
 16#include <linux/of.h>
 17#include <linux/of_address.h>
 18#include <linux/of_net.h>
 19#include <linux/of_platform.h>
 20#include <linux/dma-mapping.h>
 21#include <linux/irqchip.h>
 22#include <asm/hardware/cache-feroceon-l2.h>
 23#include <asm/mach/arch.h>
 24#include <asm/mach/map.h>
 25#include <mach/bridge-regs.h>
 26#include <plat/common.h>
 27#include <plat/pcie.h>
 28#include "pm.h"
 29
 30static struct map_desc kirkwood_io_desc[] __initdata = {
 31	{
 32		.virtual	= (unsigned long) KIRKWOOD_REGS_VIRT_BASE,
 33		.pfn		= __phys_to_pfn(KIRKWOOD_REGS_PHYS_BASE),
 34		.length		= KIRKWOOD_REGS_SIZE,
 35		.type		= MT_DEVICE,
 36	},
 37};
 38
 39static void __init kirkwood_map_io(void)
 40{
 41	iotable_init(kirkwood_io_desc, ARRAY_SIZE(kirkwood_io_desc));
 42}
 43
 44static struct resource kirkwood_cpufreq_resources[] = {
 45	[0] = {
 46		.start  = CPU_CONTROL_PHYS,
 47		.end    = CPU_CONTROL_PHYS + 3,
 48		.flags  = IORESOURCE_MEM,
 49	},
 50};
 51
 52static struct platform_device kirkwood_cpufreq_device = {
 53	.name		= "kirkwood-cpufreq",
 54	.id		= -1,
 55	.num_resources	= ARRAY_SIZE(kirkwood_cpufreq_resources),
 56	.resource	= kirkwood_cpufreq_resources,
 57};
 58
 59static void __init kirkwood_cpufreq_init(void)
 60{
 61	platform_device_register(&kirkwood_cpufreq_device);
 62}
 63
 64static struct resource kirkwood_cpuidle_resource[] = {
 65	{
 66		.flags	= IORESOURCE_MEM,
 67		.start	= DDR_OPERATION_BASE,
 68		.end	= DDR_OPERATION_BASE + 3,
 69	},
 70};
 71
 72static struct platform_device kirkwood_cpuidle = {
 73	.name		= "kirkwood_cpuidle",
 74	.id		= -1,
 75	.resource	= kirkwood_cpuidle_resource,
 76	.num_resources	= 1,
 77};
 78
 79static void __init kirkwood_cpuidle_init(void)
 80{
 81	platform_device_register(&kirkwood_cpuidle);
 82}
 83
 84/* Temporary here since mach-mvebu has a function we can use */
 85static void kirkwood_restart(enum reboot_mode mode, const char *cmd)
 86{
 87	/*
 88	 * Enable soft reset to assert RSTOUTn.
 89	 */
 90	writel(SOFT_RESET_OUT_EN, RSTOUTn_MASK);
 91
 92	/*
 93	 * Assert soft reset.
 94	 */
 95	writel(SOFT_RESET, SYSTEM_SOFT_RESET);
 96
 97	while (1)
 98		;
 99}
100
101#define MV643XX_ETH_MAC_ADDR_LOW	0x0414
102#define MV643XX_ETH_MAC_ADDR_HIGH	0x0418
103
104static void __init kirkwood_dt_eth_fixup(void)
105{
106	struct device_node *np;
107
108	/*
109	 * The ethernet interfaces forget the MAC address assigned by u-boot
110	 * if the clocks are turned off. Usually, u-boot on kirkwood boards
111	 * has no DT support to properly set local-mac-address property.
112	 * As a workaround, we get the MAC address from mv643xx_eth registers
113	 * and update the port device node if no valid MAC address is set.
114	 */
115	for_each_compatible_node(np, NULL, "marvell,kirkwood-eth-port") {
116		struct device_node *pnp = of_get_parent(np);
117		struct clk *clk;
118		struct property *pmac;
119		void __iomem *io;
120		u8 *macaddr;
121		u32 reg;
122
123		if (!pnp)
124			continue;
125
126		/* skip disabled nodes or nodes with valid MAC address*/
127		if (!of_device_is_available(pnp) || of_get_mac_address(np))
128			goto eth_fixup_skip;
129
130		clk = of_clk_get(pnp, 0);
131		if (IS_ERR(clk))
132			goto eth_fixup_skip;
133
134		io = of_iomap(pnp, 0);
135		if (!io)
136			goto eth_fixup_no_map;
137
138		/* ensure port clock is not gated to not hang CPU */
139		clk_prepare_enable(clk);
140
141		/* store MAC address register contents in local-mac-address */
142		pr_err(FW_INFO "%s: local-mac-address is not set\n",
143		       np->full_name);
144
145		pmac = kzalloc(sizeof(*pmac) + 6, GFP_KERNEL);
146		if (!pmac)
147			goto eth_fixup_no_mem;
148
149		pmac->value = pmac + 1;
150		pmac->length = 6;
151		pmac->name = kstrdup("local-mac-address", GFP_KERNEL);
152		if (!pmac->name) {
153			kfree(pmac);
154			goto eth_fixup_no_mem;
155		}
156
157		macaddr = pmac->value;
158		reg = readl(io + MV643XX_ETH_MAC_ADDR_HIGH);
159		macaddr[0] = (reg >> 24) & 0xff;
160		macaddr[1] = (reg >> 16) & 0xff;
161		macaddr[2] = (reg >> 8) & 0xff;
162		macaddr[3] = reg & 0xff;
163
164		reg = readl(io + MV643XX_ETH_MAC_ADDR_LOW);
165		macaddr[4] = (reg >> 8) & 0xff;
166		macaddr[5] = reg & 0xff;
167
168		of_update_property(np, pmac);
169
170eth_fixup_no_mem:
171		iounmap(io);
172		clk_disable_unprepare(clk);
173eth_fixup_no_map:
174		clk_put(clk);
175eth_fixup_skip:
176		of_node_put(pnp);
177	}
178}
179
180/*
181 * Disable propagation of mbus errors to the CPU local bus, as this
182 * causes mbus errors (which can occur for example for PCI aborts) to
183 * throw CPU aborts, which we're not set up to deal with.
184 */
185static void __init kirkwood_disable_mbus_error_propagation(void)
186{
187	void __iomem *cpu_config;
188
189	cpu_config = ioremap(CPU_CONFIG_PHYS, 4);
190	writel(readl(cpu_config) & ~CPU_CONFIG_ERROR_PROP, cpu_config);
191	iounmap(cpu_config);
192}
193
194static void __init kirkwood_dt_init(void)
195{
196	kirkwood_disable_mbus_error_propagation();
197
198	BUG_ON(mvebu_mbus_dt_init());
199
200#ifdef CONFIG_CACHE_FEROCEON_L2
201	feroceon_of_init();
202#endif
203	kirkwood_cpufreq_init();
204	kirkwood_cpuidle_init();
205
206	kirkwood_pm_init();
207	kirkwood_dt_eth_fixup();
208
209	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
210}
211
212static const char * const kirkwood_dt_board_compat[] = {
213	"marvell,kirkwood",
214	NULL
215};
216
217DT_MACHINE_START(KIRKWOOD_DT, "Marvell Kirkwood (Flattened Device Tree)")
218	/* Maintainer: Jason Cooper <jason@lakedaemon.net> */
219	.map_io		= kirkwood_map_io,
220	.init_machine	= kirkwood_dt_init,
221	.restart	= kirkwood_restart,
222	.dt_compat	= kirkwood_dt_board_compat,
223MACHINE_END
1