summaryrefslogtreecommitdiff
path: root/usr/src/uts/sun4u/io/px/px_hlib.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/sun4u/io/px/px_hlib.c')
-rw-r--r--usr/src/uts/sun4u/io/px/px_hlib.c2705
1 files changed, 2705 insertions, 0 deletions
diff --git a/usr/src/uts/sun4u/io/px/px_hlib.c b/usr/src/uts/sun4u/io/px/px_hlib.c
new file mode 100644
index 0000000000..52fa649029
--- /dev/null
+++ b/usr/src/uts/sun4u/io/px/px_hlib.c
@@ -0,0 +1,2705 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/vmsystm.h>
+#include <sys/vmem.h>
+#include <sys/machsystm.h> /* lddphys() */
+#include <sys/iommutsb.h>
+#include <sys/pci.h>
+#include <pcie_pwr.h>
+#include <px_obj.h>
+#include "px_regs.h"
+#include "px_csr.h"
+#include "px_lib4u.h"
+
+/*
+ * Registers that need to be saved and restored during suspend/resume.
+ */
+
+/*
+ * Registers in the PEC Module.
+ * LPU_RESET should be set to 0ull during resume
+ */
+static uint64_t pec_config_state_regs[] = {
+ PEC_CORE_AND_BLOCK_INTERRUPT_ENABLE,
+ ILU_ERROR_LOG_ENABLE,
+ ILU_INTERRUPT_ENABLE,
+ TLU_CONTROL,
+ TLU_OTHER_EVENT_LOG_ENABLE,
+ TLU_OTHER_EVENT_INTERRUPT_ENABLE,
+ TLU_DEVICE_CONTROL,
+ TLU_LINK_CONTROL,
+ TLU_UNCORRECTABLE_ERROR_LOG_ENABLE,
+ TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE,
+ TLU_CORRECTABLE_ERROR_LOG_ENABLE,
+ TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE,
+ LPU_DEBUG_CONFIG,
+ LPU_INTERRUPT_MASK,
+ LPU_LINK_LAYER_CONFIG,
+ LPU_FLOW_CONTROL_UPDATE_CONTROL,
+ LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD,
+ LPU_TXLINK_REPLAY_TIMER_THRESHOLD,
+ LPU_REPLAY_BUFFER_MAX_ADDRESS,
+ LPU_TXLINK_RETRY_FIFO_POINTER,
+ LPU_PHY_INTERRUPT_MASK,
+ LPU_RECEIVE_PHY_INTERRUPT_MASK,
+ LPU_TRANSMIT_PHY_INTERRUPT_MASK,
+ LPU_LTSSM_CONFIG2,
+ LPU_LTSSM_CONFIG3,
+ LPU_LTSSM_CONFIG4,
+ LPU_LTSSM_CONFIG5,
+ LPU_LTSSM_INTERRUPT_MASK,
+ LPU_GIGABLAZE_GLUE_INTERRUPT_MASK,
+ DMC_CORE_AND_BLOCK_INTERRUPT_ENABLE,
+ DMC_DEBUG_SELECT_FOR_PORT_A,
+ DMC_DEBUG_SELECT_FOR_PORT_B
+};
+#define PEC_SIZE (sizeof (pec_config_state_regs))
+#define PEC_KEYS (PEC_SIZE / sizeof (uint64_t))
+
+/*
+ * Registers for the MMU module.
+ * MMU_TTE_CACHE_INVALIDATE needs to be cleared. (-1ull)
+ */
+static uint64_t mmu_config_state_regs[] = {
+ MMU_TSB_CONTROL,
+ MMU_CONTROL_AND_STATUS,
+ MMU_INTERRUPT_ENABLE
+};
+#define MMU_SIZE (sizeof (mmu_config_state_regs))
+#define MMU_KEYS (MMU_SIZE / sizeof (uint64_t))
+
+/*
+ * Registers for the IB Module
+ */
+static uint64_t ib_config_state_regs[] = {
+ IMU_ERROR_LOG_ENABLE,
+ IMU_INTERRUPT_ENABLE
+};
+#define IB_SIZE (sizeof (ib_config_state_regs))
+#define IB_KEYS (IB_SIZE / sizeof (uint64_t))
+#define IB_MAP_SIZE (INTERRUPT_MAPPING_ENTRIES * sizeof (uint64_t))
+
+/*
+ * Registers for the CB module.
+ * JBC_ERROR_STATUS_CLEAR needs to be cleared. (-1ull)
+ */
+static uint64_t cb_config_state_regs[] = {
+ JBUS_PARITY_CONTROL,
+ JBC_FATAL_RESET_ENABLE,
+ JBC_CORE_AND_BLOCK_INTERRUPT_ENABLE,
+ JBC_ERROR_LOG_ENABLE,
+ JBC_INTERRUPT_ENABLE
+};
+#define CB_SIZE (sizeof (cb_config_state_regs))
+#define CB_KEYS (CB_SIZE / sizeof (uint64_t))
+
+static uint64_t msiq_config_other_regs[] = {
+ ERR_COR_MAPPING,
+ ERR_NONFATAL_MAPPING,
+ ERR_FATAL_MAPPING,
+ PM_PME_MAPPING,
+ PME_TO_ACK_MAPPING,
+ MSI_32_BIT_ADDRESS,
+ MSI_64_BIT_ADDRESS
+};
+#define MSIQ_OTHER_SIZE (sizeof (msiq_config_other_regs))
+#define MSIQ_OTHER_KEYS (MSIQ_OTHER_SIZE / sizeof (uint64_t))
+
+#define MSIQ_STATE_SIZE (EVENT_QUEUE_STATE_ENTRIES * sizeof (uint64_t))
+#define MSIQ_MAPPING_SIZE (MSI_MAPPING_ENTRIES * sizeof (uint64_t))
+
+static uint64_t msiq_suspend(devhandle_t dev_hdl, pxu_t *pxu_p);
+static void msiq_resume(devhandle_t dev_hdl, pxu_t *pxu_p);
+
+/* ARGSUSED */
+void
+hvio_cb_init(caddr_t xbc_csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+ /* Check if we need to enable inverted parity */
+ val = (1ULL << JBUS_PARITY_CONTROL_P_EN);
+ CSR_XS(xbc_csr_base, JBUS_PARITY_CONTROL, val);
+ DBG(DBG_CB, NULL, "hvio_cb_init, JBUS_PARITY_CONTROL: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBUS_PARITY_CONTROL));
+
+ val = (1 << JBC_FATAL_RESET_ENABLE_SPARE_P_INT_EN)|
+ (1 << JBC_FATAL_RESET_ENABLE_MB_PEA_P_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_CPE_P_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_APE_P_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_PIO_CPE_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_JTCEEW_P_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_JTCEEI_P_INT_EN) |
+ (1 << JBC_FATAL_RESET_ENABLE_JTCEER_P_INT_EN);
+ CSR_XS(xbc_csr_base, JBC_FATAL_RESET_ENABLE, val);
+ DBG(DBG_CB, NULL, "hvio_cb_init, JBC_FATAL_RESET_ENABLE: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBC_FATAL_RESET_ENABLE));
+
+ /*
+ * Enable merge, jbc and dmc interrupts.
+ */
+ CSR_XS(xbc_csr_base, JBC_CORE_AND_BLOCK_INTERRUPT_ENABLE, -1ull);
+ DBG(DBG_CB, NULL,
+ "hvio_cb_init, JBC_CORE_AND_BLOCK_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBC_CORE_AND_BLOCK_INTERRUPT_ENABLE));
+
+ /*
+ * Enable all error log bits.
+ */
+ CSR_XS(xbc_csr_base, JBC_ERROR_LOG_ENABLE, -1ull);
+ DBG(DBG_CB, NULL, "hvio_cb_init, JBC_ERROR_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBC_ERROR_LOG_ENABLE));
+
+ /*
+ * Enable all interrupts.
+ */
+ CSR_XS(xbc_csr_base, JBC_INTERRUPT_ENABLE, -1ull);
+ DBG(DBG_CB, NULL, "hvio_cb_init, JBC_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBC_INTERRUPT_ENABLE));
+
+ /*
+ * Emit warning for pending errors and flush the logged error
+ * status register.
+ */
+ val = CSR_XR(xbc_csr_base, JBC_ERROR_STATUS_CLEAR);
+
+ CSR_XS(xbc_csr_base, JBC_ERROR_STATUS_CLEAR, -1ull);
+ DBG(DBG_CB, NULL, "hvio_cb_init, JBC_ERROR_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(xbc_csr_base, JBC_ERROR_STATUS_CLEAR));
+}
+
+/* ARGSUSED */
+void
+hvio_ib_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+ /*
+ * CSR_V IMU_ERROR_LOG_ENABLE Expect Kernel 0x3FF
+ */
+ val = -1ull;
+ CSR_XS(csr_base, IMU_ERROR_LOG_ENABLE, val);
+ DBG(DBG_IB, NULL, "hvio_ib_init - IMU_ERROR_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, IMU_ERROR_LOG_ENABLE));
+
+ /*
+ * CSR_V IMU_INTERRUPT_ENABLE Expect Kernel 0x3FF000003FF
+ */
+ val = -1ull;
+ CSR_XS(csr_base, IMU_INTERRUPT_ENABLE, val);
+ DBG(DBG_IB, NULL, "hvio_ib_init - IMU_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, IMU_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V IMU_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_IB, NULL, "hvio_ib_init - IMU_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, IMU_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V IMU_ERROR_STATUS_CLEAR Expect HW 0x0
+ */
+ DBG(DBG_IB, NULL, "hvio_ib_init - IMU_ERROR_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(csr_base, IMU_ERROR_STATUS_CLEAR));
+}
+
+/* ARGSUSED */
+static void
+ilu_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+ /*
+ * CSR_V ILU_ERROR_LOG_ENABLE Expect OBP 0x10
+ */
+
+ val = 0ull;
+ val = (1ull << ILU_ERROR_LOG_ENABLE_IHB_PE);
+
+ CSR_XS(csr_base, ILU_ERROR_LOG_ENABLE, val);
+ DBG(DBG_ILU, NULL, "ilu_init - ILU_ERROR_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, ILU_ERROR_LOG_ENABLE));
+
+ /*
+ * CSR_V ILU_INTERRUPT_ENABLE Expect OBP 0x1000000010
+ */
+
+ val = (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_S) |
+ (1ull << ILU_INTERRUPT_ENABLE_IHB_PE_P);
+
+ CSR_XS(csr_base, ILU_INTERRUPT_ENABLE, val);
+ DBG(DBG_ILU, NULL, "ilu_init - ILU_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, ILU_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V ILU_INTERRUPT_STATUS Expect HW 0x1000000010
+ */
+ DBG(DBG_ILU, NULL, "ilu_init - ILU_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, ILU_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V ILU_ERROR_STATUS_CLEAR Expect HW 0x0
+ */
+ DBG(DBG_ILU, NULL, "ilu_init - ILU_ERROR_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(csr_base, ILU_ERROR_STATUS_CLEAR));
+}
+
+static void
+tlu_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+ /*
+ * CSR_V TLU_CONTROL Expect OBP ???
+ */
+
+ /*
+ * L0s entry default timer value - 7.0 us
+ * Completion timeout select default value - 67.1 ms and
+ * OBP will set this value.
+ *
+ * Configuration - Bit 0 should always be 0 for upstream port.
+ * Bit 1 is clock - how is this related to the clock bit in TLU
+ * Link Control register? Both are hardware dependent and likely
+ * set by OBP.
+ *
+ * Disable non-posted write bit - ordering by setting
+ * NPWR_EN bit to force serialization of writes.
+ */
+ val = CSR_XR(csr_base, TLU_CONTROL);
+
+ if (pxu_p->chip_id == FIRE_VER_10) {
+ val |= (TLU_CONTROL_L0S_TIM_DEFAULT <<
+ FIRE10_TLU_CONTROL_L0S_TIM) |
+ (1ull << FIRE10_TLU_CONTROL_NPWR_EN) |
+ TLU_CONTROL_CONFIG_DEFAULT;
+ } else {
+ /* Default case is FIRE2.0 */
+ val |= (TLU_CONTROL_L0S_TIM_DEFAULT << TLU_CONTROL_L0S_TIM) |
+ (1ull << TLU_CONTROL_NPWR_EN) | TLU_CONTROL_CONFIG_DEFAULT;
+ }
+
+ CSR_XS(csr_base, TLU_CONTROL, val);
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, TLU_CONTROL));
+
+ /*
+ * CSR_V TLU_STATUS Expect HW 0x4
+ */
+
+ /*
+ * Only bit [7:0] are currently defined. Bits [2:0]
+ * are the state, which should likely be in state active,
+ * 100b. Bit three is 'recovery', which is not understood.
+ * All other bits are reserved.
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_STATUS));
+
+ /*
+ * CSR_V TLU_PME_TURN_OFF_GENERATE Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_PME_TURN_OFF_GENERATE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_PME_TURN_OFF_GENERATE));
+
+ /*
+ * CSR_V TLU_INGRESS_CREDITS_INITIAL Expect HW 0x10000200C0
+ */
+
+ /*
+ * Ingress credits initial register. Bits [39:32] should be
+ * 0x10, bits [19:12] should be 0x20, and bits [11:0] should
+ * be 0xC0. These are the reset values, and should be set by
+ * HW.
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_INGRESS_CREDITS_INITIAL: 0x%llx\n",
+ CSR_XR(csr_base, TLU_INGRESS_CREDITS_INITIAL));
+
+ /*
+ * CSR_V TLU_DIAGNOSTIC Expect HW 0x0
+ */
+
+ /*
+ * Diagnostic register - always zero unless we are debugging.
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DIAGNOSTIC: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DIAGNOSTIC));
+
+ /*
+ * CSR_V TLU_EGRESS_CREDITS_CONSUMED Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_EGRESS_CREDITS_CONSUMED: 0x%llx\n",
+ CSR_XR(csr_base, TLU_EGRESS_CREDITS_CONSUMED));
+
+ /*
+ * CSR_V TLU_EGRESS_CREDIT_LIMIT Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_EGRESS_CREDIT_LIMIT: 0x%llx\n",
+ CSR_XR(csr_base, TLU_EGRESS_CREDIT_LIMIT));
+
+ /*
+ * CSR_V TLU_EGRESS_RETRY_BUFFER Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_EGRESS_RETRY_BUFFER: 0x%llx\n",
+ CSR_XR(csr_base, TLU_EGRESS_RETRY_BUFFER));
+
+ /*
+ * CSR_V TLU_INGRESS_CREDITS_ALLOCATED Expected HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_INGRESS_CREDITS_ALLOCATED: 0x%llx\n",
+ CSR_XR(csr_base, TLU_INGRESS_CREDITS_ALLOCATED));
+
+ /*
+ * CSR_V TLU_INGRESS_CREDITS_RECEIVED Expected HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_INGRESS_CREDITS_RECEIVED: 0x%llx\n",
+ CSR_XR(csr_base, TLU_INGRESS_CREDITS_RECEIVED));
+
+ /*
+ * CSR_V TLU_OTHER_EVENT_LOG_ENABLE Expected HW 0x7FF0F
+ */
+
+ /*
+ * First of a 'guilty five'. Problem now is that the orde
+ * seems to different - some are log enable first then
+ * interrupt enable, others are have them reversed. For
+ * now I'll do them independently before creating a common
+ * framework for them all.
+ */
+
+ val = -1ull;
+ CSR_XS(csr_base, TLU_OTHER_EVENT_LOG_ENABLE, val);
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_OTHER_EVENT_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_OTHER_EVENT_LOG_ENABLE));
+
+ /*
+ * CSR_V TLU_OTHER_EVENT_INTERRUPT_ENABLE OBP 0x7FF0F0007FF0F
+ */
+
+ /*
+ * Second of five. Bits [55-32] enable secondary other event
+ * interrupt enables, bit [23:0] enable primatry other event
+ * interrupt enables.
+ */
+
+ val = -1ull;
+ CSR_XS(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE, val);
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_OTHER_EVENT_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V TLU_OTHER_EVENT_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_OTHER_EVENT_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_OTHER_EVENT_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V TLU_OTHER_EVENT_STATUS_CLEAR Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_OTHER_EVENT_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(csr_base, TLU_OTHER_EVENT_STATUS_CLEAR));
+
+ /*
+ * CSR_V TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER1_LOG));
+
+ /*
+ * CSR_V TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_RECEIVE_OTHER_EVENT_HEADER2_LOG));
+
+ /*
+ * CSR_V TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER1_LOG));
+
+ /*
+ * CSR_V TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_TRANSMIT_OTHER_EVENT_HEADER2_LOG));
+
+ /*
+ * CSR_V TLU_PERFORMANCE_COUNTER_SELECT Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_PERFORMANCE_COUNTER_SELECT: 0x%llx\n",
+ CSR_XR(csr_base, TLU_PERFORMANCE_COUNTER_SELECT));
+
+ /*
+ * CSR_V TLU_PERFORMANCE_COUNTER_ZERO Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_PERFORMANCE_COUNTER_ZERO: 0x%llx\n",
+ CSR_XR(csr_base, TLU_PERFORMANCE_COUNTER_ZERO));
+
+ /*
+ * CSR_V TLU_PERFORMANCE_COUNTER_ONE Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_PERFORMANCE_COUNTER_ONE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_PERFORMANCE_COUNTER_ONE));
+
+ /*
+ * CSR_V TLU_PERFORMANCE_COUNTER_TWO Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_PERFORMANCE_COUNTER_TWO: 0x%llx\n",
+ CSR_XR(csr_base, TLU_PERFORMANCE_COUNTER_TWO));
+
+ /*
+ * CSR_V TLU_DEBUG_SELECT_A Expect HW 0x0
+ */
+
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DEBUG_SELECT_A: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DEBUG_SELECT_A));
+
+ /*
+ * CSR_V TLU_DEBUG_SELECT_B Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DEBUG_SELECT_B: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DEBUG_SELECT_B));
+
+ /*
+ * CSR_V TLU_DEVICE_CAPABILITIES Expect HW 0xFC2
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DEVICE_CAPABILITIES: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DEVICE_CAPABILITIES));
+
+ /*
+ * CSR_V TLU_DEVICE_CONTROL Expect HW 0x0
+ */
+
+ /*
+ * Bits [14:12] are the Max Read Request Size, which is always 64
+ * bytes which is 000b. Bits [7:5] are Max Payload Size, which
+ * start at 128 bytes which is 000b. This may be revisited if
+ * init_child finds greater values.
+ */
+ val = 0x0ull;
+ CSR_XS(csr_base, TLU_DEVICE_CONTROL, val);
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DEVICE_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DEVICE_CONTROL));
+
+ /*
+ * CSR_V TLU_DEVICE_STATUS Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_DEVICE_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_DEVICE_STATUS));
+
+ /*
+ * CSR_V TLU_LINK_CAPABILITIES Expect HW 0x15C81
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_LINK_CAPABILITIES: 0x%llx\n",
+ CSR_XR(csr_base, TLU_LINK_CAPABILITIES));
+
+ /*
+ * CSR_V TLU_LINK_CONTROL Expect OBP 0x40
+ */
+
+ /*
+ * The CLOCK bit should be set by OBP if the hardware dictates,
+ * and if it is set then ASPM should be used since then L0s exit
+ * latency should be lower than L1 exit latency.
+ *
+ * Note that we will not enable power management during bringup
+ * since it has not been test and is creating some problems in
+ * simulation.
+ */
+ val = (1ull << TLU_LINK_CONTROL_CLOCK);
+
+ CSR_XS(csr_base, TLU_LINK_CONTROL, val);
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_LINK_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, TLU_LINK_CONTROL));
+
+ /*
+ * CSR_V TLU_LINK_STATUS Expect OBP 0x1011
+ */
+
+ /*
+ * Not sure if HW or OBP will be setting this read only
+ * register. Bit 12 is Clock, and it should always be 1
+ * signifying that the component uses the same physical
+ * clock as the platform. Bits [9:4] are for the width,
+ * with the expected value above signifying a x1 width.
+ * Bits [3:0] are the speed, with 1b signifying 2.5 Gb/s,
+ * the only speed as yet supported by the PCI-E spec.
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_LINK_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_LINK_STATUS));
+
+ /*
+ * CSR_V TLU_SLOT_CAPABILITIES Expect OBP ???
+ */
+
+ /*
+ * Power Limits for the slots. Will be platform
+ * dependent, and OBP will need to set after consulting
+ * with the HW guys.
+ *
+ * Bits [16:15] are power limit scale, which most likely
+ * will be 0b signifying 1x. Bits [14:7] are the Set
+ * Power Limit Value, which is a number which is multiplied
+ * by the power limit scale to get the actual power limit.
+ */
+ DBG(DBG_TLU, NULL, "tlu_init - TLU_SLOT_CAPABILITIES: 0x%llx\n",
+ CSR_XR(csr_base, TLU_SLOT_CAPABILITIES));
+
+ /*
+ * CSR_V TLU_UNCORRECTABLE_ERROR_LOG_ENABLE Expect Kernel 0x17F011
+ */
+
+ /*
+ * First of a 'guilty five'. See note for Other Event Log.
+ */
+ val = -1ull;
+ CSR_XS(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE, val);
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_UNCORRECTABLE_ERROR_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_LOG_ENABLE));
+
+ /*
+ * CSR_V TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE
+ * Expect Kernel 0x17F0110017F011
+ */
+
+ /*
+ * Second of a 'guilty five'. Needs the value in both bits [52:32]
+ * and bits [20:0] for primary and secondary error interrupts.
+ */
+ val = -1ull;
+ CSR_XS(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE, val);
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V TLU_UNCORRECTABLE_ERROR_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_UNCORRECTABLE_ERROR_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(csr_base, TLU_UNCORRECTABLE_ERROR_STATUS_CLEAR));
+
+ /*
+ * CSR_V TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER1_LOG));
+
+ /*
+ * CSR_V TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_RECEIVE_UNCORRECTABLE_ERROR_HEADER2_LOG));
+
+ /*
+ * CSR_V TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER1_LOG));
+
+ /*
+ * CSR_V TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG: 0x%llx\n",
+ CSR_XR(csr_base, TLU_TRANSMIT_UNCORRECTABLE_ERROR_HEADER2_LOG));
+
+ /*
+ * CSR_V TLU_CORRECTABLE_ERROR_LOG_ENABLE Expect Kernel 0x11C1
+ */
+
+ /*
+ * Another set of 'guilty five'.
+ */
+
+ val = -1ull;
+ CSR_XS(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE, val);
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_CORRECTABLE_ERROR_LOG_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_LOG_ENABLE));
+
+ /*
+ * CSR_V TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE Kernel 0x11C1000011C1
+ */
+
+ /*
+ * Bits [44:32] for secondary error, bits [12:0] for primary errors.
+ */
+ val = -1ull;
+ CSR_XS(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE, val);
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V TLU_CORRECTABLE_ERROR_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_CORRECTABLE_ERROR_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V TLU_CORRECTABLE_ERROR_STATUS_CLEAR Expect HW 0x0
+ */
+ DBG(DBG_TLU, NULL,
+ "tlu_init - TLU_CORRECTABLE_ERROR_STATUS_CLEAR: 0x%llx\n",
+ CSR_XR(csr_base, TLU_CORRECTABLE_ERROR_STATUS_CLEAR));
+}
+
+static void
+lpu_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ /* Variables used to set the ACKNAK Latency Timer and Replay Timer */
+ int link_width, max_payload;
+
+ uint64_t val;
+
+ /*
+ * ACKNAK Latency Threshold Table.
+ * See Fire PRM 1.0 sections 1.2.11.1, table 1-17.
+ */
+ int fire10_acknak_timer_table[LINK_MAX_PKT_ARR_SIZE]
+ [LINK_WIDTH_ARR_SIZE] = {
+ {0xED, 0x76, 0x70, 0x58},
+ {0x1A0, 0x76, 0x6B, 0x61},
+ {0x22F, 0x9A, 0x6A, 0x6A},
+ {0x42F, 0x11A, 0x96, 0x96},
+ {0x82F, 0x21A, 0x116, 0x116},
+ {0x102F, 0x41A, 0x216, 0x216}
+ };
+
+ /*
+ * TxLink Replay Timer Latency Table
+ * See Fire PRM 1.0 sections 1.2.11.2, table 1-18.
+ */
+ int fire10_replay_timer_table[LINK_MAX_PKT_ARR_SIZE]
+ [LINK_WIDTH_ARR_SIZE] = {
+ {0x2C7, 0x108, 0xF6, 0xBD},
+ {0x4E0, 0x162, 0x141, 0xF1},
+ {0x68D, 0x1CE, 0x102, 0x102},
+ {0xC8D, 0x34E, 0x1C2, 0x1C2},
+ {0x188D, 0x64E, 0x342, 0x342},
+ {0x308D, 0xC4E, 0x642, 0x642}
+ };
+
+ /*
+ * ACKNAK Latency Threshold Table.
+ * See Fire PRM 2.0 section 1.2.12.2, table 1-17.
+ */
+ int acknak_timer_table[LINK_MAX_PKT_ARR_SIZE][LINK_WIDTH_ARR_SIZE] = {
+ {0xED, 0x49, 0x43, 0x30},
+ {0x1A0, 0x76, 0x6B, 0x48},
+ {0x22F, 0x9A, 0x56, 0x56},
+ {0x42F, 0x11A, 0x96, 0x96},
+ {0x82F, 0x21A, 0x116, 0x116},
+ {0x102F, 0x41A, 0x216, 0x216}
+ };
+
+ /*
+ * TxLink Replay Timer Latency Table
+ * See Fire PRM 2.0 sections 1.2.12.3, table 1-18.
+ */
+ int replay_timer_table[LINK_MAX_PKT_ARR_SIZE][LINK_WIDTH_ARR_SIZE] = {
+ {0x379, 0x112, 0xFC, 0xB4},
+ {0x618, 0x1BA, 0x192, 0x10E},
+ {0x831, 0x242, 0x143, 0x143},
+ {0xFB1, 0x422, 0x233, 0x233},
+ {0x1EB0, 0x7E1, 0x412, 0x412},
+ {0x3CB0, 0xF61, 0x7D2, 0x7D2}
+ };
+ /*
+ * Get the Link Width. See table above LINK_WIDTH_ARR_SIZE #define
+ * Only Link Widths of x1, x4, and x8 are supported.
+ * If any width is reported other than x8, set default to x8.
+ */
+ link_width = CSR_FR(csr_base, TLU_LINK_STATUS, WIDTH);
+ DBG(DBG_LPU, NULL, "lpu_init - Link Width: x%d\n", link_width);
+
+ /*
+ * Convert link_width to match timer array configuration.
+ */
+ switch (link_width) {
+ case 1:
+ link_width = 0;
+ break;
+ case 4:
+ link_width = 1;
+ break;
+ case 8:
+ link_width = 2;
+ break;
+ case 16:
+ link_width = 3;
+ break;
+ default:
+ link_width = 0;
+ }
+
+ /*
+ * Get the Max Payload Size.
+ * See table above LINK_MAX_PKT_ARR_SIZE #define
+ */
+ if (pxu_p->chip_id == FIRE_VER_10) {
+ max_payload = CSR_FR(csr_base,
+ FIRE10_LPU_LINK_LAYER_CONFIG, MAX_PAYLOAD);
+ } else {
+ /* Default case is FIRE2.0 */
+ max_payload = ((CSR_FR(csr_base, TLU_CONTROL, CONFIG) &
+ TLU_CONTROL_MPS_MASK) >> TLU_CONTROL_MPS_SHIFT);
+ }
+
+ DBG(DBG_LPU, NULL, "lpu_init - May Payload: %d\n",
+ (0x80 << max_payload));
+
+ /* Make sure the packet size is not greater than 4096 */
+ max_payload = (max_payload >= LINK_MAX_PKT_ARR_SIZE) ?
+ (LINK_MAX_PKT_ARR_SIZE - 1) : max_payload;
+
+ /*
+ * CSR_V LPU_ID Expect HW 0x0
+ */
+
+ /*
+ * This register has link id, phy id and gigablaze id.
+ * Should be set by HW.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_ID: 0x%llx\n",
+ CSR_XR(csr_base, LPU_ID));
+
+ /*
+ * CSR_V LPU_RESET Expect Kernel 0x0
+ */
+
+ /*
+ * No reason to have any reset bits high until an error is
+ * detected on the link.
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_RESET, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RESET: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RESET));
+
+ /*
+ * CSR_V LPU_DEBUG_STATUS Expect HW 0x0
+ */
+
+ /*
+ * Bits [15:8] are Debug B, and bit [7:0] are Debug A.
+ * They are read-only. What do the 8 bits mean, and
+ * how do they get set if they are read only?
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_DEBUG_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_DEBUG_STATUS));
+
+ /*
+ * CSR_V LPU_DEBUG_CONFIG Expect Kernel 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_DEBUG_CONFIG: 0x%llx\n",
+ CSR_XR(csr_base, LPU_DEBUG_CONFIG));
+
+ /*
+ * CSR_V LPU_LTSSM_CONTROL Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONTROL));
+
+ /*
+ * CSR_V LPU_LINK_STATUS Expect HW 0x101
+ */
+
+ /*
+ * This register has bits [9:4] for link width, and the
+ * default 0x10, means a width of x16. The problem is
+ * this width is not supported according to the TLU
+ * link status register.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LINK_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_STATUS));
+
+ /*
+ * CSR_V LPU_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_INTERRUPT_STATUS));
+
+ /*
+ * CSR_V LPU_INTERRUPT_MASK Expect HW 0x0
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER_SELECT Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER_SELECT: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER_SELECT));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER_CONTROL Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER_CONTROL));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER1 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER1));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER1_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER1_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER1_TEST));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER2 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER2));
+
+ /*
+ * CSR_V LPU_LINK_PERFORMANCE_COUNTER2_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_PERFORMANCE_COUNTER2_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_PERFORMANCE_COUNTER2_TEST));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_CONFIG Expect HW 0x100
+ */
+
+ /*
+ * This is another place where Max Payload can be set,
+ * this time for the link layer. It will be set to
+ * 128B, which is the default, but this will need to
+ * be revisited.
+ */
+ val = (1ull << LPU_LINK_LAYER_CONFIG_VC0_EN);
+ CSR_XS(csr_base, LPU_LINK_LAYER_CONFIG, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LINK_LAYER_CONFIG: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_LAYER_CONFIG));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_STATUS Expect OBP 0x5
+ */
+
+ /*
+ * Another R/W status register. Bit 3, DL up Status, will
+ * be set high. The link state machine status bits [2:0]
+ * are set to 0x1, but the status bits are not defined in the
+ * PRM. What does 0x1 mean, what others values are possible
+ * and what are thier meanings?
+ *
+ * This register has been giving us problems in simulation.
+ * It has been mentioned that software should not program
+ * any registers with WE bits except during debug. So
+ * this register will no longer be programmed.
+ */
+
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LINK_LAYER_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_LAYER_STATUS));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_INTERRUPT_AND_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_LAYER_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_LAYER_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_INTERRUPT_AND_STATUS_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_LAYER_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_LAYER_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_INTERRUPT_MASK Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LINK_LAYER_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LINK_LAYER_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_FLOW_CONTROL_UPDATE_CONTROL Expect OBP 0x7
+ */
+
+ /*
+ * The PRM says that only the first two bits will be set
+ * high by default, which will enable flow control for
+ * posted and non-posted updates, but NOT completetion
+ * updates.
+ */
+ val = (1ull << LPU_FLOW_CONTROL_UPDATE_CONTROL_FC0_U_NP_EN) |
+ (1ull << LPU_FLOW_CONTROL_UPDATE_CONTROL_FC0_U_P_EN);
+ CSR_XS(csr_base, LPU_FLOW_CONTROL_UPDATE_CONTROL, val);
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_FLOW_CONTROL_UPDATE_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_FLOW_CONTROL_UPDATE_CONTROL));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_FLOW_CONTROL_UPDATE_TIMEOUT_VALUE
+ * Expect OBP 0x1D4C
+ */
+
+ /*
+ * This should be set by OBP. We'll check to make sure.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - "
+ "LPU_LINK_LAYER_FLOW_CONTROL_UPDATE_TIMEOUT_VALUE: 0x%llx\n",
+ CSR_XR(csr_base,
+ LPU_LINK_LAYER_FLOW_CONTROL_UPDATE_TIMEOUT_VALUE));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER0 Expect OBP ???
+ */
+
+ /*
+ * This register has Flow Control Update Timer values for
+ * non-posted and posted requests, bits [30:16] and bits
+ * [14:0], respectively. These are read-only to SW so
+ * either HW or OBP needs to set them.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - "
+ "LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER0: 0x%llx\n",
+ CSR_XR(csr_base,
+ LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER0));
+
+ /*
+ * CSR_V LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER1 Expect OBP ???
+ */
+
+ /*
+ * Same as timer0 register above, except for bits [14:0]
+ * have the timer values for completetions. Read-only to
+ * SW; OBP or HW need to set it.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - "
+ "LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER1: 0x%llx\n",
+ CSR_XR(csr_base,
+ LPU_LINK_LAYER_VC0_FLOW_CONTROL_UPDATE_TIMER1));
+
+ /*
+ * CSR_V LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD
+ */
+ if (pxu_p->chip_id == FIRE_VER_10) {
+ val = fire10_acknak_timer_table[max_payload][link_width];
+ } else {
+ /* Default case is FIRE2.0 */
+ val = acknak_timer_table[max_payload][link_width];
+ }
+
+ CSR_XS(csr_base,
+ LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD, val);
+
+ DBG(DBG_LPU, NULL, "lpu_init - "
+ "LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_FREQUENT_NAK_LATENCY_TIMER_THRESHOLD));
+
+ /*
+ * CSR_V LPU_TXLINK_ACKNAK_LATENCY_TIMER Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_ACKNAK_LATENCY_TIMER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_ACKNAK_LATENCY_TIMER));
+
+ /*
+ * CSR_V LPU_TXLINK_REPLAY_TIMER_THRESHOLD
+ */
+ if (pxu_p->chip_id == FIRE_VER_10) {
+ val = fire10_replay_timer_table[max_payload][link_width];
+ } else {
+ /* Default case is FIRE2.0 */
+ val = replay_timer_table[max_payload][link_width];
+ }
+
+ CSR_XS(csr_base, LPU_TXLINK_REPLAY_TIMER_THRESHOLD, val);
+
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_REPLAY_TIMER_THRESHOLD: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_REPLAY_TIMER_THRESHOLD));
+
+ /*
+ * CSR_V LPU_TXLINK_REPLAY_TIMER Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TXLINK_REPLAY_TIMER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_REPLAY_TIMER));
+
+ /*
+ * CSR_V LPU_TXLINK_REPLAY_NUMBER_STATUS Expect OBP 0x3
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_REPLAY_NUMBER_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_REPLAY_NUMBER_STATUS));
+
+ /*
+ * CSR_V LPU_REPLAY_BUFFER_MAX_ADDRESS Expect OBP 0xB3F
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_REPLAY_BUFFER_MAX_ADDRESS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_REPLAY_BUFFER_MAX_ADDRESS));
+
+ /*
+ * CSR_V LPU_TXLINK_RETRY_FIFO_POINTER Expect OBP 0xFFFF0000
+ */
+ val = ((LPU_TXLINK_RETRY_FIFO_POINTER_RTRY_FIFO_TLPTR_DEFAULT <<
+ LPU_TXLINK_RETRY_FIFO_POINTER_RTRY_FIFO_TLPTR) |
+ (LPU_TXLINK_RETRY_FIFO_POINTER_RTRY_FIFO_HDPTR_DEFAULT <<
+ LPU_TXLINK_RETRY_FIFO_POINTER_RTRY_FIFO_HDPTR));
+
+ CSR_XS(csr_base, LPU_TXLINK_RETRY_FIFO_POINTER, val);
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_RETRY_FIFO_POINTER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_RETRY_FIFO_POINTER));
+
+ /*
+ * CSR_V LPU_TXLINK_RETRY_FIFO_R_W_POINTER Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_RETRY_FIFO_R_W_POINTER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_RETRY_FIFO_R_W_POINTER));
+
+ /*
+ * CSR_V LPU_TXLINK_RETRY_FIFO_CREDIT Expect HW 0x1580
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_RETRY_FIFO_CREDIT: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_RETRY_FIFO_CREDIT));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_COUNTER Expect OBP 0xFFF0000
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TXLINK_SEQUENCE_COUNTER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_COUNTER));
+
+ /*
+ * CSR_V LPU_TXLINK_ACK_SENT_SEQUENCE_NUMBER Expect HW 0xFFF
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_ACK_SENT_SEQUENCE_NUMBER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_ACK_SENT_SEQUENCE_NUMBER));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_COUNT_FIFO_MAX_ADDR Expect OBP 0x157
+ */
+
+ /*
+ * Test only register. Will not be programmed.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_SEQUENCE_COUNT_FIFO_MAX_ADDR: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_COUNT_FIFO_MAX_ADDR));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_COUNT_FIFO_POINTERS Expect HW 0xFFF0000
+ */
+
+ /*
+ * Test only register. Will not be programmed.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_SEQUENCE_COUNT_FIFO_POINTERS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_COUNT_FIFO_POINTERS));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_COUNT_R_W_POINTERS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_SEQUENCE_COUNT_R_W_POINTERS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_COUNT_R_W_POINTERS));
+
+ /*
+ * CSR_V LPU_TXLINK_TEST_CONTROL Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TXLINK_TEST_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_TEST_CONTROL));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_ADDRESS_CONTROL Expect HW 0x0
+ */
+
+ /*
+ * Test only register. Will not be programmed.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_ADDRESS_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_ADDRESS_CONTROL));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_DATA_LOAD0 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_DATA_LOAD0: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_DATA_LOAD0));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_DATA_LOAD1 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_DATA_LOAD1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_DATA_LOAD1));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_DATA_LOAD2 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_DATA_LOAD2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_DATA_LOAD2));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_DATA_LOAD3 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_DATA_LOAD3: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_DATA_LOAD3));
+
+ /*
+ * CSR_V LPU_TXLINK_MEMORY_DATA_LOAD4 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_MEMORY_DATA_LOAD4: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_MEMORY_DATA_LOAD4));
+
+ /*
+ * CSR_V LPU_TXLINK_RETRY_DATA_COUNT Expect HW 0x0
+ */
+
+ /*
+ * Test only register. Will not be programmed.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TXLINK_RETRY_DATA_COUNT: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_RETRY_DATA_COUNT));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_BUFFER_COUNT Expect HW 0x0
+ */
+
+ /*
+ * Test only register. Will not be programmed.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_SEQUENCE_BUFFER_COUNT: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_BUFFER_COUNT));
+
+ /*
+ * CSR_V LPU_TXLINK_SEQUENCE_BUFFER_BOTTOM_DATA Expect HW 0x0
+ */
+
+ /*
+ * Test only register.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TXLINK_SEQUENCE_BUFFER_BOTTOM_DATA: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TXLINK_SEQUENCE_BUFFER_BOTTOM_DATA));
+
+ /*
+ * CSR_V LPU_RXLINK_NEXT_RECEIVE_SEQUENCE_1_COUNTER Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - "
+ "LPU_RXLINK_NEXT_RECEIVE_SEQUENCE_1_COUNTER: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RXLINK_NEXT_RECEIVE_SEQUENCE_1_COUNTER));
+
+ /*
+ * CSR_V LPU_RXLINK_UNSUPPORTED_DLLP_RECEIVED Expect HW 0x0
+ */
+
+ /*
+ * test only register.
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_RXLINK_UNSUPPORTED_DLLP_RECEIVED: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RXLINK_UNSUPPORTED_DLLP_RECEIVED));
+
+ /*
+ * CSR_V LPU_RXLINK_TEST_CONTROL Expect HW 0x0
+ */
+
+ /*
+ * test only register.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RXLINK_TEST_CONTROL: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RXLINK_TEST_CONTROL));
+
+ /*
+ * CSR_V LPU_PHYSICAL_LAYER_CONFIGURATION Expect HW 0x10
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_PHYSICAL_LAYER_CONFIGURATION: 0x%llx\n",
+ CSR_XR(csr_base, LPU_PHYSICAL_LAYER_CONFIGURATION));
+
+ /*
+ * CSR_V LPU_PHY_LAYER_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_PHY_LAYER_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_PHY_LAYER_STATUS));
+
+ /*
+ * CSR_V LPU_PHY_LAYER_INTERRUPT_AND_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_PHY_LAYER_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_PHY_LAYER_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_PHY_INTERRUPT_AND_STATUS_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_PHY_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_PHY_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_PHY_INTERRUPT_MASK Expect HW 0x0
+ */
+
+ val = 0ull;
+ CSR_XS(csr_base, LPU_PHY_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_PHY_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_PHY_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_CONFIG Expect HW 0x0
+ */
+
+ /*
+ * This also needs some explanation. What is the best value
+ * for the water mark? Test mode enables which test mode?
+ * Programming model needed for the Receiver Reset Lane N
+ * bits.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RECEIVE_PHY_CONFIG: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_CONFIG));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_STATUS1 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RECEIVE_PHY_STATUS1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_STATUS1));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_STATUS2 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RECEIVE_PHY_STATUS2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_STATUS2));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_STATUS3 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_RECEIVE_PHY_STATUS3: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_STATUS3));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_RECEIVE_PHY_INTERRUPT_MASK Expect OBP 0x0
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_RECEIVE_PHY_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_RECEIVE_PHY_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_RECEIVE_PHY_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_CONFIG Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TRANSMIT_PHY_CONFIG: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TRANSMIT_PHY_CONFIG));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TRANSMIT_PHY_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TRANSMIT_PHY_STATUS));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base,
+ LPU_TRANSMIT_PHY_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_INTERRUPT_MASK Expect HW 0x0
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_TRANSMIT_PHY_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_TRANSMIT_PHY_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TRANSMIT_PHY_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_TRANSMIT_PHY_STATUS_2 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_TRANSMIT_PHY_STATUS_2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_TRANSMIT_PHY_STATUS_2));
+
+ /*
+ * CSR_V LPU_LTSSM_CONFIG1 Expect OBP 0x205
+ */
+
+ /*
+ * The new PRM has values for LTSSM 8 ns timeout value and
+ * LTSSM 20 ns timeout value. But what do these values mean?
+ * Most of the other bits are questions as well.
+ *
+ * As such we will use the reset value.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONFIG1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONFIG1));
+
+ /*
+ * CSR_V LPU_LTSSM_CONFIG2 Expect OBP 0x2DC6C0
+ */
+
+ /*
+ * Again, what does '12 ms timeout value mean'?
+ */
+ val = (LPU_LTSSM_CONFIG2_LTSSM_12_TO_DEFAULT <<
+ LPU_LTSSM_CONFIG2_LTSSM_12_TO);
+ CSR_XS(csr_base, LPU_LTSSM_CONFIG2, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONFIG2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONFIG2));
+
+ /*
+ * CSR_V LPU_LTSSM_CONFIG3 Expect OBP 0x7A120
+ */
+ val = (LPU_LTSSM_CONFIG3_LTSSM_2_TO_DEFAULT <<
+ LPU_LTSSM_CONFIG3_LTSSM_2_TO);
+ CSR_XS(csr_base, LPU_LTSSM_CONFIG3, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONFIG3: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONFIG3));
+
+ /*
+ * CSR_V LPU_LTSSM_CONFIG4 Expect OBP 0x21300
+ *
+ * XXX fix LPU_LTSSM_CONFIG4_DATA_RATE_DEFAULT &
+ * LPU_LTSSM_CONFIG4_N_FTS_DEFAULT in px_pec.h
+ */
+ val = ((LPU_LTSSM_CONFIG4_DATA_RATE_DEFAULT <<
+ LPU_LTSSM_CONFIG4_DATA_RATE) |
+ (LPU_LTSSM_CONFIG4_N_FTS_DEFAULT <<
+ LPU_LTSSM_CONFIG4_N_FTS));
+ CSR_XS(csr_base, LPU_LTSSM_CONFIG4, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONFIG4: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONFIG4));
+
+ /*
+ * CSR_V LPU_LTSSM_CONFIG5 Expect OBP 0x0
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_LTSSM_CONFIG5, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_CONFIG5: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_CONFIG5));
+
+ /*
+ * CSR_V LPU_LTSSM_STATUS1 Expect OBP 0x0
+ */
+
+ /*
+ * LTSSM Status registers are test only.
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_STATUS1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_STATUS1));
+
+ /*
+ * CSR_V LPU_LTSSM_STATUS2 Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_STATUS2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_STATUS2));
+
+ /*
+ * CSR_V LPU_LTSSM_INTERRUPT_AND_STATUS Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LTSSM_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_LTSSM_INTERRUPT_AND_STATUS_TEST Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LTSSM_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_LTSSM_INTERRUPT_MASK Expect HW 0x0
+ */
+ val = 0ull;
+ CSR_XS(csr_base, LPU_LTSSM_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_LTSSM_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_LTSSM_STATUS_WRITE_ENABLE Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_LTSSM_STATUS_WRITE_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, LPU_LTSSM_STATUS_WRITE_ENABLE));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_CONFIG1 Expect OBP 0x88407
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_CONFIG1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_CONFIG1));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_CONFIG2 Expect OBP 0x35
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_CONFIG2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_CONFIG2));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_CONFIG3 Expect OBP 0x4400FA
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_CONFIG3: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_CONFIG3));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_CONFIG4 Expect OBP 0x1E848
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_CONFIG4: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_CONFIG4));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_STATUS Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_STATUS));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_TEST Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - "
+ "LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_TEST: 0x%llx\n",
+ CSR_XR(csr_base,
+ LPU_GIGABLAZE_GLUE_INTERRUPT_AND_STATUS_TEST));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_INTERRUPT_MASK Expect OBP 0x0
+ */
+
+ /*
+ * Reset value masks all interrupts. This will be changed
+ * to enable all interrupts.
+ */
+ val = 0x0ull;
+ CSR_XS(csr_base, LPU_GIGABLAZE_GLUE_INTERRUPT_MASK, val);
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_GIGABLAZE_GLUE_INTERRUPT_MASK: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_INTERRUPT_MASK));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_POWER_DOWN1 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_GIGABLAZE_GLUE_POWER_DOWN1: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_POWER_DOWN1));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_POWER_DOWN2 Expect HW 0x0
+ */
+ DBG(DBG_LPU, NULL,
+ "lpu_init - LPU_GIGABLAZE_GLUE_POWER_DOWN2: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_POWER_DOWN2));
+
+ /*
+ * CSR_V LPU_GIGABLAZE_GLUE_CONFIG5 Expect OBP 0x0
+ */
+ DBG(DBG_LPU, NULL, "lpu_init - LPU_GIGABLAZE_GLUE_CONFIG5: 0x%llx\n",
+ CSR_XR(csr_base, LPU_GIGABLAZE_GLUE_CONFIG5));
+}
+
+/* ARGSUSED */
+static void
+dmc_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+/*
+ * CSR_V DMC_CORE_AND_BLOCK_INTERRUPT_ENABLE Expect OBP 0x8000000000000003
+ */
+
+ val = -1ull;
+ CSR_XS(csr_base, DMC_CORE_AND_BLOCK_INTERRUPT_ENABLE, val);
+ DBG(DBG_DMC, NULL,
+ "dmc_init - DMC_CORE_AND_BLOCK_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, DMC_CORE_AND_BLOCK_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V DMC_CORE_AND_BLOCK_ERROR_STATUS Expect HW 0x0
+ */
+ DBG(DBG_DMC, NULL,
+ "dmc_init - DMC_CORE_AND_BLOCK_ERROR_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, DMC_CORE_AND_BLOCK_ERROR_STATUS));
+
+ /*
+ * CSR_V DMC_DEBUG_SELECT_FOR_PORT_A Expect HW 0x0
+ */
+ val = 0x0ull;
+ CSR_XS(csr_base, DMC_DEBUG_SELECT_FOR_PORT_A, val);
+ DBG(DBG_DMC, NULL, "dmc_init - DMC_DEBUG_SELECT_FOR_PORT_A: 0x%llx\n",
+ CSR_XR(csr_base, DMC_DEBUG_SELECT_FOR_PORT_A));
+
+ /*
+ * CSR_V DMC_DEBUG_SELECT_FOR_PORT_B Expect HW 0x0
+ */
+ val = 0x0ull;
+ CSR_XS(csr_base, DMC_DEBUG_SELECT_FOR_PORT_B, val);
+ DBG(DBG_DMC, NULL, "dmc_init - DMC_DEBUG_SELECT_FOR_PORT_B: 0x%llx\n",
+ CSR_XR(csr_base, DMC_DEBUG_SELECT_FOR_PORT_B));
+}
+
+void
+hvio_pec_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val;
+
+ ilu_init(csr_base, pxu_p);
+ tlu_init(csr_base, pxu_p);
+ lpu_init(csr_base, pxu_p);
+ dmc_init(csr_base, pxu_p);
+
+/*
+ * CSR_V PEC_CORE_AND_BLOCK_INTERRUPT_ENABLE Expect Kernel 0x800000000000000F
+ */
+
+ val = -1ull;
+ CSR_XS(csr_base, PEC_CORE_AND_BLOCK_INTERRUPT_ENABLE, val);
+ DBG(DBG_PEC, NULL,
+ "hvio_pec_init - PEC_CORE_AND_BLOCK_INTERRUPT_ENABLE: 0x%llx\n",
+ CSR_XR(csr_base, PEC_CORE_AND_BLOCK_INTERRUPT_ENABLE));
+
+ /*
+ * CSR_V PEC_CORE_AND_BLOCK_INTERRUPT_STATUS Expect HW 0x0
+ */
+ DBG(DBG_PEC, NULL,
+ "hvio_pec_init - PEC_CORE_AND_BLOCK_INTERRUPT_STATUS: 0x%llx\n",
+ CSR_XR(csr_base, PEC_CORE_AND_BLOCK_INTERRUPT_STATUS));
+}
+
+void
+hvio_mmu_init(caddr_t csr_base, pxu_t *pxu_p)
+{
+ uint64_t val, i, tsb_ctrl, obp_tsb_pa, *base_tte_addr;
+ uint_t obp_tsb_entries, obp_tsb_size;
+
+ bzero(pxu_p->tsb_vaddr, pxu_p->tsb_size);
+
+ /*
+ * Preserve OBP's TSB
+ */
+ val = CSR_XR(csr_base, MMU_TSB_CONTROL);
+
+ tsb_ctrl = CSR_XR(csr_base, MMU_TSB_CONTROL);
+
+ obp_tsb_pa = tsb_ctrl & 0x7FFFFFFE000;
+ obp_tsb_size = tsb_ctrl & 0xF;
+
+ obp_tsb_entries = MMU_TSBSIZE_TO_TSBENTRIES(obp_tsb_size);
+
+ base_tte_addr = pxu_p->tsb_vaddr +
+ ((pxu_p->tsb_size >> 3) - obp_tsb_entries);
+
+ for (i = 0; i < obp_tsb_entries; i++) {
+ uint64_t tte = lddphys(obp_tsb_pa + i * 8);
+
+ if (!MMU_TTE_VALID(tte))
+ continue;
+
+ base_tte_addr[i] = tte;
+ }
+
+ /*
+ * Invalidate the TLB through the diagnostic register.
+ */
+
+ CSR_XS(csr_base, MMU_TTE_CACHE_INVALIDATE, -1ull);
+
+ /*
+ * Configure the Fire MMU TSB Control Register. Determine
+ * the encoding for either 8KB pages (0) or 64KB pages (1).
+ *
+ * Write the most significant 30 bits of the TSB physical address
+ * and the encoded TSB table size.
+ */
+ for (i = 8; i && (pxu_p->tsb_size < (0x2000 << i)); i--);
+
+ val = (((((va_to_pa(pxu_p->tsb_vaddr)) >> 13) << 13) |
+ ((MMU_PAGE_SHIFT == 13) ? 0 : 1) << 8) | i);
+
+ CSR_XS(csr_base, MMU_TSB_CONTROL, val);
+
+ /*
+ * Enable the MMU, set the "TSB Cache Snoop Enable",
+ * the "Cache Mode", the "Bypass Enable" and
+ * the "Translation Enable" bits.
+ */
+ val = CSR_XR(csr_base, MMU_CONTROL_AND_STATUS);
+ val |= ((1ull << MMU_CONTROL_AND_STATUS_SE)
+ | (MMU_CONTROL_AND_STATUS_CM_MASK << MMU_CONTROL_AND_STATUS_CM)
+ | (1ull << MMU_CONTROL_AND_STATUS_BE)
+ | (1ull << MMU_CONTROL_AND_STATUS_TE));
+
+ CSR_XS(csr_base, MMU_CONTROL_AND_STATUS, val);
+
+ /*
+ * Read the register here to ensure that the previous writes to
+ * the Fire MMU registers have been flushed. (Technically, this
+ * is not entirely necessary here as we will likely do later reads
+ * during Fire initialization, but it is a small price to pay for
+ * more modular code.)
+ */
+ (void) CSR_XR(csr_base, MMU_CONTROL_AND_STATUS);
+
+ /*
+ * Enable all primary and secondary interrupts.
+ */
+ val = -1ull;
+ CSR_XS(csr_base, MMU_INTERRUPT_ENABLE, val);
+}
+
+/*
+ * Generic IOMMU Servies
+ */
+
+/* ARGSUSED */
+uint64_t
+hvio_iommu_map(devhandle_t dev_hdl, pxu_t *pxu_p, tsbid_t tsbid,
+ pages_t pages, io_attributes_t io_attributes,
+ void *addr, size_t pfn_index, int flag)
+{
+ tsbindex_t tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
+ uint64_t attr = MMU_TTE_V;
+ int i;
+
+ if (io_attributes & PCI_MAP_ATTR_WRITE)
+ attr |= MMU_TTE_W;
+
+ if (flag == MMU_MAP_MP) {
+ ddi_dma_impl_t *mp = (ddi_dma_impl_t *)addr;
+
+ for (i = 0; i < pages; i++, pfn_index++, tsb_index++) {
+ px_iopfn_t pfn = PX_GET_MP_PFN(mp, pfn_index);
+
+ pxu_p->tsb_vaddr[tsb_index] =
+ MMU_PTOB(pfn) | attr;
+ }
+ } else {
+ caddr_t a = (caddr_t)addr;
+
+ for (i = 0; i < pages; i++, a += MMU_PAGE_SIZE, tsb_index++) {
+ px_iopfn_t pfn = hat_getpfnum(kas.a_hat, a);
+
+ pxu_p->tsb_vaddr[tsb_index] =
+ MMU_PTOB(pfn) | attr;
+ }
+ }
+
+ return (H_EOK);
+}
+
+/* ARGSUSED */
+uint64_t
+hvio_iommu_demap(devhandle_t dev_hdl, pxu_t *pxu_p, tsbid_t tsbid,
+ pages_t pages)
+{
+ tsbindex_t tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
+ int i;
+
+ for (i = 0; i < pages; i++, tsb_index++) {
+ pxu_p->tsb_vaddr[tsb_index] = MMU_INVALID_TTE;
+ }
+
+ return (H_EOK);
+}
+
+/* ARGSUSED */
+uint64_t
+hvio_iommu_getmap(devhandle_t dev_hdl, pxu_t *pxu_p, tsbid_t tsbid,
+ io_attributes_t *attributes_p, r_addr_t *r_addr_p)
+{
+ tsbindex_t tsb_index = PCI_TSBID_TO_TSBINDEX(tsbid);
+ uint64_t *tte_addr;
+ uint64_t ret = H_EOK;
+
+ tte_addr = (uint64_t *)(pxu_p->tsb_vaddr) + tsb_index;
+
+ if (*tte_addr & MMU_TTE_V) {
+ *r_addr_p = MMU_TTETOPA(*tte_addr);
+ *attributes_p = (*tte_addr & MMU_TTE_W) ?
+ PCI_MAP_ATTR_WRITE:PCI_MAP_ATTR_READ;
+ } else {
+ *r_addr_p = 0;
+ *attributes_p = 0;
+ ret = H_ENOMAP;
+ }
+
+ return (ret);
+}
+
+/* ARGSUSED */
+uint64_t
+hvio_iommu_getbypass(devhandle_t dev_hdl, r_addr_t ra,
+ io_attributes_t io_attributes, io_addr_t *io_addr_p)
+{
+ uint64_t pfn = MMU_BTOP(ra);
+
+ *io_addr_p = MMU_BYPASS_BASE | ra |
+ (pf_is_memory(pfn) ? 0 : MMU_BYPASS_NONCACHE);
+
+ return (H_EOK);
+}
+
+/*
+ * Generic IO Interrupt Servies
+ */
+
+/*
+ * Converts a device specific interrupt number given by the
+ * arguments devhandle and devino into a system specific ino.
+ */
+/* ARGSUSED */
+uint64_t
+hvio_intr_devino_to_sysino(devhandle_t dev_hdl, pxu_t *pxu_p, devino_t devino,
+ sysino_t *sysino)
+{
+ if (devino > INTERRUPT_MAPPING_ENTRIES) {
+ DBG(DBG_IB, NULL, "ino %x is invalid\n", devino);
+ return (H_ENOINTR);
+ }
+
+ *sysino = DEVINO_TO_SYSINO(pxu_p->portid, devino);
+
+ return (H_EOK);
+}
+
+/*
+ * Returns state in intr_valid_state if the interrupt defined by sysino
+ * is valid (enabled) or not-valid (disabled).
+ */
+uint64_t
+hvio_intr_getvalid(devhandle_t dev_hdl, sysino_t sysino,
+ intr_valid_state_t *intr_valid_state)
+{
+ if (CSRA_BR((caddr_t)dev_hdl, INTERRUPT_MAPPING,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_V)) {
+ *intr_valid_state = INTR_VALID;
+ } else {
+ *intr_valid_state = INTR_NOTVALID;
+ }
+
+ return (H_EOK);
+}
+
+/*
+ * Sets the 'valid' state of the interrupt defined by
+ * the argument sysino to the state defined by the
+ * argument intr_valid_state.
+ */
+uint64_t
+hvio_intr_setvalid(devhandle_t dev_hdl, sysino_t sysino,
+ intr_valid_state_t intr_valid_state)
+{
+ switch (intr_valid_state) {
+ case INTR_VALID:
+ CSRA_BS((caddr_t)dev_hdl, INTERRUPT_MAPPING,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_V);
+ break;
+ case INTR_NOTVALID:
+ CSRA_BC((caddr_t)dev_hdl, INTERRUPT_MAPPING,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_V);
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (H_EOK);
+}
+
+/*
+ * Returns the current state of the interrupt given by the sysino
+ * argument.
+ */
+uint64_t
+hvio_intr_getstate(devhandle_t dev_hdl, sysino_t sysino,
+ intr_state_t *intr_state)
+{
+ intr_state_t state;
+
+ state = CSRA_FR((caddr_t)dev_hdl, INTERRUPT_CLEAR,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_INT_STATE);
+
+ switch (state) {
+ case INTERRUPT_IDLE_STATE:
+ *intr_state = INTR_IDLE_STATE;
+ break;
+ case INTERRUPT_RECEIVED_STATE:
+ *intr_state = INTR_RECEIVED_STATE;
+ break;
+ case INTERRUPT_PENDING_STATE:
+ *intr_state = INTR_DELIVERED_STATE;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (H_EOK);
+
+}
+
+/*
+ * Sets the current state of the interrupt given by the sysino
+ * argument to the value given in the argument intr_state.
+ *
+ * Note: Setting the state to INTR_IDLE clears any pending
+ * interrupt for sysino.
+ */
+uint64_t
+hvio_intr_setstate(devhandle_t dev_hdl, sysino_t sysino,
+ intr_state_t intr_state)
+{
+ intr_state_t state;
+
+ switch (intr_state) {
+ case INTR_IDLE_STATE:
+ state = INTERRUPT_IDLE_STATE;
+ break;
+ case INTR_DELIVERED_STATE:
+ state = INTERRUPT_PENDING_STATE;
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ CSRA_FS((caddr_t)dev_hdl, INTERRUPT_CLEAR,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_INT_STATE, state);
+
+ return (H_EOK);
+}
+
+/*
+ * Returns the cpuid that is the current target of the
+ * interrupt given by the sysino argument.
+ *
+ * The cpuid value returned is undefined if the target
+ * has not been set via intr_settarget.
+ */
+uint64_t
+hvio_intr_gettarget(devhandle_t dev_hdl, sysino_t sysino, cpuid_t *cpuid)
+{
+ *cpuid = CSRA_FR((caddr_t)dev_hdl, INTERRUPT_MAPPING,
+ SYSINO_TO_DEVINO(sysino), ENTRIES_T_JPID);
+
+ return (H_EOK);
+}
+
+/*
+ * Set the target cpu for the interrupt defined by the argument
+ * sysino to the target cpu value defined by the argument cpuid.
+ */
+uint64_t
+hvio_intr_settarget(devhandle_t dev_hdl, sysino_t sysino, cpuid_t cpuid)
+{
+
+ uint64_t val, intr_controller;
+ uint32_t ino = SYSINO_TO_DEVINO(sysino);
+
+ /*
+ * For now, we assign interrupt controller in a round
+ * robin fashion. Later, we may need to come up with
+ * a more efficient assignment algorithm.
+ */
+ intr_controller = 0x1ull << (cpuid % 4);
+
+ val = (((cpuid & INTERRUPT_MAPPING_ENTRIES_T_JPID_MASK) <<
+ INTERRUPT_MAPPING_ENTRIES_T_JPID) |
+ ((intr_controller & INTERRUPT_MAPPING_ENTRIES_INT_CNTRL_NUM_MASK)
+ << INTERRUPT_MAPPING_ENTRIES_INT_CNTRL_NUM));
+
+ /* For EQ interrupts, set DATA MONDO bit */
+ if ((ino >= PX_DEFAULT_MSIQ_1ST_DEVINO) &&
+ (ino < (PX_DEFAULT_MSIQ_1ST_DEVINO + PX_DEFAULT_MSIQ_CNT)))
+ val |= (0x1ull << INTERRUPT_MAPPING_ENTRIES_MDO_MODE);
+
+ CSRA_XS((caddr_t)dev_hdl, INTERRUPT_MAPPING, ino, val);
+
+ return (H_EOK);
+}
+
+/*
+ * MSIQ Functions:
+ */
+uint64_t
+hvio_msiq_init(devhandle_t dev_hdl, pxu_t *pxu_p)
+{
+ CSRA_XS((caddr_t)dev_hdl, EVENT_QUEUE_BASE_ADDRESS, 0,
+ (uint64_t)pxu_p->msiq_mapped_p);
+ DBG(DBG_IB, NULL,
+ "hvio_msiq_init: EVENT_QUEUE_BASE_ADDRESS 0x%llx\n",
+ CSR_XR((caddr_t)dev_hdl, EVENT_QUEUE_BASE_ADDRESS));
+
+ CSRA_XS((caddr_t)dev_hdl, INTERRUPT_MONDO_DATA_0, 0,
+ (uint64_t)ID_TO_IGN(pxu_p->portid) << INO_BITS);
+ DBG(DBG_IB, NULL, "hvio_msiq_init: "
+ "INTERRUPT_MONDO_DATA_0: 0x%llx\n",
+ CSR_XR((caddr_t)dev_hdl, INTERRUPT_MONDO_DATA_0));
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msiq_getvalid(devhandle_t dev_hdl, msiqid_t msiq_id,
+ pci_msiq_valid_state_t *msiq_valid_state)
+{
+ uint32_t eq_state;
+ uint64_t ret = H_EOK;
+
+ eq_state = CSRA_FR((caddr_t)dev_hdl, EVENT_QUEUE_STATE,
+ msiq_id, ENTRIES_STATE);
+
+ switch (eq_state) {
+ case EQ_IDLE_STATE:
+ *msiq_valid_state = PCI_MSIQ_INVALID;
+ break;
+ case EQ_ACTIVE_STATE:
+ case EQ_ERROR_STATE:
+ *msiq_valid_state = PCI_MSIQ_VALID;
+ break;
+ default:
+ ret = H_EIO;
+ break;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msiq_setvalid(devhandle_t dev_hdl, msiqid_t msiq_id,
+ pci_msiq_valid_state_t msiq_valid_state)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msiq_valid_state) {
+ case PCI_MSIQ_INVALID:
+ CSRA_BS((caddr_t)dev_hdl, EVENT_QUEUE_CONTROL_CLEAR,
+ msiq_id, ENTRIES_DIS);
+ break;
+ case PCI_MSIQ_VALID:
+ CSRA_BS((caddr_t)dev_hdl, EVENT_QUEUE_CONTROL_SET,
+ msiq_id, ENTRIES_EN);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msiq_getstate(devhandle_t dev_hdl, msiqid_t msiq_id,
+ pci_msiq_state_t *msiq_state)
+{
+ uint32_t eq_state;
+ uint64_t ret = H_EOK;
+
+ eq_state = CSRA_FR((caddr_t)dev_hdl, EVENT_QUEUE_STATE,
+ msiq_id, ENTRIES_STATE);
+
+ switch (eq_state) {
+ case EQ_IDLE_STATE:
+ case EQ_ACTIVE_STATE:
+ *msiq_state = PCI_MSIQ_STATE_IDLE;
+ break;
+ case EQ_ERROR_STATE:
+ *msiq_state = PCI_MSIQ_STATE_ERROR;
+ break;
+ default:
+ ret = H_EIO;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msiq_setstate(devhandle_t dev_hdl, msiqid_t msiq_id,
+ pci_msiq_state_t msiq_state)
+{
+ uint32_t eq_state;
+ uint64_t ret = H_EOK;
+
+ eq_state = CSRA_FR((caddr_t)dev_hdl, EVENT_QUEUE_STATE,
+ msiq_id, ENTRIES_STATE);
+
+ switch (eq_state) {
+ case EQ_IDLE_STATE:
+ if (msiq_state == PCI_MSIQ_STATE_ERROR)
+ ret = H_EIO;
+ break;
+ case EQ_ACTIVE_STATE:
+ if (msiq_state == PCI_MSIQ_STATE_ERROR)
+ CSRA_BS((caddr_t)dev_hdl, EVENT_QUEUE_CONTROL_SET,
+ msiq_id, ENTRIES_ENOVERR);
+ else
+ ret = H_EIO;
+ break;
+ case EQ_ERROR_STATE:
+ if (msiq_state == PCI_MSIQ_STATE_IDLE)
+ CSRA_BS((caddr_t)dev_hdl, EVENT_QUEUE_CONTROL_CLEAR,
+ msiq_id, ENTRIES_E2I);
+ else
+ ret = H_EIO;
+ break;
+ default:
+ ret = H_EIO;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msiq_gethead(devhandle_t dev_hdl, msiqid_t msiq_id,
+ msiqhead_t *msiq_head)
+{
+ *msiq_head = CSRA_FR((caddr_t)dev_hdl, EVENT_QUEUE_HEAD,
+ msiq_id, ENTRIES_HEAD);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msiq_sethead(devhandle_t dev_hdl, msiqid_t msiq_id,
+ msiqhead_t msiq_head)
+{
+ CSRA_FS((caddr_t)dev_hdl, EVENT_QUEUE_HEAD, msiq_id,
+ ENTRIES_HEAD, msiq_head);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msiq_gettail(devhandle_t dev_hdl, msiqid_t msiq_id,
+ msiqtail_t *msiq_tail)
+{
+ *msiq_tail = CSRA_FR((caddr_t)dev_hdl, EVENT_QUEUE_TAIL,
+ msiq_id, ENTRIES_TAIL);
+
+ return (H_EOK);
+}
+
+/*
+ * MSI Functions:
+ */
+uint64_t
+hvio_msi_init(devhandle_t dev_hdl, uint64_t addr32, uint64_t addr64)
+{
+ /* PCI MEM 32 resources to perform 32 bit MSI transactions */
+ CSRA_FS((caddr_t)dev_hdl, MSI_32_BIT_ADDRESS, 0,
+ ADDR, (uint64_t)addr32 >> MSI_32_BIT_ADDRESS_ADDR);
+ DBG(DBG_IB, NULL, "hvio_msiq_init: MSI_32_BIT_ADDRESS: 0x%llx\n",
+ CSR_XR((caddr_t)dev_hdl, MSI_32_BIT_ADDRESS));
+
+ /* Reserve PCI MEM 64 resources to perform 64 bit MSI transactions */
+ CSRA_FS((caddr_t)dev_hdl, MSI_64_BIT_ADDRESS, 0,
+ ADDR, (uint64_t)addr64 >> MSI_64_BIT_ADDRESS_ADDR);
+ DBG(DBG_IB, NULL, "hvio_msiq_init: MSI_64_BIT_ADDRESS: 0x%llx\n",
+ CSR_XR((caddr_t)dev_hdl, MSI_64_BIT_ADDRESS));
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msi_getmsiq(devhandle_t dev_hdl, msinum_t msi_num,
+ msiqid_t *msiq_id)
+{
+ *msiq_id = CSRA_FR((caddr_t)dev_hdl, MSI_MAPPING,
+ msi_num, ENTRIES_EQNUM);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msi_setmsiq(devhandle_t dev_hdl, msinum_t msi_num,
+ msiqid_t msiq_id)
+{
+ CSRA_FS((caddr_t)dev_hdl, MSI_MAPPING, msi_num,
+ ENTRIES_EQNUM, msiq_id);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msi_getvalid(devhandle_t dev_hdl, msinum_t msi_num,
+ pci_msi_valid_state_t *msi_valid_state)
+{
+ *msi_valid_state = CSRA_BR((caddr_t)dev_hdl, MSI_MAPPING,
+ msi_num, ENTRIES_V);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msi_setvalid(devhandle_t dev_hdl, msinum_t msi_num,
+ pci_msi_valid_state_t msi_valid_state)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msi_valid_state) {
+ case PCI_MSI_VALID:
+ CSRA_BS((caddr_t)dev_hdl, MSI_MAPPING, msi_num,
+ ENTRIES_V);
+ break;
+ case PCI_MSI_INVALID:
+ CSRA_BC((caddr_t)dev_hdl, MSI_MAPPING, msi_num,
+ ENTRIES_V);
+ break;
+ default:
+ ret = H_EINVAL;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msi_getstate(devhandle_t dev_hdl, msinum_t msi_num,
+ pci_msi_state_t *msi_state)
+{
+ *msi_state = CSRA_BR((caddr_t)dev_hdl, MSI_MAPPING,
+ msi_num, ENTRIES_EQWR_N);
+
+ return (H_EOK);
+}
+
+uint64_t
+hvio_msi_setstate(devhandle_t dev_hdl, msinum_t msi_num,
+ pci_msi_state_t msi_state)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msi_state) {
+ case PCI_MSI_STATE_IDLE:
+ CSRA_BS((caddr_t)dev_hdl, MSI_CLEAR, msi_num,
+ ENTRIES_EQWR_N);
+ break;
+ case PCI_MSI_STATE_DELIVERED:
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+/*
+ * MSG Functions:
+ */
+uint64_t
+hvio_msg_getmsiq(devhandle_t dev_hdl, pcie_msg_type_t msg_type,
+ msiqid_t *msiq_id)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msg_type) {
+ case PCIE_PME_MSG:
+ *msiq_id = CSR_FR((caddr_t)dev_hdl, PM_PME_MAPPING, EQNUM);
+ break;
+ case PCIE_PME_ACK_MSG:
+ *msiq_id = CSR_FR((caddr_t)dev_hdl, PME_TO_ACK_MAPPING,
+ EQNUM);
+ break;
+ case PCIE_CORR_MSG:
+ *msiq_id = CSR_FR((caddr_t)dev_hdl, ERR_COR_MAPPING, EQNUM);
+ break;
+ case PCIE_NONFATAL_MSG:
+ *msiq_id = CSR_FR((caddr_t)dev_hdl, ERR_NONFATAL_MAPPING,
+ EQNUM);
+ break;
+ case PCIE_FATAL_MSG:
+ *msiq_id = CSR_FR((caddr_t)dev_hdl, ERR_FATAL_MAPPING, EQNUM);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msg_setmsiq(devhandle_t dev_hdl, pcie_msg_type_t msg_type,
+ msiqid_t msiq_id)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msg_type) {
+ case PCIE_PME_MSG:
+ CSR_FS((caddr_t)dev_hdl, PM_PME_MAPPING, EQNUM, msiq_id);
+ break;
+ case PCIE_PME_ACK_MSG:
+ CSR_FS((caddr_t)dev_hdl, PME_TO_ACK_MAPPING, EQNUM, msiq_id);
+ break;
+ case PCIE_CORR_MSG:
+ CSR_FS((caddr_t)dev_hdl, ERR_COR_MAPPING, EQNUM, msiq_id);
+ break;
+ case PCIE_NONFATAL_MSG:
+ CSR_FS((caddr_t)dev_hdl, ERR_NONFATAL_MAPPING, EQNUM, msiq_id);
+ break;
+ case PCIE_FATAL_MSG:
+ CSR_FS((caddr_t)dev_hdl, ERR_FATAL_MAPPING, EQNUM, msiq_id);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msg_getvalid(devhandle_t dev_hdl, pcie_msg_type_t msg_type,
+ pcie_msg_valid_state_t *msg_valid_state)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msg_type) {
+ case PCIE_PME_MSG:
+ *msg_valid_state = CSR_BR((caddr_t)dev_hdl, PM_PME_MAPPING, V);
+ break;
+ case PCIE_PME_ACK_MSG:
+ *msg_valid_state = CSR_BR((caddr_t)dev_hdl,
+ PME_TO_ACK_MAPPING, V);
+ break;
+ case PCIE_CORR_MSG:
+ *msg_valid_state = CSR_BR((caddr_t)dev_hdl, ERR_COR_MAPPING, V);
+ break;
+ case PCIE_NONFATAL_MSG:
+ *msg_valid_state = CSR_BR((caddr_t)dev_hdl,
+ ERR_NONFATAL_MAPPING, V);
+ break;
+ case PCIE_FATAL_MSG:
+ *msg_valid_state = CSR_BR((caddr_t)dev_hdl, ERR_FATAL_MAPPING,
+ V);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ return (ret);
+}
+
+uint64_t
+hvio_msg_setvalid(devhandle_t dev_hdl, pcie_msg_type_t msg_type,
+ pcie_msg_valid_state_t msg_valid_state)
+{
+ uint64_t ret = H_EOK;
+
+ switch (msg_valid_state) {
+ case PCIE_MSG_VALID:
+ switch (msg_type) {
+ case PCIE_PME_MSG:
+ CSR_BS((caddr_t)dev_hdl, PM_PME_MAPPING, V);
+ break;
+ case PCIE_PME_ACK_MSG:
+ CSR_BS((caddr_t)dev_hdl, PME_TO_ACK_MAPPING, V);
+ break;
+ case PCIE_CORR_MSG:
+ CSR_BS((caddr_t)dev_hdl, ERR_COR_MAPPING, V);
+ break;
+ case PCIE_NONFATAL_MSG:
+ CSR_BS((caddr_t)dev_hdl, ERR_NONFATAL_MAPPING, V);
+ break;
+ case PCIE_FATAL_MSG:
+ CSR_BS((caddr_t)dev_hdl, ERR_FATAL_MAPPING, V);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+
+ break;
+ case PCIE_MSG_INVALID:
+ switch (msg_type) {
+ case PCIE_PME_MSG:
+ CSR_BC((caddr_t)dev_hdl, PM_PME_MAPPING, V);
+ break;
+ case PCIE_PME_ACK_MSG:
+ CSR_BC((caddr_t)dev_hdl, PME_TO_ACK_MAPPING, V);
+ break;
+ case PCIE_CORR_MSG:
+ CSR_BC((caddr_t)dev_hdl, ERR_COR_MAPPING, V);
+ break;
+ case PCIE_NONFATAL_MSG:
+ CSR_BC((caddr_t)dev_hdl, ERR_NONFATAL_MAPPING, V);
+ break;
+ case PCIE_FATAL_MSG:
+ CSR_BC((caddr_t)dev_hdl, ERR_FATAL_MAPPING, V);
+ break;
+ default:
+ ret = H_EINVAL;
+ break;
+ }
+ break;
+ default:
+ ret = H_EINVAL;
+ }
+
+ return (ret);
+}
+
+/*
+ * Suspend/Resume Functions:
+ * (pec, mmu, ib)
+ * cb
+ * Registers saved have all been touched in the XXX_init functions.
+ */
+uint64_t
+hvio_suspend(devhandle_t dev_hdl, pxu_t *pxu_p)
+{
+ uint64_t *config_state;
+ int total_size;
+ int i;
+
+ if (msiq_suspend(dev_hdl, pxu_p) != H_EOK)
+ return (H_EIO);
+
+ total_size = PEC_SIZE + MMU_SIZE + IB_SIZE + IB_MAP_SIZE;
+ config_state = kmem_zalloc(total_size, KM_NOSLEEP);
+
+ if (config_state == NULL) {
+ return (H_EIO);
+ }
+
+ /*
+ * Soft state for suspend/resume from pxu_t
+ * uint64_t *pec_config_state;
+ * uint64_t *mmu_config_state;
+ * uint64_t *ib_intr_map;
+ * uint64_t *ib_config_state;
+ * uint64_t *xcb_config_state;
+ */
+
+ /* Save the PEC configuration states */
+ pxu_p->pec_config_state = config_state;
+ for (i = 0; i < PEC_KEYS; i++) {
+ pxu_p->pec_config_state[i] =
+ CSR_XR((caddr_t)dev_hdl, pec_config_state_regs[i]);
+ }
+
+ /* Save the MMU configuration states */
+ pxu_p->mmu_config_state = pxu_p->pec_config_state + PEC_KEYS;
+ for (i = 0; i < MMU_KEYS; i++) {
+ pxu_p->mmu_config_state[i] =
+ CSR_XR((caddr_t)dev_hdl, mmu_config_state_regs[i]);
+ }
+
+ /* Save the interrupt mapping registers */
+ pxu_p->ib_intr_map = pxu_p->mmu_config_state + MMU_KEYS;
+ for (i = 0; i < INTERRUPT_MAPPING_ENTRIES; i++) {
+ pxu_p->ib_intr_map[i] =
+ CSRA_XR((caddr_t)dev_hdl, INTERRUPT_MAPPING, i);
+ }
+
+ /* Save the IB configuration states */
+ pxu_p->ib_config_state = pxu_p->ib_intr_map + INTERRUPT_MAPPING_ENTRIES;
+ for (i = 0; i < IB_KEYS; i++) {
+ pxu_p->ib_config_state[i] =
+ CSR_XR((caddr_t)dev_hdl, ib_config_state_regs[i]);
+ }
+
+ return (H_EOK);
+}
+
+void
+hvio_resume(devhandle_t dev_hdl, devino_t devino, pxu_t *pxu_p)
+{
+ int total_size;
+ sysino_t sysino;
+ int i;
+
+ /* Make sure that suspend actually did occur */
+ if (!pxu_p->pec_config_state) {
+ return;
+ }
+
+ /* Restore IB configuration states */
+ for (i = 0; i < IB_KEYS; i++) {
+ CSR_XS((caddr_t)dev_hdl, ib_config_state_regs[i],
+ pxu_p->ib_config_state[i]);
+ }
+
+ /*
+ * Restore the interrupt mapping registers
+ * And make sure the intrs are idle.
+ */
+ for (i = 0; i < INTERRUPT_MAPPING_ENTRIES; i++) {
+ CSRA_FS((caddr_t)dev_hdl, INTERRUPT_CLEAR, i,
+ ENTRIES_INT_STATE, INTERRUPT_IDLE_STATE);
+ CSRA_XS((caddr_t)dev_hdl, INTERRUPT_MAPPING, i,
+ pxu_p->ib_intr_map[i]);
+ }
+
+ /* Restore MMU configuration states */
+ /* Clear the cache. */
+ CSR_XS((caddr_t)dev_hdl, MMU_TTE_CACHE_INVALIDATE, -1ull);
+
+ for (i = 0; i < MMU_KEYS; i++) {
+ CSR_XS((caddr_t)dev_hdl, mmu_config_state_regs[i],
+ pxu_p->mmu_config_state[i]);
+ }
+
+ /* Restore PEC configuration states */
+ /* Make sure all reset bits are low until error is detected */
+ CSR_XS((caddr_t)dev_hdl, LPU_RESET, 0ull);
+
+ for (i = 0; i < PEC_KEYS; i++) {
+ CSR_XS((caddr_t)dev_hdl, pec_config_state_regs[i],
+ pxu_p->pec_config_state[i]);
+ }
+
+ /* Enable PCI-E interrupt */
+ (void) hvio_intr_devino_to_sysino(dev_hdl, pxu_p, devino, &sysino);
+
+ (void) hvio_intr_setstate(dev_hdl, sysino, INTR_IDLE_STATE);
+
+ total_size = PEC_SIZE + MMU_SIZE + IB_SIZE + IB_MAP_SIZE;
+ kmem_free(pxu_p->pec_config_state, total_size);
+
+ pxu_p->pec_config_state = NULL;
+ pxu_p->mmu_config_state = NULL;
+ pxu_p->ib_config_state = NULL;
+ pxu_p->ib_intr_map = NULL;
+
+ msiq_resume(dev_hdl, pxu_p);
+}
+
+uint64_t
+hvio_cb_suspend(devhandle_t dev_hdl, pxu_t *pxu_p)
+{
+ uint64_t *config_state;
+ int i;
+
+ config_state = kmem_zalloc(CB_SIZE, KM_NOSLEEP);
+
+ if (config_state == NULL) {
+ return (H_EIO);
+ }
+
+ /* Save the configuration states */
+ pxu_p->xcb_config_state = config_state;
+ for (i = 0; i < CB_KEYS; i++) {
+ pxu_p->xcb_config_state[i] =
+ CSR_XR((caddr_t)dev_hdl, cb_config_state_regs[i]);
+ }
+
+ return (H_EOK);
+}
+
+void
+hvio_cb_resume(devhandle_t pci_dev_hdl, devhandle_t xbus_dev_hdl,
+ devino_t devino, pxu_t *pxu_p)
+{
+ sysino_t sysino;
+ int i;
+
+ /*
+ * No reason to have any reset bits high until an error is
+ * detected on the link.
+ */
+ CSR_XS((caddr_t)xbus_dev_hdl, JBC_ERROR_STATUS_CLEAR, -1ull);
+
+ ASSERT(pxu_p->xcb_config_state);
+
+ /* Restore the configuration states */
+ for (i = 0; i < CB_KEYS; i++) {
+ CSR_XS((caddr_t)xbus_dev_hdl, cb_config_state_regs[i],
+ pxu_p->xcb_config_state[i]);
+ }
+
+ /* Enable XBC interrupt */
+ (void) hvio_intr_devino_to_sysino(pci_dev_hdl, pxu_p, devino, &sysino);
+
+ (void) hvio_intr_setstate(pci_dev_hdl, sysino, INTR_IDLE_STATE);
+
+ kmem_free(pxu_p->xcb_config_state, CB_SIZE);
+
+ pxu_p->xcb_config_state = NULL;
+}
+
+static uint64_t
+msiq_suspend(devhandle_t dev_hdl, pxu_t *pxu_p)
+{
+ size_t bufsz;
+ volatile uint64_t *cur_p;
+ int i;
+
+ bufsz = MSIQ_STATE_SIZE + MSIQ_MAPPING_SIZE + MSIQ_OTHER_SIZE;
+ if ((pxu_p->msiq_config_state = kmem_zalloc(bufsz, KM_NOSLEEP)) ==
+ NULL)
+ return (H_EIO);
+
+ cur_p = pxu_p->msiq_config_state;
+
+ /* Save each EQ state */
+ for (i = 0; i < EVENT_QUEUE_STATE_ENTRIES; i++, cur_p++)
+ *cur_p = CSRA_XR((caddr_t)dev_hdl, EVENT_QUEUE_STATE, i);
+
+ /* Save MSI mapping registers */
+ for (i = 0; i < MSI_MAPPING_ENTRIES; i++, cur_p++)
+ *cur_p = CSRA_XR((caddr_t)dev_hdl, MSI_MAPPING, i);
+
+ /* Save all other MSIQ registers */
+ for (i = 0; i < MSIQ_OTHER_KEYS; i++, cur_p++)
+ *cur_p = CSR_XR((caddr_t)dev_hdl, msiq_config_other_regs[i]);
+ return (H_EOK);
+}
+
+static void
+msiq_resume(devhandle_t dev_hdl, pxu_t *pxu_p)
+{
+ size_t bufsz;
+ uint64_t *cur_p;
+ int i;
+
+ bufsz = MSIQ_STATE_SIZE + MSIQ_MAPPING_SIZE + MSIQ_OTHER_SIZE;
+ cur_p = pxu_p->msiq_config_state;
+ /*
+ * Initialize EQ base address register and
+ * Interrupt Mondo Data 0 register.
+ */
+ (void) hvio_msiq_init(dev_hdl, pxu_p);
+
+ /* Restore EQ states */
+ for (i = 0; i < EVENT_QUEUE_STATE_ENTRIES; i++, cur_p++) {
+ if (((*cur_p) & EVENT_QUEUE_STATE_ENTRIES_STATE_MASK) ==
+ EQ_ACTIVE_STATE) {
+ CSRA_BS((caddr_t)dev_hdl, EVENT_QUEUE_CONTROL_SET,
+ i, ENTRIES_EN);
+ }
+ }
+
+ /* Restore MSI mapping */
+ for (i = 0; i < MSI_MAPPING_ENTRIES; i++, cur_p++)
+ CSRA_XS((caddr_t)dev_hdl, MSI_MAPPING, i, *cur_p);
+
+ /*
+ * Restore all other registers. MSI 32 bit address and
+ * MSI 64 bit address are restored as part of this.
+ */
+ for (i = 0; i < MSIQ_OTHER_KEYS; i++, cur_p++)
+ CSR_XS((caddr_t)dev_hdl, msiq_config_other_regs[i], *cur_p);
+
+ kmem_free(pxu_p->msiq_config_state, bufsz);
+ pxu_p->msiq_config_state = NULL;
+}
+
+/*
+ * sends PME_Turn_Off message to put the link in L2/L3 ready state.
+ * called by px_goto_l23ready.
+ * returns DDI_SUCCESS or DDI_FAILURE
+ */
+int
+px_send_pme_turnoff(caddr_t csr_base)
+{
+ volatile uint64_t reg;
+
+ /* TBD: Wait for link to be in L1 state (link status reg) */
+
+ reg = CSR_XR(csr_base, TLU_PME_TURN_OFF_GENERATE);
+ /* If already pending, return failure */
+ if (reg & (1ull << TLU_PME_TURN_OFF_GENERATE_PTO)) {
+ return (DDI_FAILURE);
+ }
+ /* write to PME_Turn_off reg to boradcast */
+ reg |= (1ull << TLU_PME_TURN_OFF_GENERATE_PTO);
+ CSR_XS(csr_base, TLU_PME_TURN_OFF_GENERATE, reg);
+ return (DDI_SUCCESS);
+}