qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] Forward-porting RTC  device for eppc500 ?
@ 2019-03-02 11:21 Andrew Randrianasulu
  2019-03-02 16:59 ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
       [not found] ` <201903022144.45897.randrianasulu@gmail.com>
  0 siblings, 2 replies; 5+ messages in thread
From: Andrew Randrianasulu @ 2019-03-02 11:21 UTC (permalink / raw)
  To: Amit.Tomar, qemu-ppc@nongnu.org, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 15391 bytes --]

Hello, all!

I stumbled upon this email from 2015 (trying to understand why my emulated 
ppce500 machine failed to set clock correctly:

https://lists.gnu.org/archive/html/qemu-devel/2015-01/msg02642.html

Now, after some quite blind trial-and-error I applied ('forward-ported') this 
patch to qemu git commit 0f6a6d5db853c0cbe438c1831c70710bfb6530ee without 
actually porting it to new qemu device abstraction model.

It seems to work!

But because I copy-pasted patch from web archive of list - some strings 
become "address@hidden", I hope I corrected them right?

---------------------------
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 52acb7cf39..a560971f0c 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -8,6 +8,8 @@ include usb.mak
 CONFIG_PPC4XX=y
 CONFIG_M48T59=y
 CONFIG_SERIAL=y
+CONFIG_MPC_I2C=y
+CONFIG_DS1338=y
 CONFIG_I8257=y
 CONFIG_OPENPIC=y
 CONFIG_PPCE500_PCI=y
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index cecee486f7..55473fc6b2 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -9,5 +9,6 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
 common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
 common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o
+common-obj-$(CONFIG_MPC_I2C) += mpc_i2c.o
 obj-$(CONFIG_OMAP) += omap_i2c.o
 obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
new file mode 100644
index 0000000000..54d7a9aabd
--- /dev/null
+++ b/hw/i2c/mpc_i2c.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Amit Tomar, <Amit.Tomar@freescale.com>
+ *
+ * Description:
+ * This file is derived from IMX I2C controller,
+ * by Jean-Christophe DUBOIS .
+ *
+ * Thanks to Scott Wood and Alexander Graf for their kind help on this.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 or later,
+ * as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qemu/osdep.h"
+// #include "hw/i2c/imx_i2c.h"
+#include "hw/i2c/i2c.h"
+#include "qemu/log.h"
+#include "hw/sysbus.h"
+
+/* #define DEBUG_I2C */
+
+#ifdef DEBUG_I2C
+#define DPRINTF(fmt, ...)              \
+    do { fprintf(stderr, "mpc_i2c[%s]: " fmt, __func__, ## __VA_ARGS__); \
+    } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+#define TYPE_MPC_I2C "mpc-i2c"
+#define MPC_I2C(obj) \
+    OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C)
+
+#define MPC_I2C_ADR   0x00
+#define MPC_I2C_FDR   0x04
+#define MPC_I2C_CR    0x08
+#define MPC_I2C_SR    0x0c
+#define MPC_I2C_DR    0x10
+#define MPC_I2C_DFSRR 0x14
+
+#define CCR_MEN  (1<<7)
+#define CCR_MIEN (1<<6)
+#define CCR_MSTA (1<<5)
+#define CCR_MTX  (1<<4)
+#define CCR_TXAK (1<<3)
+#define CCR_RSTA (1<<2)
+#define CCR_BCST (1<<0)
+
+#define CSR_MCF  (1<<7)
+#define CSR_MAAS (1<<6)
+#define CSR_MBB  (1<<5)
+#define CSR_MAL  (1<<4)
+#define CSR_SRW  (1<<2)
+#define CSR_MIF  (1<<1)
+#define CSR_RXAK (1<<0)
+
+#define CADR_MASK 0xFE
+#define CFDR_MASK 0x3F
+#define CCR_MASK  0xFC
+#define CSR_MASK  0xED
+#define CDR_MASK  0xFF
+
+#define CYCLE_RESET 0xFF
+
+typedef struct MPCI2CState {
+    SysBusDevice parent_obj;
+
+    I2CBus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint8_t address;
+    uint8_t adr;
+    uint8_t fdr;
+    uint8_t cr;
+    uint8_t sr;
+    uint8_t dr;
+    uint8_t dfssr;
+} MPCI2CState;
+
+static bool mpc_i2c_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MEN;
+}
+
+static bool mpc_i2c_is_master(MPCI2CState *s)
+{
+    return s->cr & CCR_MSTA;
+}
+
+static bool mpc_i2c_direction_is_tx(MPCI2CState *s)
+{
+    return s->cr & CCR_MTX;
+}
+
+static bool mpc_i2c_irq_pending(MPCI2CState *s)
+{
+    return s->sr & CSR_MIF;
+}
+
+static bool mpc_i2c_irq_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MIEN;
+}
+
+static void mpc_i2c_reset(DeviceState *dev)
+{
+    MPCI2CState *i2c = MPC_I2C(dev);
+
+    i2c->address = 0xFF;
+    i2c->adr = 0x00;
+    i2c->fdr = 0x00;
+    i2c->cr =  0x00;
+    i2c->sr =  0x81;
+    i2c->dr =  0x00;
+}
+
+static void mpc_i2c_irq(MPCI2CState *s)
+{
+    bool irq_active = false;
+
+    if (mpc_i2c_is_enabled(s) && mpc_i2c_irq_is_enabled(s)
+                              && mpc_i2c_irq_pending(s)) {
+        irq_active = true;
+    }
+
+    if (irq_active) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static void mpc_i2c_soft_reset(MPCI2CState *s)
+{
+    /* This is a soft reset. ADR is preserved during soft resets */
+    uint8_t adr = s->adr;
+    mpc_i2c_reset(DEVICE(s));
+    s->adr = adr;
+}
+
+static void  mpc_i2c_address_send(MPCI2CState *s)
+{
+    /* if returns non zero slave address is not right */
+    if (i2c_start_transfer(s->bus, s->dr >> 1, s->dr & (0x01))) {
+        s->sr |= CSR_RXAK;
+    } else {
+        s->address = s->dr;
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_send(MPCI2CState *s)
+{
+    if (i2c_send(s->bus, s->dr)) {
+        /* End of transfer */
+        s->sr |= CSR_RXAK;
+        i2c_end_transfer(s->bus);
+    } else {
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_recive(MPCI2CState *s)
+{
+    int ret;
+    /* get the next byte */
+    ret = i2c_recv(s->bus);
+    if (ret >= 0) {
+        s->sr |= CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |= CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    } else {
+        DPRINTF("read failed for device");
+        ret = 0xff;
+    }
+    s->dr = ret;
+}
+
+static uint64_t mpc_i2c_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MPCI2CState *s = opaque;
+    uint8_t value;
+
+    switch (addr) {
+    case MPC_I2C_ADR:
+        value = s->adr;
+        break;
+    case MPC_I2C_FDR:
+        value = s->fdr;
+        break;
+    case MPC_I2C_CR:
+        value = s->cr;
+        break;
+    case MPC_I2C_SR:
+        value = s->sr;
+        break;
+    case MPC_I2C_DR:
+        value = s->dr;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (mpc_i2c_direction_is_tx(s)) {
+                DPRINTF("MTX is set not in recv mode\n");
+            } else {
+                mpc_i2c_data_recive(s);
+            }
+        }
+        break;
+    default:
+        value = 0;
+        DPRINTF("ERROR: Bad read addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__,
+                                         addr, value);
+    return (uint64_t)value;
+}
+
+static void mpc_i2c_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    MPCI2CState *s = opaque;
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", __func__,
+                                             addr, value);
+    switch (addr) {
+    case MPC_I2C_ADR:
+        s->adr = value & CADR_MASK;
+        break;
+    case MPC_I2C_FDR:
+        s->fdr = value & CFDR_MASK;
+        break;
+    case MPC_I2C_CR:
+        if (mpc_i2c_is_enabled(s) && ((value & CCR_MEN) == 0)) {
+            mpc_i2c_soft_reset(s);
+            break;
+        }
+        /* normal write */
+        s->cr = value & CCR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            /* set the bus to busy after master is set as per RM */
+            s->sr |= CSR_MBB;
+        } else {
+            /* bus is not busy anymore */
+            s->sr &= ~CSR_MBB;
+            /* Reset the address for fresh write/read cycle */
+        if (s->address != CYCLE_RESET) {
+            i2c_end_transfer(s->bus);
+            s->address = CYCLE_RESET;
+            }
+        }
+        /* For restart end the onging transfer */
+        if (s->cr & CCR_RSTA) {
+            if (s->address != CYCLE_RESET) {
+                s->address = CYCLE_RESET;
+                i2c_end_transfer(s->bus);
+                s->cr &= ~CCR_RSTA;
+            }
+        }
+        break;
+    case MPC_I2C_SR:
+        s->sr = value & CSR_MASK;
+        /* Lower the interrupt */
+        if (!(s->sr & CSR_MIF) || !(s->sr & CSR_MAL)) {
+            mpc_i2c_irq(s);
+        }
+        break;
+    case MPC_I2C_DR:
+        /* if the device is not enabled, nothing to do */
+        if (!mpc_i2c_is_enabled(s)) {
+            break;
+        }
+        s->dr = value & CDR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (s->address == CYCLE_RESET) {
+                mpc_i2c_address_send(s);
+            } else {
+                mpc_i2c_data_send(s);
+            }
+        }
+        break;
+    case MPC_I2C_DFSRR:
+        s->dfssr = value;
+        break;
+    default:
+        DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .read =  mpc_i2c_read,
+    .write =  mpc_i2c_write,
+    .valid.max_access_size = 1,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription mpc_i2c_vmstate = {
+    .name = TYPE_MPC_I2C,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(address, MPCI2CState),
+        VMSTATE_UINT8(adr, MPCI2CState),
+        VMSTATE_UINT8(fdr, MPCI2CState),
+        VMSTATE_UINT8(cr, MPCI2CState),
+        VMSTATE_UINT8(sr, MPCI2CState),
+        VMSTATE_UINT8(dr, MPCI2CState),
+        VMSTATE_UINT8(dfssr, MPCI2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mpc_i2c_realize(DeviceState *dev, Error **errp)
+{
+    
+    MPCI2CState  *i2c = MPC_I2C(dev);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
+    memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
+                          "mpc-i2c", 0x14);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
+    i2c->bus = i2c_init_bus(DEVICE(dev), "i2c");
+}
+
+static void mpc_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd  = &mpc_i2c_vmstate ;
+    dc->reset = mpc_i2c_reset;
+    dc->realize = mpc_i2c_realize;
+    dc->desc = "MPC I2C Controller";
+}
+
+static const TypeInfo mpc_i2c_type_info = {
+    .name          = TYPE_MPC_I2C,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MPCI2CState),
+    .class_init    = mpc_i2c_class_init,
+};
+
+static void mpc_i2c_register_types(void)
+{
+    type_register_static(&mpc_i2c_type_info);
+}
+
+type_init(mpc_i2c_register_types)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 7553f674c9..c8e8563f95 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -42,6 +42,7 @@
 #include "qemu/error-report.h"
 #include "hw/platform-bus.h"
 #include "hw/net/fsl_etsec/etsec.h"
+#include "hw/i2c/i2c.h"
 
 #define EPAPR_MAGIC                (0x45504150)
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
@@ -63,7 +64,10 @@
 #define MPC8544_PCI_REGS_SIZE      0x1000ULL
 #define MPC8544_UTIL_OFFSET        0xe0000ULL
 #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
+#define MPC8544_I2C_REGS_OFFSET    0x3000ULL
 #define MPC8XXX_GPIO_IRQ           47
+#define MPC8544_I2C_IRQ            43
+#define RTC_REGS_OFFSET            0x68
 
 struct boot_info
 {
@@ -161,6 +165,39 @@ static void create_dt_mpc8xxx_gpio(void *fdt, const char 
*soc, const char *mpic)
     g_free(poweroff);
 }
 
+static void dt_rtc_create(void *fdt, const char *i2c, const char *alias)
+{
+    int offset = RTC_REGS_OFFSET;
+
+    gchar *rtc = g_strdup_printf("%s/rtc@%"PRIx32, i2c, offset);
+    qemu_fdt_add_subnode(fdt, rtc);
+    qemu_fdt_setprop_string(fdt, rtc, "compatible", "pericom,pt7c4338");
+    qemu_fdt_setprop_cells(fdt, rtc, "reg", offset);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, rtc);
+
+    g_free(rtc);
+}
+
+static void dt_i2c_create(void *fdt, const char *soc, const char *mpic,
+                             const char *alias)
+{
+    hwaddr mmio0 = MPC8544_I2C_REGS_OFFSET;
+    int irq0 = MPC8544_I2C_IRQ;
+
+    gchar *i2c = g_strdup_printf("%s/i2c@%"PRIx64, soc, mmio0);
+    qemu_fdt_add_subnode(fdt, i2c);
+    qemu_fdt_setprop_string(fdt, i2c, "device_type", "i2c");
+    qemu_fdt_setprop_string(fdt, i2c, "compatible", "fsl-i2c");
+    qemu_fdt_setprop_cells(fdt, i2c, "reg", mmio0, 0x14);
+    qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0);
+    qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2);
+    qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c);
+
+    g_free(i2c);
+}
+
+
 typedef struct PlatformDevtreeData {
     void *fdt;
     const char *mpic;
@@ -463,6 +500,12 @@ static int ppce500_load_device_tree(PPCE500MachineState 
*pms,
         dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
                          soc, mpic, "serial0", 0, true);
     }
+    
+    /* i2c */
+    dt_i2c_create(fdt, soc, mpic, "i2c");
+
+    dt_rtc_create(fdt, "i2c", "rtc");
+
 
     gutil = g_strdup_printf("%s/global-utilities@%llx", soc,
                             MPC8544_UTIL_OFFSET);
@@ -812,6 +855,7 @@ void ppce500_init(MachineState *machine)
     MemoryRegion *ccsr_addr_space;
     SysBusDevice *s;
     PPCE500CCSRState *ccsr;
+    I2CBus *i2c;
 
     irqs = g_new0(IrqLines, smp_cpus);
     for (i = 0; i < smp_cpus; i++) {
@@ -887,6 +931,16 @@ void ppce500_init(MachineState *machine)
                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
                        serial_hd(1), DEVICE_BIG_ENDIAN);
     }
+        /* I2C */
+    dev = qdev_create(NULL, "mpc-i2c");
+    s = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ));
+    memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET,
+                                sysbus_mmio_get_region(s, 0));
+    i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", RTC_REGS_OFFSET);
+
 
     /* General Utility device */
     dev = qdev_create(NULL, "mpc8544-guts");

----------------

Test kernel I used:
http://www.xenosoft.de/linux-image-4.20.12-X1000_X5000.tar.gz
(unpack and use uImage)

guest@slax:/dev/shm/qemu$ ppc64-softmmu/qemu-system-ppc64 -M ppce500 -cpu 
e5500 -kernel /mnt/sdb1/PPC-img/linux-image-4.20.12-X1000_X5000/X5000_and_QEMU_e5500/uImage-4.20 -nographic

also, I think I found reason why some of my tests resulted in blue or green-ish 
image: -sdl,gl=on was causing troubles sometimes. It was ok with stdvga , but 
not for virtio-gpu.

At least in linux virtio-gpu driver disables "3d" (virgl) part of itself on BE 
machine. Guess sdl2  video output in qemu has no idea about guest's action, so 
it acts wrongly with BE guests and gives intensively blue console with 
offb-enabled LE guest. (on ppc64 machine).

[-- Attachment #2: Freescale_i2c_patch-real.diff --]
[-- Type: text/x-diff, Size: 14027 bytes --]

diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 52acb7cf39..a560971f0c 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -8,6 +8,8 @@ include usb.mak
 CONFIG_PPC4XX=y
 CONFIG_M48T59=y
 CONFIG_SERIAL=y
+CONFIG_MPC_I2C=y
+CONFIG_DS1338=y
 CONFIG_I8257=y
 CONFIG_OPENPIC=y
 CONFIG_PPCE500_PCI=y
diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
index cecee486f7..55473fc6b2 100644
--- a/hw/i2c/Makefile.objs
+++ b/hw/i2c/Makefile.objs
@@ -9,5 +9,6 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
 common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
 common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
 common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o
+common-obj-$(CONFIG_MPC_I2C) += mpc_i2c.o
 obj-$(CONFIG_OMAP) += omap_i2c.o
 obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
new file mode 100644
index 0000000000..54d7a9aabd
--- /dev/null
+++ b/hw/i2c/mpc_i2c.c
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Amit Tomar, <Amit.Tomar@freescale.com>
+ *
+ * Description:
+ * This file is derived from IMX I2C controller,
+ * by Jean-Christophe DUBOIS .
+ *
+ * Thanks to Scott Wood and Alexander Graf for their kind help on this.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2 or later,
+ * as published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "qemu/osdep.h"
+// #include "hw/i2c/imx_i2c.h"
+#include "hw/i2c/i2c.h"
+#include "qemu/log.h"
+#include "hw/sysbus.h"
+
+/* #define DEBUG_I2C */
+
+#ifdef DEBUG_I2C
+#define DPRINTF(fmt, ...)              \
+    do { fprintf(stderr, "mpc_i2c[%s]: " fmt, __func__, ## __VA_ARGS__); \
+    } while (0)
+#else
+#define DPRINTF(fmt, ...) do {} while (0)
+#endif
+
+#define TYPE_MPC_I2C "mpc-i2c"
+#define MPC_I2C(obj) \
+    OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C)
+
+#define MPC_I2C_ADR   0x00
+#define MPC_I2C_FDR   0x04
+#define MPC_I2C_CR    0x08
+#define MPC_I2C_SR    0x0c
+#define MPC_I2C_DR    0x10
+#define MPC_I2C_DFSRR 0x14
+
+#define CCR_MEN  (1<<7)
+#define CCR_MIEN (1<<6)
+#define CCR_MSTA (1<<5)
+#define CCR_MTX  (1<<4)
+#define CCR_TXAK (1<<3)
+#define CCR_RSTA (1<<2)
+#define CCR_BCST (1<<0)
+
+#define CSR_MCF  (1<<7)
+#define CSR_MAAS (1<<6)
+#define CSR_MBB  (1<<5)
+#define CSR_MAL  (1<<4)
+#define CSR_SRW  (1<<2)
+#define CSR_MIF  (1<<1)
+#define CSR_RXAK (1<<0)
+
+#define CADR_MASK 0xFE
+#define CFDR_MASK 0x3F
+#define CCR_MASK  0xFC
+#define CSR_MASK  0xED
+#define CDR_MASK  0xFF
+
+#define CYCLE_RESET 0xFF
+
+typedef struct MPCI2CState {
+    SysBusDevice parent_obj;
+
+    I2CBus *bus;
+    qemu_irq irq;
+    MemoryRegion iomem;
+
+    uint8_t address;
+    uint8_t adr;
+    uint8_t fdr;
+    uint8_t cr;
+    uint8_t sr;
+    uint8_t dr;
+    uint8_t dfssr;
+} MPCI2CState;
+
+static bool mpc_i2c_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MEN;
+}
+
+static bool mpc_i2c_is_master(MPCI2CState *s)
+{
+    return s->cr & CCR_MSTA;
+}
+
+static bool mpc_i2c_direction_is_tx(MPCI2CState *s)
+{
+    return s->cr & CCR_MTX;
+}
+
+static bool mpc_i2c_irq_pending(MPCI2CState *s)
+{
+    return s->sr & CSR_MIF;
+}
+
+static bool mpc_i2c_irq_is_enabled(MPCI2CState *s)
+{
+    return s->cr & CCR_MIEN;
+}
+
+static void mpc_i2c_reset(DeviceState *dev)
+{
+    MPCI2CState *i2c = MPC_I2C(dev);
+
+    i2c->address = 0xFF;
+    i2c->adr = 0x00;
+    i2c->fdr = 0x00;
+    i2c->cr =  0x00;
+    i2c->sr =  0x81;
+    i2c->dr =  0x00;
+}
+
+static void mpc_i2c_irq(MPCI2CState *s)
+{
+    bool irq_active = false;
+
+    if (mpc_i2c_is_enabled(s) && mpc_i2c_irq_is_enabled(s)
+                              && mpc_i2c_irq_pending(s)) {
+        irq_active = true;
+    }
+
+    if (irq_active) {
+        qemu_irq_raise(s->irq);
+    } else {
+        qemu_irq_lower(s->irq);
+    }
+}
+
+static void mpc_i2c_soft_reset(MPCI2CState *s)
+{
+    /* This is a soft reset. ADR is preserved during soft resets */
+    uint8_t adr = s->adr;
+    mpc_i2c_reset(DEVICE(s));
+    s->adr = adr;
+}
+
+static void  mpc_i2c_address_send(MPCI2CState *s)
+{
+    /* if returns non zero slave address is not right */
+    if (i2c_start_transfer(s->bus, s->dr >> 1, s->dr & (0x01))) {
+        s->sr |= CSR_RXAK;
+    } else {
+        s->address = s->dr;
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_send(MPCI2CState *s)
+{
+    if (i2c_send(s->bus, s->dr)) {
+        /* End of transfer */
+        s->sr |= CSR_RXAK;
+        i2c_end_transfer(s->bus);
+    } else {
+        s->sr &= ~CSR_RXAK;
+        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    }
+}
+
+static void  mpc_i2c_data_recive(MPCI2CState *s)
+{
+    int ret;
+    /* get the next byte */
+    ret = i2c_recv(s->bus);
+    if (ret >= 0) {
+        s->sr |= CSR_MCF; /* Set after Byte Transfer is completed */
+        s->sr |= CSR_MIF; /* Set after Byte Transfer is completed */
+        mpc_i2c_irq(s);
+    } else {
+        DPRINTF("read failed for device");
+        ret = 0xff;
+    }
+    s->dr = ret;
+}
+
+static uint64_t mpc_i2c_read(void *opaque, hwaddr addr, unsigned size)
+{
+    MPCI2CState *s = opaque;
+    uint8_t value;
+
+    switch (addr) {
+    case MPC_I2C_ADR:
+        value = s->adr;
+        break;
+    case MPC_I2C_FDR:
+        value = s->fdr;
+        break;
+    case MPC_I2C_CR:
+        value = s->cr;
+        break;
+    case MPC_I2C_SR:
+        value = s->sr;
+        break;
+    case MPC_I2C_DR:
+        value = s->dr;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (mpc_i2c_direction_is_tx(s)) {
+                DPRINTF("MTX is set not in recv mode\n");
+            } else {
+                mpc_i2c_data_recive(s);
+            }
+        }
+        break;
+    default:
+        value = 0;
+        DPRINTF("ERROR: Bad read addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__,
+                                         addr, value);
+    return (uint64_t)value;
+}
+
+static void mpc_i2c_write(void *opaque, hwaddr addr,
+                            uint64_t value, unsigned size)
+{
+    MPCI2CState *s = opaque;
+
+    DPRINTF("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", __func__,
+                                             addr, value);
+    switch (addr) {
+    case MPC_I2C_ADR:
+        s->adr = value & CADR_MASK;
+        break;
+    case MPC_I2C_FDR:
+        s->fdr = value & CFDR_MASK;
+        break;
+    case MPC_I2C_CR:
+        if (mpc_i2c_is_enabled(s) && ((value & CCR_MEN) == 0)) {
+            mpc_i2c_soft_reset(s);
+            break;
+        }
+        /* normal write */
+        s->cr = value & CCR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            /* set the bus to busy after master is set as per RM */
+            s->sr |= CSR_MBB;
+        } else {
+            /* bus is not busy anymore */
+            s->sr &= ~CSR_MBB;
+            /* Reset the address for fresh write/read cycle */
+        if (s->address != CYCLE_RESET) {
+            i2c_end_transfer(s->bus);
+            s->address = CYCLE_RESET;
+            }
+        }
+        /* For restart end the onging transfer */
+        if (s->cr & CCR_RSTA) {
+            if (s->address != CYCLE_RESET) {
+                s->address = CYCLE_RESET;
+                i2c_end_transfer(s->bus);
+                s->cr &= ~CCR_RSTA;
+            }
+        }
+        break;
+    case MPC_I2C_SR:
+        s->sr = value & CSR_MASK;
+        /* Lower the interrupt */
+        if (!(s->sr & CSR_MIF) || !(s->sr & CSR_MAL)) {
+            mpc_i2c_irq(s);
+        }
+        break;
+    case MPC_I2C_DR:
+        /* if the device is not enabled, nothing to do */
+        if (!mpc_i2c_is_enabled(s)) {
+            break;
+        }
+        s->dr = value & CDR_MASK;
+        if (mpc_i2c_is_master(s)) { /* master mode */
+            if (s->address == CYCLE_RESET) {
+                mpc_i2c_address_send(s);
+            } else {
+                mpc_i2c_data_send(s);
+            }
+        }
+        break;
+    case MPC_I2C_DFSRR:
+        s->dfssr = value;
+        break;
+    default:
+        DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
+        break;
+    }
+}
+
+static const MemoryRegionOps i2c_ops = {
+    .read =  mpc_i2c_read,
+    .write =  mpc_i2c_write,
+    .valid.max_access_size = 1,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static const VMStateDescription mpc_i2c_vmstate = {
+    .name = TYPE_MPC_I2C,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8(address, MPCI2CState),
+        VMSTATE_UINT8(adr, MPCI2CState),
+        VMSTATE_UINT8(fdr, MPCI2CState),
+        VMSTATE_UINT8(cr, MPCI2CState),
+        VMSTATE_UINT8(sr, MPCI2CState),
+        VMSTATE_UINT8(dr, MPCI2CState),
+        VMSTATE_UINT8(dfssr, MPCI2CState),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void mpc_i2c_realize(DeviceState *dev, Error **errp)
+{
+    
+    MPCI2CState  *i2c = MPC_I2C(dev);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
+    memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
+                          "mpc-i2c", 0x14);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
+    i2c->bus = i2c_init_bus(DEVICE(dev), "i2c");
+}
+
+static void mpc_i2c_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd  = &mpc_i2c_vmstate ;
+    dc->reset = mpc_i2c_reset;
+    dc->realize = mpc_i2c_realize;
+    dc->desc = "MPC I2C Controller";
+}
+
+static const TypeInfo mpc_i2c_type_info = {
+    .name          = TYPE_MPC_I2C,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(MPCI2CState),
+    .class_init    = mpc_i2c_class_init,
+};
+
+static void mpc_i2c_register_types(void)
+{
+    type_register_static(&mpc_i2c_type_info);
+}
+
+type_init(mpc_i2c_register_types)
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 7553f674c9..c8e8563f95 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -42,6 +42,7 @@
 #include "qemu/error-report.h"
 #include "hw/platform-bus.h"
 #include "hw/net/fsl_etsec/etsec.h"
+#include "hw/i2c/i2c.h"
 
 #define EPAPR_MAGIC                (0x45504150)
 #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
@@ -63,7 +64,10 @@
 #define MPC8544_PCI_REGS_SIZE      0x1000ULL
 #define MPC8544_UTIL_OFFSET        0xe0000ULL
 #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
+#define MPC8544_I2C_REGS_OFFSET    0x3000ULL
 #define MPC8XXX_GPIO_IRQ           47
+#define MPC8544_I2C_IRQ            43
+#define RTC_REGS_OFFSET            0x68
 
 struct boot_info
 {
@@ -161,6 +165,39 @@ static void create_dt_mpc8xxx_gpio(void *fdt, const char *soc, const char *mpic)
     g_free(poweroff);
 }
 
+static void dt_rtc_create(void *fdt, const char *i2c, const char *alias)
+{
+    int offset = RTC_REGS_OFFSET;
+
+    gchar *rtc = g_strdup_printf("%s/rtc@%"PRIx32, i2c, offset);
+    qemu_fdt_add_subnode(fdt, rtc);
+    qemu_fdt_setprop_string(fdt, rtc, "compatible", "pericom,pt7c4338");
+    qemu_fdt_setprop_cells(fdt, rtc, "reg", offset);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, rtc);
+
+    g_free(rtc);
+}
+
+static void dt_i2c_create(void *fdt, const char *soc, const char *mpic,
+                             const char *alias)
+{
+    hwaddr mmio0 = MPC8544_I2C_REGS_OFFSET;
+    int irq0 = MPC8544_I2C_IRQ;
+
+    gchar *i2c = g_strdup_printf("%s/i2c@%"PRIx64, soc, mmio0);
+    qemu_fdt_add_subnode(fdt, i2c);
+    qemu_fdt_setprop_string(fdt, i2c, "device_type", "i2c");
+    qemu_fdt_setprop_string(fdt, i2c, "compatible", "fsl-i2c");
+    qemu_fdt_setprop_cells(fdt, i2c, "reg", mmio0, 0x14);
+    qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0);
+    qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2);
+    qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic);
+    qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c);
+
+    g_free(i2c);
+}
+
+
 typedef struct PlatformDevtreeData {
     void *fdt;
     const char *mpic;
@@ -463,6 +500,12 @@ static int ppce500_load_device_tree(PPCE500MachineState *pms,
         dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
                          soc, mpic, "serial0", 0, true);
     }
+    
+    /* i2c */
+    dt_i2c_create(fdt, soc, mpic, "i2c");
+
+    dt_rtc_create(fdt, "i2c", "rtc");
+
 
     gutil = g_strdup_printf("%s/global-utilities@%llx", soc,
                             MPC8544_UTIL_OFFSET);
@@ -812,6 +855,7 @@ void ppce500_init(MachineState *machine)
     MemoryRegion *ccsr_addr_space;
     SysBusDevice *s;
     PPCE500CCSRState *ccsr;
+    I2CBus *i2c;
 
     irqs = g_new0(IrqLines, smp_cpus);
     for (i = 0; i < smp_cpus; i++) {
@@ -887,6 +931,16 @@ void ppce500_init(MachineState *machine)
                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
                        serial_hd(1), DEVICE_BIG_ENDIAN);
     }
+        /* I2C */
+    dev = qdev_create(NULL, "mpc-i2c");
+    s = SYS_BUS_DEVICE(dev);
+    qdev_init_nofail(dev);
+    sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ));
+    memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET,
+                                sysbus_mmio_get_region(s, 0));
+    i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
+    i2c_create_slave(i2c, "ds1338", RTC_REGS_OFFSET);
+
 
     /* General Utility device */
     dev = qdev_create(NULL, "mpc8544-guts");

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Forward-porting RTC device for eppc500 ?
  2019-03-02 11:21 [Qemu-devel] Forward-porting RTC device for eppc500 ? Andrew Randrianasulu
@ 2019-03-02 16:59 ` BALATON Zoltan
       [not found] ` <201903022144.45897.randrianasulu@gmail.com>
  1 sibling, 0 replies; 5+ messages in thread
From: BALATON Zoltan @ 2019-03-02 16:59 UTC (permalink / raw)
  To: Andrew Randrianasulu
  Cc: Amit.Tomar, qemu-ppc@nongnu.org, qemu-devel, David Gibson

Hello,

On Sat, 2 Mar 2019, Andrew Randrianasulu wrote:
> Hello, all!
>
> I stumbled upon this email from 2015 (trying to understand why my emulated
> ppce500 machine failed to set clock correctly:
>
> https://lists.gnu.org/archive/html/qemu-devel/2015-01/msg02642.html
>
> Now, after some quite blind trial-and-error I applied ('forward-ported') this
> patch to qemu git commit 0f6a6d5db853c0cbe438c1831c70710bfb6530ee without
> actually porting it to new qemu device abstraction model.
>
> It seems to work!
>
> But because I copy-pasted patch from web archive of list - some strings
> become "address@hidden", I hope I corrected them right?

You can get all patches submitted to the list from patchew, the original 
of this one is here:
http://patchwork.ozlabs.org/patch/431475/

The mbox format patch for git am is at the mbox link:
http://patchwork.ozlabs.org/patch/431475/mbox/

I think you could try to apply that patch with git am, fix any conflicts 
due to changes in QEMU since the original patch to get an updated commit, 
then use git format-patch to get a current patch you can submit to the 
list for inclusion. The detailed description of how to send a patch is 
here: https://wiki.qemu.org/Contribute/SubmitAPatch

Basically you should make sure you have an email that can be applied with 
git am as that's what maintainers do. It should also have your 
Signed-off-by if you made any changes to the patch after the original 
Signed-off-by of the original author (you can add it e.g. with git commit 
-s or git format-patch -s). Check the patch with scripts/checkpatch.pl 
before sending and fix all errors and cc maintainers that you can get with 
scripts/get_maintainer.pl. For PPC related stuff you should usually cc 
qemu-ppc@nongnu.org and David Gibson besides sending to 
qemu-devel@nongnu.org to make sure it's not lost.

I don't have any comments to the patch, some more comments below the other 
topic at the end.

>
> ---------------------------
> diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
> index 52acb7cf39..a560971f0c 100644
> --- a/default-configs/ppc-softmmu.mak
> +++ b/default-configs/ppc-softmmu.mak
> @@ -8,6 +8,8 @@ include usb.mak
> CONFIG_PPC4XX=y
> CONFIG_M48T59=y
> CONFIG_SERIAL=y
> +CONFIG_MPC_I2C=y
> +CONFIG_DS1338=y
> CONFIG_I8257=y
> CONFIG_OPENPIC=y
> CONFIG_PPCE500_PCI=y
> diff --git a/hw/i2c/Makefile.objs b/hw/i2c/Makefile.objs
> index cecee486f7..55473fc6b2 100644
> --- a/hw/i2c/Makefile.objs
> +++ b/hw/i2c/Makefile.objs
> @@ -9,5 +9,6 @@ common-obj-$(CONFIG_EXYNOS4) += exynos4210_i2c.o
> common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o
> common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o
> common-obj-$(CONFIG_NRF51_SOC) += microbit_i2c.o
> +common-obj-$(CONFIG_MPC_I2C) += mpc_i2c.o
> obj-$(CONFIG_OMAP) += omap_i2c.o
> obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o
> diff --git a/hw/i2c/mpc_i2c.c b/hw/i2c/mpc_i2c.c
> new file mode 100644
> index 0000000000..54d7a9aabd
> --- /dev/null
> +++ b/hw/i2c/mpc_i2c.c
> @@ -0,0 +1,360 @@
> +/*
> + * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved.
> + *
> + * Author: Amit Tomar, <Amit.Tomar@freescale.com>
> + *
> + * Description:
> + * This file is derived from IMX I2C controller,
> + * by Jean-Christophe DUBOIS .
> + *
> + * Thanks to Scott Wood and Alexander Graf for their kind help on this.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License, version 2 or later,
> + * as published by the Free Software Foundation.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see <http://www.gnu.org/licenses/>.
> +*/
> +
> +#include "qemu/osdep.h"
> +// #include "hw/i2c/imx_i2c.h"
> +#include "hw/i2c/i2c.h"
> +#include "qemu/log.h"
> +#include "hw/sysbus.h"
> +
> +/* #define DEBUG_I2C */
> +
> +#ifdef DEBUG_I2C
> +#define DPRINTF(fmt, ...)              \
> +    do { fprintf(stderr, "mpc_i2c[%s]: " fmt, __func__, ## __VA_ARGS__); \
> +    } while (0)
> +#else
> +#define DPRINTF(fmt, ...) do {} while (0)
> +#endif
> +
> +#define TYPE_MPC_I2C "mpc-i2c"
> +#define MPC_I2C(obj) \
> +    OBJECT_CHECK(MPCI2CState, (obj), TYPE_MPC_I2C)
> +
> +#define MPC_I2C_ADR   0x00
> +#define MPC_I2C_FDR   0x04
> +#define MPC_I2C_CR    0x08
> +#define MPC_I2C_SR    0x0c
> +#define MPC_I2C_DR    0x10
> +#define MPC_I2C_DFSRR 0x14
> +
> +#define CCR_MEN  (1<<7)
> +#define CCR_MIEN (1<<6)
> +#define CCR_MSTA (1<<5)
> +#define CCR_MTX  (1<<4)
> +#define CCR_TXAK (1<<3)
> +#define CCR_RSTA (1<<2)
> +#define CCR_BCST (1<<0)
> +
> +#define CSR_MCF  (1<<7)
> +#define CSR_MAAS (1<<6)
> +#define CSR_MBB  (1<<5)
> +#define CSR_MAL  (1<<4)
> +#define CSR_SRW  (1<<2)
> +#define CSR_MIF  (1<<1)
> +#define CSR_RXAK (1<<0)
> +
> +#define CADR_MASK 0xFE
> +#define CFDR_MASK 0x3F
> +#define CCR_MASK  0xFC
> +#define CSR_MASK  0xED
> +#define CDR_MASK  0xFF
> +
> +#define CYCLE_RESET 0xFF
> +
> +typedef struct MPCI2CState {
> +    SysBusDevice parent_obj;
> +
> +    I2CBus *bus;
> +    qemu_irq irq;
> +    MemoryRegion iomem;
> +
> +    uint8_t address;
> +    uint8_t adr;
> +    uint8_t fdr;
> +    uint8_t cr;
> +    uint8_t sr;
> +    uint8_t dr;
> +    uint8_t dfssr;
> +} MPCI2CState;
> +
> +static bool mpc_i2c_is_enabled(MPCI2CState *s)
> +{
> +    return s->cr & CCR_MEN;
> +}
> +
> +static bool mpc_i2c_is_master(MPCI2CState *s)
> +{
> +    return s->cr & CCR_MSTA;
> +}
> +
> +static bool mpc_i2c_direction_is_tx(MPCI2CState *s)
> +{
> +    return s->cr & CCR_MTX;
> +}
> +
> +static bool mpc_i2c_irq_pending(MPCI2CState *s)
> +{
> +    return s->sr & CSR_MIF;
> +}
> +
> +static bool mpc_i2c_irq_is_enabled(MPCI2CState *s)
> +{
> +    return s->cr & CCR_MIEN;
> +}
> +
> +static void mpc_i2c_reset(DeviceState *dev)
> +{
> +    MPCI2CState *i2c = MPC_I2C(dev);
> +
> +    i2c->address = 0xFF;
> +    i2c->adr = 0x00;
> +    i2c->fdr = 0x00;
> +    i2c->cr =  0x00;
> +    i2c->sr =  0x81;
> +    i2c->dr =  0x00;
> +}
> +
> +static void mpc_i2c_irq(MPCI2CState *s)
> +{
> +    bool irq_active = false;
> +
> +    if (mpc_i2c_is_enabled(s) && mpc_i2c_irq_is_enabled(s)
> +                              && mpc_i2c_irq_pending(s)) {
> +        irq_active = true;
> +    }
> +
> +    if (irq_active) {
> +        qemu_irq_raise(s->irq);
> +    } else {
> +        qemu_irq_lower(s->irq);
> +    }
> +}
> +
> +static void mpc_i2c_soft_reset(MPCI2CState *s)
> +{
> +    /* This is a soft reset. ADR is preserved during soft resets */
> +    uint8_t adr = s->adr;
> +    mpc_i2c_reset(DEVICE(s));
> +    s->adr = adr;
> +}
> +
> +static void  mpc_i2c_address_send(MPCI2CState *s)
> +{
> +    /* if returns non zero slave address is not right */
> +    if (i2c_start_transfer(s->bus, s->dr >> 1, s->dr & (0x01))) {
> +        s->sr |= CSR_RXAK;
> +    } else {
> +        s->address = s->dr;
> +        s->sr &= ~CSR_RXAK;
> +        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
> +        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
> +        mpc_i2c_irq(s);
> +    }
> +}
> +
> +static void  mpc_i2c_data_send(MPCI2CState *s)
> +{
> +    if (i2c_send(s->bus, s->dr)) {
> +        /* End of transfer */
> +        s->sr |= CSR_RXAK;
> +        i2c_end_transfer(s->bus);
> +    } else {
> +        s->sr &= ~CSR_RXAK;
> +        s->sr |=  CSR_MCF; /* Set after Byte Transfer is completed */
> +        s->sr |=  CSR_MIF; /* Set after Byte Transfer is completed */
> +        mpc_i2c_irq(s);
> +    }
> +}
> +
> +static void  mpc_i2c_data_recive(MPCI2CState *s)
> +{
> +    int ret;
> +    /* get the next byte */
> +    ret = i2c_recv(s->bus);
> +    if (ret >= 0) {
> +        s->sr |= CSR_MCF; /* Set after Byte Transfer is completed */
> +        s->sr |= CSR_MIF; /* Set after Byte Transfer is completed */
> +        mpc_i2c_irq(s);
> +    } else {
> +        DPRINTF("read failed for device");
> +        ret = 0xff;
> +    }
> +    s->dr = ret;
> +}
> +
> +static uint64_t mpc_i2c_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    MPCI2CState *s = opaque;
> +    uint8_t value;
> +
> +    switch (addr) {
> +    case MPC_I2C_ADR:
> +        value = s->adr;
> +        break;
> +    case MPC_I2C_FDR:
> +        value = s->fdr;
> +        break;
> +    case MPC_I2C_CR:
> +        value = s->cr;
> +        break;
> +    case MPC_I2C_SR:
> +        value = s->sr;
> +        break;
> +    case MPC_I2C_DR:
> +        value = s->dr;
> +        if (mpc_i2c_is_master(s)) { /* master mode */
> +            if (mpc_i2c_direction_is_tx(s)) {
> +                DPRINTF("MTX is set not in recv mode\n");
> +            } else {
> +                mpc_i2c_data_recive(s);
> +            }
> +        }
> +        break;
> +    default:
> +        value = 0;
> +        DPRINTF("ERROR: Bad read addr 0x%x\n", (unsigned int)addr);
> +        break;
> +    }
> +
> +    DPRINTF("%s: addr " TARGET_FMT_plx " %02" PRIx32 "\n", __func__,
> +                                         addr, value);
> +    return (uint64_t)value;
> +}
> +
> +static void mpc_i2c_write(void *opaque, hwaddr addr,
> +                            uint64_t value, unsigned size)
> +{
> +    MPCI2CState *s = opaque;
> +
> +    DPRINTF("%s: addr " TARGET_FMT_plx " val %08" PRIx64 "\n", __func__,
> +                                             addr, value);
> +    switch (addr) {
> +    case MPC_I2C_ADR:
> +        s->adr = value & CADR_MASK;
> +        break;
> +    case MPC_I2C_FDR:
> +        s->fdr = value & CFDR_MASK;
> +        break;
> +    case MPC_I2C_CR:
> +        if (mpc_i2c_is_enabled(s) && ((value & CCR_MEN) == 0)) {
> +            mpc_i2c_soft_reset(s);
> +            break;
> +        }
> +        /* normal write */
> +        s->cr = value & CCR_MASK;
> +        if (mpc_i2c_is_master(s)) { /* master mode */
> +            /* set the bus to busy after master is set as per RM */
> +            s->sr |= CSR_MBB;
> +        } else {
> +            /* bus is not busy anymore */
> +            s->sr &= ~CSR_MBB;
> +            /* Reset the address for fresh write/read cycle */
> +        if (s->address != CYCLE_RESET) {
> +            i2c_end_transfer(s->bus);
> +            s->address = CYCLE_RESET;
> +            }
> +        }
> +        /* For restart end the onging transfer */
> +        if (s->cr & CCR_RSTA) {
> +            if (s->address != CYCLE_RESET) {
> +                s->address = CYCLE_RESET;
> +                i2c_end_transfer(s->bus);
> +                s->cr &= ~CCR_RSTA;
> +            }
> +        }
> +        break;
> +    case MPC_I2C_SR:
> +        s->sr = value & CSR_MASK;
> +        /* Lower the interrupt */
> +        if (!(s->sr & CSR_MIF) || !(s->sr & CSR_MAL)) {
> +            mpc_i2c_irq(s);
> +        }
> +        break;
> +    case MPC_I2C_DR:
> +        /* if the device is not enabled, nothing to do */
> +        if (!mpc_i2c_is_enabled(s)) {
> +            break;
> +        }
> +        s->dr = value & CDR_MASK;
> +        if (mpc_i2c_is_master(s)) { /* master mode */
> +            if (s->address == CYCLE_RESET) {
> +                mpc_i2c_address_send(s);
> +            } else {
> +                mpc_i2c_data_send(s);
> +            }
> +        }
> +        break;
> +    case MPC_I2C_DFSRR:
> +        s->dfssr = value;
> +        break;
> +    default:
> +        DPRINTF("ERROR: Bad write addr 0x%x\n", (unsigned int)addr);
> +        break;
> +    }
> +}
> +
> +static const MemoryRegionOps i2c_ops = {
> +    .read =  mpc_i2c_read,
> +    .write =  mpc_i2c_write,
> +    .valid.max_access_size = 1,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static const VMStateDescription mpc_i2c_vmstate = {
> +    .name = TYPE_MPC_I2C,
> +    .version_id = 1,
> +    .minimum_version_id = 1,
> +    .fields = (VMStateField[]) {
> +        VMSTATE_UINT8(address, MPCI2CState),
> +        VMSTATE_UINT8(adr, MPCI2CState),
> +        VMSTATE_UINT8(fdr, MPCI2CState),
> +        VMSTATE_UINT8(cr, MPCI2CState),
> +        VMSTATE_UINT8(sr, MPCI2CState),
> +        VMSTATE_UINT8(dr, MPCI2CState),
> +        VMSTATE_UINT8(dfssr, MPCI2CState),
> +        VMSTATE_END_OF_LIST()
> +    }
> +};
> +
> +static void mpc_i2c_realize(DeviceState *dev, Error **errp)
> +{
> +
> +    MPCI2CState  *i2c = MPC_I2C(dev);
> +
> +    sysbus_init_irq(SYS_BUS_DEVICE(dev), &i2c->irq);
> +    memory_region_init_io(&i2c->iomem, OBJECT(i2c), &i2c_ops, i2c,
> +                          "mpc-i2c", 0x14);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &i2c->iomem);
> +    i2c->bus = i2c_init_bus(DEVICE(dev), "i2c");
> +}
> +
> +static void mpc_i2c_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->vmsd  = &mpc_i2c_vmstate ;
> +    dc->reset = mpc_i2c_reset;
> +    dc->realize = mpc_i2c_realize;
> +    dc->desc = "MPC I2C Controller";
> +}
> +
> +static const TypeInfo mpc_i2c_type_info = {
> +    .name          = TYPE_MPC_I2C,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(MPCI2CState),
> +    .class_init    = mpc_i2c_class_init,
> +};
> +
> +static void mpc_i2c_register_types(void)
> +{
> +    type_register_static(&mpc_i2c_type_info);
> +}
> +
> +type_init(mpc_i2c_register_types)
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index 7553f674c9..c8e8563f95 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -42,6 +42,7 @@
> #include "qemu/error-report.h"
> #include "hw/platform-bus.h"
> #include "hw/net/fsl_etsec/etsec.h"
> +#include "hw/i2c/i2c.h"
>
> #define EPAPR_MAGIC                (0x45504150)
> #define BINARY_DEVICE_TREE_FILE    "mpc8544ds.dtb"
> @@ -63,7 +64,10 @@
> #define MPC8544_PCI_REGS_SIZE      0x1000ULL
> #define MPC8544_UTIL_OFFSET        0xe0000ULL
> #define MPC8XXX_GPIO_OFFSET        0x000FF000ULL
> +#define MPC8544_I2C_REGS_OFFSET    0x3000ULL
> #define MPC8XXX_GPIO_IRQ           47
> +#define MPC8544_I2C_IRQ            43
> +#define RTC_REGS_OFFSET            0x68
>
> struct boot_info
> {
> @@ -161,6 +165,39 @@ static void create_dt_mpc8xxx_gpio(void *fdt, const char
> *soc, const char *mpic)
>     g_free(poweroff);
> }
>
> +static void dt_rtc_create(void *fdt, const char *i2c, const char *alias)
> +{
> +    int offset = RTC_REGS_OFFSET;
> +
> +    gchar *rtc = g_strdup_printf("%s/rtc@%"PRIx32, i2c, offset);
> +    qemu_fdt_add_subnode(fdt, rtc);
> +    qemu_fdt_setprop_string(fdt, rtc, "compatible", "pericom,pt7c4338");
> +    qemu_fdt_setprop_cells(fdt, rtc, "reg", offset);
> +    qemu_fdt_setprop_string(fdt, "/aliases", alias, rtc);
> +
> +    g_free(rtc);
> +}
> +
> +static void dt_i2c_create(void *fdt, const char *soc, const char *mpic,
> +                             const char *alias)
> +{
> +    hwaddr mmio0 = MPC8544_I2C_REGS_OFFSET;
> +    int irq0 = MPC8544_I2C_IRQ;
> +
> +    gchar *i2c = g_strdup_printf("%s/i2c@%"PRIx64, soc, mmio0);
> +    qemu_fdt_add_subnode(fdt, i2c);
> +    qemu_fdt_setprop_string(fdt, i2c, "device_type", "i2c");
> +    qemu_fdt_setprop_string(fdt, i2c, "compatible", "fsl-i2c");
> +    qemu_fdt_setprop_cells(fdt, i2c, "reg", mmio0, 0x14);
> +    qemu_fdt_setprop_cells(fdt, i2c, "cell-index", 0);
> +    qemu_fdt_setprop_cells(fdt, i2c, "interrupts", irq0, 0x2);
> +    qemu_fdt_setprop_phandle(fdt, i2c, "interrupt-parent", mpic);
> +    qemu_fdt_setprop_string(fdt, "/aliases", alias, i2c);
> +
> +    g_free(i2c);
> +}
> +
> +
> typedef struct PlatformDevtreeData {
>     void *fdt;
>     const char *mpic;
> @@ -463,6 +500,12 @@ static int ppce500_load_device_tree(PPCE500MachineState
> *pms,
>         dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
>                          soc, mpic, "serial0", 0, true);
>     }
> +
> +    /* i2c */
> +    dt_i2c_create(fdt, soc, mpic, "i2c");
> +
> +    dt_rtc_create(fdt, "i2c", "rtc");
> +
>
>     gutil = g_strdup_printf("%s/global-utilities@%llx", soc,
>                             MPC8544_UTIL_OFFSET);
> @@ -812,6 +855,7 @@ void ppce500_init(MachineState *machine)
>     MemoryRegion *ccsr_addr_space;
>     SysBusDevice *s;
>     PPCE500CCSRState *ccsr;
> +    I2CBus *i2c;
>
>     irqs = g_new0(IrqLines, smp_cpus);
>     for (i = 0; i < smp_cpus; i++) {
> @@ -887,6 +931,16 @@ void ppce500_init(MachineState *machine)
>                        0, qdev_get_gpio_in(mpicdev, 42), 399193,
>                        serial_hd(1), DEVICE_BIG_ENDIAN);
>     }
> +        /* I2C */
> +    dev = qdev_create(NULL, "mpc-i2c");
> +    s = SYS_BUS_DEVICE(dev);
> +    qdev_init_nofail(dev);
> +    sysbus_connect_irq(s, 0, qdev_get_gpio_in(mpicdev, MPC8544_I2C_IRQ));
> +    memory_region_add_subregion(ccsr_addr_space, MPC8544_I2C_REGS_OFFSET,
> +                                sysbus_mmio_get_region(s, 0));
> +    i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
> +    i2c_create_slave(i2c, "ds1338", RTC_REGS_OFFSET);
> +
>
>     /* General Utility device */
>     dev = qdev_create(NULL, "mpc8544-guts");
>
> ----------------
>
> Test kernel I used:
> http://www.xenosoft.de/linux-image-4.20.12-X1000_X5000.tar.gz
> (unpack and use uImage)
>
> guest@slax:/dev/shm/qemu$ ppc64-softmmu/qemu-system-ppc64 -M ppce500 -cpu
> e5500 -kernel /mnt/sdb1/PPC-img/linux-image-4.20.12-X1000_X5000/X5000_and_QEMU_e5500/uImage-4.20 -nographic
>
> also, I think I found reason why some of my tests resulted in blue or green-ish
> image: -sdl,gl=on was causing troubles sometimes. It was ok with stdvga , but
> not for virtio-gpu.
>
> At least in linux virtio-gpu driver disables "3d" (virgl) part of itself on BE
> machine. Guess sdl2  video output in qemu has no idea about guest's action, so
> it acts wrongly with BE guests and gives intensively blue console with
> offb-enabled LE guest. (on ppc64 machine).

There could be different endianness issues both in QEMU or in the Linux 
driver (BE systems are not well supported nowadays). I don't think SDL 
itself would play a role but I really don't know. Maybe you should post 
this question separately with details on how to reproduce it on qemu-devel 
list cc-ing the graphics maintainer Gerd Hoffmann <kraxel@redhat.com> 
otherwise it's easy to miss this at the end of an unrelated patch and 
likely no one will reply. (It's possible nobody will reply to a separate 
thread either as people may not use similar setup but the chances are 
higher to get some reply that way.)

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Forward-porting RTC device for eppc500 ?
       [not found]   ` <alpine.BSF.2.21.9999.1903022116110.13215@zero.eik.bme.hu>
