mach-mxs.c 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
/*
 * Copyright 2012 Freescale Semiconductor, Inc.
 * Copyright 2012 Linaro Ltd.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */

#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/err.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/irqdomain.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
#include <asm/mach/arch.h>
#include <asm/mach/time.h>
#include <mach/common.h>

static int __init mxs_icoll_add_irq_domain(struct device_node *np,
				struct device_node *interrupt_parent)
{
	irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);

	return 0;
}

33 34 35 36 37 38 39 40 41 42 43
static int __init mxs_gpio_add_irq_domain(struct device_node *np,
				struct device_node *interrupt_parent)
{
	static int gpio_irq_base = MXS_GPIO_IRQ_START;

	irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
	gpio_irq_base += 32;

	return 0;
}

44 45
static const struct of_device_id mxs_irq_match[] __initconst = {
	{ .compatible = "fsl,mxs-icoll", .data = mxs_icoll_add_irq_domain, },
46
	{ .compatible = "fsl,mxs-gpio", .data = mxs_gpio_add_irq_domain, },
47 48 49 50 51 52 53 54 55
	{ /* sentinel */ }
};

static void __init mxs_dt_init_irq(void)
{
	icoll_init_irq();
	of_irq_init(mxs_irq_match);
}

56 57 58 59 60 61 62 63 64
static void __init imx23_timer_init(void)
{
	mx23_clocks_init();
}

static struct sys_timer imx23_timer = {
	.init = imx23_timer_init,
};

65 66 67 68 69 70 71 72 73
static void __init imx28_timer_init(void)
{
	mx28_clocks_init();
}

static struct sys_timer imx28_timer = {
	.init = imx28_timer_init,
};

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
enum mac_oui {
	OUI_FSL,
	OUI_DENX,
};

static void __init update_fec_mac_prop(enum mac_oui oui)
{
	struct device_node *np, *from = NULL;
	struct property *oldmac, *newmac;
	const u32 *ocotp = mxs_get_ocotp();
	u8 *macaddr;
	u32 val;
	int i;

	for (i = 0; i < 2; i++) {
		np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
		if (!np)
			return;
		from = np;

		newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
		if (!newmac)
			return;
		newmac->value = newmac + 1;
		newmac->length = 6;

		newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
		if (!newmac->name) {
			kfree(newmac);
			return;
		}

		/*
		 * OCOTP only stores the last 4 octets for each mac address,
		 * so hard-code OUI here.
		 */
		macaddr = newmac->value;
		switch (oui) {
		case OUI_FSL:
			macaddr[0] = 0x00;
			macaddr[1] = 0x04;
			macaddr[2] = 0x9f;
			break;
		case OUI_DENX:
			macaddr[0] = 0xc0;
			macaddr[1] = 0xe5;
			macaddr[2] = 0x4e;
			break;
		}
		val = ocotp[i];
		macaddr[3] = (val >> 16) & 0xff;
		macaddr[4] = (val >> 8) & 0xff;
		macaddr[5] = (val >> 0) & 0xff;

		oldmac = of_find_property(np, newmac->name, NULL);
		if (oldmac)
			prom_update_property(np, newmac, oldmac);
		else
			prom_add_property(np, newmac);
	}
}

136 137 138 139 140 141 142 143
static void __init imx28_evk_init(void)
{
	struct clk *clk;

	/* Enable fec phy clock */
	clk = clk_get_sys("enet_out", NULL);
	if (!IS_ERR(clk))
		clk_prepare_enable(clk);
144 145

	update_fec_mac_prop(OUI_FSL);
146 147 148 149 150 151 152 153 154 155 156
}

static void __init mxs_machine_init(void)
{
	if (of_machine_is_compatible("fsl,imx28-evk"))
		imx28_evk_init();

	of_platform_populate(NULL, of_default_bus_match_table,
				NULL, NULL);
}

157 158 159 160 161 162
static const char *imx23_dt_compat[] __initdata = {
	"fsl,imx23-evk",
	"fsl,imx23",
	NULL,
};

163
static const char *imx28_dt_compat[] __initdata = {
164
	"crystalfontz,cfa10036",
165 166 167 168 169
	"fsl,imx28-evk",
	"fsl,imx28",
	NULL,
};

170 171 172 173 174 175 176 177 178
DT_MACHINE_START(IMX23, "Freescale i.MX23 (Device Tree)")
	.map_io		= mx23_map_io,
	.init_irq	= mxs_dt_init_irq,
	.timer		= &imx23_timer,
	.init_machine	= mxs_machine_init,
	.dt_compat	= imx23_dt_compat,
	.restart	= mxs_restart,
MACHINE_END

179 180 181 182 183 184 185 186
DT_MACHINE_START(IMX28, "Freescale i.MX28 (Device Tree)")
	.map_io		= mx28_map_io,
	.init_irq	= mxs_dt_init_irq,
	.timer		= &imx28_timer,
	.init_machine	= mxs_machine_init,
	.dt_compat	= imx28_dt_compat,
	.restart	= mxs_restart,
MACHINE_END