| 1 | |
| 2 | |
| 3 | * Initial setup-routines for HP 9000 based hardware.
|
| 4 | *
|
| 5 | * Copyright (C) 1991, 1992, 1995 Linus Torvalds
|
| 6 | * Modifications for PA-RISC (C) 1999 Helge Deller <[email protected]>
|
| 7 | * Modifications copyright 1999 SuSE GmbH (Philipp Rumpf)
|
| 8 | * Modifications copyright 2000 Martin K. Petersen <[email protected]>
|
| 9 | * Modifications copyright 2000 Philipp Rumpf <[email protected]>
|
| 10 | * Modifications copyright 2001 Ryan Bradetich <[email protected]>
|
| 11 | *
|
| 12 | * Initial PA-RISC Version: 04-23-1999 by Helge Deller
|
| 13 |
|
| 14 |
|
| 15 | #include <linux/kernel.h>
|
| 16 | #include <linux/initrd.h>
|
| 17 | #include <linux/init.h>
|
| 18 | #include <linux/console.h>
|
| 19 | #include <linux/seq_file.h>
|
| 20 | #define PCI_DEBUG
|
| 21 | #include <linux/pci.h>
|
| 22 | #undef PCI_DEBUG
|
| 23 | #include <linux/proc_fs.h>
|
| 24 | #include <linux/export.h>
|
| 25 | #include <linux/sched.h>
|
| 26 | #include <linux/sched/clock.h>
|
| 27 | #include <linux/start_kernel.h>
|
| 28 |
|
| 29 | #include <asm/cacheflush.h>
|
| 30 | #include <asm/processor.h>
|
| 31 | #include <asm/sections.h>
|
| 32 | #include <asm/pdc.h>
|
| 33 | #include <asm/led.h>
|
| 34 | #include <asm/pdc_chassis.h>
|
| 35 | #include <asm/io.h>
|
| 36 | #include <asm/setup.h>
|
| 37 | #include <asm/unwind.h>
|
| 38 | #include <asm/smp.h>
|
| 39 |
|
| 40 | static char __initdata command_line[COMMAND_LINE_SIZE];
|
| 41 |
|
| 42 | static void __init setup_cmdline(char **cmdline_p)
|
| 43 | {
|
| 44 | extern unsigned int boot_args[];
|
| 45 | char *p;
|
| 46 |
|
| 47 | *cmdline_p = command_line;
|
| 48 |
|
| 49 |
|
| 50 | if (boot_args[0] < 64)
|
| 51 | return;
|
| 52 |
|
| 53 |
|
| 54 | strscpy(boot_command_line, (char *)__va(boot_args[1]),
|
| 55 | COMMAND_LINE_SIZE);
|
| 56 |
|
| 57 |
|
| 58 | p = boot_command_line;
|
| 59 | if (!str_has_prefix(p, "console=") && !strstr(p, " console=")) {
|
| 60 | strlcat(p, " console=", COMMAND_LINE_SIZE);
|
| 61 | if (PAGE0->mem_cons.cl_class == CL_DUPLEX)
|
| 62 | strlcat(p, "ttyS0", COMMAND_LINE_SIZE);
|
| 63 | else
|
| 64 | strlcat(p, "tty0", COMMAND_LINE_SIZE);
|
| 65 | }
|
| 66 |
|
| 67 |
|
| 68 | if (!strstr(p, "earlycon"))
|
| 69 | strlcat(p, " earlycon=pdc", COMMAND_LINE_SIZE);
|
| 70 |
|
| 71 | #ifdef CONFIG_BLK_DEV_INITRD
|
| 72 |
|
| 73 | if (boot_args[2] != 0) {
|
| 74 | initrd_start = (unsigned long)__va(boot_args[2]);
|
| 75 | initrd_end = (unsigned long)__va(boot_args[3]);
|
| 76 | }
|
| 77 | #endif
|
| 78 |
|
| 79 | strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
|
| 80 | }
|
| 81 |
|
| 82 | #ifdef CONFIG_PA11
|
| 83 | static void __init dma_ops_init(void)
|
| 84 | {
|
| 85 | switch (boot_cpu_data.cpu_type) {
|
| 86 | case pcx:
|
| 87 | |
| 88 | * We've got way too many dependencies on 1.1 semantics
|
| 89 | * to support 1.0 boxes at this point.
|
| 90 |
|
| 91 | panic( "PA-RISC Linux currently only supports machines that conform to\n"
|
| 92 | "the PA-RISC 1.1 or 2.0 architecture specification.\n");
|
| 93 |
|
| 94 | case pcxl2:
|
| 95 | default:
|
| 96 | break;
|
| 97 | }
|
| 98 | }
|
| 99 | #endif
|
| 100 |
|
| 101 | void __init setup_arch(char **cmdline_p)
|
| 102 | {
|
| 103 | unwind_init();
|
| 104 |
|
| 105 | init_per_cpu(smp_processor_id());
|
| 106 |
|
| 107 | #ifdef CONFIG_64BIT
|
| 108 | printk(KERN_INFO "The 64-bit Kernel has started...\n");
|
| 109 | #else
|
| 110 | printk(KERN_INFO "The 32-bit Kernel has started...\n");
|
| 111 | #endif
|
| 112 |
|
| 113 | printk(KERN_INFO "Kernel default page size is %d KB. Huge pages ",
|
| 114 | (int)(PAGE_SIZE / 1024));
|
| 115 | #ifdef CONFIG_HUGETLB_PAGE
|
| 116 | printk(KERN_CONT "enabled with %d MB physical and %d MB virtual size",
|
| 117 | 1 << (REAL_HPAGE_SHIFT - 20), 1 << (HPAGE_SHIFT - 20));
|
| 118 | #else
|
| 119 | printk(KERN_CONT "disabled");
|
| 120 | #endif
|
| 121 | printk(KERN_CONT ".\n");
|
| 122 |
|
| 123 | #ifdef CONFIG_64BIT
|
| 124 | if(parisc_narrow_firmware) {
|
| 125 | printk(KERN_INFO "Kernel is using PDC in 32-bit mode.\n");
|
| 126 | }
|
| 127 | #endif
|
| 128 | setup_pdc();
|
| 129 | setup_cmdline(cmdline_p);
|
| 130 | collect_boot_cpu_data();
|
| 131 | do_memory_inventory();
|
| 132 | parisc_cache_init();
|
| 133 | paging_init();
|
| 134 |
|
| 135 | |
| 136 | * Parse early parameters before mm_core_init_early() runs.
|
| 137 | * Several early_param() handlers only record data that is consumed
|
| 138 | * from there - for example hugepages=, hugepagesz=,
|
| 139 | * default_hugepagesz=, hugetlb_cma= and hugetlb_free_vmemmap= - so
|
| 140 | * the generic parse_early_param() call in start_kernel() is too late
|
| 141 | * for them. jump_label_init() must come first, since early param
|
| 142 | * handlers may enable or disable static keys.
|
| 143 |
|
| 144 | jump_label_init();
|
| 145 | parse_early_param();
|
| 146 |
|
| 147 | #ifdef CONFIG_PA11
|
| 148 | dma_ops_init();
|
| 149 | #endif
|
| 150 |
|
| 151 | clear_sched_clock_stable();
|
| 152 | }
|
| 153 |
|
| 154 | |
| 155 | * Display CPU info for all CPUs.
|
| 156 |
|
| 157 | static void *
|
| 158 | c_start (struct seq_file *m, loff_t *pos)
|
| 159 | {
|
| 160 | |
| 161 | * 0, signaling EOF perhaps. This could be used to sequence
|
| 162 | * through CPUs for example. Since we print all cpu info in our
|
| 163 | * show_cpuinfo() disregarding 'pos' (which I assume is 'v' above)
|
| 164 | * we only allow for one "position".
|
| 165 | return ((long)*pos < 1) ? (void *)1 : NULL;
|
| 166 | }
|
| 167 |
|
| 168 | static void *
|
| 169 | c_next (struct seq_file *m, void *v, loff_t *pos)
|
| 170 | {
|
| 171 | ++*pos;
|
| 172 | return c_start(m, pos);
|
| 173 | }
|
| 174 |
|
| 175 | static void
|
| 176 | c_stop (struct seq_file *m, void *v)
|
| 177 | {
|
| 178 | }
|
| 179 |
|
| 180 | const struct seq_operations cpuinfo_op = {
|
| 181 | .start = c_start,
|
| 182 | .next = c_next,
|
| 183 | .stop = c_stop,
|
| 184 | .show = show_cpuinfo
|
| 185 | };
|
| 186 |
|
| 187 | static struct resource central_bus = {
|
| 188 | .name = "Central Bus",
|
| 189 | .start = F_EXTEND(0xfff80000),
|
| 190 | .end = F_EXTEND(0xfffaffff),
|
| 191 | .flags = IORESOURCE_MEM,
|
| 192 | };
|
| 193 |
|
| 194 | static struct resource local_broadcast = {
|
| 195 | .name = "Local Broadcast",
|
| 196 | .start = F_EXTEND(0xfffb0000),
|
| 197 | .end = F_EXTEND(0xfffdffff),
|
| 198 | .flags = IORESOURCE_MEM,
|
| 199 | };
|
| 200 |
|
| 201 | static struct resource global_broadcast = {
|
| 202 | .name = "Global Broadcast",
|
| 203 | .start = F_EXTEND(0xfffe0000),
|
| 204 | .end = F_EXTEND(0xffffffff),
|
| 205 | .flags = IORESOURCE_MEM,
|
| 206 | };
|
| 207 |
|
| 208 | static int __init parisc_init_resources(void)
|
| 209 | {
|
| 210 | int result;
|
| 211 |
|
| 212 | result = request_resource(&iomem_resource, ¢ral_bus);
|
| 213 | if (result < 0) {
|
| 214 | printk(KERN_ERR
|
| 215 | "%s: failed to claim %s address space!\n",
|
| 216 | __FILE__, central_bus.name);
|
| 217 | return result;
|
| 218 | }
|
| 219 |
|
| 220 | result = request_resource(&iomem_resource, &local_broadcast);
|
| 221 | if (result < 0) {
|
| 222 | printk(KERN_ERR
|
| 223 | "%s: failed to claim %s address space!\n",
|
| 224 | __FILE__, local_broadcast.name);
|
| 225 | return result;
|
| 226 | }
|
| 227 |
|
| 228 | result = request_resource(&iomem_resource, &global_broadcast);
|
| 229 | if (result < 0) {
|
| 230 | printk(KERN_ERR
|
| 231 | "%s: failed to claim %s address space!\n",
|
| 232 | __FILE__, global_broadcast.name);
|
| 233 | return result;
|
| 234 | }
|
| 235 |
|
| 236 | return 0;
|
| 237 | }
|
| 238 |
|
| 239 | static int __init parisc_init(void)
|
| 240 | {
|
| 241 | u32 osid = (OS_ID_LINUX << 16);
|
| 242 |
|
| 243 | parisc_init_resources();
|
| 244 | do_device_inventory();
|
| 245 |
|
| 246 | parisc_pdc_chassis_init();
|
| 247 |
|
| 248 |
|
| 249 | pdc_chassis_send_status(PDC_CHASSIS_DIRECT_BSTART);
|
| 250 |
|
| 251 |
|
| 252 | pdc_stable_write(0x40, &osid, sizeof(osid));
|
| 253 |
|
| 254 |
|
| 255 | flush_cache_all_local();
|
| 256 | flush_tlb_all_local(NULL);
|
| 257 |
|
| 258 | processor_init();
|
| 259 | #ifdef CONFIG_SMP
|
| 260 | pr_info("CPU(s): %d out of %d %s at %d.%06d MHz online\n",
|
| 261 | num_online_cpus(), num_present_cpus(),
|
| 262 | #else
|
| 263 | pr_info("CPU(s): 1 x %s at %d.%06d MHz\n",
|
| 264 | #endif
|
| 265 | boot_cpu_data.cpu_name,
|
| 266 | boot_cpu_data.cpu_hz / 1000000,
|
| 267 | boot_cpu_data.cpu_hz % 1000000 );
|
| 268 |
|
| 269 | #if defined(CONFIG_64BIT) && defined(CONFIG_SMP)
|
| 270 |
|
| 271 | if (num_online_cpus() == 1)
|
| 272 | pa_serialize_tlb_flushes = 0;
|
| 273 | #endif
|
| 274 |
|
| 275 | apply_alternatives_all();
|
| 276 | parisc_setup_cache_timing();
|
| 277 | return 0;
|
| 278 | }
|
| 279 | arch_initcall(parisc_init);
|
| 280 |
|
| 281 | void __init start_parisc(void)
|
| 282 | {
|
| 283 | int ret, cpunum;
|
| 284 | struct pdc_coproc_cfg coproc_cfg;
|
| 285 |
|
| 286 | |
| 287 | * Check if initial kernel page mapping is sufficient.
|
| 288 | * Print warning if not, because we may access kernel functions and
|
| 289 | * variables which can't be reached yet through the initial mappings.
|
| 290 | * Note that the panic() and printk() functions are not functional
|
| 291 | * yet, so we need to use direct iodc() firmware calls instead.
|
| 292 |
|
| 293 | const char warn1[] = "CRITICAL: Kernel may crash because "
|
| 294 | "KERNEL_INITIAL_ORDER is too small.\n";
|
| 295 | if (__pa((unsigned long) &_end) >= KERNEL_INITIAL_SIZE)
|
| 296 | pdc_iodc_print(warn1, sizeof(warn1) - 1);
|
| 297 |
|
| 298 |
|
| 299 | running_on_qemu = (memcmp(&PAGE0->pad0, "SeaBIOS", 8) == 0);
|
| 300 |
|
| 301 | cpunum = smp_processor_id();
|
| 302 |
|
| 303 | init_cpu_topology();
|
| 304 |
|
| 305 | set_firmware_width_unlocked();
|
| 306 |
|
| 307 | ret = pdc_coproc_cfg_unlocked(&coproc_cfg);
|
| 308 | if (ret >= 0 && coproc_cfg.ccr_functional) {
|
| 309 | mtctl(coproc_cfg.ccr_functional, 10);
|
| 310 |
|
| 311 | per_cpu(cpu_data, cpunum).fp_rev = coproc_cfg.revision;
|
| 312 | per_cpu(cpu_data, cpunum).fp_model = coproc_cfg.model;
|
| 313 |
|
| 314 | asm volatile ("fstd %fr0,8(%sp)");
|
| 315 | } else {
|
| 316 | panic("must have an fpu to boot linux");
|
| 317 | }
|
| 318 |
|
| 319 | early_trap_init();
|
| 320 |
|
| 321 | start_kernel();
|
| 322 | |
| 323 | }
|