diff options
author | Marek BehĂșn <marek.behun@nic.cz> | 2019-11-05 15:21:54 +0100 |
---|---|---|
committer | Marek Behun <marek.behun@nic.cz> | 2019-12-11 14:25:09 +0000 |
commit | 629dd61f1922231047fc62afc06f75e1d109e19e (patch) | |
tree | 77fb8b905cd451e84646149a080b7a8f699afe3a /drivers | |
parent | b662232d189af5289c8810c628da1640b70ae352 (diff) | |
download | trusted-firmware-a-629dd61f1922231047fc62afc06f75e1d109e19e.tar.gz |
drivers: marvell: comphy-a3700: support SGMII COMPHY power off
Add support for powering off the SGMII COMPHY (on lanes 0 and 1).
This is needed sometimes on Turris Mox when using KEXEC.
There is also another benefit of a little energy saving when the given
network interface is down.
Signed-off-by: Marek BehĂșn <marek.behun@nic.cz>
Change-Id: I55ae0fe3627e7cc0f65c78a00771939d8bf5399f
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/marvell/comphy/phy-comphy-3700.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/drivers/marvell/comphy/phy-comphy-3700.c b/drivers/marvell/comphy/phy-comphy-3700.c index fa5183bc5f..f6a40a587f 100644 --- a/drivers/marvell/comphy/phy-comphy-3700.c +++ b/drivers/marvell/comphy/phy-comphy-3700.c @@ -195,6 +195,45 @@ error: ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); } +/* + * This is something like the inverse of the previous function: for given + * lane it returns COMPHY_*_MODE. + * + * It is useful when powering the phy off. + * + * This function returns COMPHY_USB3_MODE even if the phy was configured + * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization + * code does not differentiate between these modes.) + * Also it returns COMPHY_SGMII_MODE even if the phy was configures with + * COMPHY_HS_SGMII_MODE. (The sgmii phy initialization code does differentiate + * between these modes, but it is irrelevant when powering the phy off.) + */ +static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index) +{ + uint32_t reg; + + reg = mmio_read_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG); + switch (comphy_index) { + case COMPHY_LANE0: + if ((reg & COMPHY_SELECTOR_USB3_GBE1_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE1: + if ((reg & COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT) != 0) + return COMPHY_PCIE_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE2: + if ((reg & COMPHY_SELECTOR_USB3_PHY_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SATA_MODE; + } + + return COMPHY_UNUSED; +} + /* It is only used for SATA and USB3 on comphy lane2. */ static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data, uint16_t mask, int mode) @@ -547,6 +586,23 @@ static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, return ret; } +static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index) +{ + int ret = 0; + uint32_t mask, data, offset; + + debug_enter(); + + data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT; + mask = 0; + offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index); + reg_set(offset, data, mask); + + debug_exit(); + + return ret; +} + static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, uint32_t comphy_mode) { @@ -908,7 +964,20 @@ int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode) debug_enter(); + if (!mode) { + /* + * The user did not specify which mode should be powered off. + * In this case we can identify this by reading the phy selector + * register. + */ + mode = mvebu_a3700_comphy_get_mode(comphy_index); + } + switch (mode) { + case(COMPHY_SGMII_MODE): + case(COMPHY_HS_SGMII_MODE): + err = mvebu_a3700_comphy_sgmii_power_off(comphy_index); + break; case (COMPHY_USB3_MODE): case (COMPHY_USB3H_MODE): err = mvebu_a3700_comphy_usb3_power_off(); |