blob: bc95db06a906a4ead797aca38d55e8660e4c7acf [file] [log] [blame]
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -08001/* Copyright (c) 2015, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Fundation, Inc. nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 */
29
30#include <rpm-glink.h>
31#include <smd.h>
32#include <glink.h>
33#include <glink_rpm.h>
34#include <xport_rpm.h>
35#include <stdint.h>
36#include <sys/types.h>
37#include <arch/defines.h>
38#include <debug.h>
39#include <stdlib.h>
40#include <platform/timer.h>
41#include <platform/interrupts.h>
42#include <platform/clock.h>
43#include <platform/iomap.h>
44#include <platform/irqs.h>
45#include <pm8x41.h>
46#include <kernel/event.h>
47
48#define RPM_REQ_MAGIC 0x00716572
49#define RPM_CMD_MAGIC 0x00646d63
50#define REQ_MSG_LENGTH 0x14
51#define CMD_MSG_LENGTH 0x08
52#define ACK_MSG_LENGTH 0x0C
53
54glink_handle_type rpm_glink_port, ssr_glink_port;
55static uint32_t msg_id;
Sridhar Parasurambd9c5182015-05-22 17:06:40 -070056static event_t wait_for_rpm_init;
57static event_t wait_for_ssr_init;
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -080058static event_t wait_for_data;
59
60extern glink_err_type glink_wait_link_down(glink_handle_type handle);
61
62glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type)
63{
64 rpm_req req;
65 rpm_cmd cmd;
66 glink_err_type send_err = 0;
67 uint32_t len_to_rpm = 0;
68 void *rpm_data = NULL;
69 event_init(&wait_for_data, false, EVENT_FLAG_AUTOUNSIGNAL);
70
71 switch(type)
72 {
73 case RPM_REQUEST_TYPE:
74 req.hdr.type = RPM_REQ_MAGIC;
75 req.hdr.len = len + REQ_MSG_LENGTH;//20
76 req.req_hdr.id = ++msg_id;
77 req.req_hdr.set = 0;
78 req.req_hdr.resourceType = data[RESOURCETYPE];
79 req.req_hdr.resourceId = data[RESOURCEID];
80 req.req_hdr.dataLength = len;
81
82 fill_kvp_object(&req.data, data, len);
83 len_to_rpm = req.req_hdr.dataLength + 0x28;
84
85 rpm_data = (void*) malloc(len_to_rpm);
86 ASSERT(rpm_data);
87 memset(rpm_data, 0, len_to_rpm);
88 memcpy(rpm_data, &req.hdr, sizeof(rpm_gen_hdr));
89 memcpy(rpm_data + sizeof(rpm_gen_hdr), &req.req_hdr, sizeof(rpm_req_hdr));
90 memcpy(rpm_data + sizeof(rpm_gen_hdr)+ sizeof(rpm_req_hdr), req.data, len);
91
92 // Send Data Request to RPM
93 send_err = glink_tx(rpm_glink_port, NULL, (const void *)rpm_data, len_to_rpm, 0);
94 if (send_err)
95 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -070096 dprintf(CRITICAL, "%s:%d, Glink tx error: 0x%x\n", __func__, __LINE__, send_err);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -080097 free(rpm_data);
98 free_kvp_object(&req.data);
99 break;
100 }
101#ifdef DEBUG_GLINK
102 dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
103#endif
104 event_wait(&wait_for_data);
105 free(rpm_data);
106 free_kvp_object(&req.data);
107 break;
108 case RPM_CMD_TYPE:
109 cmd.hdr.type = RPM_CMD_MAGIC;
110 cmd.hdr.len = CMD_MSG_LENGTH;//0x8;
111 len_to_rpm = sizeof(rpm_cmd);
112
113 fill_kvp_object(&cmd.data, data, len);
114 send_err = glink_tx(rpm_glink_port, NULL, (const void *)&cmd, len_to_rpm, 0);
115 if (send_err)
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700116 dprintf(CRITICAL, "%s:%d, Glink tx error: 0x%x\n", __func__, __LINE__, send_err);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800117 free_kvp_object(&cmd.data);
118 break;
119 default:
120 dprintf(CRITICAL, "Invalid RPM Request\n");
121 break;
122 }
123
124 return send_err;
125}
126
127uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t* len)
128{
129 rpm_ack_msg *resp;
130 msg_type type = 0;
131 uint32_t ret = 0;
132 /* As per the current design rpm response does not exceed 20 bytes */
133 if (rx_buffer == NULL)
134 {
135 dprintf(CRITICAL, "Invalid pointer to data received from RPM\n");
136 return 99;
137 }
138 resp = (rpm_ack_msg *)rx_buffer;
139
140 arch_invalidate_cache_range((addr_t)resp, sizeof(rpm_gen_hdr));
141
142 if(resp->hdr.type == RPM_CMD_MAGIC)
143 {
144 type = RPM_CMD_TYPE;
145 }
146 else if(resp->hdr.type == RPM_REQ_MAGIC)
147 {
148 type = RPM_REQUEST_TYPE;
149 }
150
151 if (type == RPM_CMD_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
152 {
153 dprintf(SPEW, "Received SUCCESS CMD ACK\n");
154 }
155 else if (type == RPM_REQUEST_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
156 {
157 dprintf(SPEW, "Received SUCCESS REQ ACK \n");
158 }
159 else
160 {
161 ret = 1;
162 dprintf(CRITICAL, "Received ERROR ACK \n");
163 }
164
165 if(!ret)
166 {
167 ret = sizeof(rpm_gen_hdr) + sizeof(kvp_data);
168 }
169#ifdef DEBUG_GLINK
170 dprintf(INFO, "%s:%d Return value %u\n", __func__, __LINE__, ret);
171#endif
172 return ret;
173}
174
175void rpm_vector_glink_ssr_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
176 void *buffer, size_t size, size_t intent_used,
177 glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
178{
179 char rx_buffer[12];
180 char *return_buffer = NULL;
181 uint32_t ret = 0;
182 uint32_t offset = 0;
183 size_t return_size = 0;
184
185#ifdef DEBUG_GLINK
186 dprintf(INFO, "RPM Vector GLINK SSR ISR\n");
187#endif
188 if (size == 0)
189 {
190 dprintf(CRITICAL, "Invalid size of RPM response\n");
191 ASSERT(0);
192 }
193 if (size > sizeof(rx_buffer))
194 {
195 dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
196 ASSERT(0);
197 }
198 do
199 {
200 return_buffer = vprovider(buffer, offset, &return_size);
201 if(return_buffer)
202 {
203 memcpy(rx_buffer+offset,return_buffer, return_size);
204 offset += return_size;
205 }
206 } while(return_buffer);
207 ret = rpm_glink_recv_data(rx_buffer,(uint32_t *)&size);
208 if(ret)
209 {
210 dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
211 }
212 // Release the mutex
213#ifdef DEBUG_GLINK
214 dprintf(INFO, "Received Data from RPM\n");
215#endif
216 event_signal(&wait_for_data, false);
217}
218
219void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
220 void *buffer, size_t size, size_t intent_used,
221 glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
222{
223 char rx_buffer[64];
224 char *return_buffer = NULL;
225 uint32_t ret = 0;
226 uint32_t offset = 0;
227 size_t return_size = 0;
228#ifdef DEBUG_GLINK
229 dprintf(INFO, "RPM Vector GLINK ISR\n");
230#endif
231 if (size == 0)
232 {
233 dprintf(CRITICAL, "Invalid size of RPM response\n");
234 ASSERT(0);
235 }
236 if (size > sizeof(rx_buffer))
237 {
238 dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
239 ASSERT(0);
240 }
241 do
242 {
243 return_buffer = vprovider(buffer, offset, &return_size);
244 if(return_buffer)
245 {
246 memcpy(rx_buffer+offset,return_buffer, return_size);
247 offset += return_size;
248 }
249 } while(return_buffer);
250 ret = rpm_glink_recv_data(rx_buffer, (uint32_t *)&size);
251 if(ret)
252 {
253 dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
254 }
255 // Release the mutex
256#ifdef DEBUG_GLINK
257 dprintf(INFO, "Received Data from RPM\n");
258#endif
259 event_signal(&wait_for_data, false);
260}
261
262void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
263{
264 if(event == GLINK_CONNECTED)
265 {
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700266 event_signal(&wait_for_rpm_init, false);
267 dprintf(INFO, "Glink Connection between APPS and RPM established\n");
268 return;
269 }
270}
271
272void rpm_glink_notify_state_ssr_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
273{
274 if(event == GLINK_CONNECTED)
275 {
276 event_signal(&wait_for_ssr_init, false);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800277 dprintf(INFO, "Glink Connection between APPS and RPM established\n");
278 return;
279 }
280}
281
282void rpm_glink_tx_done_isr(void)
283{
284 //empty function for tx_done cb. Nothing required here for now since we are always in
285 //"single-threaded" operation of sending GLink requests
286 return;
287}
288
289void rpm_glink_open(glink_link_info_type *link_info, void* priv)
290{
291 glink_err_type ret;
292 glink_open_config_type glink_open_cfg = {0}, glink_ssr_open_cfg = {0};
293
294 // Open channel for tx
295 glink_open_cfg.name = "rpm_requests";
296 glink_open_cfg.remote_ss = link_info->remote_ss;
297 glink_open_cfg.notify_rx = NULL;
298 glink_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_isr;
299 glink_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
300 glink_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
301 glink_open_cfg.priv = NULL;
302 ret = glink_open(&glink_open_cfg, &rpm_glink_port);
303 if (ret == GLINK_STATUS_SUCCESS)
304 dprintf(INFO, "Opening RPM Glink Port success\n");
305 else
306 {
307 dprintf(CRITICAL, "Opening RPM Glink Port failure %d\n", ret);
308 ASSERT(0);
309 }
310
311 // Open Channel for tear down
312 glink_ssr_open_cfg.name = "glink_ssr";
313 glink_ssr_open_cfg.remote_ss = link_info->remote_ss;
314 glink_ssr_open_cfg.notify_rx = NULL;
315 glink_ssr_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_ssr_isr;
316 glink_ssr_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700317 glink_ssr_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_ssr_isr;
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800318 glink_ssr_open_cfg.priv = NULL;
319
320 ret = glink_open(&glink_ssr_open_cfg, &ssr_glink_port);
321 if (ret == GLINK_STATUS_SUCCESS)
322 dprintf(INFO, "Opening SSR Glink Port success\n");
323 else
324 {
325 dprintf(CRITICAL, "Opening SSR Glink Port failure %d\n", ret);
326 ASSERT(0);
327 }
328
329}
330
331void rpm_glink_init()
332{
333 glink_err_type ret;
334 glink_link_id_type link_id;
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700335 event_init(&wait_for_rpm_init, false, EVENT_FLAG_AUTOUNSIGNAL);
336 event_init(&wait_for_ssr_init, false, EVENT_FLAG_AUTOUNSIGNAL);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800337
338 dprintf(INFO, "RPM GLink Init\n");
339 // Initialize RPM transport
340 ret = xport_rpm_init(NULL);
341 if (ret == GLINK_STATUS_SUCCESS)
342 {
343 unmask_interrupt(GLINK_IPC_IRQ);
344 GLINK_LINK_ID_STRUCT_INIT(link_id);
345 link_id.remote_ss = "rpm";
346 link_id.link_notifier = (glink_link_state_notif_cb)rpm_glink_open;
347 glink_register_link_state_cb(&link_id, NULL);
348 }
349 else
350 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700351 dprintf(CRITICAL, "RPM Glink Init Failure 0x%x\n", ret);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800352 ASSERT(0);
353 }
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700354 event_wait(&wait_for_rpm_init);
355 event_wait(&wait_for_ssr_init);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800356}
357
358void rpm_glink_uninit()
359{
360 rpm_ssr_req req;
361 glink_err_type ret;
362 uint32_t len_to_rpm, loop = 100000;
363
364 // update ssr request
365 req.version = 0;
366 req.cmd = 0;
367 req.seqnumber = 0;
368 memset(req.name, 0, sizeof(req.name));
369 strncpy(req.name, "apss", 4);
370 req.namelength = strlen(req.name);
371 len_to_rpm = sizeof(rpm_ssr_req);
372 dprintf(INFO, "RPM GLINK UnInit\n");
373 ret = glink_tx(ssr_glink_port, NULL, (const void *)&req, len_to_rpm, 0);
374
375 if (ret)
376 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700377 dprintf(CRITICAL, "Glink SSR Channel: Tx for link tear down request failure with error code: 0x%x\n", ret);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800378 ASSERT(0);
379 }
380
381#ifdef DEBUG_GLINK
382 dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
383#endif
384 // loop till the FIFO indices are cleared
385 while((ret = glink_wait_link_down(ssr_glink_port)) && loop)
386 {
387 loop--;
388 mdelay(1);
389 continue;
390 }
391 if (!loop)
392 {
393 dprintf(INFO, "%s:%d, Tearing down Glink SSR Channel Timed out\n", __func__, __LINE__);
394 ASSERT(0);
395 }
396}