@ 2019-03-02 21:50     ` Andrew Randrianasulu
  2019-03-03  0:17       ` BALATON Zoltan
  0 siblings, 1 reply; 5+ messages in thread
From: Andrew Randrianasulu @ 2019-03-02 21:50 UTC (permalink / raw)
  To: BALATON Zoltan, qemu-devel

В сообщении от Saturday 02 March 2019 23:40:47 BALATON Zoltan написал(а):

[snip]


>
> On Sat, 2 Mar 2019, Andrew Randrianasulu wrote:
> > Should I fix those?
>
> [...]
>
> > total: 14 errors, 2 warnings, 462 lines checked
> >
> > 0001-Re-applying-of-Freescale-PPC500-i2c-RTC-patch-writte.patch has style
> > problems, please review.  If any of these errors
> > are false positives report them to the maintainer, see
> > CHECKPATCH in MAINTAINERS.
>
> Yes, patches submitted to the list should pass checkpatch otherwise they
> will be rejected by automated build tests. These are simple to fix, just
> add spaces as checkpatch suggests: (1 << 0) and so on.
>
> (It's better to keep the list cc-d on reply so others can also answer your
> questions or correct my answers if I missed something which is not
> possible if you reply to me off list.)


Posted to list, arrived as 
https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg00413.html

