Unverified Commit c457d9a5 authored by Arnd Bergmann's avatar Arnd Bergmann
Browse files

Merge tag 'memory-controller-drv-mediatek-6.1' of...

Merge tag 'memory-controller-drv-mediatek-6.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl into arm/drivers

Memory controller drivers for v6.1 - MediaTek

Add support for the mt8188 SMI memory controller.

* tag 'memory-controller-drv-mediatek-6.1' of https://git.kernel.org/pub/scm/linux/kernel/git/krzk/linux-mem-ctrl:
  memory: mtk-smi: mt8188: Add SMI Support
  memory: mtk-smi: Add enable IOMMU SMC command for MM master
  memory: mtk-smi: Add return value for configure port function
  dt-bindings: memory: mediatek: Add mt8188 smi binding

Link: https://lore.kernel.org/r/20220909153037.824092-4-krzysztof.kozlowski@linaro.org


Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
parents 4da90678 673e71df
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@ description: |
  MediaTek SMI have two generations of HW architecture, here is the list
  which generation the SoCs use:
  generation 1: mt2701 and mt7623.
  generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8192 and mt8195.
  generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195.

  There's slight differences between the two SMI, for generation 2, the
  register which control the iommu port is at each larb's register base. But
@@ -37,6 +37,8 @@ properties:
          - mediatek,mt8173-smi-common
          - mediatek,mt8183-smi-common
          - mediatek,mt8186-smi-common
          - mediatek,mt8188-smi-common-vdo
          - mediatek,mt8188-smi-common-vpp
          - mediatek,mt8192-smi-common
          - mediatek,mt8195-smi-common-vdo
          - mediatek,mt8195-smi-common-vpp
+3 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ properties:
          - mediatek,mt8173-smi-larb
          - mediatek,mt8183-smi-larb
          - mediatek,mt8186-smi-larb
          - mediatek,mt8188-smi-larb
          - mediatek,mt8192-smi-larb
          - mediatek,mt8195-smi-larb

@@ -78,6 +79,7 @@ allOf:
          enum:
            - mediatek,mt8183-smi-larb
            - mediatek,mt8186-smi-larb
            - mediatek,mt8188-smi-larb
            - mediatek,mt8195-smi-larb

    then:
@@ -111,6 +113,7 @@ allOf:
              - mediatek,mt2712-smi-larb
              - mediatek,mt6779-smi-larb
              - mediatek,mt8186-smi-larb
              - mediatek,mt8188-smi-larb
              - mediatek,mt8192-smi-larb
              - mediatek,mt8195-smi-larb

+100 −9
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@
 * Copyright (c) 2015-2016 MediaTek Inc.
 * Author: Yong Wu <yong.wu@mediatek.com>
 */
#include <linux/arm-smccc.h>
#include <linux/clk.h>
#include <linux/component.h>
#include <linux/device.h>
@@ -14,6 +15,7 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/soc/mediatek/mtk_sip_svc.h>
#include <soc/mediatek/smi.h>
#include <dt-bindings/memory/mt2701-larb-port.h>
#include <dt-bindings/memory/mtk-memory-port.h>
@@ -89,6 +91,7 @@
#define MTK_SMI_FLAG_THRT_UPDATE	BIT(0)
#define MTK_SMI_FLAG_SW_FLAG		BIT(1)
#define MTK_SMI_FLAG_SLEEP_CTL		BIT(2)
#define MTK_SMI_FLAG_CFG_PORT_SEC_CTL	BIT(3)
#define MTK_SMI_CAPS(flags, _x)		(!!((flags) & (_x)))

