📄 pciehp_hpc.c
字号:
if (retval) { err("%s: Cannot check for power fault\n", __FUNCTION__); return retval; } pwr_fault = (u8)((slot_status & PWR_FAULT_DETECTED) >> 1); return pwr_fault;}static int hpc_get_emi_status(struct slot *slot, u8 *status){ struct controller *ctrl = slot->ctrl; u16 slot_status; int retval = 0; retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (retval) { err("%s : Cannot check EMI status\n", __FUNCTION__); return retval; } *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; return retval;}static int hpc_toggle_emi(struct slot *slot){ u16 slot_cmd; u16 cmd_mask; int rc; slot_cmd = EMI_CTRL; cmd_mask = EMI_CTRL; if (!pciehp_poll_mode) { slot_cmd = slot_cmd | HP_INTR_ENABLE; cmd_mask = cmd_mask | HP_INTR_ENABLE; } rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); slot->last_emi_toggle = get_seconds(); return rc;}static int hpc_set_attention_status(struct slot *slot, u8 value){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; int rc; cmd_mask = ATTN_LED_CTRL; switch (value) { case 0 : /* turn off */ slot_cmd = 0x00C0; break; case 1: /* turn on */ slot_cmd = 0x0040; break; case 2: /* turn blink */ slot_cmd = 0x0080; break; default: return -1; } if (!pciehp_poll_mode) { slot_cmd = slot_cmd | HP_INTR_ENABLE; cmd_mask = cmd_mask | HP_INTR_ENABLE; } rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); return rc;}static void hpc_set_green_led_on(struct slot *slot){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; slot_cmd = 0x0100; cmd_mask = PWR_LED_CTRL; if (!pciehp_poll_mode) { slot_cmd = slot_cmd | HP_INTR_ENABLE; cmd_mask = cmd_mask | HP_INTR_ENABLE; } pcie_write_cmd(slot, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);}static void hpc_set_green_led_off(struct slot *slot){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; slot_cmd = 0x0300; cmd_mask = PWR_LED_CTRL; if (!pciehp_poll_mode) { slot_cmd = slot_cmd | HP_INTR_ENABLE; cmd_mask = cmd_mask | HP_INTR_ENABLE; } pcie_write_cmd(slot, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);}static void hpc_set_green_led_blink(struct slot *slot){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; slot_cmd = 0x0200; cmd_mask = PWR_LED_CTRL; if (!pciehp_poll_mode) { slot_cmd = slot_cmd | HP_INTR_ENABLE; cmd_mask = cmd_mask | HP_INTR_ENABLE; } pcie_write_cmd(slot, slot_cmd, cmd_mask); dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd);}static void hpc_release_ctlr(struct controller *ctrl){ if (pciehp_poll_mode) del_timer(&ctrl->poll_timer); else free_irq(ctrl->pci_dev->irq, ctrl); /* * If this is the last controller to be released, destroy the * pciehp work queue */ if (atomic_dec_and_test(&pciehp_num_controllers)) destroy_workqueue(pciehp_wq);}static int hpc_power_on_slot(struct slot * slot){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; u16 slot_status; int retval = 0; dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); /* Clear sticky power-fault bit from previous power failures */ retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (retval) { err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); return retval; } slot_status &= PWR_FAULT_DETECTED; if (slot_status) { retval = pciehp_writew(ctrl, SLOTSTATUS, slot_status); if (retval) { err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); return retval; } } slot_cmd = POWER_ON; cmd_mask = PWR_CTRL; /* Enable detection that we turned off at slot power-off time */ if (!pciehp_poll_mode) { slot_cmd = slot_cmd | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | PRSN_DETECT_ENABLE | HP_INTR_ENABLE; cmd_mask = cmd_mask | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | PRSN_DETECT_ENABLE | HP_INTR_ENABLE; } retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); if (retval) { err("%s: Write %x command failed!\n", __FUNCTION__, slot_cmd); return -1; } dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); return retval;}static int hpc_power_off_slot(struct slot * slot){ struct controller *ctrl = slot->ctrl; u16 slot_cmd; u16 cmd_mask; int retval = 0; dbg("%s: slot->hp_slot %x\n", __FUNCTION__, slot->hp_slot); slot_cmd = POWER_OFF; cmd_mask = PWR_CTRL; /* * If we get MRL or presence detect interrupts now, the isr * will notice the sticky power-fault bit too and issue power * indicator change commands. This will lead to an endless loop * of command completions, since the power-fault bit remains on * till the slot is powered on again. */ if (!pciehp_poll_mode) { slot_cmd = (slot_cmd & ~PWR_FAULT_DETECT_ENABLE & ~MRL_DETECT_ENABLE & ~PRSN_DETECT_ENABLE) | HP_INTR_ENABLE; cmd_mask = cmd_mask | PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | PRSN_DETECT_ENABLE | HP_INTR_ENABLE; } retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); if (retval) { err("%s: Write command failed!\n", __FUNCTION__); return -1; } dbg("%s: SLOTCTRL %x write cmd %x\n", __FUNCTION__, ctrl->cap_base + SLOTCTRL, slot_cmd); return retval;}static irqreturn_t pcie_isr(int irq, void *dev_id){ struct controller *ctrl = (struct controller *)dev_id; u16 slot_status, intr_detect, intr_loc; u16 temp_word; int hp_slot = 0; /* only 1 slot per PCI Express port */ int rc = 0; unsigned long flags; rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (rc) { err("%s: Cannot read SLOTSTATUS register\n", __FUNCTION__); return IRQ_NONE; } intr_detect = (ATTN_BUTTN_PRESSED | PWR_FAULT_DETECTED | MRL_SENS_CHANGED | PRSN_DETECT_CHANGED | CMD_COMPLETED); intr_loc = slot_status & intr_detect; /* Check to see if it was our interrupt */ if ( !intr_loc ) return IRQ_NONE; dbg("%s: intr_loc %x\n", __FUNCTION__, intr_loc); /* Mask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { spin_lock_irqsave(&ctrl->lock, flags); rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); if (rc) { err("%s: Cannot read SLOT_CTRL register\n", __FUNCTION__); spin_unlock_irqrestore(&ctrl->lock, flags); return IRQ_NONE; } dbg("%s: pciehp_readw(SLOTCTRL) with value %x\n", __FUNCTION__, temp_word); temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) | 0x00; rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); if (rc) { err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); spin_unlock_irqrestore(&ctrl->lock, flags); return IRQ_NONE; } spin_unlock_irqrestore(&ctrl->lock, flags); rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (rc) { err("%s: Cannot read SLOT_STATUS register\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: pciehp_readw(SLOTSTATUS) with value %x\n", __FUNCTION__, slot_status); /* Clear command complete interrupt caused by this write */ temp_word = 0x1f; rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); if (rc) { err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); return IRQ_NONE; } } if (intr_loc & CMD_COMPLETED) { /* * Command Complete Interrupt Pending */ ctrl->cmd_busy = 0; wake_up_interruptible(&ctrl->queue); } if (intr_loc & MRL_SENS_CHANGED) pciehp_handle_switch_change(hp_slot, ctrl); if (intr_loc & ATTN_BUTTN_PRESSED) pciehp_handle_attention_button(hp_slot, ctrl); if (intr_loc & PRSN_DETECT_CHANGED) pciehp_handle_presence_change(hp_slot, ctrl); if (intr_loc & PWR_FAULT_DETECTED) pciehp_handle_power_fault(hp_slot, ctrl); /* Clear all events after serving them */ temp_word = 0x1F; rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); if (rc) { err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__); return IRQ_NONE; } /* Unmask Hot-plug Interrupt Enable */ if (!pciehp_poll_mode) { spin_lock_irqsave(&ctrl->lock, flags); rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); if (rc) { err("%s: Cannot read SLOTCTRL register\n", __FUNCTION__); spin_unlock_irqrestore(&ctrl->lock, flags); return IRQ_NONE; } dbg("%s: Unmask Hot-plug Interrupt Enable\n", __FUNCTION__); temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE; rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); if (rc) { err("%s: Cannot write to SLOTCTRL register\n", __FUNCTION__); spin_unlock_irqrestore(&ctrl->lock, flags); return IRQ_NONE; } spin_unlock_irqrestore(&ctrl->lock, flags); rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); if (rc) { err("%s: Cannot read SLOT_STATUS register\n", __FUNCTION__); return IRQ_NONE; } /* Clear command complete interrupt caused by this write */ temp_word = 0x1F; rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); if (rc) { err("%s: Cannot write to SLOTSTATUS failed\n", __FUNCTION__); return IRQ_NONE; } dbg("%s: pciehp_writew(SLOTSTATUS) with value %x\n", __FUNCTION__, temp_word); } return IRQ_HANDLED;}static int hpc_get_max_lnk_speed(struct slot *slot, enum pci_bus_speed *value){ struct controller *ctrl = slot->ctrl; enum pcie_link_speed lnk_speed; u32 lnk_cap; int retval = 0; retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); if (retval) { err("%s: Cannot read LNKCAP register\n", __FUNCTION__); return retval; } switch (lnk_cap & 0x000F) { case 1: lnk_speed = PCIE_2PT5GB; break; default: lnk_speed = PCIE_LNK_SPEED_UNKNOWN; break; } *value = lnk_speed; dbg("Max link speed = %d\n", lnk_speed); return retval;}static int hpc_get_max_lnk_width(struct slot *slot, enum pcie_link_width *value){ struct controller *ctrl = slot->ctrl; enum pcie_link_width lnk_wdth; u32 lnk_cap; int retval = 0; retval = pciehp_readl(ctrl, LNKCAP, &lnk_cap); if (retval) { err("%s: Cannot read LNKCAP register\n", __FUNCTION__); return retval; } switch ((lnk_cap & 0x03F0) >> 4){ case 0: lnk_wdth = PCIE_LNK_WIDTH_RESRV; break; case 1: lnk_wdth = PCIE_LNK_X1; break; case 2: lnk_wdth = PCIE_LNK_X2; break; case 4:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -