Skip to content

Commit 6c30eee

Browse files
RajuRangojubroonie
authored andcommitted
spi: spi_amd: Add HIDDMA basic read support
SPI index mode has hardware limitation of reading only 64 bytes per transaction due to fixed number of FIFO registers. This constraint leads to performance issues when reading data from NAND/NOR flash devices, as the controller must issue multiple requests to read 64-byte chunks, even if the slave can send up to 2 or 4 KB in single transaction. The AMD HID2 SPI controller supports DMA mode, which allows reading up to 4 KB of data in single transaction. This patch introduces changes to implement HID2 DMA read support for the HID2 SPI controller. Co-developed-by: Krishnamoorthi M <[email protected]> Signed-off-by: Krishnamoorthi M <[email protected]> Co-developed-by: Akshata MukundShetty <[email protected]> Signed-off-by: Akshata MukundShetty <[email protected]> Signed-off-by: Raju Rangoju <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 9674f16 commit 6c30eee

File tree

1 file changed

+156
-20
lines changed

1 file changed

+156
-20
lines changed

drivers/spi/spi-amd.c

Lines changed: 156 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <linux/acpi.h>
1010
#include <linux/delay.h>
11+
#include <linux/dma-mapping.h>
1112
#include <linux/init.h>
1213
#include <linux/io-64-nonatomic-lo-hi.h>
1314
#include <linux/iopoll.h>
@@ -50,9 +51,21 @@
5051
#define AMD_SPI_SPD7_SHIFT 8
5152
#define AMD_SPI_SPD7_MASK GENMASK(13, AMD_SPI_SPD7_SHIFT)
5253

54+
#define AMD_SPI_HID2_INPUT_RING_BUF0 0X100
55+
#define AMD_SPI_HID2_CNTRL 0x150
56+
#define AMD_SPI_HID2_INT_STATUS 0x154
57+
#define AMD_SPI_HID2_CMD_START 0x156
58+
#define AMD_SPI_HID2_INT_MASK 0x158
59+
#define AMD_SPI_HID2_READ_CNTRL0 0x170
60+
#define AMD_SPI_HID2_READ_CNTRL1 0x174
61+
#define AMD_SPI_HID2_READ_CNTRL2 0x180
62+
5363
#define AMD_SPI_MAX_HZ 100000000
5464
#define AMD_SPI_MIN_HZ 800000
5565

