qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
       [not found] <cover.1556515687.git.alistair@alistair23.me>
@ 2019-04-29  5:29 ` Alistair Francis
  2019-04-29  5:29   ` Alistair Francis
  2019-04-29  5:32 ` Alistair Francis
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Allow the kernel's entry point information to be returned when loading a
kernel.

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 hw/arm/armv7m.c      | 6 +++---
 hw/arm/microbit.c    | 2 +-
 hw/arm/mps2-tz.c     | 3 ++-
 hw/arm/mps2.c        | 2 +-
 hw/arm/msf2-som.c    | 2 +-
 hw/arm/musca.c       | 3 ++-
 hw/arm/netduino2.c   | 2 +-
 hw/arm/stellaris.c   | 3 ++-
 include/hw/arm/arm.h | 4 +++-
 9 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c4b2a9a1f5..a52328f188 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -286,10 +286,10 @@ static void armv7m_reset(void *opaque)
     cpu_reset(CPU(cpu));
 }
 
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry)
 {
     int image_size;
-    uint64_t entry;
     uint64_t lowaddr;
     int big_endian;
     AddressSpace *as;
@@ -311,7 +311,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
 
     if (kernel_filename) {
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
-                                 &entry, &lowaddr,
+                                 entry, &lowaddr,
                                  NULL, big_endian, EM_ARM, 1, 0, as);
         if (image_size < 0) {
             image_size = load_image_targphys_as(kernel_filename, 0,
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index da67bf6d9d..03147750f1 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -58,7 +58,7 @@ static void microbit_init(MachineState *machine)
                                         mr, -1);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       NRF51_SOC(soc)->flash_size);
+                       NRF51_SOC(soc)->flash_size, NULL);
 }
 
 static void microbit_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index f79f090a4a..f6dc7dce2a 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -613,7 +613,8 @@ static void mps2tz_common_init(MachineState *machine)
 
     create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000,
+                       NULL);
 }
 
 static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index e3d698ba6c..55d2273a54 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -328,7 +328,7 @@ static void mps2_common_init(MachineState *machine)
     system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       0x400000);
+                       0x400000, NULL);
 }
 
 static void mps2_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index 2432b5e935..f81be74716 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -92,7 +92,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
     sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       soc->envm_size);
+                       soc->envm_size, NULL);
 }
 
 static void emcraft_sf2_machine_init(MachineClass *mc)
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 23aff43f4b..59460ba090 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -589,7 +589,8 @@ static void musca_init(MachineState *machine)
                                                      "cfg_sec_resp", 0));
     }
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000,
+                       NULL);
 }
 
 static void musca_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
index f936017d4a..38a6d8fdd1 100644
--- a/hw/arm/netduino2.c
+++ b/hw/arm/netduino2.c
@@ -38,7 +38,7 @@ static void netduino2_init(MachineState *machine)
     object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       FLASH_SIZE);
+                       FLASH_SIZE, NULL);
 }
 
 static void netduino2_machine_init(MachineClass *mc)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 05f86749f4..276b1acc46 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1459,7 +1459,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
     create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
     create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
+    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size,
+                       NULL);
 }
 
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index ffed39252d..10f7e10d95 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -28,12 +28,14 @@ typedef enum {
  * @cpu: CPU
  * @kernel_filename: file to load
  * @mem_size: mem_size: maximum image size to load
+ * @entry: location of the kernel's entry point
  *
  * Load the guest image for an ARMv7M system. This must be called by
  * any ARMv7M board. (This is necessary to ensure that the CPU resets
  * correctly on system reset, as well as for kernel loading.)
  */
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry);
 
 /* arm_boot.c */
 struct arm_boot_info {
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-04-29  5:29 ` [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned Alistair Francis
@ 2019-04-29  5:29   ` Alistair Francis
  0 siblings, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:29 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Allow the kernel's entry point information to be returned when loading a
kernel.

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 hw/arm/armv7m.c      | 6 +++---
 hw/arm/microbit.c    | 2 +-
 hw/arm/mps2-tz.c     | 3 ++-
 hw/arm/mps2.c        | 2 +-
 hw/arm/msf2-som.c    | 2 +-
 hw/arm/musca.c       | 3 ++-
 hw/arm/netduino2.c   | 2 +-
 hw/arm/stellaris.c   | 3 ++-
 include/hw/arm/arm.h | 4 +++-
 9 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c4b2a9a1f5..a52328f188 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -286,10 +286,10 @@ static void armv7m_reset(void *opaque)
     cpu_reset(CPU(cpu));
 }
 
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry)
 {
     int image_size;
-    uint64_t entry;
     uint64_t lowaddr;
     int big_endian;
     AddressSpace *as;
@@ -311,7 +311,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
 
     if (kernel_filename) {
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
-                                 &entry, &lowaddr,
+                                 entry, &lowaddr,
                                  NULL, big_endian, EM_ARM, 1, 0, as);
         if (image_size < 0) {
             image_size = load_image_targphys_as(kernel_filename, 0,
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index da67bf6d9d..03147750f1 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -58,7 +58,7 @@ static void microbit_init(MachineState *machine)
                                         mr, -1);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       NRF51_SOC(soc)->flash_size);
+                       NRF51_SOC(soc)->flash_size, NULL);
 }
 
 static void microbit_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index f79f090a4a..f6dc7dce2a 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -613,7 +613,8 @@ static void mps2tz_common_init(MachineState *machine)
 
     create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000,
+                       NULL);
 }
 
 static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index e3d698ba6c..55d2273a54 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -328,7 +328,7 @@ static void mps2_common_init(MachineState *machine)
     system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       0x400000);
+                       0x400000, NULL);
 }
 
 static void mps2_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index 2432b5e935..f81be74716 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -92,7 +92,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
     sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       soc->envm_size);
+                       soc->envm_size, NULL);
 }
 
 static void emcraft_sf2_machine_init(MachineClass *mc)
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 23aff43f4b..59460ba090 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -589,7 +589,8 @@ static void musca_init(MachineState *machine)
                                                      "cfg_sec_resp", 0));
     }
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000,
+                       NULL);
 }
 
 static void musca_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
index f936017d4a..38a6d8fdd1 100644
--- a/hw/arm/netduino2.c
+++ b/hw/arm/netduino2.c
@@ -38,7 +38,7 @@ static void netduino2_init(MachineState *machine)
     object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       FLASH_SIZE);
+                       FLASH_SIZE, NULL);
 }
 
 static void netduino2_machine_init(MachineClass *mc)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 05f86749f4..276b1acc46 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1459,7 +1459,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
     create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
     create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
+    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size,
+                       NULL);
 }
 
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index ffed39252d..10f7e10d95 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -28,12 +28,14 @@ typedef enum {
  * @cpu: CPU
  * @kernel_filename: file to load
  * @mem_size: mem_size: maximum image size to load
+ * @entry: location of the kernel's entry point
  *
  * Load the guest image for an ARMv7M system. This must be called by
  * any ARMv7M board. (This is necessary to ensure that the CPU resets
  * correctly on system reset, as well as for kernel loading.)
  */
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry);
 
 /* arm_boot.c */
 struct arm_boot_info {
-- 
2.21.0



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

* [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
       [not found] <cover.1556515687.git.alistair@alistair23.me>
  2019-04-29  5:29 ` [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned Alistair Francis
@ 2019-04-29  5:32 ` Alistair Francis
  2019-04-29  5:32   ` Alistair Francis
  2019-04-30 16:04   ` Peter Maydell
  2019-04-29  5:32 ` [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device Alistair Francis
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Allow the kernel's entry point information to be returned when loading a
kernel.

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 hw/arm/armv7m.c      | 6 +++---
 hw/arm/microbit.c    | 2 +-
 hw/arm/mps2-tz.c     | 3 ++-
 hw/arm/mps2.c        | 2 +-
 hw/arm/msf2-som.c    | 2 +-
 hw/arm/musca.c       | 3 ++-
 hw/arm/netduino2.c   | 2 +-
 hw/arm/stellaris.c   | 3 ++-
 include/hw/arm/arm.h | 4 +++-
 9 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c4b2a9a1f5..a52328f188 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -286,10 +286,10 @@ static void armv7m_reset(void *opaque)
     cpu_reset(CPU(cpu));
 }
 
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry)
 {
     int image_size;
-    uint64_t entry;
     uint64_t lowaddr;
     int big_endian;
     AddressSpace *as;
@@ -311,7 +311,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
 
     if (kernel_filename) {
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
-                                 &entry, &lowaddr,
+                                 entry, &lowaddr,
                                  NULL, big_endian, EM_ARM, 1, 0, as);
         if (image_size < 0) {
             image_size = load_image_targphys_as(kernel_filename, 0,
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index da67bf6d9d..03147750f1 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -58,7 +58,7 @@ static void microbit_init(MachineState *machine)
                                         mr, -1);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       NRF51_SOC(soc)->flash_size);
+                       NRF51_SOC(soc)->flash_size, NULL);
 }
 
 static void microbit_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index f79f090a4a..f6dc7dce2a 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -613,7 +613,8 @@ static void mps2tz_common_init(MachineState *machine)
 
     create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000,
+                       NULL);
 }
 
 static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index e3d698ba6c..55d2273a54 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -328,7 +328,7 @@ static void mps2_common_init(MachineState *machine)
     system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       0x400000);
+                       0x400000, NULL);
 }
 
 static void mps2_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index 2432b5e935..f81be74716 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -92,7 +92,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
     sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       soc->envm_size);
+                       soc->envm_size, NULL);
 }
 
 static void emcraft_sf2_machine_init(MachineClass *mc)
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 23aff43f4b..59460ba090 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -589,7 +589,8 @@ static void musca_init(MachineState *machine)
                                                      "cfg_sec_resp", 0));
     }
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000,
+                       NULL);
 }
 
 static void musca_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
index f936017d4a..38a6d8fdd1 100644
--- a/hw/arm/netduino2.c
+++ b/hw/arm/netduino2.c
@@ -38,7 +38,7 @@ static void netduino2_init(MachineState *machine)
     object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       FLASH_SIZE);
+                       FLASH_SIZE, NULL);
 }
 
 static void netduino2_machine_init(MachineClass *mc)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 05f86749f4..276b1acc46 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1459,7 +1459,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
     create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
     create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
+    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size,
+                       NULL);
 }
 
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index ffed39252d..10f7e10d95 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -28,12 +28,14 @@ typedef enum {
  * @cpu: CPU
  * @kernel_filename: file to load
  * @mem_size: mem_size: maximum image size to load
+ * @entry: location of the kernel's entry point
  *
  * Load the guest image for an ARMv7M system. This must be called by
  * any ARMv7M board. (This is necessary to ensure that the CPU resets
  * correctly on system reset, as well as for kernel loading.)
  */
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry);
 
 /* arm_boot.c */
 struct arm_boot_info {
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-04-29  5:32 ` Alistair Francis
@ 2019-04-29  5:32   ` Alistair Francis
  2019-04-30 16:04   ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Allow the kernel's entry point information to be returned when loading a
kernel.

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 hw/arm/armv7m.c      | 6 +++---
 hw/arm/microbit.c    | 2 +-
 hw/arm/mps2-tz.c     | 3 ++-
 hw/arm/mps2.c        | 2 +-
 hw/arm/msf2-som.c    | 2 +-
 hw/arm/musca.c       | 3 ++-
 hw/arm/netduino2.c   | 2 +-
 hw/arm/stellaris.c   | 3 ++-
 include/hw/arm/arm.h | 4 +++-
 9 files changed, 16 insertions(+), 11 deletions(-)

diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
index c4b2a9a1f5..a52328f188 100644
--- a/hw/arm/armv7m.c
+++ b/hw/arm/armv7m.c
@@ -286,10 +286,10 @@ static void armv7m_reset(void *opaque)
     cpu_reset(CPU(cpu));
 }
 
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry)
 {
     int image_size;
-    uint64_t entry;
     uint64_t lowaddr;
     int big_endian;
     AddressSpace *as;
@@ -311,7 +311,7 @@ void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
 
     if (kernel_filename) {
         image_size = load_elf_as(kernel_filename, NULL, NULL, NULL,
-                                 &entry, &lowaddr,
+                                 entry, &lowaddr,
                                  NULL, big_endian, EM_ARM, 1, 0, as);
         if (image_size < 0) {
             image_size = load_image_targphys_as(kernel_filename, 0,
diff --git a/hw/arm/microbit.c b/hw/arm/microbit.c
index da67bf6d9d..03147750f1 100644
--- a/hw/arm/microbit.c
+++ b/hw/arm/microbit.c
@@ -58,7 +58,7 @@ static void microbit_init(MachineState *machine)
                                         mr, -1);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       NRF51_SOC(soc)->flash_size);
+                       NRF51_SOC(soc)->flash_size, NULL);
 }
 
 static void microbit_machine_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
index f79f090a4a..f6dc7dce2a 100644
--- a/hw/arm/mps2-tz.c
+++ b/hw/arm/mps2-tz.c
@@ -613,7 +613,8 @@ static void mps2tz_common_init(MachineState *machine)
 
     create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000,
+                       NULL);
 }
 
 static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
index e3d698ba6c..55d2273a54 100644
--- a/hw/arm/mps2.c
+++ b/hw/arm/mps2.c
@@ -328,7 +328,7 @@ static void mps2_common_init(MachineState *machine)
     system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       0x400000);
+                       0x400000, NULL);
 }
 
 static void mps2_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
index 2432b5e935..f81be74716 100644
--- a/hw/arm/msf2-som.c
+++ b/hw/arm/msf2-som.c
@@ -92,7 +92,7 @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
     sysbus_connect_irq(SYS_BUS_DEVICE(&soc->spi[0]), 1, cs_line);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       soc->envm_size);
+                       soc->envm_size, NULL);
 }
 
 static void emcraft_sf2_machine_init(MachineClass *mc)
diff --git a/hw/arm/musca.c b/hw/arm/musca.c
index 23aff43f4b..59460ba090 100644
--- a/hw/arm/musca.c
+++ b/hw/arm/musca.c
@@ -589,7 +589,8 @@ static void musca_init(MachineState *machine)
                                                      "cfg_sec_resp", 0));
     }
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000);
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x2000000,
+                       NULL);
 }
 
 static void musca_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
index f936017d4a..38a6d8fdd1 100644
--- a/hw/arm/netduino2.c
+++ b/hw/arm/netduino2.c
@@ -38,7 +38,7 @@ static void netduino2_init(MachineState *machine)
     object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
 
     armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
-                       FLASH_SIZE);
+                       FLASH_SIZE, NULL);
 }
 
 static void netduino2_machine_init(MachineClass *mc)
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index 05f86749f4..276b1acc46 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1459,7 +1459,8 @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
     create_unimplemented_device("hibernation", 0x400fc000, 0x1000);
     create_unimplemented_device("flash-control", 0x400fd000, 0x1000);
 
-    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size);
+    armv7m_load_kernel(ARM_CPU(first_cpu), ms->kernel_filename, flash_size,
+                       NULL);
 }
 
 /* FIXME: Figure out how to generate these from stellaris_boards.  */
