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