Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 26 Jan 2016 15:22:04 +0000 (UTC)
From:      Zbigniew Bodek <zbb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r294838 - in head/sys/contrib/alpine-hal: . eth
Message-ID:  <201601261522.u0QFM4IN062671@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: zbb
Date: Tue Jan 26 15:22:04 2016
New Revision: 294838
URL: https://svnweb.freebsd.org/changeset/base/294838

Log:
  Import Annapurna Labs Alpine HAL for networking
  
  Files required for the NIC driver
  
  Import from vendor-sys/alpine-hal/2.7
  SVN rev.: 294828
  HAL version: 2.7
  
  Obtained from:  Semihalf
  Sponsored by:   Annapurna Labs

Added:
  head/sys/contrib/alpine-hal/al_hal_iofic.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_serdes.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_serdes.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_serdes_internal_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_serdes_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_config.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_config.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_debug.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_debug.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_iofic.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_iofic.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_iofic_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_main.c   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_regs_gen.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_regs_m2s.h   (contents, props changed)
  head/sys/contrib/alpine-hal/al_hal_udma_regs_s2m.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/
  head/sys/contrib/alpine-hal/eth/al_hal_an_lt_wrapper_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_alu.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_ec_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_kr.c   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_kr.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_mac_regs.h   (contents, props changed)
  head/sys/contrib/alpine-hal/eth/al_hal_eth_main.c   (contents, props changed)

