From 08f20b36f786045db17ff89e5cc2ea44c767230e Mon Sep 17 00:00:00 2001 From: imp Date: Sat, 20 Mar 2010 03:39:35 +0000 Subject: Add support for the Samsung S3C2xx0 family of ARM SoCs written by Andrew Turner. The kernel supports the LN2410SBC evaluation board, and likely others. These parts (or similar ones) are in some open hardware designs for phones. Submitted by: Andrew Turner --- sys/arm/conf/LN2410SBC | 87 +++++ sys/arm/s3c2xx0/board_ln2410sbc.c | 45 +++ sys/arm/s3c2xx0/files.s3c2xx0 | 13 + sys/arm/s3c2xx0/s3c2410reg.h | 96 ++++++ sys/arm/s3c2xx0/s3c2410var.h | 49 +++ sys/arm/s3c2xx0/s3c2440reg.h | 109 ++++++ sys/arm/s3c2xx0/s3c24x0.c | 648 +++++++++++++++++++++++++++++++++++ sys/arm/s3c2xx0/s3c24x0_clk.c | 287 ++++++++++++++++ sys/arm/s3c2xx0/s3c24x0_machdep.c | 467 ++++++++++++++++++++++++++ sys/arm/s3c2xx0/s3c24x0reg.h | 672 +++++++++++++++++++++++++++++++++++++ sys/arm/s3c2xx0/s3c24x0var.h | 51 +++ sys/arm/s3c2xx0/s3c2xx0_space.c | 252 ++++++++++++++ sys/arm/s3c2xx0/s3c2xx0board.h | 36 ++ sys/arm/s3c2xx0/s3c2xx0reg.h | 139 ++++++++ sys/arm/s3c2xx0/s3c2xx0var.h | 89 +++++ sys/arm/s3c2xx0/std.ln2410sbc | 10 + sys/arm/s3c2xx0/std.s3c2410 | 6 + sys/arm/s3c2xx0/uart_bus_s3c2410.c | 59 ++++ sys/arm/s3c2xx0/uart_cpu_s3c2410.c | 78 +++++ sys/arm/s3c2xx0/uart_dev_s3c2410.c | 383 +++++++++++++++++++++ sys/arm/s3c2xx0/uart_dev_s3c2410.h | 88 +++++ 21 files changed, 3664 insertions(+) create mode 100644 sys/arm/conf/LN2410SBC create mode 100644 sys/arm/s3c2xx0/board_ln2410sbc.c create mode 100644 sys/arm/s3c2xx0/files.s3c2xx0 create mode 100644 sys/arm/s3c2xx0/s3c2410reg.h create mode 100644 sys/arm/s3c2xx0/s3c2410var.h create mode 100644 sys/arm/s3c2xx0/s3c2440reg.h create mode 100644 sys/arm/s3c2xx0/s3c24x0.c create mode 100644 sys/arm/s3c2xx0/s3c24x0_clk.c create mode 100644 sys/arm/s3c2xx0/s3c24x0_machdep.c create mode 100644 sys/arm/s3c2xx0/s3c24x0reg.h create mode 100644 sys/arm/s3c2xx0/s3c24x0var.h create mode 100644 sys/arm/s3c2xx0/s3c2xx0_space.c create mode 100644 sys/arm/s3c2xx0/s3c2xx0board.h create mode 100644 sys/arm/s3c2xx0/s3c2xx0reg.h create mode 100644 sys/arm/s3c2xx0/s3c2xx0var.h create mode 100644 sys/arm/s3c2xx0/std.ln2410sbc create mode 100644 sys/arm/s3c2xx0/std.s3c2410 create mode 100644 sys/arm/s3c2xx0/uart_bus_s3c2410.c create mode 100644 sys/arm/s3c2xx0/uart_cpu_s3c2410.c create mode 100644 sys/arm/s3c2xx0/uart_dev_s3c2410.c create mode 100644 sys/arm/s3c2xx0/uart_dev_s3c2410.h (limited to 'sys/arm') diff --git a/sys/arm/conf/LN2410SBC b/sys/arm/conf/LN2410SBC new file mode 100644 index 0000000..5a14f59 --- /dev/null +++ b/sys/arm/conf/LN2410SBC @@ -0,0 +1,87 @@ +# LN2410SBC -- Custom kernel configuration for the LN2410SBC +# +# For more information on this file, please read the handbook section on +# Kernel Configuration Files: +# +# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html +# +# The handbook is also available locally in /usr/share/doc/handbook +# if you've installed the doc distribution, otherwise always see the +# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the +# latest information. +# +# An exhaustive list of options and more detailed explanations of the +# device lines is also present in the ../../conf/NOTES and NOTES files. +# If you are in doubt as to the purpose or necessity of a line, check first +# in NOTES. +# +# $FreeBSD$ + +machine arm +ident LN2410SBC + +include "../s3c2xx0/std.ln2410sbc" +#To statically compile in device wiring instead of /boot/device.hints +#hints "GENERIC.hints" #Default places to look for devices. +makeoptions MODULES_OVERRIDE="" + +device board_ln2410sbc + +makeoptions DEBUG=-g #Build kernel with gdb(1) debug symbols +options HZ=100 +options DDB +options KDB + +options SCHED_4BSD #4BSD scheduler +options INET #InterNETworking +#options INET6 #IPv6 communications protocols +options FFS #Berkeley Fast Filesystem +#options SOFTUPDATES #Enable FFS soft updates support +#options UFS_ACL #Support for access control lists +#options UFS_DIRHASH #Improve performance on big directories +#options MD_ROOT #MD is a potential root device +#options MD_ROOT_SIZE=4096 # 4MB ram disk +options ROOTDEVNAME=\"ufs:da0s1\" + +#options BOOTP +#options BOOTP_NFSROOT # NFS mount root filesystem using BOOTP info +#options NFSCLIENT #Network File System client +#options NFS_ROOT #NFS usable as root device + +options PSEUDOFS #Pseudo-filesystem framework +#options SCSI_DELAY=5000 #Delay (in ms) before probing SCSI +options KTRACE #ktrace(1) support +options SYSVSHM #SYSV-style shared memory +options SYSVMSG #SYSV-style message queues +options SYSVSEM #SYSV-style semaphores +options _KPOSIX_PRIORITY_SCHEDULING #Posix P1003_1B real-time extensions + +options MUTEX_NOINLINE +options RWLOCK_NOINLINE +options SX_NOINLINE + +options NO_FFS_SNAPSHOT +options NO_SWAPPING +device random +device pty + +device loop +device ether +device bpf + +device uart + +# Debugging for use in -current +options INVARIANTS #Enable calls of extra sanity checking +options INVARIANT_SUPPORT #Extra sanity checks of internal structures, required by INVARIANTS +options WITNESS #Enable checks to detect deadlocks and cycles +options WITNESS_SKIPSPIN #Don't run witness on spinlocks for speed + +device md + +device usb +device ohci +device umass +device scbus # SCSI bus (required for da) +device da # Direct Access (disks) + diff --git a/sys/arm/s3c2xx0/board_ln2410sbc.c b/sys/arm/s3c2xx0/board_ln2410sbc.c new file mode 100644 index 0000000..5f5ac90 --- /dev/null +++ b/sys/arm/s3c2xx0/board_ln2410sbc.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2009 Andrew Turner + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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. + * + */ + +#include +__FBSDID("$FreeBSD$"); +#include +#include + +#include +#include + +extern vm_offset_t s3c2410_uart_vaddr; + +long +board_init(void) +{ + s3c2410_uart_vaddr = S3C24X0_UART_BASE(0); + + return (64 * 1024 * 1024); +} + diff --git a/sys/arm/s3c2xx0/files.s3c2xx0 b/sys/arm/s3c2xx0/files.s3c2xx0 new file mode 100644 index 0000000..113f9dd --- /dev/null +++ b/sys/arm/s3c2xx0/files.s3c2xx0 @@ -0,0 +1,13 @@ +# $FreeBSD$ +arm/arm/cpufunc_asm_arm9.S standard +arm/arm/irq_dispatch.S standard +arm/s3c2xx0/board_ln2410sbc.c optional board_ln2410sbc +arm/s3c2xx0/s3c24x0_machdep.c standard +arm/s3c2xx0/s3c24x0.c standard +arm/s3c2xx0/s3c2xx0_space.c standard +arm/s3c2xx0/s3c24x0_clk.c standard +arm/s3c2xx0/uart_bus_s3c2410.c optional uart +arm/s3c2xx0/uart_cpu_s3c2410.c optional uart +arm/s3c2xx0/uart_dev_s3c2410.c optional uart + +dev/usb/controller/ohci_s3c24x0.c optional ohci diff --git a/sys/arm/s3c2xx0/s3c2410reg.h b/sys/arm/s3c2xx0/s3c2410reg.h new file mode 100644 index 0000000..31bb857 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2410reg.h @@ -0,0 +1,96 @@ +/* $NetBSD: s3c2410reg.h,v 1.6 2004/02/12 03:52:46 bsh Exp $ */ + +/*- + * Copyright (c) 2003, 2004 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 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. + * + * $FreeBSD$ + */ + + +/* + * Samsung S3C2410X processor is ARM920T based integrated CPU + * + * Reference: + * S3C2410X User's Manual + */ +#ifndef _ARM_S3C2XX0_S3C2410REG_H_ +#define _ARM_S3C2XX0_S3C2410REG_H_ + +/* common definitions for S3C2410 and S3C2440 */ +#include + +/* + * Memory Map + */ +#define S3C2410_BANK_SIZE 0x08000000 +#define S3C2410_BANK_START(n) (S3C2410_BANK_SIZE*(n)) +#define S3C2410_SDRAM_START S3C2410_BANK_START(6) + + +/* interrupt control */ +#define S3C2410_SUBIRQ_MAX (S3C24X0_SUBIRQ_MIN+10) + +/* Clock control */ +/* CLKMAN_CLKCON */ +#define S3C2410_CLKCON_SM (1<<0) /* 1=transition to SPECIAL mode */ +/* CLKMAN_CLKDIVN */ +#define S3C2410_CLKDIVN_HDIVN (1<<1) /* hclk=fclk/2 */ + +/* NAND Flash controller */ +#define S3C2410_NANDFC_SIZE 0x18 +/* NANDFC_NFCONF */ +#define S3C2410_NFCONF_ENABLE (1<<15) /* NAND controller enabled */ +#define S3C2410_NFCONF_ECC (1<<12) /* Initialize ECC decoder/encoder */ +#define S3C2410_NFCONF_FCE (1<<11) /* Flash chip enabled */ +#define S3C2410_NFCONF_TACLS (7<<8) /* CLE and ALE duration */ +#define S3C2410_NFCONF_TWRPH0 (7<<4) /* TWRPH0 duration */ +#define S3C2410_NFCONF_TWRPH1 (7<<0) /* TWRPH1 duration */ +#define S3C2410_NANDFC_NFCMD 0x04 /* command */ +#define S3C2410_NANDFC_NFADDR 0x08 /* address */ +#define S3C2410_NANDFC_NFDATA 0x0c /* data */ +#define S3C2410_NANDFC_NFSTAT 0x10 /* operation status */ +#define S3C2410_NANDFC_NFECC 0x14 /* ecc */ + +/* MMC/SD */ +/* SDI_CON */ +#define S3C2410_CON_FIFO_RESET (1<<1) + +/* GPIO */ +#define S3C2410_GPIO_SIZE 0xb4 + +/* SD interface */ +#define S3C2410_SDI_SIZE 0x44 +#define DCON_STOP (1<<14) /* Force the transfer to stop */ +#define S3C2410_SDI_DAT 0x3c +#define S3C2410_SDI_IMSK 0x40 /* Interrupt mask */ +#define S3C2410_SDI_IMASK_ALL 0x3ffdf + +/* ADC */ +#define S3C2410_ADC_SIZE 0x14 + +#endif /* _ARM_S3C2XX0_S3C2410REG_H_ */ diff --git a/sys/arm/s3c2xx0/s3c2410var.h b/sys/arm/s3c2xx0/s3c2410var.h new file mode 100644 index 0000000..b17784d --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2410var.h @@ -0,0 +1,49 @@ +/* $NetBSD: s3c2410var.h,v 1.2 2003/08/29 12:57:50 bsh Exp $ */ + +/*- + * Copyright (c) 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 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM_S3C2410VAR_H_ +#define _ARM_S3C2410VAR_H_ + +#include + +int s3c2410_sscom_cnattach(bus_space_tag_t, int, int, int, tcflag_t); +int s3c2410_sscom_kgdb_attach(bus_space_tag_t, int, int, int, tcflag_t); +void s3c2410_intr_init(struct s3c24x0_softc *); +void s3c2410_softreset(void); + +void s3c2410_mask_subinterrupts(int); +void s3c2410_unmask_subinterrupts(int); + +void *s3c2410_extint_establish(int, int, int, int (*)(void *), void *); +void s3c2410_setup_extint(int, int); +#endif /* _ARM_S3C2410VAR_H_ */ diff --git a/sys/arm/s3c2xx0/s3c2440reg.h b/sys/arm/s3c2xx0/s3c2440reg.h new file mode 100644 index 0000000..418557d --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2440reg.h @@ -0,0 +1,109 @@ +/*- + * Copyright (C) 2009 Andrew Turner + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 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. + * + * $FreeBSD$ + */ + +/* + * Samsung S3C2440X processor is ARM920T based integrated CPU + * + * Reference: + * S3C2440A/S3C2442B User's Manual + */ +#ifndef _ARM_S3C2XX0_S3C2440REG_H_ +#define _ARM_S3C2XX0_S3C2440REG_H_ + +/* common definitions for S3C2410 and S3C2440 */ +#include + +/* + * Memory Map + */ +#define S3C2440_BANK_SIZE 0x08000000 +#define S3C2440_BANK_START(n) (S3C2410_BANK_SIZE*(n)) +#define S3C2440_SDRAM_START S3C2410_BANK_START(6) + + +/* interrupt control */ +#define S3C2440_SUBIRQ_MAX (S3C24X0_SUBIRQ_MIN+10) + +/* Clock control */ +/* CLKMAN_CLKCON */ +#define S3C2440_CLKCON_STOP (1<<0) /* 1=transition to STOP mode */ +/* CLKMAN_CLKDIVN */ +#define S3C2440_CLKDIVN_HDIVN (3<<1) /* hclk */ +#define S3C2440_CLKMAN_CAMDIVN 0x18 +#define S3C2440_CAMDIVN_HCLK4_HALF (1<<9) +#define S3C2440_CAMDIVN_HCLK3_HALF (1<<8) + +/* NAND Flash controller */ +#define S3C2440_NANDFC_SIZE 0x40 + +#define S3C2440_NANDFC_NFCONT 0x04 +#define S3C2440_NFCONT_LOCK_TIGHT (1<<13) /* Lock part of the NAND */ +#define S3C2440_NFCONT_SOFT_LOCK (1<<12) /* Soft lock part of the NAND */ +#define S3C2440_NFCONT_ILLEGAL_ACC_INT (1<<10) /* Illegal access interrupt */ +#define S3C2440_NFCONT_RNB_INT (1<<9) /* RnB transition interrupt */ +#define S3C2440_NFCONT_RNB_TRANS_MODE (1<<8) /* RnB transition mode */ +#define S3C2440_NFCONT_SPARE_ECC_LOCK (1<<6) /* Lock spare ECC generation */ +#define S3C2440_NFCONT_MAIN_ECC_LOCK (1<<5) /* Lock main ECC generation */ +#define S3C2440_NFCONT_INIT_ECC (1<<4) /* Init ECC encoder/decoder */ +#define S3C2440_NFCONT_NCE (1<<1) /* NAND Chip select */ +#define S3C2440_NFCONT_ENABLE (1<<0) /* Enable the controller */ +#define S3C2440_NANDFC_NFCMMD 0x08 +#define S3C2440_NANDFC_NFADDR 0x0c +#define S3C2440_NANDFC_NFDATA 0x10 +#define S3C2440_NANDFC_NFSTAT 0x20 + +/* MMC/SD */ +/* SDI_CON */ +#define S3C2440_CON_RESET (1<<8) +#define S3C2440_CON_CLOCK_TYPE (1<<5) +/* SDI_FSTA */ +#define S3c2440_FSTA_RESET (1<<16) +#define S3C2440_FSTA_FAIL_ERROR_MSK (3<<14) +#define S3C2440_FSTA_FAIL_NONE (0<<14) +#define S3C2440_FSTA_FAIL_FIFO (1<<14) +#define S3C2440_FSTA_FAIL_LAST_TRANS (2<<14) + +/* GPIO */ +#define S3C2440_GPIO_SIZE 0xd0 + +/* SD interface */ +#define S3C2410_SDI_SIZE 0x44 +#define DCON_START (1<<14) /* Start the data transfer */ +#define S3C2440_SDI_IMSK 0x3c /* Interrupt mask */ +#define S3C2440_SDI_IMASK_ALL 0x3C7C0 +#define S3C2440_SDI_DAT 0x40 + +/* ADC */ +#define ADCTSC_UD_SEN (1<<8) +#define S3C2440_ADC_SIZE 0x18 + +/* UART */ +#define S3C2440_UFSTAT_TXCOUNT (0x3f << 8) +#define S3C2440_UFSTAT_RXCOUNT (0x3f << 0) + +#endif /* _ARM_S3C2XX0_S3C2440REG_H_ */ diff --git a/sys/arm/s3c2xx0/s3c24x0.c b/sys/arm/s3c2xx0/s3c24x0.c new file mode 100644 index 0000000..b0e338a --- /dev/null +++ b/sys/arm/s3c2xx0/s3c24x0.c @@ -0,0 +1,648 @@ +/* $NetBSD: s3c2410.c,v 1.4 2003/08/27 03:46:05 bsh Exp $ */ + +/* + * Copyright (c) 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define S3C2XX0_XTAL_CLK 12000000 + +#define IPL_LEVELS 13 +u_int irqmasks[IPL_LEVELS]; + +static struct { + uint32_t idcode; + const char *name; + s3c2xx0_cpu cpu; +} s3c2x0_cpu_id[] = { + { CHIPID_S3C2410A, "S3C2410A", CPU_S3C2410 }, + { CHIPID_S3C2440A, "S3C2440A", CPU_S3C2440 }, + { CHIPID_S3C2442B, "S3C2442B", CPU_S3C2440 }, + + { 0, NULL } +}; + +static struct { + const char *name; + int prio; + int unit; + struct { + int type; + u_long start; + u_long count; + } res[2]; +} s3c24x0_children[] = { + { "timer", 0, -1, { { 0 }, } }, + { "uart", 1, 0, { + { SYS_RES_IRQ, S3C24X0_INT_UART0, 1 }, + { SYS_RES_IOPORT, S3C24X0_UART_BASE(0), + S3C24X0_UART_BASE(1) - S3C24X0_UART_BASE(0) }, + } }, + { "uart", 1, 1, { + { SYS_RES_IRQ, S3C24X0_INT_UART1, 1 }, + { SYS_RES_IOPORT, S3C24X0_UART_BASE(1), + S3C24X0_UART_BASE(2) - S3C24X0_UART_BASE(1) }, + } }, + { "uart", 1, 2, { + { SYS_RES_IRQ, S3C24X0_INT_UART2, 1 }, + { SYS_RES_IOPORT, S3C24X0_UART_BASE(2), + S3C24X0_UART_BASE(3) - S3C24X0_UART_BASE(2) }, + } }, + { "ohci", 0, -1, { + { SYS_RES_IRQ, S3C24X0_INT_USBH, 0 }, + { SYS_RES_IOPORT, S3C24X0_USBHC_BASE, S3C24X0_USBHC_SIZE }, + } }, + { NULL }, +}; + + +/* prototypes */ +static device_t s3c24x0_add_child(device_t, int, const char *, int); + +static int s3c24x0_probe(device_t); +static int s3c24x0_attach(device_t); +static void s3c24x0_identify(driver_t *, device_t); +static int s3c24x0_setup_intr(device_t, device_t, struct resource *, int, + driver_filter_t *, driver_intr_t *, void *, void **); +static int s3c24x0_teardown_intr(device_t, device_t, struct resource *, + void *); +static struct resource *s3c24x0_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int s3c24x0_activate_resource(device_t, device_t, int, int, + struct resource *); +static int s3c24x0_release_resource(device_t, device_t, int, int, + struct resource *); +static struct resource_list *s3c24x0_get_resource_list(device_t, device_t); + +static void s3c24x0_identify_cpu(device_t); + +static device_method_t s3c24x0_methods[] = { + DEVMETHOD(device_probe, s3c24x0_probe), + DEVMETHOD(device_attach, s3c24x0_attach), + DEVMETHOD(device_identify, s3c24x0_identify), + DEVMETHOD(bus_setup_intr, s3c24x0_setup_intr), + DEVMETHOD(bus_teardown_intr, s3c24x0_teardown_intr), + DEVMETHOD(bus_alloc_resource, s3c24x0_alloc_resource), + DEVMETHOD(bus_activate_resource, s3c24x0_activate_resource), + DEVMETHOD(bus_release_resource, s3c24x0_release_resource), + DEVMETHOD(bus_get_resource_list,s3c24x0_get_resource_list), + DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource), + DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource), + {0, 0}, +}; + +static driver_t s3c24x0_driver = { + "s3c24x0", + s3c24x0_methods, + sizeof(struct s3c24x0_softc), +}; +static devclass_t s3c24x0_devclass; + +DRIVER_MODULE(s3c24x0, nexus, s3c24x0_driver, s3c24x0_devclass, 0, 0); + +struct s3c2xx0_softc *s3c2xx0_softc = NULL; + +static device_t +s3c24x0_add_child(device_t bus, int prio, const char *name, int unit) +{ + device_t child; + struct s3c2xx0_ivar *ivar; + + child = device_add_child_ordered(bus, prio, name, unit); + if (child == NULL) + return (NULL); + + ivar = malloc(sizeof(*ivar), M_DEVBUF, M_NOWAIT | M_ZERO); + if (ivar == NULL) { + device_delete_child(bus, child); + printf("Can't add alloc ivar\n"); + return (NULL); + } + device_set_ivars(child, ivar); + resource_list_init(&ivar->resources); + + return (child); +} + +static int +s3c24x0_setup_intr(device_t dev, device_t child, + struct resource *ires, int flags, driver_filter_t *filt, + driver_intr_t *intr, void *arg, void **cookiep) +{ + int error, irq; + + error = BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, filt, + intr, arg, cookiep); + if (error != 0) + return (error); + + for (irq = rman_get_start(ires); irq <= rman_get_end(ires); irq++) { + arm_unmask_irq(irq); + } + return (0); +} + +static int +s3c24x0_teardown_intr(device_t dev, device_t child, struct resource *res, + void *cookie) +{ + return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie)); +} + +static struct resource * +s3c24x0_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource_list_entry *rle; + struct s3c2xx0_ivar *ivar = device_get_ivars(child); + struct resource_list *rl = &ivar->resources; + struct resource *res = NULL; + + if (device_get_parent(child) != bus) + return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, + type, rid, start, end, count, flags)); + + rle = resource_list_find(rl, type, *rid); + if (rle != NULL) { + /* There is a resource list. Use it */ + if (rle->res) + panic("Resource rid %d type %d already in use", *rid, + type); + if (start == 0UL && end == ~0UL) { + start = rle->start; + count = ulmax(count, rle->count); + end = ulmax(rle->end, start + count - 1); + } + /* + * When allocating an irq with children irq's really + * allocate the children as it is those we are interested + * in receiving, not the parent. + */ + if (type == SYS_RES_IRQ && start == end) { + switch (start) { + case S3C24X0_INT_ADCTC: + start = S3C24X0_INT_TC; + end = S3C24X0_INT_ADC; + break; +#ifdef S3C2440_INT_CAM + case S3C2440_INT_CAM: + start = S3C2440_INT_CAM_C; + end = S3C2440_INT_CAM_P; + break; +#endif + default: + break; + } + count = end - start + 1; + } + } + + switch (type) { + case SYS_RES_IRQ: + res = rman_reserve_resource( + &s3c2xx0_softc->s3c2xx0_irq_rman, start, end, + count, flags, child); + break; + + case SYS_RES_IOPORT: + case SYS_RES_MEMORY: + res = rman_reserve_resource( + &s3c2xx0_softc->s3c2xx0_mem_rman, + start, end, count, flags, child); + rman_set_bustag(res, &s3c2xx0_bs_tag); + rman_set_bushandle(res, start); + break; + } + + if (res != NULL) { + rman_set_rid(res, *rid); + if (rle != NULL) { + rle->res = res; + rle->start = rman_get_start(res); + rle->end = rman_get_end(res); + rle->count = count; + } + } + + return (res); +} + +static int +s3c24x0_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_activate_resource(r)); +} + +static int +s3c24x0_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + struct s3c2xx0_ivar *ivar = device_get_ivars(child); + struct resource_list *rl = &ivar->resources; + struct resource_list_entry *rle; + + if (rl == NULL) + return (EINVAL); + + rle = resource_list_find(rl, type, rid); + if (rle == NULL) + return (EINVAL); + + rman_release_resource(r); + rle->res = NULL; + + return 0; +} + +static struct resource_list * +s3c24x0_get_resource_list(device_t dev, device_t child) +{ + struct s3c2xx0_ivar *ivar; + + ivar = device_get_ivars(child); + return (&(ivar->resources)); +} + +void +s3c24x0_identify(driver_t *driver, device_t parent) +{ + + BUS_ADD_CHILD(parent, 0, "s3c24x0", 0); +} + +int +s3c24x0_probe(device_t dev) +{ + return 0; +} + +int +s3c24x0_attach(device_t dev) +{ + struct s3c24x0_softc *sc = device_get_softc(dev); + bus_space_tag_t iot; + device_t child; + unsigned int i, j; + + s3c2xx0_softc = &(sc->sc_sx); + sc->sc_sx.sc_iot = iot = &s3c2xx0_bs_tag; + + if (bus_space_map(iot, + S3C24X0_INTCTL_PA_BASE, S3C24X0_INTCTL_SIZE, + BUS_SPACE_MAP_LINEAR, &sc->sc_sx.sc_intctl_ioh)) + panic("Cannot map the interrupt controller"); + + /* Map the GPIO registers */ + if (bus_space_map(iot, S3C24X0_GPIO_PA_BASE, S3C2410_GPIO_SIZE, + 0, &sc->sc_sx.sc_gpio_ioh)) + panic("Cannot map the GPIO"); + /* Clock manager */ + if (bus_space_map(iot, S3C24X0_CLKMAN_PA_BASE, + S3C24X0_CLKMAN_SIZE, 0, &sc->sc_sx.sc_clkman_ioh)) + panic("cannot map the clock"); + + if (bus_space_map(iot, S3C24X0_TIMER_PA_BASE, + S3C24X0_TIMER_SIZE, 0, &sc->sc_timer_ioh)) + panic("cannot map the TIMER"); + + if (bus_space_map(iot, S3C24X0_USBHC_PA_BASE, + S3C24X0_USBHC_SIZE, 0, &sc->sc_sx.sc_ohci_ioh)) + panic("cannot map the USB Host"); + + if (bus_space_map(iot, S3C24X0_WDT_PA_BASE, + S3C24X0_WDT_SIZE, 0, &sc->sc_sx.sc_wdt_ioh)) + panic("cannot map the watchdog timer"); + + /* + * Identify the CPU + */ + s3c24x0_identify_cpu(dev); + + /* calculate current clock frequency */ + s3c24x0_clock_freq(&sc->sc_sx); + device_printf(dev, "fclk %d MHz hclk %d MHz pclk %d MHz\n", + sc->sc_sx.sc_fclk / 1000000, sc->sc_sx.sc_hclk / 1000000, + sc->sc_sx.sc_pclk / 1000000); + + /* + * Attach children devices + */ + s3c2xx0_softc->s3c2xx0_irq_rman.rm_type = RMAN_ARRAY; + s3c2xx0_softc->s3c2xx0_irq_rman.rm_descr = "S3C24X0 IRQs"; + s3c2xx0_softc->s3c2xx0_mem_rman.rm_type = RMAN_ARRAY; + s3c2xx0_softc->s3c2xx0_mem_rman.rm_descr = "S3C24X0 Memory"; + if (rman_init(&s3c2xx0_softc->s3c2xx0_irq_rman) != 0 || + rman_manage_region(&s3c2xx0_softc->s3c2xx0_irq_rman, 0, + S3C2410_SUBIRQ_MAX) != 0) + panic("s3c24x0_attach: failed to set up IRQ rman"); + /* Manage the registor memory space */ + if ((rman_init(&s3c2xx0_softc->s3c2xx0_mem_rman) != 0) || + (rman_manage_region(&s3c2xx0_softc->s3c2xx0_mem_rman, + S3C24X0_DEV_VA_OFFSET, + S3C24X0_DEV_VA_OFFSET + S3C24X0_DEV_VA_SIZE) != 0)) + panic("s3c24x0_attach: failed to set up register rman"); + + for (i = 0; s3c24x0_children[i].name != NULL; i++) { + child = s3c24x0_add_child(dev, s3c24x0_children[i].prio, + s3c24x0_children[i].name, s3c24x0_children[i].unit); + for (j = 0; j < sizeof(s3c24x0_children[i].res) / + sizeof(s3c24x0_children[i].res[0]) && + s3c24x0_children[i].res[j].type != 0; j++) { + bus_set_resource(child, + s3c24x0_children[i].res[j].type, 0, + s3c24x0_children[i].res[j].start, + s3c24x0_children[i].res[j].count); + } + } + + bus_generic_probe(dev); + bus_generic_attach(dev); + + return (0); +} + +static void +s3c24x0_identify_cpu(device_t dev) +{ + struct s3c24x0_softc *sc = device_get_softc(dev); + uint32_t idcode; + int i; + + idcode = bus_space_read_4(sc->sc_sx.sc_iot, sc->sc_sx.sc_gpio_ioh, + GPIO_GSTATUS1); + + for (i = 0; s3c2x0_cpu_id[i].name != NULL; i++) { + if (s3c2x0_cpu_id[i].idcode == idcode) + break; + } + if (s3c2x0_cpu_id[i].name == NULL) + panic("Unknown CPU detected ((Chip ID: %#X)", idcode); + device_printf(dev, "Found %s CPU (Chip ID: %#X)\n", + s3c2x0_cpu_id[i].name, idcode); + sc->sc_sx.sc_cpu = s3c2x0_cpu_id[i].cpu; +} + +/* + * fill sc_pclk, sc_hclk, sc_fclk from values of clock controller register. + * + * s3c24{1,4}0_clock_freq2() is meant to be called from kernel startup routines. + * s3c24x0_clock_freq() is for after kernel initialization is done. + * + * Because they can be called before bus_space is available we need to use + * volatile pointers rather than bus_space_read. + */ +void +s3c2410_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk) +{ + uint32_t pllcon, divn; + unsigned int mdiv, pdiv, sdiv; + unsigned int f, h, p; + + pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON); + divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN); + + mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT; + pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT; + sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT; + + f = ((mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv)); + h = f; + if (divn & S3C2410_CLKDIVN_HDIVN) + h /= 2; + p = h; + if (divn & CLKDIVN_PDIVN) + p /= 2; + + if (fclk) *fclk = f; + if (hclk) *hclk = h; + if (pclk) *pclk = p; +} + +void +s3c2440_clock_freq2(vm_offset_t clkman_base, int *fclk, int *hclk, int *pclk) +{ + uint32_t pllcon, divn, camdivn; + unsigned int mdiv, pdiv, sdiv; + unsigned int f, h, p; + + pllcon = *(volatile uint32_t *)(clkman_base + CLKMAN_MPLLCON); + divn = *(volatile uint32_t *)(clkman_base + CLKMAN_CLKDIVN); + camdivn = *(volatile uint32_t *)(clkman_base + S3C2440_CLKMAN_CAMDIVN); + + mdiv = (pllcon & PLLCON_MDIV_MASK) >> PLLCON_MDIV_SHIFT; + pdiv = (pllcon & PLLCON_PDIV_MASK) >> PLLCON_PDIV_SHIFT; + sdiv = (pllcon & PLLCON_SDIV_MASK) >> PLLCON_SDIV_SHIFT; + + f = (2 * (mdiv + 8) * S3C2XX0_XTAL_CLK) / ((pdiv + 2) * (1 << sdiv)); + h = f; + switch((divn >> 1) & 3) { + case 0: + break; + case 1: + h /= 2; + break; + case 2: + if ((camdivn & S3C2440_CAMDIVN_HCLK4_HALF) == + S3C2440_CAMDIVN_HCLK4_HALF) + h /= 8; + else + h /= 4; + break; + case 3: + if ((camdivn & S3C2440_CAMDIVN_HCLK3_HALF) == + S3C2440_CAMDIVN_HCLK3_HALF) + h /= 6; + else + h /= 3; + break; + } + p = h; + if (divn & CLKDIVN_PDIVN) + p /= 2; + + if (fclk) *fclk = f; + if (hclk) *hclk = h; + if (pclk) *pclk = p; +} + +void +s3c24x0_clock_freq(struct s3c2xx0_softc *sc) +{ + vm_offset_t va; + + va = sc->sc_clkman_ioh; + switch(sc->sc_cpu) { + case CPU_S3C2410: + s3c2410_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk, + &sc->sc_pclk); + break; + case CPU_S3C2440: + s3c2440_clock_freq2(va, &sc->sc_fclk, &sc->sc_hclk, + &sc->sc_pclk); + break; + } +} + +void +cpu_reset(void) +{ + (void) disable_interrupts(I32_bit|F32_bit); + + bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_wdt_ioh, WDT_WTCON, + WTCON_ENABLE | WTCON_CLKSEL_16 | WTCON_ENRST); + for(;;); +} + +void +s3c24x0_sleep(int mode __unused) +{ + int reg; + + reg = bus_space_read_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh, + CLKMAN_CLKCON); + bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_clkman_ioh, + CLKMAN_CLKCON, reg | CLKCON_IDLE); +} + + +int +arm_get_next_irq(int last __unused) +{ + uint32_t intpnd; + int irq, subirq; + + if ((irq = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTOFFSET)) != 0) { + + /* Clear the pending bit */ + intpnd = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTPND); + bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh, + INTCTL_SRCPND, intpnd); + bus_space_write_4(&s3c2xx0_bs_tag, s3c2xx0_softc->sc_intctl_ioh, + INTCTL_INTPND, intpnd); + + switch (irq) { + case S3C24X0_INT_ADCTC: + case S3C24X0_INT_UART0: + case S3C24X0_INT_UART1: + case S3C24X0_INT_UART2: + /* Find the sub IRQ */ + subirq = 0x7ff; + subirq &= bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND); + subirq &= ~(bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK)); + if (subirq == 0) + return (irq); + + subirq = ffs(subirq) - 1; + + /* Clear the sub irq pending bit */ + bus_space_write_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_SUBSRCPND, + (1 << subirq)); + + /* + * Return the parent IRQ for UART + * as it is all we ever need + */ + if (subirq <= 8) + return (irq); + + return (S3C24X0_SUBIRQ_MIN + subirq); + } + + return (irq); + } + return (-1); +} + +void +arm_mask_irq(uintptr_t irq) +{ + u_int32_t mask; + + if (irq < S3C24X0_SUBIRQ_MIN) { + mask = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK); + mask |= (1 << irq); + bus_space_write_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask); + } else { + mask = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK); + mask |= (1 << (irq - S3C24X0_SUBIRQ_MIN)); + bus_space_write_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask); + } +} + +void +arm_unmask_irq(uintptr_t irq) +{ + u_int32_t mask; + + if (irq < S3C24X0_SUBIRQ_MIN) { + mask = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK); + mask &= ~(1 << irq); + bus_space_write_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTMSK, mask); + } else { + mask = bus_space_read_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK); + mask &= ~(1 << (irq - S3C24X0_SUBIRQ_MIN)); + bus_space_write_4(&s3c2xx0_bs_tag, + s3c2xx0_softc->sc_intctl_ioh, INTCTL_INTSUBMSK, mask); + } +} diff --git a/sys/arm/s3c2xx0/s3c24x0_clk.c b/sys/arm/s3c2xx0/s3c24x0_clk.c new file mode 100644 index 0000000..33b7ae2 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c24x0_clk.c @@ -0,0 +1,287 @@ +/* $NetBSD: s3c24x0_clk.c,v 1.6 2005/12/24 20:06:52 perry Exp $ */ + +/* + * Copyright (c) 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +struct s3c24x0_timer_softc { + device_t dev; +} timer_softc; + +static unsigned s3c24x0_timer_get_timecount(struct timecounter *tc); + +static struct timecounter s3c24x0_timer_timecounter = { + s3c24x0_timer_get_timecount, /* get_timecount */ + NULL, /* no poll_pps */ + ~0u, /* counter_mask */ + 3686400, /* frequency */ + "s3c24x0 timer", /* name */ + 1000 /* quality */ +}; + +static int +s3c24x0_timer_probe(device_t dev) +{ + + device_set_desc(dev, "s3c24x0 timer"); + return (0); +} + +static int +s3c24x0_timer_attach(device_t dev) +{ + timer_softc.dev = dev; + + /* We need to do this here for devices that expect DELAY to work */ + return (0); +} + +static device_method_t s3c24x0_timer_methods[] = { + DEVMETHOD(device_probe, s3c24x0_timer_probe), + DEVMETHOD(device_attach, s3c24x0_timer_attach), + {0, 0}, +}; + +static driver_t s3c24x0_timer_driver = { + "timer", + s3c24x0_timer_methods, + sizeof(struct s3c24x0_timer_softc), +}; +static devclass_t s3c24x0_timer_devclass; + +DRIVER_MODULE(s3c24x0timer, s3c24x0, s3c24x0_timer_driver, + s3c24x0_timer_devclass, 0, 0); + +#define TIMER_FREQUENCY(pclk) ((pclk)/16) /* divider=1/16 */ + +static unsigned int timer4_reload_value; +static unsigned int timer4_prescaler; +static unsigned int timer4_mseccount; +static volatile uint32_t s3c24x0_base; + +#define usec_to_counter(t) \ + ((timer4_mseccount*(t))/1000) + +#define counter_to_usec(c,pclk) \ + (((c)*timer4_prescaler*1000)/(TIMER_FREQUENCY(pclk)/1000)) + +static inline int +read_timer(struct s3c24x0_softc *sc) +{ + int count; + + do { + count = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh, + TIMER_TCNTO(4)); + } while ( __predict_false(count > timer4_reload_value) ); + + return count; +} + +static unsigned +s3c24x0_timer_get_timecount(struct timecounter *tc) +{ + struct s3c24x0_softc *sc = (struct s3c24x0_softc *)s3c2xx0_softc; + int value; + + value = bus_space_read_2(sc->sc_sx.sc_iot, sc->sc_timer_ioh, + TIMER_TCNTO(4)); + return (s3c24x0_base - value); +} + +static int +clock_intr(void *arg) +{ + struct trapframe *fp = arg; + + atomic_add_32(&s3c24x0_base, timer4_reload_value); + + hardclock(TRAPF_USERMODE(fp), TRAPF_PC(fp)); + return (FILTER_HANDLED); +} + +void +cpu_initclocks(void) +{ + struct s3c24x0_softc *sc = (struct s3c24x0_softc *)s3c2xx0_softc; + long tc; + struct resource *irq; + int rid = 0; + void *ihl; + int err, prescaler; + int pclk = s3c2xx0_softc->sc_pclk; + bus_space_tag_t iot = sc->sc_sx.sc_iot; + bus_space_handle_t ioh = sc->sc_timer_ioh; + uint32_t reg; + device_t dev = timer_softc.dev; + + /* We have already been initialized */ + if (timer4_reload_value != 0) + return; + +#define time_constant(hz) (TIMER_FREQUENCY(pclk) /(hz)/ prescaler) +#define calc_time_constant(hz) \ + do { \ + prescaler = 1; \ + do { \ + ++prescaler; \ + tc = time_constant(hz); \ + } while( tc > 65536 ); \ + } while(0) + + + /* Use the channels 4 and 3 for hardclock and statclock, respectively */ + + /* stop all timers */ + bus_space_write_4(iot, ioh, TIMER_TCON, 0); + + /* calc suitable prescaler value */ + calc_time_constant(hz); + + timer4_prescaler = prescaler; + timer4_reload_value = TIMER_FREQUENCY(pclk) / hz / prescaler; + timer4_mseccount = TIMER_FREQUENCY(pclk)/timer4_prescaler/1000 ; + + bus_space_write_4(iot, ioh, TIMER_TCNTB(4), + ((prescaler - 1) << 16) | (timer4_reload_value - 1)); + + printf("clock: hz=%d PCLK=%d prescaler=%d tc=%ld\n", + hz, pclk, prescaler, tc); + + irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, S3C24X0_INT_TIMER4, + S3C24X0_INT_TIMER4, 1, RF_ACTIVE); + if (!irq) + panic("Unable to allocate the clock irq handler.\n"); + + err = bus_setup_intr(dev, irq, INTR_TYPE_CLK | INTR_FAST, + clock_intr, NULL, NULL, &ihl); + if (err != 0) + panic("Unable to setup the clock irq handler.\n"); + + /* set prescaler1 */ + reg = bus_space_read_4(iot, ioh, TIMER_TCFG0); + bus_space_write_4(iot, ioh, TIMER_TCFG0, + (reg & ~0xff00) | ((prescaler-1) << 8)); + + /* divider 1/16 for ch #4 */ + reg = bus_space_read_4(iot, ioh, TIMER_TCFG1); + bus_space_write_4(iot, ioh, TIMER_TCFG1, + (reg & ~(TCFG1_MUX_MASK(4))) | + (TCFG1_MUX_DIV16 << TCFG1_MUX_SHIFT(4)) ); + + + /* start timers */ + reg = bus_space_read_4(iot, ioh, TIMER_TCON); + reg &= ~(TCON_MASK(4)); + + /* load the time constant */ + bus_space_write_4(iot, ioh, TIMER_TCON, reg | TCON_MANUALUPDATE(4)); + /* set auto reload and start */ + bus_space_write_4(iot, ioh, TIMER_TCON, reg | + TCON_AUTORELOAD(4) | TCON_START(4) ); + + s3c24x0_timer_timecounter.tc_frequency = TIMER_FREQUENCY(pclk) / + timer4_prescaler; + tc_init(&s3c24x0_timer_timecounter); +} + +/* + * DELAY: + * + * Delay for at least N microseconds. + */ +void +DELAY(int n) +{ + struct s3c24x0_softc *sc = (struct s3c24x0_softc *) s3c2xx0_softc; + int v0, v1, delta; + u_int ucnt; + + if (timer4_reload_value == 0) { + /* not initialized yet */ + while ( n-- > 0 ){ + int m; + + for (m = 0; m < 100; ++m ) + ; + } + return; + } + + /* read down counter */ + v0 = read_timer(sc); + + ucnt = usec_to_counter(n); + + while( ucnt > 0 ) { + v1 = read_timer(sc); + delta = v0 - v1; + if ( delta < 0 ) + delta += timer4_reload_value; + + if((u_int)delta < ucnt){ + ucnt -= (u_int)delta; + v0 = v1; + } + else { + ucnt = 0; + } + } +} + +void +cpu_startprofclock(void) +{ +} + +void +cpu_stopprofclock(void) +{ +} diff --git a/sys/arm/s3c2xx0/s3c24x0_machdep.c b/sys/arm/s3c2xx0/s3c24x0_machdep.c new file mode 100644 index 0000000..2c73842 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c24x0_machdep.c @@ -0,0 +1,467 @@ +/*- + * Copyright (c) 1994-1998 Mark Brinicombe. + * Copyright (c) 1994 Brini. + * All rights reserved. + * + * This code is derived from software written for Brini by Mark Brinicombe + * + * 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 Brini. + * 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 BRINI ``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 BRINI 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. + * + * RiscBSD kernel project + * + * machdep.c + * + * Machine dependant functions for kernel setup + * + * This file needs a lot of work. + * + * Created : 17/09/94 + */ + +#include "opt_msgbuf.h" +#include "opt_ddb.h" + +#include +__FBSDID("$FreeBSD$"); + +#define _ARM32_BUS_DMA_PRIVATE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* Page table for mapping proc0 zero page */ +#define KERNEL_PT_SYS 0 +#define KERNEL_PT_KERN 1 +#define KERNEL_PT_KERN_NUM 44 +/* L2 table for mapping after kernel */ +#define KERNEL_PT_AFKERNEL KERNEL_PT_KERN + KERNEL_PT_KERN_NUM +#define KERNEL_PT_AFKERNEL_NUM 5 + +/* this should be evenly divisable by PAGE_SIZE / L2_TABLE_SIZE_REAL (or 4) */ +#define NUM_KERNEL_PTS (KERNEL_PT_AFKERNEL + KERNEL_PT_AFKERNEL_NUM) + +/* Define various stack sizes in pages */ +#define IRQ_STACK_SIZE 1 +#define ABT_STACK_SIZE 1 +#define UND_STACK_SIZE 1 + +extern int s3c2410_pclk; + +extern u_int data_abort_handler_address; +extern u_int prefetch_abort_handler_address; +extern u_int undefined_handler_address; + +struct pv_addr kernel_pt_table[NUM_KERNEL_PTS]; + +extern void *_end; + +extern int *end; + +struct pcpu __pcpu; +struct pcpu *pcpup = &__pcpu; + +/* Physical and virtual addresses for some global pages */ + +vm_paddr_t phys_avail[10]; +vm_paddr_t dump_avail[4]; +vm_offset_t physical_pages; + +struct pv_addr systempage; +struct pv_addr msgbufpv; +struct pv_addr irqstack; +struct pv_addr undstack; +struct pv_addr abtstack; +struct pv_addr kernelstack; + +static struct trapframe proc0_tf; + +#define _A(a) ((a) & ~L1_S_OFFSET) +#define _S(s) (((s) + L1_S_SIZE - 1) & ~(L1_S_SIZE-1)) + +/* Static device mappings. */ +static const struct pmap_devmap s3c24x0_devmap[] = { + { + _A(S3C24X0_CLKMAN_BASE), + _A(S3C24X0_CLKMAN_PA_BASE), + _S(S3C24X0_CLKMAN_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_GPIO_BASE), + _A(S3C24X0_GPIO_PA_BASE), + _S(S3C2410_GPIO_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_IIC_BASE), + _A(S3C24X0_IIC_PA_BASE), + _S(S3C24X0_IIC_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_INTCTL_BASE), + _A(S3C24X0_INTCTL_PA_BASE), + _S(S3C24X0_INTCTL_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_LCDC_BASE), + _A(S3C24X0_LCDC_PA_BASE), + _S(S3C24X0_LCDC_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_SDI_BASE), + _A(S3C24X0_SDI_PA_BASE), + _S(S3C2410_SDI_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_UART0_BASE), + _A(S3C24X0_UART0_PA_BASE), + _S(S3C24X0_UART_PA_BASE(3) - S3C24X0_UART0_PA_BASE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_USBHC_BASE), + _A(S3C24X0_USBHC_PA_BASE), + _S(S3C24X0_USBHC_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + _A(S3C24X0_WDT_BASE), + _A(S3C24X0_WDT_PA_BASE), + _S(S3C24X0_WDT_SIZE), + VM_PROT_READ|VM_PROT_WRITE, + PTE_NOCACHE, + }, + { + 0, + 0, + 0, + 0, + 0, + } +}; + +#undef _A +#undef _S + +#define ioreg_read32(a) (*(volatile uint32_t *)(a)) +#define ioreg_write32(a,v) (*(volatile uint32_t *)(a)=(v)) + +#ifdef DDB +extern vm_offset_t ksym_start, ksym_end; +#endif + +struct arm32_dma_range s3c24x0_range = { + .dr_sysbase = 0, + .dr_busbase = 0, + .dr_len = 0, +}; + +struct arm32_dma_range * +bus_dma_get_range(void) +{ + + if (s3c24x0_range.dr_len == 0) { + s3c24x0_range.dr_sysbase = dump_avail[0]; + s3c24x0_range.dr_busbase = dump_avail[0]; + s3c24x0_range.dr_len = dump_avail[1] - dump_avail[0]; + } + return (&s3c24x0_range); +} + +int +bus_dma_get_range_nb(void) +{ + return (1); +} + +void * +initarm(void *arg, void *arg2) +{ + struct pv_addr kernel_l1pt; + int loop; + u_int l1pagetable; + vm_offset_t freemempos; + vm_offset_t afterkern; + vm_offset_t lastaddr; + + int i; + uint32_t memsize; + + i = 0; + + boothowto = 0; + + set_cpufuncs(); + cpufuncs.cf_sleep = s3c24x0_sleep; + lastaddr = fake_preload_metadata(); + + pcpu_init(pcpup, 0, sizeof(struct pcpu)); + PCPU_SET(curthread, &thread0); + +#define KERNEL_TEXT_BASE (KERNBASE) + freemempos = (lastaddr + PAGE_MASK) & ~PAGE_MASK; + /* Define a macro to simplify memory allocation */ +#define valloc_pages(var, np) \ + alloc_pages((var).pv_va, (np)); \ + (var).pv_pa = (var).pv_va + (KERNPHYSADDR - KERNVIRTADDR); + +#define alloc_pages(var, np) \ + (var) = freemempos; \ + freemempos += (np * PAGE_SIZE); \ + memset((char *)(var), 0, ((np) * PAGE_SIZE)); + + while (((freemempos - L1_TABLE_SIZE) & (L1_TABLE_SIZE - 1)) != 0) + freemempos += PAGE_SIZE; + valloc_pages(kernel_l1pt, L1_TABLE_SIZE / PAGE_SIZE); + for (loop = 0; loop < NUM_KERNEL_PTS; ++loop) { + if (!(loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL))) { + valloc_pages(kernel_pt_table[loop], + L2_TABLE_SIZE / PAGE_SIZE); + } else { + kernel_pt_table[loop].pv_va = freemempos - + (loop % (PAGE_SIZE / L2_TABLE_SIZE_REAL)) * + L2_TABLE_SIZE_REAL; + kernel_pt_table[loop].pv_pa = + kernel_pt_table[loop].pv_va - KERNVIRTADDR + + KERNPHYSADDR; + } + } + /* + * Allocate a page for the system page mapped to V0x00000000 + * This page will just contain the system vectors and can be + * shared by all processes. + */ + valloc_pages(systempage, 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, KSTACK_PAGES); + valloc_pages(msgbufpv, round_page(MSGBUF_SIZE) / PAGE_SIZE); + /* + * 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_va; + + /* Map the L2 pages tables in the L1 page table */ + pmap_link_l2pt(l1pagetable, ARM_VECTORS_HIGH, + &kernel_pt_table[KERNEL_PT_SYS]); + for (i = 0; i < KERNEL_PT_KERN_NUM; i++) + pmap_link_l2pt(l1pagetable, KERNBASE + i * L1_S_SIZE, + &kernel_pt_table[KERNEL_PT_KERN + i]); + pmap_map_chunk(l1pagetable, KERNBASE, PHYSADDR, + (((uint32_t)(lastaddr) - KERNBASE) + PAGE_SIZE) & ~(PAGE_SIZE - 1), + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + afterkern = round_page((lastaddr + L1_S_SIZE) & ~(L1_S_SIZE + - 1)); + for (i = 0; i < KERNEL_PT_AFKERNEL_NUM; i++) { + pmap_link_l2pt(l1pagetable, afterkern + i * L1_S_SIZE, + &kernel_pt_table[KERNEL_PT_AFKERNEL + i]); + } + + /* Map the vector page. */ + pmap_map_entry(l1pagetable, ARM_VECTORS_HIGH, systempage.pv_pa, + VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + /* 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, + KSTACK_PAGES * 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); + pmap_map_chunk(l1pagetable, msgbufpv.pv_va, msgbufpv.pv_pa, + MSGBUF_SIZE, VM_PROT_READ|VM_PROT_WRITE, PTE_CACHE); + + + 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); + } + + pmap_devmap_bootstrap(l1pagetable, s3c24x0_devmap); + + 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)); + + /* + * 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. + */ + + cpu_control(CPU_CONTROL_MMU_ENABLE, CPU_CONTROL_MMU_ENABLE); + 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); + + /* + * We must now clean the cache again.... + * Cleaning may be done by reading new data to displace any + * dirty data in the cache. This will have happened in setttb() + * but since we are boot strapping the addresses used for the read + * may have just been remapped and thus the cache could be out + * of sync. A re-clean after the switch will cure this. + * After booting there are no gross reloations of the kernel thus + * this problem will not occur after initarm(). + */ + cpu_idcache_wbinv_all(); + + /* Disable all peripheral interrupts */ + ioreg_write32(S3C24X0_INTCTL_BASE + INTCTL_INTMSK, ~0); + memsize = board_init(); + /* Find pclk for uart */ + switch(ioreg_read32(S3C24X0_GPIO_BASE + GPIO_GSTATUS1) >> 16) { + case 0x3241: + s3c2410_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL, + &s3c2410_pclk); + break; + case 0x3244: + s3c2440_clock_freq2(S3C24X0_CLKMAN_BASE, NULL, NULL, + &s3c2410_pclk); + break; + } + cninit(); + + /* Set stack for exception handlers */ + 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; + undefined_init(); + + proc_linkup(&proc0, &thread0); + thread0.td_kstack = kernelstack.pv_va; + thread0.td_pcb = (struct pcb *) + (thread0.td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1; + thread0.td_pcb->pcb_flags = 0; + thread0.td_frame = &proc0_tf; + pcpup->pc_curpcb = thread0.td_pcb; + + arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL); + + pmap_curmaxkvaddr = afterkern + 0x100000 * (KERNEL_PT_KERN_NUM - 1); + /* + * ARM_USE_SMALL_ALLOC uses dump_avail, so it must be filled before + * calling pmap_bootstrap. + */ + dump_avail[0] = PHYSADDR; + dump_avail[1] = PHYSADDR + memsize; + dump_avail[2] = 0; + dump_avail[3] = 0; + + pmap_bootstrap(freemempos, + KERNVIRTADDR + 3 * memsize, + &kernel_l1pt); + msgbufp = (void*)msgbufpv.pv_va; + msgbufinit(msgbufp, MSGBUF_SIZE); + mutex_init(); + + physmem = memsize / PAGE_SIZE; + + phys_avail[0] = virtual_avail - KERNVIRTADDR + KERNPHYSADDR; + phys_avail[1] = PHYSADDR + memsize; + phys_avail[2] = 0; + phys_avail[3] = 0; + + /* Do basic tuning, hz etc */ + init_param1(); + init_param2(physmem); + kdb_init(); + + return ((void *)(kernelstack.pv_va + USPACE_SVC_STACK_TOP - + sizeof(struct pcb))); +} diff --git a/sys/arm/s3c2xx0/s3c24x0reg.h b/sys/arm/s3c2xx0/s3c24x0reg.h new file mode 100644 index 0000000..3b8dc6e --- /dev/null +++ b/sys/arm/s3c2xx0/s3c24x0reg.h @@ -0,0 +1,672 @@ +/* $NetBSD: s3c24x0reg.h,v 1.7 2004/02/12 03:52:46 bsh Exp $ */ + +/*- + * Copyright (c) 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 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. + * + * $FreeBSD$ + */ + + +/* + * Samsung S3C2410X/2400 processor is ARM920T based integrated CPU + * + * Reference: + * S3C2410X User's Manual + * S3C2400 User's Manual + */ +#ifndef _ARM_S3C2XX0_S3C24X0REG_H_ +#define _ARM_S3C2XX0_S3C24X0REG_H_ + +/* common definitions for S3C2800, S3C2410 and S3C2440 */ +#include + +/* + * Map the device registers into kernel space + */ +#define S3C24X0_DEV_START 0x48000000 +#define S3C24X0_DEV_STOP 0x60000000 +#define S3C24X0_DEV_VA_OFFSET 0xD0000000 +#define S3C24X0_DEV_VA_SIZE (S3C24X0_DEV_STOP - S3C24X0_DEV_START) +#define S3C24X0_DEV_PA_TO_VA(x) (x - S3C24X0_DEV_START + S3C24X0_DEV_VA_OFFSET) + +/* + * Physical address of integrated peripherals + */ +#define S3C24X0_MEMCTL_PA_BASE 0x48000000 /* memory controller */ +#define S3C24X0_MEMCTL_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_MEMCTL_PA_BASE) +#define S3C24X0_USBHC_PA_BASE 0x49000000 /* USB Host controller */ +#define S3C24X0_USBHC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_USBHC_PA_BASE) +#define S3C24X0_INTCTL_PA_BASE 0x4a000000 /* Interrupt controller */ +#define S3C24X0_INTCTL_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_INTCTL_PA_BASE) +#define S3C24X0_INTCTL_SIZE 0x20 +#define S3C24X0_DMAC_PA_BASE 0x4b000000 +#define S3C24X0_DMAC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_DMAC_PA_BASE) +#define S3C24X0_DMAC_SIZE 0xe4 +#define S3C24X0_CLKMAN_PA_BASE 0x4c000000 /* clock & power management */ +#define S3C24X0_CLKMAN_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_CLKMAN_PA_BASE) +#define S3C24X0_LCDC_PA_BASE 0x4d000000 /* LCD controller */ +#define S3C24X0_LCDC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_LCDC_PA_BASE) +#define S3C24X0_LCDC_SIZE 0x64 +#define S3C24X0_NANDFC_PA_BASE 0x4e000000 /* NAND Flash controller */ +#define S3C24X0_NANDFC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_NANDFC_PA_BASE) +#define S3C24X0_UART0_PA_BASE 0x50000000 +#define S3C24X0_UART0_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_UART0_PA_BASE) +#define S3C24X0_UART_PA_BASE(n) (S3C24X0_UART0_PA_BASE+0x4000*(n)) +#define S3C24X0_UART_BASE(n) S3C24X0_DEV_PA_TO_VA(S3C24X0_UART_PA_BASE(n)) +#define S3C24X0_TIMER_PA_BASE 0x51000000 +#define S3C24X0_TIMER_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_TIMER_PA_BASE) +#define S3C24X0_USBDC_PA_BASE 0x5200140 +#define S3C24X0_USBDC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_USBDC_PA_BASE) +#define S3C24X0_USBDC_SIZE 0x130 +#define S3C24X0_WDT_PA_BASE 0x53000000 +#define S3C24X0_WDT_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_WDT_PA_BASE) +#define S3C24X0_IIC_PA_BASE 0x54000000 +#define S3C24X0_IIC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_IIC_PA_BASE) +#define S3C24X0_IIS_PA_BASE 0x55000000 +#define S3C24X0_IIS_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_IIS_PA_BASE) +#define S3C24X0_GPIO_PA_BASE 0x56000000 +#define S3C24X0_GPIO_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_GPIO_PA_BASE) +#define S3C24X0_ADC_PA_BASE 0x58000000 +#define S3C24X0_ADC_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_ADC_PA_BASE) +#define S3C24X0_SPI0_PA_BASE 0x59000000 +#define S3C24X0_SPI0_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SPI0_PA_BASE) +#define S3C24X0_SPI1_PA_BASE 0x59000020 +#define S3C24X0_SPI1_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SPI1_PA_BASE) +#define S3C24X0_SDI_PA_BASE 0x5a000000 /* SD Interface */ +#define S3C24X0_SDI_BASE S3C24X0_DEV_PA_TO_VA(S3C24X0_SDI_PA_BASE) + +#define S3C24X0_REG_BASE 0x48000000 +#define S3C24X0_REG_SIZE 0x13000000 + +/* Memory controller */ +#define MEMCTL_BWSCON 0x00 /* Bus width and wait status */ +#define BWSCON_DW0_SHIFT 1 /* bank0 is odd */ +#define BWSCON_BANK_SHIFT(n) (4*(n)) /* for bank 1..7 */ +#define BWSCON_DW_MASK 0x03 +#define BWSCON_DW_8 0 +#define BWSCON_DW_16 1 +#define BWSCON_DW_32 2 +#define BWSCON_WS 0x04 /* WAIT enable for the bank */ +#define BWSCON_ST 0x08 /* SRAM use UB/LB for the bank */ + +#define MEMCTL_BANKCON0 0x04 /* Boot ROM control */ +#define MEMCTL_BANKCON(n) (0x04+4*(n)) /* BANKn control */ +#define BANKCON_MT_SHIFT 15 +#define BANKCON_MT_ROM (0< + +struct s3c24x0_softc { + struct s3c2xx0_softc sc_sx; + + bus_space_handle_t sc_timer_ioh; /* Timer control registers */ +}; + +void s3c24x0_clock_freq(struct s3c2xx0_softc *); +void s3c2410_clock_freq2(vm_offset_t, int *, int *, int *); +void s3c2440_clock_freq2(vm_offset_t, int *, int *, int *); + +void s3c24x0_sleep(int); + +#endif /* _ARM_S3C24X0VAR_H_ */ diff --git a/sys/arm/s3c2xx0/s3c2xx0_space.c b/sys/arm/s3c2xx0/s3c2xx0_space.c new file mode 100644 index 0000000..2349672 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2xx0_space.c @@ -0,0 +1,252 @@ +/* $NetBSD: s3c2xx0_space.c,v 1.7 2005/11/24 13:08:32 yamt Exp $ */ + +/* + * Copyright (c) 2002 Fujitsu Component Limited + * Copyright (c) 2002 Genetec Corporation + * 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. Neither the name of The Fujitsu Component Limited nor 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 FUJITSU COMPONENT LIMITED AND 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 FUJITSU COMPONENT LIMITED OR 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. + */ +/* derived from sa11x0_io.c */ + +/* + * Copyright (c) 1997 Mark Brinicombe. + * Copyright (c) 1997 Causality Limited. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Ichiro FUKUHARA. + * + * 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. + * 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. + */ + +/* + * bus_space functions for Samsung S3C2800/2400/2410. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* Prototypes for all the bus_space structure functions */ +bs_protos(s3c2xx0); +bs_protos(generic); +bs_protos(generic_armv4); + +struct bus_space s3c2xx0_bs_tag = { + /* cookie */ + (void *) 0, + + /* mapping/unmapping */ + s3c2xx0_bs_map, + s3c2xx0_bs_unmap, + s3c2xx0_bs_subregion, + + /* allocation/deallocation */ + s3c2xx0_bs_alloc, /* not implemented */ + s3c2xx0_bs_free, /* not implemented */ + + /* barrier */ + s3c2xx0_bs_barrier, + + /* read (single) */ + generic_bs_r_1, + generic_armv4_bs_r_2, + generic_bs_r_4, + NULL, + + /* read multiple */ + generic_bs_rm_1, + generic_armv4_bs_rm_2, + generic_bs_rm_4, + NULL, + + /* read region */ + generic_bs_rr_1, + generic_armv4_bs_rr_2, + generic_bs_rr_4, + NULL, + + /* write (single) */ + generic_bs_w_1, + generic_armv4_bs_w_2, + generic_bs_w_4, + NULL, + + /* write multiple */ + generic_bs_wm_1, + generic_armv4_bs_wm_2, + generic_bs_wm_4, + NULL, + + /* write region */ + generic_bs_wr_1, + generic_armv4_bs_wr_2, + generic_bs_wr_4, + NULL, + + /* set multiple */ + NULL, + NULL, + NULL, + NULL, + + /* set region */ + generic_bs_sr_1, + generic_armv4_bs_sr_2, + NULL, + NULL, + + /* copy */ + NULL, + generic_armv4_bs_c_2, + NULL, + NULL, +}; + +int +s3c2xx0_bs_map(void *t, bus_addr_t bpa, bus_size_t size, + int flag, bus_space_handle_t * bshp) +{ + u_long startpa, endpa, pa; + vm_offset_t va; + pt_entry_t *pte; + const struct pmap_devmap *pd; + + if ((pd = pmap_devmap_find_pa(bpa, size)) != NULL) { + /* Device was statically mapped. */ + *bshp = pd->pd_va + (bpa - pd->pd_pa); + return 0; + } + + startpa = trunc_page(bpa); + endpa = round_page(bpa + size); + + /* XXX use extent manager to check duplicate mapping */ + + va = kmem_alloc(kernel_map, endpa - startpa); + if (!va) + return (ENOMEM); + + *bshp = (bus_space_handle_t) (va + (bpa - startpa)); + + for (pa = startpa; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { + pmap_kenter(va, pa); + pte = vtopte(va); + if ((flag & BUS_SPACE_MAP_CACHEABLE) == 0) + *pte &= ~L2_S_CACHE_MASK; + } + return (0); +} + +void +s3c2xx0_bs_unmap(void *t, bus_space_handle_t h, bus_size_t size) +{ + vm_offset_t va, endva; + + if (pmap_devmap_find_va((vm_offset_t)t, size) != NULL) { + /* Device was statically mapped; nothing to do. */ + return; + } + + endva = round_page((vm_offset_t)t + size); + va = trunc_page((vm_offset_t)t); + + while (va < endva) { + pmap_kremove(va); + va += PAGE_SIZE; + } + kmem_free(kernel_map, va, endva - va); +} + +int +s3c2xx0_bs_subregion(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t * nbshp) +{ + + *nbshp = bsh + offset; + return (0); +} + +void +s3c2xx0_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t len, int flags) +{ + + /* Nothing to do. */ +} + +int +s3c2xx0_bs_alloc(void *t, bus_addr_t rstart, bus_addr_t rend, + bus_size_t size, bus_size_t alignment, bus_size_t boundary, + int flags, bus_addr_t * bpap, bus_space_handle_t * bshp) +{ + + panic("s3c2xx0_io_bs_alloc(): not implemented\n"); +} + +void +s3c2xx0_bs_free(void *t, bus_space_handle_t bsh, bus_size_t size) +{ + panic("s3c2xx0_io_bs_free(): not implemented\n"); +} diff --git a/sys/arm/s3c2xx0/s3c2xx0board.h b/sys/arm/s3c2xx0/s3c2xx0board.h new file mode 100644 index 0000000..8a2c631 --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2xx0board.h @@ -0,0 +1,36 @@ +/*- + * Copyright (c) 2008 Warner Losh. 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. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 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. + */ + +/* $FreeBSD$ */ + +#ifndef _ARM_S3C2XX0_S3C2XX0BOARD_H_ +#define _ARM_S3C2XX0_S3C2XX0BOARD_H_ + +/* + * These routines are expected to be provided by the board files. + */ +long board_init(void); + +#endif /* _ARM_S3C2XX0_S3C2XX0BOARD_H_ */ diff --git a/sys/arm/s3c2xx0/s3c2xx0reg.h b/sys/arm/s3c2xx0/s3c2xx0reg.h new file mode 100644 index 0000000..627c3ca --- /dev/null +++ b/sys/arm/s3c2xx0/s3c2xx0reg.h @@ -0,0 +1,139 @@ +/* $NetBSD: s3c2xx0reg.h,v 1.4 2004/02/12 03:47:29 bsh Exp $ */ + +/*- + * Copyright (c) 2002, 2003 Fujitsu Component Limited + * Copyright (c) 2002, 2003 Genetec Corporation + * 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. Neither the name of The Fujitsu Component Limited nor 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 FUJITSU COMPONENT LIMITED AND 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 FUJITSU COMPONENT LIMITED OR 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. + * + * $FreeBSD$ + */ + + +/* + * Register definitions common to S3C2800 and S3C24[01]0 + */ +#ifndef _ARM_S3C2XX0_S3C2XX0REG_H_ +#define _ARM_S3C2XX0_S3C2XX0REG_H_ + +/* UART */ +/* + * S3C2800, 2410 and 2400 have a common built-in UART block. However, + * there are small diffs in bit position of some registers. + * Following definitions can be foune in s3c{2800,24x0}reg.h for + * that reason. + * + * ULCON_IR (Infra-red mode) + * ULCON_PARITY_SHIFT (Parity mode bit position) + * UMCON_AFC (Auto flow control) + * UMSTAT_DCTS (CTS change) + */ + +#define SSCOM_ULCON 0x00 /* UART line control */ +/* ULCON_PARITY_SHIFT and ULCON_IR is defined in s3c{2800,24x0}reg.h */ +#define ULCON_PARITY_NONE (0< +#include + +typedef enum { + CPU_S3C2410, + CPU_S3C2440, +} s3c2xx0_cpu; + +struct s3c2xx0_softc { + device_t sc_dev; + + s3c2xx0_cpu sc_cpu; + + bus_space_tag_t sc_iot; + + bus_space_handle_t sc_intctl_ioh; + bus_space_handle_t sc_clkman_ioh; /* Clock manager */ + bus_space_handle_t sc_gpio_ioh; /* GPIO */ + bus_space_handle_t sc_lcd_ioh; /* LCD */ + bus_space_handle_t sc_rtc_ioh; /* real time clock */ + bus_space_handle_t sc_mci_ioh; /* MMC/SD */ + bus_space_handle_t sc_iic_ioh; /* IIC */ + bus_space_handle_t sc_ohci_ioh; /* USB/OHCI */ + bus_space_handle_t sc_wdt_ioh; /* Watchdog Timer */ + + bus_dma_tag_t sc_dmat; + + /* clock frequency */ + int sc_fclk; /* CPU clock */ + int sc_hclk; /* AHB bus clock */ + int sc_pclk; /* peripheral clock */ + + struct rman s3c2xx0_irq_rman; + struct rman s3c2xx0_mem_rman; +}; + +struct s3c2xx0_ivar { + struct resource_list resources; +}; + +typedef void *s3c2xx0_chipset_tag_t; + +extern struct bus_space s3c2xx0_bs_tag; +extern struct s3c2xx0_softc *s3c2xx0_softc; +extern struct arm32_bus_dma_tag s3c2xx0_bus_dma; + +/* Platform needs to provide this */ +bus_dma_tag_t s3c2xx0_bus_dma_init(struct arm32_bus_dma_tag *); + +#endif /* _ARM_S3C2XX0VAR_H_ */ diff --git a/sys/arm/s3c2xx0/std.ln2410sbc b/sys/arm/s3c2xx0/std.ln2410sbc new file mode 100644 index 0000000..e066fc2 --- /dev/null +++ b/sys/arm/s3c2xx0/std.ln2410sbc @@ -0,0 +1,10 @@ +#$FreeBSD$ +include "../s3c2xx0/std.s3c2410" + +makeoptions KERNPHYSADDR=0x30408000 +makeoptions KERNVIRTADDR=0xc0408000 +options KERNPHYSADDR=0x30408000 +options KERNVIRTADDR=0xc0408000 +options PHYSADDR=0x30000000 +options STARTUP_PAGETABLE_ADDR=0x30800000 + diff --git a/sys/arm/s3c2xx0/std.s3c2410 b/sys/arm/s3c2xx0/std.s3c2410 new file mode 100644 index 0000000..31ec680 --- /dev/null +++ b/sys/arm/s3c2xx0/std.s3c2410 @@ -0,0 +1,6 @@ +# $FreeBSD$ + +files "../s3c2xx0/files.s3c2xx0" +cpu CPU_ARM9 + +makeoptions CONF_CFLAGS=-mcpu=arm920t diff --git a/sys/arm/s3c2xx0/uart_bus_s3c2410.c b/sys/arm/s3c2xx0/uart_bus_s3c2410.c new file mode 100644 index 0000000..974b3d9 --- /dev/null +++ b/sys/arm/s3c2xx0/uart_bus_s3c2410.c @@ -0,0 +1,59 @@ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "uart_if.h" + +static int uart_s3c2410_probe(device_t dev); + +static device_method_t uart_s3c2410_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uart_s3c2410_probe), + DEVMETHOD(device_attach, uart_bus_attach), + DEVMETHOD(device_detach, uart_bus_detach), + { 0, 0 } +}; + +static driver_t uart_s3c2410_driver = { + uart_driver_name, + uart_s3c2410_methods, + sizeof(struct uart_softc), +}; + +extern struct uart_class uart_s3c2410_class; +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; +static int +uart_s3c2410_probe(device_t dev) +{ + struct uart_devinfo *sysdev; + struct uart_softc *sc; + int unit; + + sc = device_get_softc(dev); + sc->sc_class = &uart_s3c2410_class; + + unit = device_get_unit(dev); + sysdev = SLIST_FIRST(&uart_sysdevs); + if (S3C24X0_UART_BASE(unit) == sysdev->bas.bsh) { + sc->sc_sysdev = sysdev; + bcopy(&sc->sc_sysdev->bas, &sc->sc_bas, sizeof(sc->sc_bas)); + } + return(uart_bus_probe(dev, 0, 0, 0, unit)); +} + +DRIVER_MODULE(uart, s3c24x0, uart_s3c2410_driver, uart_devclass, 0, 0); diff --git a/sys/arm/s3c2xx0/uart_cpu_s3c2410.c b/sys/arm/s3c2xx0/uart_cpu_s3c2410.c new file mode 100644 index 0000000..835604b --- /dev/null +++ b/sys/arm/s3c2xx0/uart_cpu_s3c2410.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2007 Andrew Turner + * 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. + * + * 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include +#include + +#include + +bus_space_tag_t uart_bus_space_io; +bus_space_tag_t uart_bus_space_mem; + +extern struct uart_ops uart_s3c2410_ops; + +vm_offset_t s3c2410_uart_vaddr; +unsigned int s3c2410_pclk; + +extern struct uart_class uart_s3c2410_class; + +int +uart_cpu_eqres(struct uart_bas *b1, struct uart_bas *b2) +{ + return ((b1->bsh == b2->bsh && b1->bst == b2->bst) ? 1 : 0); +} + +int +uart_cpu_getdev(int devtype, struct uart_devinfo *di) +{ + if (devtype != UART_DEV_CONSOLE) + return (ENXIO); + + di->ops = uart_getops(&uart_s3c2410_class); + di->bas.chan = 0; + di->bas.bst = &s3c2xx0_bs_tag; + di->bas.bsh = s3c2410_uart_vaddr; + di->bas.regshft = 0; + di->bas.rclk = s3c2410_pclk; + di->baudrate = 115200; + di->databits = 8; + di->stopbits = 1; + di->parity = UART_PARITY_NONE; + uart_bus_space_io = &s3c2xx0_bs_tag; + uart_bus_space_mem = NULL; + + return (0); +} diff --git a/sys/arm/s3c2xx0/uart_dev_s3c2410.c b/sys/arm/s3c2xx0/uart_dev_s3c2410.c new file mode 100644 index 0000000..9bd9c4b --- /dev/null +++ b/sys/arm/s3c2xx0/uart_dev_s3c2410.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2003 Marcel Moolenaar + * Copyright (c) 2007-2009 Andrew Turner + * 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. + * + * 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 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 +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "uart_if.h" + +/* Finds the subirq from the parent */ +#define get_sub_irq(parent, offset) \ + ((parent == S3C24X0_INT_UART0) ? S3C24X0_SUBIRQ_MIN + offset : \ + ((parent == S3C24X0_INT_UART1) ? S3C24X0_SUBIRQ_MIN + 3 + offset : \ + S3C24X0_SUBIRQ_MIN + 6 + offset)) +#define RX_OFF 0 +#define TX_OFF 1 +#define ERR_OFF 2 + +extern unsigned int s3c2410_pclk; + +static int sscomspeed(long, long); +static int s3c24x0_uart_param(struct uart_bas *, int, int, int, int); + +/* + * Low-level UART interface. + */ +static int s3c2410_probe(struct uart_bas *bas); +static void s3c2410_init(struct uart_bas *bas, int, int, int, int); +static void s3c2410_term(struct uart_bas *bas); +static void s3c2410_putc(struct uart_bas *bas, int); +static int s3c2410_rxready(struct uart_bas *bas); +static int s3c2410_getc(struct uart_bas *bas, struct mtx *mtx); + +extern SLIST_HEAD(uart_devinfo_list, uart_devinfo) uart_sysdevs; + +static int +sscomspeed(long speed, long frequency) +{ + int x; + + if (speed <= 0 || frequency <= 0) + return -1; + x = (frequency / 16) / speed; + return x-1; +} + +static int +s3c24x0_uart_param(struct uart_bas *bas, int baudrate, int databits, + int stopbits, int parity) +{ + int brd, ulcon; + + ulcon = 0; + + switch(databits) { + case 5: + ulcon |= ULCON_LENGTH_5; + break; + case 6: + ulcon |= ULCON_LENGTH_6; + break; + case 7: + ulcon |= ULCON_LENGTH_7; + break; + case 8: + ulcon |= ULCON_LENGTH_8; + break; + default: + return (EINVAL); + } + + switch (parity) { + case UART_PARITY_NONE: + ulcon |= ULCON_PARITY_NONE; + break; + case UART_PARITY_ODD: + ulcon |= ULCON_PARITY_ODD; + break; + case UART_PARITY_EVEN: + ulcon |= ULCON_PARITY_EVEN; + break; + case UART_PARITY_MARK: + case UART_PARITY_SPACE: + default: + return (EINVAL); + } + + if (stopbits == 2) + ulcon |= ULCON_STOP; + + uart_setreg(bas, SSCOM_ULCON, ulcon); + + brd = sscomspeed(baudrate, bas->rclk); + uart_setreg(bas, SSCOM_UBRDIV, brd); + + return (0); +} + +struct uart_ops uart_s3c2410_ops = { + .probe = s3c2410_probe, + .init = s3c2410_init, + .term = s3c2410_term, + .putc = s3c2410_putc, + .rxready = s3c2410_rxready, + .getc = s3c2410_getc, +}; + +static int +s3c2410_probe(struct uart_bas *bas) +{ + return (0); +} + +static void +s3c2410_init(struct uart_bas *bas, int baudrate, int databits, int stopbits, + int parity) +{ + if (bas->rclk == 0) + bas->rclk = s3c2410_pclk; + KASSERT(bas->rclk != 0, ("s3c2410_init: Invalid rclk")); + + uart_setreg(bas, SSCOM_UCON, 0); + uart_setreg(bas, SSCOM_UFCON, + UFCON_TXTRIGGER_8 | UFCON_RXTRIGGER_8 | + UFCON_TXFIFO_RESET | UFCON_RXFIFO_RESET | + UFCON_FIFO_ENABLE); + s3c24x0_uart_param(bas, baudrate, databits, stopbits, parity); + + /* Enable UART. */ + uart_setreg(bas, SSCOM_UCON, UCON_TXMODE_INT | UCON_RXMODE_INT | + UCON_TOINT); + uart_setreg(bas, SSCOM_UMCON, UMCON_RTS); +} + +static void +s3c2410_term(struct uart_bas *bas) +{ + /* XXX */ +} + +static void +s3c2410_putc(struct uart_bas *bas, int c) +{ + while ((bus_space_read_4(bas->bst, bas->bsh, SSCOM_UFSTAT) & + UFSTAT_TXFULL) == UFSTAT_TXFULL) + continue; + + uart_setreg(bas, SSCOM_UTXH, c); +} + +static int +s3c2410_rxready(struct uart_bas *bas) +{ + return ((uart_getreg(bas, SSCOM_UTRSTAT) & UTRSTAT_RXREADY) == + UTRSTAT_RXREADY); +} + +static int +s3c2410_getc(struct uart_bas *bas, struct mtx *mtx) +{ + while (!sscom_rxrdy(bas->bst, bas->bsh)) + continue; + + return sscom_getc(bas->bst, bas->bsh); +} + +static int s3c2410_bus_probe(struct uart_softc *sc); +static int s3c2410_bus_attach(struct uart_softc *sc); +static int s3c2410_bus_flush(struct uart_softc *, int); +static int s3c2410_bus_getsig(struct uart_softc *); +static int s3c2410_bus_ioctl(struct uart_softc *, int, intptr_t); +static int s3c2410_bus_ipend(struct uart_softc *); +static int s3c2410_bus_param(struct uart_softc *, int, int, int, int); +static int s3c2410_bus_receive(struct uart_softc *); +static int s3c2410_bus_setsig(struct uart_softc *, int); +static int s3c2410_bus_transmit(struct uart_softc *); + +static kobj_method_t s3c2410_methods[] = { + KOBJMETHOD(uart_probe, s3c2410_bus_probe), + KOBJMETHOD(uart_attach, s3c2410_bus_attach), + KOBJMETHOD(uart_flush, s3c2410_bus_flush), + KOBJMETHOD(uart_getsig, s3c2410_bus_getsig), + KOBJMETHOD(uart_ioctl, s3c2410_bus_ioctl), + KOBJMETHOD(uart_ipend, s3c2410_bus_ipend), + KOBJMETHOD(uart_param, s3c2410_bus_param), + KOBJMETHOD(uart_receive, s3c2410_bus_receive), + KOBJMETHOD(uart_setsig, s3c2410_bus_setsig), + KOBJMETHOD(uart_transmit, s3c2410_bus_transmit), + + {0, 0 } +}; + +int +s3c2410_bus_probe(struct uart_softc *sc) +{ + return (0); +} + +static int +s3c2410_bus_attach(struct uart_softc *sc) +{ + uintptr_t irq; + + switch(s3c2xx0_softc->sc_cpu) { + case CPU_S3C2410: + sc->sc_txfifosz = 16; + sc->sc_rxfifosz = 16; + break; + case CPU_S3C2440: + sc->sc_txfifosz = 64; + sc->sc_rxfifosz = 64; + break; + default: + return (ENXIO); + } + + sc->sc_hwiflow = 0; + sc->sc_hwoflow = 0; + + irq = rman_get_start(sc->sc_ires); + arm_unmask_irq(irq); + arm_unmask_irq(get_sub_irq(irq, RX_OFF)); + arm_unmask_irq(get_sub_irq(irq, TX_OFF)); + arm_unmask_irq(get_sub_irq(irq, ERR_OFF)); + + return (0); +} + +static int +s3c2410_bus_transmit(struct uart_softc *sc) +{ + uintptr_t irq; + + uart_lock(sc->sc_hwmtx); + + for (int i = 0; i < sc->sc_txdatasz; i++) { + s3c2410_putc(&sc->sc_bas, sc->sc_txbuf[i]); + uart_barrier(&sc->sc_bas); + } + + sc->sc_txbusy = 1; + + uart_unlock(sc->sc_hwmtx); + + irq = rman_get_start(sc->sc_ires); + arm_unmask_irq(get_sub_irq(irq, TX_OFF)); + + return (0); +} + +static int +s3c2410_bus_setsig(struct uart_softc *sc, int sig) +{ + return (0); +} + +static int +s3c2410_bus_receive(struct uart_softc *sc) +{ + + uart_rx_put(sc, uart_getreg(&sc->sc_bas, SSCOM_URXH)); + return (0); +} + +static int +s3c2410_bus_param(struct uart_softc *sc, int baudrate, int databits, + int stopbits, int parity) +{ + int error; + + if (sc->sc_bas.rclk == 0) + sc->sc_bas.rclk = s3c2410_pclk; + KASSERT(sc->sc_bas.rclk != 0, ("s3c2410_init: Invalid rclk")); + + uart_lock(sc->sc_hwmtx); + error = s3c24x0_uart_param(&sc->sc_bas, baudrate, databits, stopbits, + parity); + uart_unlock(sc->sc_hwmtx); + + return (error); +} + +static int +s3c2410_bus_ipend(struct uart_softc *sc) +{ + uint32_t ufstat, txmask, rxmask; + uintptr_t irq; + int ipend = 0; + + uart_lock(sc->sc_hwmtx); + ufstat = bus_space_read_4(sc->sc_bas.bst, sc->sc_bas.bsh, SSCOM_UFSTAT); + uart_unlock(sc->sc_hwmtx); + + txmask = rxmask = 0; + switch (s3c2xx0_softc->sc_cpu) { + case CPU_S3C2410: + txmask = UFSTAT_TXCOUNT; + rxmask = UFSTAT_RXCOUNT; + break; + case CPU_S3C2440: + txmask = S3C2440_UFSTAT_TXCOUNT; + rxmask = S3C2440_UFSTAT_RXCOUNT; + break; + } + if ((ufstat & txmask) == 0) { + if (sc->sc_txbusy != 0) + ipend |= SER_INT_TXIDLE; + irq = rman_get_start(sc->sc_ires); + arm_mask_irq(get_sub_irq(irq, TX_OFF)); + } + if ((ufstat & rxmask) > 0) { + ipend |= SER_INT_RXREADY; + } + + return (ipend); +} + +static int +s3c2410_bus_flush(struct uart_softc *sc, int what) +{ + return (0); +} + +static int +s3c2410_bus_getsig(struct uart_softc *sc) +{ + return (0); +} + +static int +s3c2410_bus_ioctl(struct uart_softc *sc, int request, intptr_t data) +{ + return (EINVAL); +} + +struct uart_class uart_s3c2410_class = { + "s3c2410 class", + s3c2410_methods, + 1, + .uc_ops = &uart_s3c2410_ops, + .uc_range = 8, + .uc_rclk = 0, +}; diff --git a/sys/arm/s3c2xx0/uart_dev_s3c2410.h b/sys/arm/s3c2xx0/uart_dev_s3c2410.h new file mode 100644 index 0000000..5479796 --- /dev/null +++ b/sys/arm/s3c2xx0/uart_dev_s3c2410.h @@ -0,0 +1,88 @@ +/* $NetBSD: sscom_var.h,v 1.5 2003/08/04 12:28:49 bsh Exp $ */ + +/*- + * Copyright (c) 2002, 2003 Fujitsu Component Limited + * Copyright (c) 2002, 2003 Genetec Corporation + * 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. Neither the name of The Fujitsu Component Limited nor 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 FUJITSU COMPONENT LIMITED AND 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 FUJITSU COMPONENT LIMITED OR 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. + */ +/* derived from sys/dev/ic/comvar.h */ + +/*- + * Copyright (c) 1996 Christopher G. Demetriou. 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 Christopher G. Demetriou + * for the NetBSD Project. + * 4. The name of the author may not 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 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. + * + * $FreeBSD$ + */ + +#ifndef _ARM_S3C2XX0_SSCOM_VAR_H +#define _ARM_S3C2XX0_SSCOM_VAR_H + + +/* Hardware flag masks */ +#define SSCOM_HW_FLOW 0x02 +#define SSCOM_HW_DEV_OK 0x04 +#define SSCOM_HW_CONSOLE 0x08 +#define SSCOM_HW_KGDB 0x10 +#define SSCOM_HW_TXINT 0x20 +#define SSCOM_HW_RXINT 0x40 + +/* Buffer size for character buffer */ +#define SSCOM_RING_SIZE 2048 + +#define sscom_rxrdy(iot,ioh) \ + (bus_space_read_1((iot), (ioh), SSCOM_UTRSTAT) & UTRSTAT_RXREADY) +#define sscom_getc(iot,ioh) bus_space_read_1((iot), (ioh), SSCOM_URXH) +#define sscom_geterr(iot,ioh) bus_space_read_1((iot), (ioh), SSCOM_UERSTAT) + +#endif /* _ARM_S3C2XX0_SSCOM_VAR_H */ -- cgit v1.1