1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * EcoNet setup code 4 * 5 * Copyright (C) 2025 Caleb James DeLisle <cjd@cjdns.fr> 6 */ 7 8 #include <linux/init.h> 9 #include <linux/of_clk.h> 10 #include <linux/irqchip.h> 11 12 #include <asm/addrspace.h> 13 #include <asm/io.h> 14 #include <asm/bootinfo.h> 15 #include <asm/time.h> 16 #include <asm/prom.h> 17 #include <asm/smp-ops.h> 18 #include <asm/reboot.h> 19 20 #define CR_AHB_RSTCR ((void __iomem *)CKSEG1ADDR(0x1fb00040)) 21 #define RESET BIT(31) 22 23 #define UART_BASE CKSEG1ADDR(0x1fbf0003) 24 #define UART_REG_SHIFT 2 25 26 static void hw_reset(char *command) 27 { 28 iowrite32(RESET, CR_AHB_RSTCR); 29 } 30 31 /* 32 * vsmp_init_secondary expects either GIC or cascading interrupt configuration. 33 * The EN751221 is a 34Kc with VEIC, but not GIC compatible. The cascading 34 * configuration enables lines 6 and 7 for performance counters, but when this 35 * is done on the EN751221 intc with VEIC enabled, it causes the whole intc to 36 * stop sending interrupts. 37 * Only unmask lines 0 and 1 (software interrupts) in init_secondary. 38 */ 39 #ifdef CONFIG_MIPS_MT_SMP 40 extern const struct plat_smp_ops vsmp_smp_ops; 41 static struct plat_smp_ops en75_smp_ops __ro_after_init; 42 43 static void en751221_init_secondary(void) 44 { 45 write_c0_status((read_c0_status() & ~ST0_IM) | 46 (STATUSF_IP0 | STATUSF_IP1)); 47 } 48 49 static int __init en751221_register_vsmp_smp_ops(void) 50 { 51 if (!cpu_has_mipsmt) 52 return -ENODEV; 53 54 en75_smp_ops = vsmp_smp_ops; 55 en75_smp_ops.init_secondary = en751221_init_secondary; 56 register_smp_ops(&en75_smp_ops); 57 return 0; 58 } 59 #else 60 static int __init en751221_register_vsmp_smp_ops(void) 61 { 62 return -ENODEV; 63 } 64 #endif /* CONFIG_MIPS_MT_SMP */ 65 66 /* 1. Bring up early printk. */ 67 void __init prom_init(void) 68 { 69 setup_8250_early_printk_port(UART_BASE, UART_REG_SHIFT, 0); 70 _machine_restart = hw_reset; 71 } 72 73 /* 2. Parse the DT and find memory */ 74 void __init plat_mem_setup(void) 75 { 76 void *dtb; 77 78 set_io_port_base(KSEG1); 79 80 dtb = get_fdt(); 81 if (!dtb) 82 panic("no dtb found"); 83 84 __dt_setup_arch(dtb); 85 86 early_init_dt_scan_memory(); 87 } 88 89 /* 3. Overload __weak device_tree_init(), add SMP ops */ 90 void __init device_tree_init(void) 91 { 92 unflatten_and_copy_device_tree(); 93 94 /* EN751221 dual-vpe */ 95 if (!en751221_register_vsmp_smp_ops()) 96 return; 97 98 /* EN751221 with MT_SMP disabled */ 99 register_up_smp_ops(); 100 } 101 102 const char *get_system_type(void) 103 { 104 return "EcoNet-EN75xx"; 105 } 106 107 /* 4. Initialize the IRQ subsystem */ 108 void __init arch_init_irq(void) 109 { 110 irqchip_init(); 111 } 112 113 /* 5. Timers */ 114 void __init plat_time_init(void) 115 { 116 of_clk_init(NULL); 117 timer_probe(); 118 } 119