Skip to content

Commit 04d8ecf

Browse files
asdfugilsvenpeter42
authored andcommitted
nvme: apple: Add Apple A11 support
Add support for ANS2 NVMe on Apple A11 SoC. This version of ANS2 is less quirky than the one in M1, and does not have NVMMU or Linear SQ. However, it still requires a non-standard 128-byte SQE. Acked-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Nick Chan <towinchenmi@gmail.com> Reviewed-by: Sven Peter <sven@kernel.org> Link: https://lore.kernel.org/r/20250826-t8015-nvme-v5-2-caee6ab00144@gmail.com Signed-off-by: Sven Peter <sven@kernel.org>
1 parent 1dd8daf commit 04d8ecf

File tree

1 file changed

+137
-60
lines changed

1 file changed

+137
-60
lines changed

drivers/nvme/host/apple.c

Lines changed: 137 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#include "nvme.h"
3636

3737
#define APPLE_ANS_BOOT_TIMEOUT USEC_PER_SEC
38-
#define APPLE_ANS_MAX_QUEUE_DEPTH 64
3938

4039
#define APPLE_ANS_COPROC_CPU_CONTROL 0x44
4140
#define APPLE_ANS_COPROC_CPU_CONTROL_RUN BIT(4)
@@ -75,6 +74,8 @@
7574
#define APPLE_NVME_AQ_DEPTH 2
7675
#define APPLE_NVME_AQ_MQ_TAG_DEPTH (APPLE_NVME_AQ_DEPTH - 1)
7776

