2024-05-17 19:54:10

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 00/10] spi: pxa2xx: Get rid of an additional layer in PCI driver

SPI PXA2xx main driver is a compound of a core library and
a platform driver code. Decoupling that allows to eventually
get rid of an additional layer of devices hierarchy in PCI driver.
There are also precursor cleanups.

Andy Shevchenko (10):
spi: pxa2xx: Reorganize the SSP type retrieval
spi: pxa2xx: Remove no more needed driver data
spi: pxa2xx: Remove hard coded number of chip select pins
spi: pxa2xx: Utilise temporary variable for struct device
spi: pxa2xx: Print DMA burst size only when DMA is enabled
spi: pxa2xx: Remove duplicate check
spi: pxa2xx: Remove superflous check for Intel Atom SoCs
spi: pxa2xx: Extract pxa2xx_spi_platform_*() callbacks
spi: pxa2xx: Move platform driver to a separate file
spi: pxa2xx: Convert PCI driver to use spi-pxa2xx code directly

drivers/spi/Makefile | 3 +-
drivers/spi/spi-pxa2xx-pci.c | 39 ++---
drivers/spi/spi-pxa2xx-platform.c | 201 +++++++++++++++++++++++++
drivers/spi/spi-pxa2xx.c | 239 ++++--------------------------
drivers/spi/spi-pxa2xx.h | 6 +
5 files changed, 253 insertions(+), 235 deletions(-)
create mode 100644 drivers/spi/spi-pxa2xx-platform.c

--
2.43.0.rc1.1336.g36b5255a03ac



2024-05-17 19:54:30

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 02/10] spi: pxa2xx: Remove no more needed driver data

Since the ACPI enumerated devices provide a property with SSP type,
there is no more necessity to bear the copy of them in the ID table.
Drop the driver data in ACPI ID table.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 877fb6d01cd1..dee5513936ec 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1703,12 +1703,12 @@ static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
};

static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
- { "80860F0E", LPSS_BYT_SSP },
- { "8086228E", LPSS_BSW_SSP },
- { "INT33C0", LPSS_LPT_SSP },
- { "INT33C1", LPSS_LPT_SSP },
- { "INT3430", LPSS_LPT_SSP },
- { "INT3431", LPSS_LPT_SSP },
+ { "80860F0E" },
+ { "8086228E" },
+ { "INT33C0" },
+ { "INT33C1" },
+ { "INT3430" },
+ { "INT3431" },
{}
};
MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 19:54:34

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 03/10] spi: pxa2xx: Remove hard coded number of chip select pins

Remove hard coded number of chip select pins for Intel Braswell.
This comes via property.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 4 ----
1 file changed, 4 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index dee5513936ec..e7087228505e 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -99,7 +99,6 @@ struct lpss_config {
/* Chip select control */
unsigned cs_sel_shift;
unsigned cs_sel_mask;
- unsigned cs_num;
/* Quirks */
unsigned cs_clk_stays_gated : 1;
};
@@ -137,7 +136,6 @@ static const struct lpss_config lpss_platforms[] = {
.tx_threshold_hi = 224,
.cs_sel_shift = 2,
.cs_sel_mask = 1 << 2,
- .cs_num = 2,
},
{ /* LPSS_SPT_SSP */
.offset = 0x200,
@@ -1574,8 +1572,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
tmp &= LPSS_CAPS_CS_EN_MASK;
tmp >>= LPSS_CAPS_CS_EN_SHIFT;
platform_info->num_chipselect = ffz(tmp);
- } else if (config->cs_num) {
- platform_info->num_chipselect = config->cs_num;
}
}
controller->num_chipselect = platform_info->num_chipselect;
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 19:55:10

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 05/10] spi: pxa2xx: Print DMA burst size only when DMA is enabled

Print DMA burst size only when DMA is enabled to avoid making
a false impression that DMA is enabled when it may be not.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 56ff296925b7..6bbeb1d09ed9 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1412,7 +1412,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
if (IS_ERR(platform_info))
return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
}
- dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size);

