mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20151217-1' into staging
target-arm queue: * i.MX CCM patches * support guest debug for AArch64 KVM * support power button on virt board via GPIO * clean up AArch32 singlestep code * raise exception on misaligned LDREX operands * soc-dma: use hwaddr instead of target_ulong in printf * explicitly mark some ARM device loads as little-endian * i.MX: add support for lower and upper interrupt in GPIO # gpg: Signature made Thu 17 Dec 2015 13:38:09 GMT using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" # gpg: aka "Peter Maydell <pmaydell@gmail.com>" # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" * remotes/pmaydell/tags/pull-target-arm-20151217-1: (25 commits) i.MX: Add an i.MX25 specific CCM class/instance i.MX: Split the CCM class into an abstract base class and a concrete class i.MX: rename i.MX CCM get_clock() function and CLK ID enum names i.MX: Fix i.MX31 default/reset configuration tests/guest-debug: introduce basic gdbstub tests target-arm: kvm - re-inject guest debug exceptions target-arm: kvm - add support for HW assisted debug target-arm: kvm - support for single step target-arm: kvm - implement software breakpoints target-arm: kvm64 - introduce kvm_arm_init_debug() ARM: Virt: Add gpio-keys node for Poweroff using DT ARM: Virt: Add QEMU powerdown notifier and hook it to GPIO Pin 3 ARM: ACPI: Add _E03 for Power Button ACPI: Add aml_gpio_int() wrapper for GPIO Interrupt Connection ACPI: Add GPIO Connection Descriptor ARM: ACPI: Add power button device in ACPI DSDT table ARM: ACPI: Add GPIO controller in ACPI DSDT table ARM: Virt: Add a GPIO controller acpi: extend aml_interrupt() to support multiple irqs acpi: support serialized method ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
+116
-11
@@ -564,6 +564,94 @@ Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4)
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 5.0: 6.4.3.8.1 GPIO Connection Descriptor
|
||||
* Type 1, Large Item Name 0xC
|
||||
*/
|
||||
|
||||
static Aml *aml_gpio_connection(AmlGpioConnectionType type,
|
||||
AmlConsumerAndProducer con_and_pro,
|
||||
uint8_t flags, AmlPinConfig pin_config,
|
||||
uint16_t output_drive,
|
||||
uint16_t debounce_timeout,
|
||||
const uint32_t pin_list[], uint32_t pin_count,
|
||||
const char *resource_source_name,
|
||||
const uint8_t *vendor_data,
|
||||
uint16_t vendor_data_len)
|
||||
{
|
||||
Aml *var = aml_alloc();
|
||||
const uint16_t min_desc_len = 0x16;
|
||||
uint16_t resource_source_name_len, length;
|
||||
uint16_t pin_table_offset, resource_source_name_offset, vendor_data_offset;
|
||||
uint32_t i;
|
||||
|
||||
assert(resource_source_name);
|
||||
resource_source_name_len = strlen(resource_source_name) + 1;
|
||||
length = min_desc_len + resource_source_name_len + vendor_data_len;
|
||||
pin_table_offset = min_desc_len + 1;
|
||||
resource_source_name_offset = pin_table_offset + pin_count * 2;
|
||||
vendor_data_offset = resource_source_name_offset + resource_source_name_len;
|
||||
|
||||
build_append_byte(var->buf, 0x8C); /* GPIO Connection Descriptor */
|
||||
build_append_int_noprefix(var->buf, length, 2); /* Length */
|
||||
build_append_byte(var->buf, 1); /* Revision ID */
|
||||
build_append_byte(var->buf, type); /* GPIO Connection Type */
|
||||
/* General Flags (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, con_and_pro, 2);
|
||||
/* Interrupt and IO Flags (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, flags, 2);
|
||||
/* Pin Configuration 0 = Default 1 = Pull-up 2 = Pull-down 3 = No Pull */
|
||||
build_append_byte(var->buf, pin_config);
|
||||
/* Output Drive Strength (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, output_drive, 2);
|
||||
/* Debounce Timeout (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, debounce_timeout, 2);
|
||||
/* Pin Table Offset (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, pin_table_offset, 2);
|
||||
build_append_byte(var->buf, 0); /* Resource Source Index */
|
||||
/* Resource Source Name Offset (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, resource_source_name_offset, 2);
|
||||
/* Vendor Data Offset (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, vendor_data_offset, 2);
|
||||
/* Vendor Data Length (2 bytes) */
|
||||
build_append_int_noprefix(var->buf, vendor_data_len, 2);
|
||||
/* Pin Number (2n bytes)*/
|
||||
for (i = 0; i < pin_count; i++) {
|
||||
build_append_int_noprefix(var->buf, pin_list[i], 2);
|
||||
}
|
||||
|
||||
/* Resource Source Name */
|
||||
build_append_namestring(var->buf, "%s", resource_source_name);
|
||||
build_append_byte(var->buf, '\0');
|
||||
|
||||
/* Vendor-defined Data */
|
||||
if (vendor_data != NULL) {
|
||||
g_array_append_vals(var->buf, vendor_data, vendor_data_len);
|
||||
}
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 5.0: 19.5.53
|
||||
* GpioInt(GPIO Interrupt Connection Resource Descriptor Macro)
|
||||
*/
|
||||
Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
|
||||
AmlLevelAndEdge edge_level,
|
||||
AmlActiveHighAndLow active_level, AmlShared shared,
|
||||
AmlPinConfig pin_config, uint16_t debounce_timeout,
|
||||
const uint32_t pin_list[], uint32_t pin_count,
|
||||
const char *resource_source_name,
|
||||
const uint8_t *vendor_data, uint16_t vendor_data_len)
|
||||
{
|
||||
uint8_t flags = edge_level | (active_level << 1) | (shared << 3);
|
||||
|
||||
return aml_gpio_connection(AML_INTERRUPT_CONNECTION, con_and_pro, flags,
|
||||
pin_config, 0, debounce_timeout, pin_list,
|
||||
pin_count, resource_source_name, vendor_data,
|
||||
vendor_data_len);
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI 1.0b: 6.4.3.4 32-Bit Fixed Location Memory Range Descriptor
|
||||
* (Type 1, Large Item Name 0x6)
|
||||
@@ -598,23 +686,27 @@ Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
|
||||
Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
|
||||
AmlLevelAndEdge level_and_edge,
|
||||
AmlActiveHighAndLow high_and_low, AmlShared shared,
|
||||
uint32_t irq)
|
||||
uint32_t *irq_list, uint8_t irq_count)
|
||||
{
|
||||
int i;
|
||||
Aml *var = aml_alloc();
|
||||
uint8_t irq_flags = con_and_pro | (level_and_edge << 1)
|
||||
| (high_and_low << 2) | (shared << 3);
|
||||
const int header_bytes_in_len = 2;
|
||||
uint16_t len = header_bytes_in_len + irq_count * sizeof(uint32_t);
|
||||
|
||||
assert(irq_count > 0);
|
||||
|
||||
build_append_byte(var->buf, 0x89); /* Extended irq descriptor */
|
||||
build_append_byte(var->buf, 6); /* Length, bits[7:0] minimum value = 6 */
|
||||
build_append_byte(var->buf, 0); /* Length, bits[15:8] minimum value = 0 */
|
||||
build_append_byte(var->buf, len & 0xFF); /* Length, bits[7:0] */
|
||||
build_append_byte(var->buf, len >> 8); /* Length, bits[15:8] */
|
||||
build_append_byte(var->buf, irq_flags); /* Interrupt Vector Information. */
|
||||
build_append_byte(var->buf, 0x01); /* Interrupt table length = 1 */
|
||||
build_append_byte(var->buf, irq_count); /* Interrupt table length */
|
||||
|
||||
/* Interrupt Number */
|
||||
build_append_byte(var->buf, extract32(irq, 0, 8)); /* bits[7:0] */
|
||||
build_append_byte(var->buf, extract32(irq, 8, 8)); /* bits[15:8] */
|
||||
build_append_byte(var->buf, extract32(irq, 16, 8)); /* bits[23:16] */
|
||||
build_append_byte(var->buf, extract32(irq, 24, 8)); /* bits[31:24] */
|
||||
/* Interrupt Number List */
|
||||
for (i = 0; i < irq_count; i++) {
|
||||
build_append_int_noprefix(var->buf, irq_list[i], 4);
|
||||
}
|
||||
return var;
|
||||
}
|
||||
|
||||
@@ -696,11 +788,24 @@ Aml *aml_while(Aml *predicate)
|
||||
}
|
||||
|
||||
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: DefMethod */
|
||||
Aml *aml_method(const char *name, int arg_count)
|
||||
Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag)
|
||||
{
|
||||
Aml *var = aml_bundle(0x14 /* MethodOp */, AML_PACKAGE);
|
||||
int methodflags;
|
||||
|
||||
/*
|
||||
* MethodFlags:
|
||||
* bit 0-2: ArgCount (0-7)
|
||||
* bit 3: SerializeFlag
|
||||
* 0: NotSerialized
|
||||
* 1: Serialized
|
||||
* bit 4-7: reserved (must be 0)
|
||||
*/
|
||||
assert(arg_count < 8);
|
||||
methodflags = arg_count | (sflag << 3);
|
||||
|
||||
build_append_namestring(var->buf, "%s", name);
|
||||
build_append_byte(var->buf, arg_count); /* MethodFlags: ArgCount */
|
||||
build_append_byte(var->buf, methodflags); /* MethodFlags: ArgCount */
|
||||
return var;
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -38,7 +38,7 @@ static void fsl_imx25_init(Object *obj)
|
||||
object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
|
||||
qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
|
||||
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX25_CCM);
|
||||
qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
|
||||
|
||||
for (i = 0; i < FSL_IMX25_NUM_UARTS; i++) {
|
||||
@@ -150,7 +150,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
|
||||
{ FSL_IMX25_GPT4_ADDR, FSL_IMX25_GPT4_IRQ }
|
||||
};
|
||||
|
||||
s->gpt[i].ccm = DEVICE(&s->ccm);
|
||||
s->gpt[i].ccm = IMX_CCM(&s->ccm);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->gpt[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
@@ -173,7 +173,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
|
||||
{ FSL_IMX25_EPIT2_ADDR, FSL_IMX25_EPIT2_IRQ }
|
||||
};
|
||||
|
||||
s->epit[i].ccm = DEVICE(&s->ccm);
|
||||
s->epit[i].ccm = IMX_CCM(&s->ccm);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
|
||||
+3
-3
@@ -35,7 +35,7 @@ static void fsl_imx31_init(Object *obj)
|
||||
object_initialize(&s->avic, sizeof(s->avic), TYPE_IMX_AVIC);
|
||||
qdev_set_parent_bus(DEVICE(&s->avic), sysbus_get_default());
|
||||
|
||||
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX_CCM);
|
||||
object_initialize(&s->ccm, sizeof(s->ccm), TYPE_IMX31_CCM);
|
||||
qdev_set_parent_bus(DEVICE(&s->ccm), sysbus_get_default());
|
||||
|
||||
for (i = 0; i < FSL_IMX31_NUM_UARTS; i++) {
|
||||
@@ -128,7 +128,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
|
||||
serial_table[i].irq));
|
||||
}
|
||||
|
||||
s->gpt.ccm = DEVICE(&s->ccm);
|
||||
s->gpt.ccm = IMX_CCM(&s->ccm);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->gpt), true, "realized", &err);
|
||||
if (err) {
|
||||
@@ -150,7 +150,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
|
||||
{ FSL_IMX31_EPIT2_ADDR, FSL_IMX31_EPIT2_IRQ },
|
||||
};
|
||||
|
||||
s->epit[i].ccm = DEVICE(&s->ccm);
|
||||
s->epit[i].ccm = IMX_CCM(&s->ccm);
|
||||
|
||||
object_property_set_bool(OBJECT(&s->epit[i]), true, "realized", &err);
|
||||
if (err) {
|
||||
|
||||
+61
-16
@@ -43,6 +43,7 @@
|
||||
#include "hw/pci/pci.h"
|
||||
|
||||
#define ARM_SPI_BASE 32
|
||||
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
|
||||
|
||||
typedef struct VirtAcpiCpuInfo {
|
||||
DECLARE_BITMAP(found_cpus, VIRT_ACPI_CPU_ID_LIMIT);
|
||||
@@ -71,7 +72,7 @@ static void acpi_dsdt_add_cpus(Aml *scope, int smp_cpus)
|
||||
}
|
||||
|
||||
static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
|
||||
int uart_irq)
|
||||
uint32_t uart_irq)
|
||||
{
|
||||
Aml *dev = aml_device("COM0");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0011")));
|
||||
@@ -82,7 +83,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
|
||||
uart_memmap->size, AML_READ_WRITE));
|
||||
aml_append(crs,
|
||||
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, uart_irq));
|
||||
AML_EXCLUSIVE, &uart_irq, 1));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
|
||||
/* The _ADR entry is used to link this device to the UART described
|
||||
@@ -94,7 +95,7 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
|
||||
}
|
||||
|
||||
static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
|
||||
int rtc_irq)
|
||||
uint32_t rtc_irq)
|
||||
{
|
||||
Aml *dev = aml_device("RTC0");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0013")));
|
||||
@@ -105,7 +106,7 @@ static void acpi_dsdt_add_rtc(Aml *scope, const MemMapEntry *rtc_memmap,
|
||||
rtc_memmap->size, AML_READ_WRITE));
|
||||
aml_append(crs,
|
||||
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, rtc_irq));
|
||||
AML_EXCLUSIVE, &rtc_irq, 1));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
@@ -136,14 +137,14 @@ static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap)
|
||||
|
||||
static void acpi_dsdt_add_virtio(Aml *scope,
|
||||
const MemMapEntry *virtio_mmio_memmap,
|
||||
int mmio_irq, int num)
|
||||
uint32_t mmio_irq, int num)
|
||||
{
|
||||
hwaddr base = virtio_mmio_memmap->base;
|
||||
hwaddr size = virtio_mmio_memmap->size;
|
||||
int irq = mmio_irq;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
uint32_t irq = mmio_irq + i;
|
||||
Aml *dev = aml_device("VR%02u", i);
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005")));
|
||||
aml_append(dev, aml_name_decl("_UID", aml_int(i)));
|
||||
@@ -152,15 +153,15 @@ static void acpi_dsdt_add_virtio(Aml *scope,
|
||||
aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE));
|
||||
aml_append(crs,
|
||||
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, irq + i));
|
||||
AML_EXCLUSIVE, &irq, 1));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
aml_append(scope, dev);
|
||||
base += size;
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
||||
bool use_highmem)
|
||||
static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
|
||||
uint32_t irq, bool use_highmem)
|
||||
{
|
||||
Aml *method, *crs, *ifctx, *UUID, *ifctx1, *elsectx, *buf;
|
||||
int i, bus_no;
|
||||
@@ -199,29 +200,30 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
||||
|
||||
/* Create GSI link device */
|
||||
for (i = 0; i < PCI_NUM_PINS; i++) {
|
||||
uint32_t irqs = irq + i;
|
||||
Aml *dev_gsi = aml_device("GSI%d", i);
|
||||
aml_append(dev_gsi, aml_name_decl("_HID", aml_string("PNP0C0F")));
|
||||
aml_append(dev_gsi, aml_name_decl("_UID", aml_int(0)));
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs,
|
||||
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, irq + i));
|
||||
AML_EXCLUSIVE, &irqs, 1));
|
||||
aml_append(dev_gsi, aml_name_decl("_PRS", crs));
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs,
|
||||
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, irq + i));
|
||||
AML_EXCLUSIVE, &irqs, 1));
|
||||
aml_append(dev_gsi, aml_name_decl("_CRS", crs));
|
||||
method = aml_method("_SRS", 1);
|
||||
method = aml_method("_SRS", 1, AML_NOTSERIALIZED);
|
||||
aml_append(dev_gsi, method);
|
||||
aml_append(dev, dev_gsi);
|
||||
}
|
||||
|
||||
method = aml_method("_CBA", 0);
|
||||
method = aml_method("_CBA", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_int(base_ecam)));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_CRS", 0);
|
||||
method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
|
||||
Aml *rbuf = aml_resource_template();
|
||||
aml_append(rbuf,
|
||||
aml_word_bus_number(AML_MIN_FIXED, AML_MAX_FIXED, AML_POS_DECODE,
|
||||
@@ -254,7 +256,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
||||
/* Declare an _OSC (OS Control Handoff) method */
|
||||
aml_append(dev, aml_name_decl("SUPP", aml_int(0)));
|
||||
aml_append(dev, aml_name_decl("CTRL", aml_int(0)));
|
||||
method = aml_method("_OSC", 4);
|
||||
method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
|
||||
aml_append(method,
|
||||
aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
|
||||
|
||||
@@ -296,7 +298,7 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
||||
aml_append(method, elsectx);
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_DSM", 4);
|
||||
method = aml_method("_DSM", 4, AML_NOTSERIALIZED);
|
||||
|
||||
/* PCI Firmware Specification 3.0
|
||||
* 4.6.1. _DSM for PCI Express Slot Information
|
||||
@@ -323,6 +325,46 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, int irq,
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
static void acpi_dsdt_add_gpio(Aml *scope, const MemMapEntry *gpio_memmap,
|
||||
uint32_t gpio_irq)
|
||||
{
|
||||
Aml *dev = aml_device("GPO0");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("ARMH0061")));
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
|
||||
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
|
||||
|
||||
Aml *crs = aml_resource_template();
|
||||
aml_append(crs, aml_memory32_fixed(gpio_memmap->base, gpio_memmap->size,
|
||||
AML_READ_WRITE));
|
||||
aml_append(crs, aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, &gpio_irq, 1));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
|
||||
Aml *aei = aml_resource_template();
|
||||
/* Pin 3 for power button */
|
||||
const uint32_t pin_list[1] = {3};
|
||||
aml_append(aei, aml_gpio_int(AML_CONSUMER, AML_EDGE, AML_ACTIVE_HIGH,
|
||||
AML_EXCLUSIVE, AML_PULL_UP, 0, pin_list, 1,
|
||||
"GPO0", NULL, 0));
|
||||
aml_append(dev, aml_name_decl("_AEI", aei));
|
||||
|
||||
/* _E03 is handle for power button */
|
||||
Aml *method = aml_method("_E03", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_notify(aml_name(ACPI_POWER_BUTTON_DEVICE),
|
||||
aml_int(0x80)));
|
||||
aml_append(dev, method);
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
static void acpi_dsdt_add_power_button(Aml *scope)
|
||||
{
|
||||
Aml *dev = aml_device(ACPI_POWER_BUTTON_DEVICE);
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0C0C")));
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
|
||||
aml_append(dev, aml_name_decl("_UID", aml_int(0)));
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
/* RSDP */
|
||||
static GArray *
|
||||
build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
|
||||
@@ -539,6 +581,9 @@ build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
||||
(irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS);
|
||||
acpi_dsdt_add_pci(scope, memmap, (irqmap[VIRT_PCIE] + ARM_SPI_BASE),
|
||||
guest_info->use_highmem);
|
||||
acpi_dsdt_add_gpio(scope, &memmap[VIRT_GPIO],
|
||||
(irqmap[VIRT_GPIO] + ARM_SPI_BASE));
|
||||
acpi_dsdt_add_power_button(scope);
|
||||
|
||||
aml_append(dsdt, scope);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "kvm_arm.h"
|
||||
#include "hw/smbios/smbios.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "standard-headers/linux/input.h"
|
||||
|
||||
/* Number of external interrupt lines to configure the GIC with */
|
||||
#define NUM_IRQS 256
|
||||
@@ -120,6 +121,7 @@ static const MemMapEntry a15memmap[] = {
|
||||
[VIRT_UART] = { 0x09000000, 0x00001000 },
|
||||
[VIRT_RTC] = { 0x09010000, 0x00001000 },
|
||||
[VIRT_FW_CFG] = { 0x09020000, 0x00000018 },
|
||||
[VIRT_GPIO] = { 0x09030000, 0x00001000 },
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
|
||||
@@ -135,6 +137,7 @@ static const int a15irqmap[] = {
|
||||
[VIRT_UART] = 1,
|
||||
[VIRT_RTC] = 2,
|
||||
[VIRT_PCIE] = 3, /* ... to 6 */
|
||||
[VIRT_GPIO] = 7,
|
||||
[VIRT_MMIO] = 16, /* ...to 16 + NUM_VIRTIO_TRANSPORTS - 1 */
|
||||
[VIRT_GIC_V2M] = 48, /* ...to 48 + NUM_GICV2M_SPIS - 1 */
|
||||
[VIRT_PLATFORM_BUS] = 112, /* ...to 112 + PLATFORM_BUS_NUM_IRQS -1 */
|
||||
@@ -538,6 +541,61 @@ static void create_rtc(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static DeviceState *pl061_dev;
|
||||
static void virt_powerdown_req(Notifier *n, void *opaque)
|
||||
{
|
||||
/* use gpio Pin 3 for power button event */
|
||||
qemu_set_irq(qdev_get_gpio_in(pl061_dev, 3), 1);
|
||||
}
|
||||
|
||||
static Notifier virt_system_powerdown_notifier = {
|
||||
.notify = virt_powerdown_req
|
||||
};
|
||||
|
||||
static void create_gpio(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
{
|
||||
char *nodename;
|
||||
hwaddr base = vbi->memmap[VIRT_GPIO].base;
|
||||
hwaddr size = vbi->memmap[VIRT_GPIO].size;
|
||||
int irq = vbi->irqmap[VIRT_GPIO];
|
||||
const char compat[] = "arm,pl061\0arm,primecell";
|
||||
|
||||
pl061_dev = sysbus_create_simple("pl061", base, pic[irq]);
|
||||
|
||||
uint32_t phandle = qemu_fdt_alloc_phandle(vbi->fdt);
|
||||
nodename = g_strdup_printf("/pl061@%" PRIx64, base);
|
||||
qemu_fdt_add_subnode(vbi->fdt, nodename);
|
||||
qemu_fdt_setprop_sized_cells(vbi->fdt, nodename, "reg",
|
||||
2, base, 2, size);
|
||||
qemu_fdt_setprop(vbi->fdt, nodename, "compatible", compat, sizeof(compat));
|
||||
qemu_fdt_setprop_cell(vbi->fdt, nodename, "#gpio-cells", 2);
|
||||
qemu_fdt_setprop(vbi->fdt, nodename, "gpio-controller", NULL, 0);
|
||||
qemu_fdt_setprop_cells(vbi->fdt, nodename, "interrupts",
|
||||
GIC_FDT_IRQ_TYPE_SPI, irq,
|
||||
GIC_FDT_IRQ_FLAGS_LEVEL_HI);
|
||||
qemu_fdt_setprop_cell(vbi->fdt, nodename, "clocks", vbi->clock_phandle);
|
||||
qemu_fdt_setprop_string(vbi->fdt, nodename, "clock-names", "apb_pclk");
|
||||
qemu_fdt_setprop_cell(vbi->fdt, nodename, "phandle", phandle);
|
||||
|
||||
qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys");
|
||||
qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys", "compatible", "gpio-keys");
|
||||
qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#size-cells", 0);
|
||||
qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys", "#address-cells", 1);
|
||||
|
||||
qemu_fdt_add_subnode(vbi->fdt, "/gpio-keys/poweroff");
|
||||
qemu_fdt_setprop_string(vbi->fdt, "/gpio-keys/poweroff",
|
||||
"label", "GPIO Key Poweroff");
|
||||
qemu_fdt_setprop_cell(vbi->fdt, "/gpio-keys/poweroff", "linux,code",
|
||||
KEY_POWER);
|
||||
qemu_fdt_setprop_cells(vbi->fdt, "/gpio-keys/poweroff",
|
||||
"gpios", phandle, 3, 0);
|
||||
|
||||
/* connect powerdown request */
|
||||
qemu_register_powerdown_notifier(&virt_system_powerdown_notifier);
|
||||
|
||||
g_free(nodename);
|
||||
}
|
||||
|
||||
static void create_virtio_devices(const VirtBoardInfo *vbi, qemu_irq *pic)
|
||||
{
|
||||
int i;
|
||||
@@ -1041,6 +1099,8 @@ static void machvirt_init(MachineState *machine)
|
||||
|
||||
create_pcie(vbi, pic, vms->highmem);
|
||||
|
||||
create_gpio(vbi, pic);
|
||||
|
||||
/* Create mmio transports, so the user can create virtio backends
|
||||
* (which will be automatically plugged in to the transports). If
|
||||
* no backend is created the transport will just sit harmlessly idle.
|
||||
|
||||
@@ -136,7 +136,7 @@ static void glue(draw_line12_, DEPTH)(void *opaque,
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_p((void *) s);
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 4) & 0xf0;
|
||||
g = v & 0xf0;
|
||||
b = (v << 4) & 0xf0;
|
||||
@@ -159,7 +159,7 @@ static void glue(draw_line16_, DEPTH)(void *opaque,
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
v = lduw_p((void *) s);
|
||||
v = lduw_le_p((void *) s);
|
||||
r = (v >> 8) & 0xf8;
|
||||
g = (v >> 3) & 0xfc;
|
||||
b = (v << 3) & 0xf8;
|
||||
|
||||
@@ -309,10 +309,10 @@ static void pxa2xx_descriptor_load(PXA2xxLCDState *s)
|
||||
}
|
||||
|
||||
cpu_physical_memory_read(descptr, &desc, sizeof(desc));
|
||||
s->dma_ch[i].descriptor = tswap32(desc.fdaddr);
|
||||
s->dma_ch[i].source = tswap32(desc.fsaddr);
|
||||
s->dma_ch[i].id = tswap32(desc.fidr);
|
||||
s->dma_ch[i].command = tswap32(desc.ldcmd);
|
||||
s->dma_ch[i].descriptor = le32_to_cpu(desc.fdaddr);
|
||||
s->dma_ch[i].source = le32_to_cpu(desc.fsaddr);
|
||||
s->dma_ch[i].id = le32_to_cpu(desc.fidr);
|
||||
s->dma_ch[i].command = le32_to_cpu(desc.ldcmd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-22
@@ -269,11 +269,10 @@ void soc_dma_port_add_fifo(struct soc_dma_s *soc, hwaddr virt_base,
|
||||
if (entry->type == soc_dma_port_mem) {
|
||||
if (entry->addr <= virt_base &&
|
||||
entry->addr + entry->u.mem.size > virt_base) {
|
||||
fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
||||
" collides with RAM region at " TARGET_FMT_lx
|
||||
"-" TARGET_FMT_lx "\n", __FUNCTION__,
|
||||
(target_ulong) virt_base,
|
||||
(target_ulong) entry->addr, (target_ulong)
|
||||
fprintf(stderr, "%s: FIFO at %"PRIx64
|
||||
" collides with RAM region at %"PRIx64
|
||||
"-%"PRIx64 "\n", __func__,
|
||||
virt_base, entry->addr,
|
||||
(entry->addr + entry->u.mem.size));
|
||||
exit(-1);
|
||||
}
|
||||
@@ -284,10 +283,9 @@ void soc_dma_port_add_fifo(struct soc_dma_s *soc, hwaddr virt_base,
|
||||
while (entry < dma->memmap + dma->memmap_size &&
|
||||
entry->addr <= virt_base) {
|
||||
if (entry->addr == virt_base && entry->u.fifo.out == out) {
|
||||
fprintf(stderr, "%s: FIFO at " TARGET_FMT_lx
|
||||
" collides FIFO at " TARGET_FMT_lx "\n",
|
||||
__FUNCTION__, (target_ulong) virt_base,
|
||||
(target_ulong) entry->addr);
|
||||
fprintf(stderr, "%s: FIFO at %"PRIx64
|
||||
" collides FIFO at %"PRIx64 "\n",
|
||||
__func__, virt_base, entry->addr);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -322,13 +320,11 @@ void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base,
|
||||
if ((entry->addr >= virt_base && entry->addr < virt_base + size) ||
|
||||
(entry->addr <= virt_base &&
|
||||
entry->addr + entry->u.mem.size > virt_base)) {
|
||||
fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx
|
||||
" collides with RAM region at " TARGET_FMT_lx
|
||||
"-" TARGET_FMT_lx "\n", __FUNCTION__,
|
||||
(target_ulong) virt_base,
|
||||
(target_ulong) (virt_base + size),
|
||||
(target_ulong) entry->addr, (target_ulong)
|
||||
(entry->addr + entry->u.mem.size));
|
||||
fprintf(stderr, "%s: RAM at %"PRIx64 "-%"PRIx64
|
||||
" collides with RAM region at %"PRIx64
|
||||
"-%"PRIx64 "\n", __func__,
|
||||
virt_base, virt_base + size,
|
||||
entry->addr, entry->addr + entry->u.mem.size);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
@@ -337,12 +333,11 @@ void soc_dma_port_add_mem(struct soc_dma_s *soc, uint8_t *phys_base,
|
||||
} else {
|
||||
if (entry->addr >= virt_base &&
|
||||
entry->addr < virt_base + size) {
|
||||
fprintf(stderr, "%s: RAM at " TARGET_FMT_lx "-" TARGET_FMT_lx
|
||||
" collides with FIFO at " TARGET_FMT_lx
|
||||
"\n", __FUNCTION__,
|
||||
(target_ulong) virt_base,
|
||||
(target_ulong) (virt_base + size),
|
||||
(target_ulong) entry->addr);
|
||||
fprintf(stderr, "%s: RAM at %"PRIx64 "-%"PRIx64
|
||||
" collides with FIFO at %"PRIx64
|
||||
"\n", __func__,
|
||||
virt_base, virt_base + size,
|
||||
entry->addr);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
+10
-2
@@ -62,7 +62,12 @@ static const char *imx_gpio_reg_name(uint32_t reg)
|
||||
|
||||
static void imx_gpio_update_int(IMXGPIOState *s)
|
||||
{
|
||||
qemu_set_irq(s->irq, (s->isr & s->imr) ? 1 : 0);
|
||||
if (s->has_upper_pin_irq) {
|
||||
qemu_set_irq(s->irq[0], (s->isr & s->imr & 0x0000FFFF) ? 1 : 0);
|
||||
qemu_set_irq(s->irq[1], (s->isr & s->imr & 0xFFFF0000) ? 1 : 0);
|
||||
} else {
|
||||
qemu_set_irq(s->irq[0], (s->isr & s->imr) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
|
||||
@@ -282,6 +287,8 @@ static const VMStateDescription vmstate_imx_gpio = {
|
||||
|
||||
static Property imx_gpio_properties[] = {
|
||||
DEFINE_PROP_BOOL("has-edge-sel", IMXGPIOState, has_edge_sel, true),
|
||||
DEFINE_PROP_BOOL("has-upper-pin-irq", IMXGPIOState, has_upper_pin_irq,
|
||||
false),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
@@ -311,7 +318,8 @@ static void imx_gpio_realize(DeviceState *dev, Error **errp)
|
||||
qdev_init_gpio_in(DEVICE(s), imx_gpio_set, IMX_GPIO_PIN_COUNT);
|
||||
qdev_init_gpio_out(DEVICE(s), s->output, IMX_GPIO_PIN_COUNT);
|
||||
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]);
|
||||
sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[1]);
|
||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
|
||||
}
|
||||
|
||||
|
||||
+21
-20
@@ -487,7 +487,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||
int64_t bsel_val = qint_get_int(qobject_to_qint(bsel));
|
||||
|
||||
aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
|
||||
notify_method = aml_method("DVNT", 2);
|
||||
notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(bus->devices); i += PCI_FUNC_MAX) {
|
||||
@@ -503,7 +503,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||
dev = aml_device("S%.02X", PCI_DEVFN(slot, 0));
|
||||
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
|
||||
method = aml_method("_EJ0", 1);
|
||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||
aml_append(method,
|
||||
aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
|
||||
);
|
||||
@@ -546,22 +546,22 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||
s3d = 0;
|
||||
}
|
||||
|
||||
method = aml_method("_S1D", 0);
|
||||
method = aml_method("_S1D", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_int(0)));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_S2D", 0);
|
||||
method = aml_method("_S2D", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_int(0)));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_S3D", 0);
|
||||
method = aml_method("_S3D", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_int(s3d)));
|
||||
aml_append(dev, method);
|
||||
} else if (hotplug_enabled_dev) {
|
||||
/* add _SUN/_EJ0 to make slot hotpluggable */
|
||||
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
|
||||
|
||||
method = aml_method("_EJ0", 1);
|
||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||
aml_append(method,
|
||||
aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
|
||||
);
|
||||
@@ -590,7 +590,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||
/* Append PCNT method to notify about events on local and child buses.
|
||||
* Add unconditionally for root since DSDT expects it.
|
||||
*/
|
||||
method = aml_method("PCNT", 0);
|
||||
method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
|
||||
|
||||
/* If bus supports hotplug select it and notify about local events */
|
||||
if (bsel) {
|
||||
@@ -651,7 +651,7 @@ static Aml *build_prt(void)
|
||||
{
|
||||
Aml *method, *while_ctx, *pin, *res;
|
||||
|
||||
method = aml_method("_PRT", 0);
|
||||
method = aml_method("_PRT", 0, AML_NOTSERIALIZED);
|
||||
res = aml_local(0);
|
||||
pin = aml_local(1);
|
||||
aml_append(method, aml_store(aml_package(128), res));
|
||||
@@ -1112,12 +1112,12 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
/* device present, functioning, decoding, shown in UI */
|
||||
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
|
||||
|
||||
method = aml_method("RDPT", 0);
|
||||
method = aml_method("RDPT", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_store(aml_name("PEPT"), aml_local(0)));
|
||||
aml_append(method, aml_return(aml_local(0)));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("WRPT", 1);
|
||||
method = aml_method("WRPT", 1, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_store(aml_arg(0), aml_name("PEPT")));
|
||||
aml_append(dev, method);
|
||||
|
||||
@@ -1153,15 +1153,15 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
for (i = 0; i < acpi_cpus; i++) {
|
||||
dev = aml_processor(i, 0, 0, "CP%.02X", i);
|
||||
|
||||
method = aml_method("_MAT", 0);
|
||||
method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_call1("CPMA", aml_int(i))));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_STA", 0);
|
||||
method = aml_method("_STA", 0, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_return(aml_call1("CPST", aml_int(i))));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_EJ0", 1);
|
||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||
aml_append(method,
|
||||
aml_return(aml_call2("CPEJ", aml_int(i), aml_arg(0)))
|
||||
);
|
||||
@@ -1174,7 +1174,7 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
* Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
|
||||
*/
|
||||
/* Arg0 = Processor ID = APIC ID */
|
||||
method = aml_method("NTFY", 2);
|
||||
method = aml_method("NTFY", 2, AML_NOTSERIALIZED);
|
||||
for (i = 0; i < acpi_cpus; i++) {
|
||||
ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
|
||||
aml_append(ifctx,
|
||||
@@ -1269,29 +1269,29 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
aml_append(dev, aml_name_decl("_UID", aml_string("0x%02X", i)));
|
||||
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C80")));
|
||||
|
||||
method = aml_method("_CRS", 0);
|
||||
method = aml_method("_CRS", 0, AML_NOTSERIALIZED);
|
||||
s = BASEPATH stringify(MEMORY_SLOT_CRS_METHOD);
|
||||
aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_STA", 0);
|
||||
method = aml_method("_STA", 0, AML_NOTSERIALIZED);
|
||||
s = BASEPATH stringify(MEMORY_SLOT_STATUS_METHOD);
|
||||
aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_PXM", 0);
|
||||
method = aml_method("_PXM", 0, AML_NOTSERIALIZED);
|
||||
s = BASEPATH stringify(MEMORY_SLOT_PROXIMITY_METHOD);
|
||||
aml_append(method, aml_return(aml_call1(s, aml_name("_UID"))));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_OST", 3);
|
||||
method = aml_method("_OST", 3, AML_NOTSERIALIZED);
|
||||
s = BASEPATH stringify(MEMORY_SLOT_OST_METHOD);
|
||||
aml_append(method, aml_return(aml_call4(
|
||||
s, aml_name("_UID"), aml_arg(0), aml_arg(1), aml_arg(2)
|
||||
)));
|
||||
aml_append(dev, method);
|
||||
|
||||
method = aml_method("_EJ0", 1);
|
||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||
s = BASEPATH stringify(MEMORY_SLOT_EJECT_METHOD);
|
||||
aml_append(method, aml_return(aml_call2(
|
||||
s, aml_name("_UID"), aml_arg(0))));
|
||||
@@ -1303,7 +1303,8 @@ build_ssdt(GArray *table_data, GArray *linker,
|
||||
/* build Method(MEMORY_SLOT_NOTIFY_METHOD, 2) {
|
||||
* If (LEqual(Arg0, 0x00)) {Notify(MP00, Arg1)} ... }
|
||||
*/
|
||||
method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2);
|
||||
method = aml_method(stringify(MEMORY_SLOT_NOTIFY_METHOD), 2,
|
||||
AML_NOTSERIALIZED);
|
||||
for (i = 0; i < nr_mem; i++) {
|
||||
ifctx = aml_if(aml_equal(aml_arg(0), aml_int(i)));
|
||||
aml_append(ifctx,
|
||||
|
||||
@@ -26,6 +26,8 @@ obj-$(CONFIG_NSERIES) += cbus.o
|
||||
obj-$(CONFIG_ECCMEMCTL) += eccmemctl.o
|
||||
obj-$(CONFIG_EXYNOS4) += exynos4210_pmu.o
|
||||
obj-$(CONFIG_IMX) += imx_ccm.o
|
||||
obj-$(CONFIG_IMX) += imx31_ccm.o
|
||||
obj-$(CONFIG_IMX) += imx25_ccm.o
|
||||
obj-$(CONFIG_MILKYMIST) += milkymist-hpdmc.o
|
||||
obj-$(CONFIG_MILKYMIST) += milkymist-pfpu.o
|
||||
obj-$(CONFIG_MAINSTONE) += mst_fpga.o
|
||||
|
||||
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* IMX25 Clock Control Module
|
||||
*
|
||||
* Copyright (C) 2012 NICTA
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* To get the timer frequencies right, we need to emulate at least part of
|
||||
* the CCM.
|
||||
*/
|
||||
|
||||
#include "hw/misc/imx25_ccm.h"
|
||||
|
||||
#ifndef DEBUG_IMX25_CCM
|
||||
#define DEBUG_IMX25_CCM 0
|
||||
#endif
|
||||
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { \
|
||||
if (DEBUG_IMX25_CCM) { \
|
||||
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX25_CCM, \
|
||||
__func__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static char const *imx25_ccm_reg_name(uint32_t reg)
|
||||
{
|
||||
static char unknown[20];
|
||||
|
||||
switch (reg) {
|
||||
case IMX25_CCM_MPCTL_REG:
|
||||
return "mpctl";
|
||||
case IMX25_CCM_UPCTL_REG:
|
||||
return "upctl";
|
||||
case IMX25_CCM_CCTL_REG:
|
||||
return "cctl";
|
||||
case IMX25_CCM_CGCR0_REG:
|
||||
return "cgcr0";
|
||||
case IMX25_CCM_CGCR1_REG:
|
||||
return "cgcr1";
|
||||
case IMX25_CCM_CGCR2_REG:
|
||||
return "cgcr2";
|
||||
case IMX25_CCM_PCDR0_REG:
|
||||
return "pcdr0";
|
||||
case IMX25_CCM_PCDR1_REG:
|
||||
return "pcdr1";
|
||||
case IMX25_CCM_PCDR2_REG:
|
||||
return "pcdr2";
|
||||
case IMX25_CCM_PCDR3_REG:
|
||||
return "pcdr3";
|
||||
case IMX25_CCM_RCSR_REG:
|
||||
return "rcsr";
|
||||
case IMX25_CCM_CRDR_REG:
|
||||
return "crdr";
|
||||
case IMX25_CCM_DCVR0_REG:
|
||||
return "dcvr0";
|
||||
case IMX25_CCM_DCVR1_REG:
|
||||
return "dcvr1";
|
||||
case IMX25_CCM_DCVR2_REG:
|
||||
return "dcvr2";
|
||||
case IMX25_CCM_DCVR3_REG:
|
||||
return "dcvr3";
|
||||
case IMX25_CCM_LTR0_REG:
|
||||
return "ltr0";
|
||||
case IMX25_CCM_LTR1_REG:
|
||||
return "ltr1";
|
||||
case IMX25_CCM_LTR2_REG:
|
||||
return "ltr2";
|
||||
case IMX25_CCM_LTR3_REG:
|
||||
return "ltr3";
|
||||
case IMX25_CCM_LTBR0_REG:
|
||||
return "ltbr0";
|
||||
case IMX25_CCM_LTBR1_REG:
|
||||
return "ltbr1";
|
||||
case IMX25_CCM_PMCR0_REG:
|
||||
return "pmcr0";
|
||||
case IMX25_CCM_PMCR1_REG:
|
||||
return "pmcr1";
|
||||
case IMX25_CCM_PMCR2_REG:
|
||||
return "pmcr2";
|
||||
case IMX25_CCM_MCR_REG:
|
||||
return "mcr";
|
||||
case IMX25_CCM_LPIMR0_REG:
|
||||
return "lpimr0";
|
||||
case IMX25_CCM_LPIMR1_REG:
|
||||
return "lpimr1";
|
||||
default:
|
||||
sprintf(unknown, "[%d ?]", reg);
|
||||
return unknown;
|
||||
}
|
||||
}
|
||||
#define CKIH_FREQ 24000000 /* 24MHz crystal input */
|
||||
|
||||
static const VMStateDescription vmstate_imx25_ccm = {
|
||||
.name = TYPE_IMX25_CCM,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32_ARRAY(reg, IMX25CCMState, IMX25_CCM_MAX_REG),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX25CCMState *s = IMX25_CCM(dev);
|
||||
|
||||
if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], MPLL_BYPASS)) {
|
||||
freq = CKIH_FREQ;
|
||||
} else {
|
||||
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
|
||||
}
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx25_ccm_get_upll_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq = 0;
|
||||
IMX25CCMState *s = IMX25_CCM(dev);
|
||||
|
||||
if (!EXTRACT(s->reg[IMX25_CCM_CCTL_REG], UPLL_DIS)) {
|
||||
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_UPCTL_REG], CKIH_FREQ);
|
||||
}
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX25CCMState *s = IMX25_CCM(dev);
|
||||
|
||||
freq = imx25_ccm_get_mpll_clk(dev);
|
||||
|
||||
if (EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_SRC)) {
|
||||
freq = (freq * 3 / 4);
|
||||
}
|
||||
|
||||
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX25CCMState *s = IMX25_CCM(dev);
|
||||
|
||||
freq = imx25_ccm_get_mcu_clk(dev)
|
||||
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
|
||||
freq = imx25_ccm_get_ahb_clk(dev) / 2;
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
|
||||
{
|
||||
uint32_t freq = 0;
|
||||
DPRINTF("Clock = %d)\n", clock);
|
||||
|
||||
switch (clock) {
|
||||
case NOCLK:
|
||||
break;
|
||||
case CLK_MPLL:
|
||||
freq = imx25_ccm_get_mpll_clk(dev);
|
||||
break;
|
||||
case CLK_UPLL:
|
||||
freq = imx25_ccm_get_upll_clk(dev);
|
||||
break;
|
||||
case CLK_MCU:
|
||||
freq = imx25_ccm_get_mcu_clk(dev);
|
||||
break;
|
||||
case CLK_AHB:
|
||||
freq = imx25_ccm_get_ahb_clk(dev);
|
||||
break;
|
||||
case CLK_IPG:
|
||||
freq = imx25_ccm_get_ipg_clk(dev);
|
||||
break;
|
||||
case CLK_32k:
|
||||
freq = CKIL_FREQ;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
|
||||
TYPE_IMX25_CCM, __func__, clock);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF("Clock = %d) = %d\n", clock, freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static void imx25_ccm_reset(DeviceState *dev)
|
||||
{
|
||||
IMX25CCMState *s = IMX25_CCM(dev);
|
||||
|
||||
DPRINTF("\n");
|
||||
|
||||
memset(s->reg, 0, IMX25_CCM_MAX_REG * sizeof(uint32_t));
|
||||
s->reg[IMX25_CCM_MPCTL_REG] = 0x800b2c01;
|
||||
s->reg[IMX25_CCM_UPCTL_REG] = 0x84042800;
|
||||
/*
|
||||
* The value below gives:
|
||||
* CPU = 133 MHz, AHB = 66,5 MHz, IPG = 33 MHz.
|
||||
*/
|
||||
s->reg[IMX25_CCM_CCTL_REG] = 0xd0030000;
|
||||
s->reg[IMX25_CCM_CGCR0_REG] = 0x028A0100;
|
||||
s->reg[IMX25_CCM_CGCR1_REG] = 0x04008100;
|
||||
s->reg[IMX25_CCM_CGCR2_REG] = 0x00000438;
|
||||
s->reg[IMX25_CCM_PCDR0_REG] = 0x01010101;
|
||||
s->reg[IMX25_CCM_PCDR1_REG] = 0x01010101;
|
||||
s->reg[IMX25_CCM_PCDR2_REG] = 0x01010101;
|
||||
s->reg[IMX25_CCM_PCDR3_REG] = 0x01010101;
|
||||
s->reg[IMX25_CCM_PMCR0_REG] = 0x00A00000;
|
||||
s->reg[IMX25_CCM_PMCR1_REG] = 0x0000A030;
|
||||
s->reg[IMX25_CCM_PMCR2_REG] = 0x0000A030;
|
||||
s->reg[IMX25_CCM_MCR_REG] = 0x43000000;
|
||||
|
||||
/*
|
||||
* default boot will change the reset values to allow:
|
||||
* CPU = 399 MHz, AHB = 133 MHz, IPG = 66,5 MHz.
|
||||
* For some reason, this doesn't work. With the value below, linux
|
||||
* detects a 88 MHz IPG CLK instead of 66,5 MHz.
|
||||
s->reg[IMX25_CCM_CCTL_REG] = 0x20032000;
|
||||
*/
|
||||
}
|
||||
|
||||
static uint64_t imx25_ccm_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
uint32 value = 0;
|
||||
IMX25CCMState *s = (IMX25CCMState *)opaque;
|
||||
|
||||
if (offset < 0x70) {
|
||||
value = s->reg[offset >> 2];
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
|
||||
}
|
||||
|
||||
DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2),
|
||||
value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void imx25_ccm_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
IMX25CCMState *s = (IMX25CCMState *)opaque;
|
||||
|
||||
DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx25_ccm_reg_name(offset >> 2),
|
||||
(uint32_t)value);
|
||||
|
||||
if (offset < 0x70) {
|
||||
/*
|
||||
* We will do a better implementation later. In particular some bits
|
||||
* cannot be written to.
|
||||
*/
|
||||
s->reg[offset >> 2] = value;
|
||||
} else {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX25_CCM, __func__, offset);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct MemoryRegionOps imx25_ccm_ops = {
|
||||
.read = imx25_ccm_read,
|
||||
.write = imx25_ccm_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
/*
|
||||
* Our device would not work correctly if the guest was doing
|
||||
* unaligned access. This might not be a limitation on the real
|
||||
* device but in practice there is no reason for a guest to access
|
||||
* this device unaligned.
|
||||
*/
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
.unaligned = false,
|
||||
},
|
||||
};
|
||||
|
||||
static void imx25_ccm_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
||||
IMX25CCMState *s = IMX25_CCM(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &imx25_ccm_ops, s,
|
||||
TYPE_IMX25_CCM, 0x1000);
|
||||
sysbus_init_mmio(sd, &s->iomem);
|
||||
}
|
||||
|
||||
static void imx25_ccm_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
|
||||
|
||||
dc->reset = imx25_ccm_reset;
|
||||
dc->vmsd = &vmstate_imx25_ccm;
|
||||
dc->desc = "i.MX25 Clock Control Module";
|
||||
|
||||
ccm->get_clock_frequency = imx25_ccm_get_clock_frequency;
|
||||
}
|
||||
|
||||
static const TypeInfo imx25_ccm_info = {
|
||||
.name = TYPE_IMX25_CCM,
|
||||
.parent = TYPE_IMX_CCM,
|
||||
.instance_size = sizeof(IMX25CCMState),
|
||||
.instance_init = imx25_ccm_init,
|
||||
.class_init = imx25_ccm_class_init,
|
||||
};
|
||||
|
||||
static void imx25_ccm_register_types(void)
|
||||
{
|
||||
type_register_static(&imx25_ccm_info);
|
||||
}
|
||||
|
||||
type_init(imx25_ccm_register_types)
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* IMX31 Clock Control Module
|
||||
*
|
||||
* Copyright (C) 2012 NICTA
|
||||
* Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* To get the timer frequencies right, we need to emulate at least part of
|
||||
* the i.MX31 CCM.
|
||||
*/
|
||||
|
||||
#include "hw/misc/imx31_ccm.h"
|
||||
|
||||
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
|
||||
|
||||
#ifndef DEBUG_IMX31_CCM
|
||||
#define DEBUG_IMX31_CCM 0
|
||||
#endif
|
||||
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { \
|
||||
if (DEBUG_IMX31_CCM) { \
|
||||
fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX31_CCM, \
|
||||
__func__, ##args); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static char const *imx31_ccm_reg_name(uint32_t reg)
|
||||
{
|
||||
switch (reg) {
|
||||
case 0:
|
||||
return "CCMR";
|
||||
case 1:
|
||||
return "PDR0";
|
||||
case 2:
|
||||
return "PDR1";
|
||||
case 3:
|
||||
return "RCSR";
|
||||
case 4:
|
||||
return "MPCTL";
|
||||
case 5:
|
||||
return "UPCTL";
|
||||
case 6:
|
||||
return "SPCTL";
|
||||
case 7:
|
||||
return "COSR";
|
||||
case 8:
|
||||
return "CGR0";
|
||||
case 9:
|
||||
return "CGR1";
|
||||
case 10:
|
||||
return "CGR2";
|
||||
case 11:
|
||||
return "WIMR";
|
||||
case 12:
|
||||
return "LDC";
|
||||
case 13:
|
||||
return "DCVR0";
|
||||
case 14:
|
||||
return "DCVR1";
|
||||
case 15:
|
||||
return "DCVR2";
|
||||
case 16:
|
||||
return "DCVR3";
|
||||
case 17:
|
||||
return "LTR0";
|
||||
case 18:
|
||||
return "LTR1";
|
||||
case 19:
|
||||
return "LTR2";
|
||||
case 20:
|
||||
return "LTR3";
|
||||
case 21:
|
||||
return "LTBR0";
|
||||
case 22:
|
||||
return "LTBR1";
|
||||
case 23:
|
||||
return "PMCR0";
|
||||
case 24:
|
||||
return "PMCR1";
|
||||
case 25:
|
||||
return "PDR2";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_imx31_ccm = {
|
||||
.name = TYPE_IMX31_CCM,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(ccmr, IMX31CCMState),
|
||||
VMSTATE_UINT32(pdr0, IMX31CCMState),
|
||||
VMSTATE_UINT32(pdr1, IMX31CCMState),
|
||||
VMSTATE_UINT32(mpctl, IMX31CCMState),
|
||||
VMSTATE_UINT32(spctl, IMX31CCMState),
|
||||
VMSTATE_UINT32_ARRAY(cgr, IMX31CCMState, 3),
|
||||
VMSTATE_UINT32(pmcr0, IMX31CCMState),
|
||||
VMSTATE_UINT32(pmcr1, IMX31CCMState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
};
|
||||
|
||||
static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq = 0;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
if ((s->ccmr & CCMR_PRCS) == 2) {
|
||||
if (s->ccmr & CCMR_FPME) {
|
||||
freq = CKIL_FREQ;
|
||||
if (s->ccmr & CCMR_FPMF) {
|
||||
freq *= 1024;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
freq = CKIH_FREQ;
|
||||
}
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
freq = imx_ccm_calc_pll(s->mpctl, imx31_ccm_get_pll_ref_clk(dev));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
if ((s->ccmr & CCMR_MDS) || !(s->ccmr & CCMR_MPE)) {
|
||||
freq = imx31_ccm_get_pll_ref_clk(dev);
|
||||
} else {
|
||||
freq = imx31_ccm_get_mpll_clk(dev);
|
||||
}
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_mcu_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
freq = imx31_ccm_get_mcu_main_clk(dev) / (1 + EXTRACT(s->pdr0, MCU));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_hsp_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
freq = imx31_ccm_get_mcu_main_clk(dev) / (1 + EXTRACT(s->pdr0, HSP));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
freq = imx31_ccm_get_mcu_main_clk(dev) / (1 + EXTRACT(s->pdr0, MAX));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
|
||||
{
|
||||
uint32_t freq;
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
freq = imx31_ccm_get_hclk_clk(dev) / (1 + EXTRACT(s->pdr0, IPG));
|
||||
|
||||
DPRINTF("freq = %d\n", freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
|
||||
{
|
||||
uint32_t freq = 0;
|
||||
|
||||
switch (clock) {
|
||||
case NOCLK:
|
||||
break;
|
||||
case CLK_MCU:
|
||||
freq = imx31_ccm_get_mcu_clk(dev);
|
||||
break;
|
||||
case CLK_HSP:
|
||||
freq = imx31_ccm_get_hsp_clk(dev);
|
||||
break;
|
||||
case CLK_IPG:
|
||||
freq = imx31_ccm_get_ipg_clk(dev);
|
||||
break;
|
||||
case CLK_32k:
|
||||
freq = CKIL_FREQ;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: unsupported clock %d\n",
|
||||
TYPE_IMX31_CCM, __func__, clock);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF("Clock = %d) = %d\n", clock, freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
static void imx31_ccm_reset(DeviceState *dev)
|
||||
{
|
||||
IMX31CCMState *s = IMX31_CCM(dev);
|
||||
|
||||
DPRINTF("()\n");
|
||||
|
||||
s->ccmr = 0x074b0b7d;
|
||||
s->pdr0 = 0xff870b48;
|
||||
s->pdr1 = 0x49fcfe7f;
|
||||
s->mpctl = 0x04001800;
|
||||
s->cgr[0] = s->cgr[1] = s->cgr[2] = 0xffffffff;
|
||||
s->spctl = 0x04043001;
|
||||
s->pmcr0 = 0x80209828;
|
||||
s->pmcr1 = 0x00aa0000;
|
||||
}
|
||||
|
||||
static uint64_t imx31_ccm_read(void *opaque, hwaddr offset, unsigned size)
|
||||
{
|
||||
uint32 value = 0;
|
||||
IMX31CCMState *s = (IMX31CCMState *)opaque;
|
||||
|
||||
switch (offset >> 2) {
|
||||
case 0: /* CCMR */
|
||||
value = s->ccmr;
|
||||
break;
|
||||
case 1:
|
||||
value = s->pdr0;
|
||||
break;
|
||||
case 2:
|
||||
value = s->pdr1;
|
||||
break;
|
||||
case 4:
|
||||
value = s->mpctl;
|
||||
break;
|
||||
case 6:
|
||||
value = s->spctl;
|
||||
break;
|
||||
case 8:
|
||||
value = s->cgr[0];
|
||||
break;
|
||||
case 9:
|
||||
value = s->cgr[1];
|
||||
break;
|
||||
case 10:
|
||||
value = s->cgr[2];
|
||||
break;
|
||||
case 18: /* LTR1 */
|
||||
value = 0x00004040;
|
||||
break;
|
||||
case 23:
|
||||
value = s->pmcr0;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
|
||||
break;
|
||||
}
|
||||
|
||||
DPRINTF("reg[%s] => 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
|
||||
value);
|
||||
|
||||
return (uint64_t)value;
|
||||
}
|
||||
|
||||
static void imx31_ccm_write(void *opaque, hwaddr offset, uint64_t value,
|
||||
unsigned size)
|
||||
{
|
||||
IMX31CCMState *s = (IMX31CCMState *)opaque;
|
||||
|
||||
DPRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx31_ccm_reg_name(offset >> 2),
|
||||
(uint32_t)value);
|
||||
|
||||
switch (offset >> 2) {
|
||||
case 0:
|
||||
s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
|
||||
break;
|
||||
case 1:
|
||||
s->pdr0 = value & 0xff9f3fff;
|
||||
break;
|
||||
case 2:
|
||||
s->pdr1 = value;
|
||||
break;
|
||||
case 4:
|
||||
s->mpctl = value & 0xbfff3fff;
|
||||
break;
|
||||
case 6:
|
||||
s->spctl = value & 0xbfff3fff;
|
||||
break;
|
||||
case 8:
|
||||
s->cgr[0] = value;
|
||||
break;
|
||||
case 9:
|
||||
s->cgr[1] = value;
|
||||
break;
|
||||
case 10:
|
||||
s->cgr[2] = value;
|
||||
break;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX31_CCM, __func__, offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct MemoryRegionOps imx31_ccm_ops = {
|
||||
.read = imx31_ccm_read,
|
||||
.write = imx31_ccm_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
.valid = {
|
||||
/*
|
||||
* Our device would not work correctly if the guest was doing
|
||||
* unaligned access. This might not be a limitation on the real
|
||||
* device but in practice there is no reason for a guest to access
|
||||
* this device unaligned.
|
||||
*/
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 4,
|
||||
.unaligned = false,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static void imx31_ccm_init(Object *obj)
|
||||
{
|
||||
DeviceState *dev = DEVICE(obj);
|
||||
SysBusDevice *sd = SYS_BUS_DEVICE(obj);
|
||||
IMX31CCMState *s = IMX31_CCM(obj);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &imx31_ccm_ops, s,
|
||||
TYPE_IMX31_CCM, 0x1000);
|
||||
sysbus_init_mmio(sd, &s->iomem);
|
||||
}
|
||||
|
||||
static void imx31_ccm_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
IMXCCMClass *ccm = IMX_CCM_CLASS(klass);
|
||||
|
||||
dc->reset = imx31_ccm_reset;
|
||||
dc->vmsd = &vmstate_imx31_ccm;
|
||||
dc->desc = "i.MX31 Clock Control Module";
|
||||
|
||||
ccm->get_clock_frequency = imx31_ccm_get_clock_frequency;
|
||||
}
|
||||
|
||||
static const TypeInfo imx31_ccm_info = {
|
||||
.name = TYPE_IMX31_CCM,
|
||||
.parent = TYPE_IMX_CCM,
|
||||
.instance_size = sizeof(IMX31CCMState),
|
||||
.instance_init = imx31_ccm_init,
|
||||
.class_init = imx31_ccm_class_init,
|
||||
};
|
||||
|
||||
static void imx31_ccm_register_types(void)
|
||||
{
|
||||
type_register_static(&imx31_ccm_info);
|
||||
}
|
||||
|
||||
type_init(imx31_ccm_register_types)
|
||||
+22
-209
@@ -7,15 +7,12 @@
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* To get the timer frequencies right, we need to emulate at least part of
|
||||
* the CCM.
|
||||
* This is an abstract base class used to get a common interface to
|
||||
* retrieve the CCM frequencies from the various i.MX SOC.
|
||||
*/
|
||||
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
|
||||
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
|
||||
#define CKIL_FREQ 32768 /* nominal 32khz clock */
|
||||
|
||||
#ifndef DEBUG_IMX_CCM
|
||||
#define DEBUG_IMX_CCM 0
|
||||
#endif
|
||||
@@ -28,51 +25,27 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int imx_ccm_post_load(void *opaque, int version_id);
|
||||
|
||||
static const VMStateDescription vmstate_imx_ccm = {
|
||||
.name = TYPE_IMX_CCM,
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(ccmr, IMXCCMState),
|
||||
VMSTATE_UINT32(pdr0, IMXCCMState),
|
||||
VMSTATE_UINT32(pdr1, IMXCCMState),
|
||||
VMSTATE_UINT32(mpctl, IMXCCMState),
|
||||
VMSTATE_UINT32(spctl, IMXCCMState),
|
||||
VMSTATE_UINT32_ARRAY(cgr, IMXCCMState, 3),
|
||||
VMSTATE_UINT32(pmcr0, IMXCCMState),
|
||||
VMSTATE_UINT32(pmcr1, IMXCCMState),
|
||||
VMSTATE_UINT32(pll_refclk_freq, IMXCCMState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
},
|
||||
.post_load = imx_ccm_post_load,
|
||||
};
|
||||
|
||||
uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
|
||||
uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
|
||||
{
|
||||
IMXCCMState *s = IMX_CCM(dev);
|
||||
uint32_t freq = 0;
|
||||
IMXCCMClass *klass = IMX_GET_CLASS(dev);
|
||||
|
||||
switch (clock) {
|
||||
case NOCLK:
|
||||
return 0;
|
||||
case MCU:
|
||||
return s->mcu_clk_freq;
|
||||
case HSP:
|
||||
return s->hsp_clk_freq;
|
||||
case IPG:
|
||||
return s->ipg_clk_freq;
|
||||
case CLK_32k:
|
||||
return CKIL_FREQ;
|
||||
if (klass->get_clock_frequency) {
|
||||
freq = klass->get_clock_frequency(dev, clock);
|
||||
}
|
||||
return 0;
|
||||
|
||||
DPRINTF("(clock = %d) = %d\n", clock, freq);
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate PLL output frequency
|
||||
*/
|
||||
static uint32_t calc_pll(uint32_t pllreg, uint32_t base_freq)
|
||||
uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
|
||||
{
|
||||
int32_t freq;
|
||||
int32_t mfn = MFN(pllreg); /* Numerator */
|
||||
uint32_t mfi = MFI(pllreg); /* Integer part */
|
||||
uint32_t mfd = 1 + MFD(pllreg); /* Denominator */
|
||||
@@ -81,186 +54,26 @@ static uint32_t calc_pll(uint32_t pllreg, uint32_t base_freq)
|
||||
if (mfi < 5) {
|
||||
mfi = 5;
|
||||
}
|
||||
|
||||
/* mfn is 10-bit signed twos-complement */
|
||||
mfn <<= 32 - 10;
|
||||
mfn >>= 32 - 10;
|
||||
|
||||
return ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
|
||||
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
|
||||
(mfd * pd)) << 10;
|
||||
}
|
||||
|
||||
static void update_clocks(IMXCCMState *s)
|
||||
{
|
||||
/*
|
||||
* If we ever emulate more clocks, this should switch to a data-driven
|
||||
* approach
|
||||
*/
|
||||
DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
|
||||
freq);
|
||||
|
||||
if ((s->ccmr & CCMR_PRCS) == 2) {
|
||||
s->pll_refclk_freq = CKIL_FREQ * 1024;
|
||||
} else {
|
||||
s->pll_refclk_freq = CKIH_FREQ;
|
||||
}
|
||||
|
||||
/* ipg_clk_arm aka MCU clock */
|
||||
if ((s->ccmr & CCMR_MDS) || !(s->ccmr & CCMR_MPE)) {
|
||||
s->mcu_clk_freq = s->pll_refclk_freq;
|
||||
} else {
|
||||
s->mcu_clk_freq = calc_pll(s->mpctl, s->pll_refclk_freq);
|
||||
}
|
||||
|
||||
/* High-speed clock */
|
||||
s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP));
|
||||
s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG));
|
||||
|
||||
DPRINTF("mcu %uMHz, HSP %uMHz, IPG %uHz\n",
|
||||
s->mcu_clk_freq / 1000000,
|
||||
s->hsp_clk_freq / 1000000,
|
||||
s->ipg_clk_freq);
|
||||
}
|
||||
|
||||
static void imx_ccm_reset(DeviceState *dev)
|
||||
{
|
||||
IMXCCMState *s = IMX_CCM(dev);
|
||||
|
||||
s->ccmr = 0x074b0b7b;
|
||||
s->pdr0 = 0xff870b48;
|
||||
s->pdr1 = 0x49fcfe7f;
|
||||
s->mpctl = PLL_PD(1) | PLL_MFD(0) | PLL_MFI(6) | PLL_MFN(0);
|
||||
s->cgr[0] = s->cgr[1] = s->cgr[2] = 0xffffffff;
|
||||
s->spctl = PLL_PD(1) | PLL_MFD(4) | PLL_MFI(0xc) | PLL_MFN(1);
|
||||
s->pmcr0 = 0x80209828;
|
||||
|
||||
update_clocks(s);
|
||||
}
|
||||
|
||||
static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
|
||||
unsigned size)
|
||||
{
|
||||
IMXCCMState *s = (IMXCCMState *)opaque;
|
||||
|
||||
DPRINTF("(offset=0x%" HWADDR_PRIx ")\n", offset);
|
||||
|
||||
switch (offset >> 2) {
|
||||
case 0: /* CCMR */
|
||||
DPRINTF(" ccmr = 0x%x\n", s->ccmr);
|
||||
return s->ccmr;
|
||||
case 1:
|
||||
DPRINTF(" pdr0 = 0x%x\n", s->pdr0);
|
||||
return s->pdr0;
|
||||
case 2:
|
||||
DPRINTF(" pdr1 = 0x%x\n", s->pdr1);
|
||||
return s->pdr1;
|
||||
case 4:
|
||||
DPRINTF(" mpctl = 0x%x\n", s->mpctl);
|
||||
return s->mpctl;
|
||||
case 6:
|
||||
DPRINTF(" spctl = 0x%x\n", s->spctl);
|
||||
return s->spctl;
|
||||
case 8:
|
||||
DPRINTF(" cgr0 = 0x%x\n", s->cgr[0]);
|
||||
return s->cgr[0];
|
||||
case 9:
|
||||
DPRINTF(" cgr1 = 0x%x\n", s->cgr[1]);
|
||||
return s->cgr[1];
|
||||
case 10:
|
||||
DPRINTF(" cgr2 = 0x%x\n", s->cgr[2]);
|
||||
return s->cgr[2];
|
||||
case 18: /* LTR1 */
|
||||
return 0x00004040;
|
||||
case 23:
|
||||
DPRINTF(" pcmr0 = 0x%x\n", s->pmcr0);
|
||||
return s->pmcr0;
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void imx_ccm_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
IMXCCMState *s = (IMXCCMState *)opaque;
|
||||
|
||||
DPRINTF("(offset=0x%" HWADDR_PRIx ", value = 0x%x)\n",
|
||||
offset, (unsigned int)value);
|
||||
|
||||
switch (offset >> 2) {
|
||||
case 0:
|
||||
s->ccmr = CCMR_FPMF | (value & 0x3b6fdfff);
|
||||
break;
|
||||
case 1:
|
||||
s->pdr0 = value & 0xff9f3fff;
|
||||
break;
|
||||
case 2:
|
||||
s->pdr1 = value;
|
||||
break;
|
||||
case 4:
|
||||
s->mpctl = value & 0xbfff3fff;
|
||||
break;
|
||||
case 6:
|
||||
s->spctl = value & 0xbfff3fff;
|
||||
break;
|
||||
case 8:
|
||||
s->cgr[0] = value;
|
||||
return;
|
||||
case 9:
|
||||
s->cgr[1] = value;
|
||||
return;
|
||||
case 10:
|
||||
s->cgr[2] = value;
|
||||
return;
|
||||
|
||||
default:
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
|
||||
HWADDR_PRIx "\n", TYPE_IMX_CCM, __func__, offset);
|
||||
return;
|
||||
}
|
||||
update_clocks(s);
|
||||
}
|
||||
|
||||
static const struct MemoryRegionOps imx_ccm_ops = {
|
||||
.read = imx_ccm_read,
|
||||
.write = imx_ccm_write,
|
||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||
};
|
||||
|
||||
static int imx_ccm_init(SysBusDevice *dev)
|
||||
{
|
||||
IMXCCMState *s = IMX_CCM(dev);
|
||||
|
||||
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
|
||||
TYPE_IMX_CCM, 0x1000);
|
||||
sysbus_init_mmio(dev, &s->iomem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx_ccm_post_load(void *opaque, int version_id)
|
||||
{
|
||||
IMXCCMState *s = (IMXCCMState *)opaque;
|
||||
|
||||
update_clocks(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void imx_ccm_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
|
||||
|
||||
sbc->init = imx_ccm_init;
|
||||
dc->reset = imx_ccm_reset;
|
||||
dc->vmsd = &vmstate_imx_ccm;
|
||||
dc->desc = "i.MX Clock Control Module";
|
||||
return freq;
|
||||
}
|
||||
|
||||
static const TypeInfo imx_ccm_info = {
|
||||
.name = TYPE_IMX_CCM,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.name = TYPE_IMX_CCM,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(IMXCCMState),
|
||||
.class_init = imx_ccm_class_init,
|
||||
.class_size = sizeof(IMXCCMClass),
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void imx_ccm_register_types(void)
|
||||
|
||||
+9
-11
@@ -51,9 +51,9 @@ static char const *imx_epit_reg_name(uint32_t reg)
|
||||
* These are typical.
|
||||
*/
|
||||
static const IMXClk imx_epit_clocks[] = {
|
||||
0, /* 00 disabled */
|
||||
IPG, /* 01 ipg_clk, ~532MHz */
|
||||
IPG, /* 10 ipg_clk_highfreq */
|
||||
NOCLK, /* 00 disabled */
|
||||
CLK_IPG, /* 01 ipg_clk, ~532MHz */
|
||||
CLK_IPG, /* 10 ipg_clk_highfreq */
|
||||
CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */
|
||||
};
|
||||
|
||||
@@ -73,20 +73,18 @@ static void imx_epit_set_freq(IMXEPITState *s)
|
||||
{
|
||||
uint32_t clksrc;
|
||||
uint32_t prescaler;
|
||||
uint32_t freq;
|
||||
|
||||
clksrc = extract32(s->cr, CR_CLKSRC_SHIFT, 2);
|
||||
prescaler = 1 + extract32(s->cr, CR_PRESCALE_SHIFT, 12);
|
||||
|
||||
freq = imx_clock_frequency(s->ccm, imx_epit_clocks[clksrc]) / prescaler;
|
||||
s->freq = imx_ccm_get_clock_frequency(s->ccm,
|
||||
imx_epit_clocks[clksrc]) / prescaler;
|
||||
|
||||
s->freq = freq;
|
||||
DPRINTF("Setting ptimer frequency to %u\n", s->freq);
|
||||
|
||||
DPRINTF("Setting ptimer frequency to %u\n", freq);
|
||||
|
||||
if (freq) {
|
||||
ptimer_set_freq(s->timer_reload, freq);
|
||||
ptimer_set_freq(s->timer_cmp, freq);
|
||||
if (s->freq) {
|
||||
ptimer_set_freq(s->timer_reload, s->freq);
|
||||
ptimer_set_freq(s->timer_cmp, s->freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -81,8 +81,8 @@ static const VMStateDescription vmstate_imx_timer_gpt = {
|
||||
|
||||
static const IMXClk imx_gpt_clocks[] = {
|
||||
NOCLK, /* 000 No clock source */
|
||||
IPG, /* 001 ipg_clk, 532MHz*/
|
||||
IPG, /* 010 ipg_clk_highfreq */
|
||||
CLK_IPG, /* 001 ipg_clk, 532MHz*/
|
||||
CLK_IPG, /* 010 ipg_clk_highfreq */
|
||||
NOCLK, /* 011 not defined */
|
||||
CLK_32k, /* 100 ipg_clk_32k */
|
||||
NOCLK, /* 101 not defined */
|
||||
@@ -93,14 +93,14 @@ static const IMXClk imx_gpt_clocks[] = {
|
||||
static void imx_gpt_set_freq(IMXGPTState *s)
|
||||
{
|
||||
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
|
||||
uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc])
|
||||
/ (1 + s->pr);
|
||||
s->freq = freq;
|
||||
|
||||
DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq);
|
||||
s->freq = imx_ccm_get_clock_frequency(s->ccm,
|
||||
imx_gpt_clocks[clksrc]) / (1 + s->pr);
|
||||
|
||||
if (freq) {
|
||||
ptimer_set_freq(s->timer, freq);
|
||||
DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, s->freq);
|
||||
|
||||
if (s->freq) {
|
||||
ptimer_set_freq(s->timer, s->freq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -148,6 +148,32 @@ typedef enum {
|
||||
AML_SHARED_AND_WAKE = 3,
|
||||
} AmlShared;
|
||||
|
||||
/* ACPI 1.0b: 16.2.5.2 Named Objects Encoding: MethodFlags */
|
||||
typedef enum {
|
||||
AML_NOTSERIALIZED = 0,
|
||||
AML_SERIALIZED = 1,
|
||||
} AmlSerializeFlag;
|
||||
|
||||
/*
|
||||
* ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition
|
||||
* GPIO Connection Type
|
||||
*/
|
||||
typedef enum {
|
||||
AML_INTERRUPT_CONNECTION = 0,
|
||||
AML_IO_CONNECTION = 1,
|
||||
} AmlGpioConnectionType;
|
||||
|
||||
/*
|
||||
* ACPI 5.0: Table 6-189 GPIO Connection Descriptor Definition
|
||||
* _PPI field definition
|
||||
*/
|
||||
typedef enum {
|
||||
AML_PULL_DEFAULT = 0,
|
||||
AML_PULL_UP = 1,
|
||||
AML_PULL_DOWN = 2,
|
||||
AML_PULL_NONE = 3,
|
||||
} AmlPinConfig;
|
||||
|
||||
typedef
|
||||
struct AcpiBuildTables {
|
||||
GArray *table_data;
|
||||
@@ -212,12 +238,19 @@ Aml *aml_call1(const char *method, Aml *arg1);
|
||||
Aml *aml_call2(const char *method, Aml *arg1, Aml *arg2);
|
||||
Aml *aml_call3(const char *method, Aml *arg1, Aml *arg2, Aml *arg3);
|
||||
Aml *aml_call4(const char *method, Aml *arg1, Aml *arg2, Aml *arg3, Aml *arg4);
|
||||
Aml *aml_gpio_int(AmlConsumerAndProducer con_and_pro,
|
||||
AmlLevelAndEdge edge_level,
|
||||
AmlActiveHighAndLow active_level, AmlShared shared,
|
||||
AmlPinConfig pin_config, uint16_t debounce_timeout,
|
||||
const uint32_t pin_list[], uint32_t pin_count,
|
||||
const char *resource_source_name,
|
||||
const uint8_t *vendor_data, uint16_t vendor_data_len);
|
||||
Aml *aml_memory32_fixed(uint32_t addr, uint32_t size,
|
||||
AmlReadAndWrite read_and_write);
|
||||
Aml *aml_interrupt(AmlConsumerAndProducer con_and_pro,
|
||||
AmlLevelAndEdge level_and_edge,
|
||||
AmlActiveHighAndLow high_and_low, AmlShared shared,
|
||||
uint32_t irq);
|
||||
uint32_t *irq_list, uint8_t irq_count);
|
||||
Aml *aml_io(AmlIODecode dec, uint16_t min_base, uint16_t max_base,
|
||||
uint8_t aln, uint8_t len);
|
||||
Aml *aml_operation_region(const char *name, AmlRegionSpace rs,
|
||||
@@ -262,7 +295,7 @@ Aml *aml_qword_memory(AmlDecode dec, AmlMinFixed min_fixed,
|
||||
/* Block AML object primitives */
|
||||
Aml *aml_scope(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
|
||||
Aml *aml_device(const char *name_format, ...) GCC_FMT_ATTR(1, 2);
|
||||
Aml *aml_method(const char *name, int arg_count);
|
||||
Aml *aml_method(const char *name, int arg_count, AmlSerializeFlag sflag);
|
||||
Aml *aml_if(Aml *predicate);
|
||||
Aml *aml_else(void);
|
||||
Aml *aml_while(Aml *predicate);
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/intc/imx_avic.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
#include "hw/misc/imx25_ccm.h"
|
||||
#include "hw/char/imx_serial.h"
|
||||
#include "hw/timer/imx_gpt.h"
|
||||
#include "hw/timer/imx_epit.h"
|
||||
@@ -44,7 +44,7 @@ typedef struct FslIMX25State {
|
||||
/*< public >*/
|
||||
ARMCPU cpu;
|
||||
IMXAVICState avic;
|
||||
IMXCCMState ccm;
|
||||
IMX25CCMState ccm;
|
||||
IMXSerialState uart[FSL_IMX25_NUM_UARTS];
|
||||
IMXGPTState gpt[FSL_IMX25_NUM_GPTS];
|
||||
IMXEPITState epit[FSL_IMX25_NUM_EPITS];
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
#include "hw/arm/arm.h"
|
||||
#include "hw/intc/imx_avic.h"
|
||||
#include "hw/misc/imx_ccm.h"
|
||||
#include "hw/misc/imx31_ccm.h"
|
||||
#include "hw/char/imx_serial.h"
|
||||
#include "hw/timer/imx_gpt.h"
|
||||
#include "hw/timer/imx_epit.h"
|
||||
@@ -42,7 +42,7 @@ typedef struct FslIMX31State {
|
||||
/*< public >*/
|
||||
ARMCPU cpu;
|
||||
IMXAVICState avic;
|
||||
IMXCCMState ccm;
|
||||
IMX31CCMState ccm;
|
||||
IMXSerialState uart[FSL_IMX31_NUM_UARTS];
|
||||
IMXGPTState gpt;
|
||||
IMXEPITState epit[FSL_IMX31_NUM_EPITS];
|
||||
|
||||
@@ -59,6 +59,7 @@ enum {
|
||||
VIRT_PCIE_ECAM,
|
||||
VIRT_PLATFORM_BUS,
|
||||
VIRT_PCIE_MMIO_HIGH,
|
||||
VIRT_GPIO,
|
||||
};
|
||||
|
||||
typedef struct MemMapEntry {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user