1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (c) 2018, NVIDIA CORPORATION.
4  */
5 
6 #include <linux/genalloc.h>
7 #include <linux/mailbox_client.h>
8 #include <linux/platform_device.h>
9 
10 #include <soc/tegra/bpmp.h>
11 #include <soc/tegra/bpmp-abi.h>
12 #include <soc/tegra/ivc.h>
13 
14 #include "bpmp-private.h"
15 
16 struct tegra186_bpmp {
17 	struct tegra_bpmp *parent;
18 
19 	struct {
20 		struct gen_pool *pool;
21 		void __iomem *virt;
22 		dma_addr_t phys;
23 	} tx, rx;
24 
25 	struct {
26 		struct mbox_client client;
27 		struct mbox_chan *channel;
28 	} mbox;
29 };
30 
31 static inline struct tegra_bpmp *
32 mbox_client_to_bpmp(struct mbox_client *client)
33 {
34 	struct tegra186_bpmp *priv;
35 
36 	priv = container_of(client, struct tegra186_bpmp, mbox.client);
37 
38 	return priv->parent;
39 }
40 
41 static bool tegra186_bpmp_is_message_ready(struct tegra_bpmp_channel *channel)
42 {
43 	int err;
44 
45 	err = tegra_ivc_read_get_next_frame(channel->ivc, &channel->ib);
46 	if (err) {
47 		iosys_map_clear(&channel->ib);
48 		return false;
49 	}
50 
51 	return true;
52 }
53 
54 static bool tegra186_bpmp_is_channel_free(struct tegra_bpmp_channel *channel)
55 {
56 	int err;
57 
58 	err = tegra_ivc_write_get_next_frame(channel->ivc, &channel->ob);
59 	if (err) {
60 		iosys_map_clear(&channel->ob);
61 		return false;
62 	}
63 
64 	return true;
65 }
66 
67 static int tegra186_bpmp_ack_message(struct tegra_bpmp_channel *channel)
68 {
69 	return tegra_ivc_read_advance(channel->ivc);
70 }
71 
72 static int tegra186_bpmp_post_message(struct tegra_bpmp_channel *channel)
73 {
74 	return tegra_ivc_write_advance(channel->ivc);
75 }
76 
77 static int tegra186_bpmp_ring_doorbell(struct tegra_bpmp *bpmp)
78 {
79 	struct tegra186_bpmp *priv = bpmp->priv;
80 	int err;
81 
82 	err = mbox_send_message(priv->mbox.channel, NULL);
83 	if (err < 0)
84 		return err;
85 
86 	mbox_client_txdone(priv->mbox.channel, 0);
87 
88 	return 0;
89 }
90 
91 static void tegra186_bpmp_ivc_notify(struct tegra_ivc *ivc, void *data)
92 {
93 	struct tegra_bpmp *bpmp = data;
94 	struct tegra186_bpmp *priv = bpmp->priv;
95 
96 	if (WARN_ON(priv->mbox.channel == NULL))
97 		return;
98 
99 	tegra186_bpmp_ring_doorbell(bpmp);
100 }
101 
102 static int tegra186_bpmp_channel_init(struct tegra_bpmp_channel *channel,
103 				      struct tegra_bpmp *bpmp,
104 				      unsigned int index)
105 {
106 	struct tegra186_bpmp *priv = bpmp->priv;
107 	size_t message_size, queue_size;
108 	struct iosys_map rx, tx;
109 	unsigned int offset;
110 	int err;
111 
112 	channel->ivc = devm_kzalloc(bpmp->dev, sizeof(*channel->ivc),
113 				    GFP_KERNEL);
114 	if (!channel->ivc)
115 		return -ENOMEM;
116 
117 	message_size = tegra_ivc_align(MSG_MIN_SZ);
118 	queue_size = tegra_ivc_total_queue_size(message_size);
119 	offset = queue_size * index;
120 
121 	iosys_map_set_vaddr_iomem(&rx, priv->rx.virt + offset);
122 	iosys_map_set_vaddr_iomem(&tx, priv->tx.virt + offset);
123 
124 	err = tegra_ivc_init(channel->ivc, NULL, &rx, priv->rx.phys + offset, &tx,
125 			     priv->tx.phys + offset, 1, message_size, tegra186_bpmp_ivc_notify,
126 			     bpmp);
127 	if (err < 0) {
128 		dev_err(bpmp->dev, "failed to setup IVC for channel %u: %d\n",
129 			index, err);
130 		return err;
131 	}
132 
133 	init_completion(&channel->completion);
134 	channel->bpmp = bpmp;
135 
136 	return 0;
137 }
138 
139 static void tegra186_bpmp_channel_reset(struct tegra_bpmp_channel *channel)
140 {
141 	/* reset the channel state */
142 	tegra_ivc_reset(channel->ivc);
143 
144 	/* sync the channel state with BPMP */
145 	while (tegra_ivc_notified(channel->ivc))
146 		;
147 }
148 
149 static void tegra186_bpmp_channel_cleanup(struct tegra_bpmp_channel *channel)
150 {
151 	tegra_ivc_cleanup(channel->ivc);
152 }
153 
154 static void mbox_handle_rx(struct mbox_client *client, void *data)
155 {
156 	struct tegra_bpmp *bpmp = mbox_client_to_bpmp(client);
157 
158 	tegra_bpmp_handle_rx(bpmp);
159 }
160 
161 static int tegra186_bpmp_init(struct tegra_bpmp *bpmp)
162 {
163 	struct tegra186_bpmp *priv;
164 	unsigned int i;
165 	int err;
166 
167 	priv = devm_kzalloc(bpmp->dev, sizeof(*priv), GFP_KERNEL);
168 	if (!priv)
169 		return -ENOMEM;
170 
171 	bpmp->priv = priv;
172 	priv->parent = bpmp;
173 
174 	priv->tx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 0);
175 	if (!priv->tx.pool) {
176 		dev_err(bpmp->dev, "TX shmem pool not found\n");
177 		return -EPROBE_DEFER;
178 	}
179 
180 	priv->tx.virt = (void __iomem *)gen_pool_dma_alloc(priv->tx.pool, 4096, &priv->tx.phys);
181 	if (!priv->tx.virt) {
182 		dev_err(bpmp->dev, "failed to allocate from TX pool\n");
183 		return -ENOMEM;
184 	}
185 
186 	priv->rx.pool = of_gen_pool_get(bpmp->dev->of_node, "shmem", 1);
187 	if (!priv->rx.pool) {
188 		dev_err(bpmp->dev, "RX shmem pool not found\n");
189 		err = -EPROBE_DEFER;
190 		goto free_tx;
191 	}
192 
193 	priv->rx.virt = (void __iomem *)gen_pool_dma_alloc(priv->rx.pool, 4096, &priv->rx.phys);
194 	if (!priv->rx.virt) {
195 		dev_err(bpmp->dev, "failed to allocate from RX pool\n");
196 		err = -ENOMEM;
197 		goto free_tx;
198 	}
199 
200 	err = tegra186_bpmp_channel_init(bpmp->tx_channel, bpmp,
201 					 bpmp->soc->channels.cpu_tx.offset);
202 	if (err < 0)
203 		goto free_rx;
204 
205 	err = tegra186_bpmp_channel_init(bpmp->rx_channel, bpmp,
206 					 bpmp->soc->channels.cpu_rx.offset);
207 	if (err < 0)
208 		goto cleanup_tx_channel;
209 
210 	for (i = 0; i < bpmp->threaded.count; i++) {
211 		unsigned int index = bpmp->soc->channels.thread.offset + i;
212 
213 		err = tegra186_bpmp_channel_init(&bpmp->threaded_channels[i],
214 						 bpmp, index);
215 		if (err < 0)
216 			goto cleanup_channels;
217 	}
218 
219 	/* mbox registration */
220 	priv->mbox.client.dev = bpmp->dev;
221 	priv->mbox.client.rx_callback = mbox_handle_rx;
222 	priv->mbox.client.tx_block = false;
223 	priv->mbox.client.knows_txdone = false;
224 
225 	priv->mbox.channel = mbox_request_channel(&priv->mbox.client, 0);
226 	if (IS_ERR(priv->mbox.channel)) {
227 		err = PTR_ERR(priv->mbox.channel);
228 		dev_err(bpmp->dev, "failed to get HSP mailbox: %d\n", err);
229 		goto cleanup_channels;
230 	}
231 
232 	tegra186_bpmp_channel_reset(bpmp->tx_channel);
233 	tegra186_bpmp_channel_reset(bpmp->rx_channel);
234 
235 	for (i = 0; i < bpmp->threaded.count; i++)
236 		tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
237 
238 	return 0;
239 
240 cleanup_channels:
241 	for (i = 0; i < bpmp->threaded.count; i++) {
242 		if (!bpmp->threaded_channels[i].bpmp)
243 			continue;
244 
245 		tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
246 	}
247 
248 	tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
249 cleanup_tx_channel:
250 	tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
251 free_rx:
252 	gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
253 free_tx:
254 	gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
255 
256 	return err;
257 }
258 
259 static void tegra186_bpmp_deinit(struct tegra_bpmp *bpmp)
260 {
261 	struct tegra186_bpmp *priv = bpmp->priv;
262 	unsigned int i;
263 
264 	mbox_free_channel(priv->mbox.channel);
265 
266 	for (i = 0; i < bpmp->threaded.count; i++)
267 		tegra186_bpmp_channel_cleanup(&bpmp->threaded_channels[i]);
268 
269 	tegra186_bpmp_channel_cleanup(bpmp->rx_channel);
270 	tegra186_bpmp_channel_cleanup(bpmp->tx_channel);
271 
272 	gen_pool_free(priv->rx.pool, (unsigned long)priv->rx.virt, 4096);
273 	gen_pool_free(priv->tx.pool, (unsigned long)priv->tx.virt, 4096);
274 }
275 
276 static int tegra186_bpmp_resume(struct tegra_bpmp *bpmp)
277 {
278 	unsigned int i;
279 
280 	/* reset message channels */
281 	tegra186_bpmp_channel_reset(bpmp->tx_channel);
282 	tegra186_bpmp_channel_reset(bpmp->rx_channel);
283 
284 	for (i = 0; i < bpmp->threaded.count; i++)
285 		tegra186_bpmp_channel_reset(&bpmp->threaded_channels[i]);
286 
287 	return 0;
288 }
289 
290 const struct tegra_bpmp_ops tegra186_bpmp_ops = {
291 	.init = tegra186_bpmp_init,
292 	.deinit = tegra186_bpmp_deinit,
293 	.is_response_ready = tegra186_bpmp_is_message_ready,
294 	.is_request_ready = tegra186_bpmp_is_message_ready,
295 	.ack_response = tegra186_bpmp_ack_message,
296 	.ack_request = tegra186_bpmp_ack_message,
297 	.is_response_channel_free = tegra186_bpmp_is_channel_free,
298 	.is_request_channel_free = tegra186_bpmp_is_channel_free,
299 	.post_response = tegra186_bpmp_post_message,
300 	.post_request = tegra186_bpmp_post_message,
301 	.ring_doorbell = tegra186_bpmp_ring_doorbell,
302 	.resume = tegra186_bpmp_resume,
303 };
304