diff options
author | Linux Build Service Account <lnxbuild@localhost> | 2022-12-06 14:39:03 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2022-12-06 14:39:03 -0800 |
commit | 7ef1684cc542f977a99c0823aa595af65f0ba3d5 (patch) | |
tree | 5e2a32100969e7ea6be02267510d8e27b08d0a15 | |
parent | c51cda2b5a1f23dd8e22368a8a8711620f72968c (diff) | |
parent | da35396b2127d777360a103e34a7422d388980b9 (diff) |
Merge "net: stmmac: HSR seq programming in ethqos_configure_mac_v3()" into wip-er12
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 258 |
1 files changed, 257 insertions, 1 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c index ef238c72844ce..f1285e63af80f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c @@ -44,6 +44,15 @@ #define RGMII_CONFIG_PROG_SWAP BIT(1) #define RGMII_CONFIG_DDR_MODE BIT(0) +/*RGMII DLL CONFIG*/ +#define HSR_DLL_CONFIG 0x000B642C +#define HSR_DLL_CONFIG_2 0xA001 +#define HSR_DDR_CONFIG 0x80040868 +#define HSR_SDCC_USR_CTRL 0x2C010800 +#define HSR_SDCC_DLL_TEST_CTRL 0x1800000 +#define DDR_CONFIG_PRG_RCLK_DLY 115 +#define DLL_BYPASS BIT(30) + /* SDCC_HC_REG_DLL_CONFIG fields */ #define SDCC_DLL_CONFIG_DLL_RST BIT(30) #define SDCC_DLL_CONFIG_PDN BIT(29) @@ -85,6 +94,7 @@ #define RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN BIT(5) #define EMAC_I0_EMAC_CORE_HW_VERSION_RGOFFADDR 0x00000070 +#define EMAC_HW_v3_0_0_RG 0x30000000 #define MII_BUSY 0x00000001 #define MII_WRITE 0x00000002 @@ -456,6 +466,121 @@ static int ethqos_dll_configure(struct qcom_ethqos *ethqos) return 0; } +void emac_rgmii_io_macro_config_1G(struct qcom_ethqos *ethqos) +{ + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + RGMII_CONFIG_POS_NEG_DATA_SEL, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + RGMII_CONFIG_PROG_SWAP, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + if (ethqos->io_macro.tx_clk_phase_shift_en) + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + + /* Init DDR_CONFIG */ + rgmii_writel(ethqos, HSR_DDR_CONFIG, SDCC_HC_REG_DDR_CONFIG); + + /* Configure PRG_RCLK_DLY to 115*/ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_RCLK_DLY, + DDR_CONFIG_PRG_RCLK_DLY, SDCC_HC_REG_DDR_CONFIG); + /*Enable PRG_RCLK_CLY */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_PRG_DLY_EN, + SDCC_DDR_CONFIG_PRG_DLY_EN, SDCC_HC_REG_DDR_CONFIG); + + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG); +} + +void emac_rgmii_io_macro_config_100M(struct qcom_ethqos *ethqos) +{ + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + if (ethqos->io_macro.tx_clk_phase_shift_en) + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_2, + BIT(6), RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + + /* Write 0x5 to PRG_RCLK_DLY_CODE */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_EN, + SDCC_HC_REG_DDR_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG); +} + +void emac_rgmii_io_macro_config_10M(struct qcom_ethqos *ethqos) +{ + rgmii_updatel(ethqos, RGMII_CONFIG_DDR_MODE, + RGMII_CONFIG_DDR_MODE, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_CONFIG_BYPASS_TX_ID_EN, + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_POS_NEG_DATA_SEL, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG_PROG_SWAP, + 0, RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_DATA_DIVIDE_CLK_SEL, + 0, RGMII_IO_MACRO_CONFIG2); + if (ethqos->io_macro.tx_clk_phase_shift_en) + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + RGMII_IO_MACRO_CONFIG2); + else + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_CLK_PHASE_SHIFT_EN, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG_MAX_SPD_PRG_9, + BIT(12) | GENMASK(9, 8), + RGMII_IO_MACRO_CONFIG); + rgmii_updatel(ethqos, RGMII_CONFIG2_RSVD_CONFIG15, + 0, RGMII_IO_MACRO_CONFIG2); + rgmii_updatel(ethqos, RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_CONFIG2_RX_PROG_SWAP, + RGMII_IO_MACRO_CONFIG2); + + /* Write 0x5 to PRG_RCLK_DLY_CODE */ + rgmii_updatel(ethqos, SDCC_DDR_CONFIG_EXT_PRG_RCLK_DLY_CODE, + (BIT(29) | BIT(27)), SDCC_HC_REG_DDR_CONFIG); +} + static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) { /* Disable loopback mode */ @@ -661,6 +786,37 @@ static int ethqos_rgmii_macro_init(struct qcom_ethqos *ethqos) return 0; } +static int ethqos_rgmii_macro_init_v3(struct qcom_ethqos *ethqos) +{ + /* Disable loopback mode */ + rgmii_updatel(ethqos, RGMII_CONFIG2_TX_TO_RX_LOOPBACK_EN, + 0, RGMII_IO_MACRO_CONFIG2); + + /* Select RGMII, write 0 to interface select */ + rgmii_updatel(ethqos, RGMII_CONFIG_INTF_SEL, + 0, RGMII_IO_MACRO_CONFIG); + + switch (ethqos->speed) { + case SPEED_1000: + emac_rgmii_io_macro_config_1G(ethqos); + break; + + case SPEED_100: + emac_rgmii_io_macro_config_100M(ethqos); + break; + + case SPEED_10: + emac_rgmii_io_macro_config_10M(ethqos); + break; + default: + dev_err(ðqos->pdev->dev, + "Invalid speed %d\n", ethqos->speed); + return -EINVAL; + } + + return 0; +} + static int ethqos_configure(struct qcom_ethqos *ethqos) { volatile unsigned int dll_lock; @@ -766,13 +922,113 @@ static int ethqos_configure(struct qcom_ethqos *ethqos) return 0; } +/* for EMAC_HW_VER >= 3 */ +static int ethqos_configure_mac_v3(struct qcom_ethqos *ethqos) +{ + unsigned int dll_lock; + unsigned int i, retry = 1000; + int ret = 0; + /* Reset to POR values and enable clk */ + for (i = 0; i < ethqos->num_por; i++) + rgmii_writel(ethqos, ethqos->por[i].value, + ethqos->por[i].offset); + ethqos_set_func_clk_en(ethqos); + + /* Put DLL into Reset and Powerdown */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, + SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG); + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG) + ; + /*Power on and set DLL, Set->RST & PDN to '0' */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, + 0, SDCC_HC_REG_DLL_CONFIG); + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + 0, SDCC_HC_REG_DLL_CONFIG); + + /* for 10 or 100Mbps further configuration not required */ + if (ethqos->speed == SPEED_1000) { + /* Disable DLL output clock */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, + 0, SDCC_HC_REG_DLL_CONFIG); + + /* Configure SDCC_DLL_TEST_CTRL */ + rgmii_writel(ethqos, HSR_SDCC_DLL_TEST_CTRL, SDCC_TEST_CTL); + + /* Configure SDCC_USR_CTRL */ + rgmii_writel(ethqos, HSR_SDCC_USR_CTRL, SDCC_USR_CTL); + + /* Configure DLL_CONFIG */ + rgmii_writel(ethqos, HSR_DLL_CONFIG, SDCC_HC_REG_DLL_CONFIG); + + /*Set -> DLL_CONFIG_2 MCLK_FREQ_CALC*/ + rgmii_writel(ethqos, HSR_DLL_CONFIG_2, SDCC_HC_REG_DLL_CONFIG2); + + /*Power Down and Reset DLL*/ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, + SDCC_DLL_CONFIG_DLL_RST, SDCC_HC_REG_DLL_CONFIG); + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + + /*wait for 52us*/ + usleep_range(52, 55); + + /*Power on and set DLL, Set->RST & PDN to '0' */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_DLL_RST, + 0, SDCC_HC_REG_DLL_CONFIG); + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + 0, SDCC_HC_REG_DLL_CONFIG); + + /*Wait for 8000 input clock cycles, 8000 cycles of 100 MHz = 80us*/ + usleep_range(80, 85); + + /* Enable DLL output clock */ + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_CK_OUT_EN, + SDCC_DLL_CONFIG_CK_OUT_EN, SDCC_HC_REG_DLL_CONFIG); + + /* Check for DLL lock */ + do { + udelay(1); + dll_lock = rgmii_readl(ethqos, SDC4_STATUS); + if (dll_lock & SDC4_STATUS_DLL_LOCK) + break; + retry--; + } while (retry > 0); + if (!retry) + dev_err(ðqos->pdev->dev, + "Timeout while waiting for DLL lock\n"); + } + + /* DLL bypass mode for 10Mbps and 100Mbps + * 1. Write 1 to PDN bit of SDCC_HC_REG_DLL_CONFIG register. + * 2. Write 1 to bypass bit of SDCC_USR_CTL register + * 3. Default value of this register is 0x00010800 + */ + if (ethqos->speed == SPEED_10 || ethqos->speed == SPEED_100) { + rgmii_updatel(ethqos, SDCC_DLL_CONFIG_PDN, + SDCC_DLL_CONFIG_PDN, SDCC_HC_REG_DLL_CONFIG); + rgmii_updatel(ethqos, DLL_BYPASS, + DLL_BYPASS, SDCC_USR_CTL); + } + + ret = ethqos_rgmii_macro_init_v3(ethqos); + + return ret; +} + static void ethqos_fix_mac_speed(void *priv, unsigned int speed) { struct qcom_ethqos *ethqos = priv; + int ret = 0; ethqos->speed = speed; ethqos_update_rgmii_clk(ethqos, speed); - ethqos_configure(ethqos); + if (ethqos->emac_ver == EMAC_HW_v3_0_0_RG) + ret = ethqos_configure_mac_v3(ethqos); + else + ethqos_configure(ethqos); + if (ret != 0) + ETHQOSERR("HSR configuration has failed\n"); } static int ethqos_mdio_read(struct stmmac_priv *priv, int phyaddr, int phyreg) |