1/* 2 * Copyright (C) 2009 Extreme Engineering Solutions, Inc. 3 * 4 * X-ES board-specific functionality 5 * 6 * Based on mpc85xx_ds code from Freescale Semiconductor, Inc. 7 * 8 * Author: Nate Case <ncase@xes-inc.com> 9 * 10 * This is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License version 2 as 12 * published by the Free Software Foundation. 13 */ 14 15#include <linux/stddef.h> 16#include <linux/kernel.h> 17#include <linux/pci.h> 18#include <linux/kdev_t.h> 19#include <linux/delay.h> 20#include <linux/seq_file.h> 21#include <linux/interrupt.h> 22#include <linux/of_platform.h> 23 24#include <asm/system.h> 25#include <asm/time.h> 26#include <asm/machdep.h> 27#include <asm/pci-bridge.h> 28#include <mm/mmu_decl.h> 29#include <asm/prom.h> 30#include <asm/udbg.h> 31#include <asm/mpic.h> 32 33#include <sysdev/fsl_soc.h> 34#include <sysdev/fsl_pci.h> 35 36/* A few bit definitions needed for fixups on some boards */ 37#define MPC85xx_L2CTL_L2E 0x80000000 /* L2 enable */ 38#define MPC85xx_L2CTL_L2I 0x40000000 /* L2 flash invalidate */ 39#define MPC85xx_L2CTL_L2SIZ_MASK 0x30000000 /* L2 SRAM size (R/O) */ 40 41void __init xes_mpc85xx_pic_init(void) 42{ 43 struct mpic *mpic; 44 struct resource r; 45 struct device_node *np; 46 47 np = of_find_node_by_type(NULL, "open-pic"); 48 if (np == NULL) { 49 printk(KERN_ERR "Could not find open-pic node\n"); 50 return; 51 } 52 53 if (of_address_to_resource(np, 0, &r)) { 54 printk(KERN_ERR "Failed to map mpic register space\n"); 55 of_node_put(np); 56 return; 57 } 58 59 mpic = mpic_alloc(np, r.start, 60 MPIC_PRIMARY | MPIC_WANTS_RESET | 61 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 62 0, 256, " OpenPIC "); 63 BUG_ON(mpic == NULL); 64 of_node_put(np); 65 66 mpic_init(mpic); 67} 68 69static void xes_mpc85xx_configure_l2(void __iomem *l2_base) 70{ 71 volatile uint32_t ctl, tmp; 72 73 asm volatile("msync; isync"); 74 tmp = in_be32(l2_base); 75 76 /* 77 * xMon may have enabled part of L2 as SRAM, so we need to set it 78 * up for all cache mode just to be safe. 79 */ 80 printk(KERN_INFO "xes_mpc85xx: Enabling L2 as cache\n"); 81 82 ctl = MPC85xx_L2CTL_L2E | MPC85xx_L2CTL_L2I; 83 if (of_machine_is_compatible("MPC8540") || 84 of_machine_is_compatible("MPC8560")) 85 /* 86 * Assume L2 SRAM is used fully for cache, so set 87 * L2BLKSZ (bits 4:5) to match L2SIZ (bits 2:3). 88 */ 89 ctl |= (tmp & MPC85xx_L2CTL_L2SIZ_MASK) >> 2; 90 91 asm volatile("msync; isync"); 92 out_be32(l2_base, ctl); 93 asm volatile("msync; isync"); 94} 95 96static void xes_mpc85xx_fixups(void) 97{ 98 struct device_node *np; 99 int err; 100 101 /* 102 * Legacy xMon firmware on some X-ES boards does not enable L2 103 * as cache. We must ensure that they get enabled here. 104 */ 105 for_each_node_by_name(np, "l2-cache-controller") { 106 struct resource r[2]; 107 void __iomem *l2_base; 108 109 /* Only MPC8548, MPC8540, and MPC8560 boards are affected */ 110 if (!of_device_is_compatible(np, 111 "fsl,mpc8548-l2-cache-controller") && 112 !of_device_is_compatible(np, 113 "fsl,mpc8540-l2-cache-controller") && 114 !of_device_is_compatible(np, 115 "fsl,mpc8560-l2-cache-controller")) 116 continue; 117 118 err = of_address_to_resource(np, 0, &r[0]); 119 if (err) { 120 printk(KERN_WARNING "xes_mpc85xx: Could not get " 121 "resource for device tree node '%s'", 122 np->full_name); 123 continue; 124 } 125 126 l2_base = ioremap(r[0].start, r[0].end - r[0].start + 1); 127 128 xes_mpc85xx_configure_l2(l2_base); 129 } 130} 131 132#ifdef CONFIG_PCI 133static int primary_phb_addr; 134#endif 135 136/* 137 * Setup the architecture 138 */ 139#ifdef CONFIG_SMP 140extern void __init mpc85xx_smp_init(void); 141#endif 142static void __init xes_mpc85xx_setup_arch(void) 143{ 144#ifdef CONFIG_PCI 145 struct device_node *np; 146#endif 147 struct device_node *root; 148 const char *model = "Unknown"; 149 150 root = of_find_node_by_path("/"); 151 if (root == NULL) 152 return; 153 154 model = of_get_property(root, "model", NULL); 155 156 printk(KERN_INFO "X-ES MPC85xx-based single-board computer: %s\n", 157 model + strlen("xes,")); 158 159 xes_mpc85xx_fixups(); 160 161#ifdef CONFIG_PCI 162 for_each_node_by_type(np, "pci") { 163 if (of_device_is_compatible(np, "fsl,mpc8540-pci") || 164 of_device_is_compatible(np, "fsl,mpc8548-pcie")) { 165 struct resource rsrc; 166 of_address_to_resource(np, 0, &rsrc); 167 if ((rsrc.start & 0xfffff) == primary_phb_addr) 168 fsl_add_bridge(np, 1); 169 else 170 fsl_add_bridge(np, 0); 171 } 172 } 173#endif 174 175#ifdef CONFIG_SMP 176 mpc85xx_smp_init(); 177#endif 178} 179 180static struct of_device_id __initdata xes_mpc85xx_ids[] = { 181 { .type = "soc", }, 182 { .compatible = "soc", }, 183 { .compatible = "simple-bus", }, 184 { .compatible = "gianfar", }, 185 {}, 186}; 187 188static int __init xes_mpc85xx_publish_devices(void) 189{ 190 return of_platform_bus_probe(NULL, xes_mpc85xx_ids, NULL); 191} 192machine_device_initcall(xes_mpc8572, xes_mpc85xx_publish_devices); 193machine_device_initcall(xes_mpc8548, xes_mpc85xx_publish_devices); 194machine_device_initcall(xes_mpc8540, xes_mpc85xx_publish_devices); 195 196/* 197 * Called very early, device-tree isn't unflattened 198 */ 199static int __init xes_mpc8572_probe(void) 200{ 201 unsigned long root = of_get_flat_dt_root(); 202 203 if (of_flat_dt_is_compatible(root, "xes,MPC8572")) { 204#ifdef CONFIG_PCI 205 primary_phb_addr = 0x8000; 206#endif 207 return 1; 208 } else { 209 return 0; 210 } 211} 212 213static int __init xes_mpc8548_probe(void) 214{ 215 unsigned long root = of_get_flat_dt_root(); 216 217 if (of_flat_dt_is_compatible(root, "xes,MPC8548")) { 218#ifdef CONFIG_PCI 219 primary_phb_addr = 0xb000; 220#endif 221 return 1; 222 } else { 223 return 0; 224 } 225} 226 227static int __init xes_mpc8540_probe(void) 228{ 229 unsigned long root = of_get_flat_dt_root(); 230 231 if (of_flat_dt_is_compatible(root, "xes,MPC8540")) { 232#ifdef CONFIG_PCI 233 primary_phb_addr = 0xb000; 234#endif 235 return 1; 236 } else { 237 return 0; 238 } 239} 240 241define_machine(xes_mpc8572) { 242 .name = "X-ES MPC8572", 243 .probe = xes_mpc8572_probe, 244 .setup_arch = xes_mpc85xx_setup_arch, 245 .init_IRQ = xes_mpc85xx_pic_init, 246#ifdef CONFIG_PCI 247 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 248#endif 249 .get_irq = mpic_get_irq, 250 .restart = fsl_rstcr_restart, 251 .calibrate_decr = generic_calibrate_decr, 252 .progress = udbg_progress, 253}; 254 255define_machine(xes_mpc8548) { 256 .name = "X-ES MPC8548", 257 .probe = xes_mpc8548_probe, 258 .setup_arch = xes_mpc85xx_setup_arch, 259 .init_IRQ = xes_mpc85xx_pic_init, 260#ifdef CONFIG_PCI 261 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 262#endif 263 .get_irq = mpic_get_irq, 264 .restart = fsl_rstcr_restart, 265 .calibrate_decr = generic_calibrate_decr, 266 .progress = udbg_progress, 267}; 268 269define_machine(xes_mpc8540) { 270 .name = "X-ES MPC8540", 271 .probe = xes_mpc8540_probe, 272 .setup_arch = xes_mpc85xx_setup_arch, 273 .init_IRQ = xes_mpc85xx_pic_init, 274#ifdef CONFIG_PCI 275 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 276#endif 277 .get_irq = mpic_get_irq, 278 .restart = fsl_rstcr_restart, 279 .calibrate_decr = generic_calibrate_decr, 280 .progress = udbg_progress, 281}; 282