Commit 13e920d9 authored by Haijun Liu's avatar Haijun Liu Committed by David S. Miller
Browse files

net: wwan: t7xx: Add core components



Registers the t7xx device driver with the kernel. Setup all the core
components: PCIe layer, Modem Host Cross Core Interface (MHCCIF),
modem control operations, modem state machine, and build
infrastructure.

* PCIe layer code implements driver probe and removal.
* MHCCIF provides interrupt channels to communicate events
  such as handshake, PM and port enumeration.
* Modem control implements the entry point for modem init,
  reset and exit.
* The modem status monitor is a state machine used by modem control
  to complete initialization and stop. It is used also to propagate
  exception events reported by other components.

Signed-off-by: default avatarHaijun Liu <haijun.liu@mediatek.com>
Signed-off-by: default avatarChandrashekar Devegowda <chandrashekar.devegowda@intel.com>
Co-developed-by: default avatarRicardo Martinez <ricardo.martinez@linux.intel.com>
Signed-off-by: default avatarRicardo Martinez <ricardo.martinez@linux.intel.com>
Reviewed-by: default avatarLoic Poulain <loic.poulain@linaro.org>
Reviewed-by: default avatarIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Reviewed-by: default avatarSergey Ryazanov <ryazanov.s.a@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 39d43904
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -105,6 +105,20 @@ config IOSM

	  If unsure, say N.

config MTK_T7XX
	tristate "MediaTek PCIe 5G WWAN modem T7xx device"
	depends on PCI
	help
	  Enables MediaTek PCIe based 5G WWAN modem (T7xx series) device.
	  Adapts WWAN framework and provides network interface like wwan0
	  and tty interfaces like wwan0at0 (AT protocol), wwan0mbim0
	  (MBIM protocol), etc.

	  To compile this driver as a module, choose M here: the module will be
	  called mtk_t7xx.

	  If unsure, say N.

endif # WWAN

endmenu
+1 −0
Original line number Diff line number Diff line
@@ -13,3 +13,4 @@ obj-$(CONFIG_MHI_WWAN_MBIM) += mhi_wwan_mbim.o
obj-$(CONFIG_QCOM_BAM_DMUX) += qcom_bam_dmux.o
obj-$(CONFIG_RPMSG_WWAN_CTRL) += rpmsg_wwan_ctrl.o
obj-$(CONFIG_IOSM) += iosm/
obj-$(CONFIG_MTK_T7XX) += t7xx/
+12 −0
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0-only

ccflags-y += -Werror

obj-${CONFIG_MTK_T7XX} := mtk_t7xx.o
mtk_t7xx-y:=	t7xx_pci.o \
		t7xx_pcie_mac.o \
		t7xx_mhccif.o \
		t7xx_state_monitor.o  \
		t7xx_modem_ops.o \
		t7xx_cldma.o \
		t7xx_hif_cldma.o  \
+102 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2021, MediaTek Inc.
 * Copyright (c) 2021-2022, Intel Corporation.
 *
 * Authors:
 *  Haijun Liu <haijun.liu@mediatek.com>
 *  Sreehari Kancharla <sreehari.kancharla@intel.com>
 *
 * Contributors:
 *  Amir Hanania <amir.hanania@intel.com>
 *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
 */

#include <linux/bits.h>
#include <linux/completion.h>
#include <linux/dev_printk.h>
#include <linux/io.h>
#include <linux/irqreturn.h>

#include "t7xx_mhccif.h"
#include "t7xx_modem_ops.h"
#include "t7xx_pci.h"
#include "t7xx_pcie_mac.h"
#include "t7xx_reg.h"

static void t7xx_mhccif_clear_interrupts(struct t7xx_pci_dev *t7xx_dev, u32 mask)
{
	void __iomem *mhccif_pbase = t7xx_dev->base_addr.mhccif_rc_base;

	/* Clear level 2 interrupt */
	iowrite32(mask, mhccif_pbase + REG_EP2RC_SW_INT_ACK);
	/* Ensure write is complete */
	t7xx_mhccif_read_sw_int_sts(t7xx_dev);
	/* Clear level 1 interrupt */
	t7xx_pcie_mac_clear_int_status(t7xx_dev, MHCCIF_INT);
}

