/*
 * Run _EJ0 method to turn off power to the slot.
 */
static ACPI_STATUS
pciehpc_acpi_power_off_slot(pcie_hp_ctrl_t *ctrl_p)
{
	int status = AE_OK;
	pciehpc_acpi_t *acpi_p = ctrl_p->hc_misc_data;
	int dev_state = 0;
	pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];

	PCIE_DBG("turn OFF power to the slot #%d\n", slot_p->hs_phy_slot_num);

	status = AcpiEvaluateObject(acpi_p->slot_dev_obj, "_EJ0", NULL, NULL);

	/* get the state of the device (from _STA method) */
	if (status == AE_OK) {
		if (pciehpc_acpi_get_dev_state(acpi_p->slot_dev_obj,
		    &dev_state) != AE_OK)
			cmn_err(CE_WARN, "failed to get device status "
			    "on slot #%d", slot_p->hs_phy_slot_num);
	}

	PCIE_DBG("(2)device state on slot #%d: 0x%x\n",
	    slot_p->hs_phy_slot_num, dev_state);

	pciehpc_get_slot_state(slot_p);

	if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_POWERED) {
		cmn_err(CE_WARN, "failed to power OFF the slot #%d"
		    "(dev_state 0x%x, ACPI_STATUS 0x%x)",
		    slot_p->hs_phy_slot_num, dev_state, status);
		return (AE_ERROR);
	}

	return (status);
}
/*ARGSUSED*/
static int
pciehpc_acpi_slot_poweroff(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result)
{
	pcie_hp_ctrl_t	*ctrl_p = slot_p->hs_ctrl;
	pcie_bus_t	*bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip);
	uint16_t	status;

	ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex));

	/* get the current state of the slot */
	pciehpc_get_slot_state(slot_p);

	/* check if the slot is already in the state less than 'powered' */
	if (slot_p->hs_info.cn_state < DDI_HP_CN_STATE_POWERED) {
		/* slot is in the 'disconnected' state */
		PCIE_DBG("slot %d already disconnected\n",
		    slot_p->hs_phy_slot_num);
		ASSERT(slot_p->hs_power_led_state == PCIE_HP_LED_OFF);

		*result = slot_p->hs_info.cn_state;
		return (DDI_SUCCESS);
	}

	/* read the Slot Status Register */
	status =  pciehpc_reg_get16(ctrl_p,
	    bus_p->bus_pcie_off + PCIE_SLOTSTS);

	/* make sure the slot has a device present */
	if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) {
		/* slot is empty */
		PCIE_DBG("slot %d is empty", slot_p->hs_phy_slot_num);
		goto cleanup;
	}

	/* turn off power to the slot using ACPI method (EJ0) */
	if (pciehpc_acpi_power_off_slot(ctrl_p) != AE_OK)
		goto cleanup;

	/* get the current state of the slot */
	pciehpc_get_slot_state(slot_p);

	*result = slot_p->hs_info.cn_state;

	return (DDI_SUCCESS);

cleanup:
	return (DDI_FAILURE);
}
void pcie_phy_init(struct msm_pcie_dev_t *dev)
{
	PCIE_DBG(dev, "RC%d: Initializing 28nm ATE phy - 100MHz\n",
		dev->rc_idx);

	/*  1 */
	write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x01);
	/*  2 */
	write_phy(dev->phy, QSERDES_COM_SYS_CLK_CTRL, 0x3e);
	/*  3 */
	write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI, 0x0f);
	/*  4 */
	write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP, 0x23);
	/*  5 */
	write_phy(dev->phy, QSERDES_COM_PLL_IP_SETI, 0x3f);
	/*  6 */
	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL, 0xf3);
	/*  7 */
	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL2, 0x6b);
	/*  8 */
	write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL, 0x10);
	/*  9 */
	write_phy(dev->phy, QSERDES_RX_RX_TERM_HIGHZ_CM_AC_COUPLE, 0x87);
	/* 10 */
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN12, 0x54);
	/* 11 */
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1, 0xa3);
	/* 12 */
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2, 0x1b);
	/* 13 */
	write_phy(dev->phy, PCIE_PHY_SW_RESET,		0x00);
	/* 14 */
	write_phy(dev->phy, PCIE_PHY_START,		0x03);
}
/*
 * This function is similar to pciehpc_slotinfo_init() with some
 * changes:
 *	- no need for kernel thread to handle ATTN button events
 *	- function ops for connect/disconnect are different
 *
 * ASSUMPTION: No conflict in doing reads to HP registers directly.
 * Otherwise, there are no ACPI interfaces to do LED control or to get
 * the hot plug capabilities (ATTN button, MRL, etc.).
 */