66+
#define AMD_SPI_IO_SLEEP_US 20
67+
#define AMD_SPI_IO_TIMEOUT_US 2000000
68+
5669
/* SPI read command opcodes */
5770
#define AMD_SPI_OP_READ 0x03 /* Read data bytes (low frequency) */
5871
#define AMD_SPI_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
@@ -108,11 +121,15 @@ struct amd_spi_freq {
108121
/**
109122
* struct amd_spi - SPI driver instance
110123
* @io_remap_addr: Start address of the SPI controller registers
124+
* @phy_dma_buf: Physical address of DMA buffer
125+
* @dma_virt_addr: Virtual address of DMA buffer
111126
* @version: SPI controller hardware version
112127
* @speed_hz: Device frequency
113128
*/
114129
struct amd_spi {
115130
void __iomem *io_remap_addr;
131+
dma_addr_t phy_dma_buf;
132+
void *dma_virt_addr;
116133
enum amd_spi_versions version;
117134
unsigned int speed_hz;
118135
};
@@ -135,6 +152,16 @@ static void amd_spi_setclear_reg8(struct amd_spi *amd_spi, int idx, u8 set, u8 c
135152
amd_spi_writereg8(amd_spi, idx, tmp);
136153
}
137154

155+
static inline u16 amd_spi_readreg16(struct amd_spi *amd_spi, int idx)
156+
{
157+
return readw((u8 __iomem *)amd_spi->io_remap_addr + idx);
158+
}
159+
160+
static inline void amd_spi_writereg16(struct amd_spi *amd_spi, int idx, u16 val)
161+
{
162+
writew(val, ((u8 __iomem *)amd_spi->io_remap_addr + idx));
163+
}
164+
138165
static inline u32 amd_spi_readreg32(struct amd_spi *amd_spi, int idx)
139166
{
140167
return readl((u8 __iomem *)amd_spi->io_remap_addr + idx);
@@ -517,36 +544,117 @@ static void amd_spi_mem_data_out(struct amd_spi *amd_spi,
517544
amd_spi_execute_opcode(amd_spi);
518545
}
519546

547+
static void amd_spi_hiddma_read(struct amd_spi *amd_spi, const struct spi_mem_op *op)
548+
{
549+
u16 hid_cmd_start, val;
550+
u32 hid_regval;
551+
552+
/* Set the opcode in hid2_read_control0 register */
553+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_READ_CNTRL0);
554+
hid_regval = (hid_regval & ~GENMASK(7, 0)) | op->cmd.opcode;
555+
556+
/*
557+
* Program the address in the hid2_read_control0 register [8:31]. The address should
558+
* be written starting from the 8th bit of the register, requiring an 8-bit shift.
559+
* Additionally, to convert a 2-byte spinand address to a 3-byte address, another
560+
* 8-bit shift is needed. Therefore, a total shift of 16 bits is required.
561+
*/
562+
hid_regval = (hid_regval & ~GENMASK(31, 8)) | (op->addr.val << 16);
563+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_READ_CNTRL0, hid_regval);
564+
565+
/* Configure dummy clock cycles for fast read, dual, quad I/O commands */
566+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_READ_CNTRL2);
567+
/* Fast read dummy cycle */
568+
hid_regval &= ~GENMASK(4, 0);
569+
570+
/* Fast read Dual I/O dummy cycle */
571+
hid_regval &= ~GENMASK(12, 8);
572+
573+
/* Fast read Quad I/O dummy cycle */
574+
hid_regval = (hid_regval & ~GENMASK(20, 16)) | BIT(17);
575+
576+
/* Set no of preamble bytecount */
577+
hid_regval &= ~GENMASK(27, 24);
578+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_READ_CNTRL2, hid_regval);
579+
580+
/*
581+
* Program the HID2 Input Ring Buffer0. 4k aligned buf_memory_addr[31:12],
582+
* buf_size[4:0], end_input_ring[5].
583+
*/
584+
hid_regval = amd_spi->phy_dma_buf | BIT(5) | BIT(0);
585+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_INPUT_RING_BUF0, hid_regval);
586+
587+
/* Program max read length(no of DWs) in hid2_read_control1 register */
588+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_READ_CNTRL1);
589+
hid_regval = (hid_regval & ~GENMASK(15, 0)) | ((op->data.nbytes / 4) - 1);
590+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_READ_CNTRL1, hid_regval);
591+
592+
/* Set cmd start bit in hid2_cmd_start register to trigger HID basic read operation */
593+
hid_cmd_start = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_CMD_START);
594+
amd_spi_writereg16(amd_spi, AMD_SPI_HID2_CMD_START, (hid_cmd_start | BIT(3)));
595+
596+
/* Check interrupt status of HIDDMA basic read operation in hid2_int_status register */
597+
readw_poll_timeout(amd_spi->io_remap_addr + AMD_SPI_HID2_INT_STATUS, val,
598+
(val & BIT(3)), AMD_SPI_IO_SLEEP_US, AMD_SPI_IO_TIMEOUT_US);
599+
600+
/* Clear the interrupts by writing to hid2_int_status register */
601+
val = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_INT_STATUS);
602+
amd_spi_writereg16(amd_spi, AMD_SPI_HID2_INT_STATUS, val);
603+
}
604+
520605
static void amd_spi_mem_data_in(struct amd_spi *amd_spi,
521606
const struct spi_mem_op *op)
522607
{
523608
int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes;
524609
u64 *buf_64 = (u64 *)op->data.buf.in;
525610
u32 nbytes = op->data.nbytes;
526611
u32 left_data = nbytes;
612+
u32 data;
527613
u8 *buf;
528614
int i;
529615

530-
amd_spi_set_opcode(amd_spi, op->cmd.opcode);
531-
amd_spi_set_addr(amd_spi, op);
532-
amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->dummy.nbytes);
533-
534-
for (i = 0; i < op->dummy.nbytes; i++)
535-
amd_spi_writereg8(amd_spi, (base_addr + i), 0xff);
536-
537-
amd_spi_set_rx_count(amd_spi, op->data.nbytes);
538-
amd_spi_clear_fifo_ptr(amd_spi);
539-
amd_spi_execute_opcode(amd_spi);
540-
amd_spi_busy_wait(amd_spi);
541-
542-
for (i = 0; left_data >= 8; i++, left_data -= 8)
543-
*buf_64++ = amd_spi_readreg64(amd_spi, base_addr + op->dummy.nbytes +
544-
(i * 8));
616+
/*
617+
* Condition for using HID read mode. Only for reading complete page data, use HID read.
618+
* Use index mode otherwise.
619+
*/
620+
if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_read_cmd(op->cmd.opcode)) {
621+
amd_spi_hiddma_read(amd_spi, op);
622+
623+
for (i = 0; left_data >= 8; i++, left_data -= 8)
624+
*buf_64++ = readq((u8 __iomem *)amd_spi->dma_virt_addr + (i * 8));
625+
626+
buf = (u8 *)buf_64;
627+
for (i = 0; i < left_data; i++)
628+
buf[i] = readb((u8 __iomem *)amd_spi->dma_virt_addr +
629+
(nbytes - left_data + i));
630+
631+
/* Reset HID RX memory logic */
632+
data = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_CNTRL);
633+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, data | BIT(5));
634+
} else {
635+
/* Index mode */
636+
amd_spi_set_opcode(amd_spi, op->cmd.opcode);
637+
amd_spi_set_addr(amd_spi, op);
638+
amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->dummy.nbytes);
639+
640+
for (i = 0; i < op->dummy.nbytes; i++)
641+
amd_spi_writereg8(amd_spi, (base_addr + i), 0xff);
642+
643+
amd_spi_set_rx_count(amd_spi, op->data.nbytes);
644+
amd_spi_clear_fifo_ptr(amd_spi);
645+
amd_spi_execute_opcode(amd_spi);
646+
amd_spi_busy_wait(amd_spi);
647+
648+
for (i = 0; left_data >= 8; i++, left_data -= 8)
649+
*buf_64++ = amd_spi_readreg64(amd_spi, base_addr + op->dummy.nbytes +
650+
(i * 8));
651+
652+
buf = (u8 *)buf_64;
653+
for (i = 0; i < left_data; i++)
654+
buf[i] = amd_spi_readreg8(amd_spi, base_addr + op->dummy.nbytes +
655+
nbytes + i - left_data);
656+
}
545657

