Skip to content

Commit a573366

Browse files
RajuRangojubroonie
authored andcommitted
spi: spi_amd: Add HIDDMA basic write support
SPI index mode has hardware limitation of transferring only 64 bytes per transaction due to fixed number of FIFO registers. This constraint leads to performance issues when reading/writing data to/from NAND/NOR flash devices, as the controller must issue multiple requests to read/write 64-byte chunks, even if the slave can transfer up to 2 or 4 KB in a single transaction. The AMD HID2 SPI controller supports DMA mode, allowing for reading/writing up to 4 KB of data in a single transaction. The existing spi_amd driver already supports HID2 DMA read operations. This patch introduces changes to implement HID2 DMA single mode basic write support for the HID2 SPI controller. Co-developed-by: Krishnamoorthi M <krishnamoorthi.m@amd.com> Signed-off-by: Krishnamoorthi M <krishnamoorthi.m@amd.com> Co-developed-by: Akshata MukundShetty <akshata.mukundshetty@amd.com> Signed-off-by: Akshata MukundShetty <akshata.mukundshetty@amd.com> Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com> Link: https://patch.msgid.link/20250516100658.585654-3-Raju.Rangoju@amd.com Signed-off-by: Mark Brown <broonie@kernel.org>
1 parent 8cd079e commit a573366

File tree

1 file changed

+112
-23
lines changed

1 file changed

+112
-23
lines changed

drivers/spi/spi-amd.c

Lines changed: 112 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,13 @@
5454
#define AMD_SPI_SPD7_MASK GENMASK(13, AMD_SPI_SPD7_SHIFT)
5555

5656
#define AMD_SPI_HID2_INPUT_RING_BUF0 0X100
57+
#define AMD_SPI_HID2_OUTPUT_BUF0 0x140
5758
#define AMD_SPI_HID2_CNTRL 0x150
5859
#define AMD_SPI_HID2_INT_STATUS 0x154
5960
#define AMD_SPI_HID2_CMD_START 0x156
6061
#define AMD_SPI_HID2_INT_MASK 0x158
62+
#define AMD_SPI_HID2_WRITE_CNTRL0 0x160
63+
#define AMD_SPI_HID2_WRITE_CNTRL1 0x164
6164
#define AMD_SPI_HID2_READ_CNTRL0 0x170
6265
#define AMD_SPI_HID2_READ_CNTRL1 0x174
6366
#define AMD_SPI_HID2_READ_CNTRL2 0x180
@@ -83,6 +86,10 @@
8386
#define AMD_SPI_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */
8487
#define AMD_SPI_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */
8588

89+
/* SPINAND write command opcodes */
90+
#define AMD_SPI_OP_PP 0x02 /* Page program */
91+
#define AMD_SPI_OP_PP_RANDOM 0x84 /* Page program */
92+
8693
enum amd_spi_speed {
8794
F_66_66MHz,
8895
F_33_33MHz,
@@ -419,6 +426,17 @@ static inline bool amd_is_spi_read_cmd(const u16 op)
419426
}
420427
}
421428

