aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2016-08-19 13:05:35 -0400
committerThierry Reding <treding@nvidia.com>2016-11-18 08:33:43 -0500
commit983de5f97169ab59d4cb0f60d9d9157778ce4a5e (patch)
tree630ac9372721161c85d83b9ce68f309f87094957
parentca791d7f425635b63706e00896a141f85f7de463 (diff)
firmware: tegra: Add BPMP support
The Boot and Power Management Processor (BPMP) is a co-processor found on Tegra SoCs. It is designed to handle the early stages of the boot process and offload power management tasks (such as clocks, resets, powergates, ...) as well as system control services. Compared to the ARM SCPI, the services provided by BPMP are message- based rather than method-based. The BPMP firmware driver provides the services to transmit data to and receive data from the BPMP. Users can also register a Message ReQuest (MRQ), for which a service routine will be run when a corresponding event is received from the firmware. A set of messages, called the BPMP ABI, are specified for a number of different services provided by the BPMP (such as clocks or resets). Based on work by Sivaram Nair <sivaramn@nvidia.com> and Joseph Lo <josephl@nvidia.com>. Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/firmware/tegra/Kconfig12
-rw-r--r--drivers/firmware/tegra/Makefile1
-rw-r--r--drivers/firmware/tegra/bpmp.c868
-rw-r--r--include/soc/tegra/bpmp-abi.h1601
-rw-r--r--include/soc/tegra/bpmp.h141
5 files changed, 2623 insertions, 0 deletions
diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig
index 1fa3e4e136a5..ff2730d5c468 100644
--- a/drivers/firmware/tegra/Kconfig
+++ b/drivers/firmware/tegra/Kconfig
@@ -10,4 +10,16 @@ config TEGRA_IVC
10 keeps the content is synchronization between host CPU and remote 10 keeps the content is synchronization between host CPU and remote
11 processors. 11 processors.
12 12
13config TEGRA_BPMP
14 bool "Tegra BPMP driver"
15 depends on ARCH_TEGRA && TEGRA_HSP_MBOX && TEGRA_IVC
16 help
17 BPMP (Boot and Power Management Processor) is designed to off-loading
18 the PM functions which include clock/DVFS/thermal/power from the CPU.
19 It needs HSP as the HW synchronization and notification module and
20 IVC module as the message communication protocol.
21
22 This driver manages the IPC interface between host CPU and the
23 firmware running on BPMP.
24
13endmenu 25endmenu
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
index 92e2153e8173..e34a2f79e1ad 100644
--- a/drivers/firmware/tegra/Makefile
+++ b/drivers/firmware/tegra/Makefile
@@ -1 +1,2 @@
1obj-$(CONFIG_TEGRA_BPMP) += bpmp.o
1obj-$(CONFIG_TEGRA_IVC) += ivc.o 2obj-$(CONFIG_TEGRA_IVC) += ivc.o
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
new file mode 100644
index 000000000000..4ff02d310868
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp.c
@@ -0,0 +1,868 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include <linux/clk/tegra.h>
15#include <linux/genalloc.h>
16#include <linux/mailbox_client.h>
17#include <linux/of.h>
18#include <linux/of_address.h>
19#include <linux/of_device.h>
20#include <linux/platform_device.h>
21#include <linux/semaphore.h>
22
23#include <soc/tegra/bpmp.h>
24#include <soc/tegra/bpmp-abi.h>
25#include <soc/tegra/ivc.h>
26
27#define MSG_ACK BIT(0)
28#define MSG_RING BIT(1)
29
30static inline struct tegra_bpmp *
31mbox_client_to_bpmp(struct mbox_client *client)
32{
33 return container_of(client, struct tegra_bpmp, mbox.client);
34}
35
36struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
37{
38 struct platform_device *pdev;
39 struct tegra_bpmp *bpmp;
40 struct device_node *np;
41
42 np = of_parse_phandle(dev->of_node, "nvidia,bpmp", 0);
43 if (!np)
44 return ERR_PTR(-ENOENT);
45
46 pdev = of_find_device_by_node(np);
47 if (!pdev) {
48 bpmp = ERR_PTR(-ENODEV);
49 goto put;
50 }
51
52 bpmp = platform_get_drvdata(pdev);
53 if (!bpmp) {
54 bpmp = ERR_PTR(-EPROBE_DEFER);
55 put_device(&pdev->dev);
56 goto put;
57 }
58
59put:
60 of_node_put(np);
61 return bpmp;
62}
63EXPORT_SYMBOL_GPL(tegra_bpmp_get);
64
65void tegra_bpmp_put(struct tegra_bpmp *bpmp)
66{
67 if (bpmp)
68 put_device(bpmp->dev);
69}
70EXPORT_SYMBOL_GPL(tegra_bpmp_put);
71
72static int tegra_bpmp_channel_get_index(struct tegra_bpmp_channel *channel)
73{
74 return channel - channel->bpmp->channels;
75}
76
77static int
78tegra_bpmp_channel_get_thread_index(struct tegra_bpmp_channel *channel)
79{
80 struct tegra_bpmp *bpmp = channel->bpmp;
81 unsigned int offset, count;
82 int index;
83
84 offset = bpmp->soc->channels.thread.offset;
85 count = bpmp->soc->channels.thread.count;
86
87 index = tegra_bpmp_channel_get_index(channel);
88 if (index < 0)
89 return index;
90
91 if (index < offset || index >= offset + count)
92 return -EINVAL;
93
94 return index - offset;
95}
96
97static struct tegra_bpmp_channel *
98tegra_bpmp_channel_get_thread(struct tegra_bpmp *bpmp, unsigned int index)
99{
100 unsigned int offset = bpmp->soc->channels.thread.offset;
101 unsigned int count = bpmp->soc->channels.thread.count;
102
103 if (index >= count)
104 return NULL;
105
106 return &bpmp->channels[offset + index];
107}
108
109static struct tegra_bpmp_channel *
110tegra_bpmp_channel_get_tx(struct tegra_bpmp *bpmp)
111{
112 unsigned int offset = bpmp->soc->channels.cpu_tx.offset;
113
114 return &bpmp->channels[offset + smp_processor_id()];
115}
116
117static struct tegra_bpmp_channel *
118tegra_bpmp_channel_get_rx(struct tegra_bpmp *bpmp)
119{
120 unsigned int offset = bpmp->soc->channels.cpu_rx.offset;
121
122 return &bpmp->channels[offset];
123}
124
125static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
126{
127 return (msg->tx.size <= MSG_DATA_MIN_SZ) &&
128 (msg->rx.size <= MSG_DATA_MIN_SZ) &&
129 (msg->tx.size == 0 || msg->tx.data) &&
130 (msg->rx.size == 0 || msg->rx.data);
131}
132
133static bool tegra_bpmp_master_acked(struct tegra_bpmp_channel *channel)
134{
135 void *frame;
136
137 frame = tegra_ivc_read_get_next_frame(channel->ivc);
138 if (IS_ERR(frame)) {
139 channel->ib = NULL;
140 return false;
141 }
142
143 channel->ib = frame;
144
145 return true;
146}
147
148static int tegra_bpmp_wait_ack(struct tegra_bpmp_channel *channel)
149{
150 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
151 ktime_t end;
152
153 end = ktime_add_us(ktime_get(), timeout);
154
155 do {
156 if (tegra_bpmp_master_acked(channel))
157 return 0;
158 } while (ktime_before(ktime_get(), end));
159
160 return -ETIMEDOUT;
161}
162
163static bool tegra_bpmp_master_free(struct tegra_bpmp_channel *channel)
164{
165 void *frame;
166
167 frame = tegra_ivc_write_get_next_frame(channel->ivc);
168 if (IS_ERR(frame)) {
169 channel->ob = NULL;
170 return false;
171 }
172
173 channel->ob = frame;
174
175 return true;
176}
177
178static int tegra_bpmp_wait_master_free(struct tegra_bpmp_channel *channel)
179{
180 unsigned long timeout = channel->bpmp->soc->channels.cpu_tx.timeout;
181 ktime_t start, now;
182
183 start = ns_to_ktime(local_clock());
184
185 do {
186 if (tegra_bpmp_master_free(channel))
187 return 0;
188
189 now = ns_to_ktime(local_clock());
190 } while (ktime_us_delta(now, start) < timeout);
191
192 return -ETIMEDOUT;
193}
194
195static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
196 void *data, size_t size)
197{
198 if (data && size > 0)
199 memcpy(data, channel->ib->data, size);
200
201 return tegra_ivc_read_advance(channel->ivc);
202}
203
204static ssize_t tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
205 void *data, size_t size)
206{
207 struct tegra_bpmp *bpmp = channel->bpmp;
208 unsigned long flags;
209 ssize_t err;
210 int index;
211
212 index = tegra_bpmp_channel_get_thread_index(channel);
213 if (index < 0)
214 return index;
215
216 spin_lock_irqsave(&bpmp->lock, flags);
217 err = __tegra_bpmp_channel_read(channel, data, size);
218 clear_bit(index, bpmp->threaded.allocated);
219 spin_unlock_irqrestore(&bpmp->lock, flags);
220
221 up(&bpmp->threaded.lock);
222
223 return err;
224}
225
226static ssize_t __tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
227 unsigned int mrq, unsigned long flags,
228 const void *data, size_t size)
229{
230 channel->ob->code = mrq;
231 channel->ob->flags = flags;
232
233 if (data && size > 0)
234 memcpy(channel->ob->data, data, size);
235
236 return tegra_ivc_write_advance(channel->ivc);
237}
238
239static struct tegra_bpmp_channel *
240tegra_bpmp_write_threaded(struct tegra_bpmp *bpmp, unsigned int mrq,
241 const void *data, size_t size)
242{
243 unsigned long timeout = bpmp->soc->channels.thread.timeout;
244 unsigned int count = bpmp->soc->channels.thread.count;
245 struct tegra_bpmp_channel *channel;
246 unsigned long flags;
247 unsigned int index;
248 int err;
249
250 err = down_timeout(&bpmp->threaded.lock, usecs_to_jiffies(timeout));
251 if (err < 0)
252 return ERR_PTR(err);
253
254 spin_lock_irqsave(&bpmp->lock, flags);
255
256 index = find_first_zero_bit(bpmp->threaded.allocated, count);
257 if (index == count) {
258 channel = ERR_PTR(-EBUSY);
259 goto unlock;
260 }
261
262 channel = tegra_bpmp_channel_get_thread(bpmp, index);
263 if (!channel) {
264 channel = ERR_PTR(-EINVAL);
265 goto unlock;
266 }
267
268 if (!tegra_bpmp_master_free(channel)) {
269 channel = ERR_PTR(-EBUSY);
270 goto unlock;
271 }
272
273 set_bit(index, bpmp->threaded.allocated);
274
275 err = __tegra_bpmp_channel_write(channel, mrq, MSG_ACK | MSG_RING,
276 data, size);
277 if (err < 0) {
278 clear_bit(index, bpmp->threaded.allocated);
279 goto unlock;
280 }
281
282 set_bit(index, bpmp->threaded.busy);
283
284unlock:
285 spin_unlock_irqrestore(&bpmp->lock, flags);
286 return channel;
287}
288
289static ssize_t tegra_bpmp_channel_write(struct tegra_bpmp_channel *channel,
290 unsigned int mrq, unsigned long flags,
291 const void *data, size_t size)
292{
293 int err;
294
295 err = tegra_bpmp_wait_master_free(channel);
296 if (err < 0)
297 return err;
298
299 return __tegra_bpmp_channel_write(channel, mrq, flags, data, size);
300}
301
302int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
303 struct tegra_bpmp_message *msg)
304{
305 struct tegra_bpmp_channel *channel;
306 int err;
307
308 if (WARN_ON(!irqs_disabled()))
309 return -EPERM;
310
311 if (!tegra_bpmp_message_valid(msg))
312 return -EINVAL;
313
314 channel = tegra_bpmp_channel_get_tx(bpmp);
315
316 err = tegra_bpmp_channel_write(channel, msg->mrq, MSG_ACK,
317 msg->tx.data, msg->tx.size);
318 if (err < 0)
319 return err;
320
321 err = mbox_send_message(bpmp->mbox.channel, NULL);
322 if (err < 0)
323 return err;
324
325 mbox_client_txdone(bpmp->mbox.channel, 0);
326
327 err = tegra_bpmp_wait_ack(channel);
328 if (err < 0)
329 return err;
330
331 return __tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size);
332}
333EXPORT_SYMBOL_GPL(tegra_bpmp_transfer_atomic);
334
335int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
336 struct tegra_bpmp_message *msg)
337{
338 struct tegra_bpmp_channel *channel;
339 unsigned long timeout;
340 int err;
341
342 if (WARN_ON(irqs_disabled()))
343 return -EPERM;
344
345 if (!tegra_bpmp_message_valid(msg))
346 return -EINVAL;
347
348 channel = tegra_bpmp_write_threaded(bpmp, msg->mrq, msg->tx.data,
349 msg->tx.size);
350 if (IS_ERR(channel))
351 return PTR_ERR(channel);
352
353 err = mbox_send_message(bpmp->mbox.channel, NULL);
354 if (err < 0)
355 return err;
356
357 mbox_client_txdone(bpmp->mbox.channel, 0);
358
359 timeout = usecs_to_jiffies(bpmp->soc->channels.thread.timeout);
360
361 err = wait_for_completion_timeout(&channel->completion, timeout);
362 if (err == 0)
363 return -ETIMEDOUT;
364
365 return tegra_bpmp_channel_read(channel, msg->rx.data, msg->rx.size);
366}
367EXPORT_SYMBOL_GPL(tegra_bpmp_transfer);
368
369static struct tegra_bpmp_mrq *tegra_bpmp_find_mrq(struct tegra_bpmp *bpmp,
370 unsigned int mrq)
371{
372 struct tegra_bpmp_mrq *entry;
373
374 list_for_each_entry(entry, &bpmp->mrqs, list)
375 if (entry->mrq == mrq)
376 return entry;
377
378 return NULL;
379}
380
381static void tegra_bpmp_mrq_return(struct tegra_bpmp_channel *channel,
382 int code, const void *data, size_t size)
383{
384 unsigned long flags = channel->ib->flags;
385 struct tegra_bpmp *bpmp = channel->bpmp;
386 struct tegra_bpmp_mb_data *frame;
387 int err;
388
389 if (WARN_ON(size > MSG_DATA_MIN_SZ))
390 return;
391
392 err = tegra_ivc_read_advance(channel->ivc);
393 if (WARN_ON(err < 0))
394 return;
395
396 if ((flags & MSG_ACK) == 0)
397 return;
398
399 frame = tegra_ivc_write_get_next_frame(channel->ivc);
400 if (WARN_ON(IS_ERR(frame)))
401 return;
402
403 frame->code = code;
404
405 if (data && size > 0)
406 memcpy(frame->data, data, size);
407
408 err = tegra_ivc_write_advance(channel->ivc);
409 if (WARN_ON(err < 0))
410 return;
411
412 if (flags & MSG_RING) {
413 err = mbox_send_message(bpmp->mbox.channel, NULL);
414 if (WARN_ON(err < 0))
415 return;
416
417 mbox_client_txdone(bpmp->mbox.channel, 0);
418 }
419}
420
421static void tegra_bpmp_handle_mrq(struct tegra_bpmp *bpmp,
422 unsigned int mrq,
423 struct tegra_bpmp_channel *channel)
424{
425 struct tegra_bpmp_mrq *entry;
426 u32 zero = 0;
427
428 spin_lock(&bpmp->lock);
429
430 entry = tegra_bpmp_find_mrq(bpmp, mrq);
431 if (!entry) {
432 spin_unlock(&bpmp->lock);
433 tegra_bpmp_mrq_return(channel, -EINVAL, &zero, sizeof(zero));
434 return;
435 }
436
437 entry->handler(mrq, channel, entry->data);
438
439 spin_unlock(&bpmp->lock);
440}
441
442int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
443 tegra_bpmp_mrq_handler_t handler, void *data)
444{
445 struct tegra_bpmp_mrq *entry;
446 unsigned long flags;
447
448 if (!handler)
449 return -EINVAL;
450
451 entry = devm_kzalloc(bpmp->dev, sizeof(*entry), GFP_KERNEL);
452 if (!entry)
453 return -ENOMEM;
454
455 spin_lock_irqsave(&bpmp->lock, flags);
456
457 entry->mrq = mrq;
458 entry->handler = handler;
459 entry->data = data;
460 list_add(&entry->list, &bpmp->mrqs);
461
462 spin_unlock_irqrestore(&bpmp->lock, flags);
463
464 return 0;
465}
466EXPORT_SYMBOL_GPL(tegra_bpmp_request_mrq);
467
468void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq, void *data)
469{
470 struct tegra_bpmp_mrq *entry;
471 unsigned long flags;
472
473 spin_lock_irqsave(&bpmp->lock, flags);
474
475 entry = tegra_bpmp_find_mrq(bpmp, mrq);
476 if (!entry)
477 goto unlock;
478
479 list_del(&entry->list);
480 devm_kfree(bpmp->dev, entry);
481
482unlock:
483 spin_unlock_irqrestore(&bpmp->lock, flags);
484}
485EXPORT_SYMBOL_GPL(tegra_bpmp_free_mrq);
486
487static void tegra_bpmp_mrq_handle_ping(unsigned int mrq,
488 struct tegra_bpmp_channel *channel,
489 void *data)
490{
491 struct mrq_ping_request *request;
492 struct mrq_ping_response response;
493
494 request = (struct mrq_ping_request *)channel->ib->data;
495
496 memset(&response, 0, sizeof(response));
497 response.reply = request->challenge << 1;
498
499 tegra_bpmp_mrq_return(channel, 0, &response, sizeof(response));
500}
501
502static int tegra_bpmp_ping(struct tegra_bpmp *bpmp)
503{
504 struct mrq_ping_response response;
505 struct mrq_ping_request request;
506 struct tegra_bpmp_message msg;
507 unsigned long flags;
508 ktime_t start, end;
509 int err;
510
511 memset(&request, 0, sizeof(request));
512 request.challenge = 1;
513
514 memset(&response, 0, sizeof(response));
515
516 memset(&msg, 0, sizeof(msg));
517 msg.mrq = MRQ_PING;
518 msg.tx.data = &request;
519 msg.tx.size = sizeof(request);
520 msg.rx.data = &response;
521 msg.rx.size = sizeof(response);
522
523 local_irq_save(flags);
524 start = ktime_get();
525 err = tegra_bpmp_transfer_atomic(bpmp, &msg);
526 end = ktime_get();
527 local_irq_restore(flags);
528
529 if (!err)
530 dev_dbg(bpmp->dev,
531 "ping ok: challenge: %u, response: %u, time: %lld\n",
532 request.challenge, response.reply,
533 ktime_to_us(ktime_sub(end, start)));
534
535 return err;
536}
537
538static int tegra_bpmp_get_firmware_tag(struct tegra_bpmp *bpmp, char *tag,
539 size_t size)
540{
541 struct mrq_query_tag_request request;
542 struct tegra_bpmp_message msg;
543 unsigned long flags;
544 dma_addr_t phys;
545 void *virt;
546 int err;
547
548 virt = dma_alloc_coherent(bpmp->dev, MSG_DATA_MIN_SZ, &phys,
549 GFP_KERNEL | GFP_DMA32);
550 if (!virt)
551 return -ENOMEM;
552
553 memset(&request, 0, sizeof(request));
554 request.addr = phys;
555
556 memset(&msg, 0, sizeof(msg));
557 msg.mrq = MRQ_QUERY_TAG;
558 msg.tx.data = &request;
559 msg.tx.size = sizeof(request);
560
561 local_irq_save(flags);
562 err = tegra_bpmp_transfer_atomic(bpmp, &msg);
563 local_irq_restore(flags);
564
565 if (err == 0)
566 strlcpy(tag, virt, size);
567
568 dma_free_coherent(bpmp->dev, MSG_DATA_MIN_SZ, virt, phys);
569
570 return err;
571}
572
573static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
574{
575 unsigned long flags = channel->ob->flags;
576
577 if ((flags & MSG_RING) == 0)
578 return;
579
580 complete(&channel->completion);
581}
582
583static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
584{
585 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
586 struct tegra_bpmp_channel *channel;
587 unsigned int i, count;
588 unsigned long *busy;
589
590 channel = tegra_bpmp_channel_get_rx(bpmp);
591 count = bpmp->soc->channels.thread.count;
592 busy = bpmp->threaded.busy;
593
594 if (tegra_bpmp_master_acked(channel))
595 tegra_bpmp_handle_mrq(bpmp, channel->ib->code, channel);
596
597 spin_lock(&bpmp->lock);
598
599 for_each_set_bit(i, busy, count) {
600 struct tegra_bpmp_channel *channel;
601
602 channel = tegra_bpmp_channel_get_thread(bpmp, i);
603 if (!channel)
604 continue;
605
606 if (tegra_bpmp_master_acked(channel)) {
607 tegra_bpmp_channel_signal(channel);
608 clear_bit(i, busy);
609 }
610 }
611
612 spin_unlock(&bpmp->lock);
613}
614
615static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
616{
617 struct tegra_bpmp *bpmp = data;
618 int err;
619
620 if (WARN_ON(bpmp->mbox.channel == NULL))
621 return;
622
623 err = mbox_send_message(bpmp->mbox.channel, NULL);
624 if (err < 0)
625 return;
626
627 mbox_client_txdone(bpmp->mbox.channel, 0);
628}
629
630static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
631 struct tegra_bpmp *bpmp,
632 unsigned int index)
633{
634 size_t message_size, queue_size;
635 unsigned int offset;
636 int err;
637
638 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
639 GFP_KERNEL);
640 if (!channel->ivc)
641 return -ENOMEM;
642
643 message_size = tegra_ivc_align(MSG_MIN_SZ);
644 queue_size = tegra_ivc_total_queue_size(message_size);
645 offset = queue_size * index;
646
647 err = tegra_ivc_init(channel->ivc, NULL,
648 bpmp->rx.virt + offset, bpmp->rx.phys + offset,
649 bpmp->tx.virt + offset, bpmp->tx.phys + offset,
650 1, message_size, tegra_bpmp_ivc_notify,
651 bpmp);
652 if (err < 0) {
653 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
654 index, err);
655 return err;
656 }
657
658 init_completion(&channel->completion);
659 channel->bpmp = bpmp;
660
661 return 0;
662}
663
664static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
665{
666 /* reset the channel state */
667 tegra_ivc_reset(channel->ivc);
668
669 /* sync the channel state with BPMP */
670 while (tegra_ivc_notified(channel->ivc))
671 ;
672}
673
674static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
675{
676 tegra_ivc_cleanup(channel->ivc);
677}
678
679static int tegra_bpmp_probe(struct platform_device *pdev)
680{
681 struct tegra_bpmp_channel *channel;
682 struct tegra_bpmp *bpmp;
683 unsigned int i;
684 char tag[32];
685 size_t size;
686 int err;
687
688 bpmp = devm_kzalloc(&pdev->dev, sizeof(*bpmp), GFP_KERNEL);
689 if (!bpmp)
690 return -ENOMEM;
691
692 bpmp->soc = of_device_get_match_data(&pdev->dev);
693 bpmp->dev = &pdev->dev;
694
695 bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
696 if (!bpmp->tx.pool) {
697 dev_err(&pdev->dev, "TX shmem pool not found\n");
698 return -ENOMEM;
699 }
700
701 bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
702 if (!bpmp->tx.virt) {
703 dev_err(&pdev->dev, "failed to allocate from TX pool\n");
704 return -ENOMEM;
705 }
706
707 bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
708 if (!bpmp->rx.pool) {
709 dev_err(&pdev->dev, "RX shmem pool not found\n");
710 err = -ENOMEM;
711 goto free_tx;
712 }
713
714 bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
715 if (!bpmp->rx.pool) {
716 dev_err(&pdev->dev, "failed to allocate from RX pool\n");
717 err = -ENOMEM;
718 goto free_tx;
719 }
720
721 INIT_LIST_HEAD(&bpmp->mrqs);
722 spin_lock_init(&bpmp->lock);
723
724 bpmp->threaded.count = bpmp->soc->channels.thread.count;
725 sema_init(&bpmp->threaded.lock, bpmp->threaded.count);
726
727 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
728
729 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
730 if (!bpmp->threaded.allocated) {
731 err = -ENOMEM;
732 goto free_rx;
733 }
734
735 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
736 if (!bpmp->threaded.busy) {
737 err = -ENOMEM;
738 goto free_rx;
739 }
740
741 bpmp->num_channels = bpmp->soc->channels.cpu_tx.count +
742 bpmp->soc->channels.thread.count +
743 bpmp->soc->channels.cpu_rx.count;
744
745 bpmp->channels = devm_kcalloc(&pdev->dev, bpmp->num_channels,
746 sizeof(*channel), GFP_KERNEL);
747 if (!bpmp->channels) {
748 err = -ENOMEM;
749 goto free_rx;
750 }
751
752 /* message channel initialization */
753 for (i = 0; i < bpmp->num_channels; i++) {
754 struct tegra_bpmp_channel *channel = &bpmp->channels[i];
755
756 err = tegra_bpmp_channel_init(channel, bpmp, i);
757 if (err < 0)
758 goto cleanup_channels;
759 }
760
761 /* mbox registration */
762 bpmp->mbox.client.dev = &pdev->dev;
763 bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
764 bpmp->mbox.client.tx_block = false;
765 bpmp->mbox.client.knows_txdone = false;
766
767 bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
768 if (IS_ERR(bpmp->mbox.channel)) {
769 err = PTR_ERR(bpmp->mbox.channel);
770 dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
771 goto cleanup_channels;
772 }
773
774 /* reset message channels */
775 for (i = 0; i < bpmp->num_channels; i++) {
776 struct tegra_bpmp_channel *channel = &bpmp->channels[i];
777
778 tegra_bpmp_channel_reset(channel);
779 }
780
781 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
782 tegra_bpmp_mrq_handle_ping, bpmp);
783 if (err < 0)
784 goto free_mbox;
785
786 err = tegra_bpmp_ping(bpmp);
787 if (err < 0) {
788 dev_err(&pdev->dev, "failed to ping BPMP: %d\n", err);
789 goto free_mrq;
790 }
791
792 err = tegra_bpmp_get_firmware_tag(bpmp, tag, sizeof(tag) - 1);
793 if (err < 0) {
794 dev_err(&pdev->dev, "failed to get firmware tag: %d\n", err);
795 goto free_mrq;
796 }
797
798 dev_info(&pdev->dev, "firmware: %s\n", tag);
799
800 err = of_platform_default_populate(pdev->dev.of_node, NULL, &pdev->dev);
801 if (err < 0)
802 goto free_mrq;
803
804 err = tegra_bpmp_init_clocks(bpmp);
805 if (err < 0)
806 goto free_mrq;
807
808 err = tegra_bpmp_init_resets(bpmp);
809 if (err < 0)
810 goto free_mrq;
811
812 platform_set_drvdata(pdev, bpmp);
813
814 return 0;
815
816free_mrq:
817 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
818free_mbox:
819 mbox_free_channel(bpmp->mbox.channel);
820cleanup_channels:
821 while (i--)
822 tegra_bpmp_channel_cleanup(&bpmp->channels[i]);
823free_rx:
824 gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
825free_tx:
826 gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
827 return err;
828}
829
830static const struct tegra_bpmp_soc tegra186_soc = {
831 .channels = {
832 .cpu_tx = {
833 .offset = 0,
834 .count = 6,
835 .timeout = 60 * USEC_PER_SEC,
836 },
837 .thread = {
838 .offset = 6,
839 .count = 7,
840 .timeout = 600 * USEC_PER_SEC,
841 },
842 .cpu_rx = {
843 .offset = 13,
844 .count = 1,
845 .timeout = 0,
846 },
847 },
848 .num_resets = 193,
849};
850
851static const struct of_device_id tegra_bpmp_match[] = {
852 { .compatible = "nvidia,tegra186-bpmp", .data = &tegra186_soc },
853 { }
854};
855
856static struct platform_driver tegra_bpmp_driver = {
857 .driver = {
858 .name = "tegra-bpmp",
859 .of_match_table = tegra_bpmp_match,
860 },
861 .probe = tegra_bpmp_probe,
862};
863
864static int __init tegra_bpmp_init(void)
865{
866 return platform_driver_register(&tegra_bpmp_driver);
867}
868core_initcall(tegra_bpmp_init);
diff --git a/include/soc/tegra/bpmp-abi.h b/include/soc/tegra/bpmp-abi.h
new file mode 100644
index 000000000000..0aaef5960e29
--- /dev/null
+++ b/include/soc/tegra/bpmp-abi.h
@@ -0,0 +1,1601 @@
1/*
2 * Copyright (c) 2014-2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17#ifndef _ABI_BPMP_ABI_H_
18#define _ABI_BPMP_ABI_H_
19
20#ifdef LK
21#include <stdint.h>
22#endif
23
24#ifndef __ABI_PACKED
25#define __ABI_PACKED __attribute__((packed))
26#endif
27
28#ifdef NO_GCC_EXTENSIONS
29#define EMPTY char empty;
30#define EMPTY_ARRAY 1
31#else
32#define EMPTY
33#define EMPTY_ARRAY 0
34#endif
35
36#ifndef __UNION_ANON
37#define __UNION_ANON
38#endif
39/**
40 * @file
41 */
42
43
44/**
45 * @defgroup MRQ MRQ Messages
46 * @brief Messages sent to/from BPMP via IPC
47 * @{
48 * @defgroup MRQ_Format Message Format
49 * @defgroup MRQ_Codes Message Request (MRQ) Codes
50 * @defgroup MRQ_Payloads Message Payloads
51 * @defgroup Error_Codes Error Codes
52 * @}
53 */
54
55/**
56 * @addtogroup MRQ_Format Message Format
57 * @{
58 * The CPU requests the BPMP to perform a particular service by
59 * sending it an IVC frame containing a single MRQ message. An MRQ
60 * message consists of a @ref mrq_request followed by a payload whose
61 * format depends on mrq_request::mrq.
62 *
63 * The BPMP processes the data and replies with an IVC frame (on the
64 * same IVC channel) containing and MRQ response. An MRQ response
65 * consists of a @ref mrq_response followed by a payload whose format
66 * depends on the associated mrq_request::mrq.
67 *
68 * A well-defined subset of the MRQ messages that the CPU sends to the
69 * BPMP can lead to BPMP eventually sending an MRQ message to the
70 * CPU. For example, when the CPU uses an #MRQ_THERMAL message to set
71 * a thermal trip point, the BPMP may eventually send a single
72 * #MRQ_THERMAL message of its own to the CPU indicating that the trip
73 * point has been crossed.
74 * @}
75 */
76
77/**
78 * @ingroup MRQ_Format
79 * @brief header for an MRQ message
80 *
81 * Provides the MRQ number for the MRQ message: #mrq. The remainder of
82 * the MRQ message is a payload (immediately following the
83 * mrq_request) whose format depends on mrq.
84 *
85 * @todo document the flags
86 */
87struct mrq_request {
88 /** @brief MRQ number of the request */
89 uint32_t mrq;
90 /** @brief flags for the request */
91 uint32_t flags;
92} __ABI_PACKED;
93
94/**
95 * @ingroup MRQ_Format
96 * @brief header for an MRQ response
97 *
98 * Provides an error code for the associated MRQ message. The
99 * remainder of the MRQ response is a payload (immediately following
100 * the mrq_response) whose format depends on the associated
101 * mrq_request::mrq
102 *
103 * @todo document the flags
104 */
105struct mrq_response {
106 /** @brief error code for the MRQ request itself */
107 int32_t err;
108 /** @brief flags for the response */
109 uint32_t flags;
110} __ABI_PACKED;
111
112/**
113 * @ingroup MRQ_Format
114 * Minimum needed size for an IPC message buffer
115 */
116#define MSG_MIN_SZ 128
117/**
118 * @ingroup MRQ_Format
119 * Minimum size guaranteed for data in an IPC message buffer
120 */
121#define MSG_DATA_MIN_SZ 120
122
123/**
124 * @ingroup MRQ_Codes
125 * @name Legal MRQ codes
126 * These are the legal values for mrq_request::mrq
127 * @{
128 */
129
130#define MRQ_PING 0
131#define MRQ_QUERY_TAG 1
132#define MRQ_MODULE_LOAD 4
133#define MRQ_MODULE_UNLOAD 5
134#define MRQ_TRACE_MODIFY 7
135#define MRQ_WRITE_TRACE 8
136#define MRQ_THREADED_PING 9
137#define MRQ_MODULE_MAIL 11
138#define MRQ_DEBUGFS 19
139#define MRQ_RESET 20
140#define MRQ_I2C 21
141#define MRQ_CLK 22
142#define MRQ_QUERY_ABI 23
143#define MRQ_PG_READ_STATE 25
144#define MRQ_PG_UPDATE_STATE 26
145#define MRQ_THERMAL 27
146#define MRQ_CPU_VHINT 28
147#define MRQ_ABI_RATCHET 29
148#define MRQ_EMC_DVFS_LATENCY 31
149#define MRQ_TRACE_ITER 64
150
151/** @} */
152
153/**
154 * @ingroup MRQ_Codes
155 * @brief Maximum MRQ code to be sent by CPU software to
156 * BPMP. Subject to change in future
157 */
158#define MAX_CPU_MRQ_ID 64
159
160/**
161 * @addtogroup MRQ_Payloads Message Payloads
162 * @{
163 * @defgroup Ping
164 * @defgroup Query_Tag Query Tag
165 * @defgroup Module Loadable Modules
166 * @defgroup Trace
167 * @defgroup Debugfs
168 * @defgroup Reset
169 * @defgroup I2C
170 * @defgroup Clocks
171 * @defgroup ABI_info ABI Info
172 * @defgroup MC_Flush MC Flush
173 * @defgroup Powergating
174 * @defgroup Thermal
175 * @defgroup Vhint CPU Voltage hint
176 * @defgroup MRQ_Deprecated Deprecated MRQ messages
177 * @defgroup EMC
178 * @}
179 */
180
181
182/**
183 * @ingroup MRQ_Codes
184 * @def MRQ_PING
185 * @brief A simple ping
186 *
187 * * Platforms: All
188 * * Initiators: Any
189 * * Targets: Any
190 * * Request Payload: @ref mrq_ping_request
191 * * Response Payload: @ref mrq_ping_response
192 *
193 * @ingroup MRQ_Codes
194 * @def MRQ_THREADED_PING
195 * @brief A deeper ping
196 *
197 * * Platforms: All
198 * * Initiators: Any
199 * * Targets: BPMP
200 * * Request Payload: @ref mrq_ping_request
201 * * Response Payload: @ref mrq_ping_response
202 *
203 * Behavior is equivalent to a simple #MRQ_PING except that BPMP
204 * responds from a thread context (providing a slightly more robust
205 * sign of life).
206 *
207 */
208
209/**
210 * @ingroup Ping
211 * @brief request with #MRQ_PING
212 *
213 * Used by the sender of an #MRQ_PING message to request a pong from
214 * recipient. The response from the recipient is computed based on
215 * #challenge.
216 */
217struct mrq_ping_request {
218/** @brief arbitrarily chosen value */
219 uint32_t challenge;
220} __ABI_PACKED;
221
222/**
223 * @ingroup Ping
224 * @brief response to #MRQ_PING
225 *
226 * Sent in response to an #MRQ_PING message. #reply should be the
227 * mrq_ping_request challenge left shifted by 1 with the carry-bit
228 * dropped.
229 *
230 */
231struct mrq_ping_response {
232 /** @brief response to the MRQ_PING challege */
233 uint32_t reply;
234} __ABI_PACKED;
235
236/**
237 * @ingroup MRQ_Codes
238 * @def MRQ_QUERY_TAG
239 * @brief Query BPMP firmware's tag (i.e. version information)
240 *
241 * * Platforms: All
242 * * Initiators: CCPLEX
243 * * Targets: BPMP
244 * * Request Payload: @ref mrq_query_tag_request
245 * * Response Payload: N/A
246 *
247 */
248
249/**
250 * @ingroup Query_Tag
251 * @brief request with #MRQ_QUERY_TAG
252 *
253 * Used by #MRQ_QUERY_TAG call to ask BPMP to fill in the memory
254 * pointed by #addr with BPMP firmware header.
255 *
256 * The sender is reponsible for ensuring that #addr is mapped in to
257 * the recipient's address map.
258 */
259struct mrq_query_tag_request {
260 /** @brief base address to store the firmware header */
261 uint32_t addr;
262} __ABI_PACKED;
263
264/**
265 * @ingroup MRQ_Codes
266 * @def MRQ_MODULE_LOAD
267 * @brief dynamically load a BPMP code module
268 *
269 * * Platforms: All
270 * * Initiators: CCPLEX
271 * * Targets: BPMP
272 * * Request Payload: @ref mrq_module_load_request
273 * * Response Payload: @ref mrq_module_load_response
274 *
275 * @note This MRQ is disabled on production systems
276 *
277 */
278
279/**
280 * @ingroup Module
281 * @brief request with #MRQ_MODULE_LOAD
282 *
283 * Used by #MRQ_MODULE_LOAD calls to ask the recipient to dynamically
284 * load the code located at #phys_addr and having size #size
285 * bytes. #phys_addr is treated as a void pointer.
286 *
287 * The recipient copies the code from #phys_addr to locally allocated
288 * memory prior to responding to this message.
289 *
290 * @todo document the module header format
291 *
292 * The sender is responsible for ensuring that the code is mapped in
293 * the recipient's address map.
294 *
295 */
296struct mrq_module_load_request {
297 /** @brief base address of the code to load. Treated as (void *) */
298 uint32_t phys_addr; /* (void *) */
299 /** @brief size in bytes of code to load */
300 uint32_t size;
301} __ABI_PACKED;
302
303/**
304 * @ingroup Module
305 * @brief response to #MRQ_MODULE_LOAD
306 *
307 * @todo document mrq_response::err
308 */
309struct mrq_module_load_response {
310 /** @brief handle to the loaded module */
311 uint32_t base;
312} __ABI_PACKED;
313
314/**
315 * @ingroup MRQ_Codes
316 * @def MRQ_MODULE_UNLOAD
317 * @brief unload a previously loaded code module
318 *
319 * * Platforms: All
320 * * Initiators: CCPLEX
321 * * Targets: BPMP
322 * * Request Payload: @ref mrq_module_unload_request
323 * * Response Payload: N/A
324 *
325 * @note This MRQ is disabled on production systems
326 */
327
328/**
329 * @ingroup Module
330 * @brief request with #MRQ_MODULE_UNLOAD
331 *
332 * Used by #MRQ_MODULE_UNLOAD calls to request that a previously loaded
333 * module be unloaded.
334 */
335struct mrq_module_unload_request {
336 /** @brief handle of the module to unload */
337 uint32_t base;
338} __ABI_PACKED;
339
340/**
341 * @ingroup MRQ_Codes
342 * @def MRQ_TRACE_MODIFY
343 * @brief modify the set of enabled trace events
344 *
345 * * Platforms: All
346 * * Initiators: CCPLEX
347 * * Targets: BPMP
348 * * Request Payload: @ref mrq_trace_modify_request
349 * * Response Payload: @ref mrq_trace_modify_response
350 *
351 * @note This MRQ is disabled on production systems
352 */
353
354/**
355 * @ingroup Trace
356 * @brief request with #MRQ_TRACE_MODIFY
357 *
358 * Used by %MRQ_TRACE_MODIFY calls to enable or disable specify trace
359 * events. #set takes precedence for any bit set in both #set and
360 * #clr.
361 */
362struct mrq_trace_modify_request {
363 /** @brief bit mask of trace events to disable */
364 uint32_t clr;
365 /** @brief bit mask of trace events to enable */
366 uint32_t set;
367} __ABI_PACKED;
368
369/**
370 * @ingroup Trace
371 * @brief response to #MRQ_TRACE_MODIFY
372 *
373 * Sent in repsonse to an #MRQ_TRACE_MODIFY message. #mask reflects the
374 * state of which events are enabled after the recipient acted on the
375 * message.
376 *
377 */
378struct mrq_trace_modify_response {
379 /** @brief bit mask of trace event enable states */
380 uint32_t mask;
381} __ABI_PACKED;
382
383/**
384 * @ingroup MRQ_Codes
385 * @def MRQ_WRITE_TRACE
386 * @brief Write trace data to a buffer
387 *
388 * * Platforms: All
389 * * Initiators: CCPLEX
390 * * Targets: BPMP
391 * * Request Payload: @ref mrq_write_trace_request
392 * * Response Payload: @ref mrq_write_trace_response
393 *
394 * mrq_response::err depends on the @ref mrq_write_trace_request field
395 * values. err is -#BPMP_EINVAL if size is zero or area is NULL or
396 * area is in an illegal range. A positive value for err indicates the
397 * number of bytes written to area.
398 *
399 * @note This MRQ is disabled on production systems
400 */
401
402/**
403 * @ingroup Trace
404 * @brief request with #MRQ_WRITE_TRACE
405 *
406 * Used by MRQ_WRITE_TRACE calls to ask the recipient to copy trace
407 * data from the recipient's local buffer to the output buffer. #area
408 * is treated as a byte-aligned pointer in the recipient's address
409 * space.
410 *
411 * The sender is responsible for ensuring that the output
412 * buffer is mapped in the recipient's address map. The recipient is
413 * responsible for protecting its own code and data from accidental
414 * overwrites.
415 */
416struct mrq_write_trace_request {
417 /** @brief base address of output buffer */
418 uint32_t area;
419 /** @brief size in bytes of the output buffer */
420 uint32_t size;
421} __ABI_PACKED;
422
423/**
424 * @ingroup Trace
425 * @brief response to #MRQ_WRITE_TRACE
426 *
427 * Once this response is sent, the respondent will not access the
428 * output buffer further.
429 */
430struct mrq_write_trace_response {
431 /**
432 * @brief flag whether more data remains in local buffer
433 *
434 * Value is 1 if the entire local trace buffer has been
435 * drained to the outputbuffer. Value is 0 otherwise.
436 */
437 uint32_t eof;
438} __ABI_PACKED;
439
440/** @private */
441struct mrq_threaded_ping_request {
442 uint32_t challenge;
443} __ABI_PACKED;
444
445/** @private */
446struct mrq_threaded_ping_response {
447 uint32_t reply;
448} __ABI_PACKED;
449
450/**
451 * @ingroup MRQ_Codes
452 * @def MRQ_MODULE_MAIL
453 * @brief send a message to a loadable module
454 *
455 * * Platforms: All
456 * * Initiators: Any
457 * * Targets: BPMP
458 * * Request Payload: @ref mrq_module_mail_request
459 * * Response Payload: @ref mrq_module_mail_response
460 *
461 * @note This MRQ is disabled on production systems
462 */
463
464/**
465 * @ingroup Module
466 * @brief request with #MRQ_MODULE_MAIL
467 */
468struct mrq_module_mail_request {
469 /** @brief handle to the previously loaded module */
470 uint32_t base;
471 /** @brief module-specific mail payload
472 *
473 * The length of data[ ] is unknown to the BPMP core firmware
474 * but it is limited to the size of an IPC message.
475 */
476 uint8_t data[EMPTY_ARRAY];
477} __ABI_PACKED;
478
479/**
480 * @ingroup Module
481 * @brief response to #MRQ_MODULE_MAIL
482 */
483struct mrq_module_mail_response {
484 /** @brief module-specific mail payload
485 *
486 * The length of data[ ] is unknown to the BPMP core firmware
487 * but it is limited to the size of an IPC message.
488 */
489 uint8_t data[EMPTY_ARRAY];
490} __ABI_PACKED;
491
492/**
493 * @ingroup MRQ_Codes
494 * @def MRQ_DEBUGFS
495 * @brief Interact with BPMP's debugfs file nodes
496 *
497 * * Platforms: T186
498 * * Initiators: Any
499 * * Targets: BPMP
500 * * Request Payload: @ref mrq_debugfs_request
501 * * Response Payload: @ref mrq_debugfs_response
502 */
503
504/**
505 * @addtogroup Debugfs
506 * @{
507 *
508 * The BPMP firmware implements a pseudo-filesystem called
509 * debugfs. Any driver within the firmware may register with debugfs
510 * to expose an arbitrary set of "files" in the filesystem. When
511 * software on the CPU writes to a debugfs file, debugfs passes the
512 * written data to a callback provided by the driver. When software on
513 * the CPU reads a debugfs file, debugfs queries the driver for the
514 * data to return to the CPU. The intention of the debugfs filesystem
515 * is to provide information useful for debugging the system at
516 * runtime.
517 *
518 * @note The files exposed via debugfs are not part of the
519 * BPMP firmware's ABI. debugfs files may be added or removed in any
520 * given version of the firmware. Typically the semantics of a debugfs
521 * file are consistent from version to version but even that is not
522 * guaranteed.
523 *
524 * @}
525 */
526/** @ingroup Debugfs */
527enum mrq_debugfs_commands {
528 CMD_DEBUGFS_READ = 1,
529 CMD_DEBUGFS_WRITE = 2,
530 CMD_DEBUGFS_DUMPDIR = 3,
531 CMD_DEBUGFS_MAX
532};
533
534/**
535 * @ingroup Debugfs
536 * @brief parameters for CMD_DEBUGFS_READ/WRITE command
537 */
538struct cmd_debugfs_fileop_request {
539 /** @brief physical address pointing at filename */
540 uint32_t fnameaddr;
541 /** @brief length in bytes of filename buffer */
542 uint32_t fnamelen;
543 /** @brief physical address pointing to data buffer */
544 uint32_t dataaddr;
545 /** @brief length in bytes of data buffer */
546 uint32_t datalen;
547} __ABI_PACKED;
548
549/**
550 * @ingroup Debugfs
551 * @brief parameters for CMD_DEBUGFS_READ/WRITE command
552 */
553struct cmd_debugfs_dumpdir_request {
554 /** @brief physical address pointing to data buffer */
555 uint32_t dataaddr;
556 /** @brief length in bytes of data buffer */
557 uint32_t datalen;
558} __ABI_PACKED;
559
560/**
561 * @ingroup Debugfs
562 * @brief response data for CMD_DEBUGFS_READ/WRITE command
563 */
564struct cmd_debugfs_fileop_response {
565 /** @brief always 0 */
566 uint32_t reserved;
567 /** @brief number of bytes read from or written to data buffer */
568 uint32_t nbytes;
569} __ABI_PACKED;
570
571/**
572 * @ingroup Debugfs
573 * @brief response data for CMD_DEBUGFS_DUMPDIR command
574 */
575struct cmd_debugfs_dumpdir_response {
576 /** @brief always 0 */
577 uint32_t reserved;
578 /** @brief number of bytes read from or written to data buffer */
579 uint32_t nbytes;
580} __ABI_PACKED;
581
582/**
583 * @ingroup Debugfs
584 * @brief request with #MRQ_DEBUGFS.
585 *
586 * The sender of an MRQ_DEBUGFS message uses #cmd to specify a debugfs
587 * command to execute. Legal commands are the values of @ref
588 * mrq_debugfs_commands. Each command requires a specific additional
589 * payload of data.
590 *
591 * |command |payload|
592 * |-------------------|-------|
593 * |CMD_DEBUGFS_READ |fop |
594 * |CMD_DEBUGFS_WRITE |fop |
595 * |CMD_DEBUGFS_DUMPDIR|dumpdir|
596 */
597struct mrq_debugfs_request {
598 uint32_t cmd;
599 union {
600 struct cmd_debugfs_fileop_request fop;
601 struct cmd_debugfs_dumpdir_request dumpdir;
602 } __UNION_ANON;
603} __ABI_PACKED;
604
605/**
606 * @ingroup Debugfs
607 */
608struct mrq_debugfs_response {
609 /** @brief always 0 */
610 int32_t reserved;
611 union {
612 /** @brief response data for CMD_DEBUGFS_READ OR
613 * CMD_DEBUGFS_WRITE command
614 */
615 struct cmd_debugfs_fileop_response fop;
616 /** @brief response data for CMD_DEBUGFS_DUMPDIR command */
617 struct cmd_debugfs_dumpdir_response dumpdir;
618 } __UNION_ANON;
619} __ABI_PACKED;
620
621/**
622 * @addtogroup Debugfs
623 * @{
624 */
625#define DEBUGFS_S_ISDIR (1 << 9)
626#define DEBUGFS_S_IRUSR (1 << 8)
627#define DEBUGFS_S_IWUSR (1 << 7)
628/** @} */
629
630
631/**
632 * @ingroup MRQ_Codes
633 * @def MRQ_RESET
634 * @brief reset an IP block
635 *
636 * * Platforms: T186
637 * * Initiators: Any
638 * * Targets: BPMP
639 * * Request Payload: @ref mrq_reset_request
640 * * Response Payload: N/A
641 */
642
643/**
644 * @ingroup Reset
645 */
646enum mrq_reset_commands {
647 CMD_RESET_ASSERT = 1,
648 CMD_RESET_DEASSERT = 2,
649 CMD_RESET_MODULE = 3,
650 CMD_RESET_MAX, /* not part of ABI and subject to change */
651};
652
653/**
654 * @ingroup Reset
655 * @brief request with MRQ_RESET
656 *
657 * Used by the sender of an #MRQ_RESET message to request BPMP to
658 * assert or or deassert a given reset line.
659 */
660struct mrq_reset_request {
661 /** @brief reset action to perform (@enum mrq_reset_commands) */
662 uint32_t cmd;
663 /** @brief id of the reset to affected */
664 uint32_t reset_id;
665} __ABI_PACKED;
666
667/**
668 * @ingroup MRQ_Codes
669 * @def MRQ_I2C
670 * @brief issue an i2c transaction
671 *
672 * * Platforms: T186
673 * * Initiators: Any
674 * * Targets: BPMP
675 * * Request Payload: @ref mrq_i2c_request
676 * * Response Payload: @ref mrq_i2c_response
677 */
678
679/**
680 * @addtogroup I2C
681 * @{
682 */
683#define TEGRA_I2C_IPC_MAX_IN_BUF_SIZE (MSG_DATA_MIN_SZ - 12)
684#define TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE (MSG_DATA_MIN_SZ - 4)
685/** @} */
686
687/**
688 * @ingroup I2C
689 * @name Serial I2C flags
690 * Use these flags with serial_i2c_request::flags
691 * @{
692 */
693#define SERIALI2C_TEN 0x0010
694#define SERIALI2C_RD 0x0001
695#define SERIALI2C_STOP 0x8000
696#define SERIALI2C_NOSTART 0x4000
697#define SERIALI2C_REV_DIR_ADDR 0x2000
698#define SERIALI2C_IGNORE_NAK 0x1000
699#define SERIALI2C_NO_RD_ACK 0x0800
700#define SERIALI2C_RECV_LEN 0x0400
701/** @} */
702/** @ingroup I2C */
703enum {
704 CMD_I2C_XFER = 1
705};
706
707/**
708 * @ingroup I2C
709 * @brief serializable i2c request
710 *
711 * Instances of this structure are packed (little-endian) into
712 * cmd_i2c_xfer_request::data_buf. Each instance represents a single
713 * transaction (or a portion of a transaction with repeated starts) on
714 * an i2c bus.
715 *
716 * Because these structures are packed, some instances are likely to
717 * be misaligned. Additionally because #data is variable length, it is
718 * not possible to iterate through a serialized list of these
719 * structures without inspecting #len in each instance. It may be
720 * easier to serialize or deserialize cmd_i2c_xfer_request::data_buf
721 * manually rather than using this structure definition.
722*/
723struct serial_i2c_request {
724 /** @brief I2C slave address */
725 uint16_t addr;
726 /** @brief bitmask of SERIALI2C_ flags */
727 uint16_t flags;
728 /** @brief length of I2C transaction in bytes */
729 uint16_t len;
730 /** @brief for write transactions only, #len bytes of data */
731 uint8_t data[];
732} __ABI_PACKED;
733
734/**
735 * @ingroup I2C
736 * @brief trigger one or more i2c transactions
737 */
738struct cmd_i2c_xfer_request {
739 /** @brief valid bus number from mach-t186/i2c-t186.h*/
740 uint32_t bus_id;
741
742 /** @brief count of valid bytes in #data_buf*/
743 uint32_t data_size;
744
745 /** @brief serialized packed instances of @ref serial_i2c_request*/
746 uint8_t data_buf[TEGRA_I2C_IPC_MAX_IN_BUF_SIZE];
747} __ABI_PACKED;
748
749/**
750 * @ingroup I2C
751 * @brief container for data read from the i2c bus
752 *
753 * Processing an cmd_i2c_xfer_request::data_buf causes BPMP to execute
754 * zero or more I2C reads. The data read from the bus is serialized
755 * into #data_buf.
756 */
757struct cmd_i2c_xfer_response {
758 /** @brief count of valid bytes in #data_buf*/
759 uint32_t data_size;
760 /** @brief i2c read data */
761 uint8_t data_buf[TEGRA_I2C_IPC_MAX_OUT_BUF_SIZE];
762} __ABI_PACKED;
763
764/**
765 * @ingroup I2C
766 * @brief request with #MRQ_I2C
767 */
768struct mrq_i2c_request {
769 /** @brief always CMD_I2C_XFER (i.e. 1) */
770 uint32_t cmd;
771 /** @brief parameters of the transfer request */
772 struct cmd_i2c_xfer_request xfer;
773} __ABI_PACKED;
774
775/**
776 * @ingroup I2C
777 * @brief response to #MRQ_I2C
778 */
779struct mrq_i2c_response {
780 struct cmd_i2c_xfer_response xfer;
781} __ABI_PACKED;
782
783/**
784 * @ingroup MRQ_Codes
785 * @def MRQ_CLK
786 *
787 * * Platforms: T186
788 * * Initiators: Any
789 * * Targets: BPMP
790 * * Request Payload: @ref mrq_clk_request
791 * * Response Payload: @ref mrq_clk_response
792 * @addtogroup Clocks
793 * @{
794 */
795
796/**
797 * @name MRQ_CLK sub-commands
798 * @{
799 */
800enum {
801 CMD_CLK_GET_RATE = 1,
802 CMD_CLK_SET_RATE = 2,
803 CMD_CLK_ROUND_RATE = 3,
804 CMD_CLK_GET_PARENT = 4,
805 CMD_CLK_SET_PARENT = 5,
806 CMD_CLK_IS_ENABLED = 6,
807 CMD_CLK_ENABLE = 7,
808 CMD_CLK_DISABLE = 8,
809 CMD_CLK_GET_ALL_INFO = 14,
810 CMD_CLK_GET_MAX_CLK_ID = 15,
811 CMD_CLK_MAX,
812};
813/** @} */
814
815#define MRQ_CLK_NAME_MAXLEN 40
816#define MRQ_CLK_MAX_PARENTS 16
817
818/** @private */
819struct cmd_clk_get_rate_request {
820 EMPTY
821} __ABI_PACKED;
822
823struct cmd_clk_get_rate_response {
824 int64_t rate;
825} __ABI_PACKED;
826
827struct cmd_clk_set_rate_request {
828 int32_t unused;
829 int64_t rate;
830} __ABI_PACKED;
831
832struct cmd_clk_set_rate_response {
833 int64_t rate;
834} __ABI_PACKED;
835
836struct cmd_clk_round_rate_request {
837 int32_t unused;
838 int64_t rate;
839} __ABI_PACKED;
840
841struct cmd_clk_round_rate_response {
842 int64_t rate;
843} __ABI_PACKED;
844
845/** @private */
846struct cmd_clk_get_parent_request {
847 EMPTY
848} __ABI_PACKED;
849
850struct cmd_clk_get_parent_response {
851 uint32_t parent_id;
852} __ABI_PACKED;
853
854struct cmd_clk_set_parent_request {
855 uint32_t parent_id;
856} __ABI_PACKED;
857
858struct cmd_clk_set_parent_response {
859 uint32_t parent_id;
860} __ABI_PACKED;
861
862/** @private */
863struct cmd_clk_is_enabled_request {
864 EMPTY
865} __ABI_PACKED;
866
867struct cmd_clk_is_enabled_response {
868 int32_t state;
869} __ABI_PACKED;
870
871/** @private */
872struct cmd_clk_enable_request {
873 EMPTY
874} __ABI_PACKED;
875
876/** @private */
877struct cmd_clk_enable_response {
878 EMPTY
879} __ABI_PACKED;
880
881/** @private */
882struct cmd_clk_disable_request {
883 EMPTY
884} __ABI_PACKED;
885
886/** @private */
887struct cmd_clk_disable_response {
888 EMPTY
889} __ABI_PACKED;
890
891/** @private */
892struct cmd_clk_get_all_info_request {
893 EMPTY
894} __ABI_PACKED;
895
896struct cmd_clk_get_all_info_response {
897 uint32_t flags;
898 uint32_t parent;
899 uint32_t parents[MRQ_CLK_MAX_PARENTS];
900 uint8_t num_parents;
901 uint8_t name[MRQ_CLK_NAME_MAXLEN];
902} __ABI_PACKED;
903
904/** @private */
905struct cmd_clk_get_max_clk_id_request {
906 EMPTY
907} __ABI_PACKED;
908
909struct cmd_clk_get_max_clk_id_response {
910 uint32_t max_id;
911} __ABI_PACKED;
912/** @} */
913
914/**
915 * @ingroup Clocks
916 * @brief request with #MRQ_CLK
917 *
918 * Used by the sender of an #MRQ_CLK message to control clocks. The
919 * clk_request is split into several sub-commands. Some sub-commands
920 * require no additional data. Others have a sub-command specific
921 * payload
922 *
923 * |sub-command |payload |
924 * |----------------------------|-----------------------|
925 * |CMD_CLK_GET_RATE |- |
926 * |CMD_CLK_SET_RATE |clk_set_rate |
927 * |CMD_CLK_ROUND_RATE |clk_round_rate |
928 * |CMD_CLK_GET_PARENT |- |
929 * |CMD_CLK_SET_PARENT |clk_set_parent |
930 * |CMD_CLK_IS_ENABLED |- |
931 * |CMD_CLK_ENABLE |- |
932 * |CMD_CLK_DISABLE |- |
933 * |CMD_CLK_GET_ALL_INFO |- |
934 * |CMD_CLK_GET_MAX_CLK_ID |- |
935 *
936 */
937
938struct mrq_clk_request {
939 /** @brief sub-command and clock id concatenated to 32-bit word.
940 * - bits[31..24] is the sub-cmd.
941 * - bits[23..0] is the clock id
942 */
943 uint32_t cmd_and_id;
944
945 union {
946 /** @private */
947 struct cmd_clk_get_rate_request clk_get_rate;
948 struct cmd_clk_set_rate_request clk_set_rate;
949 struct cmd_clk_round_rate_request clk_round_rate;
950 /** @private */
951 struct cmd_clk_get_parent_request clk_get_parent;
952 struct cmd_clk_set_parent_request clk_set_parent;
953 /** @private */
954 struct cmd_clk_enable_request clk_enable;
955 /** @private */
956 struct cmd_clk_disable_request clk_disable;
957 /** @private */
958 struct cmd_clk_is_enabled_request clk_is_enabled;
959 /** @private */
960 struct cmd_clk_get_all_info_request clk_get_all_info;
961 /** @private */
962 struct cmd_clk_get_max_clk_id_request clk_get_max_clk_id;
963 } __UNION_ANON;
964} __ABI_PACKED;
965
966/**
967 * @ingroup Clocks
968 * @brief response to MRQ_CLK
969 *
970 * Each sub-command supported by @ref mrq_clk_request may return
971 * sub-command-specific data. Some do and some do not as indicated in
972 * the following table
973 *
974 * |sub-command |payload |
975 * |----------------------------|------------------------|
976 * |CMD_CLK_GET_RATE |clk_get_rate |
977 * |CMD_CLK_SET_RATE |clk_set_rate |
978 * |CMD_CLK_ROUND_RATE |clk_round_rate |
979 * |CMD_CLK_GET_PARENT |clk_get_parent |
980 * |CMD_CLK_SET_PARENT |clk_set_parent |
981 * |CMD_CLK_IS_ENABLED |clk_is_enabled |
982 * |CMD_CLK_ENABLE |- |
983 * |CMD_CLK_DISABLE |- |
984 * |CMD_CLK_GET_ALL_INFO |clk_get_all_info |
985 * |CMD_CLK_GET_MAX_CLK_ID |clk_get_max_id |
986 *
987 */
988
989struct mrq_clk_response {
990 union {
991 struct cmd_clk_get_rate_response clk_get_rate;
992 struct cmd_clk_set_rate_response clk_set_rate;
993 struct cmd_clk_round_rate_response clk_round_rate;
994 struct cmd_clk_get_parent_response clk_get_parent;
995 struct cmd_clk_set_parent_response clk_set_parent;
996 /** @private */
997 struct cmd_clk_enable_response clk_enable;
998 /** @private */
999 struct cmd_clk_disable_response clk_disable;
1000 struct cmd_clk_is_enabled_response clk_is_enabled;
1001 struct cmd_clk_get_all_info_response clk_get_all_info;
1002 struct cmd_clk_get_max_clk_id_response clk_get_max_clk_id;
1003 } __UNION_ANON;
1004} __ABI_PACKED;
1005
1006/**
1007 * @ingroup MRQ_Codes
1008 * @def MRQ_QUERY_ABI
1009 * @brief check if an MRQ is implemented
1010 *
1011 * * Platforms: All
1012 * * Initiators: Any
1013 * * Targets: Any
1014 * * Request Payload: @ref mrq_query_abi_request
1015 * * Response Payload: @ref mrq_query_abi_response
1016 */
1017
1018/**
1019 * @ingroup ABI_info
1020 * @brief request with MRQ_QUERY_ABI
1021 *
1022 * Used by #MRQ_QUERY_ABI call to check if MRQ code #mrq is supported
1023 * by the recipient.
1024 */
1025struct mrq_query_abi_request {
1026 /** @brief MRQ code to query */
1027 uint32_t mrq;
1028} __ABI_PACKED;
1029
1030/**
1031 * @ingroup ABI_info
1032 * @brief response to MRQ_QUERY_ABI
1033 */
1034struct mrq_query_abi_response {
1035 /** @brief 0 if queried MRQ is supported. Else, -#BPMP_ENODEV */
1036 int32_t status;
1037} __ABI_PACKED;
1038
1039/**
1040 * @ingroup MRQ_Codes
1041 * @def MRQ_PG_READ_STATE
1042 * @brief read the power-gating state of a partition
1043 *
1044 * * Platforms: T186
1045 * * Initiators: Any
1046 * * Targets: BPMP
1047 * * Request Payload: @ref mrq_pg_read_state_request
1048 * * Response Payload: @ref mrq_pg_read_state_response
1049 * @addtogroup Powergating
1050 * @{
1051 */
1052
1053/**
1054 * @brief request with #MRQ_PG_READ_STATE
1055 *
1056 * Used by MRQ_PG_READ_STATE call to read the current state of a
1057 * partition.
1058 */
1059struct mrq_pg_read_state_request {
1060 /** @brief ID of partition */
1061 uint32_t partition_id;
1062} __ABI_PACKED;
1063
1064/**
1065 * @brief response to MRQ_PG_READ_STATE
1066 * @todo define possible errors.
1067 */
1068struct mrq_pg_read_state_response {
1069 /** @brief read as don't care */
1070 uint32_t sram_state;
1071 /** @brief state of power partition
1072 * * 0 : off
1073 * * 1 : on
1074 */
1075 uint32_t logic_state;
1076} __ABI_PACKED;
1077
1078/** @} */
1079
1080/**
1081 * @ingroup MRQ_Codes
1082 * @def MRQ_PG_UPDATE_STATE
1083 * @brief modify the power-gating state of a partition
1084 *
1085 * * Platforms: T186
1086 * * Initiators: Any
1087 * * Targets: BPMP
1088 * * Request Payload: @ref mrq_pg_update_state_request
1089 * * Response Payload: N/A
1090 * @addtogroup Powergating
1091 * @{
1092 */
1093
1094/**
1095 * @brief request with mrq_pg_update_state_request
1096 *
1097 * Used by #MRQ_PG_UPDATE_STATE call to request BPMP to change the
1098 * state of a power partition #partition_id.
1099 */
1100struct mrq_pg_update_state_request {
1101 /** @brief ID of partition */
1102 uint32_t partition_id;
1103 /** @brief secondary control of power partition
1104 * @details Ignored by many versions of the BPMP
1105 * firmware. For maximum compatibility, set the value
1106 * according to @logic_state
1107 * * 0x1: power ON partition (@ref logic_state == 0x3)
1108 * * 0x3: power OFF partition (@ref logic_state == 0x1)
1109 */
1110 uint32_t sram_state;
1111 /** @brief controls state of power partition, legal values are
1112 * * 0x1 : power OFF partition
1113 * * 0x3 : power ON partition
1114 */
1115 uint32_t logic_state;
1116 /** @brief change state of clocks of the power partition, legal values
1117 * * 0x0 : do not change clock state
1118 * * 0x1 : disable partition clocks (only applicable when
1119 * @ref logic_state == 0x1)
1120 * * 0x3 : enable partition clocks (only applicable when
1121 * @ref logic_state == 0x3)
1122 */
1123 uint32_t clock_state;
1124} __ABI_PACKED;
1125/** @} */
1126
1127/**
1128 * @ingroup MRQ_Codes
1129 * @def MRQ_THERMAL
1130 * @brief interact with BPMP thermal framework
1131 *
1132 * * Platforms: T186
1133 * * Initiators: Any
1134 * * Targets: Any
1135 * * Request Payload: TODO
1136 * * Response Payload: TODO
1137 *
1138 * @addtogroup Thermal
1139 *
1140 * The BPMP firmware includes a thermal framework. Drivers within the
1141 * bpmp firmware register with the framework to provide thermal
1142 * zones. Each thermal zone corresponds to an entity whose temperature
1143 * can be measured. The framework also has a notion of trip points. A
1144 * trip point consists of a thermal zone id, a temperature, and a
1145 * callback routine. The framework invokes the callback when the zone
1146 * hits the indicated temperature. The BPMP firmware uses this thermal
1147 * framework interally to implement various temperature-dependent
1148 * functions.
1149 *
1150 * Software on the CPU can use #MRQ_THERMAL (with payload @ref
1151 * mrq_thermal_host_to_bpmp_request) to interact with the BPMP thermal
1152 * framework. The CPU must It can query the number of supported zones,
1153 * query zone temperatures, and set trip points.
1154 *
1155 * When a trip point set by the CPU gets crossed, BPMP firmware issues
1156 * an IPC to the CPU having mrq_request::mrq = #MRQ_THERMAL and a
1157 * payload of @ref mrq_thermal_bpmp_to_host_request.
1158 * @{
1159 */
1160enum mrq_thermal_host_to_bpmp_cmd {
1161 /**
1162 * @brief Check whether the BPMP driver supports the specified
1163 * request type.
1164 *
1165 * Host needs to supply request parameters.
1166 *
1167 * mrq_response::err is 0 if the specified request is
1168 * supported and -#BPMP_ENODEV otherwise.
1169 */
1170 CMD_THERMAL_QUERY_ABI = 0,
1171
1172 /**
1173 * @brief Get the current temperature of the specified zone.
1174 *
1175 * Host needs to supply request parameters.
1176 *
1177 * mrq_response::err is
1178 * * 0: Temperature query succeeded.
1179 * * -#BPMP_EINVAL: Invalid request parameters.
1180 * * -#BPMP_ENOENT: No driver registered for thermal zone..
1181 * * -#BPMP_EFAULT: Problem reading temperature measurement.
1182 */
1183 CMD_THERMAL_GET_TEMP = 1,
1184
1185 /**
1186 * @brief Enable or disable and set the lower and upper
1187 * thermal limits for a thermal trip point. Each zone has
1188 * one trip point.
1189 *
1190 * Host needs to supply request parameters. Once the
1191 * temperature hits a trip point, the BPMP will send a message
1192 * to the CPU having MRQ=MRQ_THERMAL and
1193 * type=CMD_THERMAL_HOST_TRIP_REACHED
1194 *
1195 * mrq_response::err is
1196 * * 0: Trip successfully set.
1197 * * -#BPMP_EINVAL: Invalid request parameters.
1198 * * -#BPMP_ENOENT: No driver registered for thermal zone.
1199 * * -#BPMP_EFAULT: Problem setting trip point.
1200 */
1201 CMD_THERMAL_SET_TRIP = 2,
1202
1203 /**
1204 * @brief Get the number of supported thermal zones.
1205 *
1206 * No request parameters required.
1207 *
1208 * mrq_response::err is always 0, indicating success.
1209 */
1210 CMD_THERMAL_GET_NUM_ZONES = 3,
1211
1212 /** @brief: number of supported host-to-bpmp commands. May
1213 * increase in future
1214 */
1215 CMD_THERMAL_HOST_TO_BPMP_NUM
1216};
1217
1218enum mrq_thermal_bpmp_to_host_cmd {
1219 /**
1220 * @brief Indication that the temperature for a zone has
1221 * exceeded the range indicated in the thermal trip point
1222 * for the zone.
1223 *
1224 * BPMP needs to supply request parameters. Host only needs to
1225 * acknowledge.
1226 */
1227 CMD_THERMAL_HOST_TRIP_REACHED = 100,
1228
1229 /** @brief: number of supported bpmp-to-host commands. May
1230 * increase in future
1231 */
1232 CMD_THERMAL_BPMP_TO_HOST_NUM
1233};
1234
1235/*
1236 * Host->BPMP request data for request type CMD_THERMAL_QUERY_ABI
1237 *
1238 * zone: Request type for which to check existence.
1239 */
1240struct cmd_thermal_query_abi_request {
1241 uint32_t type;
1242} __ABI_PACKED;
1243
1244/*
1245 * Host->BPMP request data for request type CMD_THERMAL_GET_TEMP
1246 *
1247 * zone: Number of thermal zone.
1248 */
1249struct cmd_thermal_get_temp_request {
1250 uint32_t zone;
1251} __ABI_PACKED;
1252
1253/*
1254 * BPMP->Host reply data for request CMD_THERMAL_GET_TEMP
1255 *
1256 * error: 0 if request succeeded.
1257 * -BPMP_EINVAL if request parameters were invalid.
1258 * -BPMP_ENOENT if no driver was registered for the specified thermal zone.
1259 * -BPMP_EFAULT for other thermal zone driver errors.
1260 * temp: Current temperature in millicelsius.
1261 */
1262struct cmd_thermal_get_temp_response {
1263 int32_t temp;
1264} __ABI_PACKED;
1265
1266/*
1267 * Host->BPMP request data for request type CMD_THERMAL_SET_TRIP
1268 *
1269 * zone: Number of thermal zone.
1270 * low: Temperature of lower trip point in millicelsius
1271 * high: Temperature of upper trip point in millicelsius
1272 * enabled: 1 to enable trip point, 0 to disable trip point
1273 */
1274struct cmd_thermal_set_trip_request {
1275 uint32_t zone;
1276 int32_t low;
1277 int32_t high;
1278 uint32_t enabled;
1279} __ABI_PACKED;
1280
1281/*
1282 * BPMP->Host request data for request type CMD_THERMAL_HOST_TRIP_REACHED
1283 *
1284 * zone: Number of thermal zone where trip point was reached.
1285 */
1286struct cmd_thermal_host_trip_reached_request {
1287 uint32_t zone;
1288} __ABI_PACKED;
1289
1290/*
1291 * BPMP->Host reply data for request type CMD_THERMAL_GET_NUM_ZONES
1292 *
1293 * num: Number of supported thermal zones. The thermal zones are indexed
1294 * starting from zero.
1295 */
1296struct cmd_thermal_get_num_zones_response {
1297 uint32_t num;
1298} __ABI_PACKED;
1299
1300/*
1301 * Host->BPMP request data.
1302 *
1303 * Reply type is union mrq_thermal_bpmp_to_host_response.
1304 *
1305 * type: Type of request. Values listed in enum mrq_thermal_type.
1306 * data: Request type specific parameters.
1307 */
1308struct mrq_thermal_host_to_bpmp_request {
1309 uint32_t type;
1310 union {
1311 struct cmd_thermal_query_abi_request query_abi;
1312 struct cmd_thermal_get_temp_request get_temp;
1313 struct cmd_thermal_set_trip_request set_trip;
1314 } __UNION_ANON;
1315} __ABI_PACKED;
1316
1317/*
1318 * BPMP->Host request data.
1319 *
1320 * type: Type of request. Values listed in enum mrq_thermal_type.
1321 * data: Request type specific parameters.
1322 */
1323struct mrq_thermal_bpmp_to_host_request {
1324 uint32_t type;
1325 union {
1326 struct cmd_thermal_host_trip_reached_request host_trip_reached;
1327 } __UNION_ANON;
1328} __ABI_PACKED;
1329
1330/*
1331 * Data in reply to a Host->BPMP request.
1332 */
1333union mrq_thermal_bpmp_to_host_response {
1334 struct cmd_thermal_get_temp_response get_temp;
1335 struct cmd_thermal_get_num_zones_response get_num_zones;
1336} __ABI_PACKED;
1337/** @} */
1338
1339/**
1340 * @ingroup MRQ_Codes
1341 * @def MRQ_CPU_VHINT
1342 * @brief Query CPU voltage hint data
1343 *
1344 * * Platforms: T186
1345 * * Initiators: CCPLEX
1346 * * Targets: BPMP
1347 * * Request Payload: @ref mrq_cpu_vhint_request
1348 * * Response Payload: N/A
1349 *
1350 * @addtogroup Vhint CPU Voltage hint
1351 * @{
1352 */
1353
1354/**
1355 * @brief request with #MRQ_CPU_VHINT
1356 *
1357 * Used by #MRQ_CPU_VHINT call by CCPLEX to retrieve voltage hint data
1358 * from BPMP to memory space pointed by #addr. CCPLEX is responsible
1359 * to allocate sizeof(cpu_vhint_data) sized block of memory and
1360 * appropriately map it for BPMP before sending the request.
1361 */
1362struct mrq_cpu_vhint_request {
1363 /** @brief IOVA address for the #cpu_vhint_data */
1364 uint32_t addr; /* struct cpu_vhint_data * */
1365 /** @brief ID of the cluster whose data is requested */
1366 uint32_t cluster_id; /* enum cluster_id */
1367} __ABI_PACKED;
1368
1369/**
1370 * @brief description of the CPU v/f relation
1371 *
1372 * Used by #MRQ_CPU_VHINT call to carry data pointed by #addr of
1373 * struct mrq_cpu_vhint_request
1374 */
1375struct cpu_vhint_data {
1376 uint32_t ref_clk_hz; /**< reference frequency in Hz */
1377 uint16_t pdiv; /**< post divider value */
1378 uint16_t mdiv; /**< input divider value */
1379 uint16_t ndiv_max; /**< fMAX expressed with max NDIV value */
1380 /** table of ndiv values as a function of vINDEX (voltage index) */
1381 uint16_t ndiv[80];
1382 /** minimum allowed NDIV value */
1383 uint16_t ndiv_min;
1384 /** minimum allowed voltage hint value (as in vINDEX) */
1385 uint16_t vfloor;
1386 /** maximum allowed voltage hint value (as in vINDEX) */
1387 uint16_t vceil;
1388 /** post-multiplier for vindex value */
1389 uint16_t vindex_mult;
1390 /** post-divider for vindex value */
1391 uint16_t vindex_div;
1392 /** reserved for future use */
1393 uint16_t reserved[328];
1394} __ABI_PACKED;
1395
1396/** @} */
1397
1398/**
1399 * @ingroup MRQ_Codes
1400 * @def MRQ_ABI_RATCHET
1401 * @brief ABI ratchet value query
1402 *
1403 * * Platforms: T186
1404 * * Initiators: Any
1405 * * Targets: BPMP
1406 * * Request Payload: @ref mrq_abi_ratchet_request
1407 * * Response Payload: @ref mrq_abi_ratchet_response
1408 * @addtogroup ABI_info
1409 * @{
1410 */
1411
1412/**
1413 * @brief an ABI compatibility mechanism
1414 *
1415 * BPMP_ABI_RATCHET_VALUE may increase for various reasons in a future
1416 * revision of this header file.
1417 * 1. That future revision deprecates some MRQ
1418 * 2. That future revision introduces a breaking change to an existing
1419 * MRQ or
1420 * 3. A bug is discovered in an existing implementation of the BPMP-FW
1421 * (or possibly one of its clients) which warrants deprecating that
1422 * implementation.
1423 */
1424#define BPMP_ABI_RATCHET_VALUE 3
1425
1426/**
1427 * @brief request with #MRQ_ABI_RATCHET.
1428 *
1429 * #ratchet should be #BPMP_ABI_RATCHET_VALUE from the ABI header
1430 * against which the requester was compiled.
1431 *
1432 * If ratchet is less than BPMP's #BPMP_ABI_RATCHET_VALUE, BPMP may
1433 * reply with mrq_response::err = -#BPMP_ERANGE to indicate that
1434 * BPMP-FW cannot interoperate correctly with the requester. Requester
1435 * should cease further communication with BPMP.
1436 *
1437 * Otherwise, err shall be 0.
1438 */
1439struct mrq_abi_ratchet_request {
1440 /** @brief requester's ratchet value */
1441 uint16_t ratchet;
1442};
1443
1444/**
1445 * @brief response to #MRQ_ABI_RATCHET
1446 *
1447 * #ratchet shall be #BPMP_ABI_RATCHET_VALUE from the ABI header
1448 * against which BPMP firwmare was compiled.
1449 *
1450 * If #ratchet is less than the requester's #BPMP_ABI_RATCHET_VALUE,
1451 * the requster must either interoperate with BPMP according to an ABI
1452 * header version with BPMP_ABI_RATCHET_VALUE = ratchet or cease
1453 * communication with BPMP.
1454 *
1455 * If mrq_response::err is 0 and ratchet is greater than or equal to the
1456 * requester's BPMP_ABI_RATCHET_VALUE, the requester should continue
1457 * normal operation.
1458 */
1459struct mrq_abi_ratchet_response {
1460 /** @brief BPMP's ratchet value */
1461 uint16_t ratchet;
1462};
1463/** @} */
1464
1465/**
1466 * @ingroup MRQ_Codes
1467 * @def MRQ_EMC_DVFS_LATENCY
1468 * @brief query frequency dependent EMC DVFS latency
1469 *
1470 * * Platforms: T186
1471 * * Initiators: CCPLEX
1472 * * Targets: BPMP
1473 * * Request Payload: N/A
1474 * * Response Payload: @ref mrq_emc_dvfs_latency_response
1475 * @addtogroup EMC
1476 * @{
1477 */
1478
1479/**
1480 * @brief used by @ref mrq_emc_dvfs_latency_response
1481 */
1482struct emc_dvfs_latency {
1483 /** @brief EMC frequency in kHz */
1484 uint32_t freq;
1485 /** @brief EMC DVFS latency in nanoseconds */
1486 uint32_t latency;
1487} __ABI_PACKED;
1488
1489#define EMC_DVFS_LATENCY_MAX_SIZE 14
1490/**
1491 * @brief response to #MRQ_EMC_DVFS_LATENCY
1492 */
1493struct mrq_emc_dvfs_latency_response {
1494 /** @brief the number valid entries in #pairs */
1495 uint32_t num_pairs;
1496 /** @brief EMC <frequency, latency> information */
1497 struct emc_dvfs_latency pairs[EMC_DVFS_LATENCY_MAX_SIZE];
1498} __ABI_PACKED;
1499
1500/** @} */
1501
1502/**
1503 * @ingroup MRQ_Codes
1504 * @def MRQ_TRACE_ITER
1505 * @brief manage the trace iterator
1506 *
1507 * * Platforms: All
1508 * * Initiators: CCPLEX
1509 * * Targets: BPMP
1510 * * Request Payload: N/A
1511 * * Response Payload: @ref mrq_trace_iter_request
1512 * @addtogroup Trace
1513 * @{
1514 */
1515enum {
1516 /** @brief (re)start the tracing now. Ignore older events */
1517 TRACE_ITER_INIT = 0,
1518 /** @brief clobber all events in the trace buffer */
1519 TRACE_ITER_CLEAN = 1
1520};
1521
1522/**
1523 * @brief request with #MRQ_TRACE_ITER
1524 */
1525struct mrq_trace_iter_request {
1526 /** @brief TRACE_ITER_INIT or TRACE_ITER_CLEAN */
1527 uint32_t cmd;
1528} __ABI_PACKED;
1529
1530/** @} */
1531
1532/*
1533 * 4. Enumerations
1534 */
1535
1536/*
1537 * 4.1 CPU enumerations
1538 *
1539 * See <mach-t186/system-t186.h>
1540 *
1541 * 4.2 CPU Cluster enumerations
1542 *
1543 * See <mach-t186/system-t186.h>
1544 *
1545 * 4.3 System low power state enumerations
1546 *
1547 * See <mach-t186/system-t186.h>
1548 */
1549
1550/*
1551 * 4.4 Clock enumerations
1552 *
1553 * For clock enumerations, see <mach-t186/clk-t186.h>
1554 */
1555
1556/*
1557 * 4.5 Reset enumerations
1558 *
1559 * For reset enumerations, see <mach-t186/reset-t186.h>
1560 */
1561
1562/*
1563 * 4.6 Thermal sensor enumerations
1564 *
1565 * For thermal sensor enumerations, see <mach-t186/thermal-t186.h>
1566 */
1567
1568/**
1569 * @defgroup Error_Codes
1570 * Negative values for mrq_response::err generally indicate some
1571 * error. The ABI defines the following error codes. Negating these
1572 * defines is an exercise left to the user.
1573 * @{
1574 */
1575/** @brief No such file or directory */
1576#define BPMP_ENOENT 2
1577/** @brief No MRQ handler */
1578#define BPMP_ENOHANDLER 3
1579/** @brief I/O error */
1580#define BPMP_EIO 5
1581/** @brief Bad sub-MRQ command */
1582#define BPMP_EBADCMD 6
1583/** @brief Not enough memory */
1584#define BPMP_ENOMEM 12
1585/** @brief Permission denied */
1586#define BPMP_EACCES 13
1587/** @brief Bad address */
1588#define BPMP_EFAULT 14
1589/** @brief No such device */
1590#define BPMP_ENODEV 19
1591/** @brief Argument is a directory */
1592#define BPMP_EISDIR 21
1593/** @brief Invalid argument */
1594#define BPMP_EINVAL 22
1595/** @brief Timeout during operation */
1596#define BPMP_ETIMEDOUT 23
1597/** @brief Out of range */
1598#define BPMP_ERANGE 34
1599/** @} */
1600/** @} */
1601#endif
diff --git a/include/soc/tegra/bpmp.h b/include/soc/tegra/bpmp.h
new file mode 100644
index 000000000000..13dcd44e91bb
--- /dev/null
+++ b/include/soc/tegra/bpmp.h
@@ -0,0 +1,141 @@
1/*
2 * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#ifndef __SOC_TEGRA_BPMP_H
15#define __SOC_TEGRA_BPMP_H
16
17#include <linux/mailbox_client.h>
18#include <linux/reset-controller.h>
19#include <linux/semaphore.h>
20#include <linux/types.h>
21
22#include <soc/tegra/bpmp-abi.h>
23
24struct tegra_bpmp_clk;
25
26struct tegra_bpmp_soc {
27 struct {
28 struct {
29 unsigned int offset;
30 unsigned int count;
31 unsigned int timeout;
32 } cpu_tx, thread, cpu_rx;
33 } channels;
34 unsigned int num_resets;
35};
36
37struct tegra_bpmp_mb_data {
38 u32 code;
39 u32 flags;
40 u8 data[MSG_DATA_MIN_SZ];
41} __packed;
42
43struct tegra_bpmp_channel {
44 struct tegra_bpmp *bpmp;
45 struct tegra_bpmp_mb_data *ib;
46 struct tegra_bpmp_mb_data *ob;
47 struct completion completion;
48 struct tegra_ivc *ivc;
49};
50
51typedef void (*tegra_bpmp_mrq_handler_t)(unsigned int mrq,
52 struct tegra_bpmp_channel *channel,
53 void *data);
54
55struct tegra_bpmp_mrq {
56 struct list_head list;
57 unsigned int mrq;
58 tegra_bpmp_mrq_handler_t handler;
59 void *data;
60};
61
62struct tegra_bpmp {
63 const struct tegra_bpmp_soc *soc;
64 struct device *dev;
65
66 struct {
67 struct gen_pool *pool;
68 dma_addr_t phys;
69 void *virt;
70 } tx, rx;
71
72 struct {
73 struct mbox_client client;
74 struct mbox_chan *channel;
75 } mbox;
76
77 struct tegra_bpmp_channel *channels;
78 unsigned int num_channels;
79
80 struct {
81 unsigned long *allocated;
82 unsigned long *busy;
83 unsigned int count;
84 struct semaphore lock;
85 } threaded;
86
87 struct list_head mrqs;
88 spinlock_t lock;
89
90 struct tegra_bpmp_clk **clocks;
91 unsigned int num_clocks;
92
93 struct reset_controller_dev rstc;
94};
95
96struct tegra_bpmp *tegra_bpmp_get(struct device *dev);
97void tegra_bpmp_put(struct tegra_bpmp *bpmp);
98
99struct tegra_bpmp_message {
100 unsigned int mrq;
101
102 struct {
103 const void *data;
104 size_t size;
105 } tx;
106
107 struct {
108 void *data;
109 size_t size;
110 } rx;
111};
112
113int tegra_bpmp_transfer_atomic(struct tegra_bpmp *bpmp,
114 struct tegra_bpmp_message *msg);
115int tegra_bpmp_transfer(struct tegra_bpmp *bpmp,
116 struct tegra_bpmp_message *msg);
117
118int tegra_bpmp_request_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
119 tegra_bpmp_mrq_handler_t handler, void *data);
120void tegra_bpmp_free_mrq(struct tegra_bpmp *bpmp, unsigned int mrq,
121 void *data);
122
123#if IS_ENABLED(CONFIG_CLK_TEGRA_BPMP)
124int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp);
125#else
126static inline int tegra_bpmp_init_clocks(struct tegra_bpmp *bpmp)
127{
128 return 0;
129}
130#endif
131
132#if IS_ENABLED(CONFIG_RESET_TEGRA_BPMP)
133int tegra_bpmp_init_resets(struct tegra_bpmp *bpmp);
134#else
135static inline int tegra_bpmp_init_resets(struct tegra_bpmp *bpmp)
136{
137 return 0;
138}
139#endif
140
141#endif /* __SOC_TEGRA_BPMP_H */