| 1 | |
| 2 | |
| 3 | * AppliedMicro X-Gene Multi-purpose PHY driver
|
| 4 | *
|
| 5 | * Copyright (c) 2014, Applied Micro Circuits Corporation
|
| 6 | * Author: Loc Ho <[email protected]>
|
| 7 | * Tuan Phan <[email protected]>
|
| 8 | * Suman Tripathi <[email protected]>
|
| 9 | *
|
| 10 | * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
|
| 11 | * The first PLL clock macro is used for internal reference clock. The second
|
| 12 | * PLL clock macro is used to generate the clock for the PHY. This driver
|
| 13 | * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
|
| 14 | * operate according to the mode of operation. The first PLL CMU is only
|
| 15 | * required if internal clock is enabled.
|
| 16 | *
|
| 17 | * Logical Layer Out Of HW module units:
|
| 18 | *
|
| 19 | * -----------------
|
| 20 | * | Internal | |------|
|
| 21 | * | Ref PLL CMU |----| | ------------- ---------
|
| 22 | * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes|
|
| 23 | * | | | | ---------
|
| 24 | * External Clock ------| | -------------
|
| 25 | * |------|
|
| 26 | *
|
| 27 | * The Ref PLL CMU CSR (Configuration System Registers) is accessed
|
| 28 | * indirectly from the SDS offset at 0x2000. It is only required for
|
| 29 | * internal reference clock.
|
| 30 | * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
|
| 31 | * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400.
|
| 32 | *
|
| 33 | * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
|
| 34 | * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
|
| 35 | * it is located outside the PHY IP. This is the case for the PHY located
|
| 36 | * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
|
| 37 | * to located the SDS/Ref PLL CMU module and its clock for that IP enabled.
|
| 38 | *
|
| 39 | * Currently, this driver only supports Gen3 SATA mode with external clock.
|
| 40 |
|
| 41 | #include <linux/module.h>
|
| 42 | #include <linux/of.h>
|
| 43 | #include <linux/platform_device.h>
|
| 44 | #include <linux/io.h>
|
| 45 | #include <linux/delay.h>
|
| 46 | #include <linux/phy/phy.h>
|
| 47 | #include <linux/clk.h>
|
| 48 |
|
| 49 |
|
| 50 | #define MAX_LANE 2
|
| 51 |
|
| 52 |
|
| 53 | #define SERDES_PLL_INDIRECT_OFFSET 0x0000
|
| 54 | #define SERDES_PLL_REF_INDIRECT_OFFSET 0x2000
|
| 55 | #define SERDES_INDIRECT_OFFSET 0x0400
|
| 56 | #define SERDES_LANE_STRIDE 0x0200
|
| 57 |
|
| 58 |
|
| 59 | #define DEFAULT_SATA_TXBOOST_GAIN { 0x1e, 0x1e, 0x1e }
|
| 60 | #define DEFAULT_SATA_TXEYEDIRECTION { 0x0, 0x0, 0x0 }
|
| 61 | #define DEFAULT_SATA_TXEYETUNING { 0xa, 0xa, 0xa }
|
| 62 | #define DEFAULT_SATA_SPD_SEL { 0x1, 0x3, 0x7 }
|
| 63 | #define DEFAULT_SATA_TXAMP { 0x8, 0x8, 0x8 }
|
| 64 | #define DEFAULT_SATA_TXCN1 { 0x2, 0x2, 0x2 }
|
| 65 | #define DEFAULT_SATA_TXCN2 { 0x0, 0x0, 0x0 }
|
| 66 | #define DEFAULT_SATA_TXCP1 { 0xa, 0xa, 0xa }
|
| 67 |
|
| 68 | #define SATA_SPD_SEL_GEN3 0x7
|
| 69 | #define SATA_SPD_SEL_GEN2 0x3
|
| 70 | #define SATA_SPD_SEL_GEN1 0x1
|
| 71 |
|
| 72 | #define SSC_DISABLE 0
|
| 73 | #define SSC_ENABLE 1
|
| 74 |
|
| 75 | #define FBDIV_VAL_50M 0x77
|
| 76 | #define REFDIV_VAL_50M 0x1
|
| 77 | #define FBDIV_VAL_100M 0x3B
|
| 78 | #define REFDIV_VAL_100M 0x0
|
| 79 |
|
| 80 |
|
| 81 | #define SATACLKENREG 0x00000000
|
| 82 | #define SATA0_CORE_CLKEN 0x00000002
|
| 83 | #define SATA1_CORE_CLKEN 0x00000004
|
| 84 | #define SATASRESETREG 0x00000004
|
| 85 | #define SATA_MEM_RESET_MASK 0x00000020
|
| 86 | #define SATA_MEM_RESET_RD(src) (((src) & 0x00000020) >> 5)
|
| 87 | #define SATA_SDS_RESET_MASK 0x00000004
|
| 88 | #define SATA_CSR_RESET_MASK 0x00000001
|
| 89 | #define SATA_CORE_RESET_MASK 0x00000002
|
| 90 | #define SATA_PMCLK_RESET_MASK 0x00000010
|
| 91 | #define SATA_PCLK_RESET_MASK 0x00000008
|
| 92 |
|
| 93 |
|
| 94 | #define SATA_ENET_SDS_PCS_CTL0 0x00000000
|
| 95 | #define REGSPEC_CFG_I_TX_WORDMODE0_SET(dst, src) \
|
| 96 | (((dst) & ~0x00070000) | (((u32) (src) << 16) & 0x00070000))
|
| 97 | #define REGSPEC_CFG_I_RX_WORDMODE0_SET(dst, src) \
|
| 98 | (((dst) & ~0x00e00000) | (((u32) (src) << 21) & 0x00e00000))
|
| 99 | #define SATA_ENET_SDS_CTL0 0x0000000c
|
| 100 | #define REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(dst, src) \
|
| 101 | (((dst) & ~0x00007fff) | (((u32) (src)) & 0x00007fff))
|
| 102 | #define SATA_ENET_SDS_CTL1 0x00000010
|
| 103 | #define CFG_I_SPD_SEL_CDR_OVR1_SET(dst, src) \
|
| 104 | (((dst) & ~0x0000000f) | (((u32) (src)) & 0x0000000f))
|
| 105 | #define SATA_ENET_SDS_RST_CTL 0x00000024
|
| 106 | #define SATA_ENET_SDS_IND_CMD_REG 0x0000003c
|
| 107 | #define CFG_IND_WR_CMD_MASK 0x00000001
|
| 108 | #define CFG_IND_RD_CMD_MASK 0x00000002
|
| 109 | #define CFG_IND_CMD_DONE_MASK 0x00000004
|
| 110 | #define CFG_IND_ADDR_SET(dst, src) \
|
| 111 | (((dst) & ~0x003ffff0) | (((u32) (src) << 4) & 0x003ffff0))
|
| 112 | #define SATA_ENET_SDS_IND_RDATA_REG 0x00000040
|
| 113 | #define SATA_ENET_SDS_IND_WDATA_REG 0x00000044
|
| 114 | #define SATA_ENET_CLK_MACRO_REG 0x0000004c
|
| 115 | #define I_RESET_B_SET(dst, src) \
|
| 116 | (((dst) & ~0x00000001) | (((u32) (src)) & 0x00000001))
|
| 117 | #define I_PLL_FBDIV_SET(dst, src) \
|
| 118 | (((dst) & ~0x001ff000) | (((u32) (src) << 12) & 0x001ff000))
|
| 119 | #define I_CUSTOMEROV_SET(dst, src) \
|
| 120 | (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
|
| 121 | #define O_PLL_LOCK_RD(src) (((src) & 0x40000000) >> 30)
|
| 122 | #define O_PLL_READY_RD(src) (((src) & 0x80000000) >> 31)
|
| 123 |
|
| 124 |
|
| 125 | #define CMU_REG0 0x00000
|
| 126 | #define CMU_REG0_PLL_REF_SEL_MASK 0x00002000
|
| 127 | #define CMU_REG0_PLL_REF_SEL_SET(dst, src) \
|
| 128 | (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
|
| 129 | #define CMU_REG0_PDOWN_MASK 0x00004000
|
| 130 | #define CMU_REG0_CAL_COUNT_RESOL_SET(dst, src) \
|
| 131 | (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
|
| 132 | #define CMU_REG1 0x00002
|
| 133 | #define CMU_REG1_PLL_CP_SET(dst, src) \
|
| 134 | (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
|
| 135 | #define CMU_REG1_PLL_MANUALCAL_SET(dst, src) \
|
| 136 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 137 | #define CMU_REG1_PLL_CP_SEL_SET(dst, src) \
|
| 138 | (((dst) & ~0x000003e0) | (((u32) (src) << 5) & 0x000003e0))
|
| 139 | #define CMU_REG1_REFCLK_CMOS_SEL_MASK 0x00000001
|
| 140 | #define CMU_REG1_REFCLK_CMOS_SEL_SET(dst, src) \
|
| 141 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
|
| 142 | #define CMU_REG2 0x00004
|
| 143 | #define CMU_REG2_PLL_REFDIV_SET(dst, src) \
|
| 144 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
|
| 145 | #define CMU_REG2_PLL_LFRES_SET(dst, src) \
|
| 146 | (((dst) & ~0x0000001e) | (((u32) (src) << 1) & 0x0000001e))
|
| 147 | #define CMU_REG2_PLL_FBDIV_SET(dst, src) \
|
| 148 | (((dst) & ~0x00003fe0) | (((u32) (src) << 5) & 0x00003fe0))
|
| 149 | #define CMU_REG3 0x00006
|
| 150 | #define CMU_REG3_VCOVARSEL_SET(dst, src) \
|
| 151 | (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
|
| 152 | #define CMU_REG3_VCO_MOMSEL_INIT_SET(dst, src) \
|
| 153 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
|
| 154 | #define CMU_REG3_VCO_MANMOMSEL_SET(dst, src) \
|
| 155 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
|
| 156 | #define CMU_REG4 0x00008
|
| 157 | #define CMU_REG5 0x0000a
|
| 158 | #define CMU_REG5_PLL_LFSMCAP_SET(dst, src) \
|
| 159 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
|
| 160 | #define CMU_REG5_PLL_LOCK_RESOLUTION_SET(dst, src) \
|
| 161 | (((dst) & ~0x0000000e) | (((u32) (src) << 1) & 0x0000000e))
|
| 162 | #define CMU_REG5_PLL_LFCAP_SET(dst, src) \
|
| 163 | (((dst) & ~0x00003000) | (((u32) (src) << 12) & 0x00003000))
|
| 164 | #define CMU_REG5_PLL_RESETB_MASK 0x00000001
|
| 165 | #define CMU_REG6 0x0000c
|
| 166 | #define CMU_REG6_PLL_VREGTRIM_SET(dst, src) \
|
| 167 | (((dst) & ~0x00000600) | (((u32) (src) << 9) & 0x00000600))
|
| 168 | #define CMU_REG6_MAN_PVT_CAL_SET(dst, src) \
|
| 169 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
|
| 170 | #define CMU_REG7 0x0000e
|
| 171 | #define CMU_REG7_PLL_CALIB_DONE_RD(src) ((0x00004000 & (u32) (src)) >> 14)
|
| 172 | #define CMU_REG7_VCO_CAL_FAIL_RD(src) ((0x00000c00 & (u32) (src)) >> 10)
|
| 173 | #define CMU_REG8 0x00010
|
| 174 | #define CMU_REG9 0x00012
|
| 175 | #define CMU_REG9_WORD_LEN_8BIT 0x000
|
| 176 | #define CMU_REG9_WORD_LEN_10BIT 0x001
|
| 177 | #define CMU_REG9_WORD_LEN_16BIT 0x002
|
| 178 | #define CMU_REG9_WORD_LEN_20BIT 0x003
|
| 179 | #define CMU_REG9_WORD_LEN_32BIT 0x004
|
| 180 | #define CMU_REG9_WORD_LEN_40BIT 0x005
|
| 181 | #define CMU_REG9_WORD_LEN_64BIT 0x006
|
| 182 | #define CMU_REG9_WORD_LEN_66BIT 0x007
|
| 183 | #define CMU_REG9_TX_WORD_MODE_CH1_SET(dst, src) \
|
| 184 | (((dst) & ~0x00000380) | (((u32) (src) << 7) & 0x00000380))
|
| 185 | #define CMU_REG9_TX_WORD_MODE_CH0_SET(dst, src) \
|
| 186 | (((dst) & ~0x00000070) | (((u32) (src) << 4) & 0x00000070))
|
| 187 | #define CMU_REG9_PLL_POST_DIVBY2_SET(dst, src) \
|
| 188 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 189 | #define CMU_REG9_VBG_BYPASSB_SET(dst, src) \
|
| 190 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
|
| 191 | #define CMU_REG9_IGEN_BYPASS_SET(dst, src) \
|
| 192 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 193 | #define CMU_REG10 0x00014
|
| 194 | #define CMU_REG10_VREG_REFSEL_SET(dst, src) \
|
| 195 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
|
| 196 | #define CMU_REG11 0x00016
|
| 197 | #define CMU_REG12 0x00018
|
| 198 | #define CMU_REG12_STATE_DELAY9_SET(dst, src) \
|
| 199 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
|
| 200 | #define CMU_REG13 0x0001a
|
| 201 | #define CMU_REG14 0x0001c
|
| 202 | #define CMU_REG15 0x0001e
|
| 203 | #define CMU_REG16 0x00020
|
| 204 | #define CMU_REG16_PVT_DN_MAN_ENA_MASK 0x00000001
|
| 205 | #define CMU_REG16_PVT_UP_MAN_ENA_MASK 0x00000002
|
| 206 | #define CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(dst, src) \
|
| 207 | (((dst) & ~0x0000001c) | (((u32) (src) << 2) & 0x0000001c))
|
| 208 | #define CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(dst, src) \
|
| 209 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
|
| 210 | #define CMU_REG16_BYPASS_PLL_LOCK_SET(dst, src) \
|
| 211 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
|
| 212 | #define CMU_REG17 0x00022
|
| 213 | #define CMU_REG17_PVT_CODE_R2A_SET(dst, src) \
|
| 214 | (((dst) & ~0x00007f00) | (((u32) (src) << 8) & 0x00007f00))
|
| 215 | #define CMU_REG17_RESERVED_7_SET(dst, src) \
|
| 216 | (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
|
| 217 | #define CMU_REG17_PVT_TERM_MAN_ENA_MASK 0x00008000
|
| 218 | #define CMU_REG18 0x00024
|
| 219 | #define CMU_REG19 0x00026
|
| 220 | #define CMU_REG20 0x00028
|
| 221 | #define CMU_REG21 0x0002a
|
| 222 | #define CMU_REG22 0x0002c
|
| 223 | #define CMU_REG23 0x0002e
|
| 224 | #define CMU_REG24 0x00030
|
| 225 | #define CMU_REG25 0x00032
|
| 226 | #define CMU_REG26 0x00034
|
| 227 | #define CMU_REG26_FORCE_PLL_LOCK_SET(dst, src) \
|
| 228 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
|
| 229 | #define CMU_REG27 0x00036
|
| 230 | #define CMU_REG28 0x00038
|
| 231 | #define CMU_REG29 0x0003a
|
| 232 | #define CMU_REG30 0x0003c
|
| 233 | #define CMU_REG30_LOCK_COUNT_SET(dst, src) \
|
| 234 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
|
| 235 | #define CMU_REG30_PCIE_MODE_SET(dst, src) \
|
| 236 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 237 | #define CMU_REG31 0x0003e
|
| 238 | #define CMU_REG32 0x00040
|
| 239 | #define CMU_REG32_FORCE_VCOCAL_START_MASK 0x00004000
|
| 240 | #define CMU_REG32_PVT_CAL_WAIT_SEL_SET(dst, src) \
|
| 241 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
|
| 242 | #define CMU_REG32_IREF_ADJ_SET(dst, src) \
|
| 243 | (((dst) & ~0x00000180) | (((u32) (src) << 7) & 0x00000180))
|
| 244 | #define CMU_REG33 0x00042
|
| 245 | #define CMU_REG34 0x00044
|
| 246 | #define CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(dst, src) \
|
| 247 | (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
|
| 248 | #define CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(dst, src) \
|
| 249 | (((dst) & ~0x00000f00) | (((u32) (src) << 8) & 0x00000f00))
|
| 250 | #define CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(dst, src) \
|
| 251 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
|
| 252 | #define CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(dst, src) \
|
| 253 | (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
|
| 254 | #define CMU_REG35 0x00046
|
| 255 | #define CMU_REG35_PLL_SSC_MOD_SET(dst, src) \
|
| 256 | (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
|
| 257 | #define CMU_REG36 0x00048
|
| 258 | #define CMU_REG36_PLL_SSC_EN_SET(dst, src) \
|
| 259 | (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
|
| 260 | #define CMU_REG36_PLL_SSC_VSTEP_SET(dst, src) \
|
| 261 | (((dst) & ~0x0000ffc0) | (((u32) (src) << 6) & 0x0000ffc0))
|
| 262 | #define CMU_REG36_PLL_SSC_DSMSEL_SET(dst, src) \
|
| 263 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
|
| 264 | #define CMU_REG37 0x0004a
|
| 265 | #define CMU_REG38 0x0004c
|
| 266 | #define CMU_REG39 0x0004e
|
| 267 |
|
| 268 |
|
| 269 | #define RXTX_REG0 0x000
|
| 270 | #define RXTX_REG0_CTLE_EQ_HR_SET(dst, src) \
|
| 271 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 272 | #define RXTX_REG0_CTLE_EQ_QR_SET(dst, src) \
|
| 273 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
|
| 274 | #define RXTX_REG0_CTLE_EQ_FR_SET(dst, src) \
|
| 275 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
|
| 276 | #define RXTX_REG1 0x002
|
| 277 | #define RXTX_REG1_RXACVCM_SET(dst, src) \
|
| 278 | (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
|
| 279 | #define RXTX_REG1_CTLE_EQ_SET(dst, src) \
|
| 280 | (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
|
| 281 | #define RXTX_REG1_RXVREG1_SET(dst, src) \
|
| 282 | (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
|
| 283 | #define RXTX_REG1_RXIREF_ADJ_SET(dst, src) \
|
| 284 | (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
|
| 285 | #define RXTX_REG2 0x004
|
| 286 | #define RXTX_REG2_VTT_ENA_SET(dst, src) \
|
| 287 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
|
| 288 | #define RXTX_REG2_TX_FIFO_ENA_SET(dst, src) \
|
| 289 | (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
|
| 290 | #define RXTX_REG2_VTT_SEL_SET(dst, src) \
|
| 291 | (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
|
| 292 | #define RXTX_REG4 0x008
|
| 293 | #define RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK 0x00000040
|
| 294 | #define RXTX_REG4_TX_DATA_RATE_SET(dst, src) \
|
| 295 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
|
| 296 | #define RXTX_REG4_TX_WORD_MODE_SET(dst, src) \
|
| 297 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
|
| 298 | #define RXTX_REG5 0x00a
|
| 299 | #define RXTX_REG5_TX_CN1_SET(dst, src) \
|
| 300 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 301 | #define RXTX_REG5_TX_CP1_SET(dst, src) \
|
| 302 | (((dst) & ~0x000007e0) | (((u32) (src) << 5) & 0x000007e0))
|
| 303 | #define RXTX_REG5_TX_CN2_SET(dst, src) \
|
| 304 | (((dst) & ~0x0000001f) | (((u32) (src) << 0) & 0x0000001f))
|
| 305 | #define RXTX_REG6 0x00c
|
| 306 | #define RXTX_REG6_TXAMP_CNTL_SET(dst, src) \
|
| 307 | (((dst) & ~0x00000780) | (((u32) (src) << 7) & 0x00000780))
|
| 308 | #define RXTX_REG6_TXAMP_ENA_SET(dst, src) \
|
| 309 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
|
| 310 | #define RXTX_REG6_RX_BIST_ERRCNT_RD_SET(dst, src) \
|
| 311 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
|
| 312 | #define RXTX_REG6_TX_IDLE_SET(dst, src) \
|
| 313 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 314 | #define RXTX_REG6_RX_BIST_RESYNC_SET(dst, src) \
|
| 315 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 316 | #define RXTX_REG7 0x00e
|
| 317 | #define RXTX_REG7_RESETB_RXD_MASK 0x00000100
|
| 318 | #define RXTX_REG7_RESETB_RXA_MASK 0x00000080
|
| 319 | #define RXTX_REG7_BIST_ENA_RX_SET(dst, src) \
|
| 320 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
|
| 321 | #define RXTX_REG7_RX_WORD_MODE_SET(dst, src) \
|
| 322 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
|
| 323 | #define RXTX_REG8 0x010
|
| 324 | #define RXTX_REG8_CDR_LOOP_ENA_SET(dst, src) \
|
| 325 | (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
|
| 326 | #define RXTX_REG8_CDR_BYPASS_RXLOS_SET(dst, src) \
|
| 327 | (((dst) & ~0x00000800) | (((u32) (src) << 11) & 0x00000800))
|
| 328 | #define RXTX_REG8_SSC_ENABLE_SET(dst, src) \
|
| 329 | (((dst) & ~0x00000200) | (((u32) (src) << 9) & 0x00000200))
|
| 330 | #define RXTX_REG8_SD_VREF_SET(dst, src) \
|
| 331 | (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
|
| 332 | #define RXTX_REG8_SD_DISABLE_SET(dst, src) \
|
| 333 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
|
| 334 | #define RXTX_REG7 0x00e
|
| 335 | #define RXTX_REG7_RESETB_RXD_SET(dst, src) \
|
| 336 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
|
| 337 | #define RXTX_REG7_RESETB_RXA_SET(dst, src) \
|
| 338 | (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
|
| 339 | #define RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK 0x00004000
|
| 340 | #define RXTX_REG7_LOOP_BACK_ENA_CTLE_SET(dst, src) \
|
| 341 | (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
|
| 342 | #define RXTX_REG11 0x016
|
| 343 | #define RXTX_REG11_PHASE_ADJUST_LIMIT_SET(dst, src) \
|
| 344 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 345 | #define RXTX_REG12 0x018
|
| 346 | #define RXTX_REG12_LATCH_OFF_ENA_SET(dst, src) \
|
| 347 | (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
|
| 348 | #define RXTX_REG12_SUMOS_ENABLE_SET(dst, src) \
|
| 349 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
|
| 350 | #define RXTX_REG12_RX_DET_TERM_ENABLE_MASK 0x00000002
|
| 351 | #define RXTX_REG12_RX_DET_TERM_ENABLE_SET(dst, src) \
|
| 352 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 353 | #define RXTX_REG13 0x01a
|
| 354 | #define RXTX_REG14 0x01c
|
| 355 | #define RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(dst, src) \
|
| 356 | (((dst) & ~0x0000003f) | (((u32) (src) << 0) & 0x0000003f))
|
| 357 | #define RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(dst, src) \
|
| 358 | (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
|
| 359 | #define RXTX_REG26 0x034
|
| 360 | #define RXTX_REG26_PERIOD_ERROR_LATCH_SET(dst, src) \
|
| 361 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
|
| 362 | #define RXTX_REG26_BLWC_ENA_SET(dst, src) \
|
| 363 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 364 | #define RXTX_REG21 0x02a
|
| 365 | #define RXTX_REG21_DO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
|
| 366 | #define RXTX_REG21_XO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
|
| 367 | #define RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(src) ((0x0000000f & (u32)(src)))
|
| 368 | #define RXTX_REG22 0x02c
|
| 369 | #define RXTX_REG22_SO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
|
| 370 | #define RXTX_REG22_EO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
|
| 371 | #define RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(src) ((0x0000000f & (u32)(src)))
|
| 372 | #define RXTX_REG23 0x02e
|
| 373 | #define RXTX_REG23_DE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
|
| 374 | #define RXTX_REG23_XE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
|
| 375 | #define RXTX_REG24 0x030
|
| 376 | #define RXTX_REG24_EE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
|
| 377 | #define RXTX_REG24_SE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
|
| 378 | #define RXTX_REG27 0x036
|
| 379 | #define RXTX_REG28 0x038
|
| 380 | #define RXTX_REG31 0x03e
|
| 381 | #define RXTX_REG38 0x04c
|
| 382 | #define RXTX_REG38_CUSTOMER_PINMODE_INV_SET(dst, src) \
|
| 383 | (((dst) & 0x0000fffe) | (((u32) (src) << 1) & 0x0000fffe))
|
| 384 | #define RXTX_REG39 0x04e
|
| 385 | #define RXTX_REG40 0x050
|
| 386 | #define RXTX_REG41 0x052
|
| 387 | #define RXTX_REG42 0x054
|
| 388 | #define RXTX_REG43 0x056
|
| 389 | #define RXTX_REG44 0x058
|
| 390 | #define RXTX_REG45 0x05a
|
| 391 | #define RXTX_REG46 0x05c
|
| 392 | #define RXTX_REG47 0x05e
|
| 393 | #define RXTX_REG48 0x060
|
| 394 | #define RXTX_REG49 0x062
|
| 395 | #define RXTX_REG50 0x064
|
| 396 | #define RXTX_REG51 0x066
|
| 397 | #define RXTX_REG52 0x068
|
| 398 | #define RXTX_REG53 0x06a
|
| 399 | #define RXTX_REG54 0x06c
|
| 400 | #define RXTX_REG55 0x06e
|
| 401 | #define RXTX_REG61 0x07a
|
| 402 | #define RXTX_REG61_ISCAN_INBERT_SET(dst, src) \
|
| 403 | (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
|
| 404 | #define RXTX_REG61_LOADFREQ_SHIFT_SET(dst, src) \
|
| 405 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 406 | #define RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(dst, src) \
|
| 407 | (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
|
| 408 | #define RXTX_REG61_SPD_SEL_CDR_SET(dst, src) \
|
| 409 | (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
|
| 410 | #define RXTX_REG62 0x07c
|
| 411 | #define RXTX_REG62_PERIOD_H1_QLATCH_SET(dst, src) \
|
| 412 | (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
|
| 413 | #define RXTX_REG81 0x0a2
|
| 414 | #define RXTX_REG89_MU_TH7_SET(dst, src) \
|
| 415 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 416 | #define RXTX_REG89_MU_TH8_SET(dst, src) \
|
| 417 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
|
| 418 | #define RXTX_REG89_MU_TH9_SET(dst, src) \
|
| 419 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
|
| 420 | #define RXTX_REG96 0x0c0
|
| 421 | #define RXTX_REG96_MU_FREQ1_SET(dst, src) \
|
| 422 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 423 | #define RXTX_REG96_MU_FREQ2_SET(dst, src) \
|
| 424 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
|
| 425 | #define RXTX_REG96_MU_FREQ3_SET(dst, src) \
|
| 426 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
|
| 427 | #define RXTX_REG99 0x0c6
|
| 428 | #define RXTX_REG99_MU_PHASE1_SET(dst, src) \
|
| 429 | (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
|
| 430 | #define RXTX_REG99_MU_PHASE2_SET(dst, src) \
|
| 431 | (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
|
| 432 | #define RXTX_REG99_MU_PHASE3_SET(dst, src) \
|
| 433 | (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
|
| 434 | #define RXTX_REG102 0x0cc
|
| 435 | #define RXTX_REG102_FREQLOOP_LIMIT_SET(dst, src) \
|
| 436 | (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
|
| 437 | #define RXTX_REG114 0x0e4
|
| 438 | #define RXTX_REG121 0x0f2
|
| 439 | #define RXTX_REG121_SUMOS_CAL_CODE_RD(src) ((0x0000003e & (u32)(src)) >> 0x1)
|
| 440 | #define RXTX_REG125 0x0fa
|
| 441 | #define RXTX_REG125_PQ_REG_SET(dst, src) \
|
| 442 | (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
|
| 443 | #define RXTX_REG125_SIGN_PQ_SET(dst, src) \
|
| 444 | (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
|
| 445 | #define RXTX_REG125_SIGN_PQ_2C_SET(dst, src) \
|
| 446 | (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
|
| 447 | #define RXTX_REG125_PHZ_MANUALCODE_SET(dst, src) \
|
| 448 | (((dst) & ~0x0000007c) | (((u32) (src) << 2) & 0x0000007c))
|
| 449 | #define RXTX_REG125_PHZ_MANUAL_SET(dst, src) \
|
| 450 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 451 | #define RXTX_REG127 0x0fe
|
| 452 | #define RXTX_REG127_FORCE_SUM_CAL_START_MASK 0x00000002
|
| 453 | #define RXTX_REG127_FORCE_LAT_CAL_START_MASK 0x00000004
|
| 454 | #define RXTX_REG127_FORCE_SUM_CAL_START_SET(dst, src) \
|
| 455 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 456 | #define RXTX_REG127_FORCE_LAT_CAL_START_SET(dst, src) \
|
| 457 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
|
| 458 | #define RXTX_REG127_LATCH_MAN_CAL_ENA_SET(dst, src) \
|
| 459 | (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
|
| 460 | #define RXTX_REG127_DO_LATCH_MANCAL_SET(dst, src) \
|
| 461 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
|
| 462 | #define RXTX_REG127_XO_LATCH_MANCAL_SET(dst, src) \
|
| 463 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
|
| 464 | #define RXTX_REG128 0x100
|
| 465 | #define RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(dst, src) \
|
| 466 | (((dst) & ~0x0000000c) | (((u32) (src) << 2) & 0x0000000c))
|
| 467 | #define RXTX_REG128_EO_LATCH_MANCAL_SET(dst, src) \
|
| 468 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
|
| 469 | #define RXTX_REG128_SO_LATCH_MANCAL_SET(dst, src) \
|
| 470 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
|
| 471 | #define RXTX_REG129 0x102
|
| 472 | #define RXTX_REG129_DE_LATCH_MANCAL_SET(dst, src) \
|
| 473 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
|
| 474 | #define RXTX_REG129_XE_LATCH_MANCAL_SET(dst, src) \
|
| 475 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
|
| 476 | #define RXTX_REG130 0x104
|
| 477 | #define RXTX_REG130_EE_LATCH_MANCAL_SET(dst, src) \
|
| 478 | (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
|
| 479 | #define RXTX_REG130_SE_LATCH_MANCAL_SET(dst, src) \
|
| 480 | (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
|
| 481 | #define RXTX_REG145 0x122
|
| 482 | #define RXTX_REG145_TX_IDLE_SATA_SET(dst, src) \
|
| 483 | (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
|
| 484 | #define RXTX_REG145_RXES_ENA_SET(dst, src) \
|
| 485 | (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
|
| 486 | #define RXTX_REG145_RXDFE_CONFIG_SET(dst, src) \
|
| 487 | (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
|
| 488 | #define RXTX_REG145_RXVWES_LATENA_SET(dst, src) \
|
| 489 | (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
|
| 490 | #define RXTX_REG147 0x126
|
| 491 | #define RXTX_REG148 0x128
|
| 492 |
|
| 493 |
|
| 494 | enum cmu_type_t {
|
| 495 | REF_CMU = 0,
|
| 496 | PHY_CMU = 1,
|
| 497 | };
|
| 498 |
|
| 499 | enum mux_type_t {
|
| 500 | MUX_SELECT_ATA = 0,
|
| 501 | MUX_SELECT_SGMMII = 0,
|
| 502 | };
|
| 503 |
|
| 504 | enum clk_type_t {
|
| 505 | CLK_EXT_DIFF = 0,
|
| 506 | CLK_INT_DIFF = 1,
|
| 507 | CLK_INT_SING = 2,
|
| 508 | };
|
| 509 |
|
| 510 | enum xgene_phy_mode {
|
| 511 | MODE_SATA = 0,
|
| 512 | MODE_SGMII = 1,
|
| 513 | MODE_PCIE = 2,
|
| 514 | MODE_USB = 3,
|
| 515 | MODE_XFI = 4,
|
| 516 | MODE_MAX
|
| 517 | };
|
| 518 |
|
| 519 | struct xgene_sata_override_param {
|
| 520 | u32 speed[MAX_LANE];
|
| 521 | u32 txspeed[3];
|
| 522 | u32 txboostgain[MAX_LANE*3];
|
| 523 | u32 txeyetuning[MAX_LANE*3];
|
| 524 | u32 txeyedirection[MAX_LANE*3];
|
| 525 | u32 txamplitude[MAX_LANE*3];
|
| 526 | u32 txprecursor_cn1[MAX_LANE*3];
|
| 527 | u32 txprecursor_cn2[MAX_LANE*3];
|
| 528 | u32 txpostcursor_cp1[MAX_LANE*3];
|
| 529 | };
|
| 530 |
|
| 531 | struct xgene_phy_ctx {
|
| 532 | struct device *dev;
|
| 533 | struct phy *phy;
|
| 534 | enum xgene_phy_mode mode;
|
| 535 | enum clk_type_t clk_type;
|
| 536 | void __iomem *sds_base;
|
| 537 | struct clk *clk;
|
| 538 |
|
| 539 |
|
| 540 | struct xgene_sata_override_param sata_param;
|
| 541 | };
|
| 542 |
|
| 543 | |
| 544 | * For chip earlier than A3 version, enable this flag.
|
| 545 | * To enable, pass boot argument phy_xgene.preA3Chip=1
|
| 546 |
|
| 547 | static int preA3Chip;
|
| 548 | MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)");
|
| 549 | module_param_named(preA3Chip, preA3Chip, int, 0444);
|
| 550 |
|
| 551 | static void sds_wr(void __iomem *csr_base, u32 indirect_cmd_reg,
|
| 552 | u32 indirect_data_reg, u32 addr, u32 data)
|
| 553 | {
|
| 554 | unsigned long deadline = jiffies + HZ;
|
| 555 | u32 val;
|
| 556 | u32 cmd;
|
| 557 |
|
| 558 | cmd = CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK;
|
| 559 | cmd = CFG_IND_ADDR_SET(cmd, addr);
|
| 560 | writel(data, csr_base + indirect_data_reg);
|
| 561 | readl(csr_base + indirect_data_reg);
|
| 562 | writel(cmd, csr_base + indirect_cmd_reg);
|
| 563 | readl(csr_base + indirect_cmd_reg);
|
| 564 | do {
|
| 565 | val = readl(csr_base + indirect_cmd_reg);
|
| 566 | } while (!(val & CFG_IND_CMD_DONE_MASK) &&
|
| 567 | time_before(jiffies, deadline));
|
| 568 | if (!(val & CFG_IND_CMD_DONE_MASK))
|
| 569 | pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
|
| 570 | csr_base + indirect_cmd_reg, addr, data);
|
| 571 | }
|
| 572 |
|
| 573 | static void sds_rd(void __iomem *csr_base, u32 indirect_cmd_reg,
|
| 574 | u32 indirect_data_reg, u32 addr, u32 *data)
|
| 575 | {
|
| 576 | unsigned long deadline = jiffies + HZ;
|
| 577 | u32 val;
|
| 578 | u32 cmd;
|
| 579 |
|
| 580 | cmd = CFG_IND_RD_CMD_MASK | CFG_IND_CMD_DONE_MASK;
|
| 581 | cmd = CFG_IND_ADDR_SET(cmd, addr);
|
| 582 | writel(cmd, csr_base + indirect_cmd_reg);
|
| 583 | readl(csr_base + indirect_cmd_reg);
|
| 584 | do {
|
| 585 | val = readl(csr_base + indirect_cmd_reg);
|
| 586 | } while (!(val & CFG_IND_CMD_DONE_MASK) &&
|
| 587 | time_before(jiffies, deadline));
|
| 588 | *data = readl(csr_base + indirect_data_reg);
|
| 589 | if (!(val & CFG_IND_CMD_DONE_MASK))
|
| 590 | pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
|
| 591 | csr_base + indirect_cmd_reg, addr, *data);
|
| 592 | }
|
| 593 |
|
| 594 | static void cmu_wr(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
|
| 595 | u32 reg, u32 data)
|
| 596 | {
|
| 597 | void __iomem *sds_base = ctx->sds_base;
|
| 598 | u32 val;
|
| 599 |
|
| 600 | if (cmu_type == REF_CMU)
|
| 601 | reg += SERDES_PLL_REF_INDIRECT_OFFSET;
|
| 602 | else
|
| 603 | reg += SERDES_PLL_INDIRECT_OFFSET;
|
| 604 | sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 605 | SATA_ENET_SDS_IND_WDATA_REG, reg, data);
|
| 606 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 607 | SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
|
| 608 | pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val);
|
| 609 | }
|
| 610 |
|
| 611 | static void cmu_rd(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
|
| 612 | u32 reg, u32 *data)
|
| 613 | {
|
| 614 | void __iomem *sds_base = ctx->sds_base;
|
| 615 |
|
| 616 | if (cmu_type == REF_CMU)
|
| 617 | reg += SERDES_PLL_REF_INDIRECT_OFFSET;
|
| 618 | else
|
| 619 | reg += SERDES_PLL_INDIRECT_OFFSET;
|
| 620 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 621 | SATA_ENET_SDS_IND_RDATA_REG, reg, data);
|
| 622 | pr_debug("CMU RD addr 0x%X value 0x%08X\n", reg, *data);
|
| 623 | }
|
| 624 |
|
| 625 | static void cmu_toggle1to0(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
|
| 626 | u32 reg, u32 bits)
|
| 627 | {
|
| 628 | u32 val;
|
| 629 |
|
| 630 | cmu_rd(ctx, cmu_type, reg, &val);
|
| 631 | val |= bits;
|
| 632 | cmu_wr(ctx, cmu_type, reg, val);
|
| 633 | cmu_rd(ctx, cmu_type, reg, &val);
|
| 634 | val &= ~bits;
|
| 635 | cmu_wr(ctx, cmu_type, reg, val);
|
| 636 | }
|
| 637 |
|
| 638 | static void cmu_clrbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
|
| 639 | u32 reg, u32 bits)
|
| 640 | {
|
| 641 | u32 val;
|
| 642 |
|
| 643 | cmu_rd(ctx, cmu_type, reg, &val);
|
| 644 | val &= ~bits;
|
| 645 | cmu_wr(ctx, cmu_type, reg, val);
|
| 646 | }
|
| 647 |
|
| 648 | static void cmu_setbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
|
| 649 | u32 reg, u32 bits)
|
| 650 | {
|
| 651 | u32 val;
|
| 652 |
|
| 653 | cmu_rd(ctx, cmu_type, reg, &val);
|
| 654 | val |= bits;
|
| 655 | cmu_wr(ctx, cmu_type, reg, val);
|
| 656 | }
|
| 657 |
|
| 658 | static void serdes_wr(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 data)
|
| 659 | {
|
| 660 | void __iomem *sds_base = ctx->sds_base;
|
| 661 | u32 val;
|
| 662 |
|
| 663 | reg += SERDES_INDIRECT_OFFSET;
|
| 664 | reg += lane * SERDES_LANE_STRIDE;
|
| 665 | sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 666 | SATA_ENET_SDS_IND_WDATA_REG, reg, data);
|
| 667 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 668 | SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
|
| 669 | pr_debug("SERDES WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data,
|
| 670 | val);
|
| 671 | }
|
| 672 |
|
| 673 | static void serdes_rd(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 *data)
|
| 674 | {
|
| 675 | void __iomem *sds_base = ctx->sds_base;
|
| 676 |
|
| 677 | reg += SERDES_INDIRECT_OFFSET;
|
| 678 | reg += lane * SERDES_LANE_STRIDE;
|
| 679 | sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
|
| 680 | SATA_ENET_SDS_IND_RDATA_REG, reg, data);
|
| 681 | pr_debug("SERDES RD addr 0x%X value 0x%08X\n", reg, *data);
|
| 682 | }
|
| 683 |
|
| 684 | static void serdes_clrbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
|
| 685 | u32 bits)
|
| 686 | {
|
| 687 | u32 val;
|
| 688 |
|
| 689 | serdes_rd(ctx, lane, reg, &val);
|
| 690 | val &= ~bits;
|
| 691 | serdes_wr(ctx, lane, reg, val);
|
| 692 | }
|
| 693 |
|
| 694 | static void serdes_setbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
|
| 695 | u32 bits)
|
| 696 | {
|
| 697 | u32 val;
|
| 698 |
|
| 699 | serdes_rd(ctx, lane, reg, &val);
|
| 700 | val |= bits;
|
| 701 | serdes_wr(ctx, lane, reg, val);
|
| 702 | }
|
| 703 |
|
| 704 | static void xgene_phy_cfg_cmu_clk_type(struct xgene_phy_ctx *ctx,
|
| 705 | enum cmu_type_t cmu_type,
|
| 706 | enum clk_type_t clk_type)
|
| 707 | {
|
| 708 | u32 val;
|
| 709 |
|
| 710 |
|
| 711 | cmu_rd(ctx, cmu_type, CMU_REG12, &val);
|
| 712 | val = CMU_REG12_STATE_DELAY9_SET(val, 0x1);
|
| 713 | cmu_wr(ctx, cmu_type, CMU_REG12, val);
|
| 714 |
|
| 715 | cmu_wr(ctx, cmu_type, CMU_REG13, 0x0222);
|
| 716 | cmu_wr(ctx, cmu_type, CMU_REG14, 0x2225);
|
| 717 |
|
| 718 |
|
| 719 | if (clk_type == CLK_EXT_DIFF) {
|
| 720 |
|
| 721 | cmu_rd(ctx, cmu_type, CMU_REG0, &val);
|
| 722 | val = CMU_REG0_PLL_REF_SEL_SET(val, 0x0);
|
| 723 | cmu_wr(ctx, cmu_type, CMU_REG0, val);
|
| 724 |
|
| 725 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 726 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
|
| 727 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 728 | dev_dbg(ctx->dev, "Set external reference clock\n");
|
| 729 | } else if (clk_type == CLK_INT_DIFF) {
|
| 730 |
|
| 731 | cmu_rd(ctx, cmu_type, CMU_REG0, &val);
|
| 732 | val = CMU_REG0_PLL_REF_SEL_SET(val, 0x1);
|
| 733 | cmu_wr(ctx, cmu_type, CMU_REG0, val);
|
| 734 |
|
| 735 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 736 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
|
| 737 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 738 | dev_dbg(ctx->dev, "Set internal reference clock\n");
|
| 739 | } else if (clk_type == CLK_INT_SING) {
|
| 740 | |
| 741 | * NOTE: This clock type is NOT support for controller
|
| 742 | * whose internal clock shared in the PCIe controller
|
| 743 | *
|
| 744 | * Select internal clock mux
|
| 745 |
|
| 746 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 747 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
|
| 748 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 749 |
|
| 750 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 751 | val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
|
| 752 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 753 | dev_dbg(ctx->dev,
|
| 754 | "Set internal single ended reference clock\n");
|
| 755 | }
|
| 756 | }
|
| 757 |
|
| 758 | static void xgene_phy_sata_cfg_cmu_core(struct xgene_phy_ctx *ctx,
|
| 759 | enum cmu_type_t cmu_type,
|
| 760 | enum clk_type_t clk_type)
|
| 761 | {
|
| 762 | u32 val;
|
| 763 | int ref_100MHz;
|
| 764 |
|
| 765 | if (cmu_type == REF_CMU) {
|
| 766 |
|
| 767 | cmu_rd(ctx, cmu_type, CMU_REG34, &val);
|
| 768 | val = CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(val, 0x7);
|
| 769 | val = CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(val, 0xc);
|
| 770 | val = CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(val, 0x3);
|
| 771 | val = CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(val, 0x8);
|
| 772 | cmu_wr(ctx, cmu_type, CMU_REG34, val);
|
| 773 | }
|
| 774 |
|
| 775 |
|
| 776 | cmu_rd(ctx, cmu_type, CMU_REG0, &val);
|
| 777 | if (cmu_type == REF_CMU || preA3Chip)
|
| 778 | val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x4);
|
| 779 | else
|
| 780 | val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x7);
|
| 781 | cmu_wr(ctx, cmu_type, CMU_REG0, val);
|
| 782 |
|
| 783 |
|
| 784 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 785 | val = CMU_REG1_PLL_CP_SET(val, 0x1);
|
| 786 | if (cmu_type == REF_CMU || preA3Chip)
|
| 787 | val = CMU_REG1_PLL_CP_SEL_SET(val, 0x5);
|
| 788 | else
|
| 789 | val = CMU_REG1_PLL_CP_SEL_SET(val, 0x3);
|
| 790 | if (cmu_type == REF_CMU)
|
| 791 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
|
| 792 | else
|
| 793 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x1);
|
| 794 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 795 |
|
| 796 | if (cmu_type != REF_CMU)
|
| 797 | cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
|
| 798 |
|
| 799 |
|
| 800 | cmu_rd(ctx, cmu_type, CMU_REG2, &val);
|
| 801 | if (cmu_type == REF_CMU) {
|
| 802 | val = CMU_REG2_PLL_LFRES_SET(val, 0xa);
|
| 803 | ref_100MHz = 1;
|
| 804 | } else {
|
| 805 | val = CMU_REG2_PLL_LFRES_SET(val, 0x3);
|
| 806 | if (clk_type == CLK_EXT_DIFF)
|
| 807 | ref_100MHz = 0;
|
| 808 | else
|
| 809 | ref_100MHz = 1;
|
| 810 | }
|
| 811 | if (ref_100MHz) {
|
| 812 | val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_100M);
|
| 813 | val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_100M);
|
| 814 | } else {
|
| 815 | val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_50M);
|
| 816 | val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_50M);
|
| 817 | }
|
| 818 | cmu_wr(ctx, cmu_type, CMU_REG2, val);
|
| 819 |
|
| 820 |
|
| 821 | cmu_rd(ctx, cmu_type, CMU_REG3, &val);
|
| 822 | if (cmu_type == REF_CMU) {
|
| 823 | val = CMU_REG3_VCOVARSEL_SET(val, 0x3);
|
| 824 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x10);
|
| 825 | } else {
|
| 826 | val = CMU_REG3_VCOVARSEL_SET(val, 0xF);
|
| 827 | if (preA3Chip)
|
| 828 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x15);
|
| 829 | else
|
| 830 | val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x1a);
|
| 831 | val = CMU_REG3_VCO_MANMOMSEL_SET(val, 0x15);
|
| 832 | }
|
| 833 | cmu_wr(ctx, cmu_type, CMU_REG3, val);
|
| 834 |
|
| 835 |
|
| 836 | cmu_rd(ctx, cmu_type, CMU_REG26, &val);
|
| 837 | val = CMU_REG26_FORCE_PLL_LOCK_SET(val, 0x0);
|
| 838 | cmu_wr(ctx, cmu_type, CMU_REG26, val);
|
| 839 |
|
| 840 |
|
| 841 | cmu_rd(ctx, cmu_type, CMU_REG5, &val);
|
| 842 | val = CMU_REG5_PLL_LFSMCAP_SET(val, 0x3);
|
| 843 | val = CMU_REG5_PLL_LFCAP_SET(val, 0x3);
|
| 844 | if (cmu_type == REF_CMU || !preA3Chip)
|
| 845 | val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x7);
|
| 846 | else
|
| 847 | val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x4);
|
| 848 | cmu_wr(ctx, cmu_type, CMU_REG5, val);
|
| 849 |
|
| 850 |
|
| 851 | cmu_rd(ctx, cmu_type, CMU_REG6, &val);
|
| 852 | val = CMU_REG6_PLL_VREGTRIM_SET(val, preA3Chip ? 0x0 : 0x2);
|
| 853 | val = CMU_REG6_MAN_PVT_CAL_SET(val, preA3Chip ? 0x1 : 0x0);
|
| 854 | cmu_wr(ctx, cmu_type, CMU_REG6, val);
|
| 855 |
|
| 856 |
|
| 857 | if (cmu_type == PHY_CMU) {
|
| 858 | cmu_rd(ctx, cmu_type, CMU_REG9, &val);
|
| 859 | val = CMU_REG9_TX_WORD_MODE_CH1_SET(val,
|
| 860 | CMU_REG9_WORD_LEN_20BIT);
|
| 861 | val = CMU_REG9_TX_WORD_MODE_CH0_SET(val,
|
| 862 | CMU_REG9_WORD_LEN_20BIT);
|
| 863 | val = CMU_REG9_PLL_POST_DIVBY2_SET(val, 0x1);
|
| 864 | if (!preA3Chip) {
|
| 865 | val = CMU_REG9_VBG_BYPASSB_SET(val, 0x0);
|
| 866 | val = CMU_REG9_IGEN_BYPASS_SET(val , 0x0);
|
| 867 | }
|
| 868 | cmu_wr(ctx, cmu_type, CMU_REG9, val);
|
| 869 |
|
| 870 | if (!preA3Chip) {
|
| 871 | cmu_rd(ctx, cmu_type, CMU_REG10, &val);
|
| 872 | val = CMU_REG10_VREG_REFSEL_SET(val, 0x1);
|
| 873 | cmu_wr(ctx, cmu_type, CMU_REG10, val);
|
| 874 | }
|
| 875 | }
|
| 876 |
|
| 877 | cmu_rd(ctx, cmu_type, CMU_REG16, &val);
|
| 878 | val = CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(val, 0x1);
|
| 879 | val = CMU_REG16_BYPASS_PLL_LOCK_SET(val, 0x1);
|
| 880 | if (cmu_type == REF_CMU || preA3Chip)
|
| 881 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x4);
|
| 882 | else
|
| 883 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
|
| 884 | cmu_wr(ctx, cmu_type, CMU_REG16, val);
|
| 885 |
|
| 886 |
|
| 887 | cmu_rd(ctx, cmu_type, CMU_REG30, &val);
|
| 888 | val = CMU_REG30_PCIE_MODE_SET(val, 0x0);
|
| 889 | val = CMU_REG30_LOCK_COUNT_SET(val, 0x3);
|
| 890 | cmu_wr(ctx, cmu_type, CMU_REG30, val);
|
| 891 |
|
| 892 |
|
| 893 | cmu_wr(ctx, cmu_type, CMU_REG31, 0xF);
|
| 894 |
|
| 895 | cmu_rd(ctx, cmu_type, CMU_REG32, &val);
|
| 896 | val = CMU_REG32_PVT_CAL_WAIT_SEL_SET(val, 0x3);
|
| 897 | if (cmu_type == REF_CMU || preA3Chip)
|
| 898 | val = CMU_REG32_IREF_ADJ_SET(val, 0x3);
|
| 899 | else
|
| 900 | val = CMU_REG32_IREF_ADJ_SET(val, 0x1);
|
| 901 | cmu_wr(ctx, cmu_type, CMU_REG32, val);
|
| 902 |
|
| 903 |
|
| 904 | if (cmu_type != REF_CMU && preA3Chip)
|
| 905 | cmu_wr(ctx, cmu_type, CMU_REG34, 0x8d27);
|
| 906 | else
|
| 907 | cmu_wr(ctx, cmu_type, CMU_REG34, 0x873c);
|
| 908 |
|
| 909 |
|
| 910 | cmu_wr(ctx, cmu_type, CMU_REG37, 0xF00F);
|
| 911 | }
|
| 912 |
|
| 913 | static void xgene_phy_ssc_enable(struct xgene_phy_ctx *ctx,
|
| 914 | enum cmu_type_t cmu_type)
|
| 915 | {
|
| 916 | u32 val;
|
| 917 |
|
| 918 |
|
| 919 | cmu_rd(ctx, cmu_type, CMU_REG35, &val);
|
| 920 | val = CMU_REG35_PLL_SSC_MOD_SET(val, 98);
|
| 921 | cmu_wr(ctx, cmu_type, CMU_REG35, val);
|
| 922 |
|
| 923 |
|
| 924 | cmu_rd(ctx, cmu_type, CMU_REG36, &val);
|
| 925 | val = CMU_REG36_PLL_SSC_VSTEP_SET(val, 30);
|
| 926 | val = CMU_REG36_PLL_SSC_EN_SET(val, 1);
|
| 927 | val = CMU_REG36_PLL_SSC_DSMSEL_SET(val, 1);
|
| 928 | cmu_wr(ctx, cmu_type, CMU_REG36, val);
|
| 929 |
|
| 930 |
|
| 931 | cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
|
| 932 | cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
|
| 933 |
|
| 934 |
|
| 935 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
|
| 936 | CMU_REG32_FORCE_VCOCAL_START_MASK);
|
| 937 | }
|
| 938 |
|
| 939 | static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx)
|
| 940 | {
|
| 941 | u32 val;
|
| 942 | u32 reg;
|
| 943 | int i;
|
| 944 | int lane;
|
| 945 |
|
| 946 | for (lane = 0; lane < MAX_LANE; lane++) {
|
| 947 | serdes_wr(ctx, lane, RXTX_REG147, 0x6);
|
| 948 |
|
| 949 |
|
| 950 | serdes_rd(ctx, lane, RXTX_REG0, &val);
|
| 951 | val = RXTX_REG0_CTLE_EQ_HR_SET(val, 0x10);
|
| 952 | val = RXTX_REG0_CTLE_EQ_QR_SET(val, 0x10);
|
| 953 | val = RXTX_REG0_CTLE_EQ_FR_SET(val, 0x10);
|
| 954 | serdes_wr(ctx, lane, RXTX_REG0, val);
|
| 955 |
|
| 956 |
|
| 957 | serdes_rd(ctx, lane, RXTX_REG1, &val);
|
| 958 | val = RXTX_REG1_RXACVCM_SET(val, 0x7);
|
| 959 | val = RXTX_REG1_CTLE_EQ_SET(val,
|
| 960 | ctx->sata_param.txboostgain[lane * 3 +
|
| 961 | ctx->sata_param.speed[lane]]);
|
| 962 | serdes_wr(ctx, lane, RXTX_REG1, val);
|
| 963 |
|
| 964 | |
| 965 | * enable TX FIFO
|
| 966 |
|
| 967 | serdes_rd(ctx, lane, RXTX_REG2, &val);
|
| 968 | val = RXTX_REG2_VTT_ENA_SET(val, 0x1);
|
| 969 | val = RXTX_REG2_VTT_SEL_SET(val, 0x1);
|
| 970 | val = RXTX_REG2_TX_FIFO_ENA_SET(val, 0x1);
|
| 971 | serdes_wr(ctx, lane, RXTX_REG2, val);
|
| 972 |
|
| 973 |
|
| 974 | serdes_rd(ctx, lane, RXTX_REG4, &val);
|
| 975 | val = RXTX_REG4_TX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
|
| 976 | serdes_wr(ctx, lane, RXTX_REG4, val);
|
| 977 |
|
| 978 | if (!preA3Chip) {
|
| 979 | serdes_rd(ctx, lane, RXTX_REG1, &val);
|
| 980 | val = RXTX_REG1_RXVREG1_SET(val, 0x2);
|
| 981 | val = RXTX_REG1_RXIREF_ADJ_SET(val, 0x2);
|
| 982 | serdes_wr(ctx, lane, RXTX_REG1, val);
|
| 983 | }
|
| 984 |
|
| 985 |
|
| 986 | serdes_rd(ctx, lane, RXTX_REG5, &val);
|
| 987 | val = RXTX_REG5_TX_CN1_SET(val,
|
| 988 | ctx->sata_param.txprecursor_cn1[lane * 3 +
|
| 989 | ctx->sata_param.speed[lane]]);
|
| 990 | val = RXTX_REG5_TX_CP1_SET(val,
|
| 991 | ctx->sata_param.txpostcursor_cp1[lane * 3 +
|
| 992 | ctx->sata_param.speed[lane]]);
|
| 993 | val = RXTX_REG5_TX_CN2_SET(val,
|
| 994 | ctx->sata_param.txprecursor_cn2[lane * 3 +
|
| 995 | ctx->sata_param.speed[lane]]);
|
| 996 | serdes_wr(ctx, lane, RXTX_REG5, val);
|
| 997 |
|
| 998 |
|
| 999 | serdes_rd(ctx, lane, RXTX_REG6, &val);
|
| 1000 | val = RXTX_REG6_TXAMP_CNTL_SET(val,
|
| 1001 | ctx->sata_param.txamplitude[lane * 3 +
|
| 1002 | ctx->sata_param.speed[lane]]);
|
| 1003 | val = RXTX_REG6_TXAMP_ENA_SET(val, 0x1);
|
| 1004 | val = RXTX_REG6_TX_IDLE_SET(val, 0x0);
|
| 1005 | val = RXTX_REG6_RX_BIST_RESYNC_SET(val, 0x0);
|
| 1006 | val = RXTX_REG6_RX_BIST_ERRCNT_RD_SET(val, 0x0);
|
| 1007 | serdes_wr(ctx, lane, RXTX_REG6, val);
|
| 1008 |
|
| 1009 |
|
| 1010 | serdes_rd(ctx, lane, RXTX_REG7, &val);
|
| 1011 | val = RXTX_REG7_BIST_ENA_RX_SET(val, 0x0);
|
| 1012 | val = RXTX_REG7_RX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
|
| 1013 | serdes_wr(ctx, lane, RXTX_REG7, val);
|
| 1014 |
|
| 1015 |
|
| 1016 | serdes_rd(ctx, lane, RXTX_REG8, &val);
|
| 1017 | val = RXTX_REG8_CDR_LOOP_ENA_SET(val, 0x1);
|
| 1018 | val = RXTX_REG8_CDR_BYPASS_RXLOS_SET(val, 0x0);
|
| 1019 | val = RXTX_REG8_SSC_ENABLE_SET(val, 0x1);
|
| 1020 | val = RXTX_REG8_SD_DISABLE_SET(val, 0x0);
|
| 1021 | val = RXTX_REG8_SD_VREF_SET(val, 0x4);
|
| 1022 | serdes_wr(ctx, lane, RXTX_REG8, val);
|
| 1023 |
|
| 1024 |
|
| 1025 | serdes_rd(ctx, lane, RXTX_REG11, &val);
|
| 1026 | val = RXTX_REG11_PHASE_ADJUST_LIMIT_SET(val, 0x0);
|
| 1027 | serdes_wr(ctx, lane, RXTX_REG11, val);
|
| 1028 |
|
| 1029 |
|
| 1030 | serdes_rd(ctx, lane, RXTX_REG12, &val);
|
| 1031 | val = RXTX_REG12_LATCH_OFF_ENA_SET(val, 0x1);
|
| 1032 | val = RXTX_REG12_SUMOS_ENABLE_SET(val, 0x0);
|
| 1033 | val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0x0);
|
| 1034 | serdes_wr(ctx, lane, RXTX_REG12, val);
|
| 1035 |
|
| 1036 |
|
| 1037 | serdes_rd(ctx, lane, RXTX_REG26, &val);
|
| 1038 | val = RXTX_REG26_PERIOD_ERROR_LATCH_SET(val, 0x0);
|
| 1039 | val = RXTX_REG26_BLWC_ENA_SET(val, 0x1);
|
| 1040 | serdes_wr(ctx, lane, RXTX_REG26, val);
|
| 1041 |
|
| 1042 | serdes_wr(ctx, lane, RXTX_REG28, 0x0);
|
| 1043 |
|
| 1044 |
|
| 1045 | serdes_wr(ctx, lane, RXTX_REG31, 0x0);
|
| 1046 |
|
| 1047 |
|
| 1048 | serdes_rd(ctx, lane, RXTX_REG61, &val);
|
| 1049 | val = RXTX_REG61_ISCAN_INBERT_SET(val, 0x1);
|
| 1050 | val = RXTX_REG61_LOADFREQ_SHIFT_SET(val, 0x0);
|
| 1051 | val = RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(val, 0x0);
|
| 1052 | serdes_wr(ctx, lane, RXTX_REG61, val);
|
| 1053 |
|
| 1054 | serdes_rd(ctx, lane, RXTX_REG62, &val);
|
| 1055 | val = RXTX_REG62_PERIOD_H1_QLATCH_SET(val, 0x0);
|
| 1056 | serdes_wr(ctx, lane, RXTX_REG62, val);
|
| 1057 |
|
| 1058 |
|
| 1059 | for (i = 0; i < 9; i++) {
|
| 1060 | reg = RXTX_REG81 + i * 2;
|
| 1061 | serdes_rd(ctx, lane, reg, &val);
|
| 1062 | val = RXTX_REG89_MU_TH7_SET(val, 0xe);
|
| 1063 | val = RXTX_REG89_MU_TH8_SET(val, 0xe);
|
| 1064 | val = RXTX_REG89_MU_TH9_SET(val, 0xe);
|
| 1065 | serdes_wr(ctx, lane, reg, val);
|
| 1066 | }
|
| 1067 |
|
| 1068 |
|
| 1069 | for (i = 0; i < 3; i++) {
|
| 1070 | reg = RXTX_REG96 + i * 2;
|
| 1071 | serdes_rd(ctx, lane, reg, &val);
|
| 1072 | val = RXTX_REG96_MU_FREQ1_SET(val, 0x10);
|
| 1073 | val = RXTX_REG96_MU_FREQ2_SET(val, 0x10);
|
| 1074 | val = RXTX_REG96_MU_FREQ3_SET(val, 0x10);
|
| 1075 | serdes_wr(ctx, lane, reg, val);
|
| 1076 | }
|
| 1077 |
|
| 1078 |
|
| 1079 | for (i = 0; i < 3; i++) {
|
| 1080 | reg = RXTX_REG99 + i * 2;
|
| 1081 | serdes_rd(ctx, lane, reg, &val);
|
| 1082 | val = RXTX_REG99_MU_PHASE1_SET(val, 0x7);
|
| 1083 | val = RXTX_REG99_MU_PHASE2_SET(val, 0x7);
|
| 1084 | val = RXTX_REG99_MU_PHASE3_SET(val, 0x7);
|
| 1085 | serdes_wr(ctx, lane, reg, val);
|
| 1086 | }
|
| 1087 |
|
| 1088 | serdes_rd(ctx, lane, RXTX_REG102, &val);
|
| 1089 | val = RXTX_REG102_FREQLOOP_LIMIT_SET(val, 0x0);
|
| 1090 | serdes_wr(ctx, lane, RXTX_REG102, val);
|
| 1091 |
|
| 1092 | serdes_wr(ctx, lane, RXTX_REG114, 0xffe0);
|
| 1093 |
|
| 1094 | serdes_rd(ctx, lane, RXTX_REG125, &val);
|
| 1095 | val = RXTX_REG125_SIGN_PQ_SET(val,
|
| 1096 | ctx->sata_param.txeyedirection[lane * 3 +
|
| 1097 | ctx->sata_param.speed[lane]]);
|
| 1098 | val = RXTX_REG125_PQ_REG_SET(val,
|
| 1099 | ctx->sata_param.txeyetuning[lane * 3 +
|
| 1100 | ctx->sata_param.speed[lane]]);
|
| 1101 | val = RXTX_REG125_PHZ_MANUAL_SET(val, 0x1);
|
| 1102 | serdes_wr(ctx, lane, RXTX_REG125, val);
|
| 1103 |
|
| 1104 | serdes_rd(ctx, lane, RXTX_REG127, &val);
|
| 1105 | val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x0);
|
| 1106 | serdes_wr(ctx, lane, RXTX_REG127, val);
|
| 1107 |
|
| 1108 | serdes_rd(ctx, lane, RXTX_REG128, &val);
|
| 1109 | val = RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(val, 0x3);
|
| 1110 | serdes_wr(ctx, lane, RXTX_REG128, val);
|
| 1111 |
|
| 1112 | serdes_rd(ctx, lane, RXTX_REG145, &val);
|
| 1113 | val = RXTX_REG145_RXDFE_CONFIG_SET(val, 0x3);
|
| 1114 | val = RXTX_REG145_TX_IDLE_SATA_SET(val, 0x0);
|
| 1115 | if (preA3Chip) {
|
| 1116 | val = RXTX_REG145_RXES_ENA_SET(val, 0x1);
|
| 1117 | val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x1);
|
| 1118 | } else {
|
| 1119 | val = RXTX_REG145_RXES_ENA_SET(val, 0x0);
|
| 1120 | val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x0);
|
| 1121 | }
|
| 1122 | serdes_wr(ctx, lane, RXTX_REG145, val);
|
| 1123 |
|
| 1124 | |
| 1125 | * Set Rx LOS filter clock rate, sample rate, and threshold
|
| 1126 | * windows
|
| 1127 |
|
| 1128 | for (i = 0; i < 4; i++) {
|
| 1129 | reg = RXTX_REG148 + i * 2;
|
| 1130 | serdes_wr(ctx, lane, reg, 0xFFFF);
|
| 1131 | }
|
| 1132 | }
|
| 1133 | }
|
| 1134 |
|
| 1135 | static int xgene_phy_cal_rdy_chk(struct xgene_phy_ctx *ctx,
|
| 1136 | enum cmu_type_t cmu_type,
|
| 1137 | enum clk_type_t clk_type)
|
| 1138 | {
|
| 1139 | void __iomem *csr_serdes = ctx->sds_base;
|
| 1140 | int loop;
|
| 1141 | u32 val;
|
| 1142 |
|
| 1143 |
|
| 1144 | writel(0xdf, csr_serdes + SATA_ENET_SDS_RST_CTL);
|
| 1145 | readl(csr_serdes + SATA_ENET_SDS_RST_CTL);
|
| 1146 |
|
| 1147 | if (cmu_type != REF_CMU) {
|
| 1148 | cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
|
| 1149 | |
| 1150 | * As per PHY design spec, the PLL reset requires a minimum
|
| 1151 | * of 800us.
|
| 1152 |
|
| 1153 | usleep_range(800, 1000);
|
| 1154 |
|
| 1155 | cmu_rd(ctx, cmu_type, CMU_REG1, &val);
|
| 1156 | val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
|
| 1157 | cmu_wr(ctx, cmu_type, CMU_REG1, val);
|
| 1158 | |
| 1159 | * As per PHY design spec, the PLL auto calibration requires
|
| 1160 | * a minimum of 800us.
|
| 1161 |
|
| 1162 | usleep_range(800, 1000);
|
| 1163 |
|
| 1164 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
|
| 1165 | CMU_REG32_FORCE_VCOCAL_START_MASK);
|
| 1166 | |
| 1167 | * As per PHY design spec, the PLL requires a minimum of
|
| 1168 | * 800us to settle.
|
| 1169 |
|
| 1170 | usleep_range(800, 1000);
|
| 1171 | }
|
| 1172 |
|
| 1173 | if (!preA3Chip)
|
| 1174 | goto skip_manual_cal;
|
| 1175 |
|
| 1176 | |
| 1177 | * Configure the termination resister calibration
|
| 1178 | * The serial receive pins, RXP/RXN, have TERMination resistor
|
| 1179 | * that is required to be calibrated.
|
| 1180 |
|
| 1181 | cmu_rd(ctx, cmu_type, CMU_REG17, &val);
|
| 1182 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x12);
|
| 1183 | val = CMU_REG17_RESERVED_7_SET(val, 0x0);
|
| 1184 | cmu_wr(ctx, cmu_type, CMU_REG17, val);
|
| 1185 | cmu_toggle1to0(ctx, cmu_type, CMU_REG17,
|
| 1186 | CMU_REG17_PVT_TERM_MAN_ENA_MASK);
|
| 1187 | |
| 1188 | * The serial transmit pins, TXP/TXN, have Pull-UP and Pull-DOWN
|
| 1189 | * resistors that are required to the calibrated.
|
| 1190 | * Configure the pull DOWN calibration
|
| 1191 |
|
| 1192 | cmu_rd(ctx, cmu_type, CMU_REG17, &val);
|
| 1193 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x29);
|
| 1194 | val = CMU_REG17_RESERVED_7_SET(val, 0x0);
|
| 1195 | cmu_wr(ctx, cmu_type, CMU_REG17, val);
|
| 1196 | cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
|
| 1197 | CMU_REG16_PVT_DN_MAN_ENA_MASK);
|
| 1198 |
|
| 1199 | cmu_rd(ctx, cmu_type, CMU_REG17, &val);
|
| 1200 | val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x28);
|
| 1201 | val = CMU_REG17_RESERVED_7_SET(val, 0x0);
|
| 1202 | cmu_wr(ctx, cmu_type, CMU_REG17, val);
|
| 1203 | cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
|
| 1204 | CMU_REG16_PVT_UP_MAN_ENA_MASK);
|
| 1205 |
|
| 1206 | skip_manual_cal:
|
| 1207 |
|
| 1208 | loop = 100;
|
| 1209 | do {
|
| 1210 | cmu_rd(ctx, cmu_type, CMU_REG7, &val);
|
| 1211 | if (CMU_REG7_PLL_CALIB_DONE_RD(val))
|
| 1212 | break;
|
| 1213 | |
| 1214 | * As per PHY design spec, PLL calibration status requires
|
| 1215 | * a minimum of 10us to be updated.
|
| 1216 |
|
| 1217 | usleep_range(10, 100);
|
| 1218 | } while (--loop > 0);
|
| 1219 |
|
| 1220 | cmu_rd(ctx, cmu_type, CMU_REG7, &val);
|
| 1221 | dev_dbg(ctx->dev, "PLL calibration %s\n",
|
| 1222 | CMU_REG7_PLL_CALIB_DONE_RD(val) ? "done" : "failed");
|
| 1223 | if (CMU_REG7_VCO_CAL_FAIL_RD(val)) {
|
| 1224 | dev_err(ctx->dev,
|
| 1225 | "PLL calibration failed due to VCO failure\n");
|
| 1226 | return -1;
|
| 1227 | }
|
| 1228 | dev_dbg(ctx->dev, "PLL calibration successful\n");
|
| 1229 |
|
| 1230 | cmu_rd(ctx, cmu_type, CMU_REG15, &val);
|
| 1231 | dev_dbg(ctx->dev, "PHY Tx is %sready\n", val & 0x300 ? "" : "not ");
|
| 1232 | return 0;
|
| 1233 | }
|
| 1234 |
|
| 1235 | static void xgene_phy_pdwn_force_vco(struct xgene_phy_ctx *ctx,
|
| 1236 | enum cmu_type_t cmu_type,
|
| 1237 | enum clk_type_t clk_type)
|
| 1238 | {
|
| 1239 | u32 val;
|
| 1240 |
|
| 1241 | dev_dbg(ctx->dev, "Reset VCO and re-start again\n");
|
| 1242 | if (cmu_type == PHY_CMU) {
|
| 1243 | cmu_rd(ctx, cmu_type, CMU_REG16, &val);
|
| 1244 | val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
|
| 1245 | cmu_wr(ctx, cmu_type, CMU_REG16, val);
|
| 1246 | }
|
| 1247 |
|
| 1248 | cmu_toggle1to0(ctx, cmu_type, CMU_REG0, CMU_REG0_PDOWN_MASK);
|
| 1249 | cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
|
| 1250 | CMU_REG32_FORCE_VCOCAL_START_MASK);
|
| 1251 | }
|
| 1252 |
|
| 1253 | static int xgene_phy_hw_init_sata(struct xgene_phy_ctx *ctx,
|
| 1254 | enum clk_type_t clk_type, int ssc_enable)
|
| 1255 | {
|
| 1256 | void __iomem *sds_base = ctx->sds_base;
|
| 1257 | u32 val;
|
| 1258 | int i;
|
| 1259 |
|
| 1260 |
|
| 1261 | dev_dbg(ctx->dev, "Reset PHY\n");
|
| 1262 |
|
| 1263 | writel(0x0, sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1264 | val = readl(sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1265 |
|
| 1266 | writel(0x20, sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1267 | readl(sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1268 |
|
| 1269 | writel(0xde, sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1270 | readl(sds_base + SATA_ENET_SDS_RST_CTL);
|
| 1271 |
|
| 1272 |
|
| 1273 | val = readl(sds_base + SATA_ENET_SDS_CTL1);
|
| 1274 | val = CFG_I_SPD_SEL_CDR_OVR1_SET(val,
|
| 1275 | ctx->sata_param.txspeed[ctx->sata_param.speed[0]]);
|
| 1276 | writel(val, sds_base + SATA_ENET_SDS_CTL1);
|
| 1277 |
|
| 1278 | dev_dbg(ctx->dev, "Set the customer pin mode to SATA\n");
|
| 1279 | val = readl(sds_base + SATA_ENET_SDS_CTL0);
|
| 1280 | val = REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(val, 0x4421);
|
| 1281 | writel(val, sds_base + SATA_ENET_SDS_CTL0);
|
| 1282 |
|
| 1283 |
|
| 1284 | xgene_phy_cfg_cmu_clk_type(ctx, PHY_CMU, clk_type);
|
| 1285 |
|
| 1286 |
|
| 1287 | xgene_phy_sata_cfg_cmu_core(ctx, PHY_CMU, clk_type);
|
| 1288 |
|
| 1289 |
|
| 1290 | if (ssc_enable)
|
| 1291 | xgene_phy_ssc_enable(ctx, PHY_CMU);
|
| 1292 |
|
| 1293 |
|
| 1294 | xgene_phy_sata_cfg_lanes(ctx);
|
| 1295 |
|
| 1296 |
|
| 1297 | val = readl(sds_base + SATA_ENET_SDS_PCS_CTL0);
|
| 1298 | val = REGSPEC_CFG_I_RX_WORDMODE0_SET(val, 0x3);
|
| 1299 | val = REGSPEC_CFG_I_TX_WORDMODE0_SET(val, 0x3);
|
| 1300 | writel(val, sds_base + SATA_ENET_SDS_PCS_CTL0);
|
| 1301 |
|
| 1302 |
|
| 1303 | i = 10;
|
| 1304 | do {
|
| 1305 | if (!xgene_phy_cal_rdy_chk(ctx, PHY_CMU, clk_type))
|
| 1306 | break;
|
| 1307 |
|
| 1308 | xgene_phy_pdwn_force_vco(ctx, PHY_CMU, clk_type);
|
| 1309 | } while (--i > 0);
|
| 1310 |
|
| 1311 | if (i <= 0)
|
| 1312 | dev_err(ctx->dev, "PLL calibration failed\n");
|
| 1313 |
|
| 1314 | return 0;
|
| 1315 | }
|
| 1316 |
|
| 1317 | static int xgene_phy_hw_initialize(struct xgene_phy_ctx *ctx,
|
| 1318 | enum clk_type_t clk_type,
|
| 1319 | int ssc_enable)
|
| 1320 | {
|
| 1321 | int rc;
|
| 1322 |
|
| 1323 | dev_dbg(ctx->dev, "PHY init clk type %d\n", clk_type);
|
| 1324 |
|
| 1325 | if (ctx->mode == MODE_SATA) {
|
| 1326 | rc = xgene_phy_hw_init_sata(ctx, clk_type, ssc_enable);
|
| 1327 | if (rc)
|
| 1328 | return rc;
|
| 1329 | } else {
|
| 1330 | dev_err(ctx->dev, "Un-supported customer pin mode %d\n",
|
| 1331 | ctx->mode);
|
| 1332 | return -ENODEV;
|
| 1333 | }
|
| 1334 |
|
| 1335 | return 0;
|
| 1336 | }
|
| 1337 |
|
| 1338 | |
| 1339 | * Receiver Offset Calibration:
|
| 1340 | *
|
| 1341 | * Calibrate the receiver signal path offset in two steps - summar and
|
| 1342 | * latch calibrations
|
| 1343 |
|
| 1344 | static void xgene_phy_force_lat_summer_cal(struct xgene_phy_ctx *ctx, int lane)
|
| 1345 | {
|
| 1346 | int i;
|
| 1347 | static const struct {
|
| 1348 | u32 reg;
|
| 1349 | u32 val;
|
| 1350 | } serdes_reg[] = {
|
| 1351 | {RXTX_REG38, 0x0},
|
| 1352 | {RXTX_REG39, 0xff00},
|
| 1353 | {RXTX_REG40, 0xffff},
|
| 1354 | {RXTX_REG41, 0xffff},
|
| 1355 | {RXTX_REG42, 0xffff},
|
| 1356 | {RXTX_REG43, 0xffff},
|
| 1357 | {RXTX_REG44, 0xffff},
|
| 1358 | {RXTX_REG45, 0xffff},
|
| 1359 | {RXTX_REG46, 0xffff},
|
| 1360 | {RXTX_REG47, 0xfffc},
|
| 1361 | {RXTX_REG48, 0x0},
|
| 1362 | {RXTX_REG49, 0x0},
|
| 1363 | {RXTX_REG50, 0x0},
|
| 1364 | {RXTX_REG51, 0x0},
|
| 1365 | {RXTX_REG52, 0x0},
|
| 1366 | {RXTX_REG53, 0x0},
|
| 1367 | {RXTX_REG54, 0x0},
|
| 1368 | {RXTX_REG55, 0x0},
|
| 1369 | };
|
| 1370 |
|
| 1371 |
|
| 1372 | serdes_setbits(ctx, lane, RXTX_REG127,
|
| 1373 | RXTX_REG127_FORCE_SUM_CAL_START_MASK);
|
| 1374 | |
| 1375 | * As per PHY design spec, the Summer calibration requires a minimum
|
| 1376 | * of 100us to complete.
|
| 1377 |
|
| 1378 | usleep_range(100, 500);
|
| 1379 | serdes_clrbits(ctx, lane, RXTX_REG127,
|
| 1380 | RXTX_REG127_FORCE_SUM_CAL_START_MASK);
|
| 1381 | |
| 1382 | * As per PHY design spec, the auto calibration requires a minimum
|
| 1383 | * of 100us to complete.
|
| 1384 |
|
| 1385 | usleep_range(100, 500);
|
| 1386 |
|
| 1387 |
|
| 1388 | serdes_setbits(ctx, lane, RXTX_REG127,
|
| 1389 | RXTX_REG127_FORCE_LAT_CAL_START_MASK);
|
| 1390 | |
| 1391 | * As per PHY design spec, the latch calibration requires a minimum
|
| 1392 | * of 100us to complete.
|
| 1393 |
|
| 1394 | usleep_range(100, 500);
|
| 1395 | serdes_clrbits(ctx, lane, RXTX_REG127,
|
| 1396 | RXTX_REG127_FORCE_LAT_CAL_START_MASK);
|
| 1397 |
|
| 1398 |
|
| 1399 | serdes_wr(ctx, lane, RXTX_REG28, 0x7);
|
| 1400 | serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
|
| 1401 | serdes_clrbits(ctx, lane, RXTX_REG4,
|
| 1402 | RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK);
|
| 1403 | serdes_clrbits(ctx, lane, RXTX_REG7,
|
| 1404 | RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK);
|
| 1405 | for (i = 0; i < ARRAY_SIZE(serdes_reg); i++)
|
| 1406 | serdes_wr(ctx, lane, serdes_reg[i].reg,
|
| 1407 | serdes_reg[i].val);
|
| 1408 | }
|
| 1409 |
|
| 1410 | static void xgene_phy_reset_rxd(struct xgene_phy_ctx *ctx, int lane)
|
| 1411 | {
|
| 1412 |
|
| 1413 | serdes_clrbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
|
| 1414 |
|
| 1415 | usleep_range(100, 150);
|
| 1416 | serdes_setbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
|
| 1417 | }
|
| 1418 |
|
| 1419 | static int xgene_phy_get_avg(int accum, int samples)
|
| 1420 | {
|
| 1421 | return (accum + (samples / 2)) / samples;
|
| 1422 | }
|
| 1423 |
|
| 1424 | static void xgene_phy_gen_avg_val(struct xgene_phy_ctx *ctx, int lane)
|
| 1425 | {
|
| 1426 | int max_loop = 10;
|
| 1427 | int avg_loop = 0;
|
| 1428 | int lat_do = 0, lat_xo = 0, lat_eo = 0, lat_so = 0;
|
| 1429 | int lat_de = 0, lat_xe = 0, lat_ee = 0, lat_se = 0;
|
| 1430 | int sum_cal = 0;
|
| 1431 | int lat_do_itr, lat_xo_itr, lat_eo_itr, lat_so_itr;
|
| 1432 | int lat_de_itr, lat_xe_itr, lat_ee_itr, lat_se_itr;
|
| 1433 | int sum_cal_itr;
|
| 1434 | int fail_even;
|
| 1435 | int fail_odd;
|
| 1436 | u32 val;
|
| 1437 |
|
| 1438 | dev_dbg(ctx->dev, "Generating avg calibration value for lane %d\n",
|
| 1439 | lane);
|
| 1440 |
|
| 1441 |
|
| 1442 | serdes_setbits(ctx, lane, RXTX_REG12,
|
| 1443 | RXTX_REG12_RX_DET_TERM_ENABLE_MASK);
|
| 1444 |
|
| 1445 | serdes_wr(ctx, lane, RXTX_REG28, 0x0000);
|
| 1446 |
|
| 1447 | serdes_wr(ctx, lane, RXTX_REG31, 0x0000);
|
| 1448 |
|
| 1449 | |
| 1450 | * Receiver Offset Calibration:
|
| 1451 | * Calibrate the receiver signal path offset in two steps - summar
|
| 1452 | * and latch calibration.
|
| 1453 | * Runs the "Receiver Offset Calibration multiple times to determine
|
| 1454 | * the average value to use.
|
| 1455 |
|
| 1456 | while (avg_loop < max_loop) {
|
| 1457 |
|
| 1458 | xgene_phy_force_lat_summer_cal(ctx, lane);
|
| 1459 |
|
| 1460 | serdes_rd(ctx, lane, RXTX_REG21, &val);
|
| 1461 | lat_do_itr = RXTX_REG21_DO_LATCH_CALOUT_RD(val);
|
| 1462 | lat_xo_itr = RXTX_REG21_XO_LATCH_CALOUT_RD(val);
|
| 1463 | fail_odd = RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(val);
|
| 1464 |
|
| 1465 | serdes_rd(ctx, lane, RXTX_REG22, &val);
|
| 1466 | lat_eo_itr = RXTX_REG22_EO_LATCH_CALOUT_RD(val);
|
| 1467 | lat_so_itr = RXTX_REG22_SO_LATCH_CALOUT_RD(val);
|
| 1468 | fail_even = RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(val);
|
| 1469 |
|
| 1470 | serdes_rd(ctx, lane, RXTX_REG23, &val);
|
| 1471 | lat_de_itr = RXTX_REG23_DE_LATCH_CALOUT_RD(val);
|
| 1472 | lat_xe_itr = RXTX_REG23_XE_LATCH_CALOUT_RD(val);
|
| 1473 |
|
| 1474 | serdes_rd(ctx, lane, RXTX_REG24, &val);
|
| 1475 | lat_ee_itr = RXTX_REG24_EE_LATCH_CALOUT_RD(val);
|
| 1476 | lat_se_itr = RXTX_REG24_SE_LATCH_CALOUT_RD(val);
|
| 1477 |
|
| 1478 | serdes_rd(ctx, lane, RXTX_REG121, &val);
|
| 1479 | sum_cal_itr = RXTX_REG121_SUMOS_CAL_CODE_RD(val);
|
| 1480 |
|
| 1481 |
|
| 1482 | if ((fail_even == 0 || fail_even == 1) &&
|
| 1483 | (fail_odd == 0 || fail_odd == 1)) {
|
| 1484 | lat_do += lat_do_itr;
|
| 1485 | lat_xo += lat_xo_itr;
|
| 1486 | lat_eo += lat_eo_itr;
|
| 1487 | lat_so += lat_so_itr;
|
| 1488 | lat_de += lat_de_itr;
|
| 1489 | lat_xe += lat_xe_itr;
|
| 1490 | lat_ee += lat_ee_itr;
|
| 1491 | lat_se += lat_se_itr;
|
| 1492 | sum_cal += sum_cal_itr;
|
| 1493 |
|
| 1494 | dev_dbg(ctx->dev, "Iteration %d:\n", avg_loop);
|
| 1495 | dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
|
| 1496 | lat_do_itr, lat_xo_itr, lat_eo_itr,
|
| 1497 | lat_so_itr);
|
| 1498 | dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
|
| 1499 | lat_de_itr, lat_xe_itr, lat_ee_itr,
|
| 1500 | lat_se_itr);
|
| 1501 | dev_dbg(ctx->dev, "SUM 0x%x\n", sum_cal_itr);
|
| 1502 | ++avg_loop;
|
| 1503 | } else {
|
| 1504 | dev_err(ctx->dev,
|
| 1505 | "Receiver calibration failed at %d loop\n",
|
| 1506 | avg_loop);
|
| 1507 | }
|
| 1508 | xgene_phy_reset_rxd(ctx, lane);
|
| 1509 | }
|
| 1510 |
|
| 1511 |
|
| 1512 | serdes_rd(ctx, lane, RXTX_REG127, &val);
|
| 1513 | val = RXTX_REG127_DO_LATCH_MANCAL_SET(val,
|
| 1514 | xgene_phy_get_avg(lat_do, max_loop));
|
| 1515 | val = RXTX_REG127_XO_LATCH_MANCAL_SET(val,
|
| 1516 | xgene_phy_get_avg(lat_xo, max_loop));
|
| 1517 | serdes_wr(ctx, lane, RXTX_REG127, val);
|
| 1518 |
|
| 1519 | serdes_rd(ctx, lane, RXTX_REG128, &val);
|
| 1520 | val = RXTX_REG128_EO_LATCH_MANCAL_SET(val,
|
| 1521 | xgene_phy_get_avg(lat_eo, max_loop));
|
| 1522 | val = RXTX_REG128_SO_LATCH_MANCAL_SET(val,
|
| 1523 | xgene_phy_get_avg(lat_so, max_loop));
|
| 1524 | serdes_wr(ctx, lane, RXTX_REG128, val);
|
| 1525 |
|
| 1526 | serdes_rd(ctx, lane, RXTX_REG129, &val);
|
| 1527 | val = RXTX_REG129_DE_LATCH_MANCAL_SET(val,
|
| 1528 | xgene_phy_get_avg(lat_de, max_loop));
|
| 1529 | val = RXTX_REG129_XE_LATCH_MANCAL_SET(val,
|
| 1530 | xgene_phy_get_avg(lat_xe, max_loop));
|
| 1531 | serdes_wr(ctx, lane, RXTX_REG129, val);
|
| 1532 |
|
| 1533 | serdes_rd(ctx, lane, RXTX_REG130, &val);
|
| 1534 | val = RXTX_REG130_EE_LATCH_MANCAL_SET(val,
|
| 1535 | xgene_phy_get_avg(lat_ee, max_loop));
|
| 1536 | val = RXTX_REG130_SE_LATCH_MANCAL_SET(val,
|
| 1537 | xgene_phy_get_avg(lat_se, max_loop));
|
| 1538 | serdes_wr(ctx, lane, RXTX_REG130, val);
|
| 1539 |
|
| 1540 |
|
| 1541 | serdes_rd(ctx, lane, RXTX_REG14, &val);
|
| 1542 | val = RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(val,
|
| 1543 | xgene_phy_get_avg(sum_cal, max_loop));
|
| 1544 | serdes_wr(ctx, lane, RXTX_REG14, val);
|
| 1545 |
|
| 1546 | dev_dbg(ctx->dev, "Average Value:\n");
|
| 1547 | dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
|
| 1548 | xgene_phy_get_avg(lat_do, max_loop),
|
| 1549 | xgene_phy_get_avg(lat_xo, max_loop),
|
| 1550 | xgene_phy_get_avg(lat_eo, max_loop),
|
| 1551 | xgene_phy_get_avg(lat_so, max_loop));
|
| 1552 | dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
|
| 1553 | xgene_phy_get_avg(lat_de, max_loop),
|
| 1554 | xgene_phy_get_avg(lat_xe, max_loop),
|
| 1555 | xgene_phy_get_avg(lat_ee, max_loop),
|
| 1556 | xgene_phy_get_avg(lat_se, max_loop));
|
| 1557 | dev_dbg(ctx->dev, "SUM 0x%x\n",
|
| 1558 | xgene_phy_get_avg(sum_cal, max_loop));
|
| 1559 |
|
| 1560 | serdes_rd(ctx, lane, RXTX_REG14, &val);
|
| 1561 | val = RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(val, 0x1);
|
| 1562 | serdes_wr(ctx, lane, RXTX_REG14, val);
|
| 1563 | dev_dbg(ctx->dev, "Enable Manual Summer calibration\n");
|
| 1564 |
|
| 1565 | serdes_rd(ctx, lane, RXTX_REG127, &val);
|
| 1566 | val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x1);
|
| 1567 | dev_dbg(ctx->dev, "Enable Manual Latch calibration\n");
|
| 1568 | serdes_wr(ctx, lane, RXTX_REG127, val);
|
| 1569 |
|
| 1570 |
|
| 1571 | serdes_rd(ctx, lane, RXTX_REG12, &val);
|
| 1572 | val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0);
|
| 1573 | serdes_wr(ctx, lane, RXTX_REG12, val);
|
| 1574 |
|
| 1575 | serdes_wr(ctx, lane, RXTX_REG28, 0x0007);
|
| 1576 |
|
| 1577 | serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
|
| 1578 | }
|
| 1579 |
|
| 1580 | static int xgene_phy_hw_init(struct phy *phy)
|
| 1581 | {
|
| 1582 | struct xgene_phy_ctx *ctx = phy_get_drvdata(phy);
|
| 1583 | int rc;
|
| 1584 | int i;
|
| 1585 |
|
| 1586 | rc = xgene_phy_hw_initialize(ctx, CLK_EXT_DIFF, SSC_DISABLE);
|
| 1587 | if (rc) {
|
| 1588 | dev_err(ctx->dev, "PHY initialize failed %d\n", rc);
|
| 1589 | return rc;
|
| 1590 | }
|
| 1591 |
|
| 1592 |
|
| 1593 | if (!IS_ERR(ctx->clk)) {
|
| 1594 |
|
| 1595 | clk_prepare_enable(ctx->clk);
|
| 1596 | clk_disable_unprepare(ctx->clk);
|
| 1597 | clk_prepare_enable(ctx->clk);
|
| 1598 | }
|
| 1599 |
|
| 1600 |
|
| 1601 | for (i = 0; i < MAX_LANE; i++)
|
| 1602 | xgene_phy_gen_avg_val(ctx, i);
|
| 1603 |
|
| 1604 | dev_dbg(ctx->dev, "PHY initialized\n");
|
| 1605 | return 0;
|
| 1606 | }
|
| 1607 |
|
| 1608 | static const struct phy_ops xgene_phy_ops = {
|
| 1609 | .init = xgene_phy_hw_init,
|
| 1610 | .owner = THIS_MODULE,
|
| 1611 | };
|
| 1612 |
|
| 1613 | static struct phy *xgene_phy_xlate(struct device *dev,
|
| 1614 | const struct of_phandle_args *args)
|
| 1615 | {
|
| 1616 | struct xgene_phy_ctx *ctx = dev_get_drvdata(dev);
|
| 1617 |
|
| 1618 | if (args->args_count <= 0)
|
| 1619 | return ERR_PTR(-EINVAL);
|
| 1620 | if (args->args[0] >= MODE_MAX)
|
| 1621 | return ERR_PTR(-EINVAL);
|
| 1622 |
|
| 1623 | ctx->mode = args->args[0];
|
| 1624 | return ctx->phy;
|
| 1625 | }
|
| 1626 |
|
| 1627 | static void xgene_phy_get_param(struct platform_device *pdev,
|
| 1628 | const char *name, u32 *buffer,
|
| 1629 | int count, u32 *default_val,
|
| 1630 | u32 conv_factor)
|
| 1631 | {
|
| 1632 | int i;
|
| 1633 |
|
| 1634 | if (!of_property_read_u32_array(pdev->dev.of_node, name, buffer,
|
| 1635 | count)) {
|
| 1636 | for (i = 0; i < count; i++)
|
| 1637 | buffer[i] /= conv_factor;
|
| 1638 | return;
|
| 1639 | }
|
| 1640 |
|
| 1641 | for (i = 0; i < count; i++)
|
| 1642 | buffer[i] = default_val[i % 3];
|
| 1643 | }
|
| 1644 |
|
| 1645 | static int xgene_phy_probe(struct platform_device *pdev)
|
| 1646 | {
|
| 1647 | struct phy_provider *phy_provider;
|
| 1648 | struct xgene_phy_ctx *ctx;
|
| 1649 | u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
|
| 1650 | u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
|
| 1651 | u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
|
| 1652 | u32 default_txeye_tuning[] = DEFAULT_SATA_TXEYETUNING;
|
| 1653 | u32 default_txamp[] = DEFAULT_SATA_TXAMP;
|
| 1654 | u32 default_txcn1[] = DEFAULT_SATA_TXCN1;
|
| 1655 | u32 default_txcn2[] = DEFAULT_SATA_TXCN2;
|
| 1656 | u32 default_txcp1[] = DEFAULT_SATA_TXCP1;
|
| 1657 | int i;
|
| 1658 |
|
| 1659 | ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
|
| 1660 | if (!ctx)
|
| 1661 | return -ENOMEM;
|
| 1662 |
|
| 1663 | ctx->dev = &pdev->dev;
|
| 1664 |
|
| 1665 | ctx->sds_base = devm_platform_ioremap_resource(pdev, 0);
|
| 1666 | if (IS_ERR(ctx->sds_base))
|
| 1667 | return PTR_ERR(ctx->sds_base);
|
| 1668 |
|
| 1669 |
|
| 1670 | ctx->clk = clk_get(&pdev->dev, NULL);
|
| 1671 |
|
| 1672 |
|
| 1673 | xgene_phy_get_param(pdev, "apm,tx-eye-tuning",
|
| 1674 | ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1);
|
| 1675 | xgene_phy_get_param(pdev, "apm,tx-eye-direction",
|
| 1676 | ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1);
|
| 1677 | xgene_phy_get_param(pdev, "apm,tx-boost-gain",
|
| 1678 | ctx->sata_param.txboostgain, 6, default_txboost_gain, 1);
|
| 1679 | xgene_phy_get_param(pdev, "apm,tx-amplitude",
|
| 1680 | ctx->sata_param.txamplitude, 6, default_txamp, 13300);
|
| 1681 | xgene_phy_get_param(pdev, "apm,tx-pre-cursor1",
|
| 1682 | ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200);
|
| 1683 | xgene_phy_get_param(pdev, "apm,tx-pre-cursor2",
|
| 1684 | ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200);
|
| 1685 | xgene_phy_get_param(pdev, "apm,tx-post-cursor",
|
| 1686 | ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200);
|
| 1687 | xgene_phy_get_param(pdev, "apm,tx-speed",
|
| 1688 | ctx->sata_param.txspeed, 3, default_spd, 1);
|
| 1689 | for (i = 0; i < MAX_LANE; i++)
|
| 1690 | ctx->sata_param.speed[i] = 2;
|
| 1691 |
|
| 1692 | platform_set_drvdata(pdev, ctx);
|
| 1693 |
|
| 1694 | ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
|
| 1695 | if (IS_ERR(ctx->phy)) {
|
| 1696 | dev_dbg(&pdev->dev, "Failed to create PHY\n");
|
| 1697 | return PTR_ERR(ctx->phy);
|
| 1698 | }
|
| 1699 | phy_set_drvdata(ctx->phy, ctx);
|
| 1700 |
|
| 1701 | phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate);
|
| 1702 | return PTR_ERR_OR_ZERO(phy_provider);
|
| 1703 | }
|
| 1704 |
|
| 1705 | static const struct of_device_id xgene_phy_of_match[] = {
|
| 1706 | {.compatible = "apm,xgene-phy",},
|
| 1707 | {},
|
| 1708 | };
|
| 1709 | MODULE_DEVICE_TABLE(of, xgene_phy_of_match);
|
| 1710 |
|
| 1711 | static struct platform_driver xgene_phy_driver = {
|
| 1712 | .probe = xgene_phy_probe,
|
| 1713 | .driver = {
|
| 1714 | .name = "xgene-phy",
|
| 1715 | .of_match_table = xgene_phy_of_match,
|
| 1716 | },
|
| 1717 | };
|
| 1718 | module_platform_driver(xgene_phy_driver);
|
| 1719 |
|
| 1720 | MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver");
|
| 1721 | MODULE_AUTHOR("Loc Ho <[email protected]>");
|
| 1722 | MODULE_LICENSE("GPL v2");
|
| 1723 | MODULE_VERSION("0.1");
|