1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2018, NVIDIA CORPORATION.
6 #include <linux/genalloc.h>
8 #include <linux/mailbox_client.h>
9 #include <linux/of_address.h>
10 #include <linux/platform_device.h>
12 #include <soc/tegra/bpmp.h>
13 #include <soc/tegra/bpmp-abi.h>
14 #include <soc/tegra/ivc.h>
16 #include "bpmp-private.h"
18 struct tegra186_bpmp
{
19 struct tegra_bpmp
*parent
;
22 struct gen_pool
*pool
;
31 struct mbox_client client
;
32 struct mbox_chan
*channel
;
36 static inline struct tegra_bpmp
*
37 mbox_client_to_bpmp(struct mbox_client
*client
)
39 struct tegra186_bpmp
*priv
;
41 priv
= container_of(client
, struct tegra186_bpmp
, mbox
.client
);
46 static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel
*channel
)
50 err
= tegra_ivc_read_get_next_frame(channel
->ivc
, &channel
->ib
);
52 iosys_map_clear(&channel
->ib
);
59 static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel
*channel
)
63 err
= tegra_ivc_write_get_next_frame(channel
->ivc
, &channel
->ob
);
65 iosys_map_clear(&channel
->ob
);
72 static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel
*channel
)
74 return tegra_ivc_read_advance(channel
->ivc
);
77 static int tegra186_bpmp_post_message(struct tegra_bpmp_channel
*channel
)
79 return tegra_ivc_write_advance(channel
->ivc
);
82 static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp
*bpmp
)
84 struct tegra186_bpmp
*priv
= bpmp
->priv
;
87 err
= mbox_send_message(priv
->mbox
.channel
, NULL
);
91 mbox_client_txdone(priv
->mbox
.channel
, 0);
96 static void tegra186_bpmp_ivc_notify(struct tegra_ivc
*ivc
, void *data
)
98 struct tegra_bpmp
*bpmp
= data
;
99 struct tegra186_bpmp
*priv
= bpmp
->priv
;
101 if (WARN_ON(priv
->mbox
.channel
== NULL
))
104 tegra186_bpmp_ring_doorbell(bpmp
);
107 static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel
*channel
,
108 struct tegra_bpmp
*bpmp
,
111 struct tegra186_bpmp
*priv
= bpmp
->priv
;
112 size_t message_size
, queue_size
;
113 struct iosys_map rx
, tx
;
117 channel
->ivc
= devm_kzalloc(bpmp
->dev
, sizeof(*channel
->ivc
),
122 message_size
= tegra_ivc_align(MSG_MIN_SZ
);
123 queue_size
= tegra_ivc_total_queue_size(message_size
);
124 offset
= queue_size
* index
;
127 iosys_map_set_vaddr_iomem(&rx
, priv
->rx
.sram
+ offset
);
128 iosys_map_set_vaddr_iomem(&tx
, priv
->tx
.sram
+ offset
);
130 iosys_map_set_vaddr(&rx
, priv
->rx
.dram
+ offset
);
131 iosys_map_set_vaddr(&tx
, priv
->tx
.dram
+ offset
);
134 err
= tegra_ivc_init(channel
->ivc
, NULL
, &rx
, priv
->rx
.phys
+ offset
, &tx
,
135 priv
->tx
.phys
+ offset
, 1, message_size
, tegra186_bpmp_ivc_notify
,
138 dev_err(bpmp
->dev
, "failed to setup IVC for channel %u: %d\n",
143 init_completion(&channel
->completion
);
144 channel
->bpmp
= bpmp
;
149 static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel
*channel
)
151 /* reset the channel state */
152 tegra_ivc_reset(channel
->ivc
);
154 /* sync the channel state with BPMP */
155 while (tegra_ivc_notified(channel
->ivc
))
159 static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel
*channel
)
161 tegra_ivc_cleanup(channel
->ivc
);
164 static void mbox_handle_rx(struct mbox_client
*client
, void *data
)
166 struct tegra_bpmp
*bpmp
= mbox_client_to_bpmp(client
);
168 tegra_bpmp_handle_rx(bpmp
);
171 static void tegra186_bpmp_teardown_channels(struct tegra_bpmp
*bpmp
)
173 struct tegra186_bpmp
*priv
= bpmp
->priv
;
176 for (i
= 0; i
< bpmp
->threaded
.count
; i
++) {
177 if (!bpmp
->threaded_channels
[i
].bpmp
)
180 tegra186_bpmp_channel_cleanup(&bpmp
->threaded_channels
[i
]);
183 tegra186_bpmp_channel_cleanup(bpmp
->rx_channel
);
184 tegra186_bpmp_channel_cleanup(bpmp
->tx_channel
);
187 gen_pool_free(priv
->tx
.pool
, (unsigned long)priv
->tx
.sram
, 4096);
188 gen_pool_free(priv
->rx
.pool
, (unsigned long)priv
->rx
.sram
, 4096);
192 static int tegra186_bpmp_dram_init(struct tegra_bpmp
*bpmp
)
194 struct tegra186_bpmp
*priv
= bpmp
->priv
;
195 struct device_node
*np
;
200 np
= of_parse_phandle(bpmp
->dev
->of_node
, "memory-region", 0);
204 err
= of_address_to_resource(np
, 0, &res
);
206 dev_warn(bpmp
->dev
, "failed to parse memory region: %d\n", err
);
210 size
= resource_size(&res
);
213 dev_warn(bpmp
->dev
, "DRAM region must be larger than 8 KiB\n");
217 priv
->tx
.phys
= res
.start
;
218 priv
->rx
.phys
= res
.start
+ SZ_4K
;
220 priv
->tx
.dram
= devm_memremap(bpmp
->dev
, priv
->tx
.phys
, size
,
222 if (IS_ERR(priv
->tx
.dram
)) {
223 err
= PTR_ERR(priv
->tx
.dram
);
224 dev_warn(bpmp
->dev
, "failed to map DRAM region: %d\n", err
);
228 priv
->rx
.dram
= priv
->tx
.dram
+ SZ_4K
;
233 static int tegra186_bpmp_sram_init(struct tegra_bpmp
*bpmp
)
235 struct tegra186_bpmp
*priv
= bpmp
->priv
;
238 priv
->tx
.pool
= of_gen_pool_get(bpmp
->dev
->of_node
, "shmem", 0);
239 if (!priv
->tx
.pool
) {
240 dev_err(bpmp
->dev
, "TX shmem pool not found\n");
241 return -EPROBE_DEFER
;
244 priv
->tx
.sram
= (void __iomem
*)gen_pool_dma_alloc(priv
->tx
.pool
, 4096,
246 if (!priv
->tx
.sram
) {
247 dev_err(bpmp
->dev
, "failed to allocate from TX pool\n");
251 priv
->rx
.pool
= of_gen_pool_get(bpmp
->dev
->of_node
, "shmem", 1);
252 if (!priv
->rx
.pool
) {
253 dev_err(bpmp
->dev
, "RX shmem pool not found\n");
258 priv
->rx
.sram
= (void __iomem
*)gen_pool_dma_alloc(priv
->rx
.pool
, 4096,
260 if (!priv
->rx
.sram
) {
261 dev_err(bpmp
->dev
, "failed to allocate from RX pool\n");
269 gen_pool_free(priv
->tx
.pool
, (unsigned long)priv
->tx
.sram
, 4096);
274 static int tegra186_bpmp_setup_channels(struct tegra_bpmp
*bpmp
)
279 err
= tegra186_bpmp_dram_init(bpmp
);
280 if (err
== -ENODEV
) {
281 err
= tegra186_bpmp_sram_init(bpmp
);
286 err
= tegra186_bpmp_channel_init(bpmp
->tx_channel
, bpmp
,
287 bpmp
->soc
->channels
.cpu_tx
.offset
);
291 err
= tegra186_bpmp_channel_init(bpmp
->rx_channel
, bpmp
,
292 bpmp
->soc
->channels
.cpu_rx
.offset
);
294 tegra186_bpmp_channel_cleanup(bpmp
->tx_channel
);
298 for (i
= 0; i
< bpmp
->threaded
.count
; i
++) {
299 unsigned int index
= bpmp
->soc
->channels
.thread
.offset
+ i
;
301 err
= tegra186_bpmp_channel_init(&bpmp
->threaded_channels
[i
],
308 tegra186_bpmp_teardown_channels(bpmp
);
313 static void tegra186_bpmp_reset_channels(struct tegra_bpmp
*bpmp
)
317 /* reset message channels */
318 tegra186_bpmp_channel_reset(bpmp
->tx_channel
);
319 tegra186_bpmp_channel_reset(bpmp
->rx_channel
);
321 for (i
= 0; i
< bpmp
->threaded
.count
; i
++)
322 tegra186_bpmp_channel_reset(&bpmp
->threaded_channels
[i
]);
325 static int tegra186_bpmp_init(struct tegra_bpmp
*bpmp
)
327 struct tegra186_bpmp
*priv
;
330 priv
= devm_kzalloc(bpmp
->dev
, sizeof(*priv
), GFP_KERNEL
);
337 err
= tegra186_bpmp_setup_channels(bpmp
);
341 /* mbox registration */
342 priv
->mbox
.client
.dev
= bpmp
->dev
;
343 priv
->mbox
.client
.rx_callback
= mbox_handle_rx
;
344 priv
->mbox
.client
.tx_block
= false;
345 priv
->mbox
.client
.knows_txdone
= false;
347 priv
->mbox
.channel
= mbox_request_channel(&priv
->mbox
.client
, 0);
348 if (IS_ERR(priv
->mbox
.channel
)) {
349 err
= PTR_ERR(priv
->mbox
.channel
);
350 dev_err(bpmp
->dev
, "failed to get HSP mailbox: %d\n", err
);
351 tegra186_bpmp_teardown_channels(bpmp
);
355 tegra186_bpmp_reset_channels(bpmp
);
360 static void tegra186_bpmp_deinit(struct tegra_bpmp
*bpmp
)
362 struct tegra186_bpmp
*priv
= bpmp
->priv
;
364 mbox_free_channel(priv
->mbox
.channel
);
366 tegra186_bpmp_teardown_channels(bpmp
);
369 static int tegra186_bpmp_resume(struct tegra_bpmp
*bpmp
)
371 tegra186_bpmp_reset_channels(bpmp
);
376 const struct tegra_bpmp_ops tegra186_bpmp_ops
= {
377 .init
= tegra186_bpmp_init
,
378 .deinit
= tegra186_bpmp_deinit
,
379 .is_response_ready
= tegra186_bpmp_is_message_ready
,
380 .is_request_ready
= tegra186_bpmp_is_message_ready
,
381 .ack_response
= tegra186_bpmp_ack_message
,
382 .ack_request
= tegra186_bpmp_ack_message
,
383 .is_response_channel_free
= tegra186_bpmp_is_channel_free
,
384 .is_request_channel_free
= tegra186_bpmp_is_channel_free
,
385 .post_response
= tegra186_bpmp_post_message
,
386 .post_request
= tegra186_bpmp_post_message
,
387 .ring_doorbell
= tegra186_bpmp_ring_doorbell
,
388 .resume
= tegra186_bpmp_resume
,