summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2019-03-08 12:25:36 +1000
committerAlistair Popple <alistair@popple.id.au>2019-03-08 15:28:21 +1100
commit7de0ee34699e297f1f224fce1790c3cd03bc2f32 (patch)
treed9028f38157a258ae194defd5831f8eb010eb2c6
parent7f55d463c7cc44d7a48818b10774f5c86f6df8dc (diff)
downloadpdbg-7de0ee34699e297f1f224fce1790c3cd03bc2f32.tar.gz
pdbg-7de0ee34699e297f1f224fce1790c3cd03bc2f32.zip
libpdbg/p8chip.c: release special wakeups for P8
This copies the special wakeup release logic from p9chip.c Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
-rw-r--r--libpdbg/p8chip.c61
1 files changed, 53 insertions, 8 deletions
diff --git a/libpdbg/p8chip.c b/libpdbg/p8chip.c
index b93e953..b9fa26d 100644
--- a/libpdbg/p8chip.c
+++ b/libpdbg/p8chip.c
@@ -163,16 +163,11 @@ static int assert_special_wakeup(struct core *chip)
return 0;
}
-#if 0
-/* TODO: Work out when to do this. */
-static int deassert_special_wakeup(struct core *chip)
+static void deassert_special_wakeup(struct core *chip)
{
/* Assert special wakeup to prevent low power states */
- CHECK_ERR(pib_write(&chip->target, PMSPCWKUPFSP_REG, 0));
-
- return 0;
+ pib_write(&chip->target, PMSPCWKUPFSP_REG, 0);
}
-#endif
static struct thread_state get_thread_status(struct thread *thread)
{
@@ -487,6 +482,16 @@ static int p8_thread_probe(struct pdbg_target *target)
return 0;
}
+static void p8_thread_release(struct pdbg_target *target)
+{
+ struct core *core = target_to_core(pdbg_target_require_parent("core", target));
+ struct thread *thread = target_to_thread(target);
+
+ if (thread->status.quiesced)
+ /* this thread is still quiesced so don't release spwkup */
+ core->release_spwkup = false;
+}
+
static int p8_get_hid0(struct pdbg_target *chip, uint64_t *value)
{
CHECK_ERR(pib_read(chip, HID0_REG, value));
@@ -534,6 +539,7 @@ static struct thread p8_thread = {
.compatible = "ibm,power8-thread",
.class = "thread",
.probe = p8_thread_probe,
+ .release = p8_thread_release,
},
.step = p8_thread_step,
.start = p8_thread_start,
@@ -562,16 +568,55 @@ static int p8_core_probe(struct pdbg_target *target)
if (!GETFIELD(PPC_BIT(0), value))
return -1;
- assert_special_wakeup(core);
+ if (assert_special_wakeup(core))
+ return -1;
+
+ /* Child threads will set this to false if they are released while quiesced */
+ core->release_spwkup = true;
+
return 0;
}
+static void p8_core_release(struct pdbg_target *target)
+{
+ struct pdbg_target *child;
+ struct core *core = target_to_core(target);
+ enum pdbg_target_status status;
+
+ usleep(1); /* enforce small delay before and after it is cleared */
+
+ /* Probe and release all threads to ensure release_spwkup is up to
+ * date */
+ pdbg_for_each_target("thread", target, child) {
+ status = pdbg_target_status(child);
+
+ /* This thread has already been release so should have set
+ * release_spwkup to false if it was quiesced, */
+ if (status == PDBG_TARGET_RELEASED)
+ continue;
+
+ status = pdbg_target_probe(child);
+ if (status != PDBG_TARGET_ENABLED)
+ continue;
+
+ /* Release the thread to ensure release_spwkup is updated. */
+ pdbg_target_release(child);
+ }
+
+ if (!core->release_spwkup)
+ return;
+
+ deassert_special_wakeup(core);
+ usleep(10000);
+}
+
static struct core p8_core = {
.target = {
.name = "POWER8 Core",
.compatible = "ibm,power8-core",
.class = "core",
.probe = p8_core_probe,
+ .release = p8_core_release,
},
};
DECLARE_HW_UNIT(p8_core);
OpenPOWER on IntegriCloud