static int
pciehpc_acpi_slotinfo_init(pcie_hp_ctrl_t *ctrl_p)
{
	uint32_t	slot_capabilities;
	pcie_hp_slot_t	*slot_p = ctrl_p->hc_slots[0];
	pcie_bus_t	*bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip);

	mutex_enter(&ctrl_p->hc_mutex);
	/*
	 * setup DDI HP framework slot information structure
	 */
	slot_p->hs_device_num = 0;
	slot_p->hs_info.cn_type = DDI_HP_CN_TYPE_PCIE;
	slot_p->hs_info.cn_type_str = PCIE_ACPI_HP_TYPE;
	slot_p->hs_info.cn_child = NULL;

	slot_p->hs_minor =
	    PCI_MINOR_NUM(ddi_get_instance(ctrl_p->hc_dip),
	    slot_p->hs_device_num);

	/* read Slot Capabilities Register */
	slot_capabilities = pciehpc_reg_get32(ctrl_p,
	    bus_p->bus_pcie_off + PCIE_SLOTCAP);

	/* setup slot number/name */
	pciehpc_set_slot_name(ctrl_p);

	/* check if Attn Button present */
	ctrl_p->hc_has_attn = (slot_capabilities &
	    PCIE_SLOTCAP_ATTN_BUTTON) ? B_TRUE : B_FALSE;

	/* check if Manual Retention Latch sensor present */
	ctrl_p->hc_has_mrl = (slot_capabilities & PCIE_SLOTCAP_MRL_SENSOR) ?
	    B_TRUE : B_FALSE;

	/*
	 * PCI-E (draft) version 1.1 defines EMI Lock Present bit
	 * in Slot Capabilities register. Check for it.
	 */
	ctrl_p->hc_has_emi_lock = (slot_capabilities &
	    PCIE_SLOTCAP_EMI_LOCK_PRESENT) ? B_TRUE : B_FALSE;

	/* get current slot state from the hw */
	pciehpc_get_slot_state(slot_p);
	if (slot_p->hs_info.cn_state >= DDI_HP_CN_STATE_ENABLED)
		slot_p->hs_condition = AP_COND_OK;

	mutex_exit(&ctrl_p->hc_mutex);

	/* setup Notify() handler for hot plug events from ACPI BIOS */
	if (pciehpc_acpi_install_event_handler(ctrl_p) != AE_OK)
		return (DDI_FAILURE);

	PCIE_DBG("ACPI hot plug is enabled for slot #%d\n",
	    slot_p->hs_phy_slot_num);

	return (DDI_SUCCESS);
}
void pcie_phy_init(struct msm_pcie_dev_t *dev)
{

	PCIE_DBG(dev, "RC%d: Initializing 20nm QMP phy - 19.2MHz\n",
		dev->rc_idx);

	write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL, 0x03);

	write_phy(dev->phy, QSERDES_COM_SYSCLK_EN_SEL_TXBAND, 0x08);
	write_phy(dev->phy, QSERDES_COM_DEC_START1, 0x82);
	write_phy(dev->phy, QSERDES_COM_DEC_START2, 0x03);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START1, 0xD5);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START2, 0xAA);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START3, 0x4D);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP_EN, 0x01);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP1, 0x2B);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP2, 0x68);
	write_phy(dev->phy, QSERDES_COM_PLL_CRCTRL, 0x7C);
	write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI, 0x02);
	write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP, 0x1F);
	write_phy(dev->phy, QSERDES_COM_PLL_CP_SETP, 0x0F);
	write_phy(dev->phy, QSERDES_COM_PLL_IP_SETI, 0x01);
	write_phy(dev->phy, QSERDES_COM_IE_TRIM, 0x0F);
	write_phy(dev->phy, QSERDES_COM_IP_TRIM, 0x0F);
	write_phy(dev->phy, QSERDES_COM_PLL_CNTRL, 0x46);

	/* CDR Settings */
	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL1, 0xF3);
	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL_HALF, 0x2B);

	/* Calibration Settings */
	write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL, 0x90);
	write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL2, 0x05);

	/* Additional writes */
	write_phy(dev->phy, QSERDES_COM_RES_CODE_START_SEG1, 0x20);
	write_phy(dev->phy, QSERDES_COM_RES_CODE_CAL_CSR, 0x77);
	write_phy(dev->phy, QSERDES_COM_RES_TRIM_CONTROL, 0x15);
	write_phy(dev->phy, QSERDES_TX_RCV_DETECT_LVL, 0x03);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN1_LSB, 0xFF);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN1_MSB, 0x1F);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN2_LSB, 0xFF);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN2_MSB, 0x00);
	write_phy(dev->phy, QSERDES_RX_RX_EQU_ADAPTOR_CNTRL2, 0x1A);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_OFFSET_ADAPTOR_CNTRL1, 0x80);
	write_phy(dev->phy, QSERDES_RX_SIGDET_ENABLES, 0x40);
	write_phy(dev->phy, QSERDES_RX_SIGDET_CNTRL, 0x70);
	write_phy(dev->phy, QSERDES_RX_SIGDET_DEGLITCH_CNTRL, 0x06);
	write_phy(dev->phy, QSERDES_COM_PLL_RXTXEPCLK_EN, 0x10);
	write_phy(dev->phy, PCIE_PHY_ENDPOINT_REFCLK_DRIVE, 0x10);
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1, 0x23);
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2, 0xCB);
	write_phy(dev->phy, QSERDES_RX_RX_RCVR_IQ_EN, 0x31);

	write_phy(dev->phy, PCIE_PHY_SW_RESET, 0x00);
	write_phy(dev->phy, PCIE_PHY_START, 0x03);
}
static void
pciehpc_acpi_uninstall_event_handler(pcie_hp_ctrl_t *ctrl_p)
{
	pciehpc_acpi_t *acpi_p = ctrl_p->hc_misc_data;
	pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];

	PCIE_DBG("Uninstall event handler for slot #%d\n",
	    slot_p->hs_phy_slot_num);
	(void) AcpiRemoveNotifyHandler(acpi_p->slot_dev_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler);
	(void) AcpiRemoveNotifyHandler(acpi_p->bus_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler);
}
示例#7
0
文件: pcie_irq.c 项目: Aetos7/Matr1x
uint32_t __init msm_pcie_irq_init(struct msm_pcie_dev_t *dev)
{
	int i, rc;

	PCIE_DBG("\n");

	/* program MSI controller and enable all interrupts */
	writel_relaxed(MSM_PCIE_MSI_PHY, dev->pcie20 + PCIE20_MSI_CTRL_ADDR);
	writel_relaxed(0, dev->pcie20 + PCIE20_MSI_CTRL_UPPER_ADDR);

	for (i = 0; i < PCIE20_MSI_CTRL_MAX; i++)
		writel_relaxed(~0, dev->pcie20 +
			       PCIE20_MSI_CTRL_INTR_EN + (i * 12));

	/* ensure that hardware is configured before proceeding */
	wmb();

	/* register handler for physical MSI interrupt line */
	rc = request_irq(PCIE20_INT_MSI, handle_msi_irq, IRQF_TRIGGER_RISING,
			 "msm_pcie_msi", dev);
	if (rc) {
		pr_err("Unable to allocate msi interrupt\n");
		goto out;
	}

	/* register handler for PCIE_WAKE_N interrupt line */
	rc = request_irq(dev->wake_n, handle_wake_irq, IRQF_TRIGGER_FALLING,
			 "msm_pcie_wake", dev);
	if (rc) {
		pr_err("Unable to allocate wake interrupt\n");
		free_irq(PCIE20_INT_MSI, dev);
		goto out;
	}

	enable_irq_wake(dev->wake_n);

	/* PCIE_WAKE_N should be enabled only during system suspend */
	disable_irq(dev->wake_n);
out:
	return rc;
}
void pcie_phy_init(struct msm_pcie_dev_t *dev)
{

	PCIE_DBG(dev, "RC%d: Initializing 28nm QMP phy - 19.2MHz\n",
		dev->rc_idx);

	write_phy(dev->phy, PCIE_PHY_POWER_DOWN_CONTROL,		0x03);
	write_phy(dev->phy, QSERDES_COM_SYSCLK_EN_SEL,		0x08);
	write_phy(dev->phy, QSERDES_COM_DEC_START1,			0x82);
	write_phy(dev->phy, QSERDES_COM_DEC_START2,			0x03);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START1,		0xd5);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START2,		0xaa);
	write_phy(dev->phy, QSERDES_COM_DIV_FRAC_START3,		0x13);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP_EN,		0x01);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP1,		0x2b);
	write_phy(dev->phy, QSERDES_COM_PLLLOCK_CMP2,		0x68);
	write_phy(dev->phy, QSERDES_COM_PLL_CRCTRL,			0xff);
	write_phy(dev->phy, QSERDES_COM_PLL_CP_SETI,		0x3f);
	write_phy(dev->phy, QSERDES_COM_PLL_IP_SETP,		0x07);
	write_phy(dev->phy, QSERDES_COM_PLL_CP_SETP,		0x03);

	if(dev->rc_idx == 1) {
		write_phy(dev->phy, QSERDES_TX_TX_EMP_POST1_LVL,		0x21);
		write_phy(dev->phy, QSERDES_TX_TX_DRV_LVL,		0x18);
	}

	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL,			0xf3);
	write_phy(dev->phy, QSERDES_RX_CDR_CONTROL2,		0x6b);
	write_phy(dev->phy, QSERDES_COM_RESETSM_CNTRL,		0x10);
	write_phy(dev->phy, QSERDES_RX_RX_TERM_HIGHZ_CM_AC_COUPLE,	0x87);
	write_phy(dev->phy, QSERDES_RX_RX_EQ_GAIN12,		0x54);
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG1,		0xa3);
	write_phy(dev->phy, PCIE_PHY_POWER_STATE_CONFIG2,		0x4b);
	if(dev->rc_idx == 0) {
		write_phy(dev->phy, QSERDES_RX_SIGDET_CNTRL,		0x50);
	}
	write_phy(dev->phy, QSERDES_COM_PLL_RXTXEPCLK_EN,		0x10);
	write_phy(dev->phy, PCIE_PHY_ENDPOINT_REFCLK_DRIVE,		0x10);
	write_phy(dev->phy, PCIE_PHY_SW_RESET,			0x00);
	write_phy(dev->phy, PCIE_PHY_START,				0x03);
}
/*
 * Install event handler for the hot plug events on the bus node as well
 * as device function (dev=0,func=0).
 */