429+
static inline bool amd_is_spi_write_cmd(const u16 op)
430+
{
431+
switch (op) {
432+
case AMD_SPI_OP_PP:
433+
case AMD_SPI_OP_PP_RANDOM:
434+
return true;
435+
default:
436+
return false;
437+
}
438+
}
439+
422440
static bool amd_spi_supports_op(struct spi_mem *mem,
423441
const struct spi_mem_op *op)
424442
{
@@ -429,7 +447,7 @@ static bool amd_spi_supports_op(struct spi_mem *mem,
429447
return false;
430448

431449
/* AMD SPI controllers support quad mode only for read operations */
432-
if (amd_is_spi_read_cmd(op->cmd.opcode)) {
450+
if (amd_is_spi_read_cmd(op->cmd.opcode) || amd_is_spi_write_cmd(op->cmd.opcode)) {
433451
if (op->data.buswidth > 4)
434452
return false;
435453

@@ -438,7 +456,8 @@ static bool amd_spi_supports_op(struct spi_mem *mem,
438456
* doesn't support 4-byte address commands.
439457
*/
440458
if (amd_spi->version == AMD_HID2_SPI) {
441-
if (amd_is_spi_read_cmd_4b(op->cmd.opcode) ||
459+
if ((amd_is_spi_read_cmd_4b(op->cmd.opcode) ||
460+
amd_is_spi_write_cmd(op->cmd.opcode)) &&
442461
op->data.nbytes > AMD_SPI_HID2_DMA_SIZE)
443462
return false;
444463
} else if (op->data.nbytes > AMD_SPI_MAX_DATA) {
@@ -464,7 +483,8 @@ static int amd_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op)
464483
* controller index mode supports maximum of 64 bytes in a single
465484
* transaction.
466485
*/
467-
if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_read_cmd(op->cmd.opcode))
486+
if (amd_spi->version == AMD_HID2_SPI && (amd_is_spi_read_cmd(op->cmd.opcode) ||
487+
amd_is_spi_write_cmd(op->cmd.opcode)))
468488
op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_HID2_DMA_SIZE);
469489
else
470490
op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_MAX_DATA);
@@ -488,32 +508,96 @@ static void amd_spi_set_addr(struct amd_spi *amd_spi,
488508
}
489509
}
490510

511+
static void amd_spi_hiddma_write(struct amd_spi *amd_spi, const struct spi_mem_op *op)
512+
{
513+
u16 hid_cmd_start, val;
514+
u32 hid_regval;
515+
516+
/*
517+
* Program the HID2 output Buffer0. 4k aligned buf_memory_addr[31:12],
518+
* buf_size[2:0].
519+
*/
520+
hid_regval = amd_spi->phy_dma_buf | BIT(0);
521+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_OUTPUT_BUF0, hid_regval);
522+
523+
/* Program max write length in hid2_write_control1 register */
524+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_WRITE_CNTRL1);
525+
hid_regval = (hid_regval & ~GENMASK(15, 0)) | ((op->data.nbytes) + 3);
526+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_WRITE_CNTRL1, hid_regval);
527+
528+
/* Set cmd start bit in hid2_cmd_start register to trigger HID basic write operation */
529+
hid_cmd_start = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_CMD_START);
530+
amd_spi_writereg16(amd_spi, AMD_SPI_HID2_CMD_START, (hid_cmd_start | BIT(2)));
531+
532+
/* Check interrupt status of HIDDMA basic write operation in hid2_int_status register */
533+
readw_poll_timeout(amd_spi->io_remap_addr + AMD_SPI_HID2_INT_STATUS, val,
534+
(val & BIT(2)), AMD_SPI_IO_SLEEP_US, AMD_SPI_IO_TIMEOUT_US);
535+
536+
/* Clear the interrupts by writing to hid2_int_status register */
537+
val = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_INT_STATUS);
538+
amd_spi_writereg16(amd_spi, AMD_SPI_HID2_INT_STATUS, val);
539+
}
540+
491541
static void amd_spi_mem_data_out(struct amd_spi *amd_spi,
492542
const struct spi_mem_op *op)
493543
{
494544
int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes;
495545
u64 *buf_64 = (u64 *)op->data.buf.out;
546+
u64 addr_val = op->addr.val;
496547
u32 nbytes = op->data.nbytes;
497548
u32 left_data = nbytes;
498549
u8 *buf;
499550
int i;
500551

501-
amd_spi_set_opcode(amd_spi, op->cmd.opcode);
502-
amd_spi_set_addr(amd_spi, op);
552+
/*
553+
* Condition for using HID write mode. Only for writing complete page data, use HID write.
554+
* Use index mode otherwise.
555+
*/
556+
if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_write_cmd(op->cmd.opcode)) {
557+
u64 *dma_buf64 = (u64 *)(amd_spi->dma_virt_addr + op->addr.nbytes + op->cmd.nbytes);
558+
u8 *dma_buf = (u8 *)amd_spi->dma_virt_addr;
503559

504-
for (i = 0; left_data >= 8; i++, left_data -= 8)
505-
amd_spi_writereg64(amd_spi, base_addr + op->dummy.nbytes + (i * 8), *buf_64++);
560+
/* Copy opcode and address to DMA buffer */
561+
*dma_buf = op->cmd.opcode;
506562

507-
buf = (u8 *)buf_64;
508-
for (i = 0; i < left_data; i++) {
509-
amd_spi_writereg8(amd_spi, base_addr + op->dummy.nbytes + nbytes + i - left_data,
510-
buf[i]);
511-
}
563+
dma_buf = (u8 *)dma_buf64;
564+
for (i = 0; i < op->addr.nbytes; i++) {
565+
*--dma_buf = addr_val & GENMASK(7, 0);
566+
addr_val >>= 8;
567+
}
512568

513-
amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes);
514-
amd_spi_set_rx_count(amd_spi, 0);
515-
amd_spi_clear_fifo_ptr(amd_spi);
516-
amd_spi_execute_opcode(amd_spi);
569+
/* Copy data to DMA buffer */
570+
while (left_data >= 8) {
571+
*dma_buf64++ = *buf_64++;
572+
left_data -= 8;
573+
}
574+
575+
buf = (u8 *)buf_64;
576+
dma_buf = (u8 *)dma_buf64;
577+
while (left_data--)
578+
*dma_buf++ = *buf++;
579+
580+
amd_spi_hiddma_write(amd_spi, op);
581+
} else {
582+
amd_spi_set_opcode(amd_spi, op->cmd.opcode);
583+
amd_spi_set_addr(amd_spi, op);
584+
585+
for (i = 0; left_data >= 8; i++, left_data -= 8)
586+
amd_spi_writereg64(amd_spi, base_addr + op->dummy.nbytes + (i * 8),
587+
*buf_64++);
588+
589+
buf = (u8 *)buf_64;
590+
for (i = 0; i < left_data; i++) {
591+
amd_spi_writereg8(amd_spi,
592+
base_addr + op->dummy.nbytes + nbytes + i - left_data,
593+
buf[i]);
594+
}
595+
596+
amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes);
597+
amd_spi_set_rx_count(amd_spi, 0);
598+
amd_spi_clear_fifo_ptr(amd_spi);
599+
amd_spi_execute_opcode(amd_spi);
600+
}
517601
}
518602

