--- zzzz-none-000/linux-3.10.107/drivers/mfd/rtsx_pcr.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/drivers/mfd/rtsx_pcr.c 2021-02-04 17:41:59.000000000 +0000 @@ -1,6 +1,6 @@ /* Driver for Realtek PCI-Express card reader * - * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. + * 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 @@ -17,7 +17,6 @@ * * Author: * Wei WANG - * No. 450, Shenhu Road, Suzhou Industry Park, Suzhou, China */ #include @@ -51,17 +50,34 @@ }, }; -static DEFINE_PCI_DEVICE_TABLE(rtsx_pci_ids) = { +static const struct pci_device_id rtsx_pci_ids[] = { { PCI_DEVICE(0x10EC, 0x5209), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5229), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5289), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5227), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x522A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { PCI_DEVICE(0x10EC, 0x5249), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5287), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5286), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x524A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x525A), PCI_CLASS_OTHERS << 16, 0xFF0000 }, { 0, } }; MODULE_DEVICE_TABLE(pci, rtsx_pci_ids); +static inline void rtsx_pci_enable_aspm(struct rtsx_pcr *pcr) +{ + rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL, + 0xFC, pcr->aspm_en); +} + +static inline void rtsx_pci_disable_aspm(struct rtsx_pcr *pcr) +{ + rtsx_pci_update_cfg_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL, + 0xFC, 0); +} + void rtsx_pci_start_run(struct rtsx_pcr *pcr) { /* If pci device removed, don't queue idle work any more */ @@ -72,6 +88,9 @@ pcr->state = PDEV_STAT_RUN; if (pcr->ops->enable_auto_blink) pcr->ops->enable_auto_blink(pcr); + + if (pcr->aspm_en) + rtsx_pci_disable_aspm(pcr); } mod_delayed_work(system_wq, &pcr->idle_work, msecs_to_jiffies(200)); @@ -126,7 +145,7 @@ } EXPORT_SYMBOL_GPL(rtsx_pci_read_register); -int rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val) +int __rtsx_pci_write_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 val) { int err, i, finished = 0; u8 tmp; @@ -158,9 +177,17 @@ 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 __rtsx_pci_read_phy_register(struct rtsx_pcr *pcr, u8 addr, u16 *val) { int err, i, finished = 0; u16 data; @@ -206,6 +233,14 @@ 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) @@ -282,8 +317,7 @@ timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { - dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n", - __func__, __LINE__); + pcr_dbg(pcr, "Timeout (%s %d)\n", __func__, __LINE__); err = -ETIMEDOUT; goto finish_send_cmd; } @@ -319,8 +353,7 @@ u64 val; u8 option = SG_VALID | SG_TRANS_DATA; - dev_dbg(&(pcr->pci->dev), "DMA addr: 0x%x, Len: 0x%x\n", - (unsigned int)addr, len); + pcr_dbg(pcr, "DMA addr: 0x%x, Len: 0x%x\n", (unsigned int)addr, len); if (end) option |= SG_END; @@ -333,40 +366,64 @@ int rtsx_pci_transfer_data(struct rtsx_pcr *pcr, struct scatterlist *sglist, int num_sg, bool read, int timeout) { - struct completion trans_done; - u8 dir; - int err = 0, i, count; - long timeleft; - unsigned long flags; - struct scatterlist *sg; - enum dma_data_direction dma_dir; - u32 val; - dma_addr_t addr; - unsigned int len; + 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); - dev_dbg(&(pcr->pci->dev), "--> %s: num_sg = %d\n", __func__, num_sg); + 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; - /* don't transfer data during abort processing */ if (pcr->remove_pci) return -EINVAL; if ((sglist == NULL) || (num_sg <= 0)) return -EINVAL; - if (read) { - dir = DEVICE_TO_HOST; - dma_dir = DMA_FROM_DEVICE; - } else { - dir = HOST_TO_DEVICE; - dma_dir = DMA_TO_DEVICE; - } + 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; - count = dma_map_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); - if (count < 1) { - dev_err(&(pcr->pci->dev), "scatterlist map failed\n"); + if ((sglist == NULL) || (count < 1)) return -EINVAL; - } - dev_dbg(&(pcr->pci->dev), "DMA mapping count: %d\n", count); val = ((u32)(dir & 0x01) << 29) | TRIG_DMA | ADMA_MODE; pcr->sgi = 0; @@ -389,19 +446,16 @@ timeleft = wait_for_completion_interruptible_timeout( &trans_done, msecs_to_jiffies(timeout)); if (timeleft <= 0) { - dev_dbg(&(pcr->pci->dev), "Timeout (%s %d)\n", - __func__, __LINE__); + 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 = -EINVAL; else if (pcr->trans_result == TRANS_NO_DEVICE) err = -ENODEV; - spin_unlock_irqrestore(&pcr->lock, flags); out: @@ -409,8 +463,6 @@ pcr->done = NULL; spin_unlock_irqrestore(&pcr->lock, flags); - dma_unmap_sg(&(pcr->pci->dev), sglist, num_sg, dma_dir); - if ((err < 0) && (err != -ENODEV)) rtsx_pci_stop_cmd(pcr); @@ -419,7 +471,7 @@ return err; } -EXPORT_SYMBOL_GPL(rtsx_pci_transfer_data); +EXPORT_SYMBOL_GPL(rtsx_pci_dma_transfer); int rtsx_pci_read_ppbuf(struct rtsx_pcr *pcr, u8 *buf, int buf_len) { @@ -510,8 +562,6 @@ static int rtsx_pci_set_pull_ctl(struct rtsx_pcr *pcr, const u32 *tbl) { - int err; - rtsx_pci_init_cmd(pcr); while (*tbl & 0xFFFF0000) { @@ -520,11 +570,7 @@ tbl++; } - err = rtsx_pci_send_cmd(pcr, 100); - if (err < 0) - return err; - - return 0; + return rtsx_pci_send_cmd(pcr, 100); } int rtsx_pci_card_pull_ctl_enable(struct rtsx_pcr *pcr, int card) @@ -568,7 +614,7 @@ /* Enable Bus Interrupt */ rtsx_pci_writel(pcr, RTSX_BIER, pcr->bier); - dev_dbg(&(pcr->pci->dev), "RTSX_BIER: 0x%08x\n", pcr->bier); + pcr_dbg(pcr, "RTSX_BIER: 0x%08x\n", pcr->bier); } static inline u8 double_ssc_depth(u8 depth) @@ -614,14 +660,13 @@ return err; card_clock /= 1000000; - dev_dbg(&(pcr->pci->dev), "Switch card clock to %dMHz\n", card_clock); + pcr_dbg(pcr, "Switch card clock to %dMHz\n", card_clock); clk = card_clock; if (!initial_mode && double_clk) clk = card_clock * 2; - dev_dbg(&(pcr->pci->dev), - "Internal SSC clock: %dMHz (cur_clock = %d)\n", - clk, pcr->cur_clock); + pcr_dbg(pcr, "Internal SSC clock: %dMHz (cur_clock = %d)\n", + clk, pcr->cur_clock); if (clk == pcr->cur_clock) return 0; @@ -650,14 +695,14 @@ } div++; } - dev_dbg(&(pcr->pci->dev), "n = %d, div = %d\n", n, 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); - dev_dbg(&(pcr->pci->dev), "ssc_depth = %d\n", ssc_depth); + pcr_dbg(pcr, "ssc_depth = %d\n", ssc_depth); rtsx_pci_init_cmd(pcr); rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, CLK_CTL, @@ -716,7 +761,7 @@ [RTSX_MS_CARD] = MS_EXIST }; - if (!pcr->ms_pmos) { + if (!(pcr->flags & PCR_MS_PMOS)) { /* When using single PMOS, accessing card is not permitted * if the existing card is not the designated one. */ @@ -779,13 +824,13 @@ dwork = to_delayed_work(work); pcr = container_of(dwork, struct rtsx_pcr, carddet_work); - dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__); + 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); - dev_dbg(&(pcr->pci->dev), "irq_status: 0x%08x\n", irq_status); + pcr_dbg(pcr, "irq_status: 0x%08x\n", irq_status); irq_status &= CARD_EXIST; card_inserted = pcr->card_inserted & irq_status; @@ -796,9 +841,8 @@ spin_unlock_irqrestore(&pcr->lock, flags); if (card_inserted || card_removed) { - dev_dbg(&(pcr->pci->dev), - "card_inserted: 0x%x, card_removed: 0x%x\n", - 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); @@ -906,7 +950,7 @@ struct delayed_work *dwork = to_delayed_work(work); struct rtsx_pcr *pcr = container_of(dwork, struct rtsx_pcr, idle_work); - dev_dbg(&(pcr->pci->dev), "--> %s\n", __func__); + pcr_dbg(pcr, "--> %s\n", __func__); mutex_lock(&pcr->pcr_mutex); @@ -917,13 +961,34 @@ if (pcr->ops->turn_off_led) pcr->ops->turn_off_led(pcr); + if (pcr->aspm_en) + rtsx_pci_enable_aspm(pcr); + mutex_unlock(&pcr->pcr_mutex); } +#ifdef CONFIG_PM +static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) +{ + if (pcr->ops->turn_off_led) + pcr->ops->turn_off_led(pcr); + + rtsx_pci_writel(pcr, RTSX_BIER, 0); + pcr->bier = 0; + + rtsx_pci_write_register(pcr, PETXCFG, 0x08, 0x08); + rtsx_pci_write_register(pcr, HOST_SLEEP_STATE, 0x03, pm_state); + + if (pcr->ops->force_power_down) + pcr->ops->force_power_down(pcr, pm_state); +} +#endif + static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) { int err; + pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP); rtsx_pci_writel(pcr, RTSX_HCBAR, pcr->host_cmds_addr); rtsx_pci_enable_bus_int(pcr); @@ -936,6 +1001,7 @@ /* 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) @@ -950,13 +1016,11 @@ 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 ASPM state to default value */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, ASPM_FORCE_CTL, 0x3F, 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, SD30_DRIVE_SEL, - 0x07, DRIVER_TYPE_D); + 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); @@ -981,15 +1045,13 @@ * 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); - /* Force CLKREQ# PIN to drive 0 to request clock */ - rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, PETXCFG, 0x08, 0x08); err = rtsx_pci_send_cmd(pcr, 100); if (err < 0) return err; /* Enable clk_request_n to enable clock power management */ - rtsx_pci_write_config_byte(pcr, 0x81, 1); + 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); @@ -1035,12 +1097,32 @@ 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; } - dev_dbg(&(pcr->pci->dev), "PID: 0x%04x, IC version: 0x%02x\n", + 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), @@ -1048,6 +1130,18 @@ 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) { @@ -1064,7 +1158,7 @@ struct rtsx_pcr *pcr; struct pcr_handle *handle; u32 base, len; - int ret, i; + int ret, i, bar = 0; dev_dbg(&(pcidev->dev), ": Realtek PCI-E Card Reader found at %s [%04x:%04x] (rev %x)\n", @@ -1109,12 +1203,14 @@ pcr->pci = pcidev; dev_set_drvdata(&pcidev->dev, handle); - len = pci_resource_len(pcidev, 0); - base = pci_resource_start(pcidev, 0); + 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_host; + goto free_handle; } pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev), @@ -1174,8 +1270,6 @@ pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr); unmap: iounmap(pcr->remap_addr); -free_host: - dev_set_drvdata(&pcidev->dev, NULL); free_handle: kfree(handle); free_pcr: @@ -1213,7 +1307,6 @@ pci_disable_msi(pcr->pci); iounmap(pcr->remap_addr); - dev_set_drvdata(&pcidev->dev, NULL); pci_release_regions(pcidev); pci_disable_device(pcidev); @@ -1236,7 +1329,6 @@ { struct pcr_handle *handle; struct rtsx_pcr *pcr; - int ret = 0; dev_dbg(&(pcidev->dev), "--> %s\n", __func__); @@ -1248,14 +1340,7 @@ mutex_lock(&pcr->pcr_mutex); - 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, 0x02); + rtsx_pci_power_off(pcr, HOST_ENTER_S3); pci_save_state(pcidev); pci_enable_wake(pcidev, pci_choose_state(pcidev, state), 0); @@ -1263,7 +1348,7 @@ pci_set_power_state(pcidev, pci_choose_state(pcidev, state)); mutex_unlock(&pcr->pcr_mutex); - return ret; + return 0; } static int rtsx_pci_resume(struct pci_dev *pcidev) @@ -1301,10 +1386,25 @@ 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); +} + #else /* CONFIG_PM */ #define rtsx_pci_suspend NULL #define rtsx_pci_resume NULL +#define rtsx_pci_shutdown NULL #endif /* CONFIG_PM */ @@ -1315,6 +1415,7 @@ .remove = rtsx_pci_remove, .suspend = rtsx_pci_suspend, .resume = rtsx_pci_resume, + .shutdown = rtsx_pci_shutdown, }; module_pci_driver(rtsx_pci_driver);