diff options
author | Wei WANG <wei_wang@realsil.com.cn> | 2013-02-08 15:24:27 +0800 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2013-02-14 00:24:12 +0100 |
commit | c3481955f6c78c8dd99921759306d7469c999ec2 (patch) | |
tree | ae65ba72e1076dd94690f16c2d03cdce56d7f34d /drivers/mfd/rtsx_pcr.c | |
parent | 0cd5b6d08c7bf8b2d81eb1413ea1463cc72487b1 (diff) | |
download | op-kernel-dev-c3481955f6c78c8dd99921759306d7469c999ec2.zip op-kernel-dev-c3481955f6c78c8dd99921759306d7469c999ec2.tar.gz |
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/rtsx_pcr.c')
-rw-r--r-- | drivers/mfd/rtsx_pcr.c | 30 |
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 822237e..481a98a 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) } EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); +int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card) +{ + unsigned int cd_mask[] = { + [RTSX_SD_CARD] = SD_EXIST, + [RTSX_MS_CARD] = MS_EXIST + }; + + if (!pcr->ms_pmos) { + /* When using single PMOS, accessing card is not permitted + * if the existing card is not the designated one. + */ + if (pcr->card_exist & (~cd_mask[card])) + return -EIO; + } + + return 0; +} +EXPORT_SYMBOL_GPL(rtsx_pci_card_exclusive_check); + int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) { if (pcr->ops->switch_output_voltage) @@ -784,6 +803,9 @@ static void rtsx_pci_card_detect(struct work_struct *work) card_inserted = pcr->ops->cd_deglitch(pcr); card_detect = card_inserted | card_removed; + + pcr->card_exist |= card_inserted; + pcr->card_exist &= ~card_removed; } mutex_unlock(&pcr->pcr_mutex); @@ -976,6 +998,14 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) return err; } + /* No CD interrupt if probing driver with card inserted. + * So we need to initialize pcr->card_exist here. + */ + if (pcr->ops->cd_deglitch) + pcr->card_exist = pcr->ops->cd_deglitch(pcr); + else + pcr->card_exist = rtsx_pci_readl(pcr, RTSX_BIPR) & CARD_EXIST; + return 0; } |