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_dvfs.h>
10 
11 typedef struct {
12 	nrfs_dvfs_evt_handler_t handler;
13 	bool is_initialized;
14 } nrfs_dvfs_cb_t;
15 static nrfs_dvfs_cb_t m_cb;
16 
nrfs_dvfs_service_notify(void * p_notification,size_t size)17 void nrfs_dvfs_service_notify(void *p_notification, size_t size)
18 {
19 	if (!m_cb.handler || !m_cb.is_initialized) {
20 		return;
21 	}
22 
23 	nrfs_dvfs_evt_t evt;
24 	nrfs_generic_t *p_data = (nrfs_generic_t *)p_notification;
25 	if (NRFS_HDR_FILTER_ERR_GET(&p_data->hdr)) {
26 		evt.type = NRFS_DVFS_EVT_REJECT;
27 		m_cb.handler(&evt, (void *)p_data->ctx.ctx);
28 		return;
29 	}
30 
31 	nrfs_dvfs_rsp_t *p_rsp = (nrfs_dvfs_rsp_t *)p_notification;
32 	evt.freq	       = p_rsp->data.freq;
33 	switch (p_data->hdr.req) {
34 	case NRFS_DVFS_REQ_INIT_PREPARE:
35 		evt.type = NRFS_DVFS_EVT_INIT_PREPARATION;
36 		m_cb.handler(&evt, (void *)p_rsp->ctx.ctx);
37 		break;
38 
39 	case NRFS_DVFS_REQ_INIT_COMPLETE:
40 		evt.type = NRFS_DVFS_EVT_INIT_DONE;
41 		m_cb.handler(&evt, (void *)p_rsp->ctx.ctx);
42 		break;
43 
44 	case NRFS_DVFS_REQ_OPPOINT:
45 		if (p_rsp->data.scaling_prepare == true) {
46 			evt.type = NRFS_DVFS_EVT_OPPOINT_SCALING_PREPARE;
47 		} else {
48 			evt.type = NRFS_DVFS_EVT_OPPOINT_REQ_CONFIRMED;
49 		}
50 		m_cb.handler(&evt, (void *)p_rsp->ctx.ctx);
51 		break;
52 
53 	case NRFS_DVFS_REQ_READY_TO_SCALE:
54 		evt.type = NRFS_DVFS_EVT_OPPOINT_SCALING_DONE;
55 		m_cb.handler(&evt, (void *)p_rsp->ctx.ctx);
56 		break;
57 
58 	default:
59 		break;
60 	}
61 }
62 
nrfs_dvfs_init(nrfs_dvfs_evt_handler_t handler)63 nrfs_err_t nrfs_dvfs_init(nrfs_dvfs_evt_handler_t handler)
64 {
65 	if (m_cb.is_initialized) {
66 		return NRFS_ERR_INVALID_STATE;
67 	}
68 
69 	m_cb.handler	    = handler;
70 	m_cb.is_initialized = true;
71 	return NRFS_SUCCESS;
72 }
73 
nrfs_dvfs_uninit(void)74 void nrfs_dvfs_uninit(void)
75 {
76 	m_cb.is_initialized = false;
77 }
78 
nrfs_dvfs_init_prepare_request(void * p_context)79 nrfs_err_t nrfs_dvfs_init_prepare_request(void *p_context)
80 {
81 	if (!m_cb.is_initialized) {
82 		return NRFS_ERR_INVALID_STATE;
83 	}
84 
85 	nrfs_dvfs_req_t req;
86 
87 	NRFS_SERVICE_HDR_FILL(&req, NRFS_DVFS_REQ_INIT_PREPARE);
88 	req.ctx.ctx = (uint32_t)p_context;
89 
90 	return nrfs_backend_send(&req, sizeof(req));
91 }
92 
nrfs_dvfs_init_complete_request(void * p_context)93 nrfs_err_t nrfs_dvfs_init_complete_request(void *p_context)
94 {
95 	if (!m_cb.is_initialized) {
96 		return NRFS_ERR_INVALID_STATE;
97 	}
98 
99 	nrfs_dvfs_req_t req;
100 
101 	NRFS_SERVICE_HDR_FILL(&req, NRFS_DVFS_REQ_INIT_COMPLETE);
102 	req.ctx.ctx = (uint32_t)p_context;
103 
104 	return nrfs_backend_send(&req, sizeof(req));
105 }
106 
nrfs_dvfs_oppoint_request(enum dvfs_frequency_setting target_freq,void * p_context)107 nrfs_err_t nrfs_dvfs_oppoint_request(enum dvfs_frequency_setting target_freq, void *p_context)
108 {
109 	if (!m_cb.is_initialized) {
110 		return NRFS_ERR_INVALID_STATE;
111 	}
112 
113 	nrfs_dvfs_opp_req_t req;
114 
115 	NRFS_SERVICE_HDR_FILL(&req, NRFS_DVFS_REQ_OPPOINT);
116 	req.ctx.ctx	     = (uint32_t)p_context;
117 	req.data.target_freq = target_freq;
118 
119 	return nrfs_backend_send(&req, sizeof(req));
120 }
121 
nrfs_dvfs_oppoint_request_no_rsp(enum dvfs_frequency_setting target_freq,void * p_context)122 nrfs_err_t nrfs_dvfs_oppoint_request_no_rsp(enum dvfs_frequency_setting target_freq,
123 					    void *p_context)
124 {
125 	if (!m_cb.is_initialized) {
126 		return NRFS_ERR_INVALID_STATE;
127 	}
128 
129 	nrfs_dvfs_opp_req_t req;
130 
131 	NRFS_SERVICE_HDR_FILL(&req, NRFS_DVFS_REQ_OPPOINT);
132 	NRFS_HDR_NO_RSP_SET(&req.hdr);
133 	req.ctx.ctx	     = (uint32_t)p_context;
134 	req.data.target_freq = target_freq;
135 
136 	return nrfs_backend_send(&req, sizeof(req));
137 }
138 
nrfs_dvfs_ready_to_scale(void * p_context)139 nrfs_err_t nrfs_dvfs_ready_to_scale(void *p_context)
140 {
141 	if (!m_cb.is_initialized) {
142 		return NRFS_ERR_INVALID_STATE;
143 	}
144 
145 	nrfs_dvfs_req_t req;
146 
147 	NRFS_SERVICE_HDR_FILL(&req, NRFS_DVFS_REQ_READY_TO_SCALE);
148 	req.ctx.ctx = (uint32_t)p_context;
149 
150 	return nrfs_backend_send(&req, sizeof(req));
151 }
152