pciehp.h 8.2 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * PCI Express Hot Plug Controller Driver
 *
 * Copyright (C) 1995,2001 Compaq Computer Corporation
 * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
 * Copyright (C) 2001 IBM Corp.
 * Copyright (C) 2003-2004 Intel Corporation
 *
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 * NON INFRINGEMENT.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
26
 * Send feedback to <greg@kroah.com>, <kristen.c.accardi@intel.com>
L
Linus Torvalds 已提交
27 28 29 30 31 32 33
 *
 */
#ifndef _PCIEHP_H
#define _PCIEHP_H

#include <linux/types.h>
#include <linux/pci.h>
34
#include <linux/pci_hotplug.h>
L
Linus Torvalds 已提交
35
#include <linux/delay.h>
36
#include <linux/sched.h>		/* signal_pending() */
L
Linus Torvalds 已提交
37
#include <linux/pcieport_if.h>
38
#include <linux/mutex.h>
L
Linus Torvalds 已提交
39 40 41 42 43 44

#define MY_NAME	"pciehp"

extern int pciehp_poll_mode;
extern int pciehp_poll_time;
extern int pciehp_debug;
45
extern int pciehp_force;
K
Kenji Kaneshige 已提交
46
extern struct workqueue_struct *pciehp_wq;
L
Linus Torvalds 已提交
47

