Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Documentation/devicetree/bindings/iommu/apple,sart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
1 change: 1 addition & 0 deletions Documentation/devicetree/bindings/nvme/apple,nvme-ans.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ allOf:
not:
contains:
enum:
- apple,t6050-nvme-ans2
- apple,t8132-nvme-ans2
- apple,t8140-nvme-ans2
then:
Expand Down
24 changes: 23 additions & 1 deletion drivers/nvme/host/apple.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ struct apple_nvme_hw {
bool needs_ioq_registers;
/* T8132 needs a PMGR reset when starting a stopped coprocessor. */
bool cold_reset;
/* The ANS is never reset through PMGR here, so no reset is named. */
bool reset_optional;
u32 max_queue_depth;
unsigned long quirks;
};
Expand Down Expand Up @@ -2407,7 +2409,9 @@ static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
goto out_detach_genpd;
}

anv->reset = devm_reset_control_array_get_exclusive(anv->dev);
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)) {
ret = dev_err_probe(dev, PTR_ERR(anv->reset),
"Failed to get reset control");
Expand Down Expand Up @@ -2776,8 +2780,26 @@ 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. */
.quirks = NVME_QUIRK_NO_APST | NVME_QUIRK_BROKEN_FUA,
};

static const struct of_device_id apple_nvme_of_match[] = {
{ .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 },
Expand Down
38 changes: 32 additions & 6 deletions drivers/soc/apple/sart.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/atomic.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/limits.h>
Expand Down Expand Up @@ -54,22 +55,29 @@
/* 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);
void (*set_entry)(struct apple_sart *sart, int index, u8 flags,
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;
Expand Down Expand Up @@ -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;
Expand All @@ -190,15 +198,28 @@ 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));
}

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,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
Loading