xref: /linux/arch/mips/econet/init.c (revision 570f7e331f5febb30f1384817463c7e42b65ca7d)
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