diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/sgi-ip30/ip30-setup.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/sgi-ip30/ip30-setup.c')
-rw-r--r-- | arch/mips/sgi-ip30/ip30-setup.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/arch/mips/sgi-ip30/ip30-setup.c b/arch/mips/sgi-ip30/ip30-setup.c new file mode 100644 index 000000000..44b1607e9 --- /dev/null +++ b/arch/mips/sgi-ip30/ip30-setup.c | |||
@@ -0,0 +1,138 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * SGI IP30 miscellaneous setup bits. | ||
4 | * | ||
5 | * Copyright (C) 2004-2007 Stanislaw Skowronek <skylark@unaligned.org> | ||
6 | * 2007 Joshua Kinard <kumba@gentoo.org> | ||
7 | * 2009 Johannes Dickgreber <tanzy@gmx.de> | ||
8 | */ | ||
9 | |||
10 | #include <linux/init.h> | ||
11 | #include <linux/io.h> | ||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/percpu.h> | ||
15 | #include <linux/memblock.h> | ||
16 | |||
17 | #include <asm/smp-ops.h> | ||
18 | #include <asm/sgialib.h> | ||
19 | #include <asm/time.h> | ||
20 | #include <asm/sgi/heart.h> | ||
21 | |||
22 | #include "ip30-common.h" | ||
23 | |||
24 | /* Structure of accessible HEART registers located in XKPHYS space. */ | ||
25 | struct ip30_heart_regs __iomem *heart_regs = HEART_XKPHYS_BASE; | ||
26 | |||
27 | /* | ||
28 | * ARCS will report up to the first 1GB of | ||
29 | * memory if queried. Anything beyond that | ||
30 | * is marked as reserved. | ||
31 | */ | ||
32 | #define IP30_MAX_PROM_MEMORY _AC(0x40000000, UL) | ||
33 | |||
34 | /* | ||
35 | * Memory in the Octane starts at 512MB | ||
36 | */ | ||
37 | #define IP30_MEMORY_BASE _AC(0x20000000, UL) | ||
38 | |||
39 | /* | ||
40 | * If using ARCS to probe for memory, then | ||
41 | * remaining memory will start at this offset. | ||
42 | */ | ||
43 | #define IP30_REAL_MEMORY_START (IP30_MEMORY_BASE + IP30_MAX_PROM_MEMORY) | ||
44 | |||
45 | #define MEM_SHIFT(x) ((x) >> 20) | ||
46 | |||
47 | static void __init ip30_mem_init(void) | ||
48 | { | ||
49 | unsigned long total_mem; | ||
50 | phys_addr_t addr; | ||
51 | phys_addr_t size; | ||
52 | u32 memcfg; | ||
53 | int i; | ||
54 | |||
55 | total_mem = 0; | ||
56 | for (i = 0; i < HEART_MEMORY_BANKS; i++) { | ||
57 | memcfg = __raw_readl(&heart_regs->mem_cfg.l[i]); | ||
58 | if (!(memcfg & HEART_MEMCFG_VALID)) | ||
59 | continue; | ||
60 | |||
61 | addr = memcfg & HEART_MEMCFG_ADDR_MASK; | ||
62 | addr <<= HEART_MEMCFG_UNIT_SHIFT; | ||
63 | addr += IP30_MEMORY_BASE; | ||
64 | size = memcfg & HEART_MEMCFG_SIZE_MASK; | ||
65 | size >>= HEART_MEMCFG_SIZE_SHIFT; | ||
66 | size += 1; | ||
67 | size <<= HEART_MEMCFG_UNIT_SHIFT; | ||
68 | |||
69 | total_mem += size; | ||
70 | |||
71 | if (addr >= IP30_REAL_MEMORY_START) | ||
72 | memblock_free(addr, size); | ||
73 | else if ((addr + size) > IP30_REAL_MEMORY_START) | ||
74 | memblock_free(IP30_REAL_MEMORY_START, | ||
75 | size - IP30_MAX_PROM_MEMORY); | ||
76 | } | ||
77 | pr_info("Detected %luMB of physical memory.\n", MEM_SHIFT(total_mem)); | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * ip30_cpu_time_init - platform time initialization. | ||
82 | */ | ||
83 | static void __init ip30_cpu_time_init(void) | ||
84 | { | ||
85 | int cpu = smp_processor_id(); | ||
86 | u64 heart_compare; | ||
87 | unsigned int start, end; | ||
88 | int time_diff; | ||
89 | |||
90 | heart_compare = (heart_read(&heart_regs->count) + | ||
91 | (HEART_CYCLES_PER_SEC / 10)); | ||
92 | start = read_c0_count(); | ||
93 | while ((heart_read(&heart_regs->count) - heart_compare) & 0x800000) | ||
94 | cpu_relax(); | ||
95 | |||
96 | end = read_c0_count(); | ||
97 | time_diff = (int)end - (int)start; | ||
98 | mips_hpt_frequency = time_diff * 10; | ||
99 | pr_info("IP30: CPU%d: %d MHz CPU detected.\n", cpu, | ||
100 | (mips_hpt_frequency * 2) / 1000000); | ||
101 | } | ||
102 | |||
103 | void __init ip30_per_cpu_init(void) | ||
104 | { | ||
105 | /* Disable all interrupts. */ | ||
106 | clear_c0_status(ST0_IM); | ||
107 | |||
108 | ip30_cpu_time_init(); | ||
109 | #ifdef CONFIG_SMP | ||
110 | ip30_install_ipi(); | ||
111 | #endif | ||
112 | |||
113 | enable_percpu_irq(IP30_HEART_L0_IRQ, IRQ_TYPE_NONE); | ||
114 | enable_percpu_irq(IP30_HEART_L1_IRQ, IRQ_TYPE_NONE); | ||
115 | enable_percpu_irq(IP30_HEART_L2_IRQ, IRQ_TYPE_NONE); | ||
116 | enable_percpu_irq(IP30_HEART_ERR_IRQ, IRQ_TYPE_NONE); | ||
117 | } | ||
118 | |||
119 | /** | ||
120 | * plat_mem_setup - despite the name, misc setup happens here. | ||
121 | */ | ||
122 | void __init plat_mem_setup(void) | ||
123 | { | ||
124 | ip30_mem_init(); | ||
125 | |||
126 | /* XXX: Hard lock on /sbin/init if this flag isn't specified. */ | ||
127 | prom_flags |= PROM_FLAG_DONT_FREE_TEMP; | ||
128 | |||
129 | #ifdef CONFIG_SMP | ||
130 | register_smp_ops(&ip30_smp_ops); | ||
131 | #else | ||
132 | ip30_per_cpu_init(); | ||
133 | #endif | ||
134 | |||
135 | ioport_resource.start = 0; | ||
136 | ioport_resource.end = ~0UL; | ||
137 | set_io_port_base(IO_BASE); | ||
138 | } | ||