1 /* 2 * spu management operations for of based platforms 3 * 4 * (C) Copyright IBM Deutschland Entwicklung GmbH 2005 5 * Copyright 2006 Sony Corp. 6 * (C) Copyright 2007 TOSHIBA CORPORATION 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; version 2 of the License. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 */ 21 22 #include <linux/interrupt.h> 23 #include <linux/list.h> 24 #include <linux/module.h> 25 #include <linux/ptrace.h> 26 #include <linux/slab.h> 27 #include <linux/wait.h> 28 #include <linux/mm.h> 29 #include <linux/io.h> 30 #include <linux/mutex.h> 31 #include <linux/device.h> 32 33 #include <asm/spu.h> 34 #include <asm/spu_priv1.h> 35 #include <asm/firmware.h> 36 #include <asm/prom.h> 37 38 #include "interrupt.h" 39 40 struct device_node *spu_devnode(struct spu *spu) 41 { 42 return spu->devnode; 43 } 44 45 EXPORT_SYMBOL_GPL(spu_devnode); 46 47 static u64 __init find_spu_unit_number(struct device_node *spe) 48 { 49 const unsigned int *prop; 50 int proplen; 51 prop = of_get_property(spe, "unit-id", &proplen); 52 if (proplen == 4) 53 return (u64)*prop; 54 55 prop = of_get_property(spe, "reg", &proplen); 56 if (proplen == 4) 57 return (u64)*prop; 58 59 return 0; 60 } 61 62 static void spu_unmap(struct spu *spu) 63 { 64 if (!firmware_has_feature(FW_FEATURE_LPAR)) 65 iounmap(spu->priv1); 66 iounmap(spu->priv2); 67 iounmap(spu->problem); 68 iounmap((__force u8 __iomem *)spu->local_store); 69 } 70 71 static int __init spu_map_interrupts_old(struct spu *spu, 72 struct device_node *np) 73 { 74 unsigned int isrc; 75 const u32 *tmp; 76 int nid; 77 78 /* Get the interrupt source unit from the device-tree */ 79 tmp = of_get_property(np, "isrc", NULL); 80 if (!tmp) 81 return -ENODEV; 82 isrc = tmp[0]; 83 84 tmp = of_get_property(np->parent->parent, "node-id", NULL); 85 if (!tmp) { 86 printk(KERN_WARNING "%s: can't find node-id\n", __FUNCTION__); 87 nid = spu->node; 88 } else 89 nid = tmp[0]; 90 91 /* Add the node number */ 92 isrc |= nid << IIC_IRQ_NODE_SHIFT; 93 94 /* Now map interrupts of all 3 classes */ 95 spu->irqs[0] = irq_create_mapping(NULL, IIC_IRQ_CLASS_0 | isrc); 96 spu->irqs[1] = irq_create_mapping(NULL, IIC_IRQ_CLASS_1 | isrc); 97 spu->irqs[2] = irq_create_mapping(NULL, IIC_IRQ_CLASS_2 | isrc); 98 99 /* Right now, we only fail if class 2 failed */ 100 return spu->irqs[2] == NO_IRQ ? -EINVAL : 0; 101 } 102 103 static void __iomem * __init spu_map_prop_old(struct spu *spu, 104 struct device_node *n, 105 const char *name) 106 { 107 const struct address_prop { 108 unsigned long address; 109 unsigned int len; 110 } __attribute__((packed)) *prop; 111 int proplen; 112 113 prop = of_get_property(n, name, &proplen); 114 if (prop == NULL || proplen != sizeof (struct address_prop)) 115 return NULL; 116 117 return ioremap(prop->address, prop->len); 118 } 119 120 static int __init spu_map_device_old(struct spu *spu) 121 { 122 struct device_node *node = spu->devnode; 123 const char *prop; 124 int ret; 125 126 ret = -ENODEV; 127 spu->name = of_get_property(node, "name", NULL); 128 if (!spu->name) 129 goto out; 130 131 prop = of_get_property(node, "local-store", NULL); 132 if (!prop) 133 goto out; 134 spu->local_store_phys = *(unsigned long *)prop; 135 136 /* we use local store as ram, not io memory */ 137 spu->local_store = (void __force *) 138 spu_map_prop_old(spu, node, "local-store"); 139 if (!spu->local_store) 140 goto out; 141 142 prop = of_get_property(node, "problem", NULL); 143 if (!prop) 144 goto out_unmap; 145 spu->problem_phys = *(unsigned long *)prop; 146 147 spu->problem = spu_map_prop_old(spu, node, "problem"); 148 if (!spu->problem) 149 goto out_unmap; 150 151 spu->priv2 = spu_map_prop_old(spu, node, "priv2"); 152 if (!spu->priv2) 153 goto out_unmap; 154 155 if (!firmware_has_feature(FW_FEATURE_LPAR)) { 156 spu->priv1 = spu_map_prop_old(spu, node, "priv1"); 157 if (!spu->priv1) 158 goto out_unmap; 159 } 160 161 ret = 0; 162 goto out; 163 164 out_unmap: 165 spu_unmap(spu); 166 out: 167 return ret; 168 } 169 170 static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) 171 { 172 struct of_irq oirq; 173 int ret; 174 int i; 175 176 for (i=0; i < 3; i++) { 177 ret = of_irq_map_one(np, i, &oirq); 178 if (ret) { 179 pr_debug("spu_new: failed to get irq %d\n", i); 180 goto err; 181 } 182 ret = -EINVAL; 183 pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], 184 oirq.controller->full_name); 185 spu->irqs[i] = irq_create_of_mapping(oirq.controller, 186 oirq.specifier, oirq.size); 187 if (spu->irqs[i] == NO_IRQ) { 188 pr_debug("spu_new: failed to map it !\n"); 189 goto err; 190 } 191 } 192 return 0; 193 194 err: 195 pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, 196 spu->name); 197 for (; i >= 0; i--) { 198 if (spu->irqs[i] != NO_IRQ) 199 irq_dispose_mapping(spu->irqs[i]); 200 } 201 return ret; 202 } 203 204 static int spu_map_resource(struct spu *spu, int nr, 205 void __iomem** virt, unsigned long *phys) 206 { 207 struct device_node *np = spu->devnode; 208 struct resource resource = { }; 209 unsigned long len; 210 int ret; 211 212 ret = of_address_to_resource(np, nr, &resource); 213 if (ret) 214 return ret; 215 if (phys) 216 *phys = resource.start; 217 len = resource.end - resource.start + 1; 218 *virt = ioremap(resource.start, len); 219 if (!*virt) 220 return -EINVAL; 221 return 0; 222 } 223 224 static int __init spu_map_device(struct spu *spu) 225 { 226 struct device_node *np = spu->devnode; 227 int ret = -ENODEV; 228 229 spu->name = of_get_property(np, "name", NULL); 230 if (!spu->name) 231 goto out; 232 233 ret = spu_map_resource(spu, 0, (void __iomem**)&spu->local_store, 234 &spu->local_store_phys); 235 if (ret) { 236 pr_debug("spu_new: failed to map %s resource 0\n", 237 np->full_name); 238 goto out; 239 } 240 ret = spu_map_resource(spu, 1, (void __iomem**)&spu->problem, 241 &spu->problem_phys); 242 if (ret) { 243 pr_debug("spu_new: failed to map %s resource 1\n", 244 np->full_name); 245 goto out_unmap; 246 } 247 ret = spu_map_resource(spu, 2, (void __iomem**)&spu->priv2, NULL); 248 if (ret) { 249 pr_debug("spu_new: failed to map %s resource 2\n", 250 np->full_name); 251 goto out_unmap; 252 } 253 if (!firmware_has_feature(FW_FEATURE_LPAR)) 254 ret = spu_map_resource(spu, 3, 255 (void __iomem**)&spu->priv1, NULL); 256 if (ret) { 257 pr_debug("spu_new: failed to map %s resource 3\n", 258 np->full_name); 259 goto out_unmap; 260 } 261 pr_debug("spu_new: %s maps:\n", np->full_name); 262 pr_debug(" local store : 0x%016lx -> 0x%p\n", 263 spu->local_store_phys, spu->local_store); 264 pr_debug(" problem state : 0x%016lx -> 0x%p\n", 265 spu->problem_phys, spu->problem); 266 pr_debug(" priv2 : 0x%p\n", spu->priv2); 267 pr_debug(" priv1 : 0x%p\n", spu->priv1); 268 269 return 0; 270 271 out_unmap: 272 spu_unmap(spu); 273 out: 274 pr_debug("failed to map spe %s: %d\n", spu->name, ret); 275 return ret; 276 } 277 278 static int __init of_enumerate_spus(int (*fn)(void *data)) 279 { 280 int ret; 281 struct device_node *node; 282 unsigned int n = 0; 283 284 ret = -ENODEV; 285 for (node = of_find_node_by_type(NULL, "spe"); 286 node; node = of_find_node_by_type(node, "spe")) { 287 ret = fn(node); 288 if (ret) { 289 printk(KERN_WARNING "%s: Error initializing %s\n", 290 __FUNCTION__, node->name); 291 break; 292 } 293 n++; 294 } 295 return ret ? ret : n; 296 } 297 298 static int __init of_create_spu(struct spu *spu, void *data) 299 { 300 int ret; 301 struct device_node *spe = (struct device_node *)data; 302 static int legacy_map = 0, legacy_irq = 0; 303 304 spu->devnode = of_node_get(spe); 305 spu->spe_id = find_spu_unit_number(spe); 306 307 spu->node = of_node_to_nid(spe); 308 if (spu->node >= MAX_NUMNODES) { 309 printk(KERN_WARNING "SPE %s on node %d ignored," 310 " node number too big\n", spe->full_name, spu->node); 311 printk(KERN_WARNING "Check if CONFIG_NUMA is enabled.\n"); 312 ret = -ENODEV; 313 goto out; 314 } 315 316 ret = spu_map_device(spu); 317 if (ret) { 318 if (!legacy_map) { 319 legacy_map = 1; 320 printk(KERN_WARNING "%s: Legacy device tree found, " 321 "trying to map old style\n", __FUNCTION__); 322 } 323 ret = spu_map_device_old(spu); 324 if (ret) { 325 printk(KERN_ERR "Unable to map %s\n", 326 spu->name); 327 goto out; 328 } 329 } 330 331 ret = spu_map_interrupts(spu, spe); 332 if (ret) { 333 if (!legacy_irq) { 334 legacy_irq = 1; 335 printk(KERN_WARNING "%s: Legacy device tree found, " 336 "trying old style irq\n", __FUNCTION__); 337 } 338 ret = spu_map_interrupts_old(spu, spe); 339 if (ret) { 340 printk(KERN_ERR "%s: could not map interrupts", 341 spu->name); 342 goto out_unmap; 343 } 344 } 345 346 pr_debug("Using SPE %s %p %p %p %p %d\n", spu->name, 347 spu->local_store, spu->problem, spu->priv1, 348 spu->priv2, spu->number); 349 goto out; 350 351 out_unmap: 352 spu_unmap(spu); 353 out: 354 return ret; 355 } 356 357 static int of_destroy_spu(struct spu *spu) 358 { 359 spu_unmap(spu); 360 of_node_put(spu->devnode); 361 return 0; 362 } 363 364 const struct spu_management_ops spu_management_of_ops = { 365 .enumerate_spus = of_enumerate_spus, 366 .create_spu = of_create_spu, 367 .destroy_spu = of_destroy_spu, 368 }; 369