blob: 009af22922caa1c1f3944a56e70eca5aa5a458cb [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FORCEWAKE_H
#define FORCEWAKE_H
#include "magma_util/macros.h"
#include "magma_util/register_io.h"
#include "registers.h"
#include <thread>
class ForceWake {
public:
static void reset(magma::RegisterIo* reg_io, registers::ForceWake::Domain domain)
{
registers::ForceWake::reset(reg_io, domain);
}
static void request(magma::RegisterIo* reg_io, registers::ForceWake::Domain domain)
{
if (registers::ForceWake::read_status(reg_io, domain) & (1 << kThreadShift))
return;
DLOG("forcewake request");
registers::ForceWake::write(reg_io, domain, 1 << kThreadShift, 1 << kThreadShift);
wait(reg_io, domain, true);
}
static void release(magma::RegisterIo* reg_io, registers::ForceWake::Domain domain)
{
if ((registers::ForceWake::read_status(reg_io, domain) & (1 << kThreadShift)) == 0)
return;
DLOG("forcewake release");
registers::ForceWake::write(reg_io, domain, 1 << kThreadShift, 0);
wait(reg_io, domain, false);
}
private:
static void wait(magma::RegisterIo* reg_io, registers::ForceWake::Domain domain, bool set)
{
uint32_t status;
for (unsigned int ms = 0; ms < kRetryMaxMs; ms++) {
status = registers::ForceWake::read_status(reg_io, domain);
if (((status >> kThreadShift) & 1) == (set ? 1 : 0))
return;
std::this_thread::sleep_for(std::chrono::milliseconds(1));
DLOG("forcewake wait retrying");
}
DLOG("timed out waiting for forcewake, status 0x%x", status);
}
static constexpr uint32_t kThreadShift = 0;
static constexpr uint32_t kRetryMaxMs = 3;
friend class TestForceWake;
};
#endif // FORCEWAKE_H