[RFC,v2,3/7] net/atlantic: Add helper functions for PHY access
diff mbox series

Message ID 3df482b37f015591e4d121e859d0c412879b233c.1571928488.git.Pavel.Belous@aquantia.com
State RFC, archived
Delegated to: akhil goyal
Headers show
Series
  • RFC: Support MACSEC offload in the RTE_SECURITY infrastructure.
Related show

Checks

Context Check Description
ci/Intel-compilation fail Compilation issues
ci/checkpatch warning coding style issues

Commit Message

Pavel Belous Oct. 25, 2019, 5:53 p.m. UTC
From: Pavel Belous <Pavel.Belous@aquantia.com>

Aquantia AQC107/AQC108 ethernet controllers includes MAC and PHY part.
Some network features, like MACSec, are configured directly in the PHY part.

This patch adds helper functions for accessing PHY part via internal MDIO interface.

Signed-off-by: Pavel Belous <pavel.belous@aquantia.com>
---
 drivers/net/atlantic/Makefile      |   2 +
 drivers/net/atlantic/macsec/mdio.c | 328 +++++++++++++++++++++++++++++++++++++
 drivers/net/atlantic/macsec/mdio.h |  19 +++
 drivers/net/atlantic/meson.build   |   1 +
 4 files changed, 350 insertions(+)
 create mode 100644 drivers/net/atlantic/macsec/mdio.c
 create mode 100644 drivers/net/atlantic/macsec/mdio.h

Patch
diff mbox series

diff --git a/drivers/net/atlantic/Makefile b/drivers/net/atlantic/Makefile
index fc12e6a..6340588 100644
--- a/drivers/net/atlantic/Makefile
+++ b/drivers/net/atlantic/Makefile
@@ -21,6 +21,7 @@  LDLIBS += -lrte_ethdev -lrte_net
 LDLIBS += -lrte_bus_pci
 
 VPATH += $(SRCDIR)/hw_atl
+VPATH += $(SRCDIR)/macsec
 
 #
 # all source are stored in SRCS-y
@@ -33,5 +34,6 @@  SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_llh.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_utils_fw2x.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += hw_atl_b0.c
 SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += rte_pmd_atlantic.c
+SRCS-$(CONFIG_RTE_LIBRTE_ATLANTIC_PMD) += mdio.c
 
 include $(RTE_SDK)/mk/rte.lib.mk