struct mtk_smi_reg_pair {
@@ -127,7 +130,7 @@ struct mtk_smi_common_plat {

struct mtk_smi_larb_gen {
	int port_in_larb[MTK_LARB_NR_MAX + 1];
	void (*config_port)(struct device *dev);
	int				(*config_port)(struct device *dev);
	unsigned int			larb_direct_to_common_mask;
	unsigned int			flags_general;
	const u8			(*ostd)[SMI_LARB_PORT_NR_MAX];
@@ -185,7 +188,7 @@ static const struct component_ops mtk_smi_larb_component_ops = {
	.unbind = mtk_smi_larb_unbind,
};

static void mtk_smi_larb_config_port_gen1(struct device *dev)
static int mtk_smi_larb_config_port_gen1(struct device *dev)
{
	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
	const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
@@ -214,31 +217,35 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
			common->smi_ao_base
			+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
	}
	return 0;
}

static void mtk_smi_larb_config_port_mt8167(struct device *dev)
static int mtk_smi_larb_config_port_mt8167(struct device *dev)
{
	struct mtk_smi_larb *larb = dev_get_drvdata(dev);

	writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN);
	return 0;
}

static void mtk_smi_larb_config_port_mt8173(struct device *dev)
static int mtk_smi_larb_config_port_mt8173(struct device *dev)
{
	struct mtk_smi_larb *larb = dev_get_drvdata(dev);

	writel(*larb->mmu, larb->base + MT8173_SMI_LARB_MMU_EN);
	return 0;
}

static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
static int mtk_smi_larb_config_port_gen2_general(struct device *dev)
{
	struct mtk_smi_larb *larb = dev_get_drvdata(dev);
	u32 reg, flags_general = larb->larb_gen->flags_general;
	const u8 *larbostd = larb->larb_gen->ostd ? larb->larb_gen->ostd[larb->larbid] : NULL;
	struct arm_smccc_res res;
	int i;

	if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
		return;
		return 0;

	if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_THRT_UPDATE)) {
		reg = readl_relaxed(larb->base + SMI_LARB_CMD_THRT_CON);
@@ -253,14 +260,78 @@ static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
	for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++)
		writel_relaxed(larbostd[i], larb->base + SMI_LARB_OSTDL_PORTx(i));

	/*
	 * When mmu_en bits are in security world, the bank_sel still is in the
	 * LARB_NONSEC_CON below. And the mmu_en bits of LARB_NONSEC_CON have no
	 * effect in this case.
	 */
	if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_CFG_PORT_SEC_CTL)) {
		arm_smccc_smc(MTK_SIP_KERNEL_IOMMU_CONTROL, IOMMU_ATF_CMD_CONFIG_SMI_LARB,
			      larb->larbid, *larb->mmu, 0, 0, 0, 0, &res);
		if (res.a0 != 0) {
			dev_err(dev, "Enable iommu fail, ret %ld\n", res.a0);
			return -EINVAL;
		}
	}

	for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
		reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
		reg |= F_MMU_EN;
		reg |= BANK_SEL(larb->bank[i]);
		writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
	}
	return 0;
}