static irqreturn_t t7xx_mhccif_isr_thread(int irq, void *data)
{
	struct t7xx_pci_dev *t7xx_dev = data;
	u32 int_status, val;

	val = T7XX_L1_1_BIT(1) | T7XX_L1_2_BIT(1);
	iowrite32(val, IREG_BASE(t7xx_dev) + DISABLE_ASPM_LOWPWR);

	int_status = t7xx_mhccif_read_sw_int_sts(t7xx_dev);
	if (int_status & D2H_SW_INT_MASK) {
		int ret = t7xx_pci_mhccif_isr(t7xx_dev);

		if (ret)
			dev_err(&t7xx_dev->pdev->dev, "PCI MHCCIF ISR failure: %d", ret);
	}

	t7xx_mhccif_clear_interrupts(t7xx_dev, int_status);
	t7xx_pcie_mac_set_int(t7xx_dev, MHCCIF_INT);
	return IRQ_HANDLED;
}

u32 t7xx_mhccif_read_sw_int_sts(struct t7xx_pci_dev *t7xx_dev)
{
	return ioread32(t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_STS);
}

void t7xx_mhccif_mask_set(struct t7xx_pci_dev *t7xx_dev, u32 val)
{
	iowrite32(val, t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK_SET);
}

void t7xx_mhccif_mask_clr(struct t7xx_pci_dev *t7xx_dev, u32 val)
{
	iowrite32(val, t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK_CLR);
}

u32 t7xx_mhccif_mask_get(struct t7xx_pci_dev *t7xx_dev)
{
	return ioread32(t7xx_dev->base_addr.mhccif_rc_base + REG_EP2RC_SW_INT_EAP_MASK);
}

static irqreturn_t t7xx_mhccif_isr_handler(int irq, void *data)
{
	return IRQ_WAKE_THREAD;
}

void t7xx_mhccif_init(struct t7xx_pci_dev *t7xx_dev)
{
	t7xx_dev->base_addr.mhccif_rc_base = t7xx_dev->base_addr.pcie_ext_reg_base +
					    MHCCIF_RC_DEV_BASE -
					    t7xx_dev->base_addr.pcie_dev_reg_trsl_addr;

	t7xx_dev->intr_handler[MHCCIF_INT] = t7xx_mhccif_isr_handler;
	t7xx_dev->intr_thread[MHCCIF_INT] = t7xx_mhccif_isr_thread;
	t7xx_dev->callback_param[MHCCIF_INT] = t7xx_dev;
}

void t7xx_mhccif_h2d_swint_trigger(struct t7xx_pci_dev *t7xx_dev, u32 channel)
{
	void __iomem *mhccif_pbase = t7xx_dev->base_addr.mhccif_rc_base;

	iowrite32(BIT(channel), mhccif_pbase + REG_RC2EP_SW_BSY);
	iowrite32(channel, mhccif_pbase + REG_RC2EP_SW_TCHNUM);
}
+37 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only
 *
 * Copyright (c) 2021, MediaTek Inc.
 * Copyright (c) 2021-2022, Intel Corporation.
 *
 * Authors:
 *  Haijun Liu <haijun.liu@mediatek.com>
 *  Sreehari Kancharla <sreehari.kancharla@intel.com>
 *
 * Contributors:
 *  Amir Hanania <amir.hanania@intel.com>
 *  Ricardo Martinez <ricardo.martinez@linux.intel.com>
 */

#ifndef __T7XX_MHCCIF_H__
#define __T7XX_MHCCIF_H__

#include <linux/types.h>

#include "t7xx_pci.h"
#include "t7xx_reg.h"

#define D2H_SW_INT_MASK (D2H_INT_EXCEPTION_INIT |		\
			 D2H_INT_EXCEPTION_INIT_DONE |		\
			 D2H_INT_EXCEPTION_CLEARQ_DONE |	\
			 D2H_INT_EXCEPTION_ALLQ_RESET |		\
			 D2H_INT_PORT_ENUM |			\
			 D2H_INT_ASYNC_MD_HK)

void t7xx_mhccif_mask_set(struct t7xx_pci_dev *t7xx_dev, u32 val);
void t7xx_mhccif_mask_clr(struct t7xx_pci_dev *t7xx_dev, u32 val);
u32 t7xx_mhccif_mask_get(struct t7xx_pci_dev *t7xx_dev);
void t7xx_mhccif_init(struct t7xx_pci_dev *t7xx_dev);
u32 t7xx_mhccif_read_sw_int_sts(struct t7xx_pci_dev *t7xx_dev);
void t7xx_mhccif_h2d_swint_trigger(struct t7xx_pci_dev *t7xx_dev, u32 channel);

#endif /*__T7XX_MHCCIF_H__ */
Loading