Merge tag 'mfd-next-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Jan 2018 18:59:24 +0000 (10:59 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 29 Jan 2018 18:59:24 +0000 (10:59 -0800)
Pull MFD updates from Lee Jones:
 "New Drivers:
   - Add support for RAVE Supervisory Processor

  Moved drivers:
   - Move Realtek Card Reader Driver to Misc

  New Device Support:
   - Add support for Pinctrl to axp20x

  New Functionality:
   - Add resume support to atmel-flexcom

  Fix-ups:
   - Split MFD (mfd) and userspace handlers (platform) in cros_ec
   - Fix trivial (whitespace, spelling) issue(s) in pcf50633-core
   - Clean-up error handling in ab8500-debugfs
   - General tidying up in tmio_core
   - Kconfig fix-ups for qcom-pm8xxx
   - Licensing changes (SPDX) to stm32-lptimer, stm32-timers
   - Device Tree fixups in mc13xxx
   - Simplify/remove unused code in cros_ec_spi, axp20x, ti_am335x_tscadc,
     kempld-core, intel_soc_pmic_core.c, ab8500-debugfs"

* tag 'mfd-next-4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd: (32 commits)
  mfd: lpc_ich: Do not touch SPI-NOR write protection bit on Apollo Lake
  mfd: axp20x: Mark axp288 CHRG_BAK_CTRL register volatile
  mfd: ab8500: Introduce DEFINE_SHOW_ATTRIBUTE() macro
  atmel_flexcom: Support resuming after a chip reset
  mfd: Remove duplicate includes
  dt-bindings: mfd: mc13xxx: Add the unit address to sysled
  mfd: stm32: Adopt SPDX identifier
  mfd: axp20x: Add pinctrl cell for AXP813
  mfd: pm8xxx: Make elegible for COMPILE_TEST
  mfd: kempld-core: Use resource_size function on resource object
  mfd: tmio: Move register macros to tmio_core.c
  mfd: cros ec: spi: Simplify delay handling between SPI messages
  mfd: palmas: Assign the right powerhold mask for tps65917
  mfd: ab8500-debugfs: Use common error handling code in ab8500_print_modem_registers()
  mfd: ti_am335x_tscadc: Remove redundant assignment to node
  mfd: pcf50633: Fix spelling mistake: 'Falied' -> 'Failed'
  dt-bindings: watchdog: Add bindings for RAVE SP watchdog driver
  watchdog: Add RAVE SP watchdog driver
  mfd: Add driver for RAVE Supervisory Processor
  serdev: Introduce devm_serdev_device_open()
  ...

1  2 
drivers/mfd/cros_ec_spi.c
drivers/misc/cardreader/rtsx_pcr.c
include/linux/rtsx_pci.h
include/linux/serdev.h

