Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0+ */
0002 /*
0003  * Standard Hot Plug Controller Driver
0004  *
0005  * Copyright (C) 1995,2001 Compaq Computer Corporation
0006  * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
0007  * Copyright (C) 2001 IBM
0008  * Copyright (C) 2003-2004 Intel Corporation
0009  *
0010  * All rights reserved.
0011  *
0012  * Send feedback to <greg@kroah.com>,<kristen.c.accardi@intel.com>
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;   /* work for button event */
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;     /* critical section mutex */
0092     struct mutex cmd_lock;      /* command lock */
0093     int num_slots;          /* Number of slots on ctlr */
0094     int slot_num_inc;       /* 1 or -1 */
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;    /* sleep & wake process */
0099     u8 slot_device_offset;
0100     u32 pcix_misc2_reg; /* for amd pogo errata */
0101     u32 first_slot;     /* First physical slot number */
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 /* Define AMD SHPC ID  */
0110 #define PCI_DEVICE_ID_AMD_POGO_7458 0x7458
0111 
0112 /* AMD PCI-X bridge registers */
0113 #define PCIX_MEM_BASE_LIMIT_OFFSET  0x1C
0114 #define PCIX_MISCII_OFFSET      0x48
0115 #define PCIX_MISC_BRIDGE_ERRORS_OFFSET  0x80
0116 
0117 /* AMD PCIX_MISCII masks and offsets */
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 /* AMD PCIX_MISC_BRIDGE_ERRORS masks and offsets */
0125 #define PERR_OBSERVED_MASK      0x00000001
0126 
0127 /* AMD PCIX_MEM_BASE_LIMIT masks */
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 /* Error messages */
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 /* offsets to the controller registers based on the above structure layout */
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     /* save MiscII register */
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     /* clear SERR/PERR enable bits */
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     /* write-one-to-clear Bridge_Errors[ PERR_OBSERVED ] */
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     /* write-one-to-clear Memory_Base_Limit[ RSE ] */
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     /* restore MiscII register */
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              /* _SHPCHP_H */