diff options
author | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2013-12-10 14:31:56 +0100 |
---|---|---|
committer | Albert ARIBAUD <albert.u.boot@aribaud.net> | 2013-12-10 22:23:59 +0100 |
commit | f15ea6e1d67782a1626d4a4922b6c20e380085e5 (patch) | |
tree | 57d78f1ee94a2060eaa591533278d2934d4f1da3 /board/imgtec | |
parent | cb7ee1b98cac6baf244daefb1192adf5a47bc983 (diff) | |
parent | f44483b57c49282299da0e5c10073b909cdad979 (diff) | |
download | u-boot-imx-f15ea6e1d67782a1626d4a4922b6c20e380085e5.zip u-boot-imx-f15ea6e1d67782a1626d4a4922b6c20e380085e5.tar.gz u-boot-imx-f15ea6e1d67782a1626d4a4922b6c20e380085e5.tar.bz2 |
Merge branch 'u-boot/master' into 'u-boot-arm/master'
Conflicts:
arch/arm/cpu/armv7/rmobile/Makefile
doc/README.scrapyard
Needed manual fix:
arch/arm/cpu/armv7/omap-common/Makefile
board/compulab/cm_t335/u-boot.lds
Diffstat (limited to 'board/imgtec')
-rw-r--r-- | board/imgtec/malta/Makefile | 10 | ||||
-rw-r--r-- | board/imgtec/malta/flash-malta-boot.tcl | 40 | ||||
-rw-r--r-- | board/imgtec/malta/lowlevel_init.S | 238 | ||||
-rw-r--r-- | board/imgtec/malta/malta.c | 220 | ||||
-rw-r--r-- | board/imgtec/malta/superio.c | 63 | ||||
-rw-r--r-- | board/imgtec/malta/superio.h | 15 |
6 files changed, 586 insertions, 0 deletions
diff --git a/board/imgtec/malta/Makefile b/board/imgtec/malta/Makefile new file mode 100644 index 0000000..19dd3a3 --- /dev/null +++ b/board/imgtec/malta/Makefile @@ -0,0 +1,10 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +obj-y = malta.o +obj-y += lowlevel_init.o +obj-y += superio.o diff --git a/board/imgtec/malta/flash-malta-boot.tcl b/board/imgtec/malta/flash-malta-boot.tcl new file mode 100644 index 0000000..0eedf07 --- /dev/null +++ b/board/imgtec/malta/flash-malta-boot.tcl @@ -0,0 +1,40 @@ +# +# Copyright (C) 2013 Imagination Technologies +# +# Programs a MIPS Malta boot flash with a flat binary image. +# +# SPDX-License-Identifier: GPL-2.0+ +# + +proc flash-boot { binfile } { + puts "flash monitor binary $binfile" + config Coherent on + config CoherencyDuringLoad on + + if {[endian]=="big"} { + puts "CPU in BE mode" + flash device sharp_16x32_be; + } else { + puts "CPU in LE mode" + flash device sharp_16x32; + } + + flash clear all; + flash set 0xBE000000..0xBE0FFFFF + flash erase sector 0xbe000000; + flash erase sector 0xbe020000; + flash erase sector 0xbe040000; + flash erase sector 0xbe060000; + flash erase sector 0xbe080000; + flash erase sector 0xbe0a0000; + flash erase sector 0xbe0c0000; + flash erase sector 0xbe0e0000; + puts "finished erasing boot flash"; + + puts "programming flash, please be patient" + load bin 0xbe000000 $binfile size4 + + flash clear all + config CoherencyDuringLoad off + puts "finished programming boot flash"; +} diff --git a/board/imgtec/malta/lowlevel_init.S b/board/imgtec/malta/lowlevel_init.S new file mode 100644 index 0000000..ae09c27 --- /dev/null +++ b/board/imgtec/malta/lowlevel_init.S @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <config.h> +#include <gt64120.h> +#include <msc01.h> +#include <pci.h> + +#include <asm/addrspace.h> +#include <asm/regdef.h> +#include <asm/malta.h> +#include <asm/mipsregs.h> + +#ifdef CONFIG_SYS_BIG_ENDIAN +#define CPU_TO_GT32(_x) ((_x)) +#else +#define CPU_TO_GT32(_x) ( \ + (((_x) & 0xff) << 24) | (((_x) & 0xff00) << 8) | \ + (((_x) & 0xff0000) >> 8) | (((_x) & 0xff000000) >> 24)) +#endif + + .text + .set noreorder + .set mips32 + + .globl lowlevel_init +lowlevel_init: + /* disable any L2 cache for now */ + sync + mfc0 t0, CP0_CONFIG, 2 + ori t0, t0, 0x1 << 12 + mtc0 t0, CP0_CONFIG, 2 + + /* detect the core card */ + li t0, KSEG1ADDR(MALTA_REVISION) + lw t0, 0(t0) + srl t0, t0, MALTA_REVISION_CORID_SHF + andi t0, t0, (MALTA_REVISION_CORID_MSK >> \ + MALTA_REVISION_CORID_SHF) + + /* core cards using the gt64120 system controller */ + li t1, MALTA_REVISION_CORID_CORE_LV + beq t0, t1, _gt64120 + + /* core cards using the MSC01 system controller */ + li t1, MALTA_REVISION_CORID_CORE_FPGA6 + beq t0, t1, _msc01 + nop + + /* unknown system controller */ + b . + nop + + /* + * Load BAR registers of GT64120 as done by YAMON + * + * based on a patch sent by Antony Pavlov <antonynpavlov@gmail.com> + * to the barebox mailing list. + * The subject of the original patch: + * 'MIPS: qemu-malta: add YAMON-style GT64120 memory map' + * URL: + * http://www.mail-archive.com/barebox@lists.infradead.org/msg06128.html + * + * based on write_bootloader() in qemu.git/hw/mips_malta.c + * see GT64120 manual and qemu.git/hw/gt64xxx.c for details + */ +_gt64120: + /* move GT64120 registers from 0x14000000 to 0x1be00000 */ + li t1, KSEG1ADDR(GT_DEF_BASE) + li t0, CPU_TO_GT32(0xdf000000) + sw t0, GT_ISD_OFS(t1) + + /* setup MEM-to-PCI0 mapping */ + li t1, KSEG1ADDR(MALTA_GT_BASE) + + /* setup PCI0 io window to 0x18000000-0x181fffff */ + li t0, CPU_TO_GT32(0xc0000000) + sw t0, GT_PCI0IOLD_OFS(t1) + li t0, CPU_TO_GT32(0x40000000) + sw t0, GT_PCI0IOHD_OFS(t1) + + /* setup PCI0 mem windows */ + li t0, CPU_TO_GT32(0x80000000) + sw t0, GT_PCI0M0LD_OFS(t1) + li t0, CPU_TO_GT32(0x3f000000) + sw t0, GT_PCI0M0HD_OFS(t1) + + li t0, CPU_TO_GT32(0xc1000000) + sw t0, GT_PCI0M1LD_OFS(t1) + li t0, CPU_TO_GT32(0x5e000000) + sw t0, GT_PCI0M1HD_OFS(t1) + + jr ra + nop + + /* + * + */ +_msc01: + /* setup peripheral bus controller clock divide */ + li t0, KSEG1ADDR(MALTA_MSC01_PBC_BASE) + li t1, 0x1 << MSC01_PBC_CLKCFG_SHF + sw t1, MSC01_PBC_CLKCFG_OFS(t0) + + /* tweak peripheral bus controller timings */ + li t1, (0x1 << MSC01_PBC_CS0TIM_CDT_SHF) | \ + (0x1 << MSC01_PBC_CS0TIM_CAT_SHF) + sw t1, MSC01_PBC_CS0TIM_OFS(t0) + li t1, (0x0 << MSC01_PBC_CS0RW_RDT_SHF) | \ + (0x2 << MSC01_PBC_CS0RW_RAT_SHF) | \ + (0x0 << MSC01_PBC_CS0RW_WDT_SHF) | \ + (0x2 << MSC01_PBC_CS0RW_WAT_SHF) + sw t1, MSC01_PBC_CS0RW_OFS(t0) + lw t1, MSC01_PBC_CS0CFG_OFS(t0) + li t2, MSC01_PBC_CS0CFG_DTYP_MSK + and t1, t2 + ori t1, (0x0 << MSC01_PBC_CS0CFG_ADM_SHF) | \ + (0x3 << MSC01_PBC_CS0CFG_WSIDLE_SHF) | \ + (0x10 << MSC01_PBC_CS0CFG_WS_SHF) + sw t1, MSC01_PBC_CS0CFG_OFS(t0) + + /* setup basic address decode */ + li t0, KSEG1ADDR(MALTA_MSC01_BIU_BASE) + li t1, 0x0 + li t2, -CONFIG_SYS_MEM_SIZE + sw t1, MSC01_BIU_MCBAS1L_OFS(t0) + sw t2, MSC01_BIU_MCMSK1L_OFS(t0) + sw t1, MSC01_BIU_MCBAS2L_OFS(t0) + sw t2, MSC01_BIU_MCMSK2L_OFS(t0) + + /* initialise IP1 - unused */ + li t1, MALTA_MSC01_IP1_BASE + li t2, -MALTA_MSC01_IP1_SIZE + sw t1, MSC01_BIU_IP1BAS1L_OFS(t0) + sw t2, MSC01_BIU_IP1MSK1L_OFS(t0) + sw t1, MSC01_BIU_IP1BAS2L_OFS(t0) + sw t2, MSC01_BIU_IP1MSK2L_OFS(t0) + + /* initialise IP2 - PCI */ + li t1, MALTA_MSC01_IP2_BASE1 + li t2, -MALTA_MSC01_IP2_SIZE1 + sw t1, MSC01_BIU_IP2BAS1L_OFS(t0) + sw t2, MSC01_BIU_IP2MSK1L_OFS(t0) + li t1, MALTA_MSC01_IP2_BASE2 + li t2, -MALTA_MSC01_IP2_SIZE2 + sw t1, MSC01_BIU_IP2BAS2L_OFS(t0) + sw t2, MSC01_BIU_IP2MSK2L_OFS(t0) + + /* initialise IP3 - peripheral bus controller */ + li t1, MALTA_MSC01_IP3_BASE + li t2, -MALTA_MSC01_IP3_SIZE + sw t1, MSC01_BIU_IP3BAS1L_OFS(t0) + sw t2, MSC01_BIU_IP3MSK1L_OFS(t0) + sw t1, MSC01_BIU_IP3BAS2L_OFS(t0) + sw t2, MSC01_BIU_IP3MSK2L_OFS(t0) + + /* setup PCI memory */ + li t0, KSEG1ADDR(MALTA_MSC01_PCI_BASE) + li t1, MALTA_MSC01_PCIMEM_BASE + li t2, (-MALTA_MSC01_PCIMEM_SIZE) & MSC01_PCI_SC2PMMSKL_MSK_MSK + li t3, MALTA_MSC01_PCIMEM_MAP + sw t1, MSC01_PCI_SC2PMBASL_OFS(t0) + sw t2, MSC01_PCI_SC2PMMSKL_OFS(t0) + sw t3, MSC01_PCI_SC2PMMAPL_OFS(t0) + + /* setup PCI I/O */ + li t1, MALTA_MSC01_PCIIO_BASE + li t2, (-MALTA_MSC01_PCIIO_SIZE) & MSC01_PCI_SC2PIOMSKL_MSK_MSK + li t3, MALTA_MSC01_PCIIO_MAP + sw t1, MSC01_PCI_SC2PIOBASL_OFS(t0) + sw t2, MSC01_PCI_SC2PIOMSKL_OFS(t0) + sw t3, MSC01_PCI_SC2PIOMAPL_OFS(t0) + + /* setup PCI_BAR0 memory window */ + li t1, -CONFIG_SYS_MEM_SIZE + sw t1, MSC01_PCI_BAR0_OFS(t0) + + /* setup PCI to SysCon/CPU translation */ + sw t1, MSC01_PCI_P2SCMSKL_OFS(t0) + sw zero, MSC01_PCI_P2SCMAPL_OFS(t0) + + /* setup PCI vendor & device IDs */ + li t1, (PCI_VENDOR_ID_MIPS << MSC01_PCI_HEAD0_VENDORID_SHF) | \ + (PCI_DEVICE_ID_MIPS_MSC01 << MSC01_PCI_HEAD0_DEVICEID_SHF) + sw t1, MSC01_PCI_HEAD0_OFS(t0) + + /* setup PCI subsystem vendor & device IDs */ + sw t1, MSC01_PCI_HEAD11_OFS(t0) + + /* setup PCI class, revision */ + li t1, (PCI_CLASS_BRIDGE_HOST << MSC01_PCI_HEAD2_CLASS_SHF) | \ + (0x1 << MSC01_PCI_HEAD2_REV_SHF) + sw t1, MSC01_PCI_HEAD2_OFS(t0) + + /* ensure a sane setup */ + sw zero, MSC01_PCI_HEAD3_OFS(t0) + sw zero, MSC01_PCI_HEAD4_OFS(t0) + sw zero, MSC01_PCI_HEAD5_OFS(t0) + sw zero, MSC01_PCI_HEAD6_OFS(t0) + sw zero, MSC01_PCI_HEAD7_OFS(t0) + sw zero, MSC01_PCI_HEAD8_OFS(t0) + sw zero, MSC01_PCI_HEAD9_OFS(t0) + sw zero, MSC01_PCI_HEAD10_OFS(t0) + sw zero, MSC01_PCI_HEAD12_OFS(t0) + sw zero, MSC01_PCI_HEAD13_OFS(t0) + sw zero, MSC01_PCI_HEAD14_OFS(t0) + sw zero, MSC01_PCI_HEAD15_OFS(t0) + + /* setup PCI command register */ + li t1, (PCI_COMMAND_FAST_BACK | \ + PCI_COMMAND_SERR | \ + PCI_COMMAND_PARITY | \ + PCI_COMMAND_MASTER | \ + PCI_COMMAND_MEMORY) + sw t1, MSC01_PCI_HEAD1_OFS(t0) + + /* setup PCI byte swapping */ +#ifdef CONFIG_SYS_BIG_ENDIAN + li t1, (0x1 << MSC01_PCI_SWAP_BAR0_BSWAP_SHF) | \ + (0x1 << MSC01_PCI_SWAP_IO_BSWAP_SHF) + sw t1, MSC01_PCI_SWAP_OFS(t0) +#else + sw zero, MSC01_PCI_SWAP_OFS(t0) +#endif + + /* enable PCI host configuration cycles */ + lw t1, MSC01_PCI_CFG_OFS(t0) + li t2, MSC01_PCI_CFG_RA_MSK | \ + MSC01_PCI_CFG_G_MSK | \ + MSC01_PCI_CFG_EN_MSK + or t1, t1, t2 + sw t1, MSC01_PCI_CFG_OFS(t0) + + jr ra + nop diff --git a/board/imgtec/malta/malta.c b/board/imgtec/malta/malta.c new file mode 100644 index 0000000..d363e49 --- /dev/null +++ b/board/imgtec/malta/malta.c @@ -0,0 +1,220 @@ +/* + * Copyright (C) 2013 Gabor Juhos <juhosg@openwrt.org> + * Copyright (C) 2013 Imagination Technologies + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <netdev.h> +#include <pci.h> +#include <pci_gt64120.h> +#include <pci_msc01.h> +#include <rtc.h> +#include <serial.h> + +#include <asm/addrspace.h> +#include <asm/io.h> +#include <asm/malta.h> + +#include "superio.h" + +enum core_card { + CORE_UNKNOWN, + CORE_LV, + CORE_FPGA6, +}; + +enum sys_con { + SYSCON_UNKNOWN, + SYSCON_GT64120, + SYSCON_MSC01, +}; + +static void malta_lcd_puts(const char *str) +{ + int i; + void *reg = (void *)CKSEG1ADDR(MALTA_ASCIIPOS0); + + /* print up to 8 characters of the string */ + for (i = 0; i < min(strlen(str), 8); i++) { + __raw_writel(str[i], reg); + reg += MALTA_ASCIIPOS1 - MALTA_ASCIIPOS0; + } + + /* fill the rest of the display with spaces */ + for (; i < 8; i++) { + __raw_writel(' ', reg); + reg += MALTA_ASCIIPOS1 - MALTA_ASCIIPOS0; + } +} + +static enum core_card malta_core_card(void) +{ + u32 corid, rev; + + rev = __raw_readl(CKSEG1ADDR(MALTA_REVISION)); + corid = (rev & MALTA_REVISION_CORID_MSK) >> MALTA_REVISION_CORID_SHF; + + switch (corid) { + case MALTA_REVISION_CORID_CORE_LV: + return CORE_LV; + + case MALTA_REVISION_CORID_CORE_FPGA6: + return CORE_FPGA6; + + default: + return CORE_UNKNOWN; + } +} + +static enum sys_con malta_sys_con(void) +{ + switch (malta_core_card()) { + case CORE_LV: + return SYSCON_GT64120; + + case CORE_FPGA6: + return SYSCON_MSC01; + + default: + return SYSCON_UNKNOWN; + } +} + +phys_size_t initdram(int board_type) +{ + return CONFIG_SYS_MEM_SIZE; +} + +int checkboard(void) +{ + enum core_card core; + + malta_lcd_puts("U-boot"); + puts("Board: MIPS Malta"); + + core = malta_core_card(); + switch (core) { + case CORE_LV: + puts(" CoreLV"); + break; + + case CORE_FPGA6: + puts(" CoreFPGA6"); + break; + + default: + puts(" CoreUnknown"); + } + + putc('\n'); + return 0; +} + +int board_eth_init(bd_t *bis) +{ + return pci_eth_init(bis); +} + +void _machine_restart(void) +{ + void __iomem *reset_base; + + reset_base = (void __iomem *)CKSEG1ADDR(MALTA_RESET_BASE); + __raw_writel(GORESET, reset_base); +} + +int board_early_init_f(void) +{ + void *io_base; + + /* choose correct PCI I/O base */ + switch (malta_sys_con()) { + case SYSCON_GT64120: + io_base = (void *)CKSEG1ADDR(MALTA_GT_PCIIO_BASE); + break; + + case SYSCON_MSC01: + io_base = (void *)CKSEG1ADDR(MALTA_MSC01_PCIIO_BASE); + break; + + default: + return -1; + } + + /* setup FDC37M817 super I/O controller */ + malta_superio_init(io_base); + + return 0; +} + +int misc_init_r(void) +{ + rtc_reset(); + + return 0; +} + +struct serial_device *default_serial_console(void) +{ + switch (malta_sys_con()) { + case SYSCON_GT64120: + return &eserial1_device; + + default: + case SYSCON_MSC01: + return &eserial2_device; + } +} + +void pci_init_board(void) +{ + pci_dev_t bdf; + u32 val32; + u8 val8; + + switch (malta_sys_con()) { + case SYSCON_GT64120: + set_io_port_base(CKSEG1ADDR(MALTA_GT_PCIIO_BASE)); + + gt64120_pci_init((void *)CKSEG1ADDR(MALTA_GT_BASE), + 0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE, + 0x10000000, 0x10000000, 128 * 1024 * 1024, + 0x00000000, 0x00000000, 0x20000); + break; + + default: + case SYSCON_MSC01: + set_io_port_base(CKSEG1ADDR(MALTA_MSC01_PCIIO_BASE)); + + msc01_pci_init((void *)CKSEG1ADDR(MALTA_MSC01_PCI_BASE), + 0x00000000, 0x00000000, CONFIG_SYS_MEM_SIZE, + MALTA_MSC01_PCIMEM_MAP, + CKSEG1ADDR(MALTA_MSC01_PCIMEM_BASE), + MALTA_MSC01_PCIMEM_SIZE, MALTA_MSC01_PCIIO_MAP, + 0x00000000, MALTA_MSC01_PCIIO_SIZE); + break; + } + + bdf = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82371AB_0, 0); + if (bdf == -1) + panic("Failed to find PIIX4 PCI bridge\n"); + + /* setup PCI interrupt routing */ + pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCA, 10); + pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCB, 10); + pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCC, 11); + pci_write_config_byte(bdf, PCI_CFG_PIIX4_PIRQRCD, 11); + + /* mux SERIRQ onto SERIRQ pin */ + pci_read_config_dword(bdf, PCI_CFG_PIIX4_GENCFG, &val32); + val32 |= PCI_CFG_PIIX4_GENCFG_SERIRQ; + pci_write_config_dword(bdf, PCI_CFG_PIIX4_GENCFG, val32); + + /* enable SERIRQ - Linux currently depends upon this */ + pci_read_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, &val8); + val8 |= PCI_CFG_PIIX4_SERIRQC_EN | PCI_CFG_PIIX4_SERIRQC_CONT; + pci_write_config_byte(bdf, PCI_CFG_PIIX4_SERIRQC, val8); +} diff --git a/board/imgtec/malta/superio.c b/board/imgtec/malta/superio.c new file mode 100644 index 0000000..eaa14df --- /dev/null +++ b/board/imgtec/malta/superio.c @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2013 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * Setup code for the FDC37M817 super I/O controller + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <common.h> +#include <asm/io.h> + +#define SIO_CONF_PORT 0x3f0 +#define SIO_DATA_PORT 0x3f1 + +enum sio_conf_key { + SIOCONF_DEVNUM = 0x07, + SIOCONF_ACTIVATE = 0x30, + SIOCONF_ENTER_SETUP = 0x55, + SIOCONF_BASE_HIGH = 0x60, + SIOCONF_BASE_LOW = 0x61, + SIOCONF_PRIMARY_INT = 0x70, + SIOCONF_EXIT_SETUP = 0xaa, + SIOCONF_MODE = 0xf0, +}; + +static struct { + u8 key; + u8 data; +} sio_config[] = { + /* tty0 */ + { SIOCONF_DEVNUM, 0x04 }, + { SIOCONF_BASE_HIGH, 0x03 }, + { SIOCONF_BASE_LOW, 0xf8 }, + { SIOCONF_MODE, 0x02 }, + { SIOCONF_PRIMARY_INT, 0x04 }, + { SIOCONF_ACTIVATE, 0x01 }, + + /* tty1 */ + { SIOCONF_DEVNUM, 0x05 }, + { SIOCONF_BASE_HIGH, 0x02 }, + { SIOCONF_BASE_LOW, 0xf8 }, + { SIOCONF_MODE, 0x02 }, + { SIOCONF_PRIMARY_INT, 0x03 }, + { SIOCONF_ACTIVATE, 0x01 }, +}; + +void malta_superio_init(void *io_base) +{ + unsigned i; + + /* enter config state */ + writeb(SIOCONF_ENTER_SETUP, io_base + SIO_CONF_PORT); + + /* configure peripherals */ + for (i = 0; i < ARRAY_SIZE(sio_config); i++) { + writeb(sio_config[i].key, io_base + SIO_CONF_PORT); + writeb(sio_config[i].data, io_base + SIO_DATA_PORT); + } + + /* exit config state */ + writeb(SIOCONF_EXIT_SETUP, io_base + SIO_CONF_PORT); +} diff --git a/board/imgtec/malta/superio.h b/board/imgtec/malta/superio.h new file mode 100644 index 0000000..1450da5 --- /dev/null +++ b/board/imgtec/malta/superio.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2013 Imagination Technologies + * Author: Paul Burton <paul.burton@imgtec.com> + * + * Setup code for the FDC37M817 super I/O controller + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef __BOARD_MALTA_SUPERIO_H__ +#define __BOARD_MALTA_SUPERIO_H__ + +extern void malta_superio_init(void *io_base); + +#endif /* __BOARD_MALTA_SUPERIO_H__ */ |