Message ID | 20250509181737.997167-1-Raju.Rangoju@amd.com |
---|---|
State | New |
Headers | show |
Series | spi: spi_amd: Add HIDDMA basic write support | expand |
Hi Raju, kernel test robot noticed the following build warnings: [auto build test WARNING on v6.15-rc5] [also build test WARNING on linus/master] [cannot apply to broonie-spi/for-next next-20250509] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/spi-spi_amd-Add-HIDDMA-basic-write-support/20250510-021954 base: v6.15-rc5 patch link: https://lore.kernel.org/r/20250509181737.997167-1-Raju.Rangoju%40amd.com patch subject: [PATCH] spi: spi_amd: Add HIDDMA basic write support config: m68k-randconfig-r111-20250511 (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/config) compiler: m68k-linux-gcc (GCC) 14.2.0 reproduce: (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202505110641.zLT16Dv7-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> drivers/spi/spi-amd.c:594:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@ drivers/spi/spi-amd.c:594:57: sparse: expected void volatile [noderef] __iomem *addr drivers/spi/spi-amd.c:594:57: sparse: got void * vim +594 drivers/spi/spi-amd.c 566 567 static void amd_spi_mem_data_out(struct amd_spi *amd_spi, 568 const struct spi_mem_op *op) 569 { 570 int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes; 571 u64 *buf_64 = (u64 *)op->data.buf.out; 572 u64 addr_val = op->addr.val; 573 u32 nbytes = op->data.nbytes; 574 u32 left_data = nbytes; 575 u8 *buf; 576 int i; 577 578 /* 579 * Condition for using HID write mode. Only for writing complete page data, use HID write. 580 * Use index mode otherwise. 581 */ 582 if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_write_cmd(op->cmd.opcode)) { 583 void *hid_base_addr = amd_spi->dma_virt_addr + op->addr.nbytes + op->cmd.nbytes; 584 585 /* Write opcode and address in system memory */ 586 writeb(op->cmd.opcode, amd_spi->dma_virt_addr); 587 588 for (i = 0; i < op->addr.nbytes; i++) { 589 writeb(addr_val & GENMASK(7, 0), hid_base_addr - i - op->cmd.nbytes); 590 addr_val >>= 8; 591 } 592 593 for (i = 0; left_data >= 8; i++, left_data -= 8) > 594 writeq(*buf_64++, hid_base_addr + (i * 8)); 595 596 buf = (u8 *)buf_64; 597 598 for (i = 0; i < left_data; i++) 599 writeb(buf[i], hid_base_addr + (nbytes - left_data + i)); 600 601 amd_spi_hiddma_write(amd_spi, op); 602 } else { 603 amd_spi_set_opcode(amd_spi, op->cmd.opcode); 604 amd_spi_set_addr(amd_spi, op); 605 606 for (i = 0; left_data >= 8; i++, left_data -= 8) 607 amd_spi_writereg64(amd_spi, base_addr + op->dummy.nbytes + (i * 8), 608 *buf_64++); 609 610 buf = (u8 *)buf_64; 611 for (i = 0; i < left_data; i++) { 612 amd_spi_writereg8(amd_spi, 613 base_addr + op->dummy.nbytes + nbytes + i - left_data, 614 buf[i]); 615 } 616 617 amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes); 618 amd_spi_set_rx_count(amd_spi, 0); 619 amd_spi_clear_fifo_ptr(amd_spi); 620 amd_spi_execute_opcode(amd_spi); 621 } 622 } 623
On 5/11/2025 3:51 AM, kernel test robot wrote: > Hi Raju, > > kernel test robot noticed the following build warnings: > > [auto build test WARNING on v6.15-rc5] > [also build test WARNING on linus/master] > [cannot apply to broonie-spi/for-next next-20250509] > [If your patch is applied to the wrong git tree, kindly drop us a note. > And when submitting patch, we suggest to use '--base' as documented in > https://git-scm.com/docs/git-format-patch#_base_tree_information] > > url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/spi-spi_amd-Add-HIDDMA-basic-write-support/20250510-021954 > base: v6.15-rc5 > patch link: https://lore.kernel.org/r/20250509181737.997167-1-Raju.Rangoju%40amd.com > patch subject: [PATCH] spi: spi_amd: Add HIDDMA basic write support > config: m68k-randconfig-r111-20250511 (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/config) > compiler: m68k-linux-gcc (GCC) 14.2.0 Thanks for reporting this. We do not support m68k. Will re-spin v2 with necessary changes in Kconfig. > reproduce: (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/reproduce) > > If you fix the issue in a separate patch/commit (i.e. not just a new version of > the same patch/commit), kindly add following tags > | Reported-by: kernel test robot <lkp@intel.com> > | Closes: https://lore.kernel.org/oe-kbuild-all/202505110641.zLT16Dv7-lkp@intel.com/ > > sparse warnings: (new ones prefixed by >>) >>> drivers/spi/spi-amd.c:594:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@ > drivers/spi/spi-amd.c:594:57: sparse: expected void volatile [noderef] __iomem *addr > drivers/spi/spi-amd.c:594:57: sparse: got void *
Hi Rangoju, On Mon, 12 May 2025 at 09:29, Rangoju, Raju <raju.rangoju@amd.com> wrote: > On 5/11/2025 3:51 AM, kernel test robot wrote: > > kernel test robot noticed the following build warnings: > > > > [auto build test WARNING on v6.15-rc5] > > [also build test WARNING on linus/master] > > [cannot apply to broonie-spi/for-next next-20250509] > > [If your patch is applied to the wrong git tree, kindly drop us a note. > > And when submitting patch, we suggest to use '--base' as documented in > > https://git-scm.com/docs/git-format-patch#_base_tree_information] > > > > url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/spi-spi_amd-Add-HIDDMA-basic-write-support/20250510-021954 > > base: v6.15-rc5 > > patch link: https://lore.kernel.org/r/20250509181737.997167-1-Raju.Rangoju%40amd.com > > patch subject: [PATCH] spi: spi_amd: Add HIDDMA basic write support > > config: m68k-randconfig-r111-20250511 (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/config) > > compiler: m68k-linux-gcc (GCC) 14.2.0 > > Thanks for reporting this. We do not support m68k. All write[bwlq]() functions take a volatile void __iomem pointer (https://elixir.bootlin.com/linux/v6.14.6/source/include/asm-generic/io.h#L174) while you are passing a void *, so sparse should complain about this on all architectures. And sparse is right, this driver is using MMIO accessors on allocated DMA memory, which is just plain wrong: amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE, &amd_spi->phy_dma_buf, GFP_KERNEL); for (i = 0; left_data >= 8; i++, left_data -= 8) *buf_64++ = readq((u8 __iomem *)amd_spi->dma_virt_addr + (i * 8)); > Will re-spin v2 with necessary changes in Kconfig. Please fix the real issue instead ;-) > > reproduce: (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/reproduce) > > > > If you fix the issue in a separate patch/commit (i.e. not just a new version of > > the same patch/commit), kindly add following tags > > | Reported-by: kernel test robot <lkp@intel.com> > > | Closes: https://lore.kernel.org/oe-kbuild-all/202505110641.zLT16Dv7-lkp@intel.com/ > > > > sparse warnings: (new ones prefixed by >>) > >>> drivers/spi/spi-amd.c:594:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@ > > drivers/spi/spi-amd.c:594:57: sparse: expected void volatile [noderef] __iomem *addr > > drivers/spi/spi-amd.c:594:57: sparse: got void * Gr{oetje,eeting}s, Geert
On 5/12/2025 7:47 PM, Geert Uytterhoeven wrote: > Hi Rangoju, > > On Mon, 12 May 2025 at 09:29, Rangoju, Raju <raju.rangoju@amd.com> wrote: >> On 5/11/2025 3:51 AM, kernel test robot wrote: >>> kernel test robot noticed the following build warnings: >>> >>> [auto build test WARNING on v6.15-rc5] >>> [also build test WARNING on linus/master] >>> [cannot apply to broonie-spi/for-next next-20250509] >>> [If your patch is applied to the wrong git tree, kindly drop us a note. >>> And when submitting patch, we suggest to use '--base' as documented in >>> https://git-scm.com/docs/git-format-patch#_base_tree_information] >>> >>> url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/spi-spi_amd-Add-HIDDMA-basic-write-support/20250510-021954 >>> base: v6.15-rc5 >>> patch link: https://lore.kernel.org/r/20250509181737.997167-1-Raju.Rangoju%40amd.com >>> patch subject: [PATCH] spi: spi_amd: Add HIDDMA basic write support >>> config: m68k-randconfig-r111-20250511 (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/config) >>> compiler: m68k-linux-gcc (GCC) 14.2.0 >> >> Thanks for reporting this. We do not support m68k. > > All write[bwlq]() functions take a volatile void __iomem pointer > (https://elixir.bootlin.com/linux/v6.14.6/source/include/asm-generic/io.h#L174) > while you are passing a void *, so sparse should complain about this > on all architectures. My bad, with the following flags included, sparse now complains this on all architectures. -fmax-errors=unlimited -fmax-warnings=unlimited And sparse is right, this driver is using MMIO > accessors on allocated DMA memory, which is just plain wrong: > > amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE, > &amd_spi->phy_dma_buf, GFP_KERNEL); > > for (i = 0; left_data >= 8; i++, left_data -= 8) > *buf_64++ = readq((u8 __iomem *)amd_spi->dma_virt_addr + (i * 8)); > >> Will re-spin v2 with necessary changes in Kconfig. > > Please fix the real issue instead ;-) We are using read*/write* calls instead of memcpy to copy data to/from DMA memory due to performance concerns, as we observed better throughput during continuous read/write compared to the memcpy functions. Additionally, the DMA operations are entirely handled by the hardware, and the software's role is limited to copying data to the DMA buffer. > >>> reproduce: (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/reproduce) >>> >>> If you fix the issue in a separate patch/commit (i.e. not just a new version of >>> the same patch/commit), kindly add following tags >>> | Reported-by: kernel test robot <lkp@intel.com> >>> | Closes: https://lore.kernel.org/oe-kbuild-all/202505110641.zLT16Dv7-lkp@intel.com/ >>> >>> sparse warnings: (new ones prefixed by >>) >>>>> drivers/spi/spi-amd.c:594:57: sparse: sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *addr @@ got void * @@ >>> drivers/spi/spi-amd.c:594:57: sparse: expected void volatile [noderef] __iomem *addr >>> drivers/spi/spi-amd.c:594:57: sparse: got void * > > Gr{oetje,eeting}s, > > Geert >
Hi Raju, On Mon, 12 May 2025 at 19:55, Rangoju, Raju <raju.rangoju@amd.com> wrote: > On 5/12/2025 7:47 PM, Geert Uytterhoeven wrote: > > On Mon, 12 May 2025 at 09:29, Rangoju, Raju <raju.rangoju@amd.com> wrote: > >> On 5/11/2025 3:51 AM, kernel test robot wrote: > >>> kernel test robot noticed the following build warnings: > >>> > >>> [auto build test WARNING on v6.15-rc5] > >>> [also build test WARNING on linus/master] > >>> [cannot apply to broonie-spi/for-next next-20250509] > >>> [If your patch is applied to the wrong git tree, kindly drop us a note. > >>> And when submitting patch, we suggest to use '--base' as documented in > >>> https://git-scm.com/docs/git-format-patch#_base_tree_information] > >>> > >>> url: https://github.com/intel-lab-lkp/linux/commits/Raju-Rangoju/spi-spi_amd-Add-HIDDMA-basic-write-support/20250510-021954 > >>> base: v6.15-rc5 > >>> patch link: https://lore.kernel.org/r/20250509181737.997167-1-Raju.Rangoju%40amd.com > >>> patch subject: [PATCH] spi: spi_amd: Add HIDDMA basic write support > >>> config: m68k-randconfig-r111-20250511 (https://download.01.org/0day-ci/archive/20250511/202505110641.zLT16Dv7-lkp@intel.com/config) > >>> compiler: m68k-linux-gcc (GCC) 14.2.0 > >> > >> Thanks for reporting this. We do not support m68k. > > > > All write[bwlq]() functions take a volatile void __iomem pointer > > (https://elixir.bootlin.com/linux/v6.14.6/source/include/asm-generic/io.h#L174) > > while you are passing a void *, so sparse should complain about this > > on all architectures. > > My bad, with the following flags included, sparse now complains this on > all architectures. > > -fmax-errors=unlimited -fmax-warnings=unlimited > > And sparse is right, this driver is using MMIO > > accessors on allocated DMA memory, which is just plain wrong: > > > > amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE, > > &amd_spi->phy_dma_buf, GFP_KERNEL); > > > > for (i = 0; left_data >= 8; i++, left_data -= 8) > > *buf_64++ = readq((u8 __iomem *)amd_spi->dma_virt_addr + (i * 8)); > > > >> Will re-spin v2 with necessary changes in Kconfig. > > > > Please fix the real issue instead ;-) > > We are using read*/write* calls instead of memcpy to copy data to/from > DMA memory due to performance concerns, as we observed better throughput > during continuous read/write compared to the memcpy functions. Perhaps your memcpy() copies backwards? https://lwn.net/Articles/1016300/ There is no guarantee that read*/write* calls work on normal RAM on all architectures. It may just crash, as some architectures return cookies instead of real pointers when mapping MMIO. Gr{oetje,eeting}s, Geert
diff --git a/drivers/spi/spi-amd.c b/drivers/spi/spi-amd.c index 17fc0b17e756..8567465d2282 100644 --- a/drivers/spi/spi-amd.c +++ b/drivers/spi/spi-amd.c @@ -52,10 +52,13 @@ #define AMD_SPI_SPD7_MASK GENMASK(13, AMD_SPI_SPD7_SHIFT) #define AMD_SPI_HID2_INPUT_RING_BUF0 0X100 +#define AMD_SPI_HID2_OUTPUT_BUF0 0x140 #define AMD_SPI_HID2_CNTRL 0x150 #define AMD_SPI_HID2_INT_STATUS 0x154 #define AMD_SPI_HID2_CMD_START 0x156 #define AMD_SPI_HID2_INT_MASK 0x158 +#define AMD_SPI_HID2_WRITE_CNTRL0 0x160 +#define AMD_SPI_HID2_WRITE_CNTRL1 0x164 #define AMD_SPI_HID2_READ_CNTRL0 0x170 #define AMD_SPI_HID2_READ_CNTRL1 0x174 #define AMD_SPI_HID2_READ_CNTRL2 0x180 @@ -93,6 +96,10 @@ enum amd_spi_versions { AMD_HID2_SPI, }; +/* SPINAND write command opcodes */ +#define AMD_SPI_OP_PP 0x02 /* Page program */ +#define AMD_SPI_OP_PP_RANDOM 0x84 /* Page program */ + enum amd_spi_speed { F_66_66MHz, F_33_33MHz, @@ -445,6 +452,17 @@ static inline bool amd_is_spi_read_cmd(const u16 op) } } +static inline bool amd_is_spi_write_cmd(const u16 op) +{ + switch (op) { + case AMD_SPI_OP_PP: + case AMD_SPI_OP_PP_RANDOM: + return true; + default: + return false; + } +} + static bool amd_spi_supports_op(struct spi_mem *mem, const struct spi_mem_op *op) { @@ -455,7 +473,7 @@ static bool amd_spi_supports_op(struct spi_mem *mem, return false; /* AMD SPI controllers support quad mode only for read operations */ - if (amd_is_spi_read_cmd(op->cmd.opcode)) { + if (amd_is_spi_read_cmd(op->cmd.opcode) || amd_is_spi_write_cmd(op->cmd.opcode)) { if (op->data.buswidth > 4) return false; @@ -464,7 +482,8 @@ static bool amd_spi_supports_op(struct spi_mem *mem, * doesn't support 4-byte address commands. */ if (amd_spi->version == AMD_HID2_SPI) { - if (amd_is_spi_read_cmd_4b(op->cmd.opcode) || + if ((amd_is_spi_read_cmd_4b(op->cmd.opcode) || + amd_is_spi_write_cmd(op->cmd.opcode)) && op->data.nbytes > AMD_SPI_HID2_DMA_SIZE) return false; } else if (op->data.nbytes > AMD_SPI_MAX_DATA) { @@ -490,7 +509,8 @@ static int amd_spi_adjust_op_size(struct spi_mem *mem, struct spi_mem_op *op) * controller index mode supports maximum of 64 bytes in a single * transaction. */ - if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_read_cmd(op->cmd.opcode)) + if (amd_spi->version == AMD_HID2_SPI && (amd_is_spi_read_cmd(op->cmd.opcode) || + amd_is_spi_write_cmd(op->cmd.opcode))) op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_HID2_DMA_SIZE); else op->data.nbytes = clamp_val(op->data.nbytes, 0, AMD_SPI_MAX_DATA); @@ -514,32 +534,91 @@ static void amd_spi_set_addr(struct amd_spi *amd_spi, } } +static void amd_spi_hiddma_write(struct amd_spi *amd_spi, const struct spi_mem_op *op) +{ + u16 hid_cmd_start, val; + u32 hid_regval; + + /* + * Program the HID2 output Buffer0. 4k aligned buf_memory_addr[31:12], + * buf_size[2:0]. + */ + hid_regval = amd_spi->phy_dma_buf | BIT(0); + amd_spi_writereg32(amd_spi, AMD_SPI_HID2_OUTPUT_BUF0, hid_regval); + + /* Program max write length in hid2_write_control1 register */ + hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_WRITE_CNTRL1); + hid_regval = (hid_regval & ~GENMASK(15, 0)) | ((op->data.nbytes) + 3); + amd_spi_writereg32(amd_spi, AMD_SPI_HID2_WRITE_CNTRL1, hid_regval); + + /* Set cmd start bit in hid2_cmd_start register to trigger HID basic write operation */ + hid_cmd_start = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_CMD_START); + amd_spi_writereg16(amd_spi, AMD_SPI_HID2_CMD_START, (hid_cmd_start | BIT(2))); + + /* Check interrupt status of HIDDMA basic write operation in hid2_int_status register */ + readw_poll_timeout(amd_spi->io_remap_addr + AMD_SPI_HID2_INT_STATUS, val, + (val & BIT(2)), AMD_SPI_IO_SLEEP_US, AMD_SPI_IO_TIMEOUT_US); + + /* Clear the interrupts by writing to hid2_int_status register */ + val = amd_spi_readreg16(amd_spi, AMD_SPI_HID2_INT_STATUS); + amd_spi_writereg16(amd_spi, AMD_SPI_HID2_INT_STATUS, val); +} + static void amd_spi_mem_data_out(struct amd_spi *amd_spi, const struct spi_mem_op *op) { int base_addr = AMD_SPI_FIFO_BASE + op->addr.nbytes; u64 *buf_64 = (u64 *)op->data.buf.out; + u64 addr_val = op->addr.val; u32 nbytes = op->data.nbytes; u32 left_data = nbytes; u8 *buf; int i; - amd_spi_set_opcode(amd_spi, op->cmd.opcode); - amd_spi_set_addr(amd_spi, op); + /* + * Condition for using HID write mode. Only for writing complete page data, use HID write. + * Use index mode otherwise. + */ + if (amd_spi->version == AMD_HID2_SPI && amd_is_spi_write_cmd(op->cmd.opcode)) { + void *hid_base_addr = amd_spi->dma_virt_addr + op->addr.nbytes + op->cmd.nbytes; - for (i = 0; left_data >= 8; i++, left_data -= 8) - amd_spi_writereg64(amd_spi, base_addr + op->dummy.nbytes + (i * 8), *buf_64++); + /* Write opcode and address in system memory */ + writeb(op->cmd.opcode, amd_spi->dma_virt_addr); - buf = (u8 *)buf_64; - for (i = 0; i < left_data; i++) { - amd_spi_writereg8(amd_spi, base_addr + op->dummy.nbytes + nbytes + i - left_data, - buf[i]); - } + for (i = 0; i < op->addr.nbytes; i++) { + writeb(addr_val & GENMASK(7, 0), hid_base_addr - i - op->cmd.nbytes); + addr_val >>= 8; + } - amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes); - amd_spi_set_rx_count(amd_spi, 0); - amd_spi_clear_fifo_ptr(amd_spi); - amd_spi_execute_opcode(amd_spi); + for (i = 0; left_data >= 8; i++, left_data -= 8) + writeq(*buf_64++, hid_base_addr + (i * 8)); + + buf = (u8 *)buf_64; + + for (i = 0; i < left_data; i++) + writeb(buf[i], hid_base_addr + (nbytes - left_data + i)); + + amd_spi_hiddma_write(amd_spi, op); + } else { + amd_spi_set_opcode(amd_spi, op->cmd.opcode); + amd_spi_set_addr(amd_spi, op); + + for (i = 0; left_data >= 8; i++, left_data -= 8) + amd_spi_writereg64(amd_spi, base_addr + op->dummy.nbytes + (i * 8), + *buf_64++); + + buf = (u8 *)buf_64; + for (i = 0; i < left_data; i++) { + amd_spi_writereg8(amd_spi, + base_addr + op->dummy.nbytes + nbytes + i - left_data, + buf[i]); + } + + amd_spi_set_tx_count(amd_spi, op->addr.nbytes + op->data.nbytes); + amd_spi_set_rx_count(amd_spi, 0); + amd_spi_clear_fifo_ptr(amd_spi); + amd_spi_execute_opcode(amd_spi); + } } static void amd_spi_hiddma_read(struct amd_spi *amd_spi, const struct spi_mem_op *op) @@ -728,23 +807,28 @@ static int amd_spi_setup_hiddma(struct amd_spi *amd_spi, struct device *dev) { u32 hid_regval; - /* Allocate DMA buffer to use for HID basic read operation */ - amd_spi->dma_virt_addr = dma_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE, - &amd_spi->phy_dma_buf, GFP_KERNEL); + /* Allocate DMA buffer to use for HID basic read and write operations. For write + * operations, the DMA buffer should include the opcode, address bytes and dummy + * bytes(if any) in addition to the data bytes. Additionally, the hardware requires + * that the buffer address be 4K aligned. So, allocate DMA buffer of size + * 2 * AMD_SPI_HID2_DMA_SIZE. + */ + amd_spi->dma_virt_addr = dmam_alloc_coherent(dev, AMD_SPI_HID2_DMA_SIZE * 2, + &amd_spi->phy_dma_buf, GFP_KERNEL); if (!amd_spi->dma_virt_addr) return -ENOMEM; /* * Enable interrupts and set mask bits in hid2_int_mask register to generate interrupt - * properly for HIDDMA basic read operations. + * properly for HIDDMA basic read and write operations. */ hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_INT_MASK); - hid_regval = (hid_regval & GENMASK(31, 8)) | BIT(19); + hid_regval = (hid_regval & GENMASK(31, 8)) | BIT(18) | BIT(19); amd_spi_writereg32(amd_spi, AMD_SPI_HID2_INT_MASK, hid_regval); - /* Configure buffer unit(4k) in hid2_control register */ + /* Configure buffer unit(4k) and write threshold in hid2_control register */ hid_regval = amd_spi_readreg32(amd_spi, AMD_SPI_HID2_CNTRL); - amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, hid_regval & ~BIT(3)); + amd_spi_writereg32(amd_spi, AMD_SPI_HID2_CNTRL, (hid_regval | GENMASK(13, 12)) & ~BIT(3)); return 0; }