aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon/setup.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/cavium-octeon/setup.c')
-rw-r--r--arch/mips/cavium-octeon/setup.c312
1 files changed, 305 insertions, 7 deletions
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c
index 67aa3b942f06..7c2b7aab77ba 100644
--- a/arch/mips/cavium-octeon/setup.c
+++ b/arch/mips/cavium-octeon/setup.c
@@ -25,6 +25,7 @@
25#include <linux/serial_8250.h> 25#include <linux/serial_8250.h>
26#include <linux/of_fdt.h> 26#include <linux/of_fdt.h>
27#include <linux/libfdt.h> 27#include <linux/libfdt.h>
28#include <linux/kexec.h>
28 29
29#include <asm/processor.h> 30#include <asm/processor.h>
30#include <asm/reboot.h> 31#include <asm/reboot.h>
@@ -58,11 +59,208 @@ struct octeon_boot_descriptor *octeon_boot_desc_ptr;
58struct cvmx_bootinfo *octeon_bootinfo; 59struct cvmx_bootinfo *octeon_bootinfo;
59EXPORT_SYMBOL(octeon_bootinfo); 60EXPORT_SYMBOL(octeon_bootinfo);
60 61
62static unsigned long long RESERVE_LOW_MEM = 0ull;
63#ifdef CONFIG_KEXEC
64#ifdef CONFIG_SMP
65/*
66 * Wait for relocation code is prepared and send
67 * secondary CPUs to spin until kernel is relocated.
68 */
69static void octeon_kexec_smp_down(void *ignored)
70{
71 int cpu = smp_processor_id();
72
73 local_irq_disable();
74 set_cpu_online(cpu, false);
75 while (!atomic_read(&kexec_ready_to_reboot))
76 cpu_relax();
77
78 asm volatile (
79 " sync \n"
80 " synci ($0) \n");
81
82 relocated_kexec_smp_wait(NULL);
83}
84#endif
85
86#define OCTEON_DDR0_BASE (0x0ULL)
87#define OCTEON_DDR0_SIZE (0x010000000ULL)
88#define OCTEON_DDR1_BASE (0x410000000ULL)
89#define OCTEON_DDR1_SIZE (0x010000000ULL)
90#define OCTEON_DDR2_BASE (0x020000000ULL)
91#define OCTEON_DDR2_SIZE (0x3e0000000ULL)
92#define OCTEON_MAX_PHY_MEM_SIZE (16*1024*1024*1024ULL)
93
94static struct kimage *kimage_ptr;
95
96static void kexec_bootmem_init(uint64_t mem_size, uint32_t low_reserved_bytes)
97{
98 int64_t addr;
99 struct cvmx_bootmem_desc *bootmem_desc;
100
101 bootmem_desc = cvmx_bootmem_get_desc();
102
103 if (mem_size > OCTEON_MAX_PHY_MEM_SIZE) {
104 mem_size = OCTEON_MAX_PHY_MEM_SIZE;
105 pr_err("Error: requested memory too large,"
106 "truncating to maximum size\n");
107 }
108
109 bootmem_desc->major_version = CVMX_BOOTMEM_DESC_MAJ_VER;
110 bootmem_desc->minor_version = CVMX_BOOTMEM_DESC_MIN_VER;
111
112 addr = (OCTEON_DDR0_BASE + RESERVE_LOW_MEM + low_reserved_bytes);
113 bootmem_desc->head_addr = 0;
114
115 if (mem_size <= OCTEON_DDR0_SIZE) {
116 __cvmx_bootmem_phy_free(addr,
117 mem_size - RESERVE_LOW_MEM -
118 low_reserved_bytes, 0);
119 return;
120 }
121
122 __cvmx_bootmem_phy_free(addr,
123 OCTEON_DDR0_SIZE - RESERVE_LOW_MEM -
124 low_reserved_bytes, 0);
125
126 mem_size -= OCTEON_DDR0_SIZE;
127
128 if (mem_size > OCTEON_DDR1_SIZE) {
129 __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, OCTEON_DDR1_SIZE, 0);
130 __cvmx_bootmem_phy_free(OCTEON_DDR2_BASE,
131 mem_size - OCTEON_DDR1_SIZE, 0);
132 } else
133 __cvmx_bootmem_phy_free(OCTEON_DDR1_BASE, mem_size, 0);
134}
135
136static int octeon_kexec_prepare(struct kimage *image)
137{
138 int i;
139 char *bootloader = "kexec";
140
141 octeon_boot_desc_ptr->argc = 0;
142 for (i = 0; i < image->nr_segments; i++) {
143 if (!strncmp(bootloader, (char *)image->segment[i].buf,
144 strlen(bootloader))) {
145 /*
146 * convert command line string to array
147 * of parameters (as bootloader does).
148 */
149 int argc = 0, offt;
150 char *str = (char *)image->segment[i].buf;
151 char *ptr = strchr(str, ' ');
152 while (ptr && (OCTEON_ARGV_MAX_ARGS > argc)) {
153 *ptr = '\0';
154 if (ptr[1] != ' ') {
155 offt = (int)(ptr - str + 1);
156 octeon_boot_desc_ptr->argv[argc] =
157 image->segment[i].mem + offt;
158 argc++;
159 }
160 ptr = strchr(ptr + 1, ' ');
161 }
162 octeon_boot_desc_ptr->argc = argc;
163 break;
164 }
165 }
166
167 /*
168 * Information about segments will be needed during pre-boot memory
169 * initialization.
170 */
171 kimage_ptr = image;
172 return 0;
173}
174
175static void octeon_generic_shutdown(void)
176{
177 int cpu, i;
178 struct cvmx_bootmem_desc *bootmem_desc;
179 void *named_block_array_ptr;
180
181 bootmem_desc = cvmx_bootmem_get_desc();
182 named_block_array_ptr =
183 cvmx_phys_to_ptr(bootmem_desc->named_block_array_addr);
184
185#ifdef CONFIG_SMP
186 /* disable watchdogs */
187 for_each_online_cpu(cpu)
188 cvmx_write_csr(CVMX_CIU_WDOGX(cpu_logical_map(cpu)), 0);
189#else
190 cvmx_write_csr(CVMX_CIU_WDOGX(cvmx_get_core_num()), 0);
191#endif
192 if (kimage_ptr != kexec_crash_image) {
193 memset(named_block_array_ptr,
194 0x0,
195 CVMX_BOOTMEM_NUM_NAMED_BLOCKS *
196 sizeof(struct cvmx_bootmem_named_block_desc));
197 /*
198 * Mark all memory (except low 0x100000 bytes) as free.
199 * It is the same thing that bootloader does.
200 */
201 kexec_bootmem_init(octeon_bootinfo->dram_size*1024ULL*1024ULL,
202 0x100000);
203 /*
204 * Allocate all segments to avoid their corruption during boot.
205 */
206 for (i = 0; i < kimage_ptr->nr_segments; i++)
207 cvmx_bootmem_alloc_address(
208 kimage_ptr->segment[i].memsz + 2*PAGE_SIZE,
209 kimage_ptr->segment[i].mem - PAGE_SIZE,
210 PAGE_SIZE);
211 } else {
212 /*
213 * Do not mark all memory as free. Free only named sections
214 * leaving the rest of memory unchanged.
215 */
216 struct cvmx_bootmem_named_block_desc *ptr =
217 (struct cvmx_bootmem_named_block_desc *)
218 named_block_array_ptr;
219
220 for (i = 0; i < bootmem_desc->named_block_num_blocks; i++)
221 if (ptr[i].size)
222 cvmx_bootmem_free_named(ptr[i].name);
223 }
224 kexec_args[2] = 1UL; /* running on octeon_main_processor */
225 kexec_args[3] = (unsigned long)octeon_boot_desc_ptr;
226#ifdef CONFIG_SMP
227 secondary_kexec_args[2] = 0UL; /* running on secondary cpu */
228 secondary_kexec_args[3] = (unsigned long)octeon_boot_desc_ptr;
229#endif
230}
231
232static void octeon_shutdown(void)
233{
234 octeon_generic_shutdown();
235#ifdef CONFIG_SMP
236 smp_call_function(octeon_kexec_smp_down, NULL, 0);
237 smp_wmb();
238 while (num_online_cpus() > 1) {
239 cpu_relax();
240 mdelay(1);
241 }
242#endif
243}
244
245static void octeon_crash_shutdown(struct pt_regs *regs)
246{
247 octeon_generic_shutdown();
248 default_machine_crash_shutdown(regs);
249}
250
251#endif /* CONFIG_KEXEC */
252
61#ifdef CONFIG_CAVIUM_RESERVE32 253#ifdef CONFIG_CAVIUM_RESERVE32
62uint64_t octeon_reserve32_memory; 254uint64_t octeon_reserve32_memory;
63EXPORT_SYMBOL(octeon_reserve32_memory); 255EXPORT_SYMBOL(octeon_reserve32_memory);
64#endif 256#endif
65 257
258#ifdef CONFIG_KEXEC
259/* crashkernel cmdline parameter is parsed _after_ memory setup
260 * we also parse it here (workaround for EHB5200) */
261static uint64_t crashk_size, crashk_base;
262#endif
263
66static int octeon_uart; 264static int octeon_uart;
67 265
68extern asmlinkage void handle_int(void); 266extern asmlinkage void handle_int(void);
@@ -417,6 +615,8 @@ void octeon_user_io_init(void)
417void __init prom_init(void) 615void __init prom_init(void)
418{ 616{
419 struct cvmx_sysinfo *sysinfo; 617 struct cvmx_sysinfo *sysinfo;
618 const char *arg;
619 char *p;
420 int i; 620 int i;
421 int argc; 621 int argc;
422#ifdef CONFIG_CAVIUM_RESERVE32 622#ifdef CONFIG_CAVIUM_RESERVE32
@@ -568,6 +768,15 @@ void __init prom_init(void)
568 if (octeon_is_simulation()) 768 if (octeon_is_simulation())
569 MAX_MEMORY = 64ull << 20; 769 MAX_MEMORY = 64ull << 20;
570 770
771 arg = strstr(arcs_cmdline, "mem=");
772 if (arg) {
773 MAX_MEMORY = memparse(arg + 4, &p);
774 if (MAX_MEMORY == 0)
775 MAX_MEMORY = 32ull << 30;
776 if (*p == '@')
777 RESERVE_LOW_MEM = memparse(p + 1, &p);
778 }
779
571 arcs_cmdline[0] = 0; 780 arcs_cmdline[0] = 0;
572 argc = octeon_boot_desc_ptr->argc; 781 argc = octeon_boot_desc_ptr->argc;
573 for (i = 0; i < argc; i++) { 782 for (i = 0; i < argc; i++) {
@@ -575,16 +784,30 @@ void __init prom_init(void)
575 cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]); 784 cvmx_phys_to_ptr(octeon_boot_desc_ptr->argv[i]);
576 if ((strncmp(arg, "MEM=", 4) == 0) || 785 if ((strncmp(arg, "MEM=", 4) == 0) ||
577 (strncmp(arg, "mem=", 4) == 0)) { 786 (strncmp(arg, "mem=", 4) == 0)) {
578 sscanf(arg + 4, "%llu", &MAX_MEMORY); 787 MAX_MEMORY = memparse(arg + 4, &p);
579 MAX_MEMORY <<= 20;
580 if (MAX_MEMORY == 0) 788 if (MAX_MEMORY == 0)
581 MAX_MEMORY = 32ull << 30; 789 MAX_MEMORY = 32ull << 30;
790 if (*p == '@')
791 RESERVE_LOW_MEM = memparse(p + 1, &p);
582 } else if (strcmp(arg, "ecc_verbose") == 0) { 792 } else if (strcmp(arg, "ecc_verbose") == 0) {
583#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC 793#ifdef CONFIG_CAVIUM_REPORT_SINGLE_BIT_ECC
584 __cvmx_interrupt_ecc_report_single_bit_errors = 1; 794 __cvmx_interrupt_ecc_report_single_bit_errors = 1;
585 pr_notice("Reporting of single bit ECC errors is " 795 pr_notice("Reporting of single bit ECC errors is "
586 "turned on\n"); 796 "turned on\n");
587#endif 797#endif
798#ifdef CONFIG_KEXEC
799 } else if (strncmp(arg, "crashkernel=", 12) == 0) {
800 crashk_size = memparse(arg+12, &p);
801 if (*p == '@')
802 crashk_base = memparse(p+1, &p);
803 strcat(arcs_cmdline, " ");
804 strcat(arcs_cmdline, arg);
805 /*
806 * To do: switch parsing to new style, something like:
807 * parse_crashkernel(arg, sysinfo->system_dram_size,
808 * &crashk_size, &crashk_base);
809 */
810#endif
588 } else if (strlen(arcs_cmdline) + strlen(arg) + 1 < 811 } else if (strlen(arcs_cmdline) + strlen(arg) + 1 <
589 sizeof(arcs_cmdline) - 1) { 812 sizeof(arcs_cmdline) - 1) {
590 strcat(arcs_cmdline, " "); 813 strcat(arcs_cmdline, " ");
@@ -619,11 +842,18 @@ void __init prom_init(void)
619 _machine_restart = octeon_restart; 842 _machine_restart = octeon_restart;
620 _machine_halt = octeon_halt; 843 _machine_halt = octeon_halt;
621 844
845#ifdef CONFIG_KEXEC
846 _machine_kexec_shutdown = octeon_shutdown;
847 _machine_crash_shutdown = octeon_crash_shutdown;
848 _machine_kexec_prepare = octeon_kexec_prepare;
849#endif
850
622 octeon_user_io_init(); 851 octeon_user_io_init();
623 register_smp_ops(&octeon_smp_ops); 852 register_smp_ops(&octeon_smp_ops);
624} 853}
625 854
626/* Exclude a single page from the regions obtained in plat_mem_setup. */ 855/* Exclude a single page from the regions obtained in plat_mem_setup. */
856#ifndef CONFIG_CRASH_DUMP
627static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size) 857static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
628{ 858{
629 if (addr > *mem && addr < *mem + *size) { 859 if (addr > *mem && addr < *mem + *size) {
@@ -638,14 +868,21 @@ static __init void memory_exclude_page(u64 addr, u64 *mem, u64 *size)
638 *size -= PAGE_SIZE; 868 *size -= PAGE_SIZE;
639 } 869 }
640} 870}
871#endif /* CONFIG_CRASH_DUMP */
641 872
642void __init plat_mem_setup(void) 873void __init plat_mem_setup(void)
643{ 874{
644 uint64_t mem_alloc_size; 875 uint64_t mem_alloc_size;
645 uint64_t total; 876 uint64_t total;
877 uint64_t crashk_end;
878#ifndef CONFIG_CRASH_DUMP
646 int64_t memory; 879 int64_t memory;
880 uint64_t kernel_start;
881 uint64_t kernel_size;
882#endif
647 883
648 total = 0; 884 total = 0;
885 crashk_end = 0;
649 886
650 /* 887 /*
651 * The Mips memory init uses the first memory location for 888 * The Mips memory init uses the first memory location for
@@ -658,6 +895,17 @@ void __init plat_mem_setup(void)
658 if (mem_alloc_size > MAX_MEMORY) 895 if (mem_alloc_size > MAX_MEMORY)
659 mem_alloc_size = MAX_MEMORY; 896 mem_alloc_size = MAX_MEMORY;
660 897
898/* Crashkernel ignores bootmem list. It relies on mem=X@Y option */
899#ifdef CONFIG_CRASH_DUMP
900 add_memory_region(RESERVE_LOW_MEM, MAX_MEMORY, BOOT_MEM_RAM);
901 total += MAX_MEMORY;
902#else
903#ifdef CONFIG_KEXEC
904 if (crashk_size > 0) {
905 add_memory_region(crashk_base, crashk_size, BOOT_MEM_RAM);
906 crashk_end = crashk_base + crashk_size;
907 }
908#endif
661 /* 909 /*
662 * When allocating memory, we want incrementing addresses from 910 * When allocating memory, we want incrementing addresses from
663 * bootmem_alloc so the code in add_memory_region can merge 911 * bootmem_alloc so the code in add_memory_region can merge
@@ -672,6 +920,9 @@ void __init plat_mem_setup(void)
672 CVMX_BOOTMEM_FLAG_NO_LOCKING); 920 CVMX_BOOTMEM_FLAG_NO_LOCKING);
673 if (memory >= 0) { 921 if (memory >= 0) {
674 u64 size = mem_alloc_size; 922 u64 size = mem_alloc_size;
923#ifdef CONFIG_KEXEC
924 uint64_t end;
925#endif
675 926
676 /* 927 /*
677 * exclude a page at the beginning and end of 928 * exclude a page at the beginning and end of
@@ -684,20 +935,67 @@ void __init plat_mem_setup(void)
684 memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE + 935 memory_exclude_page(CVMX_PCIE_BAR1_PHYS_BASE +
685 CVMX_PCIE_BAR1_PHYS_SIZE, 936 CVMX_PCIE_BAR1_PHYS_SIZE,
686 &memory, &size); 937 &memory, &size);
938#ifdef CONFIG_KEXEC
939 end = memory + mem_alloc_size;
687 940
688 /* 941 /*
689 * This function automatically merges address 942 * This function automatically merges address regions
690 * regions next to each other if they are 943 * next to each other if they are received in
691 * received in incrementing order. 944 * incrementing order
692 */ 945 */
693 if (size) 946 if (memory < crashk_base && end > crashk_end) {
694 add_memory_region(memory, size, BOOT_MEM_RAM); 947 /* region is fully in */
948 add_memory_region(memory,
949 crashk_base - memory,
950 BOOT_MEM_RAM);
951 total += crashk_base - memory;
952 add_memory_region(crashk_end,
953 end - crashk_end,
954 BOOT_MEM_RAM);
955 total += end - crashk_end;
956 continue;
957 }
958
959 if (memory >= crashk_base && end <= crashk_end)
960 /*
961 * Entire memory region is within the new
962 * kernel's memory, ignore it.
963 */
964 continue;
965
966 if (memory > crashk_base && memory < crashk_end &&
967 end > crashk_end) {
968 /*
969 * Overlap with the beginning of the region,
970 * reserve the beginning.
971 */
972 mem_alloc_size -= crashk_end - memory;
973 memory = crashk_end;
974 } else if (memory < crashk_base && end > crashk_base &&
975 end < crashk_end)
976 /*
977 * Overlap with the beginning of the region,
978 * chop of end.
979 */
980 mem_alloc_size -= end - crashk_base;
981#endif
982 add_memory_region(memory, mem_alloc_size, BOOT_MEM_RAM);
695 total += mem_alloc_size; 983 total += mem_alloc_size;
984 /* Recovering mem_alloc_size */
985 mem_alloc_size = 4 << 20;
696 } else { 986 } else {
697 break; 987 break;
698 } 988 }
699 } 989 }
700 cvmx_bootmem_unlock(); 990 cvmx_bootmem_unlock();
991 /* Add the memory region for the kernel. */
992 kernel_start = (unsigned long) _text;
993 kernel_size = ALIGN(_end - _text, 0x100000);
994
995 /* Adjust for physical offset. */
996 kernel_start &= ~0xffffffff80000000ULL;
997 add_memory_region(kernel_start, kernel_size, BOOT_MEM_RAM);
998#endif /* CONFIG_CRASH_DUMP */
701 999
702#ifdef CONFIG_CAVIUM_RESERVE32 1000#ifdef CONFIG_CAVIUM_RESERVE32
703 /* 1001 /*