@@@ -377,8 -376,8 +376,9 @@@ static int cros_ec_pkt_xfer_spi(struct 
        u8 *ptr;
        u8 *rx_buf;
        u8 sum;
 +      u8 rx_byte;
        int ret = 0, final_ret;
+       unsigned long delay;
  
        len = cros_ec_prepare_tx(ec_dev, ec_msg);
        dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
@@@ -506,9 -504,9 +502,10 @@@ static int cros_ec_cmd_xfer_spi(struct 
        int i, len;
        u8 *ptr;
        u8 *rx_buf;
 +      u8 rx_byte;
        int sum;
        int ret = 0, final_ret;
+       unsigned long delay;
  
        len = cros_ec_prepare_tx(ec_dev, ec_msg);
        dev_dbg(ec_dev->dev, "prepared, len=%d\n", len);
index 0000000,5345170..fd09b09
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1690 +1,1693 @@@
+ /* 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 },
+       { PCI_DEVICE(0x10EC, 0x5260), 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)
+ {
+       if (pcr->ops->stop_cmd)
+               return pcr->ops->stop_cmd(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(SSC_CLOCK_STABLE_WAIT);
+       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);
+ }
+ void rtsx_pci_process_ocp(struct rtsx_pcr *pcr)
+ {
+       if (pcr->ops->process_ocp)
+               pcr->ops->process_ocp(pcr);
+ }
+ int rtsx_pci_process_ocp_interrupt(struct rtsx_pcr *pcr)
+ {
+       if (pcr->option.ocp_en)
+               rtsx_pci_process_ocp(pcr);
+       return 0;
+ }
+ 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_OC_INT)
+               rtsx_pci_process_ocp_interrupt(pcr);
+       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
+ void rtsx_pci_enable_ocp(struct rtsx_pcr *pcr)
+ {
+       u8 val = SD_OCP_INT_EN | SD_DETECT_EN;
+       if (pcr->ops->enable_ocp)
+               pcr->ops->enable_ocp(pcr);
+       else
+               rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val);
+ }
+ void rtsx_pci_disable_ocp(struct rtsx_pcr *pcr)
+ {
+       u8 mask = SD_OCP_INT_EN | SD_DETECT_EN;
+       if (pcr->ops->disable_ocp)
+               pcr->ops->disable_ocp(pcr);
+       else
+               rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
+ }
+ void rtsx_pci_init_ocp(struct rtsx_pcr *pcr)
+ {
+       if (pcr->ops->init_ocp) {
+               pcr->ops->init_ocp(pcr);
+       } else {
+               struct rtsx_cr_option *option = &(pcr->option);
+               if (option->ocp_en) {
+                       u8 val = option->sd_400mA_ocp_thd;
+                       rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0);
+                       rtsx_pci_write_register(pcr, REG_OCPPARA1,
+                               SD_OCP_TIME_MASK, SD_OCP_TIME_800);
+                       rtsx_pci_write_register(pcr, REG_OCPPARA2,
+                               SD_OCP_THD_MASK, val);
+                       rtsx_pci_write_register(pcr, REG_OCPGLITCH,
+                               SD_OCP_GLITCH_MASK, pcr->hw_param.ocp_glitch);
+                       rtsx_pci_enable_ocp(pcr);
+               } else {
+                       /* OC power down */
+                       rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN,
+                               OC_POWER_DOWN);
+               }
+       }
+ }
+ int rtsx_pci_get_ocpstat(struct rtsx_pcr *pcr, u8 *val)
+ {
+       if (pcr->ops->get_ocpstat)
+               return pcr->ops->get_ocpstat(pcr, val);
+       else
+               return rtsx_pci_read_register(pcr, REG_OCPSTAT, val);
+ }
+ void rtsx_pci_clear_ocpstat(struct rtsx_pcr *pcr)
+ {
+       if (pcr->ops->clear_ocpstat) {
+               pcr->ops->clear_ocpstat(pcr);
+       } else {
+               u8 mask = SD_OCP_INT_CLR | SD_OC_CLR;
+               u8 val = SD_OCP_INT_CLR | SD_OC_CLR;
+               rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val);
+               rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0);
+       }
+ }
+ int rtsx_sd_power_off_card3v3(struct rtsx_pcr *pcr)
+ {
+       rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN |
+               MS_CLK_EN | SD40_CLK_EN, 0);
+       rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0);
+       rtsx_pci_card_power_off(pcr, RTSX_SD_CARD);
+       msleep(50);
+       rtsx_pci_card_pull_ctl_disable(pcr, RTSX_SD_CARD);
+       return 0;
+ }
+ int rtsx_ms_power_off_card3v3(struct rtsx_pcr *pcr)
+ {
+       rtsx_pci_write_register(pcr, CARD_CLK_EN, SD_CLK_EN |
+               MS_CLK_EN | SD40_CLK_EN, 0);
+       rtsx_pci_card_pull_ctl_disable(pcr, RTSX_MS_CARD);
+       rtsx_pci_write_register(pcr, CARD_OE, MS_OUTPUT_EN, 0);
+       rtsx_pci_card_power_off(pcr, RTSX_MS_CARD);
+       return 0;
+ }
+ 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:
+       case PID_5260:
+               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;
+       case 0x5260:
+               rts5260_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");
index 0000000,a44670e..478acf6
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1367 +1,1367 @@@
 -      DEV_ASPM_DISABLE = 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/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_MODE_SELECT_MASK         0x0C
