xref: /linux/arch/mips/generic/board-ocelot.c (revision 6a74422b9710e987c7d6b85a1ade7330b1e61626)
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * Microsemi MIPS SoC support
4  *
5  * Copyright (c) 2017 Microsemi Corporation
6  */
7 #include <linux/string.h>
8 #include <asm/machine.h>
9 #include <asm/prom.h>
10 
11 #define DEVCPU_GCB_CHIP_REGS_CHIP_ID	0x71070000
12 #define CHIP_ID_PART_ID			GENMASK(27, 12)
13 
14 #define OCELOT_PART_ID			(0x7514 << 12)
15 
16 #define UART_UART			0x70100000
17 
ocelot_detect(void)18 static __init bool ocelot_detect(void)
19 {
20 	u32 rev;
21 	int idx;
22 
23 	/* Look for the TLB entry set up by redboot before trying to use it */
24 	write_c0_entryhi(DEVCPU_GCB_CHIP_REGS_CHIP_ID);
25 	mtc0_tlbw_hazard();
26 	tlb_probe();
27 	tlb_probe_hazard();
28 	idx = read_c0_index();
29 	if (idx < 0)
30 		return false;
31 
32 	/* A TLB entry exists, lets assume its usable and check the CHIP ID */
33 	rev = __raw_readl((void __iomem *)DEVCPU_GCB_CHIP_REGS_CHIP_ID);
34 
35 	if ((rev & CHIP_ID_PART_ID) != OCELOT_PART_ID)
36 		return false;
37 
38 	/* Copy command line from bootloader early for Initrd detection */
39 	if (fw_arg0 < 10 && (fw_arg1 & 0xFFF00000) == 0x80000000) {
40 		unsigned int prom_argc = fw_arg0;
41 		const char **prom_argv = (const char **)fw_arg1;
42 
43 		if (prom_argc > 1 && strlen(prom_argv[1]) > 0)
44 			/* ignore all built-in args if any f/w args given */
45 			strscpy(arcs_cmdline, prom_argv[1]);
46 	}
47 
48 	return true;
49 }
50 
ocelot_earlyprintk_init(void)51 static void __init ocelot_earlyprintk_init(void)
52 {
53 	void __iomem *uart_base;
54 
55 	uart_base = ioremap(UART_UART, 0x20);
56 	setup_8250_early_printk_port((unsigned long)uart_base, 2, 50000);
57 }
58 
ocelot_late_init(void)59 static void __init ocelot_late_init(void)
60 {
61 	ocelot_earlyprintk_init();
62 }
63 
ocelot_fixup_fdt(const void * fdt,const void * match_data)64 static __init const void *ocelot_fixup_fdt(const void *fdt,
65 					   const void *match_data)
66 {
67 	/* This has to be done so late because ioremap needs to work */
68 	late_time_init = ocelot_late_init;
69 
70 	return fdt;
71 }
72 
73 extern char __dtb_ocelot_pcb123_begin[];
74 
75 MIPS_MACHINE(ocelot) = {
76 	.fdt = __dtb_ocelot_pcb123_begin,
77 	.fixup_fdt = ocelot_fixup_fdt,
78 	.detect = ocelot_detect,
79 };
80