.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Realtek PCI-Express SD/MMC Card Interface driver |
---|
2 | 3 | * |
---|
3 | 4 | * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved. |
---|
4 | | - * |
---|
5 | | - * This program is free software; you can redistribute it and/or modify it |
---|
6 | | - * under the terms of the GNU General Public License as published by the |
---|
7 | | - * Free Software Foundation; either version 2, or (at your option) any |
---|
8 | | - * later version. |
---|
9 | | - * |
---|
10 | | - * This program is distributed in the hope that it will be useful, but |
---|
11 | | - * WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
12 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
---|
13 | | - * General Public License for more details. |
---|
14 | | - * |
---|
15 | | - * You should have received a copy of the GNU General Public License along |
---|
16 | | - * with this program; if not, see <http://www.gnu.org/licenses/>. |
---|
17 | 5 | * |
---|
18 | 6 | * Author: |
---|
19 | 7 | * Wei WANG <wei_wang@realsil.com.cn> |
---|
.. | .. |
---|
49 | 37 | bool double_clk; |
---|
50 | 38 | bool eject; |
---|
51 | 39 | bool initial_mode; |
---|
52 | | - int power_state; |
---|
53 | | -#define SDMMC_POWER_ON 1 |
---|
54 | | -#define SDMMC_POWER_OFF 0 |
---|
55 | | - |
---|
| 40 | + int prev_power_state; |
---|
56 | 41 | int sg_count; |
---|
57 | 42 | s32 cookie; |
---|
58 | 43 | int cookie_sg_count; |
---|
.. | .. |
---|
697 | 682 | |
---|
698 | 683 | static void sd_wait_data_idle(struct realtek_pci_sdmmc *host) |
---|
699 | 684 | { |
---|
700 | | - int err, i; |
---|
| 685 | + int i; |
---|
701 | 686 | u8 val = 0; |
---|
702 | 687 | |
---|
703 | 688 | for (i = 0; i < 100; i++) { |
---|
704 | | - err = rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val); |
---|
| 689 | + rtsx_pci_read_register(host->pcr, SD_DATA_STATE, &val); |
---|
705 | 690 | if (val & SD_DATA_IDLE) |
---|
706 | 691 | return; |
---|
707 | 692 | |
---|
.. | .. |
---|
914 | 899 | return err; |
---|
915 | 900 | } |
---|
916 | 901 | |
---|
917 | | -static int sd_power_on(struct realtek_pci_sdmmc *host) |
---|
| 902 | +static int sd_power_on(struct realtek_pci_sdmmc *host, unsigned char power_mode) |
---|
918 | 903 | { |
---|
919 | 904 | struct rtsx_pcr *pcr = host->pcr; |
---|
920 | 905 | int err; |
---|
921 | 906 | |
---|
922 | | - if (host->power_state == SDMMC_POWER_ON) |
---|
| 907 | + if (host->prev_power_state == MMC_POWER_ON) |
---|
923 | 908 | return 0; |
---|
| 909 | + |
---|
| 910 | + if (host->prev_power_state == MMC_POWER_UP) { |
---|
| 911 | + rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, 0); |
---|
| 912 | + goto finish; |
---|
| 913 | + } |
---|
| 914 | + |
---|
| 915 | + msleep(100); |
---|
924 | 916 | |
---|
925 | 917 | rtsx_pci_init_cmd(pcr); |
---|
926 | 918 | rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_SELECT, 0x07, SD_MOD_SEL); |
---|
.. | .. |
---|
940 | 932 | if (err < 0) |
---|
941 | 933 | return err; |
---|
942 | 934 | |
---|
| 935 | + mdelay(1); |
---|
| 936 | + |
---|
943 | 937 | err = rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, SD_OUTPUT_EN); |
---|
944 | 938 | if (err < 0) |
---|
945 | 939 | return err; |
---|
946 | 940 | |
---|
947 | | - host->power_state = SDMMC_POWER_ON; |
---|
| 941 | + /* send at least 74 clocks */ |
---|
| 942 | + rtsx_pci_write_register(pcr, SD_BUS_STAT, SD_CLK_TOGGLE_EN, SD_CLK_TOGGLE_EN); |
---|
| 943 | + |
---|
| 944 | +finish: |
---|
| 945 | + host->prev_power_state = power_mode; |
---|
948 | 946 | return 0; |
---|
949 | 947 | } |
---|
950 | 948 | |
---|
.. | .. |
---|
953 | 951 | struct rtsx_pcr *pcr = host->pcr; |
---|
954 | 952 | int err; |
---|
955 | 953 | |
---|
956 | | - host->power_state = SDMMC_POWER_OFF; |
---|
| 954 | + host->prev_power_state = MMC_POWER_OFF; |
---|
957 | 955 | |
---|
958 | 956 | rtsx_pci_init_cmd(pcr); |
---|
959 | 957 | |
---|
.. | .. |
---|
979 | 977 | if (power_mode == MMC_POWER_OFF) |
---|
980 | 978 | err = sd_power_off(host); |
---|
981 | 979 | else |
---|
982 | | - err = sd_power_on(host); |
---|
| 980 | + err = sd_power_on(host, power_mode); |
---|
983 | 981 | |
---|
984 | 982 | return err; |
---|
985 | 983 | } |
---|
.. | .. |
---|
1358 | 1356 | mmc->caps |= MMC_CAP_1_8V_DDR; |
---|
1359 | 1357 | if (pcr->extra_caps & EXTRA_CAPS_MMC_8BIT) |
---|
1360 | 1358 | mmc->caps |= MMC_CAP_8_BIT_DATA; |
---|
| 1359 | + if (pcr->extra_caps & EXTRA_CAPS_NO_MMC) |
---|
| 1360 | + mmc->caps2 |= MMC_CAP2_NO_MMC; |
---|
1361 | 1361 | } |
---|
1362 | 1362 | |
---|
1363 | 1363 | static void realtek_init_host(struct realtek_pci_sdmmc *host) |
---|
.. | .. |
---|
1369 | 1369 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; |
---|
1370 | 1370 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SD_HIGHSPEED | |
---|
1371 | 1371 | MMC_CAP_MMC_HIGHSPEED | MMC_CAP_BUS_WIDTH_TEST | |
---|
1372 | | - MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25 | MMC_CAP_ERASE; |
---|
| 1372 | + MMC_CAP_UHS_SDR12 | MMC_CAP_UHS_SDR25; |
---|
1373 | 1373 | mmc->caps2 = MMC_CAP2_NO_PRESCAN_POWERUP | MMC_CAP2_FULL_PWR_CYCLE; |
---|
1374 | 1374 | mmc->max_current_330 = 400; |
---|
1375 | 1375 | mmc->max_current_180 = 800; |
---|
.. | .. |
---|
1414 | 1414 | |
---|
1415 | 1415 | host = mmc_priv(mmc); |
---|
1416 | 1416 | host->pcr = pcr; |
---|
| 1417 | + mmc->ios.power_delay_ms = 5; |
---|
1417 | 1418 | host->mmc = mmc; |
---|
1418 | 1419 | host->pdev = pdev; |
---|
1419 | 1420 | host->cookie = -1; |
---|
1420 | | - host->power_state = SDMMC_POWER_OFF; |
---|
| 1421 | + host->prev_power_state = MMC_POWER_OFF; |
---|
1421 | 1422 | INIT_WORK(&host->work, sd_request); |
---|
1422 | 1423 | platform_set_drvdata(pdev, host); |
---|
1423 | 1424 | pcr->slots[RTSX_SD_CARD].p_dev = pdev; |
---|
.. | .. |
---|
1491 | 1492 | .id_table = rtsx_pci_sdmmc_ids, |
---|
1492 | 1493 | .driver = { |
---|
1493 | 1494 | .name = DRV_NAME_RTSX_PCI_SDMMC, |
---|
| 1495 | + .probe_type = PROBE_PREFER_ASYNCHRONOUS, |
---|
1494 | 1496 | }, |
---|
1495 | 1497 | }; |
---|
1496 | 1498 | module_platform_driver(rtsx_pci_sdmmc_driver); |
---|