1 /* 2 * Copyright 2008-2011 Freescale Semiconductor, Inc. 3 * Copyright 2017 NXP 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <linux/libfdt.h> 10 #include <fdt_support.h> 11 12 #include <asm/processor.h> 13 #include <asm/io.h> 14 #ifdef CONFIG_PPC 15 #include <asm/fsl_portals.h> 16 #include <asm/fsl_liodn.h> 17 #endif 18 #include <fsl_qbman.h> 19 20 #define MAX_BPORTALS (CONFIG_SYS_BMAN_CINH_SIZE / CONFIG_SYS_BMAN_SP_CINH_SIZE) 21 #define MAX_QPORTALS (CONFIG_SYS_QMAN_CINH_SIZE / CONFIG_SYS_QMAN_SP_CINH_SIZE) 22 void setup_qbman_portals(void) 23 { 24 void __iomem *bpaddr = (void *)CONFIG_SYS_BMAN_CINH_BASE + 25 CONFIG_SYS_BMAN_SWP_ISDR_REG; 26 void __iomem *qpaddr = (void *)CONFIG_SYS_QMAN_CINH_BASE + 27 CONFIG_SYS_QMAN_SWP_ISDR_REG; 28 #ifdef CONFIG_PPC 29 struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR; 30 31 /* Set the Qman initiator BAR to match the LAW (for DQRR stashing) */ 32 #ifdef CONFIG_PHYS_64BIT 33 out_be32(&qman->qcsp_bare, (u32)(CONFIG_SYS_QMAN_MEM_PHYS >> 32)); 34 #endif 35 out_be32(&qman->qcsp_bar, (u32)CONFIG_SYS_QMAN_MEM_PHYS); 36 #endif 37 #ifdef CONFIG_FSL_CORENET 38 int i; 39 40 for (i = 0; i < CONFIG_SYS_QMAN_NUM_PORTALS; i++) { 41 u8 sdest = qp_info[i].sdest; 42 u16 fliodn = qp_info[i].fliodn; 43 u16 dliodn = qp_info[i].dliodn; 44 u16 liodn_off = qp_info[i].liodn_offset; 45 46 out_be32(&qman->qcsp[i].qcsp_lio_cfg, (liodn_off << 16) | 47 dliodn); 48 /* set frame liodn */ 49 out_be32(&qman->qcsp[i].qcsp_io_cfg, (sdest << 16) | fliodn); 50 } 51 #endif 52 53 /* Change default state of BMan ISDR portals to all 1s */ 54 inhibit_portals(bpaddr, CONFIG_SYS_BMAN_NUM_PORTALS, MAX_BPORTALS, 55 CONFIG_SYS_BMAN_SP_CINH_SIZE); 56 inhibit_portals(qpaddr, CONFIG_SYS_QMAN_NUM_PORTALS, MAX_QPORTALS, 57 CONFIG_SYS_QMAN_SP_CINH_SIZE); 58 } 59 60 void inhibit_portals(void __iomem *addr, int max_portals, 61 int arch_max_portals, int portal_cinh_size) 62 { 63 u32 val; 64 int i; 65 66 /* arch_max_portals is the maximum based on memory size. This includes 67 * the reserved memory in the SoC. max_portals the number of physical 68 * portals in the SoC 69 */ 70 if (max_portals > arch_max_portals) { 71 printf("ERROR: portal config error\n"); 72 max_portals = arch_max_portals; 73 } 74 75 for (i = 0; i < max_portals; i++) { 76 out_be32(addr, -1); 77 val = in_be32(addr); 78 if (!val) { 79 printf("ERROR: Stopped after %d portals\n", i); 80 return; 81 } 82 addr += portal_cinh_size; 83 } 84 debug("Cleared %d portals\n", i); 85 } 86 87 #ifdef CONFIG_PPC 88 static int fdt_qportal(void *blob, int off, int id, char *name, 89 enum fsl_dpaa_dev dev, int create) 90 { 91 int childoff, dev_off, ret = 0; 92 u32 dev_handle; 93 #ifdef CONFIG_FSL_CORENET 94 int num; 95 u32 liodns[2]; 96 #endif 97 98 childoff = fdt_subnode_offset(blob, off, name); 99 if (create) { 100 char handle[64], *p; 101 102 strncpy(handle, name, sizeof(handle)); 103 p = strchr(handle, '@'); 104 if (!strncmp(name, "fman", 4)) { 105 *p = *(p + 1); 106 p++; 107 } 108 *p = '\0'; 109 110 dev_off = fdt_path_offset(blob, handle); 111 /* skip this node if alias is not found */ 112 if (dev_off == -FDT_ERR_BADPATH) 113 return 0; 114 if (dev_off < 0) 115 return dev_off; 116 117 if (childoff <= 0) 118 childoff = fdt_add_subnode(blob, off, name); 119 120 /* need to update the dev_off after adding a subnode */ 121 dev_off = fdt_path_offset(blob, handle); 122 if (dev_off < 0) 123 return dev_off; 124 125 if (childoff > 0) { 126 dev_handle = fdt_get_phandle(blob, dev_off); 127 if (dev_handle <= 0) { 128 dev_handle = fdt_alloc_phandle(blob); 129 ret = fdt_set_phandle(blob, dev_off, 130 dev_handle); 131 if (ret < 0) 132 return ret; 133 } 134 135 ret = fdt_setprop(blob, childoff, "dev-handle", 136 &dev_handle, sizeof(dev_handle)); 137 if (ret < 0) 138 return ret; 139 140 #ifdef CONFIG_FSL_CORENET 141 num = get_dpaa_liodn(dev, &liodns[0], id); 142 ret = fdt_setprop(blob, childoff, "fsl,liodn", 143 &liodns[0], sizeof(u32) * num); 144 if (!strncmp(name, "pme", 3)) { 145 u32 pme_rev1, pme_rev2; 146 ccsr_pme_t *pme_regs = 147 (void *)CONFIG_SYS_FSL_CORENET_PME_ADDR; 148 149 pme_rev1 = in_be32(&pme_regs->pm_ip_rev_1); 150 pme_rev2 = in_be32(&pme_regs->pm_ip_rev_2); 151 ret = fdt_setprop(blob, childoff, 152 "fsl,pme-rev1", &pme_rev1, 153 sizeof(u32)); 154 if (ret < 0) 155 return ret; 156 ret = fdt_setprop(blob, childoff, 157 "fsl,pme-rev2", &pme_rev2, 158 sizeof(u32)); 159 } 160 #endif 161 } else { 162 return childoff; 163 } 164 } else { 165 if (childoff > 0) 166 ret = fdt_del_node(blob, childoff); 167 } 168 169 return ret; 170 } 171 #endif /* CONFIG_PPC */ 172 173 void fdt_fixup_qportals(void *blob) 174 { 175 int off, err; 176 unsigned int maj, min; 177 unsigned int ip_cfg; 178 struct ccsr_qman *qman = (void *)CONFIG_SYS_FSL_QMAN_ADDR; 179 u32 rev_1 = in_be32(&qman->ip_rev_1); 180 u32 rev_2 = in_be32(&qman->ip_rev_2); 181 char compat[64]; 182 int compat_len; 183 184 maj = (rev_1 >> 8) & 0xff; 185 min = rev_1 & 0xff; 186 ip_cfg = rev_2 & 0xff; 187 188 compat_len = sprintf(compat, "fsl,qman-portal-%u.%u.%u", 189 maj, min, ip_cfg) + 1; 190 compat_len += sprintf(compat + compat_len, "fsl,qman-portal") + 1; 191 192 off = fdt_node_offset_by_compatible(blob, -1, "fsl,qman-portal"); 193 while (off != -FDT_ERR_NOTFOUND) { 194 #ifdef CONFIG_PPC 195 #ifdef CONFIG_FSL_CORENET 196 u32 liodns[2]; 197 #endif 198 const int *ci = fdt_getprop(blob, off, "cell-index", &err); 199 int i; 200 201 if (!ci) 202 goto err; 203 204 i = *ci; 205 #ifdef CONFIG_SYS_DPAA_FMAN 206 int j; 207 #endif 208 209 #endif /* CONFIG_PPC */ 210 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 211 if (err < 0) 212 goto err; 213 #ifdef CONFIG_PPC 214 #ifdef CONFIG_FSL_CORENET 215 liodns[0] = qp_info[i].dliodn; 216 liodns[1] = qp_info[i].fliodn; 217 err = fdt_setprop(blob, off, "fsl,liodn", 218 &liodns, sizeof(u32) * 2); 219 if (err < 0) 220 goto err; 221 #endif 222 223 i++; 224 225 err = fdt_qportal(blob, off, i, "crypto@0", FSL_HW_PORTAL_SEC, 226 IS_E_PROCESSOR(get_svr())); 227 if (err < 0) 228 goto err; 229 230 #ifdef CONFIG_FSL_CORENET 231 #ifdef CONFIG_SYS_DPAA_PME 232 err = fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 1); 233 if (err < 0) 234 goto err; 235 #else 236 fdt_qportal(blob, off, i, "pme@0", FSL_HW_PORTAL_PME, 0); 237 #endif 238 #endif 239 240 #ifdef CONFIG_SYS_DPAA_FMAN 241 for (j = 0; j < CONFIG_SYS_NUM_FMAN; j++) { 242 char name[] = "fman@0"; 243 244 name[sizeof(name) - 2] = '0' + j; 245 err = fdt_qportal(blob, off, i, name, 246 FSL_HW_PORTAL_FMAN1 + j, 1); 247 if (err < 0) 248 goto err; 249 } 250 #endif 251 #ifdef CONFIG_SYS_DPAA_RMAN 252 err = fdt_qportal(blob, off, i, "rman@0", 253 FSL_HW_PORTAL_RMAN, 1); 254 if (err < 0) 255 goto err; 256 #endif 257 #endif /* CONFIG_PPC */ 258 259 err: 260 if (err < 0) { 261 printf("ERROR: unable to create props for %s: %s\n", 262 fdt_get_name(blob, off, NULL), 263 fdt_strerror(err)); 264 return; 265 } 266 267 off = fdt_node_offset_by_compatible(blob, off, 268 "fsl,qman-portal"); 269 } 270 } 271 272 void fdt_fixup_bportals(void *blob) 273 { 274 int off, err; 275 unsigned int maj, min; 276 unsigned int ip_cfg; 277 struct ccsr_bman *bman = (void *)CONFIG_SYS_FSL_BMAN_ADDR; 278 u32 rev_1 = in_be32(&bman->ip_rev_1); 279 u32 rev_2 = in_be32(&bman->ip_rev_2); 280 char compat[64]; 281 int compat_len; 282 283 maj = (rev_1 >> 8) & 0xff; 284 min = rev_1 & 0xff; 285 286 ip_cfg = rev_2 & 0xff; 287 288 compat_len = sprintf(compat, "fsl,bman-portal-%u.%u.%u", 289 maj, min, ip_cfg) + 1; 290 compat_len += sprintf(compat + compat_len, "fsl,bman-portal") + 1; 291 292 off = fdt_node_offset_by_compatible(blob, -1, "fsl,bman-portal"); 293 while (off != -FDT_ERR_NOTFOUND) { 294 err = fdt_setprop(blob, off, "compatible", compat, compat_len); 295 if (err < 0) { 296 printf("ERROR: unable to create props for %s: %s\n", 297 fdt_get_name(blob, off, NULL), 298 fdt_strerror(err)); 299 return; 300 } 301 302 off = fdt_node_offset_by_compatible(blob, off, 303 "fsl,bman-portal"); 304 } 305 } 306