Lines Matching full:smp2p

25  * The Shared Memory Point to Point (SMP2P) protocol facilitates communication
34 * single-writer, SMP2P does not require any remote locking mechanisms.
84 * @smp2p: reference to the device driver context
97 struct qcom_smp2p *smp2p; member
165 #include "trace-smp2p.h"
167 static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) in qcom_smp2p_kick() argument
172 if (smp2p->mbox_chan) { in qcom_smp2p_kick()
173 mbox_send_message(smp2p->mbox_chan, NULL); in qcom_smp2p_kick()
174 mbox_client_txdone(smp2p->mbox_chan, 0); in qcom_smp2p_kick()
176 regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); in qcom_smp2p_kick()
180 static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) in qcom_smp2p_check_ssr() argument
182 struct smp2p_smem_item *in = smp2p->in; in qcom_smp2p_check_ssr()
185 if (!smp2p->ssr_ack_enabled) in qcom_smp2p_check_ssr()
190 return restart != smp2p->ssr_ack; in qcom_smp2p_check_ssr()
193 static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p) in qcom_smp2p_do_ssr_ack() argument
195 struct smp2p_smem_item *out = smp2p->out; in qcom_smp2p_do_ssr_ack()
198 trace_smp2p_ssr_ack(smp2p->dev); in qcom_smp2p_do_ssr_ack()
199 smp2p->ssr_ack = !smp2p->ssr_ack; in qcom_smp2p_do_ssr_ack()
202 if (smp2p->ssr_ack) in qcom_smp2p_do_ssr_ack()
206 qcom_smp2p_kick(smp2p); in qcom_smp2p_do_ssr_ack()
209 static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p) in qcom_smp2p_negotiate() argument
211 struct smp2p_smem_item *out = smp2p->out; in qcom_smp2p_negotiate()
212 struct smp2p_smem_item *in = smp2p->in; in qcom_smp2p_negotiate()
218 smp2p->ssr_ack_enabled = true; in qcom_smp2p_negotiate()
220 smp2p->negotiation_done = true; in qcom_smp2p_negotiate()
221 trace_smp2p_negotiate(smp2p->dev, out->features); in qcom_smp2p_negotiate()
225 static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p) in qcom_smp2p_notify_in() argument
235 in = smp2p->in; in qcom_smp2p_notify_in()
238 for (i = smp2p->valid_entries; i < in->valid_entries; i++) { in qcom_smp2p_notify_in()
239 list_for_each_entry(entry, &smp2p->inbound, node) { in qcom_smp2p_notify_in()
247 smp2p->valid_entries = i; in qcom_smp2p_notify_in()
250 list_for_each_entry(entry, &smp2p->inbound, node) { in qcom_smp2p_notify_in()
282 * @data: smp2p driver context
292 struct qcom_smp2p *smp2p = data; in qcom_smp2p_intr() local
293 unsigned int smem_id = smp2p->smem_items[SMP2P_INBOUND]; in qcom_smp2p_intr()
294 unsigned int pid = smp2p->remote_pid; in qcom_smp2p_intr()
298 in = smp2p->in; in qcom_smp2p_intr()
304 dev_err(smp2p->dev, in qcom_smp2p_intr()
305 "Unable to acquire remote smp2p item\n"); in qcom_smp2p_intr()
309 smp2p->in = in; in qcom_smp2p_intr()
312 if (!smp2p->negotiation_done) in qcom_smp2p_intr()
313 qcom_smp2p_negotiate(smp2p); in qcom_smp2p_intr()
315 if (smp2p->negotiation_done) { in qcom_smp2p_intr()
316 ack_restart = qcom_smp2p_check_ssr(smp2p); in qcom_smp2p_intr()
317 qcom_smp2p_notify_in(smp2p); in qcom_smp2p_intr()
320 qcom_smp2p_do_ssr_ack(smp2p); in qcom_smp2p_intr()
368 seq_printf(p, "%8s", dev_name(entry->smp2p->dev)); in smp2p_irq_print_chip()
372 .name = "smp2p",
398 static int qcom_smp2p_inbound_entry(struct qcom_smp2p *smp2p, in qcom_smp2p_inbound_entry() argument
404 dev_err(smp2p->dev, "failed to add irq_domain\n"); in qcom_smp2p_inbound_entry()
428 qcom_smp2p_kick(entry->smp2p); in smp2p_update_bits()
437 static int qcom_smp2p_outbound_entry(struct qcom_smp2p *smp2p, in qcom_smp2p_outbound_entry() argument
441 struct smp2p_smem_item *out = smp2p->out; in qcom_smp2p_outbound_entry()
455 dev_err(smp2p->dev, "failed to register qcom_smem_state\n"); in qcom_smp2p_outbound_entry()
462 static int qcom_smp2p_alloc_outbound_item(struct qcom_smp2p *smp2p) in qcom_smp2p_alloc_outbound_item() argument
465 unsigned smem_id = smp2p->smem_items[SMP2P_OUTBOUND]; in qcom_smp2p_alloc_outbound_item()
466 unsigned pid = smp2p->remote_pid; in qcom_smp2p_alloc_outbound_item()
471 return dev_err_probe(smp2p->dev, ret, in qcom_smp2p_alloc_outbound_item()
472 "unable to allocate local smp2p item\n"); in qcom_smp2p_alloc_outbound_item()
476 dev_err(smp2p->dev, "Unable to acquire local smp2p item\n"); in qcom_smp2p_alloc_outbound_item()
482 out->local_pid = smp2p->local_pid; in qcom_smp2p_alloc_outbound_item()
483 out->remote_pid = smp2p->remote_pid; in qcom_smp2p_alloc_outbound_item()
495 qcom_smp2p_kick(smp2p); in qcom_smp2p_alloc_outbound_item()
497 smp2p->out = out; in qcom_smp2p_alloc_outbound_item()
502 static int smp2p_parse_ipc(struct qcom_smp2p *smp2p) in smp2p_parse_ipc() argument
505 struct device *dev = smp2p->dev; in smp2p_parse_ipc()
515 smp2p->ipc_regmap = syscon_node_to_regmap(syscon); in smp2p_parse_ipc()
517 if (IS_ERR(smp2p->ipc_regmap)) in smp2p_parse_ipc()
518 return PTR_ERR(smp2p->ipc_regmap); in smp2p_parse_ipc()
521 ret = of_property_read_u32_index(dev->of_node, key, 1, &smp2p->ipc_offset); in smp2p_parse_ipc()
527 ret = of_property_read_u32_index(dev->of_node, key, 2, &smp2p->ipc_bit); in smp2p_parse_ipc()
539 struct qcom_smp2p *smp2p; in qcom_smp2p_probe() local
544 smp2p = devm_kzalloc(&pdev->dev, sizeof(*smp2p), GFP_KERNEL); in qcom_smp2p_probe()
545 if (!smp2p) in qcom_smp2p_probe()
548 smp2p->dev = &pdev->dev; in qcom_smp2p_probe()
549 INIT_LIST_HEAD(&smp2p->inbound); in qcom_smp2p_probe()
550 INIT_LIST_HEAD(&smp2p->outbound); in qcom_smp2p_probe()
552 platform_set_drvdata(pdev, smp2p); in qcom_smp2p_probe()
556 smp2p->smem_items, 2); in qcom_smp2p_probe()
561 ret = of_property_read_u32(pdev->dev.of_node, key, &smp2p->local_pid); in qcom_smp2p_probe()
566 ret = of_property_read_u32(pdev->dev.of_node, key, &smp2p->remote_pid); in qcom_smp2p_probe()
574 smp2p->mbox_client.dev = &pdev->dev; in qcom_smp2p_probe()
575 smp2p->mbox_client.knows_txdone = true; in qcom_smp2p_probe()
576 smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); in qcom_smp2p_probe()
577 if (IS_ERR(smp2p->mbox_chan)) { in qcom_smp2p_probe()
578 if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) in qcom_smp2p_probe()
579 return PTR_ERR(smp2p->mbox_chan); in qcom_smp2p_probe()
581 smp2p->mbox_chan = NULL; in qcom_smp2p_probe()
583 ret = smp2p_parse_ipc(smp2p); in qcom_smp2p_probe()
588 ret = qcom_smp2p_alloc_outbound_item(smp2p); in qcom_smp2p_probe()
599 entry->smp2p = smp2p; in qcom_smp2p_probe()
607 ret = qcom_smp2p_inbound_entry(smp2p, entry, node); in qcom_smp2p_probe()
611 list_add(&entry->node, &smp2p->inbound); in qcom_smp2p_probe()
613 ret = qcom_smp2p_outbound_entry(smp2p, entry, node); in qcom_smp2p_probe()
617 list_add(&entry->node, &smp2p->outbound); in qcom_smp2p_probe()
622 qcom_smp2p_kick(smp2p); in qcom_smp2p_probe()
627 NULL, (void *)smp2p); in qcom_smp2p_probe()
634 * Treat smp2p interrupt as wakeup source, but keep it disabled in qcom_smp2p_probe()
654 list_for_each_entry(entry, &smp2p->inbound, node) in qcom_smp2p_probe()
657 list_for_each_entry(entry, &smp2p->outbound, node) in qcom_smp2p_probe()
660 smp2p->out->valid_entries = 0; in qcom_smp2p_probe()
663 mbox_free_channel(smp2p->mbox_chan); in qcom_smp2p_probe()
674 struct qcom_smp2p *smp2p = platform_get_drvdata(pdev); in qcom_smp2p_remove() local
679 list_for_each_entry(entry, &smp2p->inbound, node) in qcom_smp2p_remove()
682 list_for_each_entry(entry, &smp2p->outbound, node) in qcom_smp2p_remove()
685 mbox_free_channel(smp2p->mbox_chan); in qcom_smp2p_remove()
687 smp2p->out->valid_entries = 0; in qcom_smp2p_remove()
691 { .compatible = "qcom,smp2p" },