From: Vincent Sanders <vince@kyllikki.org>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] [PATCH 7/16] S3C serial peripheral
Date: Thu, 23 Apr 2009 19:00:27 +0100 [thread overview]
Message-ID: <20090423180027.GI4629@derik> (raw)
In-Reply-To: <20090423171503.GC4629@derik>
S3C serial peripheral.
Signed-off-by: Vincent Sanders <vince@simtec.co.uk>
---
s3c24xx_serial.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 266 insertions(+)
diff -urN qemusvnclean/hw/s3c24xx_serial.c qemusvnpatches/hw/s3c24xx_serial.c
--- qemusvnclean/hw/s3c24xx_serial.c 1970-01-01 01:00:00.000000000 +0100
+++ qemusvnpatches/hw/s3c24xx_serial.c 2009-04-23 17:06:16.000000000 +0100
@@ -0,0 +1,266 @@
+/* hw/s3c24xx_serial.c
+ *
+ * Samsung S3C24XX Serial block
+ *
+ * Copyright 2006, 2007 Daniel Silverstone and Vincent Sanders
+ *
+ * This file is under the terms of the GNU General Public
+ * License Version 2
+ */
+
+#include "hw.h"
+#include "qemu-char.h"
+#include "sysemu.h"
+
+#include "s3c24xx.h"
+
+/* S3C24XX serial port registers */
+
+/* port spacing */
+#define S3C_SERIAL_PORT_STRIDE 0x4000
+
+/* Line control RW WORD */
+#define S3C_SERIAL_ULCON 0x00
+/* General control RW WORD */
+#define S3C_SERIAL_UCON 0x04
+/* Fifo control RW WORD */
+#define S3C_SERIAL_UFCON 0x08
+/* Modem control RW WORD */
+#define S3C_SERIAL_UMCON 0x0C
+/* TX/RX Status RO WORD */
+#define S3C_SERIAL_UTRSTAT 0x10
+/* Receive Error Status RO WORD */
+#define S3C_SERIAL_UERSTAT 0x14
+/* FiFo Status RO WORD */
+#define S3C_SERIAL_UFSTAT 0x18
+/* Modem Status RO WORD */
+#define S3C_SERIAL_UMSTAT 0x1C
+/* TX buffer WR BYTE */
+#define S3C_SERIAL_UTXH 0x20
+/* RX buffer RO BYTE */
+#define S3C_SERIAL_URXH 0x24
+/* BAUD Divisor RW WORD */
+#define S3C_SERIAL_UBRDIV 0x28
+
+/* S3C24XX serial port state */
+typedef struct {
+ uint32_t ulcon, ucon, ufcon, umcon, ubrdiv;
+ unsigned char rx_byte;
+ /* Byte is available to be read */
+ unsigned int rx_available : 1;
+ CharDriverState *chr;
+ int port;
+ qemu_irq tx_irq;
+ qemu_irq rx_irq;
+ qemu_irq tx_level;
+ qemu_irq rx_level;
+} s3c24xx_serial_dev;
+
+static void
+s3c24xx_serial_write_f(void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ s3c24xx_serial_dev *s = opaque;
+ int reg = addr & 0x3f;
+
+ switch(reg) {
+ case S3C_SERIAL_ULCON:
+ s->ulcon = value;
+ break;
+
+ case S3C_SERIAL_UCON:
+ s->ucon = value;
+ if( s->ucon & 1<<9 ) {
+ qemu_set_irq(s->tx_level, 1);
+ } else {
+ qemu_set_irq(s->tx_level, 0);
+ }
+ if( !(s->ucon & 1<<8) ) {
+ qemu_set_irq(s->rx_level, 0);
+ }
+ break;
+
+ case S3C_SERIAL_UFCON:
+ s->ufcon = (value & ~6);
+ break;
+
+ case S3C_SERIAL_UMCON:
+ s->umcon = value;
+ break;
+
+ case S3C_SERIAL_UTRSTAT:
+ break;
+
+ case S3C_SERIAL_UERSTAT:
+ break;
+
+ case S3C_SERIAL_UFSTAT:
+ break;
+
+ case S3C_SERIAL_UMSTAT:
+ break;
+
+ case S3C_SERIAL_UTXH: {
+ unsigned char ch = value & 0xff;
+ if (s->chr && ((s->ucon & 1<<5)==0))
+ qemu_chr_write(s->chr, &ch, 1);
+ else {
+ s->rx_byte = ch;
+ s->rx_available = 1;
+ if( s->ucon & 1<<8 ) {
+ qemu_set_irq(s->rx_level, 1);
+ } else {
+ qemu_set_irq(s->rx_irq, 1);
+ }
+ }
+ if( s->ucon & 1<<9 ) {
+ qemu_set_irq(s->tx_level, 1);
+ } else {
+ qemu_set_irq(s->tx_irq, 1);
+ }
+ break;
+ }
+
+ case S3C_SERIAL_URXH:
+ break;
+
+ case S3C_SERIAL_UBRDIV:
+ s->ubrdiv = value;
+ break;
+
+ default:
+ break;
+ };
+}
+
+static uint32_t
+s3c24xx_serial_read_f(void *opaque, target_phys_addr_t addr)
+{
+ s3c24xx_serial_dev *s = opaque;
+ int reg = addr & 0x3f;
+
+ switch(reg) {
+ case S3C_SERIAL_ULCON:
+ return s->ulcon;
+
+ case S3C_SERIAL_UCON:
+ return s->ucon;
+
+ case S3C_SERIAL_UFCON:
+ return s->ufcon & ~0x8; /* bit 3 is reserved, must be zero */
+
+ case S3C_SERIAL_UMCON:
+ return s->umcon & 0x11; /* Rest are reserved, must be zero */
+
+ case S3C_SERIAL_UTRSTAT:
+ return 6 | s->rx_available; /* TX always clear, RX when available */
+
+ case S3C_SERIAL_UERSTAT:
+ return 0; /* Later, break detect comes in here */
+
+ case S3C_SERIAL_UFSTAT:
+ return s->rx_available; /* TXFIFO, always empty, RXFIFO 0 or 1 bytes */
+
+ case S3C_SERIAL_UMSTAT:
+ return 0;
+
+ case S3C_SERIAL_UTXH:
+ return 0;
+
+ case S3C_SERIAL_URXH:
+ s->rx_available = 0;
+ if( s->ucon & 1<<8 ) {
+ qemu_set_irq(s->rx_level, 0);
+ }
+ return s->rx_byte;
+
+ case S3C_SERIAL_UBRDIV:
+ return s->ubrdiv;
+
+ default:
+ return 0;
+ };
+}
+
+static CPUReadMemoryFunc *s3c24xx_serial_read[] = {
+ &s3c24xx_serial_read_f,
+ &s3c24xx_serial_read_f,
+ &s3c24xx_serial_read_f,
+};
+
+static CPUWriteMemoryFunc *s3c24xx_serial_write[] = {
+ &s3c24xx_serial_write_f,
+ &s3c24xx_serial_write_f,
+ &s3c24xx_serial_write_f,
+};
+
+
+static void s3c24xx_serial_event(void *opaque, int event)
+{
+}
+
+static int
+s3c24xx_serial_can_receive(void *opaque)
+{
+ s3c24xx_serial_dev *s = opaque;
+
+ /* If there's no byte to be read, we can receive a new one */
+ return !s->rx_available;
+}
+
+static void
+s3c24xx_serial_receive(void *opaque, const uint8_t *buf, int size)
+{
+ s3c24xx_serial_dev *s = opaque;
+ s->rx_byte = buf[0];
+ s->rx_available = 1;
+ if ( s->ucon & 1 << 8 ) {
+ qemu_set_irq(s->rx_level, 1);
+ } else {
+ /* Is there something we can do here to ensure it's just a pulse ? */
+ qemu_set_irq(s->rx_irq, 1);
+ }
+}
+
+/* Create a S3C serial port, the port implementation is common to all
+ * current s3c devices only differing in the I/O base address and number of
+ * ports.
+ */
+void
+s3c24xx_serial_init(S3CState *soc, int port, target_phys_addr_t base_addr)
+{
+ /* Initialise a serial port at the given port address */
+ s3c24xx_serial_dev *s;
+ int serial_io;
+
+ s = qemu_mallocz(sizeof(s3c24xx_serial_dev));
+ if (!s)
+ return;
+
+ /* initialise serial port context */
+ s->chr = serial_hds[port];
+ s->ulcon = 0;
+ s->ucon = 0;
+ s->ufcon = 0;
+ s->umcon = 0;
+ s->ubrdiv = 0;
+ s->port = port;
+ s->rx_available = 0;
+ s->tx_irq = soc->irqs[32 + (port * 3) + 1];
+ s->rx_irq = soc->irqs[32 + (port * 3)];
+ s->tx_level = soc->irqs[64 + 32 + (port * 3) + 1];
+ s->rx_level = soc->irqs[64 + 32 + (port * 3)];
+
+ /* Prepare our MMIO tag */
+ serial_io = cpu_register_io_memory(0, s3c24xx_serial_read, s3c24xx_serial_write, s);
+ /* Register the region with the tag */
+ cpu_register_physical_memory(base_addr + (port * S3C_SERIAL_PORT_STRIDE), 44, serial_io);
+
+ if (s->chr) {
+ /* If the port is present add to the character device's IO handlers. */
+ qemu_chr_add_handlers(s->chr,
+ s3c24xx_serial_can_receive,
+ s3c24xx_serial_receive,
+ s3c24xx_serial_event,
+ s);
+ }
+}
--
Regards Vincent
http://www.kyllikki.org/
next prev parent reply other threads:[~2009-04-23 18:00 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-04-23 17:15 [Qemu-devel] [PATCH 0/16] ARM Add S3C SOC core, drivers and boards Vincent Sanders
2009-04-23 17:45 ` [Qemu-devel] [PATCH 1/16] ARM Add ARM 920T identifiers Vincent Sanders
2009-04-30 16:08 ` Paul Brook
2009-05-23 16:50 ` Vincent Sanders
2009-05-24 18:31 ` Paul Brook
2009-05-26 9:39 ` Vincent Sanders
2009-05-26 9:42 ` Laurent Desnogues
2009-05-26 9:56 ` Jamie Lokier
2009-05-26 10:08 ` Laurent Desnogues
2009-05-26 11:29 ` Jamie Lokier
2009-05-26 11:46 ` Laurent Desnogues
2009-05-26 10:16 ` Paul Brook
2009-05-26 11:18 ` Vincent Sanders
2009-04-23 17:48 ` [Qemu-devel] [PATCH 2/16] Add s3c SOC header Vincent Sanders
2009-04-23 17:50 ` [Qemu-devel] [PATCH 3/16] S3C SDRAM memory controller Peripheral Vincent Sanders
2009-04-23 17:52 ` [Qemu-devel] [PATCH 4/16] S3C irq controller Vincent Sanders
2009-04-23 17:58 ` [Qemu-devel] [PATCH 05/16] S3C Clock controller peripheral Vincent Sanders
2009-04-23 18:00 ` Vincent Sanders [this message]
2009-04-23 18:02 ` [Qemu-devel] [PATCH 6/16] S3C Timers Vincent Sanders
2009-04-23 18:04 ` [Qemu-devel] [PATCH 8/16] S3C Real Time Clock Vincent Sanders
2009-04-23 18:05 ` [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Vincent Sanders
2009-04-23 18:07 ` [Qemu-devel] [PATCH 10/16] S3C I2C peripheral Vincent Sanders
2009-04-23 18:08 ` [Qemu-devel] [PATCH 11/16] S3C LCD display Vincent Sanders
2009-04-23 18:09 ` [Qemu-devel] [PATCH 12/16] S3C NAND controller Vincent Sanders
2009-04-23 18:11 ` [Qemu-devel] [PATCH 13/16] S3C2410 SOC implementation Vincent Sanders
2009-04-23 18:14 ` [Qemu-devel] [PATCH 14/16] S3C2440 SOC impementation Vincent Sanders
2009-04-23 18:15 ` [Qemu-devel] [PATCH 15/16] Add S3C SOC files to Makefile Vincent Sanders
2009-04-23 18:17 ` [Qemu-devel] [PATCH 16/16] Add two boards which use S3C2410 SOC Vincent Sanders
2009-04-25 12:44 ` Jean-Christophe PLAGNIOL-VILLARD
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20090423180027.GI4629@derik \
--to=vince@kyllikki.org \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.