173 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Atlantic Network Driver3 *4 * Copyright (C) 2018-2019 aQuantia Corporation5 * Copyright (C) 2019-2020 Marvell International Ltd.6 */7 8#include "aq_phy.h"9 10#define HW_ATL_PTP_DISABLE_MSK BIT(10)11 12bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw)13{14 int err = 0;15 u32 val;16 17 err = readx_poll_timeout_atomic(hw_atl_mdio_busy_get, aq_hw,18 val, val == 0U, 10U, 100000U);19 20 if (err < 0)21 return false;22 23 return true;24}25 26u16 aq_mdio_read_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr)27{28 u16 phy_addr = aq_hw->phy_id << 5 | mmd;29 30 /* Set Address register. */31 hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<32 HW_ATL_MDIO_ADDRESS_SHIFT);33 /* Send Address command. */34 hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |35 (3 << HW_ATL_MDIO_OP_MODE_SHIFT) |36 ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<37 HW_ATL_MDIO_PHY_ADDRESS_SHIFT));38 39 aq_mdio_busy_wait(aq_hw);40 41 /* Send Read command. */42 hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |43 (1 << HW_ATL_MDIO_OP_MODE_SHIFT) |44 ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<45 HW_ATL_MDIO_PHY_ADDRESS_SHIFT));46 /* Read result. */47 aq_mdio_busy_wait(aq_hw);48 49 return (u16)hw_atl_glb_mdio_iface5_get(aq_hw);50}51 52void aq_mdio_write_word(struct aq_hw_s *aq_hw, u16 mmd, u16 addr, u16 data)53{54 u16 phy_addr = aq_hw->phy_id << 5 | mmd;55 56 /* Set Address register. */57 hw_atl_glb_mdio_iface4_set(aq_hw, (addr & HW_ATL_MDIO_ADDRESS_MSK) <<58 HW_ATL_MDIO_ADDRESS_SHIFT);59 /* Send Address command. */60 hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |61 (3 << HW_ATL_MDIO_OP_MODE_SHIFT) |62 ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<63 HW_ATL_MDIO_PHY_ADDRESS_SHIFT));64 65 aq_mdio_busy_wait(aq_hw);66 67 hw_atl_glb_mdio_iface3_set(aq_hw, (data & HW_ATL_MDIO_WRITE_DATA_MSK) <<68 HW_ATL_MDIO_WRITE_DATA_SHIFT);69 /* Send Write command. */70 hw_atl_glb_mdio_iface2_set(aq_hw, HW_ATL_MDIO_EXECUTE_OPERATION_MSK |71 (2 << HW_ATL_MDIO_OP_MODE_SHIFT) |72 ((phy_addr & HW_ATL_MDIO_PHY_ADDRESS_MSK) <<73 HW_ATL_MDIO_PHY_ADDRESS_SHIFT));74 75 aq_mdio_busy_wait(aq_hw);76}77 78u16 aq_phy_read_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address)79{80 int err = 0;81 u32 val;82 83 err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,84 val, val == 1U, 10U, 100000U);85 86 if (err < 0) {87 err = 0xffff;88 goto err_exit;89 }90 91 err = aq_mdio_read_word(aq_hw, mmd, address);92 93 hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);94 95err_exit:96 return err;97}98 99void aq_phy_write_reg(struct aq_hw_s *aq_hw, u16 mmd, u16 address, u16 data)100{101 int err = 0;102 u32 val;103 104 err = readx_poll_timeout_atomic(hw_atl_sem_mdio_get, aq_hw,105 val, val == 1U, 10U, 100000U);106 if (err < 0)107 return;108 109 aq_mdio_write_word(aq_hw, mmd, address, data);110 hw_atl_reg_glb_cpu_sem_set(aq_hw, 1U, HW_ATL_FW_SM_MDIO);111}112 113bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw)114{115 u16 val;116 117 for (aq_hw->phy_id = 0; aq_hw->phy_id < HW_ATL_PHY_ID_MAX;118 ++aq_hw->phy_id) {119 /* PMA Standard Device Identifier 2: Address 1.3 */120 val = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);121 122 if (val != 0xffff)123 return true;124 }125 126 return false;127}128 129bool aq_phy_init(struct aq_hw_s *aq_hw)130{131 u32 dev_id;132 133 if (aq_hw->phy_id == HW_ATL_PHY_ID_MAX)134 if (!aq_phy_init_phy_id(aq_hw))135 return false;136 137 /* PMA Standard Device Identifier:138 * Address 1.2 = MSW,139 * Address 1.3 = LSW140 */141 dev_id = aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 2);142 dev_id <<= 16;143 dev_id |= aq_phy_read_reg(aq_hw, MDIO_MMD_PMAPMD, 3);144 145 if (dev_id == 0xffffffff) {146 aq_hw->phy_id = HW_ATL_PHY_ID_MAX;147 return false;148 }149 150 return true;151}152 153void aq_phy_disable_ptp(struct aq_hw_s *aq_hw)154{155 static const u16 ptp_registers[] = {156 0x031e,157 0x031d,158 0x031c,159 0x031b,160 };161 u16 val;162 int i;163 164 for (i = 0; i < ARRAY_SIZE(ptp_registers); i++) {165 val = aq_phy_read_reg(aq_hw, MDIO_MMD_VEND1,166 ptp_registers[i]);167 168 aq_phy_write_reg(aq_hw, MDIO_MMD_VEND1,169 ptp_registers[i],170 val & ~HW_ATL_PTP_DISABLE_MSK);171 }172}173