armv7-m: exit on external reset request
v4 cover armv7-m: exit on external reset request
Resending patch set. The only change from v3 is to the message of #3.
Changes armv7-m to implement the SYSRESETREQ register as GPIO. This necessitates some refactoring of armv7m_init() and the board code which calls it to allow the additional named GPIO to be used in board code.
The Stellaris board installs a handler which calls qemu_system_reset_request().
Michael Davidsaver (3):
armv7-m: Return DeviceState* from armv7m_init()
armv7-m: Implement SYSRESETREQ
arm: stellaris: exit on external reset request
hw/arm/armv7m.c | 9 ++------- hw/arm/stellaris.c | 41 ++++++++++++++++++++++++++++++----------- hw/arm/stm32f205_soc.c | 15 ++++++++------- hw/intc/armv7m_nvic.c | 9 ++++++++- include/hw/arm/arm.h | 2 +- 5 files changed, 49 insertions(+), 27 deletions(-)
Signature · 1 line
2.1.4
PATCH v4 1/3 armv7-m: Return DeviceState* from armv7m_init()
Change armv7m_init to return the DeviceState* for the NVIC. This allows access to all GPIO blocks, not just the IRQ inputs. Move qdev_get_gpio_in() calls out of armv7m_init() into board code for stellaris and stm32f205 boards.
--- hw/arm/armv7m.c | 9 ++------- hw/arm/stellaris.c | 29 ++++++++++++++++++----------- hw/arm/stm32f205_soc.c | 15 ++++++++------- include/hw/arm/arm.h | 2 +- 4 files changed, 29 insertions(+), 26 deletions(-)
hw/arm/armv7m.c +2 -7
@@ -166,17 +166,15 @@ static void armv7m_reset(void *opaque)mem_size is in bytes. Returns the NVIC array. */ -qemu_irq *armv7m_init (MemoryRegion *system_memory,int mem_size,int num_irq, +DeviceState *armv7m_init (MemoryRegion *system_memory,int mem_size,int num_irq,const char *kernel_filename,const char *cpu_model) {ARMCPU *cpu;CPUARMState *env;DeviceState *nvic; -qemu_irq *pic =g_new (qemu_irq, num_irq);int image_size;uint64_t entry;uint64_t lowaddr; -int i;int big_endian;MemoryRegion *hack =g_new (MemoryRegion,1 );
@@ -198,9 +196,6 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,qdev_init_nofail (nvic);sysbus_connect_irq (SYS_BUS_DEVICE (nvic),0 ,qdev_get_gpio_in (DEVICE (cpu),ARM_CPU_IRQ )); -for (i =0 ; i < num_irq; i++) { - pic[i] =qdev_get_gpio_in (nvic, i); - }#ifdef TARGET_WORDS_BIGENDIAN big_endian =1 ;
@@ -234,7 +229,7 @@ qemu_irq *armv7m_init(MemoryRegion *system_memory, int mem_size, int num_irq,memory_region_add_subregion (system_memory,0xfffff000 , hack);qemu_register_reset (armv7m_reset, cpu); -return pic; +return nvic; }static Property bitband_properties[] = {
hw/arm/stellaris.c +18 -11
@@ -1210,8 +1210,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, 0x40024000, 0x40025000, 0x40026000};static const int gpio_irq[7 ] = {0 ,1 ,2 ,3 ,4 ,30 ,31 }; -qemu_irq *pic; -DeviceState *gpio_dev[7 ]; +DeviceState *gpio_dev[7 ], *nvic;qemu_irq gpio_in[7 ][8 ];qemu_irq gpio_out[7 ][8 ];qemu_irq adc;
@@ -1241,12 +1240,16 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,vmstate_register_ram_global (sram);memory_region_add_subregion (system_memory,0x20000000 , sram); - pic =armv7m_init (system_memory, flash_size,NUM_IRQ_LINES , + nvic =armv7m_init (system_memory, flash_size,NUM_IRQ_LINES , kernel_filename, cpu_model);if (board->dc1 & (1 <<16 )) { dev =sysbus_create_varargs (TYPE_STELLARIS_ADC ,0x40038000 , - pic[14 ], pic[15 ], pic[16 ], pic[17 ],NULL ); +qdev_get_gpio_in (nvic,14 ), +qdev_get_gpio_in (nvic,15 ), +qdev_get_gpio_in (nvic,16 ), +qdev_get_gpio_in (nvic,17 ), +NULL ); adc =qdev_get_gpio_in (dev,0 ); }else { adc =NULL ;
@@ -1255,19 +1258,21 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,if (board->dc2 & (0x10000 << i)) { dev =sysbus_create_simple (TYPE_STELLARIS_GPTM ,0x40030000 + i *0x1000 , - pic[timer_irq[i]]); +qdev_get_gpio_in (nvic, timer_irq[i]));/* TODO: This is incorrect, but we get away with it because the ADC output is only ever pulsed. */ qdev_connect_gpio_out (dev,0 , adc); } } -stellaris_sys_init (0x400fe000 , pic[28 ], board, nd_table[0 ].macaddr.a); +stellaris_sys_init (0x400fe000 ,qdev_get_gpio_in (nvic,28 ), + board, nd_table[0 ].macaddr.a);for (i =0 ; i <7 ; i++) {if (board->dc4 & (1 << i)) { gpio_dev[i] =sysbus_create_simple ("pl061_luminary" , gpio_addr[i], - pic[gpio_irq[i]]); +qdev_get_gpio_in (nvic, + gpio_irq[i]));for (j =0 ; j <8 ; j++) { gpio_in[i][j] =qdev_get_gpio_in (gpio_dev[i], j); gpio_out[i][j] =NULL ;
@@ -1276,7 +1281,8 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, }if (board->dc2 & (1 <<12 )) { - dev =sysbus_create_simple (TYPE_STELLARIS_I2C ,0x40020000 , pic[8 ]); + dev =sysbus_create_simple (TYPE_STELLARIS_I2C ,0x40020000 , +qdev_get_gpio_in (nvic,8 )); i2c = (I2CBus *)qdev_get_child_bus (dev,"i2c" );if (board->peripherals &BP_OLED_I2C ) {i2c_create_slave (i2c,"ssd0303" ,0x3d );
@@ -1286,11 +1292,12 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,for (i =0 ; i <4 ; i++) {if (board->dc2 & (1 << i)) {sysbus_create_simple ("pl011_luminary" ,0x4000c000 + i *0x1000 , - pic[uart_irq[i]]); +qdev_get_gpio_in (nvic, uart_irq[i])); } }if (board->dc2 & (1 <<4 )) { - dev =sysbus_create_simple ("pl022" ,0x40008000 , pic[7 ]); + dev =sysbus_create_simple ("pl022" ,0x40008000 , +qdev_get_gpio_in (nvic,7 ));if (board->peripherals &BP_OLED_SSI ) {void *bus;DeviceState *sddev;
@@ -1326,7 +1333,7 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,qdev_set_nic_properties (enet, &nd_table[0 ]);qdev_init_nofail (enet);sysbus_mmio_map (SYS_BUS_DEVICE (enet),0 ,0x40048000 ); -sysbus_connect_irq (SYS_BUS_DEVICE (enet),0 , pic[42 ]); +sysbus_connect_irq (SYS_BUS_DEVICE (enet),0 ,qdev_get_gpio_in (nvic,42 )); }if (board->peripherals &BP_GAMEPAD ) {qemu_irq gpad_irq[5 ];
hw/arm/stm32f205_soc.c +8 -7
@@ -59,9 +59,8 @@ static void stm32f205_soc_initfn(Object *obj)static void stm32f205_soc_realize (DeviceState *dev_soc,Error **errp) {STM32F205State *s =STM32F205_SOC (dev_soc); -DeviceState *syscfgdev, *usartdev, *timerdev; +DeviceState *syscfgdev, *usartdev, *timerdev, *nvic;SysBusDevice *syscfgbusdev, *usartbusdev, *timerbusdev; -qemu_irq *pic;Error *err =NULL ;int i;
@@ -88,8 +87,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)vmstate_register_ram_global (sram);memory_region_add_subregion (system_memory,SRAM_BASE_ADDRESS , sram); - pic =armv7m_init (get_system_memory (),FLASH_SIZE ,96 , - s->kernel_filename, s->cpu_model); + nvic =armv7m_init (get_system_memory (),FLASH_SIZE ,96 , + s->kernel_filename, s->cpu_model);/* System configuration controller */ syscfgdev =DEVICE (&s->syscfg);
@@ -100,7 +99,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } syscfgbusdev =SYS_BUS_DEVICE (syscfgdev);sysbus_mmio_map (syscfgbusdev,0 ,0x40013800 ); -sysbus_connect_irq (syscfgbusdev,0 , pic[71 ]); +sysbus_connect_irq (syscfgbusdev,0 ,qdev_get_gpio_in (nvic,71 ));/* Attach UART (uses USART registers) and USART controllers */ for (i =0 ; i <STM_NUM_USARTS ; i++) {
@@ -112,7 +111,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } usartbusdev =SYS_BUS_DEVICE (usartdev);sysbus_mmio_map (usartbusdev,0 , usart_addr[i]); -sysbus_connect_irq (usartbusdev,0 , pic[usart_irq[i]]); +sysbus_connect_irq (usartbusdev,0 , +qdev_get_gpio_in (nvic, usart_irq[i])); }/* Timer 2 to 5 */
@@ -126,7 +126,8 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp) } timerbusdev =SYS_BUS_DEVICE (timerdev);sysbus_mmio_map (timerbusdev,0 , timer_addr[i]); -sysbus_connect_irq (timerbusdev,0 , pic[timer_irq[i]]); +sysbus_connect_irq (timerbusdev,0 , +qdev_get_gpio_in (nvic, timer_irq[i])); } }
include/hw/arm/arm.h +1 -1
@@ -17,7 +17,7 @@#include "cpu.h" /* armv7m.c */ -qemu_irq *armv7m_init (MemoryRegion *system_memory,int mem_size,int num_irq, +DeviceState *armv7m_init (MemoryRegion *system_memory,int mem_size,int num_irq,const char *kernel_filename,const char *cpu_model);/*
Signature · 1 line
2.1.4
PATCH v4 2/3 armv7-m: Implement SYSRESETREQ
In reply to Michael DavidsaverImplement the SYSRESETREQ bit of the AIRCR register for armv7-m (ie. cortex-m3) to trigger a GPIO out.
--- hw/intc/armv7m_nvic.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
hw/intc/armv7m_nvic.c +8 -1
@@ -28,6 +28,7 @@ typedef struct {MemoryRegion gic_iomem_alias;MemoryRegion container;uint32_t num_irq; +qemu_irq sysresetreq; } nvic_state;#define TYPE_NVIC "armv7m_nvic"
@@ -348,10 +349,13 @@ static void nvic_writel(nvic_state *s, uint32_t offset, uint32_t value)break ;case 0xd0c :/* Application Interrupt/Reset Control. */ if ((value >>16 ) ==0x05fa ) { +if (value &4 ) { +qemu_irq_pulse (s->sysresetreq); + }if (value &2 ) {qemu_log_mask (LOG_UNIMP ,"VECTCLRACTIVE unimplemented\n" ); } -if (value &5 ) { +if (value &1 ) {qemu_log_mask (LOG_UNIMP ,"AIRCR system reset unimplemented\n" ); }if (value &0x700 ) {
@@ -535,11 +539,14 @@ static void armv7m_nvic_instance_init(Object *obj)* value in the GICState struct. */ GICState *s =ARM_GIC_COMMON (obj); +DeviceState *dev =DEVICE (obj); +nvic_state *nvic =NVIC (obj);/* The ARM v7m may have anything from 0 to 496 external interrupt * IRQ lines. We default to 64. Other boards may differ and should * set the num-irq property appropriately. */ s->num_irq =64 ; +qdev_init_gpio_out_named (dev, &nvic->sysresetreq,"SYSRESETREQ" ,1 ); }static void armv7m_nvic_class_init (ObjectClass *klass,void *data)
Signature · 1 line
2.1.4
PATCH v4 3/3 arm: stellaris: exit on external reset request
In reply to Michael DavidsaverAdd GPIO in for the stellaris board which callsqemu_system_reset_request() on reset request.
--- hw/arm/stellaris.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
hw/arm/stellaris.c +12 -0
@@ -16,6 +16,7 @@#include "net/net.h" #include "hw/boards.h" #include "exec/address-spaces.h" +#include "sysemu/sysemu.h" #define GPIO_A 0#define GPIO_B 1
@@ -1176,6 +1177,14 @@ static int stellaris_adc_init(SysBusDevice *sbd)return 0 ; } +static +void do_sys_reset (void *opaque,int n,int level) +{ +if (level) { +qemu_system_reset_request (); + } +} +/* Board init. */ static stellaris_board_info stellaris_boards[] = { {"LM3S811EVB" ,
@@ -1243,6 +1252,9 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model, nvic =armv7m_init (system_memory, flash_size,NUM_IRQ_LINES , kernel_filename, cpu_model); +qdev_connect_gpio_out_named (nvic,"SYSRESETREQ" ,0 , +qemu_allocate_irq (&do_sys_reset,NULL ,0 )); +if (board->dc1 & (1 <<16 )) { dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000, qdev_get_gpio_in(nvic, 14),
Signature · 1 line
2.1.4
Quoted 8 lines · Michael Davidsaver
Resending patch set. The only change from v3 is to the message of #3.
Changes armv7-m to implement the SYSRESETREQ register as GPIO. This necessitates some refactoring of
armv7m_init()and the board code which calls it to allow the additional named GPIO to be used in board code.
The Stellaris board installs a handler which callsqemu_system_reset_request().
Thanks for the resend; in fact I'd already applied your v3 to target-arm.next (with the change to the 3/3 commit message).
thanks
-- PMM