1 /*
2  * Copyright (c) 2024 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <internal/nrfs_backend.h>
8 #include <internal/nrfs_callbacks.h>
9 #include <nrfs_pmic.h>
10 
11 typedef struct {
12 	nrfs_pmic_evt_handler_t handler;
13 	bool is_initialized;
14 } nrfs_pmic_cb_t;
15 static nrfs_pmic_cb_t m_cb;
16 
nrfs_pmic_init(nrfs_pmic_evt_handler_t handler)17 nrfs_err_t nrfs_pmic_init(nrfs_pmic_evt_handler_t handler)
18 {
19 	if (m_cb.is_initialized) {
20 		return NRFS_ERR_INVALID_STATE;
21 	}
22 
23 	m_cb.handler	    = handler;
24 	m_cb.is_initialized = true;
25 	return NRFS_SUCCESS;
26 }
27 
nrfs_pmic_uninit(void)28 void nrfs_pmic_uninit(void)
29 {
30 	m_cb.is_initialized = false;
31 }
32 
nrfs_pmic_rffe_on(void * p_context)33 nrfs_err_t nrfs_pmic_rffe_on(void *p_context)
34 {
35 	if (!m_cb.is_initialized) {
36 		return NRFS_ERR_INVALID_STATE;
37 	}
38 
39 	nrfs_pmic_rffe_on_req_t req;
40 
41 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_RFFE_ON);
42 	req.ctx.ctx = (uint32_t)p_context;
43 
44 	return nrfs_backend_send(&req, sizeof(req));
45 }
46 
nrfs_pmic_rffe_on_no_rsp(void)47 nrfs_err_t nrfs_pmic_rffe_on_no_rsp(void)
48 {
49 	if (!m_cb.is_initialized) {
50 		return NRFS_ERR_INVALID_STATE;
51 	}
52 
53 	nrfs_pmic_rffe_on_req_t req;
54 
55 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_RFFE_ON);
56 	NRFS_HDR_NO_RSP_SET(&req.hdr);
57 
58 	return nrfs_backend_send(&req, sizeof(req));
59 }
60 
nrfs_pmic_rffe_off(void * p_context)61 nrfs_err_t nrfs_pmic_rffe_off(void *p_context)
62 {
63 	if (!m_cb.is_initialized) {
64 		return NRFS_ERR_INVALID_STATE;
65 	}
66 
67 	nrfs_pmic_rffe_off_req_t req;
68 
69 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_RFFE_OFF);
70 	req.ctx.ctx = (uint32_t)p_context;
71 
72 	return nrfs_backend_send(&req, sizeof(req));
73 }
74 
nrfs_pmic_rffe_off_no_rsp(void)75 nrfs_err_t nrfs_pmic_rffe_off_no_rsp(void)
76 {
77 	if (!m_cb.is_initialized) {
78 		return NRFS_ERR_INVALID_STATE;
79 	}
80 
81 	nrfs_pmic_rffe_off_req_t req;
82 
83 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_RFFE_OFF);
84 	NRFS_HDR_NO_RSP_SET(&req.hdr);
85 
86 	return nrfs_backend_send(&req, sizeof(req));
87 }
88 
nrfs_pmic_sim_on(pmic_sim_t sim,void * p_context)89 nrfs_err_t nrfs_pmic_sim_on(pmic_sim_t sim, void *p_context)
90 {
91 	if (!m_cb.is_initialized) {
92 		return NRFS_ERR_INVALID_STATE;
93 	}
94 
95 	nrfs_pmic_sim_on_req_t req;
96 
97 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_SIM_ON);
98 	req.ctx.ctx = (uint32_t)p_context;
99 	req.sim	    = sim;
100 
101 	return nrfs_backend_send(&req, sizeof(req));
102 }
103 
nrfs_pmic_sim_on_no_rsp(pmic_sim_t sim)104 nrfs_err_t nrfs_pmic_sim_on_no_rsp(pmic_sim_t sim)
105 {
106 	if (!m_cb.is_initialized) {
107 		return NRFS_ERR_INVALID_STATE;
108 	}
109 
110 	nrfs_pmic_sim_on_req_t req;
111 
112 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_SIM_ON);
113 	NRFS_HDR_NO_RSP_SET(&req.hdr);
114 	req.sim = sim;
115 
116 	return nrfs_backend_send(&req, sizeof(req));
117 }
118 
nrfs_pmic_sim_off(pmic_sim_t sim,void * p_context)119 nrfs_err_t nrfs_pmic_sim_off(pmic_sim_t sim, void *p_context)
120 {
121 	if (!m_cb.is_initialized) {
122 		return NRFS_ERR_INVALID_STATE;
123 	}
124 
125 	nrfs_pmic_sim_off_req_t req;
126 
127 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_SIM_OFF);
128 	req.ctx.ctx = (uint32_t)p_context;
129 	req.sim	    = sim;
130 
131 	return nrfs_backend_send(&req, sizeof(req));
132 }
133 
nrfs_pmic_sim_off_no_rsp(pmic_sim_t sim)134 nrfs_err_t nrfs_pmic_sim_off_no_rsp(pmic_sim_t sim)
135 {
136 	if (!m_cb.is_initialized) {
137 		return NRFS_ERR_INVALID_STATE;
138 	}
139 
140 	nrfs_pmic_sim_off_req_t req;
141 
142 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_SIM_OFF);
143 	NRFS_HDR_NO_RSP_SET(&req.hdr);
144 	req.sim = sim;
145 
146 	return nrfs_backend_send(&req, sizeof(req));
147 }
148 
nrfs_pmic_ble_radio_on(pmic_ble_radio_txpower_t txpower,void * p_context)149 nrfs_err_t nrfs_pmic_ble_radio_on(pmic_ble_radio_txpower_t txpower, void *p_context)
150 {
151 	if (!m_cb.is_initialized) {
152 		return NRFS_ERR_INVALID_STATE;
153 	}
154 
155 	nrfs_pmic_ble_radio_on_req_t req;
156 
157 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_BLE_RADIO_ON);
158 	req.ctx.ctx = (uint32_t)p_context;
159 	req.txpower = txpower;
160 
161 	return nrfs_backend_send(&req, sizeof(req));
162 }
163 
nrfs_pmic_ble_radio_on_no_rsp(pmic_ble_radio_txpower_t txpower)164 nrfs_err_t nrfs_pmic_ble_radio_on_no_rsp(pmic_ble_radio_txpower_t txpower)
165 {
166 	if (!m_cb.is_initialized) {
167 		return NRFS_ERR_INVALID_STATE;
168 	}
169 
170 	nrfs_pmic_ble_radio_on_req_t req;
171 
172 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_BLE_RADIO_ON);
173 	NRFS_HDR_NO_RSP_SET(&req.hdr);
174 	req.txpower = txpower;
175 
176 	return nrfs_backend_send(&req, sizeof(req));
177 }
178 
nrfs_pmic_ble_radio_off(void * p_context)179 nrfs_err_t nrfs_pmic_ble_radio_off(void *p_context)
180 {
181 	if (!m_cb.is_initialized) {
182 		return NRFS_ERR_INVALID_STATE;
183 	}
184 
185 	nrfs_pmic_ble_radio_off_req_t req;
186 
187 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_BLE_RADIO_OFF);
188 	req.ctx.ctx = (uint32_t)p_context;
189 
190 	return nrfs_backend_send(&req, sizeof(req));
191 }
192 
nrfs_pmic_ble_radio_off_no_rsp(void)193 nrfs_err_t nrfs_pmic_ble_radio_off_no_rsp(void)
194 {
195 	if (!m_cb.is_initialized) {
196 		return NRFS_ERR_INVALID_STATE;
197 	}
198 
199 	nrfs_pmic_ble_radio_off_req_t req;
200 
201 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_BLE_RADIO_OFF);
202 	NRFS_HDR_NO_RSP_SET(&req.hdr);
203 
204 	return nrfs_backend_send(&req, sizeof(req));
205 }
206 
nrfs_pmic_pwm_default_set(void * p_context)207 nrfs_err_t nrfs_pmic_pwm_default_set(void *p_context)
208 {
209 	if (!m_cb.is_initialized) {
210 		return NRFS_ERR_INVALID_STATE;
211 	}
212 
213 	nrfs_pmic_pwm_default_req_t req;
214 
215 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_PWM_DEFAULT);
216 	req.ctx.ctx = (uint32_t)p_context;
217 
218 	return nrfs_backend_send(&req, sizeof(req));
219 }
220 
nrfs_pmic_pwm_default_set_no_rsp(void)221 nrfs_err_t nrfs_pmic_pwm_default_set_no_rsp(void)
222 {
223 	if (!m_cb.is_initialized) {
224 		return NRFS_ERR_INVALID_STATE;
225 	}
226 
227 	nrfs_pmic_pwm_default_req_t req;
228 
229 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_PWM_DEFAULT);
230 	NRFS_HDR_NO_RSP_SET(&req.hdr);
231 
232 	return nrfs_backend_send(&req, sizeof(req));
233 }
234 
nrfs_pmic_pwm_ghost_avoid_set(void * p_context)235 nrfs_err_t nrfs_pmic_pwm_ghost_avoid_set(void *p_context)
236 {
237 	if (!m_cb.is_initialized) {
238 		return NRFS_ERR_INVALID_STATE;
239 	}
240 
241 	nrfs_pmic_pwm_ghost_avoid_req_t req;
242 
243 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_PWM_GHOST_AVOID);
244 	req.ctx.ctx = (uint32_t)p_context;
245 
246 	return nrfs_backend_send(&req, sizeof(req));
247 }
248 
nrfs_pmic_pwm_ghost_avoid_set_no_rsp(void)249 nrfs_err_t nrfs_pmic_pwm_ghost_avoid_set_no_rsp(void)
250 {
251 	if (!m_cb.is_initialized) {
252 		return NRFS_ERR_INVALID_STATE;
253 	}
254 
255 	nrfs_pmic_pwm_ghost_avoid_req_t req;
256 
257 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_PWM_GHOST_AVOID);
258 	NRFS_HDR_NO_RSP_SET(&req.hdr);
259 
260 	return nrfs_backend_send(&req, sizeof(req));
261 }
262 
nrfs_pmic_test_if_read(uint16_t addr,void * p_context)263 nrfs_err_t nrfs_pmic_test_if_read(uint16_t addr, void *p_context)
264 {
265 	if (!m_cb.is_initialized) {
266 		return NRFS_ERR_INVALID_STATE;
267 	}
268 
269 	nrfs_pmic_test_if_req_t req;
270 
271 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_TEST_IF);
272 	req.ctx.ctx	    = (uint32_t)p_context;
273 	req.reg.access_type = PMIC_REG_READ;
274 	req.reg.addr	    = addr;
275 	req.reg.val	    = 0;
276 
277 	return nrfs_backend_send(&req, sizeof(req));
278 }
279 
nrfs_pmic_test_if_write(uint16_t addr,uint8_t val,void * p_context)280 nrfs_err_t nrfs_pmic_test_if_write(uint16_t addr, uint8_t val, void *p_context)
281 {
282 	if (!m_cb.is_initialized) {
283 		return NRFS_ERR_INVALID_STATE;
284 	}
285 
286 	nrfs_pmic_test_if_req_t req;
287 
288 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_TEST_IF);
289 	req.ctx.ctx	    = (uint32_t)p_context;
290 	req.reg.access_type = PMIC_REG_WRITE;
291 	req.reg.addr	    = addr;
292 	req.reg.val	    = val;
293 
294 	return nrfs_backend_send(&req, sizeof(req));
295 }
296 
nrfs_pmic_info_read(void * p_context)297 nrfs_err_t nrfs_pmic_info_read(void *p_context)
298 {
299 	if (!m_cb.is_initialized) {
300 		return NRFS_ERR_INVALID_STATE;
301 	}
302 
303 	nrfs_pmic_info_req_t req;
304 
305 	NRFS_SERVICE_HDR_FILL(&req, NRFS_PMIC_INFO);
306 	req.ctx.ctx = (uint32_t)p_context;
307 
308 	return nrfs_backend_send(&req, sizeof(req));
309 }
310 
nrfs_pmic_service_notify(void * p_notification,size_t size)311 void nrfs_pmic_service_notify(void *p_notification, size_t size)
312 {
313 	if (!m_cb.handler || !m_cb.is_initialized) {
314 		return;
315 	}
316 
317 	nrfs_pmic_evt_t evt;
318 	nrfs_generic_t *p_data = (nrfs_generic_t *)p_notification;
319 
320 	if (NRFS_HDR_FILTER_ERR_GET(&p_data->hdr)) {
321 		evt.type = NRFS_PMIC_EVT_REJECT;
322 		m_cb.handler(&evt, (void *)p_data->ctx.ctx);
323 		return;
324 	}
325 
326 	switch (p_data->hdr.req) {
327 	case NRFS_PMIC_RFFE_ON:
328 	case NRFS_PMIC_RFFE_OFF:
329 	case NRFS_PMIC_SIM_ON:
330 	case NRFS_PMIC_SIM_OFF:
331 	case NRFS_PMIC_BLE_RADIO_ON:
332 	case NRFS_PMIC_BLE_RADIO_OFF:
333 	case NRFS_PMIC_PWM_DEFAULT:
334 	case NRFS_PMIC_PWM_GHOST_AVOID:
335 		evt.type = NRFS_PMIC_EVT_APPLIED;
336 		m_cb.handler(&evt, (void *)p_data->ctx.ctx);
337 		break;
338 	case NRFS_PMIC_TEST_IF:
339 		nrfs_pmic_rsp_t *p_rsp = (nrfs_pmic_rsp_t *)p_notification;
340 
341 		evt.type	= NRFS_PMIC_EVT_TEST_IF_RSP;
342 		evt.val		= p_rsp->data.val;
343 		evt.access_type = p_rsp->data.access_type;
344 		m_cb.handler(&evt, (void *)p_rsp->ctx.ctx);
345 		break;
346 	case NRFS_PMIC_INFO:
347 		nrfs_pmic_info_rsp_t *p_rsp_info = (nrfs_pmic_info_rsp_t *)p_notification;
348 		nrfs_pmic_info_evt_t info_evt;
349 
350 		info_evt.type = NRFS_PMIC_EVT_INFO_RSP;
351 		info_evt.info = p_rsp_info->data;
352 		m_cb.handler(&info_evt, (void *)p_rsp_info->ctx.ctx);
353 		break;
354 	default:
355 		break;
356 	}
357 }
358