diff --git a/include/hw/arm/arm.h b/include/hw/arm/arm.h
index ffed39252d..10f7e10d95 100644
--- a/include/hw/arm/arm.h
+++ b/include/hw/arm/arm.h
@@ -28,12 +28,14 @@ typedef enum {
  * @cpu: CPU
  * @kernel_filename: file to load
  * @mem_size: mem_size: maximum image size to load
+ * @entry: location of the kernel's entry point
  *
  * Load the guest image for an ARMv7M system. This must be called by
  * any ARMv7M board. (This is necessary to ensure that the CPU resets
  * correctly on system reset, as well as for kernel loading.)
  */
-void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size);
+void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
+                        uint64_t *entry);
 
 /* arm_boot.c */
 struct arm_boot_info {
-- 
2.21.0



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

* [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device
       [not found] <cover.1556515687.git.alistair@alistair23.me>
  2019-04-29  5:29 ` [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned Alistair Francis
  2019-04-29  5:32 ` Alistair Francis
@ 2019-04-29  5:32 ` Alistair Francis
  2019-04-29  5:32   ` Alistair Francis
  2019-04-30 15:44   ` Peter Maydell
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device Alistair Francis
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 default-configs/arm-softmmu.mak    |   1 +
 hw/misc/Kconfig                    |   3 +
 hw/misc/Makefile.objs              |   1 +
 hw/misc/stm32f4xx_syscfg.c         | 275 +++++++++++++++++++++++++++++
 include/hw/misc/stm32f4xx_syscfg.h |  62 +++++++
 5 files changed, 342 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_syscfg.c
 create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 613d19a06d..c5cfdb857d 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -96,6 +96,7 @@ CONFIG_STM32F2XX_SYSCFG=y
 CONFIG_STM32F2XX_ADC=y
 CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
+CONFIG_STM32F4XX_SYSCFG=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 5f67d0d6d9..c6ff39aeeb 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -80,6 +80,9 @@ config IMX
 config STM32F2XX_SYSCFG
     bool
 
+config STM32F4XX_SYSCFG
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c71e07ae35..1413b1f232 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -57,6 +57,7 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_syscfg.c b/hw/misc/stm32f4xx_syscfg.c
new file mode 100644
index 0000000000..c0aaeeaf6c
--- /dev/null
+++ b/hw/misc/stm32f4xx_syscfg.c
@@ -0,0 +1,275 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/stm32f4xx_syscfg.h"
+
+#ifndef STM_SYSCFG_ERR_DEBUG
+#define STM_SYSCFG_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (STM_SYSCFG_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0)
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void stm32f4xx_syscfg_reset(DeviceState *dev)
+{
+    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev);
+
+    s->syscfg_memrmp = 0x00000000;
+    s->syscfg_pmc = 0x00000000;
+    s->syscfg_exticr1 = 0x00000000;
+    s->syscfg_exticr2 = 0x00000000;
+    s->syscfg_exticr3 = 0x00000000;
+    s->syscfg_exticr4 = 0x00000000;
+    s->syscfg_cmpcr = 0x00000000;
+}
+
+static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level)
+{
+    STM32F4xxSyscfgState *s = opaque;
+    uint8_t config;
+
+    DB_PRINT("Interupt: GPIO: %d, Line: %d; Level: %d\n", irq / 16,
+             irq % 16, level);
+
+    config = irq / 16;
+
+    switch (irq % 16) {
+    case 0:
+        if ((s->syscfg_exticr1 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[0], level);
+            DB_PRINT("Pulse EXTI: 0\n");
+        }
+        break;
+    case 1:
+        if (((s->syscfg_exticr1 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[1], level);
+            DB_PRINT("Pulse EXTI: 1\n");
+        }
+        break;
+    case 2:
+        if (((s->syscfg_exticr1 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[2], level);
+            DB_PRINT("Pulse EXTI: 2\n");
+        }
+        break;
+    case 3:
+        if (((s->syscfg_exticr1 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[3], level);
+            DB_PRINT("Pulse EXTI: 3\n");
+        }
+        break;
+    case 4:
+        if ((s->syscfg_exticr2 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[4], level);
+            DB_PRINT("Pulse EXTI: 4\n");
+        }
+        break;
+    case 5:
+        if (((s->syscfg_exticr2 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[5], level);
+            DB_PRINT("Pulse EXTI: 5\n");
+        }
+        break;
+    case 6:
+        if (((s->syscfg_exticr2 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[6], level);
+            DB_PRINT("Pulse EXTI: 6\n");
+        }
+        break;
+    case 7:
+        if (((s->syscfg_exticr2 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[7], level);
+            DB_PRINT("Pulse EXTI: 7\n");
+        }
+        break;
+    case 8:
+        if ((s->syscfg_exticr3 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[8], level);
+            DB_PRINT("Pulse EXTI: 8\n");
+        }
+        break;
+    case 9:
+        if (((s->syscfg_exticr3 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[9], level);
+            DB_PRINT("Pulse EXTI: 9\n");
+        }
+        break;
+    case 10:
+        if (((s->syscfg_exticr3 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[10], level);
+            DB_PRINT("Pulse EXTI: 10\n");
+        }
+        break;
+    case 11:
+        if (((s->syscfg_exticr3 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[11], level);
+            DB_PRINT("Pulse EXTI: 11\n");
+        }
+        break;
+    case 12:
+        if ((s->syscfg_exticr4 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[12], level);
+            DB_PRINT("Pulse EXTI: 12\n");
+        }
+        break;
+    case 13:
+        if (((s->syscfg_exticr4 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[13], level);
+            DB_PRINT("Pulse EXTI: 13\n");
+        }
+        break;
+    case 14:
+        if (((s->syscfg_exticr4 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[14], level);
+            DB_PRINT("Pulse EXTI: 14\n");
+        }
+        break;
+    case 15:
+        if (((s->syscfg_exticr4 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[15], level);
+            DB_PRINT("Pulse EXTI: 15\n");
+        }
+        break;
+    }
+}
+
+static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    STM32F4xxSyscfgState *s = opaque;
+
+    DB_PRINT("0x%"HWADDR_PRIx"\n", addr);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        return s->syscfg_memrmp;
+    case SYSCFG_PMC:
+        return s->syscfg_pmc;
+    case SYSCFG_EXTICR1:
+        return s->syscfg_exticr1;
+    case SYSCFG_EXTICR2:
+        return s->syscfg_exticr2;
+    case SYSCFG_EXTICR3:
+        return s->syscfg_exticr3;
+    case SYSCFG_EXTICR4:
+        return s->syscfg_exticr4;
+    case SYSCFG_CMPCR:
+        return s->syscfg_cmpcr;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+        return 0;
+    }
+
+    return 0;
+}
+
+static void stm32f4xx_syscfg_write(void *opaque, hwaddr addr,
+                       uint64_t val64, unsigned int size)
+{
+    STM32F4xxSyscfgState *s = opaque;
+    uint32_t value = val64;
+
+    DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Changeing the memory mapping isn't supported " \
+                      "in QEMU\n", __func__);
+        return;
+    case SYSCFG_PMC:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Changeing the memory mapping isn't supported " \
+                      "in QEMU\n", __func__);
+        return;
+    case SYSCFG_EXTICR1:
+        s->syscfg_exticr1 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR2:
+        s->syscfg_exticr2 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR3:
+        s->syscfg_exticr3 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR4:
+        s->syscfg_exticr4 = (value & 0xFFFF);
+        return;
+    case SYSCFG_CMPCR:
+        s->syscfg_cmpcr = value;
+        return;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+    }
+}
+
+static const MemoryRegionOps stm32f4xx_syscfg_ops = {
+    .read = stm32f4xx_syscfg_read,
+    .write = stm32f4xx_syscfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void stm32f4xx_syscfg_init(Object *obj)
+{
+    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(obj);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+    memory_region_init_io(&s->mmio, obj, &stm32f4xx_syscfg_ops, s,
+                          TYPE_STM32F4XX_SYSCFG, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_syscfg_set_irq, 16 * 9);
+    qdev_init_gpio_out(DEVICE(obj), s->gpio_out, 16);
+}
+
+static void stm32f4xx_syscfg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = stm32f4xx_syscfg_reset;
+}
+
+static const TypeInfo stm32f4xx_syscfg_info = {
+    .name          = TYPE_STM32F4XX_SYSCFG,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F4xxSyscfgState),
+    .instance_init = stm32f4xx_syscfg_init,
+    .class_init    = stm32f4xx_syscfg_class_init,
+};
+
+static void stm32f4xx_syscfg_register_types(void)
+{
+    type_register_static(&stm32f4xx_syscfg_info);
+}
+
+type_init(stm32f4xx_syscfg_register_types)
diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h
new file mode 100644
index 0000000000..790f60746f
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_syscfg.h
@@ -0,0 +1,62 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_STM_SYSCFG_H
+#define HW_STM_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define SYSCFG_MEMRMP  0x00
+#define SYSCFG_PMC     0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_CMPCR   0x20
+
+#define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg"
+#define STM32F4XX_SYSCFG(obj) \
+    OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG)
+
+typedef struct {
+    /* <private> */
+    SysBusDevice parent_obj;
+
+    /* <public> */
+    MemoryRegion mmio;
+
+    uint32_t syscfg_memrmp;
+    uint32_t syscfg_pmc;
+    uint32_t syscfg_exticr1;
+    uint32_t syscfg_exticr2;
+    uint32_t syscfg_exticr3;
+    uint32_t syscfg_exticr4;
+    uint32_t syscfg_cmpcr;
+
+    qemu_irq irq;
+    qemu_irq gpio_out[16];
+} STM32F4xxSyscfgState;
+
+#endif
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device
  2019-04-29  5:32 ` [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device Alistair Francis
@ 2019-04-29  5:32   ` Alistair Francis
  2019-04-30 15:44   ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 default-configs/arm-softmmu.mak    |   1 +
 hw/misc/Kconfig                    |   3 +
 hw/misc/Makefile.objs              |   1 +
 hw/misc/stm32f4xx_syscfg.c         | 275 +++++++++++++++++++++++++++++
 include/hw/misc/stm32f4xx_syscfg.h |  62 +++++++
 5 files changed, 342 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_syscfg.c
 create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 613d19a06d..c5cfdb857d 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -96,6 +96,7 @@ CONFIG_STM32F2XX_SYSCFG=y
 CONFIG_STM32F2XX_ADC=y
 CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
+CONFIG_STM32F4XX_SYSCFG=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 5f67d0d6d9..c6ff39aeeb 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -80,6 +80,9 @@ config IMX
 config STM32F2XX_SYSCFG
     bool
 
+config STM32F4XX_SYSCFG
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index c71e07ae35..1413b1f232 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -57,6 +57,7 @@ obj-$(CONFIG_SLAVIO) += slavio_misc.o
 obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_syscfg.c b/hw/misc/stm32f4xx_syscfg.c
new file mode 100644
index 0000000000..c0aaeeaf6c
--- /dev/null
+++ b/hw/misc/stm32f4xx_syscfg.c
@@ -0,0 +1,275 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "hw/misc/stm32f4xx_syscfg.h"
+
+#ifndef STM_SYSCFG_ERR_DEBUG
+#define STM_SYSCFG_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (STM_SYSCFG_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0)
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+static void stm32f4xx_syscfg_reset(DeviceState *dev)
+{
+    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev);
+
+    s->syscfg_memrmp = 0x00000000;
+    s->syscfg_pmc = 0x00000000;
+    s->syscfg_exticr1 = 0x00000000;
+    s->syscfg_exticr2 = 0x00000000;
+    s->syscfg_exticr3 = 0x00000000;
+    s->syscfg_exticr4 = 0x00000000;
+    s->syscfg_cmpcr = 0x00000000;
+}
+
+static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level)
+{
+    STM32F4xxSyscfgState *s = opaque;
+    uint8_t config;
+
+    DB_PRINT("Interupt: GPIO: %d, Line: %d; Level: %d\n", irq / 16,
+             irq % 16, level);
+
+    config = irq / 16;
+
+    switch (irq % 16) {
+    case 0:
+        if ((s->syscfg_exticr1 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[0], level);
+            DB_PRINT("Pulse EXTI: 0\n");
+        }
+        break;
+    case 1:
+        if (((s->syscfg_exticr1 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[1], level);
+            DB_PRINT("Pulse EXTI: 1\n");
+        }
+        break;
+    case 2:
+        if (((s->syscfg_exticr1 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[2], level);
+            DB_PRINT("Pulse EXTI: 2\n");
+        }
+        break;
+    case 3:
+        if (((s->syscfg_exticr1 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[3], level);
+            DB_PRINT("Pulse EXTI: 3\n");
+        }
+        break;
+    case 4:
+        if ((s->syscfg_exticr2 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[4], level);
+            DB_PRINT("Pulse EXTI: 4\n");
+        }
+        break;
+    case 5:
+        if (((s->syscfg_exticr2 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[5], level);
+            DB_PRINT("Pulse EXTI: 5\n");
+        }
+        break;
+    case 6:
+        if (((s->syscfg_exticr2 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[6], level);
+            DB_PRINT("Pulse EXTI: 6\n");
+        }
+        break;
+    case 7:
+        if (((s->syscfg_exticr2 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[7], level);
+            DB_PRINT("Pulse EXTI: 7\n");
+        }
+        break;
+    case 8:
+        if ((s->syscfg_exticr3 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[8], level);
+            DB_PRINT("Pulse EXTI: 8\n");
+        }
+        break;
+    case 9:
+        if (((s->syscfg_exticr3 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[9], level);
+            DB_PRINT("Pulse EXTI: 9\n");
+        }
+        break;
+    case 10:
+        if (((s->syscfg_exticr3 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[10], level);
+            DB_PRINT("Pulse EXTI: 10\n");
+        }
+        break;
+    case 11:
+        if (((s->syscfg_exticr3 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[11], level);
+            DB_PRINT("Pulse EXTI: 11\n");
+        }
+        break;
+    case 12:
+        if ((s->syscfg_exticr4 & 0xF) == config) {
+            qemu_set_irq(s->gpio_out[12], level);
+            DB_PRINT("Pulse EXTI: 12\n");
+        }
+        break;
+    case 13:
+        if (((s->syscfg_exticr4 & 0xF0) >> 4) == config) {
+            qemu_set_irq(s->gpio_out[13], level);
+            DB_PRINT("Pulse EXTI: 13\n");
+        }
+        break;
+    case 14:
+        if (((s->syscfg_exticr4 & 0xF00) >> 8) == config) {
+            qemu_set_irq(s->gpio_out[14], level);
+            DB_PRINT("Pulse EXTI: 14\n");
+        }
+        break;
+    case 15:
+        if (((s->syscfg_exticr4 & 0xF000) >> 12) == config) {
+            qemu_set_irq(s->gpio_out[15], level);
+            DB_PRINT("Pulse EXTI: 15\n");
+        }
+        break;
+    }
+}
+
+static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    STM32F4xxSyscfgState *s = opaque;
+
+    DB_PRINT("0x%"HWADDR_PRIx"\n", addr);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        return s->syscfg_memrmp;
+    case SYSCFG_PMC:
+        return s->syscfg_pmc;
+    case SYSCFG_EXTICR1:
+        return s->syscfg_exticr1;
+    case SYSCFG_EXTICR2:
+        return s->syscfg_exticr2;
+    case SYSCFG_EXTICR3:
+        return s->syscfg_exticr3;
+    case SYSCFG_EXTICR4:
+        return s->syscfg_exticr4;
+    case SYSCFG_CMPCR:
+        return s->syscfg_cmpcr;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+        return 0;
+    }
+
+    return 0;
+}
+
+static void stm32f4xx_syscfg_write(void *opaque, hwaddr addr,
+                       uint64_t val64, unsigned int size)
+{
+    STM32F4xxSyscfgState *s = opaque;
+    uint32_t value = val64;
+
+    DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr);
+
+    switch (addr) {
+    case SYSCFG_MEMRMP:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Changeing the memory mapping isn't supported " \
+                      "in QEMU\n", __func__);
+        return;
+    case SYSCFG_PMC:
+        qemu_log_mask(LOG_UNIMP,
+                      "%s: Changeing the memory mapping isn't supported " \
+                      "in QEMU\n", __func__);
+        return;
+    case SYSCFG_EXTICR1:
+        s->syscfg_exticr1 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR2:
+        s->syscfg_exticr2 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR3:
+        s->syscfg_exticr3 = (value & 0xFFFF);
+        return;
+    case SYSCFG_EXTICR4:
+        s->syscfg_exticr4 = (value & 0xFFFF);
+        return;
+    case SYSCFG_CMPCR:
+        s->syscfg_cmpcr = value;
+        return;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+    }
+}
+
+static const MemoryRegionOps stm32f4xx_syscfg_ops = {
+    .read = stm32f4xx_syscfg_read,
+    .write = stm32f4xx_syscfg_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void stm32f4xx_syscfg_init(Object *obj)
+{
+    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(obj);
+
+    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+    memory_region_init_io(&s->mmio, obj, &stm32f4xx_syscfg_ops, s,
+                          TYPE_STM32F4XX_SYSCFG, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_syscfg_set_irq, 16 * 9);
+    qdev_init_gpio_out(DEVICE(obj), s->gpio_out, 16);
+}
+
+static void stm32f4xx_syscfg_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = stm32f4xx_syscfg_reset;
+}
+
+static const TypeInfo stm32f4xx_syscfg_info = {
+    .name          = TYPE_STM32F4XX_SYSCFG,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F4xxSyscfgState),
+    .instance_init = stm32f4xx_syscfg_init,
+    .class_init    = stm32f4xx_syscfg_class_init,
+};
+
+static void stm32f4xx_syscfg_register_types(void)
+{
+    type_register_static(&stm32f4xx_syscfg_info);
+}
+
+type_init(stm32f4xx_syscfg_register_types)
diff --git a/include/hw/misc/stm32f4xx_syscfg.h b/include/hw/misc/stm32f4xx_syscfg.h
new file mode 100644
index 0000000000..790f60746f
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_syscfg.h
@@ -0,0 +1,62 @@
+/*
+ * STM32F4xx SYSCFG
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_STM_SYSCFG_H
+#define HW_STM_SYSCFG_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define SYSCFG_MEMRMP  0x00
+#define SYSCFG_PMC     0x04
+#define SYSCFG_EXTICR1 0x08
+#define SYSCFG_EXTICR2 0x0C
+#define SYSCFG_EXTICR3 0x10
+#define SYSCFG_EXTICR4 0x14
+#define SYSCFG_CMPCR   0x20
+
+#define TYPE_STM32F4XX_SYSCFG "stm32f4xx-syscfg"
+#define STM32F4XX_SYSCFG(obj) \
+    OBJECT_CHECK(STM32F4xxSyscfgState, (obj), TYPE_STM32F4XX_SYSCFG)
+
+typedef struct {
+    /* <private> */
+    SysBusDevice parent_obj;
+
+    /* <public> */
+    MemoryRegion mmio;
+
+    uint32_t syscfg_memrmp;
+    uint32_t syscfg_pmc;
+    uint32_t syscfg_exticr1;
+    uint32_t syscfg_exticr2;
+    uint32_t syscfg_exticr3;
+    uint32_t syscfg_exticr4;
+    uint32_t syscfg_cmpcr;
+
+    qemu_irq irq;
+    qemu_irq gpio_out[16];
+} STM32F4xxSyscfgState;
+
+#endif
-- 
2.21.0



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

* [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
       [not found] <cover.1556515687.git.alistair@alistair23.me>
                   ` (2 preceding siblings ...)
  2019-04-29  5:32 ` [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device Alistair Francis
@ 2019-04-29  5:33 ` Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
  2019-04-30 15:48   ` Peter Maydell
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2 Alistair Francis
  5 siblings, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 default-configs/arm-softmmu.mak  |   1 +
 hw/misc/Kconfig                  |   3 +
 hw/misc/Makefile.objs            |   1 +
 hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
 include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
 5 files changed, 237 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_exti.c
 create mode 100644 include/hw/misc/stm32f4xx_exti.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index c5cfdb857d..8eb57de211 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -97,6 +97,7 @@ CONFIG_STM32F2XX_ADC=y
 CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
 CONFIG_STM32F4XX_SYSCFG=y
+CONFIG_STM32F4XX_EXTI=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index c6ff39aeeb..3748b5f11a 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -83,6 +83,9 @@ config STM32F2XX_SYSCFG
 config STM32F4XX_SYSCFG
     bool
 
+config STM32F4XX_EXTI
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 1413b1f232..74c7ca6c05 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -58,6 +58,7 @@ obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_exti.c b/hw/misc/stm32f4xx_exti.c
new file mode 100644
index 0000000000..b31f06cdca
--- /dev/null
+++ b/hw/misc/stm32f4xx_exti.c
@@ -0,0 +1,175 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "hw/misc/stm32f4xx_exti.h"
+
+#ifndef STM_EXTI_ERR_DEBUG
+#define STM_EXTI_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (STM_EXTI_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0)
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+#define NUM_GPIO_EVENT_IN_LINES 16
+#define NUM_INTERRUPT_OUT_LINES 16
+
+static void stm32f4xx_exti_reset(DeviceState *dev)
+{
+    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
+
+    s->exti_imr = 0x00000000;
+    s->exti_emr = 0x00000000;
+    s->exti_rtsr = 0x00000000;
+    s->exti_ftsr = 0x00000000;
+    s->exti_swier = 0x00000000;
+    s->exti_pr = 0x00000000;
+}
+
+static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
+{
+    STM32F4xxExtiState *s = opaque;
+
+    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
+
+    if (level) {
+        qemu_irq_pulse(s->irq[irq]);
+        s->exti_pr |= 1 << irq;
+    }
+}
+
+static uint64_t stm32f4xx_exti_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    STM32F4xxExtiState *s = opaque;
+
+    DB_PRINT("0x%x\n", (uint) addr);
+
+    switch (addr) {
+    case EXTI_IMR:
+        return s->exti_imr;
+    case EXTI_EMR:
+        return s->exti_emr;
+    case EXTI_RTSR:
+        return s->exti_rtsr;
+    case EXTI_FTSR:
+        return s->exti_ftsr;
+    case EXTI_SWIER:
+        return s->exti_swier;
+    case EXTI_PR:
+        return s->exti_pr;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32F4XX_exti_read: Bad offset %x\n", (int)addr);
+        return 0;
+    }
+    return 0;
+}
+
+static void stm32f4xx_exti_write(void *opaque, hwaddr addr,
+                       uint64_t val64, unsigned int size)
+{
+    STM32F4xxExtiState *s = opaque;
+    uint32_t value = (uint32_t) val64;
+
+    DB_PRINT("0x%x, 0x%x\n", value, (uint) addr);
+
+    switch (addr) {
+    case EXTI_IMR:
+        s->exti_imr = value;
+        return;
+    case EXTI_EMR:
+        s->exti_emr = value;
+        return;
+    case EXTI_RTSR:
+        s->exti_rtsr = value;
+        return;
+    case EXTI_FTSR:
+        s->exti_ftsr = value;
+        return;
+    case EXTI_SWIER:
+        s->exti_swier = value;
+        return;
+    case EXTI_PR:
+        /* This bit is cleared by writing a 1 to it */
+        s->exti_pr &= ~value;
+        return;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32F4XX_exti_write: Bad offset %x\n", (int)addr);
+    }
+}
+
+static const MemoryRegionOps stm32f4xx_exti_ops = {
+    .read = stm32f4xx_exti_read,
+    .write = stm32f4xx_exti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void stm32f4xx_exti_init(Object *obj)
+{
+    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
+    int i;
+
+    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);
+    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
+    }
+
+    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
+                          TYPE_STM32F4XX_EXTI, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
+                      NUM_GPIO_EVENT_IN_LINES);
+}
+
+static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = stm32f4xx_exti_reset;
+}
+
+static const TypeInfo stm32f4xx_exti_info = {
+    .name          = TYPE_STM32F4XX_EXTI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F4xxExtiState),
+    .instance_init = stm32f4xx_exti_init,
+    .class_init    = stm32f4xx_exti_class_init,
+};
+
+static void stm32f4xx_exti_register_types(void)
+{
+    type_register_static(&stm32f4xx_exti_info);
+}
+
+type_init(stm32f4xx_exti_register_types)
diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h
new file mode 100644
index 0000000000..a9a4c86ef7
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_exti.h
@@ -0,0 +1,57 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_STM_EXTI_H
+#define HW_STM_EXTI_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define EXTI_IMR   0x00
+#define EXTI_EMR   0x04
+#define EXTI_RTSR  0x08
+#define EXTI_FTSR  0x0C
+#define EXTI_SWIER 0x10
+#define EXTI_PR    0x14
+
+#define TYPE_STM32F4XX_EXTI "stm32f4xx-exti"
+#define STM32F4XX_EXTI(obj) \
+    OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    uint32_t exti_imr;
+    uint32_t exti_emr;
+    uint32_t exti_rtsr;
+    uint32_t exti_ftsr;
+    uint32_t exti_swier;
+    uint32_t exti_pr;
+
+    qemu_irq *irq;
+} STM32F4xxExtiState;
+
+#endif
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device Alistair Francis
@ 2019-04-29  5:33   ` Alistair Francis
  2019-04-30 15:48   ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 default-configs/arm-softmmu.mak  |   1 +
 hw/misc/Kconfig                  |   3 +
 hw/misc/Makefile.objs            |   1 +
 hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
 include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
 5 files changed, 237 insertions(+)
 create mode 100644 hw/misc/stm32f4xx_exti.c
 create mode 100644 include/hw/misc/stm32f4xx_exti.h

diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index c5cfdb857d..8eb57de211 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -97,6 +97,7 @@ CONFIG_STM32F2XX_ADC=y
 CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
 CONFIG_STM32F4XX_SYSCFG=y
+CONFIG_STM32F4XX_EXTI=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index c6ff39aeeb..3748b5f11a 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -83,6 +83,9 @@ config STM32F2XX_SYSCFG
 config STM32F4XX_SYSCFG
     bool
 
+config STM32F4XX_EXTI
+    bool
+
 config MIPS_ITU
     bool
 
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
index 1413b1f232..74c7ca6c05 100644
--- a/hw/misc/Makefile.objs
+++ b/hw/misc/Makefile.objs
@@ -58,6 +58,7 @@ obj-$(CONFIG_ZYNQ) += zynq_slcr.o
 obj-$(CONFIG_ZYNQ) += zynq-xadc.o
 obj-$(CONFIG_STM32F2XX_SYSCFG) += stm32f2xx_syscfg.o
 obj-$(CONFIG_STM32F4XX_SYSCFG) += stm32f4xx_syscfg.o
+obj-$(CONFIG_STM32F4XX_EXTI) += stm32f4xx_exti.o
 obj-$(CONFIG_MIPS_CPS) += mips_cmgcr.o
 obj-$(CONFIG_MIPS_CPS) += mips_cpc.o
 obj-$(CONFIG_MIPS_ITU) += mips_itu.o
diff --git a/hw/misc/stm32f4xx_exti.c b/hw/misc/stm32f4xx_exti.c
new file mode 100644
index 0000000000..b31f06cdca
--- /dev/null
+++ b/hw/misc/stm32f4xx_exti.c
@@ -0,0 +1,175 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "qemu/log.h"
+#include "hw/misc/stm32f4xx_exti.h"
+
+#ifndef STM_EXTI_ERR_DEBUG
+#define STM_EXTI_ERR_DEBUG 0
+#endif
+
+#define DB_PRINT_L(lvl, fmt, args...) do { \
+    if (STM_EXTI_ERR_DEBUG >= lvl) { \
+        qemu_log("%s: " fmt, __func__, ## args); \
+    } \
+} while (0)
+
+#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
+
+#define NUM_GPIO_EVENT_IN_LINES 16
+#define NUM_INTERRUPT_OUT_LINES 16
+
+static void stm32f4xx_exti_reset(DeviceState *dev)
+{
+    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
+
+    s->exti_imr = 0x00000000;
+    s->exti_emr = 0x00000000;
+    s->exti_rtsr = 0x00000000;
+    s->exti_ftsr = 0x00000000;
+    s->exti_swier = 0x00000000;
+    s->exti_pr = 0x00000000;
+}
+
+static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
+{
+    STM32F4xxExtiState *s = opaque;
+
+    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
+
+    if (level) {
+        qemu_irq_pulse(s->irq[irq]);
+        s->exti_pr |= 1 << irq;
+    }
+}
+
+static uint64_t stm32f4xx_exti_read(void *opaque, hwaddr addr,
+                                     unsigned int size)
+{
+    STM32F4xxExtiState *s = opaque;
+
+    DB_PRINT("0x%x\n", (uint) addr);
+
+    switch (addr) {
+    case EXTI_IMR:
+        return s->exti_imr;
+    case EXTI_EMR:
+        return s->exti_emr;
+    case EXTI_RTSR:
+        return s->exti_rtsr;
+    case EXTI_FTSR:
+        return s->exti_ftsr;
+    case EXTI_SWIER:
+        return s->exti_swier;
+    case EXTI_PR:
+        return s->exti_pr;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32F4XX_exti_read: Bad offset %x\n", (int)addr);
+        return 0;
+    }
+    return 0;
+}
+
+static void stm32f4xx_exti_write(void *opaque, hwaddr addr,
+                       uint64_t val64, unsigned int size)
+{
+    STM32F4xxExtiState *s = opaque;
+    uint32_t value = (uint32_t) val64;
+
+    DB_PRINT("0x%x, 0x%x\n", value, (uint) addr);
+
+    switch (addr) {
+    case EXTI_IMR:
+        s->exti_imr = value;
+        return;
+    case EXTI_EMR:
+        s->exti_emr = value;
+        return;
+    case EXTI_RTSR:
+        s->exti_rtsr = value;
+        return;
+    case EXTI_FTSR:
+        s->exti_ftsr = value;
+        return;
+    case EXTI_SWIER:
+        s->exti_swier = value;
+        return;
+    case EXTI_PR:
+        /* This bit is cleared by writing a 1 to it */
+        s->exti_pr &= ~value;
+        return;
+    default:
+        qemu_log_mask(LOG_GUEST_ERROR,
+                      "STM32F4XX_exti_write: Bad offset %x\n", (int)addr);
+    }
+}
+
+static const MemoryRegionOps stm32f4xx_exti_ops = {
+    .read = stm32f4xx_exti_read,
+    .write = stm32f4xx_exti_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void stm32f4xx_exti_init(Object *obj)
+{
+    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
+    int i;
+
+    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);
+    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
+    }
+
+    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
+                          TYPE_STM32F4XX_EXTI, 0x400);
+    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
+                      NUM_GPIO_EVENT_IN_LINES);
+}
+
+static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = stm32f4xx_exti_reset;
+}
+
+static const TypeInfo stm32f4xx_exti_info = {
+    .name          = TYPE_STM32F4XX_EXTI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F4xxExtiState),
+    .instance_init = stm32f4xx_exti_init,
+    .class_init    = stm32f4xx_exti_class_init,
+};
+
+static void stm32f4xx_exti_register_types(void)
+{
+    type_register_static(&stm32f4xx_exti_info);
+}
+
+type_init(stm32f4xx_exti_register_types)
diff --git a/include/hw/misc/stm32f4xx_exti.h b/include/hw/misc/stm32f4xx_exti.h
new file mode 100644
index 0000000000..a9a4c86ef7
--- /dev/null
+++ b/include/hw/misc/stm32f4xx_exti.h
@@ -0,0 +1,57 @@
+/*
+ * STM32F4XX EXTI
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_STM_EXTI_H
+#define HW_STM_EXTI_H
+
+#include "hw/sysbus.h"
+#include "hw/hw.h"
+
+#define EXTI_IMR   0x00
+#define EXTI_EMR   0x04
+#define EXTI_RTSR  0x08
+#define EXTI_FTSR  0x0C
+#define EXTI_SWIER 0x10
+#define EXTI_PR    0x14
+
+#define TYPE_STM32F4XX_EXTI "stm32f4xx-exti"
+#define STM32F4XX_EXTI(obj) \
+    OBJECT_CHECK(STM32F4xxExtiState, (obj), TYPE_STM32F4XX_EXTI)
+
+typedef struct {
+    SysBusDevice parent_obj;
+
+    MemoryRegion mmio;
+
+    uint32_t exti_imr;
+    uint32_t exti_emr;
+    uint32_t exti_rtsr;
+    uint32_t exti_ftsr;
+    uint32_t exti_swier;
+    uint32_t exti_pr;
+
+    qemu_irq *irq;
+} STM32F4xxExtiState;
+
+#endif
-- 
2.21.0



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

* [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
       [not found] <cover.1556515687.git.alistair@alistair23.me>
                   ` (3 preceding siblings ...)
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device Alistair Francis
@ 2019-04-29  5:33 ` Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
                     ` (3 more replies)
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2 Alistair Francis
  5 siblings, 4 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 MAINTAINERS                     |   8 +
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Kconfig                  |   3 +
 hw/arm/Makefile.objs            |   1 +
 hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
 include/hw/arm/stm32f405_soc.h  |  70 ++++++++
 6 files changed, 375 insertions(+)
 create mode 100644 hw/arm/stm32f405_soc.c
 create mode 100644 include/hw/arm/stm32f405_soc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index dabbfccf9c..c9772735cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -803,6 +803,14 @@ F: hw/adc/*
 F: hw/ssi/stm32f2xx_spi.c
 F: include/hw/*/stm32*.h
 
+STM32F405
+M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/arm/stm32f405_soc.c
+F: hw/misc/stm32f4xx_syscfg.c
+F: hw/misc/stm32f4xx_exti.c
+
 Netduino 2
 M: Alistair Francis <alistair@alistair23.me>
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 8eb57de211..e079f10624 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
 CONFIG_STM32F4XX_SYSCFG=y
 CONFIG_STM32F4XX_EXTI=y
+CONFIG_STM32F405_SOC=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d298fbdc89..3a98bce15a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -62,6 +62,9 @@ config RASPI
 config STM32F205_SOC
     bool
 
+config STM32F405_SOC
+    bool
+
 config XLNX_ZYNQMP_ARM
     bool
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index fa57c7c770..36c3ff54c3 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
 obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
+obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
 obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
new file mode 100644
index 0000000000..83adec51a2
--- /dev/null
+++ b/hw/arm/stm32f405_soc.c
@@ -0,0 +1,292 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/arm.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/misc/unimp.h"
+
+#define SYSCFG_ADD                     0x40013800
+static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
+                                       0x40004C00, 0x40005000, 0x40011400,
+                                       0x40007800, 0x40007C00 };
+/* At the moment only Timer 2 to 5 are modelled */
+static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
+                                       0x40000800, 0x40000C00 };
+#define ADC_ADDR                       0x40012000
+static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
+                                       0x40013400, 0x40015000, 0x40015400 };
+#define EXTI_ADDR                      0x40013C00
+
+#define SYSCFG_IRQ               71
+static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
+static const int timer_irq[] = { 28, 29, 30, 50 };
+#define ADC_IRQ 18
+static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
+static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
+                                 40, 40, 40, 40, 40} ;
+
+
+static void stm32f405_soc_initfn(Object *obj)
+{
+    STM32F405State *s = STM32F405_SOC(obj);
+    int i;
+
+    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
+                          TYPE_ARMV7M);
+
+    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
+                          TYPE_STM32F4XX_SYSCFG);
+
+    for (i = 0; i < STM_NUM_USARTS; i++) {
+        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
+                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
+    }
+
+    for (i = 0; i < STM_NUM_TIMERS; i++) {
+        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
+                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
+    }
+
+    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
+
+    for (i = 0; i < STM_NUM_ADCS; i++) {
+        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
+                              TYPE_STM32F2XX_ADC);
+    }
+
+    for (i = 0; i < STM_NUM_SPIS; i++) {
+        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
+                              TYPE_STM32F2XX_SPI);
+    }
+
+    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
+                          TYPE_STM32F4XX_EXTI);
+}
+
+static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+    STM32F405State *s = STM32F405_SOC(dev_soc);
+    DeviceState *dev, *armv7m;
+    SysBusDevice *busdev;
+    Error *err = NULL;
+    int i;
+
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
+
+    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
+                           &error_fatal);
+    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
+                             flash, 0, FLASH_SIZE);
+
+    memory_region_set_readonly(flash, true);
+    memory_region_set_readonly(flash_alias, true);
+
+    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
+    memory_region_add_subregion(system_memory, 0, flash_alias);
+
+    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
+                           &error_fatal);
+    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
+
+    armv7m = DEVICE(&s->armv7m);
+    qdev_prop_set_uint32(armv7m, "num-irq", 96);
+    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
+    qdev_prop_set_bit(armv7m, "enable-bitband", true);
+    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
+                                     "memory", &error_abort);
+    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    /* System configuration controller */
+    dev = DEVICE(&s->syscfg);
+    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
+
+    /* Attach UART (uses USART registers) and USART controllers */
+    for (i = 0; i < STM_NUM_USARTS; i++) {
+        dev = DEVICE(&(s->usart[i]));
+        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
+        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, usart_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
+    }
+
+    /* Timer 2 to 5 */
+    for (i = 0; i < STM_NUM_TIMERS; i++) {
+        dev = DEVICE(&(s->timer[i]));
+        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
+        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, timer_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
+    }
+
+    /* ADC device, the IRQs are ORed together */
+    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
+                            "num-lines", &err);
+    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
+                          qdev_get_gpio_in(armv7m, ADC_IRQ));
+
+    dev = DEVICE(&(s->adc[i]));
+    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, ADC_ADDR);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
+
+    /* SPI devices */
+    for (i = 0; i < STM_NUM_SPIS; i++) {
+        dev = DEVICE(&(s->spi[i]));
+        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, spi_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
+    }
+
+    /* EXTI device */
+    dev = DEVICE(&s->exti);
+    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
+    for (i = 0; i < 16; i++) {
+        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
+    }
+    for (i = 0; i < 16; i++) {
+        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
+    }
+
+    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
+    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
+    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
+    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
+    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
+    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
+    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
+    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
+    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
+    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
+    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
+    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
+    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
+    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
+    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
+    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
+    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
+    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
+    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
+    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
+    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
+    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
+    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
+    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
+    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
+    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
+    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
+    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
+    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
+    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
+    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
+    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
+    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
+    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
+    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
+    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
+    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
+    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
+    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
+    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
+    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
+    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
+    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
+}
+
+static Property stm32f405_soc_properties[] = {
+    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = stm32f405_soc_realize;
+    dc->props = stm32f405_soc_properties;
+}
+
+static const TypeInfo stm32f405_soc_info = {
+    .name          = TYPE_STM32F405_SOC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F405State),
+    .instance_init = stm32f405_soc_initfn,
+    .class_init    = stm32f405_soc_class_init,
+};
+
+static void stm32f405_soc_types(void)
+{
+    type_register_static(&stm32f405_soc_info);
+}
+
+type_init(stm32f405_soc_types)
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
new file mode 100644
index 0000000000..f0aec53d32
--- /dev/null
+++ b/include/hw/arm/stm32f405_soc.h
@@ -0,0 +1,70 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_STM32F405_SOC_H
+#define HW_ARM_STM32F405_SOC_H
+
+#include "hw/misc/stm32f4xx_syscfg.h"
+#include "hw/timer/stm32f2xx_timer.h"
+#include "hw/char/stm32f2xx_usart.h"
+#include "hw/adc/stm32f2xx_adc.h"
+#include "hw/misc/stm32f4xx_exti.h"
+#include "hw/or-irq.h"
+#include "hw/ssi/stm32f2xx_spi.h"
+#include "hw/arm/armv7m.h"
+
+#define TYPE_STM32F405_SOC "stm32f405-soc"
+#define STM32F405_SOC(obj) \
+    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
+
+#define STM_NUM_USARTS 7
+#define STM_NUM_TIMERS 4
+#define STM_NUM_ADCS 6
+#define STM_NUM_SPIS 6
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (1024 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (192 * 1024)
+
+typedef struct STM32F405State {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    char *cpu_type;
+
+    ARMv7MState armv7m;
+
+    STM32F4xxSyscfgState syscfg;
+    STM32F4xxExtiState exti;
+    STM32F2XXUsartState usart[STM_NUM_USARTS];
+    STM32F2XXTimerState timer[STM_NUM_TIMERS];
+    STM32F2XXADCState adc[STM_NUM_ADCS];
+    STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+    qemu_or_irq *adc_irqs;
+} STM32F405State;
+
+#endif
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
@ 2019-04-29  5:33   ` Alistair Francis
  2019-04-29 12:38   ` KONRAD Frederic
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 MAINTAINERS                     |   8 +
 default-configs/arm-softmmu.mak |   1 +
 hw/arm/Kconfig                  |   3 +
 hw/arm/Makefile.objs            |   1 +
 hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
 include/hw/arm/stm32f405_soc.h  |  70 ++++++++
 6 files changed, 375 insertions(+)
 create mode 100644 hw/arm/stm32f405_soc.c
 create mode 100644 include/hw/arm/stm32f405_soc.h

diff --git a/MAINTAINERS b/MAINTAINERS
index dabbfccf9c..c9772735cf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -803,6 +803,14 @@ F: hw/adc/*
 F: hw/ssi/stm32f2xx_spi.c
 F: include/hw/*/stm32*.h
 
+STM32F405
+M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/arm/stm32f405_soc.c
+F: hw/misc/stm32f4xx_syscfg.c
+F: hw/misc/stm32f4xx_exti.c
+
 Netduino 2
 M: Alistair Francis <alistair@alistair23.me>
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index 8eb57de211..e079f10624 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
 CONFIG_STM32F205_SOC=y
 CONFIG_STM32F4XX_SYSCFG=y
 CONFIG_STM32F4XX_EXTI=y
+CONFIG_STM32F405_SOC=y
 CONFIG_NRF51_SOC=y
 
 CONFIG_CMSDK_APB_TIMER=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index d298fbdc89..3a98bce15a 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -62,6 +62,9 @@ config RASPI
 config STM32F205_SOC
     bool
 
+config STM32F405_SOC
+    bool
+
 config XLNX_ZYNQMP_ARM
     bool
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index fa57c7c770..36c3ff54c3 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
 obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
 obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
 obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
+obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
 obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
 obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
 obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
new file mode 100644
index 0000000000..83adec51a2
--- /dev/null
+++ b/hw/arm/stm32f405_soc.c
@@ -0,0 +1,292 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu-common.h"
+#include "hw/arm/arm.h"
+#include "exec/address-spaces.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/misc/unimp.h"
+
+#define SYSCFG_ADD                     0x40013800
+static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
+                                       0x40004C00, 0x40005000, 0x40011400,
+                                       0x40007800, 0x40007C00 };
+/* At the moment only Timer 2 to 5 are modelled */
+static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
+                                       0x40000800, 0x40000C00 };
+#define ADC_ADDR                       0x40012000
+static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
+                                       0x40013400, 0x40015000, 0x40015400 };
+#define EXTI_ADDR                      0x40013C00
+
+#define SYSCFG_IRQ               71
+static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
+static const int timer_irq[] = { 28, 29, 30, 50 };
+#define ADC_IRQ 18
+static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
+static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
+                                 40, 40, 40, 40, 40} ;
+
+
+static void stm32f405_soc_initfn(Object *obj)
+{
+    STM32F405State *s = STM32F405_SOC(obj);
+    int i;
+
+    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
+                          TYPE_ARMV7M);
+
+    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
+                          TYPE_STM32F4XX_SYSCFG);
+
+    for (i = 0; i < STM_NUM_USARTS; i++) {
+        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
+                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
+    }
+
+    for (i = 0; i < STM_NUM_TIMERS; i++) {
+        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
+                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
+    }
+
+    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
+
+    for (i = 0; i < STM_NUM_ADCS; i++) {
+        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
+                              TYPE_STM32F2XX_ADC);
+    }
+
+    for (i = 0; i < STM_NUM_SPIS; i++) {
+        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
+                              TYPE_STM32F2XX_SPI);
+    }
+
+    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
+                          TYPE_STM32F4XX_EXTI);
+}
+
+static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
+{
+    STM32F405State *s = STM32F405_SOC(dev_soc);
+    DeviceState *dev, *armv7m;
+    SysBusDevice *busdev;
+    Error *err = NULL;
+    int i;
+
+    MemoryRegion *system_memory = get_system_memory();
+    MemoryRegion *sram = g_new(MemoryRegion, 1);
+    MemoryRegion *flash = g_new(MemoryRegion, 1);
+    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
+
+    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
+                           &error_fatal);
+    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
+                             flash, 0, FLASH_SIZE);
+
+    memory_region_set_readonly(flash, true);
+    memory_region_set_readonly(flash_alias, true);
+
+    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
+    memory_region_add_subregion(system_memory, 0, flash_alias);
+
+    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
+                           &error_fatal);
+    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
+
+    armv7m = DEVICE(&s->armv7m);
+    qdev_prop_set_uint32(armv7m, "num-irq", 96);
+    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
+    qdev_prop_set_bit(armv7m, "enable-bitband", true);
+    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
+                                     "memory", &error_abort);
+    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+
+    /* System configuration controller */
+    dev = DEVICE(&s->syscfg);
+    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
+    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
+
+    /* Attach UART (uses USART registers) and USART controllers */
+    for (i = 0; i < STM_NUM_USARTS; i++) {
+        dev = DEVICE(&(s->usart[i]));
+        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
+        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, usart_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
+    }
+
+    /* Timer 2 to 5 */
+    for (i = 0; i < STM_NUM_TIMERS; i++) {
+        dev = DEVICE(&(s->timer[i]));
+        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
+        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, timer_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
+    }
+
+    /* ADC device, the IRQs are ORed together */
+    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
+                            "num-lines", &err);
+    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
+                          qdev_get_gpio_in(armv7m, ADC_IRQ));
+
+    dev = DEVICE(&(s->adc[i]));
+    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, ADC_ADDR);
+    sysbus_connect_irq(busdev, 0,
+                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
+
+    /* SPI devices */
+    for (i = 0; i < STM_NUM_SPIS; i++) {
+        dev = DEVICE(&(s->spi[i]));
+        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
+        if (err != NULL) {
+            error_propagate(errp, err);
+            return;
+        }
+        busdev = SYS_BUS_DEVICE(dev);
+        sysbus_mmio_map(busdev, 0, spi_addr[i]);
+        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
+    }
+
+    /* EXTI device */
+    dev = DEVICE(&s->exti);
+    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
+    if (err != NULL) {
+        error_propagate(errp, err);
+        return;
+    }
+    busdev = SYS_BUS_DEVICE(dev);
+    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
+    for (i = 0; i < 16; i++) {
+        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
+    }
+    for (i = 0; i < 16; i++) {
+        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
+    }
+
+    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
+    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
+    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
+    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
+    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
+    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
+    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
+    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
+    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
+    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
+    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
+    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
+    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
+    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
+    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
+    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
+    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
+    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
+    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
+    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
+    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
+    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
+    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
+    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
+    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
+    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
+    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
+    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
+    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
+    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
+    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
+    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
+    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
+    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
+    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
+    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
+    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
+    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
+    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
+    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
+    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
+    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
+    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
+}
+
+static Property stm32f405_soc_properties[] = {
+    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->realize = stm32f405_soc_realize;
+    dc->props = stm32f405_soc_properties;
+}
+
+static const TypeInfo stm32f405_soc_info = {
+    .name          = TYPE_STM32F405_SOC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(STM32F405State),
+    .instance_init = stm32f405_soc_initfn,
+    .class_init    = stm32f405_soc_class_init,
+};
+
+static void stm32f405_soc_types(void)
+{
+    type_register_static(&stm32f405_soc_info);
+}
+
+type_init(stm32f405_soc_types)
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
new file mode 100644
index 0000000000..f0aec53d32
--- /dev/null
+++ b/include/hw/arm/stm32f405_soc.h
@@ -0,0 +1,70 @@
+/*
+ * STM32F405 SoC
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef HW_ARM_STM32F405_SOC_H
+#define HW_ARM_STM32F405_SOC_H
+
+#include "hw/misc/stm32f4xx_syscfg.h"
+#include "hw/timer/stm32f2xx_timer.h"
+#include "hw/char/stm32f2xx_usart.h"
+#include "hw/adc/stm32f2xx_adc.h"
+#include "hw/misc/stm32f4xx_exti.h"
+#include "hw/or-irq.h"
+#include "hw/ssi/stm32f2xx_spi.h"
+#include "hw/arm/armv7m.h"
+
+#define TYPE_STM32F405_SOC "stm32f405-soc"
+#define STM32F405_SOC(obj) \
+    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
+
+#define STM_NUM_USARTS 7
+#define STM_NUM_TIMERS 4
+#define STM_NUM_ADCS 6
+#define STM_NUM_SPIS 6
+
+#define FLASH_BASE_ADDRESS 0x08000000
+#define FLASH_SIZE (1024 * 1024)
+#define SRAM_BASE_ADDRESS 0x20000000
+#define SRAM_SIZE (192 * 1024)
+
+typedef struct STM32F405State {
+    /*< private >*/
+    SysBusDevice parent_obj;
+    /*< public >*/
+
+    char *cpu_type;
+
+    ARMv7MState armv7m;
+
+    STM32F4xxSyscfgState syscfg;
+    STM32F4xxExtiState exti;
+    STM32F2XXUsartState usart[STM_NUM_USARTS];
+    STM32F2XXTimerState timer[STM_NUM_TIMERS];
+    STM32F2XXADCState adc[STM_NUM_ADCS];
+    STM32F2XXSPIState spi[STM_NUM_SPIS];
+
+    qemu_or_irq *adc_irqs;
+} STM32F405State;
+
+#endif
-- 
2.21.0



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