I used (in specifically created branch)

git reset origin
git reset --hard
git apply \
/home/guest/botva/src/src/qemu/0001-Re-applying-Freescale-PPC500-i2c-RTC-patch-written-b.patch
rm hw/i2c/mpc_i2c.c (leftover from my previous attempt at commiting)
again

git apply \
/home/guest/botva/src/src/qemu/0001-Re-applying-Freescale-PPC500-i2c-RTC-patch-written-b.patch
{now it applies cleanly)

git add hw/i2c/mpc_i2c.c

make

ppc64-softmmu/qemu-system-ppc64 -M ppce500 -cpu 
e5500 -kernel /mnt/sdb1/PPC-img/linux-image-4.20.12-X1000_X5000/X5000_and_QEMU_e5500/uImage-4.20 -nographic

git commit -a --author="Amit Singh Tomar <amit.tomar@freescale.com>"  
git format-patch -s 20b084c4b1401b7f8fbc385649d48c67b6f43d44
scripts/checkpatch.pl 0001-Re-applying-Freescale-PPC-E500-i2c-RTC-patch.patch

After this I created new message in Kmail and inserted 0001 file, edited it a 
bit more (adding patchwork link and mentioning fact I actually boot-tested 
patch), and then send out.

Guess next time I better to add second "-s" to git format-patch, so first 
signed-off-by-line from original will be around too?

