xref: /rk3399_rockchip-uboot/arch/powerpc/cpu/mpc8xxx/fdt.c (revision a09b9b68d492e978ef0e14cae93ff9cfbc2d3e4b)
1a47a12beSStefan Roese /*
2*a09b9b68SKumar Gala  * Copyright 2009-2011 Freescale Semiconductor, Inc.
3a47a12beSStefan Roese  *
4a47a12beSStefan Roese  * This file is derived from arch/powerpc/cpu/mpc85xx/cpu.c and
5a47a12beSStefan Roese  * arch/powerpc/cpu/mpc86xx/cpu.c. Basically this file contains
6a47a12beSStefan Roese  * cpu specific common code for 85xx/86xx processors.
7a47a12beSStefan Roese  * See file CREDITS for list of people who contributed to this
8a47a12beSStefan Roese  * project.
9a47a12beSStefan Roese  *
10a47a12beSStefan Roese  * This program is free software; you can redistribute it and/or
11a47a12beSStefan Roese  * modify it under the terms of the GNU General Public License as
12a47a12beSStefan Roese  * published by the Free Software Foundation; either version 2 of
13a47a12beSStefan Roese  * the License, or (at your option) any later version.
14a47a12beSStefan Roese  *
15a47a12beSStefan Roese  * This program is distributed in the hope that it will be useful,
16a47a12beSStefan Roese  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17a47a12beSStefan Roese  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18a47a12beSStefan Roese  * GNU General Public License for more details.
19a47a12beSStefan Roese  *
20a47a12beSStefan Roese  * You should have received a copy of the GNU General Public License
21a47a12beSStefan Roese  * along with this program; if not, write to the Free Software
22a47a12beSStefan Roese  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23a47a12beSStefan Roese  * MA 02111-1307 USA
24a47a12beSStefan Roese  */
25a47a12beSStefan Roese 
26a47a12beSStefan Roese #include <common.h>
27a47a12beSStefan Roese #include <libfdt.h>
28a47a12beSStefan Roese #include <fdt_support.h>
298f3a7fa4SKumar Gala #include <asm/mp.h>
30a1964ea5SKumar Gala #include <asm/fsl_enet.h>
31*a09b9b68SKumar Gala #include <asm/fsl_serdes.h>
32a47a12beSStefan Roese 
338f3a7fa4SKumar Gala #if defined(CONFIG_MP) && (defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx))
3411beefa3SKumar Gala static int ft_del_cpuhandle(void *blob, int cpuhandle)
3511beefa3SKumar Gala {
3611beefa3SKumar Gala 	int off, ret = -FDT_ERR_NOTFOUND;
3711beefa3SKumar Gala 
3811beefa3SKumar Gala 	/* if we find a match, we'll delete at it which point the offsets are
3911beefa3SKumar Gala 	 * invalid so we start over from the beginning
4011beefa3SKumar Gala 	 */
4111beefa3SKumar Gala 	off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle",
4211beefa3SKumar Gala 						&cpuhandle, 4);
4311beefa3SKumar Gala 	while (off != -FDT_ERR_NOTFOUND) {
4411beefa3SKumar Gala 		fdt_delprop(blob, off, "cpu-handle");
4511beefa3SKumar Gala 		ret = 1;
4611beefa3SKumar Gala 		off = fdt_node_offset_by_prop_value(blob, -1, "cpu-handle",
4711beefa3SKumar Gala 				&cpuhandle, 4);
4811beefa3SKumar Gala 	}
4911beefa3SKumar Gala 
5011beefa3SKumar Gala 	return ret;
5111beefa3SKumar Gala }
5211beefa3SKumar Gala 
53a47a12beSStefan Roese void ft_fixup_num_cores(void *blob) {
54a47a12beSStefan Roese 	int off, num_cores, del_cores;
55a47a12beSStefan Roese 
56a47a12beSStefan Roese 	del_cores = 0;
57a47a12beSStefan Roese 	num_cores = cpu_numcores();
58a47a12beSStefan Roese 
59a47a12beSStefan Roese 	off = fdt_node_offset_by_prop_value(blob, -1, "device_type", "cpu", 4);
60a47a12beSStefan Roese 	while (off != -FDT_ERR_NOTFOUND) {
61a47a12beSStefan Roese 		u32 *reg = (u32 *)fdt_getprop(blob, off, "reg", 0);
62a47a12beSStefan Roese 
638f3a7fa4SKumar Gala 		if ((*reg > num_cores-1) || (is_core_disabled(*reg))) {
6411beefa3SKumar Gala 			int ph = fdt_get_phandle(blob, off);
6511beefa3SKumar Gala 
6611beefa3SKumar Gala 			/* Delete the cpu node once there are no cpu handles */
6711beefa3SKumar Gala 			if (-FDT_ERR_NOTFOUND == ft_del_cpuhandle(blob, ph)) {
68a47a12beSStefan Roese 				fdt_del_node(blob, off);
69a47a12beSStefan Roese 				del_cores++;
7011beefa3SKumar Gala 			}
7111beefa3SKumar Gala 			/* either we deleted some cpu handles or the cpu node
7211beefa3SKumar Gala 			 * so we reset the offset back to the start since we
7311beefa3SKumar Gala 			 * can't trust the offsets anymore
7411beefa3SKumar Gala 			 */
75a47a12beSStefan Roese 			off = -1;
76a47a12beSStefan Roese 		}
77a47a12beSStefan Roese 		off = fdt_node_offset_by_prop_value(blob, off,
78a47a12beSStefan Roese 				"device_type", "cpu", 4);
79a47a12beSStefan Roese 	}
80a47a12beSStefan Roese 	debug ("%x core system found\n", num_cores);
81a47a12beSStefan Roese 	debug ("deleted %d extra core entry entries from device tree\n",
82a47a12beSStefan Roese 								del_cores);
83a47a12beSStefan Roese }
845d0c3b57SKim Phillips #endif /* defined(CONFIG_MPC85xx) || defined(CONFIG_MPC86xx) */
855d0c3b57SKim Phillips 
865d0c3b57SKim Phillips #ifdef CONFIG_HAS_FSL_DR_USB
875d0c3b57SKim Phillips void fdt_fixup_dr_usb(void *blob, bd_t *bd)
885d0c3b57SKim Phillips {
895d0c3b57SKim Phillips 	char *mode;
905d0c3b57SKim Phillips 	char *type;
915d0c3b57SKim Phillips 	const char *compat = "fsl-usb2-dr";
925d0c3b57SKim Phillips 	const char *prop_mode = "dr_mode";
935d0c3b57SKim Phillips 	const char *prop_type = "phy_type";
945d0c3b57SKim Phillips 	int node_offset;
955d0c3b57SKim Phillips 	int err;
965d0c3b57SKim Phillips 
975d0c3b57SKim Phillips 	mode = getenv("usb_dr_mode");
985d0c3b57SKim Phillips 	type = getenv("usb_phy_type");
995d0c3b57SKim Phillips 	if (!mode && !type)
1005d0c3b57SKim Phillips 		return;
1015d0c3b57SKim Phillips 
1025d0c3b57SKim Phillips 	node_offset = fdt_node_offset_by_compatible(blob, 0, compat);
1035d0c3b57SKim Phillips 	if (node_offset < 0) {
1045d0c3b57SKim Phillips 		printf("WARNING: could not find compatible node %s: %s.\n",
1055d0c3b57SKim Phillips 			compat, fdt_strerror(node_offset));
1065d0c3b57SKim Phillips 		return;
1075d0c3b57SKim Phillips 	}
1085d0c3b57SKim Phillips 
1095d0c3b57SKim Phillips 	if (mode) {
1105d0c3b57SKim Phillips 		err = fdt_setprop(blob, node_offset, prop_mode, mode,
1115d0c3b57SKim Phillips 				  strlen(mode) + 1);
1125d0c3b57SKim Phillips 		if (err < 0)
1135d0c3b57SKim Phillips 			printf("WARNING: could not set %s for %s: %s.\n",
1145d0c3b57SKim Phillips 			       prop_mode, compat, fdt_strerror(err));
1155d0c3b57SKim Phillips 	}
1165d0c3b57SKim Phillips 
1175d0c3b57SKim Phillips 	if (type) {
1185d0c3b57SKim Phillips 		err = fdt_setprop(blob, node_offset, prop_type, type,
1195d0c3b57SKim Phillips 				  strlen(type) + 1);
1205d0c3b57SKim Phillips 		if (err < 0)
1215d0c3b57SKim Phillips 			printf("WARNING: could not set %s for %s: %s.\n",
1225d0c3b57SKim Phillips 			       prop_type, compat, fdt_strerror(err));
1235d0c3b57SKim Phillips 	}
1245d0c3b57SKim Phillips }
1255d0c3b57SKim Phillips #endif /* CONFIG_HAS_FSL_DR_USB */
1265d0c3b57SKim Phillips 
1275d0c3b57SKim Phillips /*
1285d0c3b57SKim Phillips  * update crypto node properties to a specified revision of the SEC
129929a2138SKim Phillips  * called with sec_rev == 0 if not on an E processor
1305d0c3b57SKim Phillips  */
131929a2138SKim Phillips #if CONFIG_SYS_FSL_SEC_COMPAT == 2 /* SEC 2.x/3.x */
1325d0c3b57SKim Phillips void fdt_fixup_crypto_node(void *blob, int sec_rev)
1335d0c3b57SKim Phillips {
1345d0c3b57SKim Phillips 	const struct sec_rev_prop {
1355d0c3b57SKim Phillips 		u32 sec_rev;
1365d0c3b57SKim Phillips 		u32 num_channels;
1375d0c3b57SKim Phillips 		u32 channel_fifo_len;
1385d0c3b57SKim Phillips 		u32 exec_units_mask;
1395d0c3b57SKim Phillips 		u32 descriptor_types_mask;
1405d0c3b57SKim Phillips 	} sec_rev_prop_list [] = {
1415d0c3b57SKim Phillips 		{ 0x0200, 4, 24, 0x07e, 0x01010ebf }, /* SEC 2.0 */
1425d0c3b57SKim Phillips 		{ 0x0201, 4, 24, 0x0fe, 0x012b0ebf }, /* SEC 2.1 */
1435d0c3b57SKim Phillips 		{ 0x0202, 1, 24, 0x04c, 0x0122003f }, /* SEC 2.2 */
1445d0c3b57SKim Phillips 		{ 0x0204, 4, 24, 0x07e, 0x012b0ebf }, /* SEC 2.4 */
1455d0c3b57SKim Phillips 		{ 0x0300, 4, 24, 0x9fe, 0x03ab0ebf }, /* SEC 3.0 */
1465d0c3b57SKim Phillips 		{ 0x0301, 4, 24, 0xbfe, 0x03ab0ebf }, /* SEC 3.1 */
1475d0c3b57SKim Phillips 		{ 0x0303, 4, 24, 0x97c, 0x03a30abf }, /* SEC 3.3 */
1485d0c3b57SKim Phillips 	};
1495d0c3b57SKim Phillips 	char compat_strlist[ARRAY_SIZE(sec_rev_prop_list) *
1505d0c3b57SKim Phillips 			    sizeof("fsl,secX.Y")];
1515d0c3b57SKim Phillips 	int crypto_node, sec_idx, err;
1525d0c3b57SKim Phillips 	char *p;
1535d0c3b57SKim Phillips 	u32 val;
1545d0c3b57SKim Phillips 
1555d0c3b57SKim Phillips 	/* locate crypto node based on lowest common compatible */
1565d0c3b57SKim Phillips 	crypto_node = fdt_node_offset_by_compatible(blob, -1, "fsl,sec2.0");
1575d0c3b57SKim Phillips 	if (crypto_node == -FDT_ERR_NOTFOUND)
1585d0c3b57SKim Phillips 		return;
1595d0c3b57SKim Phillips 
1605d0c3b57SKim Phillips 	/* delete it if not on an E-processor */
1615d0c3b57SKim Phillips 	if (crypto_node > 0 && !sec_rev) {
1625d0c3b57SKim Phillips 		fdt_del_node(blob, crypto_node);
1635d0c3b57SKim Phillips 		return;
1645d0c3b57SKim Phillips 	}
1655d0c3b57SKim Phillips 
1665d0c3b57SKim Phillips 	/* else we got called for possible uprev */
1675d0c3b57SKim Phillips 	for (sec_idx = 0; sec_idx < ARRAY_SIZE(sec_rev_prop_list); sec_idx++)
1685d0c3b57SKim Phillips 		if (sec_rev_prop_list[sec_idx].sec_rev == sec_rev)
1695d0c3b57SKim Phillips 			break;
1705d0c3b57SKim Phillips 
1715d0c3b57SKim Phillips 	if (sec_idx == ARRAY_SIZE(sec_rev_prop_list)) {
1725d0c3b57SKim Phillips 		puts("warning: unknown SEC revision number\n");
1735d0c3b57SKim Phillips 		return;
1745d0c3b57SKim Phillips 	}
1755d0c3b57SKim Phillips 
1765d0c3b57SKim Phillips 	val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].num_channels);
1775d0c3b57SKim Phillips 	err = fdt_setprop(blob, crypto_node, "fsl,num-channels", &val, 4);
1785d0c3b57SKim Phillips 	if (err < 0)
1795d0c3b57SKim Phillips 		printf("WARNING: could not set crypto property: %s\n",
1805d0c3b57SKim Phillips 		       fdt_strerror(err));
1815d0c3b57SKim Phillips 
1825d0c3b57SKim Phillips 	val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].descriptor_types_mask);
1835d0c3b57SKim Phillips 	err = fdt_setprop(blob, crypto_node, "fsl,descriptor-types-mask", &val, 4);
1845d0c3b57SKim Phillips 	if (err < 0)
1855d0c3b57SKim Phillips 		printf("WARNING: could not set crypto property: %s\n",
1865d0c3b57SKim Phillips 		       fdt_strerror(err));
1875d0c3b57SKim Phillips 
1885d0c3b57SKim Phillips 	val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].exec_units_mask);
1895d0c3b57SKim Phillips 	err = fdt_setprop(blob, crypto_node, "fsl,exec-units-mask", &val, 4);
1905d0c3b57SKim Phillips 	if (err < 0)
1915d0c3b57SKim Phillips 		printf("WARNING: could not set crypto property: %s\n",
1925d0c3b57SKim Phillips 		       fdt_strerror(err));
1935d0c3b57SKim Phillips 
1945d0c3b57SKim Phillips 	val = cpu_to_fdt32(sec_rev_prop_list[sec_idx].channel_fifo_len);
1955d0c3b57SKim Phillips 	err = fdt_setprop(blob, crypto_node, "fsl,channel-fifo-len", &val, 4);
1965d0c3b57SKim Phillips 	if (err < 0)
1975d0c3b57SKim Phillips 		printf("WARNING: could not set crypto property: %s\n",
1985d0c3b57SKim Phillips 		       fdt_strerror(err));
1995d0c3b57SKim Phillips 
2005d0c3b57SKim Phillips 	val = 0;
2015d0c3b57SKim Phillips 	while (sec_idx >= 0) {
2025d0c3b57SKim Phillips 		p = compat_strlist + val;
2035d0c3b57SKim Phillips 		val += sprintf(p, "fsl,sec%d.%d",
2045d0c3b57SKim Phillips 			(sec_rev_prop_list[sec_idx].sec_rev & 0xff00) >> 8,
2055d0c3b57SKim Phillips 			sec_rev_prop_list[sec_idx].sec_rev & 0x00ff) + 1;
2065d0c3b57SKim Phillips 		sec_idx--;
2075d0c3b57SKim Phillips 	}
2085d0c3b57SKim Phillips 	err = fdt_setprop(blob, crypto_node, "compatible", &compat_strlist, val);
2095d0c3b57SKim Phillips 	if (err < 0)
2105d0c3b57SKim Phillips 		printf("WARNING: could not set crypto property: %s\n",
2115d0c3b57SKim Phillips 		       fdt_strerror(err));
2125d0c3b57SKim Phillips }
21322f292c7SKim Phillips #elif CONFIG_SYS_FSL_SEC_COMPAT >= 4  /* SEC4 */
21422f292c7SKim Phillips void fdt_fixup_crypto_node(void *blob, int sec_rev)
21522f292c7SKim Phillips {
21622f292c7SKim Phillips 	if (!sec_rev)
21722f292c7SKim Phillips 		fdt_del_node_and_alias(blob, "crypto");
21822f292c7SKim Phillips }
219929a2138SKim Phillips #endif
220a1964ea5SKumar Gala 
221a1964ea5SKumar Gala int fdt_fixup_phy_connection(void *blob, int offset, enum fsl_phy_enet_if phyc)
222a1964ea5SKumar Gala {
223a1964ea5SKumar Gala 	static const char *fsl_phy_enet_if_str[] = {
224a1964ea5SKumar Gala 		[MII]		= "mii",
225a1964ea5SKumar Gala 		[RMII]		= "rmii",
226a1964ea5SKumar Gala 		[GMII]		= "gmii",
227a1964ea5SKumar Gala 		[RGMII]		= "rgmii",
228a1964ea5SKumar Gala 		[RGMII_ID]	= "rgmii-id",
229a1964ea5SKumar Gala 		[RGMII_RXID]	= "rgmii-rxid",
230a1964ea5SKumar Gala 		[SGMII]		= "sgmii",
231a1964ea5SKumar Gala 		[TBI]		= "tbi",
232a1964ea5SKumar Gala 		[RTBI]		= "rtbi",
233a1964ea5SKumar Gala 		[XAUI]		= "xgmii",
234a1964ea5SKumar Gala 		[FSL_ETH_IF_NONE] = "",
235a1964ea5SKumar Gala 	};
236a1964ea5SKumar Gala 
237a1964ea5SKumar Gala 	if (phyc > ARRAY_SIZE(fsl_phy_enet_if_str))
238a1964ea5SKumar Gala 		return fdt_setprop_string(blob, offset, "phy-connection-type", "");
239a1964ea5SKumar Gala 
240a1964ea5SKumar Gala 	return fdt_setprop_string(blob, offset, "phy-connection-type",
241a1964ea5SKumar Gala 					 fsl_phy_enet_if_str[phyc]);
242a1964ea5SKumar Gala }
243*a09b9b68SKumar Gala 
244*a09b9b68SKumar Gala #ifdef CONFIG_SYS_SRIO
245*a09b9b68SKumar Gala void ft_srio_setup(void *blob)
246*a09b9b68SKumar Gala {
247*a09b9b68SKumar Gala #ifdef CONFIG_SRIO1
248*a09b9b68SKumar Gala 	if (!is_serdes_configured(SRIO1)) {
249*a09b9b68SKumar Gala 		fdt_del_node_and_alias(blob, "rio0");
250*a09b9b68SKumar Gala 	}
251*a09b9b68SKumar Gala #else
252*a09b9b68SKumar Gala 	fdt_del_node_and_alias(blob, "rio0");
253*a09b9b68SKumar Gala #endif
254*a09b9b68SKumar Gala #ifdef CONFIG_SRIO2
255*a09b9b68SKumar Gala 	if (!is_serdes_configured(SRIO2)) {
256*a09b9b68SKumar Gala 		fdt_del_node_and_alias(blob, "rio1");
257*a09b9b68SKumar Gala 	}
258*a09b9b68SKumar Gala #else
259*a09b9b68SKumar Gala 	fdt_del_node_and_alias(blob, "rio1");
260*a09b9b68SKumar Gala #endif
261*a09b9b68SKumar Gala }
262*a09b9b68SKumar Gala #endif
263