* [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
       [not found] <cover.1556515687.git.alistair@alistair23.me>
                   ` (4 preceding siblings ...)
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
@ 2019-04-29  5:33 ` Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
  2019-04-30 16:01   ` Peter Maydell
  5 siblings, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 MAINTAINERS                     |  6 +++
 default-configs/arm-softmmu.mak |  1 +
 hw/arm/Kconfig                  |  3 ++
 hw/arm/Makefile.objs            |  1 +
 hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
 5 files changed, 88 insertions(+)
 create mode 100644 hw/arm/netduinoplus2.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c9772735cf..9b0af5a0b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -817,6 +817,12 @@ M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/arm/netduino2.c
 
+Netduino Plus 2
+M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/arm/netduinoplus2.c
+
 SmartFusion2
 M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index e079f10624..1e2c82f201 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -46,6 +46,7 @@ CONFIG_A15MPCORE=y
 
 CONFIG_ARM_V7M=y
 CONFIG_NETDUINO2=y
+CONFIG_NETDUINOPLUS2=y
 
 CONFIG_ARM_GIC=y
 CONFIG_ARM_TIMER=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3a98bce15a..13fc779308 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -26,6 +26,9 @@ config MUSICPAL
 config NETDUINO2
     bool
 
+config NETDUINOPLUS2
+    bool
+
 config NSERIES
     bool
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 36c3ff54c3..1f216f4d93 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -8,6 +8,7 @@ obj-$(CONFIG_INTEGRATOR) += integratorcp.o
 obj-$(CONFIG_MAINSTONE) += mainstone.o
 obj-$(CONFIG_MUSICPAL) += musicpal.o
 obj-$(CONFIG_NETDUINO2) += netduino2.o
+obj-$(CONFIG_NETDUINOPLUS2) += netduinoplus2.o
 obj-$(CONFIG_NSERIES) += nseries.o
 obj-$(CONFIG_OMAP) += omap_sx1.o palm.o
 obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
new file mode 100644
index 0000000000..1f585cf09f
--- /dev/null
+++ b/hw/arm/netduinoplus2.c
@@ -0,0 +1,77 @@
+/*
+ * Netduino Plus 2 Machine Model
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/arm/arm.h"
+
+typedef struct ARMV7MResetArgs {
+    ARMCPU *cpu;
+    uint32_t reset_sp;
+    uint32_t reset_pc;
+} ARMV7MResetArgs;
+
+static void armv7m_reset(void *opaque)
+{
+    ARMV7MResetArgs *args = opaque;
+
+    cpu_reset(CPU(args->cpu));
+
+    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
+    args->cpu->env.thumb = args->reset_pc & 1;
+    args->cpu->env.regs[15] = args->reset_pc & ~1;
+}
+
+static void netduinoplus2_init(MachineState *machine)
+{
+    DeviceState *dev;
+    ARMV7MResetArgs reset_args;
+    uint64_t entry;
+
+    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
+    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
+    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
+
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
+                       FLASH_SIZE, &entry);
+
+    reset_args = (ARMV7MResetArgs) {
+        .cpu = ARM_CPU(first_cpu),
+        .reset_pc = entry,
+        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
+    };
+    qemu_register_reset(armv7m_reset,
+                        g_memdup(&reset_args, sizeof(reset_args)));
+}
+
+static void netduinoplus2_machine_init(MachineClass *mc)
+{
+    mc->desc = "Netduino Plus 2 Machine";
+    mc->init = netduinoplus2_init;
+}
+
+DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
-- 
2.21.0

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

* [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2 Alistair Francis
@ 2019-04-29  5:33   ` Alistair Francis
  2019-04-30 16:01   ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29  5:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: alistair23

Signed-off-by: Alistair Francis <alistair@alistair23.me>
---
 MAINTAINERS                     |  6 +++
 default-configs/arm-softmmu.mak |  1 +
 hw/arm/Kconfig                  |  3 ++
 hw/arm/Makefile.objs            |  1 +
 hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
 5 files changed, 88 insertions(+)
 create mode 100644 hw/arm/netduinoplus2.c

diff --git a/MAINTAINERS b/MAINTAINERS
index c9772735cf..9b0af5a0b0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -817,6 +817,12 @@ M: Peter Maydell <peter.maydell@linaro.org>
 S: Maintained
 F: hw/arm/netduino2.c
 
+Netduino Plus 2
+M: Alistair Francis <alistair@alistair23.me>
+M: Peter Maydell <peter.maydell@linaro.org>
+S: Maintained
+F: hw/arm/netduinoplus2.c
+
 SmartFusion2
 M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
 M: Peter Maydell <peter.maydell@linaro.org>
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
index e079f10624..1e2c82f201 100644
--- a/default-configs/arm-softmmu.mak
+++ b/default-configs/arm-softmmu.mak
@@ -46,6 +46,7 @@ CONFIG_A15MPCORE=y
 
 CONFIG_ARM_V7M=y
 CONFIG_NETDUINO2=y
+CONFIG_NETDUINOPLUS2=y
 
 CONFIG_ARM_GIC=y
 CONFIG_ARM_TIMER=y
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 3a98bce15a..13fc779308 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -26,6 +26,9 @@ config MUSICPAL
 config NETDUINO2
     bool
 
+config NETDUINOPLUS2
+    bool
+
 config NSERIES
     bool
 
diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
index 36c3ff54c3..1f216f4d93 100644
--- a/hw/arm/Makefile.objs
+++ b/hw/arm/Makefile.objs
@@ -8,6 +8,7 @@ obj-$(CONFIG_INTEGRATOR) += integratorcp.o
 obj-$(CONFIG_MAINSTONE) += mainstone.o
 obj-$(CONFIG_MUSICPAL) += musicpal.o
 obj-$(CONFIG_NETDUINO2) += netduino2.o
+obj-$(CONFIG_NETDUINOPLUS2) += netduinoplus2.o
 obj-$(CONFIG_NSERIES) += nseries.o
 obj-$(CONFIG_OMAP) += omap_sx1.o palm.o
 obj-$(CONFIG_PXA2XX) += gumstix.o spitz.o tosa.o z2.o
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
new file mode 100644
index 0000000000..1f585cf09f
--- /dev/null
+++ b/hw/arm/netduinoplus2.c
@@ -0,0 +1,77 @@
+/*
+ * Netduino Plus 2 Machine Model
+ *
+ * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "qemu/error-report.h"
+#include "hw/arm/stm32f405_soc.h"
+#include "hw/arm/arm.h"
+
+typedef struct ARMV7MResetArgs {
+    ARMCPU *cpu;
+    uint32_t reset_sp;
+    uint32_t reset_pc;
+} ARMV7MResetArgs;
+
+static void armv7m_reset(void *opaque)
+{
+    ARMV7MResetArgs *args = opaque;
+
+    cpu_reset(CPU(args->cpu));
+
+    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
+    args->cpu->env.thumb = args->reset_pc & 1;
+    args->cpu->env.regs[15] = args->reset_pc & ~1;
+}
+
+static void netduinoplus2_init(MachineState *machine)
+{
+    DeviceState *dev;
+    ARMV7MResetArgs reset_args;
+    uint64_t entry;
+
+    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
+    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
+    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
+
+    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
+                       FLASH_SIZE, &entry);
+
+    reset_args = (ARMV7MResetArgs) {
+        .cpu = ARM_CPU(first_cpu),
+        .reset_pc = entry,
+        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
+    };
+    qemu_register_reset(armv7m_reset,
+                        g_memdup(&reset_args, sizeof(reset_args)));
+}
+
+static void netduinoplus2_machine_init(MachineClass *mc)
+{
+    mc->desc = "Netduino Plus 2 Machine";
+    mc->init = netduinoplus2_init;
+}
+
+DEFINE_MACHINE("netduinoplus2", netduinoplus2_machine_init)
-- 
2.21.0



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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
@ 2019-04-29 12:38   ` KONRAD Frederic
  2019-04-29 12:38     ` KONRAD Frederic
  2019-04-29 17:00     ` Alistair Francis
  2019-04-29 12:43   ` Philippe Mathieu-Daudé
  2019-04-30 15:59   ` Peter Maydell
  3 siblings, 2 replies; 51+ messages in thread
From: KONRAD Frederic @ 2019-04-29 12:38 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel; +Cc: alistair23

Hi Alistair,

Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>   MAINTAINERS                     |   8 +
>   default-configs/arm-softmmu.mak |   1 +
>   hw/arm/Kconfig                  |   3 +
>   hw/arm/Makefile.objs            |   1 +
>   hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>   include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>   6 files changed, 375 insertions(+)
>   create mode 100644 hw/arm/stm32f405_soc.c
>   create mode 100644 include/hw/arm/stm32f405_soc.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dabbfccf9c..c9772735cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -803,6 +803,14 @@ F: hw/adc/*
>   F: hw/ssi/stm32f2xx_spi.c
>   F: include/hw/*/stm32*.h
>   
> +STM32F405
> +M: Alistair Francis <alistair@alistair23.me>
> +M: Peter Maydell <peter.maydell@linaro.org>
> +S: Maintained
> +F: hw/arm/stm32f405_soc.c
> +F: hw/misc/stm32f4xx_syscfg.c
> +F: hw/misc/stm32f4xx_exti.c
> +
>   Netduino 2
>   M: Alistair Francis <alistair@alistair23.me>
>   M: Peter Maydell <peter.maydell@linaro.org>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 8eb57de211..e079f10624 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>   CONFIG_STM32F205_SOC=y
>   CONFIG_STM32F4XX_SYSCFG=y
>   CONFIG_STM32F4XX_EXTI=y
> +CONFIG_STM32F405_SOC=y

Why not using 4xx instead of 405 in this patch as well?

>   CONFIG_NRF51_SOC=y
>   
>   CONFIG_CMSDK_APB_TIMER=y
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index d298fbdc89..3a98bce15a 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -62,6 +62,9 @@ config RASPI
>   config STM32F205_SOC
>       bool
>   
> +config STM32F405_SOC
> +    bool
> +
>   config XLNX_ZYNQMP_ARM
>       bool
>   
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index fa57c7c770..36c3ff54c3 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>   obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>   obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>   obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>   obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>   obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>   obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> new file mode 100644
> index 0000000000..83adec51a2
> --- /dev/null
> +++ b/hw/arm/stm32f405_soc.c
> @@ -0,0 +1,292 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "hw/arm/arm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/arm/stm32f405_soc.h"
> +#include "hw/misc/unimp.h"
> +
> +#define SYSCFG_ADD                     0x40013800
> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> +                                       0x40004C00, 0x40005000, 0x40011400,
> +                                       0x40007800, 0x40007C00 };
> +/* At the moment only Timer 2 to 5 are modelled */
> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> +                                       0x40000800, 0x40000C00 };
> +#define ADC_ADDR                       0x40012000
> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> +                                       0x40013400, 0x40015000, 0x40015400 };
> +#define EXTI_ADDR                      0x40013C00
> +
> +#define SYSCFG_IRQ               71
> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> +static const int timer_irq[] = { 28, 29, 30, 50 };
> +#define ADC_IRQ 18
> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> +                                 40, 40, 40, 40, 40} ;
> +
> +
> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);
> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> +                                     "memory", &error_abort);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    /* System configuration controller */
> +    dev = DEVICE(&s->syscfg);
> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> +
> +    /* Attach UART (uses USART registers) and USART controllers */
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        dev = DEVICE(&(s->usart[i]));
> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> +    }
> +
> +    /* Timer 2 to 5 */
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        dev = DEVICE(&(s->timer[i]));
> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> +    }
> +
> +    /* ADC device, the IRQs are ORed together */
> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> +                            "num-lines", &err);
> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> +
> +    dev = DEVICE(&(s->adc[i]));
> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> +    sysbus_connect_irq(busdev, 0,
> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> +
> +    /* SPI devices */
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        dev = DEVICE(&(s->spi[i]));
> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> +    }
> +
> +    /* EXTI device */
> +    dev = DEVICE(&s->exti);
> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> +    for (i = 0; i < 16; i++) {
> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> +    }
> +    for (i = 0; i < 16; i++) {
> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> +    }
> +
> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> +}
> +
> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;
> +}
> +
> +static const TypeInfo stm32f405_soc_info = {
> +    .name          = TYPE_STM32F405_SOC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F405State),
> +    .instance_init = stm32f405_soc_initfn,
> +    .class_init    = stm32f405_soc_class_init,
> +};
> +
> +static void stm32f405_soc_types(void)
> +{
> +    type_register_static(&stm32f405_soc_info);
> +}
> +
> +type_init(stm32f405_soc_types)
> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> new file mode 100644
> index 0000000000..f0aec53d32
> --- /dev/null
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -0,0 +1,70 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_ARM_STM32F405_SOC_H
> +#define HW_ARM_STM32F405_SOC_H
> +
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +#include "hw/timer/stm32f2xx_timer.h"
> +#include "hw/char/stm32f2xx_usart.h"
> +#include "hw/adc/stm32f2xx_adc.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +#include "hw/or-irq.h"
> +#include "hw/ssi/stm32f2xx_spi.h"
> +#include "hw/arm/armv7m.h"
> +
> +#define TYPE_STM32F405_SOC "stm32f405-soc"
> +#define STM32F405_SOC(obj) \
> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> +
> +#define STM_NUM_USARTS 7
> +#define STM_NUM_TIMERS 4
> +#define STM_NUM_ADCS 6
> +#define STM_NUM_SPIS 6
> +
> +#define FLASH_BASE_ADDRESS 0x08000000
> +#define FLASH_SIZE (1024 * 1024)
> +#define SRAM_BASE_ADDRESS 0x20000000
> +#define SRAM_SIZE (192 * 1024)
> +
> +typedef struct STM32F405State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    char *cpu_type;
> +
> +    ARMv7MState armv7m;
> +
> +    STM32F4xxSyscfgState syscfg;
> +    STM32F4xxExtiState exti;
> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> +    STM32F2XXADCState adc[STM_NUM_ADCS];
> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> +
> +    qemu_or_irq *adc_irqs;
> +} STM32F405State;
> +
> +#endif
> 

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 12:38   ` KONRAD Frederic
@ 2019-04-29 12:38     ` KONRAD Frederic
  2019-04-29 17:00     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: KONRAD Frederic @ 2019-04-29 12:38 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel; +Cc: alistair23

Hi Alistair,

Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>   MAINTAINERS                     |   8 +
>   default-configs/arm-softmmu.mak |   1 +
>   hw/arm/Kconfig                  |   3 +
>   hw/arm/Makefile.objs            |   1 +
>   hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>   include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>   6 files changed, 375 insertions(+)
>   create mode 100644 hw/arm/stm32f405_soc.c
>   create mode 100644 include/hw/arm/stm32f405_soc.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dabbfccf9c..c9772735cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -803,6 +803,14 @@ F: hw/adc/*
>   F: hw/ssi/stm32f2xx_spi.c
>   F: include/hw/*/stm32*.h
>   
> +STM32F405
> +M: Alistair Francis <alistair@alistair23.me>
> +M: Peter Maydell <peter.maydell@linaro.org>
> +S: Maintained
> +F: hw/arm/stm32f405_soc.c
> +F: hw/misc/stm32f4xx_syscfg.c
> +F: hw/misc/stm32f4xx_exti.c
> +
>   Netduino 2
>   M: Alistair Francis <alistair@alistair23.me>
>   M: Peter Maydell <peter.maydell@linaro.org>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 8eb57de211..e079f10624 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>   CONFIG_STM32F205_SOC=y
>   CONFIG_STM32F4XX_SYSCFG=y
>   CONFIG_STM32F4XX_EXTI=y
> +CONFIG_STM32F405_SOC=y

Why not using 4xx instead of 405 in this patch as well?

>   CONFIG_NRF51_SOC=y
>   
>   CONFIG_CMSDK_APB_TIMER=y
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index d298fbdc89..3a98bce15a 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -62,6 +62,9 @@ config RASPI
>   config STM32F205_SOC
>       bool
>   
> +config STM32F405_SOC
> +    bool
> +
>   config XLNX_ZYNQMP_ARM
>       bool
>   
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index fa57c7c770..36c3ff54c3 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>   obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>   obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>   obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>   obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>   obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>   obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> new file mode 100644
> index 0000000000..83adec51a2
> --- /dev/null
> +++ b/hw/arm/stm32f405_soc.c
> @@ -0,0 +1,292 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "hw/arm/arm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/arm/stm32f405_soc.h"
> +#include "hw/misc/unimp.h"
> +
> +#define SYSCFG_ADD                     0x40013800
> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> +                                       0x40004C00, 0x40005000, 0x40011400,
> +                                       0x40007800, 0x40007C00 };
> +/* At the moment only Timer 2 to 5 are modelled */
> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> +                                       0x40000800, 0x40000C00 };
> +#define ADC_ADDR                       0x40012000
> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> +                                       0x40013400, 0x40015000, 0x40015400 };
> +#define EXTI_ADDR                      0x40013C00
> +
> +#define SYSCFG_IRQ               71
> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> +static const int timer_irq[] = { 28, 29, 30, 50 };
> +#define ADC_IRQ 18
> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> +                                 40, 40, 40, 40, 40} ;
> +
> +
> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);
> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> +                                     "memory", &error_abort);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    /* System configuration controller */
> +    dev = DEVICE(&s->syscfg);
> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> +
> +    /* Attach UART (uses USART registers) and USART controllers */
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        dev = DEVICE(&(s->usart[i]));
> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> +    }
> +
> +    /* Timer 2 to 5 */
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        dev = DEVICE(&(s->timer[i]));
> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> +    }
> +
> +    /* ADC device, the IRQs are ORed together */
> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> +                            "num-lines", &err);
> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> +
> +    dev = DEVICE(&(s->adc[i]));
> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> +    sysbus_connect_irq(busdev, 0,
> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> +
> +    /* SPI devices */
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        dev = DEVICE(&(s->spi[i]));
> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> +    }
> +
> +    /* EXTI device */
> +    dev = DEVICE(&s->exti);
> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> +    for (i = 0; i < 16; i++) {
> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> +    }
> +    for (i = 0; i < 16; i++) {
> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> +    }
> +
> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> +}
> +
> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;
> +}
> +
> +static const TypeInfo stm32f405_soc_info = {
> +    .name          = TYPE_STM32F405_SOC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F405State),
> +    .instance_init = stm32f405_soc_initfn,
> +    .class_init    = stm32f405_soc_class_init,
> +};
> +
> +static void stm32f405_soc_types(void)
> +{
> +    type_register_static(&stm32f405_soc_info);
> +}
> +
> +type_init(stm32f405_soc_types)
> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> new file mode 100644
> index 0000000000..f0aec53d32
> --- /dev/null
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -0,0 +1,70 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_ARM_STM32F405_SOC_H
> +#define HW_ARM_STM32F405_SOC_H
> +
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +#include "hw/timer/stm32f2xx_timer.h"
> +#include "hw/char/stm32f2xx_usart.h"
> +#include "hw/adc/stm32f2xx_adc.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +#include "hw/or-irq.h"
> +#include "hw/ssi/stm32f2xx_spi.h"
> +#include "hw/arm/armv7m.h"
> +
> +#define TYPE_STM32F405_SOC "stm32f405-soc"
> +#define STM32F405_SOC(obj) \
> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> +
> +#define STM_NUM_USARTS 7
> +#define STM_NUM_TIMERS 4
> +#define STM_NUM_ADCS 6
> +#define STM_NUM_SPIS 6
> +
> +#define FLASH_BASE_ADDRESS 0x08000000
> +#define FLASH_SIZE (1024 * 1024)
> +#define SRAM_BASE_ADDRESS 0x20000000
> +#define SRAM_SIZE (192 * 1024)
> +
> +typedef struct STM32F405State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    char *cpu_type;
> +
> +    ARMv7MState armv7m;
> +
> +    STM32F4xxSyscfgState syscfg;
> +    STM32F4xxExtiState exti;
> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> +    STM32F2XXADCState adc[STM_NUM_ADCS];
> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> +
> +    qemu_or_irq *adc_irqs;
> +} STM32F405State;
> +
> +#endif
> 


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
  2019-04-29 12:38   ` KONRAD Frederic
@ 2019-04-29 12:43   ` Philippe Mathieu-Daudé
  2019-04-29 12:43     ` Philippe Mathieu-Daudé
  2019-04-29 17:01     ` Alistair Francis
  2019-04-30 15:59   ` Peter Maydell
  3 siblings, 2 replies; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-04-29 12:43 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel; +Cc: alistair23

On 4/29/19 7:33 AM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |   8 +
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Kconfig                  |   3 +
>  hw/arm/Makefile.objs            |   1 +
>  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>  6 files changed, 375 insertions(+)
>  create mode 100644 hw/arm/stm32f405_soc.c
>  create mode 100644 include/hw/arm/stm32f405_soc.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dabbfccf9c..c9772735cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -803,6 +803,14 @@ F: hw/adc/*
>  F: hw/ssi/stm32f2xx_spi.c
>  F: include/hw/*/stm32*.h
>  
> +STM32F405
> +M: Alistair Francis <alistair@alistair23.me>
> +M: Peter Maydell <peter.maydell@linaro.org>
> +S: Maintained
> +F: hw/arm/stm32f405_soc.c
> +F: hw/misc/stm32f4xx_syscfg.c
> +F: hw/misc/stm32f4xx_exti.c
> +
>  Netduino 2
>  M: Alistair Francis <alistair@alistair23.me>
>  M: Peter Maydell <peter.maydell@linaro.org>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 8eb57de211..e079f10624 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>  CONFIG_STM32F205_SOC=y
>  CONFIG_STM32F4XX_SYSCFG=y
>  CONFIG_STM32F4XX_EXTI=y
> +CONFIG_STM32F405_SOC=y
>  CONFIG_NRF51_SOC=y
>  
>  CONFIG_CMSDK_APB_TIMER=y
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index d298fbdc89..3a98bce15a 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -62,6 +62,9 @@ config RASPI
>  config STM32F205_SOC
>      bool
>  
> +config STM32F405_SOC
> +    bool
> +
>  config XLNX_ZYNQMP_ARM
>      bool
>  
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index fa57c7c770..36c3ff54c3 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>  obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>  obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>  obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> new file mode 100644
> index 0000000000..83adec51a2
> --- /dev/null
> +++ b/hw/arm/stm32f405_soc.c
> @@ -0,0 +1,292 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>

2019?

> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "hw/arm/arm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/arm/stm32f405_soc.h"
> +#include "hw/misc/unimp.h"
> +
> +#define SYSCFG_ADD                     0x40013800
> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> +                                       0x40004C00, 0x40005000, 0x40011400,
> +                                       0x40007800, 0x40007C00 };
> +/* At the moment only Timer 2 to 5 are modelled */
> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> +                                       0x40000800, 0x40000C00 };
> +#define ADC_ADDR                       0x40012000
> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> +                                       0x40013400, 0x40015000, 0x40015400 };
> +#define EXTI_ADDR                      0x40013C00
> +
> +#define SYSCFG_IRQ               71
> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> +static const int timer_irq[] = { 28, 29, 30, 50 };
> +#define ADC_IRQ 18
> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> +                                 40, 40, 40, 40, 40} ;
> +
> +
> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);
> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> +                                     "memory", &error_abort);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    /* System configuration controller */
> +    dev = DEVICE(&s->syscfg);
> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> +
> +    /* Attach UART (uses USART registers) and USART controllers */
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        dev = DEVICE(&(s->usart[i]));
> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> +    }
> +
> +    /* Timer 2 to 5 */
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        dev = DEVICE(&(s->timer[i]));
> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> +    }
> +
> +    /* ADC device, the IRQs are ORed together */
> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> +                            "num-lines", &err);
> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> +
> +    dev = DEVICE(&(s->adc[i]));
> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> +    sysbus_connect_irq(busdev, 0,
> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> +
> +    /* SPI devices */
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        dev = DEVICE(&(s->spi[i]));
> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> +    }
> +
> +    /* EXTI device */
> +    dev = DEVICE(&s->exti);
> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> +    for (i = 0; i < 16; i++) {
> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> +    }
> +    for (i = 0; i < 16; i++) {
> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> +    }
> +
> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);

You shouldn't need to remove the last byte...

> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> +}
> +
> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;
> +}
> +
> +static const TypeInfo stm32f405_soc_info = {
> +    .name          = TYPE_STM32F405_SOC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F405State),
> +    .instance_init = stm32f405_soc_initfn,
> +    .class_init    = stm32f405_soc_class_init,
> +};
> +
> +static void stm32f405_soc_types(void)
> +{
> +    type_register_static(&stm32f405_soc_info);
> +}
> +
> +type_init(stm32f405_soc_types)
> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> new file mode 100644
> index 0000000000..f0aec53d32
> --- /dev/null
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -0,0 +1,70 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_ARM_STM32F405_SOC_H
> +#define HW_ARM_STM32F405_SOC_H
> +
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +#include "hw/timer/stm32f2xx_timer.h"
> +#include "hw/char/stm32f2xx_usart.h"
> +#include "hw/adc/stm32f2xx_adc.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +#include "hw/or-irq.h"
> +#include "hw/ssi/stm32f2xx_spi.h"
> +#include "hw/arm/armv7m.h"
> +
> +#define TYPE_STM32F405_SOC "stm32f405-soc"
> +#define STM32F405_SOC(obj) \
> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> +
> +#define STM_NUM_USARTS 7
> +#define STM_NUM_TIMERS 4
> +#define STM_NUM_ADCS 6
> +#define STM_NUM_SPIS 6
> +
> +#define FLASH_BASE_ADDRESS 0x08000000
> +#define FLASH_SIZE (1024 * 1024)
> +#define SRAM_BASE_ADDRESS 0x20000000
> +#define SRAM_SIZE (192 * 1024)
> +
> +typedef struct STM32F405State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    char *cpu_type;
> +
> +    ARMv7MState armv7m;
> +
> +    STM32F4xxSyscfgState syscfg;
> +    STM32F4xxExtiState exti;
> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> +    STM32F2XXADCState adc[STM_NUM_ADCS];
> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> +
> +    qemu_or_irq *adc_irqs;
> +} STM32F405State;
> +
> +#endif
> 

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 12:43   ` Philippe Mathieu-Daudé
@ 2019-04-29 12:43     ` Philippe Mathieu-Daudé
  2019-04-29 17:01     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Philippe Mathieu-Daudé @ 2019-04-29 12:43 UTC (permalink / raw)
  To: Alistair Francis, qemu-devel; +Cc: alistair23

On 4/29/19 7:33 AM, Alistair Francis wrote:
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |   8 +
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Kconfig                  |   3 +
>  hw/arm/Makefile.objs            |   1 +
>  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>  6 files changed, 375 insertions(+)
>  create mode 100644 hw/arm/stm32f405_soc.c
>  create mode 100644 include/hw/arm/stm32f405_soc.h
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index dabbfccf9c..c9772735cf 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -803,6 +803,14 @@ F: hw/adc/*
>  F: hw/ssi/stm32f2xx_spi.c
>  F: include/hw/*/stm32*.h
>  
> +STM32F405
> +M: Alistair Francis <alistair@alistair23.me>
> +M: Peter Maydell <peter.maydell@linaro.org>
> +S: Maintained
> +F: hw/arm/stm32f405_soc.c
> +F: hw/misc/stm32f4xx_syscfg.c
> +F: hw/misc/stm32f4xx_exti.c
> +
>  Netduino 2
>  M: Alistair Francis <alistair@alistair23.me>
>  M: Peter Maydell <peter.maydell@linaro.org>
> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> index 8eb57de211..e079f10624 100644
> --- a/default-configs/arm-softmmu.mak
> +++ b/default-configs/arm-softmmu.mak
> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>  CONFIG_STM32F205_SOC=y
>  CONFIG_STM32F4XX_SYSCFG=y
>  CONFIG_STM32F4XX_EXTI=y
> +CONFIG_STM32F405_SOC=y
>  CONFIG_NRF51_SOC=y
>  
>  CONFIG_CMSDK_APB_TIMER=y
> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> index d298fbdc89..3a98bce15a 100644
> --- a/hw/arm/Kconfig
> +++ b/hw/arm/Kconfig
> @@ -62,6 +62,9 @@ config RASPI
>  config STM32F205_SOC
>      bool
>  
> +config STM32F405_SOC
> +    bool
> +
>  config XLNX_ZYNQMP_ARM
>      bool
>  
> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> index fa57c7c770..36c3ff54c3 100644
> --- a/hw/arm/Makefile.objs
> +++ b/hw/arm/Makefile.objs
> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>  obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>  obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>  obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> new file mode 100644
> index 0000000000..83adec51a2
> --- /dev/null
> +++ b/hw/arm/stm32f405_soc.c
> @@ -0,0 +1,292 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>

2019?

> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu-common.h"
> +#include "hw/arm/arm.h"
> +#include "exec/address-spaces.h"
> +#include "hw/arm/stm32f405_soc.h"
> +#include "hw/misc/unimp.h"
> +
> +#define SYSCFG_ADD                     0x40013800
> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> +                                       0x40004C00, 0x40005000, 0x40011400,
> +                                       0x40007800, 0x40007C00 };
> +/* At the moment only Timer 2 to 5 are modelled */
> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> +                                       0x40000800, 0x40000C00 };
> +#define ADC_ADDR                       0x40012000
> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> +                                       0x40013400, 0x40015000, 0x40015400 };
> +#define EXTI_ADDR                      0x40013C00
> +
> +#define SYSCFG_IRQ               71
> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> +static const int timer_irq[] = { 28, 29, 30, 50 };
> +#define ADC_IRQ 18
> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> +                                 40, 40, 40, 40, 40} ;
> +
> +
> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);
> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> +                                     "memory", &error_abort);
> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +
> +    /* System configuration controller */
> +    dev = DEVICE(&s->syscfg);
> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> +
> +    /* Attach UART (uses USART registers) and USART controllers */
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        dev = DEVICE(&(s->usart[i]));
> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> +    }
> +
> +    /* Timer 2 to 5 */
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        dev = DEVICE(&(s->timer[i]));
> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> +    }
> +
> +    /* ADC device, the IRQs are ORed together */
> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> +                            "num-lines", &err);
> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> +
> +    dev = DEVICE(&(s->adc[i]));
> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> +    sysbus_connect_irq(busdev, 0,
> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> +
> +    /* SPI devices */
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        dev = DEVICE(&(s->spi[i]));
> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> +        if (err != NULL) {
> +            error_propagate(errp, err);
> +            return;
> +        }
> +        busdev = SYS_BUS_DEVICE(dev);
> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> +    }
> +
> +    /* EXTI device */
> +    dev = DEVICE(&s->exti);
> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> +    if (err != NULL) {
> +        error_propagate(errp, err);
> +        return;
> +    }
> +    busdev = SYS_BUS_DEVICE(dev);
> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> +    for (i = 0; i < 16; i++) {
> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> +    }
> +    for (i = 0; i < 16; i++) {
> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> +    }
> +
> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);

You shouldn't need to remove the last byte...

> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> +}
> +
> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;
> +}
> +
> +static const TypeInfo stm32f405_soc_info = {
> +    .name          = TYPE_STM32F405_SOC,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F405State),
> +    .instance_init = stm32f405_soc_initfn,
> +    .class_init    = stm32f405_soc_class_init,
> +};
> +
> +static void stm32f405_soc_types(void)
> +{
> +    type_register_static(&stm32f405_soc_info);
> +}
> +
> +type_init(stm32f405_soc_types)
> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> new file mode 100644
> index 0000000000..f0aec53d32
> --- /dev/null
> +++ b/include/hw/arm/stm32f405_soc.h
> @@ -0,0 +1,70 @@
> +/*
> + * STM32F405 SoC
> + *
> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + */
> +
> +#ifndef HW_ARM_STM32F405_SOC_H
> +#define HW_ARM_STM32F405_SOC_H
> +
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +#include "hw/timer/stm32f2xx_timer.h"
> +#include "hw/char/stm32f2xx_usart.h"
> +#include "hw/adc/stm32f2xx_adc.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +#include "hw/or-irq.h"
> +#include "hw/ssi/stm32f2xx_spi.h"
> +#include "hw/arm/armv7m.h"
> +
> +#define TYPE_STM32F405_SOC "stm32f405-soc"
> +#define STM32F405_SOC(obj) \
> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> +
> +#define STM_NUM_USARTS 7
> +#define STM_NUM_TIMERS 4
> +#define STM_NUM_ADCS 6
> +#define STM_NUM_SPIS 6
> +
> +#define FLASH_BASE_ADDRESS 0x08000000
> +#define FLASH_SIZE (1024 * 1024)
> +#define SRAM_BASE_ADDRESS 0x20000000
> +#define SRAM_SIZE (192 * 1024)
> +
> +typedef struct STM32F405State {
> +    /*< private >*/
> +    SysBusDevice parent_obj;
> +    /*< public >*/
> +
> +    char *cpu_type;
> +
> +    ARMv7MState armv7m;
> +
> +    STM32F4xxSyscfgState syscfg;
> +    STM32F4xxExtiState exti;
> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> +    STM32F2XXADCState adc[STM_NUM_ADCS];
> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> +
> +    qemu_or_irq *adc_irqs;
> +} STM32F405State;
> +
> +#endif
> 


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 12:38   ` KONRAD Frederic
  2019-04-29 12:38     ` KONRAD Frederic
@ 2019-04-29 17:00     ` Alistair Francis
  2019-04-29 17:00       ` Alistair Francis
  2019-04-30 18:10       ` KONRAD Frederic
  1 sibling, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29 17:00 UTC (permalink / raw)
  To: KONRAD Frederic; +Cc: Alistair Francis, qemu-devel

 On Mon, Apr 29, 2019 at 5:38 AM KONRAD Frederic
