|
@@ -21,6 +21,7 @@
|
|
|
#include <linux/err.h>
|
|
|
#include <linux/interrupt.h>
|
|
|
#include <linux/kernel.h>
|
|
|
+#include <linux/pci.h>
|
|
|
#include <linux/platform_device.h>
|
|
|
#include <linux/spi/pxa2xx_spi.h>
|
|
|
#include <linux/spi/spi.h>
|
|
@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = {
|
|
|
.tx_threshold_lo = 160,
|
|
|
.tx_threshold_hi = 224,
|
|
|
},
|
|
|
+ { /* LPSS_SPT_SSP */
|
|
|
+ .offset = 0x200,
|
|
|
+ .reg_general = -1,
|
|
|
+ .reg_ssp = 0x20,
|
|
|
+ .reg_cs_ctrl = 0x24,
|
|
|
+ .rx_threshold = 1,
|
|
|
+ .tx_threshold_lo = 32,
|
|
|
+ .tx_threshold_hi = 56,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static inline const struct lpss_config
|
|
@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
|
|
|
switch (drv_data->ssp_type) {
|
|
|
case LPSS_LPT_SSP:
|
|
|
case LPSS_BYT_SSP:
|
|
|
+ case LPSS_SPT_SSP:
|
|
|
return true;
|
|
|
default:
|
|
|
return false;
|
|
@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi)
|
|
|
break;
|
|
|
case LPSS_LPT_SSP:
|
|
|
case LPSS_BYT_SSP:
|
|
|
+ case LPSS_SPT_SSP:
|
|
|
config = lpss_get_config(drv_data);
|
|
|
tx_thres = config->tx_threshold_lo;
|
|
|
tx_hi_thres = config->tx_threshold_hi;
|
|
@@ -1276,6 +1288,30 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
|
|
|
};
|
|
|
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
|
|
|
|
|
|
+/*
|
|
|
+ * PCI IDs of compound devices that integrate both host controller and private
|
|
|
+ * integrated DMA engine. Please note these are not used in module
|
|
|
+ * autoloading and probing in this module but matching the LPSS SSP type.
|
|
|
+ */
|
|
|
+static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
|
|
|
+ /* SPT-LP */
|
|
|
+ { PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
|
|
|
+ { PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
|
|
|
+ /* SPT-H */
|
|
|
+ { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
|
|
|
+ { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
|
|
|
+};
|
|
|
+
|
|
|
+static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
|
|
|
+{
|
|
|
+ struct device *dev = param;
|
|
|
+
|
|
|
+ if (dev != chan->device->dev->parent)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
static struct pxa2xx_spi_master *
|
|
|
pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
|
|
|
{
|
|
@@ -1283,16 +1319,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
|
|
|
struct acpi_device *adev;
|
|
|
struct ssp_device *ssp;
|
|
|
struct resource *res;
|
|
|
- const struct acpi_device_id *id;
|
|
|
+ const struct acpi_device_id *adev_id = NULL;
|
|
|
+ const struct pci_device_id *pcidev_id = NULL;
|
|
|
int devid, type;
|
|
|
|
|
|
if (!ACPI_HANDLE(&pdev->dev) ||
|
|
|
acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
|
|
|
return NULL;
|
|
|
|
|
|
- id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
|
|
|
- if (id)
|
|
|
- type = (int)id->driver_data;
|
|
|
+ if (dev_is_pci(pdev->dev.parent))
|
|
|
+ pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
|
|
|
+ to_pci_dev(pdev->dev.parent));
|
|
|
+ else
|
|
|
+ adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
|
|
|
+ &pdev->dev);
|
|
|
+
|
|
|
+ if (adev_id)
|
|
|
+ type = (int)adev_id->driver_data;
|
|
|
+ else if (pcidev_id)
|
|
|
+ type = (int)pcidev_id->driver_data;
|
|
|
else
|
|
|
return NULL;
|
|
|
|
|
@@ -1311,6 +1356,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
|
|
|
if (IS_ERR(ssp->mmio_base))
|
|
|
return NULL;
|
|
|
|
|
|
+ if (pcidev_id) {
|
|
|
+ pdata->tx_param = pdev->dev.parent;
|
|
|
+ pdata->rx_param = pdev->dev.parent;
|
|
|
+ pdata->dma_filter = pxa2xx_spi_idma_filter;
|
|
|
+ }
|
|
|
+
|
|
|
ssp->clk = devm_clk_get(&pdev->dev, NULL);
|
|
|
ssp->irq = platform_get_irq(pdev, 0);
|
|
|
ssp->type = type;
|