Loading Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt +7 −1 Original line number Diff line number Diff line Loading @@ -17,9 +17,15 @@ processor ID) and a string identifier. Value type: <prop-encoded-array> Definition: one entry specifying the smp2p notification interrupt - qcom,ipc: - mboxes: Usage: required Value type: <prop-encoded-array> Definition: reference to the associated doorbell in APCS, as described in mailbox/mailbox.txt - qcom,ipc: Usage: required, unless mboxes is specified Value type: <prop-encoded-array> Definition: three entries specifying the outgoing ipc bit used for signaling the remote end of the smp2p edge: - phandle to a syscon node representing the apcs registers Loading drivers/soc/qcom/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ config QCOM_SMEM_STATE config QCOM_SMP2P tristate "Qualcomm Shared Memory Point to Point support" depends on MAILBOX depends on QCOM_SMEM select QCOM_SMEM_STATE help Loading drivers/soc/qcom/smp2p.c +33 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/of.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/mailbox_client.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/platform_device.h> Loading Loading @@ -133,6 +134,8 @@ struct smp2p_entry { * @ipc_regmap: regmap for the outbound ipc * @ipc_offset: offset within the regmap * @ipc_bit: bit in regmap@offset to kick to signal remote processor * @mbox_client: mailbox client handle * @mbox_chan: apcs ipc mailbox channel handle * @inbound: list of inbound entries * @outbound: list of outbound entries */ Loading @@ -158,6 +161,9 @@ struct qcom_smp2p { int ipc_offset; int ipc_bit; struct mbox_client mbox_client; struct mbox_chan *mbox_chan; struct list_head inbound; struct list_head outbound; }; Loading @@ -174,8 +180,14 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) { /* Make sure any updated data is written before the kick */ wmb(); if (smp2p->mbox_chan) { mbox_send_message(smp2p->mbox_chan, NULL); mbox_client_txdone(smp2p->mbox_chan, 0); } else { regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); } } static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) { Loading Loading @@ -555,10 +567,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev) platform_set_drvdata(pdev, smp2p); ret = smp2p_parse_ipc(smp2p); if (ret) return ret; key = "qcom,smem"; ret = of_property_read_u32_array(pdev->dev.of_node, key, smp2p->smem_items, 2); Loading @@ -585,9 +593,23 @@ static int qcom_smp2p_probe(struct platform_device *pdev) return smp2p->irq; } smp2p->mbox_client.dev = &pdev->dev; smp2p->mbox_client.knows_txdone = true; smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); if (IS_ERR(smp2p->mbox_chan)) { if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) return PTR_ERR(smp2p->mbox_chan); smp2p->mbox_chan = NULL; ret = smp2p_parse_ipc(smp2p); if (ret) return ret; } ret = qcom_smp2p_alloc_outbound_item(smp2p); if (ret < 0) return ret; goto release_mbox; for_each_available_child_of_node(pdev->dev.of_node, node) { entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL); Loading Loading @@ -642,6 +664,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev) smp2p->out->valid_entries = 0; release_mbox: mbox_free_channel(smp2p->mbox_chan); return ret; } Loading @@ -656,6 +681,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev) list_for_each_entry(entry, &smp2p->outbound, node) qcom_smem_state_unregister(entry->state); mbox_free_channel(smp2p->mbox_chan); smp2p->out->valid_entries = 0; return 0; Loading Loading
Documentation/devicetree/bindings/soc/qcom/qcom,smp2p.txt +7 −1 Original line number Diff line number Diff line Loading @@ -17,9 +17,15 @@ processor ID) and a string identifier. Value type: <prop-encoded-array> Definition: one entry specifying the smp2p notification interrupt - qcom,ipc: - mboxes: Usage: required Value type: <prop-encoded-array> Definition: reference to the associated doorbell in APCS, as described in mailbox/mailbox.txt - qcom,ipc: Usage: required, unless mboxes is specified Value type: <prop-encoded-array> Definition: three entries specifying the outgoing ipc bit used for signaling the remote end of the smp2p edge: - phandle to a syscon node representing the apcs registers Loading
drivers/soc/qcom/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -277,6 +277,7 @@ config QCOM_SMEM_STATE config QCOM_SMP2P tristate "Qualcomm Shared Memory Point to Point support" depends on MAILBOX depends on QCOM_SMEM select QCOM_SMEM_STATE help Loading
drivers/soc/qcom/smp2p.c +33 −6 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/of.h> #include <linux/irq.h> #include <linux/irqdomain.h> #include <linux/mailbox_client.h> #include <linux/mfd/syscon.h> #include <linux/module.h> #include <linux/platform_device.h> Loading Loading @@ -133,6 +134,8 @@ struct smp2p_entry { * @ipc_regmap: regmap for the outbound ipc * @ipc_offset: offset within the regmap * @ipc_bit: bit in regmap@offset to kick to signal remote processor * @mbox_client: mailbox client handle * @mbox_chan: apcs ipc mailbox channel handle * @inbound: list of inbound entries * @outbound: list of outbound entries */ Loading @@ -158,6 +161,9 @@ struct qcom_smp2p { int ipc_offset; int ipc_bit; struct mbox_client mbox_client; struct mbox_chan *mbox_chan; struct list_head inbound; struct list_head outbound; }; Loading @@ -174,8 +180,14 @@ static void qcom_smp2p_kick(struct qcom_smp2p *smp2p) { /* Make sure any updated data is written before the kick */ wmb(); if (smp2p->mbox_chan) { mbox_send_message(smp2p->mbox_chan, NULL); mbox_client_txdone(smp2p->mbox_chan, 0); } else { regmap_write(smp2p->ipc_regmap, smp2p->ipc_offset, BIT(smp2p->ipc_bit)); } } static bool qcom_smp2p_check_ssr(struct qcom_smp2p *smp2p) { Loading Loading @@ -555,10 +567,6 @@ static int qcom_smp2p_probe(struct platform_device *pdev) platform_set_drvdata(pdev, smp2p); ret = smp2p_parse_ipc(smp2p); if (ret) return ret; key = "qcom,smem"; ret = of_property_read_u32_array(pdev->dev.of_node, key, smp2p->smem_items, 2); Loading @@ -585,9 +593,23 @@ static int qcom_smp2p_probe(struct platform_device *pdev) return smp2p->irq; } smp2p->mbox_client.dev = &pdev->dev; smp2p->mbox_client.knows_txdone = true; smp2p->mbox_chan = mbox_request_channel(&smp2p->mbox_client, 0); if (IS_ERR(smp2p->mbox_chan)) { if (PTR_ERR(smp2p->mbox_chan) != -ENODEV) return PTR_ERR(smp2p->mbox_chan); smp2p->mbox_chan = NULL; ret = smp2p_parse_ipc(smp2p); if (ret) return ret; } ret = qcom_smp2p_alloc_outbound_item(smp2p); if (ret < 0) return ret; goto release_mbox; for_each_available_child_of_node(pdev->dev.of_node, node) { entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL); Loading Loading @@ -642,6 +664,9 @@ static int qcom_smp2p_probe(struct platform_device *pdev) smp2p->out->valid_entries = 0; release_mbox: mbox_free_channel(smp2p->mbox_chan); return ret; } Loading @@ -656,6 +681,8 @@ static int qcom_smp2p_remove(struct platform_device *pdev) list_for_each_entry(entry, &smp2p->outbound, node) qcom_smem_state_unregister(entry->state); mbox_free_channel(smp2p->mbox_chan); smp2p->out->valid_entries = 0; return 0; Loading