519603
static void amd_spi_hiddma_read(struct amd_spi *amd_spi, const struct spi_mem_op *op)
@@ -708,23 +792,28 @@ static int amd_spi_setup_hiddma(struct amd_spi *amd_spi, struct device *dev)
708792
{
709793
u32 hid_regval;
710794

711-
/* Allocate DMA buffer to use for HID basic read operation */
712-
amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE,
713-
&amd_spi->phy_dma_buf, GFP_KERNEL);
795+
/* Allocate DMA buffer to use for HID basic read and write operations. For write
796+
* operations, the DMA buffer should include the opcode, address bytes and dummy
797+
* bytes(if any) in addition to the data bytes. Additionally, the hardware requires
798+
* that the buffer address be 4K aligned. So, allocate DMA buffer of size
799+
* 2 * AMD_SPI_HID2_DMA_SIZE.
800+
*/
801+
amd_spi->dma_virt_addr = dmam_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE * 2,
802+
&amd_spi->phy_dma_buf, GFP_KERNEL);
714803
if (!amd_spi->dma_virt_addr)
715804
return -ENOMEM;
716805

717806
/*
718807
* Enable interrupts and set mask bits in hid2_int_mask register to generate interrupt
719-
* properly for HIDDMA basic read operations.
808+
* properly for HIDDMA basic read and write operations.
720809
*/
721810
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_INT_MASK);
722-
hid_regval = (hid_regval & GENMASK(31, 8)) | BIT(19);
811+
hid_regval = (hid_regval & GENMASK(31, 8)) | BIT(18) | BIT(19);
723812
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_INT_MASK, hid_regval);
724813

725-
/* Configure buffer unit(4k) in hid2_control register */
814+
/* Configure buffer unit(4k) and write threshold in hid2_control register */
726815
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_CNTRL);
727-
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, hid_regval & ~BIT(3));
816+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, (hid_regval | GENMASK(13, 12)) & ~BIT(3));
728817

729818
return 0;
730819
}

0 commit comments

Comments
 (0)