1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Synopsys G210 Test Chip driver 4 * 5 * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com) 6 * 7 * Authors: Joao Pinto <jpinto@synopsys.com> 8 */ 9 10#include "ufshcd.h" 11#include "unipro.h" 12 13#include "ufshcd-dwc.h" 14#include "ufshci-dwc.h" 15#include "tc-dwc-g210.h" 16 17/** 18 * tc_dwc_g210_setup_40bit_rmmi() 19 * This function configures Synopsys TC specific atributes (40-bit RMMI) 20 * @hba: Pointer to drivers structure 21 * 22 * Returns 0 on success or non-zero value on failure 23 */ 24static int tc_dwc_g210_setup_40bit_rmmi(struct ufs_hba *hba) 25{ 26 static const struct ufshcd_dme_attr_val setup_attrs[] = { 27 { UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL }, 28 { UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL }, 29 { UIC_ARG_MIB(CDIRECTCTRL6), 0x80, DME_LOCAL }, 30 { UIC_ARG_MIB(CBDIVFACTOR), 0x08, DME_LOCAL }, 31 { UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL }, 32 { UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL }, 33 { UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL }, 34 { UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01, 35 DME_LOCAL }, 36 { UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19, 37 DME_LOCAL }, 38 { UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x14, 39 DME_LOCAL }, 40 { UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6, 41 DME_LOCAL }, 42 { UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01, 43 DME_LOCAL }, 44 { UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19, 45 DME_LOCAL }, 46 { UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 4, 47 DME_LOCAL }, 48 { UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80, 49 DME_LOCAL }, 50 { UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL }, 51 { UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL }, 52 { UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80, 53 DME_LOCAL }, 54 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03, 55 DME_LOCAL }, 56 { UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16, 57 DME_LOCAL }, 58 { UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42, 59 DME_LOCAL }, 60 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4, 61 DME_LOCAL }, 62 { UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01, 63 DME_LOCAL }, 64 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01, 65 DME_LOCAL }, 66 { UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28, 67 DME_LOCAL }, 68 { UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E, 69 DME_LOCAL }, 70 { UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f, 71 DME_LOCAL }, 72 { UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f, 73 DME_LOCAL }, 74 { UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL }, 75 }; 76 77 return ufshcd_dwc_dme_set_attrs(hba, setup_attrs, 78 ARRAY_SIZE(setup_attrs)); 79} 80 81/** 82 * tc_dwc_g210_setup_20bit_rmmi_lane0() 83 * This function configures Synopsys TC 20-bit RMMI Lane 0 84 * @hba: Pointer to drivers structure 85 * 86 * Returns 0 on success or non-zero value on failure 87 */ 88static int tc_dwc_g210_setup_20bit_rmmi_lane0(struct ufs_hba *hba) 89{ 90 static const struct ufshcd_dme_attr_val setup_attrs[] = { 91 { UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN0_TX), 0x01, 92 DME_LOCAL }, 93 { UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN0_TX), 0x19, 94 DME_LOCAL }, 95 { UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN0_RX), 0x19, 96 DME_LOCAL }, 97 { UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN0_TX), 0x12, 98 DME_LOCAL }, 99 { UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6, 100 DME_LOCAL }, 101 { UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN0_RX), 0x01, 102 DME_LOCAL }, 103 { UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN0_RX), 2, 104 DME_LOCAL }, 105 { UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN0_RX), 0x80, 106 DME_LOCAL }, 107 { UIC_ARG_MIB(DIRECTCTRL10), 0x04, DME_LOCAL }, 108 { UIC_ARG_MIB(DIRECTCTRL19), 0x02, DME_LOCAL }, 109 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN0_RX), 0x03, 110 DME_LOCAL }, 111 { UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN0_RX), 0x16, 112 DME_LOCAL }, 113 { UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN0_RX), 0x42, 114 DME_LOCAL }, 115 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN0_RX), 0xa4, 116 DME_LOCAL }, 117 { UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN0_RX), 0x01, 118 DME_LOCAL }, 119 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN0_RX), 0x01, 120 DME_LOCAL }, 121 { UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN0_RX), 0x28, 122 DME_LOCAL }, 123 { UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN0_RX), 0x1E, 124 DME_LOCAL }, 125 { UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN0_RX), 0x2f, 126 DME_LOCAL }, 127 { UIC_ARG_MIB(CBPRGPLL2), 0x00, DME_LOCAL }, 128 }; 129 130 return ufshcd_dwc_dme_set_attrs(hba, setup_attrs, 131 ARRAY_SIZE(setup_attrs)); 132} 133 134/** 135 * tc_dwc_g210_setup_20bit_rmmi_lane1() 136 * This function configures Synopsys TC 20-bit RMMI Lane 1 137 * @hba: Pointer to drivers structure 138 * 139 * Returns 0 on success or non-zero value on failure 140 */ 141static int tc_dwc_g210_setup_20bit_rmmi_lane1(struct ufs_hba *hba) 142{ 143 int connected_rx_lanes = 0; 144 int connected_tx_lanes = 0; 145 int ret = 0; 146 147 static const struct ufshcd_dme_attr_val setup_tx_attrs[] = { 148 { UIC_ARG_MIB_SEL(TX_REFCLKFREQ, SELIND_LN1_TX), 0x0d, 149 DME_LOCAL }, 150 { UIC_ARG_MIB_SEL(TX_CFGCLKFREQVAL, SELIND_LN1_TX), 0x19, 151 DME_LOCAL }, 152 { UIC_ARG_MIB_SEL(CFGEXTRATTR, SELIND_LN1_TX), 0x12, 153 DME_LOCAL }, 154 { UIC_ARG_MIB_SEL(DITHERCTRL2, SELIND_LN0_TX), 0xd6, 155 DME_LOCAL }, 156 }; 157 158 static const struct ufshcd_dme_attr_val setup_rx_attrs[] = { 159 { UIC_ARG_MIB_SEL(RX_REFCLKFREQ, SELIND_LN1_RX), 0x01, 160 DME_LOCAL }, 161 { UIC_ARG_MIB_SEL(RX_CFGCLKFREQVAL, SELIND_LN1_RX), 0x19, 162 DME_LOCAL }, 163 { UIC_ARG_MIB_SEL(CFGWIDEINLN, SELIND_LN1_RX), 2, 164 DME_LOCAL }, 165 { UIC_ARG_MIB_SEL(CFGRXCDR8, SELIND_LN1_RX), 0x80, 166 DME_LOCAL }, 167 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG4, SELIND_LN1_RX), 0x03, 168 DME_LOCAL }, 169 { UIC_ARG_MIB_SEL(CFGRXOVR8, SELIND_LN1_RX), 0x16, 170 DME_LOCAL }, 171 { UIC_ARG_MIB_SEL(RXDIRECTCTRL2, SELIND_LN1_RX), 0x42, 172 DME_LOCAL }, 173 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG3, SELIND_LN1_RX), 0xa4, 174 DME_LOCAL }, 175 { UIC_ARG_MIB_SEL(RXCALCTRL, SELIND_LN1_RX), 0x01, 176 DME_LOCAL }, 177 { UIC_ARG_MIB_SEL(ENARXDIRECTCFG2, SELIND_LN1_RX), 0x01, 178 DME_LOCAL }, 179 { UIC_ARG_MIB_SEL(CFGRXOVR4, SELIND_LN1_RX), 0x28, 180 DME_LOCAL }, 181 { UIC_ARG_MIB_SEL(RXSQCTRL, SELIND_LN1_RX), 0x1E, 182 DME_LOCAL }, 183 { UIC_ARG_MIB_SEL(CFGRXOVR6, SELIND_LN1_RX), 0x2f, 184 DME_LOCAL }, 185 }; 186 187 /* Get the available lane count */ 188 ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILRXDATALANES), 189 &connected_rx_lanes); 190 ufshcd_dme_get(hba, UIC_ARG_MIB(PA_AVAILTXDATALANES), 191 &connected_tx_lanes); 192 193 if (connected_tx_lanes == 2) { 194 195 ret = ufshcd_dwc_dme_set_attrs(hba, setup_tx_attrs, 196 ARRAY_SIZE(setup_tx_attrs)); 197 198 if (ret) 199 goto out; 200 } 201 202 if (connected_rx_lanes == 2) { 203 ret = ufshcd_dwc_dme_set_attrs(hba, setup_rx_attrs, 204 ARRAY_SIZE(setup_rx_attrs)); 205 } 206 207out: 208 return ret; 209} 210 211/** 212 * tc_dwc_g210_setup_20bit_rmmi() 213 * This function configures Synopsys TC specific atributes (20-bit RMMI) 214 * @hba: Pointer to drivers structure 215 * 216 * Returns 0 on success or non-zero value on failure 217 */ 218static int tc_dwc_g210_setup_20bit_rmmi(struct ufs_hba *hba) 219{ 220 int ret = 0; 221 222 static const struct ufshcd_dme_attr_val setup_attrs[] = { 223 { UIC_ARG_MIB(TX_GLOBALHIBERNATE), 0x00, DME_LOCAL }, 224 { UIC_ARG_MIB(REFCLKMODE), 0x01, DME_LOCAL }, 225 { UIC_ARG_MIB(CDIRECTCTRL6), 0xc0, DME_LOCAL }, 226 { UIC_ARG_MIB(CBDIVFACTOR), 0x44, DME_LOCAL }, 227 { UIC_ARG_MIB(CBDCOCTRL5), 0x64, DME_LOCAL }, 228 { UIC_ARG_MIB(CBPRGTUNING), 0x09, DME_LOCAL }, 229 { UIC_ARG_MIB(RTOBSERVESELECT), 0x00, DME_LOCAL }, 230 }; 231 232 ret = ufshcd_dwc_dme_set_attrs(hba, setup_attrs, 233 ARRAY_SIZE(setup_attrs)); 234 if (ret) 235 goto out; 236 237 /* Lane 0 configuration*/ 238 ret = tc_dwc_g210_setup_20bit_rmmi_lane0(hba); 239 if (ret) 240 goto out; 241 242 /* Lane 1 configuration*/ 243 ret = tc_dwc_g210_setup_20bit_rmmi_lane1(hba); 244 if (ret) 245 goto out; 246 247out: 248 return ret; 249} 250 251/** 252 * tc_dwc_g210_config_40_bit() 253 * This function configures Local (host) Synopsys 40-bit TC specific attributes 254 * 255 * @hba: Pointer to drivers structure 256 * 257 * Returns 0 on success non-zero value on failure 258 */ 259int tc_dwc_g210_config_40_bit(struct ufs_hba *hba) 260{ 261 int ret = 0; 262 263 dev_info(hba->dev, "Configuring Test Chip 40-bit RMMI\n"); 264 ret = tc_dwc_g210_setup_40bit_rmmi(hba); 265 if (ret) { 266 dev_err(hba->dev, "Configuration failed\n"); 267 goto out; 268 } 269 270 /* To write Shadow register bank to effective configuration block */ 271 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); 272 if (ret) 273 goto out; 274 275 /* To configure Debug OMC */ 276 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01); 277 278out: 279 return ret; 280} 281EXPORT_SYMBOL(tc_dwc_g210_config_40_bit); 282 283/** 284 * tc_dwc_g210_config_20_bit() 285 * This function configures Local (host) Synopsys 20-bit TC specific attributes 286 * 287 * @hba: Pointer to drivers structure 288 * 289 * Returns 0 on success non-zero value on failure 290 */ 291int tc_dwc_g210_config_20_bit(struct ufs_hba *hba) 292{ 293 int ret = 0; 294 295 dev_info(hba->dev, "Configuring Test Chip 20-bit RMMI\n"); 296 ret = tc_dwc_g210_setup_20bit_rmmi(hba); 297 if (ret) { 298 dev_err(hba->dev, "Configuration failed\n"); 299 goto out; 300 } 301 302 /* To write Shadow register bank to effective configuration block */ 303 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_MPHYCFGUPDT), 0x01); 304 if (ret) 305 goto out; 306 307 /* To configure Debug OMC */ 308 ret = ufshcd_dme_set(hba, UIC_ARG_MIB(VS_DEBUGOMC), 0x01); 309 310out: 311 return ret; 312} 313EXPORT_SYMBOL(tc_dwc_g210_config_20_bit); 314 315MODULE_AUTHOR("Joao Pinto <Joao.Pinto@synopsys.com>"); 316MODULE_DESCRIPTION("Synopsys G210 Test Chip driver"); 317MODULE_LICENSE("Dual BSD/GPL"); 318