12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2f6d57916SPaul Mackerras /* 335499c01SPaul Mackerras * Powermac setup and early boot code plus other random bits. 4f6d57916SPaul Mackerras * 5f6d57916SPaul Mackerras * PowerPC version 6f6d57916SPaul Mackerras * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 7f6d57916SPaul Mackerras * 8f6d57916SPaul Mackerras * Adapted for Power Macintosh by Paul Mackerras 935499c01SPaul Mackerras * Copyright (C) 1996 Paul Mackerras (paulus@samba.org) 10f6d57916SPaul Mackerras * 11f6d57916SPaul Mackerras * Derived from "arch/alpha/kernel/setup.c" 12f6d57916SPaul Mackerras * Copyright (C) 1995 Linus Torvalds 13f6d57916SPaul Mackerras * 14f6d57916SPaul Mackerras * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) 15f6d57916SPaul Mackerras */ 16f6d57916SPaul Mackerras 17f6d57916SPaul Mackerras /* 18f6d57916SPaul Mackerras * bootup setup stuff.. 19f6d57916SPaul Mackerras */ 20f6d57916SPaul Mackerras 21f6d57916SPaul Mackerras #include <linux/init.h> 22f6d57916SPaul Mackerras #include <linux/errno.h> 23f6d57916SPaul Mackerras #include <linux/sched.h> 24f6d57916SPaul Mackerras #include <linux/kernel.h> 25f6d57916SPaul Mackerras #include <linux/mm.h> 26f6d57916SPaul Mackerras #include <linux/stddef.h> 27f6d57916SPaul Mackerras #include <linux/unistd.h> 28f6d57916SPaul Mackerras #include <linux/ptrace.h> 2966b15db6SPaul Gortmaker #include <linux/export.h> 30f6d57916SPaul Mackerras #include <linux/user.h> 31f6d57916SPaul Mackerras #include <linux/tty.h> 32f6d57916SPaul Mackerras #include <linux/string.h> 33f6d57916SPaul Mackerras #include <linux/delay.h> 34f6d57916SPaul Mackerras #include <linux/ioport.h> 35f6d57916SPaul Mackerras #include <linux/major.h> 36f6d57916SPaul Mackerras #include <linux/initrd.h> 37f6d57916SPaul Mackerras #include <linux/vt_kern.h> 38f6d57916SPaul Mackerras #include <linux/console.h> 39f6d57916SPaul Mackerras #include <linux/pci.h> 40f6d57916SPaul Mackerras #include <linux/adb.h> 41f6d57916SPaul Mackerras #include <linux/cuda.h> 42f6d57916SPaul Mackerras #include <linux/pmu.h> 43f6d57916SPaul Mackerras #include <linux/irq.h> 44f6d57916SPaul Mackerras #include <linux/seq_file.h> 45f6d57916SPaul Mackerras #include <linux/root_dev.h> 46f6d57916SPaul Mackerras #include <linux/bitops.h> 47f6d57916SPaul Mackerras #include <linux/suspend.h> 48*81d7cac4SRob Herring #include <linux/of.h> 495f867dc7SJon Loeliger #include <linux/of_platform.h> 50f6d57916SPaul Mackerras 51f6d57916SPaul Mackerras #include <asm/reg.h> 52f6d57916SPaul Mackerras #include <asm/sections.h> 53f6d57916SPaul Mackerras #include <asm/io.h> 54f6d57916SPaul Mackerras #include <asm/pci-bridge.h> 55f6d57916SPaul Mackerras #include <asm/ohare.h> 56f6d57916SPaul Mackerras #include <asm/mediabay.h> 57f6d57916SPaul Mackerras #include <asm/machdep.h> 58f6d57916SPaul Mackerras #include <asm/dma.h> 59f6d57916SPaul Mackerras #include <asm/cputable.h> 60f6d57916SPaul Mackerras #include <asm/btext.h> 61f6d57916SPaul Mackerras #include <asm/pmac_feature.h> 62f6d57916SPaul Mackerras #include <asm/time.h> 63f6d57916SPaul Mackerras #include <asm/mmu_context.h> 6435499c01SPaul Mackerras #include <asm/iommu.h> 6535499c01SPaul Mackerras #include <asm/smu.h> 6635499c01SPaul Mackerras #include <asm/pmc.h> 6751d3082fSBenjamin Herrenschmidt #include <asm/udbg.h> 68f6d57916SPaul Mackerras 693c3f42d6SPaul Mackerras #include "pmac.h" 70f6d57916SPaul Mackerras 71f6d57916SPaul Mackerras #undef SHOW_GATWICK_IRQS 72f6d57916SPaul Mackerras 7359dc2d94SChen Lifu static int has_l2cache; 74f6d57916SPaul Mackerras 75d2515c80SOlaf Hering int pmac_newworld; 76f6d57916SPaul Mackerras 77f6d57916SPaul Mackerras static int current_root_goodness = -1; 78f6d57916SPaul Mackerras 79f5524c3fSChristoph Hellwig /* sda1 - slightly silly choice */ 80f5524c3fSChristoph Hellwig #define DEFAULT_ROOT_DEVICE MKDEV(SCSI_DISK0_MAJOR, 1) 81f6d57916SPaul Mackerras 82f6d57916SPaul Mackerras sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; 8335499c01SPaul Mackerras EXPORT_SYMBOL(sys_ctrler); 8435499c01SPaul Mackerras 850dd194d0SPaul Mackerras static void pmac_show_cpuinfo(struct seq_file *m) 86f6d57916SPaul Mackerras { 87f6d57916SPaul Mackerras struct device_node *np; 88018a3d1dSJeremy Kerr const char *pp; 89f6d57916SPaul Mackerras int plen; 900dd194d0SPaul Mackerras int mbmodel; 910dd194d0SPaul Mackerras unsigned int mbflags; 92f6d57916SPaul Mackerras char* mbname; 93f6d57916SPaul Mackerras 940dd194d0SPaul Mackerras mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, 950dd194d0SPaul Mackerras PMAC_MB_INFO_MODEL, 0); 960dd194d0SPaul Mackerras mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, 970dd194d0SPaul Mackerras PMAC_MB_INFO_FLAGS, 0); 980dd194d0SPaul Mackerras if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, 990dd194d0SPaul Mackerras (long) &mbname) != 0) 100f6d57916SPaul Mackerras mbname = "Unknown"; 101f6d57916SPaul Mackerras 102f6d57916SPaul Mackerras /* find motherboard type */ 103f6d57916SPaul Mackerras seq_printf(m, "machine\t\t: "); 1040dd194d0SPaul Mackerras np = of_find_node_by_path("/"); 105f6d57916SPaul Mackerras if (np != NULL) { 106e2eb6392SStephen Rothwell pp = of_get_property(np, "model", NULL); 107f6d57916SPaul Mackerras if (pp != NULL) 108f6d57916SPaul Mackerras seq_printf(m, "%s\n", pp); 109f6d57916SPaul Mackerras else 110f6d57916SPaul Mackerras seq_printf(m, "PowerMac\n"); 111e2eb6392SStephen Rothwell pp = of_get_property(np, "compatible", &plen); 112f6d57916SPaul Mackerras if (pp != NULL) { 113f6d57916SPaul Mackerras seq_printf(m, "motherboard\t:"); 114f6d57916SPaul Mackerras while (plen > 0) { 115f6d57916SPaul Mackerras int l = strlen(pp) + 1; 116f6d57916SPaul Mackerras seq_printf(m, " %s", pp); 117f6d57916SPaul Mackerras plen -= l; 118f6d57916SPaul Mackerras pp += l; 119f6d57916SPaul Mackerras } 120f6d57916SPaul Mackerras seq_printf(m, "\n"); 121f6d57916SPaul Mackerras } 1220dd194d0SPaul Mackerras of_node_put(np); 123f6d57916SPaul Mackerras } else 124f6d57916SPaul Mackerras seq_printf(m, "PowerMac\n"); 125f6d57916SPaul Mackerras 126f6d57916SPaul Mackerras /* print parsed model */ 127f6d57916SPaul Mackerras seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); 128f6d57916SPaul Mackerras seq_printf(m, "pmac flags\t: %08x\n", mbflags); 129f6d57916SPaul Mackerras 130f6d57916SPaul Mackerras /* find l2 cache info */ 1310dd194d0SPaul Mackerras np = of_find_node_by_name(NULL, "l2-cache"); 1320dd194d0SPaul Mackerras if (np == NULL) 1330dd194d0SPaul Mackerras np = of_find_node_by_type(NULL, "cache"); 1340dd194d0SPaul Mackerras if (np != NULL) { 135e2eb6392SStephen Rothwell const unsigned int *ic = 136e2eb6392SStephen Rothwell of_get_property(np, "i-cache-size", NULL); 137e2eb6392SStephen Rothwell const unsigned int *dc = 138e2eb6392SStephen Rothwell of_get_property(np, "d-cache-size", NULL); 139f6d57916SPaul Mackerras seq_printf(m, "L2 cache\t:"); 140f6d57916SPaul Mackerras has_l2cache = 1; 1414d57e351SRob Herring if (of_property_read_bool(np, "cache-unified") && dc) { 142f6d57916SPaul Mackerras seq_printf(m, " %dK unified", *dc / 1024); 143f6d57916SPaul Mackerras } else { 144f6d57916SPaul Mackerras if (ic) 145f6d57916SPaul Mackerras seq_printf(m, " %dK instruction", *ic / 1024); 146f6d57916SPaul Mackerras if (dc) 147f6d57916SPaul Mackerras seq_printf(m, "%s %dK data", 148f6d57916SPaul Mackerras (ic? " +": ""), *dc / 1024); 149f6d57916SPaul Mackerras } 150e2eb6392SStephen Rothwell pp = of_get_property(np, "ram-type", NULL); 151f6d57916SPaul Mackerras if (pp) 152f6d57916SPaul Mackerras seq_printf(m, " %s", pp); 153f6d57916SPaul Mackerras seq_printf(m, "\n"); 1540dd194d0SPaul Mackerras of_node_put(np); 155f6d57916SPaul Mackerras } 156f6d57916SPaul Mackerras 157f6d57916SPaul Mackerras /* Indicate newworld/oldworld */ 158f6d57916SPaul Mackerras seq_printf(m, "pmac-generation\t: %s\n", 159f6d57916SPaul Mackerras pmac_newworld ? "NewWorld" : "OldWorld"); 160f6d57916SPaul Mackerras } 161f6d57916SPaul Mackerras 16235499c01SPaul Mackerras #ifndef CONFIG_ADB_CUDA 1637da1d1ddSNick Child int __init find_via_cuda(void) 16435499c01SPaul Mackerras { 16530686ba6SStephen Rothwell struct device_node *dn = of_find_node_by_name(NULL, "via-cuda"); 16630686ba6SStephen Rothwell 16730686ba6SStephen Rothwell if (!dn) 16835499c01SPaul Mackerras return 0; 16930686ba6SStephen Rothwell of_node_put(dn); 17035499c01SPaul Mackerras printk("WARNING ! Your machine is CUDA-based but your kernel\n"); 17135499c01SPaul Mackerras printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); 17235499c01SPaul Mackerras return 0; 17335499c01SPaul Mackerras } 17435499c01SPaul Mackerras #endif 17535499c01SPaul Mackerras 17635499c01SPaul Mackerras #ifndef CONFIG_ADB_PMU 1777da1d1ddSNick Child int __init find_via_pmu(void) 17835499c01SPaul Mackerras { 17930686ba6SStephen Rothwell struct device_node *dn = of_find_node_by_name(NULL, "via-pmu"); 18030686ba6SStephen Rothwell 18130686ba6SStephen Rothwell if (!dn) 18235499c01SPaul Mackerras return 0; 18330686ba6SStephen Rothwell of_node_put(dn); 18435499c01SPaul Mackerras printk("WARNING ! Your machine is PMU-based but your kernel\n"); 18535499c01SPaul Mackerras printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); 186a575b807SPaul Mackerras return 0; 18735499c01SPaul Mackerras } 18835499c01SPaul Mackerras #endif 18935499c01SPaul Mackerras 19035499c01SPaul Mackerras #ifndef CONFIG_PMAC_SMU 191b346f571SNick Child int __init smu_init(void) 19235499c01SPaul Mackerras { 19335499c01SPaul Mackerras /* should check and warn if SMU is present */ 19435499c01SPaul Mackerras return 0; 19535499c01SPaul Mackerras } 19635499c01SPaul Mackerras #endif 19735499c01SPaul Mackerras 19835499c01SPaul Mackerras #ifdef CONFIG_PPC32 199f6d57916SPaul Mackerras static volatile u32 *sysctrl_regs; 200f6d57916SPaul Mackerras 20135499c01SPaul Mackerras static void __init ohare_init(void) 202f6d57916SPaul Mackerras { 20330686ba6SStephen Rothwell struct device_node *dn; 20430686ba6SStephen Rothwell 205f6d57916SPaul Mackerras /* this area has the CPU identification register 206f6d57916SPaul Mackerras and some registers used by smp boards */ 207f6d57916SPaul Mackerras sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); 208f6d57916SPaul Mackerras 20935499c01SPaul Mackerras /* 21035499c01SPaul Mackerras * Turn on the L2 cache. 21135499c01SPaul Mackerras * We assume that we have a PSX memory controller iff 21235499c01SPaul Mackerras * we have an ohare I/O controller. 21335499c01SPaul Mackerras */ 21430686ba6SStephen Rothwell dn = of_find_node_by_name(NULL, "ohare"); 21530686ba6SStephen Rothwell if (dn) { 21630686ba6SStephen Rothwell of_node_put(dn); 21735499c01SPaul Mackerras if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { 21835499c01SPaul Mackerras if (sysctrl_regs[4] & 0x10) 21935499c01SPaul Mackerras sysctrl_regs[4] |= 0x04000020; 22035499c01SPaul Mackerras else 22135499c01SPaul Mackerras sysctrl_regs[4] |= 0x04000000; 22235499c01SPaul Mackerras if(has_l2cache) 22335499c01SPaul Mackerras printk(KERN_INFO "Level 2 cache enabled\n"); 22435499c01SPaul Mackerras } 22535499c01SPaul Mackerras } 22635499c01SPaul Mackerras } 227f6d57916SPaul Mackerras 22835499c01SPaul Mackerras static void __init l2cr_init(void) 22935499c01SPaul Mackerras { 230f6d57916SPaul Mackerras /* Checks "l2cr-value" property in the registry */ 231f6d57916SPaul Mackerras if (cpu_has_feature(CPU_FTR_L2CR)) { 232a94fe366SRob Herring struct device_node *np; 233a94fe366SRob Herring 234a94fe366SRob Herring for_each_of_cpu_node(np) { 235018a3d1dSJeremy Kerr const unsigned int *l2cr = 236e2eb6392SStephen Rothwell of_get_property(np, "l2cr-value", NULL); 237d8731527SMathieu Malaterre if (l2cr) { 238f6d57916SPaul Mackerras _set_L2CR(0); 23959dc2d94SChen Lifu _set_L2CR(*l2cr); 24059dc2d94SChen Lifu pr_info("L2CR overridden (0x%x), backside cache is %s\n", 24159dc2d94SChen Lifu *l2cr, ((*l2cr) & 0x80000000) ? 24259dc2d94SChen Lifu "enabled" : "disabled"); 243f6d57916SPaul Mackerras } 2441658ab66SStephen Rothwell of_node_put(np); 245a94fe366SRob Herring break; 246f6d57916SPaul Mackerras } 247f6d57916SPaul Mackerras } 24835499c01SPaul Mackerras } 24935499c01SPaul Mackerras #endif 25035499c01SPaul Mackerras 251ff38e7c8SArnd Bergmann static void __init pmac_setup_arch(void) 25235499c01SPaul Mackerras { 253a575b807SPaul Mackerras struct device_node *cpu, *ic; 254018a3d1dSJeremy Kerr const int *fp; 25535499c01SPaul Mackerras unsigned long pvr; 25635499c01SPaul Mackerras 25735499c01SPaul Mackerras pvr = PVR_VER(mfspr(SPRN_PVR)); 25835499c01SPaul Mackerras 25935499c01SPaul Mackerras /* Set loops_per_jiffy to a half-way reasonable value, 26035499c01SPaul Mackerras for use until calibrate_delay gets called. */ 26135499c01SPaul Mackerras loops_per_jiffy = 50000000 / HZ; 262a94fe366SRob Herring 263a94fe366SRob Herring for_each_of_cpu_node(cpu) { 264e2eb6392SStephen Rothwell fp = of_get_property(cpu, "clock-frequency", NULL); 26535499c01SPaul Mackerras if (fp != NULL) { 26635499c01SPaul Mackerras if (pvr >= 0x30 && pvr < 0x80) 26735499c01SPaul Mackerras /* PPC970 etc. */ 26835499c01SPaul Mackerras loops_per_jiffy = *fp / (3 * HZ); 26935499c01SPaul Mackerras else if (pvr == 4 || pvr >= 8) 27035499c01SPaul Mackerras /* 604, G3, G4 etc. */ 27135499c01SPaul Mackerras loops_per_jiffy = *fp / HZ; 27235499c01SPaul Mackerras else 2738b14e1dfSChristophe Leroy /* 603, etc. */ 27435499c01SPaul Mackerras loops_per_jiffy = *fp / (2 * HZ); 27535499c01SPaul Mackerras of_node_put(cpu); 276a94fe366SRob Herring break; 277a94fe366SRob Herring } 27835499c01SPaul Mackerras } 27935499c01SPaul Mackerras 280a575b807SPaul Mackerras /* See if newworld or oldworld */ 28122059a90SMichael Ellerman ic = of_find_node_with_property(NULL, "interrupt-controller"); 282d2515c80SOlaf Hering if (ic) { 283d2515c80SOlaf Hering pmac_newworld = 1; 284a575b807SPaul Mackerras of_node_put(ic); 285d2515c80SOlaf Hering } 286a575b807SPaul Mackerras 28735499c01SPaul Mackerras #ifdef CONFIG_PPC32 28835499c01SPaul Mackerras ohare_init(); 28935499c01SPaul Mackerras l2cr_init(); 29035499c01SPaul Mackerras #endif /* CONFIG_PPC32 */ 29135499c01SPaul Mackerras 292f6d57916SPaul Mackerras find_via_cuda(); 293f6d57916SPaul Mackerras find_via_pmu(); 29435499c01SPaul Mackerras smu_init(); 29535499c01SPaul Mackerras 29620e07af7SFinn Thain #if IS_ENABLED(CONFIG_NVRAM) 297f6d57916SPaul Mackerras pmac_nvram_init(); 298f6d57916SPaul Mackerras #endif 29935499c01SPaul Mackerras #ifdef CONFIG_PPC32 300f6d57916SPaul Mackerras #ifdef CONFIG_BLK_DEV_INITRD 301f6d57916SPaul Mackerras if (initrd_start) 302f6d57916SPaul Mackerras ROOT_DEV = Root_RAM0; 303f6d57916SPaul Mackerras else 304f6d57916SPaul Mackerras #endif 305f6d57916SPaul Mackerras ROOT_DEV = DEFAULT_ROOT_DEVICE; 30635499c01SPaul Mackerras #endif 307f6d57916SPaul Mackerras 308e8222502SBenjamin Herrenschmidt #ifdef CONFIG_ADB 3093e47d147SAnton Blanchard if (strstr(boot_command_line, "adb_sync")) { 310e8222502SBenjamin Herrenschmidt extern int __adb_probe_sync; 311e8222502SBenjamin Herrenschmidt __adb_probe_sync = 1; 312e8222502SBenjamin Herrenschmidt } 313e8222502SBenjamin Herrenschmidt #endif /* CONFIG_ADB */ 314f6d57916SPaul Mackerras } 315f6d57916SPaul Mackerras 31635499c01SPaul Mackerras static int initializing = 1; 31735499c01SPaul Mackerras 318f6d57916SPaul Mackerras static int pmac_late_init(void) 319f6d57916SPaul Mackerras { 320f6d57916SPaul Mackerras initializing = 0; 321f6d57916SPaul Mackerras return 0; 322f6d57916SPaul Mackerras } 323d518b717SGrant Likely machine_late_initcall(powermac, pmac_late_init); 324f6d57916SPaul Mackerras 325f72cf3f1SMathieu Malaterre void note_bootable_part(dev_t dev, int part, int goodness); 326d7418031SStephen Rothwell /* 327bd721ea7SFabian Frederick * This is __ref because we check for "initializing" before 328d7418031SStephen Rothwell * touching any of the __init sensitive things and "initializing" 329d7418031SStephen Rothwell * will be false after __init time. This can't be __init because it 330d7418031SStephen Rothwell * can be called whenever a disk is first accessed. 331d7418031SStephen Rothwell */ 332bd721ea7SFabian Frederick void __ref note_bootable_part(dev_t dev, int part, int goodness) 333f6d57916SPaul Mackerras { 334f6d57916SPaul Mackerras char *p; 335f6d57916SPaul Mackerras 336f6d57916SPaul Mackerras if (!initializing) 337f6d57916SPaul Mackerras return; 338f6d57916SPaul Mackerras if ((goodness <= current_root_goodness) && 339f6d57916SPaul Mackerras ROOT_DEV != DEFAULT_ROOT_DEVICE) 340f6d57916SPaul Mackerras return; 341b8757b21SAlon Bar-Lev p = strstr(boot_command_line, "root="); 342b8757b21SAlon Bar-Lev if (p != NULL && (p == boot_command_line || p[-1] == ' ')) 343f6d57916SPaul Mackerras return; 344f6d57916SPaul Mackerras 345f6d57916SPaul Mackerras ROOT_DEV = dev + part; 346f6d57916SPaul Mackerras current_root_goodness = goodness; 347f6d57916SPaul Mackerras } 348f6d57916SPaul Mackerras 34935499c01SPaul Mackerras #ifdef CONFIG_ADB_CUDA 35095ec77c0SDaniel Axtens static void __noreturn cuda_restart(void) 351f6d57916SPaul Mackerras { 352f6d57916SPaul Mackerras struct adb_request req; 353f6d57916SPaul Mackerras 35435499c01SPaul Mackerras cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); 355f6d57916SPaul Mackerras for (;;) 356f6d57916SPaul Mackerras cuda_poll(); 35735499c01SPaul Mackerras } 35835499c01SPaul Mackerras 35995ec77c0SDaniel Axtens static void __noreturn cuda_shutdown(void) 36035499c01SPaul Mackerras { 36135499c01SPaul Mackerras struct adb_request req; 36235499c01SPaul Mackerras 36335499c01SPaul Mackerras cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); 36435499c01SPaul Mackerras for (;;) 36535499c01SPaul Mackerras cuda_poll(); 36635499c01SPaul Mackerras } 36735499c01SPaul Mackerras 36835499c01SPaul Mackerras #else 36935499c01SPaul Mackerras #define cuda_restart() 37035499c01SPaul Mackerras #define cuda_shutdown() 37135499c01SPaul Mackerras #endif 37235499c01SPaul Mackerras 37335499c01SPaul Mackerras #ifndef CONFIG_ADB_PMU 37435499c01SPaul Mackerras #define pmu_restart() 37535499c01SPaul Mackerras #define pmu_shutdown() 37635499c01SPaul Mackerras #endif 37735499c01SPaul Mackerras 37835499c01SPaul Mackerras #ifndef CONFIG_PMAC_SMU 37935499c01SPaul Mackerras #define smu_restart() 38035499c01SPaul Mackerras #define smu_shutdown() 38135499c01SPaul Mackerras #endif 38235499c01SPaul Mackerras 38395ec77c0SDaniel Axtens static void __noreturn pmac_restart(char *cmd) 38435499c01SPaul Mackerras { 38535499c01SPaul Mackerras switch (sys_ctrler) { 38635499c01SPaul Mackerras case SYS_CTRLER_CUDA: 38735499c01SPaul Mackerras cuda_restart(); 388f6d57916SPaul Mackerras break; 389f6d57916SPaul Mackerras case SYS_CTRLER_PMU: 390f6d57916SPaul Mackerras pmu_restart(); 391f6d57916SPaul Mackerras break; 39235499c01SPaul Mackerras case SYS_CTRLER_SMU: 39335499c01SPaul Mackerras smu_restart(); 39435499c01SPaul Mackerras break; 395f6d57916SPaul Mackerras default: ; 396f6d57916SPaul Mackerras } 39795ec77c0SDaniel Axtens while (1) ; 398f6d57916SPaul Mackerras } 399f6d57916SPaul Mackerras 40095ec77c0SDaniel Axtens static void __noreturn pmac_power_off(void) 401f6d57916SPaul Mackerras { 402f6d57916SPaul Mackerras switch (sys_ctrler) { 403f6d57916SPaul Mackerras case SYS_CTRLER_CUDA: 40435499c01SPaul Mackerras cuda_shutdown(); 405f6d57916SPaul Mackerras break; 406f6d57916SPaul Mackerras case SYS_CTRLER_PMU: 407f6d57916SPaul Mackerras pmu_shutdown(); 408f6d57916SPaul Mackerras break; 40935499c01SPaul Mackerras case SYS_CTRLER_SMU: 41035499c01SPaul Mackerras smu_shutdown(); 41135499c01SPaul Mackerras break; 412f6d57916SPaul Mackerras default: ; 413f6d57916SPaul Mackerras } 41495ec77c0SDaniel Axtens while (1) ; 415f6d57916SPaul Mackerras } 416f6d57916SPaul Mackerras 41795ec77c0SDaniel Axtens static void __noreturn 418f6d57916SPaul Mackerras pmac_halt(void) 419f6d57916SPaul Mackerras { 420f6d57916SPaul Mackerras pmac_power_off(); 421f6d57916SPaul Mackerras } 422f6d57916SPaul Mackerras 42335499c01SPaul Mackerras /* 42435499c01SPaul Mackerras * Early initialization. 42535499c01SPaul Mackerras */ 426f2d57694SBenjamin Herrenschmidt static void __init pmac_init(void) 427f6d57916SPaul Mackerras { 42851d3082fSBenjamin Herrenschmidt /* Enable early btext debug if requested */ 4293e47d147SAnton Blanchard if (strstr(boot_command_line, "btextdbg")) { 43051d3082fSBenjamin Herrenschmidt udbg_adb_init_early(); 43151d3082fSBenjamin Herrenschmidt register_early_udbg_console(); 43235499c01SPaul Mackerras } 43335499c01SPaul Mackerras 43451d3082fSBenjamin Herrenschmidt /* Probe motherboard chipset */ 43551d3082fSBenjamin Herrenschmidt pmac_feature_init(); 43651d3082fSBenjamin Herrenschmidt 43751d3082fSBenjamin Herrenschmidt /* Initialize debug stuff */ 4383e47d147SAnton Blanchard udbg_scc_init(!!strstr(boot_command_line, "sccdbg")); 4393e47d147SAnton Blanchard udbg_adb_init(!!strstr(boot_command_line, "btextdbg")); 44051d3082fSBenjamin Herrenschmidt 44151d3082fSBenjamin Herrenschmidt #ifdef CONFIG_PPC64 442e63f26d3SDaniel Axtens iommu_init_early_dart(&pmac_pci_controller_ops); 44335499c01SPaul Mackerras #endif 4447ccbe504SBenjamin Herrenschmidt 4457ccbe504SBenjamin Herrenschmidt /* SMP Init has to be done early as we need to patch up 446828a6986SAnton Blanchard * cpu_possible_mask before interrupt stacks are allocated 4477ccbe504SBenjamin Herrenschmidt * or kaboom... 4487ccbe504SBenjamin Herrenschmidt */ 4497ccbe504SBenjamin Herrenschmidt #ifdef CONFIG_SMP 4507ccbe504SBenjamin Herrenschmidt pmac_setup_smp(); 4517ccbe504SBenjamin Herrenschmidt #endif 45235499c01SPaul Mackerras } 45335499c01SPaul Mackerras 45435499c01SPaul Mackerras static int __init pmac_declare_of_platform_devices(void) 455f6d57916SPaul Mackerras { 456a28d3af2SBenjamin Herrenschmidt struct device_node *np; 457f6d57916SPaul Mackerras 458730745a5SBenjamin Herrenschmidt np = of_find_node_by_name(NULL, "valkyrie"); 4593631cb83SJulia Lawall if (np) { 46035499c01SPaul Mackerras of_platform_device_create(np, "valkyrie", NULL); 4613631cb83SJulia Lawall of_node_put(np); 4623631cb83SJulia Lawall } 463730745a5SBenjamin Herrenschmidt np = of_find_node_by_name(NULL, "platinum"); 4643631cb83SJulia Lawall if (np) { 46535499c01SPaul Mackerras of_platform_device_create(np, "platinum", NULL); 4663631cb83SJulia Lawall of_node_put(np); 4673631cb83SJulia Lawall } 46835499c01SPaul Mackerras np = of_find_node_by_type(NULL, "smu"); 46935499c01SPaul Mackerras if (np) { 47035499c01SPaul Mackerras of_platform_device_create(np, "smu", NULL); 47135499c01SPaul Mackerras of_node_put(np); 47235499c01SPaul Mackerras } 47398b14d6bSMarc Zyngier np = of_find_node_by_type(NULL, "fcu"); 47498b14d6bSMarc Zyngier if (np == NULL) { 47598b14d6bSMarc Zyngier /* Some machines have strangely broken device-tree */ 47698b14d6bSMarc Zyngier np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); 47798b14d6bSMarc Zyngier } 47898b14d6bSMarc Zyngier if (np) { 47998b14d6bSMarc Zyngier of_platform_device_create(np, "temperature", NULL); 48098b14d6bSMarc Zyngier of_node_put(np); 48198b14d6bSMarc Zyngier } 482f6d57916SPaul Mackerras 483f6d57916SPaul Mackerras return 0; 484f6d57916SPaul Mackerras } 485d518b717SGrant Likely machine_device_initcall(powermac, pmac_declare_of_platform_devices); 48635499c01SPaul Mackerras 487025d7917SBenjamin Herrenschmidt #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE 488025d7917SBenjamin Herrenschmidt /* 489025d7917SBenjamin Herrenschmidt * This is called very early, as part of console_init() (typically just after 490025d7917SBenjamin Herrenschmidt * time_init()). This function is respondible for trying to find a good 491025d7917SBenjamin Herrenschmidt * default console on serial ports. It tries to match the open firmware 492025d7917SBenjamin Herrenschmidt * default output with one of the available serial console drivers. 493025d7917SBenjamin Herrenschmidt */ 494025d7917SBenjamin Herrenschmidt static int __init check_pmac_serial_console(void) 495025d7917SBenjamin Herrenschmidt { 496025d7917SBenjamin Herrenschmidt struct device_node *prom_stdout = NULL; 497025d7917SBenjamin Herrenschmidt int offset = 0; 498025d7917SBenjamin Herrenschmidt const char *name; 499025d7917SBenjamin Herrenschmidt #ifdef CONFIG_SERIAL_PMACZILOG_TTYS 500025d7917SBenjamin Herrenschmidt char *devname = "ttyS"; 501025d7917SBenjamin Herrenschmidt #else 502025d7917SBenjamin Herrenschmidt char *devname = "ttyPZ"; 503025d7917SBenjamin Herrenschmidt #endif 504025d7917SBenjamin Herrenschmidt 505025d7917SBenjamin Herrenschmidt pr_debug(" -> check_pmac_serial_console()\n"); 506025d7917SBenjamin Herrenschmidt 507025d7917SBenjamin Herrenschmidt /* The user has requested a console so this is already set up. */ 508025d7917SBenjamin Herrenschmidt if (strstr(boot_command_line, "console=")) { 509025d7917SBenjamin Herrenschmidt pr_debug(" console was specified !\n"); 510025d7917SBenjamin Herrenschmidt return -EBUSY; 511025d7917SBenjamin Herrenschmidt } 512025d7917SBenjamin Herrenschmidt 513025d7917SBenjamin Herrenschmidt if (!of_chosen) { 514025d7917SBenjamin Herrenschmidt pr_debug(" of_chosen is NULL !\n"); 515025d7917SBenjamin Herrenschmidt return -ENODEV; 516025d7917SBenjamin Herrenschmidt } 517025d7917SBenjamin Herrenschmidt 518025d7917SBenjamin Herrenschmidt /* We are getting a weird phandle from OF ... */ 519025d7917SBenjamin Herrenschmidt /* ... So use the full path instead */ 520025d7917SBenjamin Herrenschmidt name = of_get_property(of_chosen, "linux,stdout-path", NULL); 521025d7917SBenjamin Herrenschmidt if (name == NULL) { 522025d7917SBenjamin Herrenschmidt pr_debug(" no linux,stdout-path !\n"); 523025d7917SBenjamin Herrenschmidt return -ENODEV; 524025d7917SBenjamin Herrenschmidt } 525025d7917SBenjamin Herrenschmidt prom_stdout = of_find_node_by_path(name); 526025d7917SBenjamin Herrenschmidt if (!prom_stdout) { 527025d7917SBenjamin Herrenschmidt pr_debug(" can't find stdout package %s !\n", name); 528025d7917SBenjamin Herrenschmidt return -ENODEV; 529025d7917SBenjamin Herrenschmidt } 530b7c670d6SRob Herring pr_debug("stdout is %pOF\n", prom_stdout); 531025d7917SBenjamin Herrenschmidt 5322c8e65b5SRob Herring if (of_node_name_eq(prom_stdout, "ch-a")) 533025d7917SBenjamin Herrenschmidt offset = 0; 5342c8e65b5SRob Herring else if (of_node_name_eq(prom_stdout, "ch-b")) 535025d7917SBenjamin Herrenschmidt offset = 1; 536025d7917SBenjamin Herrenschmidt else 537025d7917SBenjamin Herrenschmidt goto not_found; 538025d7917SBenjamin Herrenschmidt of_node_put(prom_stdout); 539025d7917SBenjamin Herrenschmidt 540025d7917SBenjamin Herrenschmidt pr_debug("Found serial console at %s%d\n", devname, offset); 541025d7917SBenjamin Herrenschmidt 542025d7917SBenjamin Herrenschmidt return add_preferred_console(devname, offset, NULL); 543025d7917SBenjamin Herrenschmidt 544025d7917SBenjamin Herrenschmidt not_found: 545025d7917SBenjamin Herrenschmidt pr_debug("No preferred console found !\n"); 546025d7917SBenjamin Herrenschmidt of_node_put(prom_stdout); 547025d7917SBenjamin Herrenschmidt return -ENODEV; 548025d7917SBenjamin Herrenschmidt } 549025d7917SBenjamin Herrenschmidt console_initcall(check_pmac_serial_console); 550025d7917SBenjamin Herrenschmidt 551025d7917SBenjamin Herrenschmidt #endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */ 552025d7917SBenjamin Herrenschmidt 55335499c01SPaul Mackerras /* 55435499c01SPaul Mackerras * Called very early, MMU is off, device-tree isn't unflattened 55535499c01SPaul Mackerras */ 556e8222502SBenjamin Herrenschmidt static int __init pmac_probe(void) 55735499c01SPaul Mackerras { 558406b0b6aSBenjamin Herrenschmidt if (!of_machine_is_compatible("Power Macintosh") && 559406b0b6aSBenjamin Herrenschmidt !of_machine_is_compatible("MacRISC")) 560406b0b6aSBenjamin Herrenschmidt return 0; 56135499c01SPaul Mackerras 562e8222502SBenjamin Herrenschmidt #ifdef CONFIG_PPC32 563e8222502SBenjamin Herrenschmidt /* isa_io_base gets set in pmac_pci_init */ 564e8222502SBenjamin Herrenschmidt DMA_MODE_READ = 1; 565e8222502SBenjamin Herrenschmidt DMA_MODE_WRITE = 2; 566e8222502SBenjamin Herrenschmidt #endif /* CONFIG_PPC32 */ 567e8222502SBenjamin Herrenschmidt 5689178ba29SAlexander Graf pm_power_off = pmac_power_off; 5699178ba29SAlexander Graf 570f2d57694SBenjamin Herrenschmidt pmac_init(); 571f2d57694SBenjamin Herrenschmidt 57235499c01SPaul Mackerras return 1; 57335499c01SPaul Mackerras } 57435499c01SPaul Mackerras 575e8222502SBenjamin Herrenschmidt define_machine(powermac) { 576e8222502SBenjamin Herrenschmidt .name = "PowerMac", 57735499c01SPaul Mackerras .probe = pmac_probe, 57835499c01SPaul Mackerras .setup_arch = pmac_setup_arch, 579fbbefb32SOliver O'Halloran .discover_phbs = pmac_pci_init, 58035499c01SPaul Mackerras .show_cpuinfo = pmac_show_cpuinfo, 58135499c01SPaul Mackerras .init_IRQ = pmac_pic_init, 582cc5d0189SBenjamin Herrenschmidt .get_irq = NULL, /* changed later */ 583f90bb153SBenjamin Herrenschmidt .pci_irq_fixup = pmac_pci_irq_fixup, 58435499c01SPaul Mackerras .restart = pmac_restart, 58535499c01SPaul Mackerras .halt = pmac_halt, 58635499c01SPaul Mackerras .time_init = pmac_time_init, 58735499c01SPaul Mackerras .get_boot_time = pmac_get_boot_time, 58835499c01SPaul Mackerras .set_rtc_time = pmac_set_rtc_time, 58935499c01SPaul Mackerras .get_rtc_time = pmac_get_rtc_time, 59035499c01SPaul Mackerras .calibrate_decr = pmac_calibrate_decr, 59135499c01SPaul Mackerras .feature_call = pmac_do_feature_call, 592be6b8439SKumar Gala .progress = udbg_progress, 59335499c01SPaul Mackerras #ifdef CONFIG_PPC64 594a0652fc9SPaul Mackerras .power_save = power4_idle, 59535499c01SPaul Mackerras .enable_pmcs = power4_enable_pmcs, 5963d1229d6SMichael Ellerman #endif /* CONFIG_PPC64 */ 59735499c01SPaul Mackerras #ifdef CONFIG_PPC32 59835499c01SPaul Mackerras .pcibios_after_init = pmac_pcibios_after_init, 59935499c01SPaul Mackerras .phys_mem_access_prot = pci_phys_mem_access_prot, 60035499c01SPaul Mackerras #endif 60135499c01SPaul Mackerras }; 602