All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kuo-Jung Su <dantesu@gmail.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	i.mitsyanko@samsung.com, Blue Swirl <blauwirbel@gmail.com>,
	Paul Brook <paul@codesourcery.com>,
	Kuo-Jung Su <dantesu@faraday-tech.com>,
	Andreas <afaerber@suse.de>,
	fred.konrad@greensocs.com
Subject: [Qemu-devel] [PATCH v9 13/24] hw/arm: add FTI2C010 I2C controller support
Date: Mon, 25 Mar 2013 20:09:49 +0800	[thread overview]
Message-ID: <1364213400-10266-14-git-send-email-dantesu@gmail.com> (raw)
In-Reply-To: <1364213400-10266-1-git-send-email-dantesu@gmail.com>

From: Kuo-Jung Su <dantesu@faraday-tech.com>

The FTI2C010 is a simple I2C master controller.

Signed-off-by: Kuo-Jung Su <dantesu@faraday-tech.com>
---
 hw/arm/Makefile.objs    |    2 +-
 hw/arm/ftplat_a369soc.c |    6 ++
 hw/fti2c010.c           |  224 +++++++++++++++++++++++++++++++++++++++++++++++
 hw/fti2c010.h           |   74 ++++++++++++++++
 4 files changed, 305 insertions(+), 1 deletion(-)
 create mode 100644 hw/fti2c010.c
 create mode 100644 hw/fti2c010.h

diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 8fe0f67..2bb67f7 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -25,7 +25,7 @@ obj-y += strongarm.o
 obj-y += imx_serial.o imx_ccm.o imx_timer.o imx_avic.o
 obj-$(CONFIG_KVM) += kvm/arm_gic.o
 obj-y += ftintc020.o ftahbc020.o ftddrii030.o ftpwmtmr010.o ftwdt010.o \
-                ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o
+                ftrtc011.o ftdmac020.o ftapbbrg020.o ftnandc021.o fti2c010.o
 
 obj-y := $(addprefix ../,$(obj-y))
 
diff --git a/hw/arm/ftplat_a369soc.c b/hw/arm/ftplat_a369soc.c
index e057629..b6e82ad 100644
--- a/hw/arm/ftplat_a369soc.c
+++ b/hw/arm/ftplat_a369soc.c
@@ -200,6 +200,12 @@ static void a369soc_chip_init(FaradaySoCState *s)
     req = qdev_get_gpio_in(s->hdma[0], 15);
     qdev_connect_gpio_out(s->hdma[0], 15, ack);
     qdev_connect_gpio_out(ds, 0, req);
+
+    /* fti2c010 */
+    ds = sysbus_create_simple("fti2c010", 0x92900000, s->pic[51]);
+    s->i2c[0] = ds;
+    ds = sysbus_create_simple("fti2c010", 0x92A00000, s->pic[52]);
+    s->i2c[1] = ds;
 }
 
 static void a369soc_realize(DeviceState *dev, Error **errp)
