diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2007-07-10 12:32:56 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2007-07-10 12:32:56 -0400 |
commit | f6e2373ad6148476464fc7bb2610c6450c18cd2a (patch) | |
tree | f73cb9a4d26b30b2cbf8530047c3825809867be5 /arch | |
parent | 24e9d0b96dac5503c0b6f034d553030c604228a7 (diff) |
[MIPS] MIPSsim: Move code away from the other MIPS Inc. BSP code.
It shares no code at all. While at it also fix up the beginning bitrot.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/Kconfig | 1 | ||||
-rw-r--r-- | arch/mips/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/kernel/head.S | 7 | ||||
-rw-r--r-- | arch/mips/mipssim/Makefile (renamed from arch/mips/mips-boards/sim/Makefile) | 0 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_cmdline.c (renamed from arch/mips/mips-boards/sim/sim_cmdline.c) | 0 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_console.c (renamed from arch/mips/mips-boards/sim/sim_console.c) | 2 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_int.c | 88 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_mem.c (renamed from arch/mips/mips-boards/sim/sim_mem.c) | 2 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_platform.c (renamed from arch/mips/mips-boards/sim/sim_platform.c) | 0 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_setup.c (renamed from arch/mips/mips-boards/sim/sim_setup.c) | 8 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_smp.c (renamed from arch/mips/mips-boards/sim/sim_smp.c) | 18 | ||||
-rw-r--r-- | arch/mips/mipssim/sim_time.c (renamed from arch/mips/mips-boards/sim/sim_time.c) | 30 |
12 files changed, 125 insertions, 33 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 37977db6efff..734b61f663b7 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -251,6 +251,7 @@ config MIPS_SIM | |||
251 | select SYS_HAS_EARLY_PRINTK | 251 | select SYS_HAS_EARLY_PRINTK |
252 | select SYS_SUPPORTS_32BIT_KERNEL | 252 | select SYS_SUPPORTS_32BIT_KERNEL |
253 | select SYS_SUPPORTS_BIG_ENDIAN | 253 | select SYS_SUPPORTS_BIG_ENDIAN |
254 | select SYS_SUPPORTS_MULTITHREADING | ||
254 | select SYS_SUPPORTS_LITTLE_ENDIAN | 255 | select SYS_SUPPORTS_LITTLE_ENDIAN |
255 | help | 256 | help |
256 | This option enables support for MIPS Technologies MIPSsim software | 257 | This option enables support for MIPS Technologies MIPSsim software |
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index 2b19605b7382..077eb0bd1c78 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -327,7 +327,7 @@ load-$(CONFIG_MIPS_SEAD) += 0xffffffff80100000 | |||
327 | # | 327 | # |
328 | # MIPS SIM | 328 | # MIPS SIM |
329 | # | 329 | # |
330 | core-$(CONFIG_MIPS_SIM) += arch/mips/mips-boards/sim/ | 330 | core-$(CONFIG_MIPS_SIM) += arch/mips/mipssim/ |
331 | cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-sim | 331 | cflags-$(CONFIG_MIPS_SIM) += -Iinclude/asm-mips/mach-sim |
332 | load-$(CONFIG_MIPS_SIM) += 0x80100000 | 332 | load-$(CONFIG_MIPS_SIM) += 0x80100000 |
333 | 333 | ||
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S index 6f57ca44291f..1f096aa35bc0 100644 --- a/arch/mips/kernel/head.S +++ b/arch/mips/kernel/head.S | |||
@@ -138,15 +138,14 @@ | |||
138 | EXPORT(stext) # used for profiling | 138 | EXPORT(stext) # used for profiling |
139 | EXPORT(_stext) | 139 | EXPORT(_stext) |
140 | 140 | ||
141 | #ifdef CONFIG_MIPS_SIM | 141 | #ifndef CONFIG_MIPS_SIM |
142 | /* | 142 | /* |
143 | * Give us a fighting chance of running if execution beings at the | 143 | * Give us a fighting chance of running if execution beings at the |
144 | * kernel load address. This is needed because this platform does | 144 | * kernel load address. This is needed because this platform does |
145 | * not have a ELF loader yet. | 145 | * not have a ELF loader yet. |
146 | */ | 146 | */ |
147 | j kernel_entry | ||
148 | #endif | ||
149 | __INIT | 147 | __INIT |
148 | #endif | ||
150 | 149 | ||
151 | NESTED(kernel_entry, 16, sp) # kernel entry point | 150 | NESTED(kernel_entry, 16, sp) # kernel entry point |
152 | 151 | ||
@@ -197,9 +196,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point | |||
197 | j start_kernel | 196 | j start_kernel |
198 | END(kernel_entry) | 197 | END(kernel_entry) |
199 | 198 | ||
200 | #ifdef CONFIG_QEMU | ||
201 | __INIT | 199 | __INIT |
202 | #endif | ||
203 | 200 | ||
204 | #ifdef CONFIG_SMP | 201 | #ifdef CONFIG_SMP |
205 | /* | 202 | /* |
diff --git a/arch/mips/mips-boards/sim/Makefile b/arch/mips/mipssim/Makefile index dc0bfda11427..dc0bfda11427 100644 --- a/arch/mips/mips-boards/sim/Makefile +++ b/arch/mips/mipssim/Makefile | |||
diff --git a/arch/mips/mips-boards/sim/sim_cmdline.c b/arch/mips/mipssim/sim_cmdline.c index c63021a5dc6c..c63021a5dc6c 100644 --- a/arch/mips/mips-boards/sim/sim_cmdline.c +++ b/arch/mips/mipssim/sim_cmdline.c | |||
diff --git a/arch/mips/mips-boards/sim/sim_console.c b/arch/mips/mipssim/sim_console.c index de595a9ccb27..a2f41672cd5d 100644 --- a/arch/mips/mips-boards/sim/sim_console.c +++ b/arch/mips/mipssim/sim_console.c | |||
@@ -18,8 +18,8 @@ | |||
18 | * written by Ralf Baechle | 18 | * written by Ralf Baechle |
19 | */ | 19 | */ |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/io.h> | ||
21 | #include <linux/serial_reg.h> | 22 | #include <linux/serial_reg.h> |
22 | #include <asm/io.h> | ||
23 | 23 | ||
24 | static inline unsigned int serial_in(int offset) | 24 | static inline unsigned int serial_in(int offset) |
25 | { | 25 | { |
diff --git a/arch/mips/mipssim/sim_int.c b/arch/mips/mipssim/sim_int.c new file mode 100644 index 000000000000..d86b37235cf6 --- /dev/null +++ b/arch/mips/mipssim/sim_int.c | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1999, 2005 MIPS Technologies, Inc. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can distribute it and/or modify it | ||
5 | * under the terms of the GNU General Public License (Version 2) as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
11 | * for more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. | ||
16 | * | ||
17 | */ | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/interrupt.h> | ||
22 | #include <linux/kernel_stat.h> | ||
23 | #include <asm/mips-boards/simint.h> | ||
24 | #include <asm/irq_cpu.h> | ||
25 | |||
26 | static inline int clz(unsigned long x) | ||
27 | { | ||
28 | __asm__ ( | ||
29 | " .set push \n" | ||
30 | " .set mips32 \n" | ||
31 | " clz %0, %1 \n" | ||
32 | " .set pop \n" | ||
33 | : "=r" (x) | ||
34 | : "r" (x)); | ||
35 | |||
36 | return x; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Version of ffs that only looks at bits 12..15. | ||
41 | */ | ||
42 | static inline unsigned int irq_ffs(unsigned int pending) | ||
43 | { | ||
44 | #if defined(CONFIG_CPU_MIPS32) || defined(CONFIG_CPU_MIPS64) | ||
45 | return -clz(pending) + 31 - CAUSEB_IP; | ||
46 | #else | ||
47 | unsigned int a0 = 7; | ||
48 | unsigned int t0; | ||
49 | |||
50 | t0 = s0 & 0xf000; | ||
51 | t0 = t0 < 1; | ||
52 | t0 = t0 << 2; | ||
53 | a0 = a0 - t0; | ||
54 | s0 = s0 << t0; | ||
55 | |||
56 | t0 = s0 & 0xc000; | ||
57 | t0 = t0 < 1; | ||
58 | t0 = t0 << 1; | ||
59 | a0 = a0 - t0; | ||
60 | s0 = s0 << t0; | ||
61 | |||
62 | t0 = s0 & 0x8000; | ||
63 | t0 = t0 < 1; | ||
64 | /* t0 = t0 << 2; */ | ||
65 | a0 = a0 - t0; | ||
66 | /* s0 = s0 << t0; */ | ||
67 | |||
68 | return a0; | ||
69 | #endif | ||
70 | } | ||
71 | |||
72 | asmlinkage void plat_irq_dispatch(void) | ||
73 | { | ||
74 | unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM; | ||
75 | int irq; | ||
76 | |||
77 | irq = irq_ffs(pending); | ||
78 | |||
79 | if (irq > 0) | ||
80 | do_IRQ(MIPSCPU_INT_BASE + irq); | ||
81 | else | ||
82 | spurious_interrupt(); | ||
83 | } | ||
84 | |||
85 | void __init arch_init_irq(void) | ||
86 | { | ||
87 | mips_cpu_irq_init(); | ||
88 | } | ||
diff --git a/arch/mips/mips-boards/sim/sim_mem.c b/arch/mips/mipssim/sim_mem.c index e408ef0bcd6e..2312483eb838 100644 --- a/arch/mips/mips-boards/sim/sim_mem.c +++ b/arch/mips/mipssim/sim_mem.c | |||
@@ -95,7 +95,7 @@ void __init prom_meminit(void) | |||
95 | size = p->size; | 95 | size = p->size; |
96 | 96 | ||
97 | add_memory_region(base, size, type); | 97 | add_memory_region(base, size, type); |
98 | p++; | 98 | p++; |
99 | } | 99 | } |
100 | } | 100 | } |
101 | 101 | ||
diff --git a/arch/mips/mips-boards/sim/sim_platform.c b/arch/mips/mipssim/sim_platform.c index 53210a8c5dec..53210a8c5dec 100644 --- a/arch/mips/mips-boards/sim/sim_platform.c +++ b/arch/mips/mipssim/sim_platform.c | |||
diff --git a/arch/mips/mips-boards/sim/sim_setup.c b/arch/mips/mipssim/sim_setup.c index b705f09e57c3..3643582bdade 100644 --- a/arch/mips/mips-boards/sim/sim_setup.c +++ b/arch/mips/mipssim/sim_setup.c | |||
@@ -19,18 +19,18 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/string.h> | 20 | #include <linux/string.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/io.h> | ||
23 | #include <linux/irq.h> | ||
22 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
25 | #include <linux/serial.h> | ||
23 | #include <linux/tty.h> | 26 | #include <linux/tty.h> |
24 | #include <linux/serial.h> | 27 | #include <linux/serial.h> |
25 | #include <linux/serial_core.h> | 28 | #include <linux/serial_core.h> |
26 | 29 | ||
27 | #include <asm/cpu.h> | 30 | #include <asm/cpu.h> |
28 | #include <asm/bootinfo.h> | 31 | #include <asm/bootinfo.h> |
29 | #include <asm/irq.h> | ||
30 | #include <asm/mips-boards/generic.h> | 32 | #include <asm/mips-boards/generic.h> |
31 | #include <asm/mips-boards/prom.h> | 33 | #include <asm/mips-boards/prom.h> |
32 | #include <asm/serial.h> | ||
33 | #include <asm/io.h> | ||
34 | #include <asm/time.h> | 34 | #include <asm/time.h> |
35 | #include <asm/mips-boards/sim.h> | 35 | #include <asm/mips-boards/sim.h> |
36 | #include <asm/mips-boards/simint.h> | 36 | #include <asm/mips-boards/simint.h> |
@@ -62,7 +62,7 @@ void __init plat_mem_setup(void) | |||
62 | #endif | 62 | #endif |
63 | } | 63 | } |
64 | 64 | ||
65 | void prom_init(void) | 65 | void __init prom_init(void) |
66 | { | 66 | { |
67 | set_io_port_base(0xbfd00000); | 67 | set_io_port_base(0xbfd00000); |
68 | 68 | ||
diff --git a/arch/mips/mips-boards/sim/sim_smp.c b/arch/mips/mipssim/sim_smp.c index cb47863ecf10..38fa807b99f9 100644 --- a/arch/mips/mips-boards/sim/sim_smp.c +++ b/arch/mips/mipssim/sim_smp.c | |||
@@ -22,13 +22,13 @@ | |||
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/cpumask.h> | 23 | #include <linux/cpumask.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/smp.h> | ||
26 | |||
25 | #include <asm/atomic.h> | 27 | #include <asm/atomic.h> |
26 | #include <asm/cpu.h> | 28 | #include <asm/cpu.h> |
27 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
28 | #include <asm/system.h> | 30 | #include <asm/system.h> |
29 | #include <asm/hardirq.h> | ||
30 | #include <asm/mmu_context.h> | 31 | #include <asm/mmu_context.h> |
31 | #include <asm/smp.h> | ||
32 | #ifdef CONFIG_MIPS_MT_SMTC | 32 | #ifdef CONFIG_MIPS_MT_SMTC |
33 | #include <asm/smtc_ipi.h> | 33 | #include <asm/smtc_ipi.h> |
34 | #endif /* CONFIG_MIPS_MT_SMTC */ | 34 | #endif /* CONFIG_MIPS_MT_SMTC */ |
@@ -73,11 +73,19 @@ void prom_init_secondary(void) | |||
73 | #endif /* CONFIG_MIPS_MT_SMTC */ | 73 | #endif /* CONFIG_MIPS_MT_SMTC */ |
74 | } | 74 | } |
75 | 75 | ||
76 | void plat_smp_setup(void) | ||
77 | { | ||
78 | #ifdef CONFIG_MIPS_MT_SMTC | ||
79 | if (read_c0_config3() & (1 << 2)) | ||
80 | mipsmt_build_cpu_map(0); | ||
81 | #endif /* CONFIG_MIPS_MT_SMTC */ | ||
82 | } | ||
83 | |||
76 | /* | 84 | /* |
77 | * Platform SMP pre-initialization | 85 | * Platform SMP pre-initialization |
78 | */ | 86 | */ |
79 | 87 | ||
80 | void prom_prepare_cpus(unsigned int max_cpus) | 88 | void plat_prepare_cpus(unsigned int max_cpus) |
81 | { | 89 | { |
82 | #ifdef CONFIG_MIPS_MT_SMTC | 90 | #ifdef CONFIG_MIPS_MT_SMTC |
83 | /* | 91 | /* |
@@ -85,8 +93,8 @@ void prom_prepare_cpus(unsigned int max_cpus) | |||
85 | * but it may be multithreaded. | 93 | * but it may be multithreaded. |
86 | */ | 94 | */ |
87 | 95 | ||
88 | if (read_c0_config3() & (1<<2)) { | 96 | if (read_c0_config3() & (1 << 2)) { |
89 | mipsmt_prepare_cpus(max_cpus); | 97 | mipsmt_prepare_cpus(); |
90 | } | 98 | } |
91 | #endif /* CONFIG_MIPS_MT_SMTC */ | 99 | #endif /* CONFIG_MIPS_MT_SMTC */ |
92 | } | 100 | } |
diff --git a/arch/mips/mips-boards/sim/sim_time.c b/arch/mips/mipssim/sim_time.c index 7224ffe31d36..874a18e8ac24 100644 --- a/arch/mips/mips-boards/sim/sim_time.c +++ b/arch/mips/mipssim/sim_time.c | |||
@@ -5,10 +5,10 @@ | |||
5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
6 | #include <linux/interrupt.h> | 6 | #include <linux/interrupt.h> |
7 | #include <linux/mc146818rtc.h> | 7 | #include <linux/mc146818rtc.h> |
8 | #include <linux/mipsregs.h> | ||
9 | #include <linux/smp.h> | ||
8 | #include <linux/timex.h> | 10 | #include <linux/timex.h> |
9 | 11 | ||
10 | #include <asm/mipsregs.h> | ||
11 | #include <asm/ptrace.h> | ||
12 | #include <asm/hardirq.h> | 12 | #include <asm/hardirq.h> |
13 | #include <asm/div64.h> | 13 | #include <asm/div64.h> |
14 | #include <asm/cpu.h> | 14 | #include <asm/cpu.h> |
@@ -16,7 +16,6 @@ | |||
16 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
17 | #include <asm/mc146818-time.h> | 17 | #include <asm/mc146818-time.h> |
18 | #include <asm/msc01_ic.h> | 18 | #include <asm/msc01_ic.h> |
19 | #include <asm/smp.h> | ||
20 | 19 | ||
21 | #include <asm/mips-boards/generic.h> | 20 | #include <asm/mips-boards/generic.h> |
22 | #include <asm/mips-boards/prom.h> | 21 | #include <asm/mips-boards/prom.h> |
@@ -37,8 +36,7 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id) | |||
37 | #ifndef CONFIG_MIPS_MT_SMTC | 36 | #ifndef CONFIG_MIPS_MT_SMTC |
38 | if (cpu == 0) { | 37 | if (cpu == 0) { |
39 | timer_interrupt(irq, dev_id); | 38 | timer_interrupt(irq, dev_id); |
40 | } | 39 | } else { |
41 | else { | ||
42 | /* Everyone else needs to reset the timer int here as | 40 | /* Everyone else needs to reset the timer int here as |
43 | ll_local_timer_interrupt doesn't */ | 41 | ll_local_timer_interrupt doesn't */ |
44 | /* | 42 | /* |
@@ -76,8 +74,10 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id) | |||
76 | irq_enable_hazard(); | 74 | irq_enable_hazard(); |
77 | evpe(vpflags); | 75 | evpe(vpflags); |
78 | 76 | ||
79 | if(cpu_data[cpu].vpe_id == 0) timer_interrupt(irq, dev_id); | 77 | if (cpu_data[cpu].vpe_id == 0) |
80 | else write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); | 78 | timer_interrupt(irq, dev_id); |
79 | else | ||
80 | write_c0_compare (read_c0_count() + ( mips_hpt_frequency/HZ)); | ||
81 | smtc_timer_broadcast(cpu_data[cpu].vpe_id); | 81 | smtc_timer_broadcast(cpu_data[cpu].vpe_id); |
82 | 82 | ||
83 | #endif /* CONFIG_MIPS_MT_SMTC */ | 83 | #endif /* CONFIG_MIPS_MT_SMTC */ |
@@ -85,7 +85,8 @@ irqreturn_t sim_timer_interrupt(int irq, void *dev_id) | |||
85 | /* | 85 | /* |
86 | * every CPU should do profiling and process accounting | 86 | * every CPU should do profiling and process accounting |
87 | */ | 87 | */ |
88 | local_timer_interrupt (irq, dev_id); | 88 | local_timer_interrupt (irq, dev_id); |
89 | |||
89 | return IRQ_HANDLED; | 90 | return IRQ_HANDLED; |
90 | #else | 91 | #else |
91 | return timer_interrupt (irq, dev_id); | 92 | return timer_interrupt (irq, dev_id); |
@@ -152,17 +153,15 @@ void __init sim_time_init(void) | |||
152 | 153 | ||
153 | local_irq_save(flags); | 154 | local_irq_save(flags); |
154 | 155 | ||
155 | 156 | /* Set Data mode - binary. */ | |
156 | /* Set Data mode - binary. */ | ||
157 | CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); | 157 | CMOS_WRITE(CMOS_READ(RTC_CONTROL) | RTC_DM_BINARY, RTC_CONTROL); |
158 | 158 | ||
159 | |||
160 | est_freq = estimate_cpu_frequency (); | 159 | est_freq = estimate_cpu_frequency (); |
161 | 160 | ||
162 | printk("CPU frequency %d.%02d MHz\n", est_freq/1000000, | 161 | printk(KERN_INFO "CPU frequency %d.%02d MHz\n", est_freq / 1000000, |
163 | (est_freq%1000000)*100/1000000); | 162 | (est_freq % 1000000) * 100 / 1000000); |
164 | 163 | ||
165 | cpu_khz = est_freq / 1000; | 164 | cpu_khz = est_freq / 1000; |
166 | 165 | ||
167 | local_irq_restore(flags); | 166 | local_irq_restore(flags); |
168 | } | 167 | } |
@@ -180,8 +179,7 @@ void __init plat_timer_setup(struct irqaction *irq) | |||
180 | if (cpu_has_veic) { | 179 | if (cpu_has_veic) { |
181 | set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); | 180 | set_vi_handler(MSC01E_INT_CPUCTR, mips_timer_dispatch); |
182 | mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; | 181 | mips_cpu_timer_irq = MSC01E_INT_BASE + MSC01E_INT_CPUCTR; |
183 | } | 182 | } else { |
184 | else { | ||
185 | if (cpu_has_vint) | 183 | if (cpu_has_vint) |
186 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); | 184 | set_vi_handler(cp0_compare_irq, mips_timer_dispatch); |
187 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; | 185 | mips_cpu_timer_irq = MIPS_CPU_IRQ_BASE + cp0_compare_irq; |