Add MVME3100 PPC SBC
cover Add MVME3100 PPC SBC
This series adds simulation of MVME3100 powerpc SBCs, originally from Motorola, and now sold by Artesyn[1]. There are two variants differing in CPU speed and memory size.
I've been working on this sporadically for the past 2 year. Recently I've finished all the features which I have in mind. If this series is accepted there is a continuation which adds VME bus. I've found it useful in software compatibility testing. I wonder if there is any interest at large?
There are two main parts of this series. 1-5 are changing code common with the "ppce500" and "mpc8544ds" boards, with the remainder being additions.
The changes are to how the CCSR region is handled in order to support the CCSRBAR register which allows the whole region to be relocated. Also added are a couple of memory and clock configuration registers which RTEMS guests read.
#3 is actually a minor issue I found recently with the mpc8544 PCI host bridge, which I'm uncertain how to address. The host bridge device 0:0 identifies itself as a bridge, but doesn't properly implement the bridge config registers. This confuses Linux, which then does a full re-enumeration (successfully).
The rest are additions of an I2C controller, an I2C eeprom, an I2C RTC, and new board code.
My testing has been almost exclusively with an RTEMS guest[2]. Though I have recently done a little with Linux.
RTEMS guests (and Linux too for now) require a stub bootloader[3] to put the system in the same state as the real bootloader. RTEMS has an unfortunately strong dependence on bootloader provided configuration (eg. it doesn't re-enumerate the PCI bus).
[3] https://github.com/mdavidsaver/qemu/wiki
Michael Davidsaver (12):
e500: add board config options
e500: consolidate mpc8540 guts with e500-ccsr
e500: note possible bug with host bridge
e500: additional CCSR registers
e500: name openpic and pci host bridge
i2c: add mpc8540 i2c controller
qtest: add e500_i2c_create()
e500: add mpc8540 i2c controller to ccsr
nvram: add AT24Cx i2c eeprom
timer: add ds1375 RTC
ppc: add mvme3100 machine
tests: add mvme3100-test
default-configs/ppc-softmmu.mak | 1 + hw/i2c/Makefile.objs | 1 + hw/i2c/mpc8540_i2c.c | 287 +++++++++++++++++ hw/nvram/Makefile.objs | 1 + hw/nvram/eeprom_at24c.c | 205 ++++++++++++ hw/pci-host/ppce500.c | 13 +- hw/ppc/Makefile.objs | 4 +- hw/ppc/e500-ccsr.h | 17 - hw/ppc/e500.c | 59 ++-- hw/ppc/e500.h | 4 + hw/ppc/e500_ccsr.c | 220 +++++++++++++ hw/ppc/e500plat.c | 2 + hw/ppc/mpc8544_guts.c | 143 --------- hw/ppc/mpc8544ds.c | 2 + hw/ppc/mvme3100.c | 688 ++++++++++++++++++++++++++++++++++++++++ hw/ppc/mvme3100_cpld.c | 192 +++++++++++ hw/timer/Makefile.objs | 1 + hw/timer/ds1375-i2c.c | 293 +++++++++++++++++ tests/Makefile.include | 4 + tests/libqos/i2c-e500.c | 66 ++++ tests/libqos/i2c.h | 3 + tests/mvme3100-test.c | 79 +++++ 22 files changed, 2083 insertions(+), 202 deletions(-) create mode 100644 hw/i2c/mpc8540_i2c.c create mode 100644 hw/nvram/eeprom_at24c.c delete mode 100644 hw/ppc/e500-ccsr.h create mode 100644 hw/ppc/e500_ccsr.c delete mode 100644 hw/ppc/mpc8544_guts.c create mode 100644 hw/ppc/mvme3100.c create mode 100644 hw/ppc/mvme3100_cpld.c create mode 100644 hw/timer/ds1375-i2c.c create mode 100644 tests/libqos/i2c-e500.c create mode 100644 tests/mvme3100-test.c
Signature · 1 line
2.11.0
PATCH 1/12 e500: add board config options
allow board code to skip common NIC and guest image setup and configure decrementor frequency.
Existing boards unchanged.
--- hw/ppc/e500.c | 8 ++++++-- hw/ppc/e500.h | 3 +++ hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)
hw/ppc/e500.c +6 -2
@@ -826,7 +826,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) env->mpic_iack = params->ccsrbar_base +MPC8544_MPIC_REGS_OFFSET +0xa0 ; -ppc_booke_timers_init (cpu,400000000 ,PPC_TIMER_E500 ); +ppc_booke_timers_init (cpu, params->decrementor_freq,PPC_TIMER_E500 );/* Register reset handler */ if (!i) {
@@ -899,7 +899,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)if (!pci_bus)printf ("couldn't create PCI controller!\n" ); -if (pci_bus) { +if (pci_bus && !params->tsec_nic) {/* Register network interfaces. */ for (i =0 ; i < nb_nics; i++) {pci_nic_init_nofail (&nd_table[i], pci_bus,"virtio" ,NULL );
@@ -948,6 +948,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) sysbus_mmio_get_region(s, 0)); } +if (params->skip_load) { +return ; + } +/* Load kernel. */ if (machine->kernel_filename) { kernel_base = cur_base;
hw/ppc/e500.h +3 -0
@@ -22,6 +22,9 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t decrementor_freq;/* in Hz */ +bool skip_load; +bool tsec_nic; } PPCE500Params;void ppce500_init (MachineState *machine,PPCE500Params *params);
hw/ppc/e500plat.c +1 -0
@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .decrementor_freq = 400000000, };/* Older KVM versions don't support EPR which breaks guests when we announce
hw/ppc/mpc8544ds.c +1 -0
@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .decrementor_freq = 400000000, };if (machine->ram_size >0xc0000000 ) {
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 01/12] e500: add board config options
Quoted 5 lines · Michael Davidsaver
allow board code to skip common NIC and guest image setup and configure decrementor frequency.
Existing boards unchanged.Signed-off-by Michael Davidsaver <[email protected]>
So, it's spelled "decrementer".
Other than that, the patch looks correct. However having a big common function for overall init with a pile of ad-hoc configuration parameters is usually not a great way to go. I think what we want instead is to eliminate ppce500_init(), instead doing the setup logic
separately in each of the e500 machines. The large common slabs of
code can be helpers in e500.c, but the overall logic - including most of the things controlled by the current params - would be under the individual machine's control.
Quoted 78 lines
--- hw/ppc/e500.c | 8 ++++++-- hw/ppc/e500.h | 3 +++ hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)hw/ppc/e500.c +6
-2@@ -826,7 +826,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) env->mpic_iack = params->ccsrbar_base +MPC8544_MPIC_REGS_OFFSET +0xa0 ; -ppc_booke_timers_init (cpu,400000000 ,PPC_TIMER_E500 ); +ppc_booke_timers_init (cpu, params->decrementor_freq,PPC_TIMER_E500 );/* Register reset handler */ if (!i) {@@ -899,7 +899,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)if (!pci_bus)printf ("couldn't create PCI controller!\n" ); -if (pci_bus) { +if (pci_bus && !params->tsec_nic) {/* Register network interfaces. */ for (i =0 ; i < nb_nics; i++) {pci_nic_init_nofail (&nd_table[i], pci_bus,"virtio" ,NULL );@@ -948,6 +948,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) sysbus_mmio_get_region(s, 0)); } +if (params->skip_load) { +return ; + } +/* Load kernel. */ if (machine->kernel_filename) { kernel_base = cur_base;hw/ppc/e500.h +3
-0@@ -22,6 +22,9 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t decrementor_freq;/* in Hz */ +bool skip_load; +bool tsec_nic; } PPCE500Params;void ppce500_init (MachineState *machine,PPCE500Params *params);hw/ppc/e500plat.c +1
-0@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .decrementor_freq = 400000000, };/* Older KVM versions don't support EPR which breaks guests when we announce hw/ppc/mpc8544ds.c +1
-0@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .decrementor_freq = 400000000, };if (machine->ram_size >0xc0000000 ) {
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [PATCH 01/12] e500: add board config options
Quoted 9 lines · David Gibson
Quoted 5 lines · Michael Davidsaver
allow board code to skip common NIC and guest image setup and configure decrementor frequency.
Existing boards unchanged.Signed-off-by Michael Davidsaver <[email protected]>So, it's spelled "decrementer".
Quoted 8 lines
Other than that, the patch looks correct. However having a big common function for overall init with a pile of ad-hoc configuration parameters is usually not a great way to go. I think what we want instead is to eliminate
ppce500_init(), instead doing the setup logic
separately in each of the e500 machines. The large common slabs of
code can be helpers ine500.c, but the overall logic - including most of the things controlled by the current params - would be under the individual machine's control.
I agree that ppce500_init() is unwieldy, and am willing to spend some time on cleanup. I'm just not sure what to do.
I can see moving initialization of at least the serial, i2c, gpio, and possibly MPIC and PCI host bridge into the e500-ccsr class.
I'm not sure what to do with all the device tree construction code in e500.c, which has a bunch of hard coded register offsets. A comment here summarizes the problem nicely.
Quoted 3 lines
/* TODO: parameterize */
#defineMPC8544_CCSRBAR_SIZE0x00100000ULL
#defineMPC8544_MPIC_REGS_OFFSET0x40000ULL
It seems desirable to avoid having these offsets appear in two different files, which could allow them to get out of sync.
I had the idea of using an Interface to split up device tree construction, and was encouraged to find PnvXScomInterfaceClass which seems be a way of combining device tree construction in a device class. Is this the way to go?
Some guidance would be appreciated.
Michael
Quoted 79 lines
Quoted 78 lines
--- hw/ppc/e500.c | 8 ++++++-- hw/ppc/e500.h | 3 +++ hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)hw/ppc/e500.c +6
-2@@ -826,7 +826,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) env->mpic_iack = params->ccsrbar_base +MPC8544_MPIC_REGS_OFFSET +0xa0 ; -ppc_booke_timers_init (cpu,400000000 ,PPC_TIMER_E500 ); +ppc_booke_timers_init (cpu, params->decrementor_freq,PPC_TIMER_E500 );/* Register reset handler */ if (!i) {@@ -899,7 +899,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)if (!pci_bus)printf ("couldn't create PCI controller!\n" ); -if (pci_bus) { +if (pci_bus && !params->tsec_nic) {/* Register network interfaces. */ for (i =0 ; i < nb_nics; i++) {pci_nic_init_nofail (&nd_table[i], pci_bus,"virtio" ,NULL );@@ -948,6 +948,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) sysbus_mmio_get_region(s, 0)); } +if (params->skip_load) { +return ; + } +/* Load kernel. */ if (machine->kernel_filename) { kernel_base = cur_base;hw/ppc/e500.h +3
-0@@ -22,6 +22,9 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t decrementor_freq;/* in Hz */ +bool skip_load; +bool tsec_nic; } PPCE500Params;void ppce500_init (MachineState *machine,PPCE500Params *params);hw/ppc/e500plat.c +1
-0@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .decrementor_freq = 400000000, };/* Older KVM versions don't support EPR which breaks guests when we announce hw/ppc/mpc8544ds.c +1
-0@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .decrementor_freq = 400000000, };if (machine->ram_size >0xc0000000 ) {
Re: [Qemu-devel] [Qemu-ppc] [PATCH 01/12] e500: add board config options
Quoted 19 lines · Michael Davidsaver
Quoted 9 lines · David Gibson
Quoted 5 lines · Michael Davidsaver
allow board code to skip common NIC and guest image setup and configure decrementor frequency.
Existing boards unchanged.Signed-off-by Michael Davidsaver <[email protected]>So, it's spelled "decrementer".
Quoted 8 lines
Other than that, the patch looks correct. However having a big common function for overall init with a pile of ad-hoc configuration parameters is usually not a great way to go. I think what we want instead is to eliminate
ppce500_init(), instead doing the setup logic
separately in each of the e500 machines. The large common slabs of
code can be helpers ine500.c, but the overall logic - including most of the things controlled by the current params - would be under the individual machine's control.
Quoted 5 lines
I agree that
ppce500_init()is unwieldy, and am willing to spend some time on cleanup. I'm just not sure what to do.I can see moving initialization of at least the serial, i2c, gpio, and possibly MPIC and PCI host bridge into the e500-ccsr class.
each of these controllers should have a QOM model possibly.
I think that the part above :
/* Load kernel. */
is machine specific and the part below is generic and could be called from each machine init routine. You would still need some op/struct for the device tree.
Quoted 8 lines
I'm not sure what to do with all the device tree construction code in
e500.c, which has a bunch of hard coded register offsets. A comment here summarizes the problem nicely.Quoted 3 lines
/* TODO: parameterize */
#defineMPC8544_CCSRBAR_SIZE0x00100000ULL
#defineMPC8544_MPIC_REGS_OFFSET0x40000ULL
Quoted 7 lines
It seems desirable to avoid having these offsets appear in two different files, which could allow them to get out of sync.
I had the idea of using an Interface to split up device tree construction, and was encouraged to find PnvXScomInterfaceClass which seems be a way of combining device tree construction in a device class. Is this the way to go?
yes. You would need to QOM'ify the whole machine and have all controllers be children of a 'board' object to loop on them.
Quoted 1 line
Some guidance would be appreciated.
The models of the ARM SoC are good examples to follow. You could check the Aspeed machines which have been slowly growing and which have had some good reviews from Peter. The ARM machines are all QOM'ified and that might be difficult to apply to the e500 boards quickly. At least, the models for the new controllers should follow QOM. It will ease the future work.
Thanks,
C.
Quoted 85 lines
Michael
Quoted 79 lines
Quoted 78 lines
--- hw/ppc/e500.c | 8 ++++++-- hw/ppc/e500.h | 3 +++ hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 4 files changed, 11 insertions(+), 2 deletions(-)hw/ppc/e500.c +6
-2@@ -826,7 +826,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) env->mpic_iack = params->ccsrbar_base +MPC8544_MPIC_REGS_OFFSET +0xa0 ; -ppc_booke_timers_init (cpu,400000000 ,PPC_TIMER_E500 ); +ppc_booke_timers_init (cpu, params->decrementor_freq,PPC_TIMER_E500 );/* Register reset handler */ if (!i) {@@ -899,7 +899,7 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)if (!pci_bus)printf ("couldn't create PCI controller!\n" ); -if (pci_bus) { +if (pci_bus && !params->tsec_nic) {/* Register network interfaces. */ for (i =0 ; i < nb_nics; i++) {pci_nic_init_nofail (&nd_table[i], pci_bus,"virtio" ,NULL );@@ -948,6 +948,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) sysbus_mmio_get_region(s, 0)); } +if (params->skip_load) { +return ; + } +/* Load kernel. */ if (machine->kernel_filename) { kernel_base = cur_base;hw/ppc/e500.h +3
-0@@ -22,6 +22,9 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t decrementor_freq;/* in Hz */ +bool skip_load; +bool tsec_nic; } PPCE500Params;void ppce500_init (MachineState *machine,PPCE500Params *params);hw/ppc/e500plat.c +1
-0@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .decrementor_freq = 400000000, };/* Older KVM versions don't support EPR which breaks guests when we announce hw/ppc/mpc8544ds.c +1
-0@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .decrementor_freq = 400000000, };if (machine->ram_size >0xc0000000 ) {
Re: [Qemu-devel] [PATCH 01/12] e500: add board config options
In reply to Michael DavidsaverQuoted 22 lines · Michael Davidsaver
Quoted 9 lines · David Gibson
Quoted 5 lines · Michael Davidsaver
allow board code to skip common NIC and guest image setup and configure decrementor frequency.
Existing boards unchanged.Signed-off-by Michael Davidsaver <[email protected]>So, it's spelled "decrementer".
Quoted 8 lines
Other than that, the patch looks correct. However having a big common function for overall init with a pile of ad-hoc configuration parameters is usually not a great way to go. I think what we want instead is to eliminate
ppce500_init(), instead doing the setup logic
separately in each of the e500 machines. The large common slabs of
code can be helpers ine500.c, but the overall logic - including most of the things controlled by the current params - would be under the individual machine's control.I agree that
ppce500_init()is unwieldy, and am willing to spend some time on cleanup. I'm just not sure what to do.
Quoted 6 lines
I can see moving initialization of at least the serial, i2c, gpio, and possibly MPIC and PCI host bridge into the e500-ccsr class.
I'm not sure what to do with all the device tree construction code in
e500.c, which has a bunch of hard coded register offsets. A comment here summarizes the problem nicely.
So, those aren't bad ideas for cleanups, but I'm not going to insist on that before merging this stuff. What I'm after is something simpler. At the moment the structure looks something like this:
machine_init() {
common_init(big pile of parameters);
}
common_init() {
chunk1;
if (param1)
chunk2;
chunk3;
if (param2)
chunk4;
...
}What I would prefer is:
machine_init1() {
chunk1();
chunk2(param1)
chunk3(param3);
}
machine_init2() {
chunk1();
chunk3(param3);
chunk4(param2);
}Quoted 5 lines
Quoted 4 lines
/* TODO: parameterize */
#defineMPC8544_CCSRBAR_SIZE0x00100000ULL
#defineMPC8544_MPIC_REGS_OFFSET0x40000ULL
Quoted 7 lines
It seems desirable to avoid having these offsets appear in two different files, which could allow them to get out of sync.
I had the idea of using an Interface to split up device tree construction, and was encouraged to find PnvXScomInterfaceClass which seems be a way of combining device tree construction in a device class. Is this the way to go?
At some point, quite likely (I've actually had thoughts on making devicetree construction more convenient qemu wide, but haven't had time to do much about it).
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 3/12 e500: note possible bug with host bridge
In reply to Michael Davidsaver--- hw/pci-host/ppce500.c | 3 +++ 1 file changed, 3 insertions(+)
hw/pci-host/ppce500.c +3 -0
@@ -424,6 +424,9 @@ static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp)MemoryRegion *ccsr_mr =sysbus_mmio_get_region (ccsr,0 );pci_config_set_class (d->config,PCI_CLASS_BRIDGE_PCI ); +/* BUG? identifies as PCI_HEADER_TYPE_BRIDGE but uses +* standard device config read/write +*/ d->config[PCI_HEADER_TYPE ] = (d->config[PCI_HEADER_TYPE ] &PCI_HEADER_TYPE_MULTI_FUNCTION ) |PCI_HEADER_TYPE_BRIDGE ;
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 03/12] e500: note possible bug with host bridge
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>
I'm not sure if you're saying you think there is a hardware bug which we're faithfully emulating, or a software bug.
Quoted 18 lines
--- hw/pci-host/ppce500.c | 3 +++ 1 file changed, 3 insertions(+)hw/pci-host/ppce500.c +3
-0@@ -424,6 +424,9 @@ static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp)MemoryRegion *ccsr_mr =sysbus_mmio_get_region (ccsr,0 );pci_config_set_class (d->config,PCI_CLASS_BRIDGE_PCI ); +/* BUG? identifies as PCI_HEADER_TYPE_BRIDGE but uses +* standard device config read/write +*/ d->config[PCI_HEADER_TYPE ] = (d->config[PCI_HEADER_TYPE ] &PCI_HEADER_TYPE_MULTI_FUNCTION ) |PCI_HEADER_TYPE_BRIDGE ;
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [PATCH 03/12] e500: note possible bug with host bridge
Quoted 5 lines · David Gibson
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>I'm not sure if you're saying you think there is a hardware bug which we're faithfully emulating, or a software bug.
I mean that the emulation is incorrect in that it just sets config[PCI_HEADER_TYPE]==PCI_HEADER_TYPE_BRIDGE but does none of the other initialization of the base-pci-bridge class.
I specifically observed Linux being confused by the fact that the primary, secondary, and subordinate bus registers don't work right because they're actually the BAR2 address register.
Further, it seems odd that a host bridge would identify itself as a pci-to-pci bridge. The mpc8540 doesn't. The mpc8544 docs aren't clear, and I don't have a real one to test. My inclination is to remove the line changing PCI_HEADER_TYPE, but I'm hesitant about breaking things. Especially since this doesn't trigger mis-behavior in Linux or RTEMS.
Quoted 19 lines
Quoted 18 lines
--- hw/pci-host/ppce500.c | 3 +++ 1 file changed, 3 insertions(+)hw/pci-host/ppce500.c +3
-0@@ -424,6 +424,9 @@ static void e500_pcihost_bridge_realize(PCIDevice *d, Error **errp)MemoryRegion *ccsr_mr =sysbus_mmio_get_region (ccsr,0 );pci_config_set_class (d->config,PCI_CLASS_BRIDGE_PCI ); +/* BUG? identifies as PCI_HEADER_TYPE_BRIDGE but uses +* standard device config read/write +*/ d->config[PCI_HEADER_TYPE ] = (d->config[PCI_HEADER_TYPE ] &PCI_HEADER_TYPE_MULTI_FUNCTION ) |PCI_HEADER_TYPE_BRIDGE ;
PATCH 4/12 e500: additional CCSR registers
In reply to Michael DavidsaverAdd CCSRBAR to allow CCSR region to be relocated.
Guest memory size introspection.
Dummy RAM error controls.
Guest clock introspection.
--- hw/ppc/e500.c | 2 ++ hw/ppc/e500.h | 1 + hw/ppc/e500_ccsr.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 5 files changed, 75 insertions(+), 2 deletions(-)
hw/ppc/e500.c +2 -0
@@ -853,7 +853,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) dev =qdev_create (NULL ,"e500-ccsr" );object_property_add_child (qdev_get_machine (),"e500-ccsr" ,OBJECT (dev),NULL ); +qdev_prop_set_uint32 (dev,"porpllsr" , params->porpllsr);qdev_prop_set_uint32 (dev,"base" , params->ccsrbar_base); +qdev_prop_set_uint32 (dev,"ram-size" , ram_size);qdev_init_nofail (dev); ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 );
hw/ppc/e500.h +1 -0
@@ -22,6 +22,7 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t porpllsr;/* value of PORPLLSR register */ uint32_t decrementor_freq;/* in Hz */ bool skip_load;bool tsec_nic;
hw/ppc/e500_ccsr.c +70 -2
129 lines not on this page · raw message
hw/ppc/e500plat.c +1 -0
@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .porpllsr = 0, /* TODO missing valid value */ .decrementor_freq = 400000000, };
hw/ppc/mpc8544ds.c +1 -0
@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .porpllsr = 0, /* TODO missing valid value */ .decrementor_freq = 400000000, };
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 04/12] e500: additional CCSR registers
Quoted 6 lines · Michael Davidsaver
Add CCSRBAR to allow CCSR region to be relocated.
Guest memory size introspection.
Dummy RAM error controls.
Guest clock introspection.Signed-off-by Michael Davidsaver <[email protected]>
Looks fine from the POV of someone who doesn't know details about e500.
Quoted 197 lines
--- hw/ppc/e500.c | 2 ++ hw/ppc/e500.h | 1 + hw/ppc/e500_ccsr.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- hw/ppc/e500plat.c | 1 + hw/ppc/mpc8544ds.c | 1 + 5 files changed, 75 insertions(+), 2 deletions(-)hw/ppc/e500.c +2
-0@@ -853,7 +853,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) dev =qdev_create (NULL ,"e500-ccsr" );object_property_add_child (qdev_get_machine (),"e500-ccsr" ,OBJECT (dev),NULL ); +qdev_prop_set_uint32 (dev,"porpllsr" , params->porpllsr);qdev_prop_set_uint32 (dev,"base" , params->ccsrbar_base); +qdev_prop_set_uint32 (dev,"ram-size" , ram_size);qdev_init_nofail (dev); ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 );hw/ppc/e500.h +1
-0@@ -22,6 +22,7 @@ typedef struct PPCE500Params {hwaddr pci_mmio_base;hwaddr pci_mmio_bus_base;hwaddr spin_base; +uint32_t porpllsr;/* value of PORPLLSR register */ uint32_t decrementor_freq;/* in Hz */ bool skip_load;bool tsec_nic;hw/ppc/e500_ccsr.c +70
-2@@ -31,6 +31,16 @@/* E500_ denotes registers common to all */ +#define E500_CCSRBAR (0) + +#define E500_CS0_BNDS (0x2000) + +#define E500_CS0_CONFIG (0x2080) + +#define E500_ERR_DETECT (0x2e40) +#define E500_ERR_DISABLE (0x2e44) + +#define E500_PORPLLSR (0xE0000)#define E500_PVR (0xE00A0)#define E500_SVR (0xE00A4)@@ -44,7 +54,11 @@ typedef struct {MemoryRegion iomem; -uint32_t defbase; +uint32_t defbase, base; +uint32_t ram_size; +uint32_t merrd; + +uint32_t porpllsr; } CCSRState;#define TYPE_E500_CCSR "e500-ccsr"@@ -53,10 +67,28 @@ typedef struct {static uint64_t e500_ccsr_read (void *opaque,hwaddr addr,unsigned size) { +CCSRState *ccsr = opaque;PowerPCCPU *cpu =POWERPC_CPU (current_cpu);CPUPPCState *env = &cpu->env;switch (addr) { +case E500_CCSRBAR : +return ccsr->base >>12 ; +case E500_CS0_BNDS : +/* we model all RAM in a single chip with addresses [0, ram_size) */ +return (ccsr->ram_size -1 ) >>24 ; +case E500_CS0_CONFIG : +return 1 <<31 ; +case E500_ERR_DETECT : +return 0 ;/* (errors not modeled) */ +case E500_ERR_DISABLE : +return ccsr->merrd; +case E500_PORPLLSR : +if (!ccsr->porpllsr) { +qemu_log_mask (LOG_UNIMP , +"Machine does not provide valid PORPLLSR\n" ); + } +return ccsr->porpllsr;case E500_PVR :return env->spr[SPR_PVR ];case E500_SVR :@@ -72,10 +104,22 @@ static uint64_t e500_ccsr_read(void *opaque, hwaddr addr,static void e500_ccsr_write (void *opaque,hwaddr addr,uint64_t value,unsigned size) { +CCSRState *ccsr = opaque;PowerPCCPU *cpu =POWERPC_CPU (current_cpu);CPUPPCState *env = &cpu->env;uint32_t svr = env->spr[SPR_E500_SVR ] >>16 ; +switch (addr) { +case E500_CCSRBAR : + value &=0x000fff00 ; + ccsr->base = value <<12 ; +sysbus_mmio_map (SYS_BUS_DEVICE (ccsr),0 , ccsr->base); +return ; +case E500_ERR_DISABLE : + ccsr->merrd = value &0xd ; +return ; + } +switch (svr) {case 0 :/* generic. assumed to be mpc8544ds or e500plat board */ case 0x8034 :/* mpc8544 */ @@ -104,11 +148,20 @@ static const MemoryRegionOps e500_ccsr_ops = { } }; +static int e500_ccsr_post_load (void *opaque,int version_id) +{ +CCSRState *ccsr = opaque; + +sysbus_mmio_map (SYS_BUS_DEVICE (ccsr),0 , ccsr->base); +return 0 ; +} +static void e500_ccsr_reset (DeviceState *dev) {CCSRState *ccsr =E500_CCSR (dev); -sysbus_mmio_map (SYS_BUS_DEVICE (dev),0 , ccsr->defbase); + ccsr->base = ccsr->defbase; +e500_ccsr_post_load (ccsr,1 ); }static void e500_ccsr_initfn (Object *obj)@@ -123,15 +176,30 @@ static void e500_ccsr_initfn(Object *obj)static Property e500_ccsr_props[] = {DEFINE_PROP_UINT32 ("base" , CCSRState, defbase,0xff700000 ), +DEFINE_PROP_UINT32 ("ram-size" , CCSRState, ram_size,0 ), +DEFINE_PROP_UINT32 ("porpllsr" , CCSRState, porpllsr,0 ),DEFINE_PROP_END_OF_LIST () }; +static const VMStateDescription vmstate_e500_ccsr = { + .name =TYPE_E500_CCSR , + .version_id =1 , + .minimum_version_id =1 , + .post_load = e500_ccsr_post_load, + .fields = (VMStateField []) { +VMSTATE_UINT32 (base, CCSRState), +VMSTATE_UINT32 (merrd, CCSRState), +VMSTATE_END_OF_LIST () + } +}; +static void e500_ccsr_class_initfn (ObjectClass *klass,void *data) {DeviceClass *dc =DEVICE_CLASS (klass); dc->props = e500_ccsr_props; + dc->vmsd = &vmstate_e500_ccsr; dc->reset = e500_ccsr_reset; }hw/ppc/e500plat.c +1
-0@@ -47,6 +47,7 @@ static void e500plat_init(MachineState *machine) .pci_mmio_base = 0xC00000000ULL, .pci_mmio_bus_base = 0xE0000000ULL, .spin_base = 0xFEF000000ULL, + .porpllsr = 0, /* TODO missing valid value */ .decrementor_freq = 400000000, };hw/ppc/mpc8544ds.c +1
-0@@ -40,6 +40,7 @@ static void mpc8544ds_init(MachineState *machine) .pci_mmio_bus_base = 0xC0000000ULL, .pci_pio_base = 0xE1000000ULL, .spin_base = 0xEF000000ULL, + .porpllsr = 0, /* TODO missing valid value */ .decrementor_freq = 400000000, };
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 5/12 e500: name openpic and pci host bridge
In reply to Michael Davidsaver--- hw/ppc/e500.c | 4 ++++ 1 file changed, 4 insertions(+)
hw/ppc/e500.c +4 -0
@@ -685,6 +685,8 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,int i, j, k; dev =qdev_create (NULL ,TYPE_OPENPIC ); +object_property_add_child (qdev_get_machine (),"pic" ,OBJECT (dev), + &error_fatal);qdev_prop_set_uint32 (dev,"model" , params->mpic_version);qdev_prop_set_uint32 (dev,"nb_cpus" , smp_cpus);
@@ -876,6 +878,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)/* PCI */ dev =qdev_create (NULL ,"e500-pcihost" ); +object_property_add_child (qdev_get_machine (),"pci-host" ,OBJECT (dev), + &error_abort);qdev_prop_set_uint32 (dev,"first_slot" , params->pci_first_slot);qdev_prop_set_uint32 (dev,"first_pin_irq" , pci_irq_nrs[0 ]);qdev_init_nofail (dev);
Signature · 1 line
2.11.0
David Gibson
AppliedRe: [Qemu-devel] [PATCH 05/12] e500: name openpic and pci host bridge
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>
Applied to ppc-for-2.12.
Quoted 26 lines
--- hw/ppc/e500.c | 4 ++++ 1 file changed, 4 insertions(+)hw/ppc/e500.c +4
-0@@ -685,6 +685,8 @@ static DeviceState *ppce500_init_mpic_qemu(PPCE500Params *params,int i, j, k; dev =qdev_create (NULL ,TYPE_OPENPIC ); +object_property_add_child (qdev_get_machine (),"pic" ,OBJECT (dev), + &error_fatal);qdev_prop_set_uint32 (dev,"model" , params->mpic_version);qdev_prop_set_uint32 (dev,"nb_cpus" , smp_cpus);@@ -876,6 +878,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)/* PCI */ dev =qdev_create (NULL ,"e500-pcihost" ); +object_property_add_child (qdev_get_machine (),"pci-host" ,OBJECT (dev), + &error_abort);qdev_prop_set_uint32 (dev,"first_slot" , params->pci_first_slot);qdev_prop_set_uint32 (dev,"first_pin_irq" , pci_irq_nrs[0 ]);qdev_init_nofail (dev);
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 6/12 i2c: add mpc8540 i2c controller
In reply to Michael Davidsaver--- hw/i2c/Makefile.objs | 1 + hw/i2c/mpc8540_i2c.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 hw/i2c/mpc8540_i2c.c
hw/i2c/Makefile.objs +1 -0
@@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o obj-$(CONFIG_OMAP) += omap_i2c.o obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_E500) += mpc8540_i2c.o
hw/i2c/mpc8540_i2c.c new file +287 -0
287 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 06/12] i2c: add mpc8540 i2c controller
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>
I can't speak to the accuracy of the emulation, but it's presumably better than nothing at all. Therefore, applied to ppc-for-2.12.
Quoted 308 lines
--- hw/i2c/Makefile.objs | 1 + hw/i2c/mpc8540_i2c.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 hw/i2c/mpc8540_i2c.chw/i2c/Makefile.objs +1
-0@@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o obj-$(CONFIG_OMAP) += omap_i2c.o obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_E500) += mpc8540_i2c.ohw/i2c/mpc8540_i2c.c new file +287
-0@@ -0,0 +1,287 @@ +/* +* MPC8540 I2C bus interface +* As described in +* MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1 +* Part 2 chapter 11 +* +* Copyright (c) 2015 Michael Davidsaver +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +*/ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/i2c/i2c.h" +#include "hw/sysbus.h" + +/* #define DEBUG_LVL 0 */ + +#ifdef DEBUG_LVL +#define DPRINTK (LVL ,FMT , ...) do { if ((LVL) <= DEBUG_LVL) { \ + printf(TYPE_MPC8540_I2C " : " FMT, ## __VA_ARGS__); } } while (0) +#else +#define DPRINTK (LVL ,FMT , ...) do {} while (0) +#endif + +#define LOG (MSK ,FMT , ...) qemu_log_mask(MSK, TYPE_MPC8540_I2C \ + " : " FMT, ## __VA_ARGS__) + +#define TYPE_MPC8540_I2C "mpc8540-i2c" +#define MPC8540_I2C (obj) OBJECT_CHECK(I2CState, (obj), TYPE_MPC8540_I2C) + +/* offsets relative to CCSR offset 0x3000 */ +#define R_I2CADR (0) +#define R_I2CFDR (4) +#define R_I2CCR (8) +#define R_I2CSR (0xc) +#define R_I2CDR (0x10) +#define R_I2CDFSRR (0x14) + +FIELD(I2CCR, MEN, 7, 1) +FIELD(I2CCR, MIEN, 6, 1) +FIELD(I2CCR, MSTA, 5, 1) +FIELD(I2CCR, MTX, 4, 1) +FIELD(I2CCR, TXAK, 3, 1) +FIELD(I2CCR, RSTA, 2, 1) +FIELD(I2CCR, BCST, 0, 1) + +FIELD(I2CSR, MCF, 7, 1) +FIELD(I2CSR, MAAS, 6, 1) +FIELD(I2CSR, MBB, 5, 1) +FIELD(I2CSR, MAL, 4, 1) +FIELD(I2CSR, BCSTM, 3, 1) +FIELD(I2CSR, SRW, 2, 1) +FIELD(I2CSR, MIF, 1, 1) +FIELD(I2CSR, RXAK, 0, 1) + +typedef struct I2CState { +SysBusDevice parent_obj; + +I2CBus *bus; + +uint8_t ctrl, sts; +uint8_t freq, filt; +/* Reads are pipelined, this is the next data value */ +uint8_t dbuf; + +qemu_irq irq; + +MemoryRegion mmio; +}I2CState ; + +#define I2CCR (BIT ) FIELD_EX32(i2c->ctrl, I2CCR, BIT) +#define I2CSR (BIT ) FIELD_EX32(i2c->sts, I2CSR, BIT) + +#define I2CSR_SET (BIT ,VAL ) do {\ + i2c->sts = FIELD_DP32(i2c->sts, I2CSR, BIT, VAL);\ + } while (0) + +static +void mpc8540_update_irq (I2CState *i2c) +{ +int ena = i2c->ctrl &0x40 , + sts = i2c->sts &0x02 , + act = !!(ena && sts); + +DPRINTK (1 ,"IRQ %c ena %c sts %c\n" , + act ?'X' :'_' , + ena ?'X' :'_' , + sts ?'X' :'_' ); + +qemu_set_irq (i2c->irq, act); +} + +static +uint64_t mpc8540_i2c_read (void *opaque,hwaddr addr,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t val, offset = addr; + +switch (offset) { +case R_I2CADR :/* ADDR */ + val =0 ; +break ; +case R_I2CFDR :/* Freq Div. */ + val = i2c->freq; +break ; +case R_I2CCR :/* CONTROL */ + val = i2c->ctrl & ~0x06 ; +break ; +case R_I2CSR :/* STATUS */ + val = i2c->sts; +break ; +case R_I2CDR :/* DATA */ +/* Reads are "pipelined" and so return the previous value of the +* register +*/ + val = i2c->dbuf; +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus) ||I2CCR (MTX )) { +LOG (LOG_GUEST_ERROR ,"Read during addr or tx\n" ); + i2c->dbuf =0xff ; + }else { +int ret =i2c_recv (i2c->bus); + i2c->dbuf = (uint8_t )ret; +DPRINTK (0 ,"READ %02x ('%c')\n" , i2c->dbuf, (char )i2c->dbuf); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); +mpc8540_update_irq (i2c); + } + }else { + i2c->dbuf =0xff ; +LOG (LOG_GUEST_ERROR ,"Read when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val = i2c->filt; +break ; +default : + val =0xff ; + } + +DPRINTK (offset ==0xc ?2 :1 ," read %08x -> %08x\n" , + (unsigned )offset, (unsigned )val); +return val; +} + +static +void mpc8540_i2c_write (void *opaque,hwaddr addr,uint64_t val,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t offset = addr; + +DPRINTK (1 ," write %08x <- %08x\n" , (unsigned )offset, (unsigned )val); + +switch (offset) { +case R_I2CADR :/* ADDR */ +break ; +case R_I2CFDR :/* Freq Div. */ + i2c->freq = val &0x3f ; +break ; +case R_I2CCR :/* CONTROL CCR */ +if (!FIELD_EX32 (val,I2CCR ,MEN )) { +DPRINTK (0 ,"Not Enabled\n" ); + + }else if (!I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 0 -> 1 is START */ + +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"START\n" ); +i2c_end_transfer (i2c->bus);/* paranoia */ + + }else if (I2CCR (MSTA ) && !FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 1 -> 0 is STOP */ + +I2CSR_SET (MBB ,0 ); +DPRINTK (0 ,"STOP\n" ); +i2c_end_transfer (i2c->bus); + + }else if (I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,RSTA )) { +i2c_end_transfer (i2c->bus); +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"REP START\n" ); + + } +/* RSTA always reads zero, bit 1 unusd */ + val &=0xf9 ; + i2c->ctrl = val; +mpc8540_update_irq (i2c); +break ; +case R_I2CSR :/* STATUS CSR */ +/* only MAL and MIF are writable */ + val &=0x12 ; + i2c->sts &= ~0x12 ; + i2c->sts |= val; +mpc8540_update_irq (i2c); +break ; +case R_I2CDR :/* DATA CDR */ +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus)) { +if (i2c_start_transfer (i2c->bus, val >>1 , val &1 )) { +LOG (LOG_GUEST_ERROR ,"I2C no device %02x\n" , + (unsigned )(val &0xfe )); + }else { +DPRINTK (0 ,"ADDR %02x\n" , (unsigned )(val &0xfe )); + } +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + + }else if (I2CCR (MTX )) { +DPRINTK (0 ,"WRITE %02x\n" , (unsigned )val); +i2c_send (i2c->bus, val); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write during read\n" ); + } +mpc8540_update_irq (i2c); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val &=0x3f ; + i2c->filt = val; +break ; + } + +DPRINTK (1 ,"I2CCR = %02x I2SCR = %02x\n" , i2c->ctrl, i2c->sts); +} + +static const MemoryRegionOps i2c_ops = { + .read = mpc8540_i2c_read, + .write = mpc8540_i2c_write, + .endianness =DEVICE_NATIVE_ENDIAN , + .impl = { + .min_access_size =1 , + .max_access_size =1 , + }, +}; + +static +void mpc8540_i2c_reset (DeviceState *dev) +{ +I2CState *i2c =MPC8540_I2C (dev); + + i2c->sts =0x81 ;/* transfer complete and ack received */ +} + +static int mpc8540_i2c_inst_init (SysBusDevice *dev) +{ +I2CState *i2c =MPC8540_I2C (dev); + + i2c->bus =i2c_init_bus (&dev->parent_obj,"bus" ); + +memory_region_init_io (&i2c->mmio, &dev->parent_obj.parent_obj, + &i2c_ops, i2c,TYPE_MPC8540_I2C ,0x18 ); + +sysbus_init_mmio (dev, &i2c->mmio); +sysbus_init_irq (dev, &i2c->irq); +return 0 ; +} + +static void mpc8540_i2c_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = &mpc8540_i2c_inst_init; + dc->reset = &mpc8540_i2c_reset; +} + +static const TypeInfo mpc8540_i2c_type = { + .name =TYPE_MPC8540_I2C , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (I2CState), + .class_size =sizeof (SysBusDeviceClass), + .class_init = mpc8540_i2c_class_init, +}; + +static void mpc8540_i2c_register (void ) +{ +type_register_static (&mpc8540_i2c_type); +} + +type_init (mpc8540_i2c_register)
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [Qemu-ppc] [PATCH 06/12] i2c: add mpc8540 i2c controller
In reply to Michael DavidsaverHello,
The model should be QOM'ified.
Quoted 35 lines · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>--- hw/i2c/Makefile.objs | 1 + hw/i2c/mpc8540_i2c.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 hw/i2c/mpc8540_i2c.chw/i2c/Makefile.objs +1
-0@@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o obj-$(CONFIG_OMAP) += omap_i2c.o obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_E500) += mpc8540_i2c.ohw/i2c/mpc8540_i2c.c new file +13
-0@@ -0,0 +1,287 @@ +/* +* MPC8540 I2C bus interface +* As described in +* MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1 +* Part 2 chapter 11 +* +* Copyright (c) 2015 Michael Davidsaver +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +*/ +#include "qemu/osdep.h" +#include "qemu/log.h"
hw/i2c/mpc8540_i2c.c line 23
Quoted 10 lines
hw/i2c/mpc8540_i2c.c new file +10
-0+#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/i2c/i2c.h" +#include "hw/sysbus.h" + +/* #define DEBUG_LVL 0 */ + +#ifdef DEBUG_LVL +#define DPRINTK (LVL ,FMT , ...) do { if ((LVL) <= DEBUG_LVL) { \ + printf(TYPE_MPC8540_I2C " : " FMT, ## __VA_ARGS__); } } while (0)
hmm, I am not sure 'printfs' are welcomed in QEMU.
Quoted 39 lines
hw/i2c/mpc8540_i2c.c new file +38
-0+#else +#define DPRINTK (LVL ,FMT , ...) do {} while (0) +#endif + +#define LOG (MSK ,FMT , ...) qemu_log_mask(MSK, TYPE_MPC8540_I2C \ + " : " FMT, ## __VA_ARGS__) +#define TYPE_MPC8540_I2C "mpc8540-i2c" +#define MPC8540_I2C (obj) OBJECT_CHECK(I2CState, (obj), TYPE_MPC8540_I2C) + +/* offsets relative to CCSR offset 0x3000 */ +#define R_I2CADR (0) +#define R_I2CFDR (4) +#define R_I2CCR (8) +#define R_I2CSR (0xc) +#define R_I2CDR (0x10) +#define R_I2CDFSRR (0x14) + +FIELD(I2CCR, MEN, 7, 1) +FIELD(I2CCR, MIEN, 6, 1) +FIELD(I2CCR, MSTA, 5, 1) +FIELD(I2CCR, MTX, 4, 1) +FIELD(I2CCR, TXAK, 3, 1) +FIELD(I2CCR, RSTA, 2, 1) +FIELD(I2CCR, BCST, 0, 1) + +FIELD(I2CSR, MCF, 7, 1) +FIELD(I2CSR, MAAS, 6, 1) +FIELD(I2CSR, MBB, 5, 1) +FIELD(I2CSR, MAL, 4, 1) +FIELD(I2CSR, BCSTM, 3, 1) +FIELD(I2CSR, SRW, 2, 1) +FIELD(I2CSR, MIF, 1, 1) +FIELD(I2CSR, RXAK, 0, 1) + +typedef struct I2CState { + SysBusDevice parent_obj; + + I2CBus *bus;
hw/i2c/mpc8540_i2c.c line 72
Quoted 10 lines
hw/i2c/mpc8540_i2c.c new file +10
-0+ +uint8_t ctrl, sts; +uint8_t freq, filt; +/* Reads are pipelined, this is the next data value */ +uint8_t dbuf; + +qemu_irq irq; + +MemoryRegion mmio; +} I2CState;
May be use MPC8540I2CState ? I would put the definition in a header file
hw/i2c/mpc8540_i2c.c line 86
Quoted 13 lines
hw/i2c/mpc8540_i2c.c new file +13
-0+#define I2CCR (BIT ) FIELD_EX32(i2c->ctrl, I2CCR, BIT) +#define I2CSR (BIT ) FIELD_EX32(i2c->sts, I2CSR, BIT) + +#define I2CSR_SET (BIT ,VAL ) do {\ + i2c->sts = FIELD_DP32(i2c->sts, I2CSR, BIT, VAL);\ + } while (0) + +static +void mpc8540_update_irq (I2CState *i2c) +{ +int ena = i2c->ctrl &0x40 , + sts = i2c->sts &0x02 , + act = !!(ena && sts);
OK. why not :) Three distinct lines would be better. This is minor.
hw/i2c/mpc8540_i2c.c line 100
Quoted 13 lines
hw/i2c/mpc8540_i2c.c new file +13
-0+DPRINTK (1 ,"IRQ %c ena %c sts %c\n" , + act ?'X' :'_' , + ena ?'X' :'_' , + sts ?'X' :'_' ); + +qemu_set_irq (i2c->irq, act); +} + +static +uint64_t mpc8540_i2c_read (void *opaque,hwaddr addr,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t val, offset = addr;
This 'offset = addr' looks useless. do you really need it ?
Quoted 153 lines
hw/i2c/mpc8540_i2c.c new file +153
-0+ +switch (offset) { +case R_I2CADR :/* ADDR */ + val =0 ; +break ; +case R_I2CFDR :/* Freq Div. */ + val = i2c->freq; +break ; +case R_I2CCR :/* CONTROL */ + val = i2c->ctrl & ~0x06 ; +break ; +case R_I2CSR :/* STATUS */ + val = i2c->sts; +break ; +case R_I2CDR :/* DATA */ +/* Reads are "pipelined" and so return the previous value of the +* register +*/ + val = i2c->dbuf; +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus) ||I2CCR (MTX )) { +LOG (LOG_GUEST_ERROR ,"Read during addr or tx\n" ); + i2c->dbuf =0xff ; + }else { +int ret =i2c_recv (i2c->bus); + i2c->dbuf = (uint8_t )ret; +DPRINTK (0 ,"READ %02x ('%c')\n" , i2c->dbuf, (char )i2c->dbuf); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); +mpc8540_update_irq (i2c); + } + }else { + i2c->dbuf =0xff ; +LOG (LOG_GUEST_ERROR ,"Read when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val = i2c->filt; +break ; +default : + val =0xff ; + } + +DPRINTK (offset ==0xc ?2 :1 ," read %08x -> %08x\n" , + (unsigned )offset, (unsigned )val); +return val; +} + +static +void mpc8540_i2c_write (void *opaque,hwaddr addr,uint64_t val,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t offset = addr; + +DPRINTK (1 ," write %08x <- %08x\n" , (unsigned )offset, (unsigned )val); + +switch (offset) { +case R_I2CADR :/* ADDR */ +break ; +case R_I2CFDR :/* Freq Div. */ + i2c->freq = val &0x3f ; +break ; +case R_I2CCR :/* CONTROL CCR */ +if (!FIELD_EX32 (val,I2CCR ,MEN )) { +DPRINTK (0 ,"Not Enabled\n" ); + + }else if (!I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 0 -> 1 is START */ + +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"START\n" ); +i2c_end_transfer (i2c->bus);/* paranoia */ + + }else if (I2CCR (MSTA ) && !FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 1 -> 0 is STOP */ + +I2CSR_SET (MBB ,0 ); +DPRINTK (0 ,"STOP\n" ); +i2c_end_transfer (i2c->bus); + + }else if (I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,RSTA )) { +i2c_end_transfer (i2c->bus); +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"REP START\n" ); + + } +/* RSTA always reads zero, bit 1 unusd */ + val &=0xf9 ; + i2c->ctrl = val; +mpc8540_update_irq (i2c); +break ; +case R_I2CSR :/* STATUS CSR */ +/* only MAL and MIF are writable */ + val &=0x12 ; + i2c->sts &= ~0x12 ; + i2c->sts |= val; +mpc8540_update_irq (i2c); +break ; +case R_I2CDR :/* DATA CDR */ +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus)) { +if (i2c_start_transfer (i2c->bus, val >>1 , val &1 )) { +LOG (LOG_GUEST_ERROR ,"I2C no device %02x\n" , + (unsigned )(val &0xfe )); + }else { +DPRINTK (0 ,"ADDR %02x\n" , (unsigned )(val &0xfe )); + } +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + + }else if (I2CCR (MTX )) { +DPRINTK (0 ,"WRITE %02x\n" , (unsigned )val); +i2c_send (i2c->bus, val); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write during read\n" ); + } +mpc8540_update_irq (i2c); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val &=0x3f ; + i2c->filt = val; +break ; + } + +DPRINTK (1 ,"I2CCR = %02x I2SCR = %02x\n" , i2c->ctrl, i2c->sts); +} + +static const MemoryRegionOps i2c_ops = { + .read = mpc8540_i2c_read, + .write = mpc8540_i2c_write, + .endianness =DEVICE_NATIVE_ENDIAN , + .impl = { + .min_access_size =1 , + .max_access_size =1 , + }, +}; + +static +void mpc8540_i2c_reset (DeviceState *dev) +{ +I2CState *i2c =MPC8540_I2C (dev); + + i2c->sts =0x81 ;/* transfer complete and ack received */ +} + +static int mpc8540_i2c_inst_init (SysBusDevice *dev) +{ +I2CState *i2c =MPC8540_I2C (dev);
hw/i2c/mpc8540_i2c.c line 263
Quoted 10 lines
hw/i2c/mpc8540_i2c.c new file +10
-0+ + i2c->bus =i2c_init_bus (&dev->parent_obj,"bus" ); + +memory_region_init_io (&i2c->mmio, &dev->parent_obj.parent_obj, + &i2c_ops, i2c,TYPE_MPC8540_I2C ,0x18 ); + +sysbus_init_mmio (dev, &i2c->mmio); +sysbus_init_irq (dev, &i2c->irq); +return 0 ; +}
This should be a realize routine.
C.
Quoted 24 lines
hw/i2c/mpc8540_i2c.c new file +23
-0+static void mpc8540_i2c_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = &mpc8540_i2c_inst_init; + dc->reset = &mpc8540_i2c_reset; +} + +static const TypeInfo mpc8540_i2c_type = { + .name =TYPE_MPC8540_I2C , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (I2CState), + .class_size =sizeof (SysBusDeviceClass), + .class_init = mpc8540_i2c_class_init, +}; + +static void mpc8540_i2c_register (void ) +{ +type_register_static (&mpc8540_i2c_type); +} + +type_init (mpc8540_i2c_register)
Re: [Qemu-devel] [Qemu-ppc] [PATCH 06/12] i2c: add mpc8540 i2c controller
Quoted 44 lines · Cédric Le Goater
Hello,
The model should be QOM'ified.
Quoted 39 lines · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>--- hw/i2c/Makefile.objs | 1 + hw/i2c/mpc8540_i2c.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 hw/i2c/mpc8540_i2c.chw/i2c/Makefile.objs +1
-0@@ -9,3 +9,4 @@ common-obj-$(CONFIG_IMX_I2C) += imx_i2c.o common-obj-$(CONFIG_ASPEED_SOC) += aspeed_i2c.o obj-$(CONFIG_OMAP) += omap_i2c.o obj-$(CONFIG_PPC4XX) += ppc4xx_i2c.o +obj-$(CONFIG_E500) += mpc8540_i2c.ohw/i2c/mpc8540_i2c.c new file +17
-0@@ -0,0 +1,287 @@ +/* +* MPC8540 I2C bus interface +* As described in +* MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1 +* Part 2 chapter 11 +* +* Copyright (c) 2015 Michael Davidsaver +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +*/ +#include "qemu/osdep.h" +#include "qemu/log.h" +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/i2c/i2c.h" +#include "hw/sysbus.h"
Quoted 8 lines
hw/i2c/mpc8540_i2c.c line 23
Quoted 6 lines
hw/i2c/mpc8540_i2c.c new file +6
-0+ +/* #define DEBUG_LVL 0 */ + +#ifdef DEBUG_LVL +#define DPRINTK (LVL ,FMT , ...) do { if ((LVL) <= DEBUG_LVL) { \ + printf(TYPE_MPC8540_I2C " : " FMT, ## __VA_ARGS__); } } while (0)hmm, I am not sure 'printfs' are welcomed in QEMU.
They're not, tracepoints are preferred. I tend to be ok with debug macros like this, though, since they can be convenient. It should at least be fprintf(stderr, ...) though.
Quoted 243 lines
Quoted 40 lines
hw/i2c/mpc8540_i2c.c new file +38
-0+#else +#define DPRINTK (LVL ,FMT , ...) do {} while (0) +#endif + +#define LOG (MSK ,FMT , ...) qemu_log_mask(MSK, TYPE_MPC8540_I2C \ + " : " FMT, ## __VA_ARGS__) +#define TYPE_MPC8540_I2C "mpc8540-i2c" +#define MPC8540_I2C (obj) OBJECT_CHECK(I2CState, (obj), TYPE_MPC8540_I2C) + +/* offsets relative to CCSR offset 0x3000 */ +#define R_I2CADR (0) +#define R_I2CFDR (4) +#define R_I2CCR (8) +#define R_I2CSR (0xc) +#define R_I2CDR (0x10) +#define R_I2CDFSRR (0x14) + +FIELD(I2CCR, MEN, 7, 1) +FIELD(I2CCR, MIEN, 6, 1) +FIELD(I2CCR, MSTA, 5, 1) +FIELD(I2CCR, MTX, 4, 1) +FIELD(I2CCR, TXAK, 3, 1) +FIELD(I2CCR, RSTA, 2, 1) +FIELD(I2CCR, BCST, 0, 1) + +FIELD(I2CSR, MCF, 7, 1) +FIELD(I2CSR, MAAS, 6, 1) +FIELD(I2CSR, MBB, 5, 1) +FIELD(I2CSR, MAL, 4, 1) +FIELD(I2CSR, BCSTM, 3, 1) +FIELD(I2CSR, SRW, 2, 1) +FIELD(I2CSR, MIF, 1, 1) +FIELD(I2CSR, RXAK, 0, 1) + +typedef struct I2CState { + SysBusDevice parent_obj; + + I2CBus *bus;hw/i2c/mpc8540_i2c.c line 72
Quoted 10 lines
hw/i2c/mpc8540_i2c.c new file +10
-0+ +uint8_t ctrl, sts; +uint8_t freq, filt; +/* Reads are pipelined, this is the next data value */ +uint8_t dbuf; + +qemu_irq irq; + +MemoryRegion mmio; +} I2CState;May be use MPC8540I2CState ? I would put the definition in a header file
hw/i2c/mpc8540_i2c.c line 86
Quoted 13 lines
hw/i2c/mpc8540_i2c.c new file +13
-0+#define I2CCR (BIT ) FIELD_EX32(i2c->ctrl, I2CCR, BIT) +#define I2CSR (BIT ) FIELD_EX32(i2c->sts, I2CSR, BIT) + +#define I2CSR_SET (BIT ,VAL ) do {\ + i2c->sts = FIELD_DP32(i2c->sts, I2CSR, BIT, VAL);\ + } while (0) + +static +void mpc8540_update_irq (I2CState *i2c) +{ +int ena = i2c->ctrl &0x40 , + sts = i2c->sts &0x02 , + act = !!(ena && sts);OK. why not :) Three distinct lines would be better. This is minor.
hw/i2c/mpc8540_i2c.c line 100
Quoted 13 lines
hw/i2c/mpc8540_i2c.c new file +13
-0+DPRINTK (1 ,"IRQ %c ena %c sts %c\n" , + act ?'X' :'_' , + ena ?'X' :'_' , + sts ?'X' :'_' ); + +qemu_set_irq (i2c->irq, act); +} + +static +uint64_t mpc8540_i2c_read (void *opaque,hwaddr addr,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t val, offset = addr;This 'offset = addr' looks useless. do you really need it ?
Quoted 157 lines
hw/i2c/mpc8540_i2c.c new file +157
-0+ +switch (offset) { +case R_I2CADR :/* ADDR */ + val =0 ; +break ; +case R_I2CFDR :/* Freq Div. */ + val = i2c->freq; +break ; +case R_I2CCR :/* CONTROL */ + val = i2c->ctrl & ~0x06 ; +break ; +case R_I2CSR :/* STATUS */ + val = i2c->sts; +break ; +case R_I2CDR :/* DATA */ +/* Reads are "pipelined" and so return the previous value of the +* register +*/ + val = i2c->dbuf; +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus) ||I2CCR (MTX )) { +LOG (LOG_GUEST_ERROR ,"Read during addr or tx\n" ); + i2c->dbuf =0xff ; + }else { +int ret =i2c_recv (i2c->bus); + i2c->dbuf = (uint8_t )ret; +DPRINTK (0 ,"READ %02x ('%c')\n" , i2c->dbuf, (char )i2c->dbuf); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); +mpc8540_update_irq (i2c); + } + }else { + i2c->dbuf =0xff ; +LOG (LOG_GUEST_ERROR ,"Read when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val = i2c->filt; +break ; +default : + val =0xff ; + } + +DPRINTK (offset ==0xc ?2 :1 ," read %08x -> %08x\n" , + (unsigned )offset, (unsigned )val); +return val; +} + +static +void mpc8540_i2c_write (void *opaque,hwaddr addr,uint64_t val,unsigned size) +{ +I2CState *i2c = opaque; +uint32_t offset = addr; + +DPRINTK (1 ," write %08x <- %08x\n" , (unsigned )offset, (unsigned )val); + +switch (offset) { +case R_I2CADR :/* ADDR */ +break ; +case R_I2CFDR :/* Freq Div. */ + i2c->freq = val &0x3f ; +break ; +case R_I2CCR :/* CONTROL CCR */ +if (!FIELD_EX32 (val,I2CCR ,MEN )) { +DPRINTK (0 ,"Not Enabled\n" ); + + }else if (!I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 0 -> 1 is START */ + +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"START\n" ); +i2c_end_transfer (i2c->bus);/* paranoia */ + + }else if (I2CCR (MSTA ) && !FIELD_EX32 (val,I2CCR ,MSTA )) { +/* MSTA 1 -> 0 is STOP */ + +I2CSR_SET (MBB ,0 ); +DPRINTK (0 ,"STOP\n" ); +i2c_end_transfer (i2c->bus); + + }else if (I2CCR (MSTA ) &&FIELD_EX32 (val,I2CCR ,RSTA )) { +i2c_end_transfer (i2c->bus); +I2CSR_SET (MBB ,1 ); +DPRINTK (0 ,"REP START\n" ); + + } +/* RSTA always reads zero, bit 1 unusd */ + val &=0xf9 ; + i2c->ctrl = val; +mpc8540_update_irq (i2c); +break ; +case R_I2CSR :/* STATUS CSR */ +/* only MAL and MIF are writable */ + val &=0x12 ; + i2c->sts &= ~0x12 ; + i2c->sts |= val; +mpc8540_update_irq (i2c); +break ; +case R_I2CDR :/* DATA CDR */ +if (I2CCR (MEN ) &&I2CSR (MBB )) {/* enabled and busy */ +if (!i2c_bus_busy (i2c->bus)) { +if (i2c_start_transfer (i2c->bus, val >>1 , val &1 )) { +LOG (LOG_GUEST_ERROR ,"I2C no device %02x\n" , + (unsigned )(val &0xfe )); + }else { +DPRINTK (0 ,"ADDR %02x\n" , (unsigned )(val &0xfe )); + } +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + + }else if (I2CCR (MTX )) { +DPRINTK (0 ,"WRITE %02x\n" , (unsigned )val); +i2c_send (i2c->bus, val); +I2CSR_SET (MIF ,1 ); +I2CSR_SET (RXAK ,0 ); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write during read\n" ); + } +mpc8540_update_irq (i2c); + }else { +LOG (LOG_GUEST_ERROR ,"I2CDR Write when not enabled or busy\n" ); + } +break ; +case R_I2CDFSRR :/* FILTER */ + val &=0x3f ; + i2c->filt = val; +break ; + } + +DPRINTK (1 ,"I2CCR = %02x I2SCR = %02x\n" , i2c->ctrl, i2c->sts); +} + +static const MemoryRegionOps i2c_ops = { + .read = mpc8540_i2c_read, + .write = mpc8540_i2c_write, + .endianness =DEVICE_NATIVE_ENDIAN , + .impl = { + .min_access_size =1 , + .max_access_size =1 , + }, +}; + +static +void mpc8540_i2c_reset (DeviceState *dev) +{ +I2CState *i2c =MPC8540_I2C (dev); + + i2c->sts =0x81 ;/* transfer complete and ack received */ +} + +static int mpc8540_i2c_inst_init (SysBusDevice *dev) +{ +I2CState *i2c =MPC8540_I2C (dev); + + i2c->bus =i2c_init_bus (&dev->parent_obj,"bus" ); + + memory_region_init_io(&i2c->mmio, &dev->parent_obj.parent_obj,
Quoted 8 lines
hw/i2c/mpc8540_i2c.c line 263
Quoted 6 lines
hw/i2c/mpc8540_i2c.c new file +6
-0+ &i2c_ops, i2c, TYPE_MPC8540_I2C, 0x18); + +sysbus_init_mmio (dev, &i2c->mmio); +sysbus_init_irq (dev, &i2c->irq); +return 0 ; +}This should be a realize routine.
Ah.. that's a good point, actually. On that basis, I'm pulling the draft patch from ppc-for-2.12
Quoted 25 lines
Quoted 24 lines
hw/i2c/mpc8540_i2c.c new file +23
-0+static void mpc8540_i2c_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +SysBusDeviceClass *k =SYS_BUS_DEVICE_CLASS (klass); + + k->init = &mpc8540_i2c_inst_init; + dc->reset = &mpc8540_i2c_reset; +} + +static const TypeInfo mpc8540_i2c_type = { + .name =TYPE_MPC8540_I2C , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (I2CState), + .class_size =sizeof (SysBusDeviceClass), + .class_init = mpc8540_i2c_class_init, +}; + +static void mpc8540_i2c_register (void ) +{ +type_register_static (&mpc8540_i2c_type); +} + +type_init (mpc8540_i2c_register)
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 7/12 qtest: add e500_i2c_create()
In reply to Michael DavidsaverAdd interface for testing i2c devices
with PPC e500.
--- tests/Makefile.include | 1 + tests/libqos/i2c-e500.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ tests/libqos/i2c.h | 3 +++ 3 files changed, 70 insertions(+) create mode 100644 tests/libqos/i2c-e500.c
tests/Makefile.include +1 -0
@@ -721,6 +721,7 @@ libqos-pc-obj-y += tests/libqos/malloc-pc.o tests/libqos/libqos-pc.o libqos-pc-obj-y += tests/libqos/ahci.o libqos-omap-obj-y = $(libqos-obj-y) tests/libqos/i2c-omap.o libqos-imx-obj-y = $(libqos-obj-y) tests/libqos/i2c-imx.o +libqos-e500-obj-y = $(libqos-obj-y) tests/libqos/i2c-e500.o libqos-usb-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/usb.o libqos-virtio-obj-y = $(libqos-spapr-obj-y) $(libqos-pc-obj-y) tests/libqos/virtio.o tests/libqos/virtio-pci.o tests/libqos/virtio-mmio.o tests/libqos/malloc-generic.o
tests/libqos/i2c-e500.c new file +66 -0
66 lines not on this page · raw message
tests/libqos/i2c.h +3 -0
@@ -29,4 +29,7 @@ I2CAdapter *omap_i2c_create(uint64_t addr);/* libi2c-imx.c */ I2CAdapter *imx_i2c_create (uint64_t addr); +/* i2c-e500.c */ +I2CAdapter *e500_i2c_create (uint64_t ccsr_base); +#endif
Signature · 1 line
2.11.0
PATCH 8/12 e500: add mpc8540 i2c controller to ccsr
In reply to Michael Davidsaver--- hw/ppc/e500.c | 8 ++++++++ 1 file changed, 8 insertions(+)
hw/ppc/e500.c +8 -0
@@ -861,6 +861,14 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)qdev_init_nofail (dev); ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 ); + dev =qdev_create (NULL ,"mpc8540-i2c" ); +object_property_add_child (qdev_get_machine (),"i2c[*]" , +OBJECT (dev),NULL ); +qdev_init_nofail (dev); + s =SYS_BUS_DEVICE (dev); +memory_region_add_subregion (ccsr_addr_space,0x3000 , +sysbus_mmio_get_region (s,0 )); + mpicdev =ppce500_init_mpic (machine, params, ccsr_addr_space, irqs);/* Serial */
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 08/12] e500: add mpc8540 i2c controller to ccsr
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>
You're adding what seems to be a fairly specific device to the general e500 init - this again suggests that it should be split, putting creation of devices under control of individual machines.
Quoted 23 lines
--- hw/ppc/e500.c | 8 ++++++++ 1 file changed, 8 insertions(+)hw/ppc/e500.c +8
-0@@ -861,6 +861,14 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)qdev_init_nofail (dev); ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 ); + dev =qdev_create (NULL ,"mpc8540-i2c" ); +object_property_add_child (qdev_get_machine (),"i2c[*]" , +OBJECT (dev),NULL ); +qdev_init_nofail (dev); + s =SYS_BUS_DEVICE (dev); +memory_region_add_subregion (ccsr_addr_space,0x3000 , +sysbus_mmio_get_region (s,0 )); + mpicdev =ppce500_init_mpic (machine, params, ccsr_addr_space, irqs);/* Serial */
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [PATCH 08/12] e500: add mpc8540 i2c controller to ccsr
Quoted 6 lines · David Gibson
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>You're adding what seems to be a fairly specific device to the general e500 init - this again suggests that it should be split, putting creation of devices under control of individual machines.
I'll address the ppce500_init() part of this question separately.
In addition to the MPC8540, I find that documentation for the MPC8544 (modeled) and P2020 (un-modeled) show the same i2c controller registers.
So I think it's reasonable for the generic ppce500 machine to have it
as well.
For what it's worth, the Linux driver for this unit (drivers/i2c/busses/i2c-mpc.c) lists compatibility with a number of other freescale SoCs with only some differences in clock selection (not modeled). The description for the module is:
Quoted 29 lines
MODULE_DESCRIPTION("I2C-Bus adapter for MPC107 bridge and "
"MPC824x/83xx/85xx/86xx/512x/52xx processors");Quoted 23 lines
--- hw/ppc/e500.c | 8 ++++++++ 1 file changed, 8 insertions(+)hw/ppc/e500.c +8
-0@@ -861,6 +861,14 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)qdev_init_nofail (dev); ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 ); + dev =qdev_create (NULL ,"mpc8540-i2c" ); +object_property_add_child (qdev_get_machine (),"i2c[*]" , +OBJECT (dev),NULL ); +qdev_init_nofail (dev); + s =SYS_BUS_DEVICE (dev); +memory_region_add_subregion (ccsr_addr_space,0x3000 , +sysbus_mmio_get_region (s,0 )); + mpicdev =ppce500_init_mpic (machine, params, ccsr_addr_space, irqs);/* Serial */
PATCH 9/12 nvram: add AT24Cx i2c eeprom
In reply to Michael Davidsaver--- hw/nvram/Makefile.objs | 1 + hw/nvram/eeprom_at24c.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 hw/nvram/eeprom_at24c.c
hw/nvram/Makefile.objs +1 -0
@@ -1,5 +1,6 @@ common-obj-$(CONFIG_DS1225Y) += ds1225y.o common-obj-y += eeprom93xx.o +common-obj-y += eeprom_at24c.o common-obj-y += fw_cfg.o common-obj-y += chrp_nvram.o common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.o
hw/nvram/eeprom_at24c.c new file +205 -0
205 lines not on this page · raw message
Signature · 1 line
2.11.0
David Gibson
AppliedRe: [Qemu-devel] [PATCH 09/12] nvram: add AT24Cx i2c eeprom
Quoted 1 line · Michael Davidsaver
Signed-off-by Michael Davidsaver <[email protected]>
Applied to ppc-for-2.12.
Quoted 228 lines
--- hw/nvram/Makefile.objs | 1 + hw/nvram/eeprom_at24c.c | 205 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 hw/nvram/eeprom_at24c.chw/nvram/Makefile.objs +1
-0@@ -1,5 +1,6 @@ common-obj-$(CONFIG_DS1225Y) += ds1225y.o common-obj-y += eeprom93xx.o +common-obj-y += eeprom_at24c.o common-obj-y += fw_cfg.o common-obj-y += chrp_nvram.o common-obj-$(CONFIG_MAC_NVRAM) += mac_nvram.ohw/nvram/eeprom_at24c.c new file +205
-0@@ -0,0 +1,205 @@ +/* +* *AT24C* series I2C EEPROM +* +* Copyright (c) 2015 Michael Davidsaver +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +*/ + +#include <string.h> + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/hw.h" +#include "hw/i2c/i2c.h" +#include "sysemu/block-backend.h" + +/* #define DEBUG_AT24C */ + +#ifdef DEBUG_AT24C +#define DPRINTK (FMT , ...) printf(TYPE_AT24C_EE " : " FMT, ## __VA_ARGS__) +#else +#define DPRINTK (FMT , ...) do {} while (0) +#endif + +#define ERR (FMT , ...) fprintf(stderr, TYPE_AT24C_EE " : " FMT, \ + ## __VA_ARGS__) + +#define TYPE_AT24C_EE "at24c-eeprom" +#define AT24C_EE (obj) OBJECT_CHECK(EEPROMState, (obj), TYPE_AT24C_EE) + +typedef struct EEPROMState { +I2CSlave parent_obj; + +/* address counter */ +uint16_t cur; +/* total size in bytes */ +uint32_t rsize; +bool writable; +/* cells changed since last START? */ +bool changed; +/* during WRITE, # of address bytes transfered */ +uint8_t haveaddr; + +uint8_t *mem; + +BlockBackend *blk; +}EEPROMState ; + +static +int at24c_eeprom_event (I2CSlave *s,enum i2c_event event) +{ +EEPROMState *ee =container_of (s, EEPROMState, parent_obj); + +switch (event) { +case I2C_START_SEND : +case I2C_START_RECV : +case I2C_FINISH : + ee->haveaddr =0 ; +DPRINTK ("clear\n" ); +if (ee->blk && ee->changed) { +int len =blk_pwrite (ee->blk,0 , ee->mem, ee->rsize,0 ); +if (len != ee->rsize) { +ERR (TYPE_AT24C_EE +" : failed to write backing file\n" ); + } +DPRINTK ("Wrote to backing file\n" ); + } + ee->changed = false; +break ; +case I2C_NACK : +break ; + } +return 0 ; +} + +static +int at24c_eeprom_recv (I2CSlave *s) +{ +EEPROMState *ee =AT24C_EE (s); +int ret; + + ret = ee->mem[ee->cur]; + + ee->cur = (ee->cur +1u ) % ee->rsize; +DPRINTK ("Recv %02x %c\n" , ret, ret); + +return ret; +} + +static +int at24c_eeprom_send (I2CSlave *s,uint8_t data) +{ +EEPROMState *ee =AT24C_EE (s); + +if (ee->haveaddr <2 ) { + ee->cur <<=8 ; + ee->cur |= data; + ee->haveaddr++; +if (ee->haveaddr ==2 ) { + ee->cur %= ee->rsize; +DPRINTK ("Set pointer %04x\n" , ee->cur); + } + + }else { +if (ee->writable) { +DPRINTK ("Send %02x\n" , data); + ee->mem[ee->cur] = data; + ee->changed = true; + }else { +DPRINTK ("Send error %02x read-only\n" , data); + } + ee->cur = (ee->cur +1u ) % ee->rsize; + + } + +return 0 ; +} + +static +int at24c_eeprom_init (I2CSlave *i2c) +{ +EEPROMState *ee =AT24C_EE (i2c); + + ee->mem =g_malloc0 (ee->rsize); + +if (ee->blk) { +int64_t len =blk_getlength (ee->blk); + +if (len != ee->rsize) { +ERR (TYPE_AT24C_EE " : Backing file size %lu != %u\n" , + (unsigned long )len, (unsigned )ee->rsize); +exit (1 ); + } + +if (blk_set_perm (ee->blk,BLK_PERM_CONSISTENT_READ |BLK_PERM_WRITE , +BLK_PERM_ALL , &error_fatal) <0 ) + { +ERR (TYPE_AT24C_EE +" : Backing file incorrect permission\n" ); +exit (1 ); + } + } +return 0 ; +} + +static +void at24c_eeprom_reset (DeviceState *state) +{ +EEPROMState *ee =AT24C_EE (state); + + ee->changed = false; + ee->cur =0 ; + ee->haveaddr =0 ; + +memset (ee->mem,0 , ee->rsize); + +if (ee->blk) { +int len =blk_pread (ee->blk,0 , ee->mem, ee->rsize); + +if (len != ee->rsize) { +ERR (TYPE_AT24C_EE +" : Failed initial sync with backing file\n" ); + } +DPRINTK ("Reset read backing file\n" ); + } +} + +static Property at24c_eeprom_props[] = { +DEFINE_PROP_UINT32 ("rom-size" , EEPROMState, rsize,0 ), +DEFINE_PROP_BOOL ("writable" , EEPROMState, writable, true), +DEFINE_PROP_DRIVE ("drive" , EEPROMState, blk), +DEFINE_PROP_END_OF_LIST () +}; + +static +void at24c_eeprom_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +I2CSlaveClass *k =I2C_SLAVE_CLASS (klass); + + k->init = &at24c_eeprom_init; + k->event = &at24c_eeprom_event; + k->recv = &at24c_eeprom_recv; + k->send = &at24c_eeprom_send; + + dc->props = at24c_eeprom_props; + dc->reset = at24c_eeprom_reset; +} + +static +const TypeInfo at24c_eeprom_type = { + .name =TYPE_AT24C_EE , + .parent =TYPE_I2C_SLAVE , + .instance_size =sizeof (EEPROMState), + .class_size =sizeof (I2CSlaveClass), + .class_init = at24c_eeprom_class_init, +}; + +static void at24c_eeprom_register (void ) +{ +type_register_static (&at24c_eeprom_type); +} + +type_init (at24c_eeprom_register)
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 10/12 timer: add ds1375 RTC
In reply to Michael Davidsaveronly basic functionality implemented (read time and sram). no set time or alarms.
--- default-configs/ppc-softmmu.mak | 1 + hw/timer/Makefile.objs | 1 + hw/timer/ds1375-i2c.c | 293 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 hw/timer/ds1375-i2c.c
default-configs/ppc-softmmu.mak +1 -0
@@ -52,3 +52,4 @@ CONFIG_SERIAL_ISA=y CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y CONFIG_RS6000_MC=y +CONFIG_DS1375=y
hw/timer/Makefile.objs +1 -0
@@ -4,6 +4,7 @@ common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o common-obj-$(CONFIG_CADENCE) += cadence_ttc.o common-obj-$(CONFIG_DS1338) += ds1338.o +common-obj-$(CONFIG_DS1375) += ds1375-i2c.o common-obj-$(CONFIG_HPET) += hpet.o common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o common-obj-$(CONFIG_M48T59) += m48t59.o
hw/timer/ds1375-i2c.c new file +293 -0
293 lines not on this page · raw message
Signature · 1 line
2.11.0
Re: [Qemu-devel] [PATCH 10/12] timer: add ds1375 RTC
Quoted 4 lines · Michael Davidsaver
only basic functionality implemented (read time and sram). no set time or alarms.
Signed-off-by Michael Davidsaver <[email protected]>
I know there about a zillion different Dallas/Maxim sram/rtc chips, many of which have a lot of similarities. Is it possible to share any code with the existing hw/timer/ds1338.c?
Quoted 327 lines
--- default-configs/ppc-softmmu.mak | 1 + hw/timer/Makefile.objs | 1 + hw/timer/ds1375-i2c.c | 293 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 295 insertions(+) create mode 100644 hw/timer/ds1375-i2c.cdefault-configs/ppc-softmmu.mak +1
-0@@ -52,3 +52,4 @@ CONFIG_SERIAL_ISA=y CONFIG_MC146818RTC=y CONFIG_ISA_TESTDEV=y CONFIG_RS6000_MC=y +CONFIG_DS1375=yhw/timer/Makefile.objs +1
-0@@ -4,6 +4,7 @@ common-obj-$(CONFIG_ARM_V7M) += armv7m_systick.o common-obj-$(CONFIG_A9_GTIMER) += a9gtimer.o common-obj-$(CONFIG_CADENCE) += cadence_ttc.o common-obj-$(CONFIG_DS1338) += ds1338.o +common-obj-$(CONFIG_DS1375) += ds1375-i2c.o common-obj-$(CONFIG_HPET) += hpet.o common-obj-$(CONFIG_I8254) += i8254_common.o i8254.o common-obj-$(CONFIG_M48T59) += m48t59.ohw/timer/ds1375-i2c.c new file +293
-0@@ -0,0 +1,293 @@ +/* +* Dallas/Maxim ds1375 I2C RTC w/ SRAM +* +* Copyright (c) 2017 Michael Davidsaver +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +* +* Only basic functionality is modeled (time and user SRAM). +* Alarms not modeled. +*/ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "qemu/timer.h" +#include "qemu/bcd.h" +#include "hw/hw.h" +#include "hw/registerfields.h" +#include "hw/i2c/i2c.h" + +#define DEBUG_DS1375 + +#ifdef DEBUG_DS1375 +#define DPRINTK (FMT , ...) printf(TYPE_DS1375 " : " FMT, ## __VA_ARGS__) +#else +#define DPRINTK (FMT , ...) do {} while (0) +#endif + +#define LOG (MSK ,FMT , ...) qemu_log_mask(MSK, TYPE_DS1375 " : " FMT, \ + ## __VA_ARGS__) + +#define TYPE_DS1375 "ds1375" +#define DS1375 (obj) OBJECT_CHECK(DS1375State, (obj), TYPE_DS1375) + +#define DS1375_REGSIZE 0x20 + +#define R_SEC (0x0) +#define R_MIN (0x1) +#define R_HOUR (0x2) +#define R_WDAY (0x3) +#define R_DATE (0x4) +#define R_MONTH (0x5) +#define R_YEAR (0x6) +#define R_A1SEC (0x7) +#define R_A1MIN (0x8) +#define R_A1HOUR (0x9) +#define R_A1DAY (0xa) +#define R_A2SEC (0xb) +#define R_A2MIN (0xc) +#define R_A2HOUR (0xd) +#define R_CTRL (0xe) +#define R_STS (0xf) + +FIELD(HOUR, SET12, 6, 1) +FIELD(HOUR, HOUR24, 0, 6) +FIELD(HOUR, AMPM, 5, 1) +FIELD(HOUR, HOUR12, 0, 5) + +FIELD(MONTH, MONTH, 0, 5) +FIELD(MONTH, CENTURY, 7, 1) + +FIELD(CTRL, ECLK, 7, 1) +FIELD(CTRL, CLKSEL, 5, 2) +FIELD(CTRL, RS, 3, 2) +FIELD(CTRL, INTCN, 2, 1) +FIELD(CTRL, A2IE, 1, 1) +FIELD(CTRL, A1IE, 0, 1) + +typedef struct DS1375State { +I2CSlave parent_obj; + +/* register address counter */ +uint8_t addr; +/* when writing, whether the address has been sent */ +bool addrd; + +int time_offset; + +uint8_t regs[DS1375_REGSIZE ]; +}DS1375State ; + +/* update current time register if clock enabled */ +static +void ds1375_latch (DS1375State *ds) +{ +struct tm now; + +if (!ARRAY_FIELD_EX32 (ds->regs,CTRL ,ECLK )) { +return ; + } + +qemu_get_timedate (&now, ds->time_offset); + +DPRINTK ("Current Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n" , + now.tm_year, now.tm_mon, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec, + now.tm_wday); + +/* ensure unused bits are zero */ +memset (ds->regs,0 ,R_YEAR +1 ); + + ds->regs[R_SEC ] =to_bcd (now.tm_sec); + ds->regs[R_MIN ] =to_bcd (now.tm_min); + +if (ARRAY_FIELD_EX32 (ds->regs,HOUR ,SET12 ) ==0 ) { +/* 24 hour */ +ARRAY_FIELD_DP32 (ds->regs,HOUR ,HOUR24 ,to_bcd (now.tm_hour)); + }else { +/* 12 hour am/pm */ +ARRAY_FIELD_DP32 (ds->regs,HOUR ,AMPM , now.tm_hour >=12 ); +ARRAY_FIELD_DP32 (ds->regs,HOUR ,HOUR12 ,to_bcd (now.tm_hour %12u )); + } + + ds->regs[R_WDAY ] = now.tm_wday;/* day of the week */ + ds->regs[R_DATE ] =to_bcd (now.tm_mday); + +ARRAY_FIELD_DP32 (ds->regs,MONTH ,MONTH ,to_bcd (now.tm_mon +1 )); +ARRAY_FIELD_DP32 (ds->regs,MONTH ,CENTURY , now.tm_year >99 ); + + ds->regs[R_YEAR ] =to_bcd (now.tm_year %100u ); + +DPRINTK ("Latched time\n" ); +} + +static +void ds1375_update (DS1375State *ds) +{ +struct tm now; + + now.tm_sec =from_bcd (ds->regs[R_SEC ]); + now.tm_min =from_bcd (ds->regs[R_MIN ]); + +if (ARRAY_FIELD_EX32 (ds->regs,HOUR ,SET12 )) { + now.tm_hour =from_bcd (ARRAY_FIELD_EX32 (ds->regs,HOUR ,HOUR12 )); +if (ARRAY_FIELD_EX32 (ds->regs,HOUR ,AMPM )) { + now.tm_hour +=12 ; + } + + }else { + now.tm_hour =from_bcd (ARRAY_FIELD_EX32 (ds->regs,HOUR ,HOUR24 )); + } + + now.tm_wday =from_bcd (ds->regs[R_WDAY ]); + now.tm_mday =from_bcd (ds->regs[R_DATE ]); + now.tm_mon =from_bcd (ARRAY_FIELD_EX32 (ds->regs,MONTH ,MONTH )) -1 ; + + now.tm_year =from_bcd (ds->regs[R_YEAR ]) %100u ; +if (ARRAY_FIELD_EX32 (ds->regs,MONTH ,CENTURY )) { + now.tm_year +=100 ; + } + +DPRINTK ("New Time %3u/%2u/%u %2u:%2u:%2u (wday %u)\n" , + now.tm_year, now.tm_mon, now.tm_mday, + now.tm_hour, now.tm_min, now.tm_sec, + now.tm_wday); + + ds->time_offset =qemu_timedate_diff (&now); +DPRINTK ("Update offset = %d\n" , ds->time_offset); +} + +static +int ds1375_event (I2CSlave *s,enum i2c_event event) +{ +DS1375State *ds =container_of (s, DS1375State, parent_obj); + +switch (event) { +case I2C_START_SEND : + ds->addrd = false; +case I2C_START_RECV : +ds1375_latch (ds); +case I2C_FINISH : +DPRINTK ("Event %d\n" , (int )event); +case I2C_NACK : +break ; + } +return 0 ; +} + +static +int ds1375_recv (I2CSlave *s) +{ +DS1375State *ds =container_of (s, DS1375State, parent_obj); +int ret =0 ; + +switch (ds->addr) { + case R_SEC ... R_YEAR: +case R_CTRL : +case R_STS : + case 0x10 ... 0x1f: + ret = ds->regs[ds->addr]; +break ; +default : +LOG (LOG_UNIMP ,"Read from unimplemented (%02x) %02x\n" , ds->addr, ret); + } + +DPRINTK ("Recv (%02x) %02x\n" , ds->addr, ret); + + ds->addr++; + ds->addr &=0x1f ; +if (ds->addr ==0 ) { +ds1375_latch (ds); + } + +return ret; +} + +static +int ds1375_send (I2CSlave *s,uint8_t data) +{ +DS1375State *ds =container_of (s, DS1375State, parent_obj); + +if (!ds->addrd) { + data &=0x1f ; + ds->addr = data; +DPRINTK ("Set address pointer %02x\n" , data); + ds->addrd = true; +return 0 ; + + }else { +DPRINTK ("Send (%02x) %02x\n" , ds->addr, data); +switch (ds->addr) { + case R_SEC ... R_YEAR: + ds->regs[ds->addr] = data; +ds1375_update (ds); +break ; +case R_CTRL : +if (data &0x7 ) { +LOG (LOG_UNIMP ,"Alarm interrupt/output not modeled\n" ); + } + ds->regs[ds->addr] = data; +break ; + case 0x10 ... 0x1f: + ds->regs[ds->addr] = data; +break ; +default : +LOG (LOG_UNIMP ,"Write to unimplemented (%02x) %02x\n" , + ds->addr, data); + } + + ds->addr++; + ds->addr &=0x1f ; +if (ds->addr ==0 ) { +ds1375_latch (ds); + } + +return 0 ; + } +} + +static +void ds1375_reset (DeviceState *device) +{ +DS1375State *ds =DS1375 (device); + +memset (ds->regs,0 ,sizeof (ds->regs)); +/* TODO: not clear SRAM? */ + +/* Default to 12-hour mode */ +ARRAY_FIELD_DP32 (ds->regs,CTRL ,ECLK ,1 ); + + ds->addr =0 ; + +/* do not re-zero time offset */ +} + +static +void ds1375_class_init (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); +I2CSlaveClass *k =I2C_SLAVE_CLASS (klass); + + k->event = &ds1375_event; + k->recv = &ds1375_recv; + k->send = &ds1375_send; + + dc->reset = &ds1375_reset; +} + +static +const TypeInfo ds1375_type = { + .name =TYPE_DS1375 , + .parent =TYPE_I2C_SLAVE , + .instance_size =sizeof (DS1375State), + .class_size =sizeof (I2CSlaveClass), + .class_init = ds1375_class_init, +}; + +static void ds1375_register (void ) +{ +type_register_static (&ds1375_type); +} + +type_init (ds1375_register)
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
PATCH 11/12 ppc: add mvme3100 machine
In reply to Michael Davidsaver--- hw/ppc/Makefile.objs | 1 + hw/ppc/mvme3100.c | 688 +++++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/mvme3100_cpld.c | 192 ++++++++++++++ 3 files changed, 881 insertions(+) create mode 100644 hw/ppc/mvme3100.c create mode 100644 hw/ppc/mvme3100_cpld.c
hw/ppc/Makefile.objs +1 -0
@@ -26,5 +26,6 @@ obj-$(CONFIG_MAC) += mac_newworld.o obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o obj-$(CONFIG_E500) += ppce500_spin.o obj-$(CONFIG_E500) += e500_ccsr.o +obj-$(CONFIG_E500) += mvme3100.o mvme3100_cpld.o # PowerPC 440 Xilinx ML507 reference board. obj-$(CONFIG_XILINX) += virtex_ml507.o
hw/ppc/mvme3100.c new file +688 -0
688 lines not on this page · raw message
hw/ppc/mvme3100_cpld.c new file +192 -0
192 lines not on this page · raw message
Signature · 1 line
2.11.0
PATCH 12/12 tests: add mvme3100-test
In reply to Michael DavidsaverExercise some features of the mvme3100 CPLD logic
and read from the eeprom w/ VPD.
--- tests/Makefile.include | 3 ++ tests/mvme3100-test.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tests/mvme3100-test.c
tests/Makefile.include +3 -0
@@ -372,6 +372,8 @@ check-qtest-s390x-y += tests/virtio-balloon-test$(EXESUF) check-qtest-s390x-y += tests/virtio-console-test$(EXESUF) check-qtest-s390x-y += tests/virtio-serial-test$(EXESUF) +check-qtest-ppc-$(CONFIG_E500) += tests/mvme3100-test$(EXESUF) + check-qtest-generic-y += tests/qom-test$(EXESUF) check-qtest-generic-y += tests/test-hmp$(EXESUF)
@@ -781,6 +783,7 @@ tests/i82801b11-test$(EXESUF): tests/i82801b11-test.o tests/ac97-test$(EXESUF): tests/ac97-test.o tests/es1370-test$(EXESUF): tests/es1370-test.o tests/intel-hda-test$(EXESUF): tests/intel-hda-test.o +tests/mvme3100-test$(EXESUF): tests/mvme3100-test.o $(libqos-e500-obj-y) tests/ioh3420-test$(EXESUF): tests/ioh3420-test.o tests/usb-hcd-ohci-test$(EXESUF): tests/usb-hcd-ohci-test.o $(libqos-usb-obj-y) tests/usb-hcd-uhci-test$(EXESUF): tests/usb-hcd-uhci-test.o $(libqos-usb-obj-y)
tests/mvme3100-test.c new file +79 -0
79 lines not on this page · raw message
Signature · 1 line
2.11.0
A message that is not in the archive (sent off-list or not yet received): [email protected]
David Gibson
AppliedRe: [Qemu-devel] [PATCH 02/12] e500: consolidate mpc8540 guts with e500-ccsr
Quoted 6 lines · Michael Davidsaver
Preparation for adding more MPCxxxx control
registers.Use e500 SVR to enable part specific registers. Only the mpc8544 reset register at present.
Quoted 7 lines
Expose CCSR as SysBusDevice region to eliminate
e500-ccsr.h.Track CCSR base address within device, and map on reset, in preparation for CCSRBAR.
Signed-off-by Michael Davidsaver <[email protected]>
Applied to ppc-for-2.12.
Quoted 466 lines
--- hw/pci-host/ppce500.c | 10 ++-- hw/ppc/Makefile.objs | 3 +- hw/ppc/e500-ccsr.h | 17 ------ hw/ppc/e500.c | 37 +----------- hw/ppc/e500_ccsr.c | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++ hw/ppc/mpc8544_guts.c | 143 ----------------------------------------------- 6 files changed, 162 insertions(+), 200 deletions(-) delete mode 100644 hw/ppc/e500-ccsr.h create mode 100644 hw/ppc/e500_ccsr.c delete mode 100644 hw/ppc/mpc8544_guts.chw/pci-host/ppce500.c +5
-5@@ -16,7 +16,6 @@#include "qemu/osdep.h" #include "hw/hw.h" -#include "hw/ppc/e500-ccsr.h" #include "hw/pci/pci.h" #include "hw/pci/pci_host.h" #include "qemu/bswap.h" @@ -420,16 +419,17 @@ static const VMStateDescription vmstate_ppce500_pci = {static void e500_pcihost_bridge_realize (PCIDevice *d,Error **errp) {PPCE500PCIBridgeState *b =PPC_E500_PCI_BRIDGE (d); -PPCE500CCSRState *ccsr =CCSR (container_get (qdev_get_machine (), -"/e500-ccsr" )); +SysBusDevice *ccsr =SYS_BUS_DEVICE (container_get (qdev_get_machine (), +"/e500-ccsr" )); +MemoryRegion *ccsr_mr =sysbus_mmio_get_region (ccsr,0 );pci_config_set_class (d->config,PCI_CLASS_BRIDGE_PCI ); d->config[PCI_HEADER_TYPE ] = (d->config[PCI_HEADER_TYPE ] &PCI_HEADER_TYPE_MULTI_FUNCTION ) |PCI_HEADER_TYPE_BRIDGE ; -memory_region_init_alias (&b->bar0,OBJECT (ccsr),"e500-pci-bar0" , &ccsr->ccsr_space, -0 ,int128_get64 (ccsr->ccsr_space.size)); +memory_region_init_alias (&b->bar0,OBJECT (ccsr),"e500-pci-bar0" , ccsr_mr, +0 ,memory_region_size (ccsr_mr));pci_register_bar (d,0 ,PCI_BASE_ADDRESS_SPACE_MEMORY , &b->bar0); }hw/ppc/Makefile.objs +2
-1@@ -24,6 +24,7 @@ obj-$(CONFIG_MAC) += mac_oldworld.o obj-$(CONFIG_MAC) += mac_newworld.o # e500 obj-$(CONFIG_E500) += e500.o mpc8544ds.o e500plat.o -obj-$(CONFIG_E500) += mpc8544_guts.o ppce500_spin.o +obj-$(CONFIG_E500) += ppce500_spin.o +obj-$(CONFIG_E500) += e500_ccsr.o # PowerPC 440 Xilinx ML507 reference board. obj-$(CONFIG_XILINX) += virtex_ml507.ohw/ppc/e500-ccsr.h deleted +0
-17@@ -1,17 +0,0 @@ -#ifndef E500_CCSR_H -#define E500_CCSR_H - -#include "hw/sysbus.h" - -typedef struct PPCE500CCSRState { -/*< private >*/ -SysBusDevice parent; -/*< public >*/ - -MemoryRegion ccsr_space; -}PPCE500CCSRState ; - -#define TYPE_CCSR "e500-ccsr" -#define CCSR (obj) OBJECT_CHECK(PPCE500CCSRState, (obj), TYPE_CCSR) - -#endif /* E500_CCSR_H */ hw/ppc/e500.c +3
-34@@ -15,10 +15,10 @@*/ #include "qemu/osdep.h" +#include "qemu/log.h" #include "qapi/error.h" #include "qemu-common.h" #include "e500.h" -#include "e500-ccsr.h" #include "net/net.h" #include "qemu/config-file.h" #include "hw/hw.h" @@ -795,7 +795,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)CPUPPCState *firstenv =NULL ;MemoryRegion *ccsr_addr_space;SysBusDevice *s; -PPCE500CCSRState *ccsr; irqs =g_malloc0 (smp_cpus *sizeof (qemu_irq *)); irqs[0 ] =g_malloc0 (smp_cpus *sizeof (qemu_irq) *OPENPIC_OUTPUT_NB );@@ -854,11 +853,9 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) dev =qdev_create (NULL ,"e500-ccsr" );object_property_add_child (qdev_get_machine (),"e500-ccsr" ,OBJECT (dev),NULL ); +qdev_prop_set_uint32 (dev,"base" , params->ccsrbar_base);qdev_init_nofail (dev); - ccsr =CCSR (dev); - ccsr_addr_space = &ccsr->ccsr_space; -memory_region_add_subregion (address_space_mem, params->ccsrbar_base, - ccsr_addr_space); + ccsr_addr_space =sysbus_mmio_get_region (SYS_BUS_DEVICE (dev),0 ); mpicdev =ppce500_init_mpic (machine, params, ccsr_addr_space, irqs);@@ -875,13 +872,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) serial_hds[1], DEVICE_BIG_ENDIAN); } -/* General Utility device */ - dev =qdev_create (NULL ,"mpc8544-guts" ); -qdev_init_nofail (dev); - s =SYS_BUS_DEVICE (dev); -memory_region_add_subregion (ccsr_addr_space,MPC8544_UTIL_OFFSET , -sysbus_mmio_get_region (s,0 )); -/* PCI */ dev =qdev_create (NULL ,"e500-pcihost" );qdev_prop_set_uint32 (dev,"first_slot" , params->pci_first_slot);@@ -1039,24 +1029,3 @@ void ppce500_init(MachineState *machine, PPCE500Params *params) boot_info->dt_base = dt_base; boot_info->dt_size = dt_size; } - -static void e500_ccsr_initfn (Object *obj) -{ -PPCE500CCSRState *ccsr =CCSR (obj); -memory_region_init (&ccsr->ccsr_space, obj,"e500-ccsr" , -MPC8544_CCSRBAR_SIZE ); -} - -static const TypeInfo e500_ccsr_info = { - .name =TYPE_CCSR , - .parent =TYPE_SYS_BUS_DEVICE , - .instance_size =sizeof (PPCE500CCSRState), - .instance_init = e500_ccsr_initfn, -}; - -static void e500_register_types (void ) -{ -type_register_static (&e500_ccsr_info); -} - -type_init (e500_register_types)hw/ppc/e500_ccsr.c new file +152
-0@@ -0,0 +1,152 @@ +/* +* MPC8540 and MPC8544 specific control registers. +* Not really part of e500 spec, but common to many +* Freescale parts w/ e500 cores. +* +* Copyright (c) 2017 Michael Davidsaver +* Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved. +* +* Authors: Alexander Graf, <[email protected]> +* Michael Davidsaver <[email protected]> +* +* This work is licensed under the terms of the GNU GPL, version 2. See +* the LICENSE file in the top-level directory. +* +* This model was developed according to: +* +* MPC8544E PowerQUICC III Integrated Host Processor Family Reference Manual +* Rev. 1 +* +* MPC8540 PowerQUICC III Integrated Host Processor Reference Manual, Rev. 1 +*/ + +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "qemu/log.h" +#include "qemu/error-report.h" +#include "cpu.h" +#include "hw/hw.h" +#include "sysemu/sysemu.h" +#include "hw/sysbus.h" + +/* E500_ denotes registers common to all */ + +#define E500_PVR (0xE00A0) +#define E500_SVR (0xE00A4) + +#define MPC8544_RSTCR (0xE00B0) +#define MPC8544_RSTCR_RESET (0x02) + +typedef struct { +/*< private >*/ +SysBusDevice parent_obj; +/*< public >*/ + +MemoryRegion iomem; + +uint32_t defbase; +}CCSRState ; + +#define TYPE_E500_CCSR "e500-ccsr" +#define E500_CCSR (obj) OBJECT_CHECK(CCSRState, (obj), TYPE_E500_CCSR) + +static uint64_t e500_ccsr_read (void *opaque,hwaddr addr, +unsigned size) +{ +PowerPCCPU *cpu =POWERPC_CPU (current_cpu); +CPUPPCState *env = &cpu->env; + +switch (addr) { +case E500_PVR : +return env->spr[SPR_PVR ]; +case E500_SVR : +return env->spr[SPR_E500_SVR ]; + } + +qemu_log_mask (LOG_GUEST_ERROR |LOG_UNIMP , +"can't read undefined ccsr regster %x\n" , + (unsigned )addr); +return 0 ; +} + +static void e500_ccsr_write (void *opaque,hwaddr addr, +uint64_t value,unsigned size) +{ +PowerPCCPU *cpu =POWERPC_CPU (current_cpu); +CPUPPCState *env = &cpu->env; +uint32_t svr = env->spr[SPR_E500_SVR ] >>16 ; + +switch (svr) { +case 0 :/* generic. assumed to be mpc8544ds or e500plat board */ +case 0x8034 :/* mpc8544 */ +case 0x803C :/* mpc8544E */ +switch (addr) { +case MPC8544_RSTCR : +if (value &MPC8544_RSTCR_RESET ) { +qemu_system_reset_request (SHUTDOWN_CAUSE_GUEST_RESET ); + } +return ; + } + } + +qemu_log_mask (LOG_GUEST_ERROR |LOG_UNIMP , +"can't write undefined ccsr regster %x <- %08x\n" , + (unsigned )addr, (unsigned )value); +} + +static const MemoryRegionOps e500_ccsr_ops = { + .read = e500_ccsr_read, + .write = e500_ccsr_write, + .endianness =DEVICE_BIG_ENDIAN , + .impl = { + .min_access_size =4 , + .max_access_size =4 , + } +}; + +static void e500_ccsr_reset (DeviceState *dev) +{ +CCSRState *ccsr =E500_CCSR (dev); + +sysbus_mmio_map (SYS_BUS_DEVICE (dev),0 , ccsr->defbase); +} + +static void e500_ccsr_initfn (Object *obj) +{ +CCSRState *ccsr =E500_CCSR (obj); + +memory_region_init_io (&ccsr->iomem, obj, &e500_ccsr_ops, + ccsr,"e500-ccsr" ,1024 *1024 ); +sysbus_init_mmio (SYS_BUS_DEVICE (obj), &ccsr->iomem); + +} + +static Property e500_ccsr_props[] = { +DEFINE_PROP_UINT32 ("base" , CCSRState, defbase,0xff700000 ), +DEFINE_PROP_END_OF_LIST () +}; + +static +void e500_ccsr_class_initfn (ObjectClass *klass,void *data) +{ +DeviceClass *dc =DEVICE_CLASS (klass); + + dc->props = e500_ccsr_props; + dc->reset = e500_ccsr_reset; +} + +static const TypeInfo e500_ccsr_info = { + .name =TYPE_E500_CCSR , + .parent =TYPE_SYS_BUS_DEVICE , + .instance_size =sizeof (CCSRState), + .instance_init = e500_ccsr_initfn, + .class_size =sizeof (SysBusDeviceClass), + .class_init = e500_ccsr_class_initfn +}; + +static void e500_ccsr_register_types (void ) +{ +type_register_static (&e500_ccsr_info); +} + +type_init (e500_ccsr_register_types)hw/ppc/mpc8544_guts.c deleted +0
-143@@ -1,143 +0,0 @@ -/* -* QEMU PowerPC MPC8544 global util pseudo-device -* -* Copyright (C) 2011 Freescale Semiconductor, Inc. All rights reserved. -* -* Author: Alexander Graf, <[email protected]> -* -* This is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* ***************************************************************** -* -* The documentation for this device is noted in the MPC8544 documentation, -* file name "MPC8544ERM.pdf". You can easily find it on the web. -* -*/ - -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "cpu.h" -#include "hw/hw.h" -#include "sysemu/sysemu.h" -#include "hw/sysbus.h" - -#define MPC8544_GUTS_MMIO_SIZE 0x1000 -#define MPC8544_GUTS_RSTCR_RESET 0x02 - -#define MPC8544_GUTS_ADDR_PORPLLSR 0x00 -#define MPC8544_GUTS_ADDR_PORBMSR 0x04 -#define MPC8544_GUTS_ADDR_PORIMPSCR 0x08 -#define MPC8544_GUTS_ADDR_PORDEVSR 0x0C -#define MPC8544_GUTS_ADDR_PORDBGMSR 0x10 -#define MPC8544_GUTS_ADDR_PORDEVSR2 0x14 -#define MPC8544_GUTS_ADDR_GPPORCR 0x20 -#define MPC8544_GUTS_ADDR_GPIOCR 0x30 -#define MPC8544_GUTS_ADDR_GPOUTDR 0x40 -#define MPC8544_GUTS_ADDR_GPINDR 0x50 -#define MPC8544_GUTS_ADDR_PMUXCR 0x60 -#define MPC8544_GUTS_ADDR_DEVDISR 0x70 -#define MPC8544_GUTS_ADDR_POWMGTCSR 0x80 -#define MPC8544_GUTS_ADDR_MCPSUMR 0x90 -#define MPC8544_GUTS_ADDR_RSTRSCR 0x94 -#define MPC8544_GUTS_ADDR_PVR 0xA0 -#define MPC8544_GUTS_ADDR_SVR 0xA4 -#define MPC8544_GUTS_ADDR_RSTCR 0xB0 -#define MPC8544_GUTS_ADDR_IOVSELSR 0xC0 -#define MPC8544_GUTS_ADDR_DDRCSR 0xB20 -#define MPC8544_GUTS_ADDR_DDRCDR 0xB24 -#define MPC8544_GUTS_ADDR_DDRCLKDR 0xB28 -#define MPC8544_GUTS_ADDR_CLKOCR 0xE00 -#define MPC8544_GUTS_ADDR_SRDS1CR1 0xF04 -#define MPC8544_GUTS_ADDR_SRDS2CR1 0xF10 -#define MPC8544_GUTS_ADDR_SRDS2CR3 0xF18 - -#define TYPE_MPC8544_GUTS "mpc8544-guts" -#define MPC8544_GUTS (obj) OBJECT_CHECK(GutsState, (obj), TYPE_MPC8544_GUTS) - -struct GutsState { -/*< private >*/ -SysBusDevice parent_obj; -/*< public >*/ - -MemoryRegion iomem; -}; - -typedef struct GutsState GutsState ; - -static uint64_t mpc8544_guts_read (void *opaque,hwaddr addr, -unsigned size) -{ -uint32_t value =0 ; -PowerPCCPU *cpu =POWERPC_CPU (current_cpu); -CPUPPCState *env = &cpu->env; - - addr &=MPC8544_GUTS_MMIO_SIZE -1 ; -switch (addr) { -case MPC8544_GUTS_ADDR_PVR : - value = env->spr[SPR_PVR ]; -break ; -case MPC8544_GUTS_ADDR_SVR : - value = env->spr[SPR_E500_SVR ]; -break ; -default : -fprintf (stderr,"guts: Unknown register read: %x\n" , (int )addr); -break ; - } - -return value; -} - -static void mpc8544_guts_write (void *opaque,hwaddr addr, -uint64_t value,unsigned size) -{ - addr &=MPC8544_GUTS_MMIO_SIZE -1 ; - -switch (addr) { -case MPC8544_GUTS_ADDR_RSTCR : -if (value &MPC8544_GUTS_RSTCR_RESET ) { -qemu_system_reset_request (SHUTDOWN_CAUSE_GUEST_RESET ); - } -break ; -default : -fprintf (stderr,"guts: Unknown register write: %x = %x\n" , - (int )addr, (unsigned )value); -break ; - } -} - -static const MemoryRegionOps mpc8544_guts_ops = { - .read = mpc8544_guts_read, - .write = mpc8544_guts_write, - .endianness =DEVICE_BIG_ENDIAN , - .valid = { - .min_access_size =4 , - .max_access_size =4 , - }, -}; - -static void mpc8544_guts_initfn (Object *obj) -{ -SysBusDevice *d =SYS_BUS_DEVICE (obj); -GutsState *s =MPC8544_GUTS (obj); - -memory_region_init_io (&s->iomem,OBJECT (s), &mpc8544_guts_ops, s, -"mpc8544.guts" ,MPC8544_GUTS_MMIO_SIZE ); -sysbus_init_mmio (d, &s->iomem); -} - -static const TypeInfo mpc8544_guts_info = { - .name =TYPE_MPC8544_GUTS , - .parent =TYPE_SYS_BUS_DEVICE , - .instance_size =sizeof (GutsState), - .instance_init = mpc8544_guts_initfn, -}; - -static void mpc8544_guts_register_types (void ) -{ -type_register_static (&mpc8544_guts_info); -} - -type_init (mpc8544_guts_register_types)
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [PATCH 02/12] e500: consolidate mpc8540 guts with e500-ccsr
Quoted 10 lines · David Gibson
Quoted 9 lines · Michael Davidsaver
Preparation for adding more MPCxxxx control
registers.Use e500 SVR to enable part specific registers.
Only the mpc8544 reset register at present.Expose CCSR as SysBusDevice region to eliminate
e500-ccsr.h.
Quoted 6 lines
Quoted 4 lines
Track CCSR base address within device, and map on reset, in preparation for CCSRBAR.
Signed-off-by Michael Davidsaver <[email protected]>Applied to ppc-for-2.12.
Sorry. I've now pulled this from ppc-for-2.12, because it caused a breakage of make check (specifically the boot-serial-test with ppc64).
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Re: [Qemu-devel] [PATCH 02/12] e500: consolidate mpc8540 guts with e500-ccsr
Quoted 14 lines · David Gibson
Quoted 13 lines · David Gibson
Quoted 12 lines · Michael Davidsaver
Preparation for adding more MPCxxxx control
registers.Use e500 SVR to enable part specific registers.
Only the mpc8544 reset register at present.Expose CCSR as SysBusDevice region to eliminate
e500-ccsr.h.Track CCSR base address within device, and map on reset, in preparation for CCSRBAR.
Quoted 6 lines
Quoted 3 lines
Quoted 1 line
Signed-off-by Michael Davidsaver <[email protected]>Applied to ppc-for-2.12.
Sorry. I've now pulled this from ppc-for-2.12, because it caused a breakage of make check (specifically the boot-serial-test with ppc64).
Oops, I'll begin running this test myself. So far I've only been running tests for i386, amd64, arm, and ppc.
Re: [Qemu-devel] [PATCH 02/12] e500: consolidate mpc8540 guts with e500-ccsr
Quoted 17 lines · Michael Davidsaver
Quoted 16 lines · David Gibson
Quoted 15 lines · David Gibson
Quoted 13 lines · Michael Davidsaver
Preparation for adding more MPCxxxx control
registers.Use e500 SVR to enable part specific registers.
Only the mpc8544 reset register at present.Expose CCSR as SysBusDevice region to eliminate
e500-ccsr.h.Track CCSR base address within device, and map on reset, in preparation for CCSRBAR.
Signed-off-by Michael Davidsaver <[email protected]>
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
Applied to ppc-for-2.12.
Sorry. I've now pulled this from ppc-for-2.12, because it caused a breakage of make check (specifically the boot-serial-test with ppc64).
Oops, I'll begin running this test myself. So far I've only been running tests for i386, amd64, arm, and ppc.
I really recommend running a build and make check smoke test for all targets ("./configure && make && make check SPEED=slow") before posting patches for submission. It takes a while, but not stupidly long.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
Quoted 28 lines · Michael Davidsaver
This series adds simulation of MVME3100 powerpc SBCs, originally from Motorola, and now sold by Artesyn[1]. There are two variants differing in CPU speed and memory size.
I've been working on this sporadically for the past 2 year. Recently I've finished all the features which I have in mind. If this series is accepted there is a continuation which adds VME bus. I've found it useful in software compatibility testing. I wonder if there is any interest at large?
There are two main parts of this series. 1-5 are changing code common with the "ppce500" and "mpc8544ds" boards, with the remainder being additions.
The changes are to how the CCSR region is handled in order to support the CCSRBAR register which allows the whole region to be relocated. Also added are a couple of memory and clock configuration registers which RTEMS guests read.
#3 is actually a minor issue I found recently with the mpc8544 PCI host bridge, which I'm uncertain how to address. The host bridge device 0:0 identifies itself as a bridge, but doesn't properly implement the bridge config registers. This confuses Linux, which then does a full re-enumeration (successfully).
The rest are additions of an I2C controller, an I2C eeprom, an I2C RTC, and new board code.
Quoted 7 lines
My testing has been almost exclusively with an RTEMS guest[2]. Though I have recently done a little with Linux.
RTEMS guests (and Linux too for now) require a stub bootloader[3] to put the system in the same state as the real bootloader. RTEMS has an unfortunately strong dependence on bootloader provided configuration (eg. it doesn't re-enumerate the PCI bus).
I've applied several patches from this series to ppc-for-2.12, others I've commented on. If you could address the comments and rebase what's left on ppc-for-2.12, that would be great.
Signature · 4 lines
David Gibson | I'll have my music baroque, and my code david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_ | _way_ _around_! http://www.ozlabs.org/~dgibson
On 11/21/2017 10:12 PM, David Gibson wrote:
...
Quoted 3 lines
I've applied several patches from this series to ppc-for-2.12, others I've commented on. If you could address the comments and rebase what's left on ppc-for-2.12, that would be great.
Will do.