Added: head/sys/contrib/alpine-hal/al_hal_iofic.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/contrib/alpine-hal/al_hal_iofic.c	Tue Jan 26 15:22:04 2016	(r294838)
@@ -0,0 +1,291 @@
+/*-
+*******************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+/**
+ *  @{
+ * @file   al_hal_iofic.c
+ *
+ * @brief  interrupt controller hal
+ *
+ */
+
+#include "al_hal_iofic.h"
+#include "al_hal_iofic_regs.h"
+
+/*
+ * configure the interrupt registers, interrupts will are kept masked
+ */
+int al_iofic_config(void __iomem *regs_base, int group, uint32_t flags)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	al_reg_write32(&regs->ctrl[group].int_control_grp, flags);
+
+	return 0;
+}
+
+/*
+ * configure the moderation timer resolution for a given group
+ */
+int al_iofic_moder_res_config(void __iomem *regs_base, int group,
+			     uint8_t resolution)
+
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
+	AL_REG_FIELD_SET(reg,
+			 INT_CONTROL_GRP_MOD_RES_MASK,
+			 INT_CONTROL_GRP_MOD_RES_SHIFT,
+			 resolution);
+	al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
+
+	return 0;
+}
+
+/*
+ * configure the moderation timer interval for a given legacy interrupt group
+ */
+int al_iofic_legacy_moder_interval_config(void __iomem *regs_base, int group,
+				     uint8_t interval)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
+	AL_REG_FIELD_SET(reg,
+			 INT_CONTROL_GRP_MOD_INTV_MASK,
+			 INT_CONTROL_GRP_MOD_INTV_SHIFT,
+			 interval);
+	al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
+
+	return 0;
+}
+
+
+/*
+ * configure the moderation timer interval for a given msix vector.
+ */
+int al_iofic_msix_moder_interval_config(void __iomem *regs_base, int group,
+				       uint8_t vector, uint8_t interval)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	reg = al_reg_read32(&regs->grp_int_mod[group][vector].grp_int_mod_reg);
+	AL_REG_FIELD_SET(reg,
+			 INT_MOD_INTV_MASK,
+			 INT_MOD_INTV_SHIFT,
+			 interval);
+	al_reg_write32(&regs->grp_int_mod[group][vector].grp_int_mod_reg, reg);
+
+	return 0;
+}
+
+/*
+ * configure the vmid attributes for a given msix vector.
+ */
+int al_iofic_msix_vmid_attributes_config(void __iomem *regs_base, int group,
+				       uint8_t vector, uint32_t vmid, uint8_t vmid_en)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg = 0;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	AL_REG_FIELD_SET(reg,
+			 INT_MSIX_VMID_MASK,
+			 INT_MSIX_VMID_SHIFT,
+			 vmid);
+	AL_REG_BIT_VAL_SET(reg,
+			 INT_MSIX_VMID_EN_SHIFT,
+			 vmid_en);
+
+	al_reg_write32(&regs->grp_int_mod[group][vector].grp_int_vmid_reg, reg);
+
+	return 0;
+}
+
+/*
+ * return the offset of the unmask register for a given group
+ */
+uint32_t __iomem * al_iofic_unmask_offset_get(void __iomem *regs_base, int group)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	return &regs->ctrl[group].int_mask_clear_grp;
+}
+
+
+/*
+ * unmask specific interrupts for a given group
+ */
+void al_iofic_unmask(void __iomem *regs_base, int group, uint32_t mask)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	/*
+	 * use the mask clear register, no need to read the mask register
+	 * itself. write 0 to unmask, 1 has no effect
+	 */
+	al_reg_write32_relaxed(&regs->ctrl[group].int_mask_clear_grp, ~mask);
+}
+
+/*
+ * mask specific interrupts for a given group
+ */
+void al_iofic_mask(void __iomem *regs_base, int group, uint32_t mask)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	reg = al_reg_read32(&regs->ctrl[group].int_mask_grp);
+
+	al_reg_write32(&regs->ctrl[group].int_mask_grp, reg | mask);
+}
+
+/*
+ * read the mask for a given group
+ */
+uint32_t al_iofic_read_mask(void __iomem *regs_base, int group)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	return al_reg_read32(&regs->ctrl[group].int_mask_grp);
+}
+
+/*
+ * read interrupt cause register for a given group
+ */
+uint32_t al_iofic_read_cause(void __iomem *regs_base, int group)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	return al_reg_read32(&regs->ctrl[group].int_cause_grp);
+}
+
+/*
+ * clear bits in the interrupt cause register for a given group
+ */
+void al_iofic_clear_cause(void __iomem *regs_base, int group, uint32_t mask)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	/* inverse mask, writing 1 has no effect */
+	al_reg_write32(&regs->ctrl[group].int_cause_grp, ~mask);
+}
+
+/*
+ * Set the cause register for a given group
+ */
+void al_iofic_set_cause(void __iomem *regs_base, int group, uint32_t mask)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	al_reg_write32(&regs->ctrl[group].int_cause_set_grp, mask);
+}
+
+
+/*
+ * unmask specific interrupts from aborting the udma a given group
+ */
+void al_iofic_abort_mask(void __iomem *regs_base, int group, uint32_t mask)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	al_reg_write32(&regs->ctrl[group].int_abort_msk_grp, mask);
+
+}
+
+/*
+ * trigger all interrupts that are waiting for moderation timers to expire
+ */
+void al_iofic_interrupt_moderation_reset(void __iomem *regs_base, int group)
+{
+	struct al_iofic_regs __iomem *regs = (struct al_iofic_regs __iomem *)(regs_base);
+	uint32_t reg = 0;
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	al_assert(regs_base);
+	al_assert(group < AL_IOFIC_MAX_GROUPS);
+
+	reg = al_reg_read32(&regs->ctrl[group].int_control_grp);
+	reg |= INT_CONTROL_GRP_MOD_RST;
+
+	al_reg_write32(&regs->ctrl[group].int_control_grp, reg);
+}
+
+/** @} end of interrupt controller group */