<frederic.konrad@adacore.com> wrote:
>
> Hi Alistair,
>
> Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >   MAINTAINERS                     |   8 +
> >   default-configs/arm-softmmu.mak |   1 +
> >   hw/arm/Kconfig                  |   3 +
> >   hw/arm/Makefile.objs            |   1 +
> >   hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >   include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >   6 files changed, 375 insertions(+)
> >   create mode 100644 hw/arm/stm32f405_soc.c
> >   create mode 100644 include/hw/arm/stm32f405_soc.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index dabbfccf9c..c9772735cf 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -803,6 +803,14 @@ F: hw/adc/*
> >   F: hw/ssi/stm32f2xx_spi.c
> >   F: include/hw/*/stm32*.h
> >
> > +STM32F405
> > +M: Alistair Francis <alistair@alistair23.me>
> > +M: Peter Maydell <peter.maydell@linaro.org>
> > +S: Maintained
> > +F: hw/arm/stm32f405_soc.c
> > +F: hw/misc/stm32f4xx_syscfg.c
> > +F: hw/misc/stm32f4xx_exti.c
> > +
> >   Netduino 2
> >   M: Alistair Francis <alistair@alistair23.me>
> >   M: Peter Maydell <peter.maydell@linaro.org>
> > diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> > index 8eb57de211..e079f10624 100644
> > --- a/default-configs/arm-softmmu.mak
> > +++ b/default-configs/arm-softmmu.mak
> > @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
> >   CONFIG_STM32F205_SOC=y
> >   CONFIG_STM32F4XX_SYSCFG=y
> >   CONFIG_STM32F4XX_EXTI=y
> > +CONFIG_STM32F405_SOC=y
>
> Why not using 4xx instead of 405 in this patch as well?

I'm not sure if all the SoC variants are generic like that. Looking at
the datasheet https://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf
it only specified the 405 and 407 variants. This is mostly a way just
to say that I have tested it as a 405, it might work with others but I
don't know. I think it's harder to make the SoC generic without having
tested the other optinos (or knowing they are all interchangable).

Alistair

>
> >   CONFIG_NRF51_SOC=y
> >
> >   CONFIG_CMSDK_APB_TIMER=y
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index d298fbdc89..3a98bce15a 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -62,6 +62,9 @@ config RASPI
> >   config STM32F205_SOC
> >       bool
> >
> > +config STM32F405_SOC
> > +    bool
> > +
> >   config XLNX_ZYNQMP_ARM
> >       bool
> >
> > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> > index fa57c7c770..36c3ff54c3 100644
> > --- a/hw/arm/Makefile.objs
> > +++ b/hw/arm/Makefile.objs
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
> >   obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> >   obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
> >   obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> > +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
> >   obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
> >   obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
> >   obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> > diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> > new file mode 100644
> > index 0000000000..83adec51a2
> > --- /dev/null
> > +++ b/hw/arm/stm32f405_soc.c
> > @@ -0,0 +1,292 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "hw/arm/arm.h"
> > +#include "exec/address-spaces.h"
> > +#include "hw/arm/stm32f405_soc.h"
> > +#include "hw/misc/unimp.h"
> > +
> > +#define SYSCFG_ADD                     0x40013800
> > +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> > +                                       0x40004C00, 0x40005000, 0x40011400,
> > +                                       0x40007800, 0x40007C00 };
> > +/* At the moment only Timer 2 to 5 are modelled */
> > +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> > +                                       0x40000800, 0x40000C00 };
> > +#define ADC_ADDR                       0x40012000
> > +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> > +                                       0x40013400, 0x40015000, 0x40015400 };
> > +#define EXTI_ADDR                      0x40013C00
> > +
> > +#define SYSCFG_IRQ               71
> > +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> > +static const int timer_irq[] = { 28, 29, 30, 50 };
> > +#define ADC_IRQ 18
> > +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> > +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> > +                                 40, 40, 40, 40, 40} ;
> > +
> > +
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> > +                                     "memory", &error_abort);
> > +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +
> > +    /* System configuration controller */
> > +    dev = DEVICE(&s->syscfg);
> > +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> > +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> > +
> > +    /* Attach UART (uses USART registers) and USART controllers */
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        dev = DEVICE(&(s->usart[i]));
> > +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> > +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> > +    }
> > +
> > +    /* Timer 2 to 5 */
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        dev = DEVICE(&(s->timer[i]));
> > +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> > +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> > +    }
> > +
> > +    /* ADC device, the IRQs are ORed together */
> > +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> > +                            "num-lines", &err);
> > +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> > +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> > +
> > +    dev = DEVICE(&(s->adc[i]));
> > +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> > +    sysbus_connect_irq(busdev, 0,
> > +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> > +
> > +    /* SPI devices */
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        dev = DEVICE(&(s->spi[i]));
> > +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> > +    }
> > +
> > +    /* EXTI device */
> > +    dev = DEVICE(&s->exti);
> > +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> > +    for (i = 0; i < 16; i++) {
> > +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> > +    }
> > +    for (i = 0; i < 16; i++) {
> > +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> > +    }
> > +
> > +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
> > +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> > +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> > +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> > +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> > +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> > +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> > +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> > +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> > +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> > +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> > +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> > +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> > +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> > +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> > +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> > +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> > +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> > +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> > +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> > +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> > +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> > +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> > +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> > +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> > +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> > +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> > +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> > +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> > +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> > +}
> > +
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
> > +}
> > +
> > +static const TypeInfo stm32f405_soc_info = {
> > +    .name          = TYPE_STM32F405_SOC,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F405State),
> > +    .instance_init = stm32f405_soc_initfn,
> > +    .class_init    = stm32f405_soc_class_init,
> > +};
> > +
> > +static void stm32f405_soc_types(void)
> > +{
> > +    type_register_static(&stm32f405_soc_info);
> > +}
> > +
> > +type_init(stm32f405_soc_types)
> > diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> > new file mode 100644
> > index 0000000000..f0aec53d32
> > --- /dev/null
> > +++ b/include/hw/arm/stm32f405_soc.h
> > @@ -0,0 +1,70 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#ifndef HW_ARM_STM32F405_SOC_H
> > +#define HW_ARM_STM32F405_SOC_H
> > +
> > +#include "hw/misc/stm32f4xx_syscfg.h"
> > +#include "hw/timer/stm32f2xx_timer.h"
> > +#include "hw/char/stm32f2xx_usart.h"
> > +#include "hw/adc/stm32f2xx_adc.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +#include "hw/or-irq.h"
> > +#include "hw/ssi/stm32f2xx_spi.h"
> > +#include "hw/arm/armv7m.h"
> > +
> > +#define TYPE_STM32F405_SOC "stm32f405-soc"
> > +#define STM32F405_SOC(obj) \
> > +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> > +
> > +#define STM_NUM_USARTS 7
> > +#define STM_NUM_TIMERS 4
> > +#define STM_NUM_ADCS 6
> > +#define STM_NUM_SPIS 6
> > +
> > +#define FLASH_BASE_ADDRESS 0x08000000
> > +#define FLASH_SIZE (1024 * 1024)
> > +#define SRAM_BASE_ADDRESS 0x20000000
> > +#define SRAM_SIZE (192 * 1024)
> > +
> > +typedef struct STM32F405State {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    /*< public >*/
> > +
> > +    char *cpu_type;
> > +
> > +    ARMv7MState armv7m;
> > +
> > +    STM32F4xxSyscfgState syscfg;
> > +    STM32F4xxExtiState exti;
> > +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> > +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> > +    STM32F2XXADCState adc[STM_NUM_ADCS];
> > +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> > +
> > +    qemu_or_irq *adc_irqs;
> > +} STM32F405State;
> > +
> > +#endif
> >

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 17:00     ` Alistair Francis
@ 2019-04-29 17:00       ` Alistair Francis
  2019-04-30 18:10       ` KONRAD Frederic
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29 17:00 UTC (permalink / raw)
  To: KONRAD Frederic; +Cc: Alistair Francis, qemu-devel

 On Mon, Apr 29, 2019 at 5:38 AM KONRAD Frederic
<frederic.konrad@adacore.com> wrote:
>
> Hi Alistair,
>
> Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >   MAINTAINERS                     |   8 +
> >   default-configs/arm-softmmu.mak |   1 +
> >   hw/arm/Kconfig                  |   3 +
> >   hw/arm/Makefile.objs            |   1 +
> >   hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >   include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >   6 files changed, 375 insertions(+)
> >   create mode 100644 hw/arm/stm32f405_soc.c
> >   create mode 100644 include/hw/arm/stm32f405_soc.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index dabbfccf9c..c9772735cf 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -803,6 +803,14 @@ F: hw/adc/*
> >   F: hw/ssi/stm32f2xx_spi.c
> >   F: include/hw/*/stm32*.h
> >
> > +STM32F405
> > +M: Alistair Francis <alistair@alistair23.me>
> > +M: Peter Maydell <peter.maydell@linaro.org>
> > +S: Maintained
> > +F: hw/arm/stm32f405_soc.c
> > +F: hw/misc/stm32f4xx_syscfg.c
> > +F: hw/misc/stm32f4xx_exti.c
> > +
> >   Netduino 2
> >   M: Alistair Francis <alistair@alistair23.me>
> >   M: Peter Maydell <peter.maydell@linaro.org>
> > diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> > index 8eb57de211..e079f10624 100644
> > --- a/default-configs/arm-softmmu.mak
> > +++ b/default-configs/arm-softmmu.mak
> > @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
> >   CONFIG_STM32F205_SOC=y
> >   CONFIG_STM32F4XX_SYSCFG=y
> >   CONFIG_STM32F4XX_EXTI=y
> > +CONFIG_STM32F405_SOC=y
>
> Why not using 4xx instead of 405 in this patch as well?

I'm not sure if all the SoC variants are generic like that. Looking at
the datasheet https://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf
it only specified the 405 and 407 variants. This is mostly a way just
to say that I have tested it as a 405, it might work with others but I
don't know. I think it's harder to make the SoC generic without having
tested the other optinos (or knowing they are all interchangable).

Alistair

>
> >   CONFIG_NRF51_SOC=y
> >
> >   CONFIG_CMSDK_APB_TIMER=y
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index d298fbdc89..3a98bce15a 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -62,6 +62,9 @@ config RASPI
> >   config STM32F205_SOC
> >       bool
> >
> > +config STM32F405_SOC
> > +    bool
> > +
> >   config XLNX_ZYNQMP_ARM
> >       bool
> >
> > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> > index fa57c7c770..36c3ff54c3 100644
> > --- a/hw/arm/Makefile.objs
> > +++ b/hw/arm/Makefile.objs
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
> >   obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> >   obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
> >   obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> > +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
> >   obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
> >   obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
> >   obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> > diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> > new file mode 100644
> > index 0000000000..83adec51a2
> > --- /dev/null
> > +++ b/hw/arm/stm32f405_soc.c
> > @@ -0,0 +1,292 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "hw/arm/arm.h"
> > +#include "exec/address-spaces.h"
> > +#include "hw/arm/stm32f405_soc.h"
> > +#include "hw/misc/unimp.h"
> > +
> > +#define SYSCFG_ADD                     0x40013800
> > +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> > +                                       0x40004C00, 0x40005000, 0x40011400,
> > +                                       0x40007800, 0x40007C00 };
> > +/* At the moment only Timer 2 to 5 are modelled */
> > +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> > +                                       0x40000800, 0x40000C00 };
> > +#define ADC_ADDR                       0x40012000
> > +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> > +                                       0x40013400, 0x40015000, 0x40015400 };
> > +#define EXTI_ADDR                      0x40013C00
> > +
> > +#define SYSCFG_IRQ               71
> > +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> > +static const int timer_irq[] = { 28, 29, 30, 50 };
> > +#define ADC_IRQ 18
> > +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> > +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> > +                                 40, 40, 40, 40, 40} ;
> > +
> > +
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> > +                                     "memory", &error_abort);
> > +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +
> > +    /* System configuration controller */
> > +    dev = DEVICE(&s->syscfg);
> > +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> > +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> > +
> > +    /* Attach UART (uses USART registers) and USART controllers */
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        dev = DEVICE(&(s->usart[i]));
> > +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> > +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> > +    }
> > +
> > +    /* Timer 2 to 5 */
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        dev = DEVICE(&(s->timer[i]));
> > +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> > +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> > +    }
> > +
> > +    /* ADC device, the IRQs are ORed together */
> > +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> > +                            "num-lines", &err);
> > +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> > +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> > +
> > +    dev = DEVICE(&(s->adc[i]));
> > +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> > +    sysbus_connect_irq(busdev, 0,
> > +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> > +
> > +    /* SPI devices */
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        dev = DEVICE(&(s->spi[i]));
> > +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> > +    }
> > +
> > +    /* EXTI device */
> > +    dev = DEVICE(&s->exti);
> > +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> > +    for (i = 0; i < 16; i++) {
> > +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> > +    }
> > +    for (i = 0; i < 16; i++) {
> > +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> > +    }
> > +
> > +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
> > +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> > +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> > +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> > +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> > +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> > +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> > +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> > +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> > +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> > +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> > +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> > +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> > +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> > +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> > +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> > +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> > +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> > +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> > +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> > +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> > +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> > +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> > +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> > +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> > +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> > +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> > +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> > +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> > +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> > +}
> > +
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
> > +}
> > +
> > +static const TypeInfo stm32f405_soc_info = {
> > +    .name          = TYPE_STM32F405_SOC,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F405State),
> > +    .instance_init = stm32f405_soc_initfn,
> > +    .class_init    = stm32f405_soc_class_init,
> > +};
> > +
> > +static void stm32f405_soc_types(void)
> > +{
> > +    type_register_static(&stm32f405_soc_info);
> > +}
> > +
> > +type_init(stm32f405_soc_types)
> > diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> > new file mode 100644
> > index 0000000000..f0aec53d32
> > --- /dev/null
> > +++ b/include/hw/arm/stm32f405_soc.h
> > @@ -0,0 +1,70 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#ifndef HW_ARM_STM32F405_SOC_H
> > +#define HW_ARM_STM32F405_SOC_H
> > +
> > +#include "hw/misc/stm32f4xx_syscfg.h"
> > +#include "hw/timer/stm32f2xx_timer.h"
> > +#include "hw/char/stm32f2xx_usart.h"
> > +#include "hw/adc/stm32f2xx_adc.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +#include "hw/or-irq.h"
> > +#include "hw/ssi/stm32f2xx_spi.h"
> > +#include "hw/arm/armv7m.h"
> > +
> > +#define TYPE_STM32F405_SOC "stm32f405-soc"
> > +#define STM32F405_SOC(obj) \
> > +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> > +
> > +#define STM_NUM_USARTS 7
> > +#define STM_NUM_TIMERS 4
> > +#define STM_NUM_ADCS 6
> > +#define STM_NUM_SPIS 6
> > +
> > +#define FLASH_BASE_ADDRESS 0x08000000
> > +#define FLASH_SIZE (1024 * 1024)
> > +#define SRAM_BASE_ADDRESS 0x20000000
> > +#define SRAM_SIZE (192 * 1024)
> > +
> > +typedef struct STM32F405State {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    /*< public >*/
> > +
> > +    char *cpu_type;
> > +
> > +    ARMv7MState armv7m;
> > +
> > +    STM32F4xxSyscfgState syscfg;
> > +    STM32F4xxExtiState exti;
> > +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> > +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> > +    STM32F2XXADCState adc[STM_NUM_ADCS];
> > +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> > +
> > +    qemu_or_irq *adc_irqs;
> > +} STM32F405State;
> > +
> > +#endif
> >


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 12:43   ` Philippe Mathieu-Daudé
  2019-04-29 12:43     ` Philippe Mathieu-Daudé
@ 2019-04-29 17:01     ` Alistair Francis
  2019-04-29 17:01       ` Alistair Francis
  2019-04-30 15:51       ` Peter Maydell
  1 sibling, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29 17:01 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Alistair Francis, qemu-devel

On Mon, Apr 29, 2019 at 5:43 AM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> On 4/29/19 7:33 AM, Alistair Francis wrote:
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |   8 +
> >  default-configs/arm-softmmu.mak |   1 +
> >  hw/arm/Kconfig                  |   3 +
> >  hw/arm/Makefile.objs            |   1 +
> >  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >  6 files changed, 375 insertions(+)
> >  create mode 100644 hw/arm/stm32f405_soc.c
> >  create mode 100644 include/hw/arm/stm32f405_soc.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index dabbfccf9c..c9772735cf 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -803,6 +803,14 @@ F: hw/adc/*
> >  F: hw/ssi/stm32f2xx_spi.c
> >  F: include/hw/*/stm32*.h
> >
> > +STM32F405
> > +M: Alistair Francis <alistair@alistair23.me>
> > +M: Peter Maydell <peter.maydell@linaro.org>
> > +S: Maintained
> > +F: hw/arm/stm32f405_soc.c
> > +F: hw/misc/stm32f4xx_syscfg.c
> > +F: hw/misc/stm32f4xx_exti.c
> > +
> >  Netduino 2
> >  M: Alistair Francis <alistair@alistair23.me>
> >  M: Peter Maydell <peter.maydell@linaro.org>
> > diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> > index 8eb57de211..e079f10624 100644
> > --- a/default-configs/arm-softmmu.mak
> > +++ b/default-configs/arm-softmmu.mak
> > @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
> >  CONFIG_STM32F205_SOC=y
> >  CONFIG_STM32F4XX_SYSCFG=y
> >  CONFIG_STM32F4XX_EXTI=y
> > +CONFIG_STM32F405_SOC=y
> >  CONFIG_NRF51_SOC=y
> >
> >  CONFIG_CMSDK_APB_TIMER=y
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index d298fbdc89..3a98bce15a 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -62,6 +62,9 @@ config RASPI
> >  config STM32F205_SOC
> >      bool
> >
> > +config STM32F405_SOC
> > +    bool
> > +
> >  config XLNX_ZYNQMP_ARM
> >      bool
> >
> > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> > index fa57c7c770..36c3ff54c3 100644
> > --- a/hw/arm/Makefile.objs
> > +++ b/hw/arm/Makefile.objs
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
> >  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> >  obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
> >  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> > +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
> >  obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
> >  obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
> >  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> > diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> > new file mode 100644
> > index 0000000000..83adec51a2
> > --- /dev/null
> > +++ b/hw/arm/stm32f405_soc.c
> > @@ -0,0 +1,292 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>
> 2019?

I never know how this works. It was originally written in 2014, do I
update the year based on the upstream submission?

>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "hw/arm/arm.h"
> > +#include "exec/address-spaces.h"
> > +#include "hw/arm/stm32f405_soc.h"
> > +#include "hw/misc/unimp.h"
> > +
> > +#define SYSCFG_ADD                     0x40013800
> > +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> > +                                       0x40004C00, 0x40005000, 0x40011400,
> > +                                       0x40007800, 0x40007C00 };
> > +/* At the moment only Timer 2 to 5 are modelled */
> > +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> > +                                       0x40000800, 0x40000C00 };
> > +#define ADC_ADDR                       0x40012000
> > +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> > +                                       0x40013400, 0x40015000, 0x40015400 };
> > +#define EXTI_ADDR                      0x40013C00
> > +
> > +#define SYSCFG_IRQ               71
> > +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> > +static const int timer_irq[] = { 28, 29, 30, 50 };
> > +#define ADC_IRQ 18
> > +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> > +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> > +                                 40, 40, 40, 40, 40} ;
> > +
> > +
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> > +                                     "memory", &error_abort);
> > +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +
> > +    /* System configuration controller */
> > +    dev = DEVICE(&s->syscfg);
> > +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> > +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> > +
> > +    /* Attach UART (uses USART registers) and USART controllers */
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        dev = DEVICE(&(s->usart[i]));
> > +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> > +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> > +    }
> > +
> > +    /* Timer 2 to 5 */
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        dev = DEVICE(&(s->timer[i]));
> > +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> > +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> > +    }
> > +
> > +    /* ADC device, the IRQs are ORed together */
> > +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> > +                            "num-lines", &err);
> > +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> > +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> > +
> > +    dev = DEVICE(&(s->adc[i]));
> > +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> > +    sysbus_connect_irq(busdev, 0,
> > +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> > +
> > +    /* SPI devices */
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        dev = DEVICE(&(s->spi[i]));
> > +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> > +    }
> > +
> > +    /* EXTI device */
> > +    dev = DEVICE(&s->exti);
> > +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> > +    for (i = 0; i < 16; i++) {
> > +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> > +    }
> > +    for (i = 0; i < 16; i++) {
> > +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> > +    }
> > +
> > +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
>
> You shouldn't need to remove the last byte...

Good point, I'll fix that.

Alistair

>
> > +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> > +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> > +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> > +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> > +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> > +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> > +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> > +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> > +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> > +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> > +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> > +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> > +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> > +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> > +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> > +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> > +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> > +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> > +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> > +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> > +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> > +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> > +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> > +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> > +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> > +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> > +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> > +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> > +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> > +}
> > +
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
> > +}
> > +
> > +static const TypeInfo stm32f405_soc_info = {
> > +    .name          = TYPE_STM32F405_SOC,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F405State),
> > +    .instance_init = stm32f405_soc_initfn,
> > +    .class_init    = stm32f405_soc_class_init,
> > +};
> > +
> > +static void stm32f405_soc_types(void)
> > +{
> > +    type_register_static(&stm32f405_soc_info);
> > +}
> > +
> > +type_init(stm32f405_soc_types)
> > diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> > new file mode 100644
> > index 0000000000..f0aec53d32
> > --- /dev/null
> > +++ b/include/hw/arm/stm32f405_soc.h
> > @@ -0,0 +1,70 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#ifndef HW_ARM_STM32F405_SOC_H
> > +#define HW_ARM_STM32F405_SOC_H
> > +
> > +#include "hw/misc/stm32f4xx_syscfg.h"
> > +#include "hw/timer/stm32f2xx_timer.h"
> > +#include "hw/char/stm32f2xx_usart.h"
> > +#include "hw/adc/stm32f2xx_adc.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +#include "hw/or-irq.h"
> > +#include "hw/ssi/stm32f2xx_spi.h"
> > +#include "hw/arm/armv7m.h"
> > +
> > +#define TYPE_STM32F405_SOC "stm32f405-soc"
> > +#define STM32F405_SOC(obj) \
> > +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> > +
> > +#define STM_NUM_USARTS 7
> > +#define STM_NUM_TIMERS 4
> > +#define STM_NUM_ADCS 6
> > +#define STM_NUM_SPIS 6
> > +
> > +#define FLASH_BASE_ADDRESS 0x08000000
> > +#define FLASH_SIZE (1024 * 1024)
> > +#define SRAM_BASE_ADDRESS 0x20000000
> > +#define SRAM_SIZE (192 * 1024)
> > +
> > +typedef struct STM32F405State {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    /*< public >*/
> > +
> > +    char *cpu_type;
> > +
> > +    ARMv7MState armv7m;
> > +
> > +    STM32F4xxSyscfgState syscfg;
> > +    STM32F4xxExtiState exti;
> > +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> > +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> > +    STM32F2XXADCState adc[STM_NUM_ADCS];
> > +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> > +
> > +    qemu_or_irq *adc_irqs;
> > +} STM32F405State;
> > +
> > +#endif
> >

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 17:01     ` Alistair Francis
@ 2019-04-29 17:01       ` Alistair Francis
  2019-04-30 15:51       ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-29 17:01 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé; +Cc: Alistair Francis, qemu-devel