diff --git a/drivers/net/atlantic/macsec/mdio.c b/drivers/net/atlantic/macsec/mdio.c
new file mode 100644
index 0000000..a662f58
--- /dev/null
+++ b/drivers/net/atlantic/macsec/mdio.c
@@ -0,0 +1,328 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Aquantia Corporation
+ */
+
+#include "errno.h"
+#include "../atl_hw_regs.h"
+#include "../atl_logs.h"
+#include "../hw_atl/hw_atl_llh.h"
+#include "../hw_atl/hw_atl_b0.h"
+#include "../hw_atl/hw_atl_b0_internal.h"
+#include "mdio.h"
+
+static inline uint32_t macValRead(uint32_t reg, uint32_t msk, uint32_t shift)
+{
+    return (reg & msk) >> shift;
+}
+
+static inline void macValWrite(uint32_t* reg, uint32_t msk, uint32_t shift, uint32_t val)
+{
+    *reg = (*reg & ~msk) | (val << shift);
+}
+
+static inline uint32_t macBitRead(uint32_t reg, uint32_t msk)
+{
+    return reg & msk;
+}
+
+static inline uint32_t regGlobalMdioInterface1Get(void *hw)
+{
+    return aq_hw_read_reg(hw, 0x280);
+}
+
+static inline void valGlobalMdioInterface1MdioClockEnableSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x00004000, 14, val);
+}
+
+static inline void regGlobalMdioInterface1Set(void *hw, uint32_t val)
+{
+    aq_hw_write_reg(hw, 0x280, val);
+}
+
+static inline void valGlobalMdioInterface4MdioAddressSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x0000FFFF, 0, val);
+}
+
+static inline void regGlobalMdioInterface4Set(void *hw, uint32_t val)
+{
+    aq_hw_write_reg(hw, 0x28C, val);
+}
+
+static inline void valGlobalMdioInterface2MdioExecuteOperationSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x00008000, 15, val);
+}
+
+static inline void valGlobalMdioInterface2MdioOpModeSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x00003000, 12, val);
+}
+
+static inline void valGlobalMdioInterface2MdioPhyAddressSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x000003FF, 0, val);
+}
+
+static inline void regGlobalMdioInterface2Set(void *hw, uint32_t val)
+{
+    aq_hw_write_reg(hw, 0x284, val);
+}
+
+static inline uint32_t regGlobalMdioInterface2Get(void *hw)
+{
+    return aq_hw_read_reg(hw, 0x284);
+}
+
+static inline void valGlobalMdioInterface3MdioWriteDataSet(uint32_t *reg, uint32_t val)
+{
+    macValWrite(reg, 0x0000FFFF, 0, val);
+}
+
+static inline void regGlobalMdioInterface3Set(void *hw, uint32_t val)
+{
+    aq_hw_write_reg(hw, 0x288, val);
+}
+
+static inline uint32_t regGlobalMdioInterface5Get(void *hw)
+{
+    return aq_hw_read_reg(hw, 0x290);
+}
+
+static inline uint32_t valGlobalMdioInterface5MdioReadDataGet(uint32_t reg)
+{
+    return macValRead(reg, 0x0000FFFF, 0);
+}
+
+static inline uint32_t bitGlobalMdioInterface2MdioBusyGet(uint32_t reg)
+{
+    return macBitRead(reg, 0x80000000);
+}
+
+
+/* Operation Mode for MDIO */
+#define MDIO_OP_NO 0 /* No Op */
+#define MDIO_OP_READ 1 /* Read Op */
+#define MDIO_OP_WRITE 2 /* Write Op */
+#define MDIO_OP_ADDR 3 /* Address Op */
+
+#define MDIO_COMMAND_TIMEOUT 100
+#define MDIO_SEMAPHORE_TIMEOUT_MS 30 /* msec. */
+
+
+/* 32 bits command + 32 bits preamble = 64 */
+#define MDIO_ONE_CMD_CLOCK_TICKS     64
+/* Wait 10 MDIO transactions */
+#define TIMEOUT_BUSY_WAIT_COUNT     ((MIPS_COUNT_HZ * MDIO_ONE_CMD_CLOCK_TICKS / MDIO_HZ) * 10)
+
+static int mdio_phy_addr = (0 << 5);
+
+
+static inline unsigned int mMdioBusyCheck(void *hw)
+{
+    return bitGlobalMdioInterface2MdioBusyGet(regGlobalMdioInterface2Get(hw));
+}
+
+static int mBusyWait(struct aq_hw_s *hw)
+{
+    unsigned i = 0;
+
+    for (i = 1000U; mMdioBusyCheck(hw) && i; i--){};
+
+    if (i == 0) {
+	PMD_DRV_LOG(ERR, "Mdio busy!!");
+	return 1;
+    }
+
+    return 0;
+}
+
+
+static inline void mSendPhyAddress(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr)
+{
+    uint32_t reg;
+
+    /* Set MDIO Address (0x28c) */
+    reg = 0;
+    valGlobalMdioInterface4MdioAddressSet(&reg, addr);
+    regGlobalMdioInterface4Set(hw, reg);
+
+    /* Set MDIO Address Operation and PHY Address (0x284) */
+    reg = 0;
+    valGlobalMdioInterface2MdioExecuteOperationSet(&reg, 1);
+    valGlobalMdioInterface2MdioOpModeSet(&reg, MDIO_OP_ADDR);
+    valGlobalMdioInterface2MdioPhyAddressSet(&reg, mdio_phy_addr | mmd);
+    regGlobalMdioInterface2Set(hw, reg);
+}
+
+static void mSendDummyWriteCmd(struct aq_hw_s *hw)
+{
+    uint32_t reg;
+
+    // Set data (0x288)
+    reg = 0;
+    valGlobalMdioInterface3MdioWriteDataSet(&reg, 0);
+    regGlobalMdioInterface3Set(hw, reg);
+
+    // Write operation (0x284)
+    reg = 0;
+    valGlobalMdioInterface2MdioExecuteOperationSet(&reg, 1);
+    valGlobalMdioInterface2MdioOpModeSet(&reg, MDIO_OP_WRITE);
+    valGlobalMdioInterface2MdioPhyAddressSet(&reg, 0);
+    regGlobalMdioInterface2Set(hw, reg);
+}
+
+static inline void mSendReadCmd(struct aq_hw_s *hw, unsigned int mmd)
+{
+    uint32_t reg;
+
+    // Execute Read Operation (0x284)
+    reg = 0;
+    valGlobalMdioInterface2MdioExecuteOperationSet(&reg, 1);
+    valGlobalMdioInterface2MdioOpModeSet(&reg, MDIO_OP_READ);
+    valGlobalMdioInterface2MdioPhyAddressSet(&reg, mdio_phy_addr | mmd);
+    regGlobalMdioInterface2Set(hw, reg);
+}
+
+static inline void mSendWriteCmd(struct aq_hw_s *hw, unsigned int mmd)
+{
+    uint32_t reg;
+
+    // Execute Read Operation (0x284)
+    reg = 0;
+    valGlobalMdioInterface2MdioExecuteOperationSet(&reg, 1);
+    valGlobalMdioInterface2MdioOpModeSet(&reg, MDIO_OP_WRITE);
+    valGlobalMdioInterface2MdioPhyAddressSet(&reg, mdio_phy_addr | mmd);
+    regGlobalMdioInterface2Set(hw, reg);
+}
+
+static inline unsigned short int mReadData(struct aq_hw_s *hw)
+{
+    // Register 0x290
+    return valGlobalMdioInterface5MdioReadDataGet(regGlobalMdioInterface5Get(hw));
+}
+
+static inline void mWriteData(struct aq_hw_s *hw, unsigned short int val)
+{
+    uint32_t reg;
+
+    // Register 0x288
+    reg = 0;
+    valGlobalMdioInterface3MdioWriteDataSet(&reg, val);
+    regGlobalMdioInterface3Set(hw, reg);
+}
+
+
+static int __mdioRead(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int* data)
+{
+    int ret = -1;
+
+    /* Execute Address Operation */
+    if (mBusyWait(hw))
+        goto _exit;
+    mSendPhyAddress(hw, mmd, addr);
+
+    /* Dummy write transaction */
+    if (mBusyWait(hw))
+        goto _exit;
+    mSendDummyWriteCmd(hw);
+
+    /* Read command */
+    if (mBusyWait(hw))
+        goto _exit;
+    mSendReadCmd(hw, mmd);
+
+    /* Read MDIO Data */
+    if (mBusyWait(hw))
+        goto _exit;
+    *data = mReadData(hw);
+
+    ret = 0;
+
+_exit:
+    return ret;
+}
+
+static
+int __mdioWrite(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int data)
+{
+    int ret = -1;
+
+    /* Execute Address Operation */
+    if (mBusyWait(hw))
+        goto _exit;
+    mSendPhyAddress(hw, mmd, addr);
+
+    /* Dummy write transaction */
+    if (mBusyWait(hw))
+        goto _exit;
+    mSendDummyWriteCmd(hw);
+
+    /* Write command */
+    if (mBusyWait(hw))
+        goto _exit;
+    mWriteData(hw, data);
+    mSendWriteCmd(hw, mmd);
+
+    /* Expect completion of the operation */
+    if (mBusyWait(hw))
+        goto _exit;
+
+    ret = 0;
+
+_exit:
+    return ret;
+}
+
+int mdioRead(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int* data)
+{
+    uint32_t reg;
+    int ret;
+
+    // Send Dummy Transaction
+    if (mBusyWait(hw))
+        return -1;
+    mSendDummyWriteCmd(hw);
+
+    // Enable MDIO Clock (active low) (0x280)
+    reg = regGlobalMdioInterface1Get(hw);
+    valGlobalMdioInterface1MdioClockEnableSet(&reg, 0);
+    regGlobalMdioInterface1Set(hw, reg);
+
+    ret = __mdioRead(hw, mmd, addr, data);
+
+    // Disable MDIO Clock (0x280)
+    reg = regGlobalMdioInterface1Get(hw);
+    valGlobalMdioInterface1MdioClockEnableSet(&reg, 1);
+    regGlobalMdioInterface1Set(hw, reg);
+
+    return ret;
+}
+
+int mdioWrite(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int data)
+{
+    uint32_t reg;
+    int ret;
+
+    // Send Dummy Transaction
+    if (mBusyWait(hw))
+        return -1;
+    mSendDummyWriteCmd(hw);
+
+    // Enable MDIO Clock (active low) (0x280)
+    reg = regGlobalMdioInterface1Get(hw);
+    valGlobalMdioInterface1MdioClockEnableSet(&reg, 0);
+    regGlobalMdioInterface1Set(hw, reg);
+
+    ret = __mdioWrite(hw, mmd, addr, data);
+
+    // Disable MDIO Clock (0x280)
+    reg = regGlobalMdioInterface1Get(hw);
+    valGlobalMdioInterface1MdioClockEnableSet(&reg, 1);
+    regGlobalMdioInterface1Set(hw, reg);
+
+    return ret;
+}
+
+
diff --git a/drivers/net/atlantic/macsec/mdio.h b/drivers/net/atlantic/macsec/mdio.h
new file mode 100644
index 0000000..907f04f
--- /dev/null
+++ b/drivers/net/atlantic/macsec/mdio.h
@@ -0,0 +1,19 @@ 
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(c) 2018 Aquantia Corporation
+ */
+
+#ifndef __MDIO_HH__
+#define __MDIO_HH__
+
+
+#include "../atl_types.h"
+#include "../hw_atl/hw_atl_utils.h"
+
+
+#define MMD_GLOBAL 0x1E
+
+
+int mdioRead(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int* data);
+int mdioWrite(struct aq_hw_s *hw, unsigned int mmd, unsigned int addr, unsigned short int data);
+
+#endif
diff --git a/drivers/net/atlantic/meson.build b/drivers/net/atlantic/meson.build
index 919d741..d1c66f4 100644
--- a/drivers/net/atlantic/meson.build
+++ b/drivers/net/atlantic/meson.build
@@ -12,4 +12,5 @@  sources = files(
 	'hw_atl/hw_atl_utils_fw2x.c',
 	'hw_atl/hw_atl_utils.c',
 	'rte_pmd_atlantic.c',
+	'macsec/mdio.c',
 )