0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef _SHPCHP_H
0016 #define _SHPCHP_H
0017
0018 #include <linux/types.h>
0019 #include <linux/pci.h>
0020 #include <linux/pci_hotplug.h>
0021 #include <linux/delay.h>
0022 #include <linux/sched/signal.h> /* signal_pending(), struct timer_list */
0023 #include <linux/mutex.h>
0024 #include <linux/workqueue.h>
0025
0026 #if !defined(MODULE)
0027 #define MY_NAME "shpchp"
0028 #else
0029 #define MY_NAME THIS_MODULE->name
0030 #endif
0031
0032 extern bool shpchp_poll_mode;
0033 extern int shpchp_poll_time;
0034 extern bool shpchp_debug;
0035
0036 #define dbg(format, arg...) \
0037 do { \
0038 if (shpchp_debug) \
0039 printk(KERN_DEBUG "%s: " format, MY_NAME, ## arg); \
0040 } while (0)
0041 #define err(format, arg...) \
0042 printk(KERN_ERR "%s: " format, MY_NAME, ## arg)
0043 #define info(format, arg...) \
0044 printk(KERN_INFO "%s: " format, MY_NAME, ## arg)
0045 #define warn(format, arg...) \
0046 printk(KERN_WARNING "%s: " format, MY_NAME, ## arg)
0047
0048 #define ctrl_dbg(ctrl, format, arg...) \
0049 do { \
0050 if (shpchp_debug) \
0051 pci_printk(KERN_DEBUG, ctrl->pci_dev, \
0052 format, ## arg); \
0053 } while (0)
0054 #define ctrl_err(ctrl, format, arg...) \
0055 pci_err(ctrl->pci_dev, format, ## arg)
0056 #define ctrl_info(ctrl, format, arg...) \
0057 pci_info(ctrl->pci_dev, format, ## arg)
0058 #define ctrl_warn(ctrl, format, arg...) \
0059 pci_warn(ctrl->pci_dev, format, ## arg)
0060
0061
0062 #define SLOT_NAME_SIZE 10
0063 struct slot {
0064 u8 bus;
0065 u8 device;
0066 u16 status;
0067 u32 number;
0068 u8 is_a_board;
0069 u8 state;
0070 u8 attention_save;
0071 u8 presence_save;
0072 u8 latch_save;
0073 u8 pwr_save;
0074 struct controller *ctrl;
0075 const struct hpc_ops *hpc_ops;
0076 struct hotplug_slot hotplug_slot;
0077 struct list_head slot_list;
0078 struct delayed_work work;
0079 struct mutex lock;
0080 struct workqueue_struct *wq;
0081 u8 hp_slot;
0082 };
0083
0084 struct event_info {
0085 u32 event_type;
0086 struct slot *p_slot;
0087 struct work_struct work;
0088 };
0089
0090 struct controller {
0091 struct mutex crit_sect;
0092 struct mutex cmd_lock;
0093 int num_slots;
0094 int slot_num_inc;
0095 struct pci_dev *pci_dev;
0096 struct list_head slot_list;
0097 const struct hpc_ops *hpc_ops;
0098 wait_queue_head_t queue;
0099 u8 slot_device_offset;
0100 u32 pcix_misc2_reg;
0101 u32 first_slot;
0102 u32 cap_offset;
0103 unsigned long mmio_base;
0104 unsigned long mmio_size;
0105 void __iomem *creg;
0106 struct timer_list poll_timer;
0107 };
0108
0109
0110 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
0111
0112
0113 #define PCIX_MEM_BASE_LIMIT_OFFSET 0x1C
0114 #define PCIX_MISCII_OFFSET 0x48
0115 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET 0x80
0116
0117
0118 #define PERRNONFATALENABLE_MASK 0x00040000
0119 #define PERRFATALENABLE_MASK 0x00080000
0120 #define PERRFLOODENABLE_MASK 0x00100000
0121 #define SERRNONFATALENABLE_MASK 0x00200000
0122 #define SERRFATALENABLE_MASK 0x00400000
0123
0124
0125 #define PERR_OBSERVED_MASK 0x00000001
0126
0127
0128 #define RSE_MASK 0x40000000
0129
0130 #define INT_BUTTON_IGNORE 0
0131 #define INT_PRESENCE_ON 1
0132 #define INT_PRESENCE_OFF 2
0133 #define INT_SWITCH_CLOSE 3
0134 #define INT_SWITCH_OPEN 4
0135 #define INT_POWER_FAULT 5
0136 #define INT_POWER_FAULT_CLEAR 6
0137 #define INT_BUTTON_PRESS 7
0138 #define INT_BUTTON_RELEASE 8
0139 #define INT_BUTTON_CANCEL 9
0140
0141 #define STATIC_STATE 0
0142 #define BLINKINGON_STATE 1
0143 #define BLINKINGOFF_STATE 2
0144 #define POWERON_STATE 3
0145 #define POWEROFF_STATE 4
0146
0147
0148 #define INTERLOCK_OPEN 0x00000002
0149 #define ADD_NOT_SUPPORTED 0x00000003
0150 #define CARD_FUNCTIONING 0x00000005
0151 #define ADAPTER_NOT_SAME 0x00000006
0152 #define NO_ADAPTER_PRESENT 0x00000009
0153 #define NOT_ENOUGH_RESOURCES 0x0000000B
0154 #define DEVICE_TYPE_NOT_SUPPORTED 0x0000000C
0155 #define WRONG_BUS_FREQUENCY 0x0000000D
0156 #define POWER_FAILURE 0x0000000E
0157
0158 int __must_check shpchp_create_ctrl_files(struct controller *ctrl);
0159 void shpchp_remove_ctrl_files(struct controller *ctrl);
0160 int shpchp_sysfs_enable_slot(struct slot *slot);
0161 int shpchp_sysfs_disable_slot(struct slot *slot);
0162 u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl);
0163 u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl);
0164 u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl);
0165 u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl);
0166 int shpchp_configure_device(struct slot *p_slot);
0167 void shpchp_unconfigure_device(struct slot *p_slot);
0168 void cleanup_slots(struct controller *ctrl);
0169 void shpchp_queue_pushbutton_work(struct work_struct *work);
0170 int shpc_init(struct controller *ctrl, struct pci_dev *pdev);
0171
0172 static inline const char *slot_name(struct slot *slot)
0173 {
0174 return hotplug_slot_name(&slot->hotplug_slot);
0175 }
0176
0177 struct ctrl_reg {
0178 volatile u32 base_offset;
0179 volatile u32 slot_avail1;
0180 volatile u32 slot_avail2;
0181 volatile u32 slot_config;
0182 volatile u16 sec_bus_config;
0183 volatile u8 msi_ctrl;
0184 volatile u8 prog_interface;
0185 volatile u16 cmd;
0186 volatile u16 cmd_status;
0187 volatile u32 intr_loc;
0188 volatile u32 serr_loc;
0189 volatile u32 serr_intr_enable;
0190 volatile u32 slot1;
0191 } __attribute__ ((packed));
0192
0193
0194 enum ctrl_offsets {
0195 BASE_OFFSET = offsetof(struct ctrl_reg, base_offset),
0196 SLOT_AVAIL1 = offsetof(struct ctrl_reg, slot_avail1),
0197 SLOT_AVAIL2 = offsetof(struct ctrl_reg, slot_avail2),
0198 SLOT_CONFIG = offsetof(struct ctrl_reg, slot_config),
0199 SEC_BUS_CONFIG = offsetof(struct ctrl_reg, sec_bus_config),
0200 MSI_CTRL = offsetof(struct ctrl_reg, msi_ctrl),
0201 PROG_INTERFACE = offsetof(struct ctrl_reg, prog_interface),
0202 CMD = offsetof(struct ctrl_reg, cmd),
0203 CMD_STATUS = offsetof(struct ctrl_reg, cmd_status),
0204 INTR_LOC = offsetof(struct ctrl_reg, intr_loc),
0205 SERR_LOC = offsetof(struct ctrl_reg, serr_loc),
0206 SERR_INTR_ENABLE = offsetof(struct ctrl_reg, serr_intr_enable),
0207 SLOT1 = offsetof(struct ctrl_reg, slot1),
0208 };
0209
0210 static inline struct slot *get_slot(struct hotplug_slot *hotplug_slot)
0211 {
0212 return container_of(hotplug_slot, struct slot, hotplug_slot);
0213 }
0214
0215 static inline struct slot *shpchp_find_slot(struct controller *ctrl, u8 device)
0216 {
0217 struct slot *slot;
0218
0219 list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
0220 if (slot->device == device)
0221 return slot;
0222 }
0223
0224 ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
0225 return NULL;
0226 }
0227
0228 static inline void amd_pogo_errata_save_misc_reg(struct slot *p_slot)
0229 {
0230 u32 pcix_misc2_temp;
0231
0232
0233 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
0234
0235 p_slot->ctrl->pcix_misc2_reg = pcix_misc2_temp;
0236
0237
0238 pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
0239 pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
0240 pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
0241 pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
0242 pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
0243 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
0244 }
0245
0246 static inline void amd_pogo_errata_restore_misc_reg(struct slot *p_slot)
0247 {
0248 u32 pcix_misc2_temp;
0249 u32 pcix_bridge_errors_reg;
0250 u32 pcix_mem_base_reg;
0251 u8 perr_set;
0252 u8 rse_set;
0253
0254
0255 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, &pcix_bridge_errors_reg);
0256 perr_set = pcix_bridge_errors_reg & PERR_OBSERVED_MASK;
0257 if (perr_set) {
0258 ctrl_dbg(p_slot->ctrl,
0259 "Bridge_Errors[ PERR_OBSERVED = %08X] (W1C)\n",
0260 perr_set);
0261
0262 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISC_BRIDGE_ERRORS_OFFSET, perr_set);
0263 }
0264
0265
0266 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, &pcix_mem_base_reg);
0267 rse_set = pcix_mem_base_reg & RSE_MASK;
0268 if (rse_set) {
0269 ctrl_dbg(p_slot->ctrl, "Memory_Base_Limit[ RSE ] (W1C)\n");
0270
0271 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MEM_BASE_LIMIT_OFFSET, rse_set);
0272 }
0273
0274 pci_read_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, &pcix_misc2_temp);
0275
0276 if (p_slot->ctrl->pcix_misc2_reg & SERRFATALENABLE_MASK)
0277 pcix_misc2_temp |= SERRFATALENABLE_MASK;
0278 else
0279 pcix_misc2_temp &= ~SERRFATALENABLE_MASK;
0280
0281 if (p_slot->ctrl->pcix_misc2_reg & SERRNONFATALENABLE_MASK)
0282 pcix_misc2_temp |= SERRNONFATALENABLE_MASK;
0283 else
0284 pcix_misc2_temp &= ~SERRNONFATALENABLE_MASK;
0285
0286 if (p_slot->ctrl->pcix_misc2_reg & PERRFLOODENABLE_MASK)
0287 pcix_misc2_temp |= PERRFLOODENABLE_MASK;
0288 else
0289 pcix_misc2_temp &= ~PERRFLOODENABLE_MASK;
0290
0291 if (p_slot->ctrl->pcix_misc2_reg & PERRFATALENABLE_MASK)
0292 pcix_misc2_temp |= PERRFATALENABLE_MASK;
0293 else
0294 pcix_misc2_temp &= ~PERRFATALENABLE_MASK;
0295
0296 if (p_slot->ctrl->pcix_misc2_reg & PERRNONFATALENABLE_MASK)
0297 pcix_misc2_temp |= PERRNONFATALENABLE_MASK;
0298 else
0299 pcix_misc2_temp &= ~PERRNONFATALENABLE_MASK;
0300 pci_write_config_dword(p_slot->ctrl->pci_dev, PCIX_MISCII_OFFSET, pcix_misc2_temp);
0301 }
0302
0303 struct hpc_ops {
0304 int (*power_on_slot)(struct slot *slot);
0305 int (*slot_enable)(struct slot *slot);
0306 int (*slot_disable)(struct slot *slot);
0307 int (*set_bus_speed_mode)(struct slot *slot, enum pci_bus_speed speed);
0308 int (*get_power_status)(struct slot *slot, u8 *status);
0309 int (*get_attention_status)(struct slot *slot, u8 *status);
0310 int (*set_attention_status)(struct slot *slot, u8 status);
0311 int (*get_latch_status)(struct slot *slot, u8 *status);
0312 int (*get_adapter_status)(struct slot *slot, u8 *status);
0313 int (*get_adapter_speed)(struct slot *slot, enum pci_bus_speed *speed);
0314 int (*get_mode1_ECC_cap)(struct slot *slot, u8 *mode);
0315 int (*get_prog_int)(struct slot *slot, u8 *prog_int);
0316 int (*query_power_fault)(struct slot *slot);
0317 void (*green_led_on)(struct slot *slot);
0318 void (*green_led_off)(struct slot *slot);
0319 void (*green_led_blink)(struct slot *slot);
0320 void (*release_ctlr)(struct controller *ctrl);
0321 int (*check_cmd_status)(struct controller *ctrl);
0322 };
0323
0324 #endif