546-
buf = (u8 *)buf_64;
547-
for (i = 0; i < left_data; i++)
548-
buf[i] = amd_spi_readreg8(amd_spi, base_addr + op->dummy.nbytes +
549-
nbytes + i - left_data);
550658
}
551659

552660
static void amd_set_spi_addr_mode(struct amd_spi *amd_spi,
@@ -617,6 +725,31 @@ static size_t amd_spi_max_transfer_size(struct spi_device *spi)
617725
return AMD_SPI_FIFO_SIZE;
618726
}
619727

728+
static int amd_spi_setup_hiddma(struct amd_spi *amd_spi, struct device *dev)
729+
{
730+
u32 hid_regval;
731+
732+
/* Allocate DMA buffer to use for HID basic read operation */
733+
amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE,
734+
&amd_spi->phy_dma_buf, GFP_KERNEL);
735+
if (!amd_spi->dma_virt_addr)
736+
return -ENOMEM;
737+
738+
/*
739+
* Enable interrupts and set mask bits in hid2_int_mask register to generate interrupt
740+
* properly for HIDDMA basic read operations.
741+
*/
742+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_INT_MASK);
743+
hid_regval = (hid_regval & GENMASK(31, 8)) | BIT(19);
744+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_INT_MASK, hid_regval);
745+
746+
/* Configure buffer unit(4k) in hid2_control register */
747+
hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_CNTRL);
748+
amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, hid_regval & ~BIT(3));
749+
750+
return 0;
751+
}
752+
620753
static int amd_spi_probe(struct platform_device *pdev)
621754
{
622755
struct device *dev = &pdev->dev;
@@ -657,7 +790,10 @@ static int amd_spi_probe(struct platform_device *pdev)
657790
if (err)
658791
return dev_err_probe(dev, err, "error registering SPI controller\n");
659792

660-
return 0;
793+
if (amd_spi->version == AMD_HID2_SPI)
794+
err = amd_spi_setup_hiddma(amd_spi, dev);
795+
796+
return err;
661797
}
662798

663799
#ifdef CONFIG_ACPI

0 commit comments

Comments
 (0)