11ccea77eSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
288e670feSLoc Ho /*
388e670feSLoc Ho * AppliedMicro X-Gene Multi-purpose PHY driver
488e670feSLoc Ho *
588e670feSLoc Ho * Copyright (c) 2014, Applied Micro Circuits Corporation
688e670feSLoc Ho * Author: Loc Ho <lho@apm.com>
788e670feSLoc Ho * Tuan Phan <tphan@apm.com>
888e670feSLoc Ho * Suman Tripathi <stripathi@apm.com>
988e670feSLoc Ho *
1088e670feSLoc Ho * The APM X-Gene PHY consists of two PLL clock macro's (CMU) and lanes.
1188e670feSLoc Ho * The first PLL clock macro is used for internal reference clock. The second
1288e670feSLoc Ho * PLL clock macro is used to generate the clock for the PHY. This driver
1388e670feSLoc Ho * configures the first PLL CMU, the second PLL CMU, and programs the PHY to
1488e670feSLoc Ho * operate according to the mode of operation. The first PLL CMU is only
1588e670feSLoc Ho * required if internal clock is enabled.
1688e670feSLoc Ho *
1788e670feSLoc Ho * Logical Layer Out Of HW module units:
1888e670feSLoc Ho *
1988e670feSLoc Ho * -----------------
2088e670feSLoc Ho * | Internal | |------|
2188e670feSLoc Ho * | Ref PLL CMU |----| | ------------- ---------
2288e670feSLoc Ho * ------------ ---- | MUX |-----|PHY PLL CMU|----| Serdes|
2388e670feSLoc Ho * | | | | ---------
2488e670feSLoc Ho * External Clock ------| | -------------
2588e670feSLoc Ho * |------|
2688e670feSLoc Ho *
2788e670feSLoc Ho * The Ref PLL CMU CSR (Configuration System Registers) is accessed
2888e670feSLoc Ho * indirectly from the SDS offset at 0x2000. It is only required for
2988e670feSLoc Ho * internal reference clock.
3088e670feSLoc Ho * The PHY PLL CMU CSR is accessed indirectly from the SDS offset at 0x0000.
3188e670feSLoc Ho * The Serdes CSR is accessed indirectly from the SDS offset at 0x0400.
3288e670feSLoc Ho *
3388e670feSLoc Ho * The Ref PLL CMU can be located within the same PHY IP or outside the PHY IP
3488e670feSLoc Ho * due to shared Ref PLL CMU. For PHY with Ref PLL CMU shared with another IP,
3588e670feSLoc Ho * it is located outside the PHY IP. This is the case for the PHY located
3688e670feSLoc Ho * at 0x1f23a000 (SATA Port 4/5). For such PHY, another resource is required
3788e670feSLoc Ho * to located the SDS/Ref PLL CMU module and its clock for that IP enabled.
3888e670feSLoc Ho *
3988e670feSLoc Ho * Currently, this driver only supports Gen3 SATA mode with external clock.
4088e670feSLoc Ho */
4188e670feSLoc Ho #include <linux/module.h>
42*7559e757SRob Herring #include <linux/of.h>
4388e670feSLoc Ho #include <linux/platform_device.h>
4488e670feSLoc Ho #include <linux/io.h>
4588e670feSLoc Ho #include <linux/delay.h>
4688e670feSLoc Ho #include <linux/phy/phy.h>
4788e670feSLoc Ho #include <linux/clk.h>
4888e670feSLoc Ho
4988e670feSLoc Ho /* Max 2 lanes per a PHY unit */
5088e670feSLoc Ho #define MAX_LANE 2
5188e670feSLoc Ho
5288e670feSLoc Ho /* Register offset inside the PHY */
5388e670feSLoc Ho #define SERDES_PLL_INDIRECT_OFFSET 0x0000
5488e670feSLoc Ho #define SERDES_PLL_REF_INDIRECT_OFFSET 0x2000
5588e670feSLoc Ho #define SERDES_INDIRECT_OFFSET 0x0400
5688e670feSLoc Ho #define SERDES_LANE_STRIDE 0x0200
5788e670feSLoc Ho
5888e670feSLoc Ho /* Some default Serdes parameters */
5988e670feSLoc Ho #define DEFAULT_SATA_TXBOOST_GAIN { 0x1e, 0x1e, 0x1e }
6088e670feSLoc Ho #define DEFAULT_SATA_TXEYEDIRECTION { 0x0, 0x0, 0x0 }
6188e670feSLoc Ho #define DEFAULT_SATA_TXEYETUNING { 0xa, 0xa, 0xa }
6288e670feSLoc Ho #define DEFAULT_SATA_SPD_SEL { 0x1, 0x3, 0x7 }
6388e670feSLoc Ho #define DEFAULT_SATA_TXAMP { 0x8, 0x8, 0x8 }
6488e670feSLoc Ho #define DEFAULT_SATA_TXCN1 { 0x2, 0x2, 0x2 }
6588e670feSLoc Ho #define DEFAULT_SATA_TXCN2 { 0x0, 0x0, 0x0 }
6688e670feSLoc Ho #define DEFAULT_SATA_TXCP1 { 0xa, 0xa, 0xa }
6788e670feSLoc Ho
6888e670feSLoc Ho #define SATA_SPD_SEL_GEN3 0x7
6988e670feSLoc Ho #define SATA_SPD_SEL_GEN2 0x3
7088e670feSLoc Ho #define SATA_SPD_SEL_GEN1 0x1
7188e670feSLoc Ho
7288e670feSLoc Ho #define SSC_DISABLE 0
7388e670feSLoc Ho #define SSC_ENABLE 1
7488e670feSLoc Ho
7588e670feSLoc Ho #define FBDIV_VAL_50M 0x77
7688e670feSLoc Ho #define REFDIV_VAL_50M 0x1
7788e670feSLoc Ho #define FBDIV_VAL_100M 0x3B
7888e670feSLoc Ho #define REFDIV_VAL_100M 0x0
7988e670feSLoc Ho
8088e670feSLoc Ho /* SATA Clock/Reset CSR */
8188e670feSLoc Ho #define SATACLKENREG 0x00000000
8288e670feSLoc Ho #define SATA0_CORE_CLKEN 0x00000002
8388e670feSLoc Ho #define SATA1_CORE_CLKEN 0x00000004
8488e670feSLoc Ho #define SATASRESETREG 0x00000004
8588e670feSLoc Ho #define SATA_MEM_RESET_MASK 0x00000020
8688e670feSLoc Ho #define SATA_MEM_RESET_RD(src) (((src) & 0x00000020) >> 5)
8788e670feSLoc Ho #define SATA_SDS_RESET_MASK 0x00000004
8888e670feSLoc Ho #define SATA_CSR_RESET_MASK 0x00000001
8988e670feSLoc Ho #define SATA_CORE_RESET_MASK 0x00000002
9088e670feSLoc Ho #define SATA_PMCLK_RESET_MASK 0x00000010
9188e670feSLoc Ho #define SATA_PCLK_RESET_MASK 0x00000008
9288e670feSLoc Ho
9388e670feSLoc Ho /* SDS CSR used for PHY Indirect access */
9488e670feSLoc Ho #define SATA_ENET_SDS_PCS_CTL0 0x00000000
9588e670feSLoc Ho #define REGSPEC_CFG_I_TX_WORDMODE0_SET(dst, src) \
9688e670feSLoc Ho (((dst) & ~0x00070000) | (((u32) (src) << 16) & 0x00070000))
9788e670feSLoc Ho #define REGSPEC_CFG_I_RX_WORDMODE0_SET(dst, src) \
9888e670feSLoc Ho (((dst) & ~0x00e00000) | (((u32) (src) << 21) & 0x00e00000))
9988e670feSLoc Ho #define SATA_ENET_SDS_CTL0 0x0000000c
10088e670feSLoc Ho #define REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(dst, src) \
10188e670feSLoc Ho (((dst) & ~0x00007fff) | (((u32) (src)) & 0x00007fff))
10288e670feSLoc Ho #define SATA_ENET_SDS_CTL1 0x00000010
10388e670feSLoc Ho #define CFG_I_SPD_SEL_CDR_OVR1_SET(dst, src) \
10488e670feSLoc Ho (((dst) & ~0x0000000f) | (((u32) (src)) & 0x0000000f))
10588e670feSLoc Ho #define SATA_ENET_SDS_RST_CTL 0x00000024
10688e670feSLoc Ho #define SATA_ENET_SDS_IND_CMD_REG 0x0000003c
10788e670feSLoc Ho #define CFG_IND_WR_CMD_MASK 0x00000001
10888e670feSLoc Ho #define CFG_IND_RD_CMD_MASK 0x00000002
10988e670feSLoc Ho #define CFG_IND_CMD_DONE_MASK 0x00000004
11088e670feSLoc Ho #define CFG_IND_ADDR_SET(dst, src) \
11188e670feSLoc Ho (((dst) & ~0x003ffff0) | (((u32) (src) << 4) & 0x003ffff0))
11288e670feSLoc Ho #define SATA_ENET_SDS_IND_RDATA_REG 0x00000040
11388e670feSLoc Ho #define SATA_ENET_SDS_IND_WDATA_REG 0x00000044
11488e670feSLoc Ho #define SATA_ENET_CLK_MACRO_REG 0x0000004c
11588e670feSLoc Ho #define I_RESET_B_SET(dst, src) \
11688e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src)) & 0x00000001))
11788e670feSLoc Ho #define I_PLL_FBDIV_SET(dst, src) \
11888e670feSLoc Ho (((dst) & ~0x001ff000) | (((u32) (src) << 12) & 0x001ff000))
11988e670feSLoc Ho #define I_CUSTOMEROV_SET(dst, src) \
12088e670feSLoc Ho (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
12188e670feSLoc Ho #define O_PLL_LOCK_RD(src) (((src) & 0x40000000) >> 30)
12288e670feSLoc Ho #define O_PLL_READY_RD(src) (((src) & 0x80000000) >> 31)
12388e670feSLoc Ho
12488e670feSLoc Ho /* PLL Clock Macro Unit (CMU) CSR accessing from SDS indirectly */
12588e670feSLoc Ho #define CMU_REG0 0x00000
12688e670feSLoc Ho #define CMU_REG0_PLL_REF_SEL_MASK 0x00002000
12788e670feSLoc Ho #define CMU_REG0_PLL_REF_SEL_SET(dst, src) \
12888e670feSLoc Ho (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
12988e670feSLoc Ho #define CMU_REG0_PDOWN_MASK 0x00004000
13088e670feSLoc Ho #define CMU_REG0_CAL_COUNT_RESOL_SET(dst, src) \
13188e670feSLoc Ho (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
13288e670feSLoc Ho #define CMU_REG1 0x00002
13388e670feSLoc Ho #define CMU_REG1_PLL_CP_SET(dst, src) \
13488e670feSLoc Ho (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
13588e670feSLoc Ho #define CMU_REG1_PLL_MANUALCAL_SET(dst, src) \
13688e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
13788e670feSLoc Ho #define CMU_REG1_PLL_CP_SEL_SET(dst, src) \
13888e670feSLoc Ho (((dst) & ~0x000003e0) | (((u32) (src) << 5) & 0x000003e0))
13988e670feSLoc Ho #define CMU_REG1_REFCLK_CMOS_SEL_MASK 0x00000001
14088e670feSLoc Ho #define CMU_REG1_REFCLK_CMOS_SEL_SET(dst, src) \
14188e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
14288e670feSLoc Ho #define CMU_REG2 0x00004
14388e670feSLoc Ho #define CMU_REG2_PLL_REFDIV_SET(dst, src) \
14488e670feSLoc Ho (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
14588e670feSLoc Ho #define CMU_REG2_PLL_LFRES_SET(dst, src) \
14688e670feSLoc Ho (((dst) & ~0x0000001e) | (((u32) (src) << 1) & 0x0000001e))
14788e670feSLoc Ho #define CMU_REG2_PLL_FBDIV_SET(dst, src) \
14888e670feSLoc Ho (((dst) & ~0x00003fe0) | (((u32) (src) << 5) & 0x00003fe0))
14988e670feSLoc Ho #define CMU_REG3 0x00006
15088e670feSLoc Ho #define CMU_REG3_VCOVARSEL_SET(dst, src) \
15188e670feSLoc Ho (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
15288e670feSLoc Ho #define CMU_REG3_VCO_MOMSEL_INIT_SET(dst, src) \
15388e670feSLoc Ho (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
15488e670feSLoc Ho #define CMU_REG3_VCO_MANMOMSEL_SET(dst, src) \
15588e670feSLoc Ho (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
15688e670feSLoc Ho #define CMU_REG4 0x00008
15788e670feSLoc Ho #define CMU_REG5 0x0000a
15888e670feSLoc Ho #define CMU_REG5_PLL_LFSMCAP_SET(dst, src) \
15988e670feSLoc Ho (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
16088e670feSLoc Ho #define CMU_REG5_PLL_LOCK_RESOLUTION_SET(dst, src) \
16188e670feSLoc Ho (((dst) & ~0x0000000e) | (((u32) (src) << 1) & 0x0000000e))
16288e670feSLoc Ho #define CMU_REG5_PLL_LFCAP_SET(dst, src) \
16388e670feSLoc Ho (((dst) & ~0x00003000) | (((u32) (src) << 12) & 0x00003000))
16488e670feSLoc Ho #define CMU_REG5_PLL_RESETB_MASK 0x00000001
16588e670feSLoc Ho #define CMU_REG6 0x0000c
16688e670feSLoc Ho #define CMU_REG6_PLL_VREGTRIM_SET(dst, src) \
16788e670feSLoc Ho (((dst) & ~0x00000600) | (((u32) (src) << 9) & 0x00000600))
16888e670feSLoc Ho #define CMU_REG6_MAN_PVT_CAL_SET(dst, src) \
16988e670feSLoc Ho (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
17088e670feSLoc Ho #define CMU_REG7 0x0000e
17188e670feSLoc Ho #define CMU_REG7_PLL_CALIB_DONE_RD(src) ((0x00004000 & (u32) (src)) >> 14)
17288e670feSLoc Ho #define CMU_REG7_VCO_CAL_FAIL_RD(src) ((0x00000c00 & (u32) (src)) >> 10)
17388e670feSLoc Ho #define CMU_REG8 0x00010
17488e670feSLoc Ho #define CMU_REG9 0x00012
17588e670feSLoc Ho #define CMU_REG9_WORD_LEN_8BIT 0x000
17688e670feSLoc Ho #define CMU_REG9_WORD_LEN_10BIT 0x001
17788e670feSLoc Ho #define CMU_REG9_WORD_LEN_16BIT 0x002
17888e670feSLoc Ho #define CMU_REG9_WORD_LEN_20BIT 0x003
17988e670feSLoc Ho #define CMU_REG9_WORD_LEN_32BIT 0x004
18088e670feSLoc Ho #define CMU_REG9_WORD_LEN_40BIT 0x005
18188e670feSLoc Ho #define CMU_REG9_WORD_LEN_64BIT 0x006
18288e670feSLoc Ho #define CMU_REG9_WORD_LEN_66BIT 0x007
18388e670feSLoc Ho #define CMU_REG9_TX_WORD_MODE_CH1_SET(dst, src) \
18488e670feSLoc Ho (((dst) & ~0x00000380) | (((u32) (src) << 7) & 0x00000380))
18588e670feSLoc Ho #define CMU_REG9_TX_WORD_MODE_CH0_SET(dst, src) \
18688e670feSLoc Ho (((dst) & ~0x00000070) | (((u32) (src) << 4) & 0x00000070))
18788e670feSLoc Ho #define CMU_REG9_PLL_POST_DIVBY2_SET(dst, src) \
18888e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
18988e670feSLoc Ho #define CMU_REG9_VBG_BYPASSB_SET(dst, src) \
19088e670feSLoc Ho (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
19188e670feSLoc Ho #define CMU_REG9_IGEN_BYPASS_SET(dst, src) \
19288e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
19388e670feSLoc Ho #define CMU_REG10 0x00014
19488e670feSLoc Ho #define CMU_REG10_VREG_REFSEL_SET(dst, src) \
19588e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
19688e670feSLoc Ho #define CMU_REG11 0x00016
19788e670feSLoc Ho #define CMU_REG12 0x00018
19888e670feSLoc Ho #define CMU_REG12_STATE_DELAY9_SET(dst, src) \
19988e670feSLoc Ho (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
20088e670feSLoc Ho #define CMU_REG13 0x0001a
20188e670feSLoc Ho #define CMU_REG14 0x0001c
20288e670feSLoc Ho #define CMU_REG15 0x0001e
20388e670feSLoc Ho #define CMU_REG16 0x00020
20488e670feSLoc Ho #define CMU_REG16_PVT_DN_MAN_ENA_MASK 0x00000001
20588e670feSLoc Ho #define CMU_REG16_PVT_UP_MAN_ENA_MASK 0x00000002
20688e670feSLoc Ho #define CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(dst, src) \
20788e670feSLoc Ho (((dst) & ~0x0000001c) | (((u32) (src) << 2) & 0x0000001c))
20888e670feSLoc Ho #define CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(dst, src) \
20988e670feSLoc Ho (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
21088e670feSLoc Ho #define CMU_REG16_BYPASS_PLL_LOCK_SET(dst, src) \
21188e670feSLoc Ho (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
21288e670feSLoc Ho #define CMU_REG17 0x00022
21388e670feSLoc Ho #define CMU_REG17_PVT_CODE_R2A_SET(dst, src) \
21488e670feSLoc Ho (((dst) & ~0x00007f00) | (((u32) (src) << 8) & 0x00007f00))
21588e670feSLoc Ho #define CMU_REG17_RESERVED_7_SET(dst, src) \
21688e670feSLoc Ho (((dst) & ~0x000000e0) | (((u32) (src) << 5) & 0x000000e0))
21788e670feSLoc Ho #define CMU_REG17_PVT_TERM_MAN_ENA_MASK 0x00008000
21888e670feSLoc Ho #define CMU_REG18 0x00024
21988e670feSLoc Ho #define CMU_REG19 0x00026
22088e670feSLoc Ho #define CMU_REG20 0x00028
22188e670feSLoc Ho #define CMU_REG21 0x0002a
22288e670feSLoc Ho #define CMU_REG22 0x0002c
22388e670feSLoc Ho #define CMU_REG23 0x0002e
22488e670feSLoc Ho #define CMU_REG24 0x00030
22588e670feSLoc Ho #define CMU_REG25 0x00032
22688e670feSLoc Ho #define CMU_REG26 0x00034
22788e670feSLoc Ho #define CMU_REG26_FORCE_PLL_LOCK_SET(dst, src) \
22888e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
22988e670feSLoc Ho #define CMU_REG27 0x00036
23088e670feSLoc Ho #define CMU_REG28 0x00038
23188e670feSLoc Ho #define CMU_REG29 0x0003a
23288e670feSLoc Ho #define CMU_REG30 0x0003c
23388e670feSLoc Ho #define CMU_REG30_LOCK_COUNT_SET(dst, src) \
23488e670feSLoc Ho (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
23588e670feSLoc Ho #define CMU_REG30_PCIE_MODE_SET(dst, src) \
23688e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
23788e670feSLoc Ho #define CMU_REG31 0x0003e
23888e670feSLoc Ho #define CMU_REG32 0x00040
23988e670feSLoc Ho #define CMU_REG32_FORCE_VCOCAL_START_MASK 0x00004000
24088e670feSLoc Ho #define CMU_REG32_PVT_CAL_WAIT_SEL_SET(dst, src) \
24188e670feSLoc Ho (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
24288e670feSLoc Ho #define CMU_REG32_IREF_ADJ_SET(dst, src) \
24388e670feSLoc Ho (((dst) & ~0x00000180) | (((u32) (src) << 7) & 0x00000180))
24488e670feSLoc Ho #define CMU_REG33 0x00042
24588e670feSLoc Ho #define CMU_REG34 0x00044
24688e670feSLoc Ho #define CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(dst, src) \
24788e670feSLoc Ho (((dst) & ~0x0000000f) | (((u32) (src) << 0) & 0x0000000f))
24888e670feSLoc Ho #define CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(dst, src) \
24988e670feSLoc Ho (((dst) & ~0x00000f00) | (((u32) (src) << 8) & 0x00000f00))
25088e670feSLoc Ho #define CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(dst, src) \
25188e670feSLoc Ho (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
25288e670feSLoc Ho #define CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(dst, src) \
25388e670feSLoc Ho (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
25488e670feSLoc Ho #define CMU_REG35 0x00046
25588e670feSLoc Ho #define CMU_REG35_PLL_SSC_MOD_SET(dst, src) \
25688e670feSLoc Ho (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
25788e670feSLoc Ho #define CMU_REG36 0x00048
25888e670feSLoc Ho #define CMU_REG36_PLL_SSC_EN_SET(dst, src) \
25988e670feSLoc Ho (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
26088e670feSLoc Ho #define CMU_REG36_PLL_SSC_VSTEP_SET(dst, src) \
26188e670feSLoc Ho (((dst) & ~0x0000ffc0) | (((u32) (src) << 6) & 0x0000ffc0))
26288e670feSLoc Ho #define CMU_REG36_PLL_SSC_DSMSEL_SET(dst, src) \
26388e670feSLoc Ho (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
26488e670feSLoc Ho #define CMU_REG37 0x0004a
26588e670feSLoc Ho #define CMU_REG38 0x0004c
26688e670feSLoc Ho #define CMU_REG39 0x0004e
26788e670feSLoc Ho
26888e670feSLoc Ho /* PHY lane CSR accessing from SDS indirectly */
26988e670feSLoc Ho #define RXTX_REG0 0x000
27088e670feSLoc Ho #define RXTX_REG0_CTLE_EQ_HR_SET(dst, src) \
27188e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
27288e670feSLoc Ho #define RXTX_REG0_CTLE_EQ_QR_SET(dst, src) \
27388e670feSLoc Ho (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
27488e670feSLoc Ho #define RXTX_REG0_CTLE_EQ_FR_SET(dst, src) \
27588e670feSLoc Ho (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
27688e670feSLoc Ho #define RXTX_REG1 0x002
27788e670feSLoc Ho #define RXTX_REG1_RXACVCM_SET(dst, src) \
27888e670feSLoc Ho (((dst) & ~0x0000f000) | (((u32) (src) << 12) & 0x0000f000))
27988e670feSLoc Ho #define RXTX_REG1_CTLE_EQ_SET(dst, src) \
28088e670feSLoc Ho (((dst) & ~0x00000f80) | (((u32) (src) << 7) & 0x00000f80))
28188e670feSLoc Ho #define RXTX_REG1_RXVREG1_SET(dst, src) \
28288e670feSLoc Ho (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
28388e670feSLoc Ho #define RXTX_REG1_RXIREF_ADJ_SET(dst, src) \
28488e670feSLoc Ho (((dst) & ~0x00000006) | (((u32) (src) << 1) & 0x00000006))
28588e670feSLoc Ho #define RXTX_REG2 0x004
28688e670feSLoc Ho #define RXTX_REG2_VTT_ENA_SET(dst, src) \
28788e670feSLoc Ho (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
28888e670feSLoc Ho #define RXTX_REG2_TX_FIFO_ENA_SET(dst, src) \
28988e670feSLoc Ho (((dst) & ~0x00000020) | (((u32) (src) << 5) & 0x00000020))
29088e670feSLoc Ho #define RXTX_REG2_VTT_SEL_SET(dst, src) \
29188e670feSLoc Ho (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
29288e670feSLoc Ho #define RXTX_REG4 0x008
29388e670feSLoc Ho #define RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK 0x00000040
29488e670feSLoc Ho #define RXTX_REG4_TX_DATA_RATE_SET(dst, src) \
29588e670feSLoc Ho (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
29688e670feSLoc Ho #define RXTX_REG4_TX_WORD_MODE_SET(dst, src) \
29788e670feSLoc Ho (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
29888e670feSLoc Ho #define RXTX_REG5 0x00a
29988e670feSLoc Ho #define RXTX_REG5_TX_CN1_SET(dst, src) \
30088e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
30188e670feSLoc Ho #define RXTX_REG5_TX_CP1_SET(dst, src) \
30288e670feSLoc Ho (((dst) & ~0x000007e0) | (((u32) (src) << 5) & 0x000007e0))
30388e670feSLoc Ho #define RXTX_REG5_TX_CN2_SET(dst, src) \
30488e670feSLoc Ho (((dst) & ~0x0000001f) | (((u32) (src) << 0) & 0x0000001f))
30588e670feSLoc Ho #define RXTX_REG6 0x00c
30688e670feSLoc Ho #define RXTX_REG6_TXAMP_CNTL_SET(dst, src) \
30788e670feSLoc Ho (((dst) & ~0x00000780) | (((u32) (src) << 7) & 0x00000780))
30888e670feSLoc Ho #define RXTX_REG6_TXAMP_ENA_SET(dst, src) \
30988e670feSLoc Ho (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
31088e670feSLoc Ho #define RXTX_REG6_RX_BIST_ERRCNT_RD_SET(dst, src) \
31188e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
31288e670feSLoc Ho #define RXTX_REG6_TX_IDLE_SET(dst, src) \
31388e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
31488e670feSLoc Ho #define RXTX_REG6_RX_BIST_RESYNC_SET(dst, src) \
31588e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
31688e670feSLoc Ho #define RXTX_REG7 0x00e
31788e670feSLoc Ho #define RXTX_REG7_RESETB_RXD_MASK 0x00000100
31888e670feSLoc Ho #define RXTX_REG7_RESETB_RXA_MASK 0x00000080
31988e670feSLoc Ho #define RXTX_REG7_BIST_ENA_RX_SET(dst, src) \
32088e670feSLoc Ho (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
32188e670feSLoc Ho #define RXTX_REG7_RX_WORD_MODE_SET(dst, src) \
32288e670feSLoc Ho (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
32388e670feSLoc Ho #define RXTX_REG8 0x010
32488e670feSLoc Ho #define RXTX_REG8_CDR_LOOP_ENA_SET(dst, src) \
32588e670feSLoc Ho (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
32688e670feSLoc Ho #define RXTX_REG8_CDR_BYPASS_RXLOS_SET(dst, src) \
32788e670feSLoc Ho (((dst) & ~0x00000800) | (((u32) (src) << 11) & 0x00000800))
32888e670feSLoc Ho #define RXTX_REG8_SSC_ENABLE_SET(dst, src) \
32988e670feSLoc Ho (((dst) & ~0x00000200) | (((u32) (src) << 9) & 0x00000200))
33088e670feSLoc Ho #define RXTX_REG8_SD_VREF_SET(dst, src) \
33188e670feSLoc Ho (((dst) & ~0x000000f0) | (((u32) (src) << 4) & 0x000000f0))
33288e670feSLoc Ho #define RXTX_REG8_SD_DISABLE_SET(dst, src) \
33388e670feSLoc Ho (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
33488e670feSLoc Ho #define RXTX_REG7 0x00e
33588e670feSLoc Ho #define RXTX_REG7_RESETB_RXD_SET(dst, src) \
33688e670feSLoc Ho (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
33788e670feSLoc Ho #define RXTX_REG7_RESETB_RXA_SET(dst, src) \
33888e670feSLoc Ho (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
33988e670feSLoc Ho #define RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK 0x00004000
34088e670feSLoc Ho #define RXTX_REG7_LOOP_BACK_ENA_CTLE_SET(dst, src) \
34188e670feSLoc Ho (((dst) & ~0x00004000) | (((u32) (src) << 14) & 0x00004000))
34288e670feSLoc Ho #define RXTX_REG11 0x016
34388e670feSLoc Ho #define RXTX_REG11_PHASE_ADJUST_LIMIT_SET(dst, src) \
34488e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
34588e670feSLoc Ho #define RXTX_REG12 0x018
34688e670feSLoc Ho #define RXTX_REG12_LATCH_OFF_ENA_SET(dst, src) \
34788e670feSLoc Ho (((dst) & ~0x00002000) | (((u32) (src) << 13) & 0x00002000))
34888e670feSLoc Ho #define RXTX_REG12_SUMOS_ENABLE_SET(dst, src) \
34988e670feSLoc Ho (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
35088e670feSLoc Ho #define RXTX_REG12_RX_DET_TERM_ENABLE_MASK 0x00000002
35188e670feSLoc Ho #define RXTX_REG12_RX_DET_TERM_ENABLE_SET(dst, src) \
35288e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
35388e670feSLoc Ho #define RXTX_REG13 0x01a
35488e670feSLoc Ho #define RXTX_REG14 0x01c
35588e670feSLoc Ho #define RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(dst, src) \
35688e670feSLoc Ho (((dst) & ~0x0000003f) | (((u32) (src) << 0) & 0x0000003f))
35788e670feSLoc Ho #define RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(dst, src) \
35888e670feSLoc Ho (((dst) & ~0x00000040) | (((u32) (src) << 6) & 0x00000040))
35988e670feSLoc Ho #define RXTX_REG26 0x034
36088e670feSLoc Ho #define RXTX_REG26_PERIOD_ERROR_LATCH_SET(dst, src) \
36188e670feSLoc Ho (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
36288e670feSLoc Ho #define RXTX_REG26_BLWC_ENA_SET(dst, src) \
36388e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
36488e670feSLoc Ho #define RXTX_REG21 0x02a
36588e670feSLoc Ho #define RXTX_REG21_DO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
36688e670feSLoc Ho #define RXTX_REG21_XO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
36788e670feSLoc Ho #define RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(src) ((0x0000000f & (u32)(src)))
36888e670feSLoc Ho #define RXTX_REG22 0x02c
36988e670feSLoc Ho #define RXTX_REG22_SO_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
37088e670feSLoc Ho #define RXTX_REG22_EO_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
37188e670feSLoc Ho #define RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(src) ((0x0000000f & (u32)(src)))
37288e670feSLoc Ho #define RXTX_REG23 0x02e
37388e670feSLoc Ho #define RXTX_REG23_DE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
37488e670feSLoc Ho #define RXTX_REG23_XE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
37588e670feSLoc Ho #define RXTX_REG24 0x030
37688e670feSLoc Ho #define RXTX_REG24_EE_LATCH_CALOUT_RD(src) ((0x0000fc00 & (u32) (src)) >> 10)
37788e670feSLoc Ho #define RXTX_REG24_SE_LATCH_CALOUT_RD(src) ((0x000003f0 & (u32) (src)) >> 4)
37888e670feSLoc Ho #define RXTX_REG27 0x036
37988e670feSLoc Ho #define RXTX_REG28 0x038
38088e670feSLoc Ho #define RXTX_REG31 0x03e
38188e670feSLoc Ho #define RXTX_REG38 0x04c
38288e670feSLoc Ho #define RXTX_REG38_CUSTOMER_PINMODE_INV_SET(dst, src) \
38388e670feSLoc Ho (((dst) & 0x0000fffe) | (((u32) (src) << 1) & 0x0000fffe))
38488e670feSLoc Ho #define RXTX_REG39 0x04e
38588e670feSLoc Ho #define RXTX_REG40 0x050
38688e670feSLoc Ho #define RXTX_REG41 0x052
38788e670feSLoc Ho #define RXTX_REG42 0x054
38888e670feSLoc Ho #define RXTX_REG43 0x056
38988e670feSLoc Ho #define RXTX_REG44 0x058
39088e670feSLoc Ho #define RXTX_REG45 0x05a
39188e670feSLoc Ho #define RXTX_REG46 0x05c
39288e670feSLoc Ho #define RXTX_REG47 0x05e
39388e670feSLoc Ho #define RXTX_REG48 0x060
39488e670feSLoc Ho #define RXTX_REG49 0x062
39588e670feSLoc Ho #define RXTX_REG50 0x064
39688e670feSLoc Ho #define RXTX_REG51 0x066
39788e670feSLoc Ho #define RXTX_REG52 0x068
39888e670feSLoc Ho #define RXTX_REG53 0x06a
39988e670feSLoc Ho #define RXTX_REG54 0x06c
40088e670feSLoc Ho #define RXTX_REG55 0x06e
40188e670feSLoc Ho #define RXTX_REG61 0x07a
40288e670feSLoc Ho #define RXTX_REG61_ISCAN_INBERT_SET(dst, src) \
40388e670feSLoc Ho (((dst) & ~0x00000010) | (((u32) (src) << 4) & 0x00000010))
40488e670feSLoc Ho #define RXTX_REG61_LOADFREQ_SHIFT_SET(dst, src) \
40588e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
40688e670feSLoc Ho #define RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(dst, src) \
40788e670feSLoc Ho (((dst) & ~0x000000c0) | (((u32) (src) << 6) & 0x000000c0))
40888e670feSLoc Ho #define RXTX_REG61_SPD_SEL_CDR_SET(dst, src) \
40988e670feSLoc Ho (((dst) & ~0x00003c00) | (((u32) (src) << 10) & 0x00003c00))
41088e670feSLoc Ho #define RXTX_REG62 0x07c
41188e670feSLoc Ho #define RXTX_REG62_PERIOD_H1_QLATCH_SET(dst, src) \
41288e670feSLoc Ho (((dst) & ~0x00003800) | (((u32) (src) << 11) & 0x00003800))
41388e670feSLoc Ho #define RXTX_REG81 0x0a2
41488e670feSLoc Ho #define RXTX_REG89_MU_TH7_SET(dst, src) \
41588e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
41688e670feSLoc Ho #define RXTX_REG89_MU_TH8_SET(dst, src) \
41788e670feSLoc Ho (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
41888e670feSLoc Ho #define RXTX_REG89_MU_TH9_SET(dst, src) \
41988e670feSLoc Ho (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
42088e670feSLoc Ho #define RXTX_REG96 0x0c0
42188e670feSLoc Ho #define RXTX_REG96_MU_FREQ1_SET(dst, src) \
42288e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
42388e670feSLoc Ho #define RXTX_REG96_MU_FREQ2_SET(dst, src) \
42488e670feSLoc Ho (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
42588e670feSLoc Ho #define RXTX_REG96_MU_FREQ3_SET(dst, src) \
42688e670feSLoc Ho (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
42788e670feSLoc Ho #define RXTX_REG99 0x0c6
42888e670feSLoc Ho #define RXTX_REG99_MU_PHASE1_SET(dst, src) \
42988e670feSLoc Ho (((dst) & ~0x0000f800) | (((u32) (src) << 11) & 0x0000f800))
43088e670feSLoc Ho #define RXTX_REG99_MU_PHASE2_SET(dst, src) \
43188e670feSLoc Ho (((dst) & ~0x000007c0) | (((u32) (src) << 6) & 0x000007c0))
43288e670feSLoc Ho #define RXTX_REG99_MU_PHASE3_SET(dst, src) \
43388e670feSLoc Ho (((dst) & ~0x0000003e) | (((u32) (src) << 1) & 0x0000003e))
43488e670feSLoc Ho #define RXTX_REG102 0x0cc
43588e670feSLoc Ho #define RXTX_REG102_FREQLOOP_LIMIT_SET(dst, src) \
43688e670feSLoc Ho (((dst) & ~0x00000060) | (((u32) (src) << 5) & 0x00000060))
43788e670feSLoc Ho #define RXTX_REG114 0x0e4
43888e670feSLoc Ho #define RXTX_REG121 0x0f2
43988e670feSLoc Ho #define RXTX_REG121_SUMOS_CAL_CODE_RD(src) ((0x0000003e & (u32)(src)) >> 0x1)
44088e670feSLoc Ho #define RXTX_REG125 0x0fa
44188e670feSLoc Ho #define RXTX_REG125_PQ_REG_SET(dst, src) \
44288e670feSLoc Ho (((dst) & ~0x0000fe00) | (((u32) (src) << 9) & 0x0000fe00))
44388e670feSLoc Ho #define RXTX_REG125_SIGN_PQ_SET(dst, src) \
44488e670feSLoc Ho (((dst) & ~0x00000100) | (((u32) (src) << 8) & 0x00000100))
44588e670feSLoc Ho #define RXTX_REG125_SIGN_PQ_2C_SET(dst, src) \
44688e670feSLoc Ho (((dst) & ~0x00000080) | (((u32) (src) << 7) & 0x00000080))
44788e670feSLoc Ho #define RXTX_REG125_PHZ_MANUALCODE_SET(dst, src) \
44888e670feSLoc Ho (((dst) & ~0x0000007c) | (((u32) (src) << 2) & 0x0000007c))
44988e670feSLoc Ho #define RXTX_REG125_PHZ_MANUAL_SET(dst, src) \
45088e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
45188e670feSLoc Ho #define RXTX_REG127 0x0fe
45288e670feSLoc Ho #define RXTX_REG127_FORCE_SUM_CAL_START_MASK 0x00000002
45388e670feSLoc Ho #define RXTX_REG127_FORCE_LAT_CAL_START_MASK 0x00000004
45488e670feSLoc Ho #define RXTX_REG127_FORCE_SUM_CAL_START_SET(dst, src) \
45588e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
45688e670feSLoc Ho #define RXTX_REG127_FORCE_LAT_CAL_START_SET(dst, src) \
45788e670feSLoc Ho (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
45888e670feSLoc Ho #define RXTX_REG127_LATCH_MAN_CAL_ENA_SET(dst, src) \
45988e670feSLoc Ho (((dst) & ~0x00000008) | (((u32) (src) << 3) & 0x00000008))
46088e670feSLoc Ho #define RXTX_REG127_DO_LATCH_MANCAL_SET(dst, src) \
46188e670feSLoc Ho (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
46288e670feSLoc Ho #define RXTX_REG127_XO_LATCH_MANCAL_SET(dst, src) \
46388e670feSLoc Ho (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
46488e670feSLoc Ho #define RXTX_REG128 0x100
46588e670feSLoc Ho #define RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(dst, src) \
46688e670feSLoc Ho (((dst) & ~0x0000000c) | (((u32) (src) << 2) & 0x0000000c))
46788e670feSLoc Ho #define RXTX_REG128_EO_LATCH_MANCAL_SET(dst, src) \
46888e670feSLoc Ho (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
46988e670feSLoc Ho #define RXTX_REG128_SO_LATCH_MANCAL_SET(dst, src) \
47088e670feSLoc Ho (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
47188e670feSLoc Ho #define RXTX_REG129 0x102
47288e670feSLoc Ho #define RXTX_REG129_DE_LATCH_MANCAL_SET(dst, src) \
47388e670feSLoc Ho (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
47488e670feSLoc Ho #define RXTX_REG129_XE_LATCH_MANCAL_SET(dst, src) \
47588e670feSLoc Ho (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
47688e670feSLoc Ho #define RXTX_REG130 0x104
47788e670feSLoc Ho #define RXTX_REG130_EE_LATCH_MANCAL_SET(dst, src) \
47888e670feSLoc Ho (((dst) & ~0x0000fc00) | (((u32) (src) << 10) & 0x0000fc00))
47988e670feSLoc Ho #define RXTX_REG130_SE_LATCH_MANCAL_SET(dst, src) \
48088e670feSLoc Ho (((dst) & ~0x000003f0) | (((u32) (src) << 4) & 0x000003f0))
48188e670feSLoc Ho #define RXTX_REG145 0x122
48288e670feSLoc Ho #define RXTX_REG145_TX_IDLE_SATA_SET(dst, src) \
48388e670feSLoc Ho (((dst) & ~0x00000001) | (((u32) (src) << 0) & 0x00000001))
48488e670feSLoc Ho #define RXTX_REG145_RXES_ENA_SET(dst, src) \
48588e670feSLoc Ho (((dst) & ~0x00000002) | (((u32) (src) << 1) & 0x00000002))
48688e670feSLoc Ho #define RXTX_REG145_RXDFE_CONFIG_SET(dst, src) \
48788e670feSLoc Ho (((dst) & ~0x0000c000) | (((u32) (src) << 14) & 0x0000c000))
48888e670feSLoc Ho #define RXTX_REG145_RXVWES_LATENA_SET(dst, src) \
48988e670feSLoc Ho (((dst) & ~0x00000004) | (((u32) (src) << 2) & 0x00000004))
49088e670feSLoc Ho #define RXTX_REG147 0x126
49188e670feSLoc Ho #define RXTX_REG148 0x128
49288e670feSLoc Ho
49388e670feSLoc Ho /* Clock macro type */
49488e670feSLoc Ho enum cmu_type_t {
49588e670feSLoc Ho REF_CMU = 0, /* Clock macro is the internal reference clock */
49688e670feSLoc Ho PHY_CMU = 1, /* Clock macro is the PLL for the Serdes */
49788e670feSLoc Ho };
49888e670feSLoc Ho
49988e670feSLoc Ho enum mux_type_t {
50088e670feSLoc Ho MUX_SELECT_ATA = 0, /* Switch the MUX to ATA */
50188e670feSLoc Ho MUX_SELECT_SGMMII = 0, /* Switch the MUX to SGMII */
50288e670feSLoc Ho };
50388e670feSLoc Ho
50488e670feSLoc Ho enum clk_type_t {
50588e670feSLoc Ho CLK_EXT_DIFF = 0, /* External differential */
50688e670feSLoc Ho CLK_INT_DIFF = 1, /* Internal differential */
50788e670feSLoc Ho CLK_INT_SING = 2, /* Internal single ended */
50888e670feSLoc Ho };
50988e670feSLoc Ho
51065048f4dSKishon Vijay Abraham I enum xgene_phy_mode {
51188e670feSLoc Ho MODE_SATA = 0, /* List them for simple reference */
51288e670feSLoc Ho MODE_SGMII = 1,
51388e670feSLoc Ho MODE_PCIE = 2,
51488e670feSLoc Ho MODE_USB = 3,
51588e670feSLoc Ho MODE_XFI = 4,
51688e670feSLoc Ho MODE_MAX
51788e670feSLoc Ho };
51888e670feSLoc Ho
51988e670feSLoc Ho struct xgene_sata_override_param {
52088e670feSLoc Ho u32 speed[MAX_LANE]; /* Index for override parameter per lane */
52188e670feSLoc Ho u32 txspeed[3]; /* Tx speed */
52288e670feSLoc Ho u32 txboostgain[MAX_LANE*3]; /* Tx freq boost and gain control */
52388e670feSLoc Ho u32 txeyetuning[MAX_LANE*3]; /* Tx eye tuning */
52488e670feSLoc Ho u32 txeyedirection[MAX_LANE*3]; /* Tx eye tuning direction */
52588e670feSLoc Ho u32 txamplitude[MAX_LANE*3]; /* Tx amplitude control */
52688e670feSLoc Ho u32 txprecursor_cn1[MAX_LANE*3]; /* Tx emphasis taps 1st pre-cursor */
52788e670feSLoc Ho u32 txprecursor_cn2[MAX_LANE*3]; /* Tx emphasis taps 2nd pre-cursor */
52888e670feSLoc Ho u32 txpostcursor_cp1[MAX_LANE*3]; /* Tx emphasis taps post-cursor */
52988e670feSLoc Ho };
53088e670feSLoc Ho
53188e670feSLoc Ho struct xgene_phy_ctx {
53288e670feSLoc Ho struct device *dev;
53388e670feSLoc Ho struct phy *phy;
53465048f4dSKishon Vijay Abraham I enum xgene_phy_mode mode; /* Mode of operation */
53588e670feSLoc Ho enum clk_type_t clk_type; /* Input clock selection */
53688e670feSLoc Ho void __iomem *sds_base; /* PHY CSR base addr */
53788e670feSLoc Ho struct clk *clk; /* Optional clock */
53888e670feSLoc Ho
53988e670feSLoc Ho /* Override Serdes parameters */
54088e670feSLoc Ho struct xgene_sata_override_param sata_param;
54188e670feSLoc Ho };
54288e670feSLoc Ho
54388e670feSLoc Ho /*
54488e670feSLoc Ho * For chip earlier than A3 version, enable this flag.
54588e670feSLoc Ho * To enable, pass boot argument phy_xgene.preA3Chip=1
54688e670feSLoc Ho */
54788e670feSLoc Ho static int preA3Chip;
54888e670feSLoc Ho MODULE_PARM_DESC(preA3Chip, "Enable pre-A3 chip support (1=enable 0=disable)");
54988e670feSLoc Ho module_param_named(preA3Chip, preA3Chip, int, 0444);
55088e670feSLoc Ho
sds_wr(void __iomem * csr_base,u32 indirect_cmd_reg,u32 indirect_data_reg,u32 addr,u32 data)55188e670feSLoc Ho static void sds_wr(void __iomem *csr_base, u32 indirect_cmd_reg,
55288e670feSLoc Ho u32 indirect_data_reg, u32 addr, u32 data)
55388e670feSLoc Ho {
55488e670feSLoc Ho unsigned long deadline = jiffies + HZ;
55588e670feSLoc Ho u32 val;
55688e670feSLoc Ho u32 cmd;
55788e670feSLoc Ho
55888e670feSLoc Ho cmd = CFG_IND_WR_CMD_MASK | CFG_IND_CMD_DONE_MASK;
55988e670feSLoc Ho cmd = CFG_IND_ADDR_SET(cmd, addr);
56088e670feSLoc Ho writel(data, csr_base + indirect_data_reg);
56188e670feSLoc Ho readl(csr_base + indirect_data_reg); /* Force a barrier */
56288e670feSLoc Ho writel(cmd, csr_base + indirect_cmd_reg);
56388e670feSLoc Ho readl(csr_base + indirect_cmd_reg); /* Force a barrier */
56488e670feSLoc Ho do {
56588e670feSLoc Ho val = readl(csr_base + indirect_cmd_reg);
56688e670feSLoc Ho } while (!(val & CFG_IND_CMD_DONE_MASK) &&
56788e670feSLoc Ho time_before(jiffies, deadline));
56888e670feSLoc Ho if (!(val & CFG_IND_CMD_DONE_MASK))
56988e670feSLoc Ho pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
57088e670feSLoc Ho csr_base + indirect_cmd_reg, addr, data);
57188e670feSLoc Ho }
57288e670feSLoc Ho
sds_rd(void __iomem * csr_base,u32 indirect_cmd_reg,u32 indirect_data_reg,u32 addr,u32 * data)57388e670feSLoc Ho static void sds_rd(void __iomem *csr_base, u32 indirect_cmd_reg,
57488e670feSLoc Ho u32 indirect_data_reg, u32 addr, u32 *data)
57588e670feSLoc Ho {
57688e670feSLoc Ho unsigned long deadline = jiffies + HZ;
57788e670feSLoc Ho u32 val;
57888e670feSLoc Ho u32 cmd;
57988e670feSLoc Ho
58088e670feSLoc Ho cmd = CFG_IND_RD_CMD_MASK | CFG_IND_CMD_DONE_MASK;
58188e670feSLoc Ho cmd = CFG_IND_ADDR_SET(cmd, addr);
58288e670feSLoc Ho writel(cmd, csr_base + indirect_cmd_reg);
58388e670feSLoc Ho readl(csr_base + indirect_cmd_reg); /* Force a barrier */
58488e670feSLoc Ho do {
58588e670feSLoc Ho val = readl(csr_base + indirect_cmd_reg);
58688e670feSLoc Ho } while (!(val & CFG_IND_CMD_DONE_MASK) &&
58788e670feSLoc Ho time_before(jiffies, deadline));
58888e670feSLoc Ho *data = readl(csr_base + indirect_data_reg);
58988e670feSLoc Ho if (!(val & CFG_IND_CMD_DONE_MASK))
59088e670feSLoc Ho pr_err("SDS WR timeout at 0x%p offset 0x%08X value 0x%08X\n",
59188e670feSLoc Ho csr_base + indirect_cmd_reg, addr, *data);
59288e670feSLoc Ho }
59388e670feSLoc Ho
cmu_wr(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,u32 reg,u32 data)59488e670feSLoc Ho static void cmu_wr(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
59588e670feSLoc Ho u32 reg, u32 data)
59688e670feSLoc Ho {
59788e670feSLoc Ho void __iomem *sds_base = ctx->sds_base;
59888e670feSLoc Ho u32 val;
59988e670feSLoc Ho
60088e670feSLoc Ho if (cmu_type == REF_CMU)
60188e670feSLoc Ho reg += SERDES_PLL_REF_INDIRECT_OFFSET;
60288e670feSLoc Ho else
60388e670feSLoc Ho reg += SERDES_PLL_INDIRECT_OFFSET;
60488e670feSLoc Ho sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
60588e670feSLoc Ho SATA_ENET_SDS_IND_WDATA_REG, reg, data);
60688e670feSLoc Ho sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
60788e670feSLoc Ho SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
60888e670feSLoc Ho pr_debug("CMU WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data, val);
60988e670feSLoc Ho }
61088e670feSLoc Ho
cmu_rd(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,u32 reg,u32 * data)61188e670feSLoc Ho static void cmu_rd(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
61288e670feSLoc Ho u32 reg, u32 *data)
61388e670feSLoc Ho {
61488e670feSLoc Ho void __iomem *sds_base = ctx->sds_base;
61588e670feSLoc Ho
61688e670feSLoc Ho if (cmu_type == REF_CMU)
61788e670feSLoc Ho reg += SERDES_PLL_REF_INDIRECT_OFFSET;
61888e670feSLoc Ho else
61988e670feSLoc Ho reg += SERDES_PLL_INDIRECT_OFFSET;
62088e670feSLoc Ho sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
62188e670feSLoc Ho SATA_ENET_SDS_IND_RDATA_REG, reg, data);
62288e670feSLoc Ho pr_debug("CMU RD addr 0x%X value 0x%08X\n", reg, *data);
62388e670feSLoc Ho }
62488e670feSLoc Ho
cmu_toggle1to0(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,u32 reg,u32 bits)62588e670feSLoc Ho static void cmu_toggle1to0(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
62688e670feSLoc Ho u32 reg, u32 bits)
62788e670feSLoc Ho {
62888e670feSLoc Ho u32 val;
62988e670feSLoc Ho
63088e670feSLoc Ho cmu_rd(ctx, cmu_type, reg, &val);
63188e670feSLoc Ho val |= bits;
63288e670feSLoc Ho cmu_wr(ctx, cmu_type, reg, val);
63388e670feSLoc Ho cmu_rd(ctx, cmu_type, reg, &val);
63488e670feSLoc Ho val &= ~bits;
63588e670feSLoc Ho cmu_wr(ctx, cmu_type, reg, val);
63688e670feSLoc Ho }
63788e670feSLoc Ho
cmu_clrbits(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,u32 reg,u32 bits)63888e670feSLoc Ho static void cmu_clrbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
63988e670feSLoc Ho u32 reg, u32 bits)
64088e670feSLoc Ho {
64188e670feSLoc Ho u32 val;
64288e670feSLoc Ho
64388e670feSLoc Ho cmu_rd(ctx, cmu_type, reg, &val);
64488e670feSLoc Ho val &= ~bits;
64588e670feSLoc Ho cmu_wr(ctx, cmu_type, reg, val);
64688e670feSLoc Ho }
64788e670feSLoc Ho
cmu_setbits(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,u32 reg,u32 bits)64888e670feSLoc Ho static void cmu_setbits(struct xgene_phy_ctx *ctx, enum cmu_type_t cmu_type,
64988e670feSLoc Ho u32 reg, u32 bits)
65088e670feSLoc Ho {
65188e670feSLoc Ho u32 val;
65288e670feSLoc Ho
65388e670feSLoc Ho cmu_rd(ctx, cmu_type, reg, &val);
65488e670feSLoc Ho val |= bits;
65588e670feSLoc Ho cmu_wr(ctx, cmu_type, reg, val);
65688e670feSLoc Ho }
65788e670feSLoc Ho
serdes_wr(struct xgene_phy_ctx * ctx,int lane,u32 reg,u32 data)65888e670feSLoc Ho static void serdes_wr(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 data)
65988e670feSLoc Ho {
66088e670feSLoc Ho void __iomem *sds_base = ctx->sds_base;
66188e670feSLoc Ho u32 val;
66288e670feSLoc Ho
66388e670feSLoc Ho reg += SERDES_INDIRECT_OFFSET;
66488e670feSLoc Ho reg += lane * SERDES_LANE_STRIDE;
66588e670feSLoc Ho sds_wr(sds_base, SATA_ENET_SDS_IND_CMD_REG,
66688e670feSLoc Ho SATA_ENET_SDS_IND_WDATA_REG, reg, data);
66788e670feSLoc Ho sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
66888e670feSLoc Ho SATA_ENET_SDS_IND_RDATA_REG, reg, &val);
66988e670feSLoc Ho pr_debug("SERDES WR addr 0x%X value 0x%08X <-> 0x%08X\n", reg, data,
67088e670feSLoc Ho val);
67188e670feSLoc Ho }
67288e670feSLoc Ho
serdes_rd(struct xgene_phy_ctx * ctx,int lane,u32 reg,u32 * data)67388e670feSLoc Ho static void serdes_rd(struct xgene_phy_ctx *ctx, int lane, u32 reg, u32 *data)
67488e670feSLoc Ho {
67588e670feSLoc Ho void __iomem *sds_base = ctx->sds_base;
67688e670feSLoc Ho
67788e670feSLoc Ho reg += SERDES_INDIRECT_OFFSET;
67888e670feSLoc Ho reg += lane * SERDES_LANE_STRIDE;
67988e670feSLoc Ho sds_rd(sds_base, SATA_ENET_SDS_IND_CMD_REG,
68088e670feSLoc Ho SATA_ENET_SDS_IND_RDATA_REG, reg, data);
68188e670feSLoc Ho pr_debug("SERDES RD addr 0x%X value 0x%08X\n", reg, *data);
68288e670feSLoc Ho }
68388e670feSLoc Ho
serdes_clrbits(struct xgene_phy_ctx * ctx,int lane,u32 reg,u32 bits)68488e670feSLoc Ho static void serdes_clrbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
68588e670feSLoc Ho u32 bits)
68688e670feSLoc Ho {
68788e670feSLoc Ho u32 val;
68888e670feSLoc Ho
68988e670feSLoc Ho serdes_rd(ctx, lane, reg, &val);
69088e670feSLoc Ho val &= ~bits;
69188e670feSLoc Ho serdes_wr(ctx, lane, reg, val);
69288e670feSLoc Ho }
69388e670feSLoc Ho
serdes_setbits(struct xgene_phy_ctx * ctx,int lane,u32 reg,u32 bits)69488e670feSLoc Ho static void serdes_setbits(struct xgene_phy_ctx *ctx, int lane, u32 reg,
69588e670feSLoc Ho u32 bits)
69688e670feSLoc Ho {
69788e670feSLoc Ho u32 val;
69888e670feSLoc Ho
69988e670feSLoc Ho serdes_rd(ctx, lane, reg, &val);
70088e670feSLoc Ho val |= bits;
70188e670feSLoc Ho serdes_wr(ctx, lane, reg, val);
70288e670feSLoc Ho }
70388e670feSLoc Ho
xgene_phy_cfg_cmu_clk_type(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,enum clk_type_t clk_type)70488e670feSLoc Ho static void xgene_phy_cfg_cmu_clk_type(struct xgene_phy_ctx *ctx,
70588e670feSLoc Ho enum cmu_type_t cmu_type,
70688e670feSLoc Ho enum clk_type_t clk_type)
70788e670feSLoc Ho {
70888e670feSLoc Ho u32 val;
70988e670feSLoc Ho
71088e670feSLoc Ho /* Set the reset sequence delay for TX ready assertion */
71188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG12, &val);
71288e670feSLoc Ho val = CMU_REG12_STATE_DELAY9_SET(val, 0x1);
71388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG12, val);
71488e670feSLoc Ho /* Set the programmable stage delays between various enable stages */
71588e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG13, 0x0222);
71688e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG14, 0x2225);
71788e670feSLoc Ho
71888e670feSLoc Ho /* Configure clock type */
71988e670feSLoc Ho if (clk_type == CLK_EXT_DIFF) {
72088e670feSLoc Ho /* Select external clock mux */
72188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG0, &val);
72288e670feSLoc Ho val = CMU_REG0_PLL_REF_SEL_SET(val, 0x0);
72388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG0, val);
72488e670feSLoc Ho /* Select CMOS as reference clock */
72588e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
72688e670feSLoc Ho val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
72788e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
72888e670feSLoc Ho dev_dbg(ctx->dev, "Set external reference clock\n");
72988e670feSLoc Ho } else if (clk_type == CLK_INT_DIFF) {
73088e670feSLoc Ho /* Select internal clock mux */
73188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG0, &val);
73288e670feSLoc Ho val = CMU_REG0_PLL_REF_SEL_SET(val, 0x1);
73388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG0, val);
73488e670feSLoc Ho /* Select CMOS as reference clock */
73588e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
73688e670feSLoc Ho val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
73788e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
73888e670feSLoc Ho dev_dbg(ctx->dev, "Set internal reference clock\n");
73988e670feSLoc Ho } else if (clk_type == CLK_INT_SING) {
74088e670feSLoc Ho /*
74188e670feSLoc Ho * NOTE: This clock type is NOT support for controller
74288e670feSLoc Ho * whose internal clock shared in the PCIe controller
74388e670feSLoc Ho *
74488e670feSLoc Ho * Select internal clock mux
74588e670feSLoc Ho */
74688e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
74788e670feSLoc Ho val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x1);
74888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
74988e670feSLoc Ho /* Select CML as reference clock */
75088e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
75188e670feSLoc Ho val = CMU_REG1_REFCLK_CMOS_SEL_SET(val, 0x0);
75288e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
75388e670feSLoc Ho dev_dbg(ctx->dev,
75488e670feSLoc Ho "Set internal single ended reference clock\n");
75588e670feSLoc Ho }
75688e670feSLoc Ho }
75788e670feSLoc Ho
xgene_phy_sata_cfg_cmu_core(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,enum clk_type_t clk_type)75888e670feSLoc Ho static void xgene_phy_sata_cfg_cmu_core(struct xgene_phy_ctx *ctx,
75988e670feSLoc Ho enum cmu_type_t cmu_type,
76088e670feSLoc Ho enum clk_type_t clk_type)
76188e670feSLoc Ho {
76288e670feSLoc Ho u32 val;
76388e670feSLoc Ho int ref_100MHz;
76488e670feSLoc Ho
76588e670feSLoc Ho if (cmu_type == REF_CMU) {
76688e670feSLoc Ho /* Set VCO calibration voltage threshold */
76788e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG34, &val);
76888e670feSLoc Ho val = CMU_REG34_VCO_CAL_VTH_LO_MAX_SET(val, 0x7);
76988e670feSLoc Ho val = CMU_REG34_VCO_CAL_VTH_HI_MAX_SET(val, 0xc);
77088e670feSLoc Ho val = CMU_REG34_VCO_CAL_VTH_LO_MIN_SET(val, 0x3);
77188e670feSLoc Ho val = CMU_REG34_VCO_CAL_VTH_HI_MIN_SET(val, 0x8);
77288e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG34, val);
77388e670feSLoc Ho }
77488e670feSLoc Ho
77588e670feSLoc Ho /* Set the VCO calibration counter */
77688e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG0, &val);
77788e670feSLoc Ho if (cmu_type == REF_CMU || preA3Chip)
77888e670feSLoc Ho val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x4);
77988e670feSLoc Ho else
78088e670feSLoc Ho val = CMU_REG0_CAL_COUNT_RESOL_SET(val, 0x7);
78188e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG0, val);
78288e670feSLoc Ho
78388e670feSLoc Ho /* Configure PLL for calibration */
78488e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
78588e670feSLoc Ho val = CMU_REG1_PLL_CP_SET(val, 0x1);
78688e670feSLoc Ho if (cmu_type == REF_CMU || preA3Chip)
78788e670feSLoc Ho val = CMU_REG1_PLL_CP_SEL_SET(val, 0x5);
78888e670feSLoc Ho else
78988e670feSLoc Ho val = CMU_REG1_PLL_CP_SEL_SET(val, 0x3);
79088e670feSLoc Ho if (cmu_type == REF_CMU)
79188e670feSLoc Ho val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
79288e670feSLoc Ho else
79388e670feSLoc Ho val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x1);
79488e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
79588e670feSLoc Ho
79688e670feSLoc Ho if (cmu_type != REF_CMU)
79788e670feSLoc Ho cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
79888e670feSLoc Ho
79988e670feSLoc Ho /* Configure the PLL for either 100MHz or 50MHz */
80088e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG2, &val);
80188e670feSLoc Ho if (cmu_type == REF_CMU) {
80288e670feSLoc Ho val = CMU_REG2_PLL_LFRES_SET(val, 0xa);
80388e670feSLoc Ho ref_100MHz = 1;
80488e670feSLoc Ho } else {
80588e670feSLoc Ho val = CMU_REG2_PLL_LFRES_SET(val, 0x3);
80688e670feSLoc Ho if (clk_type == CLK_EXT_DIFF)
80788e670feSLoc Ho ref_100MHz = 0;
80888e670feSLoc Ho else
80988e670feSLoc Ho ref_100MHz = 1;
81088e670feSLoc Ho }
81188e670feSLoc Ho if (ref_100MHz) {
81288e670feSLoc Ho val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_100M);
81388e670feSLoc Ho val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_100M);
81488e670feSLoc Ho } else {
81588e670feSLoc Ho val = CMU_REG2_PLL_FBDIV_SET(val, FBDIV_VAL_50M);
81688e670feSLoc Ho val = CMU_REG2_PLL_REFDIV_SET(val, REFDIV_VAL_50M);
81788e670feSLoc Ho }
81888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG2, val);
81988e670feSLoc Ho
82088e670feSLoc Ho /* Configure the VCO */
82188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG3, &val);
82288e670feSLoc Ho if (cmu_type == REF_CMU) {
82388e670feSLoc Ho val = CMU_REG3_VCOVARSEL_SET(val, 0x3);
82488e670feSLoc Ho val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x10);
82588e670feSLoc Ho } else {
82688e670feSLoc Ho val = CMU_REG3_VCOVARSEL_SET(val, 0xF);
82788e670feSLoc Ho if (preA3Chip)
82888e670feSLoc Ho val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x15);
82988e670feSLoc Ho else
83088e670feSLoc Ho val = CMU_REG3_VCO_MOMSEL_INIT_SET(val, 0x1a);
83188e670feSLoc Ho val = CMU_REG3_VCO_MANMOMSEL_SET(val, 0x15);
83288e670feSLoc Ho }
83388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG3, val);
83488e670feSLoc Ho
83588e670feSLoc Ho /* Disable force PLL lock */
83688e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG26, &val);
83788e670feSLoc Ho val = CMU_REG26_FORCE_PLL_LOCK_SET(val, 0x0);
83888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG26, val);
83988e670feSLoc Ho
84088e670feSLoc Ho /* Setup PLL loop filter */
84188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG5, &val);
84288e670feSLoc Ho val = CMU_REG5_PLL_LFSMCAP_SET(val, 0x3);
84388e670feSLoc Ho val = CMU_REG5_PLL_LFCAP_SET(val, 0x3);
84488e670feSLoc Ho if (cmu_type == REF_CMU || !preA3Chip)
84588e670feSLoc Ho val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x7);
84688e670feSLoc Ho else
84788e670feSLoc Ho val = CMU_REG5_PLL_LOCK_RESOLUTION_SET(val, 0x4);
84888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG5, val);
84988e670feSLoc Ho
85088e670feSLoc Ho /* Enable or disable manual calibration */
85188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG6, &val);
85288e670feSLoc Ho val = CMU_REG6_PLL_VREGTRIM_SET(val, preA3Chip ? 0x0 : 0x2);
85388e670feSLoc Ho val = CMU_REG6_MAN_PVT_CAL_SET(val, preA3Chip ? 0x1 : 0x0);
85488e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG6, val);
85588e670feSLoc Ho
85688e670feSLoc Ho /* Configure lane for 20-bits */
85788e670feSLoc Ho if (cmu_type == PHY_CMU) {
85888e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG9, &val);
85988e670feSLoc Ho val = CMU_REG9_TX_WORD_MODE_CH1_SET(val,
86088e670feSLoc Ho CMU_REG9_WORD_LEN_20BIT);
86188e670feSLoc Ho val = CMU_REG9_TX_WORD_MODE_CH0_SET(val,
86288e670feSLoc Ho CMU_REG9_WORD_LEN_20BIT);
86388e670feSLoc Ho val = CMU_REG9_PLL_POST_DIVBY2_SET(val, 0x1);
86488e670feSLoc Ho if (!preA3Chip) {
86588e670feSLoc Ho val = CMU_REG9_VBG_BYPASSB_SET(val, 0x0);
86688e670feSLoc Ho val = CMU_REG9_IGEN_BYPASS_SET(val , 0x0);
86788e670feSLoc Ho }
86888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG9, val);
86988e670feSLoc Ho
87088e670feSLoc Ho if (!preA3Chip) {
87188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG10, &val);
87288e670feSLoc Ho val = CMU_REG10_VREG_REFSEL_SET(val, 0x1);
87388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG10, val);
87488e670feSLoc Ho }
87588e670feSLoc Ho }
87688e670feSLoc Ho
87788e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG16, &val);
87888e670feSLoc Ho val = CMU_REG16_CALIBRATION_DONE_OVERRIDE_SET(val, 0x1);
87988e670feSLoc Ho val = CMU_REG16_BYPASS_PLL_LOCK_SET(val, 0x1);
88088e670feSLoc Ho if (cmu_type == REF_CMU || preA3Chip)
88188e670feSLoc Ho val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x4);
88288e670feSLoc Ho else
88388e670feSLoc Ho val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
88488e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG16, val);
88588e670feSLoc Ho
88688e670feSLoc Ho /* Configure for SATA */
88788e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG30, &val);
88888e670feSLoc Ho val = CMU_REG30_PCIE_MODE_SET(val, 0x0);
88988e670feSLoc Ho val = CMU_REG30_LOCK_COUNT_SET(val, 0x3);
89088e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG30, val);
89188e670feSLoc Ho
89288e670feSLoc Ho /* Disable state machine bypass */
89388e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG31, 0xF);
89488e670feSLoc Ho
89588e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG32, &val);
89688e670feSLoc Ho val = CMU_REG32_PVT_CAL_WAIT_SEL_SET(val, 0x3);
89788e670feSLoc Ho if (cmu_type == REF_CMU || preA3Chip)
89888e670feSLoc Ho val = CMU_REG32_IREF_ADJ_SET(val, 0x3);
89988e670feSLoc Ho else
90088e670feSLoc Ho val = CMU_REG32_IREF_ADJ_SET(val, 0x1);
90188e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG32, val);
90288e670feSLoc Ho
90388e670feSLoc Ho /* Set VCO calibration threshold */
90488e670feSLoc Ho if (cmu_type != REF_CMU && preA3Chip)
90588e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG34, 0x8d27);
90688e670feSLoc Ho else
90788e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG34, 0x873c);
90888e670feSLoc Ho
90988e670feSLoc Ho /* Set CTLE Override and override waiting from state machine */
91088e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG37, 0xF00F);
91188e670feSLoc Ho }
91288e670feSLoc Ho
xgene_phy_ssc_enable(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type)91388e670feSLoc Ho static void xgene_phy_ssc_enable(struct xgene_phy_ctx *ctx,
91488e670feSLoc Ho enum cmu_type_t cmu_type)
91588e670feSLoc Ho {
91688e670feSLoc Ho u32 val;
91788e670feSLoc Ho
91888e670feSLoc Ho /* Set SSC modulation value */
91988e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG35, &val);
92088e670feSLoc Ho val = CMU_REG35_PLL_SSC_MOD_SET(val, 98);
92188e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG35, val);
92288e670feSLoc Ho
92388e670feSLoc Ho /* Enable SSC, set vertical step and DSM value */
92488e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG36, &val);
92588e670feSLoc Ho val = CMU_REG36_PLL_SSC_VSTEP_SET(val, 30);
92688e670feSLoc Ho val = CMU_REG36_PLL_SSC_EN_SET(val, 1);
92788e670feSLoc Ho val = CMU_REG36_PLL_SSC_DSMSEL_SET(val, 1);
92888e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG36, val);
92988e670feSLoc Ho
93088e670feSLoc Ho /* Reset the PLL */
93188e670feSLoc Ho cmu_clrbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
93288e670feSLoc Ho cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
93388e670feSLoc Ho
93488e670feSLoc Ho /* Force VCO calibration to restart */
93588e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
93688e670feSLoc Ho CMU_REG32_FORCE_VCOCAL_START_MASK);
93788e670feSLoc Ho }
93888e670feSLoc Ho
xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx * ctx)93988e670feSLoc Ho static void xgene_phy_sata_cfg_lanes(struct xgene_phy_ctx *ctx)
94088e670feSLoc Ho {
94188e670feSLoc Ho u32 val;
94288e670feSLoc Ho u32 reg;
94388e670feSLoc Ho int i;
94488e670feSLoc Ho int lane;
94588e670feSLoc Ho
94688e670feSLoc Ho for (lane = 0; lane < MAX_LANE; lane++) {
94788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG147, 0x6);
94888e670feSLoc Ho
94988e670feSLoc Ho /* Set boost control for quarter, half, and full rate */
95088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG0, &val);
95188e670feSLoc Ho val = RXTX_REG0_CTLE_EQ_HR_SET(val, 0x10);
95288e670feSLoc Ho val = RXTX_REG0_CTLE_EQ_QR_SET(val, 0x10);
95388e670feSLoc Ho val = RXTX_REG0_CTLE_EQ_FR_SET(val, 0x10);
95488e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG0, val);
95588e670feSLoc Ho
95688e670feSLoc Ho /* Set boost control value */
95788e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG1, &val);
95888e670feSLoc Ho val = RXTX_REG1_RXACVCM_SET(val, 0x7);
95988e670feSLoc Ho val = RXTX_REG1_CTLE_EQ_SET(val,
96088e670feSLoc Ho ctx->sata_param.txboostgain[lane * 3 +
96188e670feSLoc Ho ctx->sata_param.speed[lane]]);
96288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG1, val);
96388e670feSLoc Ho
96488e670feSLoc Ho /* Latch VTT value based on the termination to ground and
9653136b3b1SShubhankar Kuranagatti * enable TX FIFO
9663136b3b1SShubhankar Kuranagatti */
96788e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG2, &val);
96888e670feSLoc Ho val = RXTX_REG2_VTT_ENA_SET(val, 0x1);
96988e670feSLoc Ho val = RXTX_REG2_VTT_SEL_SET(val, 0x1);
97088e670feSLoc Ho val = RXTX_REG2_TX_FIFO_ENA_SET(val, 0x1);
97188e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG2, val);
97288e670feSLoc Ho
97388e670feSLoc Ho /* Configure Tx for 20-bits */
97488e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG4, &val);
97588e670feSLoc Ho val = RXTX_REG4_TX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
97688e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG4, val);
97788e670feSLoc Ho
97888e670feSLoc Ho if (!preA3Chip) {
97988e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG1, &val);
98088e670feSLoc Ho val = RXTX_REG1_RXVREG1_SET(val, 0x2);
98188e670feSLoc Ho val = RXTX_REG1_RXIREF_ADJ_SET(val, 0x2);
98288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG1, val);
98388e670feSLoc Ho }
98488e670feSLoc Ho
98588e670feSLoc Ho /* Set pre-emphasis first 1 and 2, and post-emphasis values */
98688e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG5, &val);
98788e670feSLoc Ho val = RXTX_REG5_TX_CN1_SET(val,
98888e670feSLoc Ho ctx->sata_param.txprecursor_cn1[lane * 3 +
98988e670feSLoc Ho ctx->sata_param.speed[lane]]);
99088e670feSLoc Ho val = RXTX_REG5_TX_CP1_SET(val,
99188e670feSLoc Ho ctx->sata_param.txpostcursor_cp1[lane * 3 +
99288e670feSLoc Ho ctx->sata_param.speed[lane]]);
99388e670feSLoc Ho val = RXTX_REG5_TX_CN2_SET(val,
99488e670feSLoc Ho ctx->sata_param.txprecursor_cn2[lane * 3 +
99588e670feSLoc Ho ctx->sata_param.speed[lane]]);
99688e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG5, val);
99788e670feSLoc Ho
99888e670feSLoc Ho /* Set TX amplitude value */
99988e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG6, &val);
100088e670feSLoc Ho val = RXTX_REG6_TXAMP_CNTL_SET(val,
100188e670feSLoc Ho ctx->sata_param.txamplitude[lane * 3 +
100288e670feSLoc Ho ctx->sata_param.speed[lane]]);
100388e670feSLoc Ho val = RXTX_REG6_TXAMP_ENA_SET(val, 0x1);
100488e670feSLoc Ho val = RXTX_REG6_TX_IDLE_SET(val, 0x0);
100588e670feSLoc Ho val = RXTX_REG6_RX_BIST_RESYNC_SET(val, 0x0);
100688e670feSLoc Ho val = RXTX_REG6_RX_BIST_ERRCNT_RD_SET(val, 0x0);
100788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG6, val);
100888e670feSLoc Ho
100988e670feSLoc Ho /* Configure Rx for 20-bits */
101088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG7, &val);
101188e670feSLoc Ho val = RXTX_REG7_BIST_ENA_RX_SET(val, 0x0);
101288e670feSLoc Ho val = RXTX_REG7_RX_WORD_MODE_SET(val, CMU_REG9_WORD_LEN_20BIT);
101388e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG7, val);
101488e670feSLoc Ho
101588e670feSLoc Ho /* Set CDR and LOS values and enable Rx SSC */
101688e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG8, &val);
101788e670feSLoc Ho val = RXTX_REG8_CDR_LOOP_ENA_SET(val, 0x1);
101888e670feSLoc Ho val = RXTX_REG8_CDR_BYPASS_RXLOS_SET(val, 0x0);
101988e670feSLoc Ho val = RXTX_REG8_SSC_ENABLE_SET(val, 0x1);
102088e670feSLoc Ho val = RXTX_REG8_SD_DISABLE_SET(val, 0x0);
102188e670feSLoc Ho val = RXTX_REG8_SD_VREF_SET(val, 0x4);
102288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG8, val);
102388e670feSLoc Ho
102488e670feSLoc Ho /* Set phase adjust upper/lower limits */
102588e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG11, &val);
102688e670feSLoc Ho val = RXTX_REG11_PHASE_ADJUST_LIMIT_SET(val, 0x0);
102788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG11, val);
102888e670feSLoc Ho
102988e670feSLoc Ho /* Enable Latch Off; disable SUMOS and Tx termination */
103088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG12, &val);
103188e670feSLoc Ho val = RXTX_REG12_LATCH_OFF_ENA_SET(val, 0x1);
103288e670feSLoc Ho val = RXTX_REG12_SUMOS_ENABLE_SET(val, 0x0);
103388e670feSLoc Ho val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0x0);
103488e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG12, val);
103588e670feSLoc Ho
103688e670feSLoc Ho /* Set period error latch to 512T and enable BWL */
103788e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG26, &val);
103888e670feSLoc Ho val = RXTX_REG26_PERIOD_ERROR_LATCH_SET(val, 0x0);
103988e670feSLoc Ho val = RXTX_REG26_BLWC_ENA_SET(val, 0x1);
104088e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG26, val);
104188e670feSLoc Ho
104288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG28, 0x0);
104388e670feSLoc Ho
104488e670feSLoc Ho /* Set DFE loop preset value */
104588e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG31, 0x0);
104688e670feSLoc Ho
104788e670feSLoc Ho /* Set Eye Monitor counter width to 12-bit */
104888e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG61, &val);
104988e670feSLoc Ho val = RXTX_REG61_ISCAN_INBERT_SET(val, 0x1);
105088e670feSLoc Ho val = RXTX_REG61_LOADFREQ_SHIFT_SET(val, 0x0);
105188e670feSLoc Ho val = RXTX_REG61_EYE_COUNT_WIDTH_SEL_SET(val, 0x0);
105288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG61, val);
105388e670feSLoc Ho
105488e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG62, &val);
105588e670feSLoc Ho val = RXTX_REG62_PERIOD_H1_QLATCH_SET(val, 0x0);
105688e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG62, val);
105788e670feSLoc Ho
105888e670feSLoc Ho /* Set BW select tap X for DFE loop */
105988e670feSLoc Ho for (i = 0; i < 9; i++) {
106088e670feSLoc Ho reg = RXTX_REG81 + i * 2;
106188e670feSLoc Ho serdes_rd(ctx, lane, reg, &val);
106288e670feSLoc Ho val = RXTX_REG89_MU_TH7_SET(val, 0xe);
106388e670feSLoc Ho val = RXTX_REG89_MU_TH8_SET(val, 0xe);
106488e670feSLoc Ho val = RXTX_REG89_MU_TH9_SET(val, 0xe);
106588e670feSLoc Ho serdes_wr(ctx, lane, reg, val);
106688e670feSLoc Ho }
106788e670feSLoc Ho
106888e670feSLoc Ho /* Set BW select tap X for frequency adjust loop */
106988e670feSLoc Ho for (i = 0; i < 3; i++) {
107088e670feSLoc Ho reg = RXTX_REG96 + i * 2;
107188e670feSLoc Ho serdes_rd(ctx, lane, reg, &val);
107288e670feSLoc Ho val = RXTX_REG96_MU_FREQ1_SET(val, 0x10);
107388e670feSLoc Ho val = RXTX_REG96_MU_FREQ2_SET(val, 0x10);
107488e670feSLoc Ho val = RXTX_REG96_MU_FREQ3_SET(val, 0x10);
107588e670feSLoc Ho serdes_wr(ctx, lane, reg, val);
107688e670feSLoc Ho }
107788e670feSLoc Ho
107888e670feSLoc Ho /* Set BW select tap X for phase adjust loop */
107988e670feSLoc Ho for (i = 0; i < 3; i++) {
108088e670feSLoc Ho reg = RXTX_REG99 + i * 2;
108188e670feSLoc Ho serdes_rd(ctx, lane, reg, &val);
108288e670feSLoc Ho val = RXTX_REG99_MU_PHASE1_SET(val, 0x7);
108388e670feSLoc Ho val = RXTX_REG99_MU_PHASE2_SET(val, 0x7);
108488e670feSLoc Ho val = RXTX_REG99_MU_PHASE3_SET(val, 0x7);
108588e670feSLoc Ho serdes_wr(ctx, lane, reg, val);
108688e670feSLoc Ho }
108788e670feSLoc Ho
108888e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG102, &val);
108988e670feSLoc Ho val = RXTX_REG102_FREQLOOP_LIMIT_SET(val, 0x0);
109088e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG102, val);
109188e670feSLoc Ho
109288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG114, 0xffe0);
109388e670feSLoc Ho
109488e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG125, &val);
109588e670feSLoc Ho val = RXTX_REG125_SIGN_PQ_SET(val,
109688e670feSLoc Ho ctx->sata_param.txeyedirection[lane * 3 +
109788e670feSLoc Ho ctx->sata_param.speed[lane]]);
109888e670feSLoc Ho val = RXTX_REG125_PQ_REG_SET(val,
109988e670feSLoc Ho ctx->sata_param.txeyetuning[lane * 3 +
110088e670feSLoc Ho ctx->sata_param.speed[lane]]);
110188e670feSLoc Ho val = RXTX_REG125_PHZ_MANUAL_SET(val, 0x1);
110288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG125, val);
110388e670feSLoc Ho
110488e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG127, &val);
110588e670feSLoc Ho val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x0);
110688e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG127, val);
110788e670feSLoc Ho
110888e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG128, &val);
110988e670feSLoc Ho val = RXTX_REG128_LATCH_CAL_WAIT_SEL_SET(val, 0x3);
111088e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG128, val);
111188e670feSLoc Ho
111288e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG145, &val);
111388e670feSLoc Ho val = RXTX_REG145_RXDFE_CONFIG_SET(val, 0x3);
111488e670feSLoc Ho val = RXTX_REG145_TX_IDLE_SATA_SET(val, 0x0);
111588e670feSLoc Ho if (preA3Chip) {
111688e670feSLoc Ho val = RXTX_REG145_RXES_ENA_SET(val, 0x1);
111788e670feSLoc Ho val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x1);
111888e670feSLoc Ho } else {
111988e670feSLoc Ho val = RXTX_REG145_RXES_ENA_SET(val, 0x0);
112088e670feSLoc Ho val = RXTX_REG145_RXVWES_LATENA_SET(val, 0x0);
112188e670feSLoc Ho }
112288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG145, val);
112388e670feSLoc Ho
112488e670feSLoc Ho /*
112588e670feSLoc Ho * Set Rx LOS filter clock rate, sample rate, and threshold
112688e670feSLoc Ho * windows
112788e670feSLoc Ho */
112888e670feSLoc Ho for (i = 0; i < 4; i++) {
112988e670feSLoc Ho reg = RXTX_REG148 + i * 2;
113088e670feSLoc Ho serdes_wr(ctx, lane, reg, 0xFFFF);
113188e670feSLoc Ho }
113288e670feSLoc Ho }
113388e670feSLoc Ho }
113488e670feSLoc Ho
xgene_phy_cal_rdy_chk(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,enum clk_type_t clk_type)113588e670feSLoc Ho static int xgene_phy_cal_rdy_chk(struct xgene_phy_ctx *ctx,
113688e670feSLoc Ho enum cmu_type_t cmu_type,
113788e670feSLoc Ho enum clk_type_t clk_type)
113888e670feSLoc Ho {
113988e670feSLoc Ho void __iomem *csr_serdes = ctx->sds_base;
114088e670feSLoc Ho int loop;
114188e670feSLoc Ho u32 val;
114288e670feSLoc Ho
114388e670feSLoc Ho /* Release PHY main reset */
114488e670feSLoc Ho writel(0xdf, csr_serdes + SATA_ENET_SDS_RST_CTL);
114588e670feSLoc Ho readl(csr_serdes + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
114688e670feSLoc Ho
114788e670feSLoc Ho if (cmu_type != REF_CMU) {
114888e670feSLoc Ho cmu_setbits(ctx, cmu_type, CMU_REG5, CMU_REG5_PLL_RESETB_MASK);
114988e670feSLoc Ho /*
115088e670feSLoc Ho * As per PHY design spec, the PLL reset requires a minimum
115188e670feSLoc Ho * of 800us.
115288e670feSLoc Ho */
115388e670feSLoc Ho usleep_range(800, 1000);
115488e670feSLoc Ho
115588e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG1, &val);
115688e670feSLoc Ho val = CMU_REG1_PLL_MANUALCAL_SET(val, 0x0);
115788e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG1, val);
115888e670feSLoc Ho /*
115988e670feSLoc Ho * As per PHY design spec, the PLL auto calibration requires
116088e670feSLoc Ho * a minimum of 800us.
116188e670feSLoc Ho */
116288e670feSLoc Ho usleep_range(800, 1000);
116388e670feSLoc Ho
116488e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
116588e670feSLoc Ho CMU_REG32_FORCE_VCOCAL_START_MASK);
116688e670feSLoc Ho /*
116788e670feSLoc Ho * As per PHY design spec, the PLL requires a minimum of
116888e670feSLoc Ho * 800us to settle.
116988e670feSLoc Ho */
117088e670feSLoc Ho usleep_range(800, 1000);
117188e670feSLoc Ho }
117288e670feSLoc Ho
117388e670feSLoc Ho if (!preA3Chip)
117488e670feSLoc Ho goto skip_manual_cal;
117588e670feSLoc Ho
117688e670feSLoc Ho /*
117788e670feSLoc Ho * Configure the termination resister calibration
117888e670feSLoc Ho * The serial receive pins, RXP/RXN, have TERMination resistor
117988e670feSLoc Ho * that is required to be calibrated.
118088e670feSLoc Ho */
118188e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG17, &val);
118288e670feSLoc Ho val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x12);
118388e670feSLoc Ho val = CMU_REG17_RESERVED_7_SET(val, 0x0);
118488e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG17, val);
118588e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG17,
118688e670feSLoc Ho CMU_REG17_PVT_TERM_MAN_ENA_MASK);
118788e670feSLoc Ho /*
118888e670feSLoc Ho * The serial transmit pins, TXP/TXN, have Pull-UP and Pull-DOWN
118988e670feSLoc Ho * resistors that are required to the calibrated.
119088e670feSLoc Ho * Configure the pull DOWN calibration
119188e670feSLoc Ho */
119288e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG17, &val);
119388e670feSLoc Ho val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x29);
119488e670feSLoc Ho val = CMU_REG17_RESERVED_7_SET(val, 0x0);
119588e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG17, val);
119688e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
119788e670feSLoc Ho CMU_REG16_PVT_DN_MAN_ENA_MASK);
119888e670feSLoc Ho /* Configure the pull UP calibration */
119988e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG17, &val);
120088e670feSLoc Ho val = CMU_REG17_PVT_CODE_R2A_SET(val, 0x28);
120188e670feSLoc Ho val = CMU_REG17_RESERVED_7_SET(val, 0x0);
120288e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG17, val);
120388e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG16,
120488e670feSLoc Ho CMU_REG16_PVT_UP_MAN_ENA_MASK);
120588e670feSLoc Ho
120688e670feSLoc Ho skip_manual_cal:
120788e670feSLoc Ho /* Poll the PLL calibration completion status for at least 1 ms */
120888e670feSLoc Ho loop = 100;
120988e670feSLoc Ho do {
121088e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG7, &val);
121188e670feSLoc Ho if (CMU_REG7_PLL_CALIB_DONE_RD(val))
121288e670feSLoc Ho break;
121388e670feSLoc Ho /*
121488e670feSLoc Ho * As per PHY design spec, PLL calibration status requires
121588e670feSLoc Ho * a minimum of 10us to be updated.
121688e670feSLoc Ho */
121788e670feSLoc Ho usleep_range(10, 100);
121888e670feSLoc Ho } while (--loop > 0);
121988e670feSLoc Ho
122088e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG7, &val);
122188e670feSLoc Ho dev_dbg(ctx->dev, "PLL calibration %s\n",
122288e670feSLoc Ho CMU_REG7_PLL_CALIB_DONE_RD(val) ? "done" : "failed");
122388e670feSLoc Ho if (CMU_REG7_VCO_CAL_FAIL_RD(val)) {
122488e670feSLoc Ho dev_err(ctx->dev,
122588e670feSLoc Ho "PLL calibration failed due to VCO failure\n");
122688e670feSLoc Ho return -1;
122788e670feSLoc Ho }
122888e670feSLoc Ho dev_dbg(ctx->dev, "PLL calibration successful\n");
122988e670feSLoc Ho
123088e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG15, &val);
123188e670feSLoc Ho dev_dbg(ctx->dev, "PHY Tx is %sready\n", val & 0x300 ? "" : "not ");
123288e670feSLoc Ho return 0;
123388e670feSLoc Ho }
123488e670feSLoc Ho
xgene_phy_pdwn_force_vco(struct xgene_phy_ctx * ctx,enum cmu_type_t cmu_type,enum clk_type_t clk_type)123588e670feSLoc Ho static void xgene_phy_pdwn_force_vco(struct xgene_phy_ctx *ctx,
123688e670feSLoc Ho enum cmu_type_t cmu_type,
123788e670feSLoc Ho enum clk_type_t clk_type)
123888e670feSLoc Ho {
123988e670feSLoc Ho u32 val;
124088e670feSLoc Ho
124188e670feSLoc Ho dev_dbg(ctx->dev, "Reset VCO and re-start again\n");
124288e670feSLoc Ho if (cmu_type == PHY_CMU) {
124388e670feSLoc Ho cmu_rd(ctx, cmu_type, CMU_REG16, &val);
124488e670feSLoc Ho val = CMU_REG16_VCOCAL_WAIT_BTW_CODE_SET(val, 0x7);
124588e670feSLoc Ho cmu_wr(ctx, cmu_type, CMU_REG16, val);
124688e670feSLoc Ho }
124788e670feSLoc Ho
124888e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG0, CMU_REG0_PDOWN_MASK);
124988e670feSLoc Ho cmu_toggle1to0(ctx, cmu_type, CMU_REG32,
125088e670feSLoc Ho CMU_REG32_FORCE_VCOCAL_START_MASK);
125188e670feSLoc Ho }
125288e670feSLoc Ho
xgene_phy_hw_init_sata(struct xgene_phy_ctx * ctx,enum clk_type_t clk_type,int ssc_enable)125388e670feSLoc Ho static int xgene_phy_hw_init_sata(struct xgene_phy_ctx *ctx,
125488e670feSLoc Ho enum clk_type_t clk_type, int ssc_enable)
125588e670feSLoc Ho {
125688e670feSLoc Ho void __iomem *sds_base = ctx->sds_base;
125788e670feSLoc Ho u32 val;
125888e670feSLoc Ho int i;
125988e670feSLoc Ho
126088e670feSLoc Ho /* Configure the PHY for operation */
126188e670feSLoc Ho dev_dbg(ctx->dev, "Reset PHY\n");
126288e670feSLoc Ho /* Place PHY into reset */
126388e670feSLoc Ho writel(0x0, sds_base + SATA_ENET_SDS_RST_CTL);
126488e670feSLoc Ho val = readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
126588e670feSLoc Ho /* Release PHY lane from reset (active high) */
126688e670feSLoc Ho writel(0x20, sds_base + SATA_ENET_SDS_RST_CTL);
126788e670feSLoc Ho readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
126888e670feSLoc Ho /* Release all PHY module out of reset except PHY main reset */
126988e670feSLoc Ho writel(0xde, sds_base + SATA_ENET_SDS_RST_CTL);
127088e670feSLoc Ho readl(sds_base + SATA_ENET_SDS_RST_CTL); /* Force a barrier */
127188e670feSLoc Ho
127288e670feSLoc Ho /* Set the operation speed */
127388e670feSLoc Ho val = readl(sds_base + SATA_ENET_SDS_CTL1);
127488e670feSLoc Ho val = CFG_I_SPD_SEL_CDR_OVR1_SET(val,
127588e670feSLoc Ho ctx->sata_param.txspeed[ctx->sata_param.speed[0]]);
127688e670feSLoc Ho writel(val, sds_base + SATA_ENET_SDS_CTL1);
127788e670feSLoc Ho
127888e670feSLoc Ho dev_dbg(ctx->dev, "Set the customer pin mode to SATA\n");
127988e670feSLoc Ho val = readl(sds_base + SATA_ENET_SDS_CTL0);
128088e670feSLoc Ho val = REGSPEC_CFG_I_CUSTOMER_PIN_MODE0_SET(val, 0x4421);
128188e670feSLoc Ho writel(val, sds_base + SATA_ENET_SDS_CTL0);
128288e670feSLoc Ho
128388e670feSLoc Ho /* Configure the clock macro unit (CMU) clock type */
128488e670feSLoc Ho xgene_phy_cfg_cmu_clk_type(ctx, PHY_CMU, clk_type);
128588e670feSLoc Ho
128688e670feSLoc Ho /* Configure the clock macro */
128788e670feSLoc Ho xgene_phy_sata_cfg_cmu_core(ctx, PHY_CMU, clk_type);
128888e670feSLoc Ho
128988e670feSLoc Ho /* Enable SSC if enabled */
129088e670feSLoc Ho if (ssc_enable)
129188e670feSLoc Ho xgene_phy_ssc_enable(ctx, PHY_CMU);
129288e670feSLoc Ho
129388e670feSLoc Ho /* Configure PHY lanes */
129488e670feSLoc Ho xgene_phy_sata_cfg_lanes(ctx);
129588e670feSLoc Ho
129688e670feSLoc Ho /* Set Rx/Tx 20-bit */
129788e670feSLoc Ho val = readl(sds_base + SATA_ENET_SDS_PCS_CTL0);
129888e670feSLoc Ho val = REGSPEC_CFG_I_RX_WORDMODE0_SET(val, 0x3);
129988e670feSLoc Ho val = REGSPEC_CFG_I_TX_WORDMODE0_SET(val, 0x3);
130088e670feSLoc Ho writel(val, sds_base + SATA_ENET_SDS_PCS_CTL0);
130188e670feSLoc Ho
130288e670feSLoc Ho /* Start PLL calibration and try for three times */
130388e670feSLoc Ho i = 10;
130488e670feSLoc Ho do {
130588e670feSLoc Ho if (!xgene_phy_cal_rdy_chk(ctx, PHY_CMU, clk_type))
130688e670feSLoc Ho break;
130788e670feSLoc Ho /* If failed, toggle the VCO power signal and start again */
130888e670feSLoc Ho xgene_phy_pdwn_force_vco(ctx, PHY_CMU, clk_type);
130988e670feSLoc Ho } while (--i > 0);
131088e670feSLoc Ho /* Even on failure, allow to continue any way */
131188e670feSLoc Ho if (i <= 0)
131288e670feSLoc Ho dev_err(ctx->dev, "PLL calibration failed\n");
131388e670feSLoc Ho
131488e670feSLoc Ho return 0;
131588e670feSLoc Ho }
131688e670feSLoc Ho
xgene_phy_hw_initialize(struct xgene_phy_ctx * ctx,enum clk_type_t clk_type,int ssc_enable)131788e670feSLoc Ho static int xgene_phy_hw_initialize(struct xgene_phy_ctx *ctx,
131888e670feSLoc Ho enum clk_type_t clk_type,
131988e670feSLoc Ho int ssc_enable)
132088e670feSLoc Ho {
132188e670feSLoc Ho int rc;
132288e670feSLoc Ho
132388e670feSLoc Ho dev_dbg(ctx->dev, "PHY init clk type %d\n", clk_type);
132488e670feSLoc Ho
132588e670feSLoc Ho if (ctx->mode == MODE_SATA) {
132688e670feSLoc Ho rc = xgene_phy_hw_init_sata(ctx, clk_type, ssc_enable);
132788e670feSLoc Ho if (rc)
132888e670feSLoc Ho return rc;
132988e670feSLoc Ho } else {
133088e670feSLoc Ho dev_err(ctx->dev, "Un-supported customer pin mode %d\n",
133188e670feSLoc Ho ctx->mode);
133288e670feSLoc Ho return -ENODEV;
133388e670feSLoc Ho }
133488e670feSLoc Ho
133588e670feSLoc Ho return 0;
133688e670feSLoc Ho }
133788e670feSLoc Ho
133888e670feSLoc Ho /*
133988e670feSLoc Ho * Receiver Offset Calibration:
134088e670feSLoc Ho *
134188e670feSLoc Ho * Calibrate the receiver signal path offset in two steps - summar and
134288e670feSLoc Ho * latch calibrations
134388e670feSLoc Ho */
xgene_phy_force_lat_summer_cal(struct xgene_phy_ctx * ctx,int lane)134488e670feSLoc Ho static void xgene_phy_force_lat_summer_cal(struct xgene_phy_ctx *ctx, int lane)
134588e670feSLoc Ho {
134688e670feSLoc Ho int i;
1347fbf6a7a4SColin Ian King static const struct {
134888e670feSLoc Ho u32 reg;
134988e670feSLoc Ho u32 val;
135088e670feSLoc Ho } serdes_reg[] = {
135188e670feSLoc Ho {RXTX_REG38, 0x0},
135288e670feSLoc Ho {RXTX_REG39, 0xff00},
135388e670feSLoc Ho {RXTX_REG40, 0xffff},
135488e670feSLoc Ho {RXTX_REG41, 0xffff},
135588e670feSLoc Ho {RXTX_REG42, 0xffff},
135688e670feSLoc Ho {RXTX_REG43, 0xffff},
135788e670feSLoc Ho {RXTX_REG44, 0xffff},
135888e670feSLoc Ho {RXTX_REG45, 0xffff},
135988e670feSLoc Ho {RXTX_REG46, 0xffff},
136088e670feSLoc Ho {RXTX_REG47, 0xfffc},
136188e670feSLoc Ho {RXTX_REG48, 0x0},
136288e670feSLoc Ho {RXTX_REG49, 0x0},
136388e670feSLoc Ho {RXTX_REG50, 0x0},
136488e670feSLoc Ho {RXTX_REG51, 0x0},
136588e670feSLoc Ho {RXTX_REG52, 0x0},
136688e670feSLoc Ho {RXTX_REG53, 0x0},
136788e670feSLoc Ho {RXTX_REG54, 0x0},
136888e670feSLoc Ho {RXTX_REG55, 0x0},
136988e670feSLoc Ho };
137088e670feSLoc Ho
137188e670feSLoc Ho /* Start SUMMER calibration */
137288e670feSLoc Ho serdes_setbits(ctx, lane, RXTX_REG127,
137388e670feSLoc Ho RXTX_REG127_FORCE_SUM_CAL_START_MASK);
137488e670feSLoc Ho /*
137588e670feSLoc Ho * As per PHY design spec, the Summer calibration requires a minimum
137688e670feSLoc Ho * of 100us to complete.
137788e670feSLoc Ho */
137888e670feSLoc Ho usleep_range(100, 500);
137988e670feSLoc Ho serdes_clrbits(ctx, lane, RXTX_REG127,
138088e670feSLoc Ho RXTX_REG127_FORCE_SUM_CAL_START_MASK);
138188e670feSLoc Ho /*
138288e670feSLoc Ho * As per PHY design spec, the auto calibration requires a minimum
138388e670feSLoc Ho * of 100us to complete.
138488e670feSLoc Ho */
138588e670feSLoc Ho usleep_range(100, 500);
138688e670feSLoc Ho
138788e670feSLoc Ho /* Start latch calibration */
138888e670feSLoc Ho serdes_setbits(ctx, lane, RXTX_REG127,
138988e670feSLoc Ho RXTX_REG127_FORCE_LAT_CAL_START_MASK);
139088e670feSLoc Ho /*
139188e670feSLoc Ho * As per PHY design spec, the latch calibration requires a minimum
139288e670feSLoc Ho * of 100us to complete.
139388e670feSLoc Ho */
139488e670feSLoc Ho usleep_range(100, 500);
139588e670feSLoc Ho serdes_clrbits(ctx, lane, RXTX_REG127,
139688e670feSLoc Ho RXTX_REG127_FORCE_LAT_CAL_START_MASK);
139788e670feSLoc Ho
139888e670feSLoc Ho /* Configure the PHY lane for calibration */
139988e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG28, 0x7);
140088e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
140188e670feSLoc Ho serdes_clrbits(ctx, lane, RXTX_REG4,
140288e670feSLoc Ho RXTX_REG4_TX_LOOPBACK_BUF_EN_MASK);
140388e670feSLoc Ho serdes_clrbits(ctx, lane, RXTX_REG7,
140488e670feSLoc Ho RXTX_REG7_LOOP_BACK_ENA_CTLE_MASK);
140588e670feSLoc Ho for (i = 0; i < ARRAY_SIZE(serdes_reg); i++)
140688e670feSLoc Ho serdes_wr(ctx, lane, serdes_reg[i].reg,
140788e670feSLoc Ho serdes_reg[i].val);
140888e670feSLoc Ho }
140988e670feSLoc Ho
xgene_phy_reset_rxd(struct xgene_phy_ctx * ctx,int lane)141088e670feSLoc Ho static void xgene_phy_reset_rxd(struct xgene_phy_ctx *ctx, int lane)
141188e670feSLoc Ho {
141288e670feSLoc Ho /* Reset digital Rx */
141388e670feSLoc Ho serdes_clrbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
141488e670feSLoc Ho /* As per PHY design spec, the reset requires a minimum of 100us. */
141588e670feSLoc Ho usleep_range(100, 150);
141688e670feSLoc Ho serdes_setbits(ctx, lane, RXTX_REG7, RXTX_REG7_RESETB_RXD_MASK);
141788e670feSLoc Ho }
141888e670feSLoc Ho
xgene_phy_get_avg(int accum,int samples)141988e670feSLoc Ho static int xgene_phy_get_avg(int accum, int samples)
142088e670feSLoc Ho {
142188e670feSLoc Ho return (accum + (samples / 2)) / samples;
142288e670feSLoc Ho }
142388e670feSLoc Ho
xgene_phy_gen_avg_val(struct xgene_phy_ctx * ctx,int lane)142488e670feSLoc Ho static void xgene_phy_gen_avg_val(struct xgene_phy_ctx *ctx, int lane)
142588e670feSLoc Ho {
142688e670feSLoc Ho int max_loop = 10;
142788e670feSLoc Ho int avg_loop = 0;
142888e670feSLoc Ho int lat_do = 0, lat_xo = 0, lat_eo = 0, lat_so = 0;
142988e670feSLoc Ho int lat_de = 0, lat_xe = 0, lat_ee = 0, lat_se = 0;
143088e670feSLoc Ho int sum_cal = 0;
143188e670feSLoc Ho int lat_do_itr, lat_xo_itr, lat_eo_itr, lat_so_itr;
143288e670feSLoc Ho int lat_de_itr, lat_xe_itr, lat_ee_itr, lat_se_itr;
143388e670feSLoc Ho int sum_cal_itr;
143488e670feSLoc Ho int fail_even;
143588e670feSLoc Ho int fail_odd;
143688e670feSLoc Ho u32 val;
143788e670feSLoc Ho
143888e670feSLoc Ho dev_dbg(ctx->dev, "Generating avg calibration value for lane %d\n",
143988e670feSLoc Ho lane);
144088e670feSLoc Ho
144188e670feSLoc Ho /* Enable RX Hi-Z termination */
144288e670feSLoc Ho serdes_setbits(ctx, lane, RXTX_REG12,
144388e670feSLoc Ho RXTX_REG12_RX_DET_TERM_ENABLE_MASK);
144488e670feSLoc Ho /* Turn off DFE */
144588e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG28, 0x0000);
144688e670feSLoc Ho /* DFE Presets to zero */
144788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG31, 0x0000);
144888e670feSLoc Ho
144988e670feSLoc Ho /*
145088e670feSLoc Ho * Receiver Offset Calibration:
145188e670feSLoc Ho * Calibrate the receiver signal path offset in two steps - summar
145288e670feSLoc Ho * and latch calibration.
145388e670feSLoc Ho * Runs the "Receiver Offset Calibration multiple times to determine
145488e670feSLoc Ho * the average value to use.
145588e670feSLoc Ho */
145688e670feSLoc Ho while (avg_loop < max_loop) {
145788e670feSLoc Ho /* Start the calibration */
145888e670feSLoc Ho xgene_phy_force_lat_summer_cal(ctx, lane);
145988e670feSLoc Ho
146088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG21, &val);
146188e670feSLoc Ho lat_do_itr = RXTX_REG21_DO_LATCH_CALOUT_RD(val);
146288e670feSLoc Ho lat_xo_itr = RXTX_REG21_XO_LATCH_CALOUT_RD(val);
146388e670feSLoc Ho fail_odd = RXTX_REG21_LATCH_CAL_FAIL_ODD_RD(val);
146488e670feSLoc Ho
146588e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG22, &val);
146688e670feSLoc Ho lat_eo_itr = RXTX_REG22_EO_LATCH_CALOUT_RD(val);
146788e670feSLoc Ho lat_so_itr = RXTX_REG22_SO_LATCH_CALOUT_RD(val);
146888e670feSLoc Ho fail_even = RXTX_REG22_LATCH_CAL_FAIL_EVEN_RD(val);
146988e670feSLoc Ho
147088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG23, &val);
147188e670feSLoc Ho lat_de_itr = RXTX_REG23_DE_LATCH_CALOUT_RD(val);
147288e670feSLoc Ho lat_xe_itr = RXTX_REG23_XE_LATCH_CALOUT_RD(val);
147388e670feSLoc Ho
147488e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG24, &val);
147588e670feSLoc Ho lat_ee_itr = RXTX_REG24_EE_LATCH_CALOUT_RD(val);
147688e670feSLoc Ho lat_se_itr = RXTX_REG24_SE_LATCH_CALOUT_RD(val);
147788e670feSLoc Ho
147888e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG121, &val);
147988e670feSLoc Ho sum_cal_itr = RXTX_REG121_SUMOS_CAL_CODE_RD(val);
148088e670feSLoc Ho
148188e670feSLoc Ho /* Check for failure. If passed, sum them for averaging */
148288e670feSLoc Ho if ((fail_even == 0 || fail_even == 1) &&
148388e670feSLoc Ho (fail_odd == 0 || fail_odd == 1)) {
148488e670feSLoc Ho lat_do += lat_do_itr;
148588e670feSLoc Ho lat_xo += lat_xo_itr;
148688e670feSLoc Ho lat_eo += lat_eo_itr;
148788e670feSLoc Ho lat_so += lat_so_itr;
148888e670feSLoc Ho lat_de += lat_de_itr;
148988e670feSLoc Ho lat_xe += lat_xe_itr;
149088e670feSLoc Ho lat_ee += lat_ee_itr;
149188e670feSLoc Ho lat_se += lat_se_itr;
149288e670feSLoc Ho sum_cal += sum_cal_itr;
149388e670feSLoc Ho
149488e670feSLoc Ho dev_dbg(ctx->dev, "Iteration %d:\n", avg_loop);
149588e670feSLoc Ho dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
149688e670feSLoc Ho lat_do_itr, lat_xo_itr, lat_eo_itr,
149788e670feSLoc Ho lat_so_itr);
149888e670feSLoc Ho dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
149988e670feSLoc Ho lat_de_itr, lat_xe_itr, lat_ee_itr,
150088e670feSLoc Ho lat_se_itr);
150188e670feSLoc Ho dev_dbg(ctx->dev, "SUM 0x%x\n", sum_cal_itr);
150288e670feSLoc Ho ++avg_loop;
150388e670feSLoc Ho } else {
150488e670feSLoc Ho dev_err(ctx->dev,
150588e670feSLoc Ho "Receiver calibration failed at %d loop\n",
150688e670feSLoc Ho avg_loop);
150788e670feSLoc Ho }
150888e670feSLoc Ho xgene_phy_reset_rxd(ctx, lane);
150988e670feSLoc Ho }
151088e670feSLoc Ho
151188e670feSLoc Ho /* Update latch manual calibration with average value */
151288e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG127, &val);
151388e670feSLoc Ho val = RXTX_REG127_DO_LATCH_MANCAL_SET(val,
151488e670feSLoc Ho xgene_phy_get_avg(lat_do, max_loop));
151588e670feSLoc Ho val = RXTX_REG127_XO_LATCH_MANCAL_SET(val,
151688e670feSLoc Ho xgene_phy_get_avg(lat_xo, max_loop));
151788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG127, val);
151888e670feSLoc Ho
151988e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG128, &val);
152088e670feSLoc Ho val = RXTX_REG128_EO_LATCH_MANCAL_SET(val,
152188e670feSLoc Ho xgene_phy_get_avg(lat_eo, max_loop));
152288e670feSLoc Ho val = RXTX_REG128_SO_LATCH_MANCAL_SET(val,
152388e670feSLoc Ho xgene_phy_get_avg(lat_so, max_loop));
152488e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG128, val);
152588e670feSLoc Ho
152688e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG129, &val);
152788e670feSLoc Ho val = RXTX_REG129_DE_LATCH_MANCAL_SET(val,
152888e670feSLoc Ho xgene_phy_get_avg(lat_de, max_loop));
152988e670feSLoc Ho val = RXTX_REG129_XE_LATCH_MANCAL_SET(val,
153088e670feSLoc Ho xgene_phy_get_avg(lat_xe, max_loop));
153188e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG129, val);
153288e670feSLoc Ho
153388e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG130, &val);
153488e670feSLoc Ho val = RXTX_REG130_EE_LATCH_MANCAL_SET(val,
153588e670feSLoc Ho xgene_phy_get_avg(lat_ee, max_loop));
153688e670feSLoc Ho val = RXTX_REG130_SE_LATCH_MANCAL_SET(val,
153788e670feSLoc Ho xgene_phy_get_avg(lat_se, max_loop));
153888e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG130, val);
153988e670feSLoc Ho
154088e670feSLoc Ho /* Update SUMMER calibration with average value */
154188e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG14, &val);
154288e670feSLoc Ho val = RXTX_REG14_CLTE_LATCAL_MAN_PROG_SET(val,
154388e670feSLoc Ho xgene_phy_get_avg(sum_cal, max_loop));
154488e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG14, val);
154588e670feSLoc Ho
154688e670feSLoc Ho dev_dbg(ctx->dev, "Average Value:\n");
154788e670feSLoc Ho dev_dbg(ctx->dev, "DO 0x%x XO 0x%x EO 0x%x SO 0x%x\n",
154888e670feSLoc Ho xgene_phy_get_avg(lat_do, max_loop),
154988e670feSLoc Ho xgene_phy_get_avg(lat_xo, max_loop),
155088e670feSLoc Ho xgene_phy_get_avg(lat_eo, max_loop),
155188e670feSLoc Ho xgene_phy_get_avg(lat_so, max_loop));
155288e670feSLoc Ho dev_dbg(ctx->dev, "DE 0x%x XE 0x%x EE 0x%x SE 0x%x\n",
155388e670feSLoc Ho xgene_phy_get_avg(lat_de, max_loop),
155488e670feSLoc Ho xgene_phy_get_avg(lat_xe, max_loop),
155588e670feSLoc Ho xgene_phy_get_avg(lat_ee, max_loop),
155688e670feSLoc Ho xgene_phy_get_avg(lat_se, max_loop));
155788e670feSLoc Ho dev_dbg(ctx->dev, "SUM 0x%x\n",
155888e670feSLoc Ho xgene_phy_get_avg(sum_cal, max_loop));
155988e670feSLoc Ho
156088e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG14, &val);
156188e670feSLoc Ho val = RXTX_REG14_CTLE_LATCAL_MAN_ENA_SET(val, 0x1);
156288e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG14, val);
156388e670feSLoc Ho dev_dbg(ctx->dev, "Enable Manual Summer calibration\n");
156488e670feSLoc Ho
156588e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG127, &val);
156688e670feSLoc Ho val = RXTX_REG127_LATCH_MAN_CAL_ENA_SET(val, 0x1);
156788e670feSLoc Ho dev_dbg(ctx->dev, "Enable Manual Latch calibration\n");
156888e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG127, val);
156988e670feSLoc Ho
157088e670feSLoc Ho /* Disable RX Hi-Z termination */
157188e670feSLoc Ho serdes_rd(ctx, lane, RXTX_REG12, &val);
157288e670feSLoc Ho val = RXTX_REG12_RX_DET_TERM_ENABLE_SET(val, 0);
157388e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG12, val);
157488e670feSLoc Ho /* Turn on DFE */
157588e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG28, 0x0007);
157688e670feSLoc Ho /* Set DFE preset */
157788e670feSLoc Ho serdes_wr(ctx, lane, RXTX_REG31, 0x7e00);
157888e670feSLoc Ho }
157988e670feSLoc Ho
xgene_phy_hw_init(struct phy * phy)158088e670feSLoc Ho static int xgene_phy_hw_init(struct phy *phy)
158188e670feSLoc Ho {
158288e670feSLoc Ho struct xgene_phy_ctx *ctx = phy_get_drvdata(phy);
158388e670feSLoc Ho int rc;
158488e670feSLoc Ho int i;
158588e670feSLoc Ho
158688e670feSLoc Ho rc = xgene_phy_hw_initialize(ctx, CLK_EXT_DIFF, SSC_DISABLE);
158788e670feSLoc Ho if (rc) {
158888e670feSLoc Ho dev_err(ctx->dev, "PHY initialize failed %d\n", rc);
158988e670feSLoc Ho return rc;
159088e670feSLoc Ho }
159188e670feSLoc Ho
159288e670feSLoc Ho /* Setup clock properly after PHY configuration */
159388e670feSLoc Ho if (!IS_ERR(ctx->clk)) {
159488e670feSLoc Ho /* HW requires an toggle of the clock */
159588e670feSLoc Ho clk_prepare_enable(ctx->clk);
159688e670feSLoc Ho clk_disable_unprepare(ctx->clk);
159788e670feSLoc Ho clk_prepare_enable(ctx->clk);
159888e670feSLoc Ho }
159988e670feSLoc Ho
160088e670feSLoc Ho /* Compute average value */
160188e670feSLoc Ho for (i = 0; i < MAX_LANE; i++)
160288e670feSLoc Ho xgene_phy_gen_avg_val(ctx, i);
160388e670feSLoc Ho
160488e670feSLoc Ho dev_dbg(ctx->dev, "PHY initialized\n");
160588e670feSLoc Ho return 0;
160688e670feSLoc Ho }
160788e670feSLoc Ho
160888e670feSLoc Ho static const struct phy_ops xgene_phy_ops = {
160988e670feSLoc Ho .init = xgene_phy_hw_init,
161088e670feSLoc Ho .owner = THIS_MODULE,
161188e670feSLoc Ho };
161288e670feSLoc Ho
xgene_phy_xlate(struct device * dev,struct of_phandle_args * args)161388e670feSLoc Ho static struct phy *xgene_phy_xlate(struct device *dev,
161488e670feSLoc Ho struct of_phandle_args *args)
161588e670feSLoc Ho {
161688e670feSLoc Ho struct xgene_phy_ctx *ctx = dev_get_drvdata(dev);
161788e670feSLoc Ho
161888e670feSLoc Ho if (args->args_count <= 0)
161988e670feSLoc Ho return ERR_PTR(-EINVAL);
1620f0c47c74SVinod Koul if (args->args[0] >= MODE_MAX)
162188e670feSLoc Ho return ERR_PTR(-EINVAL);
162288e670feSLoc Ho
162388e670feSLoc Ho ctx->mode = args->args[0];
162488e670feSLoc Ho return ctx->phy;
162588e670feSLoc Ho }
162688e670feSLoc Ho
xgene_phy_get_param(struct platform_device * pdev,const char * name,u32 * buffer,int count,u32 * default_val,u32 conv_factor)162788e670feSLoc Ho static void xgene_phy_get_param(struct platform_device *pdev,
162888e670feSLoc Ho const char *name, u32 *buffer,
162988e670feSLoc Ho int count, u32 *default_val,
163088e670feSLoc Ho u32 conv_factor)
163188e670feSLoc Ho {
163288e670feSLoc Ho int i;
163388e670feSLoc Ho
163488e670feSLoc Ho if (!of_property_read_u32_array(pdev->dev.of_node, name, buffer,
163588e670feSLoc Ho count)) {
163688e670feSLoc Ho for (i = 0; i < count; i++)
163788e670feSLoc Ho buffer[i] /= conv_factor;
163888e670feSLoc Ho return;
163988e670feSLoc Ho }
164088e670feSLoc Ho /* Does not exist, load default */
164188e670feSLoc Ho for (i = 0; i < count; i++)
164288e670feSLoc Ho buffer[i] = default_val[i % 3];
164388e670feSLoc Ho }
164488e670feSLoc Ho
xgene_phy_probe(struct platform_device * pdev)164588e670feSLoc Ho static int xgene_phy_probe(struct platform_device *pdev)
164688e670feSLoc Ho {
164788e670feSLoc Ho struct phy_provider *phy_provider;
164888e670feSLoc Ho struct xgene_phy_ctx *ctx;
164988e670feSLoc Ho u32 default_spd[] = DEFAULT_SATA_SPD_SEL;
165088e670feSLoc Ho u32 default_txboost_gain[] = DEFAULT_SATA_TXBOOST_GAIN;
165188e670feSLoc Ho u32 default_txeye_direction[] = DEFAULT_SATA_TXEYEDIRECTION;
165288e670feSLoc Ho u32 default_txeye_tuning[] = DEFAULT_SATA_TXEYETUNING;
165388e670feSLoc Ho u32 default_txamp[] = DEFAULT_SATA_TXAMP;
165488e670feSLoc Ho u32 default_txcn1[] = DEFAULT_SATA_TXCN1;
165588e670feSLoc Ho u32 default_txcn2[] = DEFAULT_SATA_TXCN2;
165688e670feSLoc Ho u32 default_txcp1[] = DEFAULT_SATA_TXCP1;
165788e670feSLoc Ho int i;
165888e670feSLoc Ho
165988e670feSLoc Ho ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
166088e670feSLoc Ho if (!ctx)
166188e670feSLoc Ho return -ENOMEM;
166288e670feSLoc Ho
166388e670feSLoc Ho ctx->dev = &pdev->dev;
166488e670feSLoc Ho
16655d797059SChunfeng Yun ctx->sds_base = devm_platform_ioremap_resource(pdev, 0);
16668fd0ea39SAxel Lin if (IS_ERR(ctx->sds_base))
16678fd0ea39SAxel Lin return PTR_ERR(ctx->sds_base);
166888e670feSLoc Ho
166988e670feSLoc Ho /* Retrieve optional clock */
167088e670feSLoc Ho ctx->clk = clk_get(&pdev->dev, NULL);
167188e670feSLoc Ho
167288e670feSLoc Ho /* Load override paramaters */
167388e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-eye-tuning",
167488e670feSLoc Ho ctx->sata_param.txeyetuning, 6, default_txeye_tuning, 1);
167588e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-eye-direction",
167688e670feSLoc Ho ctx->sata_param.txeyedirection, 6, default_txeye_direction, 1);
167788e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-boost-gain",
167888e670feSLoc Ho ctx->sata_param.txboostgain, 6, default_txboost_gain, 1);
167988e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-amplitude",
168088e670feSLoc Ho ctx->sata_param.txamplitude, 6, default_txamp, 13300);
168188e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-pre-cursor1",
168288e670feSLoc Ho ctx->sata_param.txprecursor_cn1, 6, default_txcn1, 18200);
168388e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-pre-cursor2",
168488e670feSLoc Ho ctx->sata_param.txprecursor_cn2, 6, default_txcn2, 18200);
168588e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-post-cursor",
168688e670feSLoc Ho ctx->sata_param.txpostcursor_cp1, 6, default_txcp1, 18200);
168788e670feSLoc Ho xgene_phy_get_param(pdev, "apm,tx-speed",
168888e670feSLoc Ho ctx->sata_param.txspeed, 3, default_spd, 1);
168988e670feSLoc Ho for (i = 0; i < MAX_LANE; i++)
169088e670feSLoc Ho ctx->sata_param.speed[i] = 2; /* Default to Gen3 */
169188e670feSLoc Ho
169288e670feSLoc Ho platform_set_drvdata(pdev, ctx);
169388e670feSLoc Ho
1694dbc98635SHeikki Krogerus ctx->phy = devm_phy_create(ctx->dev, NULL, &xgene_phy_ops);
169588e670feSLoc Ho if (IS_ERR(ctx->phy)) {
169688e670feSLoc Ho dev_dbg(&pdev->dev, "Failed to create PHY\n");
16978fd0ea39SAxel Lin return PTR_ERR(ctx->phy);
169888e670feSLoc Ho }
169988e670feSLoc Ho phy_set_drvdata(ctx->phy, ctx);
170088e670feSLoc Ho
17018fd0ea39SAxel Lin phy_provider = devm_of_phy_provider_register(ctx->dev, xgene_phy_xlate);
17028fd0ea39SAxel Lin return PTR_ERR_OR_ZERO(phy_provider);
170388e670feSLoc Ho }
170488e670feSLoc Ho
170588e670feSLoc Ho static const struct of_device_id xgene_phy_of_match[] = {
170688e670feSLoc Ho {.compatible = "apm,xgene-phy",},
170788e670feSLoc Ho {},
170888e670feSLoc Ho };
170988e670feSLoc Ho MODULE_DEVICE_TABLE(of, xgene_phy_of_match);
171088e670feSLoc Ho
171188e670feSLoc Ho static struct platform_driver xgene_phy_driver = {
171288e670feSLoc Ho .probe = xgene_phy_probe,
171388e670feSLoc Ho .driver = {
171488e670feSLoc Ho .name = "xgene-phy",
171588e670feSLoc Ho .of_match_table = xgene_phy_of_match,
171688e670feSLoc Ho },
171788e670feSLoc Ho };
171888e670feSLoc Ho module_platform_driver(xgene_phy_driver);
171988e670feSLoc Ho
172088e670feSLoc Ho MODULE_DESCRIPTION("APM X-Gene Multi-Purpose PHY driver");
172188e670feSLoc Ho MODULE_AUTHOR("Loc Ho <lho@apm.com>");
172288e670feSLoc Ho MODULE_LICENSE("GPL v2");
172388e670feSLoc Ho MODULE_VERSION("0.1");
1724