2 * Copyright (C) 2010 Google, Inc.
3 * Author: Dima Zavin <dima@android.com>
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
16 #include <linux/clk.h>
17 #include <linux/delay.h>
18 #include <linux/dma-mapping.h>
19 #include <linux/err.h>
21 #include <linux/kthread.h>
22 #include <linux/list.h>
23 #include <linux/mutex.h>
24 #include <linux/slab.h>
25 #include <linux/tegra_rpc.h>
26 #include <linux/types.h>
29 #include <mach/nvmap.h>
31 #include "../../../../video/tegra/nvmap/nvmap.h"
38 AVP_DBG_TRACE_SVC = 1U << 0,
41 static u32 debug_mask = 0;
42 module_param_named(debug_mask, debug_mask, uint, S_IWUSR | S_IRUGO);
44 #define DBG(flag, args...) \
45 do { if (unlikely(debug_mask & (flag))) pr_info(args); } while (0)
59 static struct avp_module avp_modules[] = {
60 [AVP_MODULE_ID_VCP] = {
62 .clk_req = CLK_REQUEST_VCP,
64 [AVP_MODULE_ID_BSEA] = {
66 .clk_req = CLK_REQUEST_BSEA,
68 [AVP_MODULE_ID_VDE] = {
70 .clk_req = CLK_REQUEST_VDE,
73 #define NUM_AVP_MODULES ARRAY_SIZE(avp_modules)
78 struct avp_module *mod;
82 struct avp_clk clks[NUM_CLK_REQUESTS];
87 struct mutex clk_lock;
89 struct trpc_endpoint *cpu_ep;
90 struct task_struct *svc_thread;
92 /* client for remote allocations, for easy tear down */
93 struct nvmap_client *nvmap_remote;
94 struct trpc_node *rpc_node;
97 static void do_svc_nvmap_create(struct avp_svc_info *avp_svc,
101 struct svc_nvmap_create *msg = (struct svc_nvmap_create *)_msg;
102 struct svc_nvmap_create_resp resp;
103 struct nvmap_handle_ref *handle;
107 handle = nvmap_create_handle(avp_svc->nvmap_remote, msg->size);
108 if (unlikely(IS_ERR(handle))) {
109 pr_err("avp_svc: error creating handle (%d bytes) for remote\n",
111 err = AVP_ERR_ENOMEM;
113 handle_id = (u32)nvmap_ref_to_id(handle);
115 resp.svc_id = SVC_NVMAP_CREATE_RESPONSE;
117 resp.handle_id = handle_id;
118 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
119 sizeof(resp), GFP_KERNEL);
120 /* TODO: do we need to put the handle if send_msg failed? */
123 static void do_svc_nvmap_alloc(struct avp_svc_info *avp_svc,
124 struct svc_msg *_msg,
127 struct svc_nvmap_alloc *msg = (struct svc_nvmap_alloc *)_msg;
128 struct svc_common_resp resp;
129 struct nvmap_handle *handle;
135 handle = nvmap_get_handle_id(avp_svc->nvmap_remote, msg->handle_id);
136 if (IS_ERR(handle)) {
137 pr_err("avp_svc: unknown remote handle 0x%x\n", msg->handle_id);
138 err = AVP_ERR_EACCES;
142 if (msg->num_heaps > 4) {
143 pr_err("avp_svc: invalid remote alloc request (%d heaps?!)\n",
145 /* TODO: should we error out instead ? */
148 if (msg->num_heaps == 0)
149 heap_mask = NVMAP_HEAP_CARVEOUT_GENERIC | NVMAP_HEAP_SYSMEM;
151 for (i = 0; i < msg->num_heaps; i++) {
152 switch (msg->heaps[i]) {
153 case AVP_NVMAP_HEAP_EXTERNAL:
154 heap_mask |= NVMAP_HEAP_SYSMEM;
156 case AVP_NVMAP_HEAP_GART:
157 heap_mask |= NVMAP_HEAP_IOVMM;
159 case AVP_NVMAP_HEAP_EXTERNAL_CARVEOUT:
160 heap_mask |= NVMAP_HEAP_CARVEOUT_GENERIC;
162 case AVP_NVMAP_HEAP_IRAM:
163 heap_mask |= NVMAP_HEAP_CARVEOUT_IRAM;
170 align = max_t(size_t, L1_CACHE_BYTES, msg->align);
171 err = nvmap_alloc_handle_id(avp_svc->nvmap_remote, msg->handle_id,
172 heap_mask, align, 0);
173 nvmap_handle_put(handle);
175 pr_err("avp_svc: can't allocate for handle 0x%x (%d)\n",
176 msg->handle_id, err);
177 err = AVP_ERR_ENOMEM;
181 resp.svc_id = SVC_NVMAP_ALLOC_RESPONSE;
183 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
184 sizeof(resp), GFP_KERNEL);
187 static void do_svc_nvmap_free(struct avp_svc_info *avp_svc,
188 struct svc_msg *_msg,
191 struct svc_nvmap_free *msg = (struct svc_nvmap_free *)_msg;
193 nvmap_free_handle_id(avp_svc->nvmap_remote, msg->handle_id);
196 static void do_svc_nvmap_pin(struct avp_svc_info *avp_svc,
197 struct svc_msg *_msg,
200 struct svc_nvmap_pin *msg = (struct svc_nvmap_pin *)_msg;
201 struct svc_nvmap_pin_resp resp;
202 struct nvmap_handle_ref *handle;
203 unsigned long addr = ~0UL;
204 unsigned long id = msg->handle_id;
207 handle = nvmap_duplicate_handle_id(avp_svc->nvmap_remote, id);
208 if (IS_ERR(handle)) {
209 pr_err("avp_svc: can't dup handle %lx\n", id);
212 err = nvmap_pin_ids(avp_svc->nvmap_remote, 1, &id);
214 pr_err("avp_svc: can't pin for handle %lx (%d)\n", id, err);
217 addr = nvmap_handle_address(avp_svc->nvmap_remote, id);
220 resp.svc_id = SVC_NVMAP_PIN_RESPONSE;
222 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
223 sizeof(resp), GFP_KERNEL);
226 static void do_svc_nvmap_unpin(struct avp_svc_info *avp_svc,
227 struct svc_msg *_msg,
230 struct svc_nvmap_unpin *msg = (struct svc_nvmap_unpin *)_msg;
231 struct svc_common_resp resp;
232 unsigned long id = msg->handle_id;
234 nvmap_unpin_ids(avp_svc->nvmap_remote, 1, &id);
235 nvmap_free_handle_id(avp_svc->nvmap_remote, id);
237 resp.svc_id = SVC_NVMAP_UNPIN_RESPONSE;
239 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
240 sizeof(resp), GFP_KERNEL);
243 static void do_svc_nvmap_from_id(struct avp_svc_info *avp_svc,
244 struct svc_msg *_msg,
247 struct svc_nvmap_from_id *msg = (struct svc_nvmap_from_id *)_msg;
248 struct svc_common_resp resp;
249 struct nvmap_handle_ref *handle;
252 handle = nvmap_duplicate_handle_id(avp_svc->nvmap_remote,
254 if (IS_ERR(handle)) {
255 pr_err("avp_svc: can't duplicate handle for id 0x%x (%d)\n",
256 msg->handle_id, (int)PTR_ERR(handle));
257 err = AVP_ERR_ENOMEM;
260 resp.svc_id = SVC_NVMAP_FROM_ID_RESPONSE;
262 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
263 sizeof(resp), GFP_KERNEL);
266 static void do_svc_nvmap_get_addr(struct avp_svc_info *avp_svc,
267 struct svc_msg *_msg,
270 struct svc_nvmap_get_addr *msg = (struct svc_nvmap_get_addr *)_msg;
271 struct svc_nvmap_get_addr_resp resp;
273 resp.svc_id = SVC_NVMAP_GET_ADDRESS_RESPONSE;
274 resp.addr = nvmap_handle_address(avp_svc->nvmap_remote, msg->handle_id);
275 resp.addr += msg->offs;
276 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
277 sizeof(resp), GFP_KERNEL);
280 static void do_svc_pwr_register(struct avp_svc_info *avp_svc,
281 struct svc_msg *_msg,
284 struct svc_pwr_register *msg = (struct svc_pwr_register *)_msg;
285 struct svc_pwr_register_resp resp;
287 resp.svc_id = SVC_POWER_RESPONSE;
289 resp.client_id = msg->client_id;
291 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
292 sizeof(resp), GFP_KERNEL);
295 static struct avp_module *find_avp_module(struct avp_svc_info *avp_svc, u32 id)
297 if (id < NUM_AVP_MODULES && avp_modules[id].name)
298 return &avp_modules[id];
302 static void do_svc_module_reset(struct avp_svc_info *avp_svc,
303 struct svc_msg *_msg,
306 struct svc_module_ctrl *msg = (struct svc_module_ctrl *)_msg;
307 struct svc_common_resp resp;
308 struct avp_module *mod;
309 struct avp_clk *aclk;
311 mod = find_avp_module(avp_svc, msg->module_id);
313 if (msg->module_id == AVP_MODULE_ID_AVP)
314 pr_err("avp_svc: AVP suicidal?!?!\n");
316 pr_err("avp_svc: Unknown module reset requested: %d\n",
318 /* other side doesn't handle errors for reset */
323 aclk = &avp_svc->clks[mod->clk_req];
324 tegra_periph_reset_assert(aclk->clk);
326 tegra_periph_reset_deassert(aclk->clk);
330 resp.svc_id = SVC_MODULE_RESET_RESPONSE;
331 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
332 sizeof(resp), GFP_KERNEL);
335 static void do_svc_module_clock(struct avp_svc_info *avp_svc,
336 struct svc_msg *_msg,
339 struct svc_module_ctrl *msg = (struct svc_module_ctrl *)_msg;
340 struct svc_common_resp resp;
341 struct avp_module *mod;
342 struct avp_clk *aclk;
344 mod = find_avp_module(avp_svc, msg->module_id);
346 pr_err("avp_svc: unknown module clock requested: %d\n",
348 resp.err = AVP_ERR_EINVAL;
352 mutex_lock(&avp_svc->clk_lock);
353 aclk = &avp_svc->clks[mod->clk_req];
355 if (aclk->refcnt++ == 0) {
356 clk_enable(avp_svc->emcclk);
357 clk_enable(avp_svc->sclk);
358 clk_enable(aclk->clk);
361 if (unlikely(aclk->refcnt == 0)) {
362 pr_err("avp_svc: unbalanced clock disable for '%s'\n",
364 } else if (--aclk->refcnt == 0) {
365 clk_disable(aclk->clk);
366 clk_disable(avp_svc->sclk);
367 clk_disable(avp_svc->emcclk);
370 mutex_unlock(&avp_svc->clk_lock);
374 resp.svc_id = SVC_MODULE_CLOCK_RESPONSE;
375 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
376 sizeof(resp), GFP_KERNEL);
379 static void do_svc_null_response(struct avp_svc_info *avp_svc,
380 struct svc_msg *_msg,
381 size_t len, u32 resp_svc_id)
383 struct svc_common_resp resp;
384 resp.svc_id = resp_svc_id;
386 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
387 sizeof(resp), GFP_KERNEL);
390 static void do_svc_dfs_get_state(struct avp_svc_info *avp_svc,
391 struct svc_msg *_msg,
394 struct svc_dfs_get_state_resp resp;
395 resp.svc_id = SVC_DFS_GETSTATE_RESPONSE;
396 resp.state = AVP_DFS_STATE_STOPPED;
397 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
398 sizeof(resp), GFP_KERNEL);
401 static void do_svc_dfs_get_clk_util(struct avp_svc_info *avp_svc,
402 struct svc_msg *_msg,
405 struct svc_dfs_get_clk_util_resp resp;
407 resp.svc_id = SVC_DFS_GET_CLK_UTIL_RESPONSE;
409 memset(&resp.usage, 0, sizeof(struct avp_clk_usage));
410 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
411 sizeof(resp), GFP_KERNEL);
414 static void do_svc_pwr_max_freq(struct avp_svc_info *avp_svc,
415 struct svc_msg *_msg,
418 struct svc_pwr_max_freq_resp resp;
420 resp.svc_id = SVC_POWER_MAXFREQ;
422 trpc_send_msg(avp_svc->rpc_node, avp_svc->cpu_ep, &resp,
423 sizeof(resp), GFP_KERNEL);
426 static void do_svc_printf(struct avp_svc_info *avp_svc, struct svc_msg *_msg,
429 struct svc_printf *msg = (struct svc_printf *)_msg;
430 char tmp_str[SVC_MAX_STRING_LEN];
432 /* ensure we null terminate the source */
433 strlcpy(tmp_str, msg->str, SVC_MAX_STRING_LEN);
434 pr_info("[AVP]: %s", tmp_str);
437 static int dispatch_svc_message(struct avp_svc_info *avp_svc,
443 switch (msg->svc_id) {
444 case SVC_NVMAP_CREATE:
445 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_create\n", __func__);
446 do_svc_nvmap_create(avp_svc, msg, len);
448 case SVC_NVMAP_ALLOC:
449 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_alloc\n", __func__);
450 do_svc_nvmap_alloc(avp_svc, msg, len);
453 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_free\n", __func__);
454 do_svc_nvmap_free(avp_svc, msg, len);
457 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_pin\n", __func__);
458 do_svc_nvmap_pin(avp_svc, msg, len);
460 case SVC_NVMAP_UNPIN:
461 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_unpin\n", __func__);
462 do_svc_nvmap_unpin(avp_svc, msg, len);
464 case SVC_NVMAP_FROM_ID:
465 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_from_id\n", __func__);
466 do_svc_nvmap_from_id(avp_svc, msg, len);
468 case SVC_NVMAP_GET_ADDRESS:
469 DBG(AVP_DBG_TRACE_SVC, "%s: got nvmap_get_addr\n", __func__);
470 do_svc_nvmap_get_addr(avp_svc, msg, len);
472 case SVC_POWER_REGISTER:
473 DBG(AVP_DBG_TRACE_SVC, "%s: got power_register\n", __func__);
474 do_svc_pwr_register(avp_svc, msg, len);
476 case SVC_POWER_UNREGISTER:
477 DBG(AVP_DBG_TRACE_SVC, "%s: got power_unregister\n", __func__);
480 case SVC_POWER_BUSY_HINT_MULTI:
481 DBG(AVP_DBG_TRACE_SVC, "%s: got power_busy_hint_multi\n",
485 case SVC_POWER_BUSY_HINT:
486 case SVC_POWER_STARVATION:
487 DBG(AVP_DBG_TRACE_SVC, "%s: got power busy/starve hint\n",
489 do_svc_null_response(avp_svc, msg, len, SVC_POWER_RESPONSE);
491 case SVC_POWER_MAXFREQ:
492 DBG(AVP_DBG_TRACE_SVC, "%s: got power get_max_freq\n",
494 do_svc_pwr_max_freq(avp_svc, msg, len);
496 case SVC_DFS_GETSTATE:
497 DBG(AVP_DBG_TRACE_SVC, "%s: got dfs_get_state\n", __func__);
498 do_svc_dfs_get_state(avp_svc, msg, len);
500 case SVC_MODULE_RESET:
501 DBG(AVP_DBG_TRACE_SVC, "%s: got module_reset\n", __func__);
502 do_svc_module_reset(avp_svc, msg, len);
504 case SVC_MODULE_CLOCK:
505 DBG(AVP_DBG_TRACE_SVC, "%s: got module_clock\n", __func__);
506 do_svc_module_clock(avp_svc, msg, len);
508 case SVC_DFS_GET_CLK_UTIL:
509 DBG(AVP_DBG_TRACE_SVC, "%s: got get_clk_util\n", __func__);
510 do_svc_dfs_get_clk_util(avp_svc, msg, len);
513 DBG(AVP_DBG_TRACE_SVC, "%s: got remote printf\n", __func__);
514 do_svc_printf(avp_svc, msg, len);
516 case SVC_AVP_WDT_RESET:
517 pr_err("avp_svc: AVP has been reset by watchdog\n");
520 pr_err("avp_svc: invalid SVC call 0x%x\n", msg->svc_id);
528 static int avp_svc_thread(void *data)
530 struct avp_svc_info *avp_svc = data;
531 u8 buf[TEGRA_RPC_MAX_MSG_LEN];
532 struct svc_msg *msg = (struct svc_msg *)buf;
535 BUG_ON(!avp_svc->cpu_ep);
537 ret = trpc_wait_peer(avp_svc->cpu_ep, -1);
539 /* XXX: teardown?! */
540 pr_err("%s: no connection from AVP (%d)\n", __func__, ret);
544 pr_info("%s: got remote peer\n", __func__);
546 while (!kthread_should_stop()) {
547 DBG(AVP_DBG_TRACE_SVC, "%s: waiting for message\n", __func__);
548 ret = trpc_recv_msg(avp_svc->rpc_node, avp_svc->cpu_ep, buf,
549 TEGRA_RPC_MAX_MSG_LEN, -1);
550 DBG(AVP_DBG_TRACE_SVC, "%s: got message\n", __func__);
552 pr_err("%s: couldn't receive msg\n", __func__);
553 /* XXX: port got closed? we should exit? */
556 pr_err("%s: received msg of len 0?!\n", __func__);
559 dispatch_svc_message(avp_svc, msg, ret);
563 trpc_put(avp_svc->cpu_ep);
564 pr_info("%s: done\n", __func__);
568 int avp_svc_start(struct avp_svc_info *avp_svc)
570 struct trpc_endpoint *ep;
573 avp_svc->nvmap_remote = nvmap_create_client(nvmap_dev, "avp_remote");
574 if (IS_ERR(avp_svc->nvmap_remote)) {
575 pr_err("%s: cannot create remote nvmap client\n", __func__);
576 ret = PTR_ERR(avp_svc->nvmap_remote);
577 goto err_nvmap_create_remote_client;
580 ep = trpc_create(avp_svc->rpc_node, "RPC_CPU_PORT", NULL, NULL);
582 pr_err("%s: can't create RPC_CPU_PORT\n", __func__);
584 goto err_cpu_port_create;
587 /* TODO: protect this */
588 avp_svc->cpu_ep = ep;
590 /* the service thread should get an extra reference for the port */
591 trpc_get(avp_svc->cpu_ep);
592 avp_svc->svc_thread = kthread_run(avp_svc_thread, avp_svc,
594 if (IS_ERR_OR_NULL(avp_svc->svc_thread)) {
595 avp_svc->svc_thread = NULL;
596 pr_err("%s: can't create svc thread\n", __func__);
603 trpc_close(avp_svc->cpu_ep);
604 trpc_put(avp_svc->cpu_ep);
605 avp_svc->cpu_ep = NULL;
607 nvmap_client_put(avp_svc->nvmap_remote);
608 err_nvmap_create_remote_client:
609 avp_svc->nvmap_remote = NULL;
613 void avp_svc_stop(struct avp_svc_info *avp_svc)
618 trpc_close(avp_svc->cpu_ep);
619 ret = kthread_stop(avp_svc->svc_thread);
621 /* the thread never started, drop it's extra reference */
622 trpc_put(avp_svc->cpu_ep);
624 avp_svc->cpu_ep = NULL;
626 nvmap_client_put(avp_svc->nvmap_remote);
627 avp_svc->nvmap_remote = NULL;
629 mutex_lock(&avp_svc->clk_lock);
630 for (i = 0; i < NUM_CLK_REQUESTS; i++) {
631 struct avp_clk *aclk = &avp_svc->clks[i];
632 BUG_ON(aclk->refcnt < 0);
633 if (aclk->refcnt > 0) {
634 pr_info("%s: remote left clock '%s' on\n", __func__,
636 clk_disable(aclk->clk);
637 /* sclk/emcclk was enabled once for every clock */
638 clk_disable(avp_svc->sclk);
639 clk_disable(avp_svc->emcclk);
643 mutex_unlock(&avp_svc->clk_lock);
646 struct avp_svc_info *avp_svc_init(struct platform_device *pdev,
647 struct trpc_node *rpc_node)
649 struct avp_svc_info *avp_svc;
656 avp_svc = kzalloc(sizeof(struct avp_svc_info), GFP_KERNEL);
662 BUILD_BUG_ON(NUM_CLK_REQUESTS > BITS_PER_LONG);
664 for (i = 0; i < NUM_AVP_MODULES; i++) {
665 struct avp_module *mod = &avp_modules[i];
669 BUG_ON(mod->clk_req >= NUM_CLK_REQUESTS ||
670 cnt++ >= NUM_CLK_REQUESTS);
672 clk = clk_get(&pdev->dev, mod->name);
675 pr_err("avp_svc: Couldn't get required clocks\n");
678 avp_svc->clks[mod->clk_req].clk = clk;
679 avp_svc->clks[mod->clk_req].mod = mod;
680 avp_svc->clks[mod->clk_req].refcnt = 0;
683 avp_svc->sclk = clk_get(&pdev->dev, "sclk");
684 if (IS_ERR(avp_svc->sclk)) {
685 pr_err("avp_svc: Couldn't get sclk for dvfs\n");
690 avp_svc->emcclk = clk_get(&pdev->dev, "emc");
691 if (IS_ERR(avp_svc->emcclk)) {
692 pr_err("avp_svc: Couldn't get emcclk for dvfs\n");
698 * The emc is a shared clock, it will be set to the highest
699 * requested rate from any user. Set the rate to ULONG_MAX to
700 * always request the max rate whenever this request is enabled
702 clk_set_rate(avp_svc->emcclk, ULONG_MAX);
704 avp_svc->rpc_node = rpc_node;
706 mutex_init(&avp_svc->clk_lock);
711 for (i = 0; i < NUM_CLK_REQUESTS; i++)
712 if (avp_svc->clks[i].clk)
713 clk_put(avp_svc->clks[i].clk);
714 if (!IS_ERR_OR_NULL(avp_svc->sclk))
715 clk_put(avp_svc->sclk);
716 if (!IS_ERR_OR_NULL(avp_svc->emcclk))
717 clk_put(avp_svc->emcclk);
722 void avp_svc_destroy(struct avp_svc_info *avp_svc)
726 for (i = 0; i < NUM_CLK_REQUESTS; i++)
727 clk_put(avp_svc->clks[i].clk);
728 clk_put(avp_svc->sclk);
729 clk_put(avp_svc->emcclk);