| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * bcm2835 sdhost driver. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 25 | 26 | * sdhci-bcm2708.c by Broadcom |
|---|
| 26 | 27 | * sdhci-bcm2835.c by Stephen Warren and Oleksandr Tymoshenko |
|---|
| 27 | 28 | * sdhci.c and sdhci-pci.c by Pierre Ossman |
|---|
| 28 | | - * |
|---|
| 29 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 30 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 31 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 32 | | - * |
|---|
| 33 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 34 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 35 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 36 | | - * more details. |
|---|
| 37 | | - * |
|---|
| 38 | | - * You should have received a copy of the GNU General Public License |
|---|
| 39 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 40 | 29 | */ |
|---|
| 41 | 30 | #include <linux/clk.h> |
|---|
| 42 | 31 | #include <linux/delay.h> |
|---|
| .. | .. |
|---|
| 159 | 148 | void __iomem *ioaddr; |
|---|
| 160 | 149 | u32 phys_addr; |
|---|
| 161 | 150 | |
|---|
| 162 | | - struct mmc_host *mmc; |
|---|
| 163 | 151 | struct platform_device *pdev; |
|---|
| 164 | 152 | |
|---|
| 165 | 153 | int clock; /* Current clock speed */ |
|---|
| .. | .. |
|---|
| 464 | 452 | static |
|---|
| 465 | 453 | void bcm2835_prepare_dma(struct bcm2835_host *host, struct mmc_data *data) |
|---|
| 466 | 454 | { |
|---|
| 467 | | - int len, dir_data, dir_slave; |
|---|
| 455 | + int sg_len, dir_data, dir_slave; |
|---|
| 468 | 456 | struct dma_async_tx_descriptor *desc = NULL; |
|---|
| 469 | 457 | struct dma_chan *dma_chan; |
|---|
| 470 | 458 | |
|---|
| .. | .. |
|---|
| 510 | 498 | &host->dma_cfg_rx : |
|---|
| 511 | 499 | &host->dma_cfg_tx); |
|---|
| 512 | 500 | |
|---|
| 513 | | - len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len, |
|---|
| 514 | | - dir_data); |
|---|
| 501 | + sg_len = dma_map_sg(dma_chan->device->dev, data->sg, data->sg_len, |
|---|
| 502 | + dir_data); |
|---|
| 503 | + if (!sg_len) |
|---|
| 504 | + return; |
|---|
| 515 | 505 | |
|---|
| 516 | | - if (len > 0) { |
|---|
| 517 | | - desc = dmaengine_prep_slave_sg(dma_chan, data->sg, |
|---|
| 518 | | - len, dir_slave, |
|---|
| 519 | | - DMA_PREP_INTERRUPT | |
|---|
| 520 | | - DMA_CTRL_ACK); |
|---|
| 506 | + desc = dmaengine_prep_slave_sg(dma_chan, data->sg, sg_len, dir_slave, |
|---|
| 507 | + DMA_PREP_INTERRUPT | DMA_CTRL_ACK); |
|---|
| 508 | + |
|---|
| 509 | + if (!desc) { |
|---|
| 510 | + dma_unmap_sg(dma_chan->device->dev, data->sg, sg_len, dir_data); |
|---|
| 511 | + return; |
|---|
| 521 | 512 | } |
|---|
| 522 | 513 | |
|---|
| 523 | | - if (desc) { |
|---|
| 524 | | - desc->callback = bcm2835_dma_complete; |
|---|
| 525 | | - desc->callback_param = host; |
|---|
| 526 | | - host->dma_desc = desc; |
|---|
| 527 | | - host->dma_chan = dma_chan; |
|---|
| 528 | | - host->dma_dir = dir_data; |
|---|
| 529 | | - } |
|---|
| 514 | + desc->callback = bcm2835_dma_complete; |
|---|
| 515 | + desc->callback_param = host; |
|---|
| 516 | + host->dma_desc = desc; |
|---|
| 517 | + host->dma_chan = dma_chan; |
|---|
| 518 | + host->dma_dir = dir_data; |
|---|
| 530 | 519 | } |
|---|
| 531 | 520 | |
|---|
| 532 | 521 | static void bcm2835_start_dma(struct bcm2835_host *host) |
|---|
| .. | .. |
|---|
| 628 | 617 | "failed to terminate DMA (%d)\n", err); |
|---|
| 629 | 618 | } |
|---|
| 630 | 619 | |
|---|
| 631 | | - mmc_request_done(host->mmc, mrq); |
|---|
| 620 | + mmc_request_done(mmc_from_priv(host), mrq); |
|---|
| 632 | 621 | } |
|---|
| 633 | 622 | |
|---|
| 634 | 623 | static |
|---|
| .. | .. |
|---|
| 847 | 836 | dev_err(dev, "timeout waiting for hardware interrupt.\n"); |
|---|
| 848 | 837 | bcm2835_dumpregs(host); |
|---|
| 849 | 838 | |
|---|
| 850 | | - bcm2835_reset(host->mmc); |
|---|
| 839 | + bcm2835_reset(mmc_from_priv(host)); |
|---|
| 851 | 840 | |
|---|
| 852 | 841 | if (host->data) { |
|---|
| 853 | 842 | host->data->error = -ETIMEDOUT; |
|---|
| .. | .. |
|---|
| 1064 | 1053 | { |
|---|
| 1065 | 1054 | struct bcm2835_host *host = |
|---|
| 1066 | 1055 | container_of(work, struct bcm2835_host, dma_work); |
|---|
| 1067 | | - struct mmc_data *data = host->data; |
|---|
| 1056 | + struct mmc_data *data; |
|---|
| 1068 | 1057 | |
|---|
| 1069 | 1058 | mutex_lock(&host->mutex); |
|---|
| 1059 | + |
|---|
| 1060 | + data = host->data; |
|---|
| 1070 | 1061 | |
|---|
| 1071 | 1062 | if (host->dma_chan) { |
|---|
| 1072 | 1063 | dma_unmap_sg(host->dma_chan->device->dev, |
|---|
| .. | .. |
|---|
| 1108 | 1099 | |
|---|
| 1109 | 1100 | static void bcm2835_set_clock(struct bcm2835_host *host, unsigned int clock) |
|---|
| 1110 | 1101 | { |
|---|
| 1102 | + struct mmc_host *mmc = mmc_from_priv(host); |
|---|
| 1111 | 1103 | int div; |
|---|
| 1112 | 1104 | |
|---|
| 1113 | 1105 | /* The SDCDIV register has 11 bits, and holds (div - 2). But |
|---|
| .. | .. |
|---|
| 1151 | 1143 | div = SDCDIV_MAX_CDIV; |
|---|
| 1152 | 1144 | |
|---|
| 1153 | 1145 | clock = host->max_clk / (div + 2); |
|---|
| 1154 | | - host->mmc->actual_clock = clock; |
|---|
| 1146 | + mmc->actual_clock = clock; |
|---|
| 1155 | 1147 | |
|---|
| 1156 | 1148 | /* Calibrate some delays */ |
|---|
| 1157 | 1149 | |
|---|
| 1158 | 1150 | host->ns_per_fifo_word = (1000000000 / clock) * |
|---|
| 1159 | | - ((host->mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); |
|---|
| 1151 | + ((mmc->caps & MMC_CAP_4_BIT_DATA) ? 8 : 32); |
|---|
| 1160 | 1152 | |
|---|
| 1161 | 1153 | host->cdiv = div; |
|---|
| 1162 | 1154 | writel(host->cdiv, host->ioaddr + SDCDIV); |
|---|
| 1163 | 1155 | |
|---|
| 1164 | 1156 | /* Set the timeout to 500ms */ |
|---|
| 1165 | | - writel(host->mmc->actual_clock / 2, host->ioaddr + SDTOUT); |
|---|
| 1157 | + writel(mmc->actual_clock / 2, host->ioaddr + SDTOUT); |
|---|
| 1166 | 1158 | } |
|---|
| 1167 | 1159 | |
|---|
| 1168 | 1160 | static void bcm2835_request(struct mmc_host *mmc, struct mmc_request *mrq) |
|---|
| .. | .. |
|---|
| 1192 | 1184 | return; |
|---|
| 1193 | 1185 | } |
|---|
| 1194 | 1186 | |
|---|
| 1195 | | - if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) |
|---|
| 1196 | | - bcm2835_prepare_dma(host, mrq->data); |
|---|
| 1197 | | - |
|---|
| 1198 | 1187 | mutex_lock(&host->mutex); |
|---|
| 1199 | 1188 | |
|---|
| 1200 | 1189 | WARN_ON(host->mrq); |
|---|
| .. | .. |
|---|
| 1217 | 1206 | mutex_unlock(&host->mutex); |
|---|
| 1218 | 1207 | return; |
|---|
| 1219 | 1208 | } |
|---|
| 1209 | + |
|---|
| 1210 | + if (host->use_dma && mrq->data && (mrq->data->blocks > PIO_THRESHOLD)) |
|---|
| 1211 | + bcm2835_prepare_dma(host, mrq->data); |
|---|
| 1220 | 1212 | |
|---|
| 1221 | 1213 | host->use_sbc = !!mrq->sbc && host->mrq->data && |
|---|
| 1222 | 1214 | (host->mrq->data->flags & MMC_DATA_READ); |
|---|
| .. | .. |
|---|
| 1272 | 1264 | |
|---|
| 1273 | 1265 | static int bcm2835_add_host(struct bcm2835_host *host) |
|---|
| 1274 | 1266 | { |
|---|
| 1275 | | - struct mmc_host *mmc = host->mmc; |
|---|
| 1267 | + struct mmc_host *mmc = mmc_from_priv(host); |
|---|
| 1276 | 1268 | struct device *dev = &host->pdev->dev; |
|---|
| 1277 | 1269 | char pio_limit_string[20]; |
|---|
| 1278 | 1270 | int ret; |
|---|
| .. | .. |
|---|
| 1288 | 1280 | |
|---|
| 1289 | 1281 | /* host controller capabilities */ |
|---|
| 1290 | 1282 | mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED | |
|---|
| 1291 | | - MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_ERASE | |
|---|
| 1292 | | - MMC_CAP_CMD23; |
|---|
| 1283 | + MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_CMD23; |
|---|
| 1293 | 1284 | |
|---|
| 1294 | 1285 | spin_lock_init(&host->lock); |
|---|
| 1295 | 1286 | mutex_init(&host->mutex); |
|---|
| 1296 | 1287 | |
|---|
| 1297 | | - if (IS_ERR_OR_NULL(host->dma_chan_rxtx)) { |
|---|
| 1288 | + if (!host->dma_chan_rxtx) { |
|---|
| 1298 | 1289 | dev_warn(dev, "unable to initialise DMA channel. Falling back to PIO\n"); |
|---|
| 1299 | 1290 | host->use_dma = false; |
|---|
| 1300 | 1291 | } else { |
|---|
| .. | .. |
|---|
| 1322 | 1313 | } |
|---|
| 1323 | 1314 | |
|---|
| 1324 | 1315 | mmc->max_segs = 128; |
|---|
| 1325 | | - mmc->max_req_size = 524288; |
|---|
| 1316 | + mmc->max_req_size = min_t(size_t, 524288, dma_max_mapping_size(dev)); |
|---|
| 1326 | 1317 | mmc->max_seg_size = mmc->max_req_size; |
|---|
| 1327 | 1318 | mmc->max_blk_size = 1024; |
|---|
| 1328 | 1319 | mmc->max_blk_count = 65535; |
|---|
| .. | .. |
|---|
| 1365 | 1356 | { |
|---|
| 1366 | 1357 | struct device *dev = &pdev->dev; |
|---|
| 1367 | 1358 | struct clk *clk; |
|---|
| 1368 | | - struct resource *iomem; |
|---|
| 1369 | 1359 | struct bcm2835_host *host; |
|---|
| 1370 | 1360 | struct mmc_host *mmc; |
|---|
| 1371 | 1361 | const __be32 *regaddr_p; |
|---|
| .. | .. |
|---|
| 1378 | 1368 | |
|---|
| 1379 | 1369 | mmc->ops = &bcm2835_ops; |
|---|
| 1380 | 1370 | host = mmc_priv(mmc); |
|---|
| 1381 | | - host->mmc = mmc; |
|---|
| 1382 | 1371 | host->pdev = pdev; |
|---|
| 1383 | 1372 | spin_lock_init(&host->lock); |
|---|
| 1384 | 1373 | |
|---|
| 1385 | | - iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
|---|
| 1386 | | - host->ioaddr = devm_ioremap_resource(dev, iomem); |
|---|
| 1374 | + host->ioaddr = devm_platform_ioremap_resource(pdev, 0); |
|---|
| 1387 | 1375 | if (IS_ERR(host->ioaddr)) { |
|---|
| 1388 | 1376 | ret = PTR_ERR(host->ioaddr); |
|---|
| 1389 | 1377 | goto err; |
|---|
| .. | .. |
|---|
| 1404 | 1392 | host->dma_chan = NULL; |
|---|
| 1405 | 1393 | host->dma_desc = NULL; |
|---|
| 1406 | 1394 | |
|---|
| 1407 | | - host->dma_chan_rxtx = dma_request_slave_channel(dev, "rx-tx"); |
|---|
| 1395 | + host->dma_chan_rxtx = dma_request_chan(dev, "rx-tx"); |
|---|
| 1396 | + if (IS_ERR(host->dma_chan_rxtx)) { |
|---|
| 1397 | + ret = PTR_ERR(host->dma_chan_rxtx); |
|---|
| 1398 | + host->dma_chan_rxtx = NULL; |
|---|
| 1399 | + |
|---|
| 1400 | + if (ret == -EPROBE_DEFER) |
|---|
| 1401 | + goto err; |
|---|
| 1402 | + |
|---|
| 1403 | + /* Ignore errors to fall back to PIO mode */ |
|---|
| 1404 | + } |
|---|
| 1405 | + |
|---|
| 1408 | 1406 | |
|---|
| 1409 | 1407 | clk = devm_clk_get(dev, NULL); |
|---|
| 1410 | 1408 | if (IS_ERR(clk)) { |
|---|
| 1411 | | - ret = PTR_ERR(clk); |
|---|
| 1412 | | - if (ret != -EPROBE_DEFER) |
|---|
| 1413 | | - dev_err(dev, "could not get clk: %d\n", ret); |
|---|
| 1409 | + ret = dev_err_probe(dev, PTR_ERR(clk), "could not get clk\n"); |
|---|
| 1414 | 1410 | goto err; |
|---|
| 1415 | 1411 | } |
|---|
| 1416 | 1412 | |
|---|
| .. | .. |
|---|
| 1418 | 1414 | |
|---|
| 1419 | 1415 | host->irq = platform_get_irq(pdev, 0); |
|---|
| 1420 | 1416 | if (host->irq <= 0) { |
|---|
| 1421 | | - dev_err(dev, "get IRQ failed\n"); |
|---|
| 1422 | 1417 | ret = -EINVAL; |
|---|
| 1423 | 1418 | goto err; |
|---|
| 1424 | 1419 | } |
|---|
| .. | .. |
|---|
| 1449 | 1444 | static int bcm2835_remove(struct platform_device *pdev) |
|---|
| 1450 | 1445 | { |
|---|
| 1451 | 1446 | struct bcm2835_host *host = platform_get_drvdata(pdev); |
|---|
| 1447 | + struct mmc_host *mmc = mmc_from_priv(host); |
|---|
| 1452 | 1448 | |
|---|
| 1453 | | - mmc_remove_host(host->mmc); |
|---|
| 1449 | + mmc_remove_host(mmc); |
|---|
| 1454 | 1450 | |
|---|
| 1455 | 1451 | writel(SDVDD_POWER_OFF, host->ioaddr + SDVDD); |
|---|
| 1456 | 1452 | |
|---|
| .. | .. |
|---|
| 1459 | 1455 | cancel_work_sync(&host->dma_work); |
|---|
| 1460 | 1456 | cancel_delayed_work_sync(&host->timeout_work); |
|---|
| 1461 | 1457 | |
|---|
| 1462 | | - mmc_free_host(host->mmc); |
|---|
| 1463 | | - platform_set_drvdata(pdev, NULL); |
|---|
| 1458 | + if (host->dma_chan_rxtx) |
|---|
| 1459 | + dma_release_channel(host->dma_chan_rxtx); |
|---|
| 1460 | + |
|---|
| 1461 | + mmc_free_host(mmc); |
|---|
| 1464 | 1462 | |
|---|
| 1465 | 1463 | return 0; |
|---|
| 1466 | 1464 | } |
|---|
| .. | .. |
|---|
| 1476 | 1474 | .remove = bcm2835_remove, |
|---|
| 1477 | 1475 | .driver = { |
|---|
| 1478 | 1476 | .name = "sdhost-bcm2835", |
|---|
| 1477 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
|---|
| 1479 | 1478 | .of_match_table = bcm2835_match, |
|---|
| 1480 | 1479 | }, |
|---|
| 1481 | 1480 | }; |
|---|