diff options
author | Yaniv Gardi <ygardi@codeaurora.org> | 2015-01-15 09:32:37 -0500 |
---|---|---|
committer | Christoph Hellwig <hch@lst.de> | 2015-01-20 13:43:26 -0500 |
commit | 81c0fc51b7a790ebe05a35de2c9176bd2f5bfe46 (patch) | |
tree | 35c186f69be9cf6d2fe99ccc647599079cbb8503 /drivers/scsi/ufs/ufs-qcom.h | |
parent | ca14ab55fb2ac620298ece3943fcf388a0387a13 (diff) |
ufs-qcom: add support for Qualcomm Technologies Inc platforms
This change adds support for Qualcomm Technologies Inc platforms that
use UFS driver. for example, it adds :
- PM specific operations during hibern8, suspend, resume, clock setup
- qcom-ufs generic phy driver initialization, calibration,
power-on/off sequence, etc.
- UFS Controller specific configuration
- Rate, Gear, Mode negotiation between device and controller
Signed-off-by: Yaniv Gardi <ygardi@codeaurora.org>
Reviewed-by: Dov Levenglick <dovl@codeaurora.org>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'drivers/scsi/ufs/ufs-qcom.h')
-rw-r--r-- | drivers/scsi/ufs/ufs-qcom.h | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/drivers/scsi/ufs/ufs-qcom.h b/drivers/scsi/ufs/ufs-qcom.h new file mode 100644 index 000000000000..9a6febd007df --- /dev/null +++ b/drivers/scsi/ufs/ufs-qcom.h | |||
@@ -0,0 +1,170 @@ | |||
1 | /* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify | ||
4 | * it under the terms of the GNU General Public License version 2 and | ||
5 | * only version 2 as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #ifndef UFS_QCOM_H_ | ||
15 | #define UFS_QCOM_H_ | ||
16 | |||
17 | #define MAX_UFS_QCOM_HOSTS 1 | ||
18 | #define MAX_U32 (~(u32)0) | ||
19 | #define MPHY_TX_FSM_STATE 0x41 | ||
20 | #define TX_FSM_HIBERN8 0x1 | ||
21 | #define HBRN8_POLL_TOUT_MS 100 | ||
22 | #define DEFAULT_CLK_RATE_HZ 1000000 | ||
23 | #define BUS_VECTOR_NAME_LEN 32 | ||
24 | |||
25 | #define UFS_HW_VER_MAJOR_SHFT (28) | ||
26 | #define UFS_HW_VER_MAJOR_MASK (0x000F << UFS_HW_VER_MAJOR_SHFT) | ||
27 | #define UFS_HW_VER_MINOR_SHFT (16) | ||
28 | #define UFS_HW_VER_MINOR_MASK (0x0FFF << UFS_HW_VER_MINOR_SHFT) | ||
29 | #define UFS_HW_VER_STEP_SHFT (0) | ||
30 | #define UFS_HW_VER_STEP_MASK (0xFFFF << UFS_HW_VER_STEP_SHFT) | ||
31 | |||
32 | /* vendor specific pre-defined parameters */ | ||
33 | #define SLOW 1 | ||
34 | #define FAST 2 | ||
35 | |||
36 | #define UFS_QCOM_LIMIT_NUM_LANES_RX 2 | ||
37 | #define UFS_QCOM_LIMIT_NUM_LANES_TX 2 | ||
38 | #define UFS_QCOM_LIMIT_HSGEAR_RX UFS_HS_G2 | ||
39 | #define UFS_QCOM_LIMIT_HSGEAR_TX UFS_HS_G2 | ||
40 | #define UFS_QCOM_LIMIT_PWMGEAR_RX UFS_PWM_G4 | ||
41 | #define UFS_QCOM_LIMIT_PWMGEAR_TX UFS_PWM_G4 | ||
42 | #define UFS_QCOM_LIMIT_RX_PWR_PWM SLOW_MODE | ||
43 | #define UFS_QCOM_LIMIT_TX_PWR_PWM SLOW_MODE | ||
44 | #define UFS_QCOM_LIMIT_RX_PWR_HS FAST_MODE | ||
45 | #define UFS_QCOM_LIMIT_TX_PWR_HS FAST_MODE | ||
46 | #define UFS_QCOM_LIMIT_HS_RATE PA_HS_MODE_B | ||
47 | #define UFS_QCOM_LIMIT_DESIRED_MODE FAST | ||
48 | |||
49 | /* QCOM UFS host controller vendor specific registers */ | ||
50 | enum { | ||
51 | REG_UFS_SYS1CLK_1US = 0xC0, | ||
52 | REG_UFS_TX_SYMBOL_CLK_NS_US = 0xC4, | ||
53 | REG_UFS_LOCAL_PORT_ID_REG = 0xC8, | ||
54 | REG_UFS_PA_ERR_CODE = 0xCC, | ||
55 | REG_UFS_RETRY_TIMER_REG = 0xD0, | ||
56 | REG_UFS_PA_LINK_STARTUP_TIMER = 0xD8, | ||
57 | REG_UFS_CFG1 = 0xDC, | ||
58 | REG_UFS_CFG2 = 0xE0, | ||
59 | REG_UFS_HW_VERSION = 0xE4, | ||
60 | |||
61 | UFS_DBG_RD_REG_UAWM = 0x100, | ||
62 | UFS_DBG_RD_REG_UARM = 0x200, | ||
63 | UFS_DBG_RD_REG_TXUC = 0x300, | ||
64 | UFS_DBG_RD_REG_RXUC = 0x400, | ||
65 | UFS_DBG_RD_REG_DFC = 0x500, | ||
66 | UFS_DBG_RD_REG_TRLUT = 0x600, | ||
67 | UFS_DBG_RD_REG_TMRLUT = 0x700, | ||
68 | UFS_UFS_DBG_RD_REG_OCSC = 0x800, | ||
69 | |||
70 | UFS_UFS_DBG_RD_DESC_RAM = 0x1500, | ||
71 | UFS_UFS_DBG_RD_PRDT_RAM = 0x1700, | ||
72 | UFS_UFS_DBG_RD_RESP_RAM = 0x1800, | ||
73 | UFS_UFS_DBG_RD_EDTL_RAM = 0x1900, | ||
74 | }; | ||
75 | |||
76 | /* bit definitions for REG_UFS_CFG2 register */ | ||
77 | #define UAWM_HW_CGC_EN (1 << 0) | ||
78 | #define UARM_HW_CGC_EN (1 << 1) | ||
79 | #define TXUC_HW_CGC_EN (1 << 2) | ||
80 | #define RXUC_HW_CGC_EN (1 << 3) | ||
81 | #define DFC_HW_CGC_EN (1 << 4) | ||
82 | #define TRLUT_HW_CGC_EN (1 << 5) | ||
83 | #define TMRLUT_HW_CGC_EN (1 << 6) | ||
84 | #define OCSC_HW_CGC_EN (1 << 7) | ||
85 | |||
86 | #define REG_UFS_CFG2_CGC_EN_ALL (UAWM_HW_CGC_EN | UARM_HW_CGC_EN |\ | ||
87 | TXUC_HW_CGC_EN | RXUC_HW_CGC_EN |\ | ||
88 | DFC_HW_CGC_EN | TRLUT_HW_CGC_EN |\ | ||
89 | TMRLUT_HW_CGC_EN | OCSC_HW_CGC_EN) | ||
90 | |||
91 | /* bit offset */ | ||
92 | enum { | ||
93 | OFFSET_UFS_PHY_SOFT_RESET = 1, | ||
94 | OFFSET_CLK_NS_REG = 10, | ||
95 | }; | ||
96 | |||
97 | /* bit masks */ | ||
98 | enum { | ||
99 | MASK_UFS_PHY_SOFT_RESET = 0x2, | ||
100 | MASK_TX_SYMBOL_CLK_1US_REG = 0x3FF, | ||
101 | MASK_CLK_NS_REG = 0xFFFC00, | ||
102 | }; | ||
103 | |||
104 | enum ufs_qcom_phy_init_type { | ||
105 | UFS_PHY_INIT_FULL, | ||
106 | UFS_PHY_INIT_CFG_RESTORE, | ||
107 | }; | ||
108 | |||
109 | static inline void | ||
110 | ufs_qcom_get_controller_revision(struct ufs_hba *hba, | ||
111 | u8 *major, u16 *minor, u16 *step) | ||
112 | { | ||
113 | u32 ver = ufshcd_readl(hba, REG_UFS_HW_VERSION); | ||
114 | |||
115 | *major = (ver & UFS_HW_VER_MAJOR_MASK) >> UFS_HW_VER_MAJOR_SHFT; | ||
116 | *minor = (ver & UFS_HW_VER_MINOR_MASK) >> UFS_HW_VER_MINOR_SHFT; | ||
117 | *step = (ver & UFS_HW_VER_STEP_MASK) >> UFS_HW_VER_STEP_SHFT; | ||
118 | }; | ||
119 | |||
120 | static inline void ufs_qcom_assert_reset(struct ufs_hba *hba) | ||
121 | { | ||
122 | ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, | ||
123 | 1 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); | ||
124 | |||
125 | /* | ||
126 | * Make sure assertion of ufs phy reset is written to | ||
127 | * register before returning | ||
128 | */ | ||
129 | mb(); | ||
130 | } | ||
131 | |||
132 | static inline void ufs_qcom_deassert_reset(struct ufs_hba *hba) | ||
133 | { | ||
134 | ufshcd_rmwl(hba, MASK_UFS_PHY_SOFT_RESET, | ||
135 | 0 << OFFSET_UFS_PHY_SOFT_RESET, REG_UFS_CFG1); | ||
136 | |||
137 | /* | ||
138 | * Make sure de-assertion of ufs phy reset is written to | ||
139 | * register before returning | ||
140 | */ | ||
141 | mb(); | ||
142 | } | ||
143 | |||
144 | struct ufs_qcom_bus_vote { | ||
145 | uint32_t client_handle; | ||
146 | uint32_t curr_vote; | ||
147 | int min_bw_vote; | ||
148 | int max_bw_vote; | ||
149 | int saved_vote; | ||
150 | bool is_max_bw_needed; | ||
151 | struct device_attribute max_bus_bw; | ||
152 | }; | ||
153 | |||
154 | struct ufs_qcom_host { | ||
155 | struct phy *generic_phy; | ||
156 | struct ufs_hba *hba; | ||
157 | struct ufs_qcom_bus_vote bus_vote; | ||
158 | struct ufs_pa_layer_attr dev_req_params; | ||
159 | struct clk *rx_l0_sync_clk; | ||
160 | struct clk *tx_l0_sync_clk; | ||
161 | struct clk *rx_l1_sync_clk; | ||
162 | struct clk *tx_l1_sync_clk; | ||
163 | bool is_lane_clks_enabled; | ||
164 | }; | ||
165 | |||
166 | #define ufs_qcom_is_link_off(hba) ufshcd_is_link_off(hba) | ||
167 | #define ufs_qcom_is_link_active(hba) ufshcd_is_link_active(hba) | ||
168 | #define ufs_qcom_is_link_hibern8(hba) ufshcd_is_link_hibern8(hba) | ||
169 | |||
170 | #endif /* UFS_QCOM_H_ */ | ||