xref: /linux/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c (revision 9cff922bba429b310507eac3b6cb5eb1b57e9ad1)
12d7ca2c4SAndrew Murray // SPDX-License-Identifier: GPL-2.0
248ec83bcSWill Deacon /*
348ec83bcSWill Deacon  * IOMMU API for ARM architected SMMUv3 implementations.
448ec83bcSWill Deacon  *
548ec83bcSWill Deacon  * Copyright (C) 2015 ARM Limited
648ec83bcSWill Deacon  *
748ec83bcSWill Deacon  * Author: Will Deacon <will.deacon@arm.com>
848ec83bcSWill Deacon  *
948ec83bcSWill Deacon  * This driver is powered by bad coffee and bombay mix.
1048ec83bcSWill Deacon  */
1148ec83bcSWill Deacon 
12e4dadfa8SLorenzo Pieralisi #include <linux/acpi.h>
13e4dadfa8SLorenzo Pieralisi #include <linux/acpi_iort.h>
141cf9e54eSRobin Murphy #include <linux/bitops.h>
15b63b3439SWill Deacon #include <linux/crash_dump.h>
1648ec83bcSWill Deacon #include <linux/delay.h>
179adb9594SRobin Murphy #include <linux/dma-iommu.h>
1848ec83bcSWill Deacon #include <linux/err.h>
1948ec83bcSWill Deacon #include <linux/interrupt.h>
20b77cf11fSRob Herring #include <linux/io-pgtable.h>
2148ec83bcSWill Deacon #include <linux/iopoll.h>
226e8fa740SWill Deacon #include <linux/module.h>
23166bdbd2SMarc Zyngier #include <linux/msi.h>
2448ec83bcSWill Deacon #include <linux/of.h>
2548ec83bcSWill Deacon #include <linux/of_address.h>
268f785154SRobin Murphy #include <linux/of_iommu.h>
27941a802dSWill Deacon #include <linux/of_platform.h>
2848ec83bcSWill Deacon #include <linux/pci.h>
299ce27afcSJean-Philippe Brucker #include <linux/pci-ats.h>
3048ec83bcSWill Deacon #include <linux/platform_device.h>
3148ec83bcSWill Deacon 
3208d4ca2aSRobin Murphy #include <linux/amba/bus.h>
3308d4ca2aSRobin Murphy 
34e881e783SJean-Philippe Brucker #include "arm-smmu-v3.h"
35395ad89dSJean-Philippe Brucker #include "../../iommu-sva-lib.h"
3650019f09SEric Auger 
373045fe45SKaixu Xia static bool disable_bypass = true;
389305d02aSBarry Song module_param(disable_bypass, bool, 0444);
3948ec83bcSWill Deacon MODULE_PARM_DESC(disable_bypass,
4048ec83bcSWill Deacon 	"Disable bypass streams such that incoming transactions from devices that are not attached to an iommu domain will report an abort back to the device and will not be allowed to pass through the SMMU.");
4148ec83bcSWill Deacon 
42bd07a20aSBarry Song static bool disable_msipolling;
43bd07a20aSBarry Song module_param(disable_msipolling, bool, 0444);
44bd07a20aSBarry Song MODULE_PARM_DESC(disable_msipolling,
45bd07a20aSBarry Song 	"Disable MSI-based polling for CMD_SYNC completion.");
46bd07a20aSBarry Song 
47166bdbd2SMarc Zyngier enum arm_smmu_msi_index {
48166bdbd2SMarc Zyngier 	EVTQ_MSI_INDEX,
49166bdbd2SMarc Zyngier 	GERROR_MSI_INDEX,
50166bdbd2SMarc Zyngier 	PRIQ_MSI_INDEX,
51166bdbd2SMarc Zyngier 	ARM_SMMU_MAX_MSIS,
52166bdbd2SMarc Zyngier };
53166bdbd2SMarc Zyngier 
54166bdbd2SMarc Zyngier static phys_addr_t arm_smmu_msi_cfg[ARM_SMMU_MAX_MSIS][3] = {
55166bdbd2SMarc Zyngier 	[EVTQ_MSI_INDEX] = {
56166bdbd2SMarc Zyngier 		ARM_SMMU_EVTQ_IRQ_CFG0,
57166bdbd2SMarc Zyngier 		ARM_SMMU_EVTQ_IRQ_CFG1,
58166bdbd2SMarc Zyngier 		ARM_SMMU_EVTQ_IRQ_CFG2,
59166bdbd2SMarc Zyngier 	},
60166bdbd2SMarc Zyngier 	[GERROR_MSI_INDEX] = {
61166bdbd2SMarc Zyngier 		ARM_SMMU_GERROR_IRQ_CFG0,
62166bdbd2SMarc Zyngier 		ARM_SMMU_GERROR_IRQ_CFG1,
63166bdbd2SMarc Zyngier 		ARM_SMMU_GERROR_IRQ_CFG2,
64166bdbd2SMarc Zyngier 	},
65166bdbd2SMarc Zyngier 	[PRIQ_MSI_INDEX] = {
66166bdbd2SMarc Zyngier 		ARM_SMMU_PRIQ_IRQ_CFG0,
67166bdbd2SMarc Zyngier 		ARM_SMMU_PRIQ_IRQ_CFG1,
68166bdbd2SMarc Zyngier 		ARM_SMMU_PRIQ_IRQ_CFG2,
69166bdbd2SMarc Zyngier 	},
70166bdbd2SMarc Zyngier };
71166bdbd2SMarc Zyngier 
725e92946cSZhen Lei struct arm_smmu_option_prop {
735e92946cSZhen Lei 	u32 opt;
745e92946cSZhen Lei 	const char *prop;
755e92946cSZhen Lei };
765e92946cSZhen Lei 
773f1ce8e8SJean-Philippe Brucker DEFINE_XARRAY_ALLOC1(arm_smmu_asid_xa);
783f1ce8e8SJean-Philippe Brucker DEFINE_MUTEX(arm_smmu_asid_lock);
790299a1a8SJean-Philippe Brucker 
8032784a95SJean-Philippe Brucker /*
8132784a95SJean-Philippe Brucker  * Special value used by SVA when a process dies, to quiesce a CD without
8232784a95SJean-Philippe Brucker  * disabling it.
8332784a95SJean-Philippe Brucker  */
8432784a95SJean-Philippe Brucker struct arm_smmu_ctx_desc quiet_cd = { 0 };
8532784a95SJean-Philippe Brucker 
865e92946cSZhen Lei static struct arm_smmu_option_prop arm_smmu_options[] = {
875e92946cSZhen Lei 	{ ARM_SMMU_OPT_SKIP_PREFETCH, "hisilicon,broken-prefetch-cmd" },
88e5b829deSLinu Cherian 	{ ARM_SMMU_OPT_PAGE0_REGS_ONLY, "cavium,cn9900-broken-page1-regspace"},
895e92946cSZhen Lei 	{ 0, NULL},
905e92946cSZhen Lei };
915e92946cSZhen Lei 
925e92946cSZhen Lei static void parse_driver_options(struct arm_smmu_device *smmu)
935e92946cSZhen Lei {
945e92946cSZhen Lei 	int i = 0;
955e92946cSZhen Lei 
965e92946cSZhen Lei 	do {
975e92946cSZhen Lei 		if (of_property_read_bool(smmu->dev->of_node,
985e92946cSZhen Lei 						arm_smmu_options[i].prop)) {
995e92946cSZhen Lei 			smmu->options |= arm_smmu_options[i].opt;
1005e92946cSZhen Lei 			dev_notice(smmu->dev, "option %s\n",
1015e92946cSZhen Lei 				arm_smmu_options[i].prop);
1025e92946cSZhen Lei 		}
1035e92946cSZhen Lei 	} while (arm_smmu_options[++i].opt);
1045e92946cSZhen Lei }
1055e92946cSZhen Lei 
10648ec83bcSWill Deacon /* Low-level queue manipulation functions */
107587e6c10SWill Deacon static bool queue_has_space(struct arm_smmu_ll_queue *q, u32 n)
108587e6c10SWill Deacon {
109587e6c10SWill Deacon 	u32 space, prod, cons;
110587e6c10SWill Deacon 
111587e6c10SWill Deacon 	prod = Q_IDX(q, q->prod);
112587e6c10SWill Deacon 	cons = Q_IDX(q, q->cons);
113587e6c10SWill Deacon 
114587e6c10SWill Deacon 	if (Q_WRP(q, q->prod) == Q_WRP(q, q->cons))
115587e6c10SWill Deacon 		space = (1 << q->max_n_shift) - (prod - cons);
116587e6c10SWill Deacon 	else
117587e6c10SWill Deacon 		space = cons - prod;
118587e6c10SWill Deacon 
119587e6c10SWill Deacon 	return space >= n;
120587e6c10SWill Deacon }
121587e6c10SWill Deacon 
1227c288a5bSWill Deacon static bool queue_full(struct arm_smmu_ll_queue *q)
12348ec83bcSWill Deacon {
12448ec83bcSWill Deacon 	return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) &&
12548ec83bcSWill Deacon 	       Q_WRP(q, q->prod) != Q_WRP(q, q->cons);
12648ec83bcSWill Deacon }
12748ec83bcSWill Deacon 
1287c288a5bSWill Deacon static bool queue_empty(struct arm_smmu_ll_queue *q)
12948ec83bcSWill Deacon {
13048ec83bcSWill Deacon 	return Q_IDX(q, q->prod) == Q_IDX(q, q->cons) &&
13148ec83bcSWill Deacon 	       Q_WRP(q, q->prod) == Q_WRP(q, q->cons);
13248ec83bcSWill Deacon }
13348ec83bcSWill Deacon 
134587e6c10SWill Deacon static bool queue_consumed(struct arm_smmu_ll_queue *q, u32 prod)
13548ec83bcSWill Deacon {
136587e6c10SWill Deacon 	return ((Q_WRP(q, q->cons) == Q_WRP(q, prod)) &&
137587e6c10SWill Deacon 		(Q_IDX(q, q->cons) > Q_IDX(q, prod))) ||
138587e6c10SWill Deacon 	       ((Q_WRP(q, q->cons) != Q_WRP(q, prod)) &&
139587e6c10SWill Deacon 		(Q_IDX(q, q->cons) <= Q_IDX(q, prod)));
14048ec83bcSWill Deacon }
14148ec83bcSWill Deacon 
1422a8868f1SWill Deacon static void queue_sync_cons_out(struct arm_smmu_queue *q)
14348ec83bcSWill Deacon {
144a868e853SWill Deacon 	/*
145a868e853SWill Deacon 	 * Ensure that all CPU accesses (reads and writes) to the queue
146a868e853SWill Deacon 	 * are complete before we update the cons pointer.
147a868e853SWill Deacon 	 */
148a76a3777SZhou Wang 	__iomb();
14952be8637SWill Deacon 	writel_relaxed(q->llq.cons, q->cons_reg);
15048ec83bcSWill Deacon }
15148ec83bcSWill Deacon 
1527c288a5bSWill Deacon static void queue_inc_cons(struct arm_smmu_ll_queue *q)
1532a8868f1SWill Deacon {
1547c288a5bSWill Deacon 	u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
1557c288a5bSWill Deacon 	q->cons = Q_OVF(q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
1562a8868f1SWill Deacon }
1572a8868f1SWill Deacon 
1582a8868f1SWill Deacon static int queue_sync_prod_in(struct arm_smmu_queue *q)
15948ec83bcSWill Deacon {
160a76a3777SZhou Wang 	u32 prod;
16148ec83bcSWill Deacon 	int ret = 0;
162a76a3777SZhou Wang 
163a76a3777SZhou Wang 	/*
164a76a3777SZhou Wang 	 * We can't use the _relaxed() variant here, as we must prevent
165a76a3777SZhou Wang 	 * speculative reads of the queue before we have determined that
166a76a3777SZhou Wang 	 * prod has indeed moved.
167a76a3777SZhou Wang 	 */
168a76a3777SZhou Wang 	prod = readl(q->prod_reg);
16948ec83bcSWill Deacon 
17052be8637SWill Deacon 	if (Q_OVF(prod) != Q_OVF(q->llq.prod))
17148ec83bcSWill Deacon 		ret = -EOVERFLOW;
17248ec83bcSWill Deacon 
17352be8637SWill Deacon 	q->llq.prod = prod;
17448ec83bcSWill Deacon 	return ret;
17548ec83bcSWill Deacon }
17648ec83bcSWill Deacon 
177587e6c10SWill Deacon static u32 queue_inc_prod_n(struct arm_smmu_ll_queue *q, int n)
17848ec83bcSWill Deacon {
179587e6c10SWill Deacon 	u32 prod = (Q_WRP(q, q->prod) | Q_IDX(q, q->prod)) + n;
180587e6c10SWill Deacon 	return Q_OVF(q->prod) | Q_WRP(q, prod) | Q_IDX(q, prod);
18148ec83bcSWill Deacon }
18248ec83bcSWill Deacon 
183587e6c10SWill Deacon static void queue_poll_init(struct arm_smmu_device *smmu,
184587e6c10SWill Deacon 			    struct arm_smmu_queue_poll *qp)
18548ec83bcSWill Deacon {
186587e6c10SWill Deacon 	qp->delay = 1;
187587e6c10SWill Deacon 	qp->spin_cnt = 0;
188587e6c10SWill Deacon 	qp->wfe = !!(smmu->features & ARM_SMMU_FEAT_SEV);
189587e6c10SWill Deacon 	qp->timeout = ktime_add_us(ktime_get(), ARM_SMMU_POLL_TIMEOUT_US);
19048ec83bcSWill Deacon }
191b847de4eSSunil Goutham 
192587e6c10SWill Deacon static int queue_poll(struct arm_smmu_queue_poll *qp)
19348ec83bcSWill Deacon {
194587e6c10SWill Deacon 	if (ktime_compare(ktime_get(), qp->timeout) > 0)
19548ec83bcSWill Deacon 		return -ETIMEDOUT;
19648ec83bcSWill Deacon 
197587e6c10SWill Deacon 	if (qp->wfe) {
19848ec83bcSWill Deacon 		wfe();
199587e6c10SWill Deacon 	} else if (++qp->spin_cnt < ARM_SMMU_POLL_SPIN_COUNT) {
20048ec83bcSWill Deacon 		cpu_relax();
2018ff0f723SRobin Murphy 	} else {
202587e6c10SWill Deacon 		udelay(qp->delay);
203587e6c10SWill Deacon 		qp->delay *= 2;
204587e6c10SWill Deacon 		qp->spin_cnt = 0;
20548ec83bcSWill Deacon 	}
20648ec83bcSWill Deacon 
20748ec83bcSWill Deacon 	return 0;
20848ec83bcSWill Deacon }
20948ec83bcSWill Deacon 
21048ec83bcSWill Deacon static void queue_write(__le64 *dst, u64 *src, size_t n_dwords)
21148ec83bcSWill Deacon {
21248ec83bcSWill Deacon 	int i;
21348ec83bcSWill Deacon 
21448ec83bcSWill Deacon 	for (i = 0; i < n_dwords; ++i)
21548ec83bcSWill Deacon 		*dst++ = cpu_to_le64(*src++);
21648ec83bcSWill Deacon }
21748ec83bcSWill Deacon 
218376cdf66SJean-Philippe Brucker static void queue_read(u64 *dst, __le64 *src, size_t n_dwords)
21948ec83bcSWill Deacon {
22048ec83bcSWill Deacon 	int i;
22148ec83bcSWill Deacon 
22248ec83bcSWill Deacon 	for (i = 0; i < n_dwords; ++i)
22348ec83bcSWill Deacon 		*dst++ = le64_to_cpu(*src++);
22448ec83bcSWill Deacon }
22548ec83bcSWill Deacon 
22648ec83bcSWill Deacon static int queue_remove_raw(struct arm_smmu_queue *q, u64 *ent)
22748ec83bcSWill Deacon {
2287c288a5bSWill Deacon 	if (queue_empty(&q->llq))
22948ec83bcSWill Deacon 		return -EAGAIN;
23048ec83bcSWill Deacon 
23152be8637SWill Deacon 	queue_read(ent, Q_ENT(q, q->llq.cons), q->ent_dwords);
2327c288a5bSWill Deacon 	queue_inc_cons(&q->llq);
2332a8868f1SWill Deacon 	queue_sync_cons_out(q);
23448ec83bcSWill Deacon 	return 0;
23548ec83bcSWill Deacon }
23648ec83bcSWill Deacon 
23748ec83bcSWill Deacon /* High-level queue accessors */
23848ec83bcSWill Deacon static int arm_smmu_cmdq_build_cmd(u64 *cmd, struct arm_smmu_cmdq_ent *ent)
23948ec83bcSWill Deacon {
240d25f6eadSWill Deacon 	memset(cmd, 0, 1 << CMDQ_ENT_SZ_SHIFT);
2417417b99cSRobin Murphy 	cmd[0] |= FIELD_PREP(CMDQ_0_OP, ent->opcode);
24248ec83bcSWill Deacon 
24348ec83bcSWill Deacon 	switch (ent->opcode) {
24448ec83bcSWill Deacon 	case CMDQ_OP_TLBI_EL2_ALL:
24548ec83bcSWill Deacon 	case CMDQ_OP_TLBI_NSNH_ALL:
24648ec83bcSWill Deacon 		break;
24748ec83bcSWill Deacon 	case CMDQ_OP_PREFETCH_CFG:
2487417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_PREFETCH_0_SID, ent->prefetch.sid);
24948ec83bcSWill Deacon 		break;
25087f42391SJean-Philippe Brucker 	case CMDQ_OP_CFGI_CD:
25187f42391SJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SSID, ent->cfgi.ssid);
252df561f66SGustavo A. R. Silva 		fallthrough;
25348ec83bcSWill Deacon 	case CMDQ_OP_CFGI_STE:
2547417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid);
2557417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_LEAF, ent->cfgi.leaf);
25648ec83bcSWill Deacon 		break;
25787f42391SJean-Philippe Brucker 	case CMDQ_OP_CFGI_CD_ALL:
25887f42391SJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_CFGI_0_SID, ent->cfgi.sid);
25987f42391SJean-Philippe Brucker 		break;
26048ec83bcSWill Deacon 	case CMDQ_OP_CFGI_ALL:
26148ec83bcSWill Deacon 		/* Cover the entire SID range */
2627417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_CFGI_1_RANGE, 31);
26348ec83bcSWill Deacon 		break;
26448ec83bcSWill Deacon 	case CMDQ_OP_TLBI_NH_VA:
2659111aebfSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
2669111aebfSJean-Philippe Brucker 		fallthrough;
2679111aebfSJean-Philippe Brucker 	case CMDQ_OP_TLBI_EL2_VA:
2686a481a95SRob Herring 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_NUM, ent->tlbi.num);
2696a481a95SRob Herring 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_SCALE, ent->tlbi.scale);
2707417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
2717417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
2726a481a95SRob Herring 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TTL, ent->tlbi.ttl);
2736a481a95SRob Herring 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TG, ent->tlbi.tg);
2741c27df1cSWill Deacon 		cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_VA_MASK;
2751c27df1cSWill Deacon 		break;
27648ec83bcSWill Deacon 	case CMDQ_OP_TLBI_S2_IPA:
2776a481a95SRob Herring 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_NUM, ent->tlbi.num);
2786a481a95SRob Herring 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_SCALE, ent->tlbi.scale);
2797417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
2807417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_LEAF, ent->tlbi.leaf);
2816a481a95SRob Herring 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TTL, ent->tlbi.ttl);
2826a481a95SRob Herring 		cmd[1] |= FIELD_PREP(CMDQ_TLBI_1_TG, ent->tlbi.tg);
2831c27df1cSWill Deacon 		cmd[1] |= ent->tlbi.addr & CMDQ_TLBI_1_IPA_MASK;
28448ec83bcSWill Deacon 		break;
28548ec83bcSWill Deacon 	case CMDQ_OP_TLBI_NH_ASID:
2867417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
287df561f66SGustavo A. R. Silva 		fallthrough;
28848ec83bcSWill Deacon 	case CMDQ_OP_TLBI_S12_VMALL:
2897417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_VMID, ent->tlbi.vmid);
29048ec83bcSWill Deacon 		break;
2919111aebfSJean-Philippe Brucker 	case CMDQ_OP_TLBI_EL2_ASID:
2929111aebfSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_TLBI_0_ASID, ent->tlbi.asid);
2939111aebfSJean-Philippe Brucker 		break;
2949ce27afcSJean-Philippe Brucker 	case CMDQ_OP_ATC_INV:
2959ce27afcSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid);
2969ce27afcSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_ATC_0_GLOBAL, ent->atc.global);
2979ce27afcSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SSID, ent->atc.ssid);
2989ce27afcSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_ATC_0_SID, ent->atc.sid);
2999ce27afcSJean-Philippe Brucker 		cmd[1] |= FIELD_PREP(CMDQ_ATC_1_SIZE, ent->atc.size);
3009ce27afcSJean-Philippe Brucker 		cmd[1] |= ent->atc.addr & CMDQ_ATC_1_ADDR_MASK;
3019ce27afcSJean-Philippe Brucker 		break;
30248ec83bcSWill Deacon 	case CMDQ_OP_PRI_RESP:
3037417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_0_SSV, ent->substream_valid);
3047417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SSID, ent->pri.ssid);
3057417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_PRI_0_SID, ent->pri.sid);
3067417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_PRI_1_GRPID, ent->pri.grpid);
30748ec83bcSWill Deacon 		switch (ent->pri.resp) {
30848ec83bcSWill Deacon 		case PRI_RESP_DENY:
30948ec83bcSWill Deacon 		case PRI_RESP_FAIL:
31048ec83bcSWill Deacon 		case PRI_RESP_SUCC:
31148ec83bcSWill Deacon 			break;
31248ec83bcSWill Deacon 		default:
31348ec83bcSWill Deacon 			return -EINVAL;
31448ec83bcSWill Deacon 		}
3157417b99cSRobin Murphy 		cmd[1] |= FIELD_PREP(CMDQ_PRI_1_RESP, ent->pri.resp);
31648ec83bcSWill Deacon 		break;
317395ad89dSJean-Philippe Brucker 	case CMDQ_OP_RESUME:
318395ad89dSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_RESUME_0_SID, ent->resume.sid);
319395ad89dSJean-Philippe Brucker 		cmd[0] |= FIELD_PREP(CMDQ_RESUME_0_RESP, ent->resume.resp);
320395ad89dSJean-Philippe Brucker 		cmd[1] |= FIELD_PREP(CMDQ_RESUME_1_STAG, ent->resume.stag);
321395ad89dSJean-Philippe Brucker 		break;
32248ec83bcSWill Deacon 	case CMDQ_OP_CMD_SYNC:
323587e6c10SWill Deacon 		if (ent->sync.msiaddr) {
3247417b99cSRobin Murphy 			cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_IRQ);
325587e6c10SWill Deacon 			cmd[1] |= ent->sync.msiaddr & CMDQ_SYNC_1_MSIADDR_MASK;
326587e6c10SWill Deacon 		} else {
3277417b99cSRobin Murphy 			cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_CS, CMDQ_SYNC_0_CS_SEV);
328587e6c10SWill Deacon 		}
3297417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSH, ARM_SMMU_SH_ISH);
3307417b99cSRobin Murphy 		cmd[0] |= FIELD_PREP(CMDQ_SYNC_0_MSIATTR, ARM_SMMU_MEMATTR_OIWB);
33148ec83bcSWill Deacon 		break;
33248ec83bcSWill Deacon 	default:
33348ec83bcSWill Deacon 		return -ENOENT;
33448ec83bcSWill Deacon 	}
33548ec83bcSWill Deacon 
33648ec83bcSWill Deacon 	return 0;
33748ec83bcSWill Deacon }
33848ec83bcSWill Deacon 
339587e6c10SWill Deacon static void arm_smmu_cmdq_build_sync_cmd(u64 *cmd, struct arm_smmu_device *smmu,
340587e6c10SWill Deacon 					 u32 prod)
341587e6c10SWill Deacon {
342587e6c10SWill Deacon 	struct arm_smmu_queue *q = &smmu->cmdq.q;
343587e6c10SWill Deacon 	struct arm_smmu_cmdq_ent ent = {
344587e6c10SWill Deacon 		.opcode = CMDQ_OP_CMD_SYNC,
345587e6c10SWill Deacon 	};
346587e6c10SWill Deacon 
347587e6c10SWill Deacon 	/*
348587e6c10SWill Deacon 	 * Beware that Hi16xx adds an extra 32 bits of goodness to its MSI
349587e6c10SWill Deacon 	 * payload, so the write will zero the entire command on that platform.
350587e6c10SWill Deacon 	 */
351bd07a20aSBarry Song 	if (smmu->options & ARM_SMMU_OPT_MSIPOLL) {
352587e6c10SWill Deacon 		ent.sync.msiaddr = q->base_dma + Q_IDX(&q->llq, prod) *
353587e6c10SWill Deacon 				   q->ent_dwords * 8;
354587e6c10SWill Deacon 	}
355587e6c10SWill Deacon 
356587e6c10SWill Deacon 	arm_smmu_cmdq_build_cmd(cmd, &ent);
357587e6c10SWill Deacon }
358587e6c10SWill Deacon 
35948ec83bcSWill Deacon static void arm_smmu_cmdq_skip_err(struct arm_smmu_device *smmu)
36048ec83bcSWill Deacon {
361d56d5162SBixuan Cui 	static const char * const cerror_str[] = {
36248ec83bcSWill Deacon 		[CMDQ_ERR_CERROR_NONE_IDX]	= "No error",
36348ec83bcSWill Deacon 		[CMDQ_ERR_CERROR_ILL_IDX]	= "Illegal command",
36448ec83bcSWill Deacon 		[CMDQ_ERR_CERROR_ABT_IDX]	= "Abort on command fetch",
3659ce27afcSJean-Philippe Brucker 		[CMDQ_ERR_CERROR_ATC_INV_IDX]	= "ATC invalidate timeout",
36648ec83bcSWill Deacon 	};
36748ec83bcSWill Deacon 
36848ec83bcSWill Deacon 	int i;
36948ec83bcSWill Deacon 	u64 cmd[CMDQ_ENT_DWORDS];
37048ec83bcSWill Deacon 	struct arm_smmu_queue *q = &smmu->cmdq.q;
37148ec83bcSWill Deacon 	u32 cons = readl_relaxed(q->cons_reg);
372cbcee19aSRobin Murphy 	u32 idx = FIELD_GET(CMDQ_CONS_ERR, cons);
37348ec83bcSWill Deacon 	struct arm_smmu_cmdq_ent cmd_sync = {
37448ec83bcSWill Deacon 		.opcode = CMDQ_OP_CMD_SYNC,
37548ec83bcSWill Deacon 	};
37648ec83bcSWill Deacon 
37748ec83bcSWill Deacon 	dev_err(smmu->dev, "CMDQ error (cons 0x%08x): %s\n", cons,
378a0d5c04cSWill Deacon 		idx < ARRAY_SIZE(cerror_str) ?  cerror_str[idx] : "Unknown");
37948ec83bcSWill Deacon 
38048ec83bcSWill Deacon 	switch (idx) {
38148ec83bcSWill Deacon 	case CMDQ_ERR_CERROR_ABT_IDX:
38248ec83bcSWill Deacon 		dev_err(smmu->dev, "retrying command fetch\n");
38348ec83bcSWill Deacon 	case CMDQ_ERR_CERROR_NONE_IDX:
38448ec83bcSWill Deacon 		return;
3859ce27afcSJean-Philippe Brucker 	case CMDQ_ERR_CERROR_ATC_INV_IDX:
3869ce27afcSJean-Philippe Brucker 		/*
3879ce27afcSJean-Philippe Brucker 		 * ATC Invalidation Completion timeout. CONS is still pointing
3889ce27afcSJean-Philippe Brucker 		 * at the CMD_SYNC. Attempt to complete other pending commands
3899ce27afcSJean-Philippe Brucker 		 * by repeating the CMD_SYNC, though we might well end up back
3909ce27afcSJean-Philippe Brucker 		 * here since the ATC invalidation may still be pending.
3919ce27afcSJean-Philippe Brucker 		 */
3929ce27afcSJean-Philippe Brucker 		return;
393a0d5c04cSWill Deacon 	case CMDQ_ERR_CERROR_ILL_IDX:
394a0d5c04cSWill Deacon 	default:
395a0d5c04cSWill Deacon 		break;
39648ec83bcSWill Deacon 	}
39748ec83bcSWill Deacon 
39848ec83bcSWill Deacon 	/*
39948ec83bcSWill Deacon 	 * We may have concurrent producers, so we need to be careful
40048ec83bcSWill Deacon 	 * not to touch any of the shadow cmdq state.
40148ec83bcSWill Deacon 	 */
402aea2037eSWill Deacon 	queue_read(cmd, Q_ENT(q, cons), q->ent_dwords);
40348ec83bcSWill Deacon 	dev_err(smmu->dev, "skipping command in error state:\n");
40448ec83bcSWill Deacon 	for (i = 0; i < ARRAY_SIZE(cmd); ++i)
40548ec83bcSWill Deacon 		dev_err(smmu->dev, "\t0x%016llx\n", (unsigned long long)cmd[i]);
40648ec83bcSWill Deacon 
40748ec83bcSWill Deacon 	/* Convert the erroneous command into a CMD_SYNC */
40848ec83bcSWill Deacon 	if (arm_smmu_cmdq_build_cmd(cmd, &cmd_sync)) {
40948ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to convert to CMD_SYNC\n");
41048ec83bcSWill Deacon 		return;
41148ec83bcSWill Deacon 	}
41248ec83bcSWill Deacon 
413aea2037eSWill Deacon 	queue_write(Q_ENT(q, cons), cmd, q->ent_dwords);
41448ec83bcSWill Deacon }
41548ec83bcSWill Deacon 
416587e6c10SWill Deacon /*
417587e6c10SWill Deacon  * Command queue locking.
418587e6c10SWill Deacon  * This is a form of bastardised rwlock with the following major changes:
419587e6c10SWill Deacon  *
420587e6c10SWill Deacon  * - The only LOCK routines are exclusive_trylock() and shared_lock().
421587e6c10SWill Deacon  *   Neither have barrier semantics, and instead provide only a control
422587e6c10SWill Deacon  *   dependency.
423587e6c10SWill Deacon  *
424587e6c10SWill Deacon  * - The UNLOCK routines are supplemented with shared_tryunlock(), which
425587e6c10SWill Deacon  *   fails if the caller appears to be the last lock holder (yes, this is
426587e6c10SWill Deacon  *   racy). All successful UNLOCK routines have RELEASE semantics.
427587e6c10SWill Deacon  */
428587e6c10SWill Deacon static void arm_smmu_cmdq_shared_lock(struct arm_smmu_cmdq *cmdq)
4292f657addSRobin Murphy {
430587e6c10SWill Deacon 	int val;
4312f657addSRobin Murphy 
432587e6c10SWill Deacon 	/*
433587e6c10SWill Deacon 	 * We can try to avoid the cmpxchg() loop by simply incrementing the
434587e6c10SWill Deacon 	 * lock counter. When held in exclusive state, the lock counter is set
435587e6c10SWill Deacon 	 * to INT_MIN so these increments won't hurt as the value will remain
436587e6c10SWill Deacon 	 * negative.
437587e6c10SWill Deacon 	 */
438587e6c10SWill Deacon 	if (atomic_fetch_inc_relaxed(&cmdq->lock) >= 0)
439587e6c10SWill Deacon 		return;
440901510eeSZhen Lei 
441587e6c10SWill Deacon 	do {
442587e6c10SWill Deacon 		val = atomic_cond_read_relaxed(&cmdq->lock, VAL >= 0);
443587e6c10SWill Deacon 	} while (atomic_cmpxchg_relaxed(&cmdq->lock, val, val + 1) != val);
444587e6c10SWill Deacon }
445587e6c10SWill Deacon 
446587e6c10SWill Deacon static void arm_smmu_cmdq_shared_unlock(struct arm_smmu_cmdq *cmdq)
447587e6c10SWill Deacon {
448587e6c10SWill Deacon 	(void)atomic_dec_return_release(&cmdq->lock);
449587e6c10SWill Deacon }
450587e6c10SWill Deacon 
451587e6c10SWill Deacon static bool arm_smmu_cmdq_shared_tryunlock(struct arm_smmu_cmdq *cmdq)
452587e6c10SWill Deacon {
453587e6c10SWill Deacon 	if (atomic_read(&cmdq->lock) == 1)
454587e6c10SWill Deacon 		return false;
455587e6c10SWill Deacon 
456587e6c10SWill Deacon 	arm_smmu_cmdq_shared_unlock(cmdq);
457587e6c10SWill Deacon 	return true;
458587e6c10SWill Deacon }
459587e6c10SWill Deacon 
460587e6c10SWill Deacon #define arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags)		\
461587e6c10SWill Deacon ({									\
462587e6c10SWill Deacon 	bool __ret;							\
463587e6c10SWill Deacon 	local_irq_save(flags);						\
464587e6c10SWill Deacon 	__ret = !atomic_cmpxchg_relaxed(&cmdq->lock, 0, INT_MIN);	\
465587e6c10SWill Deacon 	if (!__ret)							\
466587e6c10SWill Deacon 		local_irq_restore(flags);				\
467587e6c10SWill Deacon 	__ret;								\
468587e6c10SWill Deacon })
469587e6c10SWill Deacon 
470587e6c10SWill Deacon #define arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags)		\
471587e6c10SWill Deacon ({									\
472587e6c10SWill Deacon 	atomic_set_release(&cmdq->lock, 0);				\
473587e6c10SWill Deacon 	local_irq_restore(flags);					\
474587e6c10SWill Deacon })
475587e6c10SWill Deacon 
476587e6c10SWill Deacon 
477587e6c10SWill Deacon /*
478587e6c10SWill Deacon  * Command queue insertion.
479587e6c10SWill Deacon  * This is made fiddly by our attempts to achieve some sort of scalability
480587e6c10SWill Deacon  * since there is one queue shared amongst all of the CPUs in the system.  If
481587e6c10SWill Deacon  * you like mixed-size concurrency, dependency ordering and relaxed atomics,
482587e6c10SWill Deacon  * then you'll *love* this monstrosity.
483587e6c10SWill Deacon  *
484587e6c10SWill Deacon  * The basic idea is to split the queue up into ranges of commands that are
485587e6c10SWill Deacon  * owned by a given CPU; the owner may not have written all of the commands
486587e6c10SWill Deacon  * itself, but is responsible for advancing the hardware prod pointer when
487587e6c10SWill Deacon  * the time comes. The algorithm is roughly:
488587e6c10SWill Deacon  *
489587e6c10SWill Deacon  * 	1. Allocate some space in the queue. At this point we also discover
490587e6c10SWill Deacon  *	   whether the head of the queue is currently owned by another CPU,
491587e6c10SWill Deacon  *	   or whether we are the owner.
492587e6c10SWill Deacon  *
493587e6c10SWill Deacon  *	2. Write our commands into our allocated slots in the queue.
494587e6c10SWill Deacon  *
495587e6c10SWill Deacon  *	3. Mark our slots as valid in arm_smmu_cmdq.valid_map.
496587e6c10SWill Deacon  *
497587e6c10SWill Deacon  *	4. If we are an owner:
498587e6c10SWill Deacon  *		a. Wait for the previous owner to finish.
499587e6c10SWill Deacon  *		b. Mark the queue head as unowned, which tells us the range
500587e6c10SWill Deacon  *		   that we are responsible for publishing.
501587e6c10SWill Deacon  *		c. Wait for all commands in our owned range to become valid.
502587e6c10SWill Deacon  *		d. Advance the hardware prod pointer.
503587e6c10SWill Deacon  *		e. Tell the next owner we've finished.
504587e6c10SWill Deacon  *
505587e6c10SWill Deacon  *	5. If we are inserting a CMD_SYNC (we may or may not have been an
506587e6c10SWill Deacon  *	   owner), then we need to stick around until it has completed:
507587e6c10SWill Deacon  *		a. If we have MSIs, the SMMU can write back into the CMD_SYNC
508587e6c10SWill Deacon  *		   to clear the first 4 bytes.
509587e6c10SWill Deacon  *		b. Otherwise, we spin waiting for the hardware cons pointer to
510587e6c10SWill Deacon  *		   advance past our command.
511587e6c10SWill Deacon  *
512587e6c10SWill Deacon  * The devil is in the details, particularly the use of locking for handling
513587e6c10SWill Deacon  * SYNC completion and freeing up space in the queue before we think that it is
514587e6c10SWill Deacon  * full.
515587e6c10SWill Deacon  */
516587e6c10SWill Deacon static void __arm_smmu_cmdq_poll_set_valid_map(struct arm_smmu_cmdq *cmdq,
517587e6c10SWill Deacon 					       u32 sprod, u32 eprod, bool set)
518587e6c10SWill Deacon {
519587e6c10SWill Deacon 	u32 swidx, sbidx, ewidx, ebidx;
520587e6c10SWill Deacon 	struct arm_smmu_ll_queue llq = {
521587e6c10SWill Deacon 		.max_n_shift	= cmdq->q.llq.max_n_shift,
522587e6c10SWill Deacon 		.prod		= sprod,
523587e6c10SWill Deacon 	};
524587e6c10SWill Deacon 
525587e6c10SWill Deacon 	ewidx = BIT_WORD(Q_IDX(&llq, eprod));
526587e6c10SWill Deacon 	ebidx = Q_IDX(&llq, eprod) % BITS_PER_LONG;
527587e6c10SWill Deacon 
528587e6c10SWill Deacon 	while (llq.prod != eprod) {
529587e6c10SWill Deacon 		unsigned long mask;
530587e6c10SWill Deacon 		atomic_long_t *ptr;
531587e6c10SWill Deacon 		u32 limit = BITS_PER_LONG;
532587e6c10SWill Deacon 
533587e6c10SWill Deacon 		swidx = BIT_WORD(Q_IDX(&llq, llq.prod));
534587e6c10SWill Deacon 		sbidx = Q_IDX(&llq, llq.prod) % BITS_PER_LONG;
535587e6c10SWill Deacon 
536587e6c10SWill Deacon 		ptr = &cmdq->valid_map[swidx];
537587e6c10SWill Deacon 
538587e6c10SWill Deacon 		if ((swidx == ewidx) && (sbidx < ebidx))
539587e6c10SWill Deacon 			limit = ebidx;
540587e6c10SWill Deacon 
541587e6c10SWill Deacon 		mask = GENMASK(limit - 1, sbidx);
542587e6c10SWill Deacon 
543587e6c10SWill Deacon 		/*
544587e6c10SWill Deacon 		 * The valid bit is the inverse of the wrap bit. This means
545587e6c10SWill Deacon 		 * that a zero-initialised queue is invalid and, after marking
546587e6c10SWill Deacon 		 * all entries as valid, they become invalid again when we
547587e6c10SWill Deacon 		 * wrap.
548587e6c10SWill Deacon 		 */
549587e6c10SWill Deacon 		if (set) {
550587e6c10SWill Deacon 			atomic_long_xor(mask, ptr);
551587e6c10SWill Deacon 		} else { /* Poll */
552587e6c10SWill Deacon 			unsigned long valid;
553587e6c10SWill Deacon 
554587e6c10SWill Deacon 			valid = (ULONG_MAX + !!Q_WRP(&llq, llq.prod)) & mask;
555587e6c10SWill Deacon 			atomic_long_cond_read_relaxed(ptr, (VAL & mask) == valid);
556587e6c10SWill Deacon 		}
557587e6c10SWill Deacon 
558587e6c10SWill Deacon 		llq.prod = queue_inc_prod_n(&llq, limit - sbidx);
559587e6c10SWill Deacon 	}
560587e6c10SWill Deacon }
561587e6c10SWill Deacon 
562587e6c10SWill Deacon /* Mark all entries in the range [sprod, eprod) as valid */
563587e6c10SWill Deacon static void arm_smmu_cmdq_set_valid_map(struct arm_smmu_cmdq *cmdq,
564587e6c10SWill Deacon 					u32 sprod, u32 eprod)
565587e6c10SWill Deacon {
566587e6c10SWill Deacon 	__arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, true);
567587e6c10SWill Deacon }
568587e6c10SWill Deacon 
569587e6c10SWill Deacon /* Wait for all entries in the range [sprod, eprod) to become valid */
570587e6c10SWill Deacon static void arm_smmu_cmdq_poll_valid_map(struct arm_smmu_cmdq *cmdq,
571587e6c10SWill Deacon 					 u32 sprod, u32 eprod)
572587e6c10SWill Deacon {
573587e6c10SWill Deacon 	__arm_smmu_cmdq_poll_set_valid_map(cmdq, sprod, eprod, false);
574587e6c10SWill Deacon }
575587e6c10SWill Deacon 
576587e6c10SWill Deacon /* Wait for the command queue to become non-full */
577587e6c10SWill Deacon static int arm_smmu_cmdq_poll_until_not_full(struct arm_smmu_device *smmu,
578587e6c10SWill Deacon 					     struct arm_smmu_ll_queue *llq)
579587e6c10SWill Deacon {
580587e6c10SWill Deacon 	unsigned long flags;
581587e6c10SWill Deacon 	struct arm_smmu_queue_poll qp;
582587e6c10SWill Deacon 	struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
583587e6c10SWill Deacon 	int ret = 0;
584587e6c10SWill Deacon 
585587e6c10SWill Deacon 	/*
586587e6c10SWill Deacon 	 * Try to update our copy of cons by grabbing exclusive cmdq access. If
587587e6c10SWill Deacon 	 * that fails, spin until somebody else updates it for us.
588587e6c10SWill Deacon 	 */
589587e6c10SWill Deacon 	if (arm_smmu_cmdq_exclusive_trylock_irqsave(cmdq, flags)) {
590587e6c10SWill Deacon 		WRITE_ONCE(cmdq->q.llq.cons, readl_relaxed(cmdq->q.cons_reg));
591587e6c10SWill Deacon 		arm_smmu_cmdq_exclusive_unlock_irqrestore(cmdq, flags);
592587e6c10SWill Deacon 		llq->val = READ_ONCE(cmdq->q.llq.val);
593587e6c10SWill Deacon 		return 0;
594587e6c10SWill Deacon 	}
595587e6c10SWill Deacon 
596587e6c10SWill Deacon 	queue_poll_init(smmu, &qp);
597587e6c10SWill Deacon 	do {
598587e6c10SWill Deacon 		llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
599587e6c10SWill Deacon 		if (!queue_full(llq))
600587e6c10SWill Deacon 			break;
601587e6c10SWill Deacon 
602587e6c10SWill Deacon 		ret = queue_poll(&qp);
603587e6c10SWill Deacon 	} while (!ret);
604587e6c10SWill Deacon 
605587e6c10SWill Deacon 	return ret;
606587e6c10SWill Deacon }
607587e6c10SWill Deacon 
608587e6c10SWill Deacon /*
609587e6c10SWill Deacon  * Wait until the SMMU signals a CMD_SYNC completion MSI.
610587e6c10SWill Deacon  * Must be called with the cmdq lock held in some capacity.
611587e6c10SWill Deacon  */
612587e6c10SWill Deacon static int __arm_smmu_cmdq_poll_until_msi(struct arm_smmu_device *smmu,
613587e6c10SWill Deacon 					  struct arm_smmu_ll_queue *llq)
614587e6c10SWill Deacon {
615587e6c10SWill Deacon 	int ret = 0;
616587e6c10SWill Deacon 	struct arm_smmu_queue_poll qp;
617587e6c10SWill Deacon 	struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
618587e6c10SWill Deacon 	u32 *cmd = (u32 *)(Q_ENT(&cmdq->q, llq->prod));
619587e6c10SWill Deacon 
620587e6c10SWill Deacon 	queue_poll_init(smmu, &qp);
621587e6c10SWill Deacon 
622587e6c10SWill Deacon 	/*
623587e6c10SWill Deacon 	 * The MSI won't generate an event, since it's being written back
624587e6c10SWill Deacon 	 * into the command queue.
625587e6c10SWill Deacon 	 */
626587e6c10SWill Deacon 	qp.wfe = false;
627587e6c10SWill Deacon 	smp_cond_load_relaxed(cmd, !VAL || (ret = queue_poll(&qp)));
628587e6c10SWill Deacon 	llq->cons = ret ? llq->prod : queue_inc_prod_n(llq, 1);
629587e6c10SWill Deacon 	return ret;
630587e6c10SWill Deacon }
631587e6c10SWill Deacon 
632587e6c10SWill Deacon /*
633587e6c10SWill Deacon  * Wait until the SMMU cons index passes llq->prod.
634587e6c10SWill Deacon  * Must be called with the cmdq lock held in some capacity.
635587e6c10SWill Deacon  */
636587e6c10SWill Deacon static int __arm_smmu_cmdq_poll_until_consumed(struct arm_smmu_device *smmu,
637587e6c10SWill Deacon 					       struct arm_smmu_ll_queue *llq)
638587e6c10SWill Deacon {
639587e6c10SWill Deacon 	struct arm_smmu_queue_poll qp;
640587e6c10SWill Deacon 	struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
641587e6c10SWill Deacon 	u32 prod = llq->prod;
642587e6c10SWill Deacon 	int ret = 0;
643587e6c10SWill Deacon 
644587e6c10SWill Deacon 	queue_poll_init(smmu, &qp);
645587e6c10SWill Deacon 	llq->val = READ_ONCE(smmu->cmdq.q.llq.val);
646587e6c10SWill Deacon 	do {
647587e6c10SWill Deacon 		if (queue_consumed(llq, prod))
648587e6c10SWill Deacon 			break;
649587e6c10SWill Deacon 
650587e6c10SWill Deacon 		ret = queue_poll(&qp);
651587e6c10SWill Deacon 
652587e6c10SWill Deacon 		/*
653587e6c10SWill Deacon 		 * This needs to be a readl() so that our subsequent call
654587e6c10SWill Deacon 		 * to arm_smmu_cmdq_shared_tryunlock() can fail accurately.
655587e6c10SWill Deacon 		 *
656587e6c10SWill Deacon 		 * Specifically, we need to ensure that we observe all
657587e6c10SWill Deacon 		 * shared_lock()s by other CMD_SYNCs that share our owner,
658587e6c10SWill Deacon 		 * so that a failing call to tryunlock() means that we're
659587e6c10SWill Deacon 		 * the last one out and therefore we can safely advance
660587e6c10SWill Deacon 		 * cmdq->q.llq.cons. Roughly speaking:
661587e6c10SWill Deacon 		 *
662587e6c10SWill Deacon 		 * CPU 0		CPU1			CPU2 (us)
663587e6c10SWill Deacon 		 *
664587e6c10SWill Deacon 		 * if (sync)
665587e6c10SWill Deacon 		 * 	shared_lock();
666587e6c10SWill Deacon 		 *
667587e6c10SWill Deacon 		 * dma_wmb();
668587e6c10SWill Deacon 		 * set_valid_map();
669587e6c10SWill Deacon 		 *
670587e6c10SWill Deacon 		 * 			if (owner) {
671587e6c10SWill Deacon 		 *				poll_valid_map();
672587e6c10SWill Deacon 		 *				<control dependency>
673587e6c10SWill Deacon 		 *				writel(prod_reg);
674587e6c10SWill Deacon 		 *
675587e6c10SWill Deacon 		 *						readl(cons_reg);
676587e6c10SWill Deacon 		 *						tryunlock();
677587e6c10SWill Deacon 		 *
678587e6c10SWill Deacon 		 * Requires us to see CPU 0's shared_lock() acquisition.
679587e6c10SWill Deacon 		 */
680587e6c10SWill Deacon 		llq->cons = readl(cmdq->q.cons_reg);
681587e6c10SWill Deacon 	} while (!ret);
682587e6c10SWill Deacon 
683587e6c10SWill Deacon 	return ret;
684587e6c10SWill Deacon }
685587e6c10SWill Deacon 
686587e6c10SWill Deacon static int arm_smmu_cmdq_poll_until_sync(struct arm_smmu_device *smmu,
687587e6c10SWill Deacon 					 struct arm_smmu_ll_queue *llq)
688587e6c10SWill Deacon {
689bd07a20aSBarry Song 	if (smmu->options & ARM_SMMU_OPT_MSIPOLL)
690587e6c10SWill Deacon 		return __arm_smmu_cmdq_poll_until_msi(smmu, llq);
691587e6c10SWill Deacon 
692587e6c10SWill Deacon 	return __arm_smmu_cmdq_poll_until_consumed(smmu, llq);
693587e6c10SWill Deacon }
694587e6c10SWill Deacon 
695587e6c10SWill Deacon static void arm_smmu_cmdq_write_entries(struct arm_smmu_cmdq *cmdq, u64 *cmds,
696587e6c10SWill Deacon 					u32 prod, int n)
697587e6c10SWill Deacon {
698587e6c10SWill Deacon 	int i;
699587e6c10SWill Deacon 	struct arm_smmu_ll_queue llq = {
700587e6c10SWill Deacon 		.max_n_shift	= cmdq->q.llq.max_n_shift,
701587e6c10SWill Deacon 		.prod		= prod,
702587e6c10SWill Deacon 	};
703587e6c10SWill Deacon 
704587e6c10SWill Deacon 	for (i = 0; i < n; ++i) {
705587e6c10SWill Deacon 		u64 *cmd = &cmds[i * CMDQ_ENT_DWORDS];
706587e6c10SWill Deacon 
707587e6c10SWill Deacon 		prod = queue_inc_prod_n(&llq, i);
708587e6c10SWill Deacon 		queue_write(Q_ENT(&cmdq->q, prod), cmd, CMDQ_ENT_DWORDS);
709587e6c10SWill Deacon 	}
710587e6c10SWill Deacon }
711587e6c10SWill Deacon 
71205cbaf4dSWill Deacon /*
71305cbaf4dSWill Deacon  * This is the actual insertion function, and provides the following
71405cbaf4dSWill Deacon  * ordering guarantees to callers:
71505cbaf4dSWill Deacon  *
71605cbaf4dSWill Deacon  * - There is a dma_wmb() before publishing any commands to the queue.
71705cbaf4dSWill Deacon  *   This can be relied upon to order prior writes to data structures
71805cbaf4dSWill Deacon  *   in memory (such as a CD or an STE) before the command.
71905cbaf4dSWill Deacon  *
72005cbaf4dSWill Deacon  * - On completion of a CMD_SYNC, there is a control dependency.
72105cbaf4dSWill Deacon  *   This can be relied upon to order subsequent writes to memory (e.g.
72205cbaf4dSWill Deacon  *   freeing an IOVA) after completion of the CMD_SYNC.
72305cbaf4dSWill Deacon  *
72405cbaf4dSWill Deacon  * - Command insertion is totally ordered, so if two CPUs each race to
72505cbaf4dSWill Deacon  *   insert their own list of commands then all of the commands from one
72605cbaf4dSWill Deacon  *   CPU will appear before any of the commands from the other CPU.
72705cbaf4dSWill Deacon  */
728587e6c10SWill Deacon static int arm_smmu_cmdq_issue_cmdlist(struct arm_smmu_device *smmu,
729587e6c10SWill Deacon 				       u64 *cmds, int n, bool sync)
730587e6c10SWill Deacon {
731587e6c10SWill Deacon 	u64 cmd_sync[CMDQ_ENT_DWORDS];
732587e6c10SWill Deacon 	u32 prod;
733587e6c10SWill Deacon 	unsigned long flags;
734587e6c10SWill Deacon 	bool owner;
735587e6c10SWill Deacon 	struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
736587e6c10SWill Deacon 	struct arm_smmu_ll_queue llq = {
737587e6c10SWill Deacon 		.max_n_shift = cmdq->q.llq.max_n_shift,
738587e6c10SWill Deacon 	}, head = llq;
739587e6c10SWill Deacon 	int ret = 0;
740587e6c10SWill Deacon 
741587e6c10SWill Deacon 	/* 1. Allocate some space in the queue */
742587e6c10SWill Deacon 	local_irq_save(flags);
743587e6c10SWill Deacon 	llq.val = READ_ONCE(cmdq->q.llq.val);
744587e6c10SWill Deacon 	do {
745587e6c10SWill Deacon 		u64 old;
746587e6c10SWill Deacon 
747587e6c10SWill Deacon 		while (!queue_has_space(&llq, n + sync)) {
748587e6c10SWill Deacon 			local_irq_restore(flags);
749587e6c10SWill Deacon 			if (arm_smmu_cmdq_poll_until_not_full(smmu, &llq))
7502f657addSRobin Murphy 				dev_err_ratelimited(smmu->dev, "CMDQ timeout\n");
751587e6c10SWill Deacon 			local_irq_save(flags);
752587e6c10SWill Deacon 		}
753587e6c10SWill Deacon 
754587e6c10SWill Deacon 		head.cons = llq.cons;
755587e6c10SWill Deacon 		head.prod = queue_inc_prod_n(&llq, n + sync) |
756587e6c10SWill Deacon 					     CMDQ_PROD_OWNED_FLAG;
757587e6c10SWill Deacon 
758587e6c10SWill Deacon 		old = cmpxchg_relaxed(&cmdq->q.llq.val, llq.val, head.val);
759587e6c10SWill Deacon 		if (old == llq.val)
760587e6c10SWill Deacon 			break;
761587e6c10SWill Deacon 
762587e6c10SWill Deacon 		llq.val = old;
763587e6c10SWill Deacon 	} while (1);
764587e6c10SWill Deacon 	owner = !(llq.prod & CMDQ_PROD_OWNED_FLAG);
765587e6c10SWill Deacon 	head.prod &= ~CMDQ_PROD_OWNED_FLAG;
766587e6c10SWill Deacon 	llq.prod &= ~CMDQ_PROD_OWNED_FLAG;
767587e6c10SWill Deacon 
768587e6c10SWill Deacon 	/*
769587e6c10SWill Deacon 	 * 2. Write our commands into the queue
770587e6c10SWill Deacon 	 * Dependency ordering from the cmpxchg() loop above.
771587e6c10SWill Deacon 	 */
772587e6c10SWill Deacon 	arm_smmu_cmdq_write_entries(cmdq, cmds, llq.prod, n);
773587e6c10SWill Deacon 	if (sync) {
774587e6c10SWill Deacon 		prod = queue_inc_prod_n(&llq, n);
775587e6c10SWill Deacon 		arm_smmu_cmdq_build_sync_cmd(cmd_sync, smmu, prod);
776587e6c10SWill Deacon 		queue_write(Q_ENT(&cmdq->q, prod), cmd_sync, CMDQ_ENT_DWORDS);
777587e6c10SWill Deacon 
778587e6c10SWill Deacon 		/*
779587e6c10SWill Deacon 		 * In order to determine completion of our CMD_SYNC, we must
780587e6c10SWill Deacon 		 * ensure that the queue can't wrap twice without us noticing.
781587e6c10SWill Deacon 		 * We achieve that by taking the cmdq lock as shared before
782587e6c10SWill Deacon 		 * marking our slot as valid.
783587e6c10SWill Deacon 		 */
784587e6c10SWill Deacon 		arm_smmu_cmdq_shared_lock(cmdq);
785587e6c10SWill Deacon 	}
786587e6c10SWill Deacon 
787587e6c10SWill Deacon 	/* 3. Mark our slots as valid, ensuring commands are visible first */
788587e6c10SWill Deacon 	dma_wmb();
789587e6c10SWill Deacon 	arm_smmu_cmdq_set_valid_map(cmdq, llq.prod, head.prod);
790587e6c10SWill Deacon 
791587e6c10SWill Deacon 	/* 4. If we are the owner, take control of the SMMU hardware */
792587e6c10SWill Deacon 	if (owner) {
793587e6c10SWill Deacon 		/* a. Wait for previous owner to finish */
794587e6c10SWill Deacon 		atomic_cond_read_relaxed(&cmdq->owner_prod, VAL == llq.prod);
795587e6c10SWill Deacon 
796587e6c10SWill Deacon 		/* b. Stop gathering work by clearing the owned flag */
797587e6c10SWill Deacon 		prod = atomic_fetch_andnot_relaxed(CMDQ_PROD_OWNED_FLAG,
798587e6c10SWill Deacon 						   &cmdq->q.llq.atomic.prod);
799587e6c10SWill Deacon 		prod &= ~CMDQ_PROD_OWNED_FLAG;
800587e6c10SWill Deacon 
801587e6c10SWill Deacon 		/*
802587e6c10SWill Deacon 		 * c. Wait for any gathered work to be written to the queue.
803587e6c10SWill Deacon 		 * Note that we read our own entries so that we have the control
804587e6c10SWill Deacon 		 * dependency required by (d).
805587e6c10SWill Deacon 		 */
806587e6c10SWill Deacon 		arm_smmu_cmdq_poll_valid_map(cmdq, llq.prod, prod);
807587e6c10SWill Deacon 
808587e6c10SWill Deacon 		/*
809587e6c10SWill Deacon 		 * d. Advance the hardware prod pointer
810587e6c10SWill Deacon 		 * Control dependency ordering from the entries becoming valid.
811587e6c10SWill Deacon 		 */
812587e6c10SWill Deacon 		writel_relaxed(prod, cmdq->q.prod_reg);
813587e6c10SWill Deacon 
814587e6c10SWill Deacon 		/*
815587e6c10SWill Deacon 		 * e. Tell the next owner we're done
816587e6c10SWill Deacon 		 * Make sure we've updated the hardware first, so that we don't
817587e6c10SWill Deacon 		 * race to update prod and potentially move it backwards.
818587e6c10SWill Deacon 		 */
819587e6c10SWill Deacon 		atomic_set_release(&cmdq->owner_prod, prod);
820587e6c10SWill Deacon 	}
821587e6c10SWill Deacon 
822587e6c10SWill Deacon 	/* 5. If we are inserting a CMD_SYNC, we must wait for it to complete */
823587e6c10SWill Deacon 	if (sync) {
824587e6c10SWill Deacon 		llq.prod = queue_inc_prod_n(&llq, n);
825587e6c10SWill Deacon 		ret = arm_smmu_cmdq_poll_until_sync(smmu, &llq);
826587e6c10SWill Deacon 		if (ret) {
827587e6c10SWill Deacon 			dev_err_ratelimited(smmu->dev,
828587e6c10SWill Deacon 					    "CMD_SYNC timeout at 0x%08x [hwprod 0x%08x, hwcons 0x%08x]\n",
829587e6c10SWill Deacon 					    llq.prod,
830587e6c10SWill Deacon 					    readl_relaxed(cmdq->q.prod_reg),
831587e6c10SWill Deacon 					    readl_relaxed(cmdq->q.cons_reg));
832587e6c10SWill Deacon 		}
833587e6c10SWill Deacon 
834587e6c10SWill Deacon 		/*
83549fbb250SJohn Garry 		 * Try to unlock the cmdq lock. This will fail if we're the last
836587e6c10SWill Deacon 		 * reader, in which case we can safely update cmdq->q.llq.cons
837587e6c10SWill Deacon 		 */
838587e6c10SWill Deacon 		if (!arm_smmu_cmdq_shared_tryunlock(cmdq)) {
839587e6c10SWill Deacon 			WRITE_ONCE(cmdq->q.llq.cons, llq.cons);
840587e6c10SWill Deacon 			arm_smmu_cmdq_shared_unlock(cmdq);
8412f657addSRobin Murphy 		}
8422f657addSRobin Murphy 	}
8432f657addSRobin Murphy 
844587e6c10SWill Deacon 	local_irq_restore(flags);
845587e6c10SWill Deacon 	return ret;
846587e6c10SWill Deacon }
847587e6c10SWill Deacon 
848587e6c10SWill Deacon static int arm_smmu_cmdq_issue_cmd(struct arm_smmu_device *smmu,
84948ec83bcSWill Deacon 				   struct arm_smmu_cmdq_ent *ent)
85048ec83bcSWill Deacon {
85148ec83bcSWill Deacon 	u64 cmd[CMDQ_ENT_DWORDS];
85248ec83bcSWill Deacon 
85348ec83bcSWill Deacon 	if (arm_smmu_cmdq_build_cmd(cmd, ent)) {
85448ec83bcSWill Deacon 		dev_warn(smmu->dev, "ignoring unknown CMDQ opcode 0x%x\n",
85548ec83bcSWill Deacon 			 ent->opcode);
856587e6c10SWill Deacon 		return -EINVAL;
85748ec83bcSWill Deacon 	}
85848ec83bcSWill Deacon 
859587e6c10SWill Deacon 	return arm_smmu_cmdq_issue_cmdlist(smmu, cmd, 1, false);
86049806599SWill Deacon }
86149806599SWill Deacon 
8629ce27afcSJean-Philippe Brucker static int arm_smmu_cmdq_issue_sync(struct arm_smmu_device *smmu)
86349806599SWill Deacon {
864587e6c10SWill Deacon 	return arm_smmu_cmdq_issue_cmdlist(smmu, NULL, 0, true);
86548ec83bcSWill Deacon }
86648ec83bcSWill Deacon 
8674ce8da45SJean-Philippe Brucker static void arm_smmu_cmdq_batch_add(struct arm_smmu_device *smmu,
8684ce8da45SJean-Philippe Brucker 				    struct arm_smmu_cmdq_batch *cmds,
8694ce8da45SJean-Philippe Brucker 				    struct arm_smmu_cmdq_ent *cmd)
8704ce8da45SJean-Philippe Brucker {
8714ce8da45SJean-Philippe Brucker 	if (cmds->num == CMDQ_BATCH_ENTRIES) {
8724ce8da45SJean-Philippe Brucker 		arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, false);
8734ce8da45SJean-Philippe Brucker 		cmds->num = 0;
8744ce8da45SJean-Philippe Brucker 	}
8754ce8da45SJean-Philippe Brucker 	arm_smmu_cmdq_build_cmd(&cmds->cmds[cmds->num * CMDQ_ENT_DWORDS], cmd);
8764ce8da45SJean-Philippe Brucker 	cmds->num++;
8774ce8da45SJean-Philippe Brucker }
8784ce8da45SJean-Philippe Brucker 
8794ce8da45SJean-Philippe Brucker static int arm_smmu_cmdq_batch_submit(struct arm_smmu_device *smmu,
8804ce8da45SJean-Philippe Brucker 				      struct arm_smmu_cmdq_batch *cmds)
8814ce8da45SJean-Philippe Brucker {
8824ce8da45SJean-Philippe Brucker 	return arm_smmu_cmdq_issue_cmdlist(smmu, cmds->cmds, cmds->num, true);
8834ce8da45SJean-Philippe Brucker }
8844ce8da45SJean-Philippe Brucker 
885395ad89dSJean-Philippe Brucker static int arm_smmu_page_response(struct device *dev,
886395ad89dSJean-Philippe Brucker 				  struct iommu_fault_event *unused,
887395ad89dSJean-Philippe Brucker 				  struct iommu_page_response *resp)
888395ad89dSJean-Philippe Brucker {
889395ad89dSJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd = {0};
890395ad89dSJean-Philippe Brucker 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
891395ad89dSJean-Philippe Brucker 	int sid = master->streams[0].id;
892395ad89dSJean-Philippe Brucker 
893395ad89dSJean-Philippe Brucker 	if (master->stall_enabled) {
894395ad89dSJean-Philippe Brucker 		cmd.opcode		= CMDQ_OP_RESUME;
895395ad89dSJean-Philippe Brucker 		cmd.resume.sid		= sid;
896395ad89dSJean-Philippe Brucker 		cmd.resume.stag		= resp->grpid;
897395ad89dSJean-Philippe Brucker 		switch (resp->code) {
898395ad89dSJean-Philippe Brucker 		case IOMMU_PAGE_RESP_INVALID:
899395ad89dSJean-Philippe Brucker 		case IOMMU_PAGE_RESP_FAILURE:
900395ad89dSJean-Philippe Brucker 			cmd.resume.resp = CMDQ_RESUME_0_RESP_ABORT;
901395ad89dSJean-Philippe Brucker 			break;
902395ad89dSJean-Philippe Brucker 		case IOMMU_PAGE_RESP_SUCCESS:
903395ad89dSJean-Philippe Brucker 			cmd.resume.resp = CMDQ_RESUME_0_RESP_RETRY;
904395ad89dSJean-Philippe Brucker 			break;
905395ad89dSJean-Philippe Brucker 		default:
906395ad89dSJean-Philippe Brucker 			return -EINVAL;
907395ad89dSJean-Philippe Brucker 		}
908395ad89dSJean-Philippe Brucker 	} else {
909395ad89dSJean-Philippe Brucker 		return -ENODEV;
910395ad89dSJean-Philippe Brucker 	}
911395ad89dSJean-Philippe Brucker 
912395ad89dSJean-Philippe Brucker 	arm_smmu_cmdq_issue_cmd(master->smmu, &cmd);
913395ad89dSJean-Philippe Brucker 	/*
914395ad89dSJean-Philippe Brucker 	 * Don't send a SYNC, it doesn't do anything for RESUME or PRI_RESP.
915395ad89dSJean-Philippe Brucker 	 * RESUME consumption guarantees that the stalled transaction will be
916395ad89dSJean-Philippe Brucker 	 * terminated... at some point in the future. PRI_RESP is fire and
917395ad89dSJean-Philippe Brucker 	 * forget.
918395ad89dSJean-Philippe Brucker 	 */
919395ad89dSJean-Philippe Brucker 
920395ad89dSJean-Philippe Brucker 	return 0;
921395ad89dSJean-Philippe Brucker }
922395ad89dSJean-Philippe Brucker 
92348ec83bcSWill Deacon /* Context descriptor manipulation functions */
9243e630336SJean-Philippe Brucker void arm_smmu_tlb_inv_asid(struct arm_smmu_device *smmu, u16 asid)
9253e630336SJean-Philippe Brucker {
9263e630336SJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd = {
9279111aebfSJean-Philippe Brucker 		.opcode	= smmu->features & ARM_SMMU_FEAT_E2H ?
9289111aebfSJean-Philippe Brucker 			CMDQ_OP_TLBI_EL2_ASID : CMDQ_OP_TLBI_NH_ASID,
9293e630336SJean-Philippe Brucker 		.tlbi.asid = asid,
9303e630336SJean-Philippe Brucker 	};
9313e630336SJean-Philippe Brucker 
9323e630336SJean-Philippe Brucker 	arm_smmu_cmdq_issue_cmd(smmu, &cmd);
9333e630336SJean-Philippe Brucker 	arm_smmu_cmdq_issue_sync(smmu);
9343e630336SJean-Philippe Brucker }
9353e630336SJean-Philippe Brucker 
93687f42391SJean-Philippe Brucker static void arm_smmu_sync_cd(struct arm_smmu_domain *smmu_domain,
93787f42391SJean-Philippe Brucker 			     int ssid, bool leaf)
93848ec83bcSWill Deacon {
93987f42391SJean-Philippe Brucker 	size_t i;
94087f42391SJean-Philippe Brucker 	unsigned long flags;
94187f42391SJean-Philippe Brucker 	struct arm_smmu_master *master;
942edd0351eSJean-Philippe Brucker 	struct arm_smmu_cmdq_batch cmds = {};
94387f42391SJean-Philippe Brucker 	struct arm_smmu_device *smmu = smmu_domain->smmu;
94487f42391SJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd = {
94587f42391SJean-Philippe Brucker 		.opcode	= CMDQ_OP_CFGI_CD,
94687f42391SJean-Philippe Brucker 		.cfgi	= {
94787f42391SJean-Philippe Brucker 			.ssid	= ssid,
94887f42391SJean-Philippe Brucker 			.leaf	= leaf,
94987f42391SJean-Philippe Brucker 		},
95087f42391SJean-Philippe Brucker 	};
95148ec83bcSWill Deacon 
95287f42391SJean-Philippe Brucker 	spin_lock_irqsave(&smmu_domain->devices_lock, flags);
95387f42391SJean-Philippe Brucker 	list_for_each_entry(master, &smmu_domain->devices, domain_head) {
954cdf315f9SJean-Philippe Brucker 		for (i = 0; i < master->num_streams; i++) {
955cdf315f9SJean-Philippe Brucker 			cmd.cfgi.sid = master->streams[i].id;
956edd0351eSJean-Philippe Brucker 			arm_smmu_cmdq_batch_add(smmu, &cmds, &cmd);
95787f42391SJean-Philippe Brucker 		}
95887f42391SJean-Philippe Brucker 	}
95987f42391SJean-Philippe Brucker 	spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
96048ec83bcSWill Deacon 
961edd0351eSJean-Philippe Brucker 	arm_smmu_cmdq_batch_submit(smmu, &cmds);
96248ec83bcSWill Deacon }
96348ec83bcSWill Deacon 
96473af06f5SJean-Philippe Brucker static int arm_smmu_alloc_cd_leaf_table(struct arm_smmu_device *smmu,
96573af06f5SJean-Philippe Brucker 					struct arm_smmu_l1_ctx_desc *l1_desc)
96648ec83bcSWill Deacon {
96773af06f5SJean-Philippe Brucker 	size_t size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
96873af06f5SJean-Philippe Brucker 
96973af06f5SJean-Philippe Brucker 	l1_desc->l2ptr = dmam_alloc_coherent(smmu->dev, size,
97073af06f5SJean-Philippe Brucker 					     &l1_desc->l2ptr_dma, GFP_KERNEL);
97173af06f5SJean-Philippe Brucker 	if (!l1_desc->l2ptr) {
97273af06f5SJean-Philippe Brucker 		dev_warn(smmu->dev,
97373af06f5SJean-Philippe Brucker 			 "failed to allocate context descriptor table\n");
97473af06f5SJean-Philippe Brucker 		return -ENOMEM;
97573af06f5SJean-Philippe Brucker 	}
97673af06f5SJean-Philippe Brucker 	return 0;
97773af06f5SJean-Philippe Brucker }
97873af06f5SJean-Philippe Brucker 
97973af06f5SJean-Philippe Brucker static void arm_smmu_write_cd_l1_desc(__le64 *dst,
98073af06f5SJean-Philippe Brucker 				      struct arm_smmu_l1_ctx_desc *l1_desc)
98173af06f5SJean-Philippe Brucker {
98273af06f5SJean-Philippe Brucker 	u64 val = (l1_desc->l2ptr_dma & CTXDESC_L1_DESC_L2PTR_MASK) |
98373af06f5SJean-Philippe Brucker 		  CTXDESC_L1_DESC_V;
98473af06f5SJean-Philippe Brucker 
98587e5fe5bSJean-Philippe Brucker 	/* See comment in arm_smmu_write_ctx_desc() */
98673af06f5SJean-Philippe Brucker 	WRITE_ONCE(*dst, cpu_to_le64(val));
98773af06f5SJean-Philippe Brucker }
98873af06f5SJean-Philippe Brucker 
98973af06f5SJean-Philippe Brucker static __le64 *arm_smmu_get_cd_ptr(struct arm_smmu_domain *smmu_domain,
99073af06f5SJean-Philippe Brucker 				   u32 ssid)
99173af06f5SJean-Philippe Brucker {
99273af06f5SJean-Philippe Brucker 	__le64 *l1ptr;
99373af06f5SJean-Philippe Brucker 	unsigned int idx;
99473af06f5SJean-Philippe Brucker 	struct arm_smmu_l1_ctx_desc *l1_desc;
99573af06f5SJean-Philippe Brucker 	struct arm_smmu_device *smmu = smmu_domain->smmu;
99673af06f5SJean-Philippe Brucker 	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
99773af06f5SJean-Philippe Brucker 
99873af06f5SJean-Philippe Brucker 	if (smmu_domain->s1_cfg.s1fmt == STRTAB_STE_0_S1FMT_LINEAR)
99973af06f5SJean-Philippe Brucker 		return cdcfg->cdtab + ssid * CTXDESC_CD_DWORDS;
100073af06f5SJean-Philippe Brucker 
100173af06f5SJean-Philippe Brucker 	idx = ssid >> CTXDESC_SPLIT;
100273af06f5SJean-Philippe Brucker 	l1_desc = &cdcfg->l1_desc[idx];
100373af06f5SJean-Philippe Brucker 	if (!l1_desc->l2ptr) {
100473af06f5SJean-Philippe Brucker 		if (arm_smmu_alloc_cd_leaf_table(smmu, l1_desc))
100573af06f5SJean-Philippe Brucker 			return NULL;
100673af06f5SJean-Philippe Brucker 
100773af06f5SJean-Philippe Brucker 		l1ptr = cdcfg->cdtab + idx * CTXDESC_L1_DESC_DWORDS;
100873af06f5SJean-Philippe Brucker 		arm_smmu_write_cd_l1_desc(l1ptr, l1_desc);
100973af06f5SJean-Philippe Brucker 		/* An invalid L1CD can be cached */
101073af06f5SJean-Philippe Brucker 		arm_smmu_sync_cd(smmu_domain, ssid, false);
101173af06f5SJean-Philippe Brucker 	}
101273af06f5SJean-Philippe Brucker 	idx = ssid & (CTXDESC_L2_ENTRIES - 1);
101373af06f5SJean-Philippe Brucker 	return l1_desc->l2ptr + idx * CTXDESC_CD_DWORDS;
101473af06f5SJean-Philippe Brucker }
101573af06f5SJean-Philippe Brucker 
10163e630336SJean-Philippe Brucker int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain, int ssid,
10173e630336SJean-Philippe Brucker 			    struct arm_smmu_ctx_desc *cd)
101887f42391SJean-Philippe Brucker {
101987f42391SJean-Philippe Brucker 	/*
102087f42391SJean-Philippe Brucker 	 * This function handles the following cases:
102187f42391SJean-Philippe Brucker 	 *
102287f42391SJean-Philippe Brucker 	 * (1) Install primary CD, for normal DMA traffic (SSID = 0).
102387f42391SJean-Philippe Brucker 	 * (2) Install a secondary CD, for SID+SSID traffic.
102487f42391SJean-Philippe Brucker 	 * (3) Update ASID of a CD. Atomically write the first 64 bits of the
102587f42391SJean-Philippe Brucker 	 *     CD, then invalidate the old entry and mappings.
102632784a95SJean-Philippe Brucker 	 * (4) Quiesce the context without clearing the valid bit. Disable
102732784a95SJean-Philippe Brucker 	 *     translation, and ignore any translation fault.
102832784a95SJean-Philippe Brucker 	 * (5) Remove a secondary CD.
102987f42391SJean-Philippe Brucker 	 */
103048ec83bcSWill Deacon 	u64 val;
103187f42391SJean-Philippe Brucker 	bool cd_live;
103273af06f5SJean-Philippe Brucker 	__le64 *cdptr;
103373af06f5SJean-Philippe Brucker 
103473af06f5SJean-Philippe Brucker 	if (WARN_ON(ssid >= (1 << smmu_domain->s1_cfg.s1cdmax)))
103573af06f5SJean-Philippe Brucker 		return -E2BIG;
103673af06f5SJean-Philippe Brucker 
103773af06f5SJean-Philippe Brucker 	cdptr = arm_smmu_get_cd_ptr(smmu_domain, ssid);
103873af06f5SJean-Philippe Brucker 	if (!cdptr)
103973af06f5SJean-Philippe Brucker 		return -ENOMEM;
104087f42391SJean-Philippe Brucker 
104187f42391SJean-Philippe Brucker 	val = le64_to_cpu(cdptr[0]);
104287f42391SJean-Philippe Brucker 	cd_live = !!(val & CTXDESC_CD_0_V);
104387f42391SJean-Philippe Brucker 
104432784a95SJean-Philippe Brucker 	if (!cd) { /* (5) */
104587f42391SJean-Philippe Brucker 		val = 0;
104632784a95SJean-Philippe Brucker 	} else if (cd == &quiet_cd) { /* (4) */
104732784a95SJean-Philippe Brucker 		val |= CTXDESC_CD_0_TCR_EPD0;
104887f42391SJean-Philippe Brucker 	} else if (cd_live) { /* (3) */
104987f42391SJean-Philippe Brucker 		val &= ~CTXDESC_CD_0_ASID;
105087f42391SJean-Philippe Brucker 		val |= FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid);
105187f42391SJean-Philippe Brucker 		/*
105287f42391SJean-Philippe Brucker 		 * Until CD+TLB invalidation, both ASIDs may be used for tagging
105387f42391SJean-Philippe Brucker 		 * this substream's traffic
105487f42391SJean-Philippe Brucker 		 */
105587f42391SJean-Philippe Brucker 	} else { /* (1) and (2) */
105687f42391SJean-Philippe Brucker 		cdptr[1] = cpu_to_le64(cd->ttbr & CTXDESC_CD_1_TTB0_MASK);
105787f42391SJean-Philippe Brucker 		cdptr[2] = 0;
105887f42391SJean-Philippe Brucker 		cdptr[3] = cpu_to_le64(cd->mair);
105948ec83bcSWill Deacon 
106048ec83bcSWill Deacon 		/*
106187f42391SJean-Philippe Brucker 		 * STE is live, and the SMMU might read dwords of this CD in any
106287f42391SJean-Philippe Brucker 		 * order. Ensure that it observes valid values before reading
106387f42391SJean-Philippe Brucker 		 * V=1.
106448ec83bcSWill Deacon 		 */
106587f42391SJean-Philippe Brucker 		arm_smmu_sync_cd(smmu_domain, ssid, true);
106687f42391SJean-Philippe Brucker 
106787f42391SJean-Philippe Brucker 		val = cd->tcr |
106848ec83bcSWill Deacon #ifdef __BIG_ENDIAN
106948ec83bcSWill Deacon 			CTXDESC_CD_0_ENDI |
107048ec83bcSWill Deacon #endif
10713f1ce8e8SJean-Philippe Brucker 			CTXDESC_CD_0_R | CTXDESC_CD_0_A |
10723f1ce8e8SJean-Philippe Brucker 			(cd->mm ? 0 : CTXDESC_CD_0_ASET) |
107387f42391SJean-Philippe Brucker 			CTXDESC_CD_0_AA64 |
107487f42391SJean-Philippe Brucker 			FIELD_PREP(CTXDESC_CD_0_ASID, cd->asid) |
107548ec83bcSWill Deacon 			CTXDESC_CD_0_V;
10769cff86fdSYisheng Xie 
1077395ad89dSJean-Philippe Brucker 		if (smmu_domain->stall_enabled)
10789cff86fdSYisheng Xie 			val |= CTXDESC_CD_0_S;
107987f42391SJean-Philippe Brucker 	}
10809cff86fdSYisheng Xie 
108187f42391SJean-Philippe Brucker 	/*
108287f42391SJean-Philippe Brucker 	 * The SMMU accesses 64-bit values atomically. See IHI0070Ca 3.21.3
108387f42391SJean-Philippe Brucker 	 * "Configuration structures and configuration invalidation completion"
108487f42391SJean-Philippe Brucker 	 *
108587f42391SJean-Philippe Brucker 	 *   The size of single-copy atomic reads made by the SMMU is
108687f42391SJean-Philippe Brucker 	 *   IMPLEMENTATION DEFINED but must be at least 64 bits. Any single
108787f42391SJean-Philippe Brucker 	 *   field within an aligned 64-bit span of a structure can be altered
108887f42391SJean-Philippe Brucker 	 *   without first making the structure invalid.
108987f42391SJean-Philippe Brucker 	 */
109087f42391SJean-Philippe Brucker 	WRITE_ONCE(cdptr[0], cpu_to_le64(val));
109187f42391SJean-Philippe Brucker 	arm_smmu_sync_cd(smmu_domain, ssid, true);
109287f42391SJean-Philippe Brucker 	return 0;
109348ec83bcSWill Deacon }
109448ec83bcSWill Deacon 
1095a557aff0SJean-Philippe Brucker static int arm_smmu_alloc_cd_tables(struct arm_smmu_domain *smmu_domain)
1096a557aff0SJean-Philippe Brucker {
109773af06f5SJean-Philippe Brucker 	int ret;
1098a557aff0SJean-Philippe Brucker 	size_t l1size;
109973af06f5SJean-Philippe Brucker 	size_t max_contexts;
1100a557aff0SJean-Philippe Brucker 	struct arm_smmu_device *smmu = smmu_domain->smmu;
1101a557aff0SJean-Philippe Brucker 	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
1102a557aff0SJean-Philippe Brucker 	struct arm_smmu_ctx_desc_cfg *cdcfg = &cfg->cdcfg;
110348ec83bcSWill Deacon 
110473af06f5SJean-Philippe Brucker 	max_contexts = 1 << cfg->s1cdmax;
110587f42391SJean-Philippe Brucker 
110673af06f5SJean-Philippe Brucker 	if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB) ||
110773af06f5SJean-Philippe Brucker 	    max_contexts <= CTXDESC_L2_ENTRIES) {
110873af06f5SJean-Philippe Brucker 		cfg->s1fmt = STRTAB_STE_0_S1FMT_LINEAR;
110973af06f5SJean-Philippe Brucker 		cdcfg->num_l1_ents = max_contexts;
111073af06f5SJean-Philippe Brucker 
111173af06f5SJean-Philippe Brucker 		l1size = max_contexts * (CTXDESC_CD_DWORDS << 3);
111273af06f5SJean-Philippe Brucker 	} else {
111373af06f5SJean-Philippe Brucker 		cfg->s1fmt = STRTAB_STE_0_S1FMT_64K_L2;
111473af06f5SJean-Philippe Brucker 		cdcfg->num_l1_ents = DIV_ROUND_UP(max_contexts,
111573af06f5SJean-Philippe Brucker 						  CTXDESC_L2_ENTRIES);
111673af06f5SJean-Philippe Brucker 
111773af06f5SJean-Philippe Brucker 		cdcfg->l1_desc = devm_kcalloc(smmu->dev, cdcfg->num_l1_ents,
111873af06f5SJean-Philippe Brucker 					      sizeof(*cdcfg->l1_desc),
111973af06f5SJean-Philippe Brucker 					      GFP_KERNEL);
112073af06f5SJean-Philippe Brucker 		if (!cdcfg->l1_desc)
112173af06f5SJean-Philippe Brucker 			return -ENOMEM;
112273af06f5SJean-Philippe Brucker 
112373af06f5SJean-Philippe Brucker 		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
112473af06f5SJean-Philippe Brucker 	}
112573af06f5SJean-Philippe Brucker 
1126a557aff0SJean-Philippe Brucker 	cdcfg->cdtab = dmam_alloc_coherent(smmu->dev, l1size, &cdcfg->cdtab_dma,
1127a557aff0SJean-Philippe Brucker 					   GFP_KERNEL);
1128a557aff0SJean-Philippe Brucker 	if (!cdcfg->cdtab) {
1129a557aff0SJean-Philippe Brucker 		dev_warn(smmu->dev, "failed to allocate context descriptor\n");
113073af06f5SJean-Philippe Brucker 		ret = -ENOMEM;
113173af06f5SJean-Philippe Brucker 		goto err_free_l1;
1132a557aff0SJean-Philippe Brucker 	}
113373af06f5SJean-Philippe Brucker 
1134a557aff0SJean-Philippe Brucker 	return 0;
113573af06f5SJean-Philippe Brucker 
113673af06f5SJean-Philippe Brucker err_free_l1:
113773af06f5SJean-Philippe Brucker 	if (cdcfg->l1_desc) {
113873af06f5SJean-Philippe Brucker 		devm_kfree(smmu->dev, cdcfg->l1_desc);
113973af06f5SJean-Philippe Brucker 		cdcfg->l1_desc = NULL;
114073af06f5SJean-Philippe Brucker 	}
114173af06f5SJean-Philippe Brucker 	return ret;
1142a557aff0SJean-Philippe Brucker }
1143a557aff0SJean-Philippe Brucker 
1144a557aff0SJean-Philippe Brucker static void arm_smmu_free_cd_tables(struct arm_smmu_domain *smmu_domain)
1145a557aff0SJean-Philippe Brucker {
114673af06f5SJean-Philippe Brucker 	int i;
114773af06f5SJean-Philippe Brucker 	size_t size, l1size;
1148a557aff0SJean-Philippe Brucker 	struct arm_smmu_device *smmu = smmu_domain->smmu;
1149a557aff0SJean-Philippe Brucker 	struct arm_smmu_ctx_desc_cfg *cdcfg = &smmu_domain->s1_cfg.cdcfg;
115073af06f5SJean-Philippe Brucker 
115173af06f5SJean-Philippe Brucker 	if (cdcfg->l1_desc) {
115273af06f5SJean-Philippe Brucker 		size = CTXDESC_L2_ENTRIES * (CTXDESC_CD_DWORDS << 3);
115373af06f5SJean-Philippe Brucker 
115473af06f5SJean-Philippe Brucker 		for (i = 0; i < cdcfg->num_l1_ents; i++) {
115573af06f5SJean-Philippe Brucker 			if (!cdcfg->l1_desc[i].l2ptr)
115673af06f5SJean-Philippe Brucker 				continue;
115773af06f5SJean-Philippe Brucker 
115873af06f5SJean-Philippe Brucker 			dmam_free_coherent(smmu->dev, size,
115973af06f5SJean-Philippe Brucker 					   cdcfg->l1_desc[i].l2ptr,
116073af06f5SJean-Philippe Brucker 					   cdcfg->l1_desc[i].l2ptr_dma);
116173af06f5SJean-Philippe Brucker 		}
116273af06f5SJean-Philippe Brucker 		devm_kfree(smmu->dev, cdcfg->l1_desc);
116373af06f5SJean-Philippe Brucker 		cdcfg->l1_desc = NULL;
116473af06f5SJean-Philippe Brucker 
116573af06f5SJean-Philippe Brucker 		l1size = cdcfg->num_l1_ents * (CTXDESC_L1_DESC_DWORDS << 3);
116673af06f5SJean-Philippe Brucker 	} else {
116773af06f5SJean-Philippe Brucker 		l1size = cdcfg->num_l1_ents * (CTXDESC_CD_DWORDS << 3);
116873af06f5SJean-Philippe Brucker 	}
1169a557aff0SJean-Philippe Brucker 
1170a557aff0SJean-Philippe Brucker 	dmam_free_coherent(smmu->dev, l1size, cdcfg->cdtab, cdcfg->cdtab_dma);
1171a557aff0SJean-Philippe Brucker 	cdcfg->cdtab_dma = 0;
1172a557aff0SJean-Philippe Brucker 	cdcfg->cdtab = NULL;
117348ec83bcSWill Deacon }
117448ec83bcSWill Deacon 
11753f1ce8e8SJean-Philippe Brucker bool arm_smmu_free_asid(struct arm_smmu_ctx_desc *cd)
11760299a1a8SJean-Philippe Brucker {
11773f1ce8e8SJean-Philippe Brucker 	bool free;
11783f1ce8e8SJean-Philippe Brucker 	struct arm_smmu_ctx_desc *old_cd;
11790299a1a8SJean-Philippe Brucker 
11803f1ce8e8SJean-Philippe Brucker 	if (!cd->asid)
11813f1ce8e8SJean-Philippe Brucker 		return false;
11823f1ce8e8SJean-Philippe Brucker 
11833f1ce8e8SJean-Philippe Brucker 	free = refcount_dec_and_test(&cd->refs);
11843f1ce8e8SJean-Philippe Brucker 	if (free) {
11853f1ce8e8SJean-Philippe Brucker 		old_cd = xa_erase(&arm_smmu_asid_xa, cd->asid);
11863f1ce8e8SJean-Philippe Brucker 		WARN_ON(old_cd != cd);
11873f1ce8e8SJean-Philippe Brucker 	}
11883f1ce8e8SJean-Philippe Brucker 	return free;
11890299a1a8SJean-Philippe Brucker }
11900299a1a8SJean-Philippe Brucker 
119148ec83bcSWill Deacon /* Stream table manipulation functions */
119248ec83bcSWill Deacon static void
119348ec83bcSWill Deacon arm_smmu_write_strtab_l1_desc(__le64 *dst, struct arm_smmu_strtab_l1_desc *desc)
119448ec83bcSWill Deacon {
119548ec83bcSWill Deacon 	u64 val = 0;
119648ec83bcSWill Deacon 
1197ba08bdcbSRobin Murphy 	val |= FIELD_PREP(STRTAB_L1_DESC_SPAN, desc->span);
11981cf9e54eSRobin Murphy 	val |= desc->l2ptr_dma & STRTAB_L1_DESC_L2PTR_MASK;
119948ec83bcSWill Deacon 
120087e5fe5bSJean-Philippe Brucker 	/* See comment in arm_smmu_write_ctx_desc() */
120187e5fe5bSJean-Philippe Brucker 	WRITE_ONCE(*dst, cpu_to_le64(val));
120248ec83bcSWill Deacon }
120348ec83bcSWill Deacon 
120448ec83bcSWill Deacon static void arm_smmu_sync_ste_for_sid(struct arm_smmu_device *smmu, u32 sid)
120548ec83bcSWill Deacon {
120648ec83bcSWill Deacon 	struct arm_smmu_cmdq_ent cmd = {
120748ec83bcSWill Deacon 		.opcode	= CMDQ_OP_CFGI_STE,
120848ec83bcSWill Deacon 		.cfgi	= {
120948ec83bcSWill Deacon 			.sid	= sid,
121048ec83bcSWill Deacon 			.leaf	= true,
121148ec83bcSWill Deacon 		},
121248ec83bcSWill Deacon 	};
121348ec83bcSWill Deacon 
121448ec83bcSWill Deacon 	arm_smmu_cmdq_issue_cmd(smmu, &cmd);
12152f657addSRobin Murphy 	arm_smmu_cmdq_issue_sync(smmu);
121648ec83bcSWill Deacon }
121748ec83bcSWill Deacon 
12188be39a1aSJean-Philippe Brucker static void arm_smmu_write_strtab_ent(struct arm_smmu_master *master, u32 sid,
12198be39a1aSJean-Philippe Brucker 				      __le64 *dst)
122048ec83bcSWill Deacon {
122148ec83bcSWill Deacon 	/*
122248ec83bcSWill Deacon 	 * This is hideously complicated, but we only really care about
122348ec83bcSWill Deacon 	 * three cases at the moment:
122448ec83bcSWill Deacon 	 *
1225beb3c6a0SWill Deacon 	 * 1. Invalid (all zero) -> bypass/fault (init)
1226beb3c6a0SWill Deacon 	 * 2. Bypass/fault -> translation/bypass (attach)
1227beb3c6a0SWill Deacon 	 * 3. Translation/bypass -> bypass/fault (detach)
122848ec83bcSWill Deacon 	 *
122948ec83bcSWill Deacon 	 * Given that we can't update the STE atomically and the SMMU
123048ec83bcSWill Deacon 	 * doesn't read the thing in a defined order, that leaves us
123148ec83bcSWill Deacon 	 * with the following maintenance requirements:
123248ec83bcSWill Deacon 	 *
123348ec83bcSWill Deacon 	 * 1. Update Config, return (init time STEs aren't live)
123448ec83bcSWill Deacon 	 * 2. Write everything apart from dword 0, sync, write dword 0, sync
123548ec83bcSWill Deacon 	 * 3. Update Config, sync
123648ec83bcSWill Deacon 	 */
123748ec83bcSWill Deacon 	u64 val = le64_to_cpu(dst[0]);
123848ec83bcSWill Deacon 	bool ste_live = false;
12398be39a1aSJean-Philippe Brucker 	struct arm_smmu_device *smmu = NULL;
12408be39a1aSJean-Philippe Brucker 	struct arm_smmu_s1_cfg *s1_cfg = NULL;
12418be39a1aSJean-Philippe Brucker 	struct arm_smmu_s2_cfg *s2_cfg = NULL;
12428be39a1aSJean-Philippe Brucker 	struct arm_smmu_domain *smmu_domain = NULL;
124348ec83bcSWill Deacon 	struct arm_smmu_cmdq_ent prefetch_cmd = {
124448ec83bcSWill Deacon 		.opcode		= CMDQ_OP_PREFETCH_CFG,
124548ec83bcSWill Deacon 		.prefetch	= {
124648ec83bcSWill Deacon 			.sid	= sid,
124748ec83bcSWill Deacon 		},
124848ec83bcSWill Deacon 	};
124948ec83bcSWill Deacon 
12508be39a1aSJean-Philippe Brucker 	if (master) {
12518be39a1aSJean-Philippe Brucker 		smmu_domain = master->domain;
12528be39a1aSJean-Philippe Brucker 		smmu = master->smmu;
12538be39a1aSJean-Philippe Brucker 	}
12548be39a1aSJean-Philippe Brucker 
12558be39a1aSJean-Philippe Brucker 	if (smmu_domain) {
12568be39a1aSJean-Philippe Brucker 		switch (smmu_domain->stage) {
12578be39a1aSJean-Philippe Brucker 		case ARM_SMMU_DOMAIN_S1:
12588be39a1aSJean-Philippe Brucker 			s1_cfg = &smmu_domain->s1_cfg;
12598be39a1aSJean-Philippe Brucker 			break;
12608be39a1aSJean-Philippe Brucker 		case ARM_SMMU_DOMAIN_S2:
12618be39a1aSJean-Philippe Brucker 		case ARM_SMMU_DOMAIN_NESTED:
12628be39a1aSJean-Philippe Brucker 			s2_cfg = &smmu_domain->s2_cfg;
12638be39a1aSJean-Philippe Brucker 			break;
12648be39a1aSJean-Philippe Brucker 		default:
12658be39a1aSJean-Philippe Brucker 			break;
12668be39a1aSJean-Philippe Brucker 		}
12678be39a1aSJean-Philippe Brucker 	}
12688be39a1aSJean-Philippe Brucker 
126948ec83bcSWill Deacon 	if (val & STRTAB_STE_0_V) {
1270ba08bdcbSRobin Murphy 		switch (FIELD_GET(STRTAB_STE_0_CFG, val)) {
127148ec83bcSWill Deacon 		case STRTAB_STE_0_CFG_BYPASS:
127248ec83bcSWill Deacon 			break;
127348ec83bcSWill Deacon 		case STRTAB_STE_0_CFG_S1_TRANS:
127448ec83bcSWill Deacon 		case STRTAB_STE_0_CFG_S2_TRANS:
127548ec83bcSWill Deacon 			ste_live = true;
127648ec83bcSWill Deacon 			break;
12775bc0a116SWill Deacon 		case STRTAB_STE_0_CFG_ABORT:
127811f4fe9bSAnders Roxell 			BUG_ON(!disable_bypass);
12795bc0a116SWill Deacon 			break;
128048ec83bcSWill Deacon 		default:
128148ec83bcSWill Deacon 			BUG(); /* STE corruption */
128248ec83bcSWill Deacon 		}
128348ec83bcSWill Deacon 	}
128448ec83bcSWill Deacon 
1285810871c5SNate Watterson 	/* Nuke the existing STE_0 value, as we're going to rewrite it */
1286beb3c6a0SWill Deacon 	val = STRTAB_STE_0_V;
128748ec83bcSWill Deacon 
1288beb3c6a0SWill Deacon 	/* Bypass/fault */
12898be39a1aSJean-Philippe Brucker 	if (!smmu_domain || !(s1_cfg || s2_cfg)) {
12908be39a1aSJean-Philippe Brucker 		if (!smmu_domain && disable_bypass)
1291ba08bdcbSRobin Murphy 			val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_ABORT);
1292beb3c6a0SWill Deacon 		else
1293ba08bdcbSRobin Murphy 			val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_BYPASS);
1294beb3c6a0SWill Deacon 
129548ec83bcSWill Deacon 		dst[0] = cpu_to_le64(val);
1296ba08bdcbSRobin Murphy 		dst[1] = cpu_to_le64(FIELD_PREP(STRTAB_STE_1_SHCFG,
1297ba08bdcbSRobin Murphy 						STRTAB_STE_1_SHCFG_INCOMING));
129848ec83bcSWill Deacon 		dst[2] = 0; /* Nuke the VMID */
1299704c0382SWill Deacon 		/*
1300704c0382SWill Deacon 		 * The SMMU can perform negative caching, so we must sync
1301704c0382SWill Deacon 		 * the STE regardless of whether the old value was live.
1302704c0382SWill Deacon 		 */
1303704c0382SWill Deacon 		if (smmu)
130448ec83bcSWill Deacon 			arm_smmu_sync_ste_for_sid(smmu, sid);
130548ec83bcSWill Deacon 		return;
130648ec83bcSWill Deacon 	}
130748ec83bcSWill Deacon 
13088be39a1aSJean-Philippe Brucker 	if (s1_cfg) {
13099111aebfSJean-Philippe Brucker 		u64 strw = smmu->features & ARM_SMMU_FEAT_E2H ?
13109111aebfSJean-Philippe Brucker 			STRTAB_STE_1_STRW_EL2 : STRTAB_STE_1_STRW_NSEL1;
13119111aebfSJean-Philippe Brucker 
131248ec83bcSWill Deacon 		BUG_ON(ste_live);
131348ec83bcSWill Deacon 		dst[1] = cpu_to_le64(
131487f42391SJean-Philippe Brucker 			 FIELD_PREP(STRTAB_STE_1_S1DSS, STRTAB_STE_1_S1DSS_SSID0) |
1315ba08bdcbSRobin Murphy 			 FIELD_PREP(STRTAB_STE_1_S1CIR, STRTAB_STE_1_S1C_CACHE_WBRA) |
1316ba08bdcbSRobin Murphy 			 FIELD_PREP(STRTAB_STE_1_S1COR, STRTAB_STE_1_S1C_CACHE_WBRA) |
1317ba08bdcbSRobin Murphy 			 FIELD_PREP(STRTAB_STE_1_S1CSH, ARM_SMMU_SH_ISH) |
13189111aebfSJean-Philippe Brucker 			 FIELD_PREP(STRTAB_STE_1_STRW, strw));
131948ec83bcSWill Deacon 
13209cff86fdSYisheng Xie 		if (smmu->features & ARM_SMMU_FEAT_STALLS &&
1321395ad89dSJean-Philippe Brucker 		    !master->stall_enabled)
13226380be05SPrem Mallappa 			dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
13236380be05SPrem Mallappa 
13247bc4f3faSJean-Philippe Brucker 		val |= (s1_cfg->cdcfg.cdtab_dma & STRTAB_STE_0_S1CTXPTR_MASK) |
132587f42391SJean-Philippe Brucker 			FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S1_TRANS) |
132687f42391SJean-Philippe Brucker 			FIELD_PREP(STRTAB_STE_0_S1CDMAX, s1_cfg->s1cdmax) |
132787f42391SJean-Philippe Brucker 			FIELD_PREP(STRTAB_STE_0_S1FMT, s1_cfg->s1fmt);
132848ec83bcSWill Deacon 	}
132948ec83bcSWill Deacon 
13308be39a1aSJean-Philippe Brucker 	if (s2_cfg) {
133148ec83bcSWill Deacon 		BUG_ON(ste_live);
133248ec83bcSWill Deacon 		dst[2] = cpu_to_le64(
13338be39a1aSJean-Philippe Brucker 			 FIELD_PREP(STRTAB_STE_2_S2VMID, s2_cfg->vmid) |
13348be39a1aSJean-Philippe Brucker 			 FIELD_PREP(STRTAB_STE_2_VTCR, s2_cfg->vtcr) |
133548ec83bcSWill Deacon #ifdef __BIG_ENDIAN
133648ec83bcSWill Deacon 			 STRTAB_STE_2_S2ENDI |
133748ec83bcSWill Deacon #endif
133848ec83bcSWill Deacon 			 STRTAB_STE_2_S2PTW | STRTAB_STE_2_S2AA64 |
133948ec83bcSWill Deacon 			 STRTAB_STE_2_S2R);
134048ec83bcSWill Deacon 
13418be39a1aSJean-Philippe Brucker 		dst[3] = cpu_to_le64(s2_cfg->vttbr & STRTAB_STE_3_S2TTB_MASK);
134248ec83bcSWill Deacon 
1343ba08bdcbSRobin Murphy 		val |= FIELD_PREP(STRTAB_STE_0_CFG, STRTAB_STE_0_CFG_S2_TRANS);
134448ec83bcSWill Deacon 	}
134548ec83bcSWill Deacon 
13469ce27afcSJean-Philippe Brucker 	if (master->ats_enabled)
13479ce27afcSJean-Philippe Brucker 		dst[1] |= cpu_to_le64(FIELD_PREP(STRTAB_STE_1_EATS,
13489ce27afcSJean-Philippe Brucker 						 STRTAB_STE_1_EATS_TRANS));
13499ce27afcSJean-Philippe Brucker 
135048ec83bcSWill Deacon 	arm_smmu_sync_ste_for_sid(smmu, sid);
1351d71e0171SWill Deacon 	/* See comment in arm_smmu_write_ctx_desc() */
1352d71e0171SWill Deacon 	WRITE_ONCE(dst[0], cpu_to_le64(val));
135348ec83bcSWill Deacon 	arm_smmu_sync_ste_for_sid(smmu, sid);
135448ec83bcSWill Deacon 
135548ec83bcSWill Deacon 	/* It's likely that we'll want to use the new STE soon */
13565e92946cSZhen Lei 	if (!(smmu->options & ARM_SMMU_OPT_SKIP_PREFETCH))
135748ec83bcSWill Deacon 		arm_smmu_cmdq_issue_cmd(smmu, &prefetch_cmd);
135848ec83bcSWill Deacon }
135948ec83bcSWill Deacon 
1360376cdf66SJean-Philippe Brucker static void arm_smmu_init_bypass_stes(__le64 *strtab, unsigned int nent)
136148ec83bcSWill Deacon {
136248ec83bcSWill Deacon 	unsigned int i;
136348ec83bcSWill Deacon 
136448ec83bcSWill Deacon 	for (i = 0; i < nent; ++i) {
13658be39a1aSJean-Philippe Brucker 		arm_smmu_write_strtab_ent(NULL, -1, strtab);
136648ec83bcSWill Deacon 		strtab += STRTAB_STE_DWORDS;
136748ec83bcSWill Deacon 	}
136848ec83bcSWill Deacon }
136948ec83bcSWill Deacon 
137048ec83bcSWill Deacon static int arm_smmu_init_l2_strtab(struct arm_smmu_device *smmu, u32 sid)
137148ec83bcSWill Deacon {
137248ec83bcSWill Deacon 	size_t size;
137348ec83bcSWill Deacon 	void *strtab;
137448ec83bcSWill Deacon 	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
137548ec83bcSWill Deacon 	struct arm_smmu_strtab_l1_desc *desc = &cfg->l1_desc[sid >> STRTAB_SPLIT];
137648ec83bcSWill Deacon 
137748ec83bcSWill Deacon 	if (desc->l2ptr)
137848ec83bcSWill Deacon 		return 0;
137948ec83bcSWill Deacon 
138048ec83bcSWill Deacon 	size = 1 << (STRTAB_SPLIT + ilog2(STRTAB_STE_DWORDS) + 3);
138169146e7bSZhen Lei 	strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS];
138248ec83bcSWill Deacon 
138348ec83bcSWill Deacon 	desc->span = STRTAB_SPLIT + 1;
138404fa26c7SWill Deacon 	desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
13859bb9069cSJean-Philippe Brucker 					  GFP_KERNEL);
138648ec83bcSWill Deacon 	if (!desc->l2ptr) {
138748ec83bcSWill Deacon 		dev_err(smmu->dev,
138848ec83bcSWill Deacon 			"failed to allocate l2 stream table for SID %u\n",
138948ec83bcSWill Deacon 			sid);
139048ec83bcSWill Deacon 		return -ENOMEM;
139148ec83bcSWill Deacon 	}
139248ec83bcSWill Deacon 
139348ec83bcSWill Deacon 	arm_smmu_init_bypass_stes(desc->l2ptr, 1 << STRTAB_SPLIT);
139448ec83bcSWill Deacon 	arm_smmu_write_strtab_l1_desc(strtab, desc);
139548ec83bcSWill Deacon 	return 0;
139648ec83bcSWill Deacon }
139748ec83bcSWill Deacon 
1398cdf315f9SJean-Philippe Brucker static struct arm_smmu_master *
1399cdf315f9SJean-Philippe Brucker arm_smmu_find_master(struct arm_smmu_device *smmu, u32 sid)
1400cdf315f9SJean-Philippe Brucker {
1401cdf315f9SJean-Philippe Brucker 	struct rb_node *node;
1402cdf315f9SJean-Philippe Brucker 	struct arm_smmu_stream *stream;
1403cdf315f9SJean-Philippe Brucker 
1404cdf315f9SJean-Philippe Brucker 	lockdep_assert_held(&smmu->streams_mutex);
1405cdf315f9SJean-Philippe Brucker 
1406cdf315f9SJean-Philippe Brucker 	node = smmu->streams.rb_node;
1407cdf315f9SJean-Philippe Brucker 	while (node) {
1408cdf315f9SJean-Philippe Brucker 		stream = rb_entry(node, struct arm_smmu_stream, node);
1409cdf315f9SJean-Philippe Brucker 		if (stream->id < sid)
1410cdf315f9SJean-Philippe Brucker 			node = node->rb_right;
1411cdf315f9SJean-Philippe Brucker 		else if (stream->id > sid)
1412cdf315f9SJean-Philippe Brucker 			node = node->rb_left;
1413cdf315f9SJean-Philippe Brucker 		else
1414cdf315f9SJean-Philippe Brucker 			return stream->master;
1415cdf315f9SJean-Philippe Brucker 	}
1416cdf315f9SJean-Philippe Brucker 
1417cdf315f9SJean-Philippe Brucker 	return NULL;
1418cdf315f9SJean-Philippe Brucker }
1419cdf315f9SJean-Philippe Brucker 
142048ec83bcSWill Deacon /* IRQ and event handlers */
1421395ad89dSJean-Philippe Brucker static int arm_smmu_handle_evt(struct arm_smmu_device *smmu, u64 *evt)
1422395ad89dSJean-Philippe Brucker {
1423395ad89dSJean-Philippe Brucker 	int ret;
1424395ad89dSJean-Philippe Brucker 	u32 reason;
1425395ad89dSJean-Philippe Brucker 	u32 perm = 0;
1426395ad89dSJean-Philippe Brucker 	struct arm_smmu_master *master;
1427395ad89dSJean-Philippe Brucker 	bool ssid_valid = evt[0] & EVTQ_0_SSV;
1428395ad89dSJean-Philippe Brucker 	u32 sid = FIELD_GET(EVTQ_0_SID, evt[0]);
1429395ad89dSJean-Philippe Brucker 	struct iommu_fault_event fault_evt = { };
1430395ad89dSJean-Philippe Brucker 	struct iommu_fault *flt = &fault_evt.fault;
1431395ad89dSJean-Philippe Brucker 
1432395ad89dSJean-Philippe Brucker 	switch (FIELD_GET(EVTQ_0_ID, evt[0])) {
1433395ad89dSJean-Philippe Brucker 	case EVT_ID_TRANSLATION_FAULT:
1434395ad89dSJean-Philippe Brucker 		reason = IOMMU_FAULT_REASON_PTE_FETCH;
1435395ad89dSJean-Philippe Brucker 		break;
1436395ad89dSJean-Philippe Brucker 	case EVT_ID_ADDR_SIZE_FAULT:
1437395ad89dSJean-Philippe Brucker 		reason = IOMMU_FAULT_REASON_OOR_ADDRESS;
1438395ad89dSJean-Philippe Brucker 		break;
1439395ad89dSJean-Philippe Brucker 	case EVT_ID_ACCESS_FAULT:
1440395ad89dSJean-Philippe Brucker 		reason = IOMMU_FAULT_REASON_ACCESS;
1441395ad89dSJean-Philippe Brucker 		break;
1442395ad89dSJean-Philippe Brucker 	case EVT_ID_PERMISSION_FAULT:
1443395ad89dSJean-Philippe Brucker 		reason = IOMMU_FAULT_REASON_PERMISSION;
1444395ad89dSJean-Philippe Brucker 		break;
1445395ad89dSJean-Philippe Brucker 	default:
1446395ad89dSJean-Philippe Brucker 		return -EOPNOTSUPP;
1447395ad89dSJean-Philippe Brucker 	}
1448395ad89dSJean-Philippe Brucker 
1449395ad89dSJean-Philippe Brucker 	/* Stage-2 is always pinned at the moment */
1450395ad89dSJean-Philippe Brucker 	if (evt[1] & EVTQ_1_S2)
1451395ad89dSJean-Philippe Brucker 		return -EFAULT;
1452395ad89dSJean-Philippe Brucker 
1453395ad89dSJean-Philippe Brucker 	if (evt[1] & EVTQ_1_RnW)
1454395ad89dSJean-Philippe Brucker 		perm |= IOMMU_FAULT_PERM_READ;
1455395ad89dSJean-Philippe Brucker 	else
1456395ad89dSJean-Philippe Brucker 		perm |= IOMMU_FAULT_PERM_WRITE;
1457395ad89dSJean-Philippe Brucker 
1458395ad89dSJean-Philippe Brucker 	if (evt[1] & EVTQ_1_InD)
1459395ad89dSJean-Philippe Brucker 		perm |= IOMMU_FAULT_PERM_EXEC;
1460395ad89dSJean-Philippe Brucker 
1461395ad89dSJean-Philippe Brucker 	if (evt[1] & EVTQ_1_PnU)
1462395ad89dSJean-Philippe Brucker 		perm |= IOMMU_FAULT_PERM_PRIV;
1463395ad89dSJean-Philippe Brucker 
1464395ad89dSJean-Philippe Brucker 	if (evt[1] & EVTQ_1_STALL) {
1465395ad89dSJean-Philippe Brucker 		flt->type = IOMMU_FAULT_PAGE_REQ;
1466395ad89dSJean-Philippe Brucker 		flt->prm = (struct iommu_fault_page_request) {
1467395ad89dSJean-Philippe Brucker 			.flags = IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE,
1468395ad89dSJean-Philippe Brucker 			.grpid = FIELD_GET(EVTQ_1_STAG, evt[1]),
1469395ad89dSJean-Philippe Brucker 			.perm = perm,
1470395ad89dSJean-Philippe Brucker 			.addr = FIELD_GET(EVTQ_2_ADDR, evt[2]),
1471395ad89dSJean-Philippe Brucker 		};
1472395ad89dSJean-Philippe Brucker 
1473395ad89dSJean-Philippe Brucker 		if (ssid_valid) {
1474395ad89dSJean-Philippe Brucker 			flt->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
1475395ad89dSJean-Philippe Brucker 			flt->prm.pasid = FIELD_GET(EVTQ_0_SSID, evt[0]);
1476395ad89dSJean-Philippe Brucker 		}
1477395ad89dSJean-Philippe Brucker 	} else {
1478395ad89dSJean-Philippe Brucker 		flt->type = IOMMU_FAULT_DMA_UNRECOV;
1479395ad89dSJean-Philippe Brucker 		flt->event = (struct iommu_fault_unrecoverable) {
1480395ad89dSJean-Philippe Brucker 			.reason = reason,
1481395ad89dSJean-Philippe Brucker 			.flags = IOMMU_FAULT_UNRECOV_ADDR_VALID,
1482395ad89dSJean-Philippe Brucker 			.perm = perm,
1483395ad89dSJean-Philippe Brucker 			.addr = FIELD_GET(EVTQ_2_ADDR, evt[2]),
1484395ad89dSJean-Philippe Brucker 		};
1485395ad89dSJean-Philippe Brucker 
1486395ad89dSJean-Philippe Brucker 		if (ssid_valid) {
1487395ad89dSJean-Philippe Brucker 			flt->event.flags |= IOMMU_FAULT_UNRECOV_PASID_VALID;
1488395ad89dSJean-Philippe Brucker 			flt->event.pasid = FIELD_GET(EVTQ_0_SSID, evt[0]);
1489395ad89dSJean-Philippe Brucker 		}
1490395ad89dSJean-Philippe Brucker 	}
1491395ad89dSJean-Philippe Brucker 
1492395ad89dSJean-Philippe Brucker 	mutex_lock(&smmu->streams_mutex);
1493395ad89dSJean-Philippe Brucker 	master = arm_smmu_find_master(smmu, sid);
1494395ad89dSJean-Philippe Brucker 	if (!master) {
1495395ad89dSJean-Philippe Brucker 		ret = -EINVAL;
1496395ad89dSJean-Philippe Brucker 		goto out_unlock;
1497395ad89dSJean-Philippe Brucker 	}
1498395ad89dSJean-Philippe Brucker 
1499395ad89dSJean-Philippe Brucker 	ret = iommu_report_device_fault(master->dev, &fault_evt);
1500395ad89dSJean-Philippe Brucker 	if (ret && flt->type == IOMMU_FAULT_PAGE_REQ) {
1501395ad89dSJean-Philippe Brucker 		/* Nobody cared, abort the access */
1502395ad89dSJean-Philippe Brucker 		struct iommu_page_response resp = {
1503395ad89dSJean-Philippe Brucker 			.pasid		= flt->prm.pasid,
1504395ad89dSJean-Philippe Brucker 			.grpid		= flt->prm.grpid,
1505395ad89dSJean-Philippe Brucker 			.code		= IOMMU_PAGE_RESP_FAILURE,
1506395ad89dSJean-Philippe Brucker 		};
1507395ad89dSJean-Philippe Brucker 		arm_smmu_page_response(master->dev, &fault_evt, &resp);
1508395ad89dSJean-Philippe Brucker 	}
1509395ad89dSJean-Philippe Brucker 
1510395ad89dSJean-Philippe Brucker out_unlock:
1511395ad89dSJean-Philippe Brucker 	mutex_unlock(&smmu->streams_mutex);
1512395ad89dSJean-Philippe Brucker 	return ret;
1513395ad89dSJean-Philippe Brucker }
1514395ad89dSJean-Philippe Brucker 
151548ec83bcSWill Deacon static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
151648ec83bcSWill Deacon {
1517395ad89dSJean-Philippe Brucker 	int i, ret;
151848ec83bcSWill Deacon 	struct arm_smmu_device *smmu = dev;
151948ec83bcSWill Deacon 	struct arm_smmu_queue *q = &smmu->evtq.q;
15207c288a5bSWill Deacon 	struct arm_smmu_ll_queue *llq = &q->llq;
1521*9cff922bSJean-Philippe Brucker 	static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL,
1522*9cff922bSJean-Philippe Brucker 				      DEFAULT_RATELIMIT_BURST);
152348ec83bcSWill Deacon 	u64 evt[EVTQ_ENT_DWORDS];
152448ec83bcSWill Deacon 
1525b4163fb3SJean-Philippe Brucker 	do {
152648ec83bcSWill Deacon 		while (!queue_remove_raw(q, evt)) {
15277417b99cSRobin Murphy 			u8 id = FIELD_GET(EVTQ_0_ID, evt[0]);
152848ec83bcSWill Deacon 
1529395ad89dSJean-Philippe Brucker 			ret = arm_smmu_handle_evt(smmu, evt);
1530*9cff922bSJean-Philippe Brucker 			if (!ret || !__ratelimit(&rs))
1531395ad89dSJean-Philippe Brucker 				continue;
1532395ad89dSJean-Philippe Brucker 
153348ec83bcSWill Deacon 			dev_info(smmu->dev, "event 0x%02x received:\n", id);
153448ec83bcSWill Deacon 			for (i = 0; i < ARRAY_SIZE(evt); ++i)
153548ec83bcSWill Deacon 				dev_info(smmu->dev, "\t0x%016llx\n",
153648ec83bcSWill Deacon 					 (unsigned long long)evt[i]);
153748ec83bcSWill Deacon 
153848ec83bcSWill Deacon 		}
153948ec83bcSWill Deacon 
154048ec83bcSWill Deacon 		/*
154148ec83bcSWill Deacon 		 * Not much we can do on overflow, so scream and pretend we're
154248ec83bcSWill Deacon 		 * trying harder.
154348ec83bcSWill Deacon 		 */
15442a8868f1SWill Deacon 		if (queue_sync_prod_in(q) == -EOVERFLOW)
154548ec83bcSWill Deacon 			dev_err(smmu->dev, "EVTQ overflow detected -- events lost\n");
15467c288a5bSWill Deacon 	} while (!queue_empty(llq));
154748ec83bcSWill Deacon 
1548b4163fb3SJean-Philippe Brucker 	/* Sync our overflow flag, as we believe we're up to speed */
15497c288a5bSWill Deacon 	llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
15507c288a5bSWill Deacon 		    Q_IDX(llq, llq->cons);
1551b4163fb3SJean-Philippe Brucker 	return IRQ_HANDLED;
155248ec83bcSWill Deacon }
155348ec83bcSWill Deacon 
1554b4163fb3SJean-Philippe Brucker static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
155548ec83bcSWill Deacon {
155648ec83bcSWill Deacon 	u32 sid, ssid;
155748ec83bcSWill Deacon 	u16 grpid;
155848ec83bcSWill Deacon 	bool ssv, last;
155948ec83bcSWill Deacon 
15607417b99cSRobin Murphy 	sid = FIELD_GET(PRIQ_0_SID, evt[0]);
15617417b99cSRobin Murphy 	ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]);
15627417b99cSRobin Murphy 	ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : 0;
15637417b99cSRobin Murphy 	last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]);
15647417b99cSRobin Murphy 	grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
156548ec83bcSWill Deacon 
156648ec83bcSWill Deacon 	dev_info(smmu->dev, "unexpected PRI request received:\n");
156748ec83bcSWill Deacon 	dev_info(smmu->dev,
156848ec83bcSWill Deacon 		 "\tsid 0x%08x.0x%05x: [%u%s] %sprivileged %s%s%s access at iova 0x%016llx\n",
156948ec83bcSWill Deacon 		 sid, ssid, grpid, last ? "L" : "",
157048ec83bcSWill Deacon 		 evt[0] & PRIQ_0_PERM_PRIV ? "" : "un",
157148ec83bcSWill Deacon 		 evt[0] & PRIQ_0_PERM_READ ? "R" : "",
157248ec83bcSWill Deacon 		 evt[0] & PRIQ_0_PERM_WRITE ? "W" : "",
157348ec83bcSWill Deacon 		 evt[0] & PRIQ_0_PERM_EXEC ? "X" : "",
15741cf9e54eSRobin Murphy 		 evt[1] & PRIQ_1_ADDR_MASK);
157548ec83bcSWill Deacon 
157648ec83bcSWill Deacon 	if (last) {
157748ec83bcSWill Deacon 		struct arm_smmu_cmdq_ent cmd = {
157848ec83bcSWill Deacon 			.opcode			= CMDQ_OP_PRI_RESP,
157948ec83bcSWill Deacon 			.substream_valid	= ssv,
158048ec83bcSWill Deacon 			.pri			= {
158148ec83bcSWill Deacon 				.sid	= sid,
158248ec83bcSWill Deacon 				.ssid	= ssid,
158348ec83bcSWill Deacon 				.grpid	= grpid,
158448ec83bcSWill Deacon 				.resp	= PRI_RESP_DENY,
158548ec83bcSWill Deacon 			},
158648ec83bcSWill Deacon 		};
158748ec83bcSWill Deacon 
158848ec83bcSWill Deacon 		arm_smmu_cmdq_issue_cmd(smmu, &cmd);
158948ec83bcSWill Deacon 	}
159048ec83bcSWill Deacon }
159148ec83bcSWill Deacon 
1592b4163fb3SJean-Philippe Brucker static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
1593b4163fb3SJean-Philippe Brucker {
1594b4163fb3SJean-Philippe Brucker 	struct arm_smmu_device *smmu = dev;
1595b4163fb3SJean-Philippe Brucker 	struct arm_smmu_queue *q = &smmu->priq.q;
15967c288a5bSWill Deacon 	struct arm_smmu_ll_queue *llq = &q->llq;
1597b4163fb3SJean-Philippe Brucker 	u64 evt[PRIQ_ENT_DWORDS];
1598b4163fb3SJean-Philippe Brucker 
1599b4163fb3SJean-Philippe Brucker 	do {
1600b4163fb3SJean-Philippe Brucker 		while (!queue_remove_raw(q, evt))
1601b4163fb3SJean-Philippe Brucker 			arm_smmu_handle_ppr(smmu, evt);
1602b4163fb3SJean-Philippe Brucker 
16032a8868f1SWill Deacon 		if (queue_sync_prod_in(q) == -EOVERFLOW)
1604b4163fb3SJean-Philippe Brucker 			dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
16057c288a5bSWill Deacon 	} while (!queue_empty(llq));
1606b4163fb3SJean-Philippe Brucker 
160748ec83bcSWill Deacon 	/* Sync our overflow flag, as we believe we're up to speed */
16087c288a5bSWill Deacon 	llq->cons = Q_OVF(llq->prod) | Q_WRP(llq, llq->cons) |
16097c288a5bSWill Deacon 		      Q_IDX(llq, llq->cons);
16107c288a5bSWill Deacon 	queue_sync_cons_out(q);
161148ec83bcSWill Deacon 	return IRQ_HANDLED;
161248ec83bcSWill Deacon }
161348ec83bcSWill Deacon 
161448ec83bcSWill Deacon static int arm_smmu_device_disable(struct arm_smmu_device *smmu);
161548ec83bcSWill Deacon 
161648ec83bcSWill Deacon static irqreturn_t arm_smmu_gerror_handler(int irq, void *dev)
161748ec83bcSWill Deacon {
1618324ba108SPrem Mallappa 	u32 gerror, gerrorn, active;
161948ec83bcSWill Deacon 	struct arm_smmu_device *smmu = dev;
162048ec83bcSWill Deacon 
162148ec83bcSWill Deacon 	gerror = readl_relaxed(smmu->base + ARM_SMMU_GERROR);
162248ec83bcSWill Deacon 	gerrorn = readl_relaxed(smmu->base + ARM_SMMU_GERRORN);
162348ec83bcSWill Deacon 
1624324ba108SPrem Mallappa 	active = gerror ^ gerrorn;
1625324ba108SPrem Mallappa 	if (!(active & GERROR_ERR_MASK))
162648ec83bcSWill Deacon 		return IRQ_NONE; /* No errors pending */
162748ec83bcSWill Deacon 
162848ec83bcSWill Deacon 	dev_warn(smmu->dev,
162948ec83bcSWill Deacon 		 "unexpected global error reported (0x%08x), this could be serious\n",
1630324ba108SPrem Mallappa 		 active);
163148ec83bcSWill Deacon 
1632324ba108SPrem Mallappa 	if (active & GERROR_SFM_ERR) {
163348ec83bcSWill Deacon 		dev_err(smmu->dev, "device has entered Service Failure Mode!\n");
163448ec83bcSWill Deacon 		arm_smmu_device_disable(smmu);
163548ec83bcSWill Deacon 	}
163648ec83bcSWill Deacon 
1637324ba108SPrem Mallappa 	if (active & GERROR_MSI_GERROR_ABT_ERR)
163848ec83bcSWill Deacon 		dev_warn(smmu->dev, "GERROR MSI write aborted\n");
163948ec83bcSWill Deacon 
1640b4163fb3SJean-Philippe Brucker 	if (active & GERROR_MSI_PRIQ_ABT_ERR)
164148ec83bcSWill Deacon 		dev_warn(smmu->dev, "PRIQ MSI write aborted\n");
164248ec83bcSWill Deacon 
1643b4163fb3SJean-Philippe Brucker 	if (active & GERROR_MSI_EVTQ_ABT_ERR)
164448ec83bcSWill Deacon 		dev_warn(smmu->dev, "EVTQ MSI write aborted\n");
164548ec83bcSWill Deacon 
1646dce032a1SRobin Murphy 	if (active & GERROR_MSI_CMDQ_ABT_ERR)
164748ec83bcSWill Deacon 		dev_warn(smmu->dev, "CMDQ MSI write aborted\n");
164848ec83bcSWill Deacon 
1649324ba108SPrem Mallappa 	if (active & GERROR_PRIQ_ABT_ERR)
165048ec83bcSWill Deacon 		dev_err(smmu->dev, "PRIQ write aborted -- events may have been lost\n");
165148ec83bcSWill Deacon 
1652324ba108SPrem Mallappa 	if (active & GERROR_EVTQ_ABT_ERR)
165348ec83bcSWill Deacon 		dev_err(smmu->dev, "EVTQ write aborted -- events may have been lost\n");
165448ec83bcSWill Deacon 
1655324ba108SPrem Mallappa 	if (active & GERROR_CMDQ_ERR)
165648ec83bcSWill Deacon 		arm_smmu_cmdq_skip_err(smmu);
165748ec83bcSWill Deacon 
165848ec83bcSWill Deacon 	writel(gerror, smmu->base + ARM_SMMU_GERRORN);
165948ec83bcSWill Deacon 	return IRQ_HANDLED;
166048ec83bcSWill Deacon }
166148ec83bcSWill Deacon 
1662f935448aSGeetha Sowjanya static irqreturn_t arm_smmu_combined_irq_thread(int irq, void *dev)
1663f935448aSGeetha Sowjanya {
1664f935448aSGeetha Sowjanya 	struct arm_smmu_device *smmu = dev;
1665f935448aSGeetha Sowjanya 
1666f935448aSGeetha Sowjanya 	arm_smmu_evtq_thread(irq, dev);
1667f935448aSGeetha Sowjanya 	if (smmu->features & ARM_SMMU_FEAT_PRI)
1668f935448aSGeetha Sowjanya 		arm_smmu_priq_thread(irq, dev);
1669f935448aSGeetha Sowjanya 
1670f935448aSGeetha Sowjanya 	return IRQ_HANDLED;
1671f935448aSGeetha Sowjanya }
1672f935448aSGeetha Sowjanya 
1673f935448aSGeetha Sowjanya static irqreturn_t arm_smmu_combined_irq_handler(int irq, void *dev)
1674f935448aSGeetha Sowjanya {
1675f935448aSGeetha Sowjanya 	arm_smmu_gerror_handler(irq, dev);
1676f935448aSGeetha Sowjanya 	return IRQ_WAKE_THREAD;
1677f935448aSGeetha Sowjanya }
1678f935448aSGeetha Sowjanya 
16799ce27afcSJean-Philippe Brucker static void
16809ce27afcSJean-Philippe Brucker arm_smmu_atc_inv_to_cmd(int ssid, unsigned long iova, size_t size,
16819ce27afcSJean-Philippe Brucker 			struct arm_smmu_cmdq_ent *cmd)
16829ce27afcSJean-Philippe Brucker {
16839ce27afcSJean-Philippe Brucker 	size_t log2_span;
16849ce27afcSJean-Philippe Brucker 	size_t span_mask;
16859ce27afcSJean-Philippe Brucker 	/* ATC invalidates are always on 4096-bytes pages */
16869ce27afcSJean-Philippe Brucker 	size_t inval_grain_shift = 12;
16879ce27afcSJean-Philippe Brucker 	unsigned long page_start, page_end;
16889ce27afcSJean-Philippe Brucker 
16892f7e8c55SJean-Philippe Brucker 	/*
16902f7e8c55SJean-Philippe Brucker 	 * ATS and PASID:
16912f7e8c55SJean-Philippe Brucker 	 *
16922f7e8c55SJean-Philippe Brucker 	 * If substream_valid is clear, the PCIe TLP is sent without a PASID
16932f7e8c55SJean-Philippe Brucker 	 * prefix. In that case all ATC entries within the address range are
16942f7e8c55SJean-Philippe Brucker 	 * invalidated, including those that were requested with a PASID! There
16952f7e8c55SJean-Philippe Brucker 	 * is no way to invalidate only entries without PASID.
16962f7e8c55SJean-Philippe Brucker 	 *
16972f7e8c55SJean-Philippe Brucker 	 * When using STRTAB_STE_1_S1DSS_SSID0 (reserving CD 0 for non-PASID
16982f7e8c55SJean-Philippe Brucker 	 * traffic), translation requests without PASID create ATC entries
16992f7e8c55SJean-Philippe Brucker 	 * without PASID, which must be invalidated with substream_valid clear.
17002f7e8c55SJean-Philippe Brucker 	 * This has the unpleasant side-effect of invalidating all PASID-tagged
17012f7e8c55SJean-Philippe Brucker 	 * ATC entries within the address range.
17022f7e8c55SJean-Philippe Brucker 	 */
17039ce27afcSJean-Philippe Brucker 	*cmd = (struct arm_smmu_cmdq_ent) {
17049ce27afcSJean-Philippe Brucker 		.opcode			= CMDQ_OP_ATC_INV,
17059ce27afcSJean-Philippe Brucker 		.substream_valid	= !!ssid,
17069ce27afcSJean-Philippe Brucker 		.atc.ssid		= ssid,
17079ce27afcSJean-Philippe Brucker 	};
17089ce27afcSJean-Philippe Brucker 
17099ce27afcSJean-Philippe Brucker 	if (!size) {
17109ce27afcSJean-Philippe Brucker 		cmd->atc.size = ATC_INV_SIZE_ALL;
17119ce27afcSJean-Philippe Brucker 		return;
17129ce27afcSJean-Philippe Brucker 	}
17139ce27afcSJean-Philippe Brucker 
17149ce27afcSJean-Philippe Brucker 	page_start	= iova >> inval_grain_shift;
17159ce27afcSJean-Philippe Brucker 	page_end	= (iova + size - 1) >> inval_grain_shift;
17169ce27afcSJean-Philippe Brucker 
17179ce27afcSJean-Philippe Brucker 	/*
17189ce27afcSJean-Philippe Brucker 	 * In an ATS Invalidate Request, the address must be aligned on the
17199ce27afcSJean-Philippe Brucker 	 * range size, which must be a power of two number of page sizes. We
17209ce27afcSJean-Philippe Brucker 	 * thus have to choose between grossly over-invalidating the region, or
17219ce27afcSJean-Philippe Brucker 	 * splitting the invalidation into multiple commands. For simplicity
17229ce27afcSJean-Philippe Brucker 	 * we'll go with the first solution, but should refine it in the future
17239ce27afcSJean-Philippe Brucker 	 * if multiple commands are shown to be more efficient.
17249ce27afcSJean-Philippe Brucker 	 *
17259ce27afcSJean-Philippe Brucker 	 * Find the smallest power of two that covers the range. The most
17269ce27afcSJean-Philippe Brucker 	 * significant differing bit between the start and end addresses,
17279ce27afcSJean-Philippe Brucker 	 * fls(start ^ end), indicates the required span. For example:
17289ce27afcSJean-Philippe Brucker 	 *
17299ce27afcSJean-Philippe Brucker 	 * We want to invalidate pages [8; 11]. This is already the ideal range:
17309ce27afcSJean-Philippe Brucker 	 *		x = 0b1000 ^ 0b1011 = 0b11
17319ce27afcSJean-Philippe Brucker 	 *		span = 1 << fls(x) = 4
17329ce27afcSJean-Philippe Brucker 	 *
17339ce27afcSJean-Philippe Brucker 	 * To invalidate pages [7; 10], we need to invalidate [0; 15]:
17349ce27afcSJean-Philippe Brucker 	 *		x = 0b0111 ^ 0b1010 = 0b1101
17359ce27afcSJean-Philippe Brucker 	 *		span = 1 << fls(x) = 16
17369ce27afcSJean-Philippe Brucker 	 */
17379ce27afcSJean-Philippe Brucker 	log2_span	= fls_long(page_start ^ page_end);
17389ce27afcSJean-Philippe Brucker 	span_mask	= (1ULL << log2_span) - 1;
17399ce27afcSJean-Philippe Brucker 
17409ce27afcSJean-Philippe Brucker 	page_start	&= ~span_mask;
17419ce27afcSJean-Philippe Brucker 
17429ce27afcSJean-Philippe Brucker 	cmd->atc.addr	= page_start << inval_grain_shift;
17439ce27afcSJean-Philippe Brucker 	cmd->atc.size	= log2_span;
17449ce27afcSJean-Philippe Brucker }
17459ce27afcSJean-Philippe Brucker 
17469e773aeeSRob Herring static int arm_smmu_atc_inv_master(struct arm_smmu_master *master)
17479ce27afcSJean-Philippe Brucker {
17489ce27afcSJean-Philippe Brucker 	int i;
17499e773aeeSRob Herring 	struct arm_smmu_cmdq_ent cmd;
17509ce27afcSJean-Philippe Brucker 
17519e773aeeSRob Herring 	arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
17529ce27afcSJean-Philippe Brucker 
1753cdf315f9SJean-Philippe Brucker 	for (i = 0; i < master->num_streams; i++) {
1754cdf315f9SJean-Philippe Brucker 		cmd.atc.sid = master->streams[i].id;
17559e773aeeSRob Herring 		arm_smmu_cmdq_issue_cmd(master->smmu, &cmd);
17569ce27afcSJean-Philippe Brucker 	}
17579ce27afcSJean-Philippe Brucker 
17589ce27afcSJean-Philippe Brucker 	return arm_smmu_cmdq_issue_sync(master->smmu);
17599ce27afcSJean-Philippe Brucker }
17609ce27afcSJean-Philippe Brucker 
17612f7e8c55SJean-Philippe Brucker int arm_smmu_atc_inv_domain(struct arm_smmu_domain *smmu_domain, int ssid,
17622f7e8c55SJean-Philippe Brucker 			    unsigned long iova, size_t size)
17639ce27afcSJean-Philippe Brucker {
17649e773aeeSRob Herring 	int i;
17659ce27afcSJean-Philippe Brucker 	unsigned long flags;
17669ce27afcSJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd;
17679ce27afcSJean-Philippe Brucker 	struct arm_smmu_master *master;
17689e773aeeSRob Herring 	struct arm_smmu_cmdq_batch cmds = {};
17699ce27afcSJean-Philippe Brucker 
17709ce27afcSJean-Philippe Brucker 	if (!(smmu_domain->smmu->features & ARM_SMMU_FEAT_ATS))
17719ce27afcSJean-Philippe Brucker 		return 0;
17729ce27afcSJean-Philippe Brucker 
1773cdb8a3c3SWill Deacon 	/*
1774cdb8a3c3SWill Deacon 	 * Ensure that we've completed prior invalidation of the main TLBs
1775cdb8a3c3SWill Deacon 	 * before we read 'nr_ats_masters' in case of a concurrent call to
1776cdb8a3c3SWill Deacon 	 * arm_smmu_enable_ats():
1777cdb8a3c3SWill Deacon 	 *
1778cdb8a3c3SWill Deacon 	 *	// unmap()			// arm_smmu_enable_ats()
1779cdb8a3c3SWill Deacon 	 *	TLBI+SYNC			atomic_inc(&nr_ats_masters);
1780cdb8a3c3SWill Deacon 	 *	smp_mb();			[...]
1781cdb8a3c3SWill Deacon 	 *	atomic_read(&nr_ats_masters);	pci_enable_ats() // writel()
1782cdb8a3c3SWill Deacon 	 *
1783cdb8a3c3SWill Deacon 	 * Ensures that we always see the incremented 'nr_ats_masters' count if
1784cdb8a3c3SWill Deacon 	 * ATS was enabled at the PCI device before completion of the TLBI.
1785cdb8a3c3SWill Deacon 	 */
1786cdb8a3c3SWill Deacon 	smp_mb();
1787cdb8a3c3SWill Deacon 	if (!atomic_read(&smmu_domain->nr_ats_masters))
1788cdb8a3c3SWill Deacon 		return 0;
1789cdb8a3c3SWill Deacon 
17909ce27afcSJean-Philippe Brucker 	arm_smmu_atc_inv_to_cmd(ssid, iova, size, &cmd);
17919ce27afcSJean-Philippe Brucker 
17929ce27afcSJean-Philippe Brucker 	spin_lock_irqsave(&smmu_domain->devices_lock, flags);
17939e773aeeSRob Herring 	list_for_each_entry(master, &smmu_domain->devices, domain_head) {
17949e773aeeSRob Herring 		if (!master->ats_enabled)
17959e773aeeSRob Herring 			continue;
17969e773aeeSRob Herring 
1797cdf315f9SJean-Philippe Brucker 		for (i = 0; i < master->num_streams; i++) {
1798cdf315f9SJean-Philippe Brucker 			cmd.atc.sid = master->streams[i].id;
17999e773aeeSRob Herring 			arm_smmu_cmdq_batch_add(smmu_domain->smmu, &cmds, &cmd);
18009e773aeeSRob Herring 		}
18019e773aeeSRob Herring 	}
18029ce27afcSJean-Philippe Brucker 	spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
18039ce27afcSJean-Philippe Brucker 
18049e773aeeSRob Herring 	return arm_smmu_cmdq_batch_submit(smmu_domain->smmu, &cmds);
18059ce27afcSJean-Philippe Brucker }
18069ce27afcSJean-Philippe Brucker 
180748ec83bcSWill Deacon /* IO_PGTABLE API */
180848ec83bcSWill Deacon static void arm_smmu_tlb_inv_context(void *cookie)
180948ec83bcSWill Deacon {
181048ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain = cookie;
181148ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
181248ec83bcSWill Deacon 	struct arm_smmu_cmdq_ent cmd;
181348ec83bcSWill Deacon 
18149662b99aSZhen Lei 	/*
18159662b99aSZhen Lei 	 * NOTE: when io-pgtable is in non-strict mode, we may get here with
18169662b99aSZhen Lei 	 * PTEs previously cleared by unmaps on the current CPU not yet visible
1817587e6c10SWill Deacon 	 * to the SMMU. We are relying on the dma_wmb() implicit during cmd
1818587e6c10SWill Deacon 	 * insertion to guarantee those are observed before the TLBI. Do be
1819587e6c10SWill Deacon 	 * careful, 007.
18209662b99aSZhen Lei 	 */
18213e630336SJean-Philippe Brucker 	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
18223e630336SJean-Philippe Brucker 		arm_smmu_tlb_inv_asid(smmu, smmu_domain->s1_cfg.cd.asid);
18233e630336SJean-Philippe Brucker 	} else {
18243e630336SJean-Philippe Brucker 		cmd.opcode	= CMDQ_OP_TLBI_S12_VMALL;
18253e630336SJean-Philippe Brucker 		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
182648ec83bcSWill Deacon 		arm_smmu_cmdq_issue_cmd(smmu, &cmd);
18275e731073SAndrew Murray 		arm_smmu_cmdq_issue_sync(smmu);
18283e630336SJean-Philippe Brucker 	}
1829353e3cf8SWill Deacon 	arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
183048ec83bcSWill Deacon }
183148ec83bcSWill Deacon 
1832eba8d2f8SJean-Philippe Brucker static void __arm_smmu_tlb_inv_range(struct arm_smmu_cmdq_ent *cmd,
1833eba8d2f8SJean-Philippe Brucker 				     unsigned long iova, size_t size,
1834eba8d2f8SJean-Philippe Brucker 				     size_t granule,
18352af2e72bSWill Deacon 				     struct arm_smmu_domain *smmu_domain)
183648ec83bcSWill Deacon {
183748ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
1838eba8d2f8SJean-Philippe Brucker 	unsigned long end = iova + size, num_pages = 0, tg = 0;
18396a481a95SRob Herring 	size_t inv_range = granule;
18404ce8da45SJean-Philippe Brucker 	struct arm_smmu_cmdq_batch cmds = {};
184148ec83bcSWill Deacon 
18427314ca86SWill Deacon 	if (!size)
18437314ca86SWill Deacon 		return;
18447314ca86SWill Deacon 
18456a481a95SRob Herring 	if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) {
18466a481a95SRob Herring 		/* Get the leaf page size */
18476a481a95SRob Herring 		tg = __ffs(smmu_domain->domain.pgsize_bitmap);
18486a481a95SRob Herring 
18496a481a95SRob Herring 		/* Convert page size of 12,14,16 (log2) to 1,2,3 */
1850eba8d2f8SJean-Philippe Brucker 		cmd->tlbi.tg = (tg - 10) / 2;
18516a481a95SRob Herring 
18526a481a95SRob Herring 		/* Determine what level the granule is at */
1853eba8d2f8SJean-Philippe Brucker 		cmd->tlbi.ttl = 4 - ((ilog2(granule) - 3) / (tg - 3));
18546a481a95SRob Herring 
18556a481a95SRob Herring 		num_pages = size >> tg;
18566a481a95SRob Herring 	}
18576a481a95SRob Herring 
18582af2e72bSWill Deacon 	while (iova < end) {
18596a481a95SRob Herring 		if (smmu->features & ARM_SMMU_FEAT_RANGE_INV) {
18606a481a95SRob Herring 			/*
18616a481a95SRob Herring 			 * On each iteration of the loop, the range is 5 bits
18626a481a95SRob Herring 			 * worth of the aligned size remaining.
18636a481a95SRob Herring 			 * The range in pages is:
18646a481a95SRob Herring 			 *
18656a481a95SRob Herring 			 * range = (num_pages & (0x1f << __ffs(num_pages)))
18666a481a95SRob Herring 			 */
18676a481a95SRob Herring 			unsigned long scale, num;
18686a481a95SRob Herring 
18696a481a95SRob Herring 			/* Determine the power of 2 multiple number of pages */
18706a481a95SRob Herring 			scale = __ffs(num_pages);
1871eba8d2f8SJean-Philippe Brucker 			cmd->tlbi.scale = scale;
18726a481a95SRob Herring 
18736a481a95SRob Herring 			/* Determine how many chunks of 2^scale size we have */
18746a481a95SRob Herring 			num = (num_pages >> scale) & CMDQ_TLBI_RANGE_NUM_MAX;
1875eba8d2f8SJean-Philippe Brucker 			cmd->tlbi.num = num - 1;
18766a481a95SRob Herring 
18776a481a95SRob Herring 			/* range is num * 2^scale * pgsize */
18786a481a95SRob Herring 			inv_range = num << (scale + tg);
18796a481a95SRob Herring 
18806a481a95SRob Herring 			/* Clear out the lower order bits for the next iteration */
18816a481a95SRob Herring 			num_pages -= num << scale;
188248ec83bcSWill Deacon 		}
188348ec83bcSWill Deacon 
1884eba8d2f8SJean-Philippe Brucker 		cmd->tlbi.addr = iova;
1885eba8d2f8SJean-Philippe Brucker 		arm_smmu_cmdq_batch_add(smmu, &cmds, cmd);
18866a481a95SRob Herring 		iova += inv_range;
18872af2e72bSWill Deacon 	}
18884ce8da45SJean-Philippe Brucker 	arm_smmu_cmdq_batch_submit(smmu, &cmds);
1889eba8d2f8SJean-Philippe Brucker }
1890eba8d2f8SJean-Philippe Brucker 
1891eba8d2f8SJean-Philippe Brucker static void arm_smmu_tlb_inv_range_domain(unsigned long iova, size_t size,
1892eba8d2f8SJean-Philippe Brucker 					  size_t granule, bool leaf,
1893eba8d2f8SJean-Philippe Brucker 					  struct arm_smmu_domain *smmu_domain)
1894eba8d2f8SJean-Philippe Brucker {
1895eba8d2f8SJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd = {
1896eba8d2f8SJean-Philippe Brucker 		.tlbi = {
1897eba8d2f8SJean-Philippe Brucker 			.leaf	= leaf,
1898eba8d2f8SJean-Philippe Brucker 		},
1899eba8d2f8SJean-Philippe Brucker 	};
1900eba8d2f8SJean-Philippe Brucker 
1901eba8d2f8SJean-Philippe Brucker 	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
19029111aebfSJean-Philippe Brucker 		cmd.opcode	= smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ?
19039111aebfSJean-Philippe Brucker 				  CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA;
1904eba8d2f8SJean-Philippe Brucker 		cmd.tlbi.asid	= smmu_domain->s1_cfg.cd.asid;
1905eba8d2f8SJean-Philippe Brucker 	} else {
1906eba8d2f8SJean-Philippe Brucker 		cmd.opcode	= CMDQ_OP_TLBI_S2_IPA;
1907eba8d2f8SJean-Philippe Brucker 		cmd.tlbi.vmid	= smmu_domain->s2_cfg.vmid;
1908eba8d2f8SJean-Philippe Brucker 	}
1909eba8d2f8SJean-Philippe Brucker 	__arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain);
1910353e3cf8SWill Deacon 
1911353e3cf8SWill Deacon 	/*
1912353e3cf8SWill Deacon 	 * Unfortunately, this can't be leaf-only since we may have
1913353e3cf8SWill Deacon 	 * zapped an entire table.
1914353e3cf8SWill Deacon 	 */
1915eba8d2f8SJean-Philippe Brucker 	arm_smmu_atc_inv_domain(smmu_domain, 0, iova, size);
191648ec83bcSWill Deacon }
191748ec83bcSWill Deacon 
191851d113c3SJean-Philippe Brucker void arm_smmu_tlb_inv_range_asid(unsigned long iova, size_t size, int asid,
191951d113c3SJean-Philippe Brucker 				 size_t granule, bool leaf,
192051d113c3SJean-Philippe Brucker 				 struct arm_smmu_domain *smmu_domain)
192151d113c3SJean-Philippe Brucker {
192251d113c3SJean-Philippe Brucker 	struct arm_smmu_cmdq_ent cmd = {
19239111aebfSJean-Philippe Brucker 		.opcode	= smmu_domain->smmu->features & ARM_SMMU_FEAT_E2H ?
19249111aebfSJean-Philippe Brucker 			  CMDQ_OP_TLBI_EL2_VA : CMDQ_OP_TLBI_NH_VA,
192551d113c3SJean-Philippe Brucker 		.tlbi = {
192651d113c3SJean-Philippe Brucker 			.asid	= asid,
192751d113c3SJean-Philippe Brucker 			.leaf	= leaf,
192851d113c3SJean-Philippe Brucker 		},
192951d113c3SJean-Philippe Brucker 	};
193051d113c3SJean-Philippe Brucker 
193151d113c3SJean-Philippe Brucker 	__arm_smmu_tlb_inv_range(&cmd, iova, size, granule, smmu_domain);
193251d113c3SJean-Philippe Brucker }
193351d113c3SJean-Philippe Brucker 
19343951c41aSWill Deacon static void arm_smmu_tlb_inv_page_nosync(struct iommu_iotlb_gather *gather,
19353951c41aSWill Deacon 					 unsigned long iova, size_t granule,
1936abfd6fe0SWill Deacon 					 void *cookie)
1937abfd6fe0SWill Deacon {
19382af2e72bSWill Deacon 	struct arm_smmu_domain *smmu_domain = cookie;
19392af2e72bSWill Deacon 	struct iommu_domain *domain = &smmu_domain->domain;
19402af2e72bSWill Deacon 
19412af2e72bSWill Deacon 	iommu_iotlb_gather_add_page(domain, gather, iova, granule);
1942abfd6fe0SWill Deacon }
1943abfd6fe0SWill Deacon 
194405aed941SWill Deacon static void arm_smmu_tlb_inv_walk(unsigned long iova, size_t size,
194505aed941SWill Deacon 				  size_t granule, void *cookie)
194605aed941SWill Deacon {
1947eba8d2f8SJean-Philippe Brucker 	arm_smmu_tlb_inv_range_domain(iova, size, granule, false, cookie);
194805aed941SWill Deacon }
194905aed941SWill Deacon 
1950298f7889SWill Deacon static const struct iommu_flush_ops arm_smmu_flush_ops = {
195148ec83bcSWill Deacon 	.tlb_flush_all	= arm_smmu_tlb_inv_context,
195205aed941SWill Deacon 	.tlb_flush_walk = arm_smmu_tlb_inv_walk,
1953abfd6fe0SWill Deacon 	.tlb_add_page	= arm_smmu_tlb_inv_page_nosync,
195448ec83bcSWill Deacon };
195548ec83bcSWill Deacon 
195648ec83bcSWill Deacon /* IOMMU API */
195748ec83bcSWill Deacon static bool arm_smmu_capable(enum iommu_cap cap)
195848ec83bcSWill Deacon {
195948ec83bcSWill Deacon 	switch (cap) {
196048ec83bcSWill Deacon 	case IOMMU_CAP_CACHE_COHERENCY:
196148ec83bcSWill Deacon 		return true;
196248ec83bcSWill Deacon 	case IOMMU_CAP_NOEXEC:
196348ec83bcSWill Deacon 		return true;
196448ec83bcSWill Deacon 	default:
196548ec83bcSWill Deacon 		return false;
196648ec83bcSWill Deacon 	}
196748ec83bcSWill Deacon }
196848ec83bcSWill Deacon 
196948ec83bcSWill Deacon static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
197048ec83bcSWill Deacon {
197148ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain;
197248ec83bcSWill Deacon 
1973beb3c6a0SWill Deacon 	if (type != IOMMU_DOMAIN_UNMANAGED &&
1974beb3c6a0SWill Deacon 	    type != IOMMU_DOMAIN_DMA &&
1975beb3c6a0SWill Deacon 	    type != IOMMU_DOMAIN_IDENTITY)
197648ec83bcSWill Deacon 		return NULL;
197748ec83bcSWill Deacon 
197848ec83bcSWill Deacon 	/*
197948ec83bcSWill Deacon 	 * Allocate the domain and initialise some of its data structures.
198048ec83bcSWill Deacon 	 * We can't really do anything meaningful until we've added a
198148ec83bcSWill Deacon 	 * master.
198248ec83bcSWill Deacon 	 */
198348ec83bcSWill Deacon 	smmu_domain = kzalloc(sizeof(*smmu_domain), GFP_KERNEL);
198448ec83bcSWill Deacon 	if (!smmu_domain)
198548ec83bcSWill Deacon 		return NULL;
198648ec83bcSWill Deacon 
19879adb9594SRobin Murphy 	if (type == IOMMU_DOMAIN_DMA &&
19889adb9594SRobin Murphy 	    iommu_get_dma_cookie(&smmu_domain->domain)) {
19899adb9594SRobin Murphy 		kfree(smmu_domain);
19909adb9594SRobin Murphy 		return NULL;
19919adb9594SRobin Murphy 	}
19929adb9594SRobin Murphy 
199348ec83bcSWill Deacon 	mutex_init(&smmu_domain->init_mutex);
19942a7e62f5SJean-Philippe Brucker 	INIT_LIST_HEAD(&smmu_domain->devices);
19952a7e62f5SJean-Philippe Brucker 	spin_lock_init(&smmu_domain->devices_lock);
199632784a95SJean-Philippe Brucker 	INIT_LIST_HEAD(&smmu_domain->mmu_notifiers);
19972a7e62f5SJean-Philippe Brucker 
199848ec83bcSWill Deacon 	return &smmu_domain->domain;
199948ec83bcSWill Deacon }
200048ec83bcSWill Deacon 
200148ec83bcSWill Deacon static int arm_smmu_bitmap_alloc(unsigned long *map, int span)
200248ec83bcSWill Deacon {
200348ec83bcSWill Deacon 	int idx, size = 1 << span;
200448ec83bcSWill Deacon 
200548ec83bcSWill Deacon 	do {
200648ec83bcSWill Deacon 		idx = find_first_zero_bit(map, size);
200748ec83bcSWill Deacon 		if (idx == size)
200848ec83bcSWill Deacon 			return -ENOSPC;
200948ec83bcSWill Deacon 	} while (test_and_set_bit(idx, map));
201048ec83bcSWill Deacon 
201148ec83bcSWill Deacon 	return idx;
201248ec83bcSWill Deacon }
201348ec83bcSWill Deacon 
201448ec83bcSWill Deacon static void arm_smmu_bitmap_free(unsigned long *map, int idx)
201548ec83bcSWill Deacon {
201648ec83bcSWill Deacon 	clear_bit(idx, map);
201748ec83bcSWill Deacon }
201848ec83bcSWill Deacon 
201948ec83bcSWill Deacon static void arm_smmu_domain_free(struct iommu_domain *domain)
202048ec83bcSWill Deacon {
202148ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
202248ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
202348ec83bcSWill Deacon 
20249adb9594SRobin Murphy 	iommu_put_dma_cookie(domain);
202548ec83bcSWill Deacon 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
202648ec83bcSWill Deacon 
202748ec83bcSWill Deacon 	/* Free the CD and ASID, if we allocated them */
202848ec83bcSWill Deacon 	if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
202948ec83bcSWill Deacon 		struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
203048ec83bcSWill Deacon 
20313f1ce8e8SJean-Philippe Brucker 		/* Prevent SVA from touching the CD while we're freeing it */
20323f1ce8e8SJean-Philippe Brucker 		mutex_lock(&arm_smmu_asid_lock);
20330299a1a8SJean-Philippe Brucker 		if (cfg->cdcfg.cdtab)
2034a557aff0SJean-Philippe Brucker 			arm_smmu_free_cd_tables(smmu_domain);
20350299a1a8SJean-Philippe Brucker 		arm_smmu_free_asid(&cfg->cd);
20363f1ce8e8SJean-Philippe Brucker 		mutex_unlock(&arm_smmu_asid_lock);
203748ec83bcSWill Deacon 	} else {
203848ec83bcSWill Deacon 		struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
203948ec83bcSWill Deacon 		if (cfg->vmid)
204048ec83bcSWill Deacon 			arm_smmu_bitmap_free(smmu->vmid_map, cfg->vmid);
204148ec83bcSWill Deacon 	}
204248ec83bcSWill Deacon 
204348ec83bcSWill Deacon 	kfree(smmu_domain);
204448ec83bcSWill Deacon }
204548ec83bcSWill Deacon 
204648ec83bcSWill Deacon static int arm_smmu_domain_finalise_s1(struct arm_smmu_domain *smmu_domain,
20472505ec6fSJean-Philippe Brucker 				       struct arm_smmu_master *master,
204848ec83bcSWill Deacon 				       struct io_pgtable_cfg *pgtbl_cfg)
204948ec83bcSWill Deacon {
205048ec83bcSWill Deacon 	int ret;
20510299a1a8SJean-Philippe Brucker 	u32 asid;
205248ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
205348ec83bcSWill Deacon 	struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
2054fb485eb1SRobin Murphy 	typeof(&pgtbl_cfg->arm_lpae_s1_cfg.tcr) tcr = &pgtbl_cfg->arm_lpae_s1_cfg.tcr;
205548ec83bcSWill Deacon 
20563f1ce8e8SJean-Philippe Brucker 	refcount_set(&cfg->cd.refs, 1);
20573f1ce8e8SJean-Philippe Brucker 
20583f1ce8e8SJean-Philippe Brucker 	/* Prevent SVA from modifying the ASID until it is written to the CD */
20593f1ce8e8SJean-Philippe Brucker 	mutex_lock(&arm_smmu_asid_lock);
20603f1ce8e8SJean-Philippe Brucker 	ret = xa_alloc(&arm_smmu_asid_xa, &asid, &cfg->cd,
20610299a1a8SJean-Philippe Brucker 		       XA_LIMIT(1, (1 << smmu->asid_bits) - 1), GFP_KERNEL);
20620299a1a8SJean-Philippe Brucker 	if (ret)
20633f1ce8e8SJean-Philippe Brucker 		goto out_unlock;
206448ec83bcSWill Deacon 
20652505ec6fSJean-Philippe Brucker 	cfg->s1cdmax = master->ssid_bits;
20662505ec6fSJean-Philippe Brucker 
2067395ad89dSJean-Philippe Brucker 	smmu_domain->stall_enabled = master->stall_enabled;
2068395ad89dSJean-Philippe Brucker 
2069a557aff0SJean-Philippe Brucker 	ret = arm_smmu_alloc_cd_tables(smmu_domain);
2070a557aff0SJean-Philippe Brucker 	if (ret)
207148ec83bcSWill Deacon 		goto out_free_asid;
207248ec83bcSWill Deacon 
2073c0733a2cSWill Deacon 	cfg->cd.asid	= (u16)asid;
2074d1e5f26fSRobin Murphy 	cfg->cd.ttbr	= pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
2075fb485eb1SRobin Murphy 	cfg->cd.tcr	= FIELD_PREP(CTXDESC_CD_0_TCR_T0SZ, tcr->tsz) |
2076fb485eb1SRobin Murphy 			  FIELD_PREP(CTXDESC_CD_0_TCR_TG0, tcr->tg) |
2077fb485eb1SRobin Murphy 			  FIELD_PREP(CTXDESC_CD_0_TCR_IRGN0, tcr->irgn) |
2078fb485eb1SRobin Murphy 			  FIELD_PREP(CTXDESC_CD_0_TCR_ORGN0, tcr->orgn) |
2079fb485eb1SRobin Murphy 			  FIELD_PREP(CTXDESC_CD_0_TCR_SH0, tcr->sh) |
2080fb485eb1SRobin Murphy 			  FIELD_PREP(CTXDESC_CD_0_TCR_IPS, tcr->ips) |
2081fb485eb1SRobin Murphy 			  CTXDESC_CD_0_TCR_EPD1 | CTXDESC_CD_0_AA64;
2082205577abSRobin Murphy 	cfg->cd.mair	= pgtbl_cfg->arm_lpae_s1_cfg.mair;
2083492ddc79SJean-Philippe Brucker 
2084492ddc79SJean-Philippe Brucker 	/*
2085492ddc79SJean-Philippe Brucker 	 * Note that this will end up calling arm_smmu_sync_cd() before
2086492ddc79SJean-Philippe Brucker 	 * the master has been added to the devices list for this domain.
2087492ddc79SJean-Philippe Brucker 	 * This isn't an issue because the STE hasn't been installed yet.
2088492ddc79SJean-Philippe Brucker 	 */
2089492ddc79SJean-Philippe Brucker 	ret = arm_smmu_write_ctx_desc(smmu_domain, 0, &cfg->cd);
2090492ddc79SJean-Philippe Brucker 	if (ret)
2091492ddc79SJean-Philippe Brucker 		goto out_free_cd_tables;
2092492ddc79SJean-Philippe Brucker 
20933f1ce8e8SJean-Philippe Brucker 	mutex_unlock(&arm_smmu_asid_lock);
209448ec83bcSWill Deacon 	return 0;
209548ec83bcSWill Deacon 
2096492ddc79SJean-Philippe Brucker out_free_cd_tables:
2097492ddc79SJean-Philippe Brucker 	arm_smmu_free_cd_tables(smmu_domain);
209848ec83bcSWill Deacon out_free_asid:
20990299a1a8SJean-Philippe Brucker 	arm_smmu_free_asid(&cfg->cd);
21003f1ce8e8SJean-Philippe Brucker out_unlock:
21013f1ce8e8SJean-Philippe Brucker 	mutex_unlock(&arm_smmu_asid_lock);
210248ec83bcSWill Deacon 	return ret;
210348ec83bcSWill Deacon }
210448ec83bcSWill Deacon 
210548ec83bcSWill Deacon static int arm_smmu_domain_finalise_s2(struct arm_smmu_domain *smmu_domain,
21062505ec6fSJean-Philippe Brucker 				       struct arm_smmu_master *master,
210748ec83bcSWill Deacon 				       struct io_pgtable_cfg *pgtbl_cfg)
210848ec83bcSWill Deacon {
2109c0733a2cSWill Deacon 	int vmid;
211048ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
211148ec83bcSWill Deacon 	struct arm_smmu_s2_cfg *cfg = &smmu_domain->s2_cfg;
2112ac4b80e5SWill Deacon 	typeof(&pgtbl_cfg->arm_lpae_s2_cfg.vtcr) vtcr;
211348ec83bcSWill Deacon 
211448ec83bcSWill Deacon 	vmid = arm_smmu_bitmap_alloc(smmu->vmid_map, smmu->vmid_bits);
2115287980e4SArnd Bergmann 	if (vmid < 0)
211648ec83bcSWill Deacon 		return vmid;
211748ec83bcSWill Deacon 
2118ac4b80e5SWill Deacon 	vtcr = &pgtbl_cfg->arm_lpae_s2_cfg.vtcr;
2119c0733a2cSWill Deacon 	cfg->vmid	= (u16)vmid;
212048ec83bcSWill Deacon 	cfg->vttbr	= pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
2121ac4b80e5SWill Deacon 	cfg->vtcr	= FIELD_PREP(STRTAB_STE_2_VTCR_S2T0SZ, vtcr->tsz) |
2122ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2SL0, vtcr->sl) |
2123ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2IR0, vtcr->irgn) |
2124ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2OR0, vtcr->orgn) |
2125ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2SH0, vtcr->sh) |
2126ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2TG, vtcr->tg) |
2127ac4b80e5SWill Deacon 			  FIELD_PREP(STRTAB_STE_2_VTCR_S2PS, vtcr->ps);
212848ec83bcSWill Deacon 	return 0;
212948ec83bcSWill Deacon }
213048ec83bcSWill Deacon 
21312505ec6fSJean-Philippe Brucker static int arm_smmu_domain_finalise(struct iommu_domain *domain,
21322505ec6fSJean-Philippe Brucker 				    struct arm_smmu_master *master)
213348ec83bcSWill Deacon {
213448ec83bcSWill Deacon 	int ret;
213548ec83bcSWill Deacon 	unsigned long ias, oas;
213648ec83bcSWill Deacon 	enum io_pgtable_fmt fmt;
213748ec83bcSWill Deacon 	struct io_pgtable_cfg pgtbl_cfg;
213848ec83bcSWill Deacon 	struct io_pgtable_ops *pgtbl_ops;
213948ec83bcSWill Deacon 	int (*finalise_stage_fn)(struct arm_smmu_domain *,
21402505ec6fSJean-Philippe Brucker 				 struct arm_smmu_master *,
214148ec83bcSWill Deacon 				 struct io_pgtable_cfg *);
214248ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
214348ec83bcSWill Deacon 	struct arm_smmu_device *smmu = smmu_domain->smmu;
214448ec83bcSWill Deacon 
2145beb3c6a0SWill Deacon 	if (domain->type == IOMMU_DOMAIN_IDENTITY) {
2146beb3c6a0SWill Deacon 		smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
2147beb3c6a0SWill Deacon 		return 0;
2148beb3c6a0SWill Deacon 	}
2149beb3c6a0SWill Deacon 
215048ec83bcSWill Deacon 	/* Restrict the stage to what we can actually support */
215148ec83bcSWill Deacon 	if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
215248ec83bcSWill Deacon 		smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
215348ec83bcSWill Deacon 	if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S2))
215448ec83bcSWill Deacon 		smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
215548ec83bcSWill Deacon 
215648ec83bcSWill Deacon 	switch (smmu_domain->stage) {
215748ec83bcSWill Deacon 	case ARM_SMMU_DOMAIN_S1:
2158dcd189e6SRobin Murphy 		ias = (smmu->features & ARM_SMMU_FEAT_VAX) ? 52 : 48;
2159dcd189e6SRobin Murphy 		ias = min_t(unsigned long, ias, VA_BITS);
216048ec83bcSWill Deacon 		oas = smmu->ias;
216148ec83bcSWill Deacon 		fmt = ARM_64_LPAE_S1;
216248ec83bcSWill Deacon 		finalise_stage_fn = arm_smmu_domain_finalise_s1;
216348ec83bcSWill Deacon 		break;
216448ec83bcSWill Deacon 	case ARM_SMMU_DOMAIN_NESTED:
216548ec83bcSWill Deacon 	case ARM_SMMU_DOMAIN_S2:
216648ec83bcSWill Deacon 		ias = smmu->ias;
216748ec83bcSWill Deacon 		oas = smmu->oas;
216848ec83bcSWill Deacon 		fmt = ARM_64_LPAE_S2;
216948ec83bcSWill Deacon 		finalise_stage_fn = arm_smmu_domain_finalise_s2;
217048ec83bcSWill Deacon 		break;
217148ec83bcSWill Deacon 	default:
217248ec83bcSWill Deacon 		return -EINVAL;
217348ec83bcSWill Deacon 	}
217448ec83bcSWill Deacon 
217548ec83bcSWill Deacon 	pgtbl_cfg = (struct io_pgtable_cfg) {
2176d5466357SRobin Murphy 		.pgsize_bitmap	= smmu->pgsize_bitmap,
217748ec83bcSWill Deacon 		.ias		= ias,
217848ec83bcSWill Deacon 		.oas		= oas,
21794f41845bSWill Deacon 		.coherent_walk	= smmu->features & ARM_SMMU_FEAT_COHERENCY,
2180298f7889SWill Deacon 		.tlb		= &arm_smmu_flush_ops,
2181bdc6d973SRobin Murphy 		.iommu_dev	= smmu->dev,
218248ec83bcSWill Deacon 	};
218348ec83bcSWill Deacon 
2184a250c23fSRobin Murphy 	if (!iommu_get_dma_strict(domain))
21859662b99aSZhen Lei 		pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT;
21869662b99aSZhen Lei 
218748ec83bcSWill Deacon 	pgtbl_ops = alloc_io_pgtable_ops(fmt, &pgtbl_cfg, smmu_domain);
218848ec83bcSWill Deacon 	if (!pgtbl_ops)
218948ec83bcSWill Deacon 		return -ENOMEM;
219048ec83bcSWill Deacon 
2191d5466357SRobin Murphy 	domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
21926619c913SRobin Murphy 	domain->geometry.aperture_end = (1UL << pgtbl_cfg.ias) - 1;
2193455eb7d3SRobin Murphy 	domain->geometry.force_aperture = true;
219448ec83bcSWill Deacon 
21952505ec6fSJean-Philippe Brucker 	ret = finalise_stage_fn(smmu_domain, master, &pgtbl_cfg);
219657d72e15SJean-Philippe Brucker 	if (ret < 0) {
219748ec83bcSWill Deacon 		free_io_pgtable_ops(pgtbl_ops);
219848ec83bcSWill Deacon 		return ret;
219948ec83bcSWill Deacon 	}
220048ec83bcSWill Deacon 
220157d72e15SJean-Philippe Brucker 	smmu_domain->pgtbl_ops = pgtbl_ops;
220257d72e15SJean-Philippe Brucker 	return 0;
220357d72e15SJean-Philippe Brucker }
220457d72e15SJean-Philippe Brucker 
220548ec83bcSWill Deacon static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
220648ec83bcSWill Deacon {
220748ec83bcSWill Deacon 	__le64 *step;
220848ec83bcSWill Deacon 	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
220948ec83bcSWill Deacon 
221048ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
221148ec83bcSWill Deacon 		struct arm_smmu_strtab_l1_desc *l1_desc;
221248ec83bcSWill Deacon 		int idx;
221348ec83bcSWill Deacon 
221448ec83bcSWill Deacon 		/* Two-level walk */
221548ec83bcSWill Deacon 		idx = (sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS;
221648ec83bcSWill Deacon 		l1_desc = &cfg->l1_desc[idx];
221748ec83bcSWill Deacon 		idx = (sid & ((1 << STRTAB_SPLIT) - 1)) * STRTAB_STE_DWORDS;
221848ec83bcSWill Deacon 		step = &l1_desc->l2ptr[idx];
221948ec83bcSWill Deacon 	} else {
222048ec83bcSWill Deacon 		/* Simple linear lookup */
222148ec83bcSWill Deacon 		step = &cfg->strtab[sid * STRTAB_STE_DWORDS];
222248ec83bcSWill Deacon 	}
222348ec83bcSWill Deacon 
222448ec83bcSWill Deacon 	return step;
222548ec83bcSWill Deacon }
222648ec83bcSWill Deacon 
2227bcecaee4SJean-Philippe Brucker static void arm_smmu_install_ste_for_dev(struct arm_smmu_master *master)
222848ec83bcSWill Deacon {
2229563b5cbeSRobin Murphy 	int i, j;
22308f785154SRobin Murphy 	struct arm_smmu_device *smmu = master->smmu;
223148ec83bcSWill Deacon 
2232cdf315f9SJean-Philippe Brucker 	for (i = 0; i < master->num_streams; ++i) {
2233cdf315f9SJean-Philippe Brucker 		u32 sid = master->streams[i].id;
223448ec83bcSWill Deacon 		__le64 *step = arm_smmu_get_step_for_sid(smmu, sid);
223548ec83bcSWill Deacon 
2236563b5cbeSRobin Murphy 		/* Bridged PCI devices may end up with duplicated IDs */
2237563b5cbeSRobin Murphy 		for (j = 0; j < i; j++)
2238cdf315f9SJean-Philippe Brucker 			if (master->streams[j].id == sid)
2239563b5cbeSRobin Murphy 				break;
2240563b5cbeSRobin Murphy 		if (j < i)
2241563b5cbeSRobin Murphy 			continue;
2242563b5cbeSRobin Murphy 
22438be39a1aSJean-Philippe Brucker 		arm_smmu_write_strtab_ent(master, sid, step);
224448ec83bcSWill Deacon 	}
224548ec83bcSWill Deacon }
224648ec83bcSWill Deacon 
2247bfff88ecSWill Deacon static bool arm_smmu_ats_supported(struct arm_smmu_master *master)
22489ce27afcSJean-Philippe Brucker {
22490b2527a6SJean-Philippe Brucker 	struct device *dev = master->dev;
22509ce27afcSJean-Philippe Brucker 	struct arm_smmu_device *smmu = master->smmu;
22510b2527a6SJean-Philippe Brucker 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
22529ce27afcSJean-Philippe Brucker 
22530b2527a6SJean-Philippe Brucker 	if (!(smmu->features & ARM_SMMU_FEAT_ATS))
2254bfff88ecSWill Deacon 		return false;
22559ce27afcSJean-Philippe Brucker 
22560b2527a6SJean-Philippe Brucker 	if (!(fwspec->flags & IOMMU_FWSPEC_PCI_RC_ATS))
2257097a7df2SYueHaibing 		return false;
22580b2527a6SJean-Philippe Brucker 
22590b2527a6SJean-Philippe Brucker 	return dev_is_pci(dev) && pci_ats_supported(to_pci_dev(dev));
2260097a7df2SYueHaibing }
2261bfff88ecSWill Deacon 
2262bfff88ecSWill Deacon static void arm_smmu_enable_ats(struct arm_smmu_master *master)
2263bfff88ecSWill Deacon {
2264bfff88ecSWill Deacon 	size_t stu;
2265bfff88ecSWill Deacon 	struct pci_dev *pdev;
2266bfff88ecSWill Deacon 	struct arm_smmu_device *smmu = master->smmu;
2267cdb8a3c3SWill Deacon 	struct arm_smmu_domain *smmu_domain = master->domain;
2268bfff88ecSWill Deacon 
2269bfff88ecSWill Deacon 	/* Don't enable ATS at the endpoint if it's not enabled in the STE */
2270bfff88ecSWill Deacon 	if (!master->ats_enabled)
2271bfff88ecSWill Deacon 		return;
22729ce27afcSJean-Philippe Brucker 
22739ce27afcSJean-Philippe Brucker 	/* Smallest Translation Unit: log2 of the smallest supported granule */
22749ce27afcSJean-Philippe Brucker 	stu = __ffs(smmu->pgsize_bitmap);
2275bfff88ecSWill Deacon 	pdev = to_pci_dev(master->dev);
22769ce27afcSJean-Philippe Brucker 
2277cdb8a3c3SWill Deacon 	atomic_inc(&smmu_domain->nr_ats_masters);
2278cdb8a3c3SWill Deacon 	arm_smmu_atc_inv_domain(smmu_domain, 0, 0, 0);
2279bfff88ecSWill Deacon 	if (pci_enable_ats(pdev, stu))
2280bfff88ecSWill Deacon 		dev_err(master->dev, "Failed to enable ATS (STU %zu)\n", stu);
22819ce27afcSJean-Philippe Brucker }
22829ce27afcSJean-Philippe Brucker 
22839ce27afcSJean-Philippe Brucker static void arm_smmu_disable_ats(struct arm_smmu_master *master)
22849ce27afcSJean-Philippe Brucker {
2285cdb8a3c3SWill Deacon 	struct arm_smmu_domain *smmu_domain = master->domain;
22868dd8f005SJean-Philippe Brucker 
2287bfff88ecSWill Deacon 	if (!master->ats_enabled)
22889ce27afcSJean-Philippe Brucker 		return;
22899ce27afcSJean-Philippe Brucker 
2290bfff88ecSWill Deacon 	pci_disable_ats(to_pci_dev(master->dev));
2291bfff88ecSWill Deacon 	/*
2292bfff88ecSWill Deacon 	 * Ensure ATS is disabled at the endpoint before we issue the
2293bfff88ecSWill Deacon 	 * ATC invalidation via the SMMU.
2294bfff88ecSWill Deacon 	 */
2295bfff88ecSWill Deacon 	wmb();
22969e773aeeSRob Herring 	arm_smmu_atc_inv_master(master);
2297cdb8a3c3SWill Deacon 	atomic_dec(&smmu_domain->nr_ats_masters);
22989ce27afcSJean-Philippe Brucker }
22999ce27afcSJean-Philippe Brucker 
2300058c59a0SJean-Philippe Brucker static int arm_smmu_enable_pasid(struct arm_smmu_master *master)
2301058c59a0SJean-Philippe Brucker {
2302058c59a0SJean-Philippe Brucker 	int ret;
2303058c59a0SJean-Philippe Brucker 	int features;
2304058c59a0SJean-Philippe Brucker 	int num_pasids;
2305058c59a0SJean-Philippe Brucker 	struct pci_dev *pdev;
2306058c59a0SJean-Philippe Brucker 
2307058c59a0SJean-Philippe Brucker 	if (!dev_is_pci(master->dev))
2308058c59a0SJean-Philippe Brucker 		return -ENODEV;
2309058c59a0SJean-Philippe Brucker 
2310058c59a0SJean-Philippe Brucker 	pdev = to_pci_dev(master->dev);
2311058c59a0SJean-Philippe Brucker 
2312058c59a0SJean-Philippe Brucker 	features = pci_pasid_features(pdev);
2313058c59a0SJean-Philippe Brucker 	if (features < 0)
2314058c59a0SJean-Philippe Brucker 		return features;
2315058c59a0SJean-Philippe Brucker 
2316058c59a0SJean-Philippe Brucker 	num_pasids = pci_max_pasids(pdev);
2317058c59a0SJean-Philippe Brucker 	if (num_pasids <= 0)
2318058c59a0SJean-Philippe Brucker 		return num_pasids;
2319058c59a0SJean-Philippe Brucker 
2320058c59a0SJean-Philippe Brucker 	ret = pci_enable_pasid(pdev, features);
2321058c59a0SJean-Philippe Brucker 	if (ret) {
2322058c59a0SJean-Philippe Brucker 		dev_err(&pdev->dev, "Failed to enable PASID\n");
2323058c59a0SJean-Philippe Brucker 		return ret;
2324058c59a0SJean-Philippe Brucker 	}
2325058c59a0SJean-Philippe Brucker 
2326058c59a0SJean-Philippe Brucker 	master->ssid_bits = min_t(u8, ilog2(num_pasids),
2327058c59a0SJean-Philippe Brucker 				  master->smmu->ssid_bits);
2328058c59a0SJean-Philippe Brucker 	return 0;
2329058c59a0SJean-Philippe Brucker }
2330058c59a0SJean-Philippe Brucker 
2331058c59a0SJean-Philippe Brucker static void arm_smmu_disable_pasid(struct arm_smmu_master *master)
2332058c59a0SJean-Philippe Brucker {
2333058c59a0SJean-Philippe Brucker 	struct pci_dev *pdev;
2334058c59a0SJean-Philippe Brucker 
2335058c59a0SJean-Philippe Brucker 	if (!dev_is_pci(master->dev))
2336058c59a0SJean-Philippe Brucker 		return;
2337058c59a0SJean-Philippe Brucker 
2338058c59a0SJean-Philippe Brucker 	pdev = to_pci_dev(master->dev);
2339058c59a0SJean-Philippe Brucker 
2340058c59a0SJean-Philippe Brucker 	if (!pdev->pasid_enabled)
2341058c59a0SJean-Philippe Brucker 		return;
2342058c59a0SJean-Philippe Brucker 
2343058c59a0SJean-Philippe Brucker 	master->ssid_bits = 0;
2344058c59a0SJean-Philippe Brucker 	pci_disable_pasid(pdev);
2345058c59a0SJean-Philippe Brucker }
2346058c59a0SJean-Philippe Brucker 
2347bcecaee4SJean-Philippe Brucker static void arm_smmu_detach_dev(struct arm_smmu_master *master)
2348bc7f2ce0SWill Deacon {
23492a7e62f5SJean-Philippe Brucker 	unsigned long flags;
23502a7e62f5SJean-Philippe Brucker 	struct arm_smmu_domain *smmu_domain = master->domain;
23512a7e62f5SJean-Philippe Brucker 
23522a7e62f5SJean-Philippe Brucker 	if (!smmu_domain)
23538be39a1aSJean-Philippe Brucker 		return;
23548be39a1aSJean-Philippe Brucker 
2355cdb8a3c3SWill Deacon 	arm_smmu_disable_ats(master);
2356cdb8a3c3SWill Deacon 
23572a7e62f5SJean-Philippe Brucker 	spin_lock_irqsave(&smmu_domain->devices_lock, flags);
23582a7e62f5SJean-Philippe Brucker 	list_del(&master->domain_head);
23592a7e62f5SJean-Philippe Brucker 	spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
23602a7e62f5SJean-Philippe Brucker 
23618be39a1aSJean-Philippe Brucker 	master->domain = NULL;
2362bfff88ecSWill Deacon 	master->ats_enabled = false;
2363bcecaee4SJean-Philippe Brucker 	arm_smmu_install_ste_for_dev(master);
2364bc7f2ce0SWill Deacon }
2365bc7f2ce0SWill Deacon 
236648ec83bcSWill Deacon static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
236748ec83bcSWill Deacon {
236848ec83bcSWill Deacon 	int ret = 0;
23692a7e62f5SJean-Philippe Brucker 	unsigned long flags;
23709b468f7dSJoerg Roedel 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
237148ec83bcSWill Deacon 	struct arm_smmu_device *smmu;
237248ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
2373b54f4260SJean-Philippe Brucker 	struct arm_smmu_master *master;
237448ec83bcSWill Deacon 
23759b468f7dSJoerg Roedel 	if (!fwspec)
237648ec83bcSWill Deacon 		return -ENOENT;
237748ec83bcSWill Deacon 
2378b7a9662fSJoerg Roedel 	master = dev_iommu_priv_get(dev);
23798f785154SRobin Murphy 	smmu = master->smmu;
23808f785154SRobin Murphy 
2381f534d98bSJean-Philippe Brucker 	/*
2382f534d98bSJean-Philippe Brucker 	 * Checking that SVA is disabled ensures that this device isn't bound to
2383f534d98bSJean-Philippe Brucker 	 * any mm, and can be safely detached from its old domain. Bonds cannot
2384f534d98bSJean-Philippe Brucker 	 * be removed concurrently since we're holding the group mutex.
2385f534d98bSJean-Philippe Brucker 	 */
2386f534d98bSJean-Philippe Brucker 	if (arm_smmu_master_sva_enabled(master)) {
2387f534d98bSJean-Philippe Brucker 		dev_err(dev, "cannot attach - SVA enabled\n");
2388f534d98bSJean-Philippe Brucker 		return -EBUSY;
2389f534d98bSJean-Philippe Brucker 	}
2390f534d98bSJean-Philippe Brucker 
2391bcecaee4SJean-Philippe Brucker 	arm_smmu_detach_dev(master);
239248ec83bcSWill Deacon 
239348ec83bcSWill Deacon 	mutex_lock(&smmu_domain->init_mutex);
239448ec83bcSWill Deacon 
239548ec83bcSWill Deacon 	if (!smmu_domain->smmu) {
239648ec83bcSWill Deacon 		smmu_domain->smmu = smmu;
23972505ec6fSJean-Philippe Brucker 		ret = arm_smmu_domain_finalise(domain, master);
239848ec83bcSWill Deacon 		if (ret) {
239948ec83bcSWill Deacon 			smmu_domain->smmu = NULL;
240048ec83bcSWill Deacon 			goto out_unlock;
240148ec83bcSWill Deacon 		}
240248ec83bcSWill Deacon 	} else if (smmu_domain->smmu != smmu) {
240348ec83bcSWill Deacon 		dev_err(dev,
240448ec83bcSWill Deacon 			"cannot attach to SMMU %s (upstream of %s)\n",
240548ec83bcSWill Deacon 			dev_name(smmu_domain->smmu->dev),
240648ec83bcSWill Deacon 			dev_name(smmu->dev));
240748ec83bcSWill Deacon 		ret = -ENXIO;
240848ec83bcSWill Deacon 		goto out_unlock;
24092505ec6fSJean-Philippe Brucker 	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
24102505ec6fSJean-Philippe Brucker 		   master->ssid_bits != smmu_domain->s1_cfg.s1cdmax) {
24112505ec6fSJean-Philippe Brucker 		dev_err(dev,
24122505ec6fSJean-Philippe Brucker 			"cannot attach to incompatible domain (%u SSID bits != %u)\n",
24132505ec6fSJean-Philippe Brucker 			smmu_domain->s1_cfg.s1cdmax, master->ssid_bits);
24142505ec6fSJean-Philippe Brucker 		ret = -EINVAL;
24152505ec6fSJean-Philippe Brucker 		goto out_unlock;
2416395ad89dSJean-Philippe Brucker 	} else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1 &&
2417395ad89dSJean-Philippe Brucker 		   smmu_domain->stall_enabled != master->stall_enabled) {
2418395ad89dSJean-Philippe Brucker 		dev_err(dev, "cannot attach to stall-%s domain\n",
2419395ad89dSJean-Philippe Brucker 			smmu_domain->stall_enabled ? "enabled" : "disabled");
2420395ad89dSJean-Philippe Brucker 		ret = -EINVAL;
2421395ad89dSJean-Philippe Brucker 		goto out_unlock;
242248ec83bcSWill Deacon 	}
242348ec83bcSWill Deacon 
24248be39a1aSJean-Philippe Brucker 	master->domain = smmu_domain;
242548ec83bcSWill Deacon 
24269ce27afcSJean-Philippe Brucker 	if (smmu_domain->stage != ARM_SMMU_DOMAIN_BYPASS)
2427bfff88ecSWill Deacon 		master->ats_enabled = arm_smmu_ats_supported(master);
24289ce27afcSJean-Philippe Brucker 
2429bcecaee4SJean-Philippe Brucker 	arm_smmu_install_ste_for_dev(master);
2430cdb8a3c3SWill Deacon 
2431cdb8a3c3SWill Deacon 	spin_lock_irqsave(&smmu_domain->devices_lock, flags);
2432cdb8a3c3SWill Deacon 	list_add(&master->domain_head, &smmu_domain->devices);
2433cdb8a3c3SWill Deacon 	spin_unlock_irqrestore(&smmu_domain->devices_lock, flags);
2434cdb8a3c3SWill Deacon 
2435bfff88ecSWill Deacon 	arm_smmu_enable_ats(master);
2436cdb8a3c3SWill Deacon 
243748ec83bcSWill Deacon out_unlock:
243848ec83bcSWill Deacon 	mutex_unlock(&smmu_domain->init_mutex);
243948ec83bcSWill Deacon 	return ret;
244048ec83bcSWill Deacon }
244148ec83bcSWill Deacon 
244248ec83bcSWill Deacon static int arm_smmu_map(struct iommu_domain *domain, unsigned long iova,
2443781ca2deSTom Murphy 			phys_addr_t paddr, size_t size, int prot, gfp_t gfp)
244448ec83bcSWill Deacon {
244558188afeSRobin Murphy 	struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
244648ec83bcSWill Deacon 
244748ec83bcSWill Deacon 	if (!ops)
244848ec83bcSWill Deacon 		return -ENODEV;
244948ec83bcSWill Deacon 
2450f34ce7a7SBaolin Wang 	return ops->map(ops, iova, paddr, size, prot, gfp);
245148ec83bcSWill Deacon }
245248ec83bcSWill Deacon 
245356f8af5eSWill Deacon static size_t arm_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
245456f8af5eSWill Deacon 			     size_t size, struct iommu_iotlb_gather *gather)
245548ec83bcSWill Deacon {
24569ce27afcSJean-Philippe Brucker 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
24579ce27afcSJean-Philippe Brucker 	struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
245848ec83bcSWill Deacon 
245948ec83bcSWill Deacon 	if (!ops)
246048ec83bcSWill Deacon 		return 0;
246148ec83bcSWill Deacon 
2462353e3cf8SWill Deacon 	return ops->unmap(ops, iova, size, gather);
246348ec83bcSWill Deacon }
246448ec83bcSWill Deacon 
246507fdef34SZhen Lei static void arm_smmu_flush_iotlb_all(struct iommu_domain *domain)
246607fdef34SZhen Lei {
246707fdef34SZhen Lei 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
246807fdef34SZhen Lei 
246907fdef34SZhen Lei 	if (smmu_domain->smmu)
247007fdef34SZhen Lei 		arm_smmu_tlb_inv_context(smmu_domain);
247107fdef34SZhen Lei }
247207fdef34SZhen Lei 
247356f8af5eSWill Deacon static void arm_smmu_iotlb_sync(struct iommu_domain *domain,
247456f8af5eSWill Deacon 				struct iommu_iotlb_gather *gather)
247532b12449SRobin Murphy {
24762af2e72bSWill Deacon 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
247732b12449SRobin Murphy 
24786cc7e5a9SXiang Chen 	if (!gather->pgsize)
24796cc7e5a9SXiang Chen 		return;
24806cc7e5a9SXiang Chen 
2481eba8d2f8SJean-Philippe Brucker 	arm_smmu_tlb_inv_range_domain(gather->start,
24827060377cSWill Deacon 				      gather->end - gather->start + 1,
24832af2e72bSWill Deacon 				      gather->pgsize, true, smmu_domain);
248432b12449SRobin Murphy }
248532b12449SRobin Murphy 
248648ec83bcSWill Deacon static phys_addr_t
248748ec83bcSWill Deacon arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
248848ec83bcSWill Deacon {
248958188afeSRobin Murphy 	struct io_pgtable_ops *ops = to_smmu_domain(domain)->pgtbl_ops;
249048ec83bcSWill Deacon 
2491bdf95923SSunil Goutham 	if (domain->type == IOMMU_DOMAIN_IDENTITY)
2492bdf95923SSunil Goutham 		return iova;
2493bdf95923SSunil Goutham 
249448ec83bcSWill Deacon 	if (!ops)
249548ec83bcSWill Deacon 		return 0;
249648ec83bcSWill Deacon 
249758188afeSRobin Murphy 	return ops->iova_to_phys(ops, iova);
249848ec83bcSWill Deacon }
249948ec83bcSWill Deacon 
25008f785154SRobin Murphy static struct platform_driver arm_smmu_driver;
25018f785154SRobin Murphy 
2502778de074SLorenzo Pieralisi static
2503778de074SLorenzo Pieralisi struct arm_smmu_device *arm_smmu_get_by_fwnode(struct fwnode_handle *fwnode)
250448ec83bcSWill Deacon {
250567843bbaSSuzuki K Poulose 	struct device *dev = driver_find_device_by_fwnode(&arm_smmu_driver.driver,
250667843bbaSSuzuki K Poulose 							  fwnode);
25078f785154SRobin Murphy 	put_device(dev);
25088f785154SRobin Murphy 	return dev ? dev_get_drvdata(dev) : NULL;
250948ec83bcSWill Deacon }
251048ec83bcSWill Deacon 
251148ec83bcSWill Deacon static bool arm_smmu_sid_in_range(struct arm_smmu_device *smmu, u32 sid)
251248ec83bcSWill Deacon {
251348ec83bcSWill Deacon 	unsigned long limit = smmu->strtab_cfg.num_l1_ents;
251448ec83bcSWill Deacon 
251548ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
251648ec83bcSWill Deacon 		limit *= 1UL << STRTAB_SPLIT;
251748ec83bcSWill Deacon 
251848ec83bcSWill Deacon 	return sid < limit;
251948ec83bcSWill Deacon }
252048ec83bcSWill Deacon 
2521cdf315f9SJean-Philippe Brucker static int arm_smmu_insert_master(struct arm_smmu_device *smmu,
2522cdf315f9SJean-Philippe Brucker 				  struct arm_smmu_master *master)
2523cdf315f9SJean-Philippe Brucker {
2524cdf315f9SJean-Philippe Brucker 	int i;
2525cdf315f9SJean-Philippe Brucker 	int ret = 0;
2526cdf315f9SJean-Philippe Brucker 	struct arm_smmu_stream *new_stream, *cur_stream;
2527cdf315f9SJean-Philippe Brucker 	struct rb_node **new_node, *parent_node = NULL;
2528cdf315f9SJean-Philippe Brucker 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
2529cdf315f9SJean-Philippe Brucker 
2530cdf315f9SJean-Philippe Brucker 	master->streams = kcalloc(fwspec->num_ids, sizeof(*master->streams),
2531cdf315f9SJean-Philippe Brucker 				  GFP_KERNEL);
2532cdf315f9SJean-Philippe Brucker 	if (!master->streams)
2533cdf315f9SJean-Philippe Brucker 		return -ENOMEM;
2534cdf315f9SJean-Philippe Brucker 	master->num_streams = fwspec->num_ids;
2535cdf315f9SJean-Philippe Brucker 
2536cdf315f9SJean-Philippe Brucker 	mutex_lock(&smmu->streams_mutex);
2537cdf315f9SJean-Philippe Brucker 	for (i = 0; i < fwspec->num_ids; i++) {
2538cdf315f9SJean-Philippe Brucker 		u32 sid = fwspec->ids[i];
2539cdf315f9SJean-Philippe Brucker 
2540cdf315f9SJean-Philippe Brucker 		new_stream = &master->streams[i];
2541cdf315f9SJean-Philippe Brucker 		new_stream->id = sid;
2542cdf315f9SJean-Philippe Brucker 		new_stream->master = master;
2543cdf315f9SJean-Philippe Brucker 
2544cdf315f9SJean-Philippe Brucker 		/*
2545cdf315f9SJean-Philippe Brucker 		 * Check the SIDs are in range of the SMMU and our stream table
2546cdf315f9SJean-Philippe Brucker 		 */
2547cdf315f9SJean-Philippe Brucker 		if (!arm_smmu_sid_in_range(smmu, sid)) {
2548cdf315f9SJean-Philippe Brucker 			ret = -ERANGE;
2549cdf315f9SJean-Philippe Brucker 			break;
2550cdf315f9SJean-Philippe Brucker 		}
2551cdf315f9SJean-Philippe Brucker 
2552cdf315f9SJean-Philippe Brucker 		/* Ensure l2 strtab is initialised */
2553cdf315f9SJean-Philippe Brucker 		if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
2554cdf315f9SJean-Philippe Brucker 			ret = arm_smmu_init_l2_strtab(smmu, sid);
2555cdf315f9SJean-Philippe Brucker 			if (ret)
2556cdf315f9SJean-Philippe Brucker 				break;
2557cdf315f9SJean-Philippe Brucker 		}
2558cdf315f9SJean-Philippe Brucker 
2559cdf315f9SJean-Philippe Brucker 		/* Insert into SID tree */
2560cdf315f9SJean-Philippe Brucker 		new_node = &(smmu->streams.rb_node);
2561cdf315f9SJean-Philippe Brucker 		while (*new_node) {
2562cdf315f9SJean-Philippe Brucker 			cur_stream = rb_entry(*new_node, struct arm_smmu_stream,
2563cdf315f9SJean-Philippe Brucker 					      node);
2564cdf315f9SJean-Philippe Brucker 			parent_node = *new_node;
2565cdf315f9SJean-Philippe Brucker 			if (cur_stream->id > new_stream->id) {
2566cdf315f9SJean-Philippe Brucker 				new_node = &((*new_node)->rb_left);
2567cdf315f9SJean-Philippe Brucker 			} else if (cur_stream->id < new_stream->id) {
2568cdf315f9SJean-Philippe Brucker 				new_node = &((*new_node)->rb_right);
2569cdf315f9SJean-Philippe Brucker 			} else {
2570cdf315f9SJean-Philippe Brucker 				dev_warn(master->dev,
2571cdf315f9SJean-Philippe Brucker 					 "stream %u already in tree\n",
2572cdf315f9SJean-Philippe Brucker 					 cur_stream->id);
2573cdf315f9SJean-Philippe Brucker 				ret = -EINVAL;
2574cdf315f9SJean-Philippe Brucker 				break;
2575cdf315f9SJean-Philippe Brucker 			}
2576cdf315f9SJean-Philippe Brucker 		}
2577cdf315f9SJean-Philippe Brucker 		if (ret)
2578cdf315f9SJean-Philippe Brucker 			break;
2579cdf315f9SJean-Philippe Brucker 
2580cdf315f9SJean-Philippe Brucker 		rb_link_node(&new_stream->node, parent_node, new_node);
2581cdf315f9SJean-Philippe Brucker 		rb_insert_color(&new_stream->node, &smmu->streams);
2582cdf315f9SJean-Philippe Brucker 	}
2583cdf315f9SJean-Philippe Brucker 
2584cdf315f9SJean-Philippe Brucker 	if (ret) {
2585cdf315f9SJean-Philippe Brucker 		for (i--; i >= 0; i--)
2586cdf315f9SJean-Philippe Brucker 			rb_erase(&master->streams[i].node, &smmu->streams);
2587cdf315f9SJean-Philippe Brucker 		kfree(master->streams);
2588cdf315f9SJean-Philippe Brucker 	}
2589cdf315f9SJean-Philippe Brucker 	mutex_unlock(&smmu->streams_mutex);
2590cdf315f9SJean-Philippe Brucker 
2591cdf315f9SJean-Philippe Brucker 	return ret;
2592cdf315f9SJean-Philippe Brucker }
2593cdf315f9SJean-Philippe Brucker 
2594cdf315f9SJean-Philippe Brucker static void arm_smmu_remove_master(struct arm_smmu_master *master)
2595cdf315f9SJean-Philippe Brucker {
2596cdf315f9SJean-Philippe Brucker 	int i;
2597cdf315f9SJean-Philippe Brucker 	struct arm_smmu_device *smmu = master->smmu;
2598cdf315f9SJean-Philippe Brucker 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(master->dev);
2599cdf315f9SJean-Philippe Brucker 
2600cdf315f9SJean-Philippe Brucker 	if (!smmu || !master->streams)
2601cdf315f9SJean-Philippe Brucker 		return;
2602cdf315f9SJean-Philippe Brucker 
2603cdf315f9SJean-Philippe Brucker 	mutex_lock(&smmu->streams_mutex);
2604cdf315f9SJean-Philippe Brucker 	for (i = 0; i < fwspec->num_ids; i++)
2605cdf315f9SJean-Philippe Brucker 		rb_erase(&master->streams[i].node, &smmu->streams);
2606cdf315f9SJean-Philippe Brucker 	mutex_unlock(&smmu->streams_mutex);
2607cdf315f9SJean-Philippe Brucker 
2608cdf315f9SJean-Philippe Brucker 	kfree(master->streams);
2609cdf315f9SJean-Philippe Brucker }
2610cdf315f9SJean-Philippe Brucker 
26118f785154SRobin Murphy static struct iommu_ops arm_smmu_ops;
26128f785154SRobin Murphy 
2613cefa0d55SJoerg Roedel static struct iommu_device *arm_smmu_probe_device(struct device *dev)
261448ec83bcSWill Deacon {
2615cdf315f9SJean-Philippe Brucker 	int ret;
261648ec83bcSWill Deacon 	struct arm_smmu_device *smmu;
2617b54f4260SJean-Philippe Brucker 	struct arm_smmu_master *master;
26189b468f7dSJoerg Roedel 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
261948ec83bcSWill Deacon 
26208f785154SRobin Murphy 	if (!fwspec || fwspec->ops != &arm_smmu_ops)
2621cefa0d55SJoerg Roedel 		return ERR_PTR(-ENODEV);
262292c1d360SWill Deacon 
2623b7a9662fSJoerg Roedel 	if (WARN_ON_ONCE(dev_iommu_priv_get(dev)))
2624cefa0d55SJoerg Roedel 		return ERR_PTR(-EBUSY);
262592c1d360SWill Deacon 
2626778de074SLorenzo Pieralisi 	smmu = arm_smmu_get_by_fwnode(fwspec->iommu_fwnode);
26278f785154SRobin Murphy 	if (!smmu)
2628cefa0d55SJoerg Roedel 		return ERR_PTR(-ENODEV);
262992c1d360SWill Deacon 
26308f785154SRobin Murphy 	master = kzalloc(sizeof(*master), GFP_KERNEL);
26318f785154SRobin Murphy 	if (!master)
2632cefa0d55SJoerg Roedel 		return ERR_PTR(-ENOMEM);
26338f785154SRobin Murphy 
26349ce27afcSJean-Philippe Brucker 	master->dev = dev;
26358f785154SRobin Murphy 	master->smmu = smmu;
2636f534d98bSJean-Philippe Brucker 	INIT_LIST_HEAD(&master->bonds);
2637b7a9662fSJoerg Roedel 	dev_iommu_priv_set(dev, master);
263848ec83bcSWill Deacon 
2639cdf315f9SJean-Philippe Brucker 	ret = arm_smmu_insert_master(smmu, master);
264048ec83bcSWill Deacon 	if (ret)
2641a2be6218SJean-Philippe Brucker 		goto err_free_master;
26428f785154SRobin Murphy 
2643434b73e6SJean-Philippe Brucker 	device_property_read_u32(dev, "pasid-num-bits", &master->ssid_bits);
2644434b73e6SJean-Philippe Brucker 	master->ssid_bits = min(smmu->ssid_bits, master->ssid_bits);
264589535821SJean-Philippe Brucker 
2646058c59a0SJean-Philippe Brucker 	/*
2647058c59a0SJean-Philippe Brucker 	 * Note that PASID must be enabled before, and disabled after ATS:
2648058c59a0SJean-Philippe Brucker 	 * PCI Express Base 4.0r1.0 - 10.5.1.3 ATS Control Register
2649058c59a0SJean-Philippe Brucker 	 *
2650058c59a0SJean-Philippe Brucker 	 *   Behavior is undefined if this bit is Set and the value of the PASID
2651058c59a0SJean-Philippe Brucker 	 *   Enable, Execute Requested Enable, or Privileged Mode Requested bits
2652058c59a0SJean-Philippe Brucker 	 *   are changed.
2653058c59a0SJean-Philippe Brucker 	 */
2654058c59a0SJean-Philippe Brucker 	arm_smmu_enable_pasid(master);
2655058c59a0SJean-Philippe Brucker 
265689535821SJean-Philippe Brucker 	if (!(smmu->features & ARM_SMMU_FEAT_2_LVL_CDTAB))
265789535821SJean-Philippe Brucker 		master->ssid_bits = min_t(u8, master->ssid_bits,
265889535821SJean-Philippe Brucker 					  CTXDESC_LINEAR_CDMAX);
265989535821SJean-Philippe Brucker 
2660395ad89dSJean-Philippe Brucker 	if ((smmu->features & ARM_SMMU_FEAT_STALLS &&
2661395ad89dSJean-Philippe Brucker 	     device_property_read_bool(dev, "dma-can-stall")) ||
2662395ad89dSJean-Philippe Brucker 	    smmu->features & ARM_SMMU_FEAT_STALL_FORCE)
2663395ad89dSJean-Philippe Brucker 		master->stall_enabled = true;
2664395ad89dSJean-Philippe Brucker 
2665cefa0d55SJoerg Roedel 	return &smmu->iommu;
2666a2be6218SJean-Philippe Brucker 
2667a2be6218SJean-Philippe Brucker err_free_master:
2668a2be6218SJean-Philippe Brucker 	kfree(master);
2669b7a9662fSJoerg Roedel 	dev_iommu_priv_set(dev, NULL);
2670cefa0d55SJoerg Roedel 	return ERR_PTR(ret);
26718f785154SRobin Murphy }
267248ec83bcSWill Deacon 
2673cefa0d55SJoerg Roedel static void arm_smmu_release_device(struct device *dev)
267448ec83bcSWill Deacon {
26759b468f7dSJoerg Roedel 	struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
2676b54f4260SJean-Philippe Brucker 	struct arm_smmu_master *master;
26778f785154SRobin Murphy 
26788f785154SRobin Murphy 	if (!fwspec || fwspec->ops != &arm_smmu_ops)
26798f785154SRobin Murphy 		return;
26808f785154SRobin Murphy 
2681b7a9662fSJoerg Roedel 	master = dev_iommu_priv_get(dev);
2682395ad89dSJean-Philippe Brucker 	if (WARN_ON(arm_smmu_master_sva_enabled(master)))
2683395ad89dSJean-Philippe Brucker 		iopf_queue_remove_device(master->smmu->evtq.iopf, dev);
2684bcecaee4SJean-Philippe Brucker 	arm_smmu_detach_dev(master);
2685058c59a0SJean-Philippe Brucker 	arm_smmu_disable_pasid(master);
2686cdf315f9SJean-Philippe Brucker 	arm_smmu_remove_master(master);
26878f785154SRobin Murphy 	kfree(master);
26888f785154SRobin Murphy 	iommu_fwspec_free(dev);
268948ec83bcSWill Deacon }
269048ec83bcSWill Deacon 
269108d4ca2aSRobin Murphy static struct iommu_group *arm_smmu_device_group(struct device *dev)
269208d4ca2aSRobin Murphy {
269308d4ca2aSRobin Murphy 	struct iommu_group *group;
269408d4ca2aSRobin Murphy 
269508d4ca2aSRobin Murphy 	/*
269608d4ca2aSRobin Murphy 	 * We don't support devices sharing stream IDs other than PCI RID
269708d4ca2aSRobin Murphy 	 * aliases, since the necessary ID-to-device lookup becomes rather
269808d4ca2aSRobin Murphy 	 * impractical given a potential sparse 32-bit stream ID space.
269908d4ca2aSRobin Murphy 	 */
270008d4ca2aSRobin Murphy 	if (dev_is_pci(dev))
270108d4ca2aSRobin Murphy 		group = pci_device_group(dev);
270208d4ca2aSRobin Murphy 	else
270308d4ca2aSRobin Murphy 		group = generic_device_group(dev);
270408d4ca2aSRobin Murphy 
270508d4ca2aSRobin Murphy 	return group;
270608d4ca2aSRobin Murphy }
270708d4ca2aSRobin Murphy 
27087e147547SChristoph Hellwig static int arm_smmu_enable_nesting(struct iommu_domain *domain)
270948ec83bcSWill Deacon {
271048ec83bcSWill Deacon 	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
271148ec83bcSWill Deacon 	int ret = 0;
271248ec83bcSWill Deacon 
271348ec83bcSWill Deacon 	mutex_lock(&smmu_domain->init_mutex);
27147e147547SChristoph Hellwig 	if (smmu_domain->smmu)
271548ec83bcSWill Deacon 		ret = -EPERM;
271648ec83bcSWill Deacon 	else
27177e147547SChristoph Hellwig 		smmu_domain->stage = ARM_SMMU_DOMAIN_NESTED;
271848ec83bcSWill Deacon 	mutex_unlock(&smmu_domain->init_mutex);
27197e147547SChristoph Hellwig 
272048ec83bcSWill Deacon 	return ret;
272148ec83bcSWill Deacon }
272248ec83bcSWill Deacon 
27238f785154SRobin Murphy static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
27248f785154SRobin Murphy {
27258f785154SRobin Murphy 	return iommu_fwspec_add_ids(dev, args->args, 1);
27268f785154SRobin Murphy }
27278f785154SRobin Murphy 
272850019f09SEric Auger static void arm_smmu_get_resv_regions(struct device *dev,
272950019f09SEric Auger 				      struct list_head *head)
273050019f09SEric Auger {
273150019f09SEric Auger 	struct iommu_resv_region *region;
273250019f09SEric Auger 	int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
273350019f09SEric Auger 
273450019f09SEric Auger 	region = iommu_alloc_resv_region(MSI_IOVA_BASE, MSI_IOVA_LENGTH,
27359d3a4de4SRobin Murphy 					 prot, IOMMU_RESV_SW_MSI);
273650019f09SEric Auger 	if (!region)
273750019f09SEric Auger 		return;
273850019f09SEric Auger 
273950019f09SEric Auger 	list_add_tail(&region->list, head);
2740273df963SRobin Murphy 
2741273df963SRobin Murphy 	iommu_dma_get_resv_regions(dev, head);
274250019f09SEric Auger }
274350019f09SEric Auger 
2744f534d98bSJean-Philippe Brucker static bool arm_smmu_dev_has_feature(struct device *dev,
2745f534d98bSJean-Philippe Brucker 				     enum iommu_dev_features feat)
2746f534d98bSJean-Philippe Brucker {
2747f534d98bSJean-Philippe Brucker 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
2748f534d98bSJean-Philippe Brucker 
2749f534d98bSJean-Philippe Brucker 	if (!master)
2750f534d98bSJean-Philippe Brucker 		return false;
2751f534d98bSJean-Philippe Brucker 
2752f534d98bSJean-Philippe Brucker 	switch (feat) {
2753395ad89dSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_IOPF:
2754395ad89dSJean-Philippe Brucker 		return arm_smmu_master_iopf_supported(master);
2755f534d98bSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_SVA:
2756f534d98bSJean-Philippe Brucker 		return arm_smmu_master_sva_supported(master);
2757f534d98bSJean-Philippe Brucker 	default:
2758f534d98bSJean-Philippe Brucker 		return false;
2759f534d98bSJean-Philippe Brucker 	}
2760f534d98bSJean-Philippe Brucker }
2761f534d98bSJean-Philippe Brucker 
2762f534d98bSJean-Philippe Brucker static bool arm_smmu_dev_feature_enabled(struct device *dev,
2763f534d98bSJean-Philippe Brucker 					 enum iommu_dev_features feat)
2764f534d98bSJean-Philippe Brucker {
2765f534d98bSJean-Philippe Brucker 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
2766f534d98bSJean-Philippe Brucker 
2767f534d98bSJean-Philippe Brucker 	if (!master)
2768f534d98bSJean-Philippe Brucker 		return false;
2769f534d98bSJean-Philippe Brucker 
2770f534d98bSJean-Philippe Brucker 	switch (feat) {
2771395ad89dSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_IOPF:
2772395ad89dSJean-Philippe Brucker 		return master->iopf_enabled;
2773f534d98bSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_SVA:
2774f534d98bSJean-Philippe Brucker 		return arm_smmu_master_sva_enabled(master);
2775f534d98bSJean-Philippe Brucker 	default:
2776f534d98bSJean-Philippe Brucker 		return false;
2777f534d98bSJean-Philippe Brucker 	}
2778f534d98bSJean-Philippe Brucker }
2779f534d98bSJean-Philippe Brucker 
2780f534d98bSJean-Philippe Brucker static int arm_smmu_dev_enable_feature(struct device *dev,
2781f534d98bSJean-Philippe Brucker 				       enum iommu_dev_features feat)
2782f534d98bSJean-Philippe Brucker {
2783395ad89dSJean-Philippe Brucker 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
2784395ad89dSJean-Philippe Brucker 
2785f534d98bSJean-Philippe Brucker 	if (!arm_smmu_dev_has_feature(dev, feat))
2786f534d98bSJean-Philippe Brucker 		return -ENODEV;
2787f534d98bSJean-Philippe Brucker 
2788f534d98bSJean-Philippe Brucker 	if (arm_smmu_dev_feature_enabled(dev, feat))
2789f534d98bSJean-Philippe Brucker 		return -EBUSY;
2790f534d98bSJean-Philippe Brucker 
2791f534d98bSJean-Philippe Brucker 	switch (feat) {
2792395ad89dSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_IOPF:
2793395ad89dSJean-Philippe Brucker 		master->iopf_enabled = true;
2794395ad89dSJean-Philippe Brucker 		return 0;
2795f534d98bSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_SVA:
2796395ad89dSJean-Philippe Brucker 		return arm_smmu_master_enable_sva(master);
2797f534d98bSJean-Philippe Brucker 	default:
2798f534d98bSJean-Philippe Brucker 		return -EINVAL;
2799f534d98bSJean-Philippe Brucker 	}
2800f534d98bSJean-Philippe Brucker }
2801f534d98bSJean-Philippe Brucker 
2802f534d98bSJean-Philippe Brucker static int arm_smmu_dev_disable_feature(struct device *dev,
2803f534d98bSJean-Philippe Brucker 					enum iommu_dev_features feat)
2804f534d98bSJean-Philippe Brucker {
2805395ad89dSJean-Philippe Brucker 	struct arm_smmu_master *master = dev_iommu_priv_get(dev);
2806395ad89dSJean-Philippe Brucker 
2807f534d98bSJean-Philippe Brucker 	if (!arm_smmu_dev_feature_enabled(dev, feat))
2808f534d98bSJean-Philippe Brucker 		return -EINVAL;
2809f534d98bSJean-Philippe Brucker 
2810f534d98bSJean-Philippe Brucker 	switch (feat) {
2811395ad89dSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_IOPF:
2812395ad89dSJean-Philippe Brucker 		if (master->sva_enabled)
2813395ad89dSJean-Philippe Brucker 			return -EBUSY;
2814395ad89dSJean-Philippe Brucker 		master->iopf_enabled = false;
2815395ad89dSJean-Philippe Brucker 		return 0;
2816f534d98bSJean-Philippe Brucker 	case IOMMU_DEV_FEAT_SVA:
2817395ad89dSJean-Philippe Brucker 		return arm_smmu_master_disable_sva(master);
2818f534d98bSJean-Philippe Brucker 	default:
2819f534d98bSJean-Philippe Brucker 		return -EINVAL;
2820f534d98bSJean-Philippe Brucker 	}
2821f534d98bSJean-Philippe Brucker }
2822f534d98bSJean-Philippe Brucker 
282348ec83bcSWill Deacon static struct iommu_ops arm_smmu_ops = {
282448ec83bcSWill Deacon 	.capable		= arm_smmu_capable,
282548ec83bcSWill Deacon 	.domain_alloc		= arm_smmu_domain_alloc,
282648ec83bcSWill Deacon 	.domain_free		= arm_smmu_domain_free,
282748ec83bcSWill Deacon 	.attach_dev		= arm_smmu_attach_dev,
282848ec83bcSWill Deacon 	.map			= arm_smmu_map,
282948ec83bcSWill Deacon 	.unmap			= arm_smmu_unmap,
283007fdef34SZhen Lei 	.flush_iotlb_all	= arm_smmu_flush_iotlb_all,
283132b12449SRobin Murphy 	.iotlb_sync		= arm_smmu_iotlb_sync,
283248ec83bcSWill Deacon 	.iova_to_phys		= arm_smmu_iova_to_phys,
2833cefa0d55SJoerg Roedel 	.probe_device		= arm_smmu_probe_device,
2834cefa0d55SJoerg Roedel 	.release_device		= arm_smmu_release_device,
283508d4ca2aSRobin Murphy 	.device_group		= arm_smmu_device_group,
28367e147547SChristoph Hellwig 	.enable_nesting		= arm_smmu_enable_nesting,
28378f785154SRobin Murphy 	.of_xlate		= arm_smmu_of_xlate,
283850019f09SEric Auger 	.get_resv_regions	= arm_smmu_get_resv_regions,
2839a66c5dc5SThierry Reding 	.put_resv_regions	= generic_iommu_put_resv_regions,
2840f534d98bSJean-Philippe Brucker 	.dev_has_feat		= arm_smmu_dev_has_feature,
2841f534d98bSJean-Philippe Brucker 	.dev_feat_enabled	= arm_smmu_dev_feature_enabled,
2842f534d98bSJean-Philippe Brucker 	.dev_enable_feat	= arm_smmu_dev_enable_feature,
2843f534d98bSJean-Philippe Brucker 	.dev_disable_feat	= arm_smmu_dev_disable_feature,
284432784a95SJean-Philippe Brucker 	.sva_bind		= arm_smmu_sva_bind,
284532784a95SJean-Philippe Brucker 	.sva_unbind		= arm_smmu_sva_unbind,
284632784a95SJean-Philippe Brucker 	.sva_get_pasid		= arm_smmu_sva_get_pasid,
2847395ad89dSJean-Philippe Brucker 	.page_response		= arm_smmu_page_response,
284848ec83bcSWill Deacon 	.pgsize_bitmap		= -1UL, /* Restricted during device attach */
2849c0aec668SRobin Murphy 	.owner			= THIS_MODULE,
285048ec83bcSWill Deacon };
285148ec83bcSWill Deacon 
285248ec83bcSWill Deacon /* Probing and initialisation functions */
285348ec83bcSWill Deacon static int arm_smmu_init_one_queue(struct arm_smmu_device *smmu,
285448ec83bcSWill Deacon 				   struct arm_smmu_queue *q,
285586d2d921SRobin Murphy 				   void __iomem *page,
285648ec83bcSWill Deacon 				   unsigned long prod_off,
285748ec83bcSWill Deacon 				   unsigned long cons_off,
2858d25f6eadSWill Deacon 				   size_t dwords, const char *name)
285948ec83bcSWill Deacon {
2860d25f6eadSWill Deacon 	size_t qsz;
286148ec83bcSWill Deacon 
2862d25f6eadSWill Deacon 	do {
286352be8637SWill Deacon 		qsz = ((1 << q->llq.max_n_shift) * dwords) << 3;
2864d25f6eadSWill Deacon 		q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma,
2865d25f6eadSWill Deacon 					      GFP_KERNEL);
2866d25f6eadSWill Deacon 		if (q->base || qsz < PAGE_SIZE)
2867d25f6eadSWill Deacon 			break;
2868d25f6eadSWill Deacon 
286952be8637SWill Deacon 		q->llq.max_n_shift--;
2870d25f6eadSWill Deacon 	} while (1);
2871d25f6eadSWill Deacon 
287248ec83bcSWill Deacon 	if (!q->base) {
2873d25f6eadSWill Deacon 		dev_err(smmu->dev,
2874d25f6eadSWill Deacon 			"failed to allocate queue (0x%zx bytes) for %s\n",
2875d25f6eadSWill Deacon 			qsz, name);
287648ec83bcSWill Deacon 		return -ENOMEM;
287748ec83bcSWill Deacon 	}
287848ec83bcSWill Deacon 
2879d25f6eadSWill Deacon 	if (!WARN_ON(q->base_dma & (qsz - 1))) {
2880d25f6eadSWill Deacon 		dev_info(smmu->dev, "allocated %u entries for %s\n",
288152be8637SWill Deacon 			 1 << q->llq.max_n_shift, name);
2882d25f6eadSWill Deacon 	}
2883d25f6eadSWill Deacon 
288486d2d921SRobin Murphy 	q->prod_reg	= page + prod_off;
288586d2d921SRobin Murphy 	q->cons_reg	= page + cons_off;
288648ec83bcSWill Deacon 	q->ent_dwords	= dwords;
288748ec83bcSWill Deacon 
288848ec83bcSWill Deacon 	q->q_base  = Q_BASE_RWA;
28891cf9e54eSRobin Murphy 	q->q_base |= q->base_dma & Q_BASE_ADDR_MASK;
289052be8637SWill Deacon 	q->q_base |= FIELD_PREP(Q_BASE_LOG2SIZE, q->llq.max_n_shift);
289148ec83bcSWill Deacon 
289252be8637SWill Deacon 	q->llq.prod = q->llq.cons = 0;
289348ec83bcSWill Deacon 	return 0;
289448ec83bcSWill Deacon }
289548ec83bcSWill Deacon 
2896587e6c10SWill Deacon static void arm_smmu_cmdq_free_bitmap(void *data)
2897587e6c10SWill Deacon {
2898587e6c10SWill Deacon 	unsigned long *bitmap = data;
2899587e6c10SWill Deacon 	bitmap_free(bitmap);
2900587e6c10SWill Deacon }
2901587e6c10SWill Deacon 
2902587e6c10SWill Deacon static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu)
2903587e6c10SWill Deacon {
2904587e6c10SWill Deacon 	int ret = 0;
2905587e6c10SWill Deacon 	struct arm_smmu_cmdq *cmdq = &smmu->cmdq;
2906587e6c10SWill Deacon 	unsigned int nents = 1 << cmdq->q.llq.max_n_shift;
2907587e6c10SWill Deacon 	atomic_long_t *bitmap;
2908587e6c10SWill Deacon 
2909587e6c10SWill Deacon 	atomic_set(&cmdq->owner_prod, 0);
2910587e6c10SWill Deacon 	atomic_set(&cmdq->lock, 0);
2911587e6c10SWill Deacon 
2912587e6c10SWill Deacon 	bitmap = (atomic_long_t *)bitmap_zalloc(nents, GFP_KERNEL);
2913587e6c10SWill Deacon 	if (!bitmap) {
2914587e6c10SWill Deacon 		dev_err(smmu->dev, "failed to allocate cmdq bitmap\n");
2915587e6c10SWill Deacon 		ret = -ENOMEM;
2916587e6c10SWill Deacon 	} else {
2917587e6c10SWill Deacon 		cmdq->valid_map = bitmap;
2918587e6c10SWill Deacon 		devm_add_action(smmu->dev, arm_smmu_cmdq_free_bitmap, bitmap);
2919587e6c10SWill Deacon 	}
2920587e6c10SWill Deacon 
2921587e6c10SWill Deacon 	return ret;
2922587e6c10SWill Deacon }
2923587e6c10SWill Deacon 
292448ec83bcSWill Deacon static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
292548ec83bcSWill Deacon {
292648ec83bcSWill Deacon 	int ret;
292748ec83bcSWill Deacon 
292848ec83bcSWill Deacon 	/* cmdq */
292986d2d921SRobin Murphy 	ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, smmu->base,
293086d2d921SRobin Murphy 				      ARM_SMMU_CMDQ_PROD, ARM_SMMU_CMDQ_CONS,
293186d2d921SRobin Murphy 				      CMDQ_ENT_DWORDS, "cmdq");
293248ec83bcSWill Deacon 	if (ret)
293304fa26c7SWill Deacon 		return ret;
293448ec83bcSWill Deacon 
2935587e6c10SWill Deacon 	ret = arm_smmu_cmdq_init(smmu);
2936587e6c10SWill Deacon 	if (ret)
2937587e6c10SWill Deacon 		return ret;
2938587e6c10SWill Deacon 
293948ec83bcSWill Deacon 	/* evtq */
294086d2d921SRobin Murphy 	ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, smmu->page1,
294186d2d921SRobin Murphy 				      ARM_SMMU_EVTQ_PROD, ARM_SMMU_EVTQ_CONS,
294286d2d921SRobin Murphy 				      EVTQ_ENT_DWORDS, "evtq");
294348ec83bcSWill Deacon 	if (ret)
294404fa26c7SWill Deacon 		return ret;
294548ec83bcSWill Deacon 
2946395ad89dSJean-Philippe Brucker 	if ((smmu->features & ARM_SMMU_FEAT_SVA) &&
2947395ad89dSJean-Philippe Brucker 	    (smmu->features & ARM_SMMU_FEAT_STALLS)) {
2948395ad89dSJean-Philippe Brucker 		smmu->evtq.iopf = iopf_queue_alloc(dev_name(smmu->dev));
2949395ad89dSJean-Philippe Brucker 		if (!smmu->evtq.iopf)
2950395ad89dSJean-Philippe Brucker 			return -ENOMEM;
2951395ad89dSJean-Philippe Brucker 	}
2952395ad89dSJean-Philippe Brucker 
295348ec83bcSWill Deacon 	/* priq */
295448ec83bcSWill Deacon 	if (!(smmu->features & ARM_SMMU_FEAT_PRI))
295548ec83bcSWill Deacon 		return 0;
295648ec83bcSWill Deacon 
295786d2d921SRobin Murphy 	return arm_smmu_init_one_queue(smmu, &smmu->priq.q, smmu->page1,
295886d2d921SRobin Murphy 				       ARM_SMMU_PRIQ_PROD, ARM_SMMU_PRIQ_CONS,
295986d2d921SRobin Murphy 				       PRIQ_ENT_DWORDS, "priq");
296048ec83bcSWill Deacon }
296148ec83bcSWill Deacon 
296248ec83bcSWill Deacon static int arm_smmu_init_l1_strtab(struct arm_smmu_device *smmu)
296348ec83bcSWill Deacon {
296448ec83bcSWill Deacon 	unsigned int i;
296548ec83bcSWill Deacon 	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
296648ec83bcSWill Deacon 	size_t size = sizeof(*cfg->l1_desc) * cfg->num_l1_ents;
296748ec83bcSWill Deacon 	void *strtab = smmu->strtab_cfg.strtab;
296848ec83bcSWill Deacon 
296948ec83bcSWill Deacon 	cfg->l1_desc = devm_kzalloc(smmu->dev, size, GFP_KERNEL);
297048ec83bcSWill Deacon 	if (!cfg->l1_desc) {
297148ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to allocate l1 stream table desc\n");
297248ec83bcSWill Deacon 		return -ENOMEM;
297348ec83bcSWill Deacon 	}
297448ec83bcSWill Deacon 
297548ec83bcSWill Deacon 	for (i = 0; i < cfg->num_l1_ents; ++i) {
297648ec83bcSWill Deacon 		arm_smmu_write_strtab_l1_desc(strtab, &cfg->l1_desc[i]);
297748ec83bcSWill Deacon 		strtab += STRTAB_L1_DESC_DWORDS << 3;
297848ec83bcSWill Deacon 	}
297948ec83bcSWill Deacon 
298048ec83bcSWill Deacon 	return 0;
298148ec83bcSWill Deacon }
298248ec83bcSWill Deacon 
298348ec83bcSWill Deacon static int arm_smmu_init_strtab_2lvl(struct arm_smmu_device *smmu)
298448ec83bcSWill Deacon {
298548ec83bcSWill Deacon 	void *strtab;
298648ec83bcSWill Deacon 	u64 reg;
2987d2e88e7cSWill Deacon 	u32 size, l1size;
298848ec83bcSWill Deacon 	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
298948ec83bcSWill Deacon 
2990692c4e42SNate Watterson 	/* Calculate the L1 size, capped to the SIDSIZE. */
299148ec83bcSWill Deacon 	size = STRTAB_L1_SZ_SHIFT - (ilog2(STRTAB_L1_DESC_DWORDS) + 3);
299248ec83bcSWill Deacon 	size = min(size, smmu->sid_bits - STRTAB_SPLIT);
2993d2e88e7cSWill Deacon 	cfg->num_l1_ents = 1 << size;
2994d2e88e7cSWill Deacon 
2995d2e88e7cSWill Deacon 	size += STRTAB_SPLIT;
2996d2e88e7cSWill Deacon 	if (size < smmu->sid_bits)
299748ec83bcSWill Deacon 		dev_warn(smmu->dev,
299848ec83bcSWill Deacon 			 "2-level strtab only covers %u/%u bits of SID\n",
2999d2e88e7cSWill Deacon 			 size, smmu->sid_bits);
300048ec83bcSWill Deacon 
3001d2e88e7cSWill Deacon 	l1size = cfg->num_l1_ents * (STRTAB_L1_DESC_DWORDS << 3);
300204fa26c7SWill Deacon 	strtab = dmam_alloc_coherent(smmu->dev, l1size, &cfg->strtab_dma,
30039bb9069cSJean-Philippe Brucker 				     GFP_KERNEL);
300448ec83bcSWill Deacon 	if (!strtab) {
300548ec83bcSWill Deacon 		dev_err(smmu->dev,
300648ec83bcSWill Deacon 			"failed to allocate l1 stream table (%u bytes)\n",
3007dc898eb8SZenghui Yu 			l1size);
300848ec83bcSWill Deacon 		return -ENOMEM;
300948ec83bcSWill Deacon 	}
301048ec83bcSWill Deacon 	cfg->strtab = strtab;
301148ec83bcSWill Deacon 
301248ec83bcSWill Deacon 	/* Configure strtab_base_cfg for 2 levels */
3013cbcee19aSRobin Murphy 	reg  = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_2LVL);
3014cbcee19aSRobin Murphy 	reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, size);
3015cbcee19aSRobin Murphy 	reg |= FIELD_PREP(STRTAB_BASE_CFG_SPLIT, STRTAB_SPLIT);
301648ec83bcSWill Deacon 	cfg->strtab_base_cfg = reg;
301748ec83bcSWill Deacon 
301804fa26c7SWill Deacon 	return arm_smmu_init_l1_strtab(smmu);
301948ec83bcSWill Deacon }
302048ec83bcSWill Deacon 
302148ec83bcSWill Deacon static int arm_smmu_init_strtab_linear(struct arm_smmu_device *smmu)
302248ec83bcSWill Deacon {
302348ec83bcSWill Deacon 	void *strtab;
302448ec83bcSWill Deacon 	u64 reg;
302548ec83bcSWill Deacon 	u32 size;
302648ec83bcSWill Deacon 	struct arm_smmu_strtab_cfg *cfg = &smmu->strtab_cfg;
302748ec83bcSWill Deacon 
302848ec83bcSWill Deacon 	size = (1 << smmu->sid_bits) * (STRTAB_STE_DWORDS << 3);
302904fa26c7SWill Deacon 	strtab = dmam_alloc_coherent(smmu->dev, size, &cfg->strtab_dma,
30309bb9069cSJean-Philippe Brucker 				     GFP_KERNEL);
303148ec83bcSWill Deacon 	if (!strtab) {
303248ec83bcSWill Deacon 		dev_err(smmu->dev,
303348ec83bcSWill Deacon 			"failed to allocate linear stream table (%u bytes)\n",
303448ec83bcSWill Deacon 			size);
303548ec83bcSWill Deacon 		return -ENOMEM;
303648ec83bcSWill Deacon 	}
303748ec83bcSWill Deacon 	cfg->strtab = strtab;
303848ec83bcSWill Deacon 	cfg->num_l1_ents = 1 << smmu->sid_bits;
303948ec83bcSWill Deacon 
304048ec83bcSWill Deacon 	/* Configure strtab_base_cfg for a linear table covering all SIDs */
3041cbcee19aSRobin Murphy 	reg  = FIELD_PREP(STRTAB_BASE_CFG_FMT, STRTAB_BASE_CFG_FMT_LINEAR);
3042cbcee19aSRobin Murphy 	reg |= FIELD_PREP(STRTAB_BASE_CFG_LOG2SIZE, smmu->sid_bits);
304348ec83bcSWill Deacon 	cfg->strtab_base_cfg = reg;
304448ec83bcSWill Deacon 
304548ec83bcSWill Deacon 	arm_smmu_init_bypass_stes(strtab, cfg->num_l1_ents);
304648ec83bcSWill Deacon 	return 0;
304748ec83bcSWill Deacon }
304848ec83bcSWill Deacon 
304948ec83bcSWill Deacon static int arm_smmu_init_strtab(struct arm_smmu_device *smmu)
305048ec83bcSWill Deacon {
305148ec83bcSWill Deacon 	u64 reg;
305248ec83bcSWill Deacon 	int ret;
305348ec83bcSWill Deacon 
305448ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB)
305548ec83bcSWill Deacon 		ret = arm_smmu_init_strtab_2lvl(smmu);
305648ec83bcSWill Deacon 	else
305748ec83bcSWill Deacon 		ret = arm_smmu_init_strtab_linear(smmu);
305848ec83bcSWill Deacon 
305948ec83bcSWill Deacon 	if (ret)
306048ec83bcSWill Deacon 		return ret;
306148ec83bcSWill Deacon 
306248ec83bcSWill Deacon 	/* Set the strtab base address */
30631cf9e54eSRobin Murphy 	reg  = smmu->strtab_cfg.strtab_dma & STRTAB_BASE_ADDR_MASK;
306448ec83bcSWill Deacon 	reg |= STRTAB_BASE_RA;
306548ec83bcSWill Deacon 	smmu->strtab_cfg.strtab_base = reg;
306648ec83bcSWill Deacon 
306748ec83bcSWill Deacon 	/* Allocate the first VMID for stage-2 bypass STEs */
306848ec83bcSWill Deacon 	set_bit(0, smmu->vmid_map);
306948ec83bcSWill Deacon 	return 0;
307048ec83bcSWill Deacon }
307148ec83bcSWill Deacon 
307248ec83bcSWill Deacon static int arm_smmu_init_structures(struct arm_smmu_device *smmu)
307348ec83bcSWill Deacon {
307448ec83bcSWill Deacon 	int ret;
307548ec83bcSWill Deacon 
3076cdf315f9SJean-Philippe Brucker 	mutex_init(&smmu->streams_mutex);
3077cdf315f9SJean-Philippe Brucker 	smmu->streams = RB_ROOT;
3078cdf315f9SJean-Philippe Brucker 
307948ec83bcSWill Deacon 	ret = arm_smmu_init_queues(smmu);
308048ec83bcSWill Deacon 	if (ret)
308148ec83bcSWill Deacon 		return ret;
308248ec83bcSWill Deacon 
308304fa26c7SWill Deacon 	return arm_smmu_init_strtab(smmu);
308448ec83bcSWill Deacon }
308548ec83bcSWill Deacon 
308648ec83bcSWill Deacon static int arm_smmu_write_reg_sync(struct arm_smmu_device *smmu, u32 val,
308748ec83bcSWill Deacon 				   unsigned int reg_off, unsigned int ack_off)
308848ec83bcSWill Deacon {
308948ec83bcSWill Deacon 	u32 reg;
309048ec83bcSWill Deacon 
309148ec83bcSWill Deacon 	writel_relaxed(val, smmu->base + reg_off);
309248ec83bcSWill Deacon 	return readl_relaxed_poll_timeout(smmu->base + ack_off, reg, reg == val,
309348ec83bcSWill Deacon 					  1, ARM_SMMU_POLL_TIMEOUT_US);
309448ec83bcSWill Deacon }
309548ec83bcSWill Deacon 
3096dc87a98dSRobin Murphy /* GBPA is "special" */
3097dc87a98dSRobin Murphy static int arm_smmu_update_gbpa(struct arm_smmu_device *smmu, u32 set, u32 clr)
3098dc87a98dSRobin Murphy {
3099dc87a98dSRobin Murphy 	int ret;
3100dc87a98dSRobin Murphy 	u32 reg, __iomem *gbpa = smmu->base + ARM_SMMU_GBPA;
3101dc87a98dSRobin Murphy 
3102dc87a98dSRobin Murphy 	ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
3103dc87a98dSRobin Murphy 					 1, ARM_SMMU_POLL_TIMEOUT_US);
3104dc87a98dSRobin Murphy 	if (ret)
3105dc87a98dSRobin Murphy 		return ret;
3106dc87a98dSRobin Murphy 
3107dc87a98dSRobin Murphy 	reg &= ~clr;
3108dc87a98dSRobin Murphy 	reg |= set;
3109dc87a98dSRobin Murphy 	writel_relaxed(reg | GBPA_UPDATE, gbpa);
3110b63b3439SWill Deacon 	ret = readl_relaxed_poll_timeout(gbpa, reg, !(reg & GBPA_UPDATE),
3111dc87a98dSRobin Murphy 					 1, ARM_SMMU_POLL_TIMEOUT_US);
3112b63b3439SWill Deacon 
3113b63b3439SWill Deacon 	if (ret)
3114b63b3439SWill Deacon 		dev_err(smmu->dev, "GBPA not responding to update\n");
3115b63b3439SWill Deacon 	return ret;
3116dc87a98dSRobin Murphy }
3117dc87a98dSRobin Murphy 
3118166bdbd2SMarc Zyngier static void arm_smmu_free_msis(void *data)
3119166bdbd2SMarc Zyngier {
3120166bdbd2SMarc Zyngier 	struct device *dev = data;
3121166bdbd2SMarc Zyngier 	platform_msi_domain_free_irqs(dev);
3122166bdbd2SMarc Zyngier }
3123166bdbd2SMarc Zyngier 
3124166bdbd2SMarc Zyngier static void arm_smmu_write_msi_msg(struct msi_desc *desc, struct msi_msg *msg)
3125166bdbd2SMarc Zyngier {
3126166bdbd2SMarc Zyngier 	phys_addr_t doorbell;
3127166bdbd2SMarc Zyngier 	struct device *dev = msi_desc_to_dev(desc);
3128166bdbd2SMarc Zyngier 	struct arm_smmu_device *smmu = dev_get_drvdata(dev);
3129166bdbd2SMarc Zyngier 	phys_addr_t *cfg = arm_smmu_msi_cfg[desc->platform.msi_index];
3130166bdbd2SMarc Zyngier 
3131166bdbd2SMarc Zyngier 	doorbell = (((u64)msg->address_hi) << 32) | msg->address_lo;
31321cf9e54eSRobin Murphy 	doorbell &= MSI_CFG0_ADDR_MASK;
3133166bdbd2SMarc Zyngier 
3134166bdbd2SMarc Zyngier 	writeq_relaxed(doorbell, smmu->base + cfg[0]);
3135166bdbd2SMarc Zyngier 	writel_relaxed(msg->data, smmu->base + cfg[1]);
3136cbcee19aSRobin Murphy 	writel_relaxed(ARM_SMMU_MEMATTR_DEVICE_nGnRE, smmu->base + cfg[2]);
3137166bdbd2SMarc Zyngier }
3138166bdbd2SMarc Zyngier 
3139166bdbd2SMarc Zyngier static void arm_smmu_setup_msis(struct arm_smmu_device *smmu)
3140166bdbd2SMarc Zyngier {
3141166bdbd2SMarc Zyngier 	struct msi_desc *desc;
3142166bdbd2SMarc Zyngier 	int ret, nvec = ARM_SMMU_MAX_MSIS;
3143166bdbd2SMarc Zyngier 	struct device *dev = smmu->dev;
3144166bdbd2SMarc Zyngier 
3145166bdbd2SMarc Zyngier 	/* Clear the MSI address regs */
3146166bdbd2SMarc Zyngier 	writeq_relaxed(0, smmu->base + ARM_SMMU_GERROR_IRQ_CFG0);
3147166bdbd2SMarc Zyngier 	writeq_relaxed(0, smmu->base + ARM_SMMU_EVTQ_IRQ_CFG0);
3148166bdbd2SMarc Zyngier 
3149166bdbd2SMarc Zyngier 	if (smmu->features & ARM_SMMU_FEAT_PRI)
3150166bdbd2SMarc Zyngier 		writeq_relaxed(0, smmu->base + ARM_SMMU_PRIQ_IRQ_CFG0);
3151166bdbd2SMarc Zyngier 	else
3152166bdbd2SMarc Zyngier 		nvec--;
3153166bdbd2SMarc Zyngier 
3154166bdbd2SMarc Zyngier 	if (!(smmu->features & ARM_SMMU_FEAT_MSI))
3155166bdbd2SMarc Zyngier 		return;
3156166bdbd2SMarc Zyngier 
3157940ded9cSNate Watterson 	if (!dev->msi_domain) {
3158940ded9cSNate Watterson 		dev_info(smmu->dev, "msi_domain absent - falling back to wired irqs\n");
3159940ded9cSNate Watterson 		return;
3160940ded9cSNate Watterson 	}
3161940ded9cSNate Watterson 
3162166bdbd2SMarc Zyngier 	/* Allocate MSIs for evtq, gerror and priq. Ignore cmdq */
3163166bdbd2SMarc Zyngier 	ret = platform_msi_domain_alloc_irqs(dev, nvec, arm_smmu_write_msi_msg);
3164166bdbd2SMarc Zyngier 	if (ret) {
3165940ded9cSNate Watterson 		dev_warn(dev, "failed to allocate MSIs - falling back to wired irqs\n");
3166166bdbd2SMarc Zyngier 		return;
3167166bdbd2SMarc Zyngier 	}
3168166bdbd2SMarc Zyngier 
3169166bdbd2SMarc Zyngier 	for_each_msi_entry(desc, dev) {
3170166bdbd2SMarc Zyngier 		switch (desc->platform.msi_index) {
3171166bdbd2SMarc Zyngier 		case EVTQ_MSI_INDEX:
3172166bdbd2SMarc Zyngier 			smmu->evtq.q.irq = desc->irq;
3173166bdbd2SMarc Zyngier 			break;
3174166bdbd2SMarc Zyngier 		case GERROR_MSI_INDEX:
3175166bdbd2SMarc Zyngier 			smmu->gerr_irq = desc->irq;
3176166bdbd2SMarc Zyngier 			break;
3177166bdbd2SMarc Zyngier 		case PRIQ_MSI_INDEX:
3178166bdbd2SMarc Zyngier 			smmu->priq.q.irq = desc->irq;
3179166bdbd2SMarc Zyngier 			break;
3180166bdbd2SMarc Zyngier 		default:	/* Unknown */
3181166bdbd2SMarc Zyngier 			continue;
3182166bdbd2SMarc Zyngier 		}
3183166bdbd2SMarc Zyngier 	}
3184166bdbd2SMarc Zyngier 
3185166bdbd2SMarc Zyngier 	/* Add callback to free MSIs on teardown */
3186166bdbd2SMarc Zyngier 	devm_add_action(dev, arm_smmu_free_msis, dev);
3187166bdbd2SMarc Zyngier }
3188166bdbd2SMarc Zyngier 
3189f935448aSGeetha Sowjanya static void arm_smmu_setup_unique_irqs(struct arm_smmu_device *smmu)
319048ec83bcSWill Deacon {
3191f935448aSGeetha Sowjanya 	int irq, ret;
319248ec83bcSWill Deacon 
3193166bdbd2SMarc Zyngier 	arm_smmu_setup_msis(smmu);
319448ec83bcSWill Deacon 
3195166bdbd2SMarc Zyngier 	/* Request interrupt lines */
319648ec83bcSWill Deacon 	irq = smmu->evtq.q.irq;
319748ec83bcSWill Deacon 	if (irq) {
3198b4163fb3SJean-Philippe Brucker 		ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
319948ec83bcSWill Deacon 						arm_smmu_evtq_thread,
3200b4163fb3SJean-Philippe Brucker 						IRQF_ONESHOT,
3201b4163fb3SJean-Philippe Brucker 						"arm-smmu-v3-evtq", smmu);
3202287980e4SArnd Bergmann 		if (ret < 0)
320348ec83bcSWill Deacon 			dev_warn(smmu->dev, "failed to enable evtq irq\n");
32044c8996d7SRobin Murphy 	} else {
32054c8996d7SRobin Murphy 		dev_warn(smmu->dev, "no evtq irq - events will not be reported!\n");
320648ec83bcSWill Deacon 	}
320748ec83bcSWill Deacon 
320848ec83bcSWill Deacon 	irq = smmu->gerr_irq;
320948ec83bcSWill Deacon 	if (irq) {
321048ec83bcSWill Deacon 		ret = devm_request_irq(smmu->dev, irq, arm_smmu_gerror_handler,
321148ec83bcSWill Deacon 				       0, "arm-smmu-v3-gerror", smmu);
3212287980e4SArnd Bergmann 		if (ret < 0)
321348ec83bcSWill Deacon 			dev_warn(smmu->dev, "failed to enable gerror irq\n");
32144c8996d7SRobin Murphy 	} else {
32154c8996d7SRobin Murphy 		dev_warn(smmu->dev, "no gerr irq - errors will not be reported!\n");
321648ec83bcSWill Deacon 	}
321748ec83bcSWill Deacon 
321848ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_PRI) {
321948ec83bcSWill Deacon 		irq = smmu->priq.q.irq;
322048ec83bcSWill Deacon 		if (irq) {
3221b4163fb3SJean-Philippe Brucker 			ret = devm_request_threaded_irq(smmu->dev, irq, NULL,
322248ec83bcSWill Deacon 							arm_smmu_priq_thread,
3223b4163fb3SJean-Philippe Brucker 							IRQF_ONESHOT,
3224b4163fb3SJean-Philippe Brucker 							"arm-smmu-v3-priq",
322548ec83bcSWill Deacon 							smmu);
3226287980e4SArnd Bergmann 			if (ret < 0)
322748ec83bcSWill Deacon 				dev_warn(smmu->dev,
322848ec83bcSWill Deacon 					 "failed to enable priq irq\n");
32294c8996d7SRobin Murphy 		} else {
32304c8996d7SRobin Murphy 			dev_warn(smmu->dev, "no priq irq - PRI will be broken\n");
3231f935448aSGeetha Sowjanya 		}
3232f935448aSGeetha Sowjanya 	}
3233f935448aSGeetha Sowjanya }
3234f935448aSGeetha Sowjanya 
3235f935448aSGeetha Sowjanya static int arm_smmu_setup_irqs(struct arm_smmu_device *smmu)
3236f935448aSGeetha Sowjanya {
3237f935448aSGeetha Sowjanya 	int ret, irq;
3238f935448aSGeetha Sowjanya 	u32 irqen_flags = IRQ_CTRL_EVTQ_IRQEN | IRQ_CTRL_GERROR_IRQEN;
3239f935448aSGeetha Sowjanya 
3240f935448aSGeetha Sowjanya 	/* Disable IRQs first */
3241f935448aSGeetha Sowjanya 	ret = arm_smmu_write_reg_sync(smmu, 0, ARM_SMMU_IRQ_CTRL,
3242f935448aSGeetha Sowjanya 				      ARM_SMMU_IRQ_CTRLACK);
3243f935448aSGeetha Sowjanya 	if (ret) {
3244f935448aSGeetha Sowjanya 		dev_err(smmu->dev, "failed to disable irqs\n");
3245f935448aSGeetha Sowjanya 		return ret;
3246f935448aSGeetha Sowjanya 	}
3247f935448aSGeetha Sowjanya 
3248f935448aSGeetha Sowjanya 	irq = smmu->combined_irq;
3249f935448aSGeetha Sowjanya 	if (irq) {
3250f935448aSGeetha Sowjanya 		/*
3251657135f3SJohn Garry 		 * Cavium ThunderX2 implementation doesn't support unique irq
3252657135f3SJohn Garry 		 * lines. Use a single irq line for all the SMMUv3 interrupts.
3253f935448aSGeetha Sowjanya 		 */
3254f935448aSGeetha Sowjanya 		ret = devm_request_threaded_irq(smmu->dev, irq,
3255f935448aSGeetha Sowjanya 					arm_smmu_combined_irq_handler,
3256f935448aSGeetha Sowjanya 					arm_smmu_combined_irq_thread,
3257f935448aSGeetha Sowjanya 					IRQF_ONESHOT,
3258f935448aSGeetha Sowjanya 					"arm-smmu-v3-combined-irq", smmu);
3259f935448aSGeetha Sowjanya 		if (ret < 0)
3260f935448aSGeetha Sowjanya 			dev_warn(smmu->dev, "failed to enable combined irq\n");
3261f935448aSGeetha Sowjanya 	} else
3262f935448aSGeetha Sowjanya 		arm_smmu_setup_unique_irqs(smmu);
3263f935448aSGeetha Sowjanya 
3264f935448aSGeetha Sowjanya 	if (smmu->features & ARM_SMMU_FEAT_PRI)
3265ccd6385dSMarc Zyngier 		irqen_flags |= IRQ_CTRL_PRIQ_IRQEN;
326648ec83bcSWill Deacon 
326748ec83bcSWill Deacon 	/* Enable interrupt generation on the SMMU */
3268ccd6385dSMarc Zyngier 	ret = arm_smmu_write_reg_sync(smmu, irqen_flags,
326948ec83bcSWill Deacon 				      ARM_SMMU_IRQ_CTRL, ARM_SMMU_IRQ_CTRLACK);
327048ec83bcSWill Deacon 	if (ret)
327148ec83bcSWill Deacon 		dev_warn(smmu->dev, "failed to enable irqs\n");
327248ec83bcSWill Deacon 
327348ec83bcSWill Deacon 	return 0;
327448ec83bcSWill Deacon }
327548ec83bcSWill Deacon 
327648ec83bcSWill Deacon static int arm_smmu_device_disable(struct arm_smmu_device *smmu)
327748ec83bcSWill Deacon {
327848ec83bcSWill Deacon 	int ret;
327948ec83bcSWill Deacon 
328048ec83bcSWill Deacon 	ret = arm_smmu_write_reg_sync(smmu, 0, ARM_SMMU_CR0, ARM_SMMU_CR0ACK);
328148ec83bcSWill Deacon 	if (ret)
328248ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to clear cr0\n");
328348ec83bcSWill Deacon 
328448ec83bcSWill Deacon 	return ret;
328548ec83bcSWill Deacon }
328648ec83bcSWill Deacon 
3287dc87a98dSRobin Murphy static int arm_smmu_device_reset(struct arm_smmu_device *smmu, bool bypass)
328848ec83bcSWill Deacon {
328948ec83bcSWill Deacon 	int ret;
329048ec83bcSWill Deacon 	u32 reg, enables;
329148ec83bcSWill Deacon 	struct arm_smmu_cmdq_ent cmd;
329248ec83bcSWill Deacon 
329348ec83bcSWill Deacon 	/* Clear CR0 and sync (disables SMMU and queue processing) */
329448ec83bcSWill Deacon 	reg = readl_relaxed(smmu->base + ARM_SMMU_CR0);
3295b63b3439SWill Deacon 	if (reg & CR0_SMMUEN) {
329648ec83bcSWill Deacon 		dev_warn(smmu->dev, "SMMU currently enabled! Resetting...\n");
32973f54c447SWill Deacon 		WARN_ON(is_kdump_kernel() && !disable_bypass);
32983f54c447SWill Deacon 		arm_smmu_update_gbpa(smmu, GBPA_ABORT, 0);
3299b63b3439SWill Deacon 	}
330048ec83bcSWill Deacon 
330148ec83bcSWill Deacon 	ret = arm_smmu_device_disable(smmu);
330248ec83bcSWill Deacon 	if (ret)
330348ec83bcSWill Deacon 		return ret;
330448ec83bcSWill Deacon 
330548ec83bcSWill Deacon 	/* CR1 (table and queue memory attributes) */
3306cbcee19aSRobin Murphy 	reg = FIELD_PREP(CR1_TABLE_SH, ARM_SMMU_SH_ISH) |
3307cbcee19aSRobin Murphy 	      FIELD_PREP(CR1_TABLE_OC, CR1_CACHE_WB) |
3308cbcee19aSRobin Murphy 	      FIELD_PREP(CR1_TABLE_IC, CR1_CACHE_WB) |
3309cbcee19aSRobin Murphy 	      FIELD_PREP(CR1_QUEUE_SH, ARM_SMMU_SH_ISH) |
3310cbcee19aSRobin Murphy 	      FIELD_PREP(CR1_QUEUE_OC, CR1_CACHE_WB) |
3311cbcee19aSRobin Murphy 	      FIELD_PREP(CR1_QUEUE_IC, CR1_CACHE_WB);
331248ec83bcSWill Deacon 	writel_relaxed(reg, smmu->base + ARM_SMMU_CR1);
331348ec83bcSWill Deacon 
331448ec83bcSWill Deacon 	/* CR2 (random crap) */
33159111aebfSJean-Philippe Brucker 	reg = CR2_PTM | CR2_RECINVSID;
33169111aebfSJean-Philippe Brucker 
33179111aebfSJean-Philippe Brucker 	if (smmu->features & ARM_SMMU_FEAT_E2H)
33189111aebfSJean-Philippe Brucker 		reg |= CR2_E2H;
33199111aebfSJean-Philippe Brucker 
332048ec83bcSWill Deacon 	writel_relaxed(reg, smmu->base + ARM_SMMU_CR2);
332148ec83bcSWill Deacon 
332248ec83bcSWill Deacon 	/* Stream table */
332348ec83bcSWill Deacon 	writeq_relaxed(smmu->strtab_cfg.strtab_base,
332448ec83bcSWill Deacon 		       smmu->base + ARM_SMMU_STRTAB_BASE);
332548ec83bcSWill Deacon 	writel_relaxed(smmu->strtab_cfg.strtab_base_cfg,
332648ec83bcSWill Deacon 		       smmu->base + ARM_SMMU_STRTAB_BASE_CFG);
332748ec83bcSWill Deacon 
332848ec83bcSWill Deacon 	/* Command queue */
332948ec83bcSWill Deacon 	writeq_relaxed(smmu->cmdq.q.q_base, smmu->base + ARM_SMMU_CMDQ_BASE);
333052be8637SWill Deacon 	writel_relaxed(smmu->cmdq.q.llq.prod, smmu->base + ARM_SMMU_CMDQ_PROD);
333152be8637SWill Deacon 	writel_relaxed(smmu->cmdq.q.llq.cons, smmu->base + ARM_SMMU_CMDQ_CONS);
333248ec83bcSWill Deacon 
333348ec83bcSWill Deacon 	enables = CR0_CMDQEN;
333448ec83bcSWill Deacon 	ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
333548ec83bcSWill Deacon 				      ARM_SMMU_CR0ACK);
333648ec83bcSWill Deacon 	if (ret) {
333748ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to enable command queue\n");
333848ec83bcSWill Deacon 		return ret;
333948ec83bcSWill Deacon 	}
334048ec83bcSWill Deacon 
334148ec83bcSWill Deacon 	/* Invalidate any cached configuration */
334248ec83bcSWill Deacon 	cmd.opcode = CMDQ_OP_CFGI_ALL;
334348ec83bcSWill Deacon 	arm_smmu_cmdq_issue_cmd(smmu, &cmd);
33442f657addSRobin Murphy 	arm_smmu_cmdq_issue_sync(smmu);
334548ec83bcSWill Deacon 
334648ec83bcSWill Deacon 	/* Invalidate any stale TLB entries */
334748ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_HYP) {
334848ec83bcSWill Deacon 		cmd.opcode = CMDQ_OP_TLBI_EL2_ALL;
334948ec83bcSWill Deacon 		arm_smmu_cmdq_issue_cmd(smmu, &cmd);
335048ec83bcSWill Deacon 	}
335148ec83bcSWill Deacon 
335248ec83bcSWill Deacon 	cmd.opcode = CMDQ_OP_TLBI_NSNH_ALL;
335348ec83bcSWill Deacon 	arm_smmu_cmdq_issue_cmd(smmu, &cmd);
33542f657addSRobin Murphy 	arm_smmu_cmdq_issue_sync(smmu);
335548ec83bcSWill Deacon 
335648ec83bcSWill Deacon 	/* Event queue */
335748ec83bcSWill Deacon 	writeq_relaxed(smmu->evtq.q.q_base, smmu->base + ARM_SMMU_EVTQ_BASE);
335886d2d921SRobin Murphy 	writel_relaxed(smmu->evtq.q.llq.prod, smmu->page1 + ARM_SMMU_EVTQ_PROD);
335986d2d921SRobin Murphy 	writel_relaxed(smmu->evtq.q.llq.cons, smmu->page1 + ARM_SMMU_EVTQ_CONS);
336048ec83bcSWill Deacon 
336148ec83bcSWill Deacon 	enables |= CR0_EVTQEN;
336248ec83bcSWill Deacon 	ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
336348ec83bcSWill Deacon 				      ARM_SMMU_CR0ACK);
336448ec83bcSWill Deacon 	if (ret) {
336548ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to enable event queue\n");
336648ec83bcSWill Deacon 		return ret;
336748ec83bcSWill Deacon 	}
336848ec83bcSWill Deacon 
336948ec83bcSWill Deacon 	/* PRI queue */
337048ec83bcSWill Deacon 	if (smmu->features & ARM_SMMU_FEAT_PRI) {
337148ec83bcSWill Deacon 		writeq_relaxed(smmu->priq.q.q_base,
337248ec83bcSWill Deacon 			       smmu->base + ARM_SMMU_PRIQ_BASE);
337352be8637SWill Deacon 		writel_relaxed(smmu->priq.q.llq.prod,
337486d2d921SRobin Murphy 			       smmu->page1 + ARM_SMMU_PRIQ_PROD);
337552be8637SWill Deacon 		writel_relaxed(smmu->priq.q.llq.cons,
337686d2d921SRobin Murphy 			       smmu->page1 + ARM_SMMU_PRIQ_CONS);
337748ec83bcSWill Deacon 
337848ec83bcSWill Deacon 		enables |= CR0_PRIQEN;
337948ec83bcSWill Deacon 		ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
338048ec83bcSWill Deacon 					      ARM_SMMU_CR0ACK);
338148ec83bcSWill Deacon 		if (ret) {
338248ec83bcSWill Deacon 			dev_err(smmu->dev, "failed to enable PRI queue\n");
338348ec83bcSWill Deacon 			return ret;
338448ec83bcSWill Deacon 		}
338548ec83bcSWill Deacon 	}
338648ec83bcSWill Deacon 
33879ce27afcSJean-Philippe Brucker 	if (smmu->features & ARM_SMMU_FEAT_ATS) {
33889ce27afcSJean-Philippe Brucker 		enables |= CR0_ATSCHK;
33899ce27afcSJean-Philippe Brucker 		ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
33909ce27afcSJean-Philippe Brucker 					      ARM_SMMU_CR0ACK);
33919ce27afcSJean-Philippe Brucker 		if (ret) {
33929ce27afcSJean-Philippe Brucker 			dev_err(smmu->dev, "failed to enable ATS check\n");
33939ce27afcSJean-Philippe Brucker 			return ret;
33949ce27afcSJean-Philippe Brucker 		}
33959ce27afcSJean-Philippe Brucker 	}
33969ce27afcSJean-Philippe Brucker 
339748ec83bcSWill Deacon 	ret = arm_smmu_setup_irqs(smmu);
339848ec83bcSWill Deacon 	if (ret) {
339948ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to setup irqs\n");
340048ec83bcSWill Deacon 		return ret;
340148ec83bcSWill Deacon 	}
340248ec83bcSWill Deacon 
34033f54c447SWill Deacon 	if (is_kdump_kernel())
34043f54c447SWill Deacon 		enables &= ~(CR0_EVTQEN | CR0_PRIQEN);
3405dc87a98dSRobin Murphy 
3406dc87a98dSRobin Murphy 	/* Enable the SMMU interface, or ensure bypass */
3407dc87a98dSRobin Murphy 	if (!bypass || disable_bypass) {
340848ec83bcSWill Deacon 		enables |= CR0_SMMUEN;
3409dc87a98dSRobin Murphy 	} else {
3410dc87a98dSRobin Murphy 		ret = arm_smmu_update_gbpa(smmu, 0, GBPA_ABORT);
3411b63b3439SWill Deacon 		if (ret)
3412dc87a98dSRobin Murphy 			return ret;
3413dc87a98dSRobin Murphy 	}
341448ec83bcSWill Deacon 	ret = arm_smmu_write_reg_sync(smmu, enables, ARM_SMMU_CR0,
341548ec83bcSWill Deacon 				      ARM_SMMU_CR0ACK);
341648ec83bcSWill Deacon 	if (ret) {
341748ec83bcSWill Deacon 		dev_err(smmu->dev, "failed to enable SMMU interface\n");
341848ec83bcSWill Deacon 		return ret;
341948ec83bcSWill Deacon 	}
342048ec83bcSWill Deacon 
342148ec83bcSWill Deacon 	return 0;
342248ec83bcSWill Deacon }
342348ec83bcSWill Deacon 
34242985b521SLorenzo Pieralisi static int arm_smmu_device_hw_probe(struct arm_smmu_device *smmu)
342548ec83bcSWill Deacon {
342648ec83bcSWill Deacon 	u32 reg;
34272985b521SLorenzo Pieralisi 	bool coherent = smmu->features & ARM_SMMU_FEAT_COHERENCY;
342848ec83bcSWill Deacon 
342948ec83bcSWill Deacon 	/* IDR0 */
343048ec83bcSWill Deacon 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
343148ec83bcSWill Deacon 
343248ec83bcSWill Deacon 	/* 2-level structures */
3433cbcee19aSRobin Murphy 	if (FIELD_GET(IDR0_ST_LVL, reg) == IDR0_ST_LVL_2LVL)
343448ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_2_LVL_STRTAB;
343548ec83bcSWill Deacon 
343648ec83bcSWill Deacon 	if (reg & IDR0_CD2L)
343748ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_2_LVL_CDTAB;
343848ec83bcSWill Deacon 
343948ec83bcSWill Deacon 	/*
344048ec83bcSWill Deacon 	 * Translation table endianness.
344148ec83bcSWill Deacon 	 * We currently require the same endianness as the CPU, but this
344248ec83bcSWill Deacon 	 * could be changed later by adding a new IO_PGTABLE_QUIRK.
344348ec83bcSWill Deacon 	 */
3444cbcee19aSRobin Murphy 	switch (FIELD_GET(IDR0_TTENDIAN, reg)) {
344548ec83bcSWill Deacon 	case IDR0_TTENDIAN_MIXED:
344648ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_TT_LE | ARM_SMMU_FEAT_TT_BE;
344748ec83bcSWill Deacon 		break;
344848ec83bcSWill Deacon #ifdef __BIG_ENDIAN
344948ec83bcSWill Deacon 	case IDR0_TTENDIAN_BE:
345048ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_TT_BE;
345148ec83bcSWill Deacon 		break;
345248ec83bcSWill Deacon #else
345348ec83bcSWill Deacon 	case IDR0_TTENDIAN_LE:
345448ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_TT_LE;
345548ec83bcSWill Deacon 		break;
345648ec83bcSWill Deacon #endif
345748ec83bcSWill Deacon 	default:
345848ec83bcSWill Deacon 		dev_err(smmu->dev, "unknown/unsupported TT endianness!\n");
345948ec83bcSWill Deacon 		return -ENXIO;
346048ec83bcSWill Deacon 	}
346148ec83bcSWill Deacon 
346248ec83bcSWill Deacon 	/* Boolean feature flags */
346348ec83bcSWill Deacon 	if (IS_ENABLED(CONFIG_PCI_PRI) && reg & IDR0_PRI)
346448ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_PRI;
346548ec83bcSWill Deacon 
346648ec83bcSWill Deacon 	if (IS_ENABLED(CONFIG_PCI_ATS) && reg & IDR0_ATS)
346748ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_ATS;
346848ec83bcSWill Deacon 
346948ec83bcSWill Deacon 	if (reg & IDR0_SEV)
347048ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_SEV;
347148ec83bcSWill Deacon 
3472bd07a20aSBarry Song 	if (reg & IDR0_MSI) {
347348ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_MSI;
3474bd07a20aSBarry Song 		if (coherent && !disable_msipolling)
3475bd07a20aSBarry Song 			smmu->options |= ARM_SMMU_OPT_MSIPOLL;
3476bd07a20aSBarry Song 	}
347748ec83bcSWill Deacon 
34789111aebfSJean-Philippe Brucker 	if (reg & IDR0_HYP) {
347948ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_HYP;
34809111aebfSJean-Philippe Brucker 		if (cpus_have_cap(ARM64_HAS_VIRT_HOST_EXTN))
34819111aebfSJean-Philippe Brucker 			smmu->features |= ARM_SMMU_FEAT_E2H;
34829111aebfSJean-Philippe Brucker 	}
348348ec83bcSWill Deacon 
348448ec83bcSWill Deacon 	/*
34852985b521SLorenzo Pieralisi 	 * The coherency feature as set by FW is used in preference to the ID
348648ec83bcSWill Deacon 	 * register, but warn on mismatch.
348748ec83bcSWill Deacon 	 */
348848ec83bcSWill Deacon 	if (!!(reg & IDR0_COHACC) != coherent)
34892a22baa2SRobin Murphy 		dev_warn(smmu->dev, "IDR0.COHACC overridden by FW configuration (%s)\n",
349048ec83bcSWill Deacon 			 coherent ? "true" : "false");
349148ec83bcSWill Deacon 
3492cbcee19aSRobin Murphy 	switch (FIELD_GET(IDR0_STALL_MODEL, reg)) {
34936380be05SPrem Mallappa 	case IDR0_STALL_MODEL_FORCE:
34949cff86fdSYisheng Xie 		smmu->features |= ARM_SMMU_FEAT_STALL_FORCE;
3495df561f66SGustavo A. R. Silva 		fallthrough;
34969cff86fdSYisheng Xie 	case IDR0_STALL_MODEL_STALL:
349748ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_STALLS;
34986380be05SPrem Mallappa 	}
349948ec83bcSWill Deacon 
350048ec83bcSWill Deacon 	if (reg & IDR0_S1P)
350148ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_TRANS_S1;
350248ec83bcSWill Deacon 
350348ec83bcSWill Deacon 	if (reg & IDR0_S2P)
350448ec83bcSWill Deacon 		smmu->features |= ARM_SMMU_FEAT_TRANS_S2;
350548ec83bcSWill Deacon 
350648ec83bcSWill Deacon 	if (!(reg & (IDR0_S1P | IDR0_S2P))) {
350748ec83bcSWill Deacon 		dev_err(smmu->dev, "no translation support!\n");
350848ec83bcSWill Deacon 		return -ENXIO;
350948ec83bcSWill Deacon 	}
351048ec83bcSWill Deacon 
351148ec83bcSWill Deacon 	/* We only support the AArch64 table format at present */
3512cbcee19aSRobin Murphy 	switch (FIELD_GET(IDR0_TTF, reg)) {
3513f0c453dbSWill Deacon 	case IDR0_TTF_AARCH32_64:
3514f0c453dbSWill Deacon 		smmu->ias = 40;
3515df561f66SGustavo A. R. Silva 		fallthrough;
3516f0c453dbSWill Deacon 	case IDR0_TTF_AARCH64:
3517f0c453dbSWill Deacon 		break;
3518f0c453dbSWill Deacon 	default:
351948ec83bcSWill Deacon 		dev_err(smmu->dev, "AArch64 table format not supported!\n");
352048ec83bcSWill Deacon 		return -ENXIO;
352148ec83bcSWill Deacon 	}
352248ec83bcSWill Deacon 
352348ec83bcSWill Deacon 	/* ASID/VMID sizes */
352448ec83bcSWill Deacon 	smmu->asid_bits = reg & IDR0_ASID16 ? 16 : 8;
352548ec83bcSWill Deacon 	smmu->vmid_bits = reg & IDR0_VMID16 ? 16 : 8;
352648ec83bcSWill Deacon 
352748ec83bcSWill Deacon 	/* IDR1 */
352848ec83bcSWill Deacon 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR1);
352948ec83bcSWill Deacon 	if (reg & (IDR1_TABLES_PRESET | IDR1_QUEUES_PRESET | IDR1_REL)) {
353048ec83bcSWill Deacon 		dev_err(smmu->dev, "embedded implementation not supported\n");
353148ec83bcSWill Deacon 		return -ENXIO;
353248ec83bcSWill Deacon 	}
353348ec83bcSWill Deacon 
3534d25f6eadSWill Deacon 	/* Queue sizes, capped to ensure natural alignment */
353552be8637SWill Deacon 	smmu->cmdq.q.llq.max_n_shift = min_t(u32, CMDQ_MAX_SZ_SHIFT,
3536cbcee19aSRobin Murphy 					     FIELD_GET(IDR1_CMDQS, reg));
35372af2e72bSWill Deacon 	if (smmu->cmdq.q.llq.max_n_shift <= ilog2(CMDQ_BATCH_ENTRIES)) {
3538587e6c10SWill Deacon 		/*
35392af2e72bSWill Deacon 		 * We don't support splitting up batches, so one batch of
35402af2e72bSWill Deacon 		 * commands plus an extra sync needs to fit inside the command
35412af2e72bSWill Deacon 		 * queue. There's also no way we can handle the weird alignment
35422af2e72bSWill Deacon 		 * restrictions on the base pointer for a unit-length queue.
3543587e6c10SWill Deacon 		 */
35442af2e72bSWill Deacon 		dev_err(smmu->dev, "command queue size <= %d entries not supported\n",
35452af2e72bSWill Deacon 			CMDQ_BATCH_ENTRIES);
354648ec83bcSWill Deacon 		return -ENXIO;
354748ec83bcSWill Deacon 	}
354848ec83bcSWill Deacon 
354952be8637SWill Deacon 	smmu->evtq.q.llq.max_n_shift = min_t(u32, EVTQ_MAX_SZ_SHIFT,
3550cbcee19aSRobin Murphy 					     FIELD_GET(IDR1_EVTQS, reg));
355152be8637SWill Deacon 	smmu->priq.q.llq.max_n_shift = min_t(u32, PRIQ_MAX_SZ_SHIFT,
3552cbcee19aSRobin Murphy 					     FIELD_GET(IDR1_PRIQS, reg));
355348ec83bcSWill Deacon 
355448ec83bcSWill Deacon 	/* SID/SSID sizes */
3555cbcee19aSRobin Murphy 	smmu->ssid_bits = FIELD_GET(IDR1_SSIDSIZE, reg);
3556cbcee19aSRobin Murphy 	smmu->sid_bits = FIELD_GET(IDR1_SIDSIZE, reg);
355748ec83bcSWill Deacon 
3558692c4e42SNate Watterson 	/*
3559692c4e42SNate Watterson 	 * If the SMMU supports fewer bits than would fill a single L2 stream
3560692c4e42SNate Watterson 	 * table, use a linear table instead.
3561692c4e42SNate Watterson 	 */
3562692c4e42SNate Watterson 	if (smmu->sid_bits <= STRTAB_SPLIT)
3563692c4e42SNate Watterson 		smmu->features &= ~ARM_SMMU_FEAT_2_LVL_STRTAB;
3564692c4e42SNate Watterson 
35656a481a95SRob Herring 	/* IDR3 */
35666a481a95SRob Herring 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR3);
35676a481a95SRob Herring 	if (FIELD_GET(IDR3_RIL, reg))
35686a481a95SRob Herring 		smmu->features |= ARM_SMMU_FEAT_RANGE_INV;
35696a481a95SRob Herring 
357048ec83bcSWill Deacon 	/* IDR5 */
357148ec83bcSWill Deacon 	reg = readl_relaxed(smmu->base + ARM_SMMU_IDR5);
357248ec83bcSWill Deacon 
357348ec83bcSWill Deacon 	/* Maximum number of outstanding stalls */
3574cbcee19aSRobin Murphy 	smmu->evtq.max_stalls = FIELD_GET(IDR5_STALL_MAX, reg);
357548ec83bcSWill Deacon 
357648ec83bcSWill Deacon 	/* Page sizes */
357748ec83bcSWill Deacon 	if (reg & IDR5_GRAN64K)
3578d5466357SRobin Murphy 		smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
357948ec83bcSWill Deacon 	if (reg & IDR5_GRAN16K)
3580d5466357SRobin Murphy 		smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
358148ec83bcSWill Deacon 	if (reg & IDR5_GRAN4K)
3582d5466357SRobin Murphy 		smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
358348ec83bcSWill Deacon 
3584dcd189e6SRobin Murphy 	/* Input address size */
3585dcd189e6SRobin Murphy 	if (FIELD_GET(IDR5_VAX, reg) == IDR5_VAX_52_BIT)
3586dcd189e6SRobin Murphy 		smmu->features |= ARM_SMMU_FEAT_VAX;
3587dcd189e6SRobin Murphy 
358848ec83bcSWill Deacon 	/* Output address size */
3589cbcee19aSRobin Murphy 	switch (FIELD_GET(IDR5_OAS, reg)) {
359048ec83bcSWill Deacon 	case IDR5_OAS_32_BIT:
359148ec83bcSWill Deacon 		smmu->oas = 32;
359248ec83bcSWill Deacon 		break;
359348ec83bcSWill Deacon 	case IDR5_OAS_36_BIT:
359448ec83bcSWill Deacon 		smmu->oas = 36;
359548ec83bcSWill Deacon 		break;
359648ec83bcSWill Deacon 	case IDR5_OAS_40_BIT:
359748ec83bcSWill Deacon 		smmu->oas = 40;
359848ec83bcSWill Deacon 		break;
359948ec83bcSWill Deacon 	case IDR5_OAS_42_BIT:
360048ec83bcSWill Deacon 		smmu->oas = 42;
360148ec83bcSWill Deacon 		break;
360248ec83bcSWill Deacon 	case IDR5_OAS_44_BIT:
360348ec83bcSWill Deacon 		smmu->oas = 44;
360448ec83bcSWill Deacon 		break;
36056619c913SRobin Murphy 	case IDR5_OAS_52_BIT:
36066619c913SRobin Murphy 		smmu->oas = 52;
36076619c913SRobin Murphy 		smmu->pgsize_bitmap |= 1ULL << 42; /* 4TB */
36086619c913SRobin Murphy 		break;
360985430968SWill Deacon 	default:
361085430968SWill Deacon 		dev_info(smmu->dev,
361185430968SWill Deacon 			"unknown output address size. Truncating to 48-bit\n");
3612df561f66SGustavo A. R. Silva 		fallthrough;
361348ec83bcSWill Deacon 	case IDR5_OAS_48_BIT:
361448ec83bcSWill Deacon 		smmu->oas = 48;
361548ec83bcSWill Deacon 	}
361648ec83bcSWill Deacon 
36176619c913SRobin Murphy 	if (arm_smmu_ops.pgsize_bitmap == -1UL)
36186619c913SRobin Murphy 		arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
36196619c913SRobin Murphy 	else
36206619c913SRobin Murphy 		arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
36216619c913SRobin Murphy 
362248ec83bcSWill Deacon 	/* Set the DMA mask for our table walker */
362348ec83bcSWill Deacon 	if (dma_set_mask_and_coherent(smmu->dev, DMA_BIT_MASK(smmu->oas)))
362448ec83bcSWill Deacon 		dev_warn(smmu->dev,
362548ec83bcSWill Deacon 			 "failed to set DMA mask for table walker\n");
362648ec83bcSWill Deacon 
3627f0c453dbSWill Deacon 	smmu->ias = max(smmu->ias, smmu->oas);
362848ec83bcSWill Deacon 
3629d744f9e6SJean-Philippe Brucker 	if (arm_smmu_sva_supported(smmu))
3630d744f9e6SJean-Philippe Brucker 		smmu->features |= ARM_SMMU_FEAT_SVA;
3631d744f9e6SJean-Philippe Brucker 
363248ec83bcSWill Deacon 	dev_info(smmu->dev, "ias %lu-bit, oas %lu-bit (features 0x%08x)\n",
363348ec83bcSWill Deacon 		 smmu->ias, smmu->oas, smmu->features);
363448ec83bcSWill Deacon 	return 0;
363548ec83bcSWill Deacon }
363648ec83bcSWill Deacon 
3637e4dadfa8SLorenzo Pieralisi #ifdef CONFIG_ACPI
3638e5b829deSLinu Cherian static void acpi_smmu_get_options(u32 model, struct arm_smmu_device *smmu)
3639e5b829deSLinu Cherian {
364099caf177Sshameer 	switch (model) {
364199caf177Sshameer 	case ACPI_IORT_SMMU_V3_CAVIUM_CN99XX:
3642e5b829deSLinu Cherian 		smmu->options |= ARM_SMMU_OPT_PAGE0_REGS_ONLY;
364399caf177Sshameer 		break;
36446948d4a7SRobin Murphy 	case ACPI_IORT_SMMU_V3_HISILICON_HI161X:
364599caf177Sshameer 		smmu->options |= ARM_SMMU_OPT_SKIP_PREFETCH;
364699caf177Sshameer 		break;
364799caf177Sshameer 	}
3648e5b829deSLinu Cherian 
3649e5b829deSLinu Cherian 	dev_notice(smmu->dev, "option mask 0x%x\n", smmu->options);
3650e5b829deSLinu Cherian }
3651e5b829deSLinu Cherian 
3652e4dadfa8SLorenzo Pieralisi static int arm_smmu_device_acpi_probe(struct platform_device *pdev,
3653e4dadfa8SLorenzo Pieralisi 				      struct arm_smmu_device *smmu)
3654e4dadfa8SLorenzo Pieralisi {
3655e4dadfa8SLorenzo Pieralisi 	struct acpi_iort_smmu_v3 *iort_smmu;
3656e4dadfa8SLorenzo Pieralisi 	struct device *dev = smmu->dev;
3657e4dadfa8SLorenzo Pieralisi 	struct acpi_iort_node *node;
3658e4dadfa8SLorenzo Pieralisi 
3659e4dadfa8SLorenzo Pieralisi 	node = *(struct acpi_iort_node **)dev_get_platdata(dev);
3660e4dadfa8SLorenzo Pieralisi 
3661e4dadfa8SLorenzo Pieralisi 	/* Retrieve SMMUv3 specific data */
3662e4dadfa8SLorenzo Pieralisi 	iort_smmu = (struct acpi_iort_smmu_v3 *)node->node_data;
3663e4dadfa8SLorenzo Pieralisi 
3664e5b829deSLinu Cherian 	acpi_smmu_get_options(iort_smmu->model, smmu);
3665e5b829deSLinu Cherian 
3666e4dadfa8SLorenzo Pieralisi 	if (iort_smmu->flags & ACPI_IORT_SMMU_V3_COHACC_OVERRIDE)
3667e4dadfa8SLorenzo Pieralisi 		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
3668e4dadfa8SLorenzo Pieralisi 
3669e4dadfa8SLorenzo Pieralisi 	return 0;
3670e4dadfa8SLorenzo Pieralisi }
3671e4dadfa8SLorenzo Pieralisi #else
3672e4dadfa8SLorenzo Pieralisi static inline int arm_smmu_device_acpi_probe(struct platform_device *pdev,
3673e4dadfa8SLorenzo Pieralisi 					     struct arm_smmu_device *smmu)
3674e4dadfa8SLorenzo Pieralisi {
3675e4dadfa8SLorenzo Pieralisi 	return -ENODEV;
3676e4dadfa8SLorenzo Pieralisi }
3677e4dadfa8SLorenzo Pieralisi #endif
3678e4dadfa8SLorenzo Pieralisi 
36792985b521SLorenzo Pieralisi static int arm_smmu_device_dt_probe(struct platform_device *pdev,
36802985b521SLorenzo Pieralisi 				    struct arm_smmu_device *smmu)
368148ec83bcSWill Deacon {
368248ec83bcSWill Deacon 	struct device *dev = &pdev->dev;
3683dc87a98dSRobin Murphy 	u32 cells;
36842985b521SLorenzo Pieralisi 	int ret = -EINVAL;
3685dc87a98dSRobin Murphy 
3686dc87a98dSRobin Murphy 	if (of_property_read_u32(dev->of_node, "#iommu-cells", &cells))
3687dc87a98dSRobin Murphy 		dev_err(dev, "missing #iommu-cells property\n");
3688dc87a98dSRobin Murphy 	else if (cells != 1)
3689dc87a98dSRobin Murphy 		dev_err(dev, "invalid #iommu-cells value (%d)\n", cells);
3690dc87a98dSRobin Murphy 	else
36912985b521SLorenzo Pieralisi 		ret = 0;
36922985b521SLorenzo Pieralisi 
36932985b521SLorenzo Pieralisi 	parse_driver_options(smmu);
36942985b521SLorenzo Pieralisi 
36952985b521SLorenzo Pieralisi 	if (of_dma_is_coherent(dev->of_node))
36962985b521SLorenzo Pieralisi 		smmu->features |= ARM_SMMU_FEAT_COHERENCY;
36972985b521SLorenzo Pieralisi 
36982985b521SLorenzo Pieralisi 	return ret;
36992985b521SLorenzo Pieralisi }
37002985b521SLorenzo Pieralisi 
3701e5b829deSLinu Cherian static unsigned long arm_smmu_resource_size(struct arm_smmu_device *smmu)
3702e5b829deSLinu Cherian {
3703e5b829deSLinu Cherian 	if (smmu->options & ARM_SMMU_OPT_PAGE0_REGS_ONLY)
3704e5b829deSLinu Cherian 		return SZ_64K;
3705e5b829deSLinu Cherian 	else
3706e5b829deSLinu Cherian 		return SZ_128K;
3707e5b829deSLinu Cherian }
3708e5b829deSLinu Cherian 
3709ab246774SWill Deacon static int arm_smmu_set_bus_ops(struct iommu_ops *ops)
3710ab246774SWill Deacon {
3711ab246774SWill Deacon 	int err;
3712ab246774SWill Deacon 
3713ab246774SWill Deacon #ifdef CONFIG_PCI
3714ab246774SWill Deacon 	if (pci_bus_type.iommu_ops != ops) {
3715ab246774SWill Deacon 		err = bus_set_iommu(&pci_bus_type, ops);
3716ab246774SWill Deacon 		if (err)
3717ab246774SWill Deacon 			return err;
3718ab246774SWill Deacon 	}
3719ab246774SWill Deacon #endif
3720ab246774SWill Deacon #ifdef CONFIG_ARM_AMBA
3721ab246774SWill Deacon 	if (amba_bustype.iommu_ops != ops) {
3722ab246774SWill Deacon 		err = bus_set_iommu(&amba_bustype, ops);
3723ab246774SWill Deacon 		if (err)
3724ab246774SWill Deacon 			goto err_reset_pci_ops;
3725ab246774SWill Deacon 	}
3726ab246774SWill Deacon #endif
3727ab246774SWill Deacon 	if (platform_bus_type.iommu_ops != ops) {
3728ab246774SWill Deacon 		err = bus_set_iommu(&platform_bus_type, ops);
3729ab246774SWill Deacon 		if (err)
3730ab246774SWill Deacon 			goto err_reset_amba_ops;
3731ab246774SWill Deacon 	}
3732ab246774SWill Deacon 
3733ab246774SWill Deacon 	return 0;
3734ab246774SWill Deacon 
3735ab246774SWill Deacon err_reset_amba_ops:
3736ab246774SWill Deacon #ifdef CONFIG_ARM_AMBA
3737ab246774SWill Deacon 	bus_set_iommu(&amba_bustype, NULL);
3738ab246774SWill Deacon #endif
3739ab246774SWill Deacon err_reset_pci_ops: __maybe_unused;
3740ab246774SWill Deacon #ifdef CONFIG_PCI
3741ab246774SWill Deacon 	bus_set_iommu(&pci_bus_type, NULL);
3742ab246774SWill Deacon #endif
3743ab246774SWill Deacon 	return err;
3744ab246774SWill Deacon }
3745ab246774SWill Deacon 
374652f3fab0SJean-Philippe Brucker static void __iomem *arm_smmu_ioremap(struct device *dev, resource_size_t start,
374752f3fab0SJean-Philippe Brucker 				      resource_size_t size)
374852f3fab0SJean-Philippe Brucker {
3749932bc8c7SZhen Lei 	struct resource res = DEFINE_RES_MEM(start, size);
375052f3fab0SJean-Philippe Brucker 
375152f3fab0SJean-Philippe Brucker 	return devm_ioremap_resource(dev, &res);
375252f3fab0SJean-Philippe Brucker }
375352f3fab0SJean-Philippe Brucker 
37542985b521SLorenzo Pieralisi static int arm_smmu_device_probe(struct platform_device *pdev)
37552985b521SLorenzo Pieralisi {
37562985b521SLorenzo Pieralisi 	int irq, ret;
37572985b521SLorenzo Pieralisi 	struct resource *res;
37589648cbc9SJoerg Roedel 	resource_size_t ioaddr;
37592985b521SLorenzo Pieralisi 	struct arm_smmu_device *smmu;
37602985b521SLorenzo Pieralisi 	struct device *dev = &pdev->dev;
37612985b521SLorenzo Pieralisi 	bool bypass;
376248ec83bcSWill Deacon 
376348ec83bcSWill Deacon 	smmu = devm_kzalloc(dev, sizeof(*smmu), GFP_KERNEL);
376448ec83bcSWill Deacon 	if (!smmu) {
376548ec83bcSWill Deacon 		dev_err(dev, "failed to allocate arm_smmu_device\n");
376648ec83bcSWill Deacon 		return -ENOMEM;
376748ec83bcSWill Deacon 	}
376848ec83bcSWill Deacon 	smmu->dev = dev;
376948ec83bcSWill Deacon 
3770e5b829deSLinu Cherian 	if (dev->of_node) {
3771e5b829deSLinu Cherian 		ret = arm_smmu_device_dt_probe(pdev, smmu);
3772e5b829deSLinu Cherian 	} else {
3773e5b829deSLinu Cherian 		ret = arm_smmu_device_acpi_probe(pdev, smmu);
3774e5b829deSLinu Cherian 		if (ret == -ENODEV)
3775e5b829deSLinu Cherian 			return ret;
3776e5b829deSLinu Cherian 	}
3777e5b829deSLinu Cherian 
3778e5b829deSLinu Cherian 	/* Set bypass mode according to firmware probing result */
3779e5b829deSLinu Cherian 	bypass = !!ret;
3780e5b829deSLinu Cherian 
378148ec83bcSWill Deacon 	/* Base address */
378248ec83bcSWill Deacon 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
3783322a9bbbSMasahiro Yamada 	if (resource_size(res) < arm_smmu_resource_size(smmu)) {
378448ec83bcSWill Deacon 		dev_err(dev, "MMIO region too small (%pr)\n", res);
378548ec83bcSWill Deacon 		return -EINVAL;
378648ec83bcSWill Deacon 	}
37879648cbc9SJoerg Roedel 	ioaddr = res->start;
378848ec83bcSWill Deacon 
378952f3fab0SJean-Philippe Brucker 	/*
379052f3fab0SJean-Philippe Brucker 	 * Don't map the IMPLEMENTATION DEFINED regions, since they may contain
379152f3fab0SJean-Philippe Brucker 	 * the PMCG registers which are reserved by the PMU driver.
379252f3fab0SJean-Philippe Brucker 	 */
379352f3fab0SJean-Philippe Brucker 	smmu->base = arm_smmu_ioremap(dev, ioaddr, ARM_SMMU_REG_SZ);
379448ec83bcSWill Deacon 	if (IS_ERR(smmu->base))
379548ec83bcSWill Deacon 		return PTR_ERR(smmu->base);
379648ec83bcSWill Deacon 
379752f3fab0SJean-Philippe Brucker 	if (arm_smmu_resource_size(smmu) > SZ_64K) {
379852f3fab0SJean-Philippe Brucker 		smmu->page1 = arm_smmu_ioremap(dev, ioaddr + SZ_64K,
379952f3fab0SJean-Philippe Brucker 					       ARM_SMMU_REG_SZ);
380052f3fab0SJean-Philippe Brucker 		if (IS_ERR(smmu->page1))
380152f3fab0SJean-Philippe Brucker 			return PTR_ERR(smmu->page1);
380252f3fab0SJean-Philippe Brucker 	} else {
380352f3fab0SJean-Philippe Brucker 		smmu->page1 = smmu->base;
380452f3fab0SJean-Philippe Brucker 	}
380552f3fab0SJean-Philippe Brucker 
380648ec83bcSWill Deacon 	/* Interrupt lines */
3807f935448aSGeetha Sowjanya 
3808f7aff1a9SJean-Philippe Brucker 	irq = platform_get_irq_byname_optional(pdev, "combined");
3809f935448aSGeetha Sowjanya 	if (irq > 0)
3810f935448aSGeetha Sowjanya 		smmu->combined_irq = irq;
3811f935448aSGeetha Sowjanya 	else {
3812f7aff1a9SJean-Philippe Brucker 		irq = platform_get_irq_byname_optional(pdev, "eventq");
381348ec83bcSWill Deacon 		if (irq > 0)
381448ec83bcSWill Deacon 			smmu->evtq.q.irq = irq;
381548ec83bcSWill Deacon 
3816f7aff1a9SJean-Philippe Brucker 		irq = platform_get_irq_byname_optional(pdev, "priq");
381748ec83bcSWill Deacon 		if (irq > 0)
381848ec83bcSWill Deacon 			smmu->priq.q.irq = irq;
381948ec83bcSWill Deacon 
3820f7aff1a9SJean-Philippe Brucker 		irq = platform_get_irq_byname_optional(pdev, "gerror");
382148ec83bcSWill Deacon 		if (irq > 0)
382248ec83bcSWill Deacon 			smmu->gerr_irq = irq;
3823f935448aSGeetha Sowjanya 	}
382448ec83bcSWill Deacon 	/* Probe the h/w */
38252985b521SLorenzo Pieralisi 	ret = arm_smmu_device_hw_probe(smmu);
382648ec83bcSWill Deacon 	if (ret)
382748ec83bcSWill Deacon 		return ret;
382848ec83bcSWill Deacon 
382948ec83bcSWill Deacon 	/* Initialise in-memory data structures */
383048ec83bcSWill Deacon 	ret = arm_smmu_init_structures(smmu);
383148ec83bcSWill Deacon 	if (ret)
383248ec83bcSWill Deacon 		return ret;
383348ec83bcSWill Deacon 
3834166bdbd2SMarc Zyngier 	/* Record our private device structure */
3835166bdbd2SMarc Zyngier 	platform_set_drvdata(pdev, smmu);
3836166bdbd2SMarc Zyngier 
383748ec83bcSWill Deacon 	/* Reset the device */
38388f785154SRobin Murphy 	ret = arm_smmu_device_reset(smmu, bypass);
38398f785154SRobin Murphy 	if (ret)
38408f785154SRobin Murphy 		return ret;
38418f785154SRobin Murphy 
38428f785154SRobin Murphy 	/* And we're up. Go go go! */
38439648cbc9SJoerg Roedel 	ret = iommu_device_sysfs_add(&smmu->iommu, dev, NULL,
38449648cbc9SJoerg Roedel 				     "smmu3.%pa", &ioaddr);
38459648cbc9SJoerg Roedel 	if (ret)
38469648cbc9SJoerg Roedel 		return ret;
38479648cbc9SJoerg Roedel 
38482d471b20SRobin Murphy 	ret = iommu_device_register(&smmu->iommu, &arm_smmu_ops, dev);
38495c2d0218SArvind Yadav 	if (ret) {
38505c2d0218SArvind Yadav 		dev_err(dev, "Failed to register iommu\n");
38515c2d0218SArvind Yadav 		return ret;
38525c2d0218SArvind Yadav 	}
3853778de074SLorenzo Pieralisi 
3854ab246774SWill Deacon 	return arm_smmu_set_bus_ops(&arm_smmu_ops);
3855ec615f43SRobin Murphy }
385648ec83bcSWill Deacon 
38576e8fa740SWill Deacon static int arm_smmu_device_remove(struct platform_device *pdev)
385848ec83bcSWill Deacon {
3859941a802dSWill Deacon 	struct arm_smmu_device *smmu = platform_get_drvdata(pdev);
386048ec83bcSWill Deacon 
3861ab246774SWill Deacon 	arm_smmu_set_bus_ops(NULL);
3862ab246774SWill Deacon 	iommu_device_unregister(&smmu->iommu);
3863ab246774SWill Deacon 	iommu_device_sysfs_remove(&smmu->iommu);
386448ec83bcSWill Deacon 	arm_smmu_device_disable(smmu);
3865395ad89dSJean-Philippe Brucker 	iopf_queue_free(smmu->evtq.iopf);
38666e8fa740SWill Deacon 
386748ec83bcSWill Deacon 	return 0;
386848ec83bcSWill Deacon }
386948ec83bcSWill Deacon 
387048ec83bcSWill Deacon static void arm_smmu_device_shutdown(struct platform_device *pdev)
387148ec83bcSWill Deacon {
38726e8fa740SWill Deacon 	arm_smmu_device_remove(pdev);
38737aa8619aSNate Watterson }
38747aa8619aSNate Watterson 
3875ebdd13c9SArvind Yadav static const struct of_device_id arm_smmu_of_match[] = {
387648ec83bcSWill Deacon 	{ .compatible = "arm,smmu-v3", },
387748ec83bcSWill Deacon 	{ },
387848ec83bcSWill Deacon };
38796e8fa740SWill Deacon MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
388048ec83bcSWill Deacon 
388132784a95SJean-Philippe Brucker static void arm_smmu_driver_unregister(struct platform_driver *drv)
388232784a95SJean-Philippe Brucker {
388332784a95SJean-Philippe Brucker 	arm_smmu_sva_notifier_synchronize();
388432784a95SJean-Philippe Brucker 	platform_driver_unregister(drv);
388532784a95SJean-Philippe Brucker }
388632784a95SJean-Philippe Brucker 
388748ec83bcSWill Deacon static struct platform_driver arm_smmu_driver = {
388848ec83bcSWill Deacon 	.driver	= {
388948ec83bcSWill Deacon 		.name			= "arm-smmu-v3",
38908efda06fSMasahiro Yamada 		.of_match_table		= arm_smmu_of_match,
3891c07b6426SPaul Gortmaker 		.suppress_bind_attrs	= true,
389248ec83bcSWill Deacon 	},
38932985b521SLorenzo Pieralisi 	.probe	= arm_smmu_device_probe,
38946e8fa740SWill Deacon 	.remove	= arm_smmu_device_remove,
38957aa8619aSNate Watterson 	.shutdown = arm_smmu_device_shutdown,
389648ec83bcSWill Deacon };
389732784a95SJean-Philippe Brucker module_driver(arm_smmu_driver, platform_driver_register,
389832784a95SJean-Philippe Brucker 	      arm_smmu_driver_unregister);
38996e8fa740SWill Deacon 
39006e8fa740SWill Deacon MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
39011ea27ee2SWill Deacon MODULE_AUTHOR("Will Deacon <will@kernel.org>");
3902d3daf666SArd Biesheuvel MODULE_ALIAS("platform:arm-smmu-v3");
39036e8fa740SWill Deacon MODULE_LICENSE("GPL v2");
3904