Or ..lets wait what actual maintainers will say. 
>
> Regards,
> BALATON Zoltan

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Forward-porting RTC device for eppc500 ?
  2019-03-02 21:50     ` Andrew Randrianasulu
@ 2019-03-03  0:17       ` BALATON Zoltan
  2019-03-03  0:21         ` Andrew Randrianasulu
  0 siblings, 1 reply; 5+ messages in thread
From: BALATON Zoltan @ 2019-03-03  0:17 UTC (permalink / raw)
  To: Andrew Randrianasulu; +Cc: qemu-devel

On Sun, 3 Mar 2019, Andrew Randrianasulu wrote:
> git commit -a --author="Amit Singh Tomar <amit.tomar@freescale.com>"
> git format-patch -s 20b084c4b1401b7f8fbc385649d48c67b6f43d44
>
> scripts/checkpatch.pl 0001-Re-applying-Freescale-PPC-E500-i2c-RTC-patch.patch
>
> After this I created new message in Kmail and inserted 0001 file, edited it a
> bit more (adding patchwork link and mentioning fact I actually boot-tested
> patch), and then send out.

When sending patches to list make sure your mailer sends them as plain 
text and does not try to break up lines or alter white space because that 
breaks the patch and it won't apply with git am. You can check it in 
patchew (linked from SubmitAPatch wiki page):

https://patchew.org/QEMU/201903030021.22070.randrianasulu@gmail.com/

Not sure if Kmail can do this, maybe it has some settings for this but 
it's usually better to do all editing on the git commit and send patch 
mails with git send-email.

> Guess next time I better to add second "-s" to git format-patch, so first
> signed-off-by-line from original will be around too?
>
> Or ..lets wait what actual maintainers will say.

Yes, I'll let actual maintainers to comment then you can do a corrected 
version with any requested fixes or Reviewed-by tags added. I think for 
next revision you should leave original author's Signed-off-by in commit 
message and add yours with -s after that. (When sending another version of 
a patch use -v2 option of git format-patch to add v2 to the patch 
subject and so on for higher revisions if needed.)

Regards,
BALATON Zoltan

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Qemu-devel] [Qemu-ppc] Forward-porting RTC device for eppc500 ?
  2019-03-03  0:17       ` BALATON Zoltan
