aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Alcantara <pcacjr@zytor.com>2015-06-27 11:15:47 -0300
committerPaulo Alcantara <pcacjr@zytor.com>2015-06-27 14:37:50 -0300
commit6e8c951cf35d3250da3960955bfe53d2c6ed9503 (patch)
treef6d77345d615e166ec741b2ac6cc6e5feecb3258
parent607adae1d5cea1c198f1e3e941c050e9ae97d5f8 (diff)
downloadqemu-ich9-tco-v7.tar.gz
qemu-ich9-tco-v7.tar.xz
qemu-ich9-tco-v7.zip
ich9: implement strap SPKR pin logicich9-tco-v7
If the signal is sampled high, this indicates that the system is strapped to the "No Reboot" mode (ICH9 will disable the TCO Timer system reboot feature). The status of this strap is readable via the NO_REBOOT bit (CC: offset 0x3410:bit 5). The NO_REBOOT bit is set when SPKR pin on ICH9 is sampled high. This bit may be set or cleared by software if the strap is sampled low but may not override the strap when it indicates "No Reboot". This patch implements the logic where hardware has ability to set SPKR pin through a property named "pin-spkr" and it's sampled low by default. Signed-off-by: Paulo Alcantara <pcacjr@zytor.com>
-rw-r--r--hw/acpi/tco.c3
-rw-r--r--hw/isa/lpc_ich9.c38
-rw-r--r--include/hw/i386/ich9.h11
3 files changed, 51 insertions, 1 deletions
diff --git a/hw/acpi/tco.c b/hw/acpi/tco.c
index 1794a5454..c1f573972 100644
--- a/hw/acpi/tco.c
+++ b/hw/acpi/tco.c
@@ -64,7 +64,8 @@ static void tco_timer_expired(void *opaque)
tr->tco.sts2 |= TCO_BOOT_STS;
tr->timeouts_no = 0;
- if (!(gcs & ICH9_CC_GCS_NO_REBOOT)) {
+ if ((lpc->pin_strap.spkr & ICH9_PS_SPKR_PIN_LOW) &&
+ !(gcs & ICH9_CC_GCS_NO_REBOOT)) {
watchdog_perform_action();
tco_timer_stop(tr);
return;
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index b547002e6..49d1f302f 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -575,11 +575,49 @@ static void ich9_lpc_get_sci_int(Object *obj, Visitor *v,
visit_type_uint32(v, &value, name, errp);
}
+static void ich9_lpc_get_spkr_pin(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ ICH9LPCState *lpc = opaque;
+ uint8_t value = lpc->pin_strap.spkr;
+
+ visit_type_uint8(v, &value, name, errp);
+}
+
+static void ich9_lpc_set_spkr_pin(Object *obj, Visitor *v,
+ void *opaque, const char *name,
+ Error **errp)
+{
+ ICH9LPCState *lpc = opaque;
+ Error *local_err = NULL;
+ uint8_t value;
+ uint32_t *gcs;
+
+ visit_type_uint8(v, &value, name, &local_err);
+ if (local_err) {
+ goto out;
+ }
+ value &= ICH9_PS_SPKR_PIN_MASK;
+ if (value & ICH9_PS_SPKR_PIN_HIGH) {
+ gcs = (uint32_t *)&lpc->chip_config[ICH9_CC_GCS];
+ *gcs |= ICH9_CC_GCS_NO_REBOOT;
+ }
+ lpc->pin_strap.spkr = value;
+out:
+ error_propagate(errp, local_err);
+}
+
static void ich9_lpc_add_properties(ICH9LPCState *lpc)
{
static const uint8_t acpi_enable_cmd = ICH9_APM_ACPI_ENABLE;
static const uint8_t acpi_disable_cmd = ICH9_APM_ACPI_DISABLE;
+ lpc->pin_strap.spkr = ICH9_PS_SPKR_PIN_DEFAULT;
+ object_property_add(OBJECT(lpc), "pin-spkr", "uint8",
+ ich9_lpc_get_spkr_pin,
+ ich9_lpc_set_spkr_pin,
+ NULL, lpc, NULL);
object_property_add(OBJECT(lpc), ACPI_PM_PROP_SCI_INT, "uint32",
ich9_lpc_get_sci_int,
NULL, NULL, NULL, NULL);
diff --git a/include/hw/i386/ich9.h b/include/hw/i386/ich9.h
index f5681a326..aafc43fad 100644
--- a/include/hw/i386/ich9.h
+++ b/include/hw/i386/ich9.h
@@ -46,6 +46,11 @@ typedef struct ICH9LPCState {
ICH9LPCPMRegs pm;
uint32_t sci_level; /* track sci level */
+ /* 2.24 Pin Straps */
+ struct {
+ uint8_t spkr;
+ } pin_strap;
+
/* 10.1 Chipset Configuration registers(Memory Space)
which is pointed by RCBA */
uint8_t chip_config[ICH9_CC_SIZE];
@@ -72,6 +77,12 @@ Object *ich9_lpc_find(void);
#define Q35_MASK(bit, ms_bit, ls_bit) \
((uint##bit##_t)(((1ULL << ((ms_bit) + 1)) - 1) & ~((1ULL << ls_bit) - 1)))
+/* ICH9: Pin Straps */
+#define ICH9_PS_SPKR_PIN_LOW 0x01
+#define ICH9_PS_SPKR_PIN_HIGH 0x02
+#define ICH9_PS_SPKR_PIN_MASK 0x03
+#define ICH9_PS_SPKR_PIN_DEFAULT ICH9_PS_SPKR_PIN_LOW
+
/* ICH9: Chipset Configuration Registers */
#define ICH9_CC_ADDR_MASK (ICH9_CC_SIZE - 1)