From 86093582618baee4611a53764d25858ada322102 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Marek=20Beh=C3=BAn?= Date: Tue, 24 Apr 2018 17:21:18 +0200 Subject: [PATCH] phy: marvell: a3700: Access USB3 register indirectly on lane 2 When USB3 is on comphy lane 2 on the Armada 37xx, the registers have to be accessed indirectly via SATA indirect access. This is the case of the Turris Mox board from CZ.NIC. Signed-off-by: Marek Behun Signed-off-by: Stefan Roese --- drivers/phy/marvell/comphy_a3700.c | 102 ++++++++++++++++++++++++------------- drivers/phy/marvell/comphy_a3700.h | 1 + 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/drivers/phy/marvell/comphy_a3700.c b/drivers/phy/marvell/comphy_a3700.c index 81f2b63..4fb23bb 100644 --- a/drivers/phy/marvell/comphy_a3700.c +++ b/drivers/phy/marvell/comphy_a3700.c @@ -132,7 +132,7 @@ static u32 comphy_poll_reg(void *addr, u32 val, u32 mask, u8 op_type) */ static int comphy_pcie_power_up(u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -300,13 +300,35 @@ static int comphy_sata_power_up(void) } /* + * usb3_reg_set16 + * + * return: void + */ +static void usb3_reg_set16(u32 reg, u16 data, u16 mask, u32 lane) +{ + /* + * When Lane 2 PHY is for USB3, access the PHY registers + * through indirect Address and Data registers INDIR_ACC_PHY_ADDR + * (RD00E0178h [31:0]) and INDIR_ACC_PHY_DATA (RD00E017Ch [31:0]) + * within the SATA Host Controller registers, Lane 2 base register + * offset is 0x200 + */ + + if (lane == 2) + reg_set_indirect(USB3PHY_LANE2_REG_BASE_OFFSET + reg, data, + mask); + else + reg_set16(phy_addr(USB3, reg), data, mask); +} + +/* * comphy_usb3_power_up * * return: 1 if PLL locked (OK), 0 otherwise (FAIL) */ -static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) +static int comphy_usb3_power_up(u32 lane, u32 type, u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -324,39 +346,38 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) /* 0xd005c300 = 0x1001 */ /* set PRD_TXDEEMPH (3.5db de-emph) */ - reg_set16(phy_addr(USB3, LANE_CFG0), 0x1, 0xFF); + usb3_reg_set16(LANE_CFG0, 0x1, 0xFF, lane); /* * unset BIT0: set Tx Electrical Idle Mode: Transmitter is in - * low impedance mode during electrical idle + * low impedance mode during electrical idle + * unset BIT4: set G2 Tx Datapath with no Delayed Latency + * unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - /* unset BIT4: set G2 Tx Datapath with no Delayed Latency */ - /* unset BIT6: set Tx Detect Rx Mode at LoZ mode */ - reg_set16(phy_addr(USB3, LANE_CFG1), 0x0, 0xFFFF); + usb3_reg_set16(LANE_CFG1, 0x0, 0xFFFF, lane); - /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ - reg_set16(phy_addr(USB3, LANE_CFG4), bf_spread_spectrum_clock_en, 0x80); + /* 0xd005c310 = 0x93: set Spread Spectrum Clock Enabled */ + usb3_reg_set16(LANE_CFG4, bf_spread_spectrum_clock_en, 0x80, lane); /* * set Override Margining Controls From the MAC: Use margining signals * from lane configuration */ - reg_set16(phy_addr(USB3, TEST_MODE_CTRL), rb_mode_margin_override, - 0xFFFF); + usb3_reg_set16(TEST_MODE_CTRL, rb_mode_margin_override, 0xFFFF, lane); /* set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles */ /* set Mode Clock Source = PCLK is generated from REFCLK */ - reg_set16(phy_addr(USB3, GLOB_CLK_SRC_LO), 0x0, 0xFF); + usb3_reg_set16(GLOB_CLK_SRC_LO, 0x0, 0xFF, lane); /* set G2 Spread Spectrum Clock Amplitude at 4K */ - reg_set16(phy_addr(USB3, GEN2_SETTINGS_2), g2_tx_ssc_amp, 0xF000); + usb3_reg_set16(GEN2_SETTINGS_2, g2_tx_ssc_amp, 0xF000, lane); /* * unset G3 Spread Spectrum Clock Amplitude & set G3 TX and RX Register * Master Current Select */ - reg_set16(phy_addr(USB3, GEN2_SETTINGS_3), 0x0, 0xFFFF); + usb3_reg_set16(GEN2_SETTINGS_3, 0x0, 0xFFFF, lane); /* * 3. Check crystal jumper setting and program the Power and PLL @@ -364,62 +385,72 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ if (get_ref_clk() == 40) { /* 40 MHz */ - reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA3, 0xFFFF); + usb3_reg_set16(PWR_PLL_CTRL, 0xFCA3, 0xFFFF, lane); } else { /* 25 MHz */ - reg_set16(phy_addr(USB3, PWR_PLL_CTRL), 0xFCA2, 0xFFFF); + usb3_reg_set16(PWR_PLL_CTRL, 0xFCA2, 0xFFFF, lane); } /* * 4. Change RX wait */ - reg_set16(phy_addr(USB3, PWR_MGM_TIM1), 0x10C, 0xFFFF); + usb3_reg_set16(PWR_MGM_TIM1, 0x10C, 0xFFFF, lane); /* * 5. Enable idle sync */ - reg_set16(phy_addr(USB3, UNIT_CTRL), 0x60 | rb_idle_sync_en, 0xFFFF); + usb3_reg_set16(UNIT_CTRL, 0x60 | rb_idle_sync_en, 0xFFFF, lane); /* * 6. Enable the output of 500M clock */ - reg_set16(phy_addr(USB3, MISC_REG0), 0xA00D | rb_clk500m_en, 0xFFFF); + usb3_reg_set16(MISC_REG0, 0xA00D | rb_clk500m_en, 0xFFFF, lane); /* * 7. Set 20-bit data width */ - reg_set16(phy_addr(USB3, DIG_LB_EN), 0x0400, 0xFFFF); + usb3_reg_set16(DIG_LB_EN, 0x0400, 0xFFFF, lane); /* * 8. Override Speed_PLL value and use MAC PLL */ - reg_set16(phy_addr(USB3, KVCO_CAL_CTRL), 0x0040 | rb_use_max_pll_rate, - 0xFFFF); + usb3_reg_set16(KVCO_CAL_CTRL, 0x0040 | rb_use_max_pll_rate, 0xFFFF, + lane); /* * 9. Check the Polarity invert bit */ if (invert & PHY_POLARITY_TXD_INVERT) - reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_txd_inv, 0); + usb3_reg_set16(SYNC_PATTERN, phy_txd_inv, 0, lane); if (invert & PHY_POLARITY_RXD_INVERT) - reg_set16(phy_addr(USB3, SYNC_PATTERN), phy_rxd_inv, 0); + usb3_reg_set16(SYNC_PATTERN, phy_rxd_inv, 0, lane); /* * 10. Release SW reset */ - reg_set16(phy_addr(USB3, GLOB_PHY_CTRL0), - rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 | 0x20, - 0xFFFF); + usb3_reg_set16(GLOB_PHY_CTRL0, + rb_mode_core_clk_freq_sel | rb_mode_pipe_width_32 + | 0x20, 0xFFFF, lane); /* Wait for > 55 us to allow PCLK be enabled */ udelay(PLL_SET_DELAY_US); /* Assert PCLK enabled */ - ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ - rb_txdclk_pclk_en, /* value */ - rb_txdclk_pclk_en, /* mask */ - POLL_16B_REG); /* 16bit */ + if (lane == 2) { + reg_set(rh_vsreg_addr, + LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET, + 0xFFFFFFFF); + ret = comphy_poll_reg(rh_vsreg_data, /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + POLL_32B_REG); /* 32bit */ + } else { + ret = comphy_poll_reg(phy_addr(USB3, LANE_STAT1), /* address */ + rb_txdclk_pclk_en, /* value */ + rb_txdclk_pclk_en, /* mask */ + POLL_16B_REG); /* 16bit */ + } if (!ret) printf("Failed to lock USB3 PLL\n"); @@ -455,7 +486,7 @@ static int comphy_usb3_power_up(u32 type, u32 speed, u32 invert) */ static int comphy_usb2_power_up(u8 usb32) { - int ret; + int ret; debug_enter(); @@ -620,7 +651,7 @@ static void comphy_sgmii_phy_init(u32 lane, u32 speed) */ static int comphy_sgmii_power_up(u32 lane, u32 speed, u32 invert) { - int ret; + int ret; debug_enter(); @@ -906,7 +937,8 @@ int comphy_a3700_init(struct chip_serdes_phy_config *chip_cfg, case PHY_TYPE_USB3_HOST0: case PHY_TYPE_USB3_DEVICE: - ret = comphy_usb3_power_up(comphy_map->type, + ret = comphy_usb3_power_up(lane, + comphy_map->type, comphy_map->speed, comphy_map->invert); break; diff --git a/drivers/phy/marvell/comphy_a3700.h b/drivers/phy/marvell/comphy_a3700.h index 0d7b425..07f4792 100644 --- a/drivers/phy/marvell/comphy_a3700.h +++ b/drivers/phy/marvell/comphy_a3700.h @@ -59,6 +59,7 @@ #define USB2PHY2_BASE MVEBU_REG(0x05F000) #define USB32_CTRL_BASE MVEBU_REG(0x05D800) #define USB3PHY_SHFT 2 +#define USB3PHY_LANE2_REG_BASE_OFFSET 0x200 static inline void __iomem *sgmiiphy_addr(u32 lane, u32 addr) { -- 2.7.4