summaryrefslogtreecommitdiff
path: root/drivers/scsi/ufs/ufs-qcom.h
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/ufs/ufs-qcom.h')
-rw-r--r--drivers/scsi/ufs/ufs-qcom.h173
1 files changed, 167 insertions, 6 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h
index 36249b35f858..fd98a3381d61 100644
--- a/drivers/scsi/ufs/ufs-qcom.h
+++ b/drivers/scsi/ufs/ufs-qcom.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2017, The Linux Foundation. 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 version 2 and
@@ -14,9 +14,14 @@
#ifndef UFS_QCOM_H_
#define UFS_QCOM_H_
+#include <linux/phy/phy.h>
+#include <linux/pm_qos.h>
+#include "ufshcd.h"
+
#define MAX_UFS_QCOM_HOSTS 1
#define MAX_U32 (~(u32)0)
#define MPHY_TX_FSM_STATE 0x41
+#define MPHY_RX_FSM_STATE 0xC1
#define TX_FSM_HIBERN8 0x1
#define HBRN8_POLL_TOUT_MS 100
#define DEFAULT_CLK_RATE_HZ 1000000
@@ -71,6 +76,7 @@ enum {
UFS_AH8_CFG = 0xFC,
};
+
/* QCOM UFS host controller vendor specific debug registers */
enum {
UFS_DBG_RD_REG_UAWM = 0x100,
@@ -94,7 +100,8 @@ enum {
/* bit definitions for REG_UFS_CFG1 register */
#define QUNIPRO_SEL UFS_BIT(0)
#define TEST_BUS_EN BIT(18)
-#define TEST_BUS_SEL GENMASK(22, 19)
+#define TEST_BUS_SEL 0x780000
+#define UFS_REG_TEST_BUS_EN BIT(30)
/* bit definitions for REG_UFS_CFG2 register */
#define UAWM_HW_CGC_EN (1 << 0)
@@ -114,6 +121,17 @@ enum {
DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\
TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN)
+/* bit definitions for UFS_AH8_CFG register */
+#define CC_UFS_HCLK_REQ_EN BIT(1)
+#define CC_UFS_SYS_CLK_REQ_EN BIT(2)
+#define CC_UFS_ICE_CORE_CLK_REQ_EN BIT(3)
+#define CC_UFS_UNIPRO_CORE_CLK_REQ_EN BIT(4)
+#define CC_UFS_AUXCLK_REQ_EN BIT(5)
+
+#define UFS_HW_CLK_CTRL_EN (CC_UFS_SYS_CLK_REQ_EN |\
+ CC_UFS_ICE_CORE_CLK_REQ_EN |\
+ CC_UFS_UNIPRO_CORE_CLK_REQ_EN |\
+ CC_UFS_AUXCLK_REQ_EN)
/* bit offset */
enum {
OFFSET_UFS_PHY_SOFT_RESET = 1,
@@ -142,10 +160,20 @@ enum ufs_qcom_phy_init_type {
UFS_QCOM_DBG_PRINT_TEST_BUS_EN)
/* QUniPro Vendor specific attributes */
+#define PA_VS_CONFIG_REG1 0x9000
+#define SAVECONFIGTIME_MODE_MASK 0x6000
+
+#define PA_VS_CLK_CFG_REG 0x9004
+#define PA_VS_CLK_CFG_REG_MASK 0x1FF
+
+#define DL_VS_CLK_CFG 0xA00B
+#define DL_VS_CLK_CFG_MASK 0x3FF
+
#define DME_VS_CORE_CLK_CTRL 0xD002
/* bit and mask definitions for DME_VS_CORE_CLK_CTRL attribute */
-#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
#define DME_VS_CORE_CLK_CTRL_MAX_CORE_CLK_1US_CYCLES_MASK 0xFF
+#define DME_VS_CORE_CLK_CTRL_CORE_CLK_DIV_EN_BIT BIT(8)
+#define DME_VS_CORE_CLK_CTRL_DME_HW_CGC_EN BIT(9)
static inline void
ufs_qcom_get_controller_revision(struct ufs_hba *hba,
@@ -192,6 +220,26 @@ struct ufs_qcom_bus_vote {
struct device_attribute max_bus_bw;
};
+/**
+ * struct ufs_qcom_ice_data - ICE related information
+ * @vops: pointer to variant operations of ICE
+ * @async_done: completion for supporting ICE's driver asynchronous nature
+ * @pdev: pointer to the proper ICE platform device
+ * @state: UFS-ICE interface's internal state (see
+ * ufs-qcom-ice.h for possible internal states)
+ * @quirks: UFS-ICE interface related quirks
+ * @crypto_engine_err: crypto engine errors
+ */
+struct ufs_qcom_ice_data {
+ struct qcom_ice_variant_ops *vops;
+ struct platform_device *pdev;
+ int state;
+
+ u16 quirks;
+
+ bool crypto_engine_err;
+};
+
/* Host controller hardware version: major.minor.step */
struct ufs_hw_version {
u16 step;
@@ -199,11 +247,76 @@ struct ufs_hw_version {
u8 major;
};
+#ifdef CONFIG_DEBUG_FS
+struct qcom_debugfs_files {
+ struct dentry *debugfs_root;
+ struct dentry *dbg_print_en;
+ struct dentry *testbus;
+ struct dentry *testbus_en;
+ struct dentry *testbus_cfg;
+ struct dentry *testbus_bus;
+ struct dentry *dbg_regs;
+ struct dentry *pm_qos;
+};
+#endif
+
struct ufs_qcom_testbus {
u8 select_major;
u8 select_minor;
};
+/* PM QoS voting state */
+enum ufs_qcom_pm_qos_state {
+ PM_QOS_UNVOTED,
+ PM_QOS_VOTED,
+ PM_QOS_REQ_VOTE,
+ PM_QOS_REQ_UNVOTE,
+};
+
+/**
+ * struct ufs_qcom_pm_qos_cpu_group - data related to cluster PM QoS voting
+ * logic
+ * @req: request object for PM QoS
+ * @vote_work: work object for voting procedure
+ * @unvote_work: work object for un-voting procedure
+ * @host: back pointer to the main structure
+ * @state: voting state machine current state
+ * @latency_us: requested latency value used for cluster voting, in
+ * microseconds
+ * @mask: cpu mask defined for this cluster
+ * @active_reqs: number of active requests on this cluster
+ */
+struct ufs_qcom_pm_qos_cpu_group {
+ struct pm_qos_request req;
+ struct work_struct vote_work;
+ struct work_struct unvote_work;
+ struct ufs_qcom_host *host;
+ enum ufs_qcom_pm_qos_state state;
+ s32 latency_us;
+ cpumask_t mask;
+ int active_reqs;
+};
+
+/**
+ * struct ufs_qcom_pm_qos - data related to PM QoS voting logic
+ * @groups: PM QoS cpu group state array
+ * @enable_attr: sysfs attribute to enable/disable PM QoS voting logic
+ * @latency_attr: sysfs attribute to set latency value
+ * @workq: single threaded workqueue to run PM QoS voting/unvoting
+ * @num_clusters: number of clusters defined
+ * @default_cpu: cpu to use for voting for request not specifying a cpu
+ * @is_enabled: flag specifying whether voting logic is enabled
+ */
+struct ufs_qcom_pm_qos {
+ struct ufs_qcom_pm_qos_cpu_group *groups;
+ struct device_attribute enable_attr;
+ struct device_attribute latency_attr;
+ struct workqueue_struct *workq;
+ int num_groups;
+ int default_cpu;
+ bool is_enabled;
+};
+
struct ufs_qcom_host {
/*
* Set this capability if host controller supports the QUniPro mode
@@ -218,6 +331,17 @@ struct ufs_qcom_host {
* configuration even after UFS controller core power collapse.
*/
#define UFS_QCOM_CAP_RETAIN_SEC_CFG_AFTER_PWR_COLLAPSE UFS_BIT(1)
+
+ /*
+ * Set this capability if host controller supports Qunipro internal
+ * clock gating.
+ */
+ #define UFS_QCOM_CAP_QUNIPRO_CLK_GATING UFS_BIT(2)
+
+ /*
+ * Set this capability if host controller supports SVS2 frequencies.
+ */
+ #define UFS_QCOM_CAP_SVS2 UFS_BIT(3)
u32 caps;
struct phy *generic_phy;
@@ -228,24 +352,51 @@ struct ufs_qcom_host {
struct clk *tx_l0_sync_clk;
struct clk *rx_l1_sync_clk;
struct clk *tx_l1_sync_clk;
- bool is_lane_clks_enabled;
+ /* PM Quality-of-Service (QoS) data */
+ struct ufs_qcom_pm_qos pm_qos;
+
+ bool disable_lpm;
+ bool is_lane_clks_enabled;
+ bool sec_cfg_updated;
+ struct ufs_qcom_ice_data ice;
void __iomem *dev_ref_clk_ctrl_mmio;
bool is_dev_ref_clk_enabled;
struct ufs_hw_version hw_ver;
-
u32 dev_ref_clk_en_mask;
-
+#ifdef CONFIG_DEBUG_FS
+ struct qcom_debugfs_files debugfs_files;
+#endif
/* Bitmask for enabling debug prints */
u32 dbg_print_en;
struct ufs_qcom_testbus testbus;
+
+ spinlock_t ice_work_lock;
+ struct work_struct ice_cfg_work;
+ struct request *req_pending;
+ struct ufs_vreg *vddp_ref_clk;
+ bool work_pending;
+};
+
+static inline u32
+ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg)
+{
+ if (host->hw_ver.major <= 0x02)
+ return UFS_CNTLR_2_x_x_VEN_REGS_OFFSET(reg);
+
+ return UFS_CNTLR_3_x_x_VEN_REGS_OFFSET(reg);
};
#define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba)
#define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba)
#define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba)
+bool ufs_qcom_testbus_cfg_is_ok(struct ufs_qcom_host *host, u8 select_major,
+ u8 select_minor);
int ufs_qcom_testbus_config(struct ufs_qcom_host *host);
+void ufs_qcom_print_hw_debug_reg_all(struct ufs_hba *hba, void *priv,
+ void (*print_fn)(struct ufs_hba *hba, int offset, int num_regs,
+ char *str, void *priv));
static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
{
@@ -255,4 +406,14 @@ static inline bool ufs_qcom_cap_qunipro(struct ufs_qcom_host *host)
return false;
}
+static inline bool ufs_qcom_cap_qunipro_clk_gating(struct ufs_qcom_host *host)
+{
+ return !!(host->caps & UFS_QCOM_CAP_QUNIPRO_CLK_GATING);
+}
+
+static inline bool ufs_qcom_cap_svs2(struct ufs_qcom_host *host)
+{
+ return !!(host->caps & UFS_QCOM_CAP_SVS2);
+}
+
#endif /* UFS_QCOM_H_ */