Added: head/sys/contrib/alpine-hal/al_hal_serdes.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/sys/contrib/alpine-hal/al_hal_serdes.c	Tue Jan 26 15:22:04 2016	(r294838)
@@ -0,0 +1,3228 @@
+/*-
+*******************************************************************************
+Copyright (C) 2015 Annapurna Labs Ltd.
+
+This file may be licensed under the terms of the Annapurna Labs Commercial
+License Agreement.
+
+Alternatively, this file can be distributed under the terms of the GNU General
+Public License V2 as published by the Free Software Foundation and can be
+found at http://www.gnu.org/licenses/gpl-2.0.html
+
+Alternatively, redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following conditions are
+met:
+
+    *     Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+    *     Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in
+the documentation and/or other materials provided with the
+distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+*******************************************************************************/
+
+#include "al_hal_serdes.h"
+#include "al_hal_serdes_regs.h"
+#include "al_hal_serdes_internal_regs.h"
+
+#define SRDS_CORE_REG_ADDR(page, type, offset)\
+	(((page) << 13) | ((type) << 12) | (offset))
+
+/* Link Training configuration */
+#define AL_SERDES_TX_DEEMPH_SUM_MAX		0x1b
+
+/* c configurations */
+#define AL_SERDES_TX_DEEMPH_C_ZERO_MAX_VAL	0x1b
+#define AL_SERDES_TX_DEEMPH_C_ZERO_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_ZERO_PRESET	AL_SERDES_TX_DEEMPH_C_ZERO_MAX_VAL
+
+/* c(+1) configurations */
+#define AL_SERDES_TX_DEEMPH_C_PLUS_MAX_VAL	0x9
+#define AL_SERDES_TX_DEEMPH_C_PLUS_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_PLUS_PRESET	AL_SERDES_TX_DEEMPH_C_PLUS_MIN_VAL
+
+/* c(-1) configurations */
+#define AL_SERDES_TX_DEEMPH_C_MINUS_MAX_VAL	0x6
+#define AL_SERDES_TX_DEEMPH_C_MINUS_MIN_VAL	0
+#define AL_SERDES_TX_DEEMPH_C_MINUS_PRESET	AL_SERDES_TX_DEEMPH_C_MINUS_MIN_VAL
+
+/* Rx equal total delay = MDELAY * TRIES */
+#define AL_SERDES_RX_EQUAL_MDELAY		10
+#define AL_SERDES_RX_EQUAL_TRIES		50
+
+/* Rx eye calculation delay = MDELAY * TRIES */
+#define AL_SERDES_RX_EYE_CAL_MDELAY		50
+#define AL_SERDES_RX_EYE_CAL_TRIES		70
+
+
+/**
+ * Prototypes for _lane_ compatibility
+ */
+int al_serdes_lane_read(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			*data);
+
+int al_serdes_lane_write(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			data);
+
+
+/**
+ * SERDES core reg/lane read
+ */
+static inline uint8_t al_serdes_grp_reg_read(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset);
+
+static inline uint8_t al_serdes_grp_lane_read(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_lane		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset);
+
+/**
+ * SERDES core reg/lane write
+ */
+static inline void al_serdes_grp_reg_write(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				data);
+
+static inline void al_serdes_grp_lane_write(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_lane		lane,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				data);
+
+/**
+ * SERDES core masked reg/lane write
+ */
+static inline void al_serdes_grp_reg_masked_write(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_reg_page		page,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				mask,
+	uint8_t				data);
+
+/**
+ * Lane Rx rate change software flow disable
+ */
+static void _al_serdes_lane_rx_rate_change_sw_flow_dis(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_lane		lane);
+
+/**
+ * Group Rx rate change software flow enable if all conditions met
+ */
+static void al_serdes_group_rx_rate_change_sw_flow_dis(
+	struct al_serdes_group_info	*grp_info);
+
+/**
+ * Lane Rx rate change software flow enable if all conditions met
+ */
+static void _al_serdes_lane_rx_rate_change_sw_flow_en_cond(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_lane		lane);
+
+/**
+ * Group Rx rate change software flow enable if all conditions met
+ */
+static void al_serdes_group_rx_rate_change_sw_flow_en_cond(
+	struct al_serdes_group_info	*grp_info);
+
+
+static inline void al_serdes_grp_lane_masked_write(
+	struct al_serdes_group_info	*grp_info,
+	enum al_serdes_lane		lane,
+	enum al_serdes_reg_type		type,
+	uint16_t			offset,
+	uint8_t				mask,
+	uint8_t				data);
+
+/******************************************************************************/
+/******************************************************************************/
+int al_serdes_handle_init(
+	void __iomem			*serdes_regs_base,
+	struct al_serdes_obj		*obj)
+{
+	int i;
+
+	al_dbg(
+		"%s(%p, %p)\n",
+		__func__,
+		serdes_regs_base,
+		obj);
+
+	al_assert(serdes_regs_base);
+
+	for (i = 0; i < AL_SRDS_NUM_GROUPS; i++) {
+		obj->grp_info[i].pobj = obj;
+
+		obj->grp_info[i].regs_base =
+			&((struct al_serdes_regs *)serdes_regs_base)[i];
+	}
+
+	return 0;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+int al_serdes_reg_read(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_reg_page	page,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			*data)
+{
+	int status = 0;
+
+	al_dbg(
+		"%s(%p, %d, %d, %d, %u)\n",
+		__func__,
+		obj,
+		grp,
+		page,
+		type,
+		offset);
+
+	al_assert(obj);
+	al_assert(data);
+	al_assert(((int)grp) >= AL_SRDS_GRP_A);
+	al_assert(((int)grp) <= AL_SRDS_GRP_D);
+	al_assert(((int)page) >= AL_SRDS_REG_PAGE_0_LANE_0);
+	al_assert(((int)page) <= AL_SRDS_REG_PAGE_4_COMMON);
+	al_assert(((int)type) >= AL_SRDS_REG_TYPE_PMA);
+	al_assert(((int)type) <= AL_SRDS_REG_TYPE_PCS);
+
+	*data = al_serdes_grp_reg_read(
+		&obj->grp_info[grp],
+		page,
+		type,
+		offset);
+
+	al_dbg(
+		"%s: return(%u)\n",
+		__func__,
+		*data);
+
+	return status;
+}
+
+int al_serdes_lane_read(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			*data)
+{
+	return al_serdes_reg_read(obj, grp, (enum al_serdes_reg_page)lane, type,
+				  offset, data);
+}
+/******************************************************************************/
+/******************************************************************************/
+int al_serdes_reg_write(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_reg_page	page,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			data)
+{
+	int status = 0;
+
+	al_dbg(
+		"%s(%p, %d, %d, %d, %u, %u)\n",
+		__func__,
+		obj,
+		grp,
+		page,
+		type,
+		offset,
+		data);
+
+	al_assert(obj);
+	al_assert(((int)grp) >= AL_SRDS_GRP_A);
+	al_assert(((int)grp) <= AL_SRDS_GRP_D);
+	al_assert(((int)page) >= AL_SRDS_REG_PAGE_0_LANE_0);
+	al_assert(((int)page) <= AL_SRDS_REG_PAGE_0123_LANES_0123);
+	al_assert(((int)type) >= AL_SRDS_REG_TYPE_PMA);
+	al_assert(((int)type) <= AL_SRDS_REG_TYPE_PCS);
+
+	al_serdes_grp_reg_write(
+		&obj->grp_info[grp],
+		page,
+		type,
+		offset,
+		data);
+
+	return status;
+}
+
+int al_serdes_lane_write(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane,
+	enum al_serdes_reg_type	type,
+	uint16_t		offset,
+	uint8_t			data)
+{
+	return al_serdes_reg_write(obj, grp, (enum al_serdes_reg_page)lane,
+				   type, offset, data);
+}
+/******************************************************************************/
+/******************************************************************************/
+#if (SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM != SERDES_IREG_FLD_PCSTX_DATAWIDTH_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM != SERDES_IREG_FLD_PCSTX_DIVRATE_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCS_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCSBIST_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM != SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_LB_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRX_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRXBIST_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSRXEQ_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+#if (SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM != SERDES_IREG_FLD_PCSTX_LOCWREN_REG_NUM)
+#error "Wrong assumption!"
+#endif
+void al_serdes_bist_overrides_enable(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_rate	rate)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+	int i;
+
+	uint8_t rx_rate_val;
+	uint8_t tx_rate_val;
+
+	switch (rate) {
+	case AL_SRDS_RATE_1_8:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_8;
+		break;
+	case AL_SRDS_RATE_1_4:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_4;
+		break;
+	case AL_SRDS_RATE_1_2:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_2;
+		break;
+	case AL_SRDS_RATE_FULL:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1;
+		break;
+	default:
+		al_err("%s: invalid rate (%d)\n",  __func__, rate);
+		al_assert(0);
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		tx_rate_val = SERDES_IREG_FLD_PCSTX_DIVRATE_VAL_1_1;
+	}
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_REG_NUM,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_MASK |
+			SERDES_IREG_FLD_PCSTX_DATAWIDTH_MASK,
+			SERDES_IREG_FLD_PCSRX_DATAWIDTH_VAL_20 |
+			SERDES_IREG_FLD_PCSTX_DATAWIDTH_VAL_20);
+
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM,
+			SERDES_IREG_FLD_PCSRX_DIVRATE_MASK |
+			SERDES_IREG_FLD_PCSTX_DIVRATE_MASK,
+			rx_rate_val | tx_rate_val);
+	}
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN |
+		SERDES_IREG_FLD_CMNPCS_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN |
+		SERDES_IREG_FLD_CMNPCS_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN |
+		SERDES_IREG_FLD_CMNPCSPSTATE_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_PCS_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_PCS_LOCWREN,
+		0);
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE_REG_NUM,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE,
+		SERDES_IREG_FLD_CMNPCS_TXENABLE);
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN |
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRX_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN |
+			SERDES_IREG_FLD_PCSRXEQ_LOCWREN |
+			SERDES_IREG_FLD_PCSTX_LOCWREN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN_REG_NUM,
+			SERDES_IREG_FLD_TX_DRV_OVERRIDE_EN,
+			0);
+
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN_REG_NUM,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN,
+			SERDES_IREG_FLD_RXLOCK2REF_OVREN);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_bist_overrides_disable(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+	int i;
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCIEGEN3_LOCWREN_REG_NUM,
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN,
+		SERDES_IREG_FLD_CMNPCSBIST_LOCWREN);
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_LANEPCSPSTATE_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN,
+			SERDES_IREG_FLD_LB_LOCWREN |
+			SERDES_IREG_FLD_PCSRXBIST_LOCWREN);
+
+		al_serdes_grp_reg_masked_write(
+			grp_info,
+			(enum al_serdes_reg_page)i,
+			AL_SRDS_REG_TYPE_PMA,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN_REG_NUM,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN,
+			SERDES_IREG_FLD_PCSTXBIST_LOCWREN);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_rx_rate_change(
+	struct al_serdes_obj *obj,
+	enum al_serdes_group grp,
+	enum al_serdes_rate rate)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+	int i;
+
+	uint8_t rx_rate_val;
+
+	switch (rate) {
+	case AL_SRDS_RATE_1_8:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_8;
+		break;
+	case AL_SRDS_RATE_1_4:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_4;
+		break;
+	case AL_SRDS_RATE_1_2:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_2;
+		break;
+	case AL_SRDS_RATE_FULL:
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		break;
+	default:
+		al_err("%s: invalid rate (%d)\n",  __func__, rate);
+		rx_rate_val = SERDES_IREG_FLD_PCSRX_DIVRATE_VAL_1_1;
+		break;
+	}
+
+	for (i = 0; i < AL_SRDS_NUM_LANES; i++) {
+		al_serdes_grp_reg_masked_write(
+				   grp_info,
+				   (enum al_serdes_reg_page)i,
+				   AL_SRDS_REG_TYPE_PMA,
+				   SERDES_IREG_FLD_PCSRX_DIVRATE_REG_NUM,
+				   SERDES_IREG_FLD_PCSRX_DIVRATE_MASK,
+				   rx_rate_val);
+	}
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_group_pm_set(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_pm	pm)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+
+	uint8_t pm_val;
+
+	switch (pm) {
+	case AL_SRDS_PM_PD:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_PD;
+		break;
+	case AL_SRDS_PM_P2:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P2;
+		break;
+	case AL_SRDS_PM_P1:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P1;
+		break;
+	case AL_SRDS_PM_P0S:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0S;
+		break;
+	case AL_SRDS_PM_P0:
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0;
+		break;
+	default:
+		al_err("%s: invalid power mode (%d)\n",  __func__, pm);
+		al_assert(0);
+		pm_val = SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_VAL_P0;
+	}
+
+	if (pm == AL_SRDS_PM_PD)
+		al_serdes_group_rx_rate_change_sw_flow_dis(grp_info);
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		AL_SRDS_REG_PAGE_4_COMMON,
+		AL_SRDS_REG_TYPE_PMA,
+		SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_REG_NUM,
+		SERDES_IREG_FLD_CMNPCSPSTATE_SYNTH_MASK,
+		pm_val);
+
+	if (pm != AL_SRDS_PM_PD)
+		al_serdes_group_rx_rate_change_sw_flow_en_cond(grp_info);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_lane_rx_rate_change_sw_flow_en(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane)
+{
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 201, 0xfc);
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 202, 0xff);
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 203, 0xff);
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 204, 0xff);
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f);
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0xff);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_lane_rx_rate_change_sw_flow_dis(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane)
+{
+	al_serdes_lane_write(obj, grp, lane, AL_SRDS_REG_TYPE_PMA, 205, 0x7f);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_lane_pcie_rate_override_enable_set(
+	struct al_serdes_obj		*obj,
+	enum al_serdes_group		grp,
+	enum al_serdes_lane		lane,
+	al_bool				en)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA,
+		en ? SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA : 0);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+al_bool al_serdes_lane_pcie_rate_override_is_enabled(
+	struct al_serdes_obj		*obj,
+	enum al_serdes_group		grp,
+	enum al_serdes_lane		lane)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+
+	return (al_serdes_grp_lane_read(
+		grp_info,
+		lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA_REG_NUM) &
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_ENA) ? AL_TRUE : AL_FALSE;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+enum al_serdes_pcie_rate al_serdes_lane_pcie_rate_get(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+
+	return (al_serdes_grp_reg_read(
+		grp_info,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM) &
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK) >>
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_lane_pcie_rate_set(
+	struct al_serdes_obj		*obj,
+	enum al_serdes_group		grp,
+	enum al_serdes_lane		lane,
+	enum al_serdes_pcie_rate	rate)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+
+	al_serdes_grp_reg_masked_write(
+		grp_info,
+		(enum al_serdes_reg_page)lane,
+		AL_SRDS_REG_TYPE_PCS,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_REG_NUM,
+		SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_MASK,
+		rate << SERDES_IREG_FLD_PCS_VPCSIF_OVR_RATE_SHIFT);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+void al_serdes_lane_pm_set(
+	struct al_serdes_obj	*obj,
+	enum al_serdes_group	grp,
+	enum al_serdes_lane	lane,
+	enum al_serdes_pm	rx_pm,
+	enum al_serdes_pm	tx_pm)
+{
+	struct al_serdes_group_info *grp_info = &obj->grp_info[grp];
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201601261522.u0QFM4IN062671>