1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * spu management operations for of based platforms 4 * 5 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 6 * Copyright 2006 Sony Corp. 7 * (C) Copyright 2007 TOSHIBA CORPORATION 8 */ 9 10 #include <linux/interrupt.h> 11 #include <linux/list.h> 12 #include <linux/export.h> 13 #include <linux/ptrace.h> 14 #include <linux/wait.h> 15 #include <linux/mm.h> 16 #include <linux/io.h> 17 #include <linux/mutex.h> 18 #include <linux/device.h> 19 20 #include <asm/spu.h> 21 #include <asm/spu_priv1.h> 22 #include <asm/firmware.h> 23 #include <asm/prom.h> 24 25 #include "spufs/spufs.h" 26 #include "interrupt.h" 27 28 struct device_node *spu_devnode(struct spu *spu) 29 { 30 return spu->devnode; 31 } 32 33 EXPORT_SYMBOL_GPL(spu_devnode); 34 35 static u64 __init find_spu_unit_number(struct device_node *spe) 36 { 37 const unsigned int *prop; 38 int proplen; 39 40 /* new device trees should provide the physical-id attribute */ 41 prop = of_get_property(spe, "physical-id", &proplen); 42 if (proplen == 4) 43 return (u64)*prop; 44 45 /* celleb device tree provides the unit-id */ 46 prop = of_get_property(spe, "unit-id", &proplen); 47 if (proplen == 4) 48 return (u64)*prop; 49 50 /* legacy device trees provide the id in the reg attribute */ 51 prop = of_get_property(spe, "reg", &proplen); 52 if (proplen == 4) 53 return (u64)*prop; 54 55 return 0; 56 } 57 58 static void spu_unmap(struct spu *spu) 59 { 60 if (!firmware_has_feature(FW_FEATURE_LPAR)) 61 iounmap(spu->priv1); 62 iounmap(spu->priv2); 63 iounmap(spu->problem); 64 iounmap((__force u8 __iomem *)spu->local_store); 65 } 66 67 static int __init spu_map_interrupts_old(struct spu *spu, 68 struct device_node *np) 69 { 70 unsigned int isrc; 71 const u32 *tmp; 72 int nid; 73 74 /* Get the interrupt source unit from the device-tree */ 75 tmp = of_get_property(np, "isrc", NULL); 76 if (!tmp) 77 return -ENODEV; 78 isrc = tmp[0]; 79 80 tmp = of_get_property(np->parent->parent, "node-id", NULL); 81 if (!tmp) { 82 printk(KERN_WARNING "%s: can't find node-id\n", __func__); 83 nid = spu->node; 84 } else 85 nid = tmp[0]; 86 87 /* Add the node number */ 88 isrc |= nid << IIC_IRQ_NODE_SHIFT; 89 90 /* Now map interrupts of all 3 classes */ 91 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); 92 spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); 93 spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); 94 95 /* Right now, we only fail if class 2 failed */ 96 if (!spu->irqs[2]) 97 return -EINVAL; 98 99 return 0; 100 } 101 102 static void __iomem * __init spu_map_prop_old(struct spu *spu, 103 struct device_node *n, 104 const char *name) 105 { 106 const struct address_prop { 107 unsigned long address; 108 unsigned int len; 109 } __attribute__((packed)) *prop; 110 int proplen; 111 112 prop = of_get_property(n, name, &proplen); 113 if (prop == NULL || proplen != sizeof (struct address_prop)) 114 return NULL; 115 116 return ioremap(prop->address, prop->len); 117 } 118 119 static int __init spu_map_device_old(struct spu *spu) 120 { 121 struct device_node *node = spu->devnode; 122 const char *prop; 123 int ret; 124 125 ret = -ENODEV; 126 spu->name = of_get_property(node, "name", NULL); 127 if (!spu->name) 128 goto out; 129 130 prop = of_get_property(node, "local-store", NULL); 131 if (!prop) 132 goto out; 133 spu->local_store_phys = *(unsigned long *)prop; 134 135 /* we use local store as ram, not io memory */ 136 spu->local_store = (void __force *) 137 spu_map_prop_old(spu, node, "local-store"); 138 if (!spu->local_store) 139 goto out; 140 141 prop = of_get_property(node, "problem", NULL); 142 if (!prop) 143 goto out_unmap; 144 spu->problem_phys = *(unsigned long *)prop; 145 146 spu->problem = spu_map_prop_old(spu, node, "problem"); 147 if (!spu->problem) 148 goto out_unmap; 149 150 spu->priv2 = spu_map_prop_old(spu, node, "priv2"); 151 if (!spu->priv2) 152 goto out_unmap; 153 154 if (!firmware_has_feature(FW_FEATURE_LPAR)) { 155 spu->priv1 = spu_map_prop_old(spu, node, "priv1"); 156 if (!spu->priv1) 157 goto out_unmap; 158 } 159 160 ret = 0; 161 goto out; 162 163 out_unmap: 164 spu_unmap(spu); 165 out: 166 return ret; 167 } 168 169 static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) 170 { 171 int i; 172 173 for (i=0; i < 3; i++) { 174 spu->irqs[i] = irq_of_parse_and_map(np, i); 175 if (!spu->irqs[i]) 176 goto err; 177 } 178 return 0; 179 180 err: 181 pr_debug("failed to map irq %x for spu %s\n", i, spu->name); 182 for (; i >= 0; i--) { 183 if (spu->irqs[i]) 184 irq_dispose_mapping(spu->irqs[i]); 185 } 186 return -EINVAL; 187 } 188 189 static int __init spu_map_resource(struct spu *spu, int nr, 190 void __iomem** virt, unsigned long *phys) 191 { 192 struct device_node *np = spu->devnode; 193 struct resource resource = { }; 194 unsigned long len; 195 int ret; 196 197 ret = of_address_to_resource(np, nr, &resource); 198 if (ret) 199 return ret; 200 if (phys) 201 *phys = resource.start; 202 len = resource_size(&resource); 203 *virt = ioremap(resource.start, len); 204 if (!*virt) 205 return -EINVAL; 206 return 0; 207 } 208 209 static int __init spu_map_device(struct spu *spu) 210 { 211 struct device_node *np = spu->devnode; 212 int ret = -ENODEV; 213 214 spu->name = of_get_property(np, "name", NULL); 215 if (!spu->name) 216 goto out; 217 218 ret = spu_map_resource(spu, 0, (void __iomem**)&spu->local_store, 219 &spu->local_store_phys); 220 if (ret) { 221 pr_debug("spu_new: failed to map %pOF resource 0\n", 222 np); 223 goto out; 224 } 225 ret = spu_map_resource(spu, 1, (void __iomem**)&spu->problem, 226 &spu->problem_phys); 227 if (ret) { 228 pr_debug("spu_new: failed to map %pOF resource 1\n", 229 np); 230 goto out_unmap; 231 } 232 ret = spu_map_resource(spu, 2, (void __iomem**)&spu->priv2, NULL); 233 if (ret) { 234 pr_debug("spu_new: failed to map %pOF resource 2\n", 235 np); 236 goto out_unmap; 237 } 238 if (!firmware_has_feature(FW_FEATURE_LPAR)) 239 ret = spu_map_resource(spu, 3, 240 (void __iomem**)&spu->priv1, NULL); 241 if (ret) { 242 pr_debug("spu_new: failed to map %pOF resource 3\n", 243 np); 244 goto out_unmap; 245 } 246 pr_debug("spu_new: %pOF maps:\n", np); 247 pr_debug(" local store : 0x%016lx -> 0x%p\n", 248 spu->local_store_phys, spu->local_store); 249 pr_debug(" problem state : 0x%016lx -> 0x%p\n", 250 spu->problem_phys, spu->problem); 251 pr_debug(" priv2 : 0x%p\n", spu->priv2); 252 pr_debug(" priv1 : 0x%p\n", spu->priv1); 253 254 return 0; 255 256 out_unmap: 257 spu_unmap(spu); 258 out: 259 pr_debug("failed to map spe %s: %d\n", spu->name, ret); 260 return ret; 261 } 262 263 static int __init of_enumerate_spus(int (*fn)(void *data)) 264 { 265 int ret; 266 struct device_node *node; 267 unsigned int n = 0; 268 269 ret = -ENODEV; 270 for_each_node_by_type(node, "spe") { 271 ret = fn(node); 272 if (ret) { 273 printk(KERN_WARNING "%s: Error initializing %pOFn\n", 274 __func__, node); 275 of_node_put(node); 276 break; 277 } 278 n++; 279 } 280 return ret ? ret : n; 281 } 282 283 static int __init of_create_spu(struct spu *spu, void *data) 284 { 285 int ret; 286 struct device_node *spe = (struct device_node *)data; 287 static int legacy_map = 0, legacy_irq = 0; 288 289 spu->devnode = of_node_get(spe); 290 spu->spe_id = find_spu_unit_number(spe); 291 292 spu->node = of_node_to_nid(spe); 293 if (spu->node >= MAX_NUMNODES) { 294 printk(KERN_WARNING "SPE %pOF on node %d ignored," 295 " node number too big\n", spe, spu->node); 296 printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); 297 ret = -ENODEV; 298 goto out; 299 } 300 301 ret = spu_map_device(spu); 302 if (ret) { 303 if (!legacy_map) { 304 legacy_map = 1; 305 printk(KERN_WARNING "%s: Legacy device tree found, " 306 "trying to map old style\n", __func__); 307 } 308 ret = spu_map_device_old(spu); 309 if (ret) { 310 printk(KERN_ERR "Unable to map %s\n", 311 spu->name); 312 goto out; 313 } 314 } 315 316 ret = spu_map_interrupts(spu, spe); 317 if (ret) { 318 if (!legacy_irq) { 319 legacy_irq = 1; 320 printk(KERN_WARNING "%s: Legacy device tree found, " 321 "trying old style irq\n", __func__); 322 } 323 ret = spu_map_interrupts_old(spu, spe); 324 if (ret) { 325 printk(KERN_ERR "%s: could not map interrupts\n", 326 spu->name); 327 goto out_unmap; 328 } 329 } 330 331 pr_debug("Using SPE %s %p %p %p %p %d\n", spu->name, 332 spu->local_store, spu->problem, spu->priv1, 333 spu->priv2, spu->number); 334 goto out; 335 336 out_unmap: 337 spu_unmap(spu); 338 out: 339 return ret; 340 } 341 342 static int of_destroy_spu(struct spu *spu) 343 { 344 spu_unmap(spu); 345 of_node_put(spu->devnode); 346 return 0; 347 } 348 349 static void enable_spu_by_master_run(struct spu_context *ctx) 350 { 351 ctx->ops->master_start(ctx); 352 } 353 354 static void disable_spu_by_master_run(struct spu_context *ctx) 355 { 356 ctx->ops->master_stop(ctx); 357 } 358 359 /* Hardcoded affinity idxs for qs20 */ 360 #define QS20_SPES_PER_BE 8 361 static int qs20_reg_idxs[QS20_SPES_PER_BE] = { 0, 2, 4, 6, 7, 5, 3, 1 }; 362 static int qs20_reg_memory[QS20_SPES_PER_BE] = { 1, 1, 0, 0, 0, 0, 0, 0 }; 363 364 static struct spu *__init spu_lookup_reg(int node, u32 reg) 365 { 366 struct spu *spu; 367 const u32 *spu_reg; 368 369 list_for_each_entry(spu, &cbe_spu_info[node].spus, cbe_list) { 370 spu_reg = of_get_property(spu_devnode(spu), "reg", NULL); 371 if (*spu_reg == reg) 372 return spu; 373 } 374 return NULL; 375 } 376 377 static void __init init_affinity_qs20_harcoded(void) 378 { 379 int node, i; 380 struct spu *last_spu, *spu; 381 u32 reg; 382 383 for (node = 0; node < MAX_NUMNODES; node++) { 384 last_spu = NULL; 385 for (i = 0; i < QS20_SPES_PER_BE; i++) { 386 reg = qs20_reg_idxs[i]; 387 spu = spu_lookup_reg(node, reg); 388 if (!spu) 389 continue; 390 spu->has_mem_affinity = qs20_reg_memory[reg]; 391 if (last_spu) 392 list_add_tail(&spu->aff_list, 393 &last_spu->aff_list); 394 last_spu = spu; 395 } 396 } 397 } 398 399 static int __init of_has_vicinity(void) 400 { 401 struct device_node *dn; 402 403 for_each_node_by_type(dn, "spe") { 404 if (of_find_property(dn, "vicinity", NULL)) { 405 of_node_put(dn); 406 return 1; 407 } 408 } 409 return 0; 410 } 411 412 static struct spu *__init devnode_spu(int cbe, struct device_node *dn) 413 { 414 struct spu *spu; 415 416 list_for_each_entry(spu, &cbe_spu_info[cbe].spus, cbe_list) 417 if (spu_devnode(spu) == dn) 418 return spu; 419 return NULL; 420 } 421 422 static struct spu * __init 423 neighbour_spu(int cbe, struct device_node *target, struct device_node *avoid) 424 { 425 struct spu *spu; 426 struct device_node *spu_dn; 427 const phandle *vic_handles; 428 int lenp, i; 429 430 list_for_each_entry(spu, &cbe_spu_info[cbe].spus, cbe_list) { 431 spu_dn = spu_devnode(spu); 432 if (spu_dn == avoid) 433 continue; 434 vic_handles = of_get_property(spu_dn, "vicinity", &lenp); 435 for (i=0; i < (lenp / sizeof(phandle)); i++) { 436 if (vic_handles[i] == target->phandle) 437 return spu; 438 } 439 } 440 return NULL; 441 } 442 443 static void __init init_affinity_node(int cbe) 444 { 445 struct spu *spu, *last_spu; 446 struct device_node *vic_dn, *last_spu_dn; 447 phandle avoid_ph; 448 const phandle *vic_handles; 449 int lenp, i, added; 450 451 last_spu = list_first_entry(&cbe_spu_info[cbe].spus, struct spu, 452 cbe_list); 453 avoid_ph = 0; 454 for (added = 1; added < cbe_spu_info[cbe].n_spus; added++) { 455 last_spu_dn = spu_devnode(last_spu); 456 vic_handles = of_get_property(last_spu_dn, "vicinity", &lenp); 457 458 /* 459 * Walk through each phandle in vicinity property of the spu 460 * (typically two vicinity phandles per spe node) 461 */ 462 for (i = 0; i < (lenp / sizeof(phandle)); i++) { 463 if (vic_handles[i] == avoid_ph) 464 continue; 465 466 vic_dn = of_find_node_by_phandle(vic_handles[i]); 467 if (!vic_dn) 468 continue; 469 470 if (of_node_name_eq(vic_dn, "spe") ) { 471 spu = devnode_spu(cbe, vic_dn); 472 avoid_ph = last_spu_dn->phandle; 473 } else { 474 /* 475 * "mic-tm" and "bif0" nodes do not have 476 * vicinity property. So we need to find the 477 * spe which has vic_dn as neighbour, but 478 * skipping the one we came from (last_spu_dn) 479 */ 480 spu = neighbour_spu(cbe, vic_dn, last_spu_dn); 481 if (!spu) 482 continue; 483 if (of_node_name_eq(vic_dn, "mic-tm")) { 484 last_spu->has_mem_affinity = 1; 485 spu->has_mem_affinity = 1; 486 } 487 avoid_ph = vic_dn->phandle; 488 } 489 490 list_add_tail(&spu->aff_list, &last_spu->aff_list); 491 last_spu = spu; 492 break; 493 } 494 } 495 } 496 497 static void __init init_affinity_fw(void) 498 { 499 int cbe; 500 501 for (cbe = 0; cbe < MAX_NUMNODES; cbe++) 502 init_affinity_node(cbe); 503 } 504 505 static int __init init_affinity(void) 506 { 507 if (of_has_vicinity()) { 508 init_affinity_fw(); 509 } else { 510 if (of_machine_is_compatible("IBM,CPBW-1.0")) 511 init_affinity_qs20_harcoded(); 512 else 513 printk("No affinity configuration found\n"); 514 } 515 516 return 0; 517 } 518 519 const struct spu_management_ops spu_management_of_ops = { 520 .enumerate_spus = of_enumerate_spus, 521 .create_spu = of_create_spu, 522 .destroy_spu = of_destroy_spu, 523 .enable_spu = enable_spu_by_master_run, 524 .disable_spu = disable_spu_by_master_run, 525 .init_affinity = init_affinity, 526 }; 527