aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci')
-rw-r--r--drivers/pci/hotplug/pciehp_hpc.c150
1 files changed, 38 insertions, 112 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 19eba2a2f746..7104a15e2661 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -242,13 +242,12 @@ static inline int pcie_wait_cmd(struct controller *ctrl)
242 242
243/** 243/**
244 * pcie_write_cmd - Issue controller command 244 * pcie_write_cmd - Issue controller command
245 * @slot: slot to which the command is issued 245 * @ctrl: controller to which the command is issued
246 * @cmd: command value written to slot control register 246 * @cmd: command value written to slot control register
247 * @mask: bitmask of slot control register to be modified 247 * @mask: bitmask of slot control register to be modified
248 */ 248 */
249static int pcie_write_cmd(struct slot *slot, u16 cmd, u16 mask) 249static int pcie_write_cmd(struct controller *ctrl, u16 cmd, u16 mask)
250{ 250{
251 struct controller *ctrl = slot->ctrl;
252 int retval = 0; 251 int retval = 0;
253 u16 slot_status; 252 u16 slot_status;
254 u16 slot_ctrl; 253 u16 slot_ctrl;
@@ -468,7 +467,7 @@ static int hpc_toggle_emi(struct slot *slot)
468 cmd_mask = cmd_mask | HP_INTR_ENABLE; 467 cmd_mask = cmd_mask | HP_INTR_ENABLE;
469 } 468 }
470 469
471 rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); 470 rc = pcie_write_cmd(slot->ctrl, slot_cmd, cmd_mask);
472 slot->last_emi_toggle = get_seconds(); 471 slot->last_emi_toggle = get_seconds();
473 472
474 return rc; 473 return rc;
@@ -500,7 +499,7 @@ static int hpc_set_attention_status(struct slot *slot, u8 value)
500 cmd_mask = cmd_mask | HP_INTR_ENABLE; 499 cmd_mask = cmd_mask | HP_INTR_ENABLE;
501 } 500 }
502 501
503 rc = pcie_write_cmd(slot, slot_cmd, cmd_mask); 502 rc = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
504 dbg("%s: SLOTCTRL %x write cmd %x\n", 503 dbg("%s: SLOTCTRL %x write cmd %x\n",
505 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 504 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
506 505
@@ -520,7 +519,7 @@ static void hpc_set_green_led_on(struct slot *slot)
520 cmd_mask = cmd_mask | HP_INTR_ENABLE; 519 cmd_mask = cmd_mask | HP_INTR_ENABLE;
521 } 520 }
522 521
523 pcie_write_cmd(slot, slot_cmd, cmd_mask); 522 pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
524 523
525 dbg("%s: SLOTCTRL %x write cmd %x\n", 524 dbg("%s: SLOTCTRL %x write cmd %x\n",
526 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 525 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -539,7 +538,7 @@ static void hpc_set_green_led_off(struct slot *slot)
539 cmd_mask = cmd_mask | HP_INTR_ENABLE; 538 cmd_mask = cmd_mask | HP_INTR_ENABLE;
540 } 539 }
541 540
542 pcie_write_cmd(slot, slot_cmd, cmd_mask); 541 pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
543 dbg("%s: SLOTCTRL %x write cmd %x\n", 542 dbg("%s: SLOTCTRL %x write cmd %x\n",
544 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 543 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
545} 544}
@@ -557,7 +556,7 @@ static void hpc_set_green_led_blink(struct slot *slot)
557 cmd_mask = cmd_mask | HP_INTR_ENABLE; 556 cmd_mask = cmd_mask | HP_INTR_ENABLE;
558 } 557 }
559 558
560 pcie_write_cmd(slot, slot_cmd, cmd_mask); 559 pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
561 560
562 dbg("%s: SLOTCTRL %x write cmd %x\n", 561 dbg("%s: SLOTCTRL %x write cmd %x\n",
563 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd); 562 __func__, ctrl->cap_base + SLOTCTRL, slot_cmd);
@@ -620,7 +619,7 @@ static int hpc_power_on_slot(struct slot * slot)
620 HP_INTR_ENABLE; 619 HP_INTR_ENABLE;
621 } 620 }
622 621
623 retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); 622 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
624 623
625 if (retval) { 624 if (retval) {
626 err("%s: Write %x command failed!\n", __func__, slot_cmd); 625 err("%s: Write %x command failed!\n", __func__, slot_cmd);
@@ -704,7 +703,7 @@ static int hpc_power_off_slot(struct slot * slot)
704 HP_INTR_ENABLE; 703 HP_INTR_ENABLE;
705 } 704 }
706 705
707 retval = pcie_write_cmd(slot, slot_cmd, cmd_mask); 706 retval = pcie_write_cmd(ctrl, slot_cmd, cmd_mask);
708 if (retval) { 707 if (retval) {
709 err("%s: Write command failed!\n", __func__); 708 err("%s: Write command failed!\n", __func__);
710 retval = -1; 709 retval = -1;
@@ -1036,45 +1035,9 @@ int pciehp_acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev)
1036static int pcie_init_hardware_part1(struct controller *ctrl, 1035static int pcie_init_hardware_part1(struct controller *ctrl,
1037 struct pcie_device *dev) 1036 struct pcie_device *dev)
1038{ 1037{
1039 int rc;
1040 u16 temp_word;
1041 u32 slot_cap;
1042 u16 slot_status;
1043
1044 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
1045 if (rc) {
1046 err("%s: Cannot read SLOTCAP register\n", __func__);
1047 return -1;
1048 }
1049
1050 /* Mask Hot-plug Interrupt Enable */ 1038 /* Mask Hot-plug Interrupt Enable */
1051 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1039 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE | CMD_CMPL_INTR_ENABLE)) {
1052 if (rc) { 1040 err("%s: Cannot mask hotplug interrupt enable\n", __func__);
1053 err("%s: Cannot read SLOTCTRL register\n", __func__);
1054 return -1;
1055 }
1056
1057 dbg("%s: SLOTCTRL %x value read %x\n",
1058 __func__, ctrl->cap_base + SLOTCTRL, temp_word);
1059 temp_word = (temp_word & ~HP_INTR_ENABLE & ~CMD_CMPL_INTR_ENABLE) |
1060 0x00;
1061
1062 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1063 if (rc) {
1064 err("%s: Cannot write to SLOTCTRL register\n", __func__);
1065 return -1;
1066 }
1067
1068 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1069 if (rc) {
1070 err("%s: Cannot read SLOTSTATUS register\n", __func__);
1071 return -1;
1072 }
1073
1074 temp_word = 0x1F; /* Clear all events */
1075 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word);
1076 if (rc) {
1077 err("%s: Cannot write to SLOTSTATUS register\n", __func__);
1078 return -1; 1041 return -1;
1079 } 1042 }
1080 return 0; 1043 return 0;
@@ -1082,84 +1045,47 @@ static int pcie_init_hardware_part1(struct controller *ctrl,
1082 1045
1083int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev) 1046int pcie_init_hardware_part2(struct controller *ctrl, struct pcie_device *dev)
1084{ 1047{
1085 int rc; 1048 u16 cmd, mask;
1086 u16 temp_word;
1087 u16 intr_enable = 0;
1088 u32 slot_cap;
1089 u16 slot_status;
1090
1091 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word);
1092 if (rc) {
1093 err("%s: Cannot read SLOTCTRL register\n", __func__);
1094 goto abort;
1095 }
1096
1097 intr_enable = intr_enable | PRSN_DETECT_ENABLE;
1098
1099 rc = pciehp_readl(ctrl, SLOTCAP, &slot_cap);
1100 if (rc) {
1101 err("%s: Cannot read SLOTCAP register\n", __func__);
1102 goto abort;
1103 }
1104
1105 if (ATTN_BUTTN(slot_cap))
1106 intr_enable = intr_enable | ATTN_BUTTN_ENABLE;
1107
1108 if (POWER_CTRL(slot_cap))
1109 intr_enable = intr_enable | PWR_FAULT_DETECT_ENABLE;
1110
1111 if (MRL_SENS(slot_cap))
1112 intr_enable = intr_enable | MRL_DETECT_ENABLE;
1113
1114 temp_word = (temp_word & ~intr_enable) | intr_enable;
1115
1116 if (pciehp_poll_mode) {
1117 temp_word = (temp_word & ~HP_INTR_ENABLE) | 0x0;
1118 } else {
1119 temp_word = (temp_word & ~HP_INTR_ENABLE) | HP_INTR_ENABLE;
1120 }
1121 1049
1122 /* 1050 /*
1123 * Unmask Hot-plug Interrupt Enable for the interrupt 1051 * We need to clear all events before enabling hotplug interrupt
1124 * notification mechanism case. 1052 * notification mechanism in order for hotplug controler to
1053 * generate interrupts.
1125 */ 1054 */
1126 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word); 1055 if (pciehp_writew(ctrl, SLOTSTATUS, 0x1f)) {
1127 if (rc) { 1056 err("%s: Cannot write to SLOTSTATUS register\n", __FUNCTION__);
1128 err("%s: Cannot write to SLOTCTRL register\n", __func__); 1057 return -1;
1129 goto abort;
1130 }
1131 rc = pciehp_readw(ctrl, SLOTSTATUS, &slot_status);
1132 if (rc) {
1133 err("%s: Cannot read SLOTSTATUS register\n", __func__);
1134 goto abort_disable_intr;
1135 } 1058 }
1136 1059
1137 temp_word = 0x1F; /* Clear all events */ 1060 cmd = PRSN_DETECT_ENABLE;
1138 rc = pciehp_writew(ctrl, SLOTSTATUS, temp_word); 1061 if (ATTN_BUTTN(ctrl->ctrlcap))
1139 if (rc) { 1062 cmd |= ATTN_BUTTN_ENABLE;
1140 err("%s: Cannot write to SLOTSTATUS register\n", __func__); 1063 if (POWER_CTRL(ctrl->ctrlcap))
1141 goto abort_disable_intr; 1064 cmd |= PWR_FAULT_DETECT_ENABLE;
1065 if (MRL_SENS(ctrl->ctrlcap))
1066 cmd |= MRL_DETECT_ENABLE;
1067 if (!pciehp_poll_mode)
1068 cmd |= HP_INTR_ENABLE;
1069
1070 mask = PRSN_DETECT_ENABLE | ATTN_BUTTN_ENABLE |
1071 PWR_FAULT_DETECT_ENABLE | MRL_DETECT_ENABLE | HP_INTR_ENABLE;
1072
1073 if (pcie_write_cmd(ctrl, cmd, mask)) {
1074 err("%s: Cannot enable software notification\n", __func__);
1075 goto abort;
1142 } 1076 }
1143 1077
1144 if (pciehp_force) { 1078 if (pciehp_force)
1145 dbg("Bypassing BIOS check for pciehp use on %s\n", 1079 dbg("Bypassing BIOS check for pciehp use on %s\n",
1146 pci_name(ctrl->pci_dev)); 1080 pci_name(ctrl->pci_dev));
1147 } else { 1081 else if (pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev))
1148 rc = pciehp_get_hp_hw_control_from_firmware(ctrl->pci_dev); 1082 goto abort_disable_intr;
1149 if (rc)
1150 goto abort_disable_intr;
1151 }
1152 1083
1153 return 0; 1084 return 0;
1154 1085
1155 /* We end up here for the many possible ways to fail this API. */ 1086 /* We end up here for the many possible ways to fail this API. */
1156abort_disable_intr: 1087abort_disable_intr:
1157 rc = pciehp_readw(ctrl, SLOTCTRL, &temp_word); 1088 if (pcie_write_cmd(ctrl, 0, HP_INTR_ENABLE))
1158 if (!rc) {
1159 temp_word &= ~(intr_enable | HP_INTR_ENABLE);
1160 rc = pciehp_writew(ctrl, SLOTCTRL, temp_word);
1161 }
1162 if (rc)
1163 err("%s : disabling interrupts failed\n", __func__); 1089 err("%s : disabling interrupts failed\n", __func__);
1164abort: 1090abort:
1165 return -1; 1091 return -1;