ssp = pxa_ssp_request(pdev->id, pdev->name);
if (!ssp)
@@ -1496,6 +1495,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
controller->max_dma_len = MAX_DMA_LEN;
controller->max_transfer_size =
pxa2xx_spi_max_dma_transfer_size;
+
+ dev_dbg(dev, "DMA burst size set to %u\n", platform_info->dma_burst_size);
}
}

--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 19:55:12

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 06/10] spi: pxa2xx: Remove duplicate check

The mmio_base can't be NULL at this point. It's either checked
in both pxa_ssp_probe() and pxa2xx_spi_init_ssp() or correctly
provided by PCI core. Hence, remove duplicate check which is
a dead code.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 6bbeb1d09ed9..cd28b798b53b 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1417,9 +1417,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
if (!ssp)
ssp = &platform_info->ssp;

- if (!ssp->mmio_base)
- return dev_err_probe(dev, -ENODEV, "failed to get SSP\n");
-
if (platform_info->is_target)
controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
else
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 20:56:45

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 08/10] spi: pxa2xx: Extract pxa2xx_spi_platform_*() callbacks

In preparation of the extracting platform driver from spi-pxa2xx.c
split the probe and remove functions so we have bus independent
and platform device ones.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 63 +++++++++++++++++++++++++++-------------
1 file changed, 43 insertions(+), 20 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index 3ea4b9821a8e..f53827d61a21 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1391,28 +1391,16 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
return MAX_DMA_LEN;
}

-static int pxa2xx_spi_probe(struct platform_device *pdev)
+static int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
{
- struct device *dev = &pdev->dev;
struct pxa2xx_spi_controller *platform_info;
struct spi_controller *controller;
struct driver_data *drv_data;
- struct ssp_device *ssp;
const struct lpss_config *config;
int status;
u32 tmp;

platform_info = dev_get_platdata(dev);
- if (!platform_info) {
- platform_info = pxa2xx_spi_init_pdata(pdev);
- if (IS_ERR(platform_info))
- return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
- }
-
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (!ssp)
- ssp = &platform_info->ssp;
-
if (platform_info->is_target)
controller = devm_spi_alloc_target(dev, sizeof(*drv_data));
else
@@ -1610,9 +1598,8 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return status;
}

-static void pxa2xx_spi_remove(struct platform_device *pdev)
+static void pxa2xx_spi_remove(struct device *dev)
{
- struct device *dev = &pdev->dev;
struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;

@@ -1633,9 +1620,6 @@ static void pxa2xx_spi_remove(struct platform_device *pdev)

/* Release IRQ */
free_irq(ssp->irq, drv_data);
-
- /* Release SSP */
- pxa_ssp_free(ssp);
}

static int pxa2xx_spi_suspend(struct device *dev)
@@ -1693,6 +1677,45 @@ static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend, pxa2xx_spi_runtime_resume, NULL)
};

+static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pxa2xx_spi_controller *platform_info;
+ struct ssp_device *ssp;
+ int status;
+
+ platform_info = dev_get_platdata(dev);
+ if (!platform_info) {
+ platform_info = pxa2xx_spi_init_pdata(pdev);
+ if (IS_ERR(platform_info))
+ return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
+
+ dev->platform_data = platform_info;
+
+ }
+
+ ssp = pxa_ssp_request(pdev->id, pdev->name);
+ if (!ssp)
+ ssp = &platform_info->ssp;
+
+ status = pxa2xx_spi_probe(dev, ssp);
+ if (status)
+ pxa_ssp_free(ssp);
+
+ return status;
+}
+
+static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
+{
+ struct driver_data *drv_data = platform_get_drvdata(pdev);
+ struct ssp_device *ssp = drv_data->ssp;
+
+ pxa2xx_spi_remove(&pdev->dev);
+
+ /* Release SSP */
+ pxa_ssp_free(ssp);
+}
+
static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
{ "80860F0E" },
{ "8086228E" },
@@ -1717,8 +1740,8 @@ static struct platform_driver driver = {
.acpi_match_table = pxa2xx_spi_acpi_match,
.of_match_table = pxa2xx_spi_of_match,
},
- .probe = pxa2xx_spi_probe,
- .remove_new = pxa2xx_spi_remove,
+ .probe = pxa2xx_spi_platform_probe,
+ .remove_new = pxa2xx_spi_platform_remove,
};

static int __init pxa2xx_spi_init(void)
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 20:57:03

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 04/10] spi: pxa2xx: Utilise temporary variable for struct device

We have a temporary variable to keep a pointer to struct device.
Utilise it where it makes sense.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index e7087228505e..56ff296925b7 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1586,13 +1586,13 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
}
}

- pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
- pm_runtime_use_autosuspend(&pdev->dev);
- pm_runtime_set_active(&pdev->dev);
- pm_runtime_enable(&pdev->dev);
+ pm_runtime_set_autosuspend_delay(dev, 50);
+ pm_runtime_use_autosuspend(dev);
+ pm_runtime_set_active(dev);
+ pm_runtime_enable(dev);

/* Register with the SPI framework */
- platform_set_drvdata(pdev, drv_data);
+ dev_set_drvdata(dev, drv_data);
status = spi_register_controller(controller);
if (status) {
dev_err_probe(dev, status, "problem registering SPI controller\n");
@@ -1602,7 +1602,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
return status;

out_error_pm_runtime_enabled:
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_disable(dev);

out_error_clock_enabled:
clk_disable_unprepare(ssp->clk);
@@ -1618,10 +1618,11 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)

static void pxa2xx_spi_remove(struct platform_device *pdev)
{
- struct driver_data *drv_data = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+ struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;

- pm_runtime_get_sync(&pdev->dev);
+ pm_runtime_get_sync(dev);

spi_unregister_controller(drv_data->controller);

@@ -1633,8 +1634,8 @@ static void pxa2xx_spi_remove(struct platform_device *pdev)
if (drv_data->controller_info->enable_dma)
pxa2xx_spi_dma_release(drv_data);

- pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(dev);
+ pm_runtime_disable(dev);

/* Release IRQ */
free_irq(ssp->irq, drv_data);
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 21:07:32

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 09/10] spi: pxa2xx: Move platform driver to a separate file

The spi-pxa2xx.c is bloated with a platform driver code while
pretending to provide a core functionality. Make it real core
library by splitting out the platform driver to a separate file.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/Makefile | 3 +-
drivers/spi/spi-pxa2xx-platform.c | 201 +++++++++++++++++++++++++++++
drivers/spi/spi-pxa2xx.c | 203 ++----------------------------
drivers/spi/spi-pxa2xx.h | 6 +
4 files changed, 217 insertions(+), 196 deletions(-)
create mode 100644 drivers/spi/spi-pxa2xx-platform.c

diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile
index e694254dec04..bcfb6efd88e0 100644
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -107,7 +107,8 @@ obj-$(CONFIG_SPI_PIC32) += spi-pic32.o
obj-$(CONFIG_SPI_PIC32_SQI) += spi-pic32-sqi.o
obj-$(CONFIG_SPI_PL022) += spi-pl022.o
obj-$(CONFIG_SPI_PPC4xx) += spi-ppc4xx.o
-spi-pxa2xx-platform-objs := spi-pxa2xx.o spi-pxa2xx-dma.o
+obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-core.o
+spi-pxa2xx-core-y := spi-pxa2xx.o spi-pxa2xx-dma.o
obj-$(CONFIG_SPI_PXA2XX) += spi-pxa2xx-platform.o
obj-$(CONFIG_SPI_PXA2XX_PCI) += spi-pxa2xx-pci.o
obj-$(CONFIG_SPI_QCOM_GENI) += spi-geni-qcom.o
diff --git a/drivers/spi/spi-pxa2xx-platform.c b/drivers/spi/spi-pxa2xx-platform.c
new file mode 100644
index 000000000000..081ab31bb49d
--- /dev/null
+++ b/drivers/spi/spi-pxa2xx-platform.c
@@ -0,0 +1,201 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <linux/acpi.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/types.h>
+
+#include "spi-pxa2xx.h"
+
+static int
+pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
+{
+ struct device *dev = &pdev->dev;
+ struct resource *res;
+ int status;
+ u64 uid;
+
+ ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(ssp->mmio_base))
+ return PTR_ERR(ssp->mmio_base);
+
+ ssp->phys_base = res->start;
+
+ ssp->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(ssp->clk))
+ return PTR_ERR(ssp->clk);
+
+ ssp->irq = platform_get_irq(pdev, 0);
+ if (ssp->irq < 0)
+ return ssp->irq;
+
+ ssp->type = type;
+ ssp->dev = dev;
+
+ status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
+ if (status)
+ ssp->port_id = -1;
+ else
+ ssp->port_id = uid;
+
+ return 0;
+}
+
+static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
+{
+ return param == chan->device->dev;
+}
+
+static struct pxa2xx_spi_controller *
+pxa2xx_spi_init_pdata(struct platform_device *pdev)
+{
+ struct pxa2xx_spi_controller *pdata;
+ struct device *dev = &pdev->dev;
+ struct device *parent = dev->parent;
+ const void *match = device_get_match_data(dev);
+ enum pxa_ssp_type type = SSP_UNDEFINED;
+ struct ssp_device *ssp = NULL;
+ bool is_lpss_priv;
+ u32 num_cs = 1;
+ int status;
+
+ ssp = pxa_ssp_request(pdev->id, pdev->name);
+ if (ssp) {
+ type = ssp->type;
+ pxa_ssp_free(ssp);
+ } else if (match) {
+ type = (enum pxa_ssp_type)(uintptr_t)match;
+ } else {
+ u32 value;
+
+ status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
+ if (status)
+ return ERR_PTR(status);
+
+ type = (enum pxa_ssp_type)value;
+ }
+
+ /* Validate the SSP type correctness */
+ if (!(type > SSP_UNDEFINED && type < SSP_MAX))
+ return ERR_PTR(-EINVAL);
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return ERR_PTR(-ENOMEM);
+
+ /* Platforms with iDMA 64-bit */
+ is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
+ if (is_lpss_priv) {
+ pdata->tx_param = parent;
+ pdata->rx_param = parent;
+ pdata->dma_filter = pxa2xx_spi_idma_filter;
+ }
+
+ /* Read number of chip select pins, if provided */
+ device_property_read_u32(dev, "num-cs", &num_cs);
+
+ pdata->num_chipselect = num_cs;
+ pdata->is_target = device_property_read_bool(dev, "spi-slave");
+ pdata->enable_dma = true;
+ pdata->dma_burst_size = 1;
+
+ /* If SSP has been already enumerated, use it */
+ if (ssp)
+ return pdata;
+
+ status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
+ if (status)
+ return ERR_PTR(status);
+
+ return pdata;
+}
+
+static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct pxa2xx_spi_controller *platform_info;
+ struct ssp_device *ssp;
+ int status;
+
+ platform_info = dev_get_platdata(dev);
+ if (!platform_info) {
+ platform_info = pxa2xx_spi_init_pdata(pdev);
+ if (IS_ERR(platform_info))
+ return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
+
+ dev->platform_data = platform_info;
+
+ }
+
+ ssp = pxa_ssp_request(pdev->id, pdev->name);
+ if (!ssp)
+ ssp = &platform_info->ssp;
+
+ status = pxa2xx_spi_probe(dev, ssp);
+ if (status)
+ pxa_ssp_free(ssp);
+
+ return status;
+}
+
+static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
+{
+ struct driver_data *drv_data = platform_get_drvdata(pdev);
+ struct ssp_device *ssp = drv_data->ssp;
+
+ pxa2xx_spi_remove(&pdev->dev);
+
+ /* Release SSP */
+ pxa_ssp_free(ssp);
+}
+
+static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
+ { "80860F0E" },
+ { "8086228E" },
+ { "INT33C0" },
+ { "INT33C1" },
+ { "INT3430" },
+ { "INT3431" },
+ {}
+};
+MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
+
+static const struct of_device_id pxa2xx_spi_of_match[] = {
+ { .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
+
+static struct platform_driver driver = {
+ .driver = {
+ .name = "pxa2xx-spi",
+ .pm = pm_ptr(&pxa2xx_spi_pm_ops),
+ .acpi_match_table = pxa2xx_spi_acpi_match,
+ .of_match_table = pxa2xx_spi_of_match,
+ },
+ .probe = pxa2xx_spi_platform_probe,
+ .remove_new = pxa2xx_spi_platform_remove,
+};
+
+static int __init pxa2xx_spi_init(void)
+{
+ return platform_driver_register(&driver);
+}
+subsys_initcall(pxa2xx_spi_init);
+
+static void __exit pxa2xx_spi_exit(void)
+{
+ platform_driver_unregister(&driver);
+}
+module_exit(pxa2xx_spi_exit);
+
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Controller platform driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS(SPI_PXA2xx);
+MODULE_ALIAS("platform:pxa2xx-spi");
+MODULE_SOFTDEP("pre: dw_dmac");
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index f53827d61a21..046869ea5fb7 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -4,7 +4,6 @@
* Copyright (C) 2013, 2021 Intel Corporation
*/

-#include <linux/acpi.h>
#include <linux/atomic.h>
#include <linux/bitops.h>
#include <linux/bug.h>
@@ -14,15 +13,12 @@
#include <linux/dmaengine.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
-#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/math64.h>
#include <linux/minmax.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <linux/slab.h>
@@ -32,11 +28,6 @@

#include "spi-pxa2xx.h"

-MODULE_AUTHOR("Stephen Street");
-MODULE_DESCRIPTION("PXA2xx SSP SPI Controller");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:pxa2xx-spi");
-
#define TIMOUT_DFLT 1000

/*
@@ -1263,109 +1254,6 @@ static void cleanup(struct spi_device *spi)
kfree(chip);
}

-static bool pxa2xx_spi_idma_filter(struct dma_chan *chan, void *param)
-{
- return param == chan->device->dev;
-}
-
-static int
-pxa2xx_spi_init_ssp(struct platform_device *pdev, struct ssp_device *ssp, enum pxa_ssp_type type)
-{
- struct device *dev = &pdev->dev;
- struct resource *res;
- int status;
- u64 uid;
-
- ssp->mmio_base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(ssp->mmio_base))
- return PTR_ERR(ssp->mmio_base);
-
- ssp->phys_base = res->start;
-
- ssp->clk = devm_clk_get(dev, NULL);
- if (IS_ERR(ssp->clk))
- return PTR_ERR(ssp->clk);
-
- ssp->irq = platform_get_irq(pdev, 0);
- if (ssp->irq < 0)
- return ssp->irq;
-
- ssp->type = type;
- ssp->dev = dev;
-
- status = acpi_dev_uid_to_integer(ACPI_COMPANION(dev), &uid);
- if (status)
- ssp->port_id = -1;
- else
- ssp->port_id = uid;
-
- return 0;
-}
-
-static struct pxa2xx_spi_controller *
-pxa2xx_spi_init_pdata(struct platform_device *pdev)
-{
- struct pxa2xx_spi_controller *pdata;
- struct device *dev = &pdev->dev;
- struct device *parent = dev->parent;
- const void *match = device_get_match_data(dev);
- enum pxa_ssp_type type = SSP_UNDEFINED;
- struct ssp_device *ssp = NULL;
- bool is_lpss_priv;
- u32 num_cs = 1;
- int status;
-
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (ssp) {
- type = ssp->type;
- pxa_ssp_free(ssp);
- } else if (match) {
- type = (enum pxa_ssp_type)(uintptr_t)match;
- } else {
- u32 value;
-
- status = device_property_read_u32(dev, "intel,spi-pxa2xx-type", &value);
- if (status)
- return ERR_PTR(status);
-
- type = (enum pxa_ssp_type)value;
- }
-
- /* Validate the SSP type correctness */
- if (!(type > SSP_UNDEFINED && type < SSP_MAX))
- return ERR_PTR(-EINVAL);
-
- pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
- if (!pdata)
- return ERR_PTR(-ENOMEM);
-
- /* Platforms with iDMA 64-bit */
- is_lpss_priv = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lpss_priv");
- if (is_lpss_priv) {
- pdata->tx_param = parent;
- pdata->rx_param = parent;
- pdata->dma_filter = pxa2xx_spi_idma_filter;
- }
-
- /* Read number of chip select pins, if provided */
- device_property_read_u32(dev, "num-cs", &num_cs);
-
- pdata->num_chipselect = num_cs;
- pdata->is_target = device_property_read_bool(dev, "spi-slave");
- pdata->enable_dma = true;
- pdata->dma_burst_size = 1;
-
- /* If SSP has been already enumerated, use it */
- if (ssp)
- return pdata;
-
- status = pxa2xx_spi_init_ssp(pdev, &pdata->ssp, type);
- if (status)
- return ERR_PTR(status);
-
- return pdata;
-}
-
static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller,
unsigned int cs)
{
@@ -1391,7 +1279,7 @@ static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
return MAX_DMA_LEN;
}

-static int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
+int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
{
struct pxa2xx_spi_controller *platform_info;
struct spi_controller *controller;
@@ -1597,8 +1485,9 @@ static int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp)
pxa_ssp_free(ssp);
return status;
}
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_probe, SPI_PXA2xx);

-static void pxa2xx_spi_remove(struct device *dev)
+void pxa2xx_spi_remove(struct device *dev)
{
struct driver_data *drv_data = dev_get_drvdata(dev);
struct ssp_device *ssp = drv_data->ssp;
@@ -1621,6 +1510,7 @@ static void pxa2xx_spi_remove(struct device *dev)
/* Release IRQ */
free_irq(ssp->irq, drv_data);
}
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_remove, SPI_PXA2xx);

static int pxa2xx_spi_suspend(struct device *dev)
{
@@ -1672,88 +1562,11 @@ static int pxa2xx_spi_runtime_resume(struct device *dev)
return clk_prepare_enable(drv_data->ssp->clk);
}

-static const struct dev_pm_ops pxa2xx_spi_pm_ops = {
+EXPORT_NS_GPL_DEV_PM_OPS(pxa2xx_spi_pm_ops, SPI_PXA2xx) = {
SYSTEM_SLEEP_PM_OPS(pxa2xx_spi_suspend, pxa2xx_spi_resume)
RUNTIME_PM_OPS(pxa2xx_spi_runtime_suspend, pxa2xx_spi_runtime_resume, NULL)
};

-static int pxa2xx_spi_platform_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct pxa2xx_spi_controller *platform_info;
- struct ssp_device *ssp;
- int status;
-
- platform_info = dev_get_platdata(dev);
- if (!platform_info) {
- platform_info = pxa2xx_spi_init_pdata(pdev);
- if (IS_ERR(platform_info))
- return dev_err_probe(dev, PTR_ERR(platform_info), "missing platform data\n");
-
- dev->platform_data = platform_info;
-
- }
-
- ssp = pxa_ssp_request(pdev->id, pdev->name);
- if (!ssp)
- ssp = &platform_info->ssp;
-
- status = pxa2xx_spi_probe(dev, ssp);
- if (status)
- pxa_ssp_free(ssp);
-
- return status;
-}
-
-static void pxa2xx_spi_platform_remove(struct platform_device *pdev)
-{
- struct driver_data *drv_data = platform_get_drvdata(pdev);
- struct ssp_device *ssp = drv_data->ssp;
-
- pxa2xx_spi_remove(&pdev->dev);
-
- /* Release SSP */
- pxa_ssp_free(ssp);
-}
-
-static const struct acpi_device_id pxa2xx_spi_acpi_match[] = {
- { "80860F0E" },
- { "8086228E" },
- { "INT33C0" },
- { "INT33C1" },
- { "INT3430" },
- { "INT3431" },
- {}
-};
-MODULE_DEVICE_TABLE(acpi, pxa2xx_spi_acpi_match);
-
-static const struct of_device_id pxa2xx_spi_of_match[] = {
- { .compatible = "marvell,mmp2-ssp", .data = (void *)MMP2_SSP },
- {}
-};
-MODULE_DEVICE_TABLE(of, pxa2xx_spi_of_match);
-
-static struct platform_driver driver = {
- .driver = {
- .name = "pxa2xx-spi",
- .pm = pm_ptr(&pxa2xx_spi_pm_ops),
- .acpi_match_table = pxa2xx_spi_acpi_match,
- .of_match_table = pxa2xx_spi_of_match,
- },
- .probe = pxa2xx_spi_platform_probe,
- .remove_new = pxa2xx_spi_platform_remove,
-};
-
-static int __init pxa2xx_spi_init(void)
-{
- return platform_driver_register(&driver);
-}
-subsys_initcall(pxa2xx_spi_init);
-
-static void __exit pxa2xx_spi_exit(void)
-{
- platform_driver_unregister(&driver);
-}
-module_exit(pxa2xx_spi_exit);
-
-MODULE_SOFTDEP("pre: dw_dmac");
+MODULE_AUTHOR("Stephen Street");
+MODULE_DESCRIPTION("PXA2xx SSP SPI Controller core driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-pxa2xx.h b/drivers/spi/spi-pxa2xx.h
index 93e1e471e1c6..a470d3d634d3 100644
--- a/drivers/spi/spi-pxa2xx.h
+++ b/drivers/spi/spi-pxa2xx.h
@@ -14,6 +14,7 @@

#include <linux/pxa2xx_ssp.h>

+struct device;
struct gpio_desc;

/*
@@ -131,4 +132,9 @@ extern void pxa2xx_spi_dma_stop(struct driver_data *drv_data);
extern int pxa2xx_spi_dma_setup(struct driver_data *drv_data);
extern void pxa2xx_spi_dma_release(struct driver_data *drv_data);

+int pxa2xx_spi_probe(struct device *dev, struct ssp_device *ssp);
+void pxa2xx_spi_remove(struct device *dev);
+
+extern const struct dev_pm_ops pxa2xx_spi_pm_ops;
+
#endif /* SPI_PXA2XX_H */
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 21:07:38

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 10/10] spi: pxa2xx: Convert PCI driver to use spi-pxa2xx code directly

