Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mailbox: tegra-hsp: Add tegra_hsp_sm_ops

This patch introduces tegra_hsp_sm_ops to abstract send & receive
API's for shared mailboxes.

Signed-off-by: Kartik <kkartik@nvidia.com>
Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>

authored by

Kartik and committed by
Jassi Brar
8f585d14 1b3418ac

+49 -29
+49 -29
drivers/mailbox/tegra-hsp.c
··· 67 67 unsigned int index; 68 68 }; 69 69 70 + struct tegra_hsp_sm_ops { 71 + void (*send)(struct tegra_hsp_channel *channel, void *data); 72 + void (*recv)(struct tegra_hsp_channel *channel); 73 + }; 74 + 70 75 struct tegra_hsp_mailbox { 71 76 struct tegra_hsp_channel channel; 77 + const struct tegra_hsp_sm_ops *ops; 72 78 unsigned int index; 73 79 bool producer; 74 80 }; ··· 214 208 { 215 209 struct tegra_hsp *hsp = data; 216 210 unsigned long bit, mask; 217 - u32 status, value; 218 - void *msg; 211 + u32 status; 219 212 220 213 status = tegra_hsp_readl(hsp, HSP_INT_IR) & hsp->mask; 221 214 ··· 250 245 for_each_set_bit(bit, &mask, hsp->num_sm) { 251 246 struct tegra_hsp_mailbox *mb = &hsp->mailboxes[bit]; 252 247 253 - if (!mb->producer) { 254 - value = tegra_hsp_channel_readl(&mb->channel, 255 - HSP_SM_SHRD_MBOX); 256 - value &= ~HSP_SM_SHRD_MBOX_FULL; 257 - msg = (void *)(unsigned long)value; 258 - mbox_chan_received_data(mb->channel.chan, msg); 259 - 260 - /* 261 - * Need to clear all bits here since some producers, 262 - * such as TCU, depend on fields in the register 263 - * getting cleared by the consumer. 264 - * 265 - * The mailbox API doesn't give the consumers a way 266 - * of doing that explicitly, so we have to make sure 267 - * we cover all possible cases. 268 - */ 269 - tegra_hsp_channel_writel(&mb->channel, 0x0, 270 - HSP_SM_SHRD_MBOX); 271 - } 248 + if (!mb->producer) 249 + mb->ops->recv(&mb->channel); 272 250 } 273 251 274 252 return IRQ_HANDLED; ··· 360 372 .shutdown = tegra_hsp_doorbell_shutdown, 361 373 }; 362 374 363 - static int tegra_hsp_mailbox_send_data(struct mbox_chan *chan, void *data) 375 + static void tegra_hsp_sm_send32(struct tegra_hsp_channel *channel, void *data) 364 376 { 365 - struct tegra_hsp_mailbox *mb = chan->con_priv; 366 - struct tegra_hsp *hsp = mb->channel.hsp; 367 - unsigned long flags; 368 377 u32 value; 369 - 370 - if (WARN_ON(!mb->producer)) 371 - return -EPERM; 372 378 373 379 /* copy data and mark mailbox full */ 374 380 value = (u32)(unsigned long)data; 375 381 value |= HSP_SM_SHRD_MBOX_FULL; 376 382 377 - tegra_hsp_channel_writel(&mb->channel, value, HSP_SM_SHRD_MBOX); 383 + tegra_hsp_channel_writel(channel, value, HSP_SM_SHRD_MBOX); 384 + } 385 + 386 + static void tegra_hsp_sm_recv32(struct tegra_hsp_channel *channel) 387 + { 388 + u32 value; 389 + void *msg; 390 + 391 + value = tegra_hsp_channel_readl(channel, HSP_SM_SHRD_MBOX); 392 + value &= ~HSP_SM_SHRD_MBOX_FULL; 393 + msg = (void *)(unsigned long)value; 394 + mbox_chan_received_data(channel->chan, msg); 395 + 396 + /* 397 + * Need to clear all bits here since some producers, such as TCU, depend 398 + * on fields in the register getting cleared by the consumer. 399 + * 400 + * The mailbox API doesn't give the consumers a way of doing that 401 + * explicitly, so we have to make sure we cover all possible cases. 402 + */ 403 + tegra_hsp_channel_writel(channel, 0x0, HSP_SM_SHRD_MBOX); 404 + } 405 + 406 + static const struct tegra_hsp_sm_ops tegra_hsp_sm_32bit_ops = { 407 + .send = tegra_hsp_sm_send32, 408 + .recv = tegra_hsp_sm_recv32, 409 + }; 410 + 411 + static int tegra_hsp_mailbox_send_data(struct mbox_chan *chan, void *data) 412 + { 413 + struct tegra_hsp_mailbox *mb = chan->con_priv; 414 + struct tegra_hsp *hsp = mb->channel.hsp; 415 + unsigned long flags; 416 + 417 + if (WARN_ON(!mb->producer)) 418 + return -EPERM; 419 + 420 + mb->ops->send(&mb->channel, data); 378 421 379 422 /* enable EMPTY interrupt for the shared mailbox */ 380 423 spin_lock_irqsave(&hsp->lock, flags); ··· 576 557 return ERR_PTR(-ENODEV); 577 558 578 559 mb = &hsp->mailboxes[index]; 560 + mb->ops = &tegra_hsp_sm_32bit_ops; 579 561 580 562 if ((args->args[1] & TEGRA_HSP_SM_FLAG_TX) == 0) 581 563 mb->producer = false;