platform: generic: eswin: Add shutdown/reboot support for Hifive Premier P550

Hifive Premier P550[1] is a Mini-DTX form factor board with EIC7700X.
It has a STM32F407VET6 onboard MCU acting as the BMC, controlling
ATX power on/off while providing remote management features. The
EIC7700X SoC/SoM communicates with the BMC via UART2, using ESWIN's
protocol. The messages transmitted are fixed sizes (267 bytes), and
depending on the type, can be directional or bi-directional. The
shutdown and cold reboot requests are directional messages from SoC
to BMC (NOTIFY type) with CMD_POWER_OFF or CMD_RESTART. The payload
of shutdown/cold reboot requests should be empty and are ignored by
the BMC at the moment. A HFP (Hifive Premier) specific reset device
is registered in addition to the SoC reset device. For shutdown and
cold reboot, the board-level reset takes precedence.

The definitions of the SoC <-> BMC message protocol is taken from
ESWIN's repo [2]. The only file used from that repo is `hf_common.h`
It's disjunctively dual licensed as (GPL-2.0-only OR BSD-2-Clause),
hence, compatible with the license of OpenSBI. It's heavily modified
and renamed as platform/generic/include/eswin/hfp.h. The author and
copyright in the original file are retained.

Validated shutdown/cold reboot working on Hifive Premier P550.

[1] https://www.sifive.com/boards/hifive-premier-p550#documentation
[2] https://github.com/eswincomputing/hifive-premier-p550-mcu-patches.git

Signed-off-by: Bo Gan <ganboing@gmail.com>
Reviewed-by: Anup Patel <anup@brainfault.org>
Link: https://lore.kernel.org/r/20251218104243.562667-8-ganboing@gmail.com
Signed-off-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
Bo Gan
2025-12-18 02:42:43 -08:00
committed by Anup Patel
parent fbff3a7e07
commit 73183a60ab
5 changed files with 207 additions and 0 deletions

View File

@@ -48,7 +48,16 @@ struct eic770x_board_override {
#define EIC770X_SYSPORT_SIZE 0x20000000UL
#define EIC770X_SYSPORT_BASE(d) (0x40000000UL + EIC770X_SYSPORT_SIZE * (d))
#define EIC770X_SYSPORT_LOCAL EIC770X_SYSPORT_BASE(current_hart_die())
#define EIC770X_UART0 (EIC770X_SYSPORT_LOCAL + 0x10900000UL)
#define EIC770X_UART_SIZE 0x10000UL
#define EIC770X_UART(x) (EIC770X_UART0 + EIC770X_UART_SIZE * (x))
#define EIC770X_UART_REG_SHIFT 2
#define EIC770X_UART_REG_WIDTH 4
#define EIC770X_SYSCRG (EIC770X_SYSPORT_LOCAL + 0x11828000UL)
#define EIC770X_SYSCRG_LSPCLK0 (EIC770X_SYSCRG + 0x200UL)
#define EIC770X_SYSCRG_SYSCLK (EIC770X_SYSCRG + 0x20cUL)
#define EIC770X_SYSCRG_RST (EIC770X_SYSCRG + 0x300UL)
#define EIC770X_SYSCRG_RST_VAL 0x1AC0FFE6UL
@@ -76,4 +85,17 @@ struct eic770x_board_override {
#define EIC770X_TO_UNCACHED(x) ((x) - EIC770X_CACHED_BASE + \
EIC770X_UNCACHED_BASE)
/* Clock definitions */
#define EIC770X_XTAL_CLK_RATE 24000000UL
#define EIC770X_SPLL0_OUT1_RATE 1600000000UL
#define EIC770X_SPLL0_OUT2_RATE 800000000UL
#define EIC770X_SPLL0_OUT3_RATE 400000000UL
#define EIC770X_UART_CLK_BIT(x) (1UL << ((x) + 17))
#define EIC770X_SYSCLK_SEL(x) ((x) & 1)
#define EIC770X_SYSCLK_DIV(x) \
({ \
uint32_t divisor = ((x) >> 4) & 7; \
divisor > 2 ? divisor : 2; \
})
#endif

View File

@@ -0,0 +1,64 @@
// SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
/*
* Copyright (c) 2024 Beijing ESWIN Computing Technology Co., Ltd.
*
* Authors:
* Lin Min <linmin@eswincomputing.com>
* Bo Gan <ganboing@gmail.com>
*
* Adapted from Core/Inc/hf_common.h from ESWIN's Hifive Premier P550
* onboard BMC (MCU) source repo:
* https://github.com/eswincomputing/hifive-premier-p550-mcu-patches.git
*
*/
#ifndef __ESWIN_HFP_H__
#define __ESWIN_HFP_H__
#include <sbi/sbi_types.h>
enum hfp_bmc_msg {
HFP_MSG_REQUEST = 1,
HFP_MSG_REPLY,
HFP_MSG_NOTIFY,
};
enum hfp_bmc_cmd {
HFP_CMD_POWER_OFF = 1,
HFP_CMD_REBOOT,
HFP_CMD_READ_BOARD_INFO,
HFP_CMD_CONTROL_LED,
HFP_CMD_PVT_INFO,
HFP_CMD_BOARD_STATUS,
HFP_CMD_POWER_INFO,
HFP_CMD_RESTART, // cold reboot with power off/on
};
#define MAGIC_HEADER 0xA55AAA55
#define MAGIC_TAIL 0xBDBABDBA
struct hfp_bmc_message {
uint32_t header_magic;
uint32_t task_id;
uint8_t type;
uint8_t cmd;
uint8_t result;
uint8_t data_len;
uint8_t data[250];
uint8_t checksum;
uint32_t tail_magic;
} __packed;
static inline void hfp_bmc_checksum_msg(struct hfp_bmc_message *msg)
{
msg->checksum = 0;
msg->checksum ^= msg->type;
msg->checksum ^= msg->cmd;
msg->checksum ^= msg->data_len;
for (uint8_t i = 0; i != msg->data_len; i++)
msg->checksum ^= msg->data[i];
}
extern const struct eic770x_board_override hfp_override;
#endif