@ 2019-03-03  0:21         ` Andrew Randrianasulu
  0 siblings, 0 replies; 5+ messages in thread
From: Andrew Randrianasulu @ 2019-03-03  0:21 UTC (permalink / raw)
  To: BALATON Zoltan; +Cc: qemu-devel

В сообщении от Sunday 03 March 2019 03:17:47 BALATON Zoltan написал(а):
> On Sun, 3 Mar 2019, Andrew Randrianasulu wrote:
> > git commit -a --author="Amit Singh Tomar <amit.tomar@freescale.com>"
> > git format-patch -s 20b084c4b1401b7f8fbc385649d48c67b6f43d44
> >
> > scripts/checkpatch.pl
> > 0001-Re-applying-Freescale-PPC-E500-i2c-RTC-patch.patch
> >
> > After this I created new message in Kmail and inserted 0001 file, edited
> > it a bit more (adding patchwork link and mentioning fact I actually
> > boot-tested patch), and then send out.
>
> When sending patches to list make sure your mailer sends them as plain
> text and does not try to break up lines or alter white space because that
> breaks the patch and it won't apply with git am. You can check it in
> patchew (linked from SubmitAPatch wiki page):
>
> https://patchew.org/QEMU/201903030021.22070.randrianasulu@gmail.com/
>
> Not sure if Kmail can do this, maybe it has some settings for this but
> it's usually better to do all editing on the git commit and send patch
> mails with git send-email.

I see, it failed to apply. Will try to convince git send-mail to work (last time 
it failed for me, but it was long time ago)

>
> > Guess next time I better to add second "-s" to git format-patch, so first
> > signed-off-by-line from original will be around too?
> >
> > Or ..lets wait what actual maintainers will say.
>
> Yes, I'll let actual maintainers to comment then you can do a corrected
> version with any requested fixes or Reviewed-by tags added. I think for
> next revision you should leave original author's Signed-off-by in commit
> message and add yours with -s after that. (When sending another version of
> a patch use -v2 option of git format-patch to add v2 to the patch
> subject and so on for higher revisions if needed.)

Thanks.


>
> Regards,
> BALATON Zoltan

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-03-03  0:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-03-02 11:21 [Qemu-devel] Forward-porting RTC device for eppc500 ? Andrew Randrianasulu
2019-03-02 16:59 ` [Qemu-devel] [Qemu-ppc] " BALATON Zoltan
     [not found] ` <201903022144.45897.randrianasulu@gmail.com>
     [not found]   ` <alpine.BSF.2.21.9999.1903022116110.13215@zero.eik.bme.hu>
2019-03-02 21:50     ` Andrew Randrianasulu
2019-03-03  0:17       ` BALATON Zoltan
2019-03-03  0:21         ` Andrew Randrianasulu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).