16bce3deaSAlexandre Belloni // SPDX-License-Identifier: (GPL-2.0 OR MIT)
26bce3deaSAlexandre Belloni /*
36bce3deaSAlexandre Belloni * Microsemi MIPS SoC support
46bce3deaSAlexandre Belloni *
56bce3deaSAlexandre Belloni * Copyright (c) 2017 Microsemi Corporation
66bce3deaSAlexandre Belloni */
76bce3deaSAlexandre Belloni #include <asm/machine.h>
86bce3deaSAlexandre Belloni #include <asm/prom.h>
96bce3deaSAlexandre Belloni
106bce3deaSAlexandre Belloni #define DEVCPU_GCB_CHIP_REGS_CHIP_ID 0x71070000
116bce3deaSAlexandre Belloni #define CHIP_ID_PART_ID GENMASK(27, 12)
126bce3deaSAlexandre Belloni
136bce3deaSAlexandre Belloni #define OCELOT_PART_ID (0x7514 << 12)
146bce3deaSAlexandre Belloni
156bce3deaSAlexandre Belloni #define UART_UART 0x70100000
166bce3deaSAlexandre Belloni
ocelot_detect(void)176bce3deaSAlexandre Belloni static __init bool ocelot_detect(void)
186bce3deaSAlexandre Belloni {
196bce3deaSAlexandre Belloni u32 rev;
206bce3deaSAlexandre Belloni int idx;
216bce3deaSAlexandre Belloni
226bce3deaSAlexandre Belloni /* Look for the TLB entry set up by redboot before trying to use it */
236bce3deaSAlexandre Belloni write_c0_entryhi(DEVCPU_GCB_CHIP_REGS_CHIP_ID);
246bce3deaSAlexandre Belloni mtc0_tlbw_hazard();
256bce3deaSAlexandre Belloni tlb_probe();
266bce3deaSAlexandre Belloni tlb_probe_hazard();
276bce3deaSAlexandre Belloni idx = read_c0_index();
286bce3deaSAlexandre Belloni if (idx < 0)
29*4d2ee1beSHuilong Deng return false;
306bce3deaSAlexandre Belloni
316bce3deaSAlexandre Belloni /* A TLB entry exists, lets assume its usable and check the CHIP ID */
326bce3deaSAlexandre Belloni rev = __raw_readl((void __iomem *)DEVCPU_GCB_CHIP_REGS_CHIP_ID);
336bce3deaSAlexandre Belloni
346bce3deaSAlexandre Belloni if ((rev & CHIP_ID_PART_ID) != OCELOT_PART_ID)
35*4d2ee1beSHuilong Deng return false;
366bce3deaSAlexandre Belloni
376bce3deaSAlexandre Belloni /* Copy command line from bootloader early for Initrd detection */
386bce3deaSAlexandre Belloni if (fw_arg0 < 10 && (fw_arg1 & 0xFFF00000) == 0x80000000) {
396bce3deaSAlexandre Belloni unsigned int prom_argc = fw_arg0;
406bce3deaSAlexandre Belloni const char **prom_argv = (const char **)fw_arg1;
416bce3deaSAlexandre Belloni
426bce3deaSAlexandre Belloni if (prom_argc > 1 && strlen(prom_argv[1]) > 0)
436bce3deaSAlexandre Belloni /* ignore all built-in args if any f/w args given */
446bce3deaSAlexandre Belloni strcpy(arcs_cmdline, prom_argv[1]);
456bce3deaSAlexandre Belloni }
466bce3deaSAlexandre Belloni
47*4d2ee1beSHuilong Deng return true;
486bce3deaSAlexandre Belloni }
496bce3deaSAlexandre Belloni
ocelot_earlyprintk_init(void)506bce3deaSAlexandre Belloni static void __init ocelot_earlyprintk_init(void)
516bce3deaSAlexandre Belloni {
526bce3deaSAlexandre Belloni void __iomem *uart_base;
536bce3deaSAlexandre Belloni
544bdc0d67SChristoph Hellwig uart_base = ioremap(UART_UART, 0x20);
556bce3deaSAlexandre Belloni setup_8250_early_printk_port((unsigned long)uart_base, 2, 50000);
566bce3deaSAlexandre Belloni }
576bce3deaSAlexandre Belloni
ocelot_late_init(void)586bce3deaSAlexandre Belloni static void __init ocelot_late_init(void)
596bce3deaSAlexandre Belloni {
606bce3deaSAlexandre Belloni ocelot_earlyprintk_init();
616bce3deaSAlexandre Belloni }
626bce3deaSAlexandre Belloni
ocelot_fixup_fdt(const void * fdt,const void * match_data)636bce3deaSAlexandre Belloni static __init const void *ocelot_fixup_fdt(const void *fdt,
646bce3deaSAlexandre Belloni const void *match_data)
656bce3deaSAlexandre Belloni {
666bce3deaSAlexandre Belloni /* This has to be done so late because ioremap needs to work */
676bce3deaSAlexandre Belloni late_time_init = ocelot_late_init;
686bce3deaSAlexandre Belloni
696bce3deaSAlexandre Belloni return fdt;
706bce3deaSAlexandre Belloni }
716bce3deaSAlexandre Belloni
726bce3deaSAlexandre Belloni extern char __dtb_ocelot_pcb123_begin[];
736bce3deaSAlexandre Belloni
746bce3deaSAlexandre Belloni MIPS_MACHINE(ocelot) = {
756bce3deaSAlexandre Belloni .fdt = __dtb_ocelot_pcb123_begin,
766bce3deaSAlexandre Belloni .fixup_fdt = ocelot_fixup_fdt,
776bce3deaSAlexandre Belloni .detect = ocelot_detect,
786bce3deaSAlexandre Belloni };
79