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> 485f867dc7SJon Loeliger #include <linux/of_device.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 79f6d57916SPaul Mackerras #define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ 80f6d57916SPaul Mackerras 81f6d57916SPaul Mackerras sys_ctrler_t sys_ctrler = SYS_CTRLER_UNKNOWN; 8235499c01SPaul Mackerras EXPORT_SYMBOL(sys_ctrler); 8335499c01SPaul Mackerras 840dd194d0SPaul Mackerras static void pmac_show_cpuinfo(struct seq_file *m) 85f6d57916SPaul Mackerras { 86f6d57916SPaul Mackerras struct device_node *np; 87018a3d1dSJeremy Kerr const char *pp; 88f6d57916SPaul Mackerras int plen; 890dd194d0SPaul Mackerras int mbmodel; 900dd194d0SPaul Mackerras unsigned int mbflags; 91f6d57916SPaul Mackerras char* mbname; 92f6d57916SPaul Mackerras 930dd194d0SPaul Mackerras mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, 940dd194d0SPaul Mackerras PMAC_MB_INFO_MODEL, 0); 950dd194d0SPaul Mackerras mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, 960dd194d0SPaul Mackerras PMAC_MB_INFO_FLAGS, 0); 970dd194d0SPaul Mackerras if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, 980dd194d0SPaul Mackerras (long) &mbname) != 0) 99f6d57916SPaul Mackerras mbname = "Unknown"; 100f6d57916SPaul Mackerras 101f6d57916SPaul Mackerras /* find motherboard type */ 102f6d57916SPaul Mackerras seq_printf(m, "machine\t\t: "); 1030dd194d0SPaul Mackerras np = of_find_node_by_path("/"); 104f6d57916SPaul Mackerras if (np != NULL) { 105e2eb6392SStephen Rothwell pp = of_get_property(np, "model", NULL); 106f6d57916SPaul Mackerras if (pp != NULL) 107f6d57916SPaul Mackerras seq_printf(m, "%s\n", pp); 108f6d57916SPaul Mackerras else 109f6d57916SPaul Mackerras seq_printf(m, "PowerMac\n"); 110e2eb6392SStephen Rothwell pp = of_get_property(np, "compatible", &plen); 111f6d57916SPaul Mackerras if (pp != NULL) { 112f6d57916SPaul Mackerras seq_printf(m, "motherboard\t:"); 113f6d57916SPaul Mackerras while (plen > 0) { 114f6d57916SPaul Mackerras int l = strlen(pp) + 1; 115f6d57916SPaul Mackerras seq_printf(m, " %s", pp); 116f6d57916SPaul Mackerras plen -= l; 117f6d57916SPaul Mackerras pp += l; 118f6d57916SPaul Mackerras } 119f6d57916SPaul Mackerras seq_printf(m, "\n"); 120f6d57916SPaul Mackerras } 1210dd194d0SPaul Mackerras of_node_put(np); 122f6d57916SPaul Mackerras } else 123f6d57916SPaul Mackerras seq_printf(m, "PowerMac\n"); 124f6d57916SPaul Mackerras 125f6d57916SPaul Mackerras /* print parsed model */ 126f6d57916SPaul Mackerras seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); 127f6d57916SPaul Mackerras seq_printf(m, "pmac flags\t: %08x\n", mbflags); 128f6d57916SPaul Mackerras 129f6d57916SPaul Mackerras /* find l2 cache info */ 1300dd194d0SPaul Mackerras np = of_find_node_by_name(NULL, "l2-cache"); 1310dd194d0SPaul Mackerras if (np == NULL) 1320dd194d0SPaul Mackerras np = of_find_node_by_type(NULL, "cache"); 1330dd194d0SPaul Mackerras if (np != NULL) { 134e2eb6392SStephen Rothwell const unsigned int *ic = 135e2eb6392SStephen Rothwell of_get_property(np, "i-cache-size", NULL); 136e2eb6392SStephen Rothwell const unsigned int *dc = 137e2eb6392SStephen Rothwell of_get_property(np, "d-cache-size", NULL); 138f6d57916SPaul Mackerras seq_printf(m, "L2 cache\t:"); 139f6d57916SPaul Mackerras has_l2cache = 1; 140*4d57e351SRob Herring if (of_property_read_bool(np, "cache-unified") && dc) { 141f6d57916SPaul Mackerras seq_printf(m, " %dK unified", *dc / 1024); 142f6d57916SPaul Mackerras } else { 143f6d57916SPaul Mackerras if (ic) 144f6d57916SPaul Mackerras seq_printf(m, " %dK instruction", *ic / 1024); 145f6d57916SPaul Mackerras if (dc) 146f6d57916SPaul Mackerras seq_printf(m, "%s %dK data", 147f6d57916SPaul Mackerras (ic? " +": ""), *dc / 1024); 148f6d57916SPaul Mackerras } 149e2eb6392SStephen Rothwell pp = of_get_property(np, "ram-type", NULL); 150f6d57916SPaul Mackerras if (pp) 151f6d57916SPaul Mackerras seq_printf(m, " %s", pp); 152f6d57916SPaul Mackerras seq_printf(m, "\n"); 1530dd194d0SPaul Mackerras of_node_put(np); 154f6d57916SPaul Mackerras } 155f6d57916SPaul Mackerras 156f6d57916SPaul Mackerras /* Indicate newworld/oldworld */ 157f6d57916SPaul Mackerras seq_printf(m, "pmac-generation\t: %s\n", 158f6d57916SPaul Mackerras pmac_newworld ? "NewWorld" : "OldWorld"); 159f6d57916SPaul Mackerras } 160f6d57916SPaul Mackerras 16135499c01SPaul Mackerras #ifndef CONFIG_ADB_CUDA 1627da1d1ddSNick Child int __init find_via_cuda(void) 16335499c01SPaul Mackerras { 16430686ba6SStephen Rothwell struct device_node *dn = of_find_node_by_name(NULL, "via-cuda"); 16530686ba6SStephen Rothwell 16630686ba6SStephen Rothwell if (!dn) 16735499c01SPaul Mackerras return 0; 16830686ba6SStephen Rothwell of_node_put(dn); 16935499c01SPaul Mackerras printk("WARNING ! Your machine is CUDA-based but your kernel\n"); 17035499c01SPaul Mackerras printk(" wasn't compiled with CONFIG_ADB_CUDA option !\n"); 17135499c01SPaul Mackerras return 0; 17235499c01SPaul Mackerras } 17335499c01SPaul Mackerras #endif 17435499c01SPaul Mackerras 17535499c01SPaul Mackerras #ifndef CONFIG_ADB_PMU 1767da1d1ddSNick Child int __init find_via_pmu(void) 17735499c01SPaul Mackerras { 17830686ba6SStephen Rothwell struct device_node *dn = of_find_node_by_name(NULL, "via-pmu"); 17930686ba6SStephen Rothwell 18030686ba6SStephen Rothwell if (!dn) 18135499c01SPaul Mackerras return 0; 18230686ba6SStephen Rothwell of_node_put(dn); 18335499c01SPaul Mackerras printk("WARNING ! Your machine is PMU-based but your kernel\n"); 18435499c01SPaul Mackerras printk(" wasn't compiled with CONFIG_ADB_PMU option !\n"); 185a575b807SPaul Mackerras return 0; 18635499c01SPaul Mackerras } 18735499c01SPaul Mackerras #endif 18835499c01SPaul Mackerras 18935499c01SPaul Mackerras #ifndef CONFIG_PMAC_SMU 190b346f571SNick Child int __init smu_init(void) 19135499c01SPaul Mackerras { 19235499c01SPaul Mackerras /* should check and warn if SMU is present */ 19335499c01SPaul Mackerras return 0; 19435499c01SPaul Mackerras } 19535499c01SPaul Mackerras #endif 19635499c01SPaul Mackerras 19735499c01SPaul Mackerras #ifdef CONFIG_PPC32 198f6d57916SPaul Mackerras static volatile u32 *sysctrl_regs; 199f6d57916SPaul Mackerras 20035499c01SPaul Mackerras static void __init ohare_init(void) 201f6d57916SPaul Mackerras { 20230686ba6SStephen Rothwell struct device_node *dn; 20330686ba6SStephen Rothwell 204f6d57916SPaul Mackerras /* this area has the CPU identification register 205f6d57916SPaul Mackerras and some registers used by smp boards */ 206f6d57916SPaul Mackerras sysctrl_regs = (volatile u32 *) ioremap(0xf8000000, 0x1000); 207f6d57916SPaul Mackerras 20835499c01SPaul Mackerras /* 20935499c01SPaul Mackerras * Turn on the L2 cache. 21035499c01SPaul Mackerras * We assume that we have a PSX memory controller iff 21135499c01SPaul Mackerras * we have an ohare I/O controller. 21235499c01SPaul Mackerras */ 21330686ba6SStephen Rothwell dn = of_find_node_by_name(NULL, "ohare"); 21430686ba6SStephen Rothwell if (dn) { 21530686ba6SStephen Rothwell of_node_put(dn); 21635499c01SPaul Mackerras if (((sysctrl_regs[2] >> 24) & 0xf) >= 3) { 21735499c01SPaul Mackerras if (sysctrl_regs[4] & 0x10) 21835499c01SPaul Mackerras sysctrl_regs[4] |= 0x04000020; 21935499c01SPaul Mackerras else 22035499c01SPaul Mackerras sysctrl_regs[4] |= 0x04000000; 22135499c01SPaul Mackerras if(has_l2cache) 22235499c01SPaul Mackerras printk(KERN_INFO "Level 2 cache enabled\n"); 22335499c01SPaul Mackerras } 22435499c01SPaul Mackerras } 22535499c01SPaul Mackerras } 226f6d57916SPaul Mackerras 22735499c01SPaul Mackerras static void __init l2cr_init(void) 22835499c01SPaul Mackerras { 229f6d57916SPaul Mackerras /* Checks "l2cr-value" property in the registry */ 230f6d57916SPaul Mackerras if (cpu_has_feature(CPU_FTR_L2CR)) { 231a94fe366SRob Herring struct device_node *np; 232a94fe366SRob Herring 233a94fe366SRob Herring for_each_of_cpu_node(np) { 234018a3d1dSJeremy Kerr const unsigned int *l2cr = 235e2eb6392SStephen Rothwell of_get_property(np, "l2cr-value", NULL); 236d8731527SMathieu Malaterre if (l2cr) { 237f6d57916SPaul Mackerras _set_L2CR(0); 23859dc2d94SChen Lifu _set_L2CR(*l2cr); 23959dc2d94SChen Lifu pr_info("L2CR overridden (0x%x), backside cache is %s\n", 24059dc2d94SChen Lifu *l2cr, ((*l2cr) & 0x80000000) ? 24159dc2d94SChen Lifu "enabled" : "disabled"); 242f6d57916SPaul Mackerras } 2431658ab66SStephen Rothwell of_node_put(np); 244a94fe366SRob Herring break; 245f6d57916SPaul Mackerras } 246f6d57916SPaul Mackerras } 24735499c01SPaul Mackerras } 24835499c01SPaul Mackerras #endif 24935499c01SPaul Mackerras 250ff38e7c8SArnd Bergmann static void __init pmac_setup_arch(void) 25135499c01SPaul Mackerras { 252a575b807SPaul Mackerras struct device_node *cpu, *ic; 253018a3d1dSJeremy Kerr const int *fp; 25435499c01SPaul Mackerras unsigned long pvr; 25535499c01SPaul Mackerras 25635499c01SPaul Mackerras pvr = PVR_VER(mfspr(SPRN_PVR)); 25735499c01SPaul Mackerras 25835499c01SPaul Mackerras /* Set loops_per_jiffy to a half-way reasonable value, 25935499c01SPaul Mackerras for use until calibrate_delay gets called. */ 26035499c01SPaul Mackerras loops_per_jiffy = 50000000 / HZ; 261a94fe366SRob Herring 262a94fe366SRob Herring for_each_of_cpu_node(cpu) { 263e2eb6392SStephen Rothwell fp = of_get_property(cpu, "clock-frequency", NULL); 26435499c01SPaul Mackerras if (fp != NULL) { 26535499c01SPaul Mackerras if (pvr >= 0x30 && pvr < 0x80) 26635499c01SPaul Mackerras /* PPC970 etc. */ 26735499c01SPaul Mackerras loops_per_jiffy = *fp / (3 * HZ); 26835499c01SPaul Mackerras else if (pvr == 4 || pvr >= 8) 26935499c01SPaul Mackerras /* 604, G3, G4 etc. */ 27035499c01SPaul Mackerras loops_per_jiffy = *fp / HZ; 27135499c01SPaul Mackerras else 2728b14e1dfSChristophe Leroy /* 603, etc. */ 27335499c01SPaul Mackerras loops_per_jiffy = *fp / (2 * HZ); 27435499c01SPaul Mackerras of_node_put(cpu); 275a94fe366SRob Herring break; 276a94fe366SRob Herring } 27735499c01SPaul Mackerras } 27835499c01SPaul Mackerras 279a575b807SPaul Mackerras /* See if newworld or oldworld */ 28022059a90SMichael Ellerman ic = of_find_node_with_property(NULL, "interrupt-controller"); 281d2515c80SOlaf Hering if (ic) { 282d2515c80SOlaf Hering pmac_newworld = 1; 283a575b807SPaul Mackerras of_node_put(ic); 284d2515c80SOlaf Hering } 285a575b807SPaul Mackerras 28635499c01SPaul Mackerras #ifdef CONFIG_PPC32 28735499c01SPaul Mackerras ohare_init(); 28835499c01SPaul Mackerras l2cr_init(); 28935499c01SPaul Mackerras #endif /* CONFIG_PPC32 */ 29035499c01SPaul Mackerras 291f6d57916SPaul Mackerras find_via_cuda(); 292f6d57916SPaul Mackerras find_via_pmu(); 29335499c01SPaul Mackerras smu_init(); 29435499c01SPaul Mackerras 29520e07af7SFinn Thain #if IS_ENABLED(CONFIG_NVRAM) 296f6d57916SPaul Mackerras pmac_nvram_init(); 297f6d57916SPaul Mackerras #endif 29835499c01SPaul Mackerras #ifdef CONFIG_PPC32 299f6d57916SPaul Mackerras #ifdef CONFIG_BLK_DEV_INITRD 300f6d57916SPaul Mackerras if (initrd_start) 301f6d57916SPaul Mackerras ROOT_DEV = Root_RAM0; 302f6d57916SPaul Mackerras else 303f6d57916SPaul Mackerras #endif 304f6d57916SPaul Mackerras ROOT_DEV = DEFAULT_ROOT_DEVICE; 30535499c01SPaul Mackerras #endif 306f6d57916SPaul Mackerras 307e8222502SBenjamin Herrenschmidt #ifdef CONFIG_ADB 3083e47d147SAnton Blanchard if (strstr(boot_command_line, "adb_sync")) { 309e8222502SBenjamin Herrenschmidt extern int __adb_probe_sync; 310e8222502SBenjamin Herrenschmidt __adb_probe_sync = 1; 311e8222502SBenjamin Herrenschmidt } 312e8222502SBenjamin Herrenschmidt #endif /* CONFIG_ADB */ 313f6d57916SPaul Mackerras } 314f6d57916SPaul Mackerras 31535499c01SPaul Mackerras static int initializing = 1; 31635499c01SPaul Mackerras 317f6d57916SPaul Mackerras static int pmac_late_init(void) 318f6d57916SPaul Mackerras { 319f6d57916SPaul Mackerras initializing = 0; 320f6d57916SPaul Mackerras return 0; 321f6d57916SPaul Mackerras } 322d518b717SGrant Likely machine_late_initcall(powermac, pmac_late_init); 323f6d57916SPaul Mackerras 324f72cf3f1SMathieu Malaterre void note_bootable_part(dev_t dev, int part, int goodness); 325d7418031SStephen Rothwell /* 326bd721ea7SFabian Frederick * This is __ref because we check for "initializing" before 327d7418031SStephen Rothwell * touching any of the __init sensitive things and "initializing" 328d7418031SStephen Rothwell * will be false after __init time. This can't be __init because it 329d7418031SStephen Rothwell * can be called whenever a disk is first accessed. 330d7418031SStephen Rothwell */ 331bd721ea7SFabian Frederick void __ref note_bootable_part(dev_t dev, int part, int goodness) 332f6d57916SPaul Mackerras { 333f6d57916SPaul Mackerras char *p; 334f6d57916SPaul Mackerras 335f6d57916SPaul Mackerras if (!initializing) 336f6d57916SPaul Mackerras return; 337f6d57916SPaul Mackerras if ((goodness <= current_root_goodness) && 338f6d57916SPaul Mackerras ROOT_DEV != DEFAULT_ROOT_DEVICE) 339f6d57916SPaul Mackerras return; 340b8757b21SAlon Bar-Lev p = strstr(boot_command_line, "root="); 341b8757b21SAlon Bar-Lev if (p != NULL && (p == boot_command_line || p[-1] == ' ')) 342f6d57916SPaul Mackerras return; 343f6d57916SPaul Mackerras 344f6d57916SPaul Mackerras ROOT_DEV = dev + part; 345f6d57916SPaul Mackerras current_root_goodness = goodness; 346f6d57916SPaul Mackerras } 347f6d57916SPaul Mackerras 34835499c01SPaul Mackerras #ifdef CONFIG_ADB_CUDA 34995ec77c0SDaniel Axtens static void __noreturn cuda_restart(void) 350f6d57916SPaul Mackerras { 351f6d57916SPaul Mackerras struct adb_request req; 352f6d57916SPaul Mackerras 35335499c01SPaul Mackerras cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_RESET_SYSTEM); 354f6d57916SPaul Mackerras for (;;) 355f6d57916SPaul Mackerras cuda_poll(); 35635499c01SPaul Mackerras } 35735499c01SPaul Mackerras 35895ec77c0SDaniel Axtens static void __noreturn cuda_shutdown(void) 35935499c01SPaul Mackerras { 36035499c01SPaul Mackerras struct adb_request req; 36135499c01SPaul Mackerras 36235499c01SPaul Mackerras cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_POWERDOWN); 36335499c01SPaul Mackerras for (;;) 36435499c01SPaul Mackerras cuda_poll(); 36535499c01SPaul Mackerras } 36635499c01SPaul Mackerras 36735499c01SPaul Mackerras #else 36835499c01SPaul Mackerras #define cuda_restart() 36935499c01SPaul Mackerras #define cuda_shutdown() 37035499c01SPaul Mackerras #endif 37135499c01SPaul Mackerras 37235499c01SPaul Mackerras #ifndef CONFIG_ADB_PMU 37335499c01SPaul Mackerras #define pmu_restart() 37435499c01SPaul Mackerras #define pmu_shutdown() 37535499c01SPaul Mackerras #endif 37635499c01SPaul Mackerras 37735499c01SPaul Mackerras #ifndef CONFIG_PMAC_SMU 37835499c01SPaul Mackerras #define smu_restart() 37935499c01SPaul Mackerras #define smu_shutdown() 38035499c01SPaul Mackerras #endif 38135499c01SPaul Mackerras 38295ec77c0SDaniel Axtens static void __noreturn pmac_restart(char *cmd) 38335499c01SPaul Mackerras { 38435499c01SPaul Mackerras switch (sys_ctrler) { 38535499c01SPaul Mackerras case SYS_CTRLER_CUDA: 38635499c01SPaul Mackerras cuda_restart(); 387f6d57916SPaul Mackerras break; 388f6d57916SPaul Mackerras case SYS_CTRLER_PMU: 389f6d57916SPaul Mackerras pmu_restart(); 390f6d57916SPaul Mackerras break; 39135499c01SPaul Mackerras case SYS_CTRLER_SMU: 39235499c01SPaul Mackerras smu_restart(); 39335499c01SPaul Mackerras break; 394f6d57916SPaul Mackerras default: ; 395f6d57916SPaul Mackerras } 39695ec77c0SDaniel Axtens while (1) ; 397f6d57916SPaul Mackerras } 398f6d57916SPaul Mackerras 39995ec77c0SDaniel Axtens static void __noreturn pmac_power_off(void) 400f6d57916SPaul Mackerras { 401f6d57916SPaul Mackerras switch (sys_ctrler) { 402f6d57916SPaul Mackerras case SYS_CTRLER_CUDA: 40335499c01SPaul Mackerras cuda_shutdown(); 404f6d57916SPaul Mackerras break; 405f6d57916SPaul Mackerras case SYS_CTRLER_PMU: 406f6d57916SPaul Mackerras pmu_shutdown(); 407f6d57916SPaul Mackerras break; 40835499c01SPaul Mackerras case SYS_CTRLER_SMU: 40935499c01SPaul Mackerras smu_shutdown(); 41035499c01SPaul Mackerras break; 411f6d57916SPaul Mackerras default: ; 412f6d57916SPaul Mackerras } 41395ec77c0SDaniel Axtens while (1) ; 414f6d57916SPaul Mackerras } 415f6d57916SPaul Mackerras 41695ec77c0SDaniel Axtens static void __noreturn 417f6d57916SPaul Mackerras pmac_halt(void) 418f6d57916SPaul Mackerras { 419f6d57916SPaul Mackerras pmac_power_off(); 420f6d57916SPaul Mackerras } 421f6d57916SPaul Mackerras 42235499c01SPaul Mackerras /* 42335499c01SPaul Mackerras * Early initialization. 42435499c01SPaul Mackerras */ 425f2d57694SBenjamin Herrenschmidt static void __init pmac_init(void) 426f6d57916SPaul Mackerras { 42751d3082fSBenjamin Herrenschmidt /* Enable early btext debug if requested */ 4283e47d147SAnton Blanchard if (strstr(boot_command_line, "btextdbg")) { 42951d3082fSBenjamin Herrenschmidt udbg_adb_init_early(); 43051d3082fSBenjamin Herrenschmidt register_early_udbg_console(); 43135499c01SPaul Mackerras } 43235499c01SPaul Mackerras 43351d3082fSBenjamin Herrenschmidt /* Probe motherboard chipset */ 43451d3082fSBenjamin Herrenschmidt pmac_feature_init(); 43551d3082fSBenjamin Herrenschmidt 43651d3082fSBenjamin Herrenschmidt /* Initialize debug stuff */ 4373e47d147SAnton Blanchard udbg_scc_init(!!strstr(boot_command_line, "sccdbg")); 4383e47d147SAnton Blanchard udbg_adb_init(!!strstr(boot_command_line, "btextdbg")); 43951d3082fSBenjamin Herrenschmidt 44051d3082fSBenjamin Herrenschmidt #ifdef CONFIG_PPC64 441e63f26d3SDaniel Axtens iommu_init_early_dart(&pmac_pci_controller_ops); 44235499c01SPaul Mackerras #endif 4437ccbe504SBenjamin Herrenschmidt 4447ccbe504SBenjamin Herrenschmidt /* SMP Init has to be done early as we need to patch up 445828a6986SAnton Blanchard * cpu_possible_mask before interrupt stacks are allocated 4467ccbe504SBenjamin Herrenschmidt * or kaboom... 4477ccbe504SBenjamin Herrenschmidt */ 4487ccbe504SBenjamin Herrenschmidt #ifdef CONFIG_SMP 4497ccbe504SBenjamin Herrenschmidt pmac_setup_smp(); 4507ccbe504SBenjamin Herrenschmidt #endif 45135499c01SPaul Mackerras } 45235499c01SPaul Mackerras 45335499c01SPaul Mackerras static int __init pmac_declare_of_platform_devices(void) 454f6d57916SPaul Mackerras { 455a28d3af2SBenjamin Herrenschmidt struct device_node *np; 456f6d57916SPaul Mackerras 457730745a5SBenjamin Herrenschmidt np = of_find_node_by_name(NULL, "valkyrie"); 4583631cb83SJulia Lawall if (np) { 45935499c01SPaul Mackerras of_platform_device_create(np, "valkyrie", NULL); 4603631cb83SJulia Lawall of_node_put(np); 4613631cb83SJulia Lawall } 462730745a5SBenjamin Herrenschmidt np = of_find_node_by_name(NULL, "platinum"); 4633631cb83SJulia Lawall if (np) { 46435499c01SPaul Mackerras of_platform_device_create(np, "platinum", NULL); 4653631cb83SJulia Lawall of_node_put(np); 4663631cb83SJulia Lawall } 46735499c01SPaul Mackerras np = of_find_node_by_type(NULL, "smu"); 46835499c01SPaul Mackerras if (np) { 46935499c01SPaul Mackerras of_platform_device_create(np, "smu", NULL); 47035499c01SPaul Mackerras of_node_put(np); 47135499c01SPaul Mackerras } 47298b14d6bSMarc Zyngier np = of_find_node_by_type(NULL, "fcu"); 47398b14d6bSMarc Zyngier if (np == NULL) { 47498b14d6bSMarc Zyngier /* Some machines have strangely broken device-tree */ 47598b14d6bSMarc Zyngier np = of_find_node_by_path("/u3@0,f8000000/i2c@f8001000/fan@15e"); 47698b14d6bSMarc Zyngier } 47798b14d6bSMarc Zyngier if (np) { 47898b14d6bSMarc Zyngier of_platform_device_create(np, "temperature", NULL); 47998b14d6bSMarc Zyngier of_node_put(np); 48098b14d6bSMarc Zyngier } 481f6d57916SPaul Mackerras 482f6d57916SPaul Mackerras return 0; 483f6d57916SPaul Mackerras } 484d518b717SGrant Likely machine_device_initcall(powermac, pmac_declare_of_platform_devices); 48535499c01SPaul Mackerras 486025d7917SBenjamin Herrenschmidt #ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE 487025d7917SBenjamin Herrenschmidt /* 488025d7917SBenjamin Herrenschmidt * This is called very early, as part of console_init() (typically just after 489025d7917SBenjamin Herrenschmidt * time_init()). This function is respondible for trying to find a good 490025d7917SBenjamin Herrenschmidt * default console on serial ports. It tries to match the open firmware 491025d7917SBenjamin Herrenschmidt * default output with one of the available serial console drivers. 492025d7917SBenjamin Herrenschmidt */ 493025d7917SBenjamin Herrenschmidt static int __init check_pmac_serial_console(void) 494025d7917SBenjamin Herrenschmidt { 495025d7917SBenjamin Herrenschmidt struct device_node *prom_stdout = NULL; 496025d7917SBenjamin Herrenschmidt int offset = 0; 497025d7917SBenjamin Herrenschmidt const char *name; 498025d7917SBenjamin Herrenschmidt #ifdef CONFIG_SERIAL_PMACZILOG_TTYS 499025d7917SBenjamin Herrenschmidt char *devname = "ttyS"; 500025d7917SBenjamin Herrenschmidt #else 501025d7917SBenjamin Herrenschmidt char *devname = "ttyPZ"; 502025d7917SBenjamin Herrenschmidt #endif 503025d7917SBenjamin Herrenschmidt 504025d7917SBenjamin Herrenschmidt pr_debug(" -> check_pmac_serial_console()\n"); 505025d7917SBenjamin Herrenschmidt 506025d7917SBenjamin Herrenschmidt /* The user has requested a console so this is already set up. */ 507025d7917SBenjamin Herrenschmidt if (strstr(boot_command_line, "console=")) { 508025d7917SBenjamin Herrenschmidt pr_debug(" console was specified !\n"); 509025d7917SBenjamin Herrenschmidt return -EBUSY; 510025d7917SBenjamin Herrenschmidt } 511025d7917SBenjamin Herrenschmidt 512025d7917SBenjamin Herrenschmidt if (!of_chosen) { 513025d7917SBenjamin Herrenschmidt pr_debug(" of_chosen is NULL !\n"); 514025d7917SBenjamin Herrenschmidt return -ENODEV; 515025d7917SBenjamin Herrenschmidt } 516025d7917SBenjamin Herrenschmidt 517025d7917SBenjamin Herrenschmidt /* We are getting a weird phandle from OF ... */ 518025d7917SBenjamin Herrenschmidt /* ... So use the full path instead */ 519025d7917SBenjamin Herrenschmidt name = of_get_property(of_chosen, "linux,stdout-path", NULL); 520025d7917SBenjamin Herrenschmidt if (name == NULL) { 521025d7917SBenjamin Herrenschmidt pr_debug(" no linux,stdout-path !\n"); 522025d7917SBenjamin Herrenschmidt return -ENODEV; 523025d7917SBenjamin Herrenschmidt } 524025d7917SBenjamin Herrenschmidt prom_stdout = of_find_node_by_path(name); 525025d7917SBenjamin Herrenschmidt if (!prom_stdout) { 526025d7917SBenjamin Herrenschmidt pr_debug(" can't find stdout package %s !\n", name); 527025d7917SBenjamin Herrenschmidt return -ENODEV; 528025d7917SBenjamin Herrenschmidt } 529b7c670d6SRob Herring pr_debug("stdout is %pOF\n", prom_stdout); 530025d7917SBenjamin Herrenschmidt 5312c8e65b5SRob Herring if (of_node_name_eq(prom_stdout, "ch-a")) 532025d7917SBenjamin Herrenschmidt offset = 0; 5332c8e65b5SRob Herring else if (of_node_name_eq(prom_stdout, "ch-b")) 534025d7917SBenjamin Herrenschmidt offset = 1; 535025d7917SBenjamin Herrenschmidt else 536025d7917SBenjamin Herrenschmidt goto not_found; 537025d7917SBenjamin Herrenschmidt of_node_put(prom_stdout); 538025d7917SBenjamin Herrenschmidt 539025d7917SBenjamin Herrenschmidt pr_debug("Found serial console at %s%d\n", devname, offset); 540025d7917SBenjamin Herrenschmidt 541025d7917SBenjamin Herrenschmidt return add_preferred_console(devname, offset, NULL); 542025d7917SBenjamin Herrenschmidt 543025d7917SBenjamin Herrenschmidt not_found: 544025d7917SBenjamin Herrenschmidt pr_debug("No preferred console found !\n"); 545025d7917SBenjamin Herrenschmidt of_node_put(prom_stdout); 546025d7917SBenjamin Herrenschmidt return -ENODEV; 547025d7917SBenjamin Herrenschmidt } 548025d7917SBenjamin Herrenschmidt console_initcall(check_pmac_serial_console); 549025d7917SBenjamin Herrenschmidt 550025d7917SBenjamin Herrenschmidt #endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */ 551025d7917SBenjamin Herrenschmidt 55235499c01SPaul Mackerras /* 55335499c01SPaul Mackerras * Called very early, MMU is off, device-tree isn't unflattened 55435499c01SPaul Mackerras */ 555e8222502SBenjamin Herrenschmidt static int __init pmac_probe(void) 55635499c01SPaul Mackerras { 557406b0b6aSBenjamin Herrenschmidt if (!of_machine_is_compatible("Power Macintosh") && 558406b0b6aSBenjamin Herrenschmidt !of_machine_is_compatible("MacRISC")) 559406b0b6aSBenjamin Herrenschmidt return 0; 56035499c01SPaul Mackerras 561e8222502SBenjamin Herrenschmidt #ifdef CONFIG_PPC32 562e8222502SBenjamin Herrenschmidt /* isa_io_base gets set in pmac_pci_init */ 563e8222502SBenjamin Herrenschmidt DMA_MODE_READ = 1; 564e8222502SBenjamin Herrenschmidt DMA_MODE_WRITE = 2; 565e8222502SBenjamin Herrenschmidt #endif /* CONFIG_PPC32 */ 566e8222502SBenjamin Herrenschmidt 5679178ba29SAlexander Graf pm_power_off = pmac_power_off; 5689178ba29SAlexander Graf 569f2d57694SBenjamin Herrenschmidt pmac_init(); 570f2d57694SBenjamin Herrenschmidt 57135499c01SPaul Mackerras return 1; 57235499c01SPaul Mackerras } 57335499c01SPaul Mackerras 574e8222502SBenjamin Herrenschmidt define_machine(powermac) { 575e8222502SBenjamin Herrenschmidt .name = "PowerMac", 57635499c01SPaul Mackerras .probe = pmac_probe, 57735499c01SPaul Mackerras .setup_arch = pmac_setup_arch, 578fbbefb32SOliver O'Halloran .discover_phbs = pmac_pci_init, 57935499c01SPaul Mackerras .show_cpuinfo = pmac_show_cpuinfo, 58035499c01SPaul Mackerras .init_IRQ = pmac_pic_init, 581cc5d0189SBenjamin Herrenschmidt .get_irq = NULL, /* changed later */ 582f90bb153SBenjamin Herrenschmidt .pci_irq_fixup = pmac_pci_irq_fixup, 58335499c01SPaul Mackerras .restart = pmac_restart, 58435499c01SPaul Mackerras .halt = pmac_halt, 58535499c01SPaul Mackerras .time_init = pmac_time_init, 58635499c01SPaul Mackerras .get_boot_time = pmac_get_boot_time, 58735499c01SPaul Mackerras .set_rtc_time = pmac_set_rtc_time, 58835499c01SPaul Mackerras .get_rtc_time = pmac_get_rtc_time, 58935499c01SPaul Mackerras .calibrate_decr = pmac_calibrate_decr, 59035499c01SPaul Mackerras .feature_call = pmac_do_feature_call, 591be6b8439SKumar Gala .progress = udbg_progress, 59235499c01SPaul Mackerras #ifdef CONFIG_PPC64 593a0652fc9SPaul Mackerras .power_save = power4_idle, 59435499c01SPaul Mackerras .enable_pmcs = power4_enable_pmcs, 5953d1229d6SMichael Ellerman #endif /* CONFIG_PPC64 */ 59635499c01SPaul Mackerras #ifdef CONFIG_PPC32 59735499c01SPaul Mackerras .pcibios_after_init = pmac_pcibios_after_init, 59835499c01SPaul Mackerras .phys_mem_access_prot = pci_phys_mem_access_prot, 59935499c01SPaul Mackerras #endif 60035499c01SPaul Mackerras }; 601