diff --git a/Documentation/devicetree/bindings/iommu/apple,sart.yaml b/Documentation/devicetree/bindings/iommu/apple,sart.yaml index a75b4c8f05d5b..b451662226545 100644 --- a/Documentation/devicetree/bindings/iommu/apple,sart.yaml +++ b/Documentation/devicetree/bindings/iommu/apple,sart.yaml @@ -26,6 +26,9 @@ description: SART3, first seen in M1 Pro/Max, extends both the address space and filter entry size to 42 bit. + SART4, seen on M5 Ultra (T6050), keeps SART3's entries but moves the + address and size arrays, so it has no SART3 fallback. + properties: compatible: oneOf: @@ -40,6 +43,7 @@ properties: - const: apple,t6000-sart - enum: - apple,t6000-sart + - apple,t6050-sart - apple,t8015-sart - apple,t8103-sart diff --git a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml index 85f0fd2b6fa1e..3e1dfc807b846 100644 --- a/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml +++ b/Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml @@ -14,6 +14,7 @@ properties: oneOf: - const: apple,t8015-nvme-ans2 - const: apple,t6041-nvme-ans2 + - const: apple,t6050-nvme-ans2 - items: - enum: - apple,t6020-nvme-ans2 @@ -145,6 +146,7 @@ allOf: contains: enum: - apple,t6041-nvme-ans2 + - apple,t6050-nvme-ans2 - apple,t8132-nvme-ans2 then: properties: @@ -159,13 +161,29 @@ allOf: reg-names: maxItems: 2 + - if: + properties: + compatible: + contains: + const: apple,t6050-nvme-ans2 + then: + description: + The T6050 ANS is adopted running, its power stays with the firmware + and it is never reset through PMGR, so it names no power domain and + no reset. + properties: + power-domains: false + power-domain-names: false + else: + required: + - resets + - power-domains + - power-domain-names + required: - compatible - reg - reg-names - - resets - - power-domains - - power-domain-names - mboxes - interrupts - apple,sart diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c index d9e30a7da30d6..0f898ba5203d3 100644 --- a/drivers/nvme/host/apple.c +++ b/drivers/nvme/host/apple.c @@ -212,6 +212,8 @@ struct apple_nvme_hw { /* T8132 needs a PMGR reset when starting a stopped coprocessor. */ bool cold_reset; bool apif; + /* The ANS is never reset through PMGR here, so no reset is named. */ + bool reset_optional; u32 max_queue_depth; unsigned long quirks; }; @@ -2405,7 +2407,7 @@ static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev) goto out_detach_genpd; } - anv->reset = anv->hw->apif ? + anv->reset = anv->hw->reset_optional ? devm_reset_control_array_get_optional_exclusive(anv->dev) : devm_reset_control_array_get_exclusive(anv->dev); if (IS_ERR(anv->reset)) { @@ -2760,10 +2762,28 @@ static const struct apple_nvme_hw apple_nvme_t6040_hw = { .quirks = NVME_QUIRK_NO_APST, }; +/* + * T6050 (M5 Ultra) ANS on bare metal: T6040's split layout (a 64 KiB "nvme" + * block, a separate NVMMU, linear submission queues), 64 queue entries. Like + * every post-M4 ANS without cold_reset it is never reset through PMGR, so no + * reset is named. + */ +static const struct apple_nvme_hw apple_nvme_t6050_hw = { + .has_lsq_nvmmu = true, + .has_separate_nvmmu = true, + .needs_ioq_registers = true, + .lsq_in_nvmmu = true, + .reset_optional = true, + .max_queue_depth = 64, + /* FUA is not shown durable on this ANS: flush instead, as the APIF profile does. */ + .quirks = NVME_QUIRK_NO_APST | NVME_QUIRK_BROKEN_FUA, +}; + static const struct apple_nvme_hw apple_nvme_apif_hw = { .has_lsq_nvmmu = true, .needs_ioq_registers = true, .apif = true, + .reset_optional = true, .max_queue_depth = 64, .quirks = NVME_QUIRK_BROKEN_FUA, }; @@ -2771,6 +2791,7 @@ static const struct apple_nvme_hw apple_nvme_apif_hw = { static const struct of_device_id apple_nvme_of_match[] = { { .compatible = "apple,nvme-apif", .data = &apple_nvme_apif_hw }, { .compatible = "apple,t6041-nvme-ans2", .data = &apple_nvme_t6040_hw }, + { .compatible = "apple,t6050-nvme-ans2", .data = &apple_nvme_t6050_hw }, { .compatible = "apple,t8015-nvme-ans2", .data = &apple_nvme_t8015_hw }, { .compatible = "apple,t8103-nvme-ans2", .data = &apple_nvme_t8103_hw }, { .compatible = "apple,t8132-nvme-ans2", .data = &apple_nvme_t8132_hw }, diff --git a/drivers/soc/apple/sart.c b/drivers/soc/apple/sart.c index 6cedcb867c61b..8270a5a731f2c 100644 --- a/drivers/soc/apple/sart.c +++ b/drivers/soc/apple/sart.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -54,15 +55,19 @@ /* SARTv3 registers */ #define APPLE_SART3_CONFIG(idx) (0x00 + 4 * (idx)) -#define APPLE_SART3_PADDR(idx) (0x40 + 4 * (idx)) +#define APPLE_SART3_PADDR 0x40 #define APPLE_SART3_PADDR_SHIFT 12 -#define APPLE_SART3_SIZE(idx) (0x80 + 4 * (idx)) +#define APPLE_SART3_SIZE 0x80 #define APPLE_SART3_SIZE_SHIFT 12 #define APPLE_SART3_SIZE_MAX GENMASK(29, 0) #define APPLE_SART3_FLAGS_ALLOW 0xff +/* SARTv4 (M5): SARTv3's entries, with the address and size arrays moved up */ +#define APPLE_SART4_PADDR 0x60 +#define APPLE_SART4_SIZE 0xc0 + struct apple_sart_ops { void (*get_entry)(struct apple_sart *sart, int index, u8 *flags, phys_addr_t *paddr, size_t *size); @@ -70,6 +75,9 @@ struct apple_sart_ops { phys_addr_t paddr_shifted, size_t size_shifted); /* This is probably a bitfield but the exact meaning of each bit is unknown. */ unsigned int flags_allow; + /* SARTv3/v4: where the address and size arrays start */ + unsigned int paddr_reg; + unsigned int size_reg; unsigned int size_shift; unsigned int paddr_shift; size_t size_max; @@ -179,8 +187,8 @@ static struct apple_sart_ops sart_ops_v2 = { static void sart3_get_entry(struct apple_sart *sart, int index, u8 *flags, phys_addr_t *paddr, size_t *size) { - phys_addr_t paddr_ = readl(sart->regs + APPLE_SART3_PADDR(index)); - size_t size_ = readl(sart->regs + APPLE_SART3_SIZE(index)); + phys_addr_t paddr_ = readl(sart->regs + sart->ops->paddr_reg + 4 * index); + size_t size_ = readl(sart->regs + sart->ops->size_reg + 4 * index); *flags = readl(sart->regs + APPLE_SART3_CONFIG(index)); *size = size_ << APPLE_SART3_SIZE_SHIFT; @@ -190,8 +198,8 @@ static void sart3_get_entry(struct apple_sart *sart, int index, u8 *flags, static void sart3_set_entry(struct apple_sart *sart, int index, u8 flags, phys_addr_t paddr_shifted, size_t size_shifted) { - writel(paddr_shifted, sart->regs + APPLE_SART3_PADDR(index)); - writel(size_shifted, sart->regs + APPLE_SART3_SIZE(index)); + writel(paddr_shifted, sart->regs + sart->ops->paddr_reg + 4 * index); + writel(size_shifted, sart->regs + sart->ops->size_reg + 4 * index); writel(flags, sart->regs + APPLE_SART3_CONFIG(index)); } @@ -199,6 +207,19 @@ static struct apple_sart_ops sart_ops_v3 = { .get_entry = sart3_get_entry, .set_entry = sart3_set_entry, .flags_allow = APPLE_SART3_FLAGS_ALLOW, + .paddr_reg = APPLE_SART3_PADDR, + .size_reg = APPLE_SART3_SIZE, + .size_shift = APPLE_SART3_SIZE_SHIFT, + .paddr_shift = APPLE_SART3_PADDR_SHIFT, + .size_max = APPLE_SART3_SIZE_MAX, +}; + +static struct apple_sart_ops sart_ops_v4 = { + .get_entry = sart3_get_entry, + .set_entry = sart3_set_entry, + .flags_allow = APPLE_SART3_FLAGS_ALLOW, + .paddr_reg = APPLE_SART4_PADDR, + .size_reg = APPLE_SART4_SIZE, .size_shift = APPLE_SART3_SIZE_SHIFT, .paddr_shift = APPLE_SART3_PADDR_SHIFT, .size_max = APPLE_SART3_SIZE_MAX, @@ -236,6 +257,7 @@ static int apple_sart_probe(struct platform_device *pdev) i, flags, &paddr, size); set_bit(i, &sart->protected_entries); } + dev_dbg(dev, "%lu bootloader entries protected\n", hweight_long(sart->protected_entries)); platform_set_drvdata(pdev, sart); return 0; @@ -409,6 +431,10 @@ static void apple_sart_shutdown(struct platform_device *pdev) } static const struct of_device_id apple_sart_of_match[] = { + { + .compatible = "apple,t6050-sart", + .data = &sart_ops_v4, + }, { .compatible = "apple,t6000-sart", .data = &sart_ops_v3,