77+
#define APPLE_NVME_IOSQES 7
78+
7879
/*
7980
* These can be higher, but we need to ensure that any command doesn't
8081
* require an sg allocation that needs more than a page of data.
@@ -142,6 +143,7 @@ struct apple_nvme_queue {
142143
u32 __iomem *sq_db;
143144
u32 __iomem *cq_db;
144145

146+
u16 sq_tail;
145147
u16 cq_head;
146148
u8 cq_phase;
147149

@@ -166,11 +168,17 @@ struct apple_nvme_iod {
166168
struct scatterlist *sg;
167169
};
168170

171+
struct apple_nvme_hw {
172+
bool has_lsq_nvmmu;
173+
u32 max_queue_depth;
174+
};
175+
169176
struct apple_nvme {
170177
struct device *dev;
171178

172179
void __iomem *mmio_coproc;
173180
void __iomem *mmio_nvme;
181+
const struct apple_nvme_hw *hw;
174182

175183
struct device **pd_dev;
176184
struct device_link **pd_link;
@@ -215,10 +223,12 @@ static inline struct apple_nvme *queue_to_apple_nvme(struct apple_nvme_queue *q)
215223

216224
static unsigned int apple_nvme_queue_depth(struct apple_nvme_queue *q)
217225
{
218-
if (q->is_adminq)
226+
struct apple_nvme *anv = queue_to_apple_nvme(q);
227+
228+
if (q->is_adminq && anv->hw->has_lsq_nvmmu)
219229
return APPLE_NVME_AQ_DEPTH;
220230

221-
return APPLE_ANS_MAX_QUEUE_DEPTH;
231+
return anv->hw->max_queue_depth;
222232
}
223233

224234
static void apple_nvme_rtkit_crashed(void *cookie, const void *crashlog, size_t crashlog_size)
@@ -280,7 +290,28 @@ static void apple_nvmmu_inval(struct apple_nvme_queue *q, unsigned int tag)
280290
"NVMMU TCB invalidation failed\n");
281291
}
282292

283-
static void apple_nvme_submit_cmd(struct apple_nvme_queue *q,
293+
static void apple_nvme_submit_cmd_t8015(struct apple_nvme_queue *q,
294+
struct nvme_command *cmd)
295+
{
296+
struct apple_nvme *anv = queue_to_apple_nvme(q);
297+
298+
spin_lock_irq(&anv->lock);
299+
300+
if (q->is_adminq)
301+
memcpy(&q->sqes[q->sq_tail], cmd, sizeof(*cmd));
302+
else
303+
memcpy((void *)q->sqes + (q->sq_tail << APPLE_NVME_IOSQES),
304+
cmd, sizeof(*cmd));
305+
306+
if (++q->sq_tail == anv->hw->max_queue_depth)
307+
q->sq_tail = 0;
308+
309+
writel(q->sq_tail, q->sq_db);
310+
spin_unlock_irq(&anv->lock);
311+
}
312+
313+
314+
static void apple_nvme_submit_cmd_t8103(struct apple_nvme_queue *q,
284315
struct nvme_command *cmd)
285316
{
286317
struct apple_nvme *anv = queue_to_apple_nvme(q);
@@ -590,7 +621,8 @@ static inline void apple_nvme_handle_cqe(struct apple_nvme_queue *q,
590621
__u16 command_id = READ_ONCE(cqe->command_id);
591622
struct request *req;
592623

593-
apple_nvmmu_inval(q, command_id);
624+
if (anv->hw->has_lsq_nvmmu)
625+
apple_nvmmu_inval(q, command_id);
594626

595627
req = nvme_find_rq(apple_nvme_queue_tagset(anv, q), command_id);
596628
if (unlikely(!req)) {
@@ -685,7 +717,7 @@ static int apple_nvme_create_cq(struct apple_nvme *anv)
685717
c.create_cq.opcode = nvme_admin_create_cq;
686718
c.create_cq.prp1 = cpu_to_le64(anv->ioq.cq_dma_addr);
687719
c.create_cq.cqid = cpu_to_le16(1);
688-
c.create_cq.qsize = cpu_to_le16(APPLE_ANS_MAX_QUEUE_DEPTH - 1);
720+
c.create_cq.qsize = cpu_to_le16(anv->hw->max_queue_depth - 1);
689721
c.create_cq.cq_flags = cpu_to_le16(NVME_QUEUE_PHYS_CONTIG | NVME_CQ_IRQ_ENABLED);
690722
c.create_cq.irq_vector = cpu_to_le16(0);
691723

@@ -713,7 +745,7 @@ static int apple_nvme_create_sq(struct apple_nvme *anv)
713745
c.create_sq.opcode = nvme_admin_create_sq;
714746
c.create_sq.prp1 = cpu_to_le64(anv->ioq.sq_dma_addr);
715747
c.create_sq.sqid = cpu_to_le16(1);
716-
c.create_sq.qsize = cpu_to_le16(APPLE_ANS_MAX_QUEUE_DEPTH - 1);
748+
c.create_sq.qsize = cpu_to_le16(anv->hw->max_queue_depth - 1);
717749
c.create_sq.sq_flags = cpu_to_le16(NVME_QUEUE_PHYS_CONTIG);
718750
c.create_sq.cqid = cpu_to_le16(1);
719751

@@ -765,7 +797,12 @@ static blk_status_t apple_nvme_queue_rq(struct blk_mq_hw_ctx *hctx,
765797
}
766798

767799
nvme_start_request(req);
768-
apple_nvme_submit_cmd(q, cmnd);
800+
801+
if (anv->hw->has_lsq_nvmmu)
802+
apple_nvme_submit_cmd_t8103(q, cmnd);
803+
else
804+
apple_nvme_submit_cmd_t8015(q, cmnd);
805+
769806
return BLK_STS_OK;
770807

771808
out_free_cmd:
@@ -970,11 +1007,13 @@ static const struct blk_mq_ops apple_nvme_mq_ops = {
9701007
static void apple_nvme_init_queue(struct apple_nvme_queue *q)
9711008
{
9721009
unsigned int depth = apple_nvme_queue_depth(q);
1010+
struct apple_nvme *anv = queue_to_apple_nvme(q);
9731011

9741012
q->cq_head = 0;
9751013
q->cq_phase = 1;
976-
memset(q->tcbs, 0,
977-
APPLE_ANS_MAX_QUEUE_DEPTH * sizeof(struct apple_nvmmu_tcb));
1014+
if (anv->hw->has_lsq_nvmmu)
1015+
memset(q->tcbs, 0, anv->hw->max_queue_depth
1016+
* sizeof(struct apple_nvmmu_tcb));
9781017
memset(q->cqes, 0, depth * sizeof(struct nvme_completion));
9791018
WRITE_ONCE(q->enabled, true);
9801019
wmb(); /* ensure the first interrupt sees the initialization */
@@ -1069,49 +1108,55 @@ static void apple_nvme_reset_work(struct work_struct *work)
10691108

