diff options
author | Kristen Carlson Accardi <kristen.c.accardi@intel.com> | 2007-01-09 16:02:36 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2007-02-07 18:50:05 -0500 |
commit | 34d03419f03bcfdf70d9617a9b90b60c93482c4a (patch) | |
tree | 4371f46298a0bd24df178cbe73fe815bf146faad /drivers/pci/hotplug/pciehp_hpc.c | |
parent | 262303fe329a51463925f3749aafc358a4201397 (diff) |
PCIEHP: Add Electro Mechanical Interlock (EMI) support to the PCIE hotplug driver.
Signed-off-by: Kristen Carlson Accardi <kristen.c.accardi@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/pci/hotplug/pciehp_hpc.c')
-rw-r--r-- | drivers/pci/hotplug/pciehp_hpc.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index eb1862b50bb1..fbc64aa2dd68 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/timer.h> | 35 | #include <linux/timer.h> |
36 | #include <linux/pci.h> | 36 | #include <linux/pci.h> |
37 | #include <linux/interrupt.h> | 37 | #include <linux/interrupt.h> |
38 | #include <linux/time.h> | ||
38 | 39 | ||
39 | #include "../pci.h" | 40 | #include "../pci.h" |
40 | #include "pciehp.h" | 41 | #include "pciehp.h" |
@@ -192,6 +193,7 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
192 | #define ATTN_LED_CTRL 0x00C0 | 193 | #define ATTN_LED_CTRL 0x00C0 |
193 | #define PWR_LED_CTRL 0x0300 | 194 | #define PWR_LED_CTRL 0x0300 |
194 | #define PWR_CTRL 0x0400 | 195 | #define PWR_CTRL 0x0400 |
196 | #define EMI_CTRL 0x0800 | ||
195 | 197 | ||
196 | /* Attention indicator and Power indicator states */ | 198 | /* Attention indicator and Power indicator states */ |
197 | #define LED_ON 0x01 | 199 | #define LED_ON 0x01 |
@@ -202,6 +204,10 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
202 | #define POWER_ON 0 | 204 | #define POWER_ON 0 |
203 | #define POWER_OFF 0x0400 | 205 | #define POWER_OFF 0x0400 |
204 | 206 | ||
207 | /* EMI Status defines */ | ||
208 | #define EMI_DISENGAGED 0 | ||
209 | #define EMI_ENGAGED 1 | ||
210 | |||
205 | /* Field definitions in Slot Status Register */ | 211 | /* Field definitions in Slot Status Register */ |
206 | #define ATTN_BUTTN_PRESSED 0x0001 | 212 | #define ATTN_BUTTN_PRESSED 0x0001 |
207 | #define PWR_FAULT_DETECTED 0x0002 | 213 | #define PWR_FAULT_DETECTED 0x0002 |
@@ -210,6 +216,8 @@ static inline int pciehp_writel(struct controller *ctrl, int reg, u32 value) | |||
210 | #define CMD_COMPLETED 0x0010 | 216 | #define CMD_COMPLETED 0x0010 |
211 | #define MRL_STATE 0x0020 | 217 | #define MRL_STATE 0x0020 |
212 | #define PRSN_STATE 0x0040 | 218 | #define PRSN_STATE 0x0040 |
219 | #define EMI_STATE 0x0080 | ||
220 | #define EMI_STATUS_BIT 7 | ||
213 | 221 | ||
214 | static spinlock_t hpc_event_lock; | 222 | static spinlock_t hpc_event_lock; |
215 | 223 | ||
@@ -474,6 +482,51 @@ static int hpc_query_power_fault(struct slot *slot) | |||
474 | return pwr_fault; | 482 | return pwr_fault; |
475 | } | 483 | } |
476 | 484 | ||
485 | static int hpc_get_emi_status(struct slot *slot, u8 *status) | ||
486 | { | ||
487 | struct controller *ctrl = slot->ctrl; | ||
488 | u16 slot_status; | ||
489 | int retval = 0; | ||
490 | |||
491 | DBG_ENTER_ROUTINE | ||
492 | |||
493 | retval = pciehp_readw(ctrl, SLOTSTATUS, &slot_status); | ||
494 | if (retval) { | ||
495 | err("%s : Cannot check EMI status\n", __FUNCTION__); | ||
496 | return retval; | ||
497 | } | ||
498 | *status = (slot_status & EMI_STATE) >> EMI_STATUS_BIT; | ||
499 | |||
500 | DBG_LEAVE_ROUTINE | ||
501 | return retval; | ||
502 | } | ||
503 | |||
504 | static int hpc_toggle_emi(struct slot *slot) | ||
505 | { | ||
506 | struct controller *ctrl = slot->ctrl; | ||
507 | u16 slot_cmd = 0; | ||
508 | u16 slot_ctrl; | ||
509 | int rc = 0; | ||
510 | |||
511 | DBG_ENTER_ROUTINE | ||
512 | |||
513 | rc = pciehp_readw(ctrl, SLOTCTRL, &slot_ctrl); | ||
514 | if (rc) { | ||
515 | err("%s : hp_register_read_word SLOT_CTRL failed\n", | ||
516 | __FUNCTION__); | ||
517 | return rc; | ||
518 | } | ||
519 | |||
520 | slot_cmd = (slot_ctrl | EMI_CTRL); | ||
521 | if (!pciehp_poll_mode) | ||
522 | slot_cmd = slot_cmd | HP_INTR_ENABLE; | ||
523 | |||
524 | pcie_write_cmd(slot, slot_cmd); | ||
525 | slot->last_emi_toggle = get_seconds(); | ||
526 | DBG_LEAVE_ROUTINE | ||
527 | return rc; | ||
528 | } | ||
529 | |||
477 | static int hpc_set_attention_status(struct slot *slot, u8 value) | 530 | static int hpc_set_attention_status(struct slot *slot, u8 value) |
478 | { | 531 | { |
479 | struct controller *ctrl = slot->ctrl; | 532 | struct controller *ctrl = slot->ctrl; |
@@ -1009,6 +1062,8 @@ static struct hpc_ops pciehp_hpc_ops = { | |||
1009 | .get_attention_status = hpc_get_attention_status, | 1062 | .get_attention_status = hpc_get_attention_status, |
1010 | .get_latch_status = hpc_get_latch_status, | 1063 | .get_latch_status = hpc_get_latch_status, |
1011 | .get_adapter_status = hpc_get_adapter_status, | 1064 | .get_adapter_status = hpc_get_adapter_status, |
1065 | .get_emi_status = hpc_get_emi_status, | ||
1066 | .toggle_emi = hpc_toggle_emi, | ||
1012 | 1067 | ||
1013 | .get_max_bus_speed = hpc_get_max_lnk_speed, | 1068 | .get_max_bus_speed = hpc_get_max_lnk_speed, |
1014 | .get_cur_bus_speed = hpc_get_cur_lnk_speed, | 1069 | .get_cur_bus_speed = hpc_get_cur_lnk_speed, |