1/*
2 *  External Memory Interface
3 *
4 *  Copyright (C) 2011 Texas Instruments Incorporated
5 *  Author: Mark Salter <msalter@redhat.com>
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License version 2 as
9 *  published by the Free Software Foundation.
10 */
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/io.h>
14#include <asm/soc.h>
15#include <asm/dscr.h>
16
17#define NUM_EMIFA_CHIP_ENABLES 4
18
19struct emifa_regs {
20	u32	midr;
21	u32	stat;
22	u32	reserved1[6];
23	u32	bprio;
24	u32	reserved2[23];
25	u32	cecfg[NUM_EMIFA_CHIP_ENABLES];
26	u32	reserved3[4];
27	u32	awcc;
28	u32	reserved4[7];
29	u32	intraw;
30	u32	intmsk;
31	u32	intmskset;
32	u32	intmskclr;
33};
34
35static struct of_device_id emifa_match[] __initdata = {
36	{ .compatible = "ti,c64x+emifa"	},
37	{}
38};
39
40/*
41 * Parse device tree for existence of an EMIF (External Memory Interface)
42 * and initialize it if found.
43 */
44static int __init c6x_emifa_init(void)
45{
46	struct emifa_regs __iomem *regs;
47	struct device_node *node;
48	const __be32 *p;
49	u32 val;
50	int i, len, err;
51
52	node = of_find_matching_node(NULL, emifa_match);
53	if (!node)
54		return 0;
55
56	regs = of_iomap(node, 0);
57	if (!regs)
58		return 0;
59
60	/* look for a dscr-based enable for emifa pin buffers */
61	err = of_property_read_u32_array(node, "ti,dscr-dev-enable", &val, 1);
62	if (!err)
63		dscr_set_devstate(val, DSCR_DEVSTATE_ENABLED);
64
65	/* set up the chip enables */
66	p = of_get_property(node, "ti,emifa-ce-config", &len);
67	if (p) {
68		len /= sizeof(u32);
69		if (len > NUM_EMIFA_CHIP_ENABLES)
70			len = NUM_EMIFA_CHIP_ENABLES;
71		for (i = 0; i <= len; i++)
72			soc_writel(be32_to_cpup(&p[i]), &regs->cecfg[i]);
73	}
74
75	err = of_property_read_u32_array(node, "ti,emifa-burst-priority", &val, 1);
76	if (!err)
77		soc_writel(val, &regs->bprio);
78
79	err = of_property_read_u32_array(node, "ti,emifa-async-wait-control", &val, 1);
80	if (!err)
81		soc_writel(val, &regs->awcc);
82
83	iounmap(regs);
84	of_node_put(node);
85	return 0;
86}
87pure_initcall(c6x_emifa_init);
88