aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mfd
diff options
context:
space:
mode:
authorWei WANG <wei_wang@realsil.com.cn>2013-02-08 02:24:27 -0500
committerSamuel Ortiz <sameo@linux.intel.com>2013-02-13 18:24:12 -0500
commitc3481955f6c78c8dd99921759306d7469c999ec2 (patch)
treeae65ba72e1076dd94690f16c2d03cdce56d7f34d /drivers/mfd
parent0cd5b6d08c7bf8b2d81eb1413ea1463cc72487b1 (diff)
mfd: rtsx: Fix issue that booting OS with SD card inserted
Realtek card reader supports both SD and MS card. According to the settings of rtsx MFD driver, SD host will be probed before MS host. If we boot/reboot Linux with SD card inserted, the resetting flow of SD card will succeed, and the following resetting flow of MS is sure to fail. Then MS upper-level driver will ask rtsx driver to turn power off. This request leads to the result that the following SD commands fail and SD card can't be accessed again. In this commit, Realtek's SD and MS host driver will check whether the card that upper driver requesting is the one existing in the slot. If not, Realtek's host driver will refuse the operation to make sure the exlusive accessing at the same time. Signed-off-by: Wei WANG <wei_wang@realsil.com.cn> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r--drivers/mfd/rtsx_pcr.c30
1 files changed, 30 insertions, 0 deletions
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}
709EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); 709EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
710 710
711int 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}
728EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check);
729
711int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) 730int 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