* [PATCH v5 0/4] Add Microchip IPC mailbox
@ 2024-12-02 14:11 Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 1/4] riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list Valentina Fernandez
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Valentina Fernandez @ 2024-12-02 14:11 UTC (permalink / raw)
To: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
robh, krzk+dt, valentina.fernandezalanis
Cc: linux-riscv, linux-kernel, devicetree
Hello all,
This series adds support for the Microchip Inter-Processor Communication
(IPC) mailbox driver.
Microchip's family of RISC-V SoCs typically has one or more clusters
that can be configured to run in Asymmetric Multi-Processing (AMP) mode.
The Microchip IPC is used to send messages between processors using
an interrupt signaling mechanism. The driver uses the RISC-V Supervisor
Binary Interface (SBI) to communicate with software running in machine
mode (M-mode) to access the IPC hardware block.
Additional details on the Microchip vendor extension and the IPC
function IDs described in the driver can be found in the following
documentation:
https://github.com/linux4microchip/microchip-sbi-ecall-extension
The PIC64GX MPU has a Mi-V IHC block, this will be added to the PIC64GX
dts after the initial upstreaming [1].
[1] https://patchwork.kernel.org/project/linux-riscv/patch/20240725121609.13101-18-pierre-henry.moussay@microchip.com/
Changes in v5:
- change interrup-names property to use a list instead of pattern
- move assitionalProperties after allOf : block
- update reg property in dt binding example to use lowercase hex
Changes in v4:
- specify that microchip,miv-ihc-rtl-v2 is intended for use with MIV IHC Soft IP
- drop items array and use const value for compatible strings
- add a contraint to microchip,ihc-chan-disabled-mask property
- minor improvements to "'#mbox-cells' description
Changes in v3:
- Fix incorrent formatting around '=' in dt binding examples
- Add per compatible descriptions in dt binding
- Add '>' in certain dt binding descriptions to keep paragraphs maintained
- export __cpuid_to_hartid_map to compile mailbox driver as module
- Drop unused enum ipc_irq_type
- rename struct mchp_ipc_probe to mchp_ipc_mbox_info
- rename struct ipc_chan_info to mchp_ipc_sbi_chan
- rename struct microchip_ipc to mchp_ipc_sbi_mbox
- use phys_addr_t for __pa()
- drop mchp_ipc_get_chan_id function
- use num_chans in mbox_controller
- Fix buf_base_tx and buf_base_rx sizes using max and kmalloc
Changes in v2:
- use kmalloc and __pa() instead of DMA API
- fix size of buf_base to avoid potential buffer overflow
- add kernel doc for exported functions (mchp_ipc_get_chan_id)
- use EXPORT_SYMBOL_GPL instead of EXPORT_SYMBOL
- drop unnecessary blank line and fix alignment issues
- drop of_match_ptr
- move MODULE_DEVICE_TABLE next to the definition
- reword subject from riscv: asm: vendorid_list to riscv: sbi: vendorid_list
- remove the word "driver" from dt-binding commit subject
- make interrupt-names a required property for all cases
- add dependency on COMPILE_TEST and ARCH_MICROCHIP
Regards,
Valentina
Valentina Fernandez (4):
riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list
riscv: export __cpuid_to_hartid_map
dt-bindings: mailbox: add binding for Microchip IPC mailbox controller
mailbox: add Microchip IPC support
.../bindings/mailbox/microchip,sbi-ipc.yaml | 117 ++++
arch/riscv/include/asm/vendorid_list.h | 1 +
arch/riscv/kernel/smp.c | 1 +
drivers/mailbox/Kconfig | 13 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/mailbox-mchp-ipc-sbi.c | 504 ++++++++++++++++++
include/linux/mailbox/mchp-ipc.h | 33 ++
7 files changed, 671 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
create mode 100644 drivers/mailbox/mailbox-mchp-ipc-sbi.c
create mode 100644 include/linux/mailbox/mchp-ipc.h
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v5 1/4] riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list
2024-12-02 14:11 [PATCH v5 0/4] Add Microchip IPC mailbox Valentina Fernandez
@ 2024-12-02 14:11 ` Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 2/4] riscv: export __cpuid_to_hartid_map Valentina Fernandez
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Valentina Fernandez @ 2024-12-02 14:11 UTC (permalink / raw)
To: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
robh, krzk+dt, valentina.fernandezalanis
Cc: linux-riscv, linux-kernel, devicetree
Add Microchip Technology to the RISC-V vendor list.
Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
---
arch/riscv/include/asm/vendorid_list.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h
index 2f2bb0c84f9a..a5150cdf34d8 100644
--- a/arch/riscv/include/asm/vendorid_list.h
+++ b/arch/riscv/include/asm/vendorid_list.h
@@ -6,6 +6,7 @@
#define ASM_VENDOR_LIST_H
#define ANDES_VENDOR_ID 0x31e
+#define MICROCHIP_VENDOR_ID 0x029
#define SIFIVE_VENDOR_ID 0x489
#define THEAD_VENDOR_ID 0x5b7
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v5 2/4] riscv: export __cpuid_to_hartid_map
2024-12-02 14:11 [PATCH v5 0/4] Add Microchip IPC mailbox Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 1/4] riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list Valentina Fernandez
@ 2024-12-02 14:11 ` Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 4/4] mailbox: add Microchip IPC support Valentina Fernandez
3 siblings, 0 replies; 6+ messages in thread
From: Valentina Fernandez @ 2024-12-02 14:11 UTC (permalink / raw)
To: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
robh, krzk+dt, valentina.fernandezalanis
Cc: linux-riscv, linux-kernel, devicetree
EXPORT_SYMBOL_GPL() is missing for __cpuid_to_hartid_map array.
Export this symbol to allow drivers compiled as modules to use
cpuid_to_hartid_map().
Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
---
arch/riscv/kernel/smp.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/riscv/kernel/smp.c b/arch/riscv/kernel/smp.c
index c180a647a30e..d58b5e751286 100644
--- a/arch/riscv/kernel/smp.c
+++ b/arch/riscv/kernel/smp.c
@@ -43,6 +43,7 @@ enum ipi_message_type {
unsigned long __cpuid_to_hartid_map[NR_CPUS] __ro_after_init = {
[0 ... NR_CPUS-1] = INVALID_HARTID
};
+EXPORT_SYMBOL_GPL(__cpuid_to_hartid_map);
void __init smp_setup_processor_id(void)
{
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller
2024-12-02 14:11 [PATCH v5 0/4] Add Microchip IPC mailbox Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 1/4] riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 2/4] riscv: export __cpuid_to_hartid_map Valentina Fernandez
@ 2024-12-02 14:11 ` Valentina Fernandez
2024-12-04 14:52 ` Rob Herring
2024-12-02 14:11 ` [PATCH v5 4/4] mailbox: add Microchip IPC support Valentina Fernandez
3 siblings, 1 reply; 6+ messages in thread
From: Valentina Fernandez @ 2024-12-02 14:11 UTC (permalink / raw)
To: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
robh, krzk+dt, valentina.fernandezalanis
Cc: linux-riscv, linux-kernel, devicetree
Add a dt-binding for the Microchip Inter-Processor Communication (IPC)
mailbox controller.
Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
---
.../bindings/mailbox/microchip,sbi-ipc.yaml | 117 ++++++++++++++++++
1 file changed, 117 insertions(+)
create mode 100644 Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
diff --git a/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml b/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
new file mode 100644
index 000000000000..e104573d45c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/mailbox/microchip,sbi-ipc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Microchip Inter-processor communication (IPC) mailbox controller
+
+maintainers:
+ - Valentina Fernandez <valentina.fernandezalanis@microchip.com>
+
+description:
+ The Microchip Inter-processor Communication (IPC) facilitates
+ message passing between processors using an interrupt signaling
+ mechanism.
+
+properties:
+ compatible:
+ oneOf:
+ - description:
+ Intended for use by software running in supervisor privileged
+ mode (s-mode). This SBI interface is compatible with the Mi-V
+ Inter-hart Communication (IHC) IP.
+ const: microchip,sbi-ipc
+
+ - description:
+ Intended for use by the SBI implementation in machine mode
+ (m-mode), this compatible string is for the MIV_IHC Soft-IP.
+ const: microchip,miv-ihc-rtl-v2
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ minItems: 1
+ maxItems: 5
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 5
+ items:
+ enum:
+ - hart-0
+ - hart-1
+ - hart-2
+ - hart-3
+ - hart-4
+ - hart-5
+
+ "#mbox-cells":
+ description: >
+ For "microchip,sbi-ipc", the cell represents the global "logical"
+ channel IDs. The meaning of channel IDs are platform firmware dependent.
+
+ For "microchip,miv-ihc-rtl-v2", the cell represents the physical
+ channel and does not vary based on the platform firmware.
+ const: 1
+
+ microchip,ihc-chan-disabled-mask:
+ description: >
+ Represents the enable/disable state of the bi-directional IHC
+ channels within the MIV-IHC IP configuration.
+
+ A bit set to '1' indicates that the corresponding channel is disabled,
+ and any read or write operations to that channel will return zero.
+
+ A bit set to '0' indicates that the corresponding channel is enabled
+ and will be accessible through its dedicated address range registers.
+
+ The actual enable/disable state of each channel is determined by the
+ IP block’s configuration.
+ $ref: /schemas/types.yaml#/definitions/uint16
+ maximum: 0x7fff
+ default: 0
+
+required:
+ - compatible
+ - interrupts
+ - interrupt-names
+ - "#mbox-cells"
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: microchip,sbi-ipc
+ then:
+ properties:
+ reg: false
+ microchip,ihc-chan-disabled-mask: false
+ else:
+ required:
+ - reg
+ - microchip,ihc-chan-disabled-mask
+
+additionalProperties: false
+
+examples:
+ - |
+ mailbox {
+ compatible = "microchip,sbi-ipc";
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>;
+ interrupt-names = "hart-1", "hart-2", "hart-3";
+ #mbox-cells = <1>;
+ };
+ - |
+ mailbox@50000000 {
+ compatible = "microchip,miv-ihc-rtl-v2";
+ microchip,ihc-chan-disabled-mask = /bits/ 16 <0>;
+ reg = <0x50000000 0x1c000>;
+ interrupt-parent = <&plic>;
+ interrupts = <180>, <179>, <178>;
+ interrupt-names = "hart-1", "hart-2", "hart-3";
+ #mbox-cells = <1>;
+ };
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH v5 4/4] mailbox: add Microchip IPC support
2024-12-02 14:11 [PATCH v5 0/4] Add Microchip IPC mailbox Valentina Fernandez
` (2 preceding siblings ...)
2024-12-02 14:11 ` [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller Valentina Fernandez
@ 2024-12-02 14:11 ` Valentina Fernandez
3 siblings, 0 replies; 6+ messages in thread
From: Valentina Fernandez @ 2024-12-02 14:11 UTC (permalink / raw)
To: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
robh, krzk+dt, valentina.fernandezalanis
Cc: linux-riscv, linux-kernel, devicetree
Add a mailbox controller driver for the Microchip Inter-processor
Communication (IPC), which is used to send and receive data between
processors.
The driver uses the RISC-V Supervisor Binary Interface (SBI) to
communicate with software running in machine mode (M-mode) to access
the IPC hardware block.
Additional details on the Microchip vendor extension and the IPC
function IDs described in the driver can be found in the following
documentation:
https://github.com/linux4microchip/microchip-sbi-ecall-extension
This SBI interface in this driver is compatible with the Mi-V Inter-hart
Communication (IHC) IP.
Transmitting and receiving data through the mailbox framework is done
through struct mchp_ipc_msg.
Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
---
drivers/mailbox/Kconfig | 13 +
drivers/mailbox/Makefile | 2 +
drivers/mailbox/mailbox-mchp-ipc-sbi.c | 504 +++++++++++++++++++++++++
include/linux/mailbox/mchp-ipc.h | 33 ++
4 files changed, 552 insertions(+)
create mode 100644 drivers/mailbox/mailbox-mchp-ipc-sbi.c
create mode 100644 include/linux/mailbox/mchp-ipc.h
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 8ecba7fb999e..86d324c30cf8 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -178,6 +178,19 @@ config POLARFIRE_SOC_MAILBOX
If unsure, say N.
+config MCHP_SBI_IPC_MBOX
+ tristate "Microchip Inter-processor Communication (IPC) SBI driver"
+ depends on RISCV_SBI || COMPILE_TEST
+ depends on ARCH_MICROCHIP
+ help
+ Mailbox implementation for Microchip devices with an
+ Inter-process communication (IPC) controller.
+
+ To compile this driver as a module, choose M here. the
+ module will be called mailbox-mchp-ipc-sbi.
+
+ If unsure, say N.
+
config QCOM_APCS_IPC
tristate "Qualcomm APCS IPC driver"
depends on ARCH_QCOM || COMPILE_TEST
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 5f4f5b0ce2cc..d52714a4ce3d 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -45,6 +45,8 @@ obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o
obj-$(CONFIG_POLARFIRE_SOC_MAILBOX) += mailbox-mpfs.o
+obj-$(CONFIG_MCHP_SBI_IPC_MBOX) += mailbox-mchp-ipc-sbi.o
+
obj-$(CONFIG_QCOM_APCS_IPC) += qcom-apcs-ipc-mailbox.o
obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
diff --git a/drivers/mailbox/mailbox-mchp-ipc-sbi.c b/drivers/mailbox/mailbox-mchp-ipc-sbi.c
new file mode 100644
index 000000000000..a6e52009a424
--- /dev/null
+++ b/drivers/mailbox/mailbox-mchp-ipc-sbi.c
@@ -0,0 +1,504 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Microchip Inter-Processor communication (IPC) driver
+ *
+ * Copyright (c) 2021 - 2024 Microchip Technology Inc. All rights reserved.
+ *
+ * Author: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/mailbox/mchp-ipc.h>
+#include <asm/sbi.h>
+#include <asm/vendorid_list.h>
+
+#define IRQ_STATUS_BITS 12
+#define NUM_CHANS_PER_CLUSTER 5
+#define IPC_DMA_BIT_MASK 32
+#define SBI_EXT_MICROCHIP_TECHNOLOGY (SBI_EXT_VENDOR_START | \
+ MICROCHIP_VENDOR_ID)
+
+enum {
+ SBI_EXT_IPC_PROBE = 0x100,
+ SBI_EXT_IPC_CH_INIT,
+ SBI_EXT_IPC_SEND,
+ SBI_EXT_IPC_RECEIVE,
+ SBI_EXT_IPC_STATUS,
+};
+
+enum ipc_hw {
+ MIV_IHC,
+};
+
+/**
+ * struct mchp_ipc_mbox_info - IPC probe message format
+ *
+ * @hw_type: IPC implementation available in the hardware
+ * @num_channels: number of IPC channels available in the hardware
+ *
+ * Used to retrieve information on the IPC implementation
+ * using the SBI_EXT_IPC_PROBE SBI function id.
+ */
+struct mchp_ipc_mbox_info {
+ enum ipc_hw hw_type;
+ u8 num_channels;
+};
+
+/**
+ * struct mchp_ipc_init - IPC channel init message format
+ *
+ * @max_msg_size: maxmimum message size in bytes of a given channel
+ *
+ * struct used by the SBI_EXT_IPC_CH_INIT SBI function id to get
+ * the max message size in bytes of the initialized channel.
+ */
+struct mchp_ipc_init {
+ u16 max_msg_size;
+};
+
+/**
+ * struct mchp_ipc_status - IPC status message format
+ *
+ * @status: interrupt status for all channels associated to a cluster
+ * @cluster: specifies the cluster instance that originated an irq
+ *
+ * struct used by the SBI_EXT_IPC_STATUS SBI function id to get
+ * the message present and message clear interrupt status for all the
+ * channels associated to a cluster.
+ */
+struct mchp_ipc_status {
+ u32 status;
+ u8 cluster;
+};
+
+/**
+ * struct mchp_ipc_sbi_msg - IPC SBI payload message
+ *
+ * @buf_addr: physical address where the received data should be copied to
+ * @size: maximum size(in bytes) that can be stored in the buffer pointed to by `buf`
+ * @irq_type: mask representing the irq types that triggered an irq
+ *
+ * struct used by the SBI_EXT_IPC_SEND/SBI_EXT_IPC_RECEIVE SBI function
+ * ids to send/receive a message from an associated processor using
+ * the IPC.
+ */
+struct mchp_ipc_sbi_msg {
+ u64 buf_addr;
+ u16 size;
+ u8 irq_type;
+};
+
+struct mchp_ipc_cluster_cfg {
+ void *buf_base;
+ phys_addr_t buf_base_addr;
+ int irq;
+};
+
+struct mchp_ipc_sbi_mbox {
+ struct device *dev;
+ struct mbox_chan *chans;
+ struct mchp_ipc_cluster_cfg *cluster_cfg;
+ void *buf_base;
+ unsigned long buf_base_addr;
+ struct mbox_controller controller;
+ enum ipc_hw hw_type;
+};
+
+static int mchp_ipc_sbi_chan_send(u32 command, u32 channel, unsigned long address)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_MICROCHIP_TECHNOLOGY, command, channel,
+ address, 0, 0, 0, 0);
+
+ if (ret.error)
+ return sbi_err_map_linux_errno(ret.error);
+ else
+ return ret.value;
+}
+
+static int mchp_ipc_sbi_send(u32 command, unsigned long address)
+{
+ struct sbiret ret;
+
+ ret = sbi_ecall(SBI_EXT_MICROCHIP_TECHNOLOGY, command, address,
+ 0, 0, 0, 0, 0);
+
+ if (ret.error)
+ return sbi_err_map_linux_errno(ret.error);
+ else
+ return ret.value;
+}
+
+static struct mchp_ipc_sbi_mbox *to_mchp_ipc_mbox(struct mbox_controller *mbox)
+{
+ return container_of(mbox, struct mchp_ipc_sbi_mbox, controller);
+}
+
+static inline void mchp_ipc_prepare_receive_req(struct mbox_chan *chan)
+{
+ struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+ struct mchp_ipc_sbi_msg request;
+
+ request.buf_addr = chan_info->msg_buf_rx_addr;
+ request.size = chan_info->max_msg_size;
+ memcpy(chan_info->buf_base_rx, &request, sizeof(struct mchp_ipc_sbi_msg));
+}
+
+static inline void mchp_ipc_process_received_data(struct mbox_chan *chan,
+ struct mchp_ipc_msg *ipc_msg)
+{
+ struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+ struct mchp_ipc_sbi_msg sbi_msg;
+
+ memcpy(&sbi_msg, chan_info->buf_base_rx, sizeof(struct mchp_ipc_sbi_msg));
+ ipc_msg->buf = (u32 *)chan_info->msg_buf_rx;
+ ipc_msg->size = sbi_msg.size;
+}
+
+static irqreturn_t mchp_ipc_cluster_aggr_isr(int irq, void *data)
+{
+ struct mbox_chan *chan;
+ struct mchp_ipc_sbi_chan *chan_info;
+ struct mchp_ipc_sbi_mbox *ipc = (struct mchp_ipc_sbi_mbox *)data;
+ struct mchp_ipc_msg ipc_msg;
+ struct mchp_ipc_status status_msg;
+ int ret;
+ unsigned long hartid;
+ u32 i, chan_index, chan_id;
+
+ /* Find out the hart that originated the irq */
+ for_each_online_cpu(i) {
+ hartid = cpuid_to_hartid_map(i);
+ if (irq == ipc->cluster_cfg[hartid].irq)
+ break;
+ }
+
+ status_msg.cluster = hartid;
+ memcpy(ipc->cluster_cfg[hartid].buf_base, &status_msg, sizeof(struct mchp_ipc_status));
+
+ ret = mchp_ipc_sbi_send(SBI_EXT_IPC_STATUS, ipc->cluster_cfg[hartid].buf_base_addr);
+ if (ret < 0) {
+ dev_err_ratelimited(ipc->dev, "could not get IHC irq status ret=%d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ memcpy(&status_msg, ipc->cluster_cfg[hartid].buf_base, sizeof(struct mchp_ipc_status));
+
+ /*
+ * Iterate over each bit set in the IHC interrupt status register (IRQ_STATUS) to identify
+ * the channel(s) that have a message to be processed/acknowledged.
+ * The bits are organized in alternating format, where each pair of bits represents
+ * the status of the message present and message clear interrupts for each cluster/hart
+ * (from hart 0 to hart 5). Each cluster can have up to 5 fixed channels associated.
+ */
+
+ for_each_set_bit(i, (unsigned long *)&status_msg.status, IRQ_STATUS_BITS) {
+ /* Find out the destination hart that triggered the interrupt */
+ chan_index = i / 2;
+
+ /*
+ * The IP has no loopback channels, so we need to decrement the index when
+ * the target hart has a greater index than our own
+ */
+ if (chan_index >= status_msg.cluster)
+ chan_index--;
+
+ /*
+ * Calculate the channel id given the hart and channel index. Channel IDs
+ * are unique across all clusters of an IPC, and iterate contiguously
+ * across all clusters.
+ */
+ chan_id = status_msg.cluster * (NUM_CHANS_PER_CLUSTER + chan_index);
+
+ chan = &ipc->chans[chan_id];
+ chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+
+ if (i % 2 == 0) {
+ mchp_ipc_prepare_receive_req(chan);
+ ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_RECEIVE, chan_id,
+ chan_info->buf_base_rx_addr);
+ if (ret < 0)
+ continue;
+
+ mchp_ipc_process_received_data(chan, &ipc_msg);
+ mbox_chan_received_data(&ipc->chans[chan_id], (void *)&ipc_msg);
+
+ } else {
+ ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_RECEIVE, chan_id,
+ chan_info->buf_base_rx_addr);
+ mbox_chan_txdone(&ipc->chans[chan_id], ret);
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static int mchp_ipc_send_data(struct mbox_chan *chan, void *data)
+{
+ struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+ const struct mchp_ipc_msg *msg = data;
+ struct mchp_ipc_sbi_msg sbi_payload;
+
+ memcpy(chan_info->msg_buf_tx, msg->buf, msg->size);
+ sbi_payload.buf_addr = chan_info->msg_buf_tx_addr;
+ sbi_payload.size = msg->size;
+ memcpy(chan_info->buf_base_tx, &sbi_payload, sizeof(sbi_payload));
+
+ return mchp_ipc_sbi_chan_send(SBI_EXT_IPC_SEND, chan_info->id, chan_info->buf_base_tx_addr);
+}
+
+static int mchp_ipc_startup(struct mbox_chan *chan)
+{
+ struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+ struct mchp_ipc_sbi_mbox *ipc = to_mchp_ipc_mbox(chan->mbox);
+ struct mchp_ipc_init ch_init_msg;
+ int ret;
+
+ /*
+ * The TX base buffer is used to transmit two types of messages:
+ * - struct mchp_ipc_init to initialize the channel
+ * - struct mchp_ipc_sbi_msg to transmit user data/payload
+ * Ensure the TX buffer size is large enough to accommodate either message type.
+ */
+ size_t max_size = max(sizeof(struct mchp_ipc_init), sizeof(struct mchp_ipc_sbi_msg));
+
+ chan_info->buf_base_tx = kmalloc(max_size, GFP_KERNEL);
+ if (!chan_info->buf_base_tx) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ chan_info->buf_base_tx_addr = __pa(chan_info->buf_base_tx);
+
+ chan_info->buf_base_rx = kmalloc(max_size, GFP_KERNEL);
+ if (!chan_info->buf_base_rx) {
+ ret = -ENOMEM;
+ goto fail_free_buf_base_tx;
+ }
+
+ chan_info->buf_base_rx_addr = __pa(chan_info->buf_base_rx);
+
+ ret = mchp_ipc_sbi_chan_send(SBI_EXT_IPC_CH_INIT, chan_info->id,
+ chan_info->buf_base_tx_addr);
+ if (ret < 0) {
+ dev_err(ipc->dev, "channel %u init failed\n", chan_info->id);
+ goto fail_free_buf_base_rx;
+ }
+
+ memcpy(&ch_init_msg, chan_info->buf_base_tx, sizeof(struct mchp_ipc_init));
+ chan_info->max_msg_size = ch_init_msg.max_msg_size;
+
+ chan_info->msg_buf_tx = kmalloc(chan_info->max_msg_size, GFP_KERNEL);
+ if (!chan_info->msg_buf_tx) {
+ ret = -ENOMEM;
+ goto fail_free_buf_base_rx;
+ }
+
+ chan_info->msg_buf_tx_addr = __pa(chan_info->msg_buf_tx);
+
+ chan_info->msg_buf_rx = kmalloc(chan_info->max_msg_size, GFP_KERNEL);
+ if (!chan_info->msg_buf_rx) {
+ ret = -ENOMEM;
+ goto fail_free_buf_msg_tx;
+ }
+
+ chan_info->msg_buf_rx_addr = __pa(chan_info->msg_buf_rx);
+
+ switch (ipc->hw_type) {
+ case MIV_IHC:
+ return 0;
+ default:
+ goto fail_free_buf_msg_rx;
+ }
+
+ if (ret) {
+ dev_err(ipc->dev, "failed to register interrupt(s)\n");
+ goto fail_free_buf_msg_rx;
+ }
+
+ return ret;
+
+fail_free_buf_msg_rx:
+ kfree(chan_info->msg_buf_rx);
+fail_free_buf_msg_tx:
+ kfree(chan_info->msg_buf_tx);
+fail_free_buf_base_rx:
+ kfree(chan_info->buf_base_rx);
+fail_free_buf_base_tx:
+ kfree(chan_info->buf_base_tx);
+fail:
+ return ret;
+}
+
+static void mchp_ipc_shutdown(struct mbox_chan *chan)
+{
+ struct mchp_ipc_sbi_chan *chan_info = (struct mchp_ipc_sbi_chan *)chan->con_priv;
+
+ kfree(chan_info->buf_base_tx);
+ kfree(chan_info->buf_base_rx);
+ kfree(chan_info->msg_buf_tx);
+ kfree(chan_info->msg_buf_rx);
+}
+
+static const struct mbox_chan_ops mchp_ipc_ops = {
+ .startup = mchp_ipc_startup,
+ .send_data = mchp_ipc_send_data,
+ .shutdown = mchp_ipc_shutdown,
+};
+
+static struct mbox_chan *mchp_ipc_mbox_xlate(struct mbox_controller *controller,
+ const struct of_phandle_args *spec)
+{
+ struct mchp_ipc_sbi_mbox *ipc = to_mchp_ipc_mbox(controller);
+ unsigned int chan_id = spec->args[0];
+
+ if (chan_id >= ipc->controller.num_chans) {
+ dev_err(ipc->dev, "invalid channel id %d\n", chan_id);
+ return ERR_PTR(-EINVAL);
+ }
+
+ return &ipc->chans[chan_id];
+}
+
+static int mchp_ipc_get_cluster_aggr_irq(struct mchp_ipc_sbi_mbox *ipc)
+{
+ struct platform_device *pdev = to_platform_device(ipc->dev);
+ char *irq_name;
+ int cpuid, ret;
+ unsigned long hartid;
+ bool irq_found = false;
+
+ for_each_online_cpu(cpuid) {
+ hartid = cpuid_to_hartid_map(cpuid);
+ irq_name = devm_kasprintf(ipc->dev, GFP_KERNEL, "hart-%lu", hartid);
+ ret = platform_get_irq_byname_optional(pdev, irq_name);
+ if (ret <= 0)
+ continue;
+
+ ipc->cluster_cfg[hartid].irq = ret;
+ ret = devm_request_irq(ipc->dev, ipc->cluster_cfg[hartid].irq,
+ mchp_ipc_cluster_aggr_isr, IRQF_SHARED,
+ "miv-ihc-irq", ipc);
+ if (ret)
+ return ret;
+
+ ipc->cluster_cfg[hartid].buf_base = devm_kmalloc(ipc->dev,
+ sizeof(struct mchp_ipc_status),
+ GFP_KERNEL);
+
+ if (!ipc->cluster_cfg[hartid].buf_base)
+ return -ENOMEM;
+
+ ipc->cluster_cfg[hartid].buf_base_addr = __pa(ipc->cluster_cfg[hartid].buf_base);
+
+ irq_found = true;
+ }
+
+ return irq_found;
+}
+
+static int mchp_ipc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct mchp_ipc_mbox_info ipc_info;
+ struct mchp_ipc_sbi_mbox *ipc;
+ struct mchp_ipc_sbi_chan *priv;
+ bool irq_avail = false;
+ int ret;
+ u32 chan_id;
+
+ ret = sbi_probe_extension(SBI_EXT_MICROCHIP_TECHNOLOGY);
+ if (ret <= 0)
+ return dev_err_probe(dev, ret, "Microchip SBI extension not detected\n");
+
+ ipc = devm_kzalloc(dev, sizeof(*ipc), GFP_KERNEL);
+ if (!ipc)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ipc);
+
+ ipc->buf_base = devm_kmalloc(dev, sizeof(struct mchp_ipc_mbox_info), GFP_KERNEL);
+ if (!ipc->buf_base)
+ return -ENOMEM;
+
+ ipc->buf_base_addr = __pa(ipc->buf_base);
+
+ ret = mchp_ipc_sbi_send(SBI_EXT_IPC_PROBE, ipc->buf_base_addr);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "could not probe IPC SBI service\n");
+
+ memcpy(&ipc_info, ipc->buf_base, sizeof(struct mchp_ipc_mbox_info));
+ ipc->controller.num_chans = ipc_info.num_channels;
+ ipc->hw_type = ipc_info.hw_type;
+
+ ipc->chans = devm_kcalloc(dev, ipc->controller.num_chans, sizeof(*ipc->chans), GFP_KERNEL);
+ if (!ipc->chans)
+ return -ENOMEM;
+
+ ipc->dev = dev;
+ ipc->controller.txdone_irq = true;
+ ipc->controller.dev = ipc->dev;
+ ipc->controller.ops = &mchp_ipc_ops;
+ ipc->controller.chans = ipc->chans;
+ ipc->controller.of_xlate = mchp_ipc_mbox_xlate;
+
+ for (chan_id = 0; chan_id < ipc->controller.num_chans; chan_id++) {
+ priv = devm_kmalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ ipc->chans[chan_id].con_priv = priv;
+ priv->id = chan_id;
+ }
+
+ if (ipc->hw_type == MIV_IHC) {
+ ipc->cluster_cfg = devm_kcalloc(dev, num_online_cpus(),
+ sizeof(struct mchp_ipc_cluster_cfg),
+ GFP_KERNEL);
+ if (!ipc->cluster_cfg)
+ return -ENOMEM;
+
+ if (mchp_ipc_get_cluster_aggr_irq(ipc))
+ irq_avail = true;
+ }
+
+ if (!irq_avail)
+ return dev_err_probe(dev, -ENODEV, "missing interrupt property\n");
+
+ ret = devm_mbox_controller_register(dev, &ipc->controller);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Inter-Processor communication (IPC) registration failed\n");
+
+ return 0;
+}
+
+static const struct of_device_id mchp_ipc_of_match[] = {
+ {.compatible = "microchip,sbi-ipc", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mchp_ipc_of_match);
+
+static struct platform_driver mchp_ipc_driver = {
+ .driver = {
+ .name = "microchip_ipc",
+ .of_match_table = mchp_ipc_of_match,
+ },
+ .probe = mchp_ipc_probe,
+};
+
+module_platform_driver(mchp_ipc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Valentina Fernandez <valentina.fernandezalanis@microchip.com>");
+MODULE_DESCRIPTION("Microchip Inter-Processor Communication (IPC) driver");
diff --git a/include/linux/mailbox/mchp-ipc.h b/include/linux/mailbox/mchp-ipc.h
new file mode 100644
index 000000000000..f084ac9e291b
--- /dev/null
+++ b/include/linux/mailbox/mchp-ipc.h
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *Copyright (c) 2024 Microchip Technology Inc. All rights reserved.
+ */
+
+#ifndef _LINUX_MCHP_IPC_H_
+#define _LINUX_MCHP_IPC_H_
+
+#include <linux/mailbox_controller.h>
+#include <linux/types.h>
+
+struct mchp_ipc_msg {
+ u32 *buf;
+ u16 size;
+};
+
+struct mchp_ipc_sbi_chan {
+ void *buf_base_tx;
+ void *buf_base_rx;
+ void *msg_buf_tx;
+ void *msg_buf_rx;
+ phys_addr_t buf_base_tx_addr;
+ phys_addr_t buf_base_rx_addr;
+ phys_addr_t msg_buf_tx_addr;
+ phys_addr_t msg_buf_rx_addr;
+ int chan_aggregated_irq;
+ int mp_irq;
+ int mc_irq;
+ u32 id;
+ u32 max_msg_size;
+};
+
+#endif /* _LINUX_MCHP_IPC_H_ */
--
2.34.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller
2024-12-02 14:11 ` [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller Valentina Fernandez
@ 2024-12-04 14:52 ` Rob Herring
0 siblings, 0 replies; 6+ messages in thread
From: Rob Herring @ 2024-12-04 14:52 UTC (permalink / raw)
To: Valentina Fernandez
Cc: paul.walmsley, palmer, conor.dooley, conor+dt, jassisinghbrar,
krzk+dt, linux-riscv, linux-kernel, devicetree
On Mon, Dec 02, 2024 at 02:11:06PM +0000, Valentina Fernandez wrote:
> Add a dt-binding for the Microchip Inter-Processor Communication (IPC)
> mailbox controller.
>
> Signed-off-by: Valentina Fernandez <valentina.fernandezalanis@microchip.com>
> ---
> .../bindings/mailbox/microchip,sbi-ipc.yaml | 117 ++++++++++++++++++
> 1 file changed, 117 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
>
> diff --git a/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml b/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
> new file mode 100644
> index 000000000000..e104573d45c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/microchip,sbi-ipc.yaml
> @@ -0,0 +1,117 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/mailbox/microchip,sbi-ipc.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Microchip Inter-processor communication (IPC) mailbox controller
> +
> +maintainers:
> + - Valentina Fernandez <valentina.fernandezalanis@microchip.com>
> +
> +description:
> + The Microchip Inter-processor Communication (IPC) facilitates
> + message passing between processors using an interrupt signaling
> + mechanism.
> +
> +properties:
> + compatible:
> + oneOf:
> + - description:
> + Intended for use by software running in supervisor privileged
> + mode (s-mode). This SBI interface is compatible with the Mi-V
> + Inter-hart Communication (IHC) IP.
> + const: microchip,sbi-ipc
> +
> + - description:
> + Intended for use by the SBI implementation in machine mode
> + (m-mode), this compatible string is for the MIV_IHC Soft-IP.
> + const: microchip,miv-ihc-rtl-v2
> +
> + reg:
> + maxItems: 1
> +
> + interrupts:
> + minItems: 1
> + maxItems: 5
> +
> + interrupt-names:
> + minItems: 1
> + maxItems: 5
> + items:
> + enum:
> + - hart-0
> + - hart-1
> + - hart-2
> + - hart-3
> + - hart-4
> + - hart-5
I don't know why Krzysztof said to list them, when all you needed to do
was drop the '+':
pattern: "^hart-[0-5]$"
> +
> + "#mbox-cells":
> + description: >
> + For "microchip,sbi-ipc", the cell represents the global "logical"
> + channel IDs. The meaning of channel IDs are platform firmware dependent.
> +
> + For "microchip,miv-ihc-rtl-v2", the cell represents the physical
> + channel and does not vary based on the platform firmware.
> + const: 1
> +
> + microchip,ihc-chan-disabled-mask:
> + description: >
> + Represents the enable/disable state of the bi-directional IHC
> + channels within the MIV-IHC IP configuration.
> +
> + A bit set to '1' indicates that the corresponding channel is disabled,
> + and any read or write operations to that channel will return zero.
> +
> + A bit set to '0' indicates that the corresponding channel is enabled
> + and will be accessible through its dedicated address range registers.
> +
> + The actual enable/disable state of each channel is determined by the
> + IP block’s configuration.
> + $ref: /schemas/types.yaml#/definitions/uint16
> + maximum: 0x7fff
> + default: 0
> +
> +required:
> + - compatible
> + - interrupts
> + - interrupt-names
> + - "#mbox-cells"
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + const: microchip,sbi-ipc
> + then:
> + properties:
> + reg: false
How do you address the question about this? Add an explanation in the
schema. No one is going to remember an answer in a review thread. IOW,
assume that we don't remember the answer and will just ask the same
questions again.
You can do something like:
reg:
not:
description: ...
or
reg:
not: {}
description: ...
Rob
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-12-04 14:52 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-02 14:11 [PATCH v5 0/4] Add Microchip IPC mailbox Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 1/4] riscv: sbi: vendorid_list: Add Microchip Technology to the vendor list Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 2/4] riscv: export __cpuid_to_hartid_map Valentina Fernandez
2024-12-02 14:11 ` [PATCH v5 3/4] dt-bindings: mailbox: add binding for Microchip IPC mailbox controller Valentina Fernandez
2024-12-04 14:52 ` Rob Herring
2024-12-02 14:11 ` [PATCH v5 4/4] mailbox: add Microchip IPC support Valentina Fernandez
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).