10701109
dma_set_max_seg_size(anv->dev, 0xffffffff);
10711110

1072-
/*
1073-
* Enable NVMMU and linear submission queues.
1074-
* While we could keep those disabled and pretend this is slightly
1075-
* more common NVMe controller we'd still need some quirks (e.g.
1076-
* sq entries will be 128 bytes) and Apple might drop support for
1077-
* that mode in the future.
1078-
*/
1079-
writel(APPLE_ANS_LINEAR_SQ_EN,
1080-
anv->mmio_nvme + APPLE_ANS_LINEAR_SQ_CTRL);
1111+
if (anv->hw->has_lsq_nvmmu) {
1112+
/*
1113+
* Enable NVMMU and linear submission queues which is required
1114+
* since T6000.
1115+
*/
1116+
writel(APPLE_ANS_LINEAR_SQ_EN,
1117+
anv->mmio_nvme + APPLE_ANS_LINEAR_SQ_CTRL);
10811118

1082-
/* Allow as many pending command as possible for both queues */
1083-
writel(APPLE_ANS_MAX_QUEUE_DEPTH | (APPLE_ANS_MAX_QUEUE_DEPTH << 16),
1084-
anv->mmio_nvme + APPLE_ANS_MAX_PEND_CMDS_CTRL);
1119+
/* Allow as many pending command as possible for both queues */
1120+
writel(anv->hw->max_queue_depth
1121+
| (anv->hw->max_queue_depth << 16), anv->mmio_nvme
1122+
+ APPLE_ANS_MAX_PEND_CMDS_CTRL);
10851123

1086-
/* Setup the NVMMU for the maximum admin and IO queue depth */
1087-
writel(APPLE_ANS_MAX_QUEUE_DEPTH - 1,
1088-
anv->mmio_nvme + APPLE_NVMMU_NUM_TCBS);
1124+
/* Setup the NVMMU for the maximum admin and IO queue depth */
1125+
writel(anv->hw->max_queue_depth - 1,
1126+
anv->mmio_nvme + APPLE_NVMMU_NUM_TCBS);
10891127

1090-
/*
1091-
* This is probably a chicken bit: without it all commands where any PRP
1092-
* is set to zero (including those that don't use that field) fail and
1093-
* the co-processor complains about "completed with err BAD_CMD-" or
1094-
* a "NULL_PRP_PTR_ERR" in the syslog
1095-
*/
1096-
writel(readl(anv->mmio_nvme + APPLE_ANS_UNKNOWN_CTRL) &
1097-
~APPLE_ANS_PRP_NULL_CHECK,
1098-
anv->mmio_nvme + APPLE_ANS_UNKNOWN_CTRL);
1128+
/*
1129+
* This is probably a chicken bit: without it all commands
1130+
* where any PRP is set to zero (including those that don't use
1131+
* that field) fail and the co-processor complains about
1132+
* "completed with err BAD_CMD-" or a "NULL_PRP_PTR_ERR" in the
1133+
* syslog
1134+
*/
1135+
writel(readl(anv->mmio_nvme + APPLE_ANS_UNKNOWN_CTRL) &
1136+
~APPLE_ANS_PRP_NULL_CHECK,
1137+
anv->mmio_nvme + APPLE_ANS_UNKNOWN_CTRL);
1138+
}
10991139

11001140
/* Setup the admin queue */
1101-
aqa = APPLE_NVME_AQ_DEPTH - 1;
1141+
if (anv->hw->has_lsq_nvmmu)
1142+
aqa = APPLE_NVME_AQ_DEPTH - 1;
1143+
else
1144+
aqa = anv->hw->max_queue_depth - 1;
11021145
aqa |= aqa << 16;
11031146
writel(aqa, anv->mmio_nvme + NVME_REG_AQA);
11041147
writeq(anv->adminq.sq_dma_addr, anv->mmio_nvme + NVME_REG_ASQ);
11051148
writeq(anv->adminq.cq_dma_addr, anv->mmio_nvme + NVME_REG_ACQ);
11061149

