forked from Minki/linux
c489dfefe7
Commit0fa1c57934
("of/fdt: use memblock_virt_alloc for early alloc") inadvertently switched the DT unflattening allocations from memblock to bootmem which doesn't work because the unflattening happens before bootmem is initialized. Swapping the order of bootmem init and unflattening could also fix this, but removing bootmem is desired. So enable NO_BOOTMEM on h8300 like other architectures have done. Fixes:0fa1c57934
("of/fdt: use memblock_virt_alloc for early alloc") Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Cc: uclinux-h8-devel@lists.sourceforge.jp Signed-off-by: Rob Herring <robh@kernel.org> Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
232 lines
4.8 KiB
C
232 lines
4.8 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* linux/arch/h8300/kernel/setup.c
|
|
*
|
|
* Copyright (C) 2001-2014 Yoshinori Sato <ysato@users.sourceforge.jp>
|
|
*/
|
|
|
|
/*
|
|
* This file handles the architecture-dependent parts of system setup
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/console.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/string.h>
|
|
#include <linux/bootmem.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/init.h>
|
|
#include <linux/of.h>
|
|
#include <linux/of_fdt.h>
|
|
#include <linux/of_platform.h>
|
|
#include <linux/of_address.h>
|
|
#include <linux/clk-provider.h>
|
|
#include <linux/memblock.h>
|
|
#include <linux/screen_info.h>
|
|
#include <linux/clocksource.h>
|
|
|
|
#include <asm/setup.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/pgtable.h>
|
|
#include <asm/sections.h>
|
|
#include <asm/page.h>
|
|
|
|
#if defined(CONFIG_CPU_H8300H)
|
|
#define CPU "H8/300H"
|
|
#elif defined(CONFIG_CPU_H8S)
|
|
#define CPU "H8S"
|
|
#else
|
|
#define CPU "Unknown"
|
|
#endif
|
|
|
|
unsigned long memory_start;
|
|
unsigned long memory_end;
|
|
EXPORT_SYMBOL(memory_end);
|
|
static unsigned long freq;
|
|
extern char __dtb_start[];
|
|
|
|
#ifdef CONFIG_VT
|
|
struct screen_info screen_info;
|
|
#endif
|
|
|
|
char __initdata command_line[COMMAND_LINE_SIZE];
|
|
|
|
void sim_console_register(void);
|
|
|
|
void __init h8300_fdt_init(void *fdt, char *bootargs)
|
|
{
|
|
if (!fdt)
|
|
fdt = __dtb_start;
|
|
else
|
|
strcpy(command_line, bootargs);
|
|
|
|
early_init_dt_scan(fdt);
|
|
memblock_allow_resize();
|
|
}
|
|
|
|
static void __init bootmem_init(void)
|
|
{
|
|
struct memblock_region *region;
|
|
|
|
memory_end = memory_start = 0;
|
|
|
|
/* Find main memory where is the kernel */
|
|
for_each_memblock(memory, region) {
|
|
memory_start = region->base;
|
|
memory_end = region->base + region->size;
|
|
}
|
|
|
|
if (!memory_end)
|
|
panic("No memory!");
|
|
|
|
/* setup bootmem globals (we use no_bootmem, but mm still depends on this) */
|
|
min_low_pfn = PFN_UP(memory_start);
|
|
max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
|
|
max_pfn = max_low_pfn;
|
|
|
|
memblock_reserve(__pa(_stext), _end - _stext);
|
|
|
|
early_init_fdt_reserve_self();
|
|
early_init_fdt_scan_reserved_mem();
|
|
|
|
memblock_dump_all();
|
|
}
|
|
|
|
void __init setup_arch(char **cmdline_p)
|
|
{
|
|
unflatten_and_copy_device_tree();
|
|
|
|
init_mm.start_code = (unsigned long) _stext;
|
|
init_mm.end_code = (unsigned long) _etext;
|
|
init_mm.end_data = (unsigned long) _edata;
|
|
init_mm.brk = (unsigned long) 0;
|
|
|
|
pr_notice("\r\n\nuClinux " CPU "\n");
|
|
pr_notice("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
|
|
|
|
if (*command_line)
|
|
strcpy(boot_command_line, command_line);
|
|
*cmdline_p = boot_command_line;
|
|
|
|
parse_early_param();
|
|
|
|
bootmem_init();
|
|
/*
|
|
* get kmalloc into gear
|
|
*/
|
|
paging_init();
|
|
}
|
|
|
|
/*
|
|
* Get CPU information for use by the procfs.
|
|
*/
|
|
|
|
static int show_cpuinfo(struct seq_file *m, void *v)
|
|
{
|
|
char *cpu;
|
|
|
|
cpu = CPU;
|
|
|
|
seq_printf(m, "CPU:\t\t%s\n"
|
|
"Clock:\t\t%lu.%1luMHz\n"
|
|
"BogoMips:\t%lu.%02lu\n"
|
|
"Calibration:\t%lu loops\n",
|
|
cpu,
|
|
freq/1000, freq%1000,
|
|
(loops_per_jiffy*HZ)/500000,
|
|
((loops_per_jiffy*HZ)/5000)%100,
|
|
(loops_per_jiffy*HZ));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void *c_start(struct seq_file *m, loff_t *pos)
|
|
{
|
|
return *pos < num_possible_cpus() ?
|
|
((void *) 0x12345678) : NULL;
|
|
}
|
|
|
|
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
|
{
|
|
++*pos;
|
|
return c_start(m, pos);
|
|
}
|
|
|
|
static void c_stop(struct seq_file *m, void *v)
|
|
{
|
|
}
|
|
|
|
const struct seq_operations cpuinfo_op = {
|
|
.start = c_start,
|
|
.next = c_next,
|
|
.stop = c_stop,
|
|
.show = show_cpuinfo,
|
|
};
|
|
|
|
static int __init device_probe(void)
|
|
{
|
|
of_platform_populate(NULL, NULL, NULL, NULL);
|
|
|
|
return 0;
|
|
}
|
|
|
|
device_initcall(device_probe);
|
|
|
|
#if defined(CONFIG_CPU_H8300H)
|
|
#define get_wait(base, addr) ({ \
|
|
int baddr; \
|
|
baddr = ((addr) / 0x200000 * 2); \
|
|
w *= (readw((base) + 2) & (3 << baddr)) + 1; \
|
|
})
|
|
#endif
|
|
#if defined(CONFIG_CPU_H8S)
|
|
#define get_wait(base, addr) ({ \
|
|
int baddr; \
|
|
baddr = ((addr) / 0x200000 * 16); \
|
|
w *= (readl((base) + 2) & (7 << baddr)) + 1; \
|
|
})
|
|
#endif
|
|
|
|
static __init int access_timing(void)
|
|
{
|
|
struct device_node *bsc;
|
|
void __iomem *base;
|
|
unsigned long addr = (unsigned long)&__delay;
|
|
int bit = 1 << (addr / 0x200000);
|
|
int w;
|
|
|
|
bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc");
|
|
base = of_iomap(bsc, 0);
|
|
w = (readb(base + 0) & bit)?2:1;
|
|
if (readb(base + 1) & bit)
|
|
w *= get_wait(base, addr);
|
|
else
|
|
w *= 2;
|
|
return w * 3 / 2;
|
|
}
|
|
|
|
void __init calibrate_delay(void)
|
|
{
|
|
struct device_node *cpu;
|
|
int freq;
|
|
|
|
cpu = of_find_compatible_node(NULL, NULL, "renesas,h8300");
|
|
of_property_read_s32(cpu, "clock-frequency", &freq);
|
|
loops_per_jiffy = freq / HZ / (access_timing() * 2);
|
|
pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n",
|
|
loops_per_jiffy / (500000 / HZ),
|
|
(loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy);
|
|
}
|
|
|
|
|
|
void __init time_init(void)
|
|
{
|
|
of_clk_init(NULL);
|
|
timer_probe();
|
|
}
|