1// SPDX-License-Identifier: GPL-2.0 2/* 3 * linux/arch/h8300/kernel/setup.c 4 * 5 * Copyright (C) 2001-2014 Yoshinori Sato <ysato@users.sourceforge.jp> 6 */ 7 8/* 9 * This file handles the architecture-dependent parts of system setup 10 */ 11 12#include <linux/kernel.h> 13#include <linux/sched.h> 14#include <linux/delay.h> 15#include <linux/interrupt.h> 16#include <linux/io.h> 17#include <linux/mm.h> 18#include <linux/fs.h> 19#include <linux/console.h> 20#include <linux/errno.h> 21#include <linux/string.h> 22#include <linux/seq_file.h> 23#include <linux/init.h> 24#include <linux/of.h> 25#include <linux/of_fdt.h> 26#include <linux/of_address.h> 27#include <linux/clk-provider.h> 28#include <linux/memblock.h> 29#include <linux/screen_info.h> 30#include <linux/clocksource.h> 31 32#include <asm/setup.h> 33#include <asm/irq.h> 34#include <asm/sections.h> 35#include <asm/page.h> 36 37#if defined(CONFIG_CPU_H8300H) 38#define CPU "H8/300H" 39#elif defined(CONFIG_CPU_H8S) 40#define CPU "H8S" 41#else 42#define CPU "Unknown" 43#endif 44 45unsigned long memory_start; 46unsigned long memory_end; 47EXPORT_SYMBOL(memory_end); 48static unsigned long freq; 49extern char __dtb_start[]; 50 51#ifdef CONFIG_VT 52struct screen_info screen_info; 53#endif 54 55char __initdata command_line[COMMAND_LINE_SIZE]; 56 57void sim_console_register(void); 58 59void __init h8300_fdt_init(void *fdt, char *bootargs) 60{ 61 if (!fdt) 62 fdt = __dtb_start; 63 else 64 strcpy(command_line, bootargs); 65 66 early_init_dt_scan(fdt); 67 memblock_allow_resize(); 68} 69 70static void __init bootmem_init(void) 71{ 72 struct memblock_region *region; 73 74 memory_end = memory_start = 0; 75 76 /* Find main memory where is the kernel */ 77 memory_start = memblock_start_of_DRAM(); 78 memory_end = memblock_end_of_DRAM(); 79 80 if (!memory_end) 81 panic("No memory!"); 82 83 /* setup bootmem globals (we use no_bootmem, but mm still depends on this) */ 84 min_low_pfn = PFN_UP(memory_start); 85 max_low_pfn = PFN_DOWN(memory_end); 86 max_pfn = max_low_pfn; 87 88 memblock_reserve(__pa(_stext), _end - _stext); 89 90 early_init_fdt_reserve_self(); 91 early_init_fdt_scan_reserved_mem(); 92 93 memblock_dump_all(); 94} 95 96void __init setup_arch(char **cmdline_p) 97{ 98 unflatten_and_copy_device_tree(); 99 100 init_mm.start_code = (unsigned long) _stext; 101 init_mm.end_code = (unsigned long) _etext; 102 init_mm.end_data = (unsigned long) _edata; 103 init_mm.brk = (unsigned long) 0; 104 105 pr_notice("\r\n\nuClinux " CPU "\n"); 106 pr_notice("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); 107 108 if (*command_line) 109 strcpy(boot_command_line, command_line); 110 *cmdline_p = boot_command_line; 111 112 parse_early_param(); 113 114 bootmem_init(); 115 /* 116 * get kmalloc into gear 117 */ 118 paging_init(); 119} 120 121/* 122 * Get CPU information for use by the procfs. 123 */ 124 125static int show_cpuinfo(struct seq_file *m, void *v) 126{ 127 char *cpu; 128 129 cpu = CPU; 130 131 seq_printf(m, "CPU:\t\t%s\n" 132 "Clock:\t\t%lu.%1luMHz\n" 133 "BogoMips:\t%lu.%02lu\n" 134 "Calibration:\t%lu loops\n", 135 cpu, 136 freq/1000, freq%1000, 137 (loops_per_jiffy*HZ)/500000, 138 ((loops_per_jiffy*HZ)/5000)%100, 139 (loops_per_jiffy*HZ)); 140 141 return 0; 142} 143 144static void *c_start(struct seq_file *m, loff_t *pos) 145{ 146 return *pos < num_possible_cpus() ? 147 ((void *) 0x12345678) : NULL; 148} 149 150static void *c_next(struct seq_file *m, void *v, loff_t *pos) 151{ 152 ++*pos; 153 return c_start(m, pos); 154} 155 156static void c_stop(struct seq_file *m, void *v) 157{ 158} 159 160const struct seq_operations cpuinfo_op = { 161 .start = c_start, 162 .next = c_next, 163 .stop = c_stop, 164 .show = show_cpuinfo, 165}; 166 167#if defined(CONFIG_CPU_H8300H) 168#define get_wait(base, addr) ({ \ 169 int baddr; \ 170 baddr = ((addr) / 0x200000 * 2); \ 171 w *= (readw((base) + 2) & (3 << baddr)) + 1; \ 172 }) 173#endif 174#if defined(CONFIG_CPU_H8S) 175#define get_wait(base, addr) ({ \ 176 int baddr; \ 177 baddr = ((addr) / 0x200000 * 16); \ 178 w *= (readl((base) + 2) & (7 << baddr)) + 1; \ 179 }) 180#endif 181 182static __init int access_timing(void) 183{ 184 struct device_node *bsc; 185 void __iomem *base; 186 unsigned long addr = (unsigned long)&__delay; 187 int bit = 1 << (addr / 0x200000); 188 int w; 189 190 bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc"); 191 base = of_iomap(bsc, 0); 192 w = (readb(base + 0) & bit)?2:1; 193 if (readb(base + 1) & bit) 194 w *= get_wait(base, addr); 195 else 196 w *= 2; 197 return w * 3 / 2; 198} 199 200void __init calibrate_delay(void) 201{ 202 struct device_node *cpu; 203 int freq; 204 205 cpu = of_find_compatible_node(NULL, NULL, "renesas,h8300"); 206 of_property_read_s32(cpu, "clock-frequency", &freq); 207 loops_per_jiffy = freq / HZ / (access_timing() * 2); 208 pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", 209 loops_per_jiffy / (500000 / HZ), 210 (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy); 211} 212 213 214void __init time_init(void) 215{ 216 of_clk_init(NULL); 217 timer_probe(); 218} 219