]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
misc: rtsx: Move Realtek Card Reader Driver to misc
authorRui Feng <rui_feng@realsil.com.cn>
Mon, 9 Apr 2018 11:56:05 +0000 (19:56 +0800)
committerSeth Forshee <seth.forshee@canonical.com>
Thu, 12 Apr 2018 15:53:11 +0000 (10:53 -0500)
BugLink: http://bugs.launchpad.net/bugs/1737673
Because Realtek card reader drivers are pcie and usb drivers,
and they bridge mmc subsystem and memstick subsystem, they are
not mfd drivers. Greg and Lee Jones had a discussion about
where to put the drivers, the result is that misc is a good
place for them, so I move all files to misc. If I don't move
them to a right place, I can't add any patch for this driver.

Signed-off-by: Rui Feng <rui_feng@realsil.com.cn>
Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Ulf Hansson <ulf.hansson@linaro.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Tested-by: Perry Yuan <perry_yuan@dell.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
(backported from commit e455b69ddf9b69326d0cab28d374faf3325489c9)
Signed-off-by: AceLan Kao <acelan.kao@canonical.com>
Acked-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
34 files changed:
drivers/memstick/host/Kconfig
drivers/memstick/host/rtsx_pci_ms.c
drivers/memstick/host/rtsx_usb_ms.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/rtl8411.c [deleted file]
drivers/mfd/rts5209.c [deleted file]
drivers/mfd/rts5227.c [deleted file]
drivers/mfd/rts5229.c [deleted file]
drivers/mfd/rts5249.c [deleted file]
drivers/mfd/rtsx_pcr.c [deleted file]
drivers/mfd/rtsx_pcr.h [deleted file]
drivers/mfd/rtsx_usb.c [deleted file]
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/cardreader/Kconfig [new file with mode: 0644]
drivers/misc/cardreader/Makefile [new file with mode: 0644]
drivers/misc/cardreader/rtl8411.c [new file with mode: 0644]
drivers/misc/cardreader/rts5209.c [new file with mode: 0644]
drivers/misc/cardreader/rts5227.c [new file with mode: 0644]
drivers/misc/cardreader/rts5229.c [new file with mode: 0644]
drivers/misc/cardreader/rts5249.c [new file with mode: 0644]
drivers/misc/cardreader/rtsx_pcr.c [new file with mode: 0644]
drivers/misc/cardreader/rtsx_pcr.h [new file with mode: 0644]
drivers/misc/cardreader/rtsx_usb.c [new file with mode: 0644]
drivers/mmc/host/Kconfig
drivers/mmc/host/rtsx_pci_sdmmc.c
drivers/mmc/host/rtsx_usb_sdmmc.c
include/linux/mfd/rtsx_common.h [deleted file]
include/linux/mfd/rtsx_pci.h [deleted file]
include/linux/mfd/rtsx_usb.h [deleted file]
include/linux/rtsx_common.h [new file with mode: 0644]
include/linux/rtsx_pci.h [new file with mode: 0644]
include/linux/rtsx_usb.h [new file with mode: 0644]

index 7310e32b5991af59276f0f3fb7a86d715191bb35..aa2b0786bbe96674472d8ce435229a5ce2c824f5 100644 (file)
@@ -45,7 +45,7 @@ config MEMSTICK_R592
 
 config MEMSTICK_REALTEK_PCI
        tristate "Realtek PCI-E Memstick Card Interface Driver"
-       depends on MFD_RTSX_PCI
+       depends on MISC_RTSX_PCI
        help
          Say Y here to include driver code to support Memstick card interface
          of Realtek PCI-E card reader
@@ -55,7 +55,7 @@ config MEMSTICK_REALTEK_PCI
 
 config MEMSTICK_REALTEK_USB
        tristate "Realtek USB Memstick Card Interface Driver"
-       depends on MFD_RTSX_USB
+       depends on MISC_RTSX_USB
        help
          Say Y here to include driver code to support Memstick card interface
          of Realtek RTS5129/39 series USB card reader
index 818fa94354ae221f76205797bcb9ff791152f56d..a44b4578ba4dc9d186a6dc15b3f8030b55926006 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/memstick.h>
-#include <linux/mfd/rtsx_pci.h>
+#include <linux/rtsx_pci.h>
 #include <asm/unaligned.h>
 
 struct realtek_pci_ms {
index 2e3cf012ef485f863dd2de36d26dae8caae7156b..4f64563df7ded29f387cc0b32d2e147eb27e6848 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/workqueue.h>
 #include <linux/memstick.h>
 #include <linux/kthread.h>
-#include <linux/mfd/rtsx_usb.h>
+#include <linux/rtsx_usb.h>
 #include <linux/pm_runtime.h>
 #include <linux/mutex.h>
 #include <linux/sched.h>
index 1d20a800e96795cd2bf1b9303f7bd2fa1d284b03..1246ba1832d77dbc08a0fc82c0e869185a0cc821 100644 (file)
@@ -929,17 +929,6 @@ config MFD_RDC321X
          southbridge which provides access to GPIOs and Watchdog using the
          southbridge PCI device configuration space.
 
-config MFD_RTSX_PCI
-       tristate "Realtek PCI-E card reader"
-       depends on PCI
-       select MFD_CORE
-       help
-         This supports for Realtek PCI-Express card reader including rts5209,
-         rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411, etc.
-         Realtek card reader supports access to many types of memory cards,
-         such as Memory Stick, Memory Stick Pro, Secure Digital and
-         MultiMediaCard.
-
 config MFD_RT5033
        tristate "Richtek RT5033 Power Management IC"
        depends on I2C
@@ -953,16 +942,6 @@ config MFD_RT5033
          sub-devices like charger, fuel gauge, flash LED, current source,
          LDO and Buck.
 
-config MFD_RTSX_USB
-       tristate "Realtek USB card reader"
-       depends on USB
-       select MFD_CORE
-       help
-         Select this option to get support for Realtek USB 2.0 card readers
-         including RTS5129, RTS5139, RTS5179 and RTS5170.
-         Realtek card reader supports access to many types of memory cards,
-         such as Memory Stick Pro, Secure Digital and MultiMediaCard.
-
 config MFD_RC5T583
        bool "Ricoh RC5T583 Power Management system device"
        depends on I2C=y
index d9474ade32e6693fd7a3e5adb583eb2f3366c5cb..293e223c373d72c77dbd1b83e56d0ed654b4e98e 100644 (file)
@@ -19,10 +19,6 @@ obj-$(CONFIG_MFD_CROS_EC_I2C)        += cros_ec_i2c.o
 obj-$(CONFIG_MFD_CROS_EC_SPI)  += cros_ec_spi.o
 obj-$(CONFIG_MFD_EXYNOS_LPASS) += exynos-lpass.o
 
-rtsx_pci-objs                  := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
-obj-$(CONFIG_MFD_RTSX_PCI)     += rtsx_pci.o
-obj-$(CONFIG_MFD_RTSX_USB)     += rtsx_usb.o
-
 obj-$(CONFIG_HTC_PASIC3)       += htc-pasic3.o
 obj-$(CONFIG_HTC_I2CPLD)       += htc-i2cpld.o
 
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
deleted file mode 100644 (file)
index b3ae659..0000000
+++ /dev/null
@@ -1,508 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- *   Roger Tseng <rogerable@realtek.com>
- */
-
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
-{
-       u8 val;
-
-       rtsx_pci_read_register(pcr, SYS_VER, &val);
-       return val & 0x0F;
-}
-
-static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
-{
-       u8 val = 0;
-
-       rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val);
-
-       if (val & 0x2)
-               return 1;
-       else
-               return 0;
-}
-
-static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg1 = 0;
-       u8 reg3 = 0;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
-
-       if (!rtsx_vendor_setting_valid(reg1))
-               return;
-
-       pcr->aspm_en = rtsx_reg_to_aspm(reg1);
-       pcr->sd30_drive_sel_1v8 =
-               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1));
-       pcr->card_drive_sel &= 0x3F;
-       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
-
-       rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
-       pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
-}
-
-static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg = 0;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
-       if (!rtsx_vendor_setting_valid(reg))
-               return;
-
-       pcr->aspm_en = rtsx_reg_to_aspm(reg);
-       pcr->sd30_drive_sel_1v8 =
-               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
-       pcr->sd30_drive_sel_3v3 =
-               map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg));
-}
-
-static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
-}
-
-static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_init_cmd(pcr);
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
-                       0xFF, pcr->sd30_drive_sel_3v3);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
-                       CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_init_cmd(pcr);
-
-       if (rtl8411b_is_qfn48(pcr))
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               CARD_PULL_CTL3, 0xFF, 0xF5);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
-                       0xFF, pcr->sd30_drive_sel_3v3);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
-                       CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL,
-                       0x06, 0x00);
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
-}
-
-static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
-}
-
-static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
-}
-
-static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
-}
-
-static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
-                       BPP_LDO_POWB, BPP_LDO_SUSPEND);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       /* To avoid too large in-rush current */
-       udelay(150);
-
-       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                       BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
-       if (err < 0)
-               return err;
-
-       udelay(150);
-
-       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                       BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
-       if (err < 0)
-               return err;
-
-       udelay(150);
-
-       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                       BPP_POWER_MASK, BPP_POWER_ON);
-       if (err < 0)
-               return err;
-
-       return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
-}
-
-static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                       BPP_POWER_MASK, BPP_POWER_OFF);
-       if (err < 0)
-               return err;
-
-       return rtsx_pci_write_register(pcr, LDO_CTL,
-                       BPP_LDO_POWB, BPP_LDO_SUSPEND);
-}
-
-static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage,
-               int bpp_tuned18_shift, int bpp_asic_1v8)
-{
-       u8 mask, val;
-       int err;
-
-       mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK;
-       if (voltage == OUTPUT_3V3) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
-               if (err < 0)
-                       return err;
-               val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3;
-       } else if (voltage == OUTPUT_1V8) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
-               if (err < 0)
-                       return err;
-               val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8;
-       } else {
-               return -EINVAL;
-       }
-
-       return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
-}
-
-static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       return rtl8411_do_switch_output_voltage(pcr, voltage,
-                       BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8);
-}
-
-static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       return rtl8411_do_switch_output_voltage(pcr, voltage,
-                       BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0);
-}
-
-static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
-{
-       unsigned int card_exist;
-
-       card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
-       card_exist &= CARD_EXIST;
-       if (!card_exist) {
-               /* Enable card CD */
-               rtsx_pci_write_register(pcr, CD_PAD_CTL,
-                               CD_DISABLE_MASK, CD_ENABLE);
-               /* Enable card interrupt */
-               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
-               return 0;
-       }
-
-       if (hweight32(card_exist) > 1) {
-               rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                               BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
-               msleep(100);
-
-               card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
-               if (card_exist & MS_EXIST)
-                       card_exist = MS_EXIST;
-               else if (card_exist & SD_EXIST)
-                       card_exist = SD_EXIST;
-               else
-                       card_exist = 0;
-
-               rtsx_pci_write_register(pcr, CARD_PWR_CTL,
-                               BPP_POWER_MASK, BPP_POWER_OFF);
-
-               pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n",
-                       card_exist);
-       }
-
-       if (card_exist & MS_EXIST) {
-               /* Disable SD interrupt */
-               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
-               rtsx_pci_write_register(pcr, CD_PAD_CTL,
-                               CD_DISABLE_MASK, MS_CD_EN_ONLY);
-       } else if (card_exist & SD_EXIST) {
-               /* Disable MS interrupt */
-               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
-               rtsx_pci_write_register(pcr, CD_PAD_CTL,
-                               CD_DISABLE_MASK, SD_CD_EN_ONLY);
-       }
-
-       return card_exist;
-}
-
-static int rtl8411_conv_clk_and_div_n(int input, int dir)
-{
-       int output;
-
-       if (dir == CLK_TO_DIV_N)
-               output = input * 4 / 5 - 2;
-       else
-               output = (input + 2) * 5 / 4;
-
-       return output;
-}
-
-static const struct pcr_ops rtl8411_pcr_ops = {
-       .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
-       .extra_init_hw = rtl8411_extra_init_hw,
-       .optimize_phy = NULL,
-       .turn_on_led = rtl8411_turn_on_led,
-       .turn_off_led = rtl8411_turn_off_led,
-       .enable_auto_blink = rtl8411_enable_auto_blink,
-       .disable_auto_blink = rtl8411_disable_auto_blink,
-       .card_power_on = rtl8411_card_power_on,
-       .card_power_off = rtl8411_card_power_off,
-       .switch_output_voltage = rtl8411_switch_output_voltage,
-       .cd_deglitch = rtl8411_cd_deglitch,
-       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
-       .force_power_down = rtl8411_force_power_down,
-};
-
-static const struct pcr_ops rtl8402_pcr_ops = {
-       .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
-       .extra_init_hw = rtl8411_extra_init_hw,
-       .optimize_phy = NULL,
-       .turn_on_led = rtl8411_turn_on_led,
-       .turn_off_led = rtl8411_turn_off_led,
-       .enable_auto_blink = rtl8411_enable_auto_blink,
-       .disable_auto_blink = rtl8411_disable_auto_blink,
-       .card_power_on = rtl8411_card_power_on,
-       .card_power_off = rtl8411_card_power_off,
-       .switch_output_voltage = rtl8402_switch_output_voltage,
-       .cd_deglitch = rtl8411_cd_deglitch,
-       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
-       .force_power_down = rtl8411_force_power_down,
-};
-
-static const struct pcr_ops rtl8411b_pcr_ops = {
-       .fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
-       .extra_init_hw = rtl8411b_extra_init_hw,
-       .optimize_phy = NULL,
-       .turn_on_led = rtl8411_turn_on_led,
-       .turn_off_led = rtl8411_turn_off_led,
-       .enable_auto_blink = rtl8411_enable_auto_blink,
-       .disable_auto_blink = rtl8411_disable_auto_blink,
-       .card_power_on = rtl8411_card_power_on,
-       .card_power_off = rtl8411_card_power_off,
-       .switch_output_voltage = rtl8411_switch_output_voltage,
-       .cd_deglitch = rtl8411_cd_deglitch,
-       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
-       .force_power_down = rtl8411_force_power_down,
-};
-
-/* SD Pull Control Enable:
- *     SD_DAT[3:0] ==> pull up
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull up
- *     SD_CMD      ==> pull up
- *     SD_CLK      ==> pull down
- */
-static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
-       0,
-};
-
-/* SD Pull Control Disable:
- *     SD_DAT[3:0] ==> pull down
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull down
- *     SD_CMD      ==> pull down
- *     SD_CLK      ==> pull down
- */
-static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
-       0,
-};
-
-/* MS Pull Control Enable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
-       0,
-};
-
-/* MS Pull Control Disable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
-       0,
-};
-
-static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
-       0,
-};
-
-static void rtl8411_init_common_params(struct rtsx_pcr *pcr)
-{
-       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
-       pcr->num_slots = 2;
-       pcr->flags = 0;
-       pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
-       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
-       pcr->aspm_en = ASPM_L1_EN;
-       pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
-       pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
-       pcr->ic_version = rtl8411_get_ic_version(pcr);
-}
-
-void rtl8411_init_params(struct rtsx_pcr *pcr)
-{
-       rtl8411_init_common_params(pcr);
-       pcr->ops = &rtl8411_pcr_ops;
-       set_pull_ctrl_tables(pcr, rtl8411);
-}
-
-void rtl8411b_init_params(struct rtsx_pcr *pcr)
-{
-       rtl8411_init_common_params(pcr);
-       pcr->ops = &rtl8411b_pcr_ops;
-       if (rtl8411b_is_qfn48(pcr))
-               set_pull_ctrl_tables(pcr, rtl8411b_qfn48);
-       else
-               set_pull_ctrl_tables(pcr, rtl8411b_qfn64);
-}
-
-void rtl8402_init_params(struct rtsx_pcr *pcr)
-{
-       rtl8411_init_common_params(pcr);
-       pcr->ops = &rtl8402_pcr_ops;
-       set_pull_ctrl_tables(pcr, rtl8411);
-}
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
deleted file mode 100644 (file)
index b95beec..0000000
+++ /dev/null
@@ -1,277 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
-{
-       u8 val;
-
-       val = rtsx_pci_readb(pcr, 0x1C);
-       return val & 0x0F;
-}
-
-static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
-       if (rts5209_vendor_setting1_valid(reg)) {
-               if (rts5209_reg_check_ms_pmos(reg))
-                       pcr->flags |= PCR_MS_PMOS;
-               pcr->aspm_en = rts5209_reg_to_aspm(reg);
-       }
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
-
-       if (rts5209_vendor_setting2_valid(reg)) {
-               pcr->sd30_drive_sel_1v8 =
-                       rts5209_reg_to_sd30_drive_sel_1v8(reg);
-               pcr->sd30_drive_sel_3v3 =
-                       rts5209_reg_to_sd30_drive_sel_3v3(reg);
-               pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg);
-       }
-}
-
-static void rts5209_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
-}
-
-static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_init_cmd(pcr);
-
-       /* Turn off LED */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
-       /* Reset ASPM state to default value */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
-       /* Force CLKREQ# PIN to drive 0 to request clock */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
-       /* Configure GPIO as output */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
-       /* Configure driving */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
-                       0xFF, pcr->sd30_drive_sel_3v3);
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
-}
-
-static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
-}
-
-static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
-}
-
-static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
-}
-
-static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
-}
-
-static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-       u8 pwr_mask, partial_pwr_on, pwr_on;
-
-       pwr_mask = SD_POWER_MASK;
-       partial_pwr_on = SD_PARTIAL_POWER_ON;
-       pwr_on = SD_POWER_ON;
-
-       if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
-               pwr_mask = MS_POWER_MASK;
-               partial_pwr_on = MS_PARTIAL_POWER_ON;
-               pwr_on = MS_POWER_ON;
-       }
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       pwr_mask, partial_pwr_on);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x04);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       /* To avoid too large in-rush current */
-       udelay(150);
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x00);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       u8 pwr_mask, pwr_off;
-
-       pwr_mask = SD_POWER_MASK;
-       pwr_off = SD_POWER_OFF;
-
-       if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
-               pwr_mask = MS_POWER_MASK;
-               pwr_off = MS_POWER_OFF;
-       }
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x06);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       int err;
-
-       if (voltage == OUTPUT_3V3) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
-               if (err < 0)
-                       return err;
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
-               if (err < 0)
-                       return err;
-       } else if (voltage == OUTPUT_1V8) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
-               if (err < 0)
-                       return err;
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
-               if (err < 0)
-                       return err;
-       } else {
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static const struct pcr_ops rts5209_pcr_ops = {
-       .fetch_vendor_settings = rts5209_fetch_vendor_settings,
-       .extra_init_hw = rts5209_extra_init_hw,
-       .optimize_phy = rts5209_optimize_phy,
-       .turn_on_led = rts5209_turn_on_led,
-       .turn_off_led = rts5209_turn_off_led,
-       .enable_auto_blink = rts5209_enable_auto_blink,
-       .disable_auto_blink = rts5209_disable_auto_blink,
-       .card_power_on = rts5209_card_power_on,
-       .card_power_off = rts5209_card_power_off,
-       .switch_output_voltage = rts5209_switch_output_voltage,
-       .cd_deglitch = NULL,
-       .conv_clk_and_div_n = NULL,
-       .force_power_down = rts5209_force_power_down,
-};
-
-/* SD Pull Control Enable:
- *     SD_DAT[3:0] ==> pull up
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull up
- *     SD_CMD      ==> pull up
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
-       0,
-};
-
-/* SD Pull Control Disable:
- *     SD_DAT[3:0] ==> pull down
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull down
- *     SD_CMD      ==> pull down
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
-       0,
-};
-
-/* MS Pull Control Enable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-/* MS Pull Control Disable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-void rts5209_init_params(struct rtsx_pcr *pcr)
-{
-       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
-               EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
-       pcr->num_slots = 2;
-       pcr->ops = &rts5209_pcr_ops;
-
-       pcr->flags = 0;
-       pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
-       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
-       pcr->aspm_en = ASPM_L1_EN;
-       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16);
-       pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
-
-       pcr->ic_version = rts5209_get_ic_version(pcr);
-       pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
-       pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
-       pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
-       pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
-}
diff --git a/drivers/mfd/rts5227.c b/drivers/mfd/rts5227.c
deleted file mode 100644 (file)
index ff296a4..0000000
+++ /dev/null
@@ -1,374 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- *   Roger Tseng <rogerable@realtek.com>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
-{
-       u8 val;
-
-       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
-       return val & 0x0F;
-}
-
-static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
-{
-       u8 driving_3v3[4][3] = {
-               {0x13, 0x13, 0x13},
-               {0x96, 0x96, 0x96},
-               {0x7F, 0x7F, 0x7F},
-               {0x96, 0x96, 0x96},
-       };
-       u8 driving_1v8[4][3] = {
-               {0x99, 0x99, 0x99},
-               {0xAA, 0xAA, 0xAA},
-               {0xFE, 0xFE, 0xFE},
-               {0xB3, 0xB3, 0xB3},
-       };
-       u8 (*driving)[3], drive_sel;
-
-       if (voltage == OUTPUT_3V3) {
-               driving = driving_3v3;
-               drive_sel = pcr->sd30_drive_sel_3v3;
-       } else {
-               driving = driving_1v8;
-               drive_sel = pcr->sd30_drive_sel_1v8;
-       }
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
-                       0xFF, driving[drive_sel][0]);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
-                       0xFF, driving[drive_sel][1]);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
-                       0xFF, driving[drive_sel][2]);
-}
-
-static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
-       if (!rtsx_vendor_setting_valid(reg))
-               return;
-
-       pcr->aspm_en = rtsx_reg_to_aspm(reg);
-       pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
-       pcr->card_drive_sel &= 0x3F;
-       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
-       pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
-       if (rtsx_reg_check_reverse_socket(reg))
-               pcr->flags |= PCR_REVERSE_SOCKET;
-}
-
-static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       /* Set relink_time to 0 */
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
-
-       if (pm_state == HOST_ENTER_S3)
-               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10);
-
-       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
-}
-
-static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       u16 cap;
-
-       rtsx_pci_init_cmd(pcr);
-
-       /* Configure GPIO as output */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
-       /* Reset ASPM state to default value */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
-       /* Switch LDO3318 source from DV33 to card_3v3 */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
-       /* LED shine disabled, set initial shine cycle period */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
-       /* Configure LTR */
-       pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap);
-       if (cap & PCI_EXP_DEVCTL2_LTR_EN)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
-       /* Configure OBFF */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
-       /* Configure driving */
-       rts5227_fill_driving(pcr, OUTPUT_3V3);
-       /* Configure force_clock_req */
-       if (pcr->flags & PCR_REVERSE_SOCKET)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
-       else
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
-       if (err < 0)
-               return err;
-
-       /* Optimize RX sensitivity */
-       return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
-}
-
-static int rts5227_turn_on_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rts5227_turn_off_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_PARTIAL_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x02);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       /* To avoid too large in-rush current */
-       udelay(150);
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x06);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK | PMOS_STRG_MASK,
-                       SD_POWER_OFF | PMOS_STRG_400mA);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0X00);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       int err;
-
-       if (voltage == OUTPUT_3V3) {
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
-               if (err < 0)
-                       return err;
-       } else if (voltage == OUTPUT_1V8) {
-               err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
-               if (err < 0)
-                       return err;
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
-               if (err < 0)
-                       return err;
-       } else {
-               return -EINVAL;
-       }
-
-       /* set pad drive */
-       rtsx_pci_init_cmd(pcr);
-       rts5227_fill_driving(pcr, voltage);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static const struct pcr_ops rts5227_pcr_ops = {
-       .fetch_vendor_settings = rts5227_fetch_vendor_settings,
-       .extra_init_hw = rts5227_extra_init_hw,
-       .optimize_phy = rts5227_optimize_phy,
-       .turn_on_led = rts5227_turn_on_led,
-       .turn_off_led = rts5227_turn_off_led,
-       .enable_auto_blink = rts5227_enable_auto_blink,
-       .disable_auto_blink = rts5227_disable_auto_blink,
-       .card_power_on = rts5227_card_power_on,
-       .card_power_off = rts5227_card_power_off,
-       .switch_output_voltage = rts5227_switch_output_voltage,
-       .cd_deglitch = NULL,
-       .conv_clk_and_div_n = NULL,
-       .force_power_down = rts5227_force_power_down,
-};
-
-/* SD Pull Control Enable:
- *     SD_DAT[3:0] ==> pull up
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull up
- *     SD_CMD      ==> pull up
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5227_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
-       0,
-};
-
-/* SD Pull Control Disable:
- *     SD_DAT[3:0] ==> pull down
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull down
- *     SD_CMD      ==> pull down
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5227_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
-       0,
-};
-
-/* MS Pull Control Enable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5227_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-/* MS Pull Control Disable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5227_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-void rts5227_init_params(struct rtsx_pcr *pcr)
-{
-       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
-       pcr->num_slots = 2;
-       pcr->ops = &rts5227_pcr_ops;
-
-       pcr->flags = 0;
-       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
-       pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
-       pcr->aspm_en = ASPM_L1_EN;
-       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
-       pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
-
-       pcr->ic_version = rts5227_get_ic_version(pcr);
-       pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
-       pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
-       pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
-       pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
-
-       pcr->reg_pm_ctrl3 = PM_CTRL3;
-}
-
-static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
-               0x00);
-       if (err < 0)
-               return err;
-
-       if (is_version(pcr, 0x522A, IC_VER_A)) {
-               err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
-                       PHY_RCR2_INIT_27S);
-               if (err)
-                       return err;
-
-               rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
-               rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
-               rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
-               rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
-       }
-
-       return 0;
-}
-
-static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rts5227_extra_init_hw(pcr);
-
-       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
-               FUNC_FORCE_UPME_XMT_DBG);
-       rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
-       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
-       rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
-
-       return 0;
-}
-
-/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
- */
-static const struct pcr_ops rts522a_pcr_ops = {
-       .fetch_vendor_settings = rts5227_fetch_vendor_settings,
-       .extra_init_hw = rts522a_extra_init_hw,
-       .optimize_phy = rts522a_optimize_phy,
-       .turn_on_led = rts5227_turn_on_led,
-       .turn_off_led = rts5227_turn_off_led,
-       .enable_auto_blink = rts5227_enable_auto_blink,
-       .disable_auto_blink = rts5227_disable_auto_blink,
-       .card_power_on = rts5227_card_power_on,
-       .card_power_off = rts5227_card_power_off,
-       .switch_output_voltage = rts5227_switch_output_voltage,
-       .cd_deglitch = NULL,
-       .conv_clk_and_div_n = NULL,
-       .force_power_down = rts5227_force_power_down,
-};
-
-void rts522a_init_params(struct rtsx_pcr *pcr)
-{
-       rts5227_init_params(pcr);
-
-       pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
-}
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
deleted file mode 100644 (file)
index 9ed9dc8..0000000
+++ /dev/null
@@ -1,273 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
-{
-       u8 val;
-
-       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
-       return val & 0x0F;
-}
-
-static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
-       if (!rtsx_vendor_setting_valid(reg))
-               return;
-
-       pcr->aspm_en = rtsx_reg_to_aspm(reg);
-       pcr->sd30_drive_sel_1v8 =
-               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
-       pcr->card_drive_sel &= 0x3F;
-       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
-       pcr->sd30_drive_sel_3v3 =
-               map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
-}
-
-static void rts5229_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
-}
-
-static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_init_cmd(pcr);
-
-       /* Configure GPIO as output */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
-       /* Reset ASPM state to default value */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
-       /* Force CLKREQ# PIN to drive 0 to request clock */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
-       /* Switch LDO3318 source from DV33 to card_3v3 */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
-       /* LED shine disabled, set initial shine cycle period */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
-       /* Configure driving */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
-                       0xFF, pcr->sd30_drive_sel_3v3);
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
-{
-       /* Optimize RX sensitivity */
-       return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
-}
-
-static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_PARTIAL_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x02);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       /* To avoid too large in-rush current */
-       udelay(150);
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x06);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK | PMOS_STRG_MASK,
-                       SD_POWER_OFF | PMOS_STRG_400mA);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x00);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       int err;
-
-       if (voltage == OUTPUT_3V3) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
-               if (err < 0)
-                       return err;
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
-               if (err < 0)
-                       return err;
-       } else if (voltage == OUTPUT_1V8) {
-               err = rtsx_pci_write_register(pcr,
-                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
-               if (err < 0)
-                       return err;
-               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
-               if (err < 0)
-                       return err;
-       } else {
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static const struct pcr_ops rts5229_pcr_ops = {
-       .fetch_vendor_settings = rts5229_fetch_vendor_settings,
-       .extra_init_hw = rts5229_extra_init_hw,
-       .optimize_phy = rts5229_optimize_phy,
-       .turn_on_led = rts5229_turn_on_led,
-       .turn_off_led = rts5229_turn_off_led,
-       .enable_auto_blink = rts5229_enable_auto_blink,
-       .disable_auto_blink = rts5229_disable_auto_blink,
-       .card_power_on = rts5229_card_power_on,
-       .card_power_off = rts5229_card_power_off,
-       .switch_output_voltage = rts5229_switch_output_voltage,
-       .cd_deglitch = NULL,
-       .conv_clk_and_div_n = NULL,
-       .force_power_down = rts5229_force_power_down,
-};
-
-/* SD Pull Control Enable:
- *     SD_DAT[3:0] ==> pull up
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull up
- *     SD_CMD      ==> pull up
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
-       0,
-};
-
-/* For RTS5229 version C */
-static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
-       0,
-};
-
-/* SD Pull Control Disable:
- *     SD_DAT[3:0] ==> pull down
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull down
- *     SD_CMD      ==> pull down
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
-       0,
-};
-
-/* For RTS5229 version C */
-static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
-       0,
-};
-
-/* MS Pull Control Enable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-/* MS Pull Control Disable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-void rts5229_init_params(struct rtsx_pcr *pcr)
-{
-       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
-       pcr->num_slots = 2;
-       pcr->ops = &rts5229_pcr_ops;
-
-       pcr->flags = 0;
-       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
-       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
-       pcr->aspm_en = ASPM_L1_EN;
-       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
-       pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 6, 6);
-
-       pcr->ic_version = rts5229_get_ic_version(pcr);
-       if (pcr->ic_version == IC_VER_C) {
-               pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
-               pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
-       } else {
-               pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
-               pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
-       }
-       pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
-       pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
-}
diff --git a/drivers/mfd/rts5249.c b/drivers/mfd/rts5249.c
deleted file mode 100644 (file)
index 7fcf37b..0000000
+++ /dev/null
@@ -1,741 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/mfd/rtsx_pci.h>
-
-#include "rtsx_pcr.h"
-
-static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
-{
-       u8 val;
-
-       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
-       return val & 0x0F;
-}
-
-static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
-{
-       u8 driving_3v3[4][3] = {
-               {0x11, 0x11, 0x18},
-               {0x55, 0x55, 0x5C},
-               {0xFF, 0xFF, 0xFF},
-               {0x96, 0x96, 0x96},
-       };
-       u8 driving_1v8[4][3] = {
-               {0xC4, 0xC4, 0xC4},
-               {0x3C, 0x3C, 0x3C},
-               {0xFE, 0xFE, 0xFE},
-               {0xB3, 0xB3, 0xB3},
-       };
-       u8 (*driving)[3], drive_sel;
-
-       if (voltage == OUTPUT_3V3) {
-               driving = driving_3v3;
-               drive_sel = pcr->sd30_drive_sel_3v3;
-       } else {
-               driving = driving_1v8;
-               drive_sel = pcr->sd30_drive_sel_1v8;
-       }
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
-                       0xFF, driving[drive_sel][0]);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
-                       0xFF, driving[drive_sel][1]);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
-                       0xFF, driving[drive_sel][2]);
-}
-
-static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
-{
-       u32 reg;
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
-
-       if (!rtsx_vendor_setting_valid(reg)) {
-               pcr_dbg(pcr, "skip fetch vendor setting\n");
-               return;
-       }
-
-       pcr->aspm_en = rtsx_reg_to_aspm(reg);
-       pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
-       pcr->card_drive_sel &= 0x3F;
-       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
-
-       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
-       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
-       pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
-       if (rtsx_reg_check_reverse_socket(reg))
-               pcr->flags |= PCR_REVERSE_SOCKET;
-}
-
-static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       /* Set relink_time to 0 */
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
-       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
-
-       if (pm_state == HOST_ENTER_S3)
-               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3,
-                       D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);
-
-       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
-}
-
-static void rts5249_init_from_cfg(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &(pcr->option);
-       u32 lval;
-
-       if (CHK_PCI_PID(pcr, PID_524A))
-               rtsx_pci_read_config_dword(pcr,
-                       PCR_ASPM_SETTING_REG1, &lval);
-       else
-               rtsx_pci_read_config_dword(pcr,
-                       PCR_ASPM_SETTING_REG2, &lval);
-
-       if (lval & ASPM_L1_1_EN_MASK)
-               rtsx_set_dev_flag(pcr, ASPM_L1_1_EN);
-
-       if (lval & ASPM_L1_2_EN_MASK)
-               rtsx_set_dev_flag(pcr, ASPM_L1_2_EN);
-
-       if (lval & PM_L1_1_EN_MASK)
-               rtsx_set_dev_flag(pcr, PM_L1_1_EN);
-
-       if (lval & PM_L1_2_EN_MASK)
-               rtsx_set_dev_flag(pcr, PM_L1_2_EN);
-
-       if (option->ltr_en) {
-               u16 val;
-
-               pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val);
-               if (val & PCI_EXP_DEVCTL2_LTR_EN) {
-                       option->ltr_enabled = true;
-                       option->ltr_active = true;
-                       rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
-               } else {
-                       option->ltr_enabled = false;
-               }
-       }
-}
-
-static int rts5249_init_from_hw(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &(pcr->option);
-
-       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
-                               | PM_L1_1_EN | PM_L1_2_EN))
-               option->force_clkreq_0 = false;
-       else
-               option->force_clkreq_0 = true;
-
-       return 0;
-}
-
-static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &(pcr->option);
-
-       rts5249_init_from_cfg(pcr);
-       rts5249_init_from_hw(pcr);
-
-       rtsx_pci_init_cmd(pcr);
-
-       /* Rest L1SUB Config */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00);
-       /* Configure GPIO as output */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
-       /* Reset ASPM state to default value */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
-       /* Switch LDO3318 source from DV33 to card_3v3 */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
-       /* LED shine disabled, set initial shine cycle period */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
-       /* Configure driving */
-       rts5249_fill_driving(pcr, OUTPUT_3V3);
-       if (pcr->flags & PCR_REVERSE_SOCKET)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0);
-       else
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
-
-       /*
-        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
-        * to drive low, and we forcibly request clock.
-        */
-       if (option->force_clkreq_0)
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
-                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
-       else
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
-                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
-
-       return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
-}
-
-static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
-       if (err < 0)
-               return err;
-
-       err = rtsx_pci_write_phy_register(pcr, PHY_REV,
-                       PHY_REV_RESV | PHY_REV_RXIDLE_LATCHED |
-                       PHY_REV_P1_EN | PHY_REV_RXIDLE_EN |
-                       PHY_REV_CLKREQ_TX_EN | PHY_REV_RX_PWST |
-                       PHY_REV_CLKREQ_DT_1_0 | PHY_REV_STOP_CLKRD |
-                       PHY_REV_STOP_CLKWR);
-       if (err < 0)
-               return err;
-
-       msleep(1);
-
-       err = rtsx_pci_write_phy_register(pcr, PHY_BPCR,
-                       PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL |
-                       PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
-       if (err < 0)
-               return err;
-
-       err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
-                       PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
-                       PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
-                       PHY_PCR_RSSI_EN | PHY_PCR_RX10K);
-       if (err < 0)
-               return err;
-
-       err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
-                       PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
-                       PHY_RCR2_CDR_SR_2 | PHY_RCR2_FREQSEL_12 |
-                       PHY_RCR2_CDR_SC_12P | PHY_RCR2_CALIB_LATE);
-       if (err < 0)
-               return err;
-
-       err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
-                       PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
-                       PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
-                       PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER |
-                       PHY_FLD4_BER_CHK_EN);
-       if (err < 0)
-               return err;
-       err = rtsx_pci_write_phy_register(pcr, PHY_RDR,
-                       PHY_RDR_RXDSEL_1_9 | PHY_SSC_AUTO_PWD);
-       if (err < 0)
-               return err;
-       err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
-                       PHY_RCR1_ADP_TIME_4 | PHY_RCR1_VCO_COARSE);
-       if (err < 0)
-               return err;
-       err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
-                       PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 |
-                       PHY_FLD3_RXDELINK);
-       if (err < 0)
-               return err;
-
-       return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
-                       PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
-                       PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
-                       PHY_TUNE_TUNED12 | PHY_TUNE_TUNEA12);
-}
-
-static int rtsx_base_turn_on_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
-}
-
-static int rtsx_base_turn_off_led(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
-}
-
-static int rtsx_base_enable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
-}
-
-static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr)
-{
-       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
-}
-
-static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       int err;
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x02);
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       msleep(5);
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_VCC_POWER_ON);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x06);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
-                       SD_POWER_MASK, SD_POWER_OFF);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
-                       LDO3318_PWR_MASK, 0x00);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       int err;
-       u16 append;
-
-       switch (voltage) {
-       case OUTPUT_3V3:
-               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
-                       PHY_TUNE_VOLTAGE_3V3);
-               if (err < 0)
-                       return err;
-               break;
-       case OUTPUT_1V8:
-               append = PHY_TUNE_D18_1V8;
-               if (CHK_PCI_PID(pcr, 0x5249)) {
-                       err = rtsx_pci_update_phy(pcr, PHY_BACR,
-                               PHY_BACR_BASIC_MASK, 0);
-                       if (err < 0)
-                               return err;
-                       append = PHY_TUNE_D18_1V7;
-               }
-
-               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
-                       append);
-               if (err < 0)
-                       return err;
-               break;
-       default:
-               pcr_dbg(pcr, "unknown output voltage %d\n", voltage);
-               return -EINVAL;
-       }
-
-       /* set pad drive */
-       rtsx_pci_init_cmd(pcr);
-       rts5249_fill_driving(pcr, voltage);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable)
-{
-       struct rtsx_cr_option *option = &pcr->option;
-       u8 val = 0;
-
-       if (pcr->aspm_enabled == enable)
-               return;
-
-       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
-               if (enable)
-                       val = pcr->aspm_en;
-               rtsx_pci_update_cfg_byte(pcr,
-                       pcr->pcie_cap + PCI_EXP_LNKCTL,
-                       ASPM_MASK_NEG, val);
-       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
-               u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0;
-
-               if (!enable)
-                       val = FORCE_ASPM_CTL0;
-               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
-       }
-
-       pcr->aspm_enabled = enable;
-}
-
-static const struct pcr_ops rts5249_pcr_ops = {
-       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
-       .extra_init_hw = rts5249_extra_init_hw,
-       .optimize_phy = rts5249_optimize_phy,
-       .turn_on_led = rtsx_base_turn_on_led,
-       .turn_off_led = rtsx_base_turn_off_led,
-       .enable_auto_blink = rtsx_base_enable_auto_blink,
-       .disable_auto_blink = rtsx_base_disable_auto_blink,
-       .card_power_on = rtsx_base_card_power_on,
-       .card_power_off = rtsx_base_card_power_off,
-       .switch_output_voltage = rtsx_base_switch_output_voltage,
-       .force_power_down = rtsx_base_force_power_down,
-       .set_aspm = rts5249_set_aspm,
-};
-
-/* SD Pull Control Enable:
- *     SD_DAT[3:0] ==> pull up
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull up
- *     SD_CMD      ==> pull up
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
-       0,
-};
-
-/* SD Pull Control Disable:
- *     SD_DAT[3:0] ==> pull down
- *     SD_CD       ==> pull up
- *     SD_WP       ==> pull down
- *     SD_CMD      ==> pull down
- *     SD_CLK      ==> pull down
- */
-static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
-       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
-       0,
-};
-
-/* MS Pull Control Enable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-/* MS Pull Control Disable:
- *     MS CD       ==> pull up
- *     others      ==> pull down
- */
-static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
-       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
-       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
-       0,
-};
-
-void rts5249_init_params(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &(pcr->option);
-
-       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
-       pcr->num_slots = 2;
-       pcr->ops = &rts5249_pcr_ops;
-
-       pcr->flags = 0;
-       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
-       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
-       pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
-       pcr->aspm_en = ASPM_L1_EN;
-       pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
-       pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
-
-       pcr->ic_version = rts5249_get_ic_version(pcr);
-       pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
-       pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
-       pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
-       pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
-
-       pcr->reg_pm_ctrl3 = PM_CTRL3;
-
-       option->dev_flags = (LTR_L1SS_PWR_GATE_CHECK_CARD_EN
-                               | LTR_L1SS_PWR_GATE_EN);
-       option->ltr_en = true;
-
-       /* Init latency of active, idle, L1OFF to 60us, 300us, 3ms */
-       option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF;
-       option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF;
-       option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF;
-       option->dev_aspm_mode = DEV_ASPM_DYNAMIC;
-       option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF;
-       option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEF;
-       option->ltr_l1off_snooze_sspwrgate =
-               LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF;
-}
-
-static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
-       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
-
-       return __rtsx_pci_write_phy_register(pcr, addr, val);
-}
-
-static int rts524a_read_phy(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
-       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
-
-       return __rtsx_pci_read_phy_register(pcr, addr, val);
-}
-
-static int rts524a_optimize_phy(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
-               D3_DELINK_MODE_EN, 0x00);
-       if (err < 0)
-               return err;
-
-       rtsx_pci_write_phy_register(pcr, PHY_PCR,
-               PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
-               PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | PHY_PCR_RSSI_EN);
-       rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
-               PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
-
-       if (is_version(pcr, 0x524A, IC_VER_A)) {
-               rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
-                       PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
-               rtsx_pci_write_phy_register(pcr, PHY_SSCCR2,
-                       PHY_SSCCR2_PLL_NCODE | PHY_SSCCR2_TIME0 |
-                       PHY_SSCCR2_TIME2_WIDTH);
-               rtsx_pci_write_phy_register(pcr, PHY_ANA1A,
-                       PHY_ANA1A_TXR_LOOPBACK | PHY_ANA1A_RXT_BIST |
-                       PHY_ANA1A_TXR_BIST | PHY_ANA1A_REV);
-               rtsx_pci_write_phy_register(pcr, PHY_ANA1D,
-                       PHY_ANA1D_DEBUG_ADDR);
-               rtsx_pci_write_phy_register(pcr, PHY_DIG1E,
-                       PHY_DIG1E_REV | PHY_DIG1E_D0_X_D1 |
-                       PHY_DIG1E_RX_ON_HOST | PHY_DIG1E_RCLK_REF_HOST |
-                       PHY_DIG1E_RCLK_TX_EN_KEEP |
-                       PHY_DIG1E_RCLK_TX_TERM_KEEP |
-                       PHY_DIG1E_RCLK_RX_EIDLE_ON | PHY_DIG1E_TX_TERM_KEEP |
-                       PHY_DIG1E_RX_TERM_KEEP | PHY_DIG1E_TX_EN_KEEP |
-                       PHY_DIG1E_RX_EN_KEEP);
-       }
-
-       rtsx_pci_write_phy_register(pcr, PHY_ANA08,
-               PHY_ANA08_RX_EQ_DCGAIN | PHY_ANA08_SEL_RX_EN |
-               PHY_ANA08_RX_EQ_VAL | PHY_ANA08_SCP | PHY_ANA08_SEL_IPI);
-
-       return 0;
-}
-
-static int rts524a_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rts5249_extra_init_hw(pcr);
-
-       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL,
-               FORCE_ASPM_L1_EN, FORCE_ASPM_L1_EN);
-       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
-       rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_VCC_LMT_EN,
-               LDO_VCC_LMT_EN);
-       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
-       if (is_version(pcr, 0x524A, IC_VER_A)) {
-               rtsx_pci_write_register(pcr, LDO_DV18_CFG,
-                       LDO_DV18_SR_MASK, LDO_DV18_SR_DF);
-               rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
-                       LDO_VCC_REF_TUNE_MASK, LDO_VCC_REF_1V2);
-               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
-                       LDO_VIO_REF_TUNE_MASK, LDO_VIO_REF_1V2);
-               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
-                       LDO_VIO_SR_MASK, LDO_VIO_SR_DF);
-               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
-                       LDO_REF12_TUNE_MASK, LDO_REF12_TUNE_DF);
-               rtsx_pci_write_register(pcr, SD40_LDO_CTL1,
-                       SD40_VIO_TUNE_MASK, SD40_VIO_TUNE_1V7);
-       }
-
-       return 0;
-}
-
-static void rts5250_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)
-{
-       struct rtsx_cr_option *option = &(pcr->option);
-
-       u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR);
-       int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST);
-       int aspm_L1_1, aspm_L1_2;
-       u8 val = 0;
-
-       aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN);
-       aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN);
-
-       if (active) {
-               /* Run, latency: 60us */
-               if (aspm_L1_1)
-                       val = option->ltr_l1off_snooze_sspwrgate;
-       } else {
-               /* L1off, latency: 300us */
-               if (aspm_L1_2)
-                       val = option->ltr_l1off_sspwrgate;
-       }
-
-       if (aspm_L1_1 || aspm_L1_2) {
-               if (rtsx_check_dev_flag(pcr,
-                                       LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) {
-                       if (card_exist)
-                               val &= ~L1OFF_MBIAS2_EN_5250;
-                       else
-                               val |= L1OFF_MBIAS2_EN_5250;
-               }
-       }
-       rtsx_set_l1off_sub(pcr, val);
-}
-
-static const struct pcr_ops rts524a_pcr_ops = {
-       .write_phy = rts524a_write_phy,
-       .read_phy = rts524a_read_phy,
-       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
-       .extra_init_hw = rts524a_extra_init_hw,
-       .optimize_phy = rts524a_optimize_phy,
-       .turn_on_led = rtsx_base_turn_on_led,
-       .turn_off_led = rtsx_base_turn_off_led,
-       .enable_auto_blink = rtsx_base_enable_auto_blink,
-       .disable_auto_blink = rtsx_base_disable_auto_blink,
-       .card_power_on = rtsx_base_card_power_on,
-       .card_power_off = rtsx_base_card_power_off,
-       .switch_output_voltage = rtsx_base_switch_output_voltage,
-       .force_power_down = rtsx_base_force_power_down,
-       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
-       .set_aspm = rts5249_set_aspm,
-};
-
-void rts524a_init_params(struct rtsx_pcr *pcr)
-{
-       rts5249_init_params(pcr);
-       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
-       pcr->option.ltr_l1off_snooze_sspwrgate =
-               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
-
-       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
-       pcr->ops = &rts524a_pcr_ops;
-}
-
-static int rts525a_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
-               LDO_VCC_TUNE_MASK, LDO_VCC_3V3);
-       return rtsx_base_card_power_on(pcr, card);
-}
-
-static int rts525a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
-{
-       switch (voltage) {
-       case OUTPUT_3V3:
-               rtsx_pci_write_register(pcr, LDO_CONFIG2,
-                       LDO_D3318_MASK, LDO_D3318_33V);
-               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0);
-               break;
-       case OUTPUT_1V8:
-               rtsx_pci_write_register(pcr, LDO_CONFIG2,
-                       LDO_D3318_MASK, LDO_D3318_18V);
-               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8,
-                       SD_IO_USING_1V8);
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       rtsx_pci_init_cmd(pcr);
-       rts5249_fill_driving(pcr, voltage);
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-static int rts525a_optimize_phy(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
-               D3_DELINK_MODE_EN, 0x00);
-       if (err < 0)
-               return err;
-
-       rtsx_pci_write_phy_register(pcr, _PHY_FLD0,
-               _PHY_FLD0_CLK_REQ_20C | _PHY_FLD0_RX_IDLE_EN |
-               _PHY_FLD0_BIT_ERR_RSTN | _PHY_FLD0_BER_COUNT |
-               _PHY_FLD0_BER_TIMER | _PHY_FLD0_CHECK_EN);
-
-       rtsx_pci_write_phy_register(pcr, _PHY_ANA03,
-               _PHY_ANA03_TIMER_MAX | _PHY_ANA03_OOBS_DEB_EN |
-               _PHY_CMU_DEBUG_EN);
-
-       if (is_version(pcr, 0x525A, IC_VER_A))
-               rtsx_pci_write_phy_register(pcr, _PHY_REV0,
-                       _PHY_REV0_FILTER_OUT | _PHY_REV0_CDR_BYPASS_PFD |
-                       _PHY_REV0_CDR_RX_IDLE_BYPASS);
-
-       return 0;
-}
-
-static int rts525a_extra_init_hw(struct rtsx_pcr *pcr)
-{
-       rts5249_extra_init_hw(pcr);
-
-       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
-       if (is_version(pcr, 0x525A, IC_VER_A)) {
-               rtsx_pci_write_register(pcr, L1SUB_CONFIG2,
-                       L1SUB_AUTO_CFG, L1SUB_AUTO_CFG);
-               rtsx_pci_write_register(pcr, RREF_CFG,
-                       RREF_VBGSEL_MASK, RREF_VBGSEL_1V25);
-               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
-                       LDO_VIO_TUNE_MASK, LDO_VIO_1V7);
-               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
-                       LDO_D12_TUNE_MASK, LDO_D12_TUNE_DF);
-               rtsx_pci_write_register(pcr, LDO_AV12S_CFG,
-                       LDO_AV12S_TUNE_MASK, LDO_AV12S_TUNE_DF);
-               rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
-                       LDO_VCC_LMTVTH_MASK, LDO_VCC_LMTVTH_2A);
-               rtsx_pci_write_register(pcr, OOBS_CONFIG,
-                       OOBS_AUTOK_DIS | OOBS_VAL_MASK, 0x89);
-       }
-
-       return 0;
-}
-
-static const struct pcr_ops rts525a_pcr_ops = {
-       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
-       .extra_init_hw = rts525a_extra_init_hw,
-       .optimize_phy = rts525a_optimize_phy,
-       .turn_on_led = rtsx_base_turn_on_led,
-       .turn_off_led = rtsx_base_turn_off_led,
-       .enable_auto_blink = rtsx_base_enable_auto_blink,
-       .disable_auto_blink = rtsx_base_disable_auto_blink,
-       .card_power_on = rts525a_card_power_on,
-       .card_power_off = rtsx_base_card_power_off,
-       .switch_output_voltage = rts525a_switch_output_voltage,
-       .force_power_down = rtsx_base_force_power_down,
-       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
-       .set_aspm = rts5249_set_aspm,
-};
-
-void rts525a_init_params(struct rtsx_pcr *pcr)
-{
-       rts5249_init_params(pcr);
-       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
-       pcr->option.ltr_l1off_snooze_sspwrgate =
-               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
-
-       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
-       pcr->ops = &rts525a_pcr_ops;
-}
-
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
deleted file mode 100644 (file)
index c3ed885..0000000
+++ /dev/null
@@ -1,1572 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#include <linux/pci.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/highmem.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/rtsx_pci.h>
-#include <linux/mmc/card.h>
-#include <asm/unaligned.h>
-
-#include "rtsx_pcr.h"
-
-static bool msi_en = true;
-module_param(msi_en, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(msi_en, "Enable MSI");
-
-static DEFINE_IDR(rtsx_pci_idr);
-static DEFINE_SPINLOCK(rtsx_pci_lock);
-
-static struct mfd_cell rtsx_pcr_cells[] = {
-       [RTSX_SD_CARD] = {
-               .name = DRV_NAME_RTSX_PCI_SDMMC,
-       },
-       [RTSX_MS_CARD] = {
-               .name = DRV_NAME_RTSX_PCI_MS,
-       },
-};
-
-static const struct pci_device_id rtsx_pci_ids[] = {
-       { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
-       { 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
-
-static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
-               0xFC, pcr->aspm_en);
-}
-
-static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
-               0xFC, 0);
-}
-
-int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
-{
-       rtsx_pci_write_register(pcr, MSGTXDATA0,
-                               MASK_8_BIT_DEF, (u8) (latency & 0xFF));
-       rtsx_pci_write_register(pcr, MSGTXDATA1,
-                               MASK_8_BIT_DEF, (u8)((latency >> 8) & 0xFF));
-       rtsx_pci_write_register(pcr, MSGTXDATA2,
-                               MASK_8_BIT_DEF, (u8)((latency >> 16) & 0xFF));
-       rtsx_pci_write_register(pcr, MSGTXDATA3,
-                               MASK_8_BIT_DEF, (u8)((latency >> 24) & 0xFF));
-       rtsx_pci_write_register(pcr, LTR_CTL, LTR_TX_EN_MASK |
-               LTR_LATENCY_MODE_MASK, LTR_TX_EN_1 | LTR_LATENCY_MODE_SW);
-
-       return 0;
-}
-
-int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
-{
-       if (pcr->ops->set_ltr_latency)
-               return pcr->ops->set_ltr_latency(pcr, latency);
-       else
-               return rtsx_comm_set_ltr_latency(pcr, latency);
-}
-
-static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable)
-{
-       struct rtsx_cr_option *option = &pcr->option;
-
-       if (pcr->aspm_enabled == enable)
-               return;
-
-       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
-               if (enable)
-                       rtsx_pci_enable_aspm(pcr);
-               else
-                       rtsx_pci_disable_aspm(pcr);
-       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
-               u8 mask = FORCE_ASPM_VAL_MASK;
-               u8 val = 0;
-
-               if (enable)
-                       val = pcr->aspm_en;
-               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL,  mask, val);
-       }
-
-       pcr->aspm_enabled = enable;
-}
-
-static void rtsx_disable_aspm(struct rtsx_pcr *pcr)
-{
-       if (pcr->ops->set_aspm)
-               pcr->ops->set_aspm(pcr, false);
-       else
-               rtsx_comm_set_aspm(pcr, false);
-}
-
-int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val)
-{
-       rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, val);
-
-       return 0;
-}
-
-void rtsx_set_l1off_sub_cfg_d0(struct rtsx_pcr *pcr, int active)
-{
-       if (pcr->ops->set_l1off_cfg_sub_d0)
-               pcr->ops->set_l1off_cfg_sub_d0(pcr, active);
-}
-
-static void rtsx_comm_pm_full_on(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &pcr->option;
-
-       rtsx_disable_aspm(pcr);
-
-       if (option->ltr_enabled)
-               rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
-
-       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
-               rtsx_set_l1off_sub_cfg_d0(pcr, 1);
-}
-
-void rtsx_pm_full_on(struct rtsx_pcr *pcr)
-{
-       if (pcr->ops->full_on)
-               pcr->ops->full_on(pcr);
-       else
-               rtsx_comm_pm_full_on(pcr);
-}
-
-void rtsx_pci_start_run(struct rtsx_pcr *pcr)
-{
-       /* If pci device removed, don't queue idle work any more */
-       if (pcr->remove_pci)
-               return;
-
-       if (pcr->state != PDEV_STAT_RUN) {
-               pcr->state = PDEV_STAT_RUN;
-               if (pcr->ops->enable_auto_blink)
-                       pcr->ops->enable_auto_blink(pcr);
-               rtsx_pm_full_on(pcr);
-       }
-
-       mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_start_run);
-
-int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data)
-{
-       int i;
-       u32 val = HAIMR_WRITE_START;
-
-       val |= (u32)(addr & 0x3FFF) << 16;
-       val |= (u32)mask << 8;
-       val |= (u32)data;
-
-       rtsx_pci_writel(pcr, RTSX_HAIMR, val);
-
-       for (i = 0; i < MAX_RW_REG_CNT; i++) {
-               val = rtsx_pci_readl(pcr, RTSX_HAIMR);
-               if ((val & HAIMR_TRANS_END) == 0) {
-                       if (data != (u8)val)
-                               return -EIO;
-                       return 0;
-               }
-       }
-
-       return -ETIMEDOUT;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_register);
-
-int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
-{
-       u32 val = HAIMR_READ_START;
-       int i;
-
-       val |= (u32)(addr & 0x3FFF) << 16;
-       rtsx_pci_writel(pcr, RTSX_HAIMR, val);
-
-       for (i = 0; i < MAX_RW_REG_CNT; i++) {
-               val = rtsx_pci_readl(pcr, RTSX_HAIMR);
-               if ((val & HAIMR_TRANS_END) == 0)
-                       break;
-       }
-
-       if (i >= MAX_RW_REG_CNT)
-               return -ETIMEDOUT;
-
-       if (data)
-               *data = (u8)(val & 0xFF);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
-
-int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
-       int err, i, finished = 0;
-       u8 tmp;
-
-       rtsx_pci_init_cmd(pcr);
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8));
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81);
-
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 100000; i++) {
-               err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
-               if (err < 0)
-                       return err;
-
-               if (!(tmp & 0x80)) {
-                       finished = 1;
-                       break;
-               }
-       }
-
-       if (!finished)
-               return -ETIMEDOUT;
-
-       return 0;
-}
-
-int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
-{
-       if (pcr->ops->write_phy)
-               return pcr->ops->write_phy(pcr, addr, val);
-
-       return __rtsx_pci_write_phy_register(pcr, addr, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
-
-int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
-       int err, i, finished = 0;
-       u16 data;
-       u8 *ptr, tmp;
-
-       rtsx_pci_init_cmd(pcr);
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80);
-
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       for (i = 0; i < 100000; i++) {
-               err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
-               if (err < 0)
-                       return err;
-
-               if (!(tmp & 0x80)) {
-                       finished = 1;
-                       break;
-               }
-       }
-
-       if (!finished)
-               return -ETIMEDOUT;
-
-       rtsx_pci_init_cmd(pcr);
-
-       rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0);
-       rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0);
-
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       ptr = rtsx_pci_get_cmd_data(pcr);
-       data = ((u16)ptr[1] << 8) | ptr[0];
-
-       if (val)
-               *val = data;
-
-       return 0;
-}
-
-int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
-{
-       if (pcr->ops->read_phy)
-               return pcr->ops->read_phy(pcr, addr, val);
-
-       return __rtsx_pci_read_phy_register(pcr, addr, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
-
-void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
-{
-       rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
-       rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
-
-       rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80);
-       rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_stop_cmd);
-
-void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
-               u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
-{
-       unsigned long flags;
-       u32 val = 0;
-       u32 *ptr = (u32 *)(pcr->host_cmds_ptr);
-
-       val |= (u32)(cmd_type & 0x03) << 30;
-       val |= (u32)(reg_addr & 0x3FFF) << 16;
-       val |= (u32)mask << 8;
-       val |= (u32)data;
-
-       spin_lock_irqsave(&pcr->lock, flags);
-       ptr += pcr->ci;
-       if (pcr->ci < (HOST_CMDS_BUF_LEN / 4)) {
-               put_unaligned_le32(val, ptr);
-               ptr++;
-               pcr->ci++;
-       }
-       spin_unlock_irqrestore(&pcr->lock, flags);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_add_cmd);
-
-void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr)
-{
-       u32 val = 1 << 31;
-
-       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
-       val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
-       /* Hardware Auto Response */
-       val |= 0x40000000;
-       rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd_no_wait);
-
-int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
-{
-       struct completion trans_done;
-       u32 val = 1 << 31;
-       long timeleft;
-       unsigned long flags;
-       int err = 0;
-
-       spin_lock_irqsave(&pcr->lock, flags);
-
-       /* set up data structures for the wakeup system */
-       pcr->done = &trans_done;
-       pcr->trans_result = TRANS_NOT_READY;
-       init_completion(&trans_done);
-
-       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
-       val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
-       /* Hardware Auto Response */
-       val |= 0x40000000;
-       rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
-
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       /* Wait for TRANS_OK_INT */
-       timeleft = wait_for_completion_interruptible_timeout(
-                       &trans_done, msecs_to_jiffies(timeout));
-       if (timeleft <= 0) {
-               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
-               err = -ETIMEDOUT;
-               goto finish_send_cmd;
-       }
-
-       spin_lock_irqsave(&pcr->lock, flags);
-       if (pcr->trans_result == TRANS_RESULT_FAIL)
-               err = -EINVAL;
-       else if (pcr->trans_result == TRANS_RESULT_OK)
-               err = 0;
-       else if (pcr->trans_result == TRANS_NO_DEVICE)
-               err = -ENODEV;
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-finish_send_cmd:
-       spin_lock_irqsave(&pcr->lock, flags);
-       pcr->done = NULL;
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       if ((err < 0) && (err != -ENODEV))
-               rtsx_pci_stop_cmd(pcr);
-
-       if (pcr->finish_me)
-               complete(pcr->finish_me);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd);
-
-static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
-               dma_addr_t addr, unsigned int len, int end)
-{
-       u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi;
-       u64 val;
-       u8 option = SG_VALID | SG_TRANS_DATA;
-
-       pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len);
-
-       if (end)
-               option |= SG_END;
-       val = ((u64)addr << 32) | ((u64)len << 12) | option;
-
-       put_unaligned_le64(val, ptr);
-       pcr->sgi++;
-}
-
-int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read, int timeout)
-{
-       int err = 0, count;
-
-       pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg);
-       count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
-       if (count < 1)
-               return -EINVAL;
-       pcr_dbg(pcr, "DMA mapping count: %d\n", count);
-
-       err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
-
-       rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
-
-int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read)
-{
-       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
-       if (pcr->remove_pci)
-               return -EINVAL;
-
-       if ((sglist == NULL) || (num_sg <= 0))
-               return -EINVAL;
-
-       return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
-
-void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read)
-{
-       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-
-       dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
-
-int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int count, bool read, int timeout)
-{
-       struct completion trans_done;
-       struct scatterlist *sg;
-       dma_addr_t addr;
-       long timeleft;
-       unsigned long flags;
-       unsigned int len;
-       int i, err = 0;
-       u32 val;
-       u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
-
-       if (pcr->remove_pci)
-               return -ENODEV;
-
-       if ((sglist == NULL) || (count < 1))
-               return -EINVAL;
-
-       val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
-       pcr->sgi = 0;
-       for_each_sg(sglist, sg, count, i) {
-               addr = sg_dma_address(sg);
-               len = sg_dma_len(sg);
-               rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
-       }
-
-       spin_lock_irqsave(&pcr->lock, flags);
-
-       pcr->done = &trans_done;
-       pcr->trans_result = TRANS_NOT_READY;
-       init_completion(&trans_done);
-       rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
-       rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
-
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       timeleft = wait_for_completion_interruptible_timeout(
-                       &trans_done, msecs_to_jiffies(timeout));
-       if (timeleft <= 0) {
-               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
-               err = -ETIMEDOUT;
-               goto out;
-       }
-
-       spin_lock_irqsave(&pcr->lock, flags);
-       if (pcr->trans_result == TRANS_RESULT_FAIL) {
-               err = -EILSEQ;
-               if (pcr->dma_error_count < RTS_MAX_TIMES_FREQ_REDUCTION)
-                       pcr->dma_error_count++;
-       }
-
-       else if (pcr->trans_result == TRANS_NO_DEVICE)
-               err = -ENODEV;
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-out:
-       spin_lock_irqsave(&pcr->lock, flags);
-       pcr->done = NULL;
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       if ((err < 0) && (err != -ENODEV))
-               rtsx_pci_stop_cmd(pcr);
-
-       if (pcr->finish_me)
-               complete(pcr->finish_me);
-
-       return err;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
-
-int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
-{
-       int err;
-       int i, j;
-       u16 reg;
-       u8 *ptr;
-
-       if (buf_len > 512)
-               buf_len = 512;
-
-       ptr = buf;
-       reg = PPBUF_BASE2;
-       for (i = 0; i < buf_len / 256; i++) {
-               rtsx_pci_init_cmd(pcr);
-
-               for (j = 0; j < 256; j++)
-                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
-
-               err = rtsx_pci_send_cmd(pcr, 250);
-               if (err < 0)
-                       return err;
-
-               memcpy(ptr, rtsx_pci_get_cmd_data(pcr), 256);
-               ptr += 256;
-       }
-
-       if (buf_len % 256) {
-               rtsx_pci_init_cmd(pcr);
-
-               for (j = 0; j < buf_len % 256; j++)
-                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
-
-               err = rtsx_pci_send_cmd(pcr, 250);
-               if (err < 0)
-                       return err;
-       }
-
-       memcpy(ptr, rtsx_pci_get_cmd_data(pcr), buf_len % 256);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_read_ppbuf);
-
-int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
-{
-       int err;
-       int i, j;
-       u16 reg;
-       u8 *ptr;
-
-       if (buf_len > 512)
-               buf_len = 512;
-
-       ptr = buf;
-       reg = PPBUF_BASE2;
-       for (i = 0; i < buf_len / 256; i++) {
-               rtsx_pci_init_cmd(pcr);
-
-               for (j = 0; j < 256; j++) {
-                       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                                       reg++, 0xFF, *ptr);
-                       ptr++;
-               }
-
-               err = rtsx_pci_send_cmd(pcr, 250);
-               if (err < 0)
-                       return err;
-       }
-
-       if (buf_len % 256) {
-               rtsx_pci_init_cmd(pcr);
-
-               for (j = 0; j < buf_len % 256; j++) {
-                       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                                       reg++, 0xFF, *ptr);
-                       ptr++;
-               }
-
-               err = rtsx_pci_send_cmd(pcr, 250);
-               if (err < 0)
-                       return err;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
-
-static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
-{
-       rtsx_pci_init_cmd(pcr);
-
-       while (*tbl & 0xFFFF0000) {
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
-                               (u16)(*tbl >> 16), 0xFF, (u8)(*tbl));
-               tbl++;
-       }
-
-       return rtsx_pci_send_cmd(pcr, 100);
-}
-
-int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
-{
-       const u32 *tbl;
-
-       if (card == RTSX_SD_CARD)
-               tbl = pcr->sd_pull_ctl_enable_tbl;
-       else if (card == RTSX_MS_CARD)
-               tbl = pcr->ms_pull_ctl_enable_tbl;
-       else
-               return -EINVAL;
-
-       return rtsx_pci_set_pull_ctl(pcr, tbl);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_enable);
-
-int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card)
-{
-       const u32 *tbl;
-
-       if (card == RTSX_SD_CARD)
-               tbl = pcr->sd_pull_ctl_disable_tbl;
-       else if (card == RTSX_MS_CARD)
-               tbl = pcr->ms_pull_ctl_disable_tbl;
-       else
-               return -EINVAL;
-
-
-       return rtsx_pci_set_pull_ctl(pcr, tbl);
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
-
-static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
-{
-       pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
-
-       if (pcr->num_slots > 1)
-               pcr->bier |= MS_INT_EN;
-
-       /* Enable Bus Interrupt */
-       rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
-
-       pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier);
-}
-
-static inline u8 double_ssc_depth(u8 depth)
-{
-       return ((depth > 1) ? (depth - 1) : depth);
-}
-
-static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
-{
-       if (div > CLK_DIV_1) {
-               if (ssc_depth > (div - 1))
-                       ssc_depth -= (div - 1);
-               else
-                       ssc_depth = SSC_DEPTH_4M;
-       }
-
-       return ssc_depth;
-}
-
-int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
-               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
-{
-       int err, clk;
-       u8 n, clk_divider, mcu_cnt, div;
-       static const u8 depth[] = {
-               [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
-               [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
-               [RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
-               [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K,
-               [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K,
-       };
-
-       if (initial_mode) {
-               /* We use 250k(around) here, in initial stage */
-               clk_divider = SD_CLK_DIVIDE_128;
-               card_clock = 30000000;
-       } else {
-               clk_divider = SD_CLK_DIVIDE_0;
-       }
-       err = rtsx_pci_write_register(pcr, SD_CFG1,
-                       SD_CLK_DIVIDE_MASK, clk_divider);
-       if (err < 0)
-               return err;
-
-       /* Reduce card clock by 20MHz each time a DMA transfer error occurs */
-       if (card_clock == UHS_SDR104_MAX_DTR &&
-           pcr->dma_error_count &&
-           PCI_PID(pcr) == RTS5227_DEVICE_ID)
-               card_clock = UHS_SDR104_MAX_DTR -
-                       (pcr->dma_error_count * 20000000);
-
-       card_clock /= 1000000;
-       pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock);
-
-       clk = card_clock;
-       if (!initial_mode && double_clk)
-               clk = card_clock * 2;
-       pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n",
-               clk, pcr->cur_clock);
-
-       if (clk == pcr->cur_clock)
-               return 0;
-
-       if (pcr->ops->conv_clk_and_div_n)
-               n = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
-       else
-               n = (u8)(clk - 2);
-       if ((clk <= 2) || (n > MAX_DIV_N_PCR))
-               return -EINVAL;
-
-       mcu_cnt = (u8)(125/clk + 3);
-       if (mcu_cnt > 15)
-               mcu_cnt = 15;
-
-       /* Make sure that the SSC clock div_n is not less than MIN_DIV_N_PCR */
-       div = CLK_DIV_1;
-       while ((n < MIN_DIV_N_PCR) && (div < CLK_DIV_8)) {
-               if (pcr->ops->conv_clk_and_div_n) {
-                       int dbl_clk = pcr->ops->conv_clk_and_div_n(n,
-                                       DIV_N_TO_CLK) * 2;
-                       n = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk,
-                                       CLK_TO_DIV_N);
-               } else {
-                       n = (n + 2) * 2 - 2;
-               }
-               div++;
-       }
-       pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
-
-       ssc_depth = depth[ssc_depth];
-       if (double_clk)
-               ssc_depth = double_ssc_depth(ssc_depth);
-
-       ssc_depth = revise_ssc_depth(ssc_depth, div);
-       pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth);
-
-       rtsx_pci_init_cmd(pcr);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
-                       CLK_LOW_FREQ, CLK_LOW_FREQ);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV,
-                       0xFF, (div << 4) | mcu_cnt);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2,
-                       SSC_DEPTH_MASK, ssc_depth);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
-       if (vpclk) {
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
-                               PHASE_NOT_RESET, 0);
-               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
-                               PHASE_NOT_RESET, PHASE_NOT_RESET);
-       }
-
-       err = rtsx_pci_send_cmd(pcr, 2000);
-       if (err < 0)
-               return err;
-
-       /* Wait SSC clock stable */
-       udelay(10);
-       err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
-       if (err < 0)
-               return err;
-
-       pcr->cur_clock = clk;
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_switch_clock);
-
-int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card)
-{
-       if (pcr->ops->card_power_on)
-               return pcr->ops->card_power_on(pcr, card);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_power_on);
-
-int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
-{
-       if (pcr->ops->card_power_off)
-               return pcr->ops->card_power_off(pcr, card);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
-
-int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
-{
-       static const unsigned int cd_mask[] = {
-               [RTSX_SD_CARD] = SD_EXIST,
-               [RTSX_MS_CARD] = MS_EXIST
-       };
-
-       if (!(pcr->flags & 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)
-               return pcr->ops->switch_output_voltage(pcr, voltage);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage);
-
-unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
-{
-       unsigned int val;
-
-       val = rtsx_pci_readl(pcr, RTSX_BIPR);
-       if (pcr->ops->cd_deglitch)
-               val = pcr->ops->cd_deglitch(pcr);
-
-       return val;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_card_exist);
-
-void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr)
-{
-       struct completion finish;
-
-       pcr->finish_me = &finish;
-       init_completion(&finish);
-
-       if (pcr->done)
-               complete(pcr->done);
-
-       if (!pcr->remove_pci)
-               rtsx_pci_stop_cmd(pcr);
-
-       wait_for_completion_interruptible_timeout(&finish,
-                       msecs_to_jiffies(2));
-       pcr->finish_me = NULL;
-}
-EXPORT_SYMBOL_GPL(rtsx_pci_complete_unfinished_transfer);
-
-static void rtsx_pci_card_detect(struct work_struct *work)
-{
-       struct delayed_work *dwork;
-       struct rtsx_pcr *pcr;
-       unsigned long flags;
-       unsigned int card_detect = 0, card_inserted, card_removed;
-       u32 irq_status;
-
-       dwork = to_delayed_work(work);
-       pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
-
-       pcr_dbg(pcr, "--> %s\n", __func__);
-
-       mutex_lock(&pcr->pcr_mutex);
-       spin_lock_irqsave(&pcr->lock, flags);
-
-       irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
-       pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status);
-
-       irq_status &= CARD_EXIST;
-       card_inserted = pcr->card_inserted & irq_status;
-       card_removed = pcr->card_removed;
-       pcr->card_inserted = 0;
-       pcr->card_removed = 0;
-
-       spin_unlock_irqrestore(&pcr->lock, flags);
-
-       if (card_inserted || card_removed) {
-               pcr_dbg(pcr, "card_inserted: 0x%x, card_removed: 0x%x\n",
-                       card_inserted, card_removed);
-
-               if (pcr->ops->cd_deglitch)
-                       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);
-
-       if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
-               pcr->slots[RTSX_SD_CARD].card_event(
-                               pcr->slots[RTSX_SD_CARD].p_dev);
-       if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event)
-               pcr->slots[RTSX_MS_CARD].card_event(
-                               pcr->slots[RTSX_MS_CARD].p_dev);
-}
-
-static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
-{
-       struct rtsx_pcr *pcr = dev_id;
-       u32 int_reg;
-
-       if (!pcr)
-               return IRQ_NONE;
-
-       spin_lock(&pcr->lock);
-
-       int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
-       /* Clear interrupt flag */
-       rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
-       if ((int_reg & pcr->bier) == 0) {
-               spin_unlock(&pcr->lock);
-               return IRQ_NONE;
-       }
-       if (int_reg == 0xFFFFFFFF) {
-               spin_unlock(&pcr->lock);
-               return IRQ_HANDLED;
-       }
-
-       int_reg &= (pcr->bier | 0x7FFFFF);
-
-       if (int_reg & SD_INT) {
-               if (int_reg & SD_EXIST) {
-                       pcr->card_inserted |= SD_EXIST;
-               } else {
-                       pcr->card_removed |= SD_EXIST;
-                       pcr->card_inserted &= ~SD_EXIST;
-               }
-               pcr->dma_error_count = 0;
-       }
-
-       if (int_reg & MS_INT) {
-               if (int_reg & MS_EXIST) {
-                       pcr->card_inserted |= MS_EXIST;
-               } else {
-                       pcr->card_removed |= MS_EXIST;
-                       pcr->card_inserted &= ~MS_EXIST;
-               }
-       }
-
-       if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
-               if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
-                       pcr->trans_result = TRANS_RESULT_FAIL;
-                       if (pcr->done)
-                               complete(pcr->done);
-               } else if (int_reg & TRANS_OK_INT) {
-                       pcr->trans_result = TRANS_RESULT_OK;
-                       if (pcr->done)
-                               complete(pcr->done);
-               }
-       }
-
-       if (pcr->card_inserted || pcr->card_removed)
-               schedule_delayed_work(&pcr->carddet_work,
-                               msecs_to_jiffies(200));
-
-       spin_unlock(&pcr->lock);
-       return IRQ_HANDLED;
-}
-
-static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
-{
-       pcr_dbg(pcr, "%s: pcr->msi_en = %d, pci->irq = %d\n",
-                       __func__, pcr->msi_en, pcr->pci->irq);
-
-       if (request_irq(pcr->pci->irq, rtsx_pci_isr,
-                       pcr->msi_en ? 0 : IRQF_SHARED,
-                       DRV_NAME_RTSX_PCI, pcr)) {
-               dev_err(&(pcr->pci->dev),
-                       "rtsx_sdmmc: unable to grab IRQ %d, disabling device\n",
-                       pcr->pci->irq);
-               return -1;
-       }
-
-       pcr->irq = pcr->pci->irq;
-       pci_intx(pcr->pci, !pcr->msi_en);
-
-       return 0;
-}
-
-static void rtsx_enable_aspm(struct rtsx_pcr *pcr)
-{
-       if (pcr->ops->set_aspm)
-               pcr->ops->set_aspm(pcr, true);
-       else
-               rtsx_comm_set_aspm(pcr, true);
-}
-
-static void rtsx_comm_pm_power_saving(struct rtsx_pcr *pcr)
-{
-       struct rtsx_cr_option *option = &pcr->option;
-
-       if (option->ltr_enabled) {
-               u32 latency = option->ltr_l1off_latency;
-
-               if (rtsx_check_dev_flag(pcr, L1_SNOOZE_TEST_EN))
-                       mdelay(option->l1_snooze_delay);
-
-               rtsx_set_ltr_latency(pcr, latency);
-       }
-
-       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
-               rtsx_set_l1off_sub_cfg_d0(pcr, 0);
-
-       rtsx_enable_aspm(pcr);
-}
-
-void rtsx_pm_power_saving(struct rtsx_pcr *pcr)
-{
-       if (pcr->ops->power_saving)
-               pcr->ops->power_saving(pcr);
-       else
-               rtsx_comm_pm_power_saving(pcr);
-}
-
-static void rtsx_pci_idle_work(struct work_struct *work)
-{
-       struct delayed_work *dwork = to_delayed_work(work);
-       struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
-
-       pcr_dbg(pcr, "--> %s\n", __func__);
-
-       mutex_lock(&pcr->pcr_mutex);
-
-       pcr->state = PDEV_STAT_IDLE;
-
-       if (pcr->ops->disable_auto_blink)
-               pcr->ops->disable_auto_blink(pcr);
-       if (pcr->ops->turn_off_led)
-               pcr->ops->turn_off_led(pcr);
-
-       rtsx_pm_power_saving(pcr);
-
-       mutex_unlock(&pcr->pcr_mutex);
-}
-
-#ifdef CONFIG_PM
-static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
-{
-       if (pcr->ops->turn_off_led)
-               pcr->ops->turn_off_led(pcr);
-
-       rtsx_pci_writel(pcr, RTSX_BIER, 0);
-       pcr->bier = 0;
-
-       rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
-       rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state);
-
-       if (pcr->ops->force_power_down)
-               pcr->ops->force_power_down(pcr, pm_state);
-}
-#endif
-
-static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP);
-       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
-
-       rtsx_pci_enable_bus_int(pcr);
-
-       /* Power on SSC */
-       err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0);
-       if (err < 0)
-               return err;
-
-       /* Wait SSC power stable */
-       udelay(200);
-
-       rtsx_pci_disable_aspm(pcr);
-       if (pcr->ops->optimize_phy) {
-               err = pcr->ops->optimize_phy(pcr);
-               if (err < 0)
-                       return err;
-       }
-
-       rtsx_pci_init_cmd(pcr);
-
-       /* Set mcu_cnt to 7 to ensure data can be sampled properly */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV, 0x07, 0x07);
-
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, HOST_SLEEP_STATE, 0x03, 0x00);
-       /* Disable card clock */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 0x1E, 0);
-       /* Reset delink mode */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
-       /* Card driving select */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DRIVE_SEL,
-                       0xFF, pcr->card_drive_sel);
-       /* Enable SSC Clock */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
-                       0xFF, SSC_8X_EN | SSC_SEL_4M);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12);
-       /* Disable cd_pwr_save */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10);
-       /* Clear Link Ready Interrupt */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
-                       LINK_RDY_INT, LINK_RDY_INT);
-       /* Enlarge the estimation window of PERST# glitch
-        * to reduce the chance of invalid card interrupt
-        */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PERST_GLITCH_WIDTH, 0xFF, 0x80);
-       /* Update RC oscillator to 400k
-        * bit[0] F_HIGH: for RC oscillator, Rst_value is 1'b1
-        *                1: 2M  0: 400k
-        */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RCCTL, 0x01, 0x00);
-       /* Set interrupt write clear
-        * bit 1: U_elbi_if_rd_clr_en
-        *      1: Enable ELBI interrupt[31:22] & [7:0] flag read clear
-        *      0: ELBI interrupt flag[31:22] & [7:0] only can be write clear
-        */
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, NFTS_TX_CTRL, 0x02, 0);
-
-       err = rtsx_pci_send_cmd(pcr, 100);
-       if (err < 0)
-               return err;
-
-       switch (PCI_PID(pcr)) {
-       case PID_5250:
-       case PID_524A:
-       case PID_525A:
-               rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1);
-               break;
-       default:
-               break;
-       }
-
-       /* Enable clk_request_n to enable clock power management */
-       rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
-       /* Enter L1 when host tx idle */
-       rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
-
-       if (pcr->ops->extra_init_hw) {
-               err = pcr->ops->extra_init_hw(pcr);
-               if (err < 0)
-                       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;
-}
-
-static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
-{
-       int err;
-
-       spin_lock_init(&pcr->lock);
-       mutex_init(&pcr->pcr_mutex);
-
-       switch (PCI_PID(pcr)) {
-       default:
-       case 0x5209:
-               rts5209_init_params(pcr);
-               break;
-
-       case 0x5229:
-               rts5229_init_params(pcr);
-               break;
-
-       case 0x5289:
-               rtl8411_init_params(pcr);
-               break;
-
-       case 0x5227:
-               rts5227_init_params(pcr);
-               break;
-
-       case 0x522A:
-               rts522a_init_params(pcr);
-               break;
-
-       case 0x5249:
-               rts5249_init_params(pcr);
-               break;
-
-       case 0x524A:
-               rts524a_init_params(pcr);
-               break;
-
-       case 0x525A:
-               rts525a_init_params(pcr);
-               break;
-
-       case 0x5287:
-               rtl8411b_init_params(pcr);
-               break;
-
-       case 0x5286:
-               rtl8402_init_params(pcr);
-               break;
-       }
-
-       pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
-                       PCI_PID(pcr), pcr->ic_version);
-
-       pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
-                       GFP_KERNEL);
-       if (!pcr->slots)
-               return -ENOMEM;
-
-       if (pcr->ops->fetch_vendor_settings)
-               pcr->ops->fetch_vendor_settings(pcr);
-
-       pcr_dbg(pcr, "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
-       pcr_dbg(pcr, "pcr->sd30_drive_sel_1v8 = 0x%x\n",
-                       pcr->sd30_drive_sel_1v8);
-       pcr_dbg(pcr, "pcr->sd30_drive_sel_3v3 = 0x%x\n",
-                       pcr->sd30_drive_sel_3v3);
-       pcr_dbg(pcr, "pcr->card_drive_sel = 0x%x\n",
-                       pcr->card_drive_sel);
-       pcr_dbg(pcr, "pcr->flags = 0x%x\n", pcr->flags);
-
-       pcr->state = PDEV_STAT_IDLE;
-       err = rtsx_pci_init_hw(pcr);
-       if (err < 0) {
-               kfree(pcr->slots);
-               return err;
-       }
-
-       return 0;
-}
-
-static int rtsx_pci_probe(struct pci_dev *pcidev,
-                         const struct pci_device_id *id)
-{
-       struct rtsx_pcr *pcr;
-       struct pcr_handle *handle;
-       u32 base, len;
-       int ret, i, bar = 0;
-
-       dev_dbg(&(pcidev->dev),
-               ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
-               pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
-               (int)pcidev->revision);
-
-       ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
-       if (ret < 0)
-               return ret;
-
-       ret = pci_enable_device(pcidev);
-       if (ret)
-               return ret;
-
-       ret = pci_request_regions(pcidev, DRV_NAME_RTSX_PCI);
-       if (ret)
-               goto disable;
-
-       pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
-       if (!pcr) {
-               ret = -ENOMEM;
-               goto release_pci;
-       }
-
-       handle = kzalloc(sizeof(*handle), GFP_KERNEL);
-       if (!handle) {
-               ret = -ENOMEM;
-               goto free_pcr;
-       }
-       handle->pcr = pcr;
-
-       idr_preload(GFP_KERNEL);
-       spin_lock(&rtsx_pci_lock);
-       ret = idr_alloc(&rtsx_pci_idr, pcr, 0, 0, GFP_NOWAIT);
-       if (ret >= 0)
-               pcr->id = ret;
-       spin_unlock(&rtsx_pci_lock);
-       idr_preload_end();
-       if (ret < 0)
-               goto free_handle;
-
-       pcr->pci = pcidev;
-       dev_set_drvdata(&pcidev->dev, handle);
-
-       if (CHK_PCI_PID(pcr, 0x525A))
-               bar = 1;
-       len = pci_resource_len(pcidev, bar);
-       base = pci_resource_start(pcidev, bar);
-       pcr->remap_addr = ioremap_nocache(base, len);
-       if (!pcr->remap_addr) {
-               ret = -ENOMEM;
-               goto free_handle;
-       }
-
-       pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
-                       RTSX_RESV_BUF_LEN, &(pcr->rtsx_resv_buf_addr),
-                       GFP_KERNEL);
-       if (pcr->rtsx_resv_buf == NULL) {
-               ret = -ENXIO;
-               goto unmap;
-       }
-       pcr->host_cmds_ptr = pcr->rtsx_resv_buf;
-       pcr->host_cmds_addr = pcr->rtsx_resv_buf_addr;
-       pcr->host_sg_tbl_ptr = pcr->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
-       pcr->host_sg_tbl_addr = pcr->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
-
-       pcr->card_inserted = 0;
-       pcr->card_removed = 0;
-       INIT_DELAYED_WORK(&pcr->carddet_work, rtsx_pci_card_detect);
-       INIT_DELAYED_WORK(&pcr->idle_work, rtsx_pci_idle_work);
-
-       pcr->msi_en = msi_en;
-       if (pcr->msi_en) {
-               ret = pci_enable_msi(pcidev);
-               if (ret)
-                       pcr->msi_en = false;
-       }
-
-       ret = rtsx_pci_acquire_irq(pcr);
-       if (ret < 0)
-               goto disable_msi;
-
-       pci_set_master(pcidev);
-       synchronize_irq(pcr->irq);
-
-       ret = rtsx_pci_init_chip(pcr);
-       if (ret < 0)
-               goto disable_irq;
-
-       for (i = 0; i < ARRAY_SIZE(rtsx_pcr_cells); i++) {
-               rtsx_pcr_cells[i].platform_data = handle;
-               rtsx_pcr_cells[i].pdata_size = sizeof(*handle);
-       }
-       ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
-                       ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
-       if (ret < 0)
-               goto disable_irq;
-
-       schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
-
-       return 0;
-
-disable_irq:
-       free_irq(pcr->irq, (void *)pcr);
-disable_msi:
-       if (pcr->msi_en)
-               pci_disable_msi(pcr->pci);
-       dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
-                       pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
-unmap:
-       iounmap(pcr->remap_addr);
-free_handle:
-       kfree(handle);
-free_pcr:
-       kfree(pcr);
-release_pci:
-       pci_release_regions(pcidev);
-disable:
-       pci_disable_device(pcidev);
-
-       return ret;
-}
-
-static void rtsx_pci_remove(struct pci_dev *pcidev)
-{
-       struct pcr_handle *handle = pci_get_drvdata(pcidev);
-       struct rtsx_pcr *pcr = handle->pcr;
-
-       pcr->remove_pci = true;
-
-       /* Disable interrupts at the pcr level */
-       spin_lock_irq(&pcr->lock);
-       rtsx_pci_writel(pcr, RTSX_BIER, 0);
-       pcr->bier = 0;
-       spin_unlock_irq(&pcr->lock);
-
-       cancel_delayed_work_sync(&pcr->carddet_work);
-       cancel_delayed_work_sync(&pcr->idle_work);
-
-       mfd_remove_devices(&pcidev->dev);
-
-       dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
-                       pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
-       free_irq(pcr->irq, (void *)pcr);
-       if (pcr->msi_en)
-               pci_disable_msi(pcr->pci);
-       iounmap(pcr->remap_addr);
-
-       pci_release_regions(pcidev);
-       pci_disable_device(pcidev);
-
-       spin_lock(&rtsx_pci_lock);
-       idr_remove(&rtsx_pci_idr, pcr->id);
-       spin_unlock(&rtsx_pci_lock);
-
-       kfree(pcr->slots);
-       kfree(pcr);
-       kfree(handle);
-
-       dev_dbg(&(pcidev->dev),
-               ": Realtek PCI-E Card Reader at %s [%04x:%04x] has been removed\n",
-               pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
-}
-
-#ifdef CONFIG_PM
-
-static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
-{
-       struct pcr_handle *handle;
-       struct rtsx_pcr *pcr;
-
-       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
-
-       handle = pci_get_drvdata(pcidev);
-       pcr = handle->pcr;
-
-       cancel_delayed_work(&pcr->carddet_work);
-       cancel_delayed_work(&pcr->idle_work);
-
-       mutex_lock(&pcr->pcr_mutex);
-
-       rtsx_pci_power_off(pcr, HOST_ENTER_S3);
-
-       pci_save_state(pcidev);
-       pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
-       pci_disable_device(pcidev);
-       pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
-
-       mutex_unlock(&pcr->pcr_mutex);
-       return 0;
-}
-
-static int rtsx_pci_resume(struct pci_dev *pcidev)
-{
-       struct pcr_handle *handle;
-       struct rtsx_pcr *pcr;
-       int ret = 0;
-
-       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
-
-       handle = pci_get_drvdata(pcidev);
-       pcr = handle->pcr;
-
-       mutex_lock(&pcr->pcr_mutex);
-
-       pci_set_power_state(pcidev, PCI_D0);
-       pci_restore_state(pcidev);
-       ret = pci_enable_device(pcidev);
-       if (ret)
-               goto out;
-       pci_set_master(pcidev);
-
-       ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00);
-       if (ret)
-               goto out;
-
-       ret = rtsx_pci_init_hw(pcr);
-       if (ret)
-               goto out;
-
-       schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
-
-out:
-       mutex_unlock(&pcr->pcr_mutex);
-       return ret;
-}
-
-static void rtsx_pci_shutdown(struct pci_dev *pcidev)
-{
-       struct pcr_handle *handle;
-       struct rtsx_pcr *pcr;
-
-       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
-
-       handle = pci_get_drvdata(pcidev);
-       pcr = handle->pcr;
-       rtsx_pci_power_off(pcr, HOST_ENTER_S1);
-
-       pci_disable_device(pcidev);
-       free_irq(pcr->irq, (void *)pcr);
-       if (pcr->msi_en)
-               pci_disable_msi(pcr->pci);
-}
-
-#else /* CONFIG_PM */
-
-#define rtsx_pci_suspend NULL
-#define rtsx_pci_resume NULL
-#define rtsx_pci_shutdown NULL
-
-#endif /* CONFIG_PM */
-
-static struct pci_driver rtsx_pci_driver = {
-       .name = DRV_NAME_RTSX_PCI,
-       .id_table = rtsx_pci_ids,
-       .probe = rtsx_pci_probe,
-       .remove = rtsx_pci_remove,
-       .suspend = rtsx_pci_suspend,
-       .resume = rtsx_pci_resume,
-       .shutdown = rtsx_pci_shutdown,
-};
-module_pci_driver(rtsx_pci_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
-MODULE_DESCRIPTION("Realtek PCI-E Card Reader Driver");
diff --git a/drivers/mfd/rtsx_pcr.h b/drivers/mfd/rtsx_pcr.h
deleted file mode 100644 (file)
index ec784e0..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#ifndef __RTSX_PCR_H
-#define __RTSX_PCR_H
-
-#include <linux/mfd/rtsx_pci.h>
-
-#define MIN_DIV_N_PCR          80
-#define MAX_DIV_N_PCR          208
-
-#define RTS522A_PM_CTRL3               0xFF7E
-
-#define RTS524A_PME_FORCE_CTL          0xFF78
-#define RTS524A_PM_CTRL3               0xFF7E
-
-#define LTR_ACTIVE_LATENCY_DEF         0x883C
-#define LTR_IDLE_LATENCY_DEF           0x892C
-#define LTR_L1OFF_LATENCY_DEF          0x9003
-#define L1_SNOOZE_DELAY_DEF            1
-#define LTR_L1OFF_SSPWRGATE_5249_DEF           0xAF
-#define LTR_L1OFF_SSPWRGATE_5250_DEF           0xFF
-#define LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF    0xAC
-#define LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF    0xF8
-#define CMD_TIMEOUT_DEF                100
-#define ASPM_MASK_NEG          0xFC
-#define MASK_8_BIT_DEF         0xFF
-
-int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
-int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
-
-void rts5209_init_params(struct rtsx_pcr *pcr);
-void rts5229_init_params(struct rtsx_pcr *pcr);
-void rtl8411_init_params(struct rtsx_pcr *pcr);
-void rtl8402_init_params(struct rtsx_pcr *pcr);
-void rts5227_init_params(struct rtsx_pcr *pcr);
-void rts522a_init_params(struct rtsx_pcr *pcr);
-void rts5249_init_params(struct rtsx_pcr *pcr);
-void rts524a_init_params(struct rtsx_pcr *pcr);
-void rts525a_init_params(struct rtsx_pcr *pcr);
-void rtl8411b_init_params(struct rtsx_pcr *pcr);
-
-static inline u8 map_sd_drive(int idx)
-{
-       u8 sd_drive[4] = {
-               0x01,   /* Type D */
-               0x02,   /* Type C */
-               0x05,   /* Type A */
-               0x03    /* Type B */
-       };
-
-       return sd_drive[idx];
-}
-
-#define rtsx_vendor_setting_valid(reg)         (!((reg) & 0x1000000))
-#define rts5209_vendor_setting1_valid(reg)     (!((reg) & 0x80))
-#define rts5209_vendor_setting2_valid(reg)     ((reg) & 0x80)
-
-#define rtsx_reg_to_aspm(reg)                  (((reg) >> 28) & 0x03)
-#define rtsx_reg_to_sd30_drive_sel_1v8(reg)    (((reg) >> 26) & 0x03)
-#define rtsx_reg_to_sd30_drive_sel_3v3(reg)    (((reg) >> 5) & 0x03)
-#define rtsx_reg_to_card_drive_sel(reg)                ((((reg) >> 25) & 0x01) << 6)
-#define rtsx_reg_check_reverse_socket(reg)     ((reg) & 0x4000)
-#define rts5209_reg_to_aspm(reg)               (((reg) >> 5) & 0x03)
-#define rts5209_reg_check_ms_pmos(reg)         (!((reg) & 0x08))
-#define rts5209_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 3) & 0x07)
-#define rts5209_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x07)
-#define rts5209_reg_to_card_drive_sel(reg)     ((reg) >> 8)
-#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
-#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg)        ((reg) & 0x03)
-
-#define set_pull_ctrl_tables(pcr, __device)                            \
-do {                                                                   \
-       pcr->sd_pull_ctl_enable_tbl  = __device##_sd_pull_ctl_enable_tbl;  \
-       pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \
-       pcr->ms_pull_ctl_enable_tbl  = __device##_ms_pull_ctl_enable_tbl;  \
-       pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
-} while (0)
-
-/* generic operations */
-int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
-int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency);
-int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val);
-
-#endif
diff --git a/drivers/mfd/rtsx_usb.c b/drivers/mfd/rtsx_usb.c
deleted file mode 100644 (file)
index 59d61b0..0000000
+++ /dev/null
@@ -1,791 +0,0 @@
-/* Driver for Realtek USB card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Roger Tseng <rogerable@realtek.com>
- */
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/usb.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/rtsx_usb.h>
-
-static int polling_pipe = 1;
-module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
-
-static const struct mfd_cell rtsx_usb_cells[] = {
-       [RTSX_USB_SD_CARD] = {
-               .name = "rtsx_usb_sdmmc",
-               .pdata_size = 0,
-       },
-       [RTSX_USB_MS_CARD] = {
-               .name = "rtsx_usb_ms",
-               .pdata_size = 0,
-       },
-};
-
-static void rtsx_usb_sg_timed_out(struct timer_list *t)
-{
-       struct rtsx_ucr *ucr = from_timer(ucr, t, sg_timer);
-
-       dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
-       usb_sg_cancel(&ucr->current_sg);
-}
-
-static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
-               unsigned int pipe, struct scatterlist *sg, int num_sg,
-               unsigned int length, unsigned int *act_len, int timeout)
-{
-       int ret;
-
-       dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n",
-                       __func__, length, num_sg);
-       ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0,
-                       sg, num_sg, length, GFP_NOIO);
-       if (ret)
-               return ret;
-
-       ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
-       add_timer(&ucr->sg_timer);
-       usb_sg_wait(&ucr->current_sg);
-       if (!del_timer_sync(&ucr->sg_timer))
-               ret = -ETIMEDOUT;
-       else
-               ret = ucr->current_sg.status;
-
-       if (act_len)
-               *act_len = ucr->current_sg.bytes;
-
-       return ret;
-}
-
-int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
-                             void *buf, unsigned int len, int num_sg,
-                             unsigned int *act_len, int timeout)
-{
-       if (timeout < 600)
-               timeout = 600;
-
-       if (num_sg)
-               return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
-                               (struct scatterlist *)buf, num_sg, len, act_len,
-                               timeout);
-       else
-               return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
-                               timeout);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
-
-static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr,
-               u16 addr, u16 len, u8 seq_type)
-{
-       rtsx_usb_cmd_hdr_tag(ucr);
-
-       ucr->cmd_buf[PACKET_TYPE] = seq_type;
-       ucr->cmd_buf[5] = (u8)(len >> 8);
-       ucr->cmd_buf[6] = (u8)len;
-       ucr->cmd_buf[8] = (u8)(addr >> 8);
-       ucr->cmd_buf[9] = (u8)addr;
-
-       if (seq_type == SEQ_WRITE)
-               ucr->cmd_buf[STAGE_FLAG] = 0;
-       else
-               ucr->cmd_buf[STAGE_FLAG] = STAGE_R;
-}
-
-static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
-               u16 addr, u16 len, u8 *data)
-{
-       u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4);
-
-       if (!data)
-               return -EINVAL;
-
-       if (cmd_len > IOBUF_SIZE)
-               return -EINVAL;
-
-       rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE);
-       memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len);
-
-       return rtsx_usb_transfer_data(ucr,
-                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
-                       ucr->cmd_buf, cmd_len, 0, NULL, 100);
-}
-
-static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr,
-               u16 addr, u16 len, u8 *data)
-{
-       int i, ret;
-       u16 rsp_len = round_down(len, 4);
-       u16 res_len = len - rsp_len;
-
-       if (!data)
-               return -EINVAL;
-
-       /* 4-byte aligned part */
-       if (rsp_len) {
-               rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ);
-               ret = rtsx_usb_transfer_data(ucr,
-                               usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
-                               ucr->cmd_buf, 12, 0, NULL, 100);
-               if (ret)
-                       return ret;
-
-               ret = rtsx_usb_transfer_data(ucr,
-                               usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
-                               data, rsp_len, 0, NULL, 100);
-               if (ret)
-                       return ret;
-       }
-
-       /* unaligned part */
-       for (i = 0; i < res_len; i++) {
-               ret = rtsx_usb_read_register(ucr, addr + rsp_len + i,
-                               data + rsp_len + i);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
-{
-       return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf);
-
-int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
-{
-       return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf);
-
-int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
-               u8 mask, u8 data)
-{
-       u16 value, index;
-
-       addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT;
-       value = swab16(addr);
-       index = mask | data << 8;
-
-       return usb_control_msg(ucr->pusb_dev,
-                       usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
-                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, index, NULL, 0, 100);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
-
-int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
-{
-       u16 value;
-       u8 *buf;
-       int ret;
-
-       if (!data)
-               return -EINVAL;
-
-       buf = kzalloc(sizeof(u8), GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
-       value = swab16(addr);
-
-       ret = usb_control_msg(ucr->pusb_dev,
-                       usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
-                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       value, 0, buf, 1, 100);
-       *data = *buf;
-
-       kfree(buf);
-       return ret;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
-
-void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr,
-               u8 mask, u8 data)
-{
-       int i;
-
-       if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) {
-               i = CMD_OFFSET + ucr->cmd_idx * 4;
-
-               ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
-                       (u8)((reg_addr >> 8) & 0x3F);
-               ucr->cmd_buf[i++] = (u8)reg_addr;
-               ucr->cmd_buf[i++] = mask;
-               ucr->cmd_buf[i++] = data;
-
-               ucr->cmd_idx++;
-       }
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
-
-int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
-{
-       int ret;
-
-       ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
-       ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
-       ucr->cmd_buf[STAGE_FLAG] = flag;
-
-       ret = rtsx_usb_transfer_data(ucr,
-                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
-                       ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
-                       0, NULL, timeout);
-       if (ret) {
-               rtsx_usb_clear_fsm_err(ucr);
-               return ret;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
-
-int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
-{
-       if (rsp_len <= 0)
-               return -EINVAL;
-
-       rsp_len = ALIGN(rsp_len, 4);
-
-       return rtsx_usb_transfer_data(ucr,
-                       usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
-                       ucr->rsp_buf, rsp_len, 0, NULL, timeout);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
-
-static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
-{
-       int ret;
-
-       rtsx_usb_init_cmd(ucr);
-       rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
-       rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
-       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
-       if (ret)
-               return ret;
-
-       ret = rtsx_usb_get_rsp(ucr, 2, 100);
-       if (ret)
-               return ret;
-
-       *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
-                 ((ucr->rsp_buf[1] & 0x03) << 4);
-
-       return 0;
-}
-
-int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
-{
-       int ret;
-       u16 *buf;
-
-       if (!status)
-               return -EINVAL;
-
-       if (polling_pipe == 0) {
-               buf = kzalloc(sizeof(u16), GFP_KERNEL);
-               if (!buf)
-                       return -ENOMEM;
-
-               ret = usb_control_msg(ucr->pusb_dev,
-                               usb_rcvctrlpipe(ucr->pusb_dev, 0),
-                               RTSX_USB_REQ_POLL,
-                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                               0, 0, buf, 2, 100);
-               *status = *buf;
-
-               kfree(buf);
-       } else {
-               ret = rtsx_usb_get_status_with_bulk(ucr, status);
-       }
-
-       /* usb_control_msg may return positive when success */
-       if (ret < 0)
-               return ret;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
-
-static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val)
-{
-       dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n",
-                       val, addr);
-
-       rtsx_usb_init_cmd(ucr);
-
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL,
-                       0xFF, (addr >> 4) & 0x0F);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
-
-       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
-}
-
-int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data)
-{
-       rtsx_usb_init_cmd(ucr);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data);
-       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_write_register);
-
-int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
-{
-       int ret;
-
-       if (data != NULL)
-               *data = 0;
-
-       rtsx_usb_init_cmd(ucr);
-       rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0);
-       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
-       if (ret)
-               return ret;
-
-       ret = rtsx_usb_get_rsp(ucr, 1, 100);
-       if (ret)
-               return ret;
-
-       if (data != NULL)
-               *data = ucr->rsp_buf[0];
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_read_register);
-
-static inline u8 double_ssc_depth(u8 depth)
-{
-       return (depth > 1) ? (depth - 1) : depth;
-}
-
-static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
-{
-       if (div > CLK_DIV_1) {
-               if (ssc_depth > div - 1)
-                       ssc_depth -= (div - 1);
-               else
-                       ssc_depth = SSC_DEPTH_2M;
-       }
-
-       return ssc_depth;
-}
-
-int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
-               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
-{
-       int ret;
-       u8 n, clk_divider, mcu_cnt, div;
-
-       if (!card_clock) {
-               ucr->cur_clk = 0;
-               return 0;
-       }
-
-       if (initial_mode) {
-               /* We use 250k(around) here, in initial stage */
-               clk_divider = SD_CLK_DIVIDE_128;
-               card_clock = 30000000;
-       } else {
-               clk_divider = SD_CLK_DIVIDE_0;
-       }
-
-       ret = rtsx_usb_write_register(ucr, SD_CFG1,
-                       SD_CLK_DIVIDE_MASK, clk_divider);
-       if (ret < 0)
-               return ret;
-
-       card_clock /= 1000000;
-       dev_dbg(&ucr->pusb_intf->dev,
-                       "Switch card clock to %dMHz\n", card_clock);
-
-       if (!initial_mode && double_clk)
-               card_clock *= 2;
-       dev_dbg(&ucr->pusb_intf->dev,
-                       "Internal SSC clock: %dMHz (cur_clk = %d)\n",
-                       card_clock, ucr->cur_clk);
-
-       if (card_clock == ucr->cur_clk)
-               return 0;
-
-       /* Converting clock value into internal settings: n and div */
-       n = card_clock - 2;
-       if ((card_clock <= 2) || (n > MAX_DIV_N))
-               return -EINVAL;
-
-       mcu_cnt = 60/card_clock + 3;
-       if (mcu_cnt > 15)
-               mcu_cnt = 15;
-
-       /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
-
-       div = CLK_DIV_1;
-       while (n < MIN_DIV_N && div < CLK_DIV_4) {
-               n = (n + 2) * 2 - 2;
-               div++;
-       }
-       dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div);
-
-       if (double_clk)
-               ssc_depth = double_ssc_depth(ssc_depth);
-
-       ssc_depth = revise_ssc_depth(ssc_depth, div);
-       dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth);
-
-       rtsx_usb_init_cmd(ucr);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV,
-                       0x3F, (div << 4) | mcu_cnt);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2,
-                       SSC_DEPTH_MASK, ssc_depth);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
-       if (vpclk) {
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
-                               PHASE_NOT_RESET, 0);
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
-                               PHASE_NOT_RESET, PHASE_NOT_RESET);
-       }
-
-       ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000);
-       if (ret < 0)
-               return ret;
-
-       ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff,
-                       SSC_RSTB | SSC_8X_EN | SSC_SEL_4M);
-       if (ret < 0)
-               return ret;
-
-       /* Wait SSC clock stable */
-       usleep_range(100, 1000);
-
-       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0);
-       if (ret < 0)
-               return ret;
-
-       ucr->cur_clk = card_clock;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock);
-
-int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card)
-{
-       int ret;
-       u16 val;
-       u16 cd_mask[] = {
-               [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD),
-               [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD)
-       };
-
-       ret = rtsx_usb_get_card_status(ucr, &val);
-       /*
-        * If get status fails, return 0 (ok) for the exclusive check
-        * and let the flow fail at somewhere else.
-        */
-       if (ret)
-               return 0;
-
-       if (val & cd_mask[card])
-               return -EIO;
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check);
-
-static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
-{
-       int ret;
-       u8 val;
-
-       rtsx_usb_init_cmd(ucr);
-
-       if (CHECK_PKG(ucr, LQFP48)) {
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
-                               LDO3318_PWR_MASK, LDO_SUSPEND);
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
-                               FORCE_LDO_POWERB, FORCE_LDO_POWERB);
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1,
-                               0x30, 0x10);
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5,
-                               0x03, 0x01);
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6,
-                               0x0C, 0x04);
-       }
-
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
-                       CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL,
-                       SD30_DRIVE_MASK, DRIVER_TYPE_D);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
-                       CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0);
-
-       if (ucr->is_rts5179)
-               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
-                               CARD_PULL_CTL5, 0x03, 0x01);
-
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL,
-                      EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
-       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND,
-                       XD_INT | MS_INT | SD_INT,
-                       XD_INT | MS_INT | SD_INT);
-
-       ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
-       if (ret)
-               return ret;
-
-       /* config non-crystal mode */
-       rtsx_usb_read_register(ucr, CFG_MODE, &val);
-       if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) {
-               ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C);
-               if (ret)
-                       return ret;
-       }
-
-       return 0;
-}
-
-static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
-{
-       int ret;
-       u8 val;
-
-       rtsx_usb_clear_fsm_err(ucr);
-
-       /* power on SSC */
-       ret = rtsx_usb_write_register(ucr,
-                       FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
-       if (ret)
-               return ret;
-
-       usleep_range(100, 1000);
-       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
-       if (ret)
-               return ret;
-
-       /* determine IC version */
-       ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
-       if (ret)
-               return ret;
-
-       ucr->ic_version = val & HW_VER_MASK;
-
-       /* determine package */
-       ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
-       if (ret)
-               return ret;
-
-       if (val & CARD_SHARE_LQFP_SEL) {
-               ucr->package = LQFP48;
-               dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
-       } else {
-               ucr->package = QFN24;
-               dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
-       }
-
-       /* determine IC variations */
-       rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
-       if (val & RTS5179) {
-               ucr->is_rts5179 = true;
-               dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
-       } else {
-               ucr->is_rts5179 = false;
-       }
-
-       return rtsx_usb_reset_chip(ucr);
-}
-
-static int rtsx_usb_probe(struct usb_interface *intf,
-                        const struct usb_device_id *id)
-{
-       struct usb_device *usb_dev = interface_to_usbdev(intf);
-       struct rtsx_ucr *ucr;
-       int ret;
-
-       dev_dbg(&intf->dev,
-               ": Realtek USB Card Reader found at bus %03d address %03d\n",
-                usb_dev->bus->busnum, usb_dev->devnum);
-
-       ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL);
-       if (!ucr)
-               return -ENOMEM;
-
-       ucr->pusb_dev = usb_dev;
-
-       ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
-                       GFP_KERNEL, &ucr->iobuf_dma);
-       if (!ucr->iobuf)
-               return -ENOMEM;
-
-       usb_set_intfdata(intf, ucr);
-
-       ucr->vendor_id = id->idVendor;
-       ucr->product_id = id->idProduct;
-       ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
-
-       mutex_init(&ucr->dev_mutex);
-
-       ucr->pusb_intf = intf;
-
-       /* initialize */
-       ret = rtsx_usb_init_chip(ucr);
-       if (ret)
-               goto out_init_fail;
-
-       /* initialize USB SG transfer timer */
-       timer_setup(&ucr->sg_timer, rtsx_usb_sg_timed_out, 0);
-
-       ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
-                                     ARRAY_SIZE(rtsx_usb_cells));
-       if (ret)
-               goto out_init_fail;
-
-#ifdef CONFIG_PM
-       intf->needs_remote_wakeup = 1;
-       usb_enable_autosuspend(usb_dev);
-#endif
-
-       return 0;
-
-out_init_fail:
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
-       return ret;
-}
-
-static void rtsx_usb_disconnect(struct usb_interface *intf)
-{
-       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
-       dev_dbg(&intf->dev, "%s called\n", __func__);
-
-       mfd_remove_devices(&intf->dev);
-
-       usb_set_intfdata(ucr->pusb_intf, NULL);
-       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
-                       ucr->iobuf_dma);
-}
-
-#ifdef CONFIG_PM
-static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
-{
-       struct rtsx_ucr *ucr =
-               (struct rtsx_ucr *)usb_get_intfdata(intf);
-       u16 val = 0;
-
-       dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n",
-                       __func__, message.event);
-
-       if (PMSG_IS_AUTO(message)) {
-               if (mutex_trylock(&ucr->dev_mutex)) {
-                       rtsx_usb_get_card_status(ucr, &val);
-                       mutex_unlock(&ucr->dev_mutex);
-
-                       /* Defer the autosuspend if card exists */
-                       if (val & (SD_CD | MS_CD))
-                               return -EAGAIN;
-               } else {
-                       /* There is an ongoing operation*/
-                       return -EAGAIN;
-               }
-       }
-
-       return 0;
-}
-
-static int rtsx_usb_resume(struct usb_interface *intf)
-{
-       return 0;
-}
-
-static int rtsx_usb_reset_resume(struct usb_interface *intf)
-{
-       struct rtsx_ucr *ucr =
-               (struct rtsx_ucr *)usb_get_intfdata(intf);
-
-       rtsx_usb_reset_chip(ucr);
-       return 0;
-}
-
-#else /* CONFIG_PM */
-
-#define rtsx_usb_suspend NULL
-#define rtsx_usb_resume NULL
-#define rtsx_usb_reset_resume NULL
-
-#endif /* CONFIG_PM */
-
-
-static int rtsx_usb_pre_reset(struct usb_interface *intf)
-{
-       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
-       mutex_lock(&ucr->dev_mutex);
-       return 0;
-}
-
-static int rtsx_usb_post_reset(struct usb_interface *intf)
-{
-       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
-
-       mutex_unlock(&ucr->dev_mutex);
-       return 0;
-}
-
-static struct usb_device_id rtsx_usb_usb_ids[] = {
-       { USB_DEVICE(0x0BDA, 0x0129) },
-       { USB_DEVICE(0x0BDA, 0x0139) },
-       { USB_DEVICE(0x0BDA, 0x0140) },
-       { }
-};
-MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
-
-static struct usb_driver rtsx_usb_driver = {
-       .name                   = "rtsx_usb",
-       .probe                  = rtsx_usb_probe,
-       .disconnect             = rtsx_usb_disconnect,
-       .suspend                = rtsx_usb_suspend,
-       .resume                 = rtsx_usb_resume,
-       .reset_resume           = rtsx_usb_reset_resume,
-       .pre_reset              = rtsx_usb_pre_reset,
-       .post_reset             = rtsx_usb_post_reset,
-       .id_table               = rtsx_usb_usb_ids,
-       .supports_autosuspend   = 1,
-       .soft_unbind            = 1,
-};
-
-module_usb_driver(rtsx_usb_driver);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
-MODULE_DESCRIPTION("Realtek USB Card Reader Driver");
index 0534f338c84a688fa1c26622a74098f6b7c9ccd0..ffdbf14a8652446004ccb451cbd329839d6be57c 100644 (file)
@@ -496,6 +496,10 @@ config PCI_ENDPOINT_TEST
            Enable this configuration option to enable the host side test driver
            for PCI Endpoint.
 
+config MISC_RTSX
+       tristate
+       default MISC_RTSX_PCI || MISC_RTSX_USB
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
@@ -509,4 +513,5 @@ source "drivers/misc/genwqe/Kconfig"
 source "drivers/misc/echo/Kconfig"
 source "drivers/misc/cxl/Kconfig"
 source "drivers/misc/ocxl/Kconfig"
+source "drivers/misc/cardreader/Kconfig"
 endmenu
index 73326d54e246775b1496459a93098d05cc8d3b4f..c3c8624f4d9506efe0f21168a3ebf7c0ae4536ee 100644 (file)
@@ -56,6 +56,7 @@ obj-$(CONFIG_ASPEED_LPC_CTRL) += aspeed-lpc-ctrl.o
 obj-$(CONFIG_ASPEED_LPC_SNOOP) += aspeed-lpc-snoop.o
 obj-$(CONFIG_PCI_ENDPOINT_TEST)        += pci_endpoint_test.o
 obj-$(CONFIG_OCXL)             += ocxl/
+obj-$(CONFIG_MISC_RTSX)                += cardreader/
 
 lkdtm-$(CONFIG_LKDTM)          += lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)          += lkdtm_bugs.o
diff --git a/drivers/misc/cardreader/Kconfig b/drivers/misc/cardreader/Kconfig
new file mode 100644 (file)
index 0000000..e7d835a
--- /dev/null
@@ -0,0 +1,20 @@
+config MISC_RTSX_PCI
+       tristate "Realtek PCI-E card reader"
+       depends on PCI
+       select MFD_CORE
+       help
+         This supports for Realtek PCI-Express card reader including rts5209,
+         rts5227, rts522A, rts5229, rts5249, rts524A, rts525A, rtl8411.
+         Realtek card readers support access to many types of memory cards,
+         such as Memory Stick, Memory Stick Pro, Secure Digital and
+         MultiMediaCard.
+
+config MISC_RTSX_USB
+       tristate "Realtek USB card reader"
+       depends on USB
+       select MFD_CORE
+       help
+         Select this option to get support for Realtek USB 2.0 card readers
+         including RTS5129, RTS5139, RTS5179 and RTS5170.
+         Realtek card reader supports access to many types of memory cards,
+         such as Memory Stick Pro, Secure Digital and MultiMediaCard.
diff --git a/drivers/misc/cardreader/Makefile b/drivers/misc/cardreader/Makefile
new file mode 100644 (file)
index 0000000..78337b2
--- /dev/null
@@ -0,0 +1,4 @@
+rtsx_pci-objs := rtsx_pcr.o rts5209.o rts5229.o rtl8411.o rts5227.o rts5249.o
+
+obj-$(CONFIG_MISC_RTSX_PCI)    += rtsx_pci.o
+obj-$(CONFIG_MISC_RTSX_USB)    += rtsx_usb.o
diff --git a/drivers/misc/cardreader/rtl8411.c b/drivers/misc/cardreader/rtl8411.c
new file mode 100644 (file)
index 0000000..434fd07
--- /dev/null
@@ -0,0 +1,508 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <linux/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rtl8411_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       rtsx_pci_read_register(pcr, SYS_VER, &val);
+       return val & 0x0F;
+}
+
+static int rtl8411b_is_qfn48(struct rtsx_pcr *pcr)
+{
+       u8 val = 0;
+
+       rtsx_pci_read_register(pcr, RTL8411B_PACKAGE_MODE, &val);
+
+       if (val & 0x2)
+               return 1;
+       else
+               return 0;
+}
+
+static void rtl8411_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg1 = 0;
+       u8 reg3 = 0;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg1);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg1);
+
+       if (!rtsx_vendor_setting_valid(reg1))
+               return;
+
+       pcr->aspm_en = rtsx_reg_to_aspm(reg1);
+       pcr->sd30_drive_sel_1v8 =
+               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg1));
+       pcr->card_drive_sel &= 0x3F;
+       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg1);
+
+       rtsx_pci_read_config_byte(pcr, PCR_SETTING_REG3, &reg3);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG3, reg3);
+       pcr->sd30_drive_sel_3v3 = rtl8411_reg_to_sd30_drive_sel_3v3(reg3);
+}
+
+static void rtl8411b_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg = 0;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+       if (!rtsx_vendor_setting_valid(reg))
+               return;
+
+       pcr->aspm_en = rtsx_reg_to_aspm(reg);
+       pcr->sd30_drive_sel_1v8 =
+               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
+       pcr->sd30_drive_sel_3v3 =
+               map_sd_drive(rtl8411b_reg_to_sd30_drive_sel_3v3(reg));
+}
+
+static void rtl8411_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
+}
+
+static int rtl8411_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       0xFF, pcr->sd30_drive_sel_3v3);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
+                       CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rtl8411b_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_init_cmd(pcr);
+
+       if (rtl8411b_is_qfn48(pcr))
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                               CARD_PULL_CTL3, 0xFF, 0xF5);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       0xFF, pcr->sd30_drive_sel_3v3);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CD_PAD_CTL,
+                       CD_DISABLE_MASK | CD_AUTO_DISABLE, CD_ENABLE);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, FUNC_FORCE_CTL,
+                       0x06, 0x00);
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rtl8411_turn_on_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rtl8411_turn_off_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rtl8411_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rtl8411_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rtl8411_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_CTL,
+                       BPP_LDO_POWB, BPP_LDO_SUSPEND);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       /* To avoid too large in-rush current */
+       udelay(150);
+
+       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                       BPP_POWER_MASK, BPP_POWER_10_PERCENT_ON);
+       if (err < 0)
+               return err;
+
+       udelay(150);
+
+       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                       BPP_POWER_MASK, BPP_POWER_15_PERCENT_ON);
+       if (err < 0)
+               return err;
+
+       udelay(150);
+
+       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                       BPP_POWER_MASK, BPP_POWER_ON);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_write_register(pcr, LDO_CTL, BPP_LDO_POWB, BPP_LDO_ON);
+}
+
+static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                       BPP_POWER_MASK, BPP_POWER_OFF);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_write_register(pcr, LDO_CTL,
+                       BPP_LDO_POWB, BPP_LDO_SUSPEND);
+}
+
+static int rtl8411_do_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage,
+               int bpp_tuned18_shift, int bpp_asic_1v8)
+{
+       u8 mask, val;
+       int err;
+
+       mask = (BPP_REG_TUNED18 << bpp_tuned18_shift) | BPP_PAD_MASK;
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
+               if (err < 0)
+                       return err;
+               val = (BPP_ASIC_3V3 << bpp_tuned18_shift) | BPP_PAD_3V3;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
+               if (err < 0)
+                       return err;
+               val = (bpp_asic_1v8 << bpp_tuned18_shift) | BPP_PAD_1V8;
+       } else {
+               return -EINVAL;
+       }
+
+       return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
+}
+
+static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       return rtl8411_do_switch_output_voltage(pcr, voltage,
+                       BPP_TUNED18_SHIFT_8411, BPP_ASIC_1V8);
+}
+
+static int rtl8402_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       return rtl8411_do_switch_output_voltage(pcr, voltage,
+                       BPP_TUNED18_SHIFT_8402, BPP_ASIC_2V0);
+}
+
+static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
+{
+       unsigned int card_exist;
+
+       card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+       card_exist &= CARD_EXIST;
+       if (!card_exist) {
+               /* Enable card CD */
+               rtsx_pci_write_register(pcr, CD_PAD_CTL,
+                               CD_DISABLE_MASK, CD_ENABLE);
+               /* Enable card interrupt */
+               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x00);
+               return 0;
+       }
+
+       if (hweight32(card_exist) > 1) {
+               rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                               BPP_POWER_MASK, BPP_POWER_5_PERCENT_ON);
+               msleep(100);
+
+               card_exist = rtsx_pci_readl(pcr, RTSX_BIPR);
+               if (card_exist & MS_EXIST)
+                       card_exist = MS_EXIST;
+               else if (card_exist & SD_EXIST)
+                       card_exist = SD_EXIST;
+               else
+                       card_exist = 0;
+
+               rtsx_pci_write_register(pcr, CARD_PWR_CTL,
+                               BPP_POWER_MASK, BPP_POWER_OFF);
+
+               pcr_dbg(pcr, "After CD deglitch, card_exist = 0x%x\n",
+                       card_exist);
+       }
+
+       if (card_exist & MS_EXIST) {
+               /* Disable SD interrupt */
+               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x40);
+               rtsx_pci_write_register(pcr, CD_PAD_CTL,
+                               CD_DISABLE_MASK, MS_CD_EN_ONLY);
+       } else if (card_exist & SD_EXIST) {
+               /* Disable MS interrupt */
+               rtsx_pci_write_register(pcr, EFUSE_CONTENT, 0xe0, 0x80);
+               rtsx_pci_write_register(pcr, CD_PAD_CTL,
+                               CD_DISABLE_MASK, SD_CD_EN_ONLY);
+       }
+
+       return card_exist;
+}
+
+static int rtl8411_conv_clk_and_div_n(int input, int dir)
+{
+       int output;
+
+       if (dir == CLK_TO_DIV_N)
+               output = input * 4 / 5 - 2;
+       else
+               output = (input + 2) * 5 / 4;
+
+       return output;
+}
+
+static const struct pcr_ops rtl8411_pcr_ops = {
+       .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
+       .extra_init_hw = rtl8411_extra_init_hw,
+       .optimize_phy = NULL,
+       .turn_on_led = rtl8411_turn_on_led,
+       .turn_off_led = rtl8411_turn_off_led,
+       .enable_auto_blink = rtl8411_enable_auto_blink,
+       .disable_auto_blink = rtl8411_disable_auto_blink,
+       .card_power_on = rtl8411_card_power_on,
+       .card_power_off = rtl8411_card_power_off,
+       .switch_output_voltage = rtl8411_switch_output_voltage,
+       .cd_deglitch = rtl8411_cd_deglitch,
+       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
+       .force_power_down = rtl8411_force_power_down,
+};
+
+static const struct pcr_ops rtl8402_pcr_ops = {
+       .fetch_vendor_settings = rtl8411_fetch_vendor_settings,
+       .extra_init_hw = rtl8411_extra_init_hw,
+       .optimize_phy = NULL,
+       .turn_on_led = rtl8411_turn_on_led,
+       .turn_off_led = rtl8411_turn_off_led,
+       .enable_auto_blink = rtl8411_enable_auto_blink,
+       .disable_auto_blink = rtl8411_disable_auto_blink,
+       .card_power_on = rtl8411_card_power_on,
+       .card_power_off = rtl8411_card_power_off,
+       .switch_output_voltage = rtl8402_switch_output_voltage,
+       .cd_deglitch = rtl8411_cd_deglitch,
+       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
+       .force_power_down = rtl8411_force_power_down,
+};
+
+static const struct pcr_ops rtl8411b_pcr_ops = {
+       .fetch_vendor_settings = rtl8411b_fetch_vendor_settings,
+       .extra_init_hw = rtl8411b_extra_init_hw,
+       .optimize_phy = NULL,
+       .turn_on_led = rtl8411_turn_on_led,
+       .turn_off_led = rtl8411_turn_off_led,
+       .enable_auto_blink = rtl8411_enable_auto_blink,
+       .disable_auto_blink = rtl8411_disable_auto_blink,
+       .card_power_on = rtl8411_card_power_on,
+       .card_power_off = rtl8411_card_power_off,
+       .switch_output_voltage = rtl8411_switch_output_voltage,
+       .cd_deglitch = rtl8411_cd_deglitch,
+       .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
+       .force_power_down = rtl8411_force_power_down,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xA9),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x09),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+       0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rtl8411_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+       0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+       0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rtl8411_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x95),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x09 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x69 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x08 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn64_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x65),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x05 | 0xD0),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x09 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x05 | 0x50),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static const u32 rtl8411b_qfn48_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0x65 | 0x90),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x04 | 0x11),
+       0,
+};
+
+static void rtl8411_init_common_params(struct rtsx_pcr *pcr)
+{
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+       pcr->num_slots = 2;
+       pcr->flags = 0;
+       pcr->card_drive_sel = RTL8411_CARD_DRIVE_DEFAULT;
+       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
+       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
+       pcr->aspm_en = ASPM_L1_EN;
+       pcr->tx_initial_phase = SET_CLOCK_PHASE(23, 7, 14);
+       pcr->rx_initial_phase = SET_CLOCK_PHASE(4, 3, 10);
+       pcr->ic_version = rtl8411_get_ic_version(pcr);
+}
+
+void rtl8411_init_params(struct rtsx_pcr *pcr)
+{
+       rtl8411_init_common_params(pcr);
+       pcr->ops = &rtl8411_pcr_ops;
+       set_pull_ctrl_tables(pcr, rtl8411);
+}
+
+void rtl8411b_init_params(struct rtsx_pcr *pcr)
+{
+       rtl8411_init_common_params(pcr);
+       pcr->ops = &rtl8411b_pcr_ops;
+       if (rtl8411b_is_qfn48(pcr))
+               set_pull_ctrl_tables(pcr, rtl8411b_qfn48);
+       else
+               set_pull_ctrl_tables(pcr, rtl8411b_qfn64);
+}
+
+void rtl8402_init_params(struct rtsx_pcr *pcr)
+{
+       rtl8411_init_common_params(pcr);
+       pcr->ops = &rtl8402_pcr_ops;
+       set_pull_ctrl_tables(pcr, rtl8411);
+}
diff --git a/drivers/misc/cardreader/rts5209.c b/drivers/misc/cardreader/rts5209.c
new file mode 100644 (file)
index 0000000..ce68c48
--- /dev/null
@@ -0,0 +1,277 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5209_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       val = rtsx_pci_readb(pcr, 0x1C);
+       return val & 0x0F;
+}
+
+static void rts5209_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+       if (rts5209_vendor_setting1_valid(reg)) {
+               if (rts5209_reg_check_ms_pmos(reg))
+                       pcr->flags |= PCR_MS_PMOS;
+               pcr->aspm_en = rts5209_reg_to_aspm(reg);
+       }
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+
+       if (rts5209_vendor_setting2_valid(reg)) {
+               pcr->sd30_drive_sel_1v8 =
+                       rts5209_reg_to_sd30_drive_sel_1v8(reg);
+               pcr->sd30_drive_sel_3v3 =
+                       rts5209_reg_to_sd30_drive_sel_3v3(reg);
+               pcr->card_drive_sel = rts5209_reg_to_card_drive_sel(reg);
+       }
+}
+
+static void rts5209_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       rtsx_pci_write_register(pcr, FPDCTL, 0x07, 0x07);
+}
+
+static int rts5209_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_init_cmd(pcr);
+
+       /* Turn off LED */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO, 0xFF, 0x03);
+       /* Reset ASPM state to default value */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+       /* Force CLKREQ# PIN to drive 0 to request clock */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
+       /* Configure GPIO as output */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_GPIO_DIR, 0xFF, 0x03);
+       /* Configure driving */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       0xFF, pcr->sd30_drive_sel_3v3);
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5209_optimize_phy(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_phy_register(pcr, 0x00, 0xB966);
+}
+
+static int rts5209_turn_on_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x00);
+}
+
+static int rts5209_turn_off_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_GPIO, 0x01, 0x01);
+}
+
+static int rts5209_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0xFF, 0x0D);
+}
+
+static int rts5209_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, CARD_AUTO_BLINK, 0x08, 0x00);
+}
+
+static int rts5209_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+       u8 pwr_mask, partial_pwr_on, pwr_on;
+
+       pwr_mask = SD_POWER_MASK;
+       partial_pwr_on = SD_PARTIAL_POWER_ON;
+       pwr_on = SD_POWER_ON;
+
+       if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
+               pwr_mask = MS_POWER_MASK;
+               partial_pwr_on = MS_PARTIAL_POWER_ON;
+               pwr_on = MS_POWER_ON;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       pwr_mask, partial_pwr_on);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x04);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       /* To avoid too large in-rush current */
+       udelay(150);
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL, pwr_mask, pwr_on);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x00);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       u8 pwr_mask, pwr_off;
+
+       pwr_mask = SD_POWER_MASK;
+       pwr_off = SD_POWER_OFF;
+
+       if ((pcr->flags & PCR_MS_PMOS) && (card == RTSX_MS_CARD)) {
+               pwr_mask = MS_POWER_MASK;
+               pwr_off = MS_POWER_OFF;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       pwr_mask | PMOS_STRG_MASK, pwr_off | PMOS_STRG_400mA);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x06);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
+               if (err < 0)
+                       return err;
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
+               if (err < 0)
+                       return err;
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct pcr_ops rts5209_pcr_ops = {
+       .fetch_vendor_settings = rts5209_fetch_vendor_settings,
+       .extra_init_hw = rts5209_extra_init_hw,
+       .optimize_phy = rts5209_optimize_phy,
+       .turn_on_led = rts5209_turn_on_led,
+       .turn_off_led = rts5209_turn_off_led,
+       .enable_auto_blink = rts5209_enable_auto_blink,
+       .disable_auto_blink = rts5209_disable_auto_blink,
+       .card_power_on = rts5209_card_power_on,
+       .card_power_off = rts5209_card_power_off,
+       .switch_output_voltage = rts5209_switch_output_voltage,
+       .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
+       .force_power_down = rts5209_force_power_down,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+       0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5209_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+       0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5209_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+void rts5209_init_params(struct rtsx_pcr *pcr)
+{
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 |
+               EXTRA_CAPS_SD_SDR104 | EXTRA_CAPS_MMC_8BIT;
+       pcr->num_slots = 2;
+       pcr->ops = &rts5209_pcr_ops;
+
+       pcr->flags = 0;
+       pcr->card_drive_sel = RTS5209_CARD_DRIVE_DEFAULT;
+       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
+       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
+       pcr->aspm_en = ASPM_L1_EN;
+       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 16);
+       pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
+
+       pcr->ic_version = rts5209_get_ic_version(pcr);
+       pcr->sd_pull_ctl_enable_tbl = rts5209_sd_pull_ctl_enable_tbl;
+       pcr->sd_pull_ctl_disable_tbl = rts5209_sd_pull_ctl_disable_tbl;
+       pcr->ms_pull_ctl_enable_tbl = rts5209_ms_pull_ctl_enable_tbl;
+       pcr->ms_pull_ctl_disable_tbl = rts5209_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/misc/cardreader/rts5227.c b/drivers/misc/cardreader/rts5227.c
new file mode 100644 (file)
index 0000000..024dcba
--- /dev/null
@@ -0,0 +1,374 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5227_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+       return val & 0x0F;
+}
+
+static void rts5227_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
+{
+       u8 driving_3v3[4][3] = {
+               {0x13, 0x13, 0x13},
+               {0x96, 0x96, 0x96},
+               {0x7F, 0x7F, 0x7F},
+               {0x96, 0x96, 0x96},
+       };
+       u8 driving_1v8[4][3] = {
+               {0x99, 0x99, 0x99},
+               {0xAA, 0xAA, 0xAA},
+               {0xFE, 0xFE, 0xFE},
+               {0xB3, 0xB3, 0xB3},
+       };
+       u8 (*driving)[3], drive_sel;
+
+       if (voltage == OUTPUT_3V3) {
+               driving = driving_3v3;
+               drive_sel = pcr->sd30_drive_sel_3v3;
+       } else {
+               driving = driving_1v8;
+               drive_sel = pcr->sd30_drive_sel_1v8;
+       }
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
+                       0xFF, driving[drive_sel][0]);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
+                       0xFF, driving[drive_sel][1]);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
+                       0xFF, driving[drive_sel][2]);
+}
+
+static void rts5227_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+       if (!rtsx_vendor_setting_valid(reg))
+               return;
+
+       pcr->aspm_en = rtsx_reg_to_aspm(reg);
+       pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
+       pcr->card_drive_sel &= 0x3F;
+       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
+       if (rtsx_reg_check_reverse_socket(reg))
+               pcr->flags |= PCR_REVERSE_SOCKET;
+}
+
+static void rts5227_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       /* Set relink_time to 0 */
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
+
+       if (pm_state == HOST_ENTER_S3)
+               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, 0x10, 0x10);
+
+       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
+}
+
+static int rts5227_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       u16 cap;
+
+       rtsx_pci_init_cmd(pcr);
+
+       /* Configure GPIO as output */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
+       /* Reset ASPM state to default value */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+       /* Switch LDO3318 source from DV33 to card_3v3 */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
+       /* LED shine disabled, set initial shine cycle period */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
+       /* Configure LTR */
+       pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &cap);
+       if (cap & PCI_EXP_DEVCTL2_LTR_EN)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LTR_CTL, 0xFF, 0xA3);
+       /* Configure OBFF */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OBFF_CFG, 0x03, 0x03);
+       /* Configure driving */
+       rts5227_fill_driving(pcr, OUTPUT_3V3);
+       /* Configure force_clock_req */
+       if (pcr->flags & PCR_REVERSE_SOCKET)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0xB8);
+       else
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB8, 0x88);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, pcr->reg_pm_ctrl3, 0x10, 0x00);
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5227_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       /* Optimize RX sensitivity */
+       return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
+}
+
+static int rts5227_turn_on_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
+}
+
+static int rts5227_turn_off_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
+}
+
+static int rts5227_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
+}
+
+static int rts5227_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
+}
+
+static int rts5227_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_PARTIAL_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x02);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       /* To avoid too large in-rush current */
+       udelay(150);
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x06);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5227_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK | PMOS_STRG_MASK,
+                       SD_POWER_OFF | PMOS_STRG_400mA);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0X00);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5227_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_phy_register(pcr, 0x11, 0x3C02);
+               if (err < 0)
+                       return err;
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C80 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       /* set pad drive */
+       rtsx_pci_init_cmd(pcr);
+       rts5227_fill_driving(pcr, voltage);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static const struct pcr_ops rts5227_pcr_ops = {
+       .fetch_vendor_settings = rts5227_fetch_vendor_settings,
+       .extra_init_hw = rts5227_extra_init_hw,
+       .optimize_phy = rts5227_optimize_phy,
+       .turn_on_led = rts5227_turn_on_led,
+       .turn_off_led = rts5227_turn_off_led,
+       .enable_auto_blink = rts5227_enable_auto_blink,
+       .disable_auto_blink = rts5227_disable_auto_blink,
+       .card_power_on = rts5227_card_power_on,
+       .card_power_off = rts5227_card_power_off,
+       .switch_output_voltage = rts5227_switch_output_voltage,
+       .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
+       .force_power_down = rts5227_force_power_down,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5227_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+       0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5227_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+       0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5227_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5227_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+void rts5227_init_params(struct rtsx_pcr *pcr)
+{
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+       pcr->num_slots = 2;
+       pcr->ops = &rts5227_pcr_ops;
+
+       pcr->flags = 0;
+       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
+       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
+       pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
+       pcr->aspm_en = ASPM_L1_EN;
+       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
+       pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 7, 7);
+
+       pcr->ic_version = rts5227_get_ic_version(pcr);
+       pcr->sd_pull_ctl_enable_tbl = rts5227_sd_pull_ctl_enable_tbl;
+       pcr->sd_pull_ctl_disable_tbl = rts5227_sd_pull_ctl_disable_tbl;
+       pcr->ms_pull_ctl_enable_tbl = rts5227_ms_pull_ctl_enable_tbl;
+       pcr->ms_pull_ctl_disable_tbl = rts5227_ms_pull_ctl_disable_tbl;
+
+       pcr->reg_pm_ctrl3 = PM_CTRL3;
+}
+
+static int rts522a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS522A_PM_CTRL3, D3_DELINK_MODE_EN,
+               0x00);
+       if (err < 0)
+               return err;
+
+       if (is_version(pcr, 0x522A, IC_VER_A)) {
+               err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
+                       PHY_RCR2_INIT_27S);
+               if (err)
+                       return err;
+
+               rtsx_pci_write_phy_register(pcr, PHY_RCR1, PHY_RCR1_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD0, PHY_FLD0_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD3, PHY_FLD3_INIT_27S);
+               rtsx_pci_write_phy_register(pcr, PHY_FLD4, PHY_FLD4_INIT_27S);
+       }
+
+       return 0;
+}
+
+static int rts522a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5227_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL, FUNC_FORCE_UPME_XMT_DBG,
+               FUNC_FORCE_UPME_XMT_DBG);
+       rtsx_pci_write_register(pcr, PCLK_CTL, 0x04, 0x04);
+       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
+       rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 0xFF, 0x11);
+
+       return 0;
+}
+
+/* rts522a operations mainly derived from rts5227, except phy/hw init setting.
+ */
+static const struct pcr_ops rts522a_pcr_ops = {
+       .fetch_vendor_settings = rts5227_fetch_vendor_settings,
+       .extra_init_hw = rts522a_extra_init_hw,
+       .optimize_phy = rts522a_optimize_phy,
+       .turn_on_led = rts5227_turn_on_led,
+       .turn_off_led = rts5227_turn_off_led,
+       .enable_auto_blink = rts5227_enable_auto_blink,
+       .disable_auto_blink = rts5227_disable_auto_blink,
+       .card_power_on = rts5227_card_power_on,
+       .card_power_off = rts5227_card_power_off,
+       .switch_output_voltage = rts5227_switch_output_voltage,
+       .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
+       .force_power_down = rts5227_force_power_down,
+};
+
+void rts522a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5227_init_params(pcr);
+
+       pcr->reg_pm_ctrl3 = RTS522A_PM_CTRL3;
+}
diff --git a/drivers/misc/cardreader/rts5229.c b/drivers/misc/cardreader/rts5229.c
new file mode 100644 (file)
index 0000000..9119261
--- /dev/null
@@ -0,0 +1,273 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5229_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+       return val & 0x0F;
+}
+
+static void rts5229_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+       if (!rtsx_vendor_setting_valid(reg))
+               return;
+
+       pcr->aspm_en = rtsx_reg_to_aspm(reg);
+       pcr->sd30_drive_sel_1v8 =
+               map_sd_drive(rtsx_reg_to_sd30_drive_sel_1v8(reg));
+       pcr->card_drive_sel &= 0x3F;
+       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr->sd30_drive_sel_3v3 =
+               map_sd_drive(rtsx_reg_to_sd30_drive_sel_3v3(reg));
+}
+
+static void rts5229_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
+}
+
+static int rts5229_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_init_cmd(pcr);
+
+       /* Configure GPIO as output */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
+       /* Reset ASPM state to default value */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+       /* Force CLKREQ# PIN to drive 0 to request clock */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08);
+       /* Switch LDO3318 source from DV33 to card_3v3 */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
+       /* LED shine disabled, set initial shine cycle period */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
+       /* Configure driving */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       0xFF, pcr->sd30_drive_sel_3v3);
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5229_optimize_phy(struct rtsx_pcr *pcr)
+{
+       /* Optimize RX sensitivity */
+       return rtsx_pci_write_phy_register(pcr, 0x00, 0xBA42);
+}
+
+static int rts5229_turn_on_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
+}
+
+static int rts5229_turn_off_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
+}
+
+static int rts5229_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
+}
+
+static int rts5229_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
+}
+
+static int rts5229_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_PARTIAL_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x02);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       /* To avoid too large in-rush current */
+       udelay(150);
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x06);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK | PMOS_STRG_MASK,
+                       SD_POWER_OFF | PMOS_STRG_400mA);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x00);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+
+       if (voltage == OUTPUT_3V3) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_3v3);
+               if (err < 0)
+                       return err;
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+               if (err < 0)
+                       return err;
+       } else if (voltage == OUTPUT_1V8) {
+               err = rtsx_pci_write_register(pcr,
+                               SD30_DRIVE_SEL, 0x07, pcr->sd30_drive_sel_1v8);
+               if (err < 0)
+                       return err;
+               err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+               if (err < 0)
+                       return err;
+       } else {
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static const struct pcr_ops rts5229_pcr_ops = {
+       .fetch_vendor_settings = rts5229_fetch_vendor_settings,
+       .extra_init_hw = rts5229_extra_init_hw,
+       .optimize_phy = rts5229_optimize_phy,
+       .turn_on_led = rts5229_turn_on_led,
+       .turn_off_led = rts5229_turn_off_led,
+       .enable_auto_blink = rts5229_enable_auto_blink,
+       .disable_auto_blink = rts5229_disable_auto_blink,
+       .card_power_on = rts5229_card_power_on,
+       .card_power_off = rts5229_card_power_off,
+       .switch_output_voltage = rts5229_switch_output_voltage,
+       .cd_deglitch = NULL,
+       .conv_clk_and_div_n = NULL,
+       .force_power_down = rts5229_force_power_down,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_enable_tbl1[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+       0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_enable_tbl2[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD9),
+       0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5229_sd_pull_ctl_disable_tbl1[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+       0,
+};
+
+/* For RTS5229 version C */
+static const u32 rts5229_sd_pull_ctl_disable_tbl2[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE5),
+       0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5229_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+void rts5229_init_params(struct rtsx_pcr *pcr)
+{
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+       pcr->num_slots = 2;
+       pcr->ops = &rts5229_pcr_ops;
+
+       pcr->flags = 0;
+       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
+       pcr->sd30_drive_sel_1v8 = DRIVER_TYPE_B;
+       pcr->sd30_drive_sel_3v3 = DRIVER_TYPE_D;
+       pcr->aspm_en = ASPM_L1_EN;
+       pcr->tx_initial_phase = SET_CLOCK_PHASE(27, 27, 15);
+       pcr->rx_initial_phase = SET_CLOCK_PHASE(30, 6, 6);
+
+       pcr->ic_version = rts5229_get_ic_version(pcr);
+       if (pcr->ic_version == IC_VER_C) {
+               pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl2;
+               pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl2;
+       } else {
+               pcr->sd_pull_ctl_enable_tbl = rts5229_sd_pull_ctl_enable_tbl1;
+               pcr->sd_pull_ctl_disable_tbl = rts5229_sd_pull_ctl_disable_tbl1;
+       }
+       pcr->ms_pull_ctl_enable_tbl = rts5229_ms_pull_ctl_enable_tbl;
+       pcr->ms_pull_ctl_disable_tbl = rts5229_ms_pull_ctl_disable_tbl;
+}
diff --git a/drivers/misc/cardreader/rts5249.c b/drivers/misc/cardreader/rts5249.c
new file mode 100644 (file)
index 0000000..dbe013a
--- /dev/null
@@ -0,0 +1,740 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/rtsx_pci.h>
+
+#include "rtsx_pcr.h"
+
+static u8 rts5249_get_ic_version(struct rtsx_pcr *pcr)
+{
+       u8 val;
+
+       rtsx_pci_read_register(pcr, DUMMY_REG_RESET_0, &val);
+       return val & 0x0F;
+}
+
+static void rts5249_fill_driving(struct rtsx_pcr *pcr, u8 voltage)
+{
+       u8 driving_3v3[4][3] = {
+               {0x11, 0x11, 0x18},
+               {0x55, 0x55, 0x5C},
+               {0xFF, 0xFF, 0xFF},
+               {0x96, 0x96, 0x96},
+       };
+       u8 driving_1v8[4][3] = {
+               {0xC4, 0xC4, 0xC4},
+               {0x3C, 0x3C, 0x3C},
+               {0xFE, 0xFE, 0xFE},
+               {0xB3, 0xB3, 0xB3},
+       };
+       u8 (*driving)[3], drive_sel;
+
+       if (voltage == OUTPUT_3V3) {
+               driving = driving_3v3;
+               drive_sel = pcr->sd30_drive_sel_3v3;
+       } else {
+               driving = driving_1v8;
+               drive_sel = pcr->sd30_drive_sel_1v8;
+       }
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CLK_DRIVE_SEL,
+                       0xFF, driving[drive_sel][0]);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_CMD_DRIVE_SEL,
+                       0xFF, driving[drive_sel][1]);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD30_DAT_DRIVE_SEL,
+                       0xFF, driving[drive_sel][2]);
+}
+
+static void rtsx_base_fetch_vendor_settings(struct rtsx_pcr *pcr)
+{
+       u32 reg;
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG1, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG1, reg);
+
+       if (!rtsx_vendor_setting_valid(reg)) {
+               pcr_dbg(pcr, "skip fetch vendor setting\n");
+               return;
+       }
+
+       pcr->aspm_en = rtsx_reg_to_aspm(reg);
+       pcr->sd30_drive_sel_1v8 = rtsx_reg_to_sd30_drive_sel_1v8(reg);
+       pcr->card_drive_sel &= 0x3F;
+       pcr->card_drive_sel |= rtsx_reg_to_card_drive_sel(reg);
+
+       rtsx_pci_read_config_dword(pcr, PCR_SETTING_REG2, &reg);
+       pcr_dbg(pcr, "Cfg 0x%x: 0x%x\n", PCR_SETTING_REG2, reg);
+       pcr->sd30_drive_sel_3v3 = rtsx_reg_to_sd30_drive_sel_3v3(reg);
+       if (rtsx_reg_check_reverse_socket(reg))
+               pcr->flags |= PCR_REVERSE_SOCKET;
+}
+
+static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       /* Set relink_time to 0 */
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, 0xFF, 0);
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, 0xFF, 0);
+       rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, 0x01, 0);
+
+       if (pm_state == HOST_ENTER_S3)
+               rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3,
+                       D3_DELINK_MODE_EN, D3_DELINK_MODE_EN);
+
+       rtsx_pci_write_register(pcr, FPDCTL, 0x03, 0x03);
+}
+
+static void rts5249_init_from_cfg(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+       u32 lval;
+
+       if (CHK_PCI_PID(pcr, PID_524A))
+               rtsx_pci_read_config_dword(pcr,
+                       PCR_ASPM_SETTING_REG1, &lval);
+       else
+               rtsx_pci_read_config_dword(pcr,
+                       PCR_ASPM_SETTING_REG2, &lval);
+
+       if (lval & ASPM_L1_1_EN_MASK)
+               rtsx_set_dev_flag(pcr, ASPM_L1_1_EN);
+
+       if (lval & ASPM_L1_2_EN_MASK)
+               rtsx_set_dev_flag(pcr, ASPM_L1_2_EN);
+
+       if (lval & PM_L1_1_EN_MASK)
+               rtsx_set_dev_flag(pcr, PM_L1_1_EN);
+
+       if (lval & PM_L1_2_EN_MASK)
+               rtsx_set_dev_flag(pcr, PM_L1_2_EN);
+
+       if (option->ltr_en) {
+               u16 val;
+
+               pcie_capability_read_word(pcr->pci, PCI_EXP_DEVCTL2, &val);
+               if (val & PCI_EXP_DEVCTL2_LTR_EN) {
+                       option->ltr_enabled = true;
+                       option->ltr_active = true;
+                       rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
+               } else {
+                       option->ltr_enabled = false;
+               }
+       }
+}
+
+static int rts5249_init_from_hw(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       if (rtsx_check_dev_flag(pcr, ASPM_L1_1_EN | ASPM_L1_2_EN
+                               | PM_L1_1_EN | PM_L1_2_EN))
+               option->force_clkreq_0 = false;
+       else
+               option->force_clkreq_0 = true;
+
+       return 0;
+}
+
+static int rts5249_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       rts5249_init_from_cfg(pcr);
+       rts5249_init_from_hw(pcr);
+
+       rtsx_pci_init_cmd(pcr);
+
+       /* Rest L1SUB Config */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, L1SUB_CONFIG3, 0xFF, 0x00);
+       /* Configure GPIO as output */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, GPIO_CTL, 0x02, 0x02);
+       /* Reset ASPM state to default value */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 0);
+       /* Switch LDO3318 source from DV33 to card_3v3 */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x00);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, LDO_PWR_SEL, 0x03, 0x01);
+       /* LED shine disabled, set initial shine cycle period */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, OLT_LED_CTL, 0x0F, 0x02);
+       /* Configure driving */
+       rts5249_fill_driving(pcr, OUTPUT_3V3);
+       if (pcr->flags & PCR_REVERSE_SOCKET)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0xB0);
+       else
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0xB0, 0x80);
+
+       /*
+        * If u_force_clkreq_0 is enabled, CLKREQ# PIN will be forced
+        * to drive low, and we forcibly request clock.
+        */
+       if (option->force_clkreq_0)
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
+                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_LOW);
+       else
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG,
+                       FORCE_CLKREQ_DELINK_MASK, FORCE_CLKREQ_HIGH);
+
+       return rtsx_pci_send_cmd(pcr, CMD_TIMEOUT_DEF);
+}
+
+static int rts5249_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, PM_CTRL3, D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_write_phy_register(pcr, PHY_REV,
+                       PHY_REV_RESV | PHY_REV_RXIDLE_LATCHED |
+                       PHY_REV_P1_EN | PHY_REV_RXIDLE_EN |
+                       PHY_REV_CLKREQ_TX_EN | PHY_REV_RX_PWST |
+                       PHY_REV_CLKREQ_DT_1_0 | PHY_REV_STOP_CLKRD |
+                       PHY_REV_STOP_CLKWR);
+       if (err < 0)
+               return err;
+
+       msleep(1);
+
+       err = rtsx_pci_write_phy_register(pcr, PHY_BPCR,
+                       PHY_BPCR_IBRXSEL | PHY_BPCR_IBTXSEL |
+                       PHY_BPCR_IB_FILTER | PHY_BPCR_CMIRROR_EN);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_write_phy_register(pcr, PHY_PCR,
+                       PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
+                       PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 |
+                       PHY_PCR_RSSI_EN | PHY_PCR_RX10K);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_write_phy_register(pcr, PHY_RCR2,
+                       PHY_RCR2_EMPHASE_EN | PHY_RCR2_NADJR |
+                       PHY_RCR2_CDR_SR_2 | PHY_RCR2_FREQSEL_12 |
+                       PHY_RCR2_CDR_SC_12P | PHY_RCR2_CALIB_LATE);
+       if (err < 0)
+               return err;
+
+       err = rtsx_pci_write_phy_register(pcr, PHY_FLD4,
+                       PHY_FLD4_FLDEN_SEL | PHY_FLD4_REQ_REF |
+                       PHY_FLD4_RXAMP_OFF | PHY_FLD4_REQ_ADDA |
+                       PHY_FLD4_BER_COUNT | PHY_FLD4_BER_TIMER |
+                       PHY_FLD4_BER_CHK_EN);
+       if (err < 0)
+               return err;
+       err = rtsx_pci_write_phy_register(pcr, PHY_RDR,
+                       PHY_RDR_RXDSEL_1_9 | PHY_SSC_AUTO_PWD);
+       if (err < 0)
+               return err;
+       err = rtsx_pci_write_phy_register(pcr, PHY_RCR1,
+                       PHY_RCR1_ADP_TIME_4 | PHY_RCR1_VCO_COARSE);
+       if (err < 0)
+               return err;
+       err = rtsx_pci_write_phy_register(pcr, PHY_FLD3,
+                       PHY_FLD3_TIMER_4 | PHY_FLD3_TIMER_6 |
+                       PHY_FLD3_RXDELINK);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_write_phy_register(pcr, PHY_TUNE,
+                       PHY_TUNE_TUNEREF_1_0 | PHY_TUNE_VBGSEL_1252 |
+                       PHY_TUNE_SDBUS_33 | PHY_TUNE_TUNED18 |
+                       PHY_TUNE_TUNED12 | PHY_TUNE_TUNEA12);
+}
+
+static int rtsx_base_turn_on_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x02);
+}
+
+static int rtsx_base_turn_off_led(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, GPIO_CTL, 0x02, 0x00);
+}
+
+static int rtsx_base_enable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x08);
+}
+
+static int rtsx_base_disable_auto_blink(struct rtsx_pcr *pcr)
+{
+       return rtsx_pci_write_register(pcr, OLT_LED_CTL, 0x08, 0x00);
+}
+
+static int rtsx_base_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       int err;
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_VCC_PARTIAL_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x02);
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       msleep(5);
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_VCC_POWER_ON);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x06);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rtsx_base_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_PWR_CTL,
+                       SD_POWER_MASK, SD_POWER_OFF);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PWR_GATE_CTRL,
+                       LDO3318_PWR_MASK, 0x00);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rtsx_base_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       int err;
+       u16 append;
+
+       switch (voltage) {
+       case OUTPUT_3V3:
+               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
+                       PHY_TUNE_VOLTAGE_3V3);
+               if (err < 0)
+                       return err;
+               break;
+       case OUTPUT_1V8:
+               append = PHY_TUNE_D18_1V8;
+               if (CHK_PCI_PID(pcr, 0x5249)) {
+                       err = rtsx_pci_update_phy(pcr, PHY_BACR,
+                               PHY_BACR_BASIC_MASK, 0);
+                       if (err < 0)
+                               return err;
+                       append = PHY_TUNE_D18_1V7;
+               }
+
+               err = rtsx_pci_update_phy(pcr, PHY_TUNE, PHY_TUNE_VOLTAGE_MASK,
+                       append);
+               if (err < 0)
+                       return err;
+               break;
+       default:
+               pcr_dbg(pcr, "unknown output voltage %d\n", voltage);
+               return -EINVAL;
+       }
+
+       /* set pad drive */
+       rtsx_pci_init_cmd(pcr);
+       rts5249_fill_driving(pcr, voltage);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static void rts5249_set_aspm(struct rtsx_pcr *pcr, bool enable)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+       u8 val = 0;
+
+       if (pcr->aspm_enabled == enable)
+               return;
+
+       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
+               if (enable)
+                       val = pcr->aspm_en;
+               rtsx_pci_update_cfg_byte(pcr,
+                       pcr->pcie_cap + PCI_EXP_LNKCTL,
+                       ASPM_MASK_NEG, val);
+       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
+               u8 mask = FORCE_ASPM_VAL_MASK | FORCE_ASPM_CTL0;
+
+               if (!enable)
+                       val = FORCE_ASPM_CTL0;
+               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL, mask, val);
+       }
+
+       pcr->aspm_enabled = enable;
+}
+
+static const struct pcr_ops rts5249_pcr_ops = {
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
+       .extra_init_hw = rts5249_extra_init_hw,
+       .optimize_phy = rts5249_optimize_phy,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rtsx_base_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rtsx_base_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
+       .set_aspm = rts5249_set_aspm,
+};
+
+/* SD Pull Control Enable:
+ *     SD_DAT[3:0] ==> pull up
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull up
+ *     SD_CMD      ==> pull up
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5249_sd_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0xAA),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xE9),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0xAA),
+       0,
+};
+
+/* SD Pull Control Disable:
+ *     SD_DAT[3:0] ==> pull down
+ *     SD_CD       ==> pull up
+ *     SD_WP       ==> pull down
+ *     SD_CMD      ==> pull down
+ *     SD_CLK      ==> pull down
+ */
+static const u32 rts5249_sd_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL1, 0x66),
+       RTSX_REG_PAIR(CARD_PULL_CTL2, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL3, 0xD5),
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+       0,
+};
+
+/* MS Pull Control Enable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5249_ms_pull_ctl_enable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+/* MS Pull Control Disable:
+ *     MS CD       ==> pull up
+ *     others      ==> pull down
+ */
+static const u32 rts5249_ms_pull_ctl_disable_tbl[] = {
+       RTSX_REG_PAIR(CARD_PULL_CTL4, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL5, 0x55),
+       RTSX_REG_PAIR(CARD_PULL_CTL6, 0x15),
+       0,
+};
+
+void rts5249_init_params(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       pcr->extra_caps = EXTRA_CAPS_SD_SDR50 | EXTRA_CAPS_SD_SDR104;
+       pcr->num_slots = 2;
+       pcr->ops = &rts5249_pcr_ops;
+
+       pcr->flags = 0;
+       pcr->card_drive_sel = RTSX_CARD_DRIVE_DEFAULT;
+       pcr->sd30_drive_sel_1v8 = CFG_DRIVER_TYPE_B;
+       pcr->sd30_drive_sel_3v3 = CFG_DRIVER_TYPE_B;
+       pcr->aspm_en = ASPM_L1_EN;
+       pcr->tx_initial_phase = SET_CLOCK_PHASE(1, 29, 16);
+       pcr->rx_initial_phase = SET_CLOCK_PHASE(24, 6, 5);
+
+       pcr->ic_version = rts5249_get_ic_version(pcr);
+       pcr->sd_pull_ctl_enable_tbl = rts5249_sd_pull_ctl_enable_tbl;
+       pcr->sd_pull_ctl_disable_tbl = rts5249_sd_pull_ctl_disable_tbl;
+       pcr->ms_pull_ctl_enable_tbl = rts5249_ms_pull_ctl_enable_tbl;
+       pcr->ms_pull_ctl_disable_tbl = rts5249_ms_pull_ctl_disable_tbl;
+
+       pcr->reg_pm_ctrl3 = PM_CTRL3;
+
+       option->dev_flags = (LTR_L1SS_PWR_GATE_CHECK_CARD_EN
+                               | LTR_L1SS_PWR_GATE_EN);
+       option->ltr_en = true;
+
+       /* Init latency of active, idle, L1OFF to 60us, 300us, 3ms */
+       option->ltr_active_latency = LTR_ACTIVE_LATENCY_DEF;
+       option->ltr_idle_latency = LTR_IDLE_LATENCY_DEF;
+       option->ltr_l1off_latency = LTR_L1OFF_LATENCY_DEF;
+       option->dev_aspm_mode = DEV_ASPM_DYNAMIC;
+       option->l1_snooze_delay = L1_SNOOZE_DELAY_DEF;
+       option->ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5249_DEF;
+       option->ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF;
+}
+
+static int rts524a_write_phy(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
+
+       return __rtsx_pci_write_phy_register(pcr, addr, val);
+}
+
+static int rts524a_read_phy(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+       addr = addr & 0x80 ? (addr & 0x7F) | 0x40 : addr;
+
+       return __rtsx_pci_read_phy_register(pcr, addr, val);
+}
+
+static int rts524a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
+               D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       rtsx_pci_write_phy_register(pcr, PHY_PCR,
+               PHY_PCR_FORCE_CODE | PHY_PCR_OOBS_CALI_50 |
+               PHY_PCR_OOBS_VCM_08 | PHY_PCR_OOBS_SEN_90 | PHY_PCR_RSSI_EN);
+       rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
+               PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
+
+       if (is_version(pcr, 0x524A, IC_VER_A)) {
+               rtsx_pci_write_phy_register(pcr, PHY_SSCCR3,
+                       PHY_SSCCR3_STEP_IN | PHY_SSCCR3_CHECK_DELAY);
+               rtsx_pci_write_phy_register(pcr, PHY_SSCCR2,
+                       PHY_SSCCR2_PLL_NCODE | PHY_SSCCR2_TIME0 |
+                       PHY_SSCCR2_TIME2_WIDTH);
+               rtsx_pci_write_phy_register(pcr, PHY_ANA1A,
+                       PHY_ANA1A_TXR_LOOPBACK | PHY_ANA1A_RXT_BIST |
+                       PHY_ANA1A_TXR_BIST | PHY_ANA1A_REV);
+               rtsx_pci_write_phy_register(pcr, PHY_ANA1D,
+                       PHY_ANA1D_DEBUG_ADDR);
+               rtsx_pci_write_phy_register(pcr, PHY_DIG1E,
+                       PHY_DIG1E_REV | PHY_DIG1E_D0_X_D1 |
+                       PHY_DIG1E_RX_ON_HOST | PHY_DIG1E_RCLK_REF_HOST |
+                       PHY_DIG1E_RCLK_TX_EN_KEEP |
+                       PHY_DIG1E_RCLK_TX_TERM_KEEP |
+                       PHY_DIG1E_RCLK_RX_EIDLE_ON | PHY_DIG1E_TX_TERM_KEEP |
+                       PHY_DIG1E_RX_TERM_KEEP | PHY_DIG1E_TX_EN_KEEP |
+                       PHY_DIG1E_RX_EN_KEEP);
+       }
+
+       rtsx_pci_write_phy_register(pcr, PHY_ANA08,
+               PHY_ANA08_RX_EQ_DCGAIN | PHY_ANA08_SEL_RX_EN |
+               PHY_ANA08_RX_EQ_VAL | PHY_ANA08_SCP | PHY_ANA08_SEL_IPI);
+
+       return 0;
+}
+
+static int rts524a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5249_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, FUNC_FORCE_CTL,
+               FORCE_ASPM_L1_EN, FORCE_ASPM_L1_EN);
+       rtsx_pci_write_register(pcr, PM_EVENT_DEBUG, PME_DEBUG_0, PME_DEBUG_0);
+       rtsx_pci_write_register(pcr, LDO_VCC_CFG1, LDO_VCC_LMT_EN,
+               LDO_VCC_LMT_EN);
+       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
+       if (is_version(pcr, 0x524A, IC_VER_A)) {
+               rtsx_pci_write_register(pcr, LDO_DV18_CFG,
+                       LDO_DV18_SR_MASK, LDO_DV18_SR_DF);
+               rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
+                       LDO_VCC_REF_TUNE_MASK, LDO_VCC_REF_1V2);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_REF_TUNE_MASK, LDO_VIO_REF_1V2);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_SR_MASK, LDO_VIO_SR_DF);
+               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
+                       LDO_REF12_TUNE_MASK, LDO_REF12_TUNE_DF);
+               rtsx_pci_write_register(pcr, SD40_LDO_CTL1,
+                       SD40_VIO_TUNE_MASK, SD40_VIO_TUNE_1V7);
+       }
+
+       return 0;
+}
+
+static void rts5250_set_l1off_cfg_sub_d0(struct rtsx_pcr *pcr, int active)
+{
+       struct rtsx_cr_option *option = &(pcr->option);
+
+       u32 interrupt = rtsx_pci_readl(pcr, RTSX_BIPR);
+       int card_exist = (interrupt & SD_EXIST) | (interrupt & MS_EXIST);
+       int aspm_L1_1, aspm_L1_2;
+       u8 val = 0;
+
+       aspm_L1_1 = rtsx_check_dev_flag(pcr, ASPM_L1_1_EN);
+       aspm_L1_2 = rtsx_check_dev_flag(pcr, ASPM_L1_2_EN);
+
+       if (active) {
+               /* Run, latency: 60us */
+               if (aspm_L1_1)
+                       val = option->ltr_l1off_snooze_sspwrgate;
+       } else {
+               /* L1off, latency: 300us */
+               if (aspm_L1_2)
+                       val = option->ltr_l1off_sspwrgate;
+       }
+
+       if (aspm_L1_1 || aspm_L1_2) {
+               if (rtsx_check_dev_flag(pcr,
+                                       LTR_L1SS_PWR_GATE_CHECK_CARD_EN)) {
+                       if (card_exist)
+                               val &= ~L1OFF_MBIAS2_EN_5250;
+                       else
+                               val |= L1OFF_MBIAS2_EN_5250;
+               }
+       }
+       rtsx_set_l1off_sub(pcr, val);
+}
+
+static const struct pcr_ops rts524a_pcr_ops = {
+       .write_phy = rts524a_write_phy,
+       .read_phy = rts524a_read_phy,
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
+       .extra_init_hw = rts524a_extra_init_hw,
+       .optimize_phy = rts524a_optimize_phy,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rtsx_base_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rtsx_base_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
+       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
+       .set_aspm = rts5249_set_aspm,
+};
+
+void rts524a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5249_init_params(pcr);
+       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
+       pcr->option.ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
+
+       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
+       pcr->ops = &rts524a_pcr_ops;
+}
+
+static int rts525a_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       rtsx_pci_write_register(pcr, LDO_VCC_CFG1,
+               LDO_VCC_TUNE_MASK, LDO_VCC_3V3);
+       return rtsx_base_card_power_on(pcr, card);
+}
+
+static int rts525a_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+       switch (voltage) {
+       case OUTPUT_3V3:
+               rtsx_pci_write_register(pcr, LDO_CONFIG2,
+                       LDO_D3318_MASK, LDO_D3318_33V);
+               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8, 0);
+               break;
+       case OUTPUT_1V8:
+               rtsx_pci_write_register(pcr, LDO_CONFIG2,
+                       LDO_D3318_MASK, LDO_D3318_18V);
+               rtsx_pci_write_register(pcr, SD_PAD_CTL, SD_IO_USING_1V8,
+                       SD_IO_USING_1V8);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+       rts5249_fill_driving(pcr, voltage);
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+static int rts525a_optimize_phy(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       err = rtsx_pci_write_register(pcr, RTS524A_PM_CTRL3,
+               D3_DELINK_MODE_EN, 0x00);
+       if (err < 0)
+               return err;
+
+       rtsx_pci_write_phy_register(pcr, _PHY_FLD0,
+               _PHY_FLD0_CLK_REQ_20C | _PHY_FLD0_RX_IDLE_EN |
+               _PHY_FLD0_BIT_ERR_RSTN | _PHY_FLD0_BER_COUNT |
+               _PHY_FLD0_BER_TIMER | _PHY_FLD0_CHECK_EN);
+
+       rtsx_pci_write_phy_register(pcr, _PHY_ANA03,
+               _PHY_ANA03_TIMER_MAX | _PHY_ANA03_OOBS_DEB_EN |
+               _PHY_CMU_DEBUG_EN);
+
+       if (is_version(pcr, 0x525A, IC_VER_A))
+               rtsx_pci_write_phy_register(pcr, _PHY_REV0,
+                       _PHY_REV0_FILTER_OUT | _PHY_REV0_CDR_BYPASS_PFD |
+                       _PHY_REV0_CDR_RX_IDLE_BYPASS);
+
+       return 0;
+}
+
+static int rts525a_extra_init_hw(struct rtsx_pcr *pcr)
+{
+       rts5249_extra_init_hw(pcr);
+
+       rtsx_pci_write_register(pcr, PCLK_CTL, PCLK_MODE_SEL, PCLK_MODE_SEL);
+       if (is_version(pcr, 0x525A, IC_VER_A)) {
+               rtsx_pci_write_register(pcr, L1SUB_CONFIG2,
+                       L1SUB_AUTO_CFG, L1SUB_AUTO_CFG);
+               rtsx_pci_write_register(pcr, RREF_CFG,
+                       RREF_VBGSEL_MASK, RREF_VBGSEL_1V25);
+               rtsx_pci_write_register(pcr, LDO_VIO_CFG,
+                       LDO_VIO_TUNE_MASK, LDO_VIO_1V7);
+               rtsx_pci_write_register(pcr, LDO_DV12S_CFG,
+                       LDO_D12_TUNE_MASK, LDO_D12_TUNE_DF);
+               rtsx_pci_write_register(pcr, LDO_AV12S_CFG,
+                       LDO_AV12S_TUNE_MASK, LDO_AV12S_TUNE_DF);
+               rtsx_pci_write_register(pcr, LDO_VCC_CFG0,
+                       LDO_VCC_LMTVTH_MASK, LDO_VCC_LMTVTH_2A);
+               rtsx_pci_write_register(pcr, OOBS_CONFIG,
+                       OOBS_AUTOK_DIS | OOBS_VAL_MASK, 0x89);
+       }
+
+       return 0;
+}
+
+static const struct pcr_ops rts525a_pcr_ops = {
+       .fetch_vendor_settings = rtsx_base_fetch_vendor_settings,
+       .extra_init_hw = rts525a_extra_init_hw,
+       .optimize_phy = rts525a_optimize_phy,
+       .turn_on_led = rtsx_base_turn_on_led,
+       .turn_off_led = rtsx_base_turn_off_led,
+       .enable_auto_blink = rtsx_base_enable_auto_blink,
+       .disable_auto_blink = rtsx_base_disable_auto_blink,
+       .card_power_on = rts525a_card_power_on,
+       .card_power_off = rtsx_base_card_power_off,
+       .switch_output_voltage = rts525a_switch_output_voltage,
+       .force_power_down = rtsx_base_force_power_down,
+       .set_l1off_cfg_sub_d0 = rts5250_set_l1off_cfg_sub_d0,
+       .set_aspm = rts5249_set_aspm,
+};
+
+void rts525a_init_params(struct rtsx_pcr *pcr)
+{
+       rts5249_init_params(pcr);
+       pcr->option.ltr_l1off_sspwrgate = LTR_L1OFF_SSPWRGATE_5250_DEF;
+       pcr->option.ltr_l1off_snooze_sspwrgate =
+               LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF;
+
+       pcr->reg_pm_ctrl3 = RTS524A_PM_CTRL3;
+       pcr->ops = &rts525a_pcr_ops;
+}
diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c
new file mode 100644 (file)
index 0000000..c5430c2
--- /dev/null
@@ -0,0 +1,1572 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#include <linux/pci.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/idr.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/rtsx_pci.h>
+#include <linux/mmc/card.h>
+#include <asm/unaligned.h>
+
+#include "rtsx_pcr.h"
+
+static bool msi_en = true;
+module_param(msi_en, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(msi_en, "Enable MSI");
+
+static DEFINE_IDR(rtsx_pci_idr);
+static DEFINE_SPINLOCK(rtsx_pci_lock);
+
+static struct mfd_cell rtsx_pcr_cells[] = {
+       [RTSX_SD_CARD] = {
+               .name = DRV_NAME_RTSX_PCI_SDMMC,
+       },
+       [RTSX_MS_CARD] = {
+               .name = DRV_NAME_RTSX_PCI_MS,
+       },
+};
+
+static const struct pci_device_id rtsx_pci_ids[] = {
+       { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, rtsx_pci_ids);
+
+static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
+               0xFC, pcr->aspm_en);
+}
+
+static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL,
+               0xFC, 0);
+}
+
+int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
+{
+       rtsx_pci_write_register(pcr, MSGTXDATA0,
+                               MASK_8_BIT_DEF, (u8) (latency & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA1,
+                               MASK_8_BIT_DEF, (u8)((latency >> 8) & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA2,
+                               MASK_8_BIT_DEF, (u8)((latency >> 16) & 0xFF));
+       rtsx_pci_write_register(pcr, MSGTXDATA3,
+                               MASK_8_BIT_DEF, (u8)((latency >> 24) & 0xFF));
+       rtsx_pci_write_register(pcr, LTR_CTL, LTR_TX_EN_MASK |
+               LTR_LATENCY_MODE_MASK, LTR_TX_EN_1 | LTR_LATENCY_MODE_SW);
+
+       return 0;
+}
+
+int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency)
+{
+       if (pcr->ops->set_ltr_latency)
+               return pcr->ops->set_ltr_latency(pcr, latency);
+       else
+               return rtsx_comm_set_ltr_latency(pcr, latency);
+}
+
+static void rtsx_comm_set_aspm(struct rtsx_pcr *pcr, bool enable)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       if (pcr->aspm_enabled == enable)
+               return;
+
+       if (option->dev_aspm_mode == DEV_ASPM_DYNAMIC) {
+               if (enable)
+                       rtsx_pci_enable_aspm(pcr);
+               else
+                       rtsx_pci_disable_aspm(pcr);
+       } else if (option->dev_aspm_mode == DEV_ASPM_BACKDOOR) {
+               u8 mask = FORCE_ASPM_VAL_MASK;
+               u8 val = 0;
+
+               if (enable)
+                       val = pcr->aspm_en;
+               rtsx_pci_write_register(pcr, ASPM_FORCE_CTL,  mask, val);
+       }
+
+       pcr->aspm_enabled = enable;
+}
+
+static void rtsx_disable_aspm(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->set_aspm)
+               pcr->ops->set_aspm(pcr, false);
+       else
+               rtsx_comm_set_aspm(pcr, false);
+}
+
+int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val)
+{
+       rtsx_pci_write_register(pcr, L1SUB_CONFIG3, 0xFF, val);
+
+       return 0;
+}
+
+void rtsx_set_l1off_sub_cfg_d0(struct rtsx_pcr *pcr, int active)
+{
+       if (pcr->ops->set_l1off_cfg_sub_d0)
+               pcr->ops->set_l1off_cfg_sub_d0(pcr, active);
+}
+
+static void rtsx_comm_pm_full_on(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       rtsx_disable_aspm(pcr);
+
+       if (option->ltr_enabled)
+               rtsx_set_ltr_latency(pcr, option->ltr_active_latency);
+
+       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
+               rtsx_set_l1off_sub_cfg_d0(pcr, 1);
+}
+
+void rtsx_pm_full_on(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->full_on)
+               pcr->ops->full_on(pcr);
+       else
+               rtsx_comm_pm_full_on(pcr);
+}
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr)
+{
+       /* If pci device removed, don't queue idle work any more */
+       if (pcr->remove_pci)
+               return;
+
+       if (pcr->state != PDEV_STAT_RUN) {
+               pcr->state = PDEV_STAT_RUN;
+               if (pcr->ops->enable_auto_blink)
+                       pcr->ops->enable_auto_blink(pcr);
+               rtsx_pm_full_on(pcr);
+       }
+
+       mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200));
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_start_run);
+
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data)
+{
+       int i;
+       u32 val = HAIMR_WRITE_START;
+
+       val |= (u32)(addr & 0x3FFF) << 16;
+       val |= (u32)mask << 8;
+       val |= (u32)data;
+
+       rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+       for (i = 0; i < MAX_RW_REG_CNT; i++) {
+               val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+               if ((val & HAIMR_TRANS_END) == 0) {
+                       if (data != (u8)val)
+                               return -EIO;
+                       return 0;
+               }
+       }
+
+       return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_register);
+
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data)
+{
+       u32 val = HAIMR_READ_START;
+       int i;
+
+       val |= (u32)(addr & 0x3FFF) << 16;
+       rtsx_pci_writel(pcr, RTSX_HAIMR, val);
+
+       for (i = 0; i < MAX_RW_REG_CNT; i++) {
+               val = rtsx_pci_readl(pcr, RTSX_HAIMR);
+               if ((val & HAIMR_TRANS_END) == 0)
+                       break;
+       }
+
+       if (i >= MAX_RW_REG_CNT)
+               return -ETIMEDOUT;
+
+       if (data)
+               *data = (u8)(val & 0xFF);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_register);
+
+int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+       int err, i, finished = 0;
+       u8 tmp;
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA0, 0xFF, (u8)val);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYDATA1, 0xFF, (u8)(val >> 8));
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x81);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 100000; i++) {
+               err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+               if (err < 0)
+                       return err;
+
+               if (!(tmp & 0x80)) {
+                       finished = 1;
+                       break;
+               }
+       }
+
+       if (!finished)
+               return -ETIMEDOUT;
+
+       return 0;
+}
+
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val)
+{
+       if (pcr->ops->write_phy)
+               return pcr->ops->write_phy(pcr, addr, val);
+
+       return __rtsx_pci_write_phy_register(pcr, addr, val);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_phy_register);
+
+int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+       int err, i, finished = 0;
+       u16 data;
+       u8 *ptr, tmp;
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYADDR, 0xFF, addr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PHYRWCTL, 0xFF, 0x80);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       for (i = 0; i < 100000; i++) {
+               err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp);
+               if (err < 0)
+                       return err;
+
+               if (!(tmp & 0x80)) {
+                       finished = 1;
+                       break;
+               }
+       }
+
+       if (!finished)
+               return -ETIMEDOUT;
+
+       rtsx_pci_init_cmd(pcr);
+
+       rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA0, 0, 0);
+       rtsx_pci_add_cmd(pcr, READ_REG_CMD, PHYDATA1, 0, 0);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       ptr = rtsx_pci_get_cmd_data(pcr);
+       data = ((u16)ptr[1] << 8) | ptr[0];
+
+       if (val)
+               *val = data;
+
+       return 0;
+}
+
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val)
+{
+       if (pcr->ops->read_phy)
+               return pcr->ops->read_phy(pcr, addr, val);
+
+       return __rtsx_pci_read_phy_register(pcr, addr, val);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_phy_register);
+
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr)
+{
+       rtsx_pci_writel(pcr, RTSX_HCBCTLR, STOP_CMD);
+       rtsx_pci_writel(pcr, RTSX_HDBCTLR, STOP_DMA);
+
+       rtsx_pci_write_register(pcr, DMACTL, 0x80, 0x80);
+       rtsx_pci_write_register(pcr, RBCTL, 0x80, 0x80);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_stop_cmd);
+
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+               u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
+{
+       unsigned long flags;
+       u32 val = 0;
+       u32 *ptr = (u32 *)(pcr->host_cmds_ptr);
+
+       val |= (u32)(cmd_type & 0x03) << 30;
+       val |= (u32)(reg_addr & 0x3FFF) << 16;
+       val |= (u32)mask << 8;
+       val |= (u32)data;
+
+       spin_lock_irqsave(&pcr->lock, flags);
+       ptr += pcr->ci;
+       if (pcr->ci < (HOST_CMDS_BUF_LEN / 4)) {
+               put_unaligned_le32(val, ptr);
+               ptr++;
+               pcr->ci++;
+       }
+       spin_unlock_irqrestore(&pcr->lock, flags);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_add_cmd);
+
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr)
+{
+       u32 val = 1 << 31;
+
+       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+       val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+       /* Hardware Auto Response */
+       val |= 0x40000000;
+       rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd_no_wait);
+
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout)
+{
+       struct completion trans_done;
+       u32 val = 1 << 31;
+       long timeleft;
+       unsigned long flags;
+       int err = 0;
+
+       spin_lock_irqsave(&pcr->lock, flags);
+
+       /* set up data structures for the wakeup system */
+       pcr->done = &trans_done;
+       pcr->trans_result = TRANS_NOT_READY;
+       init_completion(&trans_done);
+
+       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+       val |= (u32)(pcr->ci * 4) & 0x00FFFFFF;
+       /* Hardware Auto Response */
+       val |= 0x40000000;
+       rtsx_pci_writel(pcr, RTSX_HCBCTLR, val);
+
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+       /* Wait for TRANS_OK_INT */
+       timeleft = wait_for_completion_interruptible_timeout(
+                       &trans_done, msecs_to_jiffies(timeout));
+       if (timeleft <= 0) {
+               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
+               err = -ETIMEDOUT;
+               goto finish_send_cmd;
+       }
+
+       spin_lock_irqsave(&pcr->lock, flags);
+       if (pcr->trans_result == TRANS_RESULT_FAIL)
+               err = -EINVAL;
+       else if (pcr->trans_result == TRANS_RESULT_OK)
+               err = 0;
+       else if (pcr->trans_result == TRANS_NO_DEVICE)
+               err = -ENODEV;
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+finish_send_cmd:
+       spin_lock_irqsave(&pcr->lock, flags);
+       pcr->done = NULL;
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+       if ((err < 0) && (err != -ENODEV))
+               rtsx_pci_stop_cmd(pcr);
+
+       if (pcr->finish_me)
+               complete(pcr->finish_me);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_send_cmd);
+
+static void rtsx_pci_add_sg_tbl(struct rtsx_pcr *pcr,
+               dma_addr_t addr, unsigned int len, int end)
+{
+       u64 *ptr = (u64 *)(pcr->host_sg_tbl_ptr) + pcr->sgi;
+       u64 val;
+       u8 option = SG_VALID | SG_TRANS_DATA;
+
+       pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len);
+
+       if (end)
+               option |= SG_END;
+       val = ((u64)addr << 32) | ((u64)len << 12) | option;
+
+       put_unaligned_le64(val, ptr);
+       pcr->sgi++;
+}
+
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read, int timeout)
+{
+       int err = 0, count;
+
+       pcr_dbg(pcr, "--> %s: num_sg = %d\n", __func__, num_sg);
+       count = rtsx_pci_dma_map_sg(pcr, sglist, num_sg, read);
+       if (count < 1)
+               return -EINVAL;
+       pcr_dbg(pcr, "DMA mapping count: %d\n", count);
+
+       err = rtsx_pci_dma_transfer(pcr, sglist, count, read, timeout);
+
+       rtsx_pci_dma_unmap_sg(pcr, sglist, num_sg, read);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data);
+
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read)
+{
+       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       if (pcr->remove_pci)
+               return -EINVAL;
+
+       if ((sglist == NULL) || (num_sg <= 0))
+               return -EINVAL;
+
+       return dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_map_sg);
+
+void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read)
+{
+       enum dma_data_direction dir = read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+       dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dir);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_unmap_sg);
+
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int count, bool read, int timeout)
+{
+       struct completion trans_done;
+       struct scatterlist *sg;
+       dma_addr_t addr;
+       long timeleft;
+       unsigned long flags;
+       unsigned int len;
+       int i, err = 0;
+       u32 val;
+       u8 dir = read ? DEVICE_TO_HOST : HOST_TO_DEVICE;
+
+       if (pcr->remove_pci)
+               return -ENODEV;
+
+       if ((sglist == NULL) || (count < 1))
+               return -EINVAL;
+
+       val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE;
+       pcr->sgi = 0;
+       for_each_sg(sglist, sg, count, i) {
+               addr = sg_dma_address(sg);
+               len = sg_dma_len(sg);
+               rtsx_pci_add_sg_tbl(pcr, addr, len, i == count - 1);
+       }
+
+       spin_lock_irqsave(&pcr->lock, flags);
+
+       pcr->done = &trans_done;
+       pcr->trans_result = TRANS_NOT_READY;
+       init_completion(&trans_done);
+       rtsx_pci_writel(pcr, RTSX_HDBAR, pcr->host_sg_tbl_addr);
+       rtsx_pci_writel(pcr, RTSX_HDBCTLR, val);
+
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+       timeleft = wait_for_completion_interruptible_timeout(
+                       &trans_done, msecs_to_jiffies(timeout));
+       if (timeleft <= 0) {
+               pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__);
+               err = -ETIMEDOUT;
+               goto out;
+       }
+
+       spin_lock_irqsave(&pcr->lock, flags);
+       if (pcr->trans_result == TRANS_RESULT_FAIL) {
+               err = -EILSEQ;
+               if (pcr->dma_error_count < RTS_MAX_TIMES_FREQ_REDUCTION)
+                       pcr->dma_error_count++;
+       }
+
+       else if (pcr->trans_result == TRANS_NO_DEVICE)
+               err = -ENODEV;
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+out:
+       spin_lock_irqsave(&pcr->lock, flags);
+       pcr->done = NULL;
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+       if ((err < 0) && (err != -ENODEV))
+               rtsx_pci_stop_cmd(pcr);
+
+       if (pcr->finish_me)
+               complete(pcr->finish_me);
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer);
+
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+       int err;
+       int i, j;
+       u16 reg;
+       u8 *ptr;
+
+       if (buf_len > 512)
+               buf_len = 512;
+
+       ptr = buf;
+       reg = PPBUF_BASE2;
+       for (i = 0; i < buf_len / 256; i++) {
+               rtsx_pci_init_cmd(pcr);
+
+               for (j = 0; j < 256; j++)
+                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+               err = rtsx_pci_send_cmd(pcr, 250);
+               if (err < 0)
+                       return err;
+
+               memcpy(ptr, rtsx_pci_get_cmd_data(pcr), 256);
+               ptr += 256;
+       }
+
+       if (buf_len % 256) {
+               rtsx_pci_init_cmd(pcr);
+
+               for (j = 0; j < buf_len % 256; j++)
+                       rtsx_pci_add_cmd(pcr, READ_REG_CMD, reg++, 0, 0);
+
+               err = rtsx_pci_send_cmd(pcr, 250);
+               if (err < 0)
+                       return err;
+       }
+
+       memcpy(ptr, rtsx_pci_get_cmd_data(pcr), buf_len % 256);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_read_ppbuf);
+
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len)
+{
+       int err;
+       int i, j;
+       u16 reg;
+       u8 *ptr;
+
+       if (buf_len > 512)
+               buf_len = 512;
+
+       ptr = buf;
+       reg = PPBUF_BASE2;
+       for (i = 0; i < buf_len / 256; i++) {
+               rtsx_pci_init_cmd(pcr);
+
+               for (j = 0; j < 256; j++) {
+                       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                                       reg++, 0xFF, *ptr);
+                       ptr++;
+               }
+
+               err = rtsx_pci_send_cmd(pcr, 250);
+               if (err < 0)
+                       return err;
+       }
+
+       if (buf_len % 256) {
+               rtsx_pci_init_cmd(pcr);
+
+               for (j = 0; j < buf_len % 256; j++) {
+                       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                                       reg++, 0xFF, *ptr);
+                       ptr++;
+               }
+
+               err = rtsx_pci_send_cmd(pcr, 250);
+               if (err < 0)
+                       return err;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_write_ppbuf);
+
+static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl)
+{
+       rtsx_pci_init_cmd(pcr);
+
+       while (*tbl & 0xFFFF0000) {
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD,
+                               (u16)(*tbl >> 16), 0xFF, (u8)(*tbl));
+               tbl++;
+       }
+
+       return rtsx_pci_send_cmd(pcr, 100);
+}
+
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card)
+{
+       const u32 *tbl;
+
+       if (card == RTSX_SD_CARD)
+               tbl = pcr->sd_pull_ctl_enable_tbl;
+       else if (card == RTSX_MS_CARD)
+               tbl = pcr->ms_pull_ctl_enable_tbl;
+       else
+               return -EINVAL;
+
+       return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_enable);
+
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card)
+{
+       const u32 *tbl;
+
+       if (card == RTSX_SD_CARD)
+               tbl = pcr->sd_pull_ctl_disable_tbl;
+       else if (card == RTSX_MS_CARD)
+               tbl = pcr->ms_pull_ctl_disable_tbl;
+       else
+               return -EINVAL;
+
+
+       return rtsx_pci_set_pull_ctl(pcr, tbl);
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_pull_ctl_disable);
+
+static void rtsx_pci_enable_bus_int(struct rtsx_pcr *pcr)
+{
+       pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN;
+
+       if (pcr->num_slots > 1)
+               pcr->bier |= MS_INT_EN;
+
+       /* Enable Bus Interrupt */
+       rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier);
+
+       pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier);
+}
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+       return ((depth > 1) ? (depth - 1) : depth);
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+       if (div > CLK_DIV_1) {
+               if (ssc_depth > (div - 1))
+                       ssc_depth -= (div - 1);
+               else
+                       ssc_depth = SSC_DEPTH_4M;
+       }
+
+       return ssc_depth;
+}
+
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+       int err, clk;
+       u8 n, clk_divider, mcu_cnt, div;
+       static const u8 depth[] = {
+               [RTSX_SSC_DEPTH_4M] = SSC_DEPTH_4M,
+               [RTSX_SSC_DEPTH_2M] = SSC_DEPTH_2M,
+               [RTSX_SSC_DEPTH_1M] = SSC_DEPTH_1M,
+               [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K,
+               [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K,
+       };
+
+       if (initial_mode) {
+               /* We use 250k(around) here, in initial stage */
+               clk_divider = SD_CLK_DIVIDE_128;
+               card_clock = 30000000;
+       } else {
+               clk_divider = SD_CLK_DIVIDE_0;
+       }
+       err = rtsx_pci_write_register(pcr, SD_CFG1,
+                       SD_CLK_DIVIDE_MASK, clk_divider);
+       if (err < 0)
+               return err;
+
+       /* Reduce card clock by 20MHz each time a DMA transfer error occurs */
+       if (card_clock == UHS_SDR104_MAX_DTR &&
+           pcr->dma_error_count &&
+           PCI_PID(pcr) == RTS5227_DEVICE_ID)
+               card_clock = UHS_SDR104_MAX_DTR -
+                       (pcr->dma_error_count * 20000000);
+
+       card_clock /= 1000000;
+       pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock);
+
+       clk = card_clock;
+       if (!initial_mode && double_clk)
+               clk = card_clock * 2;
+       pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n",
+               clk, pcr->cur_clock);
+
+       if (clk == pcr->cur_clock)
+               return 0;
+
+       if (pcr->ops->conv_clk_and_div_n)
+               n = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
+       else
+               n = (u8)(clk - 2);
+       if ((clk <= 2) || (n > MAX_DIV_N_PCR))
+               return -EINVAL;
+
+       mcu_cnt = (u8)(125/clk + 3);
+       if (mcu_cnt > 15)
+               mcu_cnt = 15;
+
+       /* Make sure that the SSC clock div_n is not less than MIN_DIV_N_PCR */
+       div = CLK_DIV_1;
+       while ((n < MIN_DIV_N_PCR) && (div < CLK_DIV_8)) {
+               if (pcr->ops->conv_clk_and_div_n) {
+                       int dbl_clk = pcr->ops->conv_clk_and_div_n(n,
+                                       DIV_N_TO_CLK) * 2;
+                       n = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk,
+                                       CLK_TO_DIV_N);
+               } else {
+                       n = (n + 2) * 2 - 2;
+               }
+               div++;
+       }
+       pcr_dbg(pcr, "n = %d, div = %d\n", n, div);
+
+       ssc_depth = depth[ssc_depth];
+       if (double_clk)
+               ssc_depth = double_ssc_depth(ssc_depth);
+
+       ssc_depth = revise_ssc_depth(ssc_depth, div);
+       pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth);
+
+       rtsx_pci_init_cmd(pcr);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL,
+                       CLK_LOW_FREQ, CLK_LOW_FREQ);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV,
+                       0xFF, (div << 4) | mcu_cnt);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2,
+                       SSC_DEPTH_MASK, ssc_depth);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+       if (vpclk) {
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, 0);
+               rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, PHASE_NOT_RESET);
+       }
+
+       err = rtsx_pci_send_cmd(pcr, 2000);
+       if (err < 0)
+               return err;
+
+       /* Wait SSC clock stable */
+       udelay(10);
+       err = rtsx_pci_write_register(pcr, CLK_CTL, CLK_LOW_FREQ, 0);
+       if (err < 0)
+               return err;
+
+       pcr->cur_clock = clk;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_clock);
+
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card)
+{
+       if (pcr->ops->card_power_on)
+               return pcr->ops->card_power_on(pcr, card);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_on);
+
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card)
+{
+       if (pcr->ops->card_power_off)
+               return pcr->ops->card_power_off(pcr, card);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
+
+int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card)
+{
+       static const unsigned int cd_mask[] = {
+               [RTSX_SD_CARD] = SD_EXIST,
+               [RTSX_MS_CARD] = MS_EXIST
+       };
+
+       if (!(pcr->flags & 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)
+               return pcr->ops->switch_output_voltage(pcr, voltage);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage);
+
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
+{
+       unsigned int val;
+
+       val = rtsx_pci_readl(pcr, RTSX_BIPR);
+       if (pcr->ops->cd_deglitch)
+               val = pcr->ops->cd_deglitch(pcr);
+
+       return val;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_card_exist);
+
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr)
+{
+       struct completion finish;
+
+       pcr->finish_me = &finish;
+       init_completion(&finish);
+
+       if (pcr->done)
+               complete(pcr->done);
+
+       if (!pcr->remove_pci)
+               rtsx_pci_stop_cmd(pcr);
+
+       wait_for_completion_interruptible_timeout(&finish,
+                       msecs_to_jiffies(2));
+       pcr->finish_me = NULL;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_complete_unfinished_transfer);
+
+static void rtsx_pci_card_detect(struct work_struct *work)
+{
+       struct delayed_work *dwork;
+       struct rtsx_pcr *pcr;
+       unsigned long flags;
+       unsigned int card_detect = 0, card_inserted, card_removed;
+       u32 irq_status;
+
+       dwork = to_delayed_work(work);
+       pcr = container_of(dwork, struct rtsx_pcr, carddet_work);
+
+       pcr_dbg(pcr, "--> %s\n", __func__);
+
+       mutex_lock(&pcr->pcr_mutex);
+       spin_lock_irqsave(&pcr->lock, flags);
+
+       irq_status = rtsx_pci_readl(pcr, RTSX_BIPR);
+       pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status);
+
+       irq_status &= CARD_EXIST;
+       card_inserted = pcr->card_inserted & irq_status;
+       card_removed = pcr->card_removed;
+       pcr->card_inserted = 0;
+       pcr->card_removed = 0;
+
+       spin_unlock_irqrestore(&pcr->lock, flags);
+
+       if (card_inserted || card_removed) {
+               pcr_dbg(pcr, "card_inserted: 0x%x, card_removed: 0x%x\n",
+                       card_inserted, card_removed);
+
+               if (pcr->ops->cd_deglitch)
+                       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);
+
+       if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
+               pcr->slots[RTSX_SD_CARD].card_event(
+                               pcr->slots[RTSX_SD_CARD].p_dev);
+       if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event)
+               pcr->slots[RTSX_MS_CARD].card_event(
+                               pcr->slots[RTSX_MS_CARD].p_dev);
+}
+
+static irqreturn_t rtsx_pci_isr(int irq, void *dev_id)
+{
+       struct rtsx_pcr *pcr = dev_id;
+       u32 int_reg;
+
+       if (!pcr)
+               return IRQ_NONE;
+
+       spin_lock(&pcr->lock);
+
+       int_reg = rtsx_pci_readl(pcr, RTSX_BIPR);
+       /* Clear interrupt flag */
+       rtsx_pci_writel(pcr, RTSX_BIPR, int_reg);
+       if ((int_reg & pcr->bier) == 0) {
+               spin_unlock(&pcr->lock);
+               return IRQ_NONE;
+       }
+       if (int_reg == 0xFFFFFFFF) {
+               spin_unlock(&pcr->lock);
+               return IRQ_HANDLED;
+       }
+
+       int_reg &= (pcr->bier | 0x7FFFFF);
+
+       if (int_reg & SD_INT) {
+               if (int_reg & SD_EXIST) {
+                       pcr->card_inserted |= SD_EXIST;
+               } else {
+                       pcr->card_removed |= SD_EXIST;
+                       pcr->card_inserted &= ~SD_EXIST;
+               }
+               pcr->dma_error_count = 0;
+       }
+
+       if (int_reg & MS_INT) {
+               if (int_reg & MS_EXIST) {
+                       pcr->card_inserted |= MS_EXIST;
+               } else {
+                       pcr->card_removed |= MS_EXIST;
+                       pcr->card_inserted &= ~MS_EXIST;
+               }
+       }
+
+       if (int_reg & (NEED_COMPLETE_INT | DELINK_INT)) {
+               if (int_reg & (TRANS_FAIL_INT | DELINK_INT)) {
+                       pcr->trans_result = TRANS_RESULT_FAIL;
+                       if (pcr->done)
+                               complete(pcr->done);
+               } else if (int_reg & TRANS_OK_INT) {
+                       pcr->trans_result = TRANS_RESULT_OK;
+                       if (pcr->done)
+                               complete(pcr->done);
+               }
+       }
+
+       if (pcr->card_inserted || pcr->card_removed)
+               schedule_delayed_work(&pcr->carddet_work,
+                               msecs_to_jiffies(200));
+
+       spin_unlock(&pcr->lock);
+       return IRQ_HANDLED;
+}
+
+static int rtsx_pci_acquire_irq(struct rtsx_pcr *pcr)
+{
+       pcr_dbg(pcr, "%s: pcr->msi_en = %d, pci->irq = %d\n",
+                       __func__, pcr->msi_en, pcr->pci->irq);
+
+       if (request_irq(pcr->pci->irq, rtsx_pci_isr,
+                       pcr->msi_en ? 0 : IRQF_SHARED,
+                       DRV_NAME_RTSX_PCI, pcr)) {
+               dev_err(&(pcr->pci->dev),
+                       "rtsx_sdmmc: unable to grab IRQ %d, disabling device\n",
+                       pcr->pci->irq);
+               return -1;
+       }
+
+       pcr->irq = pcr->pci->irq;
+       pci_intx(pcr->pci, !pcr->msi_en);
+
+       return 0;
+}
+
+static void rtsx_enable_aspm(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->set_aspm)
+               pcr->ops->set_aspm(pcr, true);
+       else
+               rtsx_comm_set_aspm(pcr, true);
+}
+
+static void rtsx_comm_pm_power_saving(struct rtsx_pcr *pcr)
+{
+       struct rtsx_cr_option *option = &pcr->option;
+
+       if (option->ltr_enabled) {
+               u32 latency = option->ltr_l1off_latency;
+
+               if (rtsx_check_dev_flag(pcr, L1_SNOOZE_TEST_EN))
+                       mdelay(option->l1_snooze_delay);
+
+               rtsx_set_ltr_latency(pcr, latency);
+       }
+
+       if (rtsx_check_dev_flag(pcr, LTR_L1SS_PWR_GATE_EN))
+               rtsx_set_l1off_sub_cfg_d0(pcr, 0);
+
+       rtsx_enable_aspm(pcr);
+}
+
+void rtsx_pm_power_saving(struct rtsx_pcr *pcr)
+{
+       if (pcr->ops->power_saving)
+               pcr->ops->power_saving(pcr);
+       else
+               rtsx_comm_pm_power_saving(pcr);
+}
+
+static void rtsx_pci_idle_work(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work);
+
+       pcr_dbg(pcr, "--> %s\n", __func__);
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       pcr->state = PDEV_STAT_IDLE;
+
+       if (pcr->ops->disable_auto_blink)
+               pcr->ops->disable_auto_blink(pcr);
+       if (pcr->ops->turn_off_led)
+               pcr->ops->turn_off_led(pcr);
+
+       rtsx_pm_power_saving(pcr);
+
+       mutex_unlock(&pcr->pcr_mutex);
+}
+
+#ifdef CONFIG_PM
+static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state)
+{
+       if (pcr->ops->turn_off_led)
+               pcr->ops->turn_off_led(pcr);
+
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+
+       rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08);
+       rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state);
+
+       if (pcr->ops->force_power_down)
+               pcr->ops->force_power_down(pcr, pm_state);
+}
+#endif
+
+static int rtsx_pci_init_hw(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP);
+       rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr);
+
+       rtsx_pci_enable_bus_int(pcr);
+
+       /* Power on SSC */
+       err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0);
+       if (err < 0)
+               return err;
+
+       /* Wait SSC power stable */
+       udelay(200);
+
+       rtsx_pci_disable_aspm(pcr);
+       if (pcr->ops->optimize_phy) {
+               err = pcr->ops->optimize_phy(pcr);
+               if (err < 0)
+                       return err;
+       }
+
+       rtsx_pci_init_cmd(pcr);
+
+       /* Set mcu_cnt to 7 to ensure data can be sampled properly */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_DIV, 0x07, 0x07);
+
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, HOST_SLEEP_STATE, 0x03, 0x00);
+       /* Disable card clock */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_CLK_EN, 0x1E, 0);
+       /* Reset delink mode */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x0A, 0);
+       /* Card driving select */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CARD_DRIVE_SEL,
+                       0xFF, pcr->card_drive_sel);
+       /* Enable SSC Clock */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL1,
+                       0xFF, SSC_8X_EN | SSC_SEL_4M);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, 0x12);
+       /* Disable cd_pwr_save */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CHANGE_LINK_STATE, 0x16, 0x10);
+       /* Clear Link Ready Interrupt */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, IRQSTAT0,
+                       LINK_RDY_INT, LINK_RDY_INT);
+       /* Enlarge the estimation window of PERST# glitch
+        * to reduce the chance of invalid card interrupt
+        */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PERST_GLITCH_WIDTH, 0xFF, 0x80);
+       /* Update RC oscillator to 400k
+        * bit[0] F_HIGH: for RC oscillator, Rst_value is 1'b1
+        *                1: 2M  0: 400k
+        */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, RCCTL, 0x01, 0x00);
+       /* Set interrupt write clear
+        * bit 1: U_elbi_if_rd_clr_en
+        *      1: Enable ELBI interrupt[31:22] & [7:0] flag read clear
+        *      0: ELBI interrupt flag[31:22] & [7:0] only can be write clear
+        */
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, NFTS_TX_CTRL, 0x02, 0);
+
+       err = rtsx_pci_send_cmd(pcr, 100);
+       if (err < 0)
+               return err;
+
+       switch (PCI_PID(pcr)) {
+       case PID_5250:
+       case PID_524A:
+       case PID_525A:
+               rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1);
+               break;
+       default:
+               break;
+       }
+
+       /* Enable clk_request_n to enable clock power management */
+       rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1);
+       /* Enter L1 when host tx idle */
+       rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B);
+
+       if (pcr->ops->extra_init_hw) {
+               err = pcr->ops->extra_init_hw(pcr);
+               if (err < 0)
+                       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;
+}
+
+static int rtsx_pci_init_chip(struct rtsx_pcr *pcr)
+{
+       int err;
+
+       spin_lock_init(&pcr->lock);
+       mutex_init(&pcr->pcr_mutex);
+
+       switch (PCI_PID(pcr)) {
+       default:
+       case 0x5209:
+               rts5209_init_params(pcr);
+               break;
+
+       case 0x5229:
+               rts5229_init_params(pcr);
+               break;
+
+       case 0x5289:
+               rtl8411_init_params(pcr);
+               break;
+
+       case 0x5227:
+               rts5227_init_params(pcr);
+               break;
+
+       case 0x522A:
+               rts522a_init_params(pcr);
+               break;
+
+       case 0x5249:
+               rts5249_init_params(pcr);
+               break;
+
+       case 0x524A:
+               rts524a_init_params(pcr);
+               break;
+
+       case 0x525A:
+               rts525a_init_params(pcr);
+               break;
+
+       case 0x5287:
+               rtl8411b_init_params(pcr);
+               break;
+
+       case 0x5286:
+               rtl8402_init_params(pcr);
+               break;
+       }
+
+       pcr_dbg(pcr, "PID: 0x%04x, IC version: 0x%02x\n",
+                       PCI_PID(pcr), pcr->ic_version);
+
+       pcr->slots = kcalloc(pcr->num_slots, sizeof(struct rtsx_slot),
+                       GFP_KERNEL);
+       if (!pcr->slots)
+               return -ENOMEM;
+
+       if (pcr->ops->fetch_vendor_settings)
+               pcr->ops->fetch_vendor_settings(pcr);
+
+       pcr_dbg(pcr, "pcr->aspm_en = 0x%x\n", pcr->aspm_en);
+       pcr_dbg(pcr, "pcr->sd30_drive_sel_1v8 = 0x%x\n",
+                       pcr->sd30_drive_sel_1v8);
+       pcr_dbg(pcr, "pcr->sd30_drive_sel_3v3 = 0x%x\n",
+                       pcr->sd30_drive_sel_3v3);
+       pcr_dbg(pcr, "pcr->card_drive_sel = 0x%x\n",
+                       pcr->card_drive_sel);
+       pcr_dbg(pcr, "pcr->flags = 0x%x\n", pcr->flags);
+
+       pcr->state = PDEV_STAT_IDLE;
+       err = rtsx_pci_init_hw(pcr);
+       if (err < 0) {
+               kfree(pcr->slots);
+               return err;
+       }
+
+       return 0;
+}
+
+static int rtsx_pci_probe(struct pci_dev *pcidev,
+                         const struct pci_device_id *id)
+{
+       struct rtsx_pcr *pcr;
+       struct pcr_handle *handle;
+       u32 base, len;
+       int ret, i, bar = 0;
+
+       dev_dbg(&(pcidev->dev),
+               ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n",
+               pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device,
+               (int)pcidev->revision);
+
+       ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32));
+       if (ret < 0)
+               return ret;
+
+       ret = pci_enable_device(pcidev);
+       if (ret)
+               return ret;
+
+       ret = pci_request_regions(pcidev, DRV_NAME_RTSX_PCI);
+       if (ret)
+               goto disable;
+
+       pcr = kzalloc(sizeof(*pcr), GFP_KERNEL);
+       if (!pcr) {
+               ret = -ENOMEM;
+               goto release_pci;
+       }
+
+       handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+       if (!handle) {
+               ret = -ENOMEM;
+               goto free_pcr;
+       }
+       handle->pcr = pcr;
+
+       idr_preload(GFP_KERNEL);
+       spin_lock(&rtsx_pci_lock);
+       ret = idr_alloc(&rtsx_pci_idr, pcr, 0, 0, GFP_NOWAIT);
+       if (ret >= 0)
+               pcr->id = ret;
+       spin_unlock(&rtsx_pci_lock);
+       idr_preload_end();
+       if (ret < 0)
+               goto free_handle;
+
+       pcr->pci = pcidev;
+       dev_set_drvdata(&pcidev->dev, handle);
+
+       if (CHK_PCI_PID(pcr, 0x525A))
+               bar = 1;
+       len = pci_resource_len(pcidev, bar);
+       base = pci_resource_start(pcidev, bar);
+       pcr->remap_addr = ioremap_nocache(base, len);
+       if (!pcr->remap_addr) {
+               ret = -ENOMEM;
+               goto free_handle;
+       }
+
+       pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev),
+                       RTSX_RESV_BUF_LEN, &(pcr->rtsx_resv_buf_addr),
+                       GFP_KERNEL);
+       if (pcr->rtsx_resv_buf == NULL) {
+               ret = -ENXIO;
+               goto unmap;
+       }
+       pcr->host_cmds_ptr = pcr->rtsx_resv_buf;
+       pcr->host_cmds_addr = pcr->rtsx_resv_buf_addr;
+       pcr->host_sg_tbl_ptr = pcr->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
+       pcr->host_sg_tbl_addr = pcr->rtsx_resv_buf_addr + HOST_CMDS_BUF_LEN;
+
+       pcr->card_inserted = 0;
+       pcr->card_removed = 0;
+       INIT_DELAYED_WORK(&pcr->carddet_work, rtsx_pci_card_detect);
+       INIT_DELAYED_WORK(&pcr->idle_work, rtsx_pci_idle_work);
+
+       pcr->msi_en = msi_en;
+       if (pcr->msi_en) {
+               ret = pci_enable_msi(pcidev);
+               if (ret)
+                       pcr->msi_en = false;
+       }
+
+       ret = rtsx_pci_acquire_irq(pcr);
+       if (ret < 0)
+               goto disable_msi;
+
+       pci_set_master(pcidev);
+       synchronize_irq(pcr->irq);
+
+       ret = rtsx_pci_init_chip(pcr);
+       if (ret < 0)
+               goto disable_irq;
+
+       for (i = 0; i < ARRAY_SIZE(rtsx_pcr_cells); i++) {
+               rtsx_pcr_cells[i].platform_data = handle;
+               rtsx_pcr_cells[i].pdata_size = sizeof(*handle);
+       }
+       ret = mfd_add_devices(&pcidev->dev, pcr->id, rtsx_pcr_cells,
+                       ARRAY_SIZE(rtsx_pcr_cells), NULL, 0, NULL);
+       if (ret < 0)
+               goto disable_irq;
+
+       schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+       return 0;
+
+disable_irq:
+       free_irq(pcr->irq, (void *)pcr);
+disable_msi:
+       if (pcr->msi_en)
+               pci_disable_msi(pcr->pci);
+       dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+                       pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+unmap:
+       iounmap(pcr->remap_addr);
+free_handle:
+       kfree(handle);
+free_pcr:
+       kfree(pcr);
+release_pci:
+       pci_release_regions(pcidev);
+disable:
+       pci_disable_device(pcidev);
+
+       return ret;
+}
+
+static void rtsx_pci_remove(struct pci_dev *pcidev)
+{
+       struct pcr_handle *handle = pci_get_drvdata(pcidev);
+       struct rtsx_pcr *pcr = handle->pcr;
+
+       pcr->remove_pci = true;
+
+       /* Disable interrupts at the pcr level */
+       spin_lock_irq(&pcr->lock);
+       rtsx_pci_writel(pcr, RTSX_BIER, 0);
+       pcr->bier = 0;
+       spin_unlock_irq(&pcr->lock);
+
+       cancel_delayed_work_sync(&pcr->carddet_work);
+       cancel_delayed_work_sync(&pcr->idle_work);
+
+       mfd_remove_devices(&pcidev->dev);
+
+       dma_free_coherent(&(pcr->pci->dev), RTSX_RESV_BUF_LEN,
+                       pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr);
+       free_irq(pcr->irq, (void *)pcr);
+       if (pcr->msi_en)
+               pci_disable_msi(pcr->pci);
+       iounmap(pcr->remap_addr);
+
+       pci_release_regions(pcidev);
+       pci_disable_device(pcidev);
+
+       spin_lock(&rtsx_pci_lock);
+       idr_remove(&rtsx_pci_idr, pcr->id);
+       spin_unlock(&rtsx_pci_lock);
+
+       kfree(pcr->slots);
+       kfree(pcr);
+       kfree(handle);
+
+       dev_dbg(&(pcidev->dev),
+               ": Realtek PCI-E Card Reader at %s [%04x:%04x] has been removed\n",
+               pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device);
+}
+
+#ifdef CONFIG_PM
+
+static int rtsx_pci_suspend(struct pci_dev *pcidev, pm_message_t state)
+{
+       struct pcr_handle *handle;
+       struct rtsx_pcr *pcr;
+
+       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+       handle = pci_get_drvdata(pcidev);
+       pcr = handle->pcr;
+
+       cancel_delayed_work(&pcr->carddet_work);
+       cancel_delayed_work(&pcr->idle_work);
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       rtsx_pci_power_off(pcr, HOST_ENTER_S3);
+
+       pci_save_state(pcidev);
+       pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0);
+       pci_disable_device(pcidev);
+       pci_set_power_state(pcidev, pci_choose_state(pcidev, state));
+
+       mutex_unlock(&pcr->pcr_mutex);
+       return 0;
+}
+
+static int rtsx_pci_resume(struct pci_dev *pcidev)
+{
+       struct pcr_handle *handle;
+       struct rtsx_pcr *pcr;
+       int ret = 0;
+
+       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+       handle = pci_get_drvdata(pcidev);
+       pcr = handle->pcr;
+
+       mutex_lock(&pcr->pcr_mutex);
+
+       pci_set_power_state(pcidev, PCI_D0);
+       pci_restore_state(pcidev);
+       ret = pci_enable_device(pcidev);
+       if (ret)
+               goto out;
+       pci_set_master(pcidev);
+
+       ret = rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, 0x00);
+       if (ret)
+               goto out;
+
+       ret = rtsx_pci_init_hw(pcr);
+       if (ret)
+               goto out;
+
+       schedule_delayed_work(&pcr->idle_work, msecs_to_jiffies(200));
+
+out:
+       mutex_unlock(&pcr->pcr_mutex);
+       return ret;
+}
+
+static void rtsx_pci_shutdown(struct pci_dev *pcidev)
+{
+       struct pcr_handle *handle;
+       struct rtsx_pcr *pcr;
+
+       dev_dbg(&(pcidev->dev), "--> %s\n", __func__);
+
+       handle = pci_get_drvdata(pcidev);
+       pcr = handle->pcr;
+       rtsx_pci_power_off(pcr, HOST_ENTER_S1);
+
+       pci_disable_device(pcidev);
+       free_irq(pcr->irq, (void *)pcr);
+       if (pcr->msi_en)
+               pci_disable_msi(pcr->pci);
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_pci_suspend NULL
+#define rtsx_pci_resume NULL
+#define rtsx_pci_shutdown NULL
+
+#endif /* CONFIG_PM */
+
+static struct pci_driver rtsx_pci_driver = {
+       .name = DRV_NAME_RTSX_PCI,
+       .id_table = rtsx_pci_ids,
+       .probe = rtsx_pci_probe,
+       .remove = rtsx_pci_remove,
+       .suspend = rtsx_pci_suspend,
+       .resume = rtsx_pci_resume,
+       .shutdown = rtsx_pci_shutdown,
+};
+module_pci_driver(rtsx_pci_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Wei WANG <wei_wang@realsil.com.cn>");
+MODULE_DESCRIPTION("Realtek PCI-E Card Reader Driver");
diff --git a/drivers/misc/cardreader/rtsx_pcr.h b/drivers/misc/cardreader/rtsx_pcr.h
new file mode 100644 (file)
index 0000000..b0691c9
--- /dev/null
@@ -0,0 +1,103 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#ifndef __RTSX_PCR_H
+#define __RTSX_PCR_H
+
+#include <linux/rtsx_pci.h>
+
+#define MIN_DIV_N_PCR          80
+#define MAX_DIV_N_PCR          208
+
+#define RTS522A_PM_CTRL3               0xFF7E
+
+#define RTS524A_PME_FORCE_CTL          0xFF78
+#define RTS524A_PM_CTRL3               0xFF7E
+
+#define LTR_ACTIVE_LATENCY_DEF         0x883C
+#define LTR_IDLE_LATENCY_DEF           0x892C
+#define LTR_L1OFF_LATENCY_DEF          0x9003
+#define L1_SNOOZE_DELAY_DEF            1
+#define LTR_L1OFF_SSPWRGATE_5249_DEF           0xAF
+#define LTR_L1OFF_SSPWRGATE_5250_DEF           0xFF
+#define LTR_L1OFF_SNOOZE_SSPWRGATE_5249_DEF    0xAC
+#define LTR_L1OFF_SNOOZE_SSPWRGATE_5250_DEF    0xF8
+#define CMD_TIMEOUT_DEF                100
+#define ASPM_MASK_NEG          0xFC
+#define MASK_8_BIT_DEF         0xFF
+
+int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
+int __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+
+void rts5209_init_params(struct rtsx_pcr *pcr);
+void rts5229_init_params(struct rtsx_pcr *pcr);
+void rtl8411_init_params(struct rtsx_pcr *pcr);
+void rtl8402_init_params(struct rtsx_pcr *pcr);
+void rts5227_init_params(struct rtsx_pcr *pcr);
+void rts522a_init_params(struct rtsx_pcr *pcr);
+void rts5249_init_params(struct rtsx_pcr *pcr);
+void rts524a_init_params(struct rtsx_pcr *pcr);
+void rts525a_init_params(struct rtsx_pcr *pcr);
+void rtl8411b_init_params(struct rtsx_pcr *pcr);
+
+static inline u8 map_sd_drive(int idx)
+{
+       u8 sd_drive[4] = {
+               0x01,   /* Type D */
+               0x02,   /* Type C */
+               0x05,   /* Type A */
+               0x03    /* Type B */
+       };
+
+       return sd_drive[idx];
+}
+
+#define rtsx_vendor_setting_valid(reg)         (!((reg) & 0x1000000))
+#define rts5209_vendor_setting1_valid(reg)     (!((reg) & 0x80))
+#define rts5209_vendor_setting2_valid(reg)     ((reg) & 0x80)
+
+#define rtsx_reg_to_aspm(reg)                  (((reg) >> 28) & 0x03)
+#define rtsx_reg_to_sd30_drive_sel_1v8(reg)    (((reg) >> 26) & 0x03)
+#define rtsx_reg_to_sd30_drive_sel_3v3(reg)    (((reg) >> 5) & 0x03)
+#define rtsx_reg_to_card_drive_sel(reg)                ((((reg) >> 25) & 0x01) << 6)
+#define rtsx_reg_check_reverse_socket(reg)     ((reg) & 0x4000)
+#define rts5209_reg_to_aspm(reg)               (((reg) >> 5) & 0x03)
+#define rts5209_reg_check_ms_pmos(reg)         (!((reg) & 0x08))
+#define rts5209_reg_to_sd30_drive_sel_1v8(reg) (((reg) >> 3) & 0x07)
+#define rts5209_reg_to_sd30_drive_sel_3v3(reg) ((reg) & 0x07)
+#define rts5209_reg_to_card_drive_sel(reg)     ((reg) >> 8)
+#define rtl8411_reg_to_sd30_drive_sel_3v3(reg) (((reg) >> 5) & 0x07)
+#define rtl8411b_reg_to_sd30_drive_sel_3v3(reg)        ((reg) & 0x03)
+
+#define set_pull_ctrl_tables(pcr, __device)                            \
+do {                                                                   \
+       pcr->sd_pull_ctl_enable_tbl  = __device##_sd_pull_ctl_enable_tbl;  \
+       pcr->sd_pull_ctl_disable_tbl = __device##_sd_pull_ctl_disable_tbl; \
+       pcr->ms_pull_ctl_enable_tbl  = __device##_ms_pull_ctl_enable_tbl;  \
+       pcr->ms_pull_ctl_disable_tbl = __device##_ms_pull_ctl_disable_tbl; \
+} while (0)
+
+/* generic operations */
+int rtsx_gops_pm_reset(struct rtsx_pcr *pcr);
+int rtsx_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency);
+int rtsx_set_l1off_sub(struct rtsx_pcr *pcr, u8 val);
+
+#endif
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
new file mode 100644 (file)
index 0000000..b97903f
--- /dev/null
@@ -0,0 +1,791 @@
+/* Driver for Realtek USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/usb.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/core.h>
+#include <linux/rtsx_usb.h>
+
+static int polling_pipe = 1;
+module_param(polling_pipe, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
+
+static const struct mfd_cell rtsx_usb_cells[] = {
+       [RTSX_USB_SD_CARD] = {
+               .name = "rtsx_usb_sdmmc",
+               .pdata_size = 0,
+       },
+       [RTSX_USB_MS_CARD] = {
+               .name = "rtsx_usb_ms",
+               .pdata_size = 0,
+       },
+};
+
+static void rtsx_usb_sg_timed_out(struct timer_list *t)
+{
+       struct rtsx_ucr *ucr = from_timer(ucr, t, sg_timer);
+
+       dev_dbg(&ucr->pusb_intf->dev, "%s: sg transfer timed out", __func__);
+       usb_sg_cancel(&ucr->current_sg);
+}
+
+static int rtsx_usb_bulk_transfer_sglist(struct rtsx_ucr *ucr,
+               unsigned int pipe, struct scatterlist *sg, int num_sg,
+               unsigned int length, unsigned int *act_len, int timeout)
+{
+       int ret;
+
+       dev_dbg(&ucr->pusb_intf->dev, "%s: xfer %u bytes, %d entries\n",
+                       __func__, length, num_sg);
+       ret = usb_sg_init(&ucr->current_sg, ucr->pusb_dev, pipe, 0,
+                       sg, num_sg, length, GFP_NOIO);
+       if (ret)
+               return ret;
+
+       ucr->sg_timer.expires = jiffies + msecs_to_jiffies(timeout);
+       add_timer(&ucr->sg_timer);
+       usb_sg_wait(&ucr->current_sg);
+       if (!del_timer_sync(&ucr->sg_timer))
+               ret = -ETIMEDOUT;
+       else
+               ret = ucr->current_sg.status;
+
+       if (act_len)
+               *act_len = ucr->current_sg.bytes;
+
+       return ret;
+}
+
+int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+                             void *buf, unsigned int len, int num_sg,
+                             unsigned int *act_len, int timeout)
+{
+       if (timeout < 600)
+               timeout = 600;
+
+       if (num_sg)
+               return rtsx_usb_bulk_transfer_sglist(ucr, pipe,
+                               (struct scatterlist *)buf, num_sg, len, act_len,
+                               timeout);
+       else
+               return usb_bulk_msg(ucr->pusb_dev, pipe, buf, len, act_len,
+                               timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_transfer_data);
+
+static inline void rtsx_usb_seq_cmd_hdr(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 seq_type)
+{
+       rtsx_usb_cmd_hdr_tag(ucr);
+
+       ucr->cmd_buf[PACKET_TYPE] = seq_type;
+       ucr->cmd_buf[5] = (u8)(len >> 8);
+       ucr->cmd_buf[6] = (u8)len;
+       ucr->cmd_buf[8] = (u8)(addr >> 8);
+       ucr->cmd_buf[9] = (u8)addr;
+
+       if (seq_type == SEQ_WRITE)
+               ucr->cmd_buf[STAGE_FLAG] = 0;
+       else
+               ucr->cmd_buf[STAGE_FLAG] = STAGE_R;
+}
+
+static int rtsx_usb_seq_write_register(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 *data)
+{
+       u16 cmd_len = ALIGN(SEQ_WRITE_DATA_OFFSET + len, 4);
+
+       if (!data)
+               return -EINVAL;
+
+       if (cmd_len > IOBUF_SIZE)
+               return -EINVAL;
+
+       rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_WRITE);
+       memcpy(ucr->cmd_buf + SEQ_WRITE_DATA_OFFSET, data, len);
+
+       return rtsx_usb_transfer_data(ucr,
+                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                       ucr->cmd_buf, cmd_len, 0, NULL, 100);
+}
+
+static int rtsx_usb_seq_read_register(struct rtsx_ucr *ucr,
+               u16 addr, u16 len, u8 *data)
+{
+       int i, ret;
+       u16 rsp_len = round_down(len, 4);
+       u16 res_len = len - rsp_len;
+
+       if (!data)
+               return -EINVAL;
+
+       /* 4-byte aligned part */
+       if (rsp_len) {
+               rtsx_usb_seq_cmd_hdr(ucr, addr, len, SEQ_READ);
+               ret = rtsx_usb_transfer_data(ucr,
+                               usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                               ucr->cmd_buf, 12, 0, NULL, 100);
+               if (ret)
+                       return ret;
+
+               ret = rtsx_usb_transfer_data(ucr,
+                               usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+                               data, rsp_len, 0, NULL, 100);
+               if (ret)
+                       return ret;
+       }
+
+       /* unaligned part */
+       for (i = 0; i < res_len; i++) {
+               ret = rtsx_usb_read_register(ucr, addr + rsp_len + i,
+                               data + rsp_len + i);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+       return rtsx_usb_seq_read_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_ppbuf);
+
+int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len)
+{
+       return rtsx_usb_seq_write_register(ucr, PPBUF_BASE2, (u16)buf_len, buf);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_ppbuf);
+
+int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr,
+               u8 mask, u8 data)
+{
+       u16 value, index;
+
+       addr |= EP0_WRITE_REG_CMD << EP0_OP_SHIFT;
+       value = swab16(addr);
+       index = mask | data << 8;
+
+       return usb_control_msg(ucr->pusb_dev,
+                       usb_sndctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, index, NULL, 0, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_write_register);
+
+int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+       u16 value;
+       u8 *buf;
+       int ret;
+
+       if (!data)
+               return -EINVAL;
+
+       buf = kzalloc(sizeof(u8), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       addr |= EP0_READ_REG_CMD << EP0_OP_SHIFT;
+       value = swab16(addr);
+
+       ret = usb_control_msg(ucr->pusb_dev,
+                       usb_rcvctrlpipe(ucr->pusb_dev, 0), RTSX_USB_REQ_REG_OP,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, 0, buf, 1, 100);
+       *data = *buf;
+
+       kfree(buf);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_ep0_read_register);
+
+void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type, u16 reg_addr,
+               u8 mask, u8 data)
+{
+       int i;
+
+       if (ucr->cmd_idx < (IOBUF_SIZE - CMD_OFFSET) / 4) {
+               i = CMD_OFFSET + ucr->cmd_idx * 4;
+
+               ucr->cmd_buf[i++] = ((cmd_type & 0x03) << 6) |
+                       (u8)((reg_addr >> 8) & 0x3F);
+               ucr->cmd_buf[i++] = (u8)reg_addr;
+               ucr->cmd_buf[i++] = mask;
+               ucr->cmd_buf[i++] = data;
+
+               ucr->cmd_idx++;
+       }
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_add_cmd);
+
+int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout)
+{
+       int ret;
+
+       ucr->cmd_buf[CNT_H] = (u8)(ucr->cmd_idx >> 8);
+       ucr->cmd_buf[CNT_L] = (u8)(ucr->cmd_idx);
+       ucr->cmd_buf[STAGE_FLAG] = flag;
+
+       ret = rtsx_usb_transfer_data(ucr,
+                       usb_sndbulkpipe(ucr->pusb_dev, EP_BULK_OUT),
+                       ucr->cmd_buf, ucr->cmd_idx * 4 + CMD_OFFSET,
+                       0, NULL, timeout);
+       if (ret) {
+               rtsx_usb_clear_fsm_err(ucr);
+               return ret;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_send_cmd);
+
+int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout)
+{
+       if (rsp_len <= 0)
+               return -EINVAL;
+
+       rsp_len = ALIGN(rsp_len, 4);
+
+       return rtsx_usb_transfer_data(ucr,
+                       usb_rcvbulkpipe(ucr->pusb_dev, EP_BULK_IN),
+                       ucr->rsp_buf, rsp_len, 0, NULL, timeout);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_rsp);
+
+static int rtsx_usb_get_status_with_bulk(struct rtsx_ucr *ucr, u16 *status)
+{
+       int ret;
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, CARD_EXIST, 0x00, 0x00);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, OCPSTAT, 0x00, 0x00);
+       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+       if (ret)
+               return ret;
+
+       ret = rtsx_usb_get_rsp(ucr, 2, 100);
+       if (ret)
+               return ret;
+
+       *status = ((ucr->rsp_buf[0] >> 2) & 0x0f) |
+                 ((ucr->rsp_buf[1] & 0x03) << 4);
+
+       return 0;
+}
+
+int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status)
+{
+       int ret;
+       u16 *buf;
+
+       if (!status)
+               return -EINVAL;
+
+       if (polling_pipe == 0) {
+               buf = kzalloc(sizeof(u16), GFP_KERNEL);
+               if (!buf)
+                       return -ENOMEM;
+
+               ret = usb_control_msg(ucr->pusb_dev,
+                               usb_rcvctrlpipe(ucr->pusb_dev, 0),
+                               RTSX_USB_REQ_POLL,
+                               USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                               0, 0, buf, 2, 100);
+               *status = *buf;
+
+               kfree(buf);
+       } else {
+               ret = rtsx_usb_get_status_with_bulk(ucr, status);
+       }
+
+       /* usb_control_msg may return positive when success */
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_get_card_status);
+
+static int rtsx_usb_write_phy_register(struct rtsx_ucr *ucr, u8 addr, u8 val)
+{
+       dev_dbg(&ucr->pusb_intf->dev, "Write 0x%x to phy register 0x%x\n",
+                       val, addr);
+
+       rtsx_usb_init_cmd(ucr);
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VSTAIN, 0xFF, val);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL, 0xFF, addr & 0x0F);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VCONTROL,
+                       0xFF, (addr >> 4) & 0x0F);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x00);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, HS_VLOADM, 0xFF, 0x01);
+
+       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+
+int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask, u8 data)
+{
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, addr, mask, data);
+       return rtsx_usb_send_cmd(ucr, MODE_C, 100);
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_write_register);
+
+int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data)
+{
+       int ret;
+
+       if (data != NULL)
+               *data = 0;
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, READ_REG_CMD, addr, 0, 0);
+       ret = rtsx_usb_send_cmd(ucr, MODE_CR, 100);
+       if (ret)
+               return ret;
+
+       ret = rtsx_usb_get_rsp(ucr, 1, 100);
+       if (ret)
+               return ret;
+
+       if (data != NULL)
+               *data = ucr->rsp_buf[0];
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_read_register);
+
+static inline u8 double_ssc_depth(u8 depth)
+{
+       return (depth > 1) ? (depth - 1) : depth;
+}
+
+static u8 revise_ssc_depth(u8 ssc_depth, u8 div)
+{
+       if (div > CLK_DIV_1) {
+               if (ssc_depth > div - 1)
+                       ssc_depth -= (div - 1);
+               else
+                       ssc_depth = SSC_DEPTH_2M;
+       }
+
+       return ssc_depth;
+}
+
+int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk)
+{
+       int ret;
+       u8 n, clk_divider, mcu_cnt, div;
+
+       if (!card_clock) {
+               ucr->cur_clk = 0;
+               return 0;
+       }
+
+       if (initial_mode) {
+               /* We use 250k(around) here, in initial stage */
+               clk_divider = SD_CLK_DIVIDE_128;
+               card_clock = 30000000;
+       } else {
+               clk_divider = SD_CLK_DIVIDE_0;
+       }
+
+       ret = rtsx_usb_write_register(ucr, SD_CFG1,
+                       SD_CLK_DIVIDE_MASK, clk_divider);
+       if (ret < 0)
+               return ret;
+
+       card_clock /= 1000000;
+       dev_dbg(&ucr->pusb_intf->dev,
+                       "Switch card clock to %dMHz\n", card_clock);
+
+       if (!initial_mode && double_clk)
+               card_clock *= 2;
+       dev_dbg(&ucr->pusb_intf->dev,
+                       "Internal SSC clock: %dMHz (cur_clk = %d)\n",
+                       card_clock, ucr->cur_clk);
+
+       if (card_clock == ucr->cur_clk)
+               return 0;
+
+       /* Converting clock value into internal settings: n and div */
+       n = card_clock - 2;
+       if ((card_clock <= 2) || (n > MAX_DIV_N))
+               return -EINVAL;
+
+       mcu_cnt = 60/card_clock + 3;
+       if (mcu_cnt > 15)
+               mcu_cnt = 15;
+
+       /* Make sure that the SSC clock div_n is not less than MIN_DIV_N */
+
+       div = CLK_DIV_1;
+       while (n < MIN_DIV_N && div < CLK_DIV_4) {
+               n = (n + 2) * 2 - 2;
+               div++;
+       }
+       dev_dbg(&ucr->pusb_intf->dev, "n = %d, div = %d\n", n, div);
+
+       if (double_clk)
+               ssc_depth = double_ssc_depth(ssc_depth);
+
+       ssc_depth = revise_ssc_depth(ssc_depth, div);
+       dev_dbg(&ucr->pusb_intf->dev, "ssc_depth = %d\n", ssc_depth);
+
+       rtsx_usb_init_cmd(ucr);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV, CLK_CHANGE, CLK_CHANGE);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CLK_DIV,
+                       0x3F, (div << 4) | mcu_cnt);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL2,
+                       SSC_DEPTH_MASK, ssc_depth);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
+       if (vpclk) {
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, 0);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD_VPCLK0_CTL,
+                               PHASE_NOT_RESET, PHASE_NOT_RESET);
+       }
+
+       ret = rtsx_usb_send_cmd(ucr, MODE_C, 2000);
+       if (ret < 0)
+               return ret;
+
+       ret = rtsx_usb_write_register(ucr, SSC_CTL1, 0xff,
+                       SSC_RSTB | SSC_8X_EN | SSC_SEL_4M);
+       if (ret < 0)
+               return ret;
+
+       /* Wait SSC clock stable */
+       usleep_range(100, 1000);
+
+       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0);
+       if (ret < 0)
+               return ret;
+
+       ucr->cur_clk = card_clock;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_switch_clock);
+
+int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card)
+{
+       int ret;
+       u16 val;
+       u16 cd_mask[] = {
+               [RTSX_USB_SD_CARD] = (CD_MASK & ~SD_CD),
+               [RTSX_USB_MS_CARD] = (CD_MASK & ~MS_CD)
+       };
+
+       ret = rtsx_usb_get_card_status(ucr, &val);
+       /*
+        * If get status fails, return 0 (ok) for the exclusive check
+        * and let the flow fail at somewhere else.
+        */
+       if (ret)
+               return 0;
+
+       if (val & cd_mask[card])
+               return -EIO;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_usb_card_exclusive_check);
+
+static int rtsx_usb_reset_chip(struct rtsx_ucr *ucr)
+{
+       int ret;
+       u8 val;
+
+       rtsx_usb_init_cmd(ucr);
+
+       if (CHECK_PKG(ucr, LQFP48)) {
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+                               LDO3318_PWR_MASK, LDO_SUSPEND);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PWR_CTL,
+                               FORCE_LDO_POWERB, FORCE_LDO_POWERB);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL1,
+                               0x30, 0x10);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL5,
+                               0x03, 0x01);
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_PULL_CTL6,
+                               0x0C, 0x04);
+       }
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SYS_DUMMY0, NYET_MSAK, NYET_EN);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CD_DEGLITCH_WIDTH, 0xFF, 0x08);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                       CD_DEGLITCH_EN, XD_CD_DEGLITCH_EN, 0x0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, SD30_DRIVE_SEL,
+                       SD30_DRIVE_MASK, DRIVER_TYPE_D);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                       CARD_DRIVE_SEL, SD20_DRIVE_MASK, 0x0);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, LDO_POWER_CFG, 0xE0, 0x0);
+
+       if (ucr->is_rts5179)
+               rtsx_usb_add_cmd(ucr, WRITE_REG_CMD,
+                               CARD_PULL_CTL5, 0x03, 0x01);
+
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_DMA1_CTL,
+                      EXTEND_DMA1_ASYNC_SIGNAL, EXTEND_DMA1_ASYNC_SIGNAL);
+       rtsx_usb_add_cmd(ucr, WRITE_REG_CMD, CARD_INT_PEND,
+                       XD_INT | MS_INT | SD_INT,
+                       XD_INT | MS_INT | SD_INT);
+
+       ret = rtsx_usb_send_cmd(ucr, MODE_C, 100);
+       if (ret)
+               return ret;
+
+       /* config non-crystal mode */
+       rtsx_usb_read_register(ucr, CFG_MODE, &val);
+       if ((val & XTAL_FREE) || ((val & CLK_MODE_MASK) == CLK_MODE_NON_XTAL)) {
+               ret = rtsx_usb_write_phy_register(ucr, 0xC2, 0x7C);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int rtsx_usb_init_chip(struct rtsx_ucr *ucr)
+{
+       int ret;
+       u8 val;
+
+       rtsx_usb_clear_fsm_err(ucr);
+
+       /* power on SSC */
+       ret = rtsx_usb_write_register(ucr,
+                       FPDCTL, SSC_POWER_MASK, SSC_POWER_ON);
+       if (ret)
+               return ret;
+
+       usleep_range(100, 1000);
+       ret = rtsx_usb_write_register(ucr, CLK_DIV, CLK_CHANGE, 0x00);
+       if (ret)
+               return ret;
+
+       /* determine IC version */
+       ret = rtsx_usb_read_register(ucr, HW_VERSION, &val);
+       if (ret)
+               return ret;
+
+       ucr->ic_version = val & HW_VER_MASK;
+
+       /* determine package */
+       ret = rtsx_usb_read_register(ucr, CARD_SHARE_MODE, &val);
+       if (ret)
+               return ret;
+
+       if (val & CARD_SHARE_LQFP_SEL) {
+               ucr->package = LQFP48;
+               dev_dbg(&ucr->pusb_intf->dev, "Package: LQFP48\n");
+       } else {
+               ucr->package = QFN24;
+               dev_dbg(&ucr->pusb_intf->dev, "Package: QFN24\n");
+       }
+
+       /* determine IC variations */
+       rtsx_usb_read_register(ucr, CFG_MODE_1, &val);
+       if (val & RTS5179) {
+               ucr->is_rts5179 = true;
+               dev_dbg(&ucr->pusb_intf->dev, "Device is rts5179\n");
+       } else {
+               ucr->is_rts5179 = false;
+       }
+
+       return rtsx_usb_reset_chip(ucr);
+}
+
+static int rtsx_usb_probe(struct usb_interface *intf,
+                        const struct usb_device_id *id)
+{
+       struct usb_device *usb_dev = interface_to_usbdev(intf);
+       struct rtsx_ucr *ucr;
+       int ret;
+
+       dev_dbg(&intf->dev,
+               ": Realtek USB Card Reader found at bus %03d address %03d\n",
+                usb_dev->bus->busnum, usb_dev->devnum);
+
+       ucr = devm_kzalloc(&intf->dev, sizeof(*ucr), GFP_KERNEL);
+       if (!ucr)
+               return -ENOMEM;
+
+       ucr->pusb_dev = usb_dev;
+
+       ucr->iobuf = usb_alloc_coherent(ucr->pusb_dev, IOBUF_SIZE,
+                       GFP_KERNEL, &ucr->iobuf_dma);
+       if (!ucr->iobuf)
+               return -ENOMEM;
+
+       usb_set_intfdata(intf, ucr);
+
+       ucr->vendor_id = id->idVendor;
+       ucr->product_id = id->idProduct;
+       ucr->cmd_buf = ucr->rsp_buf = ucr->iobuf;
+
+       mutex_init(&ucr->dev_mutex);
+
+       ucr->pusb_intf = intf;
+
+       /* initialize */
+       ret = rtsx_usb_init_chip(ucr);
+       if (ret)
+               goto out_init_fail;
+
+       /* initialize USB SG transfer timer */
+       timer_setup(&ucr->sg_timer, rtsx_usb_sg_timed_out, 0);
+
+       ret = mfd_add_hotplug_devices(&intf->dev, rtsx_usb_cells,
+                                     ARRAY_SIZE(rtsx_usb_cells));
+       if (ret)
+               goto out_init_fail;
+
+#ifdef CONFIG_PM
+       intf->needs_remote_wakeup = 1;
+       usb_enable_autosuspend(usb_dev);
+#endif
+
+       return 0;
+
+out_init_fail:
+       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+                       ucr->iobuf_dma);
+       return ret;
+}
+
+static void rtsx_usb_disconnect(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       dev_dbg(&intf->dev, "%s called\n", __func__);
+
+       mfd_remove_devices(&intf->dev);
+
+       usb_set_intfdata(ucr->pusb_intf, NULL);
+       usb_free_coherent(ucr->pusb_dev, IOBUF_SIZE, ucr->iobuf,
+                       ucr->iobuf_dma);
+}
+
+#ifdef CONFIG_PM
+static int rtsx_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct rtsx_ucr *ucr =
+               (struct rtsx_ucr *)usb_get_intfdata(intf);
+       u16 val = 0;
+
+       dev_dbg(&intf->dev, "%s called with pm message 0x%04x\n",
+                       __func__, message.event);
+
+       if (PMSG_IS_AUTO(message)) {
+               if (mutex_trylock(&ucr->dev_mutex)) {
+                       rtsx_usb_get_card_status(ucr, &val);
+                       mutex_unlock(&ucr->dev_mutex);
+
+                       /* Defer the autosuspend if card exists */
+                       if (val & (SD_CD | MS_CD))
+                               return -EAGAIN;
+               } else {
+                       /* There is an ongoing operation*/
+                       return -EAGAIN;
+               }
+       }
+
+       return 0;
+}
+
+static int rtsx_usb_resume(struct usb_interface *intf)
+{
+       return 0;
+}
+
+static int rtsx_usb_reset_resume(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr =
+               (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       rtsx_usb_reset_chip(ucr);
+       return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define rtsx_usb_suspend NULL
+#define rtsx_usb_resume NULL
+#define rtsx_usb_reset_resume NULL
+
+#endif /* CONFIG_PM */
+
+
+static int rtsx_usb_pre_reset(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       mutex_lock(&ucr->dev_mutex);
+       return 0;
+}
+
+static int rtsx_usb_post_reset(struct usb_interface *intf)
+{
+       struct rtsx_ucr *ucr = (struct rtsx_ucr *)usb_get_intfdata(intf);
+
+       mutex_unlock(&ucr->dev_mutex);
+       return 0;
+}
+
+static struct usb_device_id rtsx_usb_usb_ids[] = {
+       { USB_DEVICE(0x0BDA, 0x0129) },
+       { USB_DEVICE(0x0BDA, 0x0139) },
+       { USB_DEVICE(0x0BDA, 0x0140) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
+
+static struct usb_driver rtsx_usb_driver = {
+       .name                   = "rtsx_usb",
+       .probe                  = rtsx_usb_probe,
+       .disconnect             = rtsx_usb_disconnect,
+       .suspend                = rtsx_usb_suspend,
+       .resume                 = rtsx_usb_resume,
+       .reset_resume           = rtsx_usb_reset_resume,
+       .pre_reset              = rtsx_usb_pre_reset,
+       .post_reset             = rtsx_usb_post_reset,
+       .id_table               = rtsx_usb_usb_ids,
+       .supports_autosuspend   = 1,
+       .soft_unbind            = 1,
+};
+
+module_usb_driver(rtsx_usb_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Roger Tseng <rogerable@realtek.com>");
+MODULE_DESCRIPTION("Realtek USB Card Reader Driver");
index 567028c9219a98c09df88170a727eea7198a8afb..cec8152b5ede32504e82c908623d26f764c8523f 100644 (file)
@@ -838,14 +838,14 @@ config MMC_USDHI6ROL0
 
 config MMC_REALTEK_PCI
        tristate "Realtek PCI-E SD/MMC Card Interface Driver"
-       depends on MFD_RTSX_PCI
+       depends on MISC_RTSX_PCI
        help
          Say Y here to include driver code to support SD/MMC card interface
          of Realtek PCI-E card reader
 
 config MMC_REALTEK_USB
        tristate "Realtek USB SD/MMC Card Interface Driver"
-       depends on MFD_RTSX_USB
+       depends on MISC_RTSX_USB
        help
          Say Y here to include driver code to support SD/MMC card interface
          of Realtek RTS5129/39 series card reader
index 0848dc0f882e1b7c5269bff0416544bee0c94d21..30bd8081307e3244b65e86cc59fd21655dd6c678 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/mmc/sd.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/card.h>
-#include <linux/mfd/rtsx_pci.h>
+#include <linux/rtsx_pci.h>
 #include <asm/unaligned.h>
 
 struct realtek_pci_sdmmc {
index 76da1687ab370594e0ba5b7fbbfdb6b8cc95ee29..78422079ecfa425689bbdcf3882dfbe11afc694a 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/scatterlist.h>
 #include <linux/pm_runtime.h>
 
-#include <linux/mfd/rtsx_usb.h>
+#include <linux/rtsx_usb.h>
 #include <asm/unaligned.h>
 
 #if defined(CONFIG_LEDS_CLASS) || (defined(CONFIG_LEDS_CLASS_MODULE) && \
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
deleted file mode 100644 (file)
index 443176e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Driver for Realtek driver-based card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#ifndef __RTSX_COMMON_H
-#define __RTSX_COMMON_H
-
-#define DRV_NAME_RTSX_PCI              "rtsx_pci"
-#define DRV_NAME_RTSX_PCI_SDMMC                "rtsx_pci_sdmmc"
-#define DRV_NAME_RTSX_PCI_MS           "rtsx_pci_ms"
-
-#define RTSX_REG_PAIR(addr, val)       (((u32)(addr) << 16) | (u8)(val))
-
-#define RTSX_SSC_DEPTH_4M              0x01
-#define RTSX_SSC_DEPTH_2M              0x02
-#define RTSX_SSC_DEPTH_1M              0x03
-#define RTSX_SSC_DEPTH_500K            0x04
-#define RTSX_SSC_DEPTH_250K            0x05
-
-#define RTSX_SD_CARD                   0
-#define RTSX_MS_CARD                   1
-
-#define CLK_TO_DIV_N                   0
-#define DIV_N_TO_CLK                   1
-
-struct platform_device;
-
-struct rtsx_slot {
-       struct platform_device  *p_dev;
-       void                    (*card_event)(struct platform_device *p_dev);
-};
-
-#endif
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
deleted file mode 100644 (file)
index c3d3f04..0000000
+++ /dev/null
@@ -1,1141 +0,0 @@
-/* Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Wei WANG <wei_wang@realsil.com.cn>
- */
-
-#ifndef __RTSX_PCI_H
-#define __RTSX_PCI_H
-
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/mfd/rtsx_common.h>
-
-#define MAX_RW_REG_CNT                 1024
-
-#define RTSX_HCBAR                     0x00
-#define RTSX_HCBCTLR                   0x04
-#define   STOP_CMD                     (0x01 << 28)
-#define   READ_REG_CMD                 0
-#define   WRITE_REG_CMD                        1
-#define   CHECK_REG_CMD                        2
-
-#define RTSX_HDBAR                     0x08
-#define   SG_INT                       0x04
-#define   SG_END                       0x02
-#define   SG_VALID                     0x01
-#define   SG_NO_OP                     0x00
-#define   SG_TRANS_DATA                        (0x02 << 4)
-#define   SG_LINK_DESC                 (0x03 << 4)
-#define RTSX_HDBCTLR                   0x0C
-#define   SDMA_MODE                    0x00
-#define   ADMA_MODE                    (0x02 << 26)
-#define   STOP_DMA                     (0x01 << 28)
-#define   TRIG_DMA                     (0x01 << 31)
-
-#define RTSX_HAIMR                     0x10
-#define   HAIMR_TRANS_START            (0x01 << 31)
-#define   HAIMR_READ                   0x00
-#define   HAIMR_WRITE                  (0x01 << 30)
-#define   HAIMR_READ_START             (HAIMR_TRANS_START | HAIMR_READ)
-#define   HAIMR_WRITE_START            (HAIMR_TRANS_START | HAIMR_WRITE)
-#define   HAIMR_TRANS_END                      (HAIMR_TRANS_START)
-
-#define RTSX_BIPR                      0x14
-#define   CMD_DONE_INT                 (1 << 31)
-#define   DATA_DONE_INT                        (1 << 30)
-#define   TRANS_OK_INT                 (1 << 29)
-#define   TRANS_FAIL_INT               (1 << 28)
-#define   XD_INT                       (1 << 27)
-#define   MS_INT                       (1 << 26)
-#define   SD_INT                       (1 << 25)
-#define   GPIO0_INT                    (1 << 24)
-#define   OC_INT                       (1 << 23)
-#define   SD_WRITE_PROTECT             (1 << 19)
-#define   XD_EXIST                     (1 << 18)
-#define   MS_EXIST                     (1 << 17)
-#define   SD_EXIST                     (1 << 16)
-#define   DELINK_INT                   GPIO0_INT
-#define   MS_OC_INT                    (1 << 23)
-#define   SD_OC_INT                    (1 << 22)
-
-#define CARD_INT               (XD_INT | MS_INT | SD_INT)
-#define NEED_COMPLETE_INT      (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
-#define RTSX_INT               (CMD_DONE_INT | NEED_COMPLETE_INT | \
-                                       CARD_INT | GPIO0_INT | OC_INT)
-#define CARD_EXIST             (XD_EXIST | MS_EXIST | SD_EXIST)
-
-#define RTSX_BIER                      0x18
-#define   CMD_DONE_INT_EN              (1 << 31)
-#define   DATA_DONE_INT_EN             (1 << 30)
-#define   TRANS_OK_INT_EN              (1 << 29)
-#define   TRANS_FAIL_INT_EN            (1 << 28)
-#define   XD_INT_EN                    (1 << 27)
-#define   MS_INT_EN                    (1 << 26)
-#define   SD_INT_EN                    (1 << 25)
-#define   GPIO0_INT_EN                 (1 << 24)
-#define   OC_INT_EN                    (1 << 23)
-#define   DELINK_INT_EN                        GPIO0_INT_EN
-#define   MS_OC_INT_EN                 (1 << 23)
-#define   SD_OC_INT_EN                 (1 << 22)
-
-
-/*
- * macros for easy use
- */
-#define rtsx_pci_writel(pcr, reg, value) \
-       iowrite32(value, (pcr)->remap_addr + reg)
-#define rtsx_pci_readl(pcr, reg) \
-       ioread32((pcr)->remap_addr + reg)
-#define rtsx_pci_writew(pcr, reg, value) \
-       iowrite16(value, (pcr)->remap_addr + reg)
-#define rtsx_pci_readw(pcr, reg) \
-       ioread16((pcr)->remap_addr + reg)
-#define rtsx_pci_writeb(pcr, reg, value) \
-       iowrite8(value, (pcr)->remap_addr + reg)
-#define rtsx_pci_readb(pcr, reg) \
-       ioread8((pcr)->remap_addr + reg)
-
-#define rtsx_pci_read_config_byte(pcr, where, val) \
-       pci_read_config_byte((pcr)->pci, where, val)
-
-#define rtsx_pci_write_config_byte(pcr, where, val) \
-       pci_write_config_byte((pcr)->pci, where, val)
-
-#define rtsx_pci_read_config_dword(pcr, where, val) \
-       pci_read_config_dword((pcr)->pci, where, val)
-
-#define rtsx_pci_write_config_dword(pcr, where, val) \
-       pci_write_config_dword((pcr)->pci, where, val)
-
-#define STATE_TRANS_NONE               0
-#define STATE_TRANS_CMD                        1
-#define STATE_TRANS_BUF                        2
-#define STATE_TRANS_SG                 3
-
-#define TRANS_NOT_READY                        0
-#define TRANS_RESULT_OK                        1
-#define TRANS_RESULT_FAIL              2
-#define TRANS_NO_DEVICE                        3
-
-#define RTSX_RESV_BUF_LEN              4096
-#define HOST_CMDS_BUF_LEN              1024
-#define HOST_SG_TBL_BUF_LEN            (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
-#define HOST_SG_TBL_ITEMS              (HOST_SG_TBL_BUF_LEN / 8)
-#define MAX_SG_ITEM_LEN                        0x80000
-#define HOST_TO_DEVICE                 0
-#define DEVICE_TO_HOST                 1
-
-#define OUTPUT_3V3                     0
-#define OUTPUT_1V8                     1
-
-#define RTSX_PHASE_MAX                 32
-#define RX_TUNING_CNT                  3
-
-#define MS_CFG                         0xFD40
-#define   SAMPLE_TIME_RISING           0x00
-#define   SAMPLE_TIME_FALLING          0x80
-#define   PUSH_TIME_DEFAULT            0x00
-#define   PUSH_TIME_ODD                        0x40
-#define   NO_EXTEND_TOGGLE             0x00
-#define   EXTEND_TOGGLE_CHK            0x20
-#define   MS_BUS_WIDTH_1               0x00
-#define   MS_BUS_WIDTH_4               0x10
-#define   MS_BUS_WIDTH_8               0x18
-#define   MS_2K_SECTOR_MODE            0x04
-#define   MS_512_SECTOR_MODE           0x00
-#define   MS_TOGGLE_TIMEOUT_EN         0x00
-#define   MS_TOGGLE_TIMEOUT_DISEN      0x01
-#define MS_NO_CHECK_INT                        0x02
-#define MS_TPC                         0xFD41
-#define MS_TRANS_CFG                   0xFD42
-#define   WAIT_INT                     0x80
-#define   NO_WAIT_INT                  0x00
-#define   NO_AUTO_READ_INT_REG         0x00
-#define   AUTO_READ_INT_REG            0x40
-#define   MS_CRC16_ERR                 0x20
-#define   MS_RDY_TIMEOUT               0x10
-#define   MS_INT_CMDNK                 0x08
-#define   MS_INT_BREQ                  0x04
-#define   MS_INT_ERR                   0x02
-#define   MS_INT_CED                   0x01
-#define MS_TRANSFER                    0xFD43
-#define   MS_TRANSFER_START            0x80
-#define   MS_TRANSFER_END              0x40
-#define   MS_TRANSFER_ERR              0x20
-#define   MS_BS_STATE                  0x10
-#define   MS_TM_READ_BYTES             0x00
-#define   MS_TM_NORMAL_READ            0x01
-#define   MS_TM_WRITE_BYTES            0x04
-#define   MS_TM_NORMAL_WRITE           0x05
-#define   MS_TM_AUTO_READ              0x08
-#define   MS_TM_AUTO_WRITE             0x0C
-#define MS_INT_REG                     0xFD44
-#define MS_BYTE_CNT                    0xFD45
-#define MS_SECTOR_CNT_L                        0xFD46
-#define MS_SECTOR_CNT_H                        0xFD47
-#define MS_DBUS_H                      0xFD48
-
-#define SD_CFG1                                0xFDA0
-#define   SD_CLK_DIVIDE_0              0x00
-#define   SD_CLK_DIVIDE_256            0xC0
-#define   SD_CLK_DIVIDE_128            0x80
-#define   SD_BUS_WIDTH_1BIT            0x00
-#define   SD_BUS_WIDTH_4BIT            0x01
-#define   SD_BUS_WIDTH_8BIT            0x02
-#define   SD_ASYNC_FIFO_NOT_RST                0x10
-#define   SD_20_MODE                   0x00
-#define   SD_DDR_MODE                  0x04
-#define   SD_30_MODE                   0x08
-#define   SD_CLK_DIVIDE_MASK           0xC0
-#define SD_CFG2                                0xFDA1
-#define   SD_CALCULATE_CRC7            0x00
-#define   SD_NO_CALCULATE_CRC7         0x80
-#define   SD_CHECK_CRC16               0x00
-#define   SD_NO_CHECK_CRC16            0x40
-#define   SD_NO_CHECK_WAIT_CRC_TO      0x20
-#define   SD_WAIT_BUSY_END             0x08
-#define   SD_NO_WAIT_BUSY_END          0x00
-#define   SD_CHECK_CRC7                        0x00
-#define   SD_NO_CHECK_CRC7             0x04
-#define   SD_RSP_LEN_0                 0x00
-#define   SD_RSP_LEN_6                 0x01
-#define   SD_RSP_LEN_17                        0x02
-#define   SD_RSP_TYPE_R0               0x04
-#define   SD_RSP_TYPE_R1               0x01
-#define   SD_RSP_TYPE_R1b              0x09
-#define   SD_RSP_TYPE_R2               0x02
-#define   SD_RSP_TYPE_R3               0x05
-#define   SD_RSP_TYPE_R4               0x05
-#define   SD_RSP_TYPE_R5               0x01
-#define   SD_RSP_TYPE_R6               0x01
-#define   SD_RSP_TYPE_R7               0x01
-#define SD_CFG3                                0xFDA2
-#define   SD_RSP_80CLK_TIMEOUT_EN      0x01
-
-#define SD_STAT1                       0xFDA3
-#define   SD_CRC7_ERR                  0x80
-#define   SD_CRC16_ERR                 0x40
-#define   SD_CRC_WRITE_ERR             0x20
-#define   SD_CRC_WRITE_ERR_MASK                0x1C
-#define   GET_CRC_TIME_OUT             0x02
-#define   SD_TUNING_COMPARE_ERR                0x01
-#define SD_STAT2                       0xFDA4
-#define   SD_RSP_80CLK_TIMEOUT         0x01
-
-#define SD_BUS_STAT                    0xFDA5
-#define   SD_CLK_TOGGLE_EN             0x80
-#define   SD_CLK_FORCE_STOP            0x40
-#define   SD_DAT3_STATUS               0x10
-#define   SD_DAT2_STATUS               0x08
-#define   SD_DAT1_STATUS               0x04
-#define   SD_DAT0_STATUS               0x02
-#define   SD_CMD_STATUS                        0x01
-#define SD_PAD_CTL                     0xFDA6
-#define   SD_IO_USING_1V8              0x80
-#define   SD_IO_USING_3V3              0x7F
-#define   TYPE_A_DRIVING               0x00
-#define   TYPE_B_DRIVING               0x01
-#define   TYPE_C_DRIVING               0x02
-#define   TYPE_D_DRIVING               0x03
-#define SD_SAMPLE_POINT_CTL            0xFDA7
-#define   DDR_FIX_RX_DAT               0x00
-#define   DDR_VAR_RX_DAT               0x80
-#define   DDR_FIX_RX_DAT_EDGE          0x00
-#define   DDR_FIX_RX_DAT_14_DELAY      0x40
-#define   DDR_FIX_RX_CMD               0x00
-#define   DDR_VAR_RX_CMD               0x20
-#define   DDR_FIX_RX_CMD_POS_EDGE      0x00
-#define   DDR_FIX_RX_CMD_14_DELAY      0x10
-#define   SD20_RX_POS_EDGE             0x00
-#define   SD20_RX_14_DELAY             0x08
-#define SD20_RX_SEL_MASK               0x08
-#define SD_PUSH_POINT_CTL              0xFDA8
-#define   DDR_FIX_TX_CMD_DAT           0x00
-#define   DDR_VAR_TX_CMD_DAT           0x80
-#define   DDR_FIX_TX_DAT_14_TSU                0x00
-#define   DDR_FIX_TX_DAT_12_TSU                0x40
-#define   DDR_FIX_TX_CMD_NEG_EDGE      0x00
-#define   DDR_FIX_TX_CMD_14_AHEAD      0x20
-#define   SD20_TX_NEG_EDGE             0x00
-#define   SD20_TX_14_AHEAD             0x10
-#define   SD20_TX_SEL_MASK             0x10
-#define   DDR_VAR_SDCLK_POL_SWAP       0x01
-#define SD_CMD0                                0xFDA9
-#define   SD_CMD_START                 0x40
-#define SD_CMD1                                0xFDAA
-#define SD_CMD2                                0xFDAB
-#define SD_CMD3                                0xFDAC
-#define SD_CMD4                                0xFDAD
-#define SD_CMD5                                0xFDAE
-#define SD_BYTE_CNT_L                  0xFDAF
-#define SD_BYTE_CNT_H                  0xFDB0
-#define SD_BLOCK_CNT_L                 0xFDB1
-#define SD_BLOCK_CNT_H                 0xFDB2
-#define SD_TRANSFER                    0xFDB3
-#define   SD_TRANSFER_START            0x80
-#define   SD_TRANSFER_END              0x40
-#define   SD_STAT_IDLE                 0x20
-#define   SD_TRANSFER_ERR              0x10
-#define   SD_TM_NORMAL_WRITE           0x00
-#define   SD_TM_AUTO_WRITE_3           0x01
-#define   SD_TM_AUTO_WRITE_4           0x02
-#define   SD_TM_AUTO_READ_3            0x05
-#define   SD_TM_AUTO_READ_4            0x06
-#define   SD_TM_CMD_RSP                        0x08
-#define   SD_TM_AUTO_WRITE_1           0x09
-#define   SD_TM_AUTO_WRITE_2           0x0A
-#define   SD_TM_NORMAL_READ            0x0C
-#define   SD_TM_AUTO_READ_1            0x0D
-#define   SD_TM_AUTO_READ_2            0x0E
-#define   SD_TM_AUTO_TUNING            0x0F
-#define SD_CMD_STATE                   0xFDB5
-#define   SD_CMD_IDLE                  0x80
-
-#define SD_DATA_STATE                  0xFDB6
-#define   SD_DATA_IDLE                 0x80
-
-#define SRCTL                          0xFC13
-
-#define DCM_DRP_CTL                    0xFC23
-#define   DCM_RESET                    0x08
-#define   DCM_LOCKED                   0x04
-#define   DCM_208M                     0x00
-#define   DCM_TX                       0x01
-#define   DCM_RX                       0x02
-#define DCM_DRP_TRIG                   0xFC24
-#define   DRP_START                    0x80
-#define   DRP_DONE                     0x40
-#define DCM_DRP_CFG                    0xFC25
-#define   DRP_WRITE                    0x80
-#define   DRP_READ                     0x00
-#define   DCM_WRITE_ADDRESS_50         0x50
-#define   DCM_WRITE_ADDRESS_51         0x51
-#define   DCM_READ_ADDRESS_00          0x00
-#define   DCM_READ_ADDRESS_51          0x51
-#define DCM_DRP_WR_DATA_L              0xFC26
-#define DCM_DRP_WR_DATA_H              0xFC27
-#define DCM_DRP_RD_DATA_L              0xFC28
-#define DCM_DRP_RD_DATA_H              0xFC29
-#define SD_VPCLK0_CTL                  0xFC2A
-#define SD_VPCLK1_CTL                  0xFC2B
-#define   PHASE_SELECT_MASK            0x1F
-#define SD_DCMPS0_CTL                  0xFC2C
-#define SD_DCMPS1_CTL                  0xFC2D
-#define SD_VPTX_CTL                    SD_VPCLK0_CTL
-#define SD_VPRX_CTL                    SD_VPCLK1_CTL
-#define   PHASE_CHANGE                 0x80
-#define   PHASE_NOT_RESET              0x40
-#define SD_DCMPS_TX_CTL                        SD_DCMPS0_CTL
-#define SD_DCMPS_RX_CTL                        SD_DCMPS1_CTL
-#define   DCMPS_CHANGE                 0x80
-#define   DCMPS_CHANGE_DONE            0x40
-#define   DCMPS_ERROR                  0x20
-#define   DCMPS_CURRENT_PHASE          0x1F
-#define CARD_CLK_SOURCE                        0xFC2E
-#define   CRC_FIX_CLK                  (0x00 << 0)
-#define   CRC_VAR_CLK0                 (0x01 << 0)
-#define   CRC_VAR_CLK1                 (0x02 << 0)
-#define   SD30_FIX_CLK                 (0x00 << 2)
-#define   SD30_VAR_CLK0                        (0x01 << 2)
-#define   SD30_VAR_CLK1                        (0x02 << 2)
-#define   SAMPLE_FIX_CLK               (0x00 << 4)
-#define   SAMPLE_VAR_CLK0              (0x01 << 4)
-#define   SAMPLE_VAR_CLK1              (0x02 << 4)
-#define CARD_PWR_CTL                   0xFD50
-#define   PMOS_STRG_MASK               0x10
-#define   PMOS_STRG_800mA              0x10
-#define   PMOS_STRG_400mA              0x00
-#define   SD_POWER_OFF                 0x03
-#define   SD_PARTIAL_POWER_ON          0x01
-#define   SD_POWER_ON                  0x00
-#define   SD_POWER_MASK                        0x03
-#define   MS_POWER_OFF                 0x0C
-#define   MS_PARTIAL_POWER_ON          0x04
-#define   MS_POWER_ON                  0x00
-#define   MS_POWER_MASK                        0x0C
-#define   BPP_POWER_OFF                        0x0F
-#define   BPP_POWER_5_PERCENT_ON       0x0E
-#define   BPP_POWER_10_PERCENT_ON      0x0C
-#define   BPP_POWER_15_PERCENT_ON      0x08
-#define   BPP_POWER_ON                 0x00
-#define   BPP_POWER_MASK               0x0F
-#define   SD_VCC_PARTIAL_POWER_ON      0x02
-#define   SD_VCC_POWER_ON              0x00
-#define CARD_CLK_SWITCH                        0xFD51
-#define RTL8411B_PACKAGE_MODE          0xFD51
-#define CARD_SHARE_MODE                        0xFD52
-#define   CARD_SHARE_MASK              0x0F
-#define   CARD_SHARE_MULTI_LUN         0x00
-#define   CARD_SHARE_NORMAL            0x00
-#define   CARD_SHARE_48_SD             0x04
-#define   CARD_SHARE_48_MS             0x08
-#define   CARD_SHARE_BAROSSA_SD                0x01
-#define   CARD_SHARE_BAROSSA_MS                0x02
-#define CARD_DRIVE_SEL                 0xFD53
-#define   MS_DRIVE_8mA                 (0x01 << 6)
-#define   MMC_DRIVE_8mA                        (0x01 << 4)
-#define   XD_DRIVE_8mA                 (0x01 << 2)
-#define   GPIO_DRIVE_8mA               0x01
-#define RTS5209_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
-                                       XD_DRIVE_8mA | GPIO_DRIVE_8mA)
-#define RTL8411_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
-                                       XD_DRIVE_8mA)
-#define RTSX_CARD_DRIVE_DEFAULT                (MS_DRIVE_8mA | GPIO_DRIVE_8mA)
-
-#define CARD_STOP                      0xFD54
-#define   SPI_STOP                     0x01
-#define   XD_STOP                      0x02
-#define   SD_STOP                      0x04
-#define   MS_STOP                      0x08
-#define   SPI_CLR_ERR                  0x10
-#define   XD_CLR_ERR                   0x20
-#define   SD_CLR_ERR                   0x40
-#define   MS_CLR_ERR                   0x80
-#define CARD_OE                                0xFD55
-#define   SD_OUTPUT_EN                 0x04
-#define   MS_OUTPUT_EN                 0x08
-#define CARD_AUTO_BLINK                        0xFD56
-#define CARD_GPIO_DIR                  0xFD57
-#define CARD_GPIO                      0xFD58
-#define CARD_DATA_SOURCE               0xFD5B
-#define   PINGPONG_BUFFER              0x01
-#define   RING_BUFFER                  0x00
-#define SD30_CLK_DRIVE_SEL             0xFD5A
-#define   DRIVER_TYPE_A                        0x05
-#define   DRIVER_TYPE_B                        0x03
-#define   DRIVER_TYPE_C                        0x02
-#define   DRIVER_TYPE_D                        0x01
-#define CARD_SELECT                    0xFD5C
-#define   SD_MOD_SEL                   2
-#define   MS_MOD_SEL                   3
-#define SD30_DRIVE_SEL                 0xFD5E
-#define   CFG_DRIVER_TYPE_A            0x02
-#define   CFG_DRIVER_TYPE_B            0x03
-#define   CFG_DRIVER_TYPE_C            0x01
-#define   CFG_DRIVER_TYPE_D            0x00
-#define SD30_CMD_DRIVE_SEL             0xFD5E
-#define SD30_DAT_DRIVE_SEL             0xFD5F
-#define CARD_CLK_EN                    0xFD69
-#define   SD_CLK_EN                    0x04
-#define   MS_CLK_EN                    0x08
-#define SDIO_CTRL                      0xFD6B
-#define CD_PAD_CTL                     0xFD73
-#define   CD_DISABLE_MASK              0x07
-#define   MS_CD_DISABLE                        0x04
-#define   SD_CD_DISABLE                        0x02
-#define   XD_CD_DISABLE                        0x01
-#define   CD_DISABLE                   0x07
-#define   CD_ENABLE                    0x00
-#define   MS_CD_EN_ONLY                        0x03
-#define   SD_CD_EN_ONLY                        0x05
-#define   XD_CD_EN_ONLY                        0x06
-#define   FORCE_CD_LOW_MASK            0x38
-#define   FORCE_CD_XD_LOW              0x08
-#define   FORCE_CD_SD_LOW              0x10
-#define   FORCE_CD_MS_LOW              0x20
-#define   CD_AUTO_DISABLE              0x40
-#define FPDCTL                         0xFC00
-#define   SSC_POWER_DOWN               0x01
-#define   SD_OC_POWER_DOWN             0x02
-#define   ALL_POWER_DOWN               0x07
-#define   OC_POWER_DOWN                        0x06
-#define PDINFO                         0xFC01
-
-#define CLK_CTL                                0xFC02
-#define   CHANGE_CLK                   0x01
-#define   CLK_LOW_FREQ                 0x01
-
-#define CLK_DIV                                0xFC03
-#define   CLK_DIV_1                    0x01
-#define   CLK_DIV_2                    0x02
-#define   CLK_DIV_4                    0x03
-#define   CLK_DIV_8                    0x04
-#define CLK_SEL                                0xFC04
-
-#define SSC_DIV_N_0                    0xFC0F
-#define SSC_DIV_N_1                    0xFC10
-#define SSC_CTL1                       0xFC11
-#define    SSC_RSTB                    0x80
-#define    SSC_8X_EN                   0x40
-#define    SSC_FIX_FRAC                        0x20
-#define    SSC_SEL_1M                  0x00
-#define    SSC_SEL_2M                  0x08
-#define    SSC_SEL_4M                  0x10
-#define    SSC_SEL_8M                  0x18
-#define SSC_CTL2                       0xFC12
-#define    SSC_DEPTH_MASK              0x07
-#define    SSC_DEPTH_DISALBE           0x00
-#define    SSC_DEPTH_4M                        0x01
-#define    SSC_DEPTH_2M                        0x02
-#define    SSC_DEPTH_1M                        0x03
-#define    SSC_DEPTH_500K              0x04
-#define    SSC_DEPTH_250K              0x05
-#define RCCTL                          0xFC14
-
-#define FPGA_PULL_CTL                  0xFC1D
-#define OLT_LED_CTL                    0xFC1E
-#define GPIO_CTL                       0xFC1F
-
-#define LDO_CTL                                0xFC1E
-#define   BPP_ASIC_1V7                 0x00
-#define   BPP_ASIC_1V8                 0x01
-#define   BPP_ASIC_1V9                 0x02
-#define   BPP_ASIC_2V0                 0x03
-#define   BPP_ASIC_2V7                 0x04
-#define   BPP_ASIC_2V8                 0x05
-#define   BPP_ASIC_3V2                 0x06
-#define   BPP_ASIC_3V3                 0x07
-#define   BPP_REG_TUNED18              0x07
-#define   BPP_TUNED18_SHIFT_8402       5
-#define   BPP_TUNED18_SHIFT_8411       4
-#define   BPP_PAD_MASK                 0x04
-#define   BPP_PAD_3V3                  0x04
-#define   BPP_PAD_1V8                  0x00
-#define   BPP_LDO_POWB                 0x03
-#define   BPP_LDO_ON                   0x00
-#define   BPP_LDO_SUSPEND              0x02
-#define   BPP_LDO_OFF                  0x03
-#define SYS_VER                                0xFC32
-
-#define CARD_PULL_CTL1                 0xFD60
-#define CARD_PULL_CTL2                 0xFD61
-#define CARD_PULL_CTL3                 0xFD62
-#define CARD_PULL_CTL4                 0xFD63
-#define CARD_PULL_CTL5                 0xFD64
-#define CARD_PULL_CTL6                 0xFD65
-
-/* PCI Express Related Registers */
-#define IRQEN0                         0xFE20
-#define IRQSTAT0                       0xFE21
-#define    DMA_DONE_INT                        0x80
-#define    SUSPEND_INT                 0x40
-#define    LINK_RDY_INT                        0x20
-#define    LINK_DOWN_INT               0x10
-#define IRQEN1                         0xFE22
-#define IRQSTAT1                       0xFE23
-#define TLPRIEN                                0xFE24
-#define TLPRISTAT                      0xFE25
-#define TLPTIEN                                0xFE26
-#define TLPTISTAT                      0xFE27
-#define DMATC0                         0xFE28
-#define DMATC1                         0xFE29
-#define DMATC2                         0xFE2A
-#define DMATC3                         0xFE2B
-#define DMACTL                         0xFE2C
-#define   DMA_RST                      0x80
-#define   DMA_BUSY                     0x04
-#define   DMA_DIR_TO_CARD              0x00
-#define   DMA_DIR_FROM_CARD            0x02
-#define   DMA_EN                       0x01
-#define   DMA_128                      (0 << 4)
-#define   DMA_256                      (1 << 4)
-#define   DMA_512                      (2 << 4)
-#define   DMA_1024                     (3 << 4)
-#define   DMA_PACK_SIZE_MASK           0x30
-#define BCTL                           0xFE2D
-#define RBBC0                          0xFE2E
-#define RBBC1                          0xFE2F
-#define RBDAT                          0xFE30
-#define RBCTL                          0xFE34
-#define CFGADDR0                       0xFE35
-#define CFGADDR1                       0xFE36
-#define CFGDATA0                       0xFE37
-#define CFGDATA1                       0xFE38
-#define CFGDATA2                       0xFE39
-#define CFGDATA3                       0xFE3A
-#define CFGRWCTL                       0xFE3B
-#define PHYRWCTL                       0xFE3C
-#define PHYDATA0                       0xFE3D
-#define PHYDATA1                       0xFE3E
-#define PHYADDR                                0xFE3F
-#define MSGRXDATA0                     0xFE40
-#define MSGRXDATA1                     0xFE41
-#define MSGRXDATA2                     0xFE42
-#define MSGRXDATA3                     0xFE43
-#define MSGTXDATA0                     0xFE44
-#define MSGTXDATA1                     0xFE45
-#define MSGTXDATA2                     0xFE46
-#define MSGTXDATA3                     0xFE47
-#define MSGTXCTL                       0xFE48
-#define LTR_CTL                                0xFE4A
-#define LTR_TX_EN_MASK         BIT(7)
-#define LTR_TX_EN_1                    BIT(7)
-#define LTR_TX_EN_0                    0
-#define LTR_LATENCY_MODE_MASK          BIT(6)
-#define LTR_LATENCY_MODE_HW            0
-#define LTR_LATENCY_MODE_SW            BIT(6)
-#define OBFF_CFG                       0xFE4C
-
-#define CDRESUMECTL                    0xFE52
-#define WAKE_SEL_CTL                   0xFE54
-#define PCLK_CTL                       0xFE55
-#define   PCLK_MODE_SEL                        0x20
-#define PME_FORCE_CTL                  0xFE56
-
-#define ASPM_FORCE_CTL                 0xFE57
-#define   FORCE_ASPM_CTL0              0x10
-#define   FORCE_ASPM_VAL_MASK          0x03
-#define   FORCE_ASPM_L1_EN             0x02
-#define   FORCE_ASPM_L0_EN             0x01
-#define   FORCE_ASPM_NO_ASPM           0x00
-#define PM_CLK_FORCE_CTL               0xFE58
-#define FUNC_FORCE_CTL                 0xFE59
-#define   FUNC_FORCE_UPME_XMT_DBG      0x02
-#define PERST_GLITCH_WIDTH             0xFE5C
-#define CHANGE_LINK_STATE              0xFE5B
-#define RESET_LOAD_REG                 0xFE5E
-#define EFUSE_CONTENT                  0xFE5F
-#define HOST_SLEEP_STATE               0xFE60
-#define   HOST_ENTER_S1                        1
-#define   HOST_ENTER_S3                        2
-
-#define SDIO_CFG                       0xFE70
-#define PM_EVENT_DEBUG                 0xFE71
-#define   PME_DEBUG_0                  0x08
-#define NFTS_TX_CTRL                   0xFE72
-
-#define PWR_GATE_CTRL                  0xFE75
-#define   PWR_GATE_EN                  0x01
-#define   LDO3318_PWR_MASK             0x06
-#define   LDO_ON                       0x00
-#define   LDO_SUSPEND                  0x04
-#define   LDO_OFF                      0x06
-#define PWD_SUSPEND_EN                 0xFE76
-#define LDO_PWR_SEL                    0xFE78
-
-#define L1SUB_CONFIG1                  0xFE8D
-#define L1SUB_CONFIG2                  0xFE8E
-#define   L1SUB_AUTO_CFG               0x02
-#define L1SUB_CONFIG3                  0xFE8F
-#define   L1OFF_MBIAS2_EN_5250         BIT(7)
-
-#define DUMMY_REG_RESET_0              0xFE90
-
-#define AUTOLOAD_CFG_BASE              0xFF00
-#define PETXCFG                                0xFF03
-#define FORCE_CLKREQ_DELINK_MASK       BIT(7)
-#define FORCE_CLKREQ_LOW       0x80
-#define FORCE_CLKREQ_HIGH      0x00
-
-#define PM_CTRL1                       0xFF44
-#define   CD_RESUME_EN_MASK            0xF0
-
-#define PM_CTRL2                       0xFF45
-#define PM_CTRL3                       0xFF46
-#define   SDIO_SEND_PME_EN             0x80
-#define   FORCE_RC_MODE_ON             0x40
-#define   FORCE_RX50_LINK_ON           0x20
-#define   D3_DELINK_MODE_EN            0x10
-#define   USE_PESRTB_CTL_DELINK                0x08
-#define   DELAY_PIN_WAKE               0x04
-#define   RESET_PIN_WAKE               0x02
-#define   PM_WAKE_EN                   0x01
-#define PM_CTRL4                       0xFF47
-
-/* Memory mapping */
-#define SRAM_BASE                      0xE600
-#define RBUF_BASE                      0xF400
-#define PPBUF_BASE1                    0xF800
-#define PPBUF_BASE2                    0xFA00
-#define IMAGE_FLAG_ADDR0               0xCE80
-#define IMAGE_FLAG_ADDR1               0xCE81
-
-#define RREF_CFG                       0xFF6C
-#define   RREF_VBGSEL_MASK             0x38
-#define   RREF_VBGSEL_1V25             0x28
-
-#define OOBS_CONFIG                    0xFF6E
-#define   OOBS_AUTOK_DIS               0x80
-#define   OOBS_VAL_MASK                        0x1F
-
-#define LDO_DV18_CFG                   0xFF70
-#define   LDO_DV18_SR_MASK             0xC0
-#define   LDO_DV18_SR_DF               0x40
-
-#define LDO_CONFIG2                    0xFF71
-#define   LDO_D3318_MASK               0x07
-#define   LDO_D3318_33V                        0x07
-#define   LDO_D3318_18V                        0x02
-
-#define LDO_VCC_CFG0                   0xFF72
-#define   LDO_VCC_LMTVTH_MASK          0x30
-#define   LDO_VCC_LMTVTH_2A            0x10
-
-#define LDO_VCC_CFG1                   0xFF73
-#define   LDO_VCC_REF_TUNE_MASK                0x30
-#define   LDO_VCC_REF_1V2              0x20
-#define   LDO_VCC_TUNE_MASK            0x07
-#define   LDO_VCC_1V8                  0x04
-#define   LDO_VCC_3V3                  0x07
-#define   LDO_VCC_LMT_EN               0x08
-
-#define LDO_VIO_CFG                    0xFF75
-#define   LDO_VIO_SR_MASK              0xC0
-#define   LDO_VIO_SR_DF                        0x40
-#define   LDO_VIO_REF_TUNE_MASK                0x30
-#define   LDO_VIO_REF_1V2              0x20
-#define   LDO_VIO_TUNE_MASK            0x07
-#define   LDO_VIO_1V7                  0x03
-#define   LDO_VIO_1V8                  0x04
-#define   LDO_VIO_3V3                  0x07
-
-#define LDO_DV12S_CFG                  0xFF76
-#define   LDO_REF12_TUNE_MASK          0x18
-#define   LDO_REF12_TUNE_DF            0x10
-#define   LDO_D12_TUNE_MASK            0x07
-#define   LDO_D12_TUNE_DF              0x04
-
-#define LDO_AV12S_CFG                  0xFF77
-#define   LDO_AV12S_TUNE_MASK          0x07
-#define   LDO_AV12S_TUNE_DF            0x04
-
-#define SD40_LDO_CTL1                  0xFE7D
-#define   SD40_VIO_TUNE_MASK           0x70
-#define   SD40_VIO_TUNE_1V7            0x30
-#define   SD_VIO_LDO_1V8               0x40
-#define   SD_VIO_LDO_3V3               0x70
-
-/* Phy register */
-#define PHY_PCR                                0x00
-#define   PHY_PCR_FORCE_CODE           0xB000
-#define   PHY_PCR_OOBS_CALI_50         0x0800
-#define   PHY_PCR_OOBS_VCM_08          0x0200
-#define   PHY_PCR_OOBS_SEN_90          0x0040
-#define   PHY_PCR_RSSI_EN              0x0002
-#define   PHY_PCR_RX10K                        0x0001
-
-#define PHY_RCR0                       0x01
-#define PHY_RCR1                       0x02
-#define   PHY_RCR1_ADP_TIME_4          0x0400
-#define   PHY_RCR1_VCO_COARSE          0x001F
-#define   PHY_RCR1_INIT_27S            0x0A1F
-#define PHY_SSCCR2                     0x02
-#define   PHY_SSCCR2_PLL_NCODE         0x0A00
-#define   PHY_SSCCR2_TIME0             0x001C
-#define   PHY_SSCCR2_TIME2_WIDTH       0x0003
-
-#define PHY_RCR2                       0x03
-#define   PHY_RCR2_EMPHASE_EN          0x8000
-#define   PHY_RCR2_NADJR               0x4000
-#define   PHY_RCR2_CDR_SR_2            0x0100
-#define   PHY_RCR2_FREQSEL_12          0x0040
-#define   PHY_RCR2_CDR_SC_12P          0x0010
-#define   PHY_RCR2_CALIB_LATE          0x0002
-#define   PHY_RCR2_INIT_27S            0xC152
-#define PHY_SSCCR3                     0x03
-#define   PHY_SSCCR3_STEP_IN           0x2740
-#define   PHY_SSCCR3_CHECK_DELAY       0x0008
-#define _PHY_ANA03                     0x03
-#define   _PHY_ANA03_TIMER_MAX         0x2700
-#define   _PHY_ANA03_OOBS_DEB_EN       0x0040
-#define   _PHY_CMU_DEBUG_EN            0x0008
-
-#define PHY_RTCR                       0x04
-#define PHY_RDR                                0x05
-#define   PHY_RDR_RXDSEL_1_9           0x4000
-#define   PHY_SSC_AUTO_PWD             0x0600
-#define PHY_TCR0                       0x06
-#define PHY_TCR1                       0x07
-#define PHY_TUNE                       0x08
-#define   PHY_TUNE_TUNEREF_1_0         0x4000
-#define   PHY_TUNE_VBGSEL_1252         0x0C00
-#define   PHY_TUNE_SDBUS_33            0x0200
-#define   PHY_TUNE_TUNED18             0x01C0
-#define   PHY_TUNE_TUNED12             0X0020
-#define   PHY_TUNE_TUNEA12             0x0004
-#define   PHY_TUNE_VOLTAGE_MASK                0xFC3F
-#define   PHY_TUNE_VOLTAGE_3V3         0x03C0
-#define   PHY_TUNE_D18_1V8             0x0100
-#define   PHY_TUNE_D18_1V7             0x0080
-#define PHY_ANA08                      0x08
-#define   PHY_ANA08_RX_EQ_DCGAIN       0x5000
-#define   PHY_ANA08_SEL_RX_EN          0x0400
-#define   PHY_ANA08_RX_EQ_VAL          0x03C0
-#define   PHY_ANA08_SCP                        0x0020
-#define   PHY_ANA08_SEL_IPI            0x0004
-
-#define PHY_IMR                                0x09
-#define PHY_BPCR                       0x0A
-#define   PHY_BPCR_IBRXSEL             0x0400
-#define   PHY_BPCR_IBTXSEL             0x0100
-#define   PHY_BPCR_IB_FILTER           0x0080
-#define   PHY_BPCR_CMIRROR_EN          0x0040
-
-#define PHY_BIST                       0x0B
-#define PHY_RAW_L                      0x0C
-#define PHY_RAW_H                      0x0D
-#define PHY_RAW_DATA                   0x0E
-#define PHY_HOST_CLK_CTRL              0x0F
-#define PHY_DMR                                0x10
-#define PHY_BACR                       0x11
-#define   PHY_BACR_BASIC_MASK          0xFFF3
-#define PHY_IER                                0x12
-#define PHY_BCSR                       0x13
-#define PHY_BPR                                0x14
-#define PHY_BPNR2                      0x15
-#define PHY_BPNR                       0x16
-#define PHY_BRNR2                      0x17
-#define PHY_BENR                       0x18
-#define PHY_REV                                0x19
-#define   PHY_REV_RESV                 0xE000
-#define   PHY_REV_RXIDLE_LATCHED       0x1000
-#define   PHY_REV_P1_EN                        0x0800
-#define   PHY_REV_RXIDLE_EN            0x0400
-#define   PHY_REV_CLKREQ_TX_EN         0x0200
-#define   PHY_REV_CLKREQ_RX_EN         0x0100
-#define   PHY_REV_CLKREQ_DT_1_0                0x0040
-#define   PHY_REV_STOP_CLKRD           0x0020
-#define   PHY_REV_RX_PWST              0x0008
-#define   PHY_REV_STOP_CLKWR           0x0004
-#define _PHY_REV0                      0x19
-#define   _PHY_REV0_FILTER_OUT         0x3800
-#define   _PHY_REV0_CDR_BYPASS_PFD     0x0100
-#define   _PHY_REV0_CDR_RX_IDLE_BYPASS 0x0002
-
-#define PHY_FLD0                       0x1A
-#define PHY_ANA1A                      0x1A
-#define   PHY_ANA1A_TXR_LOOPBACK       0x2000
-#define   PHY_ANA1A_RXT_BIST           0x0500
-#define   PHY_ANA1A_TXR_BIST           0x0040
-#define   PHY_ANA1A_REV                        0x0006
-#define   PHY_FLD0_INIT_27S            0x2546
-#define PHY_FLD1                       0x1B
-#define PHY_FLD2                       0x1C
-#define PHY_FLD3                       0x1D
-#define   PHY_FLD3_TIMER_4             0x0800
-#define   PHY_FLD3_TIMER_6             0x0020
-#define   PHY_FLD3_RXDELINK            0x0004
-#define   PHY_FLD3_INIT_27S            0x0004
-#define PHY_ANA1D                      0x1D
-#define   PHY_ANA1D_DEBUG_ADDR         0x0004
-#define _PHY_FLD0                      0x1D
-#define   _PHY_FLD0_CLK_REQ_20C                0x8000
-#define   _PHY_FLD0_RX_IDLE_EN         0x1000
-#define   _PHY_FLD0_BIT_ERR_RSTN       0x0800
-#define   _PHY_FLD0_BER_COUNT          0x01E0
-#define   _PHY_FLD0_BER_TIMER          0x001E
-#define   _PHY_FLD0_CHECK_EN           0x0001
-
-#define PHY_FLD4                       0x1E
-#define   PHY_FLD4_FLDEN_SEL           0x4000
-#define   PHY_FLD4_REQ_REF             0x2000
-#define   PHY_FLD4_RXAMP_OFF           0x1000
-#define   PHY_FLD4_REQ_ADDA            0x0800
-#define   PHY_FLD4_BER_COUNT           0x00E0
-#define   PHY_FLD4_BER_TIMER           0x000A
-#define   PHY_FLD4_BER_CHK_EN          0x0001
-#define   PHY_FLD4_INIT_27S            0x5C7F
-#define PHY_DIG1E                      0x1E
-#define   PHY_DIG1E_REV                        0x4000
-#define   PHY_DIG1E_D0_X_D1            0x1000
-#define   PHY_DIG1E_RX_ON_HOST         0x0800
-#define   PHY_DIG1E_RCLK_REF_HOST      0x0400
-#define   PHY_DIG1E_RCLK_TX_EN_KEEP    0x0040
-#define   PHY_DIG1E_RCLK_TX_TERM_KEEP  0x0020
-#define   PHY_DIG1E_RCLK_RX_EIDLE_ON   0x0010
-#define   PHY_DIG1E_TX_TERM_KEEP       0x0008
-#define   PHY_DIG1E_RX_TERM_KEEP       0x0004
-#define   PHY_DIG1E_TX_EN_KEEP         0x0002
-#define   PHY_DIG1E_RX_EN_KEEP         0x0001
-#define PHY_DUM_REG                    0x1F
-
-#define PCR_ASPM_SETTING_REG1          0x160
-#define PCR_ASPM_SETTING_REG2          0x168
-
-#define PCR_SETTING_REG1               0x724
-#define PCR_SETTING_REG2               0x814
-#define PCR_SETTING_REG3               0x747
-
-#define rtsx_pci_init_cmd(pcr)         ((pcr)->ci = 0)
-
-#define RTS5227_DEVICE_ID              0x5227
-#define RTS_MAX_TIMES_FREQ_REDUCTION   8
-
-struct rtsx_pcr;
-
-struct pcr_handle {
-       struct rtsx_pcr                 *pcr;
-};
-
-struct pcr_ops {
-       int (*write_phy)(struct rtsx_pcr *pcr, u8 addr, u16 val);
-       int (*read_phy)(struct rtsx_pcr *pcr, u8 addr, u16 *val);
-       int             (*extra_init_hw)(struct rtsx_pcr *pcr);
-       int             (*optimize_phy)(struct rtsx_pcr *pcr);
-       int             (*turn_on_led)(struct rtsx_pcr *pcr);
-       int             (*turn_off_led)(struct rtsx_pcr *pcr);
-       int             (*enable_auto_blink)(struct rtsx_pcr *pcr);
-       int             (*disable_auto_blink)(struct rtsx_pcr *pcr);
-       int             (*card_power_on)(struct rtsx_pcr *pcr, int card);
-       int             (*card_power_off)(struct rtsx_pcr *pcr, int card);
-       int             (*switch_output_voltage)(struct rtsx_pcr *pcr,
-                                               u8 voltage);
-       unsigned int    (*cd_deglitch)(struct rtsx_pcr *pcr);
-       int             (*conv_clk_and_div_n)(int clk, int dir);
-       void            (*fetch_vendor_settings)(struct rtsx_pcr *pcr);
-       void            (*force_power_down)(struct rtsx_pcr *pcr, u8 pm_state);
-
-       void (*set_aspm)(struct rtsx_pcr *pcr, bool enable);
-       int (*set_ltr_latency)(struct rtsx_pcr *pcr, u32 latency);
-       int (*set_l1off_sub)(struct rtsx_pcr *pcr, u8 val);
-       void (*set_l1off_cfg_sub_d0)(struct rtsx_pcr *pcr, int active);
-       void (*full_on)(struct rtsx_pcr *pcr);
-       void (*power_saving)(struct rtsx_pcr *pcr);
-};
-
-enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
-
-#define ASPM_L1_1_EN_MASK              BIT(3)
-#define ASPM_L1_2_EN_MASK              BIT(2)
-#define PM_L1_1_EN_MASK                BIT(1)
-#define PM_L1_2_EN_MASK                BIT(0)
-
-#define ASPM_L1_1_EN                   BIT(0)
-#define ASPM_L1_2_EN                   BIT(1)
-#define PM_L1_1_EN                             BIT(2)
-#define PM_L1_2_EN                             BIT(3)
-#define LTR_L1SS_PWR_GATE_EN   BIT(4)
-#define L1_SNOOZE_TEST_EN              BIT(5)
-#define LTR_L1SS_PWR_GATE_CHECK_CARD_EN        BIT(6)
-
-enum dev_aspm_mode {
-       DEV_ASPM_DYNAMIC,
-       DEV_ASPM_BACKDOOR,
-       DEV_ASPM_STATIC,
-       DEV_ASPM_DISABLE,
-};
-
-/*
- * struct rtsx_cr_option  - card reader option
- * @dev_flags: device flags
- * @force_clkreq_0: force clock request
- * @ltr_en: enable ltr mode flag
- * @ltr_enabled: ltr mode in configure space flag
- * @ltr_active: ltr mode status
- * @ltr_active_latency: ltr mode active latency
- * @ltr_idle_latency: ltr mode idle latency
- * @ltr_l1off_latency: ltr mode l1off latency
- * @dev_aspm_mode: device aspm mode
- * @l1_snooze_delay: l1 snooze delay
- * @ltr_l1off_sspwrgate: ltr l1off sspwrgate
- * @ltr_l1off_snooze_sspwrgate: ltr l1off snooze sspwrgate
- */
-struct rtsx_cr_option {
-       u32 dev_flags;
-       bool force_clkreq_0;
-       bool ltr_en;
-       bool ltr_enabled;
-       bool ltr_active;
-       u32 ltr_active_latency;
-       u32 ltr_idle_latency;
-       u32 ltr_l1off_latency;
-       enum dev_aspm_mode dev_aspm_mode;
-       u32 l1_snooze_delay;
-       u8 ltr_l1off_sspwrgate;
-       u8 ltr_l1off_snooze_sspwrgate;
-};
-
-#define rtsx_set_dev_flag(cr, flag) \
-       ((cr)->option.dev_flags |= (flag))
-#define rtsx_clear_dev_flag(cr, flag) \
-       ((cr)->option.dev_flags &= ~(flag))
-#define rtsx_check_dev_flag(cr, flag) \
-       ((cr)->option.dev_flags & (flag))
-
-struct rtsx_pcr {
-       struct pci_dev                  *pci;
-       unsigned int                    id;
-       int                             pcie_cap;
-       struct rtsx_cr_option   option;
-
-       /* pci resources */
-       unsigned long                   addr;
-       void __iomem                    *remap_addr;
-       int                             irq;
-
-       /* host reserved buffer */
-       void                            *rtsx_resv_buf;
-       dma_addr_t                      rtsx_resv_buf_addr;
-
-       void                            *host_cmds_ptr;
-       dma_addr_t                      host_cmds_addr;
-       int                             ci;
-
-       void                            *host_sg_tbl_ptr;
-       dma_addr_t                      host_sg_tbl_addr;
-       int                             sgi;
-
-       u32                             bier;
-       char                            trans_result;
-
-       unsigned int                    card_inserted;
-       unsigned int                    card_removed;
-       unsigned int                    card_exist;
-
-       struct delayed_work             carddet_work;
-       struct delayed_work             idle_work;
-
-       spinlock_t                      lock;
-       struct mutex                    pcr_mutex;
-       struct completion               *done;
-       struct completion               *finish_me;
-
-       unsigned int                    cur_clock;
-       bool                            remove_pci;
-       bool                            msi_en;
-
-#define EXTRA_CAPS_SD_SDR50            (1 << 0)
-#define EXTRA_CAPS_SD_SDR104           (1 << 1)
-#define EXTRA_CAPS_SD_DDR50            (1 << 2)
-#define EXTRA_CAPS_MMC_HSDDR           (1 << 3)
-#define EXTRA_CAPS_MMC_HS200           (1 << 4)
-#define EXTRA_CAPS_MMC_8BIT            (1 << 5)
-       u32                             extra_caps;
-
-#define IC_VER_A                       0
-#define IC_VER_B                       1
-#define IC_VER_C                       2
-#define IC_VER_D                       3
-       u8                              ic_version;
-
-       u8                              sd30_drive_sel_1v8;
-       u8                              sd30_drive_sel_3v3;
-       u8                              card_drive_sel;
-#define ASPM_L1_EN                     0x02
-       u8                              aspm_en;
-       bool                            aspm_enabled;
-
-#define PCR_MS_PMOS                    (1 << 0)
-#define PCR_REVERSE_SOCKET             (1 << 1)
-       u32                             flags;
-
-       u32                             tx_initial_phase;
-       u32                             rx_initial_phase;
-
-       const u32                       *sd_pull_ctl_enable_tbl;
-       const u32                       *sd_pull_ctl_disable_tbl;
-       const u32                       *ms_pull_ctl_enable_tbl;
-       const u32                       *ms_pull_ctl_disable_tbl;
-
-       const struct pcr_ops            *ops;
-       enum PDEV_STAT                  state;
-
-       u16                             reg_pm_ctrl3;
-
-       int                             num_slots;
-       struct rtsx_slot                *slots;
-
-       u8                              dma_error_count;
-};
-
-#define PID_524A       0x524A
-#define PID_5249               0x5249
-#define PID_5250               0x5250
-#define PID_525A       0x525A
-
-#define CHK_PCI_PID(pcr, pid)          ((pcr)->pci->device == (pid))
-#define PCI_VID(pcr)                   ((pcr)->pci->vendor)
-#define PCI_PID(pcr)                   ((pcr)->pci->device)
-#define is_version(pcr, pid, ver)                              \
-       (CHK_PCI_PID(pcr, pid) && (pcr)->ic_version == (ver))
-#define pcr_dbg(pcr, fmt, arg...)                              \
-       dev_dbg(&(pcr)->pci->dev, fmt, ##arg)
-
-#define SDR104_PHASE(val)              ((val) & 0xFF)
-#define SDR50_PHASE(val)               (((val) >> 8) & 0xFF)
-#define DDR50_PHASE(val)               (((val) >> 16) & 0xFF)
-#define SDR104_TX_PHASE(pcr)           SDR104_PHASE((pcr)->tx_initial_phase)
-#define SDR50_TX_PHASE(pcr)            SDR50_PHASE((pcr)->tx_initial_phase)
-#define DDR50_TX_PHASE(pcr)            DDR50_PHASE((pcr)->tx_initial_phase)
-#define SDR104_RX_PHASE(pcr)           SDR104_PHASE((pcr)->rx_initial_phase)
-#define SDR50_RX_PHASE(pcr)            SDR50_PHASE((pcr)->rx_initial_phase)
-#define DDR50_RX_PHASE(pcr)            DDR50_PHASE((pcr)->rx_initial_phase)
-#define SET_CLOCK_PHASE(sdr104, sdr50, ddr50)  \
-                               (((ddr50) << 16) | ((sdr50) << 8) | (sdr104))
-
-void rtsx_pci_start_run(struct rtsx_pcr *pcr);
-int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data);
-int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data);
-int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
-int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
-void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr);
-void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
-               u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
-void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
-int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
-int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read, int timeout);
-int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read);
-void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int num_sg, bool read);
-int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
-               int count, bool read, int timeout);
-int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
-int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
-int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
-int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card);
-int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
-               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
-int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
-int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
-int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card);
-int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage);
-unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
-void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
-
-static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
-{
-       return (u8 *)(pcr->host_cmds_ptr);
-}
-
-static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr,
-               u8 mask, u8 append)
-{
-       int err;
-       u8 val;
-
-       err = pci_read_config_byte(pcr->pci, addr, &val);
-       if (err < 0)
-               return err;
-       return pci_write_config_byte(pcr->pci, addr, (val & mask) | append);
-}
-
-static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val)
-{
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg,     0xFF, val >> 24);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 1, 0xFF, val >> 16);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 2, 0xFF, val >> 8);
-       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val);
-}
-
-static inline int rtsx_pci_update_phy(struct rtsx_pcr *pcr, u8 addr,
-       u16 mask, u16 append)
-{
-       int err;
-       u16 val;
-
-       err = rtsx_pci_read_phy_register(pcr, addr, &val);
-       if (err < 0)
-               return err;
-
-       return rtsx_pci_write_phy_register(pcr, addr, (val & mask) | append);
-}
-
-#endif
diff --git a/include/linux/mfd/rtsx_usb.h b/include/linux/mfd/rtsx_usb.h
deleted file mode 100644 (file)
index c446e4f..0000000
+++ /dev/null
@@ -1,628 +0,0 @@
-/* Driver for Realtek RTS5139 USB card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2
- * as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
- *
- * Author:
- *   Roger Tseng <rogerable@realtek.com>
- */
-
-#ifndef __RTSX_USB_H
-#define __RTSX_USB_H
-
-#include <linux/usb.h>
-
-/* related module names */
-#define RTSX_USB_SD_CARD       0
-#define RTSX_USB_MS_CARD       1
-
-/* endpoint numbers */
-#define EP_BULK_OUT            1
-#define EP_BULK_IN             2
-#define EP_INTR_IN             3
-
-/* USB vendor requests */
-#define RTSX_USB_REQ_REG_OP    0x00
-#define RTSX_USB_REQ_POLL      0x02
-
-/* miscellaneous parameters */
-#define MIN_DIV_N              60
-#define MAX_DIV_N              120
-
-#define MAX_PHASE              15
-#define RX_TUNING_CNT          3
-
-#define QFN24                  0
-#define LQFP48                 1
-#define CHECK_PKG(ucr, pkg)    ((ucr)->package == (pkg))
-
-/* data structures */
-struct rtsx_ucr {
-       u16                     vendor_id;
-       u16                     product_id;
-
-       int                     package;
-       u8                      ic_version;
-       bool                    is_rts5179;
-
-       unsigned int            cur_clk;
-
-       u8                      *cmd_buf;
-       unsigned int            cmd_idx;
-       u8                      *rsp_buf;
-
-       struct usb_device       *pusb_dev;
-       struct usb_interface    *pusb_intf;
-       struct usb_sg_request   current_sg;
-       unsigned char           *iobuf;
-       dma_addr_t              iobuf_dma;
-
-       struct timer_list       sg_timer;
-       struct mutex            dev_mutex;
-};
-
-/* buffer size */
-#define IOBUF_SIZE             1024
-
-/* prototypes of exported functions */
-extern int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status);
-
-extern int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data);
-extern int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
-               u8 data);
-
-extern int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
-               u8 data);
-extern int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr,
-               u8 *data);
-
-extern void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type,
-               u16 reg_addr, u8 mask, u8 data);
-extern int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout);
-extern int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout);
-extern int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
-                             void *buf, unsigned int len, int use_sg,
-                             unsigned int *act_len, int timeout);
-
-extern int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
-extern int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
-extern int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
-               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
-extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
-
-/* card status */
-#define SD_CD          0x01
-#define MS_CD          0x02
-#define XD_CD          0x04
-#define CD_MASK                (SD_CD | MS_CD | XD_CD)
-#define SD_WP          0x08
-
-/* reader command field offset & parameters */
-#define READ_REG_CMD           0
-#define WRITE_REG_CMD          1
-#define CHECK_REG_CMD          2
-
-#define PACKET_TYPE            4
-#define CNT_H                  5
-#define CNT_L                  6
-#define STAGE_FLAG             7
-#define CMD_OFFSET             8
-#define SEQ_WRITE_DATA_OFFSET  12
-
-#define BATCH_CMD              0
-#define SEQ_READ               1
-#define SEQ_WRITE              2
-
-#define STAGE_R                        0x01
-#define STAGE_DI               0x02
-#define STAGE_DO               0x04
-#define STAGE_MS_STATUS                0x08
-#define STAGE_XD_STATUS                0x10
-#define MODE_C                 0x00
-#define MODE_CR                        (STAGE_R)
-#define MODE_CDIR              (STAGE_R | STAGE_DI)
-#define MODE_CDOR              (STAGE_R | STAGE_DO)
-
-#define EP0_OP_SHIFT           14
-#define EP0_READ_REG_CMD       2
-#define EP0_WRITE_REG_CMD      3
-
-#define rtsx_usb_cmd_hdr_tag(ucr)              \
-       do {                                    \
-               ucr->cmd_buf[0] = 'R';          \
-               ucr->cmd_buf[1] = 'T';          \
-               ucr->cmd_buf[2] = 'C';          \
-               ucr->cmd_buf[3] = 'R';          \
-       } while (0)
-
-static inline void rtsx_usb_init_cmd(struct rtsx_ucr *ucr)
-{
-       rtsx_usb_cmd_hdr_tag(ucr);
-       ucr->cmd_idx = 0;
-       ucr->cmd_buf[PACKET_TYPE] = BATCH_CMD;
-}
-
-/* internal register address */
-#define FPDCTL                         0xFC00
-#define SSC_DIV_N_0                    0xFC07
-#define SSC_CTL1                       0xFC09
-#define SSC_CTL2                       0xFC0A
-#define CFG_MODE                       0xFC0E
-#define CFG_MODE_1                     0xFC0F
-#define RCCTL                          0xFC14
-#define SOF_WDOG                       0xFC28
-#define SYS_DUMMY0                     0xFC30
-
-#define MS_BLKEND                      0xFD30
-#define MS_READ_START                  0xFD31
-#define MS_READ_COUNT                  0xFD32
-#define MS_WRITE_START                 0xFD33
-#define MS_WRITE_COUNT                 0xFD34
-#define MS_COMMAND                     0xFD35
-#define MS_OLD_BLOCK_0                 0xFD36
-#define MS_OLD_BLOCK_1                 0xFD37
-#define MS_NEW_BLOCK_0                 0xFD38
-#define MS_NEW_BLOCK_1                 0xFD39
-#define MS_LOG_BLOCK_0                 0xFD3A
-#define MS_LOG_BLOCK_1                 0xFD3B
-#define MS_BUS_WIDTH                   0xFD3C
-#define MS_PAGE_START                  0xFD3D
-#define MS_PAGE_LENGTH                 0xFD3E
-#define MS_CFG                         0xFD40
-#define MS_TPC                         0xFD41
-#define MS_TRANS_CFG                   0xFD42
-#define MS_TRANSFER                    0xFD43
-#define MS_INT_REG                     0xFD44
-#define MS_BYTE_CNT                    0xFD45
-#define MS_SECTOR_CNT_L                        0xFD46
-#define MS_SECTOR_CNT_H                        0xFD47
-#define MS_DBUS_H                      0xFD48
-
-#define CARD_DMA1_CTL                  0xFD5C
-#define CARD_PULL_CTL1                 0xFD60
-#define CARD_PULL_CTL2                 0xFD61
-#define CARD_PULL_CTL3                 0xFD62
-#define CARD_PULL_CTL4                 0xFD63
-#define CARD_PULL_CTL5                 0xFD64
-#define CARD_PULL_CTL6                 0xFD65
-#define CARD_EXIST                     0xFD6F
-#define CARD_INT_PEND                  0xFD71
-
-#define LDO_POWER_CFG                  0xFD7B
-
-#define SD_CFG1                                0xFDA0
-#define SD_CFG2                                0xFDA1
-#define SD_CFG3                                0xFDA2
-#define SD_STAT1                       0xFDA3
-#define SD_STAT2                       0xFDA4
-#define SD_BUS_STAT                    0xFDA5
-#define SD_PAD_CTL                     0xFDA6
-#define SD_SAMPLE_POINT_CTL            0xFDA7
-#define SD_PUSH_POINT_CTL              0xFDA8
-#define SD_CMD0                                0xFDA9
-#define SD_CMD1                                0xFDAA
-#define SD_CMD2                                0xFDAB
-#define SD_CMD3                                0xFDAC
-#define SD_CMD4                                0xFDAD
-#define SD_CMD5                                0xFDAE
-#define SD_BYTE_CNT_L                  0xFDAF
-#define SD_BYTE_CNT_H                  0xFDB0
-#define SD_BLOCK_CNT_L                 0xFDB1
-#define SD_BLOCK_CNT_H                 0xFDB2
-#define SD_TRANSFER                    0xFDB3
-#define SD_CMD_STATE                   0xFDB5
-#define SD_DATA_STATE                  0xFDB6
-#define SD_VPCLK0_CTL                  0xFC2A
-#define SD_VPCLK1_CTL                  0xFC2B
-#define SD_DCMPS0_CTL                  0xFC2C
-#define SD_DCMPS1_CTL                  0xFC2D
-
-#define CARD_DMA1_CTL                  0xFD5C
-
-#define HW_VERSION                     0xFC01
-
-#define SSC_CLK_FPGA_SEL               0xFC02
-#define CLK_DIV                                0xFC03
-#define SFSM_ED                                0xFC04
-
-#define CD_DEGLITCH_WIDTH              0xFC20
-#define CD_DEGLITCH_EN                 0xFC21
-#define AUTO_DELINK_EN                 0xFC23
-
-#define FPGA_PULL_CTL                  0xFC1D
-#define CARD_CLK_SOURCE                        0xFC2E
-
-#define CARD_SHARE_MODE                        0xFD51
-#define CARD_DRIVE_SEL                 0xFD52
-#define CARD_STOP                      0xFD53
-#define CARD_OE                                0xFD54
-#define CARD_AUTO_BLINK                        0xFD55
-#define CARD_GPIO                      0xFD56
-#define SD30_DRIVE_SEL                 0xFD57
-
-#define CARD_DATA_SOURCE               0xFD5D
-#define CARD_SELECT                    0xFD5E
-
-#define CARD_CLK_EN                    0xFD79
-#define CARD_PWR_CTL                   0xFD7A
-
-#define OCPCTL                         0xFD80
-#define OCPPARA1                       0xFD81
-#define OCPPARA2                       0xFD82
-#define OCPSTAT                                0xFD83
-
-#define HS_USB_STAT                    0xFE01
-#define HS_VCONTROL                    0xFE26
-#define HS_VSTAIN                      0xFE27
-#define HS_VLOADM                      0xFE28
-#define HS_VSTAOUT                     0xFE29
-
-#define MC_IRQ                         0xFF00
-#define MC_IRQEN                       0xFF01
-#define MC_FIFO_CTL                    0xFF02
-#define MC_FIFO_BC0                    0xFF03
-#define MC_FIFO_BC1                    0xFF04
-#define MC_FIFO_STAT                   0xFF05
-#define MC_FIFO_MODE                   0xFF06
-#define MC_FIFO_RD_PTR0                        0xFF07
-#define MC_FIFO_RD_PTR1                        0xFF08
-#define MC_DMA_CTL                     0xFF10
-#define MC_DMA_TC0                     0xFF11
-#define MC_DMA_TC1                     0xFF12
-#define MC_DMA_TC2                     0xFF13
-#define MC_DMA_TC3                     0xFF14
-#define MC_DMA_RST                     0xFF15
-
-#define RBUF_SIZE_MASK                 0xFBFF
-#define RBUF_BASE                      0xF000
-#define PPBUF_BASE1                    0xF800
-#define PPBUF_BASE2                    0xFA00
-
-/* internal register value macros */
-#define POWER_OFF                      0x03
-#define PARTIAL_POWER_ON               0x02
-#define POWER_ON                       0x00
-#define POWER_MASK                     0x03
-#define LDO3318_PWR_MASK               0x0C
-#define LDO_ON                         0x00
-#define LDO_SUSPEND                    0x08
-#define LDO_OFF                                0x0C
-#define DV3318_AUTO_PWR_OFF            0x10
-#define FORCE_LDO_POWERB               0x60
-
-/* LDO_POWER_CFG */
-#define TUNE_SD18_MASK                 0x1C
-#define TUNE_SD18_1V7                  0x00
-#define TUNE_SD18_1V8                  (0x01 << 2)
-#define TUNE_SD18_1V9                  (0x02 << 2)
-#define TUNE_SD18_2V0                  (0x03 << 2)
-#define TUNE_SD18_2V7                  (0x04 << 2)
-#define TUNE_SD18_2V8                  (0x05 << 2)
-#define TUNE_SD18_2V9                  (0x06 << 2)
-#define TUNE_SD18_3V3                  (0x07 << 2)
-
-/* CLK_DIV */
-#define CLK_CHANGE                     0x80
-#define CLK_DIV_1                      0x00
-#define CLK_DIV_2                      0x01
-#define CLK_DIV_4                      0x02
-#define CLK_DIV_8                      0x03
-
-#define SSC_POWER_MASK                 0x01
-#define SSC_POWER_DOWN                 0x01
-#define SSC_POWER_ON                   0x00
-
-#define FPGA_VER                       0x80
-#define HW_VER_MASK                    0x0F
-
-#define EXTEND_DMA1_ASYNC_SIGNAL       0x02
-
-/* CFG_MODE*/
-#define XTAL_FREE                      0x80
-#define CLK_MODE_MASK                  0x03
-#define CLK_MODE_12M_XTAL              0x00
-#define CLK_MODE_NON_XTAL              0x01
-#define CLK_MODE_24M_OSC               0x02
-#define CLK_MODE_48M_OSC               0x03
-
-/* CFG_MODE_1*/
-#define RTS5179                                0x02
-
-#define NYET_EN                                0x01
-#define NYET_MSAK                      0x01
-
-#define SD30_DRIVE_MASK                        0x07
-#define SD20_DRIVE_MASK                        0x03
-
-#define DISABLE_SD_CD                  0x08
-#define DISABLE_MS_CD                  0x10
-#define DISABLE_XD_CD                  0x20
-#define SD_CD_DEGLITCH_EN              0x01
-#define MS_CD_DEGLITCH_EN              0x02
-#define XD_CD_DEGLITCH_EN              0x04
-
-#define        CARD_SHARE_LQFP48               0x04
-#define        CARD_SHARE_QFN24                0x00
-#define CARD_SHARE_LQFP_SEL            0x04
-#define        CARD_SHARE_XD                   0x00
-#define        CARD_SHARE_SD                   0x01
-#define        CARD_SHARE_MS                   0x02
-#define CARD_SHARE_MASK                        0x03
-
-
-/* SD30_DRIVE_SEL */
-#define DRIVER_TYPE_A                  0x05
-#define DRIVER_TYPE_B                  0x03
-#define DRIVER_TYPE_C                  0x02
-#define DRIVER_TYPE_D                  0x01
-
-/* SD_BUS_STAT */
-#define        SD_CLK_TOGGLE_EN                0x80
-#define        SD_CLK_FORCE_STOP               0x40
-#define        SD_DAT3_STATUS                  0x10
-#define        SD_DAT2_STATUS                  0x08
-#define        SD_DAT1_STATUS                  0x04
-#define        SD_DAT0_STATUS                  0x02
-#define        SD_CMD_STATUS                   0x01
-
-/* SD_PAD_CTL */
-#define        SD_IO_USING_1V8                 0x80
-#define        SD_IO_USING_3V3                 0x7F
-#define        TYPE_A_DRIVING                  0x00
-#define        TYPE_B_DRIVING                  0x01
-#define        TYPE_C_DRIVING                  0x02
-#define        TYPE_D_DRIVING                  0x03
-
-/* CARD_CLK_EN */
-#define SD_CLK_EN                      0x04
-#define MS_CLK_EN                      0x08
-
-/* CARD_SELECT */
-#define SD_MOD_SEL                     2
-#define MS_MOD_SEL                     3
-
-/* CARD_SHARE_MODE */
-#define        CARD_SHARE_LQFP48               0x04
-#define        CARD_SHARE_QFN24                0x00
-#define CARD_SHARE_LQFP_SEL            0x04
-#define        CARD_SHARE_XD                   0x00
-#define        CARD_SHARE_SD                   0x01
-#define        CARD_SHARE_MS                   0x02
-#define CARD_SHARE_MASK                        0x03
-
-/* SSC_CTL1 */
-#define SSC_RSTB                       0x80
-#define SSC_8X_EN                      0x40
-#define SSC_FIX_FRAC                   0x20
-#define SSC_SEL_1M                     0x00
-#define SSC_SEL_2M                     0x08
-#define SSC_SEL_4M                     0x10
-#define SSC_SEL_8M                     0x18
-
-/* SSC_CTL2 */
-#define SSC_DEPTH_MASK                 0x03
-#define SSC_DEPTH_DISALBE              0x00
-#define SSC_DEPTH_2M                   0x01
-#define SSC_DEPTH_1M                   0x02
-#define SSC_DEPTH_512K                 0x03
-
-/* SD_VPCLK0_CTL */
-#define PHASE_CHANGE                   0x80
-#define PHASE_NOT_RESET                        0x40
-
-/* SD_TRANSFER */
-#define        SD_TRANSFER_START               0x80
-#define        SD_TRANSFER_END                 0x40
-#define SD_STAT_IDLE                   0x20
-#define        SD_TRANSFER_ERR                 0x10
-#define        SD_TM_NORMAL_WRITE              0x00
-#define        SD_TM_AUTO_WRITE_3              0x01
-#define        SD_TM_AUTO_WRITE_4              0x02
-#define        SD_TM_AUTO_READ_3               0x05
-#define        SD_TM_AUTO_READ_4               0x06
-#define        SD_TM_CMD_RSP                   0x08
-#define        SD_TM_AUTO_WRITE_1              0x09
-#define        SD_TM_AUTO_WRITE_2              0x0A
-#define        SD_TM_NORMAL_READ               0x0C
-#define        SD_TM_AUTO_READ_1               0x0D
-#define        SD_TM_AUTO_READ_2               0x0E
-#define        SD_TM_AUTO_TUNING               0x0F
-
-/* SD_CFG1 */
-#define SD_CLK_DIVIDE_0                        0x00
-#define        SD_CLK_DIVIDE_256               0xC0
-#define        SD_CLK_DIVIDE_128               0x80
-#define SD_CLK_DIVIDE_MASK             0xC0
-#define        SD_BUS_WIDTH_1BIT               0x00
-#define        SD_BUS_WIDTH_4BIT               0x01
-#define        SD_BUS_WIDTH_8BIT               0x02
-#define        SD_ASYNC_FIFO_RST               0x10
-#define        SD_20_MODE                      0x00
-#define        SD_DDR_MODE                     0x04
-#define        SD_30_MODE                      0x08
-
-/* SD_CFG2 */
-#define        SD_CALCULATE_CRC7               0x00
-#define        SD_NO_CALCULATE_CRC7            0x80
-#define        SD_CHECK_CRC16                  0x00
-#define        SD_NO_CHECK_CRC16               0x40
-#define SD_WAIT_CRC_TO_EN              0x20
-#define        SD_WAIT_BUSY_END                0x08
-#define        SD_NO_WAIT_BUSY_END             0x00
-#define        SD_CHECK_CRC7                   0x00
-#define        SD_NO_CHECK_CRC7                0x04
-#define        SD_RSP_LEN_0                    0x00
-#define        SD_RSP_LEN_6                    0x01
-#define        SD_RSP_LEN_17                   0x02
-#define        SD_RSP_TYPE_R0                  0x04
-#define        SD_RSP_TYPE_R1                  0x01
-#define        SD_RSP_TYPE_R1b                 0x09
-#define        SD_RSP_TYPE_R2                  0x02
-#define        SD_RSP_TYPE_R3                  0x05
-#define        SD_RSP_TYPE_R4                  0x05
-#define        SD_RSP_TYPE_R5                  0x01
-#define        SD_RSP_TYPE_R6                  0x01
-#define        SD_RSP_TYPE_R7                  0x01
-
-/* SD_STAT1 */
-#define        SD_CRC7_ERR                     0x80
-#define        SD_CRC16_ERR                    0x40
-#define        SD_CRC_WRITE_ERR                0x20
-#define        SD_CRC_WRITE_ERR_MASK           0x1C
-#define        GET_CRC_TIME_OUT                0x02
-#define        SD_TUNING_COMPARE_ERR           0x01
-
-/* SD_DATA_STATE */
-#define SD_DATA_IDLE                   0x80
-
-/* CARD_DATA_SOURCE */
-#define PINGPONG_BUFFER                        0x01
-#define RING_BUFFER                    0x00
-
-/* CARD_OE */
-#define SD_OUTPUT_EN                   0x04
-#define MS_OUTPUT_EN                   0x08
-
-/* CARD_STOP */
-#define SD_STOP                                0x04
-#define MS_STOP                                0x08
-#define SD_CLR_ERR                     0x40
-#define MS_CLR_ERR                     0x80
-
-/* CARD_CLK_SOURCE */
-#define CRC_FIX_CLK                    (0x00 << 0)
-#define CRC_VAR_CLK0                   (0x01 << 0)
-#define CRC_VAR_CLK1                   (0x02 << 0)
-#define SD30_FIX_CLK                   (0x00 << 2)
-#define SD30_VAR_CLK0                  (0x01 << 2)
-#define SD30_VAR_CLK1                  (0x02 << 2)
-#define SAMPLE_FIX_CLK                 (0x00 << 4)
-#define SAMPLE_VAR_CLK0                        (0x01 << 4)
-#define SAMPLE_VAR_CLK1                        (0x02 << 4)
-
-/* SD_SAMPLE_POINT_CTL */
-#define        DDR_FIX_RX_DAT                  0x00
-#define        DDR_VAR_RX_DAT                  0x80
-#define        DDR_FIX_RX_DAT_EDGE             0x00
-#define        DDR_FIX_RX_DAT_14_DELAY         0x40
-#define        DDR_FIX_RX_CMD                  0x00
-#define        DDR_VAR_RX_CMD                  0x20
-#define        DDR_FIX_RX_CMD_POS_EDGE         0x00
-#define        DDR_FIX_RX_CMD_14_DELAY         0x10
-#define        SD20_RX_POS_EDGE                0x00
-#define        SD20_RX_14_DELAY                0x08
-#define SD20_RX_SEL_MASK               0x08
-
-/* SD_PUSH_POINT_CTL */
-#define        DDR_FIX_TX_CMD_DAT              0x00
-#define        DDR_VAR_TX_CMD_DAT              0x80
-#define        DDR_FIX_TX_DAT_14_TSU           0x00
-#define        DDR_FIX_TX_DAT_12_TSU           0x40
-#define        DDR_FIX_TX_CMD_NEG_EDGE         0x00
-#define        DDR_FIX_TX_CMD_14_AHEAD         0x20
-#define        SD20_TX_NEG_EDGE                0x00
-#define        SD20_TX_14_AHEAD                0x10
-#define SD20_TX_SEL_MASK               0x10
-#define        DDR_VAR_SDCLK_POL_SWAP          0x01
-
-/* MS_CFG */
-#define        SAMPLE_TIME_RISING              0x00
-#define        SAMPLE_TIME_FALLING             0x80
-#define        PUSH_TIME_DEFAULT               0x00
-#define        PUSH_TIME_ODD                   0x40
-#define        NO_EXTEND_TOGGLE                0x00
-#define        EXTEND_TOGGLE_CHK               0x20
-#define        MS_BUS_WIDTH_1                  0x00
-#define        MS_BUS_WIDTH_4                  0x10
-#define        MS_BUS_WIDTH_8                  0x18
-#define        MS_2K_SECTOR_MODE               0x04
-#define        MS_512_SECTOR_MODE              0x00
-#define        MS_TOGGLE_TIMEOUT_EN            0x00
-#define        MS_TOGGLE_TIMEOUT_DISEN         0x01
-#define MS_NO_CHECK_INT                        0x02
-
-/* MS_TRANS_CFG */
-#define        WAIT_INT                        0x80
-#define        NO_WAIT_INT                     0x00
-#define        NO_AUTO_READ_INT_REG            0x00
-#define        AUTO_READ_INT_REG               0x40
-#define        MS_CRC16_ERR                    0x20
-#define        MS_RDY_TIMEOUT                  0x10
-#define        MS_INT_CMDNK                    0x08
-#define        MS_INT_BREQ                     0x04
-#define        MS_INT_ERR                      0x02
-#define        MS_INT_CED                      0x01
-
-/* MS_TRANSFER */
-#define        MS_TRANSFER_START               0x80
-#define        MS_TRANSFER_END                 0x40
-#define        MS_TRANSFER_ERR                 0x20
-#define        MS_BS_STATE                     0x10
-#define        MS_TM_READ_BYTES                0x00
-#define        MS_TM_NORMAL_READ               0x01
-#define        MS_TM_WRITE_BYTES               0x04
-#define        MS_TM_NORMAL_WRITE              0x05
-#define        MS_TM_AUTO_READ                 0x08
-#define        MS_TM_AUTO_WRITE                0x0C
-#define MS_TM_SET_CMD                  0x06
-#define MS_TM_COPY_PAGE                        0x07
-#define MS_TM_MULTI_READ               0x02
-#define MS_TM_MULTI_WRITE              0x03
-
-/* MC_FIFO_CTL */
-#define FIFO_FLUSH                     0x01
-
-/* MC_DMA_RST */
-#define DMA_RESET  0x01
-
-/* MC_DMA_CTL */
-#define DMA_TC_EQ_0                    0x80
-#define DMA_DIR_TO_CARD                        0x00
-#define DMA_DIR_FROM_CARD              0x02
-#define DMA_EN                         0x01
-#define DMA_128                                (0 << 2)
-#define DMA_256                                (1 << 2)
-#define DMA_512                                (2 << 2)
-#define DMA_1024                       (3 << 2)
-#define DMA_PACK_SIZE_MASK             0x0C
-
-/* CARD_INT_PEND */
-#define XD_INT                         0x10
-#define MS_INT                         0x08
-#define SD_INT                         0x04
-
-/* LED operations*/
-static inline int rtsx_usb_turn_on_led(struct rtsx_ucr *ucr)
-{
-       return  rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x02);
-}
-
-static inline int rtsx_usb_turn_off_led(struct rtsx_ucr *ucr)
-{
-       return rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x03);
-}
-
-/* HW error clearing */
-static inline void rtsx_usb_clear_fsm_err(struct rtsx_ucr *ucr)
-{
-       rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);
-}
-
-static inline void rtsx_usb_clear_dma_err(struct rtsx_ucr *ucr)
-{
-       rtsx_usb_ep0_write_register(ucr, MC_FIFO_CTL,
-                       FIFO_FLUSH, FIFO_FLUSH);
-       rtsx_usb_ep0_write_register(ucr, MC_DMA_RST, DMA_RESET, DMA_RESET);
-}
-#endif /* __RTS51139_H */
diff --git a/include/linux/rtsx_common.h b/include/linux/rtsx_common.h
new file mode 100644 (file)
index 0000000..443176e
--- /dev/null
@@ -0,0 +1,50 @@
+/* Driver for Realtek driver-based card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#ifndef __RTSX_COMMON_H
+#define __RTSX_COMMON_H
+
+#define DRV_NAME_RTSX_PCI              "rtsx_pci"
+#define DRV_NAME_RTSX_PCI_SDMMC                "rtsx_pci_sdmmc"
+#define DRV_NAME_RTSX_PCI_MS           "rtsx_pci_ms"
+
+#define RTSX_REG_PAIR(addr, val)       (((u32)(addr) << 16) | (u8)(val))
+
+#define RTSX_SSC_DEPTH_4M              0x01
+#define RTSX_SSC_DEPTH_2M              0x02
+#define RTSX_SSC_DEPTH_1M              0x03
+#define RTSX_SSC_DEPTH_500K            0x04
+#define RTSX_SSC_DEPTH_250K            0x05
+
+#define RTSX_SD_CARD                   0
+#define RTSX_MS_CARD                   1
+
+#define CLK_TO_DIV_N                   0
+#define DIV_N_TO_CLK                   1
+
+struct platform_device;
+
+struct rtsx_slot {
+       struct platform_device  *p_dev;
+       void                    (*card_event)(struct platform_device *p_dev);
+};
+
+#endif
diff --git a/include/linux/rtsx_pci.h b/include/linux/rtsx_pci.h
new file mode 100644 (file)
index 0000000..6781b5b
--- /dev/null
@@ -0,0 +1,1141 @@
+/* Driver for Realtek PCI-Express card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Wei WANG <wei_wang@realsil.com.cn>
+ */
+
+#ifndef __RTSX_PCI_H
+#define __RTSX_PCI_H
+
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/rtsx_common.h>
+
+#define MAX_RW_REG_CNT                 1024
+
+#define RTSX_HCBAR                     0x00
+#define RTSX_HCBCTLR                   0x04
+#define   STOP_CMD                     (0x01 << 28)
+#define   READ_REG_CMD                 0
+#define   WRITE_REG_CMD                        1
+#define   CHECK_REG_CMD                        2
+
+#define RTSX_HDBAR                     0x08
+#define   SG_INT                       0x04
+#define   SG_END                       0x02
+#define   SG_VALID                     0x01
+#define   SG_NO_OP                     0x00
+#define   SG_TRANS_DATA                        (0x02 << 4)
+#define   SG_LINK_DESC                 (0x03 << 4)
+#define RTSX_HDBCTLR                   0x0C
+#define   SDMA_MODE                    0x00
+#define   ADMA_MODE                    (0x02 << 26)
+#define   STOP_DMA                     (0x01 << 28)
+#define   TRIG_DMA                     (0x01 << 31)
+
+#define RTSX_HAIMR                     0x10
+#define   HAIMR_TRANS_START            (0x01 << 31)
+#define   HAIMR_READ                   0x00
+#define   HAIMR_WRITE                  (0x01 << 30)
+#define   HAIMR_READ_START             (HAIMR_TRANS_START | HAIMR_READ)
+#define   HAIMR_WRITE_START            (HAIMR_TRANS_START | HAIMR_WRITE)
+#define   HAIMR_TRANS_END                      (HAIMR_TRANS_START)
+
+#define RTSX_BIPR                      0x14
+#define   CMD_DONE_INT                 (1 << 31)
+#define   DATA_DONE_INT                        (1 << 30)
+#define   TRANS_OK_INT                 (1 << 29)
+#define   TRANS_FAIL_INT               (1 << 28)
+#define   XD_INT                       (1 << 27)
+#define   MS_INT                       (1 << 26)
+#define   SD_INT                       (1 << 25)
+#define   GPIO0_INT                    (1 << 24)
+#define   OC_INT                       (1 << 23)
+#define   SD_WRITE_PROTECT             (1 << 19)
+#define   XD_EXIST                     (1 << 18)
+#define   MS_EXIST                     (1 << 17)
+#define   SD_EXIST                     (1 << 16)
+#define   DELINK_INT                   GPIO0_INT
+#define   MS_OC_INT                    (1 << 23)
+#define   SD_OC_INT                    (1 << 22)
+
+#define CARD_INT               (XD_INT | MS_INT | SD_INT)
+#define NEED_COMPLETE_INT      (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
+#define RTSX_INT               (CMD_DONE_INT | NEED_COMPLETE_INT | \
+                                       CARD_INT | GPIO0_INT | OC_INT)
+#define CARD_EXIST             (XD_EXIST | MS_EXIST | SD_EXIST)
+
+#define RTSX_BIER                      0x18
+#define   CMD_DONE_INT_EN              (1 << 31)
+#define   DATA_DONE_INT_EN             (1 << 30)
+#define   TRANS_OK_INT_EN              (1 << 29)
+#define   TRANS_FAIL_INT_EN            (1 << 28)
+#define   XD_INT_EN                    (1 << 27)
+#define   MS_INT_EN                    (1 << 26)
+#define   SD_INT_EN                    (1 << 25)
+#define   GPIO0_INT_EN                 (1 << 24)
+#define   OC_INT_EN                    (1 << 23)
+#define   DELINK_INT_EN                        GPIO0_INT_EN
+#define   MS_OC_INT_EN                 (1 << 23)
+#define   SD_OC_INT_EN                 (1 << 22)
+
+
+/*
+ * macros for easy use
+ */
+#define rtsx_pci_writel(pcr, reg, value) \
+       iowrite32(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readl(pcr, reg) \
+       ioread32((pcr)->remap_addr + reg)
+#define rtsx_pci_writew(pcr, reg, value) \
+       iowrite16(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readw(pcr, reg) \
+       ioread16((pcr)->remap_addr + reg)
+#define rtsx_pci_writeb(pcr, reg, value) \
+       iowrite8(value, (pcr)->remap_addr + reg)
+#define rtsx_pci_readb(pcr, reg) \
+       ioread8((pcr)->remap_addr + reg)
+
+#define rtsx_pci_read_config_byte(pcr, where, val) \
+       pci_read_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_byte(pcr, where, val) \
+       pci_write_config_byte((pcr)->pci, where, val)
+
+#define rtsx_pci_read_config_dword(pcr, where, val) \
+       pci_read_config_dword((pcr)->pci, where, val)
+
+#define rtsx_pci_write_config_dword(pcr, where, val) \
+       pci_write_config_dword((pcr)->pci, where, val)
+
+#define STATE_TRANS_NONE               0
+#define STATE_TRANS_CMD                        1
+#define STATE_TRANS_BUF                        2
+#define STATE_TRANS_SG                 3
+
+#define TRANS_NOT_READY                        0
+#define TRANS_RESULT_OK                        1
+#define TRANS_RESULT_FAIL              2
+#define TRANS_NO_DEVICE                        3
+
+#define RTSX_RESV_BUF_LEN              4096
+#define HOST_CMDS_BUF_LEN              1024
+#define HOST_SG_TBL_BUF_LEN            (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
+#define HOST_SG_TBL_ITEMS              (HOST_SG_TBL_BUF_LEN / 8)
+#define MAX_SG_ITEM_LEN                        0x80000
+#define HOST_TO_DEVICE                 0
+#define DEVICE_TO_HOST                 1
+
+#define OUTPUT_3V3                     0
+#define OUTPUT_1V8                     1
+
+#define RTSX_PHASE_MAX                 32
+#define RX_TUNING_CNT                  3
+
+#define MS_CFG                         0xFD40
+#define   SAMPLE_TIME_RISING           0x00
+#define   SAMPLE_TIME_FALLING          0x80
+#define   PUSH_TIME_DEFAULT            0x00
+#define   PUSH_TIME_ODD                        0x40
+#define   NO_EXTEND_TOGGLE             0x00
+#define   EXTEND_TOGGLE_CHK            0x20
+#define   MS_BUS_WIDTH_1               0x00
+#define   MS_BUS_WIDTH_4               0x10
+#define   MS_BUS_WIDTH_8               0x18
+#define   MS_2K_SECTOR_MODE            0x04
+#define   MS_512_SECTOR_MODE           0x00
+#define   MS_TOGGLE_TIMEOUT_EN         0x00
+#define   MS_TOGGLE_TIMEOUT_DISEN      0x01
+#define MS_NO_CHECK_INT                        0x02
+#define MS_TPC                         0xFD41
+#define MS_TRANS_CFG                   0xFD42
+#define   WAIT_INT                     0x80
+#define   NO_WAIT_INT                  0x00
+#define   NO_AUTO_READ_INT_REG         0x00
+#define   AUTO_READ_INT_REG            0x40
+#define   MS_CRC16_ERR                 0x20
+#define   MS_RDY_TIMEOUT               0x10
+#define   MS_INT_CMDNK                 0x08
+#define   MS_INT_BREQ                  0x04
+#define   MS_INT_ERR                   0x02
+#define   MS_INT_CED                   0x01
+#define MS_TRANSFER                    0xFD43
+#define   MS_TRANSFER_START            0x80
+#define   MS_TRANSFER_END              0x40
+#define   MS_TRANSFER_ERR              0x20
+#define   MS_BS_STATE                  0x10
+#define   MS_TM_READ_BYTES             0x00
+#define   MS_TM_NORMAL_READ            0x01
+#define   MS_TM_WRITE_BYTES            0x04
+#define   MS_TM_NORMAL_WRITE           0x05
+#define   MS_TM_AUTO_READ              0x08
+#define   MS_TM_AUTO_WRITE             0x0C
+#define MS_INT_REG                     0xFD44
+#define MS_BYTE_CNT                    0xFD45
+#define MS_SECTOR_CNT_L                        0xFD46
+#define MS_SECTOR_CNT_H                        0xFD47
+#define MS_DBUS_H                      0xFD48
+
+#define SD_CFG1                                0xFDA0
+#define   SD_CLK_DIVIDE_0              0x00
+#define   SD_CLK_DIVIDE_256            0xC0
+#define   SD_CLK_DIVIDE_128            0x80
+#define   SD_BUS_WIDTH_1BIT            0x00
+#define   SD_BUS_WIDTH_4BIT            0x01
+#define   SD_BUS_WIDTH_8BIT            0x02
+#define   SD_ASYNC_FIFO_NOT_RST                0x10
+#define   SD_20_MODE                   0x00
+#define   SD_DDR_MODE                  0x04
+#define   SD_30_MODE                   0x08
+#define   SD_CLK_DIVIDE_MASK           0xC0
+#define SD_CFG2                                0xFDA1
+#define   SD_CALCULATE_CRC7            0x00
+#define   SD_NO_CALCULATE_CRC7         0x80
+#define   SD_CHECK_CRC16               0x00
+#define   SD_NO_CHECK_CRC16            0x40
+#define   SD_NO_CHECK_WAIT_CRC_TO      0x20
+#define   SD_WAIT_BUSY_END             0x08
+#define   SD_NO_WAIT_BUSY_END          0x00
+#define   SD_CHECK_CRC7                        0x00
+#define   SD_NO_CHECK_CRC7             0x04
+#define   SD_RSP_LEN_0                 0x00
+#define   SD_RSP_LEN_6                 0x01
+#define   SD_RSP_LEN_17                        0x02
+#define   SD_RSP_TYPE_R0               0x04
+#define   SD_RSP_TYPE_R1               0x01
+#define   SD_RSP_TYPE_R1b              0x09
+#define   SD_RSP_TYPE_R2               0x02
+#define   SD_RSP_TYPE_R3               0x05
+#define   SD_RSP_TYPE_R4               0x05
+#define   SD_RSP_TYPE_R5               0x01
+#define   SD_RSP_TYPE_R6               0x01
+#define   SD_RSP_TYPE_R7               0x01
+#define SD_CFG3                                0xFDA2
+#define   SD_RSP_80CLK_TIMEOUT_EN      0x01
+
+#define SD_STAT1                       0xFDA3
+#define   SD_CRC7_ERR                  0x80
+#define   SD_CRC16_ERR                 0x40
+#define   SD_CRC_WRITE_ERR             0x20
+#define   SD_CRC_WRITE_ERR_MASK                0x1C
+#define   GET_CRC_TIME_OUT             0x02
+#define   SD_TUNING_COMPARE_ERR                0x01
+#define SD_STAT2                       0xFDA4
+#define   SD_RSP_80CLK_TIMEOUT         0x01
+
+#define SD_BUS_STAT                    0xFDA5
+#define   SD_CLK_TOGGLE_EN             0x80
+#define   SD_CLK_FORCE_STOP            0x40
+#define   SD_DAT3_STATUS               0x10
+#define   SD_DAT2_STATUS               0x08
+#define   SD_DAT1_STATUS               0x04
+#define   SD_DAT0_STATUS               0x02
+#define   SD_CMD_STATUS                        0x01
+#define SD_PAD_CTL                     0xFDA6
+#define   SD_IO_USING_1V8              0x80
+#define   SD_IO_USING_3V3              0x7F
+#define   TYPE_A_DRIVING               0x00
+#define   TYPE_B_DRIVING               0x01
+#define   TYPE_C_DRIVING               0x02
+#define   TYPE_D_DRIVING               0x03
+#define SD_SAMPLE_POINT_CTL            0xFDA7
+#define   DDR_FIX_RX_DAT               0x00
+#define   DDR_VAR_RX_DAT               0x80
+#define   DDR_FIX_RX_DAT_EDGE          0x00
+#define   DDR_FIX_RX_DAT_14_DELAY      0x40
+#define   DDR_FIX_RX_CMD               0x00
+#define   DDR_VAR_RX_CMD               0x20
+#define   DDR_FIX_RX_CMD_POS_EDGE      0x00
+#define   DDR_FIX_RX_CMD_14_DELAY      0x10
+#define   SD20_RX_POS_EDGE             0x00
+#define   SD20_RX_14_DELAY             0x08
+#define SD20_RX_SEL_MASK               0x08
+#define SD_PUSH_POINT_CTL              0xFDA8
+#define   DDR_FIX_TX_CMD_DAT           0x00
+#define   DDR_VAR_TX_CMD_DAT           0x80
+#define   DDR_FIX_TX_DAT_14_TSU                0x00
+#define   DDR_FIX_TX_DAT_12_TSU                0x40
+#define   DDR_FIX_TX_CMD_NEG_EDGE      0x00
+#define   DDR_FIX_TX_CMD_14_AHEAD      0x20
+#define   SD20_TX_NEG_EDGE             0x00
+#define   SD20_TX_14_AHEAD             0x10
+#define   SD20_TX_SEL_MASK             0x10
+#define   DDR_VAR_SDCLK_POL_SWAP       0x01
+#define SD_CMD0                                0xFDA9
+#define   SD_CMD_START                 0x40
+#define SD_CMD1                                0xFDAA
+#define SD_CMD2                                0xFDAB
+#define SD_CMD3                                0xFDAC
+#define SD_CMD4                                0xFDAD
+#define SD_CMD5                                0xFDAE
+#define SD_BYTE_CNT_L                  0xFDAF
+#define SD_BYTE_CNT_H                  0xFDB0
+#define SD_BLOCK_CNT_L                 0xFDB1
+#define SD_BLOCK_CNT_H                 0xFDB2
+#define SD_TRANSFER                    0xFDB3
+#define   SD_TRANSFER_START            0x80
+#define   SD_TRANSFER_END              0x40
+#define   SD_STAT_IDLE                 0x20
+#define   SD_TRANSFER_ERR              0x10
+#define   SD_TM_NORMAL_WRITE           0x00
+#define   SD_TM_AUTO_WRITE_3           0x01
+#define   SD_TM_AUTO_WRITE_4           0x02
+#define   SD_TM_AUTO_READ_3            0x05
+#define   SD_TM_AUTO_READ_4            0x06
+#define   SD_TM_CMD_RSP                        0x08
+#define   SD_TM_AUTO_WRITE_1           0x09
+#define   SD_TM_AUTO_WRITE_2           0x0A
+#define   SD_TM_NORMAL_READ            0x0C
+#define   SD_TM_AUTO_READ_1            0x0D
+#define   SD_TM_AUTO_READ_2            0x0E
+#define   SD_TM_AUTO_TUNING            0x0F
+#define SD_CMD_STATE                   0xFDB5
+#define   SD_CMD_IDLE                  0x80
+
+#define SD_DATA_STATE                  0xFDB6
+#define   SD_DATA_IDLE                 0x80
+
+#define SRCTL                          0xFC13
+
+#define DCM_DRP_CTL                    0xFC23
+#define   DCM_RESET                    0x08
+#define   DCM_LOCKED                   0x04
+#define   DCM_208M                     0x00
+#define   DCM_TX                       0x01
+#define   DCM_RX                       0x02
+#define DCM_DRP_TRIG                   0xFC24
+#define   DRP_START                    0x80
+#define   DRP_DONE                     0x40
+#define DCM_DRP_CFG                    0xFC25
+#define   DRP_WRITE                    0x80
+#define   DRP_READ                     0x00
+#define   DCM_WRITE_ADDRESS_50         0x50
+#define   DCM_WRITE_ADDRESS_51         0x51
+#define   DCM_READ_ADDRESS_00          0x00
+#define   DCM_READ_ADDRESS_51          0x51
+#define DCM_DRP_WR_DATA_L              0xFC26
+#define DCM_DRP_WR_DATA_H              0xFC27
+#define DCM_DRP_RD_DATA_L              0xFC28
+#define DCM_DRP_RD_DATA_H              0xFC29
+#define SD_VPCLK0_CTL                  0xFC2A
+#define SD_VPCLK1_CTL                  0xFC2B
+#define   PHASE_SELECT_MASK            0x1F
+#define SD_DCMPS0_CTL                  0xFC2C
+#define SD_DCMPS1_CTL                  0xFC2D
+#define SD_VPTX_CTL                    SD_VPCLK0_CTL
+#define SD_VPRX_CTL                    SD_VPCLK1_CTL
+#define   PHASE_CHANGE                 0x80
+#define   PHASE_NOT_RESET              0x40
+#define SD_DCMPS_TX_CTL                        SD_DCMPS0_CTL
+#define SD_DCMPS_RX_CTL                        SD_DCMPS1_CTL
+#define   DCMPS_CHANGE                 0x80
+#define   DCMPS_CHANGE_DONE            0x40
+#define   DCMPS_ERROR                  0x20
+#define   DCMPS_CURRENT_PHASE          0x1F
+#define CARD_CLK_SOURCE                        0xFC2E
+#define   CRC_FIX_CLK                  (0x00 << 0)
+#define   CRC_VAR_CLK0                 (0x01 << 0)
+#define   CRC_VAR_CLK1                 (0x02 << 0)
+#define   SD30_FIX_CLK                 (0x00 << 2)
+#define   SD30_VAR_CLK0                        (0x01 << 2)
+#define   SD30_VAR_CLK1                        (0x02 << 2)
+#define   SAMPLE_FIX_CLK               (0x00 << 4)
+#define   SAMPLE_VAR_CLK0              (0x01 << 4)
+#define   SAMPLE_VAR_CLK1              (0x02 << 4)
+#define CARD_PWR_CTL                   0xFD50
+#define   PMOS_STRG_MASK               0x10
+#define   PMOS_STRG_800mA              0x10
+#define   PMOS_STRG_400mA              0x00
+#define   SD_POWER_OFF                 0x03
+#define   SD_PARTIAL_POWER_ON          0x01
+#define   SD_POWER_ON                  0x00
+#define   SD_POWER_MASK                        0x03
+#define   MS_POWER_OFF                 0x0C
+#define   MS_PARTIAL_POWER_ON          0x04
+#define   MS_POWER_ON                  0x00
+#define   MS_POWER_MASK                        0x0C
+#define   BPP_POWER_OFF                        0x0F
+#define   BPP_POWER_5_PERCENT_ON       0x0E
+#define   BPP_POWER_10_PERCENT_ON      0x0C
+#define   BPP_POWER_15_PERCENT_ON      0x08
+#define   BPP_POWER_ON                 0x00
+#define   BPP_POWER_MASK               0x0F
+#define   SD_VCC_PARTIAL_POWER_ON      0x02
+#define   SD_VCC_POWER_ON              0x00
+#define CARD_CLK_SWITCH                        0xFD51
+#define RTL8411B_PACKAGE_MODE          0xFD51
+#define CARD_SHARE_MODE                        0xFD52
+#define   CARD_SHARE_MASK              0x0F
+#define   CARD_SHARE_MULTI_LUN         0x00
+#define   CARD_SHARE_NORMAL            0x00
+#define   CARD_SHARE_48_SD             0x04
+#define   CARD_SHARE_48_MS             0x08
+#define   CARD_SHARE_BAROSSA_SD                0x01
+#define   CARD_SHARE_BAROSSA_MS                0x02
+#define CARD_DRIVE_SEL                 0xFD53
+#define   MS_DRIVE_8mA                 (0x01 << 6)
+#define   MMC_DRIVE_8mA                        (0x01 << 4)
+#define   XD_DRIVE_8mA                 (0x01 << 2)
+#define   GPIO_DRIVE_8mA               0x01
+#define RTS5209_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
+                                       XD_DRIVE_8mA | GPIO_DRIVE_8mA)
+#define RTL8411_CARD_DRIVE_DEFAULT     (MS_DRIVE_8mA | MMC_DRIVE_8mA |\
+                                       XD_DRIVE_8mA)
+#define RTSX_CARD_DRIVE_DEFAULT                (MS_DRIVE_8mA | GPIO_DRIVE_8mA)
+
+#define CARD_STOP                      0xFD54
+#define   SPI_STOP                     0x01
+#define   XD_STOP                      0x02
+#define   SD_STOP                      0x04
+#define   MS_STOP                      0x08
+#define   SPI_CLR_ERR                  0x10
+#define   XD_CLR_ERR                   0x20
+#define   SD_CLR_ERR                   0x40
+#define   MS_CLR_ERR                   0x80
+#define CARD_OE                                0xFD55
+#define   SD_OUTPUT_EN                 0x04
+#define   MS_OUTPUT_EN                 0x08
+#define CARD_AUTO_BLINK                        0xFD56
+#define CARD_GPIO_DIR                  0xFD57
+#define CARD_GPIO                      0xFD58
+#define CARD_DATA_SOURCE               0xFD5B
+#define   PINGPONG_BUFFER              0x01
+#define   RING_BUFFER                  0x00
+#define SD30_CLK_DRIVE_SEL             0xFD5A
+#define   DRIVER_TYPE_A                        0x05
+#define   DRIVER_TYPE_B                        0x03
+#define   DRIVER_TYPE_C                        0x02
+#define   DRIVER_TYPE_D                        0x01
+#define CARD_SELECT                    0xFD5C
+#define   SD_MOD_SEL                   2
+#define   MS_MOD_SEL                   3
+#define SD30_DRIVE_SEL                 0xFD5E
+#define   CFG_DRIVER_TYPE_A            0x02
+#define   CFG_DRIVER_TYPE_B            0x03
+#define   CFG_DRIVER_TYPE_C            0x01
+#define   CFG_DRIVER_TYPE_D            0x00
+#define SD30_CMD_DRIVE_SEL             0xFD5E
+#define SD30_DAT_DRIVE_SEL             0xFD5F
+#define CARD_CLK_EN                    0xFD69
+#define   SD_CLK_EN                    0x04
+#define   MS_CLK_EN                    0x08
+#define SDIO_CTRL                      0xFD6B
+#define CD_PAD_CTL                     0xFD73
+#define   CD_DISABLE_MASK              0x07
+#define   MS_CD_DISABLE                        0x04
+#define   SD_CD_DISABLE                        0x02
+#define   XD_CD_DISABLE                        0x01
+#define   CD_DISABLE                   0x07
+#define   CD_ENABLE                    0x00
+#define   MS_CD_EN_ONLY                        0x03
+#define   SD_CD_EN_ONLY                        0x05
+#define   XD_CD_EN_ONLY                        0x06
+#define   FORCE_CD_LOW_MASK            0x38
+#define   FORCE_CD_XD_LOW              0x08
+#define   FORCE_CD_SD_LOW              0x10
+#define   FORCE_CD_MS_LOW              0x20
+#define   CD_AUTO_DISABLE              0x40
+#define FPDCTL                         0xFC00
+#define   SSC_POWER_DOWN               0x01
+#define   SD_OC_POWER_DOWN             0x02
+#define   ALL_POWER_DOWN               0x07
+#define   OC_POWER_DOWN                        0x06
+#define PDINFO                         0xFC01
+
+#define CLK_CTL                                0xFC02
+#define   CHANGE_CLK                   0x01
+#define   CLK_LOW_FREQ                 0x01
+
+#define CLK_DIV                                0xFC03
+#define   CLK_DIV_1                    0x01
+#define   CLK_DIV_2                    0x02
+#define   CLK_DIV_4                    0x03
+#define   CLK_DIV_8                    0x04
+#define CLK_SEL                                0xFC04
+
+#define SSC_DIV_N_0                    0xFC0F
+#define SSC_DIV_N_1                    0xFC10
+#define SSC_CTL1                       0xFC11
+#define    SSC_RSTB                    0x80
+#define    SSC_8X_EN                   0x40
+#define    SSC_FIX_FRAC                        0x20
+#define    SSC_SEL_1M                  0x00
+#define    SSC_SEL_2M                  0x08
+#define    SSC_SEL_4M                  0x10
+#define    SSC_SEL_8M                  0x18
+#define SSC_CTL2                       0xFC12
+#define    SSC_DEPTH_MASK              0x07
+#define    SSC_DEPTH_DISALBE           0x00
+#define    SSC_DEPTH_4M                        0x01
+#define    SSC_DEPTH_2M                        0x02
+#define    SSC_DEPTH_1M                        0x03
+#define    SSC_DEPTH_500K              0x04
+#define    SSC_DEPTH_250K              0x05
+#define RCCTL                          0xFC14
+
+#define FPGA_PULL_CTL                  0xFC1D
+#define OLT_LED_CTL                    0xFC1E
+#define GPIO_CTL                       0xFC1F
+
+#define LDO_CTL                                0xFC1E
+#define   BPP_ASIC_1V7                 0x00
+#define   BPP_ASIC_1V8                 0x01
+#define   BPP_ASIC_1V9                 0x02
+#define   BPP_ASIC_2V0                 0x03
+#define   BPP_ASIC_2V7                 0x04
+#define   BPP_ASIC_2V8                 0x05
+#define   BPP_ASIC_3V2                 0x06
+#define   BPP_ASIC_3V3                 0x07
+#define   BPP_REG_TUNED18              0x07
+#define   BPP_TUNED18_SHIFT_8402       5
+#define   BPP_TUNED18_SHIFT_8411       4
+#define   BPP_PAD_MASK                 0x04
+#define   BPP_PAD_3V3                  0x04
+#define   BPP_PAD_1V8                  0x00
+#define   BPP_LDO_POWB                 0x03
+#define   BPP_LDO_ON                   0x00
+#define   BPP_LDO_SUSPEND              0x02
+#define   BPP_LDO_OFF                  0x03
+#define SYS_VER                                0xFC32
+
+#define CARD_PULL_CTL1                 0xFD60
+#define CARD_PULL_CTL2                 0xFD61
+#define CARD_PULL_CTL3                 0xFD62
+#define CARD_PULL_CTL4                 0xFD63
+#define CARD_PULL_CTL5                 0xFD64
+#define CARD_PULL_CTL6                 0xFD65
+
+/* PCI Express Related Registers */
+#define IRQEN0                         0xFE20
+#define IRQSTAT0                       0xFE21
+#define    DMA_DONE_INT                        0x80
+#define    SUSPEND_INT                 0x40
+#define    LINK_RDY_INT                        0x20
+#define    LINK_DOWN_INT               0x10
+#define IRQEN1                         0xFE22
+#define IRQSTAT1                       0xFE23
+#define TLPRIEN                                0xFE24
+#define TLPRISTAT                      0xFE25
+#define TLPTIEN                                0xFE26
+#define TLPTISTAT                      0xFE27
+#define DMATC0                         0xFE28
+#define DMATC1                         0xFE29
+#define DMATC2                         0xFE2A
+#define DMATC3                         0xFE2B
+#define DMACTL                         0xFE2C
+#define   DMA_RST                      0x80
+#define   DMA_BUSY                     0x04
+#define   DMA_DIR_TO_CARD              0x00
+#define   DMA_DIR_FROM_CARD            0x02
+#define   DMA_EN                       0x01
+#define   DMA_128                      (0 << 4)
+#define   DMA_256                      (1 << 4)
+#define   DMA_512                      (2 << 4)
+#define   DMA_1024                     (3 << 4)
+#define   DMA_PACK_SIZE_MASK           0x30
+#define BCTL                           0xFE2D
+#define RBBC0                          0xFE2E
+#define RBBC1                          0xFE2F
+#define RBDAT                          0xFE30
+#define RBCTL                          0xFE34
+#define CFGADDR0                       0xFE35
+#define CFGADDR1                       0xFE36
+#define CFGDATA0                       0xFE37
+#define CFGDATA1                       0xFE38
+#define CFGDATA2                       0xFE39
+#define CFGDATA3                       0xFE3A
+#define CFGRWCTL                       0xFE3B
+#define PHYRWCTL                       0xFE3C
+#define PHYDATA0                       0xFE3D
+#define PHYDATA1                       0xFE3E
+#define PHYADDR                                0xFE3F
+#define MSGRXDATA0                     0xFE40
+#define MSGRXDATA1                     0xFE41
+#define MSGRXDATA2                     0xFE42
+#define MSGRXDATA3                     0xFE43
+#define MSGTXDATA0                     0xFE44
+#define MSGTXDATA1                     0xFE45
+#define MSGTXDATA2                     0xFE46
+#define MSGTXDATA3                     0xFE47
+#define MSGTXCTL                       0xFE48
+#define LTR_CTL                                0xFE4A
+#define LTR_TX_EN_MASK         BIT(7)
+#define LTR_TX_EN_1                    BIT(7)
+#define LTR_TX_EN_0                    0
+#define LTR_LATENCY_MODE_MASK          BIT(6)
+#define LTR_LATENCY_MODE_HW            0
+#define LTR_LATENCY_MODE_SW            BIT(6)
+#define OBFF_CFG                       0xFE4C
+
+#define CDRESUMECTL                    0xFE52
+#define WAKE_SEL_CTL                   0xFE54
+#define PCLK_CTL                       0xFE55
+#define   PCLK_MODE_SEL                        0x20
+#define PME_FORCE_CTL                  0xFE56
+
+#define ASPM_FORCE_CTL                 0xFE57
+#define   FORCE_ASPM_CTL0              0x10
+#define   FORCE_ASPM_VAL_MASK          0x03
+#define   FORCE_ASPM_L1_EN             0x02
+#define   FORCE_ASPM_L0_EN             0x01
+#define   FORCE_ASPM_NO_ASPM           0x00
+#define PM_CLK_FORCE_CTL               0xFE58
+#define FUNC_FORCE_CTL                 0xFE59
+#define   FUNC_FORCE_UPME_XMT_DBG      0x02
+#define PERST_GLITCH_WIDTH             0xFE5C
+#define CHANGE_LINK_STATE              0xFE5B
+#define RESET_LOAD_REG                 0xFE5E
+#define EFUSE_CONTENT                  0xFE5F
+#define HOST_SLEEP_STATE               0xFE60
+#define   HOST_ENTER_S1                        1
+#define   HOST_ENTER_S3                        2
+
+#define SDIO_CFG                       0xFE70
+#define PM_EVENT_DEBUG                 0xFE71
+#define   PME_DEBUG_0                  0x08
+#define NFTS_TX_CTRL                   0xFE72
+
+#define PWR_GATE_CTRL                  0xFE75
+#define   PWR_GATE_EN                  0x01
+#define   LDO3318_PWR_MASK             0x06
+#define   LDO_ON                       0x00
+#define   LDO_SUSPEND                  0x04
+#define   LDO_OFF                      0x06
+#define PWD_SUSPEND_EN                 0xFE76
+#define LDO_PWR_SEL                    0xFE78
+
+#define L1SUB_CONFIG1                  0xFE8D
+#define L1SUB_CONFIG2                  0xFE8E
+#define   L1SUB_AUTO_CFG               0x02
+#define L1SUB_CONFIG3                  0xFE8F
+#define   L1OFF_MBIAS2_EN_5250         BIT(7)
+
+#define DUMMY_REG_RESET_0              0xFE90
+
+#define AUTOLOAD_CFG_BASE              0xFF00
+#define PETXCFG                                0xFF03
+#define FORCE_CLKREQ_DELINK_MASK       BIT(7)
+#define FORCE_CLKREQ_LOW       0x80
+#define FORCE_CLKREQ_HIGH      0x00
+
+#define PM_CTRL1                       0xFF44
+#define   CD_RESUME_EN_MASK            0xF0
+
+#define PM_CTRL2                       0xFF45
+#define PM_CTRL3                       0xFF46
+#define   SDIO_SEND_PME_EN             0x80
+#define   FORCE_RC_MODE_ON             0x40
+#define   FORCE_RX50_LINK_ON           0x20
+#define   D3_DELINK_MODE_EN            0x10
+#define   USE_PESRTB_CTL_DELINK                0x08
+#define   DELAY_PIN_WAKE               0x04
+#define   RESET_PIN_WAKE               0x02
+#define   PM_WAKE_EN                   0x01
+#define PM_CTRL4                       0xFF47
+
+/* Memory mapping */
+#define SRAM_BASE                      0xE600
+#define RBUF_BASE                      0xF400
+#define PPBUF_BASE1                    0xF800
+#define PPBUF_BASE2                    0xFA00
+#define IMAGE_FLAG_ADDR0               0xCE80
+#define IMAGE_FLAG_ADDR1               0xCE81
+
+#define RREF_CFG                       0xFF6C
+#define   RREF_VBGSEL_MASK             0x38
+#define   RREF_VBGSEL_1V25             0x28
+
+#define OOBS_CONFIG                    0xFF6E
+#define   OOBS_AUTOK_DIS               0x80
+#define   OOBS_VAL_MASK                        0x1F
+
+#define LDO_DV18_CFG                   0xFF70
+#define   LDO_DV18_SR_MASK             0xC0
+#define   LDO_DV18_SR_DF               0x40
+
+#define LDO_CONFIG2                    0xFF71
+#define   LDO_D3318_MASK               0x07
+#define   LDO_D3318_33V                        0x07
+#define   LDO_D3318_18V                        0x02
+
+#define LDO_VCC_CFG0                   0xFF72
+#define   LDO_VCC_LMTVTH_MASK          0x30
+#define   LDO_VCC_LMTVTH_2A            0x10
+
+#define LDO_VCC_CFG1                   0xFF73
+#define   LDO_VCC_REF_TUNE_MASK                0x30
+#define   LDO_VCC_REF_1V2              0x20
+#define   LDO_VCC_TUNE_MASK            0x07
+#define   LDO_VCC_1V8                  0x04
+#define   LDO_VCC_3V3                  0x07
+#define   LDO_VCC_LMT_EN               0x08
+
+#define LDO_VIO_CFG                    0xFF75
+#define   LDO_VIO_SR_MASK              0xC0
+#define   LDO_VIO_SR_DF                        0x40
+#define   LDO_VIO_REF_TUNE_MASK                0x30
+#define   LDO_VIO_REF_1V2              0x20
+#define   LDO_VIO_TUNE_MASK            0x07
+#define   LDO_VIO_1V7                  0x03
+#define   LDO_VIO_1V8                  0x04
+#define   LDO_VIO_3V3                  0x07
+
+#define LDO_DV12S_CFG                  0xFF76
+#define   LDO_REF12_TUNE_MASK          0x18
+#define   LDO_REF12_TUNE_DF            0x10
+#define   LDO_D12_TUNE_MASK            0x07
+#define   LDO_D12_TUNE_DF              0x04
+
+#define LDO_AV12S_CFG                  0xFF77
+#define   LDO_AV12S_TUNE_MASK          0x07
+#define   LDO_AV12S_TUNE_DF            0x04
+
+#define SD40_LDO_CTL1                  0xFE7D
+#define   SD40_VIO_TUNE_MASK           0x70
+#define   SD40_VIO_TUNE_1V7            0x30
+#define   SD_VIO_LDO_1V8               0x40
+#define   SD_VIO_LDO_3V3               0x70
+
+/* Phy register */
+#define PHY_PCR                                0x00
+#define   PHY_PCR_FORCE_CODE           0xB000
+#define   PHY_PCR_OOBS_CALI_50         0x0800
+#define   PHY_PCR_OOBS_VCM_08          0x0200
+#define   PHY_PCR_OOBS_SEN_90          0x0040
+#define   PHY_PCR_RSSI_EN              0x0002
+#define   PHY_PCR_RX10K                        0x0001
+
+#define PHY_RCR0                       0x01
+#define PHY_RCR1                       0x02
+#define   PHY_RCR1_ADP_TIME_4          0x0400
+#define   PHY_RCR1_VCO_COARSE          0x001F
+#define   PHY_RCR1_INIT_27S            0x0A1F
+#define PHY_SSCCR2                     0x02
+#define   PHY_SSCCR2_PLL_NCODE         0x0A00
+#define   PHY_SSCCR2_TIME0             0x001C
+#define   PHY_SSCCR2_TIME2_WIDTH       0x0003
+
+#define PHY_RCR2                       0x03
+#define   PHY_RCR2_EMPHASE_EN          0x8000
+#define   PHY_RCR2_NADJR               0x4000
+#define   PHY_RCR2_CDR_SR_2            0x0100
+#define   PHY_RCR2_FREQSEL_12          0x0040
+#define   PHY_RCR2_CDR_SC_12P          0x0010
+#define   PHY_RCR2_CALIB_LATE          0x0002
+#define   PHY_RCR2_INIT_27S            0xC152
+#define PHY_SSCCR3                     0x03
+#define   PHY_SSCCR3_STEP_IN           0x2740
+#define   PHY_SSCCR3_CHECK_DELAY       0x0008
+#define _PHY_ANA03                     0x03
+#define   _PHY_ANA03_TIMER_MAX         0x2700
+#define   _PHY_ANA03_OOBS_DEB_EN       0x0040
+#define   _PHY_CMU_DEBUG_EN            0x0008
+
+#define PHY_RTCR                       0x04
+#define PHY_RDR                                0x05
+#define   PHY_RDR_RXDSEL_1_9           0x4000
+#define   PHY_SSC_AUTO_PWD             0x0600
+#define PHY_TCR0                       0x06
+#define PHY_TCR1                       0x07
+#define PHY_TUNE                       0x08
+#define   PHY_TUNE_TUNEREF_1_0         0x4000
+#define   PHY_TUNE_VBGSEL_1252         0x0C00
+#define   PHY_TUNE_SDBUS_33            0x0200
+#define   PHY_TUNE_TUNED18             0x01C0
+#define   PHY_TUNE_TUNED12             0X0020
+#define   PHY_TUNE_TUNEA12             0x0004
+#define   PHY_TUNE_VOLTAGE_MASK                0xFC3F
+#define   PHY_TUNE_VOLTAGE_3V3         0x03C0
+#define   PHY_TUNE_D18_1V8             0x0100
+#define   PHY_TUNE_D18_1V7             0x0080
+#define PHY_ANA08                      0x08
+#define   PHY_ANA08_RX_EQ_DCGAIN       0x5000
+#define   PHY_ANA08_SEL_RX_EN          0x0400
+#define   PHY_ANA08_RX_EQ_VAL          0x03C0
+#define   PHY_ANA08_SCP                        0x0020
+#define   PHY_ANA08_SEL_IPI            0x0004
+
+#define PHY_IMR                                0x09
+#define PHY_BPCR                       0x0A
+#define   PHY_BPCR_IBRXSEL             0x0400
+#define   PHY_BPCR_IBTXSEL             0x0100
+#define   PHY_BPCR_IB_FILTER           0x0080
+#define   PHY_BPCR_CMIRROR_EN          0x0040
+
+#define PHY_BIST                       0x0B
+#define PHY_RAW_L                      0x0C
+#define PHY_RAW_H                      0x0D
+#define PHY_RAW_DATA                   0x0E
+#define PHY_HOST_CLK_CTRL              0x0F
+#define PHY_DMR                                0x10
+#define PHY_BACR                       0x11
+#define   PHY_BACR_BASIC_MASK          0xFFF3
+#define PHY_IER                                0x12
+#define PHY_BCSR                       0x13
+#define PHY_BPR                                0x14
+#define PHY_BPNR2                      0x15
+#define PHY_BPNR                       0x16
+#define PHY_BRNR2                      0x17
+#define PHY_BENR                       0x18
+#define PHY_REV                                0x19
+#define   PHY_REV_RESV                 0xE000
+#define   PHY_REV_RXIDLE_LATCHED       0x1000
+#define   PHY_REV_P1_EN                        0x0800
+#define   PHY_REV_RXIDLE_EN            0x0400
+#define   PHY_REV_CLKREQ_TX_EN         0x0200
+#define   PHY_REV_CLKREQ_RX_EN         0x0100
+#define   PHY_REV_CLKREQ_DT_1_0                0x0040
+#define   PHY_REV_STOP_CLKRD           0x0020
+#define   PHY_REV_RX_PWST              0x0008
+#define   PHY_REV_STOP_CLKWR           0x0004
+#define _PHY_REV0                      0x19
+#define   _PHY_REV0_FILTER_OUT         0x3800
+#define   _PHY_REV0_CDR_BYPASS_PFD     0x0100
+#define   _PHY_REV0_CDR_RX_IDLE_BYPASS 0x0002
+
+#define PHY_FLD0                       0x1A
+#define PHY_ANA1A                      0x1A
+#define   PHY_ANA1A_TXR_LOOPBACK       0x2000
+#define   PHY_ANA1A_RXT_BIST           0x0500
+#define   PHY_ANA1A_TXR_BIST           0x0040
+#define   PHY_ANA1A_REV                        0x0006
+#define   PHY_FLD0_INIT_27S            0x2546
+#define PHY_FLD1                       0x1B
+#define PHY_FLD2                       0x1C
+#define PHY_FLD3                       0x1D
+#define   PHY_FLD3_TIMER_4             0x0800
+#define   PHY_FLD3_TIMER_6             0x0020
+#define   PHY_FLD3_RXDELINK            0x0004
+#define   PHY_FLD3_INIT_27S            0x0004
+#define PHY_ANA1D                      0x1D
+#define   PHY_ANA1D_DEBUG_ADDR         0x0004
+#define _PHY_FLD0                      0x1D
+#define   _PHY_FLD0_CLK_REQ_20C                0x8000
+#define   _PHY_FLD0_RX_IDLE_EN         0x1000
+#define   _PHY_FLD0_BIT_ERR_RSTN       0x0800
+#define   _PHY_FLD0_BER_COUNT          0x01E0
+#define   _PHY_FLD0_BER_TIMER          0x001E
+#define   _PHY_FLD0_CHECK_EN           0x0001
+
+#define PHY_FLD4                       0x1E
+#define   PHY_FLD4_FLDEN_SEL           0x4000
+#define   PHY_FLD4_REQ_REF             0x2000
+#define   PHY_FLD4_RXAMP_OFF           0x1000
+#define   PHY_FLD4_REQ_ADDA            0x0800
+#define   PHY_FLD4_BER_COUNT           0x00E0
+#define   PHY_FLD4_BER_TIMER           0x000A
+#define   PHY_FLD4_BER_CHK_EN          0x0001
+#define   PHY_FLD4_INIT_27S            0x5C7F
+#define PHY_DIG1E                      0x1E
+#define   PHY_DIG1E_REV                        0x4000
+#define   PHY_DIG1E_D0_X_D1            0x1000
+#define   PHY_DIG1E_RX_ON_HOST         0x0800
+#define   PHY_DIG1E_RCLK_REF_HOST      0x0400
+#define   PHY_DIG1E_RCLK_TX_EN_KEEP    0x0040
+#define   PHY_DIG1E_RCLK_TX_TERM_KEEP  0x0020
+#define   PHY_DIG1E_RCLK_RX_EIDLE_ON   0x0010
+#define   PHY_DIG1E_TX_TERM_KEEP       0x0008
+#define   PHY_DIG1E_RX_TERM_KEEP       0x0004
+#define   PHY_DIG1E_TX_EN_KEEP         0x0002
+#define   PHY_DIG1E_RX_EN_KEEP         0x0001
+#define PHY_DUM_REG                    0x1F
+
+#define PCR_ASPM_SETTING_REG1          0x160
+#define PCR_ASPM_SETTING_REG2          0x168
+
+#define PCR_SETTING_REG1               0x724
+#define PCR_SETTING_REG2               0x814
+#define PCR_SETTING_REG3               0x747
+
+#define rtsx_pci_init_cmd(pcr)         ((pcr)->ci = 0)
+
+#define RTS5227_DEVICE_ID              0x5227
+#define RTS_MAX_TIMES_FREQ_REDUCTION   8
+
+struct rtsx_pcr;
+
+struct pcr_handle {
+       struct rtsx_pcr                 *pcr;
+};
+
+struct pcr_ops {
+       int (*write_phy)(struct rtsx_pcr *pcr, u8 addr, u16 val);
+       int (*read_phy)(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+       int             (*extra_init_hw)(struct rtsx_pcr *pcr);
+       int             (*optimize_phy)(struct rtsx_pcr *pcr);
+       int             (*turn_on_led)(struct rtsx_pcr *pcr);
+       int             (*turn_off_led)(struct rtsx_pcr *pcr);
+       int             (*enable_auto_blink)(struct rtsx_pcr *pcr);
+       int             (*disable_auto_blink)(struct rtsx_pcr *pcr);
+       int             (*card_power_on)(struct rtsx_pcr *pcr, int card);
+       int             (*card_power_off)(struct rtsx_pcr *pcr, int card);
+       int             (*switch_output_voltage)(struct rtsx_pcr *pcr,
+                                               u8 voltage);
+       unsigned int    (*cd_deglitch)(struct rtsx_pcr *pcr);
+       int             (*conv_clk_and_div_n)(int clk, int dir);
+       void            (*fetch_vendor_settings)(struct rtsx_pcr *pcr);
+       void            (*force_power_down)(struct rtsx_pcr *pcr, u8 pm_state);
+
+       void (*set_aspm)(struct rtsx_pcr *pcr, bool enable);
+       int (*set_ltr_latency)(struct rtsx_pcr *pcr, u32 latency);
+       int (*set_l1off_sub)(struct rtsx_pcr *pcr, u8 val);
+       void (*set_l1off_cfg_sub_d0)(struct rtsx_pcr *pcr, int active);
+       void (*full_on)(struct rtsx_pcr *pcr);
+       void (*power_saving)(struct rtsx_pcr *pcr);
+};
+
+enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
+
+#define ASPM_L1_1_EN_MASK              BIT(3)
+#define ASPM_L1_2_EN_MASK              BIT(2)
+#define PM_L1_1_EN_MASK                BIT(1)
+#define PM_L1_2_EN_MASK                BIT(0)
+
+#define ASPM_L1_1_EN                   BIT(0)
+#define ASPM_L1_2_EN                   BIT(1)
+#define PM_L1_1_EN                             BIT(2)
+#define PM_L1_2_EN                             BIT(3)
+#define LTR_L1SS_PWR_GATE_EN   BIT(4)
+#define L1_SNOOZE_TEST_EN              BIT(5)
+#define LTR_L1SS_PWR_GATE_CHECK_CARD_EN        BIT(6)
+
+enum dev_aspm_mode {
+       DEV_ASPM_DYNAMIC,
+       DEV_ASPM_BACKDOOR,
+       DEV_ASPM_STATIC,
+       DEV_ASPM_DISABLE,
+};
+
+/*
+ * struct rtsx_cr_option  - card reader option
+ * @dev_flags: device flags
+ * @force_clkreq_0: force clock request
+ * @ltr_en: enable ltr mode flag
+ * @ltr_enabled: ltr mode in configure space flag
+ * @ltr_active: ltr mode status
+ * @ltr_active_latency: ltr mode active latency
+ * @ltr_idle_latency: ltr mode idle latency
+ * @ltr_l1off_latency: ltr mode l1off latency
+ * @dev_aspm_mode: device aspm mode
+ * @l1_snooze_delay: l1 snooze delay
+ * @ltr_l1off_sspwrgate: ltr l1off sspwrgate
+ * @ltr_l1off_snooze_sspwrgate: ltr l1off snooze sspwrgate
+ */
+struct rtsx_cr_option {
+       u32 dev_flags;
+       bool force_clkreq_0;
+       bool ltr_en;
+       bool ltr_enabled;
+       bool ltr_active;
+       u32 ltr_active_latency;
+       u32 ltr_idle_latency;
+       u32 ltr_l1off_latency;
+       enum dev_aspm_mode dev_aspm_mode;
+       u32 l1_snooze_delay;
+       u8 ltr_l1off_sspwrgate;
+       u8 ltr_l1off_snooze_sspwrgate;
+};
+
+#define rtsx_set_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags |= (flag))
+#define rtsx_clear_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags &= ~(flag))
+#define rtsx_check_dev_flag(cr, flag) \
+       ((cr)->option.dev_flags & (flag))
+
+struct rtsx_pcr {
+       struct pci_dev                  *pci;
+       unsigned int                    id;
+       int                             pcie_cap;
+       struct rtsx_cr_option   option;
+
+       /* pci resources */
+       unsigned long                   addr;
+       void __iomem                    *remap_addr;
+       int                             irq;
+
+       /* host reserved buffer */
+       void                            *rtsx_resv_buf;
+       dma_addr_t                      rtsx_resv_buf_addr;
+
+       void                            *host_cmds_ptr;
+       dma_addr_t                      host_cmds_addr;
+       int                             ci;
+
+       void                            *host_sg_tbl_ptr;
+       dma_addr_t                      host_sg_tbl_addr;
+       int                             sgi;
+
+       u32                             bier;
+       char                            trans_result;
+
+       unsigned int                    card_inserted;
+       unsigned int                    card_removed;
+       unsigned int                    card_exist;
+
+       struct delayed_work             carddet_work;
+       struct delayed_work             idle_work;
+
+       spinlock_t                      lock;
+       struct mutex                    pcr_mutex;
+       struct completion               *done;
+       struct completion               *finish_me;
+
+       unsigned int                    cur_clock;
+       bool                            remove_pci;
+       bool                            msi_en;
+
+#define EXTRA_CAPS_SD_SDR50            (1 << 0)
+#define EXTRA_CAPS_SD_SDR104           (1 << 1)
+#define EXTRA_CAPS_SD_DDR50            (1 << 2)
+#define EXTRA_CAPS_MMC_HSDDR           (1 << 3)
+#define EXTRA_CAPS_MMC_HS200           (1 << 4)
+#define EXTRA_CAPS_MMC_8BIT            (1 << 5)
+       u32                             extra_caps;
+
+#define IC_VER_A                       0
+#define IC_VER_B                       1
+#define IC_VER_C                       2
+#define IC_VER_D                       3
+       u8                              ic_version;
+
+       u8                              sd30_drive_sel_1v8;
+       u8                              sd30_drive_sel_3v3;
+       u8                              card_drive_sel;
+#define ASPM_L1_EN                     0x02
+       u8                              aspm_en;
+       bool                            aspm_enabled;
+
+#define PCR_MS_PMOS                    (1 << 0)
+#define PCR_REVERSE_SOCKET             (1 << 1)
+       u32                             flags;
+
+       u32                             tx_initial_phase;
+       u32                             rx_initial_phase;
+
+       const u32                       *sd_pull_ctl_enable_tbl;
+       const u32                       *sd_pull_ctl_disable_tbl;
+       const u32                       *ms_pull_ctl_enable_tbl;
+       const u32                       *ms_pull_ctl_disable_tbl;
+
+       const struct pcr_ops            *ops;
+       enum PDEV_STAT                  state;
+
+       u16                             reg_pm_ctrl3;
+
+       int                             num_slots;
+       struct rtsx_slot                *slots;
+
+       u8                              dma_error_count;
+};
+
+#define PID_524A       0x524A
+#define PID_5249               0x5249
+#define PID_5250               0x5250
+#define PID_525A       0x525A
+
+#define CHK_PCI_PID(pcr, pid)          ((pcr)->pci->device == (pid))
+#define PCI_VID(pcr)                   ((pcr)->pci->vendor)
+#define PCI_PID(pcr)                   ((pcr)->pci->device)
+#define is_version(pcr, pid, ver)                              \
+       (CHK_PCI_PID(pcr, pid) && (pcr)->ic_version == (ver))
+#define pcr_dbg(pcr, fmt, arg...)                              \
+       dev_dbg(&(pcr)->pci->dev, fmt, ##arg)
+
+#define SDR104_PHASE(val)              ((val) & 0xFF)
+#define SDR50_PHASE(val)               (((val) >> 8) & 0xFF)
+#define DDR50_PHASE(val)               (((val) >> 16) & 0xFF)
+#define SDR104_TX_PHASE(pcr)           SDR104_PHASE((pcr)->tx_initial_phase)
+#define SDR50_TX_PHASE(pcr)            SDR50_PHASE((pcr)->tx_initial_phase)
+#define DDR50_TX_PHASE(pcr)            DDR50_PHASE((pcr)->tx_initial_phase)
+#define SDR104_RX_PHASE(pcr)           SDR104_PHASE((pcr)->rx_initial_phase)
+#define SDR50_RX_PHASE(pcr)            SDR50_PHASE((pcr)->rx_initial_phase)
+#define DDR50_RX_PHASE(pcr)            DDR50_PHASE((pcr)->rx_initial_phase)
+#define SET_CLOCK_PHASE(sdr104, sdr50, ddr50)  \
+                               (((ddr50) << 16) | ((sdr50) << 8) | (sdr104))
+
+void rtsx_pci_start_run(struct rtsx_pcr *pcr);
+int rtsx_pci_write_register(struct rtsx_pcr *pcr, u16 addr, u8 mask, u8 data);
+int rtsx_pci_read_register(struct rtsx_pcr *pcr, u16 addr, u8 *data);
+int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val);
+int rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val);
+void rtsx_pci_stop_cmd(struct rtsx_pcr *pcr);
+void rtsx_pci_add_cmd(struct rtsx_pcr *pcr,
+               u8 cmd_type, u16 reg_addr, u8 mask, u8 data);
+void rtsx_pci_send_cmd_no_wait(struct rtsx_pcr *pcr);
+int rtsx_pci_send_cmd(struct rtsx_pcr *pcr, int timeout);
+int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read, int timeout);
+int rtsx_pci_dma_map_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read);
+void rtsx_pci_dma_unmap_sg(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int num_sg, bool read);
+int rtsx_pci_dma_transfer(struct rtsx_pcr *pcr, struct scatterlist *sglist,
+               int count, bool read, int timeout);
+int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_write_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len);
+int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_pull_ctl_disable(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_card_exclusive_check(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage);
+unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
+void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
+
+static inline u8 *rtsx_pci_get_cmd_data(struct rtsx_pcr *pcr)
+{
+       return (u8 *)(pcr->host_cmds_ptr);
+}
+
+static inline int rtsx_pci_update_cfg_byte(struct rtsx_pcr *pcr, int addr,
+               u8 mask, u8 append)
+{
+       int err;
+       u8 val;
+
+       err = pci_read_config_byte(pcr->pci, addr, &val);
+       if (err < 0)
+               return err;
+       return pci_write_config_byte(pcr->pci, addr, (val & mask) | append);
+}
+
+static inline void rtsx_pci_write_be32(struct rtsx_pcr *pcr, u16 reg, u32 val)
+{
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg,     0xFF, val >> 24);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 1, 0xFF, val >> 16);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 2, 0xFF, val >> 8);
+       rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, reg + 3, 0xFF, val);
+}
+
+static inline int rtsx_pci_update_phy(struct rtsx_pcr *pcr, u8 addr,
+       u16 mask, u16 append)
+{
+       int err;
+       u16 val;
+
+       err = rtsx_pci_read_phy_register(pcr, addr, &val);
+       if (err < 0)
+               return err;
+
+       return rtsx_pci_write_phy_register(pcr, addr, (val & mask) | append);
+}
+
+#endif
diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h
new file mode 100644 (file)
index 0000000..c446e4f
--- /dev/null
@@ -0,0 +1,628 @@
+/* Driver for Realtek RTS5139 USB card reader
+ *
+ * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author:
+ *   Roger Tseng <rogerable@realtek.com>
+ */
+
+#ifndef __RTSX_USB_H
+#define __RTSX_USB_H
+
+#include <linux/usb.h>
+
+/* related module names */
+#define RTSX_USB_SD_CARD       0
+#define RTSX_USB_MS_CARD       1
+
+/* endpoint numbers */
+#define EP_BULK_OUT            1
+#define EP_BULK_IN             2
+#define EP_INTR_IN             3
+
+/* USB vendor requests */
+#define RTSX_USB_REQ_REG_OP    0x00
+#define RTSX_USB_REQ_POLL      0x02
+
+/* miscellaneous parameters */
+#define MIN_DIV_N              60
+#define MAX_DIV_N              120
+
+#define MAX_PHASE              15
+#define RX_TUNING_CNT          3
+
+#define QFN24                  0
+#define LQFP48                 1
+#define CHECK_PKG(ucr, pkg)    ((ucr)->package == (pkg))
+
+/* data structures */
+struct rtsx_ucr {
+       u16                     vendor_id;
+       u16                     product_id;
+
+       int                     package;
+       u8                      ic_version;
+       bool                    is_rts5179;
+
+       unsigned int            cur_clk;
+
+       u8                      *cmd_buf;
+       unsigned int            cmd_idx;
+       u8                      *rsp_buf;
+
+       struct usb_device       *pusb_dev;
+       struct usb_interface    *pusb_intf;
+       struct usb_sg_request   current_sg;
+       unsigned char           *iobuf;
+       dma_addr_t              iobuf_dma;
+
+       struct timer_list       sg_timer;
+       struct mutex            dev_mutex;
+};
+
+/* buffer size */
+#define IOBUF_SIZE             1024
+
+/* prototypes of exported functions */
+extern int rtsx_usb_get_card_status(struct rtsx_ucr *ucr, u16 *status);
+
+extern int rtsx_usb_read_register(struct rtsx_ucr *ucr, u16 addr, u8 *data);
+extern int rtsx_usb_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+               u8 data);
+
+extern int rtsx_usb_ep0_write_register(struct rtsx_ucr *ucr, u16 addr, u8 mask,
+               u8 data);
+extern int rtsx_usb_ep0_read_register(struct rtsx_ucr *ucr, u16 addr,
+               u8 *data);
+
+extern void rtsx_usb_add_cmd(struct rtsx_ucr *ucr, u8 cmd_type,
+               u16 reg_addr, u8 mask, u8 data);
+extern int rtsx_usb_send_cmd(struct rtsx_ucr *ucr, u8 flag, int timeout);
+extern int rtsx_usb_get_rsp(struct rtsx_ucr *ucr, int rsp_len, int timeout);
+extern int rtsx_usb_transfer_data(struct rtsx_ucr *ucr, unsigned int pipe,
+                             void *buf, unsigned int len, int use_sg,
+                             unsigned int *act_len, int timeout);
+
+extern int rtsx_usb_read_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_write_ppbuf(struct rtsx_ucr *ucr, u8 *buf, int buf_len);
+extern int rtsx_usb_switch_clock(struct rtsx_ucr *ucr, unsigned int card_clock,
+               u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
+extern int rtsx_usb_card_exclusive_check(struct rtsx_ucr *ucr, int card);
+
+/* card status */
+#define SD_CD          0x01
+#define MS_CD          0x02
+#define XD_CD          0x04
+#define CD_MASK                (SD_CD | MS_CD | XD_CD)
+#define SD_WP          0x08
+
+/* reader command field offset & parameters */
+#define READ_REG_CMD           0
+#define WRITE_REG_CMD          1
+#define CHECK_REG_CMD          2
+
+#define PACKET_TYPE            4
+#define CNT_H                  5
+#define CNT_L                  6
+#define STAGE_FLAG             7
+#define CMD_OFFSET             8
+#define SEQ_WRITE_DATA_OFFSET  12
+
+#define BATCH_CMD              0
+#define SEQ_READ               1
+#define SEQ_WRITE              2
+
+#define STAGE_R                        0x01
+#define STAGE_DI               0x02
+#define STAGE_DO               0x04
+#define STAGE_MS_STATUS                0x08
+#define STAGE_XD_STATUS                0x10
+#define MODE_C                 0x00
+#define MODE_CR                        (STAGE_R)
+#define MODE_CDIR              (STAGE_R | STAGE_DI)
+#define MODE_CDOR              (STAGE_R | STAGE_DO)
+
+#define EP0_OP_SHIFT           14
+#define EP0_READ_REG_CMD       2
+#define EP0_WRITE_REG_CMD      3
+
+#define rtsx_usb_cmd_hdr_tag(ucr)              \
+       do {                                    \
+               ucr->cmd_buf[0] = 'R';          \
+               ucr->cmd_buf[1] = 'T';          \
+               ucr->cmd_buf[2] = 'C';          \
+               ucr->cmd_buf[3] = 'R';          \
+       } while (0)
+
+static inline void rtsx_usb_init_cmd(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_cmd_hdr_tag(ucr);
+       ucr->cmd_idx = 0;
+       ucr->cmd_buf[PACKET_TYPE] = BATCH_CMD;
+}
+
+/* internal register address */
+#define FPDCTL                         0xFC00
+#define SSC_DIV_N_0                    0xFC07
+#define SSC_CTL1                       0xFC09
+#define SSC_CTL2                       0xFC0A
+#define CFG_MODE                       0xFC0E
+#define CFG_MODE_1                     0xFC0F
+#define RCCTL                          0xFC14
+#define SOF_WDOG                       0xFC28
+#define SYS_DUMMY0                     0xFC30
+
+#define MS_BLKEND                      0xFD30
+#define MS_READ_START                  0xFD31
+#define MS_READ_COUNT                  0xFD32
+#define MS_WRITE_START                 0xFD33
+#define MS_WRITE_COUNT                 0xFD34
+#define MS_COMMAND                     0xFD35
+#define MS_OLD_BLOCK_0                 0xFD36
+#define MS_OLD_BLOCK_1                 0xFD37
+#define MS_NEW_BLOCK_0                 0xFD38
+#define MS_NEW_BLOCK_1                 0xFD39
+#define MS_LOG_BLOCK_0                 0xFD3A
+#define MS_LOG_BLOCK_1                 0xFD3B
+#define MS_BUS_WIDTH                   0xFD3C
+#define MS_PAGE_START                  0xFD3D
+#define MS_PAGE_LENGTH                 0xFD3E
+#define MS_CFG                         0xFD40
+#define MS_TPC                         0xFD41
+#define MS_TRANS_CFG                   0xFD42
+#define MS_TRANSFER                    0xFD43
+#define MS_INT_REG                     0xFD44
+#define MS_BYTE_CNT                    0xFD45
+#define MS_SECTOR_CNT_L                        0xFD46
+#define MS_SECTOR_CNT_H                        0xFD47
+#define MS_DBUS_H                      0xFD48
+
+#define CARD_DMA1_CTL                  0xFD5C
+#define CARD_PULL_CTL1                 0xFD60
+#define CARD_PULL_CTL2                 0xFD61
+#define CARD_PULL_CTL3                 0xFD62
+#define CARD_PULL_CTL4                 0xFD63
+#define CARD_PULL_CTL5                 0xFD64
+#define CARD_PULL_CTL6                 0xFD65
+#define CARD_EXIST                     0xFD6F
+#define CARD_INT_PEND                  0xFD71
+
+#define LDO_POWER_CFG                  0xFD7B
+
+#define SD_CFG1                                0xFDA0
+#define SD_CFG2                                0xFDA1
+#define SD_CFG3                                0xFDA2
+#define SD_STAT1                       0xFDA3
+#define SD_STAT2                       0xFDA4
+#define SD_BUS_STAT                    0xFDA5
+#define SD_PAD_CTL                     0xFDA6
+#define SD_SAMPLE_POINT_CTL            0xFDA7
+#define SD_PUSH_POINT_CTL              0xFDA8
+#define SD_CMD0                                0xFDA9
+#define SD_CMD1                                0xFDAA
+#define SD_CMD2                                0xFDAB
+#define SD_CMD3                                0xFDAC
+#define SD_CMD4                                0xFDAD
+#define SD_CMD5                                0xFDAE
+#define SD_BYTE_CNT_L                  0xFDAF
+#define SD_BYTE_CNT_H                  0xFDB0
+#define SD_BLOCK_CNT_L                 0xFDB1
+#define SD_BLOCK_CNT_H                 0xFDB2
+#define SD_TRANSFER                    0xFDB3
+#define SD_CMD_STATE                   0xFDB5
+#define SD_DATA_STATE                  0xFDB6
+#define SD_VPCLK0_CTL                  0xFC2A
+#define SD_VPCLK1_CTL                  0xFC2B
+#define SD_DCMPS0_CTL                  0xFC2C
+#define SD_DCMPS1_CTL                  0xFC2D
+
+#define CARD_DMA1_CTL                  0xFD5C
+
+#define HW_VERSION                     0xFC01
+
+#define SSC_CLK_FPGA_SEL               0xFC02
+#define CLK_DIV                                0xFC03
+#define SFSM_ED                                0xFC04
+
+#define CD_DEGLITCH_WIDTH              0xFC20
+#define CD_DEGLITCH_EN                 0xFC21
+#define AUTO_DELINK_EN                 0xFC23
+
+#define FPGA_PULL_CTL                  0xFC1D
+#define CARD_CLK_SOURCE                        0xFC2E
+
+#define CARD_SHARE_MODE                        0xFD51
+#define CARD_DRIVE_SEL                 0xFD52
+#define CARD_STOP                      0xFD53
+#define CARD_OE                                0xFD54
+#define CARD_AUTO_BLINK                        0xFD55
+#define CARD_GPIO                      0xFD56
+#define SD30_DRIVE_SEL                 0xFD57
+
+#define CARD_DATA_SOURCE               0xFD5D
+#define CARD_SELECT                    0xFD5E
+
+#define CARD_CLK_EN                    0xFD79
+#define CARD_PWR_CTL                   0xFD7A
+
+#define OCPCTL                         0xFD80
+#define OCPPARA1                       0xFD81
+#define OCPPARA2                       0xFD82
+#define OCPSTAT                                0xFD83
+
+#define HS_USB_STAT                    0xFE01
+#define HS_VCONTROL                    0xFE26
+#define HS_VSTAIN                      0xFE27
+#define HS_VLOADM                      0xFE28
+#define HS_VSTAOUT                     0xFE29
+
+#define MC_IRQ                         0xFF00
+#define MC_IRQEN                       0xFF01
+#define MC_FIFO_CTL                    0xFF02
+#define MC_FIFO_BC0                    0xFF03
+#define MC_FIFO_BC1                    0xFF04
+#define MC_FIFO_STAT                   0xFF05
+#define MC_FIFO_MODE                   0xFF06
+#define MC_FIFO_RD_PTR0                        0xFF07
+#define MC_FIFO_RD_PTR1                        0xFF08
+#define MC_DMA_CTL                     0xFF10
+#define MC_DMA_TC0                     0xFF11
+#define MC_DMA_TC1                     0xFF12
+#define MC_DMA_TC2                     0xFF13
+#define MC_DMA_TC3                     0xFF14
+#define MC_DMA_RST                     0xFF15
+
+#define RBUF_SIZE_MASK                 0xFBFF
+#define RBUF_BASE                      0xF000
+#define PPBUF_BASE1                    0xF800
+#define PPBUF_BASE2                    0xFA00
+
+/* internal register value macros */
+#define POWER_OFF                      0x03
+#define PARTIAL_POWER_ON               0x02
+#define POWER_ON                       0x00
+#define POWER_MASK                     0x03
+#define LDO3318_PWR_MASK               0x0C
+#define LDO_ON                         0x00
+#define LDO_SUSPEND                    0x08
+#define LDO_OFF                                0x0C
+#define DV3318_AUTO_PWR_OFF            0x10
+#define FORCE_LDO_POWERB               0x60
+
+/* LDO_POWER_CFG */
+#define TUNE_SD18_MASK                 0x1C
+#define TUNE_SD18_1V7                  0x00
+#define TUNE_SD18_1V8                  (0x01 << 2)
+#define TUNE_SD18_1V9                  (0x02 << 2)
+#define TUNE_SD18_2V0                  (0x03 << 2)
+#define TUNE_SD18_2V7                  (0x04 << 2)
+#define TUNE_SD18_2V8                  (0x05 << 2)
+#define TUNE_SD18_2V9                  (0x06 << 2)
+#define TUNE_SD18_3V3                  (0x07 << 2)
+
+/* CLK_DIV */
+#define CLK_CHANGE                     0x80
+#define CLK_DIV_1                      0x00
+#define CLK_DIV_2                      0x01
+#define CLK_DIV_4                      0x02
+#define CLK_DIV_8                      0x03
+
+#define SSC_POWER_MASK                 0x01
+#define SSC_POWER_DOWN                 0x01
+#define SSC_POWER_ON                   0x00
+
+#define FPGA_VER                       0x80
+#define HW_VER_MASK                    0x0F
+
+#define EXTEND_DMA1_ASYNC_SIGNAL       0x02
+
+/* CFG_MODE*/
+#define XTAL_FREE                      0x80
+#define CLK_MODE_MASK                  0x03
+#define CLK_MODE_12M_XTAL              0x00
+#define CLK_MODE_NON_XTAL              0x01
+#define CLK_MODE_24M_OSC               0x02
+#define CLK_MODE_48M_OSC               0x03
+
+/* CFG_MODE_1*/
+#define RTS5179                                0x02
+
+#define NYET_EN                                0x01
+#define NYET_MSAK                      0x01
+
+#define SD30_DRIVE_MASK                        0x07
+#define SD20_DRIVE_MASK                        0x03
+
+#define DISABLE_SD_CD                  0x08
+#define DISABLE_MS_CD                  0x10
+#define DISABLE_XD_CD                  0x20
+#define SD_CD_DEGLITCH_EN              0x01
+#define MS_CD_DEGLITCH_EN              0x02
+#define XD_CD_DEGLITCH_EN              0x04
+
+#define        CARD_SHARE_LQFP48               0x04
+#define        CARD_SHARE_QFN24                0x00
+#define CARD_SHARE_LQFP_SEL            0x04
+#define        CARD_SHARE_XD                   0x00
+#define        CARD_SHARE_SD                   0x01
+#define        CARD_SHARE_MS                   0x02
+#define CARD_SHARE_MASK                        0x03
+
+
+/* SD30_DRIVE_SEL */
+#define DRIVER_TYPE_A                  0x05
+#define DRIVER_TYPE_B                  0x03
+#define DRIVER_TYPE_C                  0x02
+#define DRIVER_TYPE_D                  0x01
+
+/* SD_BUS_STAT */
+#define        SD_CLK_TOGGLE_EN                0x80
+#define        SD_CLK_FORCE_STOP               0x40
+#define        SD_DAT3_STATUS                  0x10
+#define        SD_DAT2_STATUS                  0x08
+#define        SD_DAT1_STATUS                  0x04
+#define        SD_DAT0_STATUS                  0x02
+#define        SD_CMD_STATUS                   0x01
+
+/* SD_PAD_CTL */
+#define        SD_IO_USING_1V8                 0x80
+#define        SD_IO_USING_3V3                 0x7F
+#define        TYPE_A_DRIVING                  0x00
+#define        TYPE_B_DRIVING                  0x01
+#define        TYPE_C_DRIVING                  0x02
+#define        TYPE_D_DRIVING                  0x03
+
+/* CARD_CLK_EN */
+#define SD_CLK_EN                      0x04
+#define MS_CLK_EN                      0x08
+
+/* CARD_SELECT */
+#define SD_MOD_SEL                     2
+#define MS_MOD_SEL                     3
+
+/* CARD_SHARE_MODE */
+#define        CARD_SHARE_LQFP48               0x04
+#define        CARD_SHARE_QFN24                0x00
+#define CARD_SHARE_LQFP_SEL            0x04
+#define        CARD_SHARE_XD                   0x00
+#define        CARD_SHARE_SD                   0x01
+#define        CARD_SHARE_MS                   0x02
+#define CARD_SHARE_MASK                        0x03
+
+/* SSC_CTL1 */
+#define SSC_RSTB                       0x80
+#define SSC_8X_EN                      0x40
+#define SSC_FIX_FRAC                   0x20
+#define SSC_SEL_1M                     0x00
+#define SSC_SEL_2M                     0x08
+#define SSC_SEL_4M                     0x10
+#define SSC_SEL_8M                     0x18
+
+/* SSC_CTL2 */
+#define SSC_DEPTH_MASK                 0x03
+#define SSC_DEPTH_DISALBE              0x00
+#define SSC_DEPTH_2M                   0x01
+#define SSC_DEPTH_1M                   0x02
+#define SSC_DEPTH_512K                 0x03
+
+/* SD_VPCLK0_CTL */
+#define PHASE_CHANGE                   0x80
+#define PHASE_NOT_RESET                        0x40
+
+/* SD_TRANSFER */
+#define        SD_TRANSFER_START               0x80
+#define        SD_TRANSFER_END                 0x40
+#define SD_STAT_IDLE                   0x20
+#define        SD_TRANSFER_ERR                 0x10
+#define        SD_TM_NORMAL_WRITE              0x00
+#define        SD_TM_AUTO_WRITE_3              0x01
+#define        SD_TM_AUTO_WRITE_4              0x02
+#define        SD_TM_AUTO_READ_3               0x05
+#define        SD_TM_AUTO_READ_4               0x06
+#define        SD_TM_CMD_RSP                   0x08
+#define        SD_TM_AUTO_WRITE_1              0x09
+#define        SD_TM_AUTO_WRITE_2              0x0A
+#define        SD_TM_NORMAL_READ               0x0C
+#define        SD_TM_AUTO_READ_1               0x0D
+#define        SD_TM_AUTO_READ_2               0x0E
+#define        SD_TM_AUTO_TUNING               0x0F
+
+/* SD_CFG1 */
+#define SD_CLK_DIVIDE_0                        0x00
+#define        SD_CLK_DIVIDE_256               0xC0
+#define        SD_CLK_DIVIDE_128               0x80
+#define SD_CLK_DIVIDE_MASK             0xC0
+#define        SD_BUS_WIDTH_1BIT               0x00
+#define        SD_BUS_WIDTH_4BIT               0x01
+#define        SD_BUS_WIDTH_8BIT               0x02
+#define        SD_ASYNC_FIFO_RST               0x10
+#define        SD_20_MODE                      0x00
+#define        SD_DDR_MODE                     0x04
+#define        SD_30_MODE                      0x08
+
+/* SD_CFG2 */
+#define        SD_CALCULATE_CRC7               0x00
+#define        SD_NO_CALCULATE_CRC7            0x80
+#define        SD_CHECK_CRC16                  0x00
+#define        SD_NO_CHECK_CRC16               0x40
+#define SD_WAIT_CRC_TO_EN              0x20
+#define        SD_WAIT_BUSY_END                0x08
+#define        SD_NO_WAIT_BUSY_END             0x00
+#define        SD_CHECK_CRC7                   0x00
+#define        SD_NO_CHECK_CRC7                0x04
+#define        SD_RSP_LEN_0                    0x00
+#define        SD_RSP_LEN_6                    0x01
+#define        SD_RSP_LEN_17                   0x02
+#define        SD_RSP_TYPE_R0                  0x04
+#define        SD_RSP_TYPE_R1                  0x01
+#define        SD_RSP_TYPE_R1b                 0x09
+#define        SD_RSP_TYPE_R2                  0x02
+#define        SD_RSP_TYPE_R3                  0x05
+#define        SD_RSP_TYPE_R4                  0x05
+#define        SD_RSP_TYPE_R5                  0x01
+#define        SD_RSP_TYPE_R6                  0x01
+#define        SD_RSP_TYPE_R7                  0x01
+
+/* SD_STAT1 */
+#define        SD_CRC7_ERR                     0x80
+#define        SD_CRC16_ERR                    0x40
+#define        SD_CRC_WRITE_ERR                0x20
+#define        SD_CRC_WRITE_ERR_MASK           0x1C
+#define        GET_CRC_TIME_OUT                0x02
+#define        SD_TUNING_COMPARE_ERR           0x01
+
+/* SD_DATA_STATE */
+#define SD_DATA_IDLE                   0x80
+
+/* CARD_DATA_SOURCE */
+#define PINGPONG_BUFFER                        0x01
+#define RING_BUFFER                    0x00
+
+/* CARD_OE */
+#define SD_OUTPUT_EN                   0x04
+#define MS_OUTPUT_EN                   0x08
+
+/* CARD_STOP */
+#define SD_STOP                                0x04
+#define MS_STOP                                0x08
+#define SD_CLR_ERR                     0x40
+#define MS_CLR_ERR                     0x80
+
+/* CARD_CLK_SOURCE */
+#define CRC_FIX_CLK                    (0x00 << 0)
+#define CRC_VAR_CLK0                   (0x01 << 0)
+#define CRC_VAR_CLK1                   (0x02 << 0)
+#define SD30_FIX_CLK                   (0x00 << 2)
+#define SD30_VAR_CLK0                  (0x01 << 2)
+#define SD30_VAR_CLK1                  (0x02 << 2)
+#define SAMPLE_FIX_CLK                 (0x00 << 4)
+#define SAMPLE_VAR_CLK0                        (0x01 << 4)
+#define SAMPLE_VAR_CLK1                        (0x02 << 4)
+
+/* SD_SAMPLE_POINT_CTL */
+#define        DDR_FIX_RX_DAT                  0x00
+#define        DDR_VAR_RX_DAT                  0x80
+#define        DDR_FIX_RX_DAT_EDGE             0x00
+#define        DDR_FIX_RX_DAT_14_DELAY         0x40
+#define        DDR_FIX_RX_CMD                  0x00
+#define        DDR_VAR_RX_CMD                  0x20
+#define        DDR_FIX_RX_CMD_POS_EDGE         0x00
+#define        DDR_FIX_RX_CMD_14_DELAY         0x10
+#define        SD20_RX_POS_EDGE                0x00
+#define        SD20_RX_14_DELAY                0x08
+#define SD20_RX_SEL_MASK               0x08
+
+/* SD_PUSH_POINT_CTL */
+#define        DDR_FIX_TX_CMD_DAT              0x00
+#define        DDR_VAR_TX_CMD_DAT              0x80
+#define        DDR_FIX_TX_DAT_14_TSU           0x00
+#define        DDR_FIX_TX_DAT_12_TSU           0x40
+#define        DDR_FIX_TX_CMD_NEG_EDGE         0x00
+#define        DDR_FIX_TX_CMD_14_AHEAD         0x20
+#define        SD20_TX_NEG_EDGE                0x00
+#define        SD20_TX_14_AHEAD                0x10
+#define SD20_TX_SEL_MASK               0x10
+#define        DDR_VAR_SDCLK_POL_SWAP          0x01
+
+/* MS_CFG */
+#define        SAMPLE_TIME_RISING              0x00
+#define        SAMPLE_TIME_FALLING             0x80
+#define        PUSH_TIME_DEFAULT               0x00
+#define        PUSH_TIME_ODD                   0x40
+#define        NO_EXTEND_TOGGLE                0x00
+#define        EXTEND_TOGGLE_CHK               0x20
+#define        MS_BUS_WIDTH_1                  0x00
+#define        MS_BUS_WIDTH_4                  0x10
+#define        MS_BUS_WIDTH_8                  0x18
+#define        MS_2K_SECTOR_MODE               0x04
+#define        MS_512_SECTOR_MODE              0x00
+#define        MS_TOGGLE_TIMEOUT_EN            0x00
+#define        MS_TOGGLE_TIMEOUT_DISEN         0x01
+#define MS_NO_CHECK_INT                        0x02
+
+/* MS_TRANS_CFG */
+#define        WAIT_INT                        0x80
+#define        NO_WAIT_INT                     0x00
+#define        NO_AUTO_READ_INT_REG            0x00
+#define        AUTO_READ_INT_REG               0x40
+#define        MS_CRC16_ERR                    0x20
+#define        MS_RDY_TIMEOUT                  0x10
+#define        MS_INT_CMDNK                    0x08
+#define        MS_INT_BREQ                     0x04
+#define        MS_INT_ERR                      0x02
+#define        MS_INT_CED                      0x01
+
+/* MS_TRANSFER */
+#define        MS_TRANSFER_START               0x80
+#define        MS_TRANSFER_END                 0x40
+#define        MS_TRANSFER_ERR                 0x20
+#define        MS_BS_STATE                     0x10
+#define        MS_TM_READ_BYTES                0x00
+#define        MS_TM_NORMAL_READ               0x01
+#define        MS_TM_WRITE_BYTES               0x04
+#define        MS_TM_NORMAL_WRITE              0x05
+#define        MS_TM_AUTO_READ                 0x08
+#define        MS_TM_AUTO_WRITE                0x0C
+#define MS_TM_SET_CMD                  0x06
+#define MS_TM_COPY_PAGE                        0x07
+#define MS_TM_MULTI_READ               0x02
+#define MS_TM_MULTI_WRITE              0x03
+
+/* MC_FIFO_CTL */
+#define FIFO_FLUSH                     0x01
+
+/* MC_DMA_RST */
+#define DMA_RESET  0x01
+
+/* MC_DMA_CTL */
+#define DMA_TC_EQ_0                    0x80
+#define DMA_DIR_TO_CARD                        0x00
+#define DMA_DIR_FROM_CARD              0x02
+#define DMA_EN                         0x01
+#define DMA_128                                (0 << 2)
+#define DMA_256                                (1 << 2)
+#define DMA_512                                (2 << 2)
+#define DMA_1024                       (3 << 2)
+#define DMA_PACK_SIZE_MASK             0x0C
+
+/* CARD_INT_PEND */
+#define XD_INT                         0x10
+#define MS_INT                         0x08
+#define SD_INT                         0x04
+
+/* LED operations*/
+static inline int rtsx_usb_turn_on_led(struct rtsx_ucr *ucr)
+{
+       return  rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x02);
+}
+
+static inline int rtsx_usb_turn_off_led(struct rtsx_ucr *ucr)
+{
+       return rtsx_usb_ep0_write_register(ucr, CARD_GPIO, 0x03, 0x03);
+}
+
+/* HW error clearing */
+static inline void rtsx_usb_clear_fsm_err(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_ep0_write_register(ucr, SFSM_ED, 0xf8, 0xf8);
+}
+
+static inline void rtsx_usb_clear_dma_err(struct rtsx_ucr *ucr)
+{
+       rtsx_usb_ep0_write_register(ucr, MC_FIFO_CTL,
+                       FIFO_FLUSH, FIFO_FLUSH);
+       rtsx_usb_ep0_write_register(ucr, MC_DMA_RST, DMA_RESET, DMA_RESET);
+}
+#endif /* __RTS51139_H */