linux/arch/m68k/kernel/setup_mm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  linux/arch/m68k/kernel/setup.c
   4 *
   5 *  Copyright (C) 1995  Hamish Macdonald
   6 */
   7
   8/*
   9 * This file handles the architecture-dependent parts of system setup
  10 */
  11
  12#include <linux/kernel.h>
  13#include <linux/mm.h>
  14#include <linux/sched.h>
  15#include <linux/delay.h>
  16#include <linux/interrupt.h>
  17#include <linux/fs.h>
  18#include <linux/console.h>
  19#include <linux/genhd.h>
  20#include <linux/errno.h>
  21#include <linux/string.h>
  22#include <linux/init.h>
  23#include <linux/memblock.h>
  24#include <linux/proc_fs.h>
  25#include <linux/seq_file.h>
  26#include <linux/module.h>
  27#include <linux/nvram.h>
  28#include <linux/initrd.h>
  29
  30#include <asm/bootinfo.h>
  31#include <asm/byteorder.h>
  32#include <asm/sections.h>
  33#include <asm/setup.h>
  34#include <asm/fpu.h>
  35#include <asm/irq.h>
  36#include <asm/io.h>
  37#include <asm/machdep.h>
  38#ifdef CONFIG_AMIGA
  39#include <asm/amigahw.h>
  40#endif
  41#include <asm/atarihw.h>
  42#ifdef CONFIG_ATARI
  43#include <asm/atari_stram.h>
  44#endif
  45#ifdef CONFIG_SUN3X
  46#include <asm/dvma.h>
  47#endif
  48#include <asm/macintosh.h>
  49#include <asm/natfeat.h>
  50
  51#if !FPSTATESIZE || !NR_IRQS
  52#warning No CPU/platform type selected, your kernel will not work!
  53#warning Are you building an allnoconfig kernel?
  54#endif
  55
  56unsigned long m68k_machtype;
  57EXPORT_SYMBOL(m68k_machtype);
  58unsigned long m68k_cputype;
  59EXPORT_SYMBOL(m68k_cputype);
  60unsigned long m68k_fputype;
  61unsigned long m68k_mmutype;
  62EXPORT_SYMBOL(m68k_mmutype);
  63#ifdef CONFIG_VME
  64unsigned long vme_brdtype;
  65EXPORT_SYMBOL(vme_brdtype);
  66#endif
  67
  68int m68k_is040or060;
  69EXPORT_SYMBOL(m68k_is040or060);
  70
  71extern unsigned long availmem;
  72
  73int m68k_num_memory;
  74EXPORT_SYMBOL(m68k_num_memory);
  75int m68k_realnum_memory;
  76EXPORT_SYMBOL(m68k_realnum_memory);
  77unsigned long m68k_memoffset;
  78struct m68k_mem_info m68k_memory[NUM_MEMINFO];
  79EXPORT_SYMBOL(m68k_memory);
  80
  81static struct m68k_mem_info m68k_ramdisk __initdata;
  82
  83static char m68k_command_line[CL_SIZE] __initdata;
  84
  85void (*mach_sched_init) (void) __initdata = NULL;
  86/* machine dependent irq functions */
  87void (*mach_init_IRQ) (void) __initdata = NULL;
  88void (*mach_get_model) (char *model);
  89void (*mach_get_hardware_list) (struct seq_file *m);
  90/* machine dependent timer functions */
  91int (*mach_hwclk) (int, struct rtc_time*);
  92EXPORT_SYMBOL(mach_hwclk);
  93unsigned int (*mach_get_ss)(void);
  94int (*mach_get_rtc_pll)(struct rtc_pll_info *);
  95int (*mach_set_rtc_pll)(struct rtc_pll_info *);
  96EXPORT_SYMBOL(mach_get_ss);
  97EXPORT_SYMBOL(mach_get_rtc_pll);
  98EXPORT_SYMBOL(mach_set_rtc_pll);
  99void (*mach_reset)( void );
 100void (*mach_halt)( void );
 101void (*mach_power_off)( void );
 102#ifdef CONFIG_HEARTBEAT
 103void (*mach_heartbeat) (int);
 104EXPORT_SYMBOL(mach_heartbeat);
 105#endif
 106#ifdef CONFIG_M68K_L2_CACHE
 107void (*mach_l2_flush) (int);
 108#endif
 109#if defined(CONFIG_ISA) && defined(MULTI_ISA)
 110int isa_type;
 111int isa_sex;
 112EXPORT_SYMBOL(isa_type);
 113EXPORT_SYMBOL(isa_sex);
 114#endif
 115
 116extern int amiga_parse_bootinfo(const struct bi_record *);
 117extern int atari_parse_bootinfo(const struct bi_record *);
 118extern int mac_parse_bootinfo(const struct bi_record *);
 119extern int q40_parse_bootinfo(const struct bi_record *);
 120extern int bvme6000_parse_bootinfo(const struct bi_record *);
 121extern int mvme16x_parse_bootinfo(const struct bi_record *);
 122extern int mvme147_parse_bootinfo(const struct bi_record *);
 123extern int hp300_parse_bootinfo(const struct bi_record *);
 124extern int apollo_parse_bootinfo(const struct bi_record *);
 125
 126extern void config_amiga(void);
 127extern void config_atari(void);
 128extern void config_mac(void);
 129extern void config_sun3(void);
 130extern void config_apollo(void);
 131extern void config_mvme147(void);
 132extern void config_mvme16x(void);
 133extern void config_bvme6000(void);
 134extern void config_hp300(void);
 135extern void config_q40(void);
 136extern void config_sun3x(void);
 137
 138#define MASK_256K 0xfffc0000
 139
 140extern void paging_init(void);
 141
 142static void __init m68k_parse_bootinfo(const struct bi_record *record)
 143{
 144        uint16_t tag;
 145
 146        save_bootinfo(record);
 147
 148        while ((tag = be16_to_cpu(record->tag)) != BI_LAST) {
 149                int unknown = 0;
 150                const void *data = record->data;
 151                uint16_t size = be16_to_cpu(record->size);
 152
 153                switch (tag) {
 154                case BI_MACHTYPE:
 155                case BI_CPUTYPE:
 156                case BI_FPUTYPE:
 157                case BI_MMUTYPE:
 158                        /* Already set up by head.S */
 159                        break;
 160
 161                case BI_MEMCHUNK:
 162                        if (m68k_num_memory < NUM_MEMINFO) {
 163                                const struct mem_info *m = data;
 164                                m68k_memory[m68k_num_memory].addr =
 165                                        be32_to_cpu(m->addr);
 166                                m68k_memory[m68k_num_memory].size =
 167                                        be32_to_cpu(m->size);
 168                                m68k_num_memory++;
 169                        } else
 170                                pr_warn("%s: too many memory chunks\n",
 171                                        __func__);
 172                        break;
 173
 174                case BI_RAMDISK:
 175                        {
 176                                const struct mem_info *m = data;
 177                                m68k_ramdisk.addr = be32_to_cpu(m->addr);
 178                                m68k_ramdisk.size = be32_to_cpu(m->size);
 179                        }
 180                        break;
 181
 182                case BI_COMMAND_LINE:
 183                        strlcpy(m68k_command_line, data,
 184                                sizeof(m68k_command_line));
 185                        break;
 186
 187                default:
 188                        if (MACH_IS_AMIGA)
 189                                unknown = amiga_parse_bootinfo(record);
 190                        else if (MACH_IS_ATARI)
 191                                unknown = atari_parse_bootinfo(record);
 192                        else if (MACH_IS_MAC)
 193                                unknown = mac_parse_bootinfo(record);
 194                        else if (MACH_IS_Q40)
 195                                unknown = q40_parse_bootinfo(record);
 196                        else if (MACH_IS_BVME6000)
 197                                unknown = bvme6000_parse_bootinfo(record);
 198                        else if (MACH_IS_MVME16x)
 199                                unknown = mvme16x_parse_bootinfo(record);
 200                        else if (MACH_IS_MVME147)
 201                                unknown = mvme147_parse_bootinfo(record);
 202                        else if (MACH_IS_HP300)
 203                                unknown = hp300_parse_bootinfo(record);
 204                        else if (MACH_IS_APOLLO)
 205                                unknown = apollo_parse_bootinfo(record);
 206                        else
 207                                unknown = 1;
 208                }
 209                if (unknown)
 210                        pr_warn("%s: unknown tag 0x%04x ignored\n", __func__,
 211                                tag);
 212                record = (struct bi_record *)((unsigned long)record + size);
 213        }
 214
 215        m68k_realnum_memory = m68k_num_memory;
 216#ifdef CONFIG_SINGLE_MEMORY_CHUNK
 217        if (m68k_num_memory > 1) {
 218                pr_warn("%s: ignoring last %i chunks of physical memory\n",
 219                        __func__, (m68k_num_memory - 1));
 220                m68k_num_memory = 1;
 221        }
 222#endif
 223}
 224
 225void __init setup_arch(char **cmdline_p)
 226{
 227        /* The bootinfo is located right after the kernel */
 228        if (!CPU_IS_COLDFIRE)
 229                m68k_parse_bootinfo((const struct bi_record *)_end);
 230
 231        if (CPU_IS_040)
 232                m68k_is040or060 = 4;
 233        else if (CPU_IS_060)
 234                m68k_is040or060 = 6;
 235
 236        /* FIXME: m68k_fputype is passed in by Penguin booter, which can
 237         * be confused by software FPU emulation. BEWARE.
 238         * We should really do our own FPU check at startup.
 239         * [what do we do with buggy 68LC040s? if we have problems
 240         *  with them, we should add a test to check_bugs() below] */
 241#if defined(CONFIG_FPU) && !defined(CONFIG_M68KFPU_EMU_ONLY)
 242        /* clear the fpu if we have one */
 243        if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060|FPU_COLDFIRE)) {
 244                volatile int zero = 0;
 245                asm volatile ("frestore %0" : : "m" (zero));
 246        }
 247#endif
 248
 249        if (CPU_IS_060) {
 250                u32 pcr;
 251
 252                asm (".chip 68060; movec %%pcr,%0; .chip 68k"
 253                     : "=d" (pcr));
 254                if (((pcr >> 8) & 0xff) <= 5) {
 255                        pr_warn("Enabling workaround for errata I14\n");
 256                        asm (".chip 68060; movec %0,%%pcr; .chip 68k"
 257                             : : "d" (pcr | 0x20));
 258                }
 259        }
 260
 261        setup_initial_init_mm((void *)PAGE_OFFSET, _etext, _edata, _end);
 262
 263#if defined(CONFIG_BOOTPARAM)
 264        strncpy(m68k_command_line, CONFIG_BOOTPARAM_STRING, CL_SIZE);
 265        m68k_command_line[CL_SIZE - 1] = 0;
 266#endif /* CONFIG_BOOTPARAM */
 267        process_uboot_commandline(&m68k_command_line[0], CL_SIZE);
 268        *cmdline_p = m68k_command_line;
 269        memcpy(boot_command_line, *cmdline_p, CL_SIZE);
 270
 271        parse_early_param();
 272
 273        switch (m68k_machtype) {
 274#ifdef CONFIG_AMIGA
 275        case MACH_AMIGA:
 276                config_amiga();
 277                break;
 278#endif
 279#ifdef CONFIG_ATARI
 280        case MACH_ATARI:
 281                config_atari();
 282                break;
 283#endif
 284#ifdef CONFIG_MAC
 285        case MACH_MAC:
 286                config_mac();
 287                break;
 288#endif
 289#ifdef CONFIG_SUN3
 290        case MACH_SUN3:
 291                config_sun3();
 292                break;
 293#endif
 294#ifdef CONFIG_APOLLO
 295        case MACH_APOLLO:
 296                config_apollo();
 297                break;
 298#endif
 299#ifdef CONFIG_MVME147
 300        case MACH_MVME147:
 301                config_mvme147();
 302                break;
 303#endif
 304#ifdef CONFIG_MVME16x
 305        case MACH_MVME16x:
 306                config_mvme16x();
 307                break;
 308#endif
 309#ifdef CONFIG_BVME6000
 310        case MACH_BVME6000:
 311                config_bvme6000();
 312                break;
 313#endif
 314#ifdef CONFIG_HP300
 315        case MACH_HP300:
 316                config_hp300();
 317                break;
 318#endif
 319#ifdef CONFIG_Q40
 320        case MACH_Q40:
 321                config_q40();
 322                break;
 323#endif
 324#ifdef CONFIG_SUN3X
 325        case MACH_SUN3X:
 326                config_sun3x();
 327                break;
 328#endif
 329#ifdef CONFIG_COLDFIRE
 330        case MACH_M54XX:
 331        case MACH_M5441X:
 332                cf_bootmem_alloc();
 333                cf_mmu_context_init();
 334                config_BSP(NULL, 0);
 335                break;
 336#endif
 337        default:
 338                panic("No configuration setup");
 339        }
 340
 341        paging_init();
 342
 343#ifdef CONFIG_NATFEAT
 344        nf_init();
 345#endif
 346
 347#ifndef CONFIG_SUN3
 348#ifdef CONFIG_BLK_DEV_INITRD
 349        if (m68k_ramdisk.size) {
 350                memblock_reserve(m68k_ramdisk.addr, m68k_ramdisk.size);
 351                initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
 352                initrd_end = initrd_start + m68k_ramdisk.size;
 353                pr_info("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
 354        }
 355#endif
 356
 357#ifdef CONFIG_ATARI
 358        if (MACH_IS_ATARI)
 359                atari_stram_reserve_pages((void *)availmem);
 360#endif
 361#ifdef CONFIG_SUN3X
 362        if (MACH_IS_SUN3X) {
 363                dvma_init();
 364        }
 365#endif
 366
 367#endif /* !CONFIG_SUN3 */
 368
 369/* set ISA defs early as possible */
 370#if defined(CONFIG_ISA) && defined(MULTI_ISA)
 371        if (MACH_IS_Q40) {
 372                isa_type = ISA_TYPE_Q40;
 373                isa_sex = 0;
 374        }
 375#ifdef CONFIG_AMIGA_PCMCIA
 376        if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
 377                isa_type = ISA_TYPE_AG;
 378                isa_sex = 1;
 379        }
 380#endif
 381#ifdef CONFIG_ATARI_ROM_ISA
 382        if (MACH_IS_ATARI) {
 383                isa_type = ISA_TYPE_ENEC;
 384                isa_sex = 0;
 385        }
 386#endif
 387#endif
 388}
 389
 390static int show_cpuinfo(struct seq_file *m, void *v)
 391{
 392        const char *cpu, *mmu, *fpu;
 393        unsigned long clockfreq, clockfactor;
 394
 395#define LOOP_CYCLES_68020       (8)
 396#define LOOP_CYCLES_68030       (8)
 397#define LOOP_CYCLES_68040       (3)
 398#define LOOP_CYCLES_68060       (1)
 399#define LOOP_CYCLES_COLDFIRE    (2)
 400
 401        if (CPU_IS_020) {
 402                cpu = "68020";
 403                clockfactor = LOOP_CYCLES_68020;
 404        } else if (CPU_IS_030) {
 405                cpu = "68030";
 406                clockfactor = LOOP_CYCLES_68030;
 407        } else if (CPU_IS_040) {
 408                cpu = "68040";
 409                clockfactor = LOOP_CYCLES_68040;
 410        } else if (CPU_IS_060) {
 411                cpu = "68060";
 412                clockfactor = LOOP_CYCLES_68060;
 413        } else if (CPU_IS_COLDFIRE) {
 414                cpu = "ColdFire";
 415                clockfactor = LOOP_CYCLES_COLDFIRE;
 416        } else {
 417                cpu = "680x0";
 418                clockfactor = 0;
 419        }
 420
 421#ifdef CONFIG_M68KFPU_EMU_ONLY
 422        fpu = "none(soft float)";
 423#else
 424        if (m68k_fputype & FPU_68881)
 425                fpu = "68881";
 426        else if (m68k_fputype & FPU_68882)
 427                fpu = "68882";
 428        else if (m68k_fputype & FPU_68040)
 429                fpu = "68040";
 430        else if (m68k_fputype & FPU_68060)
 431                fpu = "68060";
 432        else if (m68k_fputype & FPU_SUNFPA)
 433                fpu = "Sun FPA";
 434        else if (m68k_fputype & FPU_COLDFIRE)
 435                fpu = "ColdFire";
 436        else
 437                fpu = "none";
 438#endif
 439
 440        if (m68k_mmutype & MMU_68851)
 441                mmu = "68851";
 442        else if (m68k_mmutype & MMU_68030)
 443                mmu = "68030";
 444        else if (m68k_mmutype & MMU_68040)
 445                mmu = "68040";
 446        else if (m68k_mmutype & MMU_68060)
 447                mmu = "68060";
 448        else if (m68k_mmutype & MMU_SUN3)
 449                mmu = "Sun-3";
 450        else if (m68k_mmutype & MMU_APOLLO)
 451                mmu = "Apollo";
 452        else if (m68k_mmutype & MMU_COLDFIRE)
 453                mmu = "ColdFire";
 454        else
 455                mmu = "unknown";
 456
 457        clockfreq = loops_per_jiffy * HZ * clockfactor;
 458
 459        seq_printf(m, "CPU:\t\t%s\n"
 460                   "MMU:\t\t%s\n"
 461                   "FPU:\t\t%s\n"
 462                   "Clocking:\t%lu.%1luMHz\n"
 463                   "BogoMips:\t%lu.%02lu\n"
 464                   "Calibration:\t%lu loops\n",
 465                   cpu, mmu, fpu,
 466                   clockfreq/1000000,(clockfreq/100000)%10,
 467                   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
 468                   loops_per_jiffy);
 469        return 0;
 470}
 471
 472static void *c_start(struct seq_file *m, loff_t *pos)
 473{
 474        return *pos < 1 ? (void *)1 : NULL;
 475}
 476static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 477{
 478        ++*pos;
 479        return NULL;
 480}
 481static void c_stop(struct seq_file *m, void *v)
 482{
 483}
 484const struct seq_operations cpuinfo_op = {
 485        .start  = c_start,
 486        .next   = c_next,
 487        .stop   = c_stop,
 488        .show   = show_cpuinfo,
 489};
 490
 491#ifdef CONFIG_PROC_HARDWARE
 492static int hardware_proc_show(struct seq_file *m, void *v)
 493{
 494        char model[80];
 495        unsigned long mem;
 496        int i;
 497
 498        if (mach_get_model)
 499                mach_get_model(model);
 500        else
 501                strcpy(model, "Unknown m68k");
 502
 503        seq_printf(m, "Model:\t\t%s\n", model);
 504        for (mem = 0, i = 0; i < m68k_num_memory; i++)
 505                mem += m68k_memory[i].size;
 506        seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
 507
 508        if (mach_get_hardware_list)
 509                mach_get_hardware_list(m);
 510
 511        return 0;
 512}
 513
 514static int __init proc_hardware_init(void)
 515{
 516        proc_create_single("hardware", 0, NULL, hardware_proc_show);
 517        return 0;
 518}
 519module_init(proc_hardware_init);
 520#endif
 521
 522void check_bugs(void)
 523{
 524#if defined(CONFIG_FPU) && !defined(CONFIG_M68KFPU_EMU)
 525        if (m68k_fputype == 0) {
 526                pr_emerg("*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
 527                        "WHICH IS REQUIRED BY LINUX/M68K ***\n");
 528                pr_emerg("Upgrade your hardware or join the FPU "
 529                        "emulation project\n");
 530                panic("no FPU");
 531        }
 532#endif /* !CONFIG_M68KFPU_EMU */
 533}
 534
 535#ifdef CONFIG_ADB
 536static int __init adb_probe_sync_enable (char *str) {
 537        extern int __adb_probe_sync;
 538        __adb_probe_sync = 1;
 539        return 1;
 540}
 541
 542__setup("adb_sync", adb_probe_sync_enable);
 543#endif /* CONFIG_ADB */
 544
 545#if IS_ENABLED(CONFIG_NVRAM)
 546#ifdef CONFIG_MAC
 547static unsigned char m68k_nvram_read_byte(int addr)
 548{
 549        if (MACH_IS_MAC)
 550                return mac_pram_read_byte(addr);
 551        return 0xff;
 552}
 553
 554static void m68k_nvram_write_byte(unsigned char val, int addr)
 555{
 556        if (MACH_IS_MAC)
 557                mac_pram_write_byte(val, addr);
 558}
 559#endif /* CONFIG_MAC */
 560
 561#ifdef CONFIG_ATARI
 562static ssize_t m68k_nvram_read(char *buf, size_t count, loff_t *ppos)
 563{
 564        if (MACH_IS_ATARI)
 565                return atari_nvram_read(buf, count, ppos);
 566        else if (MACH_IS_MAC)
 567                return nvram_read_bytes(buf, count, ppos);
 568        return -EINVAL;
 569}
 570
 571static ssize_t m68k_nvram_write(char *buf, size_t count, loff_t *ppos)
 572{
 573        if (MACH_IS_ATARI)
 574                return atari_nvram_write(buf, count, ppos);
 575        else if (MACH_IS_MAC)
 576                return nvram_write_bytes(buf, count, ppos);
 577        return -EINVAL;
 578}
 579
 580static long m68k_nvram_set_checksum(void)
 581{
 582        if (MACH_IS_ATARI)
 583                return atari_nvram_set_checksum();
 584        return -EINVAL;
 585}
 586
 587static long m68k_nvram_initialize(void)
 588{
 589        if (MACH_IS_ATARI)
 590                return atari_nvram_initialize();
 591        return -EINVAL;
 592}
 593#endif /* CONFIG_ATARI */
 594
 595static ssize_t m68k_nvram_get_size(void)
 596{
 597        if (MACH_IS_ATARI)
 598                return atari_nvram_get_size();
 599        else if (MACH_IS_MAC)
 600                return mac_pram_get_size();
 601        return -ENODEV;
 602}
 603
 604/* Atari device drivers call .read (to get checksum validation) whereas
 605 * Mac and PowerMac device drivers just use .read_byte.
 606 */
 607const struct nvram_ops arch_nvram_ops = {
 608#ifdef CONFIG_MAC
 609        .read_byte      = m68k_nvram_read_byte,
 610        .write_byte     = m68k_nvram_write_byte,
 611#endif
 612#ifdef CONFIG_ATARI
 613        .read           = m68k_nvram_read,
 614        .write          = m68k_nvram_write,
 615        .set_checksum   = m68k_nvram_set_checksum,
 616        .initialize     = m68k_nvram_initialize,
 617#endif
 618        .get_size       = m68k_nvram_get_size,
 619};
 620EXPORT_SYMBOL(arch_nvram_ops);
 621#endif /* CONFIG_NVRAM */
 622