diff options
| -rw-r--r-- | drivers/memstick/host/rtsx_pci_ms.c | 7 | ||||
| -rw-r--r-- | drivers/mfd/rtsx_pcr.c | 30 | ||||
| -rw-r--r-- | drivers/mmc/host/rtsx_pci_sdmmc.c | 18 | ||||
| -rw-r--r-- | include/linux/mfd/rtsx_pci.h | 2 |
4 files changed, 57 insertions, 0 deletions
diff --git a/drivers/memstick/host/rtsx_pci_ms.c b/drivers/memstick/host/rtsx_pci_ms.c index f5ddb82dadb7..64a779c58a74 100644 --- a/drivers/memstick/host/rtsx_pci_ms.c +++ b/drivers/memstick/host/rtsx_pci_ms.c | |||
| @@ -426,6 +426,9 @@ static void rtsx_pci_ms_request(struct memstick_host *msh) | |||
| 426 | 426 | ||
| 427 | dev_dbg(ms_dev(host), "--> %s\n", __func__); | 427 | dev_dbg(ms_dev(host), "--> %s\n", __func__); |
| 428 | 428 | ||
| 429 | if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD)) | ||
| 430 | return; | ||
| 431 | |||
| 429 | schedule_work(&host->handle_req); | 432 | schedule_work(&host->handle_req); |
| 430 | } | 433 | } |
| 431 | 434 | ||
| @@ -441,6 +444,10 @@ static int rtsx_pci_ms_set_param(struct memstick_host *msh, | |||
| 441 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", | 444 | dev_dbg(ms_dev(host), "%s: param = %d, value = %d\n", |
| 442 | __func__, param, value); | 445 | __func__, param, value); |
| 443 | 446 | ||
| 447 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_MS_CARD); | ||
| 448 | if (err) | ||
| 449 | return err; | ||
| 450 | |||
| 444 | switch (param) { | 451 | switch (param) { |
| 445 | case MEMSTICK_POWER: | 452 | case MEMSTICK_POWER: |
| 446 | if (value == MEMSTICK_POWER_ON) | 453 | if (value == MEMSTICK_POWER_ON) |
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 822237e322ba..481a98a10ecd 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
| @@ -708,6 +708,25 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) | |||
| 708 | } | 708 | } |
| 709 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); | 709 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); |
| 710 | 710 | ||
| 711 | int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card) | ||
| 712 | { | ||
| 713 | unsigned int cd_mask[] = { | ||
| 714 | [RTSX_SD_CARD] = SD_EXIST, | ||
| 715 | [RTSX_MS_CARD] = MS_EXIST | ||
| 716 | }; | ||
| 717 | |||
| 718 | if (!pcr->ms_pmos) { | ||
| 719 | /* When using single PMOS, accessing card is not permitted | ||
| 720 | * if the existing card is not the designated one. | ||
| 721 | */ | ||
| 722 | if (pcr->card_exist & (~cd_mask[card])) | ||
| 723 | return -EIO; | ||
| 724 | } | ||
| 725 | |||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check); | ||
| 729 | |||
| 711 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | 730 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) |
| 712 | { | 731 | { |
| 713 | if (pcr->ops->switch_output_voltage) | 732 | if (pcr->ops->switch_output_voltage) |
| @@ -784,6 +803,9 @@ static void rtsx_pci_card_detect(struct work_struct *work) | |||
| 784 | card_inserted = pcr->ops->cd_deglitch(pcr); | 803 | card_inserted = pcr->ops->cd_deglitch(pcr); |
| 785 | 804 | ||
| 786 | card_detect = card_inserted | card_removed; | 805 | card_detect = card_inserted | card_removed; |
| 806 | |||
| 807 | pcr->card_exist |= card_inserted; | ||
| 808 | pcr->card_exist &= ~card_removed; | ||
| 787 | } | 809 | } |
| 788 | 810 | ||
| 789 | mutex_unlock(&pcr->pcr_mutex); | 811 | mutex_unlock(&pcr->pcr_mutex); |
| @@ -976,6 +998,14 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) | |||
| 976 | return err; | 998 | return err; |
| 977 | } | 999 | } |
| 978 | 1000 | ||
| 1001 | /* No CD interrupt if probing driver with card inserted. | ||
| 1002 | * So we need to initialize pcr->card_exist here. | ||
| 1003 | */ | ||
| 1004 | if (pcr->ops->cd_deglitch) | ||
| 1005 | pcr->card_exist = pcr->ops->cd_deglitch(pcr); | ||
| 1006 | else | ||
| 1007 | pcr->card_exist = rtsx_pci_readl(pcr, RTSX_BIPR) & CARD_EXIST; | ||
| 1008 | |||
| 979 | return 0; | 1009 | return 0; |
| 980 | } | 1010 | } |
| 981 | 1011 | ||
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index f74b5adca642..468c92303167 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
| @@ -678,12 +678,19 @@ static void sdmmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 678 | struct mmc_command *cmd = mrq->cmd; | 678 | struct mmc_command *cmd = mrq->cmd; |
| 679 | struct mmc_data *data = mrq->data; | 679 | struct mmc_data *data = mrq->data; |
| 680 | unsigned int data_size = 0; | 680 | unsigned int data_size = 0; |
| 681 | int err; | ||
| 681 | 682 | ||
| 682 | if (host->eject) { | 683 | if (host->eject) { |
| 683 | cmd->error = -ENOMEDIUM; | 684 | cmd->error = -ENOMEDIUM; |
| 684 | goto finish; | 685 | goto finish; |
| 685 | } | 686 | } |
| 686 | 687 | ||
| 688 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
| 689 | if (err) { | ||
| 690 | cmd->error = err; | ||
| 691 | goto finish; | ||
| 692 | } | ||
| 693 | |||
| 687 | mutex_lock(&pcr->pcr_mutex); | 694 | mutex_lock(&pcr->pcr_mutex); |
| 688 | 695 | ||
| 689 | rtsx_pci_start_run(pcr); | 696 | rtsx_pci_start_run(pcr); |
| @@ -901,6 +908,9 @@ static void sdmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 901 | if (host->eject) | 908 | if (host->eject) |
| 902 | return; | 909 | return; |
| 903 | 910 | ||
| 911 | if (rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD)) | ||
| 912 | return; | ||
| 913 | |||
| 904 | mutex_lock(&pcr->pcr_mutex); | 914 | mutex_lock(&pcr->pcr_mutex); |
| 905 | 915 | ||
| 906 | rtsx_pci_start_run(pcr); | 916 | rtsx_pci_start_run(pcr); |
| @@ -1073,6 +1083,10 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 1073 | if (host->eject) | 1083 | if (host->eject) |
| 1074 | return -ENOMEDIUM; | 1084 | return -ENOMEDIUM; |
| 1075 | 1085 | ||
| 1086 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
| 1087 | if (err) | ||
| 1088 | return err; | ||
| 1089 | |||
| 1076 | mutex_lock(&pcr->pcr_mutex); | 1090 | mutex_lock(&pcr->pcr_mutex); |
| 1077 | 1091 | ||
| 1078 | rtsx_pci_start_run(pcr); | 1092 | rtsx_pci_start_run(pcr); |
| @@ -1122,6 +1136,10 @@ static int sdmmc_execute_tuning(struct mmc_host *mmc, u32 opcode) | |||
| 1122 | if (host->eject) | 1136 | if (host->eject) |
| 1123 | return -ENOMEDIUM; | 1137 | return -ENOMEDIUM; |
| 1124 | 1138 | ||
| 1139 | err = rtsx_pci_card_exclusive_check(host->pcr, RTSX_SD_CARD); | ||
| 1140 | if (err) | ||
| 1141 | return err; | ||
| 1142 | |||
| 1125 | mutex_lock(&pcr->pcr_mutex); | 1143 | mutex_lock(&pcr->pcr_mutex); |
| 1126 | 1144 | ||
| 1127 | rtsx_pci_start_run(pcr); | 1145 | rtsx_pci_start_run(pcr); |
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h index 5d9b81e8aff4..26ea7f1b7caf 100644 --- a/include/linux/mfd/rtsx_pci.h +++ b/include/linux/mfd/rtsx_pci.h | |||
| @@ -740,6 +740,7 @@ struct rtsx_pcr { | |||
| 740 | 740 | ||
| 741 | unsigned int card_inserted; | 741 | unsigned int card_inserted; |
| 742 | unsigned int card_removed; | 742 | unsigned int card_removed; |
| 743 | unsigned int card_exist; | ||
| 743 | 744 | ||
| 744 | struct delayed_work carddet_work; | 745 | struct delayed_work carddet_work; |
| 745 | struct delayed_work idle_work; | 746 | struct delayed_work idle_work; |
| @@ -804,6 +805,7 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
| 804 | u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk); | 805 | u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk); |
| 805 | int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card); | 806 | int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card); |
| 806 | int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card); | 807 | int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card); |
| 808 | int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card); | ||
| 807 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage); | 809 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage); |
| 808 | unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr); | 810 | unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr); |
| 809 | void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr); | 811 | void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr); |
