blob: 24179660f1d2a12caa5fdd0947cb54529b8a6111 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <reg.h>
#include <stdio.h>
#include <zircon/boot/driver-config.h>
#include <arch/arm64/periphmap.h>
#include <dev/power.h>
#include <dev/psci.h>
#include <pdev/driver.h>
#include <pdev/power.h>
static vaddr_t imem_base;
static vaddr_t imem_offset;
enum RestartReason {
RESTART_REASON_BOOTLOADER = 0x77665500,
};
static void msm_reboot(enum reboot_flags flags) {
// Set reboot_reason and handoff to PSCI for the actual reboot.
if (flags == REBOOT_BOOTLOADER) {
writel(RESTART_REASON_BOOTLOADER, periph_paddr_to_vaddr(imem_base + imem_offset));
}
psci_system_reset(flags);
}
static void msm_shutdown() {
// Handoff to PSCI
psci_system_off();
}
static const struct pdev_power_ops msm_power_ops = {
.reboot = msm_reboot,
.shutdown = msm_shutdown,
};
static void msm_power_init(const void* driver_data, uint32_t length) {
ASSERT(length >= sizeof(dcfg_msm_power_driver_t));
auto driver = static_cast<const dcfg_msm_power_driver_t*>(driver_data);
ASSERT(driver->soc_imem_phys);
// get virtual addresses of our peripheral bases
imem_base = driver->soc_imem_phys;
imem_offset = driver->soc_imem_offset;
ASSERT(imem_base);
pdev_register_power(&msm_power_ops);
}
LK_PDEV_INIT(msm_power_init, KDRV_MSM_POWER, msm_power_init, LK_INIT_LEVEL_PLATFORM)