| .. | .. |
|---|
| 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; |
|---|