aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/spi')
-rw-r--r--drivers/spi/Kconfig2
-rw-r--r--drivers/spi/spi-pxa2xx.c110
2 files changed, 109 insertions, 3 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 8913d3dd5724..e79884e997ae 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -310,7 +310,7 @@ config SPI_PXA2XX_DMA
310 310
311config SPI_PXA2XX 311config SPI_PXA2XX
312 tristate "PXA2xx SSP SPI master" 312 tristate "PXA2xx SSP SPI master"
313 depends on ARCH_PXA || PCI 313 depends on ARCH_PXA || PCI || ACPI
314 select PXA_SSP if ARCH_PXA 314 select PXA_SSP if ARCH_PXA
315 help 315 help
316 This enables using a PXA2xx or Sodaville SSP port as a SPI master 316 This enables using a PXA2xx or Sodaville SSP port as a SPI master
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 4bd6b729f710..90b27a3508a6 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -32,6 +32,7 @@
32#include <linux/slab.h> 32#include <linux/slab.h>
33#include <linux/clk.h> 33#include <linux/clk.h>
34#include <linux/pm_runtime.h> 34#include <linux/pm_runtime.h>
35#include <linux/acpi.h>
35 36
36#include <asm/io.h> 37#include <asm/io.h>
37#include <asm/irq.h> 38#include <asm/irq.h>
@@ -933,6 +934,13 @@ static int setup(struct spi_device *spi)
933 chip->dma_threshold = 0; 934 chip->dma_threshold = 0;
934 if (chip_info->enable_loopback) 935 if (chip_info->enable_loopback)
935 chip->cr1 = SSCR1_LBM; 936 chip->cr1 = SSCR1_LBM;
937 } else if (ACPI_HANDLE(&spi->dev)) {
938 /*
939 * Slave devices enumerated from ACPI namespace don't
940 * usually have chip_info but we still might want to use
941 * DMA with them.
942 */
943 chip->enable_dma = drv_data->master_info->enable_dma;
936 } 944 }
937 945
938 chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) | 946 chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
@@ -1025,6 +1033,99 @@ static void cleanup(struct spi_device *spi)
1025 kfree(chip); 1033 kfree(chip);
1026} 1034}
1027 1035
1036#ifdef CONFIG_ACPI
1037static int pxa2xx_spi_acpi_add_dma(struct acpi_resource *res, void *data)
1038{
1039 struct pxa2xx_spi_master *pdata = data;
1040
1041 if (res->type == ACPI_RESOURCE_TYPE_FIXED_DMA) {
1042 const struct acpi_resource_fixed_dma *dma;
1043
1044 dma = &res->data.fixed_dma;
1045 if (pdata->tx_slave_id < 0) {
1046 pdata->tx_slave_id = dma->request_lines;
1047 pdata->tx_chan_id = dma->channels;
1048 } else if (pdata->rx_slave_id < 0) {
1049 pdata->rx_slave_id = dma->request_lines;
1050 pdata->rx_chan_id = dma->channels;
1051 }
1052 }
1053
1054 /* Tell the ACPI core to skip this resource */
1055 return 1;
1056}
1057
1058static struct pxa2xx_spi_master *
1059pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
1060{
1061 struct pxa2xx_spi_master *pdata;
1062 struct list_head resource_list;
1063 struct acpi_device *adev;
1064 struct ssp_device *ssp;
1065 struct resource *res;
1066 int devid;
1067
1068 if (!ACPI_HANDLE(&pdev->dev) ||
1069 acpi_bus_get_device(ACPI_HANDLE(&pdev->dev), &adev))
1070 return NULL;
1071
1072 pdata = devm_kzalloc(&pdev->dev, sizeof(*ssp), GFP_KERNEL);
1073 if (!pdata) {
1074 dev_err(&pdev->dev,
1075 "failed to allocate memory for platform data\n");
1076 return NULL;
1077 }
1078
1079 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1080 if (!res)
1081 return NULL;
1082
1083 ssp = &pdata->ssp;
1084
1085 ssp->phys_base = res->start;
1086 ssp->mmio_base = devm_request_and_ioremap(&pdev->dev, res);
1087 if (!ssp->mmio_base) {
1088 dev_err(&pdev->dev, "failed to ioremap mmio_base\n");
1089 return NULL;
1090 }
1091
1092 ssp->clk = devm_clk_get(&pdev->dev, NULL);
1093 ssp->irq = platform_get_irq(pdev, 0);
1094 ssp->type = LPSS_SSP;
1095 ssp->pdev = pdev;
1096
1097 ssp->port_id = -1;
1098 if (adev->pnp.unique_id && !kstrtoint(adev->pnp.unique_id, 0, &devid))
1099 ssp->port_id = devid;
1100
1101 pdata->num_chipselect = 1;
1102 pdata->rx_slave_id = -1;
1103 pdata->tx_slave_id = -1;
1104
1105 INIT_LIST_HEAD(&resource_list);
1106 acpi_dev_get_resources(adev, &resource_list, pxa2xx_spi_acpi_add_dma,
1107 pdata);
1108 acpi_dev_free_resource_list(&resource_list);
1109
1110 pdata->enable_dma = pdata->rx_slave_id >= 0 && pdata->tx_slave_id >= 0;
1111
1112 return pdata;
1113}
1114
1115static struct acpi_device_id pxa2xx_spi_acpi_match[] = {
1116 { "INT33C0", 0 },
1117 { "INT33C1", 0 },
1118 { },
1119};
1120MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
1121#else
1122static inline struct pxa2xx_spi_master *
1123pxa2xx_spi_acpi_get_pdata(struct platform_device *pdev)
1124{
1125 return NULL;
1126}
1127#endif
1128
1028static int pxa2xx_spi_probe(struct platform_device *pdev) 1129static int pxa2xx_spi_probe(struct platform_device *pdev)
1029{ 1130{
1030 struct device *dev = &pdev->dev; 1131 struct device *dev = &pdev->dev;
@@ -1036,8 +1137,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1036 1137
1037 platform_info = dev_get_platdata(dev); 1138 platform_info = dev_get_platdata(dev);
1038 if (!platform_info) { 1139 if (!platform_info) {
1039 dev_err(&pdev->dev, "missing platform data\n"); 1140 platform_info = pxa2xx_spi_acpi_get_pdata(pdev);
1040 return -ENODEV; 1141 if (!platform_info) {
1142 dev_err(&pdev->dev, "missing platform data\n");
1143 return -ENODEV;
1144 }
1041 } 1145 }
1042 1146
1043 ssp = pxa_ssp_request(pdev->id, pdev->name); 1147 ssp = pxa_ssp_request(pdev->id, pdev->name);
@@ -1064,6 +1168,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
1064 1168
1065 master->dev.parent = &pdev->dev; 1169 master->dev.parent = &pdev->dev;
1066 master->dev.of_node = pdev->dev.of_node; 1170 master->dev.of_node = pdev->dev.of_node;
1171 ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
1067 /* the spi->mode bits understood by this driver: */ 1172 /* the spi->mode bits understood by this driver: */
1068 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP; 1173 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
1069 1174
@@ -1272,6 +1377,7 @@ static struct platform_driver driver = {
1272 .name = "pxa2xx-spi", 1377 .name = "pxa2xx-spi",
1273 .owner = THIS_MODULE, 1378 .owner = THIS_MODULE,
1274 .pm = &pxa2xx_spi_pm_ops, 1379 .pm = &pxa2xx_spi_pm_ops,
1380 .acpi_match_table = ACPI_PTR(pxa2xx_spi_acpi_match),
1275 }, 1381 },
1276 .probe = pxa2xx_spi_probe, 1382 .probe = pxa2xx_spi_probe,
1277 .remove = pxa2xx_spi_remove, 1383 .remove = pxa2xx_spi_remove,