+ #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   SD30_CLK_END_EN             0x10
+ #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 REG_SD_STOP_SDCLK_CFG         0xFDB8
+ #define   SD30_CLK_STOP_CFG_EN                0x04
+ #define   SD30_CLK_STOP_CFG1          0x02
+ #define   SD30_CLK_STOP_CFG0          0x01
+ #define REG_PRE_RW_MODE                       0xFD70
+ #define EN_INFINITE_MODE              0x01
+ #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   SD40_CLK_EN         0x10
+ #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              0x03
+ #define   OC_POWER_DOWN                       0x02
+ #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   LED_SHINE_MASK              0x08
+ #define   LED_SHINE_EN                        0x08
+ #define   LED_SHINE_DISABLE           0x00
+ #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 EFUSE_CTL                     0xFC30
+ #define EFUSE_ADD                     0xFC31
+ #define SYS_VER                               0xFC32
+ #define EFUSE_DATAL                   0xFC34
+ #define EFUSE_DATAH                   0xFC35
+ #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   U_AUTO_DMA_EN_MASK          0x20
+ #define   U_AUTO_DMA_DISABLE          0x00
+ #define   RB_FLUSH                    0x80
+ #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   OBFF_EN_MASK                        0x03
+ #define   OBFF_DISABLE                        0x00
+ #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   CLK_PM_EN                   0x01
+ #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   AUX_CLK_ACTIVE_SEL_MASK     0x01
+ #define   MAC_CKSW_DONE                       0x00
+ #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   IC_VERSION_MASK             0x0F
+ #define REG_VREF                      0xFE97
+ #define   PWD_SUSPND_EN                       0x10
+ #define RTS5260_DMA_RST_CTL_0         0xFEBF
+ #define   RTS5260_DMA_RST             0x80
+ #define   RTS5260_ADMA3_RST           0x40
+ #define AUTOLOAD_CFG_BASE             0xFF00
+ #define RELINK_TIME_MASK              0x01
+ #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   DV331812_MASK                       0x70
+ #define   DV331812_33                 0x70
+ #define   DV331812_17                 0x30
+ #define LDO_CONFIG2                   0xFF71
+ #define   LDO_D3318_MASK              0x07
+ #define   LDO_D3318_33V                       0x07
+ #define   LDO_D3318_18V                       0x02
+ #define   DV331812_VDD1                       0x04
+ #define   DV331812_POWERON            0x08
+ #define   DV331812_POWEROFF           0x00
+ #define LDO_VCC_CFG0                  0xFF72
+ #define   LDO_VCC_LMTVTH_MASK         0x30
+ #define   LDO_VCC_LMTVTH_2A           0x10
+ /*RTS5260*/
+ #define   RTS5260_DVCC_TUNE_MASK      0x70
+ #define   RTS5260_DVCC_33             0x70
+ #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
+ /*RTS5260*/
+ #define         LDO_POW_SDVDD1_MASK           0x08
+ #define         LDO_POW_SDVDD1_ON             0x08
+ #define         LDO_POW_SDVDD1_OFF            0x00
+ #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
+ #define RTS5260_AUTOLOAD_CFG4         0xFF7F
+ #define   RTS5260_MIMO_DISABLE                0x8A
+ #define RTS5260_REG_GPIO_CTL0         0xFC1A
+ #define   RTS5260_REG_GPIO_MASK               0x01
+ #define   RTS5260_REG_GPIO_ON         0x01
+ #define   RTS5260_REG_GPIO_OFF                0x00
+ #define PWR_GLOBAL_CTRL                       0xF200
+ #define PCIE_L1_2_EN                  0x0C
+ #define PCIE_L1_1_EN                  0x0A
+ #define PCIE_L1_0_EN                  0x09
+ #define PWR_FE_CTL                    0xF201
+ #define PCIE_L1_2_PD_FE_EN            0x0C
+ #define PCIE_L1_1_PD_FE_EN            0x0A
+ #define PCIE_L1_0_PD_FE_EN            0x09
+ #define CFG_PCIE_APHY_OFF_0           0xF204
+ #define CFG_PCIE_APHY_OFF_0_DEFAULT   0xBF
+ #define CFG_PCIE_APHY_OFF_1           0xF205
+ #define CFG_PCIE_APHY_OFF_1_DEFAULT   0xFF
+ #define CFG_PCIE_APHY_OFF_2           0xF206
+ #define CFG_PCIE_APHY_OFF_2_DEFAULT   0x01
+ #define CFG_PCIE_APHY_OFF_3           0xF207
+ #define CFG_PCIE_APHY_OFF_3_DEFAULT   0x00
+ #define CFG_L1_0_PCIE_MAC_RET_VALUE   0xF20C
+ #define CFG_L1_0_PCIE_DPHY_RET_VALUE  0xF20E
+ #define CFG_L1_0_SYS_RET_VALUE                0xF210
+ #define CFG_L1_0_CRC_MISC_RET_VALUE   0xF212
+ #define CFG_L1_0_CRC_SD30_RET_VALUE   0xF214
+ #define CFG_L1_0_CRC_SD40_RET_VALUE   0xF216
+ #define CFG_LP_FPWM_VALUE             0xF219
+ #define CFG_LP_FPWM_VALUE_DEFAULT     0x18
+ #define PWC_CDR                               0xF253
+ #define PWC_CDR_DEFAULT                       0x03
+ #define CFG_L1_0_RET_VALUE_DEFAULT    0x1B
+ #define CFG_L1_0_CRC_MISC_RET_VALUE_DEFAULT   0x0C
+ /* OCPCTL */
+ #define SD_DETECT_EN                  0x08
+ #define SD_OCP_INT_EN                 0x04
+ #define SD_OCP_INT_CLR                        0x02
+ #define SD_OC_CLR                     0x01
+ #define SDVIO_DETECT_EN                       (1 << 7)
+ #define SDVIO_OCP_INT_EN              (1 << 6)
+ #define SDVIO_OCP_INT_CLR             (1 << 5)
+ #define SDVIO_OC_CLR                  (1 << 4)
+ /* OCPSTAT */
+ #define SD_OCP_DETECT                 0x08
+ #define SD_OC_NOW                     0x04
+ #define SD_OC_EVER                    0x02
+ #define SDVIO_OC_NOW                  (1 << 6)
+ #define SDVIO_OC_EVER                 (1 << 5)
+ #define REG_OCPCTL                    0xFD6A
+ #define REG_OCPSTAT                   0xFD6E
+ #define REG_OCPGLITCH                 0xFD6C
+ #define REG_OCPPARA1                  0xFD6B
+ #define REG_OCPPARA2                  0xFD6D
+ /* rts5260 DV3318 OCP-related registers */
+ #define REG_DV3318_OCPCTL             0xFD89
+ #define DV3318_OCP_TIME_MASK  0xF0
+ #define DV3318_DETECT_EN              0x08
+ #define DV3318_OCP_INT_EN             0x04
+ #define DV3318_OCP_INT_CLR            0x02
+ #define DV3318_OCP_CLR                        0x01
+ #define REG_DV3318_OCPSTAT            0xFD8A
+ #define DV3318_OCP_GlITCH_TIME_MASK   0xF0
+ #define DV3318_OCP_DETECT             0x08
+ #define DV3318_OCP_NOW                        0x04
+ #define DV3318_OCP_EVER                       0x02
+ #define SD_OCP_GLITCH_MASK            0x0F
+ /* OCPPARA1 */
+ #define SDVIO_OCP_TIME_60             0x00
+ #define SDVIO_OCP_TIME_100            0x10
+ #define SDVIO_OCP_TIME_200            0x20
+ #define SDVIO_OCP_TIME_400            0x30
+ #define SDVIO_OCP_TIME_600            0x40
+ #define SDVIO_OCP_TIME_800            0x50
+ #define SDVIO_OCP_TIME_1100           0x60
+ #define SDVIO_OCP_TIME_MASK           0x70
+ #define SD_OCP_TIME_60                        0x00
+ #define SD_OCP_TIME_100                       0x01
+ #define SD_OCP_TIME_200                       0x02
+ #define SD_OCP_TIME_400                       0x03
+ #define SD_OCP_TIME_600                       0x04
+ #define SD_OCP_TIME_800                       0x05
+ #define SD_OCP_TIME_1100              0x06
+ #define SD_OCP_TIME_MASK              0x07
+ /* OCPPARA2 */
+ #define SDVIO_OCP_THD_190             0x00
+ #define SDVIO_OCP_THD_250             0x10
+ #define SDVIO_OCP_THD_320             0x20
+ #define SDVIO_OCP_THD_380             0x30
+ #define SDVIO_OCP_THD_440             0x40
+ #define SDVIO_OCP_THD_500             0x50
+ #define SDVIO_OCP_THD_570             0x60
+ #define SDVIO_OCP_THD_630             0x70
+ #define SDVIO_OCP_THD_MASK            0x70
+ #define SD_OCP_THD_450                        0x00
+ #define SD_OCP_THD_550                        0x01
+ #define SD_OCP_THD_650                        0x02
+ #define SD_OCP_THD_750                        0x03
+ #define SD_OCP_THD_850                        0x04
+ #define SD_OCP_THD_950                        0x05
+ #define SD_OCP_THD_1050                       0x06
+ #define SD_OCP_THD_1150                       0x07
+ #define SD_OCP_THD_MASK                       0x07
+ #define SDVIO_OCP_GLITCH_MASK         0xF0
+ #define SDVIO_OCP_GLITCH_NONE         0x00
+ #define SDVIO_OCP_GLITCH_50U          0x10
+ #define SDVIO_OCP_GLITCH_100U         0x20
+ #define SDVIO_OCP_GLITCH_200U         0x30
+ #define SDVIO_OCP_GLITCH_600U         0x40
+ #define SDVIO_OCP_GLITCH_800U         0x50
+ #define SDVIO_OCP_GLITCH_1M           0x60
+ #define SDVIO_OCP_GLITCH_2M           0x70
+ #define SDVIO_OCP_GLITCH_3M           0x80
+ #define SDVIO_OCP_GLITCH_4M           0x90
+ #define SDVIO_OCP_GLIVCH_5M           0xA0
+ #define SDVIO_OCP_GLITCH_6M           0xB0
+ #define SDVIO_OCP_GLITCH_7M           0xC0
+ #define SDVIO_OCP_GLITCH_8M           0xD0
+ #define SDVIO_OCP_GLITCH_9M           0xE0
+ #define SDVIO_OCP_GLITCH_10M          0xF0
+ #define SD_OCP_GLITCH_MASK            0x0F
+ #define SD_OCP_GLITCH_NONE            0x00
+ #define SD_OCP_GLITCH_50U             0x01
+ #define SD_OCP_GLITCH_100U            0x02
+ #define SD_OCP_GLITCH_200U            0x03
+ #define SD_OCP_GLITCH_600U            0x04
+ #define SD_OCP_GLITCH_800U            0x05
+ #define SD_OCP_GLITCH_1M              0x06
+ #define SD_OCP_GLITCH_2M              0x07
+ #define SD_OCP_GLITCH_3M              0x08
+ #define SD_OCP_GLITCH_4M              0x09
+ #define SD_OCP_GLIVCH_5M              0x0A
+ #define SD_OCP_GLITCH_6M              0x0B
+ #define SD_OCP_GLITCH_7M              0x0C
+ #define SD_OCP_GLITCH_8M              0x0D
+ #define SD_OCP_GLITCH_9M              0x0E
+ #define SD_OCP_GLITCH_10M             0x0F
+ /* 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_ASPM_SETTING_5260         0x178
+ #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            (*stop_cmd)(struct rtsx_pcr *pcr);
+       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);
+       void (*enable_ocp)(struct rtsx_pcr *pcr);
+       void (*disable_ocp)(struct rtsx_pcr *pcr);
+       void (*init_ocp)(struct rtsx_pcr *pcr);
+       void (*process_ocp)(struct rtsx_pcr *pcr);
+       int (*get_ocpstat)(struct rtsx_pcr *pcr, u8 *val);
+       void (*clear_ocpstat)(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
+  * @ocp_en: enable ocp flag
+  * @sd_400mA_ocp_thd: 400mA ocp thd
+  * @sd_800mA_ocp_thd: 800mA ocp thd
+  */
+ 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;
+       bool ocp_en;
+       u8 sd_400mA_ocp_thd;
+       u8 sd_800mA_ocp_thd;
+ };
+ /*
+  * struct rtsx_hw_param  - card reader hardware param
+  * @interrupt_en: indicate which interrutp enable
+  * @ocp_glitch: ocp glitch time
+  */
+ struct rtsx_hw_param {
+       u32 interrupt_en;
+       u8 ocp_glitch;
+ };
+ #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;
+       struct rtsx_hw_param hw_param;
+       /* 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;
+       u8                      ocp_stat;
+       u8                      ocp_stat2;
+ };
+ #define PID_524A      0x524A
+ #define PID_5249      0x5249
+ #define PID_5250      0x5250
+ #define PID_525A      0x525A
+ #define PID_5260      0x5260
+ #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
Simple merge