On Mon, Apr 29, 2019 at 5:43 AM Philippe Mathieu-Daudé
<philmd@redhat.com> wrote:
>
> On 4/29/19 7:33 AM, Alistair Francis wrote:
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |   8 +
> >  default-configs/arm-softmmu.mak |   1 +
> >  hw/arm/Kconfig                  |   3 +
> >  hw/arm/Makefile.objs            |   1 +
> >  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >  6 files changed, 375 insertions(+)
> >  create mode 100644 hw/arm/stm32f405_soc.c
> >  create mode 100644 include/hw/arm/stm32f405_soc.h
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index dabbfccf9c..c9772735cf 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -803,6 +803,14 @@ F: hw/adc/*
> >  F: hw/ssi/stm32f2xx_spi.c
> >  F: include/hw/*/stm32*.h
> >
> > +STM32F405
> > +M: Alistair Francis <alistair@alistair23.me>
> > +M: Peter Maydell <peter.maydell@linaro.org>
> > +S: Maintained
> > +F: hw/arm/stm32f405_soc.c
> > +F: hw/misc/stm32f4xx_syscfg.c
> > +F: hw/misc/stm32f4xx_exti.c
> > +
> >  Netduino 2
> >  M: Alistair Francis <alistair@alistair23.me>
> >  M: Peter Maydell <peter.maydell@linaro.org>
> > diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
> > index 8eb57de211..e079f10624 100644
> > --- a/default-configs/arm-softmmu.mak
> > +++ b/default-configs/arm-softmmu.mak
> > @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
> >  CONFIG_STM32F205_SOC=y
> >  CONFIG_STM32F4XX_SYSCFG=y
> >  CONFIG_STM32F4XX_EXTI=y
> > +CONFIG_STM32F405_SOC=y
> >  CONFIG_NRF51_SOC=y
> >
> >  CONFIG_CMSDK_APB_TIMER=y
> > diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
> > index d298fbdc89..3a98bce15a 100644
> > --- a/hw/arm/Kconfig
> > +++ b/hw/arm/Kconfig
> > @@ -62,6 +62,9 @@ config RASPI
> >  config STM32F205_SOC
> >      bool
> >
> > +config STM32F405_SOC
> > +    bool
> > +
> >  config XLNX_ZYNQMP_ARM
> >      bool
> >
> > diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
> > index fa57c7c770..36c3ff54c3 100644
> > --- a/hw/arm/Makefile.objs
> > +++ b/hw/arm/Makefile.objs
> > @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
> >  obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
> >  obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
> >  obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
> > +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
> >  obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
> >  obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
> >  obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
> > diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
> > new file mode 100644
> > index 0000000000..83adec51a2
> > --- /dev/null
> > +++ b/hw/arm/stm32f405_soc.c
> > @@ -0,0 +1,292 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>
> 2019?

I never know how this works. It was originally written in 2014, do I
update the year based on the upstream submission?

>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qapi/error.h"
> > +#include "qemu-common.h"
> > +#include "hw/arm/arm.h"
> > +#include "exec/address-spaces.h"
> > +#include "hw/arm/stm32f405_soc.h"
> > +#include "hw/misc/unimp.h"
> > +
> > +#define SYSCFG_ADD                     0x40013800
> > +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
> > +                                       0x40004C00, 0x40005000, 0x40011400,
> > +                                       0x40007800, 0x40007C00 };
> > +/* At the moment only Timer 2 to 5 are modelled */
> > +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
> > +                                       0x40000800, 0x40000C00 };
> > +#define ADC_ADDR                       0x40012000
> > +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
> > +                                       0x40013400, 0x40015000, 0x40015400 };
> > +#define EXTI_ADDR                      0x40013C00
> > +
> > +#define SYSCFG_IRQ               71
> > +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
> > +static const int timer_irq[] = { 28, 29, 30, 50 };
> > +#define ADC_IRQ 18
> > +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
> > +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
> > +                                 40, 40, 40, 40, 40} ;
> > +
> > +
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
> > +                                     "memory", &error_abort);
> > +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +
> > +    /* System configuration controller */
> > +    dev = DEVICE(&s->syscfg);
> > +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
> > +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
> > +
> > +    /* Attach UART (uses USART registers) and USART controllers */
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        dev = DEVICE(&(s->usart[i]));
> > +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
> > +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
> > +    }
> > +
> > +    /* Timer 2 to 5 */
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        dev = DEVICE(&(s->timer[i]));
> > +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
> > +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
> > +    }
> > +
> > +    /* ADC device, the IRQs are ORed together */
> > +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
> > +                            "num-lines", &err);
> > +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
> > +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
> > +
> > +    dev = DEVICE(&(s->adc[i]));
> > +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
> > +    sysbus_connect_irq(busdev, 0,
> > +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
> > +
> > +    /* SPI devices */
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        dev = DEVICE(&(s->spi[i]));
> > +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
> > +        if (err != NULL) {
> > +            error_propagate(errp, err);
> > +            return;
> > +        }
> > +        busdev = SYS_BUS_DEVICE(dev);
> > +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
> > +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
> > +    }
> > +
> > +    /* EXTI device */
> > +    dev = DEVICE(&s->exti);
> > +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
> > +    if (err != NULL) {
> > +        error_propagate(errp, err);
> > +        return;
> > +    }
> > +    busdev = SYS_BUS_DEVICE(dev);
> > +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
> > +    for (i = 0; i < 16; i++) {
> > +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
> > +    }
> > +    for (i = 0; i < 16; i++) {
> > +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
> > +    }
> > +
> > +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
>
> You shouldn't need to remove the last byte...

Good point, I'll fix that.

Alistair

>
> > +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
> > +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
> > +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
> > +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
> > +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
> > +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
> > +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
> > +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
> > +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
> > +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
> > +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
> > +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
> > +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
> > +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
> > +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
> > +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
> > +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
> > +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
> > +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
> > +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
> > +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
> > +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
> > +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
> > +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
> > +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
> > +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
> > +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
> > +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
> > +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
> > +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
> > +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
> > +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
> > +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
> > +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
> > +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
> > +}
> > +
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
> > +}
> > +
> > +static const TypeInfo stm32f405_soc_info = {
> > +    .name          = TYPE_STM32F405_SOC,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F405State),
> > +    .instance_init = stm32f405_soc_initfn,
> > +    .class_init    = stm32f405_soc_class_init,
> > +};
> > +
> > +static void stm32f405_soc_types(void)
> > +{
> > +    type_register_static(&stm32f405_soc_info);
> > +}
> > +
> > +type_init(stm32f405_soc_types)
> > diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
> > new file mode 100644
> > index 0000000000..f0aec53d32
> > --- /dev/null
> > +++ b/include/hw/arm/stm32f405_soc.h
> > @@ -0,0 +1,70 @@
> > +/*
> > + * STM32F405 SoC
> > + *
> > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this software and associated documentation files (the "Software"), to deal
> > + * in the Software without restriction, including without limitation the rights
> > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> > + * copies of the Software, and to permit persons to whom the Software is
> > + * furnished to do so, subject to the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> > + * THE SOFTWARE.
> > + */
> > +
> > +#ifndef HW_ARM_STM32F405_SOC_H
> > +#define HW_ARM_STM32F405_SOC_H
> > +
> > +#include "hw/misc/stm32f4xx_syscfg.h"
> > +#include "hw/timer/stm32f2xx_timer.h"
> > +#include "hw/char/stm32f2xx_usart.h"
> > +#include "hw/adc/stm32f2xx_adc.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +#include "hw/or-irq.h"
> > +#include "hw/ssi/stm32f2xx_spi.h"
> > +#include "hw/arm/armv7m.h"
> > +
> > +#define TYPE_STM32F405_SOC "stm32f405-soc"
> > +#define STM32F405_SOC(obj) \
> > +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
> > +
> > +#define STM_NUM_USARTS 7
> > +#define STM_NUM_TIMERS 4
> > +#define STM_NUM_ADCS 6
> > +#define STM_NUM_SPIS 6
> > +
> > +#define FLASH_BASE_ADDRESS 0x08000000
> > +#define FLASH_SIZE (1024 * 1024)
> > +#define SRAM_BASE_ADDRESS 0x20000000
> > +#define SRAM_SIZE (192 * 1024)
> > +
> > +typedef struct STM32F405State {
> > +    /*< private >*/
> > +    SysBusDevice parent_obj;
> > +    /*< public >*/
> > +
> > +    char *cpu_type;
> > +
> > +    ARMv7MState armv7m;
> > +
> > +    STM32F4xxSyscfgState syscfg;
> > +    STM32F4xxExtiState exti;
> > +    STM32F2XXUsartState usart[STM_NUM_USARTS];
> > +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
> > +    STM32F2XXADCState adc[STM_NUM_ADCS];
> > +    STM32F2XXSPIState spi[STM_NUM_SPIS];
> > +
> > +    qemu_or_irq *adc_irqs;
> > +} STM32F405State;
> > +
> > +#endif
> >


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

* Re: [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device
  2019-04-29  5:32 ` [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device Alistair Francis
  2019-04-29  5:32   ` Alistair Francis
@ 2019-04-30 15:44   ` Peter Maydell
  2019-04-30 15:44     ` Peter Maydell
  1 sibling, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:44 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, alistair23

On Mon, 29 Apr 2019 at 06:35, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  default-configs/arm-softmmu.mak    |   1 +
>  hw/misc/Kconfig                    |   3 +
>  hw/misc/Makefile.objs              |   1 +
>  hw/misc/stm32f4xx_syscfg.c         | 275 +++++++++++++++++++++++++++++
>  include/hw/misc/stm32f4xx_syscfg.h |  62 +++++++
>  5 files changed, 342 insertions(+)
>  create mode 100644 hw/misc/stm32f4xx_syscfg.c
>  create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +
> +#ifndef STM_SYSCFG_ERR_DEBUG
> +#define STM_SYSCFG_ERR_DEBUG 0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (STM_SYSCFG_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0)
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

I think we should prefer to use a tracepoint rather than qemu_log here.

> +
> +static void stm32f4xx_syscfg_reset(DeviceState *dev)
> +{
> +    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev);
> +
> +    s->syscfg_memrmp = 0x00000000;
> +    s->syscfg_pmc = 0x00000000;
> +    s->syscfg_exticr1 = 0x00000000;
> +    s->syscfg_exticr2 = 0x00000000;
> +    s->syscfg_exticr3 = 0x00000000;
> +    s->syscfg_exticr4 = 0x00000000;
> +    s->syscfg_cmpcr = 0x00000000;
> +}
> +
> +static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +    uint8_t config;
> +
> +    DB_PRINT("Interupt: GPIO: %d, Line: %d; Level: %d\n", irq / 16,
> +             irq % 16, level);
> +
> +    config = irq / 16;
> +
> +    switch (irq % 16) {
> +    case 0:
> +        if ((s->syscfg_exticr1 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[0], level);
> +            DB_PRINT("Pulse EXTI: 0\n");
> +        }
> +        break;
> +    case 1:
> +        if (((s->syscfg_exticr1 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[1], level);
> +            DB_PRINT("Pulse EXTI: 1\n");
> +        }
> +        break;

This seems all rather repetitive. If you use an
array syscfg_exticr[] rather than 4 separate fields you
can replace this whole switch with something like:

    int icrreg = irq / 4;
    int startbit = (irq & 3) * 4;
    if (extract32(s->syscfg_exticr[icrreg], startbit, 4) == config) {
       qemu_set_irq(s->gpio_out[irq], level);
       DB_PRINT("Pulse EXTI: %d\n", irq);
    }

> +    case 2:
> +        if (((s->syscfg_exticr1 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[2], level);
> +            DB_PRINT("Pulse EXTI: 2\n");
> +        }
> +        break;
> +    case 3:
> +        if (((s->syscfg_exticr1 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[3], level);
> +            DB_PRINT("Pulse EXTI: 3\n");
> +        }
> +        break;
> +    case 4:
> +        if ((s->syscfg_exticr2 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[4], level);
> +            DB_PRINT("Pulse EXTI: 4\n");
> +        }
> +        break;
> +    case 5:
> +        if (((s->syscfg_exticr2 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[5], level);
> +            DB_PRINT("Pulse EXTI: 5\n");
> +        }
> +        break;
> +    case 6:
> +        if (((s->syscfg_exticr2 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[6], level);
> +            DB_PRINT("Pulse EXTI: 6\n");
> +        }
> +        break;
> +    case 7:
> +        if (((s->syscfg_exticr2 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[7], level);
> +            DB_PRINT("Pulse EXTI: 7\n");
> +        }
> +        break;
> +    case 8:
> +        if ((s->syscfg_exticr3 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[8], level);
> +            DB_PRINT("Pulse EXTI: 8\n");
> +        }
> +        break;
> +    case 9:
> +        if (((s->syscfg_exticr3 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[9], level);
> +            DB_PRINT("Pulse EXTI: 9\n");
> +        }
> +        break;
> +    case 10:
> +        if (((s->syscfg_exticr3 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[10], level);
> +            DB_PRINT("Pulse EXTI: 10\n");
> +        }
> +        break;
> +    case 11:
> +        if (((s->syscfg_exticr3 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[11], level);
> +            DB_PRINT("Pulse EXTI: 11\n");
> +        }
> +        break;
> +    case 12:
> +        if ((s->syscfg_exticr4 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[12], level);
> +            DB_PRINT("Pulse EXTI: 12\n");
> +        }
> +        break;
> +    case 13:
> +        if (((s->syscfg_exticr4 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[13], level);
> +            DB_PRINT("Pulse EXTI: 13\n");
> +        }
> +        break;
> +    case 14:
> +        if (((s->syscfg_exticr4 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[14], level);
> +            DB_PRINT("Pulse EXTI: 14\n");
> +        }
> +        break;
> +    case 15:
> +        if (((s->syscfg_exticr4 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[15], level);
> +            DB_PRINT("Pulse EXTI: 15\n");
> +        }
> +        break;
> +    }
> +}
> +
> +static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr,
> +                                     unsigned int size)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +
> +    DB_PRINT("0x%"HWADDR_PRIx"\n", addr);
> +
> +    switch (addr) {
> +    case SYSCFG_MEMRMP:
> +        return s->syscfg_memrmp;
> +    case SYSCFG_PMC:
> +        return s->syscfg_pmc;
> +    case SYSCFG_EXTICR1:
> +        return s->syscfg_exticr1;
> +    case SYSCFG_EXTICR2:
> +        return s->syscfg_exticr2;
> +    case SYSCFG_EXTICR3:
> +        return s->syscfg_exticr3;
> +    case SYSCFG_EXTICR4:
> +        return s->syscfg_exticr4;
> +    case SYSCFG_CMPCR:
> +        return s->syscfg_cmpcr;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> +        return 0;
> +    }
> +
> +    return 0;

This return statement is unreachable.

> +}
> +
> +static void stm32f4xx_syscfg_write(void *opaque, hwaddr addr,
> +                       uint64_t val64, unsigned int size)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +    uint32_t value = val64;
> +
> +    DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr);
> +
> +    switch (addr) {
> +    case SYSCFG_MEMRMP:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: Changeing the memory mapping isn't supported " \
> +                      "in QEMU\n", __func__);
> +        return;
> +    case SYSCFG_PMC:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: Changeing the memory mapping isn't supported " \
> +                      "in QEMU\n", __func__);

"Changing" in both these.

> +        return;
> +    case SYSCFG_EXTICR1:
> +        s->syscfg_exticr1 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR2:
> +        s->syscfg_exticr2 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR3:
> +        s->syscfg_exticr3 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR4:
> +        s->syscfg_exticr4 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_CMPCR:
> +        s->syscfg_cmpcr = value;
> +        return;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> +    }
> +}
> +
> +static const MemoryRegionOps stm32f4xx_syscfg_ops = {
> +    .read = stm32f4xx_syscfg_read,
> +    .write = stm32f4xx_syscfg_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void stm32f4xx_syscfg_init(Object *obj)
> +{
> +    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(obj);
> +
> +    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
> +
> +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_syscfg_ops, s,
> +                          TYPE_STM32F4XX_SYSCFG, 0x400);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> +
> +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_syscfg_set_irq, 16 * 9);
> +    qdev_init_gpio_out(DEVICE(obj), s->gpio_out, 16);
> +}
> +
> +static void stm32f4xx_syscfg_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = stm32f4xx_syscfg_reset;

This is missing the vmstate for migration.

> +}
> +
> +static const TypeInfo stm32f4xx_syscfg_info = {
> +    .name          = TYPE_STM32F4XX_SYSCFG,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F4xxSyscfgState),
> +    .instance_init = stm32f4xx_syscfg_init,
> +    .class_init    = stm32f4xx_syscfg_class_init,
> +};
> +
> +static void stm32f4xx_syscfg_register_types(void)
> +{
> +    type_register_static(&stm32f4xx_syscfg_info);
> +}

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device
  2019-04-30 15:44   ` Peter Maydell
@ 2019-04-30 15:44     ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:44 UTC (permalink / raw)
  To: Alistair Francis; +Cc: alistair23, qemu-devel

On Mon, 29 Apr 2019 at 06:35, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  default-configs/arm-softmmu.mak    |   1 +
>  hw/misc/Kconfig                    |   3 +
>  hw/misc/Makefile.objs              |   1 +
>  hw/misc/stm32f4xx_syscfg.c         | 275 +++++++++++++++++++++++++++++
>  include/hw/misc/stm32f4xx_syscfg.h |  62 +++++++
>  5 files changed, 342 insertions(+)
>  create mode 100644 hw/misc/stm32f4xx_syscfg.c
>  create mode 100644 include/hw/misc/stm32f4xx_syscfg.h

> +
> +#include "qemu/osdep.h"
> +#include "qemu/log.h"
> +#include "hw/misc/stm32f4xx_syscfg.h"
> +
> +#ifndef STM_SYSCFG_ERR_DEBUG
> +#define STM_SYSCFG_ERR_DEBUG 0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (STM_SYSCFG_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0)
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

I think we should prefer to use a tracepoint rather than qemu_log here.

> +
> +static void stm32f4xx_syscfg_reset(DeviceState *dev)
> +{
> +    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(dev);
> +
> +    s->syscfg_memrmp = 0x00000000;
> +    s->syscfg_pmc = 0x00000000;
> +    s->syscfg_exticr1 = 0x00000000;
> +    s->syscfg_exticr2 = 0x00000000;
> +    s->syscfg_exticr3 = 0x00000000;
> +    s->syscfg_exticr4 = 0x00000000;
> +    s->syscfg_cmpcr = 0x00000000;
> +}
> +
> +static void stm32f4xx_syscfg_set_irq(void *opaque, int irq, int level)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +    uint8_t config;
> +
> +    DB_PRINT("Interupt: GPIO: %d, Line: %d; Level: %d\n", irq / 16,
> +             irq % 16, level);
> +
> +    config = irq / 16;
> +
> +    switch (irq % 16) {
> +    case 0:
> +        if ((s->syscfg_exticr1 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[0], level);
> +            DB_PRINT("Pulse EXTI: 0\n");
> +        }
> +        break;
> +    case 1:
> +        if (((s->syscfg_exticr1 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[1], level);
> +            DB_PRINT("Pulse EXTI: 1\n");
> +        }
> +        break;

This seems all rather repetitive. If you use an
array syscfg_exticr[] rather than 4 separate fields you
can replace this whole switch with something like:

    int icrreg = irq / 4;
    int startbit = (irq & 3) * 4;
    if (extract32(s->syscfg_exticr[icrreg], startbit, 4) == config) {
       qemu_set_irq(s->gpio_out[irq], level);
       DB_PRINT("Pulse EXTI: %d\n", irq);
    }

> +    case 2:
> +        if (((s->syscfg_exticr1 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[2], level);
> +            DB_PRINT("Pulse EXTI: 2\n");
> +        }
> +        break;
> +    case 3:
> +        if (((s->syscfg_exticr1 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[3], level);
> +            DB_PRINT("Pulse EXTI: 3\n");
> +        }
> +        break;
> +    case 4:
> +        if ((s->syscfg_exticr2 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[4], level);
> +            DB_PRINT("Pulse EXTI: 4\n");
> +        }
> +        break;
> +    case 5:
> +        if (((s->syscfg_exticr2 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[5], level);
> +            DB_PRINT("Pulse EXTI: 5\n");
> +        }
> +        break;
> +    case 6:
> +        if (((s->syscfg_exticr2 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[6], level);
> +            DB_PRINT("Pulse EXTI: 6\n");
> +        }
> +        break;
> +    case 7:
> +        if (((s->syscfg_exticr2 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[7], level);
> +            DB_PRINT("Pulse EXTI: 7\n");
> +        }
> +        break;
> +    case 8:
> +        if ((s->syscfg_exticr3 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[8], level);
> +            DB_PRINT("Pulse EXTI: 8\n");
> +        }
> +        break;
> +    case 9:
> +        if (((s->syscfg_exticr3 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[9], level);
> +            DB_PRINT("Pulse EXTI: 9\n");
> +        }
> +        break;
> +    case 10:
> +        if (((s->syscfg_exticr3 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[10], level);
> +            DB_PRINT("Pulse EXTI: 10\n");
> +        }
> +        break;
> +    case 11:
> +        if (((s->syscfg_exticr3 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[11], level);
> +            DB_PRINT("Pulse EXTI: 11\n");
> +        }
> +        break;
> +    case 12:
> +        if ((s->syscfg_exticr4 & 0xF) == config) {
> +            qemu_set_irq(s->gpio_out[12], level);
> +            DB_PRINT("Pulse EXTI: 12\n");
> +        }
> +        break;
> +    case 13:
> +        if (((s->syscfg_exticr4 & 0xF0) >> 4) == config) {
> +            qemu_set_irq(s->gpio_out[13], level);
> +            DB_PRINT("Pulse EXTI: 13\n");
> +        }
> +        break;
> +    case 14:
> +        if (((s->syscfg_exticr4 & 0xF00) >> 8) == config) {
> +            qemu_set_irq(s->gpio_out[14], level);
> +            DB_PRINT("Pulse EXTI: 14\n");
> +        }
> +        break;
> +    case 15:
> +        if (((s->syscfg_exticr4 & 0xF000) >> 12) == config) {
> +            qemu_set_irq(s->gpio_out[15], level);
> +            DB_PRINT("Pulse EXTI: 15\n");
> +        }
> +        break;
> +    }
> +}
> +
> +static uint64_t stm32f4xx_syscfg_read(void *opaque, hwaddr addr,
> +                                     unsigned int size)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +
> +    DB_PRINT("0x%"HWADDR_PRIx"\n", addr);
> +
> +    switch (addr) {
> +    case SYSCFG_MEMRMP:
> +        return s->syscfg_memrmp;
> +    case SYSCFG_PMC:
> +        return s->syscfg_pmc;
> +    case SYSCFG_EXTICR1:
> +        return s->syscfg_exticr1;
> +    case SYSCFG_EXTICR2:
> +        return s->syscfg_exticr2;
> +    case SYSCFG_EXTICR3:
> +        return s->syscfg_exticr3;
> +    case SYSCFG_EXTICR4:
> +        return s->syscfg_exticr4;
> +    case SYSCFG_CMPCR:
> +        return s->syscfg_cmpcr;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> +        return 0;
> +    }
> +
> +    return 0;

This return statement is unreachable.

> +}
> +
> +static void stm32f4xx_syscfg_write(void *opaque, hwaddr addr,
> +                       uint64_t val64, unsigned int size)
> +{
> +    STM32F4xxSyscfgState *s = opaque;
> +    uint32_t value = val64;
> +
> +    DB_PRINT("0x%x, 0x%"HWADDR_PRIx"\n", value, addr);
> +
> +    switch (addr) {
> +    case SYSCFG_MEMRMP:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: Changeing the memory mapping isn't supported " \
> +                      "in QEMU\n", __func__);
> +        return;
> +    case SYSCFG_PMC:
> +        qemu_log_mask(LOG_UNIMP,
> +                      "%s: Changeing the memory mapping isn't supported " \
> +                      "in QEMU\n", __func__);

"Changing" in both these.

> +        return;
> +    case SYSCFG_EXTICR1:
> +        s->syscfg_exticr1 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR2:
> +        s->syscfg_exticr2 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR3:
> +        s->syscfg_exticr3 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_EXTICR4:
> +        s->syscfg_exticr4 = (value & 0xFFFF);
> +        return;
> +    case SYSCFG_CMPCR:
> +        s->syscfg_cmpcr = value;
> +        return;
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
> +    }
> +}
> +
> +static const MemoryRegionOps stm32f4xx_syscfg_ops = {
> +    .read = stm32f4xx_syscfg_read,
> +    .write = stm32f4xx_syscfg_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static void stm32f4xx_syscfg_init(Object *obj)
> +{
> +    STM32F4xxSyscfgState *s = STM32F4XX_SYSCFG(obj);
> +
> +    sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
> +
> +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_syscfg_ops, s,
> +                          TYPE_STM32F4XX_SYSCFG, 0x400);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> +
> +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_syscfg_set_irq, 16 * 9);
> +    qdev_init_gpio_out(DEVICE(obj), s->gpio_out, 16);
> +}
> +
> +static void stm32f4xx_syscfg_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = stm32f4xx_syscfg_reset;

This is missing the vmstate for migration.

> +}
> +
> +static const TypeInfo stm32f4xx_syscfg_info = {
> +    .name          = TYPE_STM32F4XX_SYSCFG,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F4xxSyscfgState),
> +    .instance_init = stm32f4xx_syscfg_init,
> +    .class_init    = stm32f4xx_syscfg_class_init,
> +};
> +
> +static void stm32f4xx_syscfg_register_types(void)
> +{
> +    type_register_static(&stm32f4xx_syscfg_info);
> +}

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
@ 2019-04-30 15:48   ` Peter Maydell
  2019-04-30 15:48     ` Peter Maydell
  2019-05-02  4:28     ` Alistair Francis
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:48 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, alistair23

On Mon, 29 Apr 2019 at 06:37, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  default-configs/arm-softmmu.mak  |   1 +
>  hw/misc/Kconfig                  |   3 +
>  hw/misc/Makefile.objs            |   1 +
>  hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
>  include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
>  5 files changed, 237 insertions(+)
>  create mode 100644 hw/misc/stm32f4xx_exti.c
>  create mode 100644 include/hw/misc/stm32f4xx_exti.h

Minor comments here only.

(If Thomas's kconfig patchset gets into master before this
there might be some minor fixups required to the kconfig
stuff, but it shouldn't be too hard to adapt.)

> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/log.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +
> +#ifndef STM_EXTI_ERR_DEBUG
> +#define STM_EXTI_ERR_DEBUG 0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (STM_EXTI_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0)
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

Could we use a tracepoint instead?

> +
> +#define NUM_GPIO_EVENT_IN_LINES 16
> +#define NUM_INTERRUPT_OUT_LINES 16
> +
> +static void stm32f4xx_exti_reset(DeviceState *dev)
> +{
> +    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
> +
> +    s->exti_imr = 0x00000000;
> +    s->exti_emr = 0x00000000;
> +    s->exti_rtsr = 0x00000000;
> +    s->exti_ftsr = 0x00000000;
> +    s->exti_swier = 0x00000000;
> +    s->exti_pr = 0x00000000;
> +}
> +
> +static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
> +{
> +    STM32F4xxExtiState *s = opaque;
> +
> +    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
> +
> +    if (level) {
> +        qemu_irq_pulse(s->irq[irq]);
> +        s->exti_pr |= 1 << irq;
> +    }
> +}

Just to check -- this should definitely be a pulse? I'm always
a little bit wary of uses of qemu_irq_pulse(), though some
hardware does pulse IRQ lines rather than holding them until
dismissed.

> +static void stm32f4xx_exti_init(Object *obj)
> +{
> +    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
> +    int i;
> +
> +    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);

You could just have the array be inline in the
STM32F4xxExtiState rather than allocating it separately,
right?

> +    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
> +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
> +    }
> +
> +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
> +                          TYPE_STM32F4XX_EXTI, 0x400);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> +
> +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
> +                      NUM_GPIO_EVENT_IN_LINES);
> +}
> +
> +static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = stm32f4xx_exti_reset;

This one's missing vmstate too.

> +}
> +
> +static const TypeInfo stm32f4xx_exti_info = {
> +    .name          = TYPE_STM32F4XX_EXTI,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F4xxExtiState),
> +    .instance_init = stm32f4xx_exti_init,
> +    .class_init    = stm32f4xx_exti_class_init,
> +};
> +
> +static void stm32f4xx_exti_register_types(void)
> +{
> +    type_register_static(&stm32f4xx_exti_info);
> +}
> +

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
  2019-04-30 15:48   ` Peter Maydell
@ 2019-04-30 15:48     ` Peter Maydell
  2019-05-02  4:28     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:48 UTC (permalink / raw)
  To: Alistair Francis; +Cc: alistair23, qemu-devel

On Mon, 29 Apr 2019 at 06:37, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  default-configs/arm-softmmu.mak  |   1 +
>  hw/misc/Kconfig                  |   3 +
>  hw/misc/Makefile.objs            |   1 +
>  hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
>  include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
>  5 files changed, 237 insertions(+)
>  create mode 100644 hw/misc/stm32f4xx_exti.c
>  create mode 100644 include/hw/misc/stm32f4xx_exti.h

Minor comments here only.

