diff options
Diffstat (limited to 'drivers/scsi/ufs/ufshcd.h')
-rw-r--r-- | drivers/scsi/ufs/ufshcd.h | 205 |
1 files changed, 104 insertions, 101 deletions
diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 2ae6c7c8528c..dd1ee277069a 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -55,6 +55,8 @@ #include <linux/clk.h> #include <linux/completion.h> #include <linux/regulator/consumer.h> +#include <linux/bitfield.h> +#include <linux/devfreq.h> #include "unipro.h" #include <asm/irq.h> @@ -326,6 +328,9 @@ struct ufs_hba_variant_ops { void (*dbg_register_dump)(struct ufs_hba *hba); int (*phy_initialization)(struct ufs_hba *); void (*device_reset)(struct ufs_hba *hba); + void (*config_scaling_param)(struct ufs_hba *hba, + struct devfreq_dev_profile *profile, + void *data); }; /* clock gating state */ @@ -403,15 +408,6 @@ struct ufs_clk_scaling { bool is_suspended; }; -/** - * struct ufs_init_prefetch - contains data that is pre-fetched once during - * initialization - * @icc_level: icc level which was read during initialization - */ -struct ufs_init_prefetch { - u32 icc_level; -}; - #define UFS_ERR_REG_HIST_LENGTH 8 /** * struct ufs_err_reg_hist - keeps history of errors @@ -469,6 +465,85 @@ struct ufs_stats { struct ufs_err_reg_hist task_abort; }; +enum ufshcd_quirks { + /* Interrupt aggregation support is broken */ + UFSHCD_QUIRK_BROKEN_INTR_AGGR = 1 << 0, + + /* + * delay before each dme command is required as the unipro + * layer has shown instabilities + */ + UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS = 1 << 1, + + /* + * If UFS host controller is having issue in processing LCC (Line + * Control Command) coming from device then enable this quirk. + * When this quirk is enabled, host controller driver should disable + * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE + * attribute of device to 0). + */ + UFSHCD_QUIRK_BROKEN_LCC = 1 << 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. + */ + UFSHCD_QUIRK_BROKEN_PA_RXHSUNTERMCAP = 1 << 3, + + /* + * This quirk needs to be enabled if the host controller only allows + * accessing the peer dme attributes in AUTO mode (FAST AUTO or + * SLOW AUTO). + */ + UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE = 1 << 4, + + /* + * This quirk needs to be enabled if the host controller doesn't + * advertise the correct version in UFS_VER register. If this quirk + * is enabled, standard UFS host driver will call the vendor specific + * ops (get_ufs_hci_version) to get the correct version. + */ + UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION = 1 << 5, +}; + +enum ufshcd_caps { + /* Allow dynamic clk gating */ + UFSHCD_CAP_CLK_GATING = 1 << 0, + + /* Allow hiberb8 with clk gating */ + UFSHCD_CAP_HIBERN8_WITH_CLK_GATING = 1 << 1, + + /* Allow dynamic clk scaling */ + UFSHCD_CAP_CLK_SCALING = 1 << 2, + + /* Allow auto bkops to enabled during runtime suspend */ + UFSHCD_CAP_AUTO_BKOPS_SUSPEND = 1 << 3, + + /* + * This capability allows host controller driver to use the UFS HCI's + * interrupt aggregation capability. + * CAUTION: Enabling this might reduce overall UFS throughput. + */ + UFSHCD_CAP_INTR_AGGR = 1 << 4, + + /* + * This capability allows the device auto-bkops to be always enabled + * except during suspend (both runtime and suspend). + * Enabling this capability means that device will always be allowed + * to do background operation when it's active but it might degrade + * the performance of ongoing read/write operations. + */ + UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND = 1 << 5, + + /* + * This capability allows host controller driver to automatically + * enable runtime power management by itself instead of waiting + * for userspace to control the power management. + */ + UFSHCD_CAP_RPM_AUTOSUSPEND = 1 << 6, +}; + /** * struct ufs_hba - per adapter private structure * @mmio_base: UFSHCI base register address @@ -501,7 +576,6 @@ struct ufs_stats { * @intr_mask: Interrupt Mask Bits * @ee_ctrl_mask: Exception event control mask * @is_powered: flag to check if HBA is powered - * @init_prefetch_data: data pre-fetched during initialization * @eh_work: Worker to handle UFS errors that require s/w attention * @eeh_work: Worker to handle exception events * @errors: HBA errors @@ -572,68 +646,6 @@ struct ufs_hba { bool is_irq_enabled; enum ufs_ref_clk_freq dev_ref_clk_freq; - /* Interrupt aggregation support is broken */ - #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1 - - /* - * delay before each dme command is required as the unipro - * layer has shown instabilities - */ - #define UFSHCD_QUIRK_DELAY_BEFORE_DME_CMDS 0x2 - - /* - * If UFS host controller is having issue in processing LCC (Line - * Control Command) coming from device then enable this quirk. - * When this quirk is enabled, host controller driver should disable - * the LCC transmission on UFS device (by clearing TX_LCC_ENABLE - * attribute of device to 0). - */ - #define UFSHCD_QUIRK_BROKEN_LCC 0x4 - - /* - * 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_QUIRK_BROKEN_PA_RXHSUNTERMCAP 0x8 - - /* - * This quirk needs to be enabled if the host contoller only allows - * accessing the peer dme attributes in AUTO mode (FAST AUTO or - * SLOW AUTO). - */ - #define UFSHCD_QUIRK_DME_PEER_ACCESS_AUTO_MODE 0x10 - - /* - * This quirk needs to be enabled if the host contoller doesn't - * advertise the correct version in UFS_VER register. If this quirk - * is enabled, standard UFS host driver will call the vendor specific - * ops (get_ufs_hci_version) to get the correct version. - */ - #define UFSHCD_QUIRK_BROKEN_UFS_HCI_VERSION 0x20 - - /* - * This quirk needs to be enabled if the host contoller regards - * resolution of the values of PRDTO and PRDTL in UTRD as byte. - */ - #define UFSHCD_QUIRK_PRDT_BYTE_GRAN 0x80 - - /* - * Clear handling for transfer/task request list is just opposite. - */ - #define UFSHCI_QUIRK_BROKEN_REQ_LIST_CLR 0x100 - - /* - * This quirk needs to be enabled if host controller doesn't allow - * that the interrupt aggregation timer and counter are reset by s/w. - */ - #define UFSHCI_QUIRK_SKIP_RESET_INTR_AGGR 0x200 - - /* - * This quirks needs to be enabled if host controller cannot be - * enabled via HCE register. - */ - #define UFSHCI_QUIRK_BROKEN_HCE 0x400 unsigned int quirks; /* Deviations from standard UFSHCI spec. */ /* Device deviations from standard UFS device spec. */ @@ -650,8 +662,8 @@ struct ufs_hba { u32 eh_flags; u32 intr_mask; u16 ee_ctrl_mask; + u16 hba_enable_delay_us; bool is_powered; - struct ufs_init_prefetch init_prefetch_data; /* Work Queues */ struct work_struct eh_work; @@ -688,34 +700,6 @@ struct ufs_hba { struct ufs_clk_gating clk_gating; /* Control to enable/disable host capabilities */ u32 caps; - /* Allow dynamic clk gating */ -#define UFSHCD_CAP_CLK_GATING (1 << 0) - /* Allow hiberb8 with clk gating */ -#define UFSHCD_CAP_HIBERN8_WITH_CLK_GATING (1 << 1) - /* Allow dynamic clk scaling */ -#define UFSHCD_CAP_CLK_SCALING (1 << 2) - /* Allow auto bkops to enabled during runtime suspend */ -#define UFSHCD_CAP_AUTO_BKOPS_SUSPEND (1 << 3) - /* - * This capability allows host controller driver to use the UFS HCI's - * interrupt aggregation capability. - * CAUTION: Enabling this might reduce overall UFS throughput. - */ -#define UFSHCD_CAP_INTR_AGGR (1 << 4) - /* - * This capability allows the device auto-bkops to be always enabled - * except during suspend (both runtime and suspend). - * Enabling this capability means that device will always be allowed - * to do background operation when it's active but it might degrade - * the performance of ongoing read/write operations. - */ -#define UFSHCD_CAP_KEEP_AUTO_BKOPS_ENABLED_EXCEPT_SUSPEND (1 << 5) - /* - * This capability allows host controller driver to automatically - * enable runtime power management by itself instead of waiting - * for userspace to control the power management. - */ -#define UFSHCD_CAP_RPM_AUTOSUSPEND (1 << 6) struct devfreq *devfreq; struct ufs_clk_scaling clk_scaling; @@ -773,6 +757,11 @@ static inline bool ufshcd_is_auto_hibern8_supported(struct ufs_hba *hba) return (hba->capabilities & MASK_AUTO_HIBERN8_SUPPORT); } +static inline bool ufshcd_is_auto_hibern8_enabled(struct ufs_hba *hba) +{ + return FIELD_GET(UFSHCI_AHIBERN8_TIMER_MASK, hba->ahit) ? true : false; +} + #define ufshcd_writel(hba, val, reg) \ writel((val), (hba)->mmio_base + (reg)) #define ufshcd_readl(hba, reg) \ @@ -802,6 +791,7 @@ int ufshcd_init(struct ufs_hba * , void __iomem * , unsigned int); int ufshcd_make_hba_operational(struct ufs_hba *hba); void ufshcd_remove(struct ufs_hba *); int ufshcd_uic_hibern8_exit(struct ufs_hba *hba); +void ufshcd_delay_us(unsigned long us, unsigned long tolerance); int ufshcd_wait_for_register(struct ufs_hba *hba, u32 reg, u32 mask, u32 val, unsigned long interval_us, unsigned long timeout_ms, bool can_sleep); @@ -908,6 +898,11 @@ static inline bool ufshcd_is_hs_mode(struct ufs_pa_layer_attr *pwr_info) pwr_info->pwr_tx == FASTAUTO_MODE); } +static inline int ufshcd_disable_host_tx_lcc(struct ufs_hba *hba) +{ + return ufshcd_dme_set(hba, UIC_ARG_MIB(PA_LOCAL_TX_LCC_ENABLE), 0); +} + /* Expose Query-Request API */ int ufshcd_query_descriptor_retry(struct ufs_hba *hba, enum query_opcode opcode, @@ -1092,6 +1087,14 @@ static inline void ufshcd_vops_device_reset(struct ufs_hba *hba) } } +static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba, + struct devfreq_dev_profile + *profile, void *data) +{ + if (hba->vops && hba->vops->config_scaling_param) + hba->vops->config_scaling_param(hba, profile, data); +} + extern struct ufs_pm_lvl_states ufs_pm_lvl_states[]; /* |