mirror of https://github.com/xqemu/xqemu.git
target-arm:
* provide PL031 RTC in virt board * fix missing pxa2xx and strongarm vmstate * convert cadence_ttc to instance_init * fix libvixl format strings and README -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABCAAGBQJTsVuxAAoJEDwlJe0UNgzeSX0P/1e24zP1QlEKSWLLDRceUhvR tAvAOXPGtrDqQpzWXMZ/cbxZruPA/0LrRTwqccApNXGGvzotkqf+P22gHJYEKEMH gCcyd1bKCTvBpis4CxCaM7KMMBNlQ22n4aaVgMJyczETM5atxOM6csGUJOjpHUY0 4qsTwLVVnCZBB7hz9LRkb8SKNW98lHuaYT9q0JFt0PqFWT2/eT9czHGz0JMvUaUr Fy8v0GpE2nxDy8//6LZofsrbYaIuJoojhflaSXeUqtDoSGPTxrJZuiQUSqbF+6D9 64V/aGT/NzT4qoZUxYxYdJL9tE4R6lAkR6/hniFUFHEPiFMB0adLJ1+j48zw4gzB lN0PuEJ42wCV2ixdNXyN7VqFwipD2ta1PB4/NOnfqHG5udJUGpYougOKwhnrdMTM rgqJsxy5Ari+5xrqGAIlWwdUItAhHC0PJoOrVvqvwy5+hlCa6Tb4psl6Z9CLjGzR 4TAAe/L6CGpyWH6erSn7+tTIFTMAgnANYkNZ6ttiEDFsdjggCB35ebgMVBUxi4+N m1TjexOFCPHwfruYmW4pIG2pnIQchxT9BIVCikGjykdj+6Na4/mOwVlDVIhzRRvb J3JkRE/7oQ3sOWxYBNXWECcHB9VHDFNAW47o5uCXzlu5vJXYLIDT9dBw+KS29e56 i3kG0byQWtojyLikVs3k =leR3 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20140630' into staging target-arm: * provide PL031 RTC in virt board * fix missing pxa2xx and strongarm vmstate * convert cadence_ttc to instance_init * fix libvixl format strings and README # gpg: Signature made Mon 30 Jun 2014 13:44:33 BST using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20140630: disas/libvixl: Fix wrong format strings disas/libvixl: Update README for version base timer: cadence_ttc: Convert to instance_init hw/arm/pxa2xx_gpio: Correct and register vmstate hw/arm/pxa2xx_gpio: Fix handling of GPSR/GPCR reads hw/arm/strongarm: Wire up missing GPIO and PPC vmstate hw/arm/strongarm: Fix handling of GPSR/GPCR reads hw/arm/virt: Provide PL031 RTC Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a156dd9a22
|
@ -2,7 +2,7 @@
|
||||||
The code in this directory is a subset of libvixl:
|
The code in this directory is a subset of libvixl:
|
||||||
https://github.com/armvixl/vixl
|
https://github.com/armvixl/vixl
|
||||||
(specifically, it is the set of files needed for disassembly only,
|
(specifically, it is the set of files needed for disassembly only,
|
||||||
taken from libvixl 1.1).
|
taken from libvixl 1.4).
|
||||||
Bugfixes should preferably be sent upstream initially.
|
Bugfixes should preferably be sent upstream initially.
|
||||||
|
|
||||||
The disassembler does not currently support the entire A64 instruction
|
The disassembler does not currently support the entire A64 instruction
|
||||||
|
|
|
@ -1369,7 +1369,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||||
VIXL_ASSERT(format[5] == 'L');
|
VIXL_ASSERT(format[5] == 'L');
|
||||||
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
||||||
if (instr->ShiftMoveWide() > 0) {
|
if (instr->ShiftMoveWide() > 0) {
|
||||||
AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
|
AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 8;
|
return 8;
|
||||||
|
@ -1418,7 +1418,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||||
}
|
}
|
||||||
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
||||||
if (format[3] == 'F') { // IFPFbits.
|
if (format[3] == 'F') { // IFPFbits.
|
||||||
AppendToOutput("#%d", 64 - instr->FPScale());
|
AppendToOutput("#%" PRId64, 64 - instr->FPScale());
|
||||||
return 8;
|
return 8;
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
||||||
|
@ -1439,23 +1439,23 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
case 'P': { // IP - Conditional compare.
|
case 'P': { // IP - Conditional compare.
|
||||||
AppendToOutput("#%d", instr->ImmCondCmp());
|
AppendToOutput("#%" PRId64, instr->ImmCondCmp());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'B': { // Bitfields.
|
case 'B': { // Bitfields.
|
||||||
return SubstituteBitfieldImmediateField(instr, format);
|
return SubstituteBitfieldImmediateField(instr, format);
|
||||||
}
|
}
|
||||||
case 'E': { // IExtract.
|
case 'E': { // IExtract.
|
||||||
AppendToOutput("#%d", instr->ImmS());
|
AppendToOutput("#%" PRId64, instr->ImmS());
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
case 'S': { // IS - Test and branch bit.
|
case 'S': { // IS - Test and branch bit.
|
||||||
AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
|
AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
|
||||||
instr->ImmTestBranchBit40());
|
instr->ImmTestBranchBit40());
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
case 'D': { // IDebug - HLT and BRK instructions.
|
case 'D': { // IDebug - HLT and BRK instructions.
|
||||||
AppendToOutput("#0x%x", instr->ImmException());
|
AppendToOutput("#0x%" PRIx64, instr->ImmException());
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
|
@ -1626,12 +1626,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||||
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
||||||
(instr->ExtendMode() == UXTX))) {
|
(instr->ExtendMode() == UXTX))) {
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(", lsl #%d", instr->ImmExtendShift());
|
AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
||||||
if (instr->ImmExtendShift() > 0) {
|
if (instr->ImmExtendShift() > 0) {
|
||||||
AppendToOutput(" #%d", instr->ImmExtendShift());
|
AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -1660,7 +1660,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||||
if (!((ext == UXTX) && (shift == 0))) {
|
if (!((ext == UXTX) && (shift == 0))) {
|
||||||
AppendToOutput(", %s", extend_mode[ext]);
|
AppendToOutput(", %s", extend_mode[ext]);
|
||||||
if (shift != 0) {
|
if (shift != 0) {
|
||||||
AppendToOutput(" #%d", instr->SizeLS());
|
AppendToOutput(" #%" PRId64, instr->SizeLS());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 9;
|
return 9;
|
||||||
|
|
|
@ -36,7 +36,6 @@ struct PXA2xxGPIOInfo {
|
||||||
uint32_t rising[PXA2XX_GPIO_BANKS];
|
uint32_t rising[PXA2XX_GPIO_BANKS];
|
||||||
uint32_t falling[PXA2XX_GPIO_BANKS];
|
uint32_t falling[PXA2XX_GPIO_BANKS];
|
||||||
uint32_t status[PXA2XX_GPIO_BANKS];
|
uint32_t status[PXA2XX_GPIO_BANKS];
|
||||||
uint32_t gpsr[PXA2XX_GPIO_BANKS];
|
|
||||||
uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
|
uint32_t gafr[PXA2XX_GPIO_BANKS * 2];
|
||||||
|
|
||||||
uint32_t prev_level[PXA2XX_GPIO_BANKS];
|
uint32_t prev_level[PXA2XX_GPIO_BANKS];
|
||||||
|
@ -162,14 +161,14 @@ static uint64_t pxa2xx_gpio_read(void *opaque, hwaddr offset,
|
||||||
return s->dir[bank];
|
return s->dir[bank];
|
||||||
|
|
||||||
case GPSR: /* GPIO Pin-Output Set registers */
|
case GPSR: /* GPIO Pin-Output Set registers */
|
||||||
printf("%s: Read from a write-only register " REG_FMT "\n",
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
__FUNCTION__, offset);
|
"pxa2xx GPIO: read from write only register GPSR\n");
|
||||||
return s->gpsr[bank]; /* Return last written value. */
|
return 0;
|
||||||
|
|
||||||
case GPCR: /* GPIO Pin-Output Clear registers */
|
case GPCR: /* GPIO Pin-Output Clear registers */
|
||||||
printf("%s: Read from a write-only register " REG_FMT "\n",
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
__FUNCTION__, offset);
|
"pxa2xx GPIO: read from write only register GPCR\n");
|
||||||
return 31337; /* Specified as unpredictable in the docs. */
|
return 0;
|
||||||
|
|
||||||
case GRER: /* GPIO Rising-Edge Detect Enable registers */
|
case GRER: /* GPIO Rising-Edge Detect Enable registers */
|
||||||
return s->rising[bank];
|
return s->rising[bank];
|
||||||
|
@ -217,7 +216,6 @@ static void pxa2xx_gpio_write(void *opaque, hwaddr offset,
|
||||||
case GPSR: /* GPIO Pin-Output Set registers */
|
case GPSR: /* GPIO Pin-Output Set registers */
|
||||||
s->olevel[bank] |= value;
|
s->olevel[bank] |= value;
|
||||||
pxa2xx_gpio_handler_update(s);
|
pxa2xx_gpio_handler_update(s);
|
||||||
s->gpsr[bank] = value;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCR: /* GPIO Pin-Output Clear registers */
|
case GPCR: /* GPIO Pin-Output Clear registers */
|
||||||
|
@ -314,7 +312,6 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_INT32(lines, PXA2xxGPIOInfo),
|
|
||||||
VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
|
@ -322,6 +319,7 @@ static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
|
||||||
VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
|
VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
|
||||||
|
VMSTATE_UINT32_ARRAY(prev_level, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
|
||||||
VMSTATE_END_OF_LIST(),
|
VMSTATE_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -340,6 +338,7 @@ static void pxa2xx_gpio_class_init(ObjectClass *klass, void *data)
|
||||||
k->init = pxa2xx_gpio_initfn;
|
k->init = pxa2xx_gpio_initfn;
|
||||||
dc->desc = "PXA2xx GPIO controller";
|
dc->desc = "PXA2xx GPIO controller";
|
||||||
dc->props = pxa2xx_gpio_properties;
|
dc->props = pxa2xx_gpio_properties;
|
||||||
|
dc->vmsd = &vmstate_pxa2xx_gpio_regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pxa2xx_gpio_info = {
|
static const TypeInfo pxa2xx_gpio_info = {
|
||||||
|
|
|
@ -480,7 +480,6 @@ struct StrongARMGPIOInfo {
|
||||||
uint32_t rising;
|
uint32_t rising;
|
||||||
uint32_t falling;
|
uint32_t falling;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
uint32_t gpsr;
|
|
||||||
uint32_t gafr;
|
uint32_t gafr;
|
||||||
|
|
||||||
uint32_t prev_level;
|
uint32_t prev_level;
|
||||||
|
@ -544,14 +543,14 @@ static uint64_t strongarm_gpio_read(void *opaque, hwaddr offset,
|
||||||
return s->dir;
|
return s->dir;
|
||||||
|
|
||||||
case GPSR: /* GPIO Pin-Output Set registers */
|
case GPSR: /* GPIO Pin-Output Set registers */
|
||||||
DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
__func__, offset);
|
"strongarm GPIO: read from write only register GPSR\n");
|
||||||
return s->gpsr; /* Return last written value. */
|
return 0;
|
||||||
|
|
||||||
case GPCR: /* GPIO Pin-Output Clear registers */
|
case GPCR: /* GPIO Pin-Output Clear registers */
|
||||||
DPRINTF("%s: Read from a write-only register 0x" TARGET_FMT_plx "\n",
|
qemu_log_mask(LOG_GUEST_ERROR,
|
||||||
__func__, offset);
|
"strongarm GPIO: read from write only register GPCR\n");
|
||||||
return 31337; /* Specified as unpredictable in the docs. */
|
return 0;
|
||||||
|
|
||||||
case GRER: /* GPIO Rising-Edge Detect Enable registers */
|
case GRER: /* GPIO Rising-Edge Detect Enable registers */
|
||||||
return s->rising;
|
return s->rising;
|
||||||
|
@ -590,7 +589,6 @@ static void strongarm_gpio_write(void *opaque, hwaddr offset,
|
||||||
case GPSR: /* GPIO Pin-Output Set registers */
|
case GPSR: /* GPIO Pin-Output Set registers */
|
||||||
s->olevel |= value;
|
s->olevel |= value;
|
||||||
strongarm_gpio_handler_update(s);
|
strongarm_gpio_handler_update(s);
|
||||||
s->gpsr = value;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GPCR: /* GPIO Pin-Output Clear registers */
|
case GPCR: /* GPIO Pin-Output Clear registers */
|
||||||
|
@ -676,6 +674,7 @@ static const VMStateDescription vmstate_strongarm_gpio_regs = {
|
||||||
VMSTATE_UINT32(falling, StrongARMGPIOInfo),
|
VMSTATE_UINT32(falling, StrongARMGPIOInfo),
|
||||||
VMSTATE_UINT32(status, StrongARMGPIOInfo),
|
VMSTATE_UINT32(status, StrongARMGPIOInfo),
|
||||||
VMSTATE_UINT32(gafr, StrongARMGPIOInfo),
|
VMSTATE_UINT32(gafr, StrongARMGPIOInfo),
|
||||||
|
VMSTATE_UINT32(prev_level, StrongARMGPIOInfo),
|
||||||
VMSTATE_END_OF_LIST(),
|
VMSTATE_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -687,6 +686,7 @@ static void strongarm_gpio_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
k->init = strongarm_gpio_initfn;
|
k->init = strongarm_gpio_initfn;
|
||||||
dc->desc = "StrongARM GPIO controller";
|
dc->desc = "StrongARM GPIO controller";
|
||||||
|
dc->vmsd = &vmstate_strongarm_gpio_regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo strongarm_gpio_info = {
|
static const TypeInfo strongarm_gpio_info = {
|
||||||
|
@ -846,6 +846,7 @@ static const VMStateDescription vmstate_strongarm_ppc_regs = {
|
||||||
VMSTATE_UINT32(ppar, StrongARMPPCInfo),
|
VMSTATE_UINT32(ppar, StrongARMPPCInfo),
|
||||||
VMSTATE_UINT32(psdr, StrongARMPPCInfo),
|
VMSTATE_UINT32(psdr, StrongARMPPCInfo),
|
||||||
VMSTATE_UINT32(ppfr, StrongARMPPCInfo),
|
VMSTATE_UINT32(ppfr, StrongARMPPCInfo),
|
||||||
|
VMSTATE_UINT32(prev_level, StrongARMPPCInfo),
|
||||||
VMSTATE_END_OF_LIST(),
|
VMSTATE_END_OF_LIST(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -857,6 +858,7 @@ static void strongarm_ppc_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
||||||
k->init = strongarm_ppc_init;
|
k->init = strongarm_ppc_init;
|
||||||
dc->desc = "StrongARM PPC controller";
|
dc->desc = "StrongARM PPC controller";
|
||||||
|
dc->vmsd = &vmstate_strongarm_ppc_regs;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo strongarm_ppc_info = {
|
static const TypeInfo strongarm_ppc_info = {
|
||||||
|
|
|
@ -65,6 +65,7 @@ enum {
|
||||||
VIRT_GIC_CPU,
|
VIRT_GIC_CPU,
|
||||||
VIRT_UART,
|
VIRT_UART,
|
||||||
VIRT_MMIO,
|
VIRT_MMIO,
|
||||||
|
VIRT_RTC,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct MemMapEntry {
|
typedef struct MemMapEntry {
|
||||||
|
@ -92,6 +93,8 @@ typedef struct VirtBoardInfo {
|
||||||
* high memory region beyond 4GB).
|
* high memory region beyond 4GB).
|
||||||
* This represents a compromise between how much RAM can be given to
|
* This represents a compromise between how much RAM can be given to
|
||||||
* a 32 bit VM and leaving space for expansion and in particular for PCI.
|
* a 32 bit VM and leaving space for expansion and in particular for PCI.
|
||||||
|
* Note that devices should generally be placed at multiples of 0x10000,
|
||||||
|
* to accommodate guests using 64K pages.
|
||||||
*/
|
*/
|
||||||
static const MemMapEntry a15memmap[] = {
|
static const MemMapEntry a15memmap[] = {
|
||||||
/* Space up to 0x8000000 is reserved for a boot ROM */
|
/* Space up to 0x8000000 is reserved for a boot ROM */
|
||||||
|
@ -101,6 +104,7 @@ static const MemMapEntry a15memmap[] = {
|
||||||
[VIRT_GIC_DIST] = { 0x8000000, 0x10000 },
|
[VIRT_GIC_DIST] = { 0x8000000, 0x10000 },
|
||||||
[VIRT_GIC_CPU] = { 0x8010000, 0x10000 },
|
[VIRT_GIC_CPU] = { 0x8010000, 0x10000 },
|
||||||
[VIRT_UART] = { 0x9000000, 0x1000 },
|
[VIRT_UART] = { 0x9000000, 0x1000 },
|
||||||
|
[VIRT_RTC] = { 0x90010000, 0x1000 },
|
||||||
[VIRT_MMIO] = { 0xa000000, 0x200 },
|
[VIRT_MMIO] = { 0xa000000, 0x200 },
|
||||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||||
/* 0x10000000 .. 0x40000000 reserved for PCI */
|
/* 0x10000000 .. 0x40000000 reserved for PCI */
|
||||||
|
@ -109,6 +113,7 @@ static const MemMapEntry a15memmap[] = {
|
||||||
|
|
||||||
static const int a15irqmap[] = {
|
static const int a15irqmap[] = {
|
||||||
[VIRT_UART] = 1,
|
[VIRT_UART] = 1,
|
||||||
|
[VIRT_RTC] = 2,
|
||||||
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
|
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -353,6 +358,29 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||||
g_free(nodename);
|
g_free(nodename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||||
|
{
|
||||||
|
char *nodename;
|
||||||
|
hwaddr base = vbi->memmap[VIRT_RTC].base;
|
||||||
|
hwaddr size = vbi->memmap[VIRT_RTC].size;
|
||||||
|
int irq = vbi->irqmap[VIRT_RTC];
|
||||||
|
const char compat[] = "arm,pl031\0arm,primecell";
|
||||||
|
|
||||||
|
sysbus_create_simple("pl031", base, pic[irq]);
|
||||||
|
|
||||||
|
nodename = g_strdup_printf("/pl031@%" PRIx64, base);
|
||||||
|
qemu_fdt_add_subnode(vbi->fdt, nodename);
|
||||||
|
qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat));
|
||||||
|
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
|
||||||
|
2, base, 2, size);
|
||||||
|
qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
|
||||||
|
GIC_FDT_IRQ_TYPE_SPI, irq,
|
||||||
|
GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
|
||||||
|
qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle);
|
||||||
|
qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
|
||||||
|
g_free(nodename);
|
||||||
|
}
|
||||||
|
|
||||||
static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
|
static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -469,6 +497,8 @@ static void machvirt_init(MachineState *machine)
|
||||||
|
|
||||||
create_uart(vbi, pic);
|
create_uart(vbi, pic);
|
||||||
|
|
||||||
|
create_rtc(vbi, pic);
|
||||||
|
|
||||||
/* Create mmio transports, so the user can create virtio backends
|
/* Create mmio transports, so the user can create virtio backends
|
||||||
* (which will be automatically plugged in to the transports). If
|
* (which will be automatically plugged in to the transports). If
|
||||||
* no backend is created the transport will just sit harmlessly idle.
|
* no backend is created the transport will just sit harmlessly idle.
|
||||||
|
|
|
@ -406,21 +406,19 @@ static void cadence_timer_init(uint32_t freq, CadenceTimerState *s)
|
||||||
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s);
|
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, cadence_timer_tick, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cadence_ttc_init(SysBusDevice *dev)
|
static void cadence_ttc_init(Object *obj)
|
||||||
{
|
{
|
||||||
CadenceTTCState *s = CADENCE_TTC(dev);
|
CadenceTTCState *s = CADENCE_TTC(obj);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 3; ++i) {
|
for (i = 0; i < 3; ++i) {
|
||||||
cadence_timer_init(133000000, &s->timer[i]);
|
cadence_timer_init(133000000, &s->timer[i]);
|
||||||
sysbus_init_irq(dev, &s->timer[i].irq);
|
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->timer[i].irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, OBJECT(s), &cadence_ttc_ops, s,
|
memory_region_init_io(&s->iomem, obj, &cadence_ttc_ops, s,
|
||||||
"timer", 0x1000);
|
"timer", 0x1000);
|
||||||
sysbus_init_mmio(dev, &s->iomem);
|
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cadence_timer_pre_save(void *opaque)
|
static void cadence_timer_pre_save(void *opaque)
|
||||||
|
@ -474,9 +472,7 @@ static const VMStateDescription vmstate_cadence_ttc = {
|
||||||
static void cadence_ttc_class_init(ObjectClass *klass, void *data)
|
static void cadence_ttc_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
sdc->init = cadence_ttc_init;
|
|
||||||
dc->vmsd = &vmstate_cadence_ttc;
|
dc->vmsd = &vmstate_cadence_ttc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,6 +480,7 @@ static const TypeInfo cadence_ttc_info = {
|
||||||
.name = TYPE_CADENCE_TTC,
|
.name = TYPE_CADENCE_TTC,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(CadenceTTCState),
|
.instance_size = sizeof(CadenceTTCState),
|
||||||
|
.instance_init = cadence_ttc_init,
|
||||||
.class_init = cadence_ttc_class_init,
|
.class_init = cadence_ttc_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue