openwrt/target/linux/starfive/patches-6.6/0103-spi-pl022-starfive-fix-the-problem-of-spi-overlay-re.patch
Zoltan HERPAI e2e2fc3cd0 starfive: add patches for 6.6
Add updated patches for 6.6. DMA/cache-handling patches
have been reworked / backported from upstream.

Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
2024-09-03 00:03:19 +02:00

404 lines
11 KiB
Diff

From 733e7bd23a1efad15a724fbdbce8d9f06aa6813a Mon Sep 17 00:00:00 2001
From: "ziv.xu" <ziv.xu@starfive.com>
Date: Wed, 23 Nov 2022 14:53:58 +0800
Subject: [PATCH 103/116] spi-pl022-starfive:fix the problem of spi overlay
reload
fix the problem of spi overlay reload
Signed-off-by: ziv.xu <ziv.xu@starfive.com>
Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
---
drivers/spi/spi-pl022.c | 270 ++++++++++++++++++++++++++++------------
1 file changed, 188 insertions(+), 82 deletions(-)
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -2106,6 +2106,172 @@ pl022_platform_data_dt_get(struct device
return pd;
}
+static int pl022_platform_probe(struct platform_device *pdev, const struct amba_id *id)
+{
+ struct device *dev = &pdev->dev;
+ struct spi_controller *host;
+ struct pl022_ssp_controller *platform_info;
+ struct amba_device *adev;
+ struct pl022 *pl022 = NULL;
+ struct resource *res;
+ int status = 0;
+ int irq;
+
+ dev_info(dev,
+ "ARM PL022 driver for StarFive SoC platform, device ID: 0x%08x\n",
+ id->id);
+
+ adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
+ adev->dev = pdev->dev;
+ platform_info = pl022_platform_data_dt_get(dev);
+ if (!platform_info) {
+ dev_err(dev, "probe: no platform data defined\n");
+ return -ENODEV;
+ }
+ /* Allocate host with space for data */
+ host = spi_alloc_host(dev, sizeof(struct pl022));
+ if (host == NULL) {
+ dev_err(dev, "probe - cannot alloc SPI host\n");
+ return -ENOMEM;
+ }
+
+ pl022 = spi_controller_get_devdata(host);
+ pl022->host = host;
+ pl022->host_info = platform_info;
+ pl022->adev = adev;
+ pl022->vendor = id->data;
+ pl022->host->dev.parent = &pdev->dev;
+ /*
+ * Bus Number Which has been Assigned to this SSP controller
+ * on this board
+ */
+ host->bus_num = platform_info->bus_id;
+ host->cleanup = pl022_cleanup;
+ host->setup = pl022_setup;
+ /* If open CONFIG_PM, auto_runtime_pm should be false when of-platform.*/
+ host->auto_runtime_pm = true;
+ host->transfer_one_message = pl022_transfer_one_message;
+ host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
+ host->rt = platform_info->rt;
+ host->dev.of_node = dev->of_node;
+ host->use_gpio_descriptors = true;
+
+ /*
+ * Supports mode 0-3, loopback, and active low CS. Transfers are
+ * always MS bit first on the original pl022.
+ */
+ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
+ if (pl022->vendor->extended_cr)
+ host->mode_bits |= SPI_LSB_FIRST;
+
+ dev_dbg(dev, "BUSNO: %d\n", host->bus_num);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ pl022->phybase = res->start;
+ pl022->virtbase = devm_ioremap_resource(dev, res);
+ if (pl022->virtbase == NULL) {
+ status = -ENOMEM;
+ goto err_no_ioremap;
+ }
+ dev_info(dev, "mapped registers from %llx to %llx\n",
+ pdev->resource->start, pdev->resource->end);
+
+ pl022->clk = devm_clk_get(dev, NULL);
+ if (IS_ERR(pl022->clk)) {
+ status = PTR_ERR(pl022->clk);
+ dev_err(dev, "could not retrieve SSP/SPI bus clock\n");
+ goto err_no_clk;
+ }
+ status = clk_prepare_enable(pl022->clk);
+ if (status) {
+ dev_err(dev, "could not enable SSP/SPI bus clock\n");
+ goto err_no_clk_en;
+ }
+
+ pl022->rst = devm_reset_control_get_exclusive(dev, NULL);
+ if (!IS_ERR(pl022->rst)) {
+ status = reset_control_deassert(pl022->rst);
+ if (status) {
+ dev_err(dev, "could not deassert SSP/SPI bus reset\n");
+ goto err_no_rst_clr;
+ }
+ } else {
+ status = PTR_ERR(pl022->rst);
+ dev_err(dev, "could not retrieve SSP/SPI bus reset\n");
+ goto err_no_rst;
+ }
+
+ /* Initialize transfer pump */
+ tasklet_init(&pl022->pump_transfers, pump_transfers,
+ (unsigned long)pl022);
+
+ /* Disable SSP */
+ writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
+ SSP_CR1(pl022->virtbase));
+ load_ssp_default_config(pl022);
+
+ /* Obtain IRQ line. */
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ status = -ENXIO;
+ goto err_no_irq;
+ }
+ status = devm_request_irq(dev, irq, pl022_interrupt_handler,
+ 0, "pl022", pl022);
+ if (status < 0) {
+ dev_err(dev, "probe - cannot get IRQ (%d)\n", status);
+ goto err_no_irq;
+ }
+
+ /* Get DMA channels, try autoconfiguration first */
+ status = pl022_dma_autoprobe(pl022);
+ if (status == -EPROBE_DEFER) {
+ dev_dbg(dev, "deferring probe to get DMA channel\n");
+ goto err_no_irq;
+ }
+
+ /* dma is not used unless configured in the device tree */
+ platform_info->enable_dma = 0;
+
+ /* If that failed, use channels from platform_info */
+ if (status == 0)
+ platform_info->enable_dma = 1;
+ else if (platform_info->enable_dma) {
+ status = pl022_dma_probe(pl022);
+ if (status != 0)
+ platform_info->enable_dma = 0;
+ }
+
+ /* Register with the SPI framework */
+ dev_set_drvdata(dev, pl022);
+
+ status = devm_spi_register_controller(dev, host);
+ if (status != 0) {
+ dev_err(dev,
+ "probe - problem registering spi host\n");
+ goto err_spi_register;
+ }
+ dev_dbg(dev, "probe succeeded\n");
+
+ clk_disable_unprepare(pl022->clk);
+
+ return 0;
+ err_spi_register:
+ if (platform_info->enable_dma)
+ pl022_dma_remove(pl022);
+ err_no_irq:
+ reset_control_assert(pl022->rst);
+ err_no_rst_clr:
+ err_no_rst:
+ clk_disable_unprepare(pl022->clk);
+ err_no_clk_en:
+ err_no_clk:
+ err_no_ioremap:
+ release_mem_region(pdev->resource->start, resource_size(pdev->resource));
+ spi_controller_put(host);
+ return status;
+}
+
static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
{
struct device *dev = &adev->dev;
@@ -2114,14 +2280,6 @@ static int pl022_probe(struct amba_devic
struct spi_controller *host;
struct pl022 *pl022 = NULL; /*Data for this driver */
int status = 0;
- int platform_flag = 0;
-
- if (strncmp(dev->bus->name, "platform", strlen("platform")))
- platform_flag = 0;
- else
- platform_flag = 1;
- dev_dbg(&adev->dev, "bus name:%s platform flag:%d",
- dev->bus->name, platform_flag);
dev_info(&adev->dev,
"ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
@@ -2175,11 +2333,7 @@ static int pl022_probe(struct amba_devic
goto err_no_ioregion;
pl022->phybase = adev->res.start;
- if (platform_flag)
- pl022->virtbase = ioremap(adev->res.start,
- resource_size(&adev->res));
- else
- pl022->virtbase = devm_ioremap(dev, adev->res.start,
+ pl022->virtbase = devm_ioremap(dev, adev->res.start,
resource_size(&adev->res));
if (pl022->virtbase == NULL) {
status = -ENOMEM;
@@ -2188,10 +2342,7 @@ static int pl022_probe(struct amba_devic
dev_info(&adev->dev, "mapped registers from %pa to %p\n",
&adev->res.start, pl022->virtbase);
- if (platform_flag)
- pl022->clk = clk_get(&adev->dev, NULL);
- else
- pl022->clk = devm_clk_get(&adev->dev, NULL);
+ pl022->clk = devm_clk_get(&adev->dev, NULL);
if (IS_ERR(pl022->clk)) {
status = PTR_ERR(pl022->clk);
dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
@@ -2204,10 +2355,7 @@ static int pl022_probe(struct amba_devic
goto err_no_clk_en;
}
- if (platform_flag)
- pl022->rst = reset_control_get_exclusive(&adev->dev, NULL);
- else
- pl022->rst = devm_reset_control_get(&adev->dev, NULL);
+ pl022->rst = devm_reset_control_get(&adev->dev, NULL);
if (IS_ERR(pl022->rst)) {
status = PTR_ERR(pl022->rst);
dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
@@ -2229,11 +2377,7 @@ static int pl022_probe(struct amba_devic
SSP_CR1(pl022->virtbase));
load_ssp_default_config(pl022);
- if (platform_flag)
- status = request_irq(adev->irq[0], pl022_interrupt_handler,
- 0, "pl022", pl022);
- else
- status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
+ status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
0, "pl022", pl022);
if (status < 0) {
dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
@@ -2258,18 +2402,16 @@ static int pl022_probe(struct amba_devic
/* Register with the SPI framework */
amba_set_drvdata(adev, pl022);
- if (platform_flag)
- status = spi_register_controller(host);
- else
- status = devm_spi_register_controller(&adev->dev, host);
+
+ status = devm_spi_register_controller(&adev->dev, host);
if (status != 0) {
dev_err_probe(&adev->dev, status,
"problem registering spi host\n");
goto err_spi_register;
}
dev_dbg(dev, "probe succeeded\n");
- if (!platform_flag)
- platform_info->autosuspend_delay = 100;
+
+ platform_info->autosuspend_delay = 100;
/* let runtime pm put suspend */
if (platform_info->autosuspend_delay > 0) {
dev_info(&adev->dev,
@@ -2279,10 +2421,8 @@ static int pl022_probe(struct amba_devic
platform_info->autosuspend_delay);
pm_runtime_use_autosuspend(dev);
}
- if (platform_flag)
- clk_disable_unprepare(pl022->clk);
- else
- pm_runtime_put(dev);
+
+ pm_runtime_put(dev);
return 0;
@@ -2290,26 +2430,17 @@ static int pl022_probe(struct amba_devic
if (platform_info->enable_dma)
pl022_dma_remove(pl022);
err_no_irq:
- if (platform_flag)
- free_irq(adev->irq[0], pl022);
reset_control_assert(pl022->rst);
err_no_rst_de:
- if (platform_flag)
- reset_control_put(pl022->rst);
err_no_rst:
clk_disable_unprepare(pl022->clk);
err_no_clk_en:
- if (platform_flag)
- clk_put(pl022->clk);
err_no_clk:
- if (platform_flag)
- iounmap(pl022->virtbase);
err_no_ioremap:
amba_release_regions(adev);
err_no_ioregion:
spi_controller_put(host);
- if (platform_flag)
- kfree(platform_info);
+
return status;
}
@@ -2523,23 +2654,8 @@ static int starfive_of_pl022_probe(struc
.mask = 0x000fffff,
.data = &vendor_arm
};
- struct amba_device *pcdev;
struct device *dev = &pdev->dev;
- pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
- if (!pcdev)
- return -ENOMEM;
-
- pcdev->dev = pdev->dev;
- pcdev->periphid = id.id;
- pcdev->res = *(pdev->resource);
-
- pcdev->irq[0] = platform_get_irq(pdev, 0);
- if (pcdev->irq[0] < 0) {
- dev_err(dev, "failed to get irq\n");
- ret = -EINVAL;
- }
-
ret = of_clk_set_defaults(dev->of_node, false);
if (ret < 0)
goto err_probe;
@@ -2548,16 +2664,11 @@ static int starfive_of_pl022_probe(struc
if (ret)
goto err_probe;
- ret = pl022_probe(pcdev, &id);
+ ret = pl022_platform_probe(pdev, &id);
- struct pl022 *pl022 = amba_get_drvdata(pcdev);
-
- pl022->host->dev.parent = &pdev->dev;
- platform_set_drvdata(pdev, pl022);
-
- pm_runtime_enable(&pdev->dev);
- pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
- pm_runtime_use_autosuspend(&pdev->dev);
+ pm_runtime_enable(dev);
+ pm_runtime_set_autosuspend_delay(dev, 100);
+ pm_runtime_use_autosuspend(dev);
if (ret) {
pm_runtime_disable(dev);
@@ -2572,32 +2683,27 @@ err_probe:
static int starfive_of_pl022_remove(struct platform_device *pdev)
{
- u32 size;
- int irq;
struct pl022 *pl022 = dev_get_drvdata(&pdev->dev);
if (!pl022)
return 0;
+ pm_runtime_get_sync(&pdev->dev);
pm_runtime_get_noresume(&pdev->dev);
load_ssp_default_config(pl022);
if (pl022->host_info->enable_dma)
pl022_dma_remove(pl022);
- irq = platform_get_irq(pdev, 0);
- free_irq(irq, pl022);
- reset_control_assert(pl022->rst);
- reset_control_put(pl022->rst);
clk_disable_unprepare(pl022->clk);
- clk_put(pl022->clk);
- iounmap(pl022->virtbase);
- kfree(pl022->host_info);
-
- size = resource_size(pdev->resource);
- release_mem_region(pdev->resource->start, size);
tasklet_disable(&pl022->pump_transfers);
+
+ pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
+ pm_runtime_set_suspended(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+ dev_pm_domain_detach(&pdev->dev, true);
+
return 0;
}