K
Kenji Kaneshige 已提交
48 49 50 51 52 53 54 55 56 57 58
#define dbg(format, arg...)						\
	do {								\
		if (pciehp_debug)					\
			printk("%s: " format, MY_NAME , ## arg);	\
	} while (0)
#define err(format, arg...)						\
	printk(KERN_ERR "%s: " format, MY_NAME , ## arg)
#define info(format, arg...)						\
	printk(KERN_INFO "%s: " format, MY_NAME , ## arg)
#define warn(format, arg...)						\
	printk(KERN_WARNING "%s: " format, MY_NAME , ## arg)
L
Linus Torvalds 已提交
59

60 61 62 63 64 65 66 67 68 69 70 71 72
#define ctrl_dbg(ctrl, format, arg...)					\
	do {								\
		if (pciehp_debug)					\
			dev_printk(, &ctrl->pcie->device,		\
					format, ## arg);		\
	} while (0)
#define ctrl_err(ctrl, format, arg...)					\
	dev_err(&ctrl->pcie->device, format, ## arg)
#define ctrl_info(ctrl, format, arg...)					\
	dev_info(&ctrl->pcie->device, format, ## arg)
#define ctrl_warn(ctrl, format, arg...)					\
	dev_warn(&ctrl->pcie->device, format, ## arg)

K
Kenji Kaneshige 已提交
73
#define SLOT_NAME_SIZE 10
L
Linus Torvalds 已提交
74 75 76 77 78
struct slot {
	u8 bus;
	u8 device;
	u8 state;
	u8 hp_slot;
A
Alex Chiang 已提交
79
	u32 number;
L
Linus Torvalds 已提交
80 81 82 83
	struct controller *ctrl;
	struct hpc_ops *hpc_ops;
	struct hotplug_slot *hotplug_slot;
	struct list_head	slot_list;
84
	unsigned long last_emi_toggle;
K
Kenji Kaneshige 已提交
85 86
	struct delayed_work work;	/* work for button event */
	struct mutex lock;
L
Linus Torvalds 已提交
87 88 89 90
};

struct event_info {
	u32 event_type;
K
Kenji Kaneshige 已提交
91 92
	struct slot *p_slot;
	struct work_struct work;
L
Linus Torvalds 已提交
93 94 95
};

struct controller {
96
	struct mutex crit_sect;		/* critical section mutex */
K
Kenji Kaneshige 已提交
97
	struct mutex ctrl_lock;		/* controller lock */
L
Linus Torvalds 已提交
98 99 100
	int num_slots;			/* Number of slots on ctlr */
	int slot_num_inc;		/* 1 or -1 */
	struct pci_dev *pci_dev;
101
	struct pcie_device *pcie;	/* PCI Express port service */
K
Kenji Kaneshige 已提交
102
	struct list_head slot_list;
L
Linus Torvalds 已提交
103 104 105 106 107
	struct hpc_ops *hpc_ops;
	wait_queue_head_t queue;	/* sleep & wake process */
	u8 slot_device_offset;
	u32 first_slot;		/* First physical slot number */  /* PCIE only has 1 slot */
	u8 slot_bus;		/* Bus where the slots handled by this controller sit */
108
	u32 slot_cap;
109
	u8 cap_base;
110
	struct timer_list poll_timer;
111
	int cmd_busy;
K
Kenji Kaneshige 已提交
112
	unsigned int no_cmd_complete:1;
113
	unsigned int link_active_reporting:1;
114
	unsigned int notification_enabled:1;
L
Linus Torvalds 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
};

#define INT_BUTTON_IGNORE		0
#define INT_PRESENCE_ON			1
#define INT_PRESENCE_OFF		2
#define INT_SWITCH_CLOSE		3
#define INT_SWITCH_OPEN			4
#define INT_POWER_FAULT			5
#define INT_POWER_FAULT_CLEAR		6
#define INT_BUTTON_PRESS		7
#define INT_BUTTON_RELEASE		8
#define INT_BUTTON_CANCEL		9

#define STATIC_STATE			0
#define BLINKINGON_STATE		1
#define BLINKINGOFF_STATE		2
#define POWERON_STATE			3
#define POWEROFF_STATE			4

/* Error messages */
#define INTERLOCK_OPEN			0x00000002
#define ADD_NOT_SUPPORTED		0x00000003
#define CARD_FUNCTIONING		0x00000005
#define ADAPTER_NOT_SAME		0x00000006
#define NO_ADAPTER_PRESENT		0x00000009
#define NOT_ENOUGH_RESOURCES		0x0000000B
#define DEVICE_TYPE_NOT_SUPPORTED	0x0000000C
#define WRONG_BUS_FREQUENCY		0x0000000D
#define POWER_FAILURE			0x0000000E

/* Field definitions in Slot Capabilities Register */
#define ATTN_BUTTN_PRSN	0x00000001
#define	PWR_CTRL_PRSN	0x00000002
#define MRL_SENS_PRSN	0x00000004
#define ATTN_LED_PRSN	0x00000008
#define PWR_LED_PRSN	0x00000010
#define HP_SUPR_RM_SUP	0x00000020
152
#define EMI_PRSN	0x00020000
K
Kenji Kaneshige 已提交
153
#define NO_CMD_CMPL_SUP	0x00040000
L
Linus Torvalds 已提交
154

155 156 157 158 159 160 161
#define ATTN_BUTTN(ctrl)	((ctrl)->slot_cap & ATTN_BUTTN_PRSN)
#define POWER_CTRL(ctrl)	((ctrl)->slot_cap & PWR_CTRL_PRSN)
#define MRL_SENS(ctrl)		((ctrl)->slot_cap & MRL_SENS_PRSN)
#define ATTN_LED(ctrl)		((ctrl)->slot_cap & ATTN_LED_PRSN)
#define PWR_LED(ctrl)		((ctrl)->slot_cap & PWR_LED_PRSN)
#define HP_SUPR_RM(ctrl)	((ctrl)->slot_cap & HP_SUPR_RM_SUP)
#define EMI(ctrl)		((ctrl)->slot_cap & EMI_PRSN)
K
Kenji Kaneshige 已提交
162
#define NO_CMD_CMPL(ctrl)	((ctrl)->slot_cap & NO_CMD_CMPL_SUP)
L
Linus Torvalds 已提交
163

K
Kenji Kaneshige 已提交
164 165
extern int pciehp_sysfs_enable_slot(struct slot *slot);
extern int pciehp_sysfs_disable_slot(struct slot *slot);
166 167 168 169
extern u8 pciehp_handle_attention_button(struct slot *p_slot);
  extern u8 pciehp_handle_switch_change(struct slot *p_slot);
extern u8 pciehp_handle_presence_change(struct slot *p_slot);
extern u8 pciehp_handle_power_fault(struct slot *p_slot);
K
Kenji Kaneshige 已提交
170 171
extern int pciehp_configure_device(struct slot *p_slot);
extern int pciehp_unconfigure_device(struct slot *p_slot);
172
extern void pciehp_queue_pushbutton_work(struct work_struct *work);
173
struct controller *pcie_init(struct pcie_device *dev);
174
int pcie_init_notification(struct controller *ctrl);
175
int pciehp_enable_slot(struct slot *p_slot);
176
int pciehp_disable_slot(struct slot *p_slot);
177
int pcie_enable_notification(struct controller *ctrl);
L
Linus Torvalds 已提交
178

A
Alex Chiang 已提交
179 180 181 182 183
static inline const char *slot_name(struct slot *slot)
{
	return hotplug_slot_name(slot->hotplug_slot);
}

L
Linus Torvalds 已提交
184 185
static inline struct slot *pciehp_find_slot(struct controller *ctrl, u8 device)
{
K
Kenji Kaneshige 已提交
186
	struct slot *slot;
L
Linus Torvalds 已提交
187

K
Kenji Kaneshige 已提交
188 189 190
	list_for_each_entry(slot, &ctrl->slot_list, slot_list) {
		if (slot->device == device)
			return slot;
L
Linus Torvalds 已提交
191 192
	}

193
	ctrl_err(ctrl, "Slot (device=0x%02x) not found\n", device);
K
Kenji Kaneshige 已提交
194
	return NULL;
L
Linus Torvalds 已提交
195 196 197
}

struct hpc_ops {
K
Kenji Kaneshige 已提交
198 199 200 201 202 203 204
	int (*power_on_slot)(struct slot *slot);
	int (*power_off_slot)(struct slot *slot);
	int (*get_power_status)(struct slot *slot, u8 *status);
	int (*get_attention_status)(struct slot *slot, u8 *status);
	int (*set_attention_status)(struct slot *slot, u8 status);
	int (*get_latch_status)(struct slot *slot, u8 *status);
	int (*get_adapter_status)(struct slot *slot, u8 *status);
205 206
	int (*get_emi_status)(struct slot *slot, u8 *status);
	int (*toggle_emi)(struct slot *slot);
K
Kenji Kaneshige 已提交
207 208 209 210 211 212 213 214 215 216
	int (*get_max_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
	int (*get_cur_bus_speed)(struct slot *slot, enum pci_bus_speed *speed);
	int (*get_max_lnk_width)(struct slot *slot, enum pcie_link_width *val);
	int (*get_cur_lnk_width)(struct slot *slot, enum pcie_link_width *val);
	int (*query_power_fault)(struct slot *slot);
	void (*green_led_on)(struct slot *slot);
	void (*green_led_off)(struct slot *slot);
	void (*green_led_blink)(struct slot *slot);
	void (*release_ctlr)(struct controller *ctrl);
	int (*check_lnk_status)(struct controller *ctrl);
L
Linus Torvalds 已提交
217 218
};

219
#ifdef CONFIG_ACPI
220 221 222 223
#include <acpi/acpi.h>
#include <acpi/acpi_bus.h>
#include <linux/pci-acpi.h>

224 225 226 227 228 229 230 231
extern void __init pciehp_acpi_slot_detection_init(void);
extern int pciehp_acpi_slot_detection_check(struct pci_dev *dev);

static inline void pciehp_firmware_init(void)
{
	pciehp_acpi_slot_detection_init();
}

232 233
static inline int pciehp_get_hp_hw_control_from_firmware(struct pci_dev *dev)
{
234
	int retval;
235 236
	u32 flags = (OSC_PCI_EXPRESS_NATIVE_HP_CONTROL |
		     OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
237 238 239 240
	retval = acpi_get_hp_hw_control_from_firmware(dev, flags);
	if (retval)
		return retval;
	return pciehp_acpi_slot_detection_check(dev);
241 242
}

243 244 245
static inline int pciehp_get_hp_params_from_firmware(struct pci_dev *dev,
			struct hotplug_params *hpp)
{
246
	if (ACPI_FAILURE(acpi_get_hp_params_from_firmware(dev->bus, hpp)))
247 248 249 250
		return -ENODEV;
	return 0;
}
#else
251
#define pciehp_firmware_init()				do {} while (0)
252 253 254
#define pciehp_get_hp_hw_control_from_firmware(dev) 	0
#define pciehp_get_hp_params_from_firmware(dev, hpp)    (-ENODEV)
#endif 				/* CONFIG_ACPI */
L
Linus Torvalds 已提交
255
#endif				/* _PCIEHP_H */