1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_s32_mc_rgm
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/init.h>
11 
12 /* Destructive Event Status Register */
13 #define MC_RGM_DES                      0x0
14 #define MC_RGM_DES_F_POR_MASK           BIT(0)
15 #define MC_RGM_DES_F_POR(v)             FIELD_PREP(MC_RGM_DES_F_POR_MASK, (v))
16 /* Functional / External Reset Status Register */
17 #define MC_RGM_FES                      0x8
18 #define MC_RGM_FES_F_EXR_MASK           BIT(0)
19 #define MC_RGM_FES_F_EXR(v)             FIELD_PREP(MC_RGM_FES_F_EXR_MASK, (v))
20 /* Functional Event Reset Disable Register */
21 #define MC_RGM_FERD                     0xc
22 /* Functional Bidirectional Reset Enable Register */
23 #define MC_RGM_FBRE                     0x10
24 /* Functional Reset Escalation Counter Register */
25 #define MC_RGM_FREC                     0x14
26 #define MC_RGM_FREC_FREC_MASK           GENMASK(3, 0)
27 #define MC_RGM_FREC_FREC(v)             FIELD_PREP(MC_RGM_FREC_FREC_MASK, (v))
28 /* Functional Reset Escalation Threshold Register */
29 #define MC_RGM_FRET                     0x18
30 #define MC_RGM_FRET_FRET_MASK           GENMASK(3, 0)
31 #define MC_RGM_FRET_FRET(v)             FIELD_PREP(MC_RGM_FRET_FRET_MASK, (v))
32 /* Destructive Reset Escalation Threshold Register */
33 #define MC_RGM_DRET                     0x1c
34 #define MC_RGM_DRET_DRET_MASK           GENMASK(3, 0)
35 #define MC_RGM_DRET_DRET(v)             FIELD_PREP(MC_RGM_DRET_DRET_MASK, (v))
36 /* External Reset Control Register */
37 #define MC_RGM_ERCTRL                   0x20
38 #define MC_RGM_ERCTRL_ERASSERT_MASK     BIT(0)
39 #define MC_RGM_ERCTRL_ERASSERT(v)       FIELD_PREP(MC_RGM_ERCTRL_ERASSERT_MASK, (v))
40 /* Reset During Standby Status Register */
41 #define MC_RGM_RDSS                     0x24
42 #define MC_RGM_RDSS_DES_RES_MASK        BIT(0)
43 #define MC_RGM_RDSS_DES_RES(v)          FIELD_PREP(MC_RGM_RDSS_DES_RES_MASK, (v))
44 #define MC_RGM_RDSS_FES_RES_MASK        BIT(1)
45 #define MC_RGM_RDSS_FES_RES(v)          FIELD_PREP(MC_RGM_RDSS_FES_RES_MASK, (v))
46 /* Functional Reset Entry Timeout Control Register */
47 #define MC_RGM_FRENTC                   0x28
48 #define MC_RGM_FRENTC_FRET_EN_MASK      BIT(0)
49 #define MC_RGM_FRENTC_FRET_EN(v)        FIELD_PREP(MC_RGM_FRENTC_FRET_EN_MASK, (v))
50 #define MC_RGM_FRENTC_FRET_TIMEOUT_MASK GENMASK(31, 1)
51 #define MC_RGM_FRENTC_FRET_TIMEOUT(v)   FIELD_PREP(MC_RGM_FRENTC_FRET_TIMEOUT_MASK, (v))
52 /* Low Power Debug Control Register */
53 #define MC_RGM_LPDEBUG                  0x2c
54 #define MC_RGM_LPDEBUG_LP_DBG_EN_MASK   BIT(0)
55 #define MC_RGM_LPDEBUG_LP_DBG_EN(v)     FIELD_PREP(MC_RGM_LPDEBUG_LP_DBG_EN_MASK, (v))
56 
57 #define MC_RGM_TIMEOUT_US 50000U
58 
59 /* Handy accessors */
60 #define REG_READ(r)     sys_read32((mem_addr_t)(DT_INST_REG_ADDR(0) + (r)))
61 #define REG_WRITE(r, v) sys_write32((v), (mem_addr_t)(DT_INST_REG_ADDR(0) + (r)))
62 
mc_rgm_clear_reset_status(uint32_t reg)63 static int mc_rgm_clear_reset_status(uint32_t reg)
64 {
65 	bool timeout;
66 
67 	/*
68 	 * Register bits are cleared on write 1 if the triggering event has already
69 	 * been cleared at the source
70 	 */
71 	timeout = !WAIT_FOR(REG_READ(reg) == 0U, MC_RGM_TIMEOUT_US, REG_WRITE(reg, 0xffffffff));
72 	return timeout ? -ETIMEDOUT : 0U;
73 }
74 
mc_rgm_init(const struct device * dev)75 static int mc_rgm_init(const struct device *dev)
76 {
77 	int err = 0;
78 	uint32_t rst_status;
79 
80 	ARG_UNUSED(dev);
81 
82 	/*
83 	 * MC_RGM_FES must be cleared before writing 1 to any of the fields in MC_RGM_FERD,
84 	 * otherwise an interrupt request may occur
85 	 */
86 	rst_status = REG_READ(MC_RGM_FES);
87 	if (rst_status != 0U) {
88 		err = mc_rgm_clear_reset_status(MC_RGM_FES);
89 		if (err) {
90 			return err;
91 		}
92 	}
93 
94 	/* All functional reset sources generate a reset event */
95 	REG_WRITE(MC_RGM_FERD, 0U);
96 
97 	rst_status = REG_READ(MC_RGM_DES);
98 	if ((DT_INST_PROP(0, func_reset_threshold) != 0U) && (rst_status != 0U)) {
99 		/* MC_RGM_FRET value is reset on power-on and any destructive reset */
100 		REG_WRITE(MC_RGM_FRET, MC_RGM_FRET_FRET(DT_INST_PROP(0, func_reset_threshold)));
101 	} else {
102 		REG_WRITE(MC_RGM_FRET, MC_RGM_FRET_FRET(0U));
103 	}
104 
105 	if ((DT_INST_PROP(0, dest_reset_threshold) != 0U) &&
106 	    (FIELD_GET(MC_RGM_DES_F_POR_MASK, rst_status) != 0U)) {
107 		/* MC_RGM_DRET value is reset only on power-on reset */
108 		REG_WRITE(MC_RGM_DRET, MC_RGM_DRET_DRET(DT_INST_PROP(0, dest_reset_threshold)));
109 	} else {
110 		REG_WRITE(MC_RGM_DRET, MC_RGM_DRET_DRET(0U));
111 	}
112 
113 	/* Clear destructive reset status to avoid persisting it across resets */
114 	err = mc_rgm_clear_reset_status(MC_RGM_DES);
115 	if (err) {
116 		return err;
117 	}
118 
119 	return err;
120 }
121 
122 DEVICE_DT_INST_DEFINE(0, mc_rgm_init, NULL, NULL, 0, PRE_KERNEL_1, 1, NULL);
123