PCI driver has an additional device layer for enumeration.
Remove that layer and use spi-pxa2xx code directly.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx-pci.c | 39 ++++++++++++------------------------
1 file changed, 13 insertions(+), 26 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index 6d2efdb0e95f..616d032f1a89 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -10,8 +10,7 @@
#include <linux/err.h>
#include <linux/module.h>
#include <linux/pci.h>
-#include <linux/platform_device.h>
-#include <linux/property.h>
+#include <linux/pm.h>
#include <linux/sprintf.h>
#include <linux/string.h>
#include <linux/types.h>
@@ -265,10 +264,8 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
const struct pci_device_id *ent)
{
const struct pxa_spi_info *info;
- struct platform_device_info pi;
int ret;
- struct platform_device *pdev;
- struct pxa2xx_spi_controller spi_pdata;
+ struct pxa2xx_spi_controller *pdata;
struct ssp_device *ssp;

ret = pcim_enable_device(dev);
@@ -279,15 +276,17 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
if (ret)
return ret;

- memset(&spi_pdata, 0, sizeof(spi_pdata));
+ pdata = devm_kzalloc(&dev->dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;

- ssp = &spi_pdata.ssp;
+ ssp = &pdata->ssp;
ssp->dev = &dev->dev;
ssp->phys_base = pci_resource_start(dev, 0);
ssp->mmio_base = pcim_iomap_table(dev)[0];

info = (struct pxa_spi_info *)ent->driver_data;
- ret = info->setup(dev, &spi_pdata);
+ ret = info->setup(dev, pdata);
if (ret)
return ret;

@@ -298,28 +297,12 @@ static int pxa2xx_spi_pci_probe(struct pci_dev *dev,
return ret;
ssp->irq = pci_irq_vector(dev, 0);

- memset(&pi, 0, sizeof(pi));
- pi.fwnode = dev_fwnode(&dev->dev);
- pi.parent = &dev->dev;
- pi.name = "pxa2xx-spi";
- pi.id = ssp->port_id;
- pi.data = &spi_pdata;
- pi.size_data = sizeof(spi_pdata);
-
- pdev = platform_device_register_full(&pi);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
-
- pci_set_drvdata(dev, pdev);
-
- return 0;
+ return pxa2xx_spi_probe(&dev->dev, ssp);
}

static void pxa2xx_spi_pci_remove(struct pci_dev *dev)
{
- struct platform_device *pdev = pci_get_drvdata(dev);
-
- platform_device_unregister(pdev);
+ pxa2xx_spi_remove(&dev->dev);
}

static const struct pci_device_id pxa2xx_spi_pci_devices[] = {
@@ -341,6 +324,9 @@ MODULE_DEVICE_TABLE(pci, pxa2xx_spi_pci_devices);
static struct pci_driver pxa2xx_spi_pci_driver = {
.name = "pxa2xx_spi_pci",
.id_table = pxa2xx_spi_pci_devices,
+ .driver = {
+ .pm = pm_ptr(&pxa2xx_spi_pm_ops),
+ },
.probe = pxa2xx_spi_pci_probe,
.remove = pxa2xx_spi_pci_remove,
};
@@ -349,4 +335,5 @@ module_pci_driver(pxa2xx_spi_pci_driver);

MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS(SPI_PXA2xx);
MODULE_AUTHOR("Sebastian Andrzej Siewior <[email protected]>");
--
2.43.0.rc1.1336.g36b5255a03ac


2024-05-17 23:00:41

by Andy Shevchenko

[permalink] [raw]
Subject: [PATCH v1 07/10] spi: pxa2xx: Remove superflous check for Intel Atom SoCs

pxa2xx_spi_fw_translate_cs() checks for the ACPI companion device
presence along with the SSP type. But the SSP type is uniquely
determines the case. Hence remove the superflous check.

Signed-off-by: Andy Shevchenko <[email protected]>
---
drivers/spi/spi-pxa2xx.c | 26 +++++++++++---------------
1 file changed, 11 insertions(+), 15 deletions(-)

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index cd28b798b53b..3ea4b9821a8e 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1371,23 +1371,19 @@ static int pxa2xx_spi_fw_translate_cs(struct spi_controller *controller,
{
struct driver_data *drv_data = spi_controller_get_devdata(controller);

- if (has_acpi_companion(drv_data->ssp->dev)) {
- switch (drv_data->ssp_type) {
- /*
- * For Atoms the ACPI DeviceSelection used by the Windows
- * driver starts from 1 instead of 0 so translate it here
- * to match what Linux expects.
- */
- case LPSS_BYT_SSP:
- case LPSS_BSW_SSP:
- return cs - 1;
+ switch (drv_data->ssp_type) {
+ /*
+ * For some of Intel Atoms the ACPI DeviceSelection used by the Windows
+ * driver starts from 1 instead of 0 so translate it here to match what
+ * Linux expects.
+ */
+ case LPSS_BYT_SSP:
+ case LPSS_BSW_SSP:
+ return cs - 1;

- default:
- break;
- }
+ default:
+ return cs;
}
-
- return cs;
}

static size_t pxa2xx_spi_max_dma_transfer_size(struct spi_device *spi)
--
2.43.0.rc1.1336.g36b5255a03ac