aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2015-07-30 09:30:07 -0400
committerMark Brown <broonie@kernel.org>2015-07-31 14:13:33 -0400
commit34cadd9c1bcbd5ad5a1f379b013526a8046d4aed (patch)
tree94d095ade2a89eb3806610d0bb35597968f0d1f7
parent1aae50a245736aec603c319fea2a83a90dc69aba (diff)
spi: pxa2xx: Add support for Intel Sunrisepoint
Major difference in LPSS SPI between Intel Sunrisepoint PCH and earlier platforms is an integrated DMA (iDMA) engine. iDMA is an IP that is private for each LPSS host controller (UART/SPI/I2C). Other differences are private register space offset, a few private registers that are in different location and FIFO thresholds. Intel Sunrisepoint LPSS SPI and iDMA devices are probed and registered in MFD layer as platform devices. Here these compound devices are detected by matching against known PCI IDs. This allows us to share pxa2xx_spi_acpi_get_pdata() for setting up the platform data instead of duplicating it in MFD part. This patch adds configuration for Intel Sunrisepoint LPSS SPI, above detection and DMA filter function that picks the DMA channel only from an associated iDMA block. Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@kernel.org>
-rw-r--r--drivers/spi/spi-pxa2xx.c59
-rw-r--r--include/linux/pxa2xx_ssp.h1
2 files changed, 56 insertions, 4 deletions
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 7293d6d875c5..2c9fa409d2bf 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -21,6 +21,7 @@
21#include <linux/err.h> 21#include <linux/err.h>
22#include <linux/interrupt.h> 22#include <linux/interrupt.h>
23#include <linux/kernel.h> 23#include <linux/kernel.h>
24#include <linux/pci.h>
24#include <linux/platform_device.h> 25#include <linux/platform_device.h>
25#include <linux/spi/pxa2xx_spi.h> 26#include <linux/spi/pxa2xx_spi.h>
26#include <linux/spi/spi.h> 27#include <linux/spi/spi.h>
@@ -97,6 +98,15 @@ static const struct lpss_config lpss_platforms[] = {
97 .tx_threshold_lo = 160, 98 .tx_threshold_lo = 160,
98 .tx_threshold_hi = 224, 99 .tx_threshold_hi = 224,
99 }, 100 },
101 { /* LPSS_SPT_SSP */
102 .offset = 0x200,
103 .reg_general = -1,
104 .reg_ssp = 0x20,
105 .reg_cs_ctrl = 0x24,
106 .rx_threshold = 1,
107 .tx_threshold_lo = 32,
108 .tx_threshold_hi = 56,
109 },
100}; 110};
101 111
102static inline const struct lpss_config 112static inline const struct lpss_config
@@ -110,6 +120,7 @@ static bool is_lpss_ssp(const struct driver_data *drv_data)
110 switch (drv_data->ssp_type) { 120 switch (drv_data->ssp_type) {
111 case LPSS_LPT_SSP: 121 case LPSS_LPT_SSP:
112 case LPSS_BYT_SSP: 122 case LPSS_BYT_SSP:
123 case LPSS_SPT_SSP:
113 return true; 124 return true;
114 default: 125 default:
115 return false; 126 return false;
@@ -1107,6 +1118,7 @@ static int setup(struct spi_device *spi)
1107 break; 1118 break;
1108 case LPSS_LPT_SSP: 1119 case LPSS_LPT_SSP:
1109 case LPSS_BYT_SSP: 1120 case LPSS_BYT_SSP:
1121 case LPSS_SPT_SSP:
1110 config = lpss_get_config(drv_data); 1122 config = lpss_get_config(drv_data);
1111 tx_thres = config->tx_threshold_lo; 1123 tx_thres = config->tx_threshold_lo;
1112 tx_hi_thres = config->tx_threshold_hi; 1124 tx_hi_thres = config->tx_threshold_hi;
@@ -1276,6 +1288,30 @@ static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
1276}; 1288};
1277MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match); 1289MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
1278 1290
1291/*
1292 * PCI IDs of compound devices that integrate both host controller and private
1293 * integrated DMA engine. Please note these are not used in module
1294 * autoloading and probing in this module but matching the LPSS SSP type.
1295 */
1296static const struct pci_device_id pxa2xx_spi_pci_compound_match[] = {
1297 /* SPT-LP */
1298 { PCI_VDEVICE(INTEL, 0x9d29), LPSS_SPT_SSP },
1299 { PCI_VDEVICE(INTEL, 0x9d2a), LPSS_SPT_SSP },
1300 /* SPT-H */
1301 { PCI_VDEVICE(INTEL, 0xa129), LPSS_SPT_SSP },
1302 { PCI_VDEVICE(INTEL, 0xa12a), LPSS_SPT_SSP },
1303};
1304
1305static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
1306{
1307 struct device *dev = param;
1308
1309 if (dev != chan->device->dev->parent)
1310 return false;
1311
1312 return true;
1313}
1314
1279static struct pxa2xx_spi_master * 1315static struct pxa2xx_spi_master *
1280pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev) 1316pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
1281{ 1317{
@@ -1283,16 +1319,25 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
1283 struct acpi_device *adev; 1319 struct acpi_device *adev;
1284 struct ssp_device *ssp; 1320 struct ssp_device *ssp;
1285 struct resource *res; 1321 struct resource *res;
1286 const struct acpi_device_id *id; 1322 const struct acpi_device_id *adev_id = NULL;
1323 const struct pci_device_id *pcidev_id = NULL;
1287 int devid, type; 1324 int devid, type;
1288 1325
1289 if (!ACPI_HANDLE(&pdev->dev) || 1326 if (!ACPI_HANDLE(&pdev->dev) ||
1290 acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev)) 1327 acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
1291 return NULL; 1328 return NULL;
1292 1329
1293 id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev); 1330 if (dev_is_pci(pdev->dev.parent))
1294 if (id) 1331 pcidev_id = pci_match_id(pxa2xx_spi_pci_compound_match,
1295 type = (int)id->driver_data; 1332 to_pci_dev(pdev->dev.parent));
1333 else
1334 adev_id = acpi_match_device(pdev->dev.driver->acpi_match_table,
1335 &pdev->dev);
1336
1337 if (adev_id)
1338 type = (int)adev_id->driver_data;
1339 else if (pcidev_id)
1340 type = (int)pcidev_id->driver_data;
1296 else 1341 else
1297 return NULL; 1342 return NULL;
1298 1343
@@ -1311,6 +1356,12 @@ pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
1311 if (IS_ERR(ssp->mmio_base)) 1356 if (IS_ERR(ssp->mmio_base))
1312 return NULL; 1357 return NULL;
1313 1358
1359 if (pcidev_id) {
1360 pdata->tx_param = pdev->dev.parent;
1361 pdata->rx_param = pdev->dev.parent;
1362 pdata->dma_filter = pxa2xx_spi_idma_filter;
1363 }
1364
1314 ssp->clk = devm_clk_get(&pdev->dev, NULL); 1365 ssp->clk = devm_clk_get(&pdev->dev, NULL);
1315 ssp->irq = platform_get_irq(pdev, 0); 1366 ssp->irq = platform_get_irq(pdev, 0);
1316 ssp->type = type; 1367 ssp->type = type;
diff --git a/include/linux/pxa2xx_ssp.h b/include/linux/pxa2xx_ssp.h
index 0485bab061fd..92273776bce6 100644
--- a/include/linux/pxa2xx_ssp.h
+++ b/include/linux/pxa2xx_ssp.h
@@ -197,6 +197,7 @@ enum pxa_ssp_type {
197 QUARK_X1000_SSP, 197 QUARK_X1000_SSP,
198 LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */ 198 LPSS_LPT_SSP, /* Keep LPSS types sorted with lpss_platforms[] */
199 LPSS_BYT_SSP, 199 LPSS_BYT_SSP,
200 LPSS_SPT_SSP,
200}; 201};
201 202
202struct ssp_device { 203struct ssp_device {