From f70575805708cabdedea7498aaa3f710fde4d920 Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Wed, 31 Jan 2024 03:29:01 +0000 Subject: [PATCH] add lvds1024*800 --- kernel/drivers/misc/cardreader/rtsx_pcr.c | 295 ++++++++++++++++++++++++++++++++++------------------------- 1 files changed, 170 insertions(+), 125 deletions(-) diff --git a/kernel/drivers/misc/cardreader/rtsx_pcr.c b/kernel/drivers/misc/cardreader/rtsx_pcr.c index 3eb3c23..358b000 100644 --- a/kernel/drivers/misc/cardreader/rtsx_pcr.c +++ b/kernel/drivers/misc/cardreader/rtsx_pcr.c @@ -1,19 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-or-later /* 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> @@ -34,6 +22,8 @@ #include <asm/unaligned.h> #include "rtsx_pcr.h" +#include "rts5261.h" +#include "rts5228.h" static bool msi_en = true; module_param(msi_en, bool, S_IRUGO | S_IWUSR); @@ -45,9 +35,6 @@ 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, }, }; @@ -63,21 +50,17 @@ { 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 }, + { PCI_DEVICE(0x10EC, 0x5261), PCI_CLASS_OTHERS << 16, 0xFF0000 }, + { PCI_DEVICE(0x10EC, 0x5228), 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); + pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_ASPMC, 0); } static int rtsx_comm_set_ltr_latency(struct rtsx_pcr *pcr, u32 latency) @@ -98,32 +81,17 @@ 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); + 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); - } + pcie_capability_clear_and_set_word(pcr->pci, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_ASPMC, + enable ? pcr->aspm_en : 0); pcr->aspm_enabled = enable; } @@ -167,10 +135,7 @@ static 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); + rtsx_comm_pm_full_on(pcr); } void rtsx_pci_start_run(struct rtsx_pcr *pcr) @@ -243,16 +208,10 @@ 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; + rtsx_pci_write_register(pcr, PHYDATA0, 0xFF, (u8)val); + rtsx_pci_write_register(pcr, PHYDATA1, 0xFF, (u8)(val >> 8)); + rtsx_pci_write_register(pcr, PHYADDR, 0xFF, addr); + rtsx_pci_write_register(pcr, PHYRWCTL, 0xFF, 0x81); for (i = 0; i < 100000; i++) { err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); @@ -284,16 +243,10 @@ { int err, i, finished = 0; u16 data; - u8 *ptr, tmp; + u8 tmp, val1, val2; - 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; + rtsx_pci_write_register(pcr, PHYADDR, 0xFF, addr); + rtsx_pci_write_register(pcr, PHYRWCTL, 0xFF, 0x80); for (i = 0; i < 100000; i++) { err = rtsx_pci_read_register(pcr, PHYRWCTL, &tmp); @@ -309,17 +262,9 @@ 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]; + rtsx_pci_read_register(pcr, PHYDATA0, &val1); + rtsx_pci_read_register(pcr, PHYDATA1, &val2); + data = val1 | (val2 << 8); if (val) *val = data; @@ -453,8 +398,16 @@ if (end) option |= RTSX_SG_END; - val = ((u64)addr << 32) | ((u64)len << 12) | option; + if ((PCI_PID(pcr) == PID_5261) || (PCI_PID(pcr) == PID_5228)) { + if (len > 0xFFFF) + val = ((u64)addr << 32) | (((u64)len & 0xFFFF) << 16) + | (((u64)len >> 16) << 6) | option; + else + val = ((u64)addr << 32) | ((u64)len << 16) | option; + } else { + val = ((u64)addr << 32) | ((u64)len << 12) | option; + } put_unaligned_le64(val, ptr); pcr->sgi++; } @@ -699,14 +652,16 @@ 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; + struct rtsx_hw_param *hw_param = &pcr->hw_param; + + pcr->bier = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN | SD_INT_EN + | hw_param->interrupt_en; if (pcr->num_slots > 1) pcr->bier |= MS_INT_EN; @@ -746,6 +701,13 @@ [RTSX_SSC_DEPTH_500K] = SSC_DEPTH_500K, [RTSX_SSC_DEPTH_250K] = SSC_DEPTH_250K, }; + + if (PCI_PID(pcr) == PID_5261) + return rts5261_pci_switch_clock(pcr, card_clock, + ssc_depth, initial_mode, double_clk, vpclk); + if (PCI_PID(pcr) == PID_5228) + return rts5228_pci_switch_clock(pcr, card_clock, + ssc_depth, initial_mode, double_clk, vpclk); if (initial_mode) { /* We use 250k(around) here, in initial stage */ @@ -972,8 +934,19 @@ static void rtsx_pci_process_ocp(struct rtsx_pcr *pcr) { - if (pcr->ops->process_ocp) + if (pcr->ops->process_ocp) { pcr->ops->process_ocp(pcr); + } else { + if (!pcr->option.ocp_en) + return; + rtsx_pci_get_ocpstat(pcr, &pcr->ocp_stat); + if (pcr->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) { + rtsx_pci_card_power_off(pcr, RTSX_SD_CARD); + rtsx_pci_write_register(pcr, CARD_OE, SD_OUTPUT_EN, 0); + rtsx_pci_clear_ocpstat(pcr); + pcr->ocp_stat = 0; + } + } } static int rtsx_pci_process_ocp_interrupt(struct rtsx_pcr *pcr) @@ -1042,7 +1015,7 @@ } } - if (pcr->card_inserted || pcr->card_removed) + if ((pcr->card_inserted || pcr->card_removed) && !(int_reg & SD_OC_INT)) schedule_delayed_work(&pcr->carddet_work, msecs_to_jiffies(200)); @@ -1099,10 +1072,7 @@ static 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); + rtsx_comm_pm_power_saving(pcr); } static void rtsx_pci_idle_work(struct work_struct *work) @@ -1126,8 +1096,21 @@ mutex_unlock(&pcr->pcr_mutex); } -#ifdef CONFIG_PM -static void rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) +static void rtsx_base_force_power_down(struct rtsx_pcr *pcr, u8 pm_state) +{ + /* Set relink_time to 0 */ + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 1, MASK_8_BIT_DEF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 2, MASK_8_BIT_DEF, 0); + rtsx_pci_write_register(pcr, AUTOLOAD_CFG_BASE + 3, + RELINK_TIME_MASK, 0); + + rtsx_pci_write_register(pcr, pcr->reg_pm_ctrl3, + D3_DELINK_MODE_EN, D3_DELINK_MODE_EN); + + rtsx_pci_write_register(pcr, FPDCTL, ALL_POWER_DOWN, ALL_POWER_DOWN); +} + +static void __maybe_unused rtsx_pci_power_off(struct rtsx_pcr *pcr, u8 pm_state) { if (pcr->ops->turn_off_led) pcr->ops->turn_off_led(pcr); @@ -1140,17 +1123,20 @@ if (pcr->ops->force_power_down) pcr->ops->force_power_down(pcr, pm_state); + else + rtsx_base_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) + if (pcr->ops->enable_ocp) { pcr->ops->enable_ocp(pcr); - else + } else { + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0); rtsx_pci_write_register(pcr, REG_OCPCTL, 0xFF, val); + } } @@ -1158,10 +1144,13 @@ { u8 mask = SD_OCP_INT_EN | SD_DETECT_EN; - if (pcr->ops->disable_ocp) + if (pcr->ops->disable_ocp) { pcr->ops->disable_ocp(pcr); - else + } else { rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); + rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, + OC_POWER_DOWN); + } } void rtsx_pci_init_ocp(struct rtsx_pcr *pcr) @@ -1172,7 +1161,7 @@ struct rtsx_cr_option *option = &(pcr->option); if (option->ocp_en) { - u8 val = option->sd_400mA_ocp_thd; + u8 val = option->sd_800mA_ocp_thd; rtsx_pci_write_register(pcr, FPDCTL, OC_POWER_DOWN, 0); rtsx_pci_write_register(pcr, REG_OCPPARA1, @@ -1182,10 +1171,6 @@ 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); } } } @@ -1207,8 +1192,39 @@ u8 val = SD_OCP_INT_CLR | SD_OC_CLR; rtsx_pci_write_register(pcr, REG_OCPCTL, mask, val); + udelay(100); rtsx_pci_write_register(pcr, REG_OCPCTL, mask, 0); } +} + +void rtsx_pci_enable_oobs_polling(struct rtsx_pcr *pcr) +{ + u16 val; + + if ((PCI_PID(pcr) != PID_525A) && (PCI_PID(pcr) != PID_5260)) { + rtsx_pci_read_phy_register(pcr, 0x01, &val); + val |= 1<<9; + rtsx_pci_write_phy_register(pcr, 0x01, val); + } + rtsx_pci_write_register(pcr, REG_CFG_OOBS_OFF_TIMER, 0xFF, 0x32); + rtsx_pci_write_register(pcr, REG_CFG_OOBS_ON_TIMER, 0xFF, 0x05); + rtsx_pci_write_register(pcr, REG_CFG_VCM_ON_TIMER, 0xFF, 0x83); + rtsx_pci_write_register(pcr, REG_CFG_OOBS_POLLING, 0xFF, 0xDE); + +} + +void rtsx_pci_disable_oobs_polling(struct rtsx_pcr *pcr) +{ + u16 val; + + if ((PCI_PID(pcr) != PID_525A) && (PCI_PID(pcr) != PID_5260)) { + rtsx_pci_read_phy_register(pcr, 0x01, &val); + val &= ~(1<<9); + rtsx_pci_write_phy_register(pcr, 0x01, val); + } + rtsx_pci_write_register(pcr, REG_CFG_VCM_ON_TIMER, 0xFF, 0x03); + rtsx_pci_write_register(pcr, REG_CFG_OOBS_POLLING, 0xFF, 0x00); + } int rtsx_sd_power_off_card3v3(struct rtsx_pcr *pcr) @@ -1216,7 +1232,6 @@ 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); @@ -1241,15 +1256,27 @@ static int rtsx_pci_init_hw(struct rtsx_pcr *pcr) { + struct pci_dev *pdev = pcr->pci; int err; - pcr->pcie_cap = pci_find_capability(pcr->pci, PCI_CAP_ID_EXP); + if (PCI_PID(pcr) == PID_5228) + rtsx_pci_write_register(pcr, RTS5228_LDO1_CFG1, RTS5228_LDO1_SR_TIME_MASK, + RTS5228_LDO1_SR_0_5); + 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 (PCI_PID(pcr) == PID_5261) { + /* Gating real mcu clock */ + err = rtsx_pci_write_register(pcr, RTS5261_FW_CFG1, + RTS5261_MCU_CLOCK_GATING, 0); + err = rtsx_pci_write_register(pcr, RTS5261_REG_FPDCTL, + SSC_POWER_DOWN, 0); + } else { + err = rtsx_pci_write_register(pcr, FPDCTL, SSC_POWER_DOWN, 0); + } if (err < 0) return err; @@ -1279,7 +1306,15 @@ /* 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); + if (PCI_PID(pcr) == PID_5261) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, + RTS5261_SSC_DEPTH_2M); + else if (PCI_PID(pcr) == PID_5228) + rtsx_pci_add_cmd(pcr, WRITE_REG_CMD, SSC_CTL2, 0xFF, + RTS5228_SSC_DEPTH_2M); + else + 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 */ @@ -1310,16 +1345,22 @@ case PID_524A: case PID_525A: case PID_5260: + case PID_5261: + case PID_5228: rtsx_pci_write_register(pcr, PM_CLK_FORCE_CTL, 1, 1); break; default: break; } + /*init ocp*/ + rtsx_pci_init_ocp(pcr); + /* Enable clk_request_n to enable clock power management */ - rtsx_pci_write_config_byte(pcr, pcr->pcie_cap + PCI_EXP_LNKCTL + 1, 1); + pcie_capability_write_word(pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_CLKREQ_EN); /* Enter L1 when host tx idle */ - rtsx_pci_write_config_byte(pcr, 0x70F, 0x5B); + pci_write_config_byte(pdev, 0x70F, 0x5B); if (pcr->ops->extra_init_hw) { err = pcr->ops->extra_init_hw(pcr); @@ -1386,8 +1427,17 @@ case 0x5286: rtl8402_init_params(pcr); break; + case 0x5260: rts5260_init_params(pcr); + break; + + case 0x5261: + rts5261_init_params(pcr); + break; + + case 0x5228: + rts5228_init_params(pcr); break; } @@ -1476,10 +1526,10 @@ bar = 1; len = pci_resource_len(pcidev, bar); base = pci_resource_start(pcidev, bar); - pcr->remap_addr = ioremap_nocache(base, len); + pcr->remap_addr = ioremap(base, len); if (!pcr->remap_addr) { ret = -ENOMEM; - goto free_handle; + goto free_idr; } pcr->rtsx_resv_buf = dma_alloc_coherent(&(pcidev->dev), @@ -1541,6 +1591,10 @@ pcr->rtsx_resv_buf, pcr->rtsx_resv_buf_addr); unmap: iounmap(pcr->remap_addr); +free_idr: + spin_lock(&rtsx_pci_lock); + idr_remove(&rtsx_pci_idr, pcr->id); + spin_unlock(&rtsx_pci_lock); free_handle: kfree(handle); free_pcr: @@ -1594,10 +1648,9 @@ 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) +static int __maybe_unused rtsx_pci_suspend(struct device *dev_d) { + struct pci_dev *pcidev = to_pci_dev(dev_d); struct pcr_handle *handle; struct rtsx_pcr *pcr; @@ -1613,17 +1666,15 @@ 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)); + device_wakeup_disable(dev_d); mutex_unlock(&pcr->pcr_mutex); return 0; } -static int rtsx_pci_resume(struct pci_dev *pcidev) +static int __maybe_unused rtsx_pci_resume(struct device *dev_d) { + struct pci_dev *pcidev = to_pci_dev(dev_d); struct pcr_handle *handle; struct rtsx_pcr *pcr; int ret = 0; @@ -1634,13 +1685,6 @@ 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) @@ -1656,6 +1700,8 @@ mutex_unlock(&pcr->pcr_mutex); return ret; } + +#ifdef CONFIG_PM static void rtsx_pci_shutdown(struct pci_dev *pcidev) { @@ -1676,19 +1722,18 @@ #else /* CONFIG_PM */ -#define rtsx_pci_suspend NULL -#define rtsx_pci_resume NULL #define rtsx_pci_shutdown NULL #endif /* CONFIG_PM */ + +static SIMPLE_DEV_PM_OPS(rtsx_pci_pm_ops, rtsx_pci_suspend, rtsx_pci_resume); 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, + .driver.pm = &rtsx_pci_pm_ops, .shutdown = rtsx_pci_shutdown, }; module_pci_driver(rtsx_pci_driver); -- Gitblit v1.6.2