static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
	[0] = {0x02, 0x18, 0x22, 0x22, 0x01, 0x02, 0x0a,},
	[1] = {0x12, 0x02, 0x14, 0x14, 0x01, 0x18, 0x0a,},
	[2] = {0x12, 0x12, 0x12, 0x12, 0x0a,},
	[3] = {0x12, 0x12, 0x12, 0x12, 0x28, 0x28, 0x0a,},
	[4] = {0x06, 0x01, 0x17, 0x06, 0x0a, 0x07, 0x07,},
	[5] = {0x02, 0x01, 0x04, 0x02, 0x06, 0x01, 0x06, 0x0a,},
	[6] = {0x06, 0x01, 0x06, 0x0a,},
	[7] = {0x0c, 0x0c, 0x12,},
	[8] = {0x0c, 0x01, 0x0a, 0x05, 0x02, 0x03, 0x01, 0x01, 0x14, 0x14,
	       0x0a, 0x14, 0x1e, 0x01, 0x0c, 0x0a, 0x05, 0x02, 0x02, 0x05,
	       0x03, 0x01, 0x1e, 0x01, 0x05,},
	[9] = {0x1e, 0x01, 0x0a, 0x0a, 0x01, 0x01, 0x03, 0x1e, 0x1e, 0x10,
	       0x07, 0x01, 0x0a, 0x06, 0x03, 0x03, 0x0e, 0x01, 0x04, 0x28,},
	[10] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
		0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
		0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
	[11] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
		0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
		0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
	[12] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
		0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
		0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
	[13] = {0x07, 0x02, 0x04, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
		0x07, 0x02, 0x04, 0x02, 0x05, 0x05,},
	[14] = {0x02, 0x02, 0x0c, 0x0c, 0x0c, 0x0c, 0x01, 0x01, 0x02, 0x02,
		0x02, 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
		0x02, 0x02, 0x01, 0x01,},
	[15] = {0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x0c, 0x0c,
		0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
		0x0c, 0x01, 0x01,},
	[16] = {0x28, 0x28, 0x03, 0x01, 0x01, 0x03, 0x14, 0x14, 0x0a, 0x0d,
		0x03, 0x05, 0x0e, 0x01, 0x01, 0x05, 0x06, 0x0d, 0x01,},
	[17] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a,
		0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,},
	[18] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a,
		0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,},
	[19] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
	[20] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
	[21] = {0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x01,
		0x01, 0x01, 0x04, 0x0a, 0x06, 0x01, 0x01, 0x01, 0x0a, 0x06,
		0x01, 0x01, 0x05, 0x03, 0x03, 0x04, 0x01,},
	[22] = {0x28, 0x19, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
		0x01,},
	[23] = {0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x18, 0x01, 0x01,},
	[24] = {0x12, 0x06, 0x12, 0x06,},
	[25] = {0x01},
};

static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
	[0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */
	[1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */
@@ -347,6 +418,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = {
	.flags_general	            = MTK_SMI_FLAG_SLEEP_CTL,
};

static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
	.config_port                = mtk_smi_larb_config_port_gen2_general,
	.flags_general	            = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
				      MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
	.ostd		            = mtk_smi_larb_mt8188_ostd,
};

static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
	.config_port                = mtk_smi_larb_config_port_gen2_general,
};
@@ -367,6 +445,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
	{.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173},
	{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
	{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
	{.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188},
	{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
	{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
	{}
@@ -511,9 +590,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
		mtk_smi_larb_sleep_ctrl_disable(larb);

	/* Configure the basic setting for this larb */
	larb_gen->config_port(dev);

	return 0;
	return larb_gen->config_port(dev);
}

static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
@@ -597,6 +674,18 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = {
	.bus_sel  = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7),
};

static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vdo = {
	.type     = MTK_SMI_GEN2,
	.bus_sel  = F_MMU1_LARB(1) | F_MMU1_LARB(5) | F_MMU1_LARB(7),
	.init     = mtk_smi_common_mt8195_init,
};

static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
	.type     = MTK_SMI_GEN2,
	.bus_sel  = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(7),
	.init     = mtk_smi_common_mt8195_init,
};

static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
	.type     = MTK_SMI_GEN2,
	.has_gals = true,
@@ -633,6 +722,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
	{.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2},
	{.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
	{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
	{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
	{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
	{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
	{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
	{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
+3 −0
Original line number Diff line number Diff line
@@ -22,4 +22,7 @@
	ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, MTK_SIP_SMC_CONVENTION, \
			   ARM_SMCCC_OWNER_SIP, fn_id)

/* IOMMU related SMC call */
#define MTK_SIP_KERNEL_IOMMU_CONTROL	MTK_SIP_SMC_CMD(0x514)

#endif
+5 −0
Original line number Diff line number Diff line
@@ -11,6 +11,11 @@

#if IS_ENABLED(CONFIG_MTK_SMI)

enum iommu_atf_cmd {
	IOMMU_ATF_CMD_CONFIG_SMI_LARB,		/* For mm master to en/disable iommu */
	IOMMU_ATF_CMD_MAX,
};

#define MTK_SMI_MMU_EN(port)	BIT(port)

struct mtk_smi_larb_iommu {