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

Configure Feed

Select the types of activity you want to include in your feed.

soc: qcom: smsm: Support using mailbox interface

Add support for using the mbox interface instead of manually writing to
the syscon. With this change the driver will attempt to get the mailbox
first, and if that fails it will fall back to the existing way of using
qcom,ipc-* properties and converting to syscon.

Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Signed-off-by: Luca Weiss <luca@z3ntu.xyz>
Link: https://lore.kernel.org/r/20240606-smsm-mbox-v2-2-8abe6b5f01da@z3ntu.xyz
Signed-off-by: Bjorn Andersson <andersson@kernel.org>

authored by

Luca Weiss and committed by
Bjorn Andersson
75287992 5e66abcf

+50 -1
+50 -1
drivers/soc/qcom/smsm.c
··· 5 5 */ 6 6 7 7 #include <linux/interrupt.h> 8 + #include <linux/mailbox_client.h> 8 9 #include <linux/mfd/syscon.h> 9 10 #include <linux/module.h> 10 11 #include <linux/of_irq.h> ··· 72 71 * @lock: spinlock for read-modify-write of the outgoing state 73 72 * @entries: context for each of the entries 74 73 * @hosts: context for each of the hosts 74 + * @mbox_client: mailbox client handle 75 75 */ 76 76 struct qcom_smsm { 77 77 struct device *dev; ··· 90 88 91 89 struct smsm_entry *entries; 92 90 struct smsm_host *hosts; 91 + 92 + struct mbox_client mbox_client; 93 93 }; 94 94 95 95 /** ··· 124 120 * @ipc_regmap: regmap for outgoing interrupt 125 121 * @ipc_offset: offset in @ipc_regmap for outgoing interrupt 126 122 * @ipc_bit: bit in @ipc_regmap + @ipc_offset for outgoing interrupt 123 + * @mbox_chan: apcs ipc mailbox channel handle 127 124 */ 128 125 struct smsm_host { 129 126 struct regmap *ipc_regmap; 130 127 int ipc_offset; 131 128 int ipc_bit; 129 + 130 + struct mbox_chan *mbox_chan; 132 131 }; 133 132 134 133 /** ··· 179 172 hostp = &smsm->hosts[host]; 180 173 181 174 val = readl(smsm->subscription + host); 182 - if (val & changes && hostp->ipc_regmap) { 175 + if (!(val & changes)) 176 + continue; 177 + 178 + if (hostp->mbox_chan) { 179 + mbox_send_message(hostp->mbox_chan, NULL); 180 + mbox_client_txdone(hostp->mbox_chan, 0); 181 + } else if (hostp->ipc_regmap) { 183 182 regmap_write(hostp->ipc_regmap, 184 183 hostp->ipc_offset, 185 184 BIT(hostp->ipc_bit)); ··· 366 353 }; 367 354 368 355 /** 356 + * smsm_parse_mbox() - requests an mbox channel 357 + * @smsm: smsm driver context 358 + * @host_id: index of the remote host to be resolved 359 + * 360 + * Requests the desired channel using the mbox interface which is needed for 361 + * sending the outgoing interrupts to a remove hosts - identified by @host_id. 362 + */ 363 + static int smsm_parse_mbox(struct qcom_smsm *smsm, unsigned int host_id) 364 + { 365 + struct smsm_host *host = &smsm->hosts[host_id]; 366 + int ret = 0; 367 + 368 + host->mbox_chan = mbox_request_channel(&smsm->mbox_client, host_id); 369 + if (IS_ERR(host->mbox_chan)) { 370 + ret = PTR_ERR(host->mbox_chan); 371 + host->mbox_chan = NULL; 372 + } 373 + 374 + return ret; 375 + } 376 + 377 + /** 369 378 * smsm_parse_ipc() - parses a qcom,ipc-%d device tree property 370 379 * @smsm: smsm driver context 371 380 * @host_id: index of the remote host to be resolved ··· 556 521 "qcom,local-host", 557 522 &smsm->local_host); 558 523 524 + smsm->mbox_client.dev = &pdev->dev; 525 + smsm->mbox_client.knows_txdone = true; 526 + 559 527 /* Parse the host properties */ 560 528 for (id = 0; id < smsm->num_hosts; id++) { 529 + /* Try using mbox interface first, otherwise fall back to syscon */ 530 + ret = smsm_parse_mbox(smsm, id); 531 + if (!ret) 532 + continue; 533 + 561 534 ret = smsm_parse_ipc(smsm, id); 562 535 if (ret < 0) 563 536 goto out_put; ··· 652 609 653 610 qcom_smem_state_unregister(smsm->state); 654 611 out_put: 612 + for (id = 0; id < smsm->num_hosts; id++) 613 + mbox_free_channel(smsm->hosts[id].mbox_chan); 614 + 655 615 of_node_put(local_node); 656 616 return ret; 657 617 } ··· 667 621 for (id = 0; id < smsm->num_entries; id++) 668 622 if (smsm->entries[id].domain) 669 623 irq_domain_remove(smsm->entries[id].domain); 624 + 625 + for (id = 0; id < smsm->num_hosts; id++) 626 + mbox_free_channel(smsm->hosts[id].mbox_chan); 670 627 671 628 qcom_smem_state_unregister(smsm->state); 672 629 }