1107-
/* Setup NVMMU for both queues */
1108-
writeq(anv->adminq.tcb_dma_addr,
1109-
anv->mmio_nvme + APPLE_NVMMU_ASQ_TCB_BASE);
1110-
writeq(anv->ioq.tcb_dma_addr,
1111-
anv->mmio_nvme + APPLE_NVMMU_IOSQ_TCB_BASE);
1150+
if (anv->hw->has_lsq_nvmmu) {
1151+
/* Setup NVMMU for both queues */
1152+
writeq(anv->adminq.tcb_dma_addr,
1153+
anv->mmio_nvme + APPLE_NVMMU_ASQ_TCB_BASE);
1154+
writeq(anv->ioq.tcb_dma_addr,
1155+
anv->mmio_nvme + APPLE_NVMMU_IOSQ_TCB_BASE);
1156+
}
11121157

11131158
anv->ctrl.sqsize =
1114-
APPLE_ANS_MAX_QUEUE_DEPTH - 1; /* 0's based queue depth */
1159+
anv->hw->max_queue_depth - 1; /* 0's based queue depth */
11151160
anv->ctrl.cap = readq(anv->mmio_nvme + NVME_REG_CAP);
11161161

11171162
dev_dbg(anv->dev, "Enabling controller now");
@@ -1282,8 +1327,9 @@ static int apple_nvme_alloc_tagsets(struct apple_nvme *anv)
12821327
* both queues. The admin queue gets the first APPLE_NVME_AQ_DEPTH which
12831328
* must be marked as reserved in the IO queue.
12841329
*/
1285-
anv->tagset.reserved_tags = APPLE_NVME_AQ_DEPTH;
1286-
anv->tagset.queue_depth = APPLE_ANS_MAX_QUEUE_DEPTH - 1;
1330+
if (anv->hw->has_lsq_nvmmu)
1331+
anv->tagset.reserved_tags = APPLE_NVME_AQ_DEPTH;
1332+
anv->tagset.queue_depth = anv->hw->max_queue_depth - 1;
12871333
anv->tagset.timeout = NVME_IO_TIMEOUT;
12881334
anv->tagset.numa_node = NUMA_NO_NODE;
12891335
anv->tagset.cmd_size = sizeof(struct apple_nvme_iod);
@@ -1307,29 +1353,36 @@ static int apple_nvme_queue_alloc(struct apple_nvme *anv,
13071353
struct apple_nvme_queue *q)
13081354
{
13091355
unsigned int depth = apple_nvme_queue_depth(q);
1356+
size_t iosq_size;
13101357

13111358
q->cqes = dmam_alloc_coherent(anv->dev,
13121359
depth * sizeof(struct nvme_completion),
13131360
&q->cq_dma_addr, GFP_KERNEL);
13141361
if (!q->cqes)
13151362
return -ENOMEM;
13161363

1317-
q->sqes = dmam_alloc_coherent(anv->dev,
1318-
depth * sizeof(struct nvme_command),
1364+
if (anv->hw->has_lsq_nvmmu)
1365+
iosq_size = depth * sizeof(struct nvme_command);
1366+
else
1367+
iosq_size = depth << APPLE_NVME_IOSQES;
1368+
1369+
q->sqes = dmam_alloc_coherent(anv->dev, iosq_size,
13191370
&q->sq_dma_addr, GFP_KERNEL);
13201371
if (!q->sqes)
13211372
return -ENOMEM;
13221373

1323-
/*
1324-
* We need the maximum queue depth here because the NVMMU only has a
1325-
* single depth configuration shared between both queues.
1326-
*/
1327-
q->tcbs = dmam_alloc_coherent(anv->dev,
1328-
APPLE_ANS_MAX_QUEUE_DEPTH *
1329-
sizeof(struct apple_nvmmu_tcb),
1330-
&q->tcb_dma_addr, GFP_KERNEL);
1331-
if (!q->tcbs)
1332-
return -ENOMEM;
1374+
if (anv->hw->has_lsq_nvmmu) {
1375+
/*
1376+
* We need the maximum queue depth here because the NVMMU only
1377+
* has a single depth configuration shared between both queues.
1378+
*/
1379+
q->tcbs = dmam_alloc_coherent(anv->dev,
1380+
anv->hw->max_queue_depth *
1381+
sizeof(struct apple_nvmmu_tcb),
1382+
&q->tcb_dma_addr, GFP_KERNEL);
1383+
if (!q->tcbs)
1384+
return -ENOMEM;
1385+
}
13331386

13341387
/*
13351388
* initialize phase to make sure the allocated and empty memory
@@ -1413,6 +1466,12 @@ static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
14131466
anv->adminq.is_adminq = true;
14141467
platform_set_drvdata(pdev, anv);
14151468

1469+
anv->hw = of_device_get_match_data(&pdev->dev);
1470+
if (!anv->hw) {
1471+
ret = -ENODEV;
1472+
goto put_dev;
1473+
}
1474+
14161475
ret = apple_nvme_attach_genpd(anv);
14171476
if (ret < 0) {
14181477
dev_err_probe(dev, ret, "Failed to attach power domains");
@@ -1444,10 +1503,17 @@ static struct apple_nvme *apple_nvme_alloc(struct platform_device *pdev)
14441503
goto put_dev;
14451504
}
14461505

1447-
anv->adminq.sq_db = anv->mmio_nvme + APPLE_ANS_LINEAR_ASQ_DB;
1448-
anv->adminq.cq_db = anv->mmio_nvme + APPLE_ANS_ACQ_DB;
1449-
anv->ioq.sq_db = anv->mmio_nvme + APPLE_ANS_LINEAR_IOSQ_DB;
1450-
anv->ioq.cq_db = anv->mmio_nvme + APPLE_ANS_IOCQ_DB;
1506+
if (anv->hw->has_lsq_nvmmu) {
1507+
anv->adminq.sq_db = anv->mmio_nvme + APPLE_ANS_LINEAR_ASQ_DB;
1508+
anv->adminq.cq_db = anv->mmio_nvme + APPLE_ANS_ACQ_DB;
1509+
anv->ioq.sq_db = anv->mmio_nvme + APPLE_ANS_LINEAR_IOSQ_DB;
1510+
anv->ioq.cq_db = anv->mmio_nvme + APPLE_ANS_IOCQ_DB;
1511+
} else {
1512+
anv->adminq.sq_db = anv->mmio_nvme + NVME_REG_DBS;
1513+
anv->adminq.cq_db = anv->mmio_nvme + APPLE_ANS_ACQ_DB;
1514+
anv->ioq.sq_db = anv->mmio_nvme + NVME_REG_DBS + 8;
1515+
anv->ioq.cq_db = anv->mmio_nvme + APPLE_ANS_IOCQ_DB;
1516+
}
14511517

14521518
anv->sart = devm_apple_sart_get(dev);
14531519
if (IS_ERR(anv->sart)) {
@@ -1625,8 +1691,19 @@ static int apple_nvme_suspend(struct device *dev)
16251691
static DEFINE_SIMPLE_DEV_PM_OPS(apple_nvme_pm_ops, apple_nvme_suspend,
16261692
apple_nvme_resume);
16271693

1694+
static const struct apple_nvme_hw apple_nvme_t8015_hw = {
1695+
.has_lsq_nvmmu = false,
1696+
.max_queue_depth = 16,
1697+
};
1698+
1699+
static const struct apple_nvme_hw apple_nvme_t8103_hw = {
1700+
.has_lsq_nvmmu = true,
1701+
.max_queue_depth = 64,
1702+
};
1703+
16281704
static const struct of_device_id apple_nvme_of_match[] = {
1629-
{ .compatible = "apple,nvme-ans2" },
1705+
{ .compatible = "apple,t8015-nvme-ans2", .data = &apple_nvme_t8015_hw },
1706+
{ .compatible = "apple,nvme-ans2", .data = &apple_nvme_t8103_hw },
16301707
{},
16311708
};
16321709
MODULE_DEVICE_TABLE(of, apple_nvme_of_match);

0 commit comments

Comments
 (0)