From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lx3Ip-0006wu-VV for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:05:40 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lx3Io-0006vz-Q3 for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:05:39 -0400 Received: from [199.232.76.173] (port=59454 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lx3Io-0006vs-Mk for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:05:38 -0400 Received: from flounder.pepperfish.net ([87.237.62.181]:54319) by monty-python.gnu.org with esmtps (TLS-1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Lx3In-0004yh-5Y for qemu-devel@nongnu.org; Thu, 23 Apr 2009 14:05:37 -0400 Received: from [10.112.102.2] (helo=jennifer.kylikki.org) by flounder.pepperfish.net with esmtps (Exim 4.69 #1 (Debian)) id 1Lx3Ik-0004r5-Lt for ; Thu, 23 Apr 2009 19:05:34 +0100 Received: from derik.kyllikki.org ([192.168.7.20] helo=derik) by jennifer.kylikki.org with esmtp (Exim 4.63) (envelope-from ) id 1Lx3Il-0006KL-2z for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:05:35 +0100 Received: from vince by derik with local (Exim 4.69) (envelope-from ) id 1Lx3Il-00048F-10 for qemu-devel@nongnu.org; Thu, 23 Apr 2009 19:05:35 +0100 Date: Thu, 23 Apr 2009 19:05:35 +0100 From: Vincent Sanders Subject: [Qemu-devel] [PATCH 9/16] S3C General Purpose IO Message-ID: <20090423180534.GL4629@derik> References: <20090423171503.GC4629@derik> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20090423171503.GC4629@derik> List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org S3C GPIO support Signed-off-by: Vincent Sanders --- s3c24xx_gpio.c | 190 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff -urN qemusvnclean/hw/s3c24xx_gpio.c qemusvnpatches/hw/s3c24xx_gpio.c --- qemusvnclean/hw/s3c24xx_gpio.c 1970-01-01 01:00:00.000000000 +0100 +++ qemusvnpatches/hw/s3c24xx_gpio.c 2009-04-23 17:07:45.000000000 +0100 @@ -0,0 +1,190 @@ +/* hw/s3c24xx_gpio.c + * + * Samsung S3C24XX GPIO emulation (mostly for E-INT) + * + * 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 "s3c24xx.h" + +#define S3C_GPIO_GPECON (0x40) +#define S3C_GPIO_GPEDAT (0x44) +#define S3C_GPIO_GPEUP (0x48) + +#define S3C_GPIO_EINT_MASK (0xA4) +#define S3C_GPIO_EINT_PEND (0xA8) +#define S3C_GPIO_GSTATUS0 (0xAC) +#define S3C_GPIO_GSTATUS1 (0xB0) +#define S3C_GPIO_GSTATUS2 (0xB4) +#define S3C_GPIO_GSTATUS3 (0xB8) +#define S3C_GPIO_GSTATUS4 (0xBC) + + +#define GPRN(r) (r>>2) +#define GPR(P) soc->gpio_reg[P>>2] + +static void +s3c24xx_gpio_propogate_eint(S3CState *soc) +{ + uint32_t ints, i; + + ints = GPR(S3C_GPIO_EINT_PEND) & ~GPR(S3C_GPIO_EINT_MASK); + + /* EINT0 - EINT3 are INT0 - INT3 */ + for (i=0; i < 4; ++i) + qemu_set_irq(soc->irqs[i], (ints&(1<irqs[4], (ints & 0xf0)?1:0); + + /* EINT8 - EINT23 are INT5 */ + qemu_set_irq(soc->irqs[5], (ints & 0x00ffff00)?1:0); +} + +static uint32_t +gpio_con_to_mask(uint32_t con) +{ + uint32_t mask = 0x0; + int bit; + + for (bit = 0; bit < 16; bit++) { + if (((con >> (bit*2)) & 0x3) == 0x01) + mask |= 1 << bit; + } + + return mask; +} + +static void +s3c24xx_gpio_write_f(void *opaque, target_phys_addr_t addr_, uint32_t value) +{ + S3CState *soc = (S3CState *)opaque; + int addr = (addr_ >> 2) & 0x3f; + + if (addr < 0 || addr > 47) + addr = 47; + + if (addr == (S3C_GPIO_EINT_MASK>>2)) + value &= ~0xf; /* cannot mask EINT0-EINT3 */ + + if (addr == (S3C_GPIO_EINT_PEND>>2)) { + soc->gpio_reg[addr] &= ~value; + } else { + if (addr < (0x80/4) && (addr_ & 0xf) == 0x04) { + uint32_t mask = gpio_con_to_mask(soc->gpio_reg[addr-1]); + + value &= mask; + + soc->gpio_reg[addr] &= ~mask; + soc->gpio_reg[addr] |= value; + } else + soc->gpio_reg[addr] = value; + } + + if ((addr == (S3C_GPIO_EINT_MASK)>>2) || + (addr == (S3C_GPIO_EINT_PEND)>>2)) { + /* A write to the EINT regs leads us to determine the interrupts to + * propagate + */ + s3c24xx_gpio_propogate_eint(soc); + } +} + +static uint32_t +s3c24xx_gpio_read_f(void *opaque, target_phys_addr_t addr_) +{ + S3CState *soc = (S3CState *)opaque; + uint32_t addr = (addr_ >> 2); + uint32_t ret; + + if (addr > GPRN(S3C_GPIO_GSTATUS4)) + addr = GPRN(S3C_GPIO_GSTATUS4); + + ret = soc->gpio_reg[addr]; + + if (addr == GPRN(S3C_GPIO_GPEDAT)) { + /* IIC pins are special function pins on GPE14 and GPE15. If GPE is is + * in input mode make the IIC lines appear to be pulled high. This is + * neccissary because OS i2c drivers use this to ensure the I2C bus is + * clear. + */ + if ((GPR(S3C_GPIO_GPECON) & (3<<28)) == 0) + ret |= 1 << 14; + + if ((GPR(S3C_GPIO_GPECON) & (3<<30)) == 0) + ret |= 1 << 15; + } + + return ret; +} + + +static CPUReadMemoryFunc *s3c24xx_gpio_read[] = { + &s3c24xx_gpio_read_f, + &s3c24xx_gpio_read_f, + &s3c24xx_gpio_read_f, +}; + +static CPUWriteMemoryFunc *s3c24xx_gpio_write[] = { + &s3c24xx_gpio_write_f, + &s3c24xx_gpio_write_f, + &s3c24xx_gpio_write_f, +}; + +static void +s3c24xx_gpio_irq_handler(void *opaque, int n, int level) +{ + S3CState *soc = (S3CState *)opaque; + if (level) + GPR(S3C_GPIO_EINT_PEND) |= (1<eirqs = qemu_allocate_irqs(s3c24xx_gpio_irq_handler, soc, 24); +} -- Regards Vincent http://www.kyllikki.org/