From 50a212ec906f7524620675f0c57357691c26c81f Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Wed, 16 Oct 2024 01:20:19 +0000
Subject: [PATCH] 修改GPIO导出默认初始值
---
kernel/drivers/mmc/host/bcm2835.c | 111 +++++++++++++++++++++++++++----------------------------
1 files changed, 55 insertions(+), 56 deletions(-)
diff --git a/kernel/drivers/mmc/host/bcm2835.c b/kernel/drivers/mmc/host/bcm2835.c
index 5301302..9850799 100644
--- a/kernel/drivers/mmc/host/bcm2835.c
+++ b/kernel/drivers/mmc/host/bcm2835.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0
/*
* bcm2835 sdhost driver.
*
@@ -25,18 +26,6 @@
* sdhci-bcm2708.c by Broadcom
* sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko
* sdhci.c and sdhci-pci.c by Pierre Ossman
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <linux/clk.h>
#include <linux/delay.h>
@@ -159,7 +148,6 @@
void __iomem *ioaddr;
u32 phys_addr;
- struct mmc_host *mmc;
struct platform_device *pdev;
int clock; /* Current clock speed */
@@ -464,7 +452,7 @@
static
void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data)
{
- int len, dir_data, dir_slave;
+ int sg_len, dir_data, dir_slave;
struct dma_async_tx_descriptor *desc = NULL;
struct dma_chan *dma_chan;
@@ -510,23 +498,24 @@
&host->dma_cfg_rx :
&host->dma_cfg_tx);
- len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len,
- dir_data);
+ sg_len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len,
+ dir_data);
+ if (!sg_len)
+ return;
- if (len > 0) {
- desc = dmaengine_prep_slave_sg(dma_chan, data->sg,
- len, dir_slave,
- DMA_PREP_INTERRUPT |
- DMA_CTRL_ACK);
+ desc = dmaengine_prep_slave_sg(dma_chan, data->sg, sg_len, dir_slave,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+ if (!desc) {
+ dma_unmap_sg(dma_chan->device->dev, data->sg, sg_len, dir_data);
+ return;
}
- if (desc) {
- desc->callback = bcm2835_dma_complete;
- desc->callback_param = host;
- host->dma_desc = desc;
- host->dma_chan = dma_chan;
- host->dma_dir = dir_data;
- }
+ desc->callback = bcm2835_dma_complete;
+ desc->callback_param = host;
+ host->dma_desc = desc;
+ host->dma_chan = dma_chan;
+ host->dma_dir = dir_data;
}
static void bcm2835_start_dma(struct bcm2835_host *host)
@@ -628,7 +617,7 @@
"failed to terminate DMA (%d)\n", err);
}
- mmc_request_done(host->mmc, mrq);
+ mmc_request_done(mmc_from_priv(host), mrq);
}
static
@@ -847,7 +836,7 @@
dev_err(dev, "timeout waiting for hardware interrupt.\n");
bcm2835_dumpregs(host);
- bcm2835_reset(host->mmc);
+ bcm2835_reset(mmc_from_priv(host));
if (host->data) {
host->data->error = -ETIMEDOUT;
@@ -1064,9 +1053,11 @@
{
struct bcm2835_host *host =
container_of(work, struct bcm2835_host, dma_work);
- struct mmc_data *data = host->data;
+ struct mmc_data *data;
mutex_lock(&host->mutex);
+
+ data = host->data;
if (host->dma_chan) {
dma_unmap_sg(host->dma_chan->device->dev,
@@ -1108,6 +1099,7 @@
static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock)
{
+ struct mmc_host *mmc = mmc_from_priv(host);
int div;
/* The SDCDIV register has 11 bits, and holds (div - 2). But
@@ -1151,18 +1143,18 @@
div = SDCDIV_MAX_CDIV;
clock = host->max_clk / (div + 2);
- host->mmc->actual_clock = clock;
+ mmc->actual_clock = clock;
/* Calibrate some delays */
host->ns_per_fifo_word = (1000000000 / clock) *
- ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
+ ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32);
host->cdiv = div;
writel(host->cdiv, host->ioaddr + SDCDIV);
/* Set the timeout to 500ms */
- writel(host->mmc->actual_clock / 2, host->ioaddr + SDTOUT);
+ writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT);
}
static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq)
@@ -1192,9 +1184,6 @@
return;
}
- if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
- bcm2835_prepare_dma(host, mrq->data);
-
mutex_lock(&host->mutex);
WARN_ON(host->mrq);
@@ -1217,6 +1206,9 @@
mutex_unlock(&host->mutex);
return;
}
+
+ if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD))
+ bcm2835_prepare_dma(host, mrq->data);
host->use_sbc = !!mrq->sbc && host->mrq->data &&
(host->mrq->data->flags & MMC_DATA_READ);
@@ -1272,7 +1264,7 @@
static int bcm2835_add_host(struct bcm2835_host *host)
{
- struct mmc_host *mmc = host->mmc;
+ struct mmc_host *mmc = mmc_from_priv(host);
struct device *dev = &host->pdev->dev;
char pio_limit_string[20];
int ret;
@@ -1288,13 +1280,12 @@
/* host controller capabilities */
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
- MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_ERASE |
- MMC_CAP_CMD23;
+ MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_CMD23;
spin_lock_init(&host->lock);
mutex_init(&host->mutex);
- if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) {
+ if (!host->dma_chan_rxtx) {
dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n");
host->use_dma = false;
} else {
@@ -1322,7 +1313,7 @@
}
mmc->max_segs = 128;
- mmc->max_req_size = 524288;
+ mmc->max_req_size = min_t(size_t, 524288, dma_max_mapping_size(dev));
mmc->max_seg_size = mmc->max_req_size;
mmc->max_blk_size = 1024;
mmc->max_blk_count = 65535;
@@ -1365,7 +1356,6 @@
{
struct device *dev = &pdev->dev;
struct clk *clk;
- struct resource *iomem;
struct bcm2835_host *host;
struct mmc_host *mmc;
const __be32 *regaddr_p;
@@ -1378,12 +1368,10 @@
mmc->ops = &bcm2835_ops;
host = mmc_priv(mmc);
- host->mmc = mmc;
host->pdev = pdev;
spin_lock_init(&host->lock);
- iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- host->ioaddr = devm_ioremap_resource(dev, iomem);
+ host->ioaddr = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(host->ioaddr)) {
ret = PTR_ERR(host->ioaddr);
goto err;
@@ -1404,22 +1392,29 @@
host->dma_chan = NULL;
host->dma_desc = NULL;
- host->dma_chan_rxtx = dma_request_slave_channel(dev, "rx-tx");
+ host->dma_chan_rxtx = dma_request_chan(dev, "rx-tx");
+ if (IS_ERR(host->dma_chan_rxtx)) {
+ ret = PTR_ERR(host->dma_chan_rxtx);
+ host->dma_chan_rxtx = NULL;
+
+ if (ret == -EPROBE_DEFER)
+ goto err;
+
+ /* Ignore errors to fall back to PIO mode */
+ }
+
clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "could not get clk: %d\n", ret);
+ ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n");
goto err;
}
host->max_clk = clk_get_rate(clk);
host->irq = platform_get_irq(pdev, 0);
- if (host->irq <= 0) {
- dev_err(dev, "get IRQ failed\n");
- ret = -EINVAL;
+ if (host->irq < 0) {
+ ret = host->irq;
goto err;
}
@@ -1449,8 +1444,9 @@
static int bcm2835_remove(struct platform_device *pdev)
{
struct bcm2835_host *host = platform_get_drvdata(pdev);
+ struct mmc_host *mmc = mmc_from_priv(host);
- mmc_remove_host(host->mmc);
+ mmc_remove_host(mmc);
writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD);
@@ -1459,8 +1455,10 @@
cancel_work_sync(&host->dma_work);
cancel_delayed_work_sync(&host->timeout_work);
- mmc_free_host(host->mmc);
- platform_set_drvdata(pdev, NULL);
+ if (host->dma_chan_rxtx)
+ dma_release_channel(host->dma_chan_rxtx);
+
+ mmc_free_host(mmc);
return 0;
}
@@ -1476,6 +1474,7 @@
.remove = bcm2835_remove,
.driver = {
.name = "sdhost-bcm2835",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
.of_match_table = bcm2835_match,
},
};
--
Gitblit v1.6.2