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