blob: 9cd62772ef4de0576c06957586917824ec48f0ee [file] [log] [blame]
Kongyang Liu3632ad52024-04-16 15:52:38 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com>
4 */
5
6#include <dm.h>
7#include <stdbool.h>
8#include <sysreset.h>
9#include <wait_bit.h>
10#include <linux/io.h>
11#include <linux/errno.h>
12
13#define REG_RTC_BASE (void *)0x05026000
14#define REG_RTC_CTRL_BASE (void *)0x05025000
15#define REG_RTC_EN_SHDN_REQ (REG_RTC_BASE + 0xc0)
16#define REG_RTC_EN_PWR_CYC_REQ (REG_RTC_BASE + 0xc8)
17#define REG_RTC_EN_WARM_RST_REQ (REG_RTC_BASE + 0xcc)
18#define REG_RTC_CTRL_UNLOCKKEY (REG_RTC_CTRL_BASE + 0x4)
19#define REG_RTC_CTRL (REG_RTC_CTRL_BASE + 0x8)
20
21#define CTRL_UNLOCKKEY_MAGIC 0xAB18
22
23/* REG_RTC_CTRL */
24#define BIT_REQ_SHDN BIT(0)
25#define BIT_REQ_PWR_CYC BIT(3)
26#define BIT_REQ_WARM_RST BIT(4)
27
28static struct {
29 void *pre_req_reg;
30 u32 req_bit;
31} reset_info[SYSRESET_COUNT] = {
32 [SYSRESET_WARM] = { REG_RTC_EN_WARM_RST_REQ, BIT_REQ_WARM_RST },
33 [SYSRESET_COLD] = { REG_RTC_EN_WARM_RST_REQ, BIT_REQ_WARM_RST },
34 [SYSRESET_POWER] = { REG_RTC_EN_PWR_CYC_REQ, BIT_REQ_PWR_CYC },
35 [SYSRESET_POWER_OFF] = { REG_RTC_EN_SHDN_REQ, BIT_REQ_SHDN },
36};
37
38static int cv1800b_sysreset_request(struct udevice *dev, enum sysreset_t type)
39{
40 u32 reg;
41
42 writel(1, reset_info[type].pre_req_reg);
43 writel(CTRL_UNLOCKKEY_MAGIC, REG_RTC_CTRL_UNLOCKKEY);
44 reg = readl(REG_RTC_CTRL);
45 writel(0xFFFF0800 | reset_info[type].req_bit, REG_RTC_CTRL);
46
47 return -EINPROGRESS;
48}
49
50static struct sysreset_ops cv1800b_sysreset = {
51 .request = cv1800b_sysreset_request,
52};
53
54static const struct udevice_id cv1800b_sysreset_ids[] = {
55 { .compatible = "sophgo,cv1800b-sysreset", },
56 {},
57};
58
59U_BOOT_DRIVER(sysreset_cv1800b) = {
60 .name = "cv1800b_sysreset",
61 .id = UCLASS_SYSRESET,
62 .ops = &cv1800b_sysreset,
63 .of_match = cv1800b_sysreset_ids
64};