pciehpc_nvidia.c revision ae115bc77f6fcde83175c75b4206dc2e50747966
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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
* 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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* CK8-04 specific interfaces used in PCIEHPC driver module (X86 only).
*/
#include <sys/autoconf.h>
#include <sys/ddi_impldefs.h>
#include "pciehpc_nvidia.h"
static int ck804_slotinfo_init(pciehpc_t *);
static int ck804_slotinfo_uninit(pciehpc_t *);
static void ck804_slot_refclk(pciehpc_t *, int);
static int ck804_map_regs(pciehpc_t *);
static void ck804_unmap_regs(pciehpc_t *);
static int match_lpc_dev(dev_info_t *, void *);
#ifdef DEBUG
static void ck804_dump_pci_common_config(pciehpc_t *);
static void ck804_dump_pci_device_config(pciehpc_t *);
static void ck804_dump_pci_bridge_config(pciehpc_t *);
static void ck804_dump_hpregs(pciehpc_t *);
static char *pciehpc_led_state_text(hpc_led_state_t);
#endif
/*
* setup CK8-04 specific functions if necessary for this platform.
*/
void
{
int *vendor_id = 0;
int *device_id = 0;
int *revision_id = 0;
/*
* check if this is a ck8-04 platform and revision A3 bridge
* controller
*/
return;
}
return;
}
return;
}
if ((*vendor_id == NVIDIA_VENDOR_ID) &&
(*device_id == CK804_DEVICE_ID) &&
(*revision_id == 0xa3)) {
/*
* Need special handling for CK8-04 native mode hot plug
* operations. Update ops vector.
*/
}
}
/*
* ck804_slot_connect()
*
* Connect power to the PCI-E slot on CK8-04 based platform.
* The current CK8-04 implementations require special sequence
* which is slightly different from the standard sequence.
* This function is equivalent to pciehpc_slot_connect() with
* specific changes for CK8-04 native hot plug implementation.
*
* NOTE: This code may be applicable only on the specific
* implementations of CK8-04. The future revisions of CK8-04
* may be different. For now, this code is used on all CK8-04
* based platforms.
*
* Returns: HPC_SUCCESS if the slot is powered up and enabled.
* HPC_ERR_FAILED if the slot can't be enabled.
*
* (Note: This function is called by HPS framework at kernel context only.)
*/
/*ARGSUSED*/
static int
{
int wait_time;
/* get the current state of the slot */
/* check if the slot is already in the 'connected' state */
/* slot is already in the 'connected' state */
"ck804_slot_connect() slot %d already connected\n",
return (HPC_SUCCESS);
}
/* read the Slot Status Register */
/* make sure the MRL switch is closed if present */
/* MRL switch is open */
goto cleanup;
}
/* make sure the slot has a device present */
if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) {
/* slot is empty */
goto cleanup;
}
/* get the current state of Slot Control Register */
/* check if the slot's power state is ON */
if (!(control & PCIE_SLOTCTL_PWR_CONTROL)) {
/* slot is already powered up */
"ck804_slot_connect() slot %d already connected\n",
return (HPC_SUCCESS);
}
/*
* Enable power to the slot involves:
* 1. Set power LED to blink and ATTN led to OFF.
* 2. Set power control ON in Slot Control Reigster.
* 3. Poll NV_XVR_SLOT_STS_PWROK bit in ext status reg to be up.
* 4. Set power LED to be ON.
* 5. Enable REFCLK for the slot in MCP_NVA_TGIO_CTRL register.
* 6. Set NV_XVR_SLOT_CTRL_SAFE bit in the extended control reg.
* 7. Poll link-up status bit NV_XVR_VEND_XP_DL_UP.
*/
"ck804_slot_connect() x_control %x, x_status %x"
/* make sure REFCLK is off for this slot? */
/* 1. set power LED to blink & ATTN led to OFF */
/* 2. set power control to ON */
/*
* 3. Poll NV_XVR_SLOT_STS_PWROK bit in Extended Slot Status
* register to be up.
*/
for (;;) {
if (x_status & NV_SVR_SLOT_STS_PWROK)
break;
if (wait_time <= 0) {
/* should we turn off power? */
goto cleanup;
}
wait_time -= 10;
}
/* 4. Set power LED to be ON */
/* 5. Enable REFCLK for the slot in MCP_NVA_TGIO_CTRL register */
/* 6. Set NV_XVR_SLOT_CTRL_SAFE bit in the extended control reg */
/* 7. Poll on link-up status bit NV_XVR_VEND_XP_DL_UP */
for (;;) {
if (vend_xp & NV_XVR_VEND_XP_DL_UP)
break; /* link is UP */
if (wait_time <= 0) {
/* should we turn off power? */
goto cleanup;
}
wait_time -= 10;
}
return (HPC_SUCCESS);
return (HPC_ERR_FAILED);
}
/*
* This function is same as pciehpc_slotinfo_init() except
* that it changes the slot_connect/slot_disconnect functions
* to ck804 specific functions and also maps CK8-04 specific
* control registers.
*/
static int
{
(void) pciehpc_slotinfo_init(ctrl_p);
/* map CK8-04 specific control registers */
return (ck804_map_regs(ctrl_p));
}
/*
* This function is same as pciehpc_slotinfo_uninit() except
* that it cleans up ck8-04 specific data for the slot.
*/
static int
{
(void) pciehpc_slotinfo_uninit(ctrl_p);
return (DDI_SUCCESS);
}
/*
* numbers B, C, D and E are valid. This works only for CK8-04.
* Needs work for slots under IO-4.
*/
static void
{
case 0xE:
break;
case 0xD:
break;
case 0xC:
break;
case 0xB:
break;
default:
"ck804_slot_refclk: invalid device number %x\n",
return;
};
switch (cmd) {
case DISABLE_REFCLK:
return;
case ENABLE_REFCLK:
return;
default:
cmd);
return;
}
}
#ifdef DEBUG
static void
{
if (pciehpc_debug <= 2)
return;
}
static void
{
if (pciehpc_debug <= 2)
return;
}
static void
{
if (pciehpc_debug <= 2)
return;
}
/* dump hot plug registers */
static void
{
}
static char *
{
switch (state) {
case HPC_LED_ON:
return ("on");
case HPC_LED_OFF:
return ("off");
case HPC_LED_BLINK:
default:
return ("blink");
}
}
#endif
/*
* ck804_slot_disconnect()
*
* Disconnect power to the slot. This function is equivalent of
* pciehpc_disconnect() with necessary changes specific to CK8-04 native
* hot plug implementation.
*
* Returns: HPC_SUCCESS if the slot is powered up and enabled.
* HPC_ERR_FAILED if the slot can't be enabled.
*
* (Note: This function is called by HPS framework at kernel context only.)
*/
/*ARGSUSED*/
static int
{
int wait_time;
/* get the current state of the slot */
/* check if the slot is already in the 'disconnected' state */
/* slot is in the 'disconnected' state */
"ck804_slot_disconnect(): slot %d already disconnected\n",
return (HPC_SUCCESS);
}
/* read the Slot Status Register */
/* make sure the slot has a device present */
if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) {
/* slot is empty */
"ck804_slot_disconnect(): slot %d is empty\n",
goto cleanup1;
}
/*
* Disable power to the slot involves:
* 1. Set power LED to blink.
* 2. Disable REFCLK for the slot.
* 3. Set power control OFF in Slot Control Reigster and
* wait for Command Completed Interrupt or 1 sec timeout.
* 4. Clear NV_SVR_SLOT_CTRL_SAFE bit in the Ext. Control reg.
* 5. Poll NV_XVR_SLOT_STS_PWROK bit in ext status reg to be down.
* 6. Set POWER led and ATTN led to be OFF.
*/
/* 1. set power LED to blink */
/* 2. Disable REFCLK for the slot */
/* 3. set power control to OFF */
/* 4. Clear NV_SVR_SLOT_CTRL_SAFE bit in NV_SVR_SLOT_CTRL reg */
/* 5. Poll NV_SVR_SLOT_STS_PWROK bit in ext status reg to be off */
for (;;) {
if (!(x_status & NV_SVR_SLOT_STS_PWROK))
break; /* PWROK is cleared */
if (wait_time <= 0) {
" for PWROK to go off on slot %d\n",
goto cleanup2;
}
wait_time -= 10;
}
/* 6. Set power LED to be OFF */
return (HPC_SUCCESS);
return (HPC_ERR_FAILED);
}
/*
* Background:
*
* CK8-04 defines two sets of system control registers (in I/O space)
* that are mapped in and exposed from PCI config space in the ISA
* bridge. One of the I/O BARs (offset 0x68 in PIC-ISA config space)
* defines MCP_NVA_TGIO_CTRL register (offset 0xCC from the I/O BAR)
* that has bits for managing reference clock for all the hot plug slots
* (max of 4 depending on the CK8-04 configuration) during hot plug
* operations.
*
* NOTE: The NVA I/O BAR is located in the PCI-ISA bridge device
* on both CK8-04 and IO-04. Please note that these I/O BARs are
* not regular BARs (BAR0-BAR4) in PCI config space.
*
* Description:
*
* This function finds regspec for NVA I/O BAR in the PCI-ISA
* device node and maps it in. PCI-ISA node appears as a child
* of parent nexus node (i.e child of npe nexus) with a name
* pci10de,51. It assumes the regspec number as 1. So, this
* kind of mapping registers from another device function is
* not a common thing so it is not clean w.r.t DDI but
* there is nothing in DDI that disallows it.
*/
static int
{
/* find the LPC bridge node for this pci-e hierarchy */
return (DDI_FAILURE);
/*
* Map in Analog Control I/O Bar.
*
* NOTE: reg set #0 corresponds to System Control I/O Bar and
* reg set #1 corresponds to Analog Control I/O Bar.
*/
return (DDI_SUCCESS);
}
return (DDI_FAILURE);
}
/*
*/
static void
{
return;
}
static dev_info_t *
{
int count;
return (lpc_dip);
}
/*
* check if the dip matches LPC Bridge node
*/
static int
{
int *vendor_id = 0;
int *device_id = 0;
return (DDI_WALK_TERMINATE);
}
return (DDI_WALK_TERMINATE);
}
if ((*vendor_id == NVIDIA_VENDOR_ID) &&
(*device_id == CK804_DEVICE_ID)) {
return (DDI_WALK_TERMINATE);
}
return (DDI_WALK_PRUNECHILD);
}
static uint16_t
{
}
static void
{
}