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