Loading drivers/scsi/ufs/ufs-msm.c +4 −45 Original line number Diff line number Diff line Loading @@ -2479,9 +2479,6 @@ static int msm_ufs_pwr_change_notify(struct ufs_hba *hba, switch (status) { case PRE_CHANGE: if (hba->quirks & UFSHCD_QUIRK_BROKEN_2_TX_LANES) ufs_msm_cap.tx_lanes = 1; else ufs_msm_cap.tx_lanes = UFS_MSM_LIMIT_NUM_LANES_TX; ufs_msm_cap.rx_lanes = UFS_MSM_LIMIT_NUM_LANES_RX; Loading Loading @@ -2555,25 +2552,11 @@ static void msm_ufs_advertise_quirks(struct ufs_hba *hba) msm_ufs_get_controller_revision(hba, &major, &minor, &step); /* * Interrupt aggregation and HIBERN8 on UFS HW controller revision 1.1.0 * is broken. */ if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { hba->quirks |= (UFSHCD_QUIRK_BROKEN_INTR_AGGR | UFSHCD_QUIRK_BROKEN_HIBERN8 | UFSHCD_QUIRK_BROKEN_VER_REG_1_1 | UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0 | UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_2_TX_LANES | UFSHCD_QUIRK_BROKEN_SUSPEND | UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST | UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE); } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_INTR_AGGR | UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS | UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST); | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP | UFSHCD_QUIRK_BROKEN_LCC); phy->quirks = MSM_UFS_PHY_QUIRK_CFG_RESTORE; } Loading Loading @@ -2851,30 +2834,6 @@ static int msm_ufs_init(struct ufs_hba *hba) goto out_disable_phy; msm_ufs_advertise_quirks(hba); if (hba->quirks & UFSHCD_QUIRK_BROKEN_SUSPEND) { /* * During suspend keep the device and the link active * but shut-off the system clocks. */ hba->rpm_lvl = UFS_PM_LVL_0; hba->spm_lvl = UFS_PM_LVL_0; } else if (hba->quirks & UFSHCD_QUIRK_BROKEN_HIBERN8) { /* * During runtime suspend, keep link active but put device in * sleep state. * During system suspend, power off both link and device. */ hba->rpm_lvl = UFS_PM_LVL_2; hba->spm_lvl = UFS_PM_LVL_4; } else { /* * During runtime & system suspend, put link in Hibern8 and * device in sleep. */ hba->rpm_lvl = UFS_PM_LVL_3; hba->spm_lvl = UFS_PM_LVL_3; } hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING; hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; Loading drivers/scsi/ufs/ufs_quirks.h +9 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,15 @@ struct ufs_card_fix { .quirk = (_quirk), \ } /* * If UFS device is having issue in processing LCC (Line Control * Command) coming from UFS host controller then enable this quirk. * When this quirk is enabled, host controller driver should disable * the LCC transmission on UFS host controller (by clearing * TX_LCC_ENABLE attribute of host to 0). */ #define UFS_DEVICE_QUIRK_BROKEN_LCC UFS_BIT(0) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */ drivers/scsi/ufs/ufshcd.c +30 −19 Original line number Diff line number Diff line Loading @@ -236,6 +236,22 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl) return ufs_pm_lvl_states[lvl].link_state; } static inline enum ufs_pm_level ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, enum uic_link_state link_state) { enum ufs_pm_level lvl; for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) { if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) && (ufs_pm_lvl_states[lvl].link_state == link_state)) return lvl; } /* if no match found, return the level 0 */ return UFS_PM_LVL_0; } static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); Loading Loading @@ -624,12 +640,6 @@ ufshcd_config_intr_aggr(struct ufs_hba *hba, u8 cnt, u8 tmout) #define ufshcd_is_intr_aggr_broken(hba) ((hba)->quirks & \ UFSHCD_QUIRK_BROKEN_INTR_AGGR) #define ufshcd_can_queue(hba) \ ({ \ ((hba)->quirks & \ UFSHCD_QUIRK_BROKEN_DEVICE_Q_CMND) ? 1 : (hba)->nutrs; \ }) /** * ufshcd_disable_intr_aggr - Disables interrupt aggregation. * @hba: per adapter instance Loading Loading @@ -1064,9 +1074,6 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1; hba->nutmrs = ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1; if (hba->quirks & UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0) hba->capabilities |= MASK_64_ADDRESSING_SUPPORT; } /** Loading Loading @@ -2585,7 +2592,7 @@ static int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) struct uic_command uic_cmd = {0}; int ret; if (hba->quirks & UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS) { if (hba->quirks & UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP) { ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_RXHSUNTERMCAP, 0), 1); if (ret) { Loading Loading @@ -2794,9 +2801,6 @@ static int ufshcd_config_max_pwr_mode(struct ufs_hba *hba) ufshcd_print_pwr_info(hba); if (hba->quirks & UFSHCD_QUIRK_BROKEN_PWR_MODE_CHANGE) msleep(1000); return ret; } Loading Loading @@ -3046,13 +3050,13 @@ static int ufshcd_link_startup(struct ufs_hba *hba) /* failed to get the link up... retire */ goto out; if (hba->quirks & UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST) { if (hba->quirks & UFSHCD_QUIRK_BROKEN_LCC) { ret = ufshcd_disable_device_tx_lcc(hba); if (ret) goto out; } if (hba->quirks & UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE) { if (hba->dev_quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) { ret = ufshcd_disable_host_tx_lcc(hba); if (ret) goto out; Loading Loading @@ -6177,9 +6181,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Get UFS version supported by the controller */ hba->ufs_version = ufshcd_get_ufs_version(hba); if ((hba->quirks & UFSHCD_QUIRK_BROKEN_VER_REG_1_1) && (hba->ufs_version == UFSHCI_VERSION_10)) hba->ufs_version = UFSHCI_VERSION_11; /* Get Interrupt bit mask per version */ hba->intr_mask = ufshcd_get_intr_mask(hba); Loading @@ -6200,7 +6201,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Configure LRB */ ufshcd_host_memory_configure(hba); host->can_queue = ufshcd_can_queue(hba); host->can_queue = hba->nutrs; host->cmd_per_lun = hba->nutrs; host->max_id = UFSHCD_MAX_ID; host->max_lun = UFS_MAX_LUNS; Loading Loading @@ -6270,6 +6271,16 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) hba->clk_scaling.window_start_t = 0; } /* * Set the default power management level for UFS runtime and system * suspend. Default power saving mode selected is keeping UFS link in * Hibern8 state and UFS device in sleep. */ hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); /* Hold auto suspend until async scan completes */ pm_runtime_get_sync(dev); Loading drivers/scsi/ufs/ufshcd.h +8 −49 Original line number Diff line number Diff line Loading @@ -444,47 +444,14 @@ struct ufs_hba { unsigned int irq; bool is_irq_enabled; unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ unsigned int dev_quirks; /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR (1<<0) /* HIBERN8 support is broken */ #define UFSHCD_QUIRK_BROKEN_HIBERN8 (1<<1) /* * UFS controller version register (VER) wrongly advertise the version * as v1.0 though controller implementation is as per UFSHCI v1.1 * specification. */ #define UFSHCD_QUIRK_BROKEN_VER_REG_1_1 (1<<2) /* UFSHC advertises 64-bit not supported even though it supports */ #define UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0 (1 << 3) /* Command queueing for the UFS device is broken, allowing the * controller to have a single command at a time for the device */ #define UFSHCD_QUIRK_BROKEN_DEVICE_Q_CMND (1 << 4) /* * Power mode switch is broken, the power mode will be default * to PWM-G1 or the one set by bootloader. */ #define UFSHCD_QUIRK_BROKEN_PWR_MODE_CHANGE (1 << 5) /* runtime pm or system suspend/resume is broken */ #define UFSHCD_QUIRK_BROKEN_SUSPEND (1 << 6) #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) /* * delay before each dme command is required as the unipro * layer has shown instabilities */ #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS (1 << 7) #define UFSHCD_QUIRK_BROKEN_2_TX_LANES (1 << 8) #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(1) /* * If UFS host controller is having issue in processing LCC (Line Loading @@ -493,24 +460,19 @@ struct ufs_hba { * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE * attribute of device to 0). */ #define UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST (1 << 9) #define UFSHCD_QUIRK_BROKEN_LCC UFS_BIT(2) /* * The attribute PA_RXHSUNTERMCAP specifies whether or not the * inbound Link supports unterminated line in HS mode. Setting this * attribute to 1 fixes moving to HS gear. */ #define UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS (1 << 10) #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP UFS_BIT(3) /* * If UFS device is having issue in processing LCC (Line Control * Command) coming from UFS host controller then enable this quirk. * When this quirk is enabled, host controller driver should disable * the LCC transmission on UFS host controller (by clearing * TX_LCC_ENABLE attribute of host to 0). */ #define UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE (1 << 11) unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ unsigned int dev_quirks; wait_queue_head_t tm_wq; wait_queue_head_t tm_tag_wq; Loading Loading @@ -583,10 +545,7 @@ static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) } static inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba) { if (!(hba->quirks & UFSHCD_QUIRK_BROKEN_HIBERN8)) return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; else return false; } static inline int ufshcd_is_clkscaling_enabled(struct ufs_hba *hba) { Loading Loading
drivers/scsi/ufs/ufs-msm.c +4 −45 Original line number Diff line number Diff line Loading @@ -2479,9 +2479,6 @@ static int msm_ufs_pwr_change_notify(struct ufs_hba *hba, switch (status) { case PRE_CHANGE: if (hba->quirks & UFSHCD_QUIRK_BROKEN_2_TX_LANES) ufs_msm_cap.tx_lanes = 1; else ufs_msm_cap.tx_lanes = UFS_MSM_LIMIT_NUM_LANES_TX; ufs_msm_cap.rx_lanes = UFS_MSM_LIMIT_NUM_LANES_RX; Loading Loading @@ -2555,25 +2552,11 @@ static void msm_ufs_advertise_quirks(struct ufs_hba *hba) msm_ufs_get_controller_revision(hba, &major, &minor, &step); /* * Interrupt aggregation and HIBERN8 on UFS HW controller revision 1.1.0 * is broken. */ if ((major == 0x1) && (minor == 0x001) && (step == 0x0000)) { hba->quirks |= (UFSHCD_QUIRK_BROKEN_INTR_AGGR | UFSHCD_QUIRK_BROKEN_HIBERN8 | UFSHCD_QUIRK_BROKEN_VER_REG_1_1 | UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0 | UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_2_TX_LANES | UFSHCD_QUIRK_BROKEN_SUSPEND | UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST | UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE); } else if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { if ((major == 0x1) && (minor == 0x001) && (step == 0x0001)) { hba->quirks |= (UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS | UFSHCD_QUIRK_BROKEN_INTR_AGGR | UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS | UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST); | UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP | UFSHCD_QUIRK_BROKEN_LCC); phy->quirks = MSM_UFS_PHY_QUIRK_CFG_RESTORE; } Loading Loading @@ -2851,30 +2834,6 @@ static int msm_ufs_init(struct ufs_hba *hba) goto out_disable_phy; msm_ufs_advertise_quirks(hba); if (hba->quirks & UFSHCD_QUIRK_BROKEN_SUSPEND) { /* * During suspend keep the device and the link active * but shut-off the system clocks. */ hba->rpm_lvl = UFS_PM_LVL_0; hba->spm_lvl = UFS_PM_LVL_0; } else if (hba->quirks & UFSHCD_QUIRK_BROKEN_HIBERN8) { /* * During runtime suspend, keep link active but put device in * sleep state. * During system suspend, power off both link and device. */ hba->rpm_lvl = UFS_PM_LVL_2; hba->spm_lvl = UFS_PM_LVL_4; } else { /* * During runtime & system suspend, put link in Hibern8 and * device in sleep. */ hba->rpm_lvl = UFS_PM_LVL_3; hba->spm_lvl = UFS_PM_LVL_3; } hba->caps |= UFSHCD_CAP_CLK_GATING | UFSHCD_CAP_CLK_SCALING; hba->caps |= UFSHCD_CAP_AUTO_BKOPS_SUSPEND; Loading
drivers/scsi/ufs/ufs_quirks.h +9 −0 Original line number Diff line number Diff line Loading @@ -57,6 +57,15 @@ struct ufs_card_fix { .quirk = (_quirk), \ } /* * If UFS device is having issue in processing LCC (Line Control * Command) coming from UFS host controller then enable this quirk. * When this quirk is enabled, host controller driver should disable * the LCC transmission on UFS host controller (by clearing * TX_LCC_ENABLE attribute of host to 0). */ #define UFS_DEVICE_QUIRK_BROKEN_LCC UFS_BIT(0) struct ufs_hba; void ufs_advertise_fixup_device(struct ufs_hba *hba); #endif /* UFS_QUIRKS_H_ */
drivers/scsi/ufs/ufshcd.c +30 −19 Original line number Diff line number Diff line Loading @@ -236,6 +236,22 @@ ufs_get_pm_lvl_to_link_pwr_state(enum ufs_pm_level lvl) return ufs_pm_lvl_states[lvl].link_state; } static inline enum ufs_pm_level ufs_get_desired_pm_lvl_for_dev_link_state(enum ufs_dev_pwr_mode dev_state, enum uic_link_state link_state) { enum ufs_pm_level lvl; for (lvl = UFS_PM_LVL_0; lvl < UFS_PM_LVL_MAX; lvl++) { if ((ufs_pm_lvl_states[lvl].dev_state == dev_state) && (ufs_pm_lvl_states[lvl].link_state == link_state)) return lvl; } /* if no match found, return the level 0 */ return UFS_PM_LVL_0; } static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); Loading Loading @@ -624,12 +640,6 @@ ufshcd_config_intr_aggr(struct ufs_hba *hba, u8 cnt, u8 tmout) #define ufshcd_is_intr_aggr_broken(hba) ((hba)->quirks & \ UFSHCD_QUIRK_BROKEN_INTR_AGGR) #define ufshcd_can_queue(hba) \ ({ \ ((hba)->quirks & \ UFSHCD_QUIRK_BROKEN_DEVICE_Q_CMND) ? 1 : (hba)->nutrs; \ }) /** * ufshcd_disable_intr_aggr - Disables interrupt aggregation. * @hba: per adapter instance Loading Loading @@ -1064,9 +1074,6 @@ static inline void ufshcd_hba_capabilities(struct ufs_hba *hba) hba->nutrs = (hba->capabilities & MASK_TRANSFER_REQUESTS_SLOTS) + 1; hba->nutmrs = ((hba->capabilities & MASK_TASK_MANAGEMENT_REQUEST_SLOTS) >> 16) + 1; if (hba->quirks & UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0) hba->capabilities |= MASK_64_ADDRESSING_SUPPORT; } /** Loading Loading @@ -2585,7 +2592,7 @@ static int ufshcd_uic_change_pwr_mode(struct ufs_hba *hba, u8 mode) struct uic_command uic_cmd = {0}; int ret; if (hba->quirks & UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS) { if (hba->quirks & UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP) { ret = ufshcd_dme_set(hba, UIC_ARG_MIB_SEL(PA_RXHSUNTERMCAP, 0), 1); if (ret) { Loading Loading @@ -2794,9 +2801,6 @@ static int ufshcd_config_max_pwr_mode(struct ufs_hba *hba) ufshcd_print_pwr_info(hba); if (hba->quirks & UFSHCD_QUIRK_BROKEN_PWR_MODE_CHANGE) msleep(1000); return ret; } Loading Loading @@ -3046,13 +3050,13 @@ static int ufshcd_link_startup(struct ufs_hba *hba) /* failed to get the link up... retire */ goto out; if (hba->quirks & UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST) { if (hba->quirks & UFSHCD_QUIRK_BROKEN_LCC) { ret = ufshcd_disable_device_tx_lcc(hba); if (ret) goto out; } if (hba->quirks & UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE) { if (hba->dev_quirks & UFS_DEVICE_QUIRK_BROKEN_LCC) { ret = ufshcd_disable_host_tx_lcc(hba); if (ret) goto out; Loading Loading @@ -6177,9 +6181,6 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Get UFS version supported by the controller */ hba->ufs_version = ufshcd_get_ufs_version(hba); if ((hba->quirks & UFSHCD_QUIRK_BROKEN_VER_REG_1_1) && (hba->ufs_version == UFSHCI_VERSION_10)) hba->ufs_version = UFSHCI_VERSION_11; /* Get Interrupt bit mask per version */ hba->intr_mask = ufshcd_get_intr_mask(hba); Loading @@ -6200,7 +6201,7 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) /* Configure LRB */ ufshcd_host_memory_configure(hba); host->can_queue = ufshcd_can_queue(hba); host->can_queue = hba->nutrs; host->cmd_per_lun = hba->nutrs; host->max_id = UFSHCD_MAX_ID; host->max_lun = UFS_MAX_LUNS; Loading Loading @@ -6270,6 +6271,16 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq) hba->clk_scaling.window_start_t = 0; } /* * Set the default power management level for UFS runtime and system * suspend. Default power saving mode selected is keeping UFS link in * Hibern8 state and UFS device in sleep. */ hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state( UFS_SLEEP_PWR_MODE, UIC_LINK_HIBERN8_STATE); /* Hold auto suspend until async scan completes */ pm_runtime_get_sync(dev); Loading
drivers/scsi/ufs/ufshcd.h +8 −49 Original line number Diff line number Diff line Loading @@ -444,47 +444,14 @@ struct ufs_hba { unsigned int irq; bool is_irq_enabled; unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ unsigned int dev_quirks; /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR (1<<0) /* HIBERN8 support is broken */ #define UFSHCD_QUIRK_BROKEN_HIBERN8 (1<<1) /* * UFS controller version register (VER) wrongly advertise the version * as v1.0 though controller implementation is as per UFSHCI v1.1 * specification. */ #define UFSHCD_QUIRK_BROKEN_VER_REG_1_1 (1<<2) /* UFSHC advertises 64-bit not supported even though it supports */ #define UFSHCD_QUIRK_BROKEN_CAP_64_BIT_0 (1 << 3) /* Command queueing for the UFS device is broken, allowing the * controller to have a single command at a time for the device */ #define UFSHCD_QUIRK_BROKEN_DEVICE_Q_CMND (1 << 4) /* * Power mode switch is broken, the power mode will be default * to PWM-G1 or the one set by bootloader. */ #define UFSHCD_QUIRK_BROKEN_PWR_MODE_CHANGE (1 << 5) /* runtime pm or system suspend/resume is broken */ #define UFSHCD_QUIRK_BROKEN_SUSPEND (1 << 6) #define UFSHCD_QUIRK_BROKEN_INTR_AGGR UFS_BIT(0) /* * delay before each dme command is required as the unipro * layer has shown instabilities */ #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS (1 << 7) #define UFSHCD_QUIRK_BROKEN_2_TX_LANES (1 << 8) #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS UFS_BIT(1) /* * If UFS host controller is having issue in processing LCC (Line Loading @@ -493,24 +460,19 @@ struct ufs_hba { * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE * attribute of device to 0). */ #define UFSHCD_BROKEN_LCC_PROCESSING_ON_HOST (1 << 9) #define UFSHCD_QUIRK_BROKEN_LCC UFS_BIT(2) /* * The attribute PA_RXHSUNTERMCAP specifies whether or not the * inbound Link supports unterminated line in HS mode. Setting this * attribute to 1 fixes moving to HS gear. */ #define UFSHCD_BROKEN_GEAR_CHANGE_INTO_HS (1 << 10) #define UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP UFS_BIT(3) /* * If UFS device is having issue in processing LCC (Line Control * Command) coming from UFS host controller then enable this quirk. * When this quirk is enabled, host controller driver should disable * the LCC transmission on UFS host controller (by clearing * TX_LCC_ENABLE attribute of host to 0). */ #define UFSHCD_BROKEN_LCC_PROCESSING_ON_DEVICE (1 << 11) unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ unsigned int dev_quirks; wait_queue_head_t tm_wq; wait_queue_head_t tm_tag_wq; Loading Loading @@ -583,10 +545,7 @@ static inline bool ufshcd_is_clkgating_allowed(struct ufs_hba *hba) } static inline bool ufshcd_can_hibern8_during_gating(struct ufs_hba *hba) { if (!(hba->quirks & UFSHCD_QUIRK_BROKEN_HIBERN8)) return hba->caps & UFSHCD_CAP_HIBERN8_WITH_CLK_GATING; else return false; } static inline int ufshcd_is_clkscaling_enabled(struct ufs_hba *hba) { Loading