(If Thomas's kconfig patchset gets into master before this
there might be some minor fixups required to the kconfig
stuff, but it shouldn't be too hard to adapt.)

> +#include "qemu/osdep.h"
> +#include "hw/sysbus.h"
> +#include "qemu/log.h"
> +#include "hw/misc/stm32f4xx_exti.h"
> +
> +#ifndef STM_EXTI_ERR_DEBUG
> +#define STM_EXTI_ERR_DEBUG 0
> +#endif
> +
> +#define DB_PRINT_L(lvl, fmt, args...) do { \
> +    if (STM_EXTI_ERR_DEBUG >= lvl) { \
> +        qemu_log("%s: " fmt, __func__, ## args); \
> +    } \
> +} while (0)
> +
> +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)

Could we use a tracepoint instead?

> +
> +#define NUM_GPIO_EVENT_IN_LINES 16
> +#define NUM_INTERRUPT_OUT_LINES 16
> +
> +static void stm32f4xx_exti_reset(DeviceState *dev)
> +{
> +    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
> +
> +    s->exti_imr = 0x00000000;
> +    s->exti_emr = 0x00000000;
> +    s->exti_rtsr = 0x00000000;
> +    s->exti_ftsr = 0x00000000;
> +    s->exti_swier = 0x00000000;
> +    s->exti_pr = 0x00000000;
> +}
> +
> +static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
> +{
> +    STM32F4xxExtiState *s = opaque;
> +
> +    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
> +
> +    if (level) {
> +        qemu_irq_pulse(s->irq[irq]);
> +        s->exti_pr |= 1 << irq;
> +    }
> +}

Just to check -- this should definitely be a pulse? I'm always
a little bit wary of uses of qemu_irq_pulse(), though some
hardware does pulse IRQ lines rather than holding them until
dismissed.

> +static void stm32f4xx_exti_init(Object *obj)
> +{
> +    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
> +    int i;
> +
> +    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);

You could just have the array be inline in the
STM32F4xxExtiState rather than allocating it separately,
right?

> +    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
> +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
> +    }
> +
> +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
> +                          TYPE_STM32F4XX_EXTI, 0x400);
> +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> +
> +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
> +                      NUM_GPIO_EVENT_IN_LINES);
> +}
> +
> +static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->reset = stm32f4xx_exti_reset;

This one's missing vmstate too.

> +}
> +
> +static const TypeInfo stm32f4xx_exti_info = {
> +    .name          = TYPE_STM32F4XX_EXTI,
> +    .parent        = TYPE_SYS_BUS_DEVICE,
> +    .instance_size = sizeof(STM32F4xxExtiState),
> +    .instance_init = stm32f4xx_exti_init,
> +    .class_init    = stm32f4xx_exti_class_init,
> +};
> +
> +static void stm32f4xx_exti_register_types(void)
> +{
> +    type_register_static(&stm32f4xx_exti_info);
> +}
> +

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 17:01     ` Alistair Francis
  2019-04-29 17:01       ` Alistair Francis
@ 2019-04-30 15:51       ` Peter Maydell
  2019-04-30 15:51         ` Peter Maydell
  1 sibling, 1 reply; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:51 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Philippe Mathieu-Daudé, Alistair Francis, qemu-devel

On Mon, 29 Apr 2019 at 18:30, Alistair Francis <alistair23@gmail.com> wrote:
>
> On Mon, Apr 29, 2019 at 5:43 AM Philippe Mathieu-Daudé
> <philmd@redhat.com> wrote:
> >
> > On 4/29/19 7:33 AM, Alistair Francis wrote:
> > > --- /dev/null
> > > +++ b/hw/arm/stm32f405_soc.c
> > > @@ -0,0 +1,292 @@
> > > +/*
> > > + * STM32F405 SoC
> > > + *
> > > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> >
> > 2019?
>
> I never know how this works. It was originally written in 2014, do I
> update the year based on the upstream submission?

You could say "2014, 2019" if you like; or just use the date of
original authorship.

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-30 15:51       ` Peter Maydell
@ 2019-04-30 15:51         ` Peter Maydell
  0 siblings, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:51 UTC (permalink / raw)
  To: Alistair Francis
  Cc: Alistair Francis, Philippe Mathieu-Daudé, qemu-devel

On Mon, 29 Apr 2019 at 18:30, Alistair Francis <alistair23@gmail.com> wrote:
>
> On Mon, Apr 29, 2019 at 5:43 AM Philippe Mathieu-Daudé
> <philmd@redhat.com> wrote:
> >
> > On 4/29/19 7:33 AM, Alistair Francis wrote:
> > > --- /dev/null
> > > +++ b/hw/arm/stm32f405_soc.c
> > > @@ -0,0 +1,292 @@
> > > +/*
> > > + * STM32F405 SoC
> > > + *
> > > + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
> >
> > 2019?
>
> I never know how this works. It was originally written in 2014, do I
> update the year based on the upstream submission?

You could say "2014, 2019" if you like; or just use the date of
original authorship.

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
                     ` (2 preceding siblings ...)
  2019-04-29 12:43   ` Philippe Mathieu-Daudé
@ 2019-04-30 15:59   ` Peter Maydell
  2019-04-30 15:59     ` Peter Maydell
  2019-05-02  5:04     ` Alistair Francis
  3 siblings, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:59 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, alistair23

On Mon, 29 Apr 2019 at 06:38, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |   8 +
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Kconfig                  |   3 +
>  hw/arm/Makefile.objs            |   1 +
>  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>  6 files changed, 375 insertions(+)
>  create mode 100644 hw/arm/stm32f405_soc.c
>  create mode 100644 include/hw/arm/stm32f405_soc.h

Looks good; a few minor things below.

> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));

It would be more in keeping with the style of the rest of this
device to have the device be inline in the STM32F405State
struct and initialized with object_initialize_child() rather
than allocated separately with object_new(). (hw/arm/armsse.c
has an example of doing this with a TYPE_OR_IRQ object.)

> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);

I would prefer to have these MemoryRegions be in the STM32F405State
struct rather than separately allocated.

> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);

Better to pass the error back up via errp rather than use error_fatal
in a realize function.

> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),

You could use OBJECT(system_memory) rather than calling
get_system_memory() again.

> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;

A comment here "No vmstate or reset required: device has no internal state"
would help indicate that dc->vmsd and dc->reset have not merely
been forgotten.

(Eventually I might actually write a patch to let us express
in code "dc->vmsd = device_has_no_state;"...)

> +}

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-30 15:59   ` Peter Maydell
@ 2019-04-30 15:59     ` Peter Maydell
  2019-05-02  5:04     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 15:59 UTC (permalink / raw)
  To: Alistair Francis; +Cc: alistair23, qemu-devel

On Mon, 29 Apr 2019 at 06:38, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |   8 +
>  default-configs/arm-softmmu.mak |   1 +
>  hw/arm/Kconfig                  |   3 +
>  hw/arm/Makefile.objs            |   1 +
>  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>  6 files changed, 375 insertions(+)
>  create mode 100644 hw/arm/stm32f405_soc.c
>  create mode 100644 include/hw/arm/stm32f405_soc.h

Looks good; a few minor things below.

> +static void stm32f405_soc_initfn(Object *obj)
> +{
> +    STM32F405State *s = STM32F405_SOC(obj);
> +    int i;
> +
> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> +                          TYPE_ARMV7M);
> +
> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> +                          TYPE_STM32F4XX_SYSCFG);
> +
> +    for (i = 0; i < STM_NUM_USARTS; i++) {
> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> +    }
> +
> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> +    }
> +
> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));

It would be more in keeping with the style of the rest of this
device to have the device be inline in the STM32F405State
struct and initialized with object_initialize_child() rather
than allocated separately with object_new(). (hw/arm/armsse.c
has an example of doing this with a TYPE_OR_IRQ object.)

> +
> +    for (i = 0; i < STM_NUM_ADCS; i++) {
> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> +                              TYPE_STM32F2XX_ADC);
> +    }
> +
> +    for (i = 0; i < STM_NUM_SPIS; i++) {
> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> +                              TYPE_STM32F2XX_SPI);
> +    }
> +
> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> +                          TYPE_STM32F4XX_EXTI);
> +}
> +
> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> +{
> +    STM32F405State *s = STM32F405_SOC(dev_soc);
> +    DeviceState *dev, *armv7m;
> +    SysBusDevice *busdev;
> +    Error *err = NULL;
> +    int i;
> +
> +    MemoryRegion *system_memory = get_system_memory();
> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);

I would prefer to have these MemoryRegions be in the STM32F405State
struct rather than separately allocated.

> +
> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> +                           &error_fatal);

Better to pass the error back up via errp rather than use error_fatal
in a realize function.

> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> +                             flash, 0, FLASH_SIZE);
> +
> +    memory_region_set_readonly(flash, true);
> +    memory_region_set_readonly(flash_alias, true);
> +
> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> +    memory_region_add_subregion(system_memory, 0, flash_alias);
> +
> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> +                           &error_fatal);
> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> +
> +    armv7m = DEVICE(&s->armv7m);
> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),

You could use OBJECT(system_memory) rather than calling
get_system_memory() again.

> +static Property stm32f405_soc_properties[] = {
> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> +    DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +
> +    dc->realize = stm32f405_soc_realize;
> +    dc->props = stm32f405_soc_properties;

A comment here "No vmstate or reset required: device has no internal state"
would help indicate that dc->vmsd and dc->reset have not merely
been forgotten.

(Eventually I might actually write a patch to let us express
in code "dc->vmsd = device_has_no_state;"...)

> +}

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2 Alistair Francis
  2019-04-29  5:33   ` Alistair Francis
@ 2019-04-30 16:01   ` Peter Maydell
  2019-04-30 16:01     ` Peter Maydell
  2019-04-30 20:27     ` Alistair Francis
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 16:01 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, alistair23

On Mon, 29 Apr 2019 at 06:39, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |  6 +++
>  default-configs/arm-softmmu.mak |  1 +
>  hw/arm/Kconfig                  |  3 ++
>  hw/arm/Makefile.objs            |  1 +
>  hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
>  5 files changed, 88 insertions(+)
>  create mode 100644 hw/arm/netduinoplus2.c
>

> +typedef struct ARMV7MResetArgs {
> +    ARMCPU *cpu;
> +    uint32_t reset_sp;
> +    uint32_t reset_pc;
> +} ARMV7MResetArgs;
> +
> +static void armv7m_reset(void *opaque)
> +{
> +    ARMV7MResetArgs *args = opaque;
> +
> +    cpu_reset(CPU(args->cpu));
> +
> +    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
> +    args->cpu->env.thumb = args->reset_pc & 1;
> +    args->cpu->env.regs[15] = args->reset_pc & ~1;
> +}
> +
> +static void netduinoplus2_init(MachineState *machine)
> +{
> +    DeviceState *dev;
> +    ARMV7MResetArgs reset_args;
> +    uint64_t entry;
> +
> +    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
> +    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
> +    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> +
> +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> +                       FLASH_SIZE, &entry);
> +
> +    reset_args = (ARMV7MResetArgs) {
> +        .cpu = ARM_CPU(first_cpu),
> +        .reset_pc = entry,
> +        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
> +    };
> +    qemu_register_reset(armv7m_reset,
> +                        g_memdup(&reset_args, sizeof(reset_args)));
> +}

Can you explain the purpose of the reset code? None of the other
v7m boards seem to need to do a manual qemu_register_reset().

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-30 16:01   ` Peter Maydell
@ 2019-04-30 16:01     ` Peter Maydell
  2019-04-30 20:27     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 16:01 UTC (permalink / raw)
  To: Alistair Francis; +Cc: alistair23, qemu-devel

On Mon, 29 Apr 2019 at 06:39, Alistair Francis <alistair@alistair23.me> wrote:
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  MAINTAINERS                     |  6 +++
>  default-configs/arm-softmmu.mak |  1 +
>  hw/arm/Kconfig                  |  3 ++
>  hw/arm/Makefile.objs            |  1 +
>  hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
>  5 files changed, 88 insertions(+)
>  create mode 100644 hw/arm/netduinoplus2.c
>

> +typedef struct ARMV7MResetArgs {
> +    ARMCPU *cpu;
> +    uint32_t reset_sp;
> +    uint32_t reset_pc;
> +} ARMV7MResetArgs;
> +
> +static void armv7m_reset(void *opaque)
> +{
> +    ARMV7MResetArgs *args = opaque;
> +
> +    cpu_reset(CPU(args->cpu));
> +
> +    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
> +    args->cpu->env.thumb = args->reset_pc & 1;
> +    args->cpu->env.regs[15] = args->reset_pc & ~1;
> +}
> +
> +static void netduinoplus2_init(MachineState *machine)
> +{
> +    DeviceState *dev;
> +    ARMV7MResetArgs reset_args;
> +    uint64_t entry;
> +
> +    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
> +    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
> +    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> +
> +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> +                       FLASH_SIZE, &entry);
> +
> +    reset_args = (ARMV7MResetArgs) {
> +        .cpu = ARM_CPU(first_cpu),
> +        .reset_pc = entry,
> +        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
> +    };
> +    qemu_register_reset(armv7m_reset,
> +                        g_memdup(&reset_args, sizeof(reset_args)));
> +}

Can you explain the purpose of the reset code? None of the other
v7m boards seem to need to do a manual qemu_register_reset().

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-04-29  5:32 ` Alistair Francis
  2019-04-29  5:32   ` Alistair Francis
@ 2019-04-30 16:04   ` Peter Maydell
  2019-04-30 16:04     ` Peter Maydell
  2019-05-01  3:54     ` Alistair Francis
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 16:04 UTC (permalink / raw)
  To: Alistair Francis; +Cc: qemu-devel, alistair23

On Mon, 29 Apr 2019 at 06:34, Alistair Francis <alistair@alistair23.me> wrote:
>
> Allow the kernel's entry point information to be returned when loading a
> kernel.
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  hw/arm/armv7m.c      | 6 +++---
>  hw/arm/microbit.c    | 2 +-
>  hw/arm/mps2-tz.c     | 3 ++-
>  hw/arm/mps2.c        | 2 +-
>  hw/arm/msf2-som.c    | 2 +-
>  hw/arm/musca.c       | 3 ++-
>  hw/arm/netduino2.c   | 2 +-
>  hw/arm/stellaris.c   | 3 ++-
>  include/hw/arm/arm.h | 4 +++-
>  9 files changed, 16 insertions(+), 11 deletions(-)

> -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
> +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
> +                        uint64_t *entry)

If we need to return the entry point, why not just return it
as the return value of the function rather than having the
caller pass in a pointer which we fill in ?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-04-30 16:04   ` Peter Maydell
@ 2019-04-30 16:04     ` Peter Maydell
  2019-05-01  3:54     ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-04-30 16:04 UTC (permalink / raw)
  To: Alistair Francis; +Cc: alistair23, qemu-devel

On Mon, 29 Apr 2019 at 06:34, Alistair Francis <alistair@alistair23.me> wrote:
>
> Allow the kernel's entry point information to be returned when loading a
> kernel.
>
> Signed-off-by: Alistair Francis <alistair@alistair23.me>
> ---
>  hw/arm/armv7m.c      | 6 +++---
>  hw/arm/microbit.c    | 2 +-
>  hw/arm/mps2-tz.c     | 3 ++-
>  hw/arm/mps2.c        | 2 +-
>  hw/arm/msf2-som.c    | 2 +-
>  hw/arm/musca.c       | 3 ++-
>  hw/arm/netduino2.c   | 2 +-
>  hw/arm/stellaris.c   | 3 ++-
>  include/hw/arm/arm.h | 4 +++-
>  9 files changed, 16 insertions(+), 11 deletions(-)

> -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
> +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
> +                        uint64_t *entry)

If we need to return the entry point, why not just return it
as the return value of the function rather than having the
caller pass in a pointer which we fill in ?

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-29 17:00     ` Alistair Francis
  2019-04-29 17:00       ` Alistair Francis
@ 2019-04-30 18:10       ` KONRAD Frederic
  2019-04-30 18:10         ` KONRAD Frederic
  1 sibling, 1 reply; 51+ messages in thread
From: KONRAD Frederic @ 2019-04-30 18:10 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair Francis, qemu-devel



Le 4/29/19 à 7:00 PM, Alistair Francis a écrit :
>   On Mon, Apr 29, 2019 at 5:38 AM KONRAD Frederic
> <frederic.konrad@adacore.com> wrote:
>>
>> Hi Alistair,
>>
>> Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
>>> Signed-off-by: Alistair Francis <alistair@alistair23.me>
>>> ---
>>>    MAINTAINERS                     |   8 +
>>>    default-configs/arm-softmmu.mak |   1 +
>>>    hw/arm/Kconfig                  |   3 +
>>>    hw/arm/Makefile.objs            |   1 +
>>>    hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>>>    include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>>>    6 files changed, 375 insertions(+)
>>>    create mode 100644 hw/arm/stm32f405_soc.c
>>>    create mode 100644 include/hw/arm/stm32f405_soc.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index dabbfccf9c..c9772735cf 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -803,6 +803,14 @@ F: hw/adc/*
>>>    F: hw/ssi/stm32f2xx_spi.c
>>>    F: include/hw/*/stm32*.h
>>>
>>> +STM32F405
>>> +M: Alistair Francis <alistair@alistair23.me>
>>> +M: Peter Maydell <peter.maydell@linaro.org>
>>> +S: Maintained
>>> +F: hw/arm/stm32f405_soc.c
>>> +F: hw/misc/stm32f4xx_syscfg.c
>>> +F: hw/misc/stm32f4xx_exti.c
>>> +
>>>    Netduino 2
>>>    M: Alistair Francis <alistair@alistair23.me>
>>>    M: Peter Maydell <peter.maydell@linaro.org>
>>> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
>>> index 8eb57de211..e079f10624 100644
>>> --- a/default-configs/arm-softmmu.mak
>>> +++ b/default-configs/arm-softmmu.mak
>>> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>>>    CONFIG_STM32F205_SOC=y
>>>    CONFIG_STM32F4XX_SYSCFG=y
>>>    CONFIG_STM32F4XX_EXTI=y
>>> +CONFIG_STM32F405_SOC=y
>>
>> Why not using 4xx instead of 405 in this patch as well?
> 
> I'm not sure if all the SoC variants are generic like that. Looking at
> the datasheet https://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf
> it only specified the 405 and 407 variants. This is mostly a way just
> to say that I have tested it as a 405, it might work with others but I
> don't know. I think it's harder to make the SoC generic without having
> tested the other optinos (or knowing they are all interchangable).

Ok makes sense.

I was wondering because you pass a cpu_type property and your commit message
mention "STM32F4xx".

> 
> Alistair
> 
>>
>>>    CONFIG_NRF51_SOC=y
>>>
>>>    CONFIG_CMSDK_APB_TIMER=y
>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>> index d298fbdc89..3a98bce15a 100644
>>> --- a/hw/arm/Kconfig
>>> +++ b/hw/arm/Kconfig
>>> @@ -62,6 +62,9 @@ config RASPI
>>>    config STM32F205_SOC
>>>        bool
>>>
>>> +config STM32F405_SOC
>>> +    bool
>>> +
>>>    config XLNX_ZYNQMP_ARM
>>>        bool
>>>
>>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>>> index fa57c7c770..36c3ff54c3 100644
>>> --- a/hw/arm/Makefile.objs
>>> +++ b/hw/arm/Makefile.objs
>>> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>>>    obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>>>    obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>>>    obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
>>> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>>>    obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>>>    obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>>>    obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
>>> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
>>> new file mode 100644
>>> index 0000000000..83adec51a2
>>> --- /dev/null
>>> +++ b/hw/arm/stm32f405_soc.c
>>> @@ -0,0 +1,292 @@
>>> +/*
>>> + * STM32F405 SoC
>>> + *
>>> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>> + * of this software and associated documentation files (the "Software"), to deal
>>> + * in the Software without restriction, including without limitation the rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "qapi/error.h"
>>> +#include "qemu-common.h"
>>> +#include "hw/arm/arm.h"
>>> +#include "exec/address-spaces.h"
>>> +#include "hw/arm/stm32f405_soc.h"
>>> +#include "hw/misc/unimp.h"
>>> +
>>> +#define SYSCFG_ADD                     0x40013800
>>> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
>>> +                                       0x40004C00, 0x40005000, 0x40011400,
>>> +                                       0x40007800, 0x40007C00 };
>>> +/* At the moment only Timer 2 to 5 are modelled */
>>> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
>>> +                                       0x40000800, 0x40000C00 };
>>> +#define ADC_ADDR                       0x40012000
>>> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
>>> +                                       0x40013400, 0x40015000, 0x40015400 };
>>> +#define EXTI_ADDR                      0x40013C00
>>> +
>>> +#define SYSCFG_IRQ               71
>>> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
>>> +static const int timer_irq[] = { 28, 29, 30, 50 };
>>> +#define ADC_IRQ 18
>>> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
>>> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
>>> +                                 40, 40, 40, 40, 40} ;
>>> +
>>> +
>>> +static void stm32f405_soc_initfn(Object *obj)
>>> +{
>>> +    STM32F405State *s = STM32F405_SOC(obj);
>>> +    int i;
>>> +
>>> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
>>> +                          TYPE_ARMV7M);
>>> +
>>> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
>>> +                          TYPE_STM32F4XX_SYSCFG);
>>> +
>>> +    for (i = 0; i < STM_NUM_USARTS; i++) {
>>> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
>>> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
>>> +    }
>>> +
>>> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
>>> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
>>> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
>>> +    }
>>> +
>>> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
>>> +
>>> +    for (i = 0; i < STM_NUM_ADCS; i++) {
>>> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
>>> +                              TYPE_STM32F2XX_ADC);
>>> +    }
>>> +
>>> +    for (i = 0; i < STM_NUM_SPIS; i++) {
>>> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
>>> +                              TYPE_STM32F2XX_SPI);
>>> +    }
>>> +
>>> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
>>> +                          TYPE_STM32F4XX_EXTI);
>>> +}
>>> +
>>> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
>>> +{
>>> +    STM32F405State *s = STM32F405_SOC(dev_soc);
>>> +    DeviceState *dev, *armv7m;
>>> +    SysBusDevice *busdev;
>>> +    Error *err = NULL;
>>> +    int i;
>>> +
>>> +    MemoryRegion *system_memory = get_system_memory();
>>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>>> +
>>> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
>>> +                           &error_fatal);
>>> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
>>> +                             flash, 0, FLASH_SIZE);
>>> +
>>> +    memory_region_set_readonly(flash, true);
>>> +    memory_region_set_readonly(flash_alias, true);
>>> +
>>> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
>>> +    memory_region_add_subregion(system_memory, 0, flash_alias);
>>> +
>>> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
>>> +                           &error_fatal);
>>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
>>> +
>>> +    armv7m = DEVICE(&s->armv7m);
>>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
>>> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
>>> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
>>> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
>>> +                                     "memory", &error_abort);
>>> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +
>>> +    /* System configuration controller */
>>> +    dev = DEVICE(&s->syscfg);
>>> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
>>> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
>>> +
>>> +    /* Attach UART (uses USART registers) and USART controllers */
>>> +    for (i = 0; i < STM_NUM_USARTS; i++) {
>>> +        dev = DEVICE(&(s->usart[i]));
>>> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
>>> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
>>> +    }
>>> +
>>> +    /* Timer 2 to 5 */
>>> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
>>> +        dev = DEVICE(&(s->timer[i]));
>>> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
>>> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
>>> +    }
>>> +
>>> +    /* ADC device, the IRQs are ORed together */
>>> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
>>> +                            "num-lines", &err);
>>> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
>>> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
>>> +
>>> +    dev = DEVICE(&(s->adc[i]));
>>> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
>>> +    sysbus_connect_irq(busdev, 0,
>>> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
>>> +
>>> +    /* SPI devices */
>>> +    for (i = 0; i < STM_NUM_SPIS; i++) {
>>> +        dev = DEVICE(&(s->spi[i]));
>>> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
>>> +    }
>>> +
>>> +    /* EXTI device */
>>> +    dev = DEVICE(&s->exti);
>>> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
>>> +    for (i = 0; i < 16; i++) {
>>> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
>>> +    }
>>> +    for (i = 0; i < 16; i++) {
>>> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
>>> +    }
>>> +
>>> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
>>> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
>>> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
>>> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
>>> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
>>> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
>>> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
>>> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
>>> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
>>> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
>>> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
>>> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
>>> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
>>> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
>>> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
>>> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
>>> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
>>> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
>>> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
>>> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
>>> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
>>> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
>>> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
>>> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
>>> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
>>> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
>>> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
>>> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
>>> +}
>>> +
>>> +static Property stm32f405_soc_properties[] = {
>>> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
>>> +    DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +
>>> +    dc->realize = stm32f405_soc_realize;
>>> +    dc->props = stm32f405_soc_properties;
>>> +}
>>> +
>>> +static const TypeInfo stm32f405_soc_info = {
>>> +    .name          = TYPE_STM32F405_SOC,
>>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size = sizeof(STM32F405State),
>>> +    .instance_init = stm32f405_soc_initfn,
>>> +    .class_init    = stm32f405_soc_class_init,
>>> +};
>>> +
>>> +static void stm32f405_soc_types(void)
>>> +{
>>> +    type_register_static(&stm32f405_soc_info);
>>> +}
>>> +
>>> +type_init(stm32f405_soc_types)
>>> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
>>> new file mode 100644
>>> index 0000000000..f0aec53d32
>>> --- /dev/null
>>> +++ b/include/hw/arm/stm32f405_soc.h
>>> @@ -0,0 +1,70 @@
>>> +/*
>>> + * STM32F405 SoC
>>> + *
>>> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>> + * of this software and associated documentation files (the "Software"), to deal
>>> + * in the Software without restriction, including without limitation the rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#ifndef HW_ARM_STM32F405_SOC_H
>>> +#define HW_ARM_STM32F405_SOC_H
>>> +
>>> +#include "hw/misc/stm32f4xx_syscfg.h"
>>> +#include "hw/timer/stm32f2xx_timer.h"
>>> +#include "hw/char/stm32f2xx_usart.h"
>>> +#include "hw/adc/stm32f2xx_adc.h"
>>> +#include "hw/misc/stm32f4xx_exti.h"
>>> +#include "hw/or-irq.h"
>>> +#include "hw/ssi/stm32f2xx_spi.h"
>>> +#include "hw/arm/armv7m.h"
>>> +
>>> +#define TYPE_STM32F405_SOC "stm32f405-soc"
>>> +#define STM32F405_SOC(obj) \
>>> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
>>> +
>>> +#define STM_NUM_USARTS 7
>>> +#define STM_NUM_TIMERS 4
>>> +#define STM_NUM_ADCS 6
>>> +#define STM_NUM_SPIS 6
>>> +
>>> +#define FLASH_BASE_ADDRESS 0x08000000
>>> +#define FLASH_SIZE (1024 * 1024)
>>> +#define SRAM_BASE_ADDRESS 0x20000000
>>> +#define SRAM_SIZE (192 * 1024)
>>> +
>>> +typedef struct STM32F405State {
>>> +    /*< private >*/
>>> +    SysBusDevice parent_obj;
>>> +    /*< public >*/
>>> +
>>> +    char *cpu_type;
>>> +
>>> +    ARMv7MState armv7m;
>>> +
>>> +    STM32F4xxSyscfgState syscfg;
>>> +    STM32F4xxExtiState exti;
>>> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
>>> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
>>> +    STM32F2XXADCState adc[STM_NUM_ADCS];
>>> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
>>> +
>>> +    qemu_or_irq *adc_irqs;
>>> +} STM32F405State;
>>> +
>>> +#endif
>>>

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-30 18:10       ` KONRAD Frederic
@ 2019-04-30 18:10         ` KONRAD Frederic
  0 siblings, 0 replies; 51+ messages in thread
From: KONRAD Frederic @ 2019-04-30 18:10 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair Francis, qemu-devel



Le 4/29/19 à 7:00 PM, Alistair Francis a écrit :
>   On Mon, Apr 29, 2019 at 5:38 AM KONRAD Frederic
> <frederic.konrad@adacore.com> wrote:
>>
>> Hi Alistair,
>>
>> Le 4/29/19 à 7:33 AM, Alistair Francis a écrit :
>>> Signed-off-by: Alistair Francis <alistair@alistair23.me>
>>> ---
>>>    MAINTAINERS                     |   8 +
>>>    default-configs/arm-softmmu.mak |   1 +
>>>    hw/arm/Kconfig                  |   3 +
>>>    hw/arm/Makefile.objs            |   1 +
>>>    hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
>>>    include/hw/arm/stm32f405_soc.h  |  70 ++++++++
>>>    6 files changed, 375 insertions(+)
>>>    create mode 100644 hw/arm/stm32f405_soc.c
>>>    create mode 100644 include/hw/arm/stm32f405_soc.h
>>>
>>> diff --git a/MAINTAINERS b/MAINTAINERS
>>> index dabbfccf9c..c9772735cf 100644
>>> --- a/MAINTAINERS
>>> +++ b/MAINTAINERS
>>> @@ -803,6 +803,14 @@ F: hw/adc/*
>>>    F: hw/ssi/stm32f2xx_spi.c
>>>    F: include/hw/*/stm32*.h
>>>
>>> +STM32F405
>>> +M: Alistair Francis <alistair@alistair23.me>
>>> +M: Peter Maydell <peter.maydell@linaro.org>
>>> +S: Maintained
>>> +F: hw/arm/stm32f405_soc.c
>>> +F: hw/misc/stm32f4xx_syscfg.c
>>> +F: hw/misc/stm32f4xx_exti.c
>>> +
>>>    Netduino 2
>>>    M: Alistair Francis <alistair@alistair23.me>
>>>    M: Peter Maydell <peter.maydell@linaro.org>
>>> diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
>>> index 8eb57de211..e079f10624 100644
>>> --- a/default-configs/arm-softmmu.mak
>>> +++ b/default-configs/arm-softmmu.mak
>>> @@ -98,6 +98,7 @@ CONFIG_STM32F2XX_SPI=y
>>>    CONFIG_STM32F205_SOC=y
>>>    CONFIG_STM32F4XX_SYSCFG=y
>>>    CONFIG_STM32F4XX_EXTI=y
>>> +CONFIG_STM32F405_SOC=y
>>
>> Why not using 4xx instead of 405 in this patch as well?
> 
> I'm not sure if all the SoC variants are generic like that. Looking at
> the datasheet https://www.st.com/content/ccc/resource/technical/document/datasheet/ef/92/76/6d/bb/c2/4f/f7/DM00037051.pdf/files/DM00037051.pdf/jcr:content/translations/en.DM00037051.pdf
> it only specified the 405 and 407 variants. This is mostly a way just
> to say that I have tested it as a 405, it might work with others but I
> don't know. I think it's harder to make the SoC generic without having
> tested the other optinos (or knowing they are all interchangable).

