From nobody Sat Feb 7 08:44:14 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 82DF5C54EBD for ; Fri, 13 Jan 2023 10:55:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241130AbjAMKzW (ORCPT ); Fri, 13 Jan 2023 05:55:22 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:49022 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241234AbjAMKxl (ORCPT ); Fri, 13 Jan 2023 05:53:41 -0500 Received: from mail.marcansoft.com (marcansoft.com [212.63.210.85]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7D07577D35; Fri, 13 Jan 2023 02:51:56 -0800 (PST) Received: from [127.0.0.1] (localhost [127.0.0.1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) (Authenticated sender: sendonly@marcansoft.com) by mail.marcansoft.com (Postfix) with ESMTPSA id A80FC41A42; Fri, 13 Jan 2023 10:51:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=marcan.st; s=default; t=1673607114; bh=Ju2C3rYuZeAAMQDrVFOEXIDcQ7uiTLJGKcK1Xq/Sfi4=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=Or2nRxF3+TX7nKOGGyIL4pQUoPAi5v/dGb9j1yvk5Ha5G0A7Jddz+5qB/Wp67kYbj TqLv74+57IEhw7nBdnS5fW109fISq0jJiTwqmIWoCsLlMt7iqAhhEn6MNRE/QOfzqH UbuG3XFeQFKrNgP4czvLBr83fTvRkWMLWHDPxIqaV1m5IoNiO5YKc44RKE/ofaL6yn sW5IoO43WY7qH1jqAVsARvQYRLW9mabfnNy7NzPMEddQqOsEQt8mtpB40U5+vmvTY8 zH+XxqmhTEhj8MF1le7C+GGeLkQ3zaMmG/85BARVTPzXc4hNqbtGcr0cDYtfK2g6UY 5R6b16Ei5vitw== From: Hector Martin To: Joerg Roedel , Will Deacon , Robin Murphy Cc: Sven Peter , Alyssa Rosenzweig , Janne Grunau , Rob Herring , Krzysztof Kozlowski , devicetree@vger.kernel.org, iommu@lists.linux.dev, asahi@lists.linux.dev, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, Hector Martin Subject: [PATCH 6/7] iommu: dart: Support different variants with different registers Date: Fri, 13 Jan 2023 19:50:29 +0900 Message-Id: <20230113105029.26654-7-marcan@marcan.st> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20230113105029.26654-1-marcan@marcan.st> References: <20230113105029.26654-1-marcan@marcan.st> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" T8110 has a new register layout. To accommodate this, first move all the register offsets to the hw structure, and rename all the existing registers to DART_T8020_*. Reviewed-by: Sven Peter Signed-off-by: Hector Martin --- drivers/iommu/apple-dart.c | 187 ++++++++++++++++++++++++------------- 1 file changed, 124 insertions(+), 63 deletions(-) diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c index 89be055a44be..75647433df9d 100644 --- a/drivers/iommu/apple-dart.c +++ b/drivers/iommu/apple-dart.c @@ -38,6 +38,7 @@ #define DART_MAX_TTBR 4 #define MAX_DARTS_PER_DEVICE 2 =20 +/* Common registers */ =20 #define DART_PARAMS1 0x00 #define DART_PARAMS1_PAGE_SHIFT GENMASK(27, 24) @@ -45,52 +46,78 @@ #define DART_PARAMS2 0x04 #define DART_PARAMS2_BYPASS_SUPPORT BIT(0) =20 -#define DART_STREAM_COMMAND 0x20 -#define DART_STREAM_COMMAND_BUSY BIT(2) -#define DART_STREAM_COMMAND_INVALIDATE BIT(20) +/* T8020/T6000 registers */ =20 -#define DART_STREAM_SELECT 0x34 +#define DART_T8020_STREAM_COMMAND 0x20 +#define DART_T8020_STREAM_COMMAND_BUSY BIT(2) +#define DART_T8020_STREAM_COMMAND_INVALIDATE BIT(20) =20 -#define DART_ERROR 0x40 -#define DART_ERROR_STREAM GENMASK(27, 24) -#define DART_ERROR_CODE GENMASK(11, 0) -#define DART_ERROR_FLAG BIT(31) +#define DART_T8020_STREAM_SELECT 0x34 =20 -#define DART_ERROR_READ_FAULT BIT(4) -#define DART_ERROR_WRITE_FAULT BIT(3) -#define DART_ERROR_NO_PTE BIT(2) -#define DART_ERROR_NO_PMD BIT(1) -#define DART_ERROR_NO_TTBR BIT(0) +#define DART_T8020_ERROR 0x40 +#define DART_T8020_ERROR_STREAM GENMASK(27, 24) +#define DART_T8020_ERROR_CODE GENMASK(11, 0) +#define DART_T8020_ERROR_FLAG BIT(31) =20 -#define DART_CONFIG 0x60 -#define DART_CONFIG_LOCK BIT(15) +#define DART_T8020_ERROR_READ_FAULT BIT(4) +#define DART_T8020_ERROR_WRITE_FAULT BIT(3) +#define DART_T8020_ERROR_NO_PTE BIT(2) +#define DART_T8020_ERROR_NO_PMD BIT(1) +#define DART_T8020_ERROR_NO_TTBR BIT(0) + +#define DART_T8020_CONFIG 0x60 +#define DART_T8020_CONFIG_LOCK BIT(15) =20 #define DART_STREAM_COMMAND_BUSY_TIMEOUT 100 =20 -#define DART_ERROR_ADDR_HI 0x54 -#define DART_ERROR_ADDR_LO 0x50 +#define DART_T8020_ERROR_ADDR_HI 0x54 +#define DART_T8020_ERROR_ADDR_LO 0x50 + +#define DART_T8020_STREAMS_ENABLE 0xfc =20 -#define DART_STREAMS_ENABLE 0xfc +#define DART_T8020_TCR 0x100 +#define DART_T8020_TCR_TRANSLATE_ENABLE BIT(7) +#define DART_T8020_TCR_BYPASS_DART BIT(8) +#define DART_T8020_TCR_BYPASS_DAPF BIT(12) =20 -#define DART_TCR(sid) (0x100 + 4 * (sid)) -#define DART_TCR_TRANSLATE_ENABLE BIT(7) -#define DART_TCR_BYPASS0_ENABLE BIT(8) -#define DART_TCR_BYPASS1_ENABLE BIT(12) +#define DART_T8020_TTBR 0x200 +#define DART_T8020_TTBR_VALID BIT(31) +#define DART_T8020_TTBR_ADDR_FIELD_SHIFT 0 +#define DART_T8020_TTBR_SHIFT 12 =20 -#define DART_TTBR_VALID BIT(31) -#define DART_TTBR_SHIFT 12 +#define DART_TCR(dart, sid) ((dart)->hw->tcr + ((sid) << 2)) =20 -#define DART_TTBR(dart, sid, idx) (0x200 + \ +#define DART_TTBR(dart, sid, idx) ((dart)->hw->ttbr + \ (((dart)->hw->ttbr_count * (sid)) << 2) + \ ((idx) << 2)) =20 +struct apple_dart_stream_map; =20 struct apple_dart_hw { + irqreturn_t (*irq_handler)(int irq, void *dev); + int (*invalidate_tlb)(struct apple_dart_stream_map *stream_map); + u32 oas; enum io_pgtable_fmt fmt; =20 int max_sid_count; =20 + u64 lock; + u64 lock_bit; + + u64 error; + + u64 enable_streams; + + u64 tcr; + u64 tcr_enabled; + u64 tcr_disabled; + u64 tcr_bypass; + + u64 ttbr; + u64 ttbr_valid; + u64 ttbr_addr_field_shift; + u64 ttbr_shift; int ttbr_count; }; =20 @@ -217,8 +244,7 @@ apple_dart_hw_enable_translation(struct apple_dart_stre= am_map *stream_map) int sid; =20 for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) - writel(DART_TCR_TRANSLATE_ENABLE, - dart->regs + DART_TCR(sid)); + writel(dart->hw->tcr_enabled, dart->regs + DART_TCR(dart, sid)); } =20 static void apple_dart_hw_disable_dma(struct apple_dart_stream_map *stream= _map) @@ -227,7 +253,7 @@ static void apple_dart_hw_disable_dma(struct apple_dart= _stream_map *stream_map) int sid; =20 for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) - writel(0, dart->regs + DART_TCR(sid)); + writel(dart->hw->tcr_disabled, dart->regs + DART_TCR(dart, sid)); } =20 static void @@ -238,8 +264,8 @@ apple_dart_hw_enable_bypass(struct apple_dart_stream_ma= p *stream_map) =20 WARN_ON(!stream_map->dart->supports_bypass); for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) - writel(DART_TCR_BYPASS0_ENABLE | DART_TCR_BYPASS1_ENABLE, - dart->regs + DART_TCR(sid)); + writel(dart->hw->tcr_bypass, + dart->regs + DART_TCR(dart, sid)); } =20 static void apple_dart_hw_set_ttbr(struct apple_dart_stream_map *stream_ma= p, @@ -248,9 +274,10 @@ static void apple_dart_hw_set_ttbr(struct apple_dart_s= tream_map *stream_map, struct apple_dart *dart =3D stream_map->dart; int sid; =20 - WARN_ON(paddr & ((1 << DART_TTBR_SHIFT) - 1)); + WARN_ON(paddr & ((1 << dart->hw->ttbr_shift) - 1)); for_each_set_bit(sid, stream_map->sidmap, dart->num_streams) - writel(DART_TTBR_VALID | (paddr >> DART_TTBR_SHIFT), + writel(dart->hw->ttbr_valid | + (paddr >> dart->hw->ttbr_shift) << dart->hw->ttbr_addr_field_shif= t, dart->regs + DART_TTBR(dart, sid, idx)); } =20 @@ -274,7 +301,7 @@ apple_dart_hw_clear_all_ttbrs(struct apple_dart_stream_= map *stream_map) } =20 static int -apple_dart_hw_stream_command(struct apple_dart_stream_map *stream_map, +apple_dart_t8020_hw_stream_command(struct apple_dart_stream_map *stream_ma= p, u32 command) { unsigned long flags; @@ -283,12 +310,12 @@ apple_dart_hw_stream_command(struct apple_dart_stream= _map *stream_map, =20 spin_lock_irqsave(&stream_map->dart->lock, flags); =20 - writel(stream_map->sidmap[0], stream_map->dart->regs + DART_STREAM_SELECT= ); - writel(command, stream_map->dart->regs + DART_STREAM_COMMAND); + writel(stream_map->sidmap[0], stream_map->dart->regs + DART_T8020_STREAM_= SELECT); + writel(command, stream_map->dart->regs + DART_T8020_STREAM_COMMAND); =20 ret =3D readl_poll_timeout_atomic( - stream_map->dart->regs + DART_STREAM_COMMAND, command_reg, - !(command_reg & DART_STREAM_COMMAND_BUSY), 1, + stream_map->dart->regs + DART_T8020_STREAM_COMMAND, command_reg, + !(command_reg & DART_T8020_STREAM_COMMAND_BUSY), 1, DART_STREAM_COMMAND_BUSY_TIMEOUT); =20 spin_unlock_irqrestore(&stream_map->dart->lock, flags); @@ -304,10 +331,10 @@ apple_dart_hw_stream_command(struct apple_dart_stream= _map *stream_map, } =20 static int -apple_dart_hw_invalidate_tlb(struct apple_dart_stream_map *stream_map) +apple_dart_t8020_hw_invalidate_tlb(struct apple_dart_stream_map *stream_ma= p) { - return apple_dart_hw_stream_command(stream_map, - DART_STREAM_COMMAND_INVALIDATE); + return apple_dart_t8020_hw_stream_command( + stream_map, DART_T8020_STREAM_COMMAND_INVALIDATE); } =20 static int apple_dart_hw_reset(struct apple_dart *dart) @@ -316,8 +343,8 @@ static int apple_dart_hw_reset(struct apple_dart *dart) struct apple_dart_stream_map stream_map; int i; =20 - config =3D readl(dart->regs + DART_CONFIG); - if (config & DART_CONFIG_LOCK) { + config =3D readl(dart->regs + dart->hw->lock); + if (config & dart->hw->lock_bit) { dev_err(dart->dev, "DART is locked down until reboot: %08x\n", config); return -EINVAL; @@ -331,12 +358,12 @@ static int apple_dart_hw_reset(struct apple_dart *dar= t) =20 /* enable all streams globally since TCR is used to control isolation */ for (i =3D 0; i < BITS_TO_U32(dart->num_streams); i++) - writel(U32_MAX, dart->regs + DART_STREAMS_ENABLE + 4 * i); + writel(U32_MAX, dart->regs + dart->hw->enable_streams + 4 * i); =20 /* clear any pending errors before the interrupt is unmasked */ - writel(readl(dart->regs + DART_ERROR), dart->regs + DART_ERROR); + writel(readl(dart->regs + dart->hw->error), dart->regs + dart->hw->error); =20 - return apple_dart_hw_invalidate_tlb(&stream_map); + return dart->hw->invalidate_tlb(&stream_map); } =20 static void apple_dart_domain_flush_tlb(struct apple_dart_domain *domain) @@ -351,7 +378,7 @@ static void apple_dart_domain_flush_tlb(struct apple_da= rt_domain *domain) for (j =3D 0; j < BITS_TO_LONGS(stream_map.dart->num_streams); j++) stream_map.sidmap[j] =3D atomic_long_read(&domain_stream_map->sidmap[j]= ); =20 - apple_dart_hw_invalidate_tlb(&stream_map); + stream_map.dart->hw->invalidate_tlb(&stream_map); } } =20 @@ -425,7 +452,7 @@ apple_dart_setup_translation(struct apple_dart_domain *= domain, apple_dart_hw_clear_ttbr(stream_map, i); =20 apple_dart_hw_enable_translation(stream_map); - apple_dart_hw_invalidate_tlb(stream_map); + stream_map->dart->hw->invalidate_tlb(stream_map); } =20 static int apple_dart_finalize_domain(struct iommu_domain *domain, @@ -816,30 +843,30 @@ static const struct iommu_ops apple_dart_iommu_ops = =3D { } }; =20 -static irqreturn_t apple_dart_irq(int irq, void *dev) +static irqreturn_t apple_dart_t8020_irq(int irq, void *dev) { struct apple_dart *dart =3D dev; const char *fault_name =3D NULL; - u32 error =3D readl(dart->regs + DART_ERROR); - u32 error_code =3D FIELD_GET(DART_ERROR_CODE, error); - u32 addr_lo =3D readl(dart->regs + DART_ERROR_ADDR_LO); - u32 addr_hi =3D readl(dart->regs + DART_ERROR_ADDR_HI); + u32 error =3D readl(dart->regs + DART_T8020_ERROR); + u32 error_code =3D FIELD_GET(DART_T8020_ERROR_CODE, error); + u32 addr_lo =3D readl(dart->regs + DART_T8020_ERROR_ADDR_LO); + u32 addr_hi =3D readl(dart->regs + DART_T8020_ERROR_ADDR_HI); u64 addr =3D addr_lo | (((u64)addr_hi) << 32); - u8 stream_idx =3D FIELD_GET(DART_ERROR_STREAM, error); + u8 stream_idx =3D FIELD_GET(DART_T8020_ERROR_STREAM, error); =20 - if (!(error & DART_ERROR_FLAG)) + if (!(error & DART_T8020_ERROR_FLAG)) return IRQ_NONE; =20 /* there should only be a single bit set but let's use =3D=3D to be sure = */ - if (error_code =3D=3D DART_ERROR_READ_FAULT) + if (error_code =3D=3D DART_T8020_ERROR_READ_FAULT) fault_name =3D "READ FAULT"; - else if (error_code =3D=3D DART_ERROR_WRITE_FAULT) + else if (error_code =3D=3D DART_T8020_ERROR_WRITE_FAULT) fault_name =3D "WRITE FAULT"; - else if (error_code =3D=3D DART_ERROR_NO_PTE) + else if (error_code =3D=3D DART_T8020_ERROR_NO_PTE) fault_name =3D "NO PTE FOR IOVA"; - else if (error_code =3D=3D DART_ERROR_NO_PMD) + else if (error_code =3D=3D DART_T8020_ERROR_NO_PMD) fault_name =3D "NO PMD FOR IOVA"; - else if (error_code =3D=3D DART_ERROR_NO_TTBR) + else if (error_code =3D=3D DART_T8020_ERROR_NO_TTBR) fault_name =3D "NO TTBR FOR IOVA"; else fault_name =3D "unknown"; @@ -849,7 +876,7 @@ static irqreturn_t apple_dart_irq(int irq, void *dev) "translation fault: status:0x%x stream:%d code:0x%x (%s) at 0x%llx", error, stream_idx, error_code, fault_name, addr); =20 - writel(error, dart->regs + DART_ERROR); + writel(error, dart->regs + DART_T8020_ERROR); return IRQ_HANDLED; } =20 @@ -911,7 +938,7 @@ static int apple_dart_probe(struct platform_device *pde= v) if (ret) goto err_clk_disable; =20 - ret =3D request_irq(dart->irq, apple_dart_irq, IRQF_SHARED, + ret =3D request_irq(dart->irq, dart->hw->irq_handler, IRQF_SHARED, "apple-dart fault handler", dart); if (ret) goto err_clk_disable; @@ -959,17 +986,51 @@ static int apple_dart_remove(struct platform_device *= pdev) } =20 static const struct apple_dart_hw apple_dart_hw_t8103 =3D { + .irq_handler =3D apple_dart_t8020_irq, + .invalidate_tlb =3D apple_dart_t8020_hw_invalidate_tlb, .oas =3D 36, .fmt =3D APPLE_DART, .max_sid_count =3D 16, =20 + .enable_streams =3D DART_T8020_STREAMS_ENABLE, + .lock =3D DART_T8020_CONFIG, + .lock_bit =3D DART_T8020_CONFIG_LOCK, + + .error =3D DART_T8020_ERROR, + + .tcr =3D DART_T8020_TCR, + .tcr_enabled =3D DART_T8020_TCR_TRANSLATE_ENABLE, + .tcr_disabled =3D 0, + .tcr_bypass =3D DART_T8020_TCR_BYPASS_DAPF | DART_T8020_TCR_BYPASS_DART, + + .ttbr =3D DART_T8020_TTBR, + .ttbr_valid =3D DART_T8020_TTBR_VALID, + .ttbr_addr_field_shift =3D DART_T8020_TTBR_ADDR_FIELD_SHIFT, + .ttbr_shift =3D DART_T8020_TTBR_SHIFT, .ttbr_count =3D 4, }; static const struct apple_dart_hw apple_dart_hw_t6000 =3D { + .irq_handler =3D apple_dart_t8020_irq, + .invalidate_tlb =3D apple_dart_t8020_hw_invalidate_tlb, .oas =3D 42, .fmt =3D APPLE_DART2, .max_sid_count =3D 16, =20 + .enable_streams =3D DART_T8020_STREAMS_ENABLE, + .lock =3D DART_T8020_CONFIG, + .lock_bit =3D DART_T8020_CONFIG_LOCK, + + .error =3D DART_T8020_ERROR, + + .tcr =3D DART_T8020_TCR, + .tcr_enabled =3D DART_T8020_TCR_TRANSLATE_ENABLE, + .tcr_disabled =3D 0, + .tcr_bypass =3D DART_T8020_TCR_BYPASS_DAPF | DART_T8020_TCR_BYPASS_DART, + + .ttbr =3D DART_T8020_TTBR, + .ttbr_valid =3D DART_T8020_TTBR_VALID, + .ttbr_addr_field_shift =3D DART_T8020_TTBR_ADDR_FIELD_SHIFT, + .ttbr_shift =3D DART_T8020_TTBR_SHIFT, .ttbr_count =3D 4, }; =20 @@ -979,7 +1040,7 @@ static __maybe_unused int apple_dart_suspend(struct de= vice *dev) unsigned int sid, idx; =20 for (sid =3D 0; sid < dart->num_streams; sid++) { - dart->save_tcr[sid] =3D readl_relaxed(dart->regs + DART_TCR(sid)); + dart->save_tcr[sid] =3D readl_relaxed(dart->regs + DART_TCR(dart, sid)); for (idx =3D 0; idx < dart->hw->ttbr_count; idx++) dart->save_ttbr[sid][idx] =3D readl(dart->regs + DART_TTBR(dart, sid, idx)); @@ -1004,7 +1065,7 @@ static __maybe_unused int apple_dart_resume(struct de= vice *dev) for (idx =3D 0; idx < dart->hw->ttbr_count; idx++) writel(dart->save_ttbr[sid][idx], dart->regs + DART_TTBR(dart, sid, idx)); - writel(dart->save_tcr[sid], dart->regs + DART_TCR(sid)); + writel(dart->save_tcr[sid], dart->regs + DART_TCR(dart, sid)); } =20 return 0; --=20 2.35.1