diff --git a/sys/arch/arm/arm32/kobj_machdep.c b/sys/arch/arm/arm32/kobj_machdep.c index 901d01f..6ff9326 100644 --- a/sys/arch/arm/arm32/kobj_machdep.c +++ b/sys/arch/arm/arm32/kobj_machdep.c @@ -93,6 +93,31 @@ kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data, case R_ARM_NONE: /* none */ break; + case R_ARM_PC24: { /* S - PC + (SignExt(A & 0xffffff)) << 2 */ + Elf_Addr tmp; + + /* Truncate (and sign-extend if needed) 24-bit addend */ + addend &= 0x00ffffff; + if (addend & 0x00800000) + addend |= 0xff000000; + + addr = kobj_sym_lookup(ko, symidx); + if (addr == 0) + return -1; + tmp = addr - (Elf_Addr)where + (addend << 2); + printf("kobj_reloc: R_PC24 relocation @ %p -- base = %#lx, addr = %#lx, addend = %#lx, out = %#lx\n", where, (long)relocbase, (long)addr, (long)addend, (long)tmp); + if ((tmp & 0xfe000000) != 0xfe000000 && + (tmp & 0xfe000000) != 0) { + printf("kobj_reloc: failed R_PC24 relocation @ %p (disp %ld (%#lx) out of range)\n", where, (long)tmp, (long)tmp); + return -1; + } + + tmp >>= 2; + if ((*where & 0x00ffffff) != (tmp & 0x00ffffff)) + *where = (*where & 0xff000000) | (tmp & 0x00ffffff); + break; + } + case R_ARM_ABS32: addr = kobj_sym_lookup(ko, symidx); if (addr == 0) @@ -125,7 +150,7 @@ kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data, break; default: - printf("kobj_reloc: unexpected relocation type %d\n", rtype); + printf("kobj_reloc: unexpected relocation type %d @ %p\n", rtype, where); return -1; } return 0; diff --git a/sys/arch/evbarm/conf/IPAQ3900 b/sys/arch/evbarm/conf/IPAQ3900 new file mode 100644 index 0000000..de34b38 --- /dev/null +++ b/sys/arch/evbarm/conf/IPAQ3900 @@ -0,0 +1,244 @@ +# +# IPAQ3900 -- evbarm kernel for Compaq iPAQ 3900 handheld. +# + +include "arch/evbarm/conf/std.ipaq3900" + +# estimated number of users + +maxusers 32 + +# Standard system options + +options RTC_OFFSET=0 # hardware clock is this many mins. west of GMT +#options NTP # NTP phase/frequency locked loop + +# CPU options + +options CPU_XSCALE_PXA250 # Support the XScale core +#options XSCALE_CACHE_WRITE_THROUGH +#options XSCALE_CACHE_WRITE_BACK +makeoptions CPUFLAGS="-mcpu=xscale" + +# Architecture options + +# File systems + +file-system FFS # UFS +#file-system LFS # log-structured file system +file-system MFS # memory file system +file-system NFS # Network file system +#file-system ADOSFS # AmigaDOS-compatible file system +#file-system EXT2FS # second extended file system (linux) +#file-system CD9660 # ISO 9660 + Rock Ridge file system +file-system MSDOSFS # MS-DOS file system +#file-system FDESC # /dev/fd +file-system KERNFS # /kern +#file-system NULLFS # loopback file system +#file-system PORTAL # portal filesystem (still experimental) +#file-system PROCFS # /proc +#file-system UMAPFS # NULLFS + uid and gid remapping +#file-system UNION # union file system +file-system PTYFS # /dev/pts/N support + +# File system options +#options QUOTA # UFS quotas +#options FFS_EI # FFS Endian Independant support +#options NFSSERVER +#options SOFTDEP +#options FFS_NO_SNAPSHOT # No FFS snapshot support + +# Networking options + +#options GATEWAY # packet forwarding +options INET # IP + ICMP + TCP + UDP +#options INET6 # IPV6 +#options IPSEC # IP security +#options IPSEC_ESP # IP security (encryption part; define w/ IPSEC) +#options IPSEC_NAT_T # IPsec NAT traversal (NAT-T) +#options IPSEC_DEBUG # debug for IP security +#options MROUTING # IP multicast routing +#options PIM # Protocol Independent Multicast +#options ISO,TPIP # OSI +#options EON # OSI tunneling over IP +#options NETATALK # AppleTalk networking +#options PFIL_HOOKS # pfil(9) packet filter hooks +#options PPP_BSDCOMP # BSD-Compress compression support for PPP +#options PPP_DEFLATE # Deflate compression support for PPP +#options PPP_FILTER # Active filter support for PPP (requires bpf) +#options TCP_DEBUG # Record last TCP_NDEBUG packets with SO_DEBUG + +#options NFS_BOOT_BOOTP +options NFS_BOOT_DHCP +#options NFS_BOOT_BOOTPARAM + +# Compatibility options + +#options COMPAT_43 # 4.3BSD compatibility. +options COMPAT_30 # NetBSD 3.0 compatibility. +#options COMPAT_20 # NetBSD 2.0 compatibility. +#options COMPAT_16 # NetBSD 1.6 compatibility. +#options COMPAT_15 # NetBSD 1.5 compatibility. +#options COMPAT_14 # NetBSD 1.4 compatibility. +#options COMPAT_13 # NetBSD 1.3 compatibility. +#options COMPAT_12 # NetBSD 1.2 compatibility. +#options COMPAT_11 # NetBSD 1.1 compatibility. +#options COMPAT_10 # NetBSD 1.0 compatibility. +#options COMPAT_09 # NetBSD 0.9 compatibility. +#options TCP_COMPAT_42 # 4.2BSD TCP/IP bug compat. Not recommended. +options COMPAT_BSDPTY # /dev/[pt]ty?? ptys. + +# Shared memory options + +#options SYSVMSG # System V-like message queues +#options SYSVSEM # System V-like semaphores +#options SEMMNI=10 # number of semaphore identifiers +#options SEMMNS=60 # number of semaphores in system +#options SEMUME=10 # max number of undo entries per process +#options SEMMNU=30 # number of undo structures in system +#options SYSVSHM # System V-like memory sharing +#options SHMMAXPGS=1024 # 1024 pages is the default + +# Device options + +# NB: MEMORYDISK stuff left for IPAQ3900_INSTALL kernel + +# Miscellaneous kernel options +options KTRACE # system call tracing, a la ktrace(1) +options MODULAR # NWO of loadable kernel modules +#options KMEMSTATS # kernel memory statistics +options PCMCIAVERBOSE # verbose PCMCIA configuration messages +#options SCSIVERBOSE # Verbose SCSI errors +#options MIIVERBOSE # Verbose MII autoconfuration messages +#options DDB_KEYCODE=0x40 +#options USERCONF # userconf(4) support + +# Development and Debugging options + +options DIAGNOSTIC # internally consistency checks +options EVBARM_SPL_NOINLINE +options INSECURE +#options DEBUG +#options PMAP_DEBUG # Enable pmap_debug_level code +options VERBOSE_INIT_ARM # verbose bootstraping messages +options DDB # in-kernel debugger +#options DDB_HISTORY_SIZE=100 # Enable history editing in DDB +#options KGDB +#options DEBUG_KGDB +#makeoptions DEBUG="-g" # compile full symbol table +#options SYMTAB_SPACE=200000 + +config netbsd root on ? type ? + +# The main bus device +mainbus0 at root + +# The boot cpu +cpu0 at mainbus? + +# integrated peripherals +pxaip0 at mainbus? + +pxaintc0 at pxaip? # interrupt controller +pxagpio0 at pxaip? # GPIO +options PXAGPIO_HAS_GPION_INTRS + +pxartc0 at pxaip? # RTC + + +# cotulla integrated 16550 UARTs +options COM_PXA2X0 +com0 at pxaip? addr 0x40100000 intr 22 # Full Function UART +com1 at pxaip? addr 0x40200000 intr 21 # BlueTootth UART +com2 at pxaip? addr 0x40700000 intr 20 # Standard UART (for IrDA) +#com3 at pxaip? addr 0x41600000 intr 7 # Hardware UART(console-hw, -bt) +options FFUARTCONSOLE +options BTUARTCONSOLE +options KGDB_DEVNAME="\"btuart\"" # ffuart or btuart +options KGDB_DEVRATE=115200 + +# DMAC support +pxadmac0 at pxaip? addr 0x40000000 intr 25 +options PXA2X0_DMAC_DMOVER_CONCURRENCY=4 # Enable dmover(9) backend +#options PXA2X0_DMAC_FIXED_PRIORITY # Don't want multiple priority + +# AC97 Audio support +pxaacu0 at pxaip? addr 0x40500000 intr 14 +audio* at audiobus? + +# LCD +lcd0 at pxaip? +wsdisplay* at lcd? console ? +options WSEMUL_VT100 # VT100 / VT220 emulation +options FONT_VT220L8x8 +options FONT_VT220L8x10 + +# integrated PCMCIA/CF controller +pxapcic0 at pxaip? + +# PCMCIA bus support +pcmcia* at pxapcic? + +# PCMCIA serial interfaces +com* at pcmcia? function ? # Modems and serial cards + +##pcmcom* at pcmcia? function ? # PCMCIA multi-port serial cards +##com* at pcmcom? slave ? # ...and the slave devices + +# PCMCIA SCSI controllers +##aic* at pcmcia? function ? # Adaptec APA-1460 SCSI +##esp* at pcmcia? function ? # Qlogic ESP406/FAS408 SCSI + +# SCSI devices +##st* at scsibus? target ? lun ? # SCSI tape drives +##cd* at scsibus? target ? lun ? # SCSI CD-ROM drives +##ch* at scsibus? target ? lun ? # SCSI autochangers +##ses* at scsibus? target ? lun ? # SCSI Enclosure Services devices +##ss* at scsibus? target ? lun ? # SCSI scanners + +# PCMCIA IDE controllers and disks +##wdc* at pcmcia? function ? +##atabus* at wdc? channel ? +##wd* at atabus? drive ? flags 0x0000 + +# +# Networking devices +# +##an* at pcmcia? function ? # Aironet PC4500/PC4800 (802.11) +##awi* at pcmcia? function ? # BayStack 650/660 (802.11FH/DS) +##cnw* at pcmcia? function ? # Xircom/Netwave AirSurfer +##ep* at pcmcia? function ? # 3Com 3c589 and 3c562 Ethernet +##mbe* at pcmcia? function ? # MB8696x based Ethernet +ne* at pcmcia? function ? # NE2000-compatible Ethernet +##ray* at pcmcia? function ? # Raytheon Raylink (802.11) +##sm* at pcmcia? function ? # Megahertz Ethernet +##tr* at pcmcia? function ? # TROPIC based Token-Ring +wi* at pcmcia? function ? # Lucent/Intersil WaveLan IEEE (802.11) +##xirc* at pcmcia? function ? # Xircom CreditCard Ethernet +##com* at xirc? +##xi* at xirc? + +##mhzc* at pcmcia? function ? # Megahertz Ethernet/Modem combo cards +##com* at mhzc? +##sm* at mhzc? + +# PCMCIA audio devices +###esl* at pcmcia? function ? # ESS 1688 AudioDrive + +# Pseudo-Devices + +# disk/mass storage pseudo-devices +#pseudo-device vnd # disk-like interface to files +#pseudo-device fss 4 # file system snapshot device + +# network pseudo-devices +pseudo-device bpfilter # Berkeley packet filter +pseudo-device loop # network loopback + +# miscellaneous pseudo-devices +pseudo-device pty # pseudo-terminals +pseudo-device rnd # /dev/random and in-kernel generator +#options RND_COM # XXXrkb: can deadlock due to use of + # timer, etc. locks at IPL > IPL_SCHED +pseudo-device ksyms # /dev/ksyms + diff --git a/sys/arch/evbarm/conf/IPAQ3900_INSTALL b/sys/arch/evbarm/conf/IPAQ3900_INSTALL new file mode 100644 index 0000000..7328a96 --- /dev/null +++ b/sys/arch/evbarm/conf/IPAQ3900_INSTALL @@ -0,0 +1,8 @@ +# $NetBSD$ +# +# IPAQ3900_INSTALL -- IPAQ3900 kernel with installation-sized +# ramdisk +# + +include "arch/evbarm/conf/IPAQ3900" +include "arch/evbarm/conf/INSTALL" diff --git a/sys/arch/evbarm/conf/files.ipaq3900 b/sys/arch/evbarm/conf/files.ipaq3900 new file mode 100644 index 0000000..2a76bb4 --- /dev/null +++ b/sys/arch/evbarm/conf/files.ipaq3900 @@ -0,0 +1,23 @@ +# $NetBSD: files.ipaq3900,v 1.6 2005/12/11 12:17:07 christos Exp $ +# +# Compaq iPAQ 3900 system configuration info +# + +file arch/evbarm/ipaq3900/ipaq3900_machdep.c + +# CPU support and integrated peripherals +include "arch/arm/xscale/files.pxa2x0" + +#include "dev/sdmmc/files.sdmmc" + +# PCMCIA/CF socket +attach pxapcic at pxaip with pxapcic_ipaq3900_pcic +file arch/evbarm/ipaq3900/ipaq3900_pcic.c pxapcic_ipaq3900_pcic + +# PXA2x0 MMC/SD controller +#attach pxamci at pxaip with ipaq3900_mci +#file arch/evbarm/ipaq3900/ipaq3900_mci.c ipaq3900_mci + +# LCD frame buffer +attach lcd at pxaip with ipaq3900_lcd +file arch/evbarm/ipaq3900/ipaq3900_lcd.c ipaq3900_lcd diff --git a/sys/arch/evbarm/conf/mk.ipaq3900 b/sys/arch/evbarm/conf/mk.ipaq3900 new file mode 100644 index 0000000..287e343 --- /dev/null +++ b/sys/arch/evbarm/conf/mk.ipaq3900 @@ -0,0 +1,8 @@ +# $NetBSD: mk.ipaq3900,v 1.1 2003/01/03 02:16:28 thorpej Exp $ + +SYSTEM_FIRST_OBJ= ipaq3900_start.o +SYSTEM_FIRST_SFILE= ${THISARM}/ipaq3900/ipaq3900_start.S + +KERNEL_BASE_PHYS=0xa0200000 +KERNEL_BASE_VIRT=0xc0200000 + diff --git a/sys/arch/evbarm/conf/std.ipaq3900 b/sys/arch/evbarm/conf/std.ipaq3900 new file mode 100644 index 0000000..04f6ecb --- /dev/null +++ b/sys/arch/evbarm/conf/std.ipaq3900 @@ -0,0 +1,30 @@ +# $NetBSD: std.lubbock,v 1.6 2008/01/27 12:37:12 chris Exp $ +# +# standard NetBSD/evbarm for IPAQ3900 options + +machine evbarm arm +include "conf/std" # MI standard options +include "arch/arm/conf/std.arm" # arch standard options + +# Pull in IPAQ3900 config definitions. +include "arch/evbarm/conf/files.ipaq3900" + +options COTULLA +options IPAQ3900 +options EXEC_ELF32 +options EXEC_SCRIPT + +# To support easy transit to ../arch/arm/arm32 +options ARM32 + +options KERNEL_BASE_EXT=0xc0000000 +makeoptions LOADADDRESS="0xc0200000" +makeoptions BOARDTYPE="ipaq3900" +makeoptions BOARDMKFRAG="${THISARM}/conf/mk.ipaq3900" + +options ARM_INTR_IMPL="" + +# OS Timer This is compatible to SA1110's OS Timer. +saost* at pxaip? addr 0x40a00000 size 0x20 + + diff --git a/sys/arch/evbarm/ipaq3900/ipaq3900_lcd.c b/sys/arch/evbarm/ipaq3900/ipaq3900_lcd.c new file mode 100644 index 0000000..689355b --- /dev/null +++ b/sys/arch/evbarm/ipaq3900/ipaq3900_lcd.c @@ -0,0 +1,226 @@ +/* $NetBSD: ipaq3900_lcd.c,v 1.7 2007/03/04 05:59:45 christos Exp $ */ + +/* + * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * LCD driver for Intel Lubbock. + * + * Controlling LCD is almost completely done through PXA2X0's + * integrated LCD controller. Codes for it is arm/xscale/pxa2x0_lcd.c. + * + * Codes in this file provide platform specific things including: + * LCD on/off switch in on-board PLD register. + * LCD panel geometry + */ +#include +__KERNEL_RCSID(0, "$NetBSD: ipaq3900_lcd.c,v 1.7 2007/03/04 05:59:45 christos Exp $"); + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +int lcd_match( struct device *, struct cfdata *, void *); +void lcd_attach( struct device *, struct device *, void *); +int lcdintr(void *); + +static void lcd_power_control(int); + +/* + * wsdisplay glue + */ +static struct pxa2x0_wsscreen_descr lcd_std_screen = { + .c = { + .name = "std", + .textops = &pxa2x0_lcd_emulops, + .fontwidth = 8, + .fontheight = 8, + .capabilities = WSSCREEN_WSCOLORS, + }, + .depth = 16, /* bits per pixel */ +}; + +static const struct wsscreen_descr *lcd_scr_descr[] = { + &lcd_std_screen.c +}; + +static const struct wsscreen_list lcd_screen_list = { + .nscreens = __arraycount(lcd_scr_descr), + .screens = lcd_scr_descr, +}; + +int lcd_ioctl(void *, void *, u_long, void *, int, struct lwp *); + +int lcd_show_screen(void *, void *, int, + void (*)(void *, int, int), void *); + +const struct wsdisplay_accessops lcd_accessops = { + lcd_ioctl, + pxa2x0_lcd_mmap, + pxa2x0_lcd_alloc_screen, + pxa2x0_lcd_free_screen, + lcd_show_screen, + NULL, /* load_font */ +}; + +CFATTACH_DECL(ipaq3900_lcd, sizeof (struct pxa2x0_lcd_softc), lcd_match, + lcd_attach, NULL, NULL); + +int +lcd_match( struct device *parent, struct cfdata *cf, void *aux ) +{ + return 1; +} + +static const struct lcd_panel_geometry ipaq_3900 = +{ + 320, /* Width */ + 240, /* Height */ + 0, /* No extra lines */ + + LCDPANEL_ACTIVE|LCDPANEL_HSP|LCDPANEL_VSP, + 10, /* clock divider */ + 0, /* AC bias pin freq */ + + 3, /* horizontal sync pulse width */ + 12, /* BLW */ + 17, /* ELW */ + + 3, /* vertical sync pulse width */ + 6, /* BFW */ + 17, /* EFW */ + +}; + +void lcd_attach( struct device *parent, struct device *self, void *aux ) +{ + int is_console = !(bootinfo->bi_cnuse & BI_CNUSE_SERIAL); + struct pxa2x0_lcd_softc *sc = (struct pxa2x0_lcd_softc *)self; + struct wsemuldisplaydev_attach_args aa; + + if (is_console) + pxa2x0_lcd_cnattach(&lcd_std_screen, &ipaq_3900); + + pxa2x0_lcd_attach_sub(sc, aux, &ipaq_3900); + + /* make wsdisplay screen list */ + pxa2x0_lcd_setup_wsscreen(&lcd_std_screen, &ipaq_3900, NULL); + lcd_power_control(1); + + aa.console = is_console; + aa.scrdata = &lcd_screen_list; + aa.accessops = &lcd_accessops; + aa.accesscookie = sc; + + printf( "\n" ); + + (void) config_found(self, &aa, wsemuldisplaydevprint); +} + +int +lcd_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, struct lwp *l) +{ + switch (cmd) { + case WSDISPLAYIO_SVIDEO: + if (*(int *)data == WSDISPLAYIO_VIDEO_ON) + lcd_power_control(1); + else + lcd_power_control(0); + break; /* turn on/off LCD controller */ + } + return pxa2x0_lcd_ioctl( v, vs, cmd, data, flag, l ); +} + +int +lcd_show_screen(void *v, void *cookie, int waitok, + void (*cb)(void *, int, int), void *cbarg) +{ + pxa2x0_lcd_show_screen(v,cookie,waitok,cb,cbarg); + lcd_power_control(1); + + return (0); +} + +static void +lcd_power_control(int on) +{ + if (on) { + /* + * Set up backlight params: + * H3800_ASIC2_CLOCK_Enable |= ASIC2_CLOCK_PWM; + * if ( level < 21 ) level = 21; + * if ( level > 64 ) level = 64; + * H3800_ASIC2_PWM_0_DutyTime = level; + * H3800_ASIC2_PWM_0_TimeBase |= + * PWM_TIMEBASE_ENABLE; + * + * Backlight on: + * H3900_ASIC3_GPIO_B_OUT |= GPIO3_FL_PWR_ON; + */ + ioreg16_write(IPAQ3900_ASIC3_VBASE + 0x108, + ioreg16_read(IPAQ3900_ASIC3_VBASE + 0x108) | + (1 << 5) | /* GPIO3_LCD_5V_ON */ + (1 << 6) | /* GPIO3_LCD_ON */ + (1 << 7) | /* GPIO3_LCD_PCI */ + (1 << 1) | /* GPIO3_LCD_9V_ON */ + (1 << 3)); /* GPIO3_LCD_NV_ON */ + } else { + /* + * Backlight off: + * H3900_ASIC3_GPIO_B_OUT &= ~GPIO3_FL_PWR_ON; + * + * Clean up backlight params: + * H3800_ASIC2_PWM_0_TimeBase &= + * ~PWM_TIMEBASE_ENABLE; + * H3800_ASIC2_CLOCK_Enable &= ~ASIC2_CLOCK_PWM; + */ + ioreg16_write(IPAQ3900_ASIC3_VBASE + 0x108, + ioreg16_read(IPAQ3900_ASIC3_VBASE + 0x108) & + ~((1 << 5) | /* GPIO3_LCD_5V_ON */ + (1 << 6) | /* GPIO3_LCD_ON */ + (1 << 7) | /* GPIO3_LCD_PCI */ + (1 << 1) | /* GPIO3_LCD_9V_ON */ + (1 << 3))); /* GPIO3_LCD_NV_ON */ + } +} diff --git a/sys/arch/evbarm/ipaq3900/ipaq3900_machdep.c b/sys/arch/evbarm/ipaq3900/ipaq3900_machdep.c new file mode 100644 index 0000000..c920096 --- /dev/null +++ b/sys/arch/evbarm/ipaq3900/ipaq3900_machdep.c @@ -0,0 +1,1254 @@ +/* $NetBSD: ipaq3900_machdep.c,v 1.17 2008/01/19 13:11:16 chris Exp $ */ + +/* + * Copyright (c) 2002, 2003, 2005 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Machine dependant functions for kernel setup for + * Intel DBPXA250 evaluation board (a.k.a. Lubbock). + * Based on iq80310_machhdep.c + */ +/* + * Copyright (c) 2001 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright (c) 1997,1998 Mark Brinicombe. + * Copyright (c) 1997,1998 Causality Limited. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Mark Brinicombe + * for the NetBSD Project. + * 4. The name of the company nor the name of the author may be used to + * endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Machine dependant functions for kernel setup for Intel IQ80310 evaluation + * boards using RedBoot firmware. + */ + +#include +__KERNEL_RCSID(0, "$NetBSD: ipaq3900_machdep.c,v 1.17 2008/01/19 13:11:16 chris Exp $"); + +#include "opt_ddb.h" +#include "opt_kgdb.h" +#include "opt_pmap_debug.h" +#include "opt_md.h" +#include "opt_com.h" +#include "md.h" +#include "lcd.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include +#include +#ifdef KGDB +#include +#endif + +#ifndef DB_ELFSIZE +#error Must define DB_ELFSIZE! +#endif +#define ELFSIZE DB_ELFSIZE +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* Kernel text starts 2MB in from the bottom of the kernel address space. */ +#define KERNEL_TEXT_BASE (KERNEL_BASE + 0x00200000) +#define KERNEL_VM_BASE (KERNEL_BASE + 0x01000000) + +/* + * The range 0xc1000000 - 0xccffffff is available for kernel VM space + * Core-logic registers and I/O mappings occupy 0xfd000000 - 0xffffffff + */ +#define KERNEL_VM_SIZE 0x0C000000 + + +/* + * Address to call from cpu_reset() to reset the machine. + * This is machine architecture dependant as it varies depending + * on where the ROM appears when you turn the MMU off. + */ + +u_int cpu_reset_address = 0; + +/* Define various stack sizes in pages */ +#define IRQ_STACK_SIZE 1 +#define ABT_STACK_SIZE 1 +#define UND_STACK_SIZE 1 + +vm_offset_t physical_start; +vm_offset_t physical_freestart; +vm_offset_t physical_freeend; +vm_offset_t physical_end; +u_int free_pages; +vm_offset_t pagetables_start; +int physmem = 0; + +/*int debug_flags;*/ +#ifndef PMAP_STATIC_L1S +int max_processes = 64; /* Default number */ +#endif /* !PMAP_STATIC_L1S */ + +/* Physical and virtual addresses for some global pages */ +pv_addr_t systempage; +pv_addr_t irqstack; +pv_addr_t undstack; +pv_addr_t abtstack; +pv_addr_t kernelstack; +pv_addr_t minidataclean; + +vm_offset_t msgbufphys; + +extern char etext[], _end[]; +extern u_int data_abort_handler_address; +extern u_int prefetch_abort_handler_address; +extern u_int undefined_handler_address; + +#ifdef PMAP_DEBUG +extern int pmap_debug_level; +#endif + +#define KERNEL_PT_SYS 0 /* Page table for mapping proc0 zero page */ +#define KERNEL_PT_KERNEL 1 /* Page table for mapping kernel */ +#define KERNEL_PT_KERNEL_NUM 4 +#define KERNEL_PT_VMDATA (KERNEL_PT_KERNEL+KERNEL_PT_KERNEL_NUM) + /* Page tables for mapping kernel VM */ +#define KERNEL_PT_VMDATA_NUM 4 /* start with 16MB of KVM */ +#define NUM_KERNEL_PTS (KERNEL_PT_VMDATA + KERNEL_PT_VMDATA_NUM) + +pv_addr_t kernel_pt_table[NUM_KERNEL_PTS]; + +struct user *proc0paddr; + +struct hpcboot_args { + int argc; + char** argv; + struct bootinfo* bi; +}; + + +char boot_file[16]; +BootConfig bootconfig; /* Boot config storage */ +char *boot_args = NULL; +static char booted_kernel_storage[80]; +struct bootinfo *bootinfo, bootinfo_storage; +char *booted_kernel = booted_kernel_storage; + +/* Prototypes */ + +void consinit(void); +void kgdb_port_init(void); +void change_clock(uint32_t v); + +#ifdef BOOT_DUMP +void dumppages(char *, int); +#endif + +bs_protos(bs_notimpl); + +#include "com.h" +#if NCOM > 0 +#include +#include +#endif + +#ifndef CONSPEED +#define CONSPEED B115200 /* What RedBoot uses */ +#endif +#ifndef CONMODE +#define CONMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +#endif + +int comcnspeed = CONSPEED; +int comcnmode = CONMODE; + +static struct pxa2x0_gpioconf boarddep_gpioconf[] = { + { 44, GPIO_ALT_FN_1_IN }, /* BTCST */ + { 45, GPIO_ALT_FN_2_OUT }, /* BTRST */ + + { 29, GPIO_ALT_FN_1_IN }, /* SDATA_IN0 */ + + { -1 } +}; + +static struct pxa2x0_gpioconf *ipaq3900_gpioconf[] = { + pxa25x_com_btuart_gpioconf, + pxa25x_com_ffuart_gpioconf, + pxa25x_com_stuart_gpioconf, + pxa25x_pcic_gpioconf, + pxa25x_pxaacu_gpioconf, + boarddep_gpioconf, + NULL +}; + +/* + * void cpu_reboot(int howto, char *bootstr) + * + * Reboots the system + * + * Deal with any syncing, unmounting, dumping and shutdown hooks, + * then reset the CPU. + */ +void +cpu_reboot(int howto, char *bootstr) +{ +#ifdef DIAGNOSTIC + /* info */ + printf("boot: howto=%08x curproc=%p\n", howto, curproc); +#endif + + /* + * If we are still cold then hit the air brakes + * and crash to earth fast + */ + if (cold) { + doshutdownhooks(); + printf("The operating system has halted.\n"); + printf("Please press any key to reboot.\n\n"); + cngetc(); + printf("rebooting...\n"); + cpu_reset(); + /*NOTREACHED*/ + } + + /* Disable console buffering */ +/* cnpollc(1);*/ + + /* + * If RB_NOSYNC was not specified sync the discs. + * Note: Unless cold is set to 1 here, syslogd will die during the + * unmount. It looks like syslogd is getting woken up only to find + * that it cannot page part of the binary in as the filesystem has + * been unmounted. + */ + if (!(howto & RB_NOSYNC)) + bootsync(); + + /* Say NO to interrupts */ + splhigh(); + + /* Do a dump if requested. */ + if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) + dumpsys(); + + /* Run any shutdown hooks */ + doshutdownhooks(); + + /* Make sure IRQ's are disabled */ + IRQdisable; + + if (howto & RB_HALT) { + printf("The operating system has halted.\n"); + printf("Please press any key to reboot.\n\n"); + cngetc(); + } + + printf("rebooting...\n"); + cpu_reset(); + /*NOTREACHED*/ +} + +/* + * Static device mappings. These peripheral registers are mapped at + * fixed virtual addresses very early in initarm() so that we can use + * them while booting the kernel, and stay at the same address + * throughout whole kernel's life time. + * + * We use this table twice; once with bootstrap page table, and once + * with kernel's page table which we build up in initarm(). + * + * Since we map these registers into the bootstrap page table using + * pmap_devmap_bootstrap() which calls pmap_map_chunk(), we map + * registers segment-aligned and segment-rounded in order to avoid + * using the 2nd page tables. + */ + +#define _A(a) ((a) & ~L1_S_OFFSET) +#define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) + +static const struct pmap_devmap ipaq3900_devmap[] = { + { + IPAQ3900_GPIO_VBASE, + _A(PXA2X0_GPIO_BASE), + _S(PXA250_GPIO_SIZE), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_CLKMAN_VBASE, + _A(PXA2X0_CLKMAN_BASE), + _S(PXA2X0_CLKMAN_SIZE), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_INTCTL_VBASE, + _A(PXA2X0_INTCTL_BASE), + _S(PXA2X0_INTCTL_SIZE), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_FFUART_VBASE, + _A(PXA2X0_FFUART_BASE), + _S(4 * COM_NPORTS), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_BTUART_VBASE, + _A(PXA2X0_BTUART_BASE), + _S(4 * COM_NPORTS), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_STUART_VBASE, + _A(PXA2X0_STUART_BASE), + _S(4 * COM_NPORTS), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_ASIC2_VBASE, + _A(0x15000000), + _S(0x1000), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_ASIC3_VBASE, + _A(0x14800000), + _S(0x2000), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + { + IPAQ3900_ASIC3_SD_VBASE, + _A(0x14000000), + _S(0x2000), + VM_PROT_READ|VM_PROT_WRITE, PTE_NOCACHE, + }, + {0, 0, 0, 0,} +}; + +#undef _A +#undef _S + +/* + * u_int initarm(...) + * + * Initial entry point on startup. This gets called before main() is + * entered. + * It should be responsible for setting up everything that must be + * in place when main is called. + * This includes + * Taking a copy of the boot configuration structure. + * Initialising the physical console so characters can be printed. + * Setting up page tables for the kernel + * Relocating the kernel to the bottom of physical memory + */ +u_int +initarm(void *arg) +{ + extern vaddr_t xscale_cache_clean_addr; + int loop; + int loop1; + u_int l1pagetable; + paddr_t memstart; + psize_t memsize; + size_t symbolsize = 0; + int dbg_value = '0'; +#ifdef BOOT_DUMP + vm_offset_t setup_pages_start; + vm_offset_t setup_pages_end; +#endif +#ifdef DIAGNOSTIC + extern vsize_t xscale_minidata_clean_size; /* used in KASSERT */ +#endif + struct hpcboot_args* hpc_boot_args = arg; + +#define LEDSTEP_P() \ + do { \ + while (!(ioreg8_read(PXA2X0_FFUART_BASE + 0x14) & 0x20)) \ + /* EMPTY */; \ + ioreg8_write(PXA2X0_FFUART_BASE + 0x00, dbg_value++); \ + while (!(ioreg8_read(PXA2X0_FFUART_BASE + 0x14) & 0x20)) \ + /* EMPTY */; \ + ioreg8_read(PXA2X0_FFUART_BASE + 0x08); \ + } while (0) + +#define LEDSTEP() \ + do { \ + while (!(ioreg8_read(IPAQ3900_FFUART_VBASE + 0x14) & 0x20)) \ + /* EMPTY */; \ + ioreg8_write(IPAQ3900_FFUART_VBASE + 0x00, dbg_value++); \ + while (!(ioreg8_read(IPAQ3900_FFUART_VBASE + 0x14) & 0x20)) \ + ; /* EMPTY */ \ + ioreg8_read(IPAQ3900_FFUART_VBASE + 0x08); \ + } while (0) + + /* + * XXXrkb: grotty stuff to keep interrupts from blowing us out of + * the water before we're ready. Should probably be pushed into + * the drivers, though it's good to get the HW in a sane state + * regardless of which drivers are/aren't configured in. + */ + + /* Init ASIC3 GPIO mask / output / direction registers */ + ioreg16_write(IPAQ3900_ASIC3_VBASE + 0x100, 0xffff); + ioreg16_write(IPAQ3900_ASIC3_VBASE + 0x108, 0x0004); + ioreg16_write(IPAQ3900_ASIC3_VBASE + 0x104, 0xffff); + + /* Disable RTC HZ/alarm interrupts, clear status */ + ioreg_write(PXA2X0_RTC_BASE + RTC_RTSR, 0x03); + + /* Disable OS timer match interrupts, clear status */ + ioreg_write(PXA2X0_OST_BASE + SAOST_IR, 0); + ioreg_write(PXA2X0_OST_BASE + SAOST_SR, + ioreg_read(PXA2X0_OST_BASE + SAOST_SR)); + + /* Disable LCD 'disable done' interrupt, disable LCD controller */ + ioreg_write(PXA2X0_LCDC_BASE + LCDC_LCCR0, + ioreg_read(PXA2X0_LCDC_BASE + LCDC_LCCR0) | LCCR0_LDM); + ioreg_write(PXA2X0_LCDC_BASE + LCDC_LCCR0, + ioreg_read(PXA2X0_LCDC_BASE + LCDC_LCCR0) | LCCR0_DIS); + + /* ACK any outstanding LCD controller interrupts */ + ioreg_write(PXA2X0_LCDC_BASE + LCDC_LCSR, + ioreg_read(PXA2X0_LCDC_BASE + LCDC_LCSR)); + + /* use physical address until at least bootstrap devmap is set up */ + LEDSTEP_P(); + + /* register the static device map (mapped by startup asm code) */ + pmap_devmap_register(ipaq3900_devmap); + + LEDSTEP_P(); + + /* start 32.768 kHz OSC */ + ioreg_write(IPAQ3900_CLKMAN_VBASE + 0x08, 2); + /* Get ready for splfoo() */ + pxa2x0_intr_bootstrap(IPAQ3900_INTCTL_VBASE); + + LEDSTEP(); + + /* + * Heads up ... Setup the CPU / MMU / TLB functions + */ + if (set_cpufuncs()) + panic("cpu not recognized!"); + + LEDSTEP(); + + +#if 0 + /* Calibrate the delay loop. */ +#endif + + /* + * Okay, RedBoot has provided us with the following memory map: + * + * XXXrkb: no RedBoot, but it might be useful to document the + * machine's address map here anyway (and any specifics of how + * Windows / hpcboot or the CRL bootloader sets up the machine). + * + * Physical Address Range Description + * ----------------------- ---------------------------------- + * 0x00000000 - 0x01ffffff flash Memory (32MB) + * 0x04000000 - 0x05ffffff Application flash Memory (32MB) + * 0x08000000 - 0x080000ff I/O baseboard registers + * 0x0a000000 - 0x0a0fffff SRAM (1MB) + * 0x0c000000 - 0x0c0fffff Ethernet Controller + * 0x0e000000 - 0x0e0fffff Ethernet Controller (Attribute) + * 0x10000000 - 0x103fffff SA-1111 Companion Chip + * 0x14000000 - 0x17ffffff Expansion Card (64MB) + * 0x40000000 - 0x480fffff Processor Registers + * 0xa0000000 - 0xa3ffffff SDRAM Bank 0 (64MB) + * + * + * Virtual Address Range X C B Description + * ----------------------- - - - ---------------------------------- + * 0x00000000 - 0x00003fff N Y Y SDRAM + * 0x00004000 - 0x000fffff N Y N Boot ROM + * 0x00100000 - 0x01ffffff N N N Application Flash + * 0x04000000 - 0x05ffffff N N N Exp Application Flash + * 0x08000000 - 0x080fffff N N N I/O baseboard registers + * 0x0a000000 - 0x0a0fffff N N N SRAM + * 0x40000000 - 0x480fffff N N N Processor Registers + * 0xa0000000 - 0xa000ffff N Y N RedBoot SDRAM + * 0xa0017000 - 0xa3ffffff Y Y Y SDRAM + * 0xc0000000 - 0xcfffffff Y Y Y Cache Flush Region + * (done by this routine) + * 0xfd000000 - 0xfd0000ff N N N I/O baseboard registers + * 0xfd100000 - 0xfd3fffff N N N Processor Registers. + * 0xfd400000 - 0xfd4fffff N N N FF-UART + * 0xfd500000 - 0xfd5fffff N N N BT-UART + * + * RedBoot's first level page table is at 0xa0004000. There + * are also 2 second-level tables at 0xa0008000 and + * 0xa0008400. We will continue to use them until we switch to + * our pagetable by setttb(). + * + */ + + /* setup GPIO for BTUART, in case bootloader doesn't take care of it */ + pxa2x0_gpio_bootstrap(IPAQ3900_GPIO_VBASE); + pxa2x0_gpio_config(ipaq3900_gpioconf); + + /* turn on clock to UART block. + XXX: this should not be done here. */ + ioreg_write(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN, CKEN_FFUART|CKEN_BTUART | + ioreg_read(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN)); + + LEDSTEP(); + + if (hpc_boot_args != NULL && hpc_boot_args->bi != NULL) { + /* copy bootinfo into known kernel space */ + bootinfo_storage = *hpc_boot_args->bi; + bootinfo = &bootinfo_storage; + } else { + memset(&bootinfo_storage, 0, sizeof(bootinfo_storage)); + bootinfo = &bootinfo_storage; + } + + consinit(); + LEDSTEP(); +#ifdef KGDB + kgdb_port_init(); + LEDSTEP(); +#endif + + /* Talk to the user */ + printf("\nNetBSD/evbarm (ipaq3900) booting ...\n"); + + /* parse kernel args */ + boothowto = 0; + boot_file[0] = '\0'; + if (hpc_boot_args != NULL && hpc_boot_args->argv != NULL) { + strncpy(booted_kernel_storage, hpc_boot_args->argv[0], + sizeof(booted_kernel_storage)); + +#ifdef VERBOSE_INIT_ARM + printf("booted kernel = %s\n", booted_kernel_storage); +#endif + for (loop = 1; loop < hpc_boot_args->argc; loop++) { + int howto; + char *cp = hpc_boot_args->argv[loop]; + +#ifdef VERBOSE_INIT_ARM + printf("\targv[%d] = %s\n", loop, cp); +#endif + switch (*cp) { + case '-': + /* Ignore extra '-' */ + break; + + case 'h': /* serial console */ + /* + * serial console: ignore this switch, we + * use the console setting from bootinfo + * instead. + */ + break; + + case 'b': + /* boot device: -b=sd0 etc. */ + cp = cp + 2; +#ifdef NFS + if (strcmp(cp, "nfs") == 0) + mountroot = nfs_mountroot; + else + strncpy(boot_file, cp, sizeof(boot_file)); +#else /* !NFS */ + strncpy(boot_file, cp, sizeof(boot_file)); +#endif /* !NFS */ + break; + default: + howto = 0; + BOOT_FLAG(*cp, howto); + if (! howto) + printf("bootflag '%c' not recognised\n", *cp); + else + boothowto |= howto; + break; + } + } + } + + { + /* Cotulla */ + memstart = 0xa0000000; + memsize = 0x04000000; /* 64MB */ + } + + printf("initarm: Configuring system ...\n"); + + /* Fake bootconfig structure for the benefit of pmap.c */ + /* XXX must make the memory description h/w independent */ + bootconfig.dramblocks = 1; + bootconfig.dram[0].address = memstart; + bootconfig.dram[0].pages = memsize / PAGE_SIZE; + + /* + * Set up the variables that define the availablilty of + * physical memory. For now, we're going to set + * physical_freestart to 0xa0200000 (where the kernel + * was loaded), and allocate the memory we need downwards. + * If we get too close to the page tables that RedBoot + * set up, we will panic. We will update physical_freestart + * and physical_freeend later to reflect what pmap_bootstrap() + * wants to see. + * + * XXX pmap_bootstrap() needs an enema. + */ + physical_start = bootconfig.dram[0].address; + physical_end = physical_start + (bootconfig.dram[0].pages * PAGE_SIZE); + + physical_freestart = 0xa0009000UL; + physical_freeend = 0xa0200000UL; +#ifdef BOOT_DUMP + setup_pages_end = KERNEL_BASE + physical_freeend - physical_start; +#endif + + physmem = (physical_end - physical_start) / PAGE_SIZE; + +#ifdef VERBOSE_INIT_ARM + /* Tell the user about the memory */ + printf("physmemory: %d pages at 0x%08lx -> 0x%08lx\n", physmem, + physical_start, physical_end - 1); +#endif + + /* + * Okay, the kernel starts 2MB in from the bottom of physical + * memory. We are going to allocate our bootstrap pages downwards + * from there. + * + * We need to allocate some fixed page tables to get the kernel + * going. We allocate one page directory and a number of page + * tables and store the physical addresses in the kernel_pt_table + * array. + * + * The kernel page directory must be on a 16K boundary. The page + * tables must be on 4K boundaries. What we do is allocate the + * page directory on the first 16K boundary that we encounter, and + * the page tables on 4K boundaries otherwise. Since we allocate + * at least 3 L2 page tables, we are guaranteed to encounter at + * least one 16K aligned region. + */ + +#ifdef VERBOSE_INIT_ARM + printf("Allocating page tables\n"); +#endif + + free_pages = (physical_freeend - physical_freestart) / PAGE_SIZE; + +#ifdef VERBOSE_INIT_ARM + printf("freestart = 0x%08lx, free_pages = %d (0x%08x)\n", + physical_freestart, free_pages, free_pages); +#endif + + /* Define a macro to simplify memory allocation */ +#define valloc_pages(var, np) \ + alloc_pages((var).pv_pa, (np)); \ + (var).pv_va = KERNEL_BASE + (var).pv_pa - physical_start; + +#define alloc_pages(var, np) \ + physical_freeend -= ((np) * PAGE_SIZE); \ + if (physical_freeend < physical_freestart) \ + panic("initarm: out of memory"); \ + (var) = physical_freeend; \ + free_pages -= (np); \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + + loop1 = 0; + kernel_l1pt.pv_pa = 0; + kernel_l1pt.pv_va = 0; + for (loop = 0; loop <= NUM_KERNEL_PTS; ++loop) { + /* Are we 16KB aligned for an L1 ? */ + if (((physical_freeend - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) == 0 + && kernel_l1pt.pv_pa == 0) { + valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + } else { + valloc_pages(kernel_pt_table[loop1], + L2_TABLE_SIZE / PAGE_SIZE); + ++loop1; + } + } + + /* This should never be able to happen but better confirm that. */ + if (!kernel_l1pt.pv_pa || (kernel_l1pt.pv_pa & (L1_TABLE_SIZE-1)) != 0) + panic("initarm: Failed to align the kernel page directory"); + + LEDSTEP(); + + /* + * Allocate a page for the system page mapped to V0xFFFF0000 + * This page will just contain the system vectors and can be + * shared by all processes. + */ + vector_page = ARM_VECTORS_HIGH; + alloc_pages(systempage.pv_pa, 1); + + /* Allocate stacks for all modes */ + valloc_pages(irqstack, IRQ_STACK_SIZE); + valloc_pages(abtstack, ABT_STACK_SIZE); + valloc_pages(undstack, UND_STACK_SIZE); + valloc_pages(kernelstack, UPAGES); + + /* Allocate enough pages for cleaning the Mini-Data cache. */ + KASSERT(xscale_minidata_clean_size <= PAGE_SIZE); + valloc_pages(minidataclean, 1); + +#ifdef VERBOSE_INIT_ARM + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + printf("kernel pt table[%d]: p0x%08lx v0x%08lx\n", + loop, + kernel_pt_table[loop].pv_pa, + kernel_pt_table[loop].pv_va); + } + + printf("System page: p0x%08lx v0x%08lx\n", systempage.pv_pa, + systempage.pv_va); + printf("IRQ stack: p0x%08lx v0x%08lx\n", irqstack.pv_pa, + irqstack.pv_va); + printf("ABT stack: p0x%08lx v0x%08lx\n", abtstack.pv_pa, + abtstack.pv_va); + printf("UND stack: p0x%08lx v0x%08lx\n", undstack.pv_pa, + undstack.pv_va); + printf("SVC stack: p0x%08lx v0x%08lx\n", kernelstack.pv_pa, + kernelstack.pv_va); + printf("Minidata clean: p0x%08lx v0x%08lx (size %ld)\n", + minidataclean.pv_pa, minidataclean.pv_va, + xscale_minidata_clean_size); +#endif + + /* + * XXX Defer this to later so that we can reclaim the memory + * XXX used by the initial page tables. + */ + alloc_pages(msgbufphys, round_page(MSGBUFSIZE) / PAGE_SIZE); + + /* + * Ok we have allocated physical pages for the primary kernel + * page tables + */ + +#ifdef VERBOSE_INIT_ARM + printf("Creating L1 page table at 0x%08lx\n", kernel_l1pt.pv_pa); +#endif + + /* + * Now we start construction of the L1 page table + * We start by mapping the L2 page tables into the L1. + * This means that we can replace L1 mappings later on if necessary + */ + l1pagetable = kernel_l1pt.pv_pa; + + /* Map the L2 pages tables in the L1 page table */ + pmap_link_l2pt(l1pagetable, vector_page & ~(0x00400000 - 1), + &kernel_pt_table[KERNEL_PT_SYS]); + + for (loop = 0; loop < KERNEL_PT_KERNEL_NUM; loop++) + pmap_link_l2pt(l1pagetable, KERNEL_BASE + loop * 0x00400000, + &kernel_pt_table[KERNEL_PT_KERNEL + loop]); + + for (loop = 0; loop < KERNEL_PT_VMDATA_NUM; loop++) + pmap_link_l2pt(l1pagetable, KERNEL_VM_BASE + loop * 0x00400000, + &kernel_pt_table[KERNEL_PT_VMDATA + loop]); + + /* update the top of the kernel VM */ + pmap_curmaxkvaddr = + KERNEL_VM_BASE + (KERNEL_PT_VMDATA_NUM * 0x00400000); + +#ifdef VERBOSE_INIT_ARM + printf("Mapping kernel\n"); +#endif + + /* Now we fill in the L2 pagetable for the kernel static code/data */ + { + size_t textsize = (uintptr_t) etext - KERNEL_TEXT_BASE; + size_t totalsize = (uintptr_t) _end - KERNEL_TEXT_BASE; + u_int logical; + +#if NKSYMS || defined(DDB) || defined(MODULAR) + if (!memcmp(&_end, "\177ELF", 4)) { + Elf_Shdr *sh = (Elf_Shdr *) + ((char *)&_end + ((Elf_Ehdr *)&_end)->e_shoff); + + loop = ((Elf_Ehdr *)&_end)->e_shnum; + for (; loop; loop--, sh++) + if (sh->sh_offset > 0 && + (sh->sh_offset + sh->sh_size) > symbolsize) + symbolsize = sh->sh_offset + sh->sh_size; + } + + totalsize += symbolsize; +#endif + + textsize = (textsize + PGOFSET) & ~PGOFSET; + totalsize = (totalsize + PGOFSET) & ~PGOFSET; + + logical = 0x00200000; /* offset of kernel in RAM */ + + logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, + physical_start + logical, textsize, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + logical += pmap_map_chunk(l1pagetable, KERNEL_BASE + logical, + physical_start + logical, totalsize - textsize, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + } + +#ifdef VERBOSE_INIT_ARM + printf("Constructing L2 page tables\n"); +#endif + + /* Map the stack pages */ + pmap_map_chunk(l1pagetable, irqstack.pv_va, irqstack.pv_pa, + IRQ_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1pagetable, abtstack.pv_va, abtstack.pv_pa, + ABT_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1pagetable, undstack.pv_va, undstack.pv_pa, + UND_STACK_SIZE * PAGE_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + pmap_map_chunk(l1pagetable, kernelstack.pv_va, kernelstack.pv_pa, + UPAGES * PAGE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_CACHE); + + pmap_map_chunk(l1pagetable, kernel_l1pt.pv_va, kernel_l1pt.pv_pa, + L1_TABLE_SIZE, VM_PROT_READ | VM_PROT_WRITE, PTE_PAGETABLE); + + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + pmap_map_chunk(l1pagetable, kernel_pt_table[loop].pv_va, + kernel_pt_table[loop].pv_pa, L2_TABLE_SIZE, + VM_PROT_READ|VM_PROT_WRITE, PTE_PAGETABLE); + } + + /* Map the vector page. */ + pmap_map_entry(l1pagetable, vector_page, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + printf("vector_page: v0x%08lx\n", vector_page); + + /* + * map integrated peripherals at same address in l1pagetable + * so that we can continue to use console. + */ + pmap_devmap_bootstrap(l1pagetable, ipaq3900_devmap); + + /* Map the Mini-Data cache clean area. */ + xscale_setup_minidata(l1pagetable, minidataclean.pv_va, + minidataclean.pv_pa); + + /* + * Give the XScale global cache clean code an appropriately + * sized chunk of unmapped VA space starting at 0xff000000 + * (our device mappings end before this address). + */ + xscale_cache_clean_addr = 0xff000000U; + + /* + * Now we have the real page tables in place so we can switch to them. + * Once this is done we will be running with the REAL kernel page + * tables. + */ + + /* + * Update the physical_freestart/physical_freeend/free_pages + * variables. Make sure to account for symbol table if we + * need to. + */ + { +#ifdef BOOT_DUMP + /* physical_freend points to next free page, save off last-used */ + setup_pages_start = KERNEL_BASE + physical_freeend - physical_start + PAGE_SIZE; +#endif + physical_freestart = physical_start + + (((((uintptr_t) _end + symbolsize) + PGOFSET) & ~PGOFSET) - + KERNEL_BASE); + physical_freeend = physical_end; + free_pages = + (physical_freeend - physical_freestart) / PAGE_SIZE; + } + + /* Switch tables */ +#ifdef VERBOSE_INIT_ARM + printf("freestart = 0x%08lx, free_pages = %d (0x%x)\n", + physical_freestart, free_pages, free_pages); + printf("switching to new L1 page table @%#lx...", kernel_l1pt.pv_pa); +#endif + + LEDSTEP(); + + cpu_domains((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT); + setttb(kernel_l1pt.pv_pa); + cpu_tlb_flushID(); + cpu_domains(DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)); + LEDSTEP(); + + /* + * Moved from cpu_startup() as data_abort_handler() references + * this during uvm init + */ + proc0paddr = (struct user *)kernelstack.pv_va; + lwp0.l_addr = proc0paddr; + +#ifdef VERBOSE_INIT_ARM + printf("bootstrap done.\n"); +#endif + + /* + * Enable I-cache, D-cache, BTB. Set SYSTEM protection, turn + * off ROM protection to avoid UNDEFINED access modes (if we + * turn both off, OTOH, we'll get DENIED access, so we need to + * make sure both of them have the right value). + * + * NB: Be careful this doesn't mess with the CPU_CONTROL_VECRELOC + * bit if you call arm32_vector_init() before this! + * + * Also, not sure that it matters, but force all the bits the PXA + * docs claim should always be written as ones to ones. + */ + cpu_control(0xffffdf7c, 0x0000197c); + LEDSTEP(); + + arm32_vector_init(vector_page, ARM_VEC_ALL); + LEDSTEP(); + + /* + * Pages were allocated during the secondary bootstrap for the + * stacks for different CPU modes. + * We must now set the r13 registers in the different CPU modes to + * point to these stacks. + * Since the ARM stacks use STMFD etc. we must set r13 to the top end + * of the stack memory. + */ + printf("init subsystems: stacks "); + + set_stackptr(PSR_IRQ32_MODE, irqstack.pv_va + IRQ_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_ABT32_MODE, abtstack.pv_va + ABT_STACK_SIZE * PAGE_SIZE); + set_stackptr(PSR_UND32_MODE, undstack.pv_va + UND_STACK_SIZE * PAGE_SIZE); + + /* + * Well we should set a data abort handler. + * Once things get going this will change as we will need a proper + * handler. + * Until then we will use a handler that just panics but tells us + * why. + * Initialisation of the vectors will just panic on a data abort. + * This just fills in a slightly better one. + */ + printf("vectors "); + data_abort_handler_address = (u_int)data_abort_handler; + prefetch_abort_handler_address = (u_int)prefetch_abort_handler; + undefined_handler_address = (u_int)undefinedinstruction_bounce; + + /* Initialise the undefined instruction handlers */ + printf("undefined "); + undefined_init(); + + /* Load memory into UVM. */ + printf("page "); + uvm_setpagesize(); /* initialize PAGE_SIZE-dependent variables */ + uvm_page_physload(atop(physical_freestart), atop(physical_freeend), + atop(physical_freestart), atop(physical_freeend), + VM_FREELIST_DEFAULT); + + /* Boot strap pmap telling it where the kernel page table is */ + printf("pmap "); + LEDSTEP(); + pmap_bootstrap(KERNEL_VM_BASE, KERNEL_VM_BASE + KERNEL_VM_SIZE); + LEDSTEP(); + +#ifdef __HAVE_MEMORY_DISK__ + md_root_setconf(memory_disk, sizeof memory_disk); +#endif + + LEDSTEP(); + +#ifdef KGDB + if (boothowto & RB_KDB) { + kgdb_debug_init = 1; + kgdb_connect(1); + } +#endif + +#ifdef DDB + db_machine_init(); +#endif +#if NKSYMS || defined(DDB) || defined(MODULAR) + if (symbolsize != 0) { + printf("Loading 0x%zx bytes of symbols...\n", symbolsize); + ksyms_addsyms_elf(symbolsize, ((int *)&_end), ((char *)&_end) + symbolsize); + } +#endif + +#ifdef DDB + if (boothowto & RB_KDB) + Debugger(); +#endif /* DDB */ + + /* Turn off BLUE & GREEN LED's, turn on YELLOW for now */ + ioreg8_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_BLUE + LED_TIMEBASE_REG, 0); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_BLUE + LED_PERIOD_REG, 0); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_BLUE + LED_DUTYTIME_REG, 0); + + ioreg8_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_GREEN + LED_TIMEBASE_REG, 0); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_GREEN + LED_PERIOD_REG, 0); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_GREEN + LED_DUTYTIME_REG, 0); + + ioreg8_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_YELLOW + LED_TIMEBASE_REG, 0x70); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_YELLOW + LED_PERIOD_REG, 4); + ioreg16_write(IPAQ3900_ASIC2_VBASE + ASIC_LED_BASE + + ASIC_LED_YELLOW + LED_DUTYTIME_REG, 4); + + /* We return the new stack pointer address */ + return(kernelstack.pv_va + USPACE_SVC_STACK_TOP); +} + +#ifdef KGDB +#ifndef KGDB_DEVNAME +#define KGDB_DEVNAME "ffuart" +#endif +const char kgdb_devname[] = KGDB_DEVNAME; + +#if (NCOM > 0) +#ifndef KGDB_DEVMODE +#define KGDB_DEVMODE ((TTYDEF_CFLAG & ~(CSIZE | CSTOPB | PARENB)) | CS8) /* 8N1 */ +#endif +int comkgdbmode = KGDB_DEVMODE; +#endif /* NCOM */ + +#endif /* KGDB */ + + +void +consinit(void) +{ + static int consinit_called = 0; + + if (consinit_called != 0) + return; + + consinit_called = 1; + + /* + * Nothing to do here. Console initialization is done at + * autoconf device attach time. + */ + if ((bootinfo->bi_cnuse & BI_CNUSE_SERIAL) == 0) + return; + +#if NCOM > 0 + +#ifdef FFUARTCONSOLE +#ifdef KGDB + if (0 == strcmp(kgdb_devname, "ffuart")) { + /* port is reserved for kgdb */ + } else +#endif + if (0 == comcnattach(&pxa2x0_a4x_bs_tag, PXA2X0_FFUART_BASE, + comcnspeed, PXA2X0_COM_FREQ, COM_TYPE_PXA2x0, comcnmode)) { +#if 0 + /* XXX: can't call pxa2x0_clkman_config yet */ + pxa2x0_clkman_config(CKEN_FFUART, 1); +#else + uint32_t ckenreg = ioreg_read(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN); + + ioreg_write(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN, + ckenreg|CKEN_FFUART); +#endif + + return; + } +#endif /* FFUARTCONSOLE */ + +#ifdef BTUARTCONSOLE +#ifdef KGDB + if (0 == strcmp(kgdb_devname, "btuart")) { + /* port is reserved for kgdb */ + } else +#endif + if (0 == comcnattach(&pxa2x0_a4x_bs_tag, PXA2X0_BTUART_BASE, + comcnspeed, PXA2X0_COM_FREQ, COM_TYPE_PXA2x0, comcnmode)) { + uint32_t ckenreg = ioreg_read(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN); + + ioreg_write(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN, + ckenreg|CKEN_BTUART); + return; + } +#endif /* BTUARTCONSOLE */ + + +#endif /* NCOM */ + +} + +#ifdef KGDB +void +kgdb_port_init(void) +{ +#if (NCOM > 0) && defined(COM_PXA2X0) + paddr_t paddr = 0; + uint32_t ckenreg = ioreg_read(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN); + + if (0 == strcmp(kgdb_devname, "ffuart")) { + paddr = PXA2X0_FFUART_BASE; + ckenreg |= CKEN_FFUART; + } + else if (0 == strcmp(kgdb_devname, "btuart")) { + paddr = PXA2X0_BTUART_BASE; + ckenreg |= CKEN_BTUART; + } + + if (paddr && + 0 == com_kgdb_attach(&pxa2x0_a4x_bs_tag, paddr, + kgdb_rate, PXA2X0_COM_FREQ, COM_TYPE_PXA2x0, comkgdbmode)) { + + ioreg_write(IPAQ3900_CLKMAN_VBASE+CLKMAN_CKEN, ckenreg); + } +#endif +} +#endif + +#ifdef BOOT_DUMP +void +dumppages(char *start, int nbytes) +{ + char *p = start; + char *p1; + int i; + + for (i = nbytes; i > 0; i -= 16, p += 16) { + for (p1 = p + 15; p != p1; p1--) { + if (*p1) + break; + } + if (!*p1) + continue; + printf("%08x %02x %02x %02x %02x %02x %02x %02x %02x" + " %02x %02x %02x %02x %02x %02x %02x %02x\n", + (unsigned int)p, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], + p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + } +} +#endif + +#ifdef MODULAR +/* + * Push any modules loaded by the boot loader. + */ +void +module_init_md(void) +{ +} +#endif /* MODULAR */ diff --git a/sys/arch/evbarm/ipaq3900/ipaq3900_pcic.c b/sys/arch/evbarm/ipaq3900/ipaq3900_pcic.c new file mode 100644 index 0000000..f042c51 --- /dev/null +++ b/sys/arch/evbarm/ipaq3900/ipaq3900_pcic.c @@ -0,0 +1,314 @@ +/* $NetBSD: ipaq3900_pcic.c,v 1.7 2007/12/15 00:39:15 perry Exp $ */ +/* + * Copyright (C) 2005, 2006 WIDE Project and SOUM Corporation. + * All rights reserved. + * + * Written by Takashi Kiyohara and Susumu Miki for WIDE Project and SOUM + * Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the name of SOUM Corporation + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE PROJECT and SOUM CORPORATION ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT AND SOUM CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +/* + * Copyright (c) 2002, 2003, 2005 Genetec corp. All rights reserved. + * + * PCMCIA/CF support for TWINTAIL (G4255EB) + * Written by Hiroyuki Bessho for Genetec corp. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec corp. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORP. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORP. + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Debug code to dump out MC PCMCIA timing registers if they change value */ +#define REPORT_SETUP_TIMINGS + +#ifdef DEBUG +#define DPRINTF(arg) printf arg +#else +#define DPRINTF(arg) +#endif + +#define HAVE_CARD(r) (!((r) & GPIO_SET)) + +#define IPAQ3900_PCMCIA_CD0 3 +#define IPAQ3900_PCMCIA_IRQ0 7 +#define IPAQ3900_PCMCIA_CD1 12 +#define IPAQ3900_PCMCIA_IRQ1 13 + +static int ipaq3900_pcic_match(struct device *, struct cfdata *, void *); +static void ipaq3900_pcic_attach(struct device *, struct device *, void *); +static void ipaq3900_pcic_pcic_socket_setup(struct pxapcic_socket *); + +static u_int ipaq3900_pcic_read(struct pxapcic_socket *, int); +static void ipaq3900_pcic_write(struct pxapcic_socket *, int, u_int); +static void ipaq3900_pcic_set_power(struct pxapcic_socket *, int); +static void ipaq3900_pcic_clear_intr(struct pxapcic_socket *); +static void *ipaq3900_pcic_intr_establish(struct pxapcic_socket *, int, + int (*)(void *), void *); +static void ipaq3900_pcic_intr_disestablish(struct pxapcic_socket *, void *); + +CFATTACH_DECL(pxapcic_ipaq3900_pcic, sizeof(struct pxapcic_softc), + ipaq3900_pcic_match, ipaq3900_pcic_attach, NULL, NULL); + +static struct pxapcic_tag ipaq3900_pcic_pcic_functions = { + ipaq3900_pcic_read, + ipaq3900_pcic_write, + ipaq3900_pcic_set_power, + ipaq3900_pcic_clear_intr, + ipaq3900_pcic_intr_establish, + ipaq3900_pcic_intr_disestablish, +}; + +static struct { + int cd; + int prdy; +} ipaq3900_pcic_slot_irqs[] = { + { IPAQ3900_PCMCIA_CD0, IPAQ3900_PCMCIA_IRQ0 }, + { IPAQ3900_PCMCIA_CD1, IPAQ3900_PCMCIA_IRQ1 } +}; + + +static int +ipaq3900_pcic_match(struct device *parent, struct cfdata *cf, void *aux) +{ + struct pxa2x0_gpioconf *gpioconf; + u_int reg; + int i; + + /* + * Check GPIO configuration. If you use these, it is sure already + * to have been set by gxio. + */ + gpioconf = CPU_IS_PXA250 ? pxa25x_pcic_gpioconf : + pxa27x_pcic_gpioconf; + for (i = 0; gpioconf[i].pin != -1; i++) { + reg = pxa2x0_gpio_get_function(gpioconf[i].pin); + if (GPIO_FN(reg) != GPIO_FN(gpioconf[i].value) || + GPIO_FN_IS_OUT(reg) != GPIO_FN_IS_OUT(gpioconf[i].value)) + return (0); + } + + return 1; /* match */ +} + +static void +ipaq3900_pcic_attach(struct device *parent, struct device *self, void *aux) +{ + struct pxapcic_softc *sc = (struct pxapcic_softc *)self; + struct pxaip_attach_args *pxa = (struct pxaip_attach_args *)aux; + int nslot, i; + + sc->sc_iot = pxa->pxa_iot; + + nslot = 1; /* XXXrkb: how do we find this out? */ + + for (i = 0; i < nslot; i++) { + sc->sc_irqpin[i] = ipaq3900_pcic_slot_irqs[i].prdy; + sc->sc_irqcfpin[i] = ipaq3900_pcic_slot_irqs[i].cd; + } + sc->sc_nslots = nslot; + + pxapcic_attach_common(sc, &ipaq3900_pcic_pcic_socket_setup); +} + +static void +ipaq3900_pcic_pcic_socket_setup(struct pxapcic_socket *so) +{ +#ifdef REPORT_SETUP_TIMINGS + uint32_t omcmem, omcatt, omcio; + uint32_t nmcmem, nmcatt, nmcio; +#endif + struct pxapcic_softc *sc = so->sc; + + /* 3.3V only? */ + so->power_capability = PXAPCIC_POWER_3V; + so->pcictag_cookie = NULL; + so->pcictag = &ipaq3900_pcic_pcic_functions; + + +#ifdef REPORT_SETUP_TIMINGS + omcmem = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCMEM(so->socket)); + omcatt = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCATT(so->socket)); + omcio = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCIO(so->socket)); +#endif + + /* + * These settings are based on residual settings left over by + * WinCE. NB: These are dependent on CPU/memory clock, so will + * need to be adjusted if/when we get proper CPU clock control + * implemented. + * + * The odd thing here is I expected timings for attribute and + * common memory to be the same, and I/O to be different, but + * the outlier is common memory instead (I/O and attribute + * memory are the same). + */ + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCMEM(so->socket), MC_TIMING_VAL(7, 8, 22)); + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCATT(so->socket), MC_TIMING_VAL(11, 14, 33)); + bus_space_write_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCIO(so->socket), MC_TIMING_VAL(11, 14, 33)); + +#ifdef REPORT_SETUP_TIMINGS + nmcmem = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCMEM(so->socket)); + nmcatt = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCATT(so->socket)); + nmcio = bus_space_read_4(sc->sc_iot, sc->sc_memctl_ioh, + MEMCTL_MCIO(so->socket)); + + if (omcmem != nmcmem) + printf("socket_setup: socket %d: mcmem changed from 0x%x -> 0x%x\n", so->socket, omcmem, nmcmem); + if (omcatt != nmcatt) + printf("socket_setup: socket %d: mcatt changed from 0x%x -> 0x%x\n", so->socket, omcatt, nmcatt); + if (omcio != nmcio) + printf("socket_setup: socket %d: mcio changed from 0x%x -> 0x%x\n", so->socket, omcio, nmcio); +#endif +} + +static u_int +ipaq3900_pcic_read(struct pxapcic_socket *so, int which) +{ + int reg; + + switch (which) { + case PXAPCIC_CARD_STATUS: + reg = pxa2x0_gpio_get_function(ipaq3900_pcic_slot_irqs[so->socket].cd); + return (HAVE_CARD(reg) ? + PXAPCIC_CARD_VALID : PXAPCIC_CARD_INVALID); + + case PXAPCIC_CARD_READY: + /* XXXrkb: steal VS1, VS2 from the iPAQ 3600 implementation? */ + reg = pxa2x0_gpio_get_function( + ipaq3900_pcic_slot_irqs[so->socket].prdy); + return (reg & GPIO_SET ? 1 : 0); + + default: + panic("%s: bogus register", __func__); + } + /* NOTREACHED */ +} + +/* ARGSUSED */ +static void +ipaq3900_pcic_write(struct pxapcic_socket *so, int which, u_int arg) +{ + + /* XXXrkb: steal from the iPAQ 3600 implementation */ + switch (which) { + case PXAPCIC_CARD_POWER: + case PXAPCIC_CARD_RESET: + /* We can't */ + break; + + default: + panic("%s: bogus register", __func__); + } + /* NOTREACHED */ +} + +static void +ipaq3900_pcic_set_power(struct pxapcic_socket *__so, int arg) +{ + + /* XXXrkb: steal from the iPAQ 3600 implementation? */ + if(arg != PXAPCIC_POWER_OFF && arg != PXAPCIC_POWER_3V) + panic("%s: bogus arg\n", __func__); + + /* 3.3V only? */ +} + +/* ARGSUSED */ +static void +ipaq3900_pcic_clear_intr(struct pxapcic_socket *so) +{ + + /* nothing to do */ +} + +static void * +ipaq3900_pcic_intr_establish(struct pxapcic_socket *so, int level, + int (* ih_fun)(void *), void *ih_arg) +{ + + return pxa2x0_gpio_intr_establish(so->irqpin, IST_EDGE_FALLING, + level, ih_fun, ih_arg); +} + +/* ARGSUSED */ +static void +ipaq3900_pcic_intr_disestablish(struct pxapcic_socket *so, void *ih) +{ + + pxa2x0_gpio_intr_disestablish(ih); +} + diff --git a/sys/arch/evbarm/ipaq3900/ipaq3900_reg.h b/sys/arch/evbarm/ipaq3900/ipaq3900_reg.h new file mode 100644 index 0000000..14b7eef --- /dev/null +++ b/sys/arch/evbarm/ipaq3900/ipaq3900_reg.h @@ -0,0 +1,74 @@ +/* $NetBSD: ipaq3900_reg.h,v 1.4 2005/12/11 12:17:09 christos Exp $ */ + +/* + * Copyright (c) 2002, 2003, 2005 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef _EVBARM_IPAQ3900_REG_H +#define _EVBARM_IPAQ3900_REG_H + +#include + +/* + * Logical mapping for onboard/integrated peripherals + */ +#define IPAQ3900_IO_AREA_VBASE 0xfd000000 + +/* Nothing yet -- OBIO? 0xfd000000 */ +#define IPAQ3900_GPIO_VBASE 0xfd100000 +#define IPAQ3900_CLKMAN_VBASE 0xfd200000 +#define IPAQ3900_INTCTL_VBASE 0xfd300000 +#define IPAQ3900_FFUART_VBASE 0xfd400000 +#define IPAQ3900_BTUART_VBASE 0xfd500000 +#define IPAQ3900_STUART_VBASE 0xfd600000 +#define IPAQ3900_ASIC2_VBASE 0xfd700000 +#define IPAQ3900_ASIC3_VBASE 0xfd800000 +#define IPAQ3900_ASIC3_SD_VBASE 0xfd900000 + +#define ASIC_LED_BASE 0x00000800 + +#define ASIC_LED_BLUE 0x00000000 +#define ASIC_LED_GREEN 0x00000080 +#define ASIC_LED_YELLOW 0x00000100 + +#define LED_TIMEBASE_REG 0x00 +#define LED_PERIOD_REG 0x04 +#define LED_DUTYTIME_REG 0x08 +#define LED_AUTOSTOP_REG 0x0c + +#define ioreg_read(a) (*(volatile unsigned *)(a)) +#define ioreg_write(a,v) (*(volatile unsigned *)(a)=(v)) + +#define ioreg16_read(a) (*(volatile uint16_t *)(a)) +#define ioreg16_write(a,v) (*(volatile uint16_t *)(a)=(v)) + +#define ioreg8_read(a) (*(volatile uint8_t *)(a)) +#define ioreg8_write(a,v) (*(volatile uint8_t *)(a)=(v)) + +#endif /* _EVBARM_IPAQ3900_REG_H */ diff --git a/sys/arch/evbarm/ipaq3900/ipaq3900_start.S b/sys/arch/evbarm/ipaq3900/ipaq3900_start.S new file mode 100644 index 0000000..b544626 --- /dev/null +++ b/sys/arch/evbarm/ipaq3900/ipaq3900_start.S @@ -0,0 +1,174 @@ +/* $NetBSD: ipaq3900_start.S,v 1.1 2003/06/18 10:51:15 bsh Exp $ */ + +/* + * Copyright (c) 2002, 2003 Genetec Corporation. All rights reserved. + * Written by Hiroyuki Bessho for Genetec Corporation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of Genetec Corporation may not be used to endorse or + * promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY GENETEC CORPORATION ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GENETEC CORPORATION + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include /* for PMAP_DOMAIN_KERNEL */ + +#ifndef SDRAM_START +#define SDRAM_START 0xa0000000 +#endif + +/* + * CPWAIT -- Canonical method to wait for CP15 update. + * NOTE: Clobbers the specified temp reg. + * copied from arm/arm/cpufunc_asm_xscale.S + * XXX: better be in a common header file. + */ +#define CPWAIT(tmp) \ + mrc p15, 0, tmp, c2, c0, 0 /* arbitrary read of CP15 */ ;\ + mov tmp, tmp /* wait for it to complete */ ;\ + sub pc, pc, #4 /* branch to next insn */ + +/* + * Kernel start routine for PXA-2x0-based iPAQ 39x0/54xx/... + * + * MMU is disabled when we enter here; note that we need to save + * the args passed by hpcboot.exe (argc, argv, bootinfo*) some- + * where since the generic arm32 start code only passes r0 through + * to initarm(). + */ + .text + + .global _C_LABEL(ipaq3900_start) +_C_LABEL(ipaq3900_start): + /* Put the processor in SVC32 mode, disable IRQs and FIQs */ + mov r5, sp + mrs r4, cpsr_all + bic r4, r4, #31 + orr r4, r4, #(I32_bit | F32_bit | PSR_SVC32_MODE) + msr cpsr_all, r4 + mov sp, r5 + + /* Disable PID virtual address mapping */ + mov r4, #0 + mcr 15, 0, r4, c13, c0, 0 + CPWAIT(r4) + + /* + * Save args passed to us by hpcboot.exe and pass in the pointer + * to the arg save area instead (in r0). + */ + adr r4, Lhpcboot_args + stmia r4, {r0,r1,r2} /* argc, argc, bootinfo ptr */ + mov r0, r4 + + /* + * Kernel is loaded in SDRAM (0xa0200000..), and is expected to run + * in VA 0xc0200000; the CPU is currently running with MMU off. To + * make transition easier map the whole address space VA == PA first, + * then create a (second) mapping for SDRAM at 0xc0000000. Finally, + * map on-board devices we might need while booting. + */ + ldr r4, Lstartup_pagetable + adr r5, mmu_init_table + b 2f + +1: + str r8, [r4, r7] + add r7, r7, #4 + add r8, r8, #(L1_S_SIZE) + adds r6, r6, #-1 + bhi 1b +2: + ldmia r5!, {r6,r7,r8} /* # of sections, PA|attr, VA */ + cmp r6, #0 + bne 1b + + /* Now set up the TTB, flush TLB */ + mcr p15, 0, r4, c2, c0, 0 /* Set TTB */ + mcr p15, 0, r4, c8, c7, 0 /* Flush TLB */ + + /* Set the Domain Access register. Very important! */ + mov r4, #((DOMAIN_CLIENT << (PMAP_DOMAIN_KERNEL*2)) | DOMAIN_CLIENT) + mcr p15, 0, r4, c3, c0, 0 + + /* Enable the MMU, wait for it to complete */ + mrc p15, 0, r4, c1, c0, 0 + orr r4, r4, #CPU_CONTROL_MMU_ENABLE + mcr p15, 0, r4, c1, c0, 0 + CPWAIT(r4) + + /* Jump to kernel code in TRUE VA */ + adr r4, Lstart + ldr pc, [r4] + +Lhpcboot_args: + .word 0 /* r0 == argc */ + .word 0 /* r1 == argv */ + .word 0 /* r2 == bootinfo ptr */ + +Lstart: + .word start + +#ifndef STARTUP_PAGETABLE_ADDR +#define STARTUP_PAGETABLE_ADDR 0xa0004000 +#endif +Lstartup_pagetable: + .word STARTUP_PAGETABLE_ADDR + +#define MMU_INIT(va,pa,n_sec,attr) \ + .word n_sec ; \ + .word 4*((va)>>L1_S_SHIFT) ; \ + .word (pa)|(attr) ; + +mmu_init_table: + /* fill all table VA==PA */ + MMU_INIT(0x00000000, 0x00000000, 1<<(32-L1_S_SHIFT), L1_TYPE_S|L1_S_AP(AP_KRW)) + /* map SDRAM VA==PA, WT cacheable */ + MMU_INIT(SDRAM_START, SDRAM_START, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + + /* map SDRAM at 0xc0000000, WT cachable */ + MMU_INIT(0xc0000000, SDRAM_START, 64, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + + /* Map I/O regions */ + /* map 1M VA @ 0xfd100000 to 1M PA @ 0x40e00000 (GPIO_BASE) */ + MMU_INIT(0xfd100000, 0x40e00000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd200000 to 1M PA @ 0x41300000 (CLKMAN_BASE) */ + MMU_INIT(0xfd200000, 0x41300000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd300000 to 1M PA @ 0x40d00000 (INTCTL_BASE) */ + MMU_INIT(0xfd300000, 0x40d00000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd400000 to 1M PA @ 0x40100000 (FFUART_BASE) */ + MMU_INIT(0xfd400000, 0x40100000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd500000 to 1M PA @ 0x40200000 (BTUART_BASE) */ + MMU_INIT(0xfd500000, 0x40200000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd600000 to 1M PA @ 0x40700000 (STUART_BASE) */ + MMU_INIT(0xfd600000, 0x40700000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd700000 to 1M PA @ 0x15000000 (ASIC2_BASE) */ + MMU_INIT(0xfd700000, 0x15000000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd800000 to 1M PA @ 0x14800000 (ASIC3_BASE) */ + MMU_INIT(0xfd800000, 0x14800000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + /* map 1M VA @ 0xfd900000 to 1M PA @ 0x14000000 (ASIC3_SD_BASE) */ + MMU_INIT(0xfd900000, 0x14000000, 1, L1_TYPE_S|L1_S_C|L1_S_AP(AP_KRW)) + + .word 0 /* end of table */ + diff --git a/sys/arch/evbarm/stand/board/ipaq3.c b/sys/arch/evbarm/stand/board/ipaq3.c new file mode 100644 index 0000000..7b53792 --- /dev/null +++ b/sys/arch/evbarm/stand/board/ipaq3.c @@ -0,0 +1,59 @@ +/* $NetBSD: iq80321.c,v 1.1 2002/04/17 17:37:52 thorpej Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Board initialization routines for the HP IPAQ3900. + */ + +#include +#include + +#include "board.h" + +void +board_init(void) +{ + + mem_init(); +} + +void +board_fini(void) +{ + + /* Nothing to do here. */ +} diff --git a/sys/arch/evbarm/stand/board/pxa25x_com.c b/sys/arch/evbarm/stand/board/pxa25x_com.c new file mode 100644 index 0000000..bb3b507 --- /dev/null +++ b/sys/arch/evbarm/stand/board/pxa25x_com.c @@ -0,0 +1,136 @@ +/* $NetBSD: ns16550.c,v 1.3 2005/12/24 20:07:03 perry Exp $ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides the cons_init() function and console I/O routines + * for boards that use 16550-compatible UARTs. + */ + +#include +#include +#include + +#include "board.h" + +#define INB(x) *((volatile uint8_t *) (CONADDR + (4 * x))) +#define INW(x) *((volatile uint32_t *) (CONADDR + (4 * x))) +#define OUTB(x, v) *((volatile uint8_t *) (CONADDR + (4 * x))) = (v) +#define OUTW(x, v) *((volatile uint32_t *) (CONADDR + (4 * x))) = (v) + +#define ISSET(t,f) ((t) & (f)) + +#ifndef NS16550_FREQ +#define NS16550_FREQ COM_FREQ +#endif + +static int +comspeed(int speed) +{ +#define divrnd(n, q) (((n)*2/(q)+1)/2) /* divide and round off */ + + int x, err; + + if (speed <= 0) + return (-1); + x = divrnd((NS16550_FREQ / 16), speed); + if (x <= 0) + return (-1); + err = divrnd((((quad_t)NS16550_FREQ) / 16) * 1000, speed * x) - 1000; + if (err < 0) + err = -err; + if (err > COM_TOLERANCE) + return (-1); + return (x); +#undef divrnd +} + +void +cons_init(void) +{ + int rate; + + OUTW(com_cfcr, LCR_DLAB); + rate = comspeed(CONSPEED); + OUTW(com_dlbl, rate); + OUTW(com_dlbh, rate >> 8); + OUTW(com_cfcr, LCR_8BITS); + OUTW(com_mcr, MCR_DTR | MCR_RTS); + OUTW(com_fifo, + FIFO_ENABLE | FIFO_RCV_RST | FIFO_XMT_RST | FIFO_TRIGGER_1); + OUTW(com_ier, 0); +} + +int +getchar(void) +{ + uint8_t stat; + + while (!ISSET(stat = INB(com_lsr), LSR_RXRDY)) + /* spin */ ; + return (INB(com_data)); +} + +static void +iputchar(int c) +{ + uint8_t stat; + int timo; + + /* Wait for any pending transmission to finish. */ + timo = 50000; + while (!ISSET(stat = INB(com_lsr), LSR_TXRDY) && --timo) + /* spin */ ; + + OUTB(com_data, c); + + /* Wait for this transmission to complete. */ + timo = 1500000; + while (!ISSET(stat = INB(com_lsr), LSR_TXRDY) && --timo) + /* spin */ ; + + /* Clear any interrupts generated by this transmission. */ + (void) INB(com_iir); +} + +void +putchar(int c) +{ + + if (c == '\n') + iputchar('\r'); + iputchar(c); +} diff --git a/sys/arch/evbarm/stand/board/pxa25x_mem.c b/sys/arch/evbarm/stand/board/pxa25x_mem.c new file mode 100644 index 0000000..0ad29e0 --- /dev/null +++ b/sys/arch/evbarm/stand/board/pxa25x_mem.c @@ -0,0 +1,62 @@ +/* $NetBSD$ */ + +/* + * Copyright (c) 2002 Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Jason R. Thorpe for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file provides the mem_init() function for boards using the + * HP IPAQ3900 handheld. + */ + +#include +#include + +#include "board.h" + +void +mem_init(void) +{ + uint32_t start, size, heap; + + start = 0xa0000000; + + /* HP CRL bootloader loads at top of RAM */ + size = (64 * 1024 * 1024) - (1024 * 1024); + heap = (start + size) - BOARD_HEAP_SIZE; + + printf(">> RAM 0x%x - 0x%x, heap at 0x%x\n", + start, (start + size) - 1, heap); + setheap((void *)heap, (void *)(start + size - 1)); +} diff --git a/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/Makefile b/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/Makefile new file mode 100644 index 0000000..f0c8bdb --- /dev/null +++ b/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/Makefile @@ -0,0 +1,18 @@ +# $NetBSD: Makefile,v 1.2 2003/04/29 05:36:20 thorpej Exp $ + +S= ${.CURDIR}/../../../../.. + +PLATFORM= IPAQ3 +RELOC= 0 +MAXIMAGESIZE= 0 # concatenate +LOADADDR= 0xa0200000 + +CPPFLAGS+= -DNORELOC +CPPFLAGS+= -DCONSPEED=115200 +CPPFLAGS+= -DCONADDR=0x40100000UL + +LDSCRIPT= ${.CURDIR}/ldscript + +SRCS+= ipaq3.c pxa25x_com.c pxa25x_mem.c + +.include "${S}/arch/evbarm/stand/gzboot/Makefile.gzboot" diff --git a/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/ldscript b/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/ldscript new file mode 100644 index 0000000..189d17c --- /dev/null +++ b/sys/arch/evbarm/stand/gzboot/IPAQ3_ram_noreloc/ldscript @@ -0,0 +1,81 @@ +/* $NetBSD: ldscript,v 1.4 2005/12/11 12:17:10 christos Exp $ */ + +OUTPUT_ARCH(arm) +ENTRY(FLASH) +MEMORY +{ + /* We will locate the .text section in flash, and will run directly + from there just long enough to relocate our .text and .data into + a small chunk of SDRAM starting at (SDRAM + 1M). */ + flash : o = 0x00000000, l = 2M /* XXXrkb: lie about flash size */ + sdram : o = 0xa0100000, l = 1M /* kernel loads at 0xc0200000 */ +} +SECTIONS +{ + FLASH = 0x00000000; + + /* Read-only sections, merged into text segment: */ + __text_store = FLASH; + .text : + AT (FLASH) + { + *(.text) + *(.text.*) + *(.stub) + *(.glue_7t) *(.glue_7) + *(.rodata) *(.rodata.*) + } > sdram =0 + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + __data_store = FLASH + SIZEOF(.text); + .data : + AT (LOADADDR(.text) + SIZEOF(.text)) + { + __data_start = . ; + *(.data) + *(.data.*) + } > sdram + .sdata : + AT (LOADADDR(.data) + SIZEOF(.data)) + { + *(.sdata) + *(.sdata.*) + . = ALIGN(32 / 8); + } > sdram + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + __bss_start__ = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } > sdram + .bss : + { + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } > sdram + . = ALIGN(32 / 8); + _end = .; + _bss_end__ = . ; __bss_end__ = . ; __end__ = . ; + PROVIDE (end = .); + .image (FLASH + SIZEOF(.text) + SIZEOF(.data) + SIZEOF(.sdata)) : + AT (LOADADDR(.sdata) + SIZEOF(.sdata)) + { + *(.image) + } +} diff --git a/sys/arch/hpc/stand/include/sys/cdefs.h b/sys/arch/hpc/stand/include/sys/cdefs.h new file mode 100644 index 0000000..49a23bc --- /dev/null +++ b/sys/arch/hpc/stand/include/sys/cdefs.h @@ -0,0 +1,399 @@ +/* $NetBSD$ */ +/* @NetBSD: cdefs.h,v 1.66 2007/11/26 14:52:34 joerg Exp @ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Berkeley Software Design, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 + */ + +#ifndef _SYS_CDEFS_H_ +#define _SYS_CDEFS_H_ + +/* + * Macro to test if we're using a GNU C compiler of a specific vintage + * or later, for e.g. features that appeared in a particular version + * of GNU C. Usage: + * + * #if __GNUC_PREREQ__(major, minor) + * ...cool feature... + * #else + * ...delete feature... + * #endif + */ +#ifdef __GNUC__ +#define __GNUC_PREREQ__(x, y) \ + ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || \ + (__GNUC__ > (x))) +#else +#define __GNUC_PREREQ__(x, y) 0 +#endif + +#include +#ifdef __ELF__ +#include +#else +#include +#endif + +#if defined(__cplusplus) +#define __BEGIN_DECLS extern "C" { +#define __END_DECLS } +#define __static_cast(x,y) static_cast(y) +#else +#define __BEGIN_DECLS +#define __END_DECLS +#define __static_cast(x,y) (x)y +#endif + +/* + * The __CONCAT macro is used to concatenate parts of symbol names, e.g. + * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. + * The __CONCAT macro is a bit tricky -- make sure you don't put spaces + * in between its arguments. __CONCAT can also concatenate double-quoted + * strings produced by the __STRING macro, but this only works with ANSI C. + */ + +#define ___STRING(x) __STRING(x) +#define ___CONCAT(x,y) __CONCAT(x,y) + +#if __STDC__ || defined(__cplusplus) +#define __P(protos) protos /* full-blown ANSI C */ +#define __CONCAT(x,y) x ## y +#define __STRING(x) #x + +#define __const const /* define reserved names to standard */ +#define __signed signed +#define __volatile volatile +#if defined(__cplusplus) || defined(__PCC__) +#define __inline inline /* convert to C++/C99 keyword */ +#else +#if !defined(__GNUC__) && !defined(__lint__) && !defined(_MSC_VER) +#define __inline /* delete GCC keyword */ +#endif /* !__GNUC__ && !__lint__ */ +#endif /* !__cplusplus */ + +#else /* !(__STDC__ || __cplusplus) */ +#define __P(protos) () /* traditional C preprocessor */ +#define __CONCAT(x,y) x/**/y +#define __STRING(x) "x" + +#ifndef __GNUC__ +#define __const /* delete pseudo-ANSI C keywords */ +#define __inline +#define __signed +#define __volatile +#endif /* !__GNUC__ */ + +/* + * In non-ANSI C environments, new programs will want ANSI-only C keywords + * deleted from the program and old programs will want them left alone. + * Programs using the ANSI C keywords const, inline etc. as normal + * identifiers should define -DNO_ANSI_KEYWORDS. + */ +#ifndef NO_ANSI_KEYWORDS +#define const __const /* convert ANSI C keywords */ +#define inline __inline +#define signed __signed +#define volatile __volatile +#endif /* !NO_ANSI_KEYWORDS */ +#endif /* !(__STDC__ || __cplusplus) */ + +/* + * Used for internal auditing of the NetBSD source tree. + */ +#ifdef __AUDIT__ +#define __aconst __const +#else +#define __aconst +#endif + +/* + * The following macro is used to remove const cast-away warnings + * from gcc -Wcast-qual; it should be used with caution because it + * can hide valid errors; in particular most valid uses are in + * situations where the API requires it, not to cast away string + * constants. We don't use *intptr_t on purpose here and we are + * explicit about unsigned long so that we don't have additional + * dependencies. + */ +#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a)) + +/* + * The following macro is used to remove the volatile cast-away warnings + * from gcc -Wcast-qual; as above it should be used with caution + * because it can hide valid errors or warnings. Valid uses include + * making it possible to pass a volatile pointer to memset(). + * For the same reasons as above, we use unsigned long and not intptr_t. + */ +#define __UNVOLATILE(a) ((void *)(unsigned long)(volatile void *)(a)) + +/* + * GCC2 provides __extension__ to suppress warnings for various GNU C + * language extensions under "-ansi -pedantic". + */ +#if !__GNUC_PREREQ__(2, 0) +#define __extension__ /* delete __extension__ if non-gcc or gcc1 */ +#endif + +/* + * GCC1 and some versions of GCC2 declare dead (non-returning) and + * pure (no side effects) functions using "volatile" and "const"; + * unfortunately, these then cause warnings under "-ansi -pedantic". + * GCC2 uses a new, peculiar __attribute__((attrs)) style. All of + * these work for GNU C++ (modulo a slight glitch in the C++ grammar + * in the distribution version of 2.5.5). + */ +#if !__GNUC_PREREQ__(2, 0) +#define __attribute__(x) +#endif + +#if __GNUC_PREREQ__(2, 5) +#define __dead __attribute__((__noreturn__)) +#elif defined(__GNUC__) +#define __dead __volatile +#else +#define __dead +#endif + +#if __GNUC_PREREQ__(2, 96) +#define __pure __attribute__((__pure__)) +#elif defined(__GNUC__) +#define __pure __const +#else +#define __pure +#endif + +#if __GNUC_PREREQ__(2, 7) +#define __unused __attribute__((__unused__)) +#else +#define __unused /* delete */ +#endif + +#if __GNUC_PREREQ__(3, 1) +#define __used __attribute__((__used__)) +#else +#define __used __unused +#endif + +#if __GNUC_PREREQ__(2, 7) +#define __packed __attribute__((__packed__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#elif defined(__PCC__) +#define __packed /* XXX ignore for now */ +#define __aligned(x) /* XXX ignore for now */ +#define __section(x) /* XXX ignore for now */ +#elif defined(_MSC_VER) +#define __packed /* XXX ignore */ +#define __aligned(x) /* XXX ignore */ +#define __section(x) /* XXX ignore */ +#elif defined(__lint__) +#define __packed /* delete */ +#define __aligned(x) /* delete */ +#define __section(x) /* delete */ +#else +#define __packed error: no __packed for this compiler +#define __aligned(x) error: no __aligned for this compiler +#define __section(x) error: no __section for this compiler +#endif + +/* + * C99 defines the restrict type qualifier keyword, which was made available + * in GCC 2.92. + */ +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#else +#if !__GNUC_PREREQ__(2, 92) +#define __restrict /* delete __restrict when not supported */ +#endif +#endif + +/* + * C99 defines __func__ predefined identifier, which was made available + * in GCC 2.95. + */ +#if !(__STDC_VERSION__ >= 199901L) +#if __GNUC_PREREQ__(2, 6) +#define __func__ __PRETTY_FUNCTION__ +#elif __GNUC_PREREQ__(2, 4) +#define __func__ __FUNCTION__ +#else +#define __func__ "" +#endif +#endif /* !(__STDC_VERSION__ >= 199901L) */ + +#if defined(_KERNEL) +#if defined(NO_KERNEL_RCSIDS) +#undef __KERNEL_RCSID +#define __KERNEL_RCSID(_n, _s) /* nothing */ +#endif /* NO_KERNEL_RCSIDS */ +#endif /* _KERNEL */ + +#if !defined(_STANDALONE) && !defined(_KERNEL) +#if defined(__GNUC__) || defined(__PCC__) +#define __RENAME(x) ___RENAME(x) +#else +#ifdef __lint__ +#define __RENAME(x) __symbolrename(x) +#else +#error "No function renaming possible" +#endif /* __lint__ */ +#endif /* __GNUC__ */ +#else /* _STANDALONE || _KERNEL */ +#define __RENAME(x) no renaming in kernel or standalone environment +#endif + +/* + * A barrier to stop the optimizer from moving code or assume live + * register values. This is gcc specific, the version is more or less + * arbitrary, might work with older compilers. + */ +#if __GNUC_PREREQ__(2, 95) +#define __insn_barrier() __asm __volatile("":::"memory") +#else +#define __insn_barrier() /* */ +#endif + +/* + * GNU C version 2.96 adds explicit branch prediction so that + * the CPU back-end can hint the processor and also so that + * code blocks can be reordered such that the predicted path + * sees a more linear flow, thus improving cache behavior, etc. + * + * The following two macros provide us with a way to use this + * compiler feature. Use __predict_true() if you expect the expression + * to evaluate to true, and __predict_false() if you expect the + * expression to evaluate to false. + * + * A few notes about usage: + * + * * Generally, __predict_false() error condition checks (unless + * you have some _strong_ reason to do otherwise, in which case + * document it), and/or __predict_true() `no-error' condition + * checks, assuming you want to optimize for the no-error case. + * + * * Other than that, if you don't know the likelihood of a test + * succeeding from empirical or other `hard' evidence, don't + * make predictions. + * + * * These are meant to be used in places that are run `a lot'. + * It is wasteful to make predictions in code that is run + * seldomly (e.g. at subsystem initialization time) as the + * basic block reordering that this affects can often generate + * larger code. + */ +#if __GNUC_PREREQ__(2, 96) +#define __predict_true(exp) __builtin_expect((exp) != 0, 1) +#define __predict_false(exp) __builtin_expect((exp) != 0, 0) +#else +#define __predict_true(exp) (exp) +#define __predict_false(exp) (exp) +#endif + +/* + * Macros for manipulating "link sets". Link sets are arrays of pointers + * to objects, which are gathered up by the linker. + * + * Object format-specific code has provided us with the following macros: + * + * __link_set_add_text(set, sym) + * Add a reference to the .text symbol `sym' to `set'. + * + * __link_set_add_rodata(set, sym) + * Add a reference to the .rodata symbol `sym' to `set'. + * + * __link_set_add_data(set, sym) + * Add a reference to the .data symbol `sym' to `set'. + * + * __link_set_add_bss(set, sym) + * Add a reference to the .bss symbol `sym' to `set'. + * + * __link_set_decl(set, ptype) + * Provide an extern declaration of the set `set', which + * contains an array of the pointer type `ptype'. This + * macro must be used by any code which wishes to reference + * the elements of a link set. + * + * __link_set_start(set) + * This points to the first slot in the link set. + * + * __link_set_end(set) + * This points to the (non-existent) slot after the last + * entry in the link set. + * + * __link_set_count(set) + * Count the number of entries in link set `set'. + * + * In addition, we provide the following macros for accessing link sets: + * + * __link_set_foreach(pvar, set) + * Iterate over the link set `set'. Because a link set is + * an array of pointers, pvar must be declared as "type **pvar", + * and the actual entry accessed as "*pvar". + * + * __link_set_entry(set, idx) + * Access the link set entry at index `idx' from set `set'. + */ +#define __link_set_foreach(pvar, set) \ + for (pvar = __link_set_start(set); pvar < __link_set_end(set); pvar++) + +#define __link_set_entry(set, idx) (__link_set_begin(set)[idx]) + +/* + * Return the number of elements in a statically-allocated array, + * __x. + */ +#define __arraycount(__x) (sizeof(__x) / sizeof(__x[0])) + +/* __BIT(n): nth bit, where __BIT(0) == 0x1. */ +#define __BIT(__n) \ + (((__n) >= NBBY * sizeof(uintmax_t)) ? 0 : ((uintmax_t)1 << (__n))) + +/* __BITS(m, n): bits m through n, m < n. */ +#define __BITS(__m, __n) \ + ((__BIT(MAX((__m), (__n)) + 1) - 1) ^ (__BIT(MIN((__m), (__n))) - 1)) + +/* find least significant bit that is set */ +#define __LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask)) + +#define __PRIuBIT PRIuMAX +#define __PRIuBITS __PRIuBIT + +#define __PRIxBIT PRIxMAX +#define __PRIxBITS __PRIxBIT + +#define __SHIFTOUT(__x, __mask) (((__x) & (__mask)) / __LOWEST_SET_BIT(__mask)) +#define __SHIFTIN(__x, __mask) ((__x) * __LOWEST_SET_BIT(__mask)) +#define __SHIFTOUT_MASK(__mask) __SHIFTOUT((__mask), (__mask)) + +#endif /* !_SYS_CDEFS_H_ */