diff --git a/hw/fti2c010.c b/hw/fti2c010.c
new file mode 100644
index 0000000..5b5606b
--- /dev/null
+++ b/hw/fti2c010.c
@@ -0,0 +1,224 @@
+/*
+ * QEMU model of the FTI2C010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#include "hw/sysbus.h"
+#include "hw/i2c.h"
+#include "sysemu/sysemu.h"
+
+#include "hw/fti2c010.h"
+
+#define I2C_RD  1
+#define I2C_WR  0
+
+#define TYPE_FTI2C010   "fti2c010"
+
+typedef struct Fti2c010State {
+    /*< private >*/
+    SysBusDevice parent;
+
+    /*< public >*/
+    MemoryRegion mmio;
+
+    qemu_irq irq;
+    i2c_bus *bus;
+
+    bool     recv;    /* I2C RD = true; I2C WR = false */
+
+    /* HW register cache */
+    uint32_t cr;
+    uint32_t sr;
+    uint32_t cdr;
+    uint32_t dr;
+    uint32_t tgsr;
+} Fti2c010State;
+
+#define FTI2C010(obj) \
+    OBJECT_CHECK(Fti2c010State, obj, TYPE_FTI2C010)
+
+static void
+fti2c010_update_irq(Fti2c010State *s)
+{
+    uint32_t sr = extract32(s->sr, 4, 8);
+    uint32_t cr = extract32(s->cr, 8, 8);
+    qemu_set_irq(s->irq, (sr & cr) ? 1 : 0);
+}
+
+static uint64_t
+fti2c010_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    Fti2c010State *s = FTI2C010(opaque);
+    uint32_t ret = 0;
+
+    switch (addr) {
+    case REG_CR:
+        return s->cr;
+    case REG_SR:
+        ret = s->sr | (i2c_bus_busy(s->bus) ? SR_BB : 0);
+        s->sr &= 0xfffff00f;    /* clear RC status bits */
+        fti2c010_update_irq(s);
+        break;
+    case REG_CDR:
+        return s->cdr;
+    case REG_DR:
+        return s->dr;
+    case REG_TGSR:
+        return s->tgsr;
+    case REG_BMR:
+        return 0x00000003;  /* Slave mode: SCL=1, SDA=1 */
+    case REG_REVR:
+        return 0x00011000;  /* REV. 1.10.0 */
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "fti2c010: undefined memory access@%#" HWADDR_PRIx "\n", addr);
+        break;
+    }
+
+    return ret;
+}
+
+static void
+fti2c010_mem_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    Fti2c010State *s = FTI2C010(opaque);
+
+    switch (addr) {
+    case REG_CR:
+        s->cr = (uint32_t)val;
+        if (s->cr & CR_SLAVE_MASK) {
+            qemu_log_mask(LOG_UNIMP,
+                "fti2c010: slave mask deteced!\n");
+            s->cr &= ~CR_SLAVE_MASK;
+        }
+        if (s->cr & CR_I2CRST) {
+            s->dr = 0;
+            s->sr = 0;
+        } else if ((s->cr & CR_MASTER_EN) && (s->cr & CR_TBEN)) {
+            s->sr &= ~SR_ACK;
+            if (s->cr & CR_START) {
+                s->recv = !!(s->dr & I2C_RD);
+                if (!i2c_start_transfer(s->bus,
+                                        extract32(s->dr, 1, 7),
+                                        s->recv)) {
+                    s->sr |= SR_DT | SR_ACK;
+                } else {
+                    s->sr &= ~SR_DT;
+                }
+            } else {
+                if (s->recv) {
+                    s->dr = i2c_recv(s->bus);
+                    s->sr |= SR_DR;
+                } else {
+                    i2c_send(s->bus, (uint8_t)s->dr);
+                    s->sr |= SR_DT;
+                }
+                if (s->cr & CR_NACK) {
+                    i2c_nack(s->bus);
+                }
+                s->sr |= SR_ACK;
+                if (s->cr & CR_STOP) {
+                    i2c_end_transfer(s->bus);
+                }
+            }
+        }
+        s->cr &= ~(CR_TBEN | CR_I2CRST);
+        fti2c010_update_irq(s);
+        break;
+    case REG_CDR:
+        s->cdr = (uint32_t)val & 0x3ffff;
+        break;
+    case REG_DR:
+        s->dr  = (uint32_t)val & 0xff;
+        break;
+    case REG_TGSR:
+        s->tgsr = (uint32_t)val & 0x1fff;
+        break;
+        /* slave mode is useless to QEMU, ignore it. */
+    case REG_SAR:
+        qemu_log_mask(LOG_UNIMP,
+            "fti2c010: undefined memory access@%#" HWADDR_PRIx "\n", addr);
+        break;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+            "fti2c010: undefined memory access@%#" HWADDR_PRIx "\n", addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps mmio_ops = {
+    .read  = fti2c010_mem_read,
+    .write = fti2c010_mem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 4
+    }
+};
+
+static void fti2c010_reset(DeviceState *ds)
+{
+    Fti2c010State *s = FTI2C010(SYS_BUS_DEVICE(ds));
+
+    s->cr   = 0;
+    s->sr   = 0;
+    s->cdr  = 0;
+    s->tgsr = TGSR_TSR(1) | TGSR_GSR(1);
+
+    qemu_set_irq(s->irq, 0);
+}
+
+static void fti2c010_realize(DeviceState *dev, Error **errp)
+{
+    Fti2c010State *s = FTI2C010(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+
+    s->bus = i2c_init_bus(&sbd->qdev, "i2c");
+
+    memory_region_init_io(&s->mmio, &mmio_ops, s, TYPE_FTI2C010, 0x1000);
+    sysbus_init_mmio(sbd, &s->mmio);
+    sysbus_init_irq(sbd, &s->irq);
+}
+
+static const VMStateDescription vmstate_fti2c010 = {
+    .name = TYPE_FTI2C010,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .minimum_version_id_old = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(cr, Fti2c010State),
+        VMSTATE_UINT32(sr, Fti2c010State),
+        VMSTATE_UINT32(cdr, Fti2c010State),
+        VMSTATE_UINT32(dr, Fti2c010State),
+        VMSTATE_UINT32(tgsr, Fti2c010State),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void fti2c010_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd    = &vmstate_fti2c010;
+    dc->reset   = fti2c010_reset;
+    dc->realize = fti2c010_realize;
+    dc->no_user = 1;
+}
+
+static const TypeInfo fti2c010_info = {
+    .name           = TYPE_FTI2C010,
+    .parent         = TYPE_SYS_BUS_DEVICE,
+    .instance_size  = sizeof(Fti2c010State),
+    .class_init     = fti2c010_class_init,
+};
+
+static void fti2c010_register_types(void)
+{
+    type_register_static(&fti2c010_info);
+}
+
+type_init(fti2c010_register_types)
diff --git a/hw/fti2c010.h b/hw/fti2c010.h
new file mode 100644
index 0000000..1c69eb2
--- /dev/null
+++ b/hw/fti2c010.h
@@ -0,0 +1,74 @@
+/*
+ * QEMU model of the FTI2C010 Controller
+ *
+ * Copyright (C) 2012 Faraday Technology
+ * Written by Dante Su <dantesu@faraday-tech.com>
+ *
+ * This file is licensed under GNU GPL v2+.
+ */
+
+#ifndef HW_ARM_FTI2C010_H
+#define HW_ARM_FTI2C010_H
+
+#include "qemu/bitops.h"
+
+/*
+ * FTI2C010 registers
+ */
+#define REG_CR              0x00    /* control register */
+#define REG_SR              0x04    /* status register */
+#define REG_CDR             0x08    /* clock division register */
+#define REG_DR              0x0C    /* data register */
+#define REG_SAR             0x10    /* slave address register */
+#define REG_TGSR            0x14    /* time & glitch suppression register */
+#define REG_BMR             0x18    /* bus monitor register */
+#define REG_REVR            0x30    /* revision register */
+
+/*
+ * REG_CR
+ */
+#define CR_STARTIEN         0x4000  /* start condition (slave only) */
+#define CR_ALIEN            0x2000  /* Arbitration lose (master only) */
+#define CR_SAMIEN           0x1000  /* slave address match (slave only) */
+#define CR_STOPIEN          0x800   /* stop condition (slave only) */
+#define CR_BERRIEN          0x400   /* NACK response (master only) */
+#define CR_DRIEN            0x200   /* data receive */
+#define CR_DTIEN            0x100   /* data transmit */
+#define CR_TBEN             0x80    /* transfer byte enable */
+#define CR_NACK             0x40    /* acknowledge mode: 0=ACK, 1=NACK */
+#define CR_STOP             0x20    /* stop (master only) */
+#define CR_START            0x10    /* start (master only) */
+#define CR_GCEN             0x8     /* general call message (slave only) */
+#define CR_SCLEN            0x4     /* enable clock (master only) */
+#define CR_I2CEN            0x2     /* enable I2C */
+#define CR_I2CRST           0x1     /* reset I2C */
+
+#define CR_SLAVE_MASK       (CR_GCEN | CR_SAMIEN | CR_STOPIEN | CR_STARTIEN)
+
+#define CR_MASTER_INTR      (CR_ALIEN | CR_BERRIEN | CR_DRIEN | CR_DTIEN)
+#define CR_MASTER_EN        (CR_SCLEN | CR_I2CEN)
+#define CR_MASTER_MODE      (CR_MASTER_INTR | CR_MASTER_EN)
+
+/*
+ * REG_SR
+ */
+#define SR_START            0x800
+#define SR_AL               0x400
+#define SR_GC               0x200
+#define SR_SAM              0x100
+#define SR_STOP             0x80
+#define SR_BERR             0x40
+#define SR_DR               0x20    /* received one new data byte */
+#define SR_DT               0x10    /* trandmitted one data byte */
+#define SR_BB               0x8     /* set when i2c bus is busy */
+#define SR_I2CB             0x4     /* set when fti2c010 is busy */
+#define SR_ACK              0x2
+#define SR_RW               0x1
+
+/*
+ * REG_TGSR
+ */
+#define TGSR_TSR(x)         ((x) & 0x3f)            /* setup/hold time */
+#define TGSR_GSR(x)         (((x) & 0x07) << 10)    /* glitch suppression */
+
+#endif
-- 
1.7.9.5

  parent reply	other threads:[~2013-03-25 12:27 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-25 12:09 [Qemu-devel] [PATCH v9 00/24] hw/arm: add Faraday A369 SoC platform support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 01/24] target-arm: add Faraday ARMv5TE processors support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 02/24] hw/arm: add Faraday a369 SoC platform support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 03/24] hw/arm: add FTINTC020 interrupt controller support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 04/24] hw/arm: add FTAHBC020 AHB " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 05/24] hw/arm: add FTDDRII030 DDRII " Kuo-Jung Su
