blob: f564480ab9e4c0015985376695546101db5f80ce [file] [log] [blame]
vijay kumar207b4562015-12-31 18:33:08 +05301/* Copyright (c) 2015-2016 The Linux Foundation. All rights reserved.
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -08002 *
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
vijay kumar207b4562015-12-31 18:33:08 +053062static void rpmdatacpy(uint32_t * dst, uint32_t *src, uint32_t size)
63{
64 if(size%4)
65 ASSERT(0);
66 size = size/4;
67
68 while (size >0)
69 {
70 *dst++ = *src++;
71 size--;
72 }
73}
74
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -080075glink_err_type rpm_glink_send_data(uint32_t *data, uint32_t len, msg_type type)
76{
77 rpm_req req;
78 rpm_cmd cmd;
79 glink_err_type send_err = 0;
80 uint32_t len_to_rpm = 0;
81 void *rpm_data = NULL;
82 event_init(&wait_for_data, false, EVENT_FLAG_AUTOUNSIGNAL);
83
84 switch(type)
85 {
86 case RPM_REQUEST_TYPE:
87 req.hdr.type = RPM_REQ_MAGIC;
88 req.hdr.len = len + REQ_MSG_LENGTH;//20
89 req.req_hdr.id = ++msg_id;
90 req.req_hdr.set = 0;
91 req.req_hdr.resourceType = data[RESOURCETYPE];
92 req.req_hdr.resourceId = data[RESOURCEID];
93 req.req_hdr.dataLength = len;
94
95 fill_kvp_object(&req.data, data, len);
96 len_to_rpm = req.req_hdr.dataLength + 0x28;
97
98 rpm_data = (void*) malloc(len_to_rpm);
99 ASSERT(rpm_data);
100 memset(rpm_data, 0, len_to_rpm);
101 memcpy(rpm_data, &req.hdr, sizeof(rpm_gen_hdr));
102 memcpy(rpm_data + sizeof(rpm_gen_hdr), &req.req_hdr, sizeof(rpm_req_hdr));
103 memcpy(rpm_data + sizeof(rpm_gen_hdr)+ sizeof(rpm_req_hdr), req.data, len);
104
105 // Send Data Request to RPM
106 send_err = glink_tx(rpm_glink_port, NULL, (const void *)rpm_data, len_to_rpm, 0);
107 if (send_err)
108 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700109 dprintf(CRITICAL, "%s:%d, Glink tx error: 0x%x\n", __func__, __LINE__, send_err);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800110 free(rpm_data);
111 free_kvp_object(&req.data);
112 break;
113 }
114#ifdef DEBUG_GLINK
115 dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
116#endif
117 event_wait(&wait_for_data);
118 free(rpm_data);
119 free_kvp_object(&req.data);
120 break;
121 case RPM_CMD_TYPE:
122 cmd.hdr.type = RPM_CMD_MAGIC;
123 cmd.hdr.len = CMD_MSG_LENGTH;//0x8;
124 len_to_rpm = sizeof(rpm_cmd);
125
126 fill_kvp_object(&cmd.data, data, len);
127 send_err = glink_tx(rpm_glink_port, NULL, (const void *)&cmd, len_to_rpm, 0);
128 if (send_err)
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700129 dprintf(CRITICAL, "%s:%d, Glink tx error: 0x%x\n", __func__, __LINE__, send_err);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800130 free_kvp_object(&cmd.data);
131 break;
132 default:
133 dprintf(CRITICAL, "Invalid RPM Request\n");
134 break;
135 }
136
137 return send_err;
138}
139
140uint32_t rpm_glink_recv_data(char *rx_buffer, uint32_t* len)
141{
142 rpm_ack_msg *resp;
143 msg_type type = 0;
144 uint32_t ret = 0;
145 /* As per the current design rpm response does not exceed 20 bytes */
146 if (rx_buffer == NULL)
147 {
148 dprintf(CRITICAL, "Invalid pointer to data received from RPM\n");
149 return 99;
150 }
151 resp = (rpm_ack_msg *)rx_buffer;
152
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800153 if(resp->hdr.type == RPM_CMD_MAGIC)
154 {
155 type = RPM_CMD_TYPE;
156 }
157 else if(resp->hdr.type == RPM_REQ_MAGIC)
158 {
159 type = RPM_REQUEST_TYPE;
160 }
161
162 if (type == RPM_CMD_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
163 {
164 dprintf(SPEW, "Received SUCCESS CMD ACK\n");
165 }
166 else if (type == RPM_REQUEST_TYPE && resp->hdr.len == ACK_MSG_LENGTH)
167 {
168 dprintf(SPEW, "Received SUCCESS REQ ACK \n");
169 }
170 else
171 {
172 ret = 1;
173 dprintf(CRITICAL, "Received ERROR ACK \n");
174 }
175
176 if(!ret)
177 {
178 ret = sizeof(rpm_gen_hdr) + sizeof(kvp_data);
179 }
180#ifdef DEBUG_GLINK
181 dprintf(INFO, "%s:%d Return value %u\n", __func__, __LINE__, ret);
182#endif
183 return ret;
184}
185
186void rpm_vector_glink_ssr_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
187 void *buffer, size_t size, size_t intent_used,
188 glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
189{
190 char rx_buffer[12];
191 char *return_buffer = NULL;
192 uint32_t ret = 0;
193 uint32_t offset = 0;
194 size_t return_size = 0;
195
196#ifdef DEBUG_GLINK
197 dprintf(INFO, "RPM Vector GLINK SSR ISR\n");
198#endif
199 if (size == 0)
200 {
201 dprintf(CRITICAL, "Invalid size of RPM response\n");
202 ASSERT(0);
203 }
204 if (size > sizeof(rx_buffer))
205 {
206 dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
207 ASSERT(0);
208 }
209 do
210 {
211 return_buffer = vprovider(buffer, offset, &return_size);
212 if(return_buffer)
213 {
vijay kumar207b4562015-12-31 18:33:08 +0530214 rpmdatacpy((uint32_t *)(rx_buffer + offset),(uint32_t *)return_buffer, return_size);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800215 offset += return_size;
216 }
217 } while(return_buffer);
218 ret = rpm_glink_recv_data(rx_buffer,(uint32_t *)&size);
219 if(ret)
220 {
221 dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
222 }
223 // Release the mutex
224#ifdef DEBUG_GLINK
225 dprintf(INFO, "Received Data from RPM\n");
226#endif
227 event_signal(&wait_for_data, false);
228}
229
230void rpm_vector_glink_isr(glink_handle_type port, void *unused_open_data, void *unused_pkt_priv,
231 void *buffer, size_t size, size_t intent_used,
232 glink_buffer_provider_fn vprovider, glink_buffer_provider_fn pprovider)
233{
234 char rx_buffer[64];
235 char *return_buffer = NULL;
236 uint32_t ret = 0;
237 uint32_t offset = 0;
238 size_t return_size = 0;
239#ifdef DEBUG_GLINK
240 dprintf(INFO, "RPM Vector GLINK ISR\n");
241#endif
242 if (size == 0)
243 {
244 dprintf(CRITICAL, "Invalid size of RPM response\n");
245 ASSERT(0);
246 }
247 if (size > sizeof(rx_buffer))
248 {
249 dprintf(CRITICAL, "Need larger RPM rx buffer. Size of Local Buffer: %u\tSize of RX Buffer: %u\n", size, sizeof(rx_buffer));
250 ASSERT(0);
251 }
252 do
253 {
254 return_buffer = vprovider(buffer, offset, &return_size);
255 if(return_buffer)
256 {
vijay kumar207b4562015-12-31 18:33:08 +0530257 rpmdatacpy((uint32_t *)(rx_buffer + offset),(uint32_t *)return_buffer, return_size);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800258 offset += return_size;
259 }
260 } while(return_buffer);
261 ret = rpm_glink_recv_data(rx_buffer, (uint32_t *)&size);
262 if(ret)
263 {
264 dprintf(CRITICAL, "Return value from recv_data: %x\n", ret);
265 }
266 // Release the mutex
267#ifdef DEBUG_GLINK
268 dprintf(INFO, "Received Data from RPM\n");
269#endif
270 event_signal(&wait_for_data, false);
271}
272
273void rpm_glink_notify_state_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
274{
275 if(event == GLINK_CONNECTED)
276 {
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700277 event_signal(&wait_for_rpm_init, false);
278 dprintf(INFO, "Glink Connection between APPS and RPM established\n");
279 return;
280 }
281}
282
283void rpm_glink_notify_state_ssr_isr(glink_handle_type handle, void *data, glink_channel_event_type event)
284{
285 if(event == GLINK_CONNECTED)
286 {
287 event_signal(&wait_for_ssr_init, false);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800288 dprintf(INFO, "Glink Connection between APPS and RPM established\n");
289 return;
290 }
291}
292
293void rpm_glink_tx_done_isr(void)
294{
295 //empty function for tx_done cb. Nothing required here for now since we are always in
296 //"single-threaded" operation of sending GLink requests
297 return;
298}
299
300void rpm_glink_open(glink_link_info_type *link_info, void* priv)
301{
302 glink_err_type ret;
303 glink_open_config_type glink_open_cfg = {0}, glink_ssr_open_cfg = {0};
304
305 // Open channel for tx
306 glink_open_cfg.name = "rpm_requests";
307 glink_open_cfg.remote_ss = link_info->remote_ss;
308 glink_open_cfg.notify_rx = NULL;
309 glink_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_isr;
310 glink_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
311 glink_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_isr;
312 glink_open_cfg.priv = NULL;
313 ret = glink_open(&glink_open_cfg, &rpm_glink_port);
314 if (ret == GLINK_STATUS_SUCCESS)
315 dprintf(INFO, "Opening RPM Glink Port success\n");
316 else
317 {
318 dprintf(CRITICAL, "Opening RPM Glink Port failure %d\n", ret);
319 ASSERT(0);
320 }
321
322 // Open Channel for tear down
323 glink_ssr_open_cfg.name = "glink_ssr";
324 glink_ssr_open_cfg.remote_ss = link_info->remote_ss;
325 glink_ssr_open_cfg.notify_rx = NULL;
326 glink_ssr_open_cfg.notify_rxv = (glink_rxv_notification_cb)rpm_vector_glink_ssr_isr;
327 glink_ssr_open_cfg.notify_tx_done = (glink_tx_notification_cb)rpm_glink_tx_done_isr;
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700328 glink_ssr_open_cfg.notify_state = (glink_state_notification_cb)rpm_glink_notify_state_ssr_isr;
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800329 glink_ssr_open_cfg.priv = NULL;
330
331 ret = glink_open(&glink_ssr_open_cfg, &ssr_glink_port);
332 if (ret == GLINK_STATUS_SUCCESS)
333 dprintf(INFO, "Opening SSR Glink Port success\n");
334 else
335 {
336 dprintf(CRITICAL, "Opening SSR Glink Port failure %d\n", ret);
337 ASSERT(0);
338 }
339
340}
341
342void rpm_glink_init()
343{
344 glink_err_type ret;
345 glink_link_id_type link_id;
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700346 event_init(&wait_for_rpm_init, false, EVENT_FLAG_AUTOUNSIGNAL);
347 event_init(&wait_for_ssr_init, false, EVENT_FLAG_AUTOUNSIGNAL);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800348
349 dprintf(INFO, "RPM GLink Init\n");
350 // Initialize RPM transport
351 ret = xport_rpm_init(NULL);
352 if (ret == GLINK_STATUS_SUCCESS)
353 {
354 unmask_interrupt(GLINK_IPC_IRQ);
355 GLINK_LINK_ID_STRUCT_INIT(link_id);
356 link_id.remote_ss = "rpm";
357 link_id.link_notifier = (glink_link_state_notif_cb)rpm_glink_open;
358 glink_register_link_state_cb(&link_id, NULL);
359 }
360 else
361 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700362 dprintf(CRITICAL, "RPM Glink Init Failure 0x%x\n", ret);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800363 ASSERT(0);
364 }
Sridhar Parasurambd9c5182015-05-22 17:06:40 -0700365 event_wait(&wait_for_rpm_init);
366 event_wait(&wait_for_ssr_init);
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800367}
368
369void rpm_glink_uninit()
370{
371 rpm_ssr_req req;
372 glink_err_type ret;
373 uint32_t len_to_rpm, loop = 100000;
374
375 // update ssr request
376 req.version = 0;
377 req.cmd = 0;
378 req.seqnumber = 0;
379 memset(req.name, 0, sizeof(req.name));
Channagoud Kadabib0d4a682015-07-21 20:14:16 -0700380 strlcpy(req.name, "apss", sizeof(req.name));
Sridhar Parasurama4e4fc82015-02-17 14:36:53 -0800381 req.namelength = strlen(req.name);
382 len_to_rpm = sizeof(rpm_ssr_req);
383 dprintf(INFO, "RPM GLINK UnInit\n");
384 ret = glink_tx(ssr_glink_port, NULL, (const void *)&req, len_to_rpm, 0);
385
386 if (ret)
387 {
Sridhar Parasuram06fdde42015-05-22 10:37:36 -0700388 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 -0800389 ASSERT(0);
390 }
391
392#ifdef DEBUG_GLINK
393 dprintf(INFO, "%s:%d, Wait till we receive response from RPM\n", __func__, __LINE__);
394#endif
395 // loop till the FIFO indices are cleared
396 while((ret = glink_wait_link_down(ssr_glink_port)) && loop)
397 {
398 loop--;
399 mdelay(1);
400 continue;
401 }
402 if (!loop)
403 {
404 dprintf(INFO, "%s:%d, Tearing down Glink SSR Channel Timed out\n", __func__, __LINE__);
405 ASSERT(0);
406 }
407}