summaryrefslogtreecommitdiffstats
path: root/drivers/firmware/tegra
diff options
context:
space:
mode:
authorTimo Alho <talho@nvidia.com>2019-01-24 12:03:53 -0500
committerThierry Reding <treding@nvidia.com>2019-01-25 09:58:47 -0500
commitcdfa358b248efd36c6a9cb4d4d0a3ba7509f8387 (patch)
treedb7d882df0d9233280ad0e4e300d3d3794f2b3f2 /drivers/firmware/tegra
parent165ce6e01d2d00bff2f10eba8dd679cee44163bd (diff)
firmware: tegra: Refactor BPMP driver
Split BPMP driver into common and chip specific parts to facilitate adding support for previous and future Tegra chips that are using BPMP as co-processor. Signed-off-by: Timo Alho <talho@nvidia.com> Acked-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/firmware/tegra')
-rw-r--r--drivers/firmware/tegra/Makefile1
-rw-r--r--drivers/firmware/tegra/bpmp-private.h28
-rw-r--r--drivers/firmware/tegra/bpmp-tegra186.c310
-rw-r--r--drivers/firmware/tegra/bpmp.c257
4 files changed, 394 insertions, 202 deletions
diff --git a/drivers/firmware/tegra/Makefile b/drivers/firmware/tegra/Makefile
index 1b826dcca719..559355674bca 100644
--- a/drivers/firmware/tegra/Makefile
+++ b/drivers/firmware/tegra/Makefile
@@ -1,4 +1,5 @@
1tegra-bpmp-y = bpmp.o 1tegra-bpmp-y = bpmp.o
2tegra-bpmp-$(CONFIG_ARCH_TEGRA_186_SOC) += bpmp-tegra186.o
2tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o 3tegra-bpmp-$(CONFIG_DEBUG_FS) += bpmp-debugfs.o
3obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o 4obj-$(CONFIG_TEGRA_BPMP) += tegra-bpmp.o
4obj-$(CONFIG_TEGRA_IVC) += ivc.o 5obj-$(CONFIG_TEGRA_IVC) += ivc.o
diff --git a/drivers/firmware/tegra/bpmp-private.h b/drivers/firmware/tegra/bpmp-private.h
new file mode 100644
index 000000000000..6fb10f1cfb8f
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-private.h
@@ -0,0 +1,28 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#ifndef __FIRMWARE_TEGRA_BPMP_PRIVATE_H
7#define __FIRMWARE_TEGRA_BPMP_PRIVATE_H
8
9#include <soc/tegra/bpmp.h>
10
11struct tegra_bpmp_ops {
12 int (*init)(struct tegra_bpmp *bpmp);
13 void (*deinit)(struct tegra_bpmp *bpmp);
14 bool (*is_response_ready)(struct tegra_bpmp_channel *channel);
15 bool (*is_request_ready)(struct tegra_bpmp_channel *channel);
16 int (*ack_response)(struct tegra_bpmp_channel *channel);
17 int (*ack_request)(struct tegra_bpmp_channel *channel);
18 bool (*is_response_channel_free)(struct tegra_bpmp_channel *channel);
19 bool (*is_request_channel_free)(struct tegra_bpmp_channel *channel);
20 int (*post_response)(struct tegra_bpmp_channel *channel);
21 int (*post_request)(struct tegra_bpmp_channel *channel);
22 int (*ring_doorbell)(struct tegra_bpmp *bpmp);
23 int (*resume)(struct tegra_bpmp *bpmp);
24};
25
26extern const struct tegra_bpmp_ops tegra186_bpmp_ops;
27
28#endif
diff --git a/drivers/firmware/tegra/bpmp-tegra186.c b/drivers/firmware/tegra/bpmp-tegra186.c
new file mode 100644
index 000000000000..89bb32b97345
--- /dev/null
+++ b/drivers/firmware/tegra/bpmp-tegra186.c
@@ -0,0 +1,310 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2018, NVIDIA CORPORATION.
4 */
5
6#include <linux/clk/tegra.h>
7#include <linux/genalloc.h>
8#include <linux/mailbox_client.h>
9#include <linux/of.h>
10#include <linux/of_address.h>
11#include <linux/of_device.h>
12#include <linux/platform_device.h>
13#include <linux/semaphore.h>
14
15#include <soc/tegra/bpmp.h>
16#include <soc/tegra/bpmp-abi.h>
17#include <soc/tegra/ivc.h>
18
19#include "bpmp-private.h"
20
21struct tegra186_bpmp {
22 struct tegra_bpmp *parent;
23
24 struct {
25 struct gen_pool *pool;
26 dma_addr_t phys;
27 void *virt;
28 } tx, rx;
29
30 struct {
31 struct mbox_client client;
32 struct mbox_chan *channel;
33 } mbox;
34};
35
36static inline struct tegra_bpmp *
37mbox_client_to_bpmp(struct mbox_client *client)
38{
39 struct tegra186_bpmp *priv;
40
41 priv = container_of(client, struct tegra186_bpmp, mbox.client);
42
43 return priv->parent;
44}
45
46static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
47{
48 void *frame;
49
50 frame = tegra_ivc_read_get_next_frame(channel->ivc);
51 if (IS_ERR(frame)) {
52 channel->ib = NULL;
53 return false;
54 }
55
56 channel->ib = frame;
57
58 return true;
59}
60
61static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
62{
63 void *frame;
64
65 frame = tegra_ivc_write_get_next_frame(channel->ivc);
66 if (IS_ERR(frame)) {
67 channel->ob = NULL;
68 return false;
69 }
70
71 channel->ob = frame;
72
73 return true;
74}
75
76static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
77{
78 return tegra_ivc_read_advance(channel->ivc);
79}
80
81static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
82{
83 return tegra_ivc_write_advance(channel->ivc);
84}
85
86static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
87{
88 struct tegra186_bpmp *priv = bpmp->priv;
89 int err;
90
91 err = mbox_send_message(priv->mbox.channel, NULL);
92 if (err < 0)
93 return err;
94
95 mbox_client_txdone(priv->mbox.channel, 0);
96
97 return 0;
98}
99
100static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
101{
102 struct tegra_bpmp *bpmp = data;
103 struct tegra186_bpmp *priv = bpmp->priv;
104
105 if (WARN_ON(priv->mbox.channel == NULL))
106 return;
107
108 tegra186_bpmp_ring_doorbell(bpmp);
109}
110
111static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
112 struct tegra_bpmp *bpmp,
113 unsigned int index)
114{
115 struct tegra186_bpmp *priv = bpmp->priv;
116 size_t message_size, queue_size;
117 unsigned int offset;
118 int err;
119
120 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
121 GFP_KERNEL);
122 if (!channel->ivc)
123 return -ENOMEM;
124
125 message_size = tegra_ivc_align(MSG_MIN_SZ);
126 queue_size = tegra_ivc_total_queue_size(message_size);
127 offset = queue_size * index;
128
129 err = tegra_ivc_init(channel->ivc, NULL,
130 priv->rx.virt + offset, priv->rx.phys + offset,
131 priv->tx.virt + offset, priv->tx.phys + offset,
132 1, message_size, tegra186_bpmp_ivc_notify,
133 bpmp);
134 if (err < 0) {
135 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
136 index, err);
137 return err;
138 }
139
140 init_completion(&channel->completion);
141 channel->bpmp = bpmp;
142
143 return 0;
144}
145
146static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
147{
148 /* reset the channel state */
149 tegra_ivc_reset(channel->ivc);
150
151 /* sync the channel state with BPMP */
152 while (tegra_ivc_notified(channel->ivc))
153 ;
154}
155
156static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
157{
158 tegra_ivc_cleanup(channel->ivc);
159}
160
161static void mbox_handle_rx(struct mbox_client *client, void *data)
162{
163 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
164
165 tegra_bpmp_handle_rx(bpmp);
166}
167
168static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
169{
170 struct tegra186_bpmp *priv;
171 unsigned int i;
172 int err;
173
174 priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
175 if (!priv)
176 return -ENOMEM;
177
178 bpmp->priv = priv;
179 priv->parent = bpmp;
180
181 priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
182 if (!priv->tx.pool) {
183 dev_err(bpmp->dev, "TX shmem pool not found\n");
184 return -ENOMEM;
185 }
186
187 priv->tx.virt = gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
188 if (!priv->tx.virt) {
189 dev_err(bpmp->dev, "failed to allocate from TX pool\n");
190 return -ENOMEM;
191 }
192
193 priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
194 if (!priv->rx.pool) {
195 dev_err(bpmp->dev, "RX shmem pool not found\n");
196 err = -ENOMEM;
197 goto free_tx;
198 }
199
200 priv->rx.virt = gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
201 if (!priv->rx.virt) {
202 dev_err(bpmp->dev, "failed to allocate from RX pool\n");
203 err = -ENOMEM;
204 goto free_tx;
205 }
206
207 err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
208 bpmp->soc->channels.cpu_tx.offset);
209 if (err < 0)
210 goto free_rx;
211
212 err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
213 bpmp->soc->channels.cpu_rx.offset);
214 if (err < 0)
215 goto cleanup_tx_channel;
216
217 for (i = 0; i < bpmp->threaded.count; i++) {
218 unsigned int index = bpmp->soc->channels.thread.offset + i;
219
220 err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
221 bpmp, index);
222 if (err < 0)
223 goto cleanup_channels;
224 }
225
226 /* mbox registration */
227 priv->mbox.client.dev = bpmp->dev;
228 priv->mbox.client.rx_callback = mbox_handle_rx;
229 priv->mbox.client.tx_block = false;
230 priv->mbox.client.knows_txdone = false;
231
232 priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
233 if (IS_ERR(priv->mbox.channel)) {
234 err = PTR_ERR(priv->mbox.channel);
235 dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
236 goto cleanup_channels;
237 }
238
239 tegra186_bpmp_channel_reset(bpmp->tx_channel);
240 tegra186_bpmp_channel_reset(bpmp->rx_channel);
241
242 for (i = 0; i < bpmp->threaded.count; i++)
243 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
244
245 return 0;
246
247cleanup_channels:
248 for (i = 0; i < bpmp->threaded.count; i++) {
249 if (!bpmp->threaded_channels[i].bpmp)
250 continue;
251
252 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
253 }
254
255 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
256cleanup_tx_channel:
257 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
258free_rx:
259 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
260free_tx:
261 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
262
263 return err;
264}
265
266static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
267{
268 struct tegra186_bpmp *priv = bpmp->priv;
269 unsigned int i;
270
271 mbox_free_channel(priv->mbox.channel);
272
273 for (i = 0; i < bpmp->threaded.count; i++)
274 tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
275
276 tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
277 tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
278
279 gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
280 gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
281}
282
283static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
284{
285 unsigned int i;
286
287 /* reset message channels */
288 tegra186_bpmp_channel_reset(bpmp->tx_channel);
289 tegra186_bpmp_channel_reset(bpmp->rx_channel);
290
291 for (i = 0; i < bpmp->threaded.count; i++)
292 tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
293
294 return 0;
295}
296
297const struct tegra_bpmp_ops tegra186_bpmp_ops = {
298 .init = tegra186_bpmp_init,
299 .deinit = tegra186_bpmp_deinit,
300 .is_response_ready = tegra186_bpmp_is_message_ready,
301 .is_request_ready = tegra186_bpmp_is_message_ready,
302 .ack_response = tegra186_bpmp_ack_message,
303 .ack_request = tegra186_bpmp_ack_message,
304 .is_response_channel_free = tegra186_bpmp_is_channel_free,
305 .is_request_channel_free = tegra186_bpmp_is_channel_free,
306 .post_response = tegra186_bpmp_post_message,
307 .post_request = tegra186_bpmp_post_message,
308 .ring_doorbell = tegra186_bpmp_ring_doorbell,
309 .resume = tegra186_bpmp_resume,
310};
diff --git a/drivers/firmware/tegra/bpmp.c b/drivers/firmware/tegra/bpmp.c
index e7fd68ebedd0..2b498deacdbc 100644
--- a/drivers/firmware/tegra/bpmp.c
+++ b/drivers/firmware/tegra/bpmp.c
@@ -26,6 +26,8 @@
26#include <soc/tegra/bpmp-abi.h> 26#include <soc/tegra/bpmp-abi.h>
27#include <soc/tegra/ivc.h> 27#include <soc/tegra/ivc.h>
28 28
29#include "bpmp-private.h"
30
29#define MSG_ACK BIT(0) 31#define MSG_ACK BIT(0)
30#define MSG_RING BIT(1) 32#define MSG_RING BIT(1)
31#define TAG_SZ 32 33#define TAG_SZ 32
@@ -36,6 +38,14 @@ mbox_client_to_bpmp(struct mbox_client *client)
36 return container_of(client, struct tegra_bpmp, mbox.client); 38 return container_of(client, struct tegra_bpmp, mbox.client);
37} 39}
38 40
41static inline const struct tegra_bpmp_ops *
42channel_to_ops(struct tegra_bpmp_channel *channel)
43{
44 struct tegra_bpmp *bpmp = channel->bpmp;
45
46 return bpmp->soc->ops;
47}
48
39struct tegra_bpmp *tegra_bpmp_get(struct device *dev) 49struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
40{ 50{
41 struct platform_device *pdev; 51 struct platform_device *pdev;
@@ -98,22 +108,16 @@ static bool tegra_bpmp_message_valid(const struct tegra_bpmp_message *msg)
98 108
99static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel) 109static bool tegra_bpmp_is_response_ready(struct tegra_bpmp_channel *channel)
100{ 110{
101 void *frame; 111 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
102 112
103 frame = tegra_ivc_read_get_next_frame(channel->ivc); 113 return ops->is_response_ready(channel);
104 if (IS_ERR(frame)) {
105 channel->ib = NULL;
106 return false;
107 }
108
109 channel->ib = frame;
110
111 return true;
112} 114}
113 115
114static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel) 116static bool tegra_bpmp_is_request_ready(struct tegra_bpmp_channel *channel)
115{ 117{
116 return tegra_bpmp_is_response_ready(channel); 118 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
119
120 return ops->is_request_ready(channel);
117} 121}
118 122
119static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel) 123static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
@@ -133,34 +137,32 @@ static int tegra_bpmp_wait_response(struct tegra_bpmp_channel *channel)
133 137
134static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel) 138static int tegra_bpmp_ack_response(struct tegra_bpmp_channel *channel)
135{ 139{
136 return tegra_ivc_read_advance(channel->ivc); 140 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
141
142 return ops->ack_response(channel);
137} 143}
138 144
139static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel) 145static int tegra_bpmp_ack_request(struct tegra_bpmp_channel *channel)
140{ 146{
141 return tegra_ivc_read_advance(channel->ivc); 147 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
148
149 return ops->ack_request(channel);
142} 150}
143 151
144static bool 152static bool
145tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel) 153tegra_bpmp_is_request_channel_free(struct tegra_bpmp_channel *channel)
146{ 154{
147 void *frame; 155 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
148
149 frame = tegra_ivc_write_get_next_frame(channel->ivc);
150 if (IS_ERR(frame)) {
151 channel->ob = NULL;
152 return false;
153 }
154
155 channel->ob = frame;
156 156
157 return true; 157 return ops->is_request_channel_free(channel);
158} 158}
159 159
160static bool 160static bool
161tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel) 161tegra_bpmp_is_response_channel_free(struct tegra_bpmp_channel *channel)
162{ 162{
163 return tegra_bpmp_is_request_channel_free(channel); 163 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
164
165 return ops->is_response_channel_free(channel);
164} 166}
165 167
166static int 168static int
@@ -183,28 +185,21 @@ tegra_bpmp_wait_request_channel_free(struct tegra_bpmp_channel *channel)
183 185
184static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel) 186static int tegra_bpmp_post_request(struct tegra_bpmp_channel *channel)
185{ 187{
186 return tegra_ivc_write_advance(channel->ivc); 188 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
189
190 return ops->post_request(channel);
187} 191}
188 192
189static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel) 193static int tegra_bpmp_post_response(struct tegra_bpmp_channel *channel)
190{ 194{
191 return tegra_ivc_write_advance(channel->ivc); 195 const struct tegra_bpmp_ops *ops = channel_to_ops(channel);
196
197 return ops->post_response(channel);
192} 198}
193 199
194static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp) 200static int tegra_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
195{ 201{
196 int err; 202 return bpmp->soc->ops->ring_doorbell(bpmp);
197
198 if (WARN_ON(bpmp->mbox.channel == NULL))
199 return -EINVAL;
200
201 err = mbox_send_message(bpmp->mbox.channel, NULL);
202 if (err < 0)
203 return err;
204
205 mbox_client_txdone(bpmp->mbox.channel, 0);
206
207 return 0;
208} 203}
209 204
210static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel, 205static ssize_t __tegra_bpmp_channel_read(struct tegra_bpmp_channel *channel,
@@ -668,9 +663,8 @@ static void tegra_bpmp_channel_signal(struct tegra_bpmp_channel *channel)
668 complete(&channel->completion); 663 complete(&channel->completion);
669} 664}
670 665
671static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data) 666void tegra_bpmp_handle_rx(struct tegra_bpmp *bpmp)
672{ 667{
673 struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
674 struct tegra_bpmp_channel *channel; 668 struct tegra_bpmp_channel *channel;
675 unsigned int i, count; 669 unsigned int i, count;
676 unsigned long *busy; 670 unsigned long *busy;
@@ -698,66 +692,9 @@ static void tegra_bpmp_handle_rx(struct mbox_client *client, void *data)
698 spin_unlock(&bpmp->lock); 692 spin_unlock(&bpmp->lock);
699} 693}
700 694
701static void tegra_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
702{
703 struct tegra_bpmp *bpmp = data;
704
705 WARN_ON(tegra_bpmp_ring_doorbell(bpmp));
706}
707
708static int tegra_bpmp_channel_init(struct tegra_bpmp_channel *channel,
709 struct tegra_bpmp *bpmp,
710 unsigned int index)
711{
712 size_t message_size, queue_size;
713 unsigned int offset;
714 int err;
715
716 channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
717 GFP_KERNEL);
718 if (!channel->ivc)
719 return -ENOMEM;
720
721 message_size = tegra_ivc_align(MSG_MIN_SZ);
722 queue_size = tegra_ivc_total_queue_size(message_size);
723 offset = queue_size * index;
724
725 err = tegra_ivc_init(channel->ivc, NULL,
726 bpmp->rx.virt + offset, bpmp->rx.phys + offset,
727 bpmp->tx.virt + offset, bpmp->tx.phys + offset,
728 1, message_size, tegra_bpmp_ivc_notify,
729 bpmp);
730 if (err < 0) {
731 dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
732 index, err);
733 return err;
734 }
735
736 init_completion(&channel->completion);
737 channel->bpmp = bpmp;
738
739 return 0;
740}
741
742static void tegra_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
743{
744 /* reset the channel state */
745 tegra_ivc_reset(channel->ivc);
746
747 /* sync the channel state with BPMP */
748 while (tegra_ivc_notified(channel->ivc))
749 ;
750}
751
752static void tegra_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
753{
754 tegra_ivc_cleanup(channel->ivc);
755}
756
757static int tegra_bpmp_probe(struct platform_device *pdev) 695static int tegra_bpmp_probe(struct platform_device *pdev)
758{ 696{
759 struct tegra_bpmp *bpmp; 697 struct tegra_bpmp *bpmp;
760 unsigned int i;
761 char tag[TAG_SZ]; 698 char tag[TAG_SZ];
762 size_t size; 699 size_t size;
763 int err; 700 int err;
@@ -769,32 +706,6 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
769 bpmp->soc = of_device_get_match_data(&pdev->dev); 706 bpmp->soc = of_device_get_match_data(&pdev->dev);
770 bpmp->dev = &pdev->dev; 707 bpmp->dev = &pdev->dev;
771 708
772 bpmp->tx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 0);
773 if (!bpmp->tx.pool) {
774 dev_err(&pdev->dev, "TX shmem pool not found\n");
775 return -ENOMEM;
776 }
777
778 bpmp->tx.virt = gen_pool_dma_alloc(bpmp->tx.pool, 4096, &bpmp->tx.phys);
779 if (!bpmp->tx.virt) {
780 dev_err(&pdev->dev, "failed to allocate from TX pool\n");
781 return -ENOMEM;
782 }
783
784 bpmp->rx.pool = of_gen_pool_get(pdev->dev.of_node, "shmem", 1);
785 if (!bpmp->rx.pool) {
786 dev_err(&pdev->dev, "RX shmem pool not found\n");
787 err = -ENOMEM;
788 goto free_tx;
789 }
790
791 bpmp->rx.virt = gen_pool_dma_alloc(bpmp->rx.pool, 4096, &bpmp->rx.phys);
792 if (!bpmp->rx.virt) {
793 dev_err(&pdev->dev, "failed to allocate from RX pool\n");
794 err = -ENOMEM;
795 goto free_tx;
796 }
797
798 INIT_LIST_HEAD(&bpmp->mrqs); 709 INIT_LIST_HEAD(&bpmp->mrqs);
799 spin_lock_init(&bpmp->lock); 710 spin_lock_init(&bpmp->lock);
800 711
@@ -804,81 +715,38 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
804 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long); 715 size = BITS_TO_LONGS(bpmp->threaded.count) * sizeof(long);
805 716
806 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 717 bpmp->threaded.allocated = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
807 if (!bpmp->threaded.allocated) { 718 if (!bpmp->threaded.allocated)
808 err = -ENOMEM; 719 return -ENOMEM;
809 goto free_rx;
810 }
811 720
812 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); 721 bpmp->threaded.busy = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
813 if (!bpmp->threaded.busy) { 722 if (!bpmp->threaded.busy)
814 err = -ENOMEM; 723 return -ENOMEM;
815 goto free_rx;
816 }
817 724
818 spin_lock_init(&bpmp->atomic_tx_lock); 725 spin_lock_init(&bpmp->atomic_tx_lock);
819 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel), 726 bpmp->tx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->tx_channel),
820 GFP_KERNEL); 727 GFP_KERNEL);
821 if (!bpmp->tx_channel) { 728 if (!bpmp->tx_channel)
822 err = -ENOMEM; 729 return -ENOMEM;
823 goto free_rx;
824 }
825 730
826 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel), 731 bpmp->rx_channel = devm_kzalloc(&pdev->dev, sizeof(*bpmp->rx_channel),
827 GFP_KERNEL); 732 GFP_KERNEL);
828 if (!bpmp->rx_channel) { 733 if (!bpmp->rx_channel)
829 err = -ENOMEM; 734 return -ENOMEM;
830 goto free_rx;
831 }
832 735
833 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count, 736 bpmp->threaded_channels = devm_kcalloc(&pdev->dev, bpmp->threaded.count,
834 sizeof(*bpmp->threaded_channels), 737 sizeof(*bpmp->threaded_channels),
835 GFP_KERNEL); 738 GFP_KERNEL);
836 if (!bpmp->threaded_channels) { 739 if (!bpmp->threaded_channels)
837 err = -ENOMEM; 740 return -ENOMEM;
838 goto free_rx;
839 }
840
841 err = tegra_bpmp_channel_init(bpmp->tx_channel, bpmp,
842 bpmp->soc->channels.cpu_tx.offset);
843 if (err < 0)
844 goto free_rx;
845 741
846 err = tegra_bpmp_channel_init(bpmp->rx_channel, bpmp, 742 err = bpmp->soc->ops->init(bpmp);
847 bpmp->soc->channels.cpu_rx.offset);
848 if (err < 0) 743 if (err < 0)
849 goto cleanup_tx_channel; 744 return err;
850
851 for (i = 0; i < bpmp->threaded.count; i++) {
852 err = tegra_bpmp_channel_init(
853 &bpmp->threaded_channels[i], bpmp,
854 bpmp->soc->channels.thread.offset + i);
855 if (err < 0)
856 goto cleanup_threaded_channels;
857 }
858
859 /* mbox registration */
860 bpmp->mbox.client.dev = &pdev->dev;
861 bpmp->mbox.client.rx_callback = tegra_bpmp_handle_rx;
862 bpmp->mbox.client.tx_block = false;
863 bpmp->mbox.client.knows_txdone = false;
864
865 bpmp->mbox.channel = mbox_request_channel(&bpmp->mbox.client, 0);
866 if (IS_ERR(bpmp->mbox.channel)) {
867 err = PTR_ERR(bpmp->mbox.channel);
868 dev_err(&pdev->dev, "failed to get HSP mailbox: %d\n", err);
869 goto cleanup_threaded_channels;
870 }
871
872 /* reset message channels */
873 tegra_bpmp_channel_reset(bpmp->tx_channel);
874 tegra_bpmp_channel_reset(bpmp->rx_channel);
875 for (i = 0; i < bpmp->threaded.count; i++)
876 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
877 745
878 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING, 746 err = tegra_bpmp_request_mrq(bpmp, MRQ_PING,
879 tegra_bpmp_mrq_handle_ping, bpmp); 747 tegra_bpmp_mrq_handle_ping, bpmp);
880 if (err < 0) 748 if (err < 0)
881 goto free_mbox; 749 goto deinit;
882 750
883 err = tegra_bpmp_ping(bpmp); 751 err = tegra_bpmp_ping(bpmp);
884 if (err < 0) { 752 if (err < 0) {
@@ -920,37 +788,21 @@ static int tegra_bpmp_probe(struct platform_device *pdev)
920 788
921free_mrq: 789free_mrq:
922 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp); 790 tegra_bpmp_free_mrq(bpmp, MRQ_PING, bpmp);
923free_mbox: 791deinit:
924 mbox_free_channel(bpmp->mbox.channel); 792 if (bpmp->soc->ops->deinit)
925cleanup_threaded_channels: 793 bpmp->soc->ops->deinit(bpmp);
926 for (i = 0; i < bpmp->threaded.count; i++) {
927 if (bpmp->threaded_channels[i].bpmp)
928 tegra_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
929 }
930 794
931 tegra_bpmp_channel_cleanup(bpmp->rx_channel);
932cleanup_tx_channel:
933 tegra_bpmp_channel_cleanup(bpmp->tx_channel);
934free_rx:
935 gen_pool_free(bpmp->rx.pool, (unsigned long)bpmp->rx.virt, 4096);
936free_tx:
937 gen_pool_free(bpmp->tx.pool, (unsigned long)bpmp->tx.virt, 4096);
938 return err; 795 return err;
939} 796}
940 797
941static int __maybe_unused tegra_bpmp_resume(struct device *dev) 798static int __maybe_unused tegra_bpmp_resume(struct device *dev)
942{ 799{
943 struct tegra_bpmp *bpmp = dev_get_drvdata(dev); 800 struct tegra_bpmp *bpmp = dev_get_drvdata(dev);
944 unsigned int i;
945
946 /* reset message channels */
947 tegra_bpmp_channel_reset(bpmp->tx_channel);
948 tegra_bpmp_channel_reset(bpmp->rx_channel);
949
950 for (i = 0; i < bpmp->threaded.count; i++)
951 tegra_bpmp_channel_reset(&bpmp->threaded_channels[i]);
952 801
953 return 0; 802 if (bpmp->soc->ops->resume)
803 return bpmp->soc->ops->resume(bpmp);
804 else
805 return 0;
954} 806}
955 807
956static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume); 808static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume);
@@ -971,6 +823,7 @@ static const struct tegra_bpmp_soc tegra186_soc = {
971 .timeout = 0, 823 .timeout = 0,
972 }, 824 },
973 }, 825 },
826 .ops = &tegra186_bpmp_ops,
974 .num_resets = 193, 827 .num_resets = 193,
975}; 828};
976 829