Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: spi_amd: Add PCI-based driver for AMD HID2 SPI controller

Register a new driver(spi_amd_pci) for the HID2 SPI controller using the
PCI ID of the LPC bridge device.

Add a new common probe function in spi_amd driver to encapsulate the
code required for registering the controller driver. This function will be
utilized by both the existing ACPI driver and the newly introduced
PCI-based driver for the HID2 SPI controller. The MMIO register base
address of the HID2 SPI controller can be obtained from the PCI LPC bridge
registers.

By implementing these changes, the DMA buffer will be correctly associated
with the LPC bridge device, preventing IO_PAGE_FAULT caused by IOMMU when
the LPC bridge attempts DMA operations on addresses owned by 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/20250402121514.2941334-1-Raju.Rangoju@amd.com
Signed-off-by: Mark Brown <broonie@kernel.org>

authored by

Raju Rangoju and committed by
Mark Brown
b644c277 f48d8050

+147 -49
+2
MAINTAINERS
··· 1216 1216 M: Raju Rangoju <Raju.Rangoju@amd.com> 1217 1217 L: linux-spi@vger.kernel.org 1218 1218 S: Supported 1219 + F: drivers/spi/spi-amd-pci.c 1219 1220 F: drivers/spi/spi-amd.c 1221 + F: drivers/spi/spi-amd.h 1220 1222 1221 1223 AMD XDNA DRIVER 1222 1224 M: Min Ma <min.ma@amd.com>
+1 -1
drivers/spi/Makefile
··· 162 162 obj-$(CONFIG_SPI_XTENSA_XTFPGA) += spi-xtensa-xtfpga.o 163 163 obj-$(CONFIG_SPI_ZYNQ_QSPI) += spi-zynq-qspi.o 164 164 obj-$(CONFIG_SPI_ZYNQMP_GQSPI) += spi-zynqmp-gqspi.o 165 - obj-$(CONFIG_SPI_AMD) += spi-amd.o 165 + obj-$(CONFIG_SPI_AMD) += spi-amd.o spi-amd-pci.o 166 166 167 167 # SPI slave protocol handlers 168 168 obj-$(CONFIG_SPI_SLAVE_TIME) += spi-slave-time.o
+70
drivers/spi/spi-amd-pci.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * AMD SPI controller driver 4 + * 5 + * Copyright (c) 2025, Advanced Micro Devices, Inc. 6 + * All Rights Reserved. 7 + * 8 + * Authors: Krishnamoorthi M <krishnamoorthi.m@amd.com> 9 + * Akshata MukundShetty <akshata.mukundshetty@amd.com> 10 + */ 11 + 12 + #include <linux/init.h> 13 + #include <linux/spi/spi.h> 14 + #include <linux/pci.h> 15 + 16 + #include "spi-amd.h" 17 + 18 + #define AMD_PCI_DEVICE_ID_LPC_BRIDGE 0x1682 19 + #define AMD_PCI_LPC_SPI_BASE_ADDR_REG 0xA0 20 + #define AMD_SPI_BASE_ADDR_MASK ~0xFF 21 + #define AMD_HID2_PCI_BAR_OFFSET 0x00002000 22 + #define AMD_HID2_MEM_SIZE 0x200 23 + 24 + static struct pci_device_id pci_spi_ids[] = { 25 + { PCI_DEVICE(PCI_VENDOR_ID_AMD, AMD_PCI_DEVICE_ID_LPC_BRIDGE) }, 26 + { 0, } 27 + }; 28 + MODULE_DEVICE_TABLE(pci, pci_spi_ids); 29 + 30 + static int amd_spi_pci_probe(struct pci_dev *pdev, 31 + const struct pci_device_id *id) 32 + { 33 + struct device *dev = &pdev->dev; 34 + struct spi_controller *host; 35 + struct amd_spi *amd_spi; 36 + u32 io_base_addr; 37 + 38 + /* Allocate storage for host and driver private data */ 39 + host = devm_spi_alloc_host(dev, sizeof(struct amd_spi)); 40 + if (!host) 41 + return dev_err_probe(dev, -ENOMEM, "Error allocating SPI host\n"); 42 + 43 + amd_spi = spi_controller_get_devdata(host); 44 + 45 + pci_read_config_dword(pdev, AMD_PCI_LPC_SPI_BASE_ADDR_REG, &io_base_addr); 46 + io_base_addr = (io_base_addr & AMD_SPI_BASE_ADDR_MASK) + AMD_HID2_PCI_BAR_OFFSET; 47 + amd_spi->io_remap_addr = devm_ioremap(dev, io_base_addr, AMD_HID2_MEM_SIZE); 48 + 49 + if (IS_ERR(amd_spi->io_remap_addr)) 50 + return dev_err_probe(dev, PTR_ERR(amd_spi->io_remap_addr), 51 + "ioremap of SPI registers failed\n"); 52 + 53 + dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); 54 + 55 + amd_spi->version = AMD_HID2_SPI; 56 + host->bus_num = 2; 57 + 58 + return amd_spi_probe_common(dev, host); 59 + } 60 + 61 + static struct pci_driver amd_spi_pci_driver = { 62 + .name = "amd_spi_pci", 63 + .id_table = pci_spi_ids, 64 + .probe = amd_spi_pci_probe, 65 + }; 66 + 67 + module_pci_driver(amd_spi_pci_driver); 68 + 69 + MODULE_LICENSE("GPL"); 70 + MODULE_DESCRIPTION("AMD HID2 SPI Controller Driver");
+30 -48
drivers/spi/spi-amd.c
··· 17 17 #include <linux/spi/spi.h> 18 18 #include <linux/spi/spi-mem.h> 19 19 20 + #include "spi-amd.h" 21 + 20 22 #define AMD_SPI_CTRL0_REG 0x00 21 23 #define AMD_SPI_EXEC_CMD BIT(16) 22 24 #define AMD_SPI_FIFO_CLEAR BIT(20) ··· 83 81 #define AMD_SPI_OP_READ_1_1_4_4B 0x6c /* Read data bytes (Quad Output SPI) */ 84 82 #define AMD_SPI_OP_READ_1_4_4_4B 0xec /* Read data bytes (Quad I/O SPI) */ 85 83 86 - /** 87 - * enum amd_spi_versions - SPI controller versions 88 - * @AMD_SPI_V1: AMDI0061 hardware version 89 - * @AMD_SPI_V2: AMDI0062 hardware version 90 - * @AMD_HID2_SPI: AMDI0063 hardware version 91 - */ 92 - enum amd_spi_versions { 93 - AMD_SPI_V1 = 1, 94 - AMD_SPI_V2, 95 - AMD_HID2_SPI, 96 - }; 97 - 98 84 enum amd_spi_speed { 99 85 F_66_66MHz, 100 86 F_33_33MHz, ··· 106 116 u32 speed_hz; 107 117 u32 enable_val; 108 118 u32 spd7_val; 109 - }; 110 - 111 - /** 112 - * struct amd_spi - SPI driver instance 113 - * @io_remap_addr: Start address of the SPI controller registers 114 - * @phy_dma_buf: Physical address of DMA buffer 115 - * @dma_virt_addr: Virtual address of DMA buffer 116 - * @version: SPI controller hardware version 117 - * @speed_hz: Device frequency 118 - */ 119 - struct amd_spi { 120 - void __iomem *io_remap_addr; 121 - dma_addr_t phy_dma_buf; 122 - void *dma_virt_addr; 123 - enum amd_spi_versions version; 124 - unsigned int speed_hz; 125 119 }; 126 120 127 121 static inline u8 amd_spi_readreg8(struct amd_spi *amd_spi, int idx) ··· 723 749 return 0; 724 750 } 725 751 726 - static int amd_spi_probe(struct platform_device *pdev) 752 + int amd_spi_probe_common(struct device *dev, struct spi_controller *host) 727 753 { 728 - struct device *dev = &pdev->dev; 729 - struct spi_controller *host; 730 - struct amd_spi *amd_spi; 754 + struct amd_spi *amd_spi = spi_controller_get_devdata(host); 731 755 int err; 732 756 733 - /* Allocate storage for host and driver private data */ 734 - host = devm_spi_alloc_host(dev, sizeof(struct amd_spi)); 735 - if (!host) 736 - return dev_err_probe(dev, -ENOMEM, "Error allocating SPI host\n"); 737 - 738 - amd_spi = spi_controller_get_devdata(host); 739 - amd_spi->io_remap_addr = devm_platform_ioremap_resource(pdev, 0); 740 - if (IS_ERR(amd_spi->io_remap_addr)) 741 - return dev_err_probe(dev, PTR_ERR(amd_spi->io_remap_addr), 742 - "ioremap of SPI registers failed\n"); 743 - 744 - dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); 745 - 746 - amd_spi->version = (uintptr_t) device_get_match_data(dev); 747 - 748 757 /* Initialize the spi_controller fields */ 749 - host->bus_num = (amd_spi->version == AMD_HID2_SPI) ? 2 : 0; 750 758 host->num_chipselect = 4; 751 759 host->mode_bits = SPI_TX_DUAL | SPI_TX_QUAD | SPI_RX_DUAL | SPI_RX_QUAD; 752 760 host->flags = SPI_CONTROLLER_HALF_DUPLEX; ··· 750 794 err = amd_spi_setup_hiddma(amd_spi, dev); 751 795 752 796 return err; 797 + } 798 + EXPORT_SYMBOL_GPL(amd_spi_probe_common); 799 + 800 + static int amd_spi_probe(struct platform_device *pdev) 801 + { 802 + struct device *dev = &pdev->dev; 803 + struct spi_controller *host; 804 + struct amd_spi *amd_spi; 805 + 806 + /* Allocate storage for host and driver private data */ 807 + host = devm_spi_alloc_host(dev, sizeof(struct amd_spi)); 808 + if (!host) 809 + return dev_err_probe(dev, -ENOMEM, "Error allocating SPI host\n"); 810 + 811 + amd_spi = spi_controller_get_devdata(host); 812 + amd_spi->io_remap_addr = devm_platform_ioremap_resource(pdev, 0); 813 + if (IS_ERR(amd_spi->io_remap_addr)) 814 + return dev_err_probe(dev, PTR_ERR(amd_spi->io_remap_addr), 815 + "ioremap of SPI registers failed\n"); 816 + 817 + dev_dbg(dev, "io_remap_address: %p\n", amd_spi->io_remap_addr); 818 + 819 + amd_spi->version = (uintptr_t)device_get_match_data(dev); 820 + host->bus_num = 0; 821 + 822 + return amd_spi_probe_common(dev, host); 753 823 } 754 824 755 825 #ifdef CONFIG_ACPI
+44
drivers/spi/spi-amd.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * AMD SPI controller driver common stuff 4 + * 5 + * Copyright (c) 2025, Advanced Micro Devices, Inc. 6 + * All Rights Reserved. 7 + * 8 + * Author: Krishnamoorthi M <krishnamoorthi.m@amd.com> 9 + */ 10 + 11 + #ifndef SPI_AMD_H 12 + #define SPI_AMD_H 13 + 14 + /** 15 + * enum amd_spi_versions - SPI controller versions 16 + * @AMD_SPI_V1: AMDI0061 hardware version 17 + * @AMD_SPI_V2: AMDI0062 hardware version 18 + * @AMD_HID2_SPI: AMDI0063 hardware version 19 + */ 20 + enum amd_spi_versions { 21 + AMD_SPI_V1 = 1, 22 + AMD_SPI_V2, 23 + AMD_HID2_SPI, 24 + }; 25 + 26 + /** 27 + * struct amd_spi - SPI driver instance 28 + * @io_remap_addr: Start address of the SPI controller registers 29 + * @phy_dma_buf: Physical address of DMA buffer 30 + * @dma_virt_addr: Virtual address of DMA buffer 31 + * @version: SPI controller hardware version 32 + * @speed_hz: Device frequency 33 + */ 34 + struct amd_spi { 35 + void __iomem *io_remap_addr; 36 + dma_addr_t phy_dma_buf; 37 + void *dma_virt_addr; 38 + enum amd_spi_versions version; 39 + unsigned int speed_hz; 40 + }; 41 + 42 + int amd_spi_probe_common(struct device *dev, struct spi_controller *host); 43 + 44 + #endif /* SPI_AMD_H */