aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2016-11-18 08:34:46 -0500
committerThierry Reding <treding@nvidia.com>2016-11-18 08:34:46 -0500
commit801fc022147974f4754939202efe607294479bc9 (patch)
treefc7099112e411988758b7145780a45cee6d8951c
parent1001354ca34179f3db924eb66672442a173147dc (diff)
parentb704ed8095ee91af5f3f7343bb3be23aae1cb26d (diff)
Merge branch 'for-4.10/firmware' into for-4.10/reset
-rw-r--r--Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt108
-rw-r--r--Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt52
-rw-r--r--drivers/firmware/Kconfig1
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/tegra/Kconfig25
-rw-r--r--drivers/firmware/tegra/Makefile2
-rw-r--r--drivers/firmware/tegra/bpmp.c868
-rw-r--r--drivers/firmware/tegra/ivc.c695
-rw-r--r--drivers/mailbox/Kconfig9
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/tegra-hsp.c479
-rw-r--r--drivers/soc/tegra/Kconfig14
-rw-r--r--include/dt-bindings/clock/tegra186-clock.h940
-rw-r--r--include/dt-bindings/mailbox/tegra186-hsp.h24
-rw-r--r--include/dt-bindings/power/tegra186-powergate.h39
-rw-r--r--include/dt-bindings/reset/tegra186-reset.h217
-rw-r--r--include/soc/tegra/bpmp-abi.h1601
-rw-r--r--include/soc/tegra/bpmp.h141
-rw-r--r--include/soc/tegra/ivc.h109
19 files changed, 5327 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt
new file mode 100644
index 000000000000..e821e16ad65b
--- /dev/null
+++ b/Documentation/devicetree/bindings/firmware/nvidia,tegra186-bpmp.txt
@@ -0,0 +1,108 @@
1NVIDIA Tegra Boot and Power Management Processor (BPMP)
2
3The BPMP is a specific processor in Tegra chip, which is designed for
4booting process handling and offloading the power management, clock
5management, and reset control tasks from the CPU. The binding document
6defines the resources that would be used by the BPMP firmware driver,
7which can create the interprocessor communication (IPC) between the CPU
8and BPMP.
9
10Required properties:
11- name : Should be bpmp
12- compatible
13 Array of strings
14 One of:
15 - "nvidia,tegra186-bpmp"
16- mboxes : The phandle of mailbox controller and the mailbox specifier.
17- shmem : List of the phandle of the TX and RX shared memory area that
18 the IPC between CPU and BPMP is based on.
19- #clock-cells : Should be 1.
20- #power-domain-cells : Should be 1.
21- #reset-cells : Should be 1.
22
23This node is a mailbox consumer. See the following files for details of
24the mailbox subsystem, and the specifiers implemented by the relevant
25provider(s):
26
27- .../mailbox/mailbox.txt
28- .../mailbox/nvidia,tegra186-hsp.txt
29
30This node is a clock, power domain, and reset provider. See the following
31files for general documentation of those features, and the specifiers
32implemented by this node:
33
34- .../clock/clock-bindings.txt
35- <dt-bindings/clock/tegra186-clock.h>
36- ../power/power_domain.txt
37- <dt-bindings/power/tegra186-powergate.h>
38- .../reset/reset.txt
39- <dt-bindings/reset/tegra186-reset.h>
40
41The BPMP implements some services which must be represented by separate nodes.
42For example, it can provide access to certain I2C controllers, and the I2C
43bindings represent each I2C controller as a device tree node. Such nodes should
44be nested directly inside the main BPMP node.
45
46Software can determine whether a child node of the BPMP node represents a device
47by checking for a compatible property. Any node with a compatible property
48represents a device that can be instantiated. Nodes without a compatible
49property may be used to provide configuration information regarding the BPMP
50itself, although no such configuration nodes are currently defined by this
51binding.
52
53The BPMP firmware defines no single global name-/numbering-space for such
54services. Put another way, the numbering scheme for I2C buses is distinct from
55the numbering scheme for any other service the BPMP may provide (e.g. a future
56hypothetical SPI bus service). As such, child device nodes will have no reg
57property, and the BPMP node will have no #address-cells or #size-cells property.
58
59The shared memory bindings for BPMP
60-----------------------------------
61
62The shared memory area for the IPC TX and RX between CPU and BPMP are
63predefined and work on top of sysram, which is an SRAM inside the chip.
64
65See ".../sram/sram.txt" for the bindings.
66
67Example:
68
69hsp_top0: hsp@03c00000 {
70 ...
71 #mbox-cells = <2>;
72};
73
74sysram@30000000 {
75 compatible = "nvidia,tegra186-sysram", "mmio-sram";
76 reg = <0x0 0x30000000 0x0 0x50000>;
77 #address-cells = <2>;
78 #size-cells = <2>;
79 ranges = <0 0x0 0x0 0x30000000 0x0 0x50000>;
80
81 cpu_bpmp_tx: shmem@4e000 {
82 compatible = "nvidia,tegra186-bpmp-shmem";
83 reg = <0x0 0x4e000 0x0 0x1000>;
84 label = "cpu-bpmp-tx";
85 pool;
86 };
87
88 cpu_bpmp_rx: shmem@4f000 {
89 compatible = "nvidia,tegra186-bpmp-shmem";
90 reg = <0x0 0x4f000 0x0 0x1000>;
91 label = "cpu-bpmp-rx";
92 pool;
93 };
94};
95
96bpmp {
97 compatible = "nvidia,tegra186-bpmp";
98 mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB TEGRA_HSP_DB_MASTER_BPMP>;
99 shmem = <&cpu_bpmp_tx &cpu_bpmp_rx>;
100 #clock-cells = <1>;
101 #power-domain-cells = <1>;
102 #reset-cells = <1>;
103
104 i2c {
105 compatible = "...";
106 ...
107 };
108};
diff --git a/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
new file mode 100644
index 000000000000..b99d25fc2f26
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/nvidia,tegra186-hsp.txt
@@ -0,0 +1,52 @@
1NVIDIA Tegra Hardware Synchronization Primitives (HSP)
2
3The HSP modules are used for the processors to share resources and communicate
4together. It provides a set of hardware synchronization primitives for
5interprocessor communication. So the interprocessor communication (IPC)
6protocols can use hardware synchronization primitives, when operating between
7two processors not in an SMP relationship.
8
9The features that HSP supported are shared mailboxes, shared semaphores,
10arbitrated semaphores and doorbells.
11
12Required properties:
13- name : Should be hsp
14- compatible
15 Array of strings.
16 one of:
17 - "nvidia,tegra186-hsp"
18- reg : Offset and length of the register set for the device.
19- interrupt-names
20 Array of strings.
21 Contains a list of names for the interrupts described by the interrupt
22 property. May contain the following entries, in any order:
23 - "doorbell"
24 Users of this binding MUST look up entries in the interrupt property
25 by name, using this interrupt-names property to do so.
26- interrupts
27 Array of interrupt specifiers.
28 Must contain one entry per entry in the interrupt-names property,
29 in a matching order.
30- #mbox-cells : Should be 2.
31
32The mbox specifier of the "mboxes" property in the client node should
33contain two data. The first one should be the HSP type and the second
34one should be the ID that the client is going to use. Those information
35can be found in the following file.
36
37- <dt-bindings/mailbox/tegra186-hsp.h>.
38
39Example:
40
41hsp_top0: hsp@3c00000 {
42 compatible = "nvidia,tegra186-hsp";
43 reg = <0x0 0x03c00000 0x0 0xa0000>;
44 interrupts = <GIC_SPI 176 IRQ_TYPE_LEVEL_HIGH>;
45 interrupt-names = "doorbell";
46 #mbox-cells = <2>;
47};
48
49client {
50 ...
51 mboxes = <&hsp_top0 TEGRA_HSP_MBOX_TYPE_DB TEGRA_HSP_DB_MASTER_XXX>;
52};
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index bca172d42c74..9968de04d1d5 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -210,5 +210,6 @@ source "drivers/firmware/broadcom/Kconfig"
210source "drivers/firmware/google/Kconfig" 210source "drivers/firmware/google/Kconfig"
211source "drivers/firmware/efi/Kconfig" 211source "drivers/firmware/efi/Kconfig"
212source "drivers/firmware/meson/Kconfig" 212source "drivers/firmware/meson/Kconfig"
213source "drivers/firmware/tegra/Kconfig"
213 214
214endmenu 215endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 898ac41fa8b3..2afe75c52ac2 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -26,3 +26,4 @@ obj-y += meson/
26obj-$(CONFIG_GOOGLE_FIRMWARE) += google/ 26obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
27obj-$(CONFIG_EFI) += efi/ 27obj-$(CONFIG_EFI) += efi/
28obj-$(CONFIG_UEFI_CPER) += efi/ 28obj-$(CONFIG_UEFI_CPER) += efi/
29obj-y += tegra/
diff --git a/drivers/firmware/tegra/Kconfig b/drivers/firmware/tegra/Kconfig
new file mode 100644
index 000000000000..ff2730d5c468
--- /dev/null
+++ b/drivers/firmware/tegra/Kconfig
@@ -0,0 +1,25 @@
1menu "Tegra firmware driver"
2
3config TEGRA_IVC
4 bool "Tegra IVC protocol"
5 depends on ARCH_TEGRA
6 help
7 IVC (Inter-VM Communication) protocol is part of the IPC
8 (Inter Processor Communication) framework on Tegra. It maintains the
9 data and the different commuication channels in SysRAM or RAM and
10 keeps the content is synchronization between host CPU and remote
11 processors.
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
25endmenu
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
new file mode 100644
index 000000000000..e34a2f79e1ad
--- /dev/null
+++ b/drivers/firmware/tegra/Makefile
@@ -0,0 +1,2 @@
1obj-$(CONFIG_TEGRA_BPMP) += bpmp.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/drivers/firmware/tegra/ivc.c b/drivers/firmware/tegra/ivc.c
new file mode 100644
index 000000000000..29ecfd815320
--- /dev/null
+++ b/drivers/firmware/tegra/ivc.c
@@ -0,0 +1,695 @@
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
14#include <soc/tegra/ivc.h>
15
16#define TEGRA_IVC_ALIGN 64
17
18/*
19 * IVC channel reset protocol.
20 *
21 * Each end uses its tx_channel.state to indicate its synchronization state.
22 */
23enum tegra_ivc_state {
24 /*
25 * This value is zero for backwards compatibility with services that
26 * assume channels to be initially zeroed. Such channels are in an
27 * initially valid state, but cannot be asynchronously reset, and must
28 * maintain a valid state at all times.
29 *
30 * The transmitting end can enter the established state from the sync or
31 * ack state when it observes the receiving endpoint in the ack or
32 * established state, indicating that has cleared the counters in our
33 * rx_channel.
34 */
35 TEGRA_IVC_STATE_ESTABLISHED = 0,
36
37 /*
38 * If an endpoint is observed in the sync state, the remote endpoint is
39 * allowed to clear the counters it owns asynchronously with respect to
40 * the current endpoint. Therefore, the current endpoint is no longer
41 * allowed to communicate.
42 */
43 TEGRA_IVC_STATE_SYNC,
44
45 /*
46 * When the transmitting end observes the receiving end in the sync
47 * state, it can clear the w_count and r_count and transition to the ack
48 * state. If the remote endpoint observes us in the ack state, it can
49 * return to the established state once it has cleared its counters.
50 */
51 TEGRA_IVC_STATE_ACK
52};
53
54/*
55 * This structure is divided into two-cache aligned parts, the first is only
56 * written through the tx.channel pointer, while the second is only written
57 * through the rx.channel pointer. This delineates ownership of the cache
58 * lines, which is critical to performance and necessary in non-cache coherent
59 * implementations.
60 */
61struct tegra_ivc_header {
62 union {
63 struct {
64 /* fields owned by the transmitting end */
65 u32 count;
66 u32 state;
67 };
68
69 u8 pad[TEGRA_IVC_ALIGN];
70 } tx;
71
72 union {
73 /* fields owned by the receiving end */
74 u32 count;
75 u8 pad[TEGRA_IVC_ALIGN];
76 } rx;
77};
78
79static inline void tegra_ivc_invalidate(struct tegra_ivc *ivc, dma_addr_t phys)
80{
81 if (!ivc->peer)
82 return;
83
84 dma_sync_single_for_cpu(ivc->peer, phys, TEGRA_IVC_ALIGN,
85 DMA_FROM_DEVICE);
86}
87
88static inline void tegra_ivc_flush(struct tegra_ivc *ivc, dma_addr_t phys)
89{
90 if (!ivc->peer)
91 return;
92
93 dma_sync_single_for_device(ivc->peer, phys, TEGRA_IVC_ALIGN,
94 DMA_TO_DEVICE);
95}
96
97static inline bool tegra_ivc_empty(struct tegra_ivc *ivc,
98 struct tegra_ivc_header *header)
99{
100 /*
101 * This function performs multiple checks on the same values with
102 * security implications, so create snapshots with ACCESS_ONCE() to
103 * ensure that these checks use the same values.
104 */
105 u32 tx = ACCESS_ONCE(header->tx.count);
106 u32 rx = ACCESS_ONCE(header->rx.count);
107
108 /*
109 * Perform an over-full check to prevent denial of service attacks
110 * where a server could be easily fooled into believing that there's
111 * an extremely large number of frames ready, since receivers are not
112 * expected to check for full or over-full conditions.
113 *
114 * Although the channel isn't empty, this is an invalid case caused by
115 * a potentially malicious peer, so returning empty is safer, because
116 * it gives the impression that the channel has gone silent.
117 */
118 if (tx - rx > ivc->num_frames)
119 return true;
120
121 return tx == rx;
122}
123
124static inline bool tegra_ivc_full(struct tegra_ivc *ivc,
125 struct tegra_ivc_header *header)
126{
127 u32 tx = ACCESS_ONCE(header->tx.count);
128 u32 rx = ACCESS_ONCE(header->rx.count);
129
130 /*
131 * Invalid cases where the counters indicate that the queue is over
132 * capacity also appear full.
133 */
134 return tx - rx >= ivc->num_frames;
135}
136
137static inline u32 tegra_ivc_available(struct tegra_ivc *ivc,
138 struct tegra_ivc_header *header)
139{
140 u32 tx = ACCESS_ONCE(header->tx.count);
141 u32 rx = ACCESS_ONCE(header->rx.count);
142
143 /*
144 * This function isn't expected to be used in scenarios where an
145 * over-full situation can lead to denial of service attacks. See the
146 * comment in tegra_ivc_empty() for an explanation about special
147 * over-full considerations.
148 */
149 return tx - rx;
150}
151
152static inline void tegra_ivc_advance_tx(struct tegra_ivc *ivc)
153{
154 ACCESS_ONCE(ivc->tx.channel->tx.count) =
155 ACCESS_ONCE(ivc->tx.channel->tx.count) + 1;
156
157 if (ivc->tx.position == ivc->num_frames - 1)
158 ivc->tx.position = 0;
159 else
160 ivc->tx.position++;
161}
162
163static inline void tegra_ivc_advance_rx(struct tegra_ivc *ivc)
164{
165 ACCESS_ONCE(ivc->rx.channel->rx.count) =
166 ACCESS_ONCE(ivc->rx.channel->rx.count) + 1;
167
168 if (ivc->rx.position == ivc->num_frames - 1)
169 ivc->rx.position = 0;
170 else
171 ivc->rx.position++;
172}
173
174static inline int tegra_ivc_check_read(struct tegra_ivc *ivc)
175{
176 unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
177
178 /*
179 * tx.channel->state is set locally, so it is not synchronized with
180 * state from the remote peer. The remote peer cannot reset its
181 * transmit counters until we've acknowledged its synchronization
182 * request, so no additional synchronization is required because an
183 * asynchronous transition of rx.channel->state to
184 * TEGRA_IVC_STATE_ACK is not allowed.
185 */
186 if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
187 return -ECONNRESET;
188
189 /*
190 * Avoid unnecessary invalidations when performing repeated accesses
191 * to an IVC channel by checking the old queue pointers first.
192 *
193 * Synchronization is only necessary when these pointers indicate
194 * empty or full.
195 */
196 if (!tegra_ivc_empty(ivc, ivc->rx.channel))
197 return 0;
198
199 tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
200
201 if (tegra_ivc_empty(ivc, ivc->rx.channel))
202 return -ENOSPC;
203
204 return 0;
205}
206
207static inline int tegra_ivc_check_write(struct tegra_ivc *ivc)
208{
209 unsigned int offset = offsetof(struct tegra_ivc_header, rx.count);
210
211 if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
212 return -ECONNRESET;
213
214 if (!tegra_ivc_full(ivc, ivc->tx.channel))
215 return 0;
216
217 tegra_ivc_invalidate(ivc, ivc->tx.phys + offset);
218
219 if (tegra_ivc_full(ivc, ivc->tx.channel))
220 return -ENOSPC;
221
222 return 0;
223}
224
225static void *tegra_ivc_frame_virt(struct tegra_ivc *ivc,
226 struct tegra_ivc_header *header,
227 unsigned int frame)
228{
229 if (WARN_ON(frame >= ivc->num_frames))
230 return ERR_PTR(-EINVAL);
231
232 return (void *)(header + 1) + ivc->frame_size * frame;
233}
234
235static inline dma_addr_t tegra_ivc_frame_phys(struct tegra_ivc *ivc,
236 dma_addr_t phys,
237 unsigned int frame)
238{
239 unsigned long offset;
240
241 offset = sizeof(struct tegra_ivc_header) + ivc->frame_size * frame;
242
243 return phys + offset;
244}
245
246static inline void tegra_ivc_invalidate_frame(struct tegra_ivc *ivc,
247 dma_addr_t phys,
248 unsigned int frame,
249 unsigned int offset,
250 size_t size)
251{
252 if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
253 return;
254
255 phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
256
257 dma_sync_single_for_cpu(ivc->peer, phys, size, DMA_FROM_DEVICE);
258}
259
260static inline void tegra_ivc_flush_frame(struct tegra_ivc *ivc,
261 dma_addr_t phys,
262 unsigned int frame,
263 unsigned int offset,
264 size_t size)
265{
266 if (!ivc->peer || WARN_ON(frame >= ivc->num_frames))
267 return;
268
269 phys = tegra_ivc_frame_phys(ivc, phys, frame) + offset;
270
271 dma_sync_single_for_device(ivc->peer, phys, size, DMA_TO_DEVICE);
272}
273
274/* directly peek at the next frame rx'ed */
275void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc)
276{
277 int err;
278
279 if (WARN_ON(ivc == NULL))
280 return ERR_PTR(-EINVAL);
281
282 err = tegra_ivc_check_read(ivc);
283 if (err < 0)
284 return ERR_PTR(err);
285
286 /*
287 * Order observation of ivc->rx.position potentially indicating new
288 * data before data read.
289 */
290 smp_rmb();
291
292 tegra_ivc_invalidate_frame(ivc, ivc->rx.phys, ivc->rx.position, 0,
293 ivc->frame_size);
294
295 return tegra_ivc_frame_virt(ivc, ivc->rx.channel, ivc->rx.position);
296}
297EXPORT_SYMBOL(tegra_ivc_read_get_next_frame);
298
299int tegra_ivc_read_advance(struct tegra_ivc *ivc)
300{
301 unsigned int rx = offsetof(struct tegra_ivc_header, rx.count);
302 unsigned int tx = offsetof(struct tegra_ivc_header, tx.count);
303 int err;
304
305 /*
306 * No read barriers or synchronization here: the caller is expected to
307 * have already observed the channel non-empty. This check is just to
308 * catch programming errors.
309 */
310 err = tegra_ivc_check_read(ivc);
311 if (err < 0)
312 return err;
313
314 tegra_ivc_advance_rx(ivc);
315
316 tegra_ivc_flush(ivc, ivc->rx.phys + rx);
317
318 /*
319 * Ensure our write to ivc->rx.position occurs before our read from
320 * ivc->tx.position.
321 */
322 smp_mb();
323
324 /*
325 * Notify only upon transition from full to non-full. The available
326 * count can only asynchronously increase, so the worst possible
327 * side-effect will be a spurious notification.
328 */
329 tegra_ivc_invalidate(ivc, ivc->rx.phys + tx);
330
331 if (tegra_ivc_available(ivc, ivc->rx.channel) == ivc->num_frames - 1)
332 ivc->notify(ivc, ivc->notify_data);
333
334 return 0;
335}
336EXPORT_SYMBOL(tegra_ivc_read_advance);
337
338/* directly poke at the next frame to be tx'ed */
339void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc)
340{
341 int err;
342
343 err = tegra_ivc_check_write(ivc);
344 if (err < 0)
345 return ERR_PTR(err);
346
347 return tegra_ivc_frame_virt(ivc, ivc->tx.channel, ivc->tx.position);
348}
349EXPORT_SYMBOL(tegra_ivc_write_get_next_frame);
350
351/* advance the tx buffer */
352int tegra_ivc_write_advance(struct tegra_ivc *ivc)
353{
354 unsigned int tx = offsetof(struct tegra_ivc_header, tx.count);
355 unsigned int rx = offsetof(struct tegra_ivc_header, rx.count);
356 int err;
357
358 err = tegra_ivc_check_write(ivc);
359 if (err < 0)
360 return err;
361
362 tegra_ivc_flush_frame(ivc, ivc->tx.phys, ivc->tx.position, 0,
363 ivc->frame_size);
364
365 /*
366 * Order any possible stores to the frame before update of
367 * ivc->tx.position.
368 */
369 smp_wmb();
370
371 tegra_ivc_advance_tx(ivc);
372 tegra_ivc_flush(ivc, ivc->tx.phys + tx);
373
374 /*
375 * Ensure our write to ivc->tx.position occurs before our read from
376 * ivc->rx.position.
377 */
378 smp_mb();
379
380 /*
381 * Notify only upon transition from empty to non-empty. The available
382 * count can only asynchronously decrease, so the worst possible
383 * side-effect will be a spurious notification.
384 */
385 tegra_ivc_invalidate(ivc, ivc->tx.phys + rx);
386
387 if (tegra_ivc_available(ivc, ivc->tx.channel) == 1)
388 ivc->notify(ivc, ivc->notify_data);
389
390 return 0;
391}
392EXPORT_SYMBOL(tegra_ivc_write_advance);
393
394void tegra_ivc_reset(struct tegra_ivc *ivc)
395{
396 unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
397
398 ivc->tx.channel->tx.state = TEGRA_IVC_STATE_SYNC;
399 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
400 ivc->notify(ivc, ivc->notify_data);
401}
402EXPORT_SYMBOL(tegra_ivc_reset);
403
404/*
405 * =======================================================
406 * IVC State Transition Table - see tegra_ivc_notified()
407 * =======================================================
408 *
409 * local remote action
410 * ----- ------ -----------------------------------
411 * SYNC EST <none>
412 * SYNC ACK reset counters; move to EST; notify
413 * SYNC SYNC reset counters; move to ACK; notify
414 * ACK EST move to EST; notify
415 * ACK ACK move to EST; notify
416 * ACK SYNC reset counters; move to ACK; notify
417 * EST EST <none>
418 * EST ACK <none>
419 * EST SYNC reset counters; move to ACK; notify
420 *
421 * ===============================================================
422 */
423
424int tegra_ivc_notified(struct tegra_ivc *ivc)
425{
426 unsigned int offset = offsetof(struct tegra_ivc_header, tx.count);
427 enum tegra_ivc_state state;
428
429 /* Copy the receiver's state out of shared memory. */
430 tegra_ivc_invalidate(ivc, ivc->rx.phys + offset);
431 state = ACCESS_ONCE(ivc->rx.channel->tx.state);
432
433 if (state == TEGRA_IVC_STATE_SYNC) {
434 offset = offsetof(struct tegra_ivc_header, tx.count);
435
436 /*
437 * Order observation of TEGRA_IVC_STATE_SYNC before stores
438 * clearing tx.channel.
439 */
440 smp_rmb();
441
442 /*
443 * Reset tx.channel counters. The remote end is in the SYNC
444 * state and won't make progress until we change our state,
445 * so the counters are not in use at this time.
446 */
447 ivc->tx.channel->tx.count = 0;
448 ivc->rx.channel->rx.count = 0;
449
450 ivc->tx.position = 0;
451 ivc->rx.position = 0;
452
453 /*
454 * Ensure that counters appear cleared before new state can be
455 * observed.
456 */
457 smp_wmb();
458
459 /*
460 * Move to ACK state. We have just cleared our counters, so it
461 * is now safe for the remote end to start using these values.
462 */
463 ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ACK;
464 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
465
466 /*
467 * Notify remote end to observe state transition.
468 */
469 ivc->notify(ivc, ivc->notify_data);
470
471 } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_SYNC &&
472 state == TEGRA_IVC_STATE_ACK) {
473 offset = offsetof(struct tegra_ivc_header, tx.count);
474
475 /*
476 * Order observation of ivc_state_sync before stores clearing
477 * tx_channel.
478 */
479 smp_rmb();
480
481 /*
482 * Reset tx.channel counters. The remote end is in the ACK
483 * state and won't make progress until we change our state,
484 * so the counters are not in use at this time.
485 */
486 ivc->tx.channel->tx.count = 0;
487 ivc->rx.channel->rx.count = 0;
488
489 ivc->tx.position = 0;
490 ivc->rx.position = 0;
491
492 /*
493 * Ensure that counters appear cleared before new state can be
494 * observed.
495 */
496 smp_wmb();
497
498 /*
499 * Move to ESTABLISHED state. We know that the remote end has
500 * already cleared its counters, so it is safe to start
501 * writing/reading on this channel.
502 */
503 ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
504 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
505
506 /*
507 * Notify remote end to observe state transition.
508 */
509 ivc->notify(ivc, ivc->notify_data);
510
511 } else if (ivc->tx.channel->tx.state == TEGRA_IVC_STATE_ACK) {
512 offset = offsetof(struct tegra_ivc_header, tx.count);
513
514 /*
515 * At this point, we have observed the peer to be in either
516 * the ACK or ESTABLISHED state. Next, order observation of
517 * peer state before storing to tx.channel.
518 */
519 smp_rmb();
520
521 /*
522 * Move to ESTABLISHED state. We know that we have previously
523 * cleared our counters, and we know that the remote end has
524 * cleared its counters, so it is safe to start writing/reading
525 * on this channel.
526 */
527 ivc->tx.channel->tx.state = TEGRA_IVC_STATE_ESTABLISHED;
528 tegra_ivc_flush(ivc, ivc->tx.phys + offset);
529
530 /*
531 * Notify remote end to observe state transition.
532 */
533 ivc->notify(ivc, ivc->notify_data);
534
535 } else {
536 /*
537 * There is no need to handle any further action. Either the
538 * channel is already fully established, or we are waiting for
539 * the remote end to catch up with our current state. Refer
540 * to the diagram in "IVC State Transition Table" above.
541 */
542 }
543
544 if (ivc->tx.channel->tx.state != TEGRA_IVC_STATE_ESTABLISHED)
545 return -EAGAIN;
546
547 return 0;
548}
549EXPORT_SYMBOL(tegra_ivc_notified);
550
551size_t tegra_ivc_align(size_t size)
552{
553 return ALIGN(size, TEGRA_IVC_ALIGN);
554}
555EXPORT_SYMBOL(tegra_ivc_align);
556
557unsigned tegra_ivc_total_queue_size(unsigned queue_size)
558{
559 if (!IS_ALIGNED(queue_size, TEGRA_IVC_ALIGN)) {
560 pr_err("%s: queue_size (%u) must be %u-byte aligned\n",
561 __func__, queue_size, TEGRA_IVC_ALIGN);
562 return 0;
563 }
564
565 return queue_size + sizeof(struct tegra_ivc_header);
566}
567EXPORT_SYMBOL(tegra_ivc_total_queue_size);
568
569static int tegra_ivc_check_params(unsigned long rx, unsigned long tx,
570 unsigned int num_frames, size_t frame_size)
571{
572 BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct tegra_ivc_header, tx.count),
573 TEGRA_IVC_ALIGN));
574 BUILD_BUG_ON(!IS_ALIGNED(offsetof(struct tegra_ivc_header, rx.count),
575 TEGRA_IVC_ALIGN));
576 BUILD_BUG_ON(!IS_ALIGNED(sizeof(struct tegra_ivc_header),
577 TEGRA_IVC_ALIGN));
578
579 if ((uint64_t)num_frames * (uint64_t)frame_size >= 0x100000000UL) {
580 pr_err("num_frames * frame_size overflows\n");
581 return -EINVAL;
582 }
583
584 if (!IS_ALIGNED(frame_size, TEGRA_IVC_ALIGN)) {
585 pr_err("frame size not adequately aligned: %zu\n", frame_size);
586 return -EINVAL;
587 }
588
589 /*
590 * The headers must at least be aligned enough for counters
591 * to be accessed atomically.
592 */
593 if (!IS_ALIGNED(rx, TEGRA_IVC_ALIGN)) {
594 pr_err("IVC channel start not aligned: %#lx\n", rx);
595 return -EINVAL;
596 }
597
598 if (!IS_ALIGNED(tx, TEGRA_IVC_ALIGN)) {
599 pr_err("IVC channel start not aligned: %#lx\n", tx);
600 return -EINVAL;
601 }
602
603 if (rx < tx) {
604 if (rx + frame_size * num_frames > tx) {
605 pr_err("queue regions overlap: %#lx + %zx > %#lx\n",
606 rx, frame_size * num_frames, tx);
607 return -EINVAL;
608 }
609 } else {
610 if (tx + frame_size * num_frames > rx) {
611 pr_err("queue regions overlap: %#lx + %zx > %#lx\n",
612 tx, frame_size * num_frames, rx);
613 return -EINVAL;
614 }
615 }
616
617 return 0;
618}
619
620int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
621 dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
622 unsigned int num_frames, size_t frame_size,
623 void (*notify)(struct tegra_ivc *ivc, void *data),
624 void *data)
625{
626 size_t queue_size;
627 int err;
628
629 if (WARN_ON(!ivc || !notify))
630 return -EINVAL;
631
632 /*
633 * All sizes that can be returned by communication functions should
634 * fit in an int.
635 */
636 if (frame_size > INT_MAX)
637 return -E2BIG;
638
639 err = tegra_ivc_check_params((unsigned long)rx, (unsigned long)tx,
640 num_frames, frame_size);
641 if (err < 0)
642 return err;
643
644 queue_size = tegra_ivc_total_queue_size(num_frames * frame_size);
645
646 if (peer) {
647 ivc->rx.phys = dma_map_single(peer, rx, queue_size,
648 DMA_BIDIRECTIONAL);
649 if (ivc->rx.phys == DMA_ERROR_CODE)
650 return -ENOMEM;
651
652 ivc->tx.phys = dma_map_single(peer, tx, queue_size,
653 DMA_BIDIRECTIONAL);
654 if (ivc->tx.phys == DMA_ERROR_CODE) {
655 dma_unmap_single(peer, ivc->rx.phys, queue_size,
656 DMA_BIDIRECTIONAL);
657 return -ENOMEM;
658 }
659 } else {
660 ivc->rx.phys = rx_phys;
661 ivc->tx.phys = tx_phys;
662 }
663
664 ivc->rx.channel = rx;
665 ivc->tx.channel = tx;
666 ivc->peer = peer;
667 ivc->notify = notify;
668 ivc->notify_data = data;
669 ivc->frame_size = frame_size;
670 ivc->num_frames = num_frames;
671
672 /*
673 * These values aren't necessarily correct until the channel has been
674 * reset.
675 */
676 ivc->tx.position = 0;
677 ivc->rx.position = 0;
678
679 return 0;
680}
681EXPORT_SYMBOL(tegra_ivc_init);
682
683void tegra_ivc_cleanup(struct tegra_ivc *ivc)
684{
685 if (ivc->peer) {
686 size_t size = tegra_ivc_total_queue_size(ivc->num_frames *
687 ivc->frame_size);
688
689 dma_unmap_single(ivc->peer, ivc->rx.phys, size,
690 DMA_BIDIRECTIONAL);
691 dma_unmap_single(ivc->peer, ivc->tx.phys, size,
692 DMA_BIDIRECTIONAL);
693 }
694}
695EXPORT_SYMBOL(tegra_ivc_cleanup);
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 11eebfe8a4cb..ceff415f201c 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -124,6 +124,15 @@ config MAILBOX_TEST
124 Test client to help with testing new Controller driver 124 Test client to help with testing new Controller driver
125 implementations. 125 implementations.
126 126
127config TEGRA_HSP_MBOX
128 bool "Tegra HSP (Hardware Synchronization Primitives) Driver"
129 depends on ARCH_TEGRA_186_SOC
130 help
131 The Tegra HSP driver is used for the interprocessor communication
132 between different remote processors and host processors on Tegra186
133 and later SoCs. Say Y here if you want to have this support.
134 If unsure say N.
135
127config XGENE_SLIMPRO_MBOX 136config XGENE_SLIMPRO_MBOX
128 tristate "APM SoC X-Gene SLIMpro Mailbox Controller" 137 tristate "APM SoC X-Gene SLIMpro Mailbox Controller"
129 depends on ARCH_XGENE 138 depends on ARCH_XGENE
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index ace6fed8fea9..7dde4f609ae8 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -29,3 +29,5 @@ obj-$(CONFIG_XGENE_SLIMPRO_MBOX) += mailbox-xgene-slimpro.o
29obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o 29obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o
30 30
31obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o 31obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
32
33obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
diff --git a/drivers/mailbox/tegra-hsp.c b/drivers/mailbox/tegra-hsp.c
new file mode 100644
index 000000000000..0cde356c11ab
--- /dev/null
+++ b/drivers/mailbox/tegra-hsp.c
@@ -0,0 +1,479 @@
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/interrupt.h>
15#include <linux/io.h>
16#include <linux/mailbox_controller.h>
17#include <linux/of.h>
18#include <linux/of_device.h>
19#include <linux/platform_device.h>
20#include <linux/slab.h>
21
22#include <dt-bindings/mailbox/tegra186-hsp.h>
23
24#define HSP_INT_DIMENSIONING 0x380
25#define HSP_nSM_SHIFT 0
26#define HSP_nSS_SHIFT 4
27#define HSP_nAS_SHIFT 8
28#define HSP_nDB_SHIFT 12
29#define HSP_nSI_SHIFT 16
30#define HSP_nINT_MASK 0xf
31
32#define HSP_DB_TRIGGER 0x0
33#define HSP_DB_ENABLE 0x4
34#define HSP_DB_RAW 0x8
35#define HSP_DB_PENDING 0xc
36
37#define HSP_DB_CCPLEX 1
38#define HSP_DB_BPMP 3
39#define HSP_DB_MAX 7
40
41struct tegra_hsp_channel;
42struct tegra_hsp;
43
44struct tegra_hsp_channel {
45 struct tegra_hsp *hsp;
46 struct mbox_chan *chan;
47 void __iomem *regs;
48};
49
50struct tegra_hsp_doorbell {
51 struct tegra_hsp_channel channel;
52 struct list_head list;
53 const char *name;
54 unsigned int master;
55 unsigned int index;
56};
57
58struct tegra_hsp_db_map {
59 const char *name;
60 unsigned int master;
61 unsigned int index;
62};
63
64struct tegra_hsp_soc {
65 const struct tegra_hsp_db_map *map;
66};
67
68struct tegra_hsp {
69 const struct tegra_hsp_soc *soc;
70 struct mbox_controller mbox;
71 void __iomem *regs;
72 unsigned int irq;
73 unsigned int num_sm;
74 unsigned int num_as;
75 unsigned int num_ss;
76 unsigned int num_db;
77 unsigned int num_si;
78 spinlock_t lock;
79
80 struct list_head doorbells;
81};
82
83static inline struct tegra_hsp *
84to_tegra_hsp(struct mbox_controller *mbox)
85{
86 return container_of(mbox, struct tegra_hsp, mbox);
87}
88
89static inline u32 tegra_hsp_readl(struct tegra_hsp *hsp, unsigned int offset)
90{
91 return readl(hsp->regs + offset);
92}
93
94static inline void tegra_hsp_writel(struct tegra_hsp *hsp, u32 value,
95 unsigned int offset)
96{
97 writel(value, hsp->regs + offset);
98}
99
100static inline u32 tegra_hsp_channel_readl(struct tegra_hsp_channel *channel,
101 unsigned int offset)
102{
103 return readl(channel->regs + offset);
104}
105
106static inline void tegra_hsp_channel_writel(struct tegra_hsp_channel *channel,
107 u32 value, unsigned int offset)
108{
109 writel(value, channel->regs + offset);
110}
111
112static bool tegra_hsp_doorbell_can_ring(struct tegra_hsp_doorbell *db)
113{
114 u32 value;
115
116 value = tegra_hsp_channel_readl(&db->channel, HSP_DB_ENABLE);
117
118 return (value & BIT(TEGRA_HSP_DB_MASTER_CCPLEX)) != 0;
119}
120
121static struct tegra_hsp_doorbell *
122__tegra_hsp_doorbell_get(struct tegra_hsp *hsp, unsigned int master)
123{
124 struct tegra_hsp_doorbell *entry;
125
126 list_for_each_entry(entry, &hsp->doorbells, list)
127 if (entry->master == master)
128 return entry;
129
130 return NULL;
131}
132
133static struct tegra_hsp_doorbell *
134tegra_hsp_doorbell_get(struct tegra_hsp *hsp, unsigned int master)
135{
136 struct tegra_hsp_doorbell *db;
137 unsigned long flags;
138
139 spin_lock_irqsave(&hsp->lock, flags);
140 db = __tegra_hsp_doorbell_get(hsp, master);
141 spin_unlock_irqrestore(&hsp->lock, flags);
142
143 return db;
144}
145
146static irqreturn_t tegra_hsp_doorbell_irq(int irq, void *data)
147{
148 struct tegra_hsp *hsp = data;
149 struct tegra_hsp_doorbell *db;
150 unsigned long master, value;
151
152 db = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
153 if (!db)
154 return IRQ_NONE;
155
156 value = tegra_hsp_channel_readl(&db->channel, HSP_DB_PENDING);
157 tegra_hsp_channel_writel(&db->channel, value, HSP_DB_PENDING);
158
159 spin_lock(&hsp->lock);
160
161 for_each_set_bit(master, &value, hsp->mbox.num_chans) {
162 struct tegra_hsp_doorbell *db;
163
164 db = __tegra_hsp_doorbell_get(hsp, master);
165 /*
166 * Depending on the bootloader chain, the CCPLEX doorbell will
167 * have some doorbells enabled, which means that requesting an
168 * interrupt will immediately fire.
169 *
170 * In that case, db->channel.chan will still be NULL here and
171 * cause a crash if not properly guarded.
172 *
173 * It remains to be seen if ignoring the doorbell in that case
174 * is the correct solution.
175 */
176 if (db && db->channel.chan)
177 mbox_chan_received_data(db->channel.chan, NULL);
178 }
179
180 spin_unlock(&hsp->lock);
181
182 return IRQ_HANDLED;
183}
184
185static struct tegra_hsp_channel *
186tegra_hsp_doorbell_create(struct tegra_hsp *hsp, const char *name,
187 unsigned int master, unsigned int index)
188{
189 struct tegra_hsp_doorbell *db;
190 unsigned int offset;
191 unsigned long flags;
192
193 db = kzalloc(sizeof(*db), GFP_KERNEL);
194 if (!db)
195 return ERR_PTR(-ENOMEM);
196
197 offset = (1 + (hsp->num_sm / 2) + hsp->num_ss + hsp->num_as) << 16;
198 offset += index * 0x100;
199
200 db->channel.regs = hsp->regs + offset;
201 db->channel.hsp = hsp;
202
203 db->name = kstrdup_const(name, GFP_KERNEL);
204 db->master = master;
205 db->index = index;
206
207 spin_lock_irqsave(&hsp->lock, flags);
208 list_add_tail(&db->list, &hsp->doorbells);
209 spin_unlock_irqrestore(&hsp->lock, flags);
210
211 return &db->channel;
212}
213
214static void __tegra_hsp_doorbell_destroy(struct tegra_hsp_doorbell *db)
215{
216 list_del(&db->list);
217 kfree_const(db->name);
218 kfree(db);
219}
220
221static int tegra_hsp_doorbell_send_data(struct mbox_chan *chan, void *data)
222{
223 struct tegra_hsp_doorbell *db = chan->con_priv;
224
225 tegra_hsp_channel_writel(&db->channel, 1, HSP_DB_TRIGGER);
226
227 return 0;
228}
229
230static int tegra_hsp_doorbell_startup(struct mbox_chan *chan)
231{
232 struct tegra_hsp_doorbell *db = chan->con_priv;
233 struct tegra_hsp *hsp = db->channel.hsp;
234 struct tegra_hsp_doorbell *ccplex;
235 unsigned long flags;
236 u32 value;
237
238 if (db->master >= hsp->mbox.num_chans) {
239 dev_err(hsp->mbox.dev,
240 "invalid master ID %u for HSP channel\n",
241 db->master);
242 return -EINVAL;
243 }
244
245 ccplex = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
246 if (!ccplex)
247 return -ENODEV;
248
249 if (!tegra_hsp_doorbell_can_ring(db))
250 return -ENODEV;
251
252 spin_lock_irqsave(&hsp->lock, flags);
253
254 value = tegra_hsp_channel_readl(&ccplex->channel, HSP_DB_ENABLE);
255 value |= BIT(db->master);
256 tegra_hsp_channel_writel(&ccplex->channel, value, HSP_DB_ENABLE);
257
258 spin_unlock_irqrestore(&hsp->lock, flags);
259
260 return 0;
261}
262
263static void tegra_hsp_doorbell_shutdown(struct mbox_chan *chan)
264{
265 struct tegra_hsp_doorbell *db = chan->con_priv;
266 struct tegra_hsp *hsp = db->channel.hsp;
267 struct tegra_hsp_doorbell *ccplex;
268 unsigned long flags;
269 u32 value;
270
271 ccplex = tegra_hsp_doorbell_get(hsp, TEGRA_HSP_DB_MASTER_CCPLEX);
272 if (!ccplex)
273 return;
274
275 spin_lock_irqsave(&hsp->lock, flags);
276
277 value = tegra_hsp_channel_readl(&ccplex->channel, HSP_DB_ENABLE);
278 value &= ~BIT(db->master);
279 tegra_hsp_channel_writel(&ccplex->channel, value, HSP_DB_ENABLE);
280
281 spin_unlock_irqrestore(&hsp->lock, flags);
282}
283
284static const struct mbox_chan_ops tegra_hsp_doorbell_ops = {
285 .send_data = tegra_hsp_doorbell_send_data,
286 .startup = tegra_hsp_doorbell_startup,
287 .shutdown = tegra_hsp_doorbell_shutdown,
288};
289
290static struct mbox_chan *of_tegra_hsp_xlate(struct mbox_controller *mbox,
291 const struct of_phandle_args *args)
292{
293 struct tegra_hsp_channel *channel = ERR_PTR(-ENODEV);
294 struct tegra_hsp *hsp = to_tegra_hsp(mbox);
295 unsigned int type = args->args[0];
296 unsigned int master = args->args[1];
297 struct tegra_hsp_doorbell *db;
298 struct mbox_chan *chan;
299 unsigned long flags;
300 unsigned int i;
301
302 switch (type) {
303 case TEGRA_HSP_MBOX_TYPE_DB:
304 db = tegra_hsp_doorbell_get(hsp, master);
305 if (db)
306 channel = &db->channel;
307
308 break;
309
310 default:
311 break;
312 }
313
314 if (IS_ERR(channel))
315 return ERR_CAST(channel);
316
317 spin_lock_irqsave(&hsp->lock, flags);
318
319 for (i = 0; i < hsp->mbox.num_chans; i++) {
320 chan = &hsp->mbox.chans[i];
321 if (!chan->con_priv) {
322 chan->con_priv = channel;
323 channel->chan = chan;
324 break;
325 }
326
327 chan = NULL;
328 }
329
330 spin_unlock_irqrestore(&hsp->lock, flags);
331
332 return chan ?: ERR_PTR(-EBUSY);
333}
334
335static void tegra_hsp_remove_doorbells(struct tegra_hsp *hsp)
336{
337 struct tegra_hsp_doorbell *db, *tmp;
338 unsigned long flags;
339
340 spin_lock_irqsave(&hsp->lock, flags);
341
342 list_for_each_entry_safe(db, tmp, &hsp->doorbells, list)
343 __tegra_hsp_doorbell_destroy(db);
344
345 spin_unlock_irqrestore(&hsp->lock, flags);
346}
347
348static int tegra_hsp_add_doorbells(struct tegra_hsp *hsp)
349{
350 const struct tegra_hsp_db_map *map = hsp->soc->map;
351 struct tegra_hsp_channel *channel;
352
353 while (map->name) {
354 channel = tegra_hsp_doorbell_create(hsp, map->name,
355 map->master, map->index);
356 if (IS_ERR(channel)) {
357 tegra_hsp_remove_doorbells(hsp);
358 return PTR_ERR(channel);
359 }
360
361 map++;
362 }
363
364 return 0;
365}
366
367static int tegra_hsp_probe(struct platform_device *pdev)
368{
369 struct tegra_hsp *hsp;
370 struct resource *res;
371 u32 value;
372 int err;
373
374 hsp = devm_kzalloc(&pdev->dev, sizeof(*hsp), GFP_KERNEL);
375 if (!hsp)
376 return -ENOMEM;
377
378 hsp->soc = of_device_get_match_data(&pdev->dev);
379 INIT_LIST_HEAD(&hsp->doorbells);
380 spin_lock_init(&hsp->lock);
381
382 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
383 hsp->regs = devm_ioremap_resource(&pdev->dev, res);
384 if (IS_ERR(hsp->regs))
385 return PTR_ERR(hsp->regs);
386
387 value = tegra_hsp_readl(hsp, HSP_INT_DIMENSIONING);
388 hsp->num_sm = (value >> HSP_nSM_SHIFT) & HSP_nINT_MASK;
389 hsp->num_ss = (value >> HSP_nSS_SHIFT) & HSP_nINT_MASK;
390 hsp->num_as = (value >> HSP_nAS_SHIFT) & HSP_nINT_MASK;
391 hsp->num_db = (value >> HSP_nDB_SHIFT) & HSP_nINT_MASK;
392 hsp->num_si = (value >> HSP_nSI_SHIFT) & HSP_nINT_MASK;
393
394 err = platform_get_irq_byname(pdev, "doorbell");
395 if (err < 0) {
396 dev_err(&pdev->dev, "failed to get doorbell IRQ: %d\n", err);
397 return err;
398 }
399
400 hsp->irq = err;
401
402 hsp->mbox.of_xlate = of_tegra_hsp_xlate;
403 hsp->mbox.num_chans = 32;
404 hsp->mbox.dev = &pdev->dev;
405 hsp->mbox.txdone_irq = false;
406 hsp->mbox.txdone_poll = false;
407 hsp->mbox.ops = &tegra_hsp_doorbell_ops;
408
409 hsp->mbox.chans = devm_kcalloc(&pdev->dev, hsp->mbox.num_chans,
410 sizeof(*hsp->mbox.chans),
411 GFP_KERNEL);
412 if (!hsp->mbox.chans)
413 return -ENOMEM;
414
415 err = tegra_hsp_add_doorbells(hsp);
416 if (err < 0) {
417 dev_err(&pdev->dev, "failed to add doorbells: %d\n", err);
418 return err;
419 }
420
421 platform_set_drvdata(pdev, hsp);
422
423 err = mbox_controller_register(&hsp->mbox);
424 if (err) {
425 dev_err(&pdev->dev, "failed to register mailbox: %d\n", err);
426 tegra_hsp_remove_doorbells(hsp);
427 return err;
428 }
429
430 err = devm_request_irq(&pdev->dev, hsp->irq, tegra_hsp_doorbell_irq,
431 IRQF_NO_SUSPEND, dev_name(&pdev->dev), hsp);
432 if (err < 0) {
433 dev_err(&pdev->dev, "failed to request IRQ#%u: %d\n",
434 hsp->irq, err);
435 return err;
436 }
437
438 return 0;
439}
440
441static int tegra_hsp_remove(struct platform_device *pdev)
442{
443 struct tegra_hsp *hsp = platform_get_drvdata(pdev);
444
445 mbox_controller_unregister(&hsp->mbox);
446 tegra_hsp_remove_doorbells(hsp);
447
448 return 0;
449}
450
451static const struct tegra_hsp_db_map tegra186_hsp_db_map[] = {
452 { "ccplex", TEGRA_HSP_DB_MASTER_CCPLEX, HSP_DB_CCPLEX, },
453 { "bpmp", TEGRA_HSP_DB_MASTER_BPMP, HSP_DB_BPMP, },
454 { /* sentinel */ }
455};
456
457static const struct tegra_hsp_soc tegra186_hsp_soc = {
458 .map = tegra186_hsp_db_map,
459};
460
461static const struct of_device_id tegra_hsp_match[] = {
462 { .compatible = "nvidia,tegra186-hsp", .data = &tegra186_hsp_soc },
463 { }
464};
465
466static struct platform_driver tegra_hsp_driver = {
467 .driver = {
468 .name = "tegra-hsp",
469 .of_match_table = tegra_hsp_match,
470 },
471 .probe = tegra_hsp_probe,
472 .remove = tegra_hsp_remove,
473};
474
475static int __init tegra_hsp_init(void)
476{
477 return platform_driver_register(&tegra_hsp_driver);
478}
479core_initcall(tegra_hsp_init);
diff --git a/drivers/soc/tegra/Kconfig b/drivers/soc/tegra/Kconfig
index 03089ad2fc65..e5e124c07066 100644
--- a/drivers/soc/tegra/Kconfig
+++ b/drivers/soc/tegra/Kconfig
@@ -77,5 +77,19 @@ config ARCH_TEGRA_210_SOC
77 controllers, such as GPIO, I2C, SPI, SDHCI, PCIe, SATA and XHCI, to 77 controllers, such as GPIO, I2C, SPI, SDHCI, PCIe, SATA and XHCI, to
78 name only a few. 78 name only a few.
79 79
80config ARCH_TEGRA_186_SOC
81 bool "NVIDIA Tegra186 SoC"
82 select MAILBOX
83 select TEGRA_BPMP
84 select TEGRA_HSP_MBOX
85 select TEGRA_IVC
86 help
87 Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a
88 combination of Denver and Cortex-A57 CPU cores and a GPU based on
89 the Pascal architecture. It contains an ADSP with a Cortex-A9 CPU
90 used for audio processing, hardware video encoders/decoders with
91 multi-format support, ISP for image capture processing and BPMP for
92 power management.
93
80endif 94endif
81endif 95endif
diff --git a/include/dt-bindings/clock/tegra186-clock.h b/include/dt-bindings/clock/tegra186-clock.h
new file mode 100644
index 000000000000..f73d32098f99
--- /dev/null
+++ b/include/dt-bindings/clock/tegra186-clock.h
@@ -0,0 +1,940 @@
1/** @file */
2
3#ifndef _MACH_T186_CLK_T186_H
4#define _MACH_T186_CLK_T186_H
5
6/**
7 * @defgroup clock_ids Clock Identifiers
8 * @{
9 * @defgroup extern_input external input clocks
10 * @{
11 * @def TEGRA186_CLK_OSC
12 * @def TEGRA186_CLK_CLK_32K
13 * @def TEGRA186_CLK_DTV_INPUT
14 * @def TEGRA186_CLK_SOR0_PAD_CLKOUT
15 * @def TEGRA186_CLK_SOR1_PAD_CLKOUT
16 * @def TEGRA186_CLK_I2S1_SYNC_INPUT
17 * @def TEGRA186_CLK_I2S2_SYNC_INPUT
18 * @def TEGRA186_CLK_I2S3_SYNC_INPUT
19 * @def TEGRA186_CLK_I2S4_SYNC_INPUT
20 * @def TEGRA186_CLK_I2S5_SYNC_INPUT
21 * @def TEGRA186_CLK_I2S6_SYNC_INPUT
22 * @def TEGRA186_CLK_SPDIFIN_SYNC_INPUT
23 * @}
24 *
25 * @defgroup extern_output external output clocks
26 * @{
27 * @def TEGRA186_CLK_EXTPERIPH1
28 * @def TEGRA186_CLK_EXTPERIPH2
29 * @def TEGRA186_CLK_EXTPERIPH3
30 * @def TEGRA186_CLK_EXTPERIPH4
31 * @}
32 *
33 * @defgroup display_clks display related clocks
34 * @{
35 * @def TEGRA186_CLK_CEC
36 * @def TEGRA186_CLK_DSIC
37 * @def TEGRA186_CLK_DSIC_LP
38 * @def TEGRA186_CLK_DSID
39 * @def TEGRA186_CLK_DSID_LP
40 * @def TEGRA186_CLK_DPAUX1
41 * @def TEGRA186_CLK_DPAUX
42 * @def TEGRA186_CLK_HDA2HDMICODEC
43 * @def TEGRA186_CLK_NVDISPLAY_DISP
44 * @def TEGRA186_CLK_NVDISPLAY_DSC
45 * @def TEGRA186_CLK_NVDISPLAY_P0
46 * @def TEGRA186_CLK_NVDISPLAY_P1
47 * @def TEGRA186_CLK_NVDISPLAY_P2
48 * @def TEGRA186_CLK_NVDISPLAYHUB
49 * @def TEGRA186_CLK_SOR_SAFE
50 * @def TEGRA186_CLK_SOR0
51 * @def TEGRA186_CLK_SOR0_OUT
52 * @def TEGRA186_CLK_SOR1
53 * @def TEGRA186_CLK_SOR1_OUT
54 * @def TEGRA186_CLK_DSI
55 * @def TEGRA186_CLK_MIPI_CAL
56 * @def TEGRA186_CLK_DSIA_LP
57 * @def TEGRA186_CLK_DSIB
58 * @def TEGRA186_CLK_DSIB_LP
59 * @}
60 *
61 * @defgroup camera_clks camera related clocks
62 * @{
63 * @def TEGRA186_CLK_NVCSI
64 * @def TEGRA186_CLK_NVCSILP
65 * @def TEGRA186_CLK_VI
66 * @}
67 *
68 * @defgroup audio_clks audio related clocks
69 * @{
70 * @def TEGRA186_CLK_ACLK
71 * @def TEGRA186_CLK_ADSP
72 * @def TEGRA186_CLK_ADSPNEON
73 * @def TEGRA186_CLK_AHUB
74 * @def TEGRA186_CLK_APE
75 * @def TEGRA186_CLK_APB2APE
76 * @def TEGRA186_CLK_AUD_MCLK
77 * @def TEGRA186_CLK_DMIC1
78 * @def TEGRA186_CLK_DMIC2
79 * @def TEGRA186_CLK_DMIC3
80 * @def TEGRA186_CLK_DMIC4
81 * @def TEGRA186_CLK_DSPK1
82 * @def TEGRA186_CLK_DSPK2
83 * @def TEGRA186_CLK_HDA
84 * @def TEGRA186_CLK_HDA2CODEC_2X
85 * @def TEGRA186_CLK_I2S1
86 * @def TEGRA186_CLK_I2S2
87 * @def TEGRA186_CLK_I2S3
88 * @def TEGRA186_CLK_I2S4
89 * @def TEGRA186_CLK_I2S5
90 * @def TEGRA186_CLK_I2S6
91 * @def TEGRA186_CLK_MAUD
92 * @def TEGRA186_CLK_PLL_A_OUT0
93 * @def TEGRA186_CLK_SPDIF_DOUBLER
94 * @def TEGRA186_CLK_SPDIF_IN
95 * @def TEGRA186_CLK_SPDIF_OUT
96 * @def TEGRA186_CLK_SYNC_DMIC1
97 * @def TEGRA186_CLK_SYNC_DMIC2
98 * @def TEGRA186_CLK_SYNC_DMIC3
99 * @def TEGRA186_CLK_SYNC_DMIC4
100 * @def TEGRA186_CLK_SYNC_DMIC5
101 * @def TEGRA186_CLK_SYNC_DSPK1
102 * @def TEGRA186_CLK_SYNC_DSPK2
103 * @def TEGRA186_CLK_SYNC_I2S1
104 * @def TEGRA186_CLK_SYNC_I2S2
105 * @def TEGRA186_CLK_SYNC_I2S3
106 * @def TEGRA186_CLK_SYNC_I2S4
107 * @def TEGRA186_CLK_SYNC_I2S5
108 * @def TEGRA186_CLK_SYNC_I2S6
109 * @def TEGRA186_CLK_SYNC_SPDIF
110 * @}
111 *
112 * @defgroup uart_clks UART clocks
113 * @{
114 * @def TEGRA186_CLK_AON_UART_FST_MIPI_CAL
115 * @def TEGRA186_CLK_UARTA
116 * @def TEGRA186_CLK_UARTB
117 * @def TEGRA186_CLK_UARTC
118 * @def TEGRA186_CLK_UARTD
119 * @def TEGRA186_CLK_UARTE
120 * @def TEGRA186_CLK_UARTF
121 * @def TEGRA186_CLK_UARTG
122 * @def TEGRA186_CLK_UART_FST_MIPI_CAL
123 * @}
124 *
125 * @defgroup i2c_clks I2C clocks
126 * @{
127 * @def TEGRA186_CLK_AON_I2C_SLOW
128 * @def TEGRA186_CLK_I2C1
129 * @def TEGRA186_CLK_I2C2
130 * @def TEGRA186_CLK_I2C3
131 * @def TEGRA186_CLK_I2C4
132 * @def TEGRA186_CLK_I2C5
133 * @def TEGRA186_CLK_I2C6
134 * @def TEGRA186_CLK_I2C8
135 * @def TEGRA186_CLK_I2C9
136 * @def TEGRA186_CLK_I2C1
137 * @def TEGRA186_CLK_I2C12
138 * @def TEGRA186_CLK_I2C13
139 * @def TEGRA186_CLK_I2C14
140 * @def TEGRA186_CLK_I2C_SLOW
141 * @def TEGRA186_CLK_VI_I2C
142 * @}
143 *
144 * @defgroup spi_clks SPI clocks
145 * @{
146 * @def TEGRA186_CLK_SPI1
147 * @def TEGRA186_CLK_SPI2
148 * @def TEGRA186_CLK_SPI3
149 * @def TEGRA186_CLK_SPI4
150 * @}
151 *
152 * @defgroup storage storage related clocks
153 * @{
154 * @def TEGRA186_CLK_SATA
155 * @def TEGRA186_CLK_SATA_OOB
156 * @def TEGRA186_CLK_SATA_IOBIST
157 * @def TEGRA186_CLK_SDMMC_LEGACY_TM
158 * @def TEGRA186_CLK_SDMMC1
159 * @def TEGRA186_CLK_SDMMC2
160 * @def TEGRA186_CLK_SDMMC3
161 * @def TEGRA186_CLK_SDMMC4
162 * @def TEGRA186_CLK_QSPI
163 * @def TEGRA186_CLK_QSPI_OUT
164 * @def TEGRA186_CLK_UFSDEV_REF
165 * @def TEGRA186_CLK_UFSHC
166 * @}
167 *
168 * @defgroup pwm_clks PWM clocks
169 * @{
170 * @def TEGRA186_CLK_PWM1
171 * @def TEGRA186_CLK_PWM2
172 * @def TEGRA186_CLK_PWM3
173 * @def TEGRA186_CLK_PWM4
174 * @def TEGRA186_CLK_PWM5
175 * @def TEGRA186_CLK_PWM6
176 * @def TEGRA186_CLK_PWM7
177 * @def TEGRA186_CLK_PWM8
178 * @}
179 *
180 * @defgroup plls PLLs and related clocks
181 * @{
182 * @def TEGRA186_CLK_PLLREFE_OUT_GATED
183 * @def TEGRA186_CLK_PLLREFE_OUT1
184 * @def TEGRA186_CLK_PLLD_OUT1
185 * @def TEGRA186_CLK_PLLP_OUT0
186 * @def TEGRA186_CLK_PLLP_OUT5
187 * @def TEGRA186_CLK_PLLA
188 * @def TEGRA186_CLK_PLLE_PWRSEQ
189 * @def TEGRA186_CLK_PLLA_OUT1
190 * @def TEGRA186_CLK_PLLREFE_REF
191 * @def TEGRA186_CLK_UPHY_PLL0_PWRSEQ
192 * @def TEGRA186_CLK_UPHY_PLL1_PWRSEQ
193 * @def TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH
194 * @def TEGRA186_CLK_PLLREFE_PEX
195 * @def TEGRA186_CLK_PLLREFE_IDDQ
196 * @def TEGRA186_CLK_PLLC_OUT_AON
197 * @def TEGRA186_CLK_PLLC_OUT_ISP
198 * @def TEGRA186_CLK_PLLC_OUT_VE
199 * @def TEGRA186_CLK_PLLC4_OUT
200 * @def TEGRA186_CLK_PLLREFE_OUT
201 * @def TEGRA186_CLK_PLLREFE_PLL_REF
202 * @def TEGRA186_CLK_PLLE
203 * @def TEGRA186_CLK_PLLC
204 * @def TEGRA186_CLK_PLLP
205 * @def TEGRA186_CLK_PLLD
206 * @def TEGRA186_CLK_PLLD2
207 * @def TEGRA186_CLK_PLLREFE_VCO
208 * @def TEGRA186_CLK_PLLC2
209 * @def TEGRA186_CLK_PLLC3
210 * @def TEGRA186_CLK_PLLDP
211 * @def TEGRA186_CLK_PLLC4_VCO
212 * @def TEGRA186_CLK_PLLA1
213 * @def TEGRA186_CLK_PLLNVCSI
214 * @def TEGRA186_CLK_PLLDISPHUB
215 * @def TEGRA186_CLK_PLLD3
216 * @def TEGRA186_CLK_PLLBPMPCAM
217 * @def TEGRA186_CLK_PLLAON
218 * @def TEGRA186_CLK_PLLU
219 * @def TEGRA186_CLK_PLLC4_VCO_DIV2
220 * @def TEGRA186_CLK_PLL_REF
221 * @def TEGRA186_CLK_PLLREFE_OUT1_DIV5
222 * @def TEGRA186_CLK_UTMIP_PLL_PWRSEQ
223 * @def TEGRA186_CLK_PLL_U_48M
224 * @def TEGRA186_CLK_PLL_U_480M
225 * @def TEGRA186_CLK_PLLC4_OUT0
226 * @def TEGRA186_CLK_PLLC4_OUT1
227 * @def TEGRA186_CLK_PLLC4_OUT2
228 * @def TEGRA186_CLK_PLLC4_OUT_MUX
229 * @def TEGRA186_CLK_DFLLDISP_DIV
230 * @def TEGRA186_CLK_PLLDISPHUB_DIV
231 * @def TEGRA186_CLK_PLLP_DIV8
232 * @}
233 *
234 * @defgroup nafll_clks NAFLL clock sources
235 * @{
236 * @def TEGRA186_CLK_NAFLL_AXI_CBB
237 * @def TEGRA186_CLK_NAFLL_BCPU
238 * @def TEGRA186_CLK_NAFLL_BPMP
239 * @def TEGRA186_CLK_NAFLL_DISP
240 * @def TEGRA186_CLK_NAFLL_GPU
241 * @def TEGRA186_CLK_NAFLL_ISP
242 * @def TEGRA186_CLK_NAFLL_MCPU
243 * @def TEGRA186_CLK_NAFLL_NVDEC
244 * @def TEGRA186_CLK_NAFLL_NVENC
245 * @def TEGRA186_CLK_NAFLL_NVJPG
246 * @def TEGRA186_CLK_NAFLL_SCE
247 * @def TEGRA186_CLK_NAFLL_SE
248 * @def TEGRA186_CLK_NAFLL_TSEC
249 * @def TEGRA186_CLK_NAFLL_TSECB
250 * @def TEGRA186_CLK_NAFLL_VI
251 * @def TEGRA186_CLK_NAFLL_VIC
252 * @}
253 *
254 * @defgroup mphy MPHY related clocks
255 * @{
256 * @def TEGRA186_CLK_MPHY_L0_RX_SYMB
257 * @def TEGRA186_CLK_MPHY_L0_RX_LS_BIT
258 * @def TEGRA186_CLK_MPHY_L0_TX_SYMB
259 * @def TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT
260 * @def TEGRA186_CLK_MPHY_L0_RX_ANA
261 * @def TEGRA186_CLK_MPHY_L1_RX_ANA
262 * @def TEGRA186_CLK_MPHY_IOBIST
263 * @def TEGRA186_CLK_MPHY_TX_1MHZ_REF
264 * @def TEGRA186_CLK_MPHY_CORE_PLL_FIXED
265 * @}
266 *
267 * @defgroup eavb EAVB related clocks
268 * @{
269 * @def TEGRA186_CLK_EQOS_AXI
270 * @def TEGRA186_CLK_EQOS_PTP_REF
271 * @def TEGRA186_CLK_EQOS_RX
272 * @def TEGRA186_CLK_EQOS_RX_INPUT
273 * @def TEGRA186_CLK_EQOS_TX
274 * @}
275 *
276 * @defgroup usb USB related clocks
277 * @{
278 * @def TEGRA186_CLK_PEX_USB_PAD0_MGMT
279 * @def TEGRA186_CLK_PEX_USB_PAD1_MGMT
280 * @def TEGRA186_CLK_HSIC_TRK
281 * @def TEGRA186_CLK_USB2_TRK
282 * @def TEGRA186_CLK_USB2_HSIC_TRK
283 * @def TEGRA186_CLK_XUSB_CORE_SS
284 * @def TEGRA186_CLK_XUSB_CORE_DEV
285 * @def TEGRA186_CLK_XUSB_FALCON
286 * @def TEGRA186_CLK_XUSB_FS
287 * @def TEGRA186_CLK_XUSB
288 * @def TEGRA186_CLK_XUSB_DEV
289 * @def TEGRA186_CLK_XUSB_HOST
290 * @def TEGRA186_CLK_XUSB_SS
291 * @}
292 *
293 * @defgroup bigblock compute block related clocks
294 * @{
295 * @def TEGRA186_CLK_GPCCLK
296 * @def TEGRA186_CLK_GPC2CLK
297 * @def TEGRA186_CLK_GPU
298 * @def TEGRA186_CLK_HOST1X
299 * @def TEGRA186_CLK_ISP
300 * @def TEGRA186_CLK_NVDEC
301 * @def TEGRA186_CLK_NVENC
302 * @def TEGRA186_CLK_NVJPG
303 * @def TEGRA186_CLK_SE
304 * @def TEGRA186_CLK_TSEC
305 * @def TEGRA186_CLK_TSECB
306 * @def TEGRA186_CLK_VIC
307 * @}
308 *
309 * @defgroup can CAN bus related clocks
310 * @{
311 * @def TEGRA186_CLK_CAN1
312 * @def TEGRA186_CLK_CAN1_HOST
313 * @def TEGRA186_CLK_CAN2
314 * @def TEGRA186_CLK_CAN2_HOST
315 * @}
316 *
317 * @defgroup system basic system clocks
318 * @{
319 * @def TEGRA186_CLK_ACTMON
320 * @def TEGRA186_CLK_AON_APB
321 * @def TEGRA186_CLK_AON_CPU_NIC
322 * @def TEGRA186_CLK_AON_NIC
323 * @def TEGRA186_CLK_AXI_CBB
324 * @def TEGRA186_CLK_BPMP_APB
325 * @def TEGRA186_CLK_BPMP_CPU_NIC
326 * @def TEGRA186_CLK_BPMP_NIC_RATE
327 * @def TEGRA186_CLK_CLK_M
328 * @def TEGRA186_CLK_EMC
329 * @def TEGRA186_CLK_MSS_ENCRYPT
330 * @def TEGRA186_CLK_SCE_APB
331 * @def TEGRA186_CLK_SCE_CPU_NIC
332 * @def TEGRA186_CLK_SCE_NIC
333 * @def TEGRA186_CLK_TSC
334 * @}
335 *
336 * @defgroup pcie_clks PCIe related clocks
337 * @{
338 * @def TEGRA186_CLK_AFI
339 * @def TEGRA186_CLK_PCIE
340 * @def TEGRA186_CLK_PCIE2_IOBIST
341 * @def TEGRA186_CLK_PCIERX0
342 * @def TEGRA186_CLK_PCIERX1
343 * @def TEGRA186_CLK_PCIERX2
344 * @def TEGRA186_CLK_PCIERX3
345 * @def TEGRA186_CLK_PCIERX4
346 * @}
347 */
348
349/** @brief output of gate CLK_ENB_FUSE */
350#define TEGRA186_CLK_FUSE 0
351/**
352 * @brief It's not what you think
353 * @details output of gate CLK_ENB_GPU. This output connects to the GPU
354 * pwrclk. @warning: This is almost certainly not the clock you think
355 * it is. If you're looking for the clock of the graphics engine, see
356 * TEGRA186_GPCCLK
357 */
358#define TEGRA186_CLK_GPU 1
359/** @brief output of gate CLK_ENB_PCIE */
360#define TEGRA186_CLK_PCIE 3
361/** @brief output of the divider IPFS_CLK_DIVISOR */
362#define TEGRA186_CLK_AFI 4
363/** @brief output of gate CLK_ENB_PCIE2_IOBIST */
364#define TEGRA186_CLK_PCIE2_IOBIST 5
365/** @brief output of gate CLK_ENB_PCIERX0*/
366#define TEGRA186_CLK_PCIERX0 6
367/** @brief output of gate CLK_ENB_PCIERX1*/
368#define TEGRA186_CLK_PCIERX1 7
369/** @brief output of gate CLK_ENB_PCIERX2*/
370#define TEGRA186_CLK_PCIERX2 8
371/** @brief output of gate CLK_ENB_PCIERX3*/
372#define TEGRA186_CLK_PCIERX3 9
373/** @brief output of gate CLK_ENB_PCIERX4*/
374#define TEGRA186_CLK_PCIERX4 10
375/** @brief output branch of PLL_C for ISP, controlled by gate CLK_ENB_PLLC_OUT_ISP */
376#define TEGRA186_CLK_PLLC_OUT_ISP 11
377/** @brief output branch of PLL_C for VI, controlled by gate CLK_ENB_PLLC_OUT_VE */
378#define TEGRA186_CLK_PLLC_OUT_VE 12
379/** @brief output branch of PLL_C for AON domain, controlled by gate CLK_ENB_PLLC_OUT_AON */
380#define TEGRA186_CLK_PLLC_OUT_AON 13
381/** @brief output of gate CLK_ENB_SOR_SAFE */
382#define TEGRA186_CLK_SOR_SAFE 39
383/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S2 */
384#define TEGRA186_CLK_I2S2 42
385/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S3 */
386#define TEGRA186_CLK_I2S3 43
387/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDF_IN */
388#define TEGRA186_CLK_SPDIF_IN 44
389/** @brief output of gate CLK_ENB_SPDIF_DOUBLER */
390#define TEGRA186_CLK_SPDIF_DOUBLER 45
391/** @clkdesc{spi_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_SPI3} */
392#define TEGRA186_CLK_SPI3 46
393/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C1} */
394#define TEGRA186_CLK_I2C1 47
395/** @clkdesc{i2c_clks, out, mux, CLK_RST_CONTROLLER_CLK_SOURCE_I2C5} */
396#define TEGRA186_CLK_I2C5 48
397/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI1 */
398#define TEGRA186_CLK_SPI1 49
399/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_ISP */
400#define TEGRA186_CLK_ISP 50
401/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI */
402#define TEGRA186_CLK_VI 51
403/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC1 */
404#define TEGRA186_CLK_SDMMC1 52
405/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC2 */
406#define TEGRA186_CLK_SDMMC2 53
407/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC4 */
408#define TEGRA186_CLK_SDMMC4 54
409/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTA */
410#define TEGRA186_CLK_UARTA 55
411/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTB */
412#define TEGRA186_CLK_UARTB 56
413/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HOST1X */
414#define TEGRA186_CLK_HOST1X 57
415/**
416 * @brief controls the EMC clock frequency.
417 * @details Doing a clk_set_rate on this clock will select the
418 * appropriate clock source, program the source rate and execute a
419 * specific sequence to switch to the new clock source for both memory
420 * controllers. This can be used to control the balance between memory
421 * throughput and memory controller power.
422 */
423#define TEGRA186_CLK_EMC 58
424/* @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH4 */
425#define TEGRA186_CLK_EXTPERIPH4 73
426/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI4 */
427#define TEGRA186_CLK_SPI4 74
428/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C3 */
429#define TEGRA186_CLK_I2C3 75
430/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC3 */
431#define TEGRA186_CLK_SDMMC3 76
432/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTD */
433#define TEGRA186_CLK_UARTD 77
434/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S1 */
435#define TEGRA186_CLK_I2S1 79
436/** output of gate CLK_ENB_DTV */
437#define TEGRA186_CLK_DTV 80
438/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSEC */
439#define TEGRA186_CLK_TSEC 81
440/** @brief output of gate CLK_ENB_DP2 */
441#define TEGRA186_CLK_DP2 82
442/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S4 */
443#define TEGRA186_CLK_I2S4 84
444/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2S5 */
445#define TEGRA186_CLK_I2S5 85
446/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C4 */
447#define TEGRA186_CLK_I2C4 86
448/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AHUB */
449#define TEGRA186_CLK_AHUB 87
450/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA2CODEC_2X */
451#define TEGRA186_CLK_HDA2CODEC_2X 88
452/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH1 */
453#define TEGRA186_CLK_EXTPERIPH1 89
454/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH2 */
455#define TEGRA186_CLK_EXTPERIPH2 90
456/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_EXTPERIPH3 */
457#define TEGRA186_CLK_EXTPERIPH3 91
458/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C_SLOW */
459#define TEGRA186_CLK_I2C_SLOW 92
460/** @brief output of the SOR1_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
461#define TEGRA186_CLK_SOR1 93
462/** @brief output of gate CLK_ENB_CEC */
463#define TEGRA186_CLK_CEC 94
464/** @brief output of gate CLK_ENB_DPAUX1 */
465#define TEGRA186_CLK_DPAUX1 95
466/** @brief output of gate CLK_ENB_DPAUX */
467#define TEGRA186_CLK_DPAUX 96
468/** @brief output of the SOR0_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
469#define TEGRA186_CLK_SOR0 97
470/** @brief output of gate CLK_ENB_HDA2HDMICODEC */
471#define TEGRA186_CLK_HDA2HDMICODEC 98
472/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SATA */
473#define TEGRA186_CLK_SATA 99
474/** @brief output of gate CLK_ENB_SATA_OOB */
475#define TEGRA186_CLK_SATA_OOB 100
476/** @brief output of gate CLK_ENB_SATA_IOBIST */
477#define TEGRA186_CLK_SATA_IOBIST 101
478/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_HDA */
479#define TEGRA186_CLK_HDA 102
480/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SE */
481#define TEGRA186_CLK_SE 103
482/** @brief output of gate CLK_ENB_APB2APE */
483#define TEGRA186_CLK_APB2APE 104
484/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_APE */
485#define TEGRA186_CLK_APE 105
486/** @brief output of gate CLK_ENB_IQC1 */
487#define TEGRA186_CLK_IQC1 106
488/** @brief output of gate CLK_ENB_IQC2 */
489#define TEGRA186_CLK_IQC2 107
490/** divide by 2 version of TEGRA186_CLK_PLLREFE_VCO */
491#define TEGRA186_CLK_PLLREFE_OUT 108
492/** @brief output of gate CLK_ENB_PLLREFE_PLL_REF */
493#define TEGRA186_CLK_PLLREFE_PLL_REF 109
494/** @brief output of gate CLK_ENB_PLLC4_OUT */
495#define TEGRA186_CLK_PLLC4_OUT 110
496/** @brief output of mux xusb_core_clk_switch on page 67 of T186_Clocks_IAS.doc */
497#define TEGRA186_CLK_XUSB 111
498/** controls xusb_dev_ce signal on page 66 and 67 of T186_Clocks_IAS.doc */
499#define TEGRA186_CLK_XUSB_DEV 112
500/** controls xusb_host_ce signal on page 67 of T186_Clocks_IAS.doc */
501#define TEGRA186_CLK_XUSB_HOST 113
502/** controls xusb_ss_ce signal on page 67 of T186_Clocks_IAS.doc */
503#define TEGRA186_CLK_XUSB_SS 114
504/** @brief output of gate CLK_ENB_DSI */
505#define TEGRA186_CLK_DSI 115
506/** @brief output of gate CLK_ENB_MIPI_CAL */
507#define TEGRA186_CLK_MIPI_CAL 116
508/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIA_LP */
509#define TEGRA186_CLK_DSIA_LP 117
510/** @brief output of gate CLK_ENB_DSIB */
511#define TEGRA186_CLK_DSIB 118
512/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIB_LP */
513#define TEGRA186_CLK_DSIB_LP 119
514/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC1 */
515#define TEGRA186_CLK_DMIC1 122
516/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC2 */
517#define TEGRA186_CLK_DMIC2 123
518/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AUD_MCLK */
519#define TEGRA186_CLK_AUD_MCLK 124
520/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
521#define TEGRA186_CLK_I2C6 125
522/**output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UART_FST_MIPI_CAL */
523#define TEGRA186_CLK_UART_FST_MIPI_CAL 126
524/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VIC */
525#define TEGRA186_CLK_VIC 127
526/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SDMMC_LEGACY_TM */
527#define TEGRA186_CLK_SDMMC_LEGACY_TM 128
528/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDEC */
529#define TEGRA186_CLK_NVDEC 129
530/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVJPG */
531#define TEGRA186_CLK_NVJPG 130
532/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVENC */
533#define TEGRA186_CLK_NVENC 131
534/** @brief output of the QSPI_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
535#define TEGRA186_CLK_QSPI 132
536/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_VI_I2C */
537#define TEGRA186_CLK_VI_I2C 133
538/** @brief output of gate CLK_ENB_HSIC_TRK */
539#define TEGRA186_CLK_HSIC_TRK 134
540/** @brief output of gate CLK_ENB_USB2_TRK */
541#define TEGRA186_CLK_USB2_TRK 135
542/** output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MAUD */
543#define TEGRA186_CLK_MAUD 136
544/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSECB */
545#define TEGRA186_CLK_TSECB 137
546/** @brief output of gate CLK_ENB_ADSP */
547#define TEGRA186_CLK_ADSP 138
548/** @brief output of gate CLK_ENB_ADSPNEON */
549#define TEGRA186_CLK_ADSPNEON 139
550/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_RX_LS_SYMB */
551#define TEGRA186_CLK_MPHY_L0_RX_SYMB 140
552/** @brief output of gate CLK_ENB_MPHY_L0_RX_LS_BIT */
553#define TEGRA186_CLK_MPHY_L0_RX_LS_BIT 141
554/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_L0_TX_LS_SYMB */
555#define TEGRA186_CLK_MPHY_L0_TX_SYMB 142
556/** @brief output of gate CLK_ENB_MPHY_L0_TX_LS_3XBIT */
557#define TEGRA186_CLK_MPHY_L0_TX_LS_3XBIT 143
558/** @brief output of gate CLK_ENB_MPHY_L0_RX_ANA */
559#define TEGRA186_CLK_MPHY_L0_RX_ANA 144
560/** @brief output of gate CLK_ENB_MPHY_L1_RX_ANA */
561#define TEGRA186_CLK_MPHY_L1_RX_ANA 145
562/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_IOBIST */
563#define TEGRA186_CLK_MPHY_IOBIST 146
564/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_TX_1MHZ_REF */
565#define TEGRA186_CLK_MPHY_TX_1MHZ_REF 147
566/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_MPHY_CORE_PLL_FIXED */
567#define TEGRA186_CLK_MPHY_CORE_PLL_FIXED 148
568/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AXI_CBB */
569#define TEGRA186_CLK_AXI_CBB 149
570/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC3 */
571#define TEGRA186_CLK_DMIC3 150
572/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC4 */
573#define TEGRA186_CLK_DMIC4 151
574/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK1 */
575#define TEGRA186_CLK_DSPK1 152
576/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSPK2 */
577#define TEGRA186_CLK_DSPK2 153
578/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C6 */
579#define TEGRA186_CLK_I2S6 154
580/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P0 */
581#define TEGRA186_CLK_NVDISPLAY_P0 155
582/** @brief output of the NVDISPLAY_DISP_CLK_SRC mux in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP */
583#define TEGRA186_CLK_NVDISPLAY_DISP 156
584/** @brief output of gate CLK_ENB_NVDISPLAY_DSC */
585#define TEGRA186_CLK_NVDISPLAY_DSC 157
586/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAYHUB */
587#define TEGRA186_CLK_NVDISPLAYHUB 158
588/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P1 */
589#define TEGRA186_CLK_NVDISPLAY_P1 159
590/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_P2 */
591#define TEGRA186_CLK_NVDISPLAY_P2 160
592/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TACH */
593#define TEGRA186_CLK_TACH 166
594/** @brief output of gate CLK_ENB_EQOS */
595#define TEGRA186_CLK_EQOS_AXI 167
596/** @brief output of gate CLK_ENB_EQOS_RX */
597#define TEGRA186_CLK_EQOS_RX 168
598/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSHC_CG_SYS */
599#define TEGRA186_CLK_UFSHC 178
600/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UFSDEV_REF */
601#define TEGRA186_CLK_UFSDEV_REF 179
602/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSI */
603#define TEGRA186_CLK_NVCSI 180
604/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_NVCSILP */
605#define TEGRA186_CLK_NVCSILP 181
606/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C7 */
607#define TEGRA186_CLK_I2C7 182
608/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C9 */
609#define TEGRA186_CLK_I2C9 183
610/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C12 */
611#define TEGRA186_CLK_I2C12 184
612/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C13 */
613#define TEGRA186_CLK_I2C13 185
614/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C14 */
615#define TEGRA186_CLK_I2C14 186
616/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM1 */
617#define TEGRA186_CLK_PWM1 187
618/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM2 */
619#define TEGRA186_CLK_PWM2 188
620/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM3 */
621#define TEGRA186_CLK_PWM3 189
622/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM5 */
623#define TEGRA186_CLK_PWM5 190
624/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM6 */
625#define TEGRA186_CLK_PWM6 191
626/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM7 */
627#define TEGRA186_CLK_PWM7 192
628/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM8 */
629#define TEGRA186_CLK_PWM8 193
630/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTE */
631#define TEGRA186_CLK_UARTE 194
632/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTF */
633#define TEGRA186_CLK_UARTF 195
634/** @deprecated */
635#define TEGRA186_CLK_DBGAPB 196
636/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_CPU_NIC */
637#define TEGRA186_CLK_BPMP_CPU_NIC 197
638/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_BPMP_APB */
639#define TEGRA186_CLK_BPMP_APB 199
640/** @brief output of mux controlled by TEGRA186_CLK_SOC_ACTMON */
641#define TEGRA186_CLK_ACTMON 201
642/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_CPU_NIC */
643#define TEGRA186_CLK_AON_CPU_NIC 208
644/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN1 */
645#define TEGRA186_CLK_CAN1 210
646/** @brief output of gate CLK_ENB_CAN1_HOST */
647#define TEGRA186_CLK_CAN1_HOST 211
648/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_CAN2 */
649#define TEGRA186_CLK_CAN2 212
650/** @brief output of gate CLK_ENB_CAN2_HOST */
651#define TEGRA186_CLK_CAN2_HOST 213
652/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_APB */
653#define TEGRA186_CLK_AON_APB 214
654/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTC */
655#define TEGRA186_CLK_UARTC 215
656/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_UARTG */
657#define TEGRA186_CLK_UARTG 216
658/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_UART_FST_MIPI_CAL */
659#define TEGRA186_CLK_AON_UART_FST_MIPI_CAL 217
660/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C2 */
661#define TEGRA186_CLK_I2C2 218
662/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C8 */
663#define TEGRA186_CLK_I2C8 219
664/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_I2C10 */
665#define TEGRA186_CLK_I2C10 220
666/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_I2C_SLOW */
667#define TEGRA186_CLK_AON_I2C_SLOW 221
668/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPI2 */
669#define TEGRA186_CLK_SPI2 222
670/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DMIC5 */
671#define TEGRA186_CLK_DMIC5 223
672/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_AON_TOUCH */
673#define TEGRA186_CLK_AON_TOUCH 224
674/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_PWM4 */
675#define TEGRA186_CLK_PWM4 225
676/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_TSC. This clock object is read only and is used for all timers in the system. */
677#define TEGRA186_CLK_TSC 226
678/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_MSS_ENCRYPT */
679#define TEGRA186_CLK_MSS_ENCRYPT 227
680/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_CPU_NIC */
681#define TEGRA186_CLK_SCE_CPU_NIC 228
682/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SCE_APB */
683#define TEGRA186_CLK_SCE_APB 230
684/** @brief output of gate CLK_ENB_DSIC */
685#define TEGRA186_CLK_DSIC 231
686/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSIC_LP */
687#define TEGRA186_CLK_DSIC_LP 232
688/** @brief output of gate CLK_ENB_DSID */
689#define TEGRA186_CLK_DSID 233
690/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_DSID_LP */
691#define TEGRA186_CLK_DSID_LP 234
692/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_SATA_USB_RX_BYP */
693#define TEGRA186_CLK_PEX_SATA_USB_RX_BYP 236
694/** @brief output of mux controlled by CLK_RST_CONTROLLER_CLK_SOURCE_SPDIF_OUT */
695#define TEGRA186_CLK_SPDIF_OUT 238
696/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_PTP_REF_CLK_0 */
697#define TEGRA186_CLK_EQOS_PTP_REF 239
698/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_EQOS_TX_CLK */
699#define TEGRA186_CLK_EQOS_TX 240
700/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_USB2_HSIC_TRK */
701#define TEGRA186_CLK_USB2_HSIC_TRK 241
702/** @brief output of mux xusb_ss_clk_switch on page 66 of T186_Clocks_IAS.doc */
703#define TEGRA186_CLK_XUSB_CORE_SS 242
704/** @brief output of mux xusb_core_dev_clk_switch on page 67 of T186_Clocks_IAS.doc */
705#define TEGRA186_CLK_XUSB_CORE_DEV 243
706/** @brief output of mux xusb_core_falcon_clk_switch on page 67 of T186_Clocks_IAS.doc */
707#define TEGRA186_CLK_XUSB_FALCON 244
708/** @brief output of mux xusb_fs_clk_switch on page 66 of T186_Clocks_IAS.doc */
709#define TEGRA186_CLK_XUSB_FS 245
710/** @brief output of the divider CLK_RST_CONTROLLER_PLLA_OUT */
711#define TEGRA186_CLK_PLL_A_OUT0 246
712/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S1 */
713#define TEGRA186_CLK_SYNC_I2S1 247
714/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S2 */
715#define TEGRA186_CLK_SYNC_I2S2 248
716/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S3 */
717#define TEGRA186_CLK_SYNC_I2S3 249
718/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S4 */
719#define TEGRA186_CLK_SYNC_I2S4 250
720/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S5 */
721#define TEGRA186_CLK_SYNC_I2S5 251
722/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_I2S6 */
723#define TEGRA186_CLK_SYNC_I2S6 252
724/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK1 */
725#define TEGRA186_CLK_SYNC_DSPK1 253
726/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DSPK2 */
727#define TEGRA186_CLK_SYNC_DSPK2 254
728/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC1 */
729#define TEGRA186_CLK_SYNC_DMIC1 255
730/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC2 */
731#define TEGRA186_CLK_SYNC_DMIC2 256
732/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC3 */
733#define TEGRA186_CLK_SYNC_DMIC3 257
734/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_DMIC4 */
735#define TEGRA186_CLK_SYNC_DMIC4 259
736/** @brief output of mux controlled by CLK_RST_CONTROLLER_AUDIO_SYNC_CLK_SPDIF */
737#define TEGRA186_CLK_SYNC_SPDIF 260
738/** @brief output of gate CLK_ENB_PLLREFE_OUT */
739#define TEGRA186_CLK_PLLREFE_OUT_GATED 261
740/** @brief output of the divider PLLREFE_DIVP in CLK_RST_CONTROLLER_PLLREFE_BASE. PLLREFE has 2 outputs:
741 * * VCO/pdiv defined by this clock object
742 * * VCO/2 defined by TEGRA186_CLK_PLLREFE_OUT
743 */
744#define TEGRA186_CLK_PLLREFE_OUT1 262
745#define TEGRA186_CLK_PLLD_OUT1 267
746/** @brief output of the divider PLLP_DIVP in CLK_RST_CONTROLLER_PLLP_BASE */
747#define TEGRA186_CLK_PLLP_OUT0 269
748/** @brief output of the divider CLK_RST_CONTROLLER_PLLP_OUTC */
749#define TEGRA186_CLK_PLLP_OUT5 270
750/** PLL controlled by CLK_RST_CONTROLLER_PLLA_BASE for use by audio clocks */
751#define TEGRA186_CLK_PLLA 271
752/** @brief output of mux controlled by CLK_RST_CONTROLLER_ACLK_BURST_POLICY divided by the divider controlled by ACLK_CLK_DIVISOR in CLK_RST_CONTROLLER_SUPER_ACLK_DIVIDER */
753#define TEGRA186_CLK_ACLK 273
754/** fixed 48MHz clock divided down from TEGRA186_CLK_PLL_U */
755#define TEGRA186_CLK_PLL_U_48M 274
756/** fixed 480MHz clock divided down from TEGRA186_CLK_PLL_U */
757#define TEGRA186_CLK_PLL_U_480M 275
758/** @brief output of the divider PLLC4_DIVP in CLK_RST_CONTROLLER_PLLC4_BASE. Output frequency is TEGRA186_CLK_PLLC4_VCO/PLLC4_DIVP */
759#define TEGRA186_CLK_PLLC4_OUT0 276
760/** fixed /3 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/3 */
761#define TEGRA186_CLK_PLLC4_OUT1 277
762/** fixed /5 divider. Output frequency of this clock is TEGRA186_CLK_PLLC4_VCO/5 */
763#define TEGRA186_CLK_PLLC4_OUT2 278
764/** @brief output of mux controlled by PLLC4_CLK_SEL in CLK_RST_CONTROLLER_PLLC4_MISC1 */
765#define TEGRA186_CLK_PLLC4_OUT_MUX 279
766/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when DFLLDISP_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
767#define TEGRA186_CLK_DFLLDISP_DIV 284
768/** @brief output of divider NVDISPLAY_DISP_CLK_DIVISOR in CLK_RST_CONTROLLER_CLK_SOURCE_NVDISPLAY_DISP when PLLDISPHUB_DIV is selected in NVDISPLAY_DISP_CLK_SRC */
769#define TEGRA186_CLK_PLLDISPHUB_DIV 285
770/** fixed /8 divider which is used as the input for TEGRA186_CLK_SOR_SAFE */
771#define TEGRA186_CLK_PLLP_DIV8 286
772/** @brief output of divider CLK_RST_CONTROLLER_BPMP_NIC_RATE */
773#define TEGRA186_CLK_BPMP_NIC 287
774/** @brief output of the divider CLK_RST_CONTROLLER_PLLA1_OUT1 */
775#define TEGRA186_CLK_PLL_A_OUT1 288
776/** @deprecated */
777#define TEGRA186_CLK_GPC2CLK 289
778/** A fake clock which must be enabled during KFUSE read operations to ensure adequate VDD_CORE voltage. */
779#define TEGRA186_CLK_KFUSE 293
780/**
781 * @brief controls the PLLE hardware sequencer.
782 * @details This clock only has enable and disable methods. When the
783 * PLLE hw sequencer is enabled, PLLE, will be enabled or disabled by
784 * hw based on the control signals from the PCIe, SATA and XUSB
785 * clocks. When the PLLE hw sequencer is disabled, the state of PLLE
786 * is controlled by sw using clk_enable/clk_disable on
787 * TEGRA186_CLK_PLLE.
788 */
789#define TEGRA186_CLK_PLLE_PWRSEQ 294
790/** fixed 60MHz clock divided down from, TEGRA186_CLK_PLL_U */
791#define TEGRA186_CLK_PLLREFE_REF 295
792/** @brief output of mux controlled by SOR0_CLK_SEL0 and SOR0_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0 */
793#define TEGRA186_CLK_SOR0_OUT 296
794/** @brief output of mux controlled by SOR1_CLK_SEL0 and SOR1_CLK_SEL1 in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1 */
795#define TEGRA186_CLK_SOR1_OUT 297
796/** @brief fixed /5 divider. Output frequency of this clock is TEGRA186_CLK_PLLREFE_OUT1/5. Used as input for TEGRA186_CLK_EQOS_AXI */
797#define TEGRA186_CLK_PLLREFE_OUT1_DIV5 298
798/** @brief controls the UTMIP_PLL (aka PLLU) hardware sqeuencer */
799#define TEGRA186_CLK_UTMIP_PLL_PWRSEQ 301
800/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL0_MGMT */
801#define TEGRA186_CLK_PEX_USB_PAD0_MGMT 302
802/** @brief output of the divider CLK_RST_CONTROLLER_CLK_SOURCE_PEX_USB_PAD_PLL1_MGMT */
803#define TEGRA186_CLK_PEX_USB_PAD1_MGMT 303
804/** @brief controls the UPHY_PLL0 hardware sqeuencer */
805#define TEGRA186_CLK_UPHY_PLL0_PWRSEQ 304
806/** @brief controls the UPHY_PLL1 hardware sqeuencer */
807#define TEGRA186_CLK_UPHY_PLL1_PWRSEQ 305
808/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC so the bypass output even be used when the PLL is disabled */
809#define TEGRA186_CLK_PLLREFE_PLLE_PASSTHROUGH 306
810/** @brief output of the mux controlled by PLLREFE_SEL_CLKIN_PEX in CLK_RST_CONTROLLER_PLLREFE_MISC */
811#define TEGRA186_CLK_PLLREFE_PEX 307
812/** @brief control for PLLREFE_IDDQ in CLK_RST_CONTROLLER_PLLREFE_MISC to turn on the PLL when enabled */
813#define TEGRA186_CLK_PLLREFE_IDDQ 308
814/** @brief output of the divider QSPI_CLK_DIV2_SEL in CLK_RST_CONTROLLER_CLK_SOURCE_QSPI */
815#define TEGRA186_CLK_QSPI_OUT 309
816/**
817 * @brief GPC2CLK-div-2
818 * @details fixed /2 divider. Output frequency is
819 * TEGRA186_CLK_GPC2CLK/2. The frequency of this clock is the
820 * frequency at which the GPU graphics engine runs. */
821#define TEGRA186_CLK_GPCCLK 310
822/** @brief output of divider CLK_RST_CONTROLLER_AON_NIC_RATE */
823#define TEGRA186_CLK_AON_NIC 450
824/** @brief output of divider CLK_RST_CONTROLLER_SCE_NIC_RATE */
825#define TEGRA186_CLK_SCE_NIC 451
826/** Fixed 100MHz PLL for PCIe, SATA and superspeed USB */
827#define TEGRA186_CLK_PLLE 512
828/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC_BASE */
829#define TEGRA186_CLK_PLLC 513
830/** Fixed 408MHz PLL for use by peripheral clocks */
831#define TEGRA186_CLK_PLLP 516
832/** @deprecated */
833#define TEGRA186_CLK_PLL_P TEGRA186_CLK_PLLP
834/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD_BASE for use by DSI */
835#define TEGRA186_CLK_PLLD 518
836/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD2_BASE for use by HDMI or DP */
837#define TEGRA186_CLK_PLLD2 519
838/**
839 * @brief PLL controlled by CLK_RST_CONTROLLER_PLLREFE_BASE.
840 * @details Note that this clock only controls the VCO output, before
841 * the post-divider. See TEGRA186_CLK_PLLREFE_OUT1 for more
842 * information.
843 */
844#define TEGRA186_CLK_PLLREFE_VCO 520
845/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC2_BASE */
846#define TEGRA186_CLK_PLLC2 521
847/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC3_BASE */
848#define TEGRA186_CLK_PLLC3 522
849/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDP_BASE for use as the DP link clock */
850#define TEGRA186_CLK_PLLDP 523
851/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLC4_BASE */
852#define TEGRA186_CLK_PLLC4_VCO 524
853/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLA1_BASE for use by audio clocks */
854#define TEGRA186_CLK_PLLA1 525
855/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLNVCSI_BASE */
856#define TEGRA186_CLK_PLLNVCSI 526
857/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLDISPHUB_BASE */
858#define TEGRA186_CLK_PLLDISPHUB 527
859/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLD3_BASE for use by HDMI or DP */
860#define TEGRA186_CLK_PLLD3 528
861/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLBPMPCAM_BASE */
862#define TEGRA186_CLK_PLLBPMPCAM 531
863/** @brief PLL controlled by CLK_RST_CONTROLLER_PLLAON_BASE for use by IP blocks in the AON domain */
864#define TEGRA186_CLK_PLLAON 532
865/** Fixed frequency 960MHz PLL for USB and EAVB */
866#define TEGRA186_CLK_PLLU 533
867/** fixed /2 divider. Output frequency is TEGRA186_CLK_PLLC4_VCO/2 */
868#define TEGRA186_CLK_PLLC4_VCO_DIV2 535
869/** @brief NAFLL clock source for AXI_CBB */
870#define TEGRA186_CLK_NAFLL_AXI_CBB 564
871/** @brief NAFLL clock source for BPMP */
872#define TEGRA186_CLK_NAFLL_BPMP 565
873/** @brief NAFLL clock source for ISP */
874#define TEGRA186_CLK_NAFLL_ISP 566
875/** @brief NAFLL clock source for NVDEC */
876#define TEGRA186_CLK_NAFLL_NVDEC 567
877/** @brief NAFLL clock source for NVENC */
878#define TEGRA186_CLK_NAFLL_NVENC 568
879/** @brief NAFLL clock source for NVJPG */
880#define TEGRA186_CLK_NAFLL_NVJPG 569
881/** @brief NAFLL clock source for SCE */
882#define TEGRA186_CLK_NAFLL_SCE 570
883/** @brief NAFLL clock source for SE */
884#define TEGRA186_CLK_NAFLL_SE 571
885/** @brief NAFLL clock source for TSEC */
886#define TEGRA186_CLK_NAFLL_TSEC 572
887/** @brief NAFLL clock source for TSECB */
888#define TEGRA186_CLK_NAFLL_TSECB 573
889/** @brief NAFLL clock source for VI */
890#define TEGRA186_CLK_NAFLL_VI 574
891/** @brief NAFLL clock source for VIC */
892#define TEGRA186_CLK_NAFLL_VIC 575
893/** @brief NAFLL clock source for DISP */
894#define TEGRA186_CLK_NAFLL_DISP 576
895/** @brief NAFLL clock source for GPU */
896#define TEGRA186_CLK_NAFLL_GPU 577
897/** @brief NAFLL clock source for M-CPU cluster */
898#define TEGRA186_CLK_NAFLL_MCPU 578
899/** @brief NAFLL clock source for B-CPU cluster */
900#define TEGRA186_CLK_NAFLL_BCPU 579
901/** @brief input from Tegra's CLK_32K_IN pad */
902#define TEGRA186_CLK_CLK_32K 608
903/** @brief output of divider CLK_RST_CONTROLLER_CLK_M_DIVIDE */
904#define TEGRA186_CLK_CLK_M 609
905/** @brief output of divider PLL_REF_DIV in CLK_RST_CONTROLLER_OSC_CTRL */
906#define TEGRA186_CLK_PLL_REF 610
907/** @brief input from Tegra's XTAL_IN */
908#define TEGRA186_CLK_OSC 612
909/** @brief clock recovered from EAVB input */
910#define TEGRA186_CLK_EQOS_RX_INPUT 613
911/** @brief clock recovered from DTV input */
912#define TEGRA186_CLK_DTV_INPUT 614
913/** @brief SOR0 brick output which feeds into SOR0_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR0*/
914#define TEGRA186_CLK_SOR0_PAD_CLKOUT 615
915/** @brief SOR1 brick output which feeds into SOR1_CLK_SEL mux in CLK_RST_CONTROLLER_CLK_SOURCE_SOR1*/
916#define TEGRA186_CLK_SOR1_PAD_CLKOUT 616
917/** @brief clock recovered from I2S1 input */
918#define TEGRA186_CLK_I2S1_SYNC_INPUT 617
919/** @brief clock recovered from I2S2 input */
920#define TEGRA186_CLK_I2S2_SYNC_INPUT 618
921/** @brief clock recovered from I2S3 input */
922#define TEGRA186_CLK_I2S3_SYNC_INPUT 619
923/** @brief clock recovered from I2S4 input */
924#define TEGRA186_CLK_I2S4_SYNC_INPUT 620
925/** @brief clock recovered from I2S5 input */
926#define TEGRA186_CLK_I2S5_SYNC_INPUT 621
927/** @brief clock recovered from I2S6 input */
928#define TEGRA186_CLK_I2S6_SYNC_INPUT 622
929/** @brief clock recovered from SPDIFIN input */
930#define TEGRA186_CLK_SPDIFIN_SYNC_INPUT 623
931
932/**
933 * @brief subject to change
934 * @details maximum clock identifier value plus one.
935 */
936#define TEGRA186_CLK_CLK_MAX 624
937
938/** @} */
939
940#endif
diff --git a/include/dt-bindings/mailbox/tegra186-hsp.h b/include/dt-bindings/mailbox/tegra186-hsp.h
new file mode 100644
index 000000000000..f5d66e5f5f10
--- /dev/null
+++ b/include/dt-bindings/mailbox/tegra186-hsp.h
@@ -0,0 +1,24 @@
1/*
2 * This header provides constants for binding nvidia,tegra186-hsp.
3 */
4
5#ifndef _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
6#define _DT_BINDINGS_MAILBOX_TEGRA186_HSP_H
7
8/*
9 * These define the type of mailbox that is to be used (doorbell, shared
10 * mailbox, shared semaphore or arbitrated semaphore).
11 */
12#define TEGRA_HSP_MBOX_TYPE_DB 0x0
13#define TEGRA_HSP_MBOX_TYPE_SM 0x1
14#define TEGRA_HSP_MBOX_TYPE_SS 0x2
15#define TEGRA_HSP_MBOX_TYPE_AS 0x3
16
17/*
18 * These defines represent the bit associated with the given master ID in the
19 * doorbell registers.
20 */
21#define TEGRA_HSP_DB_MASTER_CCPLEX 17
22#define TEGRA_HSP_DB_MASTER_BPMP 19
23
24#endif
diff --git a/include/dt-bindings/power/tegra186-powergate.h b/include/dt-bindings/power/tegra186-powergate.h
new file mode 100644
index 000000000000..388d6e228dc8
--- /dev/null
+++ b/include/dt-bindings/power/tegra186-powergate.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright (c) 2015-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 _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
18#define _DT_BINDINGS_POWER_TEGRA186_POWERGATE_H
19
20#define TEGRA186_POWER_DOMAIN_AUD 0
21#define TEGRA186_POWER_DOMAIN_DFD 1
22#define TEGRA186_POWER_DOMAIN_DISP 2
23#define TEGRA186_POWER_DOMAIN_DISPB 3
24#define TEGRA186_POWER_DOMAIN_DISPC 4
25#define TEGRA186_POWER_DOMAIN_ISPA 5
26#define TEGRA186_POWER_DOMAIN_NVDEC 6
27#define TEGRA186_POWER_DOMAIN_NVJPG 7
28#define TEGRA186_POWER_DOMAIN_MPE 8
29#define TEGRA186_POWER_DOMAIN_PCX 9
30#define TEGRA186_POWER_DOMAIN_SAX 10
31#define TEGRA186_POWER_DOMAIN_VE 11
32#define TEGRA186_POWER_DOMAIN_VIC 12
33#define TEGRA186_POWER_DOMAIN_XUSBA 13
34#define TEGRA186_POWER_DOMAIN_XUSBB 14
35#define TEGRA186_POWER_DOMAIN_XUSBC 15
36#define TEGRA186_POWER_DOMAIN_GPU 43
37#define TEGRA186_POWER_DOMAIN_MAX 44
38
39#endif
diff --git a/include/dt-bindings/reset/tegra186-reset.h b/include/dt-bindings/reset/tegra186-reset.h
new file mode 100644
index 000000000000..8a184e357955
--- /dev/null
+++ b/include/dt-bindings/reset/tegra186-reset.h
@@ -0,0 +1,217 @@
1/*
2 * Copyright (c) 2015, 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_MACH_T186_RESET_T186_H_
18#define _ABI_MACH_T186_RESET_T186_H_
19
20
21#define TEGRA186_RESET_ACTMON 0
22#define TEGRA186_RESET_AFI 1
23#define TEGRA186_RESET_CEC 2
24#define TEGRA186_RESET_CSITE 3
25#define TEGRA186_RESET_DP2 4
26#define TEGRA186_RESET_DPAUX 5
27#define TEGRA186_RESET_DSI 6
28#define TEGRA186_RESET_DSIB 7
29#define TEGRA186_RESET_DTV 8
30#define TEGRA186_RESET_DVFS 9
31#define TEGRA186_RESET_ENTROPY 10
32#define TEGRA186_RESET_EXTPERIPH1 11
33#define TEGRA186_RESET_EXTPERIPH2 12
34#define TEGRA186_RESET_EXTPERIPH3 13
35#define TEGRA186_RESET_GPU 14
36#define TEGRA186_RESET_HDA 15
37#define TEGRA186_RESET_HDA2CODEC_2X 16
38#define TEGRA186_RESET_HDA2HDMICODEC 17
39#define TEGRA186_RESET_HOST1X 18
40#define TEGRA186_RESET_I2C1 19
41#define TEGRA186_RESET_I2C2 20
42#define TEGRA186_RESET_I2C3 21
43#define TEGRA186_RESET_I2C4 22
44#define TEGRA186_RESET_I2C5 23
45#define TEGRA186_RESET_I2C6 24
46#define TEGRA186_RESET_ISP 25
47#define TEGRA186_RESET_KFUSE 26
48#define TEGRA186_RESET_LA 27
49#define TEGRA186_RESET_MIPI_CAL 28
50#define TEGRA186_RESET_PCIE 29
51#define TEGRA186_RESET_PCIEXCLK 30
52#define TEGRA186_RESET_SATA 31
53#define TEGRA186_RESET_SATACOLD 32
54#define TEGRA186_RESET_SDMMC1 33
55#define TEGRA186_RESET_SDMMC2 34
56#define TEGRA186_RESET_SDMMC3 35
57#define TEGRA186_RESET_SDMMC4 36
58#define TEGRA186_RESET_SE 37
59#define TEGRA186_RESET_SOC_THERM 38
60#define TEGRA186_RESET_SOR0 39
61#define TEGRA186_RESET_SPI1 40
62#define TEGRA186_RESET_SPI2 41
63#define TEGRA186_RESET_SPI3 42
64#define TEGRA186_RESET_SPI4 43
65#define TEGRA186_RESET_TMR 44
66#define TEGRA186_RESET_TRIG_SYS 45
67#define TEGRA186_RESET_TSEC 46
68#define TEGRA186_RESET_UARTA 47
69#define TEGRA186_RESET_UARTB 48
70#define TEGRA186_RESET_UARTC 49
71#define TEGRA186_RESET_UARTD 50
72#define TEGRA186_RESET_VI 51
73#define TEGRA186_RESET_VIC 52
74#define TEGRA186_RESET_XUSB_DEV 53
75#define TEGRA186_RESET_XUSB_HOST 54
76#define TEGRA186_RESET_XUSB_PADCTL 55
77#define TEGRA186_RESET_XUSB_SS 56
78#define TEGRA186_RESET_AON_APB 57
79#define TEGRA186_RESET_AXI_CBB 58
80#define TEGRA186_RESET_BPMP_APB 59
81#define TEGRA186_RESET_CAN1 60
82#define TEGRA186_RESET_CAN2 61
83#define TEGRA186_RESET_DMIC5 62
84#define TEGRA186_RESET_DSIC 63
85#define TEGRA186_RESET_DSID 64
86#define TEGRA186_RESET_EMC_EMC 65
87#define TEGRA186_RESET_EMC_MEM 66
88#define TEGRA186_RESET_EMCSB_EMC 67
89#define TEGRA186_RESET_EMCSB_MEM 68
90#define TEGRA186_RESET_EQOS 69
91#define TEGRA186_RESET_GPCDMA 70
92#define TEGRA186_RESET_GPIO_CTL0 71
93#define TEGRA186_RESET_GPIO_CTL1 72
94#define TEGRA186_RESET_GPIO_CTL2 73
95#define TEGRA186_RESET_GPIO_CTL3 74
96#define TEGRA186_RESET_GPIO_CTL4 75
97#define TEGRA186_RESET_GPIO_CTL5 76
98#define TEGRA186_RESET_I2C10 77
99#define TEGRA186_RESET_I2C12 78
100#define TEGRA186_RESET_I2C13 79
101#define TEGRA186_RESET_I2C14 80
102#define TEGRA186_RESET_I2C7 81
103#define TEGRA186_RESET_I2C8 82
104#define TEGRA186_RESET_I2C9 83
105#define TEGRA186_RESET_JTAG2AXI 84
106#define TEGRA186_RESET_MPHY_IOBIST 85
107#define TEGRA186_RESET_MPHY_L0_RX 86
108#define TEGRA186_RESET_MPHY_L0_TX 87
109#define TEGRA186_RESET_NVCSI 88
110#define TEGRA186_RESET_NVDISPLAY0_HEAD0 89
111#define TEGRA186_RESET_NVDISPLAY0_HEAD1 90
112#define TEGRA186_RESET_NVDISPLAY0_HEAD2 91
113#define TEGRA186_RESET_NVDISPLAY0_MISC 92
114#define TEGRA186_RESET_NVDISPLAY0_WGRP0 93
115#define TEGRA186_RESET_NVDISPLAY0_WGRP1 94
116#define TEGRA186_RESET_NVDISPLAY0_WGRP2 95
117#define TEGRA186_RESET_NVDISPLAY0_WGRP3 96
118#define TEGRA186_RESET_NVDISPLAY0_WGRP4 97
119#define TEGRA186_RESET_NVDISPLAY0_WGRP5 98
120#define TEGRA186_RESET_PWM1 99
121#define TEGRA186_RESET_PWM2 100
122#define TEGRA186_RESET_PWM3 101
123#define TEGRA186_RESET_PWM4 102
124#define TEGRA186_RESET_PWM5 103
125#define TEGRA186_RESET_PWM6 104
126#define TEGRA186_RESET_PWM7 105
127#define TEGRA186_RESET_PWM8 106
128#define TEGRA186_RESET_SCE_APB 107
129#define TEGRA186_RESET_SOR1 108
130#define TEGRA186_RESET_TACH 109
131#define TEGRA186_RESET_TSC 110
132#define TEGRA186_RESET_UARTF 111
133#define TEGRA186_RESET_UARTG 112
134#define TEGRA186_RESET_UFSHC 113
135#define TEGRA186_RESET_UFSHC_AXI_M 114
136#define TEGRA186_RESET_UPHY 115
137#define TEGRA186_RESET_ADSP 116
138#define TEGRA186_RESET_ADSPDBG 117
139#define TEGRA186_RESET_ADSPINTF 118
140#define TEGRA186_RESET_ADSPNEON 119
141#define TEGRA186_RESET_ADSPPERIPH 120
142#define TEGRA186_RESET_ADSPSCU 121
143#define TEGRA186_RESET_ADSPWDT 122
144#define TEGRA186_RESET_APE 123
145#define TEGRA186_RESET_DPAUX1 124
146#define TEGRA186_RESET_NVDEC 125
147#define TEGRA186_RESET_NVENC 126
148#define TEGRA186_RESET_NVJPG 127
149#define TEGRA186_RESET_PEX_USB_UPHY 128
150#define TEGRA186_RESET_QSPI 129
151#define TEGRA186_RESET_TSECB 130
152#define TEGRA186_RESET_VI_I2C 131
153#define TEGRA186_RESET_UARTE 132
154#define TEGRA186_RESET_TOP_GTE 133
155#define TEGRA186_RESET_SHSP 134
156#define TEGRA186_RESET_PEX_USB_UPHY_L5 135
157#define TEGRA186_RESET_PEX_USB_UPHY_L4 136
158#define TEGRA186_RESET_PEX_USB_UPHY_L3 137
159#define TEGRA186_RESET_PEX_USB_UPHY_L2 138
160#define TEGRA186_RESET_PEX_USB_UPHY_L1 139
161#define TEGRA186_RESET_PEX_USB_UPHY_L0 140
162#define TEGRA186_RESET_PEX_USB_UPHY_PLL1 141
163#define TEGRA186_RESET_PEX_USB_UPHY_PLL0 142
164#define TEGRA186_RESET_TSCTNVI 143
165#define TEGRA186_RESET_EXTPERIPH4 144
166#define TEGRA186_RESET_DSIPADCTL 145
167#define TEGRA186_RESET_AUD_MCLK 146
168#define TEGRA186_RESET_MPHY_CLK_CTL 147
169#define TEGRA186_RESET_MPHY_L1_RX 148
170#define TEGRA186_RESET_MPHY_L1_TX 149
171#define TEGRA186_RESET_UFSHC_LP 150
172#define TEGRA186_RESET_BPMP_NIC 151
173#define TEGRA186_RESET_BPMP_NSYSPORESET 152
174#define TEGRA186_RESET_BPMP_NRESET 153
175#define TEGRA186_RESET_BPMP_DBGRESETN 154
176#define TEGRA186_RESET_BPMP_PRESETDBGN 155
177#define TEGRA186_RESET_BPMP_PM 156
178#define TEGRA186_RESET_BPMP_CVC 157
179#define TEGRA186_RESET_BPMP_DMA 158
180#define TEGRA186_RESET_BPMP_HSP 159
181#define TEGRA186_RESET_TSCTNBPMP 160
182#define TEGRA186_RESET_BPMP_TKE 161
183#define TEGRA186_RESET_BPMP_GTE 162
184#define TEGRA186_RESET_BPMP_PM_ACTMON 163
185#define TEGRA186_RESET_AON_NIC 164
186#define TEGRA186_RESET_AON_NSYSPORESET 165
187#define TEGRA186_RESET_AON_NRESET 166
188#define TEGRA186_RESET_AON_DBGRESETN 167
189#define TEGRA186_RESET_AON_PRESETDBGN 168
190#define TEGRA186_RESET_AON_ACTMON 169
191#define TEGRA186_RESET_AOPM 170
192#define TEGRA186_RESET_AOVC 171
193#define TEGRA186_RESET_AON_DMA 172
194#define TEGRA186_RESET_AON_GPIO 173
195#define TEGRA186_RESET_AON_HSP 174
196#define TEGRA186_RESET_TSCTNAON 175
197#define TEGRA186_RESET_AON_TKE 176
198#define TEGRA186_RESET_AON_GTE 177
199#define TEGRA186_RESET_SCE_NIC 178
200#define TEGRA186_RESET_SCE_NSYSPORESET 179
201#define TEGRA186_RESET_SCE_NRESET 180
202#define TEGRA186_RESET_SCE_DBGRESETN 181
203#define TEGRA186_RESET_SCE_PRESETDBGN 182
204#define TEGRA186_RESET_SCE_ACTMON 183
205#define TEGRA186_RESET_SCE_PM 184
206#define TEGRA186_RESET_SCE_DMA 185
207#define TEGRA186_RESET_SCE_HSP 186
208#define TEGRA186_RESET_TSCTNSCE 187
209#define TEGRA186_RESET_SCE_TKE 188
210#define TEGRA186_RESET_SCE_GTE 189
211#define TEGRA186_RESET_SCE_CFG 190
212#define TEGRA186_RESET_ADSP_ALL 191
213/** @brief controls the power up/down sequence of UFSHC PSW partition. Controls LP_PWR_READY, LP_ISOL_EN, and LP_RESET_N signals */
214#define TEGRA186_RESET_UFSHC_LP_SEQ 192
215#define TEGRA186_RESET_SIZE 193
216
217#endif
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 */
diff --git a/include/soc/tegra/ivc.h b/include/soc/tegra/ivc.h
new file mode 100644
index 000000000000..b13cc43ad9d8
--- /dev/null
+++ b/include/soc/tegra/ivc.h
@@ -0,0 +1,109 @@
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 __TEGRA_IVC_H
15
16#include <linux/device.h>
17#include <linux/dma-mapping.h>
18#include <linux/types.h>
19
20struct tegra_ivc_header;
21
22struct tegra_ivc {
23 struct device *peer;
24
25 struct {
26 struct tegra_ivc_header *channel;
27 unsigned int position;
28 dma_addr_t phys;
29 } rx, tx;
30
31 void (*notify)(struct tegra_ivc *ivc, void *data);
32 void *notify_data;
33
34 unsigned int num_frames;
35 size_t frame_size;
36};
37
38/**
39 * tegra_ivc_read_get_next_frame - Peek at the next frame to receive
40 * @ivc pointer of the IVC channel
41 *
42 * Peek at the next frame to be received, without removing it from
43 * the queue.
44 *
45 * Returns a pointer to the frame, or an error encoded pointer.
46 */
47void *tegra_ivc_read_get_next_frame(struct tegra_ivc *ivc);
48
49/**
50 * tegra_ivc_read_advance - Advance the read queue
51 * @ivc pointer of the IVC channel
52 *
53 * Advance the read queue
54 *
55 * Returns 0, or a negative error value if failed.
56 */
57int tegra_ivc_read_advance(struct tegra_ivc *ivc);
58
59/**
60 * tegra_ivc_write_get_next_frame - Poke at the next frame to transmit
61 * @ivc pointer of the IVC channel
62 *
63 * Get access to the next frame.
64 *
65 * Returns a pointer to the frame, or an error encoded pointer.
66 */
67void *tegra_ivc_write_get_next_frame(struct tegra_ivc *ivc);
68
69/**
70 * tegra_ivc_write_advance - Advance the write queue
71 * @ivc pointer of the IVC channel
72 *
73 * Advance the write queue
74 *
75 * Returns 0, or a negative error value if failed.
76 */
77int tegra_ivc_write_advance(struct tegra_ivc *ivc);
78
79/**
80 * tegra_ivc_notified - handle internal messages
81 * @ivc pointer of the IVC channel
82 *
83 * This function must be called following every notification.
84 *
85 * Returns 0 if the channel is ready for communication, or -EAGAIN if a channel
86 * reset is in progress.
87 */
88int tegra_ivc_notified(struct tegra_ivc *ivc);
89
90/**
91 * tegra_ivc_reset - initiates a reset of the shared memory state
92 * @ivc pointer of the IVC channel
93 *
94 * This function must be called after a channel is reserved before it is used
95 * for communication. The channel will be ready for use when a subsequent call
96 * to notify the remote of the channel reset.
97 */
98void tegra_ivc_reset(struct tegra_ivc *ivc);
99
100size_t tegra_ivc_align(size_t size);
101unsigned tegra_ivc_total_queue_size(unsigned queue_size);
102int tegra_ivc_init(struct tegra_ivc *ivc, struct device *peer, void *rx,
103 dma_addr_t rx_phys, void *tx, dma_addr_t tx_phys,
104 unsigned int num_frames, size_t frame_size,
105 void (*notify)(struct tegra_ivc *ivc, void *data),
106 void *data);
107void tegra_ivc_cleanup(struct tegra_ivc *ivc);
108
109#endif /* __TEGRA_IVC_H */