1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT nxp_s32k3_pmc
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/init.h>
11 
12 /* Low Voltage Status and Control Register */
13 #define PMC_LVSC                 0x0
14 #define PMC_LVSC_HVDAF_MASK      BIT(0)
15 #define PMC_LVSC_HVDAF(v)        FIELD_PREP(PMC_LVSC_HVDAF_MASK, (v))
16 #define PMC_LVSC_HVDBF_MASK      BIT(1)
17 #define PMC_LVSC_HVDBF(v)        FIELD_PREP(PMC_LVSC_HVDBF_MASK, (v))
18 #define PMC_LVSC_HVD25F_MASK     BIT(2)
19 #define PMC_LVSC_HVD25F(v)       FIELD_PREP(PMC_LVSC_HVD25F_MASK, (v))
20 #define PMC_LVSC_HVD11F_MASK     BIT(3)
21 #define PMC_LVSC_HVD11F(v)       FIELD_PREP(PMC_LVSC_HVD11F_MASK, (v))
22 #define PMC_LVSC_LVD5AF_MASK     BIT(4)
23 #define PMC_LVSC_LVD5AF(v)       FIELD_PREP(PMC_LVSC_LVD5AF_MASK, (v))
24 #define PMC_LVSC_LVD15F_MASK     BIT(5)
25 #define PMC_LVSC_LVD15F(v)       FIELD_PREP(PMC_LVSC_LVD15F_MASK, (v))
26 #define PMC_LVSC_HVDAS_MASK      BIT(8)
27 #define PMC_LVSC_HVDAS(v)        FIELD_PREP(PMC_LVSC_HVDAS_MASK, (v))
28 #define PMC_LVSC_HVDBS_MASK      BIT(9)
29 #define PMC_LVSC_HVDBS(v)        FIELD_PREP(PMC_LVSC_HVDBS_MASK, (v))
30 #define PMC_LVSC_HVD25S_MASK     BIT(10)
31 #define PMC_LVSC_HVD25S(v)       FIELD_PREP(PMC_LVSC_HVD25S_MASK, (v))
32 #define PMC_LVSC_HVD11S_MASK     BIT(11)
33 #define PMC_LVSC_HVD11S(v)       FIELD_PREP(PMC_LVSC_HVD11S_MASK, (v))
34 #define PMC_LVSC_LVD5AS_MASK     BIT(12)
35 #define PMC_LVSC_LVD5AS(v)       FIELD_PREP(PMC_LVSC_LVD5AS_MASK, (v))
36 #define PMC_LVSC_LVD15S_MASK     BIT(13)
37 #define PMC_LVSC_LVD15S(v)       FIELD_PREP(PMC_LVSC_LVD15S_MASK, (v))
38 #define PMC_LVSC_LVRAF_MASK      BIT(16)
39 #define PMC_LVSC_LVRAF(v)        FIELD_PREP(PMC_LVSC_LVRAF_MASK, (v))
40 #define PMC_LVSC_LVRALPF_MASK    BIT(17)
41 #define PMC_LVSC_LVRALPF(v)      FIELD_PREP(PMC_LVSC_LVRALPF_MASK, (v))
42 #define PMC_LVSC_LVRBF_MASK      BIT(18)
43 #define PMC_LVSC_LVRBF(v)        FIELD_PREP(PMC_LVSC_LVRBF_MASK, (v))
44 #define PMC_LVSC_LVRBLPF_MASK    BIT(19)
45 #define PMC_LVSC_LVRBLPF(v)      FIELD_PREP(PMC_LVSC_LVRBLPF_MASK, (v))
46 #define PMC_LVSC_LVR25F_MASK     BIT(20)
47 #define PMC_LVSC_LVR25F(v)       FIELD_PREP(PMC_LVSC_LVR25F_MASK, (v))
48 #define PMC_LVSC_LVR25LPF_MASK   BIT(21)
49 #define PMC_LVSC_LVR25LPF(v)     FIELD_PREP(PMC_LVSC_LVR25LPF_MASK, (v))
50 #define PMC_LVSC_LVR11F_MASK     BIT(22)
51 #define PMC_LVSC_LVR11F(v)       FIELD_PREP(PMC_LVSC_LVR11F_MASK, (v))
52 #define PMC_LVSC_LVR11LPF_MASK   BIT(23)
53 #define PMC_LVSC_LVR11LPF(v)     FIELD_PREP(PMC_LVSC_LVR11LPF_MASK, (v))
54 #define PMC_LVSC_GNG25OSCF_MASK  BIT(24)
55 #define PMC_LVSC_GNG25OSCF(v)    FIELD_PREP(PMC_LVSC_GNG25OSCF_MASK, (v))
56 #define PMC_LVSC_GNG11OSCF_MASK  BIT(25)
57 #define PMC_LVSC_GNG11OSCF(v)    FIELD_PREP(PMC_LVSC_GNG11OSCF_MASK, (v))
58 #define PMC_LVSC_PORF_MASK       BIT(31)
59 #define PMC_LVSC_PORF(v)         FIELD_PREP(PMC_LVSC_PORF_MASK, (v))
60 /* PMC Configuration Register */
61 #define PMC_CONFIG               0x4
62 #define PMC_CONFIG_LMEN_MASK     BIT(0)
63 #define PMC_CONFIG_LMEN(v)       FIELD_PREP(PMC_CONFIG_LMEN_MASK, (v))
64 #define PMC_CONFIG_LMBCTLEN_MASK BIT(1)
65 #define PMC_CONFIG_LMBCTLEN(v)   FIELD_PREP(PMC_CONFIG_LMBCTLEN_MASK, (v))
66 #define PMC_CONFIG_FASTREC_MASK  BIT(2)
67 #define PMC_CONFIG_FASTREC(v)    FIELD_PREP(PMC_CONFIG_FASTREC_MASK, (v))
68 #define PMC_CONFIG_LPM25EN_MASK  BIT(3)
69 #define PMC_CONFIG_LPM25EN(v)    FIELD_PREP(PMC_CONFIG_LPM25EN_MASK, (v))
70 #define PMC_CONFIG_LVRBLPEN_MASK BIT(4)
71 #define PMC_CONFIG_LVRBLPEN(v)   FIELD_PREP(PMC_CONFIG_LVRBLPEN_MASK, (v))
72 #define PMC_CONFIG_HVDIE_MASK    BIT(8)
73 #define PMC_CONFIG_HVDIE(v)      FIELD_PREP(PMC_CONFIG_HVDIE_MASK, (v))
74 #define PMC_CONFIG_LVDIE_MASK    BIT(9)
75 #define PMC_CONFIG_LVDIE(v)      FIELD_PREP(PMC_CONFIG_LVDIE_MASK, (v))
76 #define PMC_CONFIG_LMAUTOEN_MASK BIT(16)
77 #define PMC_CONFIG_LMAUTOEN(v)   FIELD_PREP(PMC_CONFIG_LMAUTOEN_MASK, (v))
78 #define PMC_CONFIG_LMSTAT_MASK   BIT(17)
79 #define PMC_CONFIG_LMSTAT(v)     FIELD_PREP(PMC_CONFIG_LMSTAT_MASK, (v))
80 /* Version ID register */
81 #define PMC_VERID                0xc
82 #define PMC_VERID_LMFEAT_MASK    BIT(0)
83 #define PMC_VERID_LMFEAT(v)      FIELD_PREP(PMC_VERID_LMFEAT_MASK, (v))
84 #define PMC_VERID_MINOR_MASK     GENMASK(23, 16)
85 #define PMC_VERID_MINOR(v)       FIELD_PREP(PMC_VERID_MINOR_MASK, (v))
86 #define PMC_VERID_MAJOR_MASK     GENMASK(31, 24)
87 #define PMC_VERID_MAJOR(v)       FIELD_PREP(PMC_VERID_MAJOR_MASK, (v))
88 
89 /* Handy accessors */
90 #define REG_READ(r)     sys_read32((mem_addr_t)(DT_INST_REG_ADDR(0) + (r)))
91 #define REG_WRITE(r, v) sys_write32((v), (mem_addr_t)(DT_INST_REG_ADDR(0) + (r)))
92 
93 #define PMC_TIMEOUT_US 10000U
94 
pmc_init(const struct device * dev)95 static int pmc_init(const struct device *dev)
96 {
97 	uint32_t reg_val;
98 
99 	ARG_UNUSED(dev);
100 
101 	/* Clear Low Voltage Status flags after initial power ramp-up */
102 	REG_WRITE(PMC_LVSC, 0xffffffffU);
103 
104 	/* Last Mile regulator initialization */
105 	reg_val = PMC_CONFIG_LMEN(DT_INST_PROP(0, lm_reg)) |
106 		  PMC_CONFIG_LMAUTOEN(DT_INST_PROP(0, lm_reg_auto)) |
107 		  PMC_CONFIG_LMBCTLEN(DT_INST_PROP(0, lm_reg_base_control));
108 
109 	if (DT_INST_PROP(0, lm_reg)) {
110 		REG_WRITE(PMC_CONFIG, reg_val & ~PMC_CONFIG_LMEN_MASK);
111 		/*
112 		 * If external BJT is using on the PCB board, wait for the LVD15 to go above
113 		 * low-voltage detect threshold before enabling LMEN
114 		 */
115 		if (DT_INST_PROP(0, lm_reg_base_control)) {
116 			if (!WAIT_FOR(FIELD_GET(PMC_LVSC_LVD15S_MASK, REG_READ(PMC_LVSC)) == 0U,
117 				      PMC_TIMEOUT_US, k_busy_wait(10U))) {
118 				return -ETIMEDOUT;
119 			}
120 		}
121 		REG_WRITE(PMC_CONFIG, REG_READ(PMC_CONFIG) | PMC_CONFIG_LMEN(1U));
122 	} else {
123 		REG_WRITE(PMC_CONFIG, reg_val);
124 		if (DT_INST_PROP(0, lm_reg_auto)) {
125 			/* Wait for Last Mile regulator to be turned on */
126 			if (!WAIT_FOR(FIELD_GET(PMC_CONFIG_LMSTAT_MASK, REG_READ(PMC_CONFIG)) == 1U,
127 				      PMC_TIMEOUT_US, k_busy_wait(10U))) {
128 				return -ETIMEDOUT;
129 			}
130 		}
131 	}
132 
133 	return 0;
134 }
135 
136 DEVICE_DT_INST_DEFINE(0, pmc_init, NULL, NULL, 0, PRE_KERNEL_1, 1, NULL);
137