122 lines
2.0 KiB
C
122 lines
2.0 KiB
C
/*
|
|
* pmu.c
|
|
*
|
|
* Copyright (C) 2022 Sylvain Munaut <tnt@246tNt.com>
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
#include "pmu.h"
|
|
|
|
|
|
struct wb_pmu {
|
|
uint32_t ctrl;
|
|
uint32_t stat;
|
|
} __attribute__((packed,aligned(4)));
|
|
|
|
#define PMU_CTRL_BOOT_EXEC (1 << 18)
|
|
#define PMU_CTRL_BOOT_SEL(n) (((n) & 3) << 16)
|
|
#define PMU_CTRL_SYS_SHUTDOWN (1 << 11)
|
|
#define PMU_CTRL_SYS_SUSPEND (1 << 10)
|
|
#define PMU_CTRL_USB_OFF (1 << 9)
|
|
#define PMU_CTRL_USB_ON (1 << 8)
|
|
#define PMU_CTRL_BTN2_ACK (1 << 3)
|
|
#define PMU_CTRL_BTN1_ACK (1 << 1)
|
|
|
|
#define PMU_STAT_USB (1 << 8)
|
|
#define PMU_STAT_VBUS (1 << 5)
|
|
#define PMU_STAT_CHARGING (1 << 4)
|
|
#define PMU_STAT_BTN2_EVT (1 << 3)
|
|
#define PMU_STAT_BTN2_LONG (1 << 2)
|
|
#define PMU_STAT_BTN1_EVT (1 << 1)
|
|
#define PMU_STAT_BTN1_LONG (1 << 0)
|
|
|
|
|
|
static volatile struct wb_pmu * const pmu_regs= (void*)(PMU_BASE);
|
|
|
|
|
|
void
|
|
pmu_sys_suspend(void)
|
|
{
|
|
pmu_regs->ctrl = PMU_CTRL_SYS_SUSPEND;
|
|
}
|
|
|
|
void
|
|
pmu_sys_shutdown(void)
|
|
{
|
|
pmu_regs->ctrl = PMU_CTRL_SYS_SHUTDOWN;
|
|
}
|
|
|
|
void
|
|
pmu_sys_reboot(int n)
|
|
{
|
|
pmu_regs->ctrl = PMU_CTRL_BOOT_SEL(n) | PMU_CTRL_BOOT_EXEC;
|
|
}
|
|
|
|
|
|
void
|
|
pmu_usb_enable(void)
|
|
{
|
|
pmu_regs->ctrl = PMU_CTRL_USB_ON;
|
|
}
|
|
|
|
void
|
|
pmu_usb_disable(void)
|
|
{
|
|
pmu_regs->ctrl = PMU_CTRL_USB_OFF;
|
|
}
|
|
|
|
void
|
|
pmu_usb_set_state(bool state)
|
|
{
|
|
pmu_regs->ctrl = state ? PMU_CTRL_USB_ON : PMU_CTRL_USB_OFF;
|
|
}
|
|
|
|
bool
|
|
pmu_usb_state(void)
|
|
{
|
|
return !!(pmu_regs->stat & PMU_STAT_USB);
|
|
}
|
|
|
|
|
|
bool
|
|
pmu_is_charging(void)
|
|
{
|
|
return !!(pmu_regs->stat & PMU_STAT_CHARGING);
|
|
}
|
|
|
|
bool
|
|
pmu_is_vbus_present(void)
|
|
{
|
|
return !!(pmu_regs->stat & PMU_STAT_VBUS);
|
|
}
|
|
|
|
|
|
uint8_t
|
|
pmu_get_buttons(void)
|
|
{
|
|
uint32_t btn;
|
|
uint32_t ack = 0;
|
|
uint8_t rv = 0;
|
|
|
|
/* Read status */
|
|
btn = pmu_regs->stat;
|
|
|
|
/* Translate to events */
|
|
if (btn & PMU_STAT_BTN1_EVT) {
|
|
rv |= (btn & PMU_STAT_BTN1_LONG) ? BTN_1_LONG : BTN_1_SHORT;
|
|
ack |= PMU_CTRL_BTN1_ACK;
|
|
}
|
|
|
|
if (btn & PMU_STAT_BTN2_EVT) {
|
|
rv |= (btn & PMU_STAT_BTN2_LONG) ? BTN_2_LONG : BTN_2_SHORT;
|
|
ack |= PMU_CTRL_BTN2_ACK;
|
|
}
|
|
|
|
/* Ack */
|
|
if (ack)
|
|
pmu_regs->ctrl = ack;
|
|
|
|
return rv;
|
|
}
|