18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  External Memory Interface
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Copyright (C) 2011 Texas Instruments Incorporated
68c2ecf20Sopenharmony_ci *  Author: Mark Salter <msalter@redhat.com>
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/of.h>
98c2ecf20Sopenharmony_ci#include <linux/of_address.h>
108c2ecf20Sopenharmony_ci#include <linux/io.h>
118c2ecf20Sopenharmony_ci#include <asm/soc.h>
128c2ecf20Sopenharmony_ci#include <asm/dscr.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define NUM_EMIFA_CHIP_ENABLES 4
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cistruct emifa_regs {
178c2ecf20Sopenharmony_ci	u32	midr;
188c2ecf20Sopenharmony_ci	u32	stat;
198c2ecf20Sopenharmony_ci	u32	reserved1[6];
208c2ecf20Sopenharmony_ci	u32	bprio;
218c2ecf20Sopenharmony_ci	u32	reserved2[23];
228c2ecf20Sopenharmony_ci	u32	cecfg[NUM_EMIFA_CHIP_ENABLES];
238c2ecf20Sopenharmony_ci	u32	reserved3[4];
248c2ecf20Sopenharmony_ci	u32	awcc;
258c2ecf20Sopenharmony_ci	u32	reserved4[7];
268c2ecf20Sopenharmony_ci	u32	intraw;
278c2ecf20Sopenharmony_ci	u32	intmsk;
288c2ecf20Sopenharmony_ci	u32	intmskset;
298c2ecf20Sopenharmony_ci	u32	intmskclr;
308c2ecf20Sopenharmony_ci};
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_cistatic struct of_device_id emifa_match[] __initdata = {
338c2ecf20Sopenharmony_ci	{ .compatible = "ti,c64x+emifa"	},
348c2ecf20Sopenharmony_ci	{}
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/*
388c2ecf20Sopenharmony_ci * Parse device tree for existence of an EMIF (External Memory Interface)
398c2ecf20Sopenharmony_ci * and initialize it if found.
408c2ecf20Sopenharmony_ci */
418c2ecf20Sopenharmony_cistatic int __init c6x_emifa_init(void)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	struct emifa_regs __iomem *regs;
448c2ecf20Sopenharmony_ci	struct device_node *node;
458c2ecf20Sopenharmony_ci	const __be32 *p;
468c2ecf20Sopenharmony_ci	u32 val;
478c2ecf20Sopenharmony_ci	int i, len, err;
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci	node = of_find_matching_node(NULL, emifa_match);
508c2ecf20Sopenharmony_ci	if (!node)
518c2ecf20Sopenharmony_ci		return 0;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	regs = of_iomap(node, 0);
548c2ecf20Sopenharmony_ci	if (!regs)
558c2ecf20Sopenharmony_ci		return 0;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* look for a dscr-based enable for emifa pin buffers */
588c2ecf20Sopenharmony_ci	err = of_property_read_u32_array(node, "ti,dscr-dev-enable", &val, 1);
598c2ecf20Sopenharmony_ci	if (!err)
608c2ecf20Sopenharmony_ci		dscr_set_devstate(val, DSCR_DEVSTATE_ENABLED);
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	/* set up the chip enables */
638c2ecf20Sopenharmony_ci	p = of_get_property(node, "ti,emifa-ce-config", &len);
648c2ecf20Sopenharmony_ci	if (p) {
658c2ecf20Sopenharmony_ci		len /= sizeof(u32);
668c2ecf20Sopenharmony_ci		if (len > NUM_EMIFA_CHIP_ENABLES)
678c2ecf20Sopenharmony_ci			len = NUM_EMIFA_CHIP_ENABLES;
688c2ecf20Sopenharmony_ci		for (i = 0; i <= len; i++)
698c2ecf20Sopenharmony_ci			soc_writel(be32_to_cpup(&p[i]), &regs->cecfg[i]);
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	err = of_property_read_u32_array(node, "ti,emifa-burst-priority", &val, 1);
738c2ecf20Sopenharmony_ci	if (!err)
748c2ecf20Sopenharmony_ci		soc_writel(val, &regs->bprio);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	err = of_property_read_u32_array(node, "ti,emifa-async-wait-control", &val, 1);
778c2ecf20Sopenharmony_ci	if (!err)
788c2ecf20Sopenharmony_ci		soc_writel(val, &regs->awcc);
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	iounmap(regs);
818c2ecf20Sopenharmony_ci	of_node_put(node);
828c2ecf20Sopenharmony_ci	return 0;
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_cipure_initcall(c6x_emifa_init);
85