2013-03-28  0:09   ` Peter Crosthwaite
2013-03-28  3:24     ` Kuo-Jung Su
2013-03-28  3:58       ` Peter Crosthwaite
2013-03-28  5:28         ` Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 06/24] hw/arm: add FTPWMTMR010 timer support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 07/24] hw/arm: add FTWDT010 watchdog " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 08/24] hw/arm: add FTRTC011 RTC " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 09/24] tests: add QTest for FTRTC011 Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 10/24] hw/arm: add FTDMAC020 AHB DMA support Kuo-Jung Su
2013-03-29  0:22   ` Peter Crosthwaite
2013-03-29  7:23     ` Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 11/24] hw/arm: add FTAPBBRG020 APB " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 12/24] hw/arm: add FTNANDC021 nand flash controller support Kuo-Jung Su
2013-03-25 12:09 ` Kuo-Jung Su [this message]
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 14/24] hw: Add AudioCodecClass for wm87xx audio class abstration Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 15/24] hw: add WM8731 audio codec support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 16/24] The FTSSP010 is a multi-function synchronous serial port interface controller which supports SSP, SPI, I2S, AC97 and SPDIF Kuo-Jung Su
2013-03-31  2:39   ` Peter Crosthwaite
2013-04-01  1:18     ` Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 17/24] qemu/bitops.h: add the bit ordering reversal functions Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 18/24] hw/arm: add FTGMAC100 1Gbps ethernet support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 19/24] hw/arm: add FTLCDC200 LCD controller support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 20/24] hw/arm: add FTTSC010 touchscreen " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 21/24] hw/arm: add FTSDC010 MMC/SD " Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 22/24] hw/arm: add FTMAC110 10/100Mbps ethernet support Kuo-Jung Su
2013-03-25 12:09 ` [Qemu-devel] [PATCH v9 23/24] hw/arm: add FTTMR010 timer support Kuo-Jung Su
2013-03-25 12:10 ` [Qemu-devel] [PATCH v9 24/24] hw/arm: add FTSPI020 SPI flash controller support Kuo-Jung Su
2013-03-29  0:02   ` Peter Crosthwaite
2013-03-29  7:15     ` Kuo-Jung Su

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=1364213400-10266-14-git-send-email-dantesu@gmail.com \
    --to=dantesu@gmail.com \
    --cc=afaerber@suse.de \
    --cc=blauwirbel@gmail.com \
    --cc=dantesu@faraday-tech.com \
    --cc=fred.konrad@greensocs.com \
    --cc=i.mitsyanko@samsung.com \
    --cc=paul@codesourcery.com \
    --cc=peter.maydell@linaro.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.