Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * SGI IP30 miscellaneous setup bits.
0004  *
0005  * Copyright (C) 2004-2007 Stanislaw Skowronek <skylark@unaligned.org>
0006  *               2007 Joshua Kinard <kumba@gentoo.org>
0007  *               2009 Johannes Dickgreber <tanzy@gmx.de>
0008  */
0009 
0010 #include <linux/init.h>
0011 #include <linux/io.h>
0012 #include <linux/kernel.h>
0013 #include <linux/types.h>
0014 #include <linux/percpu.h>
0015 #include <linux/memblock.h>
0016 
0017 #include <asm/smp-ops.h>
0018 #include <asm/sgialib.h>
0019 #include <asm/time.h>
0020 #include <asm/sgi/heart.h>
0021 
0022 #include "ip30-common.h"
0023 
0024 /* Structure of accessible HEART registers located in XKPHYS space. */
0025 struct ip30_heart_regs __iomem *heart_regs = HEART_XKPHYS_BASE;
0026 
0027 /*
0028  * ARCS will report up to the first 1GB of
0029  * memory if queried.  Anything beyond that
0030  * is marked as reserved.
0031  */
0032 #define IP30_MAX_PROM_MEMORY    _AC(0x40000000, UL)
0033 
0034 /*
0035  * Memory in the Octane starts at 512MB
0036  */
0037 #define IP30_MEMORY_BASE    _AC(0x20000000, UL)
0038 
0039 /*
0040  * If using ARCS to probe for memory, then
0041  * remaining memory will start at this offset.
0042  */
0043 #define IP30_REAL_MEMORY_START  (IP30_MEMORY_BASE + IP30_MAX_PROM_MEMORY)
0044 
0045 #define MEM_SHIFT(x) ((x) >> 20)
0046 
0047 static void __init ip30_mem_init(void)
0048 {
0049     unsigned long total_mem;
0050     phys_addr_t addr;
0051     phys_addr_t size;
0052     u32 memcfg;
0053     int i;
0054 
0055     total_mem = 0;
0056     for (i = 0; i < HEART_MEMORY_BANKS; i++) {
0057         memcfg = __raw_readl(&heart_regs->mem_cfg.l[i]);
0058         if (!(memcfg & HEART_MEMCFG_VALID))
0059             continue;
0060 
0061         addr = memcfg & HEART_MEMCFG_ADDR_MASK;
0062         addr <<= HEART_MEMCFG_UNIT_SHIFT;
0063         addr += IP30_MEMORY_BASE;
0064         size = memcfg & HEART_MEMCFG_SIZE_MASK;
0065         size >>= HEART_MEMCFG_SIZE_SHIFT;
0066         size += 1;
0067         size <<= HEART_MEMCFG_UNIT_SHIFT;
0068 
0069         total_mem += size;
0070 
0071         if (addr >= IP30_REAL_MEMORY_START)
0072             memblock_phys_free(addr, size);
0073         else if ((addr + size) > IP30_REAL_MEMORY_START)
0074             memblock_phys_free(IP30_REAL_MEMORY_START,
0075                        size - IP30_MAX_PROM_MEMORY);
0076     }
0077     pr_info("Detected %luMB of physical memory.\n", MEM_SHIFT(total_mem));
0078 }
0079 
0080 /**
0081  * ip30_cpu_time_init - platform time initialization.
0082  */
0083 static void __init ip30_cpu_time_init(void)
0084 {
0085     int cpu = smp_processor_id();
0086     u64 heart_compare;
0087     unsigned int start, end;
0088     int time_diff;
0089 
0090     heart_compare = (heart_read(&heart_regs->count) +
0091              (HEART_CYCLES_PER_SEC / 10));
0092     start = read_c0_count();
0093     while ((heart_read(&heart_regs->count) - heart_compare) & 0x800000)
0094         cpu_relax();
0095 
0096     end = read_c0_count();
0097     time_diff = (int)end - (int)start;
0098     mips_hpt_frequency = time_diff * 10;
0099     pr_info("IP30: CPU%d: %d MHz CPU detected.\n", cpu,
0100         (mips_hpt_frequency * 2) / 1000000);
0101 }
0102 
0103 void __init ip30_per_cpu_init(void)
0104 {
0105     /* Disable all interrupts. */
0106     clear_c0_status(ST0_IM);
0107 
0108     ip30_cpu_time_init();
0109 #ifdef CONFIG_SMP
0110     ip30_install_ipi();
0111 #endif
0112 
0113     enable_percpu_irq(IP30_HEART_L0_IRQ, IRQ_TYPE_NONE);
0114     enable_percpu_irq(IP30_HEART_L1_IRQ, IRQ_TYPE_NONE);
0115     enable_percpu_irq(IP30_HEART_L2_IRQ, IRQ_TYPE_NONE);
0116     enable_percpu_irq(IP30_HEART_ERR_IRQ, IRQ_TYPE_NONE);
0117 }
0118 
0119 /**
0120  * plat_mem_setup - despite the name, misc setup happens here.
0121  */
0122 void __init plat_mem_setup(void)
0123 {
0124     ip30_mem_init();
0125 
0126     /* XXX: Hard lock on /sbin/init if this flag isn't specified. */
0127     prom_flags |= PROM_FLAG_DONT_FREE_TEMP;
0128 
0129 #ifdef CONFIG_SMP
0130     register_smp_ops(&ip30_smp_ops);
0131 #else
0132     ip30_per_cpu_init();
0133 #endif
0134 
0135     ioport_resource.start = 0;
0136     ioport_resource.end = ~0UL;
0137     set_io_port_base(IO_BASE);
0138 }