On 2020-10-06 07:54, Loic Poulain wrote:
> This is a generic MHI-over-PCI controller driver for MHI only devices
> such as QCOM modems. For now it supports registering of Qualcomm SDX55
For now, it supports registration of...
> based PCIe modules. The MHI channels have been extracted from mhi
MHI (in all caps) or just use "the" instead
> downstream driver.
>
> This driver is for MHI-only devices which have all functionnalities
functionalities
> exposed through MHI channels and accessed by the corresponding MHI
> device drivers (no out-of-band communication).
>
> Signed-off-by: Loic Poulain <loic.poulain@xxxxxxxxxx>
> ---
> v2: - remove useless delay.h include
> - remove over-logging on error
> - remove controller subdir
> - rename to mhi_pci_modem.c
> - Fix mhi_pci_probe exit path on error
> - expand module description
> - drop module version
> v3: - Rename to mhi_pci_generic
> - Add hardware accelerated IP channel (IPA)
> - Added fw/edl names for sdx55m
>
> drivers/bus/mhi/Kconfig | 9 ++
> drivers/bus/mhi/Makefile | 3 +
> drivers/bus/mhi/mhi_pci_generic.c | 332
> ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 344 insertions(+)
> create mode 100644 drivers/bus/mhi/mhi_pci_generic.c
>
> diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig
> index e841c10..daa8528 100644
> --- a/drivers/bus/mhi/Kconfig
> +++ b/drivers/bus/mhi/Kconfig
> @@ -20,3 +20,12 @@ config MHI_BUS_DEBUG
> Enable debugfs support for use with the MHI transport. Allows
> reading and/or modifying some values within the MHI controller
> for debug and test purposes.
> +
> +config MHI_BUS_PCI_GENERIC
> + tristate "MHI PCI controller driver"
> + depends on MHI_BUS
> + depends on PCI
> + help
> + This driver provides Modem Host Interface (MHI) PCI controller
> driver
> + for devices such as Qualcomm SDX55 based PCIe modems.
> +
> diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile
> index 19e6443..d1a4ef3 100644
> --- a/drivers/bus/mhi/Makefile
> +++ b/drivers/bus/mhi/Makefile
> @@ -1,2 +1,5 @@
> # core layer
> obj-y += core/
> +
> +obj-$(CONFIG_MHI_BUS_PCI_GENERIC) := mhi_pci_generic.o
> +
> diff --git a/drivers/bus/mhi/mhi_pci_generic.c
> b/drivers/bus/mhi/mhi_pci_generic.c
> new file mode 100644
> index 0000000..03fcf76
> --- /dev/null
> +++ b/drivers/bus/mhi/mhi_pci_generic.c
> @@ -0,0 +1,332 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later
> +/*
> + * MHI PCI driver - MHI over PCI controller driver
> + *
> + * This module is a generic driver for registering MHI-over-PCI
> devices,
> + * such as PCIe QCOM modems.
> + *
> + * Copyright (C) 2020 Linaro Ltd <loic.poulain@xxxxxxxxxx>
> + */
> +
> +#include <linux/device.h>
> +#include <linux/mhi.h>
> +#include <linux/module.h>
> +#include <linux/pci.h>
> +
> +#define MHI_PCI_BAR_NUM 0
> +
> +struct mhi_pci_dev_info {
> + const struct mhi_controller_config *config;
> + const char *name;
> + const char *fw;
> + const char *edl;
> +};
> +
> +#define MHI_CHANNEL_CONFIG_TX(cnum, cname, elems, event) \
> + { \
> + .num = cnum, \
> + .name = cname, \
> + .num_elements = elems, \
> + .event_ring = event, \
> + .dir = DMA_TO_DEVICE, \
> + .ee_mask = BIT(MHI_EE_AMSS), \
> + .pollcfg = 0, \
> + .doorbell = MHI_DB_BRST_DISABLE, \
> + .lpm_notify = false, \
> + .offload_channel = false, \
> + .doorbell_mode_switch = false, \
> + } \
> +
> +#define MHI_CHANNEL_CONFIG_RX(cnum, cname, elems, event) \
> + { \
> + .num = cnum, \
> + .name = cname, \
> + .num_elements = elems, \
> + .event_ring = event, \
> + .dir = DMA_FROM_DEVICE, \
> + .ee_mask = BIT(MHI_EE_AMSS), \
> + .pollcfg = 0, \
> + .doorbell = MHI_DB_BRST_DISABLE, \
> + .lpm_notify = false, \
> + .offload_channel = false, \
> + .doorbell_mode_switch = false, \
> + }
> +
> +#define MHI_EVENT_CONFIG_CTRL(enum) \
> + { \
> + .num_elements = 64, \
> + .irq_moderation_ms = 5, \
> + .irq = enum, \
> + .priority = 1, \
> + .mode = MHI_DB_BRST_DISABLE, \
> + .data_type = MHI_ER_CTRL, \
> + .hardware_event = false, \
> + .client_managed = false, \
> + .offload_channel = false, \
> + }
> +
> +#define MHI_EVENT_CONFIG_DATA(enum) \
> + { \
> + .num_elements = 64, \
> + .irq_moderation_ms = 5, \
> + .irq = enum, \
> + .priority = 1, \
> + .mode = MHI_DB_BRST_DISABLE, \
> + .data_type = MHI_ER_DATA, \
> + .hardware_event = false, \
> + .client_managed = false, \
> + .offload_channel = false, \
> + }
> +
> +#define MHI_EVENT_CONFIG_HW_DATA(enum, cnum) \
> + { \
> + .num_elements = 64, \
> + .irq_moderation_ms = 5, \
> + .irq = enum, \
> + .priority = 1, \
> + .mode = MHI_DB_BRST_ENABLE, \
> + .data_type = MHI_ER_DATA, \
> + .hardware_event = true, \
> + .client_managed = false, \
> + .offload_channel = false, \
> + .channel = cnum, \
> + }
> +
> +static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] =
> {
> + MHI_CHANNEL_CONFIG_TX(12, "MBIM", 4, 0),
> + MHI_CHANNEL_CONFIG_RX(13, "MBIM", 4, 0),
> + MHI_CHANNEL_CONFIG_TX(14, "QMI", 4, 0),
> + MHI_CHANNEL_CONFIG_RX(15, "QMI", 4, 0),
> + MHI_CHANNEL_CONFIG_TX(20, "IPCR", 4, 0),
> + MHI_CHANNEL_CONFIG_RX(21, "IPCR", 4, 0),
> + MHI_CHANNEL_CONFIG_TX(100, "IP_HW0", 64, 1),
> + MHI_CHANNEL_CONFIG_RX(101, "IP_HW0", 64, 2),
> +};
> +
> +static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
> + /* first ring is control+data ring */
> + MHI_EVENT_CONFIG_CTRL(0),
> + /* Hardware channels request dedicated hardware event rings */
> + MHI_EVENT_CONFIG_HW_DATA(1, 100),
> + MHI_EVENT_CONFIG_HW_DATA(2, 101)
> +};
> +
> +static const struct mhi_controller_config modem_qcom_v1_mhi_config = {
> + .max_channels = 128,
> + .timeout_ms = 5000,
> + .num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels),
> + .ch_cfg = modem_qcom_v1_mhi_channels,
> + .num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events),
> + .event_cfg = modem_qcom_v1_mhi_events,
> +};
> +
> +static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = {
> + .name = "qcom-sdx55m",
> + .fw = "qcom/sdx55m/sbl1.mbn",
> + .edl = "qcom/sdx55m/edl.mbn",
> + .config = &modem_qcom_v1_mhi_config
> +};
> +
> +static const struct pci_device_id mhi_pci_id_table[] = {
> + { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),
> + .driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info },
> + { }
> +};
> +MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
> +
> +static int mhi_pci_read_reg(struct mhi_controller *mhic, void __iomem
> *addr,
> + u32 *out)
> +{
> + *out = readl(addr);
> + return 0;
> +}
> +
> +static void mhi_pci_write_reg(struct mhi_controller *mhic, void
> __iomem *addr,
> + u32 val)
> +{
> + writel(val, addr);
> +}
> +
> +static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl,
> + enum mhi_callback cb)
> +{
> + return;
> +}
> +
> +static int mhi_pci_claim(struct mhi_controller *mhic)
> +{
> + struct pci_dev *pdev = to_pci_dev(mhic->cntrl_dev);
> + int err;
> +
> + err = pci_assign_resource(pdev, MHI_PCI_BAR_NUM);
Can MHI_PCI_BAR_NUM be a parameter to this function instead of
hardcoding it to 0?