1fb180322SJohn Rigby /*
2fb180322SJohn Rigby  * Copyright (C) 2007,2008 Freescale Semiconductor, Inc. All rights reserved.
3fb180322SJohn Rigby  *
4fb180322SJohn Rigby  * Author: John Rigby <jrigby@freescale.com>
5fb180322SJohn Rigby  *
6fb180322SJohn Rigby  * Description:
7fb180322SJohn Rigby  * MPC512x Shared code
8fb180322SJohn Rigby  *
9fb180322SJohn Rigby  * This is free software; you can redistribute it and/or modify it
10fb180322SJohn Rigby  * under the terms of the GNU General Public License as published by
11fb180322SJohn Rigby  * the Free Software Foundation; either version 2 of the License, or
12fb180322SJohn Rigby  * (at your option) any later version.
13fb180322SJohn Rigby  */
14fb180322SJohn Rigby 
15fb180322SJohn Rigby #include <linux/kernel.h>
16fb180322SJohn Rigby #include <linux/io.h>
17fb180322SJohn Rigby #include <linux/irq.h>
18fb180322SJohn Rigby #include <linux/of_platform.h>
19fb180322SJohn Rigby 
20fb180322SJohn Rigby #include <asm/machdep.h>
21fb180322SJohn Rigby #include <asm/ipic.h>
22fb180322SJohn Rigby #include <asm/prom.h>
23fb180322SJohn Rigby #include <asm/time.h>
24a8dbceb7SAnatolij Gustschin #include <asm/mpc5121.h>
252da8cb6aSAnatolij Gustschin #include <asm/mpc52xx_psc.h>
26fb180322SJohn Rigby 
27fb180322SJohn Rigby #include "mpc512x.h"
28fb180322SJohn Rigby 
29a8dbceb7SAnatolij Gustschin static struct mpc512x_reset_module __iomem *reset_module_base;
30a8dbceb7SAnatolij Gustschin 
31a8dbceb7SAnatolij Gustschin static void __init mpc512x_restart_init(void)
32a8dbceb7SAnatolij Gustschin {
33a8dbceb7SAnatolij Gustschin 	struct device_node *np;
34a8dbceb7SAnatolij Gustschin 
35a8dbceb7SAnatolij Gustschin 	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-reset");
36a8dbceb7SAnatolij Gustschin 	if (!np)
37a8dbceb7SAnatolij Gustschin 		return;
38a8dbceb7SAnatolij Gustschin 
39a8dbceb7SAnatolij Gustschin 	reset_module_base = of_iomap(np, 0);
40a8dbceb7SAnatolij Gustschin 	of_node_put(np);
41a8dbceb7SAnatolij Gustschin }
42a8dbceb7SAnatolij Gustschin 
43a8dbceb7SAnatolij Gustschin void mpc512x_restart(char *cmd)
44a8dbceb7SAnatolij Gustschin {
45a8dbceb7SAnatolij Gustschin 	if (reset_module_base) {
46a8dbceb7SAnatolij Gustschin 		/* Enable software reset "RSTE" */
47a8dbceb7SAnatolij Gustschin 		out_be32(&reset_module_base->rpr, 0x52535445);
48a8dbceb7SAnatolij Gustschin 		/* Set software hard reset */
49a8dbceb7SAnatolij Gustschin 		out_be32(&reset_module_base->rcr, 0x2);
50a8dbceb7SAnatolij Gustschin 	} else {
51a8dbceb7SAnatolij Gustschin 		pr_err("Restart module not mapped.\n");
52a8dbceb7SAnatolij Gustschin 	}
53a8dbceb7SAnatolij Gustschin 	for (;;)
54a8dbceb7SAnatolij Gustschin 		;
55a8dbceb7SAnatolij Gustschin }
56a8dbceb7SAnatolij Gustschin 
57fb180322SJohn Rigby void __init mpc512x_init_IRQ(void)
58fb180322SJohn Rigby {
59fb180322SJohn Rigby 	struct device_node *np;
60fb180322SJohn Rigby 
61fb180322SJohn Rigby 	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-ipic");
62fb180322SJohn Rigby 	if (!np)
63fb180322SJohn Rigby 		return;
64fb180322SJohn Rigby 
65fb180322SJohn Rigby 	ipic_init(np, 0);
66fb180322SJohn Rigby 	of_node_put(np);
67fb180322SJohn Rigby 
68fb180322SJohn Rigby 	/*
69fb180322SJohn Rigby 	 * Initialize the default interrupt mapping priorities,
70fb180322SJohn Rigby 	 * in case the boot rom changed something on us.
71fb180322SJohn Rigby 	 */
72fb180322SJohn Rigby 	ipic_set_default_priority();
73fb180322SJohn Rigby }
74fb180322SJohn Rigby 
75fb180322SJohn Rigby /*
76fb180322SJohn Rigby  * Nodes to do bus probe on, soc and localbus
77fb180322SJohn Rigby  */
78fb180322SJohn Rigby static struct of_device_id __initdata of_bus_ids[] = {
79fb180322SJohn Rigby 	{ .compatible = "fsl,mpc5121-immr", },
80fb180322SJohn Rigby 	{ .compatible = "fsl,mpc5121-localbus", },
81fb180322SJohn Rigby 	{},
82fb180322SJohn Rigby };
83fb180322SJohn Rigby 
84fb180322SJohn Rigby void __init mpc512x_declare_of_platform_devices(void)
85fb180322SJohn Rigby {
865b2b6255SAnatolij Gustschin 	struct device_node *np;
875b2b6255SAnatolij Gustschin 
88fb180322SJohn Rigby 	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
89fb180322SJohn Rigby 		printk(KERN_ERR __FILE__ ": "
90fb180322SJohn Rigby 			"Error while probing of_platform bus\n");
915b2b6255SAnatolij Gustschin 
925b2b6255SAnatolij Gustschin 	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-nfc");
935b2b6255SAnatolij Gustschin 	if (np) {
945b2b6255SAnatolij Gustschin 		of_platform_device_create(np, NULL, NULL);
955b2b6255SAnatolij Gustschin 		of_node_put(np);
965b2b6255SAnatolij Gustschin 	}
97fb180322SJohn Rigby }
98fb180322SJohn Rigby 
992da8cb6aSAnatolij Gustschin #define DEFAULT_FIFO_SIZE 16
1002da8cb6aSAnatolij Gustschin 
1012da8cb6aSAnatolij Gustschin static unsigned int __init get_fifo_size(struct device_node *np,
1022da8cb6aSAnatolij Gustschin 					 char *prop_name)
1032da8cb6aSAnatolij Gustschin {
1042da8cb6aSAnatolij Gustschin 	const unsigned int *fp;
1052da8cb6aSAnatolij Gustschin 
1062da8cb6aSAnatolij Gustschin 	fp = of_get_property(np, prop_name, NULL);
1072da8cb6aSAnatolij Gustschin 	if (fp)
1082da8cb6aSAnatolij Gustschin 		return *fp;
1092da8cb6aSAnatolij Gustschin 
1102da8cb6aSAnatolij Gustschin 	pr_warning("no %s property in %s node, defaulting to %d\n",
1112da8cb6aSAnatolij Gustschin 		   prop_name, np->full_name, DEFAULT_FIFO_SIZE);
1122da8cb6aSAnatolij Gustschin 
1132da8cb6aSAnatolij Gustschin 	return DEFAULT_FIFO_SIZE;
1142da8cb6aSAnatolij Gustschin }
1152da8cb6aSAnatolij Gustschin 
1162da8cb6aSAnatolij Gustschin #define FIFOC(_base) ((struct mpc512x_psc_fifo __iomem *) \
1172da8cb6aSAnatolij Gustschin 		    ((u32)(_base) + sizeof(struct mpc52xx_psc)))
1182da8cb6aSAnatolij Gustschin 
1192da8cb6aSAnatolij Gustschin /* Init PSC FIFO space for TX and RX slices */
1202da8cb6aSAnatolij Gustschin void __init mpc512x_psc_fifo_init(void)
1212da8cb6aSAnatolij Gustschin {
1222da8cb6aSAnatolij Gustschin 	struct device_node *np;
1232da8cb6aSAnatolij Gustschin 	void __iomem *psc;
1242da8cb6aSAnatolij Gustschin 	unsigned int tx_fifo_size;
1252da8cb6aSAnatolij Gustschin 	unsigned int rx_fifo_size;
1262da8cb6aSAnatolij Gustschin 	int fifobase = 0; /* current fifo address in 32 bit words */
1272da8cb6aSAnatolij Gustschin 
1282da8cb6aSAnatolij Gustschin 	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
1292da8cb6aSAnatolij Gustschin 		tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
1302da8cb6aSAnatolij Gustschin 		rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");
1312da8cb6aSAnatolij Gustschin 
1322da8cb6aSAnatolij Gustschin 		/* size in register is in 4 byte units */
1332da8cb6aSAnatolij Gustschin 		tx_fifo_size /= 4;
1342da8cb6aSAnatolij Gustschin 		rx_fifo_size /= 4;
1352da8cb6aSAnatolij Gustschin 		if (!tx_fifo_size)
1362da8cb6aSAnatolij Gustschin 			tx_fifo_size = 1;
1372da8cb6aSAnatolij Gustschin 		if (!rx_fifo_size)
1382da8cb6aSAnatolij Gustschin 			rx_fifo_size = 1;
1392da8cb6aSAnatolij Gustschin 
1402da8cb6aSAnatolij Gustschin 		psc = of_iomap(np, 0);
1412da8cb6aSAnatolij Gustschin 		if (!psc) {
1422da8cb6aSAnatolij Gustschin 			pr_err("%s: Can't map %s device\n",
1432da8cb6aSAnatolij Gustschin 				__func__, np->full_name);
1442da8cb6aSAnatolij Gustschin 			continue;
1452da8cb6aSAnatolij Gustschin 		}
1462da8cb6aSAnatolij Gustschin 
1472da8cb6aSAnatolij Gustschin 		/* FIFO space is 4KiB, check if requested size is available */
1482da8cb6aSAnatolij Gustschin 		if ((fifobase + tx_fifo_size + rx_fifo_size) > 0x1000) {
1492da8cb6aSAnatolij Gustschin 			pr_err("%s: no fifo space available for %s\n",
1502da8cb6aSAnatolij Gustschin 				__func__, np->full_name);
1512da8cb6aSAnatolij Gustschin 			iounmap(psc);
1522da8cb6aSAnatolij Gustschin 			/*
1532da8cb6aSAnatolij Gustschin 			 * chances are that another device requests less
1542da8cb6aSAnatolij Gustschin 			 * fifo space, so we continue.
1552da8cb6aSAnatolij Gustschin 			 */
1562da8cb6aSAnatolij Gustschin 			continue;
1572da8cb6aSAnatolij Gustschin 		}
1582da8cb6aSAnatolij Gustschin 
1592da8cb6aSAnatolij Gustschin 		/* set tx and rx fifo size registers */
1602da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->txsz, (fifobase << 16) | tx_fifo_size);
1612da8cb6aSAnatolij Gustschin 		fifobase += tx_fifo_size;
1622da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->rxsz, (fifobase << 16) | rx_fifo_size);
1632da8cb6aSAnatolij Gustschin 		fifobase += rx_fifo_size;
1642da8cb6aSAnatolij Gustschin 
1652da8cb6aSAnatolij Gustschin 		/* reset and enable the slices */
1662da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->txcmd, 0x80);
1672da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->txcmd, 0x01);
1682da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->rxcmd, 0x80);
1692da8cb6aSAnatolij Gustschin 		out_be32(&FIFOC(psc)->rxcmd, 0x01);
1702da8cb6aSAnatolij Gustschin 
1712da8cb6aSAnatolij Gustschin 		iounmap(psc);
1722da8cb6aSAnatolij Gustschin 	}
1732da8cb6aSAnatolij Gustschin }
1742da8cb6aSAnatolij Gustschin 
175284ed66fSAnatolij Gustschin void __init mpc512x_init(void)
176284ed66fSAnatolij Gustschin {
177284ed66fSAnatolij Gustschin 	mpc512x_declare_of_platform_devices();
178284ed66fSAnatolij Gustschin 	mpc5121_clk_init();
179a8dbceb7SAnatolij Gustschin 	mpc512x_restart_init();
1802da8cb6aSAnatolij Gustschin 	mpc512x_psc_fifo_init();
181284ed66fSAnatolij Gustschin }
182