| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 5 | 6 | * |
|---|
| 6 | 7 | * Current driver maintained by Ben Dooks and Simtec Electronics |
|---|
| 7 | 8 | * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org> |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 10 | | - * it under the terms of the GNU General Public License version 2 as |
|---|
| 11 | | - * published by the Free Software Foundation. |
|---|
| 12 | 9 | */ |
|---|
| 13 | 10 | |
|---|
| 14 | 11 | #include <linux/module.h> |
|---|
| .. | .. |
|---|
| 26 | 23 | #include <linux/io.h> |
|---|
| 27 | 24 | #include <linux/of.h> |
|---|
| 28 | 25 | #include <linux/of_device.h> |
|---|
| 29 | | -#include <linux/of_gpio.h> |
|---|
| 30 | 26 | #include <linux/mmc/slot-gpio.h> |
|---|
| 31 | | - |
|---|
| 32 | | -#include <plat/gpio-cfg.h> |
|---|
| 33 | | -#include <mach/dma.h> |
|---|
| 34 | | -#include <mach/gpio-samsung.h> |
|---|
| 35 | | - |
|---|
| 36 | 27 | #include <linux/platform_data/mmc-s3cmci.h> |
|---|
| 37 | 28 | |
|---|
| 38 | 29 | #include "s3cmci.h" |
|---|
| .. | .. |
|---|
| 154 | 145 | |
|---|
| 155 | 146 | static void dbg_dumpregs(struct s3cmci_host *host, char *prefix) |
|---|
| 156 | 147 | { |
|---|
| 157 | | - u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer, bsize; |
|---|
| 158 | | - u32 datcon, datcnt, datsta, fsta, imask; |
|---|
| 148 | + u32 con, pre, cmdarg, cmdcon, cmdsta, r0, r1, r2, r3, timer; |
|---|
| 149 | + u32 datcon, datcnt, datsta, fsta; |
|---|
| 159 | 150 | |
|---|
| 160 | 151 | con = readl(host->base + S3C2410_SDICON); |
|---|
| 161 | 152 | pre = readl(host->base + S3C2410_SDIPRE); |
|---|
| .. | .. |
|---|
| 167 | 158 | r2 = readl(host->base + S3C2410_SDIRSP2); |
|---|
| 168 | 159 | r3 = readl(host->base + S3C2410_SDIRSP3); |
|---|
| 169 | 160 | timer = readl(host->base + S3C2410_SDITIMER); |
|---|
| 170 | | - bsize = readl(host->base + S3C2410_SDIBSIZE); |
|---|
| 171 | 161 | datcon = readl(host->base + S3C2410_SDIDCON); |
|---|
| 172 | 162 | datcnt = readl(host->base + S3C2410_SDIDCNT); |
|---|
| 173 | 163 | datsta = readl(host->base + S3C2410_SDIDSTA); |
|---|
| 174 | 164 | fsta = readl(host->base + S3C2410_SDIFSTA); |
|---|
| 175 | | - imask = readl(host->base + host->sdiimsk); |
|---|
| 176 | 165 | |
|---|
| 177 | 166 | dbg(host, dbg_debug, "%s CON:[%08x] PRE:[%08x] TMR:[%08x]\n", |
|---|
| 178 | 167 | prefix, con, pre, timer); |
|---|
| .. | .. |
|---|
| 311 | 300 | static void s3cmci_check_sdio_irq(struct s3cmci_host *host) |
|---|
| 312 | 301 | { |
|---|
| 313 | 302 | if (host->sdio_irqen) { |
|---|
| 314 | | - if (gpio_get_value(S3C2410_GPE(8)) == 0) { |
|---|
| 303 | + if (host->pdata->bus[3] && |
|---|
| 304 | + gpiod_get_value(host->pdata->bus[3]) == 0) { |
|---|
| 315 | 305 | pr_debug("%s: signalling irq\n", __func__); |
|---|
| 316 | 306 | mmc_signal_sdio_irq(host->mmc); |
|---|
| 317 | 307 | } |
|---|
| .. | .. |
|---|
| 400 | 390 | local_irq_restore(flags); |
|---|
| 401 | 391 | } |
|---|
| 402 | 392 | |
|---|
| 403 | | -/** |
|---|
| 404 | | - * |
|---|
| 405 | | - */ |
|---|
| 406 | 393 | static void s3cmci_disable_irq(struct s3cmci_host *host, bool transfer) |
|---|
| 407 | 394 | { |
|---|
| 408 | 395 | unsigned long flags; |
|---|
| .. | .. |
|---|
| 962 | 949 | { |
|---|
| 963 | 950 | u32 dcon, imsk, stoptries = 3; |
|---|
| 964 | 951 | |
|---|
| 965 | | - /* write DCON register */ |
|---|
| 966 | | - |
|---|
| 967 | | - if (!data) { |
|---|
| 968 | | - writel(0, host->base + S3C2410_SDIDCON); |
|---|
| 969 | | - return 0; |
|---|
| 970 | | - } |
|---|
| 971 | | - |
|---|
| 972 | 952 | if ((data->blksz & 3) != 0) { |
|---|
| 973 | 953 | /* We cannot deal with unaligned blocks with more than |
|---|
| 974 | 954 | * one block being transferred. */ |
|---|
| .. | .. |
|---|
| 1217 | 1197 | switch (ios->power_mode) { |
|---|
| 1218 | 1198 | case MMC_POWER_ON: |
|---|
| 1219 | 1199 | case MMC_POWER_UP: |
|---|
| 1220 | | - /* Configure GPE5...GPE10 pins in SD mode */ |
|---|
| 1221 | | - if (!host->pdev->dev.of_node) |
|---|
| 1222 | | - s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2), |
|---|
| 1223 | | - S3C_GPIO_PULL_NONE); |
|---|
| 1224 | | - |
|---|
| 1225 | | - if (host->pdata->set_power) |
|---|
| 1226 | | - host->pdata->set_power(ios->power_mode, ios->vdd); |
|---|
| 1227 | | - |
|---|
| 1228 | 1200 | if (!host->is2440) |
|---|
| 1229 | 1201 | mci_con |= S3C2410_SDICON_FIFORESET; |
|---|
| 1230 | | - |
|---|
| 1231 | 1202 | break; |
|---|
| 1232 | 1203 | |
|---|
| 1233 | 1204 | case MMC_POWER_OFF: |
|---|
| 1234 | 1205 | default: |
|---|
| 1235 | | - if (!host->pdev->dev.of_node) |
|---|
| 1236 | | - gpio_direction_output(S3C2410_GPE(5), 0); |
|---|
| 1237 | | - |
|---|
| 1238 | 1206 | if (host->is2440) |
|---|
| 1239 | 1207 | mci_con |= S3C2440_SDICON_SDRESET; |
|---|
| 1240 | | - |
|---|
| 1241 | | - if (host->pdata->set_power) |
|---|
| 1242 | | - host->pdata->set_power(ios->power_mode, ios->vdd); |
|---|
| 1243 | | - |
|---|
| 1244 | 1208 | break; |
|---|
| 1245 | 1209 | } |
|---|
| 1210 | + |
|---|
| 1211 | + if (host->pdata->set_power) |
|---|
| 1212 | + host->pdata->set_power(ios->power_mode, ios->vdd); |
|---|
| 1246 | 1213 | |
|---|
| 1247 | 1214 | s3cmci_set_clk(host, ios); |
|---|
| 1248 | 1215 | |
|---|
| .. | .. |
|---|
| 1321 | 1288 | .enable_sdio_irq = s3cmci_enable_sdio_irq, |
|---|
| 1322 | 1289 | }; |
|---|
| 1323 | 1290 | |
|---|
| 1324 | | -static struct s3c24xx_mci_pdata s3cmci_def_pdata = { |
|---|
| 1325 | | - /* This is currently here to avoid a number of if (host->pdata) |
|---|
| 1326 | | - * checks. Any zero fields to ensure reasonable defaults are picked. */ |
|---|
| 1327 | | - .no_wprotect = 1, |
|---|
| 1328 | | - .no_detect = 1, |
|---|
| 1329 | | -}; |
|---|
| 1330 | | - |
|---|
| 1331 | 1291 | #ifdef CONFIG_ARM_S3C24XX_CPUFREQ |
|---|
| 1332 | 1292 | |
|---|
| 1333 | 1293 | static int s3cmci_cpufreq_transition(struct notifier_block *nb, |
|---|
| .. | .. |
|---|
| 1390 | 1350 | { |
|---|
| 1391 | 1351 | struct s3cmci_host *host = seq->private; |
|---|
| 1392 | 1352 | |
|---|
| 1393 | | - seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base); |
|---|
| 1353 | + seq_printf(seq, "Register base = 0x%p\n", host->base); |
|---|
| 1394 | 1354 | seq_printf(seq, "Clock rate = %ld\n", host->clk_rate); |
|---|
| 1395 | 1355 | seq_printf(seq, "Prescale = %d\n", host->prescaler); |
|---|
| 1396 | 1356 | seq_printf(seq, "is2440 = %d\n", host->is2440); |
|---|
| .. | .. |
|---|
| 1406 | 1366 | return 0; |
|---|
| 1407 | 1367 | } |
|---|
| 1408 | 1368 | |
|---|
| 1409 | | -static int s3cmci_state_open(struct inode *inode, struct file *file) |
|---|
| 1410 | | -{ |
|---|
| 1411 | | - return single_open(file, s3cmci_state_show, inode->i_private); |
|---|
| 1412 | | -} |
|---|
| 1413 | | - |
|---|
| 1414 | | -static const struct file_operations s3cmci_fops_state = { |
|---|
| 1415 | | - .owner = THIS_MODULE, |
|---|
| 1416 | | - .open = s3cmci_state_open, |
|---|
| 1417 | | - .read = seq_read, |
|---|
| 1418 | | - .llseek = seq_lseek, |
|---|
| 1419 | | - .release = single_release, |
|---|
| 1420 | | -}; |
|---|
| 1369 | +DEFINE_SHOW_ATTRIBUTE(s3cmci_state); |
|---|
| 1421 | 1370 | |
|---|
| 1422 | 1371 | #define DBG_REG(_r) { .addr = S3C2410_SDI##_r, .name = #_r } |
|---|
| 1423 | 1372 | |
|---|
| .. | .. |
|---|
| 1459 | 1408 | return 0; |
|---|
| 1460 | 1409 | } |
|---|
| 1461 | 1410 | |
|---|
| 1462 | | -static int s3cmci_regs_open(struct inode *inode, struct file *file) |
|---|
| 1463 | | -{ |
|---|
| 1464 | | - return single_open(file, s3cmci_regs_show, inode->i_private); |
|---|
| 1465 | | -} |
|---|
| 1466 | | - |
|---|
| 1467 | | -static const struct file_operations s3cmci_fops_regs = { |
|---|
| 1468 | | - .owner = THIS_MODULE, |
|---|
| 1469 | | - .open = s3cmci_regs_open, |
|---|
| 1470 | | - .read = seq_read, |
|---|
| 1471 | | - .llseek = seq_lseek, |
|---|
| 1472 | | - .release = single_release, |
|---|
| 1473 | | -}; |
|---|
| 1411 | +DEFINE_SHOW_ATTRIBUTE(s3cmci_regs); |
|---|
| 1474 | 1412 | |
|---|
| 1475 | 1413 | static void s3cmci_debugfs_attach(struct s3cmci_host *host) |
|---|
| 1476 | 1414 | { |
|---|
| 1477 | 1415 | struct device *dev = &host->pdev->dev; |
|---|
| 1416 | + struct dentry *root; |
|---|
| 1478 | 1417 | |
|---|
| 1479 | | - host->debug_root = debugfs_create_dir(dev_name(dev), NULL); |
|---|
| 1480 | | - if (IS_ERR(host->debug_root)) { |
|---|
| 1481 | | - dev_err(dev, "failed to create debugfs root\n"); |
|---|
| 1482 | | - return; |
|---|
| 1483 | | - } |
|---|
| 1418 | + root = debugfs_create_dir(dev_name(dev), NULL); |
|---|
| 1419 | + host->debug_root = root; |
|---|
| 1484 | 1420 | |
|---|
| 1485 | | - host->debug_state = debugfs_create_file("state", 0444, |
|---|
| 1486 | | - host->debug_root, host, |
|---|
| 1487 | | - &s3cmci_fops_state); |
|---|
| 1488 | | - |
|---|
| 1489 | | - if (IS_ERR(host->debug_state)) |
|---|
| 1490 | | - dev_err(dev, "failed to create debug state file\n"); |
|---|
| 1491 | | - |
|---|
| 1492 | | - host->debug_regs = debugfs_create_file("regs", 0444, |
|---|
| 1493 | | - host->debug_root, host, |
|---|
| 1494 | | - &s3cmci_fops_regs); |
|---|
| 1495 | | - |
|---|
| 1496 | | - if (IS_ERR(host->debug_regs)) |
|---|
| 1497 | | - dev_err(dev, "failed to create debug regs file\n"); |
|---|
| 1421 | + debugfs_create_file("state", 0444, root, host, &s3cmci_state_fops); |
|---|
| 1422 | + debugfs_create_file("regs", 0444, root, host, &s3cmci_regs_fops); |
|---|
| 1498 | 1423 | } |
|---|
| 1499 | 1424 | |
|---|
| 1500 | 1425 | static void s3cmci_debugfs_remove(struct s3cmci_host *host) |
|---|
| 1501 | 1426 | { |
|---|
| 1502 | | - debugfs_remove(host->debug_regs); |
|---|
| 1503 | | - debugfs_remove(host->debug_state); |
|---|
| 1504 | | - debugfs_remove(host->debug_root); |
|---|
| 1427 | + debugfs_remove_recursive(host->debug_root); |
|---|
| 1505 | 1428 | } |
|---|
| 1506 | 1429 | |
|---|
| 1507 | 1430 | #else |
|---|
| .. | .. |
|---|
| 1518 | 1441 | int i, ret; |
|---|
| 1519 | 1442 | |
|---|
| 1520 | 1443 | host->is2440 = platform_get_device_id(pdev)->driver_data; |
|---|
| 1521 | | - |
|---|
| 1522 | | - for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) { |
|---|
| 1523 | | - ret = gpio_request(i, dev_name(&pdev->dev)); |
|---|
| 1524 | | - if (ret) { |
|---|
| 1525 | | - dev_err(&pdev->dev, "failed to get gpio %d\n", i); |
|---|
| 1526 | | - |
|---|
| 1527 | | - for (i--; i >= S3C2410_GPE(5); i--) |
|---|
| 1528 | | - gpio_free(i); |
|---|
| 1529 | | - |
|---|
| 1530 | | - return ret; |
|---|
| 1531 | | - } |
|---|
| 1444 | + pdata = pdev->dev.platform_data; |
|---|
| 1445 | + if (!pdata) { |
|---|
| 1446 | + dev_err(&pdev->dev, "need platform data"); |
|---|
| 1447 | + return -ENXIO; |
|---|
| 1532 | 1448 | } |
|---|
| 1533 | 1449 | |
|---|
| 1534 | | - if (!pdev->dev.platform_data) |
|---|
| 1535 | | - pdev->dev.platform_data = &s3cmci_def_pdata; |
|---|
| 1536 | | - |
|---|
| 1537 | | - pdata = pdev->dev.platform_data; |
|---|
| 1450 | + for (i = 0; i < 6; i++) { |
|---|
| 1451 | + pdata->bus[i] = devm_gpiod_get_index(&pdev->dev, "bus", i, |
|---|
| 1452 | + GPIOD_OUT_LOW); |
|---|
| 1453 | + if (IS_ERR(pdata->bus[i])) { |
|---|
| 1454 | + dev_err(&pdev->dev, "failed to get gpio %d\n", i); |
|---|
| 1455 | + return PTR_ERR(pdata->bus[i]); |
|---|
| 1456 | + } |
|---|
| 1457 | + } |
|---|
| 1538 | 1458 | |
|---|
| 1539 | 1459 | if (pdata->no_wprotect) |
|---|
| 1540 | 1460 | mmc->caps2 |= MMC_CAP2_NO_WRITE_PROTECT; |
|---|
| .. | .. |
|---|
| 1545 | 1465 | if (pdata->wprotect_invert) |
|---|
| 1546 | 1466 | mmc->caps2 |= MMC_CAP2_RO_ACTIVE_HIGH; |
|---|
| 1547 | 1467 | |
|---|
| 1548 | | - if (pdata->detect_invert) |
|---|
| 1549 | | - mmc->caps2 |= MMC_CAP2_CD_ACTIVE_HIGH; |
|---|
| 1550 | | - |
|---|
| 1551 | | - if (gpio_is_valid(pdata->gpio_detect)) { |
|---|
| 1552 | | - ret = mmc_gpio_request_cd(mmc, pdata->gpio_detect, 0); |
|---|
| 1553 | | - if (ret) { |
|---|
| 1554 | | - dev_err(&pdev->dev, "error requesting GPIO for CD %d\n", |
|---|
| 1555 | | - ret); |
|---|
| 1556 | | - return ret; |
|---|
| 1557 | | - } |
|---|
| 1468 | + /* If we get -ENOENT we have no card detect GPIO line */ |
|---|
| 1469 | + ret = mmc_gpiod_request_cd(mmc, "cd", 0, false, 0); |
|---|
| 1470 | + if (ret != -ENOENT) { |
|---|
| 1471 | + dev_err(&pdev->dev, "error requesting GPIO for CD %d\n", |
|---|
| 1472 | + ret); |
|---|
| 1473 | + return ret; |
|---|
| 1558 | 1474 | } |
|---|
| 1559 | 1475 | |
|---|
| 1560 | | - if (gpio_is_valid(pdata->gpio_wprotect)) { |
|---|
| 1561 | | - ret = mmc_gpio_request_ro(mmc, pdata->gpio_wprotect); |
|---|
| 1562 | | - if (ret) { |
|---|
| 1563 | | - dev_err(&pdev->dev, "error requesting GPIO for WP %d\n", |
|---|
| 1564 | | - ret); |
|---|
| 1565 | | - return ret; |
|---|
| 1566 | | - } |
|---|
| 1476 | + ret = mmc_gpiod_request_ro(host->mmc, "wp", 0, 0); |
|---|
| 1477 | + if (ret != -ENOENT) { |
|---|
| 1478 | + dev_err(&pdev->dev, "error requesting GPIO for WP %d\n", |
|---|
| 1479 | + ret); |
|---|
| 1480 | + return ret; |
|---|
| 1567 | 1481 | } |
|---|
| 1568 | 1482 | |
|---|
| 1569 | 1483 | return 0; |
|---|
| .. | .. |
|---|
| 1576 | 1490 | struct mmc_host *mmc = host->mmc; |
|---|
| 1577 | 1491 | int ret; |
|---|
| 1578 | 1492 | |
|---|
| 1579 | | - host->is2440 = (int) of_device_get_match_data(&pdev->dev); |
|---|
| 1493 | + host->is2440 = (long) of_device_get_match_data(&pdev->dev); |
|---|
| 1580 | 1494 | |
|---|
| 1581 | 1495 | ret = mmc_of_parse(mmc); |
|---|
| 1582 | 1496 | if (ret) |
|---|
| .. | .. |
|---|
| 1596 | 1510 | struct s3cmci_host *host; |
|---|
| 1597 | 1511 | struct mmc_host *mmc; |
|---|
| 1598 | 1512 | int ret; |
|---|
| 1599 | | - int i; |
|---|
| 1600 | 1513 | |
|---|
| 1601 | 1514 | mmc = mmc_alloc_host(sizeof(struct s3cmci_host), &pdev->dev); |
|---|
| 1602 | 1515 | if (!mmc) { |
|---|
| .. | .. |
|---|
| 1640 | 1553 | "failed to get io memory region resource.\n"); |
|---|
| 1641 | 1554 | |
|---|
| 1642 | 1555 | ret = -ENOENT; |
|---|
| 1643 | | - goto probe_free_gpio; |
|---|
| 1556 | + goto probe_free_host; |
|---|
| 1644 | 1557 | } |
|---|
| 1645 | 1558 | |
|---|
| 1646 | 1559 | host->mem = request_mem_region(host->mem->start, |
|---|
| .. | .. |
|---|
| 1649 | 1562 | if (!host->mem) { |
|---|
| 1650 | 1563 | dev_err(&pdev->dev, "failed to request io memory region.\n"); |
|---|
| 1651 | 1564 | ret = -ENOENT; |
|---|
| 1652 | | - goto probe_free_gpio; |
|---|
| 1565 | + goto probe_free_host; |
|---|
| 1653 | 1566 | } |
|---|
| 1654 | 1567 | |
|---|
| 1655 | 1568 | host->base = ioremap(host->mem->start, resource_size(host->mem)); |
|---|
| .. | .. |
|---|
| 1661 | 1574 | |
|---|
| 1662 | 1575 | host->irq = platform_get_irq(pdev, 0); |
|---|
| 1663 | 1576 | if (host->irq <= 0) { |
|---|
| 1664 | | - dev_err(&pdev->dev, "failed to get interrupt resource.\n"); |
|---|
| 1665 | 1577 | ret = -EINVAL; |
|---|
| 1666 | 1578 | goto probe_iounmap; |
|---|
| 1667 | 1579 | } |
|---|
| .. | .. |
|---|
| 1774 | 1686 | probe_free_mem_region: |
|---|
| 1775 | 1687 | release_mem_region(host->mem->start, resource_size(host->mem)); |
|---|
| 1776 | 1688 | |
|---|
| 1777 | | - probe_free_gpio: |
|---|
| 1778 | | - if (!pdev->dev.of_node) |
|---|
| 1779 | | - for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) |
|---|
| 1780 | | - gpio_free(i); |
|---|
| 1781 | | - |
|---|
| 1782 | 1689 | probe_free_host: |
|---|
| 1783 | 1690 | mmc_free_host(mmc); |
|---|
| 1784 | 1691 | |
|---|
| .. | .. |
|---|
| 1804 | 1711 | { |
|---|
| 1805 | 1712 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
|---|
| 1806 | 1713 | struct s3cmci_host *host = mmc_priv(mmc); |
|---|
| 1807 | | - int i; |
|---|
| 1808 | 1714 | |
|---|
| 1809 | 1715 | s3cmci_shutdown(pdev); |
|---|
| 1810 | 1716 | |
|---|
| .. | .. |
|---|
| 1816 | 1722 | dma_release_channel(host->dma); |
|---|
| 1817 | 1723 | |
|---|
| 1818 | 1724 | free_irq(host->irq, host); |
|---|
| 1819 | | - |
|---|
| 1820 | | - if (!pdev->dev.of_node) |
|---|
| 1821 | | - for (i = S3C2410_GPE(5); i <= S3C2410_GPE(10); i++) |
|---|
| 1822 | | - gpio_free(i); |
|---|
| 1823 | 1725 | |
|---|
| 1824 | 1726 | iounmap(host->base); |
|---|
| 1825 | 1727 | release_mem_region(host->mem->start, resource_size(host->mem)); |
|---|