Ok makes sense.

I was wondering because you pass a cpu_type property and your commit message
mention "STM32F4xx".

> 
> Alistair
> 
>>
>>>    CONFIG_NRF51_SOC=y
>>>
>>>    CONFIG_CMSDK_APB_TIMER=y
>>> diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
>>> index d298fbdc89..3a98bce15a 100644
>>> --- a/hw/arm/Kconfig
>>> +++ b/hw/arm/Kconfig
>>> @@ -62,6 +62,9 @@ config RASPI
>>>    config STM32F205_SOC
>>>        bool
>>>
>>> +config STM32F405_SOC
>>> +    bool
>>> +
>>>    config XLNX_ZYNQMP_ARM
>>>        bool
>>>
>>> diff --git a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs
>>> index fa57c7c770..36c3ff54c3 100644
>>> --- a/hw/arm/Makefile.objs
>>> +++ b/hw/arm/Makefile.objs
>>> @@ -26,6 +26,7 @@ obj-$(CONFIG_STRONGARM) += strongarm.o
>>>    obj-$(CONFIG_ALLWINNER_A10) += allwinner-a10.o cubieboard.o
>>>    obj-$(CONFIG_RASPI) += bcm2835_peripherals.o bcm2836.o raspi.o
>>>    obj-$(CONFIG_STM32F205_SOC) += stm32f205_soc.o
>>> +obj-$(CONFIG_STM32F405_SOC) += stm32f405_soc.o
>>>    obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zynqmp.o xlnx-zcu102.o
>>>    obj-$(CONFIG_XLNX_VERSAL) += xlnx-versal.o xlnx-versal-virt.o
>>>    obj-$(CONFIG_FSL_IMX25) += fsl-imx25.o imx25_pdk.o
>>> diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
>>> new file mode 100644
>>> index 0000000000..83adec51a2
>>> --- /dev/null
>>> +++ b/hw/arm/stm32f405_soc.c
>>> @@ -0,0 +1,292 @@
>>> +/*
>>> + * STM32F405 SoC
>>> + *
>>> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>> + * of this software and associated documentation files (the "Software"), to deal
>>> + * in the Software without restriction, including without limitation the rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "qapi/error.h"
>>> +#include "qemu-common.h"
>>> +#include "hw/arm/arm.h"
>>> +#include "exec/address-spaces.h"
>>> +#include "hw/arm/stm32f405_soc.h"
>>> +#include "hw/misc/unimp.h"
>>> +
>>> +#define SYSCFG_ADD                     0x40013800
>>> +static const uint32_t usart_addr[] = { 0x40011000, 0x40004400, 0x40004800,
>>> +                                       0x40004C00, 0x40005000, 0x40011400,
>>> +                                       0x40007800, 0x40007C00 };
>>> +/* At the moment only Timer 2 to 5 are modelled */
>>> +static const uint32_t timer_addr[] = { 0x40000000, 0x40000400,
>>> +                                       0x40000800, 0x40000C00 };
>>> +#define ADC_ADDR                       0x40012000
>>> +static const uint32_t spi_addr[] =   { 0x40013000, 0x40003800, 0x40003C00,
>>> +                                       0x40013400, 0x40015000, 0x40015400 };
>>> +#define EXTI_ADDR                      0x40013C00
>>> +
>>> +#define SYSCFG_IRQ               71
>>> +static const int usart_irq[] = { 37, 38, 39, 52, 53, 71, 82, 83 };
>>> +static const int timer_irq[] = { 28, 29, 30, 50 };
>>> +#define ADC_IRQ 18
>>> +static const int spi_irq[] =   { 35, 36, 51, 0, 0, 0 };
>>> +static const int exti_irq[] =  { 6, 7, 8, 9, 10, 23, 23, 23, 23, 23, 40,
>>> +                                 40, 40, 40, 40, 40} ;
>>> +
>>> +
>>> +static void stm32f405_soc_initfn(Object *obj)
>>> +{
>>> +    STM32F405State *s = STM32F405_SOC(obj);
>>> +    int i;
>>> +
>>> +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
>>> +                          TYPE_ARMV7M);
>>> +
>>> +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
>>> +                          TYPE_STM32F4XX_SYSCFG);
>>> +
>>> +    for (i = 0; i < STM_NUM_USARTS; i++) {
>>> +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
>>> +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
>>> +    }
>>> +
>>> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
>>> +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
>>> +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
>>> +    }
>>> +
>>> +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
>>> +
>>> +    for (i = 0; i < STM_NUM_ADCS; i++) {
>>> +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
>>> +                              TYPE_STM32F2XX_ADC);
>>> +    }
>>> +
>>> +    for (i = 0; i < STM_NUM_SPIS; i++) {
>>> +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
>>> +                              TYPE_STM32F2XX_SPI);
>>> +    }
>>> +
>>> +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
>>> +                          TYPE_STM32F4XX_EXTI);
>>> +}
>>> +
>>> +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
>>> +{
>>> +    STM32F405State *s = STM32F405_SOC(dev_soc);
>>> +    DeviceState *dev, *armv7m;
>>> +    SysBusDevice *busdev;
>>> +    Error *err = NULL;
>>> +    int i;
>>> +
>>> +    MemoryRegion *system_memory = get_system_memory();
>>> +    MemoryRegion *sram = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *flash = g_new(MemoryRegion, 1);
>>> +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>>> +
>>> +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
>>> +                           &error_fatal);
>>> +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
>>> +                             flash, 0, FLASH_SIZE);
>>> +
>>> +    memory_region_set_readonly(flash, true);
>>> +    memory_region_set_readonly(flash_alias, true);
>>> +
>>> +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
>>> +    memory_region_add_subregion(system_memory, 0, flash_alias);
>>> +
>>> +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
>>> +                           &error_fatal);
>>> +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
>>> +
>>> +    armv7m = DEVICE(&s->armv7m);
>>> +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
>>> +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
>>> +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
>>> +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
>>> +                                     "memory", &error_abort);
>>> +    object_property_set_bool(OBJECT(&s->armv7m), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +
>>> +    /* System configuration controller */
>>> +    dev = DEVICE(&s->syscfg);
>>> +    object_property_set_bool(OBJECT(&s->syscfg), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, SYSCFG_ADD);
>>> +    sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, SYSCFG_IRQ));
>>> +
>>> +    /* Attach UART (uses USART registers) and USART controllers */
>>> +    for (i = 0; i < STM_NUM_USARTS; i++) {
>>> +        dev = DEVICE(&(s->usart[i]));
>>> +        qdev_prop_set_chr(dev, "chardev", serial_hd(i));
>>> +        object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, usart_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
>>> +    }
>>> +
>>> +    /* Timer 2 to 5 */
>>> +    for (i = 0; i < STM_NUM_TIMERS; i++) {
>>> +        dev = DEVICE(&(s->timer[i]));
>>> +        qdev_prop_set_uint64(dev, "clock-frequency", 1000000000);
>>> +        object_property_set_bool(OBJECT(&s->timer[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, timer_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, timer_irq[i]));
>>> +    }
>>> +
>>> +    /* ADC device, the IRQs are ORed together */
>>> +    object_property_set_int(OBJECT(s->adc_irqs), STM_NUM_ADCS,
>>> +                            "num-lines", &err);
>>> +    object_property_set_bool(OBJECT(s->adc_irqs), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    qdev_connect_gpio_out(DEVICE(s->adc_irqs), 0,
>>> +                          qdev_get_gpio_in(armv7m, ADC_IRQ));
>>> +
>>> +    dev = DEVICE(&(s->adc[i]));
>>> +    object_property_set_bool(OBJECT(&s->adc[i]), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, ADC_ADDR);
>>> +    sysbus_connect_irq(busdev, 0,
>>> +                       qdev_get_gpio_in(DEVICE(s->adc_irqs), i));
>>> +
>>> +    /* SPI devices */
>>> +    for (i = 0; i < STM_NUM_SPIS; i++) {
>>> +        dev = DEVICE(&(s->spi[i]));
>>> +        object_property_set_bool(OBJECT(&s->spi[i]), true, "realized", &err);
>>> +        if (err != NULL) {
>>> +            error_propagate(errp, err);
>>> +            return;
>>> +        }
>>> +        busdev = SYS_BUS_DEVICE(dev);
>>> +        sysbus_mmio_map(busdev, 0, spi_addr[i]);
>>> +        sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, spi_irq[i]));
>>> +    }
>>> +
>>> +    /* EXTI device */
>>> +    dev = DEVICE(&s->exti);
>>> +    object_property_set_bool(OBJECT(&s->exti), true, "realized", &err);
>>> +    if (err != NULL) {
>>> +        error_propagate(errp, err);
>>> +        return;
>>> +    }
>>> +    busdev = SYS_BUS_DEVICE(dev);
>>> +    sysbus_mmio_map(busdev, 0, EXTI_ADDR);
>>> +    for (i = 0; i < 16; i++) {
>>> +        sysbus_connect_irq(busdev, i, qdev_get_gpio_in(armv7m, exti_irq[i]));
>>> +    }
>>> +    for (i = 0; i < 16; i++) {
>>> +        qdev_connect_gpio_out(DEVICE(&s->syscfg), i, qdev_get_gpio_in(dev, i));
>>> +    }
>>> +
>>> +    create_unimplemented_device("timer[6]",    0x40001000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[7]",    0x40001400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[12]",   0x40001800, 0x400 - 1);
>>> +    create_unimplemented_device("timer[13]",   0x40001C00, 0x400 - 1);
>>> +    create_unimplemented_device("timer[14]",   0x40002000, 0x400 - 1);
>>> +    create_unimplemented_device("RTC and BKP", 0x40002800, 0x400 - 1);
>>> +    create_unimplemented_device("WWDG",        0x40002C00, 0x400 - 1);
>>> +    create_unimplemented_device("IWDG",        0x40003000, 0x400 - 1);
>>> +    create_unimplemented_device("I2S2ext",     0x40003000, 0x400 - 1);
>>> +    create_unimplemented_device("I2S3ext",     0x40004000, 0x400 - 1);
>>> +    create_unimplemented_device("I2C1",        0x40005400, 0x400 - 1);
>>> +    create_unimplemented_device("I2C2",        0x40005800, 0x400 - 1);
>>> +    create_unimplemented_device("I2C3",        0x40005C00, 0x400 - 1);
>>> +    create_unimplemented_device("CAN1",        0x40006400, 0x400 - 1);
>>> +    create_unimplemented_device("CAN2",        0x40006800, 0x400 - 1);
>>> +    create_unimplemented_device("PWR",         0x40007000, 0x400 - 1);
>>> +    create_unimplemented_device("DAC",         0x40007400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[1]",    0x40010000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[8]",    0x40010400, 0x400 - 1);
>>> +    create_unimplemented_device("SDIO",        0x40012C00, 0x400 - 1);
>>> +    create_unimplemented_device("timer[9]",    0x40014000, 0x400 - 1);
>>> +    create_unimplemented_device("timer[10]",   0x40014400, 0x400 - 1);
>>> +    create_unimplemented_device("timer[11]",   0x40014800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOA",       0x40020000, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOB",       0x40020400, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOC",       0x40020800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOD",       0x40020C00, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOE",       0x40021000, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOF",       0x40021400, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOG",       0x40021800, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOH",       0x40021C00, 0x400 - 1);
>>> +    create_unimplemented_device("GPIOI",       0x40022000, 0x400 - 1);
>>> +    create_unimplemented_device("CRC",         0x40023000, 0x400 - 1);
>>> +    create_unimplemented_device("RCC",         0x40023800, 0x400 - 1);
>>> +    create_unimplemented_device("Flash Int",   0x40023C00, 0x400 - 1);
>>> +    create_unimplemented_device("BKPSRAM",     0x40024000, 0x400 - 1);
>>> +    create_unimplemented_device("DMA1",        0x40026000, 0x400 - 1);
>>> +    create_unimplemented_device("DMA2",        0x40026400, 0x400 - 1);
>>> +    create_unimplemented_device("Ethernet",    0x40028000, 0x1400 - 1);
>>> +    create_unimplemented_device("USB OTG HS",  0x40040000, 0x30000 - 1);
>>> +    create_unimplemented_device("USB OTG FS",  0x50000000, 0x31000 - 1);
>>> +    create_unimplemented_device("DCMI",        0x50050000, 0x400 - 1);
>>> +    create_unimplemented_device("RNG",         0x50060800, 0x400 - 1);
>>> +}
>>> +
>>> +static Property stm32f405_soc_properties[] = {
>>> +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
>>> +    DEFINE_PROP_END_OF_LIST(),
>>> +};
>>> +
>>> +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
>>> +{
>>> +    DeviceClass *dc = DEVICE_CLASS(klass);
>>> +
>>> +    dc->realize = stm32f405_soc_realize;
>>> +    dc->props = stm32f405_soc_properties;
>>> +}
>>> +
>>> +static const TypeInfo stm32f405_soc_info = {
>>> +    .name          = TYPE_STM32F405_SOC,
>>> +    .parent        = TYPE_SYS_BUS_DEVICE,
>>> +    .instance_size = sizeof(STM32F405State),
>>> +    .instance_init = stm32f405_soc_initfn,
>>> +    .class_init    = stm32f405_soc_class_init,
>>> +};
>>> +
>>> +static void stm32f405_soc_types(void)
>>> +{
>>> +    type_register_static(&stm32f405_soc_info);
>>> +}
>>> +
>>> +type_init(stm32f405_soc_types)
>>> diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
>>> new file mode 100644
>>> index 0000000000..f0aec53d32
>>> --- /dev/null
>>> +++ b/include/hw/arm/stm32f405_soc.h
>>> @@ -0,0 +1,70 @@
>>> +/*
>>> + * STM32F405 SoC
>>> + *
>>> + * Copyright (c) 2014 Alistair Francis <alistair@alistair23.me>
>>> + *
>>> + * Permission is hereby granted, free of charge, to any person obtaining a copy
>>> + * of this software and associated documentation files (the "Software"), to deal
>>> + * in the Software without restriction, including without limitation the rights
>>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
>>> + * copies of the Software, and to permit persons to whom the Software is
>>> + * furnished to do so, subject to the following conditions:
>>> + *
>>> + * The above copyright notice and this permission notice shall be included in
>>> + * all copies or substantial portions of the Software.
>>> + *
>>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
>>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
>>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
>>> + * THE SOFTWARE.
>>> + */
>>> +
>>> +#ifndef HW_ARM_STM32F405_SOC_H
>>> +#define HW_ARM_STM32F405_SOC_H
>>> +
>>> +#include "hw/misc/stm32f4xx_syscfg.h"
>>> +#include "hw/timer/stm32f2xx_timer.h"
>>> +#include "hw/char/stm32f2xx_usart.h"
>>> +#include "hw/adc/stm32f2xx_adc.h"
>>> +#include "hw/misc/stm32f4xx_exti.h"
>>> +#include "hw/or-irq.h"
>>> +#include "hw/ssi/stm32f2xx_spi.h"
>>> +#include "hw/arm/armv7m.h"
>>> +
>>> +#define TYPE_STM32F405_SOC "stm32f405-soc"
>>> +#define STM32F405_SOC(obj) \
>>> +    OBJECT_CHECK(STM32F405State, (obj), TYPE_STM32F405_SOC)
>>> +
>>> +#define STM_NUM_USARTS 7
>>> +#define STM_NUM_TIMERS 4
>>> +#define STM_NUM_ADCS 6
>>> +#define STM_NUM_SPIS 6
>>> +
>>> +#define FLASH_BASE_ADDRESS 0x08000000
>>> +#define FLASH_SIZE (1024 * 1024)
>>> +#define SRAM_BASE_ADDRESS 0x20000000
>>> +#define SRAM_SIZE (192 * 1024)
>>> +
>>> +typedef struct STM32F405State {
>>> +    /*< private >*/
>>> +    SysBusDevice parent_obj;
>>> +    /*< public >*/
>>> +
>>> +    char *cpu_type;
>>> +
>>> +    ARMv7MState armv7m;
>>> +
>>> +    STM32F4xxSyscfgState syscfg;
>>> +    STM32F4xxExtiState exti;
>>> +    STM32F2XXUsartState usart[STM_NUM_USARTS];
>>> +    STM32F2XXTimerState timer[STM_NUM_TIMERS];
>>> +    STM32F2XXADCState adc[STM_NUM_ADCS];
>>> +    STM32F2XXSPIState spi[STM_NUM_SPIS];
>>> +
>>> +    qemu_or_irq *adc_irqs;
>>> +} STM32F405State;
>>> +
>>> +#endif
>>>


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-30 16:01   ` Peter Maydell
  2019-04-30 16:01     ` Peter Maydell
@ 2019-04-30 20:27     ` Alistair Francis
  2019-04-30 20:27       ` Alistair Francis
  2019-05-02 10:05       ` Peter Maydell
  1 sibling, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-30 20:27 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:39, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |  6 +++
> >  default-configs/arm-softmmu.mak |  1 +
> >  hw/arm/Kconfig                  |  3 ++
> >  hw/arm/Makefile.objs            |  1 +
> >  hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
> >  5 files changed, 88 insertions(+)
> >  create mode 100644 hw/arm/netduinoplus2.c
> >
>
> > +typedef struct ARMV7MResetArgs {
> > +    ARMCPU *cpu;
> > +    uint32_t reset_sp;
> > +    uint32_t reset_pc;
> > +} ARMV7MResetArgs;
> > +
> > +static void armv7m_reset(void *opaque)
> > +{
> > +    ARMV7MResetArgs *args = opaque;
> > +
> > +    cpu_reset(CPU(args->cpu));
> > +
> > +    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
> > +    args->cpu->env.thumb = args->reset_pc & 1;
> > +    args->cpu->env.regs[15] = args->reset_pc & ~1;
> > +}
> > +
> > +static void netduinoplus2_init(MachineState *machine)
> > +{
> > +    DeviceState *dev;
> > +    ARMV7MResetArgs reset_args;
> > +    uint64_t entry;
> > +
> > +    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
> > +    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
> > +    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> > +
> > +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> > +                       FLASH_SIZE, &entry);
> > +
> > +    reset_args = (ARMV7MResetArgs) {
> > +        .cpu = ARM_CPU(first_cpu),
> > +        .reset_pc = entry,
> > +        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
> > +    };
> > +    qemu_register_reset(armv7m_reset,
> > +                        g_memdup(&reset_args, sizeof(reset_args)));
> > +}
>
> Can you explain the purpose of the reset code? None of the other
> v7m boards seem to need to do a manual qemu_register_reset().

The reset code allows the machine to work with the -kernel option.
Without the reset override using -kernel results in the guest starting
at the wrong address. We can use the -device loader option without the
reset code though.

I don't have examples infront of me, I can run it when I'm home and
include the addresses if you want.

Alistair

>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-30 20:27     ` Alistair Francis
@ 2019-04-30 20:27       ` Alistair Francis
  2019-05-02 10:05       ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-04-30 20:27 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:39, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |  6 +++
> >  default-configs/arm-softmmu.mak |  1 +
> >  hw/arm/Kconfig                  |  3 ++
> >  hw/arm/Makefile.objs            |  1 +
> >  hw/arm/netduinoplus2.c          | 77 +++++++++++++++++++++++++++++++++
> >  5 files changed, 88 insertions(+)
> >  create mode 100644 hw/arm/netduinoplus2.c
> >
>
> > +typedef struct ARMV7MResetArgs {
> > +    ARMCPU *cpu;
> > +    uint32_t reset_sp;
> > +    uint32_t reset_pc;
> > +} ARMV7MResetArgs;
> > +
> > +static void armv7m_reset(void *opaque)
> > +{
> > +    ARMV7MResetArgs *args = opaque;
> > +
> > +    cpu_reset(CPU(args->cpu));
> > +
> > +    args->cpu->env.regs[13] = args->reset_sp & 0xFFFFFFFC;
> > +    args->cpu->env.thumb = args->reset_pc & 1;
> > +    args->cpu->env.regs[15] = args->reset_pc & ~1;
> > +}
> > +
> > +static void netduinoplus2_init(MachineState *machine)
> > +{
> > +    DeviceState *dev;
> > +    ARMV7MResetArgs reset_args;
> > +    uint64_t entry;
> > +
> > +    dev = qdev_create(NULL, TYPE_STM32F405_SOC);
> > +    qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
> > +    object_property_set_bool(OBJECT(dev), true, "realized", &error_fatal);
> > +
> > +    armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
> > +                       FLASH_SIZE, &entry);
> > +
> > +    reset_args = (ARMV7MResetArgs) {
> > +        .cpu = ARM_CPU(first_cpu),
> > +        .reset_pc = entry,
> > +        .reset_sp = (SRAM_BASE_ADDRESS + (SRAM_SIZE * 2) / 3),
> > +    };
> > +    qemu_register_reset(armv7m_reset,
> > +                        g_memdup(&reset_args, sizeof(reset_args)));
> > +}
>
> Can you explain the purpose of the reset code? None of the other
> v7m boards seem to need to do a manual qemu_register_reset().

The reset code allows the machine to work with the -kernel option.
Without the reset override using -kernel results in the guest starting
at the wrong address. We can use the -device loader option without the
reset code though.

I don't have examples infront of me, I can run it when I'm home and
include the addresses if you want.

Alistair

>
> thanks
> -- PMM


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

* Re: [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-04-30 16:04   ` Peter Maydell
  2019-04-30 16:04     ` Peter Maydell
@ 2019-05-01  3:54     ` Alistair Francis
  2019-05-01  3:54       ` Alistair Francis
  1 sibling, 1 reply; 51+ messages in thread
From: Alistair Francis @ 2019-05-01  3:54 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 9:04 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:34, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Allow the kernel's entry point information to be returned when loading a
> > kernel.
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  hw/arm/armv7m.c      | 6 +++---
> >  hw/arm/microbit.c    | 2 +-
> >  hw/arm/mps2-tz.c     | 3 ++-
> >  hw/arm/mps2.c        | 2 +-
> >  hw/arm/msf2-som.c    | 2 +-
> >  hw/arm/musca.c       | 3 ++-
> >  hw/arm/netduino2.c   | 2 +-
> >  hw/arm/stellaris.c   | 3 ++-
> >  include/hw/arm/arm.h | 4 +++-
> >  9 files changed, 16 insertions(+), 11 deletions(-)
>
> > -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
> > +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
> > +                        uint64_t *entry)
>
> If we need to return the entry point, why not just return it
> as the return value of the function rather than having the
> caller pass in a pointer which we fill in ?

There wasn't really a reason, it was just following along with load_elf().

Alistair

>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned
  2019-05-01  3:54     ` Alistair Francis
@ 2019-05-01  3:54       ` Alistair Francis
  0 siblings, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-05-01  3:54 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 9:04 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:34, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Allow the kernel's entry point information to be returned when loading a
> > kernel.
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  hw/arm/armv7m.c      | 6 +++---
> >  hw/arm/microbit.c    | 2 +-
> >  hw/arm/mps2-tz.c     | 3 ++-
> >  hw/arm/mps2.c        | 2 +-
> >  hw/arm/msf2-som.c    | 2 +-
> >  hw/arm/musca.c       | 3 ++-
> >  hw/arm/netduino2.c   | 2 +-
> >  hw/arm/stellaris.c   | 3 ++-
> >  include/hw/arm/arm.h | 4 +++-
> >  9 files changed, 16 insertions(+), 11 deletions(-)
>
> > -void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size)
> > +void armv7m_load_kernel(ARMCPU *cpu, const char *kernel_filename, int mem_size,
> > +                        uint64_t *entry)
>
> If we need to return the entry point, why not just return it
> as the return value of the function rather than having the
> caller pass in a pointer which we fill in ?

There wasn't really a reason, it was just following along with load_elf().

Alistair

>
> thanks
> -- PMM


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

* Re: [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
  2019-04-30 15:48   ` Peter Maydell
  2019-04-30 15:48     ` Peter Maydell
@ 2019-05-02  4:28     ` Alistair Francis
  2019-05-02  4:28       ` Alistair Francis
  1 sibling, 1 reply; 51+ messages in thread
From: Alistair Francis @ 2019-05-02  4:28 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 8:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:37, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  default-configs/arm-softmmu.mak  |   1 +
> >  hw/misc/Kconfig                  |   3 +
> >  hw/misc/Makefile.objs            |   1 +
> >  hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
> >  include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
> >  5 files changed, 237 insertions(+)
> >  create mode 100644 hw/misc/stm32f4xx_exti.c
> >  create mode 100644 include/hw/misc/stm32f4xx_exti.h
>
> Minor comments here only.
>
> (If Thomas's kconfig patchset gets into master before this
> there might be some minor fixups required to the kconfig
> stuff, but it shouldn't be too hard to adapt.)

Yep, I'm happy to rebase on top of his work.

>
> > +#include "qemu/osdep.h"
> > +#include "hw/sysbus.h"
> > +#include "qemu/log.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +
> > +#ifndef STM_EXTI_ERR_DEBUG
> > +#define STM_EXTI_ERR_DEBUG 0
> > +#endif
> > +
> > +#define DB_PRINT_L(lvl, fmt, args...) do { \
> > +    if (STM_EXTI_ERR_DEBUG >= lvl) { \
> > +        qemu_log("%s: " fmt, __func__, ## args); \
> > +    } \
> > +} while (0)
> > +
> > +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>
> Could we use a tracepoint instead?

Yep, fixed in both patches.

>
> > +
> > +#define NUM_GPIO_EVENT_IN_LINES 16
> > +#define NUM_INTERRUPT_OUT_LINES 16
> > +
> > +static void stm32f4xx_exti_reset(DeviceState *dev)
> > +{
> > +    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
> > +
> > +    s->exti_imr = 0x00000000;
> > +    s->exti_emr = 0x00000000;
> > +    s->exti_rtsr = 0x00000000;
> > +    s->exti_ftsr = 0x00000000;
> > +    s->exti_swier = 0x00000000;
> > +    s->exti_pr = 0x00000000;
> > +}
> > +
> > +static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
> > +{
> > +    STM32F4xxExtiState *s = opaque;
> > +
> > +    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
> > +
> > +    if (level) {
> > +        qemu_irq_pulse(s->irq[irq]);
> > +        s->exti_pr |= 1 << irq;
> > +    }
> > +}
>
> Just to check -- this should definitely be a pulse? I'm always
> a little bit wary of uses of qemu_irq_pulse(), though some
> hardware does pulse IRQ lines rather than holding them until
> dismissed.

The datasheet seems to specify pulse:
"When the selected edge occurs on the event line, an event pulse is generated"

>
> > +static void stm32f4xx_exti_init(Object *obj)
> > +{
> > +    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
> > +    int i;
> > +
> > +    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);
>
> You could just have the array be inline in the
> STM32F4xxExtiState rather than allocating it separately,
> right?

Yep.

>
> > +    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
> > +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
> > +    }
> > +
> > +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
> > +                          TYPE_STM32F4XX_EXTI, 0x400);
> > +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> > +
> > +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
> > +                      NUM_GPIO_EVENT_IN_LINES);
> > +}
> > +
> > +static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->reset = stm32f4xx_exti_reset;
>
> This one's missing vmstate too.

Fixed in both.

Alistair

>
> > +}
> > +
> > +static const TypeInfo stm32f4xx_exti_info = {
> > +    .name          = TYPE_STM32F4XX_EXTI,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F4xxExtiState),
> > +    .instance_init = stm32f4xx_exti_init,
> > +    .class_init    = stm32f4xx_exti_class_init,
> > +};
> > +
> > +static void stm32f4xx_exti_register_types(void)
> > +{
> > +    type_register_static(&stm32f4xx_exti_info);
> > +}
> > +
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device
  2019-05-02  4:28     ` Alistair Francis
@ 2019-05-02  4:28       ` Alistair Francis
  0 siblings, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-05-02  4:28 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 8:48 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:37, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  default-configs/arm-softmmu.mak  |   1 +
> >  hw/misc/Kconfig                  |   3 +
> >  hw/misc/Makefile.objs            |   1 +
> >  hw/misc/stm32f4xx_exti.c         | 175 +++++++++++++++++++++++++++++++
> >  include/hw/misc/stm32f4xx_exti.h |  57 ++++++++++
> >  5 files changed, 237 insertions(+)
> >  create mode 100644 hw/misc/stm32f4xx_exti.c
> >  create mode 100644 include/hw/misc/stm32f4xx_exti.h
>
> Minor comments here only.
>
> (If Thomas's kconfig patchset gets into master before this
> there might be some minor fixups required to the kconfig
> stuff, but it shouldn't be too hard to adapt.)

Yep, I'm happy to rebase on top of his work.

>
> > +#include "qemu/osdep.h"
> > +#include "hw/sysbus.h"
> > +#include "qemu/log.h"
> > +#include "hw/misc/stm32f4xx_exti.h"
> > +
> > +#ifndef STM_EXTI_ERR_DEBUG
> > +#define STM_EXTI_ERR_DEBUG 0
> > +#endif
> > +
> > +#define DB_PRINT_L(lvl, fmt, args...) do { \
> > +    if (STM_EXTI_ERR_DEBUG >= lvl) { \
> > +        qemu_log("%s: " fmt, __func__, ## args); \
> > +    } \
> > +} while (0)
> > +
> > +#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args)
>
> Could we use a tracepoint instead?

Yep, fixed in both patches.

>
> > +
> > +#define NUM_GPIO_EVENT_IN_LINES 16
> > +#define NUM_INTERRUPT_OUT_LINES 16
> > +
> > +static void stm32f4xx_exti_reset(DeviceState *dev)
> > +{
> > +    STM32F4xxExtiState *s = STM32F4XX_EXTI(dev);
> > +
> > +    s->exti_imr = 0x00000000;
> > +    s->exti_emr = 0x00000000;
> > +    s->exti_rtsr = 0x00000000;
> > +    s->exti_ftsr = 0x00000000;
> > +    s->exti_swier = 0x00000000;
> > +    s->exti_pr = 0x00000000;
> > +}
> > +
> > +static void stm32f4xx_exti_set_irq(void *opaque, int irq, int level)
> > +{
> > +    STM32F4xxExtiState *s = opaque;
> > +
> > +    DB_PRINT("Set EXTI: %d to %d\n", irq, level);
> > +
> > +    if (level) {
> > +        qemu_irq_pulse(s->irq[irq]);
> > +        s->exti_pr |= 1 << irq;
> > +    }
> > +}
>
> Just to check -- this should definitely be a pulse? I'm always
> a little bit wary of uses of qemu_irq_pulse(), though some
> hardware does pulse IRQ lines rather than holding them until
> dismissed.

The datasheet seems to specify pulse:
"When the selected edge occurs on the event line, an event pulse is generated"

>
> > +static void stm32f4xx_exti_init(Object *obj)
> > +{
> > +    STM32F4xxExtiState *s = STM32F4XX_EXTI(obj);
> > +    int i;
> > +
> > +    s->irq = g_new0(qemu_irq, NUM_INTERRUPT_OUT_LINES);
>
> You could just have the array be inline in the
> STM32F4xxExtiState rather than allocating it separately,
> right?

Yep.

>
> > +    for (i = 0; i < NUM_INTERRUPT_OUT_LINES; i++) {
> > +        sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq[i]);
> > +    }
> > +
> > +    memory_region_init_io(&s->mmio, obj, &stm32f4xx_exti_ops, s,
> > +                          TYPE_STM32F4XX_EXTI, 0x400);
> > +    sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
> > +
> > +    qdev_init_gpio_in(DEVICE(obj), stm32f4xx_exti_set_irq,
> > +                      NUM_GPIO_EVENT_IN_LINES);
> > +}
> > +
> > +static void stm32f4xx_exti_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->reset = stm32f4xx_exti_reset;
>
> This one's missing vmstate too.

Fixed in both.

Alistair

>
> > +}
> > +
> > +static const TypeInfo stm32f4xx_exti_info = {
> > +    .name          = TYPE_STM32F4XX_EXTI,
> > +    .parent        = TYPE_SYS_BUS_DEVICE,
> > +    .instance_size = sizeof(STM32F4xxExtiState),
> > +    .instance_init = stm32f4xx_exti_init,
> > +    .class_init    = stm32f4xx_exti_class_init,
> > +};
> > +
> > +static void stm32f4xx_exti_register_types(void)
> > +{
> > +    type_register_static(&stm32f4xx_exti_info);
> > +}
> > +
>
> thanks
> -- PMM


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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-04-30 15:59   ` Peter Maydell
  2019-04-30 15:59     ` Peter Maydell
@ 2019-05-02  5:04     ` Alistair Francis
  2019-05-02  5:04       ` Alistair Francis
  1 sibling, 1 reply; 51+ messages in thread
From: Alistair Francis @ 2019-05-02  5:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 8:59 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:38, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |   8 +
> >  default-configs/arm-softmmu.mak |   1 +
> >  hw/arm/Kconfig                  |   3 +
> >  hw/arm/Makefile.objs            |   1 +
> >  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >  6 files changed, 375 insertions(+)
> >  create mode 100644 hw/arm/stm32f405_soc.c
> >  create mode 100644 include/hw/arm/stm32f405_soc.h
>
> Looks good; a few minor things below.
>
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
>
> It would be more in keeping with the style of the rest of this
> device to have the device be inline in the STM32F405State
> struct and initialized with object_initialize_child() rather
> than allocated separately with object_new(). (hw/arm/armsse.c
> has an example of doing this with a TYPE_OR_IRQ object.)

I have addressed all your comments.

Alistair

>
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>
> I would prefer to have these MemoryRegions be in the STM32F405State
> struct rather than separately allocated.
>
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
>
> Better to pass the error back up via errp rather than use error_fatal
> in a realize function.
>
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
>
> You could use OBJECT(system_memory) rather than calling
> get_system_memory() again.
>
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
>
> A comment here "No vmstate or reset required: device has no internal state"
> would help indicate that dc->vmsd and dc->reset have not merely
> been forgotten.
>
> (Eventually I might actually write a patch to let us express
> in code "dc->vmsd = device_has_no_state;"...)
>
> > +}
>
> thanks
> -- PMM

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

* Re: [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC
  2019-05-02  5:04     ` Alistair Francis
@ 2019-05-02  5:04       ` Alistair Francis
  0 siblings, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-05-02  5:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair Francis, qemu-devel

On Tue, Apr 30, 2019 at 8:59 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Mon, 29 Apr 2019 at 06:38, Alistair Francis <alistair@alistair23.me> wrote:
> >
> > Signed-off-by: Alistair Francis <alistair@alistair23.me>
> > ---
> >  MAINTAINERS                     |   8 +
> >  default-configs/arm-softmmu.mak |   1 +
> >  hw/arm/Kconfig                  |   3 +
> >  hw/arm/Makefile.objs            |   1 +
> >  hw/arm/stm32f405_soc.c          | 292 ++++++++++++++++++++++++++++++++
> >  include/hw/arm/stm32f405_soc.h  |  70 ++++++++
> >  6 files changed, 375 insertions(+)
> >  create mode 100644 hw/arm/stm32f405_soc.c
> >  create mode 100644 include/hw/arm/stm32f405_soc.h
>
> Looks good; a few minor things below.
>
> > +static void stm32f405_soc_initfn(Object *obj)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(obj);
> > +    int i;
> > +
> > +    sysbus_init_child_obj(obj, "armv7m", &s->armv7m, sizeof(s->armv7m),
> > +                          TYPE_ARMV7M);
> > +
> > +    sysbus_init_child_obj(obj, "syscfg", &s->syscfg, sizeof(s->syscfg),
> > +                          TYPE_STM32F4XX_SYSCFG);
> > +
> > +    for (i = 0; i < STM_NUM_USARTS; i++) {
> > +        sysbus_init_child_obj(obj, "usart[*]", &s->usart[i],
> > +                              sizeof(s->usart[i]), TYPE_STM32F2XX_USART);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_TIMERS; i++) {
> > +        sysbus_init_child_obj(obj, "timer[*]", &s->timer[i],
> > +                              sizeof(s->timer[i]), TYPE_STM32F2XX_TIMER);
> > +    }
> > +
> > +    s->adc_irqs = OR_IRQ(object_new(TYPE_OR_IRQ));
>
> It would be more in keeping with the style of the rest of this
> device to have the device be inline in the STM32F405State
> struct and initialized with object_initialize_child() rather
> than allocated separately with object_new(). (hw/arm/armsse.c
> has an example of doing this with a TYPE_OR_IRQ object.)

I have addressed all your comments.

Alistair

>
> > +
> > +    for (i = 0; i < STM_NUM_ADCS; i++) {
> > +        sysbus_init_child_obj(obj, "adc[*]", &s->adc[i], sizeof(s->adc[i]),
> > +                              TYPE_STM32F2XX_ADC);
> > +    }
> > +
> > +    for (i = 0; i < STM_NUM_SPIS; i++) {
> > +        sysbus_init_child_obj(obj, "spi[*]", &s->spi[i], sizeof(s->spi[i]),
> > +                              TYPE_STM32F2XX_SPI);
> > +    }
> > +
> > +    sysbus_init_child_obj(obj, "exti", &s->exti, sizeof(s->exti),
> > +                          TYPE_STM32F4XX_EXTI);
> > +}
> > +
> > +static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
> > +{
> > +    STM32F405State *s = STM32F405_SOC(dev_soc);
> > +    DeviceState *dev, *armv7m;
> > +    SysBusDevice *busdev;
> > +    Error *err = NULL;
> > +    int i;
> > +
> > +    MemoryRegion *system_memory = get_system_memory();
> > +    MemoryRegion *sram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash = g_new(MemoryRegion, 1);
> > +    MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
>
> I would prefer to have these MemoryRegions be in the STM32F405State
> struct rather than separately allocated.
>
> > +
> > +    memory_region_init_ram(flash, NULL, "STM32F405.flash", FLASH_SIZE,
> > +                           &error_fatal);
>
> Better to pass the error back up via errp rather than use error_fatal
> in a realize function.
>
> > +    memory_region_init_alias(flash_alias, NULL, "STM32F405.flash.alias",
> > +                             flash, 0, FLASH_SIZE);
> > +
> > +    memory_region_set_readonly(flash, true);
> > +    memory_region_set_readonly(flash_alias, true);
> > +
> > +    memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
> > +    memory_region_add_subregion(system_memory, 0, flash_alias);
> > +
> > +    memory_region_init_ram(sram, NULL, "STM32F405.sram", SRAM_SIZE,
> > +                           &error_fatal);
> > +    memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
> > +
> > +    armv7m = DEVICE(&s->armv7m);
> > +    qdev_prop_set_uint32(armv7m, "num-irq", 96);
> > +    qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
> > +    qdev_prop_set_bit(armv7m, "enable-bitband", true);
> > +    object_property_set_link(OBJECT(&s->armv7m), OBJECT(get_system_memory()),
>
> You could use OBJECT(system_memory) rather than calling
> get_system_memory() again.
>
> > +static Property stm32f405_soc_properties[] = {
> > +    DEFINE_PROP_STRING("cpu-type", STM32F405State, cpu_type),
> > +    DEFINE_PROP_END_OF_LIST(),
> > +};
> > +
> > +static void stm32f405_soc_class_init(ObjectClass *klass, void *data)
> > +{
> > +    DeviceClass *dc = DEVICE_CLASS(klass);
> > +
> > +    dc->realize = stm32f405_soc_realize;
> > +    dc->props = stm32f405_soc_properties;
>
> A comment here "No vmstate or reset required: device has no internal state"
> would help indicate that dc->vmsd and dc->reset have not merely
> been forgotten.
>
> (Eventually I might actually write a patch to let us express
> in code "dc->vmsd = device_has_no_state;"...)
>
> > +}
>
> thanks
> -- PMM


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-04-30 20:27     ` Alistair Francis
  2019-04-30 20:27       ` Alistair Francis
@ 2019-05-02 10:05       ` Peter Maydell
  2019-05-02 10:05         ` Peter Maydell
  2019-05-04  4:25         ` Alistair
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-05-02 10:05 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair Francis, qemu-devel

On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
>
> On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > Can you explain the purpose of the reset code? None of the other
> > v7m boards seem to need to do a manual qemu_register_reset().
>
> The reset code allows the machine to work with the -kernel option.
> Without the reset override using -kernel results in the guest starting
> at the wrong address. We can use the -device loader option without the
> reset code though.

That sounds in line with how -kernel works on the other armv7m
boards -- the expectation is that your image file includes a
full vector table and the CPU will read the PC and SP from it
when it resets. If you want "honour the entry point" you can
use -device loader, as you say.

Ignoring the entry point for -kernel ELF files is certainly
a bit confusing, but I think if we want to change this we should
do it globally, rather than having one board which behaves
differently to the rest. Changing it does have some awkwardness:
 * possibility of breaking previously working images
 * we can get the initial PC from the ELF entrypoint, but if
   we do this what do we do about the initial SP value ?

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-02 10:05       ` Peter Maydell
@ 2019-05-02 10:05         ` Peter Maydell
  2019-05-04  4:25         ` Alistair
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-05-02 10:05 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair Francis, qemu-devel

On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
>
> On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > Can you explain the purpose of the reset code? None of the other
> > v7m boards seem to need to do a manual qemu_register_reset().
>
> The reset code allows the machine to work with the -kernel option.
> Without the reset override using -kernel results in the guest starting
> at the wrong address. We can use the -device loader option without the
> reset code though.

That sounds in line with how -kernel works on the other armv7m
boards -- the expectation is that your image file includes a
full vector table and the CPU will read the PC and SP from it
when it resets. If you want "honour the entry point" you can
use -device loader, as you say.

Ignoring the entry point for -kernel ELF files is certainly
a bit confusing, but I think if we want to change this we should
do it globally, rather than having one board which behaves
differently to the rest. Changing it does have some awkwardness:
 * possibility of breaking previously working images
 * we can get the initial PC from the ELF entrypoint, but if
   we do this what do we do about the initial SP value ?

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-02 10:05       ` Peter Maydell
  2019-05-02 10:05         ` Peter Maydell
@ 2019-05-04  4:25         ` Alistair
  2019-05-04  4:25           ` Alistair
  2019-05-04  5:25           ` Alistair Francis
  1 sibling, 2 replies; 51+ messages in thread
From: Alistair @ 2019-05-04  4:25 UTC (permalink / raw)
  To: qemu-devel@nongnu.org Developers

On Thu, May 2, 2019, at 3:06 AM, Peter Maydell wrote:
> On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
> >
> > On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > > Can you explain the purpose of the reset code? None of the other
> > > v7m boards seem to need to do a manual qemu_register_reset().
> >
> > The reset code allows the machine to work with the -kernel option.
> > Without the reset override using -kernel results in the guest starting
> > at the wrong address. We can use the -device loader option without the
> > reset code though.
> 
> That sounds in line with how -kernel works on the other armv7m
> boards -- the expectation is that your image file includes a
> full vector table and the CPU will read the PC and SP from it
> when it resets. If you want "honour the entry point" you can
> use -device loader, as you say.
> 
> Ignoring the entry point for -kernel ELF files is certainly
> a bit confusing, but I think if we want to change this we should
> do it globally, rather than having one board which behaves
> differently to the rest. Changing it does have some awkwardness:

Hmm... That is a good point. It is confusing having something just for one board. I'll drop this part and we can re-evaluate later.

> * possibility of breaking previously working images

I have no way to test the other boards, so this might be difficult to change.

> * we can get the initial PC from the ELF entrypoint, but if
>  we do this what do we do about the initial SP value ?

Not sure about this one either. I'm guessing it changes between the different M cores.

Alistair

> 
> thanks
> -- PMM
> 
> 

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-04  4:25         ` Alistair
@ 2019-05-04  4:25           ` Alistair
  2019-05-04  5:25           ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair @ 2019-05-04  4:25 UTC (permalink / raw)
  To: qemu-devel@nongnu.org Developers

On Thu, May 2, 2019, at 3:06 AM, Peter Maydell wrote:
> On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
> >
> > On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > > Can you explain the purpose of the reset code? None of the other
> > > v7m boards seem to need to do a manual qemu_register_reset().
> >
> > The reset code allows the machine to work with the -kernel option.
> > Without the reset override using -kernel results in the guest starting
> > at the wrong address. We can use the -device loader option without the
> > reset code though.
> 
> That sounds in line with how -kernel works on the other armv7m
> boards -- the expectation is that your image file includes a
> full vector table and the CPU will read the PC and SP from it
> when it resets. If you want "honour the entry point" you can
> use -device loader, as you say.
> 
> Ignoring the entry point for -kernel ELF files is certainly
> a bit confusing, but I think if we want to change this we should
> do it globally, rather than having one board which behaves
> differently to the rest. Changing it does have some awkwardness:

Hmm... That is a good point. It is confusing having something just for one board. I'll drop this part and we can re-evaluate later.

> * possibility of breaking previously working images

I have no way to test the other boards, so this might be difficult to change.

> * we can get the initial PC from the ELF entrypoint, but if
>  we do this what do we do about the initial SP value ?

Not sure about this one either. I'm guessing it changes between the different M cores.

Alistair

> 
> thanks
> -- PMM
> 
> 


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-04  4:25         ` Alistair
  2019-05-04  4:25           ` Alistair
@ 2019-05-04  5:25           ` Alistair Francis
  2019-05-04  5:25             ` Alistair Francis
  2019-05-05 15:34             ` Peter Maydell
  1 sibling, 2 replies; 51+ messages in thread
From: Alistair Francis @ 2019-05-04  5:25 UTC (permalink / raw)
  To: Alistair; +Cc: qemu-devel@nongnu.org Developers

On Fri, May 3, 2019 at 9:26 PM Alistair <alistair@alistair23.me> wrote:
>
> On Thu, May 2, 2019, at 3:06 AM, Peter Maydell wrote:
> > On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
> > >
> > > On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > > > Can you explain the purpose of the reset code? None of the other
> > > > v7m boards seem to need to do a manual qemu_register_reset().
> > >
> > > The reset code allows the machine to work with the -kernel option.
> > > Without the reset override using -kernel results in the guest starting
> > > at the wrong address. We can use the -device loader option without the
> > > reset code though.
> >
> > That sounds in line with how -kernel works on the other armv7m
> > boards -- the expectation is that your image file includes a
> > full vector table and the CPU will read the PC and SP from it
> > when it resets. If you want "honour the entry point" you can
> > use -device loader, as you say.
> >
> > Ignoring the entry point for -kernel ELF files is certainly
> > a bit confusing, but I think if we want to change this we should
> > do it globally, rather than having one board which behaves
> > differently to the rest. Changing it does have some awkwardness:
>
> Hmm... That is a good point. It is confusing having something just for one board. I'll drop this part and we can re-evaluate later.
>
> > * possibility of breaking previously working images
>
> I have no way to test the other boards, so this might be difficult to change.
>
> > * we can get the initial PC from the ELF entrypoint, but if
> >  we do this what do we do about the initial SP value ?
>
> Not sure about this one either. I'm guessing it changes between the different M cores.

Ah, it seems like -device loader doesn't work, it looks like not
setting the thumb register causes this core dump:

qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)

R00=20000000 R01=00000574 R02=200015d0 R03=200015d0
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=ffffffe0 R14=fffffff9 R15=0800cba4
XPSR=61000003 -ZC- T handler
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
s22=00000000 s23=00000000 d11=0000000000000000
s24=00000000 s25=00000000 d12=0000000000000000
s26=00000000 s27=00000000 d13=0000000000000000
s28=00000000 s29=00000000 d14=0000000000000000
s30=00000000 s31=00000000 d15=0000000000000000
s32=00000000 s33=00000000 d16=0000000000000000
s34=00000000 s35=00000000 d17=0000000000000000
s36=00000000 s37=00000000 d18=0000000000000000
s38=00000000 s39=00000000 d19=0000000000000000
s40=00000000 s41=00000000 d20=0000000000000000
s42=00000000 s43=00000000 d21=0000000000000000
s44=00000000 s45=00000000 d22=0000000000000000
s46=00000000 s47=00000000 d23=0000000000000000
s48=00000000 s49=00000000 d24=0000000000000000
s50=00000000 s51=00000000 d25=0000000000000000
s52=00000000 s53=00000000 d26=0000000000000000
s54=00000000 s55=00000000 d27=0000000000000000
s56=00000000 s57=00000000 d28=0000000000000000
s58=00000000 s59=00000000 d29=0000000000000000
s60=00000000 s61=00000000 d30=0000000000000000
s62=00000000 s63=00000000 d31=0000000000000000
FPSCR: 00000000
Aborted (core dumped)

Alistair

>
> Alistair
>
> >
> > thanks
> > -- PMM
> >
> >
>

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-04  5:25           ` Alistair Francis
@ 2019-05-04  5:25             ` Alistair Francis
  2019-05-05 15:34             ` Peter Maydell
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-05-04  5:25 UTC (permalink / raw)
  To: Alistair; +Cc: qemu-devel@nongnu.org Developers

On Fri, May 3, 2019 at 9:26 PM Alistair <alistair@alistair23.me> wrote:
>
> On Thu, May 2, 2019, at 3:06 AM, Peter Maydell wrote:
> > On Tue, 30 Apr 2019 at 21:29, Alistair Francis <alistair23@gmail.com> wrote:
> > >
> > > On Tue, Apr 30, 2019 at 9:02 AM Peter Maydell <peter.maydell@linaro.org> wrote:
> > > > Can you explain the purpose of the reset code? None of the other
> > > > v7m boards seem to need to do a manual qemu_register_reset().
> > >
> > > The reset code allows the machine to work with the -kernel option.
> > > Without the reset override using -kernel results in the guest starting
> > > at the wrong address. We can use the -device loader option without the
> > > reset code though.
> >
> > That sounds in line with how -kernel works on the other armv7m
> > boards -- the expectation is that your image file includes a
> > full vector table and the CPU will read the PC and SP from it
> > when it resets. If you want "honour the entry point" you can
> > use -device loader, as you say.
> >
> > Ignoring the entry point for -kernel ELF files is certainly
> > a bit confusing, but I think if we want to change this we should
> > do it globally, rather than having one board which behaves
> > differently to the rest. Changing it does have some awkwardness:
>
> Hmm... That is a good point. It is confusing having something just for one board. I'll drop this part and we can re-evaluate later.
>
> > * possibility of breaking previously working images
>
> I have no way to test the other boards, so this might be difficult to change.
>
> > * we can get the initial PC from the ELF entrypoint, but if
> >  we do this what do we do about the initial SP value ?
>
> Not sure about this one either. I'm guessing it changes between the different M cores.

Ah, it seems like -device loader doesn't work, it looks like not
setting the thumb register causes this core dump:

qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)

R00=20000000 R01=00000574 R02=200015d0 R03=200015d0
R04=00000000 R05=00000000 R06=00000000 R07=00000000
R08=00000000 R09=00000000 R10=00000000 R11=00000000
R12=00000000 R13=ffffffe0 R14=fffffff9 R15=0800cba4
XPSR=61000003 -ZC- T handler
s00=00000000 s01=00000000 d00=0000000000000000
s02=00000000 s03=00000000 d01=0000000000000000
s04=00000000 s05=00000000 d02=0000000000000000
s06=00000000 s07=00000000 d03=0000000000000000
s08=00000000 s09=00000000 d04=0000000000000000
s10=00000000 s11=00000000 d05=0000000000000000
s12=00000000 s13=00000000 d06=0000000000000000
s14=00000000 s15=00000000 d07=0000000000000000
s16=00000000 s17=00000000 d08=0000000000000000
s18=00000000 s19=00000000 d09=0000000000000000
s20=00000000 s21=00000000 d10=0000000000000000
s22=00000000 s23=00000000 d11=0000000000000000
s24=00000000 s25=00000000 d12=0000000000000000
s26=00000000 s27=00000000 d13=0000000000000000
s28=00000000 s29=00000000 d14=0000000000000000
s30=00000000 s31=00000000 d15=0000000000000000
s32=00000000 s33=00000000 d16=0000000000000000
s34=00000000 s35=00000000 d17=0000000000000000
s36=00000000 s37=00000000 d18=0000000000000000
s38=00000000 s39=00000000 d19=0000000000000000
s40=00000000 s41=00000000 d20=0000000000000000
s42=00000000 s43=00000000 d21=0000000000000000
s44=00000000 s45=00000000 d22=0000000000000000
s46=00000000 s47=00000000 d23=0000000000000000
s48=00000000 s49=00000000 d24=0000000000000000
s50=00000000 s51=00000000 d25=0000000000000000
s52=00000000 s53=00000000 d26=0000000000000000
s54=00000000 s55=00000000 d27=0000000000000000
s56=00000000 s57=00000000 d28=0000000000000000
s58=00000000 s59=00000000 d29=0000000000000000
s60=00000000 s61=00000000 d30=0000000000000000
s62=00000000 s63=00000000 d31=0000000000000000
FPSCR: 00000000
Aborted (core dumped)

Alistair

>
> Alistair
>
> >
> > thanks
> > -- PMM
> >
> >
>


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-04  5:25           ` Alistair Francis
  2019-05-04  5:25             ` Alistair Francis
@ 2019-05-05 15:34             ` Peter Maydell
  2019-05-05 15:34               ` Peter Maydell
  2019-06-19  1:04               ` Alistair Francis
  1 sibling, 2 replies; 51+ messages in thread
From: Peter Maydell @ 2019-05-05 15:34 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair, qemu-devel@nongnu.org Developers

On Sat, 4 May 2019 at 06:26, Alistair Francis <alistair23@gmail.com> wrote:
> Ah, it seems like -device loader doesn't work, it looks like not
> setting the thumb register causes this core dump:
>
> qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
>
> R00=20000000 R01=00000574 R02=200015d0 R03=200015d0
> R04=00000000 R05=00000000 R06=00000000 R07=00000000
> R08=00000000 R09=00000000 R10=00000000 R11=00000000
> R12=00000000 R13=ffffffe0 R14=fffffff9 R15=0800cba4

Is the ELF file incorrectly setting the entry point address to not
be a Thumb one (ie low bit set), or is the loader device not honouring
that? (I thought that we'd fixed the latter of those recently...)

thanks
-- PMM

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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-05 15:34             ` Peter Maydell
@ 2019-05-05 15:34               ` Peter Maydell
  2019-06-19  1:04               ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Peter Maydell @ 2019-05-05 15:34 UTC (permalink / raw)
  To: Alistair Francis; +Cc: Alistair, qemu-devel@nongnu.org Developers

On Sat, 4 May 2019 at 06:26, Alistair Francis <alistair23@gmail.com> wrote:
> Ah, it seems like -device loader doesn't work, it looks like not
> setting the thumb register causes this core dump:
>
> qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
>
> R00=20000000 R01=00000574 R02=200015d0 R03=200015d0
> R04=00000000 R05=00000000 R06=00000000 R07=00000000
> R08=00000000 R09=00000000 R10=00000000 R11=00000000
> R12=00000000 R13=ffffffe0 R14=fffffff9 R15=0800cba4

Is the ELF file incorrectly setting the entry point address to not
be a Thumb one (ie low bit set), or is the loader device not honouring
that? (I thought that we'd fixed the latter of those recently...)

thanks
-- PMM


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

* Re: [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2
  2019-05-05 15:34             ` Peter Maydell
  2019-05-05 15:34               ` Peter Maydell
@ 2019-06-19  1:04               ` Alistair Francis
  1 sibling, 0 replies; 51+ messages in thread
From: Alistair Francis @ 2019-06-19  1:04 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Alistair, qemu-devel@nongnu.org Developers

On Sun, May 5, 2019 at 8:34 AM Peter Maydell <peter.maydell@linaro.org> wrote:
>
> On Sat, 4 May 2019 at 06:26, Alistair Francis <alistair23@gmail.com> wrote:
> > Ah, it seems like -device loader doesn't work, it looks like not
> > setting the thumb register causes this core dump:
> >
> > qemu: fatal: Lockup: can't escalate 3 to HardFault (current priority -1)
> >
> > R00=20000000 R01=00000574 R02=200015d0 R03=200015d0
> > R04=00000000 R05=00000000 R06=00000000 R07=00000000
> > R08=00000000 R09=00000000 R10=00000000 R11=00000000
> > R12=00000000 R13=ffffffe0 R14=fffffff9 R15=0800cba4
>
> Is the ELF file incorrectly setting the entry point address to not
> be a Thumb one (ie low bit set), or is the loader device not honouring
> that? (I thought that we'd fixed the latter of those recently...)

It looks like all the reset logic is correct in terms of these lines
in arm_cpu_reset():
        env->regs[13] = initial_msp & 0xFFFFFFFC;
        env->regs[15] = initial_pc & ~1;
        env->thumb = initial_pc & 1;

The problem is that vecbase is 0, as cpu->init_svtor is 0.

cpu->init_svtor is set via QOM properties in armv7m_realize() based on
the armv7m property "init-svtor".

So hopefully I should be able to just set the property "init-svtor"
for the armv7m object. I'll test that out and see how it goes.

Alistair

>
> thanks
> -- PMM


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

end of thread, other threads:[~2019-06-19  1:08 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1556515687.git.alistair@alistair23.me>
2019-04-29  5:29 ` [Qemu-devel] [PATCH v1 1/5] armv7m: Allow entry information to be returned Alistair Francis
2019-04-29  5:29   ` Alistair Francis
2019-04-29  5:32 ` Alistair Francis
2019-04-29  5:32   ` Alistair Francis
2019-04-30 16:04   ` Peter Maydell
2019-04-30 16:04     ` Peter Maydell
2019-05-01  3:54     ` Alistair Francis
2019-05-01  3:54       ` Alistair Francis
2019-04-29  5:32 ` [Qemu-devel] [PATCH v1 2/5] hw/misc: Add the STM32F4xx Sysconfig device Alistair Francis
2019-04-29  5:32   ` Alistair Francis
2019-04-30 15:44   ` Peter Maydell
2019-04-30 15:44     ` Peter Maydell
2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 3/5] hw/misc: Add the STM32F4xx EXTI device Alistair Francis
2019-04-29  5:33   ` Alistair Francis
2019-04-30 15:48   ` Peter Maydell
2019-04-30 15:48     ` Peter Maydell
2019-05-02  4:28     ` Alistair Francis
2019-05-02  4:28       ` Alistair Francis
2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 4/5] hw/arm: Add the STM32F4xx SoC Alistair Francis
2019-04-29  5:33   ` Alistair Francis
2019-04-29 12:38   ` KONRAD Frederic
2019-04-29 12:38     ` KONRAD Frederic
2019-04-29 17:00     ` Alistair Francis
2019-04-29 17:00       ` Alistair Francis
2019-04-30 18:10       ` KONRAD Frederic
2019-04-30 18:10         ` KONRAD Frederic
2019-04-29 12:43   ` Philippe Mathieu-Daudé
2019-04-29 12:43     ` Philippe Mathieu-Daudé
2019-04-29 17:01     ` Alistair Francis
2019-04-29 17:01       ` Alistair Francis
2019-04-30 15:51       ` Peter Maydell
2019-04-30 15:51         ` Peter Maydell
2019-04-30 15:59   ` Peter Maydell
2019-04-30 15:59     ` Peter Maydell
2019-05-02  5:04     ` Alistair Francis
2019-05-02  5:04       ` Alistair Francis
2019-04-29  5:33 ` [Qemu-devel] [PATCH v1 5/5] hw/arm: Add the Netduino Plus 2 Alistair Francis
2019-04-29  5:33   ` Alistair Francis
2019-04-30 16:01   ` Peter Maydell
2019-04-30 16:01     ` Peter Maydell
2019-04-30 20:27     ` Alistair Francis
2019-04-30 20:27       ` Alistair Francis
2019-05-02 10:05       ` Peter Maydell
2019-05-02 10:05         ` Peter Maydell
2019-05-04  4:25         ` Alistair
2019-05-04  4:25           ` Alistair
2019-05-04  5:25           ` Alistair Francis
2019-05-04  5:25             ` Alistair Francis
2019-05-05 15:34             ` Peter Maydell
2019-05-05 15:34               ` Peter Maydell
2019-06-19  1:04               ` Alistair Francis

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