static ACPI_STATUS
pciehpc_acpi_install_event_handler(pcie_hp_ctrl_t *ctrl_p)
{
	pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];
	int status = AE_OK;
	pciehpc_acpi_t *acpi_p;

	PCIE_DBG("install event handler for slot %d\n",
	    slot_p->hs_phy_slot_num);
	acpi_p = ctrl_p->hc_misc_data;
	if (acpi_p->slot_dev_obj == NULL)
		return (AE_NOT_FOUND);

	/*
	 * Install event hanlder for events on the bus object.
	 * (Note: Insert event (hot-insert) is delivered on this object)
	 */
	status = AcpiInstallNotifyHandler(acpi_p->slot_dev_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler, (void *)ctrl_p);
	if (status != AE_OK)
		goto cleanup;

	/*
	 * Install event hanlder for events on the device function object.
	 * (Note: Eject device event (hot-remove) is delivered on this object)
	 *
	 * NOTE: Here the assumption is that Notify events are delivered
	 * on all of the 8 possible device functions so, subscribing to
	 * one of them is sufficient.
	 */
	status = AcpiInstallNotifyHandler(acpi_p->bus_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler, (void *)ctrl_p);
	return (status);

cleanup:
	(void) AcpiRemoveNotifyHandler(acpi_p->slot_dev_obj,
	    ACPI_SYSTEM_NOTIFY, pciehpc_acpi_notify_handler);
	return (status);
}
示例#10
0
文件: pcie_irq.c 项目: Aetos7/Matr1x
/* hookup to linux pci msi framework */
int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
{
	int irq;
	struct msi_msg msg;

	irq = msm_pcie_create_irq();
	if (irq < 0)
		return irq;

	PCIE_DBG("irq %d allocated\n", irq);

	irq_set_msi_desc(irq, desc);

	/* write msi vector and data */
	msg.address_hi = 0;
	msg.address_lo = MSM_PCIE_MSI_PHY;
	msg.data = irq - MSM_PCIE_MSI_INT(0);
	write_msi_msg(irq, &msg);

	irq_set_chip_and_handler(irq, &pcie_msi_chip, handle_simple_irq);
	set_irq_flags(irq, IRQF_VALID);
	return 0;
}
示例#11
0
文件: pcie_irq.c 项目: Aetos7/Matr1x
static irqreturn_t handle_wake_irq(int irq, void *data)
{
	PCIE_DBG("\n");
	return IRQ_HANDLED;
}
示例#12
0
文件: pcie_irq.c 项目: Aetos7/Matr1x
/* hookup to linux pci msi framework */
void arch_teardown_msi_irq(unsigned int irq)
{
	PCIE_DBG("irq %d deallocated\n", irq);
	msm_pcie_destroy_irq(irq);
}
void pcie_phy_dump(struct msm_pcie_dev_t *dev)
{
	int i;
	int control_offset[2] = {0x60, 0x70};

	PCIE_DBG(dev, "RC%d\n", dev->rc_idx);

	for (i = 0; i < 2; i++) {
		write_phy(dev->phy, PCIE_PHY_TEST_CONTROL, control_offset[i]);
		PCIE_REG(dev, "RC%d: TEST_CONTROL: 0x%08x\n",
			 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_TEST_CONTROL));
		PCIE_REG(dev, "RC%d: DEBUG_BUS_0_STATUS: 0x%08x\n",
			 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_DEBUG_BUS_0_STATUS));
		PCIE_REG(dev, "RC%d: DEBUG_BUS_1_STATUS: 0x%08x\n",
			 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_DEBUG_BUS_1_STATUS));
		PCIE_REG(dev, "RC%d: DEBUG_BUS_2_STATUS: 0x%08x\n",
			 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_DEBUG_BUS_2_STATUS));
		PCIE_REG(dev, "RC%d: DEBUG_BUS_3_STATUS: 0x%08x\n",
			 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_DEBUG_BUS_3_STATUS));
	}
	PCIE_REG(dev, "RC%d QSERDES_COM_PLL_VCO_HIGH: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_COM_PLL_VCO_HIGH));
	PCIE_REG(dev, "RC%d QSERDES_COM_RESET_SM: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_COM_RESET_SM));
	PCIE_REG(dev, "RC%d QSERDES_RX_PI_CTRL1: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_PI_CTRL1));
	PCIE_REG(dev, "RC%d QSERDES_RX_PI_CTRL2: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_PI_CTRL2));
	PCIE_REG(dev, "RC%d QSERDES_RX_PI_QUAD: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_PI_QUAD));
	PCIE_REG(dev, "RC%d QSERDES_RX_IDATA1: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_IDATA1));
	PCIE_REG(dev, "RC%d QSERDES_RX_IDATA2: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_IDATA2));
	PCIE_REG(dev, "RC%d QSERDES_RX_AUX_DATA1: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_AUX_DATA1));
	PCIE_REG(dev, "RC%d QSERDES_RX_AUX_DATA2: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_AUX_DATA2));
	PCIE_REG(dev, "RC%d QSERDES_RX_AC_JTAG_OUTP: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_AC_JTAG_OUTP));
	PCIE_REG(dev, "RC%d QSERDES_RX_AC_JTAG_OUTN: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_RX_AC_JTAG_OUTN));
	PCIE_REG(dev, "RC%d QSERDES_TX_BIST_STATUS: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_TX_BIST_STATUS));
	PCIE_REG(dev, "RC%d QSERDES_TX_BIST_ERROR_COUNT1: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_TX_BIST_ERROR_COUNT1));
	PCIE_REG(dev, "RC%d QSERDES_TX_BIST_ERROR_COUNT2: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + QSERDES_TX_BIST_ERROR_COUNT2));
	PCIE_REG(dev, "RC%d PCIE_PHY_BIST_CHK_ERR_CNT_L: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_BIST_CHK_ERR_CNT_L));
	PCIE_REG(dev, "RC%d PCIE_PHY_BIST_CHK_ERR_CNT_H: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_BIST_CHK_ERR_CNT_H));
	PCIE_REG(dev, "RC%d PCIE_PHY_BIST_CHK_STATUS: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_BIST_CHK_STATUS));
	PCIE_REG(dev, "RC%d PCIE_PHY_PCS_STATUS: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_PCS_STATUS));
	PCIE_REG(dev, "RC%d PCIE_PHY_REVISION_ID0: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_REVISION_ID0));
	PCIE_REG(dev, "RC%d PCIE_PHY_REVISION_ID1: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_REVISION_ID1));
	PCIE_REG(dev, "RC%d PCIE_PHY_REVISION_ID2: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_REVISION_ID2));
	PCIE_REG(dev, "RC%d PCIE_PHY_REVISION_ID3: 0x%x\n",
		 dev->rc_idx, readl_relaxed(dev->phy + PCIE_PHY_REVISION_ID3));
}
/*ARGSUSED*/
static void
pciehpc_acpi_notify_handler(ACPI_HANDLE device, uint32_t val, void *context)
{
	pcie_hp_ctrl_t *ctrl_p = context;
	pcie_hp_slot_t *slot_p = ctrl_p->hc_slots[0];
	pciehpc_acpi_t *acpi_p;
	ddi_hp_cn_state_t curr_state;
	int dev_state = 0;

	PCIE_DBG("received Notify(%d) event on slot #%d\n",
	    val, slot_p->hs_phy_slot_num);

	mutex_enter(&ctrl_p->hc_mutex);

	/*
	 * get the state of the device (from _STA method)
	 */
	acpi_p = ctrl_p->hc_misc_data;
	if (pciehpc_acpi_get_dev_state(acpi_p->slot_dev_obj,
	    &dev_state) != AE_OK) {
		cmn_err(CE_WARN, "failed to get device status on slot %d",
		    slot_p->hs_phy_slot_num);
	}
	PCIE_DBG("(1)device state on slot #%d: 0x%x\n",
	    slot_p->hs_phy_slot_num, dev_state);

	curr_state = slot_p->hs_info.cn_state;
	pciehpc_get_slot_state(slot_p);

	switch (val) {
	case 0: /* (re)enumerate the device */
	case 3: /* Request Eject */
	{
		ddi_hp_cn_state_t target_state;

		/*
		 * Ignore the event if ATTN button is not present (ACPI BIOS
		 * problem).
		 *
		 * NOTE: This situation has been observed on some platforms
		 * where the ACPI BIOS is generating the event for some other
		 * (non hot-plug) operations (bug).
		 */
		if (ctrl_p->hc_has_attn == B_FALSE) {
			PCIE_DBG("Ignore the unexpected event "
			    "on slot #%d (state 0x%x)",
			    slot_p->hs_phy_slot_num, dev_state);
			break;
		}

		/* send the event to DDI Hotplug framework */
		if (curr_state < DDI_HP_CN_STATE_POWERED) {
			/* Insertion. Upgrade state to ENABLED */
			target_state = DDI_HP_CN_STATE_ENABLED;

			/*
			 * When pressing ATTN button to enable a card, the slot
			 * could be powered. Keep the slot state on PWOERED
			 * other than ENABLED.
			 */
			if (slot_p->hs_info.cn_state == DDI_HP_CN_STATE_ENABLED)
				slot_p->hs_info.cn_state =
				    DDI_HP_CN_STATE_POWERED;
		} else {
			/* Want to remove; Power off Connection */
			target_state = DDI_HP_CN_STATE_EMPTY;
		}

		(void) ndi_hp_state_change_req(slot_p->hs_ctrl->hc_dip,
		    slot_p->hs_info.cn_name,
		    target_state, DDI_HP_REQ_ASYNC);

		break;
	}
	default:
		cmn_err(CE_NOTE, "Unknown Notify() event %d on slot #%d\n",
		    val, slot_p->hs_phy_slot_num);
		break;
	}
	mutex_exit(&ctrl_p->hc_mutex);
}
/*ARGSUSED*/
static int
pciehpc_acpi_slot_poweron(pcie_hp_slot_t *slot_p, ddi_hp_cn_state_t *result)
{
	pcie_hp_ctrl_t	*ctrl_p = slot_p->hs_ctrl;
	pcie_bus_t	*bus_p = PCIE_DIP2BUS(ctrl_p->hc_dip);
	uint16_t	status, control;

	ASSERT(MUTEX_HELD(&ctrl_p->hc_mutex));

	/* get the current state of the slot */
	pciehpc_get_slot_state(slot_p);

	/* check if the slot is already in the 'ENABLED' state */
	if (slot_p->hs_info.cn_state == DDI_HP_CN_STATE_ENABLED) {
		/* slot is already in the 'connected' state */
		PCIE_DBG("slot %d already connected\n",
		    slot_p->hs_phy_slot_num);

		*result = slot_p->hs_info.cn_state;
		return (DDI_SUCCESS);
	}

	/* read the Slot Status Register */
	status =  pciehpc_reg_get16(ctrl_p,
	    bus_p->bus_pcie_off + PCIE_SLOTSTS);

	/* make sure the MRL switch is closed if present */
	if ((ctrl_p->hc_has_mrl) && (status & PCIE_SLOTSTS_MRL_SENSOR_OPEN)) {
		/* MRL switch is open */
		cmn_err(CE_WARN, "MRL switch is open on slot %d",
		    slot_p->hs_phy_slot_num);
		goto cleanup;
	}

	/* make sure the slot has a device present */
	if (!(status & PCIE_SLOTSTS_PRESENCE_DETECTED)) {
		/* slot is empty */
		PCIE_DBG("slot %d is empty\n", slot_p->hs_phy_slot_num);
		goto cleanup;
	}

	/* get the current state of Slot Control Register */
	control =  pciehpc_reg_get16(ctrl_p,
	    bus_p->bus_pcie_off + PCIE_SLOTCTL);

	/* check if the slot's power state is ON */
	if (!(control & PCIE_SLOTCTL_PWR_CONTROL)) {
		/* slot is already powered up */
		PCIE_DBG("slot %d already connected\n",
		    slot_p->hs_phy_slot_num);

		*result = slot_p->hs_info.cn_state;
		return (DDI_SUCCESS);
	}

	/* turn on power to the slot using ACPI method (PS0) */
	if (pciehpc_acpi_power_on_slot(ctrl_p) != AE_OK)
		goto cleanup;

	*result = slot_p->hs_info.cn_state = DDI_HP_CN_STATE_POWERED;
	return (DDI_SUCCESS);

cleanup:
	return (DDI_FAILURE);
}