1 /*
2 * Copyright (c) 2022 Andes Technology Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/device.h>
8 #include <zephyr/drivers/hwinfo.h>
9 #include <zephyr/drivers/syscon.h>
10 #include <string.h>
11 #include <zephyr/sys/byteorder.h>
12
13 /*
14 * SMU(System Management Unit) Registers for hwinfo driver
15 */
16
17 /* Register offset*/
18 #define SMU_SYSTEMVER 0x00
19 #define SMU_WRSR 0x10
20
21 /* Wake-Up and Reset Status Register bitmask */
22 #define SMU_WRSR_APOR BIT(0)
23 #define SMU_WRSR_MPOR BIT(1)
24 #define SMU_WRSR_HW BIT(2)
25 #define SMU_WRSR_WDT BIT(3)
26 #define SMU_WRSR_SW BIT(4)
27
28 #define ANDES_RESET_STATUS_MASK BIT_MASK(5)
29
30 static const struct device *const syscon_dev =
31 DEVICE_DT_GET(DT_NODELABEL(syscon));
32
z_impl_hwinfo_get_device_id(uint8_t * buffer,size_t length)33 ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length)
34 {
35 int ret = 0;
36 uint8_t id[3];
37 uint32_t ver;
38
39 if (!device_is_ready(syscon_dev)) {
40 return -ENODEV;
41 }
42
43 ret = syscon_read_reg(syscon_dev, SMU_SYSTEMVER, &ver);
44 if (ret < 0) {
45 return ret;
46 }
47
48 if (length > sizeof(id)) {
49 length = sizeof(id);
50 }
51
52 sys_put_le24(ver, id);
53
54 memcpy(buffer, id, length);
55
56 return length;
57 }
58
z_impl_hwinfo_get_reset_cause(uint32_t * cause)59 int z_impl_hwinfo_get_reset_cause(uint32_t *cause)
60 {
61 int ret = 0;
62 uint32_t reason, flags = 0;
63
64 if (!device_is_ready(syscon_dev)) {
65 return -ENODEV;
66 }
67
68 ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason);
69 if (ret < 0) {
70 return ret;
71 }
72
73 if (reason & SMU_WRSR_APOR) {
74 flags |= RESET_POR;
75 }
76 if (reason & SMU_WRSR_MPOR) {
77 flags |= RESET_POR;
78 }
79 if (reason & SMU_WRSR_HW) {
80 flags |= RESET_PIN;
81 }
82 if (reason & SMU_WRSR_WDT) {
83 flags |= RESET_WATCHDOG;
84 }
85 if (reason & SMU_WRSR_SW) {
86 flags |= RESET_SOFTWARE;
87 }
88
89 *cause = flags;
90
91 return 0;
92 }
93
z_impl_hwinfo_clear_reset_cause(void)94 int z_impl_hwinfo_clear_reset_cause(void)
95 {
96 int ret = 0;
97 uint32_t reason;
98
99 if (!device_is_ready(syscon_dev)) {
100 return -ENODEV;
101 }
102
103 ret = syscon_write_reg(syscon_dev, SMU_WRSR, ANDES_RESET_STATUS_MASK);
104 if (ret < 0) {
105 return ret;
106 }
107
108 do {
109 ret = syscon_read_reg(syscon_dev, SMU_WRSR, &reason);
110 } while ((reason & ANDES_RESET_STATUS_MASK) && (!ret));
111
112 return ret;
113 }
114
z_impl_hwinfo_get_supported_reset_cause(uint32_t * supported)115 int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported)
116 {
117 *supported = (RESET_PIN
118 | RESET_WATCHDOG
119 | RESET_SOFTWARE
120 | RESET_POR);
121
122 return 0;
123 }
124