blob: 9fe4235abc776c5af9f6fb48334d94204c1151d3 [file] [log] [blame]
// Copyright 2017 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 <arch/arm64/periphmap.h>
#include <dev/power.h>
#include <dev/psci.h>
#include <pdev/driver.h>
#include <pdev/power.h>
#include <zircon/boot/driver-config.h>
#include <stdio.h>
// clang-format off
#define PMU_HRST_OFFSET 0x404
#define SCTRL_PEREN1_OFFSET 0x170
#define SCTRL_DDR_BYPASS (1 << 31)
#define SCTRL_REBOOT_OFFSET 0x4
// clang-format on
static vaddr_t sctrl_base;
static vaddr_t pmu_base;
static void hisi_reboot(enum reboot_flags flags) {
uint32_t temp = readl(pmu_base + PMU_HRST_OFFSET);
temp = (temp & 0xFFFFFF00) | (flags == REBOOT_BOOTLOADER ? 1 : 0);
writel(temp, pmu_base + PMU_HRST_OFFSET);
writel(SCTRL_DDR_BYPASS, sctrl_base + SCTRL_PEREN1_OFFSET);
writel(0xdeadbeef, sctrl_base + SCTRL_REBOOT_OFFSET);
}
static void hisi_shutdown() {
printf("SHUTDOWN NOT IMPLEMENTED\n");
}
static const struct pdev_power_ops hisi_power_ops = {
.reboot = hisi_reboot,
.shutdown = hisi_shutdown,
};
static void hisi_power_init(const void* driver_data, uint32_t length) {
ASSERT(length >= sizeof(dcfg_hisilicon_power_driver_t));
auto driver = static_cast<const dcfg_hisilicon_power_driver_t*>(driver_data);
ASSERT(driver->sctrl_phys && driver->pmu_phys);
// get virtual addresses of our peripheral bases
sctrl_base = periph_paddr_to_vaddr(driver->sctrl_phys);
pmu_base = periph_paddr_to_vaddr(driver->pmu_phys);
ASSERT(sctrl_base && pmu_base);
pdev_register_power(&hisi_power_ops);
}
LK_PDEV_INIT(hisi_power_init, KDRV_HISILICON_POWER, hisi